summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/cpu-freq/governors.txt86
-rw-r--r--Documentation/devicetree/bindings/arm/freescale/mxc_ion.txt23
-rw-r--r--Documentation/devicetree/bindings/crypto/fsl-dcp.txt2
-rw-r--r--Documentation/devicetree/bindings/crypto/fsl-sec4.txt9
-rw-r--r--Documentation/devicetree/bindings/display/mxsfb.txt49
-rw-r--r--Documentation/devicetree/bindings/dma/fsl-edma.txt1
-rw-r--r--Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt1
-rw-r--r--Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt3
-rw-r--r--Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt105
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-imx-rpmsg.txt38
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt23
-rw-r--r--Documentation/devicetree/bindings/i2c/trivial-devices.txt2
-rw-r--r--Documentation/devicetree/bindings/input/rpmsg-keys.txt33
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/focaltech-ts.txt48
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/vtl_ts.txt18
-rw-r--r--Documentation/devicetree/bindings/mfd/syscon.txt3
-rw-r--r--Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt2
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc.txt5
-rw-r--r--Documentation/devicetree/bindings/mtd/fsl-quadspi.txt16
-rw-r--r--Documentation/devicetree/bindings/mtd/gpmi-nand.txt7
-rw-r--r--Documentation/devicetree/bindings/mtd/spi-nor-flash.txt7
-rw-r--r--Documentation/devicetree/bindings/net/can/fsl-flexcan.txt10
-rw-r--r--Documentation/devicetree/bindings/net/fsl-fec.txt13
-rw-r--r--Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt1
-rw-r--r--Documentation/devicetree/bindings/phy/mxs-usb-phy.txt6
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx7ulp-pinctrl.txt33
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt7
-rw-r--r--Documentation/devicetree/bindings/pwm/nxp,tpm-pwm.txt18
-rw-r--r--Documentation/devicetree/bindings/regulator/anatop-regulator.txt2
-rw-r--r--Documentation/devicetree/bindings/regulator/pfuze100.txt2
-rw-r--r--Documentation/devicetree/bindings/reset/gpio-reset.txt35
-rw-r--r--Documentation/devicetree/bindings/rpmsg/imx-rpmsg.txt19
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-lpuart.txt9
-rw-r--r--Documentation/devicetree/bindings/soc/fsl/gpc.txt56
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,esai.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,mqs.txt22
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt20
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,spdif.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,ssi.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt25
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audio-mqs.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audio-rpmsg.txt13
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audio-si476x.txt24
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt12
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audio-xtor.txt30
-rw-r--r--Documentation/devicetree/bindings/sound/sgtl5000.txt9
-rw-r--r--Documentation/devicetree/bindings/sound/wm8962.txt8
-rw-r--r--Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt32
-rw-r--r--Documentation/devicetree/bindings/usb/usbmisc-imx.txt2
-rw-r--r--Documentation/usb/chipidea.txt13
-rw-r--r--arch/arm/Kconfig11
-rw-r--r--arch/arm/Kconfig.debug9
-rw-r--r--arch/arm/boot/dts/Makefile164
-rw-r--r--arch/arm/boot/dts/imx6dl-aristainetos_4.dts48
-rw-r--r--arch/arm/boot/dts/imx6dl-aristainetos_7.dts51
-rw-r--r--arch/arm/boot/dts/imx6dl-riotboard.dts33
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-ecspi.dts39
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-enetirq.dts19
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-flexcan1.dts18
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto-gpmi-weim.dts48
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto.dts14
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd-btwifi.dts10
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd-enetirq.dts18
-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.dts137
-rw-r--r--arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts44
-rw-r--r--arch/arm/boot/dts/imx6dl-tx6u-801x.dts137
-rw-r--r--arch/arm/boot/dts/imx6dl.dtsi108
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-evb-btwifi-fix-ldo.dts10
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-evb-enetirq-fix-ldo.dts18
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-evb-fix-ldo.dts219
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-evb-hdcp-fix-ldo.dts19
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-evb-interleave-android-ldo.dts209
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-fix.dtsi14
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-interleave-android.dtsi14
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-fix-ldo.dts62
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-hdcp-fix-ldo.dts19
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-interleave-android-ldo.dts62
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-wifi-fix-ldo.dts10
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-btwifi-fix-ldo.dts10
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-fix-ldo.dts147
-rw-r--r--arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-hdcp-fix-ldo.dts19
-rw-r--r--arch/arm/boot/dts/imx6dqscm-qwks-rev2.dtsi610
-rw-r--r--arch/arm/boot/dts/imx6dqscm-qwks-rev3-btwifi.dtsi86
-rw-r--r--arch/arm/boot/dts/imx6dqscm-qwks-wifi.dtsi94
-rw-r--r--arch/arm/boot/dts/imx6q-arm2-hsic.dts24
-rw-r--r--arch/arm/boot/dts/imx6q-arm2.dts30
-rw-r--r--arch/arm/boot/dts/imx6q-gk802.dts33
-rw-r--r--arch/arm/boot/dts/imx6q-gw5400-a.dts30
-rw-r--r--arch/arm/boot/dts/imx6q-pop-arm2.dts437
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-ecspi.dts40
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-enetirq.dts19
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-flexcan1.dts18
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto-gpmi-weim.dts49
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto.dts22
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd-btwifi.dts10
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd-enetirq.dts18
-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.dts34
-rw-r--r--arch/arm/boot/dts/imx6q-tbs2910.dts37
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts44
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1010.dts137
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts44
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1020.dts138
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi106
-rw-r--r--arch/arm/boot/dts/imx6qdl-aristainetos.dtsi56
-rw-r--r--arch/arm/boot/dts/imx6qdl-cubox-i.dtsi9
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw51xx.dtsi30
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw52xx.dtsi30
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw53xx.dtsi30
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw54xx.dtsi30
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw552x.dtsi30
-rw-r--r--arch/arm/boot/dts/imx6qdl-hummingboard.dtsi35
-rw-r--r--arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi33
-rw-r--r--arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi27
-rw-r--r--arch/arm/boot/dts/imx6qdl-rex.dtsi33
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabreauto.dtsi577
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabrelite.dtsi10
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi105
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd.dtsi558
-rw-r--r--arch/arm/boot/dts/imx6qdl-udoo.dtsi30
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard.dtsi7
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi220
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto-ecspi.dts40
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto-flexcan1.dts18
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto-gpmi-weim.dts50
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto.dts98
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd-btwifi.dts10
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd-hdcp.dts39
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd-ldo-pcie-cert.dts21
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd-ldo.dts34
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd.dts112
-rw-r--r--arch/arm/boot/dts/imx6qp.dtsi105
-rw-r--r--arch/arm/boot/dts/imx6sl-evk-btwifi.dts105
-rw-r--r--arch/arm/boot/dts/imx6sl-evk-csi.dts21
-rw-r--r--arch/arm/boot/dts/imx6sl-evk-ldo.dts27
-rw-r--r--arch/arm/boot/dts/imx6sl-evk-uart.dts23
-rw-r--r--arch/arm/boot/dts/imx6sl-evk.dts340
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi177
-rw-r--r--arch/arm/boot/dts/imx6sll-evk-btwifi.dts83
-rw-r--r--arch/arm/boot/dts/imx6sll-evk-reva.dts13
-rw-r--r--arch/arm/boot/dts/imx6sll-evk.dts815
-rw-r--r--arch/arm/boot/dts/imx6sll-lpddr2-arm2.dts10
-rw-r--r--arch/arm/boot/dts/imx6sll-lpddr3-arm2-csi.dts21
-rw-r--r--arch/arm/boot/dts/imx6sll-lpddr3-arm2-ecspi.dts17
-rw-r--r--arch/arm/boot/dts/imx6sll-lpddr3-arm2-spdif.dts42
-rw-r--r--arch/arm/boot/dts/imx6sll-lpddr3-arm2.dts834
-rwxr-xr-xarch/arm/boot/dts/imx6sll-pinfunc.h882
-rw-r--r--arch/arm/boot/dts/imx6sll.dtsi859
-rw-r--r--arch/arm/boot/dts/imx6sx-14x14-arm2.dts1333
-rw-r--r--arch/arm/boot/dts/imx6sx-19x19-arm2-csi.dts25
-rw-r--r--arch/arm/boot/dts/imx6sx-19x19-arm2-gpmi-weim.dts20
-rw-r--r--arch/arm/boot/dts/imx6sx-19x19-arm2-ldo.dts21
-rw-r--r--arch/arm/boot/dts/imx6sx-19x19-arm2.dts1259
-rw-r--r--arch/arm/boot/dts/imx6sx-pinfunc.h28
-rw-r--r--arch/arm/boot/dts/imx6sx-sabreauto-m4.dts93
-rw-r--r--arch/arm/boot/dts/imx6sx-sabreauto.dts826
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-btwifi.dts120
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-emmc.dts30
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-lcdif1.dts37
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-ldo.dts39
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-m4.dts91
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-mqs.dts46
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-reva-ldo.dts21
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-reva.dts47
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb-sai.dts4
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb.dts134
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb.dtsi563
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi372
-rw-r--r--arch/arm/boot/dts/imx6sxscm-1gb-evb-btwifi-ldo.dts10
-rw-r--r--arch/arm/boot/dts/imx6sxscm-1gb-evb-lcdif1-ldo.dts42
-rw-r--r--arch/arm/boot/dts/imx6sxscm-1gb-evb-ldo.dts9
-rw-r--r--arch/arm/boot/dts/imx6sxscm-1gb-evb-m4-ldo.dts90
-rw-r--r--arch/arm/boot/dts/imx6sxscm-1gb-evb-mqs-ldo.dts43
-rw-r--r--arch/arm/boot/dts/imx6sxscm-1gb-evb-sai-ldo.dts31
-rw-r--r--arch/arm/boot/dts/imx6sxscm-512mb-evb-ldo.dts10
-rw-r--r--arch/arm/boot/dts/imx6sxscm-512mb-evb-m4-ldo.dts19
-rw-r--r--arch/arm/boot/dts/imx6sxscm-512mb.dtsi14
-rw-r--r--arch/arm/boot/dts/imx6sxscm-emmc.dtsi21
-rw-r--r--arch/arm/boot/dts/imx6sxscm-epop-evb-ldo.dts9
-rw-r--r--arch/arm/boot/dts/imx6sxscm-epop-evb-m4-ldo.dts9
-rw-r--r--arch/arm/boot/dts/imx6sxscm-evb-btwifi.dtsi131
-rw-r--r--arch/arm/boot/dts/imx6sxscm-evb-ldo.dts34
-rw-r--r--arch/arm/boot/dts/imx6sxscm-evb.dts1156
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-emmc.dts23
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-flexcan2.dts18
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-gpmi-weim.dts34
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-mqs.dts41
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-spdif.dts42
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-wm8958.dts102
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2.dts774
-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.dts22
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-emmc.dts20
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-gpmi-weim.dts49
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-pf1550.dts133
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk-usb-certi.dts34
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk.dts354
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-lpddr2-arm2.dts788
-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-csi.dts22
-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-pinfunc.h169
-rw-r--r--arch/arm/boot/dts/imx6ul.dtsi287
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-adc.dts20
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-cs42888.dts158
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-ecspi.dts22
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-emmc.dts20
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-epdc.dts25
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-flexcan2.dts19
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-gpmi-weim.dts21
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-lcdif.dts29
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-ldo.dts41
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-qspi-all.dts18
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-qspi.dts9
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-tsc.dts39
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-uart2.dts21
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-usb.dts60
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-wm8958.dts155
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2.dts1029
-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.dts19
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-evk-gpmi-weim.dts49
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-evk-usb-certi.dts34
-rw-r--r--arch/arm/boot/dts/imx6ull-14x14-evk.dts750
-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-pinfunc-snvs.h29
-rw-r--r--arch/arm/boot/dts/imx6ull-pinfunc.h93
-rw-r--r--arch/arm/boot/dts/imx6ull.dtsi1187
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-ddr3-arm2.dts558
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-ecspi.dts27
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-enet2.dts17
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-flexcan.dts29
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts76
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-mipi_dsi.dts29
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-mqs.dts49
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-pcie.dts22
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-qspi.dts84
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-sai.dts46
-rw-r--r--arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2.dts1017
-rw-r--r--arch/arm/boot/dts/imx7d-19x19-lpddr2-arm2.dts454
-rw-r--r--arch/arm/boot/dts/imx7d-pinfunc-lpsr.h76
-rw-r--r--arch/arm/boot/dts/imx7d-pinfunc.h57
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-epdc.dts9
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-epdc.dtsi54
-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.dtsi68
-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-reva-epdc.dts9
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-reva-gpmi-weim.dts9
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-reva-hdmi-audio.dts20
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-reva-m4.dts9
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-reva-qspi.dts9
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-reva-touch.dts21
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-reva-wm8960.dts20
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-reva.dts92
-rw-r--r--arch/arm/boot/dts/imx7d-sdb.dts640
-rw-r--r--arch/arm/boot/dts/imx7d.dtsi379
-rw-r--r--arch/arm/boot/dts/imx7s.dtsi96
-rw-r--r--arch/arm/boot/dts/imx7ulp-14x14-arm2.dts72
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-emmc-qspi.dts18
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-emmc.dts18
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-ft5416.dts17
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-hdmi.dts26
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-lpuart.dts17
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-qspi.dts76
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-sd1.dts49
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-sensors-to-i2c5.dts22
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk-wm8960.dts217
-rw-r--r--arch/arm/boot/dts/imx7ulp-evk.dts551
-rw-r--r--arch/arm/boot/dts/imx7ulp-pinfunc.h875
-rw-r--r--arch/arm/boot/dts/imx7ulp.dtsi633
-rw-r--r--arch/arm/boot/dts/vfxxx.dtsi1
-rw-r--r--arch/arm/configs/imx_v7_defconfig455
-rw-r--r--arch/arm/configs/imx_v7_mfg_defconfig301
-rw-r--r--arch/arm/include/debug/imx-uart.h10
-rw-r--r--arch/arm/mach-imx/Kconfig74
-rw-r--r--arch/arm/mach-imx/Makefile53
-rw-r--r--arch/arm/mach-imx/anatop.c171
-rw-r--r--arch/arm/mach-imx/busfreq-imx.c1369
-rw-r--r--arch/arm/mach-imx/busfreq_ddr3.c773
-rw-r--r--arch/arm/mach-imx/busfreq_lpddr2.c373
-rw-r--r--arch/arm/mach-imx/common.c161
-rw-r--r--arch/arm/mach-imx/common.h103
-rw-r--r--arch/arm/mach-imx/cpu.c14
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c5
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sl.c176
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sll.c264
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sx.c247
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6ul.c315
-rw-r--r--arch/arm/mach-imx/cpuidle-imx7d.c356
-rw-r--r--arch/arm/mach-imx/cpuidle-imx7ulp.c62
-rw-r--r--arch/arm/mach-imx/cpuidle.h27
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6.S1079
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6sx.S737
-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.c547
-rw-r--r--arch/arm/mach-imx/gpcv2.c1052
-rw-r--r--arch/arm/mach-imx/hardware.h16
-rw-r--r--arch/arm/mach-imx/headsmp.S13
-rw-r--r--arch/arm/mach-imx/hotplug.c5
-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.S787
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6.S593
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6q.S765
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6sll.S436
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6sx.S468
-rw-r--r--arch/arm/mach-imx/lpddr3_freq_imx.S444
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c103
-rw-r--r--arch/arm/mach-imx/mach-imx6sl.c39
-rw-r--r--arch/arm/mach-imx/mach-imx6sx.c49
-rw-r--r--arch/arm/mach-imx/mach-imx6ul.c138
-rw-r--r--arch/arm/mach-imx/mach-imx7d.c62
-rw-r--r--arch/arm/mach-imx/mach-imx7ulp.c74
-rw-r--r--arch/arm/mach-imx/mmdc.c533
-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.h35
-rw-r--r--arch/arm/mach-imx/platsmp.c38
-rw-r--r--arch/arm/mach-imx/pm-imx6.c942
-rw-r--r--arch/arm/mach-imx/pm-imx7.c1187
-rw-r--r--arch/arm/mach-imx/pm-imx7ulp.c756
-rw-r--r--arch/arm/mach-imx/pm-rpmsg.c343
-rw-r--r--arch/arm/mach-imx/smp_wfe.S110
-rw-r--r--arch/arm/mach-imx/smp_wfe_imx6.S132
-rw-r--r--arch/arm/mach-imx/src.c93
-rw-r--r--arch/arm/mach-imx/suspend-imx6.S531
-rw-r--r--arch/arm/mach-imx/suspend-imx7.S714
-rw-r--r--arch/arm/mach-imx/suspend-imx7ulp.S594
-rw-r--r--arch/arm/mm/Kconfig2
-rw-r--r--arch/arm/mm/cache-v7.S3
-rw-r--r--arch/arm/mm/proc-syms.c4
-rw-r--r--arch/arm64/configs/defconfig12
-rw-r--r--arch/x86/include/asm/idle.h7
-rw-r--r--arch/x86/kernel/process.c17
-rw-r--r--block/blk-map.c15
-rw-r--r--block/scsi_ioctl.c27
-rw-r--r--crypto/gcm.c2
-rw-r--r--crypto/testmgr.c2
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/ata/ahci_imx.c56
-rw-r--r--drivers/base/Kconfig1
-rw-r--r--drivers/base/power/domain.c7
-rw-r--r--drivers/base/regmap/regmap-mmio.c20
-rw-r--r--drivers/char/Kconfig16
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/fsl_otp.c738
-rw-r--r--drivers/char/hw_random/Kconfig12
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/imx-rng.c440
-rw-r--r--drivers/char/imx_amp/Kconfig9
-rw-r--r--drivers/char/imx_amp/Makefile5
-rw-r--r--drivers/char/imx_amp/imx_sema4.c413
-rw-r--r--drivers/clk/imx/Makefile10
-rw-r--r--drivers/clk/imx/clk-busy.c2
-rw-r--r--drivers/clk/imx/clk-composite.c93
-rw-r--r--drivers/clk/imx/clk-frac-divider.c96
-rw-r--r--drivers/clk/imx/clk-gate2.c70
-rw-r--r--drivers/clk/imx/clk-imx6q.c541
-rw-r--r--drivers/clk/imx/clk-imx6sl.c102
-rw-r--r--drivers/clk/imx/clk-imx6sll.c380
-rw-r--r--drivers/clk/imx/clk-imx6sx.c285
-rw-r--r--drivers/clk/imx/clk-imx6ul.c113
-rw-r--r--drivers/clk/imx/clk-imx7d.c213
-rw-r--r--drivers/clk/imx/clk-imx7ulp.c298
-rw-r--r--drivers/clk/imx/clk-pfd.c52
-rw-r--r--drivers/clk/imx/clk-pfdv2.c172
-rw-r--r--drivers/clk/imx/clk-pllv3.c129
-rw-r--r--drivers/clk/imx/clk-pllv4.c178
-rw-r--r--drivers/clk/imx/clk-pllv5.c199
-rw-r--r--drivers/clk/imx/clk.c10
-rw-r--r--drivers/clk/imx/clk.h184
-rw-r--r--drivers/clocksource/Kconfig5
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/timer-imx-gpt.c3
-rw-r--r--drivers/clocksource/timer-imx-tpm.c189
-rw-r--r--drivers/cpufreq/Kconfig30
-rw-r--r--drivers/cpufreq/Kconfig.arm16
-rw-r--r--drivers/cpufreq/Makefile3
-rw-r--r--drivers/cpufreq/cpufreq_governor.h8
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c1365
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c231
-rw-r--r--drivers/cpufreq/imx7-cpufreq.c271
-rw-r--r--drivers/cpufreq/imx7ulp-cpufreq.c285
-rw-r--r--drivers/crypto/caam/Kconfig52
-rw-r--r--drivers/crypto/caam/Makefile3
-rw-r--r--drivers/crypto/caam/caamalg.c165
-rw-r--r--drivers/crypto/caam/caamhash.c282
-rw-r--r--drivers/crypto/caam/caamrng.c47
-rw-r--r--drivers/crypto/caam/ctrl.c220
-rw-r--r--drivers/crypto/caam/ctrl.h3
-rw-r--r--drivers/crypto/caam/desc.h32
-rw-r--r--drivers/crypto/caam/error.c14
-rw-r--r--drivers/crypto/caam/intern.h11
-rw-r--r--drivers/crypto/caam/jr.c44
-rw-r--r--drivers/crypto/caam/regs.h169
-rw-r--r--drivers/crypto/caam/secvio.c332
-rw-r--r--drivers/crypto/caam/secvio.h67
-rw-r--r--drivers/crypto/caam/sm.h125
-rw-r--r--drivers/crypto/caam/sm_store.c1234
-rw-r--r--drivers/crypto/caam/sm_test.c524
-rw-r--r--drivers/crypto/caam/snvsregs.h237
-rw-r--r--drivers/crypto/mxs-dcp.c152
-rw-r--r--drivers/dma/Kconfig5
-rw-r--r--drivers/dma/Makefile2
-rw-r--r--drivers/dma/fsl-edma.c257
-rw-r--r--drivers/dma/imx-sdma.c1034
-rw-r--r--drivers/dma/mxs-dma.c80
-rw-r--r--drivers/dma/pxp/Kconfig22
-rw-r--r--drivers/dma/pxp/Makefile3
-rw-r--r--drivers/dma/pxp/pxp_device.c878
-rw-r--r--drivers/dma/pxp/pxp_dma_v2.c1865
-rw-r--r--drivers/dma/pxp/pxp_dma_v3.c8102
-rw-r--r--drivers/dma/pxp/reg_bitfields.h280
-rw-r--r--drivers/dma/pxp/regs-pxp_v2.h1152
-rw-r--r--drivers/dma/pxp/regs-pxp_v3.h26950
-rw-r--r--drivers/extcon/extcon-usb-gpio.c181
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-74x164.c3
-rw-r--r--drivers/gpio/gpio-imx-rpmsg.c322
-rw-r--r--drivers/gpio/gpio-pca953x.c5
-rw-r--r--drivers/gpio/gpio-vf610.c28
-rw-r--r--drivers/gpu/drm/Kconfig6
-rw-r--r--drivers/gpu/drm/Makefile1
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c11
-rw-r--r--drivers/gpu/drm/vivante/Makefile29
-rw-r--r--drivers/gpu/drm/vivante/vivante_drv.c131
-rw-r--r--drivers/gpu/drm/vivante/vivante_drv.h66
-rw-r--r--drivers/hwmon/Kconfig25
-rw-r--r--drivers/hwmon/Makefile3
-rw-r--r--drivers/hwmon/mag3110.c654
-rw-r--r--drivers/hwmon/max17135-hwmon.c176
-rw-r--r--drivers/hwmon/mxc_mma8451.c598
-rw-r--r--drivers/i2c/busses/Kconfig10
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-imx-lpi2c.c667
-rw-r--r--drivers/i2c/busses/i2c-imx.c19
-rw-r--r--drivers/iio/adc/vf610_adc.c10
-rw-r--r--drivers/input/keyboard/Kconfig19
-rw-r--r--drivers/input/keyboard/Makefile2
-rw-r--r--drivers/input/keyboard/atkbd.c3
-rw-r--r--drivers/input/keyboard/gpio_keys.c4
-rw-r--r--drivers/input/keyboard/imx_keypad.c27
-rw-r--r--drivers/input/keyboard/pf1550_onkey.c206
-rw-r--r--drivers/input/keyboard/rpmsg-keys.c310
-rw-r--r--drivers/input/misc/Kconfig25
-rw-r--r--drivers/input/misc/Makefile3
-rw-r--r--drivers/input/misc/fxls8471.c582
-rw-r--r--drivers/input/misc/fxls8471.h94
-rw-r--r--drivers/input/misc/fxls8471_i2c.c111
-rw-r--r--drivers/input/misc/isl29023.c1075
-rw-r--r--drivers/input/misc/mma8450.c173
-rw-r--r--drivers/input/misc/mpl3115.c348
-rw-r--r--drivers/input/touchscreen/Kconfig27
-rw-r--r--drivers/input/touchscreen/Makefile3
-rw-r--r--drivers/input/touchscreen/ads7846.c6
-rw-r--r--drivers/input/touchscreen/egalax_ts.c14
-rw-r--r--drivers/input/touchscreen/elan_ts.c472
-rw-r--r--drivers/input/touchscreen/focaltech_touch/Kconfig16
-rw-r--r--drivers/input/touchscreen/focaltech_touch/Makefile13
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_common.h211
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_config.h219
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_core.c1439
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_core.h189
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c473
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c357
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c652
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c209
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c151
-rw-r--r--drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c311
-rw-r--r--drivers/input/touchscreen/focaltech_touch/include/firmware/FT8716_app_sample.i0
-rw-r--r--drivers/input/touchscreen/focaltech_touch/include/firmware/lcd_cfg.i0
-rw-r--r--drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8606_Pramboot_V0.7_20150507.i244
-rw-r--r--drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8607_Pramboot_V0.3_20160727.i248
-rw-r--r--drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8716_Pramboot_V0.5_20160723.i303
-rw-r--r--drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8736_Pramboot_V0.4_20160627.i288
-rw-r--r--drivers/input/touchscreen/max11801_ts.c192
-rw-r--r--drivers/input/touchscreen/vtl/Makefile5
-rw-r--r--drivers/input/touchscreen/vtl/vtl_ts.c496
-rw-r--r--drivers/input/touchscreen/vtl/vtl_ts.h181
-rw-r--r--drivers/media/platform/Kconfig17
-rw-r--r--drivers/media/platform/Makefile6
-rw-r--r--drivers/media/platform/mxc/capture/Kconfig83
-rw-r--r--drivers/media/platform/mxc/capture/Makefile21
-rw-r--r--drivers/media/platform/mxc/capture/adv7180.c1380
-rw-r--r--drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c552
-rw-r--r--drivers/media/platform/mxc/capture/ipu_csi_enc.c430
-rw-r--r--drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c638
-rw-r--r--drivers/media/platform/mxc/capture/ipu_prp_enc.c597
-rw-r--r--drivers/media/platform/mxc/capture/ipu_prp_sw.h43
-rw-r--r--drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c582
-rw-r--r--drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c521
-rw-r--r--drivers/media/platform/mxc/capture/ipu_still.c268
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.c3148
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.h262
-rw-r--r--drivers/media/platform/mxc/capture/ov5640.c1950
-rw-r--r--drivers/media/platform/mxc/capture/ov5640_mipi.c2142
-rw-r--r--drivers/media/platform/mxc/capture/ov5642.c4252
-rw-r--r--drivers/media/platform/mxc/capture/v4l2-int-device.c165
-rw-r--r--drivers/media/platform/mxc/capture/v4l2-int-device.h309
-rw-r--r--drivers/media/platform/mxc/output/Kconfig16
-rw-r--r--drivers/media/platform/mxc/output/Makefile2
-rw-r--r--drivers/media/platform/mxc/output/mxc_pxp_v4l2.c1346
-rw-r--r--drivers/media/platform/mxc/output/mxc_pxp_v4l2.h87
-rw-r--r--drivers/media/platform/mxc/output/mxc_vout.c2331
-rw-r--r--drivers/media/platform/mxc/subdev/Kconfig38
-rw-r--r--drivers/media/platform/mxc/subdev/Makefile14
-rw-r--r--drivers/media/platform/mxc/subdev/mx6s_capture.c1970
-rw-r--r--drivers/media/platform/mxc/subdev/mxc_mipi_csi.c1248
-rw-r--r--drivers/media/platform/mxc/subdev/mxc_vadc.c830
-rw-r--r--drivers/media/platform/mxc/subdev/mxc_vadc.h239
-rw-r--r--drivers/media/platform/mxc/subdev/ov5640.c1895
-rw-r--r--drivers/media/platform/mxc/subdev/ov5640_mipi.c1660
-rw-r--r--drivers/media/platform/mxc/subdev/ov5647_mipi.c1721
-rw-r--r--drivers/media/radio/radio-si476x.c24
-rw-r--r--drivers/media/v4l2-core/v4l2-async.c7
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c29
-rw-r--r--drivers/media/v4l2-core/v4l2-device.c1
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c36
-rw-r--r--drivers/media/v4l2-core/videobuf-core.c7
-rw-r--r--drivers/mfd/Kconfig29
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--drivers/mfd/max17135-core.c281
-rw-r--r--drivers/mfd/mxc-hdmi-core.c821
-rw-r--r--drivers/mfd/pf1550.c311
-rw-r--r--drivers/mfd/si476x-i2c.c23
-rw-r--r--drivers/misc/Kconfig20
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/eeprom/at25.c2
-rw-r--r--drivers/misc/fxas2100x.c618
-rw-r--r--drivers/misc/fxos8700.c970
-rw-r--r--drivers/misc/sram.c2
-rw-r--r--drivers/mmc/card/block.c9
-rw-r--r--drivers/mmc/core/core.c43
-rw-r--r--drivers/mmc/core/debugfs.c10
-rw-r--r--drivers/mmc/core/host.c34
-rw-r--r--drivers/mmc/core/mmc_ops.c6
-rw-r--r--drivers/mmc/core/sd.c7
-rw-r--r--drivers/mmc/core/sdio.c44
-rw-r--r--drivers/mmc/host/Kconfig2
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c171
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c10
-rw-r--r--drivers/mmc/host/sdhci.c70
-rw-r--r--drivers/mmc/host/sdhci.h4
-rw-r--r--drivers/mtd/Makefile2
-rw-r--r--drivers/mtd/nand/gpmi-nand/bch-regs.h24
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-lib.c110
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c413
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.h32
-rw-r--r--drivers/mtd/spi-nor/fsl-quadspi.c310
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c82
-rw-r--r--drivers/mtd/ubi/build.c2
-rw-r--r--drivers/mxc/Kconfig24
-rw-r--r--drivers/mxc/Makefile7
-rw-r--r--drivers/mxc/gpu-viv/Kbuild308
-rw-r--r--drivers/mxc/gpu-viv/Kconfig9
-rw-r--r--drivers/mxc/gpu-viv/config73
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c3150
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h199
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c15300
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h365
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c728
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c1192
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h353
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c2308
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h114
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c6137
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h2014
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_async_command.c454
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c3556
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c3948
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c1880
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c2852
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c3224
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c892
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c911
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c2756
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c556
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c381
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h63
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c284
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security_v1.c320
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c571
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h119
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c3138
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_feature_database.h46686
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h2832
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h5999
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h1343
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h300
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h123
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h587
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h324
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h3059
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h1318
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h2148
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h289
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h564
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h1422
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h1353
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h1057
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h277
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_resource.h67
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h184
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h133
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h1020
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h69
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h922
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h106
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dma.c496
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c502
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c646
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h116
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c473
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c1150
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h436
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h163
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c963
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h170
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c2305
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h256
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c1455
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c250
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c527
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h368
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c66
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_mutex.h89
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c7807
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h108
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h386
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c426
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel_emulator.c116
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c381
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h146
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/default/gc_hal_kernel_platform_default.c81
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.c1186
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.config27
-rw-r--r--drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c348
-rw-r--r--drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.h373
-rw-r--r--drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_hardware.c964
-rw-r--r--drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_hardware.h139
-rw-r--r--drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_mmu.c586
-rw-r--r--drivers/mxc/gpu-viv/hal/security_v1/os/emulator/gc_hal_ta_emulator.c322
-rw-r--r--drivers/mxc/hdmi-cec/Kconfig11
-rw-r--r--drivers/mxc/hdmi-cec/Makefile1
-rw-r--r--drivers/mxc/hdmi-cec/mxc_hdmi-cec.c665
-rw-r--r--drivers/mxc/hdmi-cec/mxc_hdmi-cec.h38
-rw-r--r--drivers/mxc/ipu3/Kconfig21
-rw-r--r--drivers/mxc/ipu3/Makefile7
-rw-r--r--drivers/mxc/ipu3/ipu_calc_stripes_sizes.c495
-rw-r--r--drivers/mxc/ipu3/ipu_capture.c816
-rw-r--r--drivers/mxc/ipu3/ipu_common.c3494
-rw-r--r--drivers/mxc/ipu3/ipu_device.c3750
-rw-r--r--drivers/mxc/ipu3/ipu_disp.c1981
-rw-r--r--drivers/mxc/ipu3/ipu_ic.c924
-rw-r--r--drivers/mxc/ipu3/ipu_param_mem.h998
-rw-r--r--drivers/mxc/ipu3/ipu_pixel_clk.c317
-rw-r--r--drivers/mxc/ipu3/ipu_prv.h369
-rw-r--r--drivers/mxc/ipu3/ipu_regs.h702
-rw-r--r--drivers/mxc/ipu3/pre-regs.h480
-rw-r--r--drivers/mxc/ipu3/pre.c999
-rw-r--r--drivers/mxc/ipu3/prg-regs.h70
-rw-r--r--drivers/mxc/ipu3/prg.c506
-rw-r--r--drivers/mxc/ipu3/vdoa.c536
-rw-r--r--drivers/mxc/ipu3/vdoa.h62
-rw-r--r--drivers/mxc/mipi/Kconfig14
-rw-r--r--drivers/mxc/mipi/Makefile4
-rw-r--r--drivers/mxc/mipi/mxc_mipi_csi2.c540
-rw-r--r--drivers/mxc/mipi/mxc_mipi_csi2.h46
-rw-r--r--drivers/mxc/mlb/Kconfig17
-rw-r--r--drivers/mxc/mlb/Makefile5
-rwxr-xr-xdrivers/mxc/mlb/mxc_mlb.c2809
-rw-r--r--drivers/mxc/sim/Kconfig13
-rw-r--r--drivers/mxc/sim/Makefile5
-rwxr-xr-xdrivers/mxc/sim/imx_sim.c1865
-rw-r--r--drivers/mxc/vpu/Kconfig31
-rw-r--r--drivers/mxc/vpu/Makefile9
-rw-r--r--drivers/mxc/vpu/mxc_vpu.c1348
-rw-r--r--drivers/net/can/flexcan.c153
-rw-r--r--drivers/net/ethernet/freescale/Kconfig4
-rw-r--r--drivers/net/ethernet/freescale/Makefile2
-rw-r--r--drivers/net/ethernet/freescale/fec.h37
-rw-r--r--drivers/net/ethernet/freescale/fec_fixup.c74
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c342
-rw-r--r--drivers/net/phy/micrel.c18
-rw-r--r--drivers/net/phy/phy_device.c23
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile1
-rw-r--r--drivers/net/wireless/bcmdhd/Kconfig64
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile229
-rw-r--r--drivers/net/wireless/bcmdhd/aiutils.c1012
-rw-r--r--drivers/net/wireless/bcmdhd/bcmevent.c242
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh.c705
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_linux.c473
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c1491
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c405
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdspi_linux.c249
-rw-r--r--drivers/net/wireless/bcmdhd/bcmspibrcm.c1814
-rw-r--r--drivers/net/wireless/bcmdhd/bcmutils.c3084
-rw-r--r--drivers/net/wireless/bcmdhd/bcmwifi_channels.c1206
-rw-r--r--drivers/net/wireless/bcmdhd/bcmwifi_channels.h495
-rw-r--r--drivers/net/wireless/bcmdhd/bcmwifi_rates.h458
-rw-r--r--drivers/net/wireless/bcmdhd/circularbuf.c326
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h931
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_bta.c337
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_bta.h39
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_bus.h158
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cdc.c789
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cfg80211.c301
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cfg80211.h59
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c2640
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_custom_gpio.c300
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_dbg.h123
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_ip.c965
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_ip.h71
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c8008
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.h77
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux_platdev.c821
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux_sched.c48
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux_wq.c316
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux_wq.h64
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_msgbuf.c1755
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pcie.c2566
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pcie.h169
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pcie_linux.c503
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pno.c1899
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pno.h253
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_proto.h115
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c8343
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_wlfc.c4049
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_wlfc.h513
-rw-r--r--drivers/net/wireless/bcmdhd/dngl_stats.h43
-rw-r--r--drivers/net/wireless/bcmdhd/dngl_wlhdr.h40
-rw-r--r--drivers/net/wireless/bcmdhd/hndpmu.c282
-rw-r--r--drivers/net/wireless/bcmdhd/include/Makefile53
-rw-r--r--drivers/net/wireless/bcmdhd/include/aidmp.h387
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcm_cfg.h29
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h361
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmcdc.h132
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmdefs.h348
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmdevs.h688
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmendian.h329
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmmsgbuf.h261
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmnvram.h272
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmpcie.h129
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmpcispi.h181
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmperf.h36
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdbus.h143
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdh.h251
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h117
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdpcm.h281
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdspi.h135
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdstd.h282
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmspi.h40
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmspibrcm.h162
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h633
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h1014
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmutils.h1204
-rw-r--r--drivers/net/wireless/bcmdhd/include/brcm_nl80211.h56
-rw-r--r--drivers/net/wireless/bcmdhd/include/circularbuf.h115
-rw-r--r--drivers/net/wireless/bcmdhd/include/dbus.h582
-rw-r--r--drivers/net/wireless/bcmdhd/include/devctrl_if/wlioctl_defs.h1987
-rw-r--r--drivers/net/wireless/bcmdhd/include/dhdioctl.h135
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h48
-rw-r--r--drivers/net/wireless/bcmdhd/include/hndpmu.h36
-rw-r--r--drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h88
-rw-r--r--drivers/net/wireless/bcmdhd/include/hndrte_cons.h78
-rw-r--r--drivers/net/wireless/bcmdhd/include/hndsoc.h282
-rw-r--r--drivers/net/wireless/bcmdhd/include/linux_osl.h763
-rw-r--r--drivers/net/wireless/bcmdhd/include/linuxver.h754
-rw-r--r--drivers/net/wireless/bcmdhd/include/miniopt.h77
-rw-r--r--drivers/net/wireless/bcmdhd/include/msgtrace.h77
-rw-r--r--drivers/net/wireless/bcmdhd/include/osl.h142
-rw-r--r--drivers/net/wireless/bcmdhd/include/packed_section_end.h59
-rw-r--r--drivers/net/wireless/bcmdhd/include/packed_section_start.h63
-rw-r--r--drivers/net/wireless/bcmdhd/include/pcicfg.h101
-rw-r--r--drivers/net/wireless/bcmdhd/include/pcie_core.h581
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/802.11.h3803
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h45
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/802.11e.h132
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/802.1d.h50
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/802.3.h52
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/bcmeth.h112
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/bcmevent.h517
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/bcmip.h231
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/bcmipv6.h159
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/bcmtcp.h90
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h441
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/eapol.h211
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/ethernet.h220
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/p2p.h608
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/sdspi.h75
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/vlan.h95
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/wpa.h175
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/wps.h379
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbchipc.h3304
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbconfig.h282
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbhnddma.h416
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbpcmcia.h113
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbsdio.h186
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h295
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbsocram.h200
-rw-r--r--drivers/net/wireless/bcmdhd/include/sdio.h619
-rw-r--r--drivers/net/wireless/bcmdhd/include/sdioh.h445
-rw-r--r--drivers/net/wireless/bcmdhd/include/sdiovar.h58
-rw-r--r--drivers/net/wireless/bcmdhd/include/siutils.h440
-rw-r--r--drivers/net/wireless/bcmdhd/include/spid.h165
-rw-r--r--drivers/net/wireless/bcmdhd/include/trxhdr.h92
-rw-r--r--drivers/net/wireless/bcmdhd/include/typedefs.h344
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlfc_proto.h304
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlioctl.h5008
-rw-r--r--drivers/net/wireless/bcmdhd/linux_osl.c1529
-rw-r--r--drivers/net/wireless/bcmdhd/sbutils.c1063
-rw-r--r--drivers/net/wireless/bcmdhd/siutils.c2882
-rw-r--r--drivers/net/wireless/bcmdhd/siutils_priv.h272
-rw-r--r--drivers/net/wireless/bcmdhd/uamp_api.h176
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c2331
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.h77
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c14404
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h1264
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg_btcoex.c545
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c2539
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h414
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgvendor.c201
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgvendor.h56
-rw-r--r--drivers/net/wireless/bcmdhd/wl_dbg.h67
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c3689
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.h159
-rw-r--r--drivers/net/wireless/bcmdhd/wl_linux_mon.c403
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.c479
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.h121
-rw-r--r--drivers/of/base.c30
-rw-r--r--drivers/of/of_reserved_mem.c43
-rw-r--r--drivers/pci/host/Kconfig24
-rw-r--r--drivers/pci/host/Makefile2
-rw-r--r--drivers/pci/host/pci-imx6-ep-driver.c171
-rw-r--r--drivers/pci/host/pci-imx6.c1002
-rw-r--r--drivers/pci/host/pcie-designware.c40
-rw-r--r--drivers/pci/host/pcie-designware.h5
-rw-r--r--drivers/pinctrl/devicetree.c44
-rw-r--r--drivers/pinctrl/freescale/Kconfig14
-rw-r--r--drivers/pinctrl/freescale/Makefile2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c66
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.h4
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx6sll.c388
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx6ul.c52
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx7d.c17
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx7ulp.c438
-rw-r--r--drivers/power/supply/Kconfig14
-rw-r--r--drivers/power/supply/Makefile2
-rw-r--r--drivers/power/supply/pf1550_charger.c656
-rw-r--r--drivers/power/supply/sabresd_battery.c1014
-rw-r--r--drivers/pwm/Kconfig9
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-tpm.c253
-rw-r--r--drivers/regulator/Kconfig19
-rw-r--r--drivers/regulator/Makefile3
-rw-r--r--drivers/regulator/anatop-regulator.c104
-rw-r--r--drivers/regulator/core.c3
-rw-r--r--drivers/regulator/fixed.c24
-rw-r--r--drivers/regulator/max17135-regulator.c858
-rw-r--r--drivers/regulator/pf1550-regulator-rpmsg.c512
-rw-r--r--drivers/regulator/pf1550.c390
-rw-r--r--drivers/regulator/pfuze100-regulator.c102
-rw-r--r--drivers/reset/Kconfig9
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/gpio-reset.c184
-rw-r--r--drivers/rpmsg/Kconfig15
-rw-r--r--drivers/rpmsg/Makefile3
-rw-r--r--drivers/rpmsg/imx_rpmsg.c563
-rw-r--r--drivers/rpmsg/imx_rpmsg_pingpong.c112
-rw-r--r--drivers/rpmsg/imx_rpmsg_tty.c238
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c39
-rw-r--r--drivers/rtc/rtc-snvs.c14
-rw-r--r--drivers/scsi/scsi_error.c20
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/imx/Makefile1
-rw-r--r--drivers/soc/imx/mu/Makefile1
-rw-r--r--drivers/soc/imx/mu/imx_mu.c143
-rw-r--r--drivers/spi/Kconfig7
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi-fsl-lpspi.c500
-rw-r--r--drivers/spi/spi-imx.c83
-rw-r--r--drivers/spi/spi.c7
-rw-r--r--drivers/staging/Makefile2
-rw-r--r--drivers/staging/android/Kconfig4
-rw-r--r--drivers/staging/android/ion/Kconfig8
-rw-r--r--drivers/staging/android/ion/Makefile2
-rw-r--r--drivers/staging/android/ion/ion.c38
-rw-r--r--drivers/staging/android/ion/ion_priv.h6
-rw-r--r--drivers/staging/android/ion/mxc/Makefile2
-rw-r--r--drivers/staging/android/ion/mxc/mxc_ion.c308
-rw-r--r--drivers/staging/android/uapi/ion.h25
-rw-r--r--drivers/thermal/Kconfig7
-rw-r--r--drivers/thermal/Makefile1
-rw-r--r--drivers/thermal/device_cooling.c151
-rw-r--r--drivers/thermal/imx_thermal.c560
-rw-r--r--drivers/tty/serial/fsl_lpuart.c1087
-rw-r--r--drivers/tty/serial/imx.c651
-rw-r--r--drivers/usb/chipidea/ci.h44
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c398
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h43
-rw-r--r--drivers/usb/chipidea/ci_hdrc_msm.c4
-rw-r--r--drivers/usb/chipidea/core.c257
-rw-r--r--drivers/usb/chipidea/host.c332
-rw-r--r--drivers/usb/chipidea/host.h8
-rw-r--r--drivers/usb/chipidea/otg.c133
-rw-r--r--drivers/usb/chipidea/otg.h13
-rw-r--r--drivers/usb/chipidea/otg_fsm.c220
-rw-r--r--drivers/usb/chipidea/otg_fsm.h28
-rw-r--r--drivers/usb/chipidea/udc.c282
-rw-r--r--drivers/usb/chipidea/udc.h13
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c707
-rw-r--r--drivers/usb/common/usb-otg-fsm.c54
-rw-r--r--drivers/usb/core/hub.c23
-rw-r--r--drivers/usb/core/otg_whitelist.h88
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c50
-rw-r--r--drivers/usb/gadget/function/fsl_updater.c594
-rw-r--r--drivers/usb/gadget/function/fsl_updater.h150
-rw-r--r--drivers/usb/gadget/legacy/Kconfig6
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-hub.c2
-rw-r--r--drivers/usb/misc/ehset.c25
-rw-r--r--drivers/usb/phy/phy-generic.c10
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c289
-rw-r--r--drivers/video/backlight/gpio_backlight.c16
-rw-r--r--drivers/video/backlight/pwm_bl.c19
-rw-r--r--drivers/video/console/fbcon.c2
-rw-r--r--drivers/video/fbdev/Kconfig4
-rw-r--r--drivers/video/fbdev/Makefile1
-rw-r--r--drivers/video/fbdev/mxc/Kconfig116
-rw-r--r--drivers/video/fbdev/mxc/Makefile17
-rw-r--r--drivers/video/fbdev/mxc/adv7535.c349
-rw-r--r--drivers/video/fbdev/mxc/crtc.h57
-rw-r--r--drivers/video/fbdev/mxc/epdc_regs.h442
-rw-r--r--drivers/video/fbdev/mxc/epdc_v2_regs.h533
-rw-r--r--drivers/video/fbdev/mxc/hannstar_cabc.c82
-rw-r--r--drivers/video/fbdev/mxc/ldb.c910
-rw-r--r--drivers/video/fbdev/mxc/mipi_dsi.c1039
-rw-r--r--drivers/video/fbdev/mxc/mipi_dsi.h125
-rw-r--r--drivers/video/fbdev/mxc/mipi_dsi_northwest.c1125
-rw-r--r--drivers/video/fbdev/mxc/mipi_dsi_samsung.c952
-rw-r--r--drivers/video/fbdev/mxc/mxc_dcic.c592
-rw-r--r--drivers/video/fbdev/mxc/mxc_dispdrv.c148
-rw-r--r--drivers/video/fbdev/mxc/mxc_dispdrv.h52
-rw-r--r--drivers/video/fbdev/mxc/mxc_edid.c771
-rw-r--r--drivers/video/fbdev/mxc/mxc_epdc_fb.c5601
-rw-r--r--drivers/video/fbdev/mxc/mxc_epdc_v2_fb.c6833
-rw-r--r--drivers/video/fbdev/mxc/mxc_hdmi.c2977
-rw-r--r--drivers/video/fbdev/mxc/mxc_ipuv3_fb.c3673
-rw-r--r--drivers/video/fbdev/mxc/mxc_lcdif.c237
-rw-r--r--drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c220
-rw-r--r--drivers/video/fbdev/mxc/mxcfb_hx8369_wvga.c451
-rw-r--r--drivers/video/fbdev/mxc/mxcfb_otm8018b_wvga.c266
-rw-r--r--drivers/video/fbdev/mxc/mxsfb_sii902x.c558
-rw-r--r--drivers/video/fbdev/mxsfb.c1819
-rw-r--r--drivers/watchdog/Kconfig13
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/imx2_wdt.c4
-rw-r--r--drivers/watchdog/imx7ulp_wdt.c291
-rw-r--r--firmware/Makefile1
-rwxr-xr-xfirmware/imx/sdma/sdma-imx6q.bin.ihex139
-rw-r--r--firmware/imx/sdma/sdma-imx7d.bin.ihex145
-rw-r--r--include/dt-bindings/clock/imx6qdl-clock.h11
-rw-r--r--include/dt-bindings/clock/imx6sl-clock.h3
-rw-r--r--include/dt-bindings/clock/imx6sll-clock.h206
-rw-r--r--include/dt-bindings/clock/imx6sx-clock.h8
-rw-r--r--include/dt-bindings/clock/imx6ul-clock.h18
-rw-r--r--include/dt-bindings/clock/imx7d-clock.h10
-rw-r--r--include/dt-bindings/clock/imx7ulp-clock.h165
-rw-r--r--include/dt-bindings/input/input.h3
-rw-r--r--include/linux/busfreq-imx.h73
-rw-r--r--include/linux/can/platform/flexcan.h20
-rw-r--r--include/linux/cpu.h7
-rw-r--r--include/linux/cpufreq.h12
-rw-r--r--include/linux/device_cooling.h45
-rw-r--r--include/linux/imx_gpc.h25
-rw-r--r--include/linux/imx_mu.h47
-rw-r--r--include/linux/imx_rpmsg.h46
-rw-r--r--include/linux/imx_sema4.h83
-rw-r--r--include/linux/ipu-v3-pre.h155
-rw-r--r--include/linux/ipu-v3-prg.h61
-rw-r--r--include/linux/ipu-v3.h770
-rw-r--r--include/linux/ipu.h38
-rw-r--r--include/linux/isl29023.h47
-rw-r--r--include/linux/mfd/max17135.h220
-rw-r--r--include/linux/mfd/mxc-hdmi-core.h56
-rw-r--r--include/linux/mfd/pf1550.h250
-rw-r--r--include/linux/mfd/si476x-core.h2
-rw-r--r--include/linux/mfd/syscon/imx6q-iomuxc-gpr.h55
-rw-r--r--include/linux/mfd/syscon/imx7-iomuxc-gpr.h2
-rw-r--r--include/linux/mipi_csi2.h93
-rw-r--r--include/linux/mipi_dsi.h165
-rw-r--r--include/linux/mipi_dsi_northwest.h152
-rw-r--r--include/linux/mipi_dsi_samsung.h131
-rw-r--r--include/linux/mmc/core.h3
-rw-r--r--include/linux/mmc/host.h2
-rw-r--r--include/linux/mmc/pm.h1
-rw-r--r--include/linux/mmc/sdio.h4
-rw-r--r--include/linux/mtd/map.h2
-rw-r--r--include/linux/mtd/spi-nor.h13
-rw-r--r--include/linux/mxc_dcic.h126
-rw-r--r--include/linux/mxc_mlb.h55
-rw-r--r--include/linux/mxc_sim_interface.h124
-rw-r--r--include/linux/mxc_v4l2.h27
-rw-r--r--include/linux/mxc_vpu.h118
-rw-r--r--include/linux/mxcfb.h46
-rw-r--r--include/linux/mxcfb_epdc.h45
-rw-r--r--include/linux/of.h6
-rw-r--r--include/linux/of_reserved_mem.h4
-rw-r--r--include/linux/phy.h1
-rw-r--r--include/linux/platform_data/dma-imx-sdma.h3
-rw-r--r--include/linux/platform_data/dma-imx.h10
-rw-r--r--include/linux/pm_domain.h9
-rw-r--r--include/linux/pmic_status.h82
-rw-r--r--include/linux/power/sabresd_battery.h65
-rw-r--r--include/linux/pwm_backlight.h1
-rw-r--r--include/linux/pxp_device.h68
-rw-r--r--include/linux/pxp_dma.h82
-rw-r--r--include/linux/regulator/consumer.h3
-rw-r--r--include/linux/regulator/fixed.h1
-rw-r--r--include/linux/usb.h1
-rw-r--r--include/linux/usb/chipidea.h19
-rw-r--r--include/linux/usb/otg-fsm.h13
-rw-r--r--include/linux/usb/phy.h42
-rw-r--r--include/linux/wakelock.h67
-rw-r--r--include/media/v4l2-chip-ident.h355
-rw-r--r--include/media/v4l2-dev.h1
-rw-r--r--include/media/v4l2-device.h2
-rw-r--r--include/media/v4l2-ioctl.h2
-rw-r--r--include/media/v4l2-subdev.h2
-rw-r--r--include/soc/imx/gpc.h7
-rw-r--r--include/soc/imx/src.h6
-rw-r--r--include/sound/dmaengine_pcm.h12
-rw-r--r--include/sound/soc.h1
-rw-r--r--include/trace/events/cpufreq_interactive.h112
-rw-r--r--include/uapi/linux/Kbuild10
-rw-r--r--include/uapi/linux/ipu.h293
-rw-r--r--include/uapi/linux/isl29023.h47
-rw-r--r--include/uapi/linux/mxc_asrc.h126
-rw-r--r--include/uapi/linux/mxc_dcic.h47
-rw-r--r--include/uapi/linux/mxc_mlb.h55
-rw-r--r--include/uapi/linux/mxc_sim_interface.h124
-rw-r--r--include/uapi/linux/mxc_v4l2.h73
-rw-r--r--include/uapi/linux/mxcfb.h198
-rw-r--r--include/uapi/linux/pxp_device.h63
-rw-r--r--include/uapi/linux/pxp_dma.h346
-rw-r--r--include/uapi/linux/usb/ch9.h2
-rw-r--r--include/uapi/linux/videodev2.h17
-rw-r--r--include/video/mxc_edid.h107
-rw-r--r--include/video/mxc_hdmi.h1015
-rw-r--r--kernel/cpu.c20
-rw-r--r--kernel/sched/cpufreq_schedutil.c8
-rw-r--r--kernel/time/tick-sched.c21
-rw-r--r--sound/core/pcm_dmaengine.c13
-rw-r--r--sound/soc/codecs/Kconfig3
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/cs42xx8.c130
-rw-r--r--sound/soc/codecs/fsl_mqs.c228
-rw-r--r--sound/soc/codecs/sgtl5000.c19
-rw-r--r--sound/soc/codecs/si476x.c19
-rw-r--r--sound/soc/codecs/wm8960.c195
-rw-r--r--sound/soc/codecs/wm8962.c14
-rw-r--r--sound/soc/codecs/wm8994.c67
-rw-r--r--sound/soc/fsl/Kconfig134
-rw-r--r--sound/soc/fsl/Makefile28
-rw-r--r--sound/soc/fsl/fsl_asrc.c256
-rw-r--r--sound/soc/fsl/fsl_asrc.h106
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c29
-rw-r--r--sound/soc/fsl/fsl_asrc_m2m.c956
-rw-r--r--sound/soc/fsl/fsl_esai.c177
-rw-r--r--sound/soc/fsl/fsl_hdmi.c750
-rw-r--r--sound/soc/fsl/fsl_rpmsg_i2s.c259
-rw-r--r--sound/soc/fsl/fsl_rpmsg_i2s.h315
-rw-r--r--sound/soc/fsl/fsl_sai.c266
-rw-r--r--sound/soc/fsl/fsl_sai.h45
-rw-r--r--sound/soc/fsl/fsl_spdif.c121
-rw-r--r--sound/soc/fsl/fsl_ssi.c88
-rw-r--r--sound/soc/fsl/hdmi_pcm.S246
-rw-r--r--sound/soc/fsl/imx-audmux.c56
-rw-r--r--sound/soc/fsl/imx-cs42888.c410
-rw-r--r--sound/soc/fsl/imx-hdmi-dma.c1171
-rw-r--r--sound/soc/fsl/imx-hdmi.c114
-rw-r--r--sound/soc/fsl/imx-hdmi.h106
-rw-r--r--sound/soc/fsl/imx-mqs.c276
-rw-r--r--sound/soc/fsl/imx-pcm-dma-v2.c230
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c44
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c535
-rw-r--r--sound/soc/fsl/imx-pcm.h49
-rw-r--r--sound/soc/fsl/imx-rpmsg.c113
-rw-r--r--sound/soc/fsl/imx-si476x.c205
-rw-r--r--sound/soc/fsl/imx-sii902x.c276
-rw-r--r--sound/soc/fsl/imx-spdif.c2
-rw-r--r--sound/soc/fsl/imx-wm8958.c587
-rw-r--r--sound/soc/fsl/imx-wm8960.c675
-rw-r--r--sound/soc/fsl/imx-wm8962.c651
-rw-r--r--sound/soc/fsl/imx-xtor.c320
-rw-r--r--sound/soc/soc-pcm.c47
1122 files changed, 508976 insertions, 4665 deletions
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index c15aa75f5227..0cf9a6bff6a5 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -28,6 +28,7 @@ Contents:
2.3 Userspace
2.4 Ondemand
2.5 Conservative
+2.6 Interactive
3. The Governor Interface in the CPUfreq Core
@@ -218,6 +219,91 @@ a decision on when to decrease the frequency while running in any
speed. Load for frequency increase is still evaluated every
sampling rate.
+2.6 Interactive
+---------------
+
+The CPUfreq governor "interactive" is designed for latency-sensitive,
+interactive workloads. This governor sets the CPU speed depending on
+usage, similar to "ondemand" and "conservative" governors, but with a
+different set of configurable behaviors.
+
+The tunable values for this governor are:
+
+above_hispeed_delay: When speed is at or above hispeed_freq, wait for
+this long before raising speed in response to continued high load.
+The format is a single delay value, optionally followed by pairs of
+CPU speeds and the delay to use at or above those speeds. Colons can
+be used between the speeds and associated delays for readability. For
+example:
+
+ 80000 1300000:200000 1500000:40000
+
+uses delay 80000 uS until CPU speed 1.3 GHz, at which speed delay
+200000 uS is used until speed 1.5 GHz, at which speed (and above)
+delay 40000 uS is used. If speeds are specified these must appear in
+ascending order. Default is 20000 uS.
+
+boost: If non-zero, immediately boost speed of all CPUs to at least
+hispeed_freq until zero is written to this attribute. If zero, allow
+CPU speeds to drop below hispeed_freq according to load as usual.
+Default is zero.
+
+boostpulse: On each write, immediately boost speed of all CPUs to
+hispeed_freq for at least the period of time specified by
+boostpulse_duration, after which speeds are allowed to drop below
+hispeed_freq according to load as usual. Its a write-only file.
+
+boostpulse_duration: Length of time to hold CPU speed at hispeed_freq
+on a write to boostpulse, before allowing speed to drop according to
+load as usual. Default is 80000 uS.
+
+go_hispeed_load: The CPU load at which to ramp to hispeed_freq.
+Default is 99%.
+
+hispeed_freq: An intermediate "high speed" at which to initially ramp
+when CPU load hits the value specified in go_hispeed_load. If load
+stays high for the amount of time specified in above_hispeed_delay,
+then speed may be bumped higher. Default is the maximum speed allowed
+by the policy at governor initialization time.
+
+io_is_busy: If set, the governor accounts IO time as CPU busy time.
+
+min_sample_time: The minimum amount of time to spend at the current
+frequency before ramping down. Default is 80000 uS.
+
+target_loads: CPU load values used to adjust speed to influence the
+current CPU load toward that value. In general, the lower the target
+load, the more often the governor will raise CPU speeds to bring load
+below the target. The format is a single target load, optionally
+followed by pairs of CPU speeds and CPU loads to target at or above
+those speeds. Colons can be used between the speeds and associated
+target loads for readability. For example:
+
+ 85 1000000:90 1700000:99
+
+targets CPU load 85% below speed 1GHz, 90% at or above 1GHz, until
+1.7GHz and above, at which load 99% is targeted. If speeds are
+specified these must appear in ascending order. Higher target load
+values are typically specified for higher speeds, that is, target load
+values also usually appear in an ascending order. The default is
+target load 90% for all speeds.
+
+timer_rate: Sample rate for reevaluating CPU load when the CPU is not
+idle. A deferrable timer is used, such that the CPU will not be woken
+from idle to service this timer until something else needs to run.
+(The maximum time to allow deferring this timer when not running at
+minimum speed is configurable via timer_slack.) Default is 20000 uS.
+
+timer_slack: Maximum additional time to defer handling the governor
+sampling timer beyond timer_rate when running at speeds above the
+minimum. For platforms that consume additional power at idle when
+CPUs are running at speeds greater than minimum, this places an upper
+bound on how long the timer will be deferred prior to re-evaluating
+load and dropping speed. For example, if timer_rate is 20000uS and
+timer_slack is 10000uS then timers will be deferred for up to 30msec
+when not at lowest speed. A value of -1 means defer timers
+indefinitely at all speeds. Default is 80000 uS.
+
3. The Governor Interface in the CPUfreq Core
=============================================
diff --git a/Documentation/devicetree/bindings/arm/freescale/mxc_ion.txt b/Documentation/devicetree/bindings/arm/freescale/mxc_ion.txt
new file mode 100644
index 000000000000..cb3e96775284
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/freescale/mxc_ion.txt
@@ -0,0 +1,23 @@
+ION Memory Manager (ION)
+
+ION is a memory manager that allows for sharing of buffers between different
+processes and between user space and kernel space. ION manages different
+memory spaces by separating the memory spaces into "heaps".
+
+Required properties for Ion
+
+- compatible: "fsl,mxc-ion"
+
+
+All child nodes of a fsl,mxc-ion node are interpreted as Ion heap
+configurations.
+
+Required properties for Ion heaps
+
+- fsl,heap-id: The ID of the ION heap.
+
+Example:
+ imx_ion {
+ compatible = "fsl,mxc-ion";
+ fsl,heap-id = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/crypto/fsl-dcp.txt b/Documentation/devicetree/bindings/crypto/fsl-dcp.txt
index 6949e50f1f16..120792d13669 100644
--- a/Documentation/devicetree/bindings/crypto/fsl-dcp.txt
+++ b/Documentation/devicetree/bindings/crypto/fsl-dcp.txt
@@ -10,7 +10,7 @@ Required properties:
Example:
dcp@80028000 {
- compatible = "fsl,imx28-dcp", "fsl,imx23-dcp";
+ compatible = "fsl,imx6sl-dcp", "fsl,imx28-dcp", "fsl,imx23-dcp";
reg = <0x80028000 0x2000>;
interrupts = <52 53>;
status = "okay";
diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
index adeca34c5a33..f6e6fba9140b 100644
--- a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
+++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
@@ -395,6 +395,15 @@ Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC Node
value type: <u32>
Definition: LP register offset. default it is 0x34.
+ - clocks
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the source clock for
+ snvs register access. If i.MX clk driver defines the clock node,
+ it needs user to specify the clocks in device tree for all modules
+ with snvs LP/HP registers access. The modules involved snvs LP/HP
+ registers access are snvs-power key, snvs-rtc, and caam.
+
EXAMPLE
sec_mon_rtc_lp@1 {
compatible = "fsl,sec-v4.0-mon-rtc-lp";
diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt b/Documentation/devicetree/bindings/display/mxsfb.txt
index 96ec5179c8a0..99e4b1a0e256 100644
--- a/Documentation/devicetree/bindings/display/mxsfb.txt
+++ b/Documentation/devicetree/bindings/display/mxsfb.txt
@@ -7,6 +7,12 @@ Required properties:
- interrupts: Should contain lcdif interrupts
- display : phandle to display node (see below for details)
+Optional properties:
+- disp-dev: Display device driver name
+- disp-videomode: Display device video mode name; this is used if the panel
+ supports multiple video modes, in order to chose the right one (see below for
+ examples)
+
* display node
Required properties:
@@ -47,3 +53,46 @@ lcdif@80030000 {
};
};
};
+
+Examples - optional properties:
+
+Snippet from imx7d-sdb-mipi-dsi.dts:
+
+&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";
+};
+
+In the above example, the panel supports 2 video modes (snippet from
+drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c):
+
+#define ACTIVE_HIGH_NAME "TRUULY-WVGA-SYNC-HIGH"
+#define ACTIVE_LOW_NAME "TRUULY-WVGA-SYNC-LOW"
+
+static struct fb_videomode truly_lcd_modedb[] = {
+ {
+ ACTIVE_HIGH_NAME, 50, 480, 854, 41042,
+ 40, 60,
+ 3, 3,
+ 8, 4,
+ 0x0,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ }, {
+ ACTIVE_LOW_NAME, 50, 480, 854, 41042,
+ 40, 60,
+ 3, 3,
+ 8, 4,
+ FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ },
+};
diff --git a/Documentation/devicetree/bindings/dma/fsl-edma.txt b/Documentation/devicetree/bindings/dma/fsl-edma.txt
index 191d7bd8a6fe..fc4eb68f50f2 100644
--- a/Documentation/devicetree/bindings/dma/fsl-edma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-edma.txt
@@ -9,6 +9,7 @@ group, DMAMUX0 or DMAMUX1, but not both.
Required properties:
- compatible :
- "fsl,vf610-edma" for eDMA used similar to that on Vybrid vf610 SoC
+ - "nxp,imx7ulp-edma" for eDMA used similar to that on NXP i.MX7ULP SoC
- reg : Specifies base physical address(s) and size of the eDMA registers.
The 1st region is eDMA control register's address and size.
The 2nd and the 3rd regions are programmable channel multiplexing
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
index 3c9a57a8443b..ccc6c0873f63 100644
--- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
@@ -50,6 +50,7 @@ The full ID of peripheral types can be found below.
22 SSI Dual FIFO (needs firmware ver >= 2)
23 Shared ASRC
24 SAI
+ 25 HDMI Audio
The third cell specifies the transfer priority as below.
diff --git a/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt
index af0b903de293..dfc14f71e81f 100644
--- a/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt
+++ b/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt
@@ -5,7 +5,10 @@ connected to a GPIO pin.
Required properties:
- compatible: Should be "linux,extcon-usb-gpio"
+
+Either one of id-gpio or vbus-gpio must be present. Both can be present as well.
- id-gpio: gpio for USB ID pin. See gpio binding.
+- vbus-gpio: gpio for USB VBUS pin.
Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below:
extcon_usb1 {
diff --git a/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt b/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt
new file mode 100644
index 000000000000..b8d27ef108fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt
@@ -0,0 +1,105 @@
+* FSL IPUv3 Display/FB
+
+The FSL IPUv3 is Image Processing Unit version 3, a part of video and graphics
+subsystem in an application processor. The goal of the IPU is to provide
+comprehensive support for the flow of data from an image sensor or/and to a
+display device.
+
+Two IPU units are on the imx6q SOC while only one IPU unit on the imx6dl SOC.
+Each IPU unit has two display interfaces.
+
+Required properties for IPU:
+- bypass_reset :Bypass reset to avoid display channel being.
+ stopped by probe since it may start to work in bootloader: 0 or 1.
+- compatible : should be "fsl,imx6q-ipu".
+- reg : the register address range.
+- interrupts : the error and sync interrupts request.
+- clocks : the clock sources that it depends on.
+- clock-names: the related clock names.
+- resets : IPU reset specifier. See reset.txt and fsl,imx-src.txt in
+ Documentation/devicetree/bindings/reset/ for details.
+
+Required properties for fb:
+- compatible : should be "fsl,mxc_sdc_fb".
+- disp_dev : display device: "ldb", "lcd", "hdmi", "mipi_dsi".
+- mode_str : "CLAA-WVGA" for lcd, "TRULY-WVGA" for TRULY mipi_dsi lcd panel,
+ "1920x1080M@60" for hdmi.
+- default_bpp : default bits per pixel: 8/16/24/32
+- int_clk : use internal clock as pixel clock: 0 or 1
+- late_init : to avoid display channel being re-initialized
+ as we've probably setup the channel in bootloader: 0 or 1
+- interface_pix_fmt : display interface pixel format as below:
+ RGB666 IPU_PIX_FMT_RGB666
+ RGB565 IPU_PIX_FMT_RGB565
+ RGB24 IPU_PIX_FMT_RGB24
+ BGR24 IPU_PIX_FMT_BGR24
+ GBR24 IPU_PIX_FMT_GBR24
+ YUV444 IPU_PIX_FMT_YUV444
+ YUYV IPU_PIX_FMT_YUYV
+ UYVY IPU_PIX_FMT_UYVY
+ YVYV IPU_PIX_FMT_YVYU
+ VYUY IPU_PIX_FMT_VYUY
+
+Required properties for display:
+- compatible : should be "fsl,lcd" for lcd panel
+- reg : the register address range if necessary to have.
+- interrupts : the error and sync interrupts if necessary to have.
+- clocks : the clock sources that it depends on if necessary to have.
+- clock-names: the related clock names if necessary to have.
+- ipu_id : ipu id for the first display device: 0 or 1
+- disp_id : display interface id for the first display interface: 0 or 1
+- default_ifmt : save as above display interface pixel format for lcd
+- pinctrl-names : should be "default"
+- pinctrl-0 : should be pinctrl_ipu1_1 or pinctrl_ipu2_1, which depends on the
+ IPU connected.
+- gpr : the mux controller for the display engine's display interfaces and the display encoder
+ (only valid for mipi dsi now).
+- disp-power-on-supply : the regulator to control display panel's power.
+ (only valid for mipi dsi now).
+- resets : the gpio pin to reset the display device(only valid for mipi display panel now).
+- lcd_panel : the video mode name for the display device(only valid for mipi display panel now).
+- dev_id : the display engine's identity within the system, which intends to replace ipu_id
+ (only valid for mipi dsi now).
+
+Example for IPU:
+ ipu1: ipu@02400000 {
+ compatible = "fsl,imx6q-ipu";
+ reg = <0x02400000 0x400000>;
+ interrupts = <0 6 0x4 0 5 0x4>;
+ clocks = <&clks 130>, <&clks 131>, <&clks 132>,
+ <&clks 39>, <&clks 40>,
+ <&clks 135>, <&clks 136>;
+ clock-names = "bus", "di0", "di1",
+ "di0_sel", "di1_sel",
+ "ldb_di0", "ldb_di1";
+ resets = <&src 2>;
+ bypass_reset = <0>;
+ };
+
+Example for fb:
+ fb0 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "ldb";
+ interface_pix_fmt = "RGB666";
+ mode_str ="LDB-XGA";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "okay";
+ };
+
+Example for mipi dsi display:
+ mipi_dsi: mipi@021e0000 {
+ compatible = "fsl,imx6q-mipi-dsi";
+ reg = <0x021e0000 0x4000>;
+ interrupts = <0 102 0x04>;
+ gpr = <&gpr>;
+ clocks = <&clks 138>, <&clks 204>;
+ clock-names = "mipi_pllref_clk", "mipi_cfg_clk";
+ dev_id = <0>;
+ disp_id = <0>;
+ lcd_panel = "TRULY-WVGA";
+ disp-power-on-supply = <&reg_mipi_dsi_pwr_on>
+ resets = <&mipi_dsi_reset>;
+ status = "okay";
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-imx-rpmsg.txt b/Documentation/devicetree/bindings/gpio/gpio-imx-rpmsg.txt
new file mode 100644
index 000000000000..49c7d321e2bf
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-imx-rpmsg.txt
@@ -0,0 +1,38 @@
+Device-Tree bindings for drivers/gpio/gpio-imx-rpmsg.c gpio driver over
+rpmsg. On i.mx7ULP PTA PTB are connected on M4 side, so rpmsg gpio driver
+needed to get/set gpio status from M4 side by rpmsg.
+
+Required properties:
+- compatible : Should be "fsl,imx-rpmsg-gpio".
+- port_idx : Specify the GPIO PORT index, PTA:0, PTB:1.
+- gpio-controller : Mark the device node as a gpio controller.
+- #gpio-cells : Should be two. The first cell is the pin number and
+ the second cell is used to specify the gpio polarity:
+ 0 = active high
+ 1 = active low
+
+Note: Each GPIO port should have an alias correctly numbered in "aliases"
+node.
+
+Examples:
+
+aliases {
+ gpio4 = &rpmsg_gpio0;
+ gpio5 = &rpmsg_gpio1;
+};
+
+rpmsg_gpio0: rpmsg-gpio0 {
+ compatible = "fsl,imx-rpmsg-gpio";
+ port_idx = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ status = "okay";
+};
+
+rpmsg_gpio1: rpmsg-gpio1 {
+ compatible = "fsl,imx-rpmsg-gpio";
+ port_idx = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ status = "okay";
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt
new file mode 100644
index 000000000000..1710abcdfa9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt
@@ -0,0 +1,23 @@
+* Freescale Low Power Inter IC (LPI2C) for i.MX
+
+Required properties:
+- compatible :
+ - "fsl,imx7ulp-lpi2c" for LPI2C compatible with the one integrated on i.MX7ULP soc
+- reg : address and length of the lpi2c master registers
+- interrupt-parent : core interrupt controller
+- interrupts : lpi2c interrupt
+- clocks : lpi2c clock specifier
+
+Examples:
+
+lpi2c4: lpi2c4@402B0000 {
+ compatible = "fsl,imx7ulp-lpi2c";
+ reg = <0x402B0000 0x10000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPI2C4>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPI2C4>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index fbbad6446741..8877fa6a3df1 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -42,6 +42,8 @@ domintech,dmard09 DMARD09: 3-axis Accelerometer
epson,rx8010 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
epson,rx8025 High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE
epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
+fsl,fxas2100x FXAS2100X: Gyroscope sensor
+fsl,fxos8700 FXOS8700: Accelerometer + Magnetometer Combo
fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
diff --git a/Documentation/devicetree/bindings/input/rpmsg-keys.txt b/Documentation/devicetree/bindings/input/rpmsg-keys.txt
new file mode 100644
index 000000000000..d9279802cc9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/rpmsg-keys.txt
@@ -0,0 +1,33 @@
+Device-Tree bindings for input/keyboard/rpmsg-keys.c keys driver over
+rpmsg. On i.mx7ULP keys are connected on M4 side, so rpmsg-keys driver
+needed to get the key status from M4 side by rpmsg.
+
+Required properties:
+ - compatible = "fsl,rpmsg-keys";
+
+Each button/key looked as the sub node:
+Required properties:
+ - label: the key name
+ - linux,code: the key value defined in
+ include/dt-bindings/input/input.h
+Optional property:
+ - rpmsg-key,wakeup: wakeup feature, the keys can wakeup from
+ suspend if the keys with this property pressed.
+
+Example nodes:
+ rpmsg_keys: rpmsg-keys {
+ compatible = "fsl,rpmsg-keys";
+
+ volume-up {
+ label = "Volume Up";
+ rpmsg-key,wakeup;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ rpmsg-key,wakeup;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/input/touchscreen/focaltech-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/focaltech-ts.txt
new file mode 100644
index 000000000000..8e5257db88f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/focaltech-ts.txt
@@ -0,0 +1,48 @@
+FocalTech touch controller
+
+The focaltech controller is connected to host processor via i2c.
+The controller generates interrupts when the user touches the panel.
+The host controller is expected to read the touch coordinates over
+i2c and pass the coordinates to the rest of the system.
+
+Required properties:
+ - compatible : should be "focaltech,fts"
+ - reg : i2c slave address of the device, should be <0x38>
+ - interrupt-parent : parent of interrupt
+ - interrupts : irq gpio, "0x02" stands for that the irq triggered by falling edge.
+ - focaltech,irq-gpio : irq gpio, same as "interrupts" node.
+ - focaltech,reset-gpio : reset gpio
+ - focaltech,num-max-touches : maximum number of touches support
+ - focaltech,display-coords : display resolution in pixels. A four tuple consisting of minX, minY, maxX and maxY.
+
+Optional properties:
+ - focaltech,have-key : specify if virtual keys are supported
+ - focaltech,key-number : number of keys
+ - focaltech,keys : virtual key codes mapping to the coords
+ - focaltech,key-y-coord : constant y coordinate of keys, depends on the y resolution
+ - focaltech,key-x-coords : constant x coordinates of keys, depends on the x resolution
+ - focaltech,swap-xy : swap x-y coordinates
+ - focaltech,panel-type : set panel type, default is FT5416 panel
+ - focaltech,scaling-down-half : scale down the x-y coordiantes to half
+
+
+Example:
+ i2c@f9927000 {
+ focaltech@38{
+ compatible = "focaltech,fts";
+ reg = <0x38>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <13 0x02>;
+ focaltech,reset-gpio = <&msm_gpio 12 0x01>;
+ focaltech,irq-gpio = <&msm_gpio 13 0x02>;
+ focaltech,max-touch-number = <5>;
+ focaltech,display-coords = <0 0 1080 1920>;
+
+ focaltech,have-key;
+ focaltech,key-number = <3>;
+ focaltech,keys = <139 102 158>;
+ focaltech,key-y-coord = <2000>;
+ focaltech,key-x-coords = <200 600 800>;
+ focaltech,swap-xy;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/vtl_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/vtl_ts.txt
new file mode 100644
index 000000000000..a41a0b993006
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/vtl_ts.txt
@@ -0,0 +1,18 @@
+* VTL Touchscreen Controller
+
+Required properties:
+- compatible: must be "vtl,ct365"
+- reg: i2c slave address
+- interrupt-parent: the phandle for the interrupt controller
+- interrupts: touch controller interrupt
+- gpios: the gpio pin to be used for reset
+
+Example:
+
+ touchscreen@01 {
+ compatible = "vtl,ct365";
+ reg = <0x01>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <14 0>;
+ gpios = <&gpio4 10 0>;
+ };
diff --git a/Documentation/devicetree/bindings/mfd/syscon.txt b/Documentation/devicetree/bindings/mfd/syscon.txt
index 408f768686f1..a438909b5cc6 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.txt
+++ b/Documentation/devicetree/bindings/mfd/syscon.txt
@@ -13,9 +13,10 @@ Required properties:
- compatible: Should contain "syscon".
- reg: the register region can be accessed from syscon
-Optional property:
+Optional properties:
- reg-io-width: the size (in bytes) of the IO accesses that should be
performed on the device.
+- clocks: clock used for accessing the regmap
Examples:
gpr: iomuxc-gpr@020e0000 {
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
index 3e29050ec769..de3270b0aec0 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
@@ -35,6 +35,8 @@ Optional properties:
This property allows user to change the tuning step to more than one delay
cells which is useful for some special boards or cards when the default
tuning step can't find the proper delay window within limited tuning retries.
+- wifi-host : assigned as a wifi host.
+ This is required for Broadcom BCM WiFi cards to do card detect
Examples:
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 8a377827695b..e654b5077117 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -12,6 +12,8 @@ Only one of the properties in this section should be supplied:
- broken-cd: There is no card detection available; polling must be used.
- cd-gpios: Specify GPIOs for card detection, see gpio binding
- non-removable: non-removable slot (like eMMC); assume always present.
+ - cd-post: postone card detect from start host for non-removable cards
+ and let client driver to start it when ready
Optional properties:
- bus-width: Number of data lines, can be <1>, <4>, or <8>. The default
@@ -74,6 +76,9 @@ Optional SDIO properties:
- keep-power-in-suspend: Preserves card power during a suspend/resume cycle
- wakeup-source: Enables wake up of host system on SDIO IRQ assertion
(Legacy property supported: "enable-sdio-wakeup")
+- pm-ignore-notify: Ignore mmc PM notify. This will prevent MMC core automatically
+ to re-detect cards after sysem resume back.
+
MMC power
---------
diff --git a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt
index c34aa6f8a424..951655466a11 100644
--- a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt
+++ b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt
@@ -1,5 +1,11 @@
* Freescale Quad Serial Peripheral Interface(QuadSPI)
+The QuadSPI controller acts as the SPI master. It is described with a node
+for the controller and a set of child nodes for each SPI NOR flash.
+
+Part I - The DT node for the controller:
+------------------------------
+
Required properties:
- compatible : Should be "fsl,vf610-qspi", "fsl,imx6sx-qspi",
"fsl,imx7d-qspi", "fsl,imx6ul-qspi",
@@ -24,6 +30,16 @@ Optional properties:
(Please check the board's schematic.)
- big-endian : That means the IP register is big endian
+Part II - The DT nodes for each SPI NOR flash
+------------------------------
+Required properties:
+- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
+
+Optional properties:
+ Please refer to the Documentation/devicetree/bindings/mtd/spi-nor-flash.txt
+ If you set the "spi-nor,ddr-quad-read-dummy", it means you enable the DDR
+ quad read feature for the driver.
+
Example:
qspi0: quadspi@40044000 {
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
index d02acaff3c35..2b7133639fd8 100644
--- a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
@@ -4,7 +4,8 @@ The GPMI nand controller provides an interface to control the
NAND flash chips.
Required properties:
- - compatible : should be "fsl,<chip>-gpmi-nand"
+ - compatible : should be "fsl,<chip>-gpmi-nand", the chip should be imx23,
+ imx28, imx6q, imx6qp, imx6sx, imx6ul, imx7d or imx6ull.
- reg : should contain registers location and length for gpmi and bch.
- reg-names: Should contain the reg names "gpmi-nand" and "bch"
- interrupts : BCH interrupt number.
@@ -35,6 +36,10 @@ Optional properties:
partitions written from Linux with this feature
turned on may not be accessible by the BootROM
code.
+ - fsl,legacy-bch-geometry: Use legacy bch geometry(ECC scheme) that
+ compatible with 3.10 kernel. Without the property,
+ software may use ECC strength according to NAND chip
+ spec, e.g. ONFI standard.
The device tree may optionally contain sub-nodes describing partitions of the
address space. See partition.txt for more detail.
diff --git a/Documentation/devicetree/bindings/mtd/spi-nor-flash.txt b/Documentation/devicetree/bindings/mtd/spi-nor-flash.txt
new file mode 100644
index 000000000000..aba4d54233d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/spi-nor-flash.txt
@@ -0,0 +1,7 @@
+This file defines some DT properties for specific SPI NOR flash features.
+The SPI NOR controller drivers may refer to this file, such as fsl-quadspi.txt
+
+Optional properties:
+ - spi-nor,ddr-quad-read-dummy: The dummy cycles used by the DDR Quad read.
+ Please refer to the chip's datasheet. This
+ property can be 4 or 6 which is less then 8.
diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
index 56d6cc336e1c..00ff7d6c9f64 100644
--- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
+++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
@@ -17,6 +17,16 @@ Optional properties:
- clock-frequency : The oscillator frequency driving the flexcan device
- xceiver-supply: Regulator that powers the CAN transceiver
+- stop-mode: register bits of stop mode control, the format is
+ <&gpr req_gpr req_bit ack_gpr ack_bit>.
+ gpr is the phandle to general purpose register node.
+ req_gpr is the gpr register offset of CAN stop request.
+ req_bit is the bit offset of CAN stop request.
+ ack_gpr is the gpr register offset of CAN stop acknowledge.
+ ack_bit is the bit offset of CAN stop acknowledge.
+- trx_en_gpio : enable gpio
+- trx_stby_gpio : standby gpio
+- trx_nerr_gpio : NERR gpio
Example:
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index a1e3693cca16..555731a9eece 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -5,6 +5,13 @@ Required properties:
- reg : Address and length of the register set for the device
- interrupts : Should contain fec interrupt
- phy-mode : See ethernet.txt file in the same directory
+- clock-name: Should be the names of the clocks
+ - "ipg" for MAC ipg_clk_s, ipg_clk_mac_s that are for register accessing
+ - "ahb" for MAC ipg_clk, ipg_clk_mac that are bus clock
+ - "ptp" for IEEE1588 timer clock
+ - "enet_clk_ref" for MAC transmit/receiver reference clock
+ - "enet_out" output clock for external device
+- clocks: Phandles to input clocks.
Optional properties:
- phy-reset-gpios : Should specify the gpio for phy reset
@@ -30,6 +37,12 @@ Optional properties:
- fsl,err006687-workaround-present: If present indicates that the system has
the hardware workaround for ERR006687 applied and does not need a software
workaround.
+- fsl,wakeup_irq : The property define the wakeup irq index in enet irq source.
+- stop-mode : If present, indicates soc need to set gpr bit to request stop
+ mode.
+- fsl,ar8031-phy-fixup : If present, indicates board need to do phy fixup setting.
+- mii-exclusive: If present, each MAC has their exclusive MDIO bus in current board
+ design, otherwise mutiple MACs share one MDIO bus to reduce Pins utilize.
Optional subnodes:
- mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
index 83aeb1f5a645..1f8db0b1ecef 100644
--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
@@ -12,6 +12,7 @@ Required properties:
- "msi": The interrupt that is asserted when an MSI is received
- clock-names: Must include the following additional entries:
- "pcie_phy"
+- ext_osc: use the external oscillator or not.
Optional properties:
- fsl,tx-deemph-gen1: Gen1 De-emphasis value. Default: 0
diff --git a/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt b/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt
index 1d25b04cd05e..415dc0d05805 100644
--- a/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt
@@ -7,6 +7,8 @@ Required properties:
* "fsl,imx6sl-usbphy" for imx6sl
* "fsl,vf610-usbphy" for Vybrid vf610
* "fsl,imx6sx-usbphy" for imx6sx
+ * "fsl,imx6ul-usbphy" for imx6ul
+ * "fsl,imx7ulp-usbphy" for imx7ulp
"fsl,imx23-usbphy" is still a fallback for other strings
- reg: Should contain registers location and length
- interrupts: Should contain phy interrupt
@@ -21,6 +23,9 @@ Optional properties:
that terminates the DP output signal. Default: 45
- fsl,tx-d-cal: Integer [79-119]. Current trimming value (as a percentage) of
the 17.78mA TX reference current. Default: 100
+- tx-d-cal: Try to adjust this value to improve signal quality, and pass
+ USB Certification, the value is from 0x0 to 0xf, and the register offset
+ is 0x10 (USBPHY_TX).
Example:
usbphy1: usbphy@020c9000 {
@@ -28,4 +33,5 @@ usbphy1: usbphy@020c9000 {
reg = <0x020c9000 0x1000>;
interrupts = <0 44 0x04>;
fsl,anatop = <&anatop>;
+ tx-d-cal = <0x5>;
};
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx7ulp-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx7ulp-pinctrl.txt
new file mode 100644
index 000000000000..541aead62607
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx7ulp-pinctrl.txt
@@ -0,0 +1,33 @@
+* Freescale i.MX7ULP IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
+and usage.
+
+Required properties:
+- compatible: "fsl,imx7ulp-iomuxc-0" or "fsl,imx7ulp-iomuxc-1"
+- fsl,pins: two integers array, represents a group of pins mux and config
+ setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
+ pin working on a specific function, CONFIG is the pad setting value like
+ pull-up for this pin. Please refer to imx7ulp datasheet for the valid pad
+ config settings.
+
+NOTE: i.MX7ULP PIN_FUNC_ID consists of 4 integers as it shares one mux and
+config register as follows:
+<mux_conf_reg input_reg mux_mode input_val>
+
+CONFIG bits definition:
+PAD_CTL_OBE (1 << 17)
+PAD_CTL_IBE (1 << 16)
+PAD_CTL_LK (1 << 15)
+PAD_CTL_DSE_HIGH (1 << 6)
+PAD_CTL_DSE_STD (0 << 6)
+PAD_CTL_ODE_OPEN_DRAIN (1 << 5)
+PAD_CTL_ODE_PUSH_PULL (0 << 5)
+PAD_CTL_SRE_SLOW (1 << 2)
+PAD_CTL_SRE_STD (0 << 2)
+PAD_CTL_PE_PULL (1 << 1)
+PAD_CTL_PS_UP (1 << 0)
+PAD_CTL_PS_DOWN (0 << 0)
+
+Refer to imx7ulp-pinfunc.h in device tree source folder for all available
+imx7ulp PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
index b73c96d24f59..05ede5f4509a 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -71,6 +71,13 @@ pinctrl-names: The list of names to assign states. List entry 0 defines the
name for integer state ID 0, list entry 1 for state ID 1, and
so on.
+pinctrl-assert-gpios:
+ List of phandles, each pointing at a GPIO which is used by some
+ board design to steer pins between two peripherals on the board.
+ It plays like a board level pin multiplexer to choose different
+ functions for given pins by pulling up/down the GPIOs. See
+ bindings/gpio/gpio.txt for details of how to specify GPIO.
+
For example:
/* For a client device requiring named states */
diff --git a/Documentation/devicetree/bindings/pwm/nxp,tpm-pwm.txt b/Documentation/devicetree/bindings/pwm/nxp,tpm-pwm.txt
new file mode 100644
index 000000000000..ac445a7ceb93
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/nxp,tpm-pwm.txt
@@ -0,0 +1,18 @@
+NXP TPM PWM controller
+
+Required properties:
+- compatible: should be "nxp,tpm-pwm"
+- reg: physical base address and length of the controller's registers
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
+- nxp,pwm-number: the number of PWM devices
+
+Example:
+
+pwm0: tpm@40250000 {
+ compatible = "nxp,tpm-pwm";
+ reg = <0x40250000 0x1000>;
+ nxp,pwm-number = <6>;
+ #pwm-cells = <2>;
+};
+
diff --git a/Documentation/devicetree/bindings/regulator/anatop-regulator.txt b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
index 37c4ea076f88..03ea26d9ccba 100644
--- a/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
@@ -14,6 +14,7 @@ Optional properties:
- anatop-delay-bit-shift: Bit shift for the step time register
- anatop-delay-bit-width: Number of bits used in the step time register
- vin-supply: The supply for this regulator
+- anatop-enable-bit: Regulator output offset bit, only for 3p0, 2p5, and 1p1.
Any property defined as part of the core regulator
binding, defined in regulator.txt, can also be used.
@@ -35,4 +36,5 @@ Example:
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1300000>;
+ anatop-enable-bit = <0>;
};
diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.txt b/Documentation/devicetree/bindings/regulator/pfuze100.txt
index 9b40db88f637..997174a46518 100644
--- a/Documentation/devicetree/bindings/regulator/pfuze100.txt
+++ b/Documentation/devicetree/bindings/regulator/pfuze100.txt
@@ -3,6 +3,8 @@ PFUZE100 family of regulators
Required properties:
- compatible: "fsl,pfuze100", "fsl,pfuze200", "fsl,pfuze3000"
- reg: I2C slave address
+- fsl,lpsr-mode: some registers need to be saved and restored in lpsr mode
+ for pfuze3000
Required child node:
- regulators: This is the list of child nodes that specify the regulator
diff --git a/Documentation/devicetree/bindings/reset/gpio-reset.txt b/Documentation/devicetree/bindings/reset/gpio-reset.txt
new file mode 100644
index 000000000000..bca5348a5131
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/gpio-reset.txt
@@ -0,0 +1,35 @@
+GPIO reset controller
+=====================
+
+A GPIO reset controller controls a single GPIO that is connected to the reset
+pin of a peripheral IC. Please also refer to reset.txt in this directory for
+common reset controller binding usage.
+
+Required properties:
+- compatible: Should be "gpio-reset"
+- reset-gpios: A gpio used as reset line. The gpio specifier for this property
+ depends on the gpio controller that provides the gpio.
+- #reset-cells: 0, see below
+
+Optional properties:
+- reset-delay-us: delay in microseconds. The gpio reset line will be asserted for
+ this duration to reset.
+- initially-in-reset: boolean. If not set, the initial state should be a
+ deasserted reset line. If this property exists, the
+ reset line should be kept in reset.
+
+example:
+
+sii902x_reset: gpio-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <10000>;
+ initially-in-reset;
+ #reset-cells = <0>;
+};
+
+/* Device with nRESET pin connected to GPIO5_0 */
+sii902x@39 {
+ /* ... */
+ resets = <&sii902x_reset>; /* active-low GPIO5_0, 10 ms delay */
+};
diff --git a/Documentation/devicetree/bindings/rpmsg/imx-rpmsg.txt b/Documentation/devicetree/bindings/rpmsg/imx-rpmsg.txt
new file mode 100644
index 000000000000..27d710274ec3
--- /dev/null
+++ b/Documentation/devicetree/bindings/rpmsg/imx-rpmsg.txt
@@ -0,0 +1,19 @@
+i.MX RPMSG platform implementations
+
+Required properties:
+- compatible : "fsl,imx7d-rpmsg", "fsl,imx6sx-rpmsg"
+- vdev-nums : The number of the remote virtual devices.
+- reg : The reserved DDR phisical memory used to store
+ vring descriptors.
+
+Example:
+rpmsg: rpmsg{
+ compatible = "fsl,imx6sx-rpmsg";
+ status = "disabled";
+};
+
+&rpmsg{
+ vdev-nums = <1>;
+ reg = <0xbfff0000 0x10000>;
+ status = "okay";
+};
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
index c95005efbcb8..4450498ec5ab 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
@@ -6,14 +6,21 @@ Required properties:
on Vybrid vf610 SoC with 8-bit register organization
- "fsl,ls1021a-lpuart" for lpuart compatible with the one integrated
on LS1021A SoC with 32-bit big-endian register organization
+ - "fsl,imx7ulp-lpuart" for lpuart compatible with the one integrated
+ on i.MX7ULP SoC with 32-bit little-endian register organization
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
- clocks : phandle + clock specifier pairs, one for each entry in clock-names
-- clock-names : should contain: "ipg" - the uart clock
+- clock-names : should contain: "ipg" - the uart peripheral register accessing
+ clock source, if "per" clock missing, the "ipg" clock also is the uart module
+ clock.
Optional properties:
- dmas: A list of two dma specifiers, one for each entry in dma-names.
- dma-names: should contain "tx" and "rx".
+- clocks : phandle + clock specifier pairs, one for each entry in clock-names
+- clock-names : "per" - the uart module clock.
+ clock.
Note: Optional properties for DMA support. Write them both or both not.
diff --git a/Documentation/devicetree/bindings/soc/fsl/gpc.txt b/Documentation/devicetree/bindings/soc/fsl/gpc.txt
new file mode 100644
index 000000000000..a7d29282f8e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/fsl/gpc.txt
@@ -0,0 +1,56 @@
+* General Power Controller (GPC)
+-------------------------------------------
+The General Power Controller (GPC) module controls the following functions:
+ - Provide low power mode control for A7 and M4 platform
+ - Provide Power domain management all ARM and SOC power domain
+ - Provide domain control mechanism based on A7 and M4 CPU domain
+ - Provide handshake with CCM for clock management in low power mode
+ - Provide handshake with SRC for power down and power up sequence
+ - Provide handshake with Analog for Deep Sleep Mode control
+
+Required properties:
+ - reg : Offset and length of the register set of the GPC block.
+ - compatible : Must contain a chip-specific GPC block compatible string
+ and (if applicable) may contain a chassis-version GPC compatible
+ string. Chip-specific strings are of the form "fsl,<chip>-gpc",
+ such as:
+ * "fsl,imx7d-gpc"
+ * "fsl,imx7s-gpc"
+ - interrupt-controller : Specifies that this is an interrupt controller
+
+Example:
+The GPC node for imx7d:
+ gpc: gpc@303a0000 {
+ compatible = "fsl,imx7d-gpc";
+ reg = <0x303a0000 0x1000>;
+ interrupt-controller;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ fsl,mf-mix-wakeup-irq = <0x54010000 0xc00 0x0 0x1040640>;
+ };
+
+* Power Gating Controller (PGC)
+-------------------------------------------
+The Power Gating Controller (PGC) is a power management component that controls the
+power-down and power-up sequencing of individual subsystems.
+The PGC block is found inside GPC, and share the same register.
+
+Required properties:
+ - compatible : Must contain a chip-specific PGC block compatible string
+ and (if applicable) may contain a chassis-version PGC compatible
+ string. Chip-specific strings are of the form "fsl,<chip>-pgc",
+ such as:
+ * "fsl,imx7d-pgc"
+ * "fsl,imx7s-pgc"
+ - *-supply : Specifies the regulators that can be managed by this PGC. For exampe:
+ * "mipi-phy-supply = <&reg_1p0d>;"
+
+Example:
+The PGC node for imx7d:
+ pgc {
+ compatible = "fsl,imx7d-pgc";
+ mipi-phy-supply = <&reg_1p0d>;
+ pcie-phy-supply = <&reg_1p0d>;
+ vcc-supply = <&reg_1p2>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt
index cd3ee5d84f03..733c0a633c13 100644
--- a/Documentation/devicetree/bindings/sound/fsl,esai.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt
@@ -46,6 +46,10 @@ Required properties:
will be in use as default, or the big endian mode
will be in use for all the device registers.
+ - fsl,dma-buffer-size: It specify the audio buffer size of playback and
+ capture. If this property is absent, using the default value of audio buffer
+ size.
+
Example:
esai: esai@02024000 {
diff --git a/Documentation/devicetree/bindings/sound/fsl,mqs.txt b/Documentation/devicetree/bindings/sound/fsl,mqs.txt
new file mode 100644
index 000000000000..7c288461e9ce
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,mqs.txt
@@ -0,0 +1,22 @@
+fsl,mqs audio CODEC
+
+Required properties:
+
+ - compatible : must contain one of "fsl,imx6sx-mqs" and "fsl,codec-mqs"
+
+ - clocks : a list of phandles + clock-specifiers, one for each entry in
+ clock-names
+
+ - clock-names : must contain "mclk"
+
+ - gpr : the gpr node.
+
+Example:
+
+mqs: mqs {
+ compatible = "fsl,imx6sx-mqs";
+ gpr = <&gpr>;
+ clocks = <&clks IMX6SX_CLK_SAI1>;
+ clock-names = "mclk";
+ status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt b/Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt
new file mode 100644
index 000000000000..f38cf9d90500
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt
@@ -0,0 +1,20 @@
+Freescale rpmsg i2s interface.
+
+The rpmsg i2s is based on RPMSG that used communicating with M4 core,
+which provides a synchronous audio interface that supports fullduplex
+serial interfaces with frame synchronization such as I2S.
+
+Required properties:
+
+ - compatible : Compatible list, contains "fsl,imx7ulp-rpmsg-i2s".
+
+ - fsl,audioindex : This is an index indicating the audio device index in
+ the M4 side.
+
+Example:
+rpmsg_i2s: rpmsg-i2s {
+ compatible = "fsl,imx7ulp-rpmsg-i2s";
+ /* the audio device index in m4 domain */
+ fsl,audioindex = <0> ;
+ status = "okay";
+};
diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
index 4ca39ddc0417..58b966b7a2af 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
@@ -37,6 +37,10 @@ Required properties:
will be in use as default, or the big endian mode
will be in use for all the device registers.
+ - fsl,dma-buffer-size: It specify the audio buffer size of playback and
+ capture. If this property is absent, using the default value of audio buffer
+ size.
+
Example:
spdif: spdif@02004000 {
diff --git a/Documentation/devicetree/bindings/sound/fsl,ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt
index 5b76be45d18b..3ad10966d3a5 100644
--- a/Documentation/devicetree/bindings/sound/fsl,ssi.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,ssi.txt
@@ -62,6 +62,10 @@ Optional properties:
"ac97-slave" - AC97 mode, SSI is clock slave
"ac97-master" - AC97 mode, SSI is clock master
+- fsl,dma-buffer-size: It specify the audio buffer size of playback and
+ capture. If this property is absent, using the default value of audio buffer
+ size.
+
Child 'codec' node required properties:
- compatible: Compatible list, contains the name of the codec
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt b/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt
new file mode 100644
index 000000000000..af746c4c81df
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt
@@ -0,0 +1,25 @@
+Freescale i.MX audio complex with CS42888 codec
+
+Required properties:
+- compatible : "fsl,imx-audio-cs42888"
+- model : The user-visible name of this sound complex
+- esai-controller : The phandle of the i.MX SSI controller
+- audio-codec : The phandle of the CS42888 audio codec
+
+Optional properties:
+- asrc-controller : The phandle of the i.MX ASRC controller
+- audio-routing : A list of the connections between audio components.
+ Each entry is a pair of strings, the first being the connection's sink,
+ the second being the connection's source. Valid names could be power
+ supplies, CS42888 pins, and the jacks on the board:
+
+Example:
+
+sound {
+ compatible = "fsl,imx6q-sabresd-wm8962",
+ "fsl,imx-audio-wm8962";
+ model = "cs42888-audio";
+ esai-controller = <&esai>;
+ asrc-controller = <&asrc_p2p>;
+ audio-codec = <&codec>;
+};
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-mqs.txt b/Documentation/devicetree/bindings/sound/imx-audio-mqs.txt
new file mode 100644
index 000000000000..1d42bd03d5c7
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-mqs.txt
@@ -0,0 +1,18 @@
+Freescale i.MX audio complex with mqs codec
+
+Required properties:
+- compatible : "fsl,imx-audio-mqs"
+- model : The user-visible name of this sound complex
+- cpu-dai : The phandle of the i.MX sai controller
+- audio-codec : The phandle of the mqs audio codec
+
+Example:
+
+sound-mqs {
+ compatible = "fsl,imx6sx-sdb-mqs",
+ "fsl,imx-audio-mqs";
+ model = "mqs-audio";
+ cpu-dai = <&sai1>;
+ audio-codec = <&mqs>;
+};
+
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.txt b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.txt
new file mode 100644
index 000000000000..3f015974ffeb
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-rpmsg.txt
@@ -0,0 +1,13 @@
+Freescale i.MX audio complex with rpmsg devices
+
+Required properties:
+- compatible : "fsl,imx-audio-rpmsg"
+- model : The user-visible name of this sound complex
+- cpu-dai : The phandle of the i.MX rpmsg i2s device.
+
+Example:
+sound-rpmsg {
+ compatible = "fsl,imx-audio-rpmsg";
+ model = "rpmsg-audio";
+ cpu-dai = <&rpmsg_i2s>;
+};
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-si476x.txt b/Documentation/devicetree/bindings/sound/imx-audio-si476x.txt
new file mode 100644
index 000000000000..53cd34afe6b8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-si476x.txt
@@ -0,0 +1,24 @@
+Freescale i.MX audio complex with si476x codec
+
+Required properties:
+- compatible : "fsl,imx-audio-si476x"
+- model : The user-visible name of this sound complex
+- ssi-controller : The phandle of the i.MX SSI controller
+
+- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
+- mux-ext-port : The external port of the i.MX audio muxer
+
+Note: The AUDMUX port numbering should start at 1, which is consistent with
+hardware manual.
+
+Example:
+
+sound {
+ compatible = "fsl,imx-audio-si476x",
+ "fsl,imx-tuner-si476x";
+ model = "imx-radio-si476x";
+
+ ssi-controller = <&ssi1>;
+ mux-int-port = <2>;
+ mux-ext-port = <5>;
+};
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt b/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt
index acea71bee34f..06bc12d4cc76 100644
--- a/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt
+++ b/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt
@@ -6,7 +6,7 @@ Required properties:
- model : The user-visible name of this sound complex
- - ssi-controller : The phandle of the i.MX SSI controller
+ - cpu-dai : The phandle of CPU DAI
- audio-codec : The phandle of the WM8962 audio codec
@@ -31,13 +31,19 @@ Required properties:
Note: The AUDMUX port numbering should start at 1, which is consistent with
hardware manual.
+Optional properties:
+- hp-det-gpios : The gpio pin to detect plug in/out event that happens to
+ Headphone jack.
+- mic-det-gpios: The gpio pin to detect plug in/out event that happens to
+ Microphone jack.
+
Example:
sound {
compatible = "fsl,imx6q-sabresd-wm8962",
"fsl,imx-audio-wm8962";
model = "wm8962-audio";
- ssi-controller = <&ssi2>;
+ cpu-dai = <&ssi2>;
audio-codec = <&codec>;
audio-routing =
"Headphone Jack", "HPOUTL",
@@ -50,4 +56,6 @@ sound {
"DMICDAT", "DMIC";
mux-int-port = <2>;
mux-ext-port = <3>;
+ hp-det-gpios = <&gpio7 8 1>;
+ mic-det-gpios = <&gpio1 9 1>;
};
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-xtor.txt b/Documentation/devicetree/bindings/sound/imx-audio-xtor.txt
new file mode 100644
index 000000000000..ed55891bca96
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-xtor.txt
@@ -0,0 +1,30 @@
+Freescale i.MX audio complex with Freescale DAI transceiver.
+Currently supports Freescale SAI or ESAI digital audio interface.
+
+Required properties:
+
+ - compatible : "fsl,imx-audio-xtor"
+
+ - model : The user-visible name of this sound complex
+
+ - cpu-dai : The phandle of the i.MX DAI, currently supports
+ SAI or ESAI controller
+
+Optional properties:
+
+ - asrc-controller : The phandle of the i.MX ASRC controller associated with DAI.
+
+Examples:
+
+sound-xtor-sai {
+ compatible = "fsl,imx-audio-xtor";
+ model = "xtor-audio-sai";
+ cpu-dai = <&sai0>;
+ asrc-controller = <&asrc0>;
+};
+
+sound-xtor-esai {
+ compatible = "fsl,imx-audio-xtor";
+ model = "xtor-audio-esai";
+ cpu-dai = <&esai0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.txt b/Documentation/devicetree/bindings/sound/sgtl5000.txt
index 5666da7b8605..7a73a9d62015 100644
--- a/Documentation/devicetree/bindings/sound/sgtl5000.txt
+++ b/Documentation/devicetree/bindings/sound/sgtl5000.txt
@@ -26,6 +26,15 @@ Optional properties:
If this node is not mentioned or the value is unknown, then
the value is set to 1.25V.
+- lrclk-strength: the LRCLK pad strength. Possible values are:
+0, 1, 2 and 3 as per the table below:
+
+VDDIO 1.8V 2.5V 3.3V
+0 = Disable
+1 = 1.66 mA 2.87 mA 4.02 mA
+2 = 3.33 mA 5.74 mA 8.03 mA
+3 = 4.99 mA 8.61 mA 12.05 mA
+
Example:
codec: sgtl5000@0a {
diff --git a/Documentation/devicetree/bindings/sound/wm8962.txt b/Documentation/devicetree/bindings/sound/wm8962.txt
index 7f82b59ec8f9..d15b9c82fd15 100644
--- a/Documentation/devicetree/bindings/sound/wm8962.txt
+++ b/Documentation/devicetree/bindings/sound/wm8962.txt
@@ -13,6 +13,14 @@ Optional properties:
of R51 (Class D Control 2) gets set, indicating that the speaker is
in mono mode.
+ - amic-mono: This is a boolean property. If present, indicating that the
+ analog micphone is hardware mono input, the driver would enable monomix
+ for it.
+
+ - dmic-mono: This is a boolean property. If present, indicating that the
+ digital micphone is hardware mono input, the driver would enable monomix
+ for it.
+
- mic-cfg : Default register value for R48 (Additional Control 4).
If absent, the default should be the register default.
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 0e03344e2e8b..db7bc373b528 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -84,8 +84,20 @@ i.mx specific properties
- over-current-active-high: over current signal polarity is high active,
typically over current signal polarity is low active.
- external-vbus-divider: enables off-chip resistor divider for Vbus
+- imx6-usb-charger-detection: enable imx6 usb charger detect function,
+ only set it when the user wants SoC usb charger detection capabilities.
+ If the user wants to use charger IC's usb charger detection capabilities,
+ please do not set it.
+- fsl,anatop: phandle for anatop module, anatop module is only existed
+ at imx6 SoC series.
+- pinctrl-names: for names of hsic pin group
+- pinctrl-0: hsic "idle" pin group
+- pinctrl-1: hsic "active" pin group
+- osc-clkgate-delay: the delay between powering up the xtal 24MHz clock
+ and release the clock to the digital logic inside the analog block,
+ 0 <= osc-clkgate-delay <= 7.
-Example:
+Examples:
usb@f7ed0000 {
compatible = "chipidea,usb2";
@@ -103,3 +115,21 @@ Example:
extcon = <0>, <&usb_id>;
phy-clkgate-delay-us = <400>;
};
+
+ usb@02184000 { /* USB OTG */
+ compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+ reg = <0x02184000 0x200>;
+ interrupts = <0 43 0x04>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc 0>;
+ disable-over-current;
+ external-vbus-divider;
+ imx6-usb-charger-detection;
+ fsl,anatop = <&anatop>;
+ pinctrl-names = "idle", "active";
+ pinctrl-0 = <&pinctrl_usbh2_1>;
+ pinctrl-1 = <&pinctrl_usbh2_2>;
+ osc-clkgate-delay = <0x3>;
+ maximum-speed = "full-speed";
+ tpl-support;
+ };
diff --git a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
index f1e27faf528e..fe37ac11e873 100644
--- a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
+++ b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
@@ -7,6 +7,8 @@ Required properties:
"fsl,vf610-usbmisc" for Vybrid vf610
"fsl,imx6sx-usbmisc" for imx6sx
"fsl,imx7d-usbmisc" for imx7d
+ "fsl,imx6ul-usbmisc" for imx6ul
+ "fsl,imx7ulp-usbmisc" for imx7ulp
- reg: Should contain registers location and length
Examples:
diff --git a/Documentation/usb/chipidea.txt b/Documentation/usb/chipidea.txt
index edf7cdfddc88..2b0c435f4cc9 100644
--- a/Documentation/usb/chipidea.txt
+++ b/Documentation/usb/chipidea.txt
@@ -32,7 +32,10 @@ cat /sys/kernel/debug/ci_hdrc.0/registers
B-device should take host role and enumrate A-device.
4) A-device switch back to host.
- On B-device:
+ On A-device:
+ echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
+
+ or, on B-device:
echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
or, by introducing HNP polling, B-Host can know when A-peripheral wish
@@ -74,6 +77,14 @@ cat /sys/kernel/debug/ci_hdrc.0/registers
"On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification
July 27, 2012 Revision 2.0 version 1.1a"
+1.4 OTG compliance test
+----------------------
+Only below 3 popular gadget drivers are declared to be USB OTG and EH 2.0
+compliant(with otg descriptor comply with USB OTG and EH 2.0 as a peripheral):
+- mass storage
+- ether
+- serial
+
2. How to enable USB as system wakeup source
-----------------------------------
Below is the example for how to enable USB as system wakeup source
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b5d529fdffab..52af0ba2a41e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1206,6 +1206,16 @@ config ARM_ERRATA_825619
DMB NSHST or DMB ISHST instruction followed by a mix of Cacheable
and Device/Strongly-Ordered loads and stores might cause deadlock
+config ARM_ERRATA_814220
+ bool "ARM errata: Cache maintenance by set/way operations can execute out of order"
+ depends on CPU_V7
+ help
+ The v7 ARM states that all cache and branch predictor maintenance operations
+ that do not specify an address execute, relative to each other, in program order.
+ However, because of this erratum, an L2 set/way cache maintenance operation can
+ overtake an L1 set/way cache maintenance operation. This ERRATA only affected the
+ Cortex-A7 and present in r0p2, r0p3, r0p4, r0p5.
+
config ARM_ERRATA_852421
bool "ARM errata: A17: DMB ST might fail to create order between stores"
depends on CPU_V7
@@ -1738,6 +1748,7 @@ config FORCE_MAX_ZONEORDER
int "Maximum zone order"
default "12" if SOC_AM33XX
default "9" if SA1111 || ARCH_EFM32
+ default "14" if ARCH_MXC
default "11"
help
The kernel memory allocator divides physically contiguous memory
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index d83f7c369e51..6d449e5d5450 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -405,6 +405,13 @@ choice
Say Y here if you want kernel low-level debugging support
on i.MX6SL.
+ config DEBUG_IMX6SLL_UART
+ bool "i.MX6SLL Debug UART"
+ depends on SOC_IMX6SLL
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX6SLL.
+
config DEBUG_IMX6SX_UART
bool "i.MX6SX Debug UART"
depends on SOC_IMX6SX
@@ -1350,6 +1357,7 @@ config DEBUG_IMX_UART_PORT
DEBUG_IMX53_UART || \
DEBUG_IMX6Q_UART || \
DEBUG_IMX6SL_UART || \
+ DEBUG_IMX6SLL_UART || \
DEBUG_IMX6SX_UART || \
DEBUG_IMX6UL_UART || \
DEBUG_IMX7D_UART
@@ -1404,6 +1412,7 @@ config DEBUG_LL_INCLUDE
DEBUG_IMX53_UART ||\
DEBUG_IMX6Q_UART || \
DEBUG_IMX6SL_UART || \
+ DEBUG_IMX6SLL_UART || \
DEBUG_IMX6SX_UART || \
DEBUG_IMX6UL_UART || \
DEBUG_IMX7D_UART
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 7037201c5e3a..5f9cf31dc0b8 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -346,8 +346,15 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-rex-basic.dtb \
imx6dl-riotboard.dtb \
imx6dl-sabreauto.dtb \
+ imx6dl-sabreauto-ecspi.dtb \
+ imx6dl-sabreauto-enetirq.dtb \
+ imx6dl-sabreauto-flexcan1.dtb \
+ imx6dl-sabreauto-gpmi-weim.dtb \
imx6dl-sabrelite.dtb \
imx6dl-sabresd.dtb \
+ imx6dl-sabresd-btwifi.dtb \
+ imx6dl-sabresd-hdcp.dtb \
+ imx6dl-sabresd-ldo.dtb \
imx6dl-ts4900.dtb \
imx6dl-tx6dl-comtft.dtb \
imx6dl-tx6s-8034.dtb \
@@ -357,14 +364,29 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-tx6u-811x.dtb \
imx6dl-tx6u-81xx-mb7.dtb \
imx6dl-udoo.dtb \
+ imx6dl-sabresd-enetirq.dtb \
imx6dl-wandboard.dtb \
imx6dl-wandboard-revb1.dtb \
+ imx6dqscm-1gb-qwks-rev2-fix-ldo.dtb \
+ imx6dqscm-1gb-qwks-rev2-interleave-android-ldo.dtb \
+ imx6dqscm-1gb-qwks-rev2-wifi-fix-ldo.dtb \
+ imx6dqscm-1gb-qwks-rev2-hdcp-fix-ldo.dtb \
+ imx6dqscm-1gb-evb-fix-ldo.dtb \
+ imx6dqscm-1gb-evb-interleave-android-ldo.dtb \
+ imx6dqscm-1gb-evb-btwifi-fix-ldo.dtb \
+ imx6dqscm-1gb-evb-enetirq-fix-ldo.dtb \
+ imx6dqscm-1gb-evb-hdcp-fix-ldo.dtb \
+ imx6dqscm-1gb-qwks-rev3-fix-ldo.dtb \
+ imx6dqscm-1gb-qwks-rev3-hdcp-fix-ldo.dtb \
+ imx6dqscm-1gb-qwks-rev3-btwifi-fix-ldo.dtb \
imx6q-apalis-ixora.dtb \
imx6q-apf6dev.dtb \
imx6q-arm2.dtb \
+ imx6q-arm2-hsic.dtb \
imx6q-b450v3.dtb \
imx6q-b650v3.dtb \
imx6q-b850v3.dtb \
+ imx6q-pop-arm2.dtb \
imx6q-cm-fx6.dtb \
imx6q-cubox-i.dtb \
imx6q-dfi-fs700-m60.dtb \
@@ -389,8 +411,16 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-phytec-pbab01.dtb \
imx6q-rex-pro.dtb \
imx6q-sabreauto.dtb \
+ imx6q-sabreauto-ecspi.dtb \
+ imx6q-sabreauto-enetirq.dtb \
+ imx6q-sabreauto-flexcan1.dtb \
+ imx6q-sabreauto-gpmi-weim.dtb \
imx6q-sabrelite.dtb \
imx6q-sabresd.dtb \
+ imx6q-sabresd-btwifi.dtb \
+ imx6q-sabresd-hdcp.dtb \
+ imx6q-sabresd-ldo.dtb \
+ imx6q-sabresd-enetirq.dtb \
imx6q-sbc6x.dtb \
imx6q-tbs2910.dtb \
imx6q-ts4900.dtb \
@@ -407,31 +437,157 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-wandboard-revb1.dtb \
imx6qp-nitrogen6_max.dtb \
imx6qp-sabreauto.dtb \
+ imx6qp-sabreauto-ecspi.dtb \
+ imx6qp-sabreauto-flexcan1.dtb \
+ imx6qp-sabreauto-gpmi-weim.dtb \
+ imx6qp-sabresd-btwifi.dtb \
+ imx6qp-sabresd-hdcp.dtb \
+ imx6qp-sabresd-ldo.dtb \
+ imx6qp-sabresd-ldo-pcie-cert.dtb \
imx6qp-sabresd.dtb
dtb-$(CONFIG_SOC_IMX6SL) += \
imx6sl-evk.dtb \
+ imx6sl-evk-btwifi.dtb \
+ imx6sl-evk-ldo.dtb \
+ imx6sl-evk-csi.dtb \
+ imx6sl-evk-uart.dtb \
imx6sl-warp.dtb
dtb-$(CONFIG_SOC_IMX6SX) += \
imx6sx-nitrogen6sx.dtb \
+ imx6sx-14x14-arm2.dtb \
imx6sx-sabreauto.dtb \
+ imx6sx-sabreauto-m4.dtb \
imx6sx-sdb-reva.dtb \
imx6sx-sdb-sai.dtb \
- imx6sx-sdb.dtb
+ imx6sx-sdb-reva-ldo.dtb \
+ imx6sx-sdb.dtb \
+ imx6sx-sdb-btwifi.dtb \
+ imx6sx-sdb-emmc.dtb \
+ imx6sx-sdb-lcdif1.dtb \
+ imx6sx-sdb-ldo.dtb \
+ imx6sx-sdb-m4.dtb \
+ imx6sx-sdb-mqs.dtb \
+ imx6sx-sdb-sai.dtb \
+ imx6sx-19x19-arm2.dtb \
+ imx6sx-19x19-arm2-ldo.dtb \
+ imx6sx-19x19-arm2-csi.dtb \
+ imx6sx-19x19-arm2-gpmi-weim.dtb \
+ imx6sxscm-1gb-evb-ldo.dtb \
+ imx6sxscm-1gb-evb-lcdif1-ldo.dtb \
+ imx6sxscm-1gb-evb-m4-ldo.dtb \
+ imx6sxscm-1gb-evb-mqs-ldo.dtb \
+ imx6sxscm-1gb-evb-sai-ldo.dtb \
+ imx6sxscm-1gb-evb-btwifi-ldo.dtb \
+ imx6sxscm-epop-evb-ldo.dtb \
+ imx6sxscm-epop-evb-m4-ldo.dtb
dtb-$(CONFIG_SOC_IMX6UL) += \
imx6ul-14x14-evk.dtb \
+ imx6ul-14x14-evk-btwifi.dtb \
+ imx6ul-14x14-evk-btwifi-oob.dtb \
+ imx6ul-14x14-evk-csi.dtb \
+ imx6ul-14x14-evk-emmc.dtb \
+ imx6ul-14x14-evk-gpmi-weim.dtb \
+ imx6ul-14x14-evk-usb-certi.dtb \
imx6ul-geam-kit.dtb \
imx6ul-pico-hobbit.dtb \
imx6ul-tx6ul-0010.dtb \
imx6ul-tx6ul-0011.dtb \
- imx6ul-tx6ul-mainboard.dtb
+ imx6ul-tx6ul-mainboard.dtb \
+ imx6ul-14x14-ddr3-arm2.dtb \
+ imx6ul-14x14-ddr3-arm2-emmc.dtb \
+ imx6ul-14x14-ddr3-arm2-flexcan2.dtb \
+ imx6ul-14x14-ddr3-arm2-gpmi-weim.dtb \
+ imx6ul-14x14-ddr3-arm2-mqs.dtb \
+ imx6ul-14x14-ddr3-arm2-spdif.dtb \
+ imx6ul-14x14-ddr3-arm2-wm8958.dtb \
+ imx6ul-14x14-lpddr2-arm2.dtb \
+ imx6ul-14x14-evk-pf1550.dtb \
+ imx6ul-9x9-evk.dtb \
+ imx6ul-9x9-evk-btwifi.dtb \
+ imx6ul-9x9-evk-btwifi-oob.dtb \
+ imx6ul-9x9-evk-csi.dtb \
+ imx6ul-9x9-evk-ldo.dtb
+dtb-$(CONFIG_SOC_IMX6ULL) += \
+ imx6ull-14x14-ddr3-arm2.dtb \
+ imx6ull-14x14-ddr3-arm2-adc.dtb \
+ imx6ull-14x14-ddr3-arm2-cs42888.dtb \
+ imx6ull-14x14-ddr3-arm2-ecspi.dtb \
+ imx6ull-14x14-ddr3-arm2-emmc.dtb \
+ imx6ull-14x14-ddr3-arm2-epdc.dtb \
+ imx6ull-14x14-ddr3-arm2-flexcan2.dtb \
+ imx6ull-14x14-ddr3-arm2-gpmi-weim.dtb \
+ imx6ull-14x14-ddr3-arm2-lcdif.dtb \
+ imx6ull-14x14-ddr3-arm2-ldo.dtb \
+ imx6ull-14x14-ddr3-arm2-qspi.dtb \
+ imx6ull-14x14-ddr3-arm2-qspi-all.dtb \
+ imx6ull-14x14-ddr3-arm2-tsc.dtb \
+ imx6ull-14x14-ddr3-arm2-uart2.dtb \
+ imx6ull-14x14-ddr3-arm2-usb.dtb \
+ imx6ull-14x14-ddr3-arm2-wm8958.dtb \
+ imx6ull-14x14-evk.dtb \
+ imx6ull-14x14-evk-btwifi.dtb \
+ imx6ull-14x14-evk-btwifi-oob.dtb \
+ imx6ull-14x14-evk-emmc.dtb \
+ imx6ull-14x14-evk-gpmi-weim.dtb \
+ imx6ull-14x14-evk-usb-certi.dtb \
+ imx6ull-9x9-evk.dtb \
+ imx6ull-9x9-evk-btwifi.dtb \
+ imx6ull-9x9-evk-btwifi-oob.dtb \
+ imx6ull-9x9-evk-ldo.dtb
+dtb-$(CONFIG_SOC_IMX6SLL) += \
+ imx6sll-lpddr2-arm2.dtb \
+ imx6sll-lpddr3-arm2.dtb \
+ imx6sll-lpddr3-arm2-csi.dtb \
+ imx6sll-lpddr3-arm2-ecspi.dtb \
+ imx6sll-lpddr3-arm2-spdif.dtb \
+ imx6sll-evk.dtb \
+ imx6sll-evk-reva.dtb \
+ imx6sll-evk-btwifi.dtb
dtb-$(CONFIG_SOC_IMX7D) += \
imx7d-cl-som-imx7.dtb \
imx7d-colibri-eval-v3.dtb \
imx7d-nitrogen7.dtb \
imx7d-sbc-imx7.dtb \
- imx7d-sdb.dtb \
imx7s-colibri-eval-v3.dtb \
- imx7s-warp.dtb
+ imx7s-warp.dtb \
+ imx7d-12x12-lpddr3-arm2.dtb \
+ imx7d-12x12-lpddr3-arm2-m4.dtb \
+ imx7d-12x12-ddr3-arm2.dtb \
+ imx7d-12x12-lpddr3-arm2-ecspi.dtb \
+ imx7d-12x12-lpddr3-arm2-enet2.dtb \
+ imx7d-12x12-lpddr3-arm2-flexcan.dtb \
+ imx7d-12x12-lpddr3-arm2-mipi_dsi.dtb \
+ imx7d-12x12-lpddr3-arm2-qspi.dtb \
+ imx7d-12x12-lpddr3-arm2-sai.dtb \
+ imx7d-12x12-lpddr3-arm2-mqs.dtb \
+ imx7d-12x12-lpddr3-arm2-pcie.dtb \
+ imx7d-19x19-lpddr2-arm2.dtb \
+ imx7d-sdb.dtb \
+ imx7d-sdb-epdc.dtb \
+ imx7d-sdb-gpmi-weim.dtb \
+ imx7d-sdb-m4.dtb \
+ imx7d-sdb-qspi.dtb \
+ imx7d-sdb-mipi-dsi.dtb \
+ imx7d-sdb-reva.dtb \
+ imx7d-sdb-reva-epdc.dtb \
+ imx7d-sdb-reva-gpmi-weim.dtb \
+ imx7d-sdb-reva-hdmi-audio.dtb \
+ imx7d-sdb-reva-m4.dtb \
+ imx7d-sdb-reva-qspi.dtb \
+ imx7d-sdb-reva-touch.dtb \
+ imx7d-sdb-reva-wm8960.dtb
+dtb-$(CONFIG_SOC_IMX7ULP) += \
+ imx7ulp-14x14-arm2.dtb \
+ imx7ulp-evk.dtb \
+ imx7ulp-evk-emmc.dtb \
+ imx7ulp-evk-emmc-qspi.dtb \
+ imx7ulp-evk-ft5416.dtb \
+ imx7ulp-evk-sd1.dtb \
+ imx7ulp-evk-lpuart.dtb \
+ imx7ulp-evk-qspi.dtb \
+ imx7ulp-evk-wm8960.dtb \
+ imx7ulp-evk-hdmi.dtb \
+ imx7ulp-evk-sensors-to-i2c5.dtb
dtb-$(CONFIG_SOC_LS1021A) += \
ls1021a-qds.dtb \
ls1021a-twr.dtb
diff --git a/arch/arm/boot/dts/imx6dl-aristainetos_4.dts b/arch/arm/boot/dts/imx6dl-aristainetos_4.dts
index d4c4a22db488..926e4ee13c1e 100644
--- a/arch/arm/boot/dts/imx6dl-aristainetos_4.dts
+++ b/arch/arm/boot/dts/imx6dl-aristainetos_4.dts
@@ -3,6 +3,8 @@
*
* Copyright (C) 2014 Heiko Schocher <hs@denx.de>
*
+ * Copyright 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.
@@ -30,39 +32,19 @@
memory {
reg = <0x10000000 0x40000000>;
};
+};
- soc {
- display0: display@di0 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "rgb24";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ipu_disp>;
- status = "okay";
-
- display-timings {
- 480x800p60 {
- native-mode;
- clock-frequency = <30000000>;
- hactive = <480>;
- vactive = <800>;
- hfront-porch = <59>;
- hback-porch = <10>;
- hsync-len = <10>;
- vback-porch = <15>;
- vfront-porch = <15>;
- vsync-len = <15>;
- hsync-active = <1>;
- vsync-active = <1>;
- };
- };
+&mxcfb1 {
+ status = "okay";
+};
- port {
- display0_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
- };
- };
+&lcd {
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu_disp>;
+ status = "okay";
};
&ecspi2 {
@@ -80,10 +62,6 @@
status = "okay";
};
-&ipu1_di0_disp0 {
- remote-endpoint = <&display0_in>;
-};
-
&pwm1 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6dl-aristainetos_7.dts b/arch/arm/boot/dts/imx6dl-aristainetos_7.dts
index 15203f0e9725..bad1e22b6bd7 100644
--- a/arch/arm/boot/dts/imx6dl-aristainetos_7.dts
+++ b/arch/arm/boot/dts/imx6dl-aristainetos_7.dts
@@ -3,6 +3,8 @@
*
* Copyright (C) 2014 Heiko Schocher <hs@denx.de>
*
+ * Copyright 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.
@@ -20,38 +22,6 @@
reg = <0x10000000 0x40000000>;
};
- soc {
- display0: display@di0 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "rgb24";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ipu_disp>;
- status = "okay";
-
- display-timings {
- 800x480p60 {
- native-mode;
- clock-frequency = <33246000>;
- hactive = <800>;
- vactive = <480>;
- hfront-porch = <88>;
- hback-porch = <88>;
- hsync-len = <80>;
- vback-porch = <10>;
- vfront-porch = <10>;
- vsync-len = <25>;
- vsync-active = <1>;
- };
- };
-
- port {
- display0_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
- };
- };
-
backlight {
compatible = "pwm-backlight";
pwms = <&pwm3 0 3000>;
@@ -62,6 +32,19 @@
};
};
+&mxcfb1 {
+ status = "okay";
+};
+
+&lcd {
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu_disp>;
+ status = "okay";
+};
+
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
@@ -69,10 +52,6 @@
status = "okay";
};
-&ipu1_di0_disp0 {
- remote-endpoint = <&display0_in>;
-};
-
&pwm3 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts
index 75d73437adf7..1e7437c9ca30 100644
--- a/arch/arm/boot/dts/imx6dl-riotboard.dts
+++ b/arch/arm/boot/dts/imx6dl-riotboard.dts
@@ -1,6 +1,8 @@
/*
* Copyright 2014 Iain Paton <ipaton0@gmail.com>
*
+ * Copyright 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.
@@ -15,6 +17,10 @@
model = "RIoTboard i.MX6S";
compatible = "riot,imx6s-riotboard", "fsl,imx6dl";
+ aliases {
+ mxcfb0 = &mxcfb1;
+ };
+
memory {
reg = <0x10000000 0x40000000>;
};
@@ -82,6 +88,17 @@
mux-int-port = <1>;
mux-ext-port = <3>;
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&audmux {
@@ -101,8 +118,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c2>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -220,6 +244,11 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&i2c4 {
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..45ae16283627
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto-ecspi.dts
@@ -0,0 +1,39 @@
+/*
+ * 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 "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..906d1d9bcda0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto-enetirq.dts
@@ -0,0 +1,19 @@
+/*
+ * 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-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>;
+};
+
+&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..ad2e937d4ffa
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto-gpmi-weim.dts
@@ -0,0 +1,48 @@
+/*
+ * 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 "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.dts b/arch/arm/boot/dts/imx6dl-sabreauto.dts
index a6ce7b487ad7..bd13b3592091 100644
--- a/arch/arm/boot/dts/imx6dl-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6dl-sabreauto.dts
@@ -15,3 +15,17 @@
model = "Freescale i.MX6 DualLite/Solo SABRE Automotive Board";
compatible = "fsl,imx6dl-sabreauto", "fsl,imx6dl";
};
+&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..814c93530a76
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-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 "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..ff4144113d5a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-enetirq.dts
@@ -0,0 +1,18 @@
+/*
+ * 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 "imx6dl-sabresd.dts"
+
+&fec {
+ pinctrl-0 = <&pinctrl_enet &pinctrl_enet_irq>;
+ interrupts-extended = <&gpio1 6 0x04>, <&gpc 0 119 0x04>;
+};
+
+&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.dts b/arch/arm/boot/dts/imx6dl-sabresd.dts
index 1e45f2f9d0b6..fb402e56f975 100644
--- a/arch/arm/boot/dts/imx6dl-sabresd.dts
+++ b/arch/arm/boot/dts/imx6dl-sabresd.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-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
@@ -15,3 +15,138 @@
model = "Freescale i.MX6 DualLite SABRE Smart Device Board";
compatible = "fsl,imx6dl-sabresd", "fsl,imx6dl";
};
+
+&battery {
+ offset-charger = <1485>;
+ offset-discharger = <1464>;
+ offset-usb-charger = <1285>;
+};
+
+&iomuxc {
+ epdc {
+ 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 {
+ 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_sensor>;
+ 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";
+ };
+ };
+ };
+};
+
+&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-tx6dl-comtft.dts b/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts
index 063fe7510da5..c6eba8ff33c7 100644
--- a/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts
+++ b/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts
@@ -47,10 +47,6 @@
model = "Ka-Ro electronics TX6DL Module on CoMpact TFT";
compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
- aliases {
- display = &display;
- };
-
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 500000 0>;
@@ -73,39 +69,15 @@
default-brightness-level = <50>;
};
- display: display@di0 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "rgb24";
+ lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_disp0_1>;
status = "okay";
-
- port {
- display0_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
-
- display-timings {
- native-mode = <&ET070001DM6>;
-
- ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <1>;
- };
- };
- };
+ };
};
&can1 {
@@ -116,10 +88,6 @@
xceiver-supply = <&reg_3v3>;
};
-&ipu1_di0_disp0 {
- remote-endpoint = <&display0_in>;
-};
-
&kpp {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6dl-tx6u-801x.dts b/arch/arm/boot/dts/imx6dl-tx6u-801x.dts
index b7a72840b7f0..34cb356b85f6 100644
--- a/arch/arm/boot/dts/imx6dl-tx6u-801x.dts
+++ b/arch/arm/boot/dts/imx6dl-tx6u-801x.dts
@@ -47,10 +47,6 @@
model = "Ka-Ro electronics TX6U-801x Module";
compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
- aliases {
- display = &display;
- };
-
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
@@ -73,135 +69,14 @@
default-brightness-level = <50>;
};
- display: display@di0 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "rgb24";
+ lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_disp0_1>;
status = "okay";
-
- port {
- display0_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
-
- display-timings {
- VGA {
- clock-frequency = <25200000>;
- hactive = <640>;
- vactive = <480>;
- hback-porch = <48>;
- hsync-len = <96>;
- hfront-porch = <16>;
- vback-porch = <31>;
- vsync-len = <2>;
- vfront-porch = <12>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ETV570 {
- clock-frequency = <25200000>;
- hactive = <640>;
- vactive = <480>;
- hback-porch = <114>;
- hsync-len = <30>;
- hfront-porch = <16>;
- vback-porch = <32>;
- vsync-len = <3>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0350 {
- clock-frequency = <6413760>;
- hactive = <320>;
- vactive = <240>;
- hback-porch = <34>;
- hsync-len = <34>;
- hfront-porch = <20>;
- vback-porch = <15>;
- vsync-len = <3>;
- vfront-porch = <4>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0430 {
- clock-frequency = <9009000>;
- hactive = <480>;
- vactive = <272>;
- hback-porch = <2>;
- hsync-len = <41>;
- hfront-porch = <2>;
- vback-porch = <2>;
- vsync-len = <10>;
- vfront-porch = <2>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <1>;
- };
-
- ET0500 {
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0700 { /* same as ET0500 */
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ETQ570 {
- clock-frequency = <6596040>;
- hactive = <320>;
- vactive = <240>;
- hback-porch = <38>;
- hsync-len = <30>;
- hfront-porch = <30>;
- vback-porch = <16>;
- vsync-len = <3>;
- vfront-porch = <4>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
- };
- };
+ };
};
-&ipu1_di0_disp0 {
- remote-endpoint = <&display0_in>;
-};
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 7aa120fbdc71..0a4c0f67308b 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -1,6 +1,6 @@
/*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-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
@@ -21,7 +21,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0>;
@@ -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>;
@@ -59,10 +63,60 @@
};
};
+ 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@00900000 {
+ 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 0x04>, <0 112 0x4>;
+ interrupt-names = "irq_busfreq_0", "irq_busfreq_1";
+ fsl,max_ddr_freq = <400000000>;
+ };
+
+ gpu@00130000 {
+ compatible = "fsl,imx6dl-gpu", "fsl,imx6q-gpu";
+ reg = <0x00130000 0x4000>, <0x00134000 0x4000>,
+ <0x0 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 = <&gpc 1>;
+ };
+
+ ocram: sram@00905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
+ reg = <0x00905000 0x1B000>;
clocks = <&clks IMX6QDL_CLK_OCRAM>;
};
@@ -71,14 +125,27 @@
compatible = "fsl,imx6dl-iomuxc";
};
+ dcic2: dcic@020e8000 {
+ clocks = <&clks IMX6QDL_CLK_DCIC1 >,
+ <&clks IMX6QDL_CLK_DCIC2>; /* DCIC2 depend on DCIC1 clock in imx6dl*/
+ clock-names = "dcic", "disp-axi";
+ };
+
pxp: pxp@020f0000 {
+ compatible = "fsl,imx6dl-pxp-dma";
reg = <0x020f0000 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@020f4000 {
+ compatible = "fsl,imx6dl-epdc";
reg = <0x020f4000 0x4000>;
interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_IPU2>, <&clks IMX6QDL_CLK_IPU2_DI1>;
+ clock-names = "epdc_axi", "epdc_pix";
};
lcdif: lcdif@020f8000 {
@@ -88,6 +155,16 @@
};
aips2: aips-bus@02100000 {
+ mipi_dsi: mipi@021e0000 {
+ compatible = "fsl,imx6dl-mipi-dsi";
+ reg = <0x021e0000 0x4000>;
+ interrupts = <0 102 0x04>;
+ 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@021f8000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -173,14 +250,25 @@
};
&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";
};
&vpu {
compatible = "fsl,imx6dl-vpu", "cnm,coda960";
};
+
+&vpu_fsl {
+ iramsize = <0>;
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-evb-btwifi-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-evb-btwifi-fix-ldo.dts
new file mode 100644
index 000000000000..d29e57254a54
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-evb-btwifi-fix-ldo.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 "imx6dqscm-1gb-evb-fix-ldo.dts"
+#include "imx6qdl-sabresd-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-evb-enetirq-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-evb-enetirq-fix-ldo.dts
new file mode 100644
index 000000000000..a6630d32e71f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-evb-enetirq-fix-ldo.dts
@@ -0,0 +1,18 @@
+/*
+ * 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 "imx6dqscm-1gb-evb-fix-ldo.dts"
+
+&fec {
+ pinctrl-0 = <&pinctrl_enet &pinctrl_enet_irq>;
+ interrupts-extended = <&gpio1 6 0x04>, <&intc 0 119 0x04>;
+};
+
+&i2c3 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-evb-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-evb-fix-ldo.dts
new file mode 100644
index 000000000000..1013cf7d3997
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-evb-fix-ldo.dts
@@ -0,0 +1,219 @@
+/*
+ * 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 "imx6q-sabresd-ldo.dts"
+
+/ {
+ model = "Freescale i.MX6D SCM EVB";
+ compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
+ memory: memory {
+ linux,usable-memory = <0x10000000 0x20000000
+ 0x80000000 0x20000000>;
+ };
+ soc {
+ busfreq {
+ fsl,max_ddr_freq = <400000000>;
+ status = "okay";
+ clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>,
+ <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>, <&clks 140>;
+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph",
+ "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "mmdc";
+ };
+ };
+};
+
+&ecspi1 {
+ cs-gpios = <&gpio2 30 0>;
+ internal_scm_flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q128a13", "jedec,spi-nor";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&i2c1 {
+ ov564x: ov564x@3c {
+ DOVDD-supply = <&sw4_reg>; /* 1.8v */
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+ assigned-clock-parents = <&clks IMX6QDL_CLK_MMDC_CH1_AXI>,
+ <&clks IMX6QDL_CLK_MMDC_CH1_AXI>;
+};
+
+&i2c2 {
+ pmic: pfuze100@08 {
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ regulator-boot-on;
+ regulator-always-on;
+
+ };
+
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ ov564x_mipi: ov564x_mipi@3c {
+ DOVDD-supply = <&sw4_reg>; /* 1.8v */
+ };
+
+};
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-sabresd {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x80000000
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x80000000
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x80000000
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000
+ 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_EIM_EB3__GPIO2_IO31 0x80000000
+ MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x80000000
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x80000000
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
+ MX6QDL_PAD_GPIO_1__WDOG2_B 0x80000000
+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
+ >;
+ };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ >;
+ };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-evb-hdcp-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-evb-hdcp-fix-ldo.dts
new file mode 100644
index 000000000000..4bb67eab0aaa
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-evb-hdcp-fix-ldo.dts
@@ -0,0 +1,19 @@
+/*
+ * 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 "imx6dqscm-1gb-evb-fix-ldo.dts"
+
+&hdmi_video {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_hdcp>;
+ fsl,hdcp;
+};
+
+&i2c2 {
+ status = "disable";
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-evb-interleave-android-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-evb-interleave-android-ldo.dts
new file mode 100644
index 000000000000..5136cd77ed4b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-evb-interleave-android-ldo.dts
@@ -0,0 +1,209 @@
+/*
+ * 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 "imx6q-sabresd-ldo.dts"
+
+/ {
+ model = "Freescale i.MX6D SCM EVB";
+ compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
+ soc {
+ busfreq {
+ fsl,max_ddr_freq = <400000000>;
+ status = "okay";
+ clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>,
+ <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>, <&clks 140>;
+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph",
+ "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "mmdc";
+ };
+ };
+};
+
+&ecspi1 {
+ cs-gpios = <&gpio2 30 0>;
+ internal_scm_flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q128a13", "jedec,spi-nor";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&i2c1 {
+ ov564x: ov564x@3c {
+ DOVDD-supply = <&sw4_reg>; /* 1.8v */
+ };
+};
+
+&i2c2 {
+ pmic: pfuze100@08 {
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ regulator-boot-on;
+ regulator-always-on;
+
+ };
+
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ ov564x_mipi: ov564x_mipi@3c {
+ DOVDD-supply = <&sw4_reg>; /* 1.8v */
+ };
+
+};
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-sabresd {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x80000000
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x80000000
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x80000000
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000
+ 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_EIM_EB3__GPIO2_IO31 0x80000000
+ MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x80000000
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x80000000
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
+ MX6QDL_PAD_GPIO_1__WDOG2_B 0x80000000
+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
+ >;
+ };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ >;
+ };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
+ >;
+ };
+ };
+};
+
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-fix.dtsi b/arch/arm/boot/dts/imx6dqscm-1gb-fix.dtsi
new file mode 100644
index 000000000000..606d361aae18
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-fix.dtsi
@@ -0,0 +1,14 @@
+/*
+ * 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.
+ */
+
+/ {
+ memory: memory {
+ linux,usable-memory = <0x10000000 0x20000000
+ 0x80000000 0x20000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-interleave-android.dtsi b/arch/arm/boot/dts/imx6dqscm-1gb-interleave-android.dtsi
new file mode 100644
index 000000000000..6edda09a9967
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-interleave-android.dtsi
@@ -0,0 +1,14 @@
+/*
+ * 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.
+ */
+
+/ {
+ memory: memory {
+ linux,usable-memory = <0x10000000 0x40000000>;
+ };
+
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-fix-ldo.dts
new file mode 100644
index 000000000000..436a90d8045d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-fix-ldo.dts
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6dqscm-qwks-rev2.dtsi"
+#include "imx6dqscm-1gb-fix.dtsi"
+
+/ {
+ model = "Freescale i.MX6DQ SCM QWKS";
+ compatible = "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";
+};
+
+&cpu0 {
+ arm-supply = <&reg_arm>;
+ soc-supply = <&reg_soc>;
+};
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&wdog1 {
+ status = "okay";
+};
+
+&wdog2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-hdcp-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-hdcp-fix-ldo.dts
new file mode 100644
index 000000000000..4aafc0deb162
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-hdcp-fix-ldo.dts
@@ -0,0 +1,19 @@
+/*
+ * 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 "imx6dqscm-1gb-qwks-rev2-fix-ldo.dts"
+
+&hdmi_video {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_hdcp>;
+ fsl,hdcp;
+};
+
+&i2c2 {
+ status = "disable";
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-interleave-android-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-interleave-android-ldo.dts
new file mode 100644
index 000000000000..65734218691c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-interleave-android-ldo.dts
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6dqscm-qwks-rev2.dtsi"
+#include "imx6dqscm-1gb-interleave-android.dtsi"
+
+/ {
+ model = "Freescale i.MX6DQ SCM QWKS";
+ compatible = "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";
+};
+
+&cpu0 {
+ arm-supply = <&reg_arm>;
+ soc-supply = <&reg_soc>;
+};
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
+
+&wdog1 {
+ status = "okay";
+};
+
+&wdog2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-wifi-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-wifi-fix-ldo.dts
new file mode 100644
index 000000000000..16171a23fa27
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev2-wifi-fix-ldo.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 "imx6dqscm-1gb-qwks-rev2-fix-ldo.dts"
+#include "imx6dqscm-qwks-wifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-btwifi-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-btwifi-fix-ldo.dts
new file mode 100644
index 000000000000..d376141dcb7a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-btwifi-fix-ldo.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 "imx6dqscm-1gb-qwks-rev3-fix-ldo.dts"
+#include "imx6dqscm-qwks-rev3-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-fix-ldo.dts
new file mode 100644
index 000000000000..3a42eaa538ef
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-fix-ldo.dts
@@ -0,0 +1,147 @@
+/*
+ * 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 "imx6dqscm-1gb-qwks-rev2-fix-ldo.dts"
+
+/ {
+ regulators {
+ reg_usb_otg_vbus: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 15 0>;
+ enable-active-high;
+ };
+ };
+
+ v4l2_cap_1 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+};
+
+&i2c2 {
+ ov564x_mipi: ov564x_mipi@3c {
+ compatible = "ovti,ov564x_mipi";
+ reg = <0x3c>;
+ clocks = <&clks 201>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&sw4_reg>;
+ AVDD-supply = <&vgen3_reg>;
+ DVDD-supply = <&vgen2_reg>;
+ pwn-gpios = <&gpio1 19 1>;
+ rst-gpios = <&gpio1 20 0>;
+ csi_id = <1>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cam>;
+ };
+
+ pmic: pfuze100@08 {
+ regulators {
+ vgen5_reg: vgen5 {
+ regulator-max-microvolt = <2500000>;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ egalax_ts@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3_egalax_int>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <14 0>;
+ wakeup-gpios = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&mipi_csi {
+ status = "okay";
+ ipu_id = <0>;
+ csi_id = <1>;
+ v_channel = <0>;
+ lanes = <2>;
+};
+
+&usdhc3 {
+ cd-gpios = <&gpio7 1 GPIO_ACTIVE_LOW>;
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio5 12 0>;
+ fsl,magic-packet;
+ assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF >;
+ assigned-clock-rates = <50000000>;
+ status = "okay";
+};
+
+&iomuxc {
+ imx6dqscm-cam {
+ pinctrl_cam: camgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x13069
+ MX6QDL_PAD_SD1_DAT2__GPIO1_IO19 0x13069
+ >;
+ };
+ };
+
+ imx6qdl-sabresd {
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x80000000
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x17059
+ >;
+ };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
+ MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-hdcp-fix-ldo.dts b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-hdcp-fix-ldo.dts
new file mode 100644
index 000000000000..1a789fe21858
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-1gb-qwks-rev3-hdcp-fix-ldo.dts
@@ -0,0 +1,19 @@
+/*
+ * 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 "imx6dqscm-1gb-qwks-rev3-fix-ldo.dts"
+
+&hdmi_video {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_hdcp>;
+ fsl,hdcp;
+};
+
+&i2c2 {
+ status = "disable";
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-qwks-rev2.dtsi b/arch/arm/boot/dts/imx6dqscm-qwks-rev2.dtsi
new file mode 100644
index 000000000000..361fe62d067a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-qwks-rev2.dtsi
@@ -0,0 +1,610 @@
+/*
+ * 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 <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ mxcfb2 = &mxcfb3;
+ mxcfb3 = &mxcfb4;
+ };
+
+ soc {
+ busfreq {
+ fsl,max_ddr_freq = <400000000>;
+ status = "okay";
+ };
+ };
+
+ hannstar_cabc {
+ compatible = "hannstar,cabc";
+
+ lvds0 {
+ gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
+
+ };
+ };
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory: memory {
+ reg = <0x10000000 0x40000000>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_usb_otg_vbus: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 22 0>;
+ enable-active-high;
+ };
+ };
+
+ 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";
+ };
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm4 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <7>;
+ status = "okay";
+ };
+
+ v4l2_out {
+ compatible = "fsl,mxc_v4l2_output";
+ status = "okay";
+ };
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ linux,code = <KEY_POWER>;
+ };
+ };
+
+};
+
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_pu {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+ assigned-clock-parents = <&clks IMX6QDL_CLK_MMDC_CH1_AXI>,
+ <&clks IMX6QDL_CLK_MMDC_CH1_AXI>;
+};
+
+&ecspi1 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio2 30 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ status = "okay";
+ flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q128a13", "jedec,spi-nor";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ egalax_ts@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2_egalax_int>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <8 2>;
+ wakeup-gpios = <&gpio6 8 GPIO_ACTIVE_HIGH>;
+ };
+
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+ egalax_ts@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3_egalax_int>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <7 2>;
+ wakeup-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+ };
+
+ touchscreen@01 {
+ compatible = "vtl,ct365";
+ reg = <0x01>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <14 0>;
+ gpios = <&gpio4 10 0>;
+ };
+
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-sabresd {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
+ MX6QDL_PAD_KEY_COL2__GPIO4_IO10 0x80000000
+ MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x80000000
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ >;
+ };
+
+ pinctrl_i2c2_egalax_int: egalax_i2c2_intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x80000000
+ >;
+ };
+
+ pinctrl_i2c3_egalax_int: egalax_i2c3_intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x80000000
+ >;
+ };
+
+ pinctrl_hdmi_cec: hdmicecgrp {
+ fsl,pins = <
+ 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
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__WDOG2_B 0x80000000
+ >;
+ };
+
+ };
+};
+
+&dcic1 {
+ dcic_id = <0>;
+ dcic_mux = "dcic-hdmi";
+ status = "okay";
+};
+
+&dcic2 {
+ dcic_id = <1>;
+ dcic_mux = "dcic-lvds1";
+ status = "okay";
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_cec>;
+ status = "okay";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <1>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
+ status = "okay";
+};
+
+&ldb {
+ status = "okay";
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ status = "okay";
+
+ 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";
+
+ 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>;
+ };
+ };
+ };
+};
+
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm4>;
+ status = "okay";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usb_otg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbphy1 {
+ tx-d-cal = <0x5>;
+};
+
+&usbphy2 {
+ tx-d-cal = <0x5>;
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ status = "okay";
+};
+
+&wdog1 {
+ status = "disabled";
+};
+
+&wdog2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-qwks-rev3-btwifi.dtsi b/arch/arm/boot/dts/imx6dqscm-qwks-rev3-btwifi.dtsi
new file mode 100644
index 000000000000..dc41db6b1517
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-qwks-rev3-btwifi.dtsi
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+/ {
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio6 1 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio6 5 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ gpios = <&gpio6 4 0>; /* WL_HOST_WAKE */
+ };
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4
+ &pinctrl_bt>;
+ fsl,uart-has-rtscts;
+ resets = <&modem_reset>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host;
+};
+
+&iomuxc {
+ imx6dqscm-murata-v2 {
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x13069
+ MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x13069
+ >;
+ };
+
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_CSI0_DAT19__GPIO6_IO05 0x13069
+ MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x13069
+ >;
+ };
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1f0b1
+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1f0b1
+ MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dqscm-qwks-wifi.dtsi b/arch/arm/boot/dts/imx6dqscm-qwks-wifi.dtsi
new file mode 100644
index 000000000000..bafca7465bb2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dqscm-qwks-wifi.dtsi
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/ {
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio4 30 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&iomuxc {
+ imx6qdl-sabresd-murata-v2 {
+ /* add MUXing entry for SD2 4-bit interface
+ * and configure control pins
+ */
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x13069
+ >;
+ };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1f0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1f0b1
+ MX6QDL_PAD_EIM_D28__UART2_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D29__UART2_RTS_B 0x1b0b1
+ MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23 0x13069
+ >;
+ };
+ 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
+ >;
+ };
+
+ };
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /*pinctrl-0 = <&pinctrl_uart2dte>; */
+};
+
+&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>; */
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host;
+};
diff --git a/arch/arm/boot/dts/imx6q-arm2-hsic.dts b/arch/arm/boot/dts/imx6q-arm2-hsic.dts
new file mode 100644
index 000000000000..10c95ad96761
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-arm2-hsic.dts
@@ -0,0 +1,24 @@
+/*
+ * 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 "imx6q-arm2.dts"
+
+&fec {
+ status = "disabled";
+};
+
+&usbh2 {
+ pinctrl-names = "idle", "active";
+ pinctrl-0 = <&pinctrl_usbh2_1>;
+ pinctrl-1 = <&pinctrl_usbh2_2>;
+ osc-clkgate-delay = <0x3>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts
index 4989d0bff10f..7793d73839e6 100644
--- a/arch/arm/boot/dts/imx6q-arm2.dts
+++ b/arch/arm/boot/dts/imx6q-arm2.dts
@@ -62,6 +62,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
status = "disabled"; /* gpmi nand conflicts with SD */
+ nand-on-flash-bbt;
};
&iomuxc {
@@ -140,6 +141,32 @@
>;
};
+ pinctrl_usbh2_1: usbh2grp-1 {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_TXC__USB_H2_DATA 0x40013030
+ MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40013030
+ >;
+ };
+
+ pinctrl_usbh2_2: usbh2grp-2 {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40017030
+ >;
+ };
+
+ pinctrl_usbh3_1: usbh3grp-1 {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA 0x40013030
+ MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40013030
+ >;
+ };
+
+ pinctrl_usbh3_2: usbh3grp-2 {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40017030
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
@@ -194,6 +221,9 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbotg>;
disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-gk802.dts b/arch/arm/boot/dts/imx6q-gk802.dts
index b715deb4ea46..b27b8aad987c 100644
--- a/arch/arm/boot/dts/imx6q-gk802.dts
+++ b/arch/arm/boot/dts/imx6q-gk802.dts
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2013 Philipp Zabel
*
+ * Copyright 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
@@ -14,6 +16,10 @@
model = "Zealz GK802";
compatible = "zealz,imx6q-gk802", "fsl,imx6q";
+ aliases {
+ mxcfb0 = &mxcfb1;
+ };
+
chosen {
stdout-path = &uart4;
};
@@ -47,10 +53,28 @@
wakeup-source;
};
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
-&hdmi {
- ddc-i2c-bus = <&i2c3>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -74,6 +98,11 @@
pinctrl-0 = <&pinctrl_i2c3>;
clock-frequency = <100000>;
status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&iomuxc {
diff --git a/arch/arm/boot/dts/imx6q-gw5400-a.dts b/arch/arm/boot/dts/imx6q-gw5400-a.dts
index 747bc104ad00..7c39985dd729 100644
--- a/arch/arm/boot/dts/imx6q-gw5400-a.dts
+++ b/arch/arm/boot/dts/imx6q-gw5400-a.dts
@@ -1,6 +1,8 @@
/*
* Copyright 2013 Gateworks Corporation
*
+ * Copyright 2015 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:
@@ -30,6 +32,7 @@
spi0 = &ecspi1;
usb0 = &usbh1;
usb1 = &usbotg;
+ mxcfb0 = &mxcfb1;
};
chosen {
@@ -129,6 +132,17 @@
mux-int-port = <1>;
mux-ext-port = <4>;
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&audmux {
@@ -159,8 +173,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c3>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -332,6 +353,11 @@
VDDIO-supply = <&reg_3p3v>;
};
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
touchscreen: egalax_ts@04 {
compatible = "eeti,egalax_ts";
reg = <0x04>;
diff --git a/arch/arm/boot/dts/imx6q-pop-arm2.dts b/arch/arm/boot/dts/imx6q-pop-arm2.dts
new file mode 100644
index 000000000000..df6e2a329aa9
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-pop-arm2.dts
@@ -0,0 +1,437 @@
+/*
+ * 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
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "imx6q.dtsi"
+
+/ {
+ model = "Freescale i.MX6 Quad Armadillo2 Board";
+ compatible = "fsl,imx6q-pop-arm2", "fsl,imx6q";
+
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ };
+
+ pwm-backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 50000>;
+ power-supply = <&reg_lvds_3p3v>;
+ brightness-levels = <
+ 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100
+ >;
+ default-brightness-level = <94>;
+ status = "okay";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio3 30 1>;
+ linux,code = <116>;
+ gpio-key,wakeup;
+ };
+ };
+
+ hannstar_cabc {
+ compatible = "hannstar,cabc";
+ lvds_share {
+ gpios = <&max7310_a 0 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ memory {
+ linux,usable-memory = <0x10000000 0x20000000>,
+ <0x80000000 0x20000000>;
+ };
+
+ 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 = "okay";
+ };
+
+ 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 = "okay";
+ };
+
+ sound-hdmi {
+ compatible = "fsl,imx6q-audio-hdmi", "fsl,imx-audio-hdmi";
+ model = "imx-audio-hdmi";
+ hdmi-controller = <&hdmi_audio>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_3p3v: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_usb_otg_vbus: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 22 0>;
+ enable-active-high;
+ };
+
+ reg_lvds_3p3v: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "LVDS-3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&max7310_b 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+ };
+};
+
+&cpu0 {
+ fsl,arm-soc-shared = <1>;
+};
+
+&busfreq {
+ fsl,max_ddr_freq = <400000000>;
+};
+
+&dcic1 {
+ dcic_id = <0>;
+ dcic_mux = "dcic-hdmi";
+ status = "okay";
+};
+
+&dcic2 {
+ dcic_id = <1>;
+ dcic_mux = "dcic-lvds0";
+ status = "okay";
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_cec>;
+ status = "okay";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <1>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
+ egalax_ts@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_egalax_int>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <31 2>;
+ wakeup-gpios = <&gpio3 31 0>;
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ max7310_a: gpio@1b {
+ compatible = "maxim,max7310";
+ reg = <0x1b>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ max7310_b: gpio@1f {
+ compatible = "maxim,max7310";
+ reg = <0x1f>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6q-arm2 {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000
+ >;
+ };
+
+ 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 0x1b0b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x1b0b0
+ >;
+ };
+
+ pinctrl_hdmi_cec: hdmicecgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A25__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
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_egalax_int: egalax_intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x80000000
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__PWM1_OUT 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3_cdwp: usdhc3cdwp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
+ };
+ };
+};
+
+&ldb {
+ status = "okay";
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ crtc = "ipu2-di0";
+ primary;
+ status = "okay";
+
+ 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>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ fsl,dte-mode;
+ fsl,uart-has-rtscts;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usb_otg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usdhc3 {
+ wp-gpios = <&gpio6 14 0>;
+ vmmc-supply = <&reg_3p3v>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3
+ &pinctrl_usdhc3_cdwp>;
+ status = "okay";
+};
+
+&usdhc4 {
+ non-removable;
+ vmmc-supply = <&reg_3p3v>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ status = "okay";
+};
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..3cf99ed9be6b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto-ecspi.dts
@@ -0,0 +1,40 @@
+/*
+ * 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-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..7acb794fbaa6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto-enetirq.dts
@@ -0,0 +1,19 @@
+/*
+ * 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-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>;
+};
+
+&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..579aeb26e05d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto-gpmi-weim.dts
@@ -0,0 +1,49 @@
+/*
+ * 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-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.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
index 334b9247e78c..a321a20832df 100644
--- a/arch/arm/boot/dts/imx6q-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -20,6 +20,26 @@
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..af65f3ad76f8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-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 "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..69da4046a75b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-enetirq.dts
@@ -0,0 +1,18 @@
+/*
+ * 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"
+
+&fec {
+ pinctrl-0 = <&pinctrl_enet &pinctrl_enet_irq>;
+ interrupts-extended = <&gpio1 6 0x04>, <&gpc 0 119 0x04>;
+};
+
+&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.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index 9cbdfe7a0931..a63e1b66a6bb 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012=2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -20,6 +20,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-tbs2910.dts b/arch/arm/boot/dts/imx6q-tbs2910.dts
index 06f492e17ca7..43ff8f5b04fe 100644
--- a/arch/arm/boot/dts/imx6q-tbs2910.dts
+++ b/arch/arm/boot/dts/imx6q-tbs2910.dts
@@ -1,6 +1,8 @@
/*
* Copyright 2014 Soeren Moch <smoch@web.de>
*
+ * Copyright 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
* This file is dual-licensed: you can use it either under the terms
* of the GPL or the X11 license, at your option. Note that this dual
* licensing only applies to this file, and not this project as a
@@ -55,6 +57,10 @@
model = "TBS2910 Matrix ARM mini PC";
compatible = "tbs,imx6q-tbs2910", "fsl,imx6q";
+ aliases {
+ mxcfb0 = &mxcfb1;
+ };
+
chosen {
stdout-path = &uart1;
};
@@ -131,6 +137,17 @@
spdif-controller = <&spdif>;
spdif-out;
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&audmux {
@@ -145,10 +162,21 @@
status = "okay";
};
-&hdmi {
+&hdmi_cec {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hdmi>;
- ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -174,6 +202,11 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&i2c3 {
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts b/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts
index 65e95ae7509a..2a129af46c73 100644
--- a/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts
+++ b/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts
@@ -47,10 +47,6 @@
model = "Ka-Ro electronics TX6Q-1010 Module on CoMpact TFT";
compatible = "karo,imx6q-tx6q", "fsl,imx6q";
- aliases {
- display = &display;
- };
-
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 500000 0>;
@@ -73,39 +69,15 @@
default-brightness-level = <50>;
};
- display: display@di0 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "rgb24";
+ lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_disp0_1>;
status = "okay";
-
- port {
- display0_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
-
- display-timings {
- native-mode = <&ET070001DM6>;
-
- ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <1>;
- };
- };
- };
+ };
};
&can1 {
@@ -116,10 +88,6 @@
xceiver-supply = <&reg_3v3>;
};
-&ipu1_di0_disp0 {
- remote-endpoint = <&display0_in>;
-};
-
&kpp {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1010.dts b/arch/arm/boot/dts/imx6q-tx6q-1010.dts
index 20cd0e7b3e21..48e6d08f7a36 100644
--- a/arch/arm/boot/dts/imx6q-tx6q-1010.dts
+++ b/arch/arm/boot/dts/imx6q-tx6q-1010.dts
@@ -47,10 +47,6 @@
model = "Ka-Ro electronics TX6Q-1010 Module";
compatible = "karo,imx6q-tx6q", "fsl,imx6q";
- aliases {
- display = &display;
- };
-
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
@@ -73,135 +69,14 @@
default-brightness-level = <50>;
};
- display: display@di0 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "rgb24";
+ lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_disp0_1>;
status = "okay";
+ };
- port {
- display0_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
-
- display-timings {
- VGA {
- clock-frequency = <25200000>;
- hactive = <640>;
- vactive = <480>;
- hback-porch = <48>;
- hsync-len = <96>;
- hfront-porch = <16>;
- vback-porch = <31>;
- vsync-len = <2>;
- vfront-porch = <12>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ETV570 {
- clock-frequency = <25200000>;
- hactive = <640>;
- vactive = <480>;
- hback-porch = <114>;
- hsync-len = <30>;
- hfront-porch = <16>;
- vback-porch = <32>;
- vsync-len = <3>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0350 {
- clock-frequency = <6413760>;
- hactive = <320>;
- vactive = <240>;
- hback-porch = <34>;
- hsync-len = <34>;
- hfront-porch = <20>;
- vback-porch = <15>;
- vsync-len = <3>;
- vfront-porch = <4>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0430 {
- clock-frequency = <9009000>;
- hactive = <480>;
- vactive = <272>;
- hback-porch = <2>;
- hsync-len = <41>;
- hfront-porch = <2>;
- vback-porch = <2>;
- vsync-len = <10>;
- vfront-porch = <2>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <1>;
- };
-
- ET0500 {
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0700 { /* same as ET0500 */
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ETQ570 {
- clock-frequency = <6596040>;
- hactive = <320>;
- vactive = <240>;
- hback-porch = <38>;
- hsync-len = <30>;
- hfront-porch = <30>;
- vback-porch = <16>;
- vsync-len = <3>;
- vfront-porch = <4>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
- };
- };
-};
-
-&ipu1_di0_disp0 {
- remote-endpoint = <&display0_in>;
};
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts b/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts
index 9ed243b704ff..51d8b010bafc 100644
--- a/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts
+++ b/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts
@@ -47,10 +47,6 @@
model = "Ka-Ro electronics TX6Q-1020 Module on CoMpact TFT";
compatible = "karo,imx6q-tx6q", "fsl,imx6q";
- aliases {
- display = &display;
- };
-
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 500000 0>;
@@ -73,39 +69,15 @@
default-brightness-level = <50>;
};
- display: display@di0 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "rgb24";
+ lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_disp0_1>;
status = "okay";
-
- port {
- display0_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
-
- display-timings {
- native-mode = <&ET070001DM6>;
-
- ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <1>;
- };
- };
- };
+ };
};
&can1 {
@@ -124,10 +96,6 @@
status = "disabled";
};
-&ipu1_di0_disp0 {
- remote-endpoint = <&display0_in>;
-};
-
&kpp {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020.dts b/arch/arm/boot/dts/imx6q-tx6q-1020.dts
index 347b531d3763..a3a87cc41295 100644
--- a/arch/arm/boot/dts/imx6q-tx6q-1020.dts
+++ b/arch/arm/boot/dts/imx6q-tx6q-1020.dts
@@ -47,10 +47,6 @@
model = "Ka-Ro electronics TX6Q-1020 Module";
compatible = "karo,imx6q-tx6q", "fsl,imx6q";
- aliases {
- display = &display;
- };
-
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
@@ -73,133 +69,15 @@
default-brightness-level = <50>;
};
- display: display@di0 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "rgb24";
+ lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_disp0_1>;
status = "okay";
-
- port {
- display0_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
-
- display-timings {
- VGA {
- clock-frequency = <25200000>;
- hactive = <640>;
- vactive = <480>;
- hback-porch = <48>;
- hsync-len = <96>;
- hfront-porch = <16>;
- vback-porch = <31>;
- vsync-len = <2>;
- vfront-porch = <12>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ETV570 {
- clock-frequency = <25200000>;
- hactive = <640>;
- vactive = <480>;
- hback-porch = <114>;
- hsync-len = <30>;
- hfront-porch = <16>;
- vback-porch = <32>;
- vsync-len = <3>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0350 {
- clock-frequency = <6413760>;
- hactive = <320>;
- vactive = <240>;
- hback-porch = <34>;
- hsync-len = <34>;
- hfront-porch = <20>;
- vback-porch = <15>;
- vsync-len = <3>;
- vfront-porch = <4>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0430 {
- clock-frequency = <9009000>;
- hactive = <480>;
- vactive = <272>;
- hback-porch = <2>;
- hsync-len = <41>;
- hfront-porch = <2>;
- vback-porch = <2>;
- vsync-len = <10>;
- vfront-porch = <2>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <1>;
- };
-
- ET0500 {
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ET0700 { /* same as ET0500 */
- clock-frequency = <33264000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hsync-len = <128>;
- hfront-porch = <40>;
- vback-porch = <33>;
- vsync-len = <2>;
- vfront-porch = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
-
- ETQ570 {
- clock-frequency = <6596040>;
- hactive = <320>;
- vactive = <240>;
- hback-porch = <38>;
- hsync-len = <30>;
- hfront-porch = <30>;
- vback-porch = <16>;
- vsync-len = <3>;
- vfront-porch = <4>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
- };
- };
+ };
};
&ds1339 {
@@ -210,10 +88,6 @@
status = "disabled";
};
-&ipu1_di0_disp0 {
- remote-endpoint = <&display0_in>;
-};
-
&usdhc4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc4>;
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index e9a5d0b8c7b0..37647331f2c1 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -1,6 +1,6 @@
/*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-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
@@ -48,9 +48,15 @@
<&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>,
+ <&clks IMX6QDL_CLK_VPU_AXI_PODF>;
clock-names = "arm", "pll2_pfd2_396m", "step",
- "pll1_sw", "pll1_sys";
+ "pll1_sw", "pll1_sys", "pll1",
+ "pll1_bypass", "pll1_bypass_src",
+ "vpu_axi_podf";
arm-supply = <&reg_arm>;
pu-supply = <&reg_pu>;
soc-supply = <&reg_soc>;
@@ -78,10 +84,58 @@
};
};
+ 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@00900000 {
+ 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>;
+ };
+
+ 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 = <&gpc 1>;
+ };
+
+ ocram: sram@00905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x40000>;
+ reg = <0x00905000 0x3B000>;
clocks = <&clks IMX6QDL_CLK_OCRAM>;
};
@@ -107,6 +161,18 @@
};
};
+ aips-bus@02100000 { /* AIPS2 */
+ mipi_dsi: mipi@021e0000 {
+ compatible = "fsl,imx6q-mipi-dsi";
+ reg = <0x021e0000 0x4000>;
+ interrupts = <0 102 0x04>;
+ 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@02200000 {
compatible = "fsl,imx6q-ahci";
reg = <0x02200000 0x4000>;
@@ -137,9 +203,18 @@
<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>;
@@ -267,13 +342,20 @@
};
&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-aristainetos.dtsi b/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
index 54f4f0193f2b..d8e1bfb89f61 100644
--- a/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
@@ -3,6 +3,8 @@
*
* Copyright (C) 2014 Heiko Schocher <hs@denx.de>
*
+ * Copyright 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.
@@ -12,6 +14,13 @@
#include <dt-bindings/gpio/gpio.h>
/ {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ mxcfb2 = &mxcfb3;
+ mxcfb3 = &mxcfb4;
+ };
+
regulators {
compatible = "simple-bus";
#address-cells = <1>;
@@ -55,6 +64,53 @@
regulator-max-microvolt = <5000000>;
};
};
+
+ 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: lcd@0 {
+ compatible = "fsl,lcd";
+ status = "disabled";
+ };
};
&audmux {
diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
index ff41f83551de..03d7b4121368 100644
--- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2014 Russell King
*
+ * Copyright 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
* This file is dual-licensed: you can use it either under the terms
* of the GPL or the X11 license, at your option. Note that this dual
* licensing only applies to this file, and not this project as a
@@ -119,13 +121,6 @@
};
};
-&hdmi {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_cubox_i_hdmi>;
- ddc-i2c-bus = <&i2c2>;
- status = "okay";
-};
-
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
index afec2c7628ef..02cab60f133a 100644
--- a/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright 2013 Gateworks Corporation
*
+ * Copyright 2015 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:
@@ -19,6 +21,7 @@
nand = &gpmi;
usb0 = &usbh1;
usb1 = &usbotg;
+ mxcfb0 = &mxcfb1;
};
chosen {
@@ -89,6 +92,17 @@
enable-active-high;
};
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&fec {
@@ -105,8 +119,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c3>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -165,6 +186,11 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&pcie {
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
index a7100f99123e..45ef098793be 100644
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright 2013 Gateworks Corporation
*
+ * Copyright 2015 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:
@@ -21,6 +23,7 @@
ssi0 = &ssi1;
usb0 = &usbh1;
usb1 = &usbotg;
+ mxcfb0 = &mxcfb1;
};
chosen {
@@ -124,6 +127,17 @@
};
};
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
+
sound {
compatible = "fsl,imx6q-ventana-sgtl5000",
"fsl,imx-audio-sgtl5000";
@@ -180,8 +194,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c3>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -249,6 +270,11 @@
VDDIO-supply = <&reg_3p3v>;
};
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
touchscreen: egalax_ts@04 {
compatible = "eeti,egalax_ts";
reg = <0x04>;
diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
index 8953eba0573d..452ba93a3e2c 100644
--- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright 2013 Gateworks Corporation
*
+ * Copyright 2015 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:
@@ -22,6 +24,7 @@
ssi0 = &ssi1;
usb0 = &usbh1;
usb1 = &usbotg;
+ mxcfb0 = &mxcfb1;
};
chosen {
@@ -138,6 +141,17 @@
mux-int-port = <1>;
mux-ext-port = <4>;
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&audmux {
@@ -173,8 +187,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c3>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -242,6 +263,11 @@
VDDIO-supply = <&reg_3p3v>;
};
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
touchscreen: egalax_ts@04 {
compatible = "eeti,egalax_ts";
reg = <0x04>;
diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
index 6ac41c7ed32e..4c6c1b92b5a6 100644
--- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright 2013 Gateworks Corporation
*
+ * Copyright 2015 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:
@@ -22,6 +24,7 @@
ssi0 = &ssi1;
usb0 = &usbh1;
usb1 = &usbotg;
+ mxcfb0 = &mxcfb1;
};
chosen {
@@ -128,6 +131,17 @@
mux-int-port = <1>;
mux-ext-port = <4>;
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&audmux {
@@ -163,8 +177,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c3>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -333,6 +354,11 @@
VDDIO-supply = <&reg_3p3v>;
};
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
touchscreen: egalax_ts@04 {
compatible = "eeti,egalax_ts";
reg = <0x04>;
diff --git a/arch/arm/boot/dts/imx6qdl-gw552x.dtsi b/arch/arm/boot/dts/imx6qdl-gw552x.dtsi
index 805e23674a94..ff0da13f649a 100644
--- a/arch/arm/boot/dts/imx6qdl-gw552x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw552x.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright 2014 Gateworks Corporation
*
+ * Copyright 2015 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:
@@ -20,6 +22,7 @@
nand = &gpmi;
usb0 = &usbh1;
usb1 = &usbotg;
+ mxcfb0 = &mxcfb1;
};
chosen {
@@ -87,6 +90,17 @@
regulator-always-on;
};
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&gpmi {
@@ -95,8 +109,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c3>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -155,6 +176,11 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&pcie {
diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
index d6c2358ffad4..d3b0b20aa05b 100644
--- a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2013,2014 Russell King
*
+ * Copyright 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
* This file is dual-licensed: you can use it either under the terms
* of the GPL or the X11 license, at your option. Note that this dual
* licensing only applies to this file, and not this project as a
@@ -42,6 +44,10 @@
#include "imx6qdl-microsom-ar8035.dtsi"
/ {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ };
+
chosen {
stdout-path = &uart1;
};
@@ -107,6 +113,17 @@
spdif-controller = <&spdif>;
spdif-out;
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&audmux {
@@ -119,10 +136,15 @@
status = "okay";
};
-&hdmi {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hummingboard_hdmi>;
- ddc-i2c-bus = <&i2c2>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -154,6 +176,11 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hummingboard_i2c2>;
status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&iomuxc {
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
index db868bc42c0f..e002dc76824e 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -1,6 +1,6 @@
/*
* Copyright 2013 Boundary Devices, Inc.
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* This file is dual-licensed: you can use it either under the terms
@@ -44,6 +44,10 @@
#include <dt-bindings/input/input.h>
/ {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ };
+
chosen {
stdout-path = &uart2;
};
@@ -232,6 +236,17 @@
};
};
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&audmux {
@@ -291,8 +306,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c2>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -321,6 +343,11 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&i2c3 {
diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
index 585b4f6986c1..044d46ec99e2 100644
--- a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
*
+ * Copyright 2015 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:
@@ -12,6 +14,10 @@
#include <dt-bindings/sound/fsl-imx-audmux.h>
/ {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ };
+
chosen {
linux,stdout-path = &uart4;
};
@@ -76,6 +82,17 @@
};
};
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
+
};
&audmux {
@@ -109,7 +126,15 @@
status = "okay";
};
-&hdmi {
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-rex.dtsi b/arch/arm/boot/dts/imx6qdl-rex.dtsi
index 17704a5c1bcb..08596ca6f7fe 100644
--- a/arch/arm/boot/dts/imx6qdl-rex.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-rex.dtsi
@@ -1,6 +1,8 @@
/*
* Copyright 2014 FEDEVEL, Inc.
*
+ * Copyright 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
* Author: Robert Nelson <robertcnelson@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -13,6 +15,10 @@
#include <dt-bindings/input/input.h>
/ {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ };
+
chosen {
stdout-path = &uart1;
};
@@ -80,6 +86,17 @@
mux-int-port = <1>;
mux-ext-port = <3>;
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&audmux {
@@ -112,8 +129,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c2>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -138,6 +162,11 @@
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
eeprom@57 {
compatible = "at,24c02";
reg = <0x57>;
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index e000e6f12bf5..d8a96b5848c3 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -11,9 +11,58 @@
*/
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
/ {
- memory {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ mxcfb2 = &mxcfb3;
+ mxcfb3 = &mxcfb4;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys1";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ home {
+ label = "Home";
+ gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ linux,code = <KEY_HOME>;
+ };
+
+ back {
+ label = "Back";
+ gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ linux,code = <KEY_BACK>;
+ };
+
+ program {
+ label = "Program";
+ gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ linux,code = <KEY_PROGRAM>;
+ };
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio2 15 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio5 14 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
+ memory: memory {
reg = <0x10000000 0x80000000>;
};
@@ -50,6 +99,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@1 {
compatible = "regulator-fixed";
reg = <1>;
@@ -69,28 +126,159 @@
gpio = <&max7310_c 1 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
+
+ reg_si4763_vio1: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "vio1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_si4763_vio2: regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "vio2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_si4763_vd: regulator@5 {
+ compatible = "regulator-fixed";
+ reg = <5>;
+ regulator-name = "vd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_si4763_va: regulator@6 {
+ compatible = "regulator-fixed";
+ reg = <6>;
+ regulator-name = "va";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_sd3_vmmc: regulator@7 {
+ compatible = "regulator-fixed";
+ regulator-name = "P3V3_SDa_SWITCHED";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio7 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ off-on-delay = <20000>;
+ /* remove below line to enable this regulator */
+ status = "disabled";
+ };
+
+ reg_can_en: regulator@8 {
+ compatible = "regulator-fixed";
+ reg = <8>;
+ regulator-name = "can-en";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&max7310_b 6 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can_stby: regulator@9 {
+ compatible = "regulator-fixed";
+ reg = <9>;
+ regulator-name = "can-stby";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&max7310_b 5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&reg_can_en>;
+ };
+ };
+
+ hannstar_cabc {
+ compatible = "hannstar,cabc";
+
+ lvds_share {
+ gpios = <&max7310_a 0 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ 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";
+ };
+
+ clocks {
+ codec_osc: anaclk2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24576000>;
+ };
};
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-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 {
@@ -108,6 +296,25 @@
default-brightness-level = <7>;
status = "okay";
};
+
+ 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";
};
&clks {
@@ -118,11 +325,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 {
fsl,spi-num-chipselects = <1>;
cs-gpios = <&gpio3 19 0>;
@@ -153,19 +372,52 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet>;
phy-mode = "rgmii";
- interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
- <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,magic-packet;
fsl,err006687-workaround-present;
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 */
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
+ status = "disabled"; /* pin conflict with uart3 */
+ nand-on-flash-bbt;
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_cec>;
+ status = "okay";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <1>;
status = "okay";
};
-&hdmi {
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -175,6 +427,16 @@
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+ egalax_ts@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_egalax_int>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <28 2>;
+ wakeup-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>;
+ };
+
pmic: pfuze100@08 {
compatible = "fsl,pfuze100";
reg = <0x08>;
@@ -274,6 +536,11 @@
};
};
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
codec: cs42888@48 {
compatible = "cirrus,cs42888";
reg = <0x48>;
@@ -285,6 +552,19 @@
VLC-supply = <&reg_audio>;
};
+ 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";
+ };
+ };
};
&i2c3 {
@@ -292,6 +572,32 @@
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
+ adv7180: adv7180@21 {
+ compatible = "adv,adv7180";
+ reg = <0x21>;
+ 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>;
+ };
+
+ isl29023@44 {
+ compatible = "fsl,isl29023";
+ reg = <0x44>;
+ rext = <499>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <17 2>;
+ };
+
max7310_a: gpio@30 {
compatible = "maxim,max7310";
reg = <0x30>;
@@ -312,6 +618,23 @@
gpio-controller;
#gpio-cells = <2>;
};
+
+ mag3110@0e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ position = <2>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <29 1>;
+ };
+
+ mma8451@1c {
+ compatible = "fsl,mma8451";
+ reg = <0x1c>;
+ position = <7>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <31 8>;
+ interrupt-route = <1>;
+ };
};
&iomuxc {
@@ -319,11 +642,27 @@
pinctrl-0 = <&pinctrl_hog>;
imx6qdl-sabreauto {
+ 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_hog: hoggrp {
fsl,pins = <
- MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1f059
MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x80000000
MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059
+ MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x80000000
+ MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x80000000
+ MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x80000000
+ MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x80000000
+ MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x80000000
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
+ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x17059
+ MX6QDL_PAD_GPIO_1__GPIO1_IO01 0x17059
>;
};
@@ -341,6 +680,12 @@
>;
};
+ pinctrl_egalax_int: egalax_intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x80000000
+ >;
+ };
+
pinctrl_enet: enetgrp {
fsl,pins = <
MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
@@ -358,6 +703,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
>;
};
@@ -377,6 +728,30 @@
>;
};
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x17059
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x17059
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x17059
+ MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x17059
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x1b0b0
+ MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x1b0b0
+ MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0
+ MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0
+ MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14 0x1b0b0
+ >;
+ };
+
pinctrl_gpio_leds: gpioledsgrp {
fsl,pins = <
MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x80000000
@@ -412,6 +787,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
@@ -419,6 +818,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
@@ -431,6 +838,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
@@ -444,6 +869,17 @@
>;
};
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17071
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10071
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17071
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17071
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17071
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17071
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
@@ -542,6 +978,12 @@
MX6QDL_PAD_EIM_DA0__EIM_AD00 0xb0b1
>;
};
+
+ pinctrl_hdmi_cec: hdmicecgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0
+ >;
+ };
};
};
@@ -551,6 +993,7 @@
lvds-channel@0 {
fsl,data-mapping = "spwg";
fsl,data-width = <18>;
+ primary;
status = "okay";
display-timings {
@@ -568,6 +1011,33 @@
};
};
};
+
+ 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>;
+ };
+ };
+ };
+};
+
+&mlb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mlb>;
+ status = "okay";
};
&pwm3 {
@@ -576,12 +1046,44 @@
status = "okay";
};
+&pcie {
+ status = "okay";
+};
+
&spdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spdif>;
+ assigned-clocks = <&clks IMX6QDL_CLK_SPDIF_SEL>,
+ <&clks IMX6QDL_CLK_SPDIF_PODF>;
+ assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_PFD3_454M>;
+ assigned-clock-rates = <0>, <227368421>;
status = "okay";
};
+&snvs_poweroff {
+ 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>;
@@ -597,6 +1099,19 @@
vbus-supply = <&reg_usb_otg_vbus>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbotg>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
status = "okay";
};
@@ -607,6 +1122,20 @@
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
cd-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+ /*
+ * Due to board issue, we can not use external regulator for card slot
+ * by default since the card power is shared with card detect pullup.
+ * Disabling the vmmc regulator will cause unexpected card detect
+ * interrupts.
+ * HW rework is needed to fix this isssue. Remove R695 first, then you
+ * can open below line to enable the using of external regulator.
+ * Then you will be able to power off the card during suspend. This is
+ * especially needed for a SD3.0 card re-enumeration working on UHS mode
+ * Note: reg_sd3_vmmc is also need to be enabled
+ */
+ /* vmmc-supply = <&reg_sd3_vmmc>; */
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
index 81dd6cd1937d..bee1fffb9d3b 100644
--- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* This file is dual-licensed: you can use it either under the terms
@@ -277,11 +277,6 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c2>;
- status = "okay";
-};
-
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
@@ -586,6 +581,9 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbotg>;
disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
status = "okay";
};
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..7164a9e44bc1
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+/*
+ * NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into SD2
+ * slot using Murata i.MX InterConnect Ver 2.0 Adapter & connecting Bluetooth
+ * UART & control signals via ribbon cable.
+ * This configuration supports both WLAN and Bluetooth.
+ * WL_REG_ON/BT_REG_ON/WL_HOST_WAKE are connected via ribbon cable (J13 connector
+ * on board).
+ * ==> Hardware modification is required. Refer to schematic.
+ */
+
+/ {
+ 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>;
+ };
+
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio4 7 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ gpios = <&gpio4 6 0>; /* WL_HOST_WAKE */
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&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 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x13069 /* WL_REG_ON */
+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x13069 /* 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 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host;
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 8e9e0d98db2f..1f9f7a42f9dd 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2016 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -14,11 +14,51 @@
#include <dt-bindings/input/input.h>
/ {
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ mxcfb2 = &mxcfb3;
+ mxcfb3 = &mxcfb4;
+ };
+
+ 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";
+ };
+
+ hannstar_cabc {
+ compatible = "hannstar,cabc";
+ lvds0 {
+ gpios = <&gpio6 15 GPIO_ACTIVE_HIGH>;
+ };
+ lvds1 {
+ gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
chosen {
stdout-path = &uart1;
};
- memory {
+ leds {
+ compatible = "gpio-leds";
+
+ charger-led {
+ gpios = <&gpio1 2 0>;
+ linux,default-trigger = "max8903-charger-charging";
+ retain-state-suspended;
+ };
+ };
+
+ memory: memory {
reg = <0x10000000 0x40000000>;
};
@@ -69,6 +109,34 @@
regulator-always-on;
enable-active-high;
};
+
+ reg_sensor: regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "sensor-supply";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 31 0>;
+ startup-delay-us = <500>;
+ enable-active-high;
+ };
+
+ reg_hdmi: regulator@5 {
+ compatible = "regulator-fixed";
+ reg = <5>;
+ 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 {
@@ -102,20 +170,89 @@
compatible = "fsl,imx6q-sabresd-wm8962",
"fsl,imx-audio-wm8962";
model = "wm8962-audio";
- ssi-controller = <&ssi2>;
+ cpu-dai = <&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";
};
- backlight_lvds: backlight-lvds {
+ lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1>;
+ status = "okay";
+ };
+
+ backlight {
compatible = "pwm-backlight";
pwms = <&pwm1 0 5000000>;
brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -123,26 +260,25 @@
status = "okay";
};
- leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpio_leds>;
-
- red {
- gpios = <&gpio1 2 0>;
- default-state = "on";
- };
+ v4l2_cap_0 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <0>;
+ mclk_source = <0>;
+ status = "okay";
};
- panel {
- compatible = "hannstar,hsd100pxn1";
- backlight = <&backlight_lvds>;
+ v4l2_cap_1 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk_source = <0>;
+ status = "okay";
+ };
- port {
- panel_in: endpoint {
- remote-endpoint = <&lvds0_out>;
- };
- };
+ v4l2_out {
+ compatible = "fsl,mxc_v4l2_output";
+ status = "okay";
};
};
@@ -155,8 +291,11 @@
&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>;
+};
+
+&clks {
};
&ecspi1 {
@@ -180,11 +319,46 @@
pinctrl-0 = <&pinctrl_enet>;
phy-mode = "rgmii";
phy-reset-gpios = <&gpio1 25 0>;
+ fsl,magic-packet;
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c2>;
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&dcic1 {
+ dcic_id = <0>;
+ dcic_mux = "dcic-hdmi";
+ status = "okay";
+};
+
+&dcic2 {
+ dcic_id = <1>;
+ dcic_mux = "dcic-lvds1";
+ status = "okay";
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_cec>;
+ status = "okay";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
+ HDMI-supply = <&reg_hdmi>;
status = "okay";
};
@@ -214,15 +388,66 @@
0x8014 /* 4:FN_DMICCDAT */
0x0000 /* 5:Default */
>;
+ amic-mono;
};
+
+ mma8451@1c {
+ compatible = "fsl,mma8451";
+ reg = <0x1c>;
+ position = <0>;
+ vdd-supply = <&reg_sensor>;
+ vddio-supply = <&reg_sensor>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <18 8>;
+ interrupt-route = <1>;
+ };
+
+ 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";
+ egalax_ts@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2_egalax_int>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <8 2>;
+ 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*/
+ };
+
pmic: pfuze100@08 {
compatible = "fsl,pfuze100";
reg = <0x08>;
@@ -322,6 +547,27 @@
};
};
};
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+
+ ov564x_mipi: ov564x_mipi@3c { /* i2c2 driver */
+ compatible = "ovti,ov564x_mipi";
+ reg = <0x3c>;
+ clocks = <&clks 201>;
+ 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>;
+ };
};
&i2c3 {
@@ -333,9 +579,30 @@
egalax_ts@04 {
compatible = "eeti,egalax_ts";
reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3_egalax_int>;
interrupt-parent = <&gpio6>;
interrupts = <7 2>;
- wakeup-gpios = <&gpio6 7 0>;
+ wakeup-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+ };
+
+ isl29023@44 {
+ compatible = "fsl,isl29023";
+ reg = <0x44>;
+ rext = <499>;
+ vdd-supply = <&reg_sensor>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <9 2>;
+ };
+
+ mag3110@0e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ position = <2>;
+ vdd-supply = <&reg_sensor>;
+ vddio-supply = <&reg_sensor>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <16 1>;
};
};
@@ -346,15 +613,29 @@
imx6qdl-sabresd {
pinctrl_hog: hoggrp {
fsl,pins = <
- MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
- MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
- MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
- MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x80000000
MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
- MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x1b0b0
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0
- MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000
+ 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_EIM_EB3__GPIO2_IO31 0x80000000
+ MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x80000000
+ MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x80000000
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x80000000
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
+ MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x80000000
>;
};
@@ -376,6 +657,18 @@
>;
};
+ pinctrl_i2c2_egalax_int: egalax_i2c2_intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x80000000
+ >;
+ };
+
+ pinctrl_i2c3_egalax_int: egalax_i2c3_intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x80000000
+ >;
+ };
+
pinctrl_enet: enetgrp {
fsl,pins = <
MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
@@ -397,6 +690,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
@@ -405,6 +704,19 @@
>;
};
+ pinctrl_hdmi_cec: hdmicecgrp {
+ fsl,pins = <
+ 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
+ >;
+ };
+
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
@@ -419,6 +731,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2_gpio_grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x1b0b0
+ MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x1b0b0
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
@@ -426,6 +745,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_pcie: pciegrp {
fsl,pins = <
MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0
@@ -451,6 +823,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
@@ -504,7 +894,7 @@
pinctrl_wdog: wdoggrp {
fsl,pins = <
- MX6QDL_PAD_GPIO_1__WDOG2_B 0x1b0b0
+ MX6QDL_PAD_GPIO_1__WDOG2_B 0x80000000
>;
};
};
@@ -521,21 +911,68 @@
&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>;
+ };
+ };
+ };
- lvds0_out: endpoint {
- remote-endpoint = <&panel_in>;
+ lvds-channel@1 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ primary;
+ 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>;
};
};
};
};
+&mipi_csi {
+ status = "okay";
+ ipu_id = <0>;
+ csi_id = <1>;
+ v_channel = <0>;
+ lanes = <2>;
+};
+
+&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";
+};
+
&pcie {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcie>;
@@ -549,11 +986,30 @@
status = "okay";
};
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+};
+
+&reg_pu {
+ vin-supply = <&sw1c_reg>;
+};
+
+&reg_soc {
+ vin-supply = <&sw1c_reg>;
+};
+
&snvs_poweroff {
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 = <1179648000>, <0>, <0>;
status = "okay";
};
@@ -573,15 +1029,29 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbotg>;
disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
status = "okay";
};
+&usbphy1 {
+ tx-d-cal = <0x5>;
+};
+
+&usbphy2 {
+ tx-d-cal = <0x5>;
+};
+
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
bus-width = <8>;
cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
status = "okay";
};
@@ -591,6 +1061,9 @@
bus-width = <8>;
cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
status = "okay";
};
@@ -600,6 +1073,7 @@
bus-width = <8>;
non-removable;
no-1-8-v;
+ keep-power-in-suspend;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi
index c96c91d83678..6b4984feea93 100644
--- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-2015 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.com>
*
@@ -15,6 +15,7 @@
panelchan = &panelchan;
panel7 = &panel7;
touchscreenp7 = &touchscreenp7;
+ mxcfb0 = &mxcfb1;
};
chosen {
@@ -89,6 +90,17 @@
mux-int-port = <1>;
mux-ext-port = <6>;
};
+
+ mxcfb1: fb@0 {
+ 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 = "okay";
+ };
};
&fec {
@@ -98,8 +110,15 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c2>;
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "okay";
};
@@ -108,6 +127,11 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+
+ hdmi_edid: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&i2c3 {
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index 2b9c2be436f9..0fb20cd3157e 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-2015 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.com>
*
@@ -64,11 +64,6 @@
status = "okay";
};
-&hdmi {
- ddc-i2c-bus = <&i2c1>;
- status = "okay";
-};
-
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index b13b0b2db881..b64e7830fced 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2016 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -78,6 +78,11 @@
interrupt-parent = <&gpc>;
ranges;
+ caam_sm: caam-sm@00100000 {
+ compatible = "fsl,imx6q-caam-sm";
+ reg = <0x00100000 0x3fff>;
+ };
+
dma_apbh: dma-apbh@00110000 {
compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
reg = <0x00110000 0x2000>;
@@ -91,6 +96,16 @@
clocks = <&clks IMX6QDL_CLK_APBH_DMA>;
};
+ irq_sec_vio: caam_secvio {
+ compatible = "fsl,imx6q-caam-secvio";
+ interrupts = <0 20 0x04>;
+ secvio_src = <0x8000001d>;
+ jtag-tamper = "disabled";
+ watchdog-tamper = "enabled";
+ internal-boot-tamper = "enabled";
+ external-pin-tamper = "disabled";
+ };
+
gpmi: gpmi-nand@00112000 {
compatible = "fsl,imx6q-gpmi-nand";
#address-cells = <1>;
@@ -160,6 +175,18 @@
power-domains = <&gpc 1>;
};
+ 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@00a00600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0x00a00600 0x20>;
@@ -211,6 +238,7 @@
<&clks IMX6QDL_CLK_LVDS1_GATE>,
<&clks IMX6QDL_CLK_PCIE_REF_125M>;
clock-names = "pcie", "pcie_bus", "pcie_phy";
+ fsl,max-link-speed = <2>;
status = "disabled";
};
@@ -219,6 +247,45 @@
interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
};
+ hdmi_core: hdmi_core@00120000 {
+ compatible = "fsl,imx6q-hdmi-core";
+ reg = <0x00120000 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@020e0000 {
+ compatible = "fsl,imx6q-hdmi-video";
+ reg = <0x020e0000 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@00120000 {
+ 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 25 0>;
+ dma-names = "tx";
+ status = "disabled";
+ };
+
+ hdmi_cec: hdmi_cec@00120000 {
+ compatible = "fsl,imx6q-hdmi-cec";
+ interrupts = <0 115 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
aips-bus@02000000 { /* AIPS1 */
compatible = "fsl,aips-bus", "simple-bus";
#address-cells = <1>;
@@ -243,7 +310,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",
@@ -262,7 +329,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";
};
@@ -276,7 +343,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";
};
@@ -290,7 +357,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";
};
@@ -304,7 +371,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";
};
@@ -346,8 +413,8 @@
clocks = <&clks IMX6QDL_CLK_SSI1_IPG>,
<&clks IMX6QDL_CLK_SSI1>;
clock-names = "ipg", "baud";
- dmas = <&sdma 37 1 0>,
- <&sdma 38 1 0>;
+ dmas = <&sdma 37 22 0>,
+ <&sdma 38 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
@@ -362,8 +429,8 @@
clocks = <&clks IMX6QDL_CLK_SSI2_IPG>,
<&clks IMX6QDL_CLK_SSI2>;
clock-names = "ipg", "baud";
- dmas = <&sdma 41 1 0>,
- <&sdma 42 1 0>;
+ dmas = <&sdma 41 22 0>,
+ <&sdma 42 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
@@ -378,8 +445,8 @@
clocks = <&clks IMX6QDL_CLK_SSI3_IPG>,
<&clks IMX6QDL_CLK_SSI3>;
clock-names = "ipg", "baud";
- dmas = <&sdma 45 1 0>,
- <&sdma 46 1 0>;
+ dmas = <&sdma 45 22 0>,
+ <&sdma 46 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
@@ -427,6 +494,24 @@
power-domains = <&gpc 1>;
resets = <&src 1>;
iram = <&ocram>;
+ status = "disabled";
+ };
+
+ vpu_fsl: vpu_fsl@02040000 {
+ compatible = "fsl,imx6-vpu";
+ reg = <0x02040000 0x3c000>;
+ reg-names = "vpu_regs";
+ interrupts = <0 3 IRQ_TYPE_EDGE_RISING>,
+ <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 = <&gpc 1>;
};
aipstz@0207c000 { /* AIPSTZ1 */
@@ -484,6 +569,7 @@
clocks = <&clks IMX6QDL_CLK_CAN1_IPG>,
<&clks IMX6QDL_CLK_CAN1_SERIAL>;
clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x34 28 0x10 17>;
status = "disabled";
};
@@ -494,6 +580,7 @@
clocks = <&clks IMX6QDL_CLK_CAN2_IPG>,
<&clks IMX6QDL_CLK_CAN2_SERIAL>;
clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x34 29 0x10 18>;
status = "disabled";
};
@@ -634,20 +721,21 @@
anatop-min-bit-val = <4>;
anatop-min-voltage = <800000>;
anatop-max-voltage = <1375000>;
+ anatop-enable-bit = <0>;
};
- regulator-3p0 {
+ reg_3p0: regulator-3p0@120 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd3p0";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <3150000>;
- regulator-always-on;
+ regulator-min-microvolt = <2625000>;
+ regulator-max-microvolt = <3400000>;
anatop-reg-offset = <0x120>;
anatop-vol-bit-shift = <8>;
anatop-vol-bit-width = <5>;
anatop-min-bit-val = <0>;
anatop-min-voltage = <2625000>;
anatop-max-voltage = <3400000>;
+ anatop-enable-bit = <0>;
};
regulator-2p5 {
@@ -662,6 +750,7 @@
anatop-min-bit-val = <0>;
anatop-min-voltage = <2000000>;
anatop-max-voltage = <2750000>;
+ anatop-enable-bit = <0>;
};
reg_arm: regulator-vddcore {
@@ -679,6 +768,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
reg_pu: regulator-vddpu {
@@ -696,6 +786,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
reg_soc: regulator-vddsoc {
@@ -713,6 +804,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
};
@@ -729,6 +821,7 @@
reg = <0x020c9000 0x1000>;
interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_USBPHY1>;
+ phy-3p0-supply = <&reg_3p0>;
fsl,anatop = <&anatop>;
};
@@ -737,9 +830,27 @@
reg = <0x020ca000 0x1000>;
interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_USBPHY2>;
+ phy-3p0-supply = <&reg_3p0>;
fsl,anatop = <&anatop>;
};
+ usbphy_nop1: usbphy_nop1 {
+ compatible = "usb-nop-xceiv";
+ clocks = <&clks IMX6QDL_CLK_USBPHY1>;
+ clock-names = "main_clk";
+ };
+
+ usbphy_nop2: usbphy_nop2 {
+ compatible = "usb-nop-xceiv";
+ clocks = <&clks IMX6QDL_CLK_USBPHY1>;
+ clock-names = "main_clk";
+ };
+
+ caam_snvs: caam-snvs@020cc000 {
+ compatible = "fsl,imx6q-caam-snvs";
+ reg = <0x020cc000 0x4000>;
+ };
+
snvs: snvs@020cc000 {
compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
reg = <0x020cc000 0x4000>;
@@ -756,7 +867,7 @@
compatible = "syscon-poweroff";
regmap = <&snvs>;
offset = <0x38>;
- mask = <0x60>;
+ mask = <0x61>;
status = "disabled";
};
};
@@ -793,7 +904,8 @@
<&clks IMX6QDL_CLK_GPU2D_CORE>,
<&clks IMX6QDL_CLK_GPU2D_AXI>,
<&clks IMX6QDL_CLK_OPENVG_AXI>,
- <&clks IMX6QDL_CLK_VPU_AXI>;
+ <&clks IMX6QDL_CLK_VPU_AXI>,
+ <&clks IMX6QDL_CLK_IPG>;
#power-domain-cells = <1>;
};
@@ -862,13 +974,23 @@
};
dcic1: dcic@020e4000 {
+ compatible = "fsl,imx6q-dcic";
reg = <0x020e4000 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@020e8000 {
+ compatible = "fsl,imx6q-dcic";
reg = <0x020e8000 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@020ec000 {
@@ -892,11 +1014,11 @@
crypto: caam@2100000 {
compatible = "fsl,sec-v4.0";
- fsl,sec-era = <4>;
#address-cells = <1>;
#size-cells = <1>;
reg = <0x2100000 0x10000>;
- ranges = <0 0x2100000 0x10000>;
+ ranges = <0 0x2100000 0x40000>;
+ interrupt-parent = <&intc>; /* interrupts = <0 92 0x4>; */
clocks = <&clks IMX6QDL_CLK_CAAM_MEM>,
<&clks IMX6QDL_CLK_CAAM_ACLK>,
<&clks IMX6QDL_CLK_CAAM_IPG>,
@@ -930,6 +1052,7 @@
ahb-burst-config = <0x0>;
tx-burst-size-dword = <0x10>;
rx-burst-size-dword = <0x10>;
+ fsl,anatop = <&anatop>;
status = "disabled";
};
@@ -957,6 +1080,9 @@
ahb-burst-config = <0x0>;
tx-burst-size-dword = <0x10>;
rx-burst-size-dword = <0x10>;
+ phy_type = "hsic";
+ fsl,usbphy = <&usbphy_nop1>;
+ fsl,anatop = <&anatop>;
status = "disabled";
};
@@ -970,6 +1096,9 @@
ahb-burst-config = <0x0>;
tx-burst-size-dword = <0x10>;
rx-burst-size-dword = <0x10>;
+ phy_type = "hsic";
+ fsl,usbphy = <&usbphy_nop2>;
+ fsl,anatop = <&anatop>;
status = "disabled";
};
@@ -984,20 +1113,28 @@
compatible = "fsl,imx6q-fec";
reg = <0x02188000 0x4000>;
interrupts-extended =
- <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
- <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+ <&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@0218c000 {
+ mlb: mlb@0218c000 {
+ 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>,
+ <&clks IMX6QDL_CLK_PLL8_MLB>;
+ clock-names = "mlb", "pll8_mlb";
+ iram = <&ocram>;
+ status = "disabled";
};
usdhc1: usdhc@02190000 {
@@ -1082,6 +1219,11 @@
reg = <0x021ac000 0x4000>;
};
+ mmdc0-1@021b0000 { /* MMDC0-1 */
+ compatible = "fsl,imx6q-mmdc-combine";
+ reg = <0x021b0000 0x8000>;
+ };
+
mmdc0: mmdc@021b0000 { /* MMDC0 */
compatible = "fsl,imx6q-mmdc";
reg = <0x021b0000 0x4000>;
@@ -1120,13 +1262,23 @@
status = "disabled";
};
- mipi_csi: mipi@021dc000 {
+ mipi_csi: mipi_csi@021dc000 { /* MIPI-CSI */
+ compatible = "fsl,imx6q-mipi-csi2";
reg = <0x021dc000 0x4000>;
+ interrupts = <0 100 0x04>, <0 101 0x04>;
+ clocks = <&clks IMX6QDL_CLK_HSI_TX>,
+ <&clks IMX6QDL_CLK_EIM_SEL>,
+ <&clks IMX6QDL_CLK_VIDEO_27M>;
+ /* Note: clks 138 is hsi_tx, however, the dphy_c
+ * hsi_tx and pll_refclk use the same clk gate.
+ * In current clk driver, open/close clk gate do
+ * use hsi_tx for a temporary debug purpose.
+ */
+ clock-names = "dphy_clk", "pixel_clk", "cfg_clk";
+ status = "disabled";
};
- mipi_dsi: mipi@021e0000 {
- #address-cells = <1>;
- #size-cells = <0>;
+ mipi@021e0000 { /* MIPI-DSI */
reg = <0x021e0000 0x4000>;
status = "disabled";
@@ -1153,8 +1305,11 @@
};
vdoa@021e4000 {
+ compatible = "fsl,imx6q-vdoa";
reg = <0x021e4000 0x4000>;
interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_VDOA>;
+ iram = <&ocram>;
};
uart2: serial@021e8000 {
@@ -1214,10 +1369,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..8846739a5558
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabreauto-ecspi.dts
@@ -0,0 +1,40 @@
+/*
+ * 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"
+
+&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..b91ebad61116
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabreauto-gpmi-weim.dts
@@ -0,0 +1,50 @@
+/*
+ * 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"
+
+&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 5ce3840d83d3..59778f046cce 100644
--- a/arch/arm/boot/dts/imx6qp-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6qp-sabreauto.dts
@@ -50,6 +50,40 @@
compatible = "fsl,imx6qp-sabreauto", "fsl,imx6qp";
};
+&ldb {
+ lvds-channel@0 {
+ crtc = "ipu2-di0";
+ };
+
+ lvds-channel@1 {
+ crtc = "ipu2-di1";
+ };
+};
+
+&mxcfb1 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb2 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb3 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb4 {
+ prefetch;
+ status = "okay";
+};
+
+&fec {
+ pinctrl-assert-gpios = <&max7322 0 GPIO_ACTIVE_HIGH>;
+};
+
&i2c2 {
max7322: gpio@68 {
compatible = "maxim,max7322";
@@ -59,33 +93,47 @@
};
};
-&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";
+&pre1 {
+ status = "okay";
+};
+
+&pre2 {
+ status = "okay";
+};
+
+&pre3 {
+ status = "okay";
+};
+
+&pre4 {
+ status = "okay";
+};
+
+&prg1 {
+ memory-region = <&memory>;
+ status = "okay";
+};
+
+&prg2 {
+ memory-region = <&memory>;
+ status = "okay";
+};
+
+&reg_sd3_vmmc {
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
+
+&usdhc3 {
+ vmmc-supply = <&reg_sd3_vmmc>;
};
&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..38d39cab570c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabresd-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 "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-pcie-cert.dts b/arch/arm/boot/dts/imx6qp-sabresd-ldo-pcie-cert.dts
new file mode 100644
index 000000000000..da6b11773680
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabresd-ldo-pcie-cert.dts
@@ -0,0 +1,21 @@
+/*
+ * 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 "imx6qp-sabresd-ldo.dts"
+
+&fec {
+ status = "disabled";
+};
+
+&pcie {
+ ext_osc = <1>;
+};
+
+&sata {
+ status = "disabled";
+};
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..946fa2cf96bf
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-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 "imx6qp-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/imx6qp-sabresd.dts b/arch/arm/boot/dts/imx6qp-sabresd.dts
index b23458062f5e..59636a0bad9f 100644
--- a/arch/arm/boot/dts/imx6qp-sabresd.dts
+++ b/arch/arm/boot/dts/imx6qp-sabresd.dts
@@ -50,8 +50,8 @@
compatible = "fsl,imx6qp-sabresd", "fsl,imx6qp";
};
-&cpu0 {
- arm-supply = <&sw2_reg>;
+&reg_arm {
+ vin-supply = <&sw2_reg>;
};
&iomuxc {
@@ -88,6 +88,112 @@
};
};
+&iomuxc {
+ imx6qdl-sabresd {
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10071
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
+ MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
+ MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
+ MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10071
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ >;
+ };
+ };
+};
+
+&ldb {
+ lvds-channel@0 {
+ crtc = "ipu2-di0";
+ };
+
+ lvds-channel@1 {
+ crtc = "ipu2-di1";
+ };
+};
+
+&mxcfb1 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb2 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb3 {
+ prefetch;
+ status = "okay";
+};
+
+&mxcfb4 {
+ prefetch;
+ status = "okay";
+};
+
+&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";
+ pcie-bus-supply = <&vgen3_reg>; /* 1.8v pwr up pcie ext osc on revb */
+ reset-gpio = <&gpio7 12 0>;
+ 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";
+};
+
+&sata {
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qp.dtsi b/arch/arm/boot/dts/imx6qp.dtsi
index 886dbf2eca49..087e3fbe39f5 100644
--- a/arch/arm/boot/dts/imx6qp.dtsi
+++ b/arch/arm/boot/dts/imx6qp.dtsi
@@ -43,6 +43,15 @@
#include "imx6q.dtsi"
/ {
+ aliases {
+ pre0 = &pre1;
+ pre1 = &pre2;
+ pre2 = &pre3;
+ pre3 = &pre4;
+ prg0 = &prg1;
+ prg1 = &prg2;
+ };
+
soc {
ocram2: sram@00940000 {
compatible = "mmio-sram";
@@ -56,12 +65,95 @@
clocks = <&clks IMX6QDL_CLK_OCRAM>;
};
+ pcie: pcie@0x01000000 {
+ compatible = "fsl,imx6qp-pcie", "snps,dw-pcie";
+ reg = <0x01ffc000 0x4000>, <0x01f00000 0x80000>;
+ reg-names = "dbi", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x81000000 0 0 0x01f80000 0 0x00010000 /* downstream I/O */
+ 0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
+ num-lanes = <1>;
+ interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 123 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 122 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 121 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_PCIE_REF_125M>, <&clks IMX6QDL_PLL6_BYPASS>,
+ <&clks IMX6QDL_PLL6_BYPASS_SRC>,
+ <&clks IMX6QDL_CLK_LVDS1_GATE>, <&clks IMX6QDL_CLK_PCIE_AXI>;
+ clock-names = "pcie_phy", "pcie_ext", "pcie_ext_src", "pcie_bus", "pcie";
+ status = "disabled";
+ };
+
+ aips-bus@02100000 { /* AIPS2 */
+ pre1: pre@021c8000 {
+ compatible = "fsl,imx6q-pre";
+ reg = <0x021c8000 0x1000>;
+ clocks = <&clks IMX6QDL_CLK_PRE0>;
+ interrupts = <0 90 IRQ_TYPE_EDGE_RISING>;
+ ocram = <&ocram2>;
+ status = "disabled";
+ };
+
+ pre2: pre@021c9000 {
+ compatible = "fsl,imx6q-pre";
+ reg = <0x021c9000 0x1000>;
+ clocks = <&clks IMX6QDL_CLK_PRE1>;
+ interrupts = <0 97 IRQ_TYPE_EDGE_RISING>;
+ ocram = <&ocram2>;
+ status = "disabled";
+ };
+
+ pre3: pre@021ca000 {
+ compatible = "fsl,imx6q-pre";
+ reg = <0x021ca000 0x1000>;
+ clocks = <&clks IMX6QDL_CLK_PRE2>;
+ interrupts = <0 98 IRQ_TYPE_EDGE_RISING>;
+ ocram = <&ocram3>;
+ status = "disabled";
+ };
+
+ pre4: pre@021cb000 {
+ compatible = "fsl,imx6q-pre";
+ reg = <0x021cb000 0x1000>;
+ clocks = <&clks IMX6QDL_CLK_PRE3>;
+ interrupts = <0 99 IRQ_TYPE_EDGE_RISING>;
+ ocram = <&ocram3>;
+ status = "disabled";
+ };
+
+ prg1: prg@021cc000 {
+ compatible = "fsl,imx6q-prg";
+ reg = <0x021cc000 0x1000>;
+ clocks = <&clks IMX6QDL_CLK_PRG0_AXI>,
+ <&clks IMX6QDL_CLK_PRG0_APB>;
+ clock-names = "axi", "apb";
+ gpr = <&gpr>;
+ status = "disabled";
+ };
+
+ prg2: prg@021cd000 {
+ compatible = "fsl,imx6q-prg";
+ reg = <0x021cd000 0x1000>;
+ clocks = <&clks IMX6QDL_CLK_PRG1_AXI>,
+ <&clks IMX6QDL_CLK_PRG1_APB>;
+ clock-names = "axi", "apb";
+ gpr = <&gpr>;
+ status = "disabled";
+ };
+ };
+
ipu1: ipu@02400000 {
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_PODF>, <&clks IMX6QDL_CLK_LDB_DI1_PODF>,
+ <&clks IMX6QDL_CLK_LDB_DI0_DIV_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_DIV_SEL>,
<&clks IMX6QDL_CLK_PRG0_APB>;
clock-names = "bus",
"di0", "di1",
@@ -74,16 +166,17 @@
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_PODF>, <&clks IMX6QDL_CLK_LDB_DI1_PODF>,
+ <&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";
};
-
- pcie: pcie@0x01000000 {
- compatible = "fsl,imx6qp-pcie", "snps,dw-pcie";
- };
};
};
+
+&ldb {
+ compatible = "fsl,imx6qp-ldb", "fsl,imx6q-ldb", "fsl,imx53-ldb";
+};
+
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..4eac83e12cf2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-evk-btwifi.dts
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+/* 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>;
+ };
+
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio5 16 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ gpios = <&gpio5 20 0>; /* WL_HOST_WAKE */
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&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 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host;
+};
+
+&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..56d824b60e41
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-evk-csi.dts
@@ -0,0 +1,21 @@
+/*
+ * 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 "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..a230e217222c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-evk-ldo.dts
@@ -0,0 +1,27 @@
+
+/*
+ * 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 be118820e9f7..be64521b3fa4 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -16,6 +16,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";
+ };
+
memory {
reg = <0x80000000 0x40000000>;
};
@@ -39,6 +52,11 @@
};
};
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
regulators {
compatible = "simple-bus";
#address-cells = <1>;
@@ -96,7 +114,7 @@
sound {
compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
model = "wm8962-audio";
- ssi-controller = <&ssi2>;
+ cpu-dai = <&ssi2>;
audio-codec = <&codec>;
audio-routing =
"Headphone Jack", "HPOUTL",
@@ -107,6 +125,23 @@
"IN3R", "AMIC";
mux-int-port = <2>;
mux-ext-port = <3>;
+ codec-master;
+ hp-det-gpios = <&gpio4 19 1>;
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif",
+ "fsl,imx6sl-evk-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-out;
+ };
+
+ sii902x_reset: sii902x-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio2 19 1>;
+ reset-delay-us = <100000>;
+ #reset-cells = <0>;
};
};
@@ -116,6 +151,29 @@
status = "okay";
};
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_pu {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&csi {
+ port {
+ csi_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
&ecspi1 {
fsl,spi-num-chipselects = <1>;
cs-gpios = <&gpio4 11 0>;
@@ -132,6 +190,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>;
@@ -140,6 +207,10 @@
status = "okay";
};
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
@@ -245,6 +316,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";
+ };
+
+ mma8450@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 {
@@ -265,6 +419,45 @@
PLLVDD-supply = <&vgen3_reg>;
SPKVDD1-supply = <&reg_aud4v>;
SPKVDD2-supply = <&reg_aud4v>;
+ amic-mono;
+ };
+
+ sii902x@39 {
+ compatible = "SiI,sii902x";
+ interrupt-parent = <&gpio2>;
+ interrupts = <10 2>;
+ mode_str ="1280x720M@60";
+ bits-per-pixel = <16>;
+ resets = <&sii902x_reset>;
+ reg = <0x39>;
+ };
+};
+
+&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>;
+ };
+ };
};
};
@@ -283,6 +476,17 @@
MX6SL_PAD_KEY_COL4__GPIO4_IO00 0x80000000
MX6SL_PAD_KEY_COL5__GPIO4_IO02 0x80000000
MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
+ 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
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO2_IO10 0x17000
+ MX6SL_PAD_EPDC_PWRCTRL2__GPIO2_IO09 0x80000000
+ MX6SL_PAD_KEY_COL6__GPIO4_IO04 0x110b0
+ MX6SL_PAD_LCD_RESET__GPIO2_IO19 0x1b0b0
+ MX6SL_PAD_ECSPI2_MISO__GPIO4_IO14 0x17000
+ MX6SL_PAD_ECSPI2_MOSI__GPIO4_IO13 0x17000
+ MX6SL_PAD_ECSPI2_SS0__GPIO4_IO15 0x17000
>;
};
@@ -304,6 +508,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
@@ -346,6 +583,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
@@ -357,7 +601,7 @@
>;
};
- pinctrl_lcd: lcdgrp {
+ pinctrl_lcdif_dat: lcdifdatgrp {
fsl,pins = <
MX6SL_PAD_LCD_DAT0__LCD_DATA00 0x1b0b0
MX6SL_PAD_LCD_DAT1__LCD_DATA01 0x1b0b0
@@ -383,6 +627,11 @@
MX6SL_PAD_LCD_DAT21__LCD_DATA21 0x1b0b0
MX6SL_PAD_LCD_DAT22__LCD_DATA22 0x1b0b0
MX6SL_PAD_LCD_DAT23__LCD_DATA23 0x1b0b0
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
MX6SL_PAD_LCD_CLK__LCD_CLK 0x1b0b0
MX6SL_PAD_LCD_ENABLE__LCD_ENABLE 0x1b0b0
MX6SL_PAD_LCD_HSYNC__LCD_HSYNC 0x1b0b0
@@ -402,6 +651,12 @@
>;
};
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_DAT4__SPDIF_OUT 0x80000000
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1
@@ -409,6 +664,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
@@ -525,9 +798,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>;
@@ -546,13 +844,14 @@
&lcdif {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_lcd>;
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
lcd-supply = <&reg_lcd_3v3>;
display = <&display0>;
status = "okay";
- display0: display0 {
- bits-per-pixel = <32>;
+ display0: display@0 {
+ bits-per-pixel = <16>;
bus-width = <24>;
display-timings {
@@ -586,7 +885,21 @@
status = "okay";
};
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif>;
+ assigned-clocks = <&clks IMX6SL_CLK_SPDIF0_SEL>,
+ <&clks IMX6SL_CLK_SPDIF0_PODF>;
+ assigned-clock-parents = <&clks IMX6SL_CLK_PLL3_PFD3>;
+ assigned-clock-rates = <0>, <227368421>;
+ status = "okay";
+};
+
&ssi2 {
+ fsl,mode = "i2s-slave";
+ assigned-clocks = <&clks IMX6SL_CLK_SSI2_SEL>,
+ <&clks IMX6SL_CLK_SSI2>;
+ assigned-clock-rates = <0>, <24000000>;
status = "okay";
};
@@ -601,6 +914,9 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbotg1>;
disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
status = "okay";
};
@@ -611,6 +927,14 @@
status = "okay";
};
+&usbphy1 {
+ tx-d-cal = <0x5>;
+};
+
+&usbphy2 {
+ tx-d-cal = <0x5>;
+};
+
&usdhc1 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc1>;
@@ -619,6 +943,8 @@
bus-width = <8>;
cd-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
status = "okay";
};
@@ -629,6 +955,8 @@
pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
status = "okay";
};
@@ -638,5 +966,7 @@
pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 02378db3f5fc..a742d7400b0e 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-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
@@ -8,6 +8,7 @@
*/
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "skeleton.dtsi"
#include "imx6sl-pinfunc.h"
#include <dt-bindings/clock/imx6sl-clock.h>
@@ -20,6 +21,10 @@
gpio2 = &gpio3;
gpio3 = &gpio4;
gpio4 = &gpio5;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc3;
+ mmc3 = &usdhc4;
serial0 = &uart1;
serial1 = &uart2;
serial2 = &uart3;
@@ -37,7 +42,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0x0>;
@@ -55,17 +60,37 @@
396000 1175000
>;
clock-latency = <61036>; /* two CLK32 periods */
- 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>;
};
};
+ 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;
+ };
+ };
+
intc: interrupt-controller@00a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
@@ -92,6 +117,10 @@
};
};
+ reg_vbus_wakeup: usb_vbus_wakeup {
+ compatible = "fsl,imx6-dummy-ldo2p5";
+ };
+
soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -99,9 +128,42 @@
interrupt-parent = <&gpc>;
ranges;
- ocram: sram@00900000 {
+ 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@00900000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x00900000 0x4000>;
+ clocks = <&clks IMX6SL_CLK_OCRAM>;
+ };
+
+ ocrams_ddr: sram@00904000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x00904000 0x1000>;
+ clocks = <&clks IMX6SL_CLK_OCRAM>;
+ };
+
+ ocram: sram@00905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
+ reg = <0x00905000 0x1B000>;
clocks = <&clks IMX6SL_CLK_OCRAM>;
};
@@ -164,6 +226,8 @@
clocks = <&clks IMX6SL_CLK_ECSPI1>,
<&clks IMX6SL_CLK_ECSPI1>;
clock-names = "ipg", "per";
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -176,6 +240,8 @@
clocks = <&clks IMX6SL_CLK_ECSPI2>,
<&clks IMX6SL_CLK_ECSPI2>;
clock-names = "ipg", "per";
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -188,6 +254,8 @@
clocks = <&clks IMX6SL_CLK_ECSPI3>,
<&clks IMX6SL_CLK_ECSPI3>;
clock-names = "ipg", "per";
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -200,6 +268,8 @@
clocks = <&clks IMX6SL_CLK_ECSPI4>,
<&clks IMX6SL_CLK_ECSPI4>;
clock-names = "ipg", "per";
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -251,8 +321,8 @@
clocks = <&clks IMX6SL_CLK_SSI1_IPG>,
<&clks IMX6SL_CLK_SSI1>;
clock-names = "ipg", "baud";
- dmas = <&sdma 37 1 0>,
- <&sdma 38 1 0>;
+ dmas = <&sdma 37 22 0>,
+ <&sdma 38 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
@@ -267,8 +337,8 @@
clocks = <&clks IMX6SL_CLK_SSI2_IPG>,
<&clks IMX6SL_CLK_SSI2>;
clock-names = "ipg", "baud";
- dmas = <&sdma 41 1 0>,
- <&sdma 42 1 0>;
+ dmas = <&sdma 41 22 0>,
+ <&sdma 42 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
@@ -283,8 +353,8 @@
clocks = <&clks IMX6SL_CLK_SSI3_IPG>,
<&clks IMX6SL_CLK_SSI3>;
clock-names = "ipg", "baud";
- dmas = <&sdma 45 1 0>,
- <&sdma 46 1 0>;
+ dmas = <&sdma 45 22 0>,
+ <&sdma 46 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
@@ -520,20 +590,21 @@
anatop-min-bit-val = <4>;
anatop-min-voltage = <800000>;
anatop-max-voltage = <1375000>;
+ anatop-enable-bit = <0>;
};
- regulator-3p0 {
+ reg_3p0: regulator-3p0@120 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd3p0";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <3150000>;
- regulator-always-on;
+ regulator-min-microvolt = <2625000>;
+ regulator-max-microvolt = <3400000>;
anatop-reg-offset = <0x120>;
anatop-vol-bit-shift = <8>;
anatop-vol-bit-width = <5>;
anatop-min-bit-val = <0>;
anatop-min-voltage = <2625000>;
anatop-max-voltage = <3400000>;
+ anatop-enable-bit = <0>;
};
regulator-2p5 {
@@ -548,6 +619,7 @@
anatop-min-bit-val = <0>;
anatop-min-voltage = <2100000>;
anatop-max-voltage = <2850000>;
+ anatop-enable-bit = <0>;
};
reg_arm: regulator-vddcore {
@@ -565,6 +637,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
reg_pu: regulator-vddpu {
@@ -572,7 +645,8 @@
regulator-name = "vddpu";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1450000>;
- regulator-always-on;
+ regulator-enable-ramp-delay = <150>;
+ regulator-boot-on;
anatop-reg-offset = <0x140>;
anatop-vol-bit-shift = <9>;
anatop-vol-bit-width = <5>;
@@ -582,6 +656,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
reg_soc: regulator-vddsoc {
@@ -599,6 +674,7 @@
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1450000>;
+ regulator-allow-bypass;
};
};
@@ -615,6 +691,7 @@
reg = <0x020c9000 0x1000>;
interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_USBPHY1>;
+ phy-3p0-supply = <&reg_3p0>;
fsl,anatop = <&anatop>;
};
@@ -623,9 +700,16 @@
reg = <0x020ca000 0x1000>;
interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_USBPHY2>;
+ phy-3p0-supply = <&reg_3p0>;
fsl,anatop = <&anatop>;
};
+ usbphy_nop1: usbphy_nop1 {
+ compatible = "usb-nop-xceiv";
+ clocks = <&clks IMX6SL_CLK_USBPHY1>;
+ clock-names = "main_clk";
+ };
+
snvs: snvs@020cc000 {
compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
reg = <0x020cc000 0x4000>;
@@ -642,7 +726,7 @@
compatible = "syscon-poweroff";
regmap = <&snvs>;
offset = <0x38>;
- mask = <0x60>;
+ mask = <0x61>;
status = "disabled";
};
};
@@ -673,8 +757,12 @@
interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&intc>;
pu-supply = <&reg_pu>;
- clocks = <&clks IMX6SL_CLK_GPU2D_OVG>,
- <&clks IMX6SL_CLK_GPU2D_PODF>;
+ clocks = <&clks IMX6SL_CLK_GPU2D_PODF>, <&clks IMX6SL_CLK_GPU2D_OVG>,
+ <&clks IMX6SL_CLK_IPG>, <&clks IMX6SL_CLK_LCDIF_AXI>,
+ <&clks IMX6SL_CLK_LCDIF_PIX>, <&clks IMX6SL_CLK_EPDC_AXI>,
+ <&clks IMX6SL_CLK_EPDC_PIX>, <&clks IMX6SL_CLK_PXP_AXI>;
+ clock-names = "gpu2d_podf", "gpu2d_ovg", "ipg", "lcd_axi",
+ "lcd_pix", "epdc_axi", "epdc_pix", "pxp_axi";
#power-domain-cells = <1>;
};
@@ -690,8 +778,14 @@
};
csi: csi@020e4000 {
+ compatible = "fsl,imx6sl-csi";
reg = <0x020e4000 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@020e8000 {
@@ -707,18 +801,26 @@
<&clks IMX6SL_CLK_SDMA>;
clock-names = "ipg", "ahb";
#dma-cells = <3>;
+ iram = <&ocram>;
/* imx6sl reuses imx6q sdma firmware */
fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
};
pxp: pxp@020f0000 {
+ compatible = "fsl,imx6sl-pxp-dma", "fsl,imx6dl-pxp-dma";
reg = <0x020f0000 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@020f4000 {
+ compatible = "fsl,imx6sl-epdc", "fsl,imx6dl-epdc";
reg = <0x020f4000 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@020f8000 {
@@ -738,6 +840,10 @@
interrupts = <0 99 IRQ_TYPE_LEVEL_HIGH>,
<0 100 IRQ_TYPE_LEVEL_HIGH>,
<0 101 IRQ_TYPE_LEVEL_HIGH>;
+ /* DCP clock always on */
+ clocks = <&clks IMX6SL_CLK_DUMMY>;
+ clock-names = "dcp";
+ status = "okay";
};
};
@@ -758,6 +864,7 @@
ahb-burst-config = <0x0>;
tx-burst-size-dword = <0x10>;
rx-burst-size-dword = <0x10>;
+ fsl,anatop = <&anatop>;
status = "disabled";
};
@@ -784,6 +891,9 @@
ahb-burst-config = <0x0>;
tx-burst-size-dword = <0x10>;
rx-burst-size-dword = <0x10>;
+ phy_type = "hsic";
+ fsl,usbphy = <&usbphy_nop1>;
+ fsl,anatop = <&anatop>;
status = "disabled";
};
@@ -792,6 +902,7 @@
compatible = "fsl,imx6sl-usbmisc", "fsl,imx6q-usbmisc";
reg = <0x02184800 0x200>;
clocks = <&clks IMX6SL_CLK_USBOH3>;
+ vbus-wakeup-supply = <&reg_vbus_wakeup>;
};
fec: ethernet@02188000 {
@@ -887,9 +998,11 @@
reg = <0x021b0000 0x4000>;
};
- rngb: rngb@021b4000 {
+ rng: rng@021b4000 {
+ compatible = "fsl,imx6sl-rng", "fsl,imx-rng", "imx-rng";
reg = <0x021b4000 0x4000>;
interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SL_CLK_DUMMY>;
};
weim: weim@021b8000 {
@@ -908,6 +1021,24 @@
reg = <0x021d8000 0x4000>;
status = "disabled";
};
+
+ gpu: gpu@02200000 {
+ compatible = "fsl,imx6sl-gpu", "fsl,imx6q-gpu";
+ reg = <0x02200000 0x4000>, <0x02204000 0x4000>,
+ <0x80000000 0x0>, <0x0 0x8000000>;
+ reg-names = "iobase_2d", "iobase_vg",
+ "phys_baseaddr", "contiguous_mem";
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "irq_2d", "irq_vg";
+ clocks = <&clks IMX6SL_CLK_MMDC_ROOT>,
+ <&clks IMX6SL_CLK_MMDC_ROOT>,
+ <&clks IMX6SL_CLK_GPU2D_OVG>;
+ clock-names = "gpu2d_axi_clk", "openvg_axi_clk",
+ "gpu2d_clk";
+ resets = <&src 3>, <&src 3>;
+ reset-names = "gpu2d", "gpuvg";
+ power-domains = <&gpc 1>;
+ };
};
};
};
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..db30b1f7deb3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-evk-btwifi.dts
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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 (J4 connector).
+ */
+
+#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>;
+ };
+
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio3 24 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ gpios = <&gpio3 26 0>; /* WL_HOST_WAKE */
+ };
+};
+
+&iomuxc {
+ imx6sll-evk-murata-v2 {
+ 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 0x17059 /* WL_HOST_WAKE */
+ >;
+ };
+ };
+};
+
+&lcdif {
+ status = "disabled";
+};
+
+&reg_sd3_vmmc {
+ regulator-always-on;
+};
+
+&uart5 {
+ resets = <&modem_reset>;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ no-1-8-v;
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host; /* add hook for SD card detect mechanism for BCMDHD driver */
+};
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..8562facad609
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-evk-reva.dts
@@ -0,0 +1,13 @@
+/*
+ * 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 "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
new file mode 100644
index 000000000000..6fb3207bda4a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-evk.dts
@@ -0,0 +1,815 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sll.dtsi"
+
+/ {
+ model = "Freescale i.MX6SLL EVK Board";
+ compatible = "fsl,imx6sll-evk", "fsl,imx6sll";
+
+ memory {
+ reg = <0x80000000 0x80000000>;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ 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";
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ 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 = <&gpio4 0 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 = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_aud3v: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "wm8962-supply-3v15";
+ regulator-min-microvolt = <3150000>;
+ regulator-max-microvolt = <3150000>;
+ regulator-boot-on;
+ };
+
+ reg_aud4v: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "wm8962-supply-4v2";
+ regulator-min-microvolt = <4325000>;
+ regulator-max-microvolt = <4325000>;
+ regulator-boot-on;
+ };
+
+ reg_lcd: regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "lcd-pwr";
+ gpio = <&gpio4 8 0>;
+ enable-active-high;
+ };
+
+ reg_sd1_vmmc: sd1_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD1_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ reg_sd2_vmmc: sd2_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "eMMC-VCCQ";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ reg_sd3_vmmc: sd3_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD3_WIFI";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ };
+
+ sound {
+ compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ cpu-dai = <&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";
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6SLL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <393216000>;
+};
+
+&cpu0 {
+ arm-supply = <&sw1a_reg>;
+ soc-supply = <&sw1c_reg>;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ 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;
+ };
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6sll-evk {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6SLL_PAD_KEY_ROW7__GPIO4_IO07 0x17059
+ MX6SLL_PAD_GPIO4_IO22__GPIO4_IO22 0x17059
+ MX6SLL_PAD_KEY_COL3__GPIO3_IO30 0x17059
+ /*
+ * Must set the LVE of pad SD2_RESET, otherwise current
+ * leakage through eMMC chip will pull high the VCCQ to
+ * 2.6v, which will impact SD1 and SD3 SD3.0 voltage switch.
+ */
+ MX6SLL_PAD_SD2_RESET__GPIO4_IO27 0x417059
+ MX6SLL_PAD_KEY_COL4__GPIO4_IO00 0x17059
+ MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059 /* SD3 CD */
+ MX6SLL_PAD_KEY_COL6__GPIO4_IO04 0x17059 /*SD3 RESET */
+ MX6SLL_PAD_KEY_COL5__GPIO4_IO02 0x17059
+ 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_csi1: csi1grp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_GDRL__CSI_MCLK 0x1b088
+ MX6SLL_PAD_EPDC_GDCLK__CSI_PIXCLK 0x1b088
+ MX6SLL_PAD_EPDC_GDSP__CSI_VSYNC 0x1b088
+ MX6SLL_PAD_EPDC_GDOE__CSI_HSYNC 0x1b088
+ MX6SLL_PAD_EPDC_DATA02__CSI_DATA02 0x1b088
+ MX6SLL_PAD_EPDC_DATA03__CSI_DATA03 0x1b088
+ MX6SLL_PAD_EPDC_DATA04__CSI_DATA04 0x1b088
+ MX6SLL_PAD_EPDC_DATA05__CSI_DATA05 0x1b088
+ MX6SLL_PAD_EPDC_DATA06__CSI_DATA06 0x1b088
+ MX6SLL_PAD_EPDC_DATA07__CSI_DATA07 0x1b088
+ MX6SLL_PAD_EPDC_SDCLK__CSI_DATA08 0x1b088
+ MX6SLL_PAD_EPDC_SDLE__CSI_DATA09 0x1b088
+ MX6SLL_PAD_EPDC_SDSHR__GPIO1_IO26 0x80000000
+ MX6SLL_PAD_EPDC_SDOE__GPIO1_IO25 0x80000000
+ >;
+ };
+
+ 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_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX6SLL_PAD_LCD_DATA00__LCD_DATA00 0x79
+ MX6SLL_PAD_LCD_DATA01__LCD_DATA01 0x79
+ MX6SLL_PAD_LCD_DATA02__LCD_DATA02 0x79
+ MX6SLL_PAD_LCD_DATA03__LCD_DATA03 0x79
+ MX6SLL_PAD_LCD_DATA04__LCD_DATA04 0x79
+ MX6SLL_PAD_LCD_DATA05__LCD_DATA05 0x79
+ MX6SLL_PAD_LCD_DATA06__LCD_DATA06 0x79
+ MX6SLL_PAD_LCD_DATA07__LCD_DATA07 0x79
+ MX6SLL_PAD_LCD_DATA08__LCD_DATA08 0x79
+ MX6SLL_PAD_LCD_DATA09__LCD_DATA09 0x79
+ MX6SLL_PAD_LCD_DATA10__LCD_DATA10 0x79
+ MX6SLL_PAD_LCD_DATA11__LCD_DATA11 0x79
+ MX6SLL_PAD_LCD_DATA12__LCD_DATA12 0x79
+ MX6SLL_PAD_LCD_DATA13__LCD_DATA13 0x79
+ MX6SLL_PAD_LCD_DATA14__LCD_DATA14 0x79
+ MX6SLL_PAD_LCD_DATA15__LCD_DATA15 0x79
+ MX6SLL_PAD_LCD_DATA16__LCD_DATA16 0x79
+ MX6SLL_PAD_LCD_DATA17__LCD_DATA17 0x79
+ MX6SLL_PAD_LCD_DATA18__LCD_DATA18 0x79
+ MX6SLL_PAD_LCD_DATA19__LCD_DATA19 0x79
+ MX6SLL_PAD_LCD_DATA20__LCD_DATA20 0x79
+ MX6SLL_PAD_LCD_DATA21__LCD_DATA21 0x79
+ MX6SLL_PAD_LCD_DATA22__LCD_DATA22 0x79
+ MX6SLL_PAD_LCD_DATA23__LCD_DATA23 0x79
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX6SLL_PAD_LCD_CLK__LCD_CLK 0x79
+ MX6SLL_PAD_LCD_ENABLE__LCD_ENABLE 0x79
+ MX6SLL_PAD_LCD_HSYNC__LCD_HSYNC 0x79
+ MX6SLL_PAD_LCD_VSYNC__LCD_VSYNC 0x79
+ MX6SLL_PAD_LCD_RESET__LCD_RESET 0x79
+ MX6SLL_PAD_ECSPI1_SCLK__GPIO4_IO08 0x79
+ >;
+ };
+
+ 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_spdif: spdifgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_DATA4__SPDIF_OUT 0x4130b0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SLL_PAD_UART1_TXD__UART1_DCE_TX 0x1b0b1
+ MX6SLL_PAD_UART1_RXD__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ 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 0x17061
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x13061
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x17061
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x17061
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x17061
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x17061
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp_100mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170a1
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x130a1
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x170a1
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x170a1
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x170a1
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x170a1
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp_200mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170e9
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x130f9
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x170e9
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x170e9
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x170e9
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x170e9
+ >;
+ };
+
+ 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_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x17061
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x13061
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x17061
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x17061
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x17061
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x17061
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp_100mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170a1
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x130a1
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x170a1
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x170a1
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x170a1
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x170a1
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp_200mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170e9
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x130f9
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x170e9
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x170e9
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x170e9
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x170e9
+ >;
+ };
+
+ pinctrl_usbotg1: usbotg1grp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1
+ MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SLL_PAD_AUD_RXFS__I2C3_SCL 0x4041b8b1
+ MX6SLL_PAD_AUD_RXC__I2C3_SDA 0x4041b8b1
+ >;
+ };
+
+ pinctrl_pwm1: pmw1grp {
+ fsl,pins = <
+ MX6SLL_PAD_PWM1__PWM1_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_wdog1: wdog1grp {
+ fsl,pins = <
+ MX6SLL_PAD_WDOG_B__WDOG1_B 0x170b0
+ >;
+ };
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
+ lcd-supply = <&reg_lcd>;
+ 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>;
+ };
+ };
+ };
+};
+
+&pxp {
+ status = "okay";
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ 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>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ cd-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ vqmmc-supply = <&reg_sd2_vmmc>;
+ bus-width = <8>;
+ no-removable;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd3_vmmc>;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&epdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc0>;
+ V3P3-supply = <&V3P3_reg>;
+ VCOM-supply = <&VCOM_reg>;
+ DISPLAY-supply = <&DISPLAY_reg>;
+ status = "okay";
+};
+
+&ssi2 {
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog1>;
+ fsl,ext-reset-output;
+};
diff --git a/arch/arm/boot/dts/imx6sll-lpddr2-arm2.dts b/arch/arm/boot/dts/imx6sll-lpddr2-arm2.dts
new file mode 100644
index 000000000000..33f230f9c972
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-lpddr2-arm2.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 "imx6sll-lpddr3-arm2.dts"
+
diff --git a/arch/arm/boot/dts/imx6sll-lpddr3-arm2-csi.dts b/arch/arm/boot/dts/imx6sll-lpddr3-arm2-csi.dts
new file mode 100644
index 000000000000..59a0c0223610
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-lpddr3-arm2-csi.dts
@@ -0,0 +1,21 @@
+/*
+ * 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 "imx6sll-lpddr3-arm2.dts"
+
+&csi {
+ status = "okay";
+};
+
+&epdc {
+ status = "disabled";
+};
+
+&ov5640 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6sll-lpddr3-arm2-ecspi.dts b/arch/arm/boot/dts/imx6sll-lpddr3-arm2-ecspi.dts
new file mode 100644
index 000000000000..d1facfc26f7c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-lpddr3-arm2-ecspi.dts
@@ -0,0 +1,17 @@
+/*
+ * 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 "imx6sll-lpddr3-arm2.dts"
+
+&ecspi1 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6sll-lpddr3-arm2-spdif.dts b/arch/arm/boot/dts/imx6sll-lpddr3-arm2-spdif.dts
new file mode 100644
index 000000000000..5bcbc0170ac2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-lpddr3-arm2-spdif.dts
@@ -0,0 +1,42 @@
+/*
+ * 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 "imx6sll-lpddr3-arm2.dts"
+
+/ {
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif",
+ "fsl,imx6sl-evk-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-out;
+ };
+};
+
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif>;
+ assigned-clocks = <&clks IMX6SLL_CLK_SPDIF_SEL>,
+ <&clks IMX6SLL_CLK_SPDIF_PODF>;
+ assigned-clock-parents = <&clks IMX6SLL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <98304000>;
+ status = "okay";
+};
+
+&usdhc2 {
+ status = "disabled";
+};
+
+
diff --git a/arch/arm/boot/dts/imx6sll-lpddr3-arm2.dts b/arch/arm/boot/dts/imx6sll-lpddr3-arm2.dts
new file mode 100644
index 000000000000..894f75e04794
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-lpddr3-arm2.dts
@@ -0,0 +1,834 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sll.dtsi"
+
+/ {
+ model = "Freescale i.MX6SLL LPDDR3 ARM2 Board";
+ compatible = "fsl,imx6sll-lpddr3-arm2", "fsl,imx6sll";
+
+ memory {
+ reg = <0x80000000 0x80000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_led>;
+
+ users {
+ label = "debug";
+ gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ 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 = <&gpio4 0 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&swbst_reg>;
+ };
+
+ 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 = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&swbst_reg>;
+ };
+
+ reg_aud3v: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "wm8962-supply-3v15";
+ regulator-min-microvolt = <3150000>;
+ regulator-max-microvolt = <3150000>;
+ regulator-boot-on;
+ };
+
+ reg_aud4v: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "wm8962-supply-4v2";
+ regulator-min-microvolt = <4325000>;
+ regulator-max-microvolt = <4325000>;
+ regulator-boot-on;
+ };
+
+ reg_lcd: regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "lcd-pwr";
+ gpio = <&gpio4 8 0>;
+ enable-active-high;
+ };
+
+ reg_sd1_vmmc: sd1_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD1_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ reg_sd2_vmmc: sd2_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "eMMC_VCCQ";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ reg_sd3_vmmc: sd3_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD3_WIFI";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ };
+
+ sound {
+ compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ cpu-dai = <&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";
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6SLL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <393216000>;
+};
+
+&cpu0 {
+ arm-supply = <&sw1a_reg>;
+ soc-supply = <&sw1c_reg>;
+};
+
+&csi {
+ status = "disabled";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ 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;
+ };
+
+ ov5640: ov5640@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi1>;
+ clocks = <&clks IMX6SLL_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>;
+ status = "disabled";
+ port {
+ ov5640_ep: endpoint {
+ remote-endpoint = <&csi1_ep>;
+ };
+ };
+ };
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog &pinctrl_hog_sd2_reset>;
+
+ imx6sll-lpddr3-arm2 {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6SLL_PAD_KEY_ROW7__GPIO4_IO07 0x17059
+ MX6SLL_PAD_GPIO4_IO22__GPIO4_IO22 0x17059
+ MX6SLL_PAD_KEY_COL3__GPIO3_IO30 0x17059
+ MX6SLL_PAD_KEY_COL4__GPIO4_IO00 0x17059
+ MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059 /* SD3 CD */
+ MX6SLL_PAD_KEY_COL6__GPIO4_IO04 0x17059 /*SD3 RESET */
+ MX6SLL_PAD_KEY_COL5__GPIO4_IO02 0x17059
+ MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x17059 /* HP DETECT */
+ >;
+ };
+
+ pinctrl_hog_sd2_reset: hoggrp-1 {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_RESET__GPIO4_IO27 0x417059
+ >;
+ };
+
+ 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_csi1: csi1grp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_GDRL__CSI_MCLK 0x1b088
+ MX6SLL_PAD_EPDC_GDCLK__CSI_PIXCLK 0x1b088
+ MX6SLL_PAD_EPDC_GDSP__CSI_VSYNC 0x1b088
+ MX6SLL_PAD_EPDC_GDOE__CSI_HSYNC 0x1b088
+ MX6SLL_PAD_EPDC_DATA02__CSI_DATA02 0x1b088
+ MX6SLL_PAD_EPDC_DATA03__CSI_DATA03 0x1b088
+ MX6SLL_PAD_EPDC_DATA04__CSI_DATA04 0x1b088
+ MX6SLL_PAD_EPDC_DATA05__CSI_DATA05 0x1b088
+ MX6SLL_PAD_EPDC_DATA06__CSI_DATA06 0x1b088
+ MX6SLL_PAD_EPDC_DATA07__CSI_DATA07 0x1b088
+ MX6SLL_PAD_EPDC_SDCLK__CSI_DATA08 0x1b088
+ MX6SLL_PAD_EPDC_SDLE__CSI_DATA09 0x1b088
+ MX6SLL_PAD_EPDC_SDSHR__GPIO1_IO26 0x80000000
+ MX6SLL_PAD_EPDC_SDOE__GPIO1_IO25 0x80000000
+ >;
+ };
+
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_VCOM1__GPIO2_IO04 0x17059
+ >;
+ };
+
+ 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_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX6SLL_PAD_LCD_DATA00__LCD_DATA00 0x79
+ MX6SLL_PAD_LCD_DATA01__LCD_DATA01 0x79
+ MX6SLL_PAD_LCD_DATA02__LCD_DATA02 0x79
+ MX6SLL_PAD_LCD_DATA03__LCD_DATA03 0x79
+ MX6SLL_PAD_LCD_DATA04__LCD_DATA04 0x79
+ MX6SLL_PAD_LCD_DATA05__LCD_DATA05 0x79
+ MX6SLL_PAD_LCD_DATA06__LCD_DATA06 0x79
+ MX6SLL_PAD_LCD_DATA07__LCD_DATA07 0x79
+ MX6SLL_PAD_LCD_DATA08__LCD_DATA08 0x79
+ MX6SLL_PAD_LCD_DATA09__LCD_DATA09 0x79
+ MX6SLL_PAD_LCD_DATA10__LCD_DATA10 0x79
+ MX6SLL_PAD_LCD_DATA11__LCD_DATA11 0x79
+ MX6SLL_PAD_LCD_DATA12__LCD_DATA12 0x79
+ MX6SLL_PAD_LCD_DATA13__LCD_DATA13 0x79
+ MX6SLL_PAD_LCD_DATA14__LCD_DATA14 0x79
+ MX6SLL_PAD_LCD_DATA15__LCD_DATA15 0x79
+ MX6SLL_PAD_LCD_DATA16__LCD_DATA16 0x79
+ MX6SLL_PAD_LCD_DATA17__LCD_DATA17 0x79
+ MX6SLL_PAD_LCD_DATA18__LCD_DATA18 0x79
+ MX6SLL_PAD_LCD_DATA19__LCD_DATA19 0x79
+ MX6SLL_PAD_LCD_DATA20__LCD_DATA20 0x79
+ MX6SLL_PAD_LCD_DATA21__LCD_DATA21 0x79
+ MX6SLL_PAD_LCD_DATA22__LCD_DATA22 0x79
+ MX6SLL_PAD_LCD_DATA23__LCD_DATA23 0x79
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX6SLL_PAD_LCD_CLK__LCD_CLK 0x79
+ MX6SLL_PAD_LCD_ENABLE__LCD_ENABLE 0x79
+ MX6SLL_PAD_LCD_HSYNC__LCD_HSYNC 0x79
+ MX6SLL_PAD_LCD_VSYNC__LCD_VSYNC 0x79
+ MX6SLL_PAD_LCD_RESET__LCD_RESET 0x79
+ MX6SLL_PAD_ECSPI1_SCLK__GPIO4_IO08 0x79
+ >;
+ };
+
+ 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_spdif: spdifgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_RESET__SPDIF_OUT 0x4130b0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SLL_PAD_UART1_TXD__UART1_DCE_TX 0x1b0b1
+ MX6SLL_PAD_UART1_RXD__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x17059
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x17059
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x17059
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x17059
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp_100mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170b9
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x170b9
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x170b9
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x170b9
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x170b9
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp_200mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170f9
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x170f9
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x170f9
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x170f9
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x170f9
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x170f9
+ >;
+ };
+
+ 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_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x17059
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x17059
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x17059
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x17059
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp_100mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170b9
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x170b9
+ 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
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp_200mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170f9
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x170f9
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x170f9
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x170f9
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x170f9
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_usbotg1: usbotg1grp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1
+ MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_SDCE2__I2C3_SCL 0x4041b8b1
+ MX6SLL_PAD_EPDC_SDCE3__I2C3_SDA 0x4041b8b1
+ >;
+ };
+
+ pinctrl_pwm1: pmw1grp {
+ fsl,pins = <
+ MX6SLL_PAD_PWM1__PWM1_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6SLL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
+ MX6SLL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
+ MX6SLL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
+ MX6SLL_PAD_ECSPI1_SS0__GPIO4_IO11 0x100b1
+ >;
+ };
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
+ lcd-supply = <&reg_lcd>;
+ 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>;
+ };
+ };
+ };
+};
+
+&pxp {
+ status = "okay";
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ 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 = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ vqmmc-supply = <&reg_sd2_vmmc>;
+ bus-width = <8>;
+ no-removable;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd3_vmmc>;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&ecspi1 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio4 11 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ flash: m25p80@0 {
+ compatible = "st,m25p32";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&epdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc0>;
+ V3P3-supply = <&V3P3_reg>;
+ VCOM-supply = <&VCOM_reg>;
+ DISPLAY-supply = <&DISPLAY_reg>;
+ status = "okay";
+};
+
+&ssi2 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6sll-pinfunc.h b/arch/arm/boot/dts/imx6sll-pinfunc.h
new file mode 100755
index 000000000000..5a3700b0a0ff
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-pinfunc.h
@@ -0,0 +1,882 @@
+/*
+ * Copyright 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.
+ *
+ */
+
+#ifndef __DTS_IMX6SLL_PINFUNC_H
+#define __DTS_IMX6SLL_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6SLL_PAD_WDOG_B__WDOG1_B 0x0014 0x02DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_WDOG_B__WDOG1_RESET_B_DEB 0x0014 0x02DC 0x0000 0x1 0x0
+#define MX6SLL_PAD_WDOG_B__UART5_RI_B 0x0014 0x02DC 0x0000 0x2 0x0
+#define MX6SLL_PAD_WDOG_B__GPIO3_IO18 0x0014 0x02DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_24M__XTALOSC_REF_CLK_24M 0x0018 0x02E0 0x0000 0x0 0x0
+#define MX6SLL_PAD_REF_CLK_24M__I2C3_SCL 0x0018 0x02E0 0x068C 0x1 0x0
+#define MX6SLL_PAD_REF_CLK_24M__PWM3_OUT 0x0018 0x02E0 0x0000 0x2 0x0
+#define MX6SLL_PAD_REF_CLK_24M__USB_OTG2_ID 0x0018 0x02E0 0x0560 0x3 0x0
+#define MX6SLL_PAD_REF_CLK_24M__CCM_PMIC_READY 0x0018 0x02E0 0x05AC 0x4 0x0
+#define MX6SLL_PAD_REF_CLK_24M__GPIO3_IO21 0x0018 0x02E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_24M__SD3_WP 0x0018 0x02E0 0x0794 0x6 0x0
+#define MX6SLL_PAD_REF_CLK_32K__XTALOSC_REF_CLK_32K 0x001C 0x02E4 0x0000 0x0 0x0
+#define MX6SLL_PAD_REF_CLK_32K__I2C3_SDA 0x001C 0x02E4 0x0690 0x1 0x0
+#define MX6SLL_PAD_REF_CLK_32K__PWM4_OUT 0x001C 0x02E4 0x0000 0x2 0x0
+#define MX6SLL_PAD_REF_CLK_32K__USB_OTG1_ID 0x001C 0x02E4 0x055C 0x3 0x0
+#define MX6SLL_PAD_REF_CLK_32K__SD1_LCTL 0x001C 0x02E4 0x0000 0x4 0x0
+#define MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22 0x001C 0x02E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_32K__SD3_CD_B 0x001C 0x02E4 0x0780 0x6 0x0
+#define MX6SLL_PAD_PWM1__PWM1_OUT 0x0020 0x02E8 0x0000 0x0 0x0
+#define MX6SLL_PAD_PWM1__CCM_CLKO 0x0020 0x02E8 0x0000 0x1 0x0
+#define MX6SLL_PAD_PWM1__AUDIO_CLK_OUT 0x0020 0x02E8 0x0000 0x2 0x0
+#define MX6SLL_PAD_PWM1__CSI_MCLK 0x0020 0x02E8 0x0000 0x4 0x0
+#define MX6SLL_PAD_PWM1__GPIO3_IO23 0x0020 0x02E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_PWM1__EPIT1_OUT 0x0020 0x02E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL0__KEY_COL0 0x0024 0x02EC 0x06A0 0x0 0x0
+#define MX6SLL_PAD_KEY_COL0__I2C2_SCL 0x0024 0x02EC 0x0684 0x1 0x0
+#define MX6SLL_PAD_KEY_COL0__LCD_DATA00 0x0024 0x02EC 0x06D8 0x2 0x0
+#define MX6SLL_PAD_KEY_COL0__SD1_CD_B 0x0024 0x02EC 0x0770 0x4 0x1
+#define MX6SLL_PAD_KEY_COL0__GPIO3_IO24 0x0024 0x02EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW0__KEY_ROW0 0x0028 0x02F0 0x06C0 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW0__I2C2_SDA 0x0028 0x02F0 0x0688 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW0__LCD_DATA01 0x0028 0x02F0 0x06DC 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW0__SD1_WP 0x0028 0x02F0 0x0774 0x4 0x1
+#define MX6SLL_PAD_KEY_ROW0__GPIO3_IO25 0x0028 0x02F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL1__KEY_COL1 0x002C 0x02F4 0x06A4 0x0 0x0
+#define MX6SLL_PAD_KEY_COL1__ECSPI4_MOSI 0x002C 0x02F4 0x0658 0x1 0x1
+#define MX6SLL_PAD_KEY_COL1__LCD_DATA02 0x002C 0x02F4 0x06E0 0x2 0x0
+#define MX6SLL_PAD_KEY_COL1__SD3_DATA4 0x002C 0x02F4 0x0784 0x4 0x0
+#define MX6SLL_PAD_KEY_COL1__GPIO3_IO26 0x002C 0x02F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW1__KEY_ROW1 0x0030 0x02F8 0x06C4 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW1__ECSPI4_MISO 0x0030 0x02F8 0x0654 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW1__LCD_DATA03 0x0030 0x02F8 0x06E4 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW1__CSI_FIELD 0x0030 0x02F8 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW1__SD3_DATA5 0x0030 0x02F8 0x0788 0x4 0x0
+#define MX6SLL_PAD_KEY_ROW1__GPIO3_IO27 0x0030 0x02F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL2__KEY_COL2 0x0034 0x02FC 0x06A8 0x0 0x0
+#define MX6SLL_PAD_KEY_COL2__ECSPI4_SS0 0x0034 0x02FC 0x065C 0x1 0x1
+#define MX6SLL_PAD_KEY_COL2__LCD_DATA04 0x0034 0x02FC 0x06E8 0x2 0x0
+#define MX6SLL_PAD_KEY_COL2__CSI_DATA12 0x0034 0x02FC 0x05B8 0x3 0x1
+#define MX6SLL_PAD_KEY_COL2__SD3_DATA6 0x0034 0x02FC 0x078C 0x4 0x0
+#define MX6SLL_PAD_KEY_COL2__GPIO3_IO28 0x0034 0x02FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW2__KEY_ROW2 0x0038 0x0300 0x06C8 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW2__ECSPI4_SCLK 0x0038 0x0300 0x0650 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW2__LCD_DATA05 0x0038 0x0300 0x06EC 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW2__CSI_DATA13 0x0038 0x0300 0x05BC 0x3 0x1
+#define MX6SLL_PAD_KEY_ROW2__SD3_DATA7 0x0038 0x0300 0x0790 0x4 0x0
+#define MX6SLL_PAD_KEY_ROW2__GPIO3_IO29 0x0038 0x0300 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL3__KEY_COL3 0x003C 0x0304 0x06AC 0x0 0x0
+#define MX6SLL_PAD_KEY_COL3__AUD6_RXFS 0x003C 0x0304 0x05A0 0x1 0x1
+#define MX6SLL_PAD_KEY_COL3__LCD_DATA06 0x003C 0x0304 0x06F0 0x2 0x0
+#define MX6SLL_PAD_KEY_COL3__CSI_DATA14 0x003C 0x0304 0x05C0 0x3 0x1
+#define MX6SLL_PAD_KEY_COL3__GPIO3_IO30 0x003C 0x0304 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL3__SD1_RESET 0x003C 0x0304 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW3__KEY_ROW3 0x0040 0x0308 0x06CC 0x0 0x1
+#define MX6SLL_PAD_KEY_ROW3__AUD6_RXC 0x0040 0x0308 0x059C 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW3__LCD_DATA07 0x0040 0x0308 0x06F4 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW3__CSI_DATA15 0x0040 0x0308 0x05C4 0x3 0x2
+#define MX6SLL_PAD_KEY_ROW3__GPIO3_IO31 0x0040 0x0308 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW3__SD1_VSELECT 0x0040 0x0308 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL4__KEY_COL4 0x0044 0x030C 0x06B0 0x0 0x1
+#define MX6SLL_PAD_KEY_COL4__AUD6_RXD 0x0044 0x030C 0x0594 0x1 0x1
+#define MX6SLL_PAD_KEY_COL4__LCD_DATA08 0x0044 0x030C 0x06F8 0x2 0x1
+#define MX6SLL_PAD_KEY_COL4__CSI_DATA16 0x0044 0x030C 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL4__GPIO4_IO00 0x0044 0x030C 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL4__USB_OTG1_PWR 0x0044 0x030C 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW4__KEY_ROW4 0x0048 0x0310 0x06D0 0x0 0x1
+#define MX6SLL_PAD_KEY_ROW4__AUD6_TXC 0x0048 0x0310 0x05A4 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW4__LCD_DATA09 0x0048 0x0310 0x06FC 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW4__CSI_DATA17 0x0048 0x0310 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW4__GPIO4_IO01 0x0048 0x0310 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW4__USB_OTG1_OC 0x0048 0x0310 0x076C 0x6 0x2
+#define MX6SLL_PAD_KEY_COL5__KEY_COL5 0x004C 0x0314 0x0694 0x0 0x1
+#define MX6SLL_PAD_KEY_COL5__AUD6_TXFS 0x004C 0x0314 0x05A8 0x1 0x1
+#define MX6SLL_PAD_KEY_COL5__LCD_DATA10 0x004C 0x0314 0x0700 0x2 0x0
+#define MX6SLL_PAD_KEY_COL5__CSI_DATA18 0x004C 0x0314 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL5__GPIO4_IO02 0x004C 0x0314 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL5__USB_OTG2_PWR 0x004C 0x0314 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW5__KEY_ROW5 0x0050 0x0318 0x06B4 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW5__AUD6_TXD 0x0050 0x0318 0x0598 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW5__LCD_DATA11 0x0050 0x0318 0x0704 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW5__CSI_DATA19 0x0050 0x0318 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW5__GPIO4_IO03 0x0050 0x0318 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW5__USB_OTG2_OC 0x0050 0x0318 0x0768 0x6 0x3
+#define MX6SLL_PAD_KEY_COL6__KEY_COL6 0x0054 0x031C 0x0698 0x0 0x2
+#define MX6SLL_PAD_KEY_COL6__UART4_DCE_RX 0x0054 0x031C 0x075C 0x1 0x2
+#define MX6SLL_PAD_KEY_COL6__UART4_DTE_TX 0x0054 0x031C 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_COL6__LCD_DATA12 0x0054 0x031C 0x0708 0x2 0x1
+#define MX6SLL_PAD_KEY_COL6__CSI_DATA20 0x0054 0x031C 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL6__GPIO4_IO04 0x0054 0x031C 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL6__SD3_RESET 0x0054 0x031C 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW6__KEY_ROW6 0x0058 0x0320 0x06B8 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW6__UART4_DCE_TX 0x0058 0x0320 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW6__UART4_DTE_RX 0x0058 0x0320 0x075C 0x1 0x3
+#define MX6SLL_PAD_KEY_ROW6__LCD_DATA13 0x0058 0x0320 0x070C 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW6__CSI_DATA21 0x0058 0x0320 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW6__GPIO4_IO05 0x0058 0x0320 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW6__SD3_VSELECT 0x0058 0x0320 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL7__KEY_COL7 0x005C 0x0324 0x069C 0x0 0x2
+#define MX6SLL_PAD_KEY_COL7__UART4_DCE_RTS 0x005C 0x0324 0x0758 0x1 0x2
+#define MX6SLL_PAD_KEY_COL7__UART4_DTE_CTS 0x005C 0x0324 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_COL7__LCD_DATA14 0x005C 0x0324 0x0710 0x2 0x1
+#define MX6SLL_PAD_KEY_COL7__CSI_DATA22 0x005C 0x0324 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL7__GPIO4_IO06 0x005C 0x0324 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL7__SD1_WP 0x005C 0x0324 0x0774 0x6 0x3
+#define MX6SLL_PAD_KEY_ROW7__KEY_ROW7 0x0060 0x0328 0x06BC 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW7__UART4_DCE_CTS 0x0060 0x0328 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW7__UART4_DTE_RTS 0x0060 0x0328 0x0758 0x1 0x3
+#define MX6SLL_PAD_KEY_ROW7__LCD_DATA15 0x0060 0x0328 0x0714 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW7__CSI_DATA23 0x0060 0x0328 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW7__GPIO4_IO07 0x0060 0x0328 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW7__SD1_CD_B 0x0060 0x0328 0x0770 0x6 0x3
+#define MX6SLL_PAD_EPDC_DATA00__EPDC_DATA00 0x0064 0x032C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA00__ECSPI4_MOSI 0x0064 0x032C 0x0658 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA00__LCD_DATA24 0x0064 0x032C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA00__CSI_DATA00 0x0064 0x032C 0x05C8 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA00__GPIO1_IO07 0x0064 0x032C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA01__EPDC_DATA01 0x0068 0x0330 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA01__ECSPI4_MISO 0x0068 0x0330 0x0654 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA01__LCD_DATA25 0x0068 0x0330 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA01__CSI_DATA01 0x0068 0x0330 0x05CC 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA01__GPIO1_IO08 0x0068 0x0330 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA02__EPDC_DATA02 0x006C 0x0334 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA02__ECSPI4_SS0 0x006C 0x0334 0x065C 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA02__LCD_DATA26 0x006C 0x0334 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA02__CSI_DATA02 0x006C 0x0334 0x05D0 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA02__GPIO1_IO09 0x006C 0x0334 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA03__EPDC_DATA03 0x0070 0x0338 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA03__ECSPI4_SCLK 0x0070 0x0338 0x0650 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA03__LCD_DATA27 0x0070 0x0338 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA03__CSI_DATA03 0x0070 0x0338 0x05D4 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA03__GPIO1_IO10 0x0070 0x0338 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA04__EPDC_DATA04 0x0074 0x033C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA04__ECSPI4_SS1 0x0074 0x033C 0x0660 0x1 0x1
+#define MX6SLL_PAD_EPDC_DATA04__LCD_DATA28 0x0074 0x033C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA04__CSI_DATA04 0x0074 0x033C 0x05D8 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA04__GPIO1_IO11 0x0074 0x033C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA05__EPDC_DATA05 0x0078 0x0340 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA05__ECSPI4_SS2 0x0078 0x0340 0x0664 0x1 0x1
+#define MX6SLL_PAD_EPDC_DATA05__LCD_DATA29 0x0078 0x0340 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA05__CSI_DATA05 0x0078 0x0340 0x05DC 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA05__GPIO1_IO12 0x0078 0x0340 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA06__EPDC_DATA06 0x007C 0x0344 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA06__ECSPI4_SS3 0x007C 0x0344 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA06__LCD_DATA30 0x007C 0x0344 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA06__CSI_DATA06 0x007C 0x0344 0x05E0 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA06__GPIO1_IO13 0x007C 0x0344 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA07__EPDC_DATA07 0x0080 0x0348 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA07__ECSPI4_RDY 0x0080 0x0348 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA07__LCD_DATA31 0x0080 0x0348 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA07__CSI_DATA07 0x0080 0x0348 0x05E4 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA07__GPIO1_IO14 0x0080 0x0348 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA08__EPDC_DATA08 0x0084 0x034C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA08__ECSPI3_MOSI 0x0084 0x034C 0x063C 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA08__EPDC_PWR_CTRL0 0x0084 0x034C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA08__GPIO1_IO15 0x0084 0x034C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA09__EPDC_DATA09 0x0088 0x0350 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA09__ECSPI3_MISO 0x0088 0x0350 0x0638 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA09__EPDC_PWR_CTRL1 0x0088 0x0350 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA09__GPIO1_IO16 0x0088 0x0350 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA10__EPDC_DATA10 0x008C 0x0354 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA10__ECSPI3_SS0 0x008C 0x0354 0x0648 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA10__EPDC_PWR_CTRL2 0x008C 0x0354 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA10__GPIO1_IO17 0x008C 0x0354 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA11__EPDC_DATA11 0x0090 0x0358 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA11__ECSPI3_SCLK 0x0090 0x0358 0x0630 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA11__EPDC_PWR_CTRL3 0x0090 0x0358 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA11__GPIO1_IO18 0x0090 0x0358 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA12__EPDC_DATA12 0x0094 0x035C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA12__UART2_DCE_RX 0x0094 0x035C 0x074C 0x1 0x4
+#define MX6SLL_PAD_EPDC_DATA12__UART2_DTE_TX 0x0094 0x035C 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA12__EPDC_PWR_COM 0x0094 0x035C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA12__GPIO1_IO19 0x0094 0x035C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA12__ECSPI3_SS1 0x0094 0x035C 0x064C 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA13__EPDC_DATA13 0x0098 0x0360 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA13__UART2_DCE_TX 0x0098 0x0360 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA13__UART2_DTE_RX 0x0098 0x0360 0x074C 0x1 0x5
+#define MX6SLL_PAD_EPDC_DATA13__EPDC_PWR_IRQ 0x0098 0x0360 0x0668 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA13__GPIO1_IO20 0x0098 0x0360 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA13__ECSPI3_SS2 0x0098 0x0360 0x0640 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA14__EPDC_DATA14 0x009C 0x0364 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA14__UART2_DCE_RTS 0x009C 0x0364 0x0748 0x1 0x4
+#define MX6SLL_PAD_EPDC_DATA14__UART2_DTE_CTS 0x009C 0x0364 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA14__EPDC_PWR_STAT 0x009C 0x0364 0x066C 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA14__GPIO1_IO21 0x009C 0x0364 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA14__ECSPI3_SS3 0x009C 0x0364 0x0644 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA15__EPDC_DATA15 0x00A0 0x0368 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA15__UART2_DCE_CTS 0x00A0 0x0368 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA15__UART2_DTE_RTS 0x00A0 0x0368 0x0748 0x1 0x5
+#define MX6SLL_PAD_EPDC_DATA15__EPDC_PWR_WAKE 0x00A0 0x0368 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA15__GPIO1_IO22 0x00A0 0x0368 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA15__ECSPI3_RDY 0x00A0 0x0368 0x0634 0x6 0x1
+#define MX6SLL_PAD_EPDC_SDCLK__EPDC_SDCLK_P 0x00A4 0x036C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCLK__ECSPI2_MOSI 0x00A4 0x036C 0x0624 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__I2C2_SCL 0x00A4 0x036C 0x0684 0x2 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__CSI_DATA08 0x00A4 0x036C 0x05E8 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__GPIO1_IO23 0x00A4 0x036C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDLE__EPDC_SDLE 0x00A8 0x0370 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDLE__ECSPI2_MISO 0x00A8 0x0370 0x0620 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDLE__I2C2_SDA 0x00A8 0x0370 0x0688 0x2 0x2
+#define MX6SLL_PAD_EPDC_SDLE__CSI_DATA09 0x00A8 0x0370 0x05EC 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDLE__GPIO1_IO24 0x00A8 0x0370 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDOE__EPDC_SDOE 0x00AC 0x0374 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDOE__ECSPI2_SS0 0x00AC 0x0374 0x0628 0x1 0x1
+#define MX6SLL_PAD_EPDC_SDOE__CSI_DATA10 0x00AC 0x0374 0x05B0 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDOE__GPIO1_IO25 0x00AC 0x0374 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__EPDC_SDSHR 0x00B0 0x0378 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__ECSPI2_SCLK 0x00B0 0x0378 0x061C 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDSHR__EPDC_SDCE4 0x00B0 0x0378 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__CSI_DATA11 0x00B0 0x0378 0x05B4 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDSHR__GPIO1_IO26 0x00B0 0x0378 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__EPDC_SDCE0 0x00B4 0x037C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__ECSPI2_SS1 0x00B4 0x037C 0x062C 0x1 0x1
+#define MX6SLL_PAD_EPDC_SDCE0__PWM3_OUT 0x00B4 0x037C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__GPIO1_IO27 0x00B4 0x037C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__EPDC_SDCE1 0x00B8 0x0380 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__WDOG2_B 0x00B8 0x0380 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__PWM4_OUT 0x00B8 0x0380 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__GPIO1_IO28 0x00B8 0x0380 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__EPDC_SDCE2 0x00BC 0x0384 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__I2C3_SCL 0x00BC 0x0384 0x068C 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCE2__PWM1_OUT 0x00BC 0x0384 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__GPIO1_IO29 0x00BC 0x0384 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__EPDC_SDCE3 0x00C0 0x0388 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__I2C3_SDA 0x00C0 0x0388 0x0690 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCE3__PWM2_OUT 0x00C0 0x0388 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__GPIO1_IO30 0x00C0 0x0388 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__EPDC_GDCLK 0x00C4 0x038C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__ECSPI2_SS2 0x00C4 0x038C 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__CSI_PIXCLK 0x00C4 0x038C 0x05F4 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDCLK__GPIO1_IO31 0x00C4 0x038C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__SD2_RESET 0x00C4 0x038C 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_GDOE__EPDC_GDOE 0x00C8 0x0390 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDOE__ECSPI2_SS3 0x00C8 0x0390 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDOE__CSI_HSYNC 0x00C8 0x0390 0x05F0 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDOE__GPIO2_IO00 0x00C8 0x0390 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDOE__SD2_VSELECT 0x00C8 0x0390 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_GDRL__EPDC_GDRL 0x00CC 0x0394 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDRL__ECSPI2_RDY 0x00CC 0x0394 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDRL__CSI_MCLK 0x00CC 0x0394 0x0000 0x3 0x0
+#define MX6SLL_PAD_EPDC_GDRL__GPIO2_IO01 0x00CC 0x0394 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDRL__SD2_WP 0x00CC 0x0394 0x077C 0x6 0x2
+#define MX6SLL_PAD_EPDC_GDSP__EPDC_GDSP 0x00D0 0x0398 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDSP__PWM4_OUT 0x00D0 0x0398 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDSP__CSI_VSYNC 0x00D0 0x0398 0x05F8 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDSP__GPIO2_IO02 0x00D0 0x0398 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDSP__SD2_CD_B 0x00D0 0x0398 0x0778 0x6 0x2
+#define MX6SLL_PAD_EPDC_VCOM0__EPDC_VCOM0 0x00D4 0x039C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__AUD5_RXFS 0x00D4 0x039C 0x0588 0x1 0x1
+#define MX6SLL_PAD_EPDC_VCOM0__UART3_DCE_RX 0x00D4 0x039C 0x0754 0x2 0x4
+#define MX6SLL_PAD_EPDC_VCOM0__UART3_DTE_TX 0x00D4 0x039C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__GPIO2_IO03 0x00D4 0x039C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__EPDC_SDCE5 0x00D4 0x039C 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__EPDC_VCOM1 0x00D8 0x03A0 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__AUD5_RXD 0x00D8 0x03A0 0x057C 0x1 0x1
+#define MX6SLL_PAD_EPDC_VCOM1__UART3_DCE_TX 0x00D8 0x03A0 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__UART3_DTE_RX 0x00D8 0x03A0 0x0754 0x2 0x5
+#define MX6SLL_PAD_EPDC_VCOM1__GPIO2_IO04 0x00D8 0x03A0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__EPDC_SDCE6 0x00D8 0x03A0 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_BDR0__EPDC_BDR0 0x00DC 0x03A4 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_BDR0__UART3_DCE_RTS 0x00DC 0x03A4 0x0750 0x2 0x2
+#define MX6SLL_PAD_EPDC_BDR0__UART3_DTE_CTS 0x00DC 0x03A4 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_BDR0__GPIO2_IO05 0x00DC 0x03A4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_BDR0__EPDC_SDCE7 0x00DC 0x03A4 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_BDR1__EPDC_BDR1 0x00E0 0x03A8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_BDR1__UART3_DCE_CTS 0x00E0 0x03A8 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_BDR1__UART3_DTE_RTS 0x00E0 0x03A8 0x0750 0x2 0x3
+#define MX6SLL_PAD_EPDC_BDR1__GPIO2_IO06 0x00E0 0x03A8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_BDR1__EPDC_SDCE8 0x00E0 0x03A8 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__EPDC_PWR_CTRL0 0x00E4 0x03AC 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__AUD5_RXC 0x00E4 0x03AC 0x0584 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__LCD_DATA16 0x00E4 0x03AC 0x0718 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__GPIO2_IO07 0x00E4 0x03AC 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__EPDC_PWR_CTRL1 0x00E8 0x03B0 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__AUD5_TXFS 0x00E8 0x03B0 0x0590 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__LCD_DATA17 0x00E8 0x03B0 0x071C 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__GPIO2_IO08 0x00E8 0x03B0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__EPDC_PWR_CTRL2 0x00EC 0x03B4 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__AUD5_TXD 0x00EC 0x03B4 0x0580 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__LCD_DATA18 0x00EC 0x03B4 0x0720 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__GPIO2_IO09 0x00EC 0x03B4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__EPDC_PWR_CTRL3 0x00F0 0x03B8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__AUD5_TXC 0x00F0 0x03B8 0x058C 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__LCD_DATA19 0x00F0 0x03B8 0x0724 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__GPIO2_IO10 0x00F0 0x03B8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__EPDC_PWR_COM 0x00F4 0x03BC 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__LCD_DATA20 0x00F4 0x03BC 0x0728 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x00F4 0x03BC 0x055C 0x4 0x4
+#define MX6SLL_PAD_EPDC_PWR_COM__GPIO2_IO11 0x00F4 0x03BC 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__SD3_RESET 0x00F4 0x03BC 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_IRQ__EPDC_PWR_IRQ 0x00F8 0x03C0 0x0668 0x0 0x1
+#define MX6SLL_PAD_EPDC_PWR_IRQ__LCD_DATA21 0x00F8 0x03C0 0x072C 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_IRQ__USB_OTG2_ID 0x00F8 0x03C0 0x0560 0x4 0x3
+#define MX6SLL_PAD_EPDC_PWR_IRQ__GPIO2_IO12 0x00F8 0x03C0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_IRQ__SD3_VSELECT 0x00F8 0x03C0 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__EPDC_PWR_STAT 0x00FC 0x03C4 0x066C 0x0 0x1
+#define MX6SLL_PAD_EPDC_PWR_STAT__LCD_DATA22 0x00FC 0x03C4 0x0730 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_STAT__ARM_EVENTI 0x00FC 0x03C4 0x0000 0x4 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__GPIO2_IO13 0x00FC 0x03C4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__SD3_WP 0x00FC 0x03C4 0x0794 0x6 0x2
+#define MX6SLL_PAD_EPDC_PWR_WAKE__EPDC_PWR_WAKE 0x0100 0x03C8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__LCD_DATA23 0x0100 0x03C8 0x0734 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_WAKE__ARM_EVENTO 0x0100 0x03C8 0x0000 0x4 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__GPIO2_IO14 0x0100 0x03C8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__SD3_CD_B 0x0100 0x03C8 0x0780 0x6 0x2
+#define MX6SLL_PAD_LCD_CLK__LCD_CLK 0x0104 0x03CC 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_CLK__LCD_WR_RWN 0x0104 0x03CC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_CLK__PWM4_OUT 0x0104 0x03CC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_CLK__GPIO2_IO15 0x0104 0x03CC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_ENABLE__LCD_ENABLE 0x0108 0x03D0 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_ENABLE__LCD_RD_E 0x0108 0x03D0 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_ENABLE__UART2_DCE_RX 0x0108 0x03D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_ENABLE__UART2_DTE_TX 0x0108 0x03D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_ENABLE__GPIO2_IO16 0x0108 0x03D0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_HSYNC__LCD_HSYNC 0x010C 0x03D4 0x06D4 0x0 0x0
+#define MX6SLL_PAD_LCD_HSYNC__LCD_CS 0x010C 0x03D4 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_HSYNC__UART2_DCE_TX 0x010C 0x03D4 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_HSYNC__UART2_DTE_RX 0x010C 0x03D4 0x074C 0x4 0x1
+#define MX6SLL_PAD_LCD_HSYNC__GPIO2_IO17 0x010C 0x03D4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_HSYNC__ARM_TRACE_CLK 0x010C 0x03D4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_VSYNC__LCD_VSYNC 0x0110 0x03D8 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_VSYNC__LCD_RS 0x0110 0x03D8 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_VSYNC__UART2_DCE_RTS 0x0110 0x03D8 0x0748 0x4 0x0
+#define MX6SLL_PAD_LCD_VSYNC__UART2_DTE_CTS 0x0110 0x03D8 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_VSYNC__GPIO2_IO18 0x0110 0x03D8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_VSYNC__ARM_TRACE_CTL 0x0110 0x03D8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_RESET__LCD_RESET 0x0114 0x03DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_RESET__LCD_BUSY 0x0114 0x03DC 0x06D4 0x2 0x1
+#define MX6SLL_PAD_LCD_RESET__UART2_DCE_CTS 0x0114 0x03DC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_RESET__UART2_DTE_RTS 0x0114 0x03DC 0x0748 0x4 0x1
+#define MX6SLL_PAD_LCD_RESET__GPIO2_IO19 0x0114 0x03DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_RESET__CCM_PMIC_READY 0x0114 0x03DC 0x05AC 0x6 0x2
+#define MX6SLL_PAD_LCD_DATA00__LCD_DATA00 0x0118 0x03E0 0x06D8 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA00__ECSPI1_MOSI 0x0118 0x03E0 0x0608 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA00__USB_OTG2_ID 0x0118 0x03E0 0x0560 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA00__PWM1_OUT 0x0118 0x03E0 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA00__UART5_DTR_B 0x0118 0x03E0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA00__GPIO2_IO20 0x0118 0x03E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA00__ARM_TRACE00 0x0118 0x03E0 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA00__SRC_BOOT_CFG00 0x0118 0x03E0 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA01__LCD_DATA01 0x011C 0x03E4 0x06DC 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA01__ECSPI1_MISO 0x011C 0x03E4 0x0604 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA01__USB_OTG1_ID 0x011C 0x03E4 0x055C 0x2 0x3
+#define MX6SLL_PAD_LCD_DATA01__PWM2_OUT 0x011C 0x03E4 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA01__AUD4_RXFS 0x011C 0x03E4 0x0570 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA01__GPIO2_IO21 0x011C 0x03E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA01__ARM_TRACE01 0x011C 0x03E4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA01__SRC_BOOT_CFG01 0x011C 0x03E4 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA02__LCD_DATA02 0x0120 0x03E8 0x06E0 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA02__ECSPI1_SS0 0x0120 0x03E8 0x0614 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA02__EPIT2_OUT 0x0120 0x03E8 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA02__PWM3_OUT 0x0120 0x03E8 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA02__AUD4_RXC 0x0120 0x03E8 0x056C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA02__GPIO2_IO22 0x0120 0x03E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA02__ARM_TRACE02 0x0120 0x03E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA02__SRC_BOOT_CFG02 0x0120 0x03E8 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA03__LCD_DATA03 0x0124 0x03EC 0x06E4 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA03__ECSPI1_SCLK 0x0124 0x03EC 0x05FC 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA03__UART5_DSR_B 0x0124 0x03EC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA03__PWM4_OUT 0x0124 0x03EC 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA03__AUD4_RXD 0x0124 0x03EC 0x0564 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA03__GPIO2_IO23 0x0124 0x03EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA03__ARM_TRACE03 0x0124 0x03EC 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA03__SRC_BOOT_CFG03 0x0124 0x03EC 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA04__LCD_DATA04 0x0128 0x03F0 0x06E8 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA04__ECSPI1_SS1 0x0128 0x03F0 0x060C 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA04__CSI_VSYNC 0x0128 0x03F0 0x05F8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA04__WDOG2_RESET_B_DEB 0x0128 0x03F0 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA04__AUD4_TXC 0x0128 0x03F0 0x0574 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA04__GPIO2_IO24 0x0128 0x03F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA04__ARM_TRACE04 0x0128 0x03F0 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA04__SRC_BOOT_CFG04 0x0128 0x03F0 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA05__LCD_DATA05 0x012C 0x03F4 0x06EC 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA05__ECSPI1_SS2 0x012C 0x03F4 0x0610 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA05__CSI_HSYNC 0x012C 0x03F4 0x05F0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA05__AUD4_TXFS 0x012C 0x03F4 0x0578 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA05__GPIO2_IO25 0x012C 0x03F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA05__ARM_TRACE05 0x012C 0x03F4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA05__SRC_BOOT_CFG05 0x012C 0x03F4 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA06__LCD_DATA06 0x0130 0x03F8 0x06F0 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA06__ECSPI1_SS3 0x0130 0x03F8 0x0618 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA06__CSI_PIXCLK 0x0130 0x03F8 0x05F4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA06__AUD4_TXD 0x0130 0x03F8 0x0568 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA06__GPIO2_IO26 0x0130 0x03F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA06__ARM_TRACE06 0x0130 0x03F8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA06__SRC_BOOT_CFG06 0x0130 0x03F8 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA07__LCD_DATA07 0x0134 0x03FC 0x06F4 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA07__ECSPI1_RDY 0x0134 0x03FC 0x0600 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA07__CSI_MCLK 0x0134 0x03FC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA07__AUDIO_CLK_OUT 0x0134 0x03FC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA07__GPIO2_IO27 0x0134 0x03FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA07__ARM_TRACE07 0x0134 0x03FC 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA07__SRC_BOOT_CFG07 0x0134 0x03FC 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA08__LCD_DATA08 0x0138 0x0400 0x06F8 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA08__KEY_COL0 0x0138 0x0400 0x06A0 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA08__CSI_DATA09 0x0138 0x0400 0x05EC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA08__ECSPI2_SCLK 0x0138 0x0400 0x061C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA08__GPIO2_IO28 0x0138 0x0400 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA08__ARM_TRACE08 0x0138 0x0400 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA08__SRC_BOOT_CFG08 0x0138 0x0400 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA09__LCD_DATA09 0x013C 0x0404 0x06FC 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA09__KEY_ROW0 0x013C 0x0404 0x06C0 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA09__CSI_DATA08 0x013C 0x0404 0x05E8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA09__ECSPI2_MOSI 0x013C 0x0404 0x0624 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA09__GPIO2_IO29 0x013C 0x0404 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA09__ARM_TRACE09 0x013C 0x0404 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA09__SRC_BOOT_CFG09 0x013C 0x0404 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA10__LCD_DATA10 0x0140 0x0408 0x0700 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA10__KEY_COL1 0x0140 0x0408 0x06A4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA10__CSI_DATA07 0x0140 0x0408 0x05E4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA10__ECSPI2_MISO 0x0140 0x0408 0x0620 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA10__GPIO2_IO30 0x0140 0x0408 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA10__ARM_TRACE10 0x0140 0x0408 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA10__SRC_BOOT_CFG10 0x0140 0x0408 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA11__LCD_DATA11 0x0144 0x040C 0x0704 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA11__KEY_ROW1 0x0144 0x040C 0x06C4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA11__CSI_DATA06 0x0144 0x040C 0x05E0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA11__ECSPI2_SS1 0x0144 0x040C 0x062C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA11__GPIO2_IO31 0x0144 0x040C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA11__ARM_TRACE11 0x0144 0x040C 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA11__SRC_BOOT_CFG11 0x0144 0x040C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA12__LCD_DATA12 0x0148 0x0410 0x0708 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA12__KEY_COL2 0x0148 0x0410 0x06A8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA12__CSI_DATA05 0x0148 0x0410 0x05DC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA12__UART5_DCE_RTS 0x0148 0x0410 0x0760 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA12__UART5_DTE_CTS 0x0148 0x0410 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA12__GPIO3_IO00 0x0148 0x0410 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA12__ARM_TRACE12 0x0148 0x0410 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA12__SRC_BOOT_CFG12 0x0148 0x0410 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA13__LCD_DATA13 0x014C 0x0414 0x070C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA13__KEY_ROW2 0x014C 0x0414 0x06C8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA13__CSI_DATA04 0x014C 0x0414 0x05D8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA13__UART5_DCE_CTS 0x014C 0x0414 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA13__UART5_DTE_RTS 0x014C 0x0414 0x0760 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA13__GPIO3_IO01 0x014C 0x0414 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA13__ARM_TRACE13 0x014C 0x0414 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA13__SRC_BOOT_CFG13 0x014C 0x0414 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA14__LCD_DATA14 0x0150 0x0418 0x0710 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA14__KEY_COL3 0x0150 0x0418 0x06AC 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA14__CSI_DATA03 0x0150 0x0418 0x05D4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA14__UART5_DCE_RX 0x0150 0x0418 0x0764 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA14__UART5_DTE_TX 0x0150 0x0418 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA14__GPIO3_IO02 0x0150 0x0418 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA14__ARM_TRACE14 0x0150 0x0418 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA14__SRC_BOOT_CFG14 0x0150 0x0418 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA15__LCD_DATA15 0x0154 0x041C 0x0714 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA15__KEY_ROW3 0x0154 0x041C 0x06CC 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA15__CSI_DATA02 0x0154 0x041C 0x05D0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA15__UART5_DCE_TX 0x0154 0x041C 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA15__UART5_DTE_RX 0x0154 0x041C 0x0764 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA15__GPIO3_IO03 0x0154 0x041C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA15__ARM_TRACE15 0x0154 0x041C 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA15__SRC_BOOT_CFG15 0x0154 0x041C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA16__LCD_DATA16 0x0158 0x0420 0x0718 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA16__KEY_COL4 0x0158 0x0420 0x06B0 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA16__CSI_DATA01 0x0158 0x0420 0x05CC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA16__I2C2_SCL 0x0158 0x0420 0x0684 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA16__GPIO3_IO04 0x0158 0x0420 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA16__SRC_BOOT_CFG24 0x0158 0x0420 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA17__LCD_DATA17 0x015C 0x0424 0x071C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA17__KEY_ROW4 0x015C 0x0424 0x06D0 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA17__CSI_DATA00 0x015C 0x0424 0x05C8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA17__I2C2_SDA 0x015C 0x0424 0x0688 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA17__GPIO3_IO05 0x015C 0x0424 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA17__SRC_BOOT_CFG25 0x015C 0x0424 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA18__LCD_DATA18 0x0160 0x0428 0x0720 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA18__KEY_COL5 0x0160 0x0428 0x0694 0x1 0x2
+#define MX6SLL_PAD_LCD_DATA18__CSI_DATA15 0x0160 0x0428 0x05C4 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA18__GPT_CAPTURE1 0x0160 0x0428 0x0670 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA18__GPIO3_IO06 0x0160 0x0428 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA18__SRC_BOOT_CFG26 0x0160 0x0428 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA19__LCD_DATA19 0x0164 0x042C 0x0724 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA19__KEY_ROW5 0x0164 0x042C 0x06B4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA19__CSI_DATA14 0x0164 0x042C 0x05C0 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA19__GPT_CAPTURE2 0x0164 0x042C 0x0674 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA19__GPIO3_IO07 0x0164 0x042C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA19__SRC_BOOT_CFG27 0x0164 0x042C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA20__LCD_DATA20 0x0168 0x0430 0x0728 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA20__KEY_COL6 0x0168 0x0430 0x0698 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA20__CSI_DATA13 0x0168 0x0430 0x05BC 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA20__GPT_COMPARE1 0x0168 0x0430 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA20__GPIO3_IO08 0x0168 0x0430 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA20__SRC_BOOT_CFG28 0x0168 0x0430 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA21__LCD_DATA21 0x016C 0x0434 0x072C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA21__KEY_ROW6 0x016C 0x0434 0x06B8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA21__CSI_DATA12 0x016C 0x0434 0x05B8 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA21__GPT_COMPARE2 0x016C 0x0434 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA21__GPIO3_IO09 0x016C 0x0434 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA21__SRC_BOOT_CFG29 0x016C 0x0434 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA22__LCD_DATA22 0x0170 0x0438 0x0730 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA22__KEY_COL7 0x0170 0x0438 0x069C 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA22__CSI_DATA11 0x0170 0x0438 0x05B4 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA22__GPT_COMPARE3 0x0170 0x0438 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA22__GPIO3_IO10 0x0170 0x0438 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA22__SRC_BOOT_CFG30 0x0170 0x0438 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA23__LCD_DATA23 0x0174 0x043C 0x0734 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA23__KEY_ROW7 0x0174 0x043C 0x06BC 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA23__CSI_DATA10 0x0174 0x043C 0x05B0 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA23__GPT_CLKIN 0x0174 0x043C 0x0678 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA23__GPIO3_IO11 0x0174 0x043C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA23__SRC_BOOT_CFG31 0x0174 0x043C 0x0000 0x7 0x0
+#define MX6SLL_PAD_AUD_RXFS__AUD3_RXFS 0x0178 0x0440 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXFS__I2C1_SCL 0x0178 0x0440 0x067C 0x1 0x1
+#define MX6SLL_PAD_AUD_RXFS__UART3_DCE_RX 0x0178 0x0440 0x0754 0x2 0x0
+#define MX6SLL_PAD_AUD_RXFS__UART3_DTE_TX 0x0178 0x0440 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXFS__I2C3_SCL 0x0178 0x0440 0x068C 0x4 0x1
+#define MX6SLL_PAD_AUD_RXFS__GPIO1_IO00 0x0178 0x0440 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_RXFS__ECSPI3_SS0 0x0178 0x0440 0x0648 0x6 0x0
+#define MX6SLL_PAD_AUD_RXFS__MBIST_BEND 0x0178 0x0440 0x0000 0x7 0x0
+#define MX6SLL_PAD_AUD_RXC__AUD3_RXC 0x017C 0x0444 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXC__I2C1_SDA 0x017C 0x0444 0x0680 0x1 0x1
+#define MX6SLL_PAD_AUD_RXC__UART3_DCE_TX 0x017C 0x0444 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXC__UART3_DTE_RX 0x017C 0x0444 0x0754 0x2 0x1
+#define MX6SLL_PAD_AUD_RXC__I2C3_SDA 0x017C 0x0444 0x0690 0x4 0x1
+#define MX6SLL_PAD_AUD_RXC__GPIO1_IO01 0x017C 0x0444 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_RXC__ECSPI3_SS1 0x017C 0x0444 0x064C 0x6 0x0
+#define MX6SLL_PAD_AUD_RXD__AUD3_RXD 0x0180 0x0448 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXD__ECSPI3_MOSI 0x0180 0x0448 0x063C 0x1 0x0
+#define MX6SLL_PAD_AUD_RXD__UART4_DCE_RX 0x0180 0x0448 0x075C 0x2 0x0
+#define MX6SLL_PAD_AUD_RXD__UART4_DTE_TX 0x0180 0x0448 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXD__SD1_LCTL 0x0180 0x0448 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_RXD__GPIO1_IO02 0x0180 0x0448 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXC__AUD3_TXC 0x0184 0x044C 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXC__ECSPI3_MISO 0x0184 0x044C 0x0638 0x1 0x0
+#define MX6SLL_PAD_AUD_TXC__UART4_DCE_TX 0x0184 0x044C 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXC__UART4_DTE_RX 0x0184 0x044C 0x075C 0x2 0x1
+#define MX6SLL_PAD_AUD_TXC__SD2_LCTL 0x0184 0x044C 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_TXC__GPIO1_IO03 0x0184 0x044C 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXFS__AUD3_TXFS 0x0188 0x0450 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXFS__PWM3_OUT 0x0188 0x0450 0x0000 0x1 0x0
+#define MX6SLL_PAD_AUD_TXFS__UART4_DCE_RTS 0x0188 0x0450 0x0758 0x2 0x0
+#define MX6SLL_PAD_AUD_TXFS__UART4_DTE_CTS 0x0188 0x0450 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXFS__SD3_LCTL 0x0188 0x0450 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_TXFS__GPIO1_IO04 0x0188 0x0450 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXD__AUD3_TXD 0x018C 0x0454 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXD__ECSPI3_SCLK 0x018C 0x0454 0x0630 0x1 0x0
+#define MX6SLL_PAD_AUD_TXD__UART4_DCE_CTS 0x018C 0x0454 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXD__UART4_DTE_RTS 0x018C 0x0454 0x0758 0x2 0x1
+#define MX6SLL_PAD_AUD_TXD__GPIO1_IO05 0x018C 0x0454 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x0190 0x0458 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_MCLK__PWM4_OUT 0x0190 0x0458 0x0000 0x1 0x0
+#define MX6SLL_PAD_AUD_MCLK__ECSPI3_RDY 0x0190 0x0458 0x0634 0x2 0x0
+#define MX6SLL_PAD_AUD_MCLK__WDOG2_RESET_B_DEB 0x0190 0x0458 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_MCLK__GPIO1_IO06 0x0190 0x0458 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_MCLK__SPDIF_EXT_CLK 0x0190 0x0458 0x073C 0x6 0x1
+#define MX6SLL_PAD_UART1_RXD__UART1_DCE_RX 0x0194 0x045C 0x0744 0x0 0x0
+#define MX6SLL_PAD_UART1_RXD__UART1_DTE_TX 0x0194 0x045C 0x0000 0x0 0x0
+#define MX6SLL_PAD_UART1_RXD__PWM1_OUT 0x0194 0x045C 0x0000 0x1 0x0
+#define MX6SLL_PAD_UART1_RXD__UART4_DCE_RX 0x0194 0x045C 0x075C 0x2 0x4
+#define MX6SLL_PAD_UART1_RXD__UART4_DTE_TX 0x0194 0x045C 0x0000 0x2 0x0
+#define MX6SLL_PAD_UART1_RXD__UART5_DCE_RX 0x0194 0x045C 0x0764 0x4 0x6
+#define MX6SLL_PAD_UART1_RXD__UART5_DTE_TX 0x0194 0x045C 0x0000 0x4 0x0
+#define MX6SLL_PAD_UART1_RXD__GPIO3_IO16 0x0194 0x045C 0x0000 0x5 0x0
+#define MX6SLL_PAD_UART1_TXD__UART1_DCE_TX 0x0198 0x0460 0x0000 0x0 0x0
+#define MX6SLL_PAD_UART1_TXD__UART1_DTE_RX 0x0198 0x0460 0x0744 0x0 0x1
+#define MX6SLL_PAD_UART1_TXD__PWM2_OUT 0x0198 0x0460 0x0000 0x1 0x0
+#define MX6SLL_PAD_UART1_TXD__UART4_DCE_TX 0x0198 0x0460 0x0000 0x2 0x0
+#define MX6SLL_PAD_UART1_TXD__UART4_DTE_RX 0x0198 0x0460 0x075C 0x2 0x5
+#define MX6SLL_PAD_UART1_TXD__UART5_DCE_TX 0x0198 0x0460 0x0000 0x4 0x0
+#define MX6SLL_PAD_UART1_TXD__UART5_DTE_RX 0x0198 0x0460 0x0764 0x4 0x7
+#define MX6SLL_PAD_UART1_TXD__GPIO3_IO17 0x0198 0x0460 0x0000 0x5 0x0
+#define MX6SLL_PAD_UART1_TXD__UART5_DCD_B 0x0198 0x0460 0x0000 0x7 0x0
+#define MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x019C 0x0464 0x067C 0x0 0x0
+#define MX6SLL_PAD_I2C1_SCL__UART1_DCE_RTS 0x019C 0x0464 0x0740 0x1 0x0
+#define MX6SLL_PAD_I2C1_SCL__UART1_DTE_CTS 0x019C 0x0464 0x0000 0x1 0x0
+#define MX6SLL_PAD_I2C1_SCL__ECSPI3_SS2 0x019C 0x0464 0x0640 0x2 0x0
+#define MX6SLL_PAD_I2C1_SCL__SD3_RESET 0x019C 0x0464 0x0000 0x4 0x0
+#define MX6SLL_PAD_I2C1_SCL__GPIO3_IO12 0x019C 0x0464 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C1_SCL__ECSPI1_SS1 0x019C 0x0464 0x060C 0x6 0x0
+#define MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x01A0 0x0468 0x0680 0x0 0x0
+#define MX6SLL_PAD_I2C1_SDA__UART1_DCE_CTS 0x01A0 0x0468 0x0000 0x1 0x0
+#define MX6SLL_PAD_I2C1_SDA__UART1_DTE_RTS 0x01A0 0x0468 0x0740 0x1 0x1
+#define MX6SLL_PAD_I2C1_SDA__ECSPI3_SS3 0x01A0 0x0468 0x0644 0x2 0x0
+#define MX6SLL_PAD_I2C1_SDA__SD3_VSELECT 0x01A0 0x0468 0x0000 0x4 0x0
+#define MX6SLL_PAD_I2C1_SDA__GPIO3_IO13 0x01A0 0x0468 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C1_SDA__ECSPI1_SS2 0x01A0 0x0468 0x0610 0x6 0x0
+#define MX6SLL_PAD_I2C2_SCL__I2C2_SCL 0x01A4 0x046C 0x0684 0x0 0x3
+#define MX6SLL_PAD_I2C2_SCL__AUD4_RXFS 0x01A4 0x046C 0x0570 0x1 0x2
+#define MX6SLL_PAD_I2C2_SCL__SPDIF_IN 0x01A4 0x046C 0x0738 0x2 0x2
+#define MX6SLL_PAD_I2C2_SCL__SD3_WP 0x01A4 0x046C 0x0794 0x4 0x3
+#define MX6SLL_PAD_I2C2_SCL__GPIO3_IO14 0x01A4 0x046C 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C2_SCL__ECSPI1_RDY 0x01A4 0x046C 0x0600 0x6 0x1
+#define MX6SLL_PAD_I2C2_SDA__I2C2_SDA 0x01A8 0x0470 0x0688 0x0 0x3
+#define MX6SLL_PAD_I2C2_SDA__AUD4_RXC 0x01A8 0x0470 0x056C 0x1 0x2
+#define MX6SLL_PAD_I2C2_SDA__SPDIF_OUT 0x01A8 0x0470 0x0000 0x2 0x0
+#define MX6SLL_PAD_I2C2_SDA__SD3_CD_B 0x01A8 0x0470 0x0780 0x4 0x3
+#define MX6SLL_PAD_I2C2_SDA__GPIO3_IO15 0x01A8 0x0470 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x01AC 0x0474 0x05FC 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_SCLK__AUD4_TXD 0x01AC 0x0474 0x0568 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_SCLK__UART5_DCE_RX 0x01AC 0x0474 0x0764 0x2 0x2
+#define MX6SLL_PAD_ECSPI1_SCLK__UART5_DTE_TX 0x01AC 0x0474 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__EPDC_VCOM0 0x01AC 0x0474 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__SD2_RESET 0x01AC 0x0474 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__GPIO4_IO08 0x01AC 0x0474 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__USB_OTG2_OC 0x01AC 0x0474 0x0768 0x6 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x01B0 0x0478 0x0608 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__AUD4_TXC 0x01B0 0x0478 0x0574 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__UART5_DCE_TX 0x01B0 0x0478 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__UART5_DTE_RX 0x01B0 0x0478 0x0764 0x2 0x3
+#define MX6SLL_PAD_ECSPI1_MOSI__EPDC_VCOM1 0x01B0 0x0478 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__SD2_VSELECT 0x01B0 0x0478 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__GPIO4_IO09 0x01B0 0x0478 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x01B4 0x047C 0x0604 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_MISO__AUD4_TXFS 0x01B4 0x047C 0x0578 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_MISO__UART5_DCE_RTS 0x01B4 0x047C 0x0760 0x2 0x2
+#define MX6SLL_PAD_ECSPI1_MISO__UART5_DTE_CTS 0x01B4 0x047C 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__EPDC_BDR0 0x01B4 0x047C 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__SD2_WP 0x01B4 0x047C 0x077C 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__GPIO4_IO10 0x01B4 0x047C 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__ECSPI1_SS0 0x01B8 0x0480 0x0614 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_SS0__AUD4_RXD 0x01B8 0x0480 0x0564 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_SS0__UART5_DCE_CTS 0x01B8 0x0480 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__UART5_DTE_RTS 0x01B8 0x0480 0x0760 0x2 0x3
+#define MX6SLL_PAD_ECSPI1_SS0__EPDC_BDR1 0x01B8 0x0480 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__SD2_CD_B 0x01B8 0x0480 0x0778 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__GPIO4_IO11 0x01B8 0x0480 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__USB_OTG2_PWR 0x01B8 0x0480 0x0000 0x6 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__ECSPI2_SCLK 0x01BC 0x0484 0x061C 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_SCLK__SPDIF_EXT_CLK 0x01BC 0x0484 0x073C 0x1 0x2
+#define MX6SLL_PAD_ECSPI2_SCLK__UART3_DCE_RX 0x01BC 0x0484 0x0754 0x2 0x2
+#define MX6SLL_PAD_ECSPI2_SCLK__UART3_DTE_TX 0x01BC 0x0484 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__CSI_PIXCLK 0x01BC 0x0484 0x05F4 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_SCLK__SD1_RESET 0x01BC 0x0484 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__GPIO4_IO12 0x01BC 0x0484 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__USB_OTG2_OC 0x01BC 0x0484 0x0768 0x6 0x2
+#define MX6SLL_PAD_ECSPI2_MOSI__ECSPI2_MOSI 0x01C0 0x0488 0x0624 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_MOSI__SDMA_EXT_EVENT1 0x01C0 0x0488 0x0000 0x1 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__UART3_DCE_TX 0x01C0 0x0488 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__UART3_DTE_RX 0x01C0 0x0488 0x0754 0x2 0x3
+#define MX6SLL_PAD_ECSPI2_MOSI__CSI_HSYNC 0x01C0 0x0488 0x05F0 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_MOSI__SD1_VSELECT 0x01C0 0x0488 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__GPIO4_IO13 0x01C0 0x0488 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__ECSPI2_MISO 0x01C4 0x048C 0x0620 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_MISO__SDMA_EXT_EVENT0 0x01C4 0x048C 0x0000 0x1 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__UART3_DCE_RTS 0x01C4 0x048C 0x0750 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__UART3_DTE_CTS 0x01C4 0x048C 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__CSI_MCLK 0x01C4 0x048C 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__SD1_WP 0x01C4 0x048C 0x0774 0x4 0x2
+#define MX6SLL_PAD_ECSPI2_MISO__GPIO4_IO14 0x01C4 0x048C 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__USB_OTG1_OC 0x01C4 0x048C 0x076C 0x6 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__ECSPI2_SS0 0x01C8 0x0490 0x0628 0x0 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__ECSPI1_SS3 0x01C8 0x0490 0x0618 0x1 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__UART3_DCE_CTS 0x01C8 0x0490 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__UART3_DTE_RTS 0x01C8 0x0490 0x0750 0x2 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__CSI_VSYNC 0x01C8 0x0490 0x05F8 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__SD1_CD_B 0x01C8 0x0490 0x0770 0x4 0x2
+#define MX6SLL_PAD_ECSPI2_SS0__GPIO4_IO15 0x01C8 0x0490 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__USB_OTG1_PWR 0x01C8 0x0490 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD1_CLK__SD1_CLK 0x01CC 0x0494 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_CLK__KEY_COL0 0x01CC 0x0494 0x06A0 0x2 0x2
+#define MX6SLL_PAD_SD1_CLK__EPDC_SDCE4 0x01CC 0x0494 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_CLK__GPIO5_IO15 0x01CC 0x0494 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_CMD__SD1_CMD 0x01D0 0x0498 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_CMD__KEY_ROW0 0x01D0 0x0498 0x06C0 0x2 0x2
+#define MX6SLL_PAD_SD1_CMD__EPDC_SDCE5 0x01D0 0x0498 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_CMD__GPIO5_IO14 0x01D0 0x0498 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x01D4 0x049C 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA0__KEY_COL1 0x01D4 0x049C 0x06A4 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA0__EPDC_SDCE6 0x01D4 0x049C 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA0__GPIO5_IO11 0x01D4 0x049C 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x01D8 0x04A0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA1__KEY_ROW1 0x01D8 0x04A0 0x06C4 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA1__EPDC_SDCE7 0x01D8 0x04A0 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA1__GPIO5_IO08 0x01D8 0x04A0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x01DC 0x04A4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA2__KEY_COL2 0x01DC 0x04A4 0x06A8 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA2__EPDC_SDCE8 0x01DC 0x04A4 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA2__GPIO5_IO13 0x01DC 0x04A4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x01E0 0x04A8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA3__KEY_ROW2 0x01E0 0x04A8 0x06C8 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA3__EPDC_SDCE9 0x01E0 0x04A8 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA3__GPIO5_IO06 0x01E0 0x04A8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA4__SD1_DATA4 0x01E4 0x04AC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA4__KEY_COL3 0x01E4 0x04AC 0x06AC 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA4__EPDC_SDCLK_N 0x01E4 0x04AC 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA4__UART4_DCE_RX 0x01E4 0x04AC 0x075C 0x4 0x6
+#define MX6SLL_PAD_SD1_DATA4__UART4_DTE_TX 0x01E4 0x04AC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA4__GPIO5_IO12 0x01E4 0x04AC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA5__SD1_DATA5 0x01E8 0x04B0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA5__KEY_ROW3 0x01E8 0x04B0 0x06CC 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA5__EPDC_SDOED 0x01E8 0x04B0 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA5__UART4_DCE_TX 0x01E8 0x04B0 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA5__UART4_DTE_RX 0x01E8 0x04B0 0x075C 0x4 0x7
+#define MX6SLL_PAD_SD1_DATA5__GPIO5_IO09 0x01E8 0x04B0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA6__SD1_DATA6 0x01EC 0x04B4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA6__KEY_COL4 0x01EC 0x04B4 0x06B0 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA6__EPDC_SDOEZ 0x01EC 0x04B4 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA6__UART4_DCE_RTS 0x01EC 0x04B4 0x0758 0x4 0x4
+#define MX6SLL_PAD_SD1_DATA6__UART4_DTE_CTS 0x01EC 0x04B4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA6__GPIO5_IO07 0x01EC 0x04B4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA7__SD1_DATA7 0x01F0 0x04B8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA7__KEY_ROW4 0x01F0 0x04B8 0x06D0 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA7__CCM_PMIC_READY 0x01F0 0x04B8 0x05AC 0x3 0x3
+#define MX6SLL_PAD_SD1_DATA7__UART4_DCE_CTS 0x01F0 0x04B8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA7__UART4_DTE_RTS 0x01F0 0x04B8 0x0758 0x4 0x5
+#define MX6SLL_PAD_SD1_DATA7__GPIO5_IO10 0x01F0 0x04B8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_RESET__SD2_RESET 0x01F4 0x04BC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_RESET__WDOG2_B 0x01F4 0x04BC 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_RESET__SPDIF_OUT 0x01F4 0x04BC 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD2_RESET__CSI_MCLK 0x01F4 0x04BC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_RESET__GPIO4_IO27 0x01F4 0x04BC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_CLK__SD2_CLK 0x01F8 0x04C0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_CLK__AUD4_RXFS 0x01F8 0x04C0 0x0570 0x1 0x1
+#define MX6SLL_PAD_SD2_CLK__ECSPI3_SCLK 0x01F8 0x04C0 0x0630 0x2 0x1
+#define MX6SLL_PAD_SD2_CLK__CSI_DATA00 0x01F8 0x04C0 0x05C8 0x3 0x1
+#define MX6SLL_PAD_SD2_CLK__GPIO5_IO05 0x01F8 0x04C0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_CMD__SD2_CMD 0x01FC 0x04C4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_CMD__AUD4_RXC 0x01FC 0x04C4 0x056C 0x1 0x1
+#define MX6SLL_PAD_SD2_CMD__ECSPI3_SS0 0x01FC 0x04C4 0x0648 0x2 0x1
+#define MX6SLL_PAD_SD2_CMD__CSI_DATA01 0x01FC 0x04C4 0x05CC 0x3 0x1
+#define MX6SLL_PAD_SD2_CMD__EPIT1_OUT 0x01FC 0x04C4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_CMD__GPIO5_IO04 0x01FC 0x04C4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x0200 0x04C8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA0__AUD4_RXD 0x0200 0x04C8 0x0564 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA0__ECSPI3_MOSI 0x0200 0x04C8 0x063C 0x2 0x1
+#define MX6SLL_PAD_SD2_DATA0__CSI_DATA02 0x0200 0x04C8 0x05D0 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA0__UART5_DCE_RTS 0x0200 0x04C8 0x0760 0x4 0x4
+#define MX6SLL_PAD_SD2_DATA0__UART5_DTE_CTS 0x0200 0x04C8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA0__GPIO5_IO01 0x0200 0x04C8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x0204 0x04CC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA1__AUD4_TXC 0x0204 0x04CC 0x0574 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA1__ECSPI3_MISO 0x0204 0x04CC 0x0638 0x2 0x1
+#define MX6SLL_PAD_SD2_DATA1__CSI_DATA03 0x0204 0x04CC 0x05D4 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA1__UART5_DCE_CTS 0x0204 0x04CC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA1__UART5_DTE_RTS 0x0204 0x04CC 0x0760 0x4 0x5
+#define MX6SLL_PAD_SD2_DATA1__GPIO4_IO30 0x0204 0x04CC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x0208 0x04D0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA2__AUD4_TXFS 0x0208 0x04D0 0x0578 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA2__CSI_DATA04 0x0208 0x04D0 0x05D8 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA2__UART5_DCE_RX 0x0208 0x04D0 0x0764 0x4 0x4
+#define MX6SLL_PAD_SD2_DATA2__UART5_DTE_TX 0x0208 0x04D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA2__GPIO5_IO03 0x0208 0x04D0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x020C 0x04D4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA3__AUD4_TXD 0x020C 0x04D4 0x0568 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA3__CSI_DATA05 0x020C 0x04D4 0x05DC 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA3__UART5_DCE_TX 0x020C 0x04D4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA3__UART5_DTE_RX 0x020C 0x04D4 0x0764 0x4 0x5
+#define MX6SLL_PAD_SD2_DATA3__GPIO4_IO28 0x020C 0x04D4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA4__SD2_DATA4 0x0210 0x04D8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA4__SD3_DATA4 0x0210 0x04D8 0x0784 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA4__UART2_DCE_RX 0x0210 0x04D8 0x074C 0x2 0x2
+#define MX6SLL_PAD_SD2_DATA4__UART2_DTE_TX 0x0210 0x04D8 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA4__CSI_DATA06 0x0210 0x04D8 0x05E0 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA4__SPDIF_OUT 0x0210 0x04D8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA4__GPIO5_IO02 0x0210 0x04D8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA5__SD2_DATA5 0x0214 0x04DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA5__SD3_DATA5 0x0214 0x04DC 0x0788 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA5__UART2_DCE_TX 0x0214 0x04DC 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA5__UART2_DTE_RX 0x0214 0x04DC 0x074C 0x2 0x3
+#define MX6SLL_PAD_SD2_DATA5__CSI_DATA07 0x0214 0x04DC 0x05E4 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA5__SPDIF_IN 0x0214 0x04DC 0x0738 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA5__GPIO4_IO31 0x0214 0x04DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA6__SD2_DATA6 0x0218 0x04E0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA6__SD3_DATA6 0x0218 0x04E0 0x078C 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA6__UART2_DCE_RTS 0x0218 0x04E0 0x0748 0x2 0x2
+#define MX6SLL_PAD_SD2_DATA6__UART2_DTE_CTS 0x0218 0x04E0 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA6__CSI_DATA08 0x0218 0x04E0 0x05E8 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA6__SD2_WP 0x0218 0x04E0 0x077C 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA6__GPIO4_IO29 0x0218 0x04E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA7__SD2_DATA7 0x021C 0x04E4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA7__SD3_DATA7 0x021C 0x04E4 0x0790 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA7__UART2_DCE_CTS 0x021C 0x04E4 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA7__UART2_DTE_RTS 0x021C 0x04E4 0x0748 0x2 0x3
+#define MX6SLL_PAD_SD2_DATA7__CSI_DATA09 0x021C 0x04E4 0x05EC 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA7__SD2_CD_B 0x021C 0x04E4 0x0778 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA7__GPIO5_IO00 0x021C 0x04E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CLK__SD3_CLK 0x0220 0x04E8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_CLK__AUD5_RXFS 0x0220 0x04E8 0x0588 0x1 0x0
+#define MX6SLL_PAD_SD3_CLK__KEY_COL5 0x0220 0x04E8 0x0694 0x2 0x0
+#define MX6SLL_PAD_SD3_CLK__CSI_DATA10 0x0220 0x04E8 0x05B0 0x3 0x0
+#define MX6SLL_PAD_SD3_CLK__WDOG1_RESET_B_DEB 0x0220 0x04E8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_CLK__GPIO5_IO18 0x0220 0x04E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CLK__USB_OTG1_PWR 0x0220 0x04E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_CMD__SD3_CMD 0x0224 0x04EC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_CMD__AUD5_RXC 0x0224 0x04EC 0x0584 0x1 0x0
+#define MX6SLL_PAD_SD3_CMD__KEY_ROW5 0x0224 0x04EC 0x06B4 0x2 0x0
+#define MX6SLL_PAD_SD3_CMD__CSI_DATA11 0x0224 0x04EC 0x05B4 0x3 0x0
+#define MX6SLL_PAD_SD3_CMD__USB_OTG2_ID 0x0224 0x04EC 0x0560 0x4 0x1
+#define MX6SLL_PAD_SD3_CMD__GPIO5_IO21 0x0224 0x04EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CMD__USB_OTG2_PWR 0x0224 0x04EC 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x0228 0x04F0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA0__AUD5_RXD 0x0228 0x04F0 0x057C 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA0__KEY_COL6 0x0228 0x04F0 0x0698 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA0__CSI_DATA12 0x0228 0x04F0 0x05B8 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA0__USB_OTG1_ID 0x0228 0x04F0 0x055C 0x4 0x1
+#define MX6SLL_PAD_SD3_DATA0__GPIO5_IO19 0x0228 0x04F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x022C 0x04F4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA1__AUD5_TXC 0x022C 0x04F4 0x058C 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA1__KEY_ROW6 0x022C 0x04F4 0x06B8 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA1__CSI_DATA13 0x022C 0x04F4 0x05BC 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA1__SD1_VSELECT 0x022C 0x04F4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA1__GPIO5_IO20 0x022C 0x04F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA1__JTAG_DE_B 0x022C 0x04F4 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x0230 0x04F8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA2__AUD5_TXFS 0x0230 0x04F8 0x0590 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA2__KEY_COL7 0x0230 0x04F8 0x069C 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA2__CSI_DATA14 0x0230 0x04F8 0x05C0 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA2__EPIT1_OUT 0x0230 0x04F8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA2__GPIO5_IO16 0x0230 0x04F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA2__USB_OTG2_OC 0x0230 0x04F8 0x0768 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x0234 0x04FC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA3__AUD5_TXD 0x0234 0x04FC 0x0580 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA3__KEY_ROW7 0x0234 0x04FC 0x06BC 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA3__CSI_DATA15 0x0234 0x04FC 0x05C4 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA3__EPIT2_OUT 0x0234 0x04FC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA3__GPIO5_IO17 0x0234 0x04FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA3__USB_OTG1_OC 0x0234 0x04FC 0x076C 0x6 0x0
+#define MX6SLL_PAD_GPIO4_IO20__SD1_STROBE 0x0238 0x0500 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO20__AUD6_RXFS 0x0238 0x0500 0x05A0 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO20__ECSPI4_SS0 0x0238 0x0500 0x065C 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO20__GPT_CAPTURE1 0x0238 0x0500 0x0670 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO20__GPIO4_IO20 0x0238 0x0500 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO21__SD2_STROBE 0x023C 0x0504 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO21__AUD6_RXC 0x023C 0x0504 0x059C 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO21__ECSPI4_SCLK 0x023C 0x0504 0x0650 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO21__GPT_CAPTURE2 0x023C 0x0504 0x0674 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO21__GPIO4_IO21 0x023C 0x0504 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO19__SD3_STROBE 0x0240 0x0508 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO19__AUD6_RXD 0x0240 0x0508 0x0594 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO19__ECSPI4_MOSI 0x0240 0x0508 0x0658 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO19__GPT_COMPARE1 0x0240 0x0508 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO19__GPIO4_IO19 0x0240 0x0508 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO25__AUD6_TXC 0x0244 0x050C 0x05A4 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO25__ECSPI4_MISO 0x0244 0x050C 0x0654 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO25__GPT_COMPARE2 0x0244 0x050C 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO25__GPIO4_IO25 0x0244 0x050C 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO18__AUD6_TXFS 0x0248 0x0510 0x05A8 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO18__ECSPI4_SS1 0x0248 0x0510 0x0660 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO18__GPT_COMPARE3 0x0248 0x0510 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO18__GPIO4_IO18 0x0248 0x0510 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO24__AUD6_TXD 0x024C 0x0514 0x0598 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO24__ECSPI4_SS2 0x024C 0x0514 0x0664 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO24__GPT_CLKIN 0x024C 0x0514 0x0678 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x024C 0x0514 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO23__AUDIO_CLK_OUT 0x0250 0x0518 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO23__SD1_RESET 0x0250 0x0518 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO23__SD3_RESET 0x0250 0x0518 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO23__GPIO4_IO23 0x0250 0x0518 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO17__USB_OTG1_ID 0x0254 0x051C 0x055C 0x2 0x2
+#define MX6SLL_PAD_GPIO4_IO17__SD1_VSELECT 0x0254 0x051C 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO17__SD3_VSELECT 0x0254 0x051C 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO17__GPIO4_IO17 0x0254 0x051C 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SPDIF_IN 0x0258 0x0520 0x0738 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SD1_WP 0x0258 0x0520 0x0774 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SD3_WP 0x0258 0x0520 0x0794 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO22__GPIO4_IO22 0x0258 0x0520 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SPDIF_OUT 0x025C 0x0524 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SD1_CD_B 0x025C 0x0524 0x0770 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SD3_CD_B 0x025C 0x0524 0x0780 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO16__GPIO4_IO16 0x025C 0x0524 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO26__WDOG1_B 0x0260 0x0528 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO26__PWM4_OUT 0x0260 0x0528 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO26__CCM_PMIC_READY 0x0260 0x0528 0x05AC 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO26__GPIO4_IO26 0x0260 0x0528 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO26__SPDIF_EXT_CLK 0x0260 0x0528 0x073C 0x6 0x0
+
+#endif /* __DTS_IMX6SLL_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
new file mode 100644
index 000000000000..675bac0572b7
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll.dtsi
@@ -0,0 +1,859 @@
+/*
+ * Copyright 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 <dt-bindings/clock/imx6sll-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "imx6sll-pinfunc.h"
+#include "skeleton.dtsi"
+
+/ {
+ aliases {
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ gpio3 = &gpio4;
+ gpio4 = &gpio5;
+ gpio5 = &gpio6;
+ i2c0 = &i2c1;
+ i2c1 = &i2c2;
+ i2c2 = &i2c3;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc3;
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ serial4 = &uart5;
+ spi0 = &ecspi1;
+ spi1 = &ecspi2;
+ spi3 = &ecspi3;
+ spi4 = &ecspi4;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ operating-points = <
+ /* kHz uV */
+ 996000 1225000
+ 792000 1175000
+ 396000 1075000
+ 198000 975000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC-PU uV */
+ 996000 1225000
+ 792000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ clock-latency = <61036>; /* two CLK32 periods */
+ 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>,
+ <&clks IMX6SLL_PLL1_BYPASS>,
+ <&clks IMX6SLL_PLL1_BYPASS_SRC>;
+ clock-names = "arm", "pll2_pfd2_396m", "step",
+ "pll1_sw", "pll1_sys", "pll1", "pll1_bypass",
+ "pll1_bypass_src";
+ };
+ };
+
+ intc: interrupt-controller@00a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a00100 0x100>;
+ interrupt-parent = <&intc>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil: clock@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "ckil";
+ };
+
+ osc: clock@1 {
+ compatible = "fixed-clock";
+ reg = <1>;
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc";
+ };
+
+ ipp_di0: clock@2 {
+ compatible = "fixed-clock";
+ reg = <2>;
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di0";
+ };
+
+ ipp_di1: clock@3 {
+ compatible = "fixed-clock";
+ reg = <3>;
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di1";
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gpc>;
+ ranges;
+
+ 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@00900000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x00900000 0x4000>;
+ };
+
+ ocrams_ddr: sram@00904000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x00904000 0x1000>;
+ };
+
+ ocram: sram@00905000 {
+ compatible = "mmio-sram";
+ reg = <0x00905000 0x1B000>;
+ };
+
+ L2: l2-cache@00a02000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x00a02000 0x1000>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ cache-unified;
+ cache-level = <2>;
+ arm,tag-latency = <4 2 3>;
+ arm,data-latency = <4 2 3>;
+ };
+
+ aips1: aips-bus@02000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x100000>;
+ ranges;
+
+ spba: spba-bus@02000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x40000>;
+ ranges;
+
+ spdif: spdif@02004000 {
+ compatible = "fsl,imx6sl-spdif", "fsl,imx35-spdif";
+ reg = <0x02004000 0x4000>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 14 18 0>, <&sdma 15 18 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_SPDIF_GCLK>,
+ <&clks IMX6SLL_CLK_OSC>,
+ <&clks IMX6SLL_CLK_SPDIF>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_IPG>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_SPBA>;
+ clock-names = "core", "rxtx0",
+ "rxtx1", "rxtx2",
+ "rxtx3", "rxtx4",
+ "rxtx5", "rxtx6",
+ "rxtx7", "spba";
+ status = "disabled";
+ };
+
+ ecspi1: ecspi@02008000 {
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02008000 0x4000>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_ECSPI1>,
+ <&clks IMX6SLL_CLK_ECSPI1>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi2: ecspi@0200c000 {
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x0200c000 0x4000>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_ECSPI2>,
+ <&clks IMX6SLL_CLK_ECSPI2>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi3: ecspi@02010000 {
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02010000 0x4000>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_ECSPI3>,
+ <&clks IMX6SLL_CLK_ECSPI3>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi4: ecspi@02014000 {
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02014000 0x4000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_ECSPI4>,
+ <&clks IMX6SLL_CLK_ECSPI4>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart4: serial@02018000 {
+ compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02018000 0x4000>;
+ interrupts =<GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART4_IPG>,
+ <&clks IMX6SLL_CLK_UART4_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart1: serial@02020000 {
+ compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02020000 0x4000>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART1_IPG>,
+ <&clks IMX6SLL_CLK_UART1_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart2: serial@02024000 {
+ compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02024000 0x4000>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART2_IPG>,
+ <&clks IMX6SLL_CLK_UART2_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ssi1: ssi@02028000 {
+ compatible = "fsl,imx6sll-ssi", "fsl,imx51-ssi";
+ reg = <0x02028000 0x4000>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 37 22 0>, <&sdma 38 22 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ clocks = <&clks IMX6SLL_CLK_SSI1_IPG>,
+ <&clks IMX6SLL_CLK_SSI1>;
+ clock-names = "ipg", "baud";
+ status = "disabled";
+ };
+
+ ssi2: ssi2@0202c000 {
+ compatible = "fsl,imx6sll-ssi", "fsl,imx51-ssi";
+ reg = <0x0202c000 0x4000>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 41 22 0>, <&sdma 42 22 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ clocks = <&clks IMX6SLL_CLK_SSI2_IPG>,
+ <&clks IMX6SLL_CLK_SSI2>;
+ clock-names = "ipg", "baud";
+ status = "disabled";
+ };
+
+ ssi3: ssi@02030000 {
+ compatible = "fsl,imx6sll-ssi", "fsl,imx51-ssi";
+ reg = <0x02030000 0x4000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 45 22 0>, <&sdma 46 22 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ clocks = <&clks IMX6SLL_CLK_SSI3_IPG>,
+ <&clks IMX6SLL_CLK_SSI3>;
+ clock-names = "ipg", "baud";
+ status = "disabled";
+ };
+
+ uart3: serial@02034000 {
+ compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02034000 0x4000>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+ dma-name = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART3_IPG>,
+ <&clks IMX6SLL_CLK_UART3_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+ };
+
+ pwm1: pwm@02080000 {
+ compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+ reg = <0x02080000 0x4000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_PWM1>,
+ <&clks IMX6SLL_CLK_PWM1>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm2: pwm@02084000 {
+ compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+ reg = <0x02084000 0x4000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_PWM2>,
+ <&clks IMX6SLL_CLK_PWM2>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm3: pwm@02088000 {
+ compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+ reg = <0x02088000 0x4000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_PWM3>,
+ <&clks IMX6SLL_CLK_PWM3>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm4: pwm@0208c000 {
+ compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+ reg = <0x0208c000 0x4000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_PWM4>,
+ <&clks IMX6SLL_CLK_PWM4>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ gpt1: gpt@02098000 {
+ compatible = "fsl,imx6sll-gpt";
+ reg = <0x02098000 0x4000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_GPT_BUS>,
+ <&clks IMX6SLL_CLK_GPT_3M>;
+ clock-names = "ipg", "osc_per";
+ };
+
+ gpio1: gpio@0209c000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x0209c000 0x4000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio@020a0000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020a0000 0x4000>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio@020a4000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020a4000 0x4000>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio4: gpio@020a8000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020a8000 0x4000>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio5: gpio@020ac000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020ac000 0x4000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio6: gpio@020b0000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020b0000 0x4000>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ kpp: kpp@020b8000 {
+ compatible = "fsl,imx6sll-kpp", "fsl,imx21-kpp";
+ reg = <0x020b8000 0x4000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_KPP>;
+ status = "disabled";
+ };
+
+ wdog1: wdog@020bc000 {
+ compatible = "fsl,imx6sll-wdt", "fsl,imx21-wdt";
+ reg = <0x020bc000 0x4000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_WDOG1>;
+ };
+
+ wdog2: wdog@020c0000 {
+ compatible = "fsl,imx6sll-wdt", "fsl,imx21-wdt";
+ reg = <0x020c0000 0x4000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_WDOG2>;
+ status = "disabled";
+ };
+
+ clks: ccm@020c4000 {
+ compatible = "fsl,imx6sll-ccm";
+ reg = <0x020c4000 0x4000>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ #clock-cells = <1>;
+ clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
+ clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
+ };
+
+ anatop: anatop@020c8000 {
+ compatible = "fsl,imx6sll-anatop",
+ "fsl,imx6q-anatop",
+ "syscon", "simple-bus";
+ reg = <0x020c8000 0x4000>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+
+ reg_3p0: regulator-3p0@120 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vdd3p0";
+ regulator-min-microvolt = <2625000>;
+ regulator-max-microvolt = <3400000>;
+ anatop-reg-offset = <0x120>;
+ anatop-vol-bit-shift = <8>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <0>;
+ anatop-min-voltage = <2625000>;
+ anatop-max-voltage = <3400000>;
+ anatop-enable-bit = <0>;
+ };
+ };
+
+ tempmon: tempmon {
+ compatible = "fsl,imx6sll-tempmon", "fsl,imx6sx-tempmon";
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,tempmon = <&anatop>;
+ fsl,tempmon-data = <&ocotp>;
+ clocks = <&clks IMX6SLL_CLK_PLL3_USB_OTG>;
+ };
+
+ usbphy1: usbphy@020c9000 {
+ compatible = "fsl,imx6sll-usbphy", "fsl,imx6ul-usbphy",
+ "fsl,imx23-usbphy";
+ reg = <0x020c9000 0x1000>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBPHY1>;
+ phy-3p0-supply = <&reg_3p0>;
+ fsl,anatop = <&anatop>;
+ };
+
+ usbphy2: usbphy@020ca000 {
+ compatible = "fsl,imx6sll-usbphy", "fsl,imx6ul-usbphy",
+ "fsl,imx23-usbphy";
+ reg = <0x020ca000 0x1000>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBPHY2>;
+ phy-reg_3p0-supply = <&reg_3p0>;
+ fsl,anatop = <&anatop>;
+ };
+
+ snvs: snvs@020cc000 {
+ compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
+ reg = <0x020cc000 0x4000>;
+
+ snvs_rtc: snvs-rtc-lp {
+ compatible = "fsl,sec-v4.0-mon-rtc-lp";
+ regmap = <&snvs>;
+ offset = <0x34>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ snvs_poweroff: snvs-poweroff {
+ compatible = "syscon-poweroff";
+ regmap = <&snvs>;
+ offset = <0x38>;
+ mask = <0x61>;
+ };
+
+ snvs_pwrkey: snvs-powerkey {
+ compatible = "fsl,sec-v4.0-pwrkey";
+ regmap = <&snvs>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ linux,keycode = <KEY_POWER>;
+ wakeup-source;
+ };
+ };
+
+ epit1: epit@020d0000 {
+ reg = <0x020d0000 0x4000>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ epit2: epit@020d4000 {
+ reg = <0x020d4000 0x4000>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ src: src@020d8000 {
+ compatible = "fsl,imx6sll-src", "fsl,imx51-src";
+ reg = <0x020d8000 0x4000>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ #reset-cells = <1>;
+ };
+
+ gpc: gpc@020dc000 {
+ compatible = "fsl,imx6sll-gpc", "fsl,imx6q-gpc";
+ reg = <0x020dc000 0x4000>;
+ interrupt-controller;
+ #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@020e0000 {
+ compatible = "fsl,imx6sll-iomuxc";
+ reg = <0x020e0000 0x4000>;
+ };
+
+ gpr: iomuxc-gpr@020e4000 {
+ compatible = "fsl,imx6sll-iomuxc-gpr",
+ "fsl,imx6q-iomuxc-gpr", "syscon";
+ reg = <0x020e4000 0x4000>;
+ };
+
+ csi: csi@020e8000 {
+ compatible = "fsl,imx6sll-csi", "fsl,imx6s-csi";
+ reg = <0x020e8000 0x4000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_CSI>,
+ <&clks IMX6SLL_CLK_DUMMY>;
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+ status = "disabled";
+ };
+
+ sdma: sdma@020ec000 {
+ compatible = "fsl,imx6ul-sdma", "fsl,imx35-sdma";
+ reg = <0x020ec000 0x4000>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_SDMA>,
+ <&clks IMX6SLL_CLK_SDMA>;
+ clock-names = "ipg", "ahb";
+ #dma-cells = <3>;
+ iram = <&ocram>;
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
+ };
+
+ pxp: pxp@020f0000 {
+ compatible = "fsl,imx6ull-pxp-dma", "fsl,imx7d-pxp-dma";
+ reg = <0x020f0000 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@020f4000 {
+ compatible = "fsl,imx6sll-epdc", "fsl,imx7d-epdc";
+ reg = <0x020f4000 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: lcdif@020f8000 {
+ compatible = "fsl,imx6sll-lcdif", "fsl,imx28-lcdif";
+ reg = <0x020f8000 0x4000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_LCDIF_PIX>,
+ <&clks IMX6SLL_CLK_LCDIF_APB>,
+ <&clks IMX6SLL_CLK_DUMMY>;
+ clock-names = "pix", "axi", "disp_axi";
+ status = "disabled";
+ };
+
+ dcp: dcp@020fc000 {
+ compatible = "fsl,imx6sl-dcp";
+ reg = <0x020fc000 0x4000>;
+ interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DCP>;
+ clock-names = "dcp";
+ };
+ };
+
+ aips2: aips-bus@02100000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02100000 0x100000>;
+ ranges;
+
+ usbotg1: usb@02184000 {
+ compatible = "fsl,imx6sll-usb", "fsl,imx6ul-usb",
+ "fsl,imx27-usb";
+ reg = <0x02184000 0x200>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBOH3>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc 0>;
+ fsl,anatop = <&anatop>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+ status = "disabled";
+ };
+
+ usbotg2: usb@02184200 {
+ compatible = "fsl,imx6sll-usb", "fsl,imx6ul-usb",
+ "fsl,imx27-usb";
+ reg = <0x02184200 0x200>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBOH3>;
+ fsl,usbphy = <&usbphy2>;
+ fsl,usbmisc = <&usbmisc 1>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+ status = "disabled";
+ };
+
+ usbmisc: usbmisc@02184800 {
+ #index-cells = <1>;
+ compatible = "fsl,imx6sll-usbmisc", "fsl,imx6ul-usbmisc",
+ "fsl,imx6q-usbmisc";
+ reg = <0x02184800 0x200>;
+ };
+
+ usdhc1: usdhc@02190000 {
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx7d-usdhc";
+ reg = <0x02190000 0x4000>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USDHC1>,
+ <&clks IMX6SLL_CLK_USDHC1>,
+ <&clks IMX6SLL_CLK_USDHC1>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
+ status = "disabled";
+ };
+
+ usdhc2: usdhc@02194000 {
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx7d-usdhc";
+ reg = <0x02194000 0x4000>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USDHC2>,
+ <&clks IMX6SLL_CLK_USDHC2>,
+ <&clks IMX6SLL_CLK_USDHC2>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
+ status = "disabled";
+ };
+
+ usdhc3: usdhc@02198000 {
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx7d-usdhc";
+ reg = <0x02198000 0x4000>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USDHC3>,
+ <&clks IMX6SLL_CLK_USDHC3>,
+ <&clks IMX6SLL_CLK_USDHC3>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@021a0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fs,imx6sll-i2c", "fsl,imx21-i2c";
+ reg = <0x021a0000 0x4000>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_I2C1>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@021a4000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sll-i2c", "fsl,imx21-i2c";
+ reg = <0x021a4000 0x4000>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_I2C2>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@021a8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sll-i2c", "fsl,imx21-i2c";
+ reg = <0x021a8000 0x4000>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_I2C3>;
+ status = "disabled";
+ };
+
+ romcp@021ac000 {
+ compatible = "fsl,imx6sll-romcp", "syscon";
+ reg = <0x021ac000 0x4000>;
+ };
+
+ mmdc: mmdc@021b0000 {
+ compatible = "fsl,imx6sll-mmdc", "fsl,imx6q-mmdc";
+ reg = <0x021b0000 0x4000>;
+ };
+
+ rngb: rngb@021b4000 {
+ compatible = "fsl,imx6sl-rng", "fsl,imx-rng", "imx-rng";
+ reg = <0x021b4000 0x4000>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DUMMY>;
+ };
+
+ ocotp: ocotp-ctrl@021bc000 {
+ compatible = "fsl,imx6sll-ocotp", "syscon";
+ reg = <0x021bc000 0x4000>;
+ clocks = <&clks IMX6SLL_CLK_OCOTP>;
+ };
+
+ csu: csu@021c0000 {
+ compatible = "fsl,imx6sll-csu";
+ reg = <0x021c0000 0x4000>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ snvs_gpr: snvs-gpr@0x021c4000 {
+ compatible = "fsl, imx6sll-snvs-gpr";
+ reg = <0x021c4000 0x10000>;
+ };
+
+ iomuxc_snvs: iomuxc-snvs@021c8000 {
+ compatible = "fsl,imx6sll-iomuxc-snvs";
+ reg = <0x021c80000 0x10000>;
+ };
+
+ audmux: audmux@021d8000 {
+ compatible = "fsl,imx6sll-audmux", "fsl,imx31-audmux";
+ reg = <0x021d8000 0x4000>;
+ status = "disabled";
+ };
+
+ uart5: serial@021f4000 {
+ compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021f4000 0x4000>;
+ interrupts =<GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART5_IPG>,
+ <&clks IMX6SLL_CLK_UART5_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6sx-14x14-arm2.dts b/arch/arm/boot/dts/imx6sx-14x14-arm2.dts
new file mode 100644
index 000000000000..3a04d28b0e80
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-14x14-arm2.dts
@@ -0,0 +1,1333 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "imx6sx.dtsi"
+
+/ {
+ model = "Freescale i.MX6 SoloX 14x14 ARM2 Board";
+ compatible = "fsl,imx6sx-14x14-lpddr2-arm2", "fsl,imx6sx";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm3 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ };
+
+ clocks {
+ codec_osc: codec_osc {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <12000000>;
+ };
+ };
+
+ max7322_reset: max7322-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1>;
+ #reset-cells = <0>;
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_3p3v: 3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_sdb_vmmc: sdb_vmmc{
+ compatible = "regulator-fixed";
+ regulator-name = "SD2_SPWR";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 11 GPIO_ACTIVE_LOW>;
+ off-on-delay = <20000>;
+ };
+
+ reg_usb_otg1_vbus: usb_otg1_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 9 0>;
+ enable-active-high;
+ };
+
+ reg_usb_otg2_vbus: usb_otg2_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 12 0>;
+ enable-active-high;
+ };
+
+ reg_vref_3v3: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ sound {
+ compatible = "fsl,imx6sx-arm2-sgtl5000",
+ "fsl,imx-audio-sgtl5000";
+ model = "imx6sx-arm2-sgtl5000";
+ cpu-dai = <&ssi1>;
+ audio-codec = <&codec>;
+ audio-routing =
+ "LINE_IN", "Line In Jack",
+ "Headphone Jack", "HP_OUT";
+ mux-int-port = <1>;
+ mux-ext-port = <4>;
+ };
+};
+
+&adc1 {
+ vref-supply = <&reg_vref_3v3>;
+ status = "okay";
+};
+
+&adc2 {
+ vref-supply = <&reg_vref_3v3>;
+ status = "okay";
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux_2>;
+ status = "okay";
+};
+
+&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>;
+};
+
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&ecspi4 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio7 4 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi4_1 &pinctrl_ecspi4_cs_1>;
+ status = "disabled"; /* pin conflict with USDHC3 */
+
+ flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,m25p32";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1_1>;
+ phy-mode = "rgmii";
+ phy-id = <1>;
+ fsl,num_tx_queues=<3>;
+ fsl,num_rx_queues=<3>;
+ pinctrl-assert-gpios = <&max7322_1 0 GPIO_ACTIVE_HIGH>;
+ fsl,magic-packet;
+ status = "okay";
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2_1>;
+ phy-mode = "rgmii";
+ phy-id = <0>;
+ fsl,num_tx_queues=<3>;
+ fsl,num_rx_queues=<3>;
+ pinctrl-assert-gpios = <&max7322_2 0 GPIO_ACTIVE_HIGH>;
+ fsl,magic-packet;
+ status = "okay";
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1_1>;
+ trx-en-gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>;
+ trx-stby-gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+ trx-err-gpio = <&gpio4 24 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2_1>;
+ trx-en-gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>;
+ trx-stby-gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+ trx-err-gpio = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0x2>;
+ fsl,cpu_pupscr_sw = <0x1>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <1>; /* use ldo-bypass, u-boot will check it and configure */
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "disabled"; /* pin conflict with qspi*/
+ nand-on-flash-bbt;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze200";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2_1>;
+ status = "okay";
+
+ max7322_1: gpio@68 {
+ compatible = "maxim,max7322";
+ reg = <0x68>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ resets = <&max7322_reset>;
+ };
+
+ max7322_2: gpio@69 {
+ compatible = "maxim,max7322";
+ reg = <0x69>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ resets = <&max7322_reset>;
+ };
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ clocks = <&codec_osc>;
+ VDDA-supply = <&vgen4_reg>;
+ VDDIO-supply = <&reg_3p3v>;
+ };
+};
+
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3_1>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4_1>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+
+ hog {
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x1f059
+ MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x1f059
+ MX6SX_PAD_QSPI1A_SS0_B__GPIO4_IO_22 0x80000000
+ /* CAN1_2_EN */
+ MX6SX_PAD_QSPI1B_DATA1__GPIO4_IO_25 0x17059
+ /* CAN1_2_STBY_B */
+ MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27 0x17059
+ /* CAN1_ERR_B */
+ MX6SX_PAD_QSPI1B_DATA0__GPIO4_IO_24 0x17059
+ /* CAN2_ERR_B */
+ MX6SX_PAD_QSPI1B_SS0_B__GPIO4_IO_30 0x17059
+ /* SD2_PWROFF */
+ MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
+ >;
+ };
+ };
+};
+
+&lcdif1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat_0
+ &pinctrl_lcdif_ctrl_0>;
+ 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>;
+ };
+ };
+ };
+};
+
+&mlb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mlb_1>;
+ status = "disabled";/* pin conflict with usdhc2*/
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3_0>;
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&qspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi2_1>;
+ status = "okay";
+ ddrsmp=<2>;
+
+ flash0: n25q256a@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ reg = <0>;
+ };
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ reg = <1>;
+ };
+};
+
+&sai2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2_1>;
+ status = "disabled";
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif_1>;
+ status = "disabled";
+};
+
+&ssi1 {
+ fsl,mode = "i2s-slave";
+ status = "okay";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_1>;
+ status = "okay";
+};
+
+&usbh {
+ pinctrl-names = "idle", "active";
+ pinctrl-0 = <&pinctrl_usbh_1>;
+ pinctrl-1 = <&pinctrl_usbh_2>;
+ osc-clkgate-delay = <0x3>;
+ pad-supply = <&vgen1_reg>;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1_1>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usbotg2 {
+ /*
+ * Pin conflict with others, need to switch R580 & R579
+ * to B and disable pwm3 to enable it.
+ */
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ disable-over-current;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg2_1>;
+ status = "disabled";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2_1>;
+ non-removable;
+ /* need hw rework to enable signal voltage switch */
+ no-1-8-v;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3_1>;
+ pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
+ bus-width = <8>;
+ cd-gpios = <&gpio2 10 0>;
+ wp-gpios = <&gpio2 15 0>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sdb_vmmc>;
+ status = "okay";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4_1>;
+ bus-width = <8>;
+ non-removable;
+ /* need hw rework to enable signal voltage switch */
+ no-1-8-v;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
+
+&iomuxc {
+ audmux {
+ pinctrl_audmux_1: audmuxgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130B0
+ MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x130B0
+ MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x120B0
+ MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x130B0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130B0
+ >;
+ };
+
+ pinctrl_audmux_2: audmuxgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_COL__AUDMUX_AUD4_TXC 0x130b0
+ MX6SX_PAD_ENET1_CRS__AUDMUX_AUD4_TXD 0x130b0
+ MX6SX_PAD_ENET1_RX_CLK__AUDMUX_AUD4_TXFS 0x130b0
+ MX6SX_PAD_ENET1_TX_CLK__AUDMUX_AUD4_RXD 0x130b0
+ >;
+ };
+
+ 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
+ >;
+ };
+ };
+
+ ecspi4 {
+ pinctrl_ecspi4_cs_1: ecspi4_cs_grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_DATA2__GPIO7_IO_4 0x80000000
+ >;
+ };
+
+ pinctrl_ecspi4_1: ecspi4grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_DATA3__ECSPI4_MISO 0x100b1
+ MX6SX_PAD_SD3_CMD__ECSPI4_MOSI 0x100b1
+ MX6SX_PAD_SD3_CLK__ECSPI4_SCLK 0x100b1
+ >;
+ };
+ };
+
+ csi {
+ 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_csi_1: csigrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_MCLK__CSI1_MCLK 0x110b0
+ MX6SX_PAD_CSI_PIXCLK__CSI1_PIXCLK 0x110b0
+ MX6SX_PAD_CSI_VSYNC__CSI1_VSYNC 0x110b0
+ MX6SX_PAD_CSI_HSYNC__CSI1_HSYNC 0x110b0
+ MX6SX_PAD_CSI_DATA00__CSI1_DATA_2 0x110b0
+ MX6SX_PAD_CSI_DATA01__CSI1_DATA_3 0x110b0
+ MX6SX_PAD_CSI_DATA02__CSI1_DATA_4 0x110b0
+ MX6SX_PAD_CSI_DATA03__CSI1_DATA_5 0x110b0
+ MX6SX_PAD_CSI_DATA04__CSI1_DATA_6 0x110b0
+ MX6SX_PAD_CSI_DATA05__CSI1_DATA_7 0x110b0
+ MX6SX_PAD_CSI_DATA06__CSI1_DATA_8 0x110b0
+ MX6SX_PAD_CSI_DATA07__CSI1_DATA_9 0x110b0
+
+ MX6SX_PAD_LCD1_ENABLE__GPIO3_IO_25 0x80000000
+ MX6SX_PAD_LCD1_HSYNC__GPIO3_IO_26 0x80000000
+ >;
+ };
+ };
+
+ enet1 {
+ pinctrl_enet1_1: enet1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
+ MX6SX_PAD_ENET1_MDC__ENET1_MDC 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
+ MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
+ MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ >;
+ };
+
+ pinctrl_enet1_clkout_1: enet1_clkoutgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x91
+ >;
+ };
+ };
+
+ enet2 {
+ pinctrl_enet2_1: enet2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
+ MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
+ >;
+ };
+ };
+
+ esai {
+ pinctrl_esai_1: esaigrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_MCLK__ESAI_TX_HF_CLK 0x1b030
+ 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_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
+ >;
+ };
+ };
+
+ flexcan1 {
+ pinctrl_flexcan1_1: flexcan1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b020
+ MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x1b020
+ >;
+ };
+ };
+
+ flexcan2 {
+ pinctrl_flexcan2_1: flexcan2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x1b020
+ MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x1b020
+ >;
+ };
+ };
+
+ gpmi-nand {
+ 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
+ >;
+ };
+ };
+
+ i2c1 {
+ pinctrl_i2c1_1: i2c1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c1_2: i2c1grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA01__I2C1_SDA 0x4001b8b1
+ MX6SX_PAD_CSI_DATA00__I2C1_SCL 0x4001b8b1
+ >;
+ };
+ };
+
+ i2c2 {
+ pinctrl_i2c2_1: i2c2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO03__I2C2_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO02__I2C2_SCL 0x4001b8b1
+ >;
+ };
+ };
+
+ i2c3 {
+ pinctrl_i2c3_1: i2c3grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_TX_CLK__I2C3_SDA 0x4001b8b1
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3_2: i2c3grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
+ };
+
+ i2c4 {
+ pinctrl_i2c4_1: i2c4grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x4001b8b1
+ MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x4001b8b1
+ >;
+ };
+ pinctrl_i2c4_2: i2c4grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_DATA1__I2C4_SDA 0x4001b8b1
+ MX6SX_PAD_SD3_DATA0__I2C4_SCL 0x4001b8b1
+ >;
+ };
+ };
+
+ lcdif1 {
+ pinctrl_lcdif_dat_0: lcdifdatgrp-0 {
+ fsl,pins = <
+ MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0
+ >;
+ };
+
+ pinctrl_lcdif_ctrl_0: lcdifctrlgrp-0 {
+ fsl,pins = <
+ MX6SX_PAD_LCD1_CLK__LCDIF1_CLK 0x4001b0b0
+ MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0
+ MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x1b0b0
+ >;
+ };
+ };
+
+ mlb {
+ pinctrl_mlb_1: mlbgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD2_DATA3__MLB_DATA 0x31
+ MX6SX_PAD_SD2_CLK__MLB_SIG 0x31
+ MX6SX_PAD_SD2_CMD__MLB_CLK 0x31
+ >;
+ };
+
+ pinctrl_mlb_2: mlbgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_RX_CLK__MLB_DATA 0x31
+ MX6SX_PAD_ENET2_CRS__MLB_SIG 0x31
+ MX6SX_PAD_ENET2_TX_CLK__MLB_CLK 0x31
+ >;
+ };
+ };
+
+ mqs {
+ pinctrl_mqs_1: mqsgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CLK__MQS_RIGHT 0x80000000
+ MX6SX_PAD_SD2_CMD__MQS_LEFT 0x80000000
+ >;
+ };
+ };
+
+ pwm3 {
+ pinctrl_pwm3_0: pwm3grp-0 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO12__PWM3_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_pwm3_1: pwm3grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x110b0
+ >;
+ };
+ };
+
+ pwm4 {
+ pinctrl_pwm4_0: pwm4grp-0 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA1__PWM4_OUT 0x110b0
+ >;
+ };
+ };
+
+ qspi1 {
+ 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
+ >;
+ };
+ };
+
+ qspi2 {
+ pinctrl_qspi2_1: qspi2grp_1 {
+ fsl,pins = <
+ MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70a1
+ MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x70a1
+ MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x70a1
+ MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x70a1
+ MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x70a1
+ MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x70a1
+ MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x70a1
+ MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x70a1
+ MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x70a1
+ MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x70a1
+ MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x70a1
+ MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x70a1
+ >;
+ };
+ };
+
+ sai1 {
+ pinctrl_sai1_1: sai1grp_1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x1b030
+ MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x1b030
+ MX6SX_PAD_CSI_DATA02__SAI1_RX_BCLK 0x1b030
+ MX6SX_PAD_CSI_DATA03__SAI1_RX_SYNC 0x1b030
+ MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x1b030
+ MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x1b030
+ >;
+ };
+
+ pinctrl_sai1_2: sai1grp_2 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x130B0
+ MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x130B0
+ MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x120B0
+ MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x130B0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130B0
+ >;
+ };
+ };
+
+ sai2 {
+ pinctrl_sai2_1: sai2grp_1 {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL0__SAI2_TX_BCLK 0x1b030
+ MX6SX_PAD_KEY_COL1__SAI2_TX_SYNC 0x1b030
+ MX6SX_PAD_KEY_ROW0__SAI2_TX_DATA_0 0x1b030
+ MX6SX_PAD_KEY_ROW1__SAI2_RX_DATA_0 0x1b030
+ >;
+ };
+ };
+
+
+ spdif {
+ pinctrl_spdif_1: spdifgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_RX_CLK__SPDIF_OUT 0x1b0b0
+ MX6SX_PAD_ENET2_COL__SPDIF_IN 0x1b0b0
+ >;
+ };
+
+ pinctrl_spdif_2: spdifgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x1b0b0
+ >;
+ };
+
+ pinctrl_spdif_3: spdifgrp-3 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__SPDIF_IN 0x1b0b0
+ >;
+ };
+ };
+
+ uart1 {
+ pinctrl_uart1_1: uart1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart1_2: uart1grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__UART1_RX 0x1b0b1
+ MX6SX_PAD_ENET2_CRS__UART1_TX 0x1b0b1
+ >;
+ };
+ };
+
+ uart2 {
+ pinctrl_uart2_1: uart2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO07__UART2_RX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO06__UART2_TX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2_2: uart2grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA0__UART2_RX 0x1b0b1
+ MX6SX_PAD_SD1_DATA1__UART2_TX 0x1b0b1
+ >;
+ };
+ };
+
+ uart5 {
+ pinctrl_uart5_1: uart5grp-1 {
+ 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_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
+ >;
+ };
+ };
+
+ usbh {
+ pinctrl_usbh_1: usbhgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_USB_H_STROBE__USB_H_STROBE 0x40013030
+ MX6SX_PAD_USB_H_DATA__USB_H_DATA 0x40013030
+ >;
+ };
+
+ pinctrl_usbh_2: usbhgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_USB_H_STROBE__USB_H_STROBE 0x40017030
+ >;
+ };
+ };
+
+ usbotg1 {
+ pinctrl_usbotg1_1: usbotg1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg1_2: usbotg1grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg1_3: usbotg1grp-3 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA1__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+ };
+
+ usbotg2 {
+ pinctrl_usbotg2_1: usbotg2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO13__ANATOP_OTG2_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg2_2: usbotg2grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_CRS__ANATOP_OTG2_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg2_3: usbotg2grp-3 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_SCLK__ANATOP_OTG2_ID 0x17059
+ >;
+ };
+ };
+
+ usdhc1 {
+ pinctrl_usdhc1_1: usdhc1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6SX_PAD_SD1_CLK__USDHC1_CLK 0x10059
+ MX6SX_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
+ MX6SX_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
+ MX6SX_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
+ MX6SX_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
+ >;
+ };
+ };
+
+ usdhc2 {
+ pinctrl_usdhc2_1: usdhc2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
+ MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17059
+ MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17059
+ MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17059
+ >;
+ };
+ };
+
+ usdhc3 {
+ pinctrl_usdhc3_1: usdhc3grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
+ >;
+ };
+
+ };
+
+ usdhc4 {
+ 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_usdhc4_2: usdhc4grp-2 {
+ 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
+ >;
+ };
+
+ pinctrl_usdhc4_3: usdhc4grp-3 {
+ fsl,pins = <
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17071
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10071
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17071
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17071
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17071
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17071
+ MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x17071
+ MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x17071
+ MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x17071
+ MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x17071
+ >;
+ };
+
+ };
+
+ wdog {
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x10b0
+ >;
+ };
+ };
+
+ weim {
+ pinctrl_weim_cs0_1: weim_cs0grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_NAND_ALE__WEIM_CS0_B 0xb0b1
+ >;
+ };
+
+ pinctrl_weim_nor_1: weim_norgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_NAND_CE1_B__WEIM_OE 0xb0b1
+ MX6SX_PAD_NAND_RE_B__WEIM_RW 0xb0b1
+ MX6SX_PAD_NAND_WE_B__WEIM_WAIT 0xb060
+ /* data */
+ MX6SX_PAD_QSPI1A_SCLK__WEIM_DATA_0 0x1b0b0
+ MX6SX_PAD_QSPI1A_SS0_B__WEIM_DATA_1 0x1b0b0
+ MX6SX_PAD_QSPI1A_SS1_B__WEIM_DATA_2 0x1b0b0
+ MX6SX_PAD_QSPI1A_DATA3__WEIM_DATA_3 0x1b0b0
+ MX6SX_PAD_QSPI1A_DATA2__WEIM_DATA_4 0x1b0b0
+ MX6SX_PAD_QSPI1A_DATA1__WEIM_DATA_5 0x1b0b0
+ MX6SX_PAD_QSPI1A_DATA0__WEIM_DATA_6 0x1b0b0
+ MX6SX_PAD_QSPI1A_DQS__WEIM_DATA_7 0x1b0b0
+ MX6SX_PAD_QSPI1B_SCLK__WEIM_DATA_8 0x1b0b0
+ MX6SX_PAD_QSPI1B_SS0_B__WEIM_DATA_9 0x1b0b0
+ MX6SX_PAD_QSPI1B_SS1_B__WEIM_DATA_10 0x1b0b0
+ MX6SX_PAD_QSPI1B_DATA3__WEIM_DATA_11 0x1b0b0
+ MX6SX_PAD_QSPI1B_DATA2__WEIM_DATA_12 0x1b0b0
+ MX6SX_PAD_QSPI1B_DATA1__WEIM_DATA_13 0x1b0b0
+ MX6SX_PAD_QSPI1B_DATA0__WEIM_DATA_14 0x1b0b0
+ MX6SX_PAD_QSPI1B_DQS__WEIM_DATA_15 0x1b0b0
+ /* address */
+ MX6SX_PAD_NAND_DATA00__WEIM_AD_0 0xb0b1
+ MX6SX_PAD_NAND_DATA01__WEIM_AD_1 0xb0b1
+ MX6SX_PAD_NAND_DATA02__WEIM_AD_2 0xb0b1
+ MX6SX_PAD_NAND_DATA03__WEIM_AD_3 0xb0b1
+ MX6SX_PAD_NAND_DATA04__WEIM_AD_4 0xb0b1
+ MX6SX_PAD_NAND_DATA05__WEIM_AD_5 0xb0b1
+ MX6SX_PAD_NAND_DATA06__WEIM_AD_6 0xb0b1
+ MX6SX_PAD_NAND_DATA07__WEIM_AD_7 0xb0b1
+ MX6SX_PAD_LCD1_DATA08__WEIM_AD_8 0xb0b1
+ MX6SX_PAD_LCD1_DATA09__WEIM_AD_9 0xb0b1
+ MX6SX_PAD_LCD1_DATA10__WEIM_AD_10 0xb0b1
+ MX6SX_PAD_LCD1_DATA11__WEIM_AD_11 0xb0b1
+ MX6SX_PAD_LCD1_DATA12__WEIM_AD_12 0xb0b1
+ MX6SX_PAD_LCD1_DATA13__WEIM_AD_13 0xb0b1
+ MX6SX_PAD_LCD1_DATA14__WEIM_AD_14 0xb0b1
+ MX6SX_PAD_LCD1_DATA15__WEIM_AD_15 0xb0b1
+ MX6SX_PAD_LCD1_DATA16__WEIM_ADDR_16 0xb0b1
+ MX6SX_PAD_LCD1_DATA17__WEIM_ADDR_17 0xb0b1
+ MX6SX_PAD_LCD1_DATA18__WEIM_ADDR_18 0xb0b1
+ MX6SX_PAD_LCD1_DATA19__WEIM_ADDR_19 0xb0b1
+ MX6SX_PAD_LCD1_DATA20__WEIM_ADDR_20 0xb0b1
+ MX6SX_PAD_LCD1_DATA21__WEIM_ADDR_21 0xb0b1
+ MX6SX_PAD_LCD1_DATA22__WEIM_ADDR_22 0xb0b1
+ MX6SX_PAD_LCD1_DATA03__WEIM_ADDR_24 0xb0b1
+ MX6SX_PAD_LCD1_DATA04__WEIM_ADDR_25 0xb0b1
+ MX6SX_PAD_LCD1_DATA05__WEIM_ADDR_26 0xb0b1
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6sx-19x19-arm2-csi.dts b/arch/arm/boot/dts/imx6sx-19x19-arm2-csi.dts
new file mode 100644
index 000000000000..411939594217
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-19x19-arm2-csi.dts
@@ -0,0 +1,25 @@
+/*
+ * 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 "imx6sx-19x19-arm2.dts"
+
+&esai {
+ /* pin conflict with sai */
+ status = "disabled";
+};
+
+&sai1 {
+ status = "disabled";
+};
+
+&i2c2 {
+ ov5640: ov5640@3c {
+ status = "okay";
+ };
+};
+
diff --git a/arch/arm/boot/dts/imx6sx-19x19-arm2-gpmi-weim.dts b/arch/arm/boot/dts/imx6sx-19x19-arm2-gpmi-weim.dts
new file mode 100644
index 000000000000..a50f335adb80
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-19x19-arm2-gpmi-weim.dts
@@ -0,0 +1,20 @@
+/*
+ * 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 "imx6sx-19x19-arm2.dts"
+
+&qspi2 {
+ status = "disabled";
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "okay"; /* pin conflict with qspi*/
+ nand-on-flash-bbt;
+};
diff --git a/arch/arm/boot/dts/imx6sx-19x19-arm2-ldo.dts b/arch/arm/boot/dts/imx6sx-19x19-arm2-ldo.dts
new file mode 100644
index 000000000000..b7aeaca70e4a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-19x19-arm2-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-19x19-arm2.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-19x19-arm2.dts b/arch/arm/boot/dts/imx6sx-19x19-arm2.dts
new file mode 100644
index 000000000000..44607424d5b8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-19x19-arm2.dts
@@ -0,0 +1,1259 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "imx6sx.dtsi"
+
+/ {
+ model = "Freescale i.MX6 SoloX 19x19 ARM2 Board";
+ compatible = "fsl,imx6sx-19x19-arm2", "fsl,imx6sx";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm3 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ };
+
+ hannstar_cabc {
+ compatible = "hannstar,cabc";
+
+ lvds0 {
+ gpios = <&gpio2 16 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ clocks {
+ codec_osc: codec_osc {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <12000000>;
+ };
+ };
+
+ max7322_reset: max7322-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio6 18 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1>;
+ #reset-cells = <0>;
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_3p3v: 3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_usb_otg1_vbus: usb_otg1_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 9 0>;
+ enable-active-high;
+ };
+ };
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ sound-cs42888 {
+ compatible = "fsl,imx6-sabreauto-cs42888",
+ "fsl,imx-audio-cs42888";
+ model = "imx-cs42888";
+ esai-controller = <&esai>;
+ asrc-controller = <&asrc>;
+ audio-codec = <&cs42888>;
+ };
+};
+
+&esai {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_esai_1>;
+ status = "okay";
+};
+
+&csi1 {
+ status = "okay";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
+&csi2 {
+ status = "okay";
+ port {
+ csi2_ep: endpoint {
+ remote-endpoint = <&vadc_ep>;
+ };
+ };
+};
+
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 996000 1275000
+ 792000 1175000
+ 396000 1075000
+ 198000 975000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC uV */
+ 996000 1175000
+ 792000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+};
+
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1_1>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy1>;
+ pinctrl-assert-gpios = <&max7322_1 0 GPIO_ACTIVE_HIGH>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+ };
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2_1>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy0>;
+ pinctrl-assert-gpios = <&max7322_2 0 GPIO_ACTIVE_HIGH>;
+ fsl,magic-packet;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2_1>;
+ status = "okay";
+
+ max7322_1: gpio@68 {
+ compatible = "maxim,max7322";
+ reg = <0x68>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ resets = <&max7322_reset>;
+ };
+
+ max7322_2: gpio@69 {
+ compatible = "maxim,max7322";
+ reg = <0x69>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ resets = <&max7322_reset>;
+ };
+
+ ov5640: ov5640@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi_1>;
+ clocks = <&clks IMX6SX_CLK_CSI>;
+ clock-names = "csi_mclk";
+ AVDD-supply = <&vgen3_reg>; /* 2.8v */
+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/
+ pwn-gpios = <&gpio3 26 1>;
+ rst-gpios = <&gpio3 25 0>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ status = "disabled";
+ port {
+ ov5640_ep: endpoint {
+ remote-endpoint = <&csi1_ep>;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3_1>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4_2>;
+ status = "okay";
+
+ sgtl5000: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ clocks = <&codec_osc>;
+ VDDA-supply = <&vgen4_reg>;
+ VDDIO-supply = <&reg_3p3v>;
+ };
+
+ cs42888: cs42888@048 {
+ compatible = "cirrus,cs42888";
+ reg = <0x048>;
+ clocks = <&clks IMX6SX_CLK_ESAI_EXTAL>;
+ clock-names = "mclk";
+ VA-supply = <&reg_3p3v>;
+ VD-supply = <&reg_3p3v>;
+ VLS-supply = <&reg_3p3v>;
+ VLC-supply = <&reg_3p3v>;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+
+ hog {
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD4_DATA4__GPIO6_IO_18 0x1b0b0
+ MX6SX_PAD_KEY_ROW1__GPIO2_IO_16 0x1b0b0
+ >;
+ };
+ };
+};
+
+&lcdif1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat_0
+ &pinctrl_lcdif_ctrl_0>;
+ display = <&display0>;
+ status = "disabled";
+
+ display0: display {
+ 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 {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+ };
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3_0>;
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&sai1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1_1>;
+ status = "disabled";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_1>;
+ status = "okay";
+};
+
+&qspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi2_1>;
+ status = "okay";
+ ddrsmp=<2>;
+
+ flash0: n25q256a@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ reg = <0>;
+ };
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ reg = <1>;
+ };
+};
+
+&usbh {
+ pinctrl-names = "idle", "active";
+ pinctrl-0 = <&pinctrl_usbh_1>;
+ pinctrl-1 = <&pinctrl_usbh_2>;
+ osc-clkgate-delay = <0x3>;
+ pad-supply = <&vgen1_reg>;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1_1>;
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1_1>;
+ bus-width = <4>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ no-1-8-v;
+ status = "okay";
+};
+
+&weim {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_weim_nor_1 &pinctrl_weim_cs0_1>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0 0x50000000 0x08000000>;
+ status = "disabled"; /* pin conflict with qspi, nand and lcd1 */
+
+ nor@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x02000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ bank-width = <2>;
+ fsl,weim-cs-timing = <0x00610081 0x00000001 0x1c022000
+ 0x0000c000 0x1404a38e 0x00000000>;
+ };
+};
+
+&vadc {
+ vadc_in = <0>;
+ csi_id = <1>;
+ status = "okay";
+ port {
+ vadc_ep: endpoint {
+ remote-endpoint = <&csi2_ep>;
+ };
+ };
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
+
+&iomuxc {
+ audmux {
+ pinctrl_audmux_1: audmuxgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130B0
+ MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x130B0
+ MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x120B0
+ MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x130B0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130B0
+ >;
+ };
+
+ pinctrl_audmux_2: audmuxgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_COL__AUDMUX_AUD4_TXC 0x130b0
+ MX6SX_PAD_ENET1_CRS__AUDMUX_AUD4_TXD 0x130b0
+ MX6SX_PAD_ENET1_RX_CLK__AUDMUX_AUD4_TXFS 0x130b0
+ MX6SX_PAD_ENET1_TX_CLK__AUDMUX_AUD4_RXD 0x130b0
+ >;
+ };
+ };
+
+ ecspi4 {
+ pinctrl_ecspi4_cs_1: ecspi4_cs_grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_DATA2__GPIO7_IO_4 0x80000000
+ >;
+ };
+
+ pinctrl_ecspi4_1: ecspi4grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_DATA3__ECSPI4_MISO 0x100b1
+ MX6SX_PAD_SD3_CMD__ECSPI4_MOSI 0x100b1
+ MX6SX_PAD_SD3_CLK__ECSPI4_SCLK 0x100b1
+ >;
+ };
+ };
+
+ canfd1 {
+ pinctrl_canfd1_1: canfd1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DQS__CANFD_TX1 0x1b0b0
+ MX6SX_PAD_QSPI1A_SS1_B__CANFD_RX1 0x1b0b0
+ >;
+ };
+ };
+
+ canfd2 {
+ pinctrl_canfd2_1: canfd2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS1_B__CANFD_RX2 0x1b0b0
+ MX6SX_PAD_QSPI1A_DQS__CANFD_TX2 0x1b0b0
+ >;
+ };
+ };
+
+ csi {
+ 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_csi_1: csigrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_MCLK__CSI1_MCLK 0x110b0
+ MX6SX_PAD_CSI_PIXCLK__CSI1_PIXCLK 0x110b0
+ MX6SX_PAD_CSI_VSYNC__CSI1_VSYNC 0x110b0
+ MX6SX_PAD_CSI_HSYNC__CSI1_HSYNC 0x110b0
+ MX6SX_PAD_CSI_DATA00__CSI1_DATA_2 0x110b0
+ MX6SX_PAD_CSI_DATA01__CSI1_DATA_3 0x110b0
+ MX6SX_PAD_CSI_DATA02__CSI1_DATA_4 0x110b0
+ MX6SX_PAD_CSI_DATA03__CSI1_DATA_5 0x110b0
+ MX6SX_PAD_CSI_DATA04__CSI1_DATA_6 0x110b0
+ MX6SX_PAD_CSI_DATA05__CSI1_DATA_7 0x110b0
+ MX6SX_PAD_CSI_DATA06__CSI1_DATA_8 0x110b0
+ MX6SX_PAD_CSI_DATA07__CSI1_DATA_9 0x110b0
+
+ MX6SX_PAD_LCD1_ENABLE__GPIO3_IO_25 0x80000000
+ MX6SX_PAD_LCD1_HSYNC__GPIO3_IO_26 0x80000000
+ >;
+ };
+ };
+
+ enet1 {
+ pinctrl_enet1_1: enet1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
+ MX6SX_PAD_ENET1_MDC__ENET1_MDC 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
+ MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
+ MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ >;
+ };
+
+ pinctrl_enet1_clkout_1: enet1_clkoutgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x91
+ >;
+ };
+ };
+
+ enet2 {
+ pinctrl_enet2_1: enet2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
+ MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
+ >;
+ };
+ };
+
+ esai {
+ pinctrl_esai_1: esaigrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_MCLK__ESAI_TX_HF_CLK 0x1b030
+ 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
+ >;
+ };
+ };
+
+ flexcan1 {
+ pinctrl_flexcan1_1: flexcan1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b0b0
+ MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x1b0b0
+ >;
+ };
+ };
+
+ flexcan2 {
+ pinctrl_flexcan2_1: flexcan2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x1b0b0
+ MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x1b0b0
+ >;
+ };
+ };
+
+ gpmi-nand {
+ 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
+ >;
+ };
+ };
+
+ i2c1 {
+ pinctrl_i2c1_1: i2c1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c1_2: i2c1grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA01__I2C1_SDA 0x4001b8b1
+ MX6SX_PAD_CSI_DATA00__I2C1_SCL 0x4001b8b1
+ >;
+ };
+ };
+
+ i2c2 {
+ pinctrl_i2c2_1: i2c2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO03__I2C2_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO02__I2C2_SCL 0x4001b8b1
+ >;
+ };
+ };
+
+ i2c3 {
+ pinctrl_i2c3_1: i2c3grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_TX_CLK__I2C3_SDA 0x4001b8b1
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3_2: i2c3grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
+ };
+
+ i2c4 {
+ pinctrl_i2c4_1: i2c4grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x4001b8b1
+ MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x4001b8b1
+ >;
+ };
+ pinctrl_i2c4_2: i2c4grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_DATA1__I2C4_SDA 0x4001b8b1
+ MX6SX_PAD_SD3_DATA0__I2C4_SCL 0x4001b8b1
+ >;
+ };
+ };
+
+ lcdif1 {
+ pinctrl_lcdif_dat_0: lcdifdatgrp-0 {
+ fsl,pins = <
+ MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0
+ >;
+ };
+
+ pinctrl_lcdif_ctrl_0: lcdifctrlgrp-0 {
+ fsl,pins = <
+ MX6SX_PAD_LCD1_CLK__LCDIF1_CLK 0x4001b0b0
+ MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0
+ MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x4001b0b0
+ >;
+ };
+ };
+
+ mlb {
+ pinctrl_mlb_1: mlbgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD2_DATA3__MLB_DATA 0x31
+ MX6SX_PAD_SD2_CLK__MLB_SIG 0x31
+ MX6SX_PAD_SD2_CMD__MLB_CLK 0x31
+ >;
+ };
+ };
+
+ mqs {
+ pinctrl_mqs_1: mqsgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CLK__MQS_RIGHT 0x80000000
+ MX6SX_PAD_SD2_CMD__MQS_LEFT 0x80000000
+ >;
+ };
+ };
+
+ pwm3 {
+ pinctrl_pwm3_0: pwm3grp-0 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO12__PWM3_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_pwm3_1: pwm3grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x110b0
+ >;
+ };
+ };
+
+ pwm4 {
+ pinctrl_pwm4_0: pwm4grp-0 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA1__PWM4_OUT 0x110b0
+ >;
+ };
+ };
+
+ qspi2 {
+ pinctrl_qspi2_1: qspi2grp_1 {
+ fsl,pins = <
+ MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70a1
+ MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x70a1
+ MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x70a1
+ MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x70a1
+ MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x70a1
+ MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x70a1
+ MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x70a1
+ MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x70a1
+ MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x70a1
+ MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x70a1
+ MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x70a1
+ MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x70a1
+ >;
+ };
+ };
+
+ sai1 {
+ pinctrl_sai1_1: sai1grp_1 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x1b030
+ MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x1b030
+ MX6SX_PAD_CSI_DATA02__SAI1_RX_BCLK 0x1b030
+ MX6SX_PAD_CSI_DATA03__SAI1_RX_SYNC 0x1b030
+ MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x1b030
+ MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x1b030
+ >;
+ };
+
+ pinctrl_sai1_2: sai1grp_2 {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x130B0
+ MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x130B0
+ MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x120B0
+ MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x130B0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130B0
+ >;
+ };
+ };
+
+ sai2 {
+ pinctrl_sai2_1: sai2grp_1 {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL0__SAI2_TX_BCLK 0x1b030
+ MX6SX_PAD_KEY_COL1__SAI2_TX_SYNC 0x1b030
+ MX6SX_PAD_KEY_ROW0__SAI2_TX_DATA_0 0x1b030
+ MX6SX_PAD_KEY_ROW1__SAI2_RX_DATA_0 0x1b030
+ >;
+ };
+ };
+
+
+ spdif {
+ pinctrl_spdif_1: spdifgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_RX_CLK__SPDIF_OUT 0x1b0b0
+ MX6SX_PAD_ENET2_COL__SPDIF_IN 0x1b0b0
+ >;
+ };
+
+ pinctrl_spdif_2: spdifgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x1b0b0
+ >;
+ };
+ };
+
+ uart1 {
+ pinctrl_uart1_1: uart1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart1_2: uart1grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__UART1_RX 0x1b0b1
+ MX6SX_PAD_ENET2_CRS__UART1_TX 0x1b0b1
+ >;
+ };
+ };
+
+ uart2 {
+ pinctrl_uart2_1: uart2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO07__UART2_RX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO06__UART2_TX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2_2: uart2grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA0__UART2_RX 0x1b0b1
+ MX6SX_PAD_SD1_DATA1__UART2_TX 0x1b0b1
+ >;
+ };
+ };
+
+ uart5 {
+ pinctrl_uart5_1: uart5grp-1 {
+ 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_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
+ >;
+ };
+ };
+
+ usbh {
+ pinctrl_usbh_1: usbhgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_USB_H_STROBE__USB_H_STROBE 0x40013030
+ MX6SX_PAD_USB_H_DATA__USB_H_DATA 0x40013030
+ >;
+ };
+
+ pinctrl_usbh_2: usbhgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_USB_H_STROBE__USB_H_STROBE 0x40017030
+ >;
+ };
+ };
+
+ usbotg1 {
+ pinctrl_usbotg1_1: usbotg1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg1_2: usbotg1grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg1_3: usbotg1grp-3 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA1__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+ };
+
+ usbotg2 {
+ pinctrl_usbotg2_1: usbotg2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO13__ANATOP_OTG2_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg2_2: usbotg2grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_CRS__ANATOP_OTG2_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg2_3: usbotg2grp-3 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_SCLK__ANATOP_OTG2_ID 0x17059
+ >;
+ };
+ };
+
+ usdhc1 {
+ pinctrl_usdhc1_1: usdhc1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6SX_PAD_SD1_CLK__USDHC1_CLK 0x10059
+ MX6SX_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
+ MX6SX_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
+ MX6SX_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
+ MX6SX_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
+ >;
+ };
+ };
+
+ usdhc2 {
+ pinctrl_usdhc2_1: usdhc2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
+ MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17059
+ MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17059
+ MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17059
+ >;
+ };
+ };
+
+ usdhc3 {
+ pinctrl_usdhc3_1: usdhc3grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
+ >;
+ };
+
+ };
+
+ usdhc4 {
+ 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_usdhc4_2: usdhc4grp-2 {
+ 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
+ >;
+ };
+
+ };
+
+ wdog {
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x10b0
+ >;
+ };
+ };
+
+ weim {
+ pinctrl_weim_cs0_1: weim_cs0grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_NAND_ALE__WEIM_CS0_B 0xb0b1
+ >;
+ };
+
+ pinctrl_weim_nor_1: weim_norgrp-1 {
+ fsl,pins = <
+ MX6SX_PAD_NAND_CE1_B__WEIM_OE 0xb0b1
+ MX6SX_PAD_NAND_RE_B__WEIM_RW 0xb0b1
+ MX6SX_PAD_NAND_WE_B__WEIM_WAIT 0xb060
+ /* data */
+ MX6SX_PAD_QSPI1A_SCLK__WEIM_DATA_0 0x1b0b0
+ MX6SX_PAD_QSPI1A_SS0_B__WEIM_DATA_1 0x1b0b0
+ MX6SX_PAD_QSPI1A_SS1_B__WEIM_DATA_2 0x1b0b0
+ MX6SX_PAD_QSPI1A_DATA3__WEIM_DATA_3 0x1b0b0
+ MX6SX_PAD_QSPI1A_DATA2__WEIM_DATA_4 0x1b0b0
+ MX6SX_PAD_QSPI1A_DATA1__WEIM_DATA_5 0x1b0b0
+ MX6SX_PAD_QSPI1A_DATA0__WEIM_DATA_6 0x1b0b0
+ MX6SX_PAD_QSPI1A_DQS__WEIM_DATA_7 0x1b0b0
+ MX6SX_PAD_QSPI1B_SCLK__WEIM_DATA_8 0x1b0b0
+ MX6SX_PAD_QSPI1B_SS0_B__WEIM_DATA_9 0x1b0b0
+ MX6SX_PAD_QSPI1B_SS1_B__WEIM_DATA_10 0x1b0b0
+ MX6SX_PAD_QSPI1B_DATA3__WEIM_DATA_11 0x1b0b0
+ MX6SX_PAD_QSPI1B_DATA2__WEIM_DATA_12 0x1b0b0
+ MX6SX_PAD_QSPI1B_DATA1__WEIM_DATA_13 0x1b0b0
+ MX6SX_PAD_QSPI1B_DATA0__WEIM_DATA_14 0x1b0b0
+ MX6SX_PAD_QSPI1B_DQS__WEIM_DATA_15 0x1b0b0
+ /* address */
+ MX6SX_PAD_NAND_DATA00__WEIM_AD_0 0xb0b1
+ MX6SX_PAD_NAND_DATA01__WEIM_AD_1 0xb0b1
+ MX6SX_PAD_NAND_DATA02__WEIM_AD_2 0xb0b1
+ MX6SX_PAD_NAND_DATA03__WEIM_AD_3 0xb0b1
+ MX6SX_PAD_NAND_DATA04__WEIM_AD_4 0xb0b1
+ MX6SX_PAD_NAND_DATA05__WEIM_AD_5 0xb0b1
+ MX6SX_PAD_NAND_DATA06__WEIM_AD_6 0xb0b1
+ MX6SX_PAD_NAND_DATA07__WEIM_AD_7 0xb0b1
+ MX6SX_PAD_LCD1_DATA08__WEIM_AD_8 0xb0b1
+ MX6SX_PAD_LCD1_DATA09__WEIM_AD_9 0xb0b1
+ MX6SX_PAD_LCD1_DATA10__WEIM_AD_10 0xb0b1
+ MX6SX_PAD_LCD1_DATA11__WEIM_AD_11 0xb0b1
+ MX6SX_PAD_LCD1_DATA12__WEIM_AD_12 0xb0b1
+ MX6SX_PAD_LCD1_DATA13__WEIM_AD_13 0xb0b1
+ MX6SX_PAD_LCD1_DATA14__WEIM_AD_14 0xb0b1
+ MX6SX_PAD_LCD1_DATA15__WEIM_AD_15 0xb0b1
+ MX6SX_PAD_LCD1_DATA16__WEIM_ADDR_16 0xb0b1
+ MX6SX_PAD_LCD1_DATA17__WEIM_ADDR_17 0xb0b1
+ MX6SX_PAD_LCD1_DATA18__WEIM_ADDR_18 0xb0b1
+ MX6SX_PAD_LCD1_DATA19__WEIM_ADDR_19 0xb0b1
+ MX6SX_PAD_LCD1_DATA20__WEIM_ADDR_20 0xb0b1
+ MX6SX_PAD_LCD1_DATA21__WEIM_ADDR_21 0xb0b1
+ MX6SX_PAD_LCD1_DATA22__WEIM_ADDR_22 0xb0b1
+ MX6SX_PAD_LCD1_DATA03__WEIM_ADDR_24 0xb0b1
+ MX6SX_PAD_LCD1_DATA04__WEIM_ADDR_25 0xb0b1
+ MX6SX_PAD_LCD1_DATA05__WEIM_ADDR_26 0xb0b1
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6sx-pinfunc.h b/arch/arm/boot/dts/imx6sx-pinfunc.h
index 42c4c800feea..5a989206f333 100644
--- a/arch/arm/boot/dts/imx6sx-pinfunc.h
+++ b/arch/arm/boot/dts/imx6sx-pinfunc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * 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
@@ -70,6 +70,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
@@ -79,6 +80,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
@@ -88,6 +90,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
@@ -97,6 +100,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
@@ -204,6 +208,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
@@ -214,6 +219,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
@@ -223,6 +229,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
@@ -255,6 +262,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
@@ -357,6 +365,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
@@ -367,6 +376,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
@@ -376,6 +386,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
@@ -394,6 +405,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
@@ -419,6 +431,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
@@ -438,6 +451,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
@@ -820,6 +834,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
@@ -830,6 +845,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
@@ -972,6 +988,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
@@ -980,6 +997,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
@@ -1251,6 +1269,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
@@ -1260,6 +1279,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
@@ -1330,6 +1350,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
@@ -1369,6 +1390,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
@@ -1414,6 +1436,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
@@ -1424,6 +1447,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
@@ -1515,6 +1539,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
@@ -1525,6 +1550,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-m4.dts b/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts
new file mode 100644
index 000000000000..a168992ffdd5
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts
@@ -0,0 +1,93 @@
+/*
+ * 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 "imx6sx-sabreauto.dts"
+
+/{
+ memory {
+ linux,usable-memory = <0x80000000 0x1ff00000>,
+ <0xa0000000 0x1ff00000>,
+ <0xc0000000 0x40000000>;
+ };
+};
+
+/*
+ * 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 0x1E000>;
+};
+
+&ocram {
+ reg = <0x00901000 0xf000>;
+};
+
+&qspi1 {
+ status = "disabled";
+};
+
+&qspi_m4 {
+ reg = <0x021e0000 0x4000>;
+ 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-sabreauto.dts b/arch/arm/boot/dts/imx6sx-sabreauto.dts
index 240a2864d044..9b01adf3c687 100644
--- a/arch/arm/boot/dts/imx6sx-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6sx-sabreauto.dts
@@ -14,15 +14,83 @@
model = "Freescale i.MX6 SoloX Sabre Auto Board";
compatible = "fsl,imx6sx-sabreauto", "fsl,imx6sx";
+ 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";
+ };
+
+ clocks {
+ codec_osc: anaclk2 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24576000>;
+ };
+ };
+
+ max7310_reset: max7310-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1>;
+ #reset-cells = <0>;
+ };
+
memory {
reg = <0x80000000 0x80000000>;
};
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
regulators {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
+ 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;
+ };
+
vcc_sd3: regulator@0 {
compatible = "regulator-fixed";
reg = <0>;
@@ -34,15 +102,507 @@
gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
+
+ reg_usb_otg1_vbus: usb_otg1_vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_vbus>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 9 0>;
+ enable-active-high;
+ };
+
+ reg_usb_otg2_vbus: usb_otg2_vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg2_vbus>;
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 12 0>;
+ enable-active-high;
+ };
+
+ reg_can_wake: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "can-wake";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&max7310_b 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can_en: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "can-en";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&max7310_b 5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&reg_can_wake>;
+ };
+
+ reg_can_stby: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "can-stby";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&max7310_b 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&reg_can_en>;
+ };
+
+ reg_vref_3v3: regulator@4 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ };
+
+ 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";
+};
+
+&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";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1_1>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy1>;
+ pinctrl-assert-gpios = <&max7322 0 GPIO_ACTIVE_HIGH>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+ };
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2_1>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ nand-on-flash-bbt;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2_1>;
+ status = "okay";
+
+ codec: cs42888@048 {
+ compatible = "cirrus,cs42888";
+ reg = <0x048>;
+ clocks = <&codec_osc 0>;
+ clock-names = "mclk";
+ VA-supply = <&reg_audio>;
+ VD-supply = <&reg_audio>;
+ VLS-supply = <&reg_audio>;
+ VLC-supply = <&reg_audio>;
+ };
+
+ egalax_ts@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_egalax_int>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <22 2>;
+ wakeup-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>;
+ };
+
+ 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";
+ };
+ };
+
+ max7322: gpio@68 {
+ compatible = "maxim,max7322";
+ reg = <0x68>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3_2>;
+ status = "okay";
+
+ max7310_a: gpio@30 {
+ compatible = "maxim,max7310";
+ reg = <0x30>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ resets = <&max7310_reset>;
+ };
+
+ max7310_b: gpio@32 {
+ compatible = "maxim,max7310";
+ reg = <0x32>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ resets = <&max7310_reset>;
+ };
+
+ mma8451@1c {
+ compatible = "fsl,mma8451";
+ reg = <0x1c>;
+ position = <7>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <24 8>;
+ interrupt-route = <1>;
+ };
+
+ mag3110@0e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ position = <2>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <6 1>;
+ };
+
+ isl29023@44 {
+ compatible = "fsl,isl29023";
+ reg = <0x44>;
+ rext = <499>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <23 2>;
+ };
+
+};
+
+&lcdif2 {
+ display = <&display1>;
+ disp-dev = "ldb";
+ status = "okay";
+
+ display1: display@1 {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+ };
+};
+
+&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>;
+ };
+ };
+ };
+};
+
+&mlb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mlb_2>;
+ status = "okay";
+};
+
+&pcie {
+ reset-gpio = <&max7310_b 3 0>;
+ 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 = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ reg = <0>;
+ };
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ reg = <1>;
+ };
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif_3>;
+ status = "okay";
+};
+
+&ssi2 {
+ fsl,mode = "i2s-master";
+ status = "okay";
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
status = "okay";
};
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_1>;
+ status = "okay";
+};
+
+&uart5 { /* for bluetooth */
+ 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>; */
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ dr_mode = "host";
+ status = "okay";
+};
+
&usdhc3 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc3>;
@@ -68,8 +628,169 @@
status = "okay";
};
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm4_0>;
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
&iomuxc {
imx6x-sabreauto {
+ 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 0x80000000
+ >;
+ };
+
+ pinctrl_enet1_1: enet1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
+ MX6SX_PAD_ENET1_MDC__ENET1_MDC 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
+ MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
+ MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ >;
+ };
+
+ pinctrl_enet2_1: enet2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
+ MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
+ >;
+ };
+
+ 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_flexcan1: flexcan1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b020
+ MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x1b020
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x1b020
+ MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x1b020
+ >;
+ };
+
+ 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_1: i2c2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO03__I2C2_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO02__I2C2_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3_2: i2c3grp-2 {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_mlb_2: mlbgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_RX_CLK__MLB_DATA 0x31
+ MX6SX_PAD_ENET2_CRS__MLB_SIG 0x31
+ MX6SX_PAD_ENET2_TX_CLK__MLB_CLK 0x31
+ >;
+ };
+
+ pinctrl_pwm4_0: pwm4grp-0 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA1__PWM4_OUT 0x110b0
+ >;
+ };
+
+ 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_spdif_3: spdifgrp-3 {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__SPDIF_IN 0x1b0b0
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
@@ -77,6 +798,49 @@
>;
};
+ pinctrl_uart2_1: uart2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO07__UART2_RX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO06__UART2_TX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5_1: uart5grp-1 {
+ 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_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_vbus: usbotg1vbusgrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x10b0
+ >;
+ };
+
+ pinctrl_usb_otg1_id: usbotg1idgrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usb_otg2_vbus: usbotg2vbusgrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12 0x10b0
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
@@ -89,8 +853,8 @@
MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
- MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
- MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
+ MX6SX_PAD_USB_H_DATA__GPIO7_IO_10 0x17059 /* CD */
+ MX6SX_PAD_LCD1_DATA18__GPIO3_IO_19 0x17059 /* WP */
>;
};
@@ -126,14 +890,13 @@
pinctrl_usdhc4: usdhc4grp {
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_DATA7__GPIO6_IO_21 0x17059 /* CD */
- MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17071
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10071
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17071
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17071
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17071
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17071
+ MX6SX_PAD_USB_H_STROBE__GPIO7_IO_11 0x17071 /* CD */
>;
};
@@ -142,5 +905,48 @@
MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
>;
};
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+ };
+};
+&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";
+};
+
+&vadc {
+ vadc_in = <0>;
+ csi_id = <1>;
+ status = "okay";
+ port {
+ vadc_ep: endpoint {
+ remote-endpoint = <&csi2_ep>;
+ };
+ };
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
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..698e49ef7734
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/*
+ * NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into SD3
+ * slot using Murata i.MX InterConnect Ver 1.0 Adapter AND SD Card Extender on
+ * SD2 slot. Bluetooth UART connects via SD3 EMMC/MMC Plus pinout.
+ * WL_REG_ON/BT_REG_ON/WL_HOST_WAKE connect via SD Card Extender.
+ */
+
+#include "imx6sx-sdb.dts"
+
+/ {
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio6 10 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ /* WL_HOST_WAKE: SD2_DAT1 (gpio6 9) */
+ gpios = <&gpio6 9 0>;
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&iomuxc {
+ imx6sx-sdb-murata-v1_sdext {
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_DATA3__GPIO6_IO_11 0x13069 /* BT_REG_ON */
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_DATA4__UART3_RX 0x1b0b1
+ MX6SX_PAD_SD3_DATA5__UART3_TX 0x1b0b1
+ MX6SX_PAD_SD3_DATA7__UART3_CTS_B 0x1b0b1
+ MX6SX_PAD_SD3_DATA6__UART3_RTS_B 0x1b0b1
+ >;
+ };
+
+ /* change MUXing on SD2 slot for control signals. */
+ pinctrl_usdhc2_1: usdhc2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
+ >;
+ };
+
+ /* Murata change SD3 to 4-bit SDIO only; use upper 4-bits for UART. */
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17069
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10071
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17069
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17069
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17069
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17069
+ MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
+ MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
+ /* Murata Module control signals */
+ MX6SX_PAD_SD2_DATA1__GPIO6_IO_9 0x13069 /* WL_HOST_WAKE */
+ MX6SX_PAD_SD2_DATA2__GPIO6_IO_10 0x13069 /* WL_REG_ON */
+ >;
+ };
+ };
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3
+ &pinctrl_bt>;
+ fsl,uart-has-rtscts;
+ resets = <&modem_reset>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2_1>;
+ bus-width = <1>;
+};
+
+&vcc_sd3 {
+ regulator-always-on;
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v; /* force 3.3V VIO */
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host; /* pull in card detect mechanism for BCMDHD driver */
+ status = "okay";
+};
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..6a2a07b0e2ba
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-emmc.dts
@@ -0,0 +1,30 @@
+/*
+ * 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"
+
+/*
+ * 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>;
+ /*
+ * 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..280540453aeb
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-lcdif1.dts
@@ -0,0 +1,37 @@
+/*
+ * 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"
+
+/ {
+ sii902x_reset: sii902x-reset {
+ status = "okay";
+ };
+};
+
+&csi1 {
+ status = "disabled";
+};
+
+&lcdif1 {
+ status = "okay";
+};
+
+&i2c1 {
+ sii902x@39 {
+ status = "okay";
+ };
+};
+
+&ov5640 {
+ status = "disabled";
+};
+
+&crypto {
+ 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..61a1db351dd6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-m4.dts
@@ -0,0 +1,91 @@
+/*
+ * 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"
+
+/{
+ memory {
+ linux,usable-memory = <0x80000000 0x1ff00000>,
+ <0xa0000000 0x1ff00000>;
+ };
+};
+
+&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..e5ff9fb99013
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-mqs.dts
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * This feature is supported by the MX6SX-SD-EXP1 board
+ *
+ */
+
+#include "imx6sx-sdb.dts"
+/ {
+ 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";
+};
+
+&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-reva.dts b/arch/arm/boot/dts/imx6sx-sdb-reva.dts
index 71005478cdf0..b5cabf97fcaf 100644
--- a/arch/arm/boot/dts/imx6sx-sdb-reva.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb-reva.dts
@@ -10,6 +10,48 @@
/ {
model = "Freescale i.MX6 SoloX SDB RevA Board";
+
+ regulators {
+ /* Transceiver EN/STBY is active high on RevA board */
+ reg_can_en: regulator@9 {
+ gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can_stby: regulator@10 {
+ gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&reg_can_en>;
+ };
+ };
+};
+
+&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>;
+};
+
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
};
&i2c1 {
@@ -124,13 +166,14 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_qspi2>;
status = "okay";
+ ddrsmp=<0>;
flash0: s25fl128s@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
compatible = "spansion,s25fl128s", "jedec,spi-nor";
- spi-max-frequency = <66000000>;
+ spi-max-frequency = <29000000>;
};
flash1: s25fl128s@1 {
@@ -138,6 +181,6 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "spansion,s25fl128s", "jedec,spi-nor";
- spi-max-frequency = <66000000>;
+ spi-max-frequency = <29000000>;
};
};
diff --git a/arch/arm/boot/dts/imx6sx-sdb-sai.dts b/arch/arm/boot/dts/imx6sx-sdb-sai.dts
index 0155450d680e..f4f699fbdfe1 100644
--- a/arch/arm/boot/dts/imx6sx-sdb-sai.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb-sai.dts
@@ -43,7 +43,7 @@
/ {
sound {
- audio-cpu = <&sai1>;
+ cpu-dai = <&sai1>;
};
};
@@ -53,6 +53,8 @@
};
&sai1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index d71da30c9cff..7797130c98b5 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -10,101 +10,41 @@
/ {
model = "Freescale i.MX6 SoloX SDB RevB Board";
-};
-
-&i2c1 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c1>;
- status = "okay";
-
- pmic: pfuze100@08 {
- compatible = "fsl,pfuze200";
- reg = <0x08>;
-
- regulators {
- sw1a_reg: sw1ab {
- regulator-min-microvolt = <300000>;
- regulator-max-microvolt = <1875000>;
- regulator-boot-on;
- regulator-always-on;
- regulator-ramp-delay = <6250>;
- };
-
- sw2_reg: sw2 {
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- sw3a_reg: sw3a {
- regulator-min-microvolt = <400000>;
- regulator-max-microvolt = <1975000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- sw3b_reg: sw3b {
- regulator-min-microvolt = <400000>;
- regulator-max-microvolt = <1975000>;
- 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: vgen1 {
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <1550000>;
- regulator-always-on;
- };
- vgen2_reg: vgen2 {
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <1550000>;
- };
-
- vgen3_reg: vgen3 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
+ regulators {
+ /* Transceiver EN/STBY is active low on RevB board */
+ reg_can_stby: regulator@10 {
+ gpio = <&gpio4 27 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
- vgen4_reg: vgen4 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 996000 1250000
+ 792000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC uV */
+ 996000 1250000
+ 792000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,arm-soc-shared = <1>;
+};
- vgen5_reg: vgen5 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
- vgen6_reg: vgen6 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
- };
- };
+&reg_soc {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
};
&qspi2 {
@@ -112,6 +52,9 @@
pinctrl-0 = <&pinctrl_qspi2>;
status = "okay";
+#ifndef SPANSIONFLASH
+ ddrsmp=<0>;
+
flash0: n25q256a@0 {
#address-cells = <1>;
#size-cells = <1>;
@@ -127,4 +70,13 @@
spi-max-frequency = <29000000>;
reg = <1>;
};
+#endif
+};
+
+&usbphy1 {
+ tx-d-cal = <0x5>;
+};
+
+&usbphy2 {
+ tx-d-cal = <0x5>;
};
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/imx6sx-sdb.dtsi
index 9d70cfd40aff..eaea8ff94cb6 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dtsi
+++ b/arch/arm/boot/dts/imx6sx-sdb.dtsi
@@ -24,11 +24,19 @@
reg = <0x80000000 0x40000000>;
};
- backlight {
+ backlight1 {
compatible = "pwm-backlight";
pwms = <&pwm3 0 5000000>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
+ fb-names = "mxs-lcdif0";
+ };
+ 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 {
@@ -49,6 +57,18 @@
};
};
+ hannstar_cabc {
+ compatible = "hannstar,cabc";
+ lvds0 {
+ gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
regulators {
compatible = "simple-bus";
#address-cells = <1>;
@@ -63,6 +83,7 @@
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
enable-active-high;
};
@@ -104,6 +125,7 @@
regulator-name = "lcd-3v3";
gpio = <&gpio3 27 0>;
enable-active-high;
+ status = "disabled";
};
reg_peri_3v3: regulator@5 {
@@ -129,12 +151,49 @@
regulator-max-microvolt = <3300000>;
gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
};
+
+ reg_vref_3v3: regulator@7 {
+ compatible = "regulator-fixed";
+ reg = <7>;
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_pcie: regulator@8 {
+ compatible = "regulator-fixed";
+ reg = <8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie_reg>;
+ regulator-name = "MPCIE_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 1 0>;
+ regulator-always-on;
+ enable-active-high;
+ };
+
+ reg_can_en: regulator@9 {
+ compatible = "regulator-fixed";
+ reg = <9>;
+ regulator-name = "can-en";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_can_stby: regulator@10 {
+ compatible = "regulator-fixed";
+ reg = <10>;
+ regulator-name = "can-stby";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
};
sound {
compatible = "fsl,imx6sx-sdb-wm8962", "fsl,imx-audio-wm8962";
model = "wm8962-audio";
- ssi-controller = <&ssi2>;
+ cpu-dai = <&ssi2>;
audio-codec = <&codec>;
audio-routing =
"Headphone Jack", "HPOUTL",
@@ -145,15 +204,48 @@
"IN3R", "AMIC";
mux-int-port = <2>;
mux-ext-port = <6>;
+ codec-master;
+ hp-det-gpios = <&gpio1 17 1>;
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif",
+ "fsl,imx6sx-sdb-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-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";
};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
@@ -176,6 +268,37 @@
};
};
+&csi1 {
+ status = "okay";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
+&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";
+};
+
&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
@@ -184,11 +307,196 @@
status = "okay";
};
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze200";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ 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: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ 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@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ 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@0e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ 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 {
@@ -209,6 +517,7 @@
PLLVDD-supply = <&vgen4_reg>;
SPKVDD1-supply = <&reg_psu_5v>;
SPKVDD2-supply = <&reg_psu_5v>;
+ amic-mono;
};
};
@@ -217,9 +526,9 @@
pinctrl-0 = <&pinctrl_lcd>;
lcd-supply = <&reg_lcd_3v3>;
display = <&display0>;
- status = "okay";
+ status = "disabled";
- display0: display0 {
+ display0: display@0 {
bits-per-pixel = <16>;
bus-width = <24>;
@@ -244,12 +553,62 @@
};
};
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio2 0 0>;
+ status = "okay";
+};
+
+&lcdif2 {
+ display = <&display1>;
+ disp-dev = "ldb";
+ status = "okay";
+ display1: display@1 {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+ };
+};
+&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>;
+ };
+ };
+ };
+};
+
&pwm3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm3>;
status = "okay";
};
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm4>;
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
&snvs_poweroff {
status = "okay";
};
@@ -260,6 +619,12 @@
status = "disabled";
};
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif>;
+ status = "okay";
+};
+
&ssi2 {
status = "okay";
};
@@ -275,12 +640,18 @@
pinctrl-0 = <&pinctrl_uart5>;
uart-has-rtscts;
status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode;*/
+ /* pinctrl-0 = <&pinctrl_uart5dte_1>; */
};
&usbotg1 {
vbus-supply = <&reg_usb_otg1_vbus>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
status = "okay";
};
@@ -329,7 +700,25 @@
};
&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog &pinctrl_can_gpios>;
+
imx6x-sdb {
+ 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
@@ -340,11 +729,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
@@ -383,6 +799,20 @@
>;
};
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b020
+ MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x1b020
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x1b020
+ MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x1b020
+ >;
+ };
+
pinctrl_gpio_keys: gpio_keysgrp {
fsl,pins = <
MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
@@ -397,6 +827,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
@@ -445,6 +882,25 @@
>;
};
+ pinctrl_mqs: mqsgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CLK__MQS_RIGHT 0x120b0
+ MX6SX_PAD_SD2_CMD__MQS_LEFT 0x120b0
+ >;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x10b0
+ >;
+ };
+
+ pinctrl_pcie_reg: pciereggrp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 0x10b0
+ >;
+ };
+
pinctrl_peri_3v3: peri3v3grp {
fsl,pins = <
MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x80000000
@@ -457,6 +913,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
@@ -474,6 +936,12 @@
>;
};
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x1b0b0
+ >;
+ };
+
pinctrl_vcc_sd3: vccsd3grp {
fsl,pins = <
MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
@@ -506,6 +974,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
@@ -537,16 +1014,16 @@
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
- MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
- MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
- MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
- MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
- MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
- MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
- MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
- MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
- MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
- MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17069
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10071
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17069
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17069
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17069
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17069
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17069
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17069
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17069
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17069
MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
>;
@@ -595,6 +1072,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
@@ -602,3 +1124,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 1a473e83efbf..7359c206ffe8 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2014-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
@@ -47,6 +47,8 @@
spi4 = &ecspi5;
usbphy0 = &usbphy1;
usbphy1 = &usbphy2;
+ lcdif0 = &lcdif1;
+ lcdif1 = &lcdif2;
};
cpus {
@@ -77,14 +79,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;
+ };
+ };
+
intc: interrupt-controller@00a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
@@ -138,13 +158,53 @@
interrupt-parent = <&gpc>;
ranges;
+ 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>;
+ };
+
pmu {
compatible = "arm,cortex-a9-pmu";
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
};
- ocram: sram@00900000 {
+ ocrams: sram@008f8000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x008f8000 0x4000>;
+ clocks = <&clks IMX6SX_CLK_OCRAM_S>;
+ };
+
+ ocrams_ddr: sram@00900000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x00900000 0x1000>;
+ clocks = <&clks IMX6SX_CLK_OCRAM>;
+ };
+
+ ocram: sram@00901000 {
compatible = "mmio-sram";
+ reg = <0x00901000 0x1F000>;
+ clocks = <&clks IMX6SX_CLK_OCRAM>;
+ };
+
+ ocram_mf: sram-mf@00900000 {
+ compatible = "fsl,mega-fast-sram";
reg = <0x00900000 0x20000>;
clocks = <&clks IMX6SX_CLK_OCRAM>;
};
@@ -159,16 +219,6 @@
arm,data-latency = <4 2 3>;
};
- gpu: gpu@01800000 {
- compatible = "vivante,gc";
- reg = <0x01800000 0x4000>;
- interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SX_CLK_GPU>,
- <&clks IMX6SX_CLK_GPU>,
- <&clks IMX6SX_CLK_GPU>;
- clock-names = "bus", "core", "shader";
- };
-
dma_apbh: dma-apbh@01804000 {
compatible = "fsl,imx6sx-dma-apbh", "fsl,imx28-dma-apbh";
reg = <0x01804000 0x2000>;
@@ -182,6 +232,37 @@
clocks = <&clks IMX6SX_CLK_APBH_DMA>;
};
+ caam_sm: caam-sm@00100000 {
+ compatible = "fsl,imx6q-caam-sm";
+ reg = <0x00100000 0x3fff>;
+ };
+
+ irq_sec_vio: caam_secvio {
+ compatible = "fsl,imx6q-caam-secvio";
+ interrupts = <0 20 0x04>;
+ secvio_src = <0x8000001d>;
+ jtag-tamper = "disabled";
+ watchdog-tamper = "enabled";
+ internal-boot-tamper = "enabled";
+ external-pin-tamper = "disabled";
+ };
+
+ gpu: gpu@01800000 {
+ compatible = "fsl,imx6sx-gpu", "fsl,imx6q-gpu";
+ reg = <0x01800000 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 = <&gpc 1>;
+ };
+
gpmi: gpmi-nand@01806000{
compatible = "fsl,imx6sx-gpmi-nand";
#address-cells = <1>;
@@ -247,6 +328,8 @@
clocks = <&clks IMX6SX_CLK_ECSPI1>,
<&clks IMX6SX_CLK_ECSPI1>;
clock-names = "ipg", "per";
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -259,6 +342,8 @@
clocks = <&clks IMX6SX_CLK_ECSPI2>,
<&clks IMX6SX_CLK_ECSPI2>;
clock-names = "ipg", "per";
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -271,6 +356,8 @@
clocks = <&clks IMX6SX_CLK_ECSPI3>,
<&clks IMX6SX_CLK_ECSPI3>;
clock-names = "ipg", "per";
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -283,11 +370,14 @@
clocks = <&clks IMX6SX_CLK_ECSPI4>,
<&clks IMX6SX_CLK_ECSPI4>;
clock-names = "ipg", "per";
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
uart1: serial@02020000 {
- compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ compatible = "fsl,imx6sx-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02020000 0x4000>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_UART_IPG>,
@@ -299,6 +389,7 @@
};
esai: esai@02024000 {
+ compatible = "fsl,imx35-esai";
reg = <0x02024000 0x4000>;
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_ESAI_IPG>,
@@ -308,6 +399,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";
};
@@ -319,7 +413,7 @@
clocks = <&clks IMX6SX_CLK_SSI1_IPG>,
<&clks IMX6SX_CLK_SSI1>;
clock-names = "ipg", "baud";
- dmas = <&sdma 37 1 0>, <&sdma 38 1 0>;
+ dmas = <&sdma 37 22 0>, <&sdma 38 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
@@ -333,7 +427,7 @@
clocks = <&clks IMX6SX_CLK_SSI2_IPG>,
<&clks IMX6SX_CLK_SSI2>;
clock-names = "ipg", "baud";
- dmas = <&sdma 41 1 0>, <&sdma 42 1 0>;
+ dmas = <&sdma 41 22 0>, <&sdma 42 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
@@ -347,25 +441,34 @@
clocks = <&clks IMX6SX_CLK_SSI3_IPG>,
<&clks IMX6SX_CLK_SSI3>;
clock-names = "ipg", "baud";
- dmas = <&sdma 45 1 0>, <&sdma 46 1 0>;
+ dmas = <&sdma 45 22 0>, <&sdma 46 22 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
status = "disabled";
};
asrc: asrc@02034000 {
+ 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>;
+ 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";
+ fsl,asrc-rate = <48000>;
+ fsl,asrc-width = <16>;
status = "okay";
};
};
@@ -417,6 +520,7 @@
clocks = <&clks IMX6SX_CLK_CAN1_IPG>,
<&clks IMX6SX_CLK_CAN1_SERIAL>;
clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x10 1 0x10 17>;
status = "disabled";
};
@@ -427,6 +531,7 @@
clocks = <&clks IMX6SX_CLK_CAN2_IPG>,
<&clks IMX6SX_CLK_CAN2_SERIAL>;
clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x10 2 0x10 18>;
status = "disabled";
};
@@ -523,6 +628,12 @@
gpio-ranges = <&iomuxc 0 148 10>, <&iomuxc 10 169 2>;
};
+ mqs: mqs {
+ compatible = "fsl,imx6sx-mqs";
+ gpr = <&gpr>;
+ status = "disabled";
+ };
+
kpp: kpp@020b8000 {
compatible = "fsl,imx6sx-kpp", "fsl,imx21-kpp";
reg = <0x020b8000 0x4000>;
@@ -576,20 +687,21 @@
anatop-min-bit-val = <4>;
anatop-min-voltage = <800000>;
anatop-max-voltage = <1375000>;
+ anatop-enable-bit = <0>;
};
- regulator-3p0 {
+ reg_3p0: regulator-3p0@120 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd3p0";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <3150000>;
- regulator-always-on;
+ regulator-min-microvolt = <2625000>;
+ regulator-max-microvolt = <3400000>;
anatop-reg-offset = <0x120>;
anatop-vol-bit-shift = <8>;
anatop-vol-bit-width = <5>;
anatop-min-bit-val = <0>;
anatop-min-voltage = <2625000>;
anatop-max-voltage = <3400000>;
+ anatop-enable-bit = <0>;
};
regulator-2p5 {
@@ -604,6 +716,7 @@
anatop-min-bit-val = <0>;
anatop-min-voltage = <2100000>;
anatop-max-voltage = <2875000>;
+ anatop-enable-bit = <0>;
};
reg_arm: regulator-vddcore {
@@ -623,9 +736,9 @@
anatop-max-voltage = <1450000>;
};
- reg_pcie: regulator-vddpcie {
+ reg_pcie_phy: regulator-vddpcie-phy@140 {
compatible = "fsl,anatop-regulator";
- regulator-name = "vddpcie";
+ regulator-name = "vddpcie-phy";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1450000>;
anatop-reg-offset = <0x140>;
@@ -670,6 +783,7 @@
reg = <0x020c9000 0x1000>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_USBPHY1>;
+ phy-3p0-supply = <&reg_3p0>;
fsl,anatop = <&anatop>;
};
@@ -678,9 +792,21 @@
reg = <0x020ca000 0x1000>;
interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_USBPHY2>;
+ phy-3p0-supply = <&reg_3p0>;
fsl,anatop = <&anatop>;
};
+ usbphy_nop1: usbphy_nop1 {
+ compatible = "usb-nop-xceiv";
+ clocks = <&clks IMX6SX_CLK_USBPHY1>;
+ clock-names = "main_clk";
+ };
+
+ caam_snvs: caam-snvs@020cc000 {
+ compatible = "fsl,imx6q-caam-snvs";
+ reg = <0x020cc000 0x4000>;
+ };
+
snvs: snvs@020cc000 {
compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
reg = <0x020cc000 0x4000>;
@@ -696,7 +822,7 @@
compatible = "syscon-poweroff";
regmap = <&snvs>;
offset = <0x38>;
- mask = <0x60>;
+ mask = <0x61>;
status = "disabled";
};
@@ -734,6 +860,16 @@
#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_GPU>, <&clks IMX6SX_CLK_IPG>,
+ <&clks IMX6SX_CLK_PXP_AXI>, <&clks IMX6SX_CLK_DISPLAY_AXI>,
+ <&clks IMX6SX_CLK_LCDIF1_PIX>, <&clks IMX6SX_CLK_LCDIF_APB>,
+ <&clks IMX6SX_CLK_LCDIF2_PIX>, <&clks IMX6SX_CLK_CSI>,
+ <&clks IMX6SX_CLK_VADC>;
+ clock-names = "gpu3d_core", "ipg", "pxp_axi", "disp_axi", "lcdif1_pix",
+ "lcdif_axi", "lcdif2_pix", "csi_mclk";
+ pcie-phy-supply = <&reg_pcie_phy>;
+ #power-domain-cells = <1>;
};
iomuxc: iomuxc@020e0000 {
@@ -747,8 +883,32 @@
reg = <0x020e4000 0x4000>;
};
+ ldb: ldb@020e0014 {
+ #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@020ec000 {
- compatible = "fsl,imx6sx-sdma", "fsl,imx6q-sdma";
+ compatible = "fsl,imx6sx-sdma", "fsl,imx35-sdma";
reg = <0x020ec000 0x4000>;
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_SDMA>,
@@ -769,12 +929,10 @@
crypto: caam@2100000 {
compatible = "fsl,sec-v4.0";
- fsl,sec-era = <4>;
#address-cells = <1>;
#size-cells = <1>;
- reg = <0x2100000 0x10000>;
- ranges = <0 0x2100000 0x10000>;
- interrupt-parent = <&intc>;
+ reg = <0x2100000 0x40000>;
+ ranges = <0 0x2100000 0x40000>;
clocks = <&clks IMX6SX_CLK_CAAM_MEM>,
<&clks IMX6SX_CLK_CAAM_ACLK>,
<&clks IMX6SX_CLK_CAAM_IPG>,
@@ -828,6 +986,7 @@
clocks = <&clks IMX6SX_CLK_USBOH3>;
fsl,usbmisc = <&usbmisc 2>;
phy_type = "hsic";
+ fsl,usbphy = <&usbphy_nop1>;
fsl,anatop = <&anatop>;
dr_mode = "host";
ahb-burst-config = <0x0>;
@@ -857,15 +1016,20 @@
"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";
};
mlb: mlb@0218c000 {
+ compatible = "fsl,imx6sx-mlb50";
reg = <0x0218c000 0x4000>;
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_MLB>;
+ clock-names = "mlb";
+ iram = <&ocram>;
status = "disabled";
};
@@ -964,6 +1128,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";
};
@@ -975,21 +1143,28 @@
};
ocotp: ocotp@021bc000 {
- compatible = "fsl,imx6sx-ocotp", "syscon";
+ compatible = "fsl,imx6sx-ocotp", "fsl,imx6q-ocotp", "syscon";
reg = <0x021bc000 0x4000>;
clocks = <&clks IMX6SX_CLK_OCOTP>;
};
+ romcp@021ac000 {
+ compatible = "fsl,imx6sx-romcp", "syscon";
+ reg = <0x021ac000 0x4000>;
+ };
+
sai1: sai@021d4000 {
compatible = "fsl,imx6sx-sai";
reg = <0x021d4000 0x4000>;
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_SAI1_IPG>,
+ <&clks IMX6SX_CLK_DUMMY>,
<&clks IMX6SX_CLK_SAI1>,
<&clks 0>, <&clks 0>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 31 24 0>, <&sdma 32 24 0>;
+ dma-source = <&gpr 0 15 0 16>;
status = "disabled";
};
@@ -1004,9 +1179,10 @@
reg = <0x021dc000 0x4000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_SAI2_IPG>,
+ <&clks IMX6SX_CLK_DUMMY>,
<&clks IMX6SX_CLK_SAI2>,
<&clks 0>, <&clks 0>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 33 24 0>, <&sdma 34 24 0>;
status = "disabled";
@@ -1038,8 +1214,15 @@
status = "disabled";
};
+ qspi_m4: qspi-m4 {
+ compatible = "fsl,imx6sx-qspi-m4-restore";
+ reg = <0x021e4000 0x4000>;
+ status = "disabled";
+ };
+
uart2: serial@021e8000 {
- compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ compatible = "fsl,imx6sx-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021e8000 0x4000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_UART_IPG>,
@@ -1051,7 +1234,8 @@
};
uart3: serial@021ec000 {
- compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ compatible = "fsl,imx6sx-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021ec000 0x4000>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_UART_IPG>,
@@ -1063,7 +1247,8 @@
};
uart4: serial@021f0000 {
- compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ compatible = "fsl,imx6sx-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f0000 0x4000>;
interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_UART_IPG>,
@@ -1075,7 +1260,8 @@
};
uart5: serial@021f4000 {
- compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ compatible = "fsl,imx6sx-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f4000 0x4000>;
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_UART_IPG>,
@@ -1095,6 +1281,11 @@
clocks = <&clks IMX6SX_CLK_I2C4>;
status = "disabled";
};
+
+ qosc: qosc@021fc000 {
+ compatible = "fsl,imx6sx-qosc";
+ reg = <0x021fc000 0x4000>;
+ };
};
aips3: aips-bus@02200000 {
@@ -1112,31 +1303,59 @@
ranges;
csi1: csi@02214000 {
+ 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 = <&gpc 2>;
+ status = "disabled";
+ };
+
+ dcic1: dcic@0220c000 {
+ compatible = "fsl,imx6sx-dcic";
+ reg = <0x0220c000 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@02210000 {
+ compatible = "fsl,imx6sx-dcic";
+ reg = <0x02210000 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@02218000 {
+ 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>,
<&clks IMX6SX_CLK_DISPLAY_AXI>;
clock-names = "pxp-axi", "disp-axi";
+ power-domains = <&gpc 2>;
status = "disabled";
};
csi2: csi@0221c000 {
+ compatible = "fsl,imx6s-csi";
reg = <0x0221c000 0x4000>;
interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_DISPLAY_AXI>,
<&clks IMX6SX_CLK_CSI>,
<&clks IMX6SX_CLK_DCIC2>;
- clock-names = "disp-axi", "csi_mclk", "dcic";
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+ power-domains = <&gpc 2>;
status = "disabled";
};
@@ -1148,6 +1367,7 @@
<&clks IMX6SX_CLK_LCDIF_APB>,
<&clks IMX6SX_CLK_DISPLAY_AXI>;
clock-names = "pix", "axi", "disp_axi";
+ power-domains = <&gpc 2>;
status = "disabled";
};
@@ -1159,15 +1379,19 @@
<&clks IMX6SX_CLK_LCDIF_APB>,
<&clks IMX6SX_CLK_DISPLAY_AXI>;
clock-names = "pix", "axi", "disp_axi";
+ power-domains = <&gpc 2>;
status = "disabled";
};
vadc: vadc@02228000 {
+ compatible = "fsl,imx6sx-vadc";
reg = <0x02228000 0x4000>, <0x0222c000 0x4000>;
reg-names = "vadc-vafe", "vadc-vdec";
clocks = <&clks IMX6SX_CLK_VADC>,
<&clks IMX6SX_CLK_CSI>;
clock-names = "vadc", "csi";
+ power-domains = <&gpc 2>;
+ gpr = <&gpr>;
status = "disabled";
};
};
@@ -1177,6 +1401,7 @@
reg = <0x02280000 0x4000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_IPG>;
+ num-channels = <4>;
clock-names = "adc";
fsl,adck-max-frequency = <30000000>, <40000000>,
<20000000>;
@@ -1188,6 +1413,7 @@
reg = <0x02284000 0x4000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_IPG>;
+ num-channels = <4>;
clock-names = "adc";
fsl,adck-max-frequency = <30000000>, <40000000>,
<20000000>;
@@ -1214,8 +1440,28 @@
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>;
+ status = "okay";
+ };
+
+ rpmsg: rpmsg{
+ compatible = "fsl,imx6sx-rpmsg";
+ status = "disabled";
+ };
+
uart6: serial@022a0000 {
- compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ compatible = "fsl,imx6sx-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x022a0000 0x4000>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_UART_IPG>,
@@ -1269,24 +1515,30 @@
pcie: pcie@0x08000000 {
compatible = "fsl,imx6sx-pcie", "snps,dw-pcie";
- reg = <0x08ffc000 0x4000>; /* DBI */
+ reg = <0x08ffc000 0x4000>, <0x08f00000 0x80000>;
+ reg-names = "dbi", "config";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
- /* configuration space */
- ranges = <0x00000800 0 0x08f00000 0x08f00000 0 0x00080000
- /* downstream I/O */
- 0x81000000 0 0 0x08f80000 0 0x00010000
- /* non-prefetchable memory */
- 0x82000000 0 0x08000000 0x08000000 0 0x00f00000>;
+ ranges = <0x81000000 0 0 0x08f80000 0 0x00010000 /* downstream I/O */
+ 0x82000000 0 0x08000000 0x08000000 0 0x00f00000>; /* non-prefetchable memory */
num-lanes = <1>;
- interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SX_CLK_PCIE_REF_125M>,
- <&clks IMX6SX_CLK_PCIE_AXI>,
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PCIE_AXI>,
<&clks IMX6SX_CLK_LVDS1_OUT>,
+ <&clks IMX6SX_CLK_PCIE_REF_125M>,
<&clks IMX6SX_CLK_DISPLAY_AXI>;
- clock-names = "pcie_ref_125m", "pcie_axi",
- "lvds_gate", "display_axi";
+ clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_inbound_axi";
+ pcie-phy-supply = <&reg_pcie_phy>;
+ power-domains = <&gpc 2>;
+ fsl,max-link-speed = <2>;
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/imx6sxscm-1gb-evb-btwifi-ldo.dts b/arch/arm/boot/dts/imx6sxscm-1gb-evb-btwifi-ldo.dts
new file mode 100644
index 000000000000..a31c4d69bd0e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-1gb-evb-btwifi-ldo.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 "imx6sxscm-1gb-evb-ldo.dts"
+#include "imx6sxscm-evb-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6sxscm-1gb-evb-lcdif1-ldo.dts b/arch/arm/boot/dts/imx6sxscm-1gb-evb-lcdif1-ldo.dts
new file mode 100644
index 000000000000..03ddbe9e6525
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-1gb-evb-lcdif1-ldo.dts
@@ -0,0 +1,42 @@
+/*
+ * 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 "imx6sxscm-1gb-evb-ldo.dts"
+/ {
+ regulators {
+ reg_lcd_3v3: regulator@4 {
+ status = "okay";
+ };
+ };
+
+ sii902x_reset: sii902x-reset {
+ status = "okay";
+ };
+};
+
+&csi1 {
+ status = "disabled";
+};
+
+&lcdif1 {
+ status = "okay";
+};
+
+&i2c4 {
+ sii902x@39 {
+ status = "okay";
+ };
+};
+
+&ov5640 {
+ status = "disabled";
+};
+
+&crypto {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6sxscm-1gb-evb-ldo.dts b/arch/arm/boot/dts/imx6sxscm-1gb-evb-ldo.dts
new file mode 100644
index 000000000000..357b92098318
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-1gb-evb-ldo.dts
@@ -0,0 +1,9 @@
+/*
+ * 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 "imx6sxscm-evb-ldo.dts"
diff --git a/arch/arm/boot/dts/imx6sxscm-1gb-evb-m4-ldo.dts b/arch/arm/boot/dts/imx6sxscm-1gb-evb-m4-ldo.dts
new file mode 100644
index 000000000000..af0e8be603ed
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-1gb-evb-m4-ldo.dts
@@ -0,0 +1,90 @@
+/*
+ * 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 "imx6sxscm-1gb-evb-ldo.dts"
+/{
+ memory {
+ linux,usable-memory = <0x80000000 0x1ff00000>,
+ <0xa0000000 0x1ff00000>;
+ };
+};
+
+&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/imx6sxscm-1gb-evb-mqs-ldo.dts b/arch/arm/boot/dts/imx6sxscm-1gb-evb-mqs-ldo.dts
new file mode 100644
index 000000000000..08aac2c6636f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-1gb-evb-mqs-ldo.dts
@@ -0,0 +1,43 @@
+/*
+ * 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 "imx6sxscm-1gb-evb-ldo.dts"
+/ {
+ 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";
+};
+
+&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/imx6sxscm-1gb-evb-sai-ldo.dts b/arch/arm/boot/dts/imx6sxscm-1gb-evb-sai-ldo.dts
new file mode 100644
index 000000000000..d95d2e6f45c3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-1gb-evb-sai-ldo.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 "imx6sxscm-1gb-evb-ldo.dts"
+/ {
+ sound {
+ cpu-dai = <&sai1>;
+ };
+};
+
+&audmux {
+ /* pin conflict with sai */
+ status = "disabled";
+};
+
+&sai1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+ status = "okay";
+};
+
+&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/imx6sxscm-512mb-evb-ldo.dts b/arch/arm/boot/dts/imx6sxscm-512mb-evb-ldo.dts
new file mode 100644
index 000000000000..f34b35802167
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-512mb-evb-ldo.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 "imx6sxscm-1gb-evb-ldo.dts"
+#include "imx6sxscm-512mb.dtsi"
diff --git a/arch/arm/boot/dts/imx6sxscm-512mb-evb-m4-ldo.dts b/arch/arm/boot/dts/imx6sxscm-512mb-evb-m4-ldo.dts
new file mode 100644
index 000000000000..240859445747
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-512mb-evb-m4-ldo.dts
@@ -0,0 +1,19 @@
+/*
+ * 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 "imx6sxscm-1gb-evb-m4-ldo.dts"
+/{
+ memory {
+ linux,usable-memory = <0x80000000 0x1ff00000> ;
+ };
+};
+
+&rpmsg{
+ vdev-nums = <1>;
+ reg = <0x9FFF0000 0x10000>;
+};
diff --git a/arch/arm/boot/dts/imx6sxscm-512mb.dtsi b/arch/arm/boot/dts/imx6sxscm-512mb.dtsi
new file mode 100644
index 000000000000..023c997640bc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-512mb.dtsi
@@ -0,0 +1,14 @@
+/*
+ * 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.
+ */
+
+/ {
+ memory {
+ reg = <0x80000000 0x20000000>;
+ };
+
+};
diff --git a/arch/arm/boot/dts/imx6sxscm-emmc.dtsi b/arch/arm/boot/dts/imx6sxscm-emmc.dtsi
new file mode 100644
index 000000000000..7e616f40ce51
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-emmc.dtsi
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+&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>;
+ no-1-8-v;
+ non-removable;
+ status = "okay";
+};
+
+&spdif {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6sxscm-epop-evb-ldo.dts b/arch/arm/boot/dts/imx6sxscm-epop-evb-ldo.dts
new file mode 100644
index 000000000000..62bc1ff83776
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-epop-evb-ldo.dts
@@ -0,0 +1,9 @@
+/*
+ * 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 "imx6sxscm-512mb-evb-ldo.dts"
+#include "imx6sxscm-emmc.dtsi"
diff --git a/arch/arm/boot/dts/imx6sxscm-epop-evb-m4-ldo.dts b/arch/arm/boot/dts/imx6sxscm-epop-evb-m4-ldo.dts
new file mode 100644
index 000000000000..ab6060283f92
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-epop-evb-m4-ldo.dts
@@ -0,0 +1,9 @@
+/*
+ * 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 "imx6sxscm-512mb-evb-m4-ldo.dts"
+#include "imx6sxscm-emmc.dtsi"
diff --git a/arch/arm/boot/dts/imx6sxscm-evb-btwifi.dtsi b/arch/arm/boot/dts/imx6sxscm-evb-btwifi.dtsi
new file mode 100644
index 000000000000..36583898f5dc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-evb-btwifi.dtsi
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+/ {
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio4 8 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ vcc_sd3: regulator@0 {
+ status = "disabled";
+ };
+
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ gpios = <&gpio7 9 0>; /* WL_HOST_WAKE */
+ };
+};
+
+&iomuxc {
+ imx6sxscm-evb-murata-v2_rc {
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ MX6SX_PAD_NAND_DATA05__GPIO4_IO_9 0x13069
+ >;
+ };
+
+ pinctrl_uart6: uart6grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL1__UART6_TX 0x1b0b1
+ MX6SX_PAD_KEY_ROW1__UART6_RX 0x1b0b1
+ MX6SX_PAD_KEY_COL0__UART6_RTS_B 0x1b0b1
+ MX6SX_PAD_KEY_ROW0__UART6_CTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc3_1: usdhc3grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17069
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10071
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17069
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17069
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17069
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17069
+ >;
+ };
+
+ pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
+ >;
+ };
+
+ /* For Murata, SD to 4-bit SDIO; use upper 4-bits for UART */
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17069
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10071
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17069
+ MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17069
+ MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17069
+ MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17069
+ /* Murata Module control signals */
+ MX6SX_PAD_NAND_DATA04__GPIO4_IO_8 0x13069
+ MX6SX_PAD_SD3_DATA7__GPIO7_IO_9 0x13069
+ >;
+ };
+ };
+};
+
+&uart6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart6
+ &pinctrl_bt>;
+ fsl,uart-has-rtscts;
+ resets = <&modem_reset>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3_1>;
+ pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
+ bus-width = <4>;
+};
+
diff --git a/arch/arm/boot/dts/imx6sxscm-evb-ldo.dts b/arch/arm/boot/dts/imx6sxscm-evb-ldo.dts
new file mode 100644
index 000000000000..954057769c87
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-evb-ldo.dts
@@ -0,0 +1,34 @@
+/*
+ * 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 "imx6sxscm-evb.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
+ >;
+ arm-supply = <&reg_arm>;
+ soc-supply = <&reg_soc>;
+ fsl,arm-soc-shared = <0>;
+};
+
+&gpc {
+ /* use ldo-enable, u-boot will check it and configure */
+ fsl,ldo-bypass = <0>;
+};
diff --git a/arch/arm/boot/dts/imx6sxscm-evb.dts b/arch/arm/boot/dts/imx6sxscm-evb.dts
new file mode 100644
index 000000000000..97651e7e6b6c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sxscm-evb.dts
@@ -0,0 +1,1156 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sx.dtsi"
+
+/ {
+ model = "Freescale i.MX6 SXSCM EVB Board";
+ compatible = "fsl,imx6sx-sdb", "fsl,imx6sx";
+
+ chosen {
+ stdout-path = &uart3;
+ };
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ backlight1 {
+ compatible = "pwm-backlight";
+ pwms = <&pwm3 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ fb-names = "mxs-lcdif0";
+ };
+
+ 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";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
+ hannstar_cabc {
+ compatible = "hannstar,cabc";
+
+ lvds0 {
+ gpios = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vcc_sd3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_vcc_sd3>;
+ regulator-name = "VCC_SD3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ reg_usb_otg1_vbus: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg2_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg2>;
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ };
+
+ reg_psu_5v: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "PSU-5V0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_lcd_3v3: regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "lcd-3v3";
+ gpio = <&gpio3 27 0>;
+ enable-active-high;
+ status = "disabled";
+ };
+
+ reg_peri_3v3: regulator@5 {
+ compatible = "regulator-fixed";
+ reg = <5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_peri_3v3>;
+ regulator-name = "peri_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 16 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ reg_enet_3v3: regulator@6 {
+ compatible = "regulator-fixed";
+ reg = <6>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_3v3>;
+ regulator-name = "enet_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio4 25 GPIO_ACTIVE_LOW>,
+ <&gpio4 26 GPIO_ACTIVE_HIGH>;
+ };
+
+ reg_vref_3v3: regulator@7 {
+ compatible = "regulator-fixed";
+ reg = <7>;
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_pcie: regulator@8 {
+ compatible = "regulator-fixed";
+ reg = <8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie_reg>;
+ regulator-name = "MPCIE_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 1 0>;
+ regulator-always-on;
+ enable-active-high;
+ };
+
+ reg_can_en: regulator@9 {
+ compatible = "regulator-fixed";
+ reg = <9>;
+ regulator-name = "can-en";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_can_stby: regulator@10 {
+ compatible = "regulator-fixed";
+ reg = <10>;
+ regulator-name = "can-stby";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 27 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ sound {
+ compatible = "fsl,imx6sxscm-evb-wm8962", "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ cpu-dai = <&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 = <6>;
+ codec-master;
+ hp-det-gpios = <&gpio1 17 1>;
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif",
+ "fsl,imx6sx-sdb-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-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";
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-supply = <&reg_enet_3v3>;
+ phy-mode = "rgmii";
+ phy-reset-gpios = <&gpio4 26 0>;
+ fsl,magic-packet;
+ status = "okay";
+};
+
+&csi1 {
+ status = "okay";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
+&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";
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ 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;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ egalax_ts@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ 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";
+
+ mma8451@1c {
+ compatible = "fsl,mma8451";
+ reg = <0x1c>;
+ position = <1>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <17 8>;
+ interrupt-route = <2>;
+ };
+
+ mag3110@0e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ position = <2>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <22 1>;
+ shared-interrupt;
+ };
+
+ isl29023@44 {
+ compatible = "fsl,isl29023";
+ reg = <0x44>;
+ rext = <499>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <22 1>;
+ shared-interrupt;
+ };
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ codec: wm8962@1a {
+ compatible = "wlf,wm8962";
+ reg = <0x1a>;
+ clocks = <&clks IMX6SX_CLK_AUDIO>;
+ DCVDD-supply = <&vgen4_reg>;
+ DBVDD-supply = <&vgen4_reg>;
+ AVDD-supply = <&vgen4_reg>;
+ CPVDD-supply = <&vgen4_reg>;
+ MICVDD-supply = <&vgen3_reg>;
+ PLLVDD-supply = <&vgen4_reg>;
+ SPKVDD1-supply = <&reg_psu_5v>;
+ SPKVDD2-supply = <&reg_psu_5v>;
+ amic-mono;
+ };
+ 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>;
+ DVDD-supply = <&vgen2_reg>;
+ 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: 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";
+ };
+};
+
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 996000 1250000
+ 792000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC uV */
+ 996000 1250000
+ 792000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,arm-soc-shared = <1>;
+};
+
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+
+&qspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi2_1>;
+ status = "okay";
+
+#ifndef SPANSIONFLASH
+ 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>;
+ };
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <1>;
+ };
+#endif
+};
+
+&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>;
+ };
+};
+
+&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>;
+ };
+ };
+ };
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
+ status = "okay";
+};
+
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm4>;
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&sai1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+ status = "disabled";
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif>;
+ status = "okay";
+};
+
+&ssi2 {
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ wifi-host;
+ no-1-8-v;
+ keep-power-in-suspend;
+ wakeup-source;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ bus-width = <8>;
+ cd-gpios = <>;
+ wp-gpios = <>;
+ keep-power-in-suspend;
+ wakeup-source;
+ pm-ignore-notify;
+ vmmc-supply = <>;
+ status = "okay";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ cd-gpios = <&gpio6 21 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio6 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog &pinctrl_can_gpios>;
+
+ imx6x-sdb {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA1__GPIO4_IO_17 0x17059
+ MX6SX_PAD_QSPI1A_SS0_B__GPIO4_IO_22 0xb000
+ MX6SX_PAD_CSI_DATA03__GPIO1_IO_17 0x17059
+ MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x30b0
+ MX6SX_PAD_QSPI1A_SCLK__GPIO4_IO_21 0x17059
+ >;
+ };
+
+ pinctrl_can_gpios: can-gpios {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27 0x17059
+ >;
+ };
+
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130b0
+ MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x130b0
+ MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x120b0
+ MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x130b0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
+ >;
+ };
+
+ pinctrl_canfd1: canfd1grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DQS__CANFD_TX1 0x1b0b0
+ MX6SX_PAD_QSPI1A_SS1_B__CANFD_RX1 0x1b0b0
+ >;
+ };
+
+ pinctrl_canfd2: canfd2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS1_B__CANFD_RX2 0x1b0b0
+ MX6SX_PAD_QSPI1A_DQS__CANFD_TX2 0x1b0b0
+ >;
+ };
+
+ 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_GPIO1_IO05__ENET1_MDIO 0xa0b1
+ MX6SX_PAD_GPIO1_IO04__ENET1_MDC 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
+ MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
+ MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x91
+ >;
+ };
+
+ pinctrl_enet_3v3: enet3v3grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DATA1__GPIO4_IO_25 0x80000000
+ MX6SX_PAD_QSPI1B_DATA2__GPIO4_IO_26 0x80000000
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
+ MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b020
+ MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x1b020
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x1b020
+ MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x1b020
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
+ MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ 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
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x4001b8b1
+ MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_lcd: lcdgrp {
+ fsl,pins = <
+ MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0
+ MX6SX_PAD_LCD1_CLK__LCDIF1_CLK 0x4001b0b0
+ MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0
+ MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x4001b0b0
+ >;
+ };
+
+ pinctrl_mqs: mqsgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CLK__MQS_RIGHT 0x120b0
+ MX6SX_PAD_SD2_CMD__MQS_LEFT 0x120b0
+ >;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x10b0
+ >;
+ };
+
+ pinctrl_pcie_reg: pciereggrp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 0x10b0
+ >;
+ };
+
+ pinctrl_peri_3v3: peri3v3grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x80000000
+ >;
+ };
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX6SX_PAD_NAND_DATA06__PWM3_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX6SX_PAD_NAND_DATA07__PWM4_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_qspi2_1: qspi2grp_1 {
+ fsl,pins = <
+ MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70f1
+ MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x70f1
+ MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x70f1
+ MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x70f1
+ MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x70f1
+ MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x70f1
+ MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x70f1
+ MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x70f1
+ MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x70f1
+ MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x70f1
+ MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x70f1
+ MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x70f1
+ >;
+ };
+
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x130b0
+ MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x130b0
+ MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x120b0
+ MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x130b0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
+ >;
+ };
+
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x1b0b0
+ >;
+ };
+
+ pinctrl_vcc_sd3: vccsd3grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO05__UART1_RX 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_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
+ >;
+ };
+
+ pinctrl_usb_otg1_id: usbotg1idgrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usb_otg2: usbot2ggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12 0x10b0
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
+ MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17059
+ MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17059
+ MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17069
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10071
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17069
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17069
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17069
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17069
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17069
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17069
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17069
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17069
+ MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059
+ MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ 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_DATA7__GPIO6_IO_21 0x17059
+ MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059
+ >;
+ };
+
+ 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_uart3: uart3grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS0_B__UART3_TX 0x1b0b1
+ MX6SX_PAD_QSPI1B_SCLK__UART3_RX 0x1b0b1
+ >;
+ };
+ };
+};
+
+&vadc {
+ vadc_in = <0>;
+ csi_id = <1>;
+ status = "disabled";
+ port {
+ vadc_ep: endpoint {
+ remote-endpoint = <&csi2_ep>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-emmc.dts b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-emmc.dts
new file mode 100644
index 000000000000..2e35ed6d353e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-emmc.dts
@@ -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.
+ */
+
+#include "imx6ul-14x14-ddr3-arm2.dts"
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1_8bit>;
+ pinctrl-1 = <&pinctrl_usdhc1_8bit_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_8bit_200mhz>;
+ bus-width = <8>;
+ cd-gpios = <>;
+ wp-gpios = <>;
+ vmmc-supply = <>;
+ tuning-step = <2>;
+ non-removable;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-flexcan2.dts b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-flexcan2.dts
new file mode 100644
index 000000000000..1a3a0141d747
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-flexcan2.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 "imx6ul-14x14-ddr3-arm2.dts"
+
+&uart2{
+ status = "disabled";
+};
+
+&can2 {
+ status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-gpmi-weim.dts b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-gpmi-weim.dts
new file mode 100644
index 000000000000..2e6b54495d05
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-gpmi-weim.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 "imx6ul-14x14-ddr3-arm2.dts"
+
+/*
+ * solve pin conflict with NAND
+ *
+ * USDHC2_CD, SD2_RST_B, USDHC2_WP conflict with RAWNAND CE pins , also
+ * overwritten the conflict of SD2_RST_B with RAWNAND ALE in hog
+ * QSPI CLK, CE and DATA pins conflict with RAWNAND data pins and CE, CLE, RB,
+ * WP, DQS pin
+ *
+ */
+&iomuxc {
+ pinctrl-0 = <&pinctrl_hog>;
+};
+
+&qspi{
+ status = "disabled";
+};
+
+&gpmi{
+ status = "okay";
+};
+
+&usdhc2 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-mqs.dts b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-mqs.dts
new file mode 100644
index 000000000000..3427bc330638
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-mqs.dts
@@ -0,0 +1,41 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+/ {
+ sound-mqs {
+ compatible = "fsl,imx6ul-ddr3-arm2-mqs",
+ "fsl,imx-audio-mqs";
+ model = "mqs-audio";
+ cpu-dai = <&sai1>;
+ asrc-controller = <&asrc>;
+ audio-codec = <&mqs>;
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&sai1 {
+ assigned-clocks = <&clks IMX6UL_CLK_SAI1_SEL>,
+ <&clks IMX6UL_CLK_SAI1>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <24576000>;
+ status = "okay";
+};
+
+&mqs {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mqs>;
+ clocks = <&clks IMX6UL_CLK_SAI1>;
+ clock-names = "mclk";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-spdif.dts b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-spdif.dts
new file mode 100644
index 000000000000..7191f0572e3b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-spdif.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 "imx6ul-14x14-ddr3-arm2.dts"
+
+/ {
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-in;
+ spdif-out;
+ };
+};
+
+&iomuxc {
+ pinctrl-0 = <&pinctrl_hog &pinctrl_hog1>;
+};
+
+&usdhc1 {
+ no-1-8-v;
+ vmmc-supply = <>;
+};
+
+&usdhc2 {
+ no-1-8-v;
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif>;
+ assigned-clocks = <&clks IMX6UL_CLK_SPDIF_SEL>,
+ <&clks IMX6UL_CLK_SPDIF_PODF>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <98304000>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-wm8958.dts b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-wm8958.dts
new file mode 100644
index 000000000000..bdc5b903602a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2-wm8958.dts
@@ -0,0 +1,102 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+/ {
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_codec_5v: codec_5v {
+ compatible = "regulator-fixed";
+ regulator-name = "CODEC_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ };
+
+ reg_aud_3v3: aud_3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "AUD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ };
+
+ reg_aud_1v8: aud_1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "AUD_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ enable-active-high;
+ };
+ };
+
+ sound-wm8958 {
+ compatible = "fsl,imx6ul-ddr3-arm2-wm8958",
+ "fsl,imx-audio-wm8958";
+ model = "wm8958-audio";
+ cpu-dai = <&sai2>;
+ audio-codec = <&codec>;
+ codec-master;
+ gpr = <&gpr 4 0x100000 0x100000>;
+ hp-det-gpios = <&gpio5 0 1>;
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ codec: wm8958@1a {
+ compatible = "wlf,wm8958";
+ reg = <0x1a>;
+ clocks = <&clks IMX6UL_CLK_SAI2>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "mclk1", "mclk2";
+
+ DBVDD1-supply = <&reg_aud_1v8>;
+ DBVDD2-supply = <&reg_aud_1v8>;
+ DBVDD3-supply = <&reg_aud_3v3>;
+ AVDD2-supply = <&reg_aud_1v8>;
+ CPVDD-supply = <&reg_aud_1v8>;
+ SPKVDD1-supply = <&reg_codec_5v>;
+ SPKVDD2-supply = <&reg_codec_5v>;
+
+ wlf,ldo1ena;
+ wlf,ldo2ena;
+ };
+};
+
+&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>, <24576000>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&usdhc1 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2.dts b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2.dts
new file mode 100644
index 000000000000..ee19df657370
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-ddr3-arm2.dts
@@ -0,0 +1,774 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx6ul.dtsi"
+
+/ {
+ model = "Freescale i.MX6 UltraLite DDR3 ARM2 Board";
+ compatible = "fsl,imx6ul-14x14-ddr3-arm2", "fsl,imx6ul";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ 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_sd1_vmmc: sd1_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD1_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ reg_sd2_vmmc: sd2_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD2_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ reg_can2_3v3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "can2-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 15 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_vref_3v3: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_usb_otg1_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&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 = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&ecspi1 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio4 26 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_cs_1>;
+ status = "okay";
+
+ flash: n25q032@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,n25q032";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&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 = "mii";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+
+ ethphy1: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <2>;
+ };
+ };
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can2_3v3>;
+ status = "disabled";
+};
+
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0x1>;
+ fsl,cpu_pupscr_sw = <0x0>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <1>; /* use ldo-bypass, u-boot will check it and configure */
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "disabled";
+ nand-on-flash-bbt;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze200";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ 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-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog &pinctrl_hog1 &pinctrl_hog_sd>;
+
+ imx6ul-ddr3-arm2 {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */
+ MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x17059 /* SD1 WP */
+ MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */
+ MX6UL_PAD_CSI_MCLK__GPIO4_IO17 0x17059 /* SD2 CD */
+ MX6UL_PAD_CSI_PIXCLK__GPIO4_IO18 0x17059 /* SD2 WP */
+ >;
+ };
+
+ pinctrl_hog1: hoggrp1 {
+ fsl,pins = <
+ MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x17059 /* SD2 RESECT */
+ >;
+ };
+
+ pinctrl_hog_sd: hoggrp_sd {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 /* SD1 RESET */
+ MX6UL_PAD_GPIO1_IO08__USDHC2_VSELECT 0x17059 /* SD2 VSELECT */
+ >;
+ };
+
+ pinctrl_adc1: adc1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0xb0
+ MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
+ >;
+ };
+
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x80000000
+ MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x80000000
+ MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x80000000
+ >;
+ };
+
+ pinctrl_ecspi1_cs_1: ecspi1_cs_grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x10b0
+ >;
+ };
+
+ pinctrl_ecspi1_1: ecspi1grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x10b0
+ MX6UL_PAD_CSI_DATA07__ECSPI1_MISO 0x10b0
+ MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK 0x10b0
+ >;
+ };
+
+ 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 0x4001b0a8
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
+ MX6UL_PAD_UART4_TX_DATA__ENET2_TDATA02 0x1b0b0
+ MX6UL_PAD_UART4_RX_DATA__ENET2_TDATA03 0x1b0b0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_TX_CLK 0x4001b0a8
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_UART3_TX_DATA__ENET2_RDATA02 0x1b0b0
+ MX6UL_PAD_UART3_RX_DATA__ENET2_RDATA03 0x1b0b0
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_UART3_CTS_B__ENET2_RX_CLK 0x4001b0a8
+ MX6UL_PAD_UART5_RX_DATA__ENET2_COL 0x1b0b0
+ MX6UL_PAD_UART5_TX_DATA__ENET2_CRS 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp{
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
+ MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
+ MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x17059 /* STBY */
+ >;
+ };
+
+ 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
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001b8b1
+ MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__I2C4_SCL 0x4001b8b0
+ MX6UL_PAD_UART2_RX_DATA__I2C4_SDA 0x4001b8b0
+ >;
+ };
+
+ 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_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
+ MX6UL_PAD_LCD_RESET__LCDIF_RESET 0x79
+ >;
+ };
+
+ pinctrl_mqs: mqsgrp {
+ fsl,pins = <
+ MX6UL_PAD_JTAG_TDI__MQS_LEFT 0x11088
+ MX6UL_PAD_JTAG_TDO__MQS_RIGHT 0x11088
+ >;
+ };
+
+ pinctrl_pwm1: pmw1grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_DATA0__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
+ MX6UL_PAD_NAND_DATA07__QSPI_A_SS1_B 0x70a1
+ MX6UL_PAD_NAND_RE_B__QSPI_B_SCLK 0x70a1
+ MX6UL_PAD_NAND_DATA02__QSPI_B_DATA00 0x70a1
+ MX6UL_PAD_NAND_DATA03__QSPI_B_DATA01 0x70a1
+ MX6UL_PAD_NAND_DATA04__QSPI_B_DATA02 0x70a1
+ MX6UL_PAD_NAND_DATA05__QSPI_B_DATA03 0x70a1
+ MX6UL_PAD_NAND_WE_B__QSPI_B_SS0_B 0x70a1
+ MX6UL_PAD_NAND_DATA00__QSPI_B_SS1_B 0x70a1
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_DATA0__SAI2_TX_SYNC 0x1b0b0
+ MX6UL_PAD_SD1_DATA1__SAI2_TX_BCLK 0x1b0b0
+ MX6UL_PAD_SD1_DATA2__SAI2_RX_DATA 0x110b0
+ MX6UL_PAD_SD1_DATA3__SAI2_TX_DATA 0x1f0b8
+ MX6UL_PAD_SD1_CLK__SAI2_MCLK 0x1b0b0
+ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x17059
+ >;
+ };
+
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO08__SPDIF_OUT 0x1b0b0
+ MX6UL_PAD_GPIO1_IO09__SPDIF_IN 0x1b0b0
+ >;
+ };
+
+ 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_UART2_CTS_B__UART2_DCE_CTS 0x1b0b1
+ MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS 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_UART2_CTS_B__UART2_DTE_RTS 0x1b0b1
+ MX6UL_PAD_UART2_RTS_B__UART2_DTE_CTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_usb_otg1_id: usbotg1idgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usb_otg1: usbotg1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x10b0
+ >;
+ };
+
+ 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_usdhc1_8bit: usdhc1_8bit_grp {
+ 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_NAND_READY_B__USDHC1_DATA4 0x17059
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x17059
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x17059
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1_8bit_100mhz: usdhc1_8bit_100mhz_grp {
+ 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
+ MX6UL_PAD_NAND_READY_B__USDHC1_DATA4 0x170b9
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x170b9
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x170b9
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc1_8bit_200mhz: usdhc1_8bit_200mhz_grp {
+ 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
+ MX6UL_PAD_NAND_READY_B__USDHC1_DATA4 0x170f9
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x170f9
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x170f9
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_HSYNC__USDHC2_CMD 0x17059
+ MX6UL_PAD_CSI_VSYNC__USDHC2_CLK 0x10059
+ MX6UL_PAD_CSI_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_CSI_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_CSI_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_CSI_DATA03__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ MX6UL_PAD_CSI_HSYNC__USDHC2_CMD 0x170b9
+ MX6UL_PAD_CSI_VSYNC__USDHC2_CLK 0x100b9
+ MX6UL_PAD_CSI_DATA00__USDHC2_DATA0 0x170b9
+ MX6UL_PAD_CSI_DATA01__USDHC2_DATA1 0x170b9
+ MX6UL_PAD_CSI_DATA02__USDHC2_DATA2 0x170b9
+ MX6UL_PAD_CSI_DATA03__USDHC2_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX6UL_PAD_CSI_HSYNC__USDHC2_CMD 0x170f9
+ MX6UL_PAD_CSI_VSYNC__USDHC2_CLK 0x100f9
+ MX6UL_PAD_CSI_DATA00__USDHC2_DATA0 0x170f9
+ MX6UL_PAD_CSI_DATA01__USDHC2_DATA1 0x170f9
+ MX6UL_PAD_CSI_DATA02__USDHC2_DATA2 0x170f9
+ MX6UL_PAD_CSI_DATA03__USDHC2_DATA3 0x170f9
+ >;
+ };
+ };
+};
+
+&pxp {
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "okay";
+ fsl,qspi-has-second-chip = <1>;
+ 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>;
+ };
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <1>;
+ };
+
+ flash2: n25q256a@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <2>;
+ };
+
+ flash3: n25q256a@3 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <3>;
+ };
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2
+ &pinctrl_bt>;
+ fsl,uart-has-rtscts;
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart2dte>; */
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ 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>;
+ wp-gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ cd-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd2_vmmc>;
+ status = "okay";
+};
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..f2bf26fff351
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-csi.dts
@@ -0,0 +1,22 @@
+/*
+ * 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"
+
+
+&csi {
+ status = "okay";
+};
+
+&ov5640 {
+ status = "okay";
+};
+
+&sim2 {
+ 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..b56d34d9f8a4
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-emmc.dts
@@ -0,0 +1,20 @@
+
+/*
+ * 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 "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..7cff0874697b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-gpmi-weim.dts
@@ -0,0 +1,49 @@
+/*
+ * 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"
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "okay";
+ nand-on-flash-bbt;
+};
+
+&iomuxc {
+ imx6ul-evk-gpmi-rework {
+ 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-pf1550.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-pf1550.dts
new file mode 100644
index 000000000000..d319f2ea551d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-pf1550.dts
@@ -0,0 +1,133 @@
+/*
+ * 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 "imx6ul-14x14-evk.dts"
+
+&cpu0 {
+ /*
+ * on i.MX6UL, no separated VDD_ARM_IN and VDD_SOC_IN,
+ * to align with other platform and use the same cpufreq
+ * driver, still use the separated OPP define for arm
+ * and soc.
+ */
+ operating-points = <
+ /* kHz uV */
+ 696000 1275000
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,soc-operating-points = <
+ /* KHz uV */
+ 696000 1275000
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,arm-soc-shared = <1>;
+};
+
+&reg_arm {
+ vin-supply = <&sw1_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1_reg>;
+ regulator-allow-bypass;
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>; /* use ldo-bypass */
+};
+
+&i2c1 {
+ pmic: pf1550@08 {
+ compatible = "fsl,pf1550";
+ interrupt-parent = <&gpio5>;
+ interrupts = <4 8>;
+ reg = <0x08>;
+ pinctrl-0 = <&pinctrl_pf1550>;
+
+ onkey {
+ compatible = "fsl,pf1550-onkey";
+ linux,keycode = <KEY_POWER>;
+ wakeup;
+ };
+
+ charger {
+ compatible = "fsl,pf1550-charger";
+ };
+
+ regulators {
+ compatible = "fsl,pf1550-regulator";
+
+ sw1_reg: SW1 {
+ regulator-name = "SW1";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1387500>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ 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;
+ };
+ };
+ };
+};
+
+&sai2 {
+ status = "disabled";
+};
+
+&sound {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-usb-certi.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-usb-certi.dts
new file mode 100644
index 000000000000..8aaf248812e6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-usb-certi.dts
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/* DTS file for USB Certification at i.mx6ul 14x14 evk board */
+
+#include "imx6ul-14x14-evk.dts"
+
+/ {
+ regulators {
+ reg_usb_otg2_vbus: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>; /* hardware rework is needed */
+ tpl-support;
+};
+
+&tsc {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index e281d5087d4a..da2ae89b3f00 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -22,6 +22,19 @@
reg = <0x80000000 0x20000000>;
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ linux,cma-default;
+ };
+ };
+
backlight {
compatible = "pwm-backlight";
pwms = <&pwm1 0 5000000>;
@@ -30,6 +43,11 @@
status = "okay";
};
+ pxp_v4l2 {
+ compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
regulators {
compatible = "simple-bus";
#address-cells = <1>;
@@ -41,41 +59,90 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
enable-active-high;
};
+
+ 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>;
+ };
};
- sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "mx6ul-wm8960";
- simple-audio-card,format = "i2s";
- simple-audio-card,bitclock-master = <&dailink_master>;
- simple-audio-card,frame-master = <&dailink_master>;
- simple-audio-card,widgets =
- "Microphone", "Mic Jack",
- "Line", "Line In",
- "Line", "Line Out",
- "Speaker", "Speaker",
- "Headphone", "Headphone Jack";
- simple-audio-card,routing =
+ sound: 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",
- "Speaker", "SPK_LP",
- "Speaker", "SPK_LN",
- "Speaker", "SPK_RP",
- "Speaker", "SPK_RN",
- "LINPUT1", "Mic Jack",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT2", "Mic Jack",
"LINPUT3", "Mic Jack",
- "RINPUT1", "Mic Jack",
- "RINPUT2", "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";
+ };
- simple-audio-card,cpu {
- sound-dai = <&sai2>;
- };
+ 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>;
- dailink_master: simple-audio-card,codec {
- sound-dai = <&codec>;
- clocks = <&clks IMX6UL_CLK_SAI2>;
+ 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>;
};
};
};
@@ -88,6 +155,7 @@
&cpu0 {
arm-supply = <&reg_arm>;
soc-supply = <&reg_soc>;
+ dc-supply = <&reg_gpio_dvfs>;
};
&i2c2 {
@@ -101,6 +169,38 @@
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>;
+ };
+ };
+ };
+};
+
+&csi {
+ status = "disabled";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
};
};
@@ -124,15 +224,59 @@
#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 = <0x1>;
+ fsl,cpu_pupscr_sw = <0x0>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <0>; /* DCDC, ldo-enable */
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ mag3110@0e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ position = <2>;
+ };
+
+ fxls8471@1e {
+ compatible = "fsl,fxls8471";
+ reg = <0x1e>;
+ position = <0>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <0 8>;
+ };
+};
&lcdif {
pinctrl-names = "default";
@@ -141,7 +285,7 @@
display = <&display0>;
status = "okay";
- display0: display {
+ display0: display@0 {
bits-per-pixel = <16>;
bus-width = <24>;
@@ -173,16 +317,22 @@
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>;
};
};
@@ -202,6 +352,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>;
@@ -221,11 +387,19 @@
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 = "peripheral";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ dr_mode = "otg";
+ srp-disable;
+ hnp-disable;
+ adp-disable;
status = "okay";
};
@@ -235,6 +409,14 @@
status = "okay";
};
+&usbphy1 {
+ tx-d-cal = <0x5>;
+};
+
+&usbphy2 {
+ tx-d-cal = <0x5>;
+};
+
&usdhc1 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc1>;
@@ -250,9 +432,7 @@
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
- no-1-8-v;
- keep-power-in-suspend;
- wakeup-source;
+ non-removable;
status = "okay";
};
@@ -264,6 +444,13 @@
&iomuxc {
pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x17059
+ >;
+ };
pinctrl_csi1: csi1grp {
fsl,pins = <
@@ -282,6 +469,12 @@
>;
};
+ 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
@@ -307,7 +500,6 @@
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 0x17059
>;
};
@@ -401,6 +593,12 @@
>;
};
+ pinctrl_pf1550: pf1550 {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x80000000
+ >;
+ };
+
pinctrl_pwm1: pwm1grp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO08__PWM1_OUT 0x110b0
@@ -410,14 +608,23 @@
pinctrl_sim2: sim2grp {
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_DATA04__SIM2_PORT1_CLK 0x11
+ MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B 0xb810
+ MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN 0xb810
+ MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD 0xb811
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
@@ -443,10 +650,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_id: usbotg1idgrp {
+ 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
@@ -482,7 +704,7 @@
pinctrl_usdhc2: usdhc2grp {
fsl,pins = <
- MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x17059
+ 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
@@ -491,9 +713,65 @@
>;
};
+ 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
>;
};
+
+ 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
+ >;
+ };
};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-lpddr2-arm2.dts b/arch/arm/boot/dts/imx6ul-14x14-lpddr2-arm2.dts
new file mode 100644
index 000000000000..94f5d86cb748
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-lpddr2-arm2.dts
@@ -0,0 +1,788 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx6ul.dtsi"
+
+/ {
+ model = "Freescale i.MX6 UltraLite 14X14 LPDDR2 ARM2 Board";
+ compatible = "fsl,imx6ul-14x14-lpddr2-arm2", "fsl,imx6ul";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x20000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ 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_sd1_vmmc: sd1_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD1_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 11 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ reg_sd2_vmmc: sd2_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD2_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can1_3v3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "can1-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 15 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_vref_3v3: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_usb_otg1_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&ecspi2 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio4 22 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2_1 &pinctrl_ecspi2_cs_1>;
+ status = "disabled";
+
+ flash: n25q032@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,n25q032";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&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 = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-mode = "mii";
+ phy-handle = <&ethphy0>;
+ status = "disabled";
+};
+
+&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@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <2>;
+ };
+
+ ethphy1: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+ };
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can1_3v3>;
+ status = "disabled";
+};
+
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0x2>;
+ fsl,cpu_pupscr_sw = <0x1>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <1>; /* use ldo-bypass, u-boot will check it and configure */
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "disabled";
+ nand-on-flash-bbt;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze200";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ 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-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&pxp {
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "disabled";
+ fsl,qspi-has-second-chip = <1>;
+ 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>;
+ };
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <1>;
+ };
+
+ flash2: n25q256a@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <2>;
+ };
+
+ flash3: n25q256a@3 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <3>;
+ };
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ 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 = <&gpio4 26 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 25 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ status = "okay";
+};
+
+&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>;
+ keep-power-in-suspend;
+ vmmc-supply = <&reg_sd2_vmmc>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog &pinctrl_hog_nand>;
+
+ imx6ul-14x14-lpddr2-arm2 {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x17059 /* SD1 CD */
+ MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x17059 /* SD1 WP */
+ MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */
+ MX6UL_PAD_GPIO1_IO08__USDHC2_VSELECT 0x17059 /* SD2 VSELECT */
+ >;
+ };
+
+ pinctrl_hog_nand: hoggrp_nand {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WP_B__GPIO4_IO11 0x17059 /* SD1 RESET */
+ MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x17059 /* SD2 RESET */
+ >;
+ };
+
+ pinctrl_ecspi2_cs_1: ecspi2_cs_grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x10b0
+ >;
+ };
+
+ pinctrl_ecspi2_1: ecspi2grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA02__ECSPI2_MOSI 0x10b0
+ MX6UL_PAD_CSI_DATA03__ECSPI2_MISO 0x10b0
+ MX6UL_PAD_CSI_DATA00__ECSPI2_SCLK 0x10b0
+ >;
+ };
+
+ 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_UART2_TX_DATA__ENET1_TDATA02 0x1b0b0
+ MX6UL_PAD_UART1_RX_DATA__ENET1_RDATA03 0x1b0b0
+ MX6UL_PAD_UART1_CTS_B__ENET1_RX_CLK 0x4b01b0a8
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+ MX6UL_PAD_UART2_TX_DATA__ENET1_TDATA02 0x1b0b0
+ MX6UL_PAD_UART2_RX_DATA__ENET1_TDATA03 0x1b0b0
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_TX_CLK 0x4b01b0a8
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
+ MX6UL_PAD_UART2_RTS_B__ENET1_COL 0x1b0b0
+ MX6UL_PAD_UART2_CTS_B__ENET1_CRS 0x1b0b0
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b0a8
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_UART3_CTS_B__ENET2_RX_CLK 0x4001b0a8
+ MX6UL_PAD_UART5_RX_DATA__ENET2_COL 0x1b0b0
+ MX6UL_PAD_UART5_TX_DATA__ENET2_CRS 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp{
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX 0x1b020
+ MX6UL_PAD_ENET1_RX_DATA1__FLEXCAN1_RX 0x1b020
+ MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x17059 /* STBY */
+ >;
+ };
+
+ 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
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_VSYNC__I2C2_SDA 0x4001b8b0
+ MX6UL_PAD_CSI_HSYNC__I2C2_SCL 0x4001b8b0
+ >;
+ };
+
+ 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_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
+ MX6UL_PAD_LCD_RESET__LCDIF_RESET 0x79
+ >;
+ };
+
+ pinctrl_pwm1: pmw1grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_DQS__PWM5_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
+ MX6UL_PAD_NAND_DATA07__QSPI_A_SS1_B 0x70a1
+ MX6UL_PAD_NAND_RE_B__QSPI_B_SCLK 0x70a1
+ MX6UL_PAD_NAND_DATA02__QSPI_B_DATA00 0x70a1
+ MX6UL_PAD_NAND_DATA03__QSPI_B_DATA01 0x70a1
+ MX6UL_PAD_NAND_DATA04__QSPI_B_DATA02 0x70a1
+ MX6UL_PAD_NAND_DATA05__QSPI_B_DATA03 0x70a1
+ MX6UL_PAD_NAND_WE_B__QSPI_B_SS0_B 0x70a1
+ MX6UL_PAD_NAND_DATA00__QSPI_B_SS1_B 0x70a1
+ >;
+ };
+
+ pinctrl_mqs: mqsgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO01__MQS_LEFT 0x11088
+ MX6UL_PAD_GPIO1_IO00__MQS_RIGHT 0x11088
+ >;
+ };
+
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA01__SAI1_MCLK 0x1b0b0
+ MX6UL_PAD_CSI_DATA02__SAI1_RX_SYNC 0x1b0b0
+ MX6UL_PAD_CSI_DATA03__SAI1_RX_BCLK 0x1b0b0
+ MX6UL_PAD_CSI_DATA04__SAI1_TX_SYNC 0x1b0b0
+ MX6UL_PAD_CSI_DATA05__SAI1_TX_BCLK 0x1b0b0
+ MX6UL_PAD_CSI_DATA06__SAI1_RX_DATA 0x110b0
+ MX6UL_PAD_CSI_DATA07__SAI1_TX_DATA 0x1f0b8
+ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x17059
+ >;
+ };
+
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CMD__SPDIF_OUT 0x1b0b0
+ MX6UL_PAD_SD1_CLK__SPDIF_IN 0x1b0b0
+ >;
+ };
+
+ pinctrl_tsc: tscgrp {
+ fsl,pin = <
+ 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_adc1: adc1grp {
+ fsl,pin = <
+ MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0xb0
+ MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pin = <
+ MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001b8b1
+ MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ 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_UART2_CTS_B__UART2_DCE_CTS 0x1b0b1
+ MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS 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_UART2_CTS_B__UART2_DTE_RTS 0x1b0b1
+ MX6UL_PAD_UART2_RTS_B__UART2_DTE_CTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_usb_otg1_id: usbotg1idgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usb_otg1: usbotg1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x10b0
+ >;
+ };
+
+ 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_usdhc1_8bit: usdhc1_8bit_grp {
+ 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_NAND_READY_B__USDHC1_DATA4 0x17059
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x17059
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x17059
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1_8bit_100mhz: usdhc1_8bit_100mhz_grp {
+ 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
+ MX6UL_PAD_NAND_READY_B__USDHC1_DATA4 0x170b9
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x170b9
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x170b9
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc1_8bit_200mhz: usdhc1_8bit_200mhz_grp {
+ 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
+ MX6UL_PAD_NAND_READY_B__USDHC1_DATA4 0x170f9
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x170f9
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x170f9
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10059
+ 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: usdhc2grp100mhz {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9
+ 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: usdhc2grp200mhz {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
+ 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_usdhc2_8bit: usdhc2_8bit_grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10059
+ 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: usdhc2_8bit_100mhz_grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9
+ 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: usdhc2_8bit_200mhz_grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
+ 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
+ >;
+ };
+ };
+};
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-csi.dts b/arch/arm/boot/dts/imx6ul-9x9-evk-csi.dts
new file mode 100644
index 000000000000..21778070fb18
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-9x9-evk-csi.dts
@@ -0,0 +1,22 @@
+/*
+ * 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"
+
+
+&csi {
+ status = "okay";
+};
+
+&ov5640 {
+ status = "okay";
+};
+
+&sim2 {
+ status = "disabled";
+};
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..29896ea18303
--- /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 = <0x6000000>;
+ 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 = <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 = <0x1>;
+ 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@08 {
+ 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@0e {
+ 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..cd7a5e6964e1
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-evk-btwifi-oob.dtsi
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+&bcmdhd_wlan_0 {
+ /* Need to define WL_HOST_WAKE for OOB IRQ: ENET2_RX_ER (gpio2_15) */
+ /* Hardware modification is needed on imx6ul evk for using OOB. */
+ gpios = <&gpio2 15 0>; /* WL_HOST_WAKE */
+};
+
+&pinctrl_wifi {
+ fsl,pins = <
+ /* MUXing for WL_HOST_WAKE */
+ MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15 0x13041
+ >;
+};
+
+/*
+ * 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";
+};
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..d4810bd30d58
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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>;
+ };
+
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio5 1 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&iomuxc {
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x03029
+ >;
+ };
+};
+
+&reg_sd1_vmmc {
+ regulator-always-on;
+};
+
+&uart2 {
+ resets = <&modem_reset>;
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_wifi>;
+ no-1-8-v;
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host; /* add hook for SD card detect mechanism for BCMDHD driver */
+};
+
+&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-pinfunc.h b/arch/arm/boot/dts/imx6ul-pinfunc.h
index 0034eeb84542..9538b0ed5c11 100644
--- a/arch/arm/boot/dts/imx6ul-pinfunc.h
+++ b/arch/arm/boot/dts/imx6ul-pinfunc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 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
@@ -34,14 +34,14 @@
#define MX6UL_PAD_JTAG_MOD__ENET1_REF_CLK_25M 0x0044 0x02d0 0x0000 3 0
#define MX6UL_PAD_JTAG_MOD__CCM_PMIC_RDY 0x0044 0x02d0 0x04c0 4 0
#define MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0x0044 0x02d0 0x0000 5 0
-#define MX6UL_PAD_JTAG_MOD__SDMA_EXT_EVENT00 0x0044 0x02d0 0x0000 6 0
+#define MX6UL_PAD_JTAG_MOD__SDMA_EXT_EVENT00 0x0044 0x02d0 0x0610 6 0
#define MX6UL_PAD_JTAG_TMS__SJC_TMS 0x0048 0x02d4 0x0000 0 0
#define MX6UL_PAD_JTAG_TMS__GPT2_CAPTURE1 0x0048 0x02d4 0x0598 1 0
-#define MX6UL_PAD_JTAG_TMS__SAI2_MCLK 0x0048 0x02d4 0x0000 2 0
+#define MX6UL_PAD_JTAG_TMS__SAI2_MCLK 0x0048 0x02d4 0x05f0 2 0
#define MX6UL_PAD_JTAG_TMS__CCM_CLKO1 0x0048 0x02d4 0x0000 3 0
#define MX6UL_PAD_JTAG_TMS__CCM_WAIT 0x0048 0x02d4 0x0000 4 0
#define MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x0048 0x02d4 0x0000 5 0
-#define MX6UL_PAD_JTAG_TMS__SDMA_EXT_EVENT01 0x0048 0x02d4 0x0000 6 0
+#define MX6UL_PAD_JTAG_TMS__SDMA_EXT_EVENT01 0x0048 0x02d4 0x0614 6 0
#define MX6UL_PAD_JTAG_TMS__EPIT1_OUT 0x0048 0x02d4 0x0000 8 0
#define MX6UL_PAD_JTAG_TDO__SJC_TDO 0x004c 0x02d8 0x0000 0 0
#define MX6UL_PAD_JTAG_TDO__GPT2_CAPTURE2 0x004c 0x02d8 0x059c 1 0
@@ -63,12 +63,14 @@
#define MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA 0x0054 0x02e0 0x05f4 2 0
#define MX6UL_PAD_JTAG_TCK__PWM7_OUT 0x0054 0x02e0 0x0000 4 0
#define MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x0054 0x02e0 0x0000 5 0
+#define MX6UL_PAD_JTAG_TCK__REF_CLK_32K 0x0054 0x02e0 0x0000 6 0
#define MX6UL_PAD_JTAG_TCK__SIM2_POWER_FAIL 0x0054 0x02e0 0x0000 8 0
#define MX6UL_PAD_JTAG_TRST_B__SJC_TRSTB 0x0058 0x02e4 0x0000 0 0
#define MX6UL_PAD_JTAG_TRST_B__GPT2_COMPARE3 0x0058 0x02e4 0x0000 1 0
#define MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x0058 0x02e4 0x0000 2 0
#define MX6UL_PAD_JTAG_TRST_B__PWM8_OUT 0x0058 0x02e4 0x0000 4 0
#define MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x0058 0x02e4 0x0000 5 0
+#define MX6UL_PAD_JTAG_TRST_B__REF_CLK_24M 0x0058 0x02e4 0x0000 6 0
#define MX6UL_PAD_JTAG_TRST_B__CAAM_RNG_OSC_OBS 0x0058 0x02e4 0x0000 8 0
#define MX6UL_PAD_GPIO1_IO00__I2C2_SCL 0x005c 0x02e8 0x05ac 0 1
#define MX6UL_PAD_GPIO1_IO00__GPT1_CAPTURE1 0x005c 0x02e8 0x058c 1 0
@@ -94,22 +96,24 @@
#define MX6UL_PAD_GPIO1_IO02__ENET1_REF_CLK_25M 0x0064 0x02f0 0x0000 3 0
#define MX6UL_PAD_GPIO1_IO02__USDHC1_WP 0x0064 0x02f0 0x066c 4 0
#define MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x0064 0x02f0 0x0000 5 0
-#define MX6UL_PAD_GPIO1_IO02__SDMA_EXT_EVENT00 0x0064 0x02f0 0x0000 6 0
+#define MX6UL_PAD_GPIO1_IO02__SDMA_EXT_EVENT00 0x0064 0x02f0 0x0610 6 1
#define MX6UL_PAD_GPIO1_IO02__SRC_ANY_PU_RESET 0x0064 0x02f0 0x0000 7 0
#define MX6UL_PAD_GPIO1_IO02__UART1_DCE_TX 0x0064 0x02f0 0x0000 8 0
#define MX6UL_PAD_GPIO1_IO02__UART1_DTE_RX 0x0064 0x02f0 0x0624 8 0
#define MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x0068 0x02f4 0x05a8 0 1
#define MX6UL_PAD_GPIO1_IO03__GPT1_COMPARE3 0x0068 0x02f4 0x0000 1 0
#define MX6UL_PAD_GPIO1_IO03__USB_OTG2_OC 0x0068 0x02f4 0x0660 2 0
+#define MX6UL_PAD_GPIO1_IO03__REF_CLK_32K 0x0068 0x02f4 0x0000 3 0
#define MX6UL_PAD_GPIO1_IO03__USDHC1_CD_B 0x0068 0x02f4 0x0668 4 0
#define MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x0068 0x02f4 0x0000 5 0
-#define MX6UL_PAD_GPIO1_IO03__CCM_DI0_eXT_CLK 0x0068 0x02f4 0x0000 6 0
+#define MX6UL_PAD_GPIO1_IO03__CCM_DI0_EXT_CLK 0x0068 0x02f4 0x0000 6 0
#define MX6UL_PAD_GPIO1_IO03__SRC_TESTER_ACK 0x0068 0x02f4 0x0000 7 0
-#define MX6UL_PAD_GPIO1_IO03__UART1_DTE_TX 0x0068 0x02f4 0x0000 8 0
#define MX6UL_PAD_GPIO1_IO03__UART1_DCE_RX 0x0068 0x02f4 0x0624 8 1
+#define MX6UL_PAD_GPIO1_IO03__UART1_DTE_TX 0x0068 0x02f4 0x0000 8 0
#define MX6UL_PAD_GPIO1_IO04__ENET1_REF_CLK1 0x006c 0x02f8 0x0574 0 1
#define MX6UL_PAD_GPIO1_IO04__PWM3_OUT 0x006c 0x02f8 0x0000 1 0
#define MX6UL_PAD_GPIO1_IO04__USB_OTG1_PWR 0x006c 0x02f8 0x0000 2 0
+#define MX6UL_PAD_GPIO1_IO04__REF_CLK_24M 0x006c 0x02f8 0x0000 3 0
#define MX6UL_PAD_GPIO1_IO04__USDHC1_RESET_B 0x006c 0x02f8 0x0000 4 0
#define MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x006c 0x02f8 0x0000 5 0
#define MX6UL_PAD_GPIO1_IO04__ENET2_1588_EVENT0_IN 0x006c 0x02f8 0x0000 6 0
@@ -200,7 +204,7 @@
#define MX6UL_PAD_UART2_TX_DATA__CSI_DATA06 0x0094 0x0320 0x04dc 3 0
#define MX6UL_PAD_UART2_TX_DATA__GPT1_CAPTURE1 0x0094 0x0320 0x058c 4 1
#define MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20 0x0094 0x0320 0x0000 5 0
-#define MX6UL_PAD_UART2_TX_DATA__ECSPI3_SS0 0x0094 0x0320 0x0000 8 0
+#define MX6UL_PAD_UART2_TX_DATA__ECSPI3_SS0 0x0094 0x0320 0x0560 8 0
#define MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x0098 0x0324 0x062c 0 1
#define MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX 0x0098 0x0324 0x0000 0 0
#define MX6UL_PAD_UART2_RX_DATA__ENET1_TDATA03 0x0098 0x0324 0x0000 1 0
@@ -232,7 +236,7 @@
#define MX6UL_PAD_UART3_TX_DATA__UART3_DTE_RX 0x00a4 0x0330 0x0634 0 0
#define MX6UL_PAD_UART3_TX_DATA__ENET2_RDATA02 0x00a4 0x0330 0x0000 1 0
#define MX6UL_PAD_UART3_TX_DATA__SIM1_PORT0_PD 0x00a4 0x0330 0x0000 2 0
-#define MX6UL_PAD_UART3_TX_DATA__CSI_DATA01 0x00a4 0x0330 0x0000 3 0
+#define MX6UL_PAD_UART3_TX_DATA__CSI_DATA01 0x00a4 0x0330 0x04d4 3 0
#define MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS 0x00a4 0x0330 0x0000 4 0
#define MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS 0x00a4 0x0330 0x0628 4 2
#define MX6UL_PAD_UART3_TX_DATA__GPIO1_IO24 0x00a4 0x0330 0x0000 5 0
@@ -242,7 +246,7 @@
#define MX6UL_PAD_UART3_RX_DATA__UART3_DTE_TX 0x00a8 0x0334 0x0000 0 0
#define MX6UL_PAD_UART3_RX_DATA__ENET2_RDATA03 0x00a8 0x0334 0x0000 1 0
#define MX6UL_PAD_UART3_RX_DATA__SIM2_PORT0_PD 0x00a8 0x0334 0x0000 2 0
-#define MX6UL_PAD_UART3_RX_DATA__CSI_DATA00 0x00a8 0x0334 0x0000 3 0
+#define MX6UL_PAD_UART3_RX_DATA__CSI_DATA00 0x00a8 0x0334 0x04d0 3 0
#define MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS 0x00a8 0x0334 0x0628 4 3
#define MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS 0x00a8 0x0334 0x0000 4 0
#define MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25 0x00a8 0x0334 0x0000 5 0
@@ -251,7 +255,7 @@
#define MX6UL_PAD_UART3_CTS_B__UART3_DTE_RTS 0x00ac 0x0338 0x0630 0 0
#define MX6UL_PAD_UART3_CTS_B__ENET2_RX_CLK 0x00ac 0x0338 0x0000 1 0
#define MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x00ac 0x0338 0x0000 2 0
-#define MX6UL_PAD_UART3_CTS_B__CSI_DATA10 0x00ac 0x0338 0x0000 3 0
+#define MX6UL_PAD_UART3_CTS_B__CSI_DATA10 0x00ac 0x0338 0x04ec 3 0
#define MX6UL_PAD_UART3_CTS_B__ENET1_1588_EVENT1_IN 0x00ac 0x0338 0x0000 4 0
#define MX6UL_PAD_UART3_CTS_B__GPIO1_IO26 0x00ac 0x0338 0x0000 5 0
#define MX6UL_PAD_UART3_CTS_B__EPIT2_OUT 0x00ac 0x0338 0x0000 8 0
@@ -259,7 +263,7 @@
#define MX6UL_PAD_UART3_RTS_B__UART3_DTE_CTS 0x00b0 0x033c 0x0000 0 0
#define MX6UL_PAD_UART3_RTS_B__ENET2_TX_ER 0x00b0 0x033c 0x0000 1 0
#define MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x00b0 0x033c 0x0584 2 0
-#define MX6UL_PAD_UART3_RTS_B__CSI_DATA11 0x00b0 0x033c 0x0000 3 0
+#define MX6UL_PAD_UART3_RTS_B__CSI_DATA11 0x00b0 0x033c 0x04f0 3 0
#define MX6UL_PAD_UART3_RTS_B__ENET1_1588_EVENT1_OUT 0x00b0 0x033c 0x0000 4 0
#define MX6UL_PAD_UART3_RTS_B__GPIO1_IO27 0x00b0 0x033c 0x0000 5 0
#define MX6UL_PAD_UART3_RTS_B__WDOG1_WDOG_B 0x00b0 0x033c 0x0000 8 0
@@ -267,7 +271,7 @@
#define MX6UL_PAD_UART4_TX_DATA__UART4_DTE_RX 0x00b4 0x0340 0x063c 0 0
#define MX6UL_PAD_UART4_TX_DATA__ENET2_TDATA02 0x00b4 0x0340 0x0000 1 0
#define MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x00b4 0x0340 0x05a4 2 1
-#define MX6UL_PAD_UART4_TX_DATA__CSI_DATA12 0x00b4 0x0340 0x0000 3 0
+#define MX6UL_PAD_UART4_TX_DATA__CSI_DATA12 0x00b4 0x0340 0x04f4 3 0
#define MX6UL_PAD_UART4_TX_DATA__CSU_CSU_ALARM_AUT02 0x00b4 0x0340 0x0000 4 0
#define MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28 0x00b4 0x0340 0x0000 5 0
#define MX6UL_PAD_UART4_TX_DATA__ECSPI2_SCLK 0x00b4 0x0340 0x0544 8 1
@@ -275,23 +279,23 @@
#define MX6UL_PAD_UART4_RX_DATA__UART4_DTE_TX 0x00b8 0x0344 0x0000 0 0
#define MX6UL_PAD_UART4_RX_DATA__ENET2_TDATA03 0x00b8 0x0344 0x0000 1 0
#define MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x00b8 0x0344 0x05a8 2 2
-#define MX6UL_PAD_UART4_RX_DATA__CSI_DATA13 0x00b8 0x0344 0x0000 3 0
+#define MX6UL_PAD_UART4_RX_DATA__CSI_DATA13 0x00b8 0x0344 0x04f8 3 0
#define MX6UL_PAD_UART4_RX_DATA__CSU_CSU_ALARM_AUT01 0x00b8 0x0344 0x0000 4 0
#define MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29 0x00b8 0x0344 0x0000 5 0
-#define MX6UL_PAD_UART4_RX_DATA__ECSPI2_SS0 0x00b8 0x0344 0x0000 8 0
+#define MX6UL_PAD_UART4_RX_DATA__ECSPI2_SS0 0x00b8 0x0344 0x0550 8 1
#define MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x00bc 0x0348 0x0000 5 0
#define MX6UL_PAD_UART5_TX_DATA__ECSPI2_MOSI 0x00bc 0x0348 0x054c 8 0
#define MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x00bc 0x0348 0x0000 0 0
#define MX6UL_PAD_UART5_TX_DATA__UART5_DTE_RX 0x00bc 0x0348 0x0644 0 4
#define MX6UL_PAD_UART5_TX_DATA__ENET2_CRS 0x00bc 0x0348 0x0000 1 0
#define MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x00bc 0x0348 0x05ac 2 2
-#define MX6UL_PAD_UART5_TX_DATA__CSI_DATA14 0x00bc 0x0348 0x0000 3 0
+#define MX6UL_PAD_UART5_TX_DATA__CSI_DATA14 0x00bc 0x0348 0x04fc 3 0
#define MX6UL_PAD_UART5_TX_DATA__CSU_CSU_ALARM_AUT00 0x00bc 0x0348 0x0000 4 0
#define MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x00c0 0x034c 0x0644 0 5
#define MX6UL_PAD_UART5_RX_DATA__UART5_DTE_TX 0x00c0 0x034c 0x0000 0 0
#define MX6UL_PAD_UART5_RX_DATA__ENET2_COL 0x00c0 0x034c 0x0000 1 0
#define MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x00c0 0x034c 0x05b0 2 2
-#define MX6UL_PAD_UART5_RX_DATA__CSI_DATA15 0x00c0 0x034c 0x0000 3 0
+#define MX6UL_PAD_UART5_RX_DATA__CSI_DATA15 0x00c0 0x034c 0x0500 3 0
#define MX6UL_PAD_UART5_RX_DATA__CSU_CSU_INT_DEB 0x00c0 0x034c 0x0000 4 0
#define MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31 0x00c0 0x034c 0x0000 5 0
#define MX6UL_PAD_UART5_RX_DATA__ECSPI2_MISO 0x00c0 0x034c 0x0548 8 1
@@ -299,59 +303,61 @@
#define MX6UL_PAD_ENET1_RX_DATA0__UART4_DCE_RTS 0x00c4 0x0350 0x0638 1 0
#define MX6UL_PAD_ENET1_RX_DATA0__UART4_DTE_CTS 0x00c4 0x0350 0x0000 1 0
#define MX6UL_PAD_ENET1_RX_DATA0__PWM1_OUT 0x00c4 0x0350 0x0000 2 0
-#define MX6UL_PAD_ENET1_RX_DATA0__CSI_DATA16 0x00c4 0x0350 0x0000 3 0
+#define MX6UL_PAD_ENET1_RX_DATA0__CSI_DATA16 0x00c4 0x0350 0x0504 3 0
#define MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX 0x00c4 0x0350 0x0000 4 0
#define MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00 0x00c4 0x0350 0x0000 5 0
-#define MX6UL_PAD_ENET1_RX_DATA0__KPP_ROW00 0x00c4 0x0350 0x0000 6 0
+#define MX6UL_PAD_ENET1_RX_DATA0__KPP_ROW00 0x00c4 0x0350 0x05d0 6 0
#define MX6UL_PAD_ENET1_RX_DATA0__USDHC1_LCTL 0x00c4 0x0350 0x0000 8 0
#define MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x00c8 0x0354 0x0000 0 0
#define MX6UL_PAD_ENET1_RX_DATA1__UART4_DCE_CTS 0x00c8 0x0354 0x0000 1 0
#define MX6UL_PAD_ENET1_RX_DATA1__UART4_DTE_RTS 0x00c8 0x0354 0x0638 1 1
#define MX6UL_PAD_ENET1_RX_DATA1__PWM2_OUT 0x00c8 0x0354 0x0000 2 0
-#define MX6UL_PAD_ENET1_RX_DATA1__CSI_DATA17 0x00c8 0x0354 0x0000 3 0
+#define MX6UL_PAD_ENET1_RX_DATA1__CSI_DATA17 0x00c8 0x0354 0x0508 3 0
#define MX6UL_PAD_ENET1_RX_DATA1__FLEXCAN1_RX 0x00c8 0x0354 0x0584 4 1
#define MX6UL_PAD_ENET1_RX_DATA1__GPIO2_IO01 0x00c8 0x0354 0x0000 5 0
-#define MX6UL_PAD_ENET1_RX_DATA1__KPP_COL00 0x00c8 0x0354 0x0000 6 0
+#define MX6UL_PAD_ENET1_RX_DATA1__KPP_COL00 0x00c8 0x0354 0x05c4 6 0
#define MX6UL_PAD_ENET1_RX_DATA1__USDHC2_LCTL 0x00c8 0x0354 0x0000 8 0
#define MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x00cc 0x0358 0x0000 0 0
#define MX6UL_PAD_ENET1_RX_EN__UART5_DCE_RTS 0x00cc 0x0358 0x0640 1 3
#define MX6UL_PAD_ENET1_RX_EN__UART5_DTE_CTS 0x00cc 0x0358 0x0000 1 0
-#define MX6UL_PAD_ENET1_RX_EN__CSI_DATA18 0x00cc 0x0358 0x0000 3 0
+#define MX6UL_PAD_ENET1_RX_EN__REF_CLK_32K 0x00cc 0x0358 0x0000 2 0
+#define MX6UL_PAD_ENET1_RX_EN__CSI_DATA18 0x00cc 0x0358 0x050c 3 0
#define MX6UL_PAD_ENET1_RX_EN__FLEXCAN2_TX 0x00cc 0x0358 0x0000 4 0
#define MX6UL_PAD_ENET1_RX_EN__GPIO2_IO02 0x00cc 0x0358 0x0000 5 0
-#define MX6UL_PAD_ENET1_RX_EN__KPP_ROW01 0x00cc 0x0358 0x0000 6 0
+#define MX6UL_PAD_ENET1_RX_EN__KPP_ROW01 0x00cc 0x0358 0x05d4 6 0
#define MX6UL_PAD_ENET1_RX_EN__USDHC1_VSELECT 0x00cc 0x0358 0x0000 8 0
#define MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x00d0 0x035c 0x0000 0 0
#define MX6UL_PAD_ENET1_TX_DATA0__UART5_DCE_CTS 0x00d0 0x035c 0x0000 1 0
#define MX6UL_PAD_ENET1_TX_DATA0__UART5_DTE_RTS 0x00d0 0x035c 0x0640 1 4
-#define MX6UL_PAD_ENET1_TX_DATA0__CSI_DATA19 0x00d0 0x035c 0x0000 3 0
+#define MX6UL_PAD_ENET1_TX_DATA0__REF_CLK_24M 0x00d0 0x035c 0x0000 2 0
+#define MX6UL_PAD_ENET1_TX_DATA0__CSI_DATA19 0x00d0 0x035c 0x0510 3 0
#define MX6UL_PAD_ENET1_TX_DATA0__FLEXCAN2_RX 0x00d0 0x035c 0x0588 4 1
#define MX6UL_PAD_ENET1_TX_DATA0__GPIO2_IO03 0x00d0 0x035c 0x0000 5 0
-#define MX6UL_PAD_ENET1_TX_DATA0__KPP_COL01 0x00d0 0x035c 0x0000 6 0
+#define MX6UL_PAD_ENET1_TX_DATA0__KPP_COL01 0x00d0 0x035c 0x05c8 6 0
#define MX6UL_PAD_ENET1_TX_DATA0__USDHC2_VSELECT 0x00d0 0x035c 0x0000 8 0
#define MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x00d4 0x0360 0x0000 0 0
#define MX6UL_PAD_ENET1_TX_DATA1__UART6_DCE_CTS 0x00d4 0x0360 0x0000 1 0
#define MX6UL_PAD_ENET1_TX_DATA1__UART6_DTE_RTS 0x00d4 0x0360 0x0648 1 2
#define MX6UL_PAD_ENET1_TX_DATA1__PWM5_OUT 0x00d4 0x0360 0x0000 2 0
-#define MX6UL_PAD_ENET1_TX_DATA1__CSI_DATA20 0x00d4 0x0360 0x0000 3 0
+#define MX6UL_PAD_ENET1_TX_DATA1__CSI_DATA20 0x00d4 0x0360 0x0514 3 0
#define MX6UL_PAD_ENET1_TX_DATA1__ENET2_MDIO 0x00d4 0x0360 0x0580 4 1
#define MX6UL_PAD_ENET1_TX_DATA1__GPIO2_IO04 0x00d4 0x0360 0x0000 5 0
-#define MX6UL_PAD_ENET1_TX_DATA1__KPP_ROW02 0x00d4 0x0360 0x0000 6 0
+#define MX6UL_PAD_ENET1_TX_DATA1__KPP_ROW02 0x00d4 0x0360 0x05d8 6 0
#define MX6UL_PAD_ENET1_TX_DATA1__WDOG1_WDOG_RST_B_DEB 0x00d4 0x0360 0x0000 8 0
#define MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x00d8 0x0364 0x0000 0 0
#define MX6UL_PAD_ENET1_TX_EN__UART6_DCE_RTS 0x00d8 0x0364 0x0648 1 3
#define MX6UL_PAD_ENET1_TX_EN__UART6_DTE_CTS 0x00d8 0x0364 0x0000 1 0
#define MX6UL_PAD_ENET1_TX_EN__PWM6_OUT 0x00d8 0x0364 0x0000 2 0
-#define MX6UL_PAD_ENET1_TX_EN__CSI_DATA21 0x00d8 0x0364 0x0000 3 0
+#define MX6UL_PAD_ENET1_TX_EN__CSI_DATA21 0x00d8 0x0364 0x0518 3 0
#define MX6UL_PAD_ENET1_TX_EN__ENET2_MDC 0x00d8 0x0364 0x0000 4 0
#define MX6UL_PAD_ENET1_TX_EN__GPIO2_IO05 0x00d8 0x0364 0x0000 5 0
-#define MX6UL_PAD_ENET1_TX_EN__KPP_COL02 0x00d8 0x0364 0x0000 6 0
+#define MX6UL_PAD_ENET1_TX_EN__KPP_COL02 0x00d8 0x0364 0x05cc 6 0
#define MX6UL_PAD_ENET1_TX_EN__WDOG2_WDOG_RST_B_DEB 0x00d8 0x0364 0x0000 8 0
#define MX6UL_PAD_ENET1_TX_CLK__ENET1_TX_CLK 0x00dc 0x0368 0x0000 0 0
#define MX6UL_PAD_ENET1_TX_CLK__UART7_DCE_CTS 0x00dc 0x0368 0x0000 1 0
#define MX6UL_PAD_ENET1_TX_CLK__UART7_DTE_RTS 0x00dc 0x0368 0x0650 1 0
#define MX6UL_PAD_ENET1_TX_CLK__PWM7_OUT 0x00dc 0x0368 0x0000 2 0
-#define MX6UL_PAD_ENET1_TX_CLK__CSI_DATA22 0x00dc 0x0368 0x0000 3 0
+#define MX6UL_PAD_ENET1_TX_CLK__CSI_DATA22 0x00dc 0x0368 0x051c 3 0
#define MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x00dc 0x0368 0x0574 4 2
#define MX6UL_PAD_ENET1_TX_CLK__GPIO2_IO06 0x00dc 0x0368 0x0000 5 0
#define MX6UL_PAD_ENET1_TX_CLK__KPP_ROW03 0x00dc 0x0368 0x0000 6 0
@@ -360,7 +366,7 @@
#define MX6UL_PAD_ENET1_RX_ER__UART7_DCE_RTS 0x00e0 0x036c 0x0650 1 1
#define MX6UL_PAD_ENET1_RX_ER__UART7_DTE_CTS 0x00e0 0x036c 0x0000 1 0
#define MX6UL_PAD_ENET1_RX_ER__PWM8_OUT 0x00e0 0x036c 0x0000 2 0
-#define MX6UL_PAD_ENET1_RX_ER__CSI_DATA23 0x00e0 0x036c 0x0000 3 0
+#define MX6UL_PAD_ENET1_RX_ER__CSI_DATA23 0x00e0 0x036c 0x0520 3 0
#define MX6UL_PAD_ENET1_RX_ER__EIM_CRE 0x00e0 0x036c 0x0000 4 0
#define MX6UL_PAD_ENET1_RX_ER__GPIO2_IO07 0x00e0 0x036c 0x0000 5 0
#define MX6UL_PAD_ENET1_RX_ER__KPP_COL03 0x00e0 0x036c 0x0000 6 0
@@ -377,7 +383,7 @@
#define MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x00e8 0x0374 0x0000 0 0
#define MX6UL_PAD_ENET2_RX_DATA1__UART6_DCE_RX 0x00e8 0x0374 0x064c 1 2
#define MX6UL_PAD_ENET2_RX_DATA1__UART6_DTE_TX 0x00e8 0x0374 0x0000 1 0
-#define MX6UL_PAD_ENET2_RX_DATA1__SIM1_PORT0_cLK 0x00e8 0x0374 0x0000 2 0
+#define MX6UL_PAD_ENET2_RX_DATA1__SIM1_PORT0_CLK 0x00e8 0x0374 0x0000 2 0
#define MX6UL_PAD_ENET2_RX_DATA1__I2C3_SDA 0x00e8 0x0374 0x05b8 3 1
#define MX6UL_PAD_ENET2_RX_DATA1__ENET1_MDC 0x00e8 0x0374 0x0000 4 0
#define MX6UL_PAD_ENET2_RX_DATA1__GPIO2_IO09 0x00e8 0x0374 0x0000 5 0
@@ -400,6 +406,7 @@
#define MX6UL_PAD_ENET2_TX_DATA0__EIM_EB_B02 0x00f0 0x037c 0x0000 4 0
#define MX6UL_PAD_ENET2_TX_DATA0__GPIO2_IO11 0x00f0 0x037c 0x0000 5 0
#define MX6UL_PAD_ENET2_TX_DATA0__KPP_COL05 0x00f0 0x037c 0x0000 6 0
+#define MX6UL_PAD_ENET2_TX_DATA0__REF_CLK_24M 0x00f0 0x037c 0x0000 8 0
#define MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x00f4 0x0380 0x0000 0 0
#define MX6UL_PAD_ENET2_TX_DATA1__UART8_DCE_TX 0x00f4 0x0380 0x0000 1 0
#define MX6UL_PAD_ENET2_TX_DATA1__UART8_DTE_RX 0x00f4 0x0380 0x065c 1 0
@@ -412,7 +419,7 @@
#define MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x00f8 0x0384 0x0000 0 0
#define MX6UL_PAD_ENET2_TX_EN__UART8_DCE_RX 0x00f8 0x0384 0x065c 1 1
#define MX6UL_PAD_ENET2_TX_EN__UART8_DTE_TX 0x00f8 0x0384 0x0000 1 0
-#define MX6UL_PAD_ENET2_TX_EN__SIM2_PORT0_cLK 0x00f8 0x0384 0x0000 2 0
+#define MX6UL_PAD_ENET2_TX_EN__SIM2_PORT0_CLK 0x00f8 0x0384 0x0000 2 0
#define MX6UL_PAD_ENET2_TX_EN__ECSPI4_MOSI 0x00f8 0x0384 0x056c 3 0
#define MX6UL_PAD_ENET2_TX_EN__EIM_ACLK_FREERUN 0x00f8 0x0384 0x0000 4 0
#define MX6UL_PAD_ENET2_TX_EN__GPIO2_IO13 0x00f8 0x0384 0x0000 5 0
@@ -431,7 +438,7 @@
#define MX6UL_PAD_ENET2_RX_ER__UART8_DCE_RTS 0x0100 0x038c 0x0658 1 1
#define MX6UL_PAD_ENET2_RX_ER__UART8_DTE_CTS 0x0100 0x038c 0x0000 1 0
#define MX6UL_PAD_ENET2_RX_ER__SIM2_PORT0_SVEN 0x0100 0x038c 0x0000 2 0
-#define MX6UL_PAD_ENET2_RX_ER__ECSPI4_SS0 0x0100 0x038c 0x0000 3 0
+#define MX6UL_PAD_ENET2_RX_ER__ECSPI4_SS0 0x0100 0x038c 0x0570 3 0
#define MX6UL_PAD_ENET2_RX_ER__EIM_ADDR25 0x0100 0x038c 0x0000 4 0
#define MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15 0x0100 0x038c 0x0000 5 0
#define MX6UL_PAD_ENET2_RX_ER__KPP_COL07 0x0100 0x038c 0x0000 6 0
@@ -440,7 +447,7 @@
#define MX6UL_PAD_LCD_CLK__LCDIF_WR_RWN 0x0104 0x0390 0x0000 1 0
#define MX6UL_PAD_LCD_CLK__UART4_DCE_TX 0x0104 0x0390 0x0000 2 0
#define MX6UL_PAD_LCD_CLK__UART4_DTE_RX 0x0104 0x0390 0x063c 2 2
-#define MX6UL_PAD_LCD_CLK__SAI3_MCLK 0x0104 0x0390 0x0000 3 0
+#define MX6UL_PAD_LCD_CLK__SAI3_MCLK 0x0104 0x0390 0x0600 3 0
#define MX6UL_PAD_LCD_CLK__EIM_CS2_B 0x0104 0x0390 0x0000 4 0
#define MX6UL_PAD_LCD_CLK__GPIO3_IO00 0x0104 0x0390 0x0000 5 0
#define MX6UL_PAD_LCD_CLK__WDOG1_WDOG_RST_B_DEB 0x0104 0x0390 0x0000 8 0
@@ -464,7 +471,7 @@
#define MX6UL_PAD_LCD_VSYNC__LCDIF_BUSY 0x0110 0x039c 0x05dc 1 1
#define MX6UL_PAD_LCD_VSYNC__UART4_DCE_RTS 0x0110 0x039c 0x0638 2 3
#define MX6UL_PAD_LCD_VSYNC__UART4_DTE_CTS 0x0110 0x039c 0x0000 2 0
-#define MX6UL_PAD_LCD_VSYNC__SAI3_RX_DATA 0x0110 0x039c 0x0000 3 0
+#define MX6UL_PAD_LCD_VSYNC__SAI3_RX_DATA 0x0110 0x039c 0x0604 3 0
#define MX6UL_PAD_LCD_VSYNC__WDOG2_WDOG_B 0x0110 0x039c 0x0000 4 0
#define MX6UL_PAD_LCD_VSYNC__GPIO3_IO03 0x0110 0x039c 0x0000 5 0
#define MX6UL_PAD_LCD_VSYNC__ECSPI2_SS2 0x0110 0x039c 0x0000 8 0
@@ -477,13 +484,15 @@
#define MX6UL_PAD_LCD_RESET__ECSPI2_SS3 0x0114 0x03a0 0x0000 8 0
#define MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x0118 0x03a4 0x0000 0 0
#define MX6UL_PAD_LCD_DATA00__PWM1_OUT 0x0118 0x03a4 0x0000 1 0
+#define MX6UL_PAD_LCD_DATA00__CA7_MX6UL_TRACE0 0x0118 0x03a4 0x0000 2 0
#define MX6UL_PAD_LCD_DATA00__ENET1_1588_EVENT2_IN 0x0118 0x03a4 0x0000 3 0
#define MX6UL_PAD_LCD_DATA00__I2C3_SDA 0x0118 0x03a4 0x05b8 4 2
#define MX6UL_PAD_LCD_DATA00__GPIO3_IO05 0x0118 0x03a4 0x0000 5 0
#define MX6UL_PAD_LCD_DATA00__SRC_BT_CFG00 0x0118 0x03a4 0x0000 6 0
-#define MX6UL_PAD_LCD_DATA00__SAI1_MCLK 0x0118 0x03a4 0x0000 8 0
+#define MX6UL_PAD_LCD_DATA00__SAI1_MCLK 0x0118 0x03a4 0x05e0 8 1
#define MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x011c 0x03a8 0x0000 0 0
#define MX6UL_PAD_LCD_DATA01__PWM2_OUT 0x011c 0x03a8 0x0000 1 0
+#define MX6UL_PAD_LCD_DATA01__CA7_MX6UL_TRACE1 0x011c 0x03a8 0x0000 2 0
#define MX6UL_PAD_LCD_DATA01__ENET1_1588_EVENT2_OUT 0x011c 0x03a8 0x0000 3 0
#define MX6UL_PAD_LCD_DATA01__I2C3_SCL 0x011c 0x03a8 0x05b4 4 2
#define MX6UL_PAD_LCD_DATA01__GPIO3_IO06 0x011c 0x03a8 0x0000 5 0
@@ -491,6 +500,7 @@
#define MX6UL_PAD_LCD_DATA01__SAI1_TX_SYNC 0x011c 0x03a8 0x05ec 8 0
#define MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x0120 0x03ac 0x0000 0 0
#define MX6UL_PAD_LCD_DATA02__PWM3_OUT 0x0120 0x03ac 0x0000 1 0
+#define MX6UL_PAD_LCD_DATA02__CA7_MX6UL_TRACE2 0x0120 0x03ac 0x0000 2 0
#define MX6UL_PAD_LCD_DATA02__ENET1_1588_EVENT3_IN 0x0120 0x03ac 0x0000 3 0
#define MX6UL_PAD_LCD_DATA02__I2C4_SDA 0x0120 0x03ac 0x05c0 4 2
#define MX6UL_PAD_LCD_DATA02__GPIO3_IO07 0x0120 0x03ac 0x0000 5 0
@@ -498,14 +508,16 @@
#define MX6UL_PAD_LCD_DATA02__SAI1_TX_BCLK 0x0120 0x03ac 0x05e8 8 0
#define MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x0124 0x03b0 0x0000 0 0
#define MX6UL_PAD_LCD_DATA03__PWM4_OUT 0x0124 0x03b0 0x0000 1 0
+#define MX6UL_PAD_LCD_DATA03__CA7_MX6UL_TRACE3 0x0124 0x03b0 0x0000 2 0
#define MX6UL_PAD_LCD_DATA03__ENET1_1588_EVENT3_OUT 0x0124 0x03b0 0x0000 3 0
#define MX6UL_PAD_LCD_DATA03__I2C4_SCL 0x0124 0x03b0 0x05bc 4 2
#define MX6UL_PAD_LCD_DATA03__GPIO3_IO08 0x0124 0x03b0 0x0000 5 0
#define MX6UL_PAD_LCD_DATA03__SRC_BT_CFG03 0x0124 0x03b0 0x0000 6 0
-#define MX6UL_PAD_LCD_DATA03__SAI1_RX_DATA 0x0124 0x03b0 0x0000 8 0
+#define MX6UL_PAD_LCD_DATA03__SAI1_RX_DATA 0x0124 0x03b0 0x05e4 8 0
#define MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x0128 0x03b4 0x0000 0 0
#define MX6UL_PAD_LCD_DATA04__UART8_DCE_CTS 0x0128 0x03b4 0x0000 1 0
#define MX6UL_PAD_LCD_DATA04__UART8_DTE_RTS 0x0128 0x03b4 0x0658 1 2
+#define MX6UL_PAD_LCD_DATA04__CA7_MX6UL_TRACE4 0x0128 0x03b4 0x0000 2 0
#define MX6UL_PAD_LCD_DATA04__ENET2_1588_EVENT2_IN 0x0128 0x03b4 0x0000 3 0
#define MX6UL_PAD_LCD_DATA04__SPDIF_SR_CLK 0x0128 0x03b4 0x0000 4 0
#define MX6UL_PAD_LCD_DATA04__GPIO3_IO09 0x0128 0x03b4 0x0000 5 0
@@ -514,6 +526,7 @@
#define MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x012c 0x03b8 0x0000 0 0
#define MX6UL_PAD_LCD_DATA05__UART8_DCE_RTS 0x012c 0x03b8 0x0658 1 3
#define MX6UL_PAD_LCD_DATA05__UART8_DTE_CTS 0x012c 0x03b8 0x0000 1 0
+#define MX6UL_PAD_LCD_DATA05__CA7_MX6UL_TRACE5 0x012c 0x03b8 0x0000 2 0
#define MX6UL_PAD_LCD_DATA05__ENET2_1588_EVENT2_OUT 0x012c 0x03b8 0x0000 3 0
#define MX6UL_PAD_LCD_DATA05__SPDIF_OUT 0x012c 0x03b8 0x0000 4 0
#define MX6UL_PAD_LCD_DATA05__GPIO3_IO10 0x012c 0x03b8 0x0000 5 0
@@ -522,6 +535,7 @@
#define MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x0130 0x03bc 0x0000 0 0
#define MX6UL_PAD_LCD_DATA06__UART7_DCE_CTS 0x0130 0x03bc 0x0000 1 0
#define MX6UL_PAD_LCD_DATA06__UART7_DTE_RTS 0x0130 0x03bc 0x0650 1 2
+#define MX6UL_PAD_LCD_DATA06__CA7_MX6UL_TRACE6 0x0130 0x03bc 0x0000 2 0
#define MX6UL_PAD_LCD_DATA06__ENET2_1588_EVENT3_IN 0x0130 0x03bc 0x0000 3 0
#define MX6UL_PAD_LCD_DATA06__SPDIF_LOCK 0x0130 0x03bc 0x0000 4 0
#define MX6UL_PAD_LCD_DATA06__GPIO3_IO11 0x0130 0x03bc 0x0000 5 0
@@ -530,6 +544,7 @@
#define MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x0134 0x03c0 0x0000 0 0
#define MX6UL_PAD_LCD_DATA07__UART7_DCE_RTS 0x0134 0x03c0 0x0650 1 3
#define MX6UL_PAD_LCD_DATA07__UART7_DTE_CTS 0x0134 0x03c0 0x0000 1 0
+#define MX6UL_PAD_LCD_DATA07__CA7_MX6UL_TRACE7 0x0134 0x03c0 0x0000 2 0
#define MX6UL_PAD_LCD_DATA07__ENET2_1588_EVENT3_OUT 0x0134 0x03c0 0x0000 3 0
#define MX6UL_PAD_LCD_DATA07__SPDIF_EXT_CLK 0x0134 0x03c0 0x061c 4 0
#define MX6UL_PAD_LCD_DATA07__GPIO3_IO12 0x0134 0x03c0 0x0000 5 0
@@ -537,56 +552,64 @@
#define MX6UL_PAD_LCD_DATA07__ECSPI1_SS3 0x0134 0x03c0 0x0000 8 0
#define MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x0138 0x03c4 0x0000 0 0
#define MX6UL_PAD_LCD_DATA08__SPDIF_IN 0x0138 0x03c4 0x0618 1 2
-#define MX6UL_PAD_LCD_DATA08__CSI_DATA16 0x0138 0x03c4 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA08__CA7_MX6UL_TRACE8 0x0138 0x03c4 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA08__CSI_DATA16 0x0138 0x03c4 0x0504 3 1
#define MX6UL_PAD_LCD_DATA08__EIM_DATA00 0x0138 0x03c4 0x0000 4 0
#define MX6UL_PAD_LCD_DATA08__GPIO3_IO13 0x0138 0x03c4 0x0000 5 0
#define MX6UL_PAD_LCD_DATA08__SRC_BT_CFG08 0x0138 0x03c4 0x0000 6 0
#define MX6UL_PAD_LCD_DATA08__FLEXCAN1_TX 0x0138 0x03c4 0x0000 8 0
#define MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x013c 0x03c8 0x0000 0 0
-#define MX6UL_PAD_LCD_DATA09__SAI3_MCLK 0x013c 0x03c8 0x0000 1 0
-#define MX6UL_PAD_LCD_DATA09__CSI_DATA17 0x013c 0x03c8 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA09__SAI3_MCLK 0x013c 0x03c8 0x0600 1 1
+#define MX6UL_PAD_LCD_DATA09__CA7_MX6UL_TRACE9 0x013c 0x03c8 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA09__CSI_DATA17 0x013c 0x03c8 0x0508 3 1
#define MX6UL_PAD_LCD_DATA09__EIM_DATA01 0x013c 0x03c8 0x0000 4 0
#define MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x013c 0x03c8 0x0000 5 0
#define MX6UL_PAD_LCD_DATA09__SRC_BT_CFG09 0x013c 0x03c8 0x0000 6 0
#define MX6UL_PAD_LCD_DATA09__FLEXCAN1_RX 0x013c 0x03c8 0x0584 8 2
#define MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x0140 0x03cc 0x0000 0 0
#define MX6UL_PAD_LCD_DATA10__SAI3_RX_SYNC 0x0140 0x03cc 0x0000 1 0
-#define MX6UL_PAD_LCD_DATA10__CSI_DATA18 0x0140 0x03cc 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA10__CA7_MX6UL_TRACE10 0x0140 0x03cc 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA10__CSI_DATA18 0x0140 0x03cc 0x050c 3 1
#define MX6UL_PAD_LCD_DATA10__EIM_DATA02 0x0140 0x03cc 0x0000 4 0
#define MX6UL_PAD_LCD_DATA10__GPIO3_IO15 0x0140 0x03cc 0x0000 5 0
#define MX6UL_PAD_LCD_DATA10__SRC_BT_CFG10 0x0140 0x03cc 0x0000 6 0
#define MX6UL_PAD_LCD_DATA10__FLEXCAN2_TX 0x0140 0x03cc 0x0000 8 0
#define MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x0144 0x03d0 0x0000 0 0
#define MX6UL_PAD_LCD_DATA11__SAI3_RX_BCLK 0x0144 0x03d0 0x0000 1 0
-#define MX6UL_PAD_LCD_DATA11__CSI_DATA19 0x0144 0x03d0 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA11__CA7_MX6UL_TRACE11 0x0144 0x03d0 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA11__CSI_DATA19 0x0144 0x03d0 0x0510 3 1
#define MX6UL_PAD_LCD_DATA11__EIM_DATA03 0x0144 0x03d0 0x0000 4 0
#define MX6UL_PAD_LCD_DATA11__GPIO3_IO16 0x0144 0x03d0 0x0000 5 0
#define MX6UL_PAD_LCD_DATA11__SRC_BT_CFG11 0x0144 0x03d0 0x0000 6 0
#define MX6UL_PAD_LCD_DATA11__FLEXCAN2_RX 0x0144 0x03d0 0x0588 8 2
#define MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x0148 0x03d4 0x0000 0 0
#define MX6UL_PAD_LCD_DATA12__SAI3_TX_SYNC 0x0148 0x03d4 0x060c 1 1
-#define MX6UL_PAD_LCD_DATA12__CSI_DATA20 0x0148 0x03d4 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA12__CA7_MX6UL_TRACE12 0x0148 0x03d4 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA12__CSI_DATA20 0x0148 0x03d4 0x0514 3 1
#define MX6UL_PAD_LCD_DATA12__EIM_DATA04 0x0148 0x03d4 0x0000 4 0
#define MX6UL_PAD_LCD_DATA12__GPIO3_IO17 0x0148 0x03d4 0x0000 5 0
#define MX6UL_PAD_LCD_DATA12__SRC_BT_CFG12 0x0148 0x03d4 0x0000 6 0
#define MX6UL_PAD_LCD_DATA12__ECSPI1_RDY 0x0148 0x03d4 0x0000 8 0
#define MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x014c 0x03d8 0x0000 0 0
#define MX6UL_PAD_LCD_DATA13__SAI3_TX_BCLK 0x014c 0x03d8 0x0608 1 1
-#define MX6UL_PAD_LCD_DATA13__CSI_DATA21 0x014c 0x03d8 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA13__CA7_MX6UL_TRACE13 0x014c 0x03d8 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA13__CSI_DATA21 0x014c 0x03d8 0x0518 3 1
#define MX6UL_PAD_LCD_DATA13__EIM_DATA05 0x014c 0x03d8 0x0000 4 0
#define MX6UL_PAD_LCD_DATA13__GPIO3_IO18 0x014c 0x03d8 0x0000 5 0
#define MX6UL_PAD_LCD_DATA13__SRC_BT_CFG13 0x014c 0x03d8 0x0000 6 0
#define MX6UL_PAD_LCD_DATA13__USDHC2_RESET_B 0x014c 0x03d8 0x0000 8 0
#define MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x0150 0x03dc 0x0000 0 0
-#define MX6UL_PAD_LCD_DATA14__SAI3_RX_DATA 0x0150 0x03dc 0x0000 1 0
-#define MX6UL_PAD_LCD_DATA14__CSI_DATA22 0x0150 0x03dc 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA14__SAI3_RX_DATA 0x0150 0x03dc 0x0604 1 1
+#define MX6UL_PAD_LCD_DATA14__CA7_MX6UL_TRACE14 0x0150 0x03dc 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA14__CSI_DATA22 0x0150 0x03dc 0x051c 3 1
#define MX6UL_PAD_LCD_DATA14__EIM_DATA06 0x0150 0x03dc 0x0000 4 0
#define MX6UL_PAD_LCD_DATA14__GPIO3_IO19 0x0150 0x03dc 0x0000 5 0
#define MX6UL_PAD_LCD_DATA14__SRC_BT_CFG14 0x0150 0x03dc 0x0000 6 0
#define MX6UL_PAD_LCD_DATA14__USDHC2_DATA4 0x0150 0x03dc 0x068c 8 0
#define MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x0154 0x03e0 0x0000 0 0
#define MX6UL_PAD_LCD_DATA15__SAI3_TX_DATA 0x0154 0x03e0 0x0000 1 0
-#define MX6UL_PAD_LCD_DATA15__CSI_DATA23 0x0154 0x03e0 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA15__CA7_MX6UL_TRACE15 0x0154 0x03e0 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA15__CSI_DATA23 0x0154 0x03e0 0x0520 3 1
#define MX6UL_PAD_LCD_DATA15__EIM_DATA07 0x0154 0x03e0 0x0000 4 0
#define MX6UL_PAD_LCD_DATA15__GPIO3_IO20 0x0154 0x03e0 0x0000 5 0
#define MX6UL_PAD_LCD_DATA15__SRC_BT_CFG15 0x0154 0x03e0 0x0000 6 0
@@ -594,7 +617,8 @@
#define MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x0158 0x03e4 0x0000 0 0
#define MX6UL_PAD_LCD_DATA16__UART7_DCE_TX 0x0158 0x03e4 0x0000 1 0
#define MX6UL_PAD_LCD_DATA16__UART7_DTE_RX 0x0158 0x03e4 0x0654 1 2
-#define MX6UL_PAD_LCD_DATA16__CSI_DATA01 0x0158 0x03e4 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA16__CA7_MX6UL_TRACE_CLK 0x0158 0x03e4 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA16__CSI_DATA01 0x0158 0x03e4 0x04d4 3 1
#define MX6UL_PAD_LCD_DATA16__EIM_DATA08 0x0158 0x03e4 0x0000 4 0
#define MX6UL_PAD_LCD_DATA16__GPIO3_IO21 0x0158 0x03e4 0x0000 5 0
#define MX6UL_PAD_LCD_DATA16__SRC_BT_CFG24 0x0158 0x03e4 0x0000 6 0
@@ -602,7 +626,8 @@
#define MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x015c 0x03e8 0x0000 0 0
#define MX6UL_PAD_LCD_DATA17__UART7_DCE_RX 0x015c 0x03e8 0x0654 1 3
#define MX6UL_PAD_LCD_DATA17__UART7_DTE_TX 0x015c 0x03e8 0x0000 1 0
-#define MX6UL_PAD_LCD_DATA17__CSI_DATA00 0x015c 0x03e8 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA17__CA7_MX6UL_TRACE_CTL 0x015c 0x03e8 0x0000 2 0
+#define MX6UL_PAD_LCD_DATA17__CSI_DATA00 0x015c 0x03e8 0x04d0 3 1
#define MX6UL_PAD_LCD_DATA17__EIM_DATA09 0x015c 0x03e8 0x0000 4 0
#define MX6UL_PAD_LCD_DATA17__GPIO3_IO22 0x015c 0x03e8 0x0000 5 0
#define MX6UL_PAD_LCD_DATA17__SRC_BT_CFG25 0x015c 0x03e8 0x0000 6 0
@@ -610,7 +635,7 @@
#define MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x0160 0x03ec 0x0000 0 0
#define MX6UL_PAD_LCD_DATA18__PWM5_OUT 0x0160 0x03ec 0x0000 1 0
#define MX6UL_PAD_LCD_DATA18__CA7_MX6UL_EVENTO 0x0160 0x03ec 0x0000 2 0
-#define MX6UL_PAD_LCD_DATA18__CSI_DATA10 0x0160 0x03ec 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA18__CSI_DATA10 0x0160 0x03ec 0x04ec 3 1
#define MX6UL_PAD_LCD_DATA18__EIM_DATA10 0x0160 0x03ec 0x0000 4 0
#define MX6UL_PAD_LCD_DATA18__GPIO3_IO23 0x0160 0x03ec 0x0000 5 0
#define MX6UL_PAD_LCD_DATA18__SRC_BT_CFG26 0x0160 0x03ec 0x0000 6 0
@@ -622,7 +647,7 @@
#define MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x0164 0x03f0 0x0000 0 0
#define MX6UL_PAD_LCD_DATA19__PWM6_OUT 0x0164 0x03f0 0x0000 1 0
#define MX6UL_PAD_LCD_DATA19__WDOG1_WDOG_ANY 0x0164 0x03f0 0x0000 2 0
-#define MX6UL_PAD_LCD_DATA19__CSI_DATA11 0x0164 0x03f0 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA19__CSI_DATA11 0x0164 0x03f0 0x04f0 3 1
#define MX6UL_PAD_LCD_DATA20__EIM_DATA12 0x0168 0x03f4 0x0000 4 0
#define MX6UL_PAD_LCD_DATA20__GPIO3_IO25 0x0168 0x03f4 0x0000 5 0
#define MX6UL_PAD_LCD_DATA20__SRC_BT_CFG28 0x0168 0x03f4 0x0000 6 0
@@ -631,12 +656,12 @@
#define MX6UL_PAD_LCD_DATA20__UART8_DCE_TX 0x0168 0x03f4 0x0000 1 0
#define MX6UL_PAD_LCD_DATA20__UART8_DTE_RX 0x0168 0x03f4 0x065c 1 2
#define MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK 0x0168 0x03f4 0x0534 2 0
-#define MX6UL_PAD_LCD_DATA20__CSI_DATA12 0x0168 0x03f4 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA20__CSI_DATA12 0x0168 0x03f4 0x04f4 3 1
#define MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x016c 0x03f8 0x0000 0 0
#define MX6UL_PAD_LCD_DATA21__UART8_DCE_RX 0x016c 0x03f8 0x065c 1 3
#define MX6UL_PAD_LCD_DATA21__UART8_DTE_TX 0x016c 0x03f8 0x0000 1 0
-#define MX6UL_PAD_LCD_DATA21__ECSPI1_SS0 0x016c 0x03f8 0x0000 2 0
-#define MX6UL_PAD_LCD_DATA21__CSI_DATA13 0x016c 0x03f8 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA21__ECSPI1_SS0 0x016c 0x03f8 0x0540 2 0
+#define MX6UL_PAD_LCD_DATA21__CSI_DATA13 0x016c 0x03f8 0x04f8 3 1
#define MX6UL_PAD_LCD_DATA21__EIM_DATA13 0x016c 0x03f8 0x0000 4 0
#define MX6UL_PAD_LCD_DATA21__GPIO3_IO26 0x016c 0x03f8 0x0000 5 0
#define MX6UL_PAD_LCD_DATA21__SRC_BT_CFG29 0x016c 0x03f8 0x0000 6 0
@@ -644,7 +669,7 @@
#define MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x0170 0x03fc 0x0000 0 0
#define MX6UL_PAD_LCD_DATA22__MQS_RIGHT 0x0170 0x03fc 0x0000 1 0
#define MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI 0x0170 0x03fc 0x053c 2 0
-#define MX6UL_PAD_LCD_DATA22__CSI_DATA14 0x0170 0x03fc 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA22__CSI_DATA14 0x0170 0x03fc 0x04fc 3 1
#define MX6UL_PAD_LCD_DATA22__EIM_DATA14 0x0170 0x03fc 0x0000 4 0
#define MX6UL_PAD_LCD_DATA22__GPIO3_IO27 0x0170 0x03fc 0x0000 5 0
#define MX6UL_PAD_LCD_DATA22__SRC_BT_CFG30 0x0170 0x03fc 0x0000 6 0
@@ -652,7 +677,7 @@
#define MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x0174 0x0400 0x0000 0 0
#define MX6UL_PAD_LCD_DATA23__MQS_LEFT 0x0174 0x0400 0x0000 1 0
#define MX6UL_PAD_LCD_DATA23__ECSPI1_MISO 0x0174 0x0400 0x0538 2 0
-#define MX6UL_PAD_LCD_DATA23__CSI_DATA15 0x0174 0x0400 0x0000 3 0
+#define MX6UL_PAD_LCD_DATA23__CSI_DATA15 0x0174 0x0400 0x0500 3 1
#define MX6UL_PAD_LCD_DATA23__EIM_DATA15 0x0174 0x0400 0x0000 4 0
#define MX6UL_PAD_LCD_DATA23__GPIO3_IO28 0x0174 0x0400 0x0000 5 0
#define MX6UL_PAD_LCD_DATA23__SRC_BT_CFG31 0x0174 0x0400 0x0000 6 0
@@ -660,42 +685,42 @@
#define MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B 0x0178 0x0404 0x0000 0 0
#define MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x0178 0x0404 0x0670 1 2
#define MX6UL_PAD_NAND_RE_B__QSPI_B_SCLK 0x0178 0x0404 0x0000 2 0
-#define MX6UL_PAD_NAND_RE_B__KPP_ROW00 0x0178 0x0404 0x0000 3 0
+#define MX6UL_PAD_NAND_RE_B__KPP_ROW00 0x0178 0x0404 0x05d0 3 1
#define MX6UL_PAD_NAND_RE_B__EIM_EB_B00 0x0178 0x0404 0x0000 4 0
#define MX6UL_PAD_NAND_RE_B__GPIO4_IO00 0x0178 0x0404 0x0000 5 0
#define MX6UL_PAD_NAND_RE_B__ECSPI3_SS2 0x0178 0x0404 0x0000 8 0
#define MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B 0x017c 0x0408 0x0000 0 0
#define MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x017c 0x0408 0x0678 1 2
#define MX6UL_PAD_NAND_WE_B__QSPI_B_SS0_B 0x017c 0x0408 0x0000 2 0
-#define MX6UL_PAD_NAND_WE_B__KPP_COL00 0x017c 0x0408 0x0000 3 0
+#define MX6UL_PAD_NAND_WE_B__KPP_COL00 0x017c 0x0408 0x05c4 3 1
#define MX6UL_PAD_NAND_WE_B__EIM_EB_B01 0x017c 0x0408 0x0000 4 0
#define MX6UL_PAD_NAND_WE_B__GPIO4_IO01 0x017c 0x0408 0x0000 5 0
#define MX6UL_PAD_NAND_WE_B__ECSPI3_SS3 0x017c 0x0408 0x0000 8 0
#define MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00 0x0180 0x040c 0x0000 0 0
#define MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x0180 0x040c 0x067c 1 2
#define MX6UL_PAD_NAND_DATA00__QSPI_B_SS1_B 0x0180 0x040c 0x0000 2 0
-#define MX6UL_PAD_NAND_DATA00__KPP_ROW01 0x0180 0x040c 0x0000 3 0
+#define MX6UL_PAD_NAND_DATA00__KPP_ROW01 0x0180 0x040c 0x05d4 3 1
#define MX6UL_PAD_NAND_DATA00__EIM_AD08 0x0180 0x040c 0x0000 4 0
#define MX6UL_PAD_NAND_DATA00__GPIO4_IO02 0x0180 0x040c 0x0000 5 0
#define MX6UL_PAD_NAND_DATA00__ECSPI4_RDY 0x0180 0x040c 0x0000 8 0
#define MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01 0x0184 0x0410 0x0000 0 0
#define MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x0184 0x0410 0x0680 1 2
#define MX6UL_PAD_NAND_DATA01__QSPI_B_DQS 0x0184 0x0410 0x0000 2 0
-#define MX6UL_PAD_NAND_DATA01__KPP_COL01 0x0184 0x0410 0x0000 3 0
+#define MX6UL_PAD_NAND_DATA01__KPP_COL01 0x0184 0x0410 0x05c8 3 1
#define MX6UL_PAD_NAND_DATA01__EIM_AD09 0x0184 0x0410 0x0000 4 0
#define MX6UL_PAD_NAND_DATA01__GPIO4_IO03 0x0184 0x0410 0x0000 5 0
#define MX6UL_PAD_NAND_DATA01__ECSPI4_SS1 0x0184 0x0410 0x0000 8 0
#define MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02 0x0188 0x0414 0x0000 0 0
#define MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x0188 0x0414 0x0684 1 1
#define MX6UL_PAD_NAND_DATA02__QSPI_B_DATA00 0x0188 0x0414 0x0000 2 0
-#define MX6UL_PAD_NAND_DATA02__KPP_ROW02 0x0188 0x0414 0x0000 3 0
+#define MX6UL_PAD_NAND_DATA02__KPP_ROW02 0x0188 0x0414 0x05d8 3 1
#define MX6UL_PAD_NAND_DATA02__EIM_AD10 0x0188 0x0414 0x0000 4 0
#define MX6UL_PAD_NAND_DATA02__GPIO4_IO04 0x0188 0x0414 0x0000 5 0
#define MX6UL_PAD_NAND_DATA02__ECSPI4_SS2 0x0188 0x0414 0x0000 8 0
#define MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03 0x018c 0x0418 0x0000 0 0
#define MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x018c 0x0418 0x0688 1 2
#define MX6UL_PAD_NAND_DATA03__QSPI_B_DATA01 0x018c 0x0418 0x0000 2 0
-#define MX6UL_PAD_NAND_DATA03__KPP_COL02 0x018c 0x0418 0x0000 3 0
+#define MX6UL_PAD_NAND_DATA03__KPP_COL02 0x018c 0x0418 0x05cc 3 1
#define MX6UL_PAD_NAND_DATA03__EIM_AD11 0x018c 0x0418 0x0000 4 0
#define MX6UL_PAD_NAND_DATA03__GPIO4_IO05 0x018c 0x0418 0x0000 5 0
#define MX6UL_PAD_NAND_DATA03__ECSPI4_SS3 0x018c 0x0418 0x0000 8 0
@@ -726,7 +751,7 @@
#define MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07 0x019c 0x0428 0x0000 0 0
#define MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x019c 0x0428 0x0698 1 1
#define MX6UL_PAD_NAND_DATA07__QSPI_A_SS1_B 0x019c 0x0428 0x0000 2 0
-#define MX6UL_PAD_NAND_DATA07__ECSPI4_SS0 0x019c 0x0428 0x0000 3 0
+#define MX6UL_PAD_NAND_DATA07__ECSPI4_SS0 0x019c 0x0428 0x0570 3 1
#define MX6UL_PAD_NAND_DATA07__EIM_AD15 0x019c 0x0428 0x0000 4 0
#define MX6UL_PAD_NAND_DATA07__GPIO4_IO09 0x019c 0x0428 0x0000 5 0
#define MX6UL_PAD_NAND_DATA07__UART2_DCE_RTS 0x019c 0x0428 0x0628 8 5
@@ -748,7 +773,7 @@
#define MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0x01a8 0x0434 0x0000 0 0
#define MX6UL_PAD_NAND_READY_B__USDHC1_DATA4 0x01a8 0x0434 0x0000 1 0
#define MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x01a8 0x0434 0x0000 2 0
-#define MX6UL_PAD_NAND_READY_B__ECSPI3_SS0 0x01a8 0x0434 0x0000 3 0
+#define MX6UL_PAD_NAND_READY_B__ECSPI3_SS0 0x01a8 0x0434 0x0560 3 1
#define MX6UL_PAD_NAND_READY_B__EIM_CS1_B 0x01a8 0x0434 0x0000 4 0
#define MX6UL_PAD_NAND_READY_B__GPIO4_IO12 0x01a8 0x0434 0x0000 5 0
#define MX6UL_PAD_NAND_READY_B__UART3_DCE_TX 0x01a8 0x0434 0x0000 8 0
@@ -783,7 +808,7 @@
#define MX6UL_PAD_NAND_DQS__PWM5_OUT 0x01b8 0x0444 0x0000 3 0
#define MX6UL_PAD_NAND_DQS__EIM_WAIT 0x01b8 0x0444 0x0000 4 0
#define MX6UL_PAD_NAND_DQS__GPIO4_IO16 0x01b8 0x0444 0x0000 5 0
-#define MX6UL_PAD_NAND_DQS__SDMA_EXT_EVENT01 0x01b8 0x0444 0x0000 6 0
+#define MX6UL_PAD_NAND_DQS__SDMA_EXT_EVENT01 0x01b8 0x0444 0x0614 6 1
#define MX6UL_PAD_NAND_DQS__SPDIF_EXT_CLK 0x01b8 0x0444 0x061c 8 1
#define MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x01bc 0x0448 0x0000 0 0
#define MX6UL_PAD_SD1_CMD__GPT2_COMPARE1 0x01bc 0x0448 0x0000 1 0
@@ -791,11 +816,11 @@
#define MX6UL_PAD_SD1_CMD__SPDIF_OUT 0x01bc 0x0448 0x0000 3 0
#define MX6UL_PAD_SD1_CMD__EIM_ADDR19 0x01bc 0x0448 0x0000 4 0
#define MX6UL_PAD_SD1_CMD__GPIO2_IO16 0x01bc 0x0448 0x0000 5 0
-#define MX6UL_PAD_SD1_CMD__SDMA_EXT_EVENT00 0x01bc 0x0448 0x0000 6 0
+#define MX6UL_PAD_SD1_CMD__SDMA_EXT_EVENT00 0x01bc 0x0448 0x0610 6 2
#define MX6UL_PAD_SD1_CMD__USB_OTG1_PWR 0x01bc 0x0448 0x0000 8 0
#define MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x01c0 0x044c 0x0000 0 0
#define MX6UL_PAD_SD1_CLK__GPT2_COMPARE2 0x01c0 0x044c 0x0000 1 0
-#define MX6UL_PAD_SD1_CLK__SAI2_MCLK 0x01c0 0x044c 0x0000 2 0
+#define MX6UL_PAD_SD1_CLK__SAI2_MCLK 0x01c0 0x044c 0x05f0 2 1
#define MX6UL_PAD_SD1_CLK__SPDIF_IN 0x01c0 0x044c 0x0618 3 3
#define MX6UL_PAD_SD1_CLK__EIM_ADDR20 0x01c0 0x044c 0x0000 4 0
#define MX6UL_PAD_SD1_CLK__GPIO2_IO17 0x01c0 0x044c 0x0000 5 0
@@ -878,10 +903,10 @@
#define MX6UL_PAD_CSI_DATA01__CSI_DATA03 0x01e8 0x0474 0x04c8 0 0
#define MX6UL_PAD_CSI_DATA01__USDHC2_DATA1 0x01e8 0x0474 0x0680 1 0
#define MX6UL_PAD_CSI_DATA01__SIM1_PORT1_SVEN 0x01e8 0x0474 0x0000 2 0
-#define MX6UL_PAD_CSI_DATA01__ECSPI2_SS0 0x01e8 0x0474 0x0000 3 0
+#define MX6UL_PAD_CSI_DATA01__ECSPI2_SS0 0x01e8 0x0474 0x0550 3 0
#define MX6UL_PAD_CSI_DATA01__EIM_AD01 0x01e8 0x0474 0x0000 4 0
#define MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x01e8 0x0474 0x0000 5 0
-#define MX6UL_PAD_CSI_DATA01__SAI1_MCLK 0x01e8 0x0474 0x0000 6 0
+#define MX6UL_PAD_CSI_DATA01__SAI1_MCLK 0x01e8 0x0474 0x05e0 6 0
#define MX6UL_PAD_CSI_DATA01__UART5_DCE_RX 0x01e8 0x0474 0x0644 8 1
#define MX6UL_PAD_CSI_DATA01__UART5_DTE_TX 0x01e8 0x0474 0x0000 8 0
#define MX6UL_PAD_CSI_DATA02__CSI_DATA04 0x01ec 0x0478 0x04d8 0 1
@@ -913,7 +938,7 @@
#define MX6UL_PAD_CSI_DATA05__CSI_DATA07 0x01f8 0x0484 0x04e0 0 1
#define MX6UL_PAD_CSI_DATA05__USDHC2_DATA5 0x01f8 0x0484 0x0690 1 2
#define MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B 0x01f8 0x0484 0x0000 2 0
-#define MX6UL_PAD_CSI_DATA05__ECSPI1_SS0 0x01f8 0x0484 0x0000 3 0
+#define MX6UL_PAD_CSI_DATA05__ECSPI1_SS0 0x01f8 0x0484 0x0540 3 1
#define MX6UL_PAD_CSI_DATA05__EIM_AD05 0x01f8 0x0484 0x0000 4 0
#define MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x01f8 0x0484 0x0000 5 0
#define MX6UL_PAD_CSI_DATA05__SAI1_TX_BCLK 0x01f8 0x0484 0x05e8 6 1
@@ -924,7 +949,7 @@
#define MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x01fc 0x0488 0x053c 3 1
#define MX6UL_PAD_CSI_DATA06__EIM_AD06 0x01fc 0x0488 0x0000 4 0
#define MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x01fc 0x0488 0x0000 5 0
-#define MX6UL_PAD_CSI_DATA06__SAI1_RX_DATA 0x01fc 0x0488 0x0000 6 0
+#define MX6UL_PAD_CSI_DATA06__SAI1_RX_DATA 0x01fc 0x0488 0x05e4 6 1
#define MX6UL_PAD_CSI_DATA06__USDHC1_RESET_B 0x01fc 0x0488 0x0000 8 0
#define MX6UL_PAD_CSI_DATA07__CSI_DATA09 0x0200 0x048c 0x04e8 0 1
#define MX6UL_PAD_CSI_DATA07__USDHC2_DATA7 0x0200 0x048c 0x0698 1 2
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index c5c05fdccc78..0b04e4eecb44 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -1,5 +1,6 @@
/*
- * Copyright 2015 Freescale Semiconductor, Inc.
+ * Copyright 2015-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
@@ -58,12 +59,14 @@
clock-latency = <61036>; /* two CLK32 periods */
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
@@ -133,15 +136,43 @@
interrupt-parent = <&gpc>;
ranges;
+ 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>;
+ };
+
pmu {
compatible = "arm,cortex-a7-pmu";
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
- ocram: sram@00900000 {
+ ocrams: sram@00900000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x00900000 0x4000>;
+ };
+
+ ocrams_ddr: sram@00904000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x00904000 0x1000>;
+ };
+
+ ocram: sram@00905000 {
compatible = "mmio-sram";
- reg = <0x00900000 0x20000>;
+ reg = <0x00905000 0x1B000>;
};
dma_apbh: dma-apbh@01804000 {
@@ -157,6 +188,21 @@
clocks = <&clks IMX6UL_CLK_APBHDMA>;
};
+ caam_sm: caam-sm@00100000 {
+ compatible = "fsl,imx7d-caam-sm", "fsl,imx6q-caam-sm";
+ reg = <0x00100000 0x3fff>;
+ };
+
+ irq_sec_vio: caam_secvio {
+ compatible = "fsl,imx7d-caam-secvio", "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";
+ };
+
+
gpmi: gpmi-nand@01806000 {
compatible = "fsl,imx6q-gpmi-nand";
#address-cells = <1>;
@@ -191,6 +237,28 @@
reg = <0x02000000 0x40000>;
ranges;
+ spdif: spdif@02004000 {
+ compatible = "fsl,imx6ul-spdif", "fsl,imx35-spdif";
+ reg = <0x02004000 0x4000>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 41 18 0>,
+ <&sdma 42 18 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6UL_CLK_SPDIF_GCLK>,
+ <&clks IMX6UL_CLK_OSC>,
+ <&clks IMX6UL_CLK_SPDIF>,
+ <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_IPG>,
+ <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_SPBA>;
+ clock-names = "core", "rxtx0",
+ "rxtx1", "rxtx2",
+ "rxtx3", "rxtx4",
+ "rxtx5", "rxtx6",
+ "rxtx7", "spba";
+ status = "disabled";
+ };
+
ecspi1: ecspi@02008000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -200,6 +268,8 @@
clocks = <&clks IMX6UL_CLK_ECSPI1>,
<&clks IMX6UL_CLK_ECSPI1>;
clock-names = "ipg", "per";
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -212,6 +282,8 @@
clocks = <&clks IMX6UL_CLK_ECSPI2>,
<&clks IMX6UL_CLK_ECSPI2>;
clock-names = "ipg", "per";
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -224,6 +296,8 @@
clocks = <&clks IMX6UL_CLK_ECSPI3>,
<&clks IMX6UL_CLK_ECSPI3>;
clock-names = "ipg", "per";
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -236,23 +310,27 @@
clocks = <&clks IMX6UL_CLK_ECSPI4>,
<&clks IMX6UL_CLK_ECSPI4>;
clock-names = "ipg", "per";
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+ dma-names = "rx", "tx";
status = "disabled";
};
uart7: serial@02018000 {
compatible = "fsl,imx6ul-uart",
- "fsl,imx6q-uart";
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02018000 0x4000>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_UART7_IPG>,
<&clks IMX6UL_CLK_UART7_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 43 4 0>, <&sdma 44 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
uart1: serial@02020000 {
compatible = "fsl,imx6ul-uart",
- "fsl,imx6q-uart";
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02020000 0x4000>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_UART1_IPG>,
@@ -263,12 +341,14 @@
uart8: serial@02024000 {
compatible = "fsl,imx6ul-uart",
- "fsl,imx6q-uart";
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02024000 0x4000>;
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_UART8_IPG>,
<&clks IMX6UL_CLK_UART8_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 45 4 0>, <&sdma 46 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -278,9 +358,10 @@
reg = <0x02028000 0x4000>;
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_SAI1_IPG>,
+ <&clks IMX6UL_CLK_DUMMY>,
<&clks IMX6UL_CLK_SAI1>,
<&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dmas = <&sdma 35 24 0>,
<&sdma 36 24 0>;
dma-names = "rx", "tx";
@@ -293,9 +374,11 @@
reg = <0x0202c000 0x4000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_SAI2_IPG>,
+ <&clks IMX6UL_CLK_DUMMY>,
<&clks IMX6UL_CLK_SAI2>,
<&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+
dmas = <&sdma 37 24 0>,
<&sdma 38 24 0>;
dma-names = "rx", "tx";
@@ -308,14 +391,40 @@
reg = <0x02030000 0x4000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_SAI3_IPG>,
+ <&clks IMX6UL_CLK_DUMMY>,
<&clks IMX6UL_CLK_SAI3>,
<&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dmas = <&sdma 39 24 0>,
<&sdma 40 24 0>;
dma-names = "rx", "tx";
status = "disabled";
};
+
+ asrc: asrc@02034000 {
+ compatible = "fsl,imx53-asrc";
+ reg = <0x02034000 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@02040000 {
@@ -329,6 +438,13 @@
status = "disabled";
};
+ bee: bee@02044000 {
+ compatible = "fsl,imx6ul-bee";
+ reg = <0x02044000 0x4000>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
pwm1: pwm@02080000 {
compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
reg = <0x02080000 0x4000>;
@@ -380,6 +496,7 @@
clocks = <&clks IMX6UL_CLK_CAN1_IPG>,
<&clks IMX6UL_CLK_CAN1_SERIAL>;
clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x10 1 0x10 17>;
status = "disabled";
};
@@ -390,6 +507,7 @@
clocks = <&clks IMX6UL_CLK_CAN2_IPG>,
<&clks IMX6UL_CLK_CAN2_SERIAL>;
clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x10 2 0x10 18>;
status = "disabled";
};
@@ -398,8 +516,8 @@
reg = <0x02098000 0x4000>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_GPT1_BUS>,
- <&clks IMX6UL_CLK_GPT1_SERIAL>;
- clock-names = "ipg", "per";
+ <&clks IMX6UL_CLK_GPT_3M>;
+ clock-names = "ipg", "osc_per";
};
gpio1: gpio@0209c000 {
@@ -463,6 +581,12 @@
gpio-ranges = <&iomuxc 0 7 10>, <&iomuxc 10 5 2>;
};
+ snvslp: snvs@020b0000 {
+ compatible = "fsl,imx6ul-snvs";
+ reg = <0x020b0000 0x4000>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
fec2: ethernet@020b4000 {
compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
reg = <0x020b4000 0x4000>;
@@ -475,8 +599,11 @@
<&clks IMX6UL_CLK_ENET2_REF_125M>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
+ stop-mode = <&gpr 0x10 4>;
fsl,num-tx-queues=<1>;
fsl,num-rx-queues=<1>;
+ fsl,magic-packet;
+ fsl,wakeup_irq = <0>;
status = "disabled";
};
@@ -588,6 +715,19 @@
fsl,anatop = <&anatop>;
};
+ tempmon: tempmon {
+ compatible = "fsl,imx6ul-tempmon", "fsl,imx6sx-tempmon";
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,tempmon = <&anatop>;
+ fsl,tempmon-data = <&ocotp>;
+ clocks = <&clks IMX6UL_CLK_PLL3_USB_OTG>;
+ };
+
+ caam_snvs: caam-snvs@020cc000 {
+ compatible = "fsl,imx6q-caam-snvs";
+ reg = <0x020cc000 0x4000>;
+ };
+
snvs: snvs@020cc000 {
compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
reg = <0x020cc000 0x4000>;
@@ -604,7 +744,7 @@
compatible = "syscon-poweroff";
regmap = <&snvs>;
offset = <0x38>;
- mask = <0x60>;
+ mask = <0x61>;
status = "disabled";
};
@@ -642,6 +782,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@020e0000 {
@@ -664,6 +805,13 @@
clock-names = "ipg", "per";
};
+ mqs: mqs {
+ compatible = "fsl,imx6sx-mqs";
+ gpr = <&gpr>;
+ status = "disabled";
+ };
+
+
sdma: sdma@020ec000 {
compatible = "fsl,imx6ul-sdma", "fsl,imx6q-sdma",
"fsl,imx35-sdma";
@@ -673,6 +821,7 @@
<&clks IMX6UL_CLK_SDMA>;
clock-names = "ipg", "ahb";
#dma-cells = <3>;
+ iram = <&ocram>;
fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
};
@@ -728,6 +877,35 @@
reg = <0x02100000 0x100000>;
ranges;
+ crypto: caam@2140000 {
+ compatible = "fsl,imx6ul-caam", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x2140000 0x3c000>;
+ ranges = <0 0x2140000 0x3c000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_CAAM_IPG>, <&clks IMX6UL_CLK_CAAM_ACLK>,
+ <&clks IMX6UL_CLK_CAAM_MEM>;
+ clock-names = "ipg", "aclk", "mem";
+
+ sec_jr0: jr0@1000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ sec_jr1: jr1@2000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ sec_jr2: jr2@3000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
usbotg1: usb@02184000 {
compatible = "fsl,imx6ul-usb", "fsl,imx27-usb";
reg = <0x02184000 0x200>;
@@ -773,8 +951,18 @@
<&clks IMX6UL_CLK_ENET_REF>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
+ stop-mode = <&gpr 0x10 3>;
fsl,num-tx-queues=<1>;
fsl,num-rx-queues=<1>;
+ 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";
};
@@ -844,11 +1032,56 @@
status = "disabled";
};
+ romcp@021ac000 {
+ compatible = "fsl,imx6ul-romcp", "syscon";
+ reg = <0x021ac000 0x4000>;
+ };
+
mmdc: mmdc@021b0000 {
compatible = "fsl,imx6ul-mmdc", "fsl,imx6q-mmdc";
reg = <0x021b0000 0x4000>;
};
+ 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@021b8000 {
+ compatible = "fsl,imx6ul-weim", "fsl,imx6q-weim";
+ reg = <0x021b8000 0x4000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>;
+ };
+
+ ocotp: ocotp-ctrl@021bc000 {
+ compatible = "fsl,imx6ul-ocotp", "syscon";
+ reg = <0x021bc000 0x4000>;
+ clocks = <&clks IMX6UL_CLK_OCOTP>;
+ };
+
+ csu: csu@021c0000 {
+ compatible = "fsl,imx6ul-csu";
+ reg = <0x021c0000 0x4000>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ csi: csi@021c4000 {
+ compatible = "fsl,imx6ul-csi", "fsl,imx6s-csi";
+ reg = <0x021c4000 0x4000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_CSI>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+ status = "disabled";
+ };
+
lcdif: lcdif@021c8000 {
compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
reg = <0x021c8000 0x4000>;
@@ -873,47 +1106,65 @@
status = "disabled";
};
+ pxp: pxp@021cc000 {
+ compatible = "fsl,imx6ul-pxp-dma", "fsl,imx6sl-pxp-dma", "fsl,imx6dl-pxp-dma";
+ reg = <0x021cc000 0x4000>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PXP>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "pxp-axi", "disp-axi";
+ status = "disabled";
+ };
+
uart2: serial@021e8000 {
compatible = "fsl,imx6ul-uart",
- "fsl,imx6q-uart";
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021e8000 0x4000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_UART2_IPG>,
<&clks IMX6UL_CLK_UART2_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
uart3: serial@021ec000 {
compatible = "fsl,imx6ul-uart",
- "fsl,imx6q-uart";
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021ec000 0x4000>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_UART3_IPG>,
<&clks IMX6UL_CLK_UART3_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
uart4: serial@021f0000 {
compatible = "fsl,imx6ul-uart",
- "fsl,imx6q-uart";
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f0000 0x4000>;
interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_UART4_IPG>,
<&clks IMX6UL_CLK_UART4_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
uart5: serial@021f4000 {
compatible = "fsl,imx6ul-uart",
- "fsl,imx6q-uart";
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f4000 0x4000>;
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_UART5_IPG>,
<&clks IMX6UL_CLK_UART5_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -929,12 +1180,14 @@
uart6: serial@021fc000 {
compatible = "fsl,imx6ul-uart",
- "fsl,imx6q-uart";
+ "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021fc000 0x4000>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_UART6_IPG>,
<&clks IMX6UL_CLK_UART6_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 0 4 0>, <&sdma 47 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-adc.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-adc.dts
new file mode 100644
index 000000000000..334597cac3ce
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-adc.dts
@@ -0,0 +1,20 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+&usbotg1 {
+ status = "disabled";
+};
+
+&adc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc1>;
+ vref-supply = <&reg_vref_3v3>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-cs42888.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-cs42888.dts
new file mode 100644
index 000000000000..0b498b21fc8a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-cs42888.dts
@@ -0,0 +1,158 @@
+/*
+ * 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-ddr3-arm2-lcdif.dts"
+
+/ {
+ clocks {
+ codec_osc: anaclk2 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24576000>;
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_audio: cs42888_supply {
+ compatible = "regulator-fixed";
+ regulator-name = "cs42888_supply";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_codec_5v: codec_5v {
+ compatible = "regulator-fixed";
+ regulator-name = "CODEC_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ };
+
+ reg_aud_3v3: aud_3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "AUD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ };
+
+ reg_aud_1v8: aud_1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "AUD_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ enable-active-high;
+ };
+ };
+
+ sound-cs42888 {
+ compatible = "fsl,imx6-sabreauto-cs42888",
+ "fsl,imx-audio-cs42888";
+ model = "imx-cs42888";
+ esai-controller = <&esai>;
+ asrc-controller = <&asrc>;
+ audio-codec = <&codec_a>;
+ codec-master;
+ };
+
+ sound-wm8958 {
+ compatible = "fsl,imx6ul-ddr3-arm2-wm8958",
+ "fsl,imx-audio-wm8958";
+ model = "wm8958-audio";
+ cpu-dai = <&sai2>;
+ audio-codec = <&codec_b>;
+ codec-master;
+ gpr = <&gpr 4 0x100000 0x100000>;
+ hp-det-gpios = <&gpio5 0 1>;
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&esai {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_esai>;
+ assigned-clocks = <&clks IMX6UL_CLK_ESAI_SEL>,
+ <&clks IMX6UL_CLK_ESAI_EXTAL>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <24576000>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ codec_a: cs42888@048 {
+ compatible = "cirrus,cs42888";
+ reg = <0x048>;
+ clocks = <&codec_osc 0>;
+ clock-names = "mclk";
+ VA-supply = <&reg_audio>;
+ VD-supply = <&reg_audio>;
+ VLS-supply = <&reg_audio>;
+ VLC-supply = <&reg_audio>;
+ };
+
+ codec_b: wm8958@1a {
+ compatible = "wlf,wm8958";
+ reg = <0x1a>;
+ clocks = <&clks IMX6UL_CLK_SAI2>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "mclk1", "mclk2";
+
+ DBVDD1-supply = <&reg_aud_1v8>;
+ DBVDD2-supply = <&reg_aud_1v8>;
+ DBVDD3-supply = <&reg_aud_3v3>;
+ AVDD2-supply = <&reg_aud_1v8>;
+ CPVDD-supply = <&reg_aud_1v8>;
+ SPKVDD1-supply = <&reg_codec_5v>;
+ SPKVDD2-supply = <&reg_codec_5v>;
+
+ wlf,ldo1ena;
+ wlf,ldo2ena;
+ };
+};
+
+&ov5640 {
+ status = "disabled";
+};
+
+&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>, <24576000>;
+ status = "okay";
+};
+
+&sdma {
+ gpr = <&gpr>;
+ /* SDMA event remap for ESAI */
+ fsl,sdma-event-remap = <0 14 1>, <0 15 1>;
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&usdhc1 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-ecspi.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-ecspi.dts
new file mode 100644
index 000000000000..e9012c95cb74
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-ecspi.dts
@@ -0,0 +1,22 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+&ecspi1 {
+ status ="okay";
+};
+
+&esai {
+ status ="disabled";
+};
+
+&ov5640{
+ status ="disabled";
+};
+
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-emmc.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-emmc.dts
new file mode 100644
index 000000000000..934e6f6b8502
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-emmc.dts
@@ -0,0 +1,20 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+&usdhc1 {
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ cd-gpios = <>;
+ wp-gpios = <>;
+ vmmc-supply = <>;
+ non-removable;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-epdc.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-epdc.dts
new file mode 100644
index 000000000000..c476f442efdf
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-epdc.dts
@@ -0,0 +1,25 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+&epdc {
+ status = "okay";
+};
+
+&fec2 {
+ status = "disabled";
+};
+
+&lcdif {
+ status = "disabled";
+};
+
+&max17135 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-flexcan2.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-flexcan2.dts
new file mode 100644
index 000000000000..7169630ccc51
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-flexcan2.dts
@@ -0,0 +1,19 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+/* flexcan2 tx/rx pin conflicts with uart2 */
+
+&uart2{
+ status = "disabled";
+};
+
+&flexcan2 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-gpmi-weim.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-gpmi-weim.dts
new file mode 100644
index 000000000000..327677aafa7d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-gpmi-weim.dts
@@ -0,0 +1,21 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+&gpmi {
+ status ="okay";
+};
+
+&qspi {
+ status ="disabled";
+};
+
+&usdhc2{
+ status ="disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-lcdif.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-lcdif.dts
new file mode 100644
index 000000000000..40e86a4e08c3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-lcdif.dts
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+/* DTS file for LCDIF at imx6ull ddr3 arm2 board */
+
+#include "imx6ull-14x14-ddr3-arm2.dts"
+
+/ {
+ backlight {
+ status = "okay";
+ };
+};
+
+&fec1 {
+ status = "disabled";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-ldo.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-ldo.dts
new file mode 100644
index 000000000000..4266dc243da6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-ldo.dts
@@ -0,0 +1,41 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 996000 1275000
+ 792000 1225000
+ 528000 1175000
+ 396000 1025000
+ 198000 950000
+ >;
+ fsl,soc-operating-points = <
+ /* KHz uV */
+ 996000 1175000
+ 792000 1175000
+ 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-14x14-ddr3-arm2-qspi-all.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-qspi-all.dts
new file mode 100644
index 000000000000..a4cdbe588d83
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-qspi-all.dts
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+#define REWORKED_ENABLE_ALL_QSPI
+#include "imx6ull-14x14-ddr3-arm2.dts"
+
+&gpmi {
+ status ="disabled";
+};
+
+&usdhc2{
+ status ="disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-qspi.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-qspi.dts
new file mode 100644
index 000000000000..2155c7af1b77
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-qspi.dts
@@ -0,0 +1,9 @@
+/*
+ * 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-ddr3-arm2.dts"
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-tsc.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-tsc.dts
new file mode 100644
index 000000000000..8893e39b0ac3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-tsc.dts
@@ -0,0 +1,39 @@
+/*
+ * 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-ddr3-arm2-lcdif.dts"
+
+&csi {
+ status = "disabled";
+};
+
+&i2c1 {
+ status = "disabled";
+};
+
+&reg_usb_otg1_vbus {
+ pinctrl-0 = < >;
+ gpio = < >;
+};
+
+&ov5640 {
+ status = "disabled";
+};
+
+&usbotg1 {
+ status = "disabled";
+};
+
+&tsc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tsc>;
+ status = "okay";
+ xnur-gpio = <&gpio1 3 0>;
+ measure_delay_time = <0xfff>;
+ pre_charge_time = <0xffff>;
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-uart2.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-uart2.dts
new file mode 100644
index 000000000000..6f157ea4656d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-uart2.dts
@@ -0,0 +1,21 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+&flexcan2 {
+ status = "disabled";
+};
+
+&i2c4 {
+ status = "disabled";
+};
+
+&uart2 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-usb.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-usb.dts
new file mode 100644
index 000000000000..619c28b89d46
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-usb.dts
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+/* DTS file for validate USB at i.mx6ull ddr3 arm2 board */
+
+#include "imx6ull-14x14-ddr3-arm2.dts"
+
+/ {
+ regulators {
+ reg_usb_otg2_vbus: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "usb_otg2_vbus";
+ pinctrl-0 = <&pinctrl_usb_otg2>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&iomuxc {
+ usbotg2 {
+ pinctrl_usb_otg2_id: usbotg2idgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO05__ANATOP_OTG2_ID 0x17059
+ >;
+ };
+
+ pinctrl_usb_otg2: usbotg2grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x10b0
+ >;
+ };
+ };
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>; /* hardware rework is needed */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg2_id>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usdhc1 {
+ no-1-8-v;
+ vmmc-supply = <>;
+ pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_cd_wp>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>, <&pinctrl_usdhc1_cd_wp>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>, <&pinctrl_usdhc1_cd_wp>;
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-wm8958.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-wm8958.dts
new file mode 100644
index 000000000000..498281b2c88b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2-wm8958.dts
@@ -0,0 +1,155 @@
+/*
+ * 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-ddr3-arm2.dts"
+
+/ {
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_codec_5v: codec_5v {
+ compatible = "regulator-fixed";
+ regulator-name = "CODEC_5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ };
+
+ reg_aud_3v3: aud_3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "AUD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ };
+
+ reg_aud_1v8: aud_1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "AUD_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ enable-active-high;
+ };
+ };
+
+ sound-mqs {
+ compatible = "fsl,imx6ul-ddr3-arm2-mqs",
+ "fsl,imx-audio-mqs";
+ model = "mqs-audio";
+ cpu-dai = <&sai1>;
+ asrc-controller = <&asrc>;
+ audio-codec = <&mqs>;
+ };
+
+ sound-wm8958 {
+ compatible = "fsl,imx6ul-ddr3-arm2-wm8958",
+ "fsl,imx-audio-wm8958";
+ model = "wm8958-audio";
+ cpu-dai = <&sai2>;
+ audio-codec = <&codec_b>;
+ codec-master;
+ gpr = <&gpr 4 0x100000 0x100000>;
+ hp-det-gpios = <&gpio5 0 1>;
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-in;
+ spdif-out;
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ codec_b: wm8958@1a {
+ compatible = "wlf,wm8958";
+ reg = <0x1a>;
+ clocks = <&clks IMX6UL_CLK_SAI2>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "mclk1", "mclk2";
+
+ DBVDD1-supply = <&reg_aud_1v8>;
+ DBVDD2-supply = <&reg_aud_1v8>;
+ DBVDD3-supply = <&reg_aud_3v3>;
+ AVDD2-supply = <&reg_aud_1v8>;
+ CPVDD-supply = <&reg_aud_1v8>;
+ SPKVDD1-supply = <&reg_codec_5v>;
+ SPKVDD2-supply = <&reg_codec_5v>;
+
+ wlf,ldo1ena;
+ wlf,ldo2ena;
+ };
+};
+
+&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>, <24576000>;
+ status = "okay";
+};
+
+&sai1 {
+ assigned-clocks = <&clks IMX6UL_CLK_SAI1_SEL>,
+ <&clks IMX6UL_CLK_SAI1>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <24576000>;
+ status = "okay";
+};
+
+&mqs {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mqs>;
+ clocks = <&clks IMX6UL_CLK_SAI1>;
+ clock-names = "mclk";
+ status = "okay";
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif>;
+ assigned-clocks = <&clks IMX6UL_CLK_SPDIF_SEL>,
+ <&clks IMX6UL_CLK_SPDIF_PODF>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <0>, <49152000>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&usdhc1 {
+ no-1-8-v;
+ vmmc-supply = <>;
+ status = "disabled";
+};
+
+&usdhc2 {
+ no-1-8-v;
+};
+
+&wdog1 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2.dts b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2.dts
new file mode 100644
index 000000000000..fdd27eb717a8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-ddr3-arm2.dts
@@ -0,0 +1,1029 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx6ull.dtsi"
+
+/ {
+ model = "Freescale i.MX6 ULL DDR3 ARM2 Board";
+ compatible = "fsl,imx6ull-ddr3-arm2", "fsl,imx6ull";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "disabled";
+ };
+
+ 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_sd1_vmmc: sd1_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD1_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <20000>;
+ enable-active-high;
+ };
+
+ reg_sd2_vmmc: sd2_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD2_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can2_3v3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "can2-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 15 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_vref_3v3: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_usb_otg1_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&clks {
+ /* For bringup, comments this.
+ 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 = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&reg_soc {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+&csi {
+ status = "okay";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&ov5640_ep>;
+ };
+ };
+};
+
+&ecspi1 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio4 26 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_cs_1>;
+ status = "disabled";
+
+ flash: n25q032@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,n25q032";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&epdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc0>;
+ V3P3-supply = <&V3P3_reg>;
+ VCOM-supply = <&VCOM_reg>;
+ DISPLAY-supply = <&DISPLAY_reg>;
+ status = "disabled";
+};
+
+&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 = "mii";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+
+ ethphy1: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <2>;
+ };
+ };
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can2_3v3>;
+ status = "disabled";
+};
+
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0x1>;
+ fsl,cpu_pupscr_sw = <0x0>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <1>; /* use ldo-bypass, u-boot will check it and configure */
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "disabled";
+ nand-on-flash-bbt;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze200";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ 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-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+
+ ov5640: ov5640@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi1>;
+ clocks = <&clks IMX6UL_CLK_CSI>;
+ clock-names = "csi_mclk";
+ AVDD-supply = <&vgen3_reg>; /* 2.8v */
+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/
+ pwn-gpios = <&gpio5 8 1>;
+ rst-gpios = <&gpio5 7 0>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ status = "okay";
+ port {
+ ov5640_ep: endpoint {
+ remote-endpoint = <&csi1_ep>;
+ };
+ };
+ };
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ 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 = <&gpio3 16 0>;
+ gpio_pmic_vcom_ctrl = <&gpio3 24 0>;
+ gpio_pmic_wakeup = <&gpio3 14 0>;
+ gpio_pmic_v3p3 = <&gpio3 17 0>;
+ gpio_pmic_intr = <&gpio3 13 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";
+ };
+ };
+ };
+};
+
+&iomuxc {
+ imx6ul-ddr3-arm2 {
+ pinctrl_adc1: adc1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0xb0
+ MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
+ >;
+ };
+
+
+ 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_ecspi1_cs_1: ecspi1_cs_grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x10b0
+ >;
+ };
+
+ pinctrl_ecspi1_1: ecspi1grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x10b0
+ MX6UL_PAD_CSI_DATA07__ECSPI1_MISO 0x10b0
+ MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK 0x10b0
+ >;
+ };
+
+ 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 0x4001b0a0
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b098
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0a0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0a0
+ MX6UL_PAD_UART4_TX_DATA__ENET2_TDATA02 0x1b0a0
+ MX6UL_PAD_UART4_RX_DATA__ENET2_TDATA03 0x1b0a0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_TX_CLK 0x4001b0a8
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_UART3_TX_DATA__ENET2_RDATA02 0x1b0b0
+ MX6UL_PAD_UART3_RX_DATA__ENET2_RDATA03 0x1b0b0
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_UART3_CTS_B__ENET2_RX_CLK 0x4001b0a8
+ MX6UL_PAD_UART5_RX_DATA__ENET2_COL 0x1b0b0
+ MX6UL_PAD_UART5_TX_DATA__ENET2_CRS 0x1b0b0
+ >;
+ };
+
+ pinctrl_epdc0: epdcgrp0 {
+ fsl,pins = <
+ MX6UL_PAD_ENET2_RX_DATA0__EPDC_SDDO08 0x10b1
+ MX6UL_PAD_ENET2_RX_DATA1__EPDC_SDDO09 0x10b1
+ MX6UL_PAD_ENET2_RX_EN__EPDC_SDDO10 0x10b1
+ MX6UL_PAD_ENET2_TX_DATA0__EPDC_SDDO11 0x10b1
+ MX6UL_PAD_ENET2_TX_DATA1__EPDC_SDDO12 0x10b1
+ MX6UL_PAD_ENET2_TX_EN__EPDC_SDDO13 0x10b1
+ MX6UL_PAD_ENET2_TX_CLK__EPDC_SDDO14 0x10b1
+ MX6UL_PAD_ENET2_RX_ER__EPDC_SDDO15 0x10b1
+ MX6UL_PAD_LCD_CLK__EPDC_SDCLK 0x10b1
+ MX6UL_PAD_LCD_ENABLE__EPDC_SDLE 0x10b1
+ MX6UL_PAD_LCD_HSYNC__EPDC_SDOE 0x10b1
+ MX6UL_PAD_LCD_VSYNC__EPDC_SDCE0 0x10b1
+ MX6UL_PAD_LCD_DATA00__EPDC_SDDO00 0x10b1
+ MX6UL_PAD_LCD_DATA01__EPDC_SDDO01 0x10b1
+ MX6UL_PAD_LCD_DATA02__EPDC_SDDO02 0x10b1
+ MX6UL_PAD_LCD_DATA03__EPDC_SDDO03 0x10b1
+ MX6UL_PAD_LCD_DATA04__EPDC_SDDO04 0x10b1
+ MX6UL_PAD_LCD_DATA05__EPDC_SDDO05 0x10b1
+ MX6UL_PAD_LCD_DATA06__EPDC_SDDO06 0x10b1
+ MX6UL_PAD_LCD_DATA07__EPDC_SDDO07 0x10b1
+ MX6UL_PAD_LCD_DATA14__EPDC_SDSHR 0x10b1
+ MX6UL_PAD_LCD_DATA15__EPDC_GDRL 0x10b1
+ MX6UL_PAD_LCD_DATA16__EPDC_GDCLK 0x10b1
+ MX6UL_PAD_LCD_DATA17__EPDC_GDSP 0x10b1
+ MX6UL_PAD_LCD_RESET__EPDC_GDOE 0x10b1
+ >;
+ };
+
+ pinctrl_esai: esaigrp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_DATA00__ESAI_TX_HF_CLK 0x1b0b0
+ MX6UL_PAD_CSI_DATA01__ESAI_RX_HF_CLK 0x1b0b0
+ MX6UL_PAD_CSI_DATA04__ESAI_TX_FS 0x1b0b0
+ MX6UL_PAD_CSI_DATA05__ESAI_TX_CLK 0x1b0b0
+ MX6UL_PAD_CSI_DATA07__ESAI_T0 0x1b0b0
+ MX6UL_PAD_CSI_HSYNC__ESAI_TX1 0x1b0b0
+ MX6UL_PAD_CSI_PIXCLK__ESAI_TX2_RX3 0x1b0b0
+ MX6UL_PAD_CSI_MCLK__ESAI_TX3_RX2 0x1b0b0
+ MX6UL_PAD_CSI_DATA02__ESAI_RX_FS 0x1b0b0
+ MX6UL_PAD_CSI_DATA03__ESAI_RX_CLK 0x1b0b0
+ MX6UL_PAD_CSI_DATA06__ESAI_TX5_RX0 0x1b0b0
+ MX6UL_PAD_CSI_VSYNC__ESAI_TX4_RX1 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp{
+ fsl,pins = <
+ MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020
+ MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020
+ MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x17059 /* STBY */
+ >;
+ };
+
+ 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
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001b8b1
+ MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_TX_DATA__I2C4_SCL 0x4001b8b0
+ MX6UL_PAD_UART2_RX_DATA__I2C4_SDA 0x4001b8b0
+ >;
+ };
+
+ 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_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
+ MX6UL_PAD_LCD_RESET__LCDIF_RESET 0x79
+ >;
+ };
+
+ pinctrl_max17135: max17135grp-1 {
+ fsl,pins = <
+ MX6UL_PAD_LCD_DATA11__GPIO3_IO16 0x80000000 /* pwrgood */
+ MX6UL_PAD_LCD_DATA19__GPIO3_IO24 0x80000000 /* vcom_ctrl */
+ MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x80000000 /* wakeup */
+ MX6UL_PAD_LCD_DATA12__GPIO3_IO17 0x80000000 /* v3p3 */
+ MX6UL_PAD_LCD_DATA08__GPIO3_IO13 0x80000000 /* pwr int */
+ >;
+ };
+
+ pinctrl_mqs: mqsgrp {
+ fsl,pins = <
+ MX6UL_PAD_JTAG_TDI__MQS_LEFT 0x11088
+ MX6UL_PAD_JTAG_TDO__MQS_RIGHT 0x11088
+ >;
+ };
+
+ pinctrl_pwm1: pmw1grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_DATA0__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
+#ifdef REWORKED_ENABLE_ALL_QSPI
+ MX6UL_PAD_NAND_DATA07__QSPI_A_SS1_B 0x70a1
+ MX6UL_PAD_NAND_RE_B__QSPI_B_SCLK 0x70a1
+ MX6UL_PAD_NAND_DATA02__QSPI_B_DATA00 0x70a1
+ MX6UL_PAD_NAND_DATA03__QSPI_B_DATA01 0x70a1
+ MX6UL_PAD_NAND_DATA04__QSPI_B_DATA02 0x70a1
+ MX6UL_PAD_NAND_DATA05__QSPI_B_DATA03 0x70a1
+ MX6UL_PAD_NAND_WE_B__QSPI_B_SS0_B 0x70a1
+ MX6UL_PAD_NAND_DATA00__QSPI_B_SS1_B 0x70a1
+#endif
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_DATA0__SAI2_TX_SYNC 0x1b0b0
+ MX6UL_PAD_SD1_DATA1__SAI2_TX_BCLK 0x1b0b0
+ MX6UL_PAD_SD1_DATA2__SAI2_RX_DATA 0x110b0
+ MX6UL_PAD_SD1_DATA3__SAI2_TX_DATA 0x110b0
+ MX6UL_PAD_SD1_CLK__SAI2_MCLK 0x1b0b0
+ >;
+ };
+
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO08__SPDIF_OUT 0x1b0b0
+ MX6UL_PAD_GPIO1_IO09__SPDIF_IN 0x1b0b0
+ >;
+ };
+
+ 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_UART2_CTS_B__UART2_DCE_CTS 0x1b0b1
+ MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS 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_UART2_CTS_B__UART2_DTE_RTS 0x1b0b1
+ MX6UL_PAD_UART2_RTS_B__UART2_DTE_CTS 0x1b0b1
+ >;
+ };
+
+ pinctrl_usb_otg1_id: usbotg1idgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usb_otg1: usbotg1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x10b0
+ >;
+ };
+
+ 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_usdhc1_8bit: usdhc1_8bit_grp {
+ 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_NAND_READY_B__USDHC1_DATA4 0x17059
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x17059
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x17059
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1_8bit_100mhz: usdhc1_8bit_100mhz_grp {
+ 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
+ MX6UL_PAD_NAND_READY_B__USDHC1_DATA4 0x170b9
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x170b9
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x170b9
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc1_8bit_200mhz: usdhc1_8bit_200mhz_grp {
+ 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
+ MX6UL_PAD_NAND_READY_B__USDHC1_DATA4 0x170f9
+ MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5 0x170f9
+ MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6 0x170f9
+ MX6UL_PAD_NAND_CLE__USDHC1_DATA7 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc1_cd_wp: usdhc1_cd_wp_grp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */
+ MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x17059 /* SD1 WP */
+ >;
+ };
+
+ pinctrl_usdhc1_rst: usdhc1_rst_grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 /* SD1 RESET */
+ >;
+ };
+
+ pinctrl_usdhc1_vselect: usdhc1_vselect_grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10059
+ 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: usdhc2grp100mhz {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100a9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170a9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170a9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170a9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170a9
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
+ 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_usdhc2_rst: usdhc2_rst_grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x17059 /* SD2 RESET */
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO08__WDOG1_WDOG_B 0x30b0
+ >;
+ };
+ };
+};
+
+&iomuxc_snvs {
+ imx6ul-ddr3-arm2 {
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x80000000
+ MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x80000000
+ MX6ULL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x80000000
+ >;
+ };
+
+ pinctrl_sai2_hp_det_b: sai2_hp_det_grp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x17059
+ >;
+ };
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
+ display = <&display0>;
+ status = "disabled";
+
+ display0: display {
+ 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>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "disabled";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi>;
+ status = "okay";
+#ifdef REWORKED_ENABLE_ALL_QSPI
+ fsl,qspi-has-second-chip = <1>;
+#endif
+ 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>;
+ };
+
+#ifdef REWORKED_ENABLE_ALL_QSPI
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <1>;
+ };
+
+ flash2: n25q256a@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <2>;
+ };
+
+ flash3: n25q256a@3 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <3>;
+ };
+#endif
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2
+ &pinctrl_bt>;
+ fsl,uart-has-rtscts;
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart2dte>; */
+ status = "disabled";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_cd_wp>, <&pinctrl_usdhc1_rst>, <&pinctrl_usdhc1_vselect>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>, <&pinctrl_usdhc1_cd_wp>, <&pinctrl_usdhc1_rst>, <&pinctrl_usdhc1_vselect>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>, <&pinctrl_usdhc1_cd_wp>, <&pinctrl_usdhc1_rst>, <&pinctrl_usdhc1_vselect>;
+ cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_rst>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_rst>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_rst>;
+ non-removable;
+ no-1-8-v; /* VSELECT not connected by default */
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&reg_sd2_vmmc>;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
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..4ea3d91e2cb6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts
@@ -0,0 +1,19 @@
+/*
+ * 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"
+
+&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..924696ee6d7d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-gpmi-weim.dts
@@ -0,0 +1,49 @@
+/*
+ * 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"
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "okay";
+ nand-on-flash-bbt;
+};
+
+&iomuxc {
+ imx6ull-evk-gpmi-rework {
+ 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-usb-certi.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-usb-certi.dts
new file mode 100644
index 000000000000..15d9176fdd59
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-usb-certi.dts
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/* DTS file for USB Certification at i.mx6ull 14x14 evk board */
+
+#include "imx6ull-14x14-evk.dts"
+
+/ {
+ regulators {
+ reg_usb_otg2_vbus: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>; /* hardware rework is needed */
+ tpl-support;
+};
+
+&tsc {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk.dts b/arch/arm/boot/dts/imx6ull-14x14-evk.dts
new file mode 100644
index 000000000000..cd2a07671d62
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk.dts
@@ -0,0 +1,750 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx6ull.dtsi"
+
+/ {
+ model = "Freescale i.MX6 ULL 14x14 EVK Board";
+ compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x20000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ linux,cma-default;
+ };
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ 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_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 = <20000>;
+ enable-active-high;
+ };
+
+ 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>;
+ };
+ };
+
+ 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>;
+ };
+ };
+};
+
+&cpu0 {
+ dc-supply = <&reg_gpio_dvfs>;
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&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>;
+ };
+ };
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can_3v3>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_3v3>;
+ status = "okay";
+};
+
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0x1>;
+ fsl,cpu_pupscr_sw = <0x0>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <0>; /* DCDC, ldo-enable */
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ mag3110@0e {
+ 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>;
+ 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_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_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_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_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_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_usb_otg1_id: usbotg1idgrp {
+ 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 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
+ >;
+ };
+
+ 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 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
+ >;
+ };
+
+ 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
+ >;
+ };
+};
+
+&iomuxc_snvs {
+ pinctrl-names = "default_snvs";
+ pinctrl-0 = <&pinctrl_hog_2>;
+ imx6ul-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@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>;
+ };
+ };
+ };
+};
+
+&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 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ dr_mode = "otg";
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&usbphy1 {
+ tx-d-cal = <0x5>;
+};
+
+&usbphy2 {
+ tx-d-cal = <0x5>;
+};
+
+&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>;
+ non-removable;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
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..8f7c6f8926b6
--- /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 = <0x6000000>;
+ 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 = <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>;
+ };
+ };
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can_3v3>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_3v3>;
+ status = "okay";
+};
+
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0x1>;
+ 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@08 {
+ 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@0e {
+ 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-pinfunc-snvs.h b/arch/arm/boot/dts/imx6ull-pinfunc-snvs.h
new file mode 100644
index 000000000000..da3f412e4269
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-pinfunc-snvs.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef __DTS_IMX6ULL_PINFUNC_SNVS_H
+#define __DTS_IMX6ULL_PINFUNC_SNVS_H
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x0000 0x0044 0x0000 0x5 0x0
+#define MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x0004 0x0048 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x0008 0x004C 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x000C 0x0050 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x0010 0x0054 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x0014 0x0058 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x0018 0x005C 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x001C 0x0060 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x0020 0x0064 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x0024 0x0068 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x0028 0x006C 0x0000 0x5 0x0
+#define MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x002C 0x0070 0x0000 0x5 0x0
+
+#endif /* __DTS_IMX6ULL_PINFUNC_SNVS_H */
+
diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h b/arch/arm/boot/dts/imx6ull-pinfunc.h
new file mode 100644
index 000000000000..b788dac7e111
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-pinfunc.h
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#ifndef __DTS_IMX6ULL_PINFUNC_H
+#define __DTS_IMX6ULL_PINFUNC_H
+
+#include "imx6ul-pinfunc.h"
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6UL_PAD_ENET1_RX_DATA0__EPDC_SDCE04 0x00C4 0x0350 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET1_RX_DATA1__EPDC_SDCE05 0x00C8 0x0354 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET1_RX_EN__EPDC_SDCE06 0x00CC 0x0358 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET1_TX_DATA0__EPDC_SDCE07 0x00D0 0x035C 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET1_TX_DATA1__EPDC_SDCE08 0x00D4 0x0360 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET1_TX_EN__EPDC_SDCE09 0x00D8 0x0364 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET1_TX_CLK__EPDC_SDOED 0x00DC 0x0368 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET1_RX_ER__EPDC_SDOEZ 0x00E0 0x036C 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET2_RX_DATA0__EPDC_SDDO08 0x00E4 0x0370 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET2_RX_DATA1__EPDC_SDDO09 0x00E8 0x0374 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET2_RX_EN__EPDC_SDDO10 0x00EC 0x0378 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET2_TX_DATA0__EPDC_SDDO11 0x00F0 0x037C 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET2_TX_DATA1__EPDC_SDDO12 0x00F4 0x0380 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET2_TX_EN__EPDC_SDDO13 0x00F8 0x0384 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET2_TX_CLK__EPDC_SDDO14 0x00FC 0x0388 0x0000 0x9 0x0
+#define MX6UL_PAD_ENET2_RX_ER__EPDC_SDDO15 0x0100 0x038C 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_CLK__EPDC_SDCLK 0x0104 0x0390 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_ENABLE__EPDC_SDLE 0x0108 0x0394 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_HSYNC__EPDC_SDOE 0x010C 0x0398 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_VSYNC__EPDC_SDCE0 0x0110 0x039C 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_RESET__EPDC_GDOE 0x0114 0x03A0 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA00__EPDC_SDDO00 0x0118 0x03A4 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA01__EPDC_SDDO01 0x011C 0x03A8 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA02__EPDC_SDDO02 0x0120 0x03AC 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA03__EPDC_SDDO03 0x0124 0x03B0 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA04__EPDC_SDDO04 0x0128 0x03B4 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA05__EPDC_SDDO05 0x012C 0x03B8 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA06__EPDC_SDDO06 0x0130 0x03BC 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA07__EPDC_SDDO07 0x0134 0x03C0 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA14__EPDC_SDSHR 0x0150 0x03DC 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA15__EPDC_GDRL 0x0154 0x03E0 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA16__EPDC_GDCLK 0x0158 0x03E4 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA17__EPDC_GDSP 0x015C 0x03E8 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA21__EPDC_SDCE1 0x016C 0x03F8 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA22__EPDC_SDCE02 0x0170 0x03FC 0x0000 0x9 0x0
+#define MX6UL_PAD_LCD_DATA23__EPDC_SDCE03 0x0174 0x0400 0x0000 0x9 0x0
+
+#define MX6UL_PAD_CSI_MCLK__ESAI_TX3_RX2 0x01D4 0x0460 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_PIXCLK__ESAI_TX2_RX3 0x01D8 0x0464 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_VSYNC__ESAI_TX4_RX1 0x01DC 0x0468 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_HSYNC__ESAI_TX1 0x01E0 0x046C 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_DATA00__ESAI_TX_HF_CLK 0x01E4 0x0470 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_DATA01__ESAI_RX_HF_CLK 0x01E8 0x0474 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_DATA02__ESAI_RX_FS 0x01EC 0x0478 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_DATA03__ESAI_RX_CLK 0x01F0 0x047C 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_DATA04__ESAI_TX_FS 0x01F4 0x0480 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_DATA05__ESAI_TX_CLK 0x01F8 0x0484 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_DATA06__ESAI_TX5_RX0 0x01FC 0x0488 0x0000 0x9 0x0
+#define MX6UL_PAD_CSI_DATA07__ESAI_T0 0x0200 0x048C 0x0000 0x9 0x0
+
+#define MX6UL_PAD_UART1_TX_DATA__UART5_DCE_TX 0x0084 0x0310 0x0000 0x9 0x0
+#define MX6UL_PAD_UART1_TX_DATA__UART5_DTE_RX 0x0084 0x0310 0x0644 0x9 0x4
+#define MX6UL_PAD_UART1_RX_DATA__UART5_DCE_RX 0x0088 0x0314 0x0644 0x9 0x5
+#define MX6UL_PAD_UART1_RX_DATA__UART5_DTE_TX 0x0088 0x0314 0x0000 0x9 0x0
+#define MX6UL_PAD_UART1_CTS_B__UART5_DCE_CTS 0x008C 0x0318 0x0000 0x9 0x0
+#define MX6UL_PAD_UART1_CTS_B__UART5_DTE_RTS 0x008C 0x0318 0x0640 0x9 0x3
+#define MX6UL_PAD_UART1_RTS_B__UART5_DCE_RTS 0x0090 0x031C 0x0640 0x9 0x4
+#define MX6UL_PAD_UART1_RTS_B__UART5_DTE_CTS 0x0090 0x031C 0x0000 0x9 0x0
+#define MX6UL_PAD_UART4_RX_DATA__EPDC_PWRCTRL01 0x00B8 0x0344 0x0000 0x9 0x0
+#define MX6UL_PAD_UART5_TX_DATA__EPDC_PWRCTRL02 0x00BC 0x0348 0x0000 0x9 0x0
+#define MX6UL_PAD_UART5_RX_DATA__EPDC_PWRCTRL03 0x00C0 0x034C 0x0000 0x9 0x0
+
+/* Below pinfunc are different with i.MX6UL, so override them in here
+ * To avoid build warning, firstly undef them.
+ */
+#undef MX6UL_PAD_UART5_TX_DATA__UART5_DTE_RX
+#undef MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX
+#undef MX6UL_PAD_ENET1_RX_EN__UART5_DCE_RTS
+#undef MX6UL_PAD_ENET1_TX_DATA0__UART5_DTE_RTS
+#undef MX6UL_PAD_CSI_DATA02__UART5_DCE_RTS
+#define MX6UL_PAD_UART5_TX_DATA__UART5_DTE_RX 0x00BC 0x0348 0x0644 0x0 0x6
+#define MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x00C0 0x034C 0x0644 0x0 0x7
+#define MX6UL_PAD_ENET1_RX_EN__UART5_DCE_RTS 0x00CC 0x0358 0x0640 0x1 0x5
+#define MX6UL_PAD_ENET1_TX_DATA0__UART5_DTE_RTS 0x00D0 0x035C 0x0640 0x1 0x6
+#define MX6UL_PAD_CSI_DATA02__UART5_DCE_RTS 0x01EC 0x0478 0x0640 0x8 0x7
+
+#endif /* __DTS_IMX6UL_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/imx6ull.dtsi
new file mode 100644
index 000000000000..d4ab6495cdc1
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull.dtsi
@@ -0,0 +1,1187 @@
+/*
+ * Copyright 2015-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 <dt-bindings/clock/imx6ul-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "imx6ull-pinfunc.h"
+#include "imx6ull-pinfunc-snvs.h"
+#include "skeleton.dtsi"
+
+/ {
+ aliases {
+ can0 = &flexcan1;
+ can1 = &flexcan2;
+ ethernet0 = &fec1;
+ ethernet1 = &fec2;
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ gpio3 = &gpio4;
+ gpio4 = &gpio5;
+ i2c0 = &i2c1;
+ i2c1 = &i2c2;
+ i2c2 = &i2c3;
+ i2c3 = &i2c4;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ sai1 = &sai1;
+ sai2 = &sai2;
+ sai3 = &sai3;
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ serial4 = &uart5;
+ serial5 = &uart6;
+ serial6 = &uart7;
+ serial7 = &uart8;
+ spi0 = &ecspi1;
+ spi1 = &ecspi2;
+ spi2 = &ecspi3;
+ spi3 = &ecspi4;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0>;
+ clock-latency = <61036>; /* two CLK32 periods */
+ operating-points = <
+ /* kHz uV */
+ 900000 1275000
+ 792000 1225000
+ 528000 1175000
+ 396000 1025000
+ 198000 950000
+ >;
+ fsl,soc-operating-points = <
+ /* KHz uV */
+ 900000 1175000
+ 792000 1175000
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ fsl,low-power-run;
+ clocks = <&clks IMX6UL_CLK_ARM>,
+ <&clks IMX6UL_CLK_PLL2_BUS>,
+ <&clks IMX6UL_CLK_PLL2_PFD2>,
+ <&clks IMX6UL_CA7_SECONDARY_SEL>,
+ <&clks IMX6UL_CLK_STEP>,
+ <&clks IMX6UL_CLK_PLL1_SW>,
+ <&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_bypass", "pll1", "pll1_bypass_src", "osc";
+ arm-supply = <&reg_arm>;
+ soc-supply = <&reg_soc>;
+ };
+ };
+
+ intc: interrupt-controller@00a01000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a02000 0x100>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil: clock@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "ckil";
+ };
+
+ osc: clock@1 {
+ compatible = "fixed-clock";
+ reg = <1>;
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc";
+ };
+
+ ipp_di0: clock@2 {
+ compatible = "fixed-clock";
+ reg = <2>;
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di0";
+ };
+
+ ipp_di1: clock@3 {
+ compatible = "fixed-clock";
+ reg = <3>;
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di1";
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gpc>;
+ ranges;
+
+ 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>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ ocrams: sram@00900000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x00900000 0x4000>;
+ };
+
+ ocrams_ddr: sram@00904000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x00904000 0x1000>;
+ };
+
+ ocram: sram@00905000 {
+ compatible = "mmio-sram";
+ reg = <0x00905000 0x1B000>;
+ };
+
+ dma_apbh: dma-apbh@01804000 {
+ compatible = "fsl,imx6ul-dma-apbh", "fsl,imx28-dma-apbh";
+ reg = <0x01804000 0x2000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
+ #dma-cells = <1>;
+ dma-channels = <4>;
+ clocks = <&clks IMX6UL_CLK_APBHDMA>;
+ };
+
+ gpmi: gpmi-nand@01806000{
+ compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x01806000 0x2000>, <0x01808000 0x4000>;
+ reg-names = "gpmi-nand", "bch";
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "bch";
+ clocks = <&clks IMX6UL_CLK_GPMI_IO>,
+ <&clks IMX6UL_CLK_GPMI_APB>,
+ <&clks IMX6UL_CLK_GPMI_BCH>,
+ <&clks IMX6UL_CLK_GPMI_BCH_APB>,
+ <&clks IMX6UL_CLK_PER_BCH>;
+ clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
+ "gpmi_bch_apb", "per1_bch";
+ dmas = <&dma_apbh 0>;
+ dma-names = "rx-tx";
+ status = "disabled";
+ };
+
+ aips1: aips-bus@02000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x100000>;
+ ranges;
+
+ spba-bus@02000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x40000>;
+ ranges;
+
+ spdif: spdif@02004000 {
+ compatible = "fsl,imx6ul-spdif", "fsl,imx35-spdif";
+ reg = <0x02004000 0x4000>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 41 18 0>,
+ <&sdma 42 18 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6UL_CLK_SPDIF_GCLK>,
+ <&clks IMX6UL_CLK_OSC>,
+ <&clks IMX6UL_CLK_SPDIF>,
+ <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_IPG>,
+ <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_SPBA>;
+ clock-names = "core", "rxtx0",
+ "rxtx1", "rxtx2",
+ "rxtx3", "rxtx4",
+ "rxtx5", "rxtx6",
+ "rxtx7", "spba";
+ status = "disabled";
+ };
+
+ ecspi1: ecspi@02008000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02008000 0x4000>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ECSPI1>,
+ <&clks IMX6UL_CLK_ECSPI1>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ ecspi2: ecspi@0200c000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x0200c000 0x4000>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ECSPI2>,
+ <&clks IMX6UL_CLK_ECSPI2>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ ecspi3: ecspi@02010000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02010000 0x4000>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ECSPI3>,
+ <&clks IMX6UL_CLK_ECSPI3>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ ecspi4: ecspi@02014000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02014000 0x4000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ECSPI4>,
+ <&clks IMX6UL_CLK_ECSPI4>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart7: serial@02018000 {
+ compatible = "fsl,imx6ul-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02018000 0x4000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_UART7_IPG>,
+ <&clks IMX6UL_CLK_UART7_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 43 4 0>, <&sdma 44 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart1: serial@02020000 {
+ compatible = "fsl,imx6ul-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02020000 0x4000>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_UART1_IPG>,
+ <&clks IMX6UL_CLK_UART1_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ esai: esai@02024000 {
+ compatible = "fsl,imx6ull-esai";
+ reg = <0x02024000 0x4000>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ESAI_IPG>,
+ <&clks IMX6UL_CLK_ESAI_MEM>,
+ <&clks IMX6UL_CLK_ESAI_EXTAL>,
+ <&clks IMX6UL_CLK_ESAI_IPG>,
+ <&clks IMX6UL_CLK_SPBA>;
+ clock-names = "core", "mem", "extal",
+ "fsys", "spba";
+ dmas = <&sdma 0 21 0>, <&sdma 47 21 0>;
+ dma-names = "rx", "tx";
+ dma-source = <&gpr 0 14 0 15>;
+ status = "disabled";
+ };
+
+ sai1: sai@02028000 {
+ #sound-dai-cells = <0>;
+ compatible = "fsl,imx6ul-sai",
+ "fsl,imx6sx-sai";
+ reg = <0x02028000 0x4000>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_SAI1_IPG>,
+ <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_SAI1>,
+ <&clks 0>, <&clks 0>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx", "tx";
+ dmas = <&sdma 35 24 0>, <&sdma 36 24 0>;
+ status = "disabled";
+ };
+
+ sai2: sai@0202c000 {
+ #sound-dai-cells = <0>;
+ compatible = "fsl,imx6ul-sai",
+ "fsl,imx6sx-sai";
+ reg = <0x0202c000 0x4000>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_SAI2_IPG>,
+ <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_SAI2>,
+ <&clks 0>, <&clks 0>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx", "tx";
+ dmas = <&sdma 37 24 0>, <&sdma 38 24 0>;
+ status = "disabled";
+ };
+
+ sai3: sai@02030000 {
+ #sound-dai-cells = <0>;
+ compatible = "fsl,imx6ul-sai",
+ "fsl,imx6sx-sai";
+ reg = <0x02030000 0x4000>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_SAI3_IPG>,
+ <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_SAI3>,
+ <&clks 0>, <&clks 0>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx", "tx";
+ dmas = <&sdma 39 24 0>, <&sdma 40 24 0>;
+ status = "disabled";
+ };
+
+ asrc: asrc@02034000 {
+ compatible = "fsl,imx53-asrc";
+ reg = <0x02034000 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@02040000 {
+ compatible = "fsl,imx6ul-tsc";
+ reg = <0x02040000 0x4000>, <0x0219c000 0x4000>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_IPG>,
+ <&clks IMX6UL_CLK_ADC2>;
+ clock-names = "tsc", "adc";
+ status = "disabled";
+ };
+
+ pwm1: pwm@02080000 {
+ compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
+ reg = <0x02080000 0x4000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PWM1>,
+ <&clks IMX6UL_CLK_PWM1>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm2: pwm@02084000 {
+ compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
+ reg = <0x02084000 0x4000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PWM2>,
+ <&clks IMX6UL_CLK_PWM2>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm3: pwm@02088000 {
+ compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
+ reg = <0x02088000 0x4000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PWM3>,
+ <&clks IMX6UL_CLK_PWM3>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm4: pwm@0208c000 {
+ compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
+ reg = <0x0208c000 0x4000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PWM4>,
+ <&clks IMX6UL_CLK_PWM4>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ flexcan1: can@02090000 {
+ compatible = "fsl,imx6ul-flexcan", "fsl,imx6q-flexcan";
+ reg = <0x02090000 0x4000>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_CAN1_IPG>,
+ <&clks IMX6UL_CLK_CAN1_SERIAL>;
+ clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x10 1 0x10 17>;
+ status = "disabled";
+ };
+
+ flexcan2: can@02094000 {
+ compatible = "fsl,imx6ul-flexcan", "fsl,imx6q-flexcan";
+ reg = <0x02094000 0x4000>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_CAN2_IPG>,
+ <&clks IMX6UL_CLK_CAN2_SERIAL>;
+ clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x10 2 0x10 18>;
+ status = "disabled";
+ };
+
+ gpt1: gpt@02098000 {
+ compatible = "fsl,imx6ul-gpt", "fsl,imx31-gpt";
+ reg = <0x02098000 0x4000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_GPT1_BUS>,
+ <&clks IMX6UL_CLK_GPT_3M>;
+ clock-names = "ipg", "osc_per";
+ };
+
+ gpio1: gpio@0209c000 {
+ compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
+ reg = <0x0209c000 0x4000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio@020a0000 {
+ compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
+ reg = <0x020a0000 0x4000>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio@020a4000 {
+ compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
+ reg = <0x020a4000 0x4000>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio4: gpio@020a8000 {
+ compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
+ reg = <0x020a8000 0x4000>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio5: gpio@020ac000 {
+ compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
+ reg = <0x020ac000 0x4000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ snvslp: snvs@020b0000 {
+ compatible = "fsl,imx6ul-snvs";
+ reg = <0x020b0000 0x4000>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ fec2: ethernet@020b4000 {
+ compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
+ reg = <0x020b4000 0x4000>;
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ENET>,
+ <&clks IMX6UL_CLK_ENET_AHB>,
+ <&clks IMX6UL_CLK_ENET_PTP>,
+ <&clks IMX6UL_CLK_ENET2_REF_125M>,
+ <&clks IMX6UL_CLK_ENET2_REF_125M>;
+ clock-names = "ipg", "ahb", "ptp",
+ "enet_clk_ref", "enet_out";
+ stop-mode = <&gpr 0x10 4>;
+ fsl,num-tx-queues=<1>;
+ fsl,num-rx-queues=<1>;
+ fsl,magic-packet;
+ fsl,wakeup_irq = <0>;
+ status = "disabled";
+ };
+
+ kpp: kpp@020b8000 {
+ compatible = "fsl,imx6ul-kpp", "fsl,imx21-kpp";
+ reg = <0x020b8000 0x4000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>;
+ status = "disabled";
+ };
+
+ wdog1: wdog@020bc000 {
+ compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt";
+ reg = <0x020bc000 0x4000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_WDOG1>;
+ };
+
+ wdog2: wdog@020c0000 {
+ compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt";
+ reg = <0x020c0000 0x4000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_WDOG2>;
+ status = "disabled";
+ };
+
+ clks: ccm@020c4000 {
+ compatible = "fsl,imx6ul-ccm";
+ reg = <0x020c4000 0x4000>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ #clock-cells = <1>;
+ clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
+ clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
+ };
+
+ anatop: anatop@020c8000 {
+ compatible = "fsl,imx6ul-anatop", "fsl,imx6q-anatop",
+ "syscon", "simple-bus";
+ reg = <0x020c8000 0x1000>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+
+ reg_3p0: regulator-3p0@120 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vdd3p0";
+ regulator-min-microvolt = <2625000>;
+ regulator-max-microvolt = <3400000>;
+ anatop-reg-offset = <0x120>;
+ anatop-vol-bit-shift = <8>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <0>;
+ anatop-min-voltage = <2625000>;
+ anatop-max-voltage = <3400000>;
+ anatop-enable-bit = <0>;
+ };
+
+ reg_arm: regulator-vddcore@140 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "cpu";
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1450000>;
+ regulator-always-on;
+ anatop-reg-offset = <0x140>;
+ anatop-vol-bit-shift = <0>;
+ anatop-vol-bit-width = <5>;
+ anatop-delay-reg-offset = <0x170>;
+ anatop-delay-bit-shift = <24>;
+ anatop-delay-bit-width = <2>;
+ anatop-min-bit-val = <1>;
+ anatop-min-voltage = <725000>;
+ anatop-max-voltage = <1450000>;
+ };
+
+ reg_soc: regulator-vddsoc@140 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vddsoc";
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1450000>;
+ regulator-always-on;
+ anatop-reg-offset = <0x140>;
+ anatop-vol-bit-shift = <18>;
+ anatop-vol-bit-width = <5>;
+ anatop-delay-reg-offset = <0x170>;
+ anatop-delay-bit-shift = <28>;
+ anatop-delay-bit-width = <2>;
+ anatop-min-bit-val = <1>;
+ anatop-min-voltage = <725000>;
+ anatop-max-voltage = <1450000>;
+ };
+ };
+
+ usbphy1: usbphy@020c9000 {
+ compatible = "fsl,imx6ul-usbphy", "fsl,imx23-usbphy";
+ reg = <0x020c9000 0x1000>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_USBPHY1>;
+ phy-3p0-supply = <&reg_3p0>;
+ fsl,anatop = <&anatop>;
+ };
+
+ usbphy2: usbphy@020ca000 {
+ compatible = "fsl,imx6ul-usbphy", "fsl,imx23-usbphy";
+ reg = <0x020ca000 0x1000>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_USBPHY2>;
+ phy-3p0-supply = <&reg_3p0>;
+ fsl,anatop = <&anatop>;
+ };
+
+ tempmon: tempmon {
+ compatible = "fsl,imx6ul-tempmon", "fsl,imx6sx-tempmon";
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,tempmon = <&anatop>;
+ fsl,tempmon-data = <&ocotp>;
+ clocks = <&clks IMX6UL_CLK_PLL3_USB_OTG>;
+ };
+
+ snvs: snvs@020cc000 {
+ compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
+ reg = <0x020cc000 0x4000>;
+
+ snvs_rtc: snvs-rtc-lp {
+ compatible = "fsl,sec-v4.0-mon-rtc-lp";
+ regmap = <&snvs>;
+ offset = <0x34>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ snvs_poweroff: snvs-poweroff {
+ compatible = "syscon-poweroff";
+ regmap = <&snvs>;
+ offset = <0x38>;
+ mask = <0x61>;
+ };
+
+ snvs_pwrkey: snvs-powerkey {
+ compatible = "fsl,sec-v4.0-pwrkey";
+ regmap = <&snvs>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ linux,keycode = <KEY_POWER>;
+ wakeup-source;
+ };
+ };
+
+ epit1: epit@020d0000 {
+ reg = <0x020d0000 0x4000>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ epit2: epit@020d4000 {
+ reg = <0x020d4000 0x4000>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ src: src@020d8000 {
+ compatible = "fsl,imx6ul-src", "fsl,imx51-src";
+ reg = <0x020d8000 0x4000>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ #reset-cells = <1>;
+ };
+
+ gpc: gpc@020dc000 {
+ compatible = "fsl,imx6ul-gpc", "fsl,imx6q-gpc";
+ reg = <0x020dc000 0x4000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&intc>;
+ fsl,mf-mix-wakeup-irq = <0xfc00000 0x7d00 0x0 0x1400640>;
+ };
+
+ iomuxc: iomuxc@020e0000 {
+ compatible = "fsl,imx6ul-iomuxc";
+ reg = <0x020e0000 0x4000>;
+ };
+
+ gpr: iomuxc-gpr@020e4000 {
+ compatible = "fsl,imx6ul-iomuxc-gpr",
+ "fsl,imx6q-iomuxc-gpr", "syscon";
+ reg = <0x020e4000 0x4000>;
+ };
+
+ mqs: mqs {
+ compatible = "fsl,imx6sx-mqs";
+ gpr = <&gpr>;
+ status = "disabled";
+ };
+
+ gpt2: gpt@020e8000 {
+ compatible = "fsl,imx6ul-gpt", "fsl,imx31-gpt";
+ reg = <0x020e8000 0x4000>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "ipg", "per";
+ };
+
+ sdma: sdma@020ec000 {
+ compatible = "fsl,imx6ul-sdma", "fsl,imx35-sdma";
+ reg = <0x020ec000 0x4000>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_SDMA>,
+ <&clks IMX6UL_CLK_SDMA>;
+ clock-names = "ipg", "ahb";
+ #dma-cells = <3>;
+ iram = <&ocram>;
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
+ };
+
+ pwm5: pwm@020f0000 {
+ compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
+ reg = <0x020f0000 0x4000>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PWM5>,
+ <&clks IMX6UL_CLK_PWM5>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm6: pwm@020f4000 {
+ compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
+ reg = <0x020f4000 0x4000>;
+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PWM6>,
+ <&clks IMX6UL_CLK_PWM6>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm7: pwm@020f8000 {
+ compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
+ reg = <0x020f8000 0x4000>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PWM7>,
+ <&clks IMX6UL_CLK_PWM7>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm8: pwm@020fc000 {
+ compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
+ reg = <0x020fc000 0x4000>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_PWM8>,
+ <&clks IMX6UL_CLK_PWM8>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+ };
+
+ aips2: aips-bus@02100000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02100000 0x100000>;
+ ranges;
+
+ usbotg1: usb@02184000 {
+ compatible = "fsl,imx6ul-usb", "fsl,imx27-usb";
+ reg = <0x02184000 0x200>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_USBOH3>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc 0>;
+ fsl,anatop = <&anatop>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+ status = "disabled";
+ };
+
+ usbotg2: usb@02184200 {
+ compatible = "fsl,imx6ul-usb", "fsl,imx27-usb";
+ reg = <0x02184200 0x200>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_USBOH3>;
+ fsl,usbphy = <&usbphy2>;
+ fsl,usbmisc = <&usbmisc 1>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+ status = "disabled";
+ };
+
+ usbmisc: usbmisc@02184800 {
+ #index-cells = <1>;
+ compatible = "fsl,imx6ul-usbmisc", "fsl,imx6q-usbmisc";
+ reg = <0x02184800 0x200>;
+ };
+
+ fec1: ethernet@02188000 {
+ compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
+ reg = <0x02188000 0x4000>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ENET>,
+ <&clks IMX6UL_CLK_ENET_AHB>,
+ <&clks IMX6UL_CLK_ENET_PTP>,
+ <&clks IMX6UL_CLK_ENET_REF>,
+ <&clks IMX6UL_CLK_ENET_REF>;
+ clock-names = "ipg", "ahb", "ptp",
+ "enet_clk_ref", "enet_out";
+ stop-mode = <&gpr 0x10 3>;
+ fsl,num-tx-queues=<1>;
+ fsl,num-rx-queues=<1>;
+ fsl,magic-packet;
+ fsl,wakeup_irq = <0>;
+ status = "disabled";
+ };
+
+ usdhc1: usdhc@02190000 {
+ compatible = "fsl,imx6ull-usdhc", "fsl,imx6sx-usdhc";
+ reg = <0x02190000 0x4000>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_USDHC1>,
+ <&clks IMX6UL_CLK_USDHC1>,
+ <&clks IMX6UL_CLK_USDHC1>;
+ clock-names = "ipg", "ahb", "per";
+ assigned-clocks = <&clks IMX6UL_CLK_USDHC1_SEL>, <&clks IMX6UL_CLK_USDHC1>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL2_PFD2>;
+ assigned-clock-rates = <0>, <132000000>;
+ bus-width = <4>;
+ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+ usdhc2: usdhc@02194000 {
+ compatible = "fsl,imx6ull-usdhc", "fsl,imx6sx-usdhc";
+ reg = <0x02194000 0x4000>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_USDHC2>,
+ <&clks IMX6UL_CLK_USDHC2>,
+ <&clks IMX6UL_CLK_USDHC2>;
+ clock-names = "ipg", "ahb", "per";
+ assigned-clocks = <&clks IMX6UL_CLK_USDHC2_SEL>, <&clks IMX6UL_CLK_USDHC2>;
+ assigned-clock-parents = <&clks IMX6UL_CLK_PLL2_PFD2>;
+ assigned-clock-rates = <0>, <132000000>;
+ bus-width = <4>;
+ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+ adc1: adc@02198000 {
+ compatible = "fsl,imx6ul-adc", "fsl,vf610-adc";
+ reg = <0x02198000 0x4000>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_ADC1>;
+ num-channels = <2>;
+ clock-names = "adc";
+ status = "disabled";
+ };
+
+ i2c1: i2c@021a0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
+ reg = <0x021a0000 0x4000>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_I2C1>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@021a4000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
+ reg = <0x021a4000 0x4000>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_I2C2>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@021a8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
+ reg = <0x021a8000 0x4000>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_I2C3>;
+ status = "disabled";
+ };
+
+ romcp@021ac000 {
+ compatible = "fsl,imx6ul-romcp", "syscon";
+ reg = <0x021ac000 0x4000>;
+ };
+
+ mmdc: mmdc@021b0000 {
+ compatible = "fsl,imx6ul-mmdc", "fsl,imx6q-mmdc";
+ reg = <0x021b0000 0x4000>;
+ };
+
+ weim: weim@021b8000 {
+ compatible = "fsl,imx6ul-weim", "fsl,imx6q-weim";
+ reg = <0x021b8000 0x4000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>;
+ };
+
+ ocotp: ocotp-ctrl@021bc000 {
+ compatible = "fsl,imx6ull-ocotp", "syscon";
+ reg = <0x021bc000 0x4000>;
+ clocks = <&clks IMX6UL_CLK_OCOTP>;
+ };
+
+ csu: csu@021c0000 {
+ compatible = "fsl,imx6ul-csu";
+ reg = <0x021c0000 0x4000>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ csi: csi@021c4000 {
+ compatible = "fsl,imx6ul-csi", "fsl,imx6s-csi";
+ reg = <0x021c4000 0x4000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>,
+ <&clks IMX6UL_CLK_CSI>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+ status = "disabled";
+ };
+
+ lcdif: lcdif@021c8000 {
+ compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
+ reg = <0x021c8000 0x4000>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,
+ <&clks IMX6UL_CLK_LCDIF_APB>,
+ <&clks IMX6UL_CLK_DUMMY>;
+ clock-names = "pix", "axi", "disp_axi";
+ status = "disabled";
+ };
+
+ pxp: pxp@021cc000 {
+ compatible = "fsl,imx6ull-pxp-dma", "fsl,imx7d-pxp-dma";
+ reg = <0x021cc000 0x4000>;
+ interrupts = <GIC_SPI 8 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";
+ };
+
+ qspi: qspi@021e0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ull-qspi", "fsl,imx6ul-qspi";
+ reg = <0x021e0000 0x4000>, <0x60000000 0x10000000>;
+ reg-names = "QuadSPI", "QuadSPI-memory";
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_QSPI>,
+ <&clks IMX6UL_CLK_QSPI>;
+ clock-names = "qspi_en", "qspi";
+ status = "disabled";
+ };
+
+ uart2: serial@021e8000 {
+ compatible = "fsl,imx6ul-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021e8000 0x4000>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_UART2_IPG>,
+ <&clks IMX6UL_CLK_UART2_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart3: serial@021ec000 {
+ compatible = "fsl,imx6ul-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021ec000 0x4000>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_UART3_IPG>,
+ <&clks IMX6UL_CLK_UART3_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart4: serial@021f0000 {
+ compatible = "fsl,imx6ul-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021f0000 0x4000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_UART4_IPG>,
+ <&clks IMX6UL_CLK_UART4_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart5: serial@021f4000 {
+ compatible = "fsl,imx6ul-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021f4000 0x4000>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_UART5_IPG>,
+ <&clks IMX6UL_CLK_UART5_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ i2c4: i2c@021f8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
+ reg = <0x021f8000 0x4000>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_I2C4>;
+ status = "disabled";
+ };
+
+ uart6: serial@021fc000 {
+ compatible = "fsl,imx6ul-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021fc000 0x4000>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_UART6_IPG>,
+ <&clks IMX6UL_CLK_UART6_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 0 4 0>, <&sdma 47 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+ };
+
+ aips3: aips-bus@02200000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02200000 0x100000>;
+ ranges;
+
+ dcp: dcp@02280000 {
+ compatible = "fsl,imx6sl-dcp";
+ reg = <0x02280000 0x4000>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DCP_CLK>;
+ clock-names = "dcp";
+ };
+
+ rngb: rngb@02284000 {
+ compatible = "fsl,imx6sl-rng", "fsl,imx-rng", "imx-rng";
+ reg = <0x02284000 0x4000>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_DUMMY>;
+ };
+
+ uart8: serial@02288000 {
+ compatible = "fsl,imx6ul-uart",
+ "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02288000 0x4000>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_UART8_IPG>,
+ <&clks IMX6UL_CLK_UART8_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 45 4 0>, <&sdma 46 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ epdc: epdc@0228c000 {
+ compatible = "fsl,imx7d-epdc";
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0228c000 0x4000>;
+ clocks = <&clks IMX6UL_CLK_EPDC_ACLK>,
+ <&clks IMX6UL_CLK_EPDC_PIX>;
+ clock-names = "epdc_axi", "epdc_pix";
+ /* Need to fix epdc-ram */
+ /* epdc-ram = <&gpr 0x4 30>; */
+ status = "disabled";
+ };
+
+ iomuxc_snvs: iomuxc-snvs@02290000 {
+ compatible = "fsl,imx6ull-iomuxc-snvs";
+ reg = <0x02290000 0x10000>;
+ };
+
+ snvs_gpr: snvs-gpr@0x02294000 {
+ compatible = "fsl, imx6ull-snvs-gpr";
+ reg = <0x02294000 0x10000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-ddr3-arm2.dts b/arch/arm/boot/dts/imx7d-12x12-ddr3-arm2.dts
new file mode 100644
index 000000000000..8626f3b50fb3
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-ddr3-arm2.dts
@@ -0,0 +1,558 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx7d.dtsi"
+
+/ {
+ model = "Freescale i.MX7 DDR3 12x12 ARM2 Board";
+ compatible = "fsl,imx7d-12x12-ddr3-arm2", "fsl,imx7d";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio3 17 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio3 18 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_sd3_vmmc: sd3_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_SD3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio6 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 = <&gpio4 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 = <&gpio4 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_can1_3v3: can1-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "can1-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 2 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 3 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ memory {
+ reg = <0x80000000 0x80000000>;
+ };
+};
+
+&adc1 {
+ vref-supply = <&reg_vref_1v8>;
+ status = "okay";
+};
+
+&cpu0 {
+ arm-supply = <&sw1a_reg>;
+};
+
+&ecspi4 {
+ fsl,spi-num-chipselects = <4>;
+ cs-gpios = <&gpio5 3 0>, <&gpio5 4 0>, <&gpio5 5 0>, <&gpio5 6 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi4_1 &pinctrl_ecspi4_cs_1>;
+ status = "disabled";
+
+ flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,m25p32";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&epxp {
+ status = "okay";
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can1_3v3>;
+ status = "disabled";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can2_3v3>;
+ status = "disabled";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_1>;
+ status = "okay";
+
+ pmic: pfuze3000@08 {
+ 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 = <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";
+ pinctrl-0 = <&pinctrl_i2c3_1>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+
+ imx7d-12x12-ddr3-arm2 {
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO14__GPIO1_IO14 0x59
+ MX7D_PAD_GPIO1_IO15__GPIO1_IO15 0x59
+ MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x59
+ >;
+ };
+
+ pinctrl_ecspi4_cs_1: ecspi4_cs_grp-1 {
+ fsl,pins = <
+ MX7D_PAD_SD1_CLK__GPIO5_IO3 0x2
+ MX7D_PAD_SD1_CMD__GPIO5_IO4 0x2
+ MX7D_PAD_SD1_DATA0__GPIO5_IO5 0x2
+ MX7D_PAD_SD1_DATA1__GPIO5_IO6 0x2
+ >;
+ };
+
+ pinctrl_ecspi4_1: ecspi4grp-1 {
+ fsl,pins = <
+ MX7D_PAD_SD1_RESET_B__ECSPI4_SCLK 0x2
+ MX7D_PAD_SD1_WP__ECSPI4_MOSI 0x2
+ MX7D_PAD_SD1_CD_B__ECSPI4_MISO 0x2
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX7D_PAD_SD3_DATA5__FLEXCAN1_TX 0x59
+ MX7D_PAD_SD3_DATA7__FLEXCAN1_RX 0x59
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX7D_PAD_SD3_DATA6__FLEXCAN2_TX 0x59
+ MX7D_PAD_SD3_DATA4__FLEXCAN2_RX 0x59
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX7D_PAD_LCD_DATA12__GPIO3_IO17 0x32
+ MX7D_PAD_LCD_DATA13__GPIO3_IO18 0x32
+ >;
+ };
+
+ pinctrl_i2c3_1: i2c3grp-1 {
+ fsl,pins = <
+ MX7D_PAD_ENET1_RGMII_RD0__I2C3_SCL 0x4000007f
+ MX7D_PAD_ENET1_RGMII_RD1__I2C3_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c4_1: i2c4grp-1 {
+ fsl,pins = <
+ MX7D_PAD_ENET1_RGMII_TD2__I2C4_SCL 0x4000007f
+ MX7D_PAD_ENET1_RGMII_TD3__I2C4_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA00__LCD_DATA0 0x4001b0b0
+ MX7D_PAD_EPDC_DATA01__LCD_DATA1 0x4001b0b0
+ MX7D_PAD_EPDC_DATA02__LCD_DATA2 0x4001b0b0
+ MX7D_PAD_EPDC_DATA03__LCD_DATA3 0x4001b0b0
+ MX7D_PAD_EPDC_DATA04__LCD_DATA4 0x4001b0b0
+ MX7D_PAD_EPDC_DATA05__LCD_DATA5 0x4001b0b0
+ MX7D_PAD_EPDC_DATA06__LCD_DATA6 0x4001b0b0
+ MX7D_PAD_EPDC_DATA07__LCD_DATA7 0x4001b0b0
+ MX7D_PAD_EPDC_DATA08__LCD_DATA8 0x4001b0b0
+ MX7D_PAD_EPDC_DATA09__LCD_DATA9 0x4001b0b0
+ MX7D_PAD_EPDC_DATA10__LCD_DATA10 0x4001b0b0
+ MX7D_PAD_EPDC_DATA11__LCD_DATA11 0x4001b0b0
+ MX7D_PAD_EPDC_DATA12__LCD_DATA12 0x4001b0b0
+ MX7D_PAD_EPDC_DATA13__LCD_DATA13 0x4001b0b0
+ MX7D_PAD_EPDC_DATA14__LCD_DATA14 0x4001b0b0
+ MX7D_PAD_EPDC_DATA15__LCD_DATA15 0x4001b0b0
+ MX7D_PAD_EPDC_SDLE__LCD_DATA16 0x4001b0b0
+ MX7D_PAD_EPDC_SDOE__LCD_DATA17 0x4001b0b0
+ MX7D_PAD_EPDC_SDSHR__LCD_DATA18 0x4001b0b0
+ MX7D_PAD_EPDC_SDCE0__LCD_DATA19 0x4001b0b0
+ MX7D_PAD_EPDC_SDCE1__LCD_DATA20 0x4001b0b0
+ MX7D_PAD_EPDC_SDCE2__LCD_DATA21 0x4001b0b0
+ MX7D_PAD_EPDC_SDCE3__LCD_DATA22 0x4001b0b0
+ MX7D_PAD_EPDC_GDCLK__LCD_DATA23 0x4001b0b0
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX7D_PAD_EPDC_SDCLK__LCD_CLK 0x4001b0b0
+ MX7D_PAD_EPDC_BDR1__LCD_ENABLE 0x4001b0b0
+ MX7D_PAD_EPDC_PWR_STAT__LCD_VSYNC 0x4001b0b0
+ MX7D_PAD_EPDC_PWR_COM__LCD_HSYNC 0x4001b0b0
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO08__PWM1_OUT 0x110b0
+ >;
+ };
+
+ 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_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
+ MX7D_PAD_ECSPI1_SCLK__SD2_DATA4 0x59
+ MX7D_PAD_ECSPI1_MOSI__SD2_DATA5 0x59
+ MX7D_PAD_ECSPI1_MISO__SD2_DATA6 0x59
+ MX7D_PAD_ECSPI1_SS0__SD2_DATA7 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
+ MX7D_PAD_ECSPI1_SCLK__SD2_DATA4 0x5a
+ MX7D_PAD_ECSPI1_MOSI__SD2_DATA5 0x5a
+ MX7D_PAD_ECSPI1_MISO__SD2_DATA6 0x5a
+ MX7D_PAD_ECSPI1_SS0__SD2_DATA7 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
+ MX7D_PAD_ECSPI1_SCLK__SD2_DATA4 0x5b
+ MX7D_PAD_ECSPI1_MOSI__SD2_DATA5 0x5b
+ MX7D_PAD_ECSPI1_MISO__SD2_DATA6 0x5b
+ MX7D_PAD_ECSPI1_SS0__SD2_DATA7 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
+ >;
+ };
+ };
+};
+
+&iomuxc_lpsr {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_2>;
+
+ imx7d-12x12-ddr3-arm2 {
+ pinctrl_hog_2: hoggrp-2 {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO02__GPIO1_IO2 0x59 /* flexcan stby1 */
+ MX7D_PAD_GPIO1_IO03__GPIO1_IO3 0x59 /* flexcan stby2 */
+ MX7D_PAD_GPIO1_IO01__ANATOP_24M_OUT 0x80000000
+ >;
+ };
+
+ pinctrl_i2c1_1: i2c1grp-1 {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO04__I2C1_SCL 0x4000007f
+ MX7D_PAD_GPIO1_IO05__I2C1_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c2_1: i2c2grp-1 {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO06__I2C2_SCL 0x4000007f
+ MX7D_PAD_GPIO1_IO07__I2C2_SDA 0x4000007f
+ >;
+ };
+ };
+};
+
+&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 = <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>;
+ };
+ };
+ };
+};
+
+&sdma {
+ status = "okay";
+};
+
+&pcie {
+ pinctrl-names = "default";
+ status = "disabled";
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_1>;
+ status = "okay";
+};
+
+&usbh {
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2_1>;
+ pinctrl-1 = <&pinctrl_usdhc2_1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_1_200mhz>;
+ assigned-clocks = <&clks IMX7D_USDHC2_ROOT_CLK>;
+ assigned-clocks-rates = <400000000>;
+ bus-width = <8>;
+ tuning-step = <2>;
+ non-removable;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3_1>;
+ vmmc-supply = <&reg_sd3_vmmc>;
+ cd-gpios = <&gpio1 14>;
+ wp-gpios = <&gpio1 15>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ no-1-8-v;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-ecspi.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-ecspi.dts
new file mode 100644
index 000000000000..16dd447a141f
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-ecspi.dts
@@ -0,0 +1,27 @@
+/*
+ * 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-12x12-lpddr3-arm2.dts"
+
+&epdc {
+ status = "disabled";
+};
+
+&ecspi1{
+ status = "okay";
+};
+
+/*
+ * pin conflict with ecspi1
+ * default hog setting conflicts with ECSPI1 MOSI and MISO
+ * EPDC PWRCTRL conflicts with ECSPI1 CS pin
+ */
+&iomuxc {
+ pinctrl-0 = <&pinctrl_hog_1>;
+ pinctrl-1 = <&pinctrl_hog_1>;
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-enet2.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-enet2.dts
new file mode 100644
index 000000000000..151853dc1712
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-enet2.dts
@@ -0,0 +1,17 @@
+/*
+ * 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-12x12-lpddr3-arm2.dts"
+
+&epdc {
+ status = "disabled";
+};
+
+&fec2 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-flexcan.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-flexcan.dts
new file mode 100644
index 000000000000..90ea88599b70
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-flexcan.dts
@@ -0,0 +1,29 @@
+/*
+* 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-12x12-lpddr3-arm2.dts"
+
+&fec1 {
+ status = "disabled";
+};
+
+&flexcan1 {
+ status = "okay";
+};
+
+&flexcan2 {
+ status = "okay";
+};
+
+&sai1 {
+ status = "disabled";
+};
+
+&sim1 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts
new file mode 100644
index 000000000000..d5579f2b437c
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts
@@ -0,0 +1,76 @@
+
+#include "imx7d-12x12-lpddr3-arm2.dts"
+
+/ {
+ memory {
+ linux,usable-memory = <0x80000000 0x1ff00000>,
+ <0xa0000000 0x1ff00000>,
+ <0xc0000000 0x40000000>;
+ };
+
+ gpio-keys {
+ status = "disabled";
+ };
+
+ m4_tcm: tcml@007f8000 {
+ compatible = "fsl, m4_tcml";
+ reg = <0x007f8000 0x8000>;
+ };
+};
+
+&adc1 {
+ status = "disabled";
+};
+
+&adc2 {
+ status = "disabled";
+};
+
+
+&i2c1 {
+ status = "disabled";
+};
+
+&flexcan1 {
+ status = "disabled";
+};
+
+&flexcan2 {
+ status = "disabled";
+};
+
+&gpt3 {
+ status = "disabled";
+};
+
+&gpt4 {
+ status = "disabled";
+};
+
+&ocram {
+ reg = <0x00901000 0xf000>;
+};
+
+&reg_can2_3v3 {
+ status = "disabled";
+};
+
+&rpmsg{
+ status = "okay";
+};
+
+&sim1 {
+ status = "disabled";
+};
+
+&tempmon {
+ status = "disabled";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&wdog3{
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-mipi_dsi.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-mipi_dsi.dts
new file mode 100644
index 000000000000..db38d4120f34
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-mipi_dsi.dts
@@ -0,0 +1,29 @@
+/*
+ * 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-12x12-lpddr3-arm2.dts"
+
+/ {
+ mipi_dsi_reset: mipi-dsi-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <50>;
+ #reset-cells = <0>;
+ };
+};
+
+&lcdif {
+ disp-dev = "mipi_dsi_samsung";
+};
+
+&mipi_dsi {
+ lcd_panel = "TRULY-WVGA";
+ disp-power-on-supply = <&reg_mipi_dsi_pwr_on>;
+ resets = <&mipi_dsi_reset>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-mqs.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-mqs.dts
new file mode 100644
index 000000000000..7fcdf6a060d8
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-mqs.dts
@@ -0,0 +1,49 @@
+/*
+ * 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-12x12-lpddr3-arm2.dts"
+
+/ {
+ sound-mqs {
+ compatible = "fsl,imx7d-12x12-lpddr3-arm2-mqs",
+ "fsl,imx-audio-mqs";
+ model = "mqs-audio";
+ cpu-dai = <&sai1>;
+ audio-codec = <&mqs>;
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
+ assigned-clock-rates = <786432000>;
+};
+
+&mqs {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_mqs>;
+ pinctrl-1 = <&pinctrl_mqs>;
+ clocks = <&clks IMX7D_SAI1_ROOT_CLK>;
+ clock-names = "mclk";
+ status = "okay";
+};
+
+&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>, <24576000>;
+ status = "okay";
+};
+
+&sdma {
+ status = "okay";
+};
+
+&sim1 {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-pcie.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-pcie.dts
new file mode 100644
index 000000000000..ffe65d934331
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-pcie.dts
@@ -0,0 +1,22 @@
+/*
+ * 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-12x12-lpddr3-arm2.dts"
+
+/*
+ * On imx7d 12x12 arm2 board, there is pin(gpio6_21) iomux
+ * between ecspi3 and pcie_rst_b. In order to resove this
+ * pin conflict, disable ecspi3 in this pcie named dts file.
+ */
+&ecspi3 {
+ status = "disabled";
+};
+
+&pcie{
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-qspi.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-qspi.dts
new file mode 100644
index 000000000000..3a7af2e8bf92
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-qspi.dts
@@ -0,0 +1,84 @@
+/*
+ * 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-12x12-lpddr3-arm2.dts"
+
+/* 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_DATA04__QSPI_A_DQS 0x51
+ MX7D_PAD_EPDC_DATA05__QSPI_A_SCLK 0x51
+ MX7D_PAD_EPDC_DATA06__QSPI_A_SS0_B 0x51
+ MX7D_PAD_EPDC_DATA07__QSPI_A_SS1_B 0x51
+ MX7D_PAD_EPDC_DATA08__QSPI_B_DATA0 0x51
+ MX7D_PAD_EPDC_DATA09__QSPI_B_DATA1 0x51
+ MX7D_PAD_EPDC_DATA10__QSPI_B_DATA2 0x51
+ MX7D_PAD_EPDC_DATA11__QSPI_B_DATA3 0x51
+ MX7D_PAD_EPDC_DATA12__QSPI_B_DQS 0x51
+ MX7D_PAD_EPDC_DATA13__QSPI_B_SCLK 0x51
+ MX7D_PAD_EPDC_DATA14__QSPI_B_SS0_B 0x51
+ MX7D_PAD_EPDC_DATA15__QSPI_B_SS1_B 0x51
+ >;
+ };
+ };
+};
+
+&qspi1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_qspi1_1>;
+ pinctrl-1 = <&pinctrl_qspi1_1>;
+ status = "okay";
+ fsl,qspi-has-second-chip = <1>;
+ 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>;
+ };
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <1>;
+ };
+
+ flash2: n25q256a@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <2>;
+ };
+
+ flash3: n25q256a@3 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a";
+ spi-max-frequency = <29000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ reg = <3>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-sai.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-sai.dts
new file mode 100644
index 000000000000..f1d36ce65119
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-sai.dts
@@ -0,0 +1,46 @@
+/*
+ * 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-12x12-lpddr3-arm2.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-arm2.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2.dts
new file mode 100644
index 000000000000..feaf056c62d9
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2.dts
@@ -0,0 +1,1017 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "imx7d.dtsi"
+
+/ {
+ model = "Freescale i.MX7 LPDDR3 12x12 ARM2 Board";
+ compatible = "fsl,imx7d-12x12-lpddr3-arm2", "fsl,imx7d";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ 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";
+ 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";
+ 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@08 {
+ compatible = "fsl,pfuze3000";
+ reg = <0x08>;
+ 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_GPIO1_IO01__PWM1_OUT 0x30
+ >;
+ };
+ };
+
+ imx7d-sdb {
+ pinctrl_usbotg1_vbus: usbotg1vbusgrp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO05__GPIO1_IO5 0x14
+ >;
+ };
+
+ pinctrl_usbotg2_vbus: usbotg2vbusgrp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO07__GPIO1_IO7 0x14
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO00__WDOD1_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 {
+ 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>;
+ 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-19x19-lpddr2-arm2.dts b/arch/arm/boot/dts/imx7d-19x19-lpddr2-arm2.dts
new file mode 100644
index 000000000000..2af374c66615
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-19x19-lpddr2-arm2.dts
@@ -0,0 +1,454 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx7d.dtsi"
+
+/ {
+ model = "Freescale i.MX7D LPDDR2 19x19 ARM2 Board";
+ compatible = "fsl,imx7d-19x19-lpddr2-arm2", "fsl,imx7d";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+ status = "disabled";
+
+ 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>;
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ 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_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>;
+ };
+ };
+
+ memory {
+ reg = <0x80000000 0x20000000>;
+ };
+};
+
+&adc1 {
+ vref-supply = <&reg_vref_1v8>;
+ status = "okay";
+};
+
+&cpu0 {
+ arm-supply = <&sw1a_reg>;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_1>;
+ status = "okay";
+
+ pmic: pfuze3000@08 {
+ 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 = <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;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2_1>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+
+ imx7d-19x19-lpddr3-arm2 {
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX7D_PAD_I2C4_SCL__GPIO4_IO14 0x80000000
+
+ MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59
+ MX7D_PAD_SD1_WP__GPIO5_IO1 0x59
+ MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x59
+
+ MX7D_PAD_GPIO1_IO14__GPIO1_IO14 0x59
+ MX7D_PAD_GPIO1_IO15__GPIO1_IO15 0x59
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO14__GPIO1_IO14 0x32
+ MX7D_PAD_GPIO1_IO15__GPIO1_IO15 0x32
+ >;
+ };
+
+ 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_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_weim_cs0_1: weim_cs0grp-1 {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA10__EIM_CS0_B 0x71
+ >;
+ };
+
+ pinctrl_weim_nor_1: weim_norgrp-1 {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA08__EIM_OE 0x71
+ MX7D_PAD_EPDC_DATA09__EIM_RW 0x71
+ MX7D_PAD_EPDC_DATA11__EIM_BCLK 0x71
+ MX7D_PAD_EPDC_DATA12__EIM_LBA_B 0x71
+ MX7D_PAD_EPDC_DATA13__EIM_WAIT 0x75
+ /* data */
+ MX7D_PAD_LCD_DATA00__EIM_DATA0 0x7d
+ MX7D_PAD_LCD_DATA01__EIM_DATA1 0x7d
+ MX7D_PAD_LCD_DATA02__EIM_DATA2 0x7d
+ MX7D_PAD_LCD_DATA03__EIM_DATA3 0x7d
+ MX7D_PAD_LCD_DATA04__EIM_DATA4 0x7d
+ MX7D_PAD_LCD_DATA05__EIM_DATA5 0x7d
+ MX7D_PAD_LCD_DATA06__EIM_DATA6 0x7d
+ MX7D_PAD_LCD_DATA07__EIM_DATA7 0x7d
+ MX7D_PAD_LCD_DATA08__EIM_DATA8 0x7d
+ MX7D_PAD_LCD_DATA09__EIM_DATA9 0x7d
+ MX7D_PAD_LCD_DATA10__EIM_DATA10 0x7d
+ MX7D_PAD_LCD_DATA11__EIM_DATA11 0x7d
+ MX7D_PAD_LCD_DATA12__EIM_DATA12 0x7d
+ MX7D_PAD_LCD_DATA13__EIM_DATA13 0x7d
+ MX7D_PAD_LCD_DATA14__EIM_DATA14 0x7d
+ MX7D_PAD_LCD_DATA15__EIM_DATA15 0x7d
+ /* address */
+ MX7D_PAD_EPDC_DATA00__EIM_AD0 0x71
+ MX7D_PAD_EPDC_DATA01__EIM_AD1 0x71
+ MX7D_PAD_EPDC_DATA02__EIM_AD2 0x71
+ MX7D_PAD_EPDC_DATA03__EIM_AD3 0x71
+ MX7D_PAD_EPDC_DATA04__EIM_AD4 0x71
+ MX7D_PAD_EPDC_DATA05__EIM_AD5 0x71
+ MX7D_PAD_EPDC_DATA06__EIM_AD6 0x71
+ MX7D_PAD_EPDC_DATA07__EIM_AD7 0x71
+ MX7D_PAD_EPDC_BDR1__EIM_AD8 0x71
+ MX7D_PAD_EPDC_PWR_COM__EIM_AD9 0x71
+ MX7D_PAD_EPDC_SDCLK__EIM_AD10 0x71
+ MX7D_PAD_EPDC_SDLE__EIM_AD11 0x71
+ MX7D_PAD_EPDC_SDOE__EIM_AD12 0x71
+ MX7D_PAD_EPDC_SDSHR__EIM_AD13 0x71
+ MX7D_PAD_EPDC_SDCE0__EIM_AD14 0x71
+ MX7D_PAD_EPDC_SDCE1__EIM_AD15 0x71
+ MX7D_PAD_EPDC_SDCE2__EIM_ADDR16 0x71
+ MX7D_PAD_EPDC_SDCE3__EIM_ADDR17 0x71
+ MX7D_PAD_EPDC_GDCLK__EIM_ADDR18 0x71
+ MX7D_PAD_EPDC_GDOE__EIM_ADDR19 0x71
+ MX7D_PAD_EPDC_GDRL__EIM_ADDR20 0x71
+ MX7D_PAD_EPDC_GDSP__EIM_ADDR21 0x71
+ MX7D_PAD_EPDC_BDR0__EIM_ADDR22 0x71
+ MX7D_PAD_LCD_DATA20__EIM_ADDR23 0x71
+ MX7D_PAD_LCD_DATA21__EIM_ADDR24 0x71
+ MX7D_PAD_LCD_DATA22__EIM_ADDR25 0x71
+ >;
+ };
+
+ 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: usdhc1grp {
+ 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_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
+ >;
+ };
+ };
+};
+
+&iomuxc_lpsr {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_2>;
+
+ imx7d-19x19-lpddr3-arm2 {
+ pinctrl_hog_2: hoggrp-2 {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO03__GPIO1_IO3 0x14
+ MX7D_PAD_GPIO1_IO05__GPIO1_IO5 0x14
+ MX7D_PAD_GPIO1_IO07__GPIO1_IO7 0x14
+ >;
+ };
+ };
+};
+
+&sdma {
+ status = "okay";
+};
+
+&weim {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_weim_nor_1 &pinctrl_weim_cs0_1>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0 0x28000000 0x08000000>;
+ status = "okay";
+
+ nor@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x08000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ bank-width = <2>;
+ fsl,weim-cs-timing = <0x00610081 0x00000001 0x1c022000
+ 0x0000c000 0x1404a38e 0x00000000>;
+ };
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_1>;
+ assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>;
+ assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3_1>;
+ 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>;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ 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";
+};
diff --git a/arch/arm/boot/dts/imx7d-pinfunc-lpsr.h b/arch/arm/boot/dts/imx7d-pinfunc-lpsr.h
new file mode 100644
index 000000000000..378694ee05c2
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-pinfunc-lpsr.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __DTS_IMX7D_PINFUNC_LPSR_H
+#define __DTS_IMX7D_PINFUNC_LPSR_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ *
+ * NOTE: imx7d-lpsr pin groups should be put under &iomuxc_lpsr node when used
+ */
+
+#define MX7D_PAD_GPIO1_IO00__GPIO1_IO0 0x0000 0x0030 0x0000 0x0 0x0
+#define MX7D_PAD_GPIO1_IO00__PWM4_OUT 0x0000 0x0030 0x0000 0x1 0x0
+#define MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_ANY 0x0000 0x0030 0x0000 0x2 0x0
+#define MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B 0x0000 0x0030 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO00__WDOD1_WDOG__RST_B_DEB 0x0000 0x0030 0x0000 0x4 0x0
+#define MX7D_PAD_GPIO1_IO01__GPIO1_IO1 0x0004 0x0034 0x0000 0x0 0x0
+#define MX7D_PAD_GPIO1_IO01__PWM1_OUT 0x0004 0x0034 0x0000 0x1 0x0
+#define MX7D_PAD_GPIO1_IO01__CCM_ENET_REF_CLK3 0x0004 0x0034 0x0000 0x2 0x0
+#define MX7D_PAD_GPIO1_IO01__SAI1_MCLK 0x0004 0x0034 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO01__ANATOP_24M_OUT 0x0004 0x0034 0x0000 0x4 0x0
+#define MX7D_PAD_GPIO1_IO01__OBSERVE0_OUT 0x0004 0x0034 0x0000 0x6 0x0
+#define MX7D_PAD_GPIO1_IO02__GPIO1_IO2 0x0008 0x0038 0x0000 0x0 0x0
+#define MX7D_PAD_GPIO1_IO02__PWM2_OUT 0x0008 0x0038 0x0000 0x1 0x0
+#define MX7D_PAD_GPIO1_IO02__CCM_ENET_REF_CLK1 0x0008 0x0038 0x0564 0x2 0x3
+#define MX7D_PAD_GPIO1_IO02__SAI2_MCLK 0x0008 0x0038 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO02__CCM_CLKO1 0x0008 0x0038 0x0000 0x5 0x0
+#define MX7D_PAD_GPIO1_IO02__OBSERVE1_OUT 0x0008 0x0038 0x0000 0x6 0x0
+#define MX7D_PAD_GPIO1_IO02__USB_OTG1_ID 0x0008 0x0038 0x0734 0x7 0x3
+#define MX7D_PAD_GPIO1_IO03__GPIO1_IO3 0x000C 0x003C 0x0000 0x0 0x0
+#define MX7D_PAD_GPIO1_IO03__PWM3_OUT 0x000C 0x003C 0x0000 0x1 0x0
+#define MX7D_PAD_GPIO1_IO03__CCM_ENET_REF_CLK2 0x000C 0x003C 0x0570 0x2 0x3
+#define MX7D_PAD_GPIO1_IO03__SAI3_MCLK 0x000C 0x003C 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO03__CCM_CLKO2 0x000C 0x003C 0x0000 0x5 0x0
+#define MX7D_PAD_GPIO1_IO03__OBSERVE2_OUT 0x000C 0x003C 0x0000 0x6 0x0
+#define MX7D_PAD_GPIO1_IO03__USB_OTG2_ID 0x000C 0x003C 0x0730 0x7 0x3
+#define MX7D_PAD_GPIO1_IO04__GPIO1_IO4 0x0010 0x0040 0x0000 0x0 0x0
+#define MX7D_PAD_GPIO1_IO04__USB_OTG1_OC 0x0010 0x0040 0x072C 0x1 0x1
+#define MX7D_PAD_GPIO1_IO04__FLEXTIMER1_CH4 0x0010 0x0040 0x0594 0x2 0x1
+#define MX7D_PAD_GPIO1_IO04__UART5_DCE_CTS 0x0010 0x0040 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO04__UART5_DTE_RTS 0x0010 0x0040 0x0710 0x3 0x4
+#define MX7D_PAD_GPIO1_IO04__I2C1_SCL 0x0010 0x0040 0x05D4 0x4 0x2
+#define MX7D_PAD_GPIO1_IO04__OBSERVE3_OUT 0x0010 0x0040 0x0000 0x6 0x0
+#define MX7D_PAD_GPIO1_IO05__GPIO1_IO5 0x0014 0x0044 0x0000 0x0 0x0
+#define MX7D_PAD_GPIO1_IO05__USB_OTG1_PWR 0x0014 0x0044 0x0000 0x1 0x0
+#define MX7D_PAD_GPIO1_IO05__FLEXTIMER1_CH5 0x0014 0x0044 0x0598 0x2 0x1
+#define MX7D_PAD_GPIO1_IO05__UART5_DCE_RTS 0x0014 0x0044 0x0710 0x3 0x5
+#define MX7D_PAD_GPIO1_IO05__UART5_DTE_CTS 0x0014 0x0044 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO05__I2C1_SDA 0x0014 0x0044 0x05D8 0x4 0x2
+#define MX7D_PAD_GPIO1_IO05__OBSERVE4_OUT 0x0014 0x0044 0x0000 0x6 0x0
+#define MX7D_PAD_GPIO1_IO06__GPIO1_IO6 0x0018 0x0048 0x0000 0x0 0x0
+#define MX7D_PAD_GPIO1_IO06__USB_OTG2_OC 0x0018 0x0048 0x0728 0x1 0x1
+#define MX7D_PAD_GPIO1_IO06__FLEXTIMER1_CH6 0x0018 0x0048 0x059C 0x2 0x1
+#define MX7D_PAD_GPIO1_IO06__UART5_DCE_RX 0x0018 0x0048 0x0714 0x3 0x4
+#define MX7D_PAD_GPIO1_IO06__UART5_DTE_TX 0x0018 0x0048 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO06__I2C2_SCL 0x0018 0x0048 0x05DC 0x4 0x2
+#define MX7D_PAD_GPIO1_IO06__CCM_WAIT 0x0018 0x0048 0x0000 0x5 0x0
+#define MX7D_PAD_GPIO1_IO06__KPP_ROW4 0x0018 0x0048 0x0624 0x6 0x1
+#define MX7D_PAD_GPIO1_IO07__GPIO1_IO7 0x001C 0x004C 0x0000 0x0 0x0
+#define MX7D_PAD_GPIO1_IO07__USB_OTG2_PWR 0x001C 0x004C 0x0000 0x1 0x0
+#define MX7D_PAD_GPIO1_IO07__FLEXTIMER1_CH7 0x001C 0x004C 0x05A0 0x2 0x1
+#define MX7D_PAD_GPIO1_IO07__UART5_DCE_TX 0x001C 0x004C 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO07__UART5_DTE_RX 0x001C 0x004C 0x0714 0x3 0x5
+#define MX7D_PAD_GPIO1_IO07__I2C2_SDA 0x001C 0x004C 0x05E0 0x4 0x2
+#define MX7D_PAD_GPIO1_IO07__CCM_STOP 0x001C 0x004C 0x0000 0x5 0x0
+#define MX7D_PAD_GPIO1_IO07__KPP_COL4 0x001C 0x004C 0x0604 0x6 0x1
+
+#endif /* __DTS_IMX7D_PINFUNC_LPSR_H */
diff --git a/arch/arm/boot/dts/imx7d-pinfunc.h b/arch/arm/boot/dts/imx7d-pinfunc.h
index 3f9f0d9c8094..3c54694782d0 100644
--- a/arch/arm/boot/dts/imx7d-pinfunc.h
+++ b/arch/arm/boot/dts/imx7d-pinfunc.h
@@ -15,57 +15,6 @@
* <mux_reg conf_reg input_reg mux_mode input_val>
*/
-#define MX7D_PAD_GPIO1_IO00__GPIO1_IO0 0x0000 0x0030 0x0000 0x0 0x0
-#define MX7D_PAD_GPIO1_IO00__PWM4_OUT 0x0000 0x0030 0x0000 0x1 0x0
-#define MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_ANY 0x0000 0x0030 0x0000 0x2 0x0
-#define MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B 0x0000 0x0030 0x0000 0x3 0x0
-#define MX7D_PAD_GPIO1_IO00__WDOD1_WDOG__RST_B_DEB 0x0000 0x0030 0x0000 0x4 0x0
-#define MX7D_PAD_GPIO1_IO01__GPIO1_IO1 0x0004 0x0034 0x0000 0x0 0x0
-#define MX7D_PAD_GPIO1_IO01__PWM1_OUT 0x0004 0x0034 0x0000 0x1 0x0
-#define MX7D_PAD_GPIO1_IO01__CCM_ENET_REF_CLK3 0x0004 0x0034 0x0000 0x2 0x0
-#define MX7D_PAD_GPIO1_IO01__SAI1_MCLK 0x0004 0x0034 0x0000 0x3 0x0
-#define MX7D_PAD_GPIO1_IO01__ANATOP_24M_OUT 0x0004 0x0034 0x0000 0x4 0x0
-#define MX7D_PAD_GPIO1_IO01__OBSERVE0_OUT 0x0004 0x0034 0x0000 0x6 0x0
-#define MX7D_PAD_GPIO1_IO02__GPIO1_IO2 0x0008 0x0038 0x0000 0x0 0x0
-#define MX7D_PAD_GPIO1_IO02__PWM2_OUT 0x0008 0x0038 0x0000 0x1 0x0
-#define MX7D_PAD_GPIO1_IO02__CCM_ENET_REF_CLK1 0x0008 0x0038 0x0564 0x2 0x3
-#define MX7D_PAD_GPIO1_IO02__SAI2_MCLK 0x0008 0x0038 0x0000 0x3 0x0
-#define MX7D_PAD_GPIO1_IO02__CCM_CLKO1 0x0008 0x0038 0x0000 0x5 0x0
-#define MX7D_PAD_GPIO1_IO02__OBSERVE1_OUT 0x0008 0x0038 0x0000 0x6 0x0
-#define MX7D_PAD_GPIO1_IO02__USB_OTG1_ID 0x0008 0x0038 0x0734 0x7 0x3
-#define MX7D_PAD_GPIO1_IO03__GPIO1_IO3 0x000C 0x003C 0x0000 0x0 0x0
-#define MX7D_PAD_GPIO1_IO03__PWM3_OUT 0x000C 0x003C 0x0000 0x1 0x0
-#define MX7D_PAD_GPIO1_IO03__CCM_ENET_REF_CLK2 0x000C 0x003C 0x0570 0x2 0x3
-#define MX7D_PAD_GPIO1_IO03__SAI3_MCLK 0x000C 0x003C 0x0000 0x3 0x0
-#define MX7D_PAD_GPIO1_IO03__CCM_CLKO2 0x000C 0x003C 0x0000 0x5 0x0
-#define MX7D_PAD_GPIO1_IO03__OBSERVE2_OUT 0x000C 0x003C 0x0000 0x6 0x0
-#define MX7D_PAD_GPIO1_IO03__USB_OTG2_ID 0x000C 0x003C 0x0730 0x7 0x3
-#define MX7D_PAD_GPIO1_IO04__GPIO1_IO4 0x0010 0x0040 0x0000 0x0 0x0
-#define MX7D_PAD_GPIO1_IO04__USB_OTG1_OC 0x0010 0x0040 0x072C 0x1 0x1
-#define MX7D_PAD_GPIO1_IO04__FLEXTIMER1_CH4 0x0010 0x0040 0x0594 0x2 0x1
-#define MX7D_PAD_GPIO1_IO04__UART5_CTS_B 0x0010 0x0040 0x0710 0x3 0x4
-#define MX7D_PAD_GPIO1_IO04__I2C1_SCL 0x0010 0x0040 0x05D4 0x4 0x2
-#define MX7D_PAD_GPIO1_IO04__OBSERVE3_OUT 0x0010 0x0040 0x0000 0x6 0x0
-#define MX7D_PAD_GPIO1_IO05__GPIO1_IO5 0x0014 0x0044 0x0000 0x0 0x0
-#define MX7D_PAD_GPIO1_IO05__USB_OTG1_PWR 0x0014 0x0044 0x0000 0x1 0x0
-#define MX7D_PAD_GPIO1_IO05__FLEXTIMER1_CH5 0x0014 0x0044 0x0598 0x2 0x1
-#define MX7D_PAD_GPIO1_IO05__UART5_RTS_B 0x0014 0x0044 0x0710 0x3 0x5
-#define MX7D_PAD_GPIO1_IO05__I2C1_SDA 0x0014 0x0044 0x05D8 0x4 0x2
-#define MX7D_PAD_GPIO1_IO05__OBSERVE4_OUT 0x0014 0x0044 0x0000 0x6 0x0
-#define MX7D_PAD_GPIO1_IO06__GPIO1_IO6 0x0018 0x0048 0x0000 0x0 0x0
-#define MX7D_PAD_GPIO1_IO06__USB_OTG2_OC 0x0018 0x0048 0x0728 0x1 0x1
-#define MX7D_PAD_GPIO1_IO06__FLEXTIMER1_CH6 0x0018 0x0048 0x059C 0x2 0x1
-#define MX7D_PAD_GPIO1_IO06__UART5_RX_DATA 0x0018 0x0048 0x0714 0x3 0x4
-#define MX7D_PAD_GPIO1_IO06__I2C2_SCL 0x0018 0x0048 0x05DC 0x4 0x2
-#define MX7D_PAD_GPIO1_IO06__CCM_WAIT 0x0018 0x0048 0x0000 0x5 0x0
-#define MX7D_PAD_GPIO1_IO06__KPP_ROW4 0x0018 0x0048 0x0624 0x6 0x1
-#define MX7D_PAD_GPIO1_IO07__GPIO1_IO7 0x001C 0x004C 0x0000 0x0 0x0
-#define MX7D_PAD_GPIO1_IO07__USB_OTG2_PWR 0x001C 0x004C 0x0000 0x1 0x0
-#define MX7D_PAD_GPIO1_IO07__FLEXTIMER1_CH7 0x001C 0x004C 0x05A0 0x2 0x1
-#define MX7D_PAD_GPIO1_IO07__UART5_TX_DATA 0x001C 0x004C 0x0714 0x3 0x5
-#define MX7D_PAD_GPIO1_IO07__I2C2_SDA 0x001C 0x004C 0x05E0 0x4 0x2
-#define MX7D_PAD_GPIO1_IO07__CCM_STOP 0x001C 0x004C 0x0000 0x5 0x0
-#define MX7D_PAD_GPIO1_IO07__KPP_COL4 0x001C 0x004C 0x0604 0x6 0x1
#define MX7D_PAD_GPIO1_IO08__GPIO1_IO8 0x0014 0x026C 0x0000 0x0 0x0
#define MX7D_PAD_GPIO1_IO08__SD1_VSELECT 0x0014 0x026C 0x0000 0x1 0x0
#define MX7D_PAD_GPIO1_IO08__WDOG1_WDOG_B 0x0014 0x026C 0x0000 0x2 0x0
@@ -588,7 +537,7 @@
#define MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX 0x0130 0x03A0 0x06FC 0x0 0x2
#define MX7D_PAD_UART2_RX_DATA__UART2_DTE_TX 0x0130 0x03A0 0x0000 0x0 0x0
#define MX7D_PAD_UART2_RX_DATA__I2C2_SCL 0x0130 0x03A0 0x05DC 0x1 0x0
-#define MX7D_PAD_UART2_RX_DATA__SAI3_RX_BCLK 0x0130 0x03A0 0x0000 0x2 0x0
+#define MX7D_PAD_UART2_RX_DATA__SAI3_RX_BCLK 0x0130 0x03A0 0x06C4 0x2 0x0
#define MX7D_PAD_UART2_RX_DATA__ECSPI1_SS3 0x0130 0x03A0 0x0000 0x3 0x0
#define MX7D_PAD_UART2_RX_DATA__ENET2_1588_EVENT1_IN 0x0130 0x03A0 0x0000 0x4 0x0
#define MX7D_PAD_UART2_RX_DATA__GPIO4_IO2 0x0130 0x03A0 0x0000 0x5 0x0
@@ -1108,13 +1057,13 @@
#define MX7D_PAD_ENET1_RGMII_TD3__GPIO7_IO9 0x0250 0x04C0 0x0000 0x5 0x0
#define MX7D_PAD_ENET1_RGMII_TD3__CAAM_RNG_OSC_OBS 0x0250 0x04C0 0x0000 0x7 0x0
#define MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x0254 0x04C4 0x0000 0x0 0x0
-#define MX7D_PAD_ENET1_RGMII_TX_CTL__SAI1_RX_SYNC 0x0254 0x04C4 0x0000 0x2 0x0
+#define MX7D_PAD_ENET1_RGMII_TX_CTL__SAI1_RX_SYNC 0x0254 0x04C4 0x06A4 0x2 0x1
#define MX7D_PAD_ENET1_RGMII_TX_CTL__GPT2_COMPARE1 0x0254 0x04C4 0x0000 0x3 0x0
#define MX7D_PAD_ENET1_RGMII_TX_CTL__EPDC_PWR_CTRL2 0x0254 0x04C4 0x0000 0x4 0x0
#define MX7D_PAD_ENET1_RGMII_TX_CTL__GPIO7_IO10 0x0254 0x04C4 0x0000 0x5 0x0
#define MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x0258 0x04C8 0x0000 0x0 0x0
#define MX7D_PAD_ENET1_RGMII_TXC__ENET1_TX_ER 0x0258 0x04C8 0x0000 0x1 0x0
-#define MX7D_PAD_ENET1_RGMII_TXC__SAI1_RX_BCLK 0x0258 0x04C8 0x0000 0x2 0x0
+#define MX7D_PAD_ENET1_RGMII_TXC__SAI1_RX_BCLK 0x0258 0x04C8 0x069C 0x2 0x1
#define MX7D_PAD_ENET1_RGMII_TXC__GPT2_COMPARE2 0x0258 0x04C8 0x0000 0x3 0x0
#define MX7D_PAD_ENET1_RGMII_TXC__EPDC_PWR_CTRL3 0x0258 0x04C8 0x0000 0x4 0x0
#define MX7D_PAD_ENET1_RGMII_TXC__GPIO7_IO11 0x0258 0x04C8 0x0000 0x5 0x0
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..e263ad446373
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-epdc.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-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..a04aca79b19d
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-epdc.dtsi
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+&epdc {
+ status = "okay";
+};
+
+&fec1 {
+ status = "disabled";
+};
+
+&fec2 {
+ 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..3a1208f44242
--- /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..deba9ef75646
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-m4.dtsi
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/ {
+ memory {
+ linux,usable-memory = <0x80000000 0x1ff00000>,
+ <0xa0000000 0x1ff00000>;
+ };
+ 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..1ba3e66c974a
--- /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 = "macronix,mx25l51245g";
+ spi-max-frequency = <29000000>;
+ /* take off one dummy cycle */
+ spi-nor,ddr-quad-read-dummy = <5>;
+ reg = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb-reva-epdc.dts b/arch/arm/boot/dts/imx7d-sdb-reva-epdc.dts
new file mode 100644
index 000000000000..341a8ad0b696
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-reva-epdc.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-reva.dts"
+#include "imx7d-sdb-epdc.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-sdb-reva-gpmi-weim.dts b/arch/arm/boot/dts/imx7d-sdb-reva-gpmi-weim.dts
new file mode 100644
index 000000000000..4d221f8d7dd7
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-reva-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-reva.dts"
+#include "imx7d-sdb-gpmi-weim.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-sdb-reva-hdmi-audio.dts b/arch/arm/boot/dts/imx7d-sdb-reva-hdmi-audio.dts
new file mode 100644
index 000000000000..221fdd0750d1
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-reva-hdmi-audio.dts
@@ -0,0 +1,20 @@
+/*
+ * 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"
+
+/ {
+ sound {
+ status = "disabled";
+ };
+
+ sound-hdmi {
+ status = "okay";
+ };
+};
+
diff --git a/arch/arm/boot/dts/imx7d-sdb-reva-m4.dts b/arch/arm/boot/dts/imx7d-sdb-reva-m4.dts
new file mode 100644
index 000000000000..78148f0d0a04
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-reva-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-reva.dts"
+#include "imx7d-sdb-m4.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-sdb-reva-qspi.dts b/arch/arm/boot/dts/imx7d-sdb-reva-qspi.dts
new file mode 100644
index 000000000000..7b523cac9575
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-reva-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-reva.dts"
+#include "imx7d-sdb-qspi.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-sdb-reva-touch.dts b/arch/arm/boot/dts/imx7d-sdb-reva-touch.dts
new file mode 100644
index 000000000000..d3855e8d7978
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-reva-touch.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 "imx7d-sdb-reva.dts"
+
+&sii902x {
+ status = "disabled";
+};
+
+&ecspi3 {
+ status = "okay";
+
+ tsc2046 {
+ interrupts = <13 0>;
+ pendown-gpio = <&gpio2 13 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb-reva-wm8960.dts b/arch/arm/boot/dts/imx7d-sdb-reva-wm8960.dts
new file mode 100644
index 000000000000..d9f38298f154
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-reva-wm8960.dts
@@ -0,0 +1,20 @@
+/*
+ * 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"
+
+/ {
+ sound {
+ status = "okay";
+ };
+
+ sound-hdmi {
+ status = "disabled";
+ };
+};
+
diff --git a/arch/arm/boot/dts/imx7d-sdb-reva.dts b/arch/arm/boot/dts/imx7d-sdb-reva.dts
new file mode 100644
index 000000000000..36568bd8df57
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sdb-reva.dts
@@ -0,0 +1,92 @@
+/*
+ * 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"
+
+/ {
+ regulators {
+ reg_usb_otg2_vbus: regulator@1 {
+ gpio = <&gpio4 7 GPIO_ACTIVE_HIGH>;
+ };
+
+ reg_pcie: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "MPCIE_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio_spi 6 GPIO_ACTIVE_HIGH>;
+ regulator-always-on;
+ enable-active-high;
+ };
+ };
+
+ sound-hdmi {
+ cpu-dai = <&sai1>;
+ };
+};
+
+&ecspi3 {
+ status = "disabled";
+};
+
+&epdc {
+ pinctrl-0 = <&pinctrl_epdc0>;
+ en-gpios = <&gpio_spi 5 GPIO_ACTIVE_LOW>;
+};
+
+&fec2 {
+ pinctrl-0 = <&pinctrl_enet2>;
+ pinctrl-assert-gpios = <>;
+};
+
+&i2c4 {
+ ov5647_mipi: ov5647_mipi@36 {
+ pwn-gpios = <&gpio_spi 7 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&iomuxc {
+ imx7d-sdb {
+ pinctrl_tsc2046_pendown: tsc2046_pendown {
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA13__GPIO2_IO13 0x59
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ 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
+ MX7D_PAD_SAI1_TX_SYNC__UART5_DTE_RTS 0x79
+ MX7D_PAD_SAI1_TX_DATA__UART5_DTE_CTS 0x79
+ >;
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl-0 = <&pinctrl_hog_1 &pinctrl_usbotg2_pwr_1>;
+};
+
+&iomuxc_lpsr {
+ pinctrl-0 = <&pinctrl_hog_2>;
+};
+
+&uart5 {
+ fsl,uart-has-rtscts;
+};
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
index 2f33c463cbce..1f09a0e7b999 100644
--- a/arch/arm/boot/dts/imx7d-sdb.dts
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
@@ -52,6 +52,13 @@
reg = <0x80000000 0x80000000>;
};
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
regulators {
compatible = "simple-bus";
#address-cells = <1>;
@@ -73,7 +80,7 @@
regulator-name = "usb_otg2_vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
- gpio = <&gpio4 7 GPIO_ACTIVE_HIGH>;
+ gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
@@ -83,7 +90,7 @@
regulator-name = "can2-3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- gpio = <&gpio1 7 GPIO_ACTIVE_LOW>;
+ gpio = <&gpio2 14 GPIO_ACTIVE_LOW>;
};
reg_vref_1v8: regulator@3 {
@@ -93,6 +100,102 @@
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
+
+ reg_sd1_vmmc: regulator@5 {
+ compatible = "regulator-fixed";
+ 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 = <20000>;
+ enable-active-high;
+ };
+
+ wlreg_on: fixedregulator@6 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ gpios = <&gpio4 20 0>; /* WL_HOST_WAKE */
+ wlreg_on-supply = <&wlreg_on>;
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx7d-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ 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-controler = <&sii902x>;
+ };
+
+ spi4 {
+ compatible = "spi-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1>;
+ status = "okay";
+ gpio-sck = <&gpio1 13 0>;
+ gpio-mosi = <&gpio1 9 0>;
+ cs-gpios = <&gpio1 12 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 <0x74>; /* Enable PERI_3V3, SENSOR_RST_B and HDMI_RST*/
+ spi-max-frequency = <100000>;
+ };
};
};
@@ -113,7 +216,7 @@
&ecspi3 {
fsl,spi-num-chipselects = <1>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ecspi3>;
+ pinctrl-0 = <&pinctrl_ecspi3 &pinctrl_ecspi3_cs>;
cs-gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
status = "okay";
@@ -136,9 +239,40 @@
};
};
+&clks {
+ assigned-clocks = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
+ assigned-clock-rates = <884736000>;
+};
+
+&csi1 {
+ csi-mux-mipi = <&gpr 0x14 4>;
+ status = "okay";
+
+ port {
+ csi_ep: endpoint {
+ remote-endpoint = <&csi_mipi_ep>;
+ };
+ };
+};
+
+&epdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdc0 &pinctrl_enet2_epdc0_en>;
+ 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>;
+ pinctrl-assert-gpios = <&gpio_spi 5 GPIO_ACTIVE_HIGH>;
assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
<&clks IMX7D_ENET1_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
@@ -153,10 +287,12 @@
#size-cells = <0>;
ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
reg = <0>;
};
ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
};
};
@@ -164,7 +300,8 @@
&fec2 {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_enet2>;
+ pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_epdc0_en>;
+ pinctrl-assert-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
@@ -175,7 +312,33 @@
status = "okay";
};
+&mipi_csi {
+ clock-frequency = <240000000>;
+ status = "okay";
+ port {
+ mipi_sensor_ep: endpoint1 {
+ remote-endpoint = <&ov5640_mipi_ep>;
+ data-lanes = <2>;
+ csis-hs-settle = <13>;
+ csis-clk-settle = <2>;
+ csis-wclk;
+ };
+
+ csi_mipi_ep: endpoint2 {
+ remote-endpoint = <&csi_ep>;
+ };
+ };
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can2_3v3>;
+ status = "okay";
+};
+
&i2c1 {
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
@@ -187,7 +350,7 @@
regulators {
sw1a_reg: sw1a {
regulator-min-microvolt = <700000>;
- regulator-max-microvolt = <1475000>;
+ regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
regulator-ramp-delay = <6250>;
@@ -272,18 +435,117 @@
};
&i2c2 {
+ clock-frequency = <100000>;
pinctrl-names = "default";
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>;
+ };
};
&i2c3 {
+ clock-frequency = <100000>;
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 {
+ clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c4>;
status = "okay";
@@ -295,15 +557,33 @@
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 = <&gpio_spi 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>;
+ enable-gpio = <&gpio_spi 7 GPIO_ACTIVE_LOW>;
display = <&display0>;
status = "okay";
- display0: display {
+ display0: display@0 {
bits-per-pixel = <16>;
bus-width = <24>;
@@ -329,22 +609,133 @@
};
};
+&pcie_phy{
+ status = "okay";
+};
+
+&pcie {
+ pinctrl-names = "default";
+ reset-gpio = <&gpio_spi 1 GPIO_ACTIVE_LOW>;
+ disable-gpio = <&gpio_spi 0 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&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";
+};
+
+&sdma {
+ status = "okay";
+};
+
&pwm1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm1>;
status = "okay";
};
+&iomuxc_lpsr {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_2 &pinctrl_usbotg2_pwr_2>;
+
+ imx7d-sdb {
+ pinctrl_hog_2: hoggrp-2 {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO05__GPIO1_IO5 0x14
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO01__PWM1_OUT 0x30
+ >;
+ };
+
+ pinctrl_usbotg2_pwr_2: usbotg2-2 {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO07__GPIO1_IO7 0x14
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B 0x74
+ >;
+ };
+
+ pinctrl_enet2_epdc0_en: enet2_epdc0_grp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO04__GPIO1_IO4 0x80000000
+ >;
+ };
+
+ pinctrl_sai3_mclk: sai3grp_mclk {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO03__SAI3_MCLK 0x1f
+ >;
+ };
+ };
+};
+
+&sim1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sim1_1>;
+ port = <0>;
+ sven_low_active;
+ status = "okay";
+};
+
+
&uart1 {
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";
+};
+
+&uart6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart6>;
+ assigned-clocks = <&clks IMX7D_UART6_ROOT_SRC>;
assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
+ fsl,uart-has-rtscts;
+ resets = <&modem_reset>;
status = "okay";
};
&usbotg1 {
vbus-supply = <&reg_usb_otg1_vbus>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
status = "okay";
};
@@ -355,15 +746,33 @@
};
&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;
+ vmmc-supply = <&reg_sd1_vmmc>;
+ enable-sdio-wakeup;
keep-power-in-suspend;
status = "okay";
};
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ enable-sdio-wakeup;
+ keep-power-in-suspend;
+ non-removable;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host;
+ status = "okay";
+};
+
&usdhc3 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc3>;
@@ -372,7 +781,6 @@
assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>;
assigned-clock-rates = <400000000>;
bus-width = <8>;
- fsl,tuning-step = <2>;
non-removable;
status = "okay";
};
@@ -383,17 +791,50 @@
fsl,ext-reset-output;
};
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ status = "disabled";
+ nand-on-flash-bbt;
+};
+
&iomuxc {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
+ pinctrl-0 = <&pinctrl_hog_1>;
imx7d-sdb {
+
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x59 /* headphone detect */
+ >;
+ };
+
+ 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_cs: ecspi3_cs_grp {
+ fsl,pins = <
+ MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x80000000
+ >;
+ };
+
pinctrl_ecspi3: ecspi3grp {
fsl,pins = <
MX7D_PAD_SAI2_TX_SYNC__ECSPI3_MISO 0x2
MX7D_PAD_SAI2_TX_BCLK__ECSPI3_MOSI 0x2
MX7D_PAD_SAI2_RX_DATA__ECSPI3_SCLK 0x2
- MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x59
>;
};
@@ -433,10 +874,63 @@
>;
};
- pinctrl_hog: hoggrp {
+ pinctrl_epdc0: epdcgrp0 {
+ 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_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
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
fsl,pins = <
- MX7D_PAD_UART3_CTS_B__GPIO4_IO7 0x14
- MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x34 /* bt reg on */
+ MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX 0x59
+ MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX 0x59
+ MX7D_PAD_EPDC_DATA14__GPIO2_IO14 0x59 /* CAN_STBY */
+ >;
+ };
+
+ 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
>;
};
@@ -502,9 +996,40 @@
>;
};
- pinctrl_pwm1: pwm1grp {
+ 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_GPIO1_IO01__PWM1_OUT 0x110b0
+ 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
>;
};
@@ -514,6 +1039,30 @@
>;
};
+ pinctrl_spi1: spi1grp {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x59
+ MX7D_PAD_GPIO1_IO12__GPIO1_IO12 0x59
+ MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x59
+ >;
+ };
+
+ 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
@@ -525,8 +1074,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
>;
};
@@ -536,6 +1090,22 @@
MX7D_PAD_ECSPI1_SCLK__UART6_DCE_RX 0x79
MX7D_PAD_ECSPI1_SS0__UART6_DCE_CTS 0x79
MX7D_PAD_ECSPI1_MISO__UART6_DCE_RTS 0x79
+ MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x19 /* BT_REG_ON */
+ >;
+ };
+
+ 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_usbotg2_pwr_1: usbotg2-1 {
+ fsl,pins = <
+ MX7D_PAD_UART3_CTS_B__GPIO4_IO7 0x14
>;
};
@@ -547,9 +1117,29 @@
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
>;
};
@@ -561,7 +1151,8 @@
MX7D_PAD_SD2_DATA1__SD2_DATA1 0x59
MX7D_PAD_SD2_DATA2__SD2_DATA2 0x59
MX7D_PAD_SD2_DATA3__SD2_DATA3 0x59
- MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 0x59 /* WL_REG_ON */
+ MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 0x19 /* WL_REG_ON */
+ MX7D_PAD_ECSPI2_SCLK__GPIO4_IO20 0x19 /* WL_HOST_WAKE */
>;
};
@@ -636,10 +1227,5 @@
>;
};
- pinctrl_wdog: wdoggrp {
- fsl,pins = <
- MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B 0x74
- >;
- };
};
};
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index f6dee41a05d9..457927ab3ffd 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -1,6 +1,7 @@
/*
- * Copyright 2015 Freescale Semiconductor, Inc.
+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
* Copyright 2016 Toradex AG
+ * Copyright 2017 NXP.
*
* This file is dual-licensed: you can use it either under the terms
* of the GPL or the X11 license, at your option. Note that this dual
@@ -48,6 +49,7 @@
cpu0: cpu@0 {
operating-points = <
/* KHz uV */
+ 1200000 1225000
996000 1075000
792000 975000
>;
@@ -62,6 +64,20 @@
};
};
+ 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 {
etm@3007d000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
@@ -83,6 +99,266 @@
};
};
};
+
+ 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_CLK>, <&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";
+ };
+
+ caam_sm: caam-sm@00100000 {
+ compatible = "fsl,imx7d-caam-sm", "fsl,imx6q-caam-sm";
+ reg = <0x00100000 0x3fff>;
+ };
+
+ irq_sec_vio: caam_secvio {
+ compatible = "fsl,imx7d-caam-secvio", "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";
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ ocrams_ddr: sram@00900000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x00900000 0x1000>;
+ clocks = <&clks IMX7D_OCRAM_CLK>;
+ };
+
+ ocram: sram@901000 {
+ compatible = "mmio-sram";
+ reg = <0x00901000 0x1f000>;
+ clocks = <&clks IMX7D_OCRAM_CLK>;
+ };
+
+ ocrams: sram@00180000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x00180000 0x8000>;
+ clocks = <&clks IMX7D_OCRAM_S_CLK>;
+ status = "disabled";
+ };
+
+ ocrams_mf: sram-mf@00900000 {
+ compatible = "fsl,mega-fast-sram";
+ reg = <0x00900000 0x20000>;
+ clocks = <&clks IMX7D_OCRAM_CLK>;
+ };
+
+ dma_apbh: dma-apbh@33000000 {
+ compatible = "fsl,imx7d-dma-apbh", "fsl,imx28-dma-apbh";
+ reg = <0x33000000 0x2000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
+ #dma-cells = <1>;
+ dma-channels = <4>;
+ clocks = <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>,
+ <&clks IMX7D_NAND_ROOT_CLK>;
+ clock-names = "dma_apbh_bch", "dma_apbh_io";
+ };
+
+ gpmi: gpmi-nand@33002000{
+ compatible = "fsl,imx7d-gpmi-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x33002000 0x2000>, <0x33004000 0x4000>;
+ reg-names = "gpmi-nand", "bch";
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "bch";
+ clocks = <&clks IMX7D_NAND_ROOT_CLK>,
+ <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>;
+ clock-names = "gpmi_io", "gpmi_bch_apb";
+ dmas = <&dma_apbh 0>;
+ dma-names = "rx-tx";
+ status = "disabled";
+ };
+
+ pcie: pcie@0x33800000 {
+ compatible = "fsl,imx7d-pcie", "snps,dw-pcie";
+ reg = <0x33800000 0x4000>, <0x4ff00000 0x80000>;
+ reg-names = "dbi", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x81000000 0 0 0x4ff80000 0 0x00010000 /* downstream I/O 64KB */
+ 0x82000000 0 0x40000000 0x40000000 0 0x0ff00000>; /* non-prefetchable memory */
+ num-lanes = <1>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_PCIE_CTRL_ROOT_CLK>,
+ <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>,
+ <&clks IMX7D_PCIE_PHY_ROOT_CLK>;
+ clock-names = "pcie", "pcie_bus", "pcie_phy";
+ pcie-phy-supply = <&reg_1p0d>;
+ fsl,max-link-speed = <2>;
+ status = "disabled";
+ };
+ };
+};
+
+&aips1 {
+ kpp: kpp@30320000 {
+ compatible = "fsl,imx7d-kpp", "fsl,imx21-kpp";
+ reg = <0x30320000 0x10000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_CLK_DUMMY>;
+ status = "disabled";
+ };
+
+ mqs: mqs {
+ compatible = "fsl,imx6sx-mqs";
+ gpr = <&gpr>;
+ status = "disabled";
+ };
+
+ ocotp: ocotp-ctrl@30350000 {
+ compatible = "fsl,imx7d-ocotp", "syscon";
+ reg = <0x30350000 0x10000>;
+ clocks = <&clks IMX7D_OCOTP_CLK>;
+ status = "okay";
+ };
+
+ tempmon: tempmon {
+ compatible = "fsl,imx7d-tempmon";
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,tempmon =<&anatop>;
+ fsl,tempmon-data = <&ocotp>;
+ clocks = <&clks IMX7D_PLL_SYS_MAIN_CLK>;
+ };
+
+ caam_snvs: caam-snvs@30370000 {
+ compatible = "fsl,imx6q-caam-snvs";
+ reg = <0x30370000 0x10000>;
+ };
+ iomuxc_lpsr_gpr: lpsr-gpr@30270000 {
+ compatible = "fsl,imx7d-lpsr-gpr";
+ reg = <0x30270000 0x10000>;
+ };
+};
+
+&aips2 {
+ flextimer1: flextimer@30640000 {
+ compatible = "fsl,imx7d-flextimer";
+ reg = <0x30640000 0x10000>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ flextimer2: flextimer@30650000 {
+ compatible = "fsl,imx7d-flextimer";
+ reg = <0x30650000 0x10000>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ 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";
+ };
+
+ pcie_phy: pcie-phy@306d0000 {
+ compatible = "fsl,imx-pcie-phy";
+ reg = <0x306d0000 0x10000>;
+ 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>;
+ 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: csi@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";
+ };
+
+ 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";
+ mipi-phy-supply = <&reg_1p0d>;
+ status = "disabled";
+ };
+
+ ddrc: ddrc@307a0000 {
+ compatible = "fsl,imx7-ddrc";
+ reg = <0x307a0000 0x10000>;
};
};
@@ -95,6 +371,9 @@
fsl,usbphy = <&usbphynop2>;
fsl,usbmisc = <&usbmisc2 0>;
phy-clkgate-delay-us = <400>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
status = "disabled";
};
@@ -116,17 +395,111 @@
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>,
+ clocks = <&clks IMX7D_ENET2_IPG_ROOT_CLK>,
<&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>;
fsl,num-rx-queues=<3>;
status = "disabled";
};
+
+ crypto: caam@30900000 {
+ compatible = "fsl,imx7d-caam", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x30900000 0x40000>;
+ ranges = <0 0x30900000 0x40000>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_CAAM_CLK>,
+ <&clks IMX7D_AHB_CHANNEL_ROOT_CLK>;
+ clock-names = "ipg", "aclk";
+ sec_jr0: jr0@1000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ sec_jr1: jr1@2000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ sec_jr2: jr2@3000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ 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";
+ status = "okay";
+ };
+
+ rpmsg: rpmsg{
+ compatible = "fsl,imx7d-rpmsg";
+ status = "disabled";
+ };
+
+ sema4: sema4@30ac0000 {
+ compatible = "fsl,imx7d-sema4";
+ reg = <0x30ac0000 0x10000>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_SEMA4_HS_ROOT_CLK>;
+ clock-names = "sema4";
+ status = "okay";
+ };
+
+ sim1: sim@30b90000 {
+ compatible = "fsl,imx7d-sim";
+ reg = <0x30b90000 0x10000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_SIM1_ROOT_CLK>;
+ clock-names = "sim";
+ status = "disabled";
+ };
+
+ sim2: sim@30ba0000 {
+ compatible = "fsl,imx7d-sim";
+ reg = <0x30ba0000 0x10000>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ qspi1: qspi@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";
+ };
+
+ weim: weim@30bc0000 {
+ compatible = "fsl,imx7d-weim", "fsl,imx6sx-weim", "fsl,imx6q-weim";
+ reg = <0x30bc0000 0x10000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_EIM_ROOT_CLK>;
+ status = "disabled";
+ };
+
+};
+
+&usbphynop3 {
+ vcc-supply = <&reg_1p2>;
};
&ca_funnel_ports {
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 2b6cb05bc01a..74a3938ffd46 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -46,6 +46,7 @@
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "imx7d-pinfunc.h"
+#include "imx7d-pinfunc-lpsr.h"
#include "skeleton.dtsi"
/ {
@@ -88,6 +89,7 @@
clock-frequency = <792000000>;
clock-latency = <61036>; /* two CLK32 periods */
clocks = <&clks IMX7D_CLK_ARM>;
+ clock-names = "arm";
};
};
@@ -109,7 +111,7 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
- interrupt-parent = <&intc>;
+ interrupt-parent = <&gpc>;
ranges;
funnel@30041000 {
@@ -295,14 +297,18 @@
<0x31002000 0x2000>,
<0x31004000 0x2000>,
<0x31006000 0x2000>;
+ interrupt-parent = <&intc>;
};
timer {
compatible = "arm,armv7-timer";
+ arm,cpu-registers-not-fw-configured;
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)>;
+ interrupt-parent = <&intc>;
+ clock-frequency = <8000000>;
};
aips1: aips-bus@30000000 {
@@ -312,6 +318,23 @@
reg = <0x30000000 0x400000>;
ranges;
+ gpc: gpc@303a0000 {
+ compatible = "fsl,imx7d-gpc";
+ reg = <0x303a0000 0x1000>;
+ interrupt-controller;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ fsl,mf-mix-wakeup-irq = <0x54010000 0xc00 0x0 0x1040640>;
+ };
+
+ pgc {
+ compatible = "fsl,imx7d-pgc";
+ mipi-phy-supply = <&reg_1p0d>;
+ pcie-phy-supply = <&reg_1p0d>;
+ vcc-supply = <&reg_1p2>;
+ };
+
gpio1: gpio@30200000 {
compatible = "fsl,imx7d-gpio", "fsl,imx35-gpio";
reg = <0x30200000 0x10000>;
@@ -437,9 +460,10 @@
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
reg = <0x302d0000 0x10000>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_CLK_DUMMY>,
- <&clks IMX7D_GPT1_ROOT_CLK>;
- clock-names = "ipg", "per";
+ clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
+ <&clks IMX7D_GPT1_ROOT_CLK>,
+ <&clks IMX7D_GPT_3M_CLK>;
+ clock-names = "ipg", "per", "osc_per";
};
gpt2: gpt@302e0000 {
@@ -507,8 +531,23 @@
anatop-min-bit-val = <8>;
anatop-min-voltage = <800000>;
anatop-max-voltage = <1200000>;
- anatop-enable-bit = <31>;
+ anatop-enable-bit = <0>;
+ };
+
+ reg_1p2: regulator-vdd1p2@220 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vdd1p2";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ anatop-reg-offset = <0x220>;
+ anatop-vol-bit-shift = <8>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <0x14>;
+ anatop-min-voltage = <1100000>;
+ anatop-max-voltage = <1300000>;
+ anatop-enable-bit = <31>;
};
+
};
snvs: snvs@30370000 {
@@ -527,7 +566,7 @@
compatible = "syscon-poweroff";
regmap = <&snvs>;
offset = <0x38>;
- mask = <0x60>;
+ mask = <0x61>;
};
snvs_pwrkey: snvs-powerkey {
@@ -643,8 +682,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";
};
};
@@ -711,6 +751,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";
};
@@ -722,6 +764,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";
};
@@ -731,10 +775,11 @@
reg = <0x308a0000 0x10000>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI1_IPG_CLK>,
+ <&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_SAI1_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 8 24 0>, <&sdma 9 24 0>;
status = "disabled";
@@ -746,10 +791,11 @@
reg = <0x308b0000 0x10000>;
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI2_IPG_CLK>,
+ <&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_SAI2_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 10 24 0>, <&sdma 11 24 0>;
status = "disabled";
@@ -761,10 +807,11 @@
reg = <0x308c0000 0x10000>;
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI3_IPG_CLK>,
+ <&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_SAI3_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
- clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 12 24 0>, <&sdma 13 24 0>;
status = "disabled";
@@ -777,6 +824,7 @@
clocks = <&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CAN1_ROOT_CLK>;
clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x10 1 0x10 17>;
status = "disabled";
};
@@ -787,6 +835,7 @@
clocks = <&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CAN2_ROOT_CLK>;
clock-names = "ipg", "per";
+ stop-mode = <&gpr 0x10 2 0x10 18>;
status = "disabled";
};
@@ -838,6 +887,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";
};
@@ -849,6 +900,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";
};
@@ -860,6 +913,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";
};
@@ -871,6 +926,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";
};
@@ -882,6 +939,9 @@
fsl,usbphy = <&usbphynop1>;
fsl,usbmisc = <&usbmisc1 0>;
phy-clkgate-delay-us = <400>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
status = "disabled";
};
@@ -926,10 +986,12 @@
compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc";
reg = <0x30b40000 0x10000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_CLK_DUMMY>,
- <&clks IMX7D_CLK_DUMMY>,
+ clocks = <&clks IMX7D_IPG_ROOT_CLK>,
+ <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>,
<&clks IMX7D_USDHC1_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
bus-width = <4>;
status = "disabled";
};
@@ -942,6 +1004,8 @@
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_USDHC2_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
bus-width = <4>;
status = "disabled";
};
@@ -954,6 +1018,8 @@
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_USDHC3_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
bus-width = <4>;
status = "disabled";
};
@@ -975,11 +1041,11 @@
interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>,
+ clocks = <&clks IMX7D_ENET1_IPG_ROOT_CLK>,
<&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-14x14-arm2.dts b/arch/arm/boot/dts/imx7ulp-14x14-arm2.dts
new file mode 100644
index 000000000000..6db59d4e0bee
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-14x14-arm2.dts
@@ -0,0 +1,72 @@
+/*
+ * Copyright 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.
+ */
+
+/dts-v1/;
+
+#include "imx7ulp.dtsi"
+
+/ {
+ model = "NXP i.MX7ULP 14x14 arm2";
+ compatible = "fsl,imx7ulp-14x14-arm2", "fsl,imx7ulp", "Generic DT based system";
+
+ chosen {
+ bootargs = "console=ttyLP0,115200 earlycon=lpuart32,0x402D0000,115200";
+ stdout-path = &lpuart4;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x60000000 0x40000000>;
+ };
+};
+
+&iomuxc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+
+ imx7ulp-14x14-arm2 {
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ ULP1_PAD_PTC10__PTC10 0x30100
+ ULP1_PAD_PTC1__PTC1 0x20100
+ >;
+ };
+
+ pinctrl_lpuart4: lpuart4grp {
+ fsl,pins = <
+ ULP1_PAD_PTC3__LPUART4_RX 0x400
+ ULP1_PAD_PTC2__LPUART4_TX 0x400
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ ULP1_PAD_PTE3__SDHC1_CMD 0x843
+ ULP1_PAD_PTE2__SDHC1_CLK 0x843
+ ULP1_PAD_PTE4__SDHC1_D3 0x843
+ ULP1_PAD_PTE5__SDHC1_D2 0x843
+ ULP1_PAD_PTE0__SDHC1_D1 0x843
+ ULP1_PAD_PTE1__SDHC1_D0 0x843
+ >;
+ };
+ };
+};
+
+&lpuart4 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart4>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1>;
+ non-removable;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk-emmc-qspi.dts b/arch/arm/boot/dts/imx7ulp-evk-emmc-qspi.dts
new file mode 100644
index 000000000000..47289c636e94
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-emmc-qspi.dts
@@ -0,0 +1,18 @@
+/*
+ * 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 "imx7ulp-evk-qspi.dts"
+
+&usdhc0 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc0_8bit>;
+ pinctrl-1 = <&pinctrl_usdhc0_8bit>;
+ non-removable;
+ bus-width = <8>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk-emmc.dts b/arch/arm/boot/dts/imx7ulp-evk-emmc.dts
new file mode 100644
index 000000000000..e58616e71b17
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-emmc.dts
@@ -0,0 +1,18 @@
+/*
+ * 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 "imx7ulp-evk.dts"
+
+&usdhc0 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc0_8bit>;
+ pinctrl-1 = <&pinctrl_usdhc0_8bit>;
+ non-removable;
+ bus-width = <8>;
+ status = "okay";
+};
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..2d86e33e1abb
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-ft5416.dts
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2017 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 "imx7ulp-evk.dts"
+
+&lpi2c7 {
+ focaltech@38 {
+ focaltech,panel-type = <FT5416>;
+ focaltech,swap-xy;
+ /delete-property/focaltech,scaling-down-half;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk-hdmi.dts b/arch/arm/boot/dts/imx7ulp-evk-hdmi.dts
new file mode 100644
index 000000000000..d56c8e147a2b
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-hdmi.dts
@@ -0,0 +1,26 @@
+/*
+ * 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 "imx7ulp-evk.dts"
+
+&adv7535 {
+ status = "okay";
+ port {
+ dsi_to_hdmi: endpoint {
+ remote-endpoint = <&mipi_dsi_ep>;
+ };
+ };
+};
+
+&mipi_dsi {
+ port {
+ mipi_dsi_ep: endpoint {
+ remote-endpoint = <&dsi_to_hdmi>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk-lpuart.dts b/arch/arm/boot/dts/imx7ulp-evk-lpuart.dts
new file mode 100644
index 000000000000..6c9dba0f2a35
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-lpuart.dts
@@ -0,0 +1,17 @@
+/*
+ * 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 "imx7ulp-evk.dts"
+
+&lpi2c7 {
+ status = "disabled";
+};
+
+&lpuart7 { /* Uart test */
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk-qspi.dts b/arch/arm/boot/dts/imx7ulp-evk-qspi.dts
new file mode 100644
index 000000000000..c9761a1a6ed0
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-qspi.dts
@@ -0,0 +1,76 @@
+/*
+ * 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 "imx7ulp-evk.dts"
+
+/ {
+ regulators {
+ compatible = "simple-bus";
+
+ dummy: regulator-dummy {
+ compatible = "regulator-fixed";
+ regulator-name = "dummy";
+ regulator-always-on;
+ };
+ };
+};
+
+&qspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi1_1>;
+ status = "okay";
+
+ flash0: mx25r6435f@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "macronix,mx25r6435f";
+ spi-max-frequency = <29000000>;
+ };
+};
+
+&rpmsg{
+ status = "disabled";
+};
+
+&cpu0 {
+ arm-supply= <&dummy>;
+ operating-points = <
+ /* KHz uV */
+ 503666 1025000
+ >;
+};
+
+&usdhc0 {
+ vqmmc-supply = <&dummy>;
+ no-1-8-v;
+ non-removable;
+};
+
+&iomuxc {
+ status = "okay";
+};
+
+&iomuxc {
+ imx7ulp-evk {
+ pinctrl_qspi1_1: qspi1grp_1 {
+ fsl,pins = <
+ ULP1_PAD_PTB7_LLWU0_P11__QSPIA_SS1_B 0x43 /* SS1 */
+ ULP1_PAD_PTB8__QSPIA_SS0_B 0x43 /* SS0 */
+ ULP1_PAD_PTB15__QSPIA_SCLK 0x43 /* SCLK */
+ ULP1_PAD_PTB9_LLWU0_P12__QSPIA_DQS 0x43 /* DQS */
+ ULP1_PAD_PTB16_LLWU0_P14__QSPIA_DATA3 0x43 /* D3 */
+ ULP1_PAD_PTB17__QSPIA_DATA2 0x43 /* D2 */
+ ULP1_PAD_PTB18__QSPIA_DATA1 0x43 /* D1 */
+ ULP1_PAD_PTB19_LLWU0_P15__QSPIA_DATA0 0x43 /* D0 */
+ >;
+ };
+ };
+};
+
diff --git a/arch/arm/boot/dts/imx7ulp-evk-sd1.dts b/arch/arm/boot/dts/imx7ulp-evk-sd1.dts
new file mode 100644
index 000000000000..1dddfb214cf9
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-sd1.dts
@@ -0,0 +1,49 @@
+/*
+ * Copyright 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 "imx7ulp-evk.dts"
+
+/ {
+ regulators {
+ reg_vsd_3v3b: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "VSD_3V3B";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&bcmdhd_wlan_0 {
+ status = "disabled";
+};
+
+&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 = <&gpio2 13 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&reg_vsd_3v3b>;
+ /delete-property/non-removable;
+ /delete-property/cd-post;
+ /delete-property/wifi-host;
+ /delete-property/pm-ignore-notify;
+ /delete-property/keep-power-in-suspend;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk-sensors-to-i2c5.dts b/arch/arm/boot/dts/imx7ulp-evk-sensors-to-i2c5.dts
new file mode 100644
index 000000000000..54f0e619de20
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-sensors-to-i2c5.dts
@@ -0,0 +1,22 @@
+
+#include "imx7ulp-evk.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-evk-wm8960.dts b/arch/arm/boot/dts/imx7ulp-evk-wm8960.dts
new file mode 100644
index 000000000000..9988bd15e0ae
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk-wm8960.dts
@@ -0,0 +1,217 @@
+/*
+ * Copyright 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 "imx7ulp-evk.dts"
+
+/ {
+
+ aips0: aips-bus@41000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x41000000 0x80000>;
+ ranges;
+
+ pcc0: pcc0@41026000 {
+ compatible = "fsl,imx7ulp-pcc0";
+ reg = <0x41026000 0x1000>;
+ };
+
+ clks_m4: scg0@41027000 {
+ compatible = "fsl,imx7ulp-scg0";
+ reg = <0x41027000 0x1000>;
+ clocks = <&cm4_ckil>, <&cm4_osc>, <&cm4_sirc>, <&cm4_firc>;
+ clock-names = "cm4_ckil", "cm4_osc", "cm4_sirc", "cm4_firc";
+ #clock-cells = <1>;
+ };
+
+ sai0: sai@41037000 {
+ compatible = "fsl,imx7ulp-sai";
+ reg = <0x41037000 0x1000>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks_m4 IMX7ULP_CM4_CLK_SAI0_IPG>,
+ <&clks_m4 IMX7ULP_CM4_CLK_DUMMY>,
+ <&clks_m4 IMX7ULP_CM4_CLK_SAI0_ROOT>,
+ <&clks_m4 IMX7ULP_CM4_CLK_DUMMY>,
+ <&clks_m4 IMX7ULP_CM4_CLK_DUMMY>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx", "tx";
+ dmas = <&edma0 0 59>, <&edma0 0 60>;
+ status = "disabled";
+ };
+ };
+
+ aips1: aips-bus@41080000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x41080000 0x80000>;
+ ranges;
+
+ smc0: smc0@410a4000 {
+ compatible = "fsl,imx7ulp-smc0";
+ reg = <0x410a4000 0x1000>;
+ };
+
+ sai1: sai@410AA000 {
+ compatible = "fsl,imx7ulp-sai";
+ reg = <0x410AA000 0x1000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks_m4 IMX7ULP_CM4_CLK_SAI1_IPG>,
+ <&clks_m4 IMX7ULP_CM4_CLK_DUMMY>,
+ <&clks_m4 IMX7ULP_CM4_CLK_SAI1_ROOT>,
+ <&clks_m4 IMX7ULP_CM4_CLK_DUMMY>,
+ <&clks_m4 IMX7ULP_CM4_CLK_DUMMY>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx", "tx";
+ dmas = <&edma0 0 61>, <&edma0 0 62>;
+ status = "disabled";
+ };
+
+ pcc1: pcc1@410b2000 {
+ compatible = "fsl,imx7ulp-pcc1";
+ reg = <0x410b2000 0x1000>;
+ };
+ };
+
+ clocks_m4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cm4_ckil: clock@6 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "cm4_ckil";
+ };
+
+ cm4_osc: clock@7 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "cm4_osc";
+ };
+
+ cm4_sirc: clock@8 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <16000000>;
+ clock-output-names = "cm4_sirc";
+ };
+
+ cm4_firc: clock@9 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <48000000>;
+ clock-output-names = "cm4_firc";
+ };
+ };
+
+ sound-rpmsg {
+ status = "disabled";
+ };
+
+ sound {
+ compatible = "fsl,imx7ulp-evk-wm8960",
+ "fsl,imx-audio-wm8960";
+ model = "wm8960-audio";
+ cpu-dai = <&sai0>;
+ audio-codec = <&codec>;
+ codec-master;
+ /* JD3: hp detect high for headphone*/
+ hp-det = <3 0>;
+ hp-det-gpios = <&gpio3 0 0>;
+ mic-det-gpios = <&gpio3 0 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", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "Mic Jack", "MICB";
+
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_0_1>;
+ status = "okay";
+
+ imx7ulp-evk-0 {
+ pinctrl_hog_0_1: hoggrp-0-1 {
+ fsl,pins = <
+ ULP1_PAD_PTA24__PTA24 0x127
+ ULP1_PAD_PTB0__CLKOUT 0x900
+ >;
+ };
+
+ pinctrl_sai0: sai0_grp {
+ fsl,pins = <
+ ULP1_PAD_PTA4__I2S0_MCLK 0x700
+ ULP1_PAD_PTA5__I2S0_TX_BCLK 0x0700
+ ULP1_PAD_PTA2__I2S0_RXD0 0x0700
+ ULP1_PAD_PTA6__I2S0_TX_FS 0x0700
+ ULP1_PAD_PTA7__I2S0_TXD0 0x0700
+ >;
+ };
+ };
+};
+
+&iomuxc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_audio>;
+
+ imx7ulp-evk {
+ pinctrl_hog_audio: hoggrp-audio {
+ fsl,pins = <
+ ULP1_PAD_PTF0__PTF0 0x30100
+ >;
+ };
+ };
+};
+
+&lpi2c7 {
+ status = "okay";
+
+ codec: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ clocks = <&clks_m4 IMX7ULP_CLK_SCG0_CLKOUT>;
+ clock-names = "mclk";
+ wlf,shared-lrclk;
+ assigned-clocks = <&clks_m4 IMX7ULP_CM4_CLK_APLL_SEL>,
+ <&clks_m4 IMX7ULP_CLK_SCG0_CLKOUT>;
+ assigned-clock-parents = <&clks_m4 IMX7ULP_CM4_CLK_APLL_VCO_POST_DIV2>,
+ <&clks_m4 IMX7ULP_CM4_CLK_APLL_SEL>;
+ };
+};
+
+&clks_m4 {
+ assigned-clocks = <&clks_m4 IMX7ULP_CM4_CLK_APLL_VCO_PRE_SEL>,
+ <&clks_m4 IMX7ULP_CM4_CLK_APLL_VCO>,
+ <&clks_m4 IMX7ULP_CM4_CLK_APLL_VCO_POST_DIV1>,
+ <&clks_m4 IMX7ULP_CM4_CLK_APLL_VCO_POST_DIV2>,
+ <&clks_m4 IMX7ULP_CM4_CLK_APLL_PFD0_PRE_DIV>;
+ assigned-clock-parents = <&clks_m4 IMX7ULP_CM4_CLK_OSC>;
+ assigned-clock-rates = <0>, <540672000>, <49152000>, <12288000>, <270336000>;
+};
+
+&sai0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai0>;
+ assigned-clocks = <&clks_m4 IMX7ULP_CM4_CLK_SAI0_SEL>,
+ <&clks_m4 IMX7ULP_CM4_CLK_SAI0_DIV>;
+ assigned-clock-parents = <&clks_m4 IMX7ULP_CM4_CLK_APLL_PFD0_PRE_DIV>;
+ assigned-clock-rates = <0>, <12288000>;
+ fsl,dataline = <0x1 0x1>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-evk.dts b/arch/arm/boot/dts/imx7ulp-evk.dts
new file mode 100644
index 000000000000..3ee6e3c34747
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-evk.dts
@@ -0,0 +1,551 @@
+/*
+ * Copyright 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 "imx7ulp.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "NXP i.MX7ULP EVK";
+ compatible = "fsl,imx7ulp-evk", "fsl,imx7ulp", "Generic DT based system";
+
+ aliases {
+ gpio4 = &rpmsg_gpio0;
+ gpio5 = &rpmsg_gpio1;
+ };
+
+ chosen {
+ bootargs = "console=ttyLP0,115200 earlycon=lpuart32,0x402D0000,115200";
+ stdout-path = &lpuart4;
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ bcmdhd_fw = "/lib/firmware/bcm/1DX_BCM4343W/fw_bcmdhd.bin";
+ bcmdhd_nv = "/lib/firmware/bcm/1DX_BCM4343W/bcmdhd.1DX.SDIO.cal";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x60000000 0x40000000>;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm0 1 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ mipi_dsi_reset: mipi-dsi-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio0 19 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ modem_reset: modem-reset {
+ compatible = "gpio-reset";
+ reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ #reset-cells = <0>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio2 6 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+
+ reg_usb_otg1_vbus: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usb_otg1>;
+ pinctrl-1 = <&pinctrl_usb_otg1>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_vsd_3v3: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ };
+
+ extcon_usb1: extcon_usb1 {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpio = <&gpio0 8 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_extcon_usb1>;
+ pinctrl-1 = <&pinctrl_extcon_usb1>;
+ };
+
+ 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;
+ };
+ };
+
+ rpmsg_i2s: rpmsg-i2s {
+ compatible = "fsl,imx7ulp-rpmsg-i2s";
+ /* the audio device index in m4 domain */
+ fsl,audioindex = <0> ;
+ status = "okay";
+ };
+
+ rpmsg_gpio0: rpmsg-gpio0 {
+ compatible = "fsl,imx-rpmsg-gpio";
+ port_idx = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ status = "okay";
+ };
+
+ rpmsg_gpio1: rpmsg-gpio1 {
+ compatible = "fsl,imx-rpmsg-gpio";
+ port_idx = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ 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>;
+ };
+ };
+
+ sound-rpmsg {
+ compatible = "fsl,imx-audio-rpmsg";
+ model = "rpmsg-audio";
+ cpu-dai = <&rpmsg_i2s>;
+ };
+};
+
+&cpu0 {
+ arm-supply= <&sw1_reg>;
+};
+
+&iomuxc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+
+ imx7ulp-evk {
+ pinctrl_hog_1: hoggrp-1 {
+ fsl,pins = <
+ ULP1_PAD_PTC1__PTC1 0x20000
+ >;
+ };
+
+ pinctrl_pwm0: pwm0_grp {
+ fsl,pins = <
+ ULP1_PAD_PTF2__TPM4_CH1 0x3
+ >;
+ };
+
+ pinctrl_lpi2c5: lpi2c5grp {
+ fsl,pins = <
+ ULP1_PAD_PTC4__LPI2C5_SCL 0x27
+ ULP1_PAD_PTC5__LPI2C5_SDA 0x27
+ >;
+ };
+
+ pinctrl_mipi_dsi_reset: mipi_dsi_reset_grp {
+ fsl,pins = <
+ ULP1_PAD_PTC19__PTC19 0x20003
+ >;
+ };
+
+ pinctrl_lpuart4: lpuart4grp {
+ fsl,pins = <
+ ULP1_PAD_PTC3__LPUART4_RX 0x3
+ ULP1_PAD_PTC2__LPUART4_TX 0x3
+ >;
+ };
+
+ pinctrl_lpuart6: lpuart6grp {
+ fsl,pins = <
+ ULP1_PAD_PTE10__LPUART6_TX 0x3
+ ULP1_PAD_PTE11__LPUART6_RX 0x3
+ ULP1_PAD_PTE9__LPUART6_RTS_B 0x3
+ ULP1_PAD_PTE8__LPUART6_CTS_B 0x3
+ ULP1_PAD_PTE7__PTE7 0x20000 /* BT_REG_ON */
+ >;
+ };
+
+ pinctrl_lpuart7: lpuart7grp {
+ fsl,pins = <
+ ULP1_PAD_PTF14__LPUART7_TX 0x3
+ ULP1_PAD_PTF15__LPUART7_RX 0x3
+ ULP1_PAD_PTF13__LPUART7_RTS_B 0x3
+ ULP1_PAD_PTF12__LPUART7_CTS_B 0x3
+ >;
+ };
+
+ pinctrl_usdhc0: usdhc0grp {
+ fsl,pins = <
+ ULP1_PAD_PTD1__SDHC0_CMD 0x43
+ ULP1_PAD_PTD2__SDHC0_CLK 0x10043
+ ULP1_PAD_PTD7__SDHC0_D3 0x43
+ ULP1_PAD_PTD8__SDHC0_D2 0x43
+ ULP1_PAD_PTD9__SDHC0_D1 0x43
+ ULP1_PAD_PTD10__SDHC0_D0 0x43
+ ULP1_PAD_PTC10__PTC10 0x10000 /* USDHC0 CD */
+ ULP1_PAD_PTD0__PTD0 0x20000 /* USDHC0 RST */
+ >;
+ };
+
+ pinctrl_usdhc0_8bit: usdhc0grp_8bit {
+ fsl,pins = <
+ ULP1_PAD_PTD1__SDHC0_CMD 0x43
+ ULP1_PAD_PTD2__SDHC0_CLK 0x43
+ ULP1_PAD_PTD3__SDHC0_D7 0x43
+ ULP1_PAD_PTD4__SDHC0_D6 0x43
+ ULP1_PAD_PTD5__SDHC0_D5 0x43
+ ULP1_PAD_PTD6__SDHC0_D4 0x43
+ ULP1_PAD_PTD7__SDHC0_D3 0x43
+ ULP1_PAD_PTD8__SDHC0_D2 0x43
+ ULP1_PAD_PTD9__SDHC0_D1 0x43
+ ULP1_PAD_PTD10__SDHC0_D0 0x43
+ >;
+ };
+
+ pinctrl_lpi2c7: lpi2c7grp {
+ fsl,pins = <
+ ULP1_PAD_PTF12__LPI2C7_SCL 0x27
+ ULP1_PAD_PTF13__LPI2C7_SDA 0x27
+ >;
+ };
+
+ pinctrl_lpspi3: lpspi3grp {
+ fsl,pins = <
+ ULP1_PAD_PTF16__LPSPI3_SIN 0x0
+ ULP1_PAD_PTF17__LPSPI3_SOUT 0x0
+ ULP1_PAD_PTF18__LPSPI3_SCK 0x0
+ ULP1_PAD_PTF19__LPSPI3_PCS0 0x0
+ >;
+ };
+
+ pinctrl_usb_otg1: usbotg1grp {
+ fsl,pins = <
+ ULP1_PAD_PTC0__PTC0 0x20000
+ >;
+ };
+
+ pinctrl_extcon_usb1: extcon1grp {
+ fsl,pins = <
+ ULP1_PAD_PTC8__PTC8 0x10003
+ >;
+ };
+
+ pinctrl_focaltech: focaltechgrp {
+ fsl,pins = <
+ ULP1_PAD_PTF0__PTF0 0x10043
+ ULP1_PAD_PTF1__PTF1 0x20043
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ ULP1_PAD_PTE3__SDHC1_CMD 0x43
+ ULP1_PAD_PTE2__SDHC1_CLK 0x43
+ ULP1_PAD_PTE1__SDHC1_D0 0x43
+ ULP1_PAD_PTE0__SDHC1_D1 0x43
+ ULP1_PAD_PTE5__SDHC1_D2 0x43
+ ULP1_PAD_PTE4__SDHC1_D3 0x43
+ >;
+ };
+
+ pinctrl_usdhc1_rst: usdhc1grp_rst {
+ fsl,pins = <
+ ULP1_PAD_PTE11__PTE11 0x20000 /* USDHC1 RST */
+ ULP1_PAD_PTE13__PTE13 0x10003 /* USDHC1 CD */
+ ULP1_PAD_PTE12__PTE12 0x10003 /* USDHC1 WP */
+ ULP1_PAD_PTE14__SDHC1_VS 0x43 /* USDHC1 VSEL */
+ >;
+ };
+
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ ULP1_PAD_PTE6__PTE6 0x20043 /* WL_REG_ON */
+ >;
+ };
+
+ pinctrl_dsi_hdmi: dsi_hdmi_grp {
+ fsl,pins = <
+ ULP1_PAD_PTC18__PTC18 0x10003 /* DSI_HDMI_INT */
+ >;
+ };
+ };
+};
+
+&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>;
+ };
+ };
+ };
+};
+
+&lpi2c7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_lpi2c7 &pinctrl_focaltech>;
+ pinctrl-1 = <&pinctrl_lpi2c7 &pinctrl_focaltech>;
+ status = "okay";
+
+ focaltech@38 {
+ compatible = "focaltech,fts";
+ reg = <0x38>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <0 0x02>;
+ focaltech,panel-type = <FT5426>;
+ focaltech,reset-gpio = <&gpio3 1 0x01>;
+ focaltech,irq-gpio = <&gpio3 0 0x02>;
+ focaltech,max-touch-number = <5>;
+ focaltech,display-coords = <0 0 272 480>;
+
+ focaltech,have-key;
+ focaltech,key-number = <3>;
+ focaltech,keys = <139 102 158>;
+ focaltech,key-y-coord = <2000>;
+ focaltech,key-x-coords = <200 600 800>;
+ focaltech,scaling-down-half;
+ };
+};
+
+&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_dsi_hdmi>;
+ interrupt-parent = <&gpio0>;
+ 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";
+ };
+};
+
+&lpspi3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ 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>;
+ };
+};
+
+&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";
+};
+
+&lpuart4 { /* console */
+ 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";
+};
+
+&pwm0 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_pwm0>;
+ pinctrl-1 = <&pinctrl_pwm0>;
+ status = "okay";
+};
+
+&rpmsg{
+ /*
+ * 64K for one rpmsg instance, default using 2 rpmsg instances:
+ * --0x9FF00000~0x9FF0FFFF: pmic,pm,audio,keys,gpio
+ * --0x9FF10000~0x9FF1FFFF: pingpong,virtual tty
+ */
+ vdev-nums = <2>;
+ reg = <0x9FF00000 0x20000>;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ extcon = <0>, <&extcon_usb1>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbphy1 {
+ tx-d-cal = <0xc>;
+};
+
+&usdhc0 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc0>;
+ pinctrl-1 = <&pinctrl_usdhc0>;
+ pinctrl-2 = <&pinctrl_usdhc0>;
+ pinctrl-3 = <&pinctrl_usdhc0>;
+ cd-gpios = <&gpio0 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_wifi>;
+ pinctrl-1 = <&pinctrl_usdhc1 &pinctrl_wifi>;
+ non-removable;
+ keep-power-in-suspend;
+ cd-post;
+ pm-ignore-notify;
+ wifi-host;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7ulp-pinfunc.h b/arch/arm/boot/dts/imx7ulp-pinfunc.h
new file mode 100644
index 000000000000..388345d62db5
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp-pinfunc.h
@@ -0,0 +1,875 @@
+/*
+ * Copyright 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.
+ *
+ */
+
+#ifndef __DTS_ULP1_PINFUNC_H
+#define __DTS_ULP1_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_conf_reg input_reg mux_mode input_val>
+ */
+
+#define ULP1_PAD_PTA0_LLWU0_P0__CMP0_IN2A 0x0000 0x0000 0x0 0x0
+#define ULP1_PAD_PTA0_LLWU0_P0__PTA0 0x0000 0x0000 0x1 0x0
+#define ULP1_PAD_PTA0_LLWU0_P0__LLWU0_P0 0x0000 0x0000 0xd 0x0
+#define ULP1_PAD_PTA0_LLWU0_P0__LPSPI0_PCS1 0x0000 0xd104 0x3 0x2
+#define ULP1_PAD_PTA0_LLWU0_P0__LPUART0_CTS_B 0x0000 0xd1f8 0x4 0x2
+#define ULP1_PAD_PTA0_LLWU0_P0__LPI2C0_SCL 0x0000 0xd17c 0x5 0x2
+#define ULP1_PAD_PTA0_LLWU0_P0__TPM0_CLKIN 0x0000 0xd1a8 0x6 0x2
+#define ULP1_PAD_PTA0_LLWU0_P0__I2S0_RX_BCLK 0x0000 0x01b8 0x7 0x2
+#define ULP1_PAD_PTA1__CMP0_IN2B 0x0004 0x0000 0x0 0x0
+#define ULP1_PAD_PTA1__PTA1 0x0004 0x0000 0x1 0x0
+#define ULP1_PAD_PTA1__LPSPI0_PCS2 0x0004 0xd108 0x3 0x1
+#define ULP1_PAD_PTA1__LPUART0_RTS_B 0x0004 0x0000 0x4 0x0
+#define ULP1_PAD_PTA1__LPI2C0_SDA 0x0004 0xd180 0x5 0x1
+#define ULP1_PAD_PTA1__TPM0_CH0 0x0004 0xd138 0x6 0x1
+#define ULP1_PAD_PTA1__I2S0_RX_FS 0x0004 0x01bc 0x7 0x1
+#define ULP1_PAD_PTA2__CMP1_IN2A 0x0008 0x0000 0x0 0x0
+#define ULP1_PAD_PTA2__PTA2 0x0008 0x0000 0x1 0x0
+#define ULP1_PAD_PTA2__LPSPI0_PCS3 0x0008 0xd10c 0x3 0x1
+#define ULP1_PAD_PTA2__LPUART0_TX 0x0008 0xd200 0x4 0x1
+#define ULP1_PAD_PTA2__LPI2C0_HREQ 0x0008 0xd178 0x5 0x1
+#define ULP1_PAD_PTA2__TPM0_CH1 0x0008 0xd13c 0x6 0x1
+#define ULP1_PAD_PTA2__I2S0_RXD0 0x0008 0x01dc 0x7 0x1
+#define ULP1_PAD_PTA3_LLWU0_P1__CMP1_IN2B 0x000c 0x0000 0x0 0x0
+#define ULP1_PAD_PTA3_LLWU0_P1__PTA3 0x000c 0x0000 0x1 0x0
+#define ULP1_PAD_PTA3_LLWU0_P1__CMP0_OUT 0x000c 0x0000 0xb 0x0
+#define ULP1_PAD_PTA3_LLWU0_P1__LLWU0_P1 0x000c 0x0000 0xd 0x0
+#define ULP1_PAD_PTA3_LLWU0_P1__LPUART0_RX 0x000c 0xd1fc 0x4 0x1
+#define ULP1_PAD_PTA3_LLWU0_P1__TPM0_CH2 0x000c 0xd140 0x6 0x1
+#define ULP1_PAD_PTA3_LLWU0_P1__I2S0_RXD1 0x000c 0x01e0 0x7 0x1
+#define ULP1_PAD_PTA4__ADC1_CH2A 0x0010 0x0000 0x0 0x0
+#define ULP1_PAD_PTA4__PTA4 0x0010 0x0000 0x1 0x0
+#define ULP1_PAD_PTA4__LPSPI0_SIN 0x0010 0xd114 0x3 0x1
+#define ULP1_PAD_PTA4__LPUART1_CTS_B 0x0010 0xd204 0x4 0x1
+#define ULP1_PAD_PTA4__LPI2C1_SCL 0x0010 0xd188 0x5 0x1
+#define ULP1_PAD_PTA4__TPM0_CH3 0x0010 0xd144 0x6 0x1
+#define ULP1_PAD_PTA4__I2S0_MCLK 0x0010 0x01b4 0x7 0x1
+#define ULP1_PAD_PTA5__ADC1_CH2B 0x0014 0x0000 0x0 0x0
+#define ULP1_PAD_PTA5__PTA5 0x0014 0x0000 0x1 0x0
+#define ULP1_PAD_PTA5__LPSPI0_SOUT 0x0014 0xd118 0x3 0x1
+#define ULP1_PAD_PTA5__LPUART1_RTS_B 0x0014 0x0000 0x4 0x0
+#define ULP1_PAD_PTA5__LPI2C1_SDA 0x0014 0xd18c 0x5 0x1
+#define ULP1_PAD_PTA5__TPM0_CH4 0x0014 0xd148 0x6 0x1
+#define ULP1_PAD_PTA5__I2S0_TX_BCLK 0x0014 0x01c0 0x7 0x1
+#define ULP1_PAD_PTA6__ADC1_CH3A 0x0018 0x0000 0x0 0x0
+#define ULP1_PAD_PTA6__PTA6 0x0018 0x0000 0x1 0x0
+#define ULP1_PAD_PTA6__LPSPI0_SCK 0x0018 0xd110 0x3 0x1
+#define ULP1_PAD_PTA6__LPUART1_TX 0x0018 0xd20c 0x4 0x1
+#define ULP1_PAD_PTA6__LPI2C1_HREQ 0x0018 0xd184 0x5 0x1
+#define ULP1_PAD_PTA6__TPM0_CH5 0x0018 0xd14c 0x6 0x1
+#define ULP1_PAD_PTA6__I2S0_TX_FS 0x0018 0x01c4 0x7 0x1
+#define ULP1_PAD_PTA7__ADC1_CH3B 0x001c 0x0000 0x0 0x0
+#define ULP1_PAD_PTA7__PTA7 0x001c 0x0000 0x1 0x0
+#define ULP1_PAD_PTA7__LPSPI0_PCS0 0x001c 0xd100 0x3 0x1
+#define ULP1_PAD_PTA7__LPUART1_RX 0x001c 0xd208 0x4 0x1
+#define ULP1_PAD_PTA7__TPM1_CH1 0x001c 0xd154 0x6 0x1
+#define ULP1_PAD_PTA7__I2S0_TXD0 0x001c 0x0000 0x7 0x0
+#define ULP1_PAD_PTA8__ADC1_CH7A 0x0020 0x0000 0x0 0x0
+#define ULP1_PAD_PTA8__PTA8 0x0020 0x0000 0x1 0x0
+#define ULP1_PAD_PTA8__LPSPI1_PCS1 0x0020 0xd120 0x3 0x1
+#define ULP1_PAD_PTA8__LPUART2_CTS_B 0x0020 0xd210 0x4 0x1
+#define ULP1_PAD_PTA8__LPI2C2_SCL 0x0020 0xd194 0x5 0x1
+#define ULP1_PAD_PTA8__TPM1_CLKIN 0x0020 0xd1ac 0x6 0x1
+#define ULP1_PAD_PTA8__I2S0_TXD1 0x0020 0x0000 0x7 0x0
+#define ULP1_PAD_PTA9__ADC1_CH7B 0x0024 0x0000 0x0 0x0
+#define ULP1_PAD_PTA9__PTA9 0x0024 0x0000 0x1 0x0
+#define ULP1_PAD_PTA9__NMI0_B 0x0024 0x0000 0xb 0x0
+#define ULP1_PAD_PTA9__LPSPI1_PCS2 0x0024 0xd124 0x3 0x1
+#define ULP1_PAD_PTA9__LPUART2_RTS_B 0x0024 0x0000 0x4 0x0
+#define ULP1_PAD_PTA9__LPI2C2_SDA 0x0024 0xd198 0x5 0x1
+#define ULP1_PAD_PTA9__TPM1_CH0 0x0024 0xd150 0x6 0x1
+#define ULP1_PAD_PTA10__ADC1_CH6A 0x0028 0x0000 0x0 0x0
+#define ULP1_PAD_PTA10__PTA10 0x0028 0x0000 0x1 0x0
+#define ULP1_PAD_PTA10__LPSPI1_PCS3 0x0028 0xd128 0x3 0x1
+#define ULP1_PAD_PTA10__LPUART2_TX 0x0028 0xd218 0x4 0x1
+#define ULP1_PAD_PTA10__LPI2C2_HREQ 0x0028 0xd190 0x5 0x1
+#define ULP1_PAD_PTA10__TPM2_CLKIN 0x0028 0xd1f4 0x6 0x1
+#define ULP1_PAD_PTA10__I2S0_RX_BCLK 0x0028 0x01b8 0x7 0x1
+#define ULP1_PAD_PTA11__ADC1_CH6B 0x002c 0x0000 0x0 0x0
+#define ULP1_PAD_PTA11__PTA11 0x002c 0x0000 0x1 0x0
+#define ULP1_PAD_PTA11__LPUART2_RX 0x002c 0xd214 0x4 0x1
+#define ULP1_PAD_PTA11__TPM2_CH0 0x002c 0xd158 0x6 0x1
+#define ULP1_PAD_PTA11__I2S0_RX_FS 0x002c 0x01bc 0x7 0x2
+#define ULP1_PAD_PTA12__ADC1_CH5A 0x0030 0x0000 0x0 0x0
+#define ULP1_PAD_PTA12__PTA12 0x0030 0x0000 0x1 0x0
+#define ULP1_PAD_PTA12__LPSPI1_SIN 0x0030 0xd130 0x3 0x1
+#define ULP1_PAD_PTA12__LPUART3_CTS_B 0x0030 0xd21c 0x4 0x1
+#define ULP1_PAD_PTA12__LPI2C3_SCL 0x0030 0xd1a0 0x5 0x1
+#define ULP1_PAD_PTA12__TPM2_CH1 0x0030 0xd15c 0x6 0x1
+#define ULP1_PAD_PTA12__I2S0_RXD0 0x0030 0x01dc 0x7 0x2
+#define ULP1_PAD_PTA13_LLWU0_P2__ADC1_CH5B 0x0034 0x0000 0x0 0x0
+#define ULP1_PAD_PTA13_LLWU0_P2__PTA13 0x0034 0x0000 0x1 0x0
+#define ULP1_PAD_PTA13_LLWU0_P2__CMP0_OUT 0x0034 0x0000 0xb 0x0
+#define ULP1_PAD_PTA13_LLWU0_P2__LLWU0_P2 0x0034 0x0000 0xd 0x0
+#define ULP1_PAD_PTA13_LLWU0_P2__LPSPI1_SOUT 0x0034 0xd134 0x3 0x2
+#define ULP1_PAD_PTA13_LLWU0_P2__LPUART3_RTS_B 0x0034 0x0000 0x4 0x0
+#define ULP1_PAD_PTA13_LLWU0_P2__LPI2C3_SDA 0x0034 0xd1a4 0x5 0x2
+#define ULP1_PAD_PTA13_LLWU0_P2__TPM3_CLKIN 0x0034 0xd1b0 0x6 0x1
+#define ULP1_PAD_PTA13_LLWU0_P2__I2S0_RXD1 0x0034 0x01e0 0x7 0x2
+#define ULP1_PAD_PTA14_LLWU0_P3__ADC1_CH4A 0x0038 0x0000 0x0 0x0
+#define ULP1_PAD_PTA14_LLWU0_P3__PTA14 0x0038 0x0000 0x1 0x0
+#define ULP1_PAD_PTA14_LLWU0_P3__LLWU0_P3 0x0038 0x0000 0xd 0x0
+#define ULP1_PAD_PTA14_LLWU0_P3__LPSPI1_SCK 0x0038 0xd12c 0x3 0x2
+#define ULP1_PAD_PTA14_LLWU0_P3__LPUART3_TX 0x0038 0xd224 0x4 0x2
+#define ULP1_PAD_PTA14_LLWU0_P3__LPI2C3_HREQ 0x0038 0xd19c 0x5 0x2
+#define ULP1_PAD_PTA14_LLWU0_P3__TPM3_CH0 0x0038 0xd160 0x6 0x1
+#define ULP1_PAD_PTA14_LLWU0_P3__I2S0_MCLK 0x0038 0x01b4 0x7 0x2
+#define ULP1_PAD_PTA15__ADC1_CH4B 0x003c 0x0000 0x0 0x0
+#define ULP1_PAD_PTA15__PTA15 0x003c 0x0000 0x1 0x0
+#define ULP1_PAD_PTA15__LPSPI1_PCS0 0x003c 0xd11c 0x3 0x1
+#define ULP1_PAD_PTA15__LPUART3_RX 0x003c 0xd220 0x4 0x1
+#define ULP1_PAD_PTA15__TPM3_CH1 0x003c 0xd164 0x6 0x1
+#define ULP1_PAD_PTA15__I2S0_TX_BCLK 0x003c 0x01c0 0x7 0x2
+#define ULP1_PAD_PTA16__CMP1_IN0A 0x0040 0x0000 0x0 0x0
+#define ULP1_PAD_PTA16__PTA16 0x0040 0x0000 0x1 0x0
+#define ULP1_PAD_PTA16__FXIO0_D0 0x0040 0x0000 0x2 0x0
+#define ULP1_PAD_PTA16__LPSPI0_PCS1 0x0040 0xd104 0x3 0x1
+#define ULP1_PAD_PTA16__LPUART0_CTS_B 0x0040 0xd1f8 0x4 0x1
+#define ULP1_PAD_PTA16__LPI2C0_SCL 0x0040 0xd17c 0x5 0x1
+#define ULP1_PAD_PTA16__TPM3_CH2 0x0040 0xd168 0x6 0x1
+#define ULP1_PAD_PTA16__I2S0_TX_FS 0x0040 0x01c4 0x7 0x2
+#define ULP1_PAD_PTA17__CMP1_IN0B 0x0044 0x0000 0x0 0x0
+#define ULP1_PAD_PTA17__PTA17 0x0044 0x0000 0x1 0x0
+#define ULP1_PAD_PTA17__FXIO0_D1 0x0044 0x0000 0x2 0x0
+#define ULP1_PAD_PTA17__LPSPI0_PCS2 0x0044 0xd108 0x3 0x2
+#define ULP1_PAD_PTA17__LPUART0_RTS_B 0x0044 0x0000 0x4 0x0
+#define ULP1_PAD_PTA17__LPI2C0_SDA 0x0044 0xd180 0x5 0x2
+#define ULP1_PAD_PTA17__TPM3_CH3 0x0044 0xd16c 0x6 0x1
+#define ULP1_PAD_PTA17__I2S0_TXD0 0x0044 0x0000 0x7 0x0
+#define ULP1_PAD_PTA18_LLWU0_P4__CMP1_IN1A 0x0048 0x0000 0x0 0x0
+#define ULP1_PAD_PTA18_LLWU0_P4__PTA18 0x0048 0x0000 0x1 0x0
+#define ULP1_PAD_PTA18_LLWU0_P4__NMI1_B 0x0048 0x0000 0xb 0x0
+#define ULP1_PAD_PTA18_LLWU0_P4__LLWU0_P4 0x0048 0x0000 0xd 0x0
+#define ULP1_PAD_PTA18_LLWU0_P4__FXIO0_D2 0x0048 0x0000 0x2 0x0
+#define ULP1_PAD_PTA18_LLWU0_P4__LPSPI0_PCS3 0x0048 0xd10c 0x3 0x2
+#define ULP1_PAD_PTA18_LLWU0_P4__LPUART0_TX 0x0048 0xd200 0x4 0x2
+#define ULP1_PAD_PTA18_LLWU0_P4__LPI2C0_HREQ 0x0048 0xd178 0x5 0x2
+#define ULP1_PAD_PTA18_LLWU0_P4__TPM3_CH4 0x0048 0xd170 0x6 0x1
+#define ULP1_PAD_PTA18_LLWU0_P4__I2S0_TXD1 0x0048 0x0000 0x7 0x0
+#define ULP1_PAD_PTA19_LLWU0_P5__CMP1_IN1B 0x004c 0x0000 0x0 0x0
+#define ULP1_PAD_PTA19_LLWU0_P5__PTA19 0x004c 0x0000 0x1 0x0
+#define ULP1_PAD_PTA19_LLWU0_P5__LPTMR0_ALT3 0x004c 0x0000 0xb 0x0
+#define ULP1_PAD_PTA19_LLWU0_P5__LLWU0_P5 0x004c 0x0000 0xd 0x0
+#define ULP1_PAD_PTA19_LLWU0_P5__FXIO0_D3 0x004c 0x0000 0x2 0x0
+#define ULP1_PAD_PTA19_LLWU0_P5__LPUART0_RX 0x004c 0xd1fc 0x4 0x2
+#define ULP1_PAD_PTA19_LLWU0_P5__TPM3_CH5 0x004c 0xd174 0x6 0x1
+#define ULP1_PAD_PTA19_LLWU0_P5__I2S1_RX_BCLK 0x004c 0xd1cc 0x7 0x1
+#define ULP1_PAD_PTA20__ADC0_CH7A 0x0050 0x0000 0x0 0x0
+#define ULP1_PAD_PTA20__PTA20 0x0050 0x0000 0x1 0x0
+#define ULP1_PAD_PTA20__FXIO0_D4 0x0050 0x0000 0x2 0x0
+#define ULP1_PAD_PTA20__LPSPI0_SIN 0x0050 0xd114 0x3 0x2
+#define ULP1_PAD_PTA20__LPUART1_CTS_B 0x0050 0xd204 0x4 0x2
+#define ULP1_PAD_PTA20__LPI2C1_SCL 0x0050 0xd188 0x5 0x2
+#define ULP1_PAD_PTA20__TPM0_CLKIN 0x0050 0xd1a8 0x6 0x1
+#define ULP1_PAD_PTA20__I2S1_RX_FS 0x0050 0xd1d0 0x7 0x1
+#define ULP1_PAD_PTA21__ADC0_CH7B 0x0054 0x0000 0x0 0x0
+#define ULP1_PAD_PTA21__PTA21 0x0054 0x0000 0x1 0x0
+#define ULP1_PAD_PTA21__FXIO0_D5 0x0054 0x0000 0x2 0x0
+#define ULP1_PAD_PTA21__LPSPI0_SOUT 0x0054 0xd118 0x3 0x2
+#define ULP1_PAD_PTA21__LPUART1_RTS_B 0x0054 0x0000 0x4 0x0
+#define ULP1_PAD_PTA21__LPI2C1_SDA 0x0054 0xd18c 0x5 0x2
+#define ULP1_PAD_PTA21__TPM0_CH0 0x0054 0xd138 0x6 0x2
+#define ULP1_PAD_PTA21__I2S1_RXD0 0x0054 0xd1e4 0x7 0x1
+#define ULP1_PAD_PTA22__ADC0_CH6A 0x0058 0x0000 0x0 0x0
+#define ULP1_PAD_PTA22__PTA22 0x0058 0x0000 0x1 0x0
+#define ULP1_PAD_PTA22__LPTMR0_ALT2 0x0058 0x0000 0xb 0x0
+#define ULP1_PAD_PTA22__EWM_OUT_B 0x0058 0x0000 0xc 0x0
+#define ULP1_PAD_PTA22__FXIO0_D6 0x0058 0x0000 0x2 0x0
+#define ULP1_PAD_PTA22__LPSPI0_SCK 0x0058 0xd110 0x3 0x2
+#define ULP1_PAD_PTA22__LPUART1_TX 0x0058 0xd20c 0x4 0x2
+#define ULP1_PAD_PTA22__LPI2C1_HREQ 0x0058 0xd184 0x5 0x2
+#define ULP1_PAD_PTA22__TPM0_CH1 0x0058 0xd13c 0x6 0x2
+#define ULP1_PAD_PTA22__I2S1_RXD1 0x0058 0xd1e8 0x7 0x1
+#define ULP1_PAD_PTA23_LLWU0_P6__ADC0_CH6B 0x005c 0x0000 0x0 0x0
+#define ULP1_PAD_PTA23_LLWU0_P6__PTA23 0x005c 0x0000 0x1 0x0
+#define ULP1_PAD_PTA23_LLWU0_P6__LLWU0_P6 0x005c 0x0000 0xd 0x0
+#define ULP1_PAD_PTA23_LLWU0_P6__FXIO0_D7 0x005c 0x0000 0x2 0x0
+#define ULP1_PAD_PTA23_LLWU0_P6__LPSPI0_PCS0 0x005c 0xd100 0x3 0x2
+#define ULP1_PAD_PTA23_LLWU0_P6__LPUART1_RX 0x005c 0xd208 0x4 0x2
+#define ULP1_PAD_PTA23_LLWU0_P6__TPM0_CH2 0x005c 0xd140 0x6 0x2
+#define ULP1_PAD_PTA23_LLWU0_P6__I2S1_MCLK 0x005c 0xd1c8 0x7 0x1
+#define ULP1_PAD_PTA24__ADC0_CH5A 0x0060 0x0000 0x0 0x0
+#define ULP1_PAD_PTA24__PTA24 0x0060 0x0000 0x1 0x0
+#define ULP1_PAD_PTA24__FXIO0_D8 0x0060 0x0000 0x2 0x0
+#define ULP1_PAD_PTA24__LPSPI1_PCS1 0x0060 0xd120 0x3 0x2
+#define ULP1_PAD_PTA24__LPUART2_CTS_B 0x0060 0xd210 0x4 0x2
+#define ULP1_PAD_PTA24__LPI2C2_SCL 0x0060 0xd194 0x5 0x2
+#define ULP1_PAD_PTA24__TPM0_CH3 0x0060 0xd144 0x6 0x2
+#define ULP1_PAD_PTA24__I2S1_TX_BCLK 0x0060 0xd1d4 0x7 0x1
+#define ULP1_PAD_PTA25__ADC0_CH5B 0x0064 0x0000 0x0 0x0
+#define ULP1_PAD_PTA25__PTA25 0x0064 0x0000 0x1 0x0
+#define ULP1_PAD_PTA25__FXIO0_D9 0x0064 0x0000 0x2 0x0
+#define ULP1_PAD_PTA25__LPSPI1_PCS2 0x0064 0xd124 0x3 0x2
+#define ULP1_PAD_PTA25__LPUART2_RTS_B 0x0064 0x0000 0x4 0x0
+#define ULP1_PAD_PTA25__LPI2C2_SDA 0x0064 0xd198 0x5 0x2
+#define ULP1_PAD_PTA25__TPM0_CH4 0x0064 0xd148 0x6 0x2
+#define ULP1_PAD_PTA25__I2S1_TX_FS 0x0064 0xd1d8 0x7 0x1
+#define ULP1_PAD_PTA26__PTA26 0x0068 0x0000 0x1 0x0
+#define ULP1_PAD_PTA26__JTAG_TMS_SWD_DIO 0x0068 0x0000 0xa 0x0
+#define ULP1_PAD_PTA26__FXIO0_D10 0x0068 0x0000 0x2 0x0
+#define ULP1_PAD_PTA26__LPSPI1_PCS3 0x0068 0xd128 0x3 0x2
+#define ULP1_PAD_PTA26__LPUART2_TX 0x0068 0xd218 0x4 0x2
+#define ULP1_PAD_PTA26__LPI2C2_HREQ 0x0068 0xd190 0x5 0x2
+#define ULP1_PAD_PTA26__TPM0_CH5 0x0068 0xd14c 0x6 0x2
+#define ULP1_PAD_PTA26__I2S1_RXD2 0x0068 0xd1ec 0x7 0x1
+#define ULP1_PAD_PTA27__PTA27 0x006c 0x0000 0x1 0x0
+#define ULP1_PAD_PTA27__JTAG_TDO 0x006c 0x0000 0xa 0x0
+#define ULP1_PAD_PTA27__FXIO0_D11 0x006c 0x0000 0x2 0x0
+#define ULP1_PAD_PTA27__LPUART2_RX 0x006c 0xd214 0x4 0x2
+#define ULP1_PAD_PTA27__TPM1_CH1 0x006c 0xd154 0x6 0x2
+#define ULP1_PAD_PTA27__I2S1_RXD3 0x006c 0xd1f0 0x7 0x1
+#define ULP1_PAD_PTA28__PTA28 0x0070 0x0000 0x1 0x0
+#define ULP1_PAD_PTA28__JTAG_TDI 0x0070 0x0000 0xa 0x0
+#define ULP1_PAD_PTA28__FXIO0_D12 0x0070 0x0000 0x2 0x0
+#define ULP1_PAD_PTA28__LPSPI1_SIN 0x0070 0xd130 0x3 0x2
+#define ULP1_PAD_PTA28__LPUART3_CTS_B 0x0070 0xd21c 0x4 0x2
+#define ULP1_PAD_PTA28__LPI2C3_SCL 0x0070 0xd1a0 0x5 0x2
+#define ULP1_PAD_PTA28__TPM1_CLKIN 0x0070 0xd1ac 0x6 0x2
+#define ULP1_PAD_PTA28__I2S1_TXD2 0x0070 0x0000 0x7 0x0
+#define ULP1_PAD_PTA29__PTA29 0x0074 0x0000 0x1 0x0
+#define ULP1_PAD_PTA29__JTAG_TCLK_SWD_CLK 0x0074 0x0000 0xa 0x0
+#define ULP1_PAD_PTA29__FXIO0_D13 0x0074 0x0000 0x2 0x0
+#define ULP1_PAD_PTA29__LPSPI1_SOUT 0x0074 0xd134 0x3 0x1
+#define ULP1_PAD_PTA29__LPUART3_RTS_B 0x0074 0x0000 0x4 0x0
+#define ULP1_PAD_PTA29__LPI2C3_SDA 0x0074 0xd1a4 0x5 0x1
+#define ULP1_PAD_PTA29__TPM1_CH0 0x0074 0xd150 0x6 0x2
+#define ULP1_PAD_PTA29__I2S1_TXD3 0x0074 0x0000 0x7 0x0
+#define ULP1_PAD_PTA30__ADC0_CH4A 0x0078 0x0000 0x0 0x0
+#define ULP1_PAD_PTA30__PTA30 0x0078 0x0000 0x1 0x0
+#define ULP1_PAD_PTA30__JTAG_TRST_B 0x0078 0x0000 0xa 0x0
+#define ULP1_PAD_PTA30__FXIO0_D14 0x0078 0x0000 0x2 0x0
+#define ULP1_PAD_PTA30__LPSPI1_SCK 0x0078 0xd12c 0x3 0x1
+#define ULP1_PAD_PTA30__LPUART3_TX 0x0078 0xd224 0x4 0x1
+#define ULP1_PAD_PTA30__LPI2C3_HREQ 0x0078 0xd19c 0x5 0x1
+#define ULP1_PAD_PTA30__TPM2_CLKIN 0x0078 0xd1f4 0x6 0x2
+#define ULP1_PAD_PTA30__I2S1_TXD0 0x0078 0x0000 0x7 0x0
+#define ULP1_PAD_PTA31_LLWU0_P7__ADC0_CH4B 0x007c 0x0000 0x0 0x0
+#define ULP1_PAD_PTA31_LLWU0_P7__PTA31 0x007c 0x0000 0x1 0x0
+#define ULP1_PAD_PTA31_LLWU0_P7__LPTMR0_ALT1 0x007c 0x0000 0xb 0x0
+#define ULP1_PAD_PTA31_LLWU0_P7__EWM_IN 0x007c 0xd228 0xc 0x1
+#define ULP1_PAD_PTA31_LLWU0_P7__LLWU0_P7 0x007c 0x0000 0xd 0x0
+#define ULP1_PAD_PTA31_LLWU0_P7__FXIO0_D15 0x007c 0x0000 0x2 0x0
+#define ULP1_PAD_PTA31_LLWU0_P7__LPSPI1_PCS0 0x007c 0xd11c 0x3 0x2
+#define ULP1_PAD_PTA31_LLWU0_P7__LPUART3_RX 0x007c 0xd220 0x4 0x2
+#define ULP1_PAD_PTA31_LLWU0_P7__TPM2_CH0 0x007c 0xd158 0x6 0x2
+#define ULP1_PAD_PTA31_LLWU0_P7__I2S1_TXD1 0x007c 0x0000 0x7 0x0
+#define ULP1_PAD_PTB0__ADC0_CH0A 0x0080 0x0000 0x0 0x0
+#define ULP1_PAD_PTB0__PTB0 0x0080 0x0000 0x1 0x0
+#define ULP1_PAD_PTB0__CMP1_OUT 0x0080 0x0000 0xb 0x0
+#define ULP1_PAD_PTB0__EWM_OUT_B 0x0080 0x0000 0xc 0x0
+#define ULP1_PAD_PTB0__FXIO0_D16 0x0080 0x0000 0x2 0x0
+#define ULP1_PAD_PTB0__LPSPI0_SIN 0x0080 0xd114 0x3 0x3
+#define ULP1_PAD_PTB0__LPUART0_TX 0x0080 0xd200 0x4 0x3
+#define ULP1_PAD_PTB0__TPM2_CH1 0x0080 0xd15c 0x6 0x2
+#define ULP1_PAD_PTB0__CLKOUT 0x0080 0x0000 0x9 0x0
+#define ULP1_PAD_PTB1_LLWU0_P8__ADC0_CH0B 0x0084 0x0000 0x0 0x0
+#define ULP1_PAD_PTB1_LLWU0_P8__PTB1 0x0084 0x0000 0x1 0x0
+#define ULP1_PAD_PTB1_LLWU0_P8__RTC_CLKOUT 0x0084 0x0000 0xb 0x0
+#define ULP1_PAD_PTB1_LLWU0_P8__EWM_IN 0x0084 0xd228 0xc 0x2
+#define ULP1_PAD_PTB1_LLWU0_P8__LLWU0_P8 0x0084 0x0000 0xd 0x0
+#define ULP1_PAD_PTB1_LLWU0_P8__FXIO0_D17 0x0084 0x0000 0x2 0x0
+#define ULP1_PAD_PTB1_LLWU0_P8__LPSPI0_SOUT 0x0084 0xd118 0x3 0x3
+#define ULP1_PAD_PTB1_LLWU0_P8__LPUART0_RX 0x0084 0xd1fc 0x4 0x3
+#define ULP1_PAD_PTB1_LLWU0_P8__TPM3_CLKIN 0x0084 0xd1b0 0x6 0x3
+#define ULP1_PAD_PTB1_LLWU0_P8__I2S1_TX_BCLK 0x0084 0xd1d4 0x7 0x2
+#define ULP1_PAD_PTB2__ADC0_CH1A 0x0088 0x0000 0x0 0x0
+#define ULP1_PAD_PTB2__PTB2 0x0088 0x0000 0x1 0x0
+#define ULP1_PAD_PTB2__TRACE_CLKOUT 0x0088 0x0000 0xa 0x0
+#define ULP1_PAD_PTB2__FXIO0_D18 0x0088 0x0000 0x2 0x0
+#define ULP1_PAD_PTB2__LPSPI0_SCK 0x0088 0xd110 0x3 0x3
+#define ULP1_PAD_PTB2__LPUART1_TX 0x0088 0xd20c 0x4 0x3
+#define ULP1_PAD_PTB2__TPM3_CH0 0x0088 0xd160 0x6 0x2
+#define ULP1_PAD_PTB2__I2S1_TX_FS 0x0088 0xd1d8 0x7 0x2
+#define ULP1_PAD_PTB3_LLWU0_P9__ADC0_CH1B 0x008c 0x0000 0x0 0x0
+#define ULP1_PAD_PTB3_LLWU0_P9__PTB3 0x008c 0x0000 0x1 0x0
+#define ULP1_PAD_PTB3_LLWU0_P9__TRACE_D0 0x008c 0x0000 0xa 0x0
+#define ULP1_PAD_PTB3_LLWU0_P9__LPTMR1_ALT2 0x008c 0x0000 0xb 0x0
+#define ULP1_PAD_PTB3_LLWU0_P9__LLWU0_P9 0x008c 0x0000 0xd 0x0
+#define ULP1_PAD_PTB3_LLWU0_P9__FXIO0_D19 0x008c 0x0000 0x2 0x0
+#define ULP1_PAD_PTB3_LLWU0_P9__LPSPI0_PCS0 0x008c 0xd100 0x3 0x3
+#define ULP1_PAD_PTB3_LLWU0_P9__LPUART1_RX 0x008c 0xd208 0x4 0x3
+#define ULP1_PAD_PTB3_LLWU0_P9__TPM3_CH1 0x008c 0xd164 0x6 0x2
+#define ULP1_PAD_PTB3_LLWU0_P9__I2S1_TXD0 0x008c 0x0000 0x7 0x0
+#define ULP1_PAD_PTB4__PTB4 0x0090 0x0000 0x1 0x0
+#define ULP1_PAD_PTB4__TRACE_D1 0x0090 0x0000 0xa 0x0
+#define ULP1_PAD_PTB4__BOOTCFG0 0x0090 0x0000 0xd 0x0
+#define ULP1_PAD_PTB4__FXIO0_D20 0x0090 0x0000 0x2 0x0
+#define ULP1_PAD_PTB4__LPSPI0_PCS1 0x0090 0xd104 0x3 0x3
+#define ULP1_PAD_PTB4__LPUART2_TX 0x0090 0xd218 0x4 0x3
+#define ULP1_PAD_PTB4__LPI2C0_HREQ 0x0090 0xd178 0x5 0x3
+#define ULP1_PAD_PTB4__TPM3_CH2 0x0090 0xd168 0x6 0x2
+#define ULP1_PAD_PTB4__I2S1_TXD1 0x0090 0x0000 0x7 0x0
+#define ULP1_PAD_PTB5__PTB5 0x0094 0x0000 0x1 0x0
+#define ULP1_PAD_PTB5__TRACE_D2 0x0094 0x0000 0xa 0x0
+#define ULP1_PAD_PTB5__BOOTCFG1 0x0094 0x0000 0xd 0x0
+#define ULP1_PAD_PTB5__FXIO0_D21 0x0094 0x0000 0x2 0x0
+#define ULP1_PAD_PTB5__LPSPI0_PCS2 0x0094 0xd108 0x3 0x3
+#define ULP1_PAD_PTB5__LPUART2_RX 0x0094 0xd214 0x4 0x3
+#define ULP1_PAD_PTB5__LPI2C1_HREQ 0x0094 0xd184 0x5 0x3
+#define ULP1_PAD_PTB5__TPM3_CH3 0x0094 0xd16c 0x6 0x2
+#define ULP1_PAD_PTB5__I2S1_TXD2 0x0094 0x0000 0x7 0x0
+#define ULP1_PAD_PTB6_LLWU0_P10__PTB6 0x0098 0x0000 0x1 0x0
+#define ULP1_PAD_PTB6_LLWU0_P10__TRACE_D3 0x0098 0x0000 0xa 0x0
+#define ULP1_PAD_PTB6_LLWU0_P10__LPTMR1_ALT3 0x0098 0x0000 0xb 0x0
+#define ULP1_PAD_PTB6_LLWU0_P10__LLWU0_P10 0x0098 0x0000 0xd 0x0
+#define ULP1_PAD_PTB6_LLWU0_P10__FXIO0_D22 0x0098 0x0000 0x2 0x0
+#define ULP1_PAD_PTB6_LLWU0_P10__LPSPI0_PCS3 0x0098 0xd10c 0x3 0x3
+#define ULP1_PAD_PTB6_LLWU0_P10__LPUART3_TX 0x0098 0xd224 0x4 0x3
+#define ULP1_PAD_PTB6_LLWU0_P10__LPI2C0_SCL 0x0098 0xd17c 0x5 0x3
+#define ULP1_PAD_PTB6_LLWU0_P10__TPM3_CH4 0x0098 0xd170 0x6 0x2
+#define ULP1_PAD_PTB6_LLWU0_P10__I2S1_TXD3 0x0098 0x0000 0x7 0x0
+#define ULP1_PAD_PTB7_LLWU0_P11__PTB7 0x009c 0x0000 0x1 0x0
+#define ULP1_PAD_PTB7_LLWU0_P11__CMP1_OUT 0x009c 0x0000 0xb 0x0
+#define ULP1_PAD_PTB7_LLWU0_P11__LLWU0_P11 0x009c 0x0000 0xd 0x0
+#define ULP1_PAD_PTB7_LLWU0_P11__FXIO0_D23 0x009c 0x0000 0x2 0x0
+#define ULP1_PAD_PTB7_LLWU0_P11__LPSPI1_SIN 0x009c 0xd130 0x3 0x3
+#define ULP1_PAD_PTB7_LLWU0_P11__LPUART3_RX 0x009c 0xd220 0x4 0x3
+#define ULP1_PAD_PTB7_LLWU0_P11__LPI2C0_SDA 0x009c 0xd180 0x5 0x3
+#define ULP1_PAD_PTB7_LLWU0_P11__TPM3_CH5 0x009c 0xd174 0x6 0x2
+#define ULP1_PAD_PTB7_LLWU0_P11__I2S1_MCLK 0x009c 0xd1c8 0x7 0x2
+#define ULP1_PAD_PTB7_LLWU0_P11__QSPIA_SS1_B 0x009c 0x0000 0x8 0x0
+#define ULP1_PAD_PTB8__CMP0_IN0A 0x00a0 0x0000 0x0 0x0
+#define ULP1_PAD_PTB8__PTB8 0x00a0 0x0000 0x1 0x0
+#define ULP1_PAD_PTB8__RTC_CLKOUT 0x00a0 0x0000 0xb 0x0
+#define ULP1_PAD_PTB8__FXIO0_D24 0x00a0 0x0000 0x2 0x0
+#define ULP1_PAD_PTB8__LPSPI1_SOUT 0x00a0 0xd134 0x3 0x3
+#define ULP1_PAD_PTB8__LPI2C1_SCL 0x00a0 0xd188 0x5 0x3
+#define ULP1_PAD_PTB8__TPM0_CLKIN 0x00a0 0xd1a8 0x6 0x3
+#define ULP1_PAD_PTB8__I2S1_RX_BCLK 0x00a0 0xd1cc 0x7 0x2
+#define ULP1_PAD_PTB8__QSPIA_SS0_B 0x00a0 0x0000 0x8 0x0
+#define ULP1_PAD_PTB9_LLWU0_P12__CMP0_IN0B 0x00a4 0x0000 0x0 0x0
+#define ULP1_PAD_PTB9_LLWU0_P12__PTB9 0x00a4 0x0000 0x1 0x0
+#define ULP1_PAD_PTB9_LLWU0_P12__LLWU0_P12 0x00a4 0x0000 0xd 0x0
+#define ULP1_PAD_PTB9_LLWU0_P12__FXIO0_D25 0x00a4 0x0000 0x2 0x0
+#define ULP1_PAD_PTB9_LLWU0_P12__LPSPI1_SCK 0x00a4 0xd12c 0x3 0x3
+#define ULP1_PAD_PTB9_LLWU0_P12__LPI2C1_SDA 0x00a4 0xd18c 0x5 0x3
+#define ULP1_PAD_PTB9_LLWU0_P12__TPM0_CH0 0x00a4 0xd138 0x6 0x3
+#define ULP1_PAD_PTB9_LLWU0_P12__I2S1_RX_FS 0x00a4 0xd1d0 0x7 0x2
+#define ULP1_PAD_PTB9_LLWU0_P12__QSPIA_DQS 0x00a4 0x0000 0x8 0x0
+#define ULP1_PAD_PTB10__CMP0_IN1A 0x00a8 0x0000 0x0 0x0
+#define ULP1_PAD_PTB10__PTB10 0x00a8 0x0000 0x1 0x0
+#define ULP1_PAD_PTB10__TRACE_D4 0x00a8 0x0000 0xa 0x0
+#define ULP1_PAD_PTB10__FXIO0_D26 0x00a8 0x0000 0x2 0x0
+#define ULP1_PAD_PTB10__LPSPI1_PCS0 0x00a8 0xd11c 0x3 0x3
+#define ULP1_PAD_PTB10__LPI2C2_SCL 0x00a8 0xd194 0x5 0x3
+#define ULP1_PAD_PTB10__TPM0_CH1 0x00a8 0xd13c 0x6 0x3
+#define ULP1_PAD_PTB10__I2S1_RXD0 0x00a8 0xd1e4 0x7 0x2
+#define ULP1_PAD_PTB10__QSPIA_DATA7 0x00a8 0x0000 0x8 0x0
+#define ULP1_PAD_PTB11__CMP0_IN1B 0x00ac 0x0000 0x0 0x0
+#define ULP1_PAD_PTB11__PTB11 0x00ac 0x0000 0x1 0x0
+#define ULP1_PAD_PTB11__TRACE_D5 0x00ac 0x0000 0xa 0x0
+#define ULP1_PAD_PTB11__FXIO0_D27 0x00ac 0x0000 0x2 0x0
+#define ULP1_PAD_PTB11__LPSPI1_PCS1 0x00ac 0xd120 0x3 0x3
+#define ULP1_PAD_PTB11__LPI2C2_SDA 0x00ac 0xd198 0x5 0x3
+#define ULP1_PAD_PTB11__TPM1_CLKIN 0x00ac 0xd1ac 0x6 0x3
+#define ULP1_PAD_PTB11__I2S1_RXD1 0x00ac 0xd1e8 0x7 0x2
+#define ULP1_PAD_PTB11__QSPIA_DATA6 0x00ac 0x0000 0x8 0x0
+#define ULP1_PAD_PTB12__ADC1_CH0A 0x00b0 0x0000 0x0 0x0
+#define ULP1_PAD_PTB12__PTB12 0x00b0 0x0000 0x1 0x0
+#define ULP1_PAD_PTB12__TRACE_D6 0x00b0 0x0000 0xa 0x0
+#define ULP1_PAD_PTB12__FXIO0_D28 0x00b0 0x0000 0x2 0x0
+#define ULP1_PAD_PTB12__LPSPI1_PCS2 0x00b0 0xd124 0x3 0x3
+#define ULP1_PAD_PTB12__LPI2C3_SCL 0x00b0 0xd1a0 0x5 0x3
+#define ULP1_PAD_PTB12__TPM1_CH0 0x00b0 0xd150 0x6 0x3
+#define ULP1_PAD_PTB12__I2S1_RXD2 0x00b0 0xd1ec 0x7 0x2
+#define ULP1_PAD_PTB12__QSPIA_DATA5 0x00b0 0x0000 0x8 0x0
+#define ULP1_PAD_PTB13__ADC1_CH0B 0x00b4 0x0000 0x0 0x0
+#define ULP1_PAD_PTB13__PTB13 0x00b4 0x0000 0x1 0x0
+#define ULP1_PAD_PTB13__TRACE_D7 0x00b4 0x0000 0xa 0x0
+#define ULP1_PAD_PTB13__FXIO0_D29 0x00b4 0x0000 0x2 0x0
+#define ULP1_PAD_PTB13__LPSPI1_PCS3 0x00b4 0xd128 0x3 0x3
+#define ULP1_PAD_PTB13__LPI2C3_SDA 0x00b4 0xd1a4 0x5 0x3
+#define ULP1_PAD_PTB13__TPM1_CH1 0x00b4 0xd154 0x6 0x3
+#define ULP1_PAD_PTB13__I2S1_RXD3 0x00b4 0xd1f0 0x7 0x2
+#define ULP1_PAD_PTB13__QSPIA_DATA4 0x00b4 0x0000 0x8 0x0
+#define ULP1_PAD_PTB14_LLWU0_P13__ADC1_CH1A 0x00b8 0x0000 0x0 0x0
+#define ULP1_PAD_PTB14_LLWU0_P13__PTB14 0x00b8 0x0000 0x1 0x0
+#define ULP1_PAD_PTB14_LLWU0_P13__LLWU0_P13 0x00b8 0x0000 0xd 0x0
+#define ULP1_PAD_PTB14_LLWU0_P13__FXIO0_D30 0x00b8 0x0000 0x2 0x0
+#define ULP1_PAD_PTB14_LLWU0_P13__LPI2C2_HREQ 0x00b8 0xd190 0x5 0x3
+#define ULP1_PAD_PTB14_LLWU0_P13__TPM2_CLKIN 0x00b8 0xd1f4 0x6 0x3
+#define ULP1_PAD_PTB14_LLWU0_P13__QSPIA_SS0_B 0x00b8 0x0000 0x8 0x0
+#define ULP1_PAD_PTB14_LLWU0_P13__QSPIA_SCLK_B 0x00b8 0x0000 0x9 0x0
+#define ULP1_PAD_PTB15__ADC1_CH1B 0x00bc 0x0000 0x0 0x0
+#define ULP1_PAD_PTB15__PTB15 0x00bc 0x0000 0x1 0x0
+#define ULP1_PAD_PTB15__FXIO0_D31 0x00bc 0x0000 0x2 0x0
+#define ULP1_PAD_PTB15__LPI2C3_HREQ 0x00bc 0xd19c 0x5 0x3
+#define ULP1_PAD_PTB15__TPM2_CH0 0x00bc 0xd158 0x6 0x3
+#define ULP1_PAD_PTB15__QSPIA_SCLK 0x00bc 0x0000 0x8 0x0
+#define ULP1_PAD_PTB16_LLWU0_P14__ADC0_CH2A 0x00c0 0x0000 0x0 0x0
+#define ULP1_PAD_PTB16_LLWU0_P14__PTB16 0x00c0 0x0000 0x1 0x0
+#define ULP1_PAD_PTB16_LLWU0_P14__LLWU0_P14 0x00c0 0x0000 0xd 0x0
+#define ULP1_PAD_PTB16_LLWU0_P14__TPM2_CH1 0x00c0 0xd15c 0x6 0x3
+#define ULP1_PAD_PTB16_LLWU0_P14__QSPIA_DATA3 0x00c0 0x0000 0x8 0x0
+#define ULP1_PAD_PTB17__ADC0_CH2B 0x00c4 0x0000 0x0 0x0
+#define ULP1_PAD_PTB17__PTB17 0x00c4 0x0000 0x1 0x0
+#define ULP1_PAD_PTB17__TPM3_CLKIN 0x00c4 0xd1b0 0x6 0x2
+#define ULP1_PAD_PTB17__QSPIA_DATA2 0x00c4 0x0000 0x8 0x0
+#define ULP1_PAD_PTB18__ADC0_CH3A 0x00c8 0x0000 0x0 0x0
+#define ULP1_PAD_PTB18__PTB18 0x00c8 0x0000 0x1 0x0
+#define ULP1_PAD_PTB18__TPM3_CH0 0x00c8 0xd160 0x6 0x3
+#define ULP1_PAD_PTB18__QSPIA_DATA1 0x00c8 0x0000 0x8 0x0
+#define ULP1_PAD_PTB19_LLWU0_P15__ADC0_CH3B 0x00cc 0x0000 0x0 0x0
+#define ULP1_PAD_PTB19_LLWU0_P15__PTB19 0x00cc 0x0000 0x1 0x0
+#define ULP1_PAD_PTB19_LLWU0_P15__USB0_ID 0x00cc 0x0000 0xa 0x0
+#define ULP1_PAD_PTB19_LLWU0_P15__LLWU0_P15 0x00cc 0x0000 0xd 0x0
+#define ULP1_PAD_PTB19_LLWU0_P15__TPM3_CH1 0x00cc 0xd164 0x6 0x3
+#define ULP1_PAD_PTB19_LLWU0_P15__QSPIA_DATA0 0x00cc 0x0000 0x8 0x0
+#define ULP1_PAD_PTC0__PTC0 0x0000 0x0000 0x1 0x0
+#define ULP1_PAD_PTC0__TRACE_D15 0x0000 0x0000 0xa 0x0
+#define ULP1_PAD_PTC0__LPUART4_CTS_B 0x0000 0x0244 0x4 0x1
+#define ULP1_PAD_PTC0__LPI2C4_SCL 0x0000 0x0278 0x5 0x1
+#define ULP1_PAD_PTC0__TPM4_CLKIN 0x0000 0x0298 0x6 0x1
+#define ULP1_PAD_PTC0__FB_AD0 0x0000 0x0000 0x9 0x0
+#define ULP1_PAD_PTC1__PTC1 0x0004 0x0000 0x1 0x0
+#define ULP1_PAD_PTC1__TRACE_D14 0x0004 0x0000 0xa 0x0
+#define ULP1_PAD_PTC1__LPUART4_RTS_B 0x0004 0x0000 0x4 0x0
+#define ULP1_PAD_PTC1__LPI2C4_SDA 0x0004 0x027c 0x5 0x1
+#define ULP1_PAD_PTC1__TPM4_CH0 0x0004 0x0280 0x6 0x1
+#define ULP1_PAD_PTC1__FB_AD1 0x0004 0x0000 0x9 0x0
+#define ULP1_PAD_PTC2__PTC2 0x0008 0x0000 0x1 0x0
+#define ULP1_PAD_PTC2__TRACE_D13 0x0008 0x0000 0xa 0x0
+#define ULP1_PAD_PTC2__LPUART4_TX 0x0008 0x024c 0x4 0x1
+#define ULP1_PAD_PTC2__LPI2C4_HREQ 0x0008 0x0274 0x5 0x1
+#define ULP1_PAD_PTC2__TPM4_CH1 0x0008 0x0284 0x6 0x1
+#define ULP1_PAD_PTC2__FB_AD2 0x0008 0x0000 0x9 0x0
+#define ULP1_PAD_PTC3__PTC3 0x000c 0x0000 0x1 0x0
+#define ULP1_PAD_PTC3__TRACE_D12 0x000c 0x0000 0xa 0x0
+#define ULP1_PAD_PTC3__LPUART4_RX 0x000c 0x0248 0x4 0x1
+#define ULP1_PAD_PTC3__TPM4_CH2 0x000c 0x0288 0x6 0x1
+#define ULP1_PAD_PTC3__FB_AD3 0x000c 0x0000 0x9 0x0
+#define ULP1_PAD_PTC4__PTC4 0x0010 0x0000 0x1 0x0
+#define ULP1_PAD_PTC4__TRACE_D11 0x0010 0x0000 0xa 0x0
+#define ULP1_PAD_PTC4__FXIO1_D0 0x0010 0x0204 0x2 0x1
+#define ULP1_PAD_PTC4__LPSPI2_PCS1 0x0010 0x02a0 0x3 0x1
+#define ULP1_PAD_PTC4__LPUART5_CTS_B 0x0010 0x0250 0x4 0x1
+#define ULP1_PAD_PTC4__LPI2C5_SCL 0x0010 0x02bc 0x5 0x1
+#define ULP1_PAD_PTC4__TPM4_CH3 0x0010 0x028c 0x6 0x1
+#define ULP1_PAD_PTC4__FB_AD4 0x0010 0x0000 0x9 0x0
+#define ULP1_PAD_PTC5__PTC5 0x0014 0x0000 0x1 0x0
+#define ULP1_PAD_PTC5__TRACE_D10 0x0014 0x0000 0xa 0x0
+#define ULP1_PAD_PTC5__FXIO1_D1 0x0014 0x0208 0x2 0x1
+#define ULP1_PAD_PTC5__LPSPI2_PCS2 0x0014 0x02a4 0x3 0x1
+#define ULP1_PAD_PTC5__LPUART5_RTS_B 0x0014 0x0000 0x4 0x0
+#define ULP1_PAD_PTC5__LPI2C5_SDA 0x0014 0x02c0 0x5 0x1
+#define ULP1_PAD_PTC5__TPM4_CH4 0x0014 0x0290 0x6 0x1
+#define ULP1_PAD_PTC5__FB_AD5 0x0014 0x0000 0x9 0x0
+#define ULP1_PAD_PTC6__PTC6 0x0018 0x0000 0x1 0x0
+#define ULP1_PAD_PTC6__TRACE_D9 0x0018 0x0000 0xa 0x0
+#define ULP1_PAD_PTC6__FXIO1_D2 0x0018 0x020c 0x2 0x1
+#define ULP1_PAD_PTC6__LPSPI2_PCS3 0x0018 0x02a8 0x3 0x1
+#define ULP1_PAD_PTC6__LPUART5_TX 0x0018 0x0258 0x4 0x1
+#define ULP1_PAD_PTC6__LPI2C5_HREQ 0x0018 0x02b8 0x5 0x1
+#define ULP1_PAD_PTC6__TPM4_CH5 0x0018 0x0294 0x6 0x1
+#define ULP1_PAD_PTC6__FB_AD6 0x0018 0x0000 0x9 0x0
+#define ULP1_PAD_PTC7__PTC7 0x001c 0x0000 0x1 0x0
+#define ULP1_PAD_PTC7__TRACE_D8 0x001c 0x0000 0xa 0x0
+#define ULP1_PAD_PTC7__FXIO1_D3 0x001c 0x0210 0x2 0x1
+#define ULP1_PAD_PTC7__LPUART5_RX 0x001c 0x0254 0x4 0x1
+#define ULP1_PAD_PTC7__TPM5_CH1 0x001c 0x02c8 0x6 0x1
+#define ULP1_PAD_PTC7__FB_AD7 0x001c 0x0000 0x9 0x0
+#define ULP1_PAD_PTC8__PTC8 0x0020 0x0000 0x1 0x0
+#define ULP1_PAD_PTC8__TRACE_D7 0x0020 0x0000 0xa 0x0
+#define ULP1_PAD_PTC8__FXIO1_D4 0x0020 0x0214 0x2 0x1
+#define ULP1_PAD_PTC8__LPSPI2_SIN 0x0020 0x02b0 0x3 0x1
+#define ULP1_PAD_PTC8__LPUART6_CTS_B 0x0020 0x025c 0x4 0x1
+#define ULP1_PAD_PTC8__LPI2C6_SCL 0x0020 0x02fc 0x5 0x1
+#define ULP1_PAD_PTC8__TPM5_CLKIN 0x0020 0x02cc 0x6 0x1
+#define ULP1_PAD_PTC8__FB_AD8 0x0020 0x0000 0x9 0x0
+#define ULP1_PAD_PTC9__PTC9 0x0024 0x0000 0x1 0x0
+#define ULP1_PAD_PTC9__TRACE_D6 0x0024 0x0000 0xa 0x0
+#define ULP1_PAD_PTC9__FXIO1_D5 0x0024 0x0218 0x2 0x1
+#define ULP1_PAD_PTC9__LPSPI2_SOUT 0x0024 0x02b4 0x3 0x1
+#define ULP1_PAD_PTC9__LPUART6_RTS_B 0x0024 0x0000 0x4 0x0
+#define ULP1_PAD_PTC9__LPI2C6_SDA 0x0024 0x0300 0x5 0x1
+#define ULP1_PAD_PTC9__TPM5_CH0 0x0024 0x02c4 0x6 0x1
+#define ULP1_PAD_PTC9__FB_AD9 0x0024 0x0000 0x9 0x0
+#define ULP1_PAD_PTC10__PTC10 0x0028 0x0000 0x1 0x0
+#define ULP1_PAD_PTC10__TRACE_D5 0x0028 0x0000 0xa 0x0
+#define ULP1_PAD_PTC10__FXIO1_D6 0x0028 0x021c 0x2 0x1
+#define ULP1_PAD_PTC10__LPSPI2_SCK 0x0028 0x02ac 0x3 0x1
+#define ULP1_PAD_PTC10__LPUART6_TX 0x0028 0x0264 0x4 0x1
+#define ULP1_PAD_PTC10__LPI2C6_HREQ 0x0028 0x02f8 0x5 0x1
+#define ULP1_PAD_PTC10__TPM7_CH3 0x0028 0x02e8 0x6 0x1
+#define ULP1_PAD_PTC10__FB_AD10 0x0028 0x0000 0x9 0x0
+#define ULP1_PAD_PTC11__PTC11 0x002c 0x0000 0x1 0x0
+#define ULP1_PAD_PTC11__TRACE_D4 0x002c 0x0000 0xa 0x0
+#define ULP1_PAD_PTC11__FXIO1_D7 0x002c 0x0220 0x2 0x1
+#define ULP1_PAD_PTC11__LPSPI2_PCS0 0x002c 0x029c 0x3 0x1
+#define ULP1_PAD_PTC11__LPUART6_RX 0x002c 0x0260 0x4 0x1
+#define ULP1_PAD_PTC11__TPM7_CH4 0x002c 0x02ec 0x6 0x1
+#define ULP1_PAD_PTC11__FB_AD11 0x002c 0x0000 0x9 0x0
+#define ULP1_PAD_PTC12__PTC12 0x0030 0x0000 0x1 0x0
+#define ULP1_PAD_PTC12__TRACE_D3 0x0030 0x0000 0xa 0x0
+#define ULP1_PAD_PTC12__FXIO1_D8 0x0030 0x0224 0x2 0x1
+#define ULP1_PAD_PTC12__LPSPI3_PCS1 0x0030 0x0314 0x3 0x1
+#define ULP1_PAD_PTC12__LPUART7_CTS_B 0x0030 0x0268 0x4 0x1
+#define ULP1_PAD_PTC12__LPI2C7_SCL 0x0030 0x0308 0x5 0x1
+#define ULP1_PAD_PTC12__TPM7_CH5 0x0030 0x02f0 0x6 0x1
+#define ULP1_PAD_PTC12__FB_AD12 0x0030 0x0000 0x9 0x0
+#define ULP1_PAD_PTC13__PTC13 0x0034 0x0000 0x1 0x0
+#define ULP1_PAD_PTC13__TRACE_D2 0x0034 0x0000 0xa 0x0
+#define ULP1_PAD_PTC13__FXIO1_D9 0x0034 0x0228 0x2 0x1
+#define ULP1_PAD_PTC13__LPSPI3_PCS2 0x0034 0x0318 0x3 0x1
+#define ULP1_PAD_PTC13__LPUART7_RTS_B 0x0034 0x0000 0x4 0x0
+#define ULP1_PAD_PTC13__LPI2C7_SDA 0x0034 0x030c 0x5 0x1
+#define ULP1_PAD_PTC13__TPM7_CLKIN 0x0034 0x02f4 0x6 0x1
+#define ULP1_PAD_PTC13__FB_AD13 0x0034 0x0000 0x9 0x0
+#define ULP1_PAD_PTC14__PTC14 0x0038 0x0000 0x1 0x0
+#define ULP1_PAD_PTC14__TRACE_D1 0x0038 0x0000 0xa 0x0
+#define ULP1_PAD_PTC14__FXIO1_D10 0x0038 0x022c 0x2 0x1
+#define ULP1_PAD_PTC14__LPSPI3_PCS3 0x0038 0x031c 0x3 0x1
+#define ULP1_PAD_PTC14__LPUART7_TX 0x0038 0x0270 0x4 0x1
+#define ULP1_PAD_PTC14__LPI2C7_HREQ 0x0038 0x0304 0x5 0x1
+#define ULP1_PAD_PTC14__TPM7_CH0 0x0038 0x02dc 0x6 0x1
+#define ULP1_PAD_PTC14__FB_AD14 0x0038 0x0000 0x9 0x0
+#define ULP1_PAD_PTC15__PTC15 0x003c 0x0000 0x1 0x0
+#define ULP1_PAD_PTC15__TRACE_D0 0x003c 0x0000 0xa 0x0
+#define ULP1_PAD_PTC15__FXIO1_D11 0x003c 0x0230 0x2 0x1
+#define ULP1_PAD_PTC15__LPUART7_RX 0x003c 0x026c 0x4 0x1
+#define ULP1_PAD_PTC15__TPM7_CH1 0x003c 0x02e0 0x6 0x1
+#define ULP1_PAD_PTC15__FB_AD15 0x003c 0x0000 0x9 0x0
+#define ULP1_PAD_PTC16__PTC16 0x0040 0x0000 0x1 0x0
+#define ULP1_PAD_PTC16__TRACE_CLKOUT 0x0040 0x0000 0xa 0x0
+#define ULP1_PAD_PTC16__FXIO1_D12 0x0040 0x0234 0x2 0x1
+#define ULP1_PAD_PTC16__LPSPI3_SIN 0x0040 0x0324 0x3 0x1
+#define ULP1_PAD_PTC16__TPM7_CH2 0x0040 0x02e4 0x6 0x1
+#define ULP1_PAD_PTC16__FB_ALE_FB_CS1_B_FB_TS_B 0x0040 0x0000 0x9 0x0
+#define ULP1_PAD_PTC17__PTC17 0x0044 0x0000 0x1 0x0
+#define ULP1_PAD_PTC17__FXIO1_D13 0x0044 0x0238 0x2 0x1
+#define ULP1_PAD_PTC17__LPSPI3_SOUT 0x0044 0x0328 0x3 0x1
+#define ULP1_PAD_PTC17__TPM6_CLKIN 0x0044 0x02d8 0x6 0x1
+#define ULP1_PAD_PTC17__FB_CS0_B 0x0044 0x0000 0x9 0x0
+#define ULP1_PAD_PTC18__PTC18 0x0048 0x0000 0x1 0x0
+#define ULP1_PAD_PTC18__FXIO1_D14 0x0048 0x023c 0x2 0x1
+#define ULP1_PAD_PTC18__LPSPI3_SCK 0x0048 0x0320 0x3 0x1
+#define ULP1_PAD_PTC18__TPM6_CH0 0x0048 0x02d0 0x6 0x1
+#define ULP1_PAD_PTC18__FB_OE_B 0x0048 0x0000 0x9 0x0
+#define ULP1_PAD_PTC19__PTC19 0x004c 0x0000 0x1 0x0
+#define ULP1_PAD_PTC19__FXIO1_D15 0x004c 0x0240 0x2 0x1
+#define ULP1_PAD_PTC19__LPSPI3_PCS0 0x004c 0x0310 0x3 0x1
+#define ULP1_PAD_PTC19__TPM6_CH1 0x004c 0x02d4 0x6 0x1
+#define ULP1_PAD_PTC19__FB_A16 0x004c 0x0000 0x9 0x0
+#define ULP1_PAD_PTD0__PTD0 0x0080 0x0000 0x1 0x0
+#define ULP1_PAD_PTD0__SDHC0_RESET_B 0x0080 0x0000 0x8 0x0
+#define ULP1_PAD_PTD1__PTD1 0x0084 0x0000 0x1 0x0
+#define ULP1_PAD_PTD1__SDHC0_CMD 0x0084 0x0000 0x8 0x0
+#define ULP1_PAD_PTD2__PTD2 0x0088 0x0000 0x1 0x0
+#define ULP1_PAD_PTD2__SDHC0_CLK 0x0088 0x0000 0x8 0x0
+#define ULP1_PAD_PTD3__PTD3 0x008c 0x0000 0x1 0x0
+#define ULP1_PAD_PTD3__SDHC0_D7 0x008c 0x0000 0x8 0x0
+#define ULP1_PAD_PTD4__PTD4 0x0090 0x0000 0x1 0x0
+#define ULP1_PAD_PTD4__SDHC0_D6 0x0090 0x0000 0x8 0x0
+#define ULP1_PAD_PTD5__PTD5 0x0094 0x0000 0x1 0x0
+#define ULP1_PAD_PTD5__SDHC0_D5 0x0094 0x0000 0x8 0x0
+#define ULP1_PAD_PTD6__PTD6 0x0098 0x0000 0x1 0x0
+#define ULP1_PAD_PTD6__SDHC0_D4 0x0098 0x0000 0x8 0x0
+#define ULP1_PAD_PTD7__PTD7 0x009c 0x0000 0x1 0x0
+#define ULP1_PAD_PTD7__SDHC0_D3 0x009c 0x0000 0x8 0x0
+#define ULP1_PAD_PTD8__PTD8 0x00a0 0x0000 0x1 0x0
+#define ULP1_PAD_PTD8__TPM4_CLKIN 0x00a0 0x0298 0x6 0x2
+#define ULP1_PAD_PTD8__SDHC0_D2 0x00a0 0x0000 0x8 0x0
+#define ULP1_PAD_PTD9__PTD9 0x00a4 0x0000 0x1 0x0
+#define ULP1_PAD_PTD9__TPM4_CH0 0x00a4 0x0280 0x6 0x2
+#define ULP1_PAD_PTD9__SDHC0_D1 0x00a4 0x0000 0x8 0x0
+#define ULP1_PAD_PTD10__PTD10 0x00a8 0x0000 0x1 0x0
+#define ULP1_PAD_PTD10__TPM4_CH1 0x00a8 0x0284 0x6 0x2
+#define ULP1_PAD_PTD10__SDHC0_D0 0x00a8 0x0000 0x8 0x0
+#define ULP1_PAD_PTD11__PTD11 0x00ac 0x0000 0x1 0x0
+#define ULP1_PAD_PTD11__TPM4_CH2 0x00ac 0x0288 0x6 0x2
+#define ULP1_PAD_PTD11__SDHC0_DQS 0x00ac 0x0000 0x8 0x0
+#define ULP1_PAD_PTE0__PTE0 0x0100 0x0000 0x1 0x0
+#define ULP1_PAD_PTE0__FXIO1_D31 0x0100 0x0000 0x2 0x0
+#define ULP1_PAD_PTE0__LPSPI2_PCS1 0x0100 0x02a0 0x3 0x2
+#define ULP1_PAD_PTE0__LPUART4_CTS_B 0x0100 0x0244 0x4 0x2
+#define ULP1_PAD_PTE0__LPI2C4_SCL 0x0100 0x0278 0x5 0x2
+#define ULP1_PAD_PTE0__SDHC1_D1 0x0100 0x0000 0x8 0x0
+#define ULP1_PAD_PTE0__FB_A25 0x0100 0x0000 0x9 0x0
+#define ULP1_PAD_PTE1__PTE1 0x0104 0x0000 0x1 0x0
+#define ULP1_PAD_PTE1__FXIO1_D30 0x0104 0x0000 0x2 0x0
+#define ULP1_PAD_PTE1__LPSPI2_PCS2 0x0104 0x02a4 0x3 0x2
+#define ULP1_PAD_PTE1__LPUART4_RTS_B 0x0104 0x0000 0x4 0x0
+#define ULP1_PAD_PTE1__LPI2C4_SDA 0x0104 0x027c 0x5 0x2
+#define ULP1_PAD_PTE1__SDHC1_D0 0x0104 0x0000 0x8 0x0
+#define ULP1_PAD_PTE1__FB_A26 0x0104 0x0000 0x9 0x0
+#define ULP1_PAD_PTE2__PTE2 0x0108 0x0000 0x1 0x0
+#define ULP1_PAD_PTE2__FXIO1_D29 0x0108 0x0000 0x2 0x0
+#define ULP1_PAD_PTE2__LPSPI2_PCS3 0x0108 0x02a8 0x3 0x2
+#define ULP1_PAD_PTE2__LPUART4_TX 0x0108 0x024c 0x4 0x2
+#define ULP1_PAD_PTE2__LPI2C4_HREQ 0x0108 0x0274 0x5 0x2
+#define ULP1_PAD_PTE2__SDHC1_CLK 0x0108 0x0000 0x8 0x0
+#define ULP1_PAD_PTE3__PTE3 0x010c 0x0000 0x1 0x0
+#define ULP1_PAD_PTE3__FXIO1_D28 0x010c 0x0000 0x2 0x0
+#define ULP1_PAD_PTE3__LPUART4_RX 0x010c 0x0248 0x4 0x2
+#define ULP1_PAD_PTE3__TPM5_CH1 0x010c 0x02c8 0x6 0x2
+#define ULP1_PAD_PTE3__SDHC1_CMD 0x010c 0x0000 0x8 0x0
+#define ULP1_PAD_PTE4__PTE4 0x0110 0x0000 0x1 0x0
+#define ULP1_PAD_PTE4__FXIO1_D27 0x0110 0x0000 0x2 0x0
+#define ULP1_PAD_PTE4__LPSPI2_SIN 0x0110 0x02b0 0x3 0x2
+#define ULP1_PAD_PTE4__LPUART5_CTS_B 0x0110 0x0250 0x4 0x2
+#define ULP1_PAD_PTE4__LPI2C5_SCL 0x0110 0x02bc 0x5 0x2
+#define ULP1_PAD_PTE4__TPM5_CLKIN 0x0110 0x02cc 0x6 0x2
+#define ULP1_PAD_PTE4__SDHC1_D3 0x0110 0x0000 0x8 0x0
+#define ULP1_PAD_PTE5__PTE5 0x0114 0x0000 0x1 0x0
+#define ULP1_PAD_PTE5__FXIO1_D26 0x0114 0x0000 0x2 0x0
+#define ULP1_PAD_PTE5__LPSPI2_SOUT 0x0114 0x02b4 0x3 0x2
+#define ULP1_PAD_PTE5__LPUART5_RTS_B 0x0114 0x0000 0x4 0x0
+#define ULP1_PAD_PTE5__LPI2C5_SDA 0x0114 0x02c0 0x5 0x2
+#define ULP1_PAD_PTE5__TPM5_CH0 0x0114 0x02c4 0x6 0x2
+#define ULP1_PAD_PTE5__SDHC1_D2 0x0114 0x0000 0x8 0x0
+#define ULP1_PAD_PTE6__PTE6 0x0118 0x0000 0x1 0x0
+#define ULP1_PAD_PTE6__FXIO1_D25 0x0118 0x0000 0x2 0x0
+#define ULP1_PAD_PTE6__LPSPI2_SCK 0x0118 0x02ac 0x3 0x2
+#define ULP1_PAD_PTE6__LPUART5_TX 0x0118 0x0258 0x4 0x2
+#define ULP1_PAD_PTE6__LPI2C5_HREQ 0x0118 0x02b8 0x5 0x2
+#define ULP1_PAD_PTE6__TPM7_CH3 0x0118 0x02e8 0x6 0x2
+#define ULP1_PAD_PTE6__SDHC1_D4 0x0118 0x0000 0x8 0x0
+#define ULP1_PAD_PTE6__FB_A17 0x0118 0x0000 0x9 0x0
+#define ULP1_PAD_PTE7__PTE7 0x011c 0x0000 0x1 0x0
+#define ULP1_PAD_PTE7__TRACE_D7 0x011c 0x0000 0xa 0x0
+#define ULP1_PAD_PTE7__VIU_FID 0x011c 0x0000 0xc 0x0
+#define ULP1_PAD_PTE7__FXIO1_D24 0x011c 0x0000 0x2 0x0
+#define ULP1_PAD_PTE7__LPSPI2_PCS0 0x011c 0x029c 0x3 0x2
+#define ULP1_PAD_PTE7__LPUART5_RX 0x011c 0x0254 0x4 0x2
+#define ULP1_PAD_PTE7__TPM7_CH4 0x011c 0x02ec 0x6 0x2
+#define ULP1_PAD_PTE7__SDHC1_D5 0x011c 0x0000 0x8 0x0
+#define ULP1_PAD_PTE7__FB_A18 0x011c 0x0000 0x9 0x0
+#define ULP1_PAD_PTE8__PTE8 0x0120 0x0000 0x1 0x0
+#define ULP1_PAD_PTE8__TRACE_D6 0x0120 0x0000 0xa 0x0
+#define ULP1_PAD_PTE8__VIU_D16 0x0120 0x0000 0xc 0x0
+#define ULP1_PAD_PTE8__FXIO1_D23 0x0120 0x0000 0x2 0x0
+#define ULP1_PAD_PTE8__LPSPI3_PCS1 0x0120 0x0314 0x3 0x2
+#define ULP1_PAD_PTE8__LPUART6_CTS_B 0x0120 0x025c 0x4 0x2
+#define ULP1_PAD_PTE8__LPI2C6_SCL 0x0120 0x02fc 0x5 0x2
+#define ULP1_PAD_PTE8__TPM7_CH5 0x0120 0x02f0 0x6 0x2
+#define ULP1_PAD_PTE8__SDHC1_WP 0x0120 0x0200 0x7 0x1
+#define ULP1_PAD_PTE8__SDHC1_D6 0x0120 0x0000 0x8 0x0
+#define ULP1_PAD_PTE8__FB_CS3_B_FB_BE7_0_BLS31_24_B 0x0120 0x0000 0x9 0x0
+#define ULP1_PAD_PTE9__PTE9 0x0124 0x0000 0x1 0x0
+#define ULP1_PAD_PTE9__TRACE_D5 0x0124 0x0000 0xa 0x0
+#define ULP1_PAD_PTE9__VIU_D17 0x0124 0x0000 0xc 0x0
+#define ULP1_PAD_PTE9__FXIO1_D22 0x0124 0x0000 0x2 0x0
+#define ULP1_PAD_PTE9__LPSPI3_PCS2 0x0124 0x0318 0x3 0x2
+#define ULP1_PAD_PTE9__LPUART6_RTS_B 0x0124 0x0000 0x4 0x0
+#define ULP1_PAD_PTE9__LPI2C6_SDA 0x0124 0x0300 0x5 0x2
+#define ULP1_PAD_PTE9__TPM7_CLKIN 0x0124 0x02f4 0x6 0x2
+#define ULP1_PAD_PTE9__SDHC1_CD 0x0124 0x032c 0x7 0x1
+#define ULP1_PAD_PTE9__SDHC1_D7 0x0124 0x0000 0x8 0x0
+#define ULP1_PAD_PTE9__FB_TBST_B_FB_CS2_B_FB_BE15_8_BLS23_16_B 0x0124 0x0000 0x9 0x0
+#define ULP1_PAD_PTE10__PTE10 0x0128 0x0000 0x1 0x0
+#define ULP1_PAD_PTE10__TRACE_D4 0x0128 0x0000 0xa 0x0
+#define ULP1_PAD_PTE10__VIU_D18 0x0128 0x0000 0xc 0x0
+#define ULP1_PAD_PTE10__FXIO1_D21 0x0128 0x0000 0x2 0x0
+#define ULP1_PAD_PTE10__LPSPI3_PCS3 0x0128 0x031c 0x3 0x2
+#define ULP1_PAD_PTE10__LPUART6_TX 0x0128 0x0264 0x4 0x2
+#define ULP1_PAD_PTE10__LPI2C6_HREQ 0x0128 0x02f8 0x5 0x2
+#define ULP1_PAD_PTE10__TPM7_CH0 0x0128 0x02dc 0x6 0x2
+#define ULP1_PAD_PTE10__SDHC1_VS 0x0128 0x0000 0x7 0x0
+#define ULP1_PAD_PTE10__SDHC1_DQS 0x0128 0x0000 0x8 0x0
+#define ULP1_PAD_PTE10__FB_A19 0x0128 0x0000 0x9 0x0
+#define ULP1_PAD_PTE11__PTE11 0x012c 0x0000 0x1 0x0
+#define ULP1_PAD_PTE11__TRACE_D3 0x012c 0x0000 0xa 0x0
+#define ULP1_PAD_PTE11__VIU_D19 0x012c 0x0000 0xc 0x0
+#define ULP1_PAD_PTE11__FXIO1_D20 0x012c 0x0000 0x2 0x0
+#define ULP1_PAD_PTE11__LPUART6_RX 0x012c 0x0260 0x4 0x2
+#define ULP1_PAD_PTE11__TPM7_CH1 0x012c 0x02e0 0x6 0x2
+#define ULP1_PAD_PTE11__SDHC1_RESET_B 0x012c 0x0000 0x8 0x0
+#define ULP1_PAD_PTE11__FB_A20 0x012c 0x0000 0x9 0x0
+#define ULP1_PAD_PTE12__PTE12 0x0130 0x0000 0x1 0x0
+#define ULP1_PAD_PTE12__TRACE_D2 0x0130 0x0000 0xa 0x0
+#define ULP1_PAD_PTE12__VIU_D20 0x0130 0x0000 0xc 0x0
+#define ULP1_PAD_PTE12__FXIO1_D19 0x0130 0x0000 0x2 0x0
+#define ULP1_PAD_PTE12__LPSPI3_SIN 0x0130 0x0324 0x3 0x2
+#define ULP1_PAD_PTE12__LPUART7_CTS_B 0x0130 0x0268 0x4 0x2
+#define ULP1_PAD_PTE12__LPI2C7_SCL 0x0130 0x0308 0x5 0x2
+#define ULP1_PAD_PTE12__TPM7_CH2 0x0130 0x02e4 0x6 0x2
+#define ULP1_PAD_PTE12__SDHC1_WP 0x0130 0x0200 0x8 0x2
+#define ULP1_PAD_PTE12__FB_A21 0x0130 0x0000 0x9 0x0
+#define ULP1_PAD_PTE13__PTE13 0x0134 0x0000 0x1 0x0
+#define ULP1_PAD_PTE13__TRACE_D1 0x0134 0x0000 0xa 0x0
+#define ULP1_PAD_PTE13__VIU_D21 0x0134 0x0000 0xc 0x0
+#define ULP1_PAD_PTE13__FXIO1_D18 0x0134 0x0000 0x2 0x0
+#define ULP1_PAD_PTE13__LPSPI3_SOUT 0x0134 0x0328 0x3 0x2
+#define ULP1_PAD_PTE13__LPUART7_RTS_B 0x0134 0x0000 0x4 0x0
+#define ULP1_PAD_PTE13__LPI2C7_SDA 0x0134 0x030c 0x5 0x2
+#define ULP1_PAD_PTE13__TPM6_CLKIN 0x0134 0x02d8 0x6 0x2
+#define ULP1_PAD_PTE13__SDHC1_CD 0x0134 0x032c 0x8 0x2
+#define ULP1_PAD_PTE13__FB_A22 0x0134 0x0000 0x9 0x0
+#define ULP1_PAD_PTE14__PTE14 0x0138 0x0000 0x1 0x0
+#define ULP1_PAD_PTE14__TRACE_D0 0x0138 0x0000 0xa 0x0
+#define ULP1_PAD_PTE14__VIU_D22 0x0138 0x0000 0xc 0x0
+#define ULP1_PAD_PTE14__FXIO1_D17 0x0138 0x0000 0x2 0x0
+#define ULP1_PAD_PTE14__LPSPI3_SCK 0x0138 0x0320 0x3 0x2
+#define ULP1_PAD_PTE14__LPUART7_TX 0x0138 0x0270 0x4 0x2
+#define ULP1_PAD_PTE14__LPI2C7_HREQ 0x0138 0x0304 0x5 0x2
+#define ULP1_PAD_PTE14__TPM6_CH0 0x0138 0x02d0 0x6 0x2
+#define ULP1_PAD_PTE14__SDHC1_VS 0x0138 0x0000 0x8 0x0
+#define ULP1_PAD_PTE14__FB_A23 0x0138 0x0000 0x9 0x0
+#define ULP1_PAD_PTE15__PTE15 0x013c 0x0000 0x1 0x0
+#define ULP1_PAD_PTE15__TRACE_CLKOUT 0x013c 0x0000 0xa 0x0
+#define ULP1_PAD_PTE15__VIU_D23 0x013c 0x0000 0xc 0x0
+#define ULP1_PAD_PTE15__FXIO1_D16 0x013c 0x0000 0x2 0x0
+#define ULP1_PAD_PTE15__LPSPI3_PCS0 0x013c 0x0310 0x3 0x2
+#define ULP1_PAD_PTE15__LPUART7_RX 0x013c 0x026c 0x4 0x2
+#define ULP1_PAD_PTE15__TPM6_CH1 0x013c 0x02d4 0x6 0x2
+#define ULP1_PAD_PTE15__FB_A24 0x013c 0x0000 0x9 0x0
+#define ULP1_PAD_PTF0__PTF0 0x0180 0x0000 0x1 0x0
+#define ULP1_PAD_PTF0__VIU_DE 0x0180 0x0000 0xc 0x0
+#define ULP1_PAD_PTF0__LPUART4_CTS_B 0x0180 0x0244 0x4 0x3
+#define ULP1_PAD_PTF0__LPI2C4_SCL 0x0180 0x0278 0x5 0x3
+#define ULP1_PAD_PTF0__TPM4_CLKIN 0x0180 0x0298 0x6 0x3
+#define ULP1_PAD_PTF0__FB_RW_B 0x0180 0x0000 0x9 0x0
+#define ULP1_PAD_PTF1__PTF1 0x0184 0x0000 0x1 0x0
+#define ULP1_PAD_PTF1__VIU_HSYNC 0x0184 0x0000 0xc 0x0
+#define ULP1_PAD_PTF1__LPUART4_RTS_B 0x0184 0x0000 0x4 0x0
+#define ULP1_PAD_PTF1__LPI2C4_SDA 0x0184 0x027c 0x5 0x3
+#define ULP1_PAD_PTF1__TPM4_CH0 0x0184 0x0280 0x6 0x3
+#define ULP1_PAD_PTF1__CLKOUT 0x0184 0x0000 0x9 0x0
+#define ULP1_PAD_PTF2__PTF2 0x0188 0x0000 0x1 0x0
+#define ULP1_PAD_PTF2__VIU_VSYNC 0x0188 0x0000 0xc 0x0
+#define ULP1_PAD_PTF2__LPUART4_TX 0x0188 0x024c 0x4 0x3
+#define ULP1_PAD_PTF2__LPI2C4_HREQ 0x0188 0x0274 0x5 0x3
+#define ULP1_PAD_PTF2__TPM4_CH1 0x0188 0x0284 0x6 0x3
+#define ULP1_PAD_PTF2__FB_TSIZ1_FB_CS5_B_FB_BE23_16_BLS15_8_B 0x0188 0x0000 0x9 0x0
+#define ULP1_PAD_PTF3__PTF3 0x018c 0x0000 0x1 0x0
+#define ULP1_PAD_PTF3__VIU_PCLK 0x018c 0x0000 0xc 0x0
+#define ULP1_PAD_PTF3__LPUART4_RX 0x018c 0x0248 0x4 0x3
+#define ULP1_PAD_PTF3__TPM4_CH2 0x018c 0x0288 0x6 0x3
+#define ULP1_PAD_PTF3__FB_AD16 0x018c 0x0000 0x9 0x0
+#define ULP1_PAD_PTF4__PTF4 0x0190 0x0000 0x1 0x0
+#define ULP1_PAD_PTF4__VIU_D0 0x0190 0x0000 0xc 0x0
+#define ULP1_PAD_PTF4__FXIO1_D0 0x0190 0x0204 0x2 0x2
+#define ULP1_PAD_PTF4__LPSPI2_PCS1 0x0190 0x02a0 0x3 0x3
+#define ULP1_PAD_PTF4__LPUART5_CTS_B 0x0190 0x0250 0x4 0x3
+#define ULP1_PAD_PTF4__LPI2C5_SCL 0x0190 0x02bc 0x5 0x3
+#define ULP1_PAD_PTF4__TPM4_CH3 0x0190 0x028c 0x6 0x2
+#define ULP1_PAD_PTF4__FB_AD17 0x0190 0x0000 0x9 0x0
+#define ULP1_PAD_PTF5__PTF5 0x0194 0x0000 0x1 0x0
+#define ULP1_PAD_PTF5__VIU_D1 0x0194 0x0000 0xc 0x0
+#define ULP1_PAD_PTF5__FXIO1_D1 0x0194 0x0208 0x2 0x2
+#define ULP1_PAD_PTF5__LPSPI2_PCS2 0x0194 0x02a4 0x3 0x3
+#define ULP1_PAD_PTF5__LPUART5_RTS_B 0x0194 0x0000 0x4 0x0
+#define ULP1_PAD_PTF5__LPI2C5_SDA 0x0194 0x02c0 0x5 0x3
+#define ULP1_PAD_PTF5__TPM4_CH4 0x0194 0x0290 0x6 0x2
+#define ULP1_PAD_PTF5__FB_AD18 0x0194 0x0000 0x9 0x0
+#define ULP1_PAD_PTF6__PTF6 0x0198 0x0000 0x1 0x0
+#define ULP1_PAD_PTF6__VIU_D2 0x0198 0x0000 0xc 0x0
+#define ULP1_PAD_PTF6__FXIO1_D2 0x0198 0x020c 0x2 0x2
+#define ULP1_PAD_PTF6__LPSPI2_PCS3 0x0198 0x02a8 0x3 0x3
+#define ULP1_PAD_PTF6__LPUART5_TX 0x0198 0x0258 0x4 0x3
+#define ULP1_PAD_PTF6__LPI2C5_HREQ 0x0198 0x02b8 0x5 0x3
+#define ULP1_PAD_PTF6__TPM4_CH5 0x0198 0x0294 0x6 0x2
+#define ULP1_PAD_PTF6__FB_AD19 0x0198 0x0000 0x9 0x0
+#define ULP1_PAD_PTF7__PTF7 0x019c 0x0000 0x1 0x0
+#define ULP1_PAD_PTF7__VIU_D3 0x019c 0x0000 0xc 0x0
+#define ULP1_PAD_PTF7__FXIO1_D3 0x019c 0x0210 0x2 0x2
+#define ULP1_PAD_PTF7__LPUART5_RX 0x019c 0x0254 0x4 0x3
+#define ULP1_PAD_PTF7__TPM5_CH1 0x019c 0x02c8 0x6 0x3
+#define ULP1_PAD_PTF7__FB_AD20 0x019c 0x0000 0x9 0x0
+#define ULP1_PAD_PTF8__PTF8 0x01a0 0x0000 0x1 0x0
+#define ULP1_PAD_PTF8__USB1_ULPI_CLK 0x01a0 0x0000 0xb 0x0
+#define ULP1_PAD_PTF8__VIU_D4 0x01a0 0x0000 0xc 0x0
+#define ULP1_PAD_PTF8__FXIO1_D4 0x01a0 0x0214 0x2 0x2
+#define ULP1_PAD_PTF8__LPSPI2_SIN 0x01a0 0x02b0 0x3 0x3
+#define ULP1_PAD_PTF8__LPUART6_CTS_B 0x01a0 0x025c 0x4 0x3
+#define ULP1_PAD_PTF8__LPI2C6_SCL 0x01a0 0x02fc 0x5 0x3
+#define ULP1_PAD_PTF8__TPM5_CLKIN 0x01a0 0x02cc 0x6 0x3
+#define ULP1_PAD_PTF8__FB_AD21 0x01a0 0x0000 0x9 0x0
+#define ULP1_PAD_PTF9__PTF9 0x01a4 0x0000 0x1 0x0
+#define ULP1_PAD_PTF9__USB1_ULPI_NXT 0x01a4 0x0000 0xb 0x0
+#define ULP1_PAD_PTF9__VIU_D5 0x01a4 0x0000 0xc 0x0
+#define ULP1_PAD_PTF9__FXIO1_D5 0x01a4 0x0218 0x2 0x2
+#define ULP1_PAD_PTF9__LPSPI2_SOUT 0x01a4 0x02b4 0x3 0x3
+#define ULP1_PAD_PTF9__LPUART6_RTS_B 0x01a4 0x0000 0x4 0x0
+#define ULP1_PAD_PTF9__LPI2C6_SDA 0x01a4 0x0300 0x5 0x3
+#define ULP1_PAD_PTF9__TPM5_CH0 0x01a4 0x02c4 0x6 0x3
+#define ULP1_PAD_PTF9__FB_AD22 0x01a4 0x0000 0x9 0x0
+#define ULP1_PAD_PTF10__PTF10 0x01a8 0x0000 0x1 0x0
+#define ULP1_PAD_PTF10__USB1_ULPI_STP 0x01a8 0x0000 0xb 0x0
+#define ULP1_PAD_PTF10__VIU_D6 0x01a8 0x0000 0xc 0x0
+#define ULP1_PAD_PTF10__FXIO1_D6 0x01a8 0x021c 0x2 0x2
+#define ULP1_PAD_PTF10__LPSPI2_SCK 0x01a8 0x02ac 0x3 0x3
+#define ULP1_PAD_PTF10__LPUART6_TX 0x01a8 0x0264 0x4 0x3
+#define ULP1_PAD_PTF10__LPI2C6_HREQ 0x01a8 0x02f8 0x5 0x3
+#define ULP1_PAD_PTF10__TPM7_CH3 0x01a8 0x02e8 0x6 0x3
+#define ULP1_PAD_PTF10__FB_AD23 0x01a8 0x0000 0x9 0x0
+#define ULP1_PAD_PTF11__PTF11 0x01ac 0x0000 0x1 0x0
+#define ULP1_PAD_PTF11__USB1_ULPI_DIR 0x01ac 0x0000 0xb 0x0
+#define ULP1_PAD_PTF11__VIU_D7 0x01ac 0x0000 0xc 0x0
+#define ULP1_PAD_PTF11__FXIO1_D7 0x01ac 0x0220 0x2 0x2
+#define ULP1_PAD_PTF11__LPSPI2_PCS0 0x01ac 0x029c 0x3 0x3
+#define ULP1_PAD_PTF11__LPUART6_RX 0x01ac 0x0260 0x4 0x3
+#define ULP1_PAD_PTF11__TPM7_CH4 0x01ac 0x02ec 0x6 0x3
+#define ULP1_PAD_PTF11__FB_CS4_B_FB_TSIZ0_FB_BE31_24_BLS7_0_B 0x01ac 0x0000 0x9 0x0
+#define ULP1_PAD_PTF12__PTF12 0x01b0 0x0000 0x1 0x0
+#define ULP1_PAD_PTF12__USB1_ULPI_DATA0 0x01b0 0x0000 0xb 0x0
+#define ULP1_PAD_PTF12__VIU_D8 0x01b0 0x0000 0xc 0x0
+#define ULP1_PAD_PTF12__FXIO1_D8 0x01b0 0x0224 0x2 0x2
+#define ULP1_PAD_PTF12__LPSPI3_PCS1 0x01b0 0x0314 0x3 0x3
+#define ULP1_PAD_PTF12__LPUART7_CTS_B 0x01b0 0x0268 0x4 0x3
+#define ULP1_PAD_PTF12__LPI2C7_SCL 0x01b0 0x0308 0x5 0x3
+#define ULP1_PAD_PTF12__TPM7_CH5 0x01b0 0x02f0 0x6 0x3
+#define ULP1_PAD_PTF12__FB_AD24 0x01b0 0x0000 0x9 0x0
+#define ULP1_PAD_PTF13__PTF13 0x01b4 0x0000 0x1 0x0
+#define ULP1_PAD_PTF13__USB1_ULPI_DATA1 0x01b4 0x0000 0xb 0x0
+#define ULP1_PAD_PTF13__VIU_D9 0x01b4 0x0000 0xc 0x0
+#define ULP1_PAD_PTF13__FXIO1_D9 0x01b4 0x0228 0x2 0x2
+#define ULP1_PAD_PTF13__LPSPI3_PCS2 0x01b4 0x0318 0x3 0x3
+#define ULP1_PAD_PTF13__LPUART7_RTS_B 0x01b4 0x0000 0x4 0x0
+#define ULP1_PAD_PTF13__LPI2C7_SDA 0x01b4 0x030c 0x5 0x3
+#define ULP1_PAD_PTF13__TPM7_CLKIN 0x01b4 0x02f4 0x6 0x3
+#define ULP1_PAD_PTF13__FB_AD25 0x01b4 0x0000 0x9 0x0
+#define ULP1_PAD_PTF14__PTF14 0x01b8 0x0000 0x1 0x0
+#define ULP1_PAD_PTF14__USB1_ULPI_DATA2 0x01b8 0x0000 0xb 0x0
+#define ULP1_PAD_PTF14__VIU_D10 0x01b8 0x0000 0xc 0x0
+#define ULP1_PAD_PTF14__FXIO1_D10 0x01b8 0x022c 0x2 0x2
+#define ULP1_PAD_PTF14__LPSPI3_PCS3 0x01b8 0x031c 0x3 0x3
+#define ULP1_PAD_PTF14__LPUART7_TX 0x01b8 0x0270 0x4 0x3
+#define ULP1_PAD_PTF14__LPI2C7_HREQ 0x01b8 0x0304 0x5 0x3
+#define ULP1_PAD_PTF14__TPM7_CH0 0x01b8 0x02dc 0x6 0x3
+#define ULP1_PAD_PTF14__FB_AD26 0x01b8 0x0000 0x9 0x0
+#define ULP1_PAD_PTF15__PTF15 0x01bc 0x0000 0x1 0x0
+#define ULP1_PAD_PTF15__USB1_ULPI_DATA3 0x01bc 0x0000 0xb 0x0
+#define ULP1_PAD_PTF15__VIU_D11 0x01bc 0x0000 0xc 0x0
+#define ULP1_PAD_PTF15__FXIO1_D11 0x01bc 0x0230 0x2 0x2
+#define ULP1_PAD_PTF15__LPUART7_RX 0x01bc 0x026c 0x4 0x3
+#define ULP1_PAD_PTF15__TPM7_CH1 0x01bc 0x02e0 0x6 0x3
+#define ULP1_PAD_PTF15__FB_AD27 0x01bc 0x0000 0x9 0x0
+#define ULP1_PAD_PTF16__PTF16 0x01c0 0x0000 0x1 0x0
+#define ULP1_PAD_PTF16__USB1_ULPI_DATA4 0x01c0 0x0000 0xb 0x0
+#define ULP1_PAD_PTF16__VIU_D12 0x01c0 0x0000 0xc 0x0
+#define ULP1_PAD_PTF16__FXIO1_D12 0x01c0 0x0234 0x2 0x2
+#define ULP1_PAD_PTF16__LPSPI3_SIN 0x01c0 0x0324 0x3 0x3
+#define ULP1_PAD_PTF16__TPM7_CH2 0x01c0 0x02e4 0x6 0x3
+#define ULP1_PAD_PTF16__FB_AD28 0x01c0 0x0000 0x9 0x0
+#define ULP1_PAD_PTF17__PTF17 0x01c4 0x0000 0x1 0x0
+#define ULP1_PAD_PTF17__USB1_ULPI_DATA5 0x01c4 0x0000 0xb 0x0
+#define ULP1_PAD_PTF17__VIU_D13 0x01c4 0x0000 0xc 0x0
+#define ULP1_PAD_PTF17__FXIO1_D13 0x01c4 0x0238 0x2 0x2
+#define ULP1_PAD_PTF17__LPSPI3_SOUT 0x01c4 0x0328 0x3 0x3
+#define ULP1_PAD_PTF17__TPM6_CLKIN 0x01c4 0x02d8 0x6 0x3
+#define ULP1_PAD_PTF17__FB_AD29 0x01c4 0x0000 0x9 0x0
+#define ULP1_PAD_PTF18__PTF18 0x01c8 0x0000 0x1 0x0
+#define ULP1_PAD_PTF18__USB1_ULPI_DATA6 0x01c8 0x0000 0xb 0x0
+#define ULP1_PAD_PTF18__VIU_D14 0x01c8 0x0000 0xc 0x0
+#define ULP1_PAD_PTF18__FXIO1_D14 0x01c8 0x023c 0x2 0x2
+#define ULP1_PAD_PTF18__LPSPI3_SCK 0x01c8 0x0320 0x3 0x3
+#define ULP1_PAD_PTF18__TPM6_CH0 0x01c8 0x02d0 0x6 0x3
+#define ULP1_PAD_PTF18__FB_AD30 0x01c8 0x0000 0x9 0x0
+#define ULP1_PAD_PTF19__PTF19 0x01cc 0x0000 0x1 0x0
+#define ULP1_PAD_PTF19__USB1_ULPI_DATA7 0x01cc 0x0000 0xb 0x0
+#define ULP1_PAD_PTF19__VIU_D15 0x01cc 0x0000 0xc 0x0
+#define ULP1_PAD_PTF19__FXIO1_D15 0x01cc 0x0240 0x2 0x2
+#define ULP1_PAD_PTF19__LPSPI3_PCS0 0x01cc 0x0310 0x3 0x3
+#define ULP1_PAD_PTF19__TPM6_CH1 0x01cc 0x02d4 0x6 0x3
+#define ULP1_PAD_PTF19__FB_AD31 0x01cc 0x0000 0x9 0x0
+
+#endif /* __DTS_ULP1_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
new file mode 100644
index 000000000000..323fa580bd59
--- /dev/null
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -0,0 +1,633 @@
+/*
+ * Copyright 2015-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 <dt-bindings/clock/imx7ulp-clock.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "skeleton.dtsi"
+#include "imx7ulp-pinfunc.h"
+
+/ {
+ interrupt-parent = <&intc>;
+
+ aliases {
+ gpio0 = &gpio0;
+ gpio1 = &gpio1;
+ gpio2 = &gpio2;
+ gpio3 = &gpio3;
+ mmc0 = &usdhc0;
+ mmc1 = &usdhc1;
+ serial0 = &lpuart4;
+ serial1 = &lpuart5;
+ serial2 = &lpuart6;
+ serial3 = &lpuart7;
+ usbphy0 = &usbphy1;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ clock-latency = <61036>; /* two CLK32 periods */
+ reg = <0>;
+
+ operating-points = <
+ /* KHz uV */
+ 531648 1125000
+ 416072 1025000
+ >;
+ clocks = <&clks IMX7ULP_CLK_ARM>,
+ <&clks IMX7ULP_CLK_CORE_DIV>,
+ <&clks IMX7ULP_CLK_SYS_SEL>,
+ <&clks IMX7ULP_CLK_HSRUN_SYS_SEL>,
+ <&clks IMX7ULP_CLK_HSRUN_CORE>,
+ <&clks IMX7ULP_CLK_SPLL_PFD0>,
+ <&clks IMX7ULP_CLK_SPLL_SEL>,
+ <&clks IMX7ULP_CLK_FIRC>;
+ clock-names = "arm", "core_div", "sys_sel", "hsrun_sys_sel",
+ "hsrun_core", "spll_pfd0", "spll_sel", "firc";
+ };
+ };
+
+ 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;
+ };
+
+ rpmsg_reserved: rpmsg@9FFF0000 {
+ no-map;
+ reg = <0x9FF00000 0x100000>;
+ };
+
+ };
+
+ intc: interrupt-controller@40021000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x40021000 0x1000>,
+ <0x40022000 0x100>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil: clock@0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "ckil";
+ };
+
+ osc: clock@1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc";
+ };
+
+ sirc: clock@2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <16000000>;
+ clock-output-names = "sirc";
+ };
+
+ firc: clock@3 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <48000000>;
+ clock-output-names = "firc";
+ };
+
+ upll: clock@4 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <480000000>;
+ clock-output-names = "upll";
+ };
+
+ mpll: clock@5 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <480000000>;
+ clock-output-names = "mpll";
+ };
+ };
+
+ sram: sram@20000000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x1fffc000 0x4000>;
+ };
+
+ ahbbridge0: ahb-bridge0@40000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x40000000 0x800000>;
+ ranges;
+
+ edma0: dma-controller@40080000 {
+ #dma-cells = <2>;
+ compatible = "nxp,imx7ulp-edma";
+ reg = <0x40080000 0x2000>,
+ <0x40210000 0x1000>;
+ dma-channels = <32>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "dma", "dmamux0";
+ clocks = <&clks IMX7ULP_CLK_DMA1>, <&clks IMX7ULP_CLK_DMA_MUX1>;
+ };
+
+ mu: mu@40220000 {
+ compatible = "fsl,imx7ulp-mu", "fsl,imx6sx-mu";
+ reg = <0x40220000 0x1000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ status = "okay";
+ };
+
+ nmi: nmi@40220000 {
+ compatible = "fsl,imx7ulp-nmi";
+ reg = <0x40220000 0x1000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+ status = "okay";
+ };
+
+ rpmsg: rpmsg{
+ compatible = "fsl,imx7ulp-rpmsg";
+ memory-region = <&rpmsg_reserved>;
+ status = "disabled";
+ };
+
+ snvs: snvs@40230000 {
+ compatible = "fsl,sec-v4.0-mon","syscon", "simple-mfd";
+ reg = <0x40230000 0x10000>;
+
+ snvs_rtc: snvs-rtc-lp{
+ compatible = "fsl,sec-v4.0-mon-rtc-lp";
+ regmap =<&snvs>;
+ offset = <0x34>;
+ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "snvs-rtc";
+ clocks = <&clks IMX7ULP_CLK_SNVS>;
+ };
+ };
+
+ pwm0: tpm@40250000 {
+ compatible = "nxp,tpm-pwm";
+ reg = <0x40250000 0x1000>;
+ nxp,pwm-number = <6>;
+ assigned-clocks = <&clks IMX7ULP_CLK_LPTPM4>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_OSC>;
+ clocks = <&clks IMX7ULP_CLK_LPTPM4>;
+ #pwm-cells = <2>;
+ };
+
+ tpm5: tpm@40260000 {
+ compatible = "fsl,imx7ulp-tpm";
+ reg = <0x40260000 0x1000>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPTPM5>;
+ };
+
+ lpit: 1@40270000 {
+ compatible = "fsl,imx-lpit";
+ reg = <0x40270000 0x1000>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ /* clocks = <&lpclk>;*/
+ clocks = <&clks IMX7ULP_CLK_LPIT1>;
+ assigned-clock-rates = <48000000>;
+ assigned-clocks = <&clks IMX7ULP_CLK_LPIT1>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ };
+
+ lpi2c4: lpi2c4@402B0000 {
+ compatible = "fsl,imx7ulp-lpi2c";
+ reg = <0x402B0000 0x10000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPI2C4>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPI2C4>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ 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 = <&clks IMX7ULP_CLK_LPI2C5>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPI2C5>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ };
+
+ lpspi2: lpspi@40290000 {
+ compatible = "fsl,imx7ulp-spi";
+ reg = <0x40290000 0x10000>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPSPI2>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPSPI2>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ status = "disabled";
+ };
+
+ lpspi3: lpspi@402A0000 {
+ compatible = "fsl,imx7ulp-spi";
+ reg = <0x402A0000 0x10000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPSPI3>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPSPI3>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ status = "disabled";
+ };
+
+ lpuart4: serial@402D0000 {
+ compatible = "fsl,imx7ulp-lpuart";
+ reg = <0x402D0000 0x1000>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPUART4>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPUART4>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_OSC>;
+ assigned-clock-rates = <24000000>;
+ status = "disabled";
+ };
+
+ lpuart5: serial@402E0000 {
+ compatible = "fsl,imx7ulp-lpuart";
+ reg = <0x402E0000 0x1000>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPUART5>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPUART5>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ dmas = <&edma0 0 20>, <&edma0 0 19>;
+ dma-names = "tx","rx";
+ status = "disabled";
+ };
+
+ usbotg1: usb@40330000 {
+ compatible = "fsl,imx7ulp-usb", "fsl,imx6ul-usb",
+ "fsl,imx27-usb";
+ reg = <0x40330000 0x200>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_USB0>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc1 0>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x8>;
+ rx-burst-size-dword = <0x8>;
+ status = "disabled";
+ };
+
+ usbmisc1: usbmisc@40330200 {
+ #index-cells = <1>;
+ compatible = "fsl,imx7ulp-usbmisc", "fsl,imx7d-usbmisc",
+ "fsl,imx6q-usbmisc";
+ reg = <0x40330200 0x200>;
+ };
+
+ usbphy1: usbphy@0x40350000 {
+ compatible = "fsl,imx7ulp-usbphy",
+ "fsl,imx6ul-usbphy", "fsl,imx23-usbphy";
+ reg = <0x40350000 0x1000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_USB_PHY>;
+ nxp,sim = <&sim>;
+ };
+
+ usdhc0: usdhc@40370000 {
+ compatible = "fsl,imx7ulp-usdhc";
+ reg = <0x40370000 0x10000>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_NIC1_BUS_DIV>,
+ <&clks IMX7ULP_CLK_NIC1_DIV>,
+ <&clks IMX7ULP_CLK_USDHC0>;
+ clock-names ="ipg", "ahb", "per";
+ bus-width = <4>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+ usdhc1: usdhc@40380000 {
+ compatible = "fsl,imx7ulp-usdhc";
+ reg = <0x40380000 0x10000>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_NIC1_BUS_DIV>,
+ <&clks IMX7ULP_CLK_NIC1_DIV>,
+ <&clks IMX7ULP_CLK_USDHC1>;
+ clock-names ="ipg", "ahb", "per";
+ bus-width = <4>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+ wdog1: wdog@403D0000 {
+ compatible = "fsl,imx7ulp-wdt";
+ reg = <0x403D0000 0x10000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_WDG1>;
+ assigned-clocks = <&clks IMX7ULP_CLK_WDG1>;
+ assigned-clocks-parents = <&clks IMX7ULP_CLK_FIRC>;
+ /*
+ * 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 = <&clks IMX7ULP_CLK_WDG2>;
+ assigned-clocks = <&clks IMX7ULP_CLK_WDG2>;
+ assigned-clocks-parents = <&clks IMX7ULP_CLK_FIRC>;
+ timeout-sec = <40>;
+ };
+
+ clks: scg1@403E0000 {
+ compatible = "fsl,imx7ulp-scg1";
+ reg = <0x403E0000 0x10000>;
+ clocks = <&ckil>, <&osc>, <&sirc>,
+ <&firc>, <&upll>, <&mpll>;
+ clock-names = "ckil", "osc", "sirc",
+ "firc", "upll", "mpll";
+ #clock-cells = <1>;
+ assigned-clocks = <&clks IMX7ULP_CLK_LPTPM5>,
+ <&clks IMX7ULP_CLK_USDHC1>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_OSC>,
+ <&clks IMX7ULP_CLK_NIC1_DIV>;
+ };
+
+ pcc2: pcc2@403F0000 {
+ compatible = "fsl,imx7ulp-pcc2";
+ reg = <0x403F0000 0x10000>;
+ };
+
+ pmc1: pmc1@40400000 {
+ compatible = "fsl,imx7ulp-pmc1";
+ reg = <0x40400000 0x1000>;
+ };
+
+ smc1: smc1@40410000 {
+ compatible = "fsl,imx7ulp-smc1";
+ reg = <0x40410000 0x1000>;
+ };
+
+ };
+
+ ahbbridge1: ahb-bridge1@40800000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x40800000 0x800000>;
+ ranges;
+
+ lpi2c6: lpi2c6@40A40000 {
+ compatible = "fsl,imx7ulp-lpi2c";
+ reg = <0x40A40000 0x10000>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPI2C6>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPI2C6>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ status = "disabled";
+ };
+
+ lpi2c7: lpi2c7@40A50000 {
+ compatible = "fsl,imx7ulp-lpi2c";
+ reg = <0x40A50000 0x10000>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPI2C7>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPI2C7>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ status = "disabled";
+ };
+
+ lpuart6: serial@40A60000 {
+ compatible = "fsl,imx7ulp-lpuart";
+ reg = <0x40A60000 0x1000>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPUART6>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPUART6>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ dmas = <&edma0 0 22>, <&edma0 0 21>;
+ dma-names = "tx","rx";
+ status = "disabled";
+ };
+
+ lpuart7: serial@40A70000 {
+ compatible = "fsl,imx7ulp-lpuart";
+ reg = <0x40A70000 0x1000>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_LPUART7>;
+ clock-names = "ipg";
+ assigned-clocks = <&clks IMX7ULP_CLK_LPUART7>;
+ assigned-clock-parents = <&clks IMX7ULP_CLK_FIRC>;
+ assigned-clock-rates = <48000000>;
+ dmas = <&edma0 0 24>, <&edma0 0 23>;
+ dma-names = "tx","rx";
+ status = "disabled";
+ };
+
+ lcdif: lcdif@40AA0000 {
+ compatible = "fsl,imx7ulp-lcdif";
+ reg = <0x40aa0000 0x10000>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_DUMMY>,
+ <&clks IMX7ULP_CLK_LCDIF>,
+ <&clks IMX7ULP_CLK_DUMMY>;
+ clock-names = "axi", "pix", "disp_axi";
+ status = "disabled";
+ };
+
+ mipi_dsi: mipi_dsi@40A90000 {
+ compatible = "fsl,imx7ulp-mipi-dsi";
+ reg = <0x40A90000 0x10000>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_DSI>;
+ clock-names = "mipi_dsi_clk";
+ data-lanes-num = <2>;
+ max-data-rate = <800000000>;
+ sim = <&sim>;
+ status = "disabled";
+ };
+
+ mmdc: mmdc@40ab0000 {
+ compatible = "fsl,imx7ulp-mmdc";
+ reg = <0x40ab0000 0x4000>;
+ };
+
+ pcc3: pcc3@40B30000 {
+ compatible = "fsl,imx7ulp-pcc3";
+ reg = <0x40B30000 0x10000>;
+ };
+
+ iomuxc: iomuxc@4103D000 {
+ compatible = "fsl,imx7ulp-iomuxc-0";
+ reg = <0x4103D000 0x1000>;
+ fsl,mux_mask = <0xf00>;
+ status = "disabled";
+ };
+
+ iomuxc1: iomuxc1@40ac0000 {
+ compatible = "fsl,imx7ulp-iomuxc-1";
+ reg = <0x40ac0000 0x1000>;
+ fsl,mux_mask = <0xf00>;
+ };
+
+ gpio0: gpio@40ae0000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x40ae0000 0x1000 0x400F0000 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc1 0 0 32>;
+ };
+
+ gpio1: gpio@40af0000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x40af0000 0x1000 0x400F0040 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc1 0 32 32>;
+ };
+
+ gpio2: gpio@40b00000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x40b00000 0x1000 0x400F0080 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc1 0 64 32>;
+ };
+
+ gpio3: gpio@40b10000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x40b10000 0x1000 0x400F00c0 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc1 0 96 32>;
+ };
+
+ pmc0: pmc0@410a1000 {
+ compatible = "fsl,imx7ulp-pmc0";
+ reg = <0x410a1000 0x1000>;
+ };
+
+ sim: sim@410a3000 {
+ compatible = "fsl,imx7ulp-sim", "syscon";
+ reg = <0x410a3000 0x1000>;
+ };
+
+ qspi1: qspi@410A5000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx7ulp-qspi";
+ reg = <0x410A5000 0x1000>, <0xC0000000 0x10000000>;
+ reg-names = "QuadSPI", "QuadSPI-memory";
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7ULP_CLK_DUMMY>,
+ <&clks IMX7ULP_CLK_DUMMY>;
+ clock-names = "qspi_en", "qspi";
+ status = "disabled";
+ };
+
+ ocotp: ocotp@410a6000 {
+ compatible = "fsl,imx7ulp-ocotp";
+ reg = <0x410a6000 0x4000>;
+ clocks = <&clks IMX7ULP_CLK_DUMMY>;
+ };
+
+ gpu: gpu@41800000 {
+ compatible = "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 = <&clks IMX7ULP_CLK_GPU3D>,
+ <&clks IMX7ULP_CLK_DUMMY>,
+ <&clks IMX7ULP_CLK_GPU_DIV>,
+ <&clks IMX7ULP_CLK_GPU2D>,
+ <&clks IMX7ULP_CLK_NIC1_DIV>;
+ clock-names = "gpu3d_clk", "gpu3d_shader_clk",
+ "gpu3d_axi_clk", "gpu2d_clk",
+ "gpu2d_axi_clk";
+ };
+ };
+
+ heartbeat-rpmsg {
+ compatible = "fsl,heartbeat-rpmsg";
+ };
+
+ imx_ion {
+ compatible = "fsl,mxc-ion";
+ fsl,heap-id = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 2c13ec696ac5..4cddd8029703 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -344,6 +344,7 @@
iomuxc: iomuxc@40048000 {
compatible = "fsl,vf610-iomuxc";
reg = <0x40048000 0x1000>;
+ fsl,mux_mask = <0x700000>;
};
gpio0: gpio@40049000 {
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
new file mode 100644
index 000000000000..5d6d3d0189b5
--- /dev/null
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -0,0 +1,455 @@
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX50=y
+CONFIG_SOC_IMX53=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_IMX6SX=y
+CONFIG_SOC_IMX6ULL=y
+CONFIG_SOC_IMX7D=y
+CONFIG_SOC_IMX6SLL=y
+CONFIG_SOC_IMX7ULP=y
+CONFIG_SOC_VF610=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_CMA=y
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_ARM_IMX6Q_CPUFREQ=y
+CONFIG_ARM_IMX7D_CPUFREQ=y
+CONFIG_ARM_IMX7ULP_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_VLAN_8021Q=y
+CONFIG_LLC2=y
+CONFIG_CAN=y
+CONFIG_CAN_FLEXCAN=y
+CONFIG_CAN_M_CAN=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_ATH3K=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_ATH3K=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=0
+CONFIG_IMX_WEIM=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SST25L=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+CONFIG_SPI_FSL_QUADSPI=y
+CONFIG_MTD_UBI=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_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_MICREL_PHY=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_RTL8152=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_BCMDHD=y
+CONFIG_BCMDHD_SDIO=y
+CONFIG_BCMDHD_FW_PATH="/lib/firmware/bcm/ZP_BCM4339/fw_bcmdhd.bin"
+CONFIG_BCMDHD_NVRAM_PATH="/lib/firmware/bcm/ZP_BCM4339/bcmdhd.ZP.OOB.cal"
+# CONFIG_RTL_CARDS is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_RPMSG=y
+CONFIG_KEYBOARD_PF1550_ONKEY=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_MAX11801=y
+CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
+CONFIG_TOUCHSCREEN_MC13783=y
+CONFIG_TOUCHSCREEN_TSC2007=y
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_TOUCHSCREEN_FTS=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_INPUT_MPL3115=y
+CONFIG_SENSOR_FXLS8471=y
+CONFIG_INPUT_ISL29023=y
+CONFIG_SERIO_SERPORT=m
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+CONFIG_FSL_OTP=y
+CONFIG_HW_RANDOM_IMX_RNG=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_I2C_IMX_LPI2C=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_FSL_LPSPI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_IMX_RPMSG=y
+CONFIG_GPIO_MAX732X=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_74X164=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_CHARGER_PF1550=y
+CONFIG_SABRESD_MAX8903=y
+CONFIG_SENSORS_MAX17135=y
+CONFIG_SENSORS_MAG3110=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_IMX7ULP_WDT=y
+CONFIG_MFD_DA9052_I2C=y
+CONFIG_MFD_MC13XXX_SPI=y
+CONFIG_MFD_MC13XXX_I2C=y
+CONFIG_MFD_PF1550=y
+CONFIG_MFD_MAX17135=y
+CONFIG_MFD_SI476X_CORE=y
+CONFIG_MFD_STMPE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_DA9052=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX17135=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_REGULATOR_PFUZE100=y
+CONFIG_REGULATOR_PF1550=y
+CONFIG_REGULATOR_PF1550_RPMSG=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+CONFIG_RC_DEVICES=y
+CONFIG_IR_GPIO_CIR=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MXC_OUTPUT=y
+CONFIG_VIDEO_MXC_CAPTURE=m
+CONFIG_MXC_CAMERA_OV5640=m
+CONFIG_MXC_CAMERA_OV5642=m
+CONFIG_MXC_CAMERA_OV5640_MIPI=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_VIDEO_MXC_CSI_CAMERA=m
+CONFIG_MXC_VADC=m
+CONFIG_MXC_MIPI_CSI=m
+CONFIG_MXC_CAMERA_OV5647_MIPI=m
+CONFIG_SOC_CAMERA=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_CODA=y
+CONFIG_RADIO_SI476X=y
+CONFIG_SOC_CAMERA_OV2640=y
+CONFIG_DRM=y
+CONFIG_DRM_VIVANTE=y
+CONFIG_FB_MXS=y
+CONFIG_FB_MXC_SYNC_PANEL=y
+CONFIG_FB_MXC_OVERLAY=y
+CONFIG_FB_MXC_MIPI_DSI=y
+CONFIG_FB_MXC_MIPI_DSI_SAMSUNG=y
+CONFIG_FB_MXC_MIPI_DSI_NORTHWEST=y
+CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
+CONFIG_FB_MXC_TRULY_PANEL_TFT3P5079E=y
+CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E=y
+CONFIG_FB_MXC_LDB=y
+CONFIG_FB_MXC_HDMI=y
+CONFIG_FB_MXS_SII902X=y
+CONFIG_FB_MXC_DCIC=m
+CONFIG_FB_MXC_ADV7535=y
+CONFIG_HANNSTAR_CABC=y
+CONFIG_FB_MXC_EINK_PANEL=y
+CONFIG_FB_MXC_EINK_V2_PANEL=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_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_USB=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=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=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_MXC_IPU=y
+CONFIG_MXC_IPU_V3_PRE=y
+CONFIG_MXC_GPU_VIV=y
+CONFIG_MXC_SIM=y
+CONFIG_MXC_MIPI_CSI2=y
+CONFIG_MXC_HDMI_CEC=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=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_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_MC13XXX=y
+CONFIG_RTC_DRV_MXC=y
+CONFIG_RTC_DRV_SNVS=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_ION=y
+CONFIG_ION_MXC=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_IMX7D_ADC=y
+CONFIG_VF610_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX=y
+CONFIG_PWM_TPM=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_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_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_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CTS=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_XTS=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=y
+CONFIG_CRYPTO_RMD160=y
+CONFIG_CRYPTO_RMD256=y
+CONFIG_CRYPTO_RMD320=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_CAMELLIA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y
+CONFIG_CRYPTO_DEV_MXS_DCP=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
diff --git a/arch/arm/configs/imx_v7_mfg_defconfig b/arch/arm/configs/imx_v7_mfg_defconfig
new file mode 100644
index 000000000000..b137a506ac35
--- /dev/null
+++ b/arch/arm/configs/imx_v7_mfg_defconfig
@@ -0,0 +1,301 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=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_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MULTI_V6=y
+CONFIG_ARCH_MXC=y
+# CONFIG_MACH_MX31ADS is not set
+# CONFIG_MACH_BUG is not set
+CONFIG_SOC_IMX50=y
+CONFIG_SOC_IMX53=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_IMX6SX=y
+CONFIG_SOC_IMX6ULL=y
+CONFIG_SOC_IMX7D=y
+CONFIG_SOC_IMX6SLL=y
+CONFIG_SOC_IMX7ULP=y
+CONFIG_SOC_VF610=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_CMA=y
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_ARM_IMX6Q_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_NETFILTER=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=320
+CONFIG_IMX_WEIM=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SST25L=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+CONFIG_SPI_FSL_QUADSPI=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_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_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_AT803X_PHY=y
+CONFIG_BRCMFMAC=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_EGALAX=y
+CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
+CONFIG_TOUCHSCREEN_MC13783=y
+CONFIG_TOUCHSCREEN_TSC2007=y
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_SERIO_SERPORT=m
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+CONFIG_HW_RANDOM=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_DA9052_I2C=y
+CONFIG_MFD_MC13XXX_SPI=y
+CONFIG_MFD_MC13XXX_I2C=y
+CONFIG_MFD_PF1550=y
+CONFIG_MFD_MAX17135=y
+CONFIG_MFD_SI476X_CORE=y
+CONFIG_MFD_STMPE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_DA9052=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX17135=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_REGULATOR_PFUZE100=y
+CONFIG_REGULATOR_PF1550=y
+CONFIG_REGULATOR_PF1550_RPMSG=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+CONFIG_RC_DEVICES=y
+CONFIG_IR_GPIO_CIR=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MXC_OUTPUT=y
+CONFIG_VIDEO_MXC_PXP_V4L2=y
+CONFIG_SOC_CAMERA=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_CODA=y
+CONFIG_SOC_CAMERA_OV2640=y
+CONFIG_DRM=y
+CONFIG_DRM_VIVANTE=y
+CONFIG_FB_MXS=y
+CONFIG_FB_MXC_SYNC_PANEL=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_L4F00242T03=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_SND_SOC_IMX_WM8962=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_SPDIF=y
+CONFIG_SND_SOC_IMX_MC13783=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_MASS_STORAGE=y
+CONFIG_FSL_UTP=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_MXC_IPU=y
+CONFIG_MXC_IPU_V3_PRE=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=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_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_MC13XXX=y
+CONFIG_RTC_DRV_MXC=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=y
+CONFIG_MXS_DMA=y
+CONFIG_MXC_PXP_V2=y
+CONFIG_STAGING=y
+CONFIG_STAGING_MEDIA=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_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_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+CONFIG_SECURITYFS=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
diff --git a/arch/arm/include/debug/imx-uart.h b/arch/arm/include/debug/imx-uart.h
index bce58e975ad1..24e60ce18347 100644
--- a/arch/arm/include/debug/imx-uart.h
+++ b/arch/arm/include/debug/imx-uart.h
@@ -81,6 +81,14 @@
#define IMX6SL_UART_BASE_ADDR(n) IMX6SL_UART##n##_BASE_ADDR
#define IMX6SL_UART_BASE(n) IMX6SL_UART_BASE_ADDR(n)
+#define IMX6SLL_UART1_BASE_ADDR 0x02020000
+#define IMX6SLL_UART2_BASE_ADDR 0x02024000
+#define IMX6SLL_UART3_BASE_ADDR 0x02034000
+#define IMX6SLL_UART4_BASE_ADDR 0x02018000
+#define IMX6SLL_UART5_BASE_ADDR 0x021f4000
+#define IMX6SLL_UART_BASE_ADDR(n) IMX6SLL_UART##n##_BASE_ADDR
+#define IMX6SLL_UART_BASE(n) IMX6SLL_UART_BASE_ADDR(n)
+
#define IMX6SX_UART1_BASE_ADDR 0x02020000
#define IMX6SX_UART2_BASE_ADDR 0x021e8000
#define IMX6SX_UART3_BASE_ADDR 0x021ec000
@@ -133,6 +141,8 @@
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6Q)
#elif defined(CONFIG_DEBUG_IMX6SL_UART)
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SL)
+#elif defined(CONFIG_DEBUG_IMX6SLL_UART)
+#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SLL)
#elif defined(CONFIG_DEBUG_IMX6SX_UART)
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SX)
#elif defined(CONFIG_DEBUG_IMX6UL_UART)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 9155b639c9aa..34f2c63bcaf2 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -44,6 +44,9 @@ config MXC_USE_EPIT
uses the same clocks as the GPT. Anyway, on some systems the GPT
may be in use for other purposes.
+config HAVE_IMX_RNG
+ bool
+
config HAVE_IMX_ANATOP
bool
@@ -51,9 +54,26 @@ 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
+
+config HAVE_IMX_MU
+ bool
+
+config HAVE_IMX_RPMSG
+ select RPMSG_VIRTIO
+ bool
+
config HAVE_IMX_SRC
def_bool y if SMP
select ARCH_HAS_RESET_CONTROLLER
@@ -491,6 +511,8 @@ config SOC_IMX6
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
select MFD_SYSCON
+ select HAVE_ARM_SCU if SMP
+ select HAVE_ARM_TWD if SMP
select PL310_ERRATA_769419 if CACHE_L2X0
config SOC_IMX6Q
@@ -498,14 +520,17 @@ config SOC_IMX6Q
select ARM_ERRATA_764369 if SMP
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD
+ select PCI_DOMAINS if PCI
select PINCTRL_IMX6Q
select SOC_IMX6
+ select MXC_MLB150
help
This enables support for Freescale i.MX6 Quad processor.
config SOC_IMX6SL
bool "i.MX6 SoloLite support"
+ select HAVE_IMX_RNG
select PINCTRL_IMX6SL
select SOC_IMX6
@@ -515,7 +540,14 @@ config SOC_IMX6SL
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 RPMSG
+ select IMX_SEMA4
+ select MXC_MLB150
+ select KEYBOARD_SNVS_PWRKEY
help
This enables support for Freescale i.MX6 SoloX processor.
@@ -524,18 +556,41 @@ config SOC_IMX6UL
bool "i.MX6 UltraLite support"
select PINCTRL_IMX6UL
select SOC_IMX6
+ select KEYBOARD_SNVS_PWRKEY
+ select ARM_ERRATA_814220
help
This enables support for Freescale i.MX6 UltraLite processor.
+config SOC_IMX6ULL
+ bool "i.MX6 ULL support"
+ select SOC_IMX6UL
+
+ help
+ This enables support for Freescale i.MX6 ULL processor.
+
+config SOC_IMX7
+ bool
+ select CPU_V7
+ select ARM_GIC
+ select HAVE_IMX_MU
+ select HAVE_IMX_RPMSG
+ select RPMSG
+
config SOC_IMX7D
bool "i.MX7 Dual support"
+ select SOC_IMX7
+ select PCI_DOMAINS if PCI
select PINCTRL_IMX7D
- select ARM_GIC
select HAVE_ARM_ARCH_TIMER
select HAVE_IMX_ANATOP
select HAVE_IMX_MMDC
+ select HAVE_IMX_DDRC
select HAVE_IMX_SRC
+ select KEYBOARD_SNVS_PWRKEY
+ select HAVE_IMX_GPCV2
+ select ARM_ERRATA_814220
+
help
This enables support for Freescale i.MX7 Dual processor.
@@ -553,6 +608,23 @@ comment "Cortex-A/Cortex-M asymmetric multiprocessing platforms"
if ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M
+config SOC_IMX6SLL
+ bool "i.MX6 SLL support"
+ select PINCTRL_IMX6SLL
+ select SOC_IMX6
+ select KEYBOARD_SNVS_PWRKEY
+
+ help
+ This enables support for Freescale i.MX6 SLL processor.
+
+config SOC_IMX7ULP
+ bool "i.MX7ULP support"
+ select SOC_IMX7
+ select CLKSRC_IMX_TPM
+ select PINCTRL_IMX7ULP
+ help
+ This enables support for Freescale i.MX7 Ultra Low Power processor.
+
config SOC_VF610
bool "Vybrid Family VF610 support"
select ARM_GIC if ARCH_MULTI_V7
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index cab128913e72..5d43296bdbe4 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -1,4 +1,4 @@
-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,9 +25,19 @@ 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_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_imx6sx_low_power_idle.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o imx6sx_low_power_idle.o
+AFLAGS_imx6ul_low_power_idle.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6UL) += cpuidle-imx6ul.o imx6ul_low_power_idle.o
+AFLAGS_imx6ull_low_power_idle.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6ULL) += imx6ull_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
+AFLAGS_imx7d_low_power_idle.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX7D) += cpuidle-imx7d.o imx7d_low_power_idle.o
endif
ifdef CONFIG_SND_IMX_SOC
@@ -68,25 +78,50 @@ 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_DDRC) += ddrc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
-ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
+obj-$(CONFIG_HAVE_IMX_MU) += mu.o
+ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_IMX7)$(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_IMX6SX) += mach-imx6sx.o
-obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
+obj-y += busfreq_lpddr2.o busfreq-imx.o busfreq_ddr3.o
+AFLAGS_ddr3_freq_imx6.o :=-Wa,-march=armv7-a
+AFLAGS_smp_wfe_imx6.o :=-Wa,-march=armv7-a
+AFLAGS_lpddr2_freq_imx6q.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o ddr3_freq_imx6.o smp_wfe_imx6.o \
+ lpddr2_freq_imx6q.o
+AFLAGS_lpddr2_freq_imx6.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o lpddr2_freq_imx6.o
+AFLAGS_lpddr2_freq_imx6sll.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6SLL) += mach-imx6sl.o lpddr2_freq_imx6sll.o
+AFLAGS_ddr3_freq_imx6sx.o :=-Wa,-march=armv7-a
+AFLAGS_lpddr2_freq_imx6sx.o :=-Wa,-march=armv7-a
+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) += mach-imx7d.o
+obj-$(CONFIG_SOC_IMX7ULP) += mach-imx7ulp.o pm-imx7ulp.o pm-rpmsg.o
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_IMX7D) += suspend-imx7.o
obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
+obj-$(CONFIG_SOC_IMX7ULP) += suspend-imx7ulp.o
endif
obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
+AFLAGS_smp_wfe.o :=-Wa,-march=armv7-a
+AFLAGS_ddr3_freq_imx7d.o :=-Wa,-march=armv7-a
+AFLAGS_lpddr3_freq_imx.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX7D) += pm-imx7.o ddr3_freq_imx7d.o smp_wfe.o \
+ lpddr3_freq_imx.o
obj-$(CONFIG_SOC_IMX1) += mach-imx1.o
obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c
index 649a84c251ad..d46f68417bbb 100644
--- a/arch/arm/mach-imx/anatop.c
+++ b/arch/arm/mach-imx/anatop.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-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
@@ -9,6 +10,7 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -21,9 +23,17 @@
#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_ANA_MISC2 0x170
#define ANADIG_USB1_CHRG_DETECT 0x1b0
#define ANADIG_USB2_CHRG_DETECT 0x210
#define ANADIG_DIGPROG 0x260
@@ -33,24 +43,43 @@
#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_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);
}
@@ -68,35 +97,100 @@ 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_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)
+ 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);
+
+ if ((imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2 ||
+ imx_mmdc_get_ddr_type() == IMX_MMDC_DDR_TYPE_LPDDR3) &&
+ !imx_gpc_usb_wakeup_enabled() && !imx_gpc_enet_wakeup_enabled())
imx_anatop_enable_2p5_pulldown(true);
else
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_imx6sll())
imx_anatop_disconnect_high_snvs(true);
}
void imx_anatop_post_resume(void)
{
- if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
+ 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);
+
+ if ((imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2 ||
+ imx_mmdc_get_ddr_type() == IMX_MMDC_DDR_TYPE_LPDDR3) &&
+ !imx_gpc_usb_wakeup_enabled() && !imx_gpc_enet_wakeup_enabled())
imx_anatop_enable_2p5_pulldown(false);
else
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_imx6sll())
imx_anatop_disconnect_high_snvs(false);
-
}
static void imx_anatop_usb_chrg_detect_disable(void)
@@ -116,6 +210,7 @@ void __init imx_init_revision_from_anatop(void)
unsigned int revision;
u32 digprog;
u16 offset = ANADIG_DIGPROG;
+ u16 major_part, minor_part;
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
anatop_base = of_iomap(np, 0);
@@ -127,45 +222,25 @@ void __init imx_init_revision_from_anatop(void)
digprog = readl_relaxed(anatop_base + offset);
iounmap(anatop_base);
- switch (digprog & 0xff) {
- case 0:
- /*
- * For i.MX6QP, most of the code for i.MX6Q can be resued,
- * so internally, we identify it as i.MX6Q Rev 2.0
- */
- if (digprog >> 8 & 0x01)
- revision = IMX_CHIP_REVISION_2_0;
- else
- revision = IMX_CHIP_REVISION_1_0;
- break;
- case 1:
- revision = IMX_CHIP_REVISION_1_1;
- break;
- case 2:
- revision = IMX_CHIP_REVISION_1_2;
- break;
- case 3:
- revision = IMX_CHIP_REVISION_1_3;
- break;
- case 4:
- revision = IMX_CHIP_REVISION_1_4;
- break;
- case 5:
- /*
- * i.MX6DQ TO1.5 is defined as Rev 1.3 in Data Sheet, marked
- * as 'D' in Part Number last character.
- */
- revision = IMX_CHIP_REVISION_1_5;
- break;
- default:
+ /*
+ * On i.MX7D digprog value match linux version format, so
+ * it needn't map again and we can use register value directly.
+ */
+ if (of_device_is_compatible(np, "fsl,imx7d-anatop")) {
+ revision = digprog & 0xff;
+ } else {
/*
- * Fail back to return raw register value instead of 0xff.
- * It will be easy to know version information in SOC if it
- * can't be recognized by known version. And some chip's (i.MX7D)
- * digprog value match linux version format, so it needn't map
- * again and we can use register value directly.
+ * MAJOR: [15:8], the major silicon revison;
+ * MINOR: [7: 0], the minor silicon revison;
+ *
+ * please refer to the i.MX RM for the detailed
+ * silicon revison bit define.
+ * format the major part and minor part to match the
+ * linux kernel soc version format.
*/
- revision = digprog & 0xff;
+ major_part = (digprog >> 8) & 0xf;
+ minor_part = digprog & 0xf;
+ revision = ((major_part + 1) << 4) | minor_part;
}
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..353795cec5f4
--- /dev/null
+++ b/arch/arm/mach-imx/busfreq-imx.c
@@ -0,0 +1,1369 @@
+/*
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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 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;
+static int origin_arm_volt, origin_soc_volt;
+
+extern unsigned long iram_tlb_phys_addr;
+extern int unsigned long iram_tlb_base_addr;
+
+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);
+
+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 *arm_clk;
+static struct clk *pll3_clk;
+static struct clk *step_clk;
+static struct clk *mmdc_clk;
+static struct clk *ocram_clk;
+static struct clk *pll1_clk;
+static struct clk *pll1_bypass_clk;
+static struct clk *pll1_bypass_src_clk;
+static struct clk *pll1_sys_clk;
+static struct clk *pll1_sw_clk;
+static struct clk *pll2_bypass_src_clk;
+static struct clk *pll2_bypass_clk;
+static struct clk *pll2_clk;
+static struct clk *pll2_400_clk;
+static struct clk *pll2_200_clk;
+static struct clk *pll2_bus_clk;
+static struct clk *periph_clk;
+static struct clk *periph_pre_clk;
+static struct clk *periph_clk2_clk;
+static struct clk *periph_clk2_sel_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 clk *axi_alt_sel_clk;
+static struct clk *pll3_pfd1_540m_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 int busfreq_notify(enum busfreq_event event)
+{
+ int ret;
+
+ 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)
+{
+ int ret;
+
+ if (enter) {
+ org_arm_rate = clk_get_rate(arm_clk);
+ origin_arm_volt = regulator_get_voltage(arm_reg);
+ origin_soc_volt = regulator_get_voltage(soc_reg);
+ }
+
+ 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);
+ if (cpu_is_imx6sll() && uart_from_osc) {
+ ret = regulator_set_voltage_tol(arm_reg, LOW_POWER_RUN_VOLTAGE, 0);
+ if (ret)
+ pr_err("set arm reg voltage failed\n");
+ ret = regulator_set_voltage_tol(soc_reg, LOW_POWER_RUN_VOLTAGE, 0);
+ if (ret)
+ pr_err("set soc reg voltage failed\n");
+ }
+ } else {
+ if (uart_from_osc) {
+ ret = regulator_set_voltage_tol(soc_reg, origin_soc_volt, 0);
+ if (ret)
+ pr_err("set soc reg voltage failed\n");
+ ret = regulator_set_voltage_tol(arm_reg, origin_arm_volt, 0);
+ if (ret)
+ pr_err("set arm reg voltage failed\n");
+ }
+ 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)
+ update_ddr_freq_imx6_up(LOW_AUDIO_CLK);
+ else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
+ ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
+ update_lpddr2_freq(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_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 {
+ if (ddr_type == IMX_DDR_TYPE_DDR3)
+ update_ddr_freq_imx6_up(LPAPM_CLK);
+ else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
+ ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
+ update_lpddr2_freq(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_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)
+ update_ddr_freq_imx_smp(LOW_AUDIO_CLK);
+ else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
+ update_lpddr2_freq_smp(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 {
+ if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
+ update_ddr_freq_imx_smp(LPAPM_CLK);
+ else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
+ update_lpddr2_freq_smp(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_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_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_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);
+
+ if (ddr_type == IMX_DDR_TYPE_DDR3)
+ update_ddr_freq_imx6_up(ddr_normal_rate);
+ else if (ddr_type == IMX_DDR_TYPE_LPDDR2 || ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
+ update_lpddr2_freq(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);
+ if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
+ update_ddr_freq_imx_smp(ddr_normal_rate);
+ else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
+ update_lpddr2_freq_smp(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. */
+ update_lpddr2_freq(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 (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. */
+ update_lpddr2_freq(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. */
+ update_lpddr2_freq(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)
+{
+ if (audio_bus_count) {
+ clk_prepare_enable(pfd0_392m);
+ update_ddr_freq_imx_smp(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 {
+ update_ddr_freq_imx_smp(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;
+ }
+}
+
+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);
+
+ update_ddr_freq_imx_smp(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_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 void reduce_bus_freq_handler(struct work_struct *work)
+{
+ mutex_lock(&bus_freq_mutex);
+
+ if (!cancel_reduce_bus_freq)
+ reduce_bus_freq();
+
+ 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;
+}
+
+static inline void cancel_low_bus_freq_handler(void)
+{
+ cancel_delayed_work(&low_bus_freq_handler);
+ cancel_reduce_bus_freq = true;
+}
+
+/*
+ * 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_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_imx6ul() || cpu_is_imx6sl() || cpu_is_imx6ull() ||
+ 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_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_imx6ull() || cpu_is_imx6sl() || 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(10000));
+
+ /*
+ * 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");
+ }
+ err = init_ddrc_ddr_settings(pdev);
+ } else if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
+ cpu_is_imx6sll()) {
+ ddr_type = imx_mmdc_get_ddr_type();
+ if (ddr_type == IMX_DDR_TYPE_DDR3)
+ err = init_mmdc_ddr3_settings_imx6_up(pdev);
+ else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
+ ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
+ err = init_mmdc_lpddr2_settings(pdev);
+ } else if (cpu_is_imx6q() || cpu_is_imx6dl()) {
+ ddr_type = imx_mmdc_get_ddr_type();
+ if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
+ err = init_mmdc_ddr3_settings_imx6_smp(pdev);
+ else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
+ err = init_mmdc_lpddr2_settings_mx6q(pdev);
+ } else if (cpu_is_imx6sl()) {
+ err = init_mmdc_lpddr2_settings(pdev);
+ }
+
+ 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;
+
+ printk(KERN_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..3a016f15d5bb
--- /dev/null
+++ b/arch/arm/mach-imx/busfreq_ddr3.c
@@ -0,0 +1,773 @@
+/*
+ * 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 *imx_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(imx_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(imx_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(imx_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())
+ 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()) {
+ 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..2ef1806bbc35
--- /dev/null
+++ b/arch/arm/mach-imx/busfreq_lpddr2.c
@@ -0,0 +1,373 @@
+/*
+ * 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 *imx_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())
+ 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(imx_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(imx_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(imx_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..3016f60ce141
--- /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_IMX6SL)
+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 c4436d9c52ff..b38a54e2b280 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -1,5 +1,6 @@
/*
- * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
*/
/*
@@ -12,11 +13,13 @@
#define __ASM_ARCH_MXC_COMMON_H__
#include <linux/reboot.h>
+#include <soc/imx/src.h>
struct irq_data;
struct platform_device;
struct pt_regs;
struct clk;
+struct clk_hw;
struct device_node;
enum mxc_cpu_pwr_mode;
struct of_device_id;
@@ -63,6 +66,28 @@ 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 imx25_pm_init(void);
void imx27_pm_init(void);
+unsigned int imx_gpc_is_mf_mix_off(void);
+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
+void imx_gpc_hold_m4_in_sleep(void);
+void imx_gpc_release_m4_in_sleep(void);
+void mcc_receive_from_mu_buffer(unsigned int index, unsigned int *data);
+void mcc_send_via_mu_buffer(unsigned int index, unsigned int data);
+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);
+#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 */
@@ -79,6 +104,17 @@ enum mx3_cpu_pwr_mode {
MX3_SLEEP,
};
+enum imx7ulp_cpu_pwr_mode {
+ HSRUN,
+ RUN,
+ VLPR,
+ WAIT,
+ VLPW,
+ STOP,
+ VLPS,
+ VLLS,
+};
+
void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
void imx_enable_cpu(int cpu, bool enable);
@@ -93,9 +129,35 @@ void imx_smp_prepare(void);
static inline void imx_scu_map_io(void) {}
static inline void imx_smp_prepare(void) {}
#endif
+void imx6_pm_map_io(void);
+void imx7_pm_map_io(void);
+void imx7ulp_pm_map_io(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);
+unsigned int imx_gpc_is_mf_mix_off(void);
+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);
+int imx_gpc_mf_power_on(unsigned int irq, unsigned int on);
+#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 __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);
+unsigned long save_ttbr1(void);
+void restore_ttbr1(unsigned long ttbr1);
void imx_gpc_mask_all(void);
void imx_gpc_restore_all(void);
void imx_gpc_hwirq_mask(unsigned int hwirq);
@@ -106,22 +168,52 @@ 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);
+int imx7ulp_set_lpm(enum imx7ulp_cpu_pwr_mode mode);
+#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
+#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 imx_cpu_die(unsigned int cpu);
int imx_cpu_kill(unsigned int cpu);
+void imx_busfreq_map_io(void);
+void imx7d_low_power_idle(void);
+void imx6sx_low_power_idle(void);
+void imx6ul_low_power_idle(void);
+void imx6ull_low_power_idle(void);
+void imx6sl_low_power_idle(void);
+void imx6sll_low_power_idle(void);
+bool imx_gpc_usb_wakeup_enabled(void);
+bool imx_gpc_enet_wakeup_enabled(void);
#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 imx7ulp_cpu_resume(void);
void imx6_suspend(void __iomem *ocram_vbase);
+void imx7_suspend(void __iomem *ocram_vbase);
+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 imx7ulp_cpu_resume(void) {}
static inline void imx6_suspend(void __iomem *ocram_vbase) {}
+static inline void imx7_suspend(void __iomem *ocram_vbase) {}
+static inline void imx7ulp_suspend(void __iomem *ocram_vbase) {}
#endif
+void pm_shutdown_notify_m4(void);
void imx6_pm_ccm_init(const char *ccm_compat);
void imx6q_pm_init(void);
@@ -129,6 +221,11 @@ void imx6dl_pm_init(void);
void imx6sl_pm_init(void);
void imx6sx_pm_init(void);
void imx6ul_pm_init(void);
+void imx6ull_pm_init(void);
+void imx7d_pm_init(void);
+void imx7ulp_pm_init(void);
+void imx7ulp_enable_nmi(void);
+void imx6q_pm_set_ccm_base(void __iomem *base);
#ifdef CONFIG_PM
void imx51_pm_init(void);
@@ -153,4 +250,6 @@ 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 b3347d32349f..a02b47a0be36 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -126,14 +126,26 @@ struct device * __init imx_soc_device_init(void)
soc_id = "i.MX6SX";
break;
case MXC_CPU_IMX6Q:
- soc_id = "i.MX6Q";
+ if (imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
+ soc_id = "i.MX6QP";
+ else
+ soc_id = "i.MX6Q";
break;
case MXC_CPU_IMX6UL:
soc_id = "i.MX6UL";
break;
+ case MXC_CPU_IMX6ULL:
+ soc_id = "i.MX6ULL";
+ break;
case MXC_CPU_IMX7D:
soc_id = "i.MX7D";
break;
+ case MXC_CPU_IMX6SLL:
+ soc_id = "i.MX6SLL";
+ break;
+ case MXC_CPU_IMX7ULP:
+ soc_id = "i.MX7ULP";
+ break;
default:
soc_id = "Unknown";
}
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index bfeb25aaf9a2..02d55ae7e0eb 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012, 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
@@ -30,6 +30,8 @@ static int imx6q_enter_wait(struct cpuidle_device *dev,
if (!spin_trylock(&master_lock))
goto idle;
imx6_set_lpm(WAIT_UNCLOCKED);
+ if (atomic_read(&master) != num_online_cpus())
+ imx6_set_lpm(WAIT_CLOCKED);
cpu_do_idle();
imx6_set_lpm(WAIT_CLOCKED);
spin_unlock(&master_lock);
@@ -41,6 +43,7 @@ idle:
done:
atomic_dec(&master);
+ imx6_set_lpm(WAIT_CLOCKED);
return index;
}
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
index 8d866fb674a8..21ecebf699aa 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sl.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -1,29 +1,86 @@
/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * 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 <linux/busfreq-imx.h>
#include <linux/cpuidle.h>
#include <linux/module.h>
+#include <linux/platform_device.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 "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);
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)) {
+ 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;
@@ -51,5 +108,108 @@ 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..65d82e5855e2
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6sll.c
@@ -0,0 +1,264 @@
+/*
+ * 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 <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/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 "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);
+
+static int imx6sll_idle_finish(unsigned long val)
+{
+ 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 c5a5c3a70ab1..be73709ebce5 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sx.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sx.c
@@ -1,22 +1,92 @@
/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * 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 <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 <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 "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);
+
+static int imx6_idle_finish(unsigned long val)
{
/*
* for Cortex-A7 which has an internal L2
@@ -27,7 +97,7 @@ static int imx6sx_idle_finish(unsigned long val)
* just call flush_cache_all() is fine.
*/
flush_cache_all();
- cpu_do_idle();
+ imx6sx_wfi_in_iram_fn(wfi_iram_base);
return 0;
}
@@ -35,29 +105,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);
@@ -71,24 +134,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,
+ .exit_latency = 800,
+ .target_residency = 1000,
.enter = imx6sx_enter_wait,
.name = "LOW-POWER-IDLE",
.desc = "ARM power off",
@@ -100,16 +162,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);
- /*
- * 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(2, 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..7708d878615c
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6ul.c
@@ -0,0 +1,315 @@
+/*
+ * 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/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 "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);
+
+static int imx6ul_idle_finish(unsigned long val)
+{
+ 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..36ad21a33dfa
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx7d.c
@@ -0,0 +1,356 @@
+/*
+ * 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 <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 "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_wait = ATOMIC_INIT(0);
+
+static void (*imx7d_wfi_in_iram_fn)(void __iomem *iram_vbase);
+static struct imx7_cpuidle_pm_info *cpuidle_pm_info;
+
+/* 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)
+{
+ 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 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 {
+ imx_pen_lock(dev->cpu);
+ ++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,
+};
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int cpu_hotplug_notify(struct notifier_block *self,
+ unsigned long action, void *hcpu)
+{
+ switch (action) {
+ case CPU_DEAD:
+ case CPU_ONLINE:
+ cpuidle_pm_info->num_online_cpus = num_online_cpus();
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata cpu_hotplug_notifier = {
+ .notifier_call = cpu_hotplug_notify,
+};
+#endif
+
+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();
+
+#ifdef CONFIG_HOTPLUG_CPU
+ register_hotcpu_notifier(&cpu_hotplug_notifier);
+#endif
+ /* code size should include cpuidle_pm_info size */
+ 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-imx7ulp.c b/arch/arm/mach-imx/cpuidle-imx7ulp.c
new file mode 100644
index 000000000000..924a19c16321
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx7ulp.c
@@ -0,0 +1,62 @@
+/*
+ * 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 <linux/cpuidle.h>
+#include <linux/module.h>
+#include <asm/cpuidle.h>
+
+#include "common.h"
+#include "cpuidle.h"
+#include "hardware.h"
+
+static int imx7ulp_enter_wait(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ if (index == 1)
+ imx7ulp_set_lpm(WAIT);
+ else
+ imx7ulp_set_lpm(STOP);
+
+ cpu_do_idle();
+
+ imx7ulp_set_lpm(RUN);
+
+ return index;
+}
+
+static struct cpuidle_driver imx7ulp_cpuidle_driver = {
+ .name = "imx7ulp_cpuidle",
+ .owner = THIS_MODULE,
+ .states = {
+ /* WFI */
+ ARM_CPUIDLE_WFI_STATE,
+ /* WAIT */
+ {
+ .exit_latency = 50,
+ .target_residency = 75,
+ .enter = imx7ulp_enter_wait,
+ .name = "WAIT",
+ .desc = "PSTOP2",
+ },
+ /* STOP */
+ {
+ .exit_latency = 100,
+ .target_residency = 150,
+ .enter = imx7ulp_enter_wait,
+ .name = "STOP",
+ .desc = "PSTOP1",
+ },
+ },
+ .state_count = 3,
+ .safe_state_index = 0,
+};
+
+int __init imx7ulp_cpuidle_init(void)
+{
+ return cpuidle_register(&imx7ulp_cpuidle_driver, NULL);
+}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index f9140128ba05..14eeb339e76b 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2016 Freescale Semiconductor, Inc.
* Copyright 2012 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -14,7 +14,12 @@
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)
{
@@ -28,8 +33,28 @@ 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;
+}
#endif
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..2a12669a3bef
--- /dev/null
+++ b/arch/arm/mach-imx/ddr3_freq_imx6.S
@@ -0,0 +1,1079 @@
+/*
+ * 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 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]
+
+ /* Disable L2. */
+ str r1, [r12, #0x100]
+
+ dsb
+ isb
+#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
+ /* Enable L2. */
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ ldr r6, =0x1
+ str r6, [r7, #0x100]
+ 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..9846c05f4541
--- /dev/null
+++ b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
@@ -0,0 +1,737 @@
+/*
+ * 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 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]
+
+ /* Disable L2. */
+ mov r7, #0x0
+ str r7, [r8, #0x100]
+
+ /*
+ * 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
+ /* Enable L2. */
+ ldr r8, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ ldr r7, =0x1
+ str r7, [r8, #0x100]
+#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 b54db47f6f32..551ecd0f2a4f 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -1,6 +1,7 @@
/*
- * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ * Copyright 2011-2016 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
+ * 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
@@ -26,7 +27,13 @@
#include "hardware.h"
#define GPC_CNTR 0x000
+#define GPC_CNTR_PCIE_PHY_PDU_SHIFT 0x7
+#define GPC_CNTR_PCIE_PHY_PDN_SHIFT 0x6
+#define GPC_CNTR_L2_PGE 22
+#define PGC_PCIE_PHY_CTRL 0x200
+#define PGC_PCIE_PHY_PDN_EN 0x1
#define GPC_IMR1 0x008
+#define GPC_PGC_MF_PDN 0x220
#define GPC_PGC_GPU_PDN 0x260
#define GPC_PGC_GPU_PUPSCR 0x264
#define GPC_PGC_GPU_PDNSCR 0x268
@@ -35,6 +42,22 @@
#define GPC_PGC_CPU_PDNSCR 0x2a8
#define GPC_PGC_SW2ISO_SHIFT 0x8
#define GPC_PGC_SW_SHIFT 0x0
+#define GPC_PGC_DISP_PGCR_OFFSET 0x240
+#define GPC_PGC_DISP_PUPSCR_OFFSET 0x244
+#define GPC_PGC_DISP_PDNSCR_OFFSET 0x248
+#define GPC_PGC_DISP_SR_OFFSET 0x24c
+#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)
@@ -42,7 +65,15 @@
#define GPU_VPU_PUP_REQ BIT(1)
#define GPU_VPU_PDN_REQ BIT(0)
-#define GPC_CLK_MAX 6
+#define GPC_CLK_MAX 10
+#define DEFAULT_IPG_RATE 66000000
+#define GPC_PU_UP_DELAY_MARGIN 2
+
+/* 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
struct pu_domain {
struct generic_pm_domain base;
@@ -51,9 +82,133 @@ struct pu_domain {
int num_clks;
};
+struct disp_domain {
+ struct generic_pm_domain base;
+ struct clk *clk[GPC_CLK_MAX];
+ int num_clks;
+};
+
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);
+static struct notifier_block nb_pcie;
+static struct pu_domain imx6q_pu_domain;
+static bool pu_on; /* keep always on i.mx6qp */
+static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd);
+static void _imx6q_pm_pu_power_on(struct generic_pm_domain *genpd);
+static struct clk *ipg;
+
+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_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)
{
@@ -77,6 +232,14 @@ void imx_gpc_pre_suspend(bool arm_power_off)
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
+ if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
+ _imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
+
+ /* power down the mega-fast power domain */
+ if ((cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull()
+ || 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);
@@ -92,8 +255,15 @@ void imx_gpc_post_resume(void)
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
+ if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
+ _imx6q_pm_pu_power_on(&imx6q_pu_domain.base);
+
/* 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_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);
@@ -102,11 +272,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
@@ -238,11 +411,102 @@ 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_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 imx_pcie_regulator_notify(struct notifier_block *nb,
+ unsigned long event,
+ void *ignored)
+{
+ u32 value = readl_relaxed(gpc_base + GPC_CNTR);
+
+ switch (event) {
+ case REGULATOR_EVENT_PRE_DO_ENABLE:
+ value |= 1 << GPC_CNTR_PCIE_PHY_PDU_SHIFT;
+ writel_relaxed(value, gpc_base + GPC_CNTR);
+ break;
+ case REGULATOR_EVENT_PRE_DO_DISABLE:
+ value |= 1 << GPC_CNTR_PCIE_PHY_PDN_SHIFT;
+ writel_relaxed(value, gpc_base + GPC_CNTR);
+ writel_relaxed(PGC_PCIE_PHY_PDN_EN,
+ gpc_base + PGC_PCIE_PHY_CTRL);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
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("%s: no parent, giving up\n", node->full_name);
@@ -271,12 +535,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_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);
@@ -317,12 +639,19 @@ static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
/* Wait ISO + ISO2SW IPG clock cycles */
ndelay((iso + iso2sw) * 1000 / 66);
+
+ while (readl_relaxed(gpc_base + GPC_CNTR) & GPU_VPU_PDN_REQ)
+ ;
}
static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
{
struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
+ if (&imx6q_pu_domain == pu && pu_on && cpu_is_imx6q() &&
+ imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
+ return 0;
+
_imx6q_pm_pu_power_off(genpd);
if (pu->reg)
@@ -331,18 +660,11 @@ static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
return 0;
}
-static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
+static void _imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
{
struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
- int i, ret, sw, sw2iso;
- u32 val;
-
- if (pu->reg)
- ret = regulator_enable(pu->reg);
- if (pu->reg && ret) {
- pr_err("%s: failed to enable regulator: %d\n", __func__, ret);
- return ret;
- }
+ int i;
+ u32 val, ipg_rate = clk_get_rate(ipg);
/* Enable reset clocks for all devices in the PU domain */
for (i = 0; i < pu->num_clks; i++)
@@ -351,26 +673,108 @@ static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
/* Gate off PU domain when GPU/VPU when powered down */
writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
- /* Read ISO and ISO2SW power down delays */
- val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR);
- sw = val & 0x3f;
- sw2iso = (val >> 8) & 0x3f;
-
/* Request GPC to power up GPU/VPU */
val = readl_relaxed(gpc_base + GPC_CNTR);
val |= GPU_VPU_PUP_REQ;
writel_relaxed(val, gpc_base + GPC_CNTR);
- /* Wait ISO + ISO2SW IPG clock cycles */
- ndelay((sw + sw2iso) * 1000 / 66);
+ while (readl_relaxed(gpc_base + GPC_CNTR) & GPU_VPU_PUP_REQ)
+ ;
+ /* Wait power switch done */
+ udelay(2 * DEFAULT_IPG_RATE / ipg_rate +
+ GPC_PU_UP_DELAY_MARGIN);
/* Disable reset clocks for all devices in the PU domain */
for (i = 0; i < pu->num_clks; i++)
clk_disable_unprepare(pu->clk[i]);
+}
+
+static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
+{
+ struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
+ int ret;
+
+ if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0
+ && &imx6q_pu_domain == pu) {
+ if (!pu_on)
+ pu_on = true;
+ else
+ return 0;
+ }
+
+ if (pu->reg)
+ ret = regulator_enable(pu->reg);
+ if (pu->reg && ret) {
+ pr_err("%s: failed to enable regulator: %d\n", __func__, ret);
+ return ret;
+ }
+
+ _imx6q_pm_pu_power_on(genpd);
return 0;
}
+static int imx_pm_dispmix_on(struct generic_pm_domain *genpd)
+{
+ struct disp_domain *disp = container_of(genpd, struct disp_domain, base);
+ u32 val = readl_relaxed(gpc_base + GPC_CNTR);
+ int i;
+ u32 ipg_rate = clk_get_rate(ipg);
+
+ if ((cpu_is_imx6sl() &&
+ imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) || cpu_is_imx6sx()) {
+
+ /* Enable reset clocks for all devices in the disp domain */
+ for (i = 0; i < disp->num_clks; i++)
+ clk_prepare_enable(disp->clk[i]);
+
+ writel_relaxed(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+ writel_relaxed(0x20 | val, gpc_base + GPC_CNTR);
+ while (readl_relaxed(gpc_base + GPC_CNTR) & 0x20)
+ ;
+
+ writel_relaxed(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET);
+
+ /* Wait power switch done */
+ udelay(2 * DEFAULT_IPG_RATE / ipg_rate +
+ GPC_PU_UP_DELAY_MARGIN);
+
+ /* Disable reset clocks for all devices in the disp domain */
+ for (i = 0; i < disp->num_clks; i++)
+ clk_disable_unprepare(disp->clk[i]);
+ }
+ return 0;
+}
+
+static int imx_pm_dispmix_off(struct generic_pm_domain *genpd)
+{
+ struct disp_domain *disp = container_of(genpd, struct disp_domain, base);
+ u32 val = readl_relaxed(gpc_base + GPC_CNTR);
+ int i;
+
+ if ((cpu_is_imx6sl() &&
+ imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) || cpu_is_imx6sx()) {
+
+ /* Enable reset clocks for all devices in the disp domain */
+ for (i = 0; i < disp->num_clks; i++)
+ clk_prepare_enable(disp->clk[i]);
+
+ writel_relaxed(0xFFFFFFFF,
+ gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET);
+ writel_relaxed(0xFFFFFFFF,
+ gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET);
+ writel_relaxed(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+ writel_relaxed(0x10 | val, gpc_base + GPC_CNTR);
+ while (readl_relaxed(gpc_base + GPC_CNTR) & 0x10)
+ ;
+
+ /* Disable reset clocks for all devices in the disp domain */
+ for (i = 0; i < disp->num_clks; i++)
+ clk_disable_unprepare(disp->clk[i]);
+ }
+ return 0;
+}
+
static struct generic_pm_domain imx6q_arm_domain = {
.name = "ARM",
};
@@ -390,14 +794,18 @@ static struct pu_domain imx6q_pu_domain = {
},
};
-static struct generic_pm_domain imx6sl_display_domain = {
- .name = "DISPLAY",
+static struct disp_domain imx6s_display_domain = {
+ .base = {
+ .name = "DISPLAY",
+ .power_off = imx_pm_dispmix_off,
+ .power_on = imx_pm_dispmix_on,
+ },
};
static struct generic_pm_domain *imx_gpc_domains[] = {
&imx6q_arm_domain,
&imx6q_pu_domain.base,
- &imx6sl_display_domain,
+ &imx6s_display_domain.base,
};
static struct genpd_onecell_data imx_gpc_onecell_data = {
@@ -408,30 +816,59 @@ static struct genpd_onecell_data imx_gpc_onecell_data = {
static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
{
struct clk *clk;
- int i, ret;
+ bool is_off;
+ int pu_clks, disp_clks, ipg_clks = 1;
+ int i = 0, k = 0, ret;
imx6q_pu_domain.reg = pu_reg;
- for (i = 0; ; i++) {
+ if ((cpu_is_imx6sl() &&
+ imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2)) {
+ pu_clks = 2 ;
+ disp_clks = 5;
+ } else if (cpu_is_imx6sx()) {
+ pu_clks = 1;
+ disp_clks = 7;
+ } else {
+ pu_clks = 6;
+ disp_clks = 0;
+ }
+
+ /* Get pu domain clks */
+ for (i = 0; i < pu_clks ; i++) {
clk = of_clk_get(dev->of_node, i);
if (IS_ERR(clk))
break;
- if (i >= GPC_CLK_MAX) {
- dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
- goto clk_err;
- }
imx6q_pu_domain.clk[i] = clk;
}
imx6q_pu_domain.num_clks = i;
- /* Enable power always in case bootloader disabled it. */
- imx6q_pm_pu_power_on(&imx6q_pu_domain.base);
+ ipg = of_clk_get(dev->of_node, pu_clks);
- if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
- return 0;
+ /* Get disp domain clks */
+ for (i = pu_clks + ipg_clks; i < pu_clks + ipg_clks + disp_clks;
+ i++) {
+ clk = of_clk_get(dev->of_node, i);
+ if (IS_ERR(clk))
+ break;
+ imx6s_display_domain.clk[k++] = clk;
+ }
+ imx6s_display_domain.num_clks = k;
+
+ is_off = IS_ENABLED(CONFIG_PM);
+ if (is_off && !(cpu_is_imx6q() &&
+ imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)) {
+ _imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
+ } else {
+ /*
+ * Enable power if compiled without CONFIG_PM in case the
+ * bootloader disabled it.
+ */
+ imx6q_pm_pu_power_on(&imx6q_pu_domain.base);
+ }
for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
- pm_genpd_init(imx_gpc_domains[i], NULL, false);
+ pm_genpd_init(imx_gpc_domains[i], NULL, is_off);
ret = of_genpd_add_provider_onecell(dev->of_node,
&imx_gpc_onecell_data);
@@ -442,10 +879,6 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
power_off:
imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
-clk_err:
- while (i--)
- clk_put(imx6q_pu_domain.clk[i]);
- imx6q_pu_domain.reg = NULL;
return -EINVAL;
}
@@ -453,6 +886,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
{
struct regulator *pu_reg;
int ret;
+ u32 bypass = 0;
/* bail out if DT too old and doesn't provide the necessary info */
if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells"))
@@ -463,11 +897,46 @@ static int imx_gpc_probe(struct platform_device *pdev)
pu_reg = NULL;
if (IS_ERR(pu_reg)) {
ret = PTR_ERR(pu_reg);
- dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret);
+ if (ret == -EPROBE_DEFER)
+ dev_warn(&pdev->dev, "pu regulator not ready, retry\n");
+ else
+ dev_err(&pdev->dev, "failed to get pu regulator: %d\n",
+ ret);
return ret;
}
- return imx_gpc_genpd_init(&pdev->dev, pu_reg);
+ if (of_property_read_u32(pdev->dev.of_node, "fsl,ldo-bypass", &bypass))
+ dev_warn(&pdev->dev,
+ "no fsl,ldo-bypass found!\n");
+ /* We only bypass pu since arm and soc has been set in u-boot */
+ if (pu_reg && bypass)
+ regulator_allow_bypass(pu_reg, true);
+
+ if (cpu_is_imx6sx()) {
+ struct regulator *pcie_reg;
+
+ pcie_reg = devm_regulator_get(&pdev->dev, "pcie-phy");
+ if (IS_ERR(pcie_reg)) {
+ ret = PTR_ERR(pcie_reg);
+ dev_info(&pdev->dev, "pcie regulator not ready.\n");
+ return ret;
+ }
+ nb_pcie.notifier_call = &imx_pcie_regulator_notify;
+
+ ret = regulator_register_notifier(pcie_reg, &nb_pcie);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "pcie regulator notifier request failed\n");
+ return ret;
+ }
+ }
+
+ ret = imx_gpc_genpd_init(&pdev->dev, pu_reg);
+ if (ret)
+ return ret;
+ dev_info(&pdev->dev, "Registered imx-gpc\n");
+
+ return 0;
}
static const struct of_device_id imx_gpc_dt_ids[] = {
diff --git a/arch/arm/mach-imx/gpcv2.c b/arch/arm/mach-imx/gpcv2.c
new file mode 100644
index 000000000000..60070e57633a
--- /dev/null
+++ b/arch/arm/mach-imx/gpcv2.c
@@ -0,0 +1,1052 @@
+/*
+ * 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 GPC_PGC_MIPI_PHY 0xc00
+#define GPC_PGC_PCIE_PHY 0xc40
+#define GPC_PGC_USB_OTG1_PHY 0xc80
+#define GPC_PGC_USB_OTG2_PHY 0xcc0
+#define GPC_PGC_USB_HSIC_PHY 0xd00
+
+#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);
+static struct notifier_block nb_mipi, nb_pcie, nb_usb_hsic;
+
+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 imx_usb_hsic_regulator_notify(struct notifier_block *nb,
+ unsigned long event,
+ void *ignored)
+{
+ u32 val = 0;
+
+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_MAPPING);
+ writel_relaxed(val | BIT(6), gpc_base + GPC_PGC_CPU_MAPPING);
+
+ switch (event) {
+ case REGULATOR_EVENT_PRE_DO_ENABLE:
+ val = readl_relaxed(gpc_base + GPC_PU_PGC_SW_PUP_REQ);
+ writel_relaxed(val | BIT(4), gpc_base + GPC_PU_PGC_SW_PUP_REQ);
+ while (readl_relaxed(gpc_base + GPC_PU_PGC_SW_PUP_REQ) & BIT(4))
+ ;
+ break;
+ case REGULATOR_EVENT_PRE_DO_DISABLE:
+ /* only disable phy need to set PGC bit, enable does NOT need */
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_USB_HSIC_PHY);
+ val = readl_relaxed(gpc_base + GPC_PU_PGC_SW_PDN_REQ);
+ writel_relaxed(val | BIT(4), gpc_base + GPC_PU_PGC_SW_PDN_REQ);
+ while (readl_relaxed(gpc_base + GPC_PU_PGC_SW_PDN_REQ) & BIT(4))
+ ;
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_USB_HSIC_PHY);
+ break;
+ default:
+ break;
+ }
+
+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_MAPPING);
+ writel_relaxed(val & ~BIT(6), gpc_base + GPC_PGC_CPU_MAPPING);
+
+ return NOTIFY_OK;
+}
+
+static int imx_mipi_regulator_notify(struct notifier_block *nb,
+ unsigned long event,
+ void *ignored)
+{
+ u32 val = 0;
+
+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_MAPPING);
+ writel_relaxed(val | BIT(2), gpc_base + GPC_PGC_CPU_MAPPING);
+
+ switch (event) {
+ case REGULATOR_EVENT_AFT_DO_ENABLE:
+ /*
+ * For imx7d pcie phy, VDD18 turn on time has to wait
+ * at least 0.1 .s after VDD10 turns on.
+ */
+ udelay(1);
+ val = readl_relaxed(gpc_base + GPC_PU_PGC_SW_PUP_REQ);
+ writel_relaxed(val | BIT(0), gpc_base + GPC_PU_PGC_SW_PUP_REQ);
+ while (readl_relaxed(gpc_base + GPC_PU_PGC_SW_PUP_REQ) & BIT(0))
+ ;
+ break;
+ case REGULATOR_EVENT_PRE_DO_DISABLE:
+ /* only disable phy need to set PGC bit, enable does NOT need */
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_MIPI_PHY);
+ val = readl_relaxed(gpc_base + GPC_PU_PGC_SW_PDN_REQ);
+ writel_relaxed(val | BIT(0), gpc_base + GPC_PU_PGC_SW_PDN_REQ);
+ while (readl_relaxed(gpc_base + GPC_PU_PGC_SW_PDN_REQ) & BIT(0))
+ ;
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_MIPI_PHY);
+ /*
+ * For imx7d pcie phy, VDD18 turn off time has to advance
+ * at least 0.1 .s before VDD10 turns off.
+ */
+ udelay(1);
+ break;
+ default:
+ break;
+ }
+
+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_MAPPING);
+ writel_relaxed(val & ~BIT(2), gpc_base + GPC_PGC_CPU_MAPPING);
+
+ return NOTIFY_OK;
+}
+
+static int imx_pcie_regulator_notify(struct notifier_block *nb,
+ unsigned long event,
+ void *ignored)
+{
+ u32 val = 0;
+
+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_MAPPING);
+ writel_relaxed(val | BIT(3), gpc_base + GPC_PGC_CPU_MAPPING);
+
+ switch (event) {
+ case REGULATOR_EVENT_AFT_DO_ENABLE:
+ /*
+ * For imx7d pcie phy, VDD18 turn on time has to wait
+ * at least 0.1 .s after VDD10 turns on.
+ */
+ udelay(1);
+ val = readl_relaxed(gpc_base + GPC_PU_PGC_SW_PUP_REQ);
+ writel_relaxed(val | BIT(1), gpc_base + GPC_PU_PGC_SW_PUP_REQ);
+ while (readl_relaxed(gpc_base + GPC_PU_PGC_SW_PUP_REQ) & BIT(1))
+ ;
+ break;
+ case REGULATOR_EVENT_PRE_DO_DISABLE:
+ /* only disable phy need to set PGC bit, enable does NOT need */
+ imx_gpcv2_set_m_core_pgc(true, GPC_PGC_PCIE_PHY);
+ val = readl_relaxed(gpc_base + GPC_PU_PGC_SW_PDN_REQ);
+ writel_relaxed(val | BIT(1), gpc_base + GPC_PU_PGC_SW_PDN_REQ);
+ while (readl_relaxed(gpc_base + GPC_PU_PGC_SW_PDN_REQ) & BIT(1))
+ ;
+ imx_gpcv2_set_m_core_pgc(false, GPC_PGC_PCIE_PHY);
+ /*
+ * For imx7d pcie phy, VDD18 turn off time has to advance
+ * at least 0.1 .s before VDD10 turns off.
+ */
+ udelay(1);
+ break;
+ default:
+ break;
+ }
+
+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_MAPPING);
+ writel_relaxed(val & ~BIT(3), gpc_base + GPC_PGC_CPU_MAPPING);
+
+ return NOTIFY_OK;
+}
+
+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);
+
+ 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);
+ }
+}
+
+static int imx_gpcv2_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct regulator *mipi_reg, *pcie_reg, *usb_hsic_reg;
+
+ if (cpu_is_imx7d()) {
+ mipi_reg = devm_regulator_get(&pdev->dev, "mipi-phy");
+ if (IS_ERR(mipi_reg)) {
+ ret = PTR_ERR(mipi_reg);
+ dev_info(&pdev->dev, "mipi regulator not ready.\n");
+ return ret;
+ }
+ nb_mipi.notifier_call = &imx_mipi_regulator_notify;
+
+ ret = regulator_register_notifier(mipi_reg, &nb_mipi);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "mipi regulator notifier request failed.\n");
+ return ret;
+ }
+ }
+
+ if (cpu_is_imx7d()) {
+ pcie_reg = devm_regulator_get(&pdev->dev, "pcie-phy");
+ if (IS_ERR(pcie_reg)) {
+ ret = PTR_ERR(pcie_reg);
+ dev_info(&pdev->dev, "pcie regulator not ready.\n");
+ return ret;
+ }
+ nb_pcie.notifier_call = &imx_pcie_regulator_notify;
+
+ ret = regulator_register_notifier(pcie_reg, &nb_pcie);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "pcie regulator notifier request failed\n");
+ return ret;
+ }
+
+ usb_hsic_reg = devm_regulator_get(&pdev->dev, "vcc");
+ if (IS_ERR(usb_hsic_reg)) {
+ ret = PTR_ERR(usb_hsic_reg);
+ dev_err(&pdev->dev, "usb hsic regulator not ready.\n");
+ return ret;
+ }
+ nb_usb_hsic.notifier_call = &imx_usb_hsic_regulator_notify;
+
+ ret = regulator_register_notifier(usb_hsic_reg, &nb_usb_hsic);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "usb hsic regulator notifier request failed\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static struct of_device_id imx_gpcv2_dt_ids[] = {
+ { .compatible = "fsl,imx7d-pgc" },
+ { }
+};
+
+static struct platform_driver imx_gpcv2_driver = {
+ .driver = {
+ .name = "imx-gpcv2",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_gpcv2_dt_ids,
+ },
+ .probe = imx_gpcv2_probe,
+};
+
+static int __init imx_pgcv2_init(void)
+{
+ return platform_driver_register(&imx_gpcv2_driver);
+}
+subsys_initcall(imx_pgcv2_init);
diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
index 90e10cbd8fd1..665c596a0b76 100644
--- a/arch/arm/mach-imx/hardware.h
+++ b/arch/arm/mach-imx/hardware.h
@@ -94,13 +94,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))
@@ -112,6 +115,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 6c28d28b3c64..5d6a5e2fe9ee 100644
--- a/arch/arm/mach-imx/headsmp.S
+++ b/arch/arm/mach-imx/headsmp.S
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -27,6 +27,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/hotplug.c b/arch/arm/mach-imx/hotplug.c
index b35e99cc5e5b..06dab2fc1c25 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -16,6 +16,7 @@
#include <asm/proc-fns.h>
#include "common.h"
+#include "hardware.h"
static inline void cpu_enter_lowpower(void)
{
@@ -66,5 +67,7 @@ int imx_cpu_kill(unsigned int cpu)
return 0;
imx_enable_cpu(cpu, false);
imx_set_cpu_arg(cpu, 0);
+ if (cpu_is_imx7d())
+ imx_gpcv2_set_core1_pdn_pup_by_software(true);
return 1;
}
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..1551d2ce1acf
--- /dev/null
+++ b/arch/arm/mach-imx/imx7d_low_power_idle.S
@@ -0,0 +1,787 @@
+/*
+ * 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..a7f387701bfa
--- /dev/null
+++ b/arch/arm/mach-imx/lpddr2_freq_imx6.S
@@ -0,0 +1,593 @@
+/*
+ * 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"
+
+.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
+
+ /* 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)
+
+ /* 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
+ /* 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 {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..edc115c6d72e
--- /dev/null
+++ b/arch/arm/mach-imx/lpddr2_freq_imx6sll.S
@@ -0,0 +1,436 @@
+/*
+ * 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 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
+
+ /* Disable L2. */
+ str r6, [r7, #0x100]
+#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
+ /* 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
+
+ /* 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..31555347b82f
--- /dev/null
+++ b/arch/arm/mach-imx/lpddr2_freq_imx6sx.S
@@ -0,0 +1,468 @@
+/*
+ * 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 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
+
+ /* Disable L2. */
+ str r6, [r7, #0x100]
+#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
+ /* Enable L2. */
+ ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
+ ldr r6, =0x1
+ str r6, [r7, #0x100]
+#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 45801b27ee5c..7b2462f7f598 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -1,6 +1,7 @@
/*
- * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ * Copyright 2011-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
+ * 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
@@ -31,6 +32,7 @@
#include <linux/micrel_phy.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/of_net.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/system_misc.h>
@@ -112,6 +114,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);
@@ -184,9 +198,7 @@ static void __init imx6q_1588_init(void)
{
struct device_node *np;
struct clk *ptp_clk;
- struct clk *enet_ref;
struct regmap *gpr;
- u32 clksel;
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec");
if (!np) {
@@ -200,35 +212,55 @@ static void __init imx6q_1588_init(void)
goto put_node;
}
- enet_ref = clk_get_sys(NULL, "enet_ref");
- if (IS_ERR(enet_ref)) {
- pr_warn("%s: failed to get enet clock\n", __func__);
- goto put_ptp_clk;
- }
-
/*
* If enet_ref from ANATOP/CCM is the PTP clock source, we need to
* set bit IOMUXC_GPR1[21]. Or the PTP clock must be from pad
* (external OSC), and we need to clear the bit.
*/
- clksel = clk_is_match(ptp_clk, enet_ref) ?
- IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
- IMX6Q_GPR1_ENET_CLK_SEL_PAD;
gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
if (!IS_ERR(gpr))
regmap_update_bits(gpr, IOMUXC_GPR1,
IMX6Q_GPR1_ENET_CLK_SEL_MASK,
- clksel);
+ IMX6Q_GPR1_ENET_CLK_SEL_ANATOP);
else
pr_err("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
- clk_put(enet_ref);
-put_ptp_clk:
clk_put(ptp_clk);
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_axi_init(void)
{
struct regmap *gpr;
@@ -262,11 +294,32 @@ static void __init imx6q_axi_init(void)
}
}
+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_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",
@@ -276,13 +329,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);
+ imx6q_enet_init();
imx_anatop_init();
+ imx6q_csi_mux_init();
cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
- imx6q_1588_init();
imx6q_axi_init();
}
@@ -334,6 +386,13 @@ static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
pr_warn("failed to disable 852 MHz OPP\n");
}
iounmap(base);
+
+ if (IS_ENABLED(CONFIG_MX6_VPU_352M)) {
+ if (dev_pm_opp_disable(cpu_dev, 396000000))
+ pr_warn("failed to disable 396MHz OPP\n");
+ pr_info("remove 396MHz OPP for VPU running at 352MHz!\n");
+ }
+
put_node:
of_node_put(np);
}
@@ -374,7 +433,9 @@ static void __init imx6q_init_late(void)
* WAIT mode is broken on TO 1.0 and 1.1, so there is no point
* to run cpuidle on them.
*/
- if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
+ if ((cpu_is_imx6q() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
+ || (cpu_is_imx6dl() && imx_get_soc_revision() >
+ IMX_CHIP_REVISION_1_0))
imx6q_cpuidle_init();
if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
@@ -387,6 +448,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 04084900d810..58e5033c4b18 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-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
@@ -18,8 +18,9 @@
#include "common.h"
#include "cpuidle.h"
+#include "hardware.h"
-static void __init imx6sl_fec_init(void)
+static void __init imx6sl_fec_clk_init(void)
{
struct regmap *gpr;
@@ -30,9 +31,14 @@ static void __init imx6sl_fec_init(void)
IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK, 0);
regmap_update_bits(gpr, IOMUXC_GPR1,
IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK, 0);
- } else {
+ } else
pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n");
- }
+}
+
+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)
@@ -41,7 +47,11 @@ static void __init imx6sl_init_late(void)
if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
- imx6sl_cpuidle_init();
+ /* cpuidle will be enabled later for i.MX6SLL */
+ if (cpu_is_imx6sll())
+ imx6sll_cpuidle_init();
+ else
+ imx6sl_cpuidle_init();
}
static void __init imx6sl_init_machine(void)
@@ -54,7 +64,8 @@ static void __init imx6sl_init_machine(void)
of_platform_default_populate(NULL, NULL, parent);
- imx6sl_fec_init();
+ if (!cpu_is_imx6sll())
+ imx6sl_fec_init();
imx_anatop_init();
imx6sl_pm_init();
}
@@ -66,17 +77,31 @@ static void __init imx6sl_init_irq(void)
imx_init_l2cache();
imx_src_init();
irqchip_init();
- imx6_pm_ccm_init("fsl,imx6sl-ccm");
+ if (cpu_is_imx6sll())
+ imx6_pm_ccm_init("fsl,imx6sll-ccm");
+ else
+ imx6_pm_ccm_init("fsl,imx6sl-ccm");
+}
+
+static void __init imx6sl_map_io(void)
+{
+ debug_ll_io_init();
+ 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",
NULL,
};
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 7f52d9b1e8a4..304909083930 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 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
@@ -14,9 +14,30 @@
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <linux/micrel_phy.h>
#include "common.h"
#include "cpuidle.h"
+static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
+{
+ phy_write(dev, 0x0d, device);
+ phy_write(dev, 0x0e, reg);
+ phy_write(dev, 0x0d, (1 << 14) | device);
+ phy_write(dev, 0x0e, val);
+}
+
+static int ksz9031rn_phy_fixup(struct phy_device *dev)
+{
+ /*
+ * min rx data delay, max rx/tx clock delay,
+ * min rx/tx control delay
+ */
+ mmd_write_reg(dev, 2, 4, 0);
+ mmd_write_reg(dev, 2, 5, 0);
+ mmd_write_reg(dev, 2, 8, 0x003ff);
+
+ return 0;
+}
static int ar8031_phy_fixup(struct phy_device *dev)
{
@@ -26,6 +47,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);
@@ -38,9 +67,12 @@ static int ar8031_phy_fixup(struct phy_device *dev)
#define PHY_ID_AR8031 0x004dd074
static void __init imx6sx_enet_phy_init(void)
{
- if (IS_BUILTIN(CONFIG_PHYLIB))
+ if (IS_BUILTIN(CONFIG_PHYLIB)) {
+ phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
+ ksz9031rn_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
ar8031_phy_fixup);
+ }
}
static void __init imx6sx_enet_clk_sel(void)
@@ -60,6 +92,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();
}
@@ -91,10 +124,17 @@ static void __init imx6sx_init_irq(void)
static void __init imx6sx_init_late(void)
{
- imx6sx_cpuidle_init();
-
if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
+
+ imx6sx_cpuidle_init();
+}
+
+static void __init imx6sx_map_io(void)
+{
+ debug_ll_io_init();
+ imx6_pm_map_io();
+ imx_busfreq_map_io();
}
static const char * const imx6sx_dt_compat[] __initconst = {
@@ -105,6 +145,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 58a2b88233e6..851034d5f73f 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * 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
@@ -9,14 +9,17 @@
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/micrel_phy.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
+#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include "common.h"
#include "cpuidle.h"
+#include "hardware.h"
static void __init imx6ul_enet_clk_init(void)
{
@@ -46,15 +49,122 @@ static int ksz8081_phy_fixup(struct phy_device *dev)
static void __init imx6ul_enet_phy_init(void)
{
- if (IS_BUILTIN(CONFIG_PHYLIB))
- phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK,
- ksz8081_phy_fixup);
+ if (IS_BUILTIN(CONFIG_PHYLIB)) {
+ /*
+ * i.MX6UL EVK board RevA, RevB, RevC all use KSZ8081
+ * Silicon revision 00, the PHY ID is 0x00221560, pass our
+ * test with the phy fixup.
+ */
+ phy_register_fixup(PHY_ANY_ID, PHY_ID_KSZ8081, 0xffffffff,
+ ksz8081_phy_fixup);
+
+ /*
+ * i.MX6UL EVK board RevC1 board use KSZ8081
+ * Silicon revision 01, the PHY ID is 0x00221561.
+ * This silicon revision still need the phy fixup setting.
+ */
+ #define PHY_ID_KSZ8081_MNRN61 0x00221561
+ phy_register_fixup(PHY_ANY_ID, PHY_ID_KSZ8081_MNRN61,
+ 0xffffffff, ksz8081_phy_fixup);
+ }
+}
+
+#define OCOTP_CFG3 0x440
+#define OCOTP_CFG3_SPEED_SHIFT 16
+#define OCOTP_CFG3_SPEED_696MHZ 0x2
+#define OCOTP_CFG3_SPEED_900MHZ 0x3
+
+static void __init imx6ul_opp_check_speed_grading(struct device *cpu_dev)
+{
+ struct device_node *np;
+ void __iomem *base;
+ u32 val;
+
+ if (cpu_is_imx6ul())
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
+ else
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6ull-ocotp");
+
+ if (!np) {
+ pr_warn("failed to find ocotp node\n");
+ return;
+ }
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_warn("failed to map ocotp\n");
+ goto put_node;
+ }
+
+ /*
+ * Speed GRADING[1:0] defines the max speed of ARM:
+ * 2b'00: Reserved;
+ * 2b'01: 528000000Hz;
+ * 2b'10: 700000000Hz(i.MX6UL), 800000000Hz(i.MX6ULL);
+ * 2b'11: 900000000Hz(i.MX6ULL);
+ * We need to set the max speed of ARM according to fuse map.
+ */
+ val = readl_relaxed(base + OCOTP_CFG3);
+ val >>= OCOTP_CFG3_SPEED_SHIFT;
+ val &= 0x3;
+ if (cpu_is_imx6ul()) {
+ if (val < OCOTP_CFG3_SPEED_696MHZ) {
+ if (dev_pm_opp_disable(cpu_dev, 696000000))
+ pr_warn("Failed to disable 696MHz OPP\n");
+ }
+ }
+
+ if (cpu_is_imx6ull()) {
+ if (val != OCOTP_CFG3_SPEED_696MHZ) {
+ if (dev_pm_opp_disable(cpu_dev, 792000000))
+ pr_warn("Failed to disable 792MHz OPP\n");
+ }
+
+ if (val != OCOTP_CFG3_SPEED_900MHZ) {
+ if(dev_pm_opp_disable(cpu_dev, 900000000))
+ pr_warn("Failed to disable 900MHz OPP\n");
+ }
+ }
+ iounmap(base);
+
+put_node:
+ of_node_put(np);
+}
+
+static void __init imx6ul_opp_init(void)
+{
+ struct device_node *np;
+ struct device *cpu_dev = get_cpu_device(0);
+
+ if (!cpu_dev) {
+ pr_warn("failed to get cpu0 device\n");
+ return;
+ }
+ np = of_node_get(cpu_dev->of_node);
+ if (!np) {
+ pr_warn("failed to find cpu0 node\n");
+ return;
+ }
+
+ if (dev_pm_opp_of_add_table(cpu_dev)) {
+ pr_warn("failed to init OPP table\n");
+ goto put_node;
+ }
+
+ imx6ul_opp_check_speed_grading(cpu_dev);
+
+put_node:
+ of_node_put(np);
}
static inline void imx6ul_enet_init(void)
{
imx6ul_enet_clk_init();
imx6ul_enet_phy_init();
+ if (cpu_is_imx6ul())
+ imx6_enet_mac_init("fsl,imx6ul-fec", "fsl,imx6ul-ocotp");
+ else
+ imx6_enet_mac_init("fsl,imx6ul-fec", "fsl,imx6ull-ocotp");
}
static void __init imx6ul_init_machine(void)
@@ -73,6 +183,7 @@ static void __init imx6ul_init_machine(void)
static void __init imx6ul_init_irq(void)
{
+ imx_gpc_check_dt();
imx_init_revision_from_anatop();
imx_src_init();
irqchip_init();
@@ -81,18 +192,29 @@ static void __init imx6ul_init_irq(void)
static void __init imx6ul_init_late(void)
{
- imx6sx_cpuidle_init();
-
- if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
+ if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
+ imx6ul_opp_init();
platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
+ }
+
+ imx6ul_cpuidle_init();
+}
+
+static void __init imx6ul_map_io(void)
+{
+ debug_ll_io_init();
+ imx6_pm_map_io();
+ imx_busfreq_map_io();
}
static const char * const imx6ul_dt_compat[] __initconst = {
"fsl,imx6ul",
+ "fsl,imx6ull",
NULL,
};
-DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
+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 26ca744d3e2b..3f335974723f 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -10,12 +10,20 @@
#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
+#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <asm/mach/arch.h>
#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)
{
@@ -66,6 +74,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;
@@ -81,10 +106,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;
@@ -93,15 +131,36 @@ static void __init imx7d_init_machine(void)
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
+ of_platform_default_populate(NULL, NULL, parent);
+ imx7d_pm_init();
imx_anatop_init();
imx7d_enet_init();
}
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_init_late(void)
+{
+ if (IS_ENABLED(CONFIG_ARM_IMX7D_CPUFREQ)) {
+ platform_device_register_simple("imx7d-cpufreq", -1, NULL, 0);
+ }
+ imx7d_cpuidle_init();
+}
+
+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 = {
@@ -111,7 +170,10 @@ 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,
.dt_compat = imx7d_dt_compat,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx7ulp.c b/arch/arm/mach-imx/mach-imx7ulp.c
new file mode 100644
index 000000000000..2d916e1dd2c9
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx7ulp.c
@@ -0,0 +1,74 @@
+/*
+ * 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/irqchip.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "common.h"
+#include "cpuidle.h"
+#include "hardware.h"
+
+/* 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_init_machine(void)
+{
+ struct device *parent;
+
+ parent = imx_soc_device_init();
+ if (parent == NULL)
+ pr_warn("failed to initialize soc device\n");
+
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static void __init imx7ulp_init_irq(void)
+{
+ /* TBD */
+ mxc_set_cpu_type(MXC_CPU_IMX7ULP);
+
+ irqchip_init();
+ imx7ulp_pm_init();
+}
+
+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();
+}
+
+static const char *const imx7ulp_dt_compat[] __initconst = {
+ "fsl,imx7ulp",
+ NULL,
+};
+
+DT_MACHINE_START(IMX7ulp, "Freescale i.MX7ULP (Device Tree)")
+ .map_io = imx7ulp_map_io,
+ .init_irq = imx7ulp_init_irq,
+ .init_machine = imx7ulp_init_machine,
+ .init_late = imx7ulp_init_late,
+ .dt_compat = imx7ulp_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index db9621c718ec..9c185760dbd4 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ * Copyright 2011,2016 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -10,12 +11,16 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include <linux/hrtimer.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/perf_event.h>
+#include <linux/slab.h>
#include "common.h"
@@ -26,8 +31,520 @@
#define MMDC_MDMISC 0x18
#define BM_MMDC_MDMISC_DDR_TYPE 0x18
#define BP_MMDC_MDMISC_DDR_TYPE 0x3
+#define BM_MMDC_MDMISC_LPDDR2_2CH 0x4
+#define BP_MMDC_MDMISC_LPDDR2_2CH 0x2
+
+#define TOTAL_CYCLES 0x0
+#define BUSY_CYCLES 0x1
+#define READ_ACCESSES 0x2
+#define WRITE_ACCESSES 0x3
+#define READ_BYTES 0x4
+#define WRITE_BYTES 0x5
+
+/* Enables, resets, freezes, overflow profiling*/
+#define DBG_DIS 0x0
+#define DBG_EN 0x1
+#define DBG_RST 0x2
+#define PRF_FRZ 0x4
+#define CYC_OVF 0x8
+#define PROFILE_SEL 0x10
+
+#define MMDC_MADPCR0 0x410
+#define MMDC_MADPCR1 0x414
+#define MMDC_MADPSR0 0x418
+#define MMDC_MADPSR1 0x41C
+#define MMDC_MADPSR2 0x420
+#define MMDC_MADPSR3 0x424
+#define MMDC_MADPSR4 0x428
+#define MMDC_MADPSR5 0x42C
+
+#define MMDC_NUM_COUNTERS 6
+
+#define MMDC_FLAG_PROFILE_SEL 0x1
+#define MMDC_PRF_AXI_ID_CLEAR 0x0
+
+#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;
+};
+
+static const struct fsl_mmdc_devtype_data imx6q_data = {
+};
+
+static const struct fsl_mmdc_devtype_data imx6qp_data = {
+ .flags = MMDC_FLAG_PROFILE_SEL,
+};
+
+static const struct of_device_id imx_mmdc_dt_ids[] = {
+ { .compatible = "fsl,imx6q-mmdc", .data = (void *)&imx6q_data},
+ { .compatible = "fsl,imx6qp-mmdc", .data = (void *)&imx6qp_data},
+ { /* sentinel */ }
+};
+
+
+#ifdef CONFIG_PERF_EVENTS
+
+static enum cpuhp_state cpuhp_mmdc_state;
+static DEFINE_IDA(mmdc_ida);
+
+PMU_EVENT_ATTR_STRING(total-cycles, mmdc_pmu_total_cycles, "event=0x00")
+PMU_EVENT_ATTR_STRING(busy-cycles, mmdc_pmu_busy_cycles, "event=0x01")
+PMU_EVENT_ATTR_STRING(read-accesses, mmdc_pmu_read_accesses, "event=0x02")
+PMU_EVENT_ATTR_STRING(write-accesses, mmdc_pmu_write_accesses, "event=0x03")
+PMU_EVENT_ATTR_STRING(read-bytes, mmdc_pmu_read_bytes, "event=0x04")
+PMU_EVENT_ATTR_STRING(read-bytes.unit, mmdc_pmu_read_bytes_unit, "MB");
+PMU_EVENT_ATTR_STRING(read-bytes.scale, mmdc_pmu_read_bytes_scale, "0.000001");
+PMU_EVENT_ATTR_STRING(write-bytes, mmdc_pmu_write_bytes, "event=0x05")
+PMU_EVENT_ATTR_STRING(write-bytes.unit, mmdc_pmu_write_bytes_unit, "MB");
+PMU_EVENT_ATTR_STRING(write-bytes.scale, mmdc_pmu_write_bytes_scale, "0.000001");
+
+struct mmdc_pmu {
+ struct pmu pmu;
+ void __iomem *mmdc_base;
+ cpumask_t cpu;
+ struct hrtimer hrtimer;
+ unsigned int active_events;
+ struct device *dev;
+ struct perf_event *mmdc_events[MMDC_NUM_COUNTERS];
+ struct hlist_node node;
+ struct fsl_mmdc_devtype_data *devtype_data;
+};
+
+/*
+ * Polling period is set to one second, overflow of total-cycles (the fastest
+ * increasing counter) takes ten seconds so one second is safe
+ */
+static unsigned int mmdc_pmu_poll_period_us = 1000000;
+
+module_param_named(pmu_pmu_poll_period_us, mmdc_pmu_poll_period_us, uint,
+ S_IRUGO | S_IWUSR);
+
+static ktime_t mmdc_pmu_timer_period(void)
+{
+ return ns_to_ktime((u64)mmdc_pmu_poll_period_us * 1000);
+}
+
+static ssize_t mmdc_pmu_cpumask_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mmdc_pmu *pmu_mmdc = dev_get_drvdata(dev);
+
+ return cpumap_print_to_pagebuf(true, buf, &pmu_mmdc->cpu);
+}
+
+static struct device_attribute mmdc_pmu_cpumask_attr =
+ __ATTR(cpumask, S_IRUGO, mmdc_pmu_cpumask_show, NULL);
+
+static struct attribute *mmdc_pmu_cpumask_attrs[] = {
+ &mmdc_pmu_cpumask_attr.attr,
+ NULL,
+};
+
+static struct attribute_group mmdc_pmu_cpumask_attr_group = {
+ .attrs = mmdc_pmu_cpumask_attrs,
+};
+
+static struct attribute *mmdc_pmu_events_attrs[] = {
+ &mmdc_pmu_total_cycles.attr.attr,
+ &mmdc_pmu_busy_cycles.attr.attr,
+ &mmdc_pmu_read_accesses.attr.attr,
+ &mmdc_pmu_write_accesses.attr.attr,
+ &mmdc_pmu_read_bytes.attr.attr,
+ &mmdc_pmu_read_bytes_unit.attr.attr,
+ &mmdc_pmu_read_bytes_scale.attr.attr,
+ &mmdc_pmu_write_bytes.attr.attr,
+ &mmdc_pmu_write_bytes_unit.attr.attr,
+ &mmdc_pmu_write_bytes_scale.attr.attr,
+ NULL,
+};
+
+static struct attribute_group mmdc_pmu_events_attr_group = {
+ .name = "events",
+ .attrs = mmdc_pmu_events_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-63");
+PMU_FORMAT_ATTR(axi_id, "config1:0-63");
+
+static struct attribute *mmdc_pmu_format_attrs[] = {
+ &format_attr_event.attr,
+ &format_attr_axi_id.attr,
+ NULL,
+};
+
+static struct attribute_group mmdc_pmu_format_attr_group = {
+ .name = "format",
+ .attrs = mmdc_pmu_format_attrs,
+};
+
+static const struct attribute_group *attr_groups[] = {
+ &mmdc_pmu_events_attr_group,
+ &mmdc_pmu_format_attr_group,
+ &mmdc_pmu_cpumask_attr_group,
+ NULL,
+};
+
+static u32 mmdc_pmu_read_counter(struct mmdc_pmu *pmu_mmdc, int cfg)
+{
+ void __iomem *mmdc_base, *reg;
+
+ mmdc_base = pmu_mmdc->mmdc_base;
+
+ switch (cfg) {
+ case TOTAL_CYCLES:
+ reg = mmdc_base + MMDC_MADPSR0;
+ break;
+ case BUSY_CYCLES:
+ reg = mmdc_base + MMDC_MADPSR1;
+ break;
+ case READ_ACCESSES:
+ reg = mmdc_base + MMDC_MADPSR2;
+ break;
+ case WRITE_ACCESSES:
+ reg = mmdc_base + MMDC_MADPSR3;
+ break;
+ case READ_BYTES:
+ reg = mmdc_base + MMDC_MADPSR4;
+ break;
+ case WRITE_BYTES:
+ reg = mmdc_base + MMDC_MADPSR5;
+ break;
+ default:
+ return WARN_ONCE(1,
+ "invalid configuration %d for mmdc counter", cfg);
+ }
+ return readl(reg);
+}
+
+static int mmdc_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+{
+ struct mmdc_pmu *pmu_mmdc = hlist_entry_safe(node, struct mmdc_pmu, node);
+ int target;
+
+ if (!cpumask_test_and_clear_cpu(cpu, &pmu_mmdc->cpu))
+ return 0;
+
+ target = cpumask_any_but(cpu_online_mask, cpu);
+ if (target >= nr_cpu_ids)
+ return 0;
+
+ perf_pmu_migrate_context(&pmu_mmdc->pmu, cpu, target);
+ cpumask_set_cpu(target, &pmu_mmdc->cpu);
+
+ return 0;
+}
+
+static bool mmdc_pmu_group_event_is_valid(struct perf_event *event,
+ struct pmu *pmu,
+ unsigned long *used_counters)
+{
+ int cfg = event->attr.config;
+
+ if (is_software_event(event))
+ return true;
+
+ if (event->pmu != pmu)
+ return false;
+
+ return !test_and_set_bit(cfg, used_counters);
+}
+
+/*
+ * Each event has a single fixed-purpose counter, so we can only have a
+ * single active event for each at any point in time. Here we just check
+ * for duplicates, and rely on mmdc_pmu_event_init to verify that the HW
+ * event numbers are valid.
+ */
+static bool mmdc_pmu_group_is_valid(struct perf_event *event)
+{
+ struct pmu *pmu = event->pmu;
+ struct perf_event *leader = event->group_leader;
+ struct perf_event *sibling;
+ unsigned long counter_mask = 0;
+
+ set_bit(leader->attr.config, &counter_mask);
+
+ if (event != leader) {
+ if (!mmdc_pmu_group_event_is_valid(event, pmu, &counter_mask))
+ return false;
+ }
+
+ list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
+ if (!mmdc_pmu_group_event_is_valid(sibling, pmu, &counter_mask))
+ return false;
+ }
+
+ return true;
+}
+
+static int mmdc_pmu_event_init(struct perf_event *event)
+{
+ struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+ int cfg = event->attr.config;
+
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+ return -EOPNOTSUPP;
+
+ if (event->cpu < 0) {
+ dev_warn(pmu_mmdc->dev, "Can't provide per-task data!\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (event->attr.exclude_user ||
+ event->attr.exclude_kernel ||
+ event->attr.exclude_hv ||
+ event->attr.exclude_idle ||
+ event->attr.exclude_host ||
+ event->attr.exclude_guest ||
+ event->attr.sample_period)
+ return -EINVAL;
+
+ if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS)
+ return -EINVAL;
+
+ if (!mmdc_pmu_group_is_valid(event))
+ return -EINVAL;
+
+ event->cpu = cpumask_first(&pmu_mmdc->cpu);
+ return 0;
+}
+
+static void mmdc_pmu_event_update(struct perf_event *event)
+{
+ struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ u64 delta, prev_raw_count, new_raw_count;
+
+ do {
+ prev_raw_count = local64_read(&hwc->prev_count);
+ new_raw_count = mmdc_pmu_read_counter(pmu_mmdc,
+ event->attr.config);
+ } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+ new_raw_count) != prev_raw_count);
+
+ delta = (new_raw_count - prev_raw_count) & 0xFFFFFFFF;
+
+ local64_add(delta, &event->count);
+}
+
+static void mmdc_pmu_event_start(struct perf_event *event, int flags)
+{
+ struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ void __iomem *mmdc_base, *reg;
+ u32 val;
+
+ mmdc_base = pmu_mmdc->mmdc_base;
+ reg = mmdc_base + MMDC_MADPCR0;
+
+ /*
+ * hrtimer is required because mmdc does not provide an interrupt so
+ * polling is necessary
+ */
+ hrtimer_start(&pmu_mmdc->hrtimer, mmdc_pmu_timer_period(),
+ HRTIMER_MODE_REL_PINNED);
+
+ local64_set(&hwc->prev_count, 0);
+
+ writel(DBG_RST, reg);
+
+ /*
+ * Write the AXI id parameter to MADPCR1.
+ */
+ val = event->attr.config1;
+ reg = mmdc_base + MMDC_MADPCR1;
+ writel(val, reg);
+
+ reg = mmdc_base + MMDC_MADPCR0;
+ val = DBG_EN;
+ if (pmu_mmdc->devtype_data->flags & MMDC_FLAG_PROFILE_SEL)
+ val |= PROFILE_SEL;
+
+ writel(val, reg);
+}
+
+static int mmdc_pmu_event_add(struct perf_event *event, int flags)
+{
+ struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+
+ int cfg = event->attr.config;
+
+ if (flags & PERF_EF_START)
+ mmdc_pmu_event_start(event, flags);
+
+ if (pmu_mmdc->mmdc_events[cfg] != NULL)
+ return -EAGAIN;
+
+ pmu_mmdc->mmdc_events[cfg] = event;
+ pmu_mmdc->active_events++;
+
+ local64_set(&hwc->prev_count, mmdc_pmu_read_counter(pmu_mmdc, cfg));
+
+ return 0;
+}
+
+static void mmdc_pmu_event_stop(struct perf_event *event, int flags)
+{
+ struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+ void __iomem *mmdc_base, *reg;
+
+ mmdc_base = pmu_mmdc->mmdc_base;
+ reg = mmdc_base + MMDC_MADPCR0;
+
+ writel(PRF_FRZ, reg);
+
+ reg = mmdc_base + MMDC_MADPCR1;
+ writel(MMDC_PRF_AXI_ID_CLEAR, reg);
+
+ mmdc_pmu_event_update(event);
+}
+
+static void mmdc_pmu_event_del(struct perf_event *event, int flags)
+{
+ struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+ int cfg = event->attr.config;
+
+ pmu_mmdc->mmdc_events[cfg] = NULL;
+ pmu_mmdc->active_events--;
+
+ if (pmu_mmdc->active_events == 0)
+ hrtimer_cancel(&pmu_mmdc->hrtimer);
+
+ mmdc_pmu_event_stop(event, PERF_EF_UPDATE);
+}
+
+static void mmdc_pmu_overflow_handler(struct mmdc_pmu *pmu_mmdc)
+{
+ int i;
+
+ for (i = 0; i < MMDC_NUM_COUNTERS; i++) {
+ struct perf_event *event = pmu_mmdc->mmdc_events[i];
+
+ if (event)
+ mmdc_pmu_event_update(event);
+ }
+}
+
+static enum hrtimer_restart mmdc_pmu_timer_handler(struct hrtimer *hrtimer)
+{
+ struct mmdc_pmu *pmu_mmdc = container_of(hrtimer, struct mmdc_pmu,
+ hrtimer);
+
+ mmdc_pmu_overflow_handler(pmu_mmdc);
+ hrtimer_forward_now(hrtimer, mmdc_pmu_timer_period());
+
+ return HRTIMER_RESTART;
+}
+
+static int mmdc_pmu_init(struct mmdc_pmu *pmu_mmdc,
+ void __iomem *mmdc_base, struct device *dev)
+{
+ int mmdc_num;
+
+ *pmu_mmdc = (struct mmdc_pmu) {
+ .pmu = (struct pmu) {
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = attr_groups,
+ .event_init = mmdc_pmu_event_init,
+ .add = mmdc_pmu_event_add,
+ .del = mmdc_pmu_event_del,
+ .start = mmdc_pmu_event_start,
+ .stop = mmdc_pmu_event_stop,
+ .read = mmdc_pmu_event_update,
+ },
+ .mmdc_base = mmdc_base,
+ .dev = dev,
+ .active_events = 0,
+ };
+
+ mmdc_num = ida_simple_get(&mmdc_ida, 0, 0, GFP_KERNEL);
+
+ return mmdc_num;
+}
+
+static int imx_mmdc_remove(struct platform_device *pdev)
+{
+ struct mmdc_pmu *pmu_mmdc = platform_get_drvdata(pdev);
+
+ cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
+ perf_pmu_unregister(&pmu_mmdc->pmu);
+ kfree(pmu_mmdc);
+ return 0;
+}
+
+static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base)
+{
+ struct mmdc_pmu *pmu_mmdc;
+ char *name;
+ int mmdc_num;
+ int ret;
+ const struct of_device_id *of_id =
+ of_match_device(imx_mmdc_dt_ids, &pdev->dev);
+
+ pmu_mmdc = kzalloc(sizeof(*pmu_mmdc), GFP_KERNEL);
+ if (!pmu_mmdc) {
+ pr_err("failed to allocate PMU device!\n");
+ return -ENOMEM;
+ }
+
+ /* The first instance registers the hotplug state */
+ if (!cpuhp_mmdc_state) {
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+ "perf/arm/mmdc:online", NULL,
+ mmdc_pmu_offline_cpu);
+ if (ret < 0) {
+ pr_err("cpuhp_setup_state_multi failed\n");
+ goto pmu_free;
+ }
+ cpuhp_mmdc_state = ret;
+ }
+
+ mmdc_num = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev);
+ if (mmdc_num == 0)
+ name = "mmdc";
+ else
+ name = devm_kasprintf(&pdev->dev,
+ GFP_KERNEL, "mmdc%d", mmdc_num);
+
+ pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data;
+
+ hrtimer_init(&pmu_mmdc->hrtimer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ pmu_mmdc->hrtimer.function = mmdc_pmu_timer_handler;
+
+ cpumask_set_cpu(raw_smp_processor_id(), &pmu_mmdc->cpu);
+
+ /* Register the pmu instance for cpu hotplug */
+ cpuhp_state_add_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
+
+ ret = perf_pmu_register(&(pmu_mmdc->pmu), name, -1);
+ if (ret)
+ goto pmu_register_err;
+
+ platform_set_drvdata(pdev, pmu_mmdc);
+ return 0;
+
+pmu_register_err:
+ pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret);
+ cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
+ hrtimer_cancel(&pmu_mmdc->hrtimer);
+pmu_free:
+ kfree(pmu_mmdc);
+ return ret;
+}
+
+#else
+#define imx_mmdc_remove NULL
+#define imx_mmdc_perf_init(pdev, mmdc_base) 0
+#endif
static int imx_mmdc_probe(struct platform_device *pdev)
{
@@ -44,6 +561,9 @@ static int imx_mmdc_probe(struct platform_device *pdev)
val = readl_relaxed(reg);
ddr_type = (val & BM_MMDC_MDMISC_DDR_TYPE) >>
BP_MMDC_MDMISC_DDR_TYPE;
+ /* Get lpddr2 2ch-mode */
+ lpddr2_2ch_mode = (val & BM_MMDC_MDMISC_LPDDR2_2CH) >>
+ BP_MMDC_MDMISC_LPDDR2_2CH;
reg = mmdc_base + MMDC_MAPSR;
@@ -62,7 +582,7 @@ static int imx_mmdc_probe(struct platform_device *pdev)
return -EBUSY;
}
- return 0;
+ return imx_mmdc_perf_init(pdev, mmdc_base);
}
int imx_mmdc_get_ddr_type(void)
@@ -70,10 +590,10 @@ int imx_mmdc_get_ddr_type(void)
return ddr_type;
}
-static const struct of_device_id imx_mmdc_dt_ids[] = {
- { .compatible = "fsl,imx6q-mmdc", },
- { /* sentinel */ }
-};
+int imx_mmdc_get_lpddr2_2ch_mode(void)
+{
+ return lpddr2_2ch_mode;
+}
static struct platform_driver imx_mmdc_driver = {
.driver = {
@@ -81,6 +601,7 @@ static struct platform_driver imx_mmdc_driver = {
.of_match_table = imx_mmdc_dt_ids,
},
.probe = imx_mmdc_probe,
+ .remove = imx_mmdc_remove,
};
static int __init imx_mmdc_init(void)
diff --git a/arch/arm/mach-imx/mu.c b/arch/arm/mach-imx/mu.c
new file mode 100644
index 000000000000..4ab7ef2f9d62
--- /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");
+ mu_base = of_iomap(np, 0);
+ WARN_ON(!mu_base);
+
+ ret = of_device_is_compatible(np, "fsl,imx7ulp-mu");
+ if (ret)
+ irq = platform_get_irq(pdev, 1);
+ else
+ irq = platform_get_irq(pdev, 0);
+ ret = request_irq(irq, imx_mu_isr,
+ IRQF_EARLY_RESUME | IRQF_SHARED, "imx-mu", 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");
+ 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" },
+ { .compatible = "fsl,imx7d-mu" },
+ { .compatible = "fsl,imx7ulp-mu" },
+ { }
+};
+
+#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",
+ .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..a00e86f27e65
--- /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 34f2ff62583c..f162e82d3ca1 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -39,9 +39,18 @@
#define MXC_CPU_IMX6SX 0x62
#define MXC_CPU_IMX6Q 0x63
#define MXC_CPU_IMX6UL 0x64
+#define MXC_CPU_IMX6ULL 0x65
+#define MXC_CPU_IMX6SLL 0x67
#define MXC_CPU_IMX7D 0x72
+#define MXC_CPU_IMX7ULP 0xff /* TBD */
+#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;
@@ -73,16 +82,42 @@ static inline bool cpu_is_imx6ul(void)
return __mxc_cpu_type == MXC_CPU_IMX6UL;
}
+static inline bool cpu_is_imx6ull(void)
+{
+ return __mxc_cpu_type == MXC_CPU_IMX6ULL;
+}
+
+static inline bool cpu_is_imx6sll(void)
+{
+ return __mxc_cpu_type == MXC_CPU_IMX6SLL;
+}
+
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;
+}
+
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 711dbbd5badd..1bddda6e69fb 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -24,7 +24,7 @@
#include "hardware.h"
u32 g_diag_reg;
-static void __iomem *scu_base;
+void __iomem *imx_scu_base;
static struct map_desc scu_io_desc __initdata = {
/* .virtual and .pfn are run-time assigned */
@@ -43,7 +43,7 @@ void __init imx_scu_map_io(void)
scu_io_desc.pfn = __phys_to_pfn(base);
iotable_init(&scu_io_desc, 1);
- scu_base = IMX_IO_ADDRESS(base);
+ imx_scu_base = IMX_IO_ADDRESS(base);
}
static int imx_boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -53,15 +53,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(imx_scu_base);
+ }
for (i = ncores; i < NR_CPUS; i++)
set_cpu_possible(i, false);
@@ -69,11 +93,15 @@ static void __init imx_smp_init_cpus(void)
void imx_smp_prepare(void)
{
- scu_enable(scu_base);
+ if (arm_is_ca7())
+ return;
+ scu_enable(imx_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 1515e498d348..41e148ee0b3c 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2014 Freescale Semiconductor, Inc.
+ * Copyright 2011-2016 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -19,11 +19,14 @@
#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/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>
@@ -60,13 +63,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:
@@ -96,6 +301,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 = {
@@ -110,6 +317,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 */
@@ -130,6 +349,27 @@ static const u32 imx6sl_mmdc_io_offset[] __initconst = {
0x330, 0x334, 0x320, /* SDCKE0, SDCKE1, RESET */
};
+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 = {
0x2ec, 0x2f0, 0x2f4, 0x2f8, /* DQM0 ~ DQM3 */
0x60c, 0x610, 0x61c, 0x620, /* GPR_B0DS ~ GPR_B3DS */
@@ -138,6 +378,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 */
@@ -145,6 +395,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",
@@ -153,6 +450,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 = {
@@ -163,6 +473,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 = {
@@ -173,6 +485,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,
+ .mmdc_num = 0,
+ .mmdc_offset = NULL,
};
static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
@@ -183,6 +497,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 = {
@@ -193,6 +520,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
};
/*
@@ -207,14 +589,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)
@@ -293,10 +680,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())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
+ cpu_is_imx6ull() || 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;
@@ -310,10 +705,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())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
+ cpu_is_imx6ull() || 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;
@@ -335,9 +738,11 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
*
* Note that IRQ #32 is GIC SPI #0.
*/
- imx_gpc_hwirq_unmask(0);
+ if (mode != WAIT_CLOCKED)
+ imx_gpc_hwirq_unmask(0);
writel_relaxed(val, ccm_base + CLPCR);
- imx_gpc_hwirq_mask(0);
+ if (mode != WAIT_CLOCKED)
+ imx_gpc_hwirq_mask(0);
return 0;
}
@@ -362,19 +767,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;
@@ -390,8 +880,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_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_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();
@@ -405,6 +937,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;
}
@@ -418,44 +957,109 @@ 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);
+
+ if (of_flat_dt_match(node, low_power_ocram_match)) {
+ if (!prop)
+ return -EINVAL;
- node = of_find_compatible_node(NULL, NULL, compat);
- if (!node) {
- ret = -ENODEV;
- goto out;
+ 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);
}
- ret = of_address_to_resource(node, 0, &res);
- if (ret)
- goto put_node;
+ return 0;
+}
- base->pbase = res.start;
- base->vbase = ioremap(res.start, resource_size(&res));
- if (!base->vbase)
- ret = -ENOMEM;
+void __init imx6_pm_map_io(void)
+{
+ unsigned long i;
-put_node:
- of_node_put(node);
-out:
- return ret;
+ 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));
+
+ /* 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);
@@ -464,41 +1068,24 @@ 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;
- }
-
- 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_node;
- }
-
- 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_node;
- }
+ /*
+ * 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 = virt_to_phys(v7_cpu_resume);
pm_info->pm_info_size = sizeof(*pm_info);
@@ -506,53 +1093,120 @@ 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_node;
- }
+ 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()) &&
+ 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()) &&
+ 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,
@@ -560,14 +1214,6 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
goto put_node;
-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_node:
of_node_put(node);
@@ -622,7 +1268,10 @@ void __init imx6_pm_ccm_init(const char *ccm_compat)
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)
@@ -632,15 +1281,96 @@ void __init imx6dl_pm_init(void)
void __init imx6sl_pm_init(void)
{
+ struct device_node *np;
+ struct regmap *gpr;
+
+ 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,
+ 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()) {
+ 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..540bc8effecf
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx7.c
@@ -0,0 +1,1187 @@
+/*
+ * 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/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 "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 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);
+}
+
+static int imx7_suspend_finish(unsigned long val)
+{
+ 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);
+
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ imx_anatop_pre_suspend();
+ imx_gpcv2_pre_suspend(false);
+
+ /* Zzz ... */
+ 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);
+
+ 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;
+ }
+
+ /* 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)
+{
+ struct device_node *node;
+ int i, ret = 0;
+ const u32 (*ddrc_offset_array)[2];
+ const u32 (*ddrc_phy_offset_array)[2];
+ unsigned long iram_paddr;
+
+ 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);
+
+ 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];
+ }
+
+ imx7_suspend_in_ocram_fn = fncpy(
+ suspend_ocram_base + sizeof(*pm_info),
+ &imx7_suspend,
+ MX7_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
+
+ goto put_node;
+
+put_node:
+ of_node_put(node);
+
+ return ret;
+}
+
+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 (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/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
new file mode 100644
index 000000000000..15aa46837fb0
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx7ulp.c
@@ -0,0 +1,756 @@
+/*
+ * 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/delay.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/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 "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 PMC_HSRUN 0x4
+#define PMC_RUN 0x8
+#define PMC_VLPR 0xc
+#define PMC_STOP 0x10
+#define PMC_VLPS 0x14
+#define PMC_LLS 0x18
+#define PMC_VLLS 0x1c
+#define PMC_STATUS 0x20
+#define PMC_CTRL 0x24
+#define PMC_SRAMCTRL_0 0x28
+#define PMC_SRAMCTRL_1 0x2c
+#define PMC_SRAMCTRL_2 0x30
+
+#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 BP_PMCTRL_STOPM 0
+#define BP_PMCTRL_PSTOPO 16
+
+#define MX7ULP_MAX_MMDC_IO_NUM 36
+#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 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[25][2] = {
+ {0x20, 0}, {0x3c, 0}, {0x40, 0}, {0x6c, 0},
+ {0x84, 0}, {0x8c, 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[16] = {
+ 0x14, 0x30, 0x40, 0x304,
+ 0x500, 0x504, 0x508, 0x50c,
+ 0x510, 0x514, 0x600, 0x604,
+ 0x608, 0x60c, 0x610, 0x614,
+};
+
+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 = {
+ 0x128, 0xf8, 0xd8, 0x108,
+ 0x104, 0x124, 0x80, 0x84,
+ 0x88, 0x8c, 0x120, 0x10c,
+ 0x110, 0x114, 0x118, 0x90,
+ 0x94, 0x98, 0x9c, 0xe0,
+ 0xe4,
+};
+
+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[16];
+ 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 < 16; 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 < 25; 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 < 25; 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(0x10101, scg1_base + 0x104);
+ 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 imx7ulp_cpu_pwr_mode mode)
+{
+ u32 val1 = BM_PMPROT_AHSRUN | BM_PMPROT_AVLP | BM_PMPROT_AVLLS;
+ u32 val2 = readl_relaxed(smc1_base + PMCTRL);
+ u32 val3 = readl_relaxed(pmc0_base + PMC_CTRL);
+
+ val2 &= ~(BM_PMCTRL_RUNM |
+ BM_PMCTRL_STOPM | BM_PMCTRL_PSTOPO);
+ val3 |= BM_CTRL_LDOOKDIS;
+
+ switch (mode) {
+ case RUN:
+ /* system/bus clock enabled */
+ val2 |= 0x3 << BP_PMCTRL_PSTOPO;
+ break;
+ case WAIT:
+ /* system clock disabled, bus clock enabled */
+ val2 |= 0x2 << BP_PMCTRL_PSTOPO;
+ break;
+ case STOP:
+ /* system/bus clock disabled */
+ val2 |= 0x1 << BP_PMCTRL_PSTOPO;
+ break;
+ case VLPS:
+ val2 |= 0x2 << BP_PMCTRL_STOPM;
+ break;
+ case VLLS:
+ val2 |= 0x4 << BP_PMCTRL_STOPM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ writel_relaxed(val1, smc1_base + PMPROT);
+ writel_relaxed(val2, smc1_base + PMCTRL);
+ writel_relaxed(val3, pmc0_base + PMC_CTRL);
+
+ return 0;
+}
+
+static int imx7ulp_suspend_finish(unsigned long val)
+{
+ 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:
+ imx7ulp_set_lpm(VLPS);
+ writel_relaxed(
+ readl_relaxed(pmc1_base + PMC_VLPS) | BM_VLPS_RBBEN,
+ pmc1_base + PMC_VLPS);
+
+ /* Zzz ... */
+ cpu_suspend(0, imx7ulp_suspend_finish);
+
+ writel_relaxed(
+ readl_relaxed(pmc1_base + PMC_VLPS) & ~BM_VLPS_RBBEN,
+ pmc1_base + PMC_VLPS);
+ imx7ulp_set_lpm(RUN);
+ break;
+ case PM_SUSPEND_MEM:
+ imx7ulp_gpio_save();
+ imx7ulp_scg1_save();
+ imx7ulp_pcc2_save();
+ imx7ulp_pcc3_save();
+ imx7ulp_tpm_save();
+ imx7ulp_lpuart_save();
+ imx7ulp_iomuxc_save();
+ imx7ulp_set_lpm(VLLS);
+
+ /* Zzz ... */
+ cpu_suspend(0, imx7ulp_suspend_finish);
+
+ imx7ulp_pcc2_restore();
+ imx7ulp_pcc3_restore();
+ imx7ulp_lpuart_restore();
+ imx7ulp_set_dgo(0);
+ imx7ulp_tpm_restore();
+ imx7ulp_set_lpm(RUN);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+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;
+ }
+
+ /* Set all entries to 0 except first 3 words reserved for M4. */
+ memset((void *)iram_tlb_base_addr, 0, MX7ULP_IRAM_TLB_SIZE);
+}
+
+void __init imx7ulp_pm_common_init(const struct imx7ulp_pm_socdata
+ *socdata)
+{
+ struct device_node *np;
+ unsigned long sram_paddr;
+ const u32 *mmdc_offset_array;
+ const u32 *mmdc_io_offset_array;
+ unsigned long i, j;
+ int ret;
+
+ /*
+ * 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-iomuxc-1");
+ 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]);
+ }
+
+ /*
+ * 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];
+
+ 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(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);
+
+ 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..b4bfa2ad1231
--- /dev/null
+++ b/arch/arm/mach-imx/pm-rpmsg.c
@@ -0,0 +1,343 @@
+/*
+ * 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 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>
+
+#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;
+
+ pm_send_message(&msg, &pm_rpmsg, true);
+
+}
+
+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 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,
+ msecs_to_jiffies(100));
+
+ 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");
+
+ 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 SIMPLE_DEV_PM_OPS(pm_heartbeat_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..cdee6169958e
--- /dev/null
+++ b/arch/arm/mach-imx/smp_wfe_imx6.S
@@ -0,0 +1,132 @@
+/*
+ * 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 imx_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,=imx_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,=imx_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:
+#endif
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index 70b083fe934a..c53b6da411b9 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2015 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -18,6 +18,7 @@
#include <linux/smp.h>
#include <asm/smp_plat.h>
#include "common.h"
+#include "hardware.h"
#define SRC_SCR 0x000
#define SRC_GPR1 0x020
@@ -29,9 +30,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,
@@ -41,6 +51,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)
{
@@ -57,11 +72,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) {
@@ -87,32 +102,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(virt_to_phys(jump_addr),
- src_base + SRC_GPR1 + cpu * 8);
+ if (cpu_is_imx7d())
+ writel_relaxed(virt_to_phys(jump_addr),
+ src_base + SRC_GPR1_V2 + cpu * 8);
+ else
+ writel_relaxed(virt_to_phys(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)
@@ -126,6 +168,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);
@@ -134,9 +185,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 76ee2ceec8d5..b8ad48fc85a9 100644
--- a/arch/arm/mach-imx/suspend-imx6.S
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 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
@@ -47,23 +47,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
@@ -71,9 +80,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. */
@@ -92,29 +141,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
@@ -134,23 +162,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]
@@ -185,10 +484,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.
@@ -207,31 +521,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
@@ -291,6 +633,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
@@ -303,8 +666,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
@@ -319,6 +702,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 */
@@ -329,7 +722,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)
@@ -342,8 +744,11 @@ ENDPROC(imx6_suspend)
ENTRY(v7_cpu_resume)
bl v7_invalidate_l1
+ is_cortex_a7
+ beq done
#ifdef CONFIG_CACHE_L2X0
bl l2c310_early_resume
#endif
+done:
b cpu_resume
ENDPROC(v7_cpu_resume)
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..70a0dd8d315f
--- /dev/null
+++ b/arch/arm/mach-imx/suspend-imx7ulp.S
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 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/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 0x6c
+#define PM_INFO_MX7ULP_GPIO_REG_OFFSET 0x70
+#define PM_INFO_IOMUX_NUM_OFFSET 0x90
+#define PM_INFO_IOMUX_VAL_OFFSET 0x94
+#define PM_INFO_SELECT_INPUT_NUM_OFFSET 0x264
+#define PM_INFO_SELECT_INPUT_VAL_OFFSET 0x268
+#define PM_INFO_MMDC_IO_NUM_OFFSET 0x3a0
+#define PM_INFO_MMDC_IO_VAL_OFFSET 0x3a4
+/* below offsets depends on MX7ULP_MAX_MMDC_IO_NUM(36) definition */
+#define PM_INFO_MMDC_NUM_OFFSET 0x4c4
+#define PM_INFO_MMDC_VAL_OFFSET 0x4c8
+
+#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
+
+ /* 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 DDR out of self-refresh */
+ 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]
+
+ /* 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/Kconfig b/arch/arm/mm/Kconfig
index c1799dd1d0d9..aa7d512aaffc 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -692,7 +692,7 @@ config ARM_VIRT_EXT
details.
config SWP_EMULATE
- bool "Emulate SWP/SWPB instructions" if !SMP
+ bool "Emulate SWP/SWPB instructions"
depends on CPU_V7
default y if SMP
select HAVE_PROC_CPU if PROC_FS
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index a134d8a13d00..d2dd211f66ee 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -162,6 +162,9 @@ loop2:
skip:
add r10, r10, #2 @ increment cache number
cmp r3, r10
+#ifdef CONFIG_ARM_ERRATA_814220
+ dsb
+#endif
bgt flush_levels
finished:
mov r10, #0 @ swith back to cache level 0
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index 054b491ff764..872b1ff7ff11 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -14,6 +14,7 @@
#include <asm/proc-fns.h>
#include <asm/tlbflush.h>
#include <asm/page.h>
+#include "dma.h"
#ifndef MULTI_CPU
EXPORT_SYMBOL(cpu_dcache_clean_area);
@@ -30,6 +31,9 @@ EXPORT_SYMBOL(__cpuc_flush_user_all);
EXPORT_SYMBOL(__cpuc_flush_user_range);
EXPORT_SYMBOL(__cpuc_coherent_kern_range);
EXPORT_SYMBOL(__cpuc_flush_dcache_area);
+EXPORT_SYMBOL(__glue(_CACHE,_dma_map_area));
+EXPORT_SYMBOL(__glue(_CACHE,_dma_unmap_area));
+EXPORT_SYMBOL(__glue(_CACHE,_dma_flush_range));
#else
EXPORT_SYMBOL(cpu_cache);
#endif
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index dab2cb0c1f1c..92fd2f74b666 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -194,8 +194,7 @@ CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
-CONFIG_WL18XX=m
-CONFIG_WLCORE_SDIO=m
+# CONFIG_WLAN_VENDOR_TI is not set
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_MISC=y
@@ -344,15 +343,10 @@ CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ACPI=y
CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_OF_ESDHC=y
-CONFIG_MMC_SDHCI_TEGRA=y
-CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+# CONFIG_MMC_SDHCI_IPROC is not set
CONFIG_MMC_SPI=y
CONFIG_MMC_SDHI=y
-CONFIG_MMC_DW=y
-CONFIG_MMC_DW_EXYNOS=y
-CONFIG_MMC_DW_K3=y
-CONFIG_MMC_SUNXI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
diff --git a/arch/x86/include/asm/idle.h b/arch/x86/include/asm/idle.h
index c5d1785373ed..02bab09707f2 100644
--- a/arch/x86/include/asm/idle.h
+++ b/arch/x86/include/asm/idle.h
@@ -1,13 +1,6 @@
#ifndef _ASM_X86_IDLE_H
#define _ASM_X86_IDLE_H
-#define IDLE_START 1
-#define IDLE_END 2
-
-struct notifier_block;
-void idle_notifier_register(struct notifier_block *n);
-void idle_notifier_unregister(struct notifier_block *n);
-
#ifdef CONFIG_X86_64
void enter_idle(void);
void exit_idle(void);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index a55b32007785..54b2711f2dbc 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -67,19 +67,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_tss);
#ifdef CONFIG_X86_64
static DEFINE_PER_CPU(unsigned char, is_idle);
-static ATOMIC_NOTIFIER_HEAD(idle_notifier);
-
-void idle_notifier_register(struct notifier_block *n)
-{
- atomic_notifier_chain_register(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_register);
-
-void idle_notifier_unregister(struct notifier_block *n)
-{
- atomic_notifier_chain_unregister(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_unregister);
#endif
/*
@@ -255,14 +242,14 @@ static inline void play_dead(void)
void enter_idle(void)
{
this_cpu_write(is_idle, 1);
- atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+ idle_notifier_call_chain(IDLE_START);
}
static void __exit_idle(void)
{
if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
return;
- atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+ idle_notifier_call_chain(IDLE_END);
}
/* Called from interrupts to signify idle end */
diff --git a/block/blk-map.c b/block/blk-map.c
index a8b4f526d8bb..54f9e15412f4 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -196,6 +196,12 @@ int blk_rq_unmap_user(struct bio *bio)
}
EXPORT_SYMBOL(blk_rq_unmap_user);
+#ifdef CONFIG_AHCI_IMX
+extern void *sg_io_buffer_hack;
+#else
+#define sg_io_buffer_hack NULL
+#endif
+
/**
* blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage
* @q: request queue where request should be inserted
@@ -223,7 +229,14 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
if (!len || !kbuf)
return -EINVAL;
- do_copy = !blk_rq_aligned(q, addr, len) || object_is_on_stack(kbuf);
+#ifdef CONFIG_AHCI_IMX
+ if (kbuf == sg_io_buffer_hack)
+ do_copy = 0;
+ else
+#endif
+ do_copy = !blk_rq_aligned(q, addr, len)
+ || object_is_on_stack(kbuf);
+
if (do_copy)
bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
else
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index c6fee7437be4..b00647ee3d1c 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -251,6 +251,12 @@ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
return 0;
}
+#ifdef CONFIG_AHCI_IMX
+extern void *sg_io_buffer_hack;
+#else
+#define sg_io_buffer_hack NULL
+#endif
+
static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
struct bio *bio)
{
@@ -279,7 +285,12 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
ret = -EFAULT;
}
- r = blk_rq_unmap_user(bio);
+ if (sg_io_buffer_hack && !hdr->iovec_count)
+ r = copy_to_user(hdr->dxferp, sg_io_buffer_hack,
+ hdr->dxfer_len);
+ else
+ r = blk_rq_unmap_user(bio);
+
if (!ret)
ret = r;
@@ -303,6 +314,9 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
return -EIO;
+ if (sg_io_buffer_hack && hdr->dxfer_len > 0x10000)
+ return -EIO;
+
if (hdr->dxfer_len)
switch (hdr->dxfer_direction) {
default:
@@ -349,9 +363,14 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
ret = blk_rq_map_user_iov(q, rq, NULL, &i, GFP_KERNEL);
kfree(iov);
- } else if (hdr->dxfer_len)
- ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
- GFP_KERNEL);
+ } else if (hdr->dxfer_len) {
+ if (sg_io_buffer_hack)
+ ret = blk_rq_map_kern(q, rq, sg_io_buffer_hack,
+ hdr->dxfer_len, GFP_KERNEL);
+ else
+ ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp,
+ hdr->dxfer_len, GFP_KERNEL);
+ }
if (ret)
goto out_free_cdb;
diff --git a/crypto/gcm.c b/crypto/gcm.c
index dd33fbd2d868..8d335ec6dfc5 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -119,7 +119,7 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
be128 hash;
u8 iv[16];
- struct crypto_gcm_setkey_result result;
+ struct crypto_gcm_setkey_result result ____cacheline_aligned;
struct scatterlist sg[1];
struct skcipher_request req;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 62dffa0028ac..bd03502094b5 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -3733,7 +3733,7 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}, {
- .alg = "rfc4543(gcm(aes))",
+ .alg = "rfc4543(gcm(aes))-disabled",
.test = alg_test_aead,
.suite = {
.aead = {
diff --git a/drivers/Kconfig b/drivers/Kconfig
index e1e2066cecdb..d393376de506 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -102,6 +102,8 @@ source "drivers/mmc/Kconfig"
source "drivers/memstick/Kconfig"
+source "drivers/mxc/Kconfig"
+
source "drivers/leds/Kconfig"
source "drivers/accessibility/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 7c3d58dcf6b3..c8784a267b7a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -125,6 +125,7 @@ obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
obj-y += mmc/
+obj-y += mxc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-$(CONFIG_NEW_LEDS) += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db208ae..3fccbed95ab2 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -55,6 +55,7 @@ enum {
enum ahci_imx_type {
AHCI_IMX53,
AHCI_IMX6Q,
+ AHCI_IMX6QP,
};
struct imx_ahci_priv {
@@ -69,6 +70,8 @@ struct imx_ahci_priv {
u32 phy_params;
};
+void *sg_io_buffer_hack;
+
static int ahci_imx_hotplug;
module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
@@ -231,7 +234,7 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
if (ret < 0)
goto disable_regulator;
- if (imxpriv->type == AHCI_IMX6Q) {
+ if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
/*
* set PHY Paremeters, two steps to configure the GPR13,
* one write for rest of parameters, mask of first write
@@ -255,12 +258,26 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
IMX6Q_GPR13_SATA_MPLL_CLK_EN);
usleep_range(100, 200);
+ }
+
+ if (imxpriv->type == AHCI_IMX6Q) {
ret = imx_sata_phy_reset(hpriv);
- if (ret) {
- dev_err(dev, "failed to reset phy: %d\n", ret);
- goto disable_clk;
- }
+ } else if (imxpriv->type == AHCI_IMX6QP) {
+ /* 6qp adds the sata reset mechanism, use it for 6qp sata */
+ regmap_update_bits(imxpriv->gpr, IOMUXC_GPR5,
+ BIT(10), 0);
+
+ regmap_update_bits(imxpriv->gpr, IOMUXC_GPR5,
+ BIT(11), 0);
+ udelay(50);
+ regmap_update_bits(imxpriv->gpr, IOMUXC_GPR5,
+ BIT(11), BIT(11));
+ }
+
+ if (ret) {
+ dev_err(dev, "failed to reset phy: %d\n", ret);
+ goto disable_clk;
}
usleep_range(1000, 2000);
@@ -282,7 +299,11 @@ static void imx_sata_disable(struct ahci_host_priv *hpriv)
if (imxpriv->no_device)
return;
- if (imxpriv->type == AHCI_IMX6Q) {
+ if (imxpriv->type == AHCI_IMX6QP)
+ regmap_update_bits(imxpriv->gpr, IOMUXC_GPR5,
+ BIT(10), BIT(10));
+
+ if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
IMX6Q_GPR13_SATA_MPLL_CLK_EN,
!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
@@ -336,7 +357,7 @@ static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
if (imxpriv->type == AHCI_IMX53)
ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline);
- else if (imxpriv->type == AHCI_IMX6Q)
+ else if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP)
ret = ahci_ops.softreset(link, class, deadline);
return ret;
@@ -359,6 +380,7 @@ static const struct ata_port_info ahci_imx_port_info = {
static const struct of_device_id imx_ahci_of_match[] = {
{ .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
{ .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
+ { .compatible = "fsl,imx6qp-ahci", .data = (void *)AHCI_IMX6QP },
{},
};
MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
@@ -566,7 +588,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
return PTR_ERR(imxpriv->ahb_clk);
}
- if (imxpriv->type == AHCI_IMX6Q) {
+ if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
u32 reg_value;
imxpriv->gpr = syscon_regmap_lookup_by_compatible(
@@ -622,6 +644,24 @@ static int imx_ahci_probe(struct platform_device *pdev)
reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
writel(reg_val, hpriv->mmio + IMX_TIMER1MS);
+ /*
+ * Due to IP bug on the Synopsis 3.00 SATA version,
+ * which is present on mx6q, and not on mx53,
+ * we should use sg_tablesize = 1 for reliable operation
+ */
+ if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
+ dma_addr_t dma;
+
+ ahci_platform_sht.sg_tablesize = 1;
+
+ sg_io_buffer_hack = dma_alloc_coherent(NULL, 0x10000,
+ &dma, GFP_KERNEL);
+ if (!sg_io_buffer_hack) {
+ ret = -ENOMEM;
+ goto disable_sata;
+ }
+ }
+
ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info,
&ahci_platform_sht);
if (ret)
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 0651010bba21..4a7032cbb3c1 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -154,6 +154,7 @@ config FW_LOADER_USER_HELPER
config FW_LOADER_USER_HELPER_FALLBACK
bool "Fallback user-helper invocation for firmware loading"
depends on FW_LOADER
+ default y
select FW_LOADER_USER_HELPER
help
This option enables / disables the invocation of user-helper
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 8c7d0f33bd53..2d59c2ec06e9 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -772,6 +772,8 @@ static int pm_genpd_suspend_noirq(struct device *dev)
if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
return 0;
+ pm_generic_suspend_noirq(dev);
+
if (genpd->dev_ops.stop && genpd->dev_ops.start) {
ret = pm_runtime_force_suspend(dev);
if (ret)
@@ -820,6 +822,8 @@ static int pm_genpd_resume_noirq(struct device *dev)
if (genpd->dev_ops.stop && genpd->dev_ops.start)
ret = pm_runtime_force_resume(dev);
+ pm_generic_resume_noirq(dev);
+
return ret;
}
@@ -1645,7 +1649,7 @@ EXPORT_SYMBOL_GPL(of_genpd_del_provider);
* Returns a valid pointer to struct generic_pm_domain on success or ERR_PTR()
* on failure.
*/
-static struct generic_pm_domain *genpd_get_from_provider(
+struct generic_pm_domain *genpd_get_from_provider(
struct of_phandle_args *genpdspec)
{
struct generic_pm_domain *genpd = ERR_PTR(-ENOENT);
@@ -1668,6 +1672,7 @@ static struct generic_pm_domain *genpd_get_from_provider(
return genpd;
}
+EXPORT_SYMBOL_GPL(genpd_get_from_provider);
/**
* of_genpd_add_device() - Add a device to an I/O PM domain
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 5189fd6182f6..400a297d2490 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -305,19 +305,15 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
goto err_free;
}
- if (clk_id == NULL)
- return ctx;
-
ctx->clk = clk_get(dev, clk_id);
- if (IS_ERR(ctx->clk)) {
- ret = PTR_ERR(ctx->clk);
- goto err_free;
- }
-
- ret = clk_prepare(ctx->clk);
- if (ret < 0) {
- clk_put(ctx->clk);
- goto err_free;
+ if (!IS_ERR(ctx->clk)) {
+ ret = clk_prepare(ctx->clk);
+ if (ret < 0) {
+ clk_put(ctx->clk);
+ goto err_free;
+ }
+ } else {
+ ctx->clk = NULL;
}
return ctx;
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 8453a49471d7..e4866ed3c3da 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -91,6 +91,21 @@ config BFIN_OTP_WRITE_ENABLE
If unsure, say N.
+config FSL_OTP
+ tristate "Freescale On-Chip OTP Memory Support"
+ depends on HAS_IOMEM && OF
+ help
+ If you say Y here, you will get support for a character device
+ interface into the One Time Programmable memory pages that are
+ stored on the some Freescale i.MX processors. This will not get
+ you access to the secure memory pages however. You will need to
+ write your own secure code and reader for that.
+
+ To compile this driver as a module, choose M here: the module
+ will be called fsl_otp.
+
+ If unsure, it is safe to say Y.
+
config PRINTER
tristate "Parallel printer support"
depends on PARPORT
@@ -593,5 +608,6 @@ config TILE_SROM
source "drivers/char/xillybus/Kconfig"
+source "drivers/char/imx_amp/Kconfig"
endmenu
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 6e6c244a66a0..4e34c9357a88 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o
obj-$(CONFIG_IBM_BSR) += bsr.o
obj-$(CONFIG_SGI_MBCS) += mbcs.o
obj-$(CONFIG_BFIN_OTP) += bfin-otp.o
+obj-$(CONFIG_FSL_OTP) += fsl_otp.o
obj-$(CONFIG_PRINTER) += lp.o
@@ -60,3 +61,4 @@ js-rtc-y = rtc.o
obj-$(CONFIG_TILE_SROM) += tile-srom.o
obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
+obj-$(CONFIG_HAVE_IMX_AMP) += imx_amp/
diff --git a/drivers/char/fsl_otp.c b/drivers/char/fsl_otp.c
new file mode 100644
index 000000000000..ebeb0fc0907d
--- /dev/null
+++ b/drivers/char/fsl_otp.c
@@ -0,0 +1,738 @@
+/*
+ * Freescale On-Chip OTP driver
+ *
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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 as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#define HW_OCOTP_CTRL 0x00000000
+#define HW_OCOTP_CTRL_SET 0x00000004
+#define BP_OCOTP_CTRL_WR_UNLOCK 16
+#define BM_OCOTP_CTRL_WR_UNLOCK 0xFFFF0000
+#define BM_OCOTP_CTRL_RELOAD_SHADOWS 0x00000400
+#define BM_OCOTP_CTRL_ERROR 0x00000200
+#define BM_OCOTP_CTRL_BUSY 0x00000100
+#define BP_OCOTP_CTRL_ADDR 0
+#define BM_OCOTP_CTRL_ADDR 0x0000007F
+#define BM_OCOTP_CTRL_ADDR_MX7D 0x0000000F
+#define BP_OCOTP_CTRL_ADDR_MX7ULP 0
+#define BM_OCOTP_CTRL_ADDR_MX7ULP 0x000000FF
+
+#define HW_OCOTP_TIMING 0x00000010
+#define BP_OCOTP_TIMING_STROBE_READ 16
+#define BM_OCOTP_TIMING_STROBE_READ 0x003F0000
+#define BP_OCOTP_TIMING_RELAX 12
+#define BM_OCOTP_TIMING_RELAX 0x0000F000
+#define BP_OCOTP_TIMING_STROBE_PROG 0
+#define BM_OCOTP_TIMING_STROBE_PROG 0x00000FFF
+
+#define BP_TIMING_FSOURCE 12
+#define BM_TIMING_FSOURCE 0x0007F000
+#define BV_TIMING_FSOURCE_NS 1001
+#define BP_TIMING_PROG 0
+#define BM_TIMING_PROG 0x00000FFF
+#define BV_TIMING_PROG_US 10
+
+#define HW_OCOTP_DATA 0x00000020
+
+#define HW_OCOTP_DATA0_MX7D 0x00000020
+#define HW_OCOTP_DATA1_MX7D 0x00000030
+#define HW_OCOTP_DATA2_MX7D 0x00000040
+#define HW_OCOTP_DATA3_MX7D 0x00000050
+
+#define HW_OCOTP_PDN_ULP 0x00000010
+#define HW_OCOTP_OUT_STATUS_ULP 0x00000090
+#define HW_OCOTP_OUT_STATUS_CLR_ULP 0x00000098
+
+#define BM_OUT_STATUS_DED_RELOAD_ULP (1 << 20)
+#define BM_OUT_STATUS_SEC_RELOAD_ULP (1 << 19)
+#define BM_OUT_STATUS_PROGFAIL (1 << 12)
+#define BM_OUT_STATUS_LOCKED (1 << 11)
+#define BM_OUT_STATUS_DED_ULP (1 << 10)
+
+#define HW_OCOTP_CUST_N(n) (0x00000400 + (n) * 0x10)
+#define BF(value, field) (((value) << BP_##field) & BM_##field)
+
+#define DEF_RELAX 20 /* > 16.5ns */
+
+#define BANK8(a, b, c, d, e, f, g, h) { \
+ "HW_OCOTP_"#a, "HW_OCOTP_"#b, "HW_OCOTP_"#c, "HW_OCOTP_"#d, \
+ "HW_OCOTP_"#e, "HW_OCOTP_"#f, "HW_OCOTP_"#g, "HW_OCOTP_"#h, \
+}
+
+#define BANK4(a, b, c, d) { \
+ "HW_OCOTP_"#a, "HW_OCOTP_"#b, "HW_OCOTP_"#c, "HW_OCOTP_"#d, \
+}
+
+static const char *imx6q_otp_desc[16][8] = {
+ BANK8(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6),
+ BANK8(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, ANA2),
+ BANK8(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
+ BANK8(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7),
+ BANK8(RESP0, HSJC_RESP1, MAC0, MAC1, HDCP_KSV0, HDCP_KSV1, GP1, GP2),
+ BANK8(DTCP_KEY0, DTCP_KEY1, DTCP_KEY2, DTCP_KEY3, DTCP_KEY4, MISC_CONF, FIELD_RETURN, SRK_REVOKE),
+ BANK8(HDCP_KEY0, HDCP_KEY1, HDCP_KEY2, HDCP_KEY3, HDCP_KEY4, HDCP_KEY5, HDCP_KEY6, HDCP_KEY7),
+ BANK8(HDCP_KEY8, HDCP_KEY9, HDCP_KEY10, HDCP_KEY11, HDCP_KEY12, HDCP_KEY13, HDCP_KEY14, HDCP_KEY15),
+ BANK8(HDCP_KEY16, HDCP_KEY17, HDCP_KEY18, HDCP_KEY19, HDCP_KEY20, HDCP_KEY21, HDCP_KEY22, HDCP_KEY23),
+ BANK8(HDCP_KEY24, HDCP_KEY25, HDCP_KEY26, HDCP_KEY27, HDCP_KEY28, HDCP_KEY29, HDCP_KEY30, HDCP_KEY31),
+ BANK8(HDCP_KEY32, HDCP_KEY33, HDCP_KEY34, HDCP_KEY35, HDCP_KEY36, HDCP_KEY37, HDCP_KEY38, HDCP_KEY39),
+ BANK8(HDCP_KEY40, HDCP_KEY41, HDCP_KEY42, HDCP_KEY43, HDCP_KEY44, HDCP_KEY45, HDCP_KEY46, HDCP_KEY47),
+ BANK8(HDCP_KEY48, HDCP_KEY49, HDCP_KEY50, HDCP_KEY51, HDCP_KEY52, HDCP_KEY53, HDCP_KEY54, HDCP_KEY55),
+ BANK8(HDCP_KEY56, HDCP_KEY57, HDCP_KEY58, HDCP_KEY59, HDCP_KEY60, HDCP_KEY61, HDCP_KEY62, HDCP_KEY63),
+ BANK8(HDCP_KEY64, HDCP_KEY65, HDCP_KEY66, HDCP_KEY67, HDCP_KEY68, HDCP_KEY69, HDCP_KEY70, HDCP_KEY71),
+ BANK8(CRC0, CRC1, CRC2, CRC3, CRC4, CRC5, CRC6, CRC7),
+};
+
+static const char *imx6sl_otp_desc[][8] = {
+ BANK8(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6),
+ BANK8(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, ANA2),
+ BANK8(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
+ BANK8(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7),
+ BANK8(SJC_RESP0, SJC_RESP1, MAC0, MAC1, CRC0, CRC1, GP1, GP2),
+ BANK8(SW_GP0, SW_GP1, SW_GP2, SW_GP3, SW_GP4, MISC_CONF, FIELD_RETURN, SRK_REVOKE),
+ BANK8(GP_LO0, GP_LO1, GP_LO2, GP_LO3, GP_LO4, GP_LO5, GP_LO6, GP_LO7),
+ BANK8(GP_HI0, GP_HI1, GP_HI2, GP_HI3, GP_HI4, GP_HI5, GP_HI6, GP_HI7),
+};
+
+static const char *imx6sll_otp_desc[][8] = {
+ BANK8(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6),
+ BANK8(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, USB),
+ BANK8(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
+ BANK8(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7),
+ BANK8(SJC_RESP0, SJC_RESP1, MAC0, MAC1, MAC2, CRC0, GP1, GP2),
+ BANK8(SW_GP0, SW_GP1, SW_GP2, SW_GP3, SW_GP4, MISC_CONF, FIELD_RETURN, SRK_REVOKE),
+ BANK8(ROM_PATCH0, ROM_PATCH1, ROM_PATCH2, ROM_PATCH3, ROM_PATCH4, ROM_PATCH5, ROM_PATCH6, ROM_PATCH7),
+ BANK8(GP30, GP31, GP32, GP33, GP40, GP41, GP42, GP43),
+};
+
+static const char *imx6ul_otp_desc[][8] = {
+ BANK8(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6),
+ BANK8(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, ANA2),
+ BANK8(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
+ BANK8(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7),
+ BANK8(SJC_RESP0, SJC_RESP1, MAC0, MAC1, MAC2, CRC, GP1, GP2),
+ BANK8(SW_GP0, SW_GP1, SW_GP2, SW_GP3, SW_GP4, MISC_CONF, FIELD_RETURN, SRK_REVOKE),
+ BANK8(ROM_PATCH0, ROM_PATCH1, ROM_PATCH2, ROM_PATCH3, ROM_PATCH4, ROM_PATCH5, ROM_PATCH6, ROM_PATCH7),
+ BANK8(ROM_PATCH8, ROM_PATCH9, ROM_PATCH10, ROM_PATCH11, ROM_PATCH12, ROM_PATCH13, ROM_PATCH14, ROM_PATCH15),
+ BANK8(GP30, GP31, GP32, GP33, GP34, GP35, GP36, GP37),
+ BANK8(GP38, GP39, GP310, GP311, GP312, GP313, GP314, GP315),
+ BANK8(GP40, GP41, GP42, GP43, GP44, GP45, GP46, GP47),
+ BANK8(GP48, GP49, GP410, GP411, GP412, GP413, GP414, GP415),
+ BANK8(GP50, GP51, GP52, GP53, GP54, GP55, GP56, GP57),
+ BANK8(GP58, GP59, GP510, GP511, GP512, GP513, GP514, GP515),
+ BANK8(GP60, GP61, GP62, GP63, GP64, GP65, GP66, GP67),
+ BANK8(GP70, GP71, GP72, GP73, GP80, GP81, GP82, GP83),
+};
+
+static const char *imx6ull_otp_desc[][8] = {
+ BANK8(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6),
+ BANK8(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, ANA2),
+ BANK8(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
+ BANK8(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7),
+ BANK8(SJC_RESP0, SJC_RESP1, MAC0, MAC1, MAC2, CRC, GP1, GP2),
+ BANK8(SW_GP0, SW_GP1, SW_GP2, SW_GP3, SW_GP4, MISC_CONF, FIELD_RETURN, SRK_REVOKE),
+ BANK8(ROM_PATCH0, ROM_PATCH1, ROM_PATCH2, ROM_PATCH3, ROM_PATCH4, ROM_PATCH5, ROM_PATCH6, ROM_PATCH7),
+ BANK8(GP30, GP31, GP32, GP33, GP40, GP41, GP42, GP43),
+};
+
+static const char *imx7d_otp_desc[][4] = {
+ BANK4(LOCK, TESTER0, TESTER1, TESTER2),
+ BANK4(TESTER3, TESTER4, TESTER5, BOOT_CFG0),
+ BANK4(BOOT_CFG1, BOOT_CFG2, BOOT_CFG3, BOOT_CFG4),
+ BANK4(MEM_TRIM0, MEM_TRIM1, ANA0, ANA1),
+ BANK4(OTPMK0, OTPMK1, OTPMK2, OTPMK3),
+ BANK4(OTPMK4, OTPMK5, OTPMK6, OTPMK7),
+ BANK4(SRK0, SRK1, SRK2, SRK3),
+ BANK4(SRK4, SRK5, SRK6, SRK7),
+ BANK4(SJC_RESP0, SJC_RESP1, USB_ID, FIELD_RETURN),
+ BANK4(MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, SRK_REVOKE),
+ BANK4(MAU_KEY0, MAU_KEY1, MAU_KEY2, MAU_KEY3),
+ BANK4(MAU_KEY4, MAU_KEY5, MAU_KEY6, MAU_KEY7),
+ BANK4(ROM_PATCH0, ROM_PATCH1, ROM_PATCH2, ROM_PATCH3),
+ BANK4(ROM_PATCH4, ROM_PATCH5, ROM_PATCH6, ROM_PATCH7),
+ BANK4(GP10, GP11, GP20, GP21),
+ BANK4(CRC_GP10, CRC_GP11, CRC_GP20, CRC_GP21),
+};
+
+static const char *imx7ulp_otp_desc[][8] = {
+ BANK8(TESTER0, TESTER1, TESTER2, TESTER3, TESTER4, TESTER5, TESTER6, TESTER7),
+ BANK8(LOCK0, LOCK1, LOCK2, CFG0, CFG1, CFG2, CFG3, CFG4),
+ BANK8(BOOT0, BOOT1, BOOT2, BOOT3, BOOT4, BOOT5, BOOT6, BOOT7),
+ BANK8(MEM0, MEM1, MEM2, MEM3, ANA0, ANA1, ANA2, ANA3),
+ BANK8(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
+ BANK8(A7_SRK0, A7_SRK1, A7_SRK2, A7_SRK3, A7_SRK4, A7_SRK5, A7_SRK6, A7_SRK7),
+ BANK8(M4_SRK0, M4_SRK1, M4_SRK2, M4_SRK3, M4_SRK4, M4_SRK5, M4_SRK6, M4_SRK7),
+ BANK8(SJC_RESP0, SJC_RESP1, GP0, GP1, GP2, GP3, GP4, GP5),
+ BANK8(MAU_KEY0, MAU_KEY1, MAU_KEY2, MAU_KEY3, MAU_KEY4, MAU_KEY5, MAU_KEY6, MAU_KEY7),
+ BANK8(TESTER10, TESTER11, TESTER12, TESTER13, TESTER14, TESTER15, FIELD_RETURN, SRK_REVOKE),
+ BANK8(PMU0, PMU1, PMU2, PMU3, PMU4, PMU5, PMU6, PMU7),
+ BANK8(A7_PATCH0, A7_PATCH1, A7_PATCH2, A7_PATCH3, A7_PATCH4, A7_PATCH5, A7_PATCH6, A7_PATCH7),
+ BANK8(A7_PATCH10, A7_PATCH11, A7_PATCH12, A7_PATCH13, A7_PATCH14, A7_PATCH15, A7_PATCH16, A7_PATCH17),
+ BANK8(A7_PATCH20, A7_PATCH21, A7_PATCH22, A7_PATCH23, A7_PATCH24, A7_PATCH25, A7_PATCH26, A7_PATCH27),
+ BANK8(A7_PATCH30, A7_PATCH31, A7_PATCH32, A7_PATCH33, A7_PATCH34, A7_PATCH35, A7_PATCH36, A7_PATCH37),
+ BANK8(GP10, GP11, GP12, GP13, GP14, GP15, GP16, GP17),
+ BANK8(GP20, GP21, GP22, GP23, GP24, GP25, GP26, GP27),
+ BANK8(GP30, GP31, GP32, GP33, GP34, GP35, GP36, GP37),
+ BANK8(GP40, GP41, GP42, GP43, GP44, GP45, GP46, GP47),
+ BANK8(GP50, GP51, GP52, GP53, GP54, GP55, GP56, GP57),
+ BANK8(M4_PATCH0, M4_PATCH1, M4_PATCH2, M4_PATCH3, M4_PATCH4, M4_PATCH5, M4_PATCH6, M4_PATCH7),
+ BANK8(M4_PATCH10, M4_PATCH11, M4_PATCH12, M4_PATCH13, M4_PATCH14, M4_PATCH15, M4_PATCH16, M4_PATCH17),
+ BANK8(M4_PATCH20, M4_PATCH21, M4_PATCH22, M4_PATCH23, M4_PATCH24, M4_PATCH25, M4_PATCH26, M4_PATCH27),
+ BANK8(M4_PATCH30, M4_PATCH31, M4_PATCH32, M4_PATCH33, M4_PATCH34, M4_PATCH35, M4_PATCH36, M4_PATCH37),
+ BANK8(GP60, GP61, GP62, GP63, GP64, GP65, GP66, GP67),
+ BANK8(GP70, GP71, GP72, GP73, GP74, GP75, GP76, GP77),
+ BANK8(GP80, GP81, GP82, GP83, GP84, GP85, GP86, GP87),
+ BANK8(GP90, GP91, GP92, GP93, GP94, GP95, GP96, GP97),
+ BANK8(TRIM0, TRIM1, TRIM2, TRIM3, TRIM4, TRIM5, TRIM6, TRIM7),
+ BANK8(OTFAD_KEY0, OTFAD_KEY1, OTFAD_KEY2, OTFAD_KEY3, OTFAD_CFG0, OTFAD_CFG1, OTFAD_CFG2, OTFAD_CFG3),
+ BANK8(CRC0, CRC1, CRC2, CRC3, CRC4, CRC5, CRC6, CRC7),
+};
+
+static DEFINE_MUTEX(otp_mutex);
+static void __iomem *otp_base;
+static struct clk *otp_clk;
+struct kobject *otp_kobj;
+struct kobj_attribute *otp_kattr;
+struct attribute_group *otp_attr_group;
+
+enum fsl_otp_devtype {
+ FSL_OTP_MX6Q,
+ FSL_OTP_MX6DL,
+ FSL_OTP_MX6SX,
+ FSL_OTP_MX6SL,
+ FSL_OTP_MX6SLL,
+ FSL_OTP_MX6UL,
+ FSL_OTP_MX6ULL,
+ FSL_OTP_MX7D,
+ FSL_OTP_MX7ULP,
+};
+
+struct fsl_otp_devtype_data {
+ enum fsl_otp_devtype devtype;
+ const char **bank_desc;
+ int fuse_nums;
+ void (*set_otp_timing)(void);
+};
+
+static struct fsl_otp_devtype_data *fsl_otp;
+
+/*
+ * fsl_otp_bank_physical and fsl_otp_word_physical are used to
+ * find the physical index of the word. Only used for calculating
+ * offset of the word, means only effective when reading fuse.
+ * Do not use the two functions for prog fuse. Always use the word
+ * index from fuse map to prog the fuse.
+ *
+ * Take i.MX6UL for example:
+ * there are holes between bank 5 and bank 6. The hole is 0x100 bytes.
+ * To bank 15, word 7, the word index is 15 * 8 + 7. The physical word
+ * index is 15 * 8 + 0x100 / 0x10 + 7, 0x100 contains 16 words.
+ * So use 15 * 8 + 7 to prog the fuse. And when reading, account the hole
+ * using offset 0x400 + (15 * 8 + 0x100 / 0x10 + 7) * 0x10.
+ *
+ * There is a hole in shadow registers address map of size 0x100
+ * between bank 5 and bank 6 on iMX6QP, iMX6DQ, iMX6SDL, iMX6SX and iMX6UL.
+ * Bank 5 ends at 0x6F0 and Bank 6 starts at 0x800. When reading the fuses,
+ * account for this hole in address space.
+ *
+ * Similar hole exists between bank 14 and bank 15 of size 0x80
+ * on iMX6QP, iMX6DQ, iMX6SDL, i.MX6SLL and iMX6SX.
+ * Note: iMX6SL has only 0-7 banks and there is no hole.
+ * Note: iMX6UL doesn't have this one.
+ *
+ * To i.MX6SLL, there are 9 banks. bank 7 and bank8 only contain 4 words
+ * each. Other banks contains 8 words.
+ */
+static u32 fsl_otp_bank_physical(struct fsl_otp_devtype_data *d, int bank)
+{
+ u32 phy_bank;
+
+ if ((bank == 0) || (d->devtype == FSL_OTP_MX6SL) ||
+ (d->devtype == FSL_OTP_MX7D) || (d->devtype == FSL_OTP_MX7ULP))
+ phy_bank = bank;
+ else if ((d->devtype == FSL_OTP_MX6UL) ||
+ (d->devtype == FSL_OTP_MX6ULL) ||
+ (d->devtype == FSL_OTP_MX6SLL)) {
+ if (bank >= 6)
+ phy_bank = fsl_otp_bank_physical(d, 5) + bank - 3;
+ else
+ phy_bank = bank;
+ } else {
+ if (bank >= 15)
+ phy_bank = fsl_otp_bank_physical(d, 14) + bank - 13;
+ else if (bank >= 6)
+ phy_bank = fsl_otp_bank_physical(d, 5) + bank - 3;
+ else
+ phy_bank = bank;
+ }
+
+ return phy_bank;
+}
+
+static u32 fsl_otp_word_physical(struct fsl_otp_devtype_data *d, int index)
+{
+ u32 phy_bank_off;
+ u32 word_off, bank_off;
+ u32 words_per_bank;
+
+ if (d->devtype == FSL_OTP_MX7D)
+ words_per_bank = 4;
+ else
+ words_per_bank = 8;
+
+ bank_off = index / words_per_bank;
+ word_off = index % words_per_bank;
+ phy_bank_off = fsl_otp_bank_physical(d, bank_off);
+
+ return phy_bank_off * words_per_bank + word_off;
+}
+
+static void imx6_set_otp_timing(void)
+{
+ unsigned long clk_rate = 0;
+ unsigned long strobe_read, relex, strobe_prog;
+ u32 timing = 0;
+
+ clk_rate = clk_get_rate(otp_clk);
+
+ /* do optimization for too many zeros */
+ relex = clk_rate / (1000000000 / DEF_RELAX) - 1;
+ strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1;
+ strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1;
+
+ timing = BF(relex, OCOTP_TIMING_RELAX);
+ timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ);
+ timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG);
+
+ __raw_writel(timing, otp_base + HW_OCOTP_TIMING);
+}
+
+static void imx7_set_otp_timing(void)
+{
+ unsigned long clk_rate;
+ u32 fsource, prog;
+ u32 timing = 0;
+ u32 reg;
+
+ clk_rate = clk_get_rate(otp_clk);
+
+ fsource = DIV_ROUND_UP((clk_rate / 1000) * BV_TIMING_FSOURCE_NS,
+ 1000000) + 1;
+ prog = DIV_ROUND_CLOSEST(clk_rate * BV_TIMING_PROG_US, 1000000) + 1;
+ timing = BF(fsource, TIMING_FSOURCE) | BF(prog, TIMING_PROG);
+ reg = __raw_readl(otp_base + HW_OCOTP_TIMING);
+ reg &= ~(BM_TIMING_FSOURCE | BM_TIMING_PROG);
+ reg |= timing;
+ __raw_writel(reg, otp_base + HW_OCOTP_TIMING);
+}
+
+static void imx7ulp_set_otp_timing(void)
+{
+ /* No need to setup timing for ULP */
+}
+
+static struct fsl_otp_devtype_data imx6q_data = {
+ .devtype = FSL_OTP_MX6Q,
+ .bank_desc = (const char **)imx6q_otp_desc,
+ .fuse_nums = 16 * 8,
+ .set_otp_timing = imx6_set_otp_timing,
+};
+
+static struct fsl_otp_devtype_data imx6sl_data = {
+ .devtype = FSL_OTP_MX6SL,
+ .bank_desc = (const char **)imx6sl_otp_desc,
+ .fuse_nums = 8 * 8,
+ .set_otp_timing = imx6_set_otp_timing,
+};
+
+static struct fsl_otp_devtype_data imx6sll_data = {
+ .devtype = FSL_OTP_MX6SLL,
+ .bank_desc = (const char **)imx6sll_otp_desc,
+ /* Bank 7 and Bank 8 are 4 words each */
+ .fuse_nums = 8 * 8,
+ .set_otp_timing = imx6_set_otp_timing,
+};
+
+static struct fsl_otp_devtype_data imx6ul_data = {
+ .devtype = FSL_OTP_MX6UL,
+ .bank_desc = (const char **)imx6ul_otp_desc,
+ .fuse_nums = 16 * 8,
+ .set_otp_timing = imx6_set_otp_timing,
+};
+
+static struct fsl_otp_devtype_data imx6ull_data = {
+ .devtype = FSL_OTP_MX6ULL,
+ .bank_desc = (const char **)imx6ull_otp_desc,
+ /* Bank 7 and Bank 8 are 4 words each */
+ .fuse_nums = 8 * 8,
+ .set_otp_timing = imx6_set_otp_timing,
+};
+
+static struct fsl_otp_devtype_data imx7d_data = {
+ .devtype = FSL_OTP_MX7D,
+ .bank_desc = (const char **)imx7d_otp_desc,
+ .fuse_nums = 16 * 4,
+ .set_otp_timing = imx7_set_otp_timing,
+};
+
+static struct fsl_otp_devtype_data imx7ulp_data = {
+ .devtype = FSL_OTP_MX7ULP,
+ .bank_desc = (const char **)imx7ulp_otp_desc,
+ .fuse_nums = 31 * 8,
+ .set_otp_timing = imx7ulp_set_otp_timing,
+};
+
+static int otp_wait_busy(u32 flags)
+{
+ int count;
+ u32 c;
+
+ for (count = 10000; count >= 0; count--) {
+ c = __raw_readl(otp_base + HW_OCOTP_CTRL);
+ if (!(c & (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR | flags)))
+ break;
+ cpu_relax();
+ }
+
+ if (count < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static ssize_t fsl_otp_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ unsigned int index = attr - otp_kattr;
+ unsigned int phy_index;
+ u32 value = 0;
+ int ret;
+
+ if (!fsl_otp)
+ return -ENODEV;
+
+ ret = clk_prepare_enable(otp_clk);
+ if (ret)
+ return -ENODEV;
+
+ mutex_lock(&otp_mutex);
+
+ phy_index = fsl_otp_word_physical(fsl_otp, index);
+ fsl_otp->set_otp_timing();
+ ret = otp_wait_busy(0);
+ if (ret)
+ goto out;
+
+ if (fsl_otp->devtype == FSL_OTP_MX7ULP) {
+ value = __raw_readl(otp_base + HW_OCOTP_OUT_STATUS_ULP);
+ if (value & BM_OUT_STATUS_DED_ULP) {
+ __raw_writel(BM_OUT_STATUS_DED_ULP, otp_base + HW_OCOTP_OUT_STATUS_CLR_ULP);
+ goto out;
+ }
+ }
+
+ value = __raw_readl(otp_base + HW_OCOTP_CUST_N(phy_index));
+
+ if (fsl_otp->devtype == FSL_OTP_MX7ULP) {
+ __raw_writel(1, otp_base + HW_OCOTP_PDN_ULP);
+ }
+
+out:
+ mutex_unlock(&otp_mutex);
+ clk_disable_unprepare(otp_clk);
+ return ret ? 0 : sprintf(buf, "0x%x\n", value);
+}
+
+static int imx6_otp_write_bits(int addr, u32 data, u32 magic)
+{
+ u32 c; /* for control register */
+
+ /* init the control register */
+ c = __raw_readl(otp_base + HW_OCOTP_CTRL);
+ c &= ~BM_OCOTP_CTRL_ADDR;
+ c |= BF(addr, OCOTP_CTRL_ADDR);
+ c |= BF(magic, OCOTP_CTRL_WR_UNLOCK);
+ __raw_writel(c, otp_base + HW_OCOTP_CTRL);
+
+ /* init the data register */
+ __raw_writel(data, otp_base + HW_OCOTP_DATA);
+ otp_wait_busy(0);
+
+ mdelay(2); /* Write Postamble */
+
+ return 0;
+}
+
+static int imx7ulp_otp_write_bits(int addr, u32 data, u32 magic)
+{
+ u32 c; /* for control register */
+
+ /* init the control register */
+ c = __raw_readl(otp_base + HW_OCOTP_CTRL);
+ c &= ~BM_OCOTP_CTRL_ADDR_MX7ULP;
+ c |= BF(addr, OCOTP_CTRL_ADDR_MX7ULP);
+ c |= BF(magic, OCOTP_CTRL_WR_UNLOCK);
+ __raw_writel(c, otp_base + HW_OCOTP_CTRL);
+
+ /* init the data register */
+ __raw_writel(data, otp_base + HW_OCOTP_DATA);
+ otp_wait_busy(0);
+
+ mdelay(2); /* Write Postamble */
+
+ return 0;
+}
+
+static int imx7_otp_write_bits(int addr, u32 data, u32 magic)
+{
+ u32 c; /* for control register */
+
+ /* init the control register */
+ c = __raw_readl(otp_base + HW_OCOTP_CTRL);
+ c &= ~BM_OCOTP_CTRL_ADDR_MX7D;
+ /* convert to bank address */
+ c |= BF((addr >> 2), OCOTP_CTRL_ADDR);
+ c |= BF(magic, OCOTP_CTRL_WR_UNLOCK);
+ __raw_writel(c, otp_base + HW_OCOTP_CTRL);
+
+ /* init the data register */
+ switch (addr & 0x3) {
+ case 0:
+ __raw_writel(0, otp_base + HW_OCOTP_DATA1_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA2_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA3_MX7D);
+ __raw_writel(data, otp_base + HW_OCOTP_DATA0_MX7D);
+ break;
+ case 1:
+ __raw_writel(data, otp_base + HW_OCOTP_DATA1_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA2_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA3_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA0_MX7D);
+ break;
+ case 2:
+ __raw_writel(0, otp_base + HW_OCOTP_DATA1_MX7D);
+ __raw_writel(data, otp_base + HW_OCOTP_DATA2_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA3_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA0_MX7D);
+ break;
+ case 3:
+ __raw_writel(0, otp_base + HW_OCOTP_DATA1_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA2_MX7D);
+ __raw_writel(data, otp_base + HW_OCOTP_DATA3_MX7D);
+ __raw_writel(0, otp_base + HW_OCOTP_DATA0_MX7D);
+ break;
+ }
+ __raw_writel(data, otp_base + HW_OCOTP_DATA);
+ otp_wait_busy(0);
+
+ mdelay(2); /* Write Postamble */
+
+ return 0;
+
+}
+
+static ssize_t fsl_otp_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int index = attr - otp_kattr;
+ unsigned int phy_index;
+ unsigned long value;
+ unsigned long tmp;
+ int ret;
+
+ if (!fsl_otp)
+ return -ENODEV;
+
+ ret = kstrtoul(buf, 16, &value);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = clk_prepare_enable(otp_clk);
+ if (ret)
+ return -ENODEV;
+
+ mutex_lock(&otp_mutex);
+
+ phy_index = fsl_otp_word_physical(fsl_otp, index);
+ if ((fsl_otp->devtype == FSL_OTP_MX7ULP) && (phy_index > 15)) {
+ fsl_otp->set_otp_timing();
+ ret = otp_wait_busy(0);
+ if (ret)
+ goto out;
+
+ tmp = __raw_readl(otp_base + HW_OCOTP_OUT_STATUS_ULP);
+ if (tmp & BM_OUT_STATUS_DED_ULP) {
+ __raw_writel(BM_OUT_STATUS_DED_ULP, otp_base + HW_OCOTP_OUT_STATUS_CLR_ULP);
+ goto out;
+ }
+
+ tmp = __raw_readl(otp_base + HW_OCOTP_CUST_N(phy_index));
+
+ __raw_writel(1, otp_base + HW_OCOTP_PDN_ULP);
+
+ if (tmp != 0) {
+ ret = -EPERM;
+ goto out;
+ }
+ }
+
+ fsl_otp->set_otp_timing();
+ ret = otp_wait_busy(0);
+ if (ret)
+ goto out;
+
+ if (fsl_otp->devtype == FSL_OTP_MX7D)
+ imx7_otp_write_bits(index, value, 0x3e77);
+ else if (fsl_otp->devtype == FSL_OTP_MX7ULP)
+ imx7ulp_otp_write_bits(index, value, 0x3e77);
+ else
+ imx6_otp_write_bits(index, value, 0x3e77);
+
+ if (fsl_otp->devtype == FSL_OTP_MX7ULP) {
+ value = __raw_readl(otp_base + HW_OCOTP_OUT_STATUS_ULP);
+ if (value & (BM_OUT_STATUS_LOCKED | BM_OUT_STATUS_PROGFAIL))
+ printk("ulp prog fail\n");
+
+ otp_wait_busy(0);
+ }
+
+ /* Reload all the shadow registers */
+ __raw_writel(BM_OCOTP_CTRL_RELOAD_SHADOWS,
+ otp_base + HW_OCOTP_CTRL_SET);
+ udelay(1);
+ otp_wait_busy(BM_OCOTP_CTRL_RELOAD_SHADOWS);
+
+ if (fsl_otp->devtype == FSL_OTP_MX7ULP) {
+ __raw_writel(1, otp_base + HW_OCOTP_PDN_ULP);
+ }
+
+out:
+ mutex_unlock(&otp_mutex);
+ clk_disable_unprepare(otp_clk);
+ return ret ? ret : count;
+}
+
+static const struct of_device_id fsl_otp_dt_ids[] = {
+ { .compatible = "fsl,imx6q-ocotp", .data = (void *)&imx6q_data, },
+ { .compatible = "fsl,imx6sl-ocotp", .data = (void *)&imx6sl_data, },
+ { .compatible = "fsl,imx6sll-ocotp", .data = (void *)&imx6sll_data, },
+ { .compatible = "fsl,imx6ul-ocotp", .data = (void *)&imx6ul_data, },
+ { .compatible = "fsl,imx6ull-ocotp", .data = (void *)&imx6ull_data, },
+ { .compatible = "fsl,imx7d-ocotp", .data = (void *)&imx7d_data, },
+ { .compatible = "fsl,imx7ulp-ocotp", .data = (void *)&imx7ulp_data, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_otp_dt_ids);
+
+static int fsl_otp_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct attribute **attrs;
+ const char **desc;
+ int i, num;
+ int ret;
+ const struct of_device_id *of_id =
+ of_match_device(fsl_otp_dt_ids, &pdev->dev);
+
+ fsl_otp = (struct fsl_otp_devtype_data *)of_id->data;
+ if (!fsl_otp) {
+ dev_err(&pdev->dev, "No driver data provided!\n");
+ return -ENODEV;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ otp_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(otp_base)) {
+ ret = PTR_ERR(otp_base);
+ dev_err(&pdev->dev, "failed to ioremap resource: %d\n", ret);
+ return ret;
+ }
+
+ otp_clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(otp_clk)) {
+ ret = PTR_ERR(otp_clk);
+ dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
+ return ret;
+ }
+
+ desc = fsl_otp->bank_desc;
+ num = fsl_otp->fuse_nums;
+
+ /* The last one is NULL, which is used to detect the end */
+ attrs = devm_kzalloc(&pdev->dev, (num + 1) * sizeof(*attrs),
+ GFP_KERNEL);
+ otp_kattr = devm_kzalloc(&pdev->dev, num * sizeof(*otp_kattr),
+ GFP_KERNEL);
+ otp_attr_group = devm_kzalloc(&pdev->dev, sizeof(*otp_attr_group),
+ GFP_KERNEL);
+ if (!attrs || !otp_kattr || !otp_attr_group)
+ return -ENOMEM;
+
+ for (i = 0; i < num; i++) {
+ sysfs_attr_init(&otp_kattr[i].attr);
+ otp_kattr[i].attr.name = desc[i];
+ otp_kattr[i].attr.mode = 0600;
+ otp_kattr[i].show = fsl_otp_show;
+ otp_kattr[i].store = fsl_otp_store;
+ attrs[i] = &otp_kattr[i].attr;
+ }
+ otp_attr_group->attrs = attrs;
+
+ otp_kobj = kobject_create_and_add("fsl_otp", NULL);
+ if (!otp_kobj) {
+ dev_err(&pdev->dev, "failed to add kobject\n");
+ return -ENOMEM;
+ }
+
+ ret = sysfs_create_group(otp_kobj, otp_attr_group);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to create sysfs group: %d\n", ret);
+ kobject_put(otp_kobj);
+ return ret;
+ }
+
+ mutex_init(&otp_mutex);
+
+ return 0;
+}
+
+static int fsl_otp_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(otp_kobj, otp_attr_group);
+ kobject_put(otp_kobj);
+
+ return 0;
+}
+
+static struct platform_driver fsl_otp_driver = {
+ .driver = {
+ .name = "imx-ocotp",
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_otp_dt_ids,
+ },
+ .probe = fsl_otp_probe,
+ .remove = fsl_otp_remove,
+};
+module_platform_driver(fsl_otp_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Huang Shijie <b32955@freescale.com>");
+MODULE_DESCRIPTION("Freescale i.MX OCOTP driver");
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 200dab5136a7..7969d2f36a14 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -255,6 +255,18 @@ config HW_RANDOM_MXC_RNGA
If unsure, say Y.
+config HW_RANDOM_IMX_RNG
+ tristate "Freescale RNG B/C Random Number Generator"
+ depends on HW_RANDOM && ARCH_MXC && HAVE_IMX_RNG
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator (RNGBB and RNGC) hardware found on Freescale i.MX processors.
+
+ To compile this driver as a module, choose M here: the
+ module will be called fsl-rngc.
+
+ If unsure, say Y.
+
config HW_RANDOM_NOMADIK
tristate "ST-Ericsson Nomadik Random Number Generator support"
depends on ARCH_NOMADIK
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 5f52b1e4e7be..d9d76206788e 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
+obj-$(CONFIG_HW_RANDOM_IMX_RNG) += imx-rng.o
obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
diff --git a/drivers/char/hw_random/imx-rng.c b/drivers/char/hw_random/imx-rng.c
new file mode 100644
index 000000000000..df9c13f7d325
--- /dev/null
+++ b/drivers/char/hw_random/imx-rng.c
@@ -0,0 +1,440 @@
+/*
+ * RNG driver for Freescale RNG B/C
+ *
+ * Copyright (C) 2008-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
+ */
+
+/*
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/interrupt.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME "imx-rng"
+
+#define RNGC_VERSION_MAJOR3 3
+
+#define RNGC_VERSION_ID 0x0000
+#define RNGC_COMMAND 0x0004
+#define RNGC_CONTROL 0x0008
+#define RNGC_STATUS 0x000C
+#define RNGC_ERROR 0x0010
+#define RNGC_FIFO 0x0014
+#define RNGC_VERIF_CTRL 0x0020
+#define RNGC_OSC_CTRL_COUNT 0x0028
+#define RNGC_OSC_COUNT 0x002C
+#define RNGC_OSC_COUNT_STATUS 0x0030
+
+#define RNGC_VERID_ZEROS_MASK 0x0f000000
+#define RNGC_VERID_RNG_TYPE_MASK 0xf0000000
+#define RNGC_VERID_RNG_TYPE_SHIFT 28
+#define RNGC_VERID_CHIP_VERSION_MASK 0x00ff0000
+#define RNGC_VERID_CHIP_VERSION_SHIFT 16
+#define RNGC_VERID_VERSION_MAJOR_MASK 0x0000ff00
+#define RNGC_VERID_VERSION_MAJOR_SHIFT 8
+#define RNGC_VERID_VERSION_MINOR_MASK 0x000000ff
+#define RNGC_VERID_VERSION_MINOR_SHIFT 0
+
+#define RNGC_CMD_ZEROS_MASK 0xffffff8c
+#define RNGC_CMD_SW_RST 0x00000040
+#define RNGC_CMD_CLR_ERR 0x00000020
+#define RNGC_CMD_CLR_INT 0x00000010
+#define RNGC_CMD_SEED 0x00000002
+#define RNGC_CMD_SELF_TEST 0x00000001
+
+#define RNGC_CTRL_ZEROS_MASK 0xfffffc8c
+#define RNGC_CTRL_CTL_ACC 0x00000200
+#define RNGC_CTRL_VERIF_MODE 0x00000100
+#define RNGC_CTRL_MASK_ERROR 0x00000040
+
+#define RNGC_CTRL_MASK_DONE 0x00000020
+#define RNGC_CTRL_AUTO_SEED 0x00000010
+#define RNGC_CTRL_FIFO_UFLOW_MASK 0x00000003
+#define RNGC_CTRL_FIFO_UFLOW_SHIFT 0
+
+#define RNGC_CTRL_FIFO_UFLOW_ZEROS_ERROR 0
+#define RNGC_CTRL_FIFO_UFLOW_ZEROS_ERROR2 1
+#define RNGC_CTRL_FIFO_UFLOW_BUS_XFR 2
+#define RNGC_CTRL_FIFO_UFLOW_ZEROS_INTR 3
+
+#define RNGC_STATUS_ST_PF_MASK 0x00c00000
+#define RNGC_STATUS_ST_PF_SHIFT 22
+#define RNGC_STATUS_ST_PF_TRNG 0x00800000
+#define RNGC_STATUS_ST_PF_PRNG 0x00400000
+#define RNGC_STATUS_ERROR 0x00010000
+#define RNGC_STATUS_FIFO_SIZE_MASK 0x0000f000
+#define RNGC_STATUS_FIFO_SIZE_SHIFT 12
+#define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00
+#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8
+#define RNGC_STATUS_NEXT_SEED_DONE 0x00000040
+#define RNGC_STATUS_SEED_DONE 0x00000020
+#define RNGC_STATUS_ST_DONE 0x00000010
+#define RNGC_STATUS_RESEED 0x00000008
+#define RNGC_STATUS_SLEEP 0x00000004
+#define RNGC_STATUS_BUSY 0x00000002
+#define RNGC_STATUS_SEC_STATE 0x00000001
+
+#define RNGC_ERROR_STATUS_ZEROS_MASK 0xffffffc0
+#define RNGC_ERROR_STATUS_BAD_KEY 0x00000040
+#define RNGC_ERROR_STATUS_RAND_ERR 0x00000020
+#define RNGC_ERROR_STATUS_FIFO_ERR 0x00000010
+#define RNGC_ERROR_STATUS_STAT_ERR 0x00000008
+#define RNGC_ERROR_STATUS_ST_ERR 0x00000004
+#define RNGC_ERROR_STATUS_OSC_ERR 0x00000002
+#define RNGC_ERROR_STATUS_LFSR_ERR 0x00000001
+
+#define RNG_ADDR_RANGE 0x34
+
+static DECLARE_COMPLETION(rng_self_testing);
+static DECLARE_COMPLETION(rng_seed_done);
+
+static struct platform_device *imx_rng_dev;
+
+struct imx_rng_priv_data {
+ void __iomem *reg_base;
+};
+
+int irq_rng;
+
+static int imx_rng_data_present(struct hwrng *rng, int wait)
+{
+ int level;
+ struct imx_rng_priv_data *prv = (struct imx_rng_priv_data *)rng->priv;
+
+ /* how many random numbers are in FIFO? [0-16] */
+ level = (readl(prv->reg_base + RNGC_STATUS) &
+ RNGC_STATUS_FIFO_LEVEL_MASK) >> RNGC_STATUS_FIFO_LEVEL_SHIFT;
+
+ return level > 0 ? 1 : 0;
+}
+
+static int imx_rng_data_read(struct hwrng *rng, u32 *data)
+{
+ int err;
+ struct imx_rng_priv_data *prv = (struct imx_rng_priv_data *)rng->priv;
+
+ /* retrieve a random number from FIFO */
+ *data = readl(prv->reg_base + RNGC_FIFO);
+
+ /* is there some error while reading this random number? */
+ err = readl(prv->reg_base + RNGC_STATUS) & RNGC_STATUS_ERROR;
+
+ /* if error happened doesn't return random number */
+ return err ? 0 : 4;
+}
+
+static irqreturn_t imx_rng_irq(int irq, void *dev)
+{
+ int handled = 0;
+ struct imx_rng_priv_data *prv = (struct imx_rng_priv_data *)dev;
+
+ /* is the seed creation done? */
+ if (readl(prv->reg_base + RNGC_STATUS) & RNGC_STATUS_SEED_DONE) {
+ complete(&rng_seed_done);
+ writel(RNGC_CMD_CLR_INT | RNGC_CMD_CLR_ERR,
+ prv->reg_base + RNGC_COMMAND);
+ handled = 1;
+ }
+
+ /* is the self test done? */
+ if (readl(prv->reg_base + RNGC_STATUS) & RNGC_STATUS_ST_DONE) {
+ complete(&rng_self_testing);
+ writel(RNGC_CMD_CLR_INT | RNGC_CMD_CLR_ERR,
+ prv->reg_base + RNGC_COMMAND);
+ handled = 1;
+ }
+
+ /* is there any error? */
+ if (readl(prv->reg_base + RNGC_STATUS) & RNGC_STATUS_ERROR) {
+ /* clear interrupt */
+ writel(RNGC_CMD_CLR_INT | RNGC_CMD_CLR_ERR,
+ prv->reg_base + RNGC_COMMAND);
+ handled = 1;
+ }
+
+ return handled;
+}
+
+static int imx_rng_init(struct hwrng *rng)
+{
+ int err;
+ struct imx_rng_priv_data *prv = (struct imx_rng_priv_data *)rng->priv;
+ u32 cmd, ctrl, osc;
+
+ reinit_completion(&rng_self_testing);
+ reinit_completion(&rng_seed_done);
+
+ err = readl(prv->reg_base + RNGC_STATUS) & RNGC_STATUS_ERROR;
+ if (err) {
+ /* is this a bad keys error ? */
+ if (readl(prv->reg_base + RNGC_ERROR) &
+ RNGC_ERROR_STATUS_BAD_KEY) {
+ dev_err(&imx_rng_dev->dev, "Can't start, Bad Keys.\n");
+ return -EIO;
+ }
+ }
+
+ /* mask all interrupts, will be unmasked soon */
+ ctrl = readl(prv->reg_base + RNGC_CONTROL);
+ writel(ctrl | RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR,
+ prv->reg_base + RNGC_CONTROL);
+
+ /* verify if oscillator is working */
+ osc = readl(prv->reg_base + RNGC_ERROR);
+ if (osc & RNGC_ERROR_STATUS_OSC_ERR) {
+ dev_err(&imx_rng_dev->dev, "RNGC Oscillator is dead!\n");
+ return -EIO;
+ }
+
+ err = request_irq(irq_rng, imx_rng_irq,
+ 0, "imx-rng", (void *)rng->priv);
+ if (err) {
+ dev_err(&imx_rng_dev->dev, "Can't get interrupt working.\n");
+ return -EIO;
+ }
+
+ /* do self test, repeat until get success */
+ do {
+ /* clear error */
+ cmd = readl(prv->reg_base + RNGC_COMMAND);
+ writel(cmd | RNGC_CMD_CLR_ERR, prv->reg_base + RNGC_COMMAND);
+
+ /* unmask all interrupt */
+ ctrl = readl(prv->reg_base + RNGC_CONTROL);
+ writel(ctrl & ~(RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR),
+ prv->reg_base + RNGC_CONTROL);
+
+ /* run self test */
+ cmd = readl(prv->reg_base + RNGC_COMMAND);
+ writel(cmd | RNGC_CMD_SELF_TEST,
+ prv->reg_base + RNGC_COMMAND);
+
+ wait_for_completion(&rng_self_testing);
+
+ } while (readl(prv->reg_base + RNGC_ERROR) &
+ RNGC_ERROR_STATUS_ST_ERR);
+
+ /* clear interrupt. Is it really necessary here? */
+ writel(RNGC_CMD_CLR_INT | RNGC_CMD_CLR_ERR,
+ prv->reg_base + RNGC_COMMAND);
+
+ /* create seed, repeat while there is some statistical error */
+ do {
+ /* clear error */
+ cmd = readl(prv->reg_base + RNGC_COMMAND);
+ writel(cmd | RNGC_CMD_CLR_ERR, prv->reg_base + RNGC_COMMAND);
+
+ /* seed creation */
+ cmd = readl(prv->reg_base + RNGC_COMMAND);
+ writel(cmd | RNGC_CMD_SEED, prv->reg_base + RNGC_COMMAND);
+
+ wait_for_completion(&rng_seed_done);
+
+ } while (readl(prv->reg_base + RNGC_ERROR) &
+ RNGC_ERROR_STATUS_STAT_ERR);
+
+ err = readl(prv->reg_base + RNGC_ERROR) &
+ (RNGC_ERROR_STATUS_STAT_ERR |
+ RNGC_ERROR_STATUS_RAND_ERR |
+ RNGC_ERROR_STATUS_FIFO_ERR |
+ RNGC_ERROR_STATUS_ST_ERR |
+ RNGC_ERROR_STATUS_OSC_ERR |
+ RNGC_ERROR_STATUS_LFSR_ERR);
+
+ if (err) {
+ dev_err(&imx_rng_dev->dev, "iMX RNG appears inoperable.\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static struct hwrng imx_rng = {
+ .name = "imx-rng",
+ .init = imx_rng_init,
+ .data_present = imx_rng_data_present,
+ .data_read = imx_rng_data_read
+};
+
+static int __init imx_rng_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct clk *clk;
+ struct imx_rng_priv_data *priv;
+ int err = -ENODEV;
+
+ if (imx_rng_dev)
+ return -EBUSY;
+
+ /* Enable the clock */
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ dev_err(dev, "Can not get clock.\n");
+ return PTR_ERR(clk);
+ }
+ clk_enable(clk);
+
+ /* Allocate private data memory */
+ priv = kzalloc(sizeof(struct imx_rng_priv_data), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ imx_rng.priv = (unsigned long)priv;
+ dev_set_drvdata(dev, priv);
+
+ /* ioremap that register space */
+ priv->reg_base = of_iomap(np, 0);
+ if (!priv->reg_base) {
+ kfree(priv);
+ dev_err(dev, "Failed to remap register space.\n");
+ return -ENODEV;
+ }
+
+ irq_rng = platform_get_irq(pdev, 0);
+
+ err = hwrng_register(&imx_rng);
+ if (err) {
+ iounmap(priv->reg_base);
+ kfree(priv);
+ dev_err(dev, "failed to register hwrng (%d)\n", err);
+ return err;
+ }
+
+ imx_rng_dev = pdev;
+ dev_info(dev, "iMX RNG Registered.\n");
+
+ return 0;
+}
+
+static int __exit imx_rng_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct clk *clk;
+ struct imx_rng_priv_data *priv = dev_get_drvdata(dev);
+
+ /* Disable the clock */
+ clk = of_clk_get(np, 0);
+
+ if (IS_ERR(clk))
+ dev_err(dev, "Can not get clock.\n");
+ else
+ clk_disable(clk);
+
+ hwrng_unregister(&imx_rng);
+
+ iounmap(priv->reg_base);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static int imx_rng_suspend(struct platform_device *pdev, pm_message_t state)
+{
+#ifdef CONFIG_PM
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct clk *clk = of_clk_get(np, 0);
+
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Can not get rng_clk\n");
+ return PTR_ERR(clk);
+ }
+
+ clk_disable(clk);
+#endif
+
+ return 0;
+}
+
+static int imx_rng_resume(struct platform_device *pdev)
+{
+#ifdef CONFIG_PM
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct clk *clk = of_clk_get(np, 0);
+
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Can not get rng_clk\n");
+ return PTR_ERR(clk);
+ }
+
+ clk_enable(clk);
+#endif
+
+ return 0;
+}
+
+static struct of_device_id imx_rng_dt_ids[] = {
+ { .compatible = "imx-rng",},
+ { .compatible = "fsl,imx-rng",},
+ { .compatible = "fsl,imx6sl-rng",},
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, imx_rng_dt_ids);
+
+static struct platform_driver imx_rng_driver = {
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = imx_rng_dt_ids,
+ },
+ .remove = __exit_p(imx_rng_remove),
+ .suspend = imx_rng_suspend,
+ .resume = imx_rng_resume,
+};
+
+static int __init mod_init(void)
+{
+ return platform_driver_probe(&imx_rng_driver, imx_rng_probe);
+}
+
+static void __exit mod_exit(void)
+{
+ platform_driver_unregister(&imx_rng_driver);
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("H/W RNG(B/C) driver for i.MX");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/imx_amp/Kconfig b/drivers/char/imx_amp/Kconfig
new file mode 100644
index 000000000000..1f892f8daccb
--- /dev/null
+++ b/drivers/char/imx_amp/Kconfig
@@ -0,0 +1,9 @@
+#
+# imx mcc
+#
+
+config IMX_SEMA4
+ bool "IMX SEMA4 driver"
+ depends on SOC_IMX6SX
+ help
+ Support for IMX SEMA4 driver, most people should say N here.
diff --git a/drivers/char/imx_amp/Makefile b/drivers/char/imx_amp/Makefile
new file mode 100644
index 000000000000..4e7a91691b39
--- /dev/null
+++ b/drivers/char/imx_amp/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for imx mcc
+#
+#
+obj-$(CONFIG_IMX_SEMA4) += imx_sema4.o
diff --git a/drivers/char/imx_amp/imx_sema4.c b/drivers/char/imx_amp/imx_sema4.c
new file mode 100644
index 000000000000..412202f11cbb
--- /dev/null
+++ b/drivers/char/imx_amp/imx_sema4.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2014 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/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/imx_sema4.h>
+
+static struct imx_sema4_mutex_device *imx6_sema4;
+
+/*!
+ * \brief mutex create function.
+ *
+ * This function allocates imx_sema4_mutex structure and returns a handle
+ * to it. The mutex to be created is identified by SEMA4 device number and mutex
+ * (gate) number. The handle is used to reference the created mutex in calls to
+ * other imx_sema4_mutex API functions. This function is to be called only
+ * once for each mutex.
+ *
+ * \param[in] dev_num SEMA4 device (module) number.
+ * \param[in] mutex_num Mutex (gate) number.
+ *
+ * \return NULL (Failure.)
+ * \return imx_sema4_mutex (Success.)
+ */
+struct imx_sema4_mutex *
+imx_sema4_mutex_create(u32 dev_num, u32 mutex_num)
+{
+ struct imx_sema4_mutex *mutex_ptr = NULL;
+
+ if (mutex_num >= SEMA4_NUM_GATES || dev_num >= SEMA4_NUM_DEVICES)
+ goto out;
+
+ if (imx6_sema4->cpine_val & (1 < mutex_num)) {
+ pr_err("Error: requiring a allocated sema4.\n");
+ pr_err("mutex_num %d cpine_val 0x%08x.\n",
+ mutex_num, imx6_sema4->cpine_val);
+ }
+ mutex_ptr = kzalloc(sizeof(*mutex_ptr), GFP_KERNEL);
+ if (!mutex_ptr)
+ goto out;
+ imx6_sema4->mutex_ptr[mutex_num] = mutex_ptr;
+ imx6_sema4->alloced |= 1 < mutex_num;
+ imx6_sema4->cpine_val |= idx_sema4[mutex_num];
+ writew(imx6_sema4->cpine_val, imx6_sema4->ioaddr + SEMA4_CP0INE);
+
+ mutex_ptr->valid = CORE_MUTEX_VALID;
+ mutex_ptr->gate_num = mutex_num;
+ init_waitqueue_head(&mutex_ptr->wait_q);
+
+out:
+ return mutex_ptr;
+}
+EXPORT_SYMBOL(imx_sema4_mutex_create);
+
+/*!
+ * \brief mutex destroy function.
+ *
+ * This function destroys a mutex.
+ *
+ * \param[in] mutex_ptr Pointer to mutex structure.
+ *
+ * \return MQX_COMPONENT_DOES_NOT_EXIST (mutex component not installed.)
+ * \return MQX_INVALID_PARAMETER (Wrong input parameter.)
+ * \return COREMUTEX_OK (Success.)
+ *
+ */
+int imx_sema4_mutex_destroy(struct imx_sema4_mutex *mutex_ptr)
+{
+ u32 mutex_num;
+
+ if ((mutex_ptr == NULL) || (mutex_ptr->valid != CORE_MUTEX_VALID))
+ return -EINVAL;
+
+ mutex_num = mutex_ptr->gate_num;
+ if ((imx6_sema4->cpine_val & idx_sema4[mutex_num]) == 0) {
+ pr_err("Error: trying to destroy a un-allocated sema4.\n");
+ pr_err("mutex_num %d cpine_val 0x%08x.\n",
+ mutex_num, imx6_sema4->cpine_val);
+ }
+ imx6_sema4->mutex_ptr[mutex_num] = NULL;
+ imx6_sema4->alloced &= ~(1 << mutex_num);
+ imx6_sema4->cpine_val &= ~(idx_sema4[mutex_num]);
+ writew(imx6_sema4->cpine_val, imx6_sema4->ioaddr + SEMA4_CP0INE);
+
+ kfree(mutex_ptr);
+
+ return 0;
+}
+EXPORT_SYMBOL(imx_sema4_mutex_destroy);
+
+/*!
+ * \brief Lock the mutex, shouldn't be interruted by INT.
+ *
+ * This function attempts to lock a mutex. If the mutex is already locked
+ * by another task the function return -EBUSY, and tell invoker wait until
+ * it is possible to lock the mutex.
+ *
+ * \param[in] mutex_ptr Pointer to mutex structure.
+ *
+ * \return MQX_INVALID_POINTER (Wrong pointer to the mutex structure provided.)
+ * \return COREMUTEX_OK (mutex successfully locked.)
+ *
+ * \see imx_sema4_mutex_unlock
+ */
+int _imx_sema4_mutex_lock(struct imx_sema4_mutex *mutex_ptr)
+{
+ int ret = 0, i = 0;
+
+ if ((mutex_ptr == NULL) || (mutex_ptr->valid != CORE_MUTEX_VALID))
+ return -EINVAL;
+
+ i = mutex_ptr->gate_num;
+ mutex_ptr->gate_val = readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= SEMA4_GATE_MASK;
+ /* Check to see if this core already own it */
+ if (mutex_ptr->gate_val == SEMA4_A9_LOCK) {
+ /* return -EBUSY, invoker should be in sleep, and re-lock ag */
+ pr_err("%s -> %s %d already locked, wait! num %d val %d.\n",
+ __FILE__, __func__, __LINE__,
+ i, mutex_ptr->gate_val);
+ ret = -EBUSY;
+ goto out;
+ } else {
+ /* try to lock the mutex */
+ mutex_ptr->gate_val = readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= (~SEMA4_GATE_MASK);
+ mutex_ptr->gate_val |= SEMA4_A9_LOCK;
+ writeb(mutex_ptr->gate_val, imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val = readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= SEMA4_GATE_MASK;
+ /* double check the mutex is locked, otherwise, return -EBUSY */
+ if (mutex_ptr->gate_val != SEMA4_A9_LOCK) {
+ pr_debug("wait-locked num %d val %d.\n",
+ i, mutex_ptr->gate_val);
+ ret = -EBUSY;
+ }
+ }
+out:
+ return ret;
+}
+
+/* !
+ * \brief Try to lock the core mutex.
+ *
+ * This function attempts to lock a mutex. If the mutex is successfully locked
+ * for the calling task, SEMA4_A9_LOCK is returned. If the mutex is already
+ * locked by another task, the function does not block but rather returns
+ * negative immediately.
+ *
+ * \param[in] mutex_ptr Pointer to core_mutex structure.
+ *
+ * \return SEMA4_A9_LOCK (mutex successfully locked.)
+ * \return negative (mutex not locked.)
+ *
+ */
+int imx_sema4_mutex_trylock(struct imx_sema4_mutex *mutex_ptr)
+{
+ int ret = 0;
+
+ ret = _imx_sema4_mutex_lock(mutex_ptr);
+ if (ret == 0)
+ return SEMA4_A9_LOCK;
+ else
+ return ret;
+}
+EXPORT_SYMBOL(imx_sema4_mutex_trylock);
+
+/*!
+ * \brief Invoke _imx_sema4_mutex_lock to lock the mutex.
+ *
+ * This function attempts to lock a mutex. If the mutex is already locked
+ * by another task the function, sleep itself and schedule out.
+ * Wait until it is possible to lock the mutex.
+ *
+ * Invoker should add its own wait queue into the wait queue header of the
+ * required semaphore, set TASK_INTERRUPTIBLE and sleep on itself by
+ * schedule() when the lock is failed. Re-try to lock the semaphore when
+ * it is woke up by the sema4 isr.
+ *
+ * \param[in] mutex_ptr Pointer to mutex structure.
+ *
+ * \return SEMA4_A9_LOCK (mutex successfully locked.)
+ *
+ * \see imx_sema4_mutex_unlock
+ */
+int imx_sema4_mutex_lock(struct imx_sema4_mutex *mutex_ptr)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&imx6_sema4->lock, flags);
+ ret = _imx_sema4_mutex_lock(mutex_ptr);
+ spin_unlock_irqrestore(&imx6_sema4->lock, flags);
+ while (-EBUSY == ret) {
+ spin_lock_irqsave(&imx6_sema4->lock, flags);
+ ret = _imx_sema4_mutex_lock(mutex_ptr);
+ spin_unlock_irqrestore(&imx6_sema4->lock, flags);
+ if (ret == 0)
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(imx_sema4_mutex_lock);
+
+/*!
+ * \brief Unlock the mutex.
+ *
+ * This function unlocks the specified mutex.
+ *
+ * \param[in] mutex_ptr Pointer to mutex structure.
+ *
+ * \return -EINVAL (Wrong pointer to the mutex structure provided.)
+ * \return -EINVAL (This mutex has not been locked by this core.)
+ * \return 0 (mutex successfully unlocked.)
+ *
+ * \see imx_sema4_mutex_lock
+ */
+int imx_sema4_mutex_unlock(struct imx_sema4_mutex *mutex_ptr)
+{
+ int ret = 0, i = 0;
+
+ if ((mutex_ptr == NULL) || (mutex_ptr->valid != CORE_MUTEX_VALID))
+ return -EINVAL;
+
+ i = mutex_ptr->gate_num;
+ mutex_ptr->gate_val = readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= SEMA4_GATE_MASK;
+ /* make sure it is locked by this core */
+ if (mutex_ptr->gate_val != SEMA4_A9_LOCK) {
+ pr_err("%d Trying to unlock an unlock mutex.\n", __LINE__);
+ ret = -EINVAL;
+ goto out;
+ }
+ /* unlock it */
+ mutex_ptr->gate_val = readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= (~SEMA4_GATE_MASK);
+ writeb(mutex_ptr->gate_val | SEMA4_UNLOCK, imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val = readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= SEMA4_GATE_MASK;
+ /* make sure it is locked by this core */
+ if (mutex_ptr->gate_val == SEMA4_A9_LOCK)
+ pr_err("%d ERROR, failed to unlock the mutex.\n", __LINE__);
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL(imx_sema4_mutex_unlock);
+
+/*
+ * isr used by SEMA4, wake up the sleep tasks if there are the tasks waiting
+ * for locking semaphore.
+ * FIXME the bits order of the gatn, cpnie, cpnntf are not exact identified yet!
+ */
+static irqreturn_t imx_sema4_isr(int irq, void *dev_id)
+{
+ int i;
+ struct imx_sema4_mutex *mutex_ptr;
+ unsigned int mask;
+ struct imx_sema4_mutex_device *imx6_sema4 = dev_id;
+
+ imx6_sema4->cpntf_val = readw(imx6_sema4->ioaddr + SEMA4_CP0NTF);
+ for (i = 0; i < SEMA4_NUM_GATES; i++) {
+ mask = idx_sema4[i];
+ if ((imx6_sema4->cpntf_val) & mask) {
+ mutex_ptr = imx6_sema4->mutex_ptr[i];
+ /*
+ * An interrupt is pending on this mutex, the only way
+ * to clear it is to lock it (either by this core or
+ * another).
+ */
+ mutex_ptr->gate_val = readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= (~SEMA4_GATE_MASK);
+ mutex_ptr->gate_val |= SEMA4_A9_LOCK;
+ writeb(mutex_ptr->gate_val, imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val = readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= SEMA4_GATE_MASK;
+ if (mutex_ptr->gate_val == SEMA4_A9_LOCK) {
+ /*
+ * wake up the wait queue, whatever there
+ * are wait task or not.
+ * NOTE: check gate is locted or not in
+ * sema4_lock func by wait task.
+ */
+ mutex_ptr->gate_val =
+ readb(imx6_sema4->ioaddr + i);
+ mutex_ptr->gate_val &= (~SEMA4_GATE_MASK);
+ mutex_ptr->gate_val |= SEMA4_UNLOCK;
+
+ writeb(mutex_ptr->gate_val,
+ imx6_sema4->ioaddr + i);
+ wake_up(&mutex_ptr->wait_q);
+ } else {
+ pr_debug("can't lock gate%d %s retry!\n", i,
+ mutex_ptr->gate_val ?
+ "locked by m4" : "");
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static const struct of_device_id imx_sema4_dt_ids[] = {
+ { .compatible = "fsl,imx6sx-sema4", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_sema4_dt_ids);
+
+static int imx_sema4_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret;
+
+ imx6_sema4 = devm_kzalloc(&pdev->dev, sizeof(*imx6_sema4), GFP_KERNEL);
+ if (!imx6_sema4)
+ return -ENOMEM;
+
+ imx6_sema4->dev = &pdev->dev;
+ imx6_sema4->cpine_val = 0;
+ spin_lock_init(&imx6_sema4->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (IS_ERR(res)) {
+ dev_err(&pdev->dev, "unable to get imx sema4 resource 0\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ imx6_sema4->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(imx6_sema4->ioaddr)) {
+ ret = PTR_ERR(imx6_sema4->ioaddr);
+ goto err;
+ }
+
+ imx6_sema4->irq = platform_get_irq(pdev, 0);
+ if (!imx6_sema4->irq) {
+ dev_err(&pdev->dev, "failed to get irq\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = devm_request_irq(&pdev->dev, imx6_sema4->irq, imx_sema4_isr,
+ IRQF_SHARED, "imx6sx-sema4", imx6_sema4);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request imx sema4 irq\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, imx6_sema4);
+
+err:
+ return ret;
+}
+
+static int imx_sema4_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver imx_sema4_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "imx-sema4",
+ .of_match_table = imx_sema4_dt_ids,
+ },
+ .probe = imx_sema4_probe,
+ .remove = imx_sema4_remove,
+};
+
+static int __init imx_sema4_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&imx_sema4_driver);
+ if (ret)
+ pr_err("Unable to initialize sema4 driver\n");
+ else
+ pr_info("imx sema4 driver is registered.\n");
+
+ return ret;
+}
+
+static void __exit imx_sema4_exit(void)
+{
+ pr_info("imx sema4 driver is unregistered.\n");
+ platform_driver_unregister(&imx_sema4_driver);
+}
+
+module_exit(imx_sema4_exit);
+module_init(imx_sema4_init);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IMX SEMA4 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 1ada68abb158..bb27b178c8c1 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -10,7 +10,13 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
- clk-pfd.o
+ clk-pfd.o \
+ clk-gate-exclusive.o \
+ clk-composite.o \
+ clk-frac-divider.o \
+ clk-pllv4.o \
+ clk-pllv5.o \
+ clk-pfdv2.o
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o
@@ -21,7 +27,9 @@ obj-$(CONFIG_SOC_IMX35) += clk-imx35.o
obj-$(CONFIG_SOC_IMX5) += clk-imx51-imx53.o
obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
+obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o
+obj-$(CONFIG_SOC_IMX7ULP) += clk-imx7ulp.o
obj-$(CONFIG_SOC_VF610) += clk-vf610.o
diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c
index 5cc99590f9a3..59a133d291ee 100644
--- a/drivers/clk/imx/clk-busy.c
+++ b/drivers/clk/imx/clk-busy.c
@@ -101,7 +101,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
init.name = name;
init.ops = &clk_busy_divider_ops;
- init.flags = CLK_SET_RATE_PARENT;
+ init.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
init.parent_names = &parent_name;
init.num_parents = 1;
diff --git a/drivers/clk/imx/clk-composite.c b/drivers/clk/imx/clk-composite.c
new file mode 100644
index 000000000000..7482bb923a15
--- /dev/null
+++ b/drivers/clk/imx/clk-composite.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 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-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+#define PCG_CGC BIT(30)
+#define PCG_PCS_SHIFT 24
+#define PCG_PCS_MASK 0x7
+
+struct clk *imx_clk_composite(const char *name, const char **parent_name,
+ int num_parents, bool mux_present, bool rate_present, bool gate_present,
+ void __iomem *reg)
+{
+ struct clk_gate *gate = NULL;
+ struct clk_mux *mux = NULL;
+ struct clk_frac_divider *div = NULL;
+ struct clk_hw *mux_hw = NULL, *div_hw = NULL, *gate_hw = NULL;
+ struct clk *clk;
+
+ /* check if the mux is present in this composite clk. */
+ if (mux_present) {
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux) {
+ pr_err("%s: could not allocate mux clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+ mux_hw = &mux->hw;
+ /* init the mux struct */
+ mux->reg = reg;
+ mux->shift = PCG_PCS_SHIFT;
+ mux->mask = PCG_PCS_MASK;
+ /* mux->lock */
+ }
+
+ if (rate_present) {
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div) {
+ pr_err("%s: counld not allocate divider clk\n", __func__);
+ kfree(mux);
+ return ERR_PTR(-ENOMEM);
+ }
+ div_hw = &div->hw;
+ /* init the div struct */
+ div->reg = reg;
+ div->mshift = 3;
+ div->mwidth = 1;
+ div->mmask = (0x1) << 3;
+ div->nshift = 0;
+ div->nwidth = 3;
+ div->nmask = 0x7;
+ }
+
+ if (gate_present) {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ pr_err("%s: could not allocate gate clk\n", __func__);
+ kfree(mux);
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+ gate_hw = &gate->hw;
+ /* init the gate struct */
+ gate->reg = reg;
+ gate->bit_idx = 30;
+ /* gate->lock */
+ }
+
+ /* register the composite clk itself */
+ clk = clk_register_composite(NULL, name, parent_name, num_parents,
+ mux_hw, &clk_mux_ops, div_hw, &clk_frac_divider_ops,
+ gate_hw, &clk_gate_ops, CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE);
+
+ if (IS_ERR(clk)) {
+ kfree(mux);
+ kfree(div);
+ kfree(gate);
+ }
+
+ return clk;
+}
diff --git a/drivers/clk/imx/clk-frac-divider.c b/drivers/clk/imx/clk-frac-divider.c
new file mode 100644
index 000000000000..0850ba2e26e5
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-divider.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * Based on driver/clk/clk-fractional-divider.c
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/rational.h>
+
+#include "clk.h"
+
+#define to_clk_frac_divider(_hw) container_of(_hw, struct clk_frac_divider, hw)
+
+static unsigned long clk_frac_divider_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_frac_divider *fd = to_clk_frac_divider(hw);
+ u32 val, m, n;
+ u64 ret;
+
+ val = readl_relaxed(fd->reg);
+
+ m = (val & fd->mmask) >> fd->mshift;
+ n = (val & fd->nmask) >> fd->nshift;
+
+ ret = (u64)parent_rate * (m + 1);
+ do_div(ret, n + 1);
+
+ return ret;
+}
+
+static long clk_frac_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_frac_divider *fd = to_clk_frac_divider(hw);
+ unsigned long scale;
+ unsigned long m, n;
+ u64 ret;
+
+ if (!rate || rate >= *parent_rate)
+ return *parent_rate;
+
+ scale = fls_long(*parent_rate / rate - 1);
+ if (scale > 4)
+ rate <<= scale - fd->nwidth;
+
+ rational_best_approximation(rate, *parent_rate,
+ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+ &m, &n);
+
+ ret = (u64)*parent_rate * m;
+ do_div(ret, n);
+
+ return ret;
+}
+
+static int clk_frac_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_frac_divider *fd = to_clk_frac_divider(hw);
+ unsigned long m, n;
+ u32 val;
+
+ rational_best_approximation(rate, parent_rate,
+ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+ &m, &n);
+ m = m - 1;
+ n = n - 1;
+ if (m && !n)
+ return -EINVAL;
+
+ val = readl_relaxed(fd->reg);
+ val &= ~(fd->mmask | fd->nmask);
+ val |= (m << fd->mshift) | (n << fd->nshift);
+ writel_relaxed(val, fd->reg);
+
+ return 0;
+}
+
+const struct clk_ops clk_frac_divider_ops = {
+ .recalc_rate = clk_frac_divider_recalc_rate,
+ .round_rate = clk_frac_divider_round_rate,
+ .set_rate = clk_frac_divider_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_frac_divider_ops);
diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
index db44a198a0d9..b9bd5938d44a 100644
--- a/drivers/clk/imx/clk-gate2.c
+++ b/drivers/clk/imx/clk-gate2.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
* Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ * 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
@@ -10,11 +11,13 @@
*/
#include <linux/clk-provider.h>
+#include <linux/imx_sema4.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/string.h>
+#include <soc/imx/src.h>
#include "clk.h"
/**
@@ -38,11 +41,56 @@ struct clk_gate2 {
};
#define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw)
+#define CCM_CCGR_FULL_ENABLE 0x3
+
+static void clk_gate2_do_hardware(struct clk_gate2 *gate, bool enable)
+{
+ u32 reg;
+
+ reg = readl(gate->reg);
+ if (enable)
+ reg |= CCM_CCGR_FULL_ENABLE << gate->bit_idx;
+ else
+ reg &= ~(CCM_CCGR_FULL_ENABLE << gate->bit_idx);
+ writel(reg, gate->reg);
+}
+
+static void clk_gate2_do_shared_clks(struct clk_hw *hw, bool enable)
+{
+ struct clk_gate2 *gate = to_clk_gate2(hw);
+
+ if (imx_src_is_m4_enabled() && clk_on_imx6sx()) {
+#ifdef CONFIG_SOC_IMX6SX
+ if (!amp_power_mutex || !shared_mem) {
+ if (enable)
+ clk_gate2_do_hardware(gate, enable);
+ return;
+ }
+
+ imx_sema4_mutex_lock(amp_power_mutex);
+ if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER ||
+ shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) {
+ imx_sema4_mutex_unlock(amp_power_mutex);
+ return;
+ }
+
+ if (!imx_update_shared_mem(hw, enable)) {
+ imx_sema4_mutex_unlock(amp_power_mutex);
+ return;
+ }
+
+ clk_gate2_do_hardware(gate, enable);
+
+ imx_sema4_mutex_unlock(amp_power_mutex);
+#endif
+ } else {
+ clk_gate2_do_hardware(gate, enable);
+ }
+}
static int clk_gate2_enable(struct clk_hw *hw)
{
struct clk_gate2 *gate = to_clk_gate2(hw);
- u32 reg;
unsigned long flags = 0;
spin_lock_irqsave(gate->lock, flags);
@@ -50,11 +98,7 @@ static int clk_gate2_enable(struct clk_hw *hw)
if (gate->share_count && (*gate->share_count)++ > 0)
goto out;
- reg = readl(gate->reg);
- reg &= ~(3 << gate->bit_idx);
- reg |= gate->cgr_val << gate->bit_idx;
- writel(reg, gate->reg);
-
+ clk_gate2_do_shared_clks(hw, true);
out:
spin_unlock_irqrestore(gate->lock, flags);
@@ -64,7 +108,6 @@ out:
static void clk_gate2_disable(struct clk_hw *hw)
{
struct clk_gate2 *gate = to_clk_gate2(hw);
- u32 reg;
unsigned long flags = 0;
spin_lock_irqsave(gate->lock, flags);
@@ -76,10 +119,7 @@ static void clk_gate2_disable(struct clk_hw *hw)
goto out;
}
- reg = readl(gate->reg);
- reg &= ~(3 << gate->bit_idx);
- writel(reg, gate->reg);
-
+ clk_gate2_do_shared_clks(hw, false);
out:
spin_unlock_irqrestore(gate->lock, flags);
}
@@ -105,15 +145,11 @@ static void clk_gate2_disable_unused(struct clk_hw *hw)
{
struct clk_gate2 *gate = to_clk_gate2(hw);
unsigned long flags = 0;
- u32 reg;
spin_lock_irqsave(gate->lock, flags);
- if (!gate->share_count || *gate->share_count == 0) {
- reg = readl(gate->reg);
- reg &= ~(3 << gate->bit_idx);
- writel(reg, gate->reg);
- }
+ if (!gate->share_count || *gate->share_count == 0)
+ clk_gate2_do_shared_clks(hw, false);
spin_unlock_irqrestore(gate->lock, flags);
}
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index 93a19667003d..3af10e79f0b2 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -1,6 +1,7 @@
/*
- * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
+ * 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
@@ -31,7 +32,8 @@ static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy",
static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", };
static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
-static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", };
+static const char *axi_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[] = { "periph", "axi_alt_sel", };
static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
static const char *gpu_axi_sels[] = { "axi", "ahb", };
static const char *pre_axi_sels[] = { "axi", "ahb", };
@@ -41,15 +43,17 @@ static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_p
static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll3_pfd0_720m", };
static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
static const char *ldb_di_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };
+static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
+static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu2_di1_sels[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
-static const char *ipu1_di0_sels_2[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0_podf", "ldb_di1_podf", };
-static const char *ipu1_di1_sels_2[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0_podf", "ldb_di1_podf", };
-static const char *ipu2_di0_sels_2[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0_podf", "ldb_di1_podf", };
-static const char *ipu2_di1_sels_2[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0_podf", "ldb_di1_podf", };
+static const char *ipu1_di0_sels_2[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0_div_sel", "ldb_di1_div_sel", };
+static const char *ipu1_di1_sels_2[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0_div_sel", "ldb_di1_div_sel", };
+static const char *ipu2_di0_sels_2[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0_div_sel", "ldb_di1_div_sel", };
+static const char *ipu2_di1_sels_2[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0_div_sel", "ldb_di1_div_sel", };
static const char *hsi_tx_sels[] = { "pll3_120m", "pll2_pfd2_396m", };
static const char *pcie_axi_sels[] = { "axi", "ahb", };
static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", };
@@ -95,11 +99,14 @@ static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
static struct clk *clk[IMX6QDL_CLK_END];
static struct clk_onecell_data clk_data;
+static void __iomem *ccm_base;
static unsigned int const clks_init_on[] __initconst = {
IMX6QDL_CLK_MMDC_CH0_AXI,
IMX6QDL_CLK_ROM,
IMX6QDL_CLK_ARM,
+ IMX6QDL_CLK_OCRAM,
+ IMX6QDL_CLK_AXI,
};
static struct clk_div_table clk_enet_ref_table[] = {
@@ -156,12 +163,335 @@ static struct clk ** const uart_clks[] __initconst = {
NULL
};
+static int ldb_di_sel_by_clock_id(int clock_id)
+{
+ switch (clock_id) {
+ case IMX6QDL_CLK_PLL5_VIDEO_DIV:
+ if (clk_on_imx6q() &&
+ imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
+ return -ENOENT;
+ return 0;
+ case IMX6QDL_CLK_PLL2_PFD0_352M:
+ return 1;
+ case IMX6QDL_CLK_PLL2_PFD2_396M:
+ return 2;
+ case IMX6QDL_CLK_MMDC_CH1_AXI:
+ return 3;
+ case IMX6QDL_CLK_PLL3_USB_OTG:
+ return 4;
+ default:
+ return -ENOENT;
+ }
+}
+
+static void of_assigned_ldb_sels(struct device_node *node,
+ unsigned int *ldb_di0_sel,
+ unsigned int *ldb_di1_sel)
+{
+ struct of_phandle_args clkspec;
+ int index, rc, num_parents;
+ int parent, child, sel;
+
+ num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells");
+ for (index = 0; index < num_parents; index++) {
+ rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0) {
+ /* skip empty (null) phandles */
+ if (rc == -ENOENT)
+ continue;
+ else
+ return;
+ }
+ if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+ pr_err("ccm: parent clock %d not in ccm\n", index);
+ return;
+ }
+ parent = clkspec.args[0];
+
+ rc = of_parse_phandle_with_args(node, "assigned-clocks",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0)
+ return;
+ if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+ pr_err("ccm: child clock %d not in ccm\n", index);
+ return;
+ }
+ child = clkspec.args[0];
+
+ if (child != IMX6QDL_CLK_LDB_DI0_SEL &&
+ child != IMX6QDL_CLK_LDB_DI1_SEL)
+ continue;
+
+ sel = ldb_di_sel_by_clock_id(parent);
+ if (sel < 0) {
+ pr_err("ccm: invalid ldb_di%d parent clock: %d\n",
+ child == IMX6QDL_CLK_LDB_DI1_SEL, parent);
+ continue;
+ }
+
+ if (child == IMX6QDL_CLK_LDB_DI0_SEL)
+ *ldb_di0_sel = sel;
+ if (child == IMX6QDL_CLK_LDB_DI1_SEL)
+ *ldb_di1_sel = sel;
+ }
+}
+
+#define CCM_CCDR 0x04
+#define CCM_CCSR 0x0c
+#define CCM_CS2CDR 0x2c
+#define CCM_CSCDR3 0x3c
+#define CCM_CCGR0 0x68
+#define CCM_CCGR3 0x74
+
+#define ANATOP_PLL3_PFD 0xf0
+
+
+#define CCDR_MMDC_CH1_MASK BIT(16)
+#define CCSR_PLL3_SW_CLK_SEL BIT(0)
+
+#define CS2CDR_LDB_DI0_CLK_SEL_SHIFT 9
+#define CS2CDR_LDB_DI1_CLK_SEL_SHIFT 12
+
+#define OCOTP_CFG3 0x440
+#define OCOTP_CFG3_SPEED_SHIFT 16
+#define OCOTP_CFG3_SPEED_1P2GHZ 0x3
+
+static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ reg = readl_relaxed(ccm_base + CCM_CCDR);
+ reg |= CCDR_MMDC_CH1_MASK;
+ writel_relaxed(reg, ccm_base + CCM_CCDR);
+}
+
+/*
+ * The only way to disable the MMDC_CH1 clock is to move it to pll3_sw_clk
+ * via periph2_clk2_sel and then to disable pll3_sw_clk by selecting the
+ * bypass clock source, since there is no CG bit for mmdc_ch1.
+ */
+static void mmdc_ch1_disable(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL],
+ clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+
+ /*
+ * Handshake with mmdc_ch1 module must be masked when changing
+ * periph2_clk_sel.
+ */
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_CLK2]);
+
+ /* Disable pll3_sw_clk by selecting the bypass clock source */
+ reg = readl_relaxed(ccm_base + CCM_CCSR);
+ reg |= CCSR_PLL3_SW_CLK_SEL;
+ writel_relaxed(reg, ccm_base + CCM_CCSR);
+}
+
+static void mmdc_ch1_reenable(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ /* Enable pll3_sw_clk by disabling the bypass */
+ reg = readl_relaxed(ccm_base + CCM_CCSR);
+ reg &= ~CCSR_PLL3_SW_CLK_SEL;
+ writel_relaxed(reg, ccm_base + CCM_CCSR);
+
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_PRE]);
+}
+
+/*
+ * We have to follow a strict procedure when changing the LDB clock source,
+ * otherwise we risk introducing a glitch that can lock up the LDB divider.
+ * Things to keep in mind:
+ *
+ * 1. The current and new parent clock inputs to the mux must be disabled.
+ * 2. The default clock input for ldb_di0/1_clk_sel is mmdc_ch1_axi, which
+ * has no CG bit.
+ * 3. pll2_pfd2_396m can not be gated if it is used as memory clock.
+ * 4. In the RTL implementation of the LDB_DI_CLK_SEL muxes the top four
+ * options are in one mux and the PLL3 option along with three unused
+ * inputs is in a second mux. There is a third mux with two inputs used
+ * to decide between the first and second 4-port mux:
+ *
+ * pll5_video_div 0 --|\
+ * pll2_pfd0_352m 1 --| |_
+ * pll2_pfd2_396m 2 --| | `-|\
+ * mmdc_ch1_axi 3 --|/ | |
+ * | |--
+ * pll3_usb_otg 4 --|\ | |
+ * 5 --| |_,-|/
+ * 6 --| |
+ * 7 --|/
+ *
+ * The ldb_di0/1_clk_sel[1:0] bits control both 4-port muxes at the same time.
+ * The ldb_di0/1_clk_sel[2] bit controls the 2-port mux. The code below
+ * switches the parent to the bottom mux first and then manipulates the top
+ * mux to ensure that no glitch will enter the divider.
+ */
+static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base)
+{
+ unsigned int reg;
+ unsigned int sel[2][4];
+ int i;
+
+ reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+ sel[0][0] = (reg >> CS2CDR_LDB_DI0_CLK_SEL_SHIFT) & 7;
+ sel[1][0] = (reg >> CS2CDR_LDB_DI1_CLK_SEL_SHIFT) & 7;
+
+ sel[0][3] = sel[0][2] = sel[0][1] = sel[0][0];
+ sel[1][3] = sel[1][2] = sel[1][1] = sel[1][0];
+
+ of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]);
+
+ for (i = 0; i < 2; i++) {
+ /* Warn if a glitch might have been introduced already */
+ if (sel[i][0] != 3) {
+ pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n",
+ i, sel[i][0]);
+ }
+
+ if (sel[i][0] == sel[i][3])
+ continue;
+
+ /* Only switch to or from pll2_pfd2_396m if it is disabled */
+ if ((sel[i][0] == 2 || sel[i][3] == 2) &&
+ (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+ clk[IMX6QDL_CLK_PLL2_PFD2_396M])) {
+ pr_err("ccm: ldb_di%d_sel: couldn't disable pll2_pfd2_396m\n",
+ i);
+ sel[i][3] = sel[i][2] = sel[i][1] = sel[i][0];
+ continue;
+ }
+
+ /* First switch to the bottom mux */
+ sel[i][1] = sel[i][0] | 4;
+
+ /* Then configure the top mux before switching back to it */
+ sel[i][2] = sel[i][3] | 4;
+
+ pr_debug("ccm: switching ldb_di%d_sel: %d->%d->%d->%d\n", i,
+ sel[i][0], sel[i][1], sel[i][2], sel[i][3]);
+ }
+
+ if (sel[0][0] == sel[0][3] && sel[1][0] == sel[1][3])
+ return;
+
+ mmdc_ch1_disable(ccm_base);
+
+ for (i = 1; i < 4; i++) {
+ reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+ reg &= ~((7 << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+ (7 << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+ reg |= ((sel[0][i] << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+ (sel[1][i] << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+ writel_relaxed(reg, ccm_base + CCM_CS2CDR);
+ }
+
+ mmdc_ch1_reenable(ccm_base);
+}
+
+#define CCM_ANALOG_PLL_VIDEO 0xa0
+#define CCM_ANALOG_PFD_480 0xf0
+#define CCM_ANALOG_PFD_528 0x100
+
+#define PLL_ENABLE BIT(13)
+
+#define PFD0_CLKGATE BIT(7)
+#define PFD1_CLKGATE BIT(15)
+#define PFD2_CLKGATE BIT(23)
+#define PFD3_CLKGATE BIT(31)
+
+/*
+ * workaround for ERR010579, when switching the clock source of IPU clock
+ * root in CCM. even setting CCGR3[CG0]=0x0 to gate off clock before
+ * switching, IPU may hang due to no IPU clock from CCM.
+ */
+static void __init init_ipu_clk(void __iomem *anatop_base)
+{
+ u32 val, origin_podf;
+
+ /* gate off the IPU1_IPU clock */
+ val = readl_relaxed(ccm_base + CCM_CCGR3);
+ val &= ~0x3;
+ writel_relaxed(val, ccm_base + CCM_CCGR3);
+
+ /* gate off IPU DCIC1/2 clocks */
+ val = readl_relaxed(ccm_base + CCM_CCGR0);
+ val &= ~(0xf << 24);
+ writel_relaxed(val, ccm_base + CCM_CCGR0);
+
+ /* set IPU_PODF to 3'b000 */
+ val = readl_relaxed(ccm_base + CCM_CSCDR3);
+ origin_podf = val & (0x7 << 11);
+ val &= ~(0x7 << 11);
+ writel_relaxed(val, ccm_base + CCM_CSCDR3);
+
+ /* disable PLL3_PFD1 */
+ val = readl_relaxed(anatop_base + ANATOP_PLL3_PFD);
+ val &= ~(0x1 << 15);
+ writel_relaxed(val, anatop_base + ANATOP_PLL3_PFD);
+
+ /* switch IPU_SEL clock to PLL3_PFD1 */
+ val = readl_relaxed(ccm_base + CCM_CSCDR3);
+ val |= (0x3 << 9);
+ writel_relaxed(val, ccm_base + CCM_CSCDR3);
+
+ /* restore the IPU PODF*/
+ val = readl_relaxed(ccm_base + CCM_CSCDR3);
+ val |= origin_podf;
+ writel_relaxed(val, ccm_base + CCM_CSCDR3);
+
+ /* enable PLL3_PFD1 */
+ val = readl_relaxed(anatop_base + ANATOP_PLL3_PFD);
+ val |= (0x1 << 15);
+ writel_relaxed(val, anatop_base + ANATOP_PLL3_PFD);
+
+ /* enable IPU1_IPU clock */
+ val = readl_relaxed(ccm_base + CCM_CCGR3);
+ val |= 0x3;
+ writel_relaxed(val, ccm_base + CCM_CCGR3);
+
+ /* enable IPU DCIC1/2 clock */
+ val = readl_relaxed(ccm_base + CCM_CCGR0);
+ val |= (0xf << 24);
+ writel_relaxed(val, ccm_base + CCM_CCGR0);
+}
+
+static void disable_anatop_clocks(void __iomem *anatop_base)
+{
+ unsigned int reg;
+
+ /* Make sure PLL2 PFDs 0-2 are gated */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_528);
+ /* Cannot gate PFD2 if pll2_pfd2_396m is the parent of MMDC clock */
+ if (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+ clk[IMX6QDL_CLK_PLL2_PFD2_396M])
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE;
+ else
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_528);
+
+ /* Make sure PLL3 PFDs 0-3 are gated */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_480);
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE | PFD3_CLKGATE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_480);
+
+ /* Make sure PLL5 is disabled */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PLL_VIDEO);
+ reg &= ~PLL_ENABLE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PLL_VIDEO);
+}
+
static void __init imx6q_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
- void __iomem *base;
+ void __iomem *anatop_base, *base;
int i;
- int ret;
+ u32 val;
clk[IMX6QDL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
clk[IMX6QDL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
@@ -172,7 +502,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
- base = of_iomap(np, 0);
+ anatop_base = base = of_iomap(np, 0);
WARN_ON(!base);
/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
@@ -193,7 +523,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
/* type name parent_name base div_mask */
clk[IMX6QDL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f);
- clk[IMX6QDL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+ clk[IMX6QDL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_PLL2, "pll2", "osc", base + 0x30, 0x1);
clk[IMX6QDL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3);
clk[IMX6QDL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f);
clk[IMX6QDL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f);
@@ -217,7 +547,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk_set_parent(clk[IMX6QDL_PLL6_BYPASS], clk[IMX6QDL_CLK_PLL6]);
clk_set_parent(clk[IMX6QDL_PLL7_BYPASS], clk[IMX6QDL_CLK_PLL7]);
- clk[IMX6QDL_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", base + 0x00, 13);
+ clk[IMX6QDL_CLK_PLL1_SYS] = imx_clk_fixed_factor("pll1_sys", "pll1_bypass", 1, 1);
clk[IMX6QDL_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13);
clk[IMX6QDL_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13);
clk[IMX6QDL_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13);
@@ -288,23 +618,25 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1);
}
- clk[IMX6QDL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clk[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
- clk[IMX6QDL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clk[IMX6QDL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+ clk[IMX6QDL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clk[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+ clk[IMX6QDL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clk[IMX6QDL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
np = ccm_node;
base = of_iomap(np, 0);
+ ccm_base = base;
WARN_ON(!base);
/* name reg shift width parent_names num_parents */
clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
- clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
- clk[IMX6QDL_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+ clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux_glitchless("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
+ clk[IMX6QDL_CLK_PERIPH_PRE] = imx_clk_mux_bus("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
clk[IMX6QDL_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
- clk[IMX6QDL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clk[IMX6QDL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux_bus("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
- clk[IMX6QDL_CLK_AXI_SEL] = imx_clk_mux("axi_sel", base + 0x14, 6, 2, axi_sels, ARRAY_SIZE(axi_sels));
+ clk[IMX6QDL_CLK_AXI_ALT_SEL] = imx_clk_mux("axi_alt_sel", base + 0x14, 7, 1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+ clk[IMX6QDL_CLK_AXI_SEL] = imx_clk_mux_glitchless("axi_sel", base + 0x14, 6, 1, axi_sels, ARRAY_SIZE(axi_sels));
clk[IMX6QDL_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[IMX6QDL_CLK_ASRC_SEL] = imx_clk_mux("asrc_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[IMX6QDL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
@@ -330,8 +662,27 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
clk[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clk[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
- clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+
+ if (clk_on_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0) {
+ clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+ } else {
+ disable_anatop_clocks(anatop_base);
+
+ imx6q_mmdc_ch1_mask_handshake(base);
+
+ /*
+ * The LDB_DI0/1_SEL muxes are registered read-only due to a hardware
+ * bug. Set the muxes to the requested values before registering the
+ * ldb_di_sel clocks.
+ */
+ init_ldb_clks(np, base);
+
+ clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
+ clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
+ }
+ clk[IMX6QDL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT);
clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
@@ -397,6 +748,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_divider("uart_serial_podf", "uart_sel", base + 0x24, 0, 6);
clk[IMX6QDL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0", 2, 7);
clk[IMX6QDL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1", 2, 7);
+ clk[IMX6QDL_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0", 1, 7);
+ clk[IMX6QDL_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1", 1, 7);
} else {
clk[IMX6QDL_CLK_ECSPI_ROOT] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6);
clk[IMX6QDL_CLK_CAN_ROOT] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6);
@@ -404,6 +757,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_divider("uart_serial_podf", "pll3_80m", base + 0x24, 0, 6);
clk[IMX6QDL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
clk[IMX6QDL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+ clk[IMX6QDL_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7);
+ clk[IMX6QDL_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7);
}
if (clk_on_imx6dl())
clk[IMX6QDL_CLK_MLB_PODF] = imx_clk_divider("mlb_podf", "mlb_sel", base + 0x18, 23, 3);
@@ -470,6 +825,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_root", base + 0x68, 16);
clk[IMX6QDL_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18);
clk[IMX6QDL_CLK_CAN2_SERIAL] = imx_clk_gate2("can2_serial", "can_root", base + 0x68, 20);
+ clk[IMX6QDL_CLK_DCIC1] = imx_clk_gate2("dcic1", "ipu1_podf", base + 0x68, 24);
+ clk[IMX6QDL_CLK_DCIC2] = imx_clk_gate2("dcic2", "ipu2_podf", base + 0x68, 26);
clk[IMX6QDL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0);
clk[IMX6QDL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2);
clk[IMX6QDL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4);
@@ -580,17 +937,27 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ clk_register_clkdev(clk[IMX6QDL_CLK_GPT_IPG], "ipg", "imx-gpt.0");
+ clk_register_clkdev(clk[IMX6QDL_CLK_GPT_IPG_PER], "per", "imx-gpt.0");
+ clk_register_clkdev(clk[IMX6QDL_CLK_GPT_3M], "gpt_3m", "imx-gpt.0");
clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
- if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
- clk_on_imx6dl()) {
- clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
- clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
- }
-
clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000);
- if (clk_on_imx6dl())
+ if (clk_on_imx6dl()) {
+ init_ipu_clk(anatop_base);
clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
+ clk_set_parent(clk[IMX6QDL_CLK_AXI_ALT_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
+ clk_set_parent(clk[IMX6QDL_CLK_AXI_SEL], clk[IMX6QDL_CLK_AXI_ALT_SEL]);
+ /* set epdc/pxp axi clock to 200Mhz */
+ clk_set_parent(clk[IMX6QDL_CLK_IPU2_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]);
+ clk_set_rate(clk[IMX6QDL_CLK_IPU2], 200000000);
+ } else {
+ /* set eim_slow to 132Mhz for i.MX6Q */
+ if (clk_on_imx6q())
+ clk_set_rate(clk[IMX6QDL_CLK_EIM_SLOW], 132000000);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_MMDC_CH0_AXI]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU2_SEL], clk[IMX6QDL_CLK_MMDC_CH0_AXI]);
+ }
clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
@@ -601,6 +968,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_SEL], clk[IMX6QDL_CLK_IPU2_DI0_PRE]);
clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_SEL], clk[IMX6QDL_CLK_IPU2_DI1_PRE]);
+
/*
* The gpmi needs 100MHz frequency in the EDO/Sync mode,
* We can not get the 100MHz from the pll2_pfd0_352m.
@@ -608,30 +976,93 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
*/
clk_set_parent(clk[IMX6QDL_CLK_ENFC_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]);
- for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
- clk_prepare_enable(clk[clks_init_on[i]]);
-
- if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
- clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]);
- clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]);
+ /* gpu clock initilazation */
+ /*
+ * On mx6dl, 2d core clock sources(sel, podf) is from 3d
+ * shader core clock, but 3d shader clock multiplexer of
+ * mx6dl is different. For instance the equivalent of
+ * pll2_pfd_594M on mx6q is pll2_pfd_528M on mx6dl.
+ * Make a note here.
+ */
+ if (clk_on_imx6dl()) {
+ clk_set_parent(clk[IMX6QDL_CLK_GPU3D_SHADER_SEL], clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_GPU3D_SHADER], 528000000);
+ /* for mx6dl, change gpu3d_core parent to 594_PFD*/
+ clk_set_parent(clk[IMX6QDL_CLK_GPU3D_CORE_SEL], clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_GPU3D_CORE], 528000000);
+ } else if (clk_on_imx6q()) {
+ if (imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0) {
+ clk_set_parent(clk[IMX6QDL_CLK_GPU3D_SHADER_SEL], clk[IMX6QDL_CLK_PLL3_PFD0_720M]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_GPU3D_SHADER], 720000000);
+ clk_set_parent(clk[IMX6QDL_CLK_GPU3D_CORE_SEL], clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_GPU3D_CORE], 594000000);
+ clk_set_parent(clk[IMX6QDL_CLK_GPU2D_CORE_SEL], clk[IMX6QDL_CLK_PLL3_PFD0_720M]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_GPU2D_CORE], 720000000);
+ } else {
+ clk_set_parent(clk[IMX6QDL_CLK_GPU3D_SHADER_SEL], clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_GPU3D_SHADER], 594000000);
+ clk_set_parent(clk[IMX6QDL_CLK_GPU3D_CORE_SEL], clk[IMX6QDL_CLK_MMDC_CH0_AXI]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_GPU3D_CORE], 528000000);
+ clk_set_parent(clk[IMX6QDL_CLK_GPU2D_CORE_SEL], clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_GPU2D_CORE], 480000000);
+ }
}
/*
* Let's initially set up CLKO with OSC24M, since this configuration
* is widely used by imx6q board designs to clock audio codec.
*/
- ret = clk_set_parent(clk[IMX6QDL_CLK_CKO2_SEL], clk[IMX6QDL_CLK_OSC]);
- if (!ret)
- ret = clk_set_parent(clk[IMX6QDL_CLK_CKO], clk[IMX6QDL_CLK_CKO2]);
- if (ret)
- pr_warn("failed to set up CLKO: %d\n", ret);
+ imx_clk_set_parent(clk[IMX6QDL_CLK_CKO2_SEL], clk[IMX6QDL_CLK_OSC]);
+ imx_clk_set_parent(clk[IMX6QDL_CLK_CKO], clk[IMX6QDL_CLK_CKO2]);
/* Audio-related clocks configuration */
clk_set_parent(clk[IMX6QDL_CLK_SPDIF_SEL], clk[IMX6QDL_CLK_PLL3_PFD3_454M]);
/* All existing boards with PCIe use LVDS1 */
- if (IS_ENABLED(CONFIG_PCI_IMX6))
+ if (IS_ENABLED(CONFIG_PCI_IMX6)) {
clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
+ np = of_find_compatible_node(NULL, NULL, "snps,dw-pcie");
+ /* external oscillator is used or not. */
+ if (of_property_read_u32(np, "ext_osc", &val) < 0)
+ val = 0;
+ /*
+ * imx6qp sabresd revb board has the external osc used by pcie
+ * - pll6 should be set bypass mode later in driver.
+ * - lvds_clk1 should be selected as pll6 bypass src, set here.
+ */
+ if (clk_on_imx6qp() && val == 1)
+ clk_set_parent(clk[IMX6QDL_PLL6_BYPASS_SRC], clk[IMX6QDL_CLK_LVDS1_IN]);
+ }
+
+ /*
+ * Enable clocks only after both parent and rate are all initialized
+ * as needed
+ */
+ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+ imx_clk_prepare_enable(clk[clks_init_on[i]]);
+
+ if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
+ imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]);
+ imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]);
+ }
+
+ /*Set enet_ref clock to 125M to supply for RGMII tx_clk */
+ clk_set_rate(clk[IMX6QDL_CLK_ENET_REF], 125000000);
+
+#ifdef CONFIG_MX6_VPU_352M
+ /*
+ * If VPU 352M is enabled, then PLL2_PDF2 need to be
+ * set to 352M, cpufreq will be disabled as VDDSOC/PU
+ * need to be at highest voltage, scaling cpu freq is
+ * not saving any power, and busfreq will be also disabled
+ * as the PLL2_PFD2 is not at default freq, in a word,
+ * all modules that sourceing clk from PLL2_PFD2 will
+ * be impacted.
+ */
+ imx_clk_set_rate(clk[IMX6QDL_CLK_PLL2_PFD2_396M], 352000000);
+ clk_set_parent(clk[IMX6QDL_CLK_VPU_AXI_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]);
+ pr_info("VPU 352M is enabled!\n");
+#endif
/*
* Initialize the GPU clock muxes, so that the maximum specified clock
@@ -652,5 +1083,35 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
}
imx_register_uart_clocks(uart_clks);
+
+ /*
+ * for i.MX6QP with speeding grading set to 1.2GHz,
+ * VPU should run at 396MHz.
+ */
+ if (clk_on_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0) {
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
+ WARN_ON(!np);
+
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ /*
+ * SPEED_GRADING[1:0] defines the max speed of ARM:
+ * 2b'11: 1200000000Hz;
+ * 2b'10: 996000000Hz;
+ * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
+ * 2b'00: 792000000Hz;
+ * We need to set the max speed of ARM according to fuse map.
+ */
+ val = readl_relaxed(base + OCOTP_CFG3);
+ val >>= OCOTP_CFG3_SPEED_SHIFT;
+ val &= 0x3;
+ if (val == OCOTP_CFG3_SPEED_1P2GHZ) {
+ imx_clk_set_parent(clk[IMX6QDL_CLK_VPU_AXI_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]);
+ imx_clk_set_rate(clk[IMX6QDL_CLK_VPU_AXI_PODF], 396000000);
+ pr_info("VPU frequency set to 396MHz!\n");
+ }
+ iounmap(base);
+ }
}
CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c
index 5fd4ddac1bf1..bedbb7efa2d0 100644
--- a/drivers/clk/imx/clk-imx6sl.c
+++ b/drivers/clk/imx/clk-imx6sl.c
@@ -7,6 +7,7 @@
*
*/
+#include <linux/busfreq-imx.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
@@ -18,6 +19,8 @@
#include "clk.h"
#define CCSR 0xc
+#define CCDR 0x04
+#define CCDR_CH0_HS_BYP 17
#define BM_CCSR_PLL1_SW_CLK_SEL (1 << 2)
#define CACRR 0x10
#define CDHIPR 0x48
@@ -55,7 +58,7 @@ static const char *lcdif_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_
static const char *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", };
static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", };
static const char *ecspi_sels[] = { "pll3_60m", "osc", };
-static const char *uart_sels[] = { "pll3_80m", "osc", };
+static const char *uart_sels[] = { "pll3_80m", "uart_osc_4m", };
static const char *lvds_sels[] = {
"pll1_sys", "pll2_bus", "pll2_pfd0", "pll2_pfd1", "pll2_pfd2", "dummy", "pll4_audio", "pll5_video",
"dummy", "enet_ref", "dummy", "dummy", "pll3_usb_otg", "pll7_usb_host", "pll3_pfd0", "pll3_pfd1",
@@ -143,46 +146,39 @@ static int imx6sl_get_arm_divider_for_wait(void)
}
}
-static void imx6sl_enable_pll_arm(bool enable)
-{
- static u32 saved_pll_arm;
- u32 val;
-
- if (enable) {
- saved_pll_arm = val = readl_relaxed(anatop_base + PLL_ARM);
- val |= BM_PLL_ARM_ENABLE;
- val &= ~BM_PLL_ARM_POWERDOWN;
- writel_relaxed(val, anatop_base + PLL_ARM);
- while (!(__raw_readl(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK))
- ;
- } else {
- writel_relaxed(saved_pll_arm, anatop_base + PLL_ARM);
- }
-}
-
void imx6sl_set_wait_clk(bool enter)
{
static unsigned long saved_arm_div;
+ u32 val;
int arm_div_for_wait = imx6sl_get_arm_divider_for_wait();
-
- /*
- * According to hardware design, arm podf change need
- * PLL1 clock enabled.
- */
- if (arm_div_for_wait == ARM_WAIT_DIV_396M)
- imx6sl_enable_pll_arm(true);
+ int mode = get_bus_freq_mode();
if (enter) {
- saved_arm_div = readl_relaxed(ccm_base + CACRR);
- writel_relaxed(arm_div_for_wait, ccm_base + CACRR);
+ /*
+ * If in this mode, the IPG clock is at 12MHz, we can
+ * only run ARM at a max 28.8MHz, so we need to run
+ * from the 24MHz OSC, as there is no way to get
+ * 28.8MHz, when ARM is sourced from PLl1.
+ */
+ if (mode == BUS_FREQ_LOW) {
+ val = readl_relaxed(ccm_base + CCSR);
+ val |= BM_CCSR_PLL1_SW_CLK_SEL;
+ writel_relaxed(val, ccm_base + CCSR);
+ } else {
+ saved_arm_div = readl_relaxed(ccm_base + CACRR);
+ writel_relaxed(arm_div_for_wait, ccm_base + CACRR);
+ }
} else {
- writel_relaxed(saved_arm_div, ccm_base + CACRR);
+ if (mode == BUS_FREQ_LOW) {
+ val = readl_relaxed(ccm_base + CCSR);
+ val &= ~BM_CCSR_PLL1_SW_CLK_SEL;
+ writel_relaxed(val, ccm_base + CCSR);
+ } else {
+ writel_relaxed(saved_arm_div, ccm_base + CACRR);
+ }
}
while (__raw_readl(ccm_base + CDHIPR) & BM_CDHIPR_ARM_PODF_BUSY)
;
-
- if (arm_div_for_wait == ARM_WAIT_DIV_396M)
- imx6sl_enable_pll_arm(false);
}
static struct clk ** const uart_clks[] __initconst = {
@@ -195,7 +191,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
void __iomem *base;
- int i;
+ int i, reg;
int ret;
clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
@@ -227,7 +223,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "osc", base + 0x20, 0x3);
clks[IMX6SL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
- clks[IMX6SL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SL_PLL2_BYPASS] = imx_clk_mux_flags_bus("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX6SL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX6SL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX6SL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
@@ -243,7 +239,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clk_set_parent(clks[IMX6SL_PLL6_BYPASS], clks[IMX6SL_CLK_PLL6]);
clk_set_parent(clks[IMX6SL_PLL7_BYPASS], clks[IMX6SL_CLK_PLL7]);
- clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", base + 0x00, 13);
+ clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_fixed_factor("pll1_sys", "pll1_bypass", 1, 1);
clks[IMX6SL_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13);
clks[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13);
clks[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13);
@@ -271,7 +267,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
clks[IMX6SL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
clks[IMX6SL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clks[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+ clks[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
clks[IMX6SL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0, base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
/* name parent_name reg idx */
@@ -288,6 +284,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4);
clks[IMX6SL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
clks[IMX6SL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
+ clks[IMX6SL_CLK_UART_OSC_4M] = imx_clk_fixed_factor("uart_osc_4m", "osc", 1, 6);
np = ccm_node;
base = of_iomap(np, 0);
@@ -296,13 +293,13 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
/* name reg shift width parent_names num_parents */
clks[IMX6SL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
- clks[IMX6SL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
+ clks[IMX6SL_CLK_PLL1_SW] = imx_clk_mux_glitchless("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
clks[IMX6SL_CLK_OCRAM_ALT_SEL] = imx_clk_mux("ocram_alt_sel", base + 0x14, 7, 1, ocram_alt_sels, ARRAY_SIZE(ocram_alt_sels));
clks[IMX6SL_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 1, ocram_sels, ARRAY_SIZE(ocram_sels));
- clks[IMX6SL_CLK_PRE_PERIPH2_SEL] = imx_clk_mux("pre_periph2_sel", base + 0x18, 21, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels));
- clks[IMX6SL_CLK_PRE_PERIPH_SEL] = imx_clk_mux("pre_periph_sel", base + 0x18, 18, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels));
- clks[IMX6SL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
- clks[IMX6SL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clks[IMX6SL_CLK_PRE_PERIPH2_SEL] = imx_clk_mux_bus("pre_periph2_sel", base + 0x18, 21, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels));
+ clks[IMX6SL_CLK_PRE_PERIPH_SEL] = imx_clk_mux_bus("pre_periph_sel", base + 0x18, 18, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels));
+ clks[IMX6SL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux_bus("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+ clks[IMX6SL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux_bus("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
clks[IMX6SL_CLK_CSI_SEL] = imx_clk_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels));
clks[IMX6SL_CLK_LCDIF_AXI_SEL] = imx_clk_mux("lcdif_axi_sel", base + 0x3c, 14, 2, lcdif_axi_sels, ARRAY_SIZE(lcdif_axi_sels));
clks[IMX6SL_CLK_USDHC1_SEL] = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
@@ -317,8 +314,8 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_EPDC_AXI_SEL] = imx_clk_mux("epdc_axi_sel", base + 0x34, 15, 3, epdc_axi_sels, ARRAY_SIZE(epdc_axi_sels));
clks[IMX6SL_CLK_GPU2D_OVG_SEL] = imx_clk_mux("gpu2d_ovg_sel", base + 0x18, 4, 2, gpu2d_ovg_sels, ARRAY_SIZE(gpu2d_ovg_sels));
clks[IMX6SL_CLK_GPU2D_SEL] = imx_clk_mux("gpu2d_sel", base + 0x18, 8, 2, gpu2d_sels, ARRAY_SIZE(gpu2d_sels));
- clks[IMX6SL_CLK_LCDIF_PIX_SEL] = imx_clk_mux("lcdif_pix_sel", base + 0x38, 6, 3, lcdif_pix_sels, ARRAY_SIZE(lcdif_pix_sels));
- clks[IMX6SL_CLK_EPDC_PIX_SEL] = imx_clk_mux("epdc_pix_sel", base + 0x38, 15, 3, epdc_pix_sels, ARRAY_SIZE(epdc_pix_sels));
+ clks[IMX6SL_CLK_LCDIF_PIX_SEL] = imx_clk_mux_flags("lcdif_pix_sel", base + 0x38, 6, 3, lcdif_pix_sels, ARRAY_SIZE(lcdif_pix_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SL_CLK_EPDC_PIX_SEL] = imx_clk_mux_flags("epdc_pix_sel", base + 0x38, 15, 3, epdc_pix_sels, ARRAY_SIZE(epdc_pix_sels), CLK_SET_RATE_PARENT);
clks[IMX6SL_CLK_SPDIF0_SEL] = imx_clk_mux("spdif0_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
clks[IMX6SL_CLK_SPDIF1_SEL] = imx_clk_mux("spdif1_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
clks[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
@@ -330,7 +327,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
/* name parent_name reg shift width */
- clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3);
+ clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_busy_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3, base + 0x48, 0);
clks[IMX6SL_CLK_PERIPH_CLK2_PODF] = imx_clk_divider("periph_clk2_podf", "periph_clk2_sel", base + 0x14, 27, 3);
clks[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_divider("periph2_clk2_podf", "periph2_clk2_sel", base + 0x14, 0, 3);
clks[IMX6SL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
@@ -420,6 +417,11 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clk_data.clk_num = ARRAY_SIZE(clks);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ /* Ensure the CH0 handshake is bypassed */
+ reg = readl_relaxed(base + CCDR);
+ reg |= 1 << CCDR_CH0_HS_BYP;
+ writel_relaxed(reg, base + CCDR);
+
/* Ensure the AHB clk is at 132MHz. */
ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000);
if (ret)
@@ -441,6 +443,8 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
/* Audio-related clocks configuration */
clk_set_parent(clks[IMX6SL_CLK_SPDIF0_SEL], clks[IMX6SL_CLK_PLL3_PFD3]);
+ /* Initialize Video PLLs to valid frequency (650MHz). */
+ imx_clk_set_rate(clks[IMX6SL_CLK_PLL5_VIDEO_DIV], 650000000);
/* set PLL5 video as lcdif pix parent clock */
clk_set_parent(clks[IMX6SL_CLK_LCDIF_PIX_SEL],
clks[IMX6SL_CLK_PLL5_VIDEO_DIV]);
@@ -448,6 +452,18 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL],
clks[IMX6SL_CLK_PLL2_PFD2]);
+ /* Configure EPDC clocks */
+ clk_set_parent(clks[IMX6SL_CLK_EPDC_PIX_SEL],
+ clks[IMX6SL_CLK_PLL5_VIDEO_DIV]);
+ clk_set_parent(clks[IMX6SL_CLK_EPDC_AXI_SEL],
+ clks[IMX6SL_CLK_PLL2_PFD2]);
+ clk_set_rate(clks[IMX6SL_CLK_EPDC_AXI], 200000000);
+
+ /* Set the UART parent if needed */
+ if (uart_from_osc)
+ imx_clk_set_parent(clks[IMX6SL_CLK_UART_SEL], clks[IMX6SL_CLK_UART_OSC_4M]);
+
imx_register_uart_clocks(uart_clks);
+
}
CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
diff --git a/drivers/clk/imx/clk-imx6sll.c b/drivers/clk/imx/clk-imx6sll.c
new file mode 100644
index 000000000000..ff6aaf4143ef
--- /dev/null
+++ b/drivers/clk/imx/clk-imx6sll.c
@@ -0,0 +1,380 @@
+/*
+ * 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 <dt-bindings/clock/imx6sll-clock.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/types.h>
+
+#include "clk.h"
+
+#define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16)
+#define CCDR 0x4
+
+static const char *pll_bypass_src_sels[] = { "osc", "dummy", };
+static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
+static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
+static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
+static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
+static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
+static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
+static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char *step_sels[] = { "osc", "pll2_pfd2_396m", };
+static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
+static const char *axi_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[] = {"periph", "axi_alt_sel", };
+static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
+static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", };
+static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", };
+static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", };
+static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
+static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
+static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *ssi_sels[] = {"pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", "dummy",};
+static const char *spdif_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
+static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
+static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", };
+static const char *ldb_di1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", };
+static const char *lcdif_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", };
+static const char *ecspi_sels[] = { "pll3_60m", "osc", };
+static const char *uart_sels[] = { "pll3_80m", "osc", };
+static const char *perclk_sels[] = { "ipg", "osc", };
+static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
+static const char *epdc_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *epdc_sels[] = { "epdc_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
+static struct clk *clks[IMX6SLL_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static int const clks_init_on[] __initconst = {
+ IMX6SLL_CLK_AIPSTZ1, IMX6SLL_CLK_AIPSTZ2,
+ IMX6SLL_CLK_OCRAM, IMX6SLL_CLK_ARM, IMX6SLL_CLK_ROM,
+ IMX6SLL_CLK_MMDC_P0_FAST, IMX6SLL_CLK_MMDC_P0_IPG,
+};
+
+static struct clk_div_table post_div_table[] = {
+ { .val = 2, .div = 1, },
+ { .val = 1, .div = 2, },
+ { .val = 0, .div = 4, },
+ { }
+};
+
+static struct clk_div_table video_div_table[] = {
+ { .val = 0, .div = 1, },
+ { .val = 1, .div = 2, },
+ { .val = 2, .div = 1, },
+ { .val = 3, .div = 4, },
+ { }
+};
+
+static u32 share_count_audio;
+static u32 share_count_ssi1;
+static u32 share_count_ssi2;
+static u32 share_count_ssi3;
+
+static void __init imx6sll_clocks_init(struct device_node *ccm_node)
+{
+ struct device_node *np;
+ void __iomem *base;
+ int i;
+
+ clks[IMX6SLL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+
+ clks[IMX6SLL_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
+ clks[IMX6SLL_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
+
+ /* ipp_di clock is external input */
+ clks[IMX6SLL_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0");
+ clks[IMX6SLL_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1");
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6sll-anatop");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ clks[IMX6SLL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+
+ clks[IMX6SLL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
+ clks[IMX6SLL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
+ clks[IMX6SLL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3);
+ clks[IMX6SLL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
+ clks[IMX6SLL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
+ clks[IMX6SLL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
+ clks[IMX6SLL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+
+ clks[IMX6SLL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+
+ /* Do not bypass PLLs initially */
+ clk_set_parent(clks[IMX6SLL_PLL1_BYPASS], clks[IMX6SLL_CLK_PLL1]);
+ clk_set_parent(clks[IMX6SLL_PLL2_BYPASS], clks[IMX6SLL_CLK_PLL2]);
+ clk_set_parent(clks[IMX6SLL_PLL3_BYPASS], clks[IMX6SLL_CLK_PLL3]);
+ clk_set_parent(clks[IMX6SLL_PLL4_BYPASS], clks[IMX6SLL_CLK_PLL4]);
+ clk_set_parent(clks[IMX6SLL_PLL5_BYPASS], clks[IMX6SLL_CLK_PLL5]);
+ clk_set_parent(clks[IMX6SLL_PLL6_BYPASS], clks[IMX6SLL_CLK_PLL6]);
+ clk_set_parent(clks[IMX6SLL_PLL7_BYPASS], clks[IMX6SLL_CLK_PLL7]);
+
+ clks[IMX6SLL_CLK_PLL1_SYS] = imx_clk_fixed_factor("pll1_sys", "pll1_bypass", 1, 1);
+ clks[IMX6SLL_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13);
+ clks[IMX6SLL_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13);
+ clks[IMX6SLL_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13);
+ clks[IMX6SLL_CLK_PLL5_VIDEO] = imx_clk_gate("pll5_video", "pll5_bypass", base + 0xa0, 13);
+ clks[IMX6SLL_CLK_PLL6_ENET] = imx_clk_gate("pll6_enet", "pll6_bypass", base + 0xe0, 13);
+ clks[IMX6SLL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+
+ /*
+ * Bit 20 is the reserved and read-only bit, we do this only for:
+ * - Do nothing for usbphy clk_enable/disable
+ * - Keep refcount when do usbphy clk_enable/disable, in that case,
+ * the clk framework many need to enable/disable usbphy's parent
+ */
+ clks[IMX6SLL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
+ clks[IMX6SLL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+
+ /*
+ * usbphy*_gate needs to be on after system boots up, and software
+ * never needs to control it anymore.
+ */
+ clks[IMX6SLL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+ clks[IMX6SLL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+
+ /* name parent_name reg idx */
+ clks[IMX6SLL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
+ clks[IMX6SLL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
+ clks[IMX6SLL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2);
+ clks[IMX6SLL_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus", base + 0x100, 3);
+ clks[IMX6SLL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0);
+ clks[IMX6SLL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1);
+ clks[IMX6SLL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2);
+ clks[IMX6SLL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3);
+
+ clks[IMX6SLL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clks[IMX6SLL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+ clks[IMX6SLL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clks[IMX6SLL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+
+ /* name parent_name mult div */
+ clks[IMX6SLL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
+ clks[IMX6SLL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4);
+ clks[IMX6SLL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
+ clks[IMX6SLL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
+ clks[IMX6SLL_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
+
+ np = ccm_node;
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ clks[IMX6SLL_CLK_STEP] = imx_clk_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
+ clks[IMX6SLL_CLK_PLL1_SW] = imx_clk_mux_glitchless("pll1_sw", base + 0x0c, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
+ clks[IMX6SLL_CLK_AXI_ALT_SEL] = imx_clk_mux("axi_alt_sel", base + 0x14, 7, 1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+ clks[IMX6SLL_CLK_AXI_SEL] = imx_clk_mux_flags("axi_sel", base + 0x14, 6, 1, axi_sels, ARRAY_SIZE(axi_sels), 0);
+ clks[IMX6SLL_CLK_PERIPH_PRE] = imx_clk_mux_bus("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+ clks[IMX6SLL_CLK_PERIPH2_PRE] = imx_clk_mux_bus("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+ clks[IMX6SLL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux_bus("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clks[IMX6SLL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux_bus("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+ clks[IMX6SLL_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+ clks[IMX6SLL_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+ clks[IMX6SLL_CLK_USDHC3_SEL] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+ clks[IMX6SLL_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+ clks[IMX6SLL_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+ clks[IMX6SLL_CLK_SSI3_SEL] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+ clks[IMX6SLL_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels));
+ clks[IMX6SLL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
+ clks[IMX6SLL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
+ clks[IMX6SLL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x30, 7, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
+ clks[IMX6SLL_CLK_EPDC_PRE_SEL] = imx_clk_mux("epdc_pre_sel", base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
+ clks[IMX6SLL_CLK_EPDC_SEL] = imx_clk_mux("epdc_sel", base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
+ clks[IMX6SLL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
+ clks[IMX6SLL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
+ clks[IMX6SLL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
+
+ clks[IMX6SLL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
+ clks[IMX6SLL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
+
+ clks[IMX6SLL_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3);
+ clks[IMX6SLL_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3);
+ clks[IMX6SLL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
+ clks[IMX6SLL_CLK_LCDIF_PODF] = imx_clk_divider("lcdif_podf", "lcdif_pred", base + 0x18, 23, 3);
+ clks[IMX6SLL_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6);
+ clks[IMX6SLL_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3);
+ clks[IMX6SLL_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3);
+ clks[IMX6SLL_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3);
+ clks[IMX6SLL_CLK_UART_PODF] = imx_clk_divider("uart_podf", "uart_sel", base + 0x24, 0, 6);
+ clks[IMX6SLL_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3);
+ clks[IMX6SLL_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6);
+ clks[IMX6SLL_CLK_SSI1_PRED] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3);
+ clks[IMX6SLL_CLK_SSI1_PODF] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6);
+ clks[IMX6SLL_CLK_SSI2_PRED] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3);
+ clks[IMX6SLL_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6);
+ clks[IMX6SLL_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
+ clks[IMX6SLL_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
+ clks[IMX6SLL_CLK_EXTERN_AUDIO_PRED] = imx_clk_divider("extern_audio_pred", "extern_audio_sel", base + 0x30, 12, 3);
+ clks[IMX6SLL_CLK_EXTERN_AUDIO_PODF] = imx_clk_divider("extern_audio_podf", "extern_audio_pred", base + 0x30, 9, 3);
+ clks[IMX6SLL_CLK_EPDC_PODF] = imx_clk_divider("epdc_podf", "epdc_pre_sel", base + 0x34, 12, 3);
+ clks[IMX6SLL_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel", base + 0x38, 19, 6);
+ clks[IMX6SLL_CLK_LCDIF_PRED] = imx_clk_divider("lcdif_pred", "lcdif_pre_sel", base + 0x38, 12, 3);
+
+ clks[IMX6SLL_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16);
+ clks[IMX6SLL_CLK_MMDC_PODF] = imx_clk_busy_divider("mmdc_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2);
+ clks[IMX6SLL_CLK_AXI_PODF] = imx_clk_busy_divider("axi", "axi_sel", base + 0x14, 16, 3, base + 0x48, 0);
+ clks[IMX6SLL_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1);
+
+ clks[IMX6SLL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+ clks[IMX6SLL_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7);
+ clks[IMX6SLL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+ clks[IMX6SLL_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7);
+
+ clks[IMX6SLL_CLK_LDB_DI0_SEL] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
+ clks[IMX6SLL_CLK_LDB_DI1_SEL] = imx_clk_mux("ldb_di1_sel", base + 0x1c, 7, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels));
+ clks[IMX6SLL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
+ clks[IMX6SLL_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux("ldb_di1_div_sel", base + 0x20, 10, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+
+ /* CCGR0 */
+ clks[IMX6SLL_CLK_AIPSTZ1] = imx_clk_gate2("aips_tz1", "ahb", base + 0x68, 0);
+ clks[IMX6SLL_CLK_AIPSTZ2] = imx_clk_gate2("aips_tz2", "ahb", base + 0x68, 2);
+ clks[IMX6SLL_CLK_DCP] = imx_clk_gate2("dcp", "ahb", base + 0x68, 10);
+ clks[IMX6SLL_CLK_UART2_IPG] = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28);
+ clks[IMX6SLL_CLK_UART2_SERIAL] = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28);
+
+ /* CCGR1 */
+ clks[IMX6SLL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_podf", base + 0x6c, 0);
+ clks[IMX6SLL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_podf", base + 0x6c, 2);
+ clks[IMX6SLL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_podf", base + 0x6c, 4);
+ clks[IMX6SLL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_podf", base + 0x6c, 6);
+ clks[IMX6SLL_CLK_UART3_IPG] = imx_clk_gate2("uart3_ipg", "ipg", base + 0x6c, 10);
+ clks[IMX6SLL_CLK_UART3_SERIAL] = imx_clk_gate2("uart3_serial", "uart_podf", base + 0x6c, 10);
+ clks[IMX6SLL_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12);
+ clks[IMX6SLL_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14);
+ clks[IMX6SLL_CLK_GPT_BUS] = imx_clk_gate2("gpt1_bus", "perclk", base + 0x6c, 20);
+ clks[IMX6SLL_CLK_GPT_SERIAL] = imx_clk_gate2("gpt1_serial", "perclk", base + 0x6c, 22);
+ clks[IMX6SLL_CLK_UART4_IPG] = imx_clk_gate2("uart4_ipg", "ipg", base + 0x6c, 24);
+ clks[IMX6SLL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24);
+
+ /* CCGR2 */
+ clks[IMX6SLL_CLK_CSI] = imx_clk_gate2("csi", "axi", base + 0x70, 2);
+ clks[IMX6SLL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6);
+ clks[IMX6SLL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8);
+ clks[IMX6SLL_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10);
+ clks[IMX6SLL_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12);
+ clks[IMX6SLL_CLK_LCDIF_APB] = imx_clk_gate2("lcdif_apb", "axi", base + 0x70, 28);
+ clks[IMX6SLL_CLK_PXP] = imx_clk_gate2("pxp", "axi", base + 0x70, 30);
+
+ /* CCGR3 */
+ clks[IMX6SLL_CLK_UART5_IPG] = imx_clk_gate2("uart5_ipg", "ipg", base + 0x74, 2);
+ clks[IMX6SLL_CLK_UART5_SERIAL] = imx_clk_gate2("uart5_serial", "uart_podf", base + 0x74, 2);
+ clks[IMX6SLL_CLK_EPDC_AXI] = imx_clk_gate2("epdc_aclk", "axi", base + 0x74, 4);
+ clks[IMX6SLL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_podf", base + 0x74, 4);
+ clks[IMX6SLL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_podf", base + 0x74, 10);
+ clks[IMX6SLL_CLK_WDOG1] = imx_clk_gate2("wdog1", "ipg", base + 0x74, 16);
+ clks[IMX6SLL_CLK_MMDC_P0_FAST] = imx_clk_gate("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20);
+ clks[IMX6SLL_CLK_MMDC_P0_IPG] = imx_clk_gate2("mmdc_p0_ipg", "ipg", base + 0x74, 24);
+ clks[IMX6SLL_CLK_OCRAM] = imx_clk_gate("ocram", "ahb", base + 0x74, 28);
+
+ /* CCGR4 */
+ clks[IMX6SLL_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16);
+ clks[IMX6SLL_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18);
+ clks[IMX6SLL_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20);
+ clks[IMX6SLL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22);
+
+ /* CCGR5 */
+ clks[IMX6SLL_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0);
+ clks[IMX6SLL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
+ clks[IMX6SLL_CLK_WDOG2] = imx_clk_gate2("wdog2", "ipg", base + 0x7c, 10);
+ clks[IMX6SLL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
+ clks[IMX6SLL_CLK_EXTERN_AUDIO] = imx_clk_gate2_shared("extern_audio", "extern_audio_podf", base + 0x7c, 14, &share_count_audio);
+ clks[IMX6SLL_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_audio);
+ clks[IMX6SLL_CLK_SPDIF_GCLK] = imx_clk_gate2_shared("spdif_gclk", "ipg", base + 0x7c, 14, &share_count_audio);
+ clks[IMX6SLL_CLK_SSI1] = imx_clk_gate2_shared("ssi1", "ssi1_podf", base + 0x7c, 18, &share_count_ssi1);
+ clks[IMX6SLL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
+ clks[IMX6SLL_CLK_SSI2] = imx_clk_gate2_shared("ssi2", "ssi2_podf", base + 0x7c, 20, &share_count_ssi2);
+ clks[IMX6SLL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
+ clks[IMX6SLL_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3);
+ clks[IMX6SLL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
+ clks[IMX6SLL_CLK_UART1_IPG] = imx_clk_gate2("uart1_ipg", "ipg", base + 0x7c, 24);
+ clks[IMX6SLL_CLK_UART1_SERIAL] = imx_clk_gate2("uart1_serial", "uart_podf", base + 0x7c, 24);
+
+ /* CCGR6 */
+ clks[IMX6SLL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
+ clks[IMX6SLL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2);
+ clks[IMX6SLL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
+ clks[IMX6SLL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6);
+
+ /* mask handshake of mmdc */
+ writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+
+ for (i = 0; i < ARRAY_SIZE(clks); i++)
+ if (IS_ERR(clks[i]))
+ pr_err("i.MX6SLL clk %d: register failed with %ld\n", i, PTR_ERR(clks[i]));
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+ /* set perclk to from OSC */
+ clk_set_parent(clks[IMX6SLL_CLK_PERCLK_SEL], clks[IMX6SLL_CLK_OSC]);
+
+ /* Set the UART parent if needed */
+ if (uart_from_osc)
+ imx_clk_set_parent(clks[IMX6SLL_CLK_UART_SEL], clks[IMX6SLL_CLK_OSC]);
+ else
+ imx_clk_set_parent(clks[IMX6SLL_CLK_UART_SEL], clks[IMX6SLL_CLK_PLL3_80M]);
+
+ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+ clk_prepare_enable(clks[clks_init_on[i]]);
+
+ if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
+ clk_prepare_enable(clks[IMX6SLL_CLK_USBPHY1_GATE]);
+ clk_prepare_enable(clks[IMX6SLL_CLK_USBPHY2_GATE]);
+ }
+
+ /* Lower the AHB clock rate before changing the clock source. */
+ imx_clk_set_rate(clks[IMX6SLL_CLK_AHB], 99000000);
+
+ /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
+ imx_clk_set_parent(clks[IMX6SLL_CLK_PERIPH_CLK2_SEL], clks[IMX6SLL_CLK_PLL3_USB_OTG]);
+ imx_clk_set_parent(clks[IMX6SLL_CLK_PERIPH], clks[IMX6SLL_CLK_PERIPH_CLK2]);
+ imx_clk_set_parent(clks[IMX6SLL_CLK_PERIPH_PRE], clks[IMX6SLL_CLK_PLL2_BUS]);
+ imx_clk_set_parent(clks[IMX6SLL_CLK_PERIPH], clks[IMX6SLL_CLK_PERIPH_PRE]);
+
+ imx_clk_set_rate(clks[IMX6SLL_CLK_AHB], 132000000);
+
+ /* Configure EPDC clocks */
+ imx_clk_set_rate(clks[IMX6SLL_CLK_PLL3_PFD2], 320000000);
+ clk_set_parent(clks[IMX6SLL_CLK_EPDC_PRE_SEL],
+ clks[IMX6SLL_CLK_PLL3_PFD2]);
+
+}
+
+CLK_OF_DECLARE(imx6sll, "fsl,imx6sll-ccm", imx6sll_clocks_init);
+
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c
index b5c96de41ccf..a915e28056dd 100644
--- a/drivers/clk/imx/clk-imx6sx.c
+++ b/drivers/clk/imx/clk-imx6sx.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-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
@@ -13,15 +14,19 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
+#include <linux/imx_sema4.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/types.h>
+#include <soc/imx/gpc.h>
+#include <soc/imx/src.h>
#include "clk.h"
+#define CCM_CCGR_OFFSET(index) (index * 2)
#define CCDR 0x4
#define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16)
@@ -80,7 +85,7 @@ static const char *lvds_sels[] = {
"arm", "pll1_sys", "dummy", "dummy", "dummy", "dummy", "dummy", "pll5_video_div",
"dummy", "dummy", "pcie_ref_125m", "dummy", "usbphy1", "usbphy2",
};
-static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", };
+static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", "lvds2_in", "dummy", };
static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
@@ -91,18 +96,19 @@ static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
static struct clk *clks[IMX6SX_CLK_CLK_END];
static struct clk_onecell_data clk_data;
+struct imx_sema4_mutex *amp_power_mutex;
+
+static int clks_shared[MAX_SHARED_CLK_NUMBER];
+
+struct imx_shared_mem *shared_mem;
+static unsigned int shared_mem_paddr, shared_mem_size;
static int const clks_init_on[] __initconst = {
IMX6SX_CLK_AIPS_TZ1, IMX6SX_CLK_AIPS_TZ2, IMX6SX_CLK_AIPS_TZ3,
IMX6SX_CLK_IPMUX1, IMX6SX_CLK_IPMUX2, IMX6SX_CLK_IPMUX3,
IMX6SX_CLK_WAKEUP, IMX6SX_CLK_MMDC_P0_FAST, IMX6SX_CLK_MMDC_P0_IPG,
IMX6SX_CLK_ROM, IMX6SX_CLK_ARM, IMX6SX_CLK_IPG, IMX6SX_CLK_OCRAM,
- IMX6SX_CLK_PER2_MAIN, IMX6SX_CLK_PERCLK, IMX6SX_CLK_M4,
- IMX6SX_CLK_QSPI1, IMX6SX_CLK_QSPI2, IMX6SX_CLK_UART_IPG,
- IMX6SX_CLK_UART_SERIAL, IMX6SX_CLK_I2C3, IMX6SX_CLK_ECSPI5,
- IMX6SX_CLK_CAN1_IPG, IMX6SX_CLK_CAN1_SERIAL, IMX6SX_CLK_CAN2_IPG,
- IMX6SX_CLK_CAN2_SERIAL, IMX6SX_CLK_CANFD, IMX6SX_CLK_EPIT1,
- IMX6SX_CLK_EPIT2,
+ IMX6SX_CLK_PER2_MAIN, IMX6SX_CLK_PERCLK,
};
static struct clk_div_table clk_enet_ref_table[] = {
@@ -143,6 +149,38 @@ static struct clk ** const uart_clks[] __initconst = {
NULL
};
+/*
+ * As IMX6SX_CLK_M4_PRE_SEL is NOT a glitchless MUX, so when
+ * M4 is trying to change its clk parent, need to ask A9 to
+ * help do it, and M4 must be hold in wfi. To avoid glitch
+ * occur, need to gate M4 clk first before switching its parent.
+ */
+void imx6sx_set_m4_highfreq(bool high_freq)
+{
+ static struct clk *m4_high_freq_sel;
+
+ imx_gpc_hold_m4_in_sleep();
+
+ clk_disable_unprepare(clks[IMX6SX_CLK_M4]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_M4_SEL],
+ clks[IMX6SX_CLK_LDB_DI0]);
+
+ if (high_freq) {
+ imx_clk_set_parent(clks[IMX6SX_CLK_M4_PRE_SEL],
+ m4_high_freq_sel);
+ } else {
+ m4_high_freq_sel = clk_get_parent(clks[IMX6SX_CLK_M4_PRE_SEL]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_M4_PRE_SEL],
+ clks[IMX6SX_CLK_OSC]);
+ }
+
+ imx_clk_set_parent(clks[IMX6SX_CLK_M4_SEL],
+ clks[IMX6SX_CLK_M4_PRE_SEL]);
+ clk_prepare_enable(clks[IMX6SX_CLK_M4]);
+
+ imx_gpc_release_m4_in_sleep();
+}
+
static void __init imx6sx_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
@@ -160,6 +198,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
/* Clock source from external clock via CLK1 PAD */
clks[IMX6SX_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0);
+ clks[IMX6SX_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-anatop");
base = of_iomap(np, 0);
@@ -175,7 +214,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
/* type name parent_name base div_mask */
clks[IMX6SX_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f);
- clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+ clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_PLL2, "pll2", "osc", base + 0x30, 0x1);
clks[IMX6SX_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3);
clks[IMX6SX_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f);
clks[IMX6SX_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f);
@@ -191,15 +230,15 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
/* Do not bypass PLLs initially */
- clk_set_parent(clks[IMX6SX_PLL1_BYPASS], clks[IMX6SX_CLK_PLL1]);
- clk_set_parent(clks[IMX6SX_PLL2_BYPASS], clks[IMX6SX_CLK_PLL2]);
- clk_set_parent(clks[IMX6SX_PLL3_BYPASS], clks[IMX6SX_CLK_PLL3]);
- clk_set_parent(clks[IMX6SX_PLL4_BYPASS], clks[IMX6SX_CLK_PLL4]);
- clk_set_parent(clks[IMX6SX_PLL5_BYPASS], clks[IMX6SX_CLK_PLL5]);
- clk_set_parent(clks[IMX6SX_PLL6_BYPASS], clks[IMX6SX_CLK_PLL6]);
- clk_set_parent(clks[IMX6SX_PLL7_BYPASS], clks[IMX6SX_CLK_PLL7]);
-
- clks[IMX6SX_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", base + 0x00, 13);
+ imx_clk_set_parent(clks[IMX6SX_PLL1_BYPASS], clks[IMX6SX_CLK_PLL1]);
+ imx_clk_set_parent(clks[IMX6SX_PLL2_BYPASS], clks[IMX6SX_CLK_PLL2]);
+ imx_clk_set_parent(clks[IMX6SX_PLL3_BYPASS], clks[IMX6SX_CLK_PLL3]);
+ imx_clk_set_parent(clks[IMX6SX_PLL4_BYPASS], clks[IMX6SX_CLK_PLL4]);
+ imx_clk_set_parent(clks[IMX6SX_PLL5_BYPASS], clks[IMX6SX_CLK_PLL5]);
+ imx_clk_set_parent(clks[IMX6SX_PLL6_BYPASS], clks[IMX6SX_CLK_PLL6]);
+ imx_clk_set_parent(clks[IMX6SX_PLL7_BYPASS], clks[IMX6SX_CLK_PLL7]);
+
+ clks[IMX6SX_CLK_PLL1_SYS] = imx_clk_fixed_factor("pll1_sys", "pll1_bypass", 1, 1);
clks[IMX6SX_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13);
clks[IMX6SX_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13);
clks[IMX6SX_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13);
@@ -228,7 +267,9 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
clks[IMX6SX_CLK_LVDS1_OUT] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x160, 10, BIT(12));
+ clks[IMX6SX_CLK_LVDS2_OUT] = imx_clk_gate_exclusive("lvds2_out", "lvds2_sel", base + 0x160, 11, BIT(13));
clks[IMX6SX_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10));
+ clks[IMX6SX_CLK_LVDS2_IN] = imx_clk_gate_exclusive("lvds2_in", "anaclk2", base + 0x160, 13, BIT(11));
clks[IMX6SX_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
base + 0xe0, 0, 2, 0, clk_enet_ref_table,
@@ -270,6 +311,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
/* name reg shift width parent_names num_parents */
clks[IMX6SX_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+ clks[IMX6SX_CLK_LVDS2_SEL] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
np = ccm_node;
base = of_iomap(np, 0);
@@ -277,12 +319,12 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
/* name reg shift width parent_names num_parents */
clks[IMX6SX_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
- clks[IMX6SX_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
+ clks[IMX6SX_CLK_PLL1_SW] = imx_clk_mux_glitchless("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
clks[IMX6SX_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 2, ocram_sels, ARRAY_SIZE(ocram_sels));
- clks[IMX6SX_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
- clks[IMX6SX_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
- clks[IMX6SX_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
- clks[IMX6SX_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+ clks[IMX6SX_CLK_PERIPH_PRE] = imx_clk_mux_bus("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+ clks[IMX6SX_CLK_PERIPH2_PRE] = imx_clk_mux_bus("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+ clks[IMX6SX_CLK_PERIPH_CLK2_SEL] = imx_clk_mux_bus("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clks[IMX6SX_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux_bus("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
clks[IMX6SX_CLK_PCIE_AXI_SEL] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels));
clks[IMX6SX_CLK_GPU_AXI_SEL] = imx_clk_mux("gpu_axi_sel", base + 0x18, 8, 2, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
clks[IMX6SX_CLK_GPU_CORE_SEL] = imx_clk_mux("gpu_core_sel", base + 0x18, 4, 2, gpu_core_sels, ARRAY_SIZE(gpu_core_sels));
@@ -294,13 +336,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_SSI3_SEL] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
clks[IMX6SX_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
clks[IMX6SX_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
- clks[IMX6SX_CLK_QSPI1_SEL] = imx_clk_mux_flags("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SX_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
clks[IMX6SX_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels));
clks[IMX6SX_CLK_VID_SEL] = imx_clk_mux("vid_sel", base + 0x20, 21, 3, vid_sels, ARRAY_SIZE(vid_sels));
clks[IMX6SX_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
clks[IMX6SX_CLK_CAN_SEL] = imx_clk_mux("can_sel", base + 0x20, 8, 2, can_sels, ARRAY_SIZE(can_sels));
clks[IMX6SX_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
- clks[IMX6SX_CLK_QSPI2_SEL] = imx_clk_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SX_CLK_QSPI2_SEL] = imx_clk_mux("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels));
clks[IMX6SX_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
clks[IMX6SX_CLK_AUDIO_SEL] = imx_clk_mux("audio_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
clks[IMX6SX_CLK_ENET_PRE_SEL] = imx_clk_mux("enet_pre_sel", base + 0x34, 15, 3, enet_pre_sels, ARRAY_SIZE(enet_pre_sels));
@@ -494,79 +536,196 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_CKO1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7);
clks[IMX6SX_CLK_CKO2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24);
+ /* get those shared clk nodes if M4 is active */
+ if (imx_src_is_m4_enabled()) {
+ u32 num;
+
+ of_property_read_u32(np, "fsl,shared-clks-number", &num);
+ if (num > MAX_SHARED_CLK_NUMBER)
+ pr_err("clk: shared clk nodes exceed the max number!\n");
+ of_property_read_u32_array(np, "fsl,shared-clks-index",
+ clks_shared, num);
+ if (of_property_read_u32(np, "fsl,shared-mem-addr",
+ &shared_mem_paddr))
+ pr_err("clk: fsl,shared-mem-addr NOT found!\n");
+ if (of_property_read_u32(np, "fsl,shared-mem-size",
+ &shared_mem_size))
+ pr_err("clk: fsl,shared-mem-size NOT found!\n");
+ }
+
/* mask handshake of mmdc */
writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
imx_check_clocks(clks, ARRAY_SIZE(clks));
+ /*
+ * QSPI2/GPMI_IO share the same clock source but with the
+ * different gate, need explicitely gate the QSPI2 & GPMI_IO
+ * during the clock init phase according to the SOC design.
+ */
+ if (!imx_src_is_m4_enabled()) {
+ writel_relaxed(readl_relaxed(base + 0x78) &
+ ~(3 << CCM_CCGR_OFFSET(5)), base + 0x78);
+ writel_relaxed(readl_relaxed(base + 0x78) &
+ ~(3 << CCM_CCGR_OFFSET(14)), base + 0x78);
+ }
+
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
- clk_prepare_enable(clks[clks_init_on[i]]);
+ /*
+ * As some of the modules need to access ocotp in MSL,
+ * need to make sure ocotp clk(CCM_CCGR2_CG6) is enabled
+ * during MSL, as on i.MX6SX, accessing OCOTP registers
+ * needs its clk on, it will be disabled by clk late
+ * init and managed by ocotp driver.
+ */
+ writel_relaxed(readl_relaxed(base + 0x70) | 1 << 12, base + 0x70);
+
+ /* maintain M4 usecount */
+ if (imx_src_is_m4_enabled())
+ imx_clk_prepare_enable(clks[IMX6SX_CLK_M4]);
+
+ /* set perclk to from OSC */
+ imx_clk_set_parent(clks[IMX6SX_CLK_PERCLK_SEL], clks[IMX6SX_CLK_OSC]);
if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
- clk_prepare_enable(clks[IMX6SX_CLK_USBPHY1_GATE]);
- clk_prepare_enable(clks[IMX6SX_CLK_USBPHY2_GATE]);
+ imx_clk_prepare_enable(clks[IMX6SX_CLK_USBPHY1_GATE]);
+ imx_clk_prepare_enable(clks[IMX6SX_CLK_USBPHY2_GATE]);
}
/* Set the default 132MHz for EIM module */
- clk_set_parent(clks[IMX6SX_CLK_EIM_SLOW_SEL], clks[IMX6SX_CLK_PLL2_PFD2]);
- clk_set_rate(clks[IMX6SX_CLK_EIM_SLOW], 132000000);
+ imx_clk_set_parent(clks[IMX6SX_CLK_EIM_SLOW_SEL], clks[IMX6SX_CLK_PLL2_PFD2]);
+ imx_clk_set_rate(clks[IMX6SX_CLK_EIM_SLOW], 132000000);
/* set parent clock for LCDIF1 pixel clock */
- clk_set_parent(clks[IMX6SX_CLK_LCDIF1_PRE_SEL], clks[IMX6SX_CLK_PLL5_VIDEO_DIV]);
- clk_set_parent(clks[IMX6SX_CLK_LCDIF1_SEL], clks[IMX6SX_CLK_LCDIF1_PODF]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_LCDIF1_PRE_SEL], clks[IMX6SX_CLK_PLL5_VIDEO_DIV]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_LCDIF1_SEL], clks[IMX6SX_CLK_LCDIF1_PODF]);
+
+ /* set parent clock for LCDIF2 */
+ imx_clk_set_parent(clks[IMX6SX_CLK_LCDIF2_SEL], clks[IMX6SX_CLK_LDB_DI0]);
/* Set the parent clks of PCIe lvds1 and pcie_axi to be pcie ref, axi */
- if (clk_set_parent(clks[IMX6SX_CLK_LVDS1_SEL], clks[IMX6SX_CLK_PCIE_REF_125M]))
- pr_err("Failed to set pcie bus parent clk.\n");
- if (clk_set_parent(clks[IMX6SX_CLK_PCIE_AXI_SEL], clks[IMX6SX_CLK_AXI]))
- pr_err("Failed to set pcie parent clk.\n");
+ imx_clk_set_parent(clks[IMX6SX_CLK_LVDS1_SEL], clks[IMX6SX_CLK_PCIE_REF_125M]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_PCIE_AXI_SEL], clks[IMX6SX_CLK_AXI]);
/*
* Init enet system AHB clock, set to 200MHz
* pll2_pfd2_396m-> ENET_PODF-> ENET_AHB
*/
- clk_set_parent(clks[IMX6SX_CLK_ENET_PRE_SEL], clks[IMX6SX_CLK_PLL2_PFD2]);
- clk_set_parent(clks[IMX6SX_CLK_ENET_SEL], clks[IMX6SX_CLK_ENET_PODF]);
- clk_set_rate(clks[IMX6SX_CLK_ENET_PODF], 200000000);
- clk_set_rate(clks[IMX6SX_CLK_ENET_REF], 125000000);
- clk_set_rate(clks[IMX6SX_CLK_ENET2_REF], 125000000);
+ imx_clk_set_parent(clks[IMX6SX_CLK_ENET_PRE_SEL], clks[IMX6SX_CLK_PLL2_PFD2]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_ENET_SEL], clks[IMX6SX_CLK_ENET_PODF]);
+ imx_clk_set_rate(clks[IMX6SX_CLK_ENET_PODF], 200000000);
+ imx_clk_set_rate(clks[IMX6SX_CLK_ENET_REF], 125000000);
+ imx_clk_set_rate(clks[IMX6SX_CLK_ENET2_REF], 125000000);
/* Audio clocks */
- clk_set_rate(clks[IMX6SX_CLK_PLL4_AUDIO_DIV], 393216000);
+ imx_clk_set_rate(clks[IMX6SX_CLK_PLL4_AUDIO_DIV], 393216000);
- clk_set_parent(clks[IMX6SX_CLK_SPDIF_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
- clk_set_rate(clks[IMX6SX_CLK_SPDIF_PODF], 98304000);
+ imx_clk_set_parent(clks[IMX6SX_CLK_SPDIF_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
+ imx_clk_set_rate(clks[IMX6SX_CLK_SPDIF_PODF], 24576000);
- clk_set_parent(clks[IMX6SX_CLK_AUDIO_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]);
- clk_set_rate(clks[IMX6SX_CLK_AUDIO_PODF], 24000000);
+ imx_clk_set_parent(clks[IMX6SX_CLK_AUDIO_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]);
+ imx_clk_set_rate(clks[IMX6SX_CLK_AUDIO_PODF], 24000000);
- clk_set_parent(clks[IMX6SX_CLK_SSI1_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
- clk_set_parent(clks[IMX6SX_CLK_SSI2_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
- clk_set_parent(clks[IMX6SX_CLK_SSI3_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
- clk_set_rate(clks[IMX6SX_CLK_SSI1_PODF], 24576000);
- clk_set_rate(clks[IMX6SX_CLK_SSI2_PODF], 24576000);
- clk_set_rate(clks[IMX6SX_CLK_SSI3_PODF], 24576000);
+ imx_clk_set_parent(clks[IMX6SX_CLK_SSI1_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_SSI2_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_SSI3_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
+ imx_clk_set_rate(clks[IMX6SX_CLK_SSI1_PODF], 24576000);
+ imx_clk_set_rate(clks[IMX6SX_CLK_SSI2_PODF], 24576000);
+ imx_clk_set_rate(clks[IMX6SX_CLK_SSI3_PODF], 24576000);
- clk_set_parent(clks[IMX6SX_CLK_ESAI_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
- clk_set_rate(clks[IMX6SX_CLK_ESAI_PODF], 24576000);
+ imx_clk_set_parent(clks[IMX6SX_CLK_ESAI_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
+ imx_clk_set_rate(clks[IMX6SX_CLK_ESAI_PODF], 24576000);
- /* Set parent clock for vadc */
- clk_set_parent(clks[IMX6SX_CLK_VID_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]);
+ /* Set the UART parent if needed. */
+ if (uart_from_osc)
+ clk_set_parent(clks[IMX6SX_CLK_UART_SEL], clks[IMX6SX_CLK_OSC]);
+ else
+ clk_set_parent(clks[IMX6SX_CLK_UART_SEL], clks[IMX6SX_CLK_PLL3_80M]);
- /* default parent of can_sel clock is invalid, manually set it here */
- clk_set_parent(clks[IMX6SX_CLK_CAN_SEL], clks[IMX6SX_CLK_PLL3_60M]);
+ /* Set parent clock for vadc */
+ imx_clk_set_parent(clks[IMX6SX_CLK_VID_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]);
/* Update gpu clock from default 528M to 720M */
- clk_set_parent(clks[IMX6SX_CLK_GPU_CORE_SEL], clks[IMX6SX_CLK_PLL3_PFD0]);
- clk_set_parent(clks[IMX6SX_CLK_GPU_AXI_SEL], clks[IMX6SX_CLK_PLL3_PFD0]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_GPU_CORE_SEL], clks[IMX6SX_CLK_PLL3_PFD0]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_GPU_AXI_SEL], clks[IMX6SX_CLK_PLL3_PFD0]);
- clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
- clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
+ imx_clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
+ /* Set the UART parent if needed. */
+ if (uart_from_osc)
+ imx_clk_set_parent(clks[IMX6SX_CLK_UART_SEL], clks[IMX6SX_CLK_OSC]);
+
+ if (!imx_src_is_m4_enabled())
+ /* default parent of can_sel clock is invalid, manually set it here */
+ imx_clk_set_parent(clks[IMX6SX_CLK_CAN_SEL], clks[IMX6SX_CLK_PLL3_60M]);
+
+ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+ imx_clk_prepare_enable(clks[clks_init_on[i]]);
imx_register_uart_clocks(uart_clks);
}
CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
+
+int imx_update_shared_mem(struct clk_hw *hw, bool enable)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(clks_shared); i++) {
+ if (shared_mem->imx_clk[i].self == hw->clk)
+ break;
+ }
+
+ if (i >= ARRAY_SIZE(clks_shared))
+ return 1;
+
+ /* update ca9 clk status in shared memory */
+ if (enable)
+ shared_mem->imx_clk[i].ca9_enabled = 1;
+ else
+ shared_mem->imx_clk[i].ca9_enabled = 0;
+
+ if (shared_mem->imx_clk[i].cm4_enabled == 0)
+ return 1;
+
+ return 0;
+}
+
+static int __init imx_amp_power_init(void)
+{
+ int i;
+ void __iomem *shared_mem_base;
+
+ if (!(imx_src_is_m4_enabled() && clk_on_imx6sx()))
+ return 0;
+
+ amp_power_mutex = imx_sema4_mutex_create(0, MCC_POWER_SHMEM_NUMBER);
+
+ shared_mem_base = ioremap_nocache(shared_mem_paddr, shared_mem_size);
+
+ if (!amp_power_mutex) {
+ pr_err("Failed to create sema4 mutex!\n");
+ return 0;
+ }
+
+ shared_mem = (struct imx_shared_mem *)shared_mem_base;
+
+ for (i = 0; i < ARRAY_SIZE(clks_shared); i++) {
+ shared_mem->imx_clk[i].self = clks[clks_shared[i]];
+ shared_mem->imx_clk[i].ca9_enabled = 1;
+ pr_debug("%d: name %s, addr 0x%x\n", i,
+ __clk_get_name(shared_mem->imx_clk[i].self),
+ (u32)&(shared_mem->imx_clk[i]));
+ }
+ /* enable amp power management */
+ shared_mem->ca9_valid = SHARED_MEM_MAGIC_NUMBER;
+
+ pr_info("A9-M4 sema4 num %d, A9-M4 magic number 0x%x - 0x%x.\n",
+ amp_power_mutex->gate_num, shared_mem->ca9_valid,
+ shared_mem->cm4_valid);
+
+ return 0;
+}
+late_initcall(imx_amp_power_init);
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index d1d7787ce211..e2c1719d13ef 100644
--- a/drivers/clk/imx/clk-imx6ul.c
+++ b/drivers/clk/imx/clk-imx6ul.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright (C) 2015-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
@@ -65,6 +66,11 @@ static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0
static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
static const char *sim_sels[] = { "sim_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+/* epdc_pre_sels, epdc_sels, esai_sels only exists on i.MX6ULL */
+static const char *epdc_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *esai_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *epdc_sels[] = { "epdc_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
static struct clk *clks[IMX6UL_CLK_END];
static struct clk_onecell_data clk_data;
@@ -102,6 +108,17 @@ static u32 share_count_audio;
static u32 share_count_sai1;
static u32 share_count_sai2;
static u32 share_count_sai3;
+static u32 share_count_esai;
+
+static inline int clk_on_imx6ul(void)
+{
+ return of_machine_is_compatible("fsl,imx6ul");
+}
+
+static inline int clk_on_imx6ull(void)
+{
+ return of_machine_is_compatible("fsl,imx6ull");
+}
static void __init imx6ul_clocks_init(struct device_node *ccm_node)
{
@@ -131,7 +148,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f);
- clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+ clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_PLL2, "pll2", "osc", base + 0x30, 0x1);
clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3);
clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f);
clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f);
@@ -145,7 +162,6 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX6UL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX6UL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
- clks[IMX6UL_CLK_CSI_SEL] = imx_clk_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT);
/* Do not bypass PLLs initially */
clk_set_parent(clks[IMX6UL_PLL1_BYPASS], clks[IMX6UL_CLK_PLL1]);
@@ -220,13 +236,13 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CA7_SECONDARY_SEL] = imx_clk_mux("ca7_secondary_sel", base + 0xc, 3, 1, ca7_secondary_sels, ARRAY_SIZE(ca7_secondary_sels));
clks[IMX6UL_CLK_STEP] = imx_clk_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
- clks[IMX6UL_CLK_PLL1_SW] = imx_clk_mux_flags("pll1_sw", base + 0x0c, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels), 0);
+ clks[IMX6UL_CLK_PLL1_SW] = imx_clk_mux_glitchless("pll1_sw", base + 0x0c, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
clks[IMX6UL_CLK_AXI_ALT_SEL] = imx_clk_mux("axi_alt_sel", base + 0x14, 7, 1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
clks[IMX6UL_CLK_AXI_SEL] = imx_clk_mux_flags("axi_sel", base + 0x14, 6, 1, axi_sels, ARRAY_SIZE(axi_sels), 0);
- clks[IMX6UL_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
- clks[IMX6UL_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
- clks[IMX6UL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
- clks[IMX6UL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+ clks[IMX6UL_CLK_PERIPH_PRE] = imx_clk_mux_bus("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+ clks[IMX6UL_CLK_PERIPH2_PRE] = imx_clk_mux_bus("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+ clks[IMX6UL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux_bus("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clks[IMX6UL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux_bus("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
clks[IMX6UL_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels));
clks[IMX6UL_CLK_GPMI_SEL] = imx_clk_mux("gpmi_sel", base + 0x1c, 19, 1, gpmi_sels, ARRAY_SIZE(gpmi_sels));
clks[IMX6UL_CLK_BCH_SEL] = imx_clk_mux("bch_sel", base + 0x1c, 18, 1, bch_sels, ARRAY_SIZE(bch_sels));
@@ -238,15 +254,23 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
clks[IMX6UL_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels));
clks[IMX6UL_CLK_CAN_SEL] = imx_clk_mux("can_sel", base + 0x20, 8, 2, can_sels, ARRAY_SIZE(can_sels));
+ if (clk_on_imx6ull())
+ clks[IMX6UL_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, esai_sels, ARRAY_SIZE(esai_sels));
clks[IMX6UL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
clks[IMX6UL_CLK_ENFC_SEL] = imx_clk_mux("enfc_sel", base + 0x2c, 15, 3, enfc_sels, ARRAY_SIZE(enfc_sels));
clks[IMX6UL_CLK_LDB_DI0_SEL] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
clks[IMX6UL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
- clks[IMX6UL_CLK_SIM_PRE_SEL] = imx_clk_mux("sim_pre_sel", base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
- clks[IMX6UL_CLK_SIM_SEL] = imx_clk_mux("sim_sel", base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+ if (clk_on_imx6ul()) {
+ clks[IMX6UL_CLK_SIM_PRE_SEL] = imx_clk_mux("sim_pre_sel", base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
+ clks[IMX6UL_CLK_SIM_SEL] = imx_clk_mux("sim_sel", base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+ } else {
+ clks[IMX6UL_CLK_EPDC_PRE_SEL] = imx_clk_mux("epdc_pre_sel", base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
+ clks[IMX6UL_CLK_EPDC_SEL] = imx_clk_mux("epdc_sel", base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
+ }
clks[IMX6UL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
clks[IMX6UL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
+ clks[IMX6UL_CLK_CSI_SEL] = imx_clk_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT);
clks[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
clks[IMX6UL_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
@@ -276,13 +300,20 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_SAI3_PODF] = imx_clk_divider("sai3_podf", "sai3_pred", base + 0x28, 16, 6);
clks[IMX6UL_CLK_SAI1_PRED] = imx_clk_divider("sai1_pred", "sai1_sel", base + 0x28, 6, 3);
clks[IMX6UL_CLK_SAI1_PODF] = imx_clk_divider("sai1_podf", "sai1_pred", base + 0x28, 0, 6);
+ if (clk_on_imx6ull()) {
+ clks[IMX6UL_CLK_ESAI_PRED] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3);
+ clks[IMX6UL_CLK_ESAI_PODF] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3);
+ }
clks[IMX6UL_CLK_ENFC_PRED] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3);
clks[IMX6UL_CLK_ENFC_PODF] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6);
clks[IMX6UL_CLK_SAI2_PRED] = imx_clk_divider("sai2_pred", "sai2_sel", base + 0x2c, 6, 3);
clks[IMX6UL_CLK_SAI2_PODF] = imx_clk_divider("sai2_podf", "sai2_pred", base + 0x2c, 0, 6);
clks[IMX6UL_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
clks[IMX6UL_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
- clks[IMX6UL_CLK_SIM_PODF] = imx_clk_divider("sim_podf", "sim_pre_sel", base + 0x34, 12, 3);
+ if (clk_on_imx6ul())
+ clks[IMX6UL_CLK_SIM_PODF] = imx_clk_divider("sim_podf", "sim_pre_sel", base + 0x34, 12, 3);
+ else
+ clks[IMX6UL_CLK_EPDC_PODF] = imx_clk_divider("epdc_podf", "epdc_pre_sel", base + 0x34, 12, 3);
clks[IMX6UL_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel", base + 0x38, 19, 6);
clks[IMX6UL_CLK_LCDIF_PRED] = imx_clk_divider("lcdif_pred", "lcdif_pre_sel", base + 0x38, 12, 3);
clks[IMX6UL_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3);
@@ -298,9 +329,15 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_APBHDMA] = imx_clk_gate2("apbh_dma", "bch_podf", base + 0x68, 4);
clks[IMX6UL_CLK_ASRC_IPG] = imx_clk_gate2_shared("asrc_ipg", "ahb", base + 0x68, 6, &share_count_asrc);
clks[IMX6UL_CLK_ASRC_MEM] = imx_clk_gate2_shared("asrc_mem", "ahb", base + 0x68, 6, &share_count_asrc);
- clks[IMX6UL_CLK_CAAM_MEM] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8);
- clks[IMX6UL_CLK_CAAM_ACLK] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10);
- clks[IMX6UL_CLK_CAAM_IPG] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12);
+ if (clk_on_imx6ul()) {
+ clks[IMX6UL_CLK_CAAM_MEM] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8);
+ clks[IMX6UL_CLK_CAAM_ACLK] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10);
+ clks[IMX6UL_CLK_CAAM_IPG] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12);
+ } else {
+ clks[IMX6UL_CLK_DCP_CLK] = imx_clk_gate2("dcp", "ahb", base + 0x68, 10);
+ clks[IMX6UL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x68, 12);
+ clks[IMX6UL_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "ahb", base + 0x68, 12);
+ }
clks[IMX6UL_CLK_CAN1_IPG] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14);
clks[IMX6UL_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_podf", base + 0x68, 16);
clks[IMX6UL_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18);
@@ -309,7 +346,8 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_GPT2_SERIAL] = imx_clk_gate2("gpt2_serial", "perclk", base + 0x68, 26);
clks[IMX6UL_CLK_UART2_IPG] = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28);
clks[IMX6UL_CLK_UART2_SERIAL] = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28);
- clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30);
+ if (clk_on_imx6ul())
+ clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30);
/* CCGR1 */
clks[IMX6UL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_podf", base + 0x6c, 0);
@@ -328,6 +366,11 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24);
/* CCGR2 */
+ if (clk_on_imx6ull()) {
+ clks[IMX6UL_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x70, 0, &share_count_esai);
+ clks[IMX6UL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x70, 0, &share_count_esai);
+ clks[IMX6UL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x70, 0, &share_count_esai);
+ }
clks[IMX6UL_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x70, 2);
clks[IMX6UL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6);
clks[IMX6UL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8);
@@ -340,8 +383,13 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
/* CCGR3 */
clks[IMX6UL_CLK_UART5_IPG] = imx_clk_gate2("uart5_ipg", "ipg", base + 0x74, 2);
clks[IMX6UL_CLK_UART5_SERIAL] = imx_clk_gate2("uart5_serial", "uart_podf", base + 0x74, 2);
- clks[IMX6UL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x74, 4);
- clks[IMX6UL_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "ahb", base + 0x74, 4);
+ if (clk_on_imx6ul()) {
+ clks[IMX6UL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x74, 4);
+ clks[IMX6UL_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "ahb", base + 0x74, 4);
+ } else {
+ clks[IMX6UL_CLK_EPDC_ACLK] = imx_clk_gate2("epdc_aclk", "axi", base + 0x74, 4);
+ clks[IMX6UL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_podf", base + 0x74, 4);
+ }
clks[IMX6UL_CLK_UART6_IPG] = imx_clk_gate2("uart6_ipg", "ipg", base + 0x74, 6);
clks[IMX6UL_CLK_UART6_SERIAL] = imx_clk_gate2("uart6_serial", "uart_podf", base + 0x74, 6);
clks[IMX6UL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_podf", base + 0x74, 10);
@@ -385,12 +433,16 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
clks[IMX6UL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2);
clks[IMX6UL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
- clks[IMX6UL_CLK_SIM1] = imx_clk_gate2("sim1", "sim_sel", base + 0x80, 6);
- clks[IMX6UL_CLK_SIM2] = imx_clk_gate2("sim2", "sim_sel", base + 0x80, 8);
+ if (clk_on_imx6ul()) {
+ clks[IMX6UL_CLK_SIM1] = imx_clk_gate2("sim1", "sim_sel", base + 0x80, 6);
+ clks[IMX6UL_CLK_SIM2] = imx_clk_gate2("sim2", "sim_sel", base + 0x80, 8);
+ }
clks[IMX6UL_CLK_EIM] = imx_clk_gate2("eim", "eim_slow_podf", base + 0x80, 10);
clks[IMX6UL_CLK_PWM8] = imx_clk_gate2("pwm8", "perclk", base + 0x80, 16);
clks[IMX6UL_CLK_UART8_IPG] = imx_clk_gate2("uart8_ipg", "ipg", base + 0x80, 14);
clks[IMX6UL_CLK_UART8_SERIAL] = imx_clk_gate2("uart8_serial", "uart_podf", base + 0x80, 14);
+ if (clk_on_imx6ull())
+ clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x80, 18);
clks[IMX6UL_CLK_WDOG3] = imx_clk_gate2("wdog3", "ipg", base + 0x80, 20);
clks[IMX6UL_CLK_I2C4] = imx_clk_gate2("i2c4", "perclk", base + 0x80, 24);
clks[IMX6UL_CLK_PWM5] = imx_clk_gate2("pwm5", "perclk", base + 0x80, 26);
@@ -427,9 +479,16 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
/* set perclk to from OSC */
clk_set_parent(clks[IMX6UL_CLK_PERCLK_SEL], clks[IMX6UL_CLK_OSC]);
+ /* Set the UART parent if needed */
+ if (uart_from_osc)
+ imx_clk_set_parent(clks[IMX6UL_CLK_UART_SEL], clks[IMX6UL_CLK_OSC]);
+ else
+ imx_clk_set_parent(clks[IMX6UL_CLK_UART_SEL], clks[IMX6UL_CLK_PLL3_80M]);
+
clk_set_rate(clks[IMX6UL_CLK_ENET_REF], 50000000);
clk_set_rate(clks[IMX6UL_CLK_ENET2_REF], 50000000);
clk_set_rate(clks[IMX6UL_CLK_CSI], 24000000);
+ clk_set_rate(clks[IMX6UL_CLK_PLL3_PFD2], 320000000);
/* keep all the clks on just for bringup */
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
@@ -441,9 +500,23 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
}
clk_set_parent(clks[IMX6UL_CLK_CAN_SEL], clks[IMX6UL_CLK_PLL3_60M]);
- clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+ if (clk_on_imx6ul())
+ clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+ else
+ clk_set_parent(clks[IMX6UL_CLK_EPDC_PRE_SEL], clks[IMX6UL_CLK_PLL3_PFD2]);
clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
+
+ /* Lower the AHB clock rate before changing the clock source. */
+ imx_clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000);
+
+ /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
+ imx_clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+ imx_clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]);
+ imx_clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]);
+ imx_clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]);
+
+ imx_clk_set_rate(clks[IMX6UL_CLK_AHB], 132000000);
}
CLK_OF_DECLARE(imx6ul, "fsl,imx6ul-ccm", imx6ul_clocks_init);
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index e7c7353a86fc..ccc211989522 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014-2015 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
@@ -19,12 +20,16 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/types.h>
+#include <soc/imx/src.h>
#include "clk.h"
static u32 share_count_sai1;
static u32 share_count_sai2;
static u32 share_count_sai3;
+static u32 share_count_pxp;
+static u32 share_count_enet1;
+static u32 share_count_enet2;
static struct clk_div_table test_div_table[] = {
{ .val = 3, .div = 1, },
@@ -50,25 +55,25 @@ static const char *arm_a7_sel[] = { "osc", "pll_arm_main_clk",
static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk",
"pll_enet_250m_clk", "pll_sys_pfd2_270m_clk",
- "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
+ "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_post_div",
"pll_usb_main_clk", };
static const char *arm_m0_sel[] = { "osc", "pll_sys_main_120m_clk",
"pll_enet_125m_clk", "pll_sys_pfd2_135m_clk",
- "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
+ "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_post_div",
"pll_usb_main_clk", };
static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
"pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk",
- "pll_audio_post_div", "pll_video_main_clk", "pll_sys_pfd7_clk", };
+ "pll_audio_post_div", "pll_video_post_div", "pll_sys_pfd7_clk", };
static const char *disp_axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
"pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd6_clk",
- "pll_sys_pfd7_clk", "pll_audio_post_div", "pll_video_main_clk", };
+ "pll_sys_pfd7_clk", "pll_audio_post_div", "pll_video_post_div", };
static const char *enet_axi_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
"pll_dram_533m_clk", "pll_enet_250m_clk",
- "pll_sys_main_240m_clk", "pll_audio_post_div", "pll_video_main_clk",
+ "pll_sys_main_240m_clk", "pll_audio_post_div", "pll_video_post_div",
"pll_sys_pfd4_clk", };
static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
@@ -78,8 +83,8 @@ static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
"pll_dram_533m_clk", "pll_sys_pfd0_392m_clk",
- "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_post_div",
- "pll_video_main_clk", };
+ "pll_enet_250m_clk", "pll_usb_main_clk", "pll_audio_post_div",
+ "pll_video_post_div", };
static const char *dram_phym_sel[] = { "pll_dram_main_clk",
"dram_phym_alt_clk", };
@@ -90,7 +95,7 @@ static const char *dram_sel[] = { "pll_dram_main_clk",
static const char *dram_phym_alt_sel[] = { "osc", "pll_dram_533m_clk",
"pll_sys_main_clk", "pll_enet_500m_clk",
"pll_usb_main_clk", "pll_sys_pfd7_clk", "pll_audio_post_div",
- "pll_video_main_clk", };
+ "pll_video_post_div", };
static const char *dram_alt_sel[] = { "osc", "pll_dram_533m_clk",
"pll_sys_main_clk", "pll_enet_500m_clk",
@@ -112,62 +117,62 @@ static const char *pcie_phy_sel[] = { "osc", "pll_enet_100m_clk",
static const char *epdc_pixel_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
"pll_dram_533m_clk", "pll_sys_main_clk", "pll_sys_pfd5_clk",
- "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_main_clk", };
+ "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_post_div", };
static const char *lcdif_pixel_sel[] = { "osc", "pll_sys_pfd5_clk",
"pll_dram_533m_clk", "ext_clk_3", "pll_sys_pfd4_clk",
- "pll_sys_pfd2_270m_clk", "pll_video_main_clk",
+ "pll_sys_pfd2_270m_clk", "pll_video_post_div",
"pll_usb_main_clk", };
static const char *mipi_dsi_sel[] = { "osc", "pll_sys_pfd5_clk",
"pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk",
- "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_post_div", };
+ "pll_dram_533m_clk", "pll_video_post_div", "pll_audio_post_div", };
static const char *mipi_csi_sel[] = { "osc", "pll_sys_pfd4_clk",
"pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk",
- "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_post_div", };
+ "pll_dram_533m_clk", "pll_video_post_div", "pll_audio_post_div", };
static const char *mipi_dphy_sel[] = { "osc", "pll_sys_main_120m_clk",
"pll_dram_533m_clk", "pll_sys_pfd5_clk", "ref_1m_clk", "ext_clk_2",
- "pll_video_main_clk", "ext_clk_3", };
+ "pll_video_post_div", "ext_clk_3", };
static const char *sai1_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
- "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main_clk",
+ "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_post_div",
"pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", };
static const char *sai2_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
- "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main_clk",
+ "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_post_div",
"pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", };
static const char *sai3_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
- "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main_clk",
+ "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_post_div",
"pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_3", };
static const char *spdif_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
- "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main_clk",
+ "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_post_div",
"pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_3_clk", };
static const char *enet1_ref_sel[] = { "osc", "pll_enet_125m_clk",
"pll_enet_50m_clk", "pll_enet_25m_clk",
- "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_main_clk",
+ "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_post_div",
"ext_clk_4", };
static const char *enet1_time_sel[] = { "osc", "pll_enet_100m_clk",
"pll_audio_post_div", "ext_clk_1", "ext_clk_2", "ext_clk_3",
- "ext_clk_4", "pll_video_main_clk", };
+ "ext_clk_4", "pll_video_post_div", };
static const char *enet2_ref_sel[] = { "osc", "pll_enet_125m_clk",
"pll_enet_50m_clk", "pll_enet_25m_clk",
- "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_main_clk",
+ "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_post_div",
"ext_clk_4", };
static const char *enet2_time_sel[] = { "osc", "pll_enet_100m_clk",
"pll_audio_post_div", "ext_clk_1", "ext_clk_2", "ext_clk_3",
- "ext_clk_4", "pll_video_main_clk", };
+ "ext_clk_4", "pll_video_post_div", };
static const char *enet_phy_ref_sel[] = { "osc", "pll_enet_25m_clk",
"pll_enet_50m_clk", "pll_enet_125m_clk",
- "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
+ "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_post_div",
"pll_sys_pfd3_clk", };
static const char *eim_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
@@ -178,7 +183,7 @@ static const char *eim_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
static const char *nand_sel[] = { "osc", "pll_sys_main_clk",
"pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd3_clk",
"pll_enet_500m_clk", "pll_enet_250m_clk",
- "pll_video_main_clk", };
+ "pll_video_post_div", };
static const char *qspi_sel[] = { "osc", "pll_sys_pfd4_clk",
"pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd3_clk",
@@ -208,22 +213,22 @@ static const char *can2_sel[] = { "osc", "pll_sys_main_120m_clk",
static const char *i2c1_sel[] = { "osc", "pll_sys_main_120m_clk",
"pll_enet_50m_clk", "pll_dram_533m_clk",
- "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk",
+ "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk",
"pll_sys_pfd2_135m_clk", };
static const char *i2c2_sel[] = { "osc", "pll_sys_main_120m_clk",
"pll_enet_50m_clk", "pll_dram_533m_clk",
- "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk",
+ "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk",
"pll_sys_pfd2_135m_clk", };
static const char *i2c3_sel[] = { "osc", "pll_sys_main_120m_clk",
"pll_enet_50m_clk", "pll_dram_533m_clk",
- "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk",
+ "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk",
"pll_sys_pfd2_135m_clk", };
static const char *i2c4_sel[] = { "osc", "pll_sys_main_120m_clk",
"pll_enet_50m_clk", "pll_dram_533m_clk",
- "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk",
+ "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk",
"pll_sys_pfd2_135m_clk", };
static const char *uart1_sel[] = { "osc", "pll_sys_main_240m_clk",
@@ -283,27 +288,27 @@ static const char *ecspi4_sel[] = { "osc", "pll_sys_main_240m_clk",
static const char *pwm1_sel[] = { "osc", "pll_enet_100m_clk",
"pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
- "ext_clk_1", "ref_1m_clk", "pll_video_main_clk", };
+ "ext_clk_1", "ref_1m_clk", "pll_video_post_div", };
static const char *pwm2_sel[] = { "osc", "pll_enet_100m_clk",
"pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
- "ext_clk_1", "ref_1m_clk", "pll_video_main_clk", };
+ "ext_clk_1", "ref_1m_clk", "pll_video_post_div", };
static const char *pwm3_sel[] = { "osc", "pll_enet_100m_clk",
"pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
- "ext_clk_2", "ref_1m_clk", "pll_video_main_clk", };
+ "ext_clk_2", "ref_1m_clk", "pll_video_post_div", };
static const char *pwm4_sel[] = { "osc", "pll_enet_100m_clk",
"pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
- "ext_clk_2", "ref_1m_clk", "pll_video_main_clk", };
+ "ext_clk_2", "ref_1m_clk", "pll_video_post_div", };
static const char *flextimer1_sel[] = { "osc", "pll_enet_100m_clk",
"pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
- "ext_clk_3", "ref_1m_clk", "pll_video_main_clk", };
+ "ext_clk_3", "ref_1m_clk", "pll_video_post_div", };
static const char *flextimer2_sel[] = { "osc", "pll_enet_100m_clk",
"pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
- "ext_clk_3", "ref_1m_clk", "pll_video_main_clk", };
+ "ext_clk_3", "ref_1m_clk", "pll_video_post_div", };
static const char *sim1_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
"pll_sys_main_120m_clk", "pll_dram_533m_clk",
@@ -312,23 +317,23 @@ static const char *sim1_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
static const char *sim2_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
"pll_sys_main_120m_clk", "pll_dram_533m_clk",
- "pll_usb_main_clk", "pll_video_main_clk", "pll_enet_125m_clk",
+ "pll_usb_main_clk", "pll_video_post_div", "pll_enet_125m_clk",
"pll_sys_pfd7_clk", };
static const char *gpt1_sel[] = { "osc", "pll_enet_100m_clk",
- "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk",
+ "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_post_div",
"ref_1m_clk", "pll_audio_post_div", "ext_clk_1", };
static const char *gpt2_sel[] = { "osc", "pll_enet_100m_clk",
- "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk",
+ "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_post_div",
"ref_1m_clk", "pll_audio_post_div", "ext_clk_2", };
static const char *gpt3_sel[] = { "osc", "pll_enet_100m_clk",
- "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk",
+ "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_post_div",
"ref_1m_clk", "pll_audio_post_div", "ext_clk_3", };
static const char *gpt4_sel[] = { "osc", "pll_enet_100m_clk",
- "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk",
+ "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_post_div",
"ref_1m_clk", "pll_audio_post_div", "ext_clk_4", };
static const char *trace_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
@@ -343,12 +348,12 @@ static const char *wdog_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
static const char *csi_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
"pll_sys_main_120m_clk", "pll_dram_533m_clk",
- "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_main_clk",
+ "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_post_div",
"pll_usb_main_clk", };
static const char *audio_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
"pll_sys_main_120m_clk", "pll_dram_533m_clk",
- "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_main_clk",
+ "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_post_div",
"pll_usb_main_clk", };
static const char *wrclk_sel[] = { "osc", "pll_enet_40m_clk",
@@ -362,13 +367,13 @@ static const char *clko1_sel[] = { "osc", "pll_sys_main_clk",
static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk",
"pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk",
- "pll_audio_post_div", "pll_video_main_clk", "ckil", };
+ "pll_audio_post_div", "pll_video_post_div", "ckil", };
static const char *lvds1_sel[] = { "pll_arm_main_clk",
"pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk",
"pll_sys_pfd2_270m_clk", "pll_sys_pfd3_clk", "pll_sys_pfd4_clk",
"pll_sys_pfd5_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk",
- "pll_audio_post_div", "pll_video_main_clk", "pll_enet_500m_clk",
+ "pll_audio_post_div", "pll_video_post_div", "pll_enet_500m_clk",
"pll_enet_250m_clk", "pll_enet_125m_clk", "pll_enet_100m_clk",
"pll_enet_50m_clk", "pll_enet_40m_clk", "pll_enet_25m_clk",
"pll_dram_main_clk", };
@@ -386,7 +391,7 @@ static int const clks_init_on[] __initconst = {
IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK,
IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK,
IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK,
- IMX7D_AHB_CHANNEL_ROOT_CLK,
+ IMX7D_AHB_CHANNEL_ROOT_CLK, IMX7D_IPG_ROOT_CLK,
};
static struct clk_onecell_data clk_data;
@@ -424,11 +429,11 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
clks[IMX7D_PLL_ARM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "osc", base + 0x60, 0x7f);
- clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_dram_main", "osc", base + 0x70, 0x7f);
+ clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_dram_main", "osc", base + 0x70, 0x7f);
clks[IMX7D_PLL_SYS_MAIN] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1);
clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0);
- clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "osc", base + 0xf0, 0x7f);
- clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "osc", base + 0x130, 0x7f);
+ clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_audio_main", "osc", base + 0xf0, 0x7f);
+ clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_video_main", "osc", base + 0x130, 0x7f);
clks[IMX7D_PLL_ARM_MAIN_BYPASS] = imx_clk_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT);
clks[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT);
@@ -437,23 +442,22 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_PLL_AUDIO_MAIN_BYPASS] = imx_clk_mux_flags("pll_audio_main_bypass", base + 0xf0, 16, 1, pll_audio_bypass_sel, ARRAY_SIZE(pll_audio_bypass_sel), CLK_SET_RATE_PARENT);
clks[IMX7D_PLL_VIDEO_MAIN_BYPASS] = imx_clk_mux_flags("pll_video_main_bypass", base + 0x130, 16, 1, pll_video_bypass_sel, ARRAY_SIZE(pll_video_bypass_sel), CLK_SET_RATE_PARENT);
- clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]);
- clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]);
- clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]);
- clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], clks[IMX7D_PLL_ENET_MAIN]);
- clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], clks[IMX7D_PLL_AUDIO_MAIN]);
- clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], clks[IMX7D_PLL_VIDEO_MAIN]);
-
clks[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_gate("pll_arm_main_clk", "pll_arm_main_bypass", base + 0x60, 13);
- clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", "pll_dram_main_bypass", base + 0x70, 13);
+ clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", "pll_dram_test_div", base + 0x70, 13);
clks[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_gate("pll_sys_main_clk", "pll_sys_main_bypass", base + 0xb0, 13);
- clks[IMX7D_PLL_AUDIO_MAIN_CLK] = imx_clk_gate("pll_audio_main_clk", "pll_audio_main_bypass", base + 0xf0, 13);
- clks[IMX7D_PLL_VIDEO_MAIN_CLK] = imx_clk_gate("pll_video_main_clk", "pll_video_main_bypass", base + 0x130, 13);
+ clks[IMX7D_PLL_AUDIO_MAIN_CLK] = imx_clk_gate("pll_audio_main_clk", "pll_audio_test_div", base + 0xf0, 13);
+ clks[IMX7D_PLL_VIDEO_MAIN_CLK] = imx_clk_gate("pll_video_main_clk", "pll_video_test_div", base + 0x130, 13);
- clks[IMX7D_PLL_AUDIO_TEST_DIV] = clk_register_divider_table(NULL, "pll_audio_test_div", "pll_audio_main_clk",
+ clks[IMX7D_PLL_DRAM_TEST_DIV] = clk_register_divider_table(NULL, "pll_dram_test_div", "pll_dram_main_bypass",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 21, 2, 0, test_div_table, &imx_ccm_lock);
+ clks[IMX7D_PLL_AUDIO_TEST_DIV] = clk_register_divider_table(NULL, "pll_audio_test_div", "pll_audio_main_bypass",
CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xf0, 19, 2, 0, test_div_table, &imx_ccm_lock);
- clks[IMX7D_PLL_AUDIO_POST_DIV] = clk_register_divider_table(NULL, "pll_audio_post_div", "pll_audio_test_div",
+ clks[IMX7D_PLL_AUDIO_POST_DIV] = clk_register_divider_table(NULL, "pll_audio_post_div", "pll_audio_main_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xf0, 22, 2, 0, post_div_table, &imx_ccm_lock);
+ clks[IMX7D_PLL_VIDEO_TEST_DIV] = clk_register_divider_table(NULL, "pll_video_test_div", "pll_video_main_bypass",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x130, 19, 2, 0, test_div_table, &imx_ccm_lock);
+ clks[IMX7D_PLL_VIDEO_POST_DIV] = clk_register_divider_table(NULL, "pll_video_post_div", "pll_video_main_clk",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x130, 22, 2, 0, post_div_table, &imx_ccm_lock);
clks[IMX7D_PLL_SYS_PFD0_392M_CLK] = imx_clk_pfd("pll_sys_pfd0_392m_clk", "pll_sys_main_clk", base + 0xc0, 0);
clks[IMX7D_PLL_SYS_PFD1_332M_CLK] = imx_clk_pfd("pll_sys_pfd1_332m_clk", "pll_sys_main_clk", base + 0xc0, 1);
@@ -523,7 +527,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux2("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel));
clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux2("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel));
clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux2("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel));
- clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux2("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel));
+ clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux_flags("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux2("mipi_dsi_src", base + 0xa380, 24, 3, mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel));
clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux2("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel));
clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux2("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel));
@@ -718,14 +722,15 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider2("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3);
clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider2("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3);
- clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3);
+ clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider_flags("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider2("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3);
- clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
+ clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider_flags("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6, CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
- clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider2("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
- clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6);
+ clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
+ clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_divider_flags("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6, CLK_OPS_PARENT_ENABLE);
+ clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider2("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2);
clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
@@ -736,7 +741,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider2("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6);
clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider2("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6);
clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider2("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6);
- clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider2("mipi_dphy_post_div", "mipi_csi_dphy_div", base + 0xa480, 0, 6);
+ clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider2("mipi_dphy_post_div", "mipi_dphy_pre_div", base + 0xa480, 0, 6);
clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider2("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6);
clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider2("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6);
clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider2("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6);
@@ -789,21 +794,23 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6);
clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6);
- clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0);
+ clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2_flags("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate4("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0);
clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0);
clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0);
- clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_post_div", base + 0x4120, 0);
- clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate4("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0);
- clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate4("ahb_root_clk", "ahb_post_div", base + 0x4200, 0);
+ clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
+ clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
- clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0);
+ clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate4("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
+ clks[IMX7D_SEMA4_HS_ROOT_CLK] = imx_clk_gate4("sema4_hs_root_clk", "ipg_root_clk", base + 0x4280, 0);
+ clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
+ clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4690, 0);
clks[IMX7D_SDMA_CORE_CLK] = imx_clk_gate4("sdma_root_clk", "ahb_root_clk", base + 0x4480, 0);
clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0);
clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate4("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0);
@@ -812,6 +819,10 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate4("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0);
clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate4("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0);
clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate4("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0);
+ clks[IMX7D_ENET1_IPG_ROOT_CLK] = imx_clk_gate2_shared2("enet1_ipg_root_clk", "enet_axi_post_div", base + 0x4700, 0, &share_count_enet1);
+ clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate2_shared2("enet1_time_root_clk", "enet1_time_post_div", base + 0x4700, 0, &share_count_enet1);
+ clks[IMX7D_ENET2_IPG_ROOT_CLK] = imx_clk_gate2_shared2("enet2_ipg_root_clk", "enet_axi_post_div", base + 0x4710, 0, &share_count_enet2);
+ clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate2_shared2("enet2_time_root_clk", "enet2_time_post_div", base + 0x4710, 0, &share_count_enet2);
clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate2_shared2("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0, &share_count_sai1);
clks[IMX7D_SAI1_IPG_CLK] = imx_clk_gate2_shared2("sai1_ipg_clk", "ipg_root_clk", base + 0x48c0, 0, &share_count_sai1);
clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate2_shared2("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0, &share_count_sai2);
@@ -819,13 +830,8 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate2_shared2("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0, &share_count_sai3);
clks[IMX7D_SAI3_IPG_CLK] = imx_clk_gate2_shared2("sai3_ipg_clk", "ipg_root_clk", base + 0x48e0, 0, &share_count_sai3);
clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate4("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0);
- clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate4("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x44e0, 0);
- clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate4("enet1_time_root_clk", "enet1_time_post_div", base + 0x44f0, 0);
- clks[IMX7D_ENET2_REF_ROOT_CLK] = imx_clk_gate4("enet2_ref_root_clk", "enet2_ref_post_div", base + 0x4500, 0);
- clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate4("enet2_time_root_clk", "enet2_time_post_div", base + 0x4510, 0);
- clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate4("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0);
clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate4("eim_root_clk", "eim_post_div", base + 0x4160, 0);
- clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate4("nand_root_clk", "nand_post_div", base + 0x4140, 0);
+ clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate2_flags("nand_root_clk", "nand_post_div", base + 0x4140, 0, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate4("qspi_root_clk", "qspi_post_div", base + 0x4150, 0);
clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate4("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0);
clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate4("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0);
@@ -867,7 +873,12 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
+ clks[IMX7D_USB_CTRL_CLK] = imx_clk_gate4("usb_ctrl_clk", "ahb_root_clk", base + 0x4680, 0);
+ clks[IMX7D_USB_PHY1_CLK] = imx_clk_gate4("usb_phy1_clk", "pll_usb1_main_clk", base + 0x46a0, 0);
+ clks[IMX7D_USB_PHY2_CLK] = imx_clk_gate4("usb_phy2_clk", "pll_usb_main_clk", base + 0x46b0, 0);
clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate4("adc_root_clk", "ipg_root_clk", base + 0x4200, 0);
+ clks[IMX7D_PXP_IPG_CLK] = imx_clk_gate2_shared2("pxp_ipg_clk", "ipg_root_clk", base + 0x44c0, 0, &share_count_pxp);
+ clks[IMX7D_PXP_AXI_CLK] = imx_clk_gate2_shared2("pxp_axi_clk", "main_axi_root_clk", base + 0x44c0, 0, &share_count_pxp);
clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
@@ -886,13 +897,57 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clks[clks_init_on[i]]);
+ if (imx_src_is_m4_enabled()) {
+ imx_clk_set_parent(clks[IMX7D_ARM_M4_ROOT_SRC], clks[IMX7D_PLL_SYS_MAIN_240M_CLK]);
+ imx_clk_prepare_enable(clks[IMX7D_ARM_M4_ROOT_CLK]);
+ }
+
+ imx_clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]);
+ imx_clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]);
+ imx_clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]);
+ imx_clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], clks[IMX7D_PLL_ENET_MAIN]);
+ imx_clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], clks[IMX7D_PLL_AUDIO_MAIN]);
+ imx_clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], clks[IMX7D_PLL_VIDEO_MAIN]);
+
/* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */
- clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
+ imx_clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
- /* set uart module clock's parent clock source that must be great then 80MHz */
- clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
+ /*
+ * init enet clock source:
+ * AXI clock source is 250Mhz
+ * Phy refrence clock is 25Mhz
+ * 1588 time clock source is 100Mhz
+ */
+ imx_clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]);
+ imx_clk_set_rate(clks[IMX7D_ENET_AXI_ROOT_CLK], 267000000);
+ imx_clk_set_parent(clks[IMX7D_ENET_PHY_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_25M_CLK]);
- imx_register_uart_clocks(uart_clks);
+ /* set pcie root's parent clk source */
+ imx_clk_set_parent(clks[IMX7D_PCIE_CTRL_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]);
+ imx_clk_set_parent(clks[IMX7D_PCIE_PHY_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]);
+
+ /* Set clock rate for USBPHY, the USB_PLL at CCM is from USBOTG2 */
+ clks[IMX7D_USB1_MAIN_480M_CLK] = imx_clk_fixed_factor("pll_usb1_main_clk", "osc", 20, 1);
+ clks[IMX7D_USB_MAIN_480M_CLK] = imx_clk_fixed_factor("pll_usb_main_clk", "osc", 20, 1);
+
+ /* set parent of EPDC pixel clock */
+ imx_clk_set_parent(clks[IMX7D_EPDC_PIXEL_ROOT_SRC], clks[IMX7D_PLL_SYS_MAIN_CLK]);
+ /* set lcdif pixel root clock source to get the required 33Mhz clock */
+ imx_clk_set_parent(clks[IMX7D_LCDIF_PIXEL_ROOT_SRC], clks[IMX7D_PLL_VIDEO_POST_DIV]);
+
+ imx_clk_set_parent(clks[IMX7D_MIPI_CSI_ROOT_SRC], clks[IMX7D_PLL_SYS_PFD3_CLK]);
+
+ /* set parent of SIM1 root clock */
+ imx_clk_set_parent(clks[IMX7D_SIM1_ROOT_SRC], clks[IMX7D_PLL_SYS_MAIN_120M_CLK]);
+
+ imx_clk_set_parent(clks[IMX7D_UART3_ROOT_SRC], clks[IMX7D_PLL_SYS_MAIN_240M_CLK]);
+ imx_clk_set_rate(clks[IMX7D_UART3_ROOT_DIV], 80000000);
+ imx_clk_set_parent(clks[IMX7D_UART5_ROOT_SRC], clks[IMX7D_PLL_SYS_MAIN_240M_CLK]);
+ imx_clk_set_rate(clks[IMX7D_UART5_ROOT_DIV], 80000000);
+ imx_clk_set_parent(clks[IMX7D_UART6_ROOT_SRC], clks[IMX7D_PLL_SYS_MAIN_240M_CLK]);
+ imx_clk_set_rate(clks[IMX7D_UART6_ROOT_DIV], 80000000);
+
+ imx_register_uart_clocks(uart_clks);
}
CLK_OF_DECLARE(imx7d, "fsl,imx7d-ccm", imx7d_clocks_init);
diff --git a/drivers/clk/imx/clk-imx7ulp.c b/drivers/clk/imx/clk-imx7ulp.c
new file mode 100644
index 000000000000..0de0b161a1e3
--- /dev/null
+++ b/drivers/clk/imx/clk-imx7ulp.c
@@ -0,0 +1,298 @@
+/*
+ * 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 <dt-bindings/clock/imx7ulp-clock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+static const char *pll_pre_sels[] = { "osc", "firc", };
+static const char *spll_pfd_sels[] = { "spll_pfd0", "spll_pfd1", "spll_pfd2", "spll_pfd3", };
+static const char *spll_sels[] = { "spll", "spll_pfd_sel", };
+static const char *apll_pfd_sels[] = { "apll_pfd0", "apll_pfd1", "apll_pfd2", "apll_pfd3", };
+static const char *apll_sels[] = { "apll", "apll_pfd_sel", };
+static const char *sys_sels[] = { "dummy", "osc", "sirc", "firc", "ckil", "apll_sel", "spll_sel", "upll", };
+static const char *arm_sels[] = { "core_div", "hsrun_core", };
+static const char *ddr_sels[] = { "apll_pfd_sel", "upll", };
+static const char *nic_sels[] = { "firc", "ddr_div", };
+static const char *periph_plat_sels[] = { "dummy", "nic1_bus", "nic1_div", "ddr_div", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
+/* the dummy in only a space holder of spll_bus clk */
+static const char *periph_slow_sels[] = { "dummy", "osc", "dummy", "firc", "ckil", "nic1_bus", "nic1_div", "dummy", };
+static struct clk *clks[IMX7ULP_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static const char *cm4_pll_pre_sels[] = { "cm4_osc", "cm4_firc", };
+static const char *cm4_spll_pfd_sels[] = { "cm4_spll_pfd0", "cm4_spll_pfd1", "cm4_spll_pfd2", "cm4_spll_pfd3", };
+static const char *cm4_spll_sels[] = { "cm4_spll_vco", "cm4_spll_pfd_sel", };
+static const char *cm4_apll_pfd_sels[] = { "cm4_apll_pfd0", "cm4_apll_pfd1", "cm4_apll_pfd2", "cm4_apll_pfd3", };
+static const char *cm4_apll_sels[] = { "cm4_apll_vco_post_div2", "cm4_apll_pfd_sel", };
+static const char *cm4_sys_sels[] = { "cm4_dummy", "cm4_osc", "cm4_sirc", "cm4_firc", "cm4_ckil", "cm4_apll_sel", "cm4_spll_sel", "cm4_dummy", };
+static const char *cm4_periph_slow_sels[] = { "cm4_dummy", "cm4_osc", "cm4_sirc", "cm4_firc", "cm4_ckil", "cm4_bus_div", "cm4_spll_pfd2", "cm4_apll_pfd0_pre_div", };
+static const char *scg0_clkout_sels[] = { "dummy", "cm4_osc", "cm4_sirc", "cm4_firc", "cm4_ckil", "cm4_apll_sel", "cm4_spll_sel", "dummy"};
+static struct clk *clks_cm4[IMX7ULP_CM4_CLK_END];
+static struct clk_onecell_data clk_data_cm4;
+
+
+static int const clks_init_on[] __initconst = {
+ IMX7ULP_CLK_BUS_DIV,
+ IMX7ULP_CLK_ARM,
+ IMX7ULP_CLK_NIC0_DIV,
+ IMX7ULP_CLK_NIC1_DIV,
+ IMX7ULP_CLK_NIC1_BUS_DIV,
+ IMX7ULP_CLK_MMDC,
+ IMX7ULP_CLK_RGPIO2P1,
+ IMX7ULP_CLK_PCTLC,
+ IMX7ULP_CLK_PCTLD,
+ IMX7ULP_CLK_PCTLE,
+ IMX7ULP_CLK_PCTLF,
+};
+
+static void __init imx7ulp_clocks_init(struct device_node *scg_node)
+{
+ struct device_node *np;
+ void __iomem *base;
+ int i;
+
+ clks[IMX7ULP_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+
+ clks[IMX7ULP_CLK_CKIL] = of_clk_get_by_name(scg_node, "ckil");
+ clks[IMX7ULP_CLK_OSC] = of_clk_get_by_name(scg_node, "osc");
+ clks[IMX7ULP_CLK_SIRC] = of_clk_get_by_name(scg_node, "sirc");
+ clks[IMX7ULP_CLK_FIRC] = of_clk_get_by_name(scg_node, "firc");
+ clks[IMX7ULP_CLK_MIPI_PLL] = of_clk_get_by_name(scg_node, "mpll");
+ clks[IMX7ULP_CLK_UPLL] = of_clk_get_by_name(scg_node, "upll");
+
+ np = scg_node;
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ clks[IMX7ULP_CLK_SPLL_PRE_SEL] = imx_clk_mux("spll_pre_sel", base + 0x608, 0, 1, pll_pre_sels, ARRAY_SIZE(pll_pre_sels));
+ clks[IMX7ULP_CLK_APLL_PRE_SEL] = imx_clk_mux("apll_pre_sel", base + 0x508, 0, 1, pll_pre_sels, ARRAY_SIZE(pll_pre_sels));
+ /* name parent_name reg shift width */
+ clks[IMX7ULP_CLK_SPLL_PRE_DIV] = imx_clk_divider("spll_pre_div", "spll_pre_sel", base + 0x608, 8, 3);
+ clks[IMX7ULP_CLK_APLL_PRE_DIV] = imx_clk_divider("apll_pre_div", "apll_pre_sel", base + 0x508, 8, 3);
+ /* name parent_name base*/
+ clks[IMX7ULP_CLK_SPLL] = imx_clk_pllv4("spll", "spll_pre_div", base + 0x600);
+ clks[IMX7ULP_CLK_APLL] = imx_clk_pllv4("apll", "apll_pre_div", base + 0x500);
+
+ /* SPLL PFDs */
+ clks[IMX7ULP_CLK_SPLL_PFD0] = imx_clk_pfdv2("spll_pfd0", "spll", base + 0x60C, 0);
+ clks[IMX7ULP_CLK_SPLL_PFD1] = imx_clk_pfdv2("spll_pfd1", "spll", base + 0x60C, 1);
+ clks[IMX7ULP_CLK_SPLL_PFD2] = imx_clk_pfdv2("spll_pfd2", "spll", base + 0x60C, 2);
+ clks[IMX7ULP_CLK_SPLL_PFD3] = imx_clk_pfdv2("spll_pfd3", "spll", base + 0x60C, 3);
+ /* APLL PFDs */
+ clks[IMX7ULP_CLK_APLL_PFD0] = imx_clk_pfdv2("apll_pfd0", "apll", base + 0x50C, 0);
+ clks[IMX7ULP_CLK_APLL_PFD1] = imx_clk_pfdv2("apll_pfd1", "apll", base + 0x50C, 1);
+ clks[IMX7ULP_CLK_APLL_PFD2] = imx_clk_pfdv2("apll_pfd2", "apll", base + 0x50C, 2);
+ clks[IMX7ULP_CLK_APLL_PFD3] = imx_clk_pfdv2("apll_pfd3", "apll", base + 0x50C, 3);
+
+ clks[IMX7ULP_CLK_SPLL_PFD_SEL] = imx_clk_mux("spll_pfd_sel", base + 0x608, 14, 2, spll_pfd_sels, ARRAY_SIZE(spll_pfd_sels));
+ clks[IMX7ULP_CLK_APLL_PFD_SEL] = imx_clk_mux("apll_pfd_sel", base + 0x508, 14, 2, apll_pfd_sels, ARRAY_SIZE(apll_pfd_sels));
+
+ clks[IMX7ULP_CLK_SPLL_SEL] = imx_clk_mux("spll_sel", base + 0x608, 1, 1, spll_sels, ARRAY_SIZE(spll_sels));
+ clks[IMX7ULP_CLK_APLL_SEL] = imx_clk_mux("apll_sel", base + 0x508, 1, 1, apll_sels, ARRAY_SIZE(apll_sels));
+
+ clks[IMX7ULP_CLK_SYS_SEL] = imx_clk_mux_glitchless("sys_sel", base + 0x14, 24, 4, sys_sels, ARRAY_SIZE(sys_sels));
+ clks[IMX7ULP_CLK_HSRUN_SYS_SEL] = imx_clk_mux_glitchless("hsrun_sys_sel", base + 0x1c, 24, 4, sys_sels, ARRAY_SIZE(sys_sels));
+ clks[IMX7ULP_CLK_DDR_SEL] = imx_clk_mux("ddr_sel", base + 0x30, 24, 1, ddr_sels, ARRAY_SIZE(ddr_sels));
+ clks[IMX7ULP_CLK_NIC_SEL] = imx_clk_mux("nic_sel", base + 0x40, 28, 1, nic_sels, ARRAY_SIZE(nic_sels));
+
+ clks[IMX7ULP_CLK_CORE_DIV] = imx_clk_divider_flags("core_div", "sys_sel", base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
+ clks[IMX7ULP_CLK_HSRUN_CORE] = imx_clk_divider_flags("hsrun_core", "hsrun_sys_sel", base + 0x1c, 16, 4, CLK_SET_RATE_PARENT);
+ clks[IMX7ULP_CLK_PLAT_DIV] = imx_clk_divider("plat_div", "core_div", base + 0x14, 12, 4);
+ /* Fake mux */
+ clks[IMX7ULP_CLK_ARM] = imx_clk_mux_glitchless("arm", base + 0x14, 5, 1, arm_sels, ARRAY_SIZE(arm_sels));
+
+ clks[IMX7ULP_CLK_DDR_DIV] = clk_register_divider(NULL, "ddr_div", "ddr_sel", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x30, 0, 3, CLK_DIVIDER_ONE_BASED, &imx_ccm_lock);
+ clks[IMX7ULP_CLK_NIC0_DIV] = imx_clk_divider("nic0_div", "nic_sel", base + 0x40, 24, 4);
+ clks[IMX7ULP_CLK_GPU_DIV] = imx_clk_divider("gpu_div", "nic0_div", base + 0x40, 20, 4);
+ clks[IMX7ULP_CLK_NIC1_DIV] = imx_clk_divider("nic1_div", "nic0_div", base + 0x40, 16, 4);
+ clks[IMX7ULP_CLK_NIC1_BUS_DIV] = imx_clk_divider("nic1_bus", "nic1_div", base + 0x40, 4, 4);
+
+ /* PCC2 */
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pcc2");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ clks[IMX7ULP_CLK_DMA1] = imx_clk_gate("dma1", "nic1_bus", base + 0x20, 30);
+ clks[IMX7ULP_CLK_RGPIO2P1] = imx_clk_gate("gpio", "nic1_bus", base + 0x3c, 30);
+ clks[IMX7ULP_CLK_DMA_MUX1] = imx_clk_gate("dma_mux1", "nic1_bus", base + 0x84, 30);
+ clks[IMX7ULP_CLK_SNVS] = imx_clk_gate("snvs", "nic1_bus", base + 0x8c, 30);
+ clks[IMX7ULP_CLK_CAAM] = imx_clk_gate("caam", "nic1_div", base + 0x90, 30);
+ clks[IMX7ULP_CLK_LPTPM4] = imx_clk_composite("lptpm4", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x94);
+ clks[IMX7ULP_CLK_LPTPM5] = imx_clk_composite("lptmp5", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x98);
+ clks[IMX7ULP_CLK_LPIT1] = imx_clk_composite("lpit1", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x9C);
+ clks[IMX7ULP_CLK_LPSPI2] = imx_clk_composite("lpspi2", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xA4);
+ clks[IMX7ULP_CLK_LPSPI3] = imx_clk_composite("lpspi3", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xA8);
+ clks[IMX7ULP_CLK_LPI2C4] = imx_clk_composite("lpi2c4", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xAC);
+ clks[IMX7ULP_CLK_LPI2C5] = imx_clk_composite("lpi2c5", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xB0);
+ clks[IMX7ULP_CLK_LPUART4] = imx_clk_composite("lpuart4", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xB4);
+ clks[IMX7ULP_CLK_LPUART5] = imx_clk_composite("lpuart5", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xB8);
+ clks[IMX7ULP_CLK_FLEXIO1] = imx_clk_composite("flexio", periph_slow_sels, ARRAY_SIZE(periph_plat_sels), true, false, true, base + 0xC4);
+ clks[IMX7ULP_CLK_USB0] = imx_clk_composite("usb0", periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true, true, base + 0xCC);
+ clks[IMX7ULP_CLK_USB1] = imx_clk_composite("usb1", periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true, true, base + 0xD0);
+ clks[IMX7ULP_CLK_USB_PHY] = imx_clk_gate("usb_phy", "nic1_bus", base + 0xD4, 30);
+ clks[IMX7ULP_CLK_USDHC0] = imx_clk_composite("usdhc0", periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true, true, base + 0xDC);
+ clks[IMX7ULP_CLK_USDHC1] = imx_clk_composite("usdhc1", periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true, true, base + 0xE0);
+ clks[IMX7ULP_CLK_WDG1] = imx_clk_composite("wdg1", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, true, true, base + 0xF4);
+ clks[IMX7ULP_CLK_WDG2] = imx_clk_composite("sdg2", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, true, true, base + 0x10C);
+
+ /* PCC3 */
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pcc3");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ clks[IMX7ULP_CLK_LPTPM6] = imx_clk_composite("lptpm6", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x84);
+ clks[IMX7ULP_CLK_LPTPM7] = imx_clk_composite("lptpm7", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x88);
+ clks[IMX7ULP_CLK_LPI2C6] = imx_clk_composite("lpi2c6", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x90);
+ clks[IMX7ULP_CLK_LPI2C7] = imx_clk_composite("lpi2c7", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x94);
+ clks[IMX7ULP_CLK_LPUART6] = imx_clk_composite("lpuart6", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x98);
+ clks[IMX7ULP_CLK_LPUART7] = imx_clk_composite("lpuart7", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x9C);
+ clks[IMX7ULP_CLK_VIU] = imx_clk_gate("viu", "nic1_div", base + 0xA0, 30);
+ clks[IMX7ULP_CLK_DSI] = imx_clk_composite("dsi", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, true, true, base + 0xA4);
+ clks[IMX7ULP_CLK_LCDIF] = imx_clk_composite("lcdif", periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true, true, base + 0xA8);
+ clks[IMX7ULP_CLK_MMDC] = imx_clk_gate("mmdc", "nic1_div", base + 0xAC, 30);
+ clks[IMX7ULP_CLK_GPU3D] = imx_clk_composite("gpu3d", periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, false, true, base + 0x140);
+ clks[IMX7ULP_CLK_PCTLC] = imx_clk_composite("pctlc", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xb8);
+ clks[IMX7ULP_CLK_PCTLD] = imx_clk_composite("pctld", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xbc);
+ clks[IMX7ULP_CLK_PCTLE] = imx_clk_composite("pctle", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xc0);
+ clks[IMX7ULP_CLK_PCTLF] = imx_clk_composite("pctlf", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xc4);
+ clks[IMX7ULP_CLK_GPU2D] = imx_clk_composite("gpu2d", periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, false, true, base + 0x144);
+
+ imx_check_clocks(clks, ARRAY_SIZE(clks));
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(scg_node, of_clk_src_onecell_get, &clk_data);
+
+ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+ imx_clk_prepare_enable(clks[clks_init_on[i]]);
+ imx_clk_set_parent(clks[IMX7ULP_CLK_GPU2D], clks[IMX7ULP_CLK_APLL_PFD2]);
+ imx_clk_set_parent(clks[IMX7ULP_CLK_GPU3D], clks[IMX7ULP_CLK_APLL_PFD2]);
+
+ /* make sure PFD is gated before setting its rate */
+ clk_prepare_enable(clks[IMX7ULP_CLK_APLL_PFD2]);
+ clk_disable_unprepare(clks[IMX7ULP_CLK_APLL_PFD2]);
+ imx_clk_set_rate(clks[IMX7ULP_CLK_APLL_PFD2], 350000000);
+
+ pr_info("i.MX7ULP clock tree init done.\n");
+}
+
+CLK_OF_DECLARE(imx7ulp, "fsl,imx7ulp-scg1", imx7ulp_clocks_init);
+
+static struct clk_div_table apll_pfd0_div_table[] = {
+ { .val = 1, .div = 1, },
+ { .val = 0, .div = 2, },
+ { /* sentinel */ }
+};
+
+static u32 share_count_sai0;
+static u32 share_count_sai1;
+
+static void __init imx7ulp_cm4_clocks_init(struct device_node *scg_node)
+{
+ struct device_node *np, *np_sim;
+ void __iomem *base;
+ void __iomem *base_sim;
+
+ clks_cm4[IMX7ULP_CM4_CLK_DUMMY] = imx_clk_fixed("cm4_dummy", 0);
+
+ clks_cm4[IMX7ULP_CM4_CLK_CKIL] = of_clk_get_by_name(scg_node, "cm4_ckil");
+ clks_cm4[IMX7ULP_CM4_CLK_OSC] = of_clk_get_by_name(scg_node, "cm4_osc");
+ clks_cm4[IMX7ULP_CM4_CLK_SIRC] = of_clk_get_by_name(scg_node, "cm4_sirc");
+ clks_cm4[IMX7ULP_CM4_CLK_FIRC] = of_clk_get_by_name(scg_node, "cm4_firc");
+
+ np = scg_node;
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ np_sim = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-sim");
+ base_sim = of_iomap(np_sim, 0);
+ WARN_ON(!base_sim);
+
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_VCO_PRE_SEL] = imx_clk_mux("cm4_spll_vco_pre_sel", base + 0x608, 0, 1, cm4_pll_pre_sels, ARRAY_SIZE(cm4_pll_pre_sels));
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_VCO_PRE_SEL] = imx_clk_mux("cm4_apll_vco_pre_sel", base + 0x508, 0, 1, cm4_pll_pre_sels, ARRAY_SIZE(cm4_pll_pre_sels));
+ /* name parent_name reg shift width */
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_VCO_PRE_DIV] = imx_clk_divider("cm4_spll_vco_pre_div", "cm4_spll_vco_pre_sel", base + 0x608, 8, 3);
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_VCO_PRE_DIV] = imx_clk_divider("cm4_apll_vco_pre_div", "cm4_apll_vco_pre_sel", base + 0x508, 8, 3);
+ /* name parent_name base*/
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_VCO] = imx_clk_pllv5("cm4_spll_vco", "cm4_spll_vco_pre_div", base + 0x600);
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_VCO] = imx_clk_pllv4("cm4_apll_vco", "cm4_apll_vco_pre_div", base + 0x500);
+
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_VCO_POST_DIV1] = imx_clk_divider("cm4_apll_vco_post_div1", "cm4_apll_vco", base + 0x508, 24, 4);
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_VCO_POST_DIV2] = imx_clk_divider("cm4_apll_vco_post_div2", "cm4_apll_vco_post_div1", base + 0x508, 28, 4);
+
+ /* SPLL PFDs */
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_PFD0] = imx_clk_pfdv2("cm4_spll_pfd0", "cm4_spll_vco", base + 0x60C, 0);
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_PFD1] = imx_clk_pfdv2("cm4_spll_pfd1", "cm4_spll_vco", base + 0x60C, 1);
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_PFD2] = imx_clk_pfdv2("cm4_spll_pfd2", "cm4_spll_vco", base + 0x60C, 2);
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_PFD3] = imx_clk_pfdv2("cm4_spll_pfd3", "cm4_spll_vco", base + 0x60C, 3);
+ /* APLL PFDs */
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_PFD0] = imx_clk_pfdv2("cm4_apll_pfd0", "cm4_apll_vco", base + 0x50C, 0);
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_PFD1] = imx_clk_pfdv2("cm4_apll_pfd1", "cm4_apll_vco", base + 0x50C, 1);
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_PFD2] = imx_clk_pfdv2("cm4_apll_pfd2", "cm4_apll_vco", base + 0x50C, 2);
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_PFD3] = imx_clk_pfdv2("cm4_apll_pfd3", "cm4_apll_vco", base + 0x50C, 3);
+
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_PFD0_PRE_DIV] = clk_register_divider_table(NULL, "cm4_apll_pfd0_pre_div", "cm4_apll_pfd0", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base_sim + 0x2c, 5, 1, 0, apll_pfd0_div_table, &imx_ccm_lock);
+
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_PFD_SEL] = imx_clk_mux("cm4_spll_pfd_sel", base + 0x608, 14, 2, cm4_spll_pfd_sels, ARRAY_SIZE(cm4_spll_pfd_sels));
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_PFD_SEL] = imx_clk_mux("cm4_apll_pfd_sel", base + 0x508, 14, 2, cm4_apll_pfd_sels, ARRAY_SIZE(cm4_apll_pfd_sels));
+
+ clks_cm4[IMX7ULP_CM4_CLK_SPLL_SEL] = imx_clk_mux("cm4_spll_sel", base + 0x608, 1, 1, cm4_spll_sels, ARRAY_SIZE(cm4_spll_sels));
+ clks_cm4[IMX7ULP_CM4_CLK_APLL_SEL] = imx_clk_mux("cm4_apll_sel", base + 0x508, 1, 1, cm4_apll_sels, ARRAY_SIZE(cm4_apll_sels));
+
+ clks_cm4[IMX7ULP_CM4_CLK_SYS_SEL] = imx_clk_mux("cm4_sys_sel", base + 0x14, 24, 4, cm4_sys_sels, ARRAY_SIZE(cm4_sys_sels));
+
+ clks_cm4[IMX7ULP_CM4_CLK_CORE_DIV] = imx_clk_divider("cm4_core_div", "cm4_sys_sel", base + 0x14, 16, 4);
+ clks_cm4[IMX7ULP_CM4_CLK_PLAT_DIV] = imx_clk_divider("cm4_plat_div", "cm4_core_div", base + 0x14, 12, 4);
+ clks_cm4[IMX7ULP_CM4_CLK_BUS_DIV] = imx_clk_divider("cm4_bus_div", "cm4_core_div", base + 0x14, 4, 4);
+ clks_cm4[IMX7ULP_CM4_CLK_SLOW_DIV] = imx_clk_divider("cm4_slow_div", "cm4_core_div", base + 0x14, 0, 4);
+
+ clks_cm4[IMX7ULP_CLK_SCG0_CLKOUT] = imx_clk_mux("scg0_clkout", base + 0x20, 24, 4, scg0_clkout_sels, ARRAY_SIZE(scg0_clkout_sels));
+
+ /* PCG0 */
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pcc0");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ clks_cm4[IMX7ULP_CM4_CLK_SAI0_SEL] = imx_clk_mux("cm4_sai0_sel", base + 0xDC, 24, 3, cm4_periph_slow_sels, ARRAY_SIZE(cm4_periph_slow_sels));
+ clks_cm4[IMX7ULP_CM4_CLK_SAI0_DIV] = imx_clk_divider("cm4_sai0_div", "cm4_sai0_sel", base + 0xDC, 0, 8);
+ clks_cm4[IMX7ULP_CM4_CLK_SAI0_ROOT] = imx_clk_gate2_shared("cm4_sai0_root", "cm4_sai0_div", base + 0xDC, 30, &share_count_sai0);
+ clks_cm4[IMX7ULP_CM4_CLK_SAI0_IPG] = imx_clk_gate2_shared("cm4_sai0_ipg", "cm4_bus_div", base + 0xDC, 30, &share_count_sai0);
+
+ /* PCG1 */
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pcc1");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+
+ clks_cm4[IMX7ULP_CM4_CLK_SAI1_SEL] = imx_clk_mux("cm4_sai1_sel", base + 0xA8, 24, 3, cm4_periph_slow_sels, ARRAY_SIZE(cm4_periph_slow_sels));
+ clks_cm4[IMX7ULP_CM4_CLK_SAI1_DIV] = imx_clk_divider("cm4_sai1_div", "cm4_sai1_sel", base + 0xA8, 0, 8);
+ clks_cm4[IMX7ULP_CM4_CLK_SAI1_ROOT] = imx_clk_gate2_shared("cm4_sai1_root", "cm4_sai1_div", base + 0xA8, 30, &share_count_sai1);
+ clks_cm4[IMX7ULP_CM4_CLK_SAI1_IPG] = imx_clk_gate2_shared("cm4_sai1_ipg", "cm4_bus_div", base + 0xA8, 30, &share_count_sai1);
+
+ imx_check_clocks(clks_cm4, ARRAY_SIZE(clks_cm4));
+
+ clk_data_cm4.clks = clks_cm4;
+ clk_data_cm4.clk_num = ARRAY_SIZE(clks_cm4);
+ of_clk_add_provider(scg_node, of_clk_src_onecell_get, &clk_data_cm4);
+
+ imx_clk_prepare_enable(clks_cm4[IMX7ULP_CM4_CLK_SYS_SEL]);
+
+ pr_info("i.MX7ULP cm4 clock tree init.\n");
+}
+CLK_OF_DECLARE(imx7ulp_cm4, "fsl,imx7ulp-scg0", imx7ulp_cm4_clocks_init);
diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c
index 04a3e78ea1bc..e29bd792522f 100644
--- a/drivers/clk/imx/clk-pfd.c
+++ b/drivers/clk/imx/clk-pfd.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2015 Freescale Semiconductor, Inc.
* Copyright 2012 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
@@ -11,11 +11,14 @@
*/
#include <linux/clk-provider.h>
+#include <linux/imx_sema4.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <soc/imx/src.h>
#include "clk.h"
+
/**
* struct clk_pfd - IMX PFD clock
* @clk_hw: clock source
@@ -38,20 +41,57 @@ struct clk_pfd {
#define CLR 0x8
#define OTG 0xc
-static int clk_pfd_enable(struct clk_hw *hw)
+static void clk_pfd_do_hardware(struct clk_pfd *pfd, bool enable)
+{
+ if (enable)
+ writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR);
+ else
+ writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET);
+}
+
+static void clk_pfd_do_shared_clks(struct clk_hw *hw, bool enable)
{
struct clk_pfd *pfd = to_clk_pfd(hw);
- writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR);
+ if (imx_src_is_m4_enabled() && clk_on_imx6sx()) {
+#ifdef CONFIG_SOC_IMX6SX
+ if (!amp_power_mutex || !shared_mem) {
+ if (enable)
+ clk_pfd_do_hardware(pfd, enable);
+ return;
+ }
+
+ imx_sema4_mutex_lock(amp_power_mutex);
+ if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER ||
+ shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) {
+ imx_sema4_mutex_unlock(amp_power_mutex);
+ return;
+ }
+
+ if (!imx_update_shared_mem(hw, enable)) {
+ imx_sema4_mutex_unlock(amp_power_mutex);
+ return;
+ }
+
+ clk_pfd_do_hardware(pfd, enable);
+
+ imx_sema4_mutex_unlock(amp_power_mutex);
+#endif
+ } else {
+ clk_pfd_do_hardware(pfd, enable);
+ }
+}
+
+static int clk_pfd_enable(struct clk_hw *hw)
+{
+ clk_pfd_do_shared_clks(hw, true);
return 0;
}
static void clk_pfd_disable(struct clk_hw *hw)
{
- struct clk_pfd *pfd = to_clk_pfd(hw);
-
- writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET);
+ clk_pfd_do_shared_clks(hw, false);
}
static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c
new file mode 100644
index 000000000000..b74f0809a03b
--- /dev/null
+++ b/drivers/clk/imx/clk-pfdv2.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 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/clk-provider.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+/**
+ * struct clk_pfdv2 - IMX PFD clock
+ * @clk_hw: clock source
+ * @reg: PFD register address
+ * @idx: the index of PFD encoded in the register
+ *
+ */
+
+struct clk_pfdv2 {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 idx;
+};
+
+#define to_clk_pfdv2(_hw) container_of(_hw, struct clk_pfdv2, hw)
+
+static int clk_pfd_enable(struct clk_hw *hw)
+{
+ struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
+ u32 val;
+
+ val = readl_relaxed(pfd->reg);
+ val &= ~(1 << ((pfd->idx + 1) * 8 - 1));
+ writel_relaxed(val, pfd->reg);
+
+ return 0;
+}
+
+static void clk_pfd_disable(struct clk_hw *hw)
+{
+ struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
+ u32 val;
+
+ val = readl_relaxed(pfd->reg);
+ val |= 1 << ((pfd->idx + 1) * 8 - 1);
+ writel_relaxed(val, pfd->reg);
+}
+
+static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
+ u64 tmp = parent_rate;
+ u8 frac = (readl_relaxed(pfd->reg) >> (pfd->idx * 8)) & 0x3f;
+
+ /*
+ * The reset value of pfd field is zero, so add one to avoid div
+ * by zero, optimize this late.
+ */
+ if (!frac)
+ frac += 1;
+
+ tmp *= 18;
+ do_div(tmp, frac);
+
+ return tmp;
+}
+
+static long clk_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ u64 tmp = *prate;
+ u8 frac;
+
+ tmp = tmp * 18 + rate / 2;
+ do_div(tmp, rate);
+ frac = tmp;
+ if (frac < 12)
+ frac = 12;
+ else if (frac > 35)
+ frac = 35;
+ tmp = *prate;
+ tmp *= 18;
+ do_div(tmp, frac);
+
+ return tmp;
+}
+
+static int clk_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
+ u64 tmp = parent_rate;
+ u32 val;
+ u8 frac;
+
+ /* PFD can NOT change rate without gating */
+ WARN_ON(!(readl_relaxed(pfd->reg) &
+ (1 << ((pfd->idx + 1) * 8 - 1))));
+
+ tmp = tmp * 18 + rate / 2;
+ do_div(tmp, rate);
+ frac = tmp;
+ if (frac < 12)
+ frac = 12;
+ else if (frac > 35)
+ frac = 35;
+
+ val = readl_relaxed(pfd->reg);
+ val &= ~(0x3f << (pfd->idx * 8));
+ val |= frac << (pfd->idx * 8);
+ writel_relaxed(val, pfd->reg);
+
+ return 0;
+}
+
+static int clk_pfd_is_enabled(struct clk_hw *hw)
+{
+ struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
+
+ if (readl_relaxed(pfd->reg) & (1 << ((pfd->idx + 1) * 8 - 1)))
+ return 0;
+
+ return 1;
+}
+
+static const struct clk_ops clk_pfdv2_ops = {
+ .enable = clk_pfd_enable,
+ .disable = clk_pfd_disable,
+ .recalc_rate = clk_pfd_recalc_rate,
+ .round_rate = clk_pfd_round_rate,
+ .set_rate = clk_pfd_set_rate,
+ .is_enabled = clk_pfd_is_enabled,
+};
+
+struct clk *imx_clk_pfdv2(const char *name, const char *parent_name,
+ void __iomem *reg, u8 idx)
+{
+ struct clk_pfdv2 *pfd;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ pfd = kzalloc(sizeof(*pfd), GFP_KERNEL);
+ if (!pfd)
+ return ERR_PTR(-ENOMEM);
+
+ pfd->reg = reg;
+ pfd->idx = idx;
+
+ init.name = name;
+ init.ops = &clk_pfdv2_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pfd->hw.init = &init;
+
+ clk = clk_register(NULL, &pfd->hw);
+ if (IS_ERR(clk))
+ kfree(pfd);
+
+ return clk;
+}
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index 7a6acc3e4a92..d8b481936f20 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -11,15 +11,20 @@
*/
#include <linux/clk-provider.h>
-#include <linux/delay.h>
+#include <linux/imx_sema4.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/err.h>
+#include <soc/imx/src.h>
#include "clk.h"
-#define PLL_NUM_OFFSET 0x10
-#define PLL_DENOM_OFFSET 0x20
+#define PLL_NUM_OFFSET 0x10
+#define PLL_DENOM_OFFSET 0x20
+#define PLL_AV_IMX7_NUM_OFFSET 0x20
+#define PLL_AV_IMX7_DENOM_OFFSET 0x30
+#define PLL_PLL2_NUM_OFFSET 0x20
+#define PLL_PLL2_DENOM_OFFSET 0x30
#define BM_PLL_POWER (0x1 << 12)
#define BM_PLL_LOCK (0x1 << 31)
@@ -45,6 +50,8 @@ struct clk_pllv3 {
u32 div_mask;
u32 div_shift;
unsigned long ref_clock;
+ u32 num_offset;
+ u32 denom_offset;
};
#define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
@@ -64,38 +71,79 @@ static int clk_pllv3_wait_lock(struct clk_pllv3 *pll)
break;
if (time_after(jiffies, timeout))
break;
- usleep_range(50, 500);
} while (1);
return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT;
}
-static int clk_pllv3_prepare(struct clk_hw *hw)
+static int clk_pllv3_do_hardware(struct clk_hw *hw, bool enable)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
+ int ret;
u32 val;
val = readl_relaxed(pll->base);
- if (pll->powerup_set)
- val |= pll->power_bit;
- else
- val &= ~pll->power_bit;
- writel_relaxed(val, pll->base);
+ if (enable) {
+ if (pll->powerup_set)
+ val |= pll->power_bit;
+ else
+ val &= ~pll->power_bit;
+ writel_relaxed(val, pll->base);
+
+ ret = clk_pllv3_wait_lock(pll);
+ if (ret)
+ return ret;
+ } else {
+ if (pll->powerup_set)
+ val &= ~pll->power_bit;
+ else
+ val |= pll->power_bit;
+ writel_relaxed(val, pll->base);
+ }
- return clk_pllv3_wait_lock(pll);
+ return 0;
}
-static void clk_pllv3_unprepare(struct clk_hw *hw)
+static void clk_pllv3_do_shared_clks(struct clk_hw *hw, bool enable)
{
- struct clk_pllv3 *pll = to_clk_pllv3(hw);
- u32 val;
+ if (imx_src_is_m4_enabled() && clk_on_imx6sx()) {
+#ifdef CONFIG_SOC_IMX6SX
+ if (!amp_power_mutex || !shared_mem) {
+ if (enable)
+ clk_pllv3_do_hardware(hw, enable);
+ return;
+ }
+
+ imx_sema4_mutex_lock(amp_power_mutex);
+ if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER ||
+ shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) {
+ imx_sema4_mutex_unlock(amp_power_mutex);
+ return;
+ }
+
+ if (!imx_update_shared_mem(hw, enable)) {
+ imx_sema4_mutex_unlock(amp_power_mutex);
+ return;
+ }
+ clk_pllv3_do_hardware(hw, enable);
+
+ imx_sema4_mutex_unlock(amp_power_mutex);
+#endif
+ } else {
+ clk_pllv3_do_hardware(hw, enable);
+ }
+}
- val = readl_relaxed(pll->base);
- if (pll->powerup_set)
- val &= ~pll->power_bit;
- else
- val |= pll->power_bit;
- writel_relaxed(val, pll->base);
+static int clk_pllv3_prepare(struct clk_hw *hw)
+{
+ clk_pllv3_do_shared_clks(hw, true);
+
+ return 0;
+}
+
+static void clk_pllv3_unprepare(struct clk_hw *hw)
+{
+ clk_pllv3_do_shared_clks(hw, false);
}
static int clk_pllv3_is_prepared(struct clk_hw *hw)
@@ -215,8 +263,8 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
- u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
- u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
+ u32 mfn = readl_relaxed(pll->base + pll->num_offset);
+ u32 mfd = readl_relaxed(pll->base + pll->denom_offset);
u32 div = readl_relaxed(pll->base) & pll->div_mask;
u64 temp64 = (u64)parent_rate;
@@ -277,8 +325,8 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
val &= ~pll->div_mask;
val |= div;
writel_relaxed(val, pll->base);
- writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
- writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
+ writel_relaxed(mfn, pll->base + pll->num_offset);
+ writel_relaxed(mfd, pll->base + pll->denom_offset);
return clk_pllv3_wait_lock(pll);
}
@@ -307,6 +355,28 @@ static const struct clk_ops clk_pllv3_enet_ops = {
.recalc_rate = clk_pllv3_enet_recalc_rate,
};
+static unsigned long clk_pllv3_pll2_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
+ u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask;
+ u32 mfn = readl_relaxed(pll->base + pll->num_offset);
+ u32 mfd = readl_relaxed(pll->base + pll->denom_offset);
+ u64 temp64 = (u64)parent_rate;
+
+ temp64 *= mfn;
+ do_div(temp64, mfd);
+
+ return (parent_rate * ((div == 1) ? 22 : 20)) + (u32)temp64;
+}
+
+static const struct clk_ops clk_pllv3_pll2_ops = {
+ .prepare = clk_pllv3_prepare,
+ .unprepare = clk_pllv3_unprepare,
+ .is_prepared = clk_pllv3_is_prepared,
+ .recalc_rate = clk_pllv3_pll2_recalc_rate,
+};
+
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
const char *parent_name, void __iomem *base,
u32 div_mask)
@@ -321,17 +391,28 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
return ERR_PTR(-ENOMEM);
pll->power_bit = BM_PLL_POWER;
+ pll->num_offset = PLL_NUM_OFFSET;
+ pll->denom_offset = PLL_DENOM_OFFSET;
switch (type) {
case IMX_PLLV3_SYS:
ops = &clk_pllv3_sys_ops;
break;
+ case IMX_PLLV3_PLL2:
+ pll->num_offset = PLL_PLL2_NUM_OFFSET;
+ pll->denom_offset = PLL_PLL2_DENOM_OFFSET;
+ ops = &clk_pllv3_pll2_ops;
+ break;
case IMX_PLLV3_USB_VF610:
pll->div_shift = 1;
case IMX_PLLV3_USB:
ops = &clk_pllv3_ops;
pll->powerup_set = true;
break;
+ case IMX_PLLV3_AV_IMX7:
+ pll->num_offset = PLL_AV_IMX7_NUM_OFFSET;
+ pll->denom_offset = PLL_AV_IMX7_DENOM_OFFSET;
+ /* fall through */
case IMX_PLLV3_AV:
ops = &clk_pllv3_av_ops;
break;
diff --git a/drivers/clk/imx/clk-pllv4.c b/drivers/clk/imx/clk-pllv4.c
new file mode 100644
index 000000000000..4f4c02bd6d4e
--- /dev/null
+++ b/drivers/clk/imx/clk-pllv4.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 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/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+#define PLL_EN BIT(0)
+#define BP_PLL_DIV 16
+#define BM_PLL_DIV (0x7f << 16)
+#define PLL_CFG_OFFSET 0x08
+#define PLL_NUM_OFFSET 0x10
+#define PLL_DENOM_OFFSET 0x14
+
+struct clk_pllv4 {
+ struct clk_hw hw;
+ void __iomem *base;
+ u32 div_mask;
+ u32 div_shift;
+ u32 cfg_offset;
+ u32 num_offset;
+ u32 denom_offset;
+};
+
+#define to_clk_pllv4(__hw) container_of(__hw, struct clk_pllv4, hw)
+
+static unsigned long clk_pllv4_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_pllv4 *pll = to_clk_pllv4(hw);
+ u32 mfn = readl_relaxed(pll->base + pll->num_offset);
+ u32 mfd = readl_relaxed(pll->base + pll->denom_offset);
+ u32 div = (readl_relaxed(pll->base + pll->cfg_offset)
+ & pll->div_mask) >> pll->div_shift;
+ u64 temp64 = (u64)parent_rate;
+
+ temp64 *= mfn;
+ do_div(temp64, mfd);
+
+ return (parent_rate * div) + (u32)temp64;
+}
+
+static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ unsigned long parent_rate = *prate;
+ unsigned long min_rate = parent_rate * 16;
+ unsigned long max_rate = parent_rate * 30;
+ u32 div;
+ u32 mfn, mfd = 1000000;
+ u64 temp64;
+
+ if (rate > max_rate)
+ rate = max_rate;
+ else if (rate < min_rate)
+ rate = min_rate;
+
+ div = rate / parent_rate;
+ temp64 = (u64) (rate - div * parent_rate);
+ temp64 *= mfd;
+ do_div(temp64, parent_rate);
+ mfn = temp64;
+
+ return parent_rate * div + parent_rate / mfd * mfn;
+}
+
+static int clk_pllv4_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_pllv4 *pll = to_clk_pllv4(hw);
+ unsigned long min_rate = parent_rate * 16;
+ unsigned long max_rate = parent_rate * 30;
+ u32 val, div;
+ u32 mfn, mfd = 1000000;
+ u64 temp64;
+
+ if (rate < min_rate || rate > max_rate)
+ return -EINVAL;
+
+ div = rate / parent_rate;
+ temp64 = (u64) (rate - div * parent_rate);
+ temp64 *= mfd;
+ do_div(temp64, parent_rate);
+ mfn = temp64;
+
+ val = readl_relaxed(pll->base + pll->cfg_offset);
+ val &= ~pll->div_mask;
+ val |= (div << pll->div_shift);
+ writel_relaxed(val, pll->base + pll->cfg_offset);
+ writel_relaxed(mfn, pll->base + pll->num_offset);
+ writel_relaxed(mfd, pll->base + pll->denom_offset);
+
+ return 0;
+}
+
+static int clk_pllv4_enable(struct clk_hw *hw)
+{
+ u32 val;
+ struct clk_pllv4 *pll = to_clk_pllv4(hw);
+
+ val = readl_relaxed(pll->base);
+ val |= PLL_EN;
+ writel_relaxed(val, pll->base);
+
+ return 0;
+}
+
+static void clk_pllv4_disable(struct clk_hw *hw)
+{
+ u32 val;
+ struct clk_pllv4 *pll = to_clk_pllv4(hw);
+
+ val = readl_relaxed(pll->base);
+ val &= ~PLL_EN;
+ writel_relaxed(val, pll->base);
+}
+
+static int clk_pllv4_is_enabled(struct clk_hw *hw)
+{
+ struct clk_pllv4 *pll = to_clk_pllv4(hw);
+
+ if (readl_relaxed(pll->base) & PLL_EN)
+ return 0;
+
+ return 1;
+}
+
+static const struct clk_ops clk_pllv4_ops = {
+ .recalc_rate = clk_pllv4_recalc_rate,
+ .round_rate = clk_pllv4_round_rate,
+ .set_rate = clk_pllv4_set_rate,
+ .enable = clk_pllv4_enable,
+ .disable = clk_pllv4_disable,
+ .is_enabled = clk_pllv4_is_enabled,
+};
+
+struct clk *imx_clk_pllv4(const char *name, const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_pllv4 *pll;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ pll->base = base;
+ pll->div_mask = BM_PLL_DIV;
+ pll->div_shift = BP_PLL_DIV;
+ pll->cfg_offset = PLL_CFG_OFFSET;
+ pll->num_offset = PLL_NUM_OFFSET;
+ pll->denom_offset = PLL_DENOM_OFFSET;
+
+ init.name = name;
+ init.ops = &clk_pllv4_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll->hw.init = &init;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(clk))
+ kfree(pll);
+
+ return clk;
+}
diff --git a/drivers/clk/imx/clk-pllv5.c b/drivers/clk/imx/clk-pllv5.c
new file mode 100644
index 000000000000..c45704c7942e
--- /dev/null
+++ b/drivers/clk/imx/clk-pllv5.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 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/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+#define PLL_EN BIT(0)
+#define BP_PLL_DIV 16
+#define BM_PLL_DIV (0x7 << 16)
+#define PLL_CFG_OFFSET 0x08
+
+struct clk_pllv5 {
+ struct clk_hw hw;
+ void __iomem *base;
+ u32 div_mask;
+ u32 div_shift;
+ u32 cfg_offset;
+};
+
+#define to_clk_pllv5(__hw) container_of(__hw, struct clk_pllv5, hw)
+
+static unsigned long clk_pllv5_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_pllv5 *pll = to_clk_pllv5(hw);
+ u32 val = (readl_relaxed(pll->base + pll->cfg_offset) & pll->div_mask) >> pll->div_shift;
+ u32 div;
+
+ switch (val) {
+ case 1:
+ div = 15;
+ break;
+ case 2:
+ div = 16;
+ break;
+ case 3:
+ div = 20;
+ break;
+ case 4:
+ div = 22;
+ break;
+ case 5:
+ div = 25;
+ break;
+ case 6:
+ div = 30;
+ break;
+ default:
+ div = 20;
+ break;
+ }
+
+ return parent_rate * div;
+}
+
+static long clk_pllv5_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ unsigned long parent_rate = *prate;
+ u32 div;
+
+ div = rate / parent_rate;
+
+ if (div == 15 || div == 16 ||
+ div == 20 || div == 22 ||
+ div == 25 || div == 30)
+ return parent_rate * div;
+ else
+ return parent_rate * 20;
+}
+
+static int clk_pllv5_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_pllv5 *pll = to_clk_pllv5(hw);
+ unsigned long min_rate = parent_rate * 15;
+ unsigned long max_rate = parent_rate * 30;
+ u32 val, div, reg;
+
+ if (rate < min_rate || rate > max_rate)
+ return -EINVAL;
+
+ div = rate / parent_rate;
+
+ switch (div) {
+ case 15:
+ val = 1;
+ break;
+ case 16:
+ val = 2;
+ break;
+ case 20:
+ val = 3;
+ break;
+ case 22:
+ val = 4;
+ break;
+ case 25:
+ val = 5;
+ break;
+ case 30:
+ val = 6;
+ break;
+ default:
+ val = 3;
+ break;
+ }
+
+ reg = readl_relaxed(pll->base + pll->cfg_offset);
+ reg &= ~pll->div_mask;
+ reg |= (val << pll->div_shift);
+ writel_relaxed(val, pll->base + pll->cfg_offset);
+
+ return 0;
+}
+
+static int clk_pllv5_enable(struct clk_hw *hw)
+{
+ u32 val;
+ struct clk_pllv5 *pll = to_clk_pllv5(hw);
+
+ val = readl_relaxed(pll->base);
+ val |= PLL_EN;
+ writel_relaxed(val, pll->base);
+
+ return 0;
+}
+
+static void clk_pllv5_disable(struct clk_hw *hw)
+{
+ u32 val;
+ struct clk_pllv5 *pll = to_clk_pllv5(hw);
+
+ val = readl_relaxed(pll->base);
+ val &= ~PLL_EN;
+ writel_relaxed(val, pll->base);
+}
+
+static int clk_pllv5_is_enabled(struct clk_hw *hw)
+{
+ struct clk_pllv5 *pll = to_clk_pllv5(hw);
+
+ if (readl_relaxed(pll->base) & PLL_EN)
+ return 0;
+
+ return 1;
+}
+
+static const struct clk_ops clk_pllv5_ops = {
+ .recalc_rate = clk_pllv5_recalc_rate,
+ .round_rate = clk_pllv5_round_rate,
+ .set_rate = clk_pllv5_set_rate,
+ .enable = clk_pllv5_enable,
+ .disable = clk_pllv5_disable,
+ .is_enabled = clk_pllv5_is_enabled,
+};
+
+struct clk *imx_clk_pllv5(const char *name, const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_pllv5 *pll;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ pll->base = base;
+ pll->div_mask = BM_PLL_DIV;
+ pll->div_shift = BP_PLL_DIV;
+ pll->cfg_offset = PLL_CFG_OFFSET;
+
+ init.name = name;
+ init.ops = &clk_pllv5_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll->hw.init = &init;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(clk))
+ kfree(pll);
+
+ return clk;
+}
+
diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
index a634b1185be3..f76cb0b733f1 100644
--- a/drivers/clk/imx/clk.c
+++ b/drivers/clk/imx/clk.c
@@ -7,6 +7,8 @@
DEFINE_SPINLOCK(imx_ccm_lock);
+bool uart_from_osc;
+
void __init imx_check_clocks(struct clk *clks[], unsigned int count)
{
unsigned i;
@@ -111,3 +113,11 @@ static int __init imx_clk_disable_uart(void)
return 0;
}
late_initcall_sync(imx_clk_disable_uart);
+
+static int __init setup_uart_clk(char *uart_rate)
+{
+ uart_from_osc = true;
+ return 1;
+}
+__setup("uart_from_osc", setup_uart_clk);
+
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 3799ff82a9b4..cf41e1e2cc11 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -3,6 +3,8 @@
#include <linux/spinlock.h>
#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <soc/imx/src.h>
extern spinlock_t imx_ccm_lock;
@@ -10,6 +12,10 @@ void imx_check_clocks(struct clk *clks[], unsigned int count);
void imx_register_uart_clocks(struct clk ** const clks[]);
extern void imx_cscmr1_fixup(u32 *val);
+extern struct imx_sema4_mutex *amp_power_mutex;
+extern struct imx_shared_mem *shared_mem;
+extern bool uart_from_osc;
+extern const struct clk_ops clk_frac_divider_ops;
enum imx_pllv1_type {
IMX_PLLV1_IMX1,
@@ -34,11 +40,54 @@ enum imx_pllv3_type {
IMX_PLLV3_AV,
IMX_PLLV3_ENET,
IMX_PLLV3_ENET_IMX7,
+ IMX_PLLV3_AV_IMX7,
+ IMX_PLLV3_PLL2,
+};
+
+/*
+ * frac_divider, found on i.MX7ULP PCC module.
+ * the output clock of the fractional divider is:
+ * Divider output clock = Input clock * (FRAC + 1)
+ * / (DIV + 1)
+ */
+struct clk_frac_divider {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 mshift;
+ u8 mwidth;
+ u32 mmask;
+ u8 nshift;
+ u8 nwidth;
+ u32 nmask;
+};
+
+#define MAX_SHARED_CLK_NUMBER 100
+#define SHARED_MEM_MAGIC_NUMBER 0x12345678
+#define MCC_POWER_SHMEM_NUMBER (6)
+
+struct imx_shared_clk {
+ struct clk *self;
+ struct clk *parent;
+ void *m4_clk;
+ void *m4_clk_parent;
+ u8 ca9_enabled;
+ u8 cm4_enabled;
+};
+
+struct imx_shared_mem {
+ u32 ca9_valid;
+ u32 cm4_valid;
+ struct imx_shared_clk imx_clk[MAX_SHARED_CLK_NUMBER];
};
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
const char *parent_name, void __iomem *base, u32 div_mask);
+struct clk *imx_clk_pllv4(const char *name,
+ const char *parent_name, void __iomem *base);
+struct clk *imx_clk_pllv5(const char *name, const char *parent_name,
+ void __iomem *base);
+
struct clk *clk_register_gate2(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx, u8 cgr_val,
@@ -51,6 +100,33 @@ struct clk * imx_obtain_fixed_clock(
struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
void __iomem *reg, u8 shift, u32 exclusive_mask);
+static inline void imx_clk_prepare_enable(struct clk *clk)
+{
+ int ret = clk_prepare_enable(clk);
+
+ if (ret)
+ pr_err("failed to prepare and enable clk %s: %d\n",
+ __clk_get_name(clk), ret);
+}
+
+static inline void imx_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret = clk_set_parent(clk, parent);
+
+ if (ret)
+ pr_err("failed to set parent of clk %s to %s: %d\n",
+ __clk_get_name(clk), __clk_get_name(parent), ret);
+}
+
+static inline void imx_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = clk_set_rate(clk, rate);
+
+ if (ret)
+ pr_err("failed to set rate of clk %s to %ld: %d\n",
+ __clk_get_name(clk), rate, ret);
+}
+
struct clk *imx_clk_pfd(const char *name, const char *parent_name,
void __iomem *reg, u8 idx);
@@ -62,6 +138,9 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
u8 width, void __iomem *busy_reg, u8 busy_shift,
const char **parent_names, int num_parents);
+struct clk *imx_clk_busy_gate(const char *name, const char *parent,
+ void __iomem *reg, u8 shift);
+
struct clk *imx_clk_fixup_divider(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width,
void (*fixup)(u32 *val));
@@ -75,6 +154,14 @@ static inline struct clk *imx_clk_fixed(const char *name, int rate)
return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
}
+static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg,
+ u8 shift, u8 width, const char **parents, int num_parents)
+{
+ return clk_register_mux(NULL, name, parents, num_parents,
+ CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, reg,
+ shift, width, CLK_MUX_READ_ONLY, &imx_ccm_lock);
+}
+
static inline struct clk *imx_clk_fixed_factor(const char *name,
const char *parent, unsigned int mult, unsigned int div)
{
@@ -85,23 +172,24 @@ static inline struct clk *imx_clk_fixed_factor(const char *name,
static inline struct clk *imx_clk_divider(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width)
{
- return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT,
+ return clk_register_divider(NULL, name, parent,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
reg, shift, width, 0, &imx_ccm_lock);
}
-static inline struct clk *imx_clk_divider_flags(const char *name,
- const char *parent, void __iomem *reg, u8 shift, u8 width,
- unsigned long flags)
+static inline struct clk *imx_clk_divider2(const char *name, const char *parent,
+ void __iomem *reg, u8 shift, u8 width)
{
- return clk_register_divider(NULL, name, parent, flags,
+ return clk_register_divider(NULL, name, parent,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
reg, shift, width, 0, &imx_ccm_lock);
}
-static inline struct clk *imx_clk_divider2(const char *name, const char *parent,
- void __iomem *reg, u8 shift, u8 width)
+static inline struct clk *imx_clk_divider_flags(const char *name,
+ const char *parent, void __iomem *reg, u8 shift, u8 width,
+ unsigned long flags)
{
- return clk_register_divider(NULL, name, parent,
- CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ return clk_register_divider(NULL, name, parent, flags,
reg, shift, width, 0, &imx_ccm_lock);
}
@@ -122,7 +210,15 @@ static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent,
static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{
- return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+ return clk_register_gate2(NULL, name, parent,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, reg,
+ shift, 0x3, 0, &imx_ccm_lock, NULL);
+}
+
+static inline struct clk *imx_clk_gate2_flags(const char *name, const char *parent,
+ void __iomem *reg, u8 shift, unsigned long flags)
+{
+ return clk_register_gate2(NULL, name, parent, flags, reg,
shift, 0x3, 0, &imx_ccm_lock, NULL);
}
@@ -130,7 +226,8 @@ static inline struct clk *imx_clk_gate2_shared(const char *name,
const char *parent, void __iomem *reg, u8 shift,
unsigned int *share_count)
{
- return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+ return clk_register_gate2(NULL, name, parent,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, reg,
shift, 0x3, 0, &imx_ccm_lock, share_count);
}
@@ -139,8 +236,8 @@ static inline struct clk *imx_clk_gate2_shared2(const char *name,
unsigned int *share_count)
{
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
- CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0,
- &imx_ccm_lock, share_count);
+ CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
+ reg, shift, 0x3, 0, &imx_ccm_lock, share_count);
}
static inline struct clk *imx_clk_gate2_cgr(const char *name,
@@ -153,7 +250,17 @@ static inline struct clk *imx_clk_gate2_cgr(const char *name,
static inline struct clk *imx_clk_gate3(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{
- return clk_register_gate(NULL, name, parent,
+ /*
+ * per design team's suggestion, clk root is NOT consuming
+ * much power, and clk root enable/disable does NOT have domain
+ * control, so they suggest to leave clk root always on when
+ * M4 is enabled.
+ */
+ if (imx_src_is_m4_enabled())
+ return clk_register_fixed_factor(NULL, name, parent,
+ CLK_SET_RATE_PARENT, 1, 1);
+ else
+ return clk_register_gate(NULL, name, parent,
CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
reg, shift, 0, &imx_ccm_lock);
}
@@ -162,16 +269,24 @@ static inline struct clk *imx_clk_gate4(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{
return clk_register_gate2(NULL, name, parent,
- CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
}
+static inline struct clk *imx_clk_mux_bus(const char *name, void __iomem *reg,
+ u8 shift, u8 width, const char **parents, int num_parents)
+{
+ return clk_register_mux(NULL, name, parents, num_parents,
+ CLK_SET_RATE_NO_REPARENT,
+ reg, shift, width, 0, &imx_ccm_lock);
+}
+
static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
u8 shift, u8 width, const char **parents, int num_parents)
{
return clk_register_mux(NULL, name, parents, num_parents,
- CLK_SET_RATE_NO_REPARENT, reg, shift,
- width, 0, &imx_ccm_lock);
+ CLK_SET_RATE_NO_REPARENT | CLK_SET_PARENT_GATE,
+ reg, shift, width, 0, &imx_ccm_lock);
}
static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
@@ -187,12 +302,43 @@ static inline struct clk *imx_clk_mux_flags(const char *name,
int num_parents, unsigned long flags)
{
return clk_register_mux(NULL, name, parents, num_parents,
- flags | CLK_SET_RATE_NO_REPARENT, reg, shift, width, 0,
- &imx_ccm_lock);
+ flags | CLK_SET_RATE_NO_REPARENT | CLK_SET_PARENT_GATE,
+ reg, shift, width, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_mux_flags_bus(const char *name,
+ void __iomem *reg, u8 shift, u8 width, const char **paretns,
+ int num_parents, unsigned long flags)
+{
+ return clk_register_mux(NULL, name, paretns, num_parents,
+ flags | CLK_SET_RATE_NO_REPARENT, reg, shift,
+ width, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_mux_glitchless(const char *name,
+ void __iomem *reg, u8 shift, u8 width, const char **parents,
+ int num_parents)
+{
+ return clk_register_mux(NULL, name, parents, num_parents,
+ CLK_SET_RATE_NO_REPARENT, reg, shift,
+ width, 0, &imx_ccm_lock);
}
struct clk *imx_clk_cpu(const char *name, const char *parent_name,
struct clk *div, struct clk *mux, struct clk *pll,
struct clk *step);
+int imx_update_shared_mem(struct clk_hw *hw, bool enable);
+
+static inline int clk_on_imx6sx(void)
+{
+ return of_machine_is_compatible("fsl,imx6sx");
+}
+
+struct clk *imx_clk_composite(const char *name, const char **parent_name,
+ int num_parents, bool mux_present, bool rate_present,
+ bool gate_present, void __iomem *reg);
+
+struct clk *imx_clk_pfdv2(const char *name, const char *parent_name,
+ void __iomem *reg, u8 idx);
#endif
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index e2c6e43cf8ca..daab8b22a9de 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -532,6 +532,11 @@ config CLKSRC_IMX_GPT
depends on ARM && CLKDEV_LOOKUP
select CLKSRC_MMIO
+config CLKSRC_IMX_TPM
+ bool "Clocksource using i.MX TPM" if COMPILE_TEST
+ depends on ARM && CLKDEV_LOOKUP && GENERIC_CLOCKEVENTS
+ select CLKSRC_MMIO
+
config CLKSRC_ST_LPC
bool "Low power clocksource found in the LPC" if COMPILE_TEST
select CLKSRC_OF if OF
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index cf87f407f1ad..8015232448d7 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o
obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
+obj-$(CONFIG_CLKSRC_IMX_TPM) += timer-imx-tpm.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o
obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
index f595460bfc58..d65387218418 100644
--- a/drivers/clocksource/timer-imx-gpt.c
+++ b/drivers/clocksource/timer-imx-gpt.c
@@ -556,4 +556,7 @@ CLOCKSOURCE_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
CLOCKSOURCE_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
CLOCKSOURCE_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
CLOCKSOURCE_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx6sll_timer, "fsl,imx6sll-gpt", imx6dl_timer_init_dt);
CLOCKSOURCE_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx6ul_timer, "fsl,imx6ul-gpt", imx6dl_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx7d_timer, "fsl,imx7d-gpt", imx6dl_timer_init_dt);
diff --git a/drivers/clocksource/timer-imx-tpm.c b/drivers/clocksource/timer-imx-tpm.c
new file mode 100644
index 000000000000..f7d0d68f35b1
--- /dev/null
+++ b/drivers/clocksource/timer-imx-tpm.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#define TPM_GLOBAL 0x8
+
+#define TPM_SC 0x10
+#define TPM_CNT 0x14
+#define TPM_MOD 0x18
+#define TPM_STATUS 0x1c
+#define TPM_C0SC 0x20
+#define TPM_C0V 0x24
+
+#define TPM_STATUS_CH0F 0x1
+
+#define TPM_C0SC_MSA 0x4
+
+static void __iomem *timer_base;
+static struct clock_event_device clockevent_tpm;
+
+static inline void tpm_timer_disable(void)
+{
+ unsigned int val;
+
+ val = __raw_readl(timer_base + TPM_C0SC);
+ val &= ~(0x5 << TPM_C0SC_MSA);
+ __raw_writel(val, timer_base + TPM_C0SC);
+}
+
+static inline void tpm_timer_enable(void)
+{
+ unsigned int val;
+
+ val = __raw_readl(timer_base + TPM_C0SC);
+ val |= (0x5 << TPM_C0SC_MSA);
+ __raw_writel(val, timer_base + TPM_C0SC);
+}
+
+static inline void tpm_irq_acknowledge(void)
+{
+ __raw_writel(1, timer_base + TPM_STATUS);
+}
+
+static struct delay_timer tpm_delay_timer;
+
+static unsigned long tpm_read_current_timer(void)
+{
+ return __raw_readl(timer_base + TPM_CNT);
+}
+
+static u64 notrace tpm_read_sched_clock(void)
+{
+ return __raw_readl(timer_base + TPM_CNT);
+}
+
+static int __init tpm_clocksource_init(unsigned long rate)
+{
+ tpm_delay_timer.read_current_timer = &tpm_read_current_timer;
+ tpm_delay_timer.freq = rate;
+ register_current_timer_delay(&tpm_delay_timer);
+
+ sched_clock_register(tpm_read_sched_clock, 32, rate);
+ return clocksource_mmio_init(timer_base + TPM_CNT, "imx-tpm",
+ rate, 200, 32, clocksource_mmio_readl_up);
+}
+
+static int tpm_set_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ unsigned long next, now, ret;
+
+ now = __raw_readl(timer_base + TPM_CNT);
+ next = now + delta;
+ __raw_writel(next, timer_base + TPM_C0V);
+ now = __raw_readl(timer_base + TPM_CNT);
+
+ ret = next - now;
+ return (ret > delta) ? -ETIME : 0;
+}
+
+static int tpm_set_state_oneshot(struct clock_event_device *evt)
+{
+ /* enable timer */
+ tpm_timer_enable();
+
+ return 0;
+}
+
+static int tpm_set_state_shutdown(struct clock_event_device *evt)
+{
+ /* disable timer */
+ tpm_timer_disable();
+
+ return 0;
+}
+
+static irqreturn_t tpm_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &clockevent_tpm;
+
+ tpm_irq_acknowledge();
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct clock_event_device clockevent_tpm = {
+ .name = "i.MX7ULP tpm timer",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .set_state_oneshot = tpm_set_state_oneshot,
+ .set_next_event = tpm_set_next_event,
+ .set_state_shutdown = tpm_set_state_shutdown,
+ .rating = 200,
+};
+
+static struct irqaction tpm_timer_irq = {
+ .name = "i.MX7ULP tpm timer",
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = tpm_timer_interrupt,
+ .dev_id = &clockevent_tpm,
+};
+
+static int __init tpm_clockevent_init(unsigned long rate, int irq)
+{
+ /* init the channel */
+ setup_irq(irq, &tpm_timer_irq);
+
+ clockevent_tpm.cpumask = cpumask_of(0);
+ clockevent_tpm.irq = irq;
+ clockevents_config_and_register(&clockevent_tpm,
+ rate, 300, 0xfffffffe);
+
+ return 0;
+}
+
+static int __init tpm_timer_init(struct device_node *np)
+{
+ struct clk *clk;
+ uint32_t val;
+ int irq;
+
+ timer_base = of_iomap(np, 0);
+ BUG_ON(!timer_base);
+
+ irq = irq_of_parse_and_map(np, 0);
+
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ /* clock shoube be enabled before access to the timer registers */
+ clk_prepare_enable(clk);
+
+ /* Initialize tpm module to a known state(counter disabled). */
+ __raw_writel(0, timer_base + TPM_SC);
+ __raw_writel(0, timer_base + TPM_CNT);
+ __raw_writel(0, timer_base + TPM_C0SC);
+
+ /* set the prescale div, div by 8 = 3MHz */
+ __raw_writel(0xb, timer_base + TPM_SC);
+
+ /* set the MOD register to 0xffffffff for free running counter */
+ __raw_writel(0xffffffff, timer_base + TPM_MOD);
+
+ tpm_clocksource_init(clk_get_rate(clk) / 8);
+ tpm_clockevent_init(clk_get_rate(clk) / 8, irq);
+
+ val = __raw_readl(timer_base);
+
+ return 0;
+}
+CLOCKSOURCE_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init);
+
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index cac26fb22891..a8909df6ac57 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -112,6 +112,16 @@ config CPU_FREQ_DEFAULT_GOV_SCHEDUTIL
have a look at the help section of that governor. The fallback
governor will be 'performance'.
+config CPU_FREQ_DEFAULT_GOV_INTERACTIVE
+ bool "interactive"
+ select CPU_FREQ_GOV_INTERACTIVE
+ select CPU_FREQ_GOV_PERFORMANCE
+ help
+ Use the CPUFreq governor 'interactive' as default. This allows
+ you to get a full dynamic cpu frequency capable system by simply
+ loading your cpufreq low-level hardware driver, using the
+ 'interactive' governor for latency-sensitive workloads.
+
endchoice
config CPU_FREQ_GOV_PERFORMANCE
@@ -210,6 +220,26 @@ config CPU_FREQ_GOV_SCHEDUTIL
If in doubt, say N.
+config CPU_FREQ_GOV_INTERACTIVE
+ tristate "'interactive' cpufreq policy governor"
+ depends on CPU_FREQ
+ select CPU_FREQ_GOV_ATTR_SET
+ select IRQ_WORK
+ help
+ 'interactive' - This driver adds a dynamic cpufreq policy governor
+ designed for latency-sensitive workloads.
+
+ This governor attempts to reduce the latency of clock
+ increases so that the system is more responsive to
+ interactive workloads.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cpufreq_interactive.
+
+ For details, take a look at linux/Documentation/cpu-freq.
+
+ If in doubt, say N.
+
comment "CPU frequency scaling drivers"
config CPUFREQ_DT
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index bc3917d6015a..0fc6ad87a1b2 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -60,6 +60,22 @@ config ARM_IMX6Q_CPUFREQ
If in doubt, say N.
+config ARM_IMX7D_CPUFREQ
+ tristate "Freescale i.MX7 cpufreq support"
+ depends on ARCH_MXC
+ help
+ This adds cpufreq driver support for Freescale i.MX7 series SoCs.
+
+ If in doubt, say N.
+
+config ARM_IMX7ULP_CPUFREQ
+ tristate "NXP i.MX7ULP cpufreq support"
+ depends on ARCH_MXC
+ help
+ This adds cpufreq driver support for NXP i.MX7ULP series SoCs.
+
+ If in doubt, say N.
+
config ARM_INTEGRATOR
tristate "CPUfreq driver for ARM Integrator CPUs"
depends on ARCH_INTEGRATOR
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 0a9b6a093646..4fc9f547ae6e 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
+obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o
obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o
obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o
@@ -56,6 +57,8 @@ obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
+obj-$(CONFIG_ARM_IMX7D_CPUFREQ) += imx7-cpufreq.o
+obj-$(CONFIG_ARM_IMX7ULP_CPUFREQ) += imx7ulp-cpufreq.o
obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
obj-$(CONFIG_ARM_MT8173_CPUFREQ) += mt8173-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index ef1037e9c92b..3196ed9c1c0a 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -70,14 +70,6 @@ static ssize_t show_##file_name \
return sprintf(buf, "%u\n", dbs_data->file_name); \
}
-#define gov_attr_ro(_name) \
-static struct governor_attr _name = \
-__ATTR(_name, 0444, show_##_name, NULL)
-
-#define gov_attr_rw(_name) \
-static struct governor_attr _name = \
-__ATTR(_name, 0644, show_##_name, store_##_name)
-
/* Common to all CPUs of a policy */
struct policy_dbs_info {
struct cpufreq_policy *policy;
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
new file mode 100644
index 000000000000..3ff6f6a599c8
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -0,0 +1,1365 @@
+/*
+ * drivers/cpufreq/cpufreq_interactive.c
+ *
+ * Copyright (C) 2010-2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ * Author: Mike Chan (mike@android.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/cpufreq.h>
+#include <linux/irq_work.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/sched/rt.h>
+#include <linux/tick.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/kthread.h>
+#include <linux/slab.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/cpufreq_interactive.h>
+
+/* Separate instance required for each 'interactive' directory in sysfs */
+struct interactive_tunables {
+ struct gov_attr_set attr_set;
+
+ /* Hi speed to bump to from lo speed when load burst (default max) */
+ unsigned int hispeed_freq;
+
+ /* Go to hi speed when CPU load at or above this value. */
+#define DEFAULT_GO_HISPEED_LOAD 99
+ unsigned long go_hispeed_load;
+
+ /* Target load. Lower values result in higher CPU speeds. */
+ spinlock_t target_loads_lock;
+ unsigned int *target_loads;
+ int ntarget_loads;
+
+ /*
+ * The minimum amount of time to spend at a frequency before we can ramp
+ * down.
+ */
+#define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC)
+ unsigned long min_sample_time;
+
+ /* The sample rate of the timer used to increase frequency */
+ unsigned long sampling_rate;
+
+ /*
+ * Wait this long before raising speed above hispeed, by default a
+ * single timer interval.
+ */
+ spinlock_t above_hispeed_delay_lock;
+ unsigned int *above_hispeed_delay;
+ int nabove_hispeed_delay;
+
+ /* Non-zero means indefinite speed boost active */
+ int boost;
+ /* Duration of a boot pulse in usecs */
+ int boostpulse_duration;
+ /* End time of boost pulse in ktime converted to usecs */
+ u64 boostpulse_endtime;
+ bool boosted;
+
+ /*
+ * Max additional time to wait in idle, beyond sampling_rate, at speeds
+ * above minimum before wakeup to reduce speed, or -1 if unnecessary.
+ */
+#define DEFAULT_TIMER_SLACK (4 * DEFAULT_SAMPLING_RATE)
+ unsigned long timer_slack_delay;
+ unsigned long timer_slack;
+ bool io_is_busy;
+};
+
+/* Separate instance required for each 'struct cpufreq_policy' */
+struct interactive_policy {
+ struct cpufreq_policy *policy;
+ struct interactive_tunables *tunables;
+ struct list_head tunables_hook;
+};
+
+/* Separate instance required for each CPU */
+struct interactive_cpu {
+ struct update_util_data update_util;
+ struct interactive_policy *ipolicy;
+
+ struct irq_work irq_work;
+ u64 last_sample_time;
+ bool work_in_progress;
+
+ struct rw_semaphore enable_sem;
+ struct timer_list slack_timer;
+
+ spinlock_t load_lock; /* protects the next 4 fields */
+ u64 time_in_idle;
+ u64 time_in_idle_timestamp;
+ u64 cputime_speedadj;
+ u64 cputime_speedadj_timestamp;
+
+ spinlock_t target_freq_lock; /*protects target freq */
+ unsigned int target_freq;
+
+ unsigned int floor_freq;
+ u64 pol_floor_val_time; /* policy floor_validate_time */
+ u64 loc_floor_val_time; /* per-cpu floor_validate_time */
+ u64 pol_hispeed_val_time; /* policy hispeed_validate_time */
+ u64 loc_hispeed_val_time; /* per-cpu hispeed_validate_time */
+};
+
+static DEFINE_PER_CPU(struct interactive_cpu, interactive_cpu);
+
+/* Realtime thread handles frequency scaling */
+static struct task_struct *speedchange_task;
+static cpumask_t speedchange_cpumask;
+static spinlock_t speedchange_cpumask_lock;
+
+/* Target load. Lower values result in higher CPU speeds. */
+#define DEFAULT_TARGET_LOAD 90
+static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD};
+
+#define DEFAULT_SAMPLING_RATE (20 * USEC_PER_MSEC)
+#define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_SAMPLING_RATE
+static unsigned int default_above_hispeed_delay[] = {
+ DEFAULT_ABOVE_HISPEED_DELAY
+};
+
+/* Iterate over interactive policies for tunables */
+#define for_each_ipolicy(__ip) \
+ list_for_each_entry(__ip, &tunables->attr_set.policy_list, tunables_hook)
+
+static struct interactive_tunables *global_tunables;
+static DEFINE_MUTEX(global_tunables_lock);
+
+static inline void update_slack_delay(struct interactive_tunables *tunables)
+{
+ tunables->timer_slack_delay = usecs_to_jiffies(tunables->timer_slack +
+ tunables->sampling_rate);
+}
+
+static bool timer_slack_required(struct interactive_cpu *icpu)
+{
+ struct interactive_policy *ipolicy = icpu->ipolicy;
+ struct interactive_tunables *tunables = ipolicy->tunables;
+
+ if (tunables->timer_slack < 0)
+ return false;
+
+ if (icpu->target_freq > ipolicy->policy->min)
+ return true;
+
+ return false;
+}
+
+static void gov_slack_timer_start(struct interactive_cpu *icpu, int cpu)
+{
+ struct interactive_tunables *tunables = icpu->ipolicy->tunables;
+
+ icpu->slack_timer.expires = jiffies + tunables->timer_slack_delay;
+ add_timer_on(&icpu->slack_timer, cpu);
+}
+
+static void gov_slack_timer_modify(struct interactive_cpu *icpu)
+{
+ struct interactive_tunables *tunables = icpu->ipolicy->tunables;
+
+ mod_timer(&icpu->slack_timer, jiffies + tunables->timer_slack_delay);
+}
+
+static void slack_timer_resched(struct interactive_cpu *icpu, int cpu,
+ bool modify)
+{
+ struct interactive_tunables *tunables = icpu->ipolicy->tunables;
+ unsigned long flags;
+
+ spin_lock_irqsave(&icpu->load_lock, flags);
+
+ icpu->time_in_idle = get_cpu_idle_time(cpu,
+ &icpu->time_in_idle_timestamp,
+ tunables->io_is_busy);
+ icpu->cputime_speedadj = 0;
+ icpu->cputime_speedadj_timestamp = icpu->time_in_idle_timestamp;
+
+ if (timer_slack_required(icpu)) {
+ if (modify)
+ gov_slack_timer_modify(icpu);
+ else
+ gov_slack_timer_start(icpu, cpu);
+ }
+
+ spin_unlock_irqrestore(&icpu->load_lock, flags);
+}
+
+static unsigned int
+freq_to_above_hispeed_delay(struct interactive_tunables *tunables,
+ unsigned int freq)
+{
+ unsigned long flags;
+ unsigned int ret;
+ int i;
+
+ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags);
+
+ for (i = 0; i < tunables->nabove_hispeed_delay - 1 &&
+ freq >= tunables->above_hispeed_delay[i + 1]; i += 2)
+ ;
+
+ ret = tunables->above_hispeed_delay[i];
+ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags);
+
+ return ret;
+}
+
+static unsigned int freq_to_targetload(struct interactive_tunables *tunables,
+ unsigned int freq)
+{
+ unsigned long flags;
+ unsigned int ret;
+ int i;
+
+ spin_lock_irqsave(&tunables->target_loads_lock, flags);
+
+ for (i = 0; i < tunables->ntarget_loads - 1 &&
+ freq >= tunables->target_loads[i + 1]; i += 2)
+ ;
+
+ ret = tunables->target_loads[i];
+ spin_unlock_irqrestore(&tunables->target_loads_lock, flags);
+ return ret;
+}
+
+/*
+ * If increasing frequencies never map to a lower target load then
+ * choose_freq() will find the minimum frequency that does not exceed its
+ * target load given the current load.
+ */
+static unsigned int choose_freq(struct interactive_cpu *icpu,
+ unsigned int loadadjfreq)
+{
+ struct cpufreq_policy *policy = icpu->ipolicy->policy;
+ struct cpufreq_frequency_table *freq_table = policy->freq_table;
+ unsigned int prevfreq, freqmin = 0, freqmax = UINT_MAX, tl;
+ unsigned int freq = policy->cur;
+ int index;
+
+ do {
+ prevfreq = freq;
+ tl = freq_to_targetload(icpu->ipolicy->tunables, freq);
+
+ /*
+ * Find the lowest frequency where the computed load is less
+ * than or equal to the target load.
+ */
+
+ index = cpufreq_frequency_table_target(policy, loadadjfreq / tl,
+ CPUFREQ_RELATION_L);
+ if (index < 0)
+ break;
+
+ freq = freq_table[index].frequency;
+
+ if (freq > prevfreq) {
+ /* The previous frequency is too low */
+ freqmin = prevfreq;
+
+ if (freq < freqmax)
+ continue;
+
+ /* Find highest frequency that is less than freqmax */
+ index = cpufreq_frequency_table_target(policy,
+ freqmax - 1, CPUFREQ_RELATION_H);
+ if (index < 0)
+ break;
+
+ freq = freq_table[index].frequency;
+
+ if (freq == freqmin) {
+ /*
+ * The first frequency below freqmax has already
+ * been found to be too low. freqmax is the
+ * lowest speed we found that is fast enough.
+ */
+ freq = freqmax;
+ break;
+ }
+ } else if (freq < prevfreq) {
+ /* The previous frequency is high enough. */
+ freqmax = prevfreq;
+
+ if (freq > freqmin)
+ continue;
+
+ /* Find lowest frequency that is higher than freqmin */
+ index = cpufreq_frequency_table_target(policy,
+ freqmin + 1, CPUFREQ_RELATION_L);
+ if (index < 0)
+ break;
+
+ freq = freq_table[index].frequency;
+
+ /*
+ * If freqmax is the first frequency above
+ * freqmin then we have already found that
+ * this speed is fast enough.
+ */
+ if (freq == freqmax)
+ break;
+ }
+
+ /* If same frequency chosen as previous then done. */
+ } while (freq != prevfreq);
+
+ return freq;
+}
+
+static u64 update_load(struct interactive_cpu *icpu, int cpu)
+{
+ struct interactive_tunables *tunables = icpu->ipolicy->tunables;
+ unsigned int delta_idle, delta_time;
+ u64 now_idle, now, active_time;
+
+ now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy);
+ delta_idle = (unsigned int)(now_idle - icpu->time_in_idle);
+ delta_time = (unsigned int)(now - icpu->time_in_idle_timestamp);
+
+ if (delta_time <= delta_idle)
+ active_time = 0;
+ else
+ active_time = delta_time - delta_idle;
+
+ icpu->cputime_speedadj += active_time * icpu->ipolicy->policy->cur;
+
+ icpu->time_in_idle = now_idle;
+ icpu->time_in_idle_timestamp = now;
+
+ return now;
+}
+
+/* Re-evaluate load to see if a frequency change is required or not */
+static void eval_target_freq(struct interactive_cpu *icpu)
+{
+ struct interactive_tunables *tunables = icpu->ipolicy->tunables;
+ struct cpufreq_policy *policy = icpu->ipolicy->policy;
+ struct cpufreq_frequency_table *freq_table = policy->freq_table;
+ u64 cputime_speedadj, now, max_fvtime;
+ unsigned int new_freq, loadadjfreq, index, delta_time;
+ unsigned long flags;
+ int cpu_load;
+ int cpu = smp_processor_id();
+
+ spin_lock_irqsave(&icpu->load_lock, flags);
+ now = update_load(icpu, smp_processor_id());
+ delta_time = (unsigned int)(now - icpu->cputime_speedadj_timestamp);
+ cputime_speedadj = icpu->cputime_speedadj;
+ spin_unlock_irqrestore(&icpu->load_lock, flags);
+
+ if (WARN_ON_ONCE(!delta_time))
+ return;
+
+ spin_lock_irqsave(&icpu->target_freq_lock, flags);
+ do_div(cputime_speedadj, delta_time);
+ loadadjfreq = (unsigned int)cputime_speedadj * 100;
+ cpu_load = loadadjfreq / policy->cur;
+ tunables->boosted = tunables->boost ||
+ now < tunables->boostpulse_endtime;
+
+ if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) {
+ if (policy->cur < tunables->hispeed_freq) {
+ new_freq = tunables->hispeed_freq;
+ } else {
+ new_freq = choose_freq(icpu, loadadjfreq);
+
+ if (new_freq < tunables->hispeed_freq)
+ new_freq = tunables->hispeed_freq;
+ }
+ } else {
+ new_freq = choose_freq(icpu, loadadjfreq);
+ if (new_freq > tunables->hispeed_freq &&
+ policy->cur < tunables->hispeed_freq)
+ new_freq = tunables->hispeed_freq;
+ }
+
+ if (policy->cur >= tunables->hispeed_freq &&
+ new_freq > policy->cur &&
+ now - icpu->pol_hispeed_val_time < freq_to_above_hispeed_delay(tunables, policy->cur)) {
+ trace_cpufreq_interactive_notyet(cpu, cpu_load,
+ icpu->target_freq, policy->cur, new_freq);
+ goto exit;
+ }
+
+ icpu->loc_hispeed_val_time = now;
+
+ index = cpufreq_frequency_table_target(policy, new_freq,
+ CPUFREQ_RELATION_L);
+ new_freq = freq_table[index].frequency;
+
+ /*
+ * Do not scale below floor_freq unless we have been at or above the
+ * floor frequency for the minimum sample time since last validated.
+ */
+ max_fvtime = max(icpu->pol_floor_val_time, icpu->loc_floor_val_time);
+ if (new_freq < icpu->floor_freq && icpu->target_freq >= policy->cur) {
+ if (now - max_fvtime < tunables->min_sample_time) {
+ trace_cpufreq_interactive_notyet(cpu, cpu_load,
+ icpu->target_freq, policy->cur, new_freq);
+ goto exit;
+ }
+ }
+
+ /*
+ * Update the timestamp for checking whether speed has been held at
+ * or above the selected frequency for a minimum of min_sample_time,
+ * if not boosted to hispeed_freq. If boosted to hispeed_freq then we
+ * allow the speed to drop as soon as the boostpulse duration expires
+ * (or the indefinite boost is turned off).
+ */
+
+ if (!tunables->boosted || new_freq > tunables->hispeed_freq) {
+ icpu->floor_freq = new_freq;
+ if (icpu->target_freq >= policy->cur || new_freq >= policy->cur)
+ icpu->loc_floor_val_time = now;
+ }
+
+ if (icpu->target_freq == new_freq &&
+ icpu->target_freq <= policy->cur) {
+ trace_cpufreq_interactive_already(cpu, cpu_load,
+ icpu->target_freq, policy->cur, new_freq);
+ goto exit;
+ }
+
+ trace_cpufreq_interactive_target(cpu, cpu_load, icpu->target_freq,
+ policy->cur, new_freq);
+
+ icpu->target_freq = new_freq;
+ spin_unlock_irqrestore(&icpu->target_freq_lock, flags);
+
+ spin_lock_irqsave(&speedchange_cpumask_lock, flags);
+ cpumask_set_cpu(cpu, &speedchange_cpumask);
+ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
+
+ wake_up_process(speedchange_task);
+ return;
+
+exit:
+ spin_unlock_irqrestore(&icpu->target_freq_lock, flags);
+}
+
+static void cpufreq_interactive_update(struct interactive_cpu *icpu)
+{
+ eval_target_freq(icpu);
+ slack_timer_resched(icpu, smp_processor_id(), true);
+}
+
+static void cpufreq_interactive_get_policy_info(struct cpufreq_policy *policy,
+ unsigned int *pmax_freq,
+ u64 *phvt, u64 *pfvt)
+{
+ struct interactive_cpu *icpu;
+ u64 hvt = ~0ULL, fvt = 0;
+ unsigned int max_freq = 0, i;
+
+ for_each_cpu(i, policy->cpus) {
+ icpu = &per_cpu(interactive_cpu, i);
+
+ fvt = max(fvt, icpu->loc_floor_val_time);
+ if (icpu->target_freq > max_freq) {
+ max_freq = icpu->target_freq;
+ hvt = icpu->loc_hispeed_val_time;
+ } else if (icpu->target_freq == max_freq) {
+ hvt = min(hvt, icpu->loc_hispeed_val_time);
+ }
+ }
+
+ *pmax_freq = max_freq;
+ *phvt = hvt;
+ *pfvt = fvt;
+}
+
+static void cpufreq_interactive_adjust_cpu(unsigned int cpu,
+ struct cpufreq_policy *policy)
+{
+ struct interactive_cpu *icpu;
+ u64 hvt, fvt;
+ unsigned int max_freq;
+ int i;
+
+ cpufreq_interactive_get_policy_info(policy, &max_freq, &hvt, &fvt);
+
+ for_each_cpu(i, policy->cpus) {
+ icpu = &per_cpu(interactive_cpu, i);
+ icpu->pol_floor_val_time = fvt;
+ }
+
+ if (max_freq != policy->cur) {
+ __cpufreq_driver_target(policy, max_freq, CPUFREQ_RELATION_H);
+ for_each_cpu(i, policy->cpus) {
+ icpu = &per_cpu(interactive_cpu, i);
+ icpu->pol_hispeed_val_time = hvt;
+ }
+ }
+
+ trace_cpufreq_interactive_setspeed(cpu, max_freq, policy->cur);
+}
+
+static int cpufreq_interactive_speedchange_task(void *data)
+{
+ unsigned int cpu;
+ cpumask_t tmp_mask;
+ unsigned long flags;
+
+again:
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_lock_irqsave(&speedchange_cpumask_lock, flags);
+
+ if (cpumask_empty(&speedchange_cpumask)) {
+ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
+ schedule();
+
+ if (kthread_should_stop())
+ return 0;
+
+ spin_lock_irqsave(&speedchange_cpumask_lock, flags);
+ }
+
+ set_current_state(TASK_RUNNING);
+ tmp_mask = speedchange_cpumask;
+ cpumask_clear(&speedchange_cpumask);
+ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
+
+ for_each_cpu(cpu, &tmp_mask) {
+ struct interactive_cpu *icpu = &per_cpu(interactive_cpu, cpu);
+ struct cpufreq_policy *policy = icpu->ipolicy->policy;
+
+ if (unlikely(!down_read_trylock(&icpu->enable_sem)))
+ continue;
+
+ if (likely(icpu->ipolicy))
+ cpufreq_interactive_adjust_cpu(cpu, policy);
+
+ up_read(&icpu->enable_sem);
+ }
+
+ goto again;
+}
+
+static void cpufreq_interactive_boost(struct interactive_tunables *tunables)
+{
+ struct interactive_policy *ipolicy;
+ struct cpufreq_policy *policy;
+ struct interactive_cpu *icpu;
+ unsigned long flags[2];
+ bool wakeup = false;
+ int i;
+
+ tunables->boosted = true;
+
+ spin_lock_irqsave(&speedchange_cpumask_lock, flags[0]);
+
+ for_each_ipolicy(ipolicy) {
+ policy = ipolicy->policy;
+
+ for_each_cpu(i, policy->cpus) {
+ icpu = &per_cpu(interactive_cpu, i);
+
+ if (!down_read_trylock(&icpu->enable_sem))
+ continue;
+
+ if (!icpu->ipolicy) {
+ up_read(&icpu->enable_sem);
+ continue;
+ }
+
+ spin_lock_irqsave(&icpu->target_freq_lock, flags[1]);
+ if (icpu->target_freq < tunables->hispeed_freq) {
+ icpu->target_freq = tunables->hispeed_freq;
+ cpumask_set_cpu(i, &speedchange_cpumask);
+ icpu->pol_hispeed_val_time = ktime_to_us(ktime_get());
+ wakeup = true;
+ }
+ spin_unlock_irqrestore(&icpu->target_freq_lock, flags[1]);
+
+ up_read(&icpu->enable_sem);
+ }
+ }
+
+ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags[0]);
+
+ if (wakeup)
+ wake_up_process(speedchange_task);
+}
+
+static int cpufreq_interactive_notifier(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ struct cpufreq_freqs *freq = data;
+ struct interactive_cpu *icpu = &per_cpu(interactive_cpu, freq->cpu);
+ unsigned long flags;
+
+ if (val != CPUFREQ_POSTCHANGE)
+ return 0;
+
+ if (!down_read_trylock(&icpu->enable_sem))
+ return 0;
+
+ if (!icpu->ipolicy) {
+ up_read(&icpu->enable_sem);
+ return 0;
+ }
+
+ spin_lock_irqsave(&icpu->load_lock, flags);
+ update_load(icpu, freq->cpu);
+ spin_unlock_irqrestore(&icpu->load_lock, flags);
+
+ up_read(&icpu->enable_sem);
+
+ return 0;
+}
+
+static struct notifier_block cpufreq_notifier_block = {
+ .notifier_call = cpufreq_interactive_notifier,
+};
+
+static unsigned int *get_tokenized_data(const char *buf, int *num_tokens)
+{
+ const char *cp = buf;
+ int ntokens = 1, i = 0;
+ unsigned int *tokenized_data;
+ int err = -EINVAL;
+
+ while ((cp = strpbrk(cp + 1, " :")))
+ ntokens++;
+
+ if (!(ntokens & 0x1))
+ goto err;
+
+ tokenized_data = kcalloc(ntokens, sizeof(*tokenized_data), GFP_KERNEL);
+ if (!tokenized_data) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ cp = buf;
+ while (i < ntokens) {
+ if (kstrtouint(cp, 0, &tokenized_data[i++]) < 0)
+ goto err_kfree;
+
+ cp = strpbrk(cp, " :");
+ if (!cp)
+ break;
+ cp++;
+ }
+
+ if (i != ntokens)
+ goto err_kfree;
+
+ *num_tokens = ntokens;
+ return tokenized_data;
+
+err_kfree:
+ kfree(tokenized_data);
+err:
+ return ERR_PTR(err);
+}
+
+/* Interactive governor sysfs interface */
+static struct interactive_tunables *to_tunables(struct gov_attr_set *attr_set)
+{
+ return container_of(attr_set, struct interactive_tunables, attr_set);
+}
+
+#define show_one(file_name, type) \
+static ssize_t show_##file_name(struct gov_attr_set *attr_set, char *buf) \
+{ \
+ struct interactive_tunables *tunables = to_tunables(attr_set); \
+ return sprintf(buf, type "\n", tunables->file_name); \
+}
+
+static ssize_t show_target_loads(struct gov_attr_set *attr_set, char *buf)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long flags;
+ ssize_t ret = 0;
+ int i;
+
+ spin_lock_irqsave(&tunables->target_loads_lock, flags);
+
+ for (i = 0; i < tunables->ntarget_loads; i++)
+ ret += sprintf(buf + ret, "%u%s", tunables->target_loads[i],
+ i & 0x1 ? ":" : " ");
+
+ sprintf(buf + ret - 1, "\n");
+ spin_unlock_irqrestore(&tunables->target_loads_lock, flags);
+
+ return ret;
+}
+
+static ssize_t store_target_loads(struct gov_attr_set *attr_set,
+ const char *buf, size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned int *new_target_loads;
+ unsigned long flags;
+ int ntokens;
+
+ new_target_loads = get_tokenized_data(buf, &ntokens);
+ if (IS_ERR(new_target_loads))
+ return PTR_ERR(new_target_loads);
+
+ spin_lock_irqsave(&tunables->target_loads_lock, flags);
+ if (tunables->target_loads != default_target_loads)
+ kfree(tunables->target_loads);
+ tunables->target_loads = new_target_loads;
+ tunables->ntarget_loads = ntokens;
+ spin_unlock_irqrestore(&tunables->target_loads_lock, flags);
+
+ return count;
+}
+
+static ssize_t show_above_hispeed_delay(struct gov_attr_set *attr_set,
+ char *buf)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long flags;
+ ssize_t ret = 0;
+ int i;
+
+ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags);
+
+ for (i = 0; i < tunables->nabove_hispeed_delay; i++)
+ ret += sprintf(buf + ret, "%u%s",
+ tunables->above_hispeed_delay[i],
+ i & 0x1 ? ":" : " ");
+
+ sprintf(buf + ret - 1, "\n");
+ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags);
+
+ return ret;
+}
+
+static ssize_t store_above_hispeed_delay(struct gov_attr_set *attr_set,
+ const char *buf, size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned int *new_above_hispeed_delay = NULL;
+ unsigned long flags;
+ int ntokens;
+
+ new_above_hispeed_delay = get_tokenized_data(buf, &ntokens);
+ if (IS_ERR(new_above_hispeed_delay))
+ return PTR_ERR(new_above_hispeed_delay);
+
+ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags);
+ if (tunables->above_hispeed_delay != default_above_hispeed_delay)
+ kfree(tunables->above_hispeed_delay);
+ tunables->above_hispeed_delay = new_above_hispeed_delay;
+ tunables->nabove_hispeed_delay = ntokens;
+ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags);
+
+ return count;
+}
+
+static ssize_t store_hispeed_freq(struct gov_attr_set *attr_set,
+ const char *buf, size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long int val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ tunables->hispeed_freq = val;
+
+ return count;
+}
+
+static ssize_t store_go_hispeed_load(struct gov_attr_set *attr_set,
+ const char *buf, size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ tunables->go_hispeed_load = val;
+
+ return count;
+}
+
+static ssize_t store_min_sample_time(struct gov_attr_set *attr_set,
+ const char *buf, size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ tunables->min_sample_time = val;
+
+ return count;
+}
+
+static ssize_t show_timer_rate(struct gov_attr_set *attr_set, char *buf)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+
+ return sprintf(buf, "%lu\n", tunables->sampling_rate);
+}
+
+static ssize_t store_timer_rate(struct gov_attr_set *attr_set, const char *buf,
+ size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long val, val_round;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ val_round = jiffies_to_usecs(usecs_to_jiffies(val));
+ if (val != val_round)
+ pr_warn("timer_rate not aligned to jiffy. Rounded up to %lu\n",
+ val_round);
+
+ tunables->sampling_rate = val_round;
+
+ return count;
+}
+
+static ssize_t store_timer_slack(struct gov_attr_set *attr_set, const char *buf,
+ size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ tunables->timer_slack = val;
+ update_slack_delay(tunables);
+
+ return count;
+}
+
+static ssize_t store_boost(struct gov_attr_set *attr_set, const char *buf,
+ size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ tunables->boost = val;
+
+ if (tunables->boost) {
+ trace_cpufreq_interactive_boost("on");
+ if (!tunables->boosted)
+ cpufreq_interactive_boost(tunables);
+ } else {
+ tunables->boostpulse_endtime = ktime_to_us(ktime_get());
+ trace_cpufreq_interactive_unboost("off");
+ }
+
+ return count;
+}
+
+static ssize_t store_boostpulse(struct gov_attr_set *attr_set, const char *buf,
+ size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ tunables->boostpulse_endtime = ktime_to_us(ktime_get()) +
+ tunables->boostpulse_duration;
+ trace_cpufreq_interactive_boost("pulse");
+ if (!tunables->boosted)
+ cpufreq_interactive_boost(tunables);
+
+ return count;
+}
+
+static ssize_t store_boostpulse_duration(struct gov_attr_set *attr_set,
+ const char *buf, size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ tunables->boostpulse_duration = val;
+
+ return count;
+}
+
+static ssize_t store_io_is_busy(struct gov_attr_set *attr_set, const char *buf,
+ size_t count)
+{
+ struct interactive_tunables *tunables = to_tunables(attr_set);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ tunables->io_is_busy = val;
+
+ return count;
+}
+
+show_one(hispeed_freq, "%u");
+show_one(go_hispeed_load, "%lu");
+show_one(min_sample_time, "%lu");
+show_one(timer_slack, "%lu");
+show_one(boost, "%u");
+show_one(boostpulse_duration, "%u");
+show_one(io_is_busy, "%u");
+
+gov_attr_rw(target_loads);
+gov_attr_rw(above_hispeed_delay);
+gov_attr_rw(hispeed_freq);
+gov_attr_rw(go_hispeed_load);
+gov_attr_rw(min_sample_time);
+gov_attr_rw(timer_rate);
+gov_attr_rw(timer_slack);
+gov_attr_rw(boost);
+gov_attr_wo(boostpulse);
+gov_attr_rw(boostpulse_duration);
+gov_attr_rw(io_is_busy);
+
+static struct attribute *interactive_attributes[] = {
+ &target_loads.attr,
+ &above_hispeed_delay.attr,
+ &hispeed_freq.attr,
+ &go_hispeed_load.attr,
+ &min_sample_time.attr,
+ &timer_rate.attr,
+ &timer_slack.attr,
+ &boost.attr,
+ &boostpulse.attr,
+ &boostpulse_duration.attr,
+ &io_is_busy.attr,
+ NULL
+};
+
+static struct kobj_type interactive_tunables_ktype = {
+ .default_attrs = interactive_attributes,
+ .sysfs_ops = &governor_sysfs_ops,
+};
+
+/* Interactive Governor callbacks */
+struct interactive_governor {
+ struct cpufreq_governor gov;
+ unsigned int usage_count;
+};
+
+static struct interactive_governor interactive_gov;
+
+#define CPU_FREQ_GOV_INTERACTIVE (&interactive_gov.gov)
+
+static void irq_work(struct irq_work *irq_work)
+{
+ struct interactive_cpu *icpu = container_of(irq_work, struct
+ interactive_cpu, irq_work);
+
+ cpufreq_interactive_update(icpu);
+ icpu->work_in_progress = false;
+}
+
+static void update_util_handler(struct update_util_data *data, u64 time,
+ unsigned int flags)
+{
+ struct interactive_cpu *icpu = container_of(data,
+ struct interactive_cpu, update_util);
+ struct interactive_policy *ipolicy = icpu->ipolicy;
+ struct interactive_tunables *tunables = ipolicy->tunables;
+ u64 delta_ns;
+
+ /*
+ * The irq-work may not be allowed to be queued up right now.
+ * Possible reasons:
+ * - Work has already been queued up or is in progress.
+ * - It is too early (too little time from the previous sample).
+ */
+ if (icpu->work_in_progress)
+ return;
+
+ delta_ns = time - icpu->last_sample_time;
+ if ((s64)delta_ns < tunables->sampling_rate * NSEC_PER_USEC)
+ return;
+
+ icpu->last_sample_time = time;
+
+ icpu->work_in_progress = true;
+ irq_work_queue(&icpu->irq_work);
+}
+
+static void gov_set_update_util(struct interactive_policy *ipolicy)
+{
+ struct cpufreq_policy *policy = ipolicy->policy;
+ struct interactive_cpu *icpu;
+ int cpu;
+
+ for_each_cpu(cpu, policy->cpus) {
+ icpu = &per_cpu(interactive_cpu, cpu);
+
+ icpu->last_sample_time = 0;
+ cpufreq_add_update_util_hook(cpu, &icpu->update_util,
+ update_util_handler);
+ }
+}
+
+static inline void gov_clear_update_util(struct cpufreq_policy *policy)
+{
+ int i;
+
+ for_each_cpu(i, policy->cpus)
+ cpufreq_remove_update_util_hook(i);
+
+ synchronize_sched();
+}
+
+static void icpu_cancel_work(struct interactive_cpu *icpu)
+{
+ irq_work_sync(&icpu->irq_work);
+ icpu->work_in_progress = false;
+ del_timer_sync(&icpu->slack_timer);
+}
+
+static struct interactive_policy *
+interactive_policy_alloc(struct cpufreq_policy *policy)
+{
+ struct interactive_policy *ipolicy;
+
+ ipolicy = kzalloc(sizeof(*ipolicy), GFP_KERNEL);
+ if (!ipolicy)
+ return NULL;
+
+ ipolicy->policy = policy;
+
+ return ipolicy;
+}
+
+static void interactive_policy_free(struct interactive_policy *ipolicy)
+{
+ kfree(ipolicy);
+}
+
+static struct interactive_tunables *
+interactive_tunables_alloc(struct interactive_policy *ipolicy)
+{
+ struct interactive_tunables *tunables;
+
+ tunables = kzalloc(sizeof(*tunables), GFP_KERNEL);
+ if (!tunables)
+ return NULL;
+
+ gov_attr_set_init(&tunables->attr_set, &ipolicy->tunables_hook);
+ if (!have_governor_per_policy())
+ global_tunables = tunables;
+
+ ipolicy->tunables = tunables;
+
+ return tunables;
+}
+
+static void interactive_tunables_free(struct interactive_tunables *tunables)
+{
+ if (!have_governor_per_policy())
+ global_tunables = NULL;
+
+ kfree(tunables);
+}
+
+int cpufreq_interactive_init(struct cpufreq_policy *policy)
+{
+ struct interactive_policy *ipolicy;
+ struct interactive_tunables *tunables;
+ int ret;
+
+ /* State should be equivalent to EXIT */
+ if (policy->governor_data)
+ return -EBUSY;
+
+ ipolicy = interactive_policy_alloc(policy);
+ if (!ipolicy)
+ return -ENOMEM;
+
+ mutex_lock(&global_tunables_lock);
+
+ if (global_tunables) {
+ if (WARN_ON(have_governor_per_policy())) {
+ ret = -EINVAL;
+ goto free_int_policy;
+ }
+
+ policy->governor_data = ipolicy;
+ ipolicy->tunables = global_tunables;
+
+ gov_attr_set_get(&global_tunables->attr_set,
+ &ipolicy->tunables_hook);
+ goto out;
+ }
+
+ tunables = interactive_tunables_alloc(ipolicy);
+ if (!tunables) {
+ ret = -ENOMEM;
+ goto free_int_policy;
+ }
+
+ tunables->hispeed_freq = policy->max;
+ tunables->above_hispeed_delay = default_above_hispeed_delay;
+ tunables->nabove_hispeed_delay =
+ ARRAY_SIZE(default_above_hispeed_delay);
+ tunables->go_hispeed_load = DEFAULT_GO_HISPEED_LOAD;
+ tunables->target_loads = default_target_loads;
+ tunables->ntarget_loads = ARRAY_SIZE(default_target_loads);
+ tunables->min_sample_time = DEFAULT_MIN_SAMPLE_TIME;
+ tunables->boostpulse_duration = DEFAULT_MIN_SAMPLE_TIME;
+ tunables->sampling_rate = DEFAULT_SAMPLING_RATE;
+ tunables->timer_slack = DEFAULT_TIMER_SLACK;
+ update_slack_delay(tunables);
+
+ spin_lock_init(&tunables->target_loads_lock);
+ spin_lock_init(&tunables->above_hispeed_delay_lock);
+
+ policy->governor_data = ipolicy;
+
+ ret = kobject_init_and_add(&tunables->attr_set.kobj,
+ &interactive_tunables_ktype,
+ get_governor_parent_kobj(policy), "%s",
+ interactive_gov.gov.name);
+ if (ret)
+ goto fail;
+
+ /* One time initialization for governor */
+ if (!interactive_gov.usage_count++) {
+ cpufreq_register_notifier(&cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ }
+
+ out:
+ mutex_unlock(&global_tunables_lock);
+ return 0;
+
+ fail:
+ policy->governor_data = NULL;
+ interactive_tunables_free(tunables);
+
+ free_int_policy:
+ mutex_unlock(&global_tunables_lock);
+
+ interactive_policy_free(ipolicy);
+ pr_err("governor initialization failed (%d)\n", ret);
+
+ return ret;
+}
+
+void cpufreq_interactive_exit(struct cpufreq_policy *policy)
+{
+ struct interactive_policy *ipolicy = policy->governor_data;
+ struct interactive_tunables *tunables = ipolicy->tunables;
+ unsigned int count;
+
+ mutex_lock(&global_tunables_lock);
+
+ /* Last policy using the governor ? */
+ if (!--interactive_gov.usage_count) {
+ cpufreq_unregister_notifier(&cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ }
+
+ count = gov_attr_set_put(&tunables->attr_set, &ipolicy->tunables_hook);
+ policy->governor_data = NULL;
+ if (!count)
+ interactive_tunables_free(tunables);
+
+ mutex_unlock(&global_tunables_lock);
+
+ interactive_policy_free(ipolicy);
+}
+
+int cpufreq_interactive_start(struct cpufreq_policy *policy)
+{
+ struct interactive_policy *ipolicy = policy->governor_data;
+ struct interactive_cpu *icpu;
+ unsigned int cpu;
+
+ for_each_cpu(cpu, policy->cpus) {
+ icpu = &per_cpu(interactive_cpu, cpu);
+
+ icpu->target_freq = policy->cur;
+ icpu->floor_freq = icpu->target_freq;
+ icpu->pol_floor_val_time = ktime_to_us(ktime_get());
+ icpu->loc_floor_val_time = icpu->pol_floor_val_time;
+ icpu->pol_hispeed_val_time = icpu->pol_floor_val_time;
+ icpu->loc_hispeed_val_time = icpu->pol_floor_val_time;
+
+ down_write(&icpu->enable_sem);
+ icpu->ipolicy = ipolicy;
+ up_write(&icpu->enable_sem);
+
+ slack_timer_resched(icpu, cpu, false);
+ }
+
+ gov_set_update_util(ipolicy);
+ return 0;
+}
+
+void cpufreq_interactive_stop(struct cpufreq_policy *policy)
+{
+ struct interactive_policy *ipolicy = policy->governor_data;
+ struct interactive_cpu *icpu;
+ unsigned int cpu;
+
+ gov_clear_update_util(ipolicy->policy);
+
+ for_each_cpu(cpu, policy->cpus) {
+ icpu = &per_cpu(interactive_cpu, cpu);
+
+ icpu_cancel_work(icpu);
+
+ down_write(&icpu->enable_sem);
+ icpu->ipolicy = NULL;
+ up_write(&icpu->enable_sem);
+ }
+}
+
+void cpufreq_interactive_limits(struct cpufreq_policy *policy)
+{
+ struct interactive_cpu *icpu;
+ unsigned int cpu;
+ unsigned long flags;
+
+ cpufreq_policy_apply_limits(policy);
+
+ for_each_cpu(cpu, policy->cpus) {
+ icpu = &per_cpu(interactive_cpu, cpu);
+
+ spin_lock_irqsave(&icpu->target_freq_lock, flags);
+
+ if (policy->max < icpu->target_freq)
+ icpu->target_freq = policy->max;
+ else if (policy->min > icpu->target_freq)
+ icpu->target_freq = policy->min;
+
+ spin_unlock_irqrestore(&icpu->target_freq_lock, flags);
+ }
+}
+
+static struct interactive_governor interactive_gov = {
+ .gov = {
+ .name = "interactive",
+ .max_transition_latency = TRANSITION_LATENCY_LIMIT,
+ .owner = THIS_MODULE,
+ .init = cpufreq_interactive_init,
+ .exit = cpufreq_interactive_exit,
+ .start = cpufreq_interactive_start,
+ .stop = cpufreq_interactive_stop,
+ .limits = cpufreq_interactive_limits,
+ }
+};
+
+static void cpufreq_interactive_nop_timer(unsigned long data)
+{
+ /*
+ * The purpose of slack-timer is to wake up the CPU from IDLE, in order
+ * to decrease its frequency if it is not set to minimum already.
+ *
+ * This is important for platforms where CPU with higher frequencies
+ * consume higher power even at IDLE.
+ */
+}
+
+static int __init cpufreq_interactive_gov_init(void)
+{
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+ struct interactive_cpu *icpu;
+ unsigned int cpu;
+
+ for_each_possible_cpu(cpu) {
+ icpu = &per_cpu(interactive_cpu, cpu);
+
+ init_irq_work(&icpu->irq_work, irq_work);
+ spin_lock_init(&icpu->load_lock);
+ spin_lock_init(&icpu->target_freq_lock);
+ init_rwsem(&icpu->enable_sem);
+
+ /* Initialize per-cpu slack-timer */
+ init_timer_pinned(&icpu->slack_timer);
+ icpu->slack_timer.function = cpufreq_interactive_nop_timer;
+ }
+
+ spin_lock_init(&speedchange_cpumask_lock);
+ speedchange_task = kthread_create(cpufreq_interactive_speedchange_task,
+ NULL, "cfinteractive");
+ if (IS_ERR(speedchange_task))
+ return PTR_ERR(speedchange_task);
+
+ sched_setscheduler_nocheck(speedchange_task, SCHED_FIFO, &param);
+ get_task_struct(speedchange_task);
+
+ /* wake up so the thread does not look hung to the freezer */
+ wake_up_process(speedchange_task);
+
+ return cpufreq_register_governor(CPU_FREQ_GOV_INTERACTIVE);
+}
+
+#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE
+struct cpufreq_governor *cpufreq_default_governor(void)
+{
+ return CPU_FREQ_GOV_INTERACTIVE;
+}
+
+fs_initcall(cpufreq_interactive_gov_init);
+#else
+module_init(cpufreq_interactive_gov_init);
+#endif
+
+static void __exit cpufreq_interactive_gov_exit(void)
+{
+ cpufreq_unregister_governor(CPU_FREQ_GOV_INTERACTIVE);
+ kthread_stop(speedchange_task);
+ put_task_struct(speedchange_task);
+}
+module_exit(cpufreq_interactive_gov_exit);
+
+MODULE_AUTHOR("Mike Chan <mike@android.com>");
+MODULE_DESCRIPTION("'cpufreq_interactive' - A dynamic cpufreq governor for Latency sensitive workloads");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index ef1fa8145419..dbcf35b456b8 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -1,28 +1,39 @@
/*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-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/clk.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/of.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
#define PU_SOC_VOLTAGE_NORMAL 1250000
#define PU_SOC_VOLTAGE_HIGH 1275000
+#define DC_VOLTAGE_MIN 1300000
+#define DC_VOLTAGE_MAX 1400000
#define FREQ_1P2_GHZ 1200000000
+#define FREQ_396_MHZ 396000
+#define FREQ_528_MHZ 528000
+#define FREQ_198_MHZ 198000
+#define FREQ_24_MHZ 24000
-static struct regulator *arm_reg;
+struct regulator *arm_reg;
static struct regulator *pu_reg;
-static struct regulator *soc_reg;
+struct regulator *soc_reg;
+static struct regulator *dc_reg;
static struct clk *arm_clk;
static struct clk *pll1_sys_clk;
@@ -31,6 +42,9 @@ static struct clk *step_clk;
static struct clk *pll2_pfd2_396m_clk;
/* clk used by i.MX6UL */
+static struct clk *pll1_bypass;
+static struct clk *pll1_bypass_src;
+static struct clk *pll1;
static struct clk *pll2_bus_clk;
static struct clk *secondary_sel_clk;
@@ -38,9 +52,11 @@ static struct device *cpu_dev;
static bool free_opp;
static struct cpufreq_frequency_table *freq_table;
static unsigned int transition_latency;
-
+static struct mutex set_cpufreq_lock;
static u32 *imx6_soc_volt;
static u32 soc_opp_count;
+static bool ignore_dc_reg;
+static bool low_power_run_support;
static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
{
@@ -49,15 +65,29 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
unsigned int old_freq, new_freq;
int ret;
+ mutex_lock(&set_cpufreq_lock);
+
new_freq = freq_table[index].frequency;
freq_hz = new_freq * 1000;
- old_freq = clk_get_rate(arm_clk) / 1000;
+ old_freq = policy->cur;
+
+ /*
+ * ON i.MX6ULL, the 24MHz setpoint is not seen by cpufreq
+ * so we neet to prevent the cpufreq change frequency
+ * from 24MHz to 198Mhz directly. busfreq will handle this
+ * when exit from low bus mode.
+ */
+ if (old_freq == FREQ_24_MHZ && new_freq == FREQ_198_MHZ) {
+ mutex_unlock(&set_cpufreq_lock);
+ return 0;
+ };
rcu_read_lock();
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
if (IS_ERR(opp)) {
rcu_read_unlock();
dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
+ mutex_unlock(&set_cpufreq_lock);
return PTR_ERR(opp);
}
@@ -68,6 +98,16 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
old_freq / 1000, volt_old / 1000,
new_freq / 1000, volt / 1000);
+ /*
+ * CPU freq is increasing, so need to ensure
+ * that bus frequency is increased too.
+ */
+ if (low_power_run_support) {
+ if (old_freq == freq_table[0].frequency)
+ request_bus_freq(BUS_FREQ_HIGH);
+ } else if (old_freq <= FREQ_396_MHZ && new_freq > FREQ_396_MHZ) {
+ request_bus_freq(BUS_FREQ_HIGH);
+ }
/* scaling up? scale voltage before frequency */
if (new_freq > old_freq) {
@@ -75,18 +115,21 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
if (ret) {
dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
+ mutex_unlock(&set_cpufreq_lock);
return ret;
}
}
ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
if (ret) {
dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret);
+ mutex_unlock(&set_cpufreq_lock);
return ret;
}
ret = regulator_set_voltage_tol(arm_reg, volt, 0);
if (ret) {
dev_err(cpu_dev,
"failed to scale vddarm up: %d\n", ret);
+ mutex_unlock(&set_cpufreq_lock);
return ret;
}
}
@@ -102,7 +145,8 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
* - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it
* - Disable pll2_pfd2_396m_clk
*/
- if (of_machine_is_compatible("fsl,imx6ul")) {
+ if (of_machine_is_compatible("fsl,imx6ul") ||
+ of_machine_is_compatible("fsl,imx6ull")) {
/*
* When changing pll1_sw_clk's parent to pll1_sys_clk,
* CPU may run at higher than 528MHz, this will lead to
@@ -118,12 +162,28 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
clk_set_parent(secondary_sel_clk, pll2_pfd2_396m_clk);
clk_set_parent(step_clk, secondary_sel_clk);
clk_set_parent(pll1_sw_clk, step_clk);
+ if (freq_hz > clk_get_rate(pll2_bus_clk)) {
+ clk_set_rate(pll1, new_freq * 1000);
+ clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+ }
} else {
clk_set_parent(step_clk, pll2_pfd2_396m_clk);
clk_set_parent(pll1_sw_clk, step_clk);
if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
+ /* Ensure that pll1_bypass is set back to
+ * pll1. We have to do this first so that the
+ * change rate done to pll1_sys_clk done below
+ * can propagate up to pll1.
+ */
+ clk_set_parent(pll1_bypass, pll1);
clk_set_rate(pll1_sys_clk, new_freq * 1000);
clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+ } else {
+ /*
+ * Need to ensure that PLL1 is bypassed and enabled
+ * before ARM-PODF is set.
+ */
+ clk_set_parent(pll1_bypass, pll1_bypass_src);
}
}
@@ -132,6 +192,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
if (ret) {
dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
regulator_set_voltage_tol(arm_reg, volt_old, 0);
+ mutex_unlock(&set_cpufreq_lock);
return ret;
}
@@ -156,14 +217,40 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
}
}
}
+ /*
+ * If CPU is dropped to the lowest level, release the need
+ * for a high bus frequency.
+ */
+ if (low_power_run_support) {
+ if (new_freq == freq_table[0].frequency)
+ release_bus_freq(BUS_FREQ_HIGH);
+ } else if (old_freq > FREQ_396_MHZ && new_freq <= FREQ_396_MHZ) {
+ release_bus_freq(BUS_FREQ_HIGH);
+ }
+ mutex_unlock(&set_cpufreq_lock);
return 0;
}
static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
{
+ int ret;
+
policy->clk = arm_clk;
- return cpufreq_generic_init(policy, freq_table, transition_latency);
+ policy->cur = clk_get_rate(arm_clk) / 1000;
+
+ ret = cpufreq_generic_init(policy, freq_table, transition_latency);
+ if (ret) {
+ dev_err(cpu_dev, "imx6 cpufreq init failed!\n");
+ return ret;
+ }
+ if (low_power_run_support && policy->cur > freq_table[0].frequency) {
+ request_bus_freq(BUS_FREQ_HIGH);
+ } else if (policy->cur > FREQ_396_MHZ) {
+ request_bus_freq(BUS_FREQ_HIGH);
+ }
+
+ return 0;
}
static struct cpufreq_driver imx6q_cpufreq_driver = {
@@ -176,15 +263,61 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
.attr = cpufreq_generic_attr,
};
+static int imx6_cpufreq_pm_notify(struct notifier_block *nb,
+ unsigned long event, void *dummy)
+{
+ struct cpufreq_policy *data = cpufreq_cpu_get(0);
+ static u32 cpufreq_policy_min_pre_suspend;
+
+ /*
+ * During suspend/resume, When cpufreq driver try to increase
+ * voltage/freq, it needs to control I2C/SPI to communicate
+ * with external PMIC to adjust voltage, but these I2C/SPI
+ * devices may be already suspended, to avoid such scenario,
+ * we just increase cpufreq to highest setpoint before suspend.
+ */
+ if (!data)
+ return NOTIFY_BAD;
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ cpufreq_policy_min_pre_suspend = data->user_policy.min;
+ data->user_policy.min = data->user_policy.max;
+
+ if (!IS_ERR(dc_reg) && !ignore_dc_reg)
+ regulator_set_voltage_tol(dc_reg, DC_VOLTAGE_MAX, 0);
+ break;
+ case PM_POST_SUSPEND:
+ data->user_policy.min = cpufreq_policy_min_pre_suspend;
+
+ if (!IS_ERR(dc_reg) && !ignore_dc_reg)
+ regulator_set_voltage_tol(dc_reg, DC_VOLTAGE_MIN, 0);
+ break;
+ default:
+ break;
+ }
+
+ cpufreq_update_policy(0);
+ cpufreq_cpu_put(data);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block imx6_cpufreq_pm_notifier = {
+ .notifier_call = imx6_cpufreq_pm_notify,
+};
+
static int imx6q_cpufreq_probe(struct platform_device *pdev)
{
struct device_node *np;
struct dev_pm_opp *opp;
+ struct clk *vpu_axi_podf;
unsigned long min_volt, max_volt;
int num, ret;
const struct property *prop;
const __be32 *val;
- u32 nr, i, j;
+ u32 nr, j, i = 0;
+ u32 vpu_axi_rate = 0;
cpu_dev = get_cpu_device(0);
if (!cpu_dev) {
@@ -203,14 +336,19 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
pll1_sw_clk = clk_get(cpu_dev, "pll1_sw");
step_clk = clk_get(cpu_dev, "step");
pll2_pfd2_396m_clk = clk_get(cpu_dev, "pll2_pfd2_396m");
+ pll1 = clk_get(cpu_dev, "pll1");
+ pll1_bypass = clk_get(cpu_dev, "pll1_bypass");
+ pll1_bypass_src = clk_get(cpu_dev, "pll1_bypass_src");
if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) ||
- IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) {
+ IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk) || IS_ERR(pll1) ||
+ IS_ERR(pll1_bypass) || IS_ERR(pll1_bypass_src)) {
dev_err(cpu_dev, "failed to get clocks\n");
ret = -ENOENT;
goto put_clk;
}
- if (of_machine_is_compatible("fsl,imx6ul")) {
+ if (of_machine_is_compatible("fsl,imx6ul") ||
+ of_machine_is_compatible("fsl,imx6ull")) {
pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
@@ -220,15 +358,40 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
}
}
+ vpu_axi_podf = clk_get(cpu_dev, "vpu_axi_podf");
+ if (!IS_ERR(vpu_axi_podf)) {
+ vpu_axi_rate = clk_get_rate(vpu_axi_podf);
+ clk_put(vpu_axi_podf);
+ }
+
arm_reg = regulator_get(cpu_dev, "arm");
pu_reg = regulator_get_optional(cpu_dev, "pu");
soc_reg = regulator_get(cpu_dev, "soc");
if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) {
- dev_err(cpu_dev, "failed to get regulators\n");
- ret = -ENOENT;
+ ret = IS_ERR(arm_reg)?PTR_ERR(arm_reg):PTR_ERR(soc_reg);
+ if (ret == -EPROBE_DEFER)
+ dev_warn(cpu_dev, "regulators not ready, retry\n");
+ else
+ dev_err(cpu_dev, "failed to get regulators: %d\n", ret);
goto put_reg;
}
+ dc_reg = regulator_get_optional(cpu_dev, "dc");
+
+ /*
+ * soc_reg sync with arm_reg if arm shares the same regulator
+ * with soc. Otherwise, regulator common framework will refuse to update
+ * this consumer's voltage right now while another consumer voltage
+ * still keep in old one. For example, imx6sx-sdb with pfuze200 in
+ * ldo-bypass mode.
+ */
+ of_property_read_u32(np, "fsl,arm-soc-shared", &i);
+ if (i == 1)
+ soc_reg = arm_reg;
+
+ /* On i.MX6ULL, check the 24MHz low power run mode support */
+ low_power_run_support = of_property_read_bool(np, "fsl,low-power-run");
+
/*
* We expect an OPP table supplied by platform.
* Just, incase the platform did not supply the OPP
@@ -259,8 +422,17 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
goto put_reg;
}
+ /*
+ * On i.MX6UL/ULL EVK board, if the SOC is run in overide frequency,
+ * the dc_regulator voltage should not be touched.
+ */
+ if (freq_table[num - 1].frequency > FREQ_528_MHZ)
+ ignore_dc_reg = true;
+ if (!IS_ERR(dc_reg) && !ignore_dc_reg)
+ regulator_set_voltage_tol(dc_reg, DC_VOLTAGE_MIN, 0);
+
/* Make imx6_soc_volt array's size same as arm opp number */
- imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL);
+ imx6_soc_volt = kzalloc(sizeof(*imx6_soc_volt) * num, GFP_KERNEL);
if (imx6_soc_volt == NULL) {
ret = -ENOMEM;
goto free_freq_table;
@@ -285,6 +457,19 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
unsigned long volt = be32_to_cpup(val++);
if (freq_table[j].frequency == freq) {
imx6_soc_volt[soc_opp_count++] = volt;
+#ifdef CONFIG_MX6_VPU_352M
+ if (freq == 792000) {
+ pr_info("increase SOC/PU voltage for VPU352MHz\n");
+ imx6_soc_volt[soc_opp_count - 1] = 1250000;
+ }
+#endif
+ if (vpu_axi_rate == 396000000) {
+ if (freq <= 996000) {
+ pr_info("increase SOC/PU voltage for VPU396MHz at %ld MHz\n",
+ freq / 1000);
+ imx6_soc_volt[soc_opp_count - 1] = 1275000;
+ }
+ }
break;
}
}
@@ -333,16 +518,22 @@ soc_opp_out:
if (ret > 0)
transition_latency += ret * 1000;
+ mutex_init(&set_cpufreq_lock);
+
ret = cpufreq_register_driver(&imx6q_cpufreq_driver);
if (ret) {
dev_err(cpu_dev, "failed register driver: %d\n", ret);
goto free_freq_table;
}
+ register_pm_notifier(&imx6_cpufreq_pm_notifier);
+
of_node_put(np);
+ dev_info(cpu_dev, "Registered imx6q-cpufreq\n");
return 0;
free_freq_table:
+ kfree(imx6_soc_volt);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_opp:
if (free_opp)
@@ -354,6 +545,8 @@ put_reg:
regulator_put(pu_reg);
if (!IS_ERR(soc_reg))
regulator_put(soc_reg);
+ if (!IS_ERR(dc_reg))
+ regulator_put(dc_reg);
put_clk:
if (!IS_ERR(arm_clk))
clk_put(arm_clk);
@@ -365,6 +558,12 @@ put_clk:
clk_put(step_clk);
if (!IS_ERR(pll2_pfd2_396m_clk))
clk_put(pll2_pfd2_396m_clk);
+ if (!IS_ERR(pll1))
+ clk_put(pll1);
+ if (!IS_ERR(pll1_bypass))
+ clk_put(pll1_bypass);
+ if (!IS_ERR(pll1_bypass_src))
+ clk_put(pll1_bypass_src);
if (!IS_ERR(pll2_bus_clk))
clk_put(pll2_bus_clk);
if (!IS_ERR(secondary_sel_clk))
@@ -376,6 +575,7 @@ put_clk:
static int imx6q_cpufreq_remove(struct platform_device *pdev)
{
cpufreq_unregister_driver(&imx6q_cpufreq_driver);
+ kfree(imx6_soc_volt);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
if (free_opp)
dev_pm_opp_of_remove_table(cpu_dev);
@@ -383,10 +583,15 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev)
if (!IS_ERR(pu_reg))
regulator_put(pu_reg);
regulator_put(soc_reg);
+ if (!IS_ERR(dc_reg))
+ regulator_put(dc_reg);
clk_put(arm_clk);
clk_put(pll1_sys_clk);
clk_put(pll1_sw_clk);
clk_put(step_clk);
+ clk_put(pll1);
+ clk_put(pll1_bypass);
+ clk_put(pll1_bypass_src);
clk_put(pll2_pfd2_396m_clk);
clk_put(pll2_bus_clk);
clk_put(secondary_sel_clk);
diff --git a/drivers/cpufreq/imx7-cpufreq.c b/drivers/cpufreq/imx7-cpufreq.c
new file mode 100644
index 000000000000..32f30cec04ff
--- /dev/null
+++ b/drivers/cpufreq/imx7-cpufreq.c
@@ -0,0 +1,271 @@
+/*
+ * 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/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_opp.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+static struct clk *arm_clk;
+
+static struct regulator *arm_reg;
+
+static struct device *cpu_dev;
+static struct cpufreq_frequency_table *freq_table;
+static unsigned int transition_latency;
+static struct mutex set_cpufreq_lock;
+
+static int imx7d_set_target(struct cpufreq_policy *policy, unsigned int index)
+{
+ struct dev_pm_opp *opp;
+ unsigned long freq_hz, volt, volt_old;
+ unsigned int old_freq, new_freq;
+ int ret;
+
+ mutex_lock(&set_cpufreq_lock);
+
+ new_freq = freq_table[index].frequency;
+ freq_hz = new_freq * 1000;
+ old_freq = clk_get_rate(arm_clk) / 1000;
+
+ rcu_read_lock();
+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
+ dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
+ mutex_unlock(&set_cpufreq_lock);
+ return PTR_ERR(opp);
+ }
+ volt = dev_pm_opp_get_voltage(opp);
+
+ rcu_read_unlock();
+ volt_old = regulator_get_voltage(arm_reg);
+
+ dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
+ old_freq / 1000, volt_old / 1000,
+ new_freq / 1000, volt / 1000);
+
+ /* Scaling up? scale voltage before frequency */
+ if (new_freq > old_freq) {
+ ret = regulator_set_voltage_tol(arm_reg, volt, 0);
+ if (ret) {
+ dev_err(cpu_dev, "failed to scale vddarm up: %d\n", ret);
+ mutex_unlock(&set_cpufreq_lock);
+ return ret;
+ }
+ }
+
+ /* change the cpu frequency */
+ ret = clk_set_rate(arm_clk, new_freq * 1000);
+ if (ret) {
+ dev_err(cpu_dev, " failed to set clock rate: %d\n", ret);
+ regulator_set_voltage_tol(arm_reg, volt_old, 0);
+ mutex_unlock(&set_cpufreq_lock);
+ return ret;
+ }
+
+ /* scaling down? scaling voltage after frequency */
+ if (new_freq < old_freq) {
+ ret = regulator_set_voltage_tol(arm_reg, volt, 0);
+ if (ret) {
+ dev_warn(cpu_dev, "failed to scale vddarm down: %d\n", ret);
+ ret = 0;
+ }
+ }
+
+ mutex_unlock(&set_cpufreq_lock);
+ return 0;
+}
+
+static int imx7d_cpufreq_init(struct cpufreq_policy *policy)
+{
+ int ret;
+ policy->clk = arm_clk;
+ policy->cur = clk_get_rate(arm_clk) / 1000;
+
+ ret = cpufreq_generic_init(policy, freq_table, transition_latency);
+ if (ret) {
+ dev_err(cpu_dev, "imx7d cpufreq init failed!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct cpufreq_driver imx7d_cpufreq_driver = {
+ .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+ .verify = cpufreq_generic_frequency_table_verify,
+ .target_index = imx7d_set_target,
+ .get = cpufreq_generic_get,
+ .init = imx7d_cpufreq_init,
+ .name = "imx7d-cpufreq",
+ .attr = cpufreq_generic_attr,
+};
+
+static int imx7_cpufreq_pm_notify(struct notifier_block *nb,
+ unsigned long event, void *dummy)
+{
+ struct cpufreq_policy *data = cpufreq_cpu_get(0);
+ static u32 cpufreq_policy_min_pre_suspend;
+
+ /*
+ * During suspend/resume, when cpufreq driver try to increase
+ * voltage/freq, it needs to control I2C/SPI to communicate
+ * with external PMIC to adjust voltage, but these I2C/SPI
+ * devices may be already suspended, to avoid such scenario,
+ * we just increase cpufreq to highest setpoint before suspend.
+ */
+ if (!data)
+ return NOTIFY_BAD;
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ cpufreq_policy_min_pre_suspend = data->user_policy.min;
+ data->user_policy.min = data->user_policy.max;
+ break;
+ case PM_POST_SUSPEND:
+ data->user_policy.min = cpufreq_policy_min_pre_suspend;
+ break;
+ default:
+ break;
+ }
+
+ cpufreq_update_policy(0);
+ cpufreq_cpu_put(data);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block imx7_cpufreq_pm_notifier = {
+ .notifier_call = imx7_cpufreq_pm_notify,
+};
+
+static int imx7d_cpufreq_probe(struct platform_device *pdev)
+{
+ struct device_node *np;
+ struct dev_pm_opp *opp;
+ unsigned long min_volt, max_volt;
+ int num, ret;
+
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev) {
+ pr_err("failed to get cpu0 device\n");
+ return -ENODEV;
+ }
+
+ np = of_node_get(cpu_dev->of_node);
+ if (!np) {
+ dev_err(cpu_dev, "failed to find the cpu0 node\n");
+ return -ENOENT;
+ }
+
+ arm_clk = devm_clk_get(cpu_dev, "arm");
+ if (IS_ERR(arm_clk)) {
+ dev_err(cpu_dev, "failed to get arm clock\n");
+ ret = PTR_ERR(arm_clk);
+ goto put_node;
+ }
+
+ arm_reg = devm_regulator_get(cpu_dev, "arm");
+ if (IS_ERR(arm_reg)) {
+ dev_err(cpu_dev, "failed to get the regulator\n");
+ ret = -ENOENT;
+ goto put_node;
+ }
+
+ /* We expect an OPP table supplied by platform.
+ * Just incase the platform did not supply the OPP
+ * table, it will try to get it.
+ */
+ num = dev_pm_opp_get_opp_count(cpu_dev);
+ if (num < 0) {
+ ret = dev_pm_opp_of_add_table(cpu_dev);
+ if (ret < 0) {
+ dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
+ goto put_node;
+ }
+ num = dev_pm_opp_get_opp_count(cpu_dev);
+ if (num < 0) {
+ ret = num;
+ dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
+ goto put_node;
+ }
+ }
+
+ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
+ if (ret) {
+ dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
+ goto put_node;
+ }
+
+ if (of_property_read_u32(np, "clock-latency", &transition_latency))
+ transition_latency = CPUFREQ_ETERNAL;
+
+ /* OPP is maintained in order of increasing frequency, and
+ * freq_table initialized from OPP is therefore sorted in the
+ * same order
+ */
+ rcu_read_lock();
+ opp = dev_pm_opp_find_freq_exact(cpu_dev,
+ freq_table[0].frequency * 1000, true);
+ min_volt = dev_pm_opp_get_voltage(opp);
+ opp = dev_pm_opp_find_freq_exact(cpu_dev,
+ freq_table[--num].frequency * 1000, true);
+ max_volt = dev_pm_opp_get_voltage(opp);
+ rcu_read_unlock();
+ ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
+ if (ret > 0)
+ transition_latency += ret * 1000;
+
+ mutex_init(&set_cpufreq_lock);
+
+ ret = cpufreq_register_driver(&imx7d_cpufreq_driver);
+ if (ret) {
+ dev_err(cpu_dev, "failed register driver: %d\n", ret);
+ goto free_freq_table;
+ }
+
+ register_pm_notifier(&imx7_cpufreq_pm_notifier);
+
+ of_node_put(np);
+ return 0;
+
+free_freq_table:
+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+put_node:
+ of_node_put(np);
+
+ return ret;
+}
+
+static int imx7d_cpufreq_remove(struct platform_device *pdev)
+{
+ cpufreq_unregister_driver(&imx7d_cpufreq_driver);
+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+
+ return 0;
+}
+
+static struct platform_driver imx7d_cpufreq_platdrv = {
+ .driver = {
+ .name = "imx7d-cpufreq",
+ .owner = THIS_MODULE,
+ },
+ .probe = imx7d_cpufreq_probe,
+ .remove = imx7d_cpufreq_remove,
+};
+
+module_platform_driver(imx7d_cpufreq_platdrv);
+
+MODULE_DESCRIPTION("Freescale i.MX7D cpufreq driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/imx7ulp-cpufreq.c b/drivers/cpufreq/imx7ulp-cpufreq.c
new file mode 100644
index 000000000000..f2b95d705a1b
--- /dev/null
+++ b/drivers/cpufreq/imx7ulp-cpufreq.c
@@ -0,0 +1,285 @@
+ /*
+ * 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/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_opp.h>
+#include <linux/pm_qos.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+
+#define MAX_RUN_FREQ 528000
+#define SMC_PMPROT 0x8
+#define SMC_PMCTRL 0x10
+
+static struct clk *arm_clk;
+static struct clk *core_div;
+static struct clk *sys_sel;
+static struct clk *hsrun_sys_sel;
+static struct clk *hsrun_core;
+static struct clk *spll_pfd0;
+static struct clk *spll_sel;
+static struct clk *firc_clk;
+
+static struct pm_qos_request pm_qos_hsrun;
+
+static void __iomem *smc_base;
+
+static struct regulator *arm_reg;
+static struct device *cpu_dev;
+static struct cpufreq_frequency_table *freq_table;
+static unsigned int transition_latency;
+static struct mutex set_cpufreq_lock;
+
+static int imx7ulp_set_target(struct cpufreq_policy *policy, unsigned int index)
+{
+ struct dev_pm_opp *opp;
+ unsigned long freq_hz, volt, volt_old;
+ unsigned int old_freq, new_freq;
+ u32 val;
+ int ret;
+
+ mutex_lock(&set_cpufreq_lock);
+
+ new_freq = freq_table[index].frequency;
+ freq_hz = new_freq * 1000;
+ old_freq = clk_get_rate(arm_clk) / 1000;
+
+ rcu_read_lock();
+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
+ dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
+ mutex_unlock(&set_cpufreq_lock);
+ return PTR_ERR(opp);
+ }
+ volt = dev_pm_opp_get_voltage(opp);
+
+ rcu_read_unlock();
+ volt_old = regulator_get_voltage(arm_reg);
+
+ dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
+ old_freq / 1000, volt_old / 1000,
+ new_freq / 1000, volt / 1000);
+
+ /* Scaling up? scale voltage before frequency */
+ if (new_freq > old_freq) {
+ ret = regulator_set_voltage_tol(arm_reg, volt, 0);
+ if (ret) {
+ dev_err(cpu_dev, "failed to scale vddarm up: %d\n", ret);
+ mutex_unlock(&set_cpufreq_lock);
+ return ret;
+ }
+ }
+
+ /* before changing pll_arm rate, change the arm_src's soure
+ * to firc clk first.
+ */
+ if (new_freq > MAX_RUN_FREQ) {
+ pm_qos_add_request(&pm_qos_hsrun, PM_QOS_CPU_DMA_LATENCY, 0);
+ clk_set_parent(sys_sel, firc_clk);
+ /* switch to HSRUN mode */
+ val = readl_relaxed(smc_base + SMC_PMCTRL);
+ val |= (0x3 << 8);
+ writel_relaxed(val, smc_base + SMC_PMCTRL);
+ /* change the clock rate in HSRUN */
+ clk_set_rate(spll_pfd0, new_freq * 1000);
+ clk_set_parent(hsrun_sys_sel, spll_sel);
+ clk_set_parent(arm_clk, hsrun_core);
+ } else {
+ /* change the HSRUN clock to firc */
+ clk_set_parent(hsrun_sys_sel, firc_clk);
+ /* switch to RUN mode */
+ val = readl_relaxed(smc_base + SMC_PMCTRL);
+ val &= ~(0x3 << 8);
+ writel_relaxed(val, smc_base + SMC_PMCTRL);
+
+ clk_set_rate(spll_pfd0, new_freq * 1000);
+ clk_set_parent(sys_sel, spll_sel);
+ clk_set_parent(arm_clk, core_div);
+ if (old_freq > MAX_RUN_FREQ)
+ pm_qos_remove_request(&pm_qos_hsrun);
+ }
+
+ /* scaling down? scaling voltage after frequency */
+ if (new_freq < old_freq) {
+ ret = regulator_set_voltage_tol(arm_reg, volt, 0);
+ if (ret) {
+ dev_warn(cpu_dev, "failed to scale vddarm down: %d\n", ret);
+ ret = 0;
+ }
+ }
+
+ mutex_unlock(&set_cpufreq_lock);
+ return 0;
+}
+
+static int imx7ulp_cpufreq_init(struct cpufreq_policy *policy)
+{
+ int ret;
+ policy->clk = arm_clk;
+ policy->cur = clk_get_rate(arm_clk) / 1000;
+ policy->suspend_freq = freq_table[0].frequency;
+
+ ret = cpufreq_generic_init(policy, freq_table, transition_latency);
+
+ if (ret) {
+ dev_err(cpu_dev, "imx7ulp cpufreq init failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct cpufreq_driver imx7ulp_cpufreq_driver = {
+ .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+ .verify = cpufreq_generic_frequency_table_verify,
+ .target_index = imx7ulp_set_target,
+ .get = cpufreq_generic_get,
+ .init = imx7ulp_cpufreq_init,
+ .name = "imx7ulp-cpufreq",
+ .attr = cpufreq_generic_attr,
+#ifdef CONFIG_PM
+ .suspend = cpufreq_generic_suspend,
+#endif
+};
+
+static int imx7ulp_cpufreq_probe(struct platform_device *pdev)
+{
+ struct device_node *np;
+ int ret;
+
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev) {
+ pr_err("failed to get cpu0 device\n");
+ return -ENOENT;
+ }
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-smc1");
+ smc_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!smc_base)
+ return -ENOMEM;
+
+ np = of_node_get(cpu_dev->of_node);
+ if (!np) {
+ dev_err(cpu_dev, "failed to find the cpu0 node\n");
+ return -ENOENT;
+ }
+
+ arm_clk = clk_get(cpu_dev, "arm");
+ sys_sel = clk_get(cpu_dev, "sys_sel");
+ core_div = clk_get(cpu_dev, "core_div");
+ hsrun_sys_sel = clk_get(cpu_dev, "hsrun_sys_sel");
+ hsrun_core = clk_get(cpu_dev, "hsrun_core");
+ spll_pfd0 = clk_get(cpu_dev, "spll_pfd0");
+ spll_sel = clk_get(cpu_dev, "spll_sel");
+ firc_clk = clk_get(cpu_dev, "firc");
+
+ if (IS_ERR(arm_clk) || IS_ERR(sys_sel) || IS_ERR(spll_sel) ||
+ IS_ERR(spll_sel) || IS_ERR(firc_clk) || IS_ERR(hsrun_sys_sel) ||
+ IS_ERR(hsrun_core)) {
+ dev_err(cpu_dev, "failed to get cpu clock\n");
+ ret = -ENOENT;
+ goto put_clk;
+ }
+
+ arm_reg = regulator_get(cpu_dev, "arm");
+ if (IS_ERR(arm_reg)) {
+ dev_err(cpu_dev, "failed to get regulator\n");
+ ret = -ENOENT;
+ goto put_reg;
+ }
+
+ ret = dev_pm_opp_of_add_table(cpu_dev);
+ if (ret < 0) {
+ dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
+ goto put_reg;
+ }
+
+ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
+ if (ret) {
+ dev_err(cpu_dev, "failed to init cpufreq table\n");
+ goto put_reg;
+ }
+
+ if (of_property_read_u32(np, "clock-latency", &transition_latency))
+ transition_latency = CPUFREQ_ETERNAL;
+
+ mutex_init(&set_cpufreq_lock);
+ ret = cpufreq_register_driver(&imx7ulp_cpufreq_driver);
+ if (ret) {
+ dev_err(cpu_dev, "failed to register driver\n");
+ goto free_opp_table;
+ }
+
+ return 0;
+
+free_opp_table:
+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+put_reg:
+ regulator_put(arm_reg);
+put_clk:
+ if (!IS_ERR(arm_clk))
+ clk_put(arm_clk);
+ if (!IS_ERR(sys_sel))
+ clk_put(sys_sel);
+ if (!IS_ERR(core_div))
+ clk_put(core_div);
+ if (!IS_ERR(hsrun_sys_sel))
+ clk_put(hsrun_sys_sel);
+ if (!IS_ERR(hsrun_core))
+ clk_put(hsrun_core);
+ if (!IS_ERR(spll_pfd0))
+ clk_put(spll_pfd0);
+ if (!IS_ERR(spll_sel))
+ clk_put(spll_sel);
+ if (!IS_ERR(firc_clk))
+ clk_put(firc_clk);
+
+ return ret;
+}
+
+static int imx7ulp_cpufreq_remove(struct platform_device *pdev)
+{
+ cpufreq_unregister_driver(&imx7ulp_cpufreq_driver);
+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+
+ regulator_put(arm_reg);
+ clk_put(arm_clk);
+ clk_put(sys_sel);
+ clk_put(core_div);
+ clk_put(hsrun_sys_sel);
+ clk_put(hsrun_core);
+ clk_put(spll_pfd0);
+ clk_put(spll_sel);
+ clk_put(firc_clk);
+
+ return 0;
+}
+
+static struct platform_driver imx7ulp_cpufreq_platdrv = {
+ .driver = {
+ .name = "imx7ulp-cpufreq",
+ .owner = THIS_MODULE,
+ },
+ .probe = imx7ulp_cpufreq_probe,
+ .remove = imx7ulp_cpufreq_remove,
+};
+
+module_platform_driver(imx7ulp_cpufreq_platdrv);
+
+MODULE_DESCRIPTION("NXP i.MX7ULP cpufreq driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 64bf3024b680..6741be76b20b 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -79,6 +79,7 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
select CRYPTO_AEAD
select CRYPTO_AUTHENC
select CRYPTO_BLKCIPHER
+ select CRYPTO_DES
help
Selecting this will offload crypto for users of the
scatterlist crypto API (such as the linux native IPSec
@@ -128,6 +129,57 @@ config CRYPTO_DEV_FSL_CAAM_IMX
def_bool SOC_IMX6 || SOC_IMX7D
depends on CRYPTO_DEV_FSL_CAAM
+
+config CRYPTO_DEV_FSL_CAAM_RNG_TEST
+ boolean "Test caam rng"
+ depends on CRYPTO_DEV_FSL_CAAM_RNG_API
+ default n
+ help
+ Selecting this will enable a self-test to run for the
+ caam RNG. This test is several minutes long and executes
+ just before the RNG is registered with the hw_random API.
+
+config CRYPTO_DEV_FSL_CAAM_SM
+ tristate "CAAM Secure Memory / Keystore API (EXPERIMENTAL)"
+ default n
+ help
+ Enables use of a prototype kernel-level Keystore API with CAAM
+ Secure Memory for insertion/extraction of bus-protected secrets.
+
+config CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE
+ int "Size of each keystore slot in Secure Memory"
+ depends on CRYPTO_DEV_FSL_CAAM_SM
+ range 5 9
+ default 7
+ help
+ Select size of allocation units to divide Secure Memory pages into
+ (the size of a "slot" as referenced inside the API code).
+ Established as powers of two.
+ Examples:
+ 5 => 32 bytes
+ 6 => 64 bytes
+ 7 => 128 bytes
+ 8 => 256 bytes
+ 9 => 512 bytes
+
+config CRYPTO_DEV_FSL_CAAM_SM_TEST
+ tristate "CAAM Secure Memory - Keystore Test/Example (EXPERIMENTAL)"
+ depends on CRYPTO_DEV_FSL_CAAM_SM
+ default n
+ help
+ Example thread to exercise the Keystore API and to verify that
+ stored and recovered secrets can be used for general purpose
+ encryption/decryption.
+
+config CRYPTO_DEV_FSL_CAAM_SECVIO
+ tristate "CAAM/SNVS Security Violation Handler (EXPERIMENTAL)"
+ depends on CRYPTO_DEV_FSL_CAAM
+ default n
+ help
+ Enables installation of an interrupt handler with registrable
+ handler functions which can be specified to act on the consequences
+ of a security violation.
+
config CRYPTO_DEV_FSL_CAAM_DEBUG
bool "Enable debug output in CAAM driver"
depends on CRYPTO_DEV_FSL_CAAM
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 08bf5515ae8a..e09e7e20f767 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -11,6 +11,9 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SM) += sm_store.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST) += sm_test.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO) += secvio.o
caam-objs := ctrl.o
caam_jr-objs := jr.o key_gen.o error.o
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 0d743c634f25..8cef9ad08c2b 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -163,6 +163,9 @@ struct caam_aead_alg {
bool registered;
};
+static uint8_t *ecb_zero_iv;
+static dma_addr_t ecb_ziv_dma;
+
/* Set DK bit in class 1 operation if shared */
static inline void append_dec_op1(u32 *desc, u32 type)
{
@@ -1755,6 +1758,33 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
return ret;
}
+
+static int ablkcipher_des_setkey(struct crypto_ablkcipher *ablkcipher,
+ const u8 *key, unsigned int keylen)
+{
+ u32 tmp[DES_EXPKEY_WORDS];
+ u32 flags;
+ int ret;
+
+ if (keylen != DES_KEY_SIZE) {
+ crypto_ablkcipher_set_flags(ablkcipher,
+ CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+
+ ret = des_ekey(tmp, key);
+
+ flags = crypto_ablkcipher_get_flags(ablkcipher);
+ if (!ret && (flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ crypto_ablkcipher_set_flags(ablkcipher,
+ CRYPTO_TFM_RES_WEAK_KEY);
+ return -EINVAL;
+ }
+
+ return ablkcipher_setkey(ablkcipher, key, keylen);
+}
+
+
static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
const u8 *key, unsigned int keylen)
{
@@ -2015,7 +2045,10 @@ static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
struct ablkcipher_request *req = context;
struct ablkcipher_edesc *edesc;
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+ int bsize = crypto_ablkcipher_blocksize(ablkcipher);
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+ size_t ivcopy = min_t(size_t, bsize, ivsize);
#ifdef DEBUG
dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
@@ -2047,6 +2080,12 @@ static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
kfree(edesc);
+ /* Pass IV along for cbc */
+ if ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == OP_ALG_AAI_CBC) {
+ scatterwalk_map_and_copy(req->info, req->dst,
+ req->nbytes - bsize, ivcopy, 0);
+ }
+
ablkcipher_request_complete(req, err);
}
@@ -2626,6 +2665,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
int sgc;
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
int sec4_sg_index;
+ uint32_t c1_alg_typ = ctx->class1_alg_type;
src_nents = sg_count(req->src, req->nbytes);
@@ -2642,10 +2682,17 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
DMA_FROM_DEVICE);
}
- iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, iv_dma)) {
- dev_err(jrdev, "unable to map IV\n");
- return ERR_PTR(-ENOMEM);
+ if ((!req->info && ivsize) &&
+ ((c1_alg_typ & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES) &&
+ ((c1_alg_typ & OP_ALG_AAI_MASK) == OP_ALG_AAI_ECB)) {
+ iv_dma = ecb_ziv_dma;
+ } else {
+ iv_dma = dma_map_single(jrdev, req->info, ivsize,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, iv_dma)) {
+ dev_err(jrdev, "unable to map IV\n");
+ return ERR_PTR(-ENOMEM);
+ }
}
/*
@@ -2956,6 +3003,22 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
},
{
+ .name = "ecb(aes)",
+ .driver_name = "ecb-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .template_ablkcipher = {
+ .setkey = ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_ECB,
+ },
+ {
.name = "cbc(des3_ede)",
.driver_name = "cbc-3des-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
@@ -2973,6 +3036,22 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
},
{
+ .name = "ecb(des3_ede)",
+ .driver_name = "ecb-des3-caam",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .template_ablkcipher = {
+ .setkey = ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_ECB,
+ },
+ {
.name = "cbc(des)",
.driver_name = "cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
@@ -2990,6 +3069,22 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
},
{
+ .name = "ecb(des)",
+ .driver_name = "ecb-des-caam",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .template_ablkcipher = {
+ .setkey = ablkcipher_des_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_ECB,
+ },
+ {
.name = "ctr(aes)",
.driver_name = "ctr-aes-caam",
.blocksize = 1,
@@ -3040,6 +3135,23 @@ static struct caam_alg_template driver_algs[] = {
},
.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XTS,
},
+ {
+ .name = "ecb(arc4)",
+ .driver_name = "ecb-arc4-caam",
+ .blocksize = ARC4_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .template_ablkcipher = {
+ .setkey = ablkcipher_setkey,
+ .encrypt = ablkcipher_encrypt,
+ .decrypt = ablkcipher_decrypt,
+ .geniv = "eseqiv",
+ .min_keysize = ARC4_MIN_KEY_SIZE,
+ .max_keysize = ARC4_MAX_KEY_SIZE,
+ .ivsize = ARC4_BLOCK_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_ARC4 | OP_ALG_AAI_ECB
+ },
+
};
static struct caam_aead_alg driver_aeads[] = {
@@ -4455,10 +4567,35 @@ static void caam_aead_exit(struct crypto_aead *tfm)
static void __exit caam_algapi_exit(void)
{
-
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ struct device *ctrldev;
struct caam_crypto_alg *t_alg, *n;
int i;
+ if (!ecb_zero_iv)
+ goto skip_ecb_ziv;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ goto skip_ecb_ziv;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+
+ if (!pdev) {
+ of_node_put(dev_node);
+ goto skip_ecb_ziv;
+ }
+
+ ctrldev = &pdev->dev;
+
+ dma_unmap_single(ctrldev, ecb_ziv_dma, AES_BLOCK_SIZE, DMA_TO_DEVICE);
+ kfree(ecb_zero_iv);
+
+skip_ecb_ziv:
for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) {
struct caam_aead_alg *t_alg = driver_aeads + i;
@@ -4500,8 +4637,12 @@ static struct caam_crypto_alg *caam_alg_alloc(struct caam_alg_template
alg->cra_blocksize = template->blocksize;
alg->cra_alignmask = 0;
alg->cra_ctxsize = sizeof(struct caam_ctx);
- alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
- template->type;
+ alg->cra_flags = CRYPTO_ALG_ASYNC | template->type;
+
+#ifdef CRYPTO_ALG_KERN_DRIVER_ONLY
+ alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
+#endif
+
switch (template->type) {
case CRYPTO_ALG_TYPE_GIVCIPHER:
alg->cra_type = &crypto_givcipher_type;
@@ -4568,6 +4709,16 @@ static int __init caam_algapi_init(void)
if (!priv)
return -ENODEV;
+ ecb_zero_iv = kzalloc(AES_BLOCK_SIZE, GFP_KERNEL);
+ if (!ecb_zero_iv)
+ return -ENOMEM;
+
+ ecb_ziv_dma = dma_map_single(ctrldev, ecb_zero_iv, AES_BLOCK_SIZE,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(ctrldev, ecb_ziv_dma)) {
+ kfree(ecb_zero_iv);
+ return -ENOMEM;
+ }
INIT_LIST_HEAD(&alg_list);
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 631337c2e4a7..c0fe91d80ef5 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -62,6 +62,7 @@
#include "error.h"
#include "sg_sw_sec4.h"
#include "key_gen.h"
+#include <linux/string.h>
#define CAAM_CRA_PRIORITY 3000
@@ -115,6 +116,7 @@ struct caam_hash_ctx {
u8 key[CAAM_MAX_HASH_KEY_SIZE];
dma_addr_t key_dma;
int ctx_len;
+ unsigned int key_len;
unsigned int split_key_len;
unsigned int split_key_pad_len;
};
@@ -232,6 +234,13 @@ static inline void append_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
KEY_DEST_MDHA_SPLIT | KEY_ENC);
}
+static inline void append_key_axcbc(u32 *desc, struct caam_hash_ctx *ctx)
+{
+ append_key_as_imm(desc, ctx->key, ctx->key_len,
+ ctx->key_len, CLASS_1 |
+ KEY_DEST_CLASS_REG);
+}
+
/* Append key if it has been set */
static inline void init_sh_desc_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
{
@@ -253,6 +262,25 @@ static inline void init_sh_desc_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
}
+static inline void init_sh_desc_key_axcbc(u32 *desc, struct caam_hash_ctx *ctx)
+{
+ u32 *key_jump_cmd;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ if (ctx->key_len) {
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ append_key_axcbc(desc, ctx);
+
+ set_jump_tgt_here(desc, key_jump_cmd);
+ }
+
+ /* Propagate errors from shared to job descriptor */
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
+
+}
/*
* For ahash read data from seqin following state->caam_ctx,
* and write resulting class2 context to seqout, which may be state->caam_ctx
@@ -272,6 +300,20 @@ static inline void ahash_append_load_str(u32 *desc, int digestsize)
LDST_SRCDST_BYTE_CONTEXT);
}
+static inline void axcbc_append_load_str(u32 *desc, int digestsize)
+{
+ /* Calculate remaining bytes to read */
+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+ /* Read remaining bytes */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_LAST1 |
+ FIFOLD_TYPE_MSG | KEY_VLF);
+
+ /* Store class1 context bytes */
+ append_seq_store(desc, digestsize, LDST_CLASS_1_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+}
+
/*
* For ahash update, final and finup, import context, read and write to seqout
*/
@@ -294,6 +336,27 @@ static inline void ahash_ctx_data_to_out(u32 *desc, u32 op, u32 state,
ahash_append_load_str(desc, digestsize);
}
+/*
+ * For ahash update, final and finup, import context, read and write to seqout
+ */
+static inline void axcbc_ctx_data_to_out(u32 *desc, u32 op, u32 state,
+ int digestsize,
+ struct caam_hash_ctx *ctx)
+{
+ init_sh_desc_key_axcbc(desc, ctx);
+
+ /* Import context from software */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | ctx->ctx_len);
+
+ /* Class 1 operation */
+ append_operation(desc, op | state | OP_ALG_ENCRYPT);
+
+ /*
+ * Load from buf and/or src and write to req->result or state->context
+ */
+ axcbc_append_load_str(desc, digestsize);
+}
/* For ahash firsts and digest, read and write to seqout */
static inline void ahash_data_to_out(u32 *desc, u32 op, u32 state,
int digestsize, struct caam_hash_ctx *ctx)
@@ -309,6 +372,21 @@ static inline void ahash_data_to_out(u32 *desc, u32 op, u32 state,
ahash_append_load_str(desc, digestsize);
}
+/* For ahash firsts and digest, read and write to seqout */
+static inline void axcbc_data_to_out(u32 *desc, u32 op, u32 state,
+ int digestsize, struct caam_hash_ctx *ctx)
+{
+ init_sh_desc_key_axcbc(desc, ctx);
+
+ /* Class 1 operation */
+ append_operation(desc, op | state | OP_ALG_ENCRYPT);
+
+ /*
+ * Load from buf and/or src and write to req->result or state->context
+ */
+ axcbc_append_load_str(desc, digestsize);
+}
+
static int ahash_set_sh_desc(struct crypto_ahash *ahash)
{
struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
@@ -426,6 +504,124 @@ static int ahash_set_sh_desc(struct crypto_ahash *ahash)
return 0;
}
+static int axcbc_set_sh_desc(struct crypto_ahash *ahash)
+{
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ int digestsize = crypto_ahash_digestsize(ahash);
+ struct device *jrdev = ctx->jrdev;
+ u32 have_key = 0;
+ u32 *desc;
+
+ /* ahash_update shared descriptor */
+ desc = ctx->sh_desc_update;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* Import context from software */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | ctx->ctx_len);
+
+ /* Class 1 operation */
+ append_operation(desc, ctx->alg_type | OP_ALG_AS_UPDATE |
+ OP_ALG_ENCRYPT);
+
+ /* Load data and write to result or context */
+ axcbc_append_load_str(desc, ctx->ctx_len);
+
+ ctx->sh_desc_update_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_update_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash update shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ /* ahash_update_first shared descriptor */
+ desc = ctx->sh_desc_update_first;
+
+ axcbc_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INIT,
+ ctx->ctx_len, ctx);
+
+ ctx->sh_desc_update_first_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_update_first_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash update first shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
+ desc_bytes(desc), DMA_TO_DEVICE);
+
+ /* ahash_final shared descriptor */
+ desc = ctx->sh_desc_fin;
+
+ axcbc_ctx_data_to_out(desc, have_key | ctx->alg_type,
+ OP_ALG_AS_FINALIZE, digestsize, ctx);
+
+ ctx->sh_desc_fin_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_fin_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash final shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
+ desc_bytes(desc), DMA_TO_DEVICE);
+
+ /* ahash_finup shared descriptor */
+ desc = ctx->sh_desc_finup;
+
+ axcbc_ctx_data_to_out(desc, have_key | ctx->alg_type,
+ OP_ALG_AS_FINALIZE, digestsize, ctx);
+
+ ctx->sh_desc_finup_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_finup_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash finup shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_finup_dma,
+ desc_bytes(desc), DMA_TO_DEVICE);
+
+ /* ahash_digest shared descriptor */
+ desc = ctx->sh_desc_digest;
+
+ axcbc_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INITFINAL,
+ digestsize, ctx);
+
+ ctx->sh_desc_digest_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_digest_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash digest shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
+ desc_bytes(desc), DMA_TO_DEVICE);
+
+ return 0;
+}
static int gen_split_hash_key(struct caam_hash_ctx *ctx, const u8 *key_in,
u32 keylen)
{
@@ -582,6 +778,25 @@ static int ahash_setkey(struct crypto_ahash *ahash,
return -EINVAL;
}
+static int axcbc_setkey(struct crypto_ahash *ahash,
+ const u8 *key, unsigned int keylen)
+{
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ int ret = 0;
+
+ ctx->key_len = keylen;
+ memcpy(ctx->key, key, keylen);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
+ ctx->key_len, 1);
+#endif
+
+ ret = axcbc_set_sh_desc(ahash);
+
+ return ret;
+}
/*
* ahash_edesc - s/w-extended ahash descriptor
* @dst_dma: physical mapped address of req->result
@@ -1826,6 +2041,29 @@ static struct caam_hash_template driver_hash[] = {
.alg_type = OP_ALG_ALGSEL_MD5,
.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
},
+ {
+ .name = "xcbc(aes)",
+ .driver_name = "xcbc-aes-caam",
+ .hmac_name = "xcbc(aes)",
+ .hmac_driver_name = "xcbc-aes-caam",
+ .blocksize = XCBC_MAC_BLOCK_WORDS * 4,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = axcbc_setkey,
+ .halg = {
+ .digestsize = XCBC_MAC_DIGEST_SIZE,
+ .statesize = sizeof(struct caam_export_state),
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC,
+ .alg_op = OP_ALG_ALGSEL_AES,
+ },
};
struct caam_hash_alg {
@@ -1875,6 +2113,41 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm)
return ahash_set_sh_desc(ahash);
}
+static int caam_axcbc_cra_init(struct crypto_tfm *tfm)
+{
+ struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+ struct crypto_alg *base = tfm->__crt_alg;
+ struct hash_alg_common *halg =
+ container_of(base, struct hash_alg_common, base);
+ struct ahash_alg *alg =
+ container_of(halg, struct ahash_alg, halg);
+ struct caam_hash_alg *caam_hash =
+ container_of(alg, struct caam_hash_alg, ahash_alg);
+ struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+ int ret = 0;
+
+ /*
+ * Get a Job ring from Job Ring driver to ensure in-order
+ * crypto request processing per tfm
+ */
+ ctx->jrdev = caam_jr_alloc();
+ if (IS_ERR(ctx->jrdev)) {
+ pr_err("Job Ring Device allocation for transform failed\n");
+ return PTR_ERR(ctx->jrdev);
+ }
+
+ /* copy descriptor header template value */
+ ctx->alg_type = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
+ ctx->alg_op = OP_TYPE_CLASS1_ALG | caam_hash->alg_op;
+
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct caam_hash_state));
+
+ ret = axcbc_set_sh_desc(ahash);
+
+ return ret;
+}
+
static void caam_hash_cra_exit(struct crypto_tfm *tfm)
{
struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
@@ -1951,7 +2224,11 @@ caam_hash_alloc(struct caam_hash_template *template,
t_alg->ahash_alg.setkey = NULL;
}
alg->cra_module = THIS_MODULE;
- alg->cra_init = caam_hash_cra_init;
+
+ if (strstr(alg->cra_name, "xcbc") > 0)
+ alg->cra_init = caam_axcbc_cra_init;
+ else
+ alg->cra_init = caam_hash_cra_init;
alg->cra_exit = caam_hash_cra_exit;
alg->cra_ctxsize = sizeof(struct caam_hash_ctx);
alg->cra_priority = CAAM_CRA_PRIORITY;
@@ -2046,6 +2323,9 @@ static int __init caam_algapi_hash_init(void)
} else
list_add_tail(&t_alg->entry, &hash_list);
+ if (alg->alg_op == OP_ALG_ALGSEL_AES)
+ continue;
+
/* register unkeyed version */
t_alg = caam_hash_alloc(alg, false);
if (IS_ERR(t_alg)) {
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index 9b92af2c7241..601381c239d8 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -256,6 +256,49 @@ static void caam_cleanup(struct hwrng *rng)
rng_unmap_ctx(rng_ctx);
}
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
+static inline void test_len(struct hwrng *rng, size_t len, bool wait)
+{
+ u8 *buf;
+ int real_len;
+
+ buf = kzalloc(sizeof(u8) * len, GFP_KERNEL);
+ real_len = rng->read(rng, buf, len, wait);
+ if (real_len == 0 && wait)
+ pr_err("WAITING FAILED\n");
+ pr_info("wanted %d bytes, got %d\n", len, real_len);
+ print_hex_dump(KERN_INFO, "random bytes@: ", DUMP_PREFIX_ADDRESS,
+ 16, 4, buf, real_len, 1);
+ kfree(buf);
+}
+
+static inline void test_mode_once(struct hwrng *rng, bool wait)
+{
+#define TEST_CHUNK (RN_BUF_SIZE / 4)
+
+ test_len(rng, TEST_CHUNK, wait);
+ test_len(rng, RN_BUF_SIZE * 2, wait);
+ test_len(rng, RN_BUF_SIZE * 2 - TEST_CHUNK, wait);
+}
+
+static inline void test_mode(struct hwrng *rng, bool wait)
+{
+#define TEST_PASS 1
+ int i;
+
+ for (i = 0; i < TEST_PASS; i++)
+ test_mode_once(rng, wait);
+}
+
+static void self_test(struct hwrng *rng)
+{
+ pr_info("testing without waiting\n");
+ test_mode(rng, false);
+ pr_info("testing with waiting\n");
+ test_mode(rng, true);
+}
+#endif
+
static int caam_init_buf(struct caam_rng_ctx *ctx, int buf_id)
{
struct buf_data *bd = &ctx->bufs[buf_id];
@@ -360,6 +403,10 @@ static int __init caam_rng_init(void)
if (err)
goto free_rng_ctx;
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
+ self_test(&caam_rng);
+#endif
+
dev_info(dev, "registering rng-caam\n");
return hwrng_register(&caam_rng);
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 2ca101ac0c17..a468f2bc6229 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -15,6 +15,7 @@
#include "desc_constr.h"
#include "error.h"
#include "ctrl.h"
+#include "sm.h"
bool caam_little_end;
EXPORT_SYMBOL(caam_little_end);
@@ -382,8 +383,8 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
wr_reg32(&r4tst->rtsdctl, val);
/* min. freq. count, equal to 1/4 of the entropy sample length */
wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
- /* disable maximum frequency count */
- wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE);
+ /* max. freq. count, equal to 16 times the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmax, ent_delay << 4);
/* read the control register */
val = rd_reg32(&r4tst->rtmctl);
/*
@@ -397,23 +398,115 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
wr_reg32(&r4tst->rtmctl, val);
}
-/**
- * caam_get_era() - Return the ERA of the SEC on SoC, based
- * on "sec-era" propery in the DTS. This property is updated by u-boot.
- **/
-int caam_get_era(void)
+static void detect_era(struct caam_drv_private *ctrlpriv)
{
+ int ret, i;
+ u32 caam_era;
+ u32 caam_id_ms;
+ char *era_source;
struct device_node *caam_node;
- int ret;
- u32 prop;
-
+ struct sec_vid sec_vid;
+ static const struct {
+ u16 ip_id;
+ u8 maj_rev;
+ u8 era;
+ } caam_eras[] = {
+ {0x0A10, 1, 1},
+ {0x0A10, 2, 2},
+ {0x0A12, 1, 3},
+ {0x0A14, 1, 3},
+ {0x0A10, 3, 4},
+ {0x0A11, 1, 4},
+ {0x0A14, 2, 4},
+ {0x0A16, 1, 4},
+ {0x0A18, 1, 4},
+ {0x0A11, 2, 5},
+ {0x0A12, 2, 5},
+ {0x0A13, 1, 5},
+ {0x0A1C, 1, 5},
+ {0x0A12, 4, 6},
+ {0x0A13, 2, 6},
+ {0x0A16, 2, 6},
+ {0x0A17, 1, 6},
+ {0x0A18, 2, 6},
+ {0x0A1A, 1, 6},
+ {0x0A1C, 2, 6},
+ {0x0A14, 3, 7},
+ {0x0A10, 4, 8},
+ {0x0A11, 3, 8},
+ {0x0A11, 4, 8},
+ {0x0A12, 5, 8},
+ {0x0A16, 3, 8},
+ };
+
+ /* If the user or bootloader has set the property we'll use that */
caam_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- ret = of_property_read_u32(caam_node, "fsl,sec-era", &prop);
+ ret = of_property_read_u32(caam_node, "fsl,sec-era", &caam_era);
of_node_put(caam_node);
- return ret ? -ENOTSUPP : prop;
+ if (!ret) {
+ era_source = "device tree";
+ goto era_found;
+ }
+
+ /* If ccbvid has the era, use that (era 6 and onwards) */
+ caam_era = rd_reg32(&ctrlpriv->ctrl->perfmon.ccb_id);
+ caam_era = caam_era >> CCB_VID_ERA_SHIFT & CCB_VID_ERA_MASK;
+
+ if (caam_era) {
+ era_source = "CCBVID";
+ goto era_found;
+ }
+
+ /* If we can match caamvid to known versions, use that */
+ caam_id_ms = rd_reg32(&ctrlpriv->ctrl->perfmon.caam_id_ms);
+ sec_vid.ip_id = caam_id_ms >> SEC_VID_IPID_SHIFT;
+ sec_vid.maj_rev = (caam_id_ms & SEC_VID_MAJ_MASK) >> SEC_VID_MAJ_SHIFT;
+
+ for (i = 0; i < ARRAY_SIZE(caam_eras); i++)
+ if (caam_eras[i].ip_id == sec_vid.ip_id &&
+ caam_eras[i].maj_rev == sec_vid.maj_rev) {
+ caam_era = caam_eras[i].era;
+ era_source = "CAAMVID";
+ goto era_found;
+ }
+
+ ctrlpriv->era = -ENOTSUPP;
+ return;
+
+era_found:
+ ctrlpriv->era = caam_era;
+ dev_info(&ctrlpriv->pdev->dev, "ERA source: %s.\n", era_source);
+}
+
+static void handle_imx6_err005766(struct caam_drv_private *ctrlpriv)
+{
+ /*
+ * ERRATA: mx6 devices have an issue wherein AXI bus transactions
+ * may not occur in the correct order. This isn't a problem running
+ * single descriptors, but can be if running multiple concurrent
+ * descriptors. Reworking the driver to throttle to single requests
+ * is impractical, thus the workaround is to limit the AXI pipeline
+ * to a depth of 1 (from it's default of 4) to preclude this situation
+ * from occurring.
+ */
+
+ u32 mcr_val;
+
+ if (ctrlpriv->era != IMX_ERR005766_ERA)
+ return;
+
+ if (of_machine_is_compatible("fsl,imx6q") ||
+ of_machine_is_compatible("fsl,imx6dl") ||
+ of_machine_is_compatible("fsl,imx6qp")) {
+ dev_info(&ctrlpriv->pdev->dev,
+ "AXI pipeline throttling enabled.\n");
+ mcr_val = rd_reg32(&ctrlpriv->ctrl->mcr);
+ wr_reg32(&ctrlpriv->ctrl->mcr,
+ (mcr_val & ~(MCFGR_AXIPIPE_MASK)) |
+ ((1 << MCFGR_AXIPIPE_SHIFT) & MCFGR_AXIPIPE_MASK));
+ }
}
-EXPORT_SYMBOL(caam_get_era);
#ifdef CONFIG_DEBUG_FS
static int caam_debugfs_u64_get(void *data, u64 *val)
@@ -469,57 +562,63 @@ static int caam_probe(struct platform_device *pdev)
}
ctrlpriv->caam_ipg = clk;
- clk = caam_drv_identify_clk(&pdev->dev, "mem");
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- dev_err(&pdev->dev,
- "can't identify CAAM mem clk: %d\n", ret);
+ ret = clk_prepare_enable(ctrlpriv->caam_ipg);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret);
return ret;
}
- ctrlpriv->caam_mem = clk;
clk = caam_drv_identify_clk(&pdev->dev, "aclk");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
dev_err(&pdev->dev,
"can't identify CAAM aclk clk: %d\n", ret);
- return ret;
+ goto disable_clocks;
}
ctrlpriv->caam_aclk = clk;
- clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- dev_err(&pdev->dev,
- "can't identify CAAM emi_slow clk: %d\n", ret);
- return ret;
- }
- ctrlpriv->caam_emi_slow = clk;
-
- ret = clk_prepare_enable(ctrlpriv->caam_ipg);
- if (ret < 0) {
- dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret);
- return ret;
- }
-
- ret = clk_prepare_enable(ctrlpriv->caam_mem);
+ ret = clk_prepare_enable(ctrlpriv->caam_aclk);
if (ret < 0) {
- dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
+ dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n",
ret);
- goto disable_caam_ipg;
+ goto disable_clocks;
}
- ret = clk_prepare_enable(ctrlpriv->caam_aclk);
- if (ret < 0) {
- dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
- goto disable_caam_mem;
- }
+ if (!(of_find_compatible_node(NULL, NULL, "fsl,imx7d-caam"))) {
- ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
- if (ret < 0) {
- dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
- ret);
- goto disable_caam_aclk;
+ clk = caam_drv_identify_clk(&pdev->dev, "mem");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(&pdev->dev,
+ "can't identify CAAM mem clk: %d\n", ret);
+ goto disable_clocks;
+ }
+ ctrlpriv->caam_mem = clk;
+
+ ret = clk_prepare_enable(ctrlpriv->caam_mem);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
+ ret);
+ goto disable_clocks;
+ }
+
+ if (!(of_find_compatible_node(NULL, NULL, "fsl,imx6ul-caam"))) {
+ clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(&pdev->dev,
+ "can't identify CAAM emi_slow clk: %d\n", ret);
+ goto disable_clocks;
+ }
+ ctrlpriv->caam_emi_slow = clk;
+
+ ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
+ ret);
+ goto disable_clocks;
+ }
+ }
}
/* Get configuration properties from device tree */
@@ -528,7 +627,7 @@ static int caam_probe(struct platform_device *pdev)
if (ctrl == NULL) {
dev_err(dev, "caam: of_iomap() failed\n");
ret = -ENOMEM;
- goto disable_caam_emi_slow;
+ goto disable_clocks;
}
caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) &
@@ -556,8 +655,15 @@ static int caam_probe(struct platform_device *pdev)
BLOCK_OFFSET * DECO_BLOCK_NUMBER
);
- /* Get the IRQ of the controller (for security violations only) */
- ctrlpriv->secvio_irq = irq_of_parse_and_map(nprop, 0);
+ detect_era(ctrlpriv);
+
+ /* Get CAAM-SM node and of_iomap() and save */
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm");
+ if (!np)
+ return -ENODEV;
+
+ ctrlpriv->sm_base = of_iomap(np, 0);
+ ctrlpriv->sm_size = 0x3fff;
/*
* Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel,
@@ -568,6 +674,8 @@ static int caam_probe(struct platform_device *pdev)
MCFGR_WDENABLE | MCFGR_LARGE_BURST |
(sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
+ handle_imx6_err005766(ctrlpriv);
+
/*
* Read the Compile Time paramters and SCFGR to determine
* if Virtualization is enabled for this platform
@@ -594,6 +702,7 @@ static int caam_probe(struct platform_device *pdev)
JRSTART_JR1_START | JRSTART_JR2_START |
JRSTART_JR3_START);
+ /* Set DMA masks according to platform ranging */
if (sizeof(dma_addr_t) == sizeof(u64))
if (of_device_is_compatible(nprop, "fsl,sec-v5.0"))
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
@@ -732,9 +841,9 @@ static int caam_probe(struct platform_device *pdev)
caam_id = (u64)rd_reg32(&ctrl->perfmon.caam_id_ms) << 32 |
(u64)rd_reg32(&ctrl->perfmon.caam_id_ls);
- /* Report "alive" for developer to see */
dev_info(dev, "device ID = 0x%016llx (Era %d)\n", caam_id,
- caam_get_era());
+ ctrlpriv->era);
+
dev_info(dev, "job rings = %d, qi = %d\n",
ctrlpriv->total_jobrs, ctrlpriv->qi_present);
@@ -837,13 +946,10 @@ caam_remove:
iounmap_ctrl:
iounmap(ctrl);
-disable_caam_emi_slow:
+disable_clocks:
clk_disable_unprepare(ctrlpriv->caam_emi_slow);
-disable_caam_aclk:
clk_disable_unprepare(ctrlpriv->caam_aclk);
-disable_caam_mem:
clk_disable_unprepare(ctrlpriv->caam_mem);
-disable_caam_ipg:
clk_disable_unprepare(ctrlpriv->caam_ipg);
return ret;
}
diff --git a/drivers/crypto/caam/ctrl.h b/drivers/crypto/caam/ctrl.h
index cac5402a46eb..d52e8830d409 100644
--- a/drivers/crypto/caam/ctrl.h
+++ b/drivers/crypto/caam/ctrl.h
@@ -1,13 +1,12 @@
/*
* CAAM control-plane driver backend public-level include definitions
*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
*/
#ifndef CTRL_H
#define CTRL_H
/* Prototypes for backend-level services exposed to APIs */
-int caam_get_era(void);
#endif /* CTRL_H */
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 513b6646bb36..62474d9c2f72 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -2,7 +2,7 @@
* CAAM descriptor composition header
* Definitions to support CAAM descriptor instruction generation
*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2015 Freescale Semiconductor, Inc.
*/
#ifndef DESC_H
@@ -400,7 +400,10 @@ struct sec4_sg_entry {
#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_AF_SBOX_JKEK (0x10 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_AF_SBOX_CCM_JKEK (0x10 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_AF_SBOX_CCM_TKEK (0x11 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_CCM_JKEK (0x14 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_CCM_TKEK (0x15 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_AF_SBOX_TKEK (0x21 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT)
@@ -1104,6 +1107,23 @@ struct sec4_sg_entry {
#define OP_PCL_PKPROT_ECC 0x0002
#define OP_PCL_PKPROT_F2M 0x0001
+/* Blob protocol protinfo bits */
+#define OP_PCL_BLOB_TK 0x0200
+#define OP_PCL_BLOB_EKT 0x0100
+
+#define OP_PCL_BLOB_K2KR_MEM 0x0000
+#define OP_PCL_BLOB_K2KR_C1KR 0x0010
+#define OP_PCL_BLOB_K2KR_C2KR 0x0030
+#define OP_PCL_BLOB_K2KR_AFHAS 0x0050
+#define OP_PCL_BLOB_K2KR_C2KR_SPLIT 0x0070
+
+#define OP_PCL_BLOB_PTXT_SECMEM 0x0008
+#define OP_PCL_BLOB_BLACK 0x0004
+
+#define OP_PCL_BLOB_FMT_NORMAL 0x0000
+#define OP_PCL_BLOB_FMT_MSTR 0x0002
+#define OP_PCL_BLOB_FMT_TEST 0x0003
+
/* For non-protocol/alg-only op commands */
#define OP_ALG_TYPE_SHIFT 24
#define OP_ALG_TYPE_MASK (0x7 << OP_ALG_TYPE_SHIFT)
@@ -1629,4 +1649,12 @@ struct sec4_sg_entry {
/* Frame Descriptor Command for Replacement Job Descriptor */
#define FD_CMD_REPLACE_JOB_DESC 0x20000000
+#define ARC4_BLOCK_SIZE 1
+#define ARC4_MAX_KEY_SIZE 256
+#define ARC4_MIN_KEY_SIZE 1
+
+#define XCBC_MAC_DIGEST_SIZE 16
+#define XCBC_MAC_BLOCK_WORDS 16
+
+
#endif /* DESC_H */
diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c
index 33e41ea83fcc..918061db4134 100644
--- a/drivers/crypto/caam/error.c
+++ b/drivers/crypto/caam/error.c
@@ -117,6 +117,20 @@ static const char * const rng_err_id_list[] = {
"Secure key generation",
};
+#define SPRINTFCAT(str, format, param, max_alloc) \
+{ \
+ char *tmp; \
+ \
+ tmp = kmalloc(sizeof(format) + max_alloc, GFP_ATOMIC); \
+ if (likely(tmp)) { \
+ sprintf(tmp, format, param); \
+ strcat(str, tmp); \
+ kfree(tmp); \
+ } else { \
+ strcat(str, "kmalloc failure in SPRINTFCAT"); \
+ } \
+}
+
static void report_ccb_status(struct device *jrdev, const u32 status,
const char *error)
{
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index e2bcacc1a921..785876439b9b 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -66,15 +66,25 @@ struct caam_drv_private_jr {
struct caam_drv_private {
struct device *dev;
+ struct device *smdev;
struct platform_device **jrpdev; /* Alloc'ed array per sub-device */
struct platform_device *pdev;
+ /*
+ * ERA of the CAAM block,
+ * -ENOTSUPP if no era version was supplied or detected.
+ */
+#define IMX_ERR005766_ERA 4 /* ERA affected by i.mx AXI errata */
+ int era;
+
/* Physical-presence section */
struct caam_ctrl __iomem *ctrl; /* controller region */
struct caam_deco __iomem *deco; /* DECO/CCB views */
struct caam_assurance __iomem *assure;
struct caam_queue_if __iomem *qi; /* QI control region */
struct caam_job_ring __iomem *jr[4]; /* JobR's register space */
+ dma_addr_t __iomem *sm_base; /* Secure memory storage base */
+ u32 sm_size;
/*
* Detected geometry block. Filled in from device tree if powerpc,
@@ -82,7 +92,6 @@ struct caam_drv_private {
*/
u8 total_jobrs; /* Total Job Rings in device */
u8 qi_present; /* Nonzero if QI present in device */
- int secvio_irq; /* Security violation interrupt number */
int virt_en; /* Virtualization enabled in CAAM */
#define RNG4_MAX_HANDLES 2
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 9e7f28122bb7..0a88728a1bd9 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -2,7 +2,7 @@
* CAAM/SEC 4.x transport/backend driver
* JobR backend functionality
*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2015 Freescale Semiconductor, Inc.
*/
#include <linux/of_irq.h>
@@ -296,8 +296,7 @@ EXPORT_SYMBOL(caam_jr_free);
* caam_jr_enqueue() - Enqueue a job descriptor head. Returns 0 if OK,
* -EBUSY if the queue is full, -EIO if it cannot map the caller's
* descriptor.
- * @dev: device of the job ring to be used. This device should have
- * been assigned prior by caam_jr_register().
+ * @dev: device of the job ring to be used.
* @desc: points to a job descriptor that execute our request. All
* descriptors (and all referenced data) must be in a DMAable
* region, and all data references must be physical addresses
@@ -508,6 +507,10 @@ static int caam_jr_probe(struct platform_device *pdev)
/* Identify the interrupt */
jrpriv->irq = irq_of_parse_and_map(nprop, 0);
+ if (jrpriv->irq <= 0) {
+ kfree(jrpriv);
+ return -EINVAL;
+ }
/* Now do the platform independent part */
error = caam_jr_init(jrdev); /* now turn on hardware */
@@ -515,7 +518,7 @@ static int caam_jr_probe(struct platform_device *pdev)
irq_dispose_mapping(jrpriv->irq);
iounmap(ctrl);
return error;
- }
+ }
jrpriv->dev = jrdev;
spin_lock(&driver_data.jr_alloc_lock);
@@ -524,9 +527,39 @@ static int caam_jr_probe(struct platform_device *pdev)
atomic_set(&jrpriv->tfm_count, 0);
+ device_init_wakeup(&pdev->dev, 1);
+ device_set_wakeup_enable(&pdev->dev, false);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int caam_jr_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(jrpriv->irq);
+
+ return 0;
+}
+
+static int caam_jr_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(&pdev->dev))
+ disable_irq_wake(jrpriv->irq);
+
return 0;
}
+static SIMPLE_DEV_PM_OPS(caam_jr_pm_ops, caam_jr_suspend,
+ caam_jr_resume);
+#endif
+
static struct of_device_id caam_jr_match[] = {
{
.compatible = "fsl,sec-v4.0-job-ring",
@@ -542,6 +575,9 @@ static struct platform_driver caam_jr_driver = {
.driver = {
.name = "caam_jr",
.of_match_table = caam_jr_match,
+#ifdef CONFIG_PM
+ .pm = &caam_jr_pm_ops,
+#endif
},
.probe = caam_jr_probe,
.remove = caam_jr_remove,
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 84d2f838a063..0565a07e3fd4 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -271,12 +271,26 @@ struct jr_outentry {
#define CHA_ID_MS_JR_SHIFT 28
#define CHA_ID_MS_JR_MASK (0xfull << CHA_ID_MS_JR_SHIFT)
+/*
+ * caam_perfmon - Performance Monitor/Secure Memory Status/
+ * CAAM Global Status/Component Version IDs
+ *
+ * Spans f00-fff wherever instantiated
+ */
+
struct sec_vid {
u16 ip_id;
u8 maj_rev;
u8 min_rev;
};
+#define SEC_VID_IPID_SHIFT 16
+#define SEC_VID_MAJ_SHIFT 8
+#define SEC_VID_MAJ_MASK 0x0000FF00
+
+#define CCB_VID_ERA_SHIFT 24
+#define CCB_VID_ERA_MASK 0x000000FF
+
struct caam_perfmon {
/* Performance Monitor Registers f00-f9f */
u64 req_dequeued; /* PC_REQ_DEQ - Dequeued Requests */
@@ -299,17 +313,22 @@ struct caam_perfmon {
#define CTPR_MS_PG_SZ_SHIFT 4
u32 comp_parms_ms; /* CTPR - Compile Parameters Register */
u32 comp_parms_ls; /* CTPR - Compile Parameters Register */
- u64 rsvd1[2];
+ /* Secure Memory State Visibility */
+ u32 rsvd1;
+ u32 smstatus; /* Secure memory status */
+ u32 rsvd2;
+ u32 smpartown; /* Secure memory partition owner */
/* CAAM Global Status fc0-fdf */
u64 faultaddr; /* FAR - Fault Address */
u32 faultliodn; /* FALR - Fault Address LIODN */
u32 faultdetail; /* FADR - Fault Addr Detail */
- u32 rsvd2;
#define CSTA_PLEND BIT(10)
#define CSTA_ALT_PLEND BIT(18)
+ u32 rsvd3;
u32 status; /* CSTA - CAAM Status */
- u64 rsvd3;
+ u32 smpart; /* Secure Memory Partition Parameters */
+ u32 smvid; /* Secure Memory Version ID */
/* Component Instantiation Parameters fe0-fff */
u32 rtic_id; /* RVID - RTIC Version ID */
@@ -322,6 +341,62 @@ struct caam_perfmon {
u32 caam_id_ls; /* CAAMVID - CAAM Version ID LS */
};
+#define SMSTATUS_PART_SHIFT 28
+#define SMSTATUS_PART_MASK (0xf << SMSTATUS_PART_SHIFT)
+#define SMSTATUS_PAGE_SHIFT 16
+#define SMSTATUS_PAGE_MASK (0x7ff << SMSTATUS_PAGE_SHIFT)
+#define SMSTATUS_MID_SHIFT 8
+#define SMSTATUS_MID_MASK (0x3f << SMSTATUS_MID_SHIFT)
+#define SMSTATUS_ACCERR_SHIFT 4
+#define SMSTATUS_ACCERR_MASK (0xf << SMSTATUS_ACCERR_SHIFT)
+#define SMSTATUS_ACCERR_NONE 0
+#define SMSTATUS_ACCERR_ALLOC 1 /* Page not allocated */
+#define SMSTATUS_ACCESS_ID 2 /* Not granted by ID */
+#define SMSTATUS_ACCESS_WRITE 3 /* Writes not allowed */
+#define SMSTATUS_ACCESS_READ 4 /* Reads not allowed */
+#define SMSTATUS_ACCESS_NONKEY 6 /* Non-key reads not allowed */
+#define SMSTATUS_ACCESS_BLOB 9 /* Blob access not allowed */
+#define SMSTATUS_ACCESS_DESCB 10 /* Descriptor Blob access spans pages */
+#define SMSTATUS_ACCESS_NON_SM 11 /* Outside Secure Memory range */
+#define SMSTATUS_ACCESS_XPAGE 12 /* Access crosses pages */
+#define SMSTATUS_ACCESS_INITPG 13 /* Page still initializing */
+#define SMSTATUS_STATE_SHIFT 0
+#define SMSTATUS_STATE_MASK (0xf << SMSTATUS_STATE_SHIFT)
+#define SMSTATUS_STATE_RESET 0
+#define SMSTATUS_STATE_INIT 1
+#define SMSTATUS_STATE_NORMAL 2
+#define SMSTATUS_STATE_FAIL 3
+
+/* up to 15 rings, 2 bits shifted by ring number */
+#define SMPARTOWN_RING_SHIFT 2
+#define SMPARTOWN_RING_MASK 3
+#define SMPARTOWN_AVAILABLE 0
+#define SMPARTOWN_NOEXIST 1
+#define SMPARTOWN_UNAVAILABLE 2
+#define SMPARTOWN_OURS 3
+
+/* Maximum number of pages possible */
+#define SMPART_MAX_NUMPG_SHIFT 16
+#define SMPART_MAX_NUMPG_MASK (0x3f << SMPART_MAX_NUMPG_SHIFT)
+
+/* Maximum partition number */
+#define SMPART_MAX_PNUM_SHIFT 12
+#define SMPART_MAX_PNUM_MASK (0xf << SMPART_MAX_PNUM_SHIFT)
+
+/* Highest possible page number */
+#define SMPART_MAX_PG_SHIFT 0
+#define SMPART_MAX_PG_MASK (0x3f << SMPART_MAX_PG_SHIFT)
+
+/* Max size of a page */
+#define SMVID_PG_SIZE_SHIFT 16
+#define SMVID_PG_SIZE_MASK (0x7 << SMVID_PG_SIZE_SHIFT)
+
+/* Major/Minor Version ID */
+#define SMVID_MAJ_VERS_SHIFT 8
+#define SMVID_MAJ_VERS (0xf << SMVID_MAJ_VERS_SHIFT)
+#define SMVID_MIN_VERS_SHIFT 0
+#define SMVID_MIN_VERS (0xf << SMVID_MIN_VERS_SHIFT)
+
/* LIODN programming for DMA configuration */
#define MSTRID_LOCK_LIODN 0x80000000
#define MSTRID_LOCK_MAKETRUSTED 0x00010000 /* only for JR masterid */
@@ -523,6 +598,35 @@ struct caam_ctrl {
#define JRSTART_JR2_START 0x00000004 /* Start Job ring 2 */
#define JRSTART_JR3_START 0x00000008 /* Start Job ring 3 */
+/* Secure Memory Configuration - if you have it */
+/* Secure Memory Register Offset from JR Base Reg*/
+#define SM_V1_OFFSET 0x0f4
+#define SM_V2_OFFSET 0xa00
+
+/* Minimum SM Version ID requiring v2 SM register mapping */
+#define SMVID_V2 0x20105
+
+struct caam_secure_mem_v1 {
+ u32 sm_cmd; /* SMCJRx - Secure memory command */
+ u32 rsvd1;
+ u32 sm_status; /* SMCSJRx - Secure memory status */
+ u32 rsvd2;
+
+ u32 sm_perm; /* SMAPJRx - Secure memory access perms */
+ u32 sm_group2; /* SMAP2JRx - Secure memory access group 2 */
+ u32 sm_group1; /* SMAP1JRx - Secure memory access group 1 */
+};
+
+struct caam_secure_mem_v2 {
+ u32 sm_perm; /* SMAPJRx - Secure memory access perms */
+ u32 sm_group2; /* SMAP2JRx - Secure memory access group 2 */
+ u32 sm_group1; /* SMAP1JRx - Secure memory access group 1 */
+ u32 rsvd1[118];
+ u32 sm_cmd; /* SMCJRx - Secure memory command */
+ u32 rsvd2;
+ u32 sm_status; /* SMCSJRx - Secure memory status */
+};
+
/*
* caam_job_ring - direct job ring setup
* 1-4 possible per instantiation, base + 1000/2000/3000/4000
@@ -564,8 +668,7 @@ struct caam_job_ring {
/* Command/control */
u32 rsvd11;
u32 jrcommand; /* JRCRx - JobR command */
-
- u32 rsvd12[932];
+ u32 rsvd12[931];
/* Performance Monitor f00-fff */
struct caam_perfmon perfmon;
@@ -688,6 +791,62 @@ struct caam_job_ring {
#define JRCR_RESET 0x01
+/* secure memory command */
+#define SMC_PAGE_SHIFT 16
+#define SMC_PAGE_MASK (0xffff << SMC_PAGE_SHIFT)
+#define SMC_PART_SHIFT 8
+#define SMC_PART_MASK (0x0f << SMC_PART_SHIFT)
+#define SMC_CMD_SHIFT 0
+#define SMC_CMD_MASK (0x0f << SMC_CMD_SHIFT)
+
+#define SMC_CMD_ALLOC_PAGE 0x01 /* allocate page to this partition */
+#define SMC_CMD_DEALLOC_PAGE 0x02 /* deallocate page from partition */
+#define SMC_CMD_DEALLOC_PART 0x03 /* deallocate partition */
+#define SMC_CMD_PAGE_INQUIRY 0x05 /* find partition associate with page */
+
+/* secure memory (command) status */
+#define SMCS_PAGE_SHIFT 16
+#define SMCS_PAGE_MASK (0x0fff << SMCS_PAGE_SHIFT)
+#define SMCS_CMDERR_SHIFT 14
+#define SMCS_CMDERR_MASK (3 << SMCS_CMDERR_SHIFT)
+#define SMCS_ALCERR_SHIFT 12
+#define SMCS_ALCERR_MASK (3 << SMCS_ALCERR_SHIFT)
+#define SMCS_PGOWN_SHIFT 6
+#define SMCS_PGWON_MASK (3 << SMCS_PGOWN_SHIFT)
+#define SMCS_PART_SHIFT 0
+#define SMCS_PART_MASK (0xf << SMCS_PART_SHIFT)
+
+#define SMCS_CMDERR_NONE 0
+#define SMCS_CMDERR_INCOMP 1 /* Command not yet complete */
+#define SMCS_CMDERR_SECFAIL 2 /* Security failure occurred */
+#define SMCS_CMDERR_OVERFLOW 3 /* Command overflow */
+
+#define SMCS_ALCERR_NONE 0
+#define SMCS_ALCERR_PSPERR 1 /* Partion marked PSP (dealloc only) */
+#define SMCS_ALCERR_PAGEAVAIL 2 /* Page not available */
+#define SMCS_ALCERR_PARTOWN 3 /* Partition ownership error */
+
+#define SMCS_PGOWN_AVAIL 0 /* Page is available */
+#define SMCS_PGOWN_NOEXIST 1 /* Page initializing or nonexistent */
+#define SMCS_PGOWN_NOOWN 2 /* Page owned by another processor */
+#define SMCS_PGOWN_OWNED 3 /* Page belongs to this processor */
+
+/* secure memory access permissions */
+#define SMCS_PERM_KEYMOD_SHIFT 16
+#define SMCA_PERM_KEYMOD_MASK (0xff << SMCS_PERM_KEYMOD_SHIFT)
+#define SMCA_PERM_CSP_ZERO 0x8000 /* Zero when deallocated or released */
+#define SMCA_PERM_PSP_LOCK 0x4000 /* Part./pages can't be deallocated */
+#define SMCA_PERM_PERM_LOCK 0x2000 /* Lock permissions */
+#define SMCA_PERM_GRP_LOCK 0x1000 /* Lock access groups */
+#define SMCA_PERM_RINGID_SHIFT 10
+#define SMCA_PERM_RINGID_MASK (3 << SMCA_PERM_RINGID_SHIFT)
+#define SMCA_PERM_G2_BLOB 0x0080 /* Group 2 blob import/export */
+#define SMCA_PERM_G2_WRITE 0x0020 /* Group 2 write */
+#define SMCA_PERM_G2_READ 0x0010 /* Group 2 read */
+#define SMCA_PERM_G1_BLOB 0x0008 /* Group 1... */
+#define SMCA_PERM_G1_WRITE 0x0002
+#define SMCA_PERM_G1_READ 0x0001
+
/*
* caam_assurance - Assurance Controller View
* base + 0x6000 padded out to 0x1000
diff --git a/drivers/crypto/caam/secvio.c b/drivers/crypto/caam/secvio.c
new file mode 100644
index 000000000000..4bbebb9d341d
--- /dev/null
+++ b/drivers/crypto/caam/secvio.c
@@ -0,0 +1,332 @@
+
+/*
+ * SNVS Security Violation Handler
+ * Copyright (C) 2012-2016 Freescale Semiconductor, Inc., All Rights Reserved
+ */
+
+#include "compat.h"
+#include "intern.h"
+#include "secvio.h"
+#include "regs.h"
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+/*
+ * These names are associated with each violation handler.
+ * The source names were taken from MX6, and are based on recommendations
+ * for most common SoCs.
+ */
+static const u8 *violation_src_name[] = {
+ "CAAM Internal Security Violation",
+ "JTAG Alarm",
+ "Watchdog",
+ "(reserved)",
+ "External Boot",
+ "External Tamper Detect",
+};
+
+/* These names help describe security monitor state for the console */
+static const u8 *snvs_ssm_state_name[] = {
+ "init",
+ "hard fail",
+ "(undef:2)",
+ "soft fail",
+ "(undef:4)",
+ "(undef:5)",
+ "(undef:6)",
+ "(undef:7)",
+ "transition",
+ "check",
+ "(undef:10)",
+ "non-secure",
+ "(undef:12)",
+ "trusted",
+ "(undef:14)",
+ "secure",
+};
+
+/* Top-level security violation interrupt */
+static irqreturn_t snvs_secvio_interrupt(int irq, void *snvsdev)
+{
+ struct device *dev = snvsdev;
+ struct snvs_secvio_drv_private *svpriv = dev_get_drvdata(dev);
+
+ clk_enable(svpriv->clk);
+ /* Check the HP secvio status register */
+ svpriv->irqcause = rd_reg32(&svpriv->svregs->hp.secvio_status) &
+ HP_SECVIOST_SECVIOMASK;
+
+ if (!svpriv->irqcause) {
+ clk_disable(svpriv->clk);
+ return IRQ_NONE;
+ }
+
+ /* Now ACK cause */
+ clrsetbits_32(&svpriv->svregs->hp.secvio_status, 0, svpriv->irqcause);
+
+ /* And run deferred service */
+ preempt_disable();
+ tasklet_schedule(&svpriv->irqtask[smp_processor_id()]);
+ preempt_enable();
+
+ clk_disable(svpriv->clk);
+
+ return IRQ_HANDLED;
+}
+
+/* Deferred service handler. Tasklet arg is simply the SNVS dev */
+static void snvs_secvio_dispatch(unsigned long indev)
+{
+ struct device *dev = (struct device *)indev;
+ struct snvs_secvio_drv_private *svpriv = dev_get_drvdata(dev);
+ unsigned long flags;
+ int i;
+
+
+ /* Look through stored causes, call each handler if exists */
+ for (i = 0; i < MAX_SECVIO_SOURCES; i++)
+ if (svpriv->irqcause & (1 << i)) {
+ spin_lock_irqsave(&svpriv->svlock, flags);
+ svpriv->intsrc[i].handler(dev, i,
+ svpriv->intsrc[i].ext);
+ spin_unlock_irqrestore(&svpriv->svlock, flags);
+ };
+
+ /* Re-enable now-serviced interrupts */
+ clrsetbits_32(&svpriv->svregs->hp.secvio_intcfg, 0, svpriv->irqcause);
+}
+
+/*
+ * Default cause handler, used in lieu of an application-defined handler.
+ * All it does at this time is print a console message. It could force a halt.
+ */
+static void snvs_secvio_default(struct device *dev, u32 cause, void *ext)
+{
+ struct snvs_secvio_drv_private *svpriv = dev_get_drvdata(dev);
+
+ dev_err(dev, "Unhandled Security Violation Interrupt %d = %s\n",
+ cause, svpriv->intsrc[cause].intname);
+}
+
+/*
+ * Install an application-defined handler for a specified cause
+ * Arguments:
+ * - dev points to SNVS-owning device
+ * - cause interrupt source cause
+ * - handler application-defined handler, gets called with dev
+ * source cause, and locally-defined handler argument
+ * - cause_description points to a string to override the default cause
+ * name, this can be used as an alternate for error
+ * messages and such. If left NULL, the default
+ * description string is used.
+ * - ext pointer to any extra data needed by the handler.
+ */
+int snvs_secvio_install_handler(struct device *dev, enum secvio_cause cause,
+ void (*handler)(struct device *dev, u32 cause,
+ void *ext),
+ u8 *cause_description, void *ext)
+{
+ unsigned long flags;
+ struct snvs_secvio_drv_private *svpriv;
+
+ svpriv = dev_get_drvdata(dev);
+
+ if ((handler == NULL) || (cause > SECVIO_CAUSE_SOURCE_5))
+ return -EINVAL;
+
+ spin_lock_irqsave(&svpriv->svlock, flags);
+ svpriv->intsrc[cause].handler = handler;
+ if (cause_description != NULL)
+ svpriv->intsrc[cause].intname = cause_description;
+ if (ext != NULL)
+ svpriv->intsrc[cause].ext = ext;
+ spin_unlock_irqrestore(&svpriv->svlock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(snvs_secvio_install_handler);
+
+/*
+ * Remove an application-defined handler for a specified cause (and, by
+ * implication, restore the "default".
+ * Arguments:
+ * - dev points to SNVS-owning device
+ * - cause interrupt source cause
+ */
+int snvs_secvio_remove_handler(struct device *dev, enum secvio_cause cause)
+{
+ unsigned long flags;
+ struct snvs_secvio_drv_private *svpriv;
+
+ svpriv = dev_get_drvdata(dev);
+
+ if (cause > SECVIO_CAUSE_SOURCE_5)
+ return -EINVAL;
+
+ spin_lock_irqsave(&svpriv->svlock, flags);
+ svpriv->intsrc[cause].intname = violation_src_name[cause];
+ svpriv->intsrc[cause].handler = snvs_secvio_default;
+ svpriv->intsrc[cause].ext = NULL;
+ spin_unlock_irqrestore(&svpriv->svlock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(snvs_secvio_remove_handler);
+
+static int snvs_secvio_remove(struct platform_device *pdev)
+{
+ struct device *svdev;
+ struct snvs_secvio_drv_private *svpriv;
+ int i;
+
+ svdev = &pdev->dev;
+ svpriv = dev_get_drvdata(svdev);
+
+ clk_enable(svpriv->clk);
+ /* Set all sources to nonfatal */
+ wr_reg32(&svpriv->svregs->hp.secvio_intcfg, 0);
+
+ /* Remove tasklets and release interrupt */
+ for_each_possible_cpu(i)
+ tasklet_kill(&svpriv->irqtask[i]);
+
+ clk_disable_unprepare(svpriv->clk);
+ free_irq(svpriv->irq, svdev);
+ iounmap(svpriv->svregs);
+ kfree(svpriv);
+
+ return 0;
+}
+
+static int snvs_secvio_probe(struct platform_device *pdev)
+{
+ struct device *svdev;
+ struct snvs_secvio_drv_private *svpriv;
+ struct device_node *np, *npirq;
+ struct snvs_full __iomem *snvsregs;
+ int i, error;
+ u32 hpstate;
+ const void *jtd, *wtd, *itd, *etd;
+ u32 td_en;
+
+ svpriv = kzalloc(sizeof(struct snvs_secvio_drv_private), GFP_KERNEL);
+ if (!svpriv)
+ return -ENOMEM;
+
+ svdev = &pdev->dev;
+ dev_set_drvdata(svdev, svpriv);
+ svpriv->pdev = pdev;
+ np = pdev->dev.of_node;
+
+ npirq = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-secvio");
+ if (!npirq) {
+ dev_err(svdev, "can't identify secvio interrupt\n");
+ kfree(svpriv);
+ return -EINVAL;
+ }
+ svpriv->irq = irq_of_parse_and_map(npirq, 0);
+ if (svpriv->irq <= 0) {
+ kfree(svpriv);
+ return -EINVAL;
+ }
+
+ jtd = of_get_property(npirq, "jtag-tamper", NULL);
+ wtd = of_get_property(npirq, "watchdog-tamper", NULL);
+ itd = of_get_property(npirq, "internal-boot-tamper", NULL);
+ etd = of_get_property(npirq, "external-pin-tamper", NULL);
+ if (!jtd | !wtd | !itd | !etd ) {
+ dev_err(svdev, "can't identify tamper alarm configuration\n");
+ kfree(svpriv);
+ return -EINVAL;
+ }
+
+ /*
+ * Configure all sources according to device tree property.
+ * If the property is enabled then the source is ser as
+ * fatal violations except LP section,
+ * source #5 (typically used as an external tamper detect), and
+ * source #3 (typically unused). Whenever the transition to
+ * secure mode has occurred, these will now be "fatal" violations
+ */
+ td_en = HP_SECVIO_INTEN_SRC0;
+ if (!strcmp(jtd, "enabled"))
+ td_en |= HP_SECVIO_INTEN_SRC1;
+ if (!strcmp(wtd, "enabled"))
+ td_en |= HP_SECVIO_INTEN_SRC2;
+ if (!strcmp(itd, "enabled"))
+ td_en |= HP_SECVIO_INTEN_SRC4;
+ if (!strcmp(etd, "enabled"))
+ td_en |= HP_SECVIO_INTEN_SRC5;
+
+ snvsregs = of_iomap(np, 0);
+ if (!snvsregs) {
+ dev_err(svdev, "register mapping failed\n");
+ return -ENOMEM;
+ }
+ svpriv->svregs = (struct snvs_full __force *)snvsregs;
+
+ svpriv->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(svpriv->clk)) {
+ dev_err(&pdev->dev, "can't get snvs clock\n");
+ svpriv->clk = NULL;
+ }
+
+ /* Write the Secvio Enable Config the SVCR */
+ wr_reg32(&svpriv->svregs->hp.secvio_ctl, td_en);
+ wr_reg32(&svpriv->svregs->hp.secvio_intcfg, td_en);
+
+ /* Device data set up. Now init interrupt source descriptions */
+ for (i = 0; i < MAX_SECVIO_SOURCES; i++) {
+ svpriv->intsrc[i].intname = violation_src_name[i];
+ svpriv->intsrc[i].handler = snvs_secvio_default;
+ }
+ /* Connect main handler */
+ for_each_possible_cpu(i)
+ tasklet_init(&svpriv->irqtask[i], snvs_secvio_dispatch,
+ (unsigned long)svdev);
+
+ error = request_irq(svpriv->irq, snvs_secvio_interrupt,
+ IRQF_SHARED, "snvs-secvio", svdev);
+ if (error) {
+ dev_err(svdev, "can't connect secvio interrupt\n");
+ irq_dispose_mapping(svpriv->irq);
+ svpriv->irq = 0;
+ iounmap(svpriv->svregs);
+ kfree(svpriv);
+ return -EINVAL;
+ }
+
+ clk_prepare_enable(svpriv->clk);
+
+ hpstate = (rd_reg32(&svpriv->svregs->hp.status) &
+ HP_STATUS_SSM_ST_MASK) >> HP_STATUS_SSM_ST_SHIFT;
+ dev_info(svdev, "violation handlers armed - %s state\n",
+ snvs_ssm_state_name[hpstate]);
+
+ clk_disable(svpriv->clk);
+
+ return 0;
+}
+
+static struct of_device_id snvs_secvio_match[] = {
+ {
+ .compatible = "fsl,imx6q-caam-snvs",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, snvs_secvio_match);
+
+static struct platform_driver snvs_secvio_driver = {
+ .driver = {
+ .name = "snvs-secvio",
+ .owner = THIS_MODULE,
+ .of_match_table = snvs_secvio_match,
+ },
+ .probe = snvs_secvio_probe,
+ .remove = snvs_secvio_remove,
+};
+
+module_platform_driver(snvs_secvio_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL SNVS Security Violation Handler");
+MODULE_AUTHOR("Freescale Semiconductor - MCU");
diff --git a/drivers/crypto/caam/secvio.h b/drivers/crypto/caam/secvio.h
new file mode 100644
index 000000000000..97eb2723f19c
--- /dev/null
+++ b/drivers/crypto/caam/secvio.h
@@ -0,0 +1,67 @@
+
+/*
+ * CAAM Security Violation Handler
+ * Copyright (C) 2012-2015 Freescale Semiconductor, Inc., All Rights Reserved
+ */
+
+#ifndef SECVIO_H
+#define SECVIO_H
+
+#include "snvsregs.h"
+
+
+/*
+ * Defines the published interfaces to install/remove application-specified
+ * handlers for catching violations
+ */
+
+#define MAX_SECVIO_SOURCES 6
+
+/* these are the untranslated causes */
+enum secvio_cause {
+ SECVIO_CAUSE_SOURCE_0,
+ SECVIO_CAUSE_SOURCE_1,
+ SECVIO_CAUSE_SOURCE_2,
+ SECVIO_CAUSE_SOURCE_3,
+ SECVIO_CAUSE_SOURCE_4,
+ SECVIO_CAUSE_SOURCE_5
+};
+
+/* These are common "recommended" cause definitions for most devices */
+#define SECVIO_CAUSE_CAAM_VIOLATION SECVIO_CAUSE_SOURCE_0
+#define SECVIO_CAUSE_JTAG_ALARM SECVIO_CAUSE_SOURCE_1
+#define SECVIO_CAUSE_WATCHDOG SECVIO_CAUSE_SOURCE_2
+#define SECVIO_CAUSE_EXTERNAL_BOOT SECVIO_CAUSE_SOURCE_4
+#define SECVIO_CAUSE_TAMPER_DETECT SECVIO_CAUSE_SOURCE_5
+
+int snvs_secvio_install_handler(struct device *dev, enum secvio_cause cause,
+ void (*handler)(struct device *dev, u32 cause,
+ void *ext),
+ u8 *cause_description, void *ext);
+int snvs_secvio_remove_handler(struct device *dev, enum secvio_cause cause);
+
+/*
+ * Private data definitions for the secvio "driver"
+ */
+
+struct secvio_int_src {
+ const u8 *intname; /* Points to a descriptive name for source */
+ void *ext; /* Extended data to pass to the handler */
+ void (*handler)(struct device *dev, u32 cause, void *ext);
+};
+
+struct snvs_secvio_drv_private {
+ struct platform_device *pdev;
+ spinlock_t svlock ____cacheline_aligned;
+ struct tasklet_struct irqtask[NR_CPUS];
+ struct snvs_full __iomem *svregs; /* both HP and LP domains */
+ struct clk *clk;
+ int irq;
+ u32 irqcause; /* stashed cause of violation interrupt */
+
+ /* Registered handlers for each violation */
+ struct secvio_int_src intsrc[MAX_SECVIO_SOURCES];
+
+};
+
+#endif /* SECVIO_H */
diff --git a/drivers/crypto/caam/sm.h b/drivers/crypto/caam/sm.h
new file mode 100644
index 000000000000..65ec9d75ef56
--- /dev/null
+++ b/drivers/crypto/caam/sm.h
@@ -0,0 +1,125 @@
+
+/*
+ * CAAM Secure Memory/Keywrap API Definitions
+ * Copyright (C) 2008-2015 Freescale Semiconductor, Inc.
+ */
+
+#ifndef SM_H
+#define SM_H
+
+
+/* Storage access permissions */
+#define SM_PERM_READ 0x01
+#define SM_PERM_WRITE 0x02
+#define SM_PERM_BLOB 0x03
+
+/* Define treatment of secure memory vs. general memory blobs */
+#define SM_SECMEM 0
+#define SM_GENMEM 1
+
+/* Define treatment of red/black keys */
+#define RED_KEY 0
+#define BLACK_KEY 1
+
+/* Define key encryption/covering options */
+#define KEY_COVER_ECB 0 /* cover key in AES-ECB */
+#define KEY_COVER_CCM 1 /* cover key with AES-CCM */
+
+/*
+ * Round a key size up to an AES blocksize boundary so to allow for
+ * padding out to a full block
+ */
+#define AES_BLOCK_PAD(x) ((x % 16) ? ((x >> 4) + 1) << 4 : x)
+
+/* Define space required for BKEK + MAC tag storage in any blob */
+#define BLOB_OVERHEAD (32 + 16)
+
+/* Keystore maintenance functions */
+void sm_init_keystore(struct device *dev);
+u32 sm_detect_keystore_units(struct device *dev);
+int sm_establish_keystore(struct device *dev, u32 unit);
+void sm_release_keystore(struct device *dev, u32 unit);
+void caam_sm_shutdown(struct platform_device *pdev);
+int caam_sm_example_init(struct platform_device *pdev);
+
+/* Keystore accessor functions */
+extern int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size,
+ u32 *slot);
+extern int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot);
+extern int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot,
+ const u8 *key_data, u32 key_length);
+extern int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot,
+ u32 key_length, u8 *key_data);
+extern int sm_keystore_cover_key(struct device *dev, u32 unit, u32 slot,
+ u16 key_length, u8 keyauth);
+extern int sm_keystore_slot_export(struct device *dev, u32 unit, u32 slot,
+ u8 keycolor, u8 keyauth, u8 *outbuf,
+ u16 keylen, u8 *keymod);
+extern int sm_keystore_slot_import(struct device *dev, u32 unit, u32 slot,
+ u8 keycolor, u8 keyauth, u8 *inbuf,
+ u16 keylen, u8 *keymod);
+
+/* Prior functions from legacy API, deprecated */
+extern int sm_keystore_slot_encapsulate(struct device *dev, u32 unit,
+ u32 inslot, u32 outslot, u16 secretlen,
+ u8 *keymod, u16 keymodlen);
+extern int sm_keystore_slot_decapsulate(struct device *dev, u32 unit,
+ u32 inslot, u32 outslot, u16 secretlen,
+ u8 *keymod, u16 keymodlen);
+
+/* Data structure to hold per-slot information */
+struct keystore_data_slot_info {
+ u8 allocated; /* Track slot assignments */
+ u32 key_length; /* Size of the key */
+};
+
+/* Data structure to hold keystore information */
+struct keystore_data {
+ void *base_address; /* Virtual base of secure memory pages */
+ void *phys_address; /* Physical base of secure memory pages */
+ u32 slot_count; /* Number of slots in the keystore */
+ struct keystore_data_slot_info *slot; /* Per-slot information */
+};
+
+/* store the detected attributes of a secure memory page */
+struct sm_page_descriptor {
+ u16 phys_pagenum; /* may be discontiguous */
+ u16 own_part; /* Owning partition */
+ void *pg_base; /* Calculated virtual address */
+ void *pg_phys; /* Calculated physical address */
+ struct keystore_data *ksdata;
+};
+
+struct caam_drv_private_sm {
+ struct device *parentdev; /* this ends up as the controller */
+ struct device *smringdev; /* ring that owns this instance */
+ struct platform_device *sm_pdev; /* Secure Memory platform device */
+ spinlock_t kslock ____cacheline_aligned;
+
+ /* SM Register offset from JR base address */
+ u32 sm_reg_offset;
+
+ /* Default parameters for geometry */
+ u32 max_pages; /* maximum pages this instance can support */
+ u32 top_partition; /* highest partition number in this instance */
+ u32 top_page; /* highest page number in this instance */
+ u32 page_size; /* page size */
+ u32 slot_size; /* selected size of each storage block */
+
+ /* Partition/Page Allocation Map */
+ u32 localpages; /* Number of pages we can access */
+ struct sm_page_descriptor *pagedesc; /* Allocated per-page */
+
+ /* Installed handlers for keystore access */
+ int (*data_init)(struct device *dev, u32 unit);
+ void (*data_cleanup)(struct device *dev, u32 unit);
+ int (*slot_alloc)(struct device *dev, u32 unit, u32 size, u32 *slot);
+ int (*slot_dealloc)(struct device *dev, u32 unit, u32 slot);
+ void *(*slot_get_address)(struct device *dev, u32 unit, u32 handle);
+ void *(*slot_get_physical)(struct device *dev, u32 unit, u32 handle);
+ u32 (*slot_get_base)(struct device *dev, u32 unit, u32 handle);
+ u32 (*slot_get_offset)(struct device *dev, u32 unit, u32 handle);
+ u32 (*slot_get_slot_size)(struct device *dev, u32 unit, u32 handle);
+};
+
+#endif /* SM_H */
diff --git a/drivers/crypto/caam/sm_store.c b/drivers/crypto/caam/sm_store.c
new file mode 100644
index 000000000000..1bd921be59bc
--- /dev/null
+++ b/drivers/crypto/caam/sm_store.c
@@ -0,0 +1,1234 @@
+/*
+ * CAAM Secure Memory Storage Interface
+ * Copyright (C) 2008-2015 Freescale Semiconductor, Inc.
+ *
+ * Loosely based on the SHW Keystore API for SCC/SCC2
+ * Experimental implementation and NOT intended for upstream use. Expect
+ * this interface to be amended significantly in the future once it becomes
+ * integrated into live applications.
+ *
+ * Known issues:
+ *
+ * - Executes one instance of an secure memory "driver". This is tied to the
+ * fact that job rings can't run as standalone instances in the present
+ * configuration.
+ *
+ * - It does not expose a userspace interface. The value of a userspace
+ * interface for access to secrets is a point for further architectural
+ * discussion.
+ *
+ * - Partition/permission management is not part of this interface. It
+ * depends on some level of "knowledge" agreed upon between bootloader,
+ * provisioning applications, and OS-hosted software (which uses this
+ * driver).
+ *
+ * - No means of identifying the location or purpose of secrets managed by
+ * this interface exists; "slot location" and format of a given secret
+ * needs to be agreed upon between bootloader, provisioner, and OS-hosted
+ * application.
+ */
+
+#include "compat.h"
+#include "regs.h"
+#include "jr.h"
+#include "desc.h"
+#include "intern.h"
+#include "error.h"
+#include "sm.h"
+#include <linux/of_address.h>
+
+#define SECMEM_KEYMOD_LEN 8
+#define GENMEM_KEYMOD_LEN 16
+
+#ifdef SM_DEBUG_CONT
+void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ u32 i, *smdata;
+
+ dev_info(dev, "physical page %d content at 0x%08x\n",
+ pgdesc->phys_pagenum, pgdesc->pg_base);
+ smdata = pgdesc->pg_base;
+ for (i = 0; i < (smpriv->page_size / sizeof(u32)); i += 4)
+ dev_info(dev, "[0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ (u32)&smdata[i], smdata[i], smdata[i+1], smdata[i+2],
+ smdata[i+3]);
+}
+#endif
+
+#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */
+
+static __always_inline int sm_set_cmd_reg(struct caam_drv_private_sm *smpriv,
+ struct caam_drv_private_jr *jrpriv,
+ u32 val)
+{
+
+ if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
+ struct caam_secure_mem_v1 *sm_regs_v1;
+ sm_regs_v1 = (struct caam_secure_mem_v1 *)
+ ((void *)jrpriv->rregs + SM_V1_OFFSET);
+ wr_reg32(&sm_regs_v1->sm_cmd, val);
+
+ } else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
+ struct caam_secure_mem_v2 *sm_regs_v2;
+ sm_regs_v2 = (struct caam_secure_mem_v2 *)
+ ((void *)jrpriv->rregs + SM_V2_OFFSET);
+ wr_reg32(&sm_regs_v2->sm_cmd, val);
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static __always_inline u32 sm_get_status_reg(struct caam_drv_private_sm *smpriv,
+ struct caam_drv_private_jr *jrpriv,
+ u32 *val)
+{
+ if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
+ struct caam_secure_mem_v1 *sm_regs_v1;
+ sm_regs_v1 = (struct caam_secure_mem_v1 *)
+ ((void *)jrpriv->rregs + SM_V1_OFFSET);
+ *val = rd_reg32(&sm_regs_v1->sm_status);
+ } else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
+ struct caam_secure_mem_v2 *sm_regs_v2;
+ sm_regs_v2 = (struct caam_secure_mem_v2 *)
+ ((void *)jrpriv->rregs + SM_V2_OFFSET);
+ *val = rd_reg32(&sm_regs_v2->sm_status);
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Construct a black key conversion job descriptor
+ *
+ * This function constructs a job descriptor capable of performing
+ * a key blackening operation on a plaintext secure memory resident object.
+ *
+ * - desc pointer to a pointer to the descriptor generated by this
+ * function. Caller will be responsible to kfree() this
+ * descriptor after execution.
+ * - key physical pointer to the plaintext, which will also hold
+ * the result. Since encryption occurs in place, caller must
+ * ensure that the space is large enough to accommodate the
+ * blackened key
+ * - keysz size of the plaintext
+ * - auth if a CCM-covered key is required, use KEY_COVER_CCM, else
+ * use KEY_COVER_ECB.
+ *
+ * KEY to key1 from @key_addr LENGTH 16 BYTES;
+ * FIFO STORE from key1[ecb] TO @key_addr LENGTH 16 BYTES;
+ *
+ * Note that this variant uses the JDKEK only; it does not accommodate the
+ * trusted key encryption key at this time.
+ *
+ */
+static int blacken_key_jobdesc(u32 **desc, void *key, u16 keysz, bool auth)
+{
+ u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
+ u16 dsize, idx;
+
+ memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32));
+ idx = 1;
+
+ /* Load key to class 1 key register */
+ tmpdesc[idx++] = CMD_KEY | CLASS_1 | (keysz & KEY_LENGTH_MASK);
+ tmpdesc[idx++] = (u32)key;
+
+ /* ...and write back out via FIFO store*/
+ tmpdesc[idx] = CMD_FIFO_STORE | CLASS_1 | (keysz & KEY_LENGTH_MASK);
+
+ /* plus account for ECB/CCM option in FIFO_STORE */
+ if (auth == KEY_COVER_ECB)
+ tmpdesc[idx] |= FIFOST_TYPE_KEY_KEK;
+ else
+ tmpdesc[idx] |= FIFOST_TYPE_KEY_CCM_JKEK;
+
+ idx++;
+ tmpdesc[idx++] = (u32)key;
+
+ /* finish off the job header */
+ tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);
+ dsize = idx * sizeof(u32);
+
+ /* now allocate execution buffer and coat it with executable */
+ tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA);
+ if (tdesc == NULL)
+ return 0;
+
+ memcpy(tdesc, tmpdesc, dsize);
+ *desc = tdesc;
+
+ return dsize;
+}
+
+/*
+ * Construct a blob encapsulation job descriptor
+ *
+ * This function dynamically constructs a blob encapsulation job descriptor
+ * from the following arguments:
+ *
+ * - desc pointer to a pointer to the descriptor generated by this
+ * function. Caller will be responsible to kfree() this
+ * descriptor after execution.
+ * - keymod Physical pointer to a key modifier, which must reside in a
+ * contiguous piece of memory. Modifier will be assumed to be
+ * 8 bytes long for a blob of type SM_SECMEM, or 16 bytes long
+ * for a blob of type SM_GENMEM (see blobtype argument).
+ * - secretbuf Physical pointer to a secret, normally a black or red key,
+ * possibly residing within an accessible secure memory page,
+ * of the secret to be encapsulated to an output blob.
+ * - outbuf Physical pointer to the destination buffer to receive the
+ * encapsulated output. This buffer will need to be 48 bytes
+ * larger than the input because of the added encapsulation data.
+ * The generated descriptor will account for the increase in size,
+ * but the caller must also account for this increase in the
+ * buffer allocator.
+ * - secretsz Size of input secret, in bytes. This is limited to 65536
+ * less the size of blob overhead, since the length embeds into
+ * DECO pointer in/out instructions.
+ * - keycolor Determines if the source data is covered (black key) or
+ * plaintext (red key). RED_KEY or BLACK_KEY are defined in
+ * for this purpose.
+ * - blobtype Determine if encapsulated blob should be a secure memory
+ * blob (SM_SECMEM), with partition data embedded with key
+ * material, or a general memory blob (SM_GENMEM).
+ * - auth If BLACK_KEY source is covered via AES-CCM, specify
+ * KEY_COVER_CCM, else uses AES-ECB (KEY_COVER_ECB).
+ *
+ * Upon completion, desc points to a buffer containing a CAAM job
+ * descriptor which encapsulates data into an externally-storable blob
+ * suitable for use across power cycles.
+ *
+ * This is an example of a black key encapsulation job into a general memory
+ * blob. Notice the 16-byte key modifier in the LOAD instruction. Also note
+ * the output 48 bytes longer than the input:
+ *
+ * [00] B0800008 jobhdr: stidx=0 len=8
+ * [01] 14400010 ld: ccb2-key len=16 offs=0
+ * [02] 08144891 ptr->@0x08144891
+ * [03] F800003A seqoutptr: len=58
+ * [04] 01000000 out_ptr->@0x01000000
+ * [05] F000000A seqinptr: len=10
+ * [06] 09745090 in_ptr->@0x09745090
+ * [07] 870D0004 operation: encap blob reg=memory, black, format=normal
+ *
+ * This is an example of a red key encapsulation job for storing a red key
+ * into a secure memory blob. Note the 8 byte modifier on the 12 byte offset
+ * in the LOAD instruction; this accounts for blob permission storage:
+ *
+ * [00] B0800008 jobhdr: stidx=0 len=8
+ * [01] 14400C08 ld: ccb2-key len=8 offs=12
+ * [02] 087D0784 ptr->@0x087d0784
+ * [03] F8000050 seqoutptr: len=80
+ * [04] 09251BB2 out_ptr->@0x09251bb2
+ * [05] F0000020 seqinptr: len=32
+ * [06] 40000F31 in_ptr->@0x40000f31
+ * [07] 870D0008 operation: encap blob reg=memory, red, sec_mem,
+ * format=normal
+ *
+ * Note: this function only generates 32-bit pointers at present, and should
+ * be refactored using a scheme that allows both 32 and 64 bit addressing
+ */
+
+static int blob_encap_jobdesc(u32 **desc, dma_addr_t keymod,
+ void *secretbuf, dma_addr_t outbuf,
+ u16 secretsz, u8 keycolor, u8 blobtype, u8 auth)
+{
+ u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
+ u16 dsize, idx;
+
+ memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32));
+ idx = 1;
+
+ /*
+ * Key modifier works differently for secure/general memory blobs
+ * This accounts for the permission/protection data encapsulated
+ * within the blob if a secure memory blob is requested
+ */
+ if (blobtype == SM_SECMEM)
+ tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_KEY |
+ ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK)
+ | (8 & LDST_LEN_MASK);
+ else /* is general memory blob */
+ tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_KEY | (16 & LDST_LEN_MASK);
+
+ tmpdesc[idx++] = (u32)keymod;
+
+ /*
+ * Encapsulation output must include space for blob key encryption
+ * key and MAC tag
+ */
+ tmpdesc[idx++] = CMD_SEQ_OUT_PTR | (secretsz + BLOB_OVERHEAD);
+ tmpdesc[idx++] = (u32)outbuf;
+
+ /* Input data, should be somewhere in secure memory */
+ tmpdesc[idx++] = CMD_SEQ_IN_PTR | secretsz;
+ tmpdesc[idx++] = (u32)secretbuf;
+
+ /* Set blob encap, then color */
+ tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB;
+
+ if (blobtype == SM_SECMEM)
+ tmpdesc[idx] |= OP_PCL_BLOB_PTXT_SECMEM;
+
+ if (auth == KEY_COVER_CCM)
+ tmpdesc[idx] |= OP_PCL_BLOB_EKT;
+
+ if (keycolor == BLACK_KEY)
+ tmpdesc[idx] |= OP_PCL_BLOB_BLACK;
+
+ idx++;
+ tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);
+ dsize = idx * sizeof(u32);
+
+ tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA);
+ if (tdesc == NULL)
+ return 0;
+
+ memcpy(tdesc, tmpdesc, dsize);
+ *desc = tdesc;
+ return dsize;
+}
+
+/*
+ * Construct a blob decapsulation job descriptor
+ *
+ * This function dynamically constructs a blob decapsulation job descriptor
+ * from the following arguments:
+ *
+ * - desc pointer to a pointer to the descriptor generated by this
+ * function. Caller will be responsible to kfree() this
+ * descriptor after execution.
+ * - keymod Physical pointer to a key modifier, which must reside in a
+ * contiguous piece of memory. Modifier will be assumed to be
+ * 8 bytes long for a blob of type SM_SECMEM, or 16 bytes long
+ * for a blob of type SM_GENMEM (see blobtype argument).
+ * - blobbuf Physical pointer (into external memory) of the blob to
+ * be decapsulated. Blob must reside in a contiguous memory
+ * segment.
+ * - outbuf Physical pointer of the decapsulated output, possibly into
+ * a location within a secure memory page. Must be contiguous.
+ * - secretsz Size of encapsulated secret in bytes (not the size of the
+ * input blob).
+ * - keycolor Determines if decapsulated content is encrypted (BLACK_KEY)
+ * or left as plaintext (RED_KEY).
+ * - blobtype Determine if encapsulated blob should be a secure memory
+ * blob (SM_SECMEM), with partition data embedded with key
+ * material, or a general memory blob (SM_GENMEM).
+ * - auth If decapsulation path is specified by BLACK_KEY, then if
+ * AES-CCM is requested for key covering use KEY_COVER_CCM, else
+ * use AES-ECB (KEY_COVER_ECB).
+ *
+ * Upon completion, desc points to a buffer containing a CAAM job descriptor
+ * that decapsulates a key blob from external memory into a black (encrypted)
+ * key or red (plaintext) content.
+ *
+ * This is an example of a black key decapsulation job from a general memory
+ * blob. Notice the 16-byte key modifier in the LOAD instruction.
+ *
+ * [00] B0800008 jobhdr: stidx=0 len=8
+ * [01] 14400010 ld: ccb2-key len=16 offs=0
+ * [02] 08A63B7F ptr->@0x08a63b7f
+ * [03] F8000010 seqoutptr: len=16
+ * [04] 01000000 out_ptr->@0x01000000
+ * [05] F000003A seqinptr: len=58
+ * [06] 01000010 in_ptr->@0x01000010
+ * [07] 860D0004 operation: decap blob reg=memory, black, format=normal
+ *
+ * This is an example of a red key decapsulation job for restoring a red key
+ * from a secure memory blob. Note the 8 byte modifier on the 12 byte offset
+ * in the LOAD instruction:
+ *
+ * [00] B0800008 jobhdr: stidx=0 len=8
+ * [01] 14400C08 ld: ccb2-key len=8 offs=12
+ * [02] 01000000 ptr->@0x01000000
+ * [03] F8000020 seqoutptr: len=32
+ * [04] 400000E6 out_ptr->@0x400000e6
+ * [05] F0000050 seqinptr: len=80
+ * [06] 08F0C0EA in_ptr->@0x08f0c0ea
+ * [07] 860D0008 operation: decap blob reg=memory, red, sec_mem,
+ * format=normal
+ *
+ * Note: this function only generates 32-bit pointers at present, and should
+ * be refactored using a scheme that allows both 32 and 64 bit addressing
+ */
+
+static int blob_decap_jobdesc(u32 **desc, dma_addr_t keymod, dma_addr_t blobbuf,
+ u8 *outbuf, u16 secretsz, u8 keycolor,
+ u8 blobtype, u8 auth)
+{
+ u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
+ u16 dsize, idx;
+
+ memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32));
+ idx = 1;
+
+ /* Load key modifier */
+ if (blobtype == SM_SECMEM)
+ tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_KEY |
+ ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK)
+ | (8 & LDST_LEN_MASK);
+ else /* is general memory blob */
+ tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_KEY | (16 & LDST_LEN_MASK);
+
+ tmpdesc[idx++] = (u32)keymod;
+
+ /* Compensate BKEK + MAC tag over size of encapsulated secret */
+ tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + BLOB_OVERHEAD);
+ tmpdesc[idx++] = (u32)blobbuf;
+ tmpdesc[idx++] = CMD_SEQ_OUT_PTR | secretsz;
+ tmpdesc[idx++] = (u32)outbuf;
+
+ /* Decapsulate from secure memory partition to black blob */
+ tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB;
+
+ if (blobtype == SM_SECMEM)
+ tmpdesc[idx] |= OP_PCL_BLOB_PTXT_SECMEM;
+
+ if (auth == KEY_COVER_CCM)
+ tmpdesc[idx] |= OP_PCL_BLOB_EKT;
+
+ if (keycolor == BLACK_KEY)
+ tmpdesc[idx] |= OP_PCL_BLOB_BLACK;
+
+ idx++;
+ tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);
+ dsize = idx * sizeof(u32);
+
+ tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA);
+ if (tdesc == NULL)
+ return 0;
+
+ memcpy(tdesc, tmpdesc, dsize);
+ *desc = tdesc;
+ return dsize;
+}
+
+/*
+ * Pseudo-synchronous ring access functions for carrying out key
+ * encapsulation and decapsulation
+ */
+
+struct sm_key_job_result {
+ int error;
+ struct completion completion;
+};
+
+void sm_key_job_done(struct device *dev, u32 *desc, u32 err, void *context)
+{
+ struct sm_key_job_result *res = context;
+
+ res->error = err; /* save off the error for postprocessing */
+ complete(&res->completion); /* mark us complete */
+}
+
+static int sm_key_job(struct device *ksdev, u32 *jobdesc)
+{
+ struct sm_key_job_result testres;
+ struct caam_drv_private_sm *kspriv;
+ int rtn = 0;
+
+ kspriv = dev_get_drvdata(ksdev);
+
+ init_completion(&testres.completion);
+
+ rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, sm_key_job_done,
+ &testres);
+ if (!rtn) {
+ wait_for_completion_interruptible(&testres.completion);
+ rtn = testres.error;
+ }
+ return rtn;
+}
+
+/*
+ * Following section establishes the default methods for keystore access
+ * They are NOT intended for use external to this module
+ *
+ * In the present version, these are the only means for the higher-level
+ * interface to deal with the mechanics of accessing the phyiscal keystore
+ */
+
+
+int slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
+ u32 i;
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_alloc(): requesting slot for %d bytes\n", size);
+#endif
+
+ if (size > smpriv->slot_size)
+ return -EKEYREJECTED;
+
+ for (i = 0; i < ksdata->slot_count; i++) {
+ if (ksdata->slot[i].allocated == 0) {
+ ksdata->slot[i].allocated = 1;
+ (*slot) = i;
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_alloc(): new slot %d allocated\n",
+ *slot);
+#endif
+ return 0;
+ }
+ }
+
+ return -ENOSPC;
+}
+EXPORT_SYMBOL(slot_alloc);
+
+int slot_dealloc(struct device *dev, u32 unit, u32 slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
+ u8 __iomem *slotdata;
+
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_dealloc(): releasing slot %d\n", slot);
+#endif
+ if (slot >= ksdata->slot_count)
+ return -EINVAL;
+ slotdata = ksdata->base_address + slot * smpriv->slot_size;
+
+ if (ksdata->slot[slot].allocated == 1) {
+ /* Forcibly overwrite the data from the keystore */
+ memset(ksdata->base_address + slot * smpriv->slot_size, 0,
+ smpriv->slot_size);
+
+ ksdata->slot[slot].allocated = 0;
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_dealloc(): slot %d released\n", slot);
+#endif
+ return 0;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(slot_dealloc);
+
+void *slot_get_address(struct device *dev, u32 unit, u32 slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
+
+ if (slot >= ksdata->slot_count)
+ return NULL;
+
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_get_address(): slot %d is 0x%08x\n", slot,
+ (u32)ksdata->base_address + slot * smpriv->slot_size);
+#endif
+
+ return ksdata->base_address + slot * smpriv->slot_size;
+}
+
+void *slot_get_physical(struct device *dev, u32 unit, u32 slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
+
+ if (slot >= ksdata->slot_count)
+ return NULL;
+
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_get_physical(): slot %d is 0x%08x\n", slot,
+ (u32)ksdata->phys_address + slot * smpriv->slot_size);
+#endif
+
+ return ksdata->phys_address + slot * smpriv->slot_size;
+}
+
+u32 slot_get_base(struct device *dev, u32 unit, u32 slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
+
+ /*
+ * There could potentially be more than one secure partition object
+ * associated with this keystore. For now, there is just one.
+ */
+
+ (void)slot;
+
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_get_base(): slot %d = 0x%08x\n",
+ slot, (u32)ksdata->base_address);
+#endif
+
+ return (u32)(ksdata->base_address);
+}
+
+u32 slot_get_offset(struct device *dev, u32 unit, u32 slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
+
+ if (slot >= ksdata->slot_count)
+ return -EINVAL;
+
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_get_offset(): slot %d = %d\n", slot,
+ slot * smpriv->slot_size);
+#endif
+
+ return slot * smpriv->slot_size;
+}
+
+u32 slot_get_slot_size(struct device *dev, u32 unit, u32 slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+
+
+#ifdef SM_DEBUG
+ dev_info(dev, "slot_get_slot_size(): slot %d = %d\n", slot,
+ smpriv->slot_size);
+#endif
+ /* All slots are the same size in the default implementation */
+ return smpriv->slot_size;
+}
+
+
+
+int kso_init_data(struct device *dev, u32 unit)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ int retval = -EINVAL;
+ struct keystore_data *keystore_data = NULL;
+ u32 slot_count;
+ u32 keystore_data_size;
+
+ /*
+ * Calculate the required size of the keystore data structure, based
+ * on the number of keys that can fit in the partition.
+ */
+ slot_count = smpriv->page_size / smpriv->slot_size;
+#ifdef SM_DEBUG
+ dev_info(dev, "kso_init_data: %d slots initializing\n", slot_count);
+#endif
+
+ keystore_data_size = sizeof(struct keystore_data) +
+ slot_count *
+ sizeof(struct keystore_data_slot_info);
+
+ keystore_data = kzalloc(keystore_data_size, GFP_KERNEL);
+
+ if (keystore_data == NULL) {
+ retval = -ENOSPC;
+ goto out;
+ }
+
+#ifdef SM_DEBUG
+ dev_info(dev, "kso_init_data: keystore data size = %d\n",
+ keystore_data_size);
+#endif
+
+ /*
+ * Place the slot information structure directly after the keystore data
+ * structure.
+ */
+ keystore_data->slot = (struct keystore_data_slot_info *)
+ (keystore_data + 1);
+ keystore_data->slot_count = slot_count;
+
+ smpriv->pagedesc[unit].ksdata = keystore_data;
+ smpriv->pagedesc[unit].ksdata->base_address =
+ smpriv->pagedesc[unit].pg_base;
+ smpriv->pagedesc[unit].ksdata->phys_address =
+ smpriv->pagedesc[unit].pg_phys;
+
+ retval = 0;
+
+out:
+ if (retval != 0)
+ if (keystore_data != NULL)
+ kfree(keystore_data);
+
+
+ return retval;
+}
+
+void kso_cleanup_data(struct device *dev, u32 unit)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ struct keystore_data *keystore_data = NULL;
+
+ if (smpriv->pagedesc[unit].ksdata != NULL)
+ keystore_data = smpriv->pagedesc[unit].ksdata;
+
+ /* Release the allocated keystore management data */
+ kfree(smpriv->pagedesc[unit].ksdata);
+
+ return;
+}
+
+
+
+/*
+ * Keystore management section
+ */
+
+void sm_init_keystore(struct device *dev)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+
+ smpriv->data_init = kso_init_data;
+ smpriv->data_cleanup = kso_cleanup_data;
+ smpriv->slot_alloc = slot_alloc;
+ smpriv->slot_dealloc = slot_dealloc;
+ smpriv->slot_get_address = slot_get_address;
+ smpriv->slot_get_physical = slot_get_physical;
+ smpriv->slot_get_base = slot_get_base;
+ smpriv->slot_get_offset = slot_get_offset;
+ smpriv->slot_get_slot_size = slot_get_slot_size;
+#ifdef SM_DEBUG
+ dev_info(dev, "sm_init_keystore(): handlers installed\n");
+#endif
+}
+EXPORT_SYMBOL(sm_init_keystore);
+
+/* Return available pages/units */
+u32 sm_detect_keystore_units(struct device *dev)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+
+ return smpriv->localpages;
+}
+EXPORT_SYMBOL(sm_detect_keystore_units);
+
+/*
+ * Do any keystore specific initializations
+ */
+int sm_establish_keystore(struct device *dev, u32 unit)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+
+#ifdef SM_DEBUG
+ dev_info(dev, "sm_establish_keystore(): unit %d initializing\n", unit);
+#endif
+
+ if (smpriv->data_init == NULL)
+ return -EINVAL;
+
+ /* Call the data_init function for any user setup */
+ return smpriv->data_init(dev, unit);
+}
+EXPORT_SYMBOL(sm_establish_keystore);
+
+void sm_release_keystore(struct device *dev, u32 unit)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+
+#ifdef SM_DEBUG
+ dev_info(dev, "sm_establish_keystore(): unit %d releasing\n", unit);
+#endif
+ if ((smpriv != NULL) && (smpriv->data_cleanup != NULL))
+ smpriv->data_cleanup(dev, unit);
+
+ return;
+}
+EXPORT_SYMBOL(sm_release_keystore);
+
+/*
+ * Subsequent interfacce (sm_keystore_*) forms the accessor interfacce to
+ * the keystore
+ */
+int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ int retval = -EINVAL;
+
+ spin_lock(&smpriv->kslock);
+
+ if ((smpriv->slot_alloc == NULL) ||
+ (smpriv->pagedesc[unit].ksdata == NULL))
+ goto out;
+
+ retval = smpriv->slot_alloc(dev, unit, size, slot);
+
+out:
+ spin_unlock(&smpriv->kslock);
+ return retval;
+}
+EXPORT_SYMBOL(sm_keystore_slot_alloc);
+
+int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ int retval = -EINVAL;
+
+ spin_lock(&smpriv->kslock);
+
+ if ((smpriv->slot_alloc == NULL) ||
+ (smpriv->pagedesc[unit].ksdata == NULL))
+ goto out;
+
+ retval = smpriv->slot_dealloc(dev, unit, slot);
+out:
+ spin_unlock(&smpriv->kslock);
+ return retval;
+}
+EXPORT_SYMBOL(sm_keystore_slot_dealloc);
+
+int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot,
+ const u8 *key_data, u32 key_length)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ int retval = -EINVAL;
+ u32 slot_size;
+ u32 i;
+ u8 __iomem *slot_location;
+
+ spin_lock(&smpriv->kslock);
+
+ slot_size = smpriv->slot_get_slot_size(dev, unit, slot);
+
+ if (key_length > slot_size) {
+ retval = -EFBIG;
+ goto out;
+ }
+
+ slot_location = smpriv->slot_get_address(dev, unit, slot);
+
+ for (i = 0; i < key_length; i++)
+ slot_location[i] = key_data[i];
+
+ retval = 0;
+
+out:
+ spin_unlock(&smpriv->kslock);
+ return retval;
+}
+EXPORT_SYMBOL(sm_keystore_slot_load);
+
+int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot,
+ u32 key_length, u8 *key_data)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ int retval = -EINVAL;
+ u8 __iomem *slot_addr;
+ u32 slot_size;
+
+ spin_lock(&smpriv->kslock);
+
+ slot_addr = smpriv->slot_get_address(dev, unit, slot);
+ slot_size = smpriv->slot_get_slot_size(dev, unit, slot);
+
+ if (key_length > slot_size) {
+ retval = -EKEYREJECTED;
+ goto out;
+ }
+
+ memcpy(key_data, slot_addr, key_length);
+ retval = 0;
+
+out:
+ spin_unlock(&smpriv->kslock);
+ return retval;
+}
+EXPORT_SYMBOL(sm_keystore_slot_read);
+
+/*
+ * Blacken a clear key in a slot. Operates "in place".
+ * Limited to class 1 keys at the present time
+ */
+int sm_keystore_cover_key(struct device *dev, u32 unit, u32 slot,
+ u16 key_length, u8 keyauth)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ int retval = 0;
+ u8 __iomem *slotaddr;
+ void *slotphys;
+ u32 dsize, jstat;
+ u32 __iomem *coverdesc = NULL;
+
+ /* Get the address of the object in the slot */
+ slotaddr = (u8 *)smpriv->slot_get_address(dev, unit, slot);
+ slotphys = (u8 *)smpriv->slot_get_physical(dev, unit, slot);
+
+ dsize = blacken_key_jobdesc(&coverdesc, slotphys, key_length, keyauth);
+ if (!dsize)
+ return -ENOMEM;
+ jstat = sm_key_job(dev, coverdesc);
+ if (jstat)
+ retval = -EIO;
+
+ kfree(coverdesc);
+ return retval;
+}
+EXPORT_SYMBOL(sm_keystore_cover_key);
+
+/* Export a black/red key to a blob in external memory */
+int sm_keystore_slot_export(struct device *dev, u32 unit, u32 slot, u8 keycolor,
+ u8 keyauth, u8 *outbuf, u16 keylen, u8 *keymod)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ int retval = 0;
+ u8 __iomem *slotaddr, *lkeymod;
+ u8 __iomem *slotphys;
+ dma_addr_t keymod_dma, outbuf_dma;
+ u32 dsize, jstat;
+ u32 __iomem *encapdesc = NULL;
+
+ /* Get the base address(es) of the specified slot */
+ slotaddr = (u8 *)smpriv->slot_get_address(dev, unit, slot);
+ slotphys = smpriv->slot_get_physical(dev, unit, slot);
+
+ /* Build/map/flush the key modifier */
+ lkeymod = kmalloc(SECMEM_KEYMOD_LEN, GFP_KERNEL | GFP_DMA);
+ memcpy(lkeymod, keymod, SECMEM_KEYMOD_LEN);
+ keymod_dma = dma_map_single(dev, lkeymod, SECMEM_KEYMOD_LEN,
+ DMA_TO_DEVICE);
+ dma_sync_single_for_device(dev, keymod_dma, SECMEM_KEYMOD_LEN,
+ DMA_TO_DEVICE);
+
+ outbuf_dma = dma_map_single(dev, outbuf, keylen + BLOB_OVERHEAD,
+ DMA_FROM_DEVICE);
+
+ /* Build the encapsulation job descriptor */
+ dsize = blob_encap_jobdesc(&encapdesc, keymod_dma, slotphys, outbuf_dma,
+ keylen, keycolor, SM_SECMEM, keyauth);
+ if (!dsize) {
+ dev_err(dev, "can't alloc an encapsulation descriptor\n");
+ retval = -ENOMEM;
+ goto out;
+ }
+ jstat = sm_key_job(dev, encapdesc);
+ dma_sync_single_for_cpu(dev, outbuf_dma, keylen + BLOB_OVERHEAD,
+ DMA_FROM_DEVICE);
+ if (jstat)
+ retval = -EIO;
+
+out:
+ dma_unmap_single(dev, outbuf_dma, keylen + BLOB_OVERHEAD,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(dev, keymod_dma, SECMEM_KEYMOD_LEN, DMA_TO_DEVICE);
+ kfree(encapdesc);
+
+ return retval;
+}
+EXPORT_SYMBOL(sm_keystore_slot_export);
+
+/* Import a black/red key from a blob residing in external memory */
+int sm_keystore_slot_import(struct device *dev, u32 unit, u32 slot, u8 keycolor,
+ u8 keyauth, u8 *inbuf, u16 keylen, u8 *keymod)
+{
+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
+ int retval = 0;
+ u8 __iomem *slotaddr, *lkeymod;
+ u8 __iomem *slotphys;
+ dma_addr_t keymod_dma, inbuf_dma;
+ u32 dsize, jstat;
+ u32 __iomem *decapdesc = NULL;
+
+ /* Get the base address(es) of the specified slot */
+ slotaddr = (u8 *)smpriv->slot_get_address(dev, unit, slot);
+ slotphys = smpriv->slot_get_physical(dev, unit, slot);
+
+ /* Build/map/flush the key modifier */
+ lkeymod = kmalloc(SECMEM_KEYMOD_LEN, GFP_KERNEL | GFP_DMA);
+ memcpy(lkeymod, keymod, SECMEM_KEYMOD_LEN);
+ keymod_dma = dma_map_single(dev, lkeymod, SECMEM_KEYMOD_LEN,
+ DMA_TO_DEVICE);
+ dma_sync_single_for_device(dev, keymod_dma, SECMEM_KEYMOD_LEN,
+ DMA_TO_DEVICE);
+
+ inbuf_dma = dma_map_single(dev, inbuf, keylen + BLOB_OVERHEAD,
+ DMA_TO_DEVICE);
+ dma_sync_single_for_device(dev, inbuf_dma, keylen + BLOB_OVERHEAD,
+ DMA_TO_DEVICE);
+
+ /* Build the encapsulation job descriptor */
+ dsize = blob_decap_jobdesc(&decapdesc, keymod_dma, inbuf_dma, slotphys,
+ keylen, keycolor, SM_SECMEM, keyauth);
+ if (!dsize) {
+ dev_err(dev, "can't alloc a decapsulation descriptor\n");
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ jstat = sm_key_job(dev, decapdesc);
+
+ /*
+ * May want to expand upon error meanings a bit. Any CAAM status
+ * is reported as EIO, but we might want to look for something more
+ * meaningful for something like an ICV error on restore, otherwise
+ * the caller is left guessing.
+ */
+ if (jstat)
+ retval = -EIO;
+
+out:
+ dma_unmap_single(dev, inbuf_dma, keylen + BLOB_OVERHEAD,
+ DMA_TO_DEVICE);
+ dma_unmap_single(dev, keymod_dma, SECMEM_KEYMOD_LEN, DMA_TO_DEVICE);
+ kfree(decapdesc);
+
+ return retval;
+}
+EXPORT_SYMBOL(sm_keystore_slot_import);
+
+/*
+ * Initialization/shutdown subsystem
+ * Assumes statically-invoked startup/shutdown from the controller driver
+ * for the present time, to be reworked when a device tree becomes
+ * available. This code will not modularize in present form.
+ *
+ * Also, simply uses ring 0 for execution at the present
+ */
+
+int caam_sm_startup(struct platform_device *pdev)
+{
+ struct device *ctrldev, *smdev;
+ struct caam_drv_private *ctrlpriv;
+ struct caam_drv_private_sm *smpriv;
+ struct caam_drv_private_jr *jrpriv; /* need this for reg page */
+ struct platform_device *sm_pdev;
+ struct sm_page_descriptor *lpagedesc;
+ u32 page, pgstat, lpagect, detectedpage, smvid;
+
+ struct device_node *np;
+ ctrldev = &pdev->dev;
+ ctrlpriv = dev_get_drvdata(ctrldev);
+
+ /*
+ * If ctrlpriv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!ctrlpriv)
+ return -ENODEV;
+
+ /*
+ * Set up the private block for secure memory
+ * Only one instance is possible
+ */
+ smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL);
+ if (smpriv == NULL) {
+ dev_err(ctrldev, "can't alloc private mem for secure memory\n");
+ return -ENOMEM;
+ }
+ smpriv->parentdev = ctrldev; /* copy of parent dev is handy */
+ spin_lock_init(&smpriv->kslock);
+
+ /* Create the dev */
+#ifdef CONFIG_OF
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm");
+ if (np)
+ of_node_clear_flag(np, OF_POPULATED);
+ sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev);
+#else
+ sm_pdev = platform_device_register_data(ctrldev, "caam_sm", 0,
+ smpriv,
+ sizeof(struct caam_drv_private_sm));
+#endif
+ if (sm_pdev == NULL) {
+ kfree(smpriv);
+ return -EINVAL;
+ }
+
+ /* Save a pointer to the platform device for Secure Memory */
+ smpriv->sm_pdev = sm_pdev;
+ smdev = &sm_pdev->dev;
+ dev_set_drvdata(smdev, smpriv);
+ ctrlpriv->smdev = smdev;
+
+ /* Set the Secure Memory Register Map Version */
+ smvid = rd_reg32(&ctrlpriv->ctrl->perfmon.smvid);
+ if (smvid < SMVID_V2)
+ smpriv->sm_reg_offset = SM_V1_OFFSET;
+ else
+ smpriv->sm_reg_offset = SM_V2_OFFSET;
+
+ /*
+ * Collect configuration limit data for reference
+ * This batch comes from the partition data/vid registers in perfmon
+ */
+ smpriv->max_pages = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart)
+ & SMPART_MAX_NUMPG_MASK) >>
+ SMPART_MAX_NUMPG_SHIFT) + 1;
+ smpriv->top_partition = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart)
+ & SMPART_MAX_PNUM_MASK) >>
+ SMPART_MAX_PNUM_SHIFT) + 1;
+ smpriv->top_page = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart)
+ & SMPART_MAX_PG_MASK) >> SMPART_MAX_PG_SHIFT) + 1;
+ smpriv->page_size = 1024 << ((rd_reg32(&ctrlpriv->ctrl->perfmon.smvid)
+ & SMVID_PG_SIZE_MASK) >> SMVID_PG_SIZE_SHIFT);
+ smpriv->slot_size = 1 << CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE;
+
+#ifdef SM_DEBUG
+ dev_info(smdev, "max pages = %d, top partition = %d\n",
+ smpriv->max_pages, smpriv->top_partition);
+ dev_info(smdev, "top page = %d, page size = %d (total = %d)\n",
+ smpriv->top_page, smpriv->page_size,
+ smpriv->top_page * smpriv->page_size);
+ dev_info(smdev, "selected slot size = %d\n", smpriv->slot_size);
+#endif
+
+ /*
+ * Now probe for partitions/pages to which we have access. Note that
+ * these have likely been set up by a bootloader or platform
+ * provisioning application, so we have to assume that we "inherit"
+ * a configuration and work within the constraints of what it might be.
+ *
+ * Assume use of the zeroth ring in the present iteration (until
+ * we can divorce the controller and ring drivers, and then assign
+ * an SM instance to any ring instance).
+ */
+ smpriv->smringdev = &ctrlpriv->jrpdev[0]->dev;
+ jrpriv = dev_get_drvdata(smpriv->smringdev);
+ lpagect = 0;
+ pgstat = 0;
+ lpagedesc = kzalloc(sizeof(struct sm_page_descriptor)
+ * smpriv->max_pages, GFP_KERNEL);
+ if (lpagedesc == NULL) {
+ kfree(smpriv);
+ return -ENOMEM;
+ }
+
+ for (page = 0; page < smpriv->max_pages; page++) {
+ if (sm_set_cmd_reg(smpriv, jrpriv,
+ ((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) |
+ (SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK)))
+ return -EINVAL;
+ if (sm_get_status_reg(smpriv, jrpriv, &pgstat))
+ return -EINVAL;
+
+ if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT)
+ == SMCS_PGOWN_OWNED) { /* our page? */
+ lpagedesc[page].phys_pagenum =
+ (pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT;
+ lpagedesc[page].own_part =
+ (pgstat & SMCS_PART_SHIFT) >> SMCS_PART_MASK;
+ lpagedesc[page].pg_base = ctrlpriv->sm_base +
+ ((smpriv->page_size * page) / sizeof(u32));
+ /* FIXME: get base address from platform property... */
+ lpagedesc[page].pg_phys = (u32 *)0x00100000 +
+ ((smpriv->page_size * page) / sizeof(u32));
+ lpagect++;
+#ifdef SM_DEBUG
+ dev_info(smdev,
+ "physical page %d, owning partition = %d\n",
+ lpagedesc[page].phys_pagenum,
+ lpagedesc[page].own_part);
+#endif
+ }
+ }
+
+ smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect,
+ GFP_KERNEL);
+ if (smpriv->pagedesc == NULL) {
+ kfree(lpagedesc);
+ kfree(smpriv);
+ return -ENOMEM;
+ }
+ smpriv->localpages = lpagect;
+
+ detectedpage = 0;
+ for (page = 0; page < smpriv->max_pages; page++) {
+ if (lpagedesc[page].pg_base != NULL) { /* e.g. live entry */
+ memcpy(&smpriv->pagedesc[detectedpage],
+ &lpagedesc[page],
+ sizeof(struct sm_page_descriptor));
+#ifdef SM_DEBUG_CONT
+ sm_show_page(smdev, &smpriv->pagedesc[detectedpage]);
+#endif
+ detectedpage++;
+ }
+ }
+
+ kfree(lpagedesc);
+
+ sm_init_keystore(smdev);
+
+ return 0;
+}
+
+void caam_sm_shutdown(struct platform_device *pdev)
+{
+ struct device *ctrldev, *smdev;
+ struct caam_drv_private *priv;
+ struct caam_drv_private_sm *smpriv;
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+ smdev = priv->smdev;
+
+ /* Return if resource not initialized by startup */
+ if (smdev == NULL)
+ return;
+
+ smpriv = dev_get_drvdata(smdev);
+
+ /* Remove Secure Memory Platform Device */
+ of_device_unregister(smpriv->sm_pdev);
+
+ kfree(smpriv->pagedesc);
+ kfree(smpriv);
+}
+EXPORT_SYMBOL(caam_sm_shutdown);
+#ifdef CONFIG_OF
+static void __exit caam_sm_exit(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return;
+
+ of_node_put(dev_node);
+
+ caam_sm_shutdown(pdev);
+
+ return;
+}
+
+static int __init caam_sm_init(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+
+ /*
+ * Do of_find_compatible_node() then of_find_device_by_node()
+ * once a functional device tree is available
+ */
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return -ENODEV;
+
+ of_node_get(dev_node);
+
+ caam_sm_startup(pdev);
+
+ return 0;
+}
+
+module_init(caam_sm_init);
+module_exit(caam_sm_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL CAAM Secure Memory / Keystore");
+MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD");
+#endif
diff --git a/drivers/crypto/caam/sm_test.c b/drivers/crypto/caam/sm_test.c
new file mode 100644
index 000000000000..3c5eba4c6fbc
--- /dev/null
+++ b/drivers/crypto/caam/sm_test.c
@@ -0,0 +1,524 @@
+/*
+ * Secure Memory / Keystore Exemplification Module
+ * Copyright (C) 2012-2015 Freescale Semiconductor, Inc. All Rights Reserved
+ *
+ * This module has been overloaded as an example to show:
+ * - Secure memory subsystem initialization/shutdown
+ * - Allocation/deallocation of "slots" in a secure memory page
+ * - Loading and unloading of key material into slots
+ * - Covering of secure memory objects into "black keys" (ECB only at present)
+ * - Verification of key covering (by differentiation only)
+ * - Exportation of keys into secure memory blobs (with display of result)
+ * - Importation of keys from secure memory blobs (with display of result)
+ * - Verification of re-imported keys where possible.
+ *
+ * The module does not show the use of key objects as working key register
+ * source material at this time.
+ *
+ * This module can use a substantial amount of refactoring, which may occur
+ * after the API gets some mileage. Furthermore, expect this module to
+ * eventually disappear once the API is integrated into "real" software.
+ */
+
+#include "compat.h"
+#include "intern.h"
+#include "desc.h"
+#include "error.h"
+#include "jr.h"
+#include "sm.h"
+
+/* Fixed known pattern for a key modifier */
+static u8 skeymod[] = {
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
+};
+
+/* Fixed known pattern for a key */
+static u8 clrkey[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x0f, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static void key_display(struct device *dev, u8 *label, u16 size, u8 *key)
+{
+ unsigned i;
+
+ dev_info(dev, label);
+ for (i = 0; i < size; i += 8)
+ dev_info(dev,
+ "[%04d] %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ i, key[i], key[i + 1], key[i + 2], key[i + 3],
+ key[i + 4], key[i + 5], key[i + 6], key[i + 7]);
+}
+
+int caam_sm_example_init(struct platform_device *pdev)
+{
+ struct device *ctrldev, *ksdev;
+ struct caam_drv_private *ctrlpriv;
+ struct caam_drv_private_sm *kspriv;
+ u32 unit, units;
+ int rtnval = 0;
+ u8 clrkey8[8], clrkey16[16], clrkey24[24], clrkey32[32];
+ u8 blkkey8[AES_BLOCK_PAD(8)], blkkey16[AES_BLOCK_PAD(16)];
+ u8 blkkey24[AES_BLOCK_PAD(24)], blkkey32[AES_BLOCK_PAD(32)];
+ u8 rstkey8[AES_BLOCK_PAD(8)], rstkey16[AES_BLOCK_PAD(16)];
+ u8 rstkey24[AES_BLOCK_PAD(24)], rstkey32[AES_BLOCK_PAD(32)];
+ u8 __iomem *blob8, *blob16, *blob24, *blob32;
+ u32 keyslot8, keyslot16, keyslot24, keyslot32 = 0;
+
+ blob8 = blob16 = blob24 = blob32 = NULL;
+
+ /*
+ * 3.5.x and later revs for MX6 should be able to ditch this
+ * and detect via dts property
+ */
+ ctrldev = &pdev->dev;
+ ctrlpriv = dev_get_drvdata(ctrldev);
+
+ /*
+ * If ctrlpriv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!ctrlpriv)
+ return -ENODEV;
+
+ ksdev = ctrlpriv->smdev;
+ kspriv = dev_get_drvdata(ksdev);
+ if (kspriv == NULL)
+ return -ENODEV;
+
+ /* What keystores are available ? */
+ units = sm_detect_keystore_units(ksdev);
+ if (!units)
+ dev_err(ksdev, "blkkey_ex: no keystore units available\n");
+
+ /*
+ * MX6 bootloader stores some stuff in unit 0, so let's
+ * use 1 or above
+ */
+ if (units < 2) {
+ dev_err(ksdev, "blkkey_ex: insufficient keystore units\n");
+ return -ENODEV;
+ }
+ unit = 1;
+
+ dev_info(ksdev, "blkkey_ex: %d keystore units available\n", units);
+
+ /* Initialize/Establish Keystore */
+ sm_establish_keystore(ksdev, unit); /* Initalize store in #1 */
+
+ /*
+ * Now let's set up buffers for blobs in DMA-able memory. All are
+ * larger than need to be so that blob size can be seen.
+ */
+ blob8 = kzalloc(128, GFP_KERNEL | GFP_DMA);
+ blob16 = kzalloc(128, GFP_KERNEL | GFP_DMA);
+ blob24 = kzalloc(128, GFP_KERNEL | GFP_DMA);
+ blob32 = kzalloc(128, GFP_KERNEL | GFP_DMA);
+
+ if ((blob8 == NULL) || (blob16 == NULL) || (blob24 == NULL) ||
+ (blob32 == NULL)) {
+ rtnval = -ENOMEM;
+ dev_err(ksdev, "blkkey_ex: can't get blob buffers\n");
+ goto freemem;
+ }
+
+ /* Initialize clear keys with a known and recognizable pattern */
+ memcpy(clrkey8, clrkey, 8);
+ memcpy(clrkey16, clrkey, 16);
+ memcpy(clrkey24, clrkey, 24);
+ memcpy(clrkey32, clrkey, 32);
+
+ memset(blkkey8, 0, AES_BLOCK_PAD(8));
+ memset(blkkey16, 0, AES_BLOCK_PAD(16));
+ memset(blkkey24, 0, AES_BLOCK_PAD(24));
+ memset(blkkey32, 0, AES_BLOCK_PAD(32));
+
+ memset(rstkey8, 0, AES_BLOCK_PAD(8));
+ memset(rstkey16, 0, AES_BLOCK_PAD(16));
+ memset(rstkey24, 0, AES_BLOCK_PAD(24));
+ memset(rstkey32, 0, AES_BLOCK_PAD(32));
+
+ /*
+ * Allocate keyslots. Since we're going to blacken keys in-place,
+ * we want slots big enough to pad out to the next larger AES blocksize
+ * so pad them out.
+ */
+ if (sm_keystore_slot_alloc(ksdev, unit, AES_BLOCK_PAD(8), &keyslot8))
+ goto dealloc;
+
+ if (sm_keystore_slot_alloc(ksdev, unit, AES_BLOCK_PAD(16), &keyslot16))
+ goto dealloc;
+
+ if (sm_keystore_slot_alloc(ksdev, unit, AES_BLOCK_PAD(24), &keyslot24))
+ goto dealloc;
+
+ if (sm_keystore_slot_alloc(ksdev, unit, AES_BLOCK_PAD(32), &keyslot32))
+ goto dealloc;
+
+
+ /* Now load clear key data into the newly allocated slots */
+ if (sm_keystore_slot_load(ksdev, unit, keyslot8, clrkey8, 8))
+ goto dealloc;
+
+ if (sm_keystore_slot_load(ksdev, unit, keyslot16, clrkey16, 16))
+ goto dealloc;
+
+ if (sm_keystore_slot_load(ksdev, unit, keyslot24, clrkey24, 24))
+ goto dealloc;
+
+ if (sm_keystore_slot_load(ksdev, unit, keyslot32, clrkey32, 32))
+ goto dealloc;
+
+ /*
+ * All cleartext keys are loaded into slots (in an unprotected
+ * partition at this time)
+ *
+ * Cover keys in-place
+ */
+ if (sm_keystore_cover_key(ksdev, unit, keyslot8, 8, KEY_COVER_ECB)) {
+ dev_info(ksdev, "blkkey_ex: can't cover 64-bit key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_cover_key(ksdev, unit, keyslot16, 16, KEY_COVER_ECB)) {
+ dev_info(ksdev, "blkkey_ex: can't cover 128-bit key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_cover_key(ksdev, unit, keyslot24, 24, KEY_COVER_ECB)) {
+ dev_info(ksdev, "blkkey_ex: can't cover 192-bit key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_cover_key(ksdev, unit, keyslot32, 32, KEY_COVER_ECB)) {
+ dev_info(ksdev, "blkkey_ex: can't cover 256-bit key\n");
+ goto dealloc;
+ }
+
+ /*
+ * Keys should be covered and appear sufficiently "random"
+ * as a result of the covering (blackening) process. Assuming
+ * non-secure mode, read them back out for examination; they should
+ * appear as random data, completely differing from the clear
+ * inputs. So, this will read them back from secure memory and
+ * compare them. If they match the clear key, then the covering
+ * operation didn't occur.
+ */
+
+ if (sm_keystore_slot_read(ksdev, unit, keyslot8, AES_BLOCK_PAD(8),
+ blkkey8)) {
+ dev_info(ksdev, "blkkey_ex: can't read 64-bit black key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_read(ksdev, unit, keyslot16, AES_BLOCK_PAD(16),
+ blkkey16)) {
+ dev_info(ksdev, "blkkey_ex: can't read 128-bit black key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_read(ksdev, unit, keyslot24, AES_BLOCK_PAD(24),
+ blkkey24)) {
+ dev_info(ksdev, "blkkey_ex: can't read 192-bit black key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_read(ksdev, unit, keyslot32, AES_BLOCK_PAD(32),
+ blkkey32)) {
+ dev_info(ksdev, "blkkey_ex: can't read 256-bit black key\n");
+ goto dealloc;
+ }
+
+
+ if (!memcmp(blkkey8, clrkey8, 8)) {
+ dev_info(ksdev, "blkkey_ex: 64-bit key cover failed\n");
+ goto dealloc;
+ }
+
+ if (!memcmp(blkkey16, clrkey16, 16)) {
+ dev_info(ksdev, "blkkey_ex: 128-bit key cover failed\n");
+ goto dealloc;
+ }
+
+ if (!memcmp(blkkey24, clrkey24, 24)) {
+ dev_info(ksdev, "blkkey_ex: 192-bit key cover failed\n");
+ goto dealloc;
+ }
+
+ if (!memcmp(blkkey32, clrkey32, 32)) {
+ dev_info(ksdev, "blkkey_ex: 256-bit key cover failed\n");
+ goto dealloc;
+ }
+
+
+ key_display(ksdev, "64-bit clear key:", 8, clrkey8);
+ key_display(ksdev, "64-bit black key:", AES_BLOCK_PAD(8), blkkey8);
+
+ key_display(ksdev, "128-bit clear key:", 16, clrkey16);
+ key_display(ksdev, "128-bit black key:", AES_BLOCK_PAD(16), blkkey16);
+
+ key_display(ksdev, "192-bit clear key:", 24, clrkey24);
+ key_display(ksdev, "192-bit black key:", AES_BLOCK_PAD(24), blkkey24);
+
+ key_display(ksdev, "256-bit clear key:", 32, clrkey32);
+ key_display(ksdev, "256-bit black key:", AES_BLOCK_PAD(32), blkkey32);
+
+ /*
+ * Now encapsulate all keys as SM blobs out to external memory
+ * Blobs will appear as random-looking blocks of data different
+ * from the original source key, and 48 bytes longer than the
+ * original key, to account for the extra data encapsulated within.
+ */
+ key_display(ksdev, "64-bit unwritten blob:", 96, blob8);
+ key_display(ksdev, "128-bit unwritten blob:", 96, blob16);
+ key_display(ksdev, "196-bit unwritten blob:", 96, blob24);
+ key_display(ksdev, "256-bit unwritten blob:", 96, blob32);
+
+ if (sm_keystore_slot_export(ksdev, unit, keyslot8, BLACK_KEY,
+ KEY_COVER_ECB, blob8, 8, skeymod)) {
+ dev_info(ksdev, "blkkey_ex: can't encapsulate 64-bit key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_export(ksdev, unit, keyslot16, BLACK_KEY,
+ KEY_COVER_ECB, blob16, 16, skeymod)) {
+ dev_info(ksdev, "blkkey_ex: can't encapsulate 128-bit key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_export(ksdev, unit, keyslot24, BLACK_KEY,
+ KEY_COVER_ECB, blob24, 24, skeymod)) {
+ dev_info(ksdev, "blkkey_ex: can't encapsulate 192-bit key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_export(ksdev, unit, keyslot32, BLACK_KEY,
+ KEY_COVER_ECB, blob32, 32, skeymod)) {
+ dev_info(ksdev, "blkkey_ex: can't encapsulate 256-bit key\n");
+ goto dealloc;
+ }
+
+ key_display(ksdev, "64-bit black key in blob:", 96, blob8);
+ key_display(ksdev, "128-bit black key in blob:", 96, blob16);
+ key_display(ksdev, "192-bit black key in blob:", 96, blob24);
+ key_display(ksdev, "256-bit black key in blob:", 96, blob32);
+
+ /*
+ * Now re-import black keys from secure-memory blobs stored
+ * in general memory from the previous operation. Since we are
+ * working with black keys, and since power has not cycled, the
+ * restored black keys should match the original blackened keys
+ * (this would not be true if the blobs were save in some non-volatile
+ * store, and power was cycled between the save and restore)
+ */
+ if (sm_keystore_slot_import(ksdev, unit, keyslot8, BLACK_KEY,
+ KEY_COVER_ECB, blob8, 8, skeymod)) {
+ dev_info(ksdev, "blkkey_ex: can't decapsulate 64-bit blob\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_import(ksdev, unit, keyslot16, BLACK_KEY,
+ KEY_COVER_ECB, blob16, 16, skeymod)) {
+ dev_info(ksdev, "blkkey_ex: can't decapsulate 128-bit blob\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_import(ksdev, unit, keyslot24, BLACK_KEY,
+ KEY_COVER_ECB, blob24, 24, skeymod)) {
+ dev_info(ksdev, "blkkey_ex: can't decapsulate 196-bit blob\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_import(ksdev, unit, keyslot32, BLACK_KEY,
+ KEY_COVER_ECB, blob32, 32, skeymod)) {
+ dev_info(ksdev, "blkkey_ex: can't decapsulate 256-bit blob\n");
+ goto dealloc;
+ }
+
+
+ /*
+ * Blobs are now restored as black keys. Read those black keys back
+ * for a comparison with the original black key, they should match
+ */
+ if (sm_keystore_slot_read(ksdev, unit, keyslot8, AES_BLOCK_PAD(8),
+ rstkey8)) {
+ dev_info(ksdev,
+ "blkkey_ex: can't read restored 64-bit black key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_read(ksdev, unit, keyslot16, AES_BLOCK_PAD(16),
+ rstkey16)) {
+ dev_info(ksdev,
+ "blkkey_ex: can't read restored 128-bit black key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_read(ksdev, unit, keyslot24, AES_BLOCK_PAD(24),
+ rstkey24)) {
+ dev_info(ksdev,
+ "blkkey_ex: can't read restored 196-bit black key\n");
+ goto dealloc;
+ }
+
+ if (sm_keystore_slot_read(ksdev, unit, keyslot32, AES_BLOCK_PAD(32),
+ rstkey32)) {
+ dev_info(ksdev,
+ "blkkey_ex: can't read restored 256-bit black key\n");
+ goto dealloc;
+ }
+
+ key_display(ksdev, "restored 64-bit black key:", AES_BLOCK_PAD(8),
+ rstkey8);
+ key_display(ksdev, "restored 128-bit black key:", AES_BLOCK_PAD(16),
+ rstkey16);
+ key_display(ksdev, "restored 192-bit black key:", AES_BLOCK_PAD(24),
+ rstkey24);
+ key_display(ksdev, "restored 256-bit black key:", AES_BLOCK_PAD(32),
+ rstkey32);
+
+ /*
+ * Compare the restored black keys with the original blackened keys
+ * As long as we're operating within the same power cycle, a black key
+ * restored from a blob should match the original black key IF the
+ * key happens to be of a size that matches a multiple of the AES
+ * blocksize. Any key that is padded to fill the block size will not
+ * match, excepting a key that exceeds a block; only the first full
+ * blocks will match (assuming ECB).
+ *
+ * Therefore, compare the 16 and 32 bit keys, they should match.
+ * The 24 bit key can only match within the first 16 byte block.
+ */
+
+ if (memcmp(rstkey16, blkkey16, AES_BLOCK_PAD(16))) {
+ dev_info(ksdev, "blkkey_ex: 128-bit restored key mismatch\n");
+ rtnval--;
+ }
+
+ /* Only first AES block will match, remainder subject to padding */
+ if (memcmp(rstkey24, blkkey24, 16)) {
+ dev_info(ksdev, "blkkey_ex: 192-bit restored key mismatch\n");
+ rtnval--;
+ }
+
+ if (memcmp(rstkey32, blkkey32, AES_BLOCK_PAD(32))) {
+ dev_info(ksdev, "blkkey_ex: 256-bit restored key mismatch\n");
+ rtnval--;
+ }
+
+
+ /* Remove keys from keystore */
+dealloc:
+ sm_keystore_slot_dealloc(ksdev, unit, keyslot8);
+ sm_keystore_slot_dealloc(ksdev, unit, keyslot16);
+ sm_keystore_slot_dealloc(ksdev, unit, keyslot24);
+ sm_keystore_slot_dealloc(ksdev, unit, keyslot32);
+
+
+ /* Free resources */
+freemem:
+ kfree(blob8);
+ kfree(blob16);
+ kfree(blob24);
+ kfree(blob32);
+
+ /* Disconnect from keystore and leave */
+ sm_release_keystore(ksdev, unit);
+
+ return rtnval;
+}
+EXPORT_SYMBOL(caam_sm_example_init);
+
+void caam_sm_example_shutdown(void)
+{
+ /* unused in present version */
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+
+ /*
+ * Do of_find_compatible_node() then of_find_device_by_node()
+ * once a functional device tree is available
+ */
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return;
+
+ of_node_get(dev_node);
+
+}
+
+static int __init caam_sm_test_init(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+
+ /*
+ * Do of_find_compatible_node() then of_find_device_by_node()
+ * once a functional device tree is available
+ */
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return -ENODEV;
+
+ of_node_put(dev_node);
+
+ caam_sm_example_init(pdev);
+
+ return 0;
+}
+
+
+/* Module-based initialization needs to wait for dev tree */
+#ifdef CONFIG_OF
+module_init(caam_sm_test_init);
+module_exit(caam_sm_example_shutdown);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL CAAM Black Key Usage Example");
+MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD");
+#endif
diff --git a/drivers/crypto/caam/snvsregs.h b/drivers/crypto/caam/snvsregs.h
new file mode 100644
index 000000000000..eef6b8930db5
--- /dev/null
+++ b/drivers/crypto/caam/snvsregs.h
@@ -0,0 +1,237 @@
+/*
+ * SNVS hardware register-level view
+ *
+ * Copyright (C) 2012-2015 Freescale Semiconductor, Inc., All Rights Reserved
+ */
+
+#ifndef SNVSREGS_H
+#define SNVSREGS_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+/*
+ * SNVS High Power Domain
+ * Includes security violations, HA counter, RTC, alarm
+ */
+struct snvs_hp {
+ u32 lock; /* HPLR - HP Lock */
+ u32 cmd; /* HPCOMR - HP Command */
+ u32 ctl; /* HPCR - HP Control */
+ u32 secvio_intcfg; /* HPSICR - Security Violation Int Config */
+ u32 secvio_ctl; /* HPSVCR - Security Violation Control */
+ u32 status; /* HPSR - HP Status */
+ u32 secvio_status; /* HPSVSR - Security Violation Status */
+ u32 ha_counteriv; /* High Assurance Counter IV */
+ u32 ha_counter; /* High Assurance Counter */
+ u32 rtc_msb; /* Real Time Clock/Counter MSB */
+ u32 rtc_lsb; /* Real Time Counter LSB */
+ u32 time_alarm_msb; /* Time Alarm MSB */
+ u32 time_alarm_lsb; /* Time Alarm LSB */
+};
+
+#define HP_LOCK_HAC_LCK 0x00040000
+#define HP_LOCK_HPSICR_LCK 0x00020000
+#define HP_LOCK_HPSVCR_LCK 0x00010000
+#define HP_LOCK_MKEYSEL_LCK 0x00000200
+#define HP_LOCK_TAMPCFG_LCK 0x00000100
+#define HP_LOCK_TAMPFLT_LCK 0x00000080
+#define HP_LOCK_SECVIO_LCK 0x00000040
+#define HP_LOCK_GENP_LCK 0x00000020
+#define HP_LOCK_MONOCTR_LCK 0x00000010
+#define HP_LOCK_CALIB_LCK 0x00000008
+#define HP_LOCK_SRTC_LCK 0x00000004
+#define HP_LOCK_ZMK_RD_LCK 0x00000002
+#define HP_LOCK_ZMK_WT_LCK 0x00000001
+
+#define HP_CMD_NONPRIV_AXS 0x80000000
+#define HP_CMD_HAC_STOP 0x00080000
+#define HP_CMD_HAC_CLEAR 0x00040000
+#define HP_CMD_HAC_LOAD 0x00020000
+#define HP_CMD_HAC_CFG_EN 0x00010000
+#define HP_CMD_SNVS_MSTR_KEY 0x00002000
+#define HP_CMD_PROG_ZMK 0x00001000
+#define HP_CMD_SW_LPSV 0x00000400
+#define HP_CMD_SW_FSV 0x00000200
+#define HP_CMD_SW_SV 0x00000100
+#define HP_CMD_LP_SWR_DIS 0x00000020
+#define HP_CMD_LP_SWR 0x00000010
+#define HP_CMD_SSM_SFNS_DIS 0x00000004
+#define HP_CMD_SSM_ST_DIS 0x00000002
+#define HP_CMD_SMM_ST 0x00000001
+
+#define HP_CTL_TIME_SYNC 0x00010000
+#define HP_CTL_CAL_VAL_SHIFT 10
+#define HP_CTL_CAL_VAL_MASK (0x1f << HP_CTL_CALIB_SHIFT)
+#define HP_CTL_CALIB_EN 0x00000100
+#define HP_CTL_PI_FREQ_SHIFT 4
+#define HP_CTL_PI_FREQ_MASK (0xf << HP_CTL_PI_FREQ_SHIFT)
+#define HP_CTL_PI_EN 0x00000008
+#define HP_CTL_TIMEALARM_EN 0x00000002
+#define HP_CTL_RTC_EN 0x00000001
+
+#define HP_SECVIO_INTEN_EN 0x10000000
+#define HP_SECVIO_INTEN_SRC5 0x00000020
+#define HP_SECVIO_INTEN_SRC4 0x00000010
+#define HP_SECVIO_INTEN_SRC3 0x00000008
+#define HP_SECVIO_INTEN_SRC2 0x00000004
+#define HP_SECVIO_INTEN_SRC1 0x00000002
+#define HP_SECVIO_INTEN_SRC0 0x00000001
+#define HP_SECVIO_INTEN_ALL 0x8000003f
+
+#define HP_SECVIO_ICTL_CFG_SHIFT 30
+#define HP_SECVIO_ICTL_CFG_MASK (0x3 << HP_SECVIO_ICTL_CFG_SHIFT)
+#define HP_SECVIO_ICTL_CFG5_SHIFT 5
+#define HP_SECVIO_ICTL_CFG5_MASK (0x3 << HP_SECVIO_ICTL_CFG5_SHIFT)
+#define HP_SECVIO_ICTL_CFG_DISABLE 0
+#define HP_SECVIO_ICTL_CFG_NONFATAL 1
+#define HP_SECVIO_ICTL_CFG_FATAL 2
+#define HP_SECVIO_ICTL_CFG4_FATAL 0x00000010
+#define HP_SECVIO_ICTL_CFG3_FATAL 0x00000008
+#define HP_SECVIO_ICTL_CFG2_FATAL 0x00000004
+#define HP_SECVIO_ICTL_CFG1_FATAL 0x00000002
+#define HP_SECVIO_ICTL_CFG0_FATAL 0x00000001
+
+#define HP_STATUS_ZMK_ZERO 0x80000000
+#define HP_STATUS_OTPMK_ZERO 0x08000000
+#define HP_STATUS_OTPMK_SYN_SHIFT 16
+#define HP_STATUS_OTPMK_SYN_MASK (0x1ff << HP_STATUS_OTPMK_SYN_SHIFT)
+#define HP_STATUS_SSM_ST_SHIFT 8
+#define HP_STATUS_SSM_ST_MASK (0xf << HP_STATUS_SSM_ST_SHIFT)
+#define HP_STATUS_SSM_ST_INIT 0
+#define HP_STATUS_SSM_ST_HARDFAIL 1
+#define HP_STATUS_SSM_ST_SOFTFAIL 3
+#define HP_STATUS_SSM_ST_INITINT 8
+#define HP_STATUS_SSM_ST_CHECK 9
+#define HP_STATUS_SSM_ST_NONSECURE 11
+#define HP_STATUS_SSM_ST_TRUSTED 13
+#define HP_STATUS_SSM_ST_SECURE 15
+
+#define HP_SECVIOST_ZMK_ECC_FAIL 0x08000000 /* write to clear */
+#define HP_SECVIOST_ZMK_SYN_SHIFT 16
+#define HP_SECVIOST_ZMK_SYN_MASK (0x1ff << HP_SECVIOST_ZMK_SYN_SHIFT)
+#define HP_SECVIOST_SECVIO5 0x00000020
+#define HP_SECVIOST_SECVIO4 0x00000010
+#define HP_SECVIOST_SECVIO3 0x00000008
+#define HP_SECVIOST_SECVIO2 0x00000004
+#define HP_SECVIOST_SECVIO1 0x00000002
+#define HP_SECVIOST_SECVIO0 0x00000001
+#define HP_SECVIOST_SECVIOMASK 0x0000003f
+
+/*
+ * SNVS Low Power Domain
+ * Includes glitch detector, SRTC, alarm, monotonic counter, ZMK
+ */
+struct snvs_lp {
+ u32 lock;
+ u32 ctl;
+ u32 mstr_key_ctl; /* Master Key Control */
+ u32 secvio_ctl; /* Security Violation Control */
+ u32 tamper_filt_cfg; /* Tamper Glitch Filters Configuration */
+ u32 tamper_det_cfg; /* Tamper Detectors Configuration */
+ u32 status;
+ u32 srtc_msb; /* Secure Real Time Clock/Counter MSB */
+ u32 srtc_lsb; /* Secure Real Time Clock/Counter LSB */
+ u32 time_alarm; /* Time Alarm */
+ u32 smc_msb; /* Secure Monotonic Counter MSB */
+ u32 smc_lsb; /* Secure Monotonic Counter LSB */
+ u32 pwr_glitch_det; /* Power Glitch Detector */
+ u32 gen_purpose;
+ u32 zmk[8]; /* Zeroizable Master Key */
+};
+
+#define LP_LOCK_MKEYSEL_LCK 0x00000200
+#define LP_LOCK_TAMPDET_LCK 0x00000100
+#define LP_LOCK_TAMPFLT_LCK 0x00000080
+#define LP_LOCK_SECVIO_LCK 0x00000040
+#define LP_LOCK_GENP_LCK 0x00000020
+#define LP_LOCK_MONOCTR_LCK 0x00000010
+#define LP_LOCK_CALIB_LCK 0x00000008
+#define LP_LOCK_SRTC_LCK 0x00000004
+#define LP_LOCK_ZMK_RD_LCK 0x00000002
+#define LP_LOCK_ZMK_WT_LCK 0x00000001
+
+#define LP_CTL_CAL_VAL_SHIFT 10
+#define LP_CTL_CAL_VAL_MASK (0x1f << LP_CTL_CAL_VAL_SHIFT)
+#define LP_CTL_CALIB_EN 0x00000100
+#define LP_CTL_SRTC_INVAL_EN 0x00000010
+#define LP_CTL_WAKE_INT_EN 0x00000008
+#define LP_CTL_MONOCTR_EN 0x00000004
+#define LP_CTL_TIMEALARM_EN 0x00000002
+#define LP_CTL_SRTC_EN 0x00000001
+
+#define LP_MKEYCTL_ZMKECC_SHIFT 8
+#define LP_MKEYCTL_ZMKECC_MASK (0xff << LP_MKEYCTL_ZMKECC_SHIFT)
+#define LP_MKEYCTL_ZMKECC_EN 0x00000010
+#define LP_MKEYCTL_ZMKECC_VAL 0x00000008
+#define LP_MKEYCTL_ZMKECC_PROG 0x00000004
+#define LP_MKEYCTL_MKSEL_SHIFT 0
+#define LP_MKEYCTL_MKSEL_MASK (3 << LP_MKEYCTL_MKSEL_SHIFT)
+#define LP_MKEYCTL_MK_OTP 0
+#define LP_MKEYCTL_MK_ZMK 2
+#define LP_MKEYCTL_MK_COMB 3
+
+#define LP_SECVIO_CTL_SRC5 0x20
+#define LP_SECVIO_CTL_SRC4 0x10
+#define LP_SECVIO_CTL_SRC3 0x08
+#define LP_SECVIO_CTL_SRC2 0x04
+#define LP_SECVIO_CTL_SRC1 0x02
+#define LP_SECVIO_CTL_SRC0 0x01
+
+#define LP_TAMPFILT_EXT2_EN 0x80000000
+#define LP_TAMPFILT_EXT2_SHIFT 24
+#define LP_TAMPFILT_EXT2_MASK (0x1f << LP_TAMPFILT_EXT2_SHIFT)
+#define LP_TAMPFILT_EXT1_EN 0x00800000
+#define LP_TAMPFILT_EXT1_SHIFT 16
+#define LP_TAMPFILT_EXT1_MASK (0x1f << LP_TAMPFILT_EXT1_SHIFT)
+#define LP_TAMPFILT_WM_EN 0x00000080
+#define LP_TAMPFILT_WM_SHIFT 0
+#define LP_TAMPFILT_WM_MASK (0x1f << LP_TAMPFILT_WM_SHIFT)
+
+#define LP_TAMPDET_OSC_BPS 0x10000000
+#define LP_TAMPDET_VRC_SHIFT 24
+#define LP_TAMPDET_VRC_MASK (3 << LP_TAMPFILT_VRC_SHIFT)
+#define LP_TAMPDET_HTDC_SHIFT 20
+#define LP_TAMPDET_HTDC_MASK (3 << LP_TAMPFILT_HTDC_SHIFT)
+#define LP_TAMPDET_LTDC_SHIFT 16
+#define LP_TAMPDET_LTDC_MASK (3 << LP_TAMPFILT_LTDC_SHIFT)
+#define LP_TAMPDET_POR_OBS 0x00008000
+#define LP_TAMPDET_PFD_OBS 0x00004000
+#define LP_TAMPDET_ET2_EN 0x00000400
+#define LP_TAMPDET_ET1_EN 0x00000200
+#define LP_TAMPDET_WMT2_EN 0x00000100
+#define LP_TAMPDET_WMT1_EN 0x00000080
+#define LP_TAMPDET_VT_EN 0x00000040
+#define LP_TAMPDET_TT_EN 0x00000020
+#define LP_TAMPDET_CT_EN 0x00000010
+#define LP_TAMPDET_MCR_EN 0x00000004
+#define LP_TAMPDET_SRTCR_EN 0x00000002
+
+#define LP_STATUS_SECURE
+#define LP_STATUS_NONSECURE
+#define LP_STATUS_SCANEXIT 0x00100000 /* all write 1 clear here on */
+#define LP_STATUS_EXT_SECVIO 0x00010000
+#define LP_STATUS_ET2 0x00000400
+#define LP_STATUS_ET1 0x00000200
+#define LP_STATUS_WMT2 0x00000100
+#define LP_STATUS_WMT1 0x00000080
+#define LP_STATUS_VTD 0x00000040
+#define LP_STATUS_TTD 0x00000020
+#define LP_STATUS_CTD 0x00000010
+#define LP_STATUS_PGD 0x00000008
+#define LP_STATUS_MCR 0x00000004
+#define LP_STATUS_SRTCR 0x00000002
+#define LP_STATUS_LPTA 0x00000001
+
+/* Full SNVS register page, including version/options */
+struct snvs_full {
+ struct snvs_hp hp;
+ struct snvs_lp lp;
+ u32 rsvd[731]; /* deadspace 0x08c-0xbf7 */
+
+ /* Version / Revision / Option ID space - end of register page */
+ u32 vid; /* 0xbf8 HP Version ID (VID 1) */
+ u32 opt_rev; /* 0xbfc HP Options / Revision (VID 2) */
+};
+
+#endif /* SNVSREGS_H */
diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c
index 625ee50fd78b..093a99ce8c64 100644
--- a/drivers/crypto/mxs-dcp.c
+++ b/drivers/crypto/mxs-dcp.c
@@ -20,6 +20,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/stmp_device.h>
+#include <linux/clk.h>
#include <crypto/aes.h>
#include <crypto/sha.h>
@@ -28,9 +29,25 @@
#define DCP_MAX_CHANS 4
#define DCP_BUF_SZ PAGE_SIZE
+#define DCP_SHA_PAY_SZ 64
#define DCP_ALIGNMENT 64
+
+/*
+ * Null hashes to align with hw behavior on imx6sl and ull
+ * these are flipped for consistency with hw output
+ */
+const uint8_t sha1_null_hash[] =
+ "\x09\x07\xd8\xaf\x90\x18\x60\x95\xef\xbf"
+ "\x55\x32\x0d\x4b\x6b\x5e\xee\xa3\x39\xda";
+
+const uint8_t sha256_null_hash[] =
+ "\x55\xb8\x52\x78\x1b\x99\x95\xa4"
+ "\x4c\x93\x9b\x64\xe4\x41\xae\x27"
+ "\x24\xb9\x6f\x99\xc8\xf4\xfb\x9a"
+ "\x14\x1c\xfc\x98\x42\xc4\xb0\xe3";
+
/* DCP DMA descriptor. */
struct dcp_dma_desc {
uint32_t next_cmd_addr;
@@ -48,6 +65,7 @@ struct dcp_coherent_block {
uint8_t aes_in_buf[DCP_BUF_SZ];
uint8_t aes_out_buf[DCP_BUF_SZ];
uint8_t sha_in_buf[DCP_BUF_SZ];
+ uint8_t sha_out_buf[DCP_SHA_PAY_SZ];
uint8_t aes_key[2 * AES_KEYSIZE_128];
@@ -66,6 +84,10 @@ struct dcp {
struct mutex mutex[DCP_MAX_CHANS];
struct task_struct *thread[DCP_MAX_CHANS];
struct crypto_queue queue[DCP_MAX_CHANS];
+#ifdef CONFIG_ARM
+ struct clk *dcp_clk;
+#endif
+ int enable_sha_workaround;
};
enum dcp_chan {
@@ -99,6 +121,11 @@ struct dcp_sha_req_ctx {
unsigned int fini:1;
};
+struct dcp_export_state {
+ struct dcp_sha_req_ctx req_ctx;
+ struct dcp_async_ctx async_ctx;
+};
+
/*
* There can even be only one instance of the MXS DCP due to the
* design of Linux Crypto API.
@@ -209,6 +236,12 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
dma_addr_t dst_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_out_buf,
DCP_BUF_SZ, DMA_FROM_DEVICE);
+ if (actx->fill % AES_BLOCK_SIZE) {
+ dev_err(sdcp->dev, "Invalid block size!\n");
+ ret = -EINVAL;
+ goto aes_done_run;
+ }
+
/* Fill in the DMA descriptor. */
desc->control0 = MXS_DCP_CONTROL0_DECR_SEMAPHORE |
MXS_DCP_CONTROL0_INTERRUPT |
@@ -238,6 +271,7 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
ret = mxs_dcp_start_dma(actx);
+aes_done_run:
dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128,
DMA_TO_DEVICE);
dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
@@ -264,13 +298,15 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
uint8_t *out_tmp, *src_buf, *dst_buf = NULL;
uint32_t dst_off = 0;
+ uint32_t last_out_len = 0;
uint8_t *key = sdcp->coh->aes_key;
int ret = 0;
int split = 0;
- unsigned int i, len, clen, rem = 0;
+ unsigned int i, len, clen, rem = 0, tlen = 0;
int init = 0;
+ bool limit_hit = false;
actx->fill = 0;
@@ -289,6 +325,11 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
for_each_sg(req->src, src, nents, i) {
src_buf = sg_virt(src);
len = sg_dma_len(src);
+ tlen += len;
+ limit_hit = tlen > req->nbytes;
+
+ if (limit_hit)
+ len = req->nbytes - (tlen - len);
do {
if (actx->fill + len > out_off)
@@ -305,13 +346,15 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
* If we filled the buffer or this is the last SG,
* submit the buffer.
*/
- if (actx->fill == out_off || sg_is_last(src)) {
+ if (actx->fill == out_off || sg_is_last(src) ||
+ limit_hit) {
ret = mxs_dcp_run_aes(actx, req, init);
if (ret)
return ret;
init = 0;
out_tmp = out_buf;
+ last_out_len = actx->fill;
while (dst && actx->fill) {
if (!split) {
dst_buf = sg_virt(dst);
@@ -334,6 +377,13 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
}
}
} while (len);
+
+ if (limit_hit)
+ break;
+ }
+ if (last_out_len >= AES_BLOCK_SIZE) {
+ memcpy(req->info, out_buf+(last_out_len-AES_BLOCK_SIZE),
+ AES_BLOCK_SIZE);
}
return ret;
@@ -509,8 +559,6 @@ static int mxs_dcp_run_sha(struct ahash_request *req)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
- struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
-
struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
dma_addr_t digest_phys = 0;
@@ -532,10 +580,24 @@ static int mxs_dcp_run_sha(struct ahash_request *req)
desc->payload = 0;
desc->status = 0;
+ /*
+ * Align driver with hw behavior when generating null hashes
+ */
+ if (rctx->init && rctx->fini && desc->size == 0 &&
+ sdcp->enable_sha_workaround) {
+ struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
+ const uint8_t *sha_buf =
+ (actx->alg == MXS_DCP_CONTROL1_HASH_SELECT_SHA1) ?
+ sha1_null_hash : sha256_null_hash;
+ memcpy(sdcp->coh->sha_out_buf, sha_buf, halg->digestsize);
+ ret = 0;
+ goto done_run;
+ }
+
/* Set HASH_TERM bit for last transfer block. */
if (rctx->fini) {
- digest_phys = dma_map_single(sdcp->dev, req->result,
- halg->digestsize, DMA_FROM_DEVICE);
+ digest_phys = dma_map_single(sdcp->dev, sdcp->coh->sha_out_buf,
+ DCP_SHA_PAY_SZ, DMA_FROM_DEVICE);
desc->control0 |= MXS_DCP_CONTROL0_HASH_TERM;
desc->payload = digest_phys;
}
@@ -543,9 +605,10 @@ static int mxs_dcp_run_sha(struct ahash_request *req)
ret = mxs_dcp_start_dma(actx);
if (rctx->fini)
- dma_unmap_single(sdcp->dev, digest_phys, halg->digestsize,
+ dma_unmap_single(sdcp->dev, digest_phys, DCP_SHA_PAY_SZ,
DMA_FROM_DEVICE);
+done_run:
dma_unmap_single(sdcp->dev, buf_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
return ret;
@@ -563,6 +626,7 @@ static int dcp_sha_req_to_buf(struct crypto_async_request *arq)
const int nents = sg_nents(req->src);
uint8_t *in_buf = sdcp->coh->sha_in_buf;
+ uint8_t *out_buf = sdcp->coh->sha_out_buf;
uint8_t *src_buf;
@@ -617,11 +681,9 @@ static int dcp_sha_req_to_buf(struct crypto_async_request *arq)
actx->fill = 0;
- /* For some reason, the result is flipped. */
- for (i = 0; i < halg->digestsize / 2; i++) {
- swap(req->result[i],
- req->result[halg->digestsize - i - 1]);
- }
+ /* For some reason the result is flipped */
+ for (i = 0; i < halg->digestsize; i++)
+ req->result[i] = out_buf[halg->digestsize - i - 1];
}
return 0;
@@ -748,6 +810,35 @@ static int dcp_sha_finup(struct ahash_request *req)
return dcp_sha_update_fx(req, 1);
}
+static int dcp_sha_export(struct ahash_request *req, void *out)
+{
+ struct dcp_sha_req_ctx *rctx_state = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct dcp_async_ctx *actx_state = crypto_ahash_ctx(tfm);
+ struct dcp_export_state *export = out;
+
+ memcpy(&export->req_ctx, rctx_state, sizeof(struct dcp_sha_req_ctx));
+ memcpy(&export->async_ctx, actx_state, sizeof(struct dcp_async_ctx));
+
+ return 0;
+}
+
+static int dcp_sha_import(struct ahash_request *req, const void *in)
+{
+ struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
+ const struct dcp_export_state *export = in;
+
+ memset(rctx, 0, sizeof(struct dcp_sha_req_ctx));
+ memset(actx, 0, sizeof(struct dcp_async_ctx));
+
+ memcpy(rctx, &export->req_ctx, sizeof(struct dcp_sha_req_ctx));
+ memcpy(actx, &export->async_ctx, sizeof(struct dcp_async_ctx));
+
+ return 0;
+}
+
static int dcp_sha_digest(struct ahash_request *req)
{
int ret;
@@ -829,8 +920,11 @@ static struct ahash_alg dcp_sha1_alg = {
.final = dcp_sha_final,
.finup = dcp_sha_finup,
.digest = dcp_sha_digest,
+ .export = dcp_sha_export,
+ .import = dcp_sha_import,
.halg = {
.digestsize = SHA1_DIGEST_SIZE,
+ .statesize = sizeof(struct dcp_export_state),
.base = {
.cra_name = "sha1",
.cra_driver_name = "sha1-dcp",
@@ -853,8 +947,11 @@ static struct ahash_alg dcp_sha256_alg = {
.final = dcp_sha_final,
.finup = dcp_sha_finup,
.digest = dcp_sha_digest,
+ .export = dcp_sha_export,
+ .import = dcp_sha_import,
.halg = {
.digestsize = SHA256_DIGEST_SIZE,
+ .statesize = sizeof(struct dcp_export_state),
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-dcp",
@@ -924,6 +1021,26 @@ static int mxs_dcp_probe(struct platform_device *pdev)
if (IS_ERR(sdcp->base))
return PTR_ERR(sdcp->base);
+#ifdef CONFIG_ARM
+ sdcp->dcp_clk = devm_clk_get(dev, "dcp");
+
+ if (IS_ERR(sdcp->dcp_clk)) {
+ ret = PTR_ERR(sdcp->dcp_clk);
+ dev_err(dev, "can't identify DCP clk: %d\n", ret);
+ return -ENODEV;
+ }
+
+ ret = clk_prepare(sdcp->dcp_clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't prepare DCP clock: %d\n", ret);
+ return -ENODEV;
+ }
+ ret = clk_enable(sdcp->dcp_clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can't enable DCP clock: %d\n", ret);
+ return -ENODEV;
+ }
+#endif
ret = devm_request_irq(dev, dcp_vmi_irq, mxs_dcp_irq, 0,
"dcp-vmi-irq", sdcp);
@@ -984,6 +1101,11 @@ static int mxs_dcp_probe(struct platform_device *pdev)
crypto_init_queue(&sdcp->queue[i], 50);
}
+ /*
+ * Enable driver alignment with hw behavior for sha generation
+ */
+ sdcp->enable_sha_workaround = 1;
+
/* Create the SHA and AES handler threads. */
sdcp->thread[DCP_CHAN_HASH_SHA] = kthread_run(dcp_chan_thread_sha,
NULL, "mxs_dcp_chan/sha");
@@ -1065,6 +1187,11 @@ static int mxs_dcp_remove(struct platform_device *pdev)
kthread_stop(sdcp->thread[DCP_CHAN_HASH_SHA]);
kthread_stop(sdcp->thread[DCP_CHAN_CRYPTO]);
+#ifdef CONFIG_ARM
+ /* shut clocks off before finalizing shutdown */
+ clk_disable(sdcp->dcp_clk);
+#endif
+
platform_set_drvdata(pdev, NULL);
global_sdcp = NULL;
@@ -1075,6 +1202,7 @@ static int mxs_dcp_remove(struct platform_device *pdev)
static const struct of_device_id mxs_dcp_dt_ids[] = {
{ .compatible = "fsl,imx23-dcp", .data = NULL, },
{ .compatible = "fsl,imx28-dcp", .data = NULL, },
+ { .compatible = "fsl,imx6sl-dcp", .data = NULL, },
{ /* sentinel */ }
};
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 141aefbe37ec..e4a26a151e9f 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -224,6 +224,7 @@ config IMX_SDMA
tristate "i.MX SDMA support"
depends on ARCH_MXC
select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
help
Support the i.MX SDMA engine. This engine is integrated into
Freescale i.MX25/31/35/51/53/6 chips.
@@ -354,7 +355,7 @@ config MV_XOR_V2
config MXS_DMA
bool "MXS DMA support"
- depends on SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q || SOC_IMX6UL
+ depends on ARCH_MXS || ARCH_MXC || COMPILE_TEST
select STMP_DEVICE
select DMA_ENGINE
help
@@ -362,6 +363,8 @@ config MXS_DMA
and APBX-DMA is integrated into Freescale
i.MX23/28/MX6Q/MX6DL/MX6UL chips.
+source "drivers/dma/pxp/Kconfig"
+
config MX3_IPU
bool "MX3x Image Processing Unit support"
depends on ARCH_MXC
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index e4dc9cac7ee8..0f4da5b7b3be 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -53,6 +53,8 @@ obj-$(CONFIG_PCH_DMA) += pch_dma.o
obj-$(CONFIG_PL330_DMA) += pl330.o
obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
obj-$(CONFIG_PXA_DMA) += pxa_dma.o
+obj-$(CONFIG_MXC_PXP_V2) += pxp/
+obj-$(CONFIG_MXC_PXP_V3) += pxp/
obj-$(CONFIG_RENESAS_DMA) += sh/
obj-$(CONFIG_SIRF_DMA) += sirf-dma.o
obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 6775f2c74e25..1847add29fa2 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -2,6 +2,7 @@
* drivers/dma/fsl-edma.c
*
* Copyright 2013-2014 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
*
* Driver for the Freescale eDMA engine with flexible channel multiplexing
* capability for DMA request sources. The eDMA block can be found on some
@@ -111,11 +112,18 @@
#define EDMAMUX_CHCFG_SOURCE(n) ((n) & 0x3F)
#define DMAMUX_NR 2
+#define FSL_EDMA_REG_NUM 3
+#define FSL_DMAMUX_SLOTS 32
+#define FSL_DMAMUX_REG_NUM (DMAMUX_NR * FSL_DMAMUX_SLOTS)
#define FSL_EDMA_BUSWIDTHS BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)
+
+/* Controller will loss power in i.MX7ULP VLLS low power mode */
+#define FSL_EDMA_QUIRK_VLLS_MODE (1 << 0)
+
enum fsl_edma_pm_state {
RUNNING = 0,
SUSPENDED,
@@ -158,6 +166,8 @@ struct fsl_edma_chan {
struct fsl_edma_desc *edesc;
struct fsl_edma_slave_config fsc;
struct dma_pool *tcd_pool;
+ char chan_name[16];
+ u32 chn_real_count;
};
struct fsl_edma_desc {
@@ -172,15 +182,79 @@ struct fsl_edma_engine {
struct dma_device dma_dev;
void __iomem *membase;
void __iomem *muxbase[DMAMUX_NR];
+ struct clk *dmaclk;
struct clk *muxclk[DMAMUX_NR];
struct mutex fsl_edma_mutex;
u32 n_chans;
int txirq;
int errirq;
bool big_endian;
+ u32 dmamux_nr;
+ u32 version;
+ void (*mux_configure)(struct fsl_edma_chan *,
+ void __iomem *muxaddr, u32 off,
+ u32 slot, bool enable);
+ u32 edma_regs[FSL_EDMA_REG_NUM];
+ u32 dmamux_regs[FSL_DMAMUX_REG_NUM];
+ u32 quirks;
struct fsl_edma_chan chans[];
};
+static struct platform_device_id fsl_edma_devtype[] = {
+ {
+ .name = "vf610-edma",
+ .driver_data = 0,
+ }, {
+ .name = "imx7ulp-edma",
+ .driver_data = FSL_EDMA_QUIRK_VLLS_MODE,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, fsl_edma_devtype);
+
+enum fsl_edma_type {
+ VF610_EDMA,
+ IMX7ULP_EDMA,
+};
+
+static const struct of_device_id fsl_edma_dt_ids[] = {
+ {
+ .compatible = "fsl,vf610-edma",
+ .data = &fsl_edma_devtype[VF610_EDMA],
+ }, {
+ .compatible = "nxp,imx7ulp-edma",
+ .data = &fsl_edma_devtype[IMX7ULP_EDMA],
+ }, { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
+
+void mux_configure8(struct fsl_edma_chan *fsl_chan, void __iomem *muxaddr,
+ u32 off, u32 slot, bool enable)
+{
+ u8 val8;
+
+ if (enable)
+ val8 = EDMAMUX_CHCFG_ENBL | slot;
+ else
+ val8 = EDMAMUX_CHCFG_DIS;
+
+ iowrite8(val8, muxaddr + off);
+}
+
+void mux_configure32(struct fsl_edma_chan *fsl_chan, void __iomem *muxaddr,
+ u32 off, u32 slot, bool enable)
+{
+ u32 val;
+
+ if (enable)
+ val = EDMAMUX_CHCFG_ENBL << 24 | slot;
+ else
+ val = EDMAMUX_CHCFG_DIS;
+
+ iowrite32(val, muxaddr + off * 4);
+}
+
/*
* R/W functions for big- or little-endian registers:
* The eDMA controller's endian is independent of the CPU core's endian.
@@ -257,15 +331,12 @@ static void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
void __iomem *muxaddr;
unsigned chans_per_mux, ch_off;
- chans_per_mux = fsl_chan->edma->n_chans / DMAMUX_NR;
+ chans_per_mux = fsl_chan->edma->n_chans / fsl_chan->edma->dmamux_nr;
ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux;
muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
slot = EDMAMUX_CHCFG_SOURCE(slot);
- if (enable)
- iowrite8(EDMAMUX_CHCFG_ENBL | slot, muxaddr + ch_off);
- else
- iowrite8(EDMAMUX_CHCFG_DIS, muxaddr + ch_off);
+ fsl_chan->edma->mux_configure(fsl_chan, muxaddr, ch_off, slot, enable);
}
static unsigned int fsl_edma_get_tcd_attr(enum dma_slave_buswidth addr_width)
@@ -312,7 +383,7 @@ static int fsl_edma_terminate_all(struct dma_chan *chan)
return 0;
}
-static int fsl_edma_pause(struct dma_chan *chan)
+static int fsl_edma_device_pause(struct dma_chan *chan)
{
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
unsigned long flags;
@@ -327,7 +398,7 @@ static int fsl_edma_pause(struct dma_chan *chan)
return 0;
}
-static int fsl_edma_resume(struct dma_chan *chan)
+static int fsl_edma_device_resume(struct dma_chan *chan)
{
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
unsigned long flags;
@@ -416,8 +487,12 @@ static enum dma_status fsl_edma_tx_status(struct dma_chan *chan,
unsigned long flags;
status = dma_cookie_status(chan, cookie, txstate);
- if (status == DMA_COMPLETE)
+ if (status == DMA_COMPLETE) {
+ spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
+ txstate->residue = fsl_chan->chn_real_count;
+ spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
return status;
+ }
if (!txstate)
return fsl_chan->status;
@@ -426,7 +501,7 @@ static enum dma_status fsl_edma_tx_status(struct dma_chan *chan,
vdesc = vchan_find_desc(&fsl_chan->vchan, cookie);
if (fsl_chan->edesc && cookie == fsl_chan->edesc->vdesc.tx.cookie)
txstate->residue = fsl_edma_desc_residue(fsl_chan, vdesc, true);
- else if (vdesc)
+ else if (fsl_chan->edesc && vdesc)
txstate->residue = fsl_edma_desc_residue(fsl_chan, vdesc, false);
else
txstate->residue = 0;
@@ -661,6 +736,11 @@ static void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan)
fsl_chan->idle = false;
}
+static void fsl_edma_get_realcnt(struct fsl_edma_chan *fsl_chan)
+{
+ fsl_chan->chn_real_count = fsl_edma_desc_residue(fsl_chan, NULL, true);
+}
+
static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
{
struct fsl_edma_engine *fsl_edma = dev_id;
@@ -683,6 +763,7 @@ static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
spin_lock(&fsl_chan->vchan.lock);
if (!fsl_chan->edesc->iscyclic) {
+ fsl_edma_get_realcnt(fsl_chan);
list_del(&fsl_chan->edesc->vdesc.node);
vchan_cookie_complete(&fsl_chan->edesc->vdesc);
fsl_chan->edesc = NULL;
@@ -712,6 +793,7 @@ static irqreturn_t fsl_edma_err_handler(int irq, void *dev_id)
for (ch = 0; ch < fsl_edma->n_chans; ch++) {
if (err & (0x1 << ch)) {
+ dev_err(fsl_edma->dma_dev.dev, "DMA CH%d Err!\n", ch);
fsl_edma_disable_request(&fsl_edma->chans[ch]);
edma_writeb(fsl_edma, EDMA_CERR_CERR(ch),
fsl_edma->membase + EDMA_CERR);
@@ -755,7 +837,7 @@ static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
struct fsl_edma_engine *fsl_edma = ofdma->of_dma_data;
struct dma_chan *chan, *_chan;
struct fsl_edma_chan *fsl_chan;
- unsigned long chans_per_mux = fsl_edma->n_chans / DMAMUX_NR;
+ unsigned long chans_per_mux = fsl_edma->n_chans / fsl_edma->dmamux_nr;
if (dma_spec->args_count != 2)
return NULL;
@@ -867,8 +949,51 @@ static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma)
{
int i;
- for (i = 0; i < DMAMUX_NR; i++)
+ for (i = 0; i < fsl_edma->dmamux_nr; i++)
clk_disable_unprepare(fsl_edma->muxclk[i]);
+
+ if (fsl_edma->dmaclk)
+ clk_disable_unprepare(fsl_edma->dmaclk);
+}
+
+static int
+fsl_edma2_irq_init(struct platform_device *pdev,
+ struct fsl_edma_engine *fsl_edma)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int i, ret, irq;
+ int count = 0;
+
+ count = of_irq_count(np);
+ dev_info(&pdev->dev, "%s Found %d interrupts\r\n", __func__, count);
+ if(count < 2){
+ dev_err(&pdev->dev, "Interrupts in DTS not correct.\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < count; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ return -ENXIO;
+
+ sprintf(fsl_edma->chans[i].chan_name, "eDMA2-CH%02d", i);
+
+ /* The last IRQ is for eDMA err */
+ if (i == count - 1)
+ ret = devm_request_irq(&pdev->dev, irq,
+ fsl_edma_err_handler,
+ 0, "eDMA2-ERR", fsl_edma);
+ else
+
+ ret = devm_request_irq(&pdev->dev, irq,
+ fsl_edma_tx_handler, 0,
+ fsl_edma->chans[i].chan_name,
+ fsl_edma);
+ if(ret)
+ return ret;
+ }
+
+ return 0;
}
static int fsl_edma_probe(struct platform_device *pdev)
@@ -876,6 +1001,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct fsl_edma_engine *fsl_edma;
struct fsl_edma_chan *fsl_chan;
+ const struct of_device_id *of_id;
struct resource *res;
int len, chans;
int ret, i;
@@ -891,6 +1017,11 @@ static int fsl_edma_probe(struct platform_device *pdev)
if (!fsl_edma)
return -ENOMEM;
+ of_id = of_match_device(fsl_edma_dt_ids, &pdev->dev);
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ fsl_edma->quirks = pdev->id_entry->driver_data;
+
fsl_edma->n_chans = chans;
mutex_init(&fsl_edma->fsl_edma_mutex);
@@ -899,7 +1030,29 @@ static int fsl_edma_probe(struct platform_device *pdev)
if (IS_ERR(fsl_edma->membase))
return PTR_ERR(fsl_edma->membase);
- for (i = 0; i < DMAMUX_NR; i++) {
+ fsl_edma->dmamux_nr = DMAMUX_NR;
+ fsl_edma->mux_configure = mux_configure8;
+ fsl_edma->version = 1;
+
+ if (of_device_is_compatible(np, "nxp,imx7ulp-edma")) {
+ fsl_edma->dmamux_nr = 1;
+ fsl_edma->mux_configure = mux_configure32;
+ fsl_edma->version = 2;
+
+ fsl_edma->dmaclk = devm_clk_get(&pdev->dev, "dma");
+ if (IS_ERR(fsl_edma->dmaclk)) {
+ dev_err(&pdev->dev, "Missing DMA block clock.\n");
+ return PTR_ERR(fsl_edma->dmaclk);
+ }
+
+ ret = clk_prepare_enable(fsl_edma->dmaclk);
+ if (ret) {
+ dev_err(&pdev->dev, "DMA clk block failed.\n");
+ return ret;
+ }
+ }
+
+ for (i = 0; i < fsl_edma->dmamux_nr; i++) {
char clkname[32];
res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
@@ -926,6 +1079,14 @@ static int fsl_edma_probe(struct platform_device *pdev)
}
+ edma_writel(fsl_edma, ~0, fsl_edma->membase + EDMA_INTR);
+ if (fsl_edma->version == 1)
+ ret = fsl_edma_irq_init(pdev, fsl_edma);
+ else
+ ret = fsl_edma2_irq_init(pdev, fsl_edma);
+ if (ret)
+ return ret;
+
fsl_edma->big_endian = of_property_read_bool(np, "big-endian");
INIT_LIST_HEAD(&fsl_edma->dma_dev.channels);
@@ -940,14 +1101,11 @@ static int fsl_edma_probe(struct platform_device *pdev)
vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
edma_writew(fsl_edma, 0x0, fsl_edma->membase + EDMA_TCD_CSR(i));
+ fsl_chan->vchan.chan.chan_id = i;
fsl_edma_chan_mux(fsl_chan, 0, false);
+ fsl_chan->vchan.chan.chan_id = 0;
}
- edma_writel(fsl_edma, ~0, fsl_edma->membase + EDMA_INTR);
- ret = fsl_edma_irq_init(pdev, fsl_edma);
- if (ret)
- return ret;
-
dma_cap_set(DMA_PRIVATE, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_SLAVE, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_CYCLIC, fsl_edma->dma_dev.cap_mask);
@@ -961,8 +1119,8 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
fsl_edma->dma_dev.device_prep_dma_cyclic = fsl_edma_prep_dma_cyclic;
fsl_edma->dma_dev.device_config = fsl_edma_slave_config;
- fsl_edma->dma_dev.device_pause = fsl_edma_pause;
- fsl_edma->dma_dev.device_resume = fsl_edma_resume;
+ fsl_edma->dma_dev.device_pause = fsl_edma_device_pause;
+ fsl_edma->dma_dev.device_resume = fsl_edma_device_resume;
fsl_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all;
fsl_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
@@ -1020,6 +1178,56 @@ static int fsl_edma_remove(struct platform_device *pdev)
return 0;
}
+static int fsl_edma_register_save(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fsl_edma_engine *fsl_edma = platform_get_drvdata(pdev);
+ int i, j;
+
+ if (!(fsl_edma->quirks & FSL_EDMA_QUIRK_VLLS_MODE))
+ return 0;
+
+ /* save regs */
+ fsl_edma->edma_regs[0] =
+ edma_readl(fsl_edma, fsl_edma->membase + EDMA_CR);
+ fsl_edma->edma_regs[1] =
+ edma_readl(fsl_edma, fsl_edma->membase + EDMA_ERQ);
+ fsl_edma->edma_regs[2] =
+ edma_readl(fsl_edma, fsl_edma->membase + EDMA_EEI);
+ for (i = 0; i < fsl_edma->dmamux_nr; i++)
+ for (j = 0; j < fsl_edma->n_chans; j++)
+ fsl_edma->dmamux_regs[i * fsl_edma->n_chans + j] =
+ edma_readl(fsl_edma,
+ fsl_edma->muxbase[i] + j * 4);
+
+ return 0;
+}
+
+static int fsl_edma_register_restore(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fsl_edma_engine *fsl_edma = platform_get_drvdata(pdev);
+ int i, j;
+
+ if (!(fsl_edma->quirks & FSL_EDMA_QUIRK_VLLS_MODE))
+ return 0;
+
+ /* restore the regs */
+ for (i = 0; i < fsl_edma->dmamux_nr; i++)
+ for (j = 0; j < fsl_edma->n_chans; j++)
+ edma_writel(fsl_edma,
+ fsl_edma->dmamux_regs[i * fsl_edma->n_chans + j],
+ fsl_edma->muxbase[i] + j * 4);
+ edma_writel(fsl_edma, fsl_edma->edma_regs[1],
+ fsl_edma->membase + EDMA_ERQ);
+ edma_writel(fsl_edma, fsl_edma->edma_regs[2],
+ fsl_edma->membase + EDMA_EEI);
+ edma_writel(fsl_edma, fsl_edma->edma_regs[0],
+ fsl_edma->membase + EDMA_CR);
+
+ return 0;
+}
+
static int fsl_edma_suspend_late(struct device *dev)
{
struct fsl_edma_engine *fsl_edma = dev_get_drvdata(dev);
@@ -1041,6 +1249,8 @@ static int fsl_edma_suspend_late(struct device *dev)
spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
}
+ fsl_edma_register_save(dev);
+
return 0;
}
@@ -1050,6 +1260,8 @@ static int fsl_edma_resume_early(struct device *dev)
struct fsl_edma_chan *fsl_chan;
int i;
+ fsl_edma_register_restore(dev);
+
for (i = 0; i < fsl_edma->n_chans; i++) {
fsl_chan = &fsl_edma->chans[i];
fsl_chan->pm_state = RUNNING;
@@ -1074,18 +1286,13 @@ static const struct dev_pm_ops fsl_edma_pm_ops = {
.resume_early = fsl_edma_resume_early,
};
-static const struct of_device_id fsl_edma_dt_ids[] = {
- { .compatible = "fsl,vf610-edma", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
-
static struct platform_driver fsl_edma_driver = {
.driver = {
.name = "fsl-edma",
.of_match_table = fsl_edma_dt_ids,
.pm = &fsl_edma_pm_ops,
},
+ .id_table = fsl_edma_devtype,
.probe = fsl_edma_probe,
.remove = fsl_edma_remove,
};
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d1651a50c349..b72d21cb5eb8 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -7,7 +7,7 @@
*
* Based on code from Freescale:
*
- * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-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
@@ -30,7 +30,9 @@
#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/device.h>
+#include <linux/genalloc.h>
#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
@@ -48,6 +50,7 @@
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include "dmaengine.h"
+#include "virt-dma.h"
/* SDMA registers */
#define SDMA_H_C0PTR 0x000
@@ -173,6 +176,8 @@
#define SDMA_WATERMARK_LEVEL_SPDIF BIT(10)
#define SDMA_WATERMARK_LEVEL_SP BIT(11)
#define SDMA_WATERMARK_LEVEL_DP BIT(12)
+#define SDMA_WATERMARK_LEVEL_SD BIT(13)
+#define SDMA_WATERMARK_LEVEL_DD BIT(14)
#define SDMA_WATERMARK_LEVEL_HWML (0xFF << 16)
#define SDMA_WATERMARK_LEVEL_LWE BIT(28)
#define SDMA_WATERMARK_LEVEL_HWE BIT(29)
@@ -284,9 +289,22 @@ struct sdma_context_data {
} __attribute__ ((packed));
#define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
+#define SDMA_BD_MAX_CNT 0xfffc /* align with 4 bytes */
struct sdma_engine;
+struct sdma_desc {
+ struct virt_dma_desc vd;
+ struct list_head node;
+ unsigned int num_bd;
+ dma_addr_t bd_phys;
+ bool bd_iram;
+ unsigned int buf_tail;
+ unsigned int buf_ptail;
+ struct sdma_channel *sdmac;
+ struct sdma_buffer_descriptor *bd;
+};
+
/**
* struct sdma_channel - housekeeping for a SDMA channel
*
@@ -297,39 +315,37 @@ struct sdma_engine;
* @event_id0 aka dma request line
* @event_id1 for channels that use 2 events
* @word_size peripheral access size
- * @buf_tail ID of the buffer that was processed
- * @buf_ptail ID of the previous buffer that was processed
- * @num_bd max NUM_BD. number of descriptors currently handling
+ * @bd_iram flag indicating the memory location of buffer descriptor
*/
struct sdma_channel {
+ struct virt_dma_chan vc;
+ struct list_head pending;
struct sdma_engine *sdma;
+ struct sdma_desc *desc;
unsigned int channel;
enum dma_transfer_direction direction;
enum sdma_peripheral_type peripheral_type;
unsigned int event_id0;
unsigned int event_id1;
enum dma_slave_buswidth word_size;
- unsigned int buf_tail;
- unsigned int buf_ptail;
- unsigned int num_bd;
unsigned int period_len;
- struct sdma_buffer_descriptor *bd;
- dma_addr_t bd_phys;
unsigned int pc_from_device, pc_to_device;
unsigned int device_to_device;
+ unsigned int pc_to_pc;
unsigned long flags;
dma_addr_t per_address, per_address2;
unsigned long event_mask[2];
unsigned long watermark_level;
u32 shp_addr, per_addr;
- struct dma_chan chan;
- spinlock_t lock;
- struct dma_async_tx_descriptor desc;
enum dma_status status;
+ struct imx_dma_data data;
unsigned int chn_count;
unsigned int chn_real_count;
- struct tasklet_struct tasklet;
- struct imx_dma_data data;
+ bool context_loaded;
+ u32 bd_size_sum;
+ bool src_dualfifo;
+ bool dst_dualfifo;
+ struct dma_pool *bd_pool;
};
#define IMX_DMA_SG_LOOP BIT(0)
@@ -338,6 +354,14 @@ struct sdma_channel {
#define MXC_SDMA_DEFAULT_PRIORITY 1
#define MXC_SDMA_MIN_PRIORITY 1
#define MXC_SDMA_MAX_PRIORITY 7
+/*
+ * 0x78(SDMA_XTRIG_CONF2+4)~0x100(SDMA_CHNPRI_O) registers are reserved and
+ * can't be accessed. Skip these register touch in suspend/resume. Also below
+ * two macros are only used on i.mx6sx.
+ */
+#define MXC_SDMA_RESERVED_REG (SDMA_CHNPRI_0 - SDMA_XTRIG_CONF2 - 4)
+#define MXC_SDMA_SAVED_REG_NUM (((SDMA_CHNENBL0_IMX35 + 4 * 48) - \
+ MXC_SDMA_RESERVED_REG) / 4)
#define SDMA_FIRMWARE_MAGIC 0x414d4453
@@ -376,6 +400,8 @@ struct sdma_engine {
struct device_dma_parameters dma_parms;
struct sdma_channel channel[MAX_DMA_CHANNELS];
struct sdma_channel_control *channel_control;
+ u32 save_regs[MXC_SDMA_SAVED_REG_NUM];
+ const char *fw_name;
void __iomem *regs;
struct sdma_context_data *context;
dma_addr_t context_phys;
@@ -389,6 +415,12 @@ struct sdma_engine {
u32 spba_start_addr;
u32 spba_end_addr;
unsigned int irq;
+ struct gen_pool *iram_pool;
+ /* channel0 bd */
+ dma_addr_t bd0_phys;
+ bool bd0_iram;
+ struct sdma_buffer_descriptor *bd0;
+ bool suspend_off;
};
static struct sdma_driver_data sdma_imx31 = {
@@ -466,7 +498,6 @@ static struct sdma_script_start_addrs sdma_script_imx6q = {
.ap_2_ap_addr = 642,
.uart_2_mcu_addr = 817,
.mcu_2_app_addr = 747,
- .per_2_per_addr = 6331,
.uartsh_2_mcu_addr = 1032,
.mcu_2_shp_addr = 960,
.app_2_mcu_addr = 683,
@@ -481,6 +512,30 @@ static struct sdma_driver_data sdma_imx6q = {
.script_addrs = &sdma_script_imx6q,
};
+static struct sdma_script_start_addrs sdma_script_imx6sx = {
+ .ap_2_ap_addr = 642,
+ .uart_2_mcu_addr = 817,
+ .mcu_2_app_addr = 747,
+ .uartsh_2_mcu_addr = 1032,
+ .mcu_2_shp_addr = 960,
+ .app_2_mcu_addr = 683,
+ .shp_2_mcu_addr = 891,
+ .spdif_2_mcu_addr = 1100,
+ .mcu_2_spdif_addr = 1134,
+};
+
+static struct sdma_driver_data sdma_imx6sx = {
+ .chnenbl0 = SDMA_CHNENBL0_IMX35,
+ .num_events = 48,
+ .script_addrs = &sdma_script_imx6sx,
+};
+
+static struct sdma_driver_data sdma_imx6ul = {
+ .chnenbl0 = SDMA_CHNENBL0_IMX35,
+ .num_events = 48,
+ .script_addrs = &sdma_script_imx6sx,
+};
+
static struct sdma_script_start_addrs sdma_script_imx7d = {
.ap_2_ap_addr = 644,
.uart_2_mcu_addr = 819,
@@ -519,6 +574,9 @@ static const struct platform_device_id sdma_devtypes[] = {
.name = "imx6q-sdma",
.driver_data = (unsigned long)&sdma_imx6q,
}, {
+ .name = "imx6sx-sdma",
+ .driver_data = (unsigned long)&sdma_imx6sx,
+ }, {
.name = "imx7d-sdma",
.driver_data = (unsigned long)&sdma_imx7d,
}, {
@@ -528,6 +586,8 @@ static const struct platform_device_id sdma_devtypes[] = {
MODULE_DEVICE_TABLE(platform, sdma_devtypes);
static const struct of_device_id sdma_dt_ids[] = {
+ { .compatible = "fsl,imx6ul-sdma", .data = &sdma_imx6ul, },
+ { .compatible = "fsl,imx6sx-sdma", .data = &sdma_imx6sx, },
{ .compatible = "fsl,imx6q-sdma", .data = &sdma_imx6q, },
{ .compatible = "fsl,imx53-sdma", .data = &sdma_imx53, },
{ .compatible = "fsl,imx51-sdma", .data = &sdma_imx51, },
@@ -544,6 +604,8 @@ MODULE_DEVICE_TABLE(of, sdma_dt_ids);
#define SDMA_H_CONFIG_ACR BIT(4) /* indicates if AHB freq /core freq = 2 or 1 */
#define SDMA_H_CONFIG_CSM (3) /* indicates which context switch mode is selected*/
+static void sdma_start_desc(struct sdma_channel *sdmac);
+
static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
{
u32 chnenbl0 = sdma->drvdata->chnenbl0;
@@ -616,23 +678,25 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
u32 address)
{
- struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
void *buf_virt;
dma_addr_t buf_phys;
int ret;
unsigned long flags;
+ bool use_iram = true;
- buf_virt = dma_alloc_coherent(NULL,
- size,
- &buf_phys, GFP_KERNEL);
+ buf_virt = gen_pool_dma_alloc(sdma->iram_pool, size, &buf_phys);
if (!buf_virt) {
- return -ENOMEM;
+ use_iram = false;
+ buf_virt = dma_alloc_coherent(sdma->dev, size, &buf_phys, GFP_KERNEL);
+ if (!buf_virt)
+ return -ENOMEM;
}
spin_lock_irqsave(&sdma->channel_0_lock, flags);
bd0->mode.command = C0_SETPM;
- bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
+ bd0->mode.status = BD_DONE | BD_WRAP | BD_EXTD;
bd0->mode.count = size / 2;
bd0->buffer_addr = buf_phys;
bd0->ext_buffer_addr = address;
@@ -643,7 +707,10 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
- dma_free_coherent(NULL, size, buf_virt, buf_phys);
+ if (use_iram)
+ gen_pool_free(sdma->iram_pool, (unsigned long)buf_virt, size);
+ else
+ dma_free_coherent(sdma->dev, size, buf_virt, buf_phys);
return ret;
}
@@ -675,6 +742,7 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
static void sdma_update_channel_loop(struct sdma_channel *sdmac)
{
struct sdma_buffer_descriptor *bd;
+ struct sdma_desc *desc = sdmac->desc;
int error = 0;
enum dma_status old_status = sdmac->status;
@@ -682,8 +750,8 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* loop mode. Iterate over descriptors, re-setup them and
* call callback function.
*/
- while (1) {
- bd = &sdmac->bd[sdmac->buf_tail];
+ while (desc) {
+ bd = &desc->bd[desc->buf_tail];
if (bd->mode.status & BD_DONE)
break;
@@ -702,36 +770,35 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
sdmac->chn_real_count = bd->mode.count;
bd->mode.status |= BD_DONE;
bd->mode.count = sdmac->period_len;
- sdmac->buf_ptail = sdmac->buf_tail;
- sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
-
- /*
- * The callback is called from the interrupt context in order
- * to reduce latency and to avoid the risk of altering the
- * SDMA transaction status by the time the client tasklet is
- * executed.
- */
-
- dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
+ desc->buf_ptail = desc->buf_tail;
+ desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
if (error)
sdmac->status = old_status;
+ /*
+ * The callback is called from the interrupt context in order
+ * to reduce latency and to avoid the risk of altering the
+ * SDMA transaction status by the time the client tasklet is
+ * executed.
+ */
+ spin_unlock(&sdmac->vc.lock);
+ dmaengine_desc_get_callback_invoke(&desc->vd.tx, NULL);
+ spin_lock(&sdmac->vc.lock);
}
}
-static void mxc_sdma_handle_channel_normal(unsigned long data)
+static void mxc_sdma_handle_channel_normal(struct sdma_channel *data)
{
struct sdma_channel *sdmac = (struct sdma_channel *) data;
struct sdma_buffer_descriptor *bd;
int i, error = 0;
- sdmac->chn_real_count = 0;
/*
* non loop mode. Iterate over all descriptors, collect
* errors and call callback function
*/
- for (i = 0; i < sdmac->num_bd; i++) {
- bd = &sdmac->bd[i];
+ for (i = 0; i < sdmac->desc->num_bd; i++) {
+ bd = &sdmac->desc->bd[i];
if (bd->mode.status & (BD_DONE | BD_RROR))
error = -EIO;
@@ -742,10 +809,6 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
sdmac->status = DMA_ERROR;
else
sdmac->status = DMA_COMPLETE;
-
- dma_cookie_complete(&sdmac->desc);
-
- dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
}
static irqreturn_t sdma_int_handler(int irq, void *dev_id)
@@ -761,13 +824,26 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id)
while (stat) {
int channel = fls(stat) - 1;
struct sdma_channel *sdmac = &sdma->channel[channel];
-
- if (sdmac->flags & IMX_DMA_SG_LOOP)
- sdma_update_channel_loop(sdmac);
- else
- tasklet_schedule(&sdmac->tasklet);
-
+ struct sdma_desc *desc;
+
+ spin_lock(&sdmac->vc.lock);
+ desc = sdmac->desc;
+ if (desc) {
+ if (sdmac->flags & IMX_DMA_SG_LOOP) {
+ if (sdmac->peripheral_type != IMX_DMATYPE_HDMI)
+ sdma_update_channel_loop(sdmac);
+ else
+ vchan_cyclic_callback(&desc->vd);
+ } else {
+ mxc_sdma_handle_channel_normal(sdmac);
+ vchan_cookie_complete(&desc->vd);
+ if (!list_empty(&sdmac->pending))
+ list_del(&desc->node);
+ sdma_start_desc(sdmac);
+ }
+ }
__clear_bit(channel, &stat);
+ spin_unlock(&sdmac->vc.lock);
}
return IRQ_HANDLED;
@@ -785,14 +861,16 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
* These are needed once we start to support transfers between
* two peripherals or memory-to-memory transfers
*/
- int per_2_per = 0;
+ int per_2_per = 0, emi_2_emi = 0;
sdmac->pc_from_device = 0;
sdmac->pc_to_device = 0;
sdmac->device_to_device = 0;
+ sdmac->pc_to_pc = 0;
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
+ emi_2_emi = sdma->script_addrs->ap_2_ap_addr;
break;
case IMX_DMATYPE_DSP:
emi_2_per = sdma->script_addrs->bp_2_ap_addr;
@@ -815,6 +893,9 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
emi_2_per = sdma->script_addrs->mcu_2_ata_addr;
break;
case IMX_DMATYPE_CSPI:
+ per_2_emi = sdma->script_addrs->app_2_mcu_addr;
+ emi_2_per = sdma->script_addrs->mcu_2_ecspi_addr;
+ break;
case IMX_DMATYPE_EXT:
case IMX_DMATYPE_SSI:
case IMX_DMATYPE_SAI:
@@ -858,6 +939,9 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
case IMX_DMATYPE_IPU_MEMORY:
emi_2_per = sdma->script_addrs->ext_mem_2_ipu_addr;
break;
+ case IMX_DMATYPE_HDMI:
+ emi_2_per = sdma->script_addrs->hdmi_dma_addr;
+ break;
default:
break;
}
@@ -865,6 +949,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
sdmac->pc_from_device = per_2_emi;
sdmac->pc_to_device = emi_2_per;
sdmac->device_to_device = per_2_per;
+ sdmac->pc_to_pc = emi_2_emi;
}
static int sdma_load_context(struct sdma_channel *sdmac)
@@ -873,14 +958,19 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int channel = sdmac->channel;
int load_address;
struct sdma_context_data *context = sdma->context;
- struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
int ret;
unsigned long flags;
+ if (sdmac->context_loaded)
+ return 0;
+
if (sdmac->direction == DMA_DEV_TO_MEM)
load_address = sdmac->pc_from_device;
else if (sdmac->direction == DMA_DEV_TO_DEV)
load_address = sdmac->device_to_device;
+ else if (sdmac->direction == DMA_MEM_TO_MEM)
+ load_address = sdmac->pc_to_pc;
else
load_address = sdmac->pc_to_device;
@@ -902,14 +992,19 @@ static int sdma_load_context(struct sdma_channel *sdmac)
/* Send by context the event mask,base address for peripheral
* and watermark level
*/
- context->gReg[0] = sdmac->event_mask[1];
- context->gReg[1] = sdmac->event_mask[0];
- context->gReg[2] = sdmac->per_addr;
- context->gReg[6] = sdmac->shp_addr;
- context->gReg[7] = sdmac->watermark_level;
+ if (sdmac->peripheral_type == IMX_DMATYPE_HDMI) {
+ context->gReg[4] = sdmac->per_addr;
+ context->gReg[6] = sdmac->shp_addr;
+ } else {
+ context->gReg[0] = sdmac->event_mask[1];
+ context->gReg[1] = sdmac->event_mask[0];
+ context->gReg[2] = sdmac->per_addr;
+ context->gReg[6] = sdmac->shp_addr;
+ context->gReg[7] = sdmac->watermark_level;
+ }
bd0->mode.command = C0_SETDM;
- bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
+ bd0->mode.status = BD_DONE | BD_WRAP | BD_EXTD;
bd0->mode.count = sizeof(*context) / 4;
bd0->buffer_addr = sdma->context_phys;
bd0->ext_buffer_addr = 2048 + (sizeof(*context) / 4) * channel;
@@ -917,12 +1012,39 @@ static int sdma_load_context(struct sdma_channel *sdmac)
spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
+ sdmac->context_loaded = true;
+
+ return ret;
+}
+
+static int sdma_save_restore_context(struct sdma_engine *sdma, bool save)
+{
+ struct sdma_context_data *context = sdma->context;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&sdma->channel_0_lock, flags);
+
+ if (save)
+ bd0->mode.command = C0_GETDM;
+ else
+ bd0->mode.command = C0_SETDM;
+
+ bd0->mode.status = BD_DONE | BD_WRAP | BD_EXTD;
+ bd0->mode.count = MAX_DMA_CHANNELS * sizeof(*context) / 4;
+ bd0->buffer_addr = sdma->context_phys;
+ bd0->ext_buffer_addr = 2048;
+ ret = sdma_run_channel0(sdma);
+
+ spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
+
return ret;
}
static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
{
- return container_of(chan, struct sdma_channel, chan);
+ return container_of(chan, struct sdma_channel, vc.chan);
}
static int sdma_disable_channel(struct dma_chan *chan)
@@ -975,6 +1097,11 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_DP;
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_CONT;
+
+ if (sdmac->src_dualfifo)
+ sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SD;
+ if (sdmac->dst_dualfifo)
+ sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_DD;
}
static int sdma_config_channel(struct dma_chan *chan)
@@ -989,11 +1116,9 @@ static int sdma_config_channel(struct dma_chan *chan)
sdmac->shp_addr = 0;
sdmac->per_addr = 0;
- if (sdmac->event_id0) {
- if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
- return -EINVAL;
- sdma_event_enable(sdmac, sdmac->event_id0);
- }
+ if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
+ return -EINVAL;
+ sdma_event_enable(sdmac, sdmac->event_id0);
if (sdmac->event_id1) {
if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events)
@@ -1022,8 +1147,15 @@ static int sdma_config_channel(struct dma_chan *chan)
if (sdmac->peripheral_type == IMX_DMATYPE_ASRC_SP ||
sdmac->peripheral_type == IMX_DMATYPE_ASRC)
sdma_set_watermarklevel_for_p2p(sdmac);
- } else
+ } else {
+ /* ERR008517 fixed on i.mx6ul, no workaround needed */
+ if (sdmac->peripheral_type == IMX_DMATYPE_CSPI &&
+ sdmac->direction == DMA_MEM_TO_DEV &&
+ sdmac->sdma->drvdata == &sdma_imx6ul)
+ __set_bit(31, &sdmac->watermark_level);
+
__set_bit(sdmac->event_id0, sdmac->event_mask);
+ }
/* Address */
sdmac->shp_addr = sdmac->per_address;
@@ -1053,52 +1185,191 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac,
return 0;
}
-static int sdma_request_channel(struct sdma_channel *sdmac)
+static int sdma_alloc_bd(struct sdma_desc *desc)
{
- struct sdma_engine *sdma = sdmac->sdma;
- int channel = sdmac->channel;
- int ret = -EBUSY;
+ u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
+ int ret = -ENOMEM;
+ unsigned long flags;
- sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys,
- GFP_KERNEL);
- if (!sdmac->bd) {
- ret = -ENOMEM;
- goto out;
+ desc->bd_iram = true;
+ desc->bd = gen_pool_dma_alloc(desc->sdmac->sdma->iram_pool, bd_size,
+ &desc->bd_phys);
+ if (!desc->bd) {
+ desc->bd_iram = false;
+ desc->bd = dma_pool_alloc(desc->sdmac->bd_pool, GFP_ATOMIC,
+ &desc->bd_phys);
+ if (!desc->bd)
+ return ret;
+ }
+ spin_lock_irqsave(&desc->sdmac->vc.lock, flags);
+ desc->sdmac->bd_size_sum += bd_size;
+ spin_unlock_irqrestore(&desc->sdmac->vc.lock, flags);
+
+ memset(desc->bd, 0, bd_size);
+
+ return 0;
+}
+
+static void sdma_free_bd(struct sdma_desc *desc)
+{
+ u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
+ unsigned long flags;
+
+ if (desc->bd) {
+ if (desc->bd_iram)
+ gen_pool_free(desc->sdmac->sdma->iram_pool,
+ (unsigned long)desc->bd, bd_size);
+ else
+ dma_pool_free(desc->sdmac->bd_pool, desc->bd,
+ desc->bd_phys);
+ spin_lock_irqsave(&desc->sdmac->vc.lock, flags);
+ desc->sdmac->bd_size_sum -= bd_size;
+ spin_unlock_irqrestore(&desc->sdmac->vc.lock, flags);
}
+}
+
+static int sdma_request_channel0(struct sdma_engine *sdma)
+{
+ int ret = 0;
+
+ sdma->bd0_iram = true;
+ sdma->bd0 = gen_pool_dma_alloc(sdma->iram_pool, PAGE_SIZE, &sdma->bd0_phys);
+ if (!sdma->bd0) {
+ sdma->bd0_iram = false;
+ sdma->bd0 = dma_alloc_coherent(sdma->dev, PAGE_SIZE,
+ &sdma->bd0_phys, GFP_KERNEL);
+ if (!sdma->bd0) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ memset(sdma->bd0, 0, PAGE_SIZE);
- sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ sdma->channel_control[0].base_bd_ptr = sdma->bd0_phys;
+ sdma->channel_control[0].current_bd_ptr = sdma->bd0_phys;
- sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
+ sdma_set_channel_priority(&sdma->channel[0], MXC_SDMA_DEFAULT_PRIORITY);
return 0;
out:
return ret;
}
-static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
+static struct sdma_desc *to_sdma_desc(struct dma_async_tx_descriptor *t)
+{
+ return container_of(t, struct sdma_desc, vd.tx);
+}
+
+static void sdma_desc_free(struct virt_dma_desc *vd)
{
+ struct sdma_desc *desc = container_of(vd, struct sdma_desc, vd);
+ if (desc) {
+ sdma_free_bd(desc);
+ kfree(desc);
+ }
+}
+
+static int sdma_channel_pause(struct dma_chan *chan)
+{
+ struct sdma_channel *sdmac = to_sdma_chan(chan);
unsigned long flags;
- struct sdma_channel *sdmac = to_sdma_chan(tx->chan);
- dma_cookie_t cookie;
- spin_lock_irqsave(&sdmac->lock, flags);
+ if (!(sdmac->flags & IMX_DMA_SG_LOOP))
+ return -EINVAL;
- cookie = dma_cookie_assign(tx);
+ sdma_disable_channel(chan);
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ sdmac->status = DMA_PAUSED;
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
- spin_unlock_irqrestore(&sdmac->lock, flags);
+ return 0;
+}
- return cookie;
+static int sdma_channel_resume(struct dma_chan *chan)
+{
+ struct sdma_channel *sdmac = to_sdma_chan(chan);
+ struct sdma_engine *sdma = sdmac->sdma;
+ unsigned long flags;
+
+ if (!(sdmac->flags & IMX_DMA_SG_LOOP))
+ return -EINVAL;
+
+ /*
+ * restore back context since context may loss if mega/fast OFF
+ */
+ if (sdma->suspend_off) {
+ if (sdma_load_context(sdmac)) {
+ dev_err(sdmac->sdma->dev, "context load failed.\n");
+ return -EINVAL;
+ }
+ }
+
+ sdma_enable_channel(sdmac->sdma, sdmac->channel);
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ sdmac->status = DMA_IN_PROGRESS;
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
+
+ return 0;
+}
+
+static int sdma_terminate_all(struct dma_chan *chan)
+{
+ struct sdma_channel *sdmac = to_sdma_chan(chan);
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ vchan_get_all_descriptors(&sdmac->vc, &head);
+ while (!list_empty(&sdmac->pending)) {
+ struct sdma_desc *desc = list_first_entry(&sdmac->pending,
+ struct sdma_desc, node);
+
+ list_del(&desc->node);
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
+ sdmac->vc.desc_free(&desc->vd);
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ }
+ if (sdmac->desc)
+ sdmac->desc = NULL;
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
+ vchan_dma_desc_free_list(&sdmac->vc, &head);
+ sdma_disable_channel(chan);
+ sdmac->context_loaded = false;
+
+ return 0;
}
static int sdma_alloc_chan_resources(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct imx_dma_data *data = chan->private;
+ struct imx_dma_data default_data;
int prio, ret;
- if (!data)
- return -EINVAL;
+ ret = clk_enable(sdmac->sdma->clk_ipg);
+ if (ret)
+ return ret;
+ ret = clk_enable(sdmac->sdma->clk_ahb);
+ if (ret)
+ goto disable_clk_ipg;
+
+ /*
+ * dmatest(memcpy) will never call slave_config before prep, so we need
+ * do some job in slave_config in this case.
+ */
+ if (!data) {
+ sdmac->word_size = sdmac->sdma->dma_device.copy_align;
+ default_data.priority = 2;
+ default_data.peripheral_type = IMX_DMATYPE_MEMORY;
+ default_data.dma_request = 0;
+ default_data.dma_request2 = 0;
+ data = &default_data;
+
+ sdma_config_ownership(sdmac, false, true, false);
+ sdma_get_pc(sdmac, IMX_DMATYPE_MEMORY);
+ sdma_load_context(sdmac);
+ }
switch (data->priority) {
case DMA_PRIO_HIGH:
@@ -1116,26 +1387,18 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
sdmac->peripheral_type = data->peripheral_type;
sdmac->event_id0 = data->dma_request;
sdmac->event_id1 = data->dma_request2;
-
- ret = clk_enable(sdmac->sdma->clk_ipg);
- if (ret)
- return ret;
- ret = clk_enable(sdmac->sdma->clk_ahb);
- if (ret)
- goto disable_clk_ipg;
-
- ret = sdma_request_channel(sdmac);
- if (ret)
- goto disable_clk_ahb;
+ sdmac->src_dualfifo = data->src_dualfifo;
+ sdmac->dst_dualfifo = data->dst_dualfifo;
ret = sdma_set_channel_priority(sdmac, prio);
if (ret)
goto disable_clk_ahb;
- dma_async_tx_descriptor_init(&sdmac->desc, chan);
- sdmac->desc.tx_submit = sdma_tx_submit;
- /* txd.flags will be overwritten in prep funcs */
- sdmac->desc.flags = DMA_CTRL_ACK;
+ sdmac->bd_size_sum = 0;
+
+ sdmac->bd_pool = dma_pool_create("bd_pool", chan->device->dev,
+ sizeof(struct sdma_buffer_descriptor),
+ 32, 0);
return 0;
@@ -1151,10 +1414,9 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
- sdma_disable_channel(chan);
+ sdma_terminate_all(chan);
- if (sdmac->event_id0)
- sdma_event_disable(sdmac, sdmac->event_id0);
+ sdma_event_disable(sdmac, sdmac->event_id0);
if (sdmac->event_id1)
sdma_event_disable(sdmac, sdmac->event_id1);
@@ -1163,115 +1425,242 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
sdma_set_channel_priority(sdmac, 0);
- dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
-
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
+
+ dma_pool_destroy(sdmac->bd_pool);
+ sdmac->bd_pool = NULL;
}
-static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
- struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
+ enum dma_transfer_direction direction, u32 bds)
+{
+ struct sdma_desc *desc;
+ /* Now allocate and setup the descriptor. */
+ desc = kzalloc((sizeof(*desc)), GFP_ATOMIC);
+ if (!desc)
+ goto err_out;
+
+ sdmac->status = DMA_IN_PROGRESS;
+ sdmac->direction = direction;
+ sdmac->flags = 0;
+ sdmac->chn_count = 0;
+ sdmac->chn_real_count = 0;
+
+ desc->sdmac = sdmac;
+ desc->num_bd = bds;
+ INIT_LIST_HEAD(&desc->node);
+
+ if (sdma_alloc_bd(desc))
+ goto err_desc_out;
+
+ if (sdma_load_context(sdmac))
+ goto err_desc_out;
+
+ return desc;
+
+err_desc_out:
+ kfree(desc);
+err_out:
+ return NULL;
+}
+
+static int check_bd_buswidth(struct sdma_buffer_descriptor *bd,
+ struct sdma_channel *sdmac, int count,
+ dma_addr_t dma_dst, dma_addr_t dma_src)
+{
+ int ret = 0;
+
+ switch (sdmac->word_size) {
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
+ bd->mode.command = 0;
+ if ((count | dma_dst | dma_src) & 3)
+ ret = -EINVAL;
+ break;
+ case DMA_SLAVE_BUSWIDTH_2_BYTES:
+ bd->mode.command = 2;
+ if ((count | dma_dst | dma_src) & 1)
+ ret = -EINVAL;
+ break;
+ case DMA_SLAVE_BUSWIDTH_1_BYTE:
+ bd->mode.command = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static struct dma_async_tx_descriptor *sdma_prep_memcpy(
+ struct dma_chan *chan, dma_addr_t dma_dst,
+ dma_addr_t dma_src, size_t len, unsigned long flags)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
- int ret, i, count;
int channel = sdmac->channel;
- struct scatterlist *sg;
+ size_t count;
+ int i = 0, param;
+ struct sdma_buffer_descriptor *bd;
+ struct sdma_desc *desc;
- if (sdmac->status == DMA_IN_PROGRESS)
+ if (!chan || !len)
return NULL;
- sdmac->status = DMA_IN_PROGRESS;
- sdmac->flags = 0;
+ dev_dbg(sdma->dev, "memcpy: %pad->%pad, len=%zu, channel=%d.\n",
+ &dma_src, &dma_dst, len, channel);
- sdmac->buf_tail = 0;
- sdmac->buf_ptail = 0;
- sdmac->chn_real_count = 0;
+ desc = sdma_transfer_init(sdmac, DMA_MEM_TO_MEM, len / SDMA_BD_MAX_CNT + 1);
+ if (!desc)
+ goto err_out;
- dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
- sg_len, channel);
+ do {
+ count = min_t(size_t, len, SDMA_BD_MAX_CNT);
+ bd = &desc->bd[i];
+ bd->buffer_addr = dma_src;
+ bd->ext_buffer_addr = dma_dst;
+ bd->mode.count = count;
+ sdmac->chn_count += count;
- sdmac->direction = direction;
- ret = sdma_load_context(sdmac);
- if (ret)
- goto err_out;
+ if (check_bd_buswidth(bd, sdmac, count, dma_dst, dma_src))
+ goto err_bd_out;
- if (sg_len > NUM_BD) {
- dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
- channel, sg_len, NUM_BD);
- ret = -EINVAL;
+ dma_src += count;
+ dma_dst += count;
+ len -= count;
+ i++;
+
+ param = BD_DONE | BD_EXTD | BD_CONT;
+ /* last bd */
+ if (!len) {
+ param |= BD_INTR;
+ param |= BD_LAST;
+ param &= ~BD_CONT;
+ }
+
+ dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%u %s%s\n",
+ i, count, bd->buffer_addr,
+ param & BD_WRAP ? "wrap" : "",
+ param & BD_INTR ? " intr" : "");
+
+ bd->mode.status = param;
+ } while (len);
+
+ return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
+err_bd_out:
+ sdma_free_bd(desc);
+ kfree(desc);
+err_out:
+ return NULL;
+}
+
+/*
+ * Please ensure dst_nents no smaller than src_nents , also every sg_len of
+ * dst_sg node no smaller than src_sg. To simply things, please use the same
+ * size of dst_sg as src_sg.
+ */
+static struct dma_async_tx_descriptor *sdma_prep_sg(
+ struct dma_chan *chan,
+ struct scatterlist *dst_sg, unsigned int dst_nents,
+ struct scatterlist *src_sg, unsigned int src_nents,
+ enum dma_transfer_direction direction, unsigned long flags)
+{
+ struct sdma_channel *sdmac = to_sdma_chan(chan);
+ struct sdma_engine *sdma = sdmac->sdma;
+ int ret, i, count;
+ int channel = sdmac->channel;
+ struct scatterlist *sg_src = src_sg, *sg_dst = dst_sg;
+ struct sdma_desc *desc;
+
+ if (!chan)
+ return NULL;
+
+ dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
+ src_nents, channel);
+
+ desc = sdma_transfer_init(sdmac, direction, src_nents);
+ if (!desc)
goto err_out;
- }
- sdmac->chn_count = 0;
- for_each_sg(sgl, sg, sg_len, i) {
- struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+ for_each_sg(src_sg, sg_src, src_nents, i) {
+ struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
- bd->buffer_addr = sg->dma_address;
+ bd->buffer_addr = sg_src->dma_address;
+
+ if (direction == DMA_MEM_TO_MEM) {
+ BUG_ON(!sg_dst);
+ bd->ext_buffer_addr = sg_dst->dma_address;
+ }
- count = sg_dma_len(sg);
+ count = sg_dma_len(sg_src);
- if (count > 0xffff) {
+ if (count > SDMA_BD_MAX_CNT) {
dev_err(sdma->dev, "SDMA channel %d: maximum bytes for sg entry exceeded: %d > %d\n",
- channel, count, 0xffff);
+ channel, count, SDMA_BD_MAX_CNT);
ret = -EINVAL;
- goto err_out;
+ goto err_bd_out;
}
bd->mode.count = count;
sdmac->chn_count += count;
- if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
- ret = -EINVAL;
- goto err_out;
- }
-
- switch (sdmac->word_size) {
- case DMA_SLAVE_BUSWIDTH_4_BYTES:
- bd->mode.command = 0;
- if (count & 3 || sg->dma_address & 3)
- return NULL;
- break;
- case DMA_SLAVE_BUSWIDTH_2_BYTES:
- bd->mode.command = 2;
- if (count & 1 || sg->dma_address & 1)
- return NULL;
- break;
- case DMA_SLAVE_BUSWIDTH_1_BYTE:
- bd->mode.command = 1;
- break;
- default:
- return NULL;
- }
+ if (direction == DMA_MEM_TO_MEM)
+ ret = check_bd_buswidth(bd, sdmac, count,
+ sg_dst->dma_address,
+ sg_src->dma_address);
+ else
+ ret = check_bd_buswidth(bd, sdmac, count, 0,
+ sg_src->dma_address);
+ if (ret)
+ goto err_bd_out;
param = BD_DONE | BD_EXTD | BD_CONT;
- if (i + 1 == sg_len) {
+ if (i + 1 == src_nents) {
param |= BD_INTR;
param |= BD_LAST;
param &= ~BD_CONT;
}
- dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
- i, count, (u64)sg->dma_address,
+ dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%pad %s%s\n",
+ i, count, &sg_src->dma_address,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
bd->mode.status = param;
+ if (direction == DMA_MEM_TO_MEM)
+ sg_dst = sg_next(sg_dst);
}
- sdmac->num_bd = sg_len;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
- return &sdmac->desc;
+err_bd_out:
+ sdma_free_bd(desc);
+ kfree(desc);
err_out:
- sdmac->status = DMA_ERROR;
+ dev_dbg(sdma->dev, "Can't get desc.\n");
return NULL;
}
+static struct dma_async_tx_descriptor *sdma_prep_memcpy_sg(
+ struct dma_chan *chan,
+ struct scatterlist *dst_sg, unsigned int dst_nents,
+ struct scatterlist *src_sg, unsigned int src_nents,
+ unsigned long flags)
+{
+ return sdma_prep_sg(chan, dst_sg, dst_nents, src_sg, src_nents,
+ DMA_MEM_TO_MEM, flags);
+}
+
+static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
+ struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ return sdma_prep_sg(chan, NULL, 0, sgl, sg_len, direction, flags);
+}
+
static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
@@ -1279,42 +1668,42 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
- int num_periods = buf_len / period_len;
int channel = sdmac->channel;
- int ret, i = 0, buf = 0;
+ int i = 0, buf = 0;
+ int num_periods = 0;
+ struct sdma_desc *desc;
dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
- if (sdmac->status == DMA_IN_PROGRESS)
- return NULL;
-
- sdmac->status = DMA_IN_PROGRESS;
+ if (sdmac->peripheral_type != IMX_DMATYPE_HDMI)
+ num_periods = buf_len / period_len;
+ /* Now allocate and setup the descriptor. */
+ desc = sdma_transfer_init(sdmac, direction, num_periods);
+ if (!desc)
+ goto err_out;
- sdmac->buf_tail = 0;
- sdmac->buf_ptail = 0;
- sdmac->chn_real_count = 0;
sdmac->period_len = period_len;
-
sdmac->flags |= IMX_DMA_SG_LOOP;
- sdmac->direction = direction;
- ret = sdma_load_context(sdmac);
- if (ret)
- goto err_out;
- if (num_periods > NUM_BD) {
- dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
- channel, num_periods, NUM_BD);
- goto err_out;
- }
+ /* for hdmi-audio without BDs */
+ if (sdmac->peripheral_type == IMX_DMATYPE_HDMI)
+ return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
- if (period_len > 0xffff) {
- dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %d > %d\n",
- channel, period_len, 0xffff);
- goto err_out;
+ desc->buf_tail = 0;
+ desc->buf_ptail = 0;
+ sdmac->chn_real_count = 0;
+
+ if (period_len > SDMA_BD_MAX_CNT) {
+ dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %zu > %d\n",
+ channel, period_len, SDMA_BD_MAX_CNT);
+ goto err_bd_out;
}
+ if (sdmac->peripheral_type == IMX_DMATYPE_UART)
+ sdmac->chn_count = period_len;
+
while (buf < buf_len) {
- struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+ struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
bd->buffer_addr = dma_addr;
@@ -1322,7 +1711,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
bd->mode.count = period_len;
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES)
- goto err_out;
+ goto err_bd_out;
if (sdmac->word_size == DMA_SLAVE_BUSWIDTH_4_BYTES)
bd->mode.command = 0;
else
@@ -1332,8 +1721,8 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
if (i + 1 == num_periods)
param |= BD_WRAP;
- dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
- i, period_len, (u64)dma_addr,
+ dev_dbg(sdma->dev, "entry %d: count: %d dma: %pad %s%s\n",
+ i, period_len, &dma_addr,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
@@ -1344,13 +1733,12 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
i++;
}
+ return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
- sdmac->num_bd = num_periods;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
-
- return &sdmac->desc;
+err_bd_out:
+ sdma_free_bd(desc);
+ kfree(desc);
err_out:
- sdmac->status = DMA_ERROR;
return NULL;
}
@@ -1372,6 +1760,12 @@ static int sdma_config(struct dma_chan *chan,
sdmac->watermark_level |= (dmaengine_cfg->dst_maxburst << 16) &
SDMA_WATERMARK_LEVEL_HWML;
sdmac->word_size = dmaengine_cfg->dst_addr_width;
+ } else if (sdmac->peripheral_type == IMX_DMATYPE_HDMI) {
+ sdmac->per_address = dmaengine_cfg->dst_addr;
+ sdmac->per_address2 = dmaengine_cfg->src_addr;
+ sdmac->watermark_level = 0;
+ } else if (dmaengine_cfg->direction == DMA_MEM_TO_MEM) {
+ sdmac->word_size = dmaengine_cfg->dst_addr_width;
} else {
sdmac->per_address = dmaengine_cfg->dst_addr;
sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
@@ -1382,32 +1776,92 @@ static int sdma_config(struct dma_chan *chan,
return sdma_config_channel(chan);
}
+static void sdma_wait_tasklet(struct dma_chan *chan)
+{
+ struct sdma_channel *sdmac = to_sdma_chan(chan);
+
+ tasklet_kill(&sdmac->vc.task);
+}
+
static enum dma_status sdma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
u32 residue;
+ struct virt_dma_desc *vd;
+ struct sdma_desc *desc;
+ enum dma_status ret;
+ unsigned long flags;
- if (sdmac->flags & IMX_DMA_SG_LOOP)
- residue = (sdmac->num_bd - sdmac->buf_ptail) *
- sdmac->period_len - sdmac->chn_real_count;
- else
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (!txstate) {
+ return ret;
+ } else if (ret == DMA_COMPLETE) {
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ txstate->residue = sdmac->chn_count - sdmac->chn_real_count;
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
+ return ret;
+ }
+
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ vd = vchan_find_desc(&sdmac->vc, cookie);
+ desc = to_sdma_desc(&vd->tx);
+ if (vd) {
+ if ((sdmac->flags & IMX_DMA_SG_LOOP)) {
+ if (sdmac->peripheral_type != IMX_DMATYPE_UART)
+ residue = (desc->num_bd - desc->buf_ptail) *
+ sdmac->period_len - sdmac->chn_real_count;
+ else
+ residue = sdmac->chn_count - sdmac->chn_real_count;
+ } else
+ residue = sdmac->chn_count;
+ } else if (sdmac->desc && sdmac->desc->vd.tx.cookie == cookie)
residue = sdmac->chn_count - sdmac->chn_real_count;
+ else
+ residue = 0;
- dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
- residue);
+ txstate->residue = residue;
+ ret = sdmac->status;
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
- return sdmac->status;
+ return ret;
+}
+
+static void sdma_start_desc(struct sdma_channel *sdmac)
+{
+ struct virt_dma_desc *vd = vchan_next_desc(&sdmac->vc);
+ struct sdma_desc *desc;
+ struct sdma_engine *sdma = sdmac->sdma;
+ int channel = sdmac->channel;
+
+ if (!vd) {
+ sdmac->desc = NULL;
+ return;
+ }
+ sdmac->desc = desc = to_sdma_desc(&vd->tx);
+ /*
+ * Do not delete the node in desc_issued list in cyclic mode, otherwise
+ * the desc alloced will never be freed in vchan_dma_desc_free_list
+ */
+ if (!(sdmac->flags & IMX_DMA_SG_LOOP)) {
+ list_add_tail(&sdmac->desc->node, &sdmac->pending);
+ list_del(&vd->node);
+ }
+ sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
+ sdma_enable_channel(sdma, sdmac->channel);
}
static void sdma_issue_pending(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
- struct sdma_engine *sdma = sdmac->sdma;
+ unsigned long flags;
- if (sdmac->status == DMA_IN_PROGRESS)
- sdma_enable_channel(sdma, sdmac->channel);
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ if (vchan_issue_pending(&sdmac->vc) && !sdmac->desc)
+ sdma_start_desc(sdmac);
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
}
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34
@@ -1573,7 +2027,7 @@ static int sdma_get_firmware(struct sdma_engine *sdma,
static int sdma_init(struct sdma_engine *sdma)
{
- int i, ret;
+ int i, ret, ccbsize;
dma_addr_t ccb_phys;
ret = clk_enable(sdma->clk_ipg);
@@ -1586,14 +2040,17 @@ static int sdma_init(struct sdma_engine *sdma)
/* Be sure SDMA has not started yet */
writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
- sdma->channel_control = dma_alloc_coherent(NULL,
- MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) +
- sizeof(struct sdma_context_data),
- &ccb_phys, GFP_KERNEL);
+ ccbsize = MAX_DMA_CHANNELS * (sizeof(struct sdma_channel_control)
+ + sizeof(struct sdma_context_data));
+ sdma->channel_control = gen_pool_dma_alloc(sdma->iram_pool, ccbsize, &ccb_phys);
if (!sdma->channel_control) {
- ret = -ENOMEM;
- goto err_dma_alloc;
+ sdma->channel_control = dma_alloc_coherent(sdma->dev, ccbsize,
+ &ccb_phys, GFP_KERNEL);
+ if (!sdma->channel_control) {
+ ret = -ENOMEM;
+ goto err_dma_alloc;
+ }
}
sdma->context = (void *)sdma->channel_control +
@@ -1613,7 +2070,7 @@ static int sdma_init(struct sdma_engine *sdma)
for (i = 0; i < MAX_DMA_CHANNELS; i++)
writel_relaxed(0, sdma->regs + SDMA_CHNPRI_0 + i * 4);
- ret = sdma_request_channel(&sdma->channel[0]);
+ ret = sdma_request_channel0(sdma);
if (ret)
goto err_dma_alloc;
@@ -1668,17 +2125,11 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
if (dma_spec->args_count != 3)
return NULL;
+ memset(&data, 0, sizeof(data));
+
data.dma_request = dma_spec->args[0];
data.peripheral_type = dma_spec->args[1];
data.priority = dma_spec->args[2];
- /*
- * init dma_request2 to zero, which is not used by the dts.
- * For P2P, dma_request2 is init from dma_request_channel(),
- * chan->private will point to the imx_dma_data, and in
- * device_alloc_chan_resources(), imx_dma_data.dma_request2 will
- * be set to sdmac->event_id1.
- */
- data.dma_request2 = 0;
return dma_request_channel(mask, sdma_filter_fn, &data);
}
@@ -1761,6 +2212,7 @@ static int sdma_probe(struct platform_device *pdev)
dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
+ dma_cap_set(DMA_MEMCPY, sdma->dma_device.cap_mask);
INIT_LIST_HEAD(&sdma->dma_device.channels);
/* Initialize channel parameters */
@@ -1768,24 +2220,26 @@ static int sdma_probe(struct platform_device *pdev)
struct sdma_channel *sdmac = &sdma->channel[i];
sdmac->sdma = sdma;
- spin_lock_init(&sdmac->lock);
-
- sdmac->chan.device = &sdma->dma_device;
- dma_cookie_init(&sdmac->chan);
+ sdmac->context_loaded = false;
sdmac->channel = i;
+ sdmac->status = DMA_IN_PROGRESS;
+ sdmac->vc.desc_free = sdma_desc_free;
+ INIT_LIST_HEAD(&sdmac->pending);
- tasklet_init(&sdmac->tasklet, mxc_sdma_handle_channel_normal,
- (unsigned long) sdmac);
/*
* Add the channel to the DMAC list. Do not add channel 0 though
* because we need it internally in the SDMA driver. This also means
* that channel 0 in dmaengine counting matches sdma channel 1.
*/
if (i)
- list_add_tail(&sdmac->chan.device_node,
- &sdma->dma_device.channels);
+ vchan_init(&sdmac->vc, &sdma->dma_device);
}
+ if (np)
+ sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
+ if (!sdma->iram_pool)
+ dev_warn(&pdev->dev, "no iram assigned, using external mem\n");
+
ret = sdma_init(sdma);
if (ret)
goto err_init;
@@ -1819,23 +2273,30 @@ static int sdma_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "failed to get firmware from device tree\n");
}
}
+ sdma->fw_name = fw_name;
sdma->dma_device.dev = &pdev->dev;
sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources;
sdma->dma_device.device_free_chan_resources = sdma_free_chan_resources;
sdma->dma_device.device_tx_status = sdma_tx_status;
+ sdma->dma_device.device_synchronize = sdma_wait_tasklet;
sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg;
sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic;
sdma->dma_device.device_config = sdma_config;
- sdma->dma_device.device_terminate_all = sdma_disable_channel;
+ sdma->dma_device.device_terminate_all = sdma_terminate_all;
+ sdma->dma_device.device_pause = sdma_channel_pause;
+ sdma->dma_device.device_resume = sdma_channel_resume;
sdma->dma_device.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
sdma->dma_device.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
sdma->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+ sdma->dma_device.device_prep_dma_memcpy = sdma_prep_memcpy;
+ sdma->dma_device.device_prep_dma_sg = sdma_prep_memcpy_sg;
sdma->dma_device.device_issue_pending = sdma_issue_pending;
sdma->dma_device.dev->dma_parms = &sdma->dma_parms;
- dma_set_max_seg_size(sdma->dma_device.dev, 65535);
+ sdma->dma_device.copy_align = 2;
+ dma_set_max_seg_size(sdma->dma_device.dev, SDMA_BD_MAX_CNT);
platform_set_drvdata(pdev, sdma);
@@ -1882,17 +2343,122 @@ static int sdma_remove(struct platform_device *pdev)
for (i = 0; i < MAX_DMA_CHANNELS; i++) {
struct sdma_channel *sdmac = &sdma->channel[i];
- tasklet_kill(&sdmac->tasklet);
+ tasklet_kill(&sdmac->vc.task);
+ sdma_free_chan_resources(&sdmac->vc.chan);
}
platform_set_drvdata(pdev, NULL);
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int sdma_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sdma_engine *sdma = platform_get_drvdata(pdev);
+ int i, ret = 0;
+
+ sdma->suspend_off = false;
+
+ /* Do nothing if not i.MX6SX or i.MX7D*/
+ if (sdma->drvdata != &sdma_imx6sx && sdma->drvdata != &sdma_imx7d
+ && sdma->drvdata != &sdma_imx6ul)
+ return 0;
+
+ clk_enable(sdma->clk_ipg);
+ clk_enable(sdma->clk_ahb);
+
+ ret = sdma_save_restore_context(sdma, true);
+ if (ret) {
+ dev_err(sdma->dev, "save context error!\n");
+ return ret;
+ }
+ /* save regs */
+ for (i = 0; i < MXC_SDMA_SAVED_REG_NUM; i++) {
+ /*
+ * 0x78(SDMA_XTRIG_CONF2+4)~0x100(SDMA_CHNPRI_O) registers are
+ * reserved and can't be touched. Skip these regs.
+ */
+ if (i > SDMA_XTRIG_CONF2 / 4)
+ sdma->save_regs[i] = readl_relaxed(sdma->regs +
+ MXC_SDMA_RESERVED_REG
+ + 4 * i);
+ else
+ sdma->save_regs[i] = readl_relaxed(sdma->regs + 4 * i);
+ }
+
+ clk_disable(sdma->clk_ipg);
+ clk_disable(sdma->clk_ahb);
+
+ return 0;
+}
+
+static int sdma_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sdma_engine *sdma = platform_get_drvdata(pdev);
+ int i, ret;
+
+ /* Do nothing if not i.MX6SX or i.MX7D*/
+ if (sdma->drvdata != &sdma_imx6sx && sdma->drvdata != &sdma_imx7d
+ && sdma->drvdata != &sdma_imx6ul)
+ return 0;
+
+ clk_enable(sdma->clk_ipg);
+ clk_enable(sdma->clk_ahb);
+ /* Do nothing if mega/fast mix not turned off */
+ if (readl_relaxed(sdma->regs + SDMA_H_C0PTR)) {
+ clk_disable(sdma->clk_ipg);
+ clk_disable(sdma->clk_ahb);
+ return 0;
+ }
+
+ sdma->suspend_off = true;
+
+ /* restore regs and load firmware */
+ for (i = 0; i < MXC_SDMA_SAVED_REG_NUM; i++) {
+ /*
+ * 0x78(SDMA_XTRIG_CONF2+4)~0x100(SDMA_CHNPRI_O) registers are
+ * reserved and can't be touched. Skip these regs.
+ */
+ if (i > SDMA_XTRIG_CONF2 / 4)
+ writel_relaxed(sdma->save_regs[i], sdma->regs +
+ MXC_SDMA_RESERVED_REG + 4 * i);
+ else
+ writel_relaxed(sdma->save_regs[i] , sdma->regs + 4 * i);
+ }
+
+ /* prepare priority for channel0 to start */
+ sdma_set_channel_priority(&sdma->channel[0], MXC_SDMA_DEFAULT_PRIORITY);
+
+ ret = sdma_get_firmware(sdma, sdma->fw_name);
+ if (ret) {
+ dev_warn(&pdev->dev, "failed to get firware\n");
+ return ret;
+ }
+
+ ret = sdma_save_restore_context(sdma, false);
+ if (ret) {
+ dev_err(sdma->dev, "restore context error!\n");
+ return ret;
+ }
+
+ clk_disable(sdma->clk_ipg);
+ clk_disable(sdma->clk_ahb);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops sdma_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(sdma_suspend, sdma_resume)
+};
+
static struct platform_driver sdma_driver = {
.driver = {
.name = "imx-sdma",
.of_match_table = sdma_dt_ids,
+ .pm = &sdma_pm_ops,
},
.id_table = sdma_devtypes,
.remove = sdma_remove,
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index e217268c7098..0e90c17a4fdd 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
*
* Refer to drivers/dma/imx-sdma.c
*
@@ -28,7 +28,6 @@
#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/list.h>
-
#include <asm/irq.h>
#include "dmaengine.h"
@@ -135,6 +134,7 @@ enum mxs_dma_devtype {
enum mxs_dma_id {
IMX23_DMA,
IMX28_DMA,
+ IMX7D_DMA,
};
struct mxs_dma_engine {
@@ -142,6 +142,7 @@ struct mxs_dma_engine {
enum mxs_dma_devtype type;
void __iomem *base;
struct clk *clk;
+ struct clk *clk_io;
struct dma_device dma_device;
struct device_dma_parameters dma_parms;
struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS];
@@ -167,6 +168,9 @@ static struct mxs_dma_type mxs_dma_types[] = {
}, {
.id = IMX28_DMA,
.type = MXS_DMA_APBX,
+ }, {
+ .id = IMX7D_DMA,
+ .type = MXS_DMA_APBH,
}
};
@@ -184,6 +188,9 @@ static const struct platform_device_id mxs_dma_ids[] = {
.name = "imx28-dma-apbx",
.driver_data = (kernel_ulong_t) &mxs_dma_types[3],
}, {
+ .name = "imx7d-dma-apbh",
+ .driver_data = (kernel_ulong_t) &mxs_dma_types[4],
+ }, {
/* end of list */
}
};
@@ -193,6 +200,7 @@ static const struct of_device_id mxs_dma_dt_ids[] = {
{ .compatible = "fsl,imx23-dma-apbx", .data = &mxs_dma_ids[1], },
{ .compatible = "fsl,imx28-dma-apbh", .data = &mxs_dma_ids[2], },
{ .compatible = "fsl,imx28-dma-apbx", .data = &mxs_dma_ids[3], },
+ { .compatible = "fsl,imx7d-dma-apbh", .data = &mxs_dma_ids[4], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxs_dma_dt_ids);
@@ -437,6 +445,12 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
if (ret)
goto err_clk;
+ if (mxs_dma->dev_id == IMX7D_DMA) {
+ ret = clk_prepare_enable(mxs_dma->clk_io);
+ if (ret)
+ goto err_clk_unprepare;
+ }
+
mxs_dma_reset_chan(chan);
dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
@@ -447,6 +461,8 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
return 0;
+err_clk_unprepare:
+ clk_disable_unprepare(mxs_dma->clk);
err_clk:
free_irq(mxs_chan->chan_irq, mxs_dma);
err_irq:
@@ -468,6 +484,9 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
dma_free_coherent(mxs_dma->dma_device.dev, CCW_BLOCK_SIZE,
mxs_chan->ccw, mxs_chan->ccw_phys);
+ if (mxs_dma->dev_id == IMX7D_DMA)
+ clk_disable_unprepare(mxs_dma->clk_io);
+
clk_disable_unprepare(mxs_dma->clk);
}
@@ -690,7 +709,7 @@ static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
return mxs_chan->status;
}
-static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
+static int mxs_dma_init(struct mxs_dma_engine *mxs_dma)
{
int ret;
@@ -698,9 +717,15 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
if (ret)
return ret;
+ if (mxs_dma->dev_id == IMX7D_DMA) {
+ ret = clk_prepare_enable(mxs_dma->clk_io);
+ if (ret)
+ goto err_clk_bch;
+ }
+
ret = stmp_reset_block(mxs_dma->base);
if (ret)
- goto err_out;
+ goto err_clk_io;
/* enable apbh burst */
if (dma_is_apbh(mxs_dma)) {
@@ -714,7 +739,10 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS,
mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_SET);
-err_out:
+err_clk_io:
+ if (mxs_dma->dev_id == IMX7D_DMA)
+ clk_disable_unprepare(mxs_dma->clk_io);
+err_clk_bch:
clk_disable_unprepare(mxs_dma->clk);
return ret;
}
@@ -800,9 +828,19 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
if (IS_ERR(mxs_dma->base))
return PTR_ERR(mxs_dma->base);
- mxs_dma->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(mxs_dma->clk))
- return PTR_ERR(mxs_dma->clk);
+ if (mxs_dma->dev_id == IMX7D_DMA) {
+ mxs_dma->clk = devm_clk_get(&pdev->dev, "dma_apbh_bch");
+ if (IS_ERR(mxs_dma->clk))
+ return PTR_ERR(mxs_dma->clk);
+ mxs_dma->clk_io = devm_clk_get(&pdev->dev, "dma_apbh_io");
+ if (IS_ERR(mxs_dma->clk_io))
+ return PTR_ERR(mxs_dma->clk_io);
+
+ } else {
+ mxs_dma->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(mxs_dma->clk))
+ return PTR_ERR(mxs_dma->clk);
+ }
dma_cap_set(DMA_SLAVE, mxs_dma->dma_device.cap_mask);
dma_cap_set(DMA_CYCLIC, mxs_dma->dma_device.cap_mask);
@@ -832,6 +870,7 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
mxs_dma->pdev = pdev;
mxs_dma->dma_device.dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, mxs_dma);
/* mxs_dma gets 65535 bytes maximum sg size */
mxs_dma->dma_device.dev->dma_parms = &mxs_dma->dma_parms;
@@ -869,9 +908,34 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
return 0;
}
+static int mxs_dma_pm_suspend(struct device *dev)
+{
+ /*
+ * We do not save any registers here, since the gpmi will release its
+ * DMA channel.
+ */
+ return 0;
+}
+
+static int mxs_dma_pm_resume(struct device *dev)
+{
+ struct mxs_dma_engine *mxs_dma = dev_get_drvdata(dev);
+ int ret;
+
+ ret = mxs_dma_init(mxs_dma);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static const struct dev_pm_ops mxs_dma_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(mxs_dma_pm_suspend, mxs_dma_pm_resume)
+};
+
static struct platform_driver mxs_dma_driver = {
.driver = {
.name = "mxs-dma",
+ .pm = &mxs_dma_pm_ops,
.of_match_table = mxs_dma_dt_ids,
},
.id_table = mxs_dma_ids,
diff --git a/drivers/dma/pxp/Kconfig b/drivers/dma/pxp/Kconfig
new file mode 100644
index 000000000000..76717f7d78e1
--- /dev/null
+++ b/drivers/dma/pxp/Kconfig
@@ -0,0 +1,22 @@
+config MXC_PXP_V2
+ bool "MXC PxP V2 support"
+ depends on ARM
+ select DMA_ENGINE
+ help
+ Support the PxP (Pixel Pipeline) on i.MX6 DualLite and i.MX6 SoloLite.
+ If unsure, select N.
+
+config MXC_PXP_V3
+ bool "MXC PxP V3 support"
+ depends on ARM
+ select DMA_ENGINE
+ help
+ Support the PxP V3(Pixel Pipeline) on i.MX7D. The PxP V3 supports
+ more functions than PxP V2, dithering, reagl/-D and etc.
+ If unsure, select N.
+
+config MXC_PXP_CLIENT_DEVICE
+ bool "MXC PxP Client Device"
+ default y
+ depends on MXC_PXP_V2 || MXC_PXP_V3
+
diff --git a/drivers/dma/pxp/Makefile b/drivers/dma/pxp/Makefile
new file mode 100644
index 000000000000..42e4ace02fbd
--- /dev/null
+++ b/drivers/dma/pxp/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MXC_PXP_V2) += pxp_dma_v2.o
+obj-$(CONFIG_MXC_PXP_V3) += pxp_dma_v3.o
+obj-$(CONFIG_MXC_PXP_CLIENT_DEVICE) += pxp_device.o
diff --git a/drivers/dma/pxp/pxp_device.c b/drivers/dma/pxp/pxp_device.c
new file mode 100644
index 000000000000..a4a65a45d30c
--- /dev/null
+++ b/drivers/dma/pxp/pxp_device.c
@@ -0,0 +1,878 @@
+/*
+ * Copyright (C) 2010-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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/pxp_device.h>
+#include <linux/atomic.h>
+#include <linux/platform_data/dma-imx.h>
+
+#define BUFFER_HASH_ORDER 4
+
+static struct pxp_buffer_hash bufhash;
+static struct pxp_irq_info irq_info[NR_PXP_VIRT_CHANNEL];
+
+static int pxp_ht_create(struct pxp_buffer_hash *hash, int order)
+{
+ unsigned long i;
+ unsigned long table_size;
+
+ table_size = 1U << order;
+
+ hash->order = order;
+ hash->hash_table = kmalloc(sizeof(*hash->hash_table) * table_size, GFP_KERNEL);
+
+ if (!hash->hash_table) {
+ pr_err("%s: Out of memory for hash table\n", __func__);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < table_size; i++)
+ INIT_HLIST_HEAD(&hash->hash_table[i]);
+
+ return 0;
+}
+
+static int pxp_ht_insert_item(struct pxp_buffer_hash *hash,
+ struct pxp_buf_obj *new)
+{
+ unsigned long hashkey;
+ struct hlist_head *h_list;
+
+ hashkey = hash_long(new->offset >> PAGE_SHIFT, hash->order);
+ h_list = &hash->hash_table[hashkey];
+
+ spin_lock(&hash->hash_lock);
+ hlist_add_head_rcu(&new->item, h_list);
+ spin_unlock(&hash->hash_lock);
+
+ return 0;
+}
+
+static int pxp_ht_remove_item(struct pxp_buffer_hash *hash,
+ struct pxp_buf_obj *obj)
+{
+ spin_lock(&hash->hash_lock);
+ hlist_del_init_rcu(&obj->item);
+ spin_unlock(&hash->hash_lock);
+ return 0;
+}
+
+static struct hlist_node *pxp_ht_find_key(struct pxp_buffer_hash *hash,
+ unsigned long key)
+{
+ struct pxp_buf_obj *entry;
+ struct hlist_head *h_list;
+ unsigned long hashkey;
+
+ hashkey = hash_long(key, hash->order);
+ h_list = &hash->hash_table[hashkey];
+
+ hlist_for_each_entry_rcu(entry, h_list, item) {
+ if (entry->offset >> PAGE_SHIFT == key)
+ return &entry->item;
+ }
+
+ return NULL;
+}
+
+static void pxp_ht_destroy(struct pxp_buffer_hash *hash)
+{
+ kfree(hash->hash_table);
+ hash->hash_table = NULL;
+}
+
+static int pxp_buffer_handle_create(struct pxp_file *file_priv,
+ struct pxp_buf_obj *obj,
+ uint32_t *handlep)
+{
+ int ret;
+
+ idr_preload(GFP_KERNEL);
+ spin_lock(&file_priv->buffer_lock);
+
+ ret = idr_alloc(&file_priv->buffer_idr, obj, 1, 0, GFP_NOWAIT);
+
+ spin_unlock(&file_priv->buffer_lock);
+ idr_preload_end();
+
+ if (ret < 0)
+ return ret;
+
+ *handlep = ret;
+
+ return 0;
+}
+
+static struct pxp_buf_obj *
+pxp_buffer_object_lookup(struct pxp_file *file_priv,
+ uint32_t handle)
+{
+ struct pxp_buf_obj *obj;
+
+ spin_lock(&file_priv->buffer_lock);
+
+ obj = idr_find(&file_priv->buffer_idr, handle);
+ if (!obj) {
+ spin_unlock(&file_priv->buffer_lock);
+ return NULL;
+ }
+
+ spin_unlock(&file_priv->buffer_lock);
+
+ return obj;
+}
+
+static int pxp_buffer_handle_delete(struct pxp_file *file_priv,
+ uint32_t handle)
+{
+ struct pxp_buf_obj *obj;
+
+ spin_lock(&file_priv->buffer_lock);
+
+ obj = idr_find(&file_priv->buffer_idr, handle);
+ if (!obj) {
+ spin_unlock(&file_priv->buffer_lock);
+ return -EINVAL;
+ }
+
+ idr_remove(&file_priv->buffer_idr, handle);
+ spin_unlock(&file_priv->buffer_lock);
+
+ return 0;
+}
+
+static int pxp_channel_handle_create(struct pxp_file *file_priv,
+ struct pxp_chan_obj *obj,
+ uint32_t *handlep)
+{
+ int ret;
+
+ idr_preload(GFP_KERNEL);
+ spin_lock(&file_priv->channel_lock);
+
+ ret = idr_alloc(&file_priv->channel_idr, obj, 0, 0, GFP_NOWAIT);
+
+ spin_unlock(&file_priv->channel_lock);
+ idr_preload_end();
+
+ if (ret < 0)
+ return ret;
+
+ *handlep = ret;
+
+ return 0;
+}
+
+static struct pxp_chan_obj *
+pxp_channel_object_lookup(struct pxp_file *file_priv,
+ uint32_t handle)
+{
+ struct pxp_chan_obj *obj;
+
+ spin_lock(&file_priv->channel_lock);
+
+ obj = idr_find(&file_priv->channel_idr, handle);
+ if (!obj) {
+ spin_unlock(&file_priv->channel_lock);
+ return NULL;
+ }
+
+ spin_unlock(&file_priv->channel_lock);
+
+ return obj;
+}
+
+static int pxp_channel_handle_delete(struct pxp_file *file_priv,
+ uint32_t handle)
+{
+ struct pxp_chan_obj *obj;
+
+ spin_lock(&file_priv->channel_lock);
+
+ obj = idr_find(&file_priv->channel_idr, handle);
+ if (!obj) {
+ spin_unlock(&file_priv->channel_lock);
+ return -EINVAL;
+ }
+
+ idr_remove(&file_priv->channel_idr, handle);
+ spin_unlock(&file_priv->channel_lock);
+
+ return 0;
+}
+
+static int pxp_alloc_dma_buffer(struct pxp_buf_obj *obj)
+{
+ obj->virtual = dma_alloc_coherent(NULL, PAGE_ALIGN(obj->size),
+ (dma_addr_t *) (&obj->offset),
+ GFP_DMA | GFP_KERNEL);
+ pr_debug("[ALLOC] mem alloc phys_addr = 0x%lx\n", obj->offset);
+
+ if (obj->virtual == NULL) {
+ printk(KERN_ERR "Physical memory allocation error!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void pxp_free_dma_buffer(struct pxp_buf_obj *obj)
+{
+ if (obj->virtual != NULL) {
+ dma_free_coherent(0, PAGE_ALIGN(obj->size),
+ obj->virtual, (dma_addr_t)obj->offset);
+ }
+}
+
+static int
+pxp_buffer_object_free(int id, void *ptr, void *data)
+{
+ struct pxp_file *file_priv = data;
+ struct pxp_buf_obj *obj = ptr;
+ int ret;
+
+ ret = pxp_buffer_handle_delete(file_priv, obj->handle);
+ if (ret < 0)
+ return ret;
+
+ pxp_ht_remove_item(&bufhash, obj);
+ pxp_free_dma_buffer(obj);
+ kfree(obj);
+
+ return 0;
+}
+
+static int
+pxp_channel_object_free(int id, void *ptr, void *data)
+{
+ struct pxp_file *file_priv = data;
+ struct pxp_chan_obj *obj = ptr;
+ int chan_id;
+
+ chan_id = obj->chan->chan_id;
+ wait_event(irq_info[chan_id].waitq,
+ atomic_read(&irq_info[chan_id].irq_pending) == 0);
+
+ pxp_channel_handle_delete(file_priv, obj->handle);
+ dma_release_channel(obj->chan);
+ kfree(obj);
+
+ return 0;
+}
+
+static void pxp_free_buffers(struct pxp_file *file_priv)
+{
+ idr_for_each(&file_priv->buffer_idr,
+ &pxp_buffer_object_free, file_priv);
+ idr_destroy(&file_priv->buffer_idr);
+}
+
+static void pxp_free_channels(struct pxp_file *file_priv)
+{
+ idr_for_each(&file_priv->channel_idr,
+ &pxp_channel_object_free, file_priv);
+ idr_destroy(&file_priv->channel_idr);
+}
+
+/* Callback function triggered after PxP receives an EOF interrupt */
+static void pxp_dma_done(void *arg)
+{
+ struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
+ struct dma_chan *chan = tx_desc->txd.chan;
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ int chan_id = pxp_chan->dma_chan.chan_id;
+
+ pr_debug("DMA Done ISR, chan_id %d\n", chan_id);
+
+ atomic_dec(&irq_info[chan_id].irq_pending);
+ irq_info[chan_id].hist_status = tx_desc->hist_status;
+
+ wake_up(&(irq_info[chan_id].waitq));
+}
+
+static int pxp_ioc_config_chan(struct pxp_file *priv, unsigned long arg)
+{
+ struct scatterlist *sg;
+ struct pxp_tx_desc *desc;
+ struct dma_async_tx_descriptor *txd;
+ struct pxp_config_data *pxp_conf;
+ dma_cookie_t cookie;
+ int handle, chan_id;
+ struct dma_chan *chan;
+ struct pxp_chan_obj *obj;
+ int i = 0, j = 0, k = 0, m = 0, length, ret, sg_len;
+
+ pxp_conf = kzalloc(sizeof(*pxp_conf), GFP_KERNEL);
+ if (!pxp_conf)
+ return -ENOMEM;
+
+ ret = copy_from_user(pxp_conf,
+ (struct pxp_config_data *)arg,
+ sizeof(struct pxp_config_data));
+ if (ret) {
+ kfree(pxp_conf);
+ return -EFAULT;
+ }
+
+ handle = pxp_conf->handle;
+ obj = pxp_channel_object_lookup(priv, handle);
+ if (!obj) {
+ kfree(pxp_conf);
+ return -EINVAL;
+ }
+ chan = obj->chan;
+ chan_id = chan->chan_id;
+
+ sg_len = 3;
+ if (pxp_conf->proc_data.engine_enable & PXP_ENABLE_WFE_A)
+ sg_len += 4;
+ if (pxp_conf->proc_data.engine_enable & PXP_ENABLE_WFE_B)
+ sg_len += 4;
+ if (pxp_conf->proc_data.engine_enable & PXP_ENABLE_DITHER)
+ sg_len += 4;
+
+ sg = kmalloc(sizeof(*sg) * sg_len, GFP_KERNEL);
+ if (!sg) {
+ kfree(pxp_conf);
+ return -ENOMEM;
+ }
+
+ sg_init_table(sg, sg_len);
+
+ txd = chan->device->device_prep_slave_sg(chan,
+ sg, sg_len,
+ DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT,
+ NULL);
+ if (!txd) {
+ pr_err("Error preparing a DMA transaction descriptor.\n");
+ kfree(pxp_conf);
+ kfree(sg);
+ return -EIO;
+ }
+
+ txd->callback_param = txd;
+ txd->callback = pxp_dma_done;
+
+ desc = to_tx_desc(txd);
+
+ length = desc->len;
+ for (i = 0; i < length; i++) {
+ if (i == 0) { /* S0 */
+ memcpy(&desc->proc_data,
+ &pxp_conf->proc_data,
+ sizeof(struct pxp_proc_data));
+ memcpy(&desc->layer_param.s0_param,
+ &pxp_conf->s0_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+ } else if (i == 1) { /* Output */
+ memcpy(&desc->layer_param.out_param,
+ &pxp_conf->out_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+ } else if (i == 2) {
+ /* OverLay */
+ memcpy(&desc->layer_param.ol_param,
+ &pxp_conf->ol_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+ } else if ((pxp_conf->proc_data.engine_enable & PXP_ENABLE_WFE_A) && (j < 4)) {
+ for (j = 0; j < 4; j++) {
+ if (j == 0) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_fetch_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_FETCH0;
+ } else if (j == 1) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_fetch_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_FETCH1;
+ } else if (j == 2) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_store_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_STORE0;
+ } else if (j == 3) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_store_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_STORE1;
+ }
+
+ desc = desc->next;
+ }
+
+ i += 4;
+
+ } else if ((pxp_conf->proc_data.engine_enable & PXP_ENABLE_WFE_B) && (m < 4)) {
+ for (m = 0; m < 4; m++) {
+ if (m == 0) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_b_fetch_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_B_FETCH0;
+ } else if (m == 1) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_b_fetch_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_B_FETCH1;
+ } else if (m == 2) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_b_store_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_B_STORE0;
+ } else if (m == 3) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_b_store_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_B_STORE1;
+ }
+
+ desc = desc->next;
+ }
+
+ i += 4;
+
+ } else if ((pxp_conf->proc_data.engine_enable & PXP_ENABLE_DITHER) && (k < 4)) {
+ for (k = 0; k < 4; k++) {
+ if (k == 0) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->dither_fetch_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_DITHER_FETCH0;
+ } else if (k == 1) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->dither_fetch_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_DITHER_FETCH1;
+ } else if (k == 2) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->dither_store_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_DITHER_STORE0;
+ } else if (k == 3) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->dither_store_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_DITHER_STORE1;
+ }
+
+ desc = desc->next;
+ }
+
+ i += 4;
+ }
+ }
+
+ cookie = txd->tx_submit(txd);
+ if (cookie < 0) {
+ pr_err("Error tx_submit\n");
+ kfree(pxp_conf);
+ kfree(sg);
+ return -EIO;
+ }
+
+ atomic_inc(&irq_info[chan_id].irq_pending);
+
+ kfree(pxp_conf);
+ kfree(sg);
+
+ return 0;
+}
+
+static int pxp_device_open(struct inode *inode, struct file *filp)
+{
+ struct pxp_file *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+
+ if (!priv)
+ return -ENOMEM;
+
+ filp->private_data = priv;
+ priv->filp = filp;
+
+ idr_init(&priv->buffer_idr);
+ spin_lock_init(&priv->buffer_lock);
+
+ idr_init(&priv->channel_idr);
+ spin_lock_init(&priv->channel_lock);
+
+ return 0;
+}
+
+static int pxp_device_release(struct inode *inode, struct file *filp)
+{
+ struct pxp_file *priv = filp->private_data;
+
+ if (priv) {
+ pxp_free_channels(priv);
+ pxp_free_buffers(priv);
+ kfree(priv);
+ filp->private_data = NULL;
+ }
+
+ return 0;
+}
+
+static int pxp_device_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ int request_size;
+ struct hlist_node *node;
+ struct pxp_buf_obj *obj;
+
+ request_size = vma->vm_end - vma->vm_start;
+
+ pr_debug("start=0x%x, pgoff=0x%x, size=0x%x\n",
+ (unsigned int)(vma->vm_start), (unsigned int)(vma->vm_pgoff),
+ request_size);
+
+ node = pxp_ht_find_key(&bufhash, vma->vm_pgoff);
+ if (!node)
+ return -EINVAL;
+
+ obj = list_entry(node, struct pxp_buf_obj, item);
+ if (obj->offset + (obj->size >> PAGE_SHIFT) <
+ (vma->vm_pgoff + vma_pages(vma)))
+ return -ENOMEM;
+
+ switch (obj->mem_type) {
+ case MEMORY_TYPE_UNCACHED:
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ break;
+ case MEMORY_TYPE_WC:
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ break;
+ case MEMORY_TYPE_CACHED:
+ break;
+ default:
+ pr_err("%s: invalid memory type!\n", __func__);
+ return -EINVAL;
+ }
+
+ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ request_size, vma->vm_page_prot) ? -EAGAIN : 0;
+}
+
+static bool chan_filter(struct dma_chan *chan, void *arg)
+{
+ if (imx_dma_is_pxp(chan))
+ return true;
+ else
+ return false;
+}
+
+static long pxp_device_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ struct pxp_file *file_priv = filp->private_data;
+
+ switch (cmd) {
+ case PXP_IOC_GET_CHAN:
+ {
+ int ret;
+ struct dma_chan *chan = NULL;
+ dma_cap_mask_t mask;
+ struct pxp_chan_obj *obj = NULL;
+
+ pr_debug("drv: PXP_IOC_GET_CHAN Line %d\n", __LINE__);
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_PRIVATE, mask);
+
+ chan = dma_request_channel(mask, chan_filter, NULL);
+ if (!chan) {
+ pr_err("Unsccessfully received channel!\n");
+ return -EBUSY;
+ }
+
+ pr_debug("Successfully received channel."
+ "chan_id %d\n", chan->chan_id);
+
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+ if (!obj) {
+ dma_release_channel(chan);
+ return -ENOMEM;
+ }
+ obj->chan = chan;
+
+ ret = pxp_channel_handle_create(file_priv, obj,
+ &obj->handle);
+ if (ret) {
+ dma_release_channel(chan);
+ kfree(obj);
+ return ret;
+ }
+
+ init_waitqueue_head(&(irq_info[chan->chan_id].waitq));
+ if (put_user(obj->handle, (u32 __user *) arg)) {
+ pxp_channel_handle_delete(file_priv, obj->handle);
+ dma_release_channel(chan);
+ kfree(obj);
+ return -EFAULT;
+ }
+
+ break;
+ }
+ case PXP_IOC_PUT_CHAN:
+ {
+ int handle;
+ struct pxp_chan_obj *obj;
+
+ if (get_user(handle, (u32 __user *) arg))
+ return -EFAULT;
+
+ pr_debug("%d release handle %d\n", __LINE__, handle);
+
+ obj = pxp_channel_object_lookup(file_priv, handle);
+ if (!obj)
+ return -EINVAL;
+
+ pxp_channel_handle_delete(file_priv, obj->handle);
+ dma_release_channel(obj->chan);
+ kfree(obj);
+
+ break;
+ }
+ case PXP_IOC_CONFIG_CHAN:
+ {
+ int ret;
+
+ ret = pxp_ioc_config_chan(file_priv, arg);
+ if (ret)
+ return ret;
+
+ break;
+ }
+ case PXP_IOC_START_CHAN:
+ {
+ int handle;
+ struct pxp_chan_obj *obj = NULL;
+
+ if (get_user(handle, (u32 __user *) arg))
+ return -EFAULT;
+
+ obj = pxp_channel_object_lookup(file_priv, handle);
+ if (!obj)
+ return -EINVAL;
+
+ dma_async_issue_pending(obj->chan);
+
+ break;
+ }
+ case PXP_IOC_GET_PHYMEM:
+ {
+ struct pxp_mem_desc buffer;
+ struct pxp_buf_obj *obj;
+
+ ret = copy_from_user(&buffer,
+ (struct pxp_mem_desc *)arg,
+ sizeof(struct pxp_mem_desc));
+ if (ret)
+ return -EFAULT;
+
+ pr_debug("[ALLOC] mem alloc size = 0x%x\n",
+ buffer.size);
+
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+ if (!obj)
+ return -ENOMEM;
+ obj->size = buffer.size;
+ obj->mem_type = buffer.mtype;
+
+ ret = pxp_alloc_dma_buffer(obj);
+ if (ret == -1) {
+ printk(KERN_ERR
+ "Physical memory allocation error!\n");
+ kfree(obj);
+ return ret;
+ }
+
+ ret = pxp_buffer_handle_create(file_priv, obj, &obj->handle);
+ if (ret) {
+ pxp_free_dma_buffer(obj);
+ kfree(obj);
+ return ret;
+ }
+ buffer.handle = obj->handle;
+ buffer.phys_addr = obj->offset;
+
+ ret = copy_to_user((void __user *)arg, &buffer,
+ sizeof(struct pxp_mem_desc));
+ if (ret) {
+ pxp_buffer_handle_delete(file_priv, buffer.handle);
+ pxp_free_dma_buffer(obj);
+ kfree(obj);
+ return -EFAULT;
+ }
+
+ pxp_ht_insert_item(&bufhash, obj);
+
+ break;
+ }
+ case PXP_IOC_PUT_PHYMEM:
+ {
+ struct pxp_mem_desc pxp_mem;
+ struct pxp_buf_obj *obj;
+
+ ret = copy_from_user(&pxp_mem,
+ (struct pxp_mem_desc *)arg,
+ sizeof(struct pxp_mem_desc));
+ if (ret)
+ return -EACCES;
+
+ obj = pxp_buffer_object_lookup(file_priv, pxp_mem.handle);
+ if (!obj)
+ return -EINVAL;
+
+ ret = pxp_buffer_handle_delete(file_priv, obj->handle);
+ if (ret)
+ return ret;
+
+ pxp_ht_remove_item(&bufhash, obj);
+ pxp_free_dma_buffer(obj);
+ kfree(obj);
+
+ break;
+ }
+ case PXP_IOC_FLUSH_PHYMEM:
+ {
+ int ret;
+ struct pxp_mem_flush flush;
+ struct pxp_buf_obj *obj;
+
+ ret = copy_from_user(&flush,
+ (struct pxp_mem_flush *)arg,
+ sizeof(struct pxp_mem_flush));
+ if (ret)
+ return -EACCES;
+
+ obj = pxp_buffer_object_lookup(file_priv, flush.handle);
+ if (!obj)
+ return -EINVAL;
+
+ switch (flush.type) {
+ case CACHE_CLEAN:
+ dma_sync_single_for_device(NULL, obj->offset,
+ obj->size, DMA_TO_DEVICE);
+ break;
+ case CACHE_INVALIDATE:
+ dma_sync_single_for_device(NULL, obj->offset,
+ obj->size, DMA_FROM_DEVICE);
+ break;
+ case CACHE_FLUSH:
+ dma_sync_single_for_device(NULL, obj->offset,
+ obj->size, DMA_TO_DEVICE);
+ dma_sync_single_for_device(NULL, obj->offset,
+ obj->size, DMA_FROM_DEVICE);
+ break;
+ default:
+ pr_err("%s: invalid cache flush type\n", __func__);
+ return -EINVAL;
+ }
+
+ break;
+ }
+ case PXP_IOC_WAIT4CMPLT:
+ {
+ struct pxp_chan_handle chan_handle;
+ int ret, chan_id, handle;
+ struct pxp_chan_obj *obj = NULL;
+
+ ret = copy_from_user(&chan_handle,
+ (struct pxp_chan_handle *)arg,
+ sizeof(struct pxp_chan_handle));
+ if (ret)
+ return -EFAULT;
+
+ handle = chan_handle.handle;
+ obj = pxp_channel_object_lookup(file_priv, handle);
+ if (!obj)
+ return -EINVAL;
+ chan_id = obj->chan->chan_id;
+
+ ret = wait_event_interruptible
+ (irq_info[chan_id].waitq,
+ (atomic_read(&irq_info[chan_id].irq_pending) == 0));
+ if (ret < 0)
+ return -ERESTARTSYS;
+
+ chan_handle.hist_status = irq_info[chan_id].hist_status;
+ ret = copy_to_user((struct pxp_chan_handle *)arg,
+ &chan_handle,
+ sizeof(struct pxp_chan_handle));
+ if (ret)
+ return -EFAULT;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct file_operations pxp_device_fops = {
+ .open = pxp_device_open,
+ .release = pxp_device_release,
+ .unlocked_ioctl = pxp_device_ioctl,
+ .mmap = pxp_device_mmap,
+};
+
+static struct miscdevice pxp_device_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "pxp_device",
+ .fops = &pxp_device_fops,
+};
+
+int register_pxp_device(void)
+{
+ int ret;
+
+ ret = misc_register(&pxp_device_miscdev);
+ if (ret)
+ return ret;
+
+ ret = pxp_ht_create(&bufhash, BUFFER_HASH_ORDER);
+ if (ret)
+ return ret;
+ spin_lock_init(&(bufhash.hash_lock));
+
+ pr_debug("PxP_Device registered Successfully\n");
+ return 0;
+}
+
+void unregister_pxp_device(void)
+{
+ pxp_ht_destroy(&bufhash);
+ misc_deregister(&pxp_device_miscdev);
+}
diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c
new file mode 100644
index 000000000000..8ab9e29dc896
--- /dev/null
+++ b/drivers/dma/pxp/pxp_dma_v2.c
@@ -0,0 +1,1865 @@
+/*
+ * Copyright (C) 2010-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+/*
+ * Based on STMP378X PxP driver
+ * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/freezer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pxp_dma.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+
+#include "regs-pxp_v2.h"
+
+#define PXP_DOWNSCALE_THRESHOLD 0x4000
+
+static LIST_HEAD(head);
+static int timeout_in_ms = 600;
+static unsigned int block_size;
+static struct kmem_cache *tx_desc_cache;
+
+struct pxp_dma {
+ struct dma_device dma;
+};
+
+struct pxps {
+ struct platform_device *pdev;
+ struct clk *clk;
+ struct clk *clk_disp_axi; /* may exist on some SoC for gating */
+ void __iomem *base;
+ int irq; /* PXP IRQ to the CPU */
+
+ spinlock_t lock;
+ struct mutex clk_mutex;
+ int clk_stat;
+#define CLK_STAT_OFF 0
+#define CLK_STAT_ON 1
+ int pxp_ongoing;
+ int lut_state;
+
+ struct device *dev;
+ struct pxp_dma pxp_dma;
+ struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
+ struct work_struct work;
+
+ /* describes most recent processing configuration */
+ struct pxp_config_data pxp_conf_state;
+
+ /* to turn clock off when pxp is inactive */
+ struct timer_list clk_timer;
+
+ /* for pxp config dispatch asynchronously*/
+ struct task_struct *dispatch;
+ wait_queue_head_t thread_waitq;
+ struct completion complete;
+};
+
+#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma)
+#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
+#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
+#define to_pxp(id) container_of(id, struct pxps, pxp_dma)
+
+#define PXP_DEF_BUFS 2
+#define PXP_MIN_PIX 8
+
+/*
+ * PXP common functions
+ */
+static void dump_pxp_reg(struct pxps *pxp)
+{
+ dev_dbg(pxp->dev, "PXP_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CTRL));
+ dev_dbg(pxp->dev, "PXP_STAT 0x%x",
+ __raw_readl(pxp->base + HW_PXP_STAT));
+ dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_CTRL));
+ dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_BUF));
+ dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_BUF2));
+ dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_PITCH));
+ dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_LRC));
+ dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC));
+ dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC));
+ dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC));
+ dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC));
+ dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_CTRL));
+ dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_BUF));
+ dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_UBUF));
+ dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_VBUF));
+ dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_PITCH));
+ dev_dbg(pxp->dev, "PXP_PS_BACKGROUND 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND));
+ dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_SCALE));
+ dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_OFFSET));
+ dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW));
+ dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH));
+ dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_CTRL));
+ dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_BUF));
+ dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_PITCH));
+ dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW));
+ dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH));
+ dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF0));
+ dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF1));
+ dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF2));
+ dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_CTRL));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF0));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF1));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF2));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF3));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF4));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF5));
+ dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_LUT_CTRL));
+ dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x",
+ __raw_readl(pxp->base + HW_PXP_LUT_ADDR));
+ dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x",
+ __raw_readl(pxp->base + HW_PXP_LUT_DATA));
+ dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x",
+ __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM));
+ dev_dbg(pxp->dev, "PXP_CFA 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CFA));
+ dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST_CTRL));
+ dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST2_PARAM));
+ dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST4_PARAM));
+ dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST8_PARAM0));
+ dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST8_PARAM1));
+ dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM0));
+ dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM1));
+ dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM2));
+ dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
+ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM3));
+ dev_dbg(pxp->dev, "PXP_POWER 0x%x",
+ __raw_readl(pxp->base + HW_PXP_POWER));
+ dev_dbg(pxp->dev, "PXP_NEXT 0x%x",
+ __raw_readl(pxp->base + HW_PXP_NEXT));
+ dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_DEBUGCTRL));
+ dev_dbg(pxp->dev, "PXP_DEBUG 0x%x",
+ __raw_readl(pxp->base + HW_PXP_DEBUG));
+ dev_dbg(pxp->dev, "PXP_VERSION 0x%x",
+ __raw_readl(pxp->base + HW_PXP_VERSION));
+}
+
+static bool is_yuv(u32 pix_fmt)
+{
+ switch (pix_fmt) {
+ case PXP_PIX_FMT_YUYV:
+ case PXP_PIX_FMT_UYVY:
+ case PXP_PIX_FMT_YVYU:
+ case PXP_PIX_FMT_VYUY:
+ case PXP_PIX_FMT_Y41P:
+ case PXP_PIX_FMT_VUY444:
+ case PXP_PIX_FMT_NV12:
+ case PXP_PIX_FMT_NV21:
+ case PXP_PIX_FMT_NV16:
+ case PXP_PIX_FMT_NV61:
+ case PXP_PIX_FMT_GREY:
+ case PXP_PIX_FMT_GY04:
+ case PXP_PIX_FMT_YVU410P:
+ case PXP_PIX_FMT_YUV410P:
+ case PXP_PIX_FMT_YVU420P:
+ case PXP_PIX_FMT_YUV420P:
+ case PXP_PIX_FMT_YUV420P2:
+ case PXP_PIX_FMT_YVU422P:
+ case PXP_PIX_FMT_YUV422P:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void pxp_soft_reset(struct pxps *pxp)
+{
+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_CLR);
+ __raw_writel(BM_PXP_CTRL_CLKGATE, pxp->base + HW_PXP_CTRL_CLR);
+
+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_SET);
+ while (!(__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_CLKGATE))
+ dev_dbg(pxp->dev, "%s: wait for clock gate off", __func__);
+
+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_CLR);
+ __raw_writel(BM_PXP_CTRL_CLKGATE, pxp->base + HW_PXP_CTRL_CLR);
+}
+
+static void pxp_set_ctrl(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ u32 ctrl;
+ u32 fmt_ctrl;
+ int need_swap = 0; /* to support YUYV and YVYU formats */
+
+ /* Configure S0 input format */
+ switch (pxp_conf->s0_param.pixel_fmt) {
+ case PXP_PIX_FMT_XRGB32:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888;
+ break;
+ case PXP_PIX_FMT_RGB565:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565;
+ break;
+ case PXP_PIX_FMT_RGB555:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555;
+ break;
+ case PXP_PIX_FMT_YUV420P:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
+ break;
+ case PXP_PIX_FMT_YVU420P:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
+ break;
+ case PXP_PIX_FMT_GREY:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8;
+ break;
+ case PXP_PIX_FMT_GY04:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4;
+ break;
+ case PXP_PIX_FMT_VUY444:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV1P444;
+ break;
+ case PXP_PIX_FMT_YUV422P:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422;
+ break;
+ case PXP_PIX_FMT_UYVY:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+ break;
+ case PXP_PIX_FMT_YUYV:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+ need_swap = 1;
+ break;
+ case PXP_PIX_FMT_VYUY:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+ break;
+ case PXP_PIX_FMT_YVYU:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+ need_swap = 1;
+ break;
+ case PXP_PIX_FMT_NV12:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420;
+ break;
+ case PXP_PIX_FMT_NV21:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420;
+ break;
+ case PXP_PIX_FMT_NV16:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422;
+ break;
+ case PXP_PIX_FMT_NV61:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422;
+ break;
+ default:
+ fmt_ctrl = 0;
+ }
+
+ ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl) | BF_PXP_PS_CTRL_SWAP(need_swap);
+ __raw_writel(ctrl, pxp->base + HW_PXP_PS_CTRL_SET);
+
+ /* Configure output format based on out_channel format */
+ switch (pxp_conf->out_param.pixel_fmt) {
+ case PXP_PIX_FMT_XRGB32:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888;
+ break;
+ case PXP_PIX_FMT_BGRA32:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
+ break;
+ case PXP_PIX_FMT_RGB24:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P;
+ break;
+ case PXP_PIX_FMT_RGB565:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565;
+ break;
+ case PXP_PIX_FMT_RGB555:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555;
+ break;
+ case PXP_PIX_FMT_GREY:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8;
+ break;
+ case PXP_PIX_FMT_GY04:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4;
+ break;
+ case PXP_PIX_FMT_UYVY:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
+ break;
+ case PXP_PIX_FMT_VYUY:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
+ break;
+ case PXP_PIX_FMT_NV12:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
+ break;
+ case PXP_PIX_FMT_NV21:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
+ break;
+ case PXP_PIX_FMT_NV16:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
+ break;
+ case PXP_PIX_FMT_NV61:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
+ break;
+ default:
+ fmt_ctrl = 0;
+ }
+
+ ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl);
+ __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL);
+
+ ctrl = 0;
+ if (proc_data->scaling)
+ ;
+ if (proc_data->vflip)
+ ctrl |= BM_PXP_CTRL_VFLIP;
+ if (proc_data->hflip)
+ ctrl |= BM_PXP_CTRL_HFLIP;
+ if (proc_data->rotate)
+ ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90);
+
+ /* In default, the block size is set to 8x8
+ * But block size can be set to 16x16 due to
+ * blocksize variable modification
+ */
+ ctrl |= block_size << 23;
+
+ __raw_writel(ctrl, pxp->base + HW_PXP_CTRL);
+}
+
+static int pxp_start(struct pxps *pxp)
+{
+ __raw_writel(BM_PXP_CTRL_IRQ_ENABLE, pxp->base + HW_PXP_CTRL_SET);
+ __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET);
+ dump_pxp_reg(pxp);
+
+ return 0;
+}
+
+static void pxp_set_outbuf(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *out_params = &pxp_conf->out_param;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+
+ __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF);
+
+ if ((out_params->pixel_fmt == PXP_PIX_FMT_NV12) ||
+ (out_params->pixel_fmt == PXP_PIX_FMT_NV21) ||
+ (out_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
+ (out_params->pixel_fmt == PXP_PIX_FMT_NV61)) {
+ dma_addr_t Y, U;
+
+ Y = out_params->paddr;
+ U = Y + (out_params->width * out_params->height);
+
+ __raw_writel(U, pxp->base + HW_PXP_OUT_BUF2);
+ }
+
+ if (proc_data->rotate == 90 || proc_data->rotate == 270)
+ __raw_writel(BF_PXP_OUT_LRC_X(out_params->height - 1) |
+ BF_PXP_OUT_LRC_Y(out_params->width - 1),
+ pxp->base + HW_PXP_OUT_LRC);
+ else
+ __raw_writel(BF_PXP_OUT_LRC_X(out_params->width - 1) |
+ BF_PXP_OUT_LRC_Y(out_params->height - 1),
+ pxp->base + HW_PXP_OUT_LRC);
+
+ if (out_params->pixel_fmt == PXP_PIX_FMT_RGB24) {
+ __raw_writel(out_params->stride * 3,
+ pxp->base + HW_PXP_OUT_PITCH);
+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_BGRA32 ||
+ out_params->pixel_fmt == PXP_PIX_FMT_XRGB32) {
+ __raw_writel(out_params->stride << 2,
+ pxp->base + HW_PXP_OUT_PITCH);
+ } else if ((out_params->pixel_fmt == PXP_PIX_FMT_RGB565) ||
+ (out_params->pixel_fmt == PXP_PIX_FMT_RGB555)) {
+ __raw_writel(out_params->stride << 1,
+ pxp->base + HW_PXP_OUT_PITCH);
+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
+ (out_params->pixel_fmt == PXP_PIX_FMT_VYUY)) {
+ __raw_writel(out_params->stride << 1,
+ pxp->base + HW_PXP_OUT_PITCH);
+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_GREY ||
+ out_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
+ out_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
+ out_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
+ out_params->pixel_fmt == PXP_PIX_FMT_NV61) {
+ __raw_writel(out_params->stride,
+ pxp->base + HW_PXP_OUT_PITCH);
+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_GY04) {
+ __raw_writel(out_params->stride >> 1,
+ pxp->base + HW_PXP_OUT_PITCH);
+ } else {
+ __raw_writel(0, pxp->base + HW_PXP_OUT_PITCH);
+ }
+
+ /* set global alpha if necessary */
+ if (out_params->global_alpha_enable) {
+ __raw_writel(out_params->global_alpha << 24,
+ pxp->base + HW_PXP_OUT_CTRL_SET);
+ __raw_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT,
+ pxp->base + HW_PXP_OUT_CTRL_SET);
+ }
+}
+
+static void pxp_set_s0colorkey(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+
+ /* Low and high are set equal. V4L does not allow a chromakey range */
+ if (s0_params->color_key_enable == 0 || s0_params->color_key == -1) {
+ /* disable color key */
+ __raw_writel(0xFFFFFF, pxp->base + HW_PXP_PS_CLRKEYLOW);
+ __raw_writel(0, pxp->base + HW_PXP_PS_CLRKEYHIGH);
+ } else {
+ __raw_writel(s0_params->color_key,
+ pxp->base + HW_PXP_PS_CLRKEYLOW);
+ __raw_writel(s0_params->color_key,
+ pxp->base + HW_PXP_PS_CLRKEYHIGH);
+ }
+}
+
+static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no];
+
+ /* Low and high are set equal. V4L does not allow a chromakey range */
+ if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) {
+ __raw_writel(ol_params->color_key,
+ pxp->base + HW_PXP_AS_CLRKEYLOW);
+ __raw_writel(ol_params->color_key,
+ pxp->base + HW_PXP_AS_CLRKEYHIGH);
+ } else {
+ /* disable color key */
+ __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW);
+ __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH);
+ }
+}
+
+static void pxp_set_oln(int layer_no, struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
+ dma_addr_t phys_addr = olparams_data->paddr;
+ u32 pitch = olparams_data->stride ? olparams_data->stride :
+ olparams_data->width;
+
+ __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF);
+
+ /* Fixme */
+ if (olparams_data->width == 0 && olparams_data->height == 0) {
+ __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC);
+ __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_LRC);
+ } else {
+ __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC);
+ __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
+ BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
+ pxp->base + HW_PXP_OUT_AS_LRC);
+ }
+
+ if ((olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) ||
+ (olparams_data->pixel_fmt == PXP_PIX_FMT_XRGB32)) {
+ __raw_writel(pitch << 2,
+ pxp->base + HW_PXP_AS_PITCH);
+ } else if ((olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) ||
+ (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB555)) {
+ __raw_writel(pitch << 1,
+ pxp->base + HW_PXP_AS_PITCH);
+ } else {
+ __raw_writel(0, pxp->base + HW_PXP_AS_PITCH);
+ }
+}
+
+static void pxp_set_olparam(int layer_no, struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
+ u32 olparam;
+
+ olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha);
+ if (olparams_data->pixel_fmt == PXP_PIX_FMT_XRGB32) {
+ olparam |=
+ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888);
+ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) {
+ olparam |=
+ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__ARGB8888);
+ if (!olparams_data->combine_enable) {
+ olparam |=
+ BF_PXP_AS_CTRL_ALPHA_CTRL
+ (BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
+ olparam |= 0x3 << 16;
+ }
+ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
+ olparam |=
+ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565);
+ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB555) {
+ olparam |=
+ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB555);
+ }
+
+ if (olparams_data->global_alpha_enable) {
+ if (olparams_data->global_override) {
+ olparam |=
+ BF_PXP_AS_CTRL_ALPHA_CTRL
+ (BV_PXP_AS_CTRL_ALPHA_CTRL__Override);
+ } else {
+ olparam |=
+ BF_PXP_AS_CTRL_ALPHA_CTRL
+ (BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply);
+ }
+ if (olparams_data->alpha_invert)
+ olparam |= BM_PXP_AS_CTRL_ALPHA_INVERT;
+ }
+ if (olparams_data->color_key_enable)
+ olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY;
+
+ __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL);
+}
+
+static void pxp_set_s0param(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ struct pxp_layer_param *out_params = &pxp_conf->out_param;
+ u32 s0param_ulc, s0param_lrc;
+
+ /* contains the coordinate for the PS in the OUTPUT buffer. */
+ if ((pxp_conf->s0_param).width == 0 &&
+ (pxp_conf->s0_param).height == 0) {
+ __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC);
+ __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC);
+ } else {
+ switch (proc_data->rotate) {
+ case 0:
+ s0param_ulc = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left);
+ s0param_ulc |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top);
+ s0param_lrc = BF_PXP_OUT_PS_LRC_X(((s0param_ulc & BM_PXP_OUT_PS_ULC_X) >> 16) + proc_data->drect.width - 1);
+ s0param_lrc |= BF_PXP_OUT_PS_LRC_Y((s0param_ulc & BM_PXP_OUT_PS_ULC_Y) + proc_data->drect.height - 1);
+ break;
+ case 90:
+ s0param_ulc = BF_PXP_OUT_PS_ULC_Y(out_params->width - (proc_data->drect.left + proc_data->drect.width));
+ s0param_ulc |= BF_PXP_OUT_PS_ULC_X(proc_data->drect.top);
+ s0param_lrc = BF_PXP_OUT_PS_LRC_X(((s0param_ulc & BM_PXP_OUT_PS_ULC_X) >> 16) + proc_data->drect.height - 1);
+ s0param_lrc |= BF_PXP_OUT_PS_LRC_Y((s0param_ulc & BM_PXP_OUT_PS_ULC_Y) + proc_data->drect.width - 1);
+ break;
+ case 180:
+ s0param_ulc = BF_PXP_OUT_PS_ULC_X(out_params->width - (proc_data->drect.left + proc_data->drect.width));
+ s0param_ulc |= BF_PXP_OUT_PS_ULC_Y(out_params->height - (proc_data->drect.top + proc_data->drect.height));
+ s0param_lrc = BF_PXP_OUT_PS_LRC_X(((s0param_ulc & BM_PXP_OUT_PS_ULC_X) >> 16) + proc_data->drect.width - 1);
+ s0param_lrc |= BF_PXP_OUT_PS_LRC_Y((s0param_ulc & BM_PXP_OUT_PS_ULC_Y) + proc_data->drect.height - 1);
+ break;
+ case 270:
+ s0param_ulc = BF_PXP_OUT_PS_ULC_X(out_params->height - (proc_data->drect.top + proc_data->drect.height));
+ s0param_ulc |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.left);
+ s0param_lrc = BF_PXP_OUT_PS_LRC_X(((s0param_ulc & BM_PXP_OUT_PS_ULC_X) >> 16) + proc_data->drect.height - 1);
+ s0param_lrc |= BF_PXP_OUT_PS_LRC_Y((s0param_ulc & BM_PXP_OUT_PS_ULC_Y) + proc_data->drect.width - 1);
+ break;
+ default:
+ return;
+ }
+ __raw_writel(s0param_ulc, pxp->base + HW_PXP_OUT_PS_ULC);
+ __raw_writel(s0param_lrc, pxp->base + HW_PXP_OUT_PS_LRC);
+ }
+
+ /* Since user apps always pass the rotated drect
+ * to this driver, we need to first swap the width
+ * and height which is used to calculate the scale
+ * factors later.
+ */
+ if (proc_data->rotate == 90 || proc_data->rotate == 270) {
+ int temp;
+ temp = proc_data->drect.width;
+ proc_data->drect.width = proc_data->drect.height;
+ proc_data->drect.height = temp;
+ }
+}
+
+/* crop behavior is re-designed in h/w. */
+static void pxp_set_s0crop(struct pxps *pxp)
+{
+ /*
+ * place-holder, it's implemented in other functions in this driver.
+ * Refer to "Clipping source images" section in RM for detail.
+ */
+}
+
+static int pxp_set_scaling(struct pxps *pxp)
+{
+ int ret = 0;
+ u32 xscale, yscale, s0scale;
+ u32 decx, decy, xdec = 0, ydec = 0;
+ struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data;
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+ struct pxp_layer_param *out_params = &pxp_conf->out_param;
+
+ proc_data->scaling = 1;
+
+ if (!proc_data->drect.width || !proc_data->drect.height) {
+ pr_err("Invalid drect width and height passed in\n");
+ return -EINVAL;
+ }
+
+ decx = proc_data->srect.width / proc_data->drect.width;
+ decy = proc_data->srect.height / proc_data->drect.height;
+ if (decx > 1) {
+ if (decx >= 2 && decx < 4) {
+ decx = 2;
+ xdec = 1;
+ } else if (decx >= 4 && decx < 8) {
+ decx = 4;
+ xdec = 2;
+ } else if (decx >= 8) {
+ decx = 8;
+ xdec = 3;
+ }
+ xscale = proc_data->srect.width * 0x1000 /
+ (proc_data->drect.width * decx);
+ } else {
+ if (!is_yuv(s0_params->pixel_fmt) ||
+ (is_yuv(s0_params->pixel_fmt) ==
+ is_yuv(out_params->pixel_fmt)) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_GY04) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_VUY444)) {
+ if ((proc_data->srect.width > 1) &&
+ (proc_data->drect.width > 1))
+ xscale = (proc_data->srect.width - 1) * 0x1000 /
+ (proc_data->drect.width - 1);
+ else
+ xscale = proc_data->srect.width * 0x1000 /
+ proc_data->drect.width;
+ } else {
+ if ((proc_data->srect.width > 2) &&
+ (proc_data->drect.width > 1))
+ xscale = (proc_data->srect.width - 2) * 0x1000 /
+ (proc_data->drect.width - 1);
+ else
+ xscale = proc_data->srect.width * 0x1000 /
+ proc_data->drect.width;
+ }
+ }
+ if (decy > 1) {
+ if (decy >= 2 && decy < 4) {
+ decy = 2;
+ ydec = 1;
+ } else if (decy >= 4 && decy < 8) {
+ decy = 4;
+ ydec = 2;
+ } else if (decy >= 8) {
+ decy = 8;
+ ydec = 3;
+ }
+ yscale = proc_data->srect.height * 0x1000 /
+ (proc_data->drect.height * decy);
+ } else {
+ if ((proc_data->srect.height > 1) &&
+ (proc_data->drect.height > 1))
+ yscale = (proc_data->srect.height - 1) * 0x1000 /
+ (proc_data->drect.height - 1);
+ else
+ yscale = proc_data->srect.height * 0x1000 /
+ proc_data->drect.height;
+ }
+
+ __raw_writel((xdec << 10) | (ydec << 8), pxp->base + HW_PXP_PS_CTRL);
+
+ if (xscale > PXP_DOWNSCALE_THRESHOLD)
+ xscale = PXP_DOWNSCALE_THRESHOLD;
+ if (yscale > PXP_DOWNSCALE_THRESHOLD)
+ yscale = PXP_DOWNSCALE_THRESHOLD;
+ s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) |
+ BF_PXP_PS_SCALE_XSCALE(xscale);
+ __raw_writel(s0scale, pxp->base + HW_PXP_PS_SCALE);
+
+ pxp_set_ctrl(pxp);
+
+ return ret;
+}
+
+static void pxp_set_bg(struct pxps *pxp)
+{
+ __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor,
+ pxp->base + HW_PXP_PS_BACKGROUND);
+}
+
+static void pxp_set_lut(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ int lut_op = pxp_conf->proc_data.lut_transform;
+ u32 reg_val;
+ int i;
+ bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false;
+ u8 *cmap = pxp_conf->proc_data.lut_map;
+ u32 entry_src;
+ u32 pix_val;
+ u8 entry[4];
+
+ /*
+ * If LUT already configured as needed, return...
+ * Unless CMAP is needed and it has been updated.
+ */
+ if ((pxp->lut_state == lut_op) &&
+ !(use_cmap && pxp_conf->proc_data.lut_map_updated))
+ return;
+
+ if (lut_op == PXP_LUT_NONE) {
+ __raw_writel(BM_PXP_LUT_CTRL_BYPASS,
+ pxp->base + HW_PXP_LUT_CTRL);
+ } else if (((lut_op & PXP_LUT_INVERT) != 0)
+ && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) {
+ /* Fill out LUT table with inverted monochromized values */
+
+ /* clear bypass bit, set lookup mode & out mode */
+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+ BF_PXP_LUT_CTRL_OUT_MODE
+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+ pxp->base + HW_PXP_LUT_CTRL);
+
+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+ /* LUT address pointer auto-increments after each data write */
+ for (pix_val = 0; pix_val < 256; pix_val += 4) {
+ for (i = 0; i < 4; i++) {
+ entry_src = use_cmap ?
+ cmap[pix_val + i] : pix_val + i;
+ entry[i] = (entry_src < 0x80) ? 0xFF : 0x00;
+ }
+ reg_val = (entry[3] << 24) | (entry[2] << 16) |
+ (entry[1] << 8) | entry[0];
+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+ }
+ } else if ((lut_op & PXP_LUT_INVERT) != 0) {
+ /* Fill out LUT table with 8-bit inverted values */
+
+ /* clear bypass bit, set lookup mode & out mode */
+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+ BF_PXP_LUT_CTRL_OUT_MODE
+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+ pxp->base + HW_PXP_LUT_CTRL);
+
+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+ /* LUT address pointer auto-increments after each data write */
+ for (pix_val = 0; pix_val < 256; pix_val += 4) {
+ for (i = 0; i < 4; i++) {
+ entry_src = use_cmap ?
+ cmap[pix_val + i] : pix_val + i;
+ entry[i] = ~entry_src & 0xFF;
+ }
+ reg_val = (entry[3] << 24) | (entry[2] << 16) |
+ (entry[1] << 8) | entry[0];
+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+ }
+ } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) {
+ /* Fill out LUT table with 8-bit monochromized values */
+
+ /* clear bypass bit, set lookup mode & out mode */
+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+ BF_PXP_LUT_CTRL_OUT_MODE
+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+ pxp->base + HW_PXP_LUT_CTRL);
+
+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+ /* LUT address pointer auto-increments after each data write */
+ for (pix_val = 0; pix_val < 256; pix_val += 4) {
+ for (i = 0; i < 4; i++) {
+ entry_src = use_cmap ?
+ cmap[pix_val + i] : pix_val + i;
+ entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF;
+ }
+ reg_val = (entry[3] << 24) | (entry[2] << 16) |
+ (entry[1] << 8) | entry[0];
+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+ }
+ } else if (use_cmap) {
+ /* Fill out LUT table using colormap values */
+
+ /* clear bypass bit, set lookup mode & out mode */
+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+ BF_PXP_LUT_CTRL_OUT_MODE
+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+ pxp->base + HW_PXP_LUT_CTRL);
+
+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+ /* LUT address pointer auto-increments after each data write */
+ for (pix_val = 0; pix_val < 256; pix_val += 4) {
+ for (i = 0; i < 4; i++)
+ entry[i] = cmap[pix_val + i];
+ reg_val = (entry[3] << 24) | (entry[2] << 16) |
+ (entry[1] << 8) | entry[0];
+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+ }
+ }
+
+ pxp->lut_state = lut_op;
+}
+
+static void pxp_set_csc(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+ struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0];
+ struct pxp_layer_param *out_params = &pxp_conf->out_param;
+
+ bool input_is_YUV = is_yuv(s0_params->pixel_fmt);
+ bool output_is_YUV = is_yuv(out_params->pixel_fmt);
+
+ if (input_is_YUV && output_is_YUV) {
+ /*
+ * Input = YUV, Output = YUV
+ * No CSC unless we need to do combining
+ */
+ if (ol_params->combine_enable) {
+ /* Must convert to RGB for combining with RGB overlay */
+
+ /* CSC1 - YUV->RGB */
+ __raw_writel(0x04030000, pxp->base + HW_PXP_CSC1_COEF0);
+ __raw_writel(0x01230208, pxp->base + HW_PXP_CSC1_COEF1);
+ __raw_writel(0x076b079c, pxp->base + HW_PXP_CSC1_COEF2);
+
+ /* CSC2 - RGB->YUV */
+ __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
+ __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
+ __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
+ __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
+ __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
+ __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
+ } else {
+ /* Input & Output both YUV, so bypass both CSCs */
+
+ /* CSC1 - Bypass */
+ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
+
+ /* CSC2 - Bypass */
+ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
+ }
+ } else if (input_is_YUV && !output_is_YUV) {
+ /*
+ * Input = YUV, Output = RGB
+ * Use CSC1 to convert to RGB
+ */
+
+ /* CSC1 - YUV->RGB */
+ __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0);
+ __raw_writel(0x01980204, pxp->base + HW_PXP_CSC1_COEF1);
+ __raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2);
+
+ /* CSC2 - Bypass */
+ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
+ } else if (!input_is_YUV && output_is_YUV) {
+ /*
+ * Input = RGB, Output = YUV
+ * Use CSC2 to convert to YUV
+ */
+
+ /* CSC1 - Bypass */
+ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
+
+ /* CSC2 - RGB->YUV */
+ __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
+ __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
+ __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
+ __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
+ __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
+ __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
+ } else {
+ /*
+ * Input = RGB, Output = RGB
+ * Input & Output both RGB, so bypass both CSCs
+ */
+
+ /* CSC1 - Bypass */
+ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
+
+ /* CSC2 - Bypass */
+ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
+ }
+
+ /* YCrCb colorspace */
+ /* Not sure when we use this...no YCrCb formats are defined for PxP */
+ /*
+ __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR);
+ __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR);
+ __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR);
+ */
+
+}
+
+static void pxp_set_s0buf(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ dma_addr_t Y, U, V;
+ dma_addr_t Y1, U1, V1;
+ u32 offset, bpp = 1;
+ u32 pitch = s0_params->stride ? s0_params->stride :
+ s0_params->width;
+
+ Y = s0_params->paddr;
+
+ if ((s0_params->pixel_fmt == PXP_PIX_FMT_RGB565) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_RGB555))
+ bpp = 2;
+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_XRGB32)
+ bpp = 4;
+ offset = (proc_data->srect.top * s0_params->width +
+ proc_data->srect.left) * bpp;
+ /* clipping or cropping */
+ Y1 = Y + offset;
+ __raw_writel(Y1, pxp->base + HW_PXP_PS_BUF);
+ if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)) {
+ /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */
+ int s = 2;
+ if (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)
+ s = 1;
+
+ offset = proc_data->srect.top * s0_params->width / 4 +
+ proc_data->srect.left / 2;
+ U = Y + (s0_params->width * s0_params->height);
+ U1 = U + offset;
+ V = U + ((s0_params->width * s0_params->height) >> s);
+ V1 = V + offset;
+ if (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) {
+ __raw_writel(V1, pxp->base + HW_PXP_PS_UBUF);
+ __raw_writel(U1, pxp->base + HW_PXP_PS_VBUF);
+ } else {
+ __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
+ __raw_writel(V1, pxp->base + HW_PXP_PS_VBUF);
+ }
+ } else if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV12) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_NV21) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) {
+ int s = 2;
+ if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_NV61))
+ s = 1;
+
+ offset = (proc_data->srect.top * s0_params->width +
+ proc_data->srect.left) / s;
+ U = Y + (s0_params->width * s0_params->height);
+ U1 = U + offset;
+
+ __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
+ }
+
+ /* TODO: only support RGB565, Y8, Y4, YUV420 */
+ if (s0_params->pixel_fmt == PXP_PIX_FMT_GREY ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_NV61 ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) {
+ __raw_writel(pitch, pxp->base + HW_PXP_PS_PITCH);
+ }
+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_GY04)
+ __raw_writel(pitch >> 1,
+ pxp->base + HW_PXP_PS_PITCH);
+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_XRGB32 ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_VUY444)
+ __raw_writel(pitch << 2,
+ pxp->base + HW_PXP_PS_PITCH);
+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_YUYV ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_VYUY ||
+ s0_params->pixel_fmt == PXP_PIX_FMT_YVYU)
+ __raw_writel(pitch << 1,
+ pxp->base + HW_PXP_PS_PITCH);
+ else if ((s0_params->pixel_fmt == PXP_PIX_FMT_RGB565) ||
+ (s0_params->pixel_fmt == PXP_PIX_FMT_RGB555))
+ __raw_writel(pitch << 1,
+ pxp->base + HW_PXP_PS_PITCH);
+ else
+ __raw_writel(0, pxp->base + HW_PXP_PS_PITCH);
+}
+
+/**
+ * pxp_config() - configure PxP for a processing task
+ * @pxps: PXP context.
+ * @pxp_chan: PXP channel.
+ * @return: 0 on success or negative error code on failure.
+ */
+static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
+{
+ /* Configure PxP regs */
+ pxp_set_ctrl(pxp);
+ pxp_set_s0param(pxp);
+ pxp_set_s0crop(pxp);
+ pxp_set_scaling(pxp);
+ pxp_set_s0colorkey(pxp);
+
+ pxp_set_oln(0, pxp);
+ pxp_set_olparam(0, pxp);
+ pxp_set_olcolorkey(0, pxp);
+
+ pxp_set_csc(pxp);
+ pxp_set_bg(pxp);
+ pxp_set_lut(pxp);
+
+ pxp_set_s0buf(pxp);
+ pxp_set_outbuf(pxp);
+
+ return 0;
+}
+
+static void pxp_clk_enable(struct pxps *pxp)
+{
+ mutex_lock(&pxp->clk_mutex);
+
+ if (pxp->clk_stat == CLK_STAT_ON) {
+ mutex_unlock(&pxp->clk_mutex);
+ return;
+ }
+
+ pm_runtime_get_sync(pxp->dev);
+
+ if (pxp->clk_disp_axi)
+ clk_prepare_enable(pxp->clk_disp_axi);
+ clk_prepare_enable(pxp->clk);
+ pxp->clk_stat = CLK_STAT_ON;
+
+ mutex_unlock(&pxp->clk_mutex);
+}
+
+static void pxp_clk_disable(struct pxps *pxp)
+{
+ unsigned long flags;
+
+ mutex_lock(&pxp->clk_mutex);
+
+ if (pxp->clk_stat == CLK_STAT_OFF) {
+ mutex_unlock(&pxp->clk_mutex);
+ return;
+ }
+
+ spin_lock_irqsave(&pxp->lock, flags);
+ if ((pxp->pxp_ongoing == 0) && list_empty(&head)) {
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ clk_disable_unprepare(pxp->clk);
+ if (pxp->clk_disp_axi)
+ clk_disable_unprepare(pxp->clk_disp_axi);
+ pxp->clk_stat = CLK_STAT_OFF;
+ pm_runtime_put_sync_suspend(pxp->dev);
+ } else
+ spin_unlock_irqrestore(&pxp->lock, flags);
+
+ mutex_unlock(&pxp->clk_mutex);
+}
+
+static inline void clkoff_callback(struct work_struct *w)
+{
+ struct pxps *pxp = container_of(w, struct pxps, work);
+
+ pxp_clk_disable(pxp);
+}
+
+static void pxp_clkoff_timer(unsigned long arg)
+{
+ struct pxps *pxp = (struct pxps *)arg;
+
+ if ((pxp->pxp_ongoing == 0) && list_empty(&head))
+ schedule_work(&pxp->work);
+ else
+ mod_timer(&pxp->clk_timer,
+ jiffies + msecs_to_jiffies(timeout_in_ms));
+}
+
+static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan)
+{
+ return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list);
+}
+
+/* called with pxp_chan->lock held */
+static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
+{
+ struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device);
+ struct pxps *pxp = to_pxp(pxp_dma);
+ struct pxp_tx_desc *desc;
+ struct pxp_tx_desc *child;
+ int i = 0;
+
+ memset(&pxp->pxp_conf_state.s0_param, 0, sizeof(struct pxp_layer_param));
+ memset(&pxp->pxp_conf_state.out_param, 0, sizeof(struct pxp_layer_param));
+ memset(pxp->pxp_conf_state.ol_param, 0, sizeof(struct pxp_layer_param) * 8);
+ memset(&pxp->pxp_conf_state.proc_data, 0, sizeof(struct pxp_proc_data));
+ /* S0 */
+ desc = list_first_entry(&head, struct pxp_tx_desc, list);
+ memcpy(&pxp->pxp_conf_state.s0_param,
+ &desc->layer_param.s0_param, sizeof(struct pxp_layer_param));
+ memcpy(&pxp->pxp_conf_state.proc_data,
+ &desc->proc_data, sizeof(struct pxp_proc_data));
+
+ /* Save PxP configuration */
+ list_for_each_entry(child, &desc->tx_list, list) {
+ if (i == 0) { /* Output */
+ memcpy(&pxp->pxp_conf_state.out_param,
+ &child->layer_param.out_param,
+ sizeof(struct pxp_layer_param));
+ } else { /* Overlay */
+ memcpy(&pxp->pxp_conf_state.ol_param[i - 1],
+ &child->layer_param.ol_param,
+ sizeof(struct pxp_layer_param));
+ }
+
+ i++;
+ }
+ pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__,
+ pxp->pxp_conf_state.s0_param.width,
+ pxp->pxp_conf_state.s0_param.height,
+ pxp->pxp_conf_state.s0_param.paddr);
+ pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__,
+ pxp->pxp_conf_state.out_param.width,
+ pxp->pxp_conf_state.out_param.height,
+ pxp->pxp_conf_state.out_param.paddr);
+}
+
+static void pxpdma_dostart_work(struct pxps *pxp)
+{
+ struct pxp_channel *pxp_chan = NULL;
+ unsigned long flags;
+ struct pxp_tx_desc *desc = NULL;
+
+ spin_lock_irqsave(&pxp->lock, flags);
+
+ desc = list_entry(head.next, struct pxp_tx_desc, list);
+ pxp_chan = to_pxp_channel(desc->txd.chan);
+
+ __pxpdma_dostart(pxp_chan);
+
+ /* Configure PxP */
+ pxp_config(pxp, pxp_chan);
+
+ pxp_start(pxp);
+
+ spin_unlock_irqrestore(&pxp->lock, flags);
+}
+
+static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct pxps *pxp)
+{
+ unsigned long flags;
+ struct pxp_tx_desc *desc = NULL;
+
+ do {
+ desc = pxpdma_first_queued(pxp_chan);
+ spin_lock_irqsave(&pxp->lock, flags);
+ list_move_tail(&desc->list, &head);
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ } while (!list_empty(&pxp_chan->queue));
+}
+
+static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct pxp_tx_desc *desc = to_tx_desc(tx);
+ struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan);
+ dma_cookie_t cookie;
+
+ dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n");
+
+ /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */
+ spin_lock(&pxp_chan->lock);
+
+ cookie = pxp_chan->dma_chan.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+
+ /* from dmaengine.h: "last cookie value returned to client" */
+ pxp_chan->dma_chan.cookie = cookie;
+ tx->cookie = cookie;
+
+ /* Here we add the tx descriptor to our PxP task queue. */
+ list_add_tail(&desc->list, &pxp_chan->queue);
+
+ spin_unlock(&pxp_chan->lock);
+
+ dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n");
+
+ return cookie;
+}
+
+/**
+ * pxp_init_channel() - initialize a PXP channel.
+ * @pxp_dma: PXP DMA context.
+ * @pchan: pointer to the channel object.
+ * @return 0 on success or negative error code on failure.
+ */
+static int pxp_init_channel(struct pxp_dma *pxp_dma,
+ struct pxp_channel *pxp_chan)
+{
+ int ret = 0;
+
+ /*
+ * We are using _virtual_ channel here.
+ * Each channel contains all parameters of corresponding layers
+ * for one transaction; each layer is represented as one descriptor
+ * (i.e., pxp_tx_desc) here.
+ */
+
+ INIT_LIST_HEAD(&pxp_chan->queue);
+
+ return ret;
+}
+
+static irqreturn_t pxp_irq(int irq, void *dev_id)
+{
+ struct pxps *pxp = dev_id;
+ struct pxp_channel *pxp_chan;
+ struct pxp_tx_desc *desc;
+ struct pxp_tx_desc *child, *_child;
+ dma_async_tx_callback callback;
+ void *callback_param;
+ unsigned long flags;
+ u32 hist_status;
+
+ dump_pxp_reg(pxp);
+
+ hist_status =
+ __raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS;
+
+ __raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR);
+
+ /* set the SFTRST bit to be 1 to reset
+ * the PXP block to its default state.
+ */
+ pxp_soft_reset(pxp);
+
+ spin_lock_irqsave(&pxp->lock, flags);
+
+ if (list_empty(&head)) {
+ pxp->pxp_ongoing = 0;
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ return IRQ_NONE;
+ }
+
+ /* Get descriptor and call callback */
+ desc = list_entry(head.next, struct pxp_tx_desc, list);
+ pxp_chan = to_pxp_channel(desc->txd.chan);
+
+ pxp_chan->completed = desc->txd.cookie;
+
+ callback = desc->txd.callback;
+ callback_param = desc->txd.callback_param;
+
+ /* Send histogram status back to caller */
+ desc->hist_status = hist_status;
+
+ if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
+ callback(callback_param);
+
+ pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+
+ list_for_each_entry_safe(child, _child, &desc->tx_list, list) {
+ list_del_init(&child->list);
+ kmem_cache_free(tx_desc_cache, (void *)child);
+ }
+ list_del_init(&desc->list);
+ kmem_cache_free(tx_desc_cache, (void *)desc);
+
+ complete(&pxp->complete);
+ pxp->pxp_ongoing = 0;
+ mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
+
+ spin_unlock_irqrestore(&pxp->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+/* allocate/free dma tx descriptor dynamically*/
+static struct pxp_tx_desc *pxpdma_desc_alloc(struct pxp_channel *pxp_chan)
+{
+ struct pxp_tx_desc *desc = NULL;
+ struct dma_async_tx_descriptor *txd = NULL;
+
+ desc = kmem_cache_alloc(tx_desc_cache, GFP_KERNEL | __GFP_ZERO);
+ if (desc == NULL)
+ return NULL;
+
+ INIT_LIST_HEAD(&desc->list);
+ INIT_LIST_HEAD(&desc->tx_list);
+ txd = &desc->txd;
+ dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan);
+ txd->tx_submit = pxp_tx_submit;
+
+ return desc;
+}
+
+/* Allocate and initialise a transfer descriptor. */
+static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan,
+ struct scatterlist
+ *sgl,
+ unsigned int sg_len,
+ enum
+ dma_transfer_direction
+ direction,
+ unsigned long tx_flags,
+ void *context)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+ struct pxps *pxp = to_pxp(pxp_dma);
+ struct pxp_tx_desc *pos = NULL, *next = NULL;
+ struct pxp_tx_desc *desc = NULL;
+ struct pxp_tx_desc *first = NULL, *prev = NULL;
+ struct scatterlist *sg;
+ dma_addr_t phys_addr;
+ int i;
+
+ if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
+ dev_err(chan->device->dev, "Invalid DMA direction %d!\n",
+ direction);
+ return NULL;
+ }
+
+ if (unlikely(sg_len < 2))
+ return NULL;
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ desc = pxpdma_desc_alloc(pxp_chan);
+ if (!desc) {
+ dev_err(chan->device->dev, "no enough memory to allocate tx descriptor\n");
+
+ if (first) {
+ list_for_each_entry_safe(pos, next, &first->tx_list, list) {
+ list_del_init(&pos->list);
+ kmem_cache_free(tx_desc_cache, (void*)pos);
+ }
+ list_del_init(&first->list);
+ kmem_cache_free(tx_desc_cache, (void*)first);
+ }
+
+ return NULL;
+ }
+
+ phys_addr = sg_dma_address(sg);
+
+ if (!first) {
+ first = desc;
+
+ desc->layer_param.s0_param.paddr = phys_addr;
+ } else {
+ list_add_tail(&desc->list, &first->tx_list);
+ prev->next = desc;
+ desc->next = NULL;
+
+ if (i == 1)
+ desc->layer_param.out_param.paddr = phys_addr;
+ else
+ desc->layer_param.ol_param.paddr = phys_addr;
+ }
+
+ prev = desc;
+ }
+
+ pxp->pxp_conf_state.layer_nr = sg_len;
+ first->txd.flags = tx_flags;
+ first->len = sg_len;
+ pr_debug("%s:%d first %p, first->len %d, flags %08x\n",
+ __func__, __LINE__, first, first->len, first->txd.flags);
+
+ return &first->txd;
+}
+
+static void pxp_issue_pending(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+ struct pxps *pxp = to_pxp(pxp_dma);
+
+ spin_lock(&pxp_chan->lock);
+
+ if (list_empty(&pxp_chan->queue)) {
+ spin_unlock(&pxp_chan->lock);
+ return;
+ }
+
+ pxpdma_dequeue(pxp_chan, pxp);
+ pxp_chan->status = PXP_CHANNEL_READY;
+
+ spin_unlock(&pxp_chan->lock);
+
+ pxp_clk_enable(pxp);
+ wake_up_interruptible(&pxp->thread_waitq);
+}
+
+static void __pxp_terminate_all(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+ pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+}
+
+static int pxp_device_terminate_all(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+ spin_lock(&pxp_chan->lock);
+ __pxp_terminate_all(chan);
+ spin_unlock(&pxp_chan->lock);
+
+ return 0;
+}
+
+static int pxp_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+ int ret;
+
+ /* dmaengine.c now guarantees to only offer free channels */
+ BUG_ON(chan->client_count > 1);
+ WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE);
+
+ chan->cookie = 1;
+ pxp_chan->completed = -ENXIO;
+
+ pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id);
+ ret = pxp_init_channel(pxp_dma, pxp_chan);
+ if (ret < 0)
+ goto err_chan;
+
+ pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+
+ dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
+ chan->chan_id, pxp_chan->eof_irq);
+
+ return ret;
+
+err_chan:
+ return ret;
+}
+
+static void pxp_free_chan_resources(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+ spin_lock(&pxp_chan->lock);
+
+ __pxp_terminate_all(chan);
+
+ pxp_chan->status = PXP_CHANNEL_FREE;
+
+ spin_unlock(&pxp_chan->lock);
+}
+
+static enum dma_status pxp_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+ if (cookie != chan->cookie)
+ return DMA_ERROR;
+
+ if (txstate) {
+ txstate->last = pxp_chan->completed;
+ txstate->used = chan->cookie;
+ txstate->residue = 0;
+ }
+ return DMA_COMPLETE;
+}
+
+static int pxp_dma_init(struct pxps *pxp)
+{
+ struct pxp_dma *pxp_dma = &pxp->pxp_dma;
+ struct dma_device *dma = &pxp_dma->dma;
+ int i;
+
+ dma_cap_set(DMA_SLAVE, dma->cap_mask);
+ dma_cap_set(DMA_PRIVATE, dma->cap_mask);
+
+ /* Compulsory common fields */
+ dma->dev = pxp->dev;
+ dma->device_alloc_chan_resources = pxp_alloc_chan_resources;
+ dma->device_free_chan_resources = pxp_free_chan_resources;
+ dma->device_tx_status = pxp_tx_status;
+ dma->device_issue_pending = pxp_issue_pending;
+
+ /* Compulsory for DMA_SLAVE fields */
+ dma->device_prep_slave_sg = pxp_prep_slave_sg;
+ dma->device_terminate_all = pxp_device_terminate_all;
+
+ /* Initialize PxP Channels */
+ INIT_LIST_HEAD(&dma->channels);
+ for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) {
+ struct pxp_channel *pxp_chan = pxp->channel + i;
+ struct dma_chan *dma_chan = &pxp_chan->dma_chan;
+
+ spin_lock_init(&pxp_chan->lock);
+
+ /* Only one EOF IRQ for PxP, shared by all channels */
+ pxp_chan->eof_irq = pxp->irq;
+ pxp_chan->status = PXP_CHANNEL_FREE;
+ pxp_chan->completed = -ENXIO;
+ snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name),
+ "PXP EOF %d", i);
+
+ dma_chan->device = &pxp_dma->dma;
+ dma_chan->cookie = 1;
+ dma_chan->chan_id = i;
+ list_add_tail(&dma_chan->device_node, &dma->channels);
+ }
+
+ return dma_async_device_register(&pxp_dma->dma);
+}
+
+static ssize_t clk_off_timeout_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", timeout_in_ms);
+}
+
+static ssize_t clk_off_timeout_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val;
+ if (sscanf(buf, "%d", &val) > 0) {
+ timeout_in_ms = val;
+ return count;
+ }
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show,
+ clk_off_timeout_store);
+
+static ssize_t block_size_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", block_size);
+}
+
+static ssize_t block_size_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char **last = NULL;
+
+ block_size = simple_strtoul(buf, last, 0);
+ if (block_size > 1)
+ block_size = 1;
+
+ return count;
+}
+static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO,
+ block_size_show, block_size_store);
+
+static const struct of_device_id imx_pxpdma_dt_ids[] = {
+ { .compatible = "fsl,imx6dl-pxp-dma", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids);
+
+static int has_pending_task(struct pxps *pxp, struct pxp_channel *task)
+{
+ int found;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pxp->lock, flags);
+ found = !list_empty(&head);
+ spin_unlock_irqrestore(&pxp->lock, flags);
+
+ return found;
+}
+
+static int pxp_dispatch_thread(void *argv)
+{
+ struct pxps *pxp = (struct pxps *)argv;
+ struct pxp_channel *pending = NULL;
+ unsigned long flags;
+
+ set_freezable();
+
+ while (!kthread_should_stop()) {
+ int ret;
+ ret = wait_event_freezable(pxp->thread_waitq,
+ has_pending_task(pxp, pending) ||
+ kthread_should_stop());
+ if (ret < 0)
+ continue;
+
+ if (kthread_should_stop())
+ break;
+
+ spin_lock_irqsave(&pxp->lock, flags);
+ pxp->pxp_ongoing = 1;
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ init_completion(&pxp->complete);
+ pxpdma_dostart_work(pxp);
+ ret = wait_for_completion_timeout(&pxp->complete, 2 * HZ);
+ if (ret == 0) {
+ printk(KERN_EMERG "%s: task is timeout\n\n", __func__);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int pxp_probe(struct platform_device *pdev)
+{
+ struct pxps *pxp;
+ struct resource *res;
+ int irq;
+ int err = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (!res || irq < 0) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL);
+ if (!pxp) {
+ dev_err(&pdev->dev, "failed to allocate control object\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ pxp->dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, pxp);
+ pxp->irq = irq;
+
+ spin_lock_init(&pxp->lock);
+ mutex_init(&pxp->clk_mutex);
+
+ pxp->base = devm_ioremap_resource(&pdev->dev, res);
+ if (pxp->base == NULL) {
+ dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+ err = -ENODEV;
+ goto exit;
+ }
+
+ pxp->pdev = pdev;
+
+ pxp->clk_disp_axi = devm_clk_get(&pdev->dev, "disp-axi");
+ if (IS_ERR(pxp->clk_disp_axi))
+ pxp->clk_disp_axi = NULL;
+ pxp->clk = devm_clk_get(&pdev->dev, "pxp-axi");
+
+ err = devm_request_irq(&pdev->dev, pxp->irq, pxp_irq, 0,
+ "pxp-dmaengine", pxp);
+ if (err)
+ goto exit;
+ /* Initialize DMA engine */
+ err = pxp_dma_init(pxp);
+ if (err < 0)
+ goto exit;
+
+ if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) {
+ dev_err(&pdev->dev,
+ "Unable to create file from clk_off_timeout\n");
+ goto exit;
+ }
+
+ device_create_file(&pdev->dev, &dev_attr_block_size);
+ pxp_clk_enable(pxp);
+ dump_pxp_reg(pxp);
+ pxp_clk_disable(pxp);
+
+ INIT_WORK(&pxp->work, clkoff_callback);
+ init_timer(&pxp->clk_timer);
+ pxp->clk_timer.function = pxp_clkoff_timer;
+ pxp->clk_timer.data = (unsigned long)pxp;
+
+ init_waitqueue_head(&pxp->thread_waitq);
+ /* allocate a kernel thread to dispatch pxp conf */
+ pxp->dispatch = kthread_run(pxp_dispatch_thread, pxp, "pxp_dispatch");
+ if (IS_ERR(pxp->dispatch)) {
+ err = PTR_ERR(pxp->dispatch);
+ goto exit;
+ }
+ tx_desc_cache = kmem_cache_create("tx_desc", sizeof(struct pxp_tx_desc),
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!tx_desc_cache) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ register_pxp_device();
+
+ pm_runtime_enable(pxp->dev);
+
+exit:
+ if (err)
+ dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n");
+ return err;
+}
+
+static int pxp_remove(struct platform_device *pdev)
+{
+ struct pxps *pxp = platform_get_drvdata(pdev);
+
+ unregister_pxp_device();
+ kmem_cache_destroy(tx_desc_cache);
+ kthread_stop(pxp->dispatch);
+ cancel_work_sync(&pxp->work);
+ del_timer_sync(&pxp->clk_timer);
+ clk_disable_unprepare(pxp->clk);
+ if (pxp->clk_disp_axi)
+ clk_disable_unprepare(pxp->clk_disp_axi);
+ device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout);
+ device_remove_file(&pdev->dev, &dev_attr_block_size);
+ dma_async_device_unregister(&(pxp->pxp_dma.dma));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pxp_suspend(struct device *dev)
+{
+ struct pxps *pxp = dev_get_drvdata(dev);
+
+ pxp_clk_enable(pxp);
+ while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
+ ;
+
+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
+ pxp_clk_disable(pxp);
+
+ return 0;
+}
+
+static int pxp_resume(struct device *dev)
+{
+ struct pxps *pxp = dev_get_drvdata(dev);
+
+ pxp_clk_enable(pxp);
+ /* Pull PxP out of reset */
+ __raw_writel(0, pxp->base + HW_PXP_CTRL);
+ pxp_clk_disable(pxp);
+
+ return 0;
+}
+#else
+#define pxp_suspend NULL
+#define pxp_resume NULL
+#endif
+
+#ifdef CONFIG_PM
+static int pxp_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pxp busfreq high release.\n");
+ return 0;
+}
+
+static int pxp_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pxp busfreq high request.\n");
+ return 0;
+}
+#else
+#define pxp_runtime_suspend NULL
+#define pxp_runtime_resume NULL
+#endif
+
+static const struct dev_pm_ops pxp_pm_ops = {
+ SET_RUNTIME_PM_OPS(pxp_runtime_suspend, pxp_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pxp_suspend, pxp_resume)
+};
+
+static struct platform_driver pxp_driver = {
+ .driver = {
+ .name = "imx-pxp",
+ .of_match_table = of_match_ptr(imx_pxpdma_dt_ids),
+ .pm = &pxp_pm_ops,
+ },
+ .probe = pxp_probe,
+ .remove = pxp_remove,
+};
+
+module_platform_driver(pxp_driver);
+
+
+MODULE_DESCRIPTION("i.MX PxP driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/pxp/pxp_dma_v3.c b/drivers/dma/pxp/pxp_dma_v3.c
new file mode 100644
index 000000000000..5a613e97bb09
--- /dev/null
+++ b/drivers/dma/pxp/pxp_dma_v3.c
@@ -0,0 +1,8102 @@
+/*
+ * Copyright (C) 2010-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+/*
+ * Based on STMP378X PxP driver
+ * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/freezer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/dmaengine.h>
+#include <linux/pxp_dma.h>
+#include <linux/timer.h>
+#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+
+#include "regs-pxp_v3.h"
+#include "reg_bitfields.h"
+
+#ifdef CONFIG_MXC_FPGA_M4_TEST
+#include "cm4_image.c"
+#define FPGA_TCML_ADDR 0x0C7F8000
+#define PINCTRL 0x0C018000
+#define PIN_DOUT 0x700
+void __iomem *fpga_tcml_base;
+void __iomem *pinctrl_base;
+#endif
+
+
+#define PXP_FILL_TIMEOUT 3000
+#define busy_wait(cond) \
+ ({ \
+ unsigned long end_jiffies = jiffies + \
+ msecs_to_jiffies(PXP_FILL_TIMEOUT); \
+ bool succeeded = false; \
+ do { \
+ if (cond) { \
+ succeeded = true; \
+ break; \
+ } \
+ cpu_relax(); \
+ } while (time_after(end_jiffies, jiffies)); \
+ succeeded; \
+ })
+
+#define PXP_DOWNSCALE_THRESHOLD 0x4000
+
+#define CONFIG_FB_MXC_EINK_FPGA
+
+/* define all the pxp 2d nodes */
+#define PXP_2D_PS 0
+#define PXP_2D_AS 1
+#define PXP_2D_INPUT_FETCH0 2
+#define PXP_2D_INPUT_FETCH1 3
+#define PXP_2D_CSC1 4
+#define PXP_2D_ROTATION1 5
+#define PXP_2D_ALPHA0_S0 6
+#define PXP_2D_ALPHA0_S1 7
+#define PXP_2D_ALPHA1_S0 8
+#define PXP_2D_ALPHA1_S1 9
+#define PXP_2D_CSC2 10
+#define PXP_2D_LUT 11
+#define PXP_2D_ROTATION0 12
+#define PXP_2D_OUT 13
+#define PXP_2D_INPUT_STORE0 14
+#define PXP_2D_INPUT_STORE1 15
+#define PXP_2D_NUM 16
+
+#define PXP_2D_ALPHA0_S0_S1 0xaa
+#define PXP_2D_ALPHA1_S0_S1 0xbb
+
+#define PXP_2D_MUX_BASE 50
+#define PXP_2D_MUX_MUX0 (PXP_2D_MUX_BASE + 0)
+#define PXP_2D_MUX_MUX1 (PXP_2D_MUX_BASE + 1)
+#define PXP_2D_MUX_MUX2 (PXP_2D_MUX_BASE + 2)
+#define PXP_2D_MUX_MUX3 (PXP_2D_MUX_BASE + 3)
+#define PXP_2D_MUX_MUX4 (PXP_2D_MUX_BASE + 4)
+#define PXP_2D_MUX_MUX5 (PXP_2D_MUX_BASE + 5)
+#define PXP_2D_MUX_MUX6 (PXP_2D_MUX_BASE + 6)
+#define PXP_2D_MUX_MUX7 (PXP_2D_MUX_BASE + 7)
+#define PXP_2D_MUX_MUX8 (PXP_2D_MUX_BASE + 8)
+#define PXP_2D_MUX_MUX9 (PXP_2D_MUX_BASE + 9)
+#define PXP_2D_MUX_MUX10 (PXP_2D_MUX_BASE + 10)
+#define PXP_2D_MUX_MUX11 (PXP_2D_MUX_BASE + 11)
+#define PXP_2D_MUX_MUX12 (PXP_2D_MUX_BASE + 12)
+#define PXP_2D_MUX_MUX13 (PXP_2D_MUX_BASE + 13)
+#define PXP_2D_MUX_MUX14 (PXP_2D_MUX_BASE + 14)
+#define PXP_2D_MUX_MUX15 (PXP_2D_MUX_BASE + 15)
+
+/* define pxp 2d node types */
+#define PXP_2D_TYPE_INPUT 1
+#define PXP_2D_TYPE_ALU 2
+#define PXP_2D_TYPE_OUTPUT 3
+
+#define DISTANCE_INFINITY 0xffff
+#define NO_PATH_NODE 0xffffffff
+
+#define PXP_MAX_INPUT_NUM 2
+#define PXP_MAX_OUTPUT_NUM 2
+
+#define FETCH_NOOP 0x01
+#define FETCH_EXPAND 0x02
+#define FETCH_SHIFT 0x04
+
+#define STORE_NOOP 0x01
+#define STORE_SHIFT 0x02
+#define STORE_SHRINK 0x04
+
+#define NEED_YUV_SWAP 0x02
+
+#define IN_NEED_COMPOSITE (0x01 | IN_NEED_FMT_UNIFIED)
+#define IN_NEED_CSC (0x02 | IN_NEED_FMT_UNIFIED)
+#define IN_NEED_SCALE (0x04 | IN_NEED_FMT_UNIFIED)
+#define IN_NEED_ROTATE_FLIP (0x08 | IN_NEED_FMT_UNIFIED)
+#define IN_NEED_FMT_UNIFIED 0x10
+#define IN_NEED_SHIFT 0x20
+#define IN_NEED_LUT (0x40 | IN_NEED_UNIFIED)
+
+#define OUT_NEED_SHRINK 0x100
+#define OUT_NEED_SHIFT 0x200
+
+#define PXP_ROTATE_0 0
+#define PXP_ROTATE_90 1
+#define PXP_ROTATE_180 2
+#define PXP_ROTATE_270 3
+
+#define PXP_H_FLIP 1
+#define PXP_V_FLIP 2
+
+#define PXP_OP_TYPE_2D 0x001
+#define PXP_OP_TYPE_DITHER 0x002
+#define PXP_OP_TYPE_WFE_A 0x004
+#define PXP_OP_TYPE_WFE_B 0x008
+
+/* define store engine output mode */
+#define STORE_MODE_NORMAL 1
+#define STORE_MODE_BYPASS 2
+#define STORE_MODE_DUAL 3
+#define STORE_MODE_HANDSHAKE 4
+
+/* define fetch engine input mode */
+#define FETCH_MODE_NORMAL 1
+#define FETCH_MODE_BYPASS 2
+#define FETCH_MODE_HANDSHAKE 3
+
+#define COMMON_FMT_BPP 32
+
+#define R_COMP 0
+#define G_COMP 1
+#define B_COMP 2
+#define A_COMP 3
+
+#define Y_COMP 0
+#define U_COMP 1
+#define V_COMP 2
+#define Y1_COMP 4
+
+static LIST_HEAD(head);
+static int timeout_in_ms = 600;
+static unsigned int block_size;
+static struct kmem_cache *tx_desc_cache;
+static struct kmem_cache *edge_node_cache;
+static struct pxp_collision_info col_info;
+static dma_addr_t paddr;
+static bool v3p_flag;
+static int alpha_blending_version;
+static bool pxp_legacy;
+
+struct pxp_dma {
+ struct dma_device dma;
+};
+
+enum pxp_alpha_blending_version {
+ PXP_ALPHA_BLENDING_NONE = 0x0,
+ PXP_ALPHA_BLENDING_V1 = 0x1,
+ PXP_ALPHA_BLENDING_V2 = 0x2,
+};
+
+struct pxp_alpha_global {
+ unsigned int color_key_enable;
+ bool combine_enable;
+ bool global_alpha_enable;
+ bool global_override;
+ bool alpha_invert;
+ bool local_alpha_enable;
+ unsigned char global_alpha;
+ int comp_mask;
+};
+
+struct rectangle {
+ uint16_t x;
+ uint16_t y;
+ uint16_t width;
+ uint16_t height;
+};
+
+struct pxp_alpha_info {
+ uint8_t alpha_mode;
+ uint8_t rop_type;
+
+ struct pxp_alpha s0_alpha;
+ struct pxp_alpha s1_alpha;
+};
+
+struct pxp_op_info{
+ uint16_t op_type;
+ uint16_t rotation;
+ uint8_t flip;
+ uint8_t fill_en;
+ uint32_t fill_data;
+ uint8_t alpha_blending;
+ struct pxp_alpha_info alpha_info;
+
+ /* Dithering specific data */
+ uint32_t dither_mode;
+ uint32_t quant_bit;
+
+ /*
+ * partial:
+ * 0 - full update
+ * 1 - partial update
+ * alpha_en:
+ * 0 - upd is {Y4[3:0],4'b0000} format
+ * 1 - upd is {Y4[3:0],3'b000,alpha} format
+ * reagl_en:
+ * 0 - use normal waveform algorithm
+ * 1 - enable reagl/-d waveform algorithm
+ * detection_only:
+ * 0 - write working buffer
+ * 1 - do no write working buffer, detection only
+ * lut:
+ * valid value 0-63
+ * set to the lut used for next update
+ */
+ bool partial_update;
+ bool alpha_en;
+ bool lut_update;
+ bool reagl_en; /* enable reagl/-d */
+ bool reagl_d_en; /* enable reagl or reagl-d */
+ bool detection_only;
+ int lut;
+ uint32_t lut_status_1;
+ uint32_t lut_status_2;
+};
+
+struct pxp_pixmap {
+ uint8_t channel_id;
+ uint8_t bpp;
+ int32_t pitch;
+ uint16_t width;
+ uint16_t height;
+ struct rectangle crop;
+ uint32_t rotate;
+ uint8_t flip;
+ uint32_t format; /* fourcc pixmap format */
+ uint32_t flags;
+ bool valid;
+ dma_addr_t paddr;
+ struct pxp_alpha_global g_alpha;
+};
+
+struct pxp_task_info {
+ uint8_t input_num;
+ uint8_t output_num;
+ struct pxp_pixmap input[PXP_MAX_INPUT_NUM];
+ struct pxp_pixmap output[PXP_MAX_OUTPUT_NUM];
+ struct pxp_op_info op_info;
+ uint32_t pxp_2d_flags;
+};
+
+struct pxps {
+ struct platform_device *pdev;
+ struct clk *ipg_clk;
+ struct clk *axi_clk;
+ void __iomem *base;
+ int irq; /* PXP IRQ to the CPU */
+
+ spinlock_t lock;
+ struct mutex clk_mutex;
+ int clk_stat;
+#define CLK_STAT_OFF 0
+#define CLK_STAT_ON 1
+ int pxp_ongoing;
+ int lut_state;
+
+ struct device *dev;
+ struct pxp_dma pxp_dma;
+ struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
+ struct work_struct work;
+
+ const struct pxp_devdata *devdata;
+ struct pxp_task_info task;
+
+ /* describes most recent processing configuration */
+ struct pxp_config_data pxp_conf_state;
+
+ /* to turn clock off when pxp is inactive */
+ struct timer_list clk_timer;
+
+ /* for pxp config dispatch asynchronously*/
+ struct task_struct *dispatch;
+ wait_queue_head_t thread_waitq;
+ struct completion complete;
+};
+
+#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma)
+#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
+#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
+#define to_pxp(id) container_of(id, struct pxps, pxp_dma)
+
+#define to_pxp_task_info(op) container_of((op), struct pxp_task_info, op_info)
+#define to_pxp_from_task(task) container_of((task), struct pxps, task)
+
+#define PXP_DEF_BUFS 2
+#define PXP_MIN_PIX 8
+
+static uint8_t active_bpp(uint8_t bpp)
+{
+ switch(bpp) {
+ case 8:
+ return 0x0;
+ case 16:
+ return 0x1;
+ case 32:
+ return 0x2;
+ case 64:
+ return 0x3;
+ default:
+ return 0xff;
+ }
+}
+
+static uint8_t rotate_map(uint32_t degree)
+{
+ switch (degree) {
+ case 0:
+ return PXP_ROTATE_0;
+ case 90:
+ return PXP_ROTATE_90;
+ case 180:
+ return PXP_ROTATE_180;
+ case 270:
+ return PXP_ROTATE_270;
+ default:
+ return 0;
+ }
+}
+
+static uint8_t expand_format(uint32_t format)
+{
+ switch (format) {
+ case PXP_PIX_FMT_RGB565:
+ case PXP_PIX_FMT_BGR565:
+ return 0x0;
+ case PXP_PIX_FMT_RGB555:
+ return 0x1;
+ case PXP_PIX_FMT_YUYV:
+ case PXP_PIX_FMT_YVYU:
+ return 0x5;
+ case PXP_PIX_FMT_UYVY:
+ case PXP_PIX_FMT_VYUY:
+ return 0x6;
+ case PXP_PIX_FMT_NV16:
+ return 0x7;
+ default:
+ return 0xff;
+ }
+}
+
+struct color_component {
+ uint8_t id;
+ uint8_t offset;
+ uint8_t length;
+ uint8_t mask;
+};
+
+struct color {
+ uint32_t format;
+ struct color_component comp[4];
+};
+
+struct color rgb_colors[] = {
+ {
+ .format = PXP_PIX_FMT_RGB565,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 5, .mask = 0x1f, },
+ { .id = G_COMP, .offset = 5, .length = 6, .mask = 0x3f, },
+ { .id = R_COMP, .offset = 11, .length = 5, .mask = 0x1f, },
+ { .id = A_COMP, .offset = 0, .length = 0, .mask = 0x0, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_BGR565,
+ .comp = {
+ { .id = R_COMP, .offset = 0, .length = 5, .mask = 0x1f, },
+ { .id = G_COMP, .offset = 5, .length = 6, .mask = 0x3f, },
+ { .id = B_COMP, .offset = 11, .length = 6, .mask = 0x3f, },
+ { .id = A_COMP, .offset = 0, .length = 0, .mask = 0x0, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_ARGB555,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 5, .mask = 0x1f, },
+ { .id = G_COMP, .offset = 5, .length = 5, .mask = 0x1f, },
+ { .id = R_COMP, .offset = 10, .length = 5, .mask = 0x1f, },
+ { .id = A_COMP, .offset = 15, .length = 1, .mask = 0x1, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_XRGB555,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 5, .mask = 0x1f, },
+ { .id = G_COMP, .offset = 5, .length = 5, .mask = 0x1f, },
+ { .id = R_COMP, .offset = 10, .length = 5, .mask = 0x1f, },
+ { .id = A_COMP, .offset = 15, .length = 1, .mask = 0x1, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_RGB555,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 5, .mask = 0x1f, },
+ { .id = G_COMP, .offset = 5, .length = 5, .mask = 0x1f, },
+ { .id = R_COMP, .offset = 10, .length = 5, .mask = 0x1f, },
+ { .id = A_COMP, .offset = 15, .length = 1, .mask = 0x1, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_RGBA555,
+ .comp = {
+ { .id = A_COMP, .offset = 0, .length = 1, .mask = 0x1, },
+ { .id = B_COMP, .offset = 1, .length = 5, .mask = 0x1f, },
+ { .id = G_COMP, .offset = 6, .length = 5, .mask = 0x1f, },
+ { .id = R_COMP, .offset = 11, .length = 5, .mask = 0x1f, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_ARGB444,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 4, .mask = 0xf, },
+ { .id = G_COMP, .offset = 4, .length = 4, .mask = 0xf, },
+ { .id = R_COMP, .offset = 8, .length = 4, .mask = 0xf, },
+ { .id = A_COMP, .offset = 12, .length = 4, .mask = 0xf, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_XRGB444,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 4, .mask = 0xf, },
+ { .id = G_COMP, .offset = 4, .length = 4, .mask = 0xf, },
+ { .id = R_COMP, .offset = 8, .length = 4, .mask = 0xf, },
+ { .id = A_COMP, .offset = 12, .length = 4, .mask = 0xf, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_RGBA444,
+ .comp = {
+ { .id = A_COMP, .offset = 0, .length = 4, .mask = 0xf, },
+ { .id = B_COMP, .offset = 4, .length = 4, .mask = 0xf, },
+ { .id = G_COMP, .offset = 8, .length = 4, .mask = 0xf, },
+ { .id = R_COMP, .offset = 12, .length = 4, .mask = 0xf, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_RGB24,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = R_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = A_COMP, .offset = 0, .length = 0, .mask = 0x0, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_BGR24,
+ .comp = {
+ { .id = R_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = B_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = A_COMP, .offset = 0, .length = 0, .mask = 0x0, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_XRGB32,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = R_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = A_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_RGBX32,
+ .comp = {
+ { .id = A_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = B_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = R_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_XBGR32,
+ .comp = {
+ { .id = R_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = B_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = A_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_BGRX32,
+ .comp = {
+ { .id = A_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = R_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = B_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_ARGB32,
+ .comp = {
+ { .id = B_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = R_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = A_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_ABGR32,
+ .comp = {
+ { .id = R_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = B_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = A_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_RGBA32,
+ .comp = {
+ { .id = A_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = B_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = R_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_BGRA32,
+ .comp = {
+ { .id = A_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = R_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = G_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = B_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ },
+};
+
+/* only one plane yuv formats */
+struct color yuv_colors[] = {
+ {
+ .format = PXP_PIX_FMT_GREY,
+ .comp = {
+ { .id = Y_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = U_COMP, .offset = 8, .length = 0, .mask = 0x00, },
+ { .id = V_COMP, .offset = 16, .length = 0, .mask = 0x00, },
+ { .id = A_COMP, .offset = 24, .length = 0, .mask = 0x00, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_YUYV,
+ .comp = {
+ { .id = V_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = Y1_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = U_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = Y_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_UYVY,
+ .comp = {
+ { .id = Y1_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = V_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = Y_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = U_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_YVYU,
+ .comp = {
+ { .id = U_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = Y1_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = V_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = Y_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_VYUY,
+ .comp = {
+ { .id = Y1_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = U_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = Y_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = V_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_YUV444,
+ .comp = {
+ { .id = V_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = U_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = Y_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = A_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ }, {
+ .format = PXP_PIX_FMT_YVU444,
+ .comp = {
+ { .id = U_COMP, .offset = 0, .length = 8, .mask = 0xff, },
+ { .id = V_COMP, .offset = 8, .length = 8, .mask = 0xff, },
+ { .id = Y_COMP, .offset = 16, .length = 8, .mask = 0xff, },
+ { .id = A_COMP, .offset = 24, .length = 8, .mask = 0xff, },
+ },
+ },
+};
+
+/* 4 to 1 mux */
+struct mux {
+ uint32_t id;
+ uint8_t mux_inputs[4];
+ uint8_t mux_outputs[2];
+};
+
+/* Adjacent list structure */
+struct edge_node {
+ uint32_t adjvex;
+ uint32_t prev_vnode;
+ struct edge_node *next;
+ uint32_t mux_used;
+ struct mux_config muxes;
+};
+
+struct vetex_node {
+ uint8_t type;
+ struct edge_node *first;
+};
+
+struct path_node {
+ struct list_head node;
+ uint32_t id;
+ uint32_t distance;
+ uint32_t prev_node;
+};
+
+static struct vetex_node adj_list[PXP_2D_NUM];
+static struct path_node path_table[PXP_2D_NUM][PXP_2D_NUM];
+
+static bool adj_array_v3[PXP_2D_NUM][PXP_2D_NUM] = {
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
+ {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 0 */
+ {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, /* 1 */
+ {0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0}, /* 2 */
+ {0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1}, /* 3 */
+ {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 4 */
+ {0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0}, /* 5 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0}, /* 6 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0}, /* 7 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0}, /* 8 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0}, /* 9 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0}, /* 10 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, /* 11 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, /* 12 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 13 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 14 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 15 */
+};
+
+
+static struct mux muxes_v3[16] = {
+ {
+ /* mux0 */
+ .id = 0,
+ .mux_inputs = {PXP_2D_CSC1, PXP_2D_INPUT_FETCH0, PXP_2D_INPUT_FETCH1, 0xff},
+ .mux_outputs = {PXP_2D_ROTATION1, 0xff},
+ }, {
+ /* mux1 */
+ .id = 1,
+ .mux_inputs = {PXP_2D_INPUT_FETCH0, PXP_2D_ROTATION1, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_ALPHA1_S1, PXP_2D_MUX_MUX5},
+ }, {
+ /* mux2 */
+ .id = 2,
+ .mux_inputs = {PXP_2D_INPUT_FETCH1, PXP_2D_ROTATION1, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_ALPHA1_S0, 0xff},
+ }, {
+ /* mux3 */
+ .id = 3,
+ .mux_inputs = {PXP_2D_CSC1, PXP_2D_ROTATION1, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_ALPHA0_S0, 0xff},
+ }, {
+ /* mux4 is not used in ULT1 */
+ .id = 4,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux5 */
+ .id = 5,
+ .mux_inputs = {PXP_2D_MUX_MUX1, PXP_2D_ALPHA1_S0_S1, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_MUX_MUX7, 0xff},
+ }, {
+ /* mux6 */
+ .id = 6,
+ .mux_inputs = {PXP_2D_ALPHA1_S0_S1, PXP_2D_ALPHA0_S0_S1, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_CSC2, 0xff},
+ }, {
+ /* mux7 */
+ .id = 7,
+ .mux_inputs = {PXP_2D_MUX_MUX5, PXP_2D_CSC2, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_MUX_MUX9, PXP_2D_MUX_MUX10},
+ }, {
+ /* mux8 */
+ .id = 8,
+ .mux_inputs = {PXP_2D_CSC2, PXP_2D_ALPHA0_S0_S1, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_MUX_MUX9, PXP_2D_MUX_MUX11},
+ }, {
+ /* mux9 */
+ .id = 9,
+ .mux_inputs = {PXP_2D_MUX_MUX7, PXP_2D_MUX_MUX8, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_LUT, 0xff},
+ }, {
+ /* mux10 */
+ .id = 10,
+ .mux_inputs = {PXP_2D_MUX_MUX7, PXP_2D_LUT, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_MUX_MUX12, PXP_2D_MUX_MUX15},
+ }, {
+ /* mux11 */
+ .id = 11,
+ .mux_inputs = {PXP_2D_LUT, PXP_2D_MUX_MUX8, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_MUX_MUX12, PXP_2D_MUX_MUX14},
+ }, {
+ /* mux12 */
+ .id = 12,
+ .mux_inputs = {PXP_2D_MUX_MUX10, PXP_2D_MUX_MUX11, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_ROTATION0, 0xff},
+ }, {
+ /* mux13 */
+ .id = 13,
+ .mux_inputs = {PXP_2D_INPUT_FETCH1, 0xff, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_INPUT_STORE1, 0xff},
+ }, {
+ /* mux14 */
+ .id = 14,
+ .mux_inputs = {PXP_2D_ROTATION0, PXP_2D_MUX_MUX11, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_OUT, 0xff},
+ }, {
+ /* mux15 */
+ .id = 15,
+ .mux_inputs = {PXP_2D_INPUT_FETCH0, PXP_2D_MUX_MUX10, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_INPUT_STORE0, 0xff},
+ },
+};
+
+static bool adj_array_v3p[PXP_2D_NUM][PXP_2D_NUM] = {
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
+ {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 0 */
+ {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, /* 1 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 2 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 3 */
+ {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 4 */
+ {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 5 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0}, /* 6 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0}, /* 7 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 8 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 9 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}, /* 10 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, /* 11 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, /* 12 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 13 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 14 */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 15 */
+};
+
+static struct mux muxes_v3p[16] = {
+ {
+ /* mux0 */
+ .id = 0,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux1 */
+ .id = 1,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux2 */
+ .id = 2,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux3 */
+ .id = 3,
+ .mux_inputs = {PXP_2D_CSC1, PXP_2D_ROTATION1, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_ALPHA0_S0, 0xff},
+ }, {
+ /* mux4 is not used in ULT1 */
+ .id = 4,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux5 */
+ .id = 5,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux6 */
+ .id = 6,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux7 */
+ .id = 7,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux8 */
+ .id = 8,
+ .mux_inputs = {PXP_2D_CSC2, PXP_2D_ALPHA0_S0_S1, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_MUX_MUX9, PXP_2D_MUX_MUX11},
+ }, {
+ /* mux9 */
+ .id = 9,
+ .mux_inputs = {0xff, PXP_2D_MUX_MUX8, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_LUT, 0xff},
+ }, {
+ /* mux10 */
+ .id = 10,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux11 */
+ .id = 11,
+ .mux_inputs = {PXP_2D_LUT, PXP_2D_MUX_MUX8, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_MUX_MUX12, PXP_2D_ROTATION0},
+ }, {
+ /* mux12 */
+ .id = 12,
+ .mux_inputs = {PXP_2D_ROTATION0, PXP_2D_MUX_MUX11, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_MUX_MUX14, 0xff},
+ }, {
+ /* mux13 */
+ .id = 13,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ }, {
+ /* mux14 */
+ .id = 14,
+ .mux_inputs = {0xff, PXP_2D_MUX_MUX12, 0xff, 0xff},
+ .mux_outputs = {PXP_2D_OUT, 0xff},
+ }, {
+ /* mux15 */
+ .id = 15,
+ .mux_inputs = {0xff, 0xff, 0xff, 0xff},
+ .mux_outputs = {0xff, 0xff},
+ },
+};
+
+static void __iomem *pxp_reg_base;
+
+#define pxp_writel(val, reg) writel(val, pxp_reg_base + (reg))
+
+static __attribute__((aligned (1024*4))) unsigned int active_matrix_data_8x8[64]={
+ 0x06050100, 0x04030207, 0x06050100, 0x04030207,
+ 0x00040302, 0x07060501, 0x00040302, 0x07060501,
+ 0x02070605, 0x01000403, 0x02070605, 0x01000403,
+ 0x05010004, 0x03020706, 0x05010004, 0x03020706,
+ 0x04030207, 0x06050100, 0x04030207, 0x06050100,
+ 0x07060501, 0x00040302, 0x07060501, 0x00040302,
+ 0x01000403, 0x02070605, 0x01000403, 0x02070605,
+ 0x03020706, 0x05010004, 0x03020706, 0x05010004,
+ 0x06050100, 0x04030207, 0x06050100, 0x04030207,
+ 0x00040302, 0x07060501, 0x00040302, 0x07060501,
+ 0x02070605, 0x01000403, 0x02070605, 0x01000403,
+ 0x05010004, 0x03020706, 0x05010004, 0x03020706,
+ 0x04030207, 0x06050100, 0x04030207, 0x06050100,
+ 0x07060501, 0x00040302, 0x07060501, 0x00040302,
+ 0x01000403, 0x02070605, 0x01000403, 0x02070605,
+ 0x03020706, 0x05010004, 0x03020706, 0x05010004
+ };
+
+static __attribute__((aligned (1024*4))) unsigned int bit1_dither_data_8x8[64]={
+
+ 1, 49*2, 13*2, 61*2, 4*2, 52*2, 16*2, 64*2,
+ 33*2, 17*2, 45*2, 29*2, 36*2, 20*2, 48*2, 32*2,
+ 9*2, 57*2, 5*2, 53*2, 12*2, 60*2, 8*2, 56*2,
+ 41*2, 25*2, 37*2, 21*2, 44*2, 28*2, 40*2, 24*2,
+ 3*2, 51*2, 15*2, 63*2, 2*2, 50*2, 14*2, 62*2,
+ 35*2, 19*2, 47*2, 31*2, 34*2, 18*2, 46*2, 30*2,
+ 11*2, 59*2, 7*2, 55*2, 10*2, 58*2, 6*2, 54*2,
+ 43*2, 27*2, 39*2, 23*2, 42*2, 26*2, 38*2, 22*2
+};
+
+static __attribute__((aligned (1024*4))) unsigned int bit2_dither_data_8x8[64]={
+
+ 1, 49, 13, 61, 4, 52, 16, 64,
+ 33, 17, 45, 29, 36, 20, 48, 32,
+ 9, 57, 5, 53, 12, 60, 8, 56,
+ 41, 25, 37, 21, 44, 28, 40, 24,
+ 3, 51, 15, 63, 2, 50, 14, 62,
+ 35, 19, 47, 31, 34, 18, 46, 30,
+ 11, 59, 7, 55, 10, 58, 6, 54,
+ 43, 27, 39, 23, 42, 26, 38, 22
+};
+
+static __attribute__((aligned (1024*4))) unsigned int bit4_dither_data_8x8[64]={
+
+ 1, 49/4, 13/4, 61/4, 4/4, 52/4, 16/4, 64/4,
+ 33/4, 17/4, 45/4, 29/4, 36/4, 20/4, 48/4, 32/4,
+ 9/4, 57/4, 5/4, 53/4, 12/4, 60/4, 8/4, 56/4,
+ 41/4, 25/4, 37/4, 21/4, 44/4, 28/4, 40/4, 24/4,
+ 3/4, 51/4, 15/4, 63/4, 2/4, 50/4, 14/4, 62/4,
+ 35/4, 19/4, 47/4, 31/4, 34/4, 18/4, 46/4, 30/4,
+ 11/4, 59/4, 7/4, 55/4, 10/4, 58/4, 6/4, 54/4,
+ 43/4, 27/4, 39/4, 23/4, 42/4, 26/4, 38/4, 22/4
+};
+
+static void pxp_dithering_configure(struct pxps *pxp);
+static void pxp_dithering_configure_v3p(struct pxps *pxp);
+static void pxp_dithering_process(struct pxps *pxp);
+static void pxp_wfe_a_process(struct pxps *pxp);
+static void pxp_wfe_a_process_v3p(struct pxps *pxp);
+static void pxp_wfe_a_configure(struct pxps *pxp);
+static void pxp_wfe_a_configure_v3p(struct pxps *pxp);
+static void pxp_wfe_b_process(struct pxps *pxp);
+static void pxp_wfe_b_configure(struct pxps *pxp);
+static void pxp_lut_status_set(struct pxps *pxp, unsigned int lut);
+static void pxp_lut_status_set_v3p(struct pxps *pxp, unsigned int lut);
+static void pxp_lut_status_clr(unsigned int lut);
+static void pxp_lut_status_clr_v3p(unsigned int lut);
+static void pxp_start2(struct pxps *pxp);
+static void pxp_data_path_config_v3p(struct pxps *pxp);
+static void pxp_soft_reset(struct pxps *pxp);
+static void pxp_collision_detection_disable(struct pxps *pxp);
+static void pxp_collision_detection_enable(struct pxps *pxp,
+ unsigned int width,
+ unsigned int height);
+static void pxp_luts_activate(struct pxps *pxp, u64 lut_status);
+static bool pxp_collision_status_report(struct pxps *pxp, struct pxp_collision_info *info);
+static void pxp_histogram_status_report(struct pxps *pxp, u32 *hist_status);
+static void pxp_histogram_enable(struct pxps *pxp,
+ unsigned int width,
+ unsigned int height);
+static void pxp_histogram_disable(struct pxps *pxp);
+static void pxp_lut_cleanup_multiple(struct pxps *pxp, u64 lut, bool set);
+static void pxp_lut_cleanup_multiple_v3p(struct pxps *pxp, u64 lut, bool set);
+static void pxp_luts_deactivate(struct pxps *pxp, u64 lut_status);
+static void pxp_set_colorkey(struct pxps *pxp);
+
+enum {
+ DITHER0_LUT = 0x0, /* Select the LUT memory for access */
+ DITHER0_ERR0 = 0x1, /* Select the ERR0 memory for access */
+ DITHER0_ERR1 = 0x2, /* Select the ERR1 memory for access */
+ DITHER1_LUT = 0x3, /* Select the LUT memory for access */
+ DITHER2_LUT = 0x4, /* Select the LUT memory for access */
+ ALU_A = 0x5, /* Select the ALU instr memory for access */
+ ALU_B = 0x6, /* Select the ALU instr memory for access */
+ WFE_A = 0x7, /* Select the WFE_A instr memory for access */
+ WFE_B = 0x8, /* Select the WFE_B instr memory for access */
+ RESERVED = 0x15,
+};
+
+enum pxp_devtype {
+ PXP_V3,
+ PXP_V3P, /* minor changes over V3, use WFE_B to replace WFE_A */
+};
+
+#define pxp_is_v3(pxp) (pxp->devdata->version == 30)
+#define pxp_is_v3p(pxp) (pxp->devdata->version == 31)
+
+struct pxp_devdata {
+ void (*pxp_wfe_a_configure)(struct pxps *pxp);
+ void (*pxp_wfe_a_process)(struct pxps *pxp);
+ void (*pxp_lut_status_set)(struct pxps *pxp, unsigned int lut);
+ void (*pxp_lut_status_clr)(unsigned int lut);
+ void (*pxp_dithering_configure)(struct pxps *pxp);
+ void (*pxp_lut_cleanup_multiple)(struct pxps *pxp, u64 lut, bool set);
+ void (*pxp_data_path_config)(struct pxps *pxp);
+ unsigned int version;
+};
+
+static const struct pxp_devdata pxp_devdata[] = {
+ [PXP_V3] = {
+ .pxp_wfe_a_configure = pxp_wfe_a_configure,
+ .pxp_wfe_a_process = pxp_wfe_a_process,
+ .pxp_lut_status_set = pxp_lut_status_set,
+ .pxp_lut_status_clr = pxp_lut_status_clr,
+ .pxp_lut_cleanup_multiple = pxp_lut_cleanup_multiple,
+ .pxp_dithering_configure = pxp_dithering_configure,
+ .pxp_data_path_config = NULL,
+ .version = 30,
+ },
+ [PXP_V3P] = {
+ .pxp_wfe_a_configure = pxp_wfe_a_configure_v3p,
+ .pxp_wfe_a_process = pxp_wfe_a_process_v3p,
+ .pxp_lut_status_set = pxp_lut_status_set_v3p,
+ .pxp_lut_status_clr = pxp_lut_status_clr_v3p,
+ .pxp_lut_cleanup_multiple = pxp_lut_cleanup_multiple_v3p,
+ .pxp_dithering_configure = pxp_dithering_configure_v3p,
+ .pxp_data_path_config = pxp_data_path_config_v3p,
+ .version = 31,
+ },
+};
+
+/*
+ * PXP common functions
+ */
+static void dump_pxp_reg(struct pxps *pxp)
+{
+ dev_dbg(pxp->dev, "PXP_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CTRL));
+ dev_dbg(pxp->dev, "PXP_STAT 0x%x",
+ __raw_readl(pxp->base + HW_PXP_STAT));
+ dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_CTRL));
+ dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_BUF));
+ dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_BUF2));
+ dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_PITCH));
+ dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_LRC));
+ dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC));
+ dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC));
+ dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC));
+ dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x",
+ __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC));
+ dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_CTRL));
+ dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_BUF));
+ dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_UBUF));
+ dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_VBUF));
+ dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_PITCH));
+ dev_dbg(pxp->dev, "PXP_PS_BACKGROUND_0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND_0));
+ dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_SCALE));
+ dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_OFFSET));
+ dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW_0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW_0));
+ dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH_0));
+ dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_CTRL));
+ dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_BUF));
+ dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_PITCH));
+ dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW_0));
+ dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x",
+ __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH_0));
+ dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF0));
+ dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF1));
+ dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF2));
+ dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_CTRL));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF0));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF1));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF2));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF3));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF4));
+ dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF5));
+ dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_LUT_CTRL));
+ dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x",
+ __raw_readl(pxp->base + HW_PXP_LUT_ADDR));
+ dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x",
+ __raw_readl(pxp->base + HW_PXP_LUT_DATA));
+ dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x",
+ __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM));
+ dev_dbg(pxp->dev, "PXP_CFA 0x%x",
+ __raw_readl(pxp->base + HW_PXP_CFA));
+ dev_dbg(pxp->dev, "PXP_ALPHA_A_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_ALPHA_A_CTRL));
+ dev_dbg(pxp->dev, "PXP_ALPHA_B_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_ALPHA_B_CTRL));
+ dev_dbg(pxp->dev, "PXP_POWER_REG0 0x%x",
+ __raw_readl(pxp->base + HW_PXP_POWER_REG0));
+ dev_dbg(pxp->dev, "PXP_NEXT 0x%x",
+ __raw_readl(pxp->base + HW_PXP_NEXT));
+ dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_DEBUGCTRL));
+ dev_dbg(pxp->dev, "PXP_DEBUG 0x%x",
+ __raw_readl(pxp->base + HW_PXP_DEBUG));
+ dev_dbg(pxp->dev, "PXP_VERSION 0x%x",
+ __raw_readl(pxp->base + HW_PXP_VERSION));
+}
+
+static void dump_pxp_reg2(struct pxps *pxp)
+{
+#ifdef DEBUG
+ int i = 0;
+
+ for (i=0; i< ((0x33C0/0x10) + 1);i++) {
+ printk("0x%08x: 0x%08x\n", 0x10*i, __raw_readl(pxp->base + 0x10*i));
+ }
+#endif
+}
+
+static void print_param(struct pxp_layer_param *p, char *s)
+{
+ pr_debug("%s: t/l/w/h/s %d/%d/%d/%d/%d, addr %x\n", s,
+ p->top, p->left, p->width, p->height, p->stride, p->paddr);
+}
+
+/* when it is, return yuv plane number */
+static uint8_t is_yuv(uint32_t format)
+{
+ switch (format) {
+ case PXP_PIX_FMT_GREY:
+ case PXP_PIX_FMT_GY04:
+ case PXP_PIX_FMT_YUYV:
+ case PXP_PIX_FMT_UYVY:
+ case PXP_PIX_FMT_YVYU:
+ case PXP_PIX_FMT_VYUY:
+ case PXP_PIX_FMT_YUV444:
+ case PXP_PIX_FMT_YVU444:
+ return 1;
+ case PXP_PIX_FMT_NV12:
+ case PXP_PIX_FMT_NV21:
+ case PXP_PIX_FMT_NV16:
+ case PXP_PIX_FMT_NV61:
+ return 2;
+ case PXP_PIX_FMT_YUV420P:
+ case PXP_PIX_FMT_YUV422P:
+ case PXP_PIX_FMT_YVU420P:
+ case PXP_PIX_FMT_YVU422P:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+static u32 get_bpp_from_fmt(u32 pix_fmt)
+{
+ unsigned int bpp = 0;
+
+ switch (pix_fmt) {
+ case PXP_PIX_FMT_GREY:
+ case PXP_PIX_FMT_NV16:
+ case PXP_PIX_FMT_NV61:
+ case PXP_PIX_FMT_NV12:
+ case PXP_PIX_FMT_NV21:
+ case PXP_PIX_FMT_YUV422P:
+ case PXP_PIX_FMT_YVU422P:
+ case PXP_PIX_FMT_YUV420P:
+ case PXP_PIX_FMT_YVU420P:
+ bpp = 8;
+ break;
+ case PXP_PIX_FMT_RGB555:
+ case PXP_PIX_FMT_ARGB555:
+ case PXP_PIX_FMT_XRGB555:
+ case PXP_PIX_FMT_RGBA555:
+ case PXP_PIX_FMT_ARGB444:
+ case PXP_PIX_FMT_XRGB444:
+ case PXP_PIX_FMT_RGBA444:
+ case PXP_PIX_FMT_RGB565:
+ case PXP_PIX_FMT_BGR565:
+ case PXP_PIX_FMT_YUYV:
+ case PXP_PIX_FMT_YVYU:
+ case PXP_PIX_FMT_UYVY:
+ case PXP_PIX_FMT_VYUY:
+ bpp = 16;
+ break;
+ case PXP_PIX_FMT_RGB24:
+ case PXP_PIX_FMT_BGR24:
+ bpp = 24;
+ break;
+ case PXP_PIX_FMT_XRGB32:
+ case PXP_PIX_FMT_RGBX32:
+ case PXP_PIX_FMT_XBGR32:
+ case PXP_PIX_FMT_BGRX32:
+ case PXP_PIX_FMT_ARGB32:
+ case PXP_PIX_FMT_RGBA32:
+ case PXP_PIX_FMT_ABGR32:
+ case PXP_PIX_FMT_BGRA32:
+ case PXP_PIX_FMT_YUV444:
+ case PXP_PIX_FMT_YVU444:
+ bpp = 32;
+ break;
+ default:
+ pr_err("%s: pix_fmt unsupport yet: 0x%x\n", __func__, pix_fmt);
+ break;
+ }
+
+ return bpp;
+}
+
+static uint32_t pxp_parse_ps_fmt(uint32_t format)
+{
+ uint32_t fmt_ctrl;
+
+ switch (format) {
+ case PXP_PIX_FMT_XRGB32:
+ case PXP_PIX_FMT_ARGB32:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888;
+ break;
+ case PXP_PIX_FMT_RGB565:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565;
+ break;
+ case PXP_PIX_FMT_RGB555:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555;
+ break;
+ case PXP_PIX_FMT_YUV420P:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
+ break;
+ case PXP_PIX_FMT_YVU420P:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
+ break;
+ case PXP_PIX_FMT_GREY:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8;
+ break;
+ case PXP_PIX_FMT_GY04:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4;
+ break;
+ case PXP_PIX_FMT_VUY444:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV1P444;
+ break;
+ case PXP_PIX_FMT_YUV422P:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422;
+ break;
+ case PXP_PIX_FMT_UYVY:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+ break;
+ case PXP_PIX_FMT_YUYV:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+ break;
+ case PXP_PIX_FMT_VYUY:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+ break;
+ case PXP_PIX_FMT_YVYU:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+ break;
+ case PXP_PIX_FMT_NV12:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420;
+ break;
+ case PXP_PIX_FMT_NV21:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420;
+ break;
+ case PXP_PIX_FMT_NV16:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422;
+ break;
+ case PXP_PIX_FMT_NV61:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422;
+ break;
+ case PXP_PIX_FMT_RGBA32:
+ case PXP_PIX_FMT_RGBX32:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGBA888;
+ break;
+ default:
+ pr_debug("PS doesn't support this format\n");
+ fmt_ctrl = 0;
+ }
+
+ return fmt_ctrl;
+}
+
+static void pxp_set_colorkey(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+ struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0];
+
+ /* Low and high are set equal. V4L does not allow a chromakey range */
+ if (s0_params->color_key_enable == 0 || s0_params->color_key == -1) {
+ /* disable color key */
+ pxp_writel(0xFFFFFF, HW_PXP_PS_CLRKEYLOW_0);
+ pxp_writel(0, HW_PXP_PS_CLRKEYHIGH_0);
+ } else {
+ pxp_writel(s0_params->color_key, HW_PXP_PS_CLRKEYLOW_0);
+ pxp_writel(s0_params->color_key, HW_PXP_PS_CLRKEYHIGH_0);
+ }
+
+ if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) {
+ pxp_writel(ol_params->color_key, HW_PXP_AS_CLRKEYLOW_0);
+ pxp_writel(ol_params->color_key, HW_PXP_AS_CLRKEYHIGH_0);
+ } else {
+ /* disable color key */
+ pxp_writel(0xFFFFFF, HW_PXP_AS_CLRKEYLOW_0);
+ pxp_writel(0, HW_PXP_AS_CLRKEYHIGH_0);
+ }
+}
+
+static uint32_t pxp_parse_as_fmt(uint32_t format)
+{
+ uint32_t fmt_ctrl;
+
+ switch (format) {
+ case PXP_PIX_FMT_BGRA32:
+ case PXP_PIX_FMT_ARGB32:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__ARGB8888;
+ break;
+ case PXP_PIX_FMT_RGBA32:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__RGBA8888;
+ break;
+ case PXP_PIX_FMT_XRGB32:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__RGB888;
+ break;
+ case PXP_PIX_FMT_ARGB555:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__ARGB1555;
+ break;
+ case PXP_PIX_FMT_ARGB444:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__ARGB4444;
+ break;
+ case PXP_PIX_FMT_RGBA555:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__RGBA5551;
+ break;
+ case PXP_PIX_FMT_RGBA444:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__RGBA4444;
+ break;
+ case PXP_PIX_FMT_RGB555:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__RGB555;
+ break;
+ case PXP_PIX_FMT_RGB444:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__RGB444;
+ break;
+ case PXP_PIX_FMT_RGB565:
+ fmt_ctrl = BV_PXP_AS_CTRL_FORMAT__RGB565;
+ break;
+ default:
+ pr_debug("AS doesn't support this format\n");
+ fmt_ctrl = 0xf;
+ break;
+ }
+
+ return fmt_ctrl;
+}
+
+static uint32_t pxp_parse_out_fmt(uint32_t format)
+{
+ uint32_t fmt_ctrl;
+
+ switch (format) {
+ case PXP_PIX_FMT_BGRA32:
+ case PXP_PIX_FMT_ARGB32:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
+ break;
+ case PXP_PIX_FMT_XRGB32:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888;
+ break;
+ case PXP_PIX_FMT_RGB24:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P;
+ break;
+ case PXP_PIX_FMT_RGB565:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565;
+ break;
+ case PXP_PIX_FMT_RGB555:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555;
+ break;
+ case PXP_PIX_FMT_GREY:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8;
+ break;
+ case PXP_PIX_FMT_GY04:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4;
+ break;
+ case PXP_PIX_FMT_UYVY:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
+ break;
+ case PXP_PIX_FMT_VYUY:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
+ break;
+ case PXP_PIX_FMT_NV12:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
+ break;
+ case PXP_PIX_FMT_NV21:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
+ break;
+ case PXP_PIX_FMT_NV16:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
+ break;
+ case PXP_PIX_FMT_NV61:
+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
+ break;
+ default:
+ pr_debug("OUT doesn't support this format\n");
+ fmt_ctrl = 0;
+ }
+
+ return fmt_ctrl;
+}
+
+static void set_mux(struct mux_config *path_ctrl)
+{
+ struct mux_config *mux = path_ctrl;
+
+ *(uint32_t *)path_ctrl = 0xFFFFFFFF;
+
+ mux->mux0_sel = 0;
+ mux->mux3_sel = 1;
+ mux->mux6_sel = 1;
+ mux->mux8_sel = 0;
+ mux->mux9_sel = 1;
+ mux->mux11_sel = 0;
+ mux->mux12_sel = 1;
+ mux->mux14_sel = 0;
+}
+
+static void set_mux_val(struct mux_config *muxes,
+ uint32_t mux_id,
+ uint32_t mux_val)
+{
+ BUG_ON(!muxes);
+ BUG_ON(mux_id > 15);
+
+ switch (mux_id) {
+ case 0:
+ muxes->mux0_sel = mux_val;
+ break;
+ case 1:
+ muxes->mux1_sel = mux_val;
+ break;
+ case 2:
+ muxes->mux2_sel = mux_val;
+ break;
+ case 3:
+ muxes->mux3_sel = mux_val;
+ break;
+ case 4:
+ muxes->mux4_sel = mux_val;
+ break;
+ case 5:
+ muxes->mux5_sel = mux_val;
+ break;
+ case 6:
+ muxes->mux6_sel = mux_val;
+ break;
+ case 7:
+ muxes->mux7_sel = mux_val;
+ break;
+ case 8:
+ muxes->mux8_sel = mux_val;
+ break;
+ case 9:
+ muxes->mux9_sel = mux_val;
+ break;
+ case 10:
+ muxes->mux10_sel = mux_val;
+ break;
+ case 11:
+ muxes->mux11_sel = mux_val;
+ break;
+ case 12:
+ muxes->mux12_sel = mux_val;
+ break;
+ case 13:
+ muxes->mux13_sel = mux_val;
+ break;
+ case 14:
+ muxes->mux14_sel = mux_val;
+ break;
+ case 15:
+ muxes->mux15_sel = mux_val;
+ break;
+ default:
+ break;
+ }
+}
+
+static uint32_t get_mux_val(struct mux_config *muxes,
+ uint32_t mux_id)
+{
+ BUG_ON(!muxes);
+ BUG_ON(mux_id > 15);
+
+ switch (mux_id) {
+ case 0:
+ return muxes->mux0_sel;
+ case 1:
+ return muxes->mux1_sel;
+ case 2:
+ return muxes->mux2_sel;
+ case 3:
+ return muxes->mux3_sel;
+ case 4:
+ return muxes->mux4_sel;
+ case 5:
+ return muxes->mux5_sel;
+ case 6:
+ return muxes->mux6_sel;
+ case 7:
+ return muxes->mux7_sel;
+ case 8:
+ return muxes->mux8_sel;
+ case 9:
+ return muxes->mux9_sel;
+ case 10:
+ return muxes->mux10_sel;
+ case 11:
+ return muxes->mux11_sel;
+ case 12:
+ return muxes->mux12_sel;
+ case 13:
+ return muxes->mux13_sel;
+ case 14:
+ return muxes->mux14_sel;
+ case 15:
+ return muxes->mux15_sel;
+ default:
+ return -EINVAL;
+ }
+}
+
+static uint32_t pxp_store_ctrl_config(struct pxp_pixmap *out, uint8_t mode,
+ uint8_t fill_en, uint8_t combine_2ch)
+{
+ struct store_ctrl ctrl;
+ uint8_t output_active_bpp;
+
+ memset((void*)&ctrl, 0x0, sizeof(ctrl));
+
+ if (combine_2ch) {
+ ctrl.combine_2channel = 1;
+ if (out) {
+ output_active_bpp = active_bpp(out->bpp);
+ ctrl.pack_in_sel = (output_active_bpp < 0x3) ? 1 : 0;
+ ctrl.store_memory_en = 1;
+ }
+ } else {
+ if (fill_en) {
+ ctrl.fill_data_en = 1;
+ ctrl.wr_num_bytes = 2;
+ }
+ ctrl.store_memory_en = 1;
+ }
+
+ if (out->rotate || out->flip)
+ ctrl.block_en = 1;
+
+ ctrl.ch_en = 1;
+
+ return *(uint32_t *)&ctrl;
+}
+
+static uint32_t pxp_store_size_config(struct pxp_pixmap *out)
+{
+ struct store_size size;
+
+ memset((void*)&size, 0x0, sizeof(size));
+
+ size.out_height = out->height - 1;
+ size.out_width = out->width - 1;
+
+ return *(uint32_t *)&size;
+}
+
+static uint32_t pxp_store_pitch_config(struct pxp_pixmap *out0,
+ struct pxp_pixmap *out1)
+{
+ struct store_pitch pitch;
+
+ memset((void*)&pitch, 0x0, sizeof(pitch));
+
+ pitch.ch0_out_pitch = out0->pitch;
+ pitch.ch1_out_pitch = out1 ? out1->pitch : 0;
+
+ return *(uint32_t *)&pitch;
+}
+
+static struct color *pxp_find_rgb_color(uint32_t format)
+{
+ int i;
+
+ for (i = 0; i < sizeof(rgb_colors) / sizeof(struct color); i++) {
+ if (rgb_colors[i].format == format)
+ return &rgb_colors[i];
+ }
+
+ return NULL;
+}
+
+static struct color_component *pxp_find_comp(struct color *color, uint8_t id)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (id == color->comp[i].id)
+ return &color->comp[i];
+ }
+
+ return NULL;
+}
+
+static struct color *pxp_find_yuv_color(uint32_t format)
+{
+ int i;
+
+ for (i = 0; i < sizeof(yuv_colors) / sizeof(struct color); i++) {
+ if (yuv_colors[i].format == format)
+ return &yuv_colors[i];
+ }
+
+ return NULL;
+}
+
+static uint64_t pxp_store_d_shift_calc(uint32_t in_fmt, uint32_t out_fmt,
+ struct store_d_mask *d_mask)
+{
+ int i, shift_width, shift_flag, drop = 0;
+ struct store_d_shift d_shift;
+ struct color *input_color, *output_color;
+ struct color_component *input_comp, *output_comp;
+
+ BUG_ON((in_fmt == out_fmt));
+ memset((void*)&d_shift, 0x0, sizeof(d_shift));
+ memset((void*)d_mask, 0x0, sizeof(*d_mask) * 8);
+
+ if (!is_yuv(in_fmt)) {
+ input_color = pxp_find_rgb_color(in_fmt);
+ output_color = pxp_find_rgb_color(out_fmt);
+ } else {
+ input_color = pxp_find_yuv_color(in_fmt);
+ output_color = pxp_find_yuv_color(out_fmt);
+ }
+
+ for (i = 0; i < 4; i++) {
+ input_comp = &input_color->comp[i];
+ if (!input_comp->length)
+ continue;
+
+ output_comp = pxp_find_comp(output_color, input_comp->id);
+ if (!output_comp->length)
+ continue;
+
+ /* only rgb format can drop color bits */
+ if (input_comp->length > output_comp->length) {
+ drop = input_comp->length - output_comp->length;
+ input_comp->offset += drop;
+ }
+ d_mask[i].d_mask_l = output_comp->mask << input_comp->offset;
+
+ shift_width = input_comp->offset - output_comp->offset;
+ if (shift_width > 0)
+ shift_flag = 0; /* right shift */
+ else if (shift_width < 0) {
+ shift_flag = 1; /* left shift */
+ shift_width = -shift_width;
+ } else
+ shift_width = shift_flag = 0; /* no shift require */
+
+ switch (i) {
+ case 0:
+ d_shift.d_shift_width0 = shift_width;
+ d_shift.d_shift_flag0 = shift_flag;
+ break;
+ case 1:
+ d_shift.d_shift_width1 = shift_width;
+ d_shift.d_shift_flag1 = shift_flag;
+ break;
+ case 2:
+ d_shift.d_shift_width2 = shift_width;
+ d_shift.d_shift_flag2 = shift_flag;
+ break;
+ case 3:
+ d_shift.d_shift_width3 = shift_width;
+ d_shift.d_shift_flag3 = shift_flag;
+ break;
+ default:
+ printk(KERN_ERR "unsupport d shift\n");
+ break;
+ }
+
+ input_comp->offset -= drop;
+ }
+
+ return *(uint64_t *)&d_shift;
+}
+
+static uint32_t pxp_store_shift_ctrl_config(struct pxp_pixmap *out,
+ uint8_t shift_bypass)
+{
+ struct store_shift_ctrl shift_ctrl;
+
+ memset((void*)&shift_ctrl, 0x0, sizeof(shift_ctrl));
+
+ shift_ctrl.output_active_bpp = active_bpp(out->bpp);
+ /* Not general data */
+ if (!shift_bypass) {
+ switch(out->format) {
+ case PXP_PIX_FMT_YUYV:
+ shift_bypass = 1;
+ case PXP_PIX_FMT_YVYU:
+ shift_ctrl.out_yuv422_1p_en = 1;
+ break;
+ case PXP_PIX_FMT_NV16:
+ shift_bypass = 1;
+ case PXP_PIX_FMT_NV61:
+ shift_ctrl.out_yuv422_2p_en = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ shift_ctrl.shift_bypass = shift_bypass;
+
+ return *(uint32_t *)&shift_ctrl;
+}
+
+static uint32_t pxp_fetch_ctrl_config(struct pxp_pixmap *in,
+ uint8_t mode)
+{
+ struct fetch_ctrl ctrl;
+
+ memset((void*)&ctrl, 0x0, sizeof(ctrl));
+
+ if (mode == FETCH_MODE_NORMAL)
+ ctrl.bypass_pixel_en = 0;
+
+ if (in->flip == PXP_H_FLIP)
+ ctrl.hflip = 1;
+ else if (in->flip == PXP_V_FLIP)
+ ctrl.vflip = 1;
+
+ ctrl.rotation_angle = rotate_map(in->rotate);
+
+ if (in->rotate || in->flip)
+ ctrl.block_en = 1;
+
+ ctrl.ch_en = 1;
+
+ return *(uint32_t *)&ctrl;
+}
+
+static uint32_t pxp_fetch_active_size_ulc(struct pxp_pixmap *in)
+{
+ struct fetch_active_size_ulc size_ulc;
+
+ memset((void*)&size_ulc, 0x0, sizeof(size_ulc));
+
+ size_ulc.active_size_ulc_x = 0;
+ size_ulc.active_size_ulc_y = 0;
+
+ return *(uint32_t *)&size_ulc;
+}
+
+static uint32_t pxp_fetch_active_size_lrc(struct pxp_pixmap *in)
+{
+ struct fetch_active_size_lrc size_lrc;
+
+ memset((void*)&size_lrc, 0x0, sizeof(size_lrc));
+
+ size_lrc.active_size_lrc_x = in->crop.width - 1;
+ size_lrc.active_size_lrc_y = in->crop.height - 1;
+
+ return *(uint32_t *)&size_lrc;
+}
+
+static uint32_t pxp_fetch_pitch_config(struct pxp_pixmap *in0,
+ struct pxp_pixmap *in1)
+{
+ struct fetch_pitch pitch;
+
+ memset((void*)&pitch, 0x0, sizeof(pitch));
+
+ if (in0)
+ pitch.ch0_input_pitch = in0->pitch;
+ if (in1)
+ pitch.ch1_input_pitch = in1->pitch;
+
+ return *(uint32_t *)&pitch;
+}
+
+static uint32_t pxp_fetch_shift_ctrl_config(struct pxp_pixmap *in,
+ uint8_t shift_bypass,
+ uint8_t need_expand)
+{
+ uint8_t input_expand_format;
+ struct fetch_shift_ctrl shift_ctrl;
+
+ memset((void*)&shift_ctrl, 0x0, sizeof(shift_ctrl));
+
+ shift_ctrl.input_active_bpp = active_bpp(in->bpp);
+ shift_ctrl.shift_bypass = shift_bypass;
+
+ if (in->bpp == 32)
+ need_expand = 0;
+
+ if (need_expand) {
+ input_expand_format = expand_format(in->format);
+
+ if (input_expand_format <= 0x7) {
+ shift_ctrl.expand_en = 1;
+ shift_ctrl.expand_format = input_expand_format;
+ }
+ }
+
+ return *(uint32_t *)&shift_ctrl;
+}
+
+static uint32_t pxp_fetch_shift_calc(uint32_t in_fmt, uint32_t out_fmt,
+ struct fetch_shift_width *shift_width)
+{
+ int i;
+ struct fetch_shift_offset shift_offset;
+ struct color *input_color, *output_color;
+ struct color_component *input_comp, *output_comp;
+
+ memset((void*)&shift_offset, 0x0, sizeof(shift_offset));
+ memset((void*)shift_width, 0x0, sizeof(*shift_width));
+
+ if (!is_yuv(in_fmt)) {
+ input_color = pxp_find_rgb_color(in_fmt);
+ output_color = pxp_find_rgb_color(out_fmt);
+ } else {
+ input_color = pxp_find_yuv_color(in_fmt);
+ output_color = pxp_find_yuv_color(out_fmt);
+ }
+
+ for(i = 0; i < 4; i++) {
+ output_comp = &output_color->comp[i];
+ if (!output_comp->length)
+ continue;
+
+ input_comp = pxp_find_comp(input_color, output_comp->id);
+ switch (i) {
+ case 0:
+ shift_offset.offset0 = input_comp->offset;
+ shift_width->width0 = input_comp->length;
+ break;
+ case 1:
+ shift_offset.offset1 = input_comp->offset;
+ shift_width->width1 = input_comp->length;
+ break;
+ case 2:
+ shift_offset.offset2 = input_comp->offset;
+ shift_width->width2 = input_comp->length;
+ break;
+ case 3:
+ shift_offset.offset3 = input_comp->offset;
+ shift_width->width3 = input_comp->length;
+ break;
+ }
+ }
+
+ return *(uint32_t *)&shift_offset;
+}
+
+static int pxp_start(struct pxps *pxp)
+{
+ __raw_writel(BM_PXP_CTRL_ENABLE_ROTATE1 | BM_PXP_CTRL_ENABLE |
+ BM_PXP_CTRL_ENABLE_CSC2 | BM_PXP_CTRL_ENABLE_LUT |
+ BM_PXP_CTRL_ENABLE_PS_AS_OUT | BM_PXP_CTRL_ENABLE_ROTATE0,
+ pxp->base + HW_PXP_CTRL_SET);
+ dump_pxp_reg(pxp);
+
+ return 0;
+}
+
+static bool fmt_ps_support(uint32_t format)
+{
+ switch (format) {
+ case PXP_PIX_FMT_XRGB32:
+ case PXP_PIX_FMT_ARGB32:
+ case PXP_PIX_FMT_RGB555:
+ case PXP_PIX_FMT_XRGB555:
+ case PXP_PIX_FMT_ARGB555:
+ case PXP_PIX_FMT_RGB444:
+ case PXP_PIX_FMT_XRGB444:
+ case PXP_PIX_FMT_ARGB444:
+ case PXP_PIX_FMT_RGB565:
+ case PXP_PIX_FMT_YUV444:
+ case PXP_PIX_FMT_UYVY:
+ /* need word byte swap */
+ case PXP_PIX_FMT_YUYV:
+ case PXP_PIX_FMT_VYUY:
+ /* need word byte swap */
+ case PXP_PIX_FMT_YVYU:
+ case PXP_PIX_FMT_GREY:
+ case PXP_PIX_FMT_GY04:
+ case PXP_PIX_FMT_NV16:
+ case PXP_PIX_FMT_NV12:
+ case PXP_PIX_FMT_NV61:
+ case PXP_PIX_FMT_NV21:
+ case PXP_PIX_FMT_YUV422P:
+ case PXP_PIX_FMT_YUV420P:
+ case PXP_PIX_FMT_YVU420P:
+ case PXP_PIX_FMT_RGBA32:
+ case PXP_PIX_FMT_RGBX32:
+ case PXP_PIX_FMT_RGBA555:
+ case PXP_PIX_FMT_RGBA444:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool fmt_as_support(uint32_t format)
+{
+ switch (format) {
+ case PXP_PIX_FMT_ARGB32:
+ case PXP_PIX_FMT_RGBA32:
+ case PXP_PIX_FMT_XRGB32:
+ case PXP_PIX_FMT_BGRA32:
+ case PXP_PIX_FMT_ARGB555:
+ case PXP_PIX_FMT_ARGB444:
+ case PXP_PIX_FMT_RGBA555:
+ case PXP_PIX_FMT_RGBA444:
+ case PXP_PIX_FMT_RGB555:
+ case PXP_PIX_FMT_RGB444:
+ case PXP_PIX_FMT_RGB565:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool fmt_out_support(uint32_t format)
+{
+ switch (format) {
+ case PXP_PIX_FMT_ARGB32:
+ case PXP_PIX_FMT_XRGB32:
+ case PXP_PIX_FMT_BGRA32:
+ case PXP_PIX_FMT_RGB24:
+ case PXP_PIX_FMT_ARGB555:
+ case PXP_PIX_FMT_ARGB444:
+ case PXP_PIX_FMT_RGB555:
+ case PXP_PIX_FMT_RGB444:
+ case PXP_PIX_FMT_RGB565:
+ case PXP_PIX_FMT_YUV444:
+ case PXP_PIX_FMT_UYVY:
+ case PXP_PIX_FMT_VYUY:
+ case PXP_PIX_FMT_GREY:
+ case PXP_PIX_FMT_GY04:
+ case PXP_PIX_FMT_NV16:
+ case PXP_PIX_FMT_NV12:
+ case PXP_PIX_FMT_NV61:
+ case PXP_PIX_FMT_NV21:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* common means 'ARGB32/XRGB32/YUV444' */
+static uint8_t fmt_fetch_to_common(uint32_t in)
+{
+ switch (in) {
+ case PXP_PIX_FMT_ARGB32:
+ case PXP_PIX_FMT_XRGB32:
+ case PXP_PIX_FMT_YUV444:
+ return FETCH_NOOP;
+
+ case PXP_PIX_FMT_RGB565:
+ case PXP_PIX_FMT_RGB555:
+ case PXP_PIX_FMT_ARGB555:
+ case PXP_PIX_FMT_RGB444:
+ case PXP_PIX_FMT_ARGB444:
+ case PXP_PIX_FMT_YUYV:
+ case PXP_PIX_FMT_UYVY:
+ case PXP_PIX_FMT_NV16:
+ return FETCH_EXPAND;
+
+ case PXP_PIX_FMT_RGBA32:
+ case PXP_PIX_FMT_RGBX32:
+ case PXP_PIX_FMT_BGRA32:
+ case PXP_PIX_FMT_BGRX32:
+ case PXP_PIX_FMT_ABGR32:
+ case PXP_PIX_FMT_XBGR32:
+ case PXP_PIX_FMT_YVU444:
+ return FETCH_SHIFT;
+
+ case PXP_PIX_FMT_BGR565:
+ case PXP_PIX_FMT_YVYU:
+ case PXP_PIX_FMT_VYUY:
+ return FETCH_EXPAND | FETCH_SHIFT;
+
+ default:
+ return 0;
+ }
+}
+
+static uint8_t fmt_store_from_common(uint32_t out)
+{
+ switch (out) {
+ case PXP_PIX_FMT_ARGB32:
+ case PXP_PIX_FMT_XRGB32:
+ case PXP_PIX_FMT_YUV444:
+ return STORE_NOOP;
+
+ case PXP_PIX_FMT_YUYV:
+ case PXP_PIX_FMT_NV16:
+ return STORE_SHRINK;
+
+ case PXP_PIX_FMT_RGBA32:
+ case PXP_PIX_FMT_RGBX32:
+ case PXP_PIX_FMT_BGRA32:
+ case PXP_PIX_FMT_BGRX32:
+ case PXP_PIX_FMT_ABGR32:
+ case PXP_PIX_FMT_XBGR32:
+ case PXP_PIX_FMT_YVU444:
+ case PXP_PIX_FMT_RGB565:
+ case PXP_PIX_FMT_RGB555:
+ case PXP_PIX_FMT_ARGB555:
+ case PXP_PIX_FMT_RGB444:
+ case PXP_PIX_FMT_ARGB444:
+ case PXP_PIX_FMT_GREY:
+ return STORE_SHIFT;
+
+ case PXP_PIX_FMT_YVYU:
+ case PXP_PIX_FMT_NV61:
+ return STORE_SHIFT | STORE_SHRINK;
+
+ default:
+ return 0;
+ }
+}
+
+static void filter_possible_inputs(struct pxp_pixmap *input,
+ uint32_t *possible)
+{
+ uint8_t clear = 0xff;
+ uint8_t position = 0;
+
+ do {
+ position = find_next_bit((unsigned long *)possible, 32, position);
+ if (position >= sizeof(uint32_t) * 8)
+ break;
+
+ switch (position) {
+ case PXP_2D_PS:
+ if (!fmt_ps_support(input->format))
+ clear = PXP_2D_PS;
+ break;
+ case PXP_2D_AS:
+ if (!fmt_as_support(input->format))
+ clear = PXP_2D_AS;
+ break;
+ case PXP_2D_INPUT_FETCH0:
+ case PXP_2D_INPUT_FETCH1:
+ if ((is_yuv(input->format) == 3)) {
+ clear = position;
+ break;
+ }
+ if ((input->flags & IN_NEED_FMT_UNIFIED) ||
+ is_yuv(input->format) == 2)
+ if (!fmt_fetch_to_common(input->format))
+ clear = position;
+ break;
+ default:
+ pr_err("invalid input node: %d\n", position);
+ clear = position;
+ break;
+ }
+
+ if (clear != 0xff) {
+ clear_bit(clear, (unsigned long*)possible);
+ clear = 0xff;
+ }
+
+ position++;
+ } while (1);
+}
+
+static void filter_possible_outputs(struct pxp_pixmap *output,
+ uint32_t *possible)
+{
+ uint8_t clear = 0xff;
+ uint8_t position = 0;
+
+ do {
+ position = find_next_bit((unsigned long *)possible, 32, position);
+ if (position >= sizeof(uint32_t) * 8)
+ break;
+
+ switch (position) {
+ case PXP_2D_OUT:
+ if (!fmt_out_support(output->format))
+ clear = PXP_2D_OUT;
+ break;
+ case PXP_2D_INPUT_STORE0:
+ case PXP_2D_INPUT_STORE1:
+ if (output->flags) {
+ if (!fmt_store_from_common(output->format))
+ clear = position;
+ }
+ break;
+ default:
+ pr_err("invalid output node: %d\n", position);
+ clear = position;
+ break;
+ }
+
+ if (clear != 0xff) {
+ clear_bit(clear, (unsigned long*)possible);
+ clear = 0xff;
+ }
+
+ position++;
+ } while (1);
+}
+
+static uint32_t calc_shortest_path(uint32_t *nodes_used)
+{
+ uint32_t distance = 0;
+ uint32_t from = 0, to = 0, bypass, end;
+
+ do {
+ from = find_next_bit((unsigned long *)nodes_used, 32, from);
+ if (from >= sizeof(uint32_t) * 8)
+ break;
+
+ if (to != 0) {
+ if (path_table[to][from].distance == DISTANCE_INFINITY)
+ return DISTANCE_INFINITY;
+
+ distance += path_table[to][from].distance;
+ /* backtrace */
+ end = from;
+ while (1) {
+ bypass = path_table[to][end].prev_node;
+ if (bypass == to)
+ break;
+ set_bit(bypass, (unsigned long*)nodes_used);
+ end = bypass;
+ }
+ }
+
+ to = find_next_bit((unsigned long *)nodes_used, 32, from + 1);
+ if (to >= sizeof(uint32_t) * 8)
+ break;
+
+ if (path_table[from][to].distance == DISTANCE_INFINITY)
+ return DISTANCE_INFINITY;
+
+ distance += path_table[from][to].distance;
+ /* backtrace */
+ end = to;
+ while (1) {
+ bypass = path_table[from][end].prev_node;
+ if (bypass == from)
+ break;
+ set_bit(bypass, (unsigned long*)nodes_used);
+ end = bypass;
+ }
+
+ from = to + 1;
+ } while (1);
+
+ return distance;
+}
+
+static uint32_t find_best_path(uint32_t inputs,
+ uint32_t outputs,
+ struct pxp_pixmap *in,
+ uint32_t *nodes_used)
+{
+ uint32_t outs;
+ uint32_t nodes_add, best_nodes_used = 0;
+ uint8_t in_pos = 0, out_pos = 0;
+ uint32_t nodes_in_path, best_nodes_in_path = 0;
+ uint32_t best_distance = DISTANCE_INFINITY, distance;
+
+ do {
+ outs = outputs;
+ in_pos = find_next_bit((unsigned long *)&inputs, 32, in_pos);
+ if (in_pos >= sizeof(uint32_t) * 8)
+ break;
+ nodes_add = 0;
+ set_bit(in_pos, (unsigned long *)&nodes_add);
+
+ switch (in_pos) {
+ case PXP_2D_PS:
+ if ((in->flags & IN_NEED_CSC) == IN_NEED_CSC) {
+ if (is_yuv(in->format))
+ set_bit(PXP_2D_CSC1,
+ (unsigned long *)&nodes_add);
+ else
+ set_bit(PXP_2D_CSC2,
+ (unsigned long *)&nodes_add);
+ }
+ if ((in->flags & IN_NEED_ROTATE_FLIP) == IN_NEED_ROTATE_FLIP)
+ set_bit(PXP_2D_ROTATION1,
+ (unsigned long *)&nodes_add);
+ clear_bit(PXP_2D_INPUT_STORE0, (unsigned long *)&outs);
+ break;
+ case PXP_2D_AS:
+ if ((in->flags & IN_NEED_CSC) == IN_NEED_CSC)
+ set_bit(PXP_2D_CSC2,
+ (unsigned long *)&nodes_add);
+ if ((in->flags & IN_NEED_ROTATE_FLIP) == IN_NEED_ROTATE_FLIP)
+ set_bit(PXP_2D_ROTATION0,
+ (unsigned long *)&nodes_add);
+ clear_bit(PXP_2D_INPUT_STORE0, (unsigned long *)&outs);
+ break;
+ case PXP_2D_INPUT_FETCH0:
+ case PXP_2D_INPUT_FETCH1:
+ if ((in->flags & IN_NEED_CSC) == IN_NEED_CSC)
+ set_bit(PXP_2D_CSC2,
+ (unsigned long *)&nodes_add);
+ clear_bit(PXP_2D_OUT, (unsigned long *)&outs);
+ if ((in->flags & IN_NEED_ROTATE_FLIP) == IN_NEED_ROTATE_FLIP)
+ set_bit(PXP_2D_ROTATION1,
+ (unsigned long *)&nodes_add);
+ break;
+ default:
+ /* alph0_s0/s1, alpha1_s0/s1 */
+ break;
+ }
+
+ nodes_add |= *nodes_used;
+
+ do {
+ out_pos = find_next_bit((unsigned long *)&outs, 32, out_pos);
+ if (out_pos >= sizeof(uint32_t) * 8)
+ break;
+ set_bit(out_pos, (unsigned long *)&nodes_add);
+
+ switch(out_pos) {
+ case PXP_2D_ALPHA0_S0:
+ case PXP_2D_ALPHA0_S1:
+ case PXP_2D_ALPHA1_S0:
+ case PXP_2D_ALPHA1_S1:
+ clear_bit(PXP_2D_CSC2, (unsigned long *)&nodes_add);
+ clear_bit(PXP_2D_ROTATION0, (unsigned long *)&nodes_add);
+ clear_bit(PXP_2D_LUT, (unsigned long *)&nodes_add);
+ break;
+ default:
+ break;
+ }
+
+ nodes_in_path = nodes_add;
+ distance = calc_shortest_path(&nodes_in_path);
+ if (best_distance > distance) {
+ best_distance = distance;
+ best_nodes_used = nodes_add;
+ best_nodes_in_path = nodes_in_path;
+ }
+ pr_debug("%s: out_pos = %d, nodes_in_path = 0x%x, nodes_add = 0x%x, distance = 0x%x\n",
+ __func__, out_pos, nodes_in_path, nodes_add, distance);
+
+ clear_bit(out_pos, (unsigned long *)&nodes_add);
+
+ out_pos++;
+ } while (1);
+
+ in_pos++;
+ } while (1);
+
+ *nodes_used = best_nodes_used;
+
+ return best_nodes_in_path;
+}
+
+static uint32_t ps_calc_scaling(struct pxp_pixmap *input,
+ struct pxp_pixmap *output,
+ struct ps_ctrl *ctrl)
+{
+ struct ps_scale scale;
+ uint32_t decx, decy;
+
+ memset((void*)&scale, 0x0, sizeof(scale));
+
+ if (!output->crop.width || !output->crop.height) {
+ pr_err("Invalid drect width and height passed in\n");
+ return 0;
+ }
+
+ if ((input->rotate == 90) || (input->rotate == 270))
+ swap(output->crop.width, output->crop.height);
+
+ decx = input->crop.width / output->crop.width;
+ decy = input->crop.height / output->crop.height;
+
+ if (decx > 1) {
+ if (decx >= 2 && decx < 4) {
+ decx = 2;
+ ctrl->decx = 1;
+ } else if (decx >= 4 && decx < 8) {
+ decx = 4;
+ ctrl->decx = 2;
+ } else if (decx >= 8) {
+ decx = 8;
+ ctrl->decx = 3;
+ }
+ scale.xscale = input->crop.width * 0x1000 /
+ (output->crop.width * decx);
+ } else {
+ if (!is_yuv(input->format) ||
+ (is_yuv(input->format) == is_yuv(output->format)) ||
+ (input->format == PXP_PIX_FMT_GREY) ||
+ (input->format == PXP_PIX_FMT_GY04) ||
+ (input->format == PXP_PIX_FMT_VUY444)) {
+ if ((input->crop.width > 1) &&
+ (output->crop.width > 1))
+ scale.xscale = (input->crop.width - 1) * 0x1000 /
+ (output->crop.width - 1);
+ else
+ scale.xscale = input->crop.width * 0x1000 /
+ output->crop.width;
+ } else {
+ if ((input->crop.width > 2) &&
+ (output->crop.width > 1))
+ scale.xscale = (input->crop.width - 2) * 0x1000 /
+ (output->crop.width - 1);
+ else
+ scale.xscale = input->crop.width * 0x1000 /
+ output->crop.width;
+ }
+ }
+
+ if (decy > 1) {
+ if (decy >= 2 && decy < 4) {
+ decy = 2;
+ ctrl->decy = 1;
+ } else if (decy >= 4 && decy < 8) {
+ decy = 4;
+ ctrl->decy = 2;
+ } else if (decy >= 8) {
+ decy = 8;
+ ctrl->decy = 3;
+ }
+ scale.yscale = input->crop.height * 0x1000 /
+ (output->crop.height * decy);
+ } else {
+ if ((input->crop.height > 1) && (output->crop.height > 1))
+ scale.yscale = (input->crop.height - 1) * 0x1000 /
+ (output->crop.height - 1);
+ else
+ scale.yscale = input->crop.height * 0x1000 /
+ output->crop.height;
+ }
+
+ return *(uint32_t *)&scale;
+}
+
+static int pxp_ps_config(struct pxp_pixmap *input,
+ struct pxp_pixmap *output)
+{
+ uint32_t offset, U, V;
+ struct ps_ctrl ctrl;
+ struct coordinate out_ps_ulc, out_ps_lrc;
+
+ memset((void*)&ctrl, 0x0, sizeof(ctrl));
+
+ ctrl.format = pxp_parse_ps_fmt(input->format);
+
+ switch (output->rotate) {
+ case 0:
+ out_ps_ulc.x = output->crop.x;
+ out_ps_ulc.y = output->crop.y;
+ out_ps_lrc.x = out_ps_ulc.x + output->crop.width - 1;
+ out_ps_lrc.y = out_ps_ulc.y + output->crop.height - 1;
+ break;
+ case 90:
+ out_ps_ulc.x = output->crop.y;
+ out_ps_ulc.y = output->width - (output->crop.x + output->crop.width);
+ out_ps_lrc.x = out_ps_ulc.x + output->crop.height - 1;
+ out_ps_lrc.y = out_ps_ulc.y + output->crop.width - 1;
+ break;
+ case 180:
+ out_ps_ulc.x = output->width - (output->crop.x + output->crop.width);
+ out_ps_ulc.y = output->height - (output->crop.y + output->crop.height);
+ out_ps_lrc.x = out_ps_ulc.x + output->crop.width - 1;
+ out_ps_lrc.y = out_ps_ulc.y + output->crop.height - 1;
+ break;
+ case 270:
+ out_ps_ulc.x = output->height - (output->crop.y + output->crop.height);
+ out_ps_ulc.y = output->crop.x;
+ out_ps_lrc.x = out_ps_ulc.x + output->crop.height - 1;
+ out_ps_lrc.y = out_ps_ulc.y + output->crop.width - 1;
+ break;
+ default:
+ pr_err("PxP only support rotate 0 90 180 270\n");
+ return -EINVAL;
+ break;
+ }
+
+ if ((input->format == PXP_PIX_FMT_YUYV) ||
+ (input->format == PXP_PIX_FMT_YVYU))
+ ctrl.wb_swap = 1;
+
+ pxp_writel(ps_calc_scaling(input, output, &ctrl),
+ HW_PXP_PS_SCALE);
+ pxp_writel(*(uint32_t *)&ctrl, HW_PXP_PS_CTRL);
+
+ offset = input->crop.y * input->pitch +
+ input->crop.x * (input->bpp >> 3);
+ pxp_writel(input->paddr + offset, HW_PXP_PS_BUF);
+
+ switch (is_yuv(input->format)) {
+ case 0: /* RGB */
+ case 1: /* 1 Plane YUV */
+ break;
+ case 2: /* NV16,NV61,NV12,NV21 */
+ if ((input->format == PXP_PIX_FMT_NV16) ||
+ (input->format == PXP_PIX_FMT_NV61)) {
+ U = input->paddr + input->width * input->height;
+ pxp_writel(U + offset, HW_PXP_PS_UBUF);
+ }
+ else {
+ U = input->paddr + input->width * input->height;
+ pxp_writel(U + (offset >> 1), HW_PXP_PS_UBUF);
+ }
+ break;
+ case 3: /* YUV422P, YUV420P */
+ if (input->format == PXP_PIX_FMT_YUV422P) {
+ U = input->paddr + input->width * input->height;
+ pxp_writel(U + (offset >> 1), HW_PXP_PS_UBUF);
+ V = U + (input->width * input->height >> 1);
+ pxp_writel(V + (offset >> 1), HW_PXP_PS_VBUF);
+ } else if (input->format == PXP_PIX_FMT_YUV420P) {
+ U = input->paddr + input->width * input->height;
+ pxp_writel(U + (offset >> 2), HW_PXP_PS_UBUF);
+ V = U + (input->width * input->height >> 2);
+ pxp_writel(V + (offset >> 2), HW_PXP_PS_VBUF);
+ } else if (input->format == PXP_PIX_FMT_YVU420P) {
+ U = input->paddr + input->width * input->height;
+ V = U + (input->width * input->height >> 2);
+ pxp_writel(U + (offset >> 2), HW_PXP_PS_VBUF);
+ pxp_writel(V + (offset >> 2), HW_PXP_PS_UBUF);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ pxp_writel(input->pitch, HW_PXP_PS_PITCH);
+ pxp_writel(*(uint32_t *)&out_ps_ulc, HW_PXP_OUT_PS_ULC);
+ pxp_writel(*(uint32_t *)&out_ps_lrc, HW_PXP_OUT_PS_LRC);
+
+ pxp_writel(BF_PXP_CTRL_ENABLE_PS_AS_OUT(1) |
+ BF_PXP_CTRL_IRQ_ENABLE(1),
+ HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static int pxp_as_config(struct pxp_pixmap *input,
+ struct pxp_pixmap *output)
+{
+ uint32_t offset;
+ struct as_ctrl ctrl;
+ struct coordinate out_as_ulc, out_as_lrc;
+
+ memset((void*)&ctrl, 0x0, sizeof(ctrl));
+
+ ctrl.format = pxp_parse_as_fmt(input->format);
+
+ if (alpha_blending_version == PXP_ALPHA_BLENDING_V1) {
+ if (input->format == PXP_PIX_FMT_BGRA32) {
+ if (!input->g_alpha.combine_enable) {
+ ctrl.alpha_ctrl = BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs;
+ ctrl.rop = 0x3;
+ }
+ }
+
+ if (input->g_alpha.global_alpha_enable) {
+ if (input->g_alpha.global_override)
+ ctrl.alpha_ctrl = BV_PXP_AS_CTRL_ALPHA_CTRL__Override;
+ else
+ ctrl.alpha_ctrl = BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply;
+
+ if (input->g_alpha.alpha_invert)
+ ctrl.alpha0_invert = 0x1;
+ }
+
+ if (input->g_alpha.color_key_enable) {
+ ctrl.enable_colorkey = 1;
+ }
+
+ ctrl.alpha = input->g_alpha.global_alpha;
+ }
+
+ out_as_ulc.x = out_as_ulc.y = 0;
+ if (input->g_alpha.combine_enable) {
+ out_as_lrc.x = input->width - 1;
+ out_as_lrc.y = input->height - 1;
+ } else {
+ out_as_lrc.x = output->crop.width - 1;
+ out_as_lrc.y = output->crop.height - 1;
+ }
+
+ offset = input->crop.y * input->pitch +
+ input->crop.x * (input->bpp >> 3);
+ pxp_writel(input->paddr + offset, HW_PXP_AS_BUF);
+
+ pxp_writel(input->pitch, HW_PXP_AS_PITCH);
+ pxp_writel(*(uint32_t *)&out_as_ulc, HW_PXP_OUT_AS_ULC);
+ pxp_writel(*(uint32_t *)&out_as_lrc, HW_PXP_OUT_AS_LRC);
+
+ pxp_writel(*(uint32_t *)&ctrl, HW_PXP_AS_CTRL);
+ pxp_writel(BF_PXP_CTRL_ENABLE_PS_AS_OUT(1) |
+ BF_PXP_CTRL_IRQ_ENABLE(1),
+ HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static uint32_t pxp_fetch_size_config(struct pxp_pixmap *input)
+{
+ struct fetch_size total_size;
+
+ memset((void*)&total_size, 0x0, sizeof(total_size));
+
+ total_size.input_total_width = input->width - 1;
+ total_size.input_total_height = input->height - 1;
+
+ return *(uint32_t *)&total_size;
+}
+
+static int pxp_fetch_config(struct pxp_pixmap *input,
+ uint32_t fetch_index)
+{
+ uint8_t shift_bypass = 1, expand_en = 0;
+ uint32_t flags, pitch = 0, offset, UV = 0;
+ uint32_t in_fmt, out_fmt;
+ uint32_t size_ulc, size_lrc;
+ uint32_t fetch_ctrl, total_size;
+ uint32_t shift_ctrl, shift_offset = 0;
+ struct fetch_shift_width shift_width;
+
+ memset((unsigned int *)&shift_width, 0x0, sizeof(shift_width));
+ fetch_ctrl = pxp_fetch_ctrl_config(input, FETCH_MODE_NORMAL);
+ size_ulc = pxp_fetch_active_size_ulc(input);
+ size_lrc = pxp_fetch_active_size_lrc(input);
+ total_size = pxp_fetch_size_config(input);
+
+ if (input->flags) {
+ flags = fmt_fetch_to_common(input->format);
+ shift_bypass = (flags & FETCH_SHIFT) ? 0 : 1;
+ expand_en = (flags & FETCH_EXPAND) ? 1 : 0;
+
+ if (!shift_bypass) {
+ if (expand_en) {
+ if (is_yuv(input->format)) {
+ in_fmt = PXP_PIX_FMT_YVU444;
+ out_fmt = PXP_PIX_FMT_YUV444;
+ } else {
+ in_fmt = PXP_PIX_FMT_ABGR32;
+ out_fmt = PXP_PIX_FMT_ARGB32;
+ }
+ } else {
+ in_fmt = input->format;
+ out_fmt = is_yuv(input->format) ?
+ PXP_PIX_FMT_YUV444 :
+ PXP_PIX_FMT_ARGB32;
+ }
+
+ shift_offset = pxp_fetch_shift_calc(in_fmt, out_fmt,
+ &shift_width);
+ }
+ }
+ shift_ctrl = pxp_fetch_shift_ctrl_config(input, shift_bypass, expand_en);
+
+ offset = input->crop.y * input->pitch +
+ input->crop.x * (input->bpp >> 3);
+ if (is_yuv(input->format) == 2)
+ UV = input->paddr + input->width * input->height;
+
+ switch (fetch_index) {
+ case PXP_2D_INPUT_FETCH0:
+ pitch = __raw_readl(pxp_reg_base + HW_PXP_INPUT_FETCH_PITCH);
+ pitch |= pxp_fetch_pitch_config(input, NULL);
+ pxp_writel(fetch_ctrl, HW_PXP_INPUT_FETCH_CTRL_CH0);
+ pxp_writel(size_ulc, HW_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0);
+ pxp_writel(size_lrc, HW_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0);
+ pxp_writel(total_size, HW_PXP_INPUT_FETCH_SIZE_CH0);
+ pxp_writel(shift_ctrl, HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH0);
+ pxp_writel(input->paddr + offset, HW_PXP_INPUT_FETCH_ADDR_0_CH0);
+ if (UV)
+ pxp_writel(UV + offset, HW_PXP_INPUT_FETCH_ADDR_1_CH0);
+ pxp_writel(shift_ctrl, HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH0);
+ if (shift_offset)
+ pxp_writel(*(uint32_t *)&shift_offset, HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0);
+ pxp_writel(*(uint32_t *)&shift_width, HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0);
+ break;
+ case PXP_2D_INPUT_FETCH1:
+ pitch = __raw_readl(pxp_reg_base + HW_PXP_INPUT_FETCH_PITCH);
+ pitch |= pxp_fetch_pitch_config(NULL, input);
+ pxp_writel(fetch_ctrl, HW_PXP_INPUT_FETCH_CTRL_CH1);
+ pxp_writel(size_ulc, HW_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1);
+ pxp_writel(size_lrc, HW_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1);
+ pxp_writel(total_size, HW_PXP_INPUT_FETCH_SIZE_CH1);
+ pxp_writel(shift_ctrl, HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH1);
+ pxp_writel(input->paddr + offset, HW_PXP_INPUT_FETCH_ADDR_0_CH1);
+ if (UV)
+ pxp_writel(UV + offset, HW_PXP_INPUT_FETCH_ADDR_1_CH1);
+ pxp_writel(shift_ctrl, HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH1);
+ if (shift_offset)
+ pxp_writel(*(uint32_t *)&shift_offset, HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1);
+ pxp_writel(*(uint32_t *)&shift_width, HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1);
+ break;
+ default:
+ break;
+ }
+
+ pxp_writel(pitch, HW_PXP_INPUT_FETCH_PITCH);
+ pxp_writel(BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(1), HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static int pxp_csc1_config(struct pxp_pixmap *input,
+ bool is_ycbcr)
+{
+ BUG_ON(!is_yuv(input->format));
+
+ if (!is_ycbcr) {
+ /* YUV -> RGB */
+ pxp_writel(0x04030000, HW_PXP_CSC1_COEF0);
+ pxp_writel(0x01230208, HW_PXP_CSC1_COEF1);
+ pxp_writel(0x076b079c, HW_PXP_CSC1_COEF2);
+
+ return 0;
+ }
+
+ /* YCbCr -> RGB */
+ pxp_writel(0x84ab01f0, HW_PXP_CSC1_COEF0);
+ pxp_writel(0x01980204, HW_PXP_CSC1_COEF1);
+ pxp_writel(0x0730079c, HW_PXP_CSC1_COEF2);
+
+ return 0;
+}
+
+static int pxp_rotation1_config(struct pxp_pixmap *input)
+{
+ uint8_t rotate;
+
+ if (input->flip == PXP_H_FLIP)
+ pxp_writel(BF_PXP_CTRL_HFLIP1(1), HW_PXP_CTRL_SET);
+ else if (input->flip == PXP_V_FLIP)
+ pxp_writel(BF_PXP_CTRL_VFLIP1(1), HW_PXP_CTRL_SET);
+
+ rotate = rotate_map(input->rotate);
+ pxp_writel(BF_PXP_CTRL_ROTATE1(rotate), HW_PXP_CTRL_SET);
+
+ pxp_writel(BF_PXP_CTRL_ENABLE_ROTATE1(1), HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static int pxp_rotation0_config(struct pxp_pixmap *input)
+{
+ uint8_t rotate;
+
+ if (input->flip == PXP_H_FLIP)
+ pxp_writel(BF_PXP_CTRL_HFLIP0(1), HW_PXP_CTRL_SET);
+ else if (input->flip == PXP_V_FLIP)
+ pxp_writel(BF_PXP_CTRL_VFLIP0(1), HW_PXP_CTRL_SET);
+
+ rotate = rotate_map(input->rotate);
+ pxp_writel(BF_PXP_CTRL_ROTATE0(rotate), HW_PXP_CTRL_SET);
+
+ pxp_writel(BF_PXP_CTRL_ENABLE_ROTATE0(1), HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static int pxp_csc2_config(struct pxp_pixmap *output)
+{
+ if (is_yuv(output->format)) {
+ /* RGB -> YUV */
+ pxp_writel(0x4, HW_PXP_CSC2_CTRL);
+ pxp_writel(0x0096004D, HW_PXP_CSC2_COEF0);
+ pxp_writel(0x05DA001D, HW_PXP_CSC2_COEF1);
+ pxp_writel(0x007005B6, HW_PXP_CSC2_COEF2);
+ pxp_writel(0x057C009E, HW_PXP_CSC2_COEF3);
+ pxp_writel(0x000005E6, HW_PXP_CSC2_COEF4);
+ pxp_writel(0x00000000, HW_PXP_CSC2_COEF5);
+ }
+
+ pxp_writel(BF_PXP_CTRL_ENABLE_CSC2(1), HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static int pxp_out_config(struct pxp_pixmap *output)
+{
+ uint32_t offset, UV;
+ struct out_ctrl ctrl;
+ struct coordinate out_lrc;
+
+ memset((void*)&ctrl, 0x0, sizeof(ctrl));
+
+ ctrl.format = pxp_parse_out_fmt(output->format);
+ offset = output->crop.y * output->pitch +
+ output->crop.x * (output->bpp >> 3);
+
+ pxp_writel(*(uint32_t *)&ctrl, HW_PXP_OUT_CTRL);
+
+ pxp_writel(output->paddr, HW_PXP_OUT_BUF);
+ if (is_yuv(output->format) == 2) {
+ UV = output->paddr + output->width * output->height;
+ if ((output->format == PXP_PIX_FMT_NV16) ||
+ (output->format == PXP_PIX_FMT_NV61))
+ pxp_writel(UV + offset, HW_PXP_OUT_BUF2);
+ else
+ pxp_writel(UV + (offset >> 1), HW_PXP_OUT_BUF2);
+ }
+
+ if (output->rotate == 90 || output->rotate == 270) {
+ out_lrc.y = output->width - 1;
+ out_lrc.x = output->height - 1;
+ } else {
+ out_lrc.x = output->width - 1;
+ out_lrc.y = output->height - 1;
+ }
+
+ pxp_writel(*(uint32_t *)&out_lrc, HW_PXP_OUT_LRC);
+
+ pxp_writel(output->pitch, HW_PXP_OUT_PITCH);
+
+ /* set global alpha if necessary */
+ if (output->g_alpha.global_alpha_enable) {
+ pxp_writel(output->g_alpha.global_alpha << 24, HW_PXP_OUT_CTRL_SET);
+ pxp_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT, HW_PXP_OUT_CTRL_SET);
+ }
+
+ pxp_writel(BF_PXP_CTRL_ENABLE_PS_AS_OUT(1) |
+ BF_PXP_CTRL_IRQ_ENABLE(1),
+ HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static int pxp_store_config(struct pxp_pixmap *output,
+ struct pxp_op_info *op)
+{
+ uint8_t combine_2ch, flags;
+ uint32_t in_fmt, out_fmt, offset, UV = 0;
+ uint64_t d_shift = 0;
+ struct store_d_mask d_mask[8];
+ uint32_t store_ctrl, store_size, store_pitch, shift_ctrl;
+
+ memset((void*)d_mask, 0x0, sizeof(*d_mask) * 8);
+ combine_2ch = (output->bpp == 64) ? 1 : 0;
+ store_ctrl = pxp_store_ctrl_config(output, STORE_MODE_NORMAL,
+ op->fill_en, combine_2ch);
+ store_size = pxp_store_size_config(output);
+ store_pitch = pxp_store_pitch_config(output, NULL);
+
+ pxp_writel(store_ctrl, HW_PXP_INPUT_STORE_CTRL_CH0);
+
+ if (output->flags) {
+ flags = fmt_store_from_common(output->format);
+ if (flags == STORE_NOOP)
+ shift_ctrl = pxp_store_shift_ctrl_config(output, 1);
+ else if (flags & STORE_SHIFT) {
+ in_fmt = is_yuv(output->format) ? PXP_PIX_FMT_YUV444 :
+ PXP_PIX_FMT_ARGB32;
+ out_fmt = (flags & STORE_SHRINK) ? PXP_PIX_FMT_YVU444 :
+ output->format;
+ d_shift = pxp_store_d_shift_calc(in_fmt, out_fmt, d_mask);
+ shift_ctrl = pxp_store_shift_ctrl_config(output, 0);
+ } else
+ shift_ctrl = pxp_store_shift_ctrl_config(output, 0);
+
+ if (flags & STORE_SHIFT) {
+ pxp_writel((uint32_t)d_shift, HW_PXP_INPUT_STORE_D_SHIFT_L_CH0);
+ /* TODO use only 4 masks */
+ pxp_writel(d_mask[0].d_mask_l, HW_PXP_INPUT_STORE_D_MASK0_L_CH0);
+ pxp_writel(d_mask[0].d_mask_h, HW_PXP_INPUT_STORE_D_MASK0_H_CH0);
+ pxp_writel(d_mask[1].d_mask_l, HW_PXP_INPUT_STORE_D_MASK1_L_CH0);
+ pxp_writel(d_mask[1].d_mask_h, HW_PXP_INPUT_STORE_D_MASK1_H_CH0);
+ pxp_writel(d_mask[2].d_mask_l, HW_PXP_INPUT_STORE_D_MASK2_L_CH0);
+ pxp_writel(d_mask[2].d_mask_h, HW_PXP_INPUT_STORE_D_MASK2_H_CH0);
+ pxp_writel(d_mask[3].d_mask_l, HW_PXP_INPUT_STORE_D_MASK3_L_CH0);
+ pxp_writel(d_mask[3].d_mask_h, HW_PXP_INPUT_STORE_D_MASK3_H_CH0);
+ }
+ } else
+ shift_ctrl = pxp_store_shift_ctrl_config(output, 1);
+
+ pxp_writel(shift_ctrl, HW_PXP_INPUT_STORE_SHIFT_CTRL_CH0);
+ pxp_writel(store_size, HW_PXP_INPUT_STORE_SIZE_CH0);
+ pxp_writel(store_pitch, HW_PXP_INPUT_STORE_PITCH);
+ if (op->fill_en) {
+ uint32_t lrc;
+
+ lrc = (output->width - 1) | ((output->height - 1) << 16);
+ pxp_writel(op->fill_data, HW_PXP_INPUT_STORE_FILL_DATA_CH0);
+
+ pxp_writel(0x1, HW_PXP_INPUT_FETCH_CTRL_CH0);
+ pxp_writel(0, HW_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0);
+ pxp_writel(lrc, HW_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0);
+ }
+
+ offset = output->crop.y * output->pitch +
+ output->crop.x * (output->bpp >> 3);
+ if (is_yuv(output->format == 2)) {
+ UV = output->paddr + output->width * output->height;
+ pxp_writel(UV + offset, HW_PXP_INPUT_STORE_ADDR_1_CH0);
+ }
+ pxp_writel(output->paddr + offset, HW_PXP_INPUT_STORE_ADDR_0_CH0);
+
+ pxp_writel(BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(1), HW_PXP_CTRL_SET);
+
+ return 0;
+}
+
+static int pxp_alpha_config(struct pxp_op_info *op,
+ uint8_t alpha_node)
+{
+ uint32_t as_ctrl;
+ struct pxp_alpha_ctrl alpha_ctrl;
+ struct pxp_alpha_info *alpha = &op->alpha_info;
+ struct pxp_alpha *s0_alpha, *s1_alpha;
+
+ memset((void*)&alpha_ctrl, 0x0, sizeof(alpha_ctrl));
+
+ if (alpha_blending_version != PXP_ALPHA_BLENDING_V1) {
+ if (alpha->alpha_mode == ALPHA_MODE_ROP) {
+ switch (alpha_node) {
+ case PXP_2D_ALPHA0_S0:
+ as_ctrl = __raw_readl(pxp_reg_base + HW_PXP_AS_CTRL);
+ as_ctrl |= BF_PXP_AS_CTRL_ALPHA_CTRL(BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
+ as_ctrl |= BF_PXP_AS_CTRL_ROP(alpha->rop_type);
+ pxp_writel(as_ctrl, HW_PXP_AS_CTRL);
+ break;
+ case PXP_2D_ALPHA1_S0:
+ pxp_writel(BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE |
+ BF_PXP_ALPHA_B_CTRL_1_ROP(alpha->rop_type),
+ HW_PXP_ALPHA_B_CTRL_1);
+ pxp_writel(BF_PXP_CTRL_ENABLE_ALPHA_B(1), HW_PXP_CTRL_SET);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+ }
+
+ s0_alpha = &alpha->s0_alpha;
+ s1_alpha = &alpha->s1_alpha;
+
+ alpha_ctrl.poter_duff_enable = 1;
+
+ alpha_ctrl.s0_s1_factor_mode = s1_alpha->factor_mode;
+ alpha_ctrl.s0_global_alpha_mode = s0_alpha->global_alpha_mode;
+ alpha_ctrl.s0_alpha_mode = s0_alpha->alpha_mode;
+ alpha_ctrl.s0_color_mode = s0_alpha->color_mode;
+
+ alpha_ctrl.s1_s0_factor_mode = s0_alpha->factor_mode;
+ alpha_ctrl.s1_global_alpha_mode = s1_alpha->global_alpha_mode;
+ alpha_ctrl.s1_alpha_mode = s1_alpha->alpha_mode;
+ alpha_ctrl.s1_color_mode = s1_alpha->color_mode;
+
+ alpha_ctrl.s0_global_alpha = s0_alpha->global_alpha_value;
+ alpha_ctrl.s1_global_alpha = s1_alpha->global_alpha_value;
+
+ switch (alpha_node) {
+ case PXP_2D_ALPHA0_S0:
+ pxp_writel(*(uint32_t *)&alpha_ctrl, HW_PXP_ALPHA_A_CTRL);
+ break;
+ case PXP_2D_ALPHA1_S0:
+ pxp_writel(*(uint32_t *)&alpha_ctrl, HW_PXP_ALPHA_B_CTRL);
+ pxp_writel(BF_PXP_CTRL_ENABLE_ALPHA_B(1), HW_PXP_CTRL_SET);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void pxp_lut_config(struct pxp_op_info *op)
+{
+ struct pxp_task_info *task = to_pxp_task_info(op);
+ struct pxps *pxp = to_pxp_from_task(task);
+ struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data;
+ int lut_op = proc_data->lut_transform;
+ u32 reg_val;
+ int i;
+ bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false;
+ u8 *cmap = proc_data->lut_map;
+ u32 entry_src;
+ u32 pix_val;
+ u8 entry[4];
+
+ /*
+ * If LUT already configured as needed, return...
+ * Unless CMAP is needed and it has been updated.
+ */
+ if ((pxp->lut_state == lut_op) &&
+ !(use_cmap && proc_data->lut_map_updated))
+ return;
+
+ if (lut_op == PXP_LUT_NONE) {
+ __raw_writel(BM_PXP_LUT_CTRL_BYPASS,
+ pxp->base + HW_PXP_LUT_CTRL);
+ } else if (((lut_op & PXP_LUT_INVERT) != 0)
+ && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) {
+ /* Fill out LUT table with inverted monochromized values */
+
+ /* clear bypass bit, set lookup mode & out mode */
+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+ BF_PXP_LUT_CTRL_OUT_MODE
+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+ pxp->base + HW_PXP_LUT_CTRL);
+
+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+ /* LUT address pointer auto-increments after each data write */
+ for (pix_val = 0; pix_val < 256; pix_val += 4) {
+ for (i = 0; i < 4; i++) {
+ entry_src = use_cmap ?
+ cmap[pix_val + i] : pix_val + i;
+ entry[i] = (entry_src < 0x80) ? 0xFF : 0x00;
+ }
+ reg_val = (entry[3] << 24) | (entry[2] << 16) |
+ (entry[1] << 8) | entry[0];
+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+ }
+ } else if ((lut_op & PXP_LUT_INVERT) != 0) {
+ /* Fill out LUT table with 8-bit inverted values */
+
+ /* clear bypass bit, set lookup mode & out mode */
+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+ BF_PXP_LUT_CTRL_OUT_MODE
+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+ pxp->base + HW_PXP_LUT_CTRL);
+
+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+ /* LUT address pointer auto-increments after each data write */
+ for (pix_val = 0; pix_val < 256; pix_val += 4) {
+ for (i = 0; i < 4; i++) {
+ entry_src = use_cmap ?
+ cmap[pix_val + i] : pix_val + i;
+ entry[i] = ~entry_src & 0xFF;
+ }
+ reg_val = (entry[3] << 24) | (entry[2] << 16) |
+ (entry[1] << 8) | entry[0];
+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+ }
+ } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) {
+ /* Fill out LUT table with 8-bit monochromized values */
+
+ /* clear bypass bit, set lookup mode & out mode */
+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+ BF_PXP_LUT_CTRL_OUT_MODE
+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+ pxp->base + HW_PXP_LUT_CTRL);
+
+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+ /* LUT address pointer auto-increments after each data write */
+ for (pix_val = 0; pix_val < 256; pix_val += 4) {
+ for (i = 0; i < 4; i++) {
+ entry_src = use_cmap ?
+ cmap[pix_val + i] : pix_val + i;
+ entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF;
+ }
+ reg_val = (entry[3] << 24) | (entry[2] << 16) |
+ (entry[1] << 8) | entry[0];
+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+ }
+ } else if (use_cmap) {
+ /* Fill out LUT table using colormap values */
+
+ /* clear bypass bit, set lookup mode & out mode */
+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+ BF_PXP_LUT_CTRL_OUT_MODE
+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+ pxp->base + HW_PXP_LUT_CTRL);
+
+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+ /* LUT address pointer auto-increments after each data write */
+ for (pix_val = 0; pix_val < 256; pix_val += 4) {
+ for (i = 0; i < 4; i++)
+ entry[i] = cmap[pix_val + i];
+ reg_val = (entry[3] << 24) | (entry[2] << 16) |
+ (entry[1] << 8) | entry[0];
+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+ }
+ }
+
+ pxp_writel(BM_PXP_CTRL_ENABLE_ROTATE1 | BM_PXP_CTRL_ENABLE_ROTATE0 |
+ BM_PXP_CTRL_ENABLE_CSC2 | BM_PXP_CTRL_ENABLE_LUT,
+ HW_PXP_CTRL_SET);
+
+ pxp->lut_state = lut_op;
+}
+
+static int pxp_2d_task_config(struct pxp_pixmap *input,
+ struct pxp_pixmap *output,
+ struct pxp_op_info *op,
+ uint32_t nodes_used)
+{
+ uint8_t position = 0;
+
+
+ do {
+ position = find_next_bit((unsigned long *)&nodes_used, 32, position);
+ if (position >= sizeof(uint32_t) * 8)
+ break;
+
+ switch (position) {
+ case PXP_2D_PS:
+ pxp_ps_config(input, output);
+ break;
+ case PXP_2D_AS:
+ pxp_as_config(input, output);
+ break;
+ case PXP_2D_INPUT_FETCH0:
+ case PXP_2D_INPUT_FETCH1:
+ pxp_fetch_config(input, position);
+ break;
+ case PXP_2D_CSC1:
+ pxp_csc1_config(input, true);
+ break;
+ case PXP_2D_ROTATION1:
+ pxp_rotation1_config(input);
+ break;
+ case PXP_2D_ALPHA0_S0:
+ case PXP_2D_ALPHA1_S0:
+ pxp_alpha_config(op, position);
+ break;
+ case PXP_2D_ALPHA0_S1:
+ case PXP_2D_ALPHA1_S1:
+ break;
+ case PXP_2D_CSC2:
+ pxp_csc2_config(output);
+ break;
+ case PXP_2D_LUT:
+ pxp_lut_config(op);
+ break;
+ case PXP_2D_ROTATION0:
+ pxp_rotation0_config(input);
+ break;
+ case PXP_2D_OUT:
+ pxp_out_config(output);
+ break;
+ case PXP_2D_INPUT_STORE0:
+ case PXP_2D_INPUT_STORE1:
+ pxp_store_config(output, op);
+ break;
+ default:
+ break;
+ }
+
+ position++;
+ } while (1);
+
+ return 0;
+}
+
+static void mux_config_helper(struct mux_config *path_ctrl,
+ struct edge_node *enode)
+{
+ uint32_t mux_val, mux_pos = 0;
+
+ if (enode->mux_used) {
+ do {
+ mux_pos = find_next_bit((unsigned long *)&enode->mux_used,
+ 32, mux_pos);
+ if (mux_pos >= 16)
+ break;
+
+ mux_val = get_mux_val(&enode->muxes, mux_pos);
+ pr_debug("%s: mux_pos = %d, mux_val = %d\n",
+ __func__, mux_pos, mux_val);
+ set_mux_val(path_ctrl, mux_pos, mux_val);
+
+ mux_pos++;
+ } while (1);
+ }
+}
+
+static void pxp_2d_calc_mux(uint32_t nodes, struct mux_config *path_ctrl)
+{
+ struct edge_node *enode;
+ uint8_t from = 0, to = 0;
+
+ do {
+ from = find_next_bit((unsigned long *)&nodes, 32, from);
+ if (from >= sizeof(uint32_t) * 8)
+ break;
+
+ if (to != 0) {
+ enode = adj_list[to].first;
+ while (enode) {
+ if (enode->adjvex == from) {
+ mux_config_helper(path_ctrl, enode);
+ break;
+ }
+ enode = enode->next;
+ }
+ }
+
+ to = find_next_bit((unsigned long *)&nodes, 32, from + 1);
+ if (to >= sizeof(uint32_t) * 8)
+ break;
+
+ enode = adj_list[from].first;
+ while (enode) {
+ if (enode->adjvex == to) {
+ mux_config_helper(path_ctrl, enode);
+ break;
+ }
+ enode = enode->next;
+ }
+
+ from = to + 1;
+ } while (1);
+}
+
+static int pxp_2d_op_handler(struct pxps *pxp)
+{
+ struct mux_config path_ctrl0;
+ struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data;
+ struct pxp_task_info *task = &pxp->task;
+ struct pxp_op_info *op = &task->op_info;
+ struct pxp_pixmap *input, *output, *input_s0, *input_s1;
+ uint32_t possible_inputs, possible_outputs;
+ uint32_t possible_inputs_s0, possible_inputs_s1;
+ uint32_t inputs_filter_s0, inputs_filter_s1;
+ uint32_t nodes_used = 0, nodes_in_path;
+ uint32_t partial_nodes_used = 0;
+ uint32_t nodes_used_s0 = 0, nodes_used_s1 = 0;
+ uint32_t nodes_in_path_s0, nodes_in_path_s1;
+
+ output = &task->output[0];
+ if (!output->pitch)
+ return -EINVAL;
+
+ *(unsigned int*)&path_ctrl0 = 0xffffffff;
+
+reparse:
+ switch (task->input_num) {
+ case 0:
+ /* Fill operation: use input store engine */
+ if (is_yuv(output->format) > 1)
+ return -EINVAL;
+
+ if (output->bpp > 32)
+ return -EINVAL;
+
+ nodes_used = 1 << PXP_2D_INPUT_STORE0;
+ pxp_2d_task_config(NULL, output, op, nodes_used);
+ break;
+ case 1:
+ /* No Composite */
+ possible_inputs = (1 << PXP_2D_PS) |
+ (1 << PXP_2D_AS) |
+ (1 << PXP_2D_INPUT_FETCH0);
+ possible_outputs = (1 << PXP_2D_OUT) |
+ (1 << PXP_2D_INPUT_STORE0);
+
+ input = &task->input[0];
+ if (!input->pitch)
+ return -EINVAL;
+
+ if (input->rotate || input->flip) {
+ input->flags |= IN_NEED_ROTATE_FLIP;
+ output->rotate = input->rotate;
+ output->flip = input->flip;
+ }
+
+ if (!is_yuv(input->format) != !is_yuv(output->format))
+ input->flags |= IN_NEED_CSC;
+ else if (input->format != output->format)
+ input->flags |= IN_NEED_FMT_UNIFIED;
+
+ if ((input->rotate == 90) || (input->rotate == 270)) {
+ if ((input->crop.width != output->crop.height) ||
+ (input->crop.height != output->crop.width))
+ input->flags |= IN_NEED_SCALE;
+ } else {
+ if ((input->crop.width != output->crop.width) ||
+ (input->crop.height != output->crop.height))
+ input->flags |= IN_NEED_SCALE;
+ }
+
+ if (input->flags) {
+ /* only ps has scaling function */
+ if ((input->flags & IN_NEED_SCALE) == IN_NEED_SCALE)
+ possible_inputs = 1 << PXP_2D_PS;
+ output->flags |= (output->bpp < 32) ? OUT_NEED_SHRINK :
+ OUT_NEED_SHIFT;
+ }
+
+ filter_possible_inputs(input, &possible_inputs);
+ filter_possible_outputs(output, &possible_outputs);
+
+ if (!possible_inputs || !possible_outputs) {
+ dev_err(&pxp->pdev->dev, "unsupport 2d operation\n");
+ return -EINVAL;
+ }
+
+ if (proc_data->lut_transform)
+ nodes_used |= (1 << PXP_2D_LUT);
+
+ nodes_in_path = find_best_path(possible_inputs,
+ possible_outputs,
+ input, &nodes_used);
+
+ if (nodes_in_path & (1 << PXP_2D_ROTATION1)) {
+ clear_bit(PXP_2D_ROTATION1, (unsigned long *)&nodes_in_path);
+ set_bit(PXP_2D_ROTATION0, (unsigned long *)&nodes_in_path);
+ }
+
+ if (nodes_used & (1 << PXP_2D_ROTATION1)) {
+ clear_bit(PXP_2D_ROTATION1, (unsigned long *)&nodes_used);
+ set_bit(PXP_2D_ROTATION0, (unsigned long *)&nodes_used);
+ }
+
+ pr_debug("%s: nodes_in_path = 0x%x, nodes_used = 0x%x\n",
+ __func__, nodes_in_path, nodes_used);
+ if (!nodes_used) {
+ dev_err(&pxp->pdev->dev, "unsupport 2d operation\n");
+ return -EINVAL;
+ }
+
+ /* If use input fetch0, should use
+ * alpha b instead of alpha a */
+ if (nodes_in_path & (1 << PXP_2D_ALPHA0_S0)) {
+ if (nodes_in_path & (1 << PXP_2D_INPUT_FETCH0)) {
+ clear_bit(PXP_2D_ALPHA0_S0,
+ (unsigned long *)&nodes_in_path);
+ set_bit(PXP_2D_ALPHA1_S1,
+ (unsigned long *)&nodes_in_path);
+ }
+ }
+
+ /* In this case input read in
+ * by input fetch engine
+ */
+ if ((nodes_in_path & (1 << PXP_2D_ALPHA1_S1)) ||
+ (nodes_in_path & (1 << PXP_2D_ALPHA1_S0))) {
+ memcpy(&task->input[1], input, sizeof(*input));
+ if (input->rotate == 90 || input->rotate == 270) {
+ uint32_t temp;
+
+ input = &task->input[1];
+ input->rotate = 0;
+ input->flags = 0;
+ temp = input->width;
+ input->width = input->height;
+ input->height = temp;
+ input->pitch = input->width * (input->bpp >> 3);
+ temp = input->crop.width;
+ input->crop.width = input->crop.height;
+ input->crop.height = temp;
+ }
+
+ op->alpha_info.alpha_mode = ALPHA_MODE_ROP;
+ /* s0 AND s1 */
+ op->alpha_info.rop_type = 0x0;
+ task->input_num = 2;
+ goto reparse;
+ }
+
+ pxp_2d_calc_mux(nodes_in_path, &path_ctrl0);
+ pr_debug("%s: path_ctrl0 = 0x%x\n",
+ __func__, *(uint32_t *)&path_ctrl0);
+ pxp_2d_task_config(input, output, op, nodes_used);
+ break;
+ case 2:
+ /* Composite */
+ input_s0 = &task->input[0];
+ input_s1 = &task->input[1];
+ if (!input_s0->pitch || !input_s1->pitch)
+ return -EINVAL;
+
+ possible_inputs_s0 = (1 << PXP_2D_PS) |
+ (1 << PXP_2D_INPUT_FETCH0) |
+ (1 << PXP_2D_INPUT_FETCH1);
+ possible_inputs_s1 = (1 << PXP_2D_AS) |
+ (1 << PXP_2D_INPUT_FETCH0);
+ possible_outputs = (1 << PXP_2D_OUT) |
+ (1 << PXP_2D_INPUT_STORE0);
+
+ if (input_s0->rotate || input_s0->flip) {
+ input_s0->flags |= IN_NEED_ROTATE_FLIP;
+ output->rotate = input_s0->rotate;
+ output->flip = input_s0->flip;
+ }
+ if (input_s1->rotate || input_s1->flip) {
+ input_s1->flags |= IN_NEED_ROTATE_FLIP;
+ clear_bit(PXP_2D_AS,
+ (unsigned long *)&possible_inputs_s1);
+ }
+
+ if (is_yuv(input_s0->format) && is_yuv(input_s1->format))
+ return -EINVAL;
+
+ if (is_yuv(input_s0->format)){
+ /* need do yuv -> rgb conversion by csc1 */
+ possible_inputs_s0 = 1 << PXP_2D_PS;
+ input_s0->flags |= IN_NEED_CSC;
+ } else if (is_yuv(input_s1->format)) {
+ possible_inputs_s1 = 1 << PXP_2D_PS;
+ input_s1->flags |= IN_NEED_CSC;
+ }
+
+ filter_possible_inputs(input_s0, &possible_inputs_s0);
+ filter_possible_inputs(input_s1, &possible_inputs_s1);
+
+ if (!possible_inputs_s0 || !possible_inputs_s0)
+ return -EINVAL;
+
+ filter_possible_outputs(output, &possible_outputs);
+ if (!possible_outputs)
+ return -EINVAL;
+
+ pr_debug("%s: poss_s0 = 0x%x, poss_s1 = 0x%x, poss_out = 0x%x\n",
+ __func__, possible_inputs_s0, possible_inputs_s1, possible_outputs);
+
+ inputs_filter_s0 = possible_inputs_s0;
+ inputs_filter_s1 = possible_inputs_s1;
+
+ /* Using alpha0, possible cases:
+ * 1. PS --> S0, AS --> S1;
+ */
+ if (possible_inputs_s1 & (1 << PXP_2D_AS)) {
+ clear_bit(PXP_2D_INPUT_FETCH0,
+ (unsigned long *)&possible_inputs_s0);
+ clear_bit(PXP_2D_INPUT_FETCH1,
+ (unsigned long *)&possible_inputs_s0);
+ clear_bit(PXP_2D_INPUT_STORE0,
+ (unsigned long *)&possible_outputs);
+
+ if (!possible_inputs_s0 || !possible_outputs)
+ goto alpha1;
+
+ nodes_in_path_s0 = find_best_path(possible_inputs_s0,
+ 1 << PXP_2D_ALPHA0_S0,
+ input_s0,
+ &partial_nodes_used);
+ if (!nodes_in_path_s0)
+ goto alpha1;
+
+ nodes_used_s0 |= partial_nodes_used;
+ partial_nodes_used = 0;
+
+ if (is_yuv(output->format))
+ set_bit(PXP_2D_CSC2,
+ (unsigned long *)&partial_nodes_used);
+ if (output->rotate || output->flip)
+ set_bit(PXP_2D_ROTATION0,
+ (unsigned long *)&partial_nodes_used);
+
+ nodes_in_path_s0 |= find_best_path(1 << PXP_2D_ALPHA0_S0,
+ possible_outputs,
+ input_s0,
+ &partial_nodes_used);
+ if (!(nodes_in_path_s0 & possible_outputs))
+ goto alpha1;
+ nodes_used_s0 |= partial_nodes_used;
+
+ possible_inputs_s1 = (1 << PXP_2D_AS);
+ nodes_in_path_s1 = find_best_path(possible_inputs_s1,
+ 1 << PXP_2D_ALPHA0_S1,
+ input_s1,
+ &nodes_used_s1);
+ if (!nodes_in_path_s1)
+ goto alpha1;
+
+ goto config;
+ }
+alpha1:
+ partial_nodes_used = 0;
+ possible_inputs_s0 = inputs_filter_s0;
+ possible_inputs_s1 = inputs_filter_s1;
+
+ /* Using alpha1, possible cases:
+ * 1. FETCH1 --> S0, FETCH0 --> S1;
+ */
+ clear_bit(PXP_2D_PS,
+ (unsigned long *)&possible_inputs_s0);
+ clear_bit(PXP_2D_INPUT_FETCH0,
+ (unsigned long *)&possible_inputs_s0);
+ clear_bit(PXP_2D_OUT,
+ (unsigned long *)&possible_outputs);
+
+ if (!possible_inputs_s0 || !possible_outputs)
+ return -EINVAL;
+
+ nodes_in_path_s0 = find_best_path(possible_inputs_s0,
+ 1 << PXP_2D_ALPHA1_S0,
+ input_s0,
+ &partial_nodes_used);
+ pr_debug("%s: nodes_in_path_s0 = 0x%x\n", __func__, nodes_in_path_s0);
+ BUG_ON(!nodes_in_path_s0);
+
+ nodes_used_s0 |= partial_nodes_used;
+ if ((nodes_used_s0 & (1 << PXP_2D_INPUT_FETCH0)) ||
+ (nodes_used_s0 & (1 << PXP_2D_INPUT_FETCH1)))
+ clear_bit(PXP_2D_OUT, (unsigned long *)&possible_outputs);
+ else
+ clear_bit(PXP_2D_INPUT_STORE0,
+ (unsigned long *)&possible_outputs);
+ partial_nodes_used = 0;
+
+ if (is_yuv(output->format))
+ set_bit(PXP_2D_CSC2,
+ (unsigned long *)&partial_nodes_used);
+ if (output->rotate || output->flip)
+ set_bit(PXP_2D_ROTATION0,
+ (unsigned long *)&partial_nodes_used);
+
+ nodes_in_path_s0 |= find_best_path(1 << PXP_2D_ALPHA1_S0,
+ possible_outputs,
+ input_s0,
+ &partial_nodes_used);
+ BUG_ON(!(nodes_in_path_s0 & possible_outputs));
+ nodes_used_s0 |= partial_nodes_used;
+ pr_debug("%s: nodes_in_path_s0 = 0x%x, nodes_used_s0 = 0x%x\n",
+ __func__, nodes_in_path_s0, nodes_used_s0);
+
+ clear_bit(PXP_2D_AS,
+ (unsigned long *)&possible_inputs_s1);
+ BUG_ON(!possible_inputs_s1);
+
+ nodes_in_path_s1 = find_best_path(possible_inputs_s1,
+ 1 << PXP_2D_ALPHA1_S1,
+ input_s1,
+ &nodes_used_s1);
+ pr_debug("%s: poss_s1 = 0x%x, nodes_used_s1 = 0x%x\n",
+ __func__, possible_inputs_s1, nodes_used_s1);
+ BUG_ON(!nodes_in_path_s1);
+ /* To workaround an IC bug */
+ path_ctrl0.mux4_sel = 0x0;
+config:
+ if (nodes_in_path_s0 & (1 << PXP_2D_ROTATION1)) {
+ clear_bit(PXP_2D_ROTATION1, (unsigned long *)&nodes_in_path_s0);
+ set_bit(PXP_2D_ROTATION0, (unsigned long *)&nodes_in_path_s0);
+ }
+
+ pr_debug("%s: nodes_in_path_s0 = 0x%x, nodes_used_s0 = 0x%x, nodes_in_path_s1 = 0x%x, nodes_used_s1 = 0x%x\n",
+ __func__, nodes_in_path_s0, nodes_used_s0, nodes_in_path_s1, nodes_used_s1);
+ pxp_2d_calc_mux(nodes_in_path_s0, &path_ctrl0);
+ pxp_2d_calc_mux(nodes_in_path_s1, &path_ctrl0);
+
+ pr_debug("%s: s0 paddr = 0x%x, s1 paddr = 0x%x, out paddr = 0x%x\n",
+ __func__, input_s0->paddr, input_s1->paddr, output->paddr);
+
+ if (nodes_used_s0 & (1 << PXP_2D_ROTATION1)) {
+ clear_bit(PXP_2D_ROTATION1, (unsigned long *)&nodes_used_s0);
+ set_bit(PXP_2D_ROTATION0, (unsigned long *)&nodes_used_s0);
+ }
+
+ pxp_2d_task_config(input_s0, output, op, nodes_used_s0);
+ pxp_2d_task_config(input_s1, output, op, nodes_used_s1);
+ break;
+ default:
+ break;
+ }
+
+ __raw_writel(proc_data->bgcolor,
+ pxp->base + HW_PXP_PS_BACKGROUND_0);
+ pxp_set_colorkey(pxp);
+
+ if (proc_data->lut_transform && pxp_is_v3(pxp))
+ set_mux(&path_ctrl0);
+
+ pr_debug("%s: path_ctrl0 = 0x%x\n",
+ __func__, *(uint32_t *)&path_ctrl0);
+ pxp_writel(*(uint32_t *)&path_ctrl0, HW_PXP_DATA_PATH_CTRL0);
+
+ return 0;
+}
+
+/**
+ * pxp_config() - configure PxP for a processing task
+ * @pxps: PXP context.
+ * @pxp_chan: PXP channel.
+ * @return: 0 on success or negative error code on failure.
+ */
+static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
+{
+ int ret = 0;
+ struct pxp_task_info *task = &pxp->task;
+ struct pxp_op_info *op = &task->op_info;
+ struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf_data->proc_data;
+
+ switch (op->op_type) {
+ case PXP_OP_TYPE_2D:
+ pxp_writel(0xffffffff, HW_PXP_OUT_AS_ULC);
+ pxp_writel(0x0, HW_PXP_OUT_AS_LRC);
+ pxp_writel(0xffffffff, HW_PXP_OUT_PS_ULC);
+ pxp_writel(0x0, HW_PXP_OUT_PS_LRC);
+ pxp_writel(0x0, HW_PXP_INPUT_FETCH_PITCH);
+ pxp_writel(0x40000000, HW_PXP_CSC1_COEF0);
+ ret = pxp_2d_op_handler(pxp);
+ break;
+ case PXP_OP_TYPE_DITHER:
+ pxp_dithering_process(pxp);
+ if (pxp_is_v3p(pxp)) {
+ __raw_writel(
+ BM_PXP_CTRL_ENABLE |
+ BM_PXP_CTRL_ENABLE_DITHER |
+ BM_PXP_CTRL_ENABLE_CSC2 |
+ BM_PXP_CTRL_ENABLE_LUT |
+ BM_PXP_CTRL_ENABLE_ROTATE0 |
+ BM_PXP_CTRL_ENABLE_PS_AS_OUT,
+ pxp->base + HW_PXP_CTRL_SET);
+ return 0;
+ }
+ break;
+ case PXP_OP_TYPE_WFE_A:
+ pxp_luts_deactivate(pxp, proc_data->lut_sels);
+
+ if (proc_data->lut_cleanup == 0) {
+ /* We should enable histogram in standard mode
+ * in wfe_a processing for waveform mode selection
+ */
+ pxp_histogram_enable(pxp, pxp_conf_data->wfe_a_fetch_param[0].width,
+ pxp_conf_data->wfe_a_fetch_param[0].height);
+
+ pxp_luts_activate(pxp, (u64)proc_data->lut_status_1 |
+ ((u64)proc_data->lut_status_2 << 32));
+
+ /* collision detection should be always enable in standard mode */
+ pxp_collision_detection_enable(pxp, pxp_conf_data->wfe_a_fetch_param[0].width,
+ pxp_conf_data->wfe_a_fetch_param[0].height);
+ }
+
+ if (pxp->devdata && pxp->devdata->pxp_wfe_a_configure)
+ pxp->devdata->pxp_wfe_a_configure(pxp);
+ if (pxp->devdata && pxp->devdata->pxp_wfe_a_process)
+ pxp->devdata->pxp_wfe_a_process(pxp);
+ break;
+ case PXP_OP_TYPE_WFE_B:
+ pxp_wfe_b_configure(pxp);
+ pxp_wfe_b_process(pxp);
+ break;
+ default:
+ /* Unsupport */
+ ret = -EINVAL;
+ pr_err("Invalid pxp operation type passed\n");
+ break;
+ }
+
+ return ret;
+}
+
+static void pxp_clk_enable(struct pxps *pxp)
+{
+ mutex_lock(&pxp->clk_mutex);
+
+ if (pxp->clk_stat == CLK_STAT_ON) {
+ mutex_unlock(&pxp->clk_mutex);
+ return;
+ }
+
+ pm_runtime_get_sync(pxp->dev);
+
+ clk_prepare_enable(pxp->ipg_clk);
+ clk_prepare_enable(pxp->axi_clk);
+ pxp->clk_stat = CLK_STAT_ON;
+
+ mutex_unlock(&pxp->clk_mutex);
+}
+
+static void pxp_clk_disable(struct pxps *pxp)
+{
+ unsigned long flags;
+
+ mutex_lock(&pxp->clk_mutex);
+
+ if (pxp->clk_stat == CLK_STAT_OFF) {
+ mutex_unlock(&pxp->clk_mutex);
+ return;
+ }
+
+ spin_lock_irqsave(&pxp->lock, flags);
+ if ((pxp->pxp_ongoing == 0) && list_empty(&head)) {
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ clk_disable_unprepare(pxp->ipg_clk);
+ clk_disable_unprepare(pxp->axi_clk);
+ pxp->clk_stat = CLK_STAT_OFF;
+ } else
+ spin_unlock_irqrestore(&pxp->lock, flags);
+
+ pm_runtime_put_sync_suspend(pxp->dev);
+
+ mutex_unlock(&pxp->clk_mutex);
+}
+
+static inline void clkoff_callback(struct work_struct *w)
+{
+ struct pxps *pxp = container_of(w, struct pxps, work);
+
+ pxp_clk_disable(pxp);
+}
+
+static void pxp_clkoff_timer(unsigned long arg)
+{
+ struct pxps *pxp = (struct pxps *)arg;
+
+ if ((pxp->pxp_ongoing == 0) && list_empty(&head))
+ schedule_work(&pxp->work);
+ else
+ mod_timer(&pxp->clk_timer,
+ jiffies + msecs_to_jiffies(timeout_in_ms));
+}
+
+static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan)
+{
+ return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list);
+}
+
+static int convert_param_to_pixmap(struct pxp_pixmap *pixmap,
+ struct pxp_layer_param *param)
+{
+ if (!param->width || !param->height)
+ return -EINVAL;
+
+ pixmap->width = param->width;
+ pixmap->height = param->height;
+ pixmap->format = param->pixel_fmt;
+ pixmap->paddr = param->paddr;
+ pixmap->bpp = get_bpp_from_fmt(pixmap->format);
+
+ if (pxp_legacy) {
+ pixmap->pitch = (param->stride) ? (param->stride * pixmap->bpp >> 3) :
+ (param->width * pixmap->bpp >> 3);
+ } else {
+ if (!param->stride || (param->stride == param->width))
+ pixmap->pitch = param->width * pixmap->bpp >> 3;
+ else
+ pixmap->pitch = param->stride;
+ }
+
+ pixmap->crop.x = param->crop.left;
+ pixmap->crop.y = param->crop.top;
+ pixmap->crop.width = param->crop.width;
+ pixmap->crop.height = param->crop.height;
+
+ pixmap->g_alpha.color_key_enable = param->color_key_enable;
+ pixmap->g_alpha.combine_enable = param->combine_enable;
+ pixmap->g_alpha.global_alpha_enable = param->global_alpha_enable;
+ pixmap->g_alpha.global_override = param->global_override;
+ pixmap->g_alpha.global_alpha = param->global_alpha;
+ pixmap->g_alpha.alpha_invert = param->alpha_invert;
+ pixmap->g_alpha.local_alpha_enable = param->local_alpha_enable;
+ pixmap->g_alpha.comp_mask = param->comp_mask;
+
+ return 0;
+}
+
+/* called with pxp_chan->lock held */
+static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
+{
+ struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device);
+ struct pxps *pxp = to_pxp(pxp_dma);
+ struct pxp_config_data *config_data = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &config_data->proc_data;
+ struct pxp_tx_desc *desc;
+ struct pxp_tx_desc *child;
+ struct pxp_task_info *task = &pxp->task;
+ struct pxp_op_info *op = &task->op_info;
+ struct pxp_alpha_info *alpha = &op->alpha_info;
+ struct pxp_layer_param *param = NULL;
+ struct pxp_pixmap *input, *output;
+ int i = 0, ret;
+ bool combine_enable = false;
+
+ memset(&pxp->pxp_conf_state.s0_param, 0, sizeof(struct pxp_layer_param));
+ memset(&pxp->pxp_conf_state.out_param, 0, sizeof(struct pxp_layer_param));
+ memset(pxp->pxp_conf_state.ol_param, 0, sizeof(struct pxp_layer_param));
+ memset(&pxp->pxp_conf_state.proc_data, 0, sizeof(struct pxp_proc_data));
+
+ memset(task, 0, sizeof(*task));
+ /* S0 */
+ desc = list_first_entry(&head, struct pxp_tx_desc, list);
+ memcpy(&pxp->pxp_conf_state.s0_param,
+ &desc->layer_param.s0_param, sizeof(struct pxp_layer_param));
+ memcpy(&pxp->pxp_conf_state.proc_data,
+ &desc->proc_data, sizeof(struct pxp_proc_data));
+
+ if (proc_data->combine_enable)
+ alpha_blending_version = PXP_ALPHA_BLENDING_V2;
+ else
+ alpha_blending_version = PXP_ALPHA_BLENDING_NONE;
+
+ pxp_legacy = (proc_data->pxp_legacy) ? true : false;
+
+ /* Save PxP configuration */
+ list_for_each_entry(child, &desc->tx_list, list) {
+ if (i == 0) { /* Output */
+ memcpy(&pxp->pxp_conf_state.out_param,
+ &child->layer_param.out_param,
+ sizeof(struct pxp_layer_param));
+ } else if (i == 1) { /* Overlay */
+ memcpy(&pxp->pxp_conf_state.ol_param[i - 1],
+ &child->layer_param.ol_param,
+ sizeof(struct pxp_layer_param));
+ if (pxp->pxp_conf_state.ol_param[i - 1].width != 0 &&
+ pxp->pxp_conf_state.ol_param[i - 1].height != 0) {
+ if (pxp->pxp_conf_state.ol_param[i - 1].combine_enable)
+ alpha_blending_version = PXP_ALPHA_BLENDING_V1;
+ }
+ }
+
+ if (proc_data->engine_enable & PXP_ENABLE_DITHER) {
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_DITHER_FETCH0)
+ memcpy(&pxp->pxp_conf_state.dither_fetch_param[0],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_DITHER_FETCH1)
+ memcpy(&pxp->pxp_conf_state.dither_fetch_param[1],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_DITHER_STORE0)
+ memcpy(&pxp->pxp_conf_state.dither_store_param[0],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_DITHER_STORE1)
+ memcpy(&pxp->pxp_conf_state.dither_store_param[1],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ op->op_type = PXP_OP_TYPE_DITHER;
+ }
+
+ if (proc_data->engine_enable & PXP_ENABLE_WFE_A) {
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_WFE_A_FETCH0)
+ memcpy(&pxp->pxp_conf_state.wfe_a_fetch_param[0],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_WFE_A_FETCH1)
+ memcpy(&pxp->pxp_conf_state.wfe_a_fetch_param[1],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_WFE_A_STORE0)
+ memcpy(&pxp->pxp_conf_state.wfe_a_store_param[0],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_WFE_A_STORE1)
+ memcpy(&pxp->pxp_conf_state.wfe_a_store_param[1],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ op->op_type = PXP_OP_TYPE_WFE_A;
+ }
+
+ if (proc_data->engine_enable & PXP_ENABLE_WFE_B) {
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_WFE_B_FETCH0)
+ memcpy(&pxp->pxp_conf_state.wfe_b_fetch_param[0],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_WFE_B_FETCH1)
+ memcpy(&pxp->pxp_conf_state.wfe_b_fetch_param[1],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_WFE_B_STORE0)
+ memcpy(&pxp->pxp_conf_state.wfe_b_store_param[0],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ if (child->layer_param.processing_param.flag & PXP_BUF_FLAG_WFE_B_STORE1)
+ memcpy(&pxp->pxp_conf_state.wfe_b_store_param[1],
+ &child->layer_param.processing_param,
+ sizeof(struct pxp_layer_param));
+ op->op_type = PXP_OP_TYPE_WFE_B;
+ }
+
+ i++;
+ }
+
+ if (!op->op_type) {
+ op->op_type = PXP_OP_TYPE_2D;
+
+ if ((alpha_blending_version == PXP_ALPHA_BLENDING_V1) ||
+ (alpha_blending_version == PXP_ALPHA_BLENDING_V2))
+ combine_enable = true;
+
+ if (combine_enable)
+ task->input_num = 2;
+ else if (proc_data->fill_en)
+ task->input_num = 0;
+ else
+ task->input_num = 1;
+
+ output = &task->output[0];
+ switch (task->input_num) {
+ case 0:
+ op->fill_en = 1;
+ op->fill_data = proc_data->bgcolor;
+ break;
+ case 1:
+ param = &pxp->pxp_conf_state.s0_param;
+ input = &task->input[0];
+
+ ret = convert_param_to_pixmap(input, param);
+ if (ret < 0) {
+ param = &pxp->pxp_conf_state.ol_param[0];
+ ret = convert_param_to_pixmap(input, param);
+ BUG_ON(ret < 0);
+ } else {
+ input->crop.x = proc_data->srect.left;
+ input->crop.y = proc_data->srect.top;
+ input->crop.width = proc_data->srect.width;
+ input->crop.height = proc_data->srect.height;
+ }
+
+ input->rotate = proc_data->rotate;
+ input->flip = (proc_data->hflip) ? PXP_H_FLIP :
+ (proc_data->vflip) ? PXP_V_FLIP : 0;
+ break;
+ case 2:
+ /* s0 */
+ param = &pxp->pxp_conf_state.s0_param;
+ input = &task->input[0];
+
+ ret = convert_param_to_pixmap(input, param);
+ BUG_ON(ret < 0);
+ input->crop.x = proc_data->srect.left;
+ input->crop.y = proc_data->srect.top;
+ input->crop.width = proc_data->srect.width;
+ input->crop.height = proc_data->srect.height;
+ alpha->s0_alpha = param->alpha;
+
+ input->rotate = proc_data->rotate;
+ input->flip = (proc_data->hflip) ? PXP_H_FLIP :
+ (proc_data->vflip) ? PXP_V_FLIP : 0;
+
+ /* overlay */
+ param = &pxp->pxp_conf_state.ol_param[0];
+ input = &task->input[1];
+
+ ret = convert_param_to_pixmap(input, param);
+ BUG_ON(ret < 0);
+ alpha->s1_alpha = param->alpha;
+ alpha->alpha_mode = proc_data->alpha_mode;
+ break;
+ }
+
+ param = &pxp->pxp_conf_state.out_param;
+ ret = convert_param_to_pixmap(output, param);
+ BUG_ON(ret < 0);
+
+ output->crop.x = proc_data->drect.left;
+ output->crop.y = proc_data->drect.top;
+ output->crop.width = proc_data->drect.width;
+ output->crop.height = proc_data->drect.height;
+ }
+
+ pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__,
+ pxp->pxp_conf_state.s0_param.width,
+ pxp->pxp_conf_state.s0_param.height,
+ pxp->pxp_conf_state.s0_param.paddr);
+ pr_debug("%s:%d S0 crop (top, left)=(%d, %d), (width, height)=(%d, %d)\n",
+ __func__, __LINE__,
+ pxp->pxp_conf_state.s0_param.crop.top,
+ pxp->pxp_conf_state.s0_param.crop.left,
+ pxp->pxp_conf_state.s0_param.crop.width,
+ pxp->pxp_conf_state.s0_param.crop.height);
+ pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__,
+ pxp->pxp_conf_state.out_param.width,
+ pxp->pxp_conf_state.out_param.height,
+ pxp->pxp_conf_state.out_param.paddr);
+}
+
+static int pxpdma_dostart_work(struct pxps *pxp)
+{
+ int ret;
+ struct pxp_channel *pxp_chan = NULL;
+ unsigned long flags;
+ dma_async_tx_callback callback;
+ void *callback_param;
+ struct pxp_tx_desc *desc = NULL;
+ struct pxp_tx_desc *child, *_child;
+ struct pxp_config_data *config_data = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &config_data->proc_data;
+
+ spin_lock_irqsave(&pxp->lock, flags);
+
+ desc = list_entry(head.next, struct pxp_tx_desc, list);
+ pxp_chan = to_pxp_channel(desc->txd.chan);
+
+ __pxpdma_dostart(pxp_chan);
+
+ /* Configure PxP */
+ ret = pxp_config(pxp, pxp_chan);
+ if (ret) {
+ callback = desc->txd.callback;
+ callback_param = desc->txd.callback_param;
+
+ callback(callback_param);
+
+ /* Unsupport operation */
+ list_for_each_entry_safe(child, _child, &desc->tx_list, list) {
+ list_del_init(&child->list);
+ kmem_cache_free(tx_desc_cache, (void *)child);
+ }
+ list_del_init(&desc->list);
+ kmem_cache_free(tx_desc_cache, (void *)desc);
+
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ return -EINVAL;
+ }
+
+ if (proc_data->working_mode & PXP_MODE_STANDARD) {
+ if(!pxp_is_v3p(pxp) || !(proc_data->engine_enable & PXP_ENABLE_DITHER))
+ pxp_start2(pxp);
+ } else
+ pxp_start(pxp);
+
+ spin_unlock_irqrestore(&pxp->lock, flags);
+
+ return 0;
+}
+
+static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct pxps *pxp)
+{
+ unsigned long flags;
+ struct pxp_tx_desc *desc = NULL;
+
+ do {
+ desc = pxpdma_first_queued(pxp_chan);
+ spin_lock_irqsave(&pxp->lock, flags);
+ list_move_tail(&desc->list, &head);
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ } while (!list_empty(&pxp_chan->queue));
+}
+
+static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct pxp_tx_desc *desc = to_tx_desc(tx);
+ struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan);
+ dma_cookie_t cookie;
+
+ dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n");
+
+ /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */
+ spin_lock(&pxp_chan->lock);
+
+ cookie = pxp_chan->dma_chan.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+
+ /* from dmaengine.h: "last cookie value returned to client" */
+ pxp_chan->dma_chan.cookie = cookie;
+ tx->cookie = cookie;
+
+ /* Here we add the tx descriptor to our PxP task queue. */
+ list_add_tail(&desc->list, &pxp_chan->queue);
+
+ spin_unlock(&pxp_chan->lock);
+
+ dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n");
+
+ return cookie;
+}
+
+/**
+ * pxp_init_channel() - initialize a PXP channel.
+ * @pxp_dma: PXP DMA context.
+ * @pchan: pointer to the channel object.
+ * @return 0 on success or negative error code on failure.
+ */
+static int pxp_init_channel(struct pxp_dma *pxp_dma,
+ struct pxp_channel *pxp_chan)
+{
+ int ret = 0;
+
+ /*
+ * We are using _virtual_ channel here.
+ * Each channel contains all parameters of corresponding layers
+ * for one transaction; each layer is represented as one descriptor
+ * (i.e., pxp_tx_desc) here.
+ */
+
+ INIT_LIST_HEAD(&pxp_chan->queue);
+
+ return ret;
+}
+
+static irqreturn_t pxp_irq(int irq, void *dev_id)
+{
+ struct pxps *pxp = dev_id;
+ struct pxp_channel *pxp_chan;
+ struct pxp_tx_desc *desc;
+ struct pxp_tx_desc *child, *_child;
+ dma_async_tx_callback callback;
+ void *callback_param;
+ unsigned long flags;
+ u32 hist_status;
+ int pxp_irq_status = 0;
+
+ dump_pxp_reg(pxp);
+
+ if (__raw_readl(pxp->base + HW_PXP_STAT) & BM_PXP_STAT_IRQ0)
+ __raw_writel(BM_PXP_STAT_IRQ0, pxp->base + HW_PXP_STAT_CLR);
+ else {
+ int irq_clr = 0;
+
+ pxp_irq_status = __raw_readl(pxp->base + HW_PXP_IRQ);
+ BUG_ON(!pxp_irq_status);
+
+ if (pxp_irq_status & BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ)
+ irq_clr |= BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ)
+ irq_clr |= BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_FIRST_CH0_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_FIRST_CH0_STORE_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_FIRST_CH1_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_FIRST_CH1_STORE_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_FIRST_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_FIRST_STORE_IRQ;
+
+ if (pxp_irq_status & BM_PXP_IRQ_WFE_B_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_WFE_B_STORE_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_WFE_A_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_WFE_A_STORE_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_DITHER_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_DITHER_STORE_IRQ;
+
+ if (pxp_irq_status & BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ;
+
+ if (pxp_irq_status & BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ;
+
+ if (pxp_irq_status & BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ)
+ irq_clr |= BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ)
+ irq_clr |= BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_DITHER_CH0_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_DITHER_CH0_STORE_IRQ;
+ if (pxp_irq_status & BM_PXP_IRQ_DITHER_CH1_STORE_IRQ)
+ irq_clr |= BM_PXP_IRQ_DITHER_CH1_STORE_IRQ;
+ /*XXX other irqs status clear should be added below */
+
+ __raw_writel(irq_clr, pxp->base + HW_PXP_IRQ_CLR);
+
+ pxp_writel(BM_PXP_CTRL_ENABLE, HW_PXP_CTRL_CLR);
+ }
+ pxp_collision_status_report(pxp, &col_info);
+ pxp_histogram_status_report(pxp, &hist_status);
+ /*XXX before a new update operation, we should
+ * always clear all the collision information
+ */
+ pxp_collision_detection_disable(pxp);
+ pxp_histogram_disable(pxp);
+
+ pxp_writel(0x0, HW_PXP_CTRL);
+ pxp_soft_reset(pxp);
+ if (pxp->devdata && pxp->devdata->pxp_data_path_config)
+ pxp->devdata->pxp_data_path_config(pxp);
+ __raw_writel(0xffff, pxp->base + HW_PXP_IRQ_MASK);
+
+ spin_lock_irqsave(&pxp->lock, flags);
+ if (list_empty(&head)) {
+ pxp->pxp_ongoing = 0;
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ return IRQ_NONE;
+ }
+
+ /* Get descriptor and call callback */
+ desc = list_entry(head.next, struct pxp_tx_desc, list);
+ pxp_chan = to_pxp_channel(desc->txd.chan);
+
+ pxp_chan->completed = desc->txd.cookie;
+
+ callback = desc->txd.callback;
+ callback_param = desc->txd.callback_param;
+
+ /* Send histogram status back to caller */
+ desc->hist_status = hist_status;
+
+ if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
+ callback(callback_param);
+
+ pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+
+ list_for_each_entry_safe(child, _child, &desc->tx_list, list) {
+ list_del_init(&child->list);
+ kmem_cache_free(tx_desc_cache, (void *)child);
+ }
+ list_del_init(&desc->list);
+ kmem_cache_free(tx_desc_cache, (void *)desc);
+
+ complete(&pxp->complete);
+ pxp->pxp_ongoing = 0;
+ mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
+
+ spin_unlock_irqrestore(&pxp->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+/* allocate/free dma tx descriptor dynamically*/
+static struct pxp_tx_desc *pxpdma_desc_alloc(struct pxp_channel *pxp_chan)
+{
+ struct pxp_tx_desc *desc = NULL;
+ struct dma_async_tx_descriptor *txd = NULL;
+
+ desc = kmem_cache_alloc(tx_desc_cache, GFP_KERNEL | __GFP_ZERO);
+ if (desc == NULL)
+ return NULL;
+
+ INIT_LIST_HEAD(&desc->list);
+ INIT_LIST_HEAD(&desc->tx_list);
+ txd = &desc->txd;
+ dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan);
+ txd->tx_submit = pxp_tx_submit;
+
+ return desc;
+}
+
+
+/* Allocate and initialise a transfer descriptor. */
+static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan,
+ struct scatterlist
+ *sgl,
+ unsigned int sg_len,
+ enum
+ dma_transfer_direction
+ direction,
+ unsigned long tx_flags,
+ void *context)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+ struct pxps *pxp = to_pxp(pxp_dma);
+ struct pxp_tx_desc *pos = NULL, *next = NULL;
+ struct pxp_tx_desc *desc = NULL;
+ struct pxp_tx_desc *first = NULL, *prev = NULL;
+ struct scatterlist *sg;
+ dma_addr_t phys_addr;
+ int i;
+
+ if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
+ dev_err(chan->device->dev, "Invalid DMA direction %d!\n",
+ direction);
+ return NULL;
+ }
+
+ if (unlikely(sg_len < 2))
+ return NULL;
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ desc = pxpdma_desc_alloc(pxp_chan);
+ if (!desc) {
+ dev_err(chan->device->dev, "no enough memory to allocate tx descriptor\n");
+
+ if (first) {
+ list_for_each_entry_safe(pos, next, &first->tx_list, list) {
+ list_del_init(&pos->list);
+ kmem_cache_free(tx_desc_cache, (void*)pos);
+ }
+ list_del_init(&first->list);
+ kmem_cache_free(tx_desc_cache, (void*)first);
+ }
+
+ return NULL;
+ }
+
+ phys_addr = sg_dma_address(sg);
+
+ if (!first) {
+ first = desc;
+
+ desc->layer_param.s0_param.paddr = phys_addr;
+ } else {
+ list_add_tail(&desc->list, &first->tx_list);
+ prev->next = desc;
+ desc->next = NULL;
+
+ if (i == 1)
+ desc->layer_param.out_param.paddr = phys_addr;
+ else
+ desc->layer_param.ol_param.paddr = phys_addr;
+ }
+
+ prev = desc;
+ }
+
+ pxp->pxp_conf_state.layer_nr = sg_len;
+ first->txd.flags = tx_flags;
+ first->len = sg_len;
+ pr_debug("%s:%d first %p, first->len %d, flags %08x\n",
+ __func__, __LINE__, first, first->len, first->txd.flags);
+
+ return &first->txd;
+}
+
+static void pxp_issue_pending(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+ struct pxps *pxp = to_pxp(pxp_dma);
+
+ spin_lock(&pxp_chan->lock);
+
+ if (list_empty(&pxp_chan->queue)) {
+ spin_unlock(&pxp_chan->lock);
+ return;
+ }
+
+ pxpdma_dequeue(pxp_chan, pxp);
+ pxp_chan->status = PXP_CHANNEL_READY;
+
+ spin_unlock(&pxp_chan->lock);
+
+ pxp_clk_enable(pxp);
+ wake_up_interruptible(&pxp->thread_waitq);
+}
+
+static void __pxp_terminate_all(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+}
+
+static int pxp_device_terminate_all(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+ spin_lock(&pxp_chan->lock);
+ __pxp_terminate_all(chan);
+ spin_unlock(&pxp_chan->lock);
+
+ return 0;
+}
+
+static int pxp_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+ int ret;
+
+ /* dmaengine.c now guarantees to only offer free channels */
+ BUG_ON(chan->client_count > 1);
+ WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE);
+
+ chan->cookie = 1;
+ pxp_chan->completed = -ENXIO;
+
+ pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id);
+ ret = pxp_init_channel(pxp_dma, pxp_chan);
+ if (ret < 0)
+ goto err_chan;
+
+ pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+
+ dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
+ chan->chan_id, pxp_chan->eof_irq);
+
+ return ret;
+
+err_chan:
+ return ret;
+}
+
+static void pxp_free_chan_resources(struct dma_chan *chan)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+ spin_lock(&pxp_chan->lock);
+
+ __pxp_terminate_all(chan);
+
+ pxp_chan->status = PXP_CHANNEL_FREE;
+
+ spin_unlock(&pxp_chan->lock);
+}
+
+static enum dma_status pxp_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+ if (cookie != chan->cookie)
+ return DMA_ERROR;
+
+ if (txstate) {
+ txstate->last = pxp_chan->completed;
+ txstate->used = chan->cookie;
+ txstate->residue = 0;
+ }
+ return DMA_COMPLETE;
+}
+
+static void pxp_data_path_config_v3p(struct pxps *pxp)
+{
+ u32 val = 0;
+
+ __raw_writel(
+ BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1)|
+ BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(1)|
+ BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(0)|
+ BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(0),
+ pxp->base + HW_PXP_DATA_PATH_CTRL0);
+
+ /*
+ * MUX17: HIST_B as histogram: 0: output buffer, 1: wfe_store
+ * MUX16: HIST_A as collision: 0: output buffer, 1: wfe_store
+ */
+ if (pxp_is_v3(pxp))
+ val = BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(1)|
+ BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(0);
+ else if (pxp_is_v3p(pxp))
+ val = BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(1)|
+ BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(1);
+ __raw_writel(val, pxp->base + HW_PXP_DATA_PATH_CTRL1);
+}
+
+static void pxp_soft_reset(struct pxps *pxp)
+{
+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_CLR);
+ __raw_writel(BM_PXP_CTRL_CLKGATE, pxp->base + HW_PXP_CTRL_CLR);
+
+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_SET);
+ while (!(__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_CLKGATE))
+ dev_dbg(pxp->dev, "%s: wait for clock gate off", __func__);
+
+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_CLR);
+ __raw_writel(BM_PXP_CTRL_CLKGATE, pxp->base + HW_PXP_CTRL_CLR);
+}
+
+static void pxp_sram_init(struct pxps *pxp, u32 select,
+ u32 buffer_addr, u32 length)
+{
+ u32 i;
+
+ __raw_writel(
+ BF_PXP_INIT_MEM_CTRL_ADDR(0) |
+ BF_PXP_INIT_MEM_CTRL_SELECT(select) |
+ BF_PXP_INIT_MEM_CTRL_START(1),
+ pxp->base + HW_PXP_INIT_MEM_CTRL);
+
+ if ((select == WFE_A) || (select == WFE_B)) {
+ for (i = 0; i < length / 2; i++) {
+ __raw_writel(*(((u32*)buffer_addr) + 2 * i + 1),
+ pxp->base + HW_PXP_INIT_MEM_DATA_HIGH);
+
+ __raw_writel(*(((u32*)buffer_addr) + 2 * i),
+ pxp->base + HW_PXP_INIT_MEM_DATA);
+ }
+ } else {
+ for (i = 0; i < length; i++) {
+ __raw_writel(*(((u32*) buffer_addr) + i),
+ pxp->base + HW_PXP_INIT_MEM_DATA);
+ }
+ }
+
+ __raw_writel(
+ BF_PXP_INIT_MEM_CTRL_ADDR(0) |
+ BF_PXP_INIT_MEM_CTRL_SELECT(select) |
+ BF_PXP_INIT_MEM_CTRL_START(0),
+ pxp->base + HW_PXP_INIT_MEM_CTRL);
+}
+
+/*
+ * wfe a configuration
+ * configure wfe a engine for waveform processing
+ * including its fetch and store module
+ */
+static void pxp_wfe_a_configure(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+
+ /* FETCH */
+ __raw_writel(
+ BF_PXP_WFA_FETCH_CTRL_BF1_EN(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_HSK_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BYTES_PP(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_SRAM_IF(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BURST_LEN(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BYPASS_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_EN(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_HSK_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BYTES_PP(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_SRAM_IF(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BURST_LEN(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BYPASS_MODE(0),
+ pxp->base + HW_PXP_WFA_FETCH_CTRL);
+
+ __raw_writel(
+ BF_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL(1) |
+ BF_PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS(0) |
+ BF_PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS(3),
+ pxp->base + HW_PXP_WFA_ARRAY_PIXEL0_MASK);
+
+ __raw_writel(
+ BF_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL1_MASK_BUF_SEL(1) |
+ BF_PXP_WFA_ARRAY_PIXEL1_MASK_H_OFS(4) |
+ BF_PXP_WFA_ARRAY_PIXEL1_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFA_ARRAY_PIXEL1_MASK);
+
+ __raw_writel(
+ BF_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL3_MASK_BUF_SEL(1) |
+ BF_PXP_WFA_ARRAY_PIXEL3_MASK_H_OFS(8) |
+ BF_PXP_WFA_ARRAY_PIXEL3_MASK_L_OFS(9),
+ pxp->base + HW_PXP_WFA_ARRAY_PIXEL2_MASK);
+
+ __raw_writel(
+ BF_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL4_MASK_BUF_SEL(1) |
+ BF_PXP_WFA_ARRAY_PIXEL4_MASK_H_OFS(10) |
+ BF_PXP_WFA_ARRAY_PIXEL4_MASK_L_OFS(15),
+ pxp->base + HW_PXP_WFA_ARRAY_PIXEL3_MASK);
+
+ __raw_writel(
+ BF_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_Y(0) |
+ BF_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_X(0) |
+ BF_PXP_WFA_ARRAY_PIXEL2_MASK_BUF_SEL(0) |
+ BF_PXP_WFA_ARRAY_PIXEL2_MASK_H_OFS(4) |
+ BF_PXP_WFA_ARRAY_PIXEL2_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFA_ARRAY_PIXEL4_MASK);
+
+ __raw_writel(1, pxp->base + HW_PXP_WFA_ARRAY_REG2);
+
+ /* STORE */
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_CTRL_CH0_CH_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_PACK_IN_SEL(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_FILL_DATA_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES(8)|
+ BF_PXP_WFE_A_STORE_CTRL_CH0_COMBINE_2CHANNEL(1) |
+ BF_PXP_WFE_A_STORE_CTRL_CH0_ARBIT_EN(0),
+ pxp->base + HW_PXP_WFE_A_STORE_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_CTRL_CH1_CH_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_16(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES(16),
+ pxp->base + HW_PXP_WFE_A_STORE_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(0)|
+ BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(0)|
+ BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(0)|
+ BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(0),
+ pxp->base + HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH0);
+
+
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(1)|
+ BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN(0)|
+ BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN(0),
+ pxp->base + HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH1);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_FILL_DATA_CH0_FILL_DATA_CH0(0),
+ pxp->base + HW_PXP_WFE_A_STORE_FILL_DATA_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK0_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(0xf), /* fetch CP */
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK0_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK1_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(0xf00), /* fetch NP */
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK1_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK2_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(0x00000),
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK2_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK3_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0(0x3f000000), /* fetch LUT */
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK3_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0(0xf),
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK4_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0(0x0), /* fetch Y4 */
+ pxp->base + HW_PXP_WFE_A_STORE_D_MASK4_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(32) |
+ BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(1) |
+ BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(28)|
+ BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(1) |
+ BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(24)|
+ BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(1)|
+ BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(18)|
+ BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(1),
+ pxp->base + HW_PXP_WFE_A_STORE_D_SHIFT_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4(28) |
+ BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4(0) |
+ BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5(0)|
+ BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5(0) |
+ BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6(0)|
+ BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6(0) |
+ BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7(0),
+ pxp->base + HW_PXP_WFE_A_STORE_D_SHIFT_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(1)|
+ BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(1)|
+ BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(1)|
+ BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(0)|
+ BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(32+6)|
+ BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(1)|
+ BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(32+6)|
+ BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(1),
+ pxp->base + HW_PXP_WFE_A_STORE_F_SHIFT_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK4(0)|
+ BF_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK5(0)|
+ BF_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK6(0)|
+ BF_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK7(0),
+ pxp->base + HW_PXP_WFE_A_STORE_F_MASK_H_CH0);
+
+
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK0(0x1) |
+ BF_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK1(0x2) |
+ BF_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK2(0x4) |
+ BF_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK3(0x8),
+ pxp->base + HW_PXP_WFE_A_STORE_F_MASK_L_CH0);
+
+ /* ALU */
+ __raw_writel(BF_PXP_ALU_A_INST_ENTRY_ENTRY_ADDR(0),
+ pxp->base + HW_PXP_ALU_A_INST_ENTRY);
+
+ __raw_writel(BF_PXP_ALU_A_PARAM_PARAM0(0) |
+ BF_PXP_ALU_A_PARAM_PARAM1(0),
+ pxp->base + HW_PXP_ALU_A_PARAM);
+
+ __raw_writel(BF_PXP_ALU_A_CONFIG_BUF_ADDR(0),
+ pxp->base + HW_PXP_ALU_A_CONFIG);
+
+ __raw_writel(BF_PXP_ALU_A_LUT_CONFIG_MODE(0) |
+ BF_PXP_ALU_A_LUT_CONFIG_EN(0),
+ pxp->base + HW_PXP_ALU_A_LUT_CONFIG);
+
+ __raw_writel(BF_PXP_ALU_A_LUT_DATA0_LUT_DATA_L(0),
+ pxp->base + HW_PXP_ALU_A_LUT_DATA0);
+
+ __raw_writel(BF_PXP_ALU_A_LUT_DATA1_LUT_DATA_H(0),
+ pxp->base + HW_PXP_ALU_A_LUT_DATA1);
+
+ __raw_writel(BF_PXP_ALU_A_CTRL_BYPASS (1) |
+ BF_PXP_ALU_A_CTRL_ENABLE (1) |
+ BF_PXP_ALU_A_CTRL_START (0) |
+ BF_PXP_ALU_A_CTRL_SW_RESET (0),
+ pxp->base + HW_PXP_ALU_A_CTRL);
+
+ /* WFE A */
+ __raw_writel(0x3F3F0303, pxp->base + HW_PXP_WFE_A_STAGE1_MUX0);
+ __raw_writel(0x0C00000C, pxp->base + HW_PXP_WFE_A_STAGE1_MUX1);
+ __raw_writel(0x01040000, pxp->base + HW_PXP_WFE_A_STAGE1_MUX2);
+ __raw_writel(0x0A0A0904, pxp->base + HW_PXP_WFE_A_STAGE1_MUX3);
+ __raw_writel(0x00000B0B, pxp->base + HW_PXP_WFE_A_STAGE1_MUX4);
+
+ __raw_writel(0x1800280E, pxp->base + HW_PXP_WFE_A_STAGE2_MUX0);
+ __raw_writel(0x00280E01, pxp->base + HW_PXP_WFE_A_STAGE2_MUX1);
+ __raw_writel(0x280E0118, pxp->base + HW_PXP_WFE_A_STAGE2_MUX2);
+ __raw_writel(0x00011800, pxp->base + HW_PXP_WFE_A_STAGE2_MUX3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STAGE2_MUX4);
+ __raw_writel(0x1800280E, pxp->base + HW_PXP_WFE_A_STAGE2_MUX5);
+ __raw_writel(0x00280E01, pxp->base + HW_PXP_WFE_A_STAGE2_MUX6);
+ __raw_writel(0x1A0E0118, pxp->base + HW_PXP_WFE_A_STAGE2_MUX7);
+ __raw_writel(0x1B012911, pxp->base + HW_PXP_WFE_A_STAGE2_MUX8);
+ __raw_writel(0x00002911, pxp->base + HW_PXP_WFE_A_STAGE2_MUX9);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STAGE2_MUX10);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STAGE2_MUX11);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STAGE2_MUX12);
+
+ __raw_writel(0x07060504, pxp->base + HW_PXP_WFE_A_STAGE3_MUX0);
+ __raw_writel(0x3F3F3F08, pxp->base + HW_PXP_WFE_A_STAGE3_MUX1);
+ __raw_writel(0x03020100, pxp->base + HW_PXP_WFE_A_STAGE3_MUX2);
+ __raw_writel(0x3F3F3F3F, pxp->base + HW_PXP_WFE_A_STAGE3_MUX3);
+
+ __raw_writel(0x001F1F1F, pxp->base + HW_PXP_WFE_A_STAGE2_5X6_MASKS_0);
+ __raw_writel(0x3f030100, pxp->base + HW_PXP_WFE_A_STAGE2_5X6_ADDR_0);
+
+ __raw_writel(0x00000700, pxp->base + HW_PXP_WFE_A_STG2_5X1_OUT0);
+ __raw_writel(0x00007000, pxp->base + HW_PXP_WFE_A_STG2_5X1_OUT1);
+ __raw_writel(0x0000A000, pxp->base + HW_PXP_WFE_A_STG2_5X1_OUT2);
+ __raw_writel(0x000000C0, pxp->base + HW_PXP_WFE_A_STG2_5X1_OUT3);
+ __raw_writel(0x071F1F1F, pxp->base + HW_PXP_WFE_A_STG2_5X1_MASKS);
+
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT0_2);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT0_3);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT0_4);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT0_5);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT0_6);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT0_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT2_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT2_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT2_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT2_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT2_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT2_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT2_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT2_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT3_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT3_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT3_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT3_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT3_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT3_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT3_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT3_7);
+
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT0_0);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT0_1);
+ __raw_writel(0x04050505, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT0_2);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT0_3);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT0_4);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT0_5);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT0_6);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT0_7);
+
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT1_0);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT1_1);
+ __raw_writel(0x05080808, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT1_2);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT1_3);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT1_4);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT1_5);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT1_6);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT1_7);
+
+ __raw_writel(0x07070707, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT2_0);
+ __raw_writel(0x07070707, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT2_1);
+ __raw_writel(0x070C0C0C, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT2_2);
+ __raw_writel(0x07070707, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT2_3);
+ __raw_writel(0X0F0F0F0F, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT2_4);
+ __raw_writel(0X0F0F0F0F, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT2_5);
+ __raw_writel(0X0F0F0F0F, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT2_6);
+ __raw_writel(0X0F0F0F0F, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT2_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT3_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT3_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT3_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT3_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT3_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT3_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT3_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG2_5X6_OUT3_7);
+
+ if (pxp->devdata && pxp->devdata->pxp_lut_cleanup_multiple)
+ pxp->devdata->pxp_lut_cleanup_multiple(pxp,
+ proc_data->lut_sels, 1);
+}
+
+static void pxp_wfe_a_configure_v3p(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+
+ /* FETCH */
+ __raw_writel(
+ BF_PXP_WFB_FETCH_CTRL_BF1_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE(0),
+ pxp->base + HW_PXP_WFB_FETCH_CTRL);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_L_OFS(3),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL0_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_H_OFS(4) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL1_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_H_OFS(8) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_L_OFS(9),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL2_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_H_OFS(10) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_L_OFS(15),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL3_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_H_OFS(4) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL4_MASK);
+
+ __raw_writel(1, pxp->base + HW_PXP_WFB_ARRAY_REG2);
+
+ /* STORE */
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_CTRL_CH0_CH_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_PACK_IN_SEL(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_FILL_DATA_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES(8)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_COMBINE_2CHANNEL(1) |
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARBIT_EN(0),
+ pxp->base + HW_PXP_WFE_B_STORE_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_CTRL_CH1_CH_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_16(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_PACK_IN_SEL(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES(16),
+ pxp->base + HW_PXP_WFE_B_STORE_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(0),
+ pxp->base + HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH0);
+
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(1)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN(0),
+ pxp->base + HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH1);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_FILL_DATA_CH0_FILL_DATA_CH0(0),
+ pxp->base + HW_PXP_WFE_B_STORE_FILL_DATA_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK0_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(0xf), /* fetch CP */
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK0_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK1_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(0xf00), /* fetch NP */
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK1_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK2_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(0x00000),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK2_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK3_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0(0x3f000000), /* fetch LUT */
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK3_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0(0xf),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK4_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0(0x0), /* fetch Y4 */
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK4_L_CH0);
+
+ __raw_writel(0x0, pxp->base + HW_PXP_WFE_B_STORE_D_MASK5_H_CH0);
+ __raw_writel(0x0, pxp->base + HW_PXP_WFE_B_STORE_D_MASK5_L_CH0);
+ __raw_writel(0x0, pxp->base + HW_PXP_WFE_B_STORE_D_MASK6_H_CH0);
+ __raw_writel(0x0, pxp->base + HW_PXP_WFE_B_STORE_D_MASK6_L_CH0);
+ __raw_writel(0x0, pxp->base + HW_PXP_WFE_B_STORE_D_MASK7_H_CH0);
+ __raw_writel(0x0, pxp->base + HW_PXP_WFE_B_STORE_D_MASK7_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(32) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(1) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(28)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(1) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(24)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(1)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(18)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(1),
+ pxp->base + HW_PXP_WFE_B_STORE_D_SHIFT_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4(28) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7(0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_SHIFT_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(1)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(1)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(1)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(32+6)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(1)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(32+6)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(1),
+ pxp->base + HW_PXP_WFE_B_STORE_F_SHIFT_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7(0),
+ pxp->base + HW_PXP_WFE_B_STORE_F_SHIFT_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK0(0x1) |
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK1(0x2) |
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK2(0x4) |
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK3(0x8),
+ pxp->base + HW_PXP_WFE_B_STORE_F_MASK_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK4(0x0)|
+ BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK5(0x0)|
+ BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK6(0x0)|
+ BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK7(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_F_MASK_H_CH0);
+
+
+ /* ALU */
+ __raw_writel(BF_PXP_ALU_B_INST_ENTRY_ENTRY_ADDR(0),
+ pxp->base + HW_PXP_ALU_B_INST_ENTRY);
+
+ __raw_writel(BF_PXP_ALU_B_PARAM_PARAM0(0) |
+ BF_PXP_ALU_B_PARAM_PARAM1(0),
+ pxp->base + HW_PXP_ALU_B_PARAM);
+
+ __raw_writel(BF_PXP_ALU_B_CONFIG_BUF_ADDR(0),
+ pxp->base + HW_PXP_ALU_B_CONFIG);
+
+ __raw_writel(BF_PXP_ALU_B_LUT_CONFIG_MODE(0) |
+ BF_PXP_ALU_B_LUT_CONFIG_EN(0),
+ pxp->base + HW_PXP_ALU_B_LUT_CONFIG);
+
+ __raw_writel(BF_PXP_ALU_B_LUT_DATA0_LUT_DATA_L(0),
+ pxp->base + HW_PXP_ALU_B_LUT_DATA0);
+
+ __raw_writel(BF_PXP_ALU_B_LUT_DATA1_LUT_DATA_H(0),
+ pxp->base + HW_PXP_ALU_B_LUT_DATA1);
+
+ __raw_writel(BF_PXP_ALU_B_CTRL_BYPASS (1) |
+ BF_PXP_ALU_B_CTRL_ENABLE (1) |
+ BF_PXP_ALU_B_CTRL_START (0) |
+ BF_PXP_ALU_B_CTRL_SW_RESET (0),
+ pxp->base + HW_PXP_ALU_B_CTRL);
+
+ /* WFE A */
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX2);
+ __raw_writel(0x03000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX3);
+ __raw_writel(0x00000003, pxp->base + HW_PXP_WFE_B_STAGE1_MUX4);
+ __raw_writel(0x04000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX5);
+ __raw_writel(0x0A090401, pxp->base + HW_PXP_WFE_B_STAGE1_MUX6);
+ __raw_writel(0x000B0B0A, pxp->base + HW_PXP_WFE_B_STAGE1_MUX7);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX8);
+
+ __raw_writel(0x1901290C, pxp->base + HW_PXP_WFE_B_STAGE2_MUX0);
+ __raw_writel(0x01290C02, pxp->base + HW_PXP_WFE_B_STAGE2_MUX1);
+ __raw_writel(0x290C0219, pxp->base + HW_PXP_WFE_B_STAGE2_MUX2);
+ __raw_writel(0x00021901, pxp->base + HW_PXP_WFE_B_STAGE2_MUX3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STAGE2_MUX4);
+ __raw_writel(0x1901290C, pxp->base + HW_PXP_WFE_B_STAGE2_MUX5);
+ __raw_writel(0x01290C02, pxp->base + HW_PXP_WFE_B_STAGE2_MUX6);
+ __raw_writel(0x1B0C0219, pxp->base + HW_PXP_WFE_B_STAGE2_MUX7);
+ __raw_writel(0x1C022A0F, pxp->base + HW_PXP_WFE_B_STAGE2_MUX8);
+ __raw_writel(0x02002A0F, pxp->base + HW_PXP_WFE_B_STAGE2_MUX9);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STAGE2_MUX10);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STAGE2_MUX11);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STAGE2_MUX12);
+
+ __raw_writel(0x2a123a1d, pxp->base + HW_PXP_WFE_B_STAGE3_MUX0);
+ __raw_writel(0x00000013, pxp->base + HW_PXP_WFE_B_STAGE3_MUX1);
+ __raw_writel(0x2a123a1d, pxp->base + HW_PXP_WFE_B_STAGE3_MUX2);
+ __raw_writel(0x00000013, pxp->base + HW_PXP_WFE_B_STAGE3_MUX3);
+ __raw_writel(0x3b202c1d, pxp->base + HW_PXP_WFE_B_STAGE3_MUX4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE3_MUX5);
+ __raw_writel(0x003b202d, pxp->base + HW_PXP_WFE_B_STAGE3_MUX6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE3_MUX7);
+ __raw_writel(0x07060504, pxp->base + HW_PXP_WFE_B_STAGE3_MUX8);
+ __raw_writel(0x00000008, pxp->base + HW_PXP_WFE_B_STAGE3_MUX9);
+ __raw_writel(0x03020100, pxp->base + HW_PXP_WFE_B_STAGE3_MUX10);
+
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_2);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_7);
+
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_2);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_7);
+
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_5X8_MASKS_0);
+
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X1_OUT0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X1_MASKS);
+
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_2);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_3);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_4);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_5);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_6);
+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_7);
+
+ __raw_writel(0x00000700, pxp->base + HW_PXP_WFE_B_STG2_5X1_OUT0);
+ __raw_writel(0x00007000, pxp->base + HW_PXP_WFE_B_STG2_5X1_OUT1);
+ __raw_writel(0x0000A000, pxp->base + HW_PXP_WFE_B_STG2_5X1_OUT2);
+ __raw_writel(0x000000C0, pxp->base + HW_PXP_WFE_B_STG2_5X1_OUT3);
+ __raw_writel(0x070F1F1F, pxp->base + HW_PXP_WFE_B_STG2_5X1_MASKS);
+
+ __raw_writel(0x001F1F1F, pxp->base + HW_PXP_WFE_B_STAGE2_5X6_MASKS_0);
+ __raw_writel(0x3f232120, pxp->base + HW_PXP_WFE_B_STAGE2_5X6_ADDR_0);
+
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_0);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_1);
+ __raw_writel(0x04050505, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_2);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_3);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_4);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_5);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_6);
+ __raw_writel(0x04040404, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_7);
+
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_0);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_1);
+ __raw_writel(0x05080808, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_2);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_3);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_4);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_5);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_6);
+ __raw_writel(0x05050505, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_7);
+
+ __raw_writel(0x07070707, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT2_0);
+ __raw_writel(0x07070707, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT2_1);
+ __raw_writel(0x070C0C0C, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT2_2);
+ __raw_writel(0x07070707, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT2_3);
+ __raw_writel(0x0F0F0F0F, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT2_4);
+ __raw_writel(0x0F0F0F0F, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT2_5);
+ __raw_writel(0x0F0F0F0F, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT2_6);
+ __raw_writel(0x0F0F0F0F, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT2_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT3_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT3_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT3_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT3_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT3_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT3_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT3_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT3_7);
+
+ __raw_writel(0x070F1F1F, pxp->base + HW_PXP_WFE_B_STG3_F8X1_MASKS);
+
+ __raw_writel(0x00000700, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_2);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_7);
+
+ __raw_writel(0x00007000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_2);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_7);
+
+ __raw_writel(0x0000A000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT2_0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT2_1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT2_2);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT2_3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT2_4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT2_5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT2_6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT2_7);
+
+ __raw_writel(0x000000C0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT3_0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT3_1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT3_2);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT3_3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT3_4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT3_5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT3_6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT3_7);
+
+ if (pxp->devdata && pxp->devdata->pxp_lut_cleanup_multiple)
+ pxp->devdata->pxp_lut_cleanup_multiple(pxp,
+ proc_data->lut_sels, 1);
+}
+
+/*
+ * wfe a processing
+ * use wfe a to process an update
+ * x,y,width,height:
+ * coordinate and size of the update region
+ * wb:
+ * working buffer, 16bpp
+ * upd:
+ * update buffer, in Y4 with or without alpha, 8bpp
+ * twb:
+ * temp working buffer, 16bpp
+ * only used when reagl_en is 1
+ * y4c:
+ * y4c buffer, {Y4[3:0],3'b000,collision}, 8bpp
+ * lut:
+ * valid value 0-63
+ * set to the lut used for next update
+ * partial:
+ * 0 - full update
+ * 1 - partial update
+ * reagl_en:
+ * 0 - use normal waveform algorithm
+ * 1 - enable reagl/-d waveform algorithm
+ * detection_only:
+ * 0 - write working buffer
+ * 1 - do no write working buffer, detection only
+ * alpha_en:
+ * 0 - upd is {Y4[3:0],4'b0000} format
+ * 1 - upd is {Y4[3:0],3'b000,alpha} format
+ */
+static void pxp_wfe_a_process(struct pxps *pxp)
+{
+ struct pxp_config_data *config_data = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &config_data->proc_data;
+ struct pxp_layer_param *fetch_ch0 = &config_data->wfe_a_fetch_param[0];
+ struct pxp_layer_param *fetch_ch1 = &config_data->wfe_a_fetch_param[1];
+ struct pxp_layer_param *store_ch0 = &config_data->wfe_a_store_param[0];
+ struct pxp_layer_param *store_ch1 = &config_data->wfe_a_store_param[1];
+ int v;
+
+ if (fetch_ch0->width != fetch_ch1->width ||
+ fetch_ch0->height != fetch_ch1->height) {
+ dev_err(pxp->dev, "width/height should be same for two fetch "
+ "channels\n");
+ }
+
+ print_param(fetch_ch0, "wfe_a fetch_ch0");
+ print_param(fetch_ch1, "wfe_a fetch_ch1");
+ print_param(store_ch0, "wfe_a store_ch0");
+ print_param(store_ch1, "wfe_a store_ch1");
+
+ /* Fetch */
+ __raw_writel(fetch_ch0->paddr, pxp->base + HW_PXP_WFA_FETCH_BUF1_ADDR);
+
+ __raw_writel(BF_PXP_WFA_FETCH_BUF1_CORD_YCORD(fetch_ch0->top) |
+ BF_PXP_WFA_FETCH_BUF1_CORD_XCORD(fetch_ch0->left),
+ pxp->base + HW_PXP_WFA_FETCH_BUF1_CORD);
+
+ __raw_writel(fetch_ch0->stride, pxp->base + HW_PXP_WFA_FETCH_BUF1_PITCH);
+
+ __raw_writel(BF_PXP_WFA_FETCH_BUF1_SIZE_BUF_HEIGHT(fetch_ch0->height - 1) |
+ BF_PXP_WFA_FETCH_BUF1_SIZE_BUF_WIDTH(fetch_ch0->width - 1),
+ pxp->base + HW_PXP_WFA_FETCH_BUF1_SIZE);
+
+ __raw_writel(fetch_ch1->paddr, pxp->base + HW_PXP_WFA_FETCH_BUF2_ADDR);
+
+ __raw_writel(BF_PXP_WFA_FETCH_BUF2_CORD_YCORD(fetch_ch1->top) |
+ BF_PXP_WFA_FETCH_BUF2_CORD_XCORD(fetch_ch1->left),
+ pxp->base + HW_PXP_WFA_FETCH_BUF2_CORD);
+
+ __raw_writel(fetch_ch1->stride * 2, pxp->base + HW_PXP_WFA_FETCH_BUF2_PITCH);
+
+ __raw_writel(BF_PXP_WFA_FETCH_BUF2_SIZE_BUF_HEIGHT(fetch_ch1->height - 1) |
+ BF_PXP_WFA_FETCH_BUF2_SIZE_BUF_WIDTH(fetch_ch1->width - 1),
+ pxp->base + HW_PXP_WFA_FETCH_BUF2_SIZE);
+
+ /* Store */
+ __raw_writel(BF_PXP_WFE_A_STORE_SIZE_CH0_OUT_WIDTH(store_ch0->width - 1) |
+ BF_PXP_WFE_A_STORE_SIZE_CH0_OUT_HEIGHT(store_ch0->height - 1),
+ pxp->base + HW_PXP_WFE_A_STORE_SIZE_CH0);
+
+
+ __raw_writel(BF_PXP_WFE_A_STORE_SIZE_CH1_OUT_WIDTH(store_ch1->width - 1) |
+ BF_PXP_WFE_A_STORE_SIZE_CH1_OUT_HEIGHT(store_ch1->height - 1),
+ pxp->base + HW_PXP_WFE_A_STORE_SIZE_CH1);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_PITCH_CH0_OUT_PITCH(store_ch0->stride) |
+ BF_PXP_WFE_A_STORE_PITCH_CH1_OUT_PITCH(store_ch1->stride * 2),
+ pxp->base + HW_PXP_WFE_A_STORE_PITCH);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(store_ch0->paddr),
+ pxp->base + HW_PXP_WFE_A_STORE_ADDR_0_CH0);
+ __raw_writel(BF_PXP_WFE_A_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_WFE_A_STORE_ADDR_1_CH0);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(
+ store_ch1->paddr + (store_ch1->left + store_ch1->top *
+ store_ch1->stride) * 2),
+ pxp->base + HW_PXP_WFE_A_STORE_ADDR_0_CH1);
+
+ __raw_writel(BF_PXP_WFE_A_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_WFE_A_STORE_ADDR_1_CH1);
+
+ /* ALU */
+ __raw_writel(BF_PXP_ALU_A_BUF_SIZE_BUF_WIDTH(fetch_ch0->width) |
+ BF_PXP_ALU_A_BUF_SIZE_BUF_HEIGHT(fetch_ch0->height),
+ pxp->base + HW_PXP_ALU_A_BUF_SIZE);
+
+ /* WFE */
+ __raw_writel(BF_PXP_WFE_A_DIMENSIONS_WIDTH(fetch_ch0->width) |
+ BF_PXP_WFE_A_DIMENSIONS_HEIGHT(fetch_ch0->height),
+ pxp->base + HW_PXP_WFE_A_DIMENSIONS);
+
+ /* Here it should be fetch_ch1 */
+ __raw_writel(BF_PXP_WFE_A_OFFSET_X_OFFSET(fetch_ch1->left) |
+ BF_PXP_WFE_A_OFFSET_Y_OFFSET(fetch_ch1->top),
+ pxp->base + HW_PXP_WFE_A_OFFSET);
+
+ __raw_writel((proc_data->lut & 0x000000FF) | 0x00000F00,
+ pxp->base + HW_PXP_WFE_A_SW_DATA_REGS);
+ __raw_writel((proc_data->partial_update | (proc_data->reagl_en << 1)),
+ pxp->base + HW_PXP_WFE_A_SW_FLAG_REGS);
+
+ __raw_writel(
+ BF_PXP_WFE_A_CTRL_ENABLE(1) |
+ BF_PXP_WFE_A_CTRL_SW_RESET(1),
+ pxp->base + HW_PXP_WFE_A_CTRL);
+
+ if (proc_data->alpha_en) {
+ __raw_writel(BF_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_Y(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_Y(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_X(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_X(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_H_OFS(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_L_OFS(0),
+ pxp->base + HW_PXP_WFA_ARRAY_FLAG0_MASK);
+ } else {
+ __raw_writel(BF_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_Y(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_Y(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_X(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_X(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL(2) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_H_OFS(0) |
+ BF_PXP_WFA_ARRAY_FLAG0_MASK_L_OFS(0),
+ pxp->base + HW_PXP_WFA_ARRAY_FLAG0_MASK);
+ }
+
+ /* disable CH1 when only doing detection */
+ v = __raw_readl(pxp->base + HW_PXP_WFE_A_STORE_CTRL_CH1);
+ if (proc_data->detection_only) {
+ v &= ~BF_PXP_WFE_A_STORE_CTRL_CH1_CH_EN(1);
+ printk(KERN_EMERG "%s: detection only happens\n", __func__);
+ } else
+ v |= BF_PXP_WFE_A_STORE_CTRL_CH1_CH_EN(1);
+ __raw_writel(v, pxp->base + HW_PXP_WFE_A_STORE_CTRL_CH1);
+}
+
+static void pxp_wfe_a_process_v3p(struct pxps *pxp)
+{
+ struct pxp_config_data *config_data = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &config_data->proc_data;
+ struct pxp_layer_param *fetch_ch0 = &config_data->wfe_a_fetch_param[0];
+ struct pxp_layer_param *fetch_ch1 = &config_data->wfe_a_fetch_param[1];
+ struct pxp_layer_param *store_ch0 = &config_data->wfe_a_store_param[0];
+ struct pxp_layer_param *store_ch1 = &config_data->wfe_a_store_param[1];
+ int v;
+
+ if (fetch_ch0->width != fetch_ch1->width ||
+ fetch_ch0->height != fetch_ch1->height) {
+ dev_err(pxp->dev, "width/height should be same for two fetch "
+ "channels\n");
+ }
+
+ print_param(fetch_ch0, "wfe_a fetch_ch0");
+ print_param(fetch_ch1, "wfe_a fetch_ch1");
+ print_param(store_ch0, "wfe_a store_ch0");
+ print_param(store_ch1, "wfe_a store_ch1");
+
+ /* Fetch */
+ __raw_writel(fetch_ch0->paddr, pxp->base + HW_PXP_WFB_FETCH_BUF1_ADDR);
+
+ __raw_writel(BF_PXP_WFB_FETCH_BUF1_CORD_YCORD(fetch_ch0->top) |
+ BF_PXP_WFB_FETCH_BUF1_CORD_XCORD(fetch_ch0->left),
+ pxp->base + HW_PXP_WFB_FETCH_BUF1_CORD);
+
+ __raw_writel(fetch_ch0->stride, pxp->base + HW_PXP_WFB_FETCH_BUF1_PITCH);
+
+ __raw_writel(BF_PXP_WFB_FETCH_BUF1_SIZE_BUF_HEIGHT(fetch_ch0->height - 1) |
+ BF_PXP_WFB_FETCH_BUF1_SIZE_BUF_WIDTH(fetch_ch0->width - 1),
+ pxp->base + HW_PXP_WFB_FETCH_BUF1_SIZE);
+
+ __raw_writel(fetch_ch1->paddr, pxp->base + HW_PXP_WFB_FETCH_BUF2_ADDR);
+
+ __raw_writel(BF_PXP_WFB_FETCH_BUF2_CORD_YCORD(fetch_ch1->top) |
+ BF_PXP_WFB_FETCH_BUF2_CORD_XCORD(fetch_ch1->left),
+ pxp->base + HW_PXP_WFB_FETCH_BUF2_CORD);
+
+ __raw_writel(fetch_ch1->stride * 2, pxp->base + HW_PXP_WFB_FETCH_BUF2_PITCH);
+
+ __raw_writel(BF_PXP_WFB_FETCH_BUF2_SIZE_BUF_HEIGHT(fetch_ch1->height - 1) |
+ BF_PXP_WFB_FETCH_BUF2_SIZE_BUF_WIDTH(fetch_ch1->width - 1),
+ pxp->base + HW_PXP_WFB_FETCH_BUF2_SIZE);
+
+ /* Store */
+ __raw_writel(BF_PXP_WFE_B_STORE_SIZE_CH0_OUT_WIDTH(store_ch0->width - 1) |
+ BF_PXP_WFE_B_STORE_SIZE_CH0_OUT_HEIGHT(store_ch0->height - 1),
+ pxp->base + HW_PXP_WFE_B_STORE_SIZE_CH0);
+
+
+ __raw_writel(BF_PXP_WFE_B_STORE_SIZE_CH1_OUT_WIDTH(store_ch1->width - 1) |
+ BF_PXP_WFE_B_STORE_SIZE_CH1_OUT_HEIGHT(store_ch1->height - 1),
+ pxp->base + HW_PXP_WFE_B_STORE_SIZE_CH1);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_PITCH_CH0_OUT_PITCH(store_ch0->stride) |
+ BF_PXP_WFE_B_STORE_PITCH_CH1_OUT_PITCH(store_ch1->stride * 2),
+ pxp->base + HW_PXP_WFE_B_STORE_PITCH);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(store_ch0->paddr),
+ pxp->base + HW_PXP_WFE_B_STORE_ADDR_0_CH0);
+ __raw_writel(BF_PXP_WFE_B_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_WFE_B_STORE_ADDR_1_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(
+ store_ch1->paddr + (store_ch1->left + store_ch1->top *
+ store_ch1->stride) * 2),
+ pxp->base + HW_PXP_WFE_B_STORE_ADDR_0_CH1);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_WFE_B_STORE_ADDR_1_CH1);
+
+ /* ALU */
+ __raw_writel(BF_PXP_ALU_B_BUF_SIZE_BUF_WIDTH(fetch_ch0->width) |
+ BF_PXP_ALU_B_BUF_SIZE_BUF_HEIGHT(fetch_ch0->height),
+ pxp->base + HW_PXP_ALU_B_BUF_SIZE);
+
+ /* WFE */
+ __raw_writel(BF_PXP_WFE_B_DIMENSIONS_WIDTH(fetch_ch0->width) |
+ BF_PXP_WFE_B_DIMENSIONS_HEIGHT(fetch_ch0->height),
+ pxp->base + HW_PXP_WFE_B_DIMENSIONS);
+
+ /* Here it should be fetch_ch1 */
+ __raw_writel(BF_PXP_WFE_B_OFFSET_X_OFFSET(fetch_ch1->left) |
+ BF_PXP_WFE_B_OFFSET_Y_OFFSET(fetch_ch1->top),
+ pxp->base + HW_PXP_WFE_B_OFFSET);
+
+ __raw_writel((proc_data->lut & 0x000000FF) | 0x00000F00,
+ pxp->base + HW_PXP_WFE_B_SW_DATA_REGS);
+ __raw_writel((proc_data->partial_update | (proc_data->reagl_en << 1)),
+ pxp->base + HW_PXP_WFE_B_SW_FLAG_REGS);
+
+ __raw_writel(
+ BF_PXP_WFE_B_CTRL_ENABLE(1) |
+ BF_PXP_WFE_B_CTRL_SW_RESET(1),
+ pxp->base + HW_PXP_WFE_B_CTRL);
+
+ if (proc_data->alpha_en) {
+ __raw_writel(BF_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_L_OFS(0),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG0_MASK);
+ } else {
+ __raw_writel(BF_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL(2) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_L_OFS(0),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG0_MASK);
+ }
+
+ /* disable CH1 when only doing detection */
+ v = __raw_readl(pxp->base + HW_PXP_WFE_B_STORE_CTRL_CH1);
+ if (proc_data->detection_only) {
+ v &= ~BF_PXP_WFE_B_STORE_CTRL_CH1_CH_EN(1);
+ printk(KERN_EMERG "%s: detection only happens\n", __func__);
+ } else
+ v |= BF_PXP_WFE_B_STORE_CTRL_CH1_CH_EN(1);
+ __raw_writel(v, pxp->base + HW_PXP_WFE_B_STORE_CTRL_CH1);
+}
+
+/*
+ * wfe b configuration
+ *
+ * configure wfe b engnine for reagl/-d waveform processing
+ */
+static void pxp_wfe_b_configure(struct pxps *pxp)
+{
+ /* Fetch */
+ __raw_writel(
+ BF_PXP_WFB_FETCH_CTRL_BF1_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE(0),
+ pxp->base + HW_PXP_WFB_FETCH_CTRL);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_PIXEL0_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL0_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_H_OFS(10) |
+ BF_PXP_WFB_ARRAY_PIXEL1_MASK_L_OFS(15),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL1_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL(0) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_H_OFS(2) |
+ BF_PXP_WFB_ARRAY_PIXEL2_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL2_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_PIXEL3_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL3_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_X(1) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_X(1) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_PIXEL4_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL4_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_X(1) |
+ BF_PXP_WFB_ARRAY_PIXEL5_MASK_BUF_SEL(0) |
+ BF_PXP_WFB_ARRAY_PIXEL5_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_PIXEL5_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL5_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_Y(1) |
+ BF_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_Y(1) |
+ BF_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL6_MASK_BUF_SEL(0) |
+ BF_PXP_WFB_ARRAY_PIXEL6_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_PIXEL6_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL6_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_Y(1) |
+ BF_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_PIXEL7_MASK_BUF_SEL(0) |
+ BF_PXP_WFB_ARRAY_PIXEL7_MASK_H_OFS(0) |
+ BF_PXP_WFB_ARRAY_PIXEL7_MASK_L_OFS(7),
+ pxp->base + HW_PXP_WFB_ARRAY_PIXEL7_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_H_OFS(8) |
+ BF_PXP_WFB_ARRAY_FLAG0_MASK_L_OFS(8),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG0_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG1_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG1_MASK_H_OFS(9) |
+ BF_PXP_WFB_ARRAY_FLAG1_MASK_L_OFS(9),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG1_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_X(1) |
+ BF_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_X(1) |
+ BF_PXP_WFB_ARRAY_FLAG2_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG2_MASK_H_OFS(8) |
+ BF_PXP_WFB_ARRAY_FLAG2_MASK_L_OFS(8),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG2_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_X(1) |
+ BF_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_X(1) |
+ BF_PXP_WFB_ARRAY_FLAG3_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG3_MASK_H_OFS(9) |
+ BF_PXP_WFB_ARRAY_FLAG3_MASK_L_OFS(9),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG3_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_X(1) |
+ BF_PXP_WFB_ARRAY_FLAG4_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG4_MASK_H_OFS(8) |
+ BF_PXP_WFB_ARRAY_FLAG4_MASK_L_OFS(8),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG4_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_X(1) |
+ BF_PXP_WFB_ARRAY_FLAG5_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG5_MASK_H_OFS(9) |
+ BF_PXP_WFB_ARRAY_FLAG5_MASK_L_OFS(9),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG5_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_Y(1) |
+ BF_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_Y(1) |
+ BF_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG6_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG6_MASK_H_OFS(8) |
+ BF_PXP_WFB_ARRAY_FLAG6_MASK_L_OFS(8),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG6_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_Y(1) |
+ BF_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_Y(1) |
+ BF_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG7_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG7_MASK_H_OFS(9) |
+ BF_PXP_WFB_ARRAY_FLAG7_MASK_L_OFS(9),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG7_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_Y(1) |
+ BF_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG8_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG8_MASK_H_OFS(8) |
+ BF_PXP_WFB_ARRAY_FLAG8_MASK_L_OFS(8),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG8_MASK);
+
+ __raw_writel(
+ BF_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_Y(0) |
+ BF_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_Y(1) |
+ BF_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_X(0) |
+ BF_PXP_WFB_ARRAY_FLAG9_MASK_BUF_SEL(1) |
+ BF_PXP_WFB_ARRAY_FLAG9_MASK_H_OFS(9) |
+ BF_PXP_WFB_ARRAY_FLAG9_MASK_L_OFS(9),
+ pxp->base + HW_PXP_WFB_ARRAY_FLAG9_MASK);
+
+ pxp_sram_init(pxp, WFE_B, (u32)active_matrix_data_8x8, 64);
+
+ /* Store */
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_CTRL_CH0_CH_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_PACK_IN_SEL(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_FILL_DATA_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES(32)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_COMBINE_2CHANNEL(1) |
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARBIT_EN(0),
+ pxp->base + HW_PXP_WFE_B_STORE_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_CTRL_CH1_CH_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_16(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_STORE_MEMORY_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_PACK_IN_SEL(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES(32),
+ pxp->base + HW_PXP_WFE_B_STORE_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(1)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(0),
+ pxp->base + HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(1)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(0),
+ pxp->base + HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH1);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_WFE_B_STORE_ADDR_1_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(0),
+ pxp->base + HW_PXP_WFE_B_STORE_ADDR_0_CH1);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_WFE_B_STORE_ADDR_1_CH1);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_FILL_DATA_CH0_FILL_DATA_CH0(0),
+ pxp->base + HW_PXP_WFE_B_STORE_FILL_DATA_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(0x00000000),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK0_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(0xff),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK0_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK1_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(0x3f00),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK1_L_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK2_H_CH0);
+
+ __raw_writel(BF_PXP_WFE_B_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK2_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7(0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_SHIFT_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(2)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(1) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(6)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_SHIFT_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(8)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(1)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(0),
+ pxp->base + HW_PXP_WFE_B_STORE_F_SHIFT_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK4(0)|
+ BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK5(0)|
+ BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK6(0)|
+ BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK7(0),
+ pxp->base + HW_PXP_WFE_B_STORE_F_MASK_H_CH0);
+
+ /* ALU */
+ __raw_writel(BF_PXP_ALU_B_INST_ENTRY_ENTRY_ADDR(0),
+ pxp->base + HW_PXP_ALU_B_INST_ENTRY);
+
+ __raw_writel(BF_PXP_ALU_B_PARAM_PARAM0(0) |
+ BF_PXP_ALU_B_PARAM_PARAM1(0),
+ pxp->base + HW_PXP_ALU_B_PARAM);
+
+ __raw_writel(BF_PXP_ALU_B_CONFIG_BUF_ADDR(0),
+ pxp->base + HW_PXP_ALU_B_CONFIG);
+
+ __raw_writel(BF_PXP_ALU_B_LUT_CONFIG_MODE(0) |
+ BF_PXP_ALU_B_LUT_CONFIG_EN(0),
+ pxp->base + HW_PXP_ALU_B_LUT_CONFIG);
+
+ __raw_writel(BF_PXP_ALU_B_LUT_DATA0_LUT_DATA_L(0),
+ pxp->base + HW_PXP_ALU_B_LUT_DATA0);
+
+ __raw_writel(BF_PXP_ALU_B_LUT_DATA1_LUT_DATA_H(0),
+ pxp->base + HW_PXP_ALU_B_LUT_DATA1);
+
+ __raw_writel(
+ BF_PXP_ALU_B_CTRL_BYPASS (1) |
+ BF_PXP_ALU_B_CTRL_ENABLE (1) |
+ BF_PXP_ALU_B_CTRL_START (0) |
+ BF_PXP_ALU_B_CTRL_SW_RESET (0),
+ pxp->base + HW_PXP_ALU_B_CTRL);
+
+ /* WFE */
+ __raw_writel(0x00000402, pxp->base + HW_PXP_WFE_B_SW_DATA_REGS);
+
+ __raw_writel(0x02040608, pxp->base + HW_PXP_WFE_B_STAGE1_MUX0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX2);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX4);
+ __raw_writel(0x03000000, pxp->base + HW_PXP_WFE_B_STAGE1_MUX5);
+ __raw_writel(0x050A040A, pxp->base + HW_PXP_WFE_B_STAGE1_MUX6);
+ __raw_writel(0x070A060A, pxp->base + HW_PXP_WFE_B_STAGE1_MUX7);
+ __raw_writel(0x0000000A, pxp->base + HW_PXP_WFE_B_STAGE1_MUX8);
+
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX0);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX1);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX2);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX4);
+ __raw_writel(0x1C1E2022, pxp->base + HW_PXP_WFE_B_STAGE2_MUX5);
+ __raw_writel(0x1215181A, pxp->base + HW_PXP_WFE_B_STAGE2_MUX6);
+ __raw_writel(0x00000C0F, pxp->base + HW_PXP_WFE_B_STAGE2_MUX7);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX8);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX9);
+ __raw_writel(0x01000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX10);
+ __raw_writel(0x000C010B, pxp->base + HW_PXP_WFE_B_STAGE2_MUX11);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE2_MUX12);
+
+ __raw_writel(0x09000C01, pxp->base + HW_PXP_WFE_B_STAGE3_MUX0);
+ __raw_writel(0x003A2A1D, pxp->base + HW_PXP_WFE_B_STAGE3_MUX1);
+ __raw_writel(0x09000C01, pxp->base + HW_PXP_WFE_B_STAGE3_MUX2);
+ __raw_writel(0x003A2A1D, pxp->base + HW_PXP_WFE_B_STAGE3_MUX3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE3_MUX4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE3_MUX5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE3_MUX6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STAGE3_MUX7);
+ __raw_writel(0x07060504, pxp->base + HW_PXP_WFE_B_STAGE3_MUX8);
+ __raw_writel(0x00000008, pxp->base + HW_PXP_WFE_B_STAGE3_MUX9);
+ __raw_writel(0x00001211, pxp->base + HW_PXP_WFE_B_STAGE3_MUX10);
+
+ __raw_writel(0x02010100, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_0);
+ __raw_writel(0x03020201, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_1);
+ __raw_writel(0x03020201, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_2);
+ __raw_writel(0x04030302, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT0_7);
+
+ __raw_writel(0x02010100, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_0);
+ __raw_writel(0x03020201, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_1);
+ __raw_writel(0x03020201, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_2);
+ __raw_writel(0x04030302, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_3);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_4);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_5);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_6);
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X8_OUT1_7);
+
+ __raw_writel(0x0000000F, pxp->base + HW_PXP_WFE_B_STAGE1_5X8_MASKS_0);
+
+ __raw_writel(0x00000000, pxp->base + HW_PXP_WFE_B_STG1_5X1_OUT0);
+ __raw_writel(0x0000000F, pxp->base + HW_PXP_WFE_B_STG1_5X1_MASKS);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT2_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT3_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT4_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STAGE2_5X6_MASKS_0);
+ __raw_writel(0x3F3F3F3F, pxp->base + HW_PXP_WFE_B_STAGE2_5X6_ADDR_0);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT0_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X6_OUT1_7);
+
+ __raw_writel(0x00008000, pxp->base + HW_PXP_WFE_B_STG2_5X1_OUT0);
+ __raw_writel(0x0000FFFE, pxp->base + HW_PXP_WFE_B_STG2_5X1_OUT1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X1_OUT2);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG2_5X1_OUT3);
+ __raw_writel(0x00000F0F, pxp->base + HW_PXP_WFE_B_STG2_5X1_MASKS);
+
+ __raw_writel(0x00007F7F, pxp->base + HW_PXP_WFE_B_STG3_F8X1_MASKS);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_0);
+ __raw_writel(0x00FF00FF, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_2);
+ __raw_writel(0x000000FF, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT0_7);
+
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_0);
+ __raw_writel(0xFF3FFF3F, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_1);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_2);
+ __raw_writel(0xFFFFFF1F, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_3);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_4);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_5);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_6);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG3_F8X1_OUT1_7);
+
+ __raw_writel(
+ BF_PXP_WFE_B_CTRL_ENABLE(1) |
+ BF_PXP_WFE_B_CTRL_SW_RESET(1),
+ pxp->base + HW_PXP_WFE_B_CTRL);
+}
+
+/* wfe b processing
+ * use wfe b to process an update
+ * call this function only after pxp_wfe_a_processing
+ * x,y,width,height:
+ * coordinate and size of the update region
+ * twb:
+ * temp working buffer, 16bpp
+ * only used when reagl_en is 1
+ * wb:
+ * working buffer, 16bpp
+ * lut:
+ * lut buffer, 8bpp
+ * lut_update:
+ * 0 - wfe_b is used for reagl/reagl-d operation
+ * 1 - wfe_b is used for lut update operation
+ * reagl_d_en:
+ * 0 - use reagl waveform algorithm
+ * 1 - use reagl/-d waveform algorithm
+ */
+static void pxp_wfe_b_process(struct pxps *pxp)
+{
+ struct pxp_config_data *config_data = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &config_data->proc_data;
+ struct pxp_layer_param *fetch_ch0 = &config_data->wfe_b_fetch_param[0];
+ struct pxp_layer_param *fetch_ch1 = &config_data->wfe_b_fetch_param[1];
+ struct pxp_layer_param *store_ch0 = &config_data->wfe_b_store_param[0];
+ struct pxp_layer_param *store_ch1 = &config_data->wfe_b_store_param[1];
+ static int comp_mask;
+ /* Fetch */
+
+ print_param(fetch_ch0, "wfe_b fetch_ch0");
+ print_param(fetch_ch1, "wfe_b fetch_ch1");
+ print_param(store_ch0, "wfe_b store_ch0");
+ print_param(store_ch1, "wfe_b store_ch1");
+
+ __raw_writel(fetch_ch0->paddr, pxp->base + HW_PXP_WFB_FETCH_BUF1_ADDR);
+
+ __raw_writel(
+ BF_PXP_WFB_FETCH_BUF1_CORD_YCORD(fetch_ch0->top) |
+ BF_PXP_WFB_FETCH_BUF1_CORD_XCORD(fetch_ch0->left),
+ pxp->base + HW_PXP_WFB_FETCH_BUF1_CORD);
+
+ __raw_writel(fetch_ch0->stride,
+ pxp->base + HW_PXP_WFB_FETCH_BUF1_PITCH);
+
+ __raw_writel(
+ BF_PXP_WFB_FETCH_BUF1_SIZE_BUF_HEIGHT(fetch_ch0->height-1) |
+ BF_PXP_WFB_FETCH_BUF1_SIZE_BUF_WIDTH(fetch_ch0->width-1),
+ pxp->base + HW_PXP_WFB_FETCH_BUF1_SIZE);
+
+ __raw_writel(fetch_ch1->paddr, pxp->base + HW_PXP_WFB_FETCH_BUF2_ADDR);
+
+ __raw_writel(fetch_ch1->stride * 2,
+ pxp->base + HW_PXP_WFB_FETCH_BUF2_PITCH);
+
+ __raw_writel(
+ BF_PXP_WFB_FETCH_BUF2_CORD_YCORD(fetch_ch1->top) |
+ BF_PXP_WFB_FETCH_BUF2_CORD_XCORD(fetch_ch1->left),
+ pxp->base + HW_PXP_WFB_FETCH_BUF2_CORD);
+
+ __raw_writel(
+ BF_PXP_WFB_FETCH_BUF2_SIZE_BUF_HEIGHT(fetch_ch1->height-1) |
+ BF_PXP_WFB_FETCH_BUF2_SIZE_BUF_WIDTH(fetch_ch1->width-1),
+ pxp->base + HW_PXP_WFB_FETCH_BUF2_SIZE);
+
+ if (!proc_data->lut_update) {
+ __raw_writel(
+ BF_PXP_WFB_FETCH_CTRL_BF1_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE(0),
+ pxp->base + HW_PXP_WFB_FETCH_CTRL);
+ } else {
+ __raw_writel(
+ BF_PXP_WFB_FETCH_CTRL_BF1_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE(0),
+ pxp->base + HW_PXP_WFB_FETCH_CTRL);
+ }
+
+#ifdef CONFIG_REAGLD_ALGO_CHECK
+ __raw_writel(
+ (__raw_readl(pxp->base + HW_PXP_WFE_B_SW_DATA_REGS) & 0x0000FFFF) | ((fetch_ch0->comp_mask&0x000000FF)<<16),
+ pxp->base + HW_PXP_WFE_B_SW_DATA_REGS);
+#else
+ __raw_writel(
+ (__raw_readl(pxp->base + HW_PXP_WFE_B_SW_DATA_REGS) & 0x0000FFFF) | ((comp_mask&0x000000FF)<<16),
+ pxp->base + HW_PXP_WFE_B_SW_DATA_REGS);
+
+ /* comp_mask only need to be updated upon REAGL-D, 0,1,...7, 0,1,... */
+ if (proc_data->reagl_d_en) {
+ comp_mask++;
+ if (comp_mask>7)
+ comp_mask = 0;
+ }
+#endif
+
+ /* Store */
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SIZE_CH0_OUT_WIDTH(store_ch0->width-1)|
+ BF_PXP_WFE_B_STORE_SIZE_CH0_OUT_HEIGHT(store_ch0->height-1),
+ pxp->base + HW_PXP_WFE_B_STORE_SIZE_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SIZE_CH1_OUT_WIDTH(store_ch1->width-1)|
+ BF_PXP_WFE_B_STORE_SIZE_CH1_OUT_HEIGHT(store_ch1->height-1),
+ pxp->base + HW_PXP_WFE_B_STORE_SIZE_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_PITCH_CH0_OUT_PITCH(store_ch0->stride * 2)|
+ BF_PXP_WFE_B_STORE_PITCH_CH1_OUT_PITCH(store_ch1->stride * 2),
+ pxp->base + HW_PXP_WFE_B_STORE_PITCH);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(store_ch0->paddr
+ + (store_ch0->left + store_ch0->top * store_ch0->stride) * 2),
+ pxp->base + HW_PXP_WFE_B_STORE_ADDR_0_CH0);
+
+ if (proc_data->lut_update) {
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK1_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK1_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK2_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(0x3f0000),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK2_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK0(0x30)|
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK1(0)|
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK2(0)|
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK3(0),
+ pxp->base + HW_PXP_WFE_B_STORE_F_MASK_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(4)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(1)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(0),
+ pxp->base + HW_PXP_WFE_B_STORE_F_SHIFT_L_CH0);
+ } else {
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK1_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(0x3f00),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK1_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK2_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(0x0),
+ pxp->base + HW_PXP_WFE_B_STORE_D_MASK2_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK0(3)|
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK1(0)|
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK2(0)|
+ BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK3(0),
+ pxp->base + HW_PXP_WFE_B_STORE_F_MASK_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(8)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(1)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(0)|
+ BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(0),
+ pxp->base + HW_PXP_WFE_B_STORE_F_SHIFT_L_CH0);
+ }
+
+ /* ALU */
+ __raw_writel(
+ BF_PXP_ALU_B_BUF_SIZE_BUF_WIDTH(fetch_ch0->width) |
+ BF_PXP_ALU_B_BUF_SIZE_BUF_HEIGHT(fetch_ch0->height),
+ pxp->base + HW_PXP_ALU_B_BUF_SIZE);
+
+ /* WFE */
+ __raw_writel(
+ BF_PXP_WFE_B_DIMENSIONS_WIDTH(fetch_ch0->width) |
+ BF_PXP_WFE_B_DIMENSIONS_HEIGHT(fetch_ch0->height),
+ pxp->base + HW_PXP_WFE_B_DIMENSIONS);
+
+ __raw_writel( /*TODO check*/
+ BF_PXP_WFE_B_OFFSET_X_OFFSET(fetch_ch0->left) |
+ BF_PXP_WFE_B_OFFSET_Y_OFFSET(fetch_ch0->top),
+ pxp->base + HW_PXP_WFE_B_OFFSET);
+
+ __raw_writel(proc_data->reagl_d_en, pxp->base + HW_PXP_WFE_B_SW_FLAG_REGS);
+}
+
+void pxp_fill(
+ u32 bpp,
+ u32 value,
+ u32 width,
+ u32 height,
+ u32 output_buffer,
+ u32 output_pitch)
+{
+ u32 active_bpp;
+ u32 pitch;
+
+ if (bpp == 8) {
+ active_bpp = 0;
+ pitch = output_pitch;
+ } else if(bpp == 16) {
+ active_bpp = 1;
+ pitch = output_pitch * 2;
+ } else {
+ active_bpp = 2;
+ pitch = output_pitch * 4;
+ }
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_CTRL_CH0_CH_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_PACK_IN_SEL(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_FILL_DATA_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES(32)|
+ BF_PXP_WFE_B_STORE_CTRL_CH0_COMBINE_2CHANNEL(0) |
+ BF_PXP_WFE_B_STORE_CTRL_CH0_ARBIT_EN(0),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_CTRL_CH1_CH_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_16(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_PACK_IN_SEL(0)|
+ BF_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES(16),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SIZE_CH0_OUT_WIDTH(width-1)|
+ BF_PXP_WFE_B_STORE_SIZE_CH0_OUT_HEIGHT(height-1),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_SIZE_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SIZE_CH1_OUT_WIDTH(width-1)|
+ BF_PXP_WFE_B_STORE_SIZE_CH1_OUT_HEIGHT(height-1),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_SIZE_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_PITCH_CH0_OUT_PITCH(pitch)|
+ BF_PXP_WFE_B_STORE_PITCH_CH1_OUT_PITCH(pitch),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_PITCH);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(active_bpp)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(1),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(active_bpp)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN(0)|
+ BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN(0),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(output_buffer),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_ADDR_0_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(0),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_ADDR_1_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(output_buffer),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_ADDR_0_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(0),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_ADDR_1_CH1);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_FILL_DATA_CH0_FILL_DATA_CH0(value),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_FILL_DATA_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(0x00000000),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_D_MASK0_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(0x000000ff),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_D_MASK0_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(0x00000000),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_D_MASK1_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(0x000000ff),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_D_MASK1_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(0x00000000),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_D_MASK2_H_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(0x000000ff),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_D_MASK2_L_CH0);
+
+ __raw_writel(
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(0) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(32)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(1) |
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(40)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(1)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(0)|
+ BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(0),
+ pxp_reg_base + HW_PXP_WFE_B_STORE_D_SHIFT_L_CH0);
+
+ __raw_writel(
+ BF_PXP_CTRL2_ENABLE (1) |
+ BF_PXP_CTRL2_ROTATE0 (0) |
+ BF_PXP_CTRL2_HFLIP0 (0) |
+ BF_PXP_CTRL2_VFLIP0 (0) |
+ BF_PXP_CTRL2_ROTATE1 (0) |
+ BF_PXP_CTRL2_HFLIP1 (0) |
+ BF_PXP_CTRL2_VFLIP1 (0) |
+ BF_PXP_CTRL2_ENABLE_DITHER (0) |
+ BF_PXP_CTRL2_ENABLE_WFE_A (0) |
+ BF_PXP_CTRL2_ENABLE_WFE_B (1) |
+ BF_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE (0) |
+ BF_PXP_CTRL2_ENABLE_ALPHA_B (0) |
+ BF_PXP_CTRL2_BLOCK_SIZE (0) |
+ BF_PXP_CTRL2_ENABLE_CSC2 (0) |
+ BF_PXP_CTRL2_ENABLE_LUT (0) |
+ BF_PXP_CTRL2_ENABLE_ROTATE0 (0) |
+ BF_PXP_CTRL2_ENABLE_ROTATE1 (0),
+ pxp_reg_base + HW_PXP_CTRL2);
+
+ if (busy_wait(BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ &
+ __raw_readl(pxp_reg_base + HW_PXP_IRQ)) == false)
+ printk("%s: wait for completion timeout\n", __func__);
+}
+EXPORT_SYMBOL(pxp_fill);
+
+static void pxp_lut_cleanup_multiple(struct pxps *pxp, u64 lut, bool set)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+
+ if (proc_data->lut_cleanup == 1) {
+ if (set) {
+ __raw_writel((u32)lut, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_0 + 0x4);
+ __raw_writel((u32)(lut>>32), pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_1 + 0x4);
+ } else {
+ pxp_luts_deactivate(pxp, lut);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT1_1);
+ }
+ }
+}
+
+static void pxp_lut_cleanup_multiple_v3p(struct pxps *pxp, u64 lut, bool set)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+
+ if (proc_data->lut_cleanup == 1) {
+ if (set) {
+ __raw_writel((u32)lut, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_0 + 0x4);
+ __raw_writel((u32)(lut>>32), pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_1 + 0x4);
+ } else {
+ pxp_luts_deactivate(pxp, lut);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_0);
+ __raw_writel(0, pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT1_1);
+ }
+ }
+}
+
+#ifdef CONFIG_MXC_FPGA_M4_TEST
+void m4_process(void)
+{
+ __raw_writel(0x7, pinctrl_base + PIN_DOUT); /* M4 Start */
+
+ while (!(__raw_readl(pxp_reg_base + HW_PXP_HANDSHAKE_CPU_STORE) & BM_PXP_HANDSHAKE_CPU_STORE_SW0_B0_READY));
+
+ __raw_writel(0x3, pinctrl_base + PIN_DOUT); /* M4 Stop */
+
+
+}
+#else
+void m4_process(void) {}
+#endif
+EXPORT_SYMBOL(m4_process);
+
+static void pxp_lut_status_set(struct pxps *pxp, unsigned int lut)
+{
+ if(lut<32)
+ __raw_writel(
+ __raw_readl(pxp_reg_base + HW_PXP_WFE_A_STG1_8X1_OUT0_0) | (1 << lut),
+ pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT0_0);
+ else {
+ lut = lut -32;
+ __raw_writel(
+ __raw_readl(pxp_reg_base + HW_PXP_WFE_A_STG1_8X1_OUT0_1) | (1 << lut),
+ pxp->base + HW_PXP_WFE_A_STG1_8X1_OUT0_1);
+ }
+}
+
+static void pxp_lut_status_set_v3p(struct pxps *pxp, unsigned int lut)
+{
+ if(lut<32)
+ __raw_writel(
+ __raw_readl(pxp_reg_base + HW_PXP_WFE_B_STG1_8X1_OUT0_0) | (1 << lut),
+ pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_0);
+ else {
+ lut = lut -32;
+ __raw_writel(
+ __raw_readl(pxp_reg_base + HW_PXP_WFE_B_STG1_8X1_OUT0_1) | (1 << lut),
+ pxp->base + HW_PXP_WFE_B_STG1_8X1_OUT0_1);
+ }
+}
+
+static void pxp_luts_activate(struct pxps *pxp, u64 lut_status)
+{
+ int i = 0;
+
+ if (!lut_status)
+ return;
+
+ for (i = 0; i < 64; i++) {
+ if (lut_status & (1ULL << i))
+ if (pxp->devdata && pxp->devdata->pxp_lut_status_set)
+ pxp->devdata->pxp_lut_status_set(pxp, i);
+ }
+}
+
+static void pxp_lut_status_clr(unsigned int lut)
+{
+ if(lut<32)
+ __raw_writel(
+ __raw_readl(pxp_reg_base + HW_PXP_WFE_A_STG1_8X1_OUT0_0) & (~(1 << lut)),
+ pxp_reg_base + HW_PXP_WFE_A_STG1_8X1_OUT0_0);
+ else
+ {
+ lut = lut -32;
+ __raw_writel(
+ __raw_readl(pxp_reg_base + HW_PXP_WFE_A_STG1_8X1_OUT0_1) & (~(1 << lut)),
+ pxp_reg_base + HW_PXP_WFE_A_STG1_8X1_OUT0_1);
+ }
+}
+
+static void pxp_lut_status_clr_v3p(unsigned int lut)
+{
+ if(lut<32)
+ __raw_writel(
+ __raw_readl(pxp_reg_base + HW_PXP_WFE_B_STG1_8X1_OUT0_0) & (~(1 << lut)),
+ pxp_reg_base + HW_PXP_WFE_B_STG1_8X1_OUT0_0);
+ else
+ {
+ lut = lut -32;
+ __raw_writel(
+ __raw_readl(pxp_reg_base + HW_PXP_WFE_B_STG1_8X1_OUT0_1) & (~(1 << lut)),
+ pxp_reg_base + HW_PXP_WFE_B_STG1_8X1_OUT0_1);
+ }
+}
+
+/* this function should be called in the epdc
+ * driver explicitly when some epdc lut becomes
+ * idle. So it should be exported.
+ */
+static void pxp_luts_deactivate(struct pxps *pxp, u64 lut_status)
+{
+ int i = 0;
+
+ if (!lut_status)
+ return;
+
+ for (i = 0; i < 64; i++) {
+ if (lut_status & (1ULL << i))
+ if (pxp->devdata && pxp->devdata->pxp_lut_status_clr)
+ pxp->devdata->pxp_lut_status_clr(i);
+ }
+}
+
+/* use histogram_B engine to calculate histogram status */
+static void pxp_histogram_enable(struct pxps *pxp,
+ unsigned int width,
+ unsigned int height)
+{
+ __raw_writel(
+ BF_PXP_HIST_B_BUF_SIZE_HEIGHT(height)|
+ BF_PXP_HIST_B_BUF_SIZE_WIDTH(width),
+ pxp->base + HW_PXP_HIST_B_BUF_SIZE);
+
+ __raw_writel(
+ BF_PXP_HIST_B_MASK_MASK_EN(1)|
+ BF_PXP_HIST_B_MASK_MASK_MODE(0)|
+ BF_PXP_HIST_B_MASK_MASK_OFFSET(64)|
+ BF_PXP_HIST_B_MASK_MASK_WIDTH(0)|
+ BF_PXP_HIST_B_MASK_MASK_VALUE0(1) |
+ BF_PXP_HIST_B_MASK_MASK_VALUE1(0),
+ pxp->base + HW_PXP_HIST_B_MASK);
+
+ __raw_writel(
+ BF_PXP_HIST_B_CTRL_PIXEL_WIDTH(3)|
+ BF_PXP_HIST_B_CTRL_PIXEL_OFFSET(8)|
+ BF_PXP_HIST_B_CTRL_CLEAR(0)|
+ BF_PXP_HIST_B_CTRL_ENABLE(1),
+ pxp->base + HW_PXP_HIST_B_CTRL);
+}
+
+static void pxp_histogram_status_report(struct pxps *pxp, u32 *hist_status)
+{
+ BUG_ON(!hist_status);
+
+ *hist_status = (__raw_readl(pxp->base + HW_PXP_HIST_B_CTRL) & BM_PXP_HIST_B_CTRL_STATUS)
+ >> BP_PXP_HIST_B_CTRL_STATUS;
+ dev_dbg(pxp->dev, "%d pixels are used to calculate histogram status %d\n",
+ __raw_readl(pxp->base + HW_PXP_HIST_B_TOTAL_PIXEL), *hist_status);
+}
+
+static void pxp_histogram_disable(struct pxps *pxp)
+{
+ __raw_writel(
+ BF_PXP_HIST_B_CTRL_PIXEL_WIDTH(3)|
+ BF_PXP_HIST_B_CTRL_PIXEL_OFFSET(4)|
+ BF_PXP_HIST_B_CTRL_CLEAR(1)|
+ BF_PXP_HIST_B_CTRL_ENABLE(0),
+ pxp->base + HW_PXP_HIST_B_CTRL);
+}
+
+/* the collision detection function will be
+ * called by epdc driver when required
+ */
+static void pxp_collision_detection_enable(struct pxps *pxp,
+ unsigned int width,
+ unsigned int height)
+{
+ __raw_writel(
+ BF_PXP_HIST_A_BUF_SIZE_HEIGHT(height)|
+ BF_PXP_HIST_A_BUF_SIZE_WIDTH(width),
+ pxp_reg_base + HW_PXP_HIST_A_BUF_SIZE);
+
+ __raw_writel(
+ BF_PXP_HIST_A_MASK_MASK_EN(1)|
+ BF_PXP_HIST_A_MASK_MASK_MODE(0)|
+ BF_PXP_HIST_A_MASK_MASK_OFFSET(65)|
+ BF_PXP_HIST_A_MASK_MASK_WIDTH(0)|
+ BF_PXP_HIST_A_MASK_MASK_VALUE0(1) |
+ BF_PXP_HIST_A_MASK_MASK_VALUE1(0),
+ pxp_reg_base + HW_PXP_HIST_A_MASK);
+
+ __raw_writel(
+ BF_PXP_HIST_A_CTRL_PIXEL_WIDTH(6)|
+ BF_PXP_HIST_A_CTRL_PIXEL_OFFSET(24)|
+ BF_PXP_HIST_A_CTRL_CLEAR(0)|
+ BF_PXP_HIST_A_CTRL_ENABLE(1),
+ pxp_reg_base + HW_PXP_HIST_A_CTRL);
+}
+
+static void pxp_collision_detection_disable(struct pxps *pxp)
+{
+ __raw_writel(
+ BF_PXP_HIST_A_CTRL_PIXEL_WIDTH(6)|
+ BF_PXP_HIST_A_CTRL_PIXEL_OFFSET(24)|
+ BF_PXP_HIST_A_CTRL_CLEAR(1)|
+ BF_PXP_HIST_A_CTRL_ENABLE(0),
+ pxp_reg_base + HW_PXP_HIST_A_CTRL);
+}
+
+/* this function can be called in the epdc callback
+ * function in the pxp_irq() to let the epdc know
+ * the collision information for the previous working
+ * buffer update.
+ */
+static bool pxp_collision_status_report(struct pxps *pxp, struct pxp_collision_info *info)
+{
+ unsigned int count;
+
+ BUG_ON(!info);
+ memset(info, 0x0, sizeof(*info));
+
+ info->pixel_cnt = count = __raw_readl(pxp->base + HW_PXP_HIST_A_TOTAL_PIXEL);
+ if (!count)
+ return false;
+
+ dev_dbg(pxp->dev, "%s: pixel_cnt = %d\n", __func__, info->pixel_cnt);
+ info->rect_min_x = __raw_readl(pxp->base + HW_PXP_HIST_A_ACTIVE_AREA_X) & 0xffff;
+ dev_dbg(pxp->dev, "%s: rect_min_x = %d\n", __func__, info->rect_min_x);
+ info->rect_max_x = (__raw_readl(pxp->base + HW_PXP_HIST_A_ACTIVE_AREA_X) >> 16) & 0xffff;
+ dev_dbg(pxp->dev, "%s: rect_max_x = %d\n", __func__, info->rect_max_x);
+ info->rect_min_y = __raw_readl(pxp->base + HW_PXP_HIST_A_ACTIVE_AREA_Y) & 0xffff;
+ dev_dbg(pxp->dev, "%s: rect_min_y = %d\n", __func__, info->rect_min_y);
+ info->rect_max_y = (__raw_readl(pxp->base + HW_PXP_HIST_A_ACTIVE_AREA_Y) >> 16) & 0xffff;
+ dev_dbg(pxp->dev, "%s: rect_max_y = %d\n", __func__, info->rect_max_y);
+
+ info->victim_luts[0] = __raw_readl(pxp->base + HW_PXP_HIST_A_RAW_STAT0);
+ dev_dbg(pxp->dev, "%s: victim_luts[0] = 0x%x\n", __func__, info->victim_luts[0]);
+ info->victim_luts[1] = __raw_readl(pxp->base + HW_PXP_HIST_A_RAW_STAT1);
+ dev_dbg(pxp->dev, "%s: victim_luts[1] = 0x%x\n", __func__, info->victim_luts[1]);
+
+ return true;
+}
+
+void pxp_get_collision_info(struct pxp_collision_info *info)
+{
+ BUG_ON(!info);
+
+ memcpy(info, &col_info, sizeof(struct pxp_collision_info));
+}
+EXPORT_SYMBOL(pxp_get_collision_info);
+
+static void dither_prefetch_config(struct pxps *pxp)
+{
+ struct pxp_config_data *config_data = &pxp->pxp_conf_state;
+ struct pxp_layer_param *fetch_ch0 = &config_data->dither_fetch_param[0];
+ struct pxp_layer_param *fetch_ch1 = &config_data->dither_fetch_param[1];
+
+ print_param(fetch_ch0, "dither fetch_ch0");
+ print_param(fetch_ch1, "dither fetch_ch1");
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_CTRL_CH0_CH_EN(1) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_BYPASS_PIXEL_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_HFLIP(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_VFLIP(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES(32) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_ARBIT_EN(0),
+ pxp->base + HW_PXP_DITHER_FETCH_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_CTRL_CH1_CH_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_16(0)|
+ BF_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH1_BYPASS_PIXEL_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH1_HFLIP(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH1_VFLIP(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES(2) |
+ BF_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM(0),
+ pxp->base + HW_PXP_DITHER_FETCH_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X(0) |
+ BF_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y(0),
+ pxp->base + HW_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0);
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X(fetch_ch0->width - 1) |
+ BF_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y(fetch_ch0->height - 1),
+ pxp->base + HW_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X(0) |
+ BF_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y(0),
+ pxp->base + HW_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1);
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X(fetch_ch1->width - 1) |
+ BF_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y(fetch_ch1->height - 1),
+ pxp->base + HW_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1);
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH(fetch_ch0->width - 1) |
+ BF_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT(fetch_ch0->height - 1),
+ pxp->base + HW_PXP_DITHER_FETCH_SIZE_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH(fetch_ch1->width - 1) |
+ BF_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT(fetch_ch1->height - 1),
+ pxp->base + HW_PXP_DITHER_FETCH_SIZE_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_PITCH_CH0_INPUT_PITCH(fetch_ch0->stride) |
+ BF_PXP_DITHER_FETCH_PITCH_CH1_INPUT_PITCH(fetch_ch1->stride),
+ pxp->base + HW_PXP_DITHER_FETCH_PITCH);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_EN(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS(1),
+ pxp->base + HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_EN(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS(1),
+ pxp->base + HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET0(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET1(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET2(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET3(0),
+ pxp->base + HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET0(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET1(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET2(0) |
+ BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET3(0),
+ pxp->base + HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH0(7) |
+ BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH1(7) |
+ BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH2(7) |
+ BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH3(7),
+ pxp->base + HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH0(7) |
+ BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH1(7) |
+ BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH2(7) |
+ BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH3(7),
+ pxp->base + HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_ADDR_0_CH0_INPUT_BASE_ADDR0(fetch_ch0->paddr),
+ pxp->base + HW_PXP_DITHER_FETCH_ADDR_0_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_ADDR_1_CH0_INPUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_DITHER_FETCH_ADDR_1_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_ADDR_0_CH1_INPUT_BASE_ADDR0(fetch_ch1->paddr),
+ pxp->base + HW_PXP_DITHER_FETCH_ADDR_0_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_ADDR_1_CH1_INPUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_DITHER_FETCH_ADDR_1_CH1);
+}
+
+static void dither_store_config(struct pxps *pxp)
+{
+ struct pxp_config_data *config_data = &pxp->pxp_conf_state;
+ struct pxp_layer_param *store_ch0 = &config_data->dither_store_param[0];
+ struct pxp_layer_param *store_ch1 = &config_data->dither_store_param[1];
+
+ print_param(store_ch0, "dither store_ch0");
+ print_param(store_ch1, "dither store_ch1");
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_CTRL_CH0_CH_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_BLOCK_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_HANDSHAKE_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARRAY_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_STORE_BYPASS_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_STORE_MEMORY_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_PACK_IN_SEL(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_FILL_DATA_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES(32)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL(0) |
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN(0),
+ pxp->base + HW_PXP_DITHER_STORE_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_CTRL_CH1_CH_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_BLOCK_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_BLOCK_16(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_HANDSHAKE_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_ARRAY_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_STORE_BYPASS_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_STORE_MEMORY_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_PACK_IN_SEL(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES(32),
+ pxp->base + HW_PXP_DITHER_STORE_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH(store_ch0->width - 1) |
+ BF_PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT(store_ch0->height - 1),
+ pxp->base + HW_PXP_DITHER_STORE_SIZE_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_SIZE_CH1_OUT_WIDTH(store_ch1->width - 1) |
+ BF_PXP_DITHER_STORE_SIZE_CH1_OUT_HEIGHT(store_ch1->height - 1),
+ pxp->base + HW_PXP_DITHER_STORE_SIZE_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_PITCH_CH0_OUT_PITCH(store_ch0->stride) |
+ BF_PXP_DITHER_STORE_PITCH_CH1_OUT_PITCH(store_ch1->stride),
+ pxp->base + HW_PXP_DITHER_STORE_PITCH);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(0)|
+ BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(0)|
+ BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(0)|
+ BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(1),
+ pxp->base + HW_PXP_DITHER_STORE_SHIFT_CTRL_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(0)|
+ BF_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN(0)|
+ BF_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN(0),
+ pxp->base + HW_PXP_DITHER_STORE_SHIFT_CTRL_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(store_ch0->paddr),
+ pxp->base + HW_PXP_DITHER_STORE_ADDR_0_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_DITHER_STORE_ADDR_1_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(store_ch1->paddr),
+ pxp->base + HW_PXP_DITHER_STORE_ADDR_0_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(0),
+ pxp->base + HW_PXP_DITHER_STORE_ADDR_1_CH1);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_FILL_DATA_CH0_FILL_DATA_CH0(0),
+ pxp->base + HW_PXP_DITHER_STORE_FILL_DATA_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(0xffffff),
+ pxp->base + HW_PXP_DITHER_STORE_D_MASK0_H_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(0x0),
+ pxp->base + HW_PXP_DITHER_STORE_D_MASK0_L_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(0x0),
+ pxp->base + HW_PXP_DITHER_STORE_D_MASK1_H_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(0xff),
+ pxp->base + HW_PXP_DITHER_STORE_D_MASK1_L_CH0);
+
+ __raw_writel(
+ BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(32) |
+ BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(0) |
+ BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(32)|
+ BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(1) |
+ BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(0)|
+ BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(0)|
+ BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(0)|
+ BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(0),
+ pxp->base + HW_PXP_DITHER_STORE_D_SHIFT_L_CH0);
+}
+
+static void pxp_set_final_lut_data(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+
+ if(proc_data->quant_bit < 2) {
+ pxp_sram_init(pxp, DITHER0_LUT, (u32)bit1_dither_data_8x8, 64);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA0(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA1(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA2(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA3(0x0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA4(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA5(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA6(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA7(0x0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA8(0xf0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA9(0xf0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA10(0xf0)|
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA11(0xf0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA2);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA12(0xf0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA13(0xf0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA14(0xf0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA15(0xf0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA3);
+ } else if(proc_data->quant_bit < 4) {
+ pxp_sram_init(pxp, DITHER0_LUT, (u32)bit2_dither_data_8x8, 64);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA0(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA1(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA2(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA3(0x0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA4(0x50) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA5(0x50) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA6(0x50) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA7(0x50),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA8(0xa0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA9(0xa0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA10(0xa0)|
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA11(0xa0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA2);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA12(0xf0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA13(0xf0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA14(0xf0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA15(0xf0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA3);
+ } else {
+ pxp_sram_init(pxp, DITHER0_LUT, (u32)bit4_dither_data_8x8, 64);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA0(0x0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA1(0x10) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA2(0x20) |
+ BF_PXP_DITHER_FINAL_LUT_DATA0_DATA3(0x30),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA0);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA4(0x40) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA5(0x50) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA6(0x60) |
+ BF_PXP_DITHER_FINAL_LUT_DATA1_DATA7(0x70),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA1);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA8(0x80) |
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA9(0x90) |
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA10(0xa0)|
+ BF_PXP_DITHER_FINAL_LUT_DATA2_DATA11(0xb0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA2);
+
+ __raw_writel(
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA12(0xc0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA13(0xd0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA14(0xe0) |
+ BF_PXP_DITHER_FINAL_LUT_DATA3_DATA15(0xf0),
+ pxp->base + HW_PXP_DITHER_FINAL_LUT_DATA3);
+ }
+}
+
+static void pxp_dithering_process(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ u32 val = 0;
+
+ if (pxp->devdata && pxp->devdata->pxp_dithering_configure)
+ pxp->devdata->pxp_dithering_configure(pxp);
+
+ if (pxp_is_v3(pxp))
+ val = BF_PXP_DITHER_CTRL_ENABLE0 (1) |
+ BF_PXP_DITHER_CTRL_ENABLE1 (0) |
+ BF_PXP_DITHER_CTRL_ENABLE2 (0) |
+ BF_PXP_DITHER_CTRL_DITHER_MODE2 (0) |
+ BF_PXP_DITHER_CTRL_DITHER_MODE1 (0) |
+ BF_PXP_DITHER_CTRL_DITHER_MODE0(proc_data->dither_mode) |
+ BF_PXP_DITHER_CTRL_LUT_MODE (0) |
+ BF_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE (1) |
+ BF_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE (0) |
+ BF_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE (0) |
+ BF_PXP_DITHER_CTRL_BUSY2 (0) |
+ BF_PXP_DITHER_CTRL_BUSY1 (0) |
+ BF_PXP_DITHER_CTRL_BUSY0 (0);
+ else if (pxp_is_v3p(pxp)) {
+ if (proc_data->dither_mode != 0 &&
+ proc_data->dither_mode != 3) {
+ dev_err(pxp->dev, "Not supported dithering mode. "
+ "Forced to be Orderred mode!\n");
+ proc_data->dither_mode = 3;
+ }
+
+ val = BF_PXP_DITHER_CTRL_ENABLE0 (1) |
+ BF_PXP_DITHER_CTRL_ENABLE1 (1) |
+ BF_PXP_DITHER_CTRL_ENABLE2 (1) |
+ BF_PXP_DITHER_CTRL_DITHER_MODE2(proc_data->dither_mode) |
+ BF_PXP_DITHER_CTRL_DITHER_MODE1(proc_data->dither_mode) |
+ BF_PXP_DITHER_CTRL_DITHER_MODE0(proc_data->dither_mode) |
+ BF_PXP_DITHER_CTRL_LUT_MODE (0) |
+ BF_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE (1) |
+ BF_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE (1) |
+ BF_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE (1) |
+ BF_PXP_DITHER_CTRL_FINAL_LUT_ENABLE (0) |
+ BF_PXP_DITHER_CTRL_BUSY2 (0) |
+ BF_PXP_DITHER_CTRL_BUSY1 (0) |
+ BF_PXP_DITHER_CTRL_BUSY0 (0);
+ }
+ __raw_writel(val, pxp->base + HW_PXP_DITHER_CTRL);
+
+ switch(proc_data->dither_mode) {
+ case PXP_DITHER_PASS_THROUGH:
+ /* no more settings required */
+ break;
+ case PXP_DITHER_FLOYD:
+ case PXP_DITHER_ATKINSON:
+ case PXP_DITHER_ORDERED:
+ if(!proc_data->quant_bit || proc_data->quant_bit > 7) {
+ dev_err(pxp->dev, "unsupported quantization bit number!\n");
+ return;
+ }
+ __raw_writel(
+ BF_PXP_DITHER_CTRL_FINAL_LUT_ENABLE(1) |
+ BF_PXP_DITHER_CTRL_NUM_QUANT_BIT(proc_data->quant_bit),
+ pxp->base + HW_PXP_DITHER_CTRL_SET);
+ pxp_set_final_lut_data(pxp);
+
+ break;
+ case PXP_DITHER_QUANT_ONLY:
+ if(!proc_data->quant_bit || proc_data->quant_bit > 7) {
+ dev_err(pxp->dev, "unsupported quantization bit number!\n");
+ return;
+ }
+ __raw_writel(
+ BF_PXP_DITHER_CTRL_NUM_QUANT_BIT(proc_data->quant_bit),
+ pxp->base + HW_PXP_DITHER_CTRL_SET);
+ break;
+ default:
+ /* unknown mode */
+ dev_err(pxp->dev, "unknown dithering mode passed!\n");
+ __raw_writel(0x0, pxp->base + HW_PXP_DITHER_CTRL);
+ return;
+ }
+}
+
+static void pxp_dithering_configure(struct pxps *pxp)
+{
+ dither_prefetch_config(pxp);
+ dither_store_config(pxp);
+}
+
+static void pxp_dithering_configure_v3p(struct pxps *pxp)
+{
+ struct pxp_config_data *config_data = &pxp->pxp_conf_state;
+ struct pxp_layer_param *fetch_ch0 = &config_data->dither_fetch_param[0];
+ struct pxp_layer_param *store_ch0 = &config_data->dither_store_param[0];
+
+ __raw_writel(BF_PXP_CTRL_BLOCK_SIZE(BV_PXP_CTRL_BLOCK_SIZE__8X8) |
+ BF_PXP_CTRL_ROTATE0(BV_PXP_CTRL_ROTATE0__ROT_0) |
+ BM_PXP_CTRL_IRQ_ENABLE,
+ pxp->base + HW_PXP_CTRL);
+
+ __raw_writel(BF_PXP_PS_CTRL_DECX(BV_PXP_PS_CTRL_DECX__DISABLE) |
+ BF_PXP_PS_CTRL_DECY(BV_PXP_PS_CTRL_DECY__DISABLE) |
+ BF_PXP_PS_CTRL_FORMAT(BV_PXP_PS_CTRL_FORMAT__Y8),
+ pxp->base + HW_PXP_PS_CTRL);
+
+ __raw_writel(BF_PXP_OUT_CTRL_FORMAT(BV_PXP_OUT_CTRL_FORMAT__Y8),
+ pxp->base + HW_PXP_OUT_CTRL);
+
+ __raw_writel(BF_PXP_PS_SCALE_YSCALE(4096) |
+ BF_PXP_PS_SCALE_XSCALE(4096),
+ pxp->base + HW_PXP_PS_SCALE);
+
+ __raw_writel(store_ch0->paddr, pxp->base + HW_PXP_OUT_BUF);
+
+ __raw_writel(store_ch0->stride, pxp->base + HW_PXP_OUT_PITCH);
+
+ __raw_writel(BF_PXP_OUT_LRC_X(store_ch0->width - 1) |
+ BF_PXP_OUT_LRC_Y(store_ch0->height - 1),
+ pxp->base + HW_PXP_OUT_LRC);
+
+ __raw_writel(BF_PXP_OUT_AS_ULC_X(1) |
+ BF_PXP_OUT_AS_ULC_Y(1),
+ pxp->base + HW_PXP_OUT_AS_ULC);
+
+ __raw_writel(BF_PXP_OUT_AS_LRC_X(0) |
+ BF_PXP_OUT_AS_LRC_Y(0),
+ pxp->base + HW_PXP_OUT_AS_LRC);
+
+ __raw_writel(BF_PXP_OUT_PS_ULC_X(0) |
+ BF_PXP_OUT_PS_ULC_Y(0),
+ pxp->base + HW_PXP_OUT_PS_ULC);
+
+ __raw_writel(BF_PXP_OUT_PS_LRC_X(fetch_ch0->width - 1) |
+ BF_PXP_OUT_PS_LRC_Y(fetch_ch0->height - 1),
+ pxp->base + HW_PXP_OUT_PS_LRC);
+
+ __raw_writel(fetch_ch0->paddr, pxp->base + HW_PXP_PS_BUF);
+
+ __raw_writel(fetch_ch0->stride, pxp->base + HW_PXP_PS_PITCH);
+
+ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
+
+ __raw_writel(BF_PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH(store_ch0->width-1)|
+ BF_PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT(store_ch0->height-1),
+ pxp->base + HW_PXP_DITHER_STORE_SIZE_CH0);
+
+ __raw_writel(BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1),
+ pxp->base + HW_PXP_DATA_PATH_CTRL0_CLR);
+}
+
+static void pxp_start2(struct pxps *pxp)
+{
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ int dither_wfe_a_handshake = 0;
+ int wfe_a_b_handshake = 0;
+ int count = 0;
+
+ int wfe_a_enable = ((proc_data->engine_enable & PXP_ENABLE_WFE_A) == PXP_ENABLE_WFE_A);
+ int wfe_b_enable = ((proc_data->engine_enable & PXP_ENABLE_WFE_B) == PXP_ENABLE_WFE_B);
+ int dither_enable = ((proc_data->engine_enable & PXP_ENABLE_DITHER) == PXP_ENABLE_DITHER);
+ int handshake = ((proc_data->engine_enable & PXP_ENABLE_HANDSHAKE) == PXP_ENABLE_HANDSHAKE);
+ int dither_bypass = ((proc_data->engine_enable & PXP_ENABLE_DITHER_BYPASS) == PXP_ENABLE_DITHER_BYPASS);
+ u32 val = 0;
+
+ if (dither_enable)
+ count++;
+ if (wfe_a_enable)
+ count++;
+ if (wfe_b_enable)
+ count++;
+
+ if (count == 0)
+ return;
+ if (handshake && (count == 1)) {
+ dev_warn(pxp->dev, "Warning: Can not use handshake mode when "
+ "only one sub-block is enabled!\n");
+ handshake = 0;
+ }
+
+ if (handshake && wfe_b_enable && (wfe_a_enable == 0)) {
+ dev_err(pxp->dev, "WFE_B only works when WFE_A is enabled!\n");
+ return;
+ }
+
+ if (handshake && dither_enable && wfe_a_enable)
+ dither_wfe_a_handshake = 1;
+ if (handshake && wfe_a_enable && wfe_b_enable)
+ wfe_a_b_handshake = 1;
+
+ dev_dbg(pxp->dev, "handshake %d, dither_wfe_a_handshake %d, "
+ "wfe_a_b_handshake %d, dither_bypass %d\n",
+ handshake,
+ dither_wfe_a_handshake,
+ wfe_a_b_handshake,
+ dither_bypass);
+
+ if (handshake) {
+ /* for handshake, we only enable the last completion INT */
+ if (wfe_b_enable)
+ __raw_writel(0x8000, pxp->base + HW_PXP_IRQ_MASK);
+ else if (wfe_a_enable)
+ __raw_writel(0x4000, pxp->base + HW_PXP_IRQ_MASK);
+
+ /* Dither fetch */
+ __raw_writel(
+ BF_PXP_DITHER_FETCH_CTRL_CH0_CH_EN(1) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_BYPASS_PIXEL_EN(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_HFLIP(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_VFLIP(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES(32) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM(0) |
+ BF_PXP_DITHER_FETCH_CTRL_CH0_ARBIT_EN(0),
+ pxp->base + HW_PXP_DITHER_FETCH_CTRL_CH0);
+
+ if (dither_bypass) {
+ /* Dither store */
+ __raw_writel(
+ BF_PXP_DITHER_STORE_CTRL_CH0_CH_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_BLOCK_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_HANDSHAKE_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARRAY_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_STORE_BYPASS_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_STORE_MEMORY_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_PACK_IN_SEL(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_FILL_DATA_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES(32)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL(0) |
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN(0),
+ pxp->base + HW_PXP_DITHER_STORE_CTRL_CH0);
+
+ /* WFE_A fetch */
+ __raw_writel(
+ BF_PXP_WFA_FETCH_CTRL_BF1_EN(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_HSK_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BYTES_PP(2) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_SRAM_IF(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BURST_LEN(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BYPASS_MODE(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_EN(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_HSK_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BYTES_PP(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_SRAM_IF(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BURST_LEN(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BYPASS_MODE(0),
+ pxp->base + HW_PXP_WFA_FETCH_CTRL);
+
+ } else if (dither_wfe_a_handshake) {
+ /* Dither store */
+ __raw_writel(
+ BF_PXP_DITHER_STORE_CTRL_CH0_CH_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_BLOCK_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_BLOCK_16(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_HANDSHAKE_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARRAY_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_STORE_BYPASS_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_STORE_MEMORY_EN(1)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_PACK_IN_SEL(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_FILL_DATA_EN(0)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES(32)|
+ BF_PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL(0) |
+ BF_PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN(0),
+ pxp->base + HW_PXP_DITHER_STORE_CTRL_CH0);
+
+ /* WFE_A fetch */
+ __raw_writel(
+ BF_PXP_WFA_FETCH_CTRL_BF1_EN(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_HSK_MODE(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BYTES_PP(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_SRAM_IF(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BURST_LEN(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF1_BYPASS_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_EN(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_HSK_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BYTES_PP(1) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_SRAM_IF(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BURST_LEN(0) |
+ BF_PXP_WFA_FETCH_CTRL_BF2_BYPASS_MODE(0),
+ pxp->base + HW_PXP_WFA_FETCH_CTRL);
+ }
+
+ if (wfe_a_b_handshake) {
+ /* WFE_A Store */
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_CTRL_CH1_CH_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_16(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_HANDSHAKE_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES(16),
+ pxp->base + HW_PXP_WFE_A_STORE_CTRL_CH1);
+
+ /* WFE_B fetch */
+ __raw_writel(
+ BF_PXP_WFB_FETCH_CTRL_BF1_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_EN(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN(0) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE(1) |
+ BF_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE(0),
+ pxp->base + HW_PXP_WFB_FETCH_CTRL);
+ } else {
+ /* WFE_A Store */
+ __raw_writel(
+ BF_PXP_WFE_A_STORE_CTRL_CH1_CH_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_16(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_HANDSHAKE_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_STORE_BYPASS_EN(0)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL(1)|
+ BF_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES(16),
+ pxp->base + HW_PXP_WFE_A_STORE_CTRL_CH1);
+ }
+
+ if (pxp_is_v3(pxp))
+ val = BF_PXP_CTRL_ENABLE_WFE_A(wfe_a_enable) |
+ BF_PXP_CTRL_ENABLE_WFE_B(wfe_b_enable);
+ else if (pxp_is_v3p(pxp))
+ val = BF_PXP_CTRL_ENABLE_WFE_B(wfe_a_enable |
+ wfe_b_enable);
+
+ /* trigger operation */
+ __raw_writel(
+ BF_PXP_CTRL_ENABLE(1) |
+ BF_PXP_CTRL_IRQ_ENABLE(0) |
+ BF_PXP_CTRL_NEXT_IRQ_ENABLE(0) |
+ BF_PXP_CTRL_LUT_DMA_IRQ_ENABLE(0) |
+ BF_PXP_CTRL_ENABLE_LCD0_HANDSHAKE(1) |
+ BF_PXP_CTRL_HANDSHAKE_ABORT_SKIP(1) |
+ BF_PXP_CTRL_ROTATE0(0) |
+ BF_PXP_CTRL_HFLIP0(0) |
+ BF_PXP_CTRL_VFLIP0(0) |
+ BF_PXP_CTRL_ROTATE1(0) |
+ BF_PXP_CTRL_HFLIP1(0) |
+ BF_PXP_CTRL_VFLIP1(0) |
+ BF_PXP_CTRL_ENABLE_PS_AS_OUT(0) |
+ BF_PXP_CTRL_ENABLE_DITHER(dither_enable) |
+ BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(0) |
+ BF_PXP_CTRL_ENABLE_ALPHA_B(0) |
+ BF_PXP_CTRL_BLOCK_SIZE(1) |
+ BF_PXP_CTRL_ENABLE_CSC2(0) |
+ BF_PXP_CTRL_ENABLE_LUT(1) |
+ BF_PXP_CTRL_ENABLE_ROTATE0(0) |
+ BF_PXP_CTRL_ENABLE_ROTATE1(0) |
+ BF_PXP_CTRL_EN_REPEAT(0) |
+ val,
+ pxp->base + HW_PXP_CTRL);
+
+ return;
+ }
+
+ if (pxp_is_v3(pxp))
+ val = BF_PXP_CTRL_ENABLE_WFE_A(wfe_a_enable) |
+ BF_PXP_CTRL_ENABLE_WFE_B(wfe_b_enable) |
+ BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(0) |
+ BF_PXP_CTRL_ENABLE_ALPHA_B(0);
+ else if (pxp_is_v3p(pxp))
+ val = BF_PXP_CTRL_ENABLE_WFE_B(wfe_a_enable |
+ wfe_b_enable);
+
+ __raw_writel(
+ BF_PXP_CTRL_ENABLE(1) |
+ BF_PXP_CTRL_IRQ_ENABLE(0) |
+ BF_PXP_CTRL_NEXT_IRQ_ENABLE(0) |
+ BF_PXP_CTRL_LUT_DMA_IRQ_ENABLE(0) |
+ BF_PXP_CTRL_ENABLE_LCD0_HANDSHAKE(0) |
+ BF_PXP_CTRL_ROTATE0(0) |
+ BF_PXP_CTRL_HFLIP0(0) |
+ BF_PXP_CTRL_VFLIP0(0) |
+ BF_PXP_CTRL_ROTATE1(0) |
+ BF_PXP_CTRL_HFLIP1(0) |
+ BF_PXP_CTRL_VFLIP1(0) |
+ BF_PXP_CTRL_ENABLE_PS_AS_OUT(0) |
+ BF_PXP_CTRL_ENABLE_DITHER(dither_enable) |
+ BF_PXP_CTRL_BLOCK_SIZE(0) |
+ BF_PXP_CTRL_ENABLE_CSC2(0) |
+ BF_PXP_CTRL_ENABLE_LUT(0) |
+ BF_PXP_CTRL_ENABLE_ROTATE0(0) |
+ BF_PXP_CTRL_ENABLE_ROTATE1(0) |
+ BF_PXP_CTRL_EN_REPEAT(0) |
+ val,
+ pxp->base + HW_PXP_CTRL);
+
+ if (pxp_is_v3(pxp))
+ val = BF_PXP_CTRL2_ENABLE_WFE_A (0) |
+ BF_PXP_CTRL2_ENABLE_WFE_B (0) |
+ BF_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE (0) |
+ BF_PXP_CTRL2_ENABLE_ALPHA_B (0);
+ else if (pxp_is_v3p(pxp))
+ val = BF_PXP_CTRL2_ENABLE_WFE_B(0);
+
+ __raw_writel(
+ BF_PXP_CTRL2_ENABLE (0) |
+ BF_PXP_CTRL2_ROTATE0 (0) |
+ BF_PXP_CTRL2_HFLIP0 (0) |
+ BF_PXP_CTRL2_VFLIP0 (0) |
+ BF_PXP_CTRL2_ROTATE1 (0) |
+ BF_PXP_CTRL2_HFLIP1 (0) |
+ BF_PXP_CTRL2_VFLIP1 (0) |
+ BF_PXP_CTRL2_ENABLE_DITHER (0) |
+ BF_PXP_CTRL2_BLOCK_SIZE (0) |
+ BF_PXP_CTRL2_ENABLE_CSC2 (0) |
+ BF_PXP_CTRL2_ENABLE_LUT (0) |
+ BF_PXP_CTRL2_ENABLE_ROTATE0 (0) |
+ BF_PXP_CTRL2_ENABLE_ROTATE1 (0),
+ pxp->base + HW_PXP_CTRL2);
+
+ dump_pxp_reg2(pxp);
+}
+
+static int pxp_dma_init(struct pxps *pxp)
+{
+ struct pxp_dma *pxp_dma = &pxp->pxp_dma;
+ struct dma_device *dma = &pxp_dma->dma;
+ int i;
+
+ dma_cap_set(DMA_SLAVE, dma->cap_mask);
+ dma_cap_set(DMA_PRIVATE, dma->cap_mask);
+
+ /* Compulsory common fields */
+ dma->dev = pxp->dev;
+ dma->device_alloc_chan_resources = pxp_alloc_chan_resources;
+ dma->device_free_chan_resources = pxp_free_chan_resources;
+ dma->device_tx_status = pxp_tx_status;
+ dma->device_issue_pending = pxp_issue_pending;
+
+ /* Compulsory for DMA_SLAVE fields */
+ dma->device_prep_slave_sg = pxp_prep_slave_sg;
+ dma->device_terminate_all = pxp_device_terminate_all;
+
+ /* Initialize PxP Channels */
+ INIT_LIST_HEAD(&dma->channels);
+ for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) {
+ struct pxp_channel *pxp_chan = pxp->channel + i;
+ struct dma_chan *dma_chan = &pxp_chan->dma_chan;
+
+ spin_lock_init(&pxp_chan->lock);
+
+ /* Only one EOF IRQ for PxP, shared by all channels */
+ pxp_chan->eof_irq = pxp->irq;
+ pxp_chan->status = PXP_CHANNEL_FREE;
+ pxp_chan->completed = -ENXIO;
+ snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name),
+ "PXP EOF %d", i);
+
+ dma_chan->device = &pxp_dma->dma;
+ dma_chan->cookie = 1;
+ dma_chan->chan_id = i;
+ list_add_tail(&dma_chan->device_node, &dma->channels);
+ }
+
+ return dma_async_device_register(&pxp_dma->dma);
+}
+
+static ssize_t clk_off_timeout_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", timeout_in_ms);
+}
+
+static ssize_t clk_off_timeout_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val;
+ if (sscanf(buf, "%d", &val) > 0) {
+ timeout_in_ms = val;
+ return count;
+ }
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show,
+ clk_off_timeout_store);
+
+static ssize_t block_size_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", block_size);
+}
+
+static ssize_t block_size_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char **last = NULL;
+
+ block_size = simple_strtoul(buf, last, 0);
+ if (block_size > 1)
+ block_size = 1;
+
+ return count;
+}
+static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO,
+ block_size_show, block_size_store);
+
+static struct platform_device_id imx_pxpdma_devtype[] = {
+ {
+ .name = "imx7d-pxp-dma",
+ .driver_data = PXP_V3,
+ }, {
+ .name = "imx6ull-pxp-dma",
+ .driver_data = PXP_V3P,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imx_pxpdma_devtype);
+
+static const struct of_device_id imx_pxpdma_dt_ids[] = {
+ { .compatible = "fsl,imx7d-pxp-dma", .data = &imx_pxpdma_devtype[0], },
+ { .compatible = "fsl,imx6ull-pxp-dma", .data = &imx_pxpdma_devtype[1], },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids);
+
+static int has_pending_task(struct pxps *pxp, struct pxp_channel *task)
+{
+ int found;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pxp->lock, flags);
+ found = !list_empty(&head);
+ spin_unlock_irqrestore(&pxp->lock, flags);
+
+ return found;
+}
+
+static int pxp_dispatch_thread(void *argv)
+{
+ struct pxps *pxp = (struct pxps *)argv;
+ struct pxp_channel *pending = NULL;
+ unsigned long flags;
+
+ set_freezable();
+
+ while (!kthread_should_stop()) {
+ int ret;
+ ret = wait_event_freezable(pxp->thread_waitq,
+ has_pending_task(pxp, pending) ||
+ kthread_should_stop());
+ if (ret < 0)
+ continue;
+
+ if (kthread_should_stop())
+ break;
+
+ spin_lock_irqsave(&pxp->lock, flags);
+ pxp->pxp_ongoing = 1;
+ spin_unlock_irqrestore(&pxp->lock, flags);
+ init_completion(&pxp->complete);
+ ret = pxpdma_dostart_work(pxp);
+ if (ret) {
+ pxp->pxp_ongoing = 0;
+ continue;
+ }
+ ret = wait_for_completion_timeout(&pxp->complete, 2 * HZ);
+ if (ret == 0) {
+ printk(KERN_EMERG "%s: task is timeout\n\n", __func__);
+ break;
+ }
+ if (pxp->devdata && pxp->devdata->pxp_lut_cleanup_multiple)
+ pxp->devdata->pxp_lut_cleanup_multiple(pxp, 0, 0);
+ }
+
+ return 0;
+}
+
+static int pxp_init_interrupt(struct platform_device *pdev)
+{
+ int legacy_irq, std_irq, err;
+ struct pxps *pxp = platform_get_drvdata(pdev);
+
+ legacy_irq = platform_get_irq(pdev, 0);
+ if (legacy_irq < 0) {
+ dev_err(&pdev->dev, "failed to get pxp legacy irq: %d\n",
+ legacy_irq);
+ return legacy_irq;
+ }
+
+ std_irq = platform_get_irq(pdev, 1);
+ if (std_irq < 0) {
+ dev_err(&pdev->dev, "failed to get pxp standard irq: %d\n",
+ std_irq);
+ return std_irq;
+ }
+
+ err = devm_request_irq(&pdev->dev, legacy_irq, pxp_irq, 0,
+ "pxp-dmaengine-legacy", pxp);
+ if (err) {
+ dev_err(&pdev->dev, "Request pxp legacy irq failed: %d\n", err);
+ return err;
+ }
+
+ err = devm_request_irq(&pdev->dev, std_irq, pxp_irq, 0,
+ "pxp-dmaengine-std", pxp);
+ if (err) {
+ dev_err(&pdev->dev, "Request pxp standard irq failed: %d\n", err);
+ return err;
+ }
+
+ pxp->irq = legacy_irq;
+
+ /* enable all the possible irq raised by PXP */
+ __raw_writel(0xffff, pxp->base + HW_PXP_IRQ_MASK);
+
+ return 0;
+}
+
+static int pxp_create_attrs(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ if ((ret = device_create_file(&pdev->dev, &dev_attr_clk_off_timeout))) {
+ dev_err(&pdev->dev,
+ "Unable to create file from clk_off_timeout\n");
+ return ret;
+ }
+
+ if ((ret = device_create_file(&pdev->dev, &dev_attr_block_size))) {
+ device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout);
+
+ dev_err(&pdev->dev,
+ "Unable to create file from block_size\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void pxp_remove_attrs(struct platform_device *pdev)
+{
+ device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout);
+ device_remove_file(&pdev->dev, &dev_attr_block_size);
+}
+
+static void pxp_init_timer(struct pxps *pxp)
+{
+ INIT_WORK(&pxp->work, clkoff_callback);
+
+ init_timer(&pxp->clk_timer);
+ pxp->clk_timer.function = pxp_clkoff_timer;
+ pxp->clk_timer.data = (unsigned long)pxp;
+}
+
+static bool is_mux_node(uint32_t node_id)
+{
+ if ((node_id < PXP_2D_MUX_MUX0) ||
+ (node_id > PXP_2D_MUX_MUX15))
+ return false;
+
+ return true;
+}
+
+static bool search_mux_chain(uint32_t mux_id,
+ struct edge_node *enode)
+{
+ bool found = false;
+ uint32_t i, j, next_mux = 0;
+ uint32_t output;
+ struct mux *muxes;
+
+ muxes = (v3p_flag) ? muxes_v3p : muxes_v3;
+
+ for (i = 0; i < 2; i++) {
+ output = muxes[mux_id].mux_outputs[i];
+ if (output == 0xff)
+ break;
+
+ if ((output == enode->adjvex)) {
+ /* found */
+ found = true;
+ break;
+ } else if (is_mux_node(output)) {
+ next_mux = output - PXP_2D_MUX_BASE;
+ found = search_mux_chain(next_mux, enode);
+
+ if (found) {
+ for (j = 0; j < 4; j++) {
+ if (muxes[next_mux].mux_inputs[j] ==
+ (mux_id + PXP_2D_MUX_BASE))
+ break;
+ }
+
+ set_bit(next_mux, (unsigned long *)&enode->mux_used);
+ set_mux_val(&enode->muxes, next_mux, j);
+ break;
+ }
+ }
+ }
+
+ return found;
+}
+
+static void enode_mux_config(unsigned int vnode_id,
+ struct edge_node *enode)
+{
+ uint32_t i, j;
+ bool via_mux = false, need_search = false;
+ struct mux *muxes;
+
+ BUG_ON(vnode_id >= PXP_2D_NUM);
+ BUG_ON(enode->adjvex >= PXP_2D_NUM);
+
+ muxes = (v3p_flag) ? muxes_v3p : muxes_v3;
+
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 4; j++) {
+ if (muxes[i].mux_inputs[j] == 0xff)
+ break;
+
+ if (muxes[i].mux_inputs[j] == vnode_id)
+ need_search = true;
+ else if (muxes[i].mux_inputs[j] == PXP_2D_ALPHA0_S0_S1) {
+ if ((vnode_id == PXP_2D_ALPHA0_S0) ||
+ (vnode_id == PXP_2D_ALPHA0_S1))
+ need_search = true;
+ } else if (muxes[i].mux_inputs[j] == PXP_2D_ALPHA1_S0_S1) {
+ if ((vnode_id == PXP_2D_ALPHA1_S0) ||
+ (vnode_id == PXP_2D_ALPHA1_S1))
+ need_search = true;
+ }
+
+ if (need_search) {
+ via_mux = search_mux_chain(i, enode);
+ need_search = false;
+ break;
+ }
+ }
+
+ if (via_mux) {
+ set_bit(i, (unsigned long *)&enode->mux_used);
+ set_mux_val(&enode->muxes, i, j);
+ break;
+ }
+ }
+}
+
+static int pxp_create_initial_graph(struct platform_device *pdev)
+{
+ int i, j, first;
+ static bool (*adj_array)[PXP_2D_NUM];
+ struct edge_node *enode, *curr = NULL;
+
+ adj_array = (v3p_flag) ? adj_array_v3p : adj_array_v3;
+
+ for (i = 0; i < PXP_2D_NUM; i++) {
+ switch (i) {
+ case PXP_2D_PS:
+ case PXP_2D_AS:
+ case PXP_2D_INPUT_FETCH0:
+ case PXP_2D_INPUT_FETCH1:
+ adj_list[i].type = PXP_2D_TYPE_INPUT;
+ break;
+ case PXP_2D_OUT:
+ case PXP_2D_INPUT_STORE0:
+ case PXP_2D_INPUT_STORE1:
+ adj_list[i].type = PXP_2D_TYPE_OUTPUT;
+ break;
+ default:
+ adj_list[i].type = PXP_2D_TYPE_ALU;
+ break;
+ }
+
+ first = -1;
+
+ for (j = 0; j < PXP_2D_NUM; j++) {
+ if (adj_array[i][j]) {
+ enode = kmem_cache_alloc(edge_node_cache,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!enode) {
+ dev_err(&pdev->dev, "allocate edge node failed\n");
+ return -ENOMEM;
+ }
+ enode->adjvex = j;
+ enode->prev_vnode = i;
+
+ if (unlikely(first == -1)) {
+ first = j;
+ adj_list[i].first = enode;
+ } else
+ curr->next = enode;
+
+ curr = enode;
+ enode_mux_config(i, enode);
+ dev_dbg(&pdev->dev, "(%d -> %d): mux_used 0x%x, mux_config 0x%x\n\n",
+ i, j, enode->mux_used, *(unsigned int*)&enode->muxes);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Calculate the shortest paths start via
+ * 'from' node to other nodes
+ */
+static void pxp_find_shortest_path(unsigned int from)
+{
+ int i;
+ struct edge_node *enode;
+ struct path_node *pnode, *adjnode;
+ struct list_head queue;
+
+ INIT_LIST_HEAD(&queue);
+ list_add_tail(&path_table[from][from].node, &queue);
+
+ while(!list_empty(&queue)) {
+ pnode = list_entry(queue.next, struct path_node, node);
+ enode = adj_list[pnode->id].first;
+ while (enode) {
+ adjnode = &path_table[from][enode->adjvex];
+
+ if (adjnode->distance == DISTANCE_INFINITY) {
+ adjnode->distance = pnode->distance + 1;
+ adjnode->prev_node = pnode->id;
+ list_add_tail(&adjnode->node, &queue);
+ }
+
+ enode = enode->next;
+ }
+ list_del_init(&pnode->node);
+ }
+
+ for (i = 0; i < PXP_2D_NUM; i++)
+ pr_debug("From %u: to %d (id = %d, distance = 0x%x, prev_node = %d\n",
+ from, i, path_table[from][i].id, path_table[from][i].distance,
+ path_table[from][i].prev_node);
+}
+
+static int pxp_gen_shortest_paths(struct platform_device *pdev)
+{
+ int i, j;
+
+ for (i = 0; i < PXP_2D_NUM; i++) {
+ for (j = 0; j < PXP_2D_NUM; j++) {
+ path_table[i][j].id = j;
+ path_table[i][j].distance = DISTANCE_INFINITY;
+ path_table[i][j].prev_node = NO_PATH_NODE;
+ INIT_LIST_HEAD(&path_table[i][j].node);
+ }
+
+ path_table[i][i].distance = 0;
+
+ pxp_find_shortest_path(i);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_MXC_FPGA_M4_TEST
+static void pxp_config_m4(struct platform_device *pdev)
+{
+ fpga_tcml_base = ioremap(FPGA_TCML_ADDR, SZ_32K);
+ if (fpga_tcml_base == NULL) {
+ dev_err(&pdev->dev,
+ "get fpga_tcml_base error.\n");
+ goto exit;
+ }
+ pinctrl_base = ioremap(PINCTRL, SZ_4K);
+ if (pinctrl_base == NULL) {
+ dev_err(&pdev->dev,
+ "get fpga_tcml_base error.\n");
+ goto exit;
+ }
+
+ __raw_writel(0xC0000000, pinctrl_base + 0x08);
+ __raw_writel(0x3, pinctrl_base + PIN_DOUT);
+ int i;
+ for (i = 0; i < 1024 * 32 / 4; i++) {
+ *(((unsigned int *)(fpga_tcml_base)) + i) = cm4_image[i];
+ }
+}
+#endif
+
+static int pxp_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *of_id =
+ of_match_device(imx_pxpdma_dt_ids, &pdev->dev);
+ struct pxps *pxp;
+ struct resource *res;
+ int err = 0;
+
+ if (of_id)
+ pdev->id_entry = of_id->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL);
+ if (!pxp) {
+ dev_err(&pdev->dev, "failed to allocate control object\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ pxp->dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, pxp);
+
+ spin_lock_init(&pxp->lock);
+ mutex_init(&pxp->clk_mutex);
+
+ pxp->base = devm_ioremap_resource(&pdev->dev, res);
+ if (pxp->base == NULL) {
+ dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+ err = -ENODEV;
+ goto exit;
+ }
+ pxp_reg_base = pxp->base;
+
+ pxp->pdev = pdev;
+ pxp->devdata = &pxp_devdata[pdev->id_entry->driver_data];
+
+ v3p_flag = (pxp_is_v3p(pxp)) ? true : false;
+
+ pxp->ipg_clk = devm_clk_get(&pdev->dev, "pxp_ipg");
+ pxp->axi_clk = devm_clk_get(&pdev->dev, "pxp_axi");
+
+ if (IS_ERR(pxp->ipg_clk) || IS_ERR(pxp->axi_clk)) {
+ dev_err(&pdev->dev, "pxp clocks invalid\n");
+ err = -EINVAL;
+ goto exit;
+ }
+
+ pxp_soft_reset(pxp);
+ pxp_writel(0x0, HW_PXP_CTRL);
+ /* Initialize DMA engine */
+ err = pxp_dma_init(pxp);
+ if (err < 0)
+ goto exit;
+
+ pxp_clk_enable(pxp);
+ pxp_soft_reset(pxp);
+
+ /* Initialize PXP Interrupt */
+ err = pxp_init_interrupt(pdev);
+ if (err < 0)
+ goto exit;
+
+ if (pxp->devdata && pxp->devdata->pxp_data_path_config)
+ pxp->devdata->pxp_data_path_config(pxp);
+
+ dump_pxp_reg(pxp);
+ pxp_clk_disable(pxp);
+
+ pxp_init_timer(pxp);
+
+ init_waitqueue_head(&pxp->thread_waitq);
+ /* allocate a kernel thread to dispatch pxp conf */
+ pxp->dispatch = kthread_run(pxp_dispatch_thread, pxp, "pxp_dispatch");
+ if (IS_ERR(pxp->dispatch)) {
+ err = PTR_ERR(pxp->dispatch);
+ goto exit;
+ }
+ tx_desc_cache = kmem_cache_create("tx_desc", sizeof(struct pxp_tx_desc),
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!tx_desc_cache) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ edge_node_cache = kmem_cache_create("edge_node", sizeof(struct edge_node),
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!edge_node_cache) {
+ err = -ENOMEM;
+ kmem_cache_destroy(tx_desc_cache);
+ goto exit;
+ }
+
+ err = pxp_create_attrs(pdev);
+ if (err) {
+ kmem_cache_destroy(tx_desc_cache);
+ kmem_cache_destroy(edge_node_cache);
+ goto exit;
+ }
+
+ if ((err = pxp_create_initial_graph(pdev))) {
+ kmem_cache_destroy(tx_desc_cache);
+ kmem_cache_destroy(edge_node_cache);
+ goto exit;
+ }
+
+ pxp_gen_shortest_paths(pdev);
+
+#ifdef CONFIG_MXC_FPGA_M4_TEST
+ pxp_config_m4(pdev);
+#endif
+ register_pxp_device();
+ pm_runtime_enable(pxp->dev);
+
+ dma_alloc_coherent(NULL, PAGE_ALIGN(1920 * 1088 * 4),
+ &paddr, GFP_KERNEL);
+
+exit:
+ if (err)
+ dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n");
+ return err;
+}
+
+static int pxp_remove(struct platform_device *pdev)
+{
+ struct pxps *pxp = platform_get_drvdata(pdev);
+
+ unregister_pxp_device();
+ kmem_cache_destroy(tx_desc_cache);
+ kmem_cache_destroy(edge_node_cache);
+ kthread_stop(pxp->dispatch);
+ cancel_work_sync(&pxp->work);
+ del_timer_sync(&pxp->clk_timer);
+ clk_disable_unprepare(pxp->ipg_clk);
+ clk_disable_unprepare(pxp->axi_clk);
+ pxp_remove_attrs(pdev);
+ dma_async_device_unregister(&(pxp->pxp_dma.dma));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pxp_suspend(struct device *dev)
+{
+ struct pxps *pxp = dev_get_drvdata(dev);
+
+ pxp_clk_enable(pxp);
+ while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
+ ;
+
+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
+ pxp_clk_disable(pxp);
+
+ return 0;
+}
+
+static int pxp_resume(struct device *dev)
+{
+ struct pxps *pxp = dev_get_drvdata(dev);
+
+ pxp_clk_enable(pxp);
+ /* Pull PxP out of reset */
+ pxp_soft_reset(pxp);
+ if (pxp->devdata && pxp->devdata->pxp_data_path_config)
+ pxp->devdata->pxp_data_path_config(pxp);
+ /* enable all the possible irq raised by PXP */
+ __raw_writel(0xffff, pxp->base + HW_PXP_IRQ_MASK);
+ pxp_clk_disable(pxp);
+
+ return 0;
+}
+#else
+#define pxp_suspend NULL
+#define pxp_resume NULL
+#endif
+
+#ifdef CONFIG_PM
+static int pxp_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pxp busfreq high release.\n");
+
+ return 0;
+}
+
+static int pxp_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pxp busfreq high request.\n");
+
+ return 0;
+}
+#else
+#define pxp_runtime_suspend NULL
+#define pxp_runtime_resume NULL
+#endif
+
+static const struct dev_pm_ops pxp_pm_ops = {
+ SET_RUNTIME_PM_OPS(pxp_runtime_suspend, pxp_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pxp_suspend, pxp_resume)
+};
+
+static struct platform_driver pxp_driver = {
+ .driver = {
+ .name = "imx-pxp-v3",
+ .of_match_table = of_match_ptr(imx_pxpdma_dt_ids),
+ .pm = &pxp_pm_ops,
+ },
+ .probe = pxp_probe,
+ .remove = pxp_remove,
+};
+
+static int __init pxp_init(void)
+{
+ return platform_driver_register(&pxp_driver);
+}
+late_initcall(pxp_init);
+
+static void __exit pxp_exit(void)
+{
+ platform_driver_unregister(&pxp_driver);
+}
+module_exit(pxp_exit);
+
+
+MODULE_DESCRIPTION("i.MX PxP driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/pxp/reg_bitfields.h b/drivers/dma/pxp/reg_bitfields.h
new file mode 100644
index 000000000000..95b5c83b4b15
--- /dev/null
+++ b/drivers/dma/pxp/reg_bitfields.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2010-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _REG_BITFIELDS_H
+#define _REG_BITFIELDS_H
+struct mux_config {
+ uint32_t mux0_sel : 2;
+ uint32_t mux1_sel : 2;
+ uint32_t mux2_sel : 2;
+ uint32_t mux3_sel : 2;
+ uint32_t mux4_sel : 2;
+ uint32_t mux5_sel : 2;
+ uint32_t mux6_sel : 2;
+ uint32_t mux7_sel : 2;
+ uint32_t mux8_sel : 2;
+ uint32_t mux9_sel : 2;
+ uint32_t mux10_sel : 2;
+ uint32_t mux11_sel : 2;
+ uint32_t mux12_sel : 2;
+ uint32_t mux13_sel : 2;
+ uint32_t mux14_sel : 2;
+ uint32_t mux15_sel : 2;
+};
+
+/* legacy engine registers */
+struct ps_ctrl {
+ uint32_t format : 6;
+ uint32_t wb_swap : 1;
+ uint32_t rsvd0 : 1;
+ uint32_t decy : 2;
+ uint32_t decx : 2;
+ uint32_t rsvd1 : 20;
+};
+
+struct ps_scale {
+ uint32_t xscale : 15;
+ uint32_t rsvd1 : 1;
+ uint32_t yscale : 15;
+ uint32_t rsvd2 : 1;
+};
+
+struct ps_offset {
+ uint32_t xoffset : 12;
+ uint32_t rsvd1 : 4;
+ uint32_t yoffset : 12;
+ uint32_t rsvd2 : 4;
+};
+
+struct as_ctrl {
+ uint32_t rsvd0 : 1;
+ uint32_t alpha_ctrl : 2;
+ uint32_t enable_colorkey : 1;
+ uint32_t format : 4;
+ uint32_t alpha : 8;
+ uint32_t rop : 4;
+ uint32_t alpha0_invert : 1;
+ uint32_t alpha1_invert : 1;
+ uint32_t rsvd1 : 10;
+};
+
+struct out_ctrl {
+ uint32_t format : 5;
+ uint32_t rsvd0 : 3;
+ uint32_t interlaced_output : 2;
+ uint32_t rsvd1 : 13;
+ uint32_t alpha_output : 1;
+ uint32_t alpha : 8;
+};
+
+struct coordinate {
+ uint32_t y : 14;
+ uint32_t rsvd0 : 2;
+ uint32_t x : 14;
+ uint32_t rsvd1 : 2;
+};
+
+struct pxp_alpha_ctrl {
+ uint32_t poter_duff_enable : 1;
+ uint32_t s0_s1_factor_mode : 2;
+ uint32_t s0_global_alpha_mode : 2;
+ uint32_t s0_alpha_mode : 1;
+ uint32_t s0_color_mode : 1;
+ uint32_t rsvd1 : 1;
+ uint32_t s1_s0_factor_mode : 2;
+ uint32_t s1_global_alpha_mode : 2;
+ uint32_t s1_alpha_mode : 1;
+ uint32_t s1_color_mode : 1;
+ uint32_t rsvd0 : 2;
+ uint32_t s0_global_alpha : 8;
+ uint32_t s1_global_alpha : 8;
+};
+
+/* store engine registers */
+struct store_ctrl {
+ uint32_t ch_en : 1;
+ uint32_t block_en : 1;
+ uint32_t block_16 : 1;
+ uint32_t handshake_en : 1;
+ uint32_t array_en : 1;
+ uint32_t array_line_num : 2;
+ uint32_t rsvd3 : 1;
+ uint32_t store_bypass_en : 1;
+ uint32_t store_memory_en : 1;
+ uint32_t pack_in_sel : 1;
+ uint32_t fill_data_en : 1;
+ uint32_t rsvd2 : 4;
+ uint32_t wr_num_bytes : 2;
+ uint32_t rsvd1 : 6;
+ uint32_t combine_2channel : 1;
+ uint32_t rsvd0 : 6;
+ uint32_t arbit_en : 1;
+};
+
+struct store_size {
+ uint32_t out_width : 16;
+ uint32_t out_height : 16;
+};
+
+struct store_pitch {
+ uint32_t ch0_out_pitch : 16;
+ uint32_t ch1_out_pitch : 16;
+};
+
+struct store_shift_ctrl {
+ uint32_t rsvd2 : 2;
+ uint32_t output_active_bpp : 2;
+ uint32_t out_yuv422_1p_en : 1;
+ uint32_t out_yuv422_2p_en : 1;
+ uint32_t rsvd1 : 1;
+ uint32_t shift_bypass : 1;
+ uint32_t rsvd0 : 24;
+};
+
+struct store_d_shift {
+ uint64_t d_shift_width0 : 6;
+ uint64_t rsvd3 : 1;
+ uint64_t d_shift_flag0 : 1;
+ uint64_t d_shift_width1 : 6;
+ uint64_t rsvd2 : 1;
+ uint64_t d_shift_flag1 : 1;
+ uint64_t d_shift_width2 : 6;
+ uint64_t rsvd1 : 1;
+ uint64_t d_shift_flag2 : 1;
+ uint64_t d_shift_width3 : 6;
+ uint64_t rsvd0 : 1;
+ uint64_t d_shift_flag3 : 1;
+
+ uint64_t d_shift_width4 : 6;
+ uint64_t rsvd7 : 1;
+ uint64_t d_shift_flag4 : 1;
+ uint64_t d_shift_width5 : 6;
+ uint64_t rsvd6 : 1;
+ uint64_t d_shift_flag5 : 1;
+ uint64_t d_shift_width6 : 6;
+ uint64_t rsvd5 : 1;
+ uint64_t d_shift_flag6 : 1;
+ uint64_t d_shift_width7 : 6;
+ uint64_t rsvd4 : 1;
+ uint64_t d_shift_flag7 : 1;
+};
+
+struct store_f_shift {
+ uint64_t f_shift_width0 : 6;
+ uint64_t rsvd3 : 1;
+ uint64_t f_shift_flag0 : 1;
+ uint64_t f_shift_width1 : 6;
+ uint64_t rsvd2 : 1;
+ uint64_t f_shift_flag1 : 1;
+ uint64_t f_shift_width2 : 6;
+ uint64_t rsvd1 : 1;
+ uint64_t f_shift_flag2 : 1;
+ uint64_t f_shift_width3 : 6;
+ uint64_t rsvd0 : 1;
+ uint64_t f_shift_flag3 : 1;
+
+ uint64_t f_shift_width4 : 6;
+ uint64_t rsvd7 : 1;
+ uint64_t f_shift_flag4 : 1;
+ uint64_t f_shift_width5 : 6;
+ uint64_t rsvd6 : 1;
+ uint64_t f_shift_flag5 : 1;
+ uint64_t f_shift_width6 : 6;
+ uint64_t rsvd5 : 1;
+ uint64_t f_shift_flag6 : 1;
+ uint64_t f_shift_width7 : 6;
+ uint64_t rsvd4 : 1;
+ uint64_t f_shift_flag7 : 1;
+};
+
+struct store_d_mask {
+ uint64_t d_mask_l : 32;
+ uint64_t d_mask_h : 32;
+};
+
+/* fetch engine registers */
+struct fetch_ctrl {
+ uint32_t ch_en : 1;
+ uint32_t block_en : 1;
+ uint32_t block_16 : 1;
+ uint32_t handshake_en : 1;
+ uint32_t bypass_pixel_en : 1;
+ uint32_t high_byte : 1;
+ uint32_t rsvd4 : 3;
+ uint32_t hflip : 1;
+ uint32_t vflip : 1;
+ uint32_t rsvd3 : 1;
+ uint32_t rotation_angle : 2;
+ uint32_t rsvd2 : 2;
+ uint32_t rd_num_bytes : 2;
+ uint32_t rsvd1 : 6;
+ uint32_t handshake_scan_line_num : 2;
+ uint32_t rsvd0 : 5;
+ uint32_t arbit_en : 1;
+};
+
+struct fetch_active_size_ulc {
+ uint32_t active_size_ulc_x : 16;
+ uint32_t active_size_ulc_y : 16;
+};
+
+struct fetch_active_size_lrc {
+ uint32_t active_size_lrc_x : 16;
+ uint32_t active_size_lrc_y : 16;
+};
+
+struct fetch_size {
+ uint32_t input_total_width : 16;
+ uint32_t input_total_height : 16;
+};
+
+struct fetch_pitch {
+ uint32_t ch0_input_pitch : 16;
+ uint32_t ch1_input_pitch : 16;
+};
+
+struct fetch_shift_ctrl {
+ uint32_t input_active_bpp : 2;
+ uint32_t rsvd1 : 6;
+ uint32_t expand_format : 3;
+ uint32_t expand_en : 1;
+ uint32_t shift_bypass : 1;
+ uint32_t rsvd0 : 19;
+};
+
+struct fetch_shift_offset {
+ uint32_t offset0 : 5;
+ uint32_t rsvd3 : 3;
+ uint32_t offset1 : 5;
+ uint32_t rsvd2 : 3;
+ uint32_t offset2 : 5;
+ uint32_t rsvd1 : 3;
+ uint32_t offset3 : 5;
+ uint32_t rsvd0 : 3;
+};
+
+struct fetch_shift_width {
+ uint32_t width0 : 4;
+ uint32_t width1 : 4;
+ uint32_t width2 : 4;
+ uint32_t width3 : 4;
+ uint32_t rsvd0 : 16;
+};
+#endif
diff --git a/drivers/dma/pxp/regs-pxp_v2.h b/drivers/dma/pxp/regs-pxp_v2.h
new file mode 100644
index 000000000000..8b20ddef3954
--- /dev/null
+++ b/drivers/dma/pxp/regs-pxp_v2.h
@@ -0,0 +1,1152 @@
+/*
+ * Freescale PXP Register Definitions
+ *
+ * Copyright (C) 2012-2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.29
+ * Template revision: 1.3
+ */
+
+#ifndef __ARCH_ARM___PXP_H
+#define __ARCH_ARM___PXP_H
+
+#define HW_PXP_CTRL (0x00000000)
+#define HW_PXP_CTRL_SET (0x00000004)
+#define HW_PXP_CTRL_CLR (0x00000008)
+#define HW_PXP_CTRL_TOG (0x0000000c)
+
+#define BM_PXP_CTRL_SFTRST 0x80000000
+#define BM_PXP_CTRL_CLKGATE 0x40000000
+#define BM_PXP_CTRL_RSVD4 0x20000000
+#define BM_PXP_CTRL_EN_REPEAT 0x10000000
+#define BP_PXP_CTRL_RSVD3 26
+#define BM_PXP_CTRL_RSVD3 0x0C000000
+#define BF_PXP_CTRL_RSVD3(v) \
+ (((v) << 26) & BM_PXP_CTRL_RSVD3)
+#define BP_PXP_CTRL_INTERLACED_INPUT 24
+#define BM_PXP_CTRL_INTERLACED_INPUT 0x03000000
+#define BF_PXP_CTRL_INTERLACED_INPUT(v) \
+ (((v) << 24) & BM_PXP_CTRL_INTERLACED_INPUT)
+#define BV_PXP_CTRL_INTERLACED_INPUT__PROGRESSIVE 0x0
+#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD0 0x2
+#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD1 0x3
+#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000
+#define BV_PXP_CTRL_BLOCK_SIZE__8X8 0x0
+#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1
+#define BM_PXP_CTRL_ROT_POS 0x00400000
+#define BM_PXP_CTRL_IN_PLACE 0x00200000
+#define BP_PXP_CTRL_RSVD1 12
+#define BM_PXP_CTRL_RSVD1 0x001FF000
+#define BF_PXP_CTRL_RSVD1(v) \
+ (((v) << 12) & BM_PXP_CTRL_RSVD1)
+#define BM_PXP_CTRL_VFLIP 0x00000800
+#define BM_PXP_CTRL_HFLIP 0x00000400
+#define BP_PXP_CTRL_ROTATE 8
+#define BM_PXP_CTRL_ROTATE 0x00000300
+#define BF_PXP_CTRL_ROTATE(v) \
+ (((v) << 8) & BM_PXP_CTRL_ROTATE)
+#define BV_PXP_CTRL_ROTATE__ROT_0 0x0
+#define BV_PXP_CTRL_ROTATE__ROT_90 0x1
+#define BV_PXP_CTRL_ROTATE__ROT_180 0x2
+#define BV_PXP_CTRL_ROTATE__ROT_270 0x3
+#define BP_PXP_CTRL_RSVD0 5
+#define BM_PXP_CTRL_RSVD0 0x000000E0
+#define BF_PXP_CTRL_RSVD0(v) \
+ (((v) << 5) & BM_PXP_CTRL_RSVD0)
+#define BM_PXP_CTRL_ENABLE_LCD_HANDSHAKE 0x00000010
+#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008
+#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004
+#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002
+#define BM_PXP_CTRL_ENABLE 0x00000001
+
+#define HW_PXP_STAT (0x00000010)
+#define HW_PXP_STAT_SET (0x00000014)
+#define HW_PXP_STAT_CLR (0x00000018)
+#define HW_PXP_STAT_TOG (0x0000001c)
+
+#define BP_PXP_STAT_BLOCKX 24
+#define BM_PXP_STAT_BLOCKX 0xFF000000
+#define BF_PXP_STAT_BLOCKX(v) \
+ (((v) << 24) & BM_PXP_STAT_BLOCKX)
+#define BP_PXP_STAT_BLOCKY 16
+#define BM_PXP_STAT_BLOCKY 0x00FF0000
+#define BF_PXP_STAT_BLOCKY(v) \
+ (((v) << 16) & BM_PXP_STAT_BLOCKY)
+#define BP_PXP_STAT_RSVD2 9
+#define BM_PXP_STAT_RSVD2 0x0000FE00
+#define BF_PXP_STAT_RSVD2(v) \
+ (((v) << 9) & BM_PXP_STAT_RSVD2)
+#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100
+#define BP_PXP_STAT_AXI_ERROR_ID 4
+#define BM_PXP_STAT_AXI_ERROR_ID 0x000000F0
+#define BF_PXP_STAT_AXI_ERROR_ID(v) \
+ (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID)
+#define BM_PXP_STAT_NEXT_IRQ 0x00000008
+#define BM_PXP_STAT_AXI_READ_ERROR 0x00000004
+#define BM_PXP_STAT_AXI_WRITE_ERROR 0x00000002
+#define BM_PXP_STAT_IRQ 0x00000001
+
+#define HW_PXP_OUT_CTRL (0x00000020)
+#define HW_PXP_OUT_CTRL_SET (0x00000024)
+#define HW_PXP_OUT_CTRL_CLR (0x00000028)
+#define HW_PXP_OUT_CTRL_TOG (0x0000002c)
+
+#define BP_PXP_OUT_CTRL_ALPHA 24
+#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000
+#define BF_PXP_OUT_CTRL_ALPHA(v) \
+ (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA)
+#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000
+#define BP_PXP_OUT_CTRL_RSVD1 10
+#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00
+#define BF_PXP_OUT_CTRL_RSVD1(v) \
+ (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1)
+#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT 8
+#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300
+#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v) \
+ (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT)
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0 0x1
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1 0x2
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED 0x3
+#define BP_PXP_OUT_CTRL_RSVD0 5
+#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0
+#define BF_PXP_OUT_CTRL_RSVD0(v) \
+ (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0)
+#define BP_PXP_OUT_CTRL_FORMAT 0
+#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F
+#define BF_PXP_OUT_CTRL_FORMAT(v) \
+ (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT)
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888 0x0
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888P 0x5
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555 0x8
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444 0x9
+#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE
+#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10
+#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_OUT_CTRL_FORMAT__Y8 0x14
+#define BV_PXP_OUT_CTRL_FORMAT__Y4 0x15
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422 0x18
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420 0x19
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422 0x1A
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420 0x1B
+
+#define HW_PXP_OUT_BUF (0x00000030)
+
+#define BP_PXP_OUT_BUF_ADDR 0
+#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF_ADDR(v) (v)
+
+#define HW_PXP_OUT_BUF2 (0x00000040)
+
+#define BP_PXP_OUT_BUF2_ADDR 0
+#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF2_ADDR(v) (v)
+
+#define HW_PXP_OUT_PITCH (0x00000050)
+
+#define BP_PXP_OUT_PITCH_RSVD 16
+#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_OUT_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_OUT_PITCH_RSVD)
+#define BP_PXP_OUT_PITCH_PITCH 0
+#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_OUT_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_OUT_PITCH_PITCH)
+
+#define HW_PXP_OUT_LRC (0x00000060)
+
+#define BP_PXP_OUT_LRC_RSVD1 30
+#define BM_PXP_OUT_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_LRC_RSVD1)
+#define BP_PXP_OUT_LRC_X 16
+#define BM_PXP_OUT_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_LRC_X)
+#define BP_PXP_OUT_LRC_RSVD0 14
+#define BM_PXP_OUT_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_LRC_RSVD0)
+#define BP_PXP_OUT_LRC_Y 0
+#define BM_PXP_OUT_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_LRC_Y)
+
+#define HW_PXP_OUT_PS_ULC (0x00000070)
+
+#define BP_PXP_OUT_PS_ULC_RSVD1 30
+#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_ULC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1)
+#define BP_PXP_OUT_PS_ULC_X 16
+#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_ULC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_PS_ULC_X)
+#define BP_PXP_OUT_PS_ULC_RSVD0 14
+#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_ULC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0)
+#define BP_PXP_OUT_PS_ULC_Y 0
+#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_ULC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_PS_ULC_Y)
+
+#define HW_PXP_OUT_PS_LRC (0x00000080)
+
+#define BP_PXP_OUT_PS_LRC_RSVD1 30
+#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1)
+#define BP_PXP_OUT_PS_LRC_X 16
+#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_PS_LRC_X)
+#define BP_PXP_OUT_PS_LRC_RSVD0 14
+#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0)
+#define BP_PXP_OUT_PS_LRC_Y 0
+#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_PS_LRC_Y)
+
+#define HW_PXP_OUT_AS_ULC (0x00000090)
+
+#define BP_PXP_OUT_AS_ULC_RSVD1 30
+#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_ULC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1)
+#define BP_PXP_OUT_AS_ULC_X 16
+#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_ULC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_AS_ULC_X)
+#define BP_PXP_OUT_AS_ULC_RSVD0 14
+#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_ULC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0)
+#define BP_PXP_OUT_AS_ULC_Y 0
+#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_ULC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_AS_ULC_Y)
+
+#define HW_PXP_OUT_AS_LRC (0x000000a0)
+
+#define BP_PXP_OUT_AS_LRC_RSVD1 30
+#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1)
+#define BP_PXP_OUT_AS_LRC_X 16
+#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_AS_LRC_X)
+#define BP_PXP_OUT_AS_LRC_RSVD0 14
+#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0)
+#define BP_PXP_OUT_AS_LRC_Y 0
+#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_AS_LRC_Y)
+
+#define HW_PXP_PS_CTRL (0x000000b0)
+#define HW_PXP_PS_CTRL_SET (0x000000b4)
+#define HW_PXP_PS_CTRL_CLR (0x000000b8)
+#define HW_PXP_PS_CTRL_TOG (0x000000bc)
+
+#define BP_PXP_PS_CTRL_RSVD1 12
+#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000
+#define BF_PXP_PS_CTRL_RSVD1(v) \
+ (((v) << 12) & BM_PXP_PS_CTRL_RSVD1)
+#define BP_PXP_PS_CTRL_DECX 10
+#define BM_PXP_PS_CTRL_DECX 0x00000C00
+#define BF_PXP_PS_CTRL_DECX(v) \
+ (((v) << 10) & BM_PXP_PS_CTRL_DECX)
+#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECX__DECX2 0x1
+#define BV_PXP_PS_CTRL_DECX__DECX4 0x2
+#define BV_PXP_PS_CTRL_DECX__DECX8 0x3
+#define BP_PXP_PS_CTRL_DECY 8
+#define BM_PXP_PS_CTRL_DECY 0x00000300
+#define BF_PXP_PS_CTRL_DECY(v) \
+ (((v) << 8) & BM_PXP_PS_CTRL_DECY)
+#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECY__DECY2 0x1
+#define BV_PXP_PS_CTRL_DECY__DECY4 0x2
+#define BV_PXP_PS_CTRL_DECY__DECY8 0x3
+#define BP_PXP_PS_CTRL_SWAP 5
+#define BM_PXP_PS_CTRL_SWAP 0x000000E0
+#define BF_PXP_PS_CTRL_SWAP(v) \
+ (((v) << 5) & BM_PXP_PS_CTRL_SWAP)
+#define BP_PXP_PS_CTRL_FORMAT 0
+#define BM_PXP_PS_CTRL_FORMAT 0x0000001F
+#define BF_PXP_PS_CTRL_FORMAT(v) \
+ (((v) << 0) & BM_PXP_PS_CTRL_FORMAT)
+#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_PS_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_PS_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE
+#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10
+#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_PS_CTRL_FORMAT__Y8 0x14
+#define BV_PXP_PS_CTRL_FORMAT__Y4 0x15
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P422 0x18
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P420 0x19
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P422 0x1A
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P420 0x1B
+#define BV_PXP_PS_CTRL_FORMAT__YUV422 0x1E
+#define BV_PXP_PS_CTRL_FORMAT__YUV420 0x1F
+
+#define HW_PXP_PS_BUF (0x000000c0)
+
+#define BP_PXP_PS_BUF_ADDR 0
+#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_BUF_ADDR(v) (v)
+
+#define HW_PXP_PS_UBUF (0x000000d0)
+
+#define BP_PXP_PS_UBUF_ADDR 0
+#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_UBUF_ADDR(v) (v)
+
+#define HW_PXP_PS_VBUF (0x000000e0)
+
+#define BP_PXP_PS_VBUF_ADDR 0
+#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_VBUF_ADDR(v) (v)
+
+#define HW_PXP_PS_PITCH (0x000000f0)
+
+#define BP_PXP_PS_PITCH_RSVD 16
+#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_PS_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_PS_PITCH_RSVD)
+#define BP_PXP_PS_PITCH_PITCH 0
+#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_PS_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_PS_PITCH_PITCH)
+
+#define HW_PXP_PS_BACKGROUND (0x00000100)
+
+#define BP_PXP_PS_BACKGROUND_RSVD 24
+#define BM_PXP_PS_BACKGROUND_RSVD 0xFF000000
+#define BF_PXP_PS_BACKGROUND_RSVD(v) \
+ (((v) << 24) & BM_PXP_PS_BACKGROUND_RSVD)
+#define BP_PXP_PS_BACKGROUND_COLOR 0
+#define BM_PXP_PS_BACKGROUND_COLOR 0x00FFFFFF
+#define BF_PXP_PS_BACKGROUND_COLOR(v) \
+ (((v) << 0) & BM_PXP_PS_BACKGROUND_COLOR)
+
+#define HW_PXP_PS_SCALE (0x00000110)
+
+#define BM_PXP_PS_SCALE_RSVD2 0x80000000
+#define BP_PXP_PS_SCALE_YSCALE 16
+#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000
+#define BF_PXP_PS_SCALE_YSCALE(v) \
+ (((v) << 16) & BM_PXP_PS_SCALE_YSCALE)
+#define BM_PXP_PS_SCALE_RSVD1 0x00008000
+#define BP_PXP_PS_SCALE_XSCALE 0
+#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF
+#define BF_PXP_PS_SCALE_XSCALE(v) \
+ (((v) << 0) & BM_PXP_PS_SCALE_XSCALE)
+
+#define HW_PXP_PS_OFFSET (0x00000120)
+
+#define BP_PXP_PS_OFFSET_RSVD2 28
+#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000
+#define BF_PXP_PS_OFFSET_RSVD2(v) \
+ (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2)
+#define BP_PXP_PS_OFFSET_YOFFSET 16
+#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000
+#define BF_PXP_PS_OFFSET_YOFFSET(v) \
+ (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET)
+#define BP_PXP_PS_OFFSET_RSVD1 12
+#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000
+#define BF_PXP_PS_OFFSET_RSVD1(v) \
+ (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1)
+#define BP_PXP_PS_OFFSET_XOFFSET 0
+#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF
+#define BF_PXP_PS_OFFSET_XOFFSET(v) \
+ (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET)
+
+#define HW_PXP_PS_CLRKEYLOW (0x00000130)
+
+#define BP_PXP_PS_CLRKEYLOW_RSVD1 24
+#define BM_PXP_PS_CLRKEYLOW_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYLOW_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYLOW_RSVD1)
+#define BP_PXP_PS_CLRKEYLOW_PIXEL 0
+#define BM_PXP_PS_CLRKEYLOW_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYLOW_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYLOW_PIXEL)
+
+#define HW_PXP_PS_CLRKEYHIGH (0x00000140)
+
+#define BP_PXP_PS_CLRKEYHIGH_RSVD1 24
+#define BM_PXP_PS_CLRKEYHIGH_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYHIGH_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_RSVD1)
+#define BP_PXP_PS_CLRKEYHIGH_PIXEL 0
+#define BM_PXP_PS_CLRKEYHIGH_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYHIGH_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_PIXEL)
+
+#define HW_PXP_AS_CTRL (0x00000150)
+
+#define BP_PXP_AS_CTRL_RSVD1 21
+#define BM_PXP_AS_CTRL_RSVD1 0xFFE00000
+#define BF_PXP_AS_CTRL_RSVD1(v) \
+ (((v) << 21) & BM_PXP_AS_CTRL_RSVD1)
+#define BM_PXP_AS_CTRL_ALPHA_INVERT 0x00100000
+#define BP_PXP_AS_CTRL_ROP 16
+#define BM_PXP_AS_CTRL_ROP 0x000F0000
+#define BF_PXP_AS_CTRL_ROP(v) \
+ (((v) << 16) & BM_PXP_AS_CTRL_ROP)
+#define BV_PXP_AS_CTRL_ROP__MASKAS 0x0
+#define BV_PXP_AS_CTRL_ROP__MASKNOTAS 0x1
+#define BV_PXP_AS_CTRL_ROP__MASKASNOT 0x2
+#define BV_PXP_AS_CTRL_ROP__MERGEAS 0x3
+#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4
+#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5
+#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS 0x6
+#define BV_PXP_AS_CTRL_ROP__NOT 0x7
+#define BV_PXP_AS_CTRL_ROP__NOTMASKAS 0x8
+#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9
+#define BV_PXP_AS_CTRL_ROP__XORAS 0xA
+#define BV_PXP_AS_CTRL_ROP__NOTXORAS 0xB
+#define BP_PXP_AS_CTRL_ALPHA 8
+#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00
+#define BF_PXP_AS_CTRL_ALPHA(v) \
+ (((v) << 8) & BM_PXP_AS_CTRL_ALPHA)
+#define BP_PXP_AS_CTRL_FORMAT 4
+#define BM_PXP_AS_CTRL_FORMAT 0x000000F0
+#define BF_PXP_AS_CTRL_FORMAT(v) \
+ (((v) << 4) & BM_PXP_AS_CTRL_FORMAT)
+#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0
+#define BV_PXP_AS_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8
+#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9
+#define BV_PXP_AS_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_AS_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_AS_CTRL_FORMAT__RGB565 0xE
+#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008
+#define BP_PXP_AS_CTRL_ALPHA_CTRL 1
+#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006
+#define BF_PXP_AS_CTRL_ALPHA_CTRL(v) \
+ (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL)
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs 0x3
+#define BM_PXP_AS_CTRL_RSVD0 0x00000001
+
+#define HW_PXP_AS_BUF (0x00000160)
+
+#define BP_PXP_AS_BUF_ADDR 0
+#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_AS_BUF_ADDR(v) (v)
+
+#define HW_PXP_AS_PITCH (0x00000170)
+
+#define BP_PXP_AS_PITCH_RSVD 16
+#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_AS_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_AS_PITCH_RSVD)
+#define BP_PXP_AS_PITCH_PITCH 0
+#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_AS_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_AS_PITCH_PITCH)
+
+#define HW_PXP_AS_CLRKEYLOW (0x00000180)
+
+#define BP_PXP_AS_CLRKEYLOW_RSVD1 24
+#define BM_PXP_AS_CLRKEYLOW_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYLOW_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYLOW_RSVD1)
+#define BP_PXP_AS_CLRKEYLOW_PIXEL 0
+#define BM_PXP_AS_CLRKEYLOW_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYLOW_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYLOW_PIXEL)
+
+#define HW_PXP_AS_CLRKEYHIGH (0x00000190)
+
+#define BP_PXP_AS_CLRKEYHIGH_RSVD1 24
+#define BM_PXP_AS_CLRKEYHIGH_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYHIGH_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_RSVD1)
+#define BP_PXP_AS_CLRKEYHIGH_PIXEL 0
+#define BM_PXP_AS_CLRKEYHIGH_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYHIGH_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_PIXEL)
+
+#define HW_PXP_CSC1_COEF0 (0x000001a0)
+
+#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000
+#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000
+#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000
+#define BP_PXP_CSC1_COEF0_C0 18
+#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000
+#define BF_PXP_CSC1_COEF0_C0(v) \
+ (((v) << 18) & BM_PXP_CSC1_COEF0_C0)
+#define BP_PXP_CSC1_COEF0_UV_OFFSET 9
+#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00
+#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \
+ (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET)
+#define BP_PXP_CSC1_COEF0_Y_OFFSET 0
+#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF
+#define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET)
+
+#define HW_PXP_CSC1_COEF1 (0x000001b0)
+
+#define BP_PXP_CSC1_COEF1_RSVD1 27
+#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF1_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1)
+#define BP_PXP_CSC1_COEF1_C1 16
+#define BM_PXP_CSC1_COEF1_C1 0x07FF0000
+#define BF_PXP_CSC1_COEF1_C1(v) \
+ (((v) << 16) & BM_PXP_CSC1_COEF1_C1)
+#define BP_PXP_CSC1_COEF1_RSVD0 11
+#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF1_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0)
+#define BP_PXP_CSC1_COEF1_C4 0
+#define BM_PXP_CSC1_COEF1_C4 0x000007FF
+#define BF_PXP_CSC1_COEF1_C4(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF1_C4)
+
+#define HW_PXP_CSC1_COEF2 (0x000001c0)
+
+#define BP_PXP_CSC1_COEF2_RSVD1 27
+#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF2_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1)
+#define BP_PXP_CSC1_COEF2_C2 16
+#define BM_PXP_CSC1_COEF2_C2 0x07FF0000
+#define BF_PXP_CSC1_COEF2_C2(v) \
+ (((v) << 16) & BM_PXP_CSC1_COEF2_C2)
+#define BP_PXP_CSC1_COEF2_RSVD0 11
+#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF2_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0)
+#define BP_PXP_CSC1_COEF2_C3 0
+#define BM_PXP_CSC1_COEF2_C3 0x000007FF
+#define BF_PXP_CSC1_COEF2_C3(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF2_C3)
+
+#define HW_PXP_CSC2_CTRL (0x000001d0)
+
+#define BP_PXP_CSC2_CTRL_RSVD 3
+#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8
+#define BF_PXP_CSC2_CTRL_RSVD(v) \
+ (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD)
+#define BP_PXP_CSC2_CTRL_CSC_MODE 1
+#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006
+#define BF_PXP_CSC2_CTRL_CSC_MODE(v) \
+ (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE)
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB 0x0
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV 0x2
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3
+#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001
+
+#define HW_PXP_CSC2_COEF0 (0x000001e0)
+
+#define BP_PXP_CSC2_COEF0_RSVD1 27
+#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF0_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1)
+#define BP_PXP_CSC2_COEF0_A2 16
+#define BM_PXP_CSC2_COEF0_A2 0x07FF0000
+#define BF_PXP_CSC2_COEF0_A2(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF0_A2)
+#define BP_PXP_CSC2_COEF0_RSVD0 11
+#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF0_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0)
+#define BP_PXP_CSC2_COEF0_A1 0
+#define BM_PXP_CSC2_COEF0_A1 0x000007FF
+#define BF_PXP_CSC2_COEF0_A1(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF0_A1)
+
+#define HW_PXP_CSC2_COEF1 (0x000001f0)
+
+#define BP_PXP_CSC2_COEF1_RSVD1 27
+#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF1_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1)
+#define BP_PXP_CSC2_COEF1_B1 16
+#define BM_PXP_CSC2_COEF1_B1 0x07FF0000
+#define BF_PXP_CSC2_COEF1_B1(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF1_B1)
+#define BP_PXP_CSC2_COEF1_RSVD0 11
+#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF1_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0)
+#define BP_PXP_CSC2_COEF1_A3 0
+#define BM_PXP_CSC2_COEF1_A3 0x000007FF
+#define BF_PXP_CSC2_COEF1_A3(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF1_A3)
+
+#define HW_PXP_CSC2_COEF2 (0x00000200)
+
+#define BP_PXP_CSC2_COEF2_RSVD1 27
+#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF2_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1)
+#define BP_PXP_CSC2_COEF2_B3 16
+#define BM_PXP_CSC2_COEF2_B3 0x07FF0000
+#define BF_PXP_CSC2_COEF2_B3(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF2_B3)
+#define BP_PXP_CSC2_COEF2_RSVD0 11
+#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF2_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0)
+#define BP_PXP_CSC2_COEF2_B2 0
+#define BM_PXP_CSC2_COEF2_B2 0x000007FF
+#define BF_PXP_CSC2_COEF2_B2(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF2_B2)
+
+#define HW_PXP_CSC2_COEF3 (0x00000210)
+
+#define BP_PXP_CSC2_COEF3_RSVD1 27
+#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF3_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1)
+#define BP_PXP_CSC2_COEF3_C2 16
+#define BM_PXP_CSC2_COEF3_C2 0x07FF0000
+#define BF_PXP_CSC2_COEF3_C2(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF3_C2)
+#define BP_PXP_CSC2_COEF3_RSVD0 11
+#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF3_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0)
+#define BP_PXP_CSC2_COEF3_C1 0
+#define BM_PXP_CSC2_COEF3_C1 0x000007FF
+#define BF_PXP_CSC2_COEF3_C1(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF3_C1)
+
+#define HW_PXP_CSC2_COEF4 (0x00000220)
+
+#define BP_PXP_CSC2_COEF4_RSVD1 25
+#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF4_RSVD1(v) \
+ (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1)
+#define BP_PXP_CSC2_COEF4_D1 16
+#define BM_PXP_CSC2_COEF4_D1 0x01FF0000
+#define BF_PXP_CSC2_COEF4_D1(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF4_D1)
+#define BP_PXP_CSC2_COEF4_RSVD0 11
+#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF4_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0)
+#define BP_PXP_CSC2_COEF4_C3 0
+#define BM_PXP_CSC2_COEF4_C3 0x000007FF
+#define BF_PXP_CSC2_COEF4_C3(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF4_C3)
+
+#define HW_PXP_CSC2_COEF5 (0x00000230)
+
+#define BP_PXP_CSC2_COEF5_RSVD1 25
+#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF5_RSVD1(v) \
+ (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1)
+#define BP_PXP_CSC2_COEF5_D3 16
+#define BM_PXP_CSC2_COEF5_D3 0x01FF0000
+#define BF_PXP_CSC2_COEF5_D3(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF5_D3)
+#define BP_PXP_CSC2_COEF5_RSVD0 9
+#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00
+#define BF_PXP_CSC2_COEF5_RSVD0(v) \
+ (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0)
+#define BP_PXP_CSC2_COEF5_D2 0
+#define BM_PXP_CSC2_COEF5_D2 0x000001FF
+#define BF_PXP_CSC2_COEF5_D2(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF5_D2)
+
+#define HW_PXP_LUT_CTRL (0x00000240)
+
+#define BM_PXP_LUT_CTRL_BYPASS 0x80000000
+#define BP_PXP_LUT_CTRL_RSVD3 26
+#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000
+#define BF_PXP_LUT_CTRL_RSVD3(v) \
+ (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3)
+#define BP_PXP_LUT_CTRL_LOOKUP_MODE 24
+#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000
+#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \
+ (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE)
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565 0x0
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8 0x1
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3
+#define BP_PXP_LUT_CTRL_RSVD2 18
+#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000
+#define BF_PXP_LUT_CTRL_RSVD2(v) \
+ (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2)
+#define BP_PXP_LUT_CTRL_OUT_MODE 16
+#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000
+#define BF_PXP_LUT_CTRL_OUT_MODE(v) \
+ (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE)
+#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED 0x0
+#define BV_PXP_LUT_CTRL_OUT_MODE__Y8 0x1
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888 0x3
+#define BP_PXP_LUT_CTRL_RSVD1 11
+#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800
+#define BF_PXP_LUT_CTRL_RSVD1(v) \
+ (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1)
+#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400
+#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200
+#define BM_PXP_LUT_CTRL_INVALID 0x00000100
+#define BP_PXP_LUT_CTRL_RSVD0 1
+#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE
+#define BF_PXP_LUT_CTRL_RSVD0(v) \
+ (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0)
+#define BM_PXP_LUT_CTRL_DMA_START 0x00000001
+
+#define HW_PXP_LUT_ADDR (0x00000250)
+
+#define BM_PXP_LUT_ADDR_RSVD2 0x80000000
+#define BP_PXP_LUT_ADDR_NUM_BYTES 16
+#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000
+#define BF_PXP_LUT_ADDR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES)
+#define BP_PXP_LUT_ADDR_RSVD1 14
+#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000
+#define BF_PXP_LUT_ADDR_RSVD1(v) \
+ (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1)
+#define BP_PXP_LUT_ADDR_ADDR 0
+#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF
+#define BF_PXP_LUT_ADDR_ADDR(v) \
+ (((v) << 0) & BM_PXP_LUT_ADDR_ADDR)
+
+#define HW_PXP_LUT_DATA (0x00000260)
+
+#define BP_PXP_LUT_DATA_DATA 0
+#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF
+#define BF_PXP_LUT_DATA_DATA(v) (v)
+
+#define HW_PXP_LUT_EXTMEM (0x00000270)
+
+#define BP_PXP_LUT_EXTMEM_ADDR 0
+#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF
+#define BF_PXP_LUT_EXTMEM_ADDR(v) (v)
+
+#define HW_PXP_CFA (0x00000280)
+
+#define BP_PXP_CFA_DATA 0
+#define BM_PXP_CFA_DATA 0xFFFFFFFF
+#define BF_PXP_CFA_DATA(v) (v)
+
+#define HW_PXP_HIST_CTRL (0x00000290)
+
+#define BP_PXP_HIST_CTRL_RSVD 6
+#define BM_PXP_HIST_CTRL_RSVD 0xFFFFFFC0
+#define BF_PXP_HIST_CTRL_RSVD(v) \
+ (((v) << 6) & BM_PXP_HIST_CTRL_RSVD)
+#define BP_PXP_HIST_CTRL_PANEL_MODE 4
+#define BM_PXP_HIST_CTRL_PANEL_MODE 0x00000030
+#define BF_PXP_HIST_CTRL_PANEL_MODE(v) \
+ (((v) << 4) & BM_PXP_HIST_CTRL_PANEL_MODE)
+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY4 0x0
+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY8 0x1
+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16 0x2
+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY32 0x3
+#define BP_PXP_HIST_CTRL_STATUS 0
+#define BM_PXP_HIST_CTRL_STATUS 0x0000000F
+#define BF_PXP_HIST_CTRL_STATUS(v) \
+ (((v) << 0) & BM_PXP_HIST_CTRL_STATUS)
+
+#define HW_PXP_HIST2_PARAM (0x000002a0)
+
+#define BP_PXP_HIST2_PARAM_RSVD 16
+#define BM_PXP_HIST2_PARAM_RSVD 0xFFFF0000
+#define BF_PXP_HIST2_PARAM_RSVD(v) \
+ (((v) << 16) & BM_PXP_HIST2_PARAM_RSVD)
+#define BP_PXP_HIST2_PARAM_RSVD1 13
+#define BM_PXP_HIST2_PARAM_RSVD1 0x0000E000
+#define BF_PXP_HIST2_PARAM_RSVD1(v) \
+ (((v) << 13) & BM_PXP_HIST2_PARAM_RSVD1)
+#define BP_PXP_HIST2_PARAM_VALUE1 8
+#define BM_PXP_HIST2_PARAM_VALUE1 0x00001F00
+#define BF_PXP_HIST2_PARAM_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST2_PARAM_VALUE1)
+#define BP_PXP_HIST2_PARAM_RSVD0 5
+#define BM_PXP_HIST2_PARAM_RSVD0 0x000000E0
+#define BF_PXP_HIST2_PARAM_RSVD0(v) \
+ (((v) << 5) & BM_PXP_HIST2_PARAM_RSVD0)
+#define BP_PXP_HIST2_PARAM_VALUE0 0
+#define BM_PXP_HIST2_PARAM_VALUE0 0x0000001F
+#define BF_PXP_HIST2_PARAM_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST2_PARAM_VALUE0)
+
+#define HW_PXP_HIST4_PARAM (0x000002b0)
+
+#define BP_PXP_HIST4_PARAM_RSVD3 29
+#define BM_PXP_HIST4_PARAM_RSVD3 0xE0000000
+#define BF_PXP_HIST4_PARAM_RSVD3(v) \
+ (((v) << 29) & BM_PXP_HIST4_PARAM_RSVD3)
+#define BP_PXP_HIST4_PARAM_VALUE3 24
+#define BM_PXP_HIST4_PARAM_VALUE3 0x1F000000
+#define BF_PXP_HIST4_PARAM_VALUE3(v) \
+ (((v) << 24) & BM_PXP_HIST4_PARAM_VALUE3)
+#define BP_PXP_HIST4_PARAM_RSVD2 21
+#define BM_PXP_HIST4_PARAM_RSVD2 0x00E00000
+#define BF_PXP_HIST4_PARAM_RSVD2(v) \
+ (((v) << 21) & BM_PXP_HIST4_PARAM_RSVD2)
+#define BP_PXP_HIST4_PARAM_VALUE2 16
+#define BM_PXP_HIST4_PARAM_VALUE2 0x001F0000
+#define BF_PXP_HIST4_PARAM_VALUE2(v) \
+ (((v) << 16) & BM_PXP_HIST4_PARAM_VALUE2)
+#define BP_PXP_HIST4_PARAM_RSVD1 13
+#define BM_PXP_HIST4_PARAM_RSVD1 0x0000E000
+#define BF_PXP_HIST4_PARAM_RSVD1(v) \
+ (((v) << 13) & BM_PXP_HIST4_PARAM_RSVD1)
+#define BP_PXP_HIST4_PARAM_VALUE1 8
+#define BM_PXP_HIST4_PARAM_VALUE1 0x00001F00
+#define BF_PXP_HIST4_PARAM_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST4_PARAM_VALUE1)
+#define BP_PXP_HIST4_PARAM_RSVD0 5
+#define BM_PXP_HIST4_PARAM_RSVD0 0x000000E0
+#define BF_PXP_HIST4_PARAM_RSVD0(v) \
+ (((v) << 5) & BM_PXP_HIST4_PARAM_RSVD0)
+#define BP_PXP_HIST4_PARAM_VALUE0 0
+#define BM_PXP_HIST4_PARAM_VALUE0 0x0000001F
+#define BF_PXP_HIST4_PARAM_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST4_PARAM_VALUE0)
+
+#define HW_PXP_HIST8_PARAM0 (0x000002c0)
+
+#define BP_PXP_HIST8_PARAM0_RSVD3 29
+#define BM_PXP_HIST8_PARAM0_RSVD3 0xE0000000
+#define BF_PXP_HIST8_PARAM0_RSVD3(v) \
+ (((v) << 29) & BM_PXP_HIST8_PARAM0_RSVD3)
+#define BP_PXP_HIST8_PARAM0_VALUE3 24
+#define BM_PXP_HIST8_PARAM0_VALUE3 0x1F000000
+#define BF_PXP_HIST8_PARAM0_VALUE3(v) \
+ (((v) << 24) & BM_PXP_HIST8_PARAM0_VALUE3)
+#define BP_PXP_HIST8_PARAM0_RSVD2 21
+#define BM_PXP_HIST8_PARAM0_RSVD2 0x00E00000
+#define BF_PXP_HIST8_PARAM0_RSVD2(v) \
+ (((v) << 21) & BM_PXP_HIST8_PARAM0_RSVD2)
+#define BP_PXP_HIST8_PARAM0_VALUE2 16
+#define BM_PXP_HIST8_PARAM0_VALUE2 0x001F0000
+#define BF_PXP_HIST8_PARAM0_VALUE2(v) \
+ (((v) << 16) & BM_PXP_HIST8_PARAM0_VALUE2)
+#define BP_PXP_HIST8_PARAM0_RSVD1 13
+#define BM_PXP_HIST8_PARAM0_RSVD1 0x0000E000
+#define BF_PXP_HIST8_PARAM0_RSVD1(v) \
+ (((v) << 13) & BM_PXP_HIST8_PARAM0_RSVD1)
+#define BP_PXP_HIST8_PARAM0_VALUE1 8
+#define BM_PXP_HIST8_PARAM0_VALUE1 0x00001F00
+#define BF_PXP_HIST8_PARAM0_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST8_PARAM0_VALUE1)
+#define BP_PXP_HIST8_PARAM0_RSVD0 5
+#define BM_PXP_HIST8_PARAM0_RSVD0 0x000000E0
+#define BF_PXP_HIST8_PARAM0_RSVD0(v) \
+ (((v) << 5) & BM_PXP_HIST8_PARAM0_RSVD0)
+#define BP_PXP_HIST8_PARAM0_VALUE0 0
+#define BM_PXP_HIST8_PARAM0_VALUE0 0x0000001F
+#define BF_PXP_HIST8_PARAM0_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST8_PARAM0_VALUE0)
+
+#define HW_PXP_HIST8_PARAM1 (0x000002d0)
+
+#define BP_PXP_HIST8_PARAM1_RSVD7 29
+#define BM_PXP_HIST8_PARAM1_RSVD7 0xE0000000
+#define BF_PXP_HIST8_PARAM1_RSVD7(v) \
+ (((v) << 29) & BM_PXP_HIST8_PARAM1_RSVD7)
+#define BP_PXP_HIST8_PARAM1_VALUE7 24
+#define BM_PXP_HIST8_PARAM1_VALUE7 0x1F000000
+#define BF_PXP_HIST8_PARAM1_VALUE7(v) \
+ (((v) << 24) & BM_PXP_HIST8_PARAM1_VALUE7)
+#define BP_PXP_HIST8_PARAM1_RSVD6 21
+#define BM_PXP_HIST8_PARAM1_RSVD6 0x00E00000
+#define BF_PXP_HIST8_PARAM1_RSVD6(v) \
+ (((v) << 21) & BM_PXP_HIST8_PARAM1_RSVD6)
+#define BP_PXP_HIST8_PARAM1_VALUE6 16
+#define BM_PXP_HIST8_PARAM1_VALUE6 0x001F0000
+#define BF_PXP_HIST8_PARAM1_VALUE6(v) \
+ (((v) << 16) & BM_PXP_HIST8_PARAM1_VALUE6)
+#define BP_PXP_HIST8_PARAM1_RSVD5 13
+#define BM_PXP_HIST8_PARAM1_RSVD5 0x0000E000
+#define BF_PXP_HIST8_PARAM1_RSVD5(v) \
+ (((v) << 13) & BM_PXP_HIST8_PARAM1_RSVD5)
+#define BP_PXP_HIST8_PARAM1_VALUE5 8
+#define BM_PXP_HIST8_PARAM1_VALUE5 0x00001F00
+#define BF_PXP_HIST8_PARAM1_VALUE5(v) \
+ (((v) << 8) & BM_PXP_HIST8_PARAM1_VALUE5)
+#define BP_PXP_HIST8_PARAM1_RSVD4 5
+#define BM_PXP_HIST8_PARAM1_RSVD4 0x000000E0
+#define BF_PXP_HIST8_PARAM1_RSVD4(v) \
+ (((v) << 5) & BM_PXP_HIST8_PARAM1_RSVD4)
+#define BP_PXP_HIST8_PARAM1_VALUE4 0
+#define BM_PXP_HIST8_PARAM1_VALUE4 0x0000001F
+#define BF_PXP_HIST8_PARAM1_VALUE4(v) \
+ (((v) << 0) & BM_PXP_HIST8_PARAM1_VALUE4)
+
+#define HW_PXP_HIST16_PARAM0 (0x000002e0)
+
+#define BP_PXP_HIST16_PARAM0_RSVD3 29
+#define BM_PXP_HIST16_PARAM0_RSVD3 0xE0000000
+#define BF_PXP_HIST16_PARAM0_RSVD3(v) \
+ (((v) << 29) & BM_PXP_HIST16_PARAM0_RSVD3)
+#define BP_PXP_HIST16_PARAM0_VALUE3 24
+#define BM_PXP_HIST16_PARAM0_VALUE3 0x1F000000
+#define BF_PXP_HIST16_PARAM0_VALUE3(v) \
+ (((v) << 24) & BM_PXP_HIST16_PARAM0_VALUE3)
+#define BP_PXP_HIST16_PARAM0_RSVD2 21
+#define BM_PXP_HIST16_PARAM0_RSVD2 0x00E00000
+#define BF_PXP_HIST16_PARAM0_RSVD2(v) \
+ (((v) << 21) & BM_PXP_HIST16_PARAM0_RSVD2)
+#define BP_PXP_HIST16_PARAM0_VALUE2 16
+#define BM_PXP_HIST16_PARAM0_VALUE2 0x001F0000
+#define BF_PXP_HIST16_PARAM0_VALUE2(v) \
+ (((v) << 16) & BM_PXP_HIST16_PARAM0_VALUE2)
+#define BP_PXP_HIST16_PARAM0_RSVD1 13
+#define BM_PXP_HIST16_PARAM0_RSVD1 0x0000E000
+#define BF_PXP_HIST16_PARAM0_RSVD1(v) \
+ (((v) << 13) & BM_PXP_HIST16_PARAM0_RSVD1)
+#define BP_PXP_HIST16_PARAM0_VALUE1 8
+#define BM_PXP_HIST16_PARAM0_VALUE1 0x00001F00
+#define BF_PXP_HIST16_PARAM0_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST16_PARAM0_VALUE1)
+#define BP_PXP_HIST16_PARAM0_RSVD0 5
+#define BM_PXP_HIST16_PARAM0_RSVD0 0x000000E0
+#define BF_PXP_HIST16_PARAM0_RSVD0(v) \
+ (((v) << 5) & BM_PXP_HIST16_PARAM0_RSVD0)
+#define BP_PXP_HIST16_PARAM0_VALUE0 0
+#define BM_PXP_HIST16_PARAM0_VALUE0 0x0000001F
+#define BF_PXP_HIST16_PARAM0_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST16_PARAM0_VALUE0)
+
+#define HW_PXP_HIST16_PARAM1 (0x000002f0)
+
+#define BP_PXP_HIST16_PARAM1_RSVD7 29
+#define BM_PXP_HIST16_PARAM1_RSVD7 0xE0000000
+#define BF_PXP_HIST16_PARAM1_RSVD7(v) \
+ (((v) << 29) & BM_PXP_HIST16_PARAM1_RSVD7)
+#define BP_PXP_HIST16_PARAM1_VALUE7 24
+#define BM_PXP_HIST16_PARAM1_VALUE7 0x1F000000
+#define BF_PXP_HIST16_PARAM1_VALUE7(v) \
+ (((v) << 24) & BM_PXP_HIST16_PARAM1_VALUE7)
+#define BP_PXP_HIST16_PARAM1_RSVD6 21
+#define BM_PXP_HIST16_PARAM1_RSVD6 0x00E00000
+#define BF_PXP_HIST16_PARAM1_RSVD6(v) \
+ (((v) << 21) & BM_PXP_HIST16_PARAM1_RSVD6)
+#define BP_PXP_HIST16_PARAM1_VALUE6 16
+#define BM_PXP_HIST16_PARAM1_VALUE6 0x001F0000
+#define BF_PXP_HIST16_PARAM1_VALUE6(v) \
+ (((v) << 16) & BM_PXP_HIST16_PARAM1_VALUE6)
+#define BP_PXP_HIST16_PARAM1_RSVD5 13
+#define BM_PXP_HIST16_PARAM1_RSVD5 0x0000E000
+#define BF_PXP_HIST16_PARAM1_RSVD5(v) \
+ (((v) << 13) & BM_PXP_HIST16_PARAM1_RSVD5)
+#define BP_PXP_HIST16_PARAM1_VALUE5 8
+#define BM_PXP_HIST16_PARAM1_VALUE5 0x00001F00
+#define BF_PXP_HIST16_PARAM1_VALUE5(v) \
+ (((v) << 8) & BM_PXP_HIST16_PARAM1_VALUE5)
+#define BP_PXP_HIST16_PARAM1_RSVD4 5
+#define BM_PXP_HIST16_PARAM1_RSVD4 0x000000E0
+#define BF_PXP_HIST16_PARAM1_RSVD4(v) \
+ (((v) << 5) & BM_PXP_HIST16_PARAM1_RSVD4)
+#define BP_PXP_HIST16_PARAM1_VALUE4 0
+#define BM_PXP_HIST16_PARAM1_VALUE4 0x0000001F
+#define BF_PXP_HIST16_PARAM1_VALUE4(v) \
+ (((v) << 0) & BM_PXP_HIST16_PARAM1_VALUE4)
+
+#define HW_PXP_HIST16_PARAM2 (0x00000300)
+
+#define BP_PXP_HIST16_PARAM2_RSVD11 29
+#define BM_PXP_HIST16_PARAM2_RSVD11 0xE0000000
+#define BF_PXP_HIST16_PARAM2_RSVD11(v) \
+ (((v) << 29) & BM_PXP_HIST16_PARAM2_RSVD11)
+#define BP_PXP_HIST16_PARAM2_VALUE11 24
+#define BM_PXP_HIST16_PARAM2_VALUE11 0x1F000000
+#define BF_PXP_HIST16_PARAM2_VALUE11(v) \
+ (((v) << 24) & BM_PXP_HIST16_PARAM2_VALUE11)
+#define BP_PXP_HIST16_PARAM2_RSVD10 21
+#define BM_PXP_HIST16_PARAM2_RSVD10 0x00E00000
+#define BF_PXP_HIST16_PARAM2_RSVD10(v) \
+ (((v) << 21) & BM_PXP_HIST16_PARAM2_RSVD10)
+#define BP_PXP_HIST16_PARAM2_VALUE10 16
+#define BM_PXP_HIST16_PARAM2_VALUE10 0x001F0000
+#define BF_PXP_HIST16_PARAM2_VALUE10(v) \
+ (((v) << 16) & BM_PXP_HIST16_PARAM2_VALUE10)
+#define BP_PXP_HIST16_PARAM2_RSVD9 13
+#define BM_PXP_HIST16_PARAM2_RSVD9 0x0000E000
+#define BF_PXP_HIST16_PARAM2_RSVD9(v) \
+ (((v) << 13) & BM_PXP_HIST16_PARAM2_RSVD9)
+#define BP_PXP_HIST16_PARAM2_VALUE9 8
+#define BM_PXP_HIST16_PARAM2_VALUE9 0x00001F00
+#define BF_PXP_HIST16_PARAM2_VALUE9(v) \
+ (((v) << 8) & BM_PXP_HIST16_PARAM2_VALUE9)
+#define BP_PXP_HIST16_PARAM2_RSVD8 5
+#define BM_PXP_HIST16_PARAM2_RSVD8 0x000000E0
+#define BF_PXP_HIST16_PARAM2_RSVD8(v) \
+ (((v) << 5) & BM_PXP_HIST16_PARAM2_RSVD8)
+#define BP_PXP_HIST16_PARAM2_VALUE8 0
+#define BM_PXP_HIST16_PARAM2_VALUE8 0x0000001F
+#define BF_PXP_HIST16_PARAM2_VALUE8(v) \
+ (((v) << 0) & BM_PXP_HIST16_PARAM2_VALUE8)
+
+#define HW_PXP_HIST16_PARAM3 (0x00000310)
+
+#define BP_PXP_HIST16_PARAM3_RSVD15 29
+#define BM_PXP_HIST16_PARAM3_RSVD15 0xE0000000
+#define BF_PXP_HIST16_PARAM3_RSVD15(v) \
+ (((v) << 29) & BM_PXP_HIST16_PARAM3_RSVD15)
+#define BP_PXP_HIST16_PARAM3_VALUE15 24
+#define BM_PXP_HIST16_PARAM3_VALUE15 0x1F000000
+#define BF_PXP_HIST16_PARAM3_VALUE15(v) \
+ (((v) << 24) & BM_PXP_HIST16_PARAM3_VALUE15)
+#define BP_PXP_HIST16_PARAM3_RSVD14 21
+#define BM_PXP_HIST16_PARAM3_RSVD14 0x00E00000
+#define BF_PXP_HIST16_PARAM3_RSVD14(v) \
+ (((v) << 21) & BM_PXP_HIST16_PARAM3_RSVD14)
+#define BP_PXP_HIST16_PARAM3_VALUE14 16
+#define BM_PXP_HIST16_PARAM3_VALUE14 0x001F0000
+#define BF_PXP_HIST16_PARAM3_VALUE14(v) \
+ (((v) << 16) & BM_PXP_HIST16_PARAM3_VALUE14)
+#define BP_PXP_HIST16_PARAM3_RSVD13 13
+#define BM_PXP_HIST16_PARAM3_RSVD13 0x0000E000
+#define BF_PXP_HIST16_PARAM3_RSVD13(v) \
+ (((v) << 13) & BM_PXP_HIST16_PARAM3_RSVD13)
+#define BP_PXP_HIST16_PARAM3_VALUE13 8
+#define BM_PXP_HIST16_PARAM3_VALUE13 0x00001F00
+#define BF_PXP_HIST16_PARAM3_VALUE13(v) \
+ (((v) << 8) & BM_PXP_HIST16_PARAM3_VALUE13)
+#define BP_PXP_HIST16_PARAM3_RSVD12 5
+#define BM_PXP_HIST16_PARAM3_RSVD12 0x000000E0
+#define BF_PXP_HIST16_PARAM3_RSVD12(v) \
+ (((v) << 5) & BM_PXP_HIST16_PARAM3_RSVD12)
+#define BP_PXP_HIST16_PARAM3_VALUE12 0
+#define BM_PXP_HIST16_PARAM3_VALUE12 0x0000001F
+#define BF_PXP_HIST16_PARAM3_VALUE12(v) \
+ (((v) << 0) & BM_PXP_HIST16_PARAM3_VALUE12)
+
+#define HW_PXP_POWER (0x00000320)
+
+#define BP_PXP_POWER_CTRL 12
+#define BM_PXP_POWER_CTRL 0xFFFFF000
+#define BF_PXP_POWER_CTRL(v) \
+ (((v) << 12) & BM_PXP_POWER_CTRL)
+#define BP_PXP_POWER_ROT_MEM_LP_STATE 9
+#define BM_PXP_POWER_ROT_MEM_LP_STATE 0x00000E00
+#define BF_PXP_POWER_ROT_MEM_LP_STATE(v) \
+ (((v) << 9) & BM_PXP_POWER_ROT_MEM_LP_STATE)
+#define BV_PXP_POWER_ROT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_ROT_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_ROT_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_ROT_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 6
+#define BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 0x000001C0
+#define BF_PXP_POWER_LUT_LP_STATE_WAY1_BANKN(v) \
+ (((v) << 6) & BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN)
+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__NONE 0x0
+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__LS 0x1
+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__DS 0x2
+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__SD 0x4
+#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 3
+#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 0x00000038
+#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANKN(v) \
+ (((v) << 3) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN)
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__NONE 0x0
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__LS 0x1
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__DS 0x2
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__SD 0x4
+#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0
+#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0x00000007
+#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANK0(v) \
+ (((v) << 0) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0)
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__NONE 0x0
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__LS 0x1
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__DS 0x2
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__SD 0x4
+
+#define HW_PXP_NEXT (0x00000400)
+
+#define BP_PXP_NEXT_POINTER 2
+#define BM_PXP_NEXT_POINTER 0xFFFFFFFC
+#define BF_PXP_NEXT_POINTER(v) \
+ (((v) << 2) & BM_PXP_NEXT_POINTER)
+#define BM_PXP_NEXT_RSVD 0x00000002
+#define BM_PXP_NEXT_ENABLED 0x00000001
+
+#define HW_PXP_DEBUGCTRL (0x00000410)
+
+#define BP_PXP_DEBUGCTRL_RSVD 12
+#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000
+#define BF_PXP_DEBUGCTRL_RSVD(v) \
+ (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD)
+#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 8
+#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00
+#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v) \
+ (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT)
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE 0x0
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT 0x2
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT 0x4
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT 0x8
+#define BP_PXP_DEBUGCTRL_SELECT 0
+#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF
+#define BF_PXP_DEBUGCTRL_SELECT(v) \
+ (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT)
+#define BV_PXP_DEBUGCTRL_SELECT__NONE 0x0
+#define BV_PXP_DEBUGCTRL_SELECT__CTRL 0x1
+#define BV_PXP_DEBUGCTRL_SELECT__PSBUF 0x2
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAX 0x3
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAY 0x4
+#define BV_PXP_DEBUGCTRL_SELECT__ASBUF 0x5
+#define BV_PXP_DEBUGCTRL_SELECT__ROTATION 0x6
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0 0x7
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1 0x8
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2 0x9
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT 0x10
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS 0x11
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT 0x12
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT 0x13
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14
+
+#define HW_PXP_DEBUG (0x00000420)
+
+#define BP_PXP_DEBUG_DATA 0
+#define BM_PXP_DEBUG_DATA 0xFFFFFFFF
+#define BF_PXP_DEBUG_DATA(v) (v)
+
+#define HW_PXP_VERSION (0x00000430)
+
+#define BP_PXP_VERSION_MAJOR 24
+#define BM_PXP_VERSION_MAJOR 0xFF000000
+#define BF_PXP_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_PXP_VERSION_MAJOR)
+#define BP_PXP_VERSION_MINOR 16
+#define BM_PXP_VERSION_MINOR 0x00FF0000
+#define BF_PXP_VERSION_MINOR(v) \
+ (((v) << 16) & BM_PXP_VERSION_MINOR)
+#define BP_PXP_VERSION_STEP 0
+#define BM_PXP_VERSION_STEP 0x0000FFFF
+#define BF_PXP_VERSION_STEP(v) \
+ (((v) << 0) & BM_PXP_VERSION_STEP)
+#endif /* __ARCH_ARM___PXP_H */
diff --git a/drivers/dma/pxp/regs-pxp_v3.h b/drivers/dma/pxp/regs-pxp_v3.h
new file mode 100644
index 000000000000..15a481151a13
--- /dev/null
+++ b/drivers/dma/pxp/regs-pxp_v3.h
@@ -0,0 +1,26950 @@
+/*
+ * Freescale PXP Register Definitions
+ *
+ * Copyright 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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.77
+ * Template revision: 1.3
+ */
+
+#ifndef __ARCH_ARM___PXP_H
+#define __ARCH_ARM___PXP_H
+
+
+#define HW_PXP_CTRL (0x00000000)
+#define HW_PXP_CTRL_SET (0x00000004)
+#define HW_PXP_CTRL_CLR (0x00000008)
+#define HW_PXP_CTRL_TOG (0x0000000c)
+
+#define BM_PXP_CTRL_SFTRST 0x80000000
+#define BF_PXP_CTRL_SFTRST(v) \
+ (((v) << 31) & BM_PXP_CTRL_SFTRST)
+#define BM_PXP_CTRL_CLKGATE 0x40000000
+#define BF_PXP_CTRL_CLKGATE(v) \
+ (((v) << 30) & BM_PXP_CTRL_CLKGATE)
+#define BM_PXP_CTRL_RSVD4 0x20000000
+#define BF_PXP_CTRL_RSVD4(v) \
+ (((v) << 29) & BM_PXP_CTRL_RSVD4)
+#define BM_PXP_CTRL_EN_REPEAT 0x10000000
+#define BF_PXP_CTRL_EN_REPEAT(v) \
+ (((v) << 28) & BM_PXP_CTRL_EN_REPEAT)
+#define BM_PXP_CTRL_ENABLE_ROTATE1 0x08000000
+#define BF_PXP_CTRL_ENABLE_ROTATE1(v) \
+ (((v) << 27) & BM_PXP_CTRL_ENABLE_ROTATE1)
+#define BM_PXP_CTRL_ENABLE_ROTATE0 0x04000000
+#define BF_PXP_CTRL_ENABLE_ROTATE0(v) \
+ (((v) << 26) & BM_PXP_CTRL_ENABLE_ROTATE0)
+#define BM_PXP_CTRL_ENABLE_LUT 0x02000000
+#define BF_PXP_CTRL_ENABLE_LUT(v) \
+ (((v) << 25) & BM_PXP_CTRL_ENABLE_LUT)
+#define BM_PXP_CTRL_ENABLE_CSC2 0x01000000
+#define BF_PXP_CTRL_ENABLE_CSC2(v) \
+ (((v) << 24) & BM_PXP_CTRL_ENABLE_CSC2)
+#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000
+#define BF_PXP_CTRL_BLOCK_SIZE(v) \
+ (((v) << 23) & BM_PXP_CTRL_BLOCK_SIZE)
+#define BV_PXP_CTRL_BLOCK_SIZE__8X8 0x0
+#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1
+#define BM_PXP_CTRL_RSVD1 0x00400000
+#define BF_PXP_CTRL_RSVD1(v) \
+ (((v) << 22) & BM_PXP_CTRL_RSVD1)
+#define BM_PXP_CTRL_ENABLE_ALPHA_B 0x00200000
+#define BF_PXP_CTRL_ENABLE_ALPHA_B(v) \
+ (((v) << 21) & BM_PXP_CTRL_ENABLE_ALPHA_B)
+#define BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE 0x00100000
+#define BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(v) \
+ (((v) << 20) & BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE)
+#define BM_PXP_CTRL_ENABLE_WFE_B 0x00080000
+#define BF_PXP_CTRL_ENABLE_WFE_B(v) \
+ (((v) << 19) & BM_PXP_CTRL_ENABLE_WFE_B)
+#define BM_PXP_CTRL_ENABLE_WFE_A 0x00040000
+#define BF_PXP_CTRL_ENABLE_WFE_A(v) \
+ (((v) << 18) & BM_PXP_CTRL_ENABLE_WFE_A)
+#define BM_PXP_CTRL_ENABLE_DITHER 0x00020000
+#define BF_PXP_CTRL_ENABLE_DITHER(v) \
+ (((v) << 17) & BM_PXP_CTRL_ENABLE_DITHER)
+#define BM_PXP_CTRL_ENABLE_PS_AS_OUT 0x00010000
+#define BF_PXP_CTRL_ENABLE_PS_AS_OUT(v) \
+ (((v) << 16) & BM_PXP_CTRL_ENABLE_PS_AS_OUT)
+#define BM_PXP_CTRL_VFLIP1 0x00008000
+#define BF_PXP_CTRL_VFLIP1(v) \
+ (((v) << 15) & BM_PXP_CTRL_VFLIP1)
+#define BM_PXP_CTRL_HFLIP1 0x00004000
+#define BF_PXP_CTRL_HFLIP1(v) \
+ (((v) << 14) & BM_PXP_CTRL_HFLIP1)
+#define BP_PXP_CTRL_ROTATE1 12
+#define BM_PXP_CTRL_ROTATE1 0x00003000
+#define BF_PXP_CTRL_ROTATE1(v) \
+ (((v) << 12) & BM_PXP_CTRL_ROTATE1)
+#define BV_PXP_CTRL_ROTATE1__ROT_0 0x0
+#define BV_PXP_CTRL_ROTATE1__ROT_90 0x1
+#define BV_PXP_CTRL_ROTATE1__ROT_180 0x2
+#define BV_PXP_CTRL_ROTATE1__ROT_270 0x3
+#define BM_PXP_CTRL_VFLIP0 0x00000800
+#define BF_PXP_CTRL_VFLIP0(v) \
+ (((v) << 11) & BM_PXP_CTRL_VFLIP0)
+#define BM_PXP_CTRL_HFLIP0 0x00000400
+#define BF_PXP_CTRL_HFLIP0(v) \
+ (((v) << 10) & BM_PXP_CTRL_HFLIP0)
+#define BP_PXP_CTRL_ROTATE0 8
+#define BM_PXP_CTRL_ROTATE0 0x00000300
+#define BF_PXP_CTRL_ROTATE0(v) \
+ (((v) << 8) & BM_PXP_CTRL_ROTATE0)
+#define BV_PXP_CTRL_ROTATE0__ROT_0 0x0
+#define BV_PXP_CTRL_ROTATE0__ROT_90 0x1
+#define BV_PXP_CTRL_ROTATE0__ROT_180 0x2
+#define BV_PXP_CTRL_ROTATE0__ROT_270 0x3
+#define BP_PXP_CTRL_RSVD0 6
+#define BM_PXP_CTRL_RSVD0 0x000000C0
+#define BF_PXP_CTRL_RSVD0(v) \
+ (((v) << 6) & BM_PXP_CTRL_RSVD0)
+#define BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP 0x00000020
+#define BF_PXP_CTRL_HANDSHAKE_ABORT_SKIP(v) \
+ (((v) << 5) & BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP)
+#define BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE 0x00000010
+#define BF_PXP_CTRL_ENABLE_LCD0_HANDSHAKE(v) \
+ (((v) << 4) & BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE)
+#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008
+#define BF_PXP_CTRL_LUT_DMA_IRQ_ENABLE(v) \
+ (((v) << 3) & BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE)
+#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004
+#define BF_PXP_CTRL_NEXT_IRQ_ENABLE(v) \
+ (((v) << 2) & BM_PXP_CTRL_NEXT_IRQ_ENABLE)
+#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002
+#define BF_PXP_CTRL_IRQ_ENABLE(v) \
+ (((v) << 1) & BM_PXP_CTRL_IRQ_ENABLE)
+#define BM_PXP_CTRL_ENABLE 0x00000001
+#define BF_PXP_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PXP_CTRL_ENABLE)
+
+#define HW_PXP_STAT (0x00000010)
+#define HW_PXP_STAT_SET (0x00000014)
+#define HW_PXP_STAT_CLR (0x00000018)
+#define HW_PXP_STAT_TOG (0x0000001c)
+
+#define BP_PXP_STAT_BLOCKX 24
+#define BM_PXP_STAT_BLOCKX 0xFF000000
+#define BF_PXP_STAT_BLOCKX(v) \
+ (((v) << 24) & BM_PXP_STAT_BLOCKX)
+#define BP_PXP_STAT_BLOCKY 16
+#define BM_PXP_STAT_BLOCKY 0x00FF0000
+#define BF_PXP_STAT_BLOCKY(v) \
+ (((v) << 16) & BM_PXP_STAT_BLOCKY)
+#define BP_PXP_STAT_AXI_ERROR_ID_1 12
+#define BM_PXP_STAT_AXI_ERROR_ID_1 0x0000F000
+#define BF_PXP_STAT_AXI_ERROR_ID_1(v) \
+ (((v) << 12) & BM_PXP_STAT_AXI_ERROR_ID_1)
+#define BM_PXP_STAT_RSVD2 0x00000800
+#define BF_PXP_STAT_RSVD2(v) \
+ (((v) << 11) & BM_PXP_STAT_RSVD2)
+#define BM_PXP_STAT_AXI_READ_ERROR_1 0x00000400
+#define BF_PXP_STAT_AXI_READ_ERROR_1(v) \
+ (((v) << 10) & BM_PXP_STAT_AXI_READ_ERROR_1)
+#define BM_PXP_STAT_AXI_WRITE_ERROR_1 0x00000200
+#define BF_PXP_STAT_AXI_WRITE_ERROR_1(v) \
+ (((v) << 9) & BM_PXP_STAT_AXI_WRITE_ERROR_1)
+#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100
+#define BF_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ(v) \
+ (((v) << 8) & BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ)
+#define BP_PXP_STAT_AXI_ERROR_ID_0 4
+#define BM_PXP_STAT_AXI_ERROR_ID_0 0x000000F0
+#define BF_PXP_STAT_AXI_ERROR_ID_0(v) \
+ (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID_0)
+#define BM_PXP_STAT_NEXT_IRQ 0x00000008
+#define BF_PXP_STAT_NEXT_IRQ(v) \
+ (((v) << 3) & BM_PXP_STAT_NEXT_IRQ)
+#define BM_PXP_STAT_AXI_READ_ERROR_0 0x00000004
+#define BF_PXP_STAT_AXI_READ_ERROR_0(v) \
+ (((v) << 2) & BM_PXP_STAT_AXI_READ_ERROR_0)
+#define BM_PXP_STAT_AXI_WRITE_ERROR_0 0x00000002
+#define BF_PXP_STAT_AXI_WRITE_ERROR_0(v) \
+ (((v) << 1) & BM_PXP_STAT_AXI_WRITE_ERROR_0)
+#define BM_PXP_STAT_IRQ0 0x00000001
+#define BF_PXP_STAT_IRQ0(v) \
+ (((v) << 0) & BM_PXP_STAT_IRQ0)
+
+#define HW_PXP_OUT_CTRL (0x00000020)
+#define HW_PXP_OUT_CTRL_SET (0x00000024)
+#define HW_PXP_OUT_CTRL_CLR (0x00000028)
+#define HW_PXP_OUT_CTRL_TOG (0x0000002c)
+
+#define BP_PXP_OUT_CTRL_ALPHA 24
+#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000
+#define BF_PXP_OUT_CTRL_ALPHA(v) \
+ (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA)
+#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000
+#define BF_PXP_OUT_CTRL_ALPHA_OUTPUT(v) \
+ (((v) << 23) & BM_PXP_OUT_CTRL_ALPHA_OUTPUT)
+#define BP_PXP_OUT_CTRL_RSVD1 10
+#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00
+#define BF_PXP_OUT_CTRL_RSVD1(v) \
+ (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1)
+#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT 8
+#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300
+#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v) \
+ (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT)
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0 0x1
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1 0x2
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED 0x3
+#define BP_PXP_OUT_CTRL_RSVD0 5
+#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0
+#define BF_PXP_OUT_CTRL_RSVD0(v) \
+ (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0)
+#define BP_PXP_OUT_CTRL_FORMAT 0
+#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F
+#define BF_PXP_OUT_CTRL_FORMAT(v) \
+ (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT)
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888 0x0
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888P 0x5
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555 0x8
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444 0x9
+#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE
+#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10
+#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_OUT_CTRL_FORMAT__Y8 0x14
+#define BV_PXP_OUT_CTRL_FORMAT__Y4 0x15
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422 0x18
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420 0x19
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422 0x1A
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420 0x1B
+
+#define HW_PXP_OUT_BUF (0x00000030)
+
+#define BP_PXP_OUT_BUF_ADDR 0
+#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF_ADDR(v) (v)
+
+#define HW_PXP_OUT_BUF2 (0x00000040)
+
+#define BP_PXP_OUT_BUF2_ADDR 0
+#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF2_ADDR(v) (v)
+
+#define HW_PXP_OUT_PITCH (0x00000050)
+
+#define BP_PXP_OUT_PITCH_RSVD 16
+#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_OUT_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_OUT_PITCH_RSVD)
+#define BP_PXP_OUT_PITCH_PITCH 0
+#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_OUT_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_OUT_PITCH_PITCH)
+
+#define HW_PXP_OUT_LRC (0x00000060)
+
+#define BP_PXP_OUT_LRC_RSVD1 30
+#define BM_PXP_OUT_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_LRC_RSVD1)
+#define BP_PXP_OUT_LRC_X 16
+#define BM_PXP_OUT_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_LRC_X)
+#define BP_PXP_OUT_LRC_RSVD0 14
+#define BM_PXP_OUT_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_LRC_RSVD0)
+#define BP_PXP_OUT_LRC_Y 0
+#define BM_PXP_OUT_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_LRC_Y)
+
+#define HW_PXP_OUT_PS_ULC (0x00000070)
+
+#define BP_PXP_OUT_PS_ULC_RSVD1 30
+#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_ULC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1)
+#define BP_PXP_OUT_PS_ULC_X 16
+#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_ULC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_PS_ULC_X)
+#define BP_PXP_OUT_PS_ULC_RSVD0 14
+#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_ULC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0)
+#define BP_PXP_OUT_PS_ULC_Y 0
+#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_ULC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_PS_ULC_Y)
+
+#define HW_PXP_OUT_PS_LRC (0x00000080)
+
+#define BP_PXP_OUT_PS_LRC_RSVD1 30
+#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1)
+#define BP_PXP_OUT_PS_LRC_X 16
+#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_PS_LRC_X)
+#define BP_PXP_OUT_PS_LRC_RSVD0 14
+#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0)
+#define BP_PXP_OUT_PS_LRC_Y 0
+#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_PS_LRC_Y)
+
+#define HW_PXP_OUT_AS_ULC (0x00000090)
+
+#define BP_PXP_OUT_AS_ULC_RSVD1 30
+#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_ULC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1)
+#define BP_PXP_OUT_AS_ULC_X 16
+#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_ULC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_AS_ULC_X)
+#define BP_PXP_OUT_AS_ULC_RSVD0 14
+#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_ULC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0)
+#define BP_PXP_OUT_AS_ULC_Y 0
+#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_ULC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_AS_ULC_Y)
+
+#define HW_PXP_OUT_AS_LRC (0x000000a0)
+
+#define BP_PXP_OUT_AS_LRC_RSVD1 30
+#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_LRC_RSVD1(v) \
+ (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1)
+#define BP_PXP_OUT_AS_LRC_X 16
+#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_LRC_X(v) \
+ (((v) << 16) & BM_PXP_OUT_AS_LRC_X)
+#define BP_PXP_OUT_AS_LRC_RSVD0 14
+#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_LRC_RSVD0(v) \
+ (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0)
+#define BP_PXP_OUT_AS_LRC_Y 0
+#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_LRC_Y(v) \
+ (((v) << 0) & BM_PXP_OUT_AS_LRC_Y)
+
+#define HW_PXP_PS_CTRL (0x000000b0)
+#define HW_PXP_PS_CTRL_SET (0x000000b4)
+#define HW_PXP_PS_CTRL_CLR (0x000000b8)
+#define HW_PXP_PS_CTRL_TOG (0x000000bc)
+
+#define BP_PXP_PS_CTRL_RSVD1 12
+#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000
+#define BF_PXP_PS_CTRL_RSVD1(v) \
+ (((v) << 12) & BM_PXP_PS_CTRL_RSVD1)
+#define BP_PXP_PS_CTRL_DECX 10
+#define BM_PXP_PS_CTRL_DECX 0x00000C00
+#define BF_PXP_PS_CTRL_DECX(v) \
+ (((v) << 10) & BM_PXP_PS_CTRL_DECX)
+#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECX__DECX2 0x1
+#define BV_PXP_PS_CTRL_DECX__DECX4 0x2
+#define BV_PXP_PS_CTRL_DECX__DECX8 0x3
+#define BP_PXP_PS_CTRL_DECY 8
+#define BM_PXP_PS_CTRL_DECY 0x00000300
+#define BF_PXP_PS_CTRL_DECY(v) \
+ (((v) << 8) & BM_PXP_PS_CTRL_DECY)
+#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECY__DECY2 0x1
+#define BV_PXP_PS_CTRL_DECY__DECY4 0x2
+#define BV_PXP_PS_CTRL_DECY__DECY8 0x3
+#define BM_PXP_PS_CTRL_RSVD0 0x00000080
+#define BF_PXP_PS_CTRL_RSVD0(v) \
+ (((v) << 7) & BM_PXP_PS_CTRL_RSVD0)
+#define BM_PXP_PS_CTRL_WB_SWAP 0x00000040
+#define BF_PXP_PS_CTRL_WB_SWAP(v) \
+ (((v) << 6) & BM_PXP_PS_CTRL_WB_SWAP)
+#define BP_PXP_PS_CTRL_FORMAT 0
+#define BM_PXP_PS_CTRL_FORMAT 0x0000003F
+#define BF_PXP_PS_CTRL_FORMAT(v) \
+ (((v) << 0) & BM_PXP_PS_CTRL_FORMAT)
+#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_PS_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_PS_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE
+#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10
+#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_PS_CTRL_FORMAT__Y8 0x14
+#define BV_PXP_PS_CTRL_FORMAT__Y4 0x15
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P422 0x18
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P420 0x19
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P422 0x1A
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P420 0x1B
+#define BV_PXP_PS_CTRL_FORMAT__YUV422 0x1E
+#define BV_PXP_PS_CTRL_FORMAT__YUV420 0x1F
+#define BV_PXP_PS_CTRL_FORMAT__RGBA888 0x24
+
+#define HW_PXP_PS_BUF (0x000000c0)
+
+#define BP_PXP_PS_BUF_ADDR 0
+#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_BUF_ADDR(v) (v)
+
+#define HW_PXP_PS_UBUF (0x000000d0)
+
+#define BP_PXP_PS_UBUF_ADDR 0
+#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_UBUF_ADDR(v) (v)
+
+#define HW_PXP_PS_VBUF (0x000000e0)
+
+#define BP_PXP_PS_VBUF_ADDR 0
+#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_VBUF_ADDR(v) (v)
+
+#define HW_PXP_PS_PITCH (0x000000f0)
+
+#define BP_PXP_PS_PITCH_RSVD 16
+#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_PS_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_PS_PITCH_RSVD)
+#define BP_PXP_PS_PITCH_PITCH 0
+#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_PS_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_PS_PITCH_PITCH)
+
+#define HW_PXP_PS_BACKGROUND_0 (0x00000100)
+
+#define BP_PXP_PS_BACKGROUND_0_RSVD 24
+#define BM_PXP_PS_BACKGROUND_0_RSVD 0xFF000000
+#define BF_PXP_PS_BACKGROUND_0_RSVD(v) \
+ (((v) << 24) & BM_PXP_PS_BACKGROUND_0_RSVD)
+#define BP_PXP_PS_BACKGROUND_0_COLOR 0
+#define BM_PXP_PS_BACKGROUND_0_COLOR 0x00FFFFFF
+#define BF_PXP_PS_BACKGROUND_0_COLOR(v) \
+ (((v) << 0) & BM_PXP_PS_BACKGROUND_0_COLOR)
+
+#define HW_PXP_PS_SCALE (0x00000110)
+
+#define BM_PXP_PS_SCALE_RSVD2 0x80000000
+#define BF_PXP_PS_SCALE_RSVD2(v) \
+ (((v) << 31) & BM_PXP_PS_SCALE_RSVD2)
+#define BP_PXP_PS_SCALE_YSCALE 16
+#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000
+#define BF_PXP_PS_SCALE_YSCALE(v) \
+ (((v) << 16) & BM_PXP_PS_SCALE_YSCALE)
+#define BM_PXP_PS_SCALE_RSVD1 0x00008000
+#define BF_PXP_PS_SCALE_RSVD1(v) \
+ (((v) << 15) & BM_PXP_PS_SCALE_RSVD1)
+#define BP_PXP_PS_SCALE_XSCALE 0
+#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF
+#define BF_PXP_PS_SCALE_XSCALE(v) \
+ (((v) << 0) & BM_PXP_PS_SCALE_XSCALE)
+
+#define HW_PXP_PS_OFFSET (0x00000120)
+
+#define BP_PXP_PS_OFFSET_RSVD2 28
+#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000
+#define BF_PXP_PS_OFFSET_RSVD2(v) \
+ (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2)
+#define BP_PXP_PS_OFFSET_YOFFSET 16
+#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000
+#define BF_PXP_PS_OFFSET_YOFFSET(v) \
+ (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET)
+#define BP_PXP_PS_OFFSET_RSVD1 12
+#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000
+#define BF_PXP_PS_OFFSET_RSVD1(v) \
+ (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1)
+#define BP_PXP_PS_OFFSET_XOFFSET 0
+#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF
+#define BF_PXP_PS_OFFSET_XOFFSET(v) \
+ (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET)
+
+#define HW_PXP_PS_CLRKEYLOW_0 (0x00000130)
+
+#define BP_PXP_PS_CLRKEYLOW_0_RSVD1 24
+#define BM_PXP_PS_CLRKEYLOW_0_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYLOW_0_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYLOW_0_RSVD1)
+#define BP_PXP_PS_CLRKEYLOW_0_PIXEL 0
+#define BM_PXP_PS_CLRKEYLOW_0_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYLOW_0_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYLOW_0_PIXEL)
+
+#define HW_PXP_PS_CLRKEYHIGH_0 (0x00000140)
+
+#define BP_PXP_PS_CLRKEYHIGH_0_RSVD1 24
+#define BM_PXP_PS_CLRKEYHIGH_0_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYHIGH_0_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_0_RSVD1)
+#define BP_PXP_PS_CLRKEYHIGH_0_PIXEL 0
+#define BM_PXP_PS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYHIGH_0_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_0_PIXEL)
+
+#define HW_PXP_AS_CTRL (0x00000150)
+
+#define BP_PXP_AS_CTRL_RSVD1 22
+#define BM_PXP_AS_CTRL_RSVD1 0xFFC00000
+#define BF_PXP_AS_CTRL_RSVD1(v) \
+ (((v) << 22) & BM_PXP_AS_CTRL_RSVD1)
+#define BM_PXP_AS_CTRL_ALPHA1_INVERT 0x00200000
+#define BF_PXP_AS_CTRL_ALPHA1_INVERT(v) \
+ (((v) << 21) & BM_PXP_AS_CTRL_ALPHA1_INVERT)
+#define BM_PXP_AS_CTRL_ALPHA0_INVERT 0x00100000
+#define BF_PXP_AS_CTRL_ALPHA0_INVERT(v) \
+ (((v) << 20) & BM_PXP_AS_CTRL_ALPHA0_INVERT)
+#define BP_PXP_AS_CTRL_ROP 16
+#define BM_PXP_AS_CTRL_ROP 0x000F0000
+#define BF_PXP_AS_CTRL_ROP(v) \
+ (((v) << 16) & BM_PXP_AS_CTRL_ROP)
+#define BV_PXP_AS_CTRL_ROP__MASKAS 0x0
+#define BV_PXP_AS_CTRL_ROP__MASKNOTAS 0x1
+#define BV_PXP_AS_CTRL_ROP__MASKASNOT 0x2
+#define BV_PXP_AS_CTRL_ROP__MERGEAS 0x3
+#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4
+#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5
+#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS 0x6
+#define BV_PXP_AS_CTRL_ROP__NOT 0x7
+#define BV_PXP_AS_CTRL_ROP__NOTMASKAS 0x8
+#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9
+#define BV_PXP_AS_CTRL_ROP__XORAS 0xA
+#define BV_PXP_AS_CTRL_ROP__NOTXORAS 0xB
+#define BP_PXP_AS_CTRL_ALPHA 8
+#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00
+#define BF_PXP_AS_CTRL_ALPHA(v) \
+ (((v) << 8) & BM_PXP_AS_CTRL_ALPHA)
+#define BP_PXP_AS_CTRL_FORMAT 4
+#define BM_PXP_AS_CTRL_FORMAT 0x000000F0
+#define BF_PXP_AS_CTRL_FORMAT(v) \
+ (((v) << 4) & BM_PXP_AS_CTRL_FORMAT)
+#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0
+#define BV_PXP_AS_CTRL_FORMAT__RGBA8888 0x1
+#define BV_PXP_AS_CTRL_FORMAT__RGB888 0x4
+#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8
+#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9
+#define BV_PXP_AS_CTRL_FORMAT__RGBA5551 0xA
+#define BV_PXP_AS_CTRL_FORMAT__RGBA4444 0xB
+#define BV_PXP_AS_CTRL_FORMAT__RGB555 0xC
+#define BV_PXP_AS_CTRL_FORMAT__RGB444 0xD
+#define BV_PXP_AS_CTRL_FORMAT__RGB565 0xE
+#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008
+#define BF_PXP_AS_CTRL_ENABLE_COLORKEY(v) \
+ (((v) << 3) & BM_PXP_AS_CTRL_ENABLE_COLORKEY)
+#define BP_PXP_AS_CTRL_ALPHA_CTRL 1
+#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006
+#define BF_PXP_AS_CTRL_ALPHA_CTRL(v) \
+ (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL)
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs 0x3
+#define BM_PXP_AS_CTRL_RSVD0 0x00000001
+#define BF_PXP_AS_CTRL_RSVD0(v) \
+ (((v) << 0) & BM_PXP_AS_CTRL_RSVD0)
+
+#define HW_PXP_AS_BUF (0x00000160)
+
+#define BP_PXP_AS_BUF_ADDR 0
+#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_AS_BUF_ADDR(v) (v)
+
+#define HW_PXP_AS_PITCH (0x00000170)
+
+#define BP_PXP_AS_PITCH_RSVD 16
+#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_AS_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_AS_PITCH_RSVD)
+#define BP_PXP_AS_PITCH_PITCH 0
+#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_AS_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_AS_PITCH_PITCH)
+
+#define HW_PXP_AS_CLRKEYLOW_0 (0x00000180)
+
+#define BP_PXP_AS_CLRKEYLOW_0_RSVD1 24
+#define BM_PXP_AS_CLRKEYLOW_0_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYLOW_0_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYLOW_0_RSVD1)
+#define BP_PXP_AS_CLRKEYLOW_0_PIXEL 0
+#define BM_PXP_AS_CLRKEYLOW_0_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYLOW_0_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYLOW_0_PIXEL)
+
+#define HW_PXP_AS_CLRKEYHIGH_0 (0x00000190)
+
+#define BP_PXP_AS_CLRKEYHIGH_0_RSVD1 24
+#define BM_PXP_AS_CLRKEYHIGH_0_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYHIGH_0_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_0_RSVD1)
+#define BP_PXP_AS_CLRKEYHIGH_0_PIXEL 0
+#define BM_PXP_AS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYHIGH_0_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_0_PIXEL)
+
+#define HW_PXP_CSC1_COEF0 (0x000001a0)
+
+#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000
+#define BF_PXP_CSC1_COEF0_YCBCR_MODE(v) \
+ (((v) << 31) & BM_PXP_CSC1_COEF0_YCBCR_MODE)
+#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000
+#define BF_PXP_CSC1_COEF0_BYPASS(v) \
+ (((v) << 30) & BM_PXP_CSC1_COEF0_BYPASS)
+#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000
+#define BF_PXP_CSC1_COEF0_RSVD1(v) \
+ (((v) << 29) & BM_PXP_CSC1_COEF0_RSVD1)
+#define BP_PXP_CSC1_COEF0_C0 18
+#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000
+#define BF_PXP_CSC1_COEF0_C0(v) \
+ (((v) << 18) & BM_PXP_CSC1_COEF0_C0)
+#define BP_PXP_CSC1_COEF0_UV_OFFSET 9
+#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00
+#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \
+ (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET)
+#define BP_PXP_CSC1_COEF0_Y_OFFSET 0
+#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF
+#define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET)
+
+#define HW_PXP_CSC1_COEF1 (0x000001b0)
+
+#define BP_PXP_CSC1_COEF1_RSVD1 27
+#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF1_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1)
+#define BP_PXP_CSC1_COEF1_C1 16
+#define BM_PXP_CSC1_COEF1_C1 0x07FF0000
+#define BF_PXP_CSC1_COEF1_C1(v) \
+ (((v) << 16) & BM_PXP_CSC1_COEF1_C1)
+#define BP_PXP_CSC1_COEF1_RSVD0 11
+#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF1_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0)
+#define BP_PXP_CSC1_COEF1_C4 0
+#define BM_PXP_CSC1_COEF1_C4 0x000007FF
+#define BF_PXP_CSC1_COEF1_C4(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF1_C4)
+
+#define HW_PXP_CSC1_COEF2 (0x000001c0)
+
+#define BP_PXP_CSC1_COEF2_RSVD1 27
+#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF2_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1)
+#define BP_PXP_CSC1_COEF2_C2 16
+#define BM_PXP_CSC1_COEF2_C2 0x07FF0000
+#define BF_PXP_CSC1_COEF2_C2(v) \
+ (((v) << 16) & BM_PXP_CSC1_COEF2_C2)
+#define BP_PXP_CSC1_COEF2_RSVD0 11
+#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF2_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0)
+#define BP_PXP_CSC1_COEF2_C3 0
+#define BM_PXP_CSC1_COEF2_C3 0x000007FF
+#define BF_PXP_CSC1_COEF2_C3(v) \
+ (((v) << 0) & BM_PXP_CSC1_COEF2_C3)
+
+#define HW_PXP_CSC2_CTRL (0x000001d0)
+
+#define BP_PXP_CSC2_CTRL_RSVD 3
+#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8
+#define BF_PXP_CSC2_CTRL_RSVD(v) \
+ (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD)
+#define BP_PXP_CSC2_CTRL_CSC_MODE 1
+#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006
+#define BF_PXP_CSC2_CTRL_CSC_MODE(v) \
+ (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE)
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB 0x0
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV 0x2
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3
+#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001
+#define BF_PXP_CSC2_CTRL_BYPASS(v) \
+ (((v) << 0) & BM_PXP_CSC2_CTRL_BYPASS)
+
+#define HW_PXP_CSC2_COEF0 (0x000001e0)
+
+#define BP_PXP_CSC2_COEF0_RSVD1 27
+#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF0_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1)
+#define BP_PXP_CSC2_COEF0_A2 16
+#define BM_PXP_CSC2_COEF0_A2 0x07FF0000
+#define BF_PXP_CSC2_COEF0_A2(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF0_A2)
+#define BP_PXP_CSC2_COEF0_RSVD0 11
+#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF0_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0)
+#define BP_PXP_CSC2_COEF0_A1 0
+#define BM_PXP_CSC2_COEF0_A1 0x000007FF
+#define BF_PXP_CSC2_COEF0_A1(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF0_A1)
+
+#define HW_PXP_CSC2_COEF1 (0x000001f0)
+
+#define BP_PXP_CSC2_COEF1_RSVD1 27
+#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF1_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1)
+#define BP_PXP_CSC2_COEF1_B1 16
+#define BM_PXP_CSC2_COEF1_B1 0x07FF0000
+#define BF_PXP_CSC2_COEF1_B1(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF1_B1)
+#define BP_PXP_CSC2_COEF1_RSVD0 11
+#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF1_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0)
+#define BP_PXP_CSC2_COEF1_A3 0
+#define BM_PXP_CSC2_COEF1_A3 0x000007FF
+#define BF_PXP_CSC2_COEF1_A3(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF1_A3)
+
+#define HW_PXP_CSC2_COEF2 (0x00000200)
+
+#define BP_PXP_CSC2_COEF2_RSVD1 27
+#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF2_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1)
+#define BP_PXP_CSC2_COEF2_B3 16
+#define BM_PXP_CSC2_COEF2_B3 0x07FF0000
+#define BF_PXP_CSC2_COEF2_B3(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF2_B3)
+#define BP_PXP_CSC2_COEF2_RSVD0 11
+#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF2_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0)
+#define BP_PXP_CSC2_COEF2_B2 0
+#define BM_PXP_CSC2_COEF2_B2 0x000007FF
+#define BF_PXP_CSC2_COEF2_B2(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF2_B2)
+
+#define HW_PXP_CSC2_COEF3 (0x00000210)
+
+#define BP_PXP_CSC2_COEF3_RSVD1 27
+#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF3_RSVD1(v) \
+ (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1)
+#define BP_PXP_CSC2_COEF3_C2 16
+#define BM_PXP_CSC2_COEF3_C2 0x07FF0000
+#define BF_PXP_CSC2_COEF3_C2(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF3_C2)
+#define BP_PXP_CSC2_COEF3_RSVD0 11
+#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF3_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0)
+#define BP_PXP_CSC2_COEF3_C1 0
+#define BM_PXP_CSC2_COEF3_C1 0x000007FF
+#define BF_PXP_CSC2_COEF3_C1(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF3_C1)
+
+#define HW_PXP_CSC2_COEF4 (0x00000220)
+
+#define BP_PXP_CSC2_COEF4_RSVD1 25
+#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF4_RSVD1(v) \
+ (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1)
+#define BP_PXP_CSC2_COEF4_D1 16
+#define BM_PXP_CSC2_COEF4_D1 0x01FF0000
+#define BF_PXP_CSC2_COEF4_D1(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF4_D1)
+#define BP_PXP_CSC2_COEF4_RSVD0 11
+#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF4_RSVD0(v) \
+ (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0)
+#define BP_PXP_CSC2_COEF4_C3 0
+#define BM_PXP_CSC2_COEF4_C3 0x000007FF
+#define BF_PXP_CSC2_COEF4_C3(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF4_C3)
+
+#define HW_PXP_CSC2_COEF5 (0x00000230)
+
+#define BP_PXP_CSC2_COEF5_RSVD1 25
+#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF5_RSVD1(v) \
+ (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1)
+#define BP_PXP_CSC2_COEF5_D3 16
+#define BM_PXP_CSC2_COEF5_D3 0x01FF0000
+#define BF_PXP_CSC2_COEF5_D3(v) \
+ (((v) << 16) & BM_PXP_CSC2_COEF5_D3)
+#define BP_PXP_CSC2_COEF5_RSVD0 9
+#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00
+#define BF_PXP_CSC2_COEF5_RSVD0(v) \
+ (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0)
+#define BP_PXP_CSC2_COEF5_D2 0
+#define BM_PXP_CSC2_COEF5_D2 0x000001FF
+#define BF_PXP_CSC2_COEF5_D2(v) \
+ (((v) << 0) & BM_PXP_CSC2_COEF5_D2)
+
+#define HW_PXP_LUT_CTRL (0x00000240)
+
+#define BM_PXP_LUT_CTRL_BYPASS 0x80000000
+#define BF_PXP_LUT_CTRL_BYPASS(v) \
+ (((v) << 31) & BM_PXP_LUT_CTRL_BYPASS)
+#define BP_PXP_LUT_CTRL_RSVD3 26
+#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000
+#define BF_PXP_LUT_CTRL_RSVD3(v) \
+ (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3)
+#define BP_PXP_LUT_CTRL_LOOKUP_MODE 24
+#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000
+#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \
+ (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE)
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565 0x0
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8 0x1
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3
+#define BP_PXP_LUT_CTRL_RSVD2 18
+#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000
+#define BF_PXP_LUT_CTRL_RSVD2(v) \
+ (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2)
+#define BP_PXP_LUT_CTRL_OUT_MODE 16
+#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000
+#define BF_PXP_LUT_CTRL_OUT_MODE(v) \
+ (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE)
+#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED 0x0
+#define BV_PXP_LUT_CTRL_OUT_MODE__Y8 0x1
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888 0x3
+#define BP_PXP_LUT_CTRL_RSVD1 11
+#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800
+#define BF_PXP_LUT_CTRL_RSVD1(v) \
+ (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1)
+#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400
+#define BF_PXP_LUT_CTRL_SEL_8KB(v) \
+ (((v) << 10) & BM_PXP_LUT_CTRL_SEL_8KB)
+#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200
+#define BF_PXP_LUT_CTRL_LRU_UPD(v) \
+ (((v) << 9) & BM_PXP_LUT_CTRL_LRU_UPD)
+#define BM_PXP_LUT_CTRL_INVALID 0x00000100
+#define BF_PXP_LUT_CTRL_INVALID(v) \
+ (((v) << 8) & BM_PXP_LUT_CTRL_INVALID)
+#define BP_PXP_LUT_CTRL_RSVD0 1
+#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE
+#define BF_PXP_LUT_CTRL_RSVD0(v) \
+ (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0)
+#define BM_PXP_LUT_CTRL_DMA_START 0x00000001
+#define BF_PXP_LUT_CTRL_DMA_START(v) \
+ (((v) << 0) & BM_PXP_LUT_CTRL_DMA_START)
+
+#define HW_PXP_LUT_ADDR (0x00000250)
+
+#define BM_PXP_LUT_ADDR_RSVD2 0x80000000
+#define BF_PXP_LUT_ADDR_RSVD2(v) \
+ (((v) << 31) & BM_PXP_LUT_ADDR_RSVD2)
+#define BP_PXP_LUT_ADDR_NUM_BYTES 16
+#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000
+#define BF_PXP_LUT_ADDR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES)
+#define BP_PXP_LUT_ADDR_RSVD1 14
+#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000
+#define BF_PXP_LUT_ADDR_RSVD1(v) \
+ (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1)
+#define BP_PXP_LUT_ADDR_ADDR 0
+#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF
+#define BF_PXP_LUT_ADDR_ADDR(v) \
+ (((v) << 0) & BM_PXP_LUT_ADDR_ADDR)
+
+#define HW_PXP_LUT_DATA (0x00000260)
+
+#define BP_PXP_LUT_DATA_DATA 0
+#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF
+#define BF_PXP_LUT_DATA_DATA(v) (v)
+
+#define HW_PXP_LUT_EXTMEM (0x00000270)
+
+#define BP_PXP_LUT_EXTMEM_ADDR 0
+#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF
+#define BF_PXP_LUT_EXTMEM_ADDR(v) (v)
+
+#define HW_PXP_CFA (0x00000280)
+
+#define BP_PXP_CFA_DATA 0
+#define BM_PXP_CFA_DATA 0xFFFFFFFF
+#define BF_PXP_CFA_DATA(v) (v)
+
+#define HW_PXP_ALPHA_A_CTRL (0x00000290)
+
+#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA 24
+#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA 0xFF000000
+#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA(v) \
+ (((v) << 24) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA 16
+#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA 0x00FF0000
+#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA(v) \
+ (((v) << 16) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_A_CTRL_RSVD0 14
+#define BM_PXP_ALPHA_A_CTRL_RSVD0 0x0000C000
+#define BF_PXP_ALPHA_A_CTRL_RSVD0(v) \
+ (((v) << 14) & BM_PXP_ALPHA_A_CTRL_RSVD0)
+#define BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE 0x00002000
+#define BF_PXP_ALPHA_A_CTRL_S1_COLOR_MODE(v) \
+ (((v) << 13) & BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE 0x00001000
+#define BF_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE(v) \
+ (((v) << 12) & BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE 10
+#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00
+#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE(v) \
+ (((v) << 10) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x0
+#define BP_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE 8
+#define BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE 0x00000300
+#define BF_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE(v) \
+ (((v) << 8) & BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_A_CTRL_RSVD1 0x00000080
+#define BF_PXP_ALPHA_A_CTRL_RSVD1(v) \
+ (((v) << 7) & BM_PXP_ALPHA_A_CTRL_RSVD1)
+#define BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE 0x00000040
+#define BF_PXP_ALPHA_A_CTRL_S0_COLOR_MODE(v) \
+ (((v) << 6) & BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE 0x00000020
+#define BF_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE(v) \
+ (((v) << 5) & BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE 3
+#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018
+#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE(v) \
+ (((v) << 3) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE 1
+#define BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE 0x00000006
+#define BF_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE(v) \
+ (((v) << 1) & BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE 0x00000001
+#define BF_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE(v) \
+ (((v) << 0) & BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE)
+#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__1 0x1
+
+#define HW_PXP_ALPHA_B_CTRL (0x000002a0)
+
+#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA 24
+#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA 0xFF000000
+#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA(v) \
+ (((v) << 24) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA 16
+#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA 0x00FF0000
+#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA(v) \
+ (((v) << 16) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_B_CTRL_RSVD0 14
+#define BM_PXP_ALPHA_B_CTRL_RSVD0 0x0000C000
+#define BF_PXP_ALPHA_B_CTRL_RSVD0(v) \
+ (((v) << 14) & BM_PXP_ALPHA_B_CTRL_RSVD0)
+#define BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE 0x00002000
+#define BF_PXP_ALPHA_B_CTRL_S1_COLOR_MODE(v) \
+ (((v) << 13) & BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE 0x00001000
+#define BF_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE(v) \
+ (((v) << 12) & BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE 10
+#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00
+#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE(v) \
+ (((v) << 10) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE 8
+#define BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE 0x00000300
+#define BF_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE(v) \
+ (((v) << 8) & BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_B_CTRL_RSVD1 0x00000080
+#define BF_PXP_ALPHA_B_CTRL_RSVD1(v) \
+ (((v) << 7) & BM_PXP_ALPHA_B_CTRL_RSVD1)
+#define BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE 0x00000040
+#define BF_PXP_ALPHA_B_CTRL_S0_COLOR_MODE(v) \
+ (((v) << 6) & BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE 0x00000020
+#define BF_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE(v) \
+ (((v) << 5) & BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE 3
+#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018
+#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE(v) \
+ (((v) << 3) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE 1
+#define BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE 0x00000006
+#define BF_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE(v) \
+ (((v) << 1) & BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE 0x00000001
+#define BF_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE(v) \
+ (((v) << 0) & BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE)
+#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__1 0x1
+
+#define HW_PXP_ALPHA_B_CTRL_1 (0x000002b0)
+
+#define BP_PXP_ALPHA_B_CTRL_1_RSVD0 8
+#define BM_PXP_ALPHA_B_CTRL_1_RSVD0 0xFFFFFF00
+#define BF_PXP_ALPHA_B_CTRL_1_RSVD0(v) \
+ (((v) << 8) & BM_PXP_ALPHA_B_CTRL_1_RSVD0)
+#define BP_PXP_ALPHA_B_CTRL_1_ROP 4
+#define BM_PXP_ALPHA_B_CTRL_1_ROP 0x000000F0
+#define BF_PXP_ALPHA_B_CTRL_1_ROP(v) \
+ (((v) << 4) & BM_PXP_ALPHA_B_CTRL_1_ROP)
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKAS 0x0
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKNOTAS 0x1
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKASNOT 0x2
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEAS 0x3
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGENOTAS 0x4
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEASNOT 0x5
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTCOPYAS 0x6
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOT 0x7
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMASKAS 0x8
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMERGEAS 0x9
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__XORAS 0xA
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTXORAS 0xB
+#define BP_PXP_ALPHA_B_CTRL_1_RSVD1 2
+#define BM_PXP_ALPHA_B_CTRL_1_RSVD1 0x0000000C
+#define BF_PXP_ALPHA_B_CTRL_1_RSVD1(v) \
+ (((v) << 2) & BM_PXP_ALPHA_B_CTRL_1_RSVD1)
+#define BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE 0x00000002
+#define BF_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE(v) \
+ (((v) << 1) & BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE)
+#define BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE 0x00000001
+#define BF_PXP_ALPHA_B_CTRL_1_ROP_ENABLE(v) \
+ (((v) << 0) & BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE)
+
+#define HW_PXP_PS_BACKGROUND_1 (0x000002c0)
+
+#define BP_PXP_PS_BACKGROUND_1_RSVD 24
+#define BM_PXP_PS_BACKGROUND_1_RSVD 0xFF000000
+#define BF_PXP_PS_BACKGROUND_1_RSVD(v) \
+ (((v) << 24) & BM_PXP_PS_BACKGROUND_1_RSVD)
+#define BP_PXP_PS_BACKGROUND_1_COLOR 0
+#define BM_PXP_PS_BACKGROUND_1_COLOR 0x00FFFFFF
+#define BF_PXP_PS_BACKGROUND_1_COLOR(v) \
+ (((v) << 0) & BM_PXP_PS_BACKGROUND_1_COLOR)
+
+#define HW_PXP_PS_CLRKEYLOW_1 (0x000002d0)
+
+#define BP_PXP_PS_CLRKEYLOW_1_RSVD1 24
+#define BM_PXP_PS_CLRKEYLOW_1_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYLOW_1_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYLOW_1_RSVD1)
+#define BP_PXP_PS_CLRKEYLOW_1_PIXEL 0
+#define BM_PXP_PS_CLRKEYLOW_1_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYLOW_1_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYLOW_1_PIXEL)
+
+#define HW_PXP_PS_CLRKEYHIGH_1 (0x000002e0)
+
+#define BP_PXP_PS_CLRKEYHIGH_1_RSVD1 24
+#define BM_PXP_PS_CLRKEYHIGH_1_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYHIGH_1_RSVD1(v) \
+ (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_1_RSVD1)
+#define BP_PXP_PS_CLRKEYHIGH_1_PIXEL 0
+#define BM_PXP_PS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYHIGH_1_PIXEL(v) \
+ (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_1_PIXEL)
+
+#define HW_PXP_AS_CLRKEYLOW_1 (0x000002f0)
+
+#define BP_PXP_AS_CLRKEYLOW_1_RSVD1 24
+#define BM_PXP_AS_CLRKEYLOW_1_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYLOW_1_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYLOW_1_RSVD1)
+#define BP_PXP_AS_CLRKEYLOW_1_PIXEL 0
+#define BM_PXP_AS_CLRKEYLOW_1_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYLOW_1_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYLOW_1_PIXEL)
+
+#define HW_PXP_AS_CLRKEYHIGH_1 (0x00000300)
+
+#define BP_PXP_AS_CLRKEYHIGH_1_RSVD1 24
+#define BM_PXP_AS_CLRKEYHIGH_1_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYHIGH_1_RSVD1(v) \
+ (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_1_RSVD1)
+#define BP_PXP_AS_CLRKEYHIGH_1_PIXEL 0
+#define BM_PXP_AS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYHIGH_1_PIXEL(v) \
+ (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_1_PIXEL)
+
+#define HW_PXP_CTRL2 (0x00000310)
+#define HW_PXP_CTRL2_SET (0x00000314)
+#define HW_PXP_CTRL2_CLR (0x00000318)
+#define HW_PXP_CTRL2_TOG (0x0000031c)
+
+#define BP_PXP_CTRL2_RSVD3 28
+#define BM_PXP_CTRL2_RSVD3 0xF0000000
+#define BF_PXP_CTRL2_RSVD3(v) \
+ (((v) << 28) & BM_PXP_CTRL2_RSVD3)
+#define BM_PXP_CTRL2_ENABLE_ROTATE1 0x08000000
+#define BF_PXP_CTRL2_ENABLE_ROTATE1(v) \
+ (((v) << 27) & BM_PXP_CTRL2_ENABLE_ROTATE1)
+#define BM_PXP_CTRL2_ENABLE_ROTATE0 0x04000000
+#define BF_PXP_CTRL2_ENABLE_ROTATE0(v) \
+ (((v) << 26) & BM_PXP_CTRL2_ENABLE_ROTATE0)
+#define BM_PXP_CTRL2_ENABLE_LUT 0x02000000
+#define BF_PXP_CTRL2_ENABLE_LUT(v) \
+ (((v) << 25) & BM_PXP_CTRL2_ENABLE_LUT)
+#define BM_PXP_CTRL2_ENABLE_CSC2 0x01000000
+#define BF_PXP_CTRL2_ENABLE_CSC2(v) \
+ (((v) << 24) & BM_PXP_CTRL2_ENABLE_CSC2)
+#define BM_PXP_CTRL2_BLOCK_SIZE 0x00800000
+#define BF_PXP_CTRL2_BLOCK_SIZE(v) \
+ (((v) << 23) & BM_PXP_CTRL2_BLOCK_SIZE)
+#define BV_PXP_CTRL2_BLOCK_SIZE__8X8 0x0
+#define BV_PXP_CTRL2_BLOCK_SIZE__16X16 0x1
+#define BM_PXP_CTRL2_RSVD2 0x00400000
+#define BF_PXP_CTRL2_RSVD2(v) \
+ (((v) << 22) & BM_PXP_CTRL2_RSVD2)
+#define BM_PXP_CTRL2_ENABLE_ALPHA_B 0x00200000
+#define BF_PXP_CTRL2_ENABLE_ALPHA_B(v) \
+ (((v) << 21) & BM_PXP_CTRL2_ENABLE_ALPHA_B)
+#define BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE 0x00100000
+#define BF_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE(v) \
+ (((v) << 20) & BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE)
+#define BM_PXP_CTRL2_ENABLE_WFE_B 0x00080000
+#define BF_PXP_CTRL2_ENABLE_WFE_B(v) \
+ (((v) << 19) & BM_PXP_CTRL2_ENABLE_WFE_B)
+#define BM_PXP_CTRL2_ENABLE_WFE_A 0x00040000
+#define BF_PXP_CTRL2_ENABLE_WFE_A(v) \
+ (((v) << 18) & BM_PXP_CTRL2_ENABLE_WFE_A)
+#define BM_PXP_CTRL2_ENABLE_DITHER 0x00020000
+#define BF_PXP_CTRL2_ENABLE_DITHER(v) \
+ (((v) << 17) & BM_PXP_CTRL2_ENABLE_DITHER)
+#define BM_PXP_CTRL2_RSVD1 0x00010000
+#define BF_PXP_CTRL2_RSVD1(v) \
+ (((v) << 16) & BM_PXP_CTRL2_RSVD1)
+#define BM_PXP_CTRL2_VFLIP1 0x00008000
+#define BF_PXP_CTRL2_VFLIP1(v) \
+ (((v) << 15) & BM_PXP_CTRL2_VFLIP1)
+#define BM_PXP_CTRL2_HFLIP1 0x00004000
+#define BF_PXP_CTRL2_HFLIP1(v) \
+ (((v) << 14) & BM_PXP_CTRL2_HFLIP1)
+#define BP_PXP_CTRL2_ROTATE1 12
+#define BM_PXP_CTRL2_ROTATE1 0x00003000
+#define BF_PXP_CTRL2_ROTATE1(v) \
+ (((v) << 12) & BM_PXP_CTRL2_ROTATE1)
+#define BV_PXP_CTRL2_ROTATE1__ROT_0 0x0
+#define BV_PXP_CTRL2_ROTATE1__ROT_90 0x1
+#define BV_PXP_CTRL2_ROTATE1__ROT_180 0x2
+#define BV_PXP_CTRL2_ROTATE1__ROT_270 0x3
+#define BM_PXP_CTRL2_VFLIP0 0x00000800
+#define BF_PXP_CTRL2_VFLIP0(v) \
+ (((v) << 11) & BM_PXP_CTRL2_VFLIP0)
+#define BM_PXP_CTRL2_HFLIP0 0x00000400
+#define BF_PXP_CTRL2_HFLIP0(v) \
+ (((v) << 10) & BM_PXP_CTRL2_HFLIP0)
+#define BP_PXP_CTRL2_ROTATE0 8
+#define BM_PXP_CTRL2_ROTATE0 0x00000300
+#define BF_PXP_CTRL2_ROTATE0(v) \
+ (((v) << 8) & BM_PXP_CTRL2_ROTATE0)
+#define BV_PXP_CTRL2_ROTATE0__ROT_0 0x0
+#define BV_PXP_CTRL2_ROTATE0__ROT_90 0x1
+#define BV_PXP_CTRL2_ROTATE0__ROT_180 0x2
+#define BV_PXP_CTRL2_ROTATE0__ROT_270 0x3
+#define BP_PXP_CTRL2_RSVD0 1
+#define BM_PXP_CTRL2_RSVD0 0x000000FE
+#define BF_PXP_CTRL2_RSVD0(v) \
+ (((v) << 1) & BM_PXP_CTRL2_RSVD0)
+#define BM_PXP_CTRL2_ENABLE 0x00000001
+#define BF_PXP_CTRL2_ENABLE(v) \
+ (((v) << 0) & BM_PXP_CTRL2_ENABLE)
+
+#define HW_PXP_POWER_REG0 (0x00000320)
+
+#define BP_PXP_POWER_REG0_CTRL 12
+#define BM_PXP_POWER_REG0_CTRL 0xFFFFF000
+#define BF_PXP_POWER_REG0_CTRL(v) \
+ (((v) << 12) & BM_PXP_POWER_REG0_CTRL)
+#define BP_PXP_POWER_REG0_ROT0_MEM_LP_STATE 9
+#define BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE 0x00000E00
+#define BF_PXP_POWER_REG0_ROT0_MEM_LP_STATE(v) \
+ (((v) << 9) & BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE)
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN 6
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN 0x000001C0
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN(v) \
+ (((v) << 6) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__LS 0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__DS 0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__SD 0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN 3
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN 0x00000038
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN(v) \
+ (((v) << 3) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__LS 0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__DS 0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__SD 0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0 0
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0 0x00000007
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0(v) \
+ (((v) << 0) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__LS 0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__DS 0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__SD 0x4
+
+#define HW_PXP_POWER_REG1 (0x00000330)
+
+#define BP_PXP_POWER_REG1_RSVD0 24
+#define BM_PXP_POWER_REG1_RSVD0 0xFF000000
+#define BF_PXP_POWER_REG1_RSVD0(v) \
+ (((v) << 24) & BM_PXP_POWER_REG1_RSVD0)
+#define BP_PXP_POWER_REG1_ALU_B_MEM_LP_STATE 21
+#define BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE 0x00E00000
+#define BF_PXP_POWER_REG1_ALU_B_MEM_LP_STATE(v) \
+ (((v) << 21) & BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_ALU_A_MEM_LP_STATE 18
+#define BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE 0x001C0000
+#define BF_PXP_POWER_REG1_ALU_A_MEM_LP_STATE(v) \
+ (((v) << 18) & BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE 15
+#define BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE 0x00038000
+#define BF_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE(v) \
+ (((v) << 15) & BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE 12
+#define BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE 0x00007000
+#define BF_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE(v) \
+ (((v) << 12) & BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE 9
+#define BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE 0x00000E00
+#define BF_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE(v) \
+ (((v) << 9) & BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE 6
+#define BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE 0x000001C0
+#define BF_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE(v) \
+ (((v) << 6) & BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE 3
+#define BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE 0x00000038
+#define BF_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE(v) \
+ (((v) << 3) & BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__SD 0x4
+#define BP_PXP_POWER_REG1_ROT1_MEM_LP_STATE 0
+#define BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE 0x00000007
+#define BF_PXP_POWER_REG1_ROT1_MEM_LP_STATE(v) \
+ (((v) << 0) & BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__LS 0x1
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__DS 0x2
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__SD 0x4
+
+#define HW_PXP_DATA_PATH_CTRL0 (0x00000340)
+#define HW_PXP_DATA_PATH_CTRL0_SET (0x00000344)
+#define HW_PXP_DATA_PATH_CTRL0_CLR (0x00000348)
+#define HW_PXP_DATA_PATH_CTRL0_TOG (0x0000034c)
+
+#define BP_PXP_DATA_PATH_CTRL0_MUX15_SEL 30
+#define BM_PXP_DATA_PATH_CTRL0_MUX15_SEL 0xC0000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(v) \
+ (((v) << 30) & BM_PXP_DATA_PATH_CTRL0_MUX15_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX14_SEL 28
+#define BM_PXP_DATA_PATH_CTRL0_MUX14_SEL 0x30000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(v) \
+ (((v) << 28) & BM_PXP_DATA_PATH_CTRL0_MUX14_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX13_SEL 26
+#define BM_PXP_DATA_PATH_CTRL0_MUX13_SEL 0x0C000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(v) \
+ (((v) << 26) & BM_PXP_DATA_PATH_CTRL0_MUX13_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX12_SEL 24
+#define BM_PXP_DATA_PATH_CTRL0_MUX12_SEL 0x03000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(v) \
+ (((v) << 24) & BM_PXP_DATA_PATH_CTRL0_MUX12_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX11_SEL 22
+#define BM_PXP_DATA_PATH_CTRL0_MUX11_SEL 0x00C00000
+#define BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(v) \
+ (((v) << 22) & BM_PXP_DATA_PATH_CTRL0_MUX11_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX10_SEL 20
+#define BM_PXP_DATA_PATH_CTRL0_MUX10_SEL 0x00300000
+#define BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(v) \
+ (((v) << 20) & BM_PXP_DATA_PATH_CTRL0_MUX10_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX9_SEL 18
+#define BM_PXP_DATA_PATH_CTRL0_MUX9_SEL 0x000C0000
+#define BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(v) \
+ (((v) << 18) & BM_PXP_DATA_PATH_CTRL0_MUX9_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX8_SEL 16
+#define BM_PXP_DATA_PATH_CTRL0_MUX8_SEL 0x00030000
+#define BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(v) \
+ (((v) << 16) & BM_PXP_DATA_PATH_CTRL0_MUX8_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX7_SEL 14
+#define BM_PXP_DATA_PATH_CTRL0_MUX7_SEL 0x0000C000
+#define BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(v) \
+ (((v) << 14) & BM_PXP_DATA_PATH_CTRL0_MUX7_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX6_SEL 12
+#define BM_PXP_DATA_PATH_CTRL0_MUX6_SEL 0x00003000
+#define BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(v) \
+ (((v) << 12) & BM_PXP_DATA_PATH_CTRL0_MUX6_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX5_SEL 10
+#define BM_PXP_DATA_PATH_CTRL0_MUX5_SEL 0x00000C00
+#define BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(v) \
+ (((v) << 10) & BM_PXP_DATA_PATH_CTRL0_MUX5_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX4_SEL 8
+#define BM_PXP_DATA_PATH_CTRL0_MUX4_SEL 0x00000300
+#define BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(v) \
+ (((v) << 8) & BM_PXP_DATA_PATH_CTRL0_MUX4_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX3_SEL 6
+#define BM_PXP_DATA_PATH_CTRL0_MUX3_SEL 0x000000C0
+#define BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(v) \
+ (((v) << 6) & BM_PXP_DATA_PATH_CTRL0_MUX3_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX2_SEL 4
+#define BM_PXP_DATA_PATH_CTRL0_MUX2_SEL 0x00000030
+#define BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(v) \
+ (((v) << 4) & BM_PXP_DATA_PATH_CTRL0_MUX2_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX1_SEL 2
+#define BM_PXP_DATA_PATH_CTRL0_MUX1_SEL 0x0000000C
+#define BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(v) \
+ (((v) << 2) & BM_PXP_DATA_PATH_CTRL0_MUX1_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX0_SEL 0
+#define BM_PXP_DATA_PATH_CTRL0_MUX0_SEL 0x00000003
+#define BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(v) \
+ (((v) << 0) & BM_PXP_DATA_PATH_CTRL0_MUX0_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__3 0x3
+
+#define HW_PXP_DATA_PATH_CTRL1 (0x00000350)
+#define HW_PXP_DATA_PATH_CTRL1_SET (0x00000354)
+#define HW_PXP_DATA_PATH_CTRL1_CLR (0x00000358)
+#define HW_PXP_DATA_PATH_CTRL1_TOG (0x0000035c)
+
+#define BP_PXP_DATA_PATH_CTRL1_RSVD0 4
+#define BM_PXP_DATA_PATH_CTRL1_RSVD0 0xFFFFFFF0
+#define BF_PXP_DATA_PATH_CTRL1_RSVD0(v) \
+ (((v) << 4) & BM_PXP_DATA_PATH_CTRL1_RSVD0)
+#define BP_PXP_DATA_PATH_CTRL1_MUX17_SEL 2
+#define BM_PXP_DATA_PATH_CTRL1_MUX17_SEL 0x0000000C
+#define BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(v) \
+ (((v) << 2) & BM_PXP_DATA_PATH_CTRL1_MUX17_SEL)
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL1_MUX16_SEL 0
+#define BM_PXP_DATA_PATH_CTRL1_MUX16_SEL 0x00000003
+#define BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(v) \
+ (((v) << 0) & BM_PXP_DATA_PATH_CTRL1_MUX16_SEL)
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__3 0x3
+
+#define HW_PXP_INIT_MEM_CTRL (0x00000360)
+#define HW_PXP_INIT_MEM_CTRL_SET (0x00000364)
+#define HW_PXP_INIT_MEM_CTRL_CLR (0x00000368)
+#define HW_PXP_INIT_MEM_CTRL_TOG (0x0000036c)
+
+#define BM_PXP_INIT_MEM_CTRL_START 0x80000000
+#define BF_PXP_INIT_MEM_CTRL_START(v) \
+ (((v) << 31) & BM_PXP_INIT_MEM_CTRL_START)
+#define BP_PXP_INIT_MEM_CTRL_SELECT 27
+#define BM_PXP_INIT_MEM_CTRL_SELECT 0x78000000
+#define BF_PXP_INIT_MEM_CTRL_SELECT(v) \
+ (((v) << 27) & BM_PXP_INIT_MEM_CTRL_SELECT)
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_LUT 0x0
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR0 0x1
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR1 0x2
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER1_LUT 0x3
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER2_LUT 0x4
+#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_A 0x5
+#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_B 0x6
+#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_A_FETCH 0x7
+#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_B_FETCH 0x8
+#define BV_PXP_INIT_MEM_CTRL_SELECT__RESERVED 0x15
+#define BP_PXP_INIT_MEM_CTRL_RSVD0 16
+#define BM_PXP_INIT_MEM_CTRL_RSVD0 0x07FF0000
+#define BF_PXP_INIT_MEM_CTRL_RSVD0(v) \
+ (((v) << 16) & BM_PXP_INIT_MEM_CTRL_RSVD0)
+#define BP_PXP_INIT_MEM_CTRL_ADDR 0
+#define BM_PXP_INIT_MEM_CTRL_ADDR 0x0000FFFF
+#define BF_PXP_INIT_MEM_CTRL_ADDR(v) \
+ (((v) << 0) & BM_PXP_INIT_MEM_CTRL_ADDR)
+
+#define HW_PXP_INIT_MEM_DATA (0x00000370)
+
+#define BP_PXP_INIT_MEM_DATA_DATA 0
+#define BM_PXP_INIT_MEM_DATA_DATA 0xFFFFFFFF
+#define BF_PXP_INIT_MEM_DATA_DATA(v) (v)
+
+#define HW_PXP_INIT_MEM_DATA_HIGH (0x00000380)
+
+#define BP_PXP_INIT_MEM_DATA_HIGH_DATA 0
+#define BM_PXP_INIT_MEM_DATA_HIGH_DATA 0xFFFFFFFF
+#define BF_PXP_INIT_MEM_DATA_HIGH_DATA(v) (v)
+
+#define HW_PXP_IRQ_MASK (0x00000390)
+#define HW_PXP_IRQ_MASK_SET (0x00000394)
+#define HW_PXP_IRQ_MASK_CLR (0x00000398)
+#define HW_PXP_IRQ_MASK_TOG (0x0000039c)
+
+#define BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN 0x80000000
+#define BF_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN(v) \
+ (((v) << 31) & BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN)
+#define BP_PXP_IRQ_MASK_RSVD1 16
+#define BM_PXP_IRQ_MASK_RSVD1 0x7FFF0000
+#define BF_PXP_IRQ_MASK_RSVD1(v) \
+ (((v) << 16) & BM_PXP_IRQ_MASK_RSVD1)
+#define BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN 0x00008000
+#define BF_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN(v) \
+ (((v) << 15) & BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN 0x00004000
+#define BF_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN(v) \
+ (((v) << 14) & BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN 0x00002000
+#define BF_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN(v) \
+ (((v) << 13) & BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN 0x00001000
+#define BF_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN(v) \
+ (((v) << 12) & BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN 0x00000800
+#define BF_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN(v) \
+ (((v) << 11) & BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN 0x00000400
+#define BF_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN(v) \
+ (((v) << 10) & BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN 0x00000200
+#define BF_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN(v) \
+ (((v) << 9) & BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN 0x00000100
+#define BF_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN(v) \
+ (((v) << 8) & BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN 0x00000080
+#define BF_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN(v) \
+ (((v) << 7) & BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN 0x00000040
+#define BF_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN(v) \
+ (((v) << 6) & BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN 0x00000020
+#define BF_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN(v) \
+ (((v) << 5) & BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN 0x00000010
+#define BF_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN(v) \
+ (((v) << 4) & BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN 0x00000008
+#define BF_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN(v) \
+ (((v) << 3) & BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN 0x00000004
+#define BF_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN(v) \
+ (((v) << 2) & BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN 0x00000002
+#define BF_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN(v) \
+ (((v) << 1) & BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN 0x00000001
+#define BF_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN(v) \
+ (((v) << 0) & BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN)
+
+#define HW_PXP_IRQ (0x000003a0)
+#define HW_PXP_IRQ_SET (0x000003a4)
+#define HW_PXP_IRQ_CLR (0x000003a8)
+#define HW_PXP_IRQ_TOG (0x000003ac)
+
+#define BM_PXP_IRQ_COMPRESS_DONE_IRQ 0x80000000
+#define BF_PXP_IRQ_COMPRESS_DONE_IRQ(v) \
+ (((v) << 31) & BM_PXP_IRQ_COMPRESS_DONE_IRQ)
+#define BP_PXP_IRQ_RSVD1 16
+#define BM_PXP_IRQ_RSVD1 0x7FFF0000
+#define BF_PXP_IRQ_RSVD1(v) \
+ (((v) << 16) & BM_PXP_IRQ_RSVD1)
+#define BM_PXP_IRQ_WFE_B_STORE_IRQ 0x00008000
+#define BF_PXP_IRQ_WFE_B_STORE_IRQ(v) \
+ (((v) << 15) & BM_PXP_IRQ_WFE_B_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_STORE_IRQ 0x00004000
+#define BF_PXP_IRQ_WFE_A_STORE_IRQ(v) \
+ (((v) << 14) & BM_PXP_IRQ_WFE_A_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_STORE_IRQ 0x00002000
+#define BF_PXP_IRQ_DITHER_STORE_IRQ(v) \
+ (((v) << 13) & BM_PXP_IRQ_DITHER_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_STORE_IRQ 0x00001000
+#define BF_PXP_IRQ_FIRST_STORE_IRQ(v) \
+ (((v) << 12) & BM_PXP_IRQ_FIRST_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ 0x00000800
+#define BF_PXP_IRQ_WFE_B_CH1_STORE_IRQ(v) \
+ (((v) << 11) & BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ 0x00000400
+#define BF_PXP_IRQ_WFE_B_CH0_STORE_IRQ(v) \
+ (((v) << 10) & BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ 0x00000200
+#define BF_PXP_IRQ_WFE_A_CH1_STORE_IRQ(v) \
+ (((v) << 9) & BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ 0x00000100
+#define BF_PXP_IRQ_WFE_A_CH0_STORE_IRQ(v) \
+ (((v) << 8) & BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH1_STORE_IRQ 0x00000080
+#define BF_PXP_IRQ_DITHER_CH1_STORE_IRQ(v) \
+ (((v) << 7) & BM_PXP_IRQ_DITHER_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH0_STORE_IRQ 0x00000040
+#define BF_PXP_IRQ_DITHER_CH0_STORE_IRQ(v) \
+ (((v) << 6) & BM_PXP_IRQ_DITHER_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ 0x00000020
+#define BF_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ(v) \
+ (((v) << 5) & BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ)
+#define BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ 0x00000010
+#define BF_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ(v) \
+ (((v) << 4) & BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ)
+#define BM_PXP_IRQ_FIRST_CH1_STORE_IRQ 0x00000008
+#define BF_PXP_IRQ_FIRST_CH1_STORE_IRQ(v) \
+ (((v) << 3) & BM_PXP_IRQ_FIRST_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_CH0_STORE_IRQ 0x00000004
+#define BF_PXP_IRQ_FIRST_CH0_STORE_IRQ(v) \
+ (((v) << 2) & BM_PXP_IRQ_FIRST_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ 0x00000002
+#define BF_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ(v) \
+ (((v) << 1) & BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ)
+#define BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ 0x00000001
+#define BF_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ(v) \
+ (((v) << 0) & BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ)
+
+#define HW_PXP_NEXT (0x00000400)
+
+#define BP_PXP_NEXT_POINTER 2
+#define BM_PXP_NEXT_POINTER 0xFFFFFFFC
+#define BF_PXP_NEXT_POINTER(v) \
+ (((v) << 2) & BM_PXP_NEXT_POINTER)
+#define BM_PXP_NEXT_RSVD 0x00000002
+#define BF_PXP_NEXT_RSVD(v) \
+ (((v) << 1) & BM_PXP_NEXT_RSVD)
+#define BM_PXP_NEXT_ENABLED 0x00000001
+#define BF_PXP_NEXT_ENABLED(v) \
+ (((v) << 0) & BM_PXP_NEXT_ENABLED)
+
+#define HW_PXP_DEBUGCTRL (0x00000410)
+
+#define BP_PXP_DEBUGCTRL_RSVD 12
+#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000
+#define BF_PXP_DEBUGCTRL_RSVD(v) \
+ (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD)
+#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 8
+#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00
+#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v) \
+ (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT)
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE 0x0
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT 0x2
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT 0x4
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT 0x8
+#define BP_PXP_DEBUGCTRL_SELECT 0
+#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF
+#define BF_PXP_DEBUGCTRL_SELECT(v) \
+ (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT)
+#define BV_PXP_DEBUGCTRL_SELECT__NONE 0x0
+#define BV_PXP_DEBUGCTRL_SELECT__CTRL 0x1
+#define BV_PXP_DEBUGCTRL_SELECT__PSBUF 0x2
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAX 0x3
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAY 0x4
+#define BV_PXP_DEBUGCTRL_SELECT__ASBUF 0x5
+#define BV_PXP_DEBUGCTRL_SELECT__ROTATION 0x6
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0 0x7
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1 0x8
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2 0x9
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT 0x10
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS 0x11
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT 0x12
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT 0x13
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14
+
+#define HW_PXP_DEBUG (0x00000420)
+
+#define BP_PXP_DEBUG_DATA 0
+#define BM_PXP_DEBUG_DATA 0xFFFFFFFF
+#define BF_PXP_DEBUG_DATA(v) (v)
+
+#define HW_PXP_VERSION (0x00000430)
+
+#define BP_PXP_VERSION_MAJOR 24
+#define BM_PXP_VERSION_MAJOR 0xFF000000
+#define BF_PXP_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_PXP_VERSION_MAJOR)
+#define BP_PXP_VERSION_MINOR 16
+#define BM_PXP_VERSION_MINOR 0x00FF0000
+#define BF_PXP_VERSION_MINOR(v) \
+ (((v) << 16) & BM_PXP_VERSION_MINOR)
+#define BP_PXP_VERSION_STEP 0
+#define BM_PXP_VERSION_STEP 0x0000FFFF
+#define BF_PXP_VERSION_STEP(v) \
+ (((v) << 0) & BM_PXP_VERSION_STEP)
+
+#define HW_PXP_INPUT_FETCH_CTRL_CH0 (0x00000450)
+#define HW_PXP_INPUT_FETCH_CTRL_CH0_SET (0x00000454)
+#define HW_PXP_INPUT_FETCH_CTRL_CH0_CLR (0x00000458)
+#define HW_PXP_INPUT_FETCH_CTRL_CH0_TOG (0x0000045c)
+
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_ARBIT_EN 0x80000000
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_ARBIT_EN(v) \
+ (((v) << 31) & BM_PXP_INPUT_FETCH_CTRL_CH0_ARBIT_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_ARBIT_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_ARBIT_EN__1 0x1
+#define BP_PXP_INPUT_FETCH_CTRL_CH0_RSVD0 26
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD0 0x7C000000
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_RSVD0(v) \
+ (((v) << 26) & BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD0)
+#define BP_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM 24
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM 0x03000000
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM(v) \
+ (((v) << 24) & BM_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM__1 0x1
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM__2 0x2
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM__3 0x3
+#define BP_PXP_INPUT_FETCH_CTRL_CH0_RSVD1 18
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD1 0x00FC0000
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_RSVD1(v) \
+ (((v) << 18) & BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD1)
+#define BP_PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES 16
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES 0x00030000
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_INPUT_FETCH_CTRL_CH0_RSVD2 14
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD2 0x0000C000
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD2)
+#define BP_PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE 12
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE 0x00003000
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE(v) \
+ (((v) << 12) & BM_PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE__ROT_0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE__ROT_90 0x1
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE__ROT_180 0x2
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE__ROT_270 0x3
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD3 0x00000800
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_RSVD3(v) \
+ (((v) << 11) & BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD3)
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_VFLIP 0x00000400
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_VFLIP(v) \
+ (((v) << 10) & BM_PXP_INPUT_FETCH_CTRL_CH0_VFLIP)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_VFLIP__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_VFLIP__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_HFLIP 0x00000200
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_HFLIP(v) \
+ (((v) << 9) & BM_PXP_INPUT_FETCH_CTRL_CH0_HFLIP)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HFLIP__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HFLIP__1 0x1
+#define BP_PXP_INPUT_FETCH_CTRL_CH0_RSVD4 6
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD4 0x000001C0
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_RSVD4(v) \
+ (((v) << 6) & BM_PXP_INPUT_FETCH_CTRL_CH0_RSVD4)
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_HIGH_BYTE 0x00000020
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_HIGH_BYTE(v) \
+ (((v) << 5) & BM_PXP_INPUT_FETCH_CTRL_CH0_HIGH_BYTE)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HIGH_BYTE__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HIGH_BYTE__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_BYPASS_PIXEL_EN 0x00000010
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_BYPASS_PIXEL_EN(v) \
+ (((v) << 4) & BM_PXP_INPUT_FETCH_CTRL_CH0_BYPASS_PIXEL_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_BYPASS_PIXEL_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_BYPASS_PIXEL_EN__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_EN 0x00000008
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_EN__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_16 0x00000004
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_16)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_16__8x8 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_16__16x16 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_EN 0x00000002
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_BLOCK_EN__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH0_CH_EN 0x00000001
+#define BF_PXP_INPUT_FETCH_CTRL_CH0_CH_EN(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_CTRL_CH0_CH_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_CH_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH0_CH_EN__1 0x1
+
+#define HW_PXP_INPUT_FETCH_CTRL_CH1 (0x00000460)
+#define HW_PXP_INPUT_FETCH_CTRL_CH1_SET (0x00000464)
+#define HW_PXP_INPUT_FETCH_CTRL_CH1_CLR (0x00000468)
+#define HW_PXP_INPUT_FETCH_CTRL_CH1_TOG (0x0000046c)
+
+#define BP_PXP_INPUT_FETCH_CTRL_CH1_RSVD0 26
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD0 0xFC000000
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_RSVD0(v) \
+ (((v) << 26) & BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD0)
+#define BP_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM 24
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM 0x03000000
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM(v) \
+ (((v) << 24) & BM_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM__1 0x1
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM__2 0x2
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM__3 0x3
+#define BP_PXP_INPUT_FETCH_CTRL_CH1_RSVD1 18
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD1 0x00FC0000
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_RSVD1(v) \
+ (((v) << 18) & BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD1)
+#define BP_PXP_INPUT_FETCH_CTRL_CH1_RD_NUM_BYTES 16
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_RD_NUM_BYTES 0x00030000
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_RD_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_CTRL_CH1_RD_NUM_BYTES)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_RD_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_RD_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_RD_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_RD_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_INPUT_FETCH_CTRL_CH1_RSVD2 14
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD2 0x0000C000
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD2)
+#define BP_PXP_INPUT_FETCH_CTRL_CH1_ROTATION_ANGLE 12
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_ROTATION_ANGLE 0x00003000
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_ROTATION_ANGLE(v) \
+ (((v) << 12) & BM_PXP_INPUT_FETCH_CTRL_CH1_ROTATION_ANGLE)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_ROTATION_ANGLE__ROT_0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_ROTATION_ANGLE__ROT_90 0x1
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_ROTATION_ANGLE__ROT_180 0x2
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_ROTATION_ANGLE__ROT_270 0x3
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD3 0x00000800
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_RSVD3(v) \
+ (((v) << 11) & BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD3)
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_VFLIP 0x00000400
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_VFLIP(v) \
+ (((v) << 10) & BM_PXP_INPUT_FETCH_CTRL_CH1_VFLIP)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_VFLIP__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_VFLIP__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_HFLIP 0x00000200
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_HFLIP(v) \
+ (((v) << 9) & BM_PXP_INPUT_FETCH_CTRL_CH1_HFLIP)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_HFLIP__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_HFLIP__1 0x1
+#define BP_PXP_INPUT_FETCH_CTRL_CH1_RSVD4 5
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD4 0x000001E0
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_RSVD4(v) \
+ (((v) << 5) & BM_PXP_INPUT_FETCH_CTRL_CH1_RSVD4)
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_BYPASS_PIXEL_EN 0x00000010
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_BYPASS_PIXEL_EN(v) \
+ (((v) << 4) & BM_PXP_INPUT_FETCH_CTRL_CH1_BYPASS_PIXEL_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_BYPASS_PIXEL_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_BYPASS_PIXEL_EN__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_EN 0x00000008
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_HANDSHAKE_EN__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_16 0x00000004
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_16)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_16__8x8 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_16__16x16 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_EN 0x00000002
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_BLOCK_EN__1 0x1
+#define BM_PXP_INPUT_FETCH_CTRL_CH1_CH_EN 0x00000001
+#define BF_PXP_INPUT_FETCH_CTRL_CH1_CH_EN(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_CTRL_CH1_CH_EN)
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_CH_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_CTRL_CH1_CH_EN__1 0x1
+
+#define HW_PXP_INPUT_FETCH_STATUS_CH0 (0x00000470)
+
+#define BP_PXP_INPUT_FETCH_STATUS_CH0_PREFETCH_BLOCK_Y 16
+#define BM_PXP_INPUT_FETCH_STATUS_CH0_PREFETCH_BLOCK_Y 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_STATUS_CH0_PREFETCH_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_STATUS_CH0_PREFETCH_BLOCK_Y)
+#define BP_PXP_INPUT_FETCH_STATUS_CH0_PREFETCH_BLOCK_X 0
+#define BM_PXP_INPUT_FETCH_STATUS_CH0_PREFETCH_BLOCK_X 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_STATUS_CH0_PREFETCH_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_STATUS_CH0_PREFETCH_BLOCK_X)
+
+#define HW_PXP_INPUT_FETCH_STATUS_CH1 (0x00000480)
+
+#define BP_PXP_INPUT_FETCH_STATUS_CH1_PREFETCH_BLOCK_Y 16
+#define BM_PXP_INPUT_FETCH_STATUS_CH1_PREFETCH_BLOCK_Y 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_STATUS_CH1_PREFETCH_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_STATUS_CH1_PREFETCH_BLOCK_Y)
+#define BP_PXP_INPUT_FETCH_STATUS_CH1_PREFETCH_BLOCK_X 0
+#define BM_PXP_INPUT_FETCH_STATUS_CH1_PREFETCH_BLOCK_X 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_STATUS_CH1_PREFETCH_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_STATUS_CH1_PREFETCH_BLOCK_X)
+
+#define HW_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0 (0x00000490)
+
+#define BP_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y 16
+#define BM_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y)
+#define BP_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X 0
+#define BM_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X)
+
+#define HW_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0 (0x000004a0)
+
+#define BP_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y 16
+#define BM_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y)
+#define BP_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X 0
+#define BM_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X)
+
+#define HW_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1 (0x000004b0)
+
+#define BP_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y 16
+#define BM_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y)
+#define BP_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X 0
+#define BM_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X)
+
+#define HW_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1 (0x000004c0)
+
+#define BP_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y 16
+#define BM_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y)
+#define BP_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X 0
+#define BM_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X)
+
+#define HW_PXP_INPUT_FETCH_SIZE_CH0 (0x000004d0)
+
+#define BP_PXP_INPUT_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT 16
+#define BM_PXP_INPUT_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT)
+#define BP_PXP_INPUT_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH 0
+#define BM_PXP_INPUT_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH)
+
+#define HW_PXP_INPUT_FETCH_SIZE_CH1 (0x000004e0)
+
+#define BP_PXP_INPUT_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT 16
+#define BM_PXP_INPUT_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT)
+#define BP_PXP_INPUT_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH 0
+#define BM_PXP_INPUT_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH)
+
+#define HW_PXP_INPUT_FETCH_BACKGROUND_COLOR_CH0 (0x000004f0)
+
+#define BP_PXP_INPUT_FETCH_BACKGROUND_COLOR_CH0_BACKGROUND_COLOR 0
+#define BM_PXP_INPUT_FETCH_BACKGROUND_COLOR_CH0_BACKGROUND_COLOR 0xFFFFFFFF
+#define BF_PXP_INPUT_FETCH_BACKGROUND_COLOR_CH0_BACKGROUND_COLOR(v) (v)
+
+#define HW_PXP_INPUT_FETCH_BACKGROUND_COLOR_CH1 (0x00000500)
+
+#define BP_PXP_INPUT_FETCH_BACKGROUND_COLOR_CH1_BACKGROUND_COLOR 0
+#define BM_PXP_INPUT_FETCH_BACKGROUND_COLOR_CH1_BACKGROUND_COLOR 0xFFFFFFFF
+#define BF_PXP_INPUT_FETCH_BACKGROUND_COLOR_CH1_BACKGROUND_COLOR(v) (v)
+
+#define HW_PXP_INPUT_FETCH_PITCH (0x00000510)
+
+#define BP_PXP_INPUT_FETCH_PITCH_CH1_INPUT_PITCH 16
+#define BM_PXP_INPUT_FETCH_PITCH_CH1_INPUT_PITCH 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_PITCH_CH1_INPUT_PITCH(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_PITCH_CH1_INPUT_PITCH)
+#define BP_PXP_INPUT_FETCH_PITCH_CH0_INPUT_PITCH 0
+#define BM_PXP_INPUT_FETCH_PITCH_CH0_INPUT_PITCH 0x0000FFFF
+#define BF_PXP_INPUT_FETCH_PITCH_CH0_INPUT_PITCH(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_PITCH_CH0_INPUT_PITCH)
+
+#define HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH0 (0x00000520)
+#define HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_SET (0x00000524)
+#define HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_CLR (0x00000528)
+#define HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_TOG (0x0000052c)
+
+#define BP_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_RSVD0 13
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_RSVD0 0xFFFFE000
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_RSVD0(v) \
+ (((v) << 13) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_RSVD0)
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS 0x00001000
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS(v) \
+ (((v) << 12) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS)
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS__0 0x0
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS__1 0x1
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_EN 0x00000800
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_EN(v) \
+ (((v) << 11) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_EN)
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_EN__1 0x1
+#define BP_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT 8
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT 0x00000700
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT(v) \
+ (((v) << 8) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT)
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__0 0x0
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__1 0x1
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__2 0x2
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__3 0x3
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__4 0x4
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__5 0x5
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__6 0x6
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__7 0x7
+#define BP_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_RSVD1 2
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_RSVD1 0x000000FC
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_RSVD1(v) \
+ (((v) << 2) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_RSVD1)
+#define BP_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP 0
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP 0x00000003
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP)
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP__3 0x3
+
+#define HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH1 (0x00000530)
+#define HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_SET (0x00000534)
+#define HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_CLR (0x00000538)
+#define HW_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_TOG (0x0000053c)
+
+#define BP_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_RSVD0 13
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_RSVD0 0xFFFFE000
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_RSVD0(v) \
+ (((v) << 13) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_RSVD0)
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS 0x00001000
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS(v) \
+ (((v) << 12) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS)
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS__0 0x0
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS__1 0x1
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_EN 0x00000800
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_EN(v) \
+ (((v) << 11) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_EN)
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_EN__0 0x0
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_EN__1 0x1
+#define BP_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT 8
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT 0x00000700
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT(v) \
+ (((v) << 8) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT)
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__0 0x0
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__1 0x1
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__2 0x2
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__3 0x3
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__4 0x4
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__5 0x5
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__6 0x6
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__7 0x7
+#define BP_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_RSVD1 2
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_RSVD1 0x000000FC
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_RSVD1(v) \
+ (((v) << 2) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_RSVD1)
+#define BP_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP 0
+#define BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP 0x00000003
+#define BF_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP)
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_INPUT_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP__3 0x3
+
+#define HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0 (0x00000540)
+#define HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_SET (0x00000544)
+#define HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_CLR (0x00000548)
+#define HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_TOG (0x0000054c)
+
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD0 29
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD0 0xE0000000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD0(v) \
+ (((v) << 29) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD0)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET3 24
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET3 0x1F000000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET3(v) \
+ (((v) << 24) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET3)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD1 21
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD1 0x00E00000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD1(v) \
+ (((v) << 21) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD1)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET2 16
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET2 0x001F0000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET2(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET2)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD2 13
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD2 0x0000E000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD2(v) \
+ (((v) << 13) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD2)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET1 8
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET1 0x00001F00
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET1(v) \
+ (((v) << 8) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET1)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD3 5
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD3 0x000000E0
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD3(v) \
+ (((v) << 5) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_RSVD3)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET0 0
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET0 0x0000001F
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET0(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH0_OFFSET0)
+
+#define HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1 (0x00000550)
+#define HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_SET (0x00000554)
+#define HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_CLR (0x00000558)
+#define HW_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_TOG (0x0000055c)
+
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD0 29
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD0 0xE0000000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD0(v) \
+ (((v) << 29) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD0)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET3 24
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET3 0x1F000000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET3(v) \
+ (((v) << 24) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET3)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD1 21
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD1 0x00E00000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD1(v) \
+ (((v) << 21) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD1)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET2 16
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET2 0x001F0000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET2(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET2)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD2 13
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD2 0x0000E000
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD2(v) \
+ (((v) << 13) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD2)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET1 8
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET1 0x00001F00
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET1(v) \
+ (((v) << 8) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET1)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD3 5
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD3 0x000000E0
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD3(v) \
+ (((v) << 5) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_RSVD3)
+#define BP_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET0 0
+#define BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET0 0x0000001F
+#define BF_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET0(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_SHIFT_OFFSET_CH1_OFFSET0)
+
+#define HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0 (0x00000560)
+#define HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_SET (0x00000564)
+#define HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_CLR (0x00000568)
+#define HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_TOG (0x0000056c)
+
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_RSVD0 16
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_RSVD0 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_RSVD0(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_RSVD0)
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH3 12
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH3 0x0000F000
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH3(v) \
+ (((v) << 12) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH3)
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH2 8
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH2 0x00000F00
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH2(v) \
+ (((v) << 8) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH2)
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH1 4
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH1 0x000000F0
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH1(v) \
+ (((v) << 4) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH1)
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH0 0
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH0 0x0000000F
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH0_WIDTH0)
+
+#define HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1 (0x00000570)
+#define HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_SET (0x00000574)
+#define HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_CLR (0x00000578)
+#define HW_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_TOG (0x0000057c)
+
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_RSVD0 16
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_RSVD0 0xFFFF0000
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_RSVD0(v) \
+ (((v) << 16) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_RSVD0)
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH3 12
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH3 0x0000F000
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH3(v) \
+ (((v) << 12) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH3)
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH2 8
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH2 0x00000F00
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH2(v) \
+ (((v) << 8) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH2)
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH1 4
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH1 0x000000F0
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH1(v) \
+ (((v) << 4) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH1)
+#define BP_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH0 0
+#define BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH0 0x0000000F
+#define BF_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_INPUT_FETCH_SHIFT_WIDTH_CH1_WIDTH0)
+
+#define HW_PXP_INPUT_FETCH_ADDR_0_CH0 (0x00000580)
+
+#define BP_PXP_INPUT_FETCH_ADDR_0_CH0_INPUT_BASE_ADDR0 0
+#define BM_PXP_INPUT_FETCH_ADDR_0_CH0_INPUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_INPUT_FETCH_ADDR_0_CH0_INPUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_INPUT_FETCH_ADDR_1_CH0 (0x00000590)
+
+#define BP_PXP_INPUT_FETCH_ADDR_1_CH0_INPUT_BASE_ADDR1 0
+#define BM_PXP_INPUT_FETCH_ADDR_1_CH0_INPUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_INPUT_FETCH_ADDR_1_CH0_INPUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_INPUT_FETCH_ADDR_0_CH1 (0x000005a0)
+
+#define BP_PXP_INPUT_FETCH_ADDR_0_CH1_INPUT_BASE_ADDR0 0
+#define BM_PXP_INPUT_FETCH_ADDR_0_CH1_INPUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_INPUT_FETCH_ADDR_0_CH1_INPUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_INPUT_FETCH_ADDR_1_CH1 (0x000005b0)
+
+#define BP_PXP_INPUT_FETCH_ADDR_1_CH1_INPUT_BASE_ADDR1 0
+#define BM_PXP_INPUT_FETCH_ADDR_1_CH1_INPUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_INPUT_FETCH_ADDR_1_CH1_INPUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_INPUT_STORE_CTRL_CH0 (0x000005c0)
+#define HW_PXP_INPUT_STORE_CTRL_CH0_SET (0x000005c4)
+#define HW_PXP_INPUT_STORE_CTRL_CH0_CLR (0x000005c8)
+#define HW_PXP_INPUT_STORE_CTRL_CH0_TOG (0x000005cc)
+
+#define BM_PXP_INPUT_STORE_CTRL_CH0_ARBIT_EN 0x80000000
+#define BF_PXP_INPUT_STORE_CTRL_CH0_ARBIT_EN(v) \
+ (((v) << 31) & BM_PXP_INPUT_STORE_CTRL_CH0_ARBIT_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_ARBIT_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_ARBIT_EN__1 0x1
+#define BP_PXP_INPUT_STORE_CTRL_CH0_RSVD0 25
+#define BM_PXP_INPUT_STORE_CTRL_CH0_RSVD0 0x7E000000
+#define BF_PXP_INPUT_STORE_CTRL_CH0_RSVD0(v) \
+ (((v) << 25) & BM_PXP_INPUT_STORE_CTRL_CH0_RSVD0)
+#define BM_PXP_INPUT_STORE_CTRL_CH0_COMBINE_2CHANNEL 0x01000000
+#define BF_PXP_INPUT_STORE_CTRL_CH0_COMBINE_2CHANNEL(v) \
+ (((v) << 24) & BM_PXP_INPUT_STORE_CTRL_CH0_COMBINE_2CHANNEL)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_COMBINE_2CHANNEL__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_COMBINE_2CHANNEL__1 0x1
+#define BP_PXP_INPUT_STORE_CTRL_CH0_RSVD1 18
+#define BM_PXP_INPUT_STORE_CTRL_CH0_RSVD1 0x00FC0000
+#define BF_PXP_INPUT_STORE_CTRL_CH0_RSVD1(v) \
+ (((v) << 18) & BM_PXP_INPUT_STORE_CTRL_CH0_RSVD1)
+#define BP_PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES 16
+#define BM_PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES 0x00030000
+#define BF_PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_INPUT_STORE_CTRL_CH0_RSVD2 12
+#define BM_PXP_INPUT_STORE_CTRL_CH0_RSVD2 0x0000F000
+#define BF_PXP_INPUT_STORE_CTRL_CH0_RSVD2(v) \
+ (((v) << 12) & BM_PXP_INPUT_STORE_CTRL_CH0_RSVD2)
+#define BM_PXP_INPUT_STORE_CTRL_CH0_FILL_DATA_EN 0x00000800
+#define BF_PXP_INPUT_STORE_CTRL_CH0_FILL_DATA_EN(v) \
+ (((v) << 11) & BM_PXP_INPUT_STORE_CTRL_CH0_FILL_DATA_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_FILL_DATA_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_FILL_DATA_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH0_PACK_IN_SEL 0x00000400
+#define BF_PXP_INPUT_STORE_CTRL_CH0_PACK_IN_SEL(v) \
+ (((v) << 10) & BM_PXP_INPUT_STORE_CTRL_CH0_PACK_IN_SEL)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_PACK_IN_SEL__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_PACK_IN_SEL__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH0_STORE_MEMORY_EN 0x00000200
+#define BF_PXP_INPUT_STORE_CTRL_CH0_STORE_MEMORY_EN(v) \
+ (((v) << 9) & BM_PXP_INPUT_STORE_CTRL_CH0_STORE_MEMORY_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_STORE_MEMORY_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_STORE_MEMORY_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH0_STORE_BYPASS_EN 0x00000100
+#define BF_PXP_INPUT_STORE_CTRL_CH0_STORE_BYPASS_EN(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_CTRL_CH0_STORE_BYPASS_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_STORE_BYPASS_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_STORE_BYPASS_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH0_RSVD3 0x00000080
+#define BF_PXP_INPUT_STORE_CTRL_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_INPUT_STORE_CTRL_CH0_RSVD3)
+#define BP_PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM 5
+#define BM_PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM 0x00000060
+#define BF_PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM(v) \
+ (((v) << 5) & BM_PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM__1 0x1
+#define BV_PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM__2 0x2
+#define BV_PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM__3 0x3
+#define BM_PXP_INPUT_STORE_CTRL_CH0_ARRAY_EN 0x00000010
+#define BF_PXP_INPUT_STORE_CTRL_CH0_ARRAY_EN(v) \
+ (((v) << 4) & BM_PXP_INPUT_STORE_CTRL_CH0_ARRAY_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_ARRAY_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_ARRAY_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH0_HANDSHAKE_EN 0x00000008
+#define BF_PXP_INPUT_STORE_CTRL_CH0_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_INPUT_STORE_CTRL_CH0_HANDSHAKE_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_HANDSHAKE_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_HANDSHAKE_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH0_BLOCK_16 0x00000004
+#define BF_PXP_INPUT_STORE_CTRL_CH0_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_INPUT_STORE_CTRL_CH0_BLOCK_16)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_BLOCK_16__8x8 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_BLOCK_16__16x16 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH0_BLOCK_EN 0x00000002
+#define BF_PXP_INPUT_STORE_CTRL_CH0_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_INPUT_STORE_CTRL_CH0_BLOCK_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_BLOCK_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_BLOCK_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH0_CH_EN 0x00000001
+#define BF_PXP_INPUT_STORE_CTRL_CH0_CH_EN(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_CTRL_CH0_CH_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH0_CH_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH0_CH_EN__1 0x1
+
+#define HW_PXP_INPUT_STORE_CTRL_CH1 (0x000005d0)
+#define HW_PXP_INPUT_STORE_CTRL_CH1_SET (0x000005d4)
+#define HW_PXP_INPUT_STORE_CTRL_CH1_CLR (0x000005d8)
+#define HW_PXP_INPUT_STORE_CTRL_CH1_TOG (0x000005dc)
+
+#define BP_PXP_INPUT_STORE_CTRL_CH1_RSVD0 18
+#define BM_PXP_INPUT_STORE_CTRL_CH1_RSVD0 0xFFFC0000
+#define BF_PXP_INPUT_STORE_CTRL_CH1_RSVD0(v) \
+ (((v) << 18) & BM_PXP_INPUT_STORE_CTRL_CH1_RSVD0)
+#define BP_PXP_INPUT_STORE_CTRL_CH1_WR_NUM_BYTES 16
+#define BM_PXP_INPUT_STORE_CTRL_CH1_WR_NUM_BYTES 0x00030000
+#define BF_PXP_INPUT_STORE_CTRL_CH1_WR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_CTRL_CH1_WR_NUM_BYTES)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_INPUT_STORE_CTRL_CH1_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_INPUT_STORE_CTRL_CH1_WR_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_INPUT_STORE_CTRL_CH1_RSVD1 11
+#define BM_PXP_INPUT_STORE_CTRL_CH1_RSVD1 0x0000F800
+#define BF_PXP_INPUT_STORE_CTRL_CH1_RSVD1(v) \
+ (((v) << 11) & BM_PXP_INPUT_STORE_CTRL_CH1_RSVD1)
+#define BM_PXP_INPUT_STORE_CTRL_CH1_PACK_IN_SEL 0x00000400
+#define BF_PXP_INPUT_STORE_CTRL_CH1_PACK_IN_SEL(v) \
+ (((v) << 10) & BM_PXP_INPUT_STORE_CTRL_CH1_PACK_IN_SEL)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_PACK_IN_SEL__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_PACK_IN_SEL__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH1_STORE_MEMORY_EN 0x00000200
+#define BF_PXP_INPUT_STORE_CTRL_CH1_STORE_MEMORY_EN(v) \
+ (((v) << 9) & BM_PXP_INPUT_STORE_CTRL_CH1_STORE_MEMORY_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_STORE_MEMORY_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_STORE_MEMORY_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH1_STORE_BYPASS_EN 0x00000100
+#define BF_PXP_INPUT_STORE_CTRL_CH1_STORE_BYPASS_EN(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_CTRL_CH1_STORE_BYPASS_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_STORE_BYPASS_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_STORE_BYPASS_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH1_RSVD3 0x00000080
+#define BF_PXP_INPUT_STORE_CTRL_CH1_RSVD3(v) \
+ (((v) << 7) & BM_PXP_INPUT_STORE_CTRL_CH1_RSVD3)
+#define BP_PXP_INPUT_STORE_CTRL_CH1_ARRAY_LINE_NUM 5
+#define BM_PXP_INPUT_STORE_CTRL_CH1_ARRAY_LINE_NUM 0x00000060
+#define BF_PXP_INPUT_STORE_CTRL_CH1_ARRAY_LINE_NUM(v) \
+ (((v) << 5) & BM_PXP_INPUT_STORE_CTRL_CH1_ARRAY_LINE_NUM)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_ARRAY_LINE_NUM__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_ARRAY_LINE_NUM__1 0x1
+#define BV_PXP_INPUT_STORE_CTRL_CH1_ARRAY_LINE_NUM__2 0x2
+#define BV_PXP_INPUT_STORE_CTRL_CH1_ARRAY_LINE_NUM__3 0x3
+#define BM_PXP_INPUT_STORE_CTRL_CH1_ARRAY_EN 0x00000010
+#define BF_PXP_INPUT_STORE_CTRL_CH1_ARRAY_EN(v) \
+ (((v) << 4) & BM_PXP_INPUT_STORE_CTRL_CH1_ARRAY_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_ARRAY_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_ARRAY_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH1_HANDSHAKE_EN 0x00000008
+#define BF_PXP_INPUT_STORE_CTRL_CH1_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_INPUT_STORE_CTRL_CH1_HANDSHAKE_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_HANDSHAKE_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_HANDSHAKE_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH1_BLOCK_16 0x00000004
+#define BF_PXP_INPUT_STORE_CTRL_CH1_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_INPUT_STORE_CTRL_CH1_BLOCK_16)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_BLOCK_16__8x8 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_BLOCK_16__16x16 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH1_BLOCK_EN 0x00000002
+#define BF_PXP_INPUT_STORE_CTRL_CH1_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_INPUT_STORE_CTRL_CH1_BLOCK_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_BLOCK_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_BLOCK_EN__1 0x1
+#define BM_PXP_INPUT_STORE_CTRL_CH1_CH_EN 0x00000001
+#define BF_PXP_INPUT_STORE_CTRL_CH1_CH_EN(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_CTRL_CH1_CH_EN)
+#define BV_PXP_INPUT_STORE_CTRL_CH1_CH_EN__0 0x0
+#define BV_PXP_INPUT_STORE_CTRL_CH1_CH_EN__1 0x1
+
+#define HW_PXP_INPUT_STORE_STATUS_CH0 (0x000005e0)
+
+#define BP_PXP_INPUT_STORE_STATUS_CH0_STORE_BLOCK_Y 16
+#define BM_PXP_INPUT_STORE_STATUS_CH0_STORE_BLOCK_Y 0xFFFF0000
+#define BF_PXP_INPUT_STORE_STATUS_CH0_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_STATUS_CH0_STORE_BLOCK_Y)
+#define BP_PXP_INPUT_STORE_STATUS_CH0_STORE_BLOCK_X 0
+#define BM_PXP_INPUT_STORE_STATUS_CH0_STORE_BLOCK_X 0x0000FFFF
+#define BF_PXP_INPUT_STORE_STATUS_CH0_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_STATUS_CH0_STORE_BLOCK_X)
+
+#define HW_PXP_INPUT_STORE_STATUS_CH1 (0x000005f0)
+
+#define BP_PXP_INPUT_STORE_STATUS_CH1_STORE_BLOCK_Y 16
+#define BM_PXP_INPUT_STORE_STATUS_CH1_STORE_BLOCK_Y 0xFFFF0000
+#define BF_PXP_INPUT_STORE_STATUS_CH1_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_STATUS_CH1_STORE_BLOCK_Y)
+#define BP_PXP_INPUT_STORE_STATUS_CH1_STORE_BLOCK_X 0
+#define BM_PXP_INPUT_STORE_STATUS_CH1_STORE_BLOCK_X 0x0000FFFF
+#define BF_PXP_INPUT_STORE_STATUS_CH1_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_STATUS_CH1_STORE_BLOCK_X)
+
+#define HW_PXP_INPUT_STORE_SIZE_CH0 (0x00000600)
+
+#define BP_PXP_INPUT_STORE_SIZE_CH0_OUT_HEIGHT 16
+#define BM_PXP_INPUT_STORE_SIZE_CH0_OUT_HEIGHT 0xFFFF0000
+#define BF_PXP_INPUT_STORE_SIZE_CH0_OUT_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_SIZE_CH0_OUT_HEIGHT)
+#define BP_PXP_INPUT_STORE_SIZE_CH0_OUT_WIDTH 0
+#define BM_PXP_INPUT_STORE_SIZE_CH0_OUT_WIDTH 0x0000FFFF
+#define BF_PXP_INPUT_STORE_SIZE_CH0_OUT_WIDTH(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_SIZE_CH0_OUT_WIDTH)
+
+#define HW_PXP_INPUT_STORE_SIZE_CH1 (0x00000610)
+
+#define BP_PXP_INPUT_STORE_SIZE_CH1_OUT_HEIGHT 16
+#define BM_PXP_INPUT_STORE_SIZE_CH1_OUT_HEIGHT 0xFFFF0000
+#define BF_PXP_INPUT_STORE_SIZE_CH1_OUT_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_SIZE_CH1_OUT_HEIGHT)
+#define BP_PXP_INPUT_STORE_SIZE_CH1_OUT_WIDTH 0
+#define BM_PXP_INPUT_STORE_SIZE_CH1_OUT_WIDTH 0x0000FFFF
+#define BF_PXP_INPUT_STORE_SIZE_CH1_OUT_WIDTH(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_SIZE_CH1_OUT_WIDTH)
+
+#define HW_PXP_INPUT_STORE_PITCH (0x00000620)
+
+#define BP_PXP_INPUT_STORE_PITCH_CH1_OUT_PITCH 16
+#define BM_PXP_INPUT_STORE_PITCH_CH1_OUT_PITCH 0xFFFF0000
+#define BF_PXP_INPUT_STORE_PITCH_CH1_OUT_PITCH(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_PITCH_CH1_OUT_PITCH)
+#define BP_PXP_INPUT_STORE_PITCH_CH0_OUT_PITCH 0
+#define BM_PXP_INPUT_STORE_PITCH_CH0_OUT_PITCH 0x0000FFFF
+#define BF_PXP_INPUT_STORE_PITCH_CH0_OUT_PITCH(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_PITCH_CH0_OUT_PITCH)
+
+#define HW_PXP_INPUT_STORE_SHIFT_CTRL_CH0 (0x00000630)
+#define HW_PXP_INPUT_STORE_SHIFT_CTRL_CH0_SET (0x00000634)
+#define HW_PXP_INPUT_STORE_SHIFT_CTRL_CH0_CLR (0x00000638)
+#define HW_PXP_INPUT_STORE_SHIFT_CTRL_CH0_TOG (0x0000063c)
+
+#define BP_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD0 8
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD0 0xFFFFFF00
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD0(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD0)
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS 0x00000080
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(v) \
+ (((v) << 7) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS)
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS__0 0x0
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS__1 0x1
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD1 0x00000040
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD1(v) \
+ (((v) << 6) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD1)
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN 0x00000020
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(v) \
+ (((v) << 5) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN)
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN__0 0x0
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN__1 0x1
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN 0x00000010
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(v) \
+ (((v) << 4) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN)
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN__0 0x0
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN__1 0x1
+#define BP_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP 2
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP 0x0000000C
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 2) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP)
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__3 0x3
+#define BP_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD2 0
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD2 0x00000003
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD2(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH0_RSVD2)
+
+#define HW_PXP_INPUT_STORE_SHIFT_CTRL_CH1 (0x00000640)
+#define HW_PXP_INPUT_STORE_SHIFT_CTRL_CH1_SET (0x00000644)
+#define HW_PXP_INPUT_STORE_SHIFT_CTRL_CH1_CLR (0x00000648)
+#define HW_PXP_INPUT_STORE_SHIFT_CTRL_CH1_TOG (0x0000064c)
+
+#define BP_PXP_INPUT_STORE_SHIFT_CTRL_CH1_RSVD0 6
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_RSVD0 0xFFFFFFC0
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH1_RSVD0(v) \
+ (((v) << 6) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_RSVD0)
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN 0x00000020
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN(v) \
+ (((v) << 5) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN)
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN__0 0x0
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN__1 0x1
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN 0x00000010
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN(v) \
+ (((v) << 4) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN)
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN__0 0x0
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN__1 0x1
+#define BP_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP 2
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP 0x0000000C
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 2) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP)
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_INPUT_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__3 0x3
+#define BP_PXP_INPUT_STORE_SHIFT_CTRL_CH1_RSVD2 0
+#define BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_RSVD2 0x00000003
+#define BF_PXP_INPUT_STORE_SHIFT_CTRL_CH1_RSVD2(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_SHIFT_CTRL_CH1_RSVD2)
+
+#define HW_PXP_INPUT_STORE_ADDR_0_CH0 (0x00000690)
+
+#define BP_PXP_INPUT_STORE_ADDR_0_CH0_OUT_BASE_ADDR0 0
+#define BM_PXP_INPUT_STORE_ADDR_0_CH0_OUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_INPUT_STORE_ADDR_1_CH0 (0x000006a0)
+
+#define BP_PXP_INPUT_STORE_ADDR_1_CH0_OUT_BASE_ADDR1 0
+#define BM_PXP_INPUT_STORE_ADDR_1_CH0_OUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_INPUT_STORE_FILL_DATA_CH0 (0x000006b0)
+
+#define BP_PXP_INPUT_STORE_FILL_DATA_CH0_FILL_DATA_CH0 0
+#define BM_PXP_INPUT_STORE_FILL_DATA_CH0_FILL_DATA_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_FILL_DATA_CH0_FILL_DATA_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_ADDR_0_CH1 (0x000006c0)
+
+#define BP_PXP_INPUT_STORE_ADDR_0_CH1_OUT_BASE_ADDR0 0
+#define BM_PXP_INPUT_STORE_ADDR_0_CH1_OUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_INPUT_STORE_ADDR_1_CH1 (0x000006d0)
+
+#define BP_PXP_INPUT_STORE_ADDR_1_CH1_OUT_BASE_ADDR1 0
+#define BM_PXP_INPUT_STORE_ADDR_1_CH1_OUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK0_H_CH0 (0x000006e0)
+
+#define BP_PXP_INPUT_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK0_L_CH0 (0x000006f0)
+
+#define BP_PXP_INPUT_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK1_H_CH0 (0x00000700)
+
+#define BP_PXP_INPUT_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK1_L_CH0 (0x00000710)
+
+#define BP_PXP_INPUT_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK2_H_CH0 (0x00000720)
+
+#define BP_PXP_INPUT_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK2_L_CH0 (0x00000730)
+
+#define BP_PXP_INPUT_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK3_H_CH0 (0x00000740)
+
+#define BP_PXP_INPUT_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK3_L_CH0 (0x00000750)
+
+#define BP_PXP_INPUT_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK4_H_CH0 (0x00000760)
+
+#define BP_PXP_INPUT_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK4_L_CH0 (0x00000770)
+
+#define BP_PXP_INPUT_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK5_H_CH0 (0x00000780)
+
+#define BP_PXP_INPUT_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK5_L_CH0 (0x00000790)
+
+#define BP_PXP_INPUT_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK6_H_CH0 (0x000007a0)
+
+#define BP_PXP_INPUT_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK6_L_CH0 (0x000007b0)
+
+#define BP_PXP_INPUT_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK7_H_CH0 (0x000007c0)
+
+#define BP_PXP_INPUT_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_MASK7_L_CH0 (0x000007e0)
+
+#define BP_PXP_INPUT_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0 0
+#define BM_PXP_INPUT_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0 0xFFFFFFFF
+#define BF_PXP_INPUT_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0(v) (v)
+
+#define HW_PXP_INPUT_STORE_D_SHIFT_L_CH0 (0x000007f0)
+
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3 0x80000000
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(v) \
+ (((v) << 31) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3)
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD0 0x40000000
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD0)
+#define BP_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3 24
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3 0x3F000000
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(v) \
+ (((v) << 24) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3)
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2 0x00800000
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(v) \
+ (((v) << 23) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2)
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD1 0x00400000
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD1)
+#define BP_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2 16
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2 0x003F0000
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2)
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1 0x00008000
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(v) \
+ (((v) << 15) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1)
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD2 0x00004000
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD2)
+#define BP_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1 8
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1 0x00003F00
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1)
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0 0x00000080
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(v) \
+ (((v) << 7) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0)
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD3 0x00000040
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_RSVD3)
+#define BP_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0 0
+#define BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0 0x0000003F
+#define BF_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0)
+
+#define HW_PXP_INPUT_STORE_D_SHIFT_H_CH0 (0x00000800)
+
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7 0x80000000
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7(v) \
+ (((v) << 31) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7)
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD0 0x40000000
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD0)
+#define BP_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7 24
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7 0x3F000000
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7(v) \
+ (((v) << 24) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7)
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6 0x00800000
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6(v) \
+ (((v) << 23) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6)
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD1 0x00400000
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD1)
+#define BP_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6 16
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6 0x003F0000
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6)
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5 0x00008000
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5(v) \
+ (((v) << 15) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5)
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD2 0x00004000
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD2)
+#define BP_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5 8
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5 0x00003F00
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5)
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4 0x00000080
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4(v) \
+ (((v) << 7) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4)
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD3 0x00000040
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_RSVD3)
+#define BP_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4 0
+#define BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4 0x0000003F
+#define BF_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4)
+
+#define HW_PXP_INPUT_STORE_F_SHIFT_L_CH0 (0x00000810)
+
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD0 0x80000000
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD0(v) \
+ (((v) << 31) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD0)
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3 0x40000000
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(v) \
+ (((v) << 30) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3)
+#define BP_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3 24
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3 0x3F000000
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(v) \
+ (((v) << 24) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3)
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD1 0x00800000
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD1(v) \
+ (((v) << 23) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD1)
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2 0x00400000
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(v) \
+ (((v) << 22) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2)
+#define BP_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2 16
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2 0x003F0000
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2)
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD2 0x00008000
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD2(v) \
+ (((v) << 15) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD2)
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1 0x00004000
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(v) \
+ (((v) << 14) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1)
+#define BP_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1 8
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1 0x00003F00
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1)
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD3 0x00000080
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_RSVD3)
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0 0x00000040
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(v) \
+ (((v) << 6) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0)
+#define BP_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0 0
+#define BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0 0x0000003F
+#define BF_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0)
+
+#define HW_PXP_INPUT_STORE_F_SHIFT_H_CH0 (0x00000820)
+
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD0 0x80000000
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD0(v) \
+ (((v) << 31) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD0)
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7 0x40000000
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7(v) \
+ (((v) << 30) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7)
+#define BP_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7 24
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7 0x3F000000
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7(v) \
+ (((v) << 24) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7)
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD1 0x00800000
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD1(v) \
+ (((v) << 23) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD1)
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6 0x00400000
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6(v) \
+ (((v) << 22) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6)
+#define BP_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6 16
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6 0x003F0000
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6)
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD2 0x00008000
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD2(v) \
+ (((v) << 15) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD2)
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5 0x00004000
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5(v) \
+ (((v) << 14) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5)
+#define BP_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5 8
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5 0x00003F00
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5)
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD3 0x00000080
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_RSVD3)
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4 0x00000040
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4(v) \
+ (((v) << 6) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4)
+#define BP_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4 0
+#define BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4 0x0000003F
+#define BF_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4)
+
+#define HW_PXP_INPUT_STORE_F_MASK_L_CH0 (0x00000830)
+
+#define BP_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK3 24
+#define BM_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK3 0xFF000000
+#define BF_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK3(v) \
+ (((v) << 24) & BM_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK3)
+#define BP_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK2 16
+#define BM_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK2 0x00FF0000
+#define BF_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK2(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK2)
+#define BP_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK1 8
+#define BM_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK1 0x0000FF00
+#define BF_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK1(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK1)
+#define BP_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK0 0
+#define BM_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK0 0x000000FF
+#define BF_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK0(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_F_MASK_L_CH0_F_MASK0)
+
+#define HW_PXP_INPUT_STORE_F_MASK_H_CH0 (0x00000840)
+
+#define BP_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK7 24
+#define BM_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK7 0xFF000000
+#define BF_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK7(v) \
+ (((v) << 24) & BM_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK7)
+#define BP_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK6 16
+#define BM_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK6 0x00FF0000
+#define BF_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK6(v) \
+ (((v) << 16) & BM_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK6)
+#define BP_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK5 8
+#define BM_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK5 0x0000FF00
+#define BF_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK5(v) \
+ (((v) << 8) & BM_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK5)
+#define BP_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK4 0
+#define BM_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK4 0x000000FF
+#define BF_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK4(v) \
+ (((v) << 0) & BM_PXP_INPUT_STORE_F_MASK_H_CH0_F_MASK4)
+
+#define HW_PXP_DITHER_FETCH_CTRL_CH0 (0x00000850)
+#define HW_PXP_DITHER_FETCH_CTRL_CH0_SET (0x00000854)
+#define HW_PXP_DITHER_FETCH_CTRL_CH0_CLR (0x00000858)
+#define HW_PXP_DITHER_FETCH_CTRL_CH0_TOG (0x0000085c)
+
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_ARBIT_EN 0x80000000
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_ARBIT_EN(v) \
+ (((v) << 31) & BM_PXP_DITHER_FETCH_CTRL_CH0_ARBIT_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_ARBIT_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_ARBIT_EN__1 0x1
+#define BP_PXP_DITHER_FETCH_CTRL_CH0_RSVD0 26
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD0 0x7C000000
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_RSVD0(v) \
+ (((v) << 26) & BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD0)
+#define BP_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM 24
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM 0x03000000
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM(v) \
+ (((v) << 24) & BM_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM__1 0x1
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM__2 0x2
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM__3 0x3
+#define BP_PXP_DITHER_FETCH_CTRL_CH0_RSVD1 18
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD1 0x00FC0000
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_RSVD1(v) \
+ (((v) << 18) & BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD1)
+#define BP_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES 16
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES 0x00030000
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_RD_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_DITHER_FETCH_CTRL_CH0_RSVD2 14
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD2 0x0000C000
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD2)
+#define BP_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE 12
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE 0x00003000
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE(v) \
+ (((v) << 12) & BM_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE__ROT_0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE__ROT_90 0x1
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE__ROT_180 0x2
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_ROTATION_ANGLE__ROT_270 0x3
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD3 0x00000800
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_RSVD3(v) \
+ (((v) << 11) & BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD3)
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_VFLIP 0x00000400
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_VFLIP(v) \
+ (((v) << 10) & BM_PXP_DITHER_FETCH_CTRL_CH0_VFLIP)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_VFLIP__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_VFLIP__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_HFLIP 0x00000200
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_HFLIP(v) \
+ (((v) << 9) & BM_PXP_DITHER_FETCH_CTRL_CH0_HFLIP)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HFLIP__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HFLIP__1 0x1
+#define BP_PXP_DITHER_FETCH_CTRL_CH0_RSVD4 6
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD4 0x000001C0
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_RSVD4(v) \
+ (((v) << 6) & BM_PXP_DITHER_FETCH_CTRL_CH0_RSVD4)
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE 0x00000020
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE(v) \
+ (((v) << 5) & BM_PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_BYPASS_PIXEL_EN 0x00000010
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_BYPASS_PIXEL_EN(v) \
+ (((v) << 4) & BM_PXP_DITHER_FETCH_CTRL_CH0_BYPASS_PIXEL_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_BYPASS_PIXEL_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_BYPASS_PIXEL_EN__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_EN 0x00000008
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_HANDSHAKE_EN__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_16 0x00000004
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_16)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_16__8x8 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_16__16x16 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_EN 0x00000002
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_BLOCK_EN__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH0_CH_EN 0x00000001
+#define BF_PXP_DITHER_FETCH_CTRL_CH0_CH_EN(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_CTRL_CH0_CH_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_CH_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH0_CH_EN__1 0x1
+
+#define HW_PXP_DITHER_FETCH_CTRL_CH1 (0x00000860)
+#define HW_PXP_DITHER_FETCH_CTRL_CH1_SET (0x00000864)
+#define HW_PXP_DITHER_FETCH_CTRL_CH1_CLR (0x00000868)
+#define HW_PXP_DITHER_FETCH_CTRL_CH1_TOG (0x0000086c)
+
+#define BP_PXP_DITHER_FETCH_CTRL_CH1_RSVD0 26
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD0 0xFC000000
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_RSVD0(v) \
+ (((v) << 26) & BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD0)
+#define BP_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM 24
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM 0x03000000
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM(v) \
+ (((v) << 24) & BM_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM__1 0x1
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM__2 0x2
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_SCAN_LINE_NUM__3 0x3
+#define BP_PXP_DITHER_FETCH_CTRL_CH1_RSVD1 18
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD1 0x00FC0000
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_RSVD1(v) \
+ (((v) << 18) & BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD1)
+#define BP_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES 16
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES 0x00030000
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_RD_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_DITHER_FETCH_CTRL_CH1_RSVD2 14
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD2 0x0000C000
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD2)
+#define BP_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE 12
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE 0x00003000
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE(v) \
+ (((v) << 12) & BM_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE__ROT_0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE__ROT_90 0x1
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE__ROT_180 0x2
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_ROTATION_ANGLE__ROT_270 0x3
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD3 0x00000800
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_RSVD3(v) \
+ (((v) << 11) & BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD3)
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_VFLIP 0x00000400
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_VFLIP(v) \
+ (((v) << 10) & BM_PXP_DITHER_FETCH_CTRL_CH1_VFLIP)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_VFLIP__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_VFLIP__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_HFLIP 0x00000200
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_HFLIP(v) \
+ (((v) << 9) & BM_PXP_DITHER_FETCH_CTRL_CH1_HFLIP)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_HFLIP__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_HFLIP__1 0x1
+#define BP_PXP_DITHER_FETCH_CTRL_CH1_RSVD4 5
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD4 0x000001E0
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_RSVD4(v) \
+ (((v) << 5) & BM_PXP_DITHER_FETCH_CTRL_CH1_RSVD4)
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_BYPASS_PIXEL_EN 0x00000010
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_BYPASS_PIXEL_EN(v) \
+ (((v) << 4) & BM_PXP_DITHER_FETCH_CTRL_CH1_BYPASS_PIXEL_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_BYPASS_PIXEL_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_BYPASS_PIXEL_EN__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_EN 0x00000008
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_HANDSHAKE_EN__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_16 0x00000004
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_16)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_16__8x8 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_16__16x16 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_EN 0x00000002
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_BLOCK_EN__1 0x1
+#define BM_PXP_DITHER_FETCH_CTRL_CH1_CH_EN 0x00000001
+#define BF_PXP_DITHER_FETCH_CTRL_CH1_CH_EN(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_CTRL_CH1_CH_EN)
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_CH_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_CTRL_CH1_CH_EN__1 0x1
+
+#define HW_PXP_DITHER_FETCH_STATUS_CH0 (0x00000870)
+
+#define BP_PXP_DITHER_FETCH_STATUS_CH0_PREFETCH_BLOCK_Y 16
+#define BM_PXP_DITHER_FETCH_STATUS_CH0_PREFETCH_BLOCK_Y 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_STATUS_CH0_PREFETCH_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_STATUS_CH0_PREFETCH_BLOCK_Y)
+#define BP_PXP_DITHER_FETCH_STATUS_CH0_PREFETCH_BLOCK_X 0
+#define BM_PXP_DITHER_FETCH_STATUS_CH0_PREFETCH_BLOCK_X 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_STATUS_CH0_PREFETCH_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_STATUS_CH0_PREFETCH_BLOCK_X)
+
+#define HW_PXP_DITHER_FETCH_STATUS_CH1 (0x00000880)
+
+#define BP_PXP_DITHER_FETCH_STATUS_CH1_PREFETCH_BLOCK_Y 16
+#define BM_PXP_DITHER_FETCH_STATUS_CH1_PREFETCH_BLOCK_Y 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_STATUS_CH1_PREFETCH_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_STATUS_CH1_PREFETCH_BLOCK_Y)
+#define BP_PXP_DITHER_FETCH_STATUS_CH1_PREFETCH_BLOCK_X 0
+#define BM_PXP_DITHER_FETCH_STATUS_CH1_PREFETCH_BLOCK_X 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_STATUS_CH1_PREFETCH_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_STATUS_CH1_PREFETCH_BLOCK_X)
+
+#define HW_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0 (0x00000890)
+
+#define BP_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y 16
+#define BM_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_Y)
+#define BP_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X 0
+#define BM_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH0_ACTIVE_SIZE_ULC_X)
+
+#define HW_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0 (0x000008a0)
+
+#define BP_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y 16
+#define BM_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_Y)
+#define BP_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X 0
+#define BM_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH0_ACTIVE_SIZE_LRC_X)
+
+#define HW_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1 (0x000008b0)
+
+#define BP_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y 16
+#define BM_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_Y)
+#define BP_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X 0
+#define BM_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_ACTIVE_SIZE_ULC_CH1_ACTIVE_SIZE_ULC_X)
+
+#define HW_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1 (0x000008c0)
+
+#define BP_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y 16
+#define BM_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_Y)
+#define BP_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X 0
+#define BM_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_ACTIVE_SIZE_LRC_CH1_ACTIVE_SIZE_LRC_X)
+
+#define HW_PXP_DITHER_FETCH_SIZE_CH0 (0x000008d0)
+
+#define BP_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT 16
+#define BM_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_HEIGHT)
+#define BP_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH 0
+#define BM_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_SIZE_CH0_INPUT_TOTAL_WIDTH)
+
+#define HW_PXP_DITHER_FETCH_SIZE_CH1 (0x000008e0)
+
+#define BP_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT 16
+#define BM_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_HEIGHT)
+#define BP_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH 0
+#define BM_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_SIZE_CH1_INPUT_TOTAL_WIDTH)
+
+#define HW_PXP_DITHER_FETCH_BACKGROUND_COLOR_CH0 (0x000008f0)
+
+#define BP_PXP_DITHER_FETCH_BACKGROUND_COLOR_CH0_BACKGROUND_COLOR 0
+#define BM_PXP_DITHER_FETCH_BACKGROUND_COLOR_CH0_BACKGROUND_COLOR 0xFFFFFFFF
+#define BF_PXP_DITHER_FETCH_BACKGROUND_COLOR_CH0_BACKGROUND_COLOR(v) (v)
+
+#define HW_PXP_DITHER_FETCH_BACKGROUND_COLOR_CH1 (0x00000900)
+
+#define BP_PXP_DITHER_FETCH_BACKGROUND_COLOR_CH1_BACKGROUND_COLOR 0
+#define BM_PXP_DITHER_FETCH_BACKGROUND_COLOR_CH1_BACKGROUND_COLOR 0xFFFFFFFF
+#define BF_PXP_DITHER_FETCH_BACKGROUND_COLOR_CH1_BACKGROUND_COLOR(v) (v)
+
+#define HW_PXP_DITHER_FETCH_PITCH (0x00000910)
+
+#define BP_PXP_DITHER_FETCH_PITCH_CH1_INPUT_PITCH 16
+#define BM_PXP_DITHER_FETCH_PITCH_CH1_INPUT_PITCH 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_PITCH_CH1_INPUT_PITCH(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_PITCH_CH1_INPUT_PITCH)
+#define BP_PXP_DITHER_FETCH_PITCH_CH0_INPUT_PITCH 0
+#define BM_PXP_DITHER_FETCH_PITCH_CH0_INPUT_PITCH 0x0000FFFF
+#define BF_PXP_DITHER_FETCH_PITCH_CH0_INPUT_PITCH(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_PITCH_CH0_INPUT_PITCH)
+
+#define HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH0 (0x00000920)
+#define HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_SET (0x00000924)
+#define HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_CLR (0x00000928)
+#define HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_TOG (0x0000092c)
+
+#define BP_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_RSVD0 13
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_RSVD0 0xFFFFE000
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_RSVD0(v) \
+ (((v) << 13) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_RSVD0)
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS 0x00001000
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS(v) \
+ (((v) << 12) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS)
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS__0 0x0
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS__1 0x1
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_EN 0x00000800
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_EN(v) \
+ (((v) << 11) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_EN)
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_EN__1 0x1
+#define BP_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT 8
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT 0x00000700
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT(v) \
+ (((v) << 8) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT)
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__0 0x0
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__1 0x1
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__2 0x2
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__3 0x3
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__4 0x4
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__5 0x5
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__6 0x6
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT__7 0x7
+#define BP_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_RSVD1 2
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_RSVD1 0x000000FC
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_RSVD1(v) \
+ (((v) << 2) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_RSVD1)
+#define BP_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP 0
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP 0x00000003
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP)
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP__3 0x3
+
+#define HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH1 (0x00000930)
+#define HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_SET (0x00000934)
+#define HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_CLR (0x00000938)
+#define HW_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_TOG (0x0000093c)
+
+#define BP_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_RSVD0 13
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_RSVD0 0xFFFFE000
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_RSVD0(v) \
+ (((v) << 13) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_RSVD0)
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS 0x00001000
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS(v) \
+ (((v) << 12) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS)
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS__0 0x0
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_SHIFT_BYPASS__1 0x1
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_EN 0x00000800
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_EN(v) \
+ (((v) << 11) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_EN)
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_EN__0 0x0
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_EN__1 0x1
+#define BP_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT 8
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT 0x00000700
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT(v) \
+ (((v) << 8) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT)
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__0 0x0
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__1 0x1
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__2 0x2
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__3 0x3
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__4 0x4
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__5 0x5
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__6 0x6
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_EXPAND_FORMAT__7 0x7
+#define BP_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_RSVD1 2
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_RSVD1 0x000000FC
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_RSVD1(v) \
+ (((v) << 2) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_RSVD1)
+#define BP_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP 0
+#define BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP 0x00000003
+#define BF_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP)
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_DITHER_FETCH_SHIFT_CTRL_CH1_INPUT_ACTIVE_BPP__3 0x3
+
+#define HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0 (0x00000940)
+#define HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_SET (0x00000944)
+#define HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_CLR (0x00000948)
+#define HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_TOG (0x0000094c)
+
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD0 29
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD0 0xE0000000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD0(v) \
+ (((v) << 29) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD0)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET3 24
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET3 0x1F000000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET3(v) \
+ (((v) << 24) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET3)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD1 21
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD1 0x00E00000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD1(v) \
+ (((v) << 21) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD1)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET2 16
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET2 0x001F0000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET2(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET2)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD2 13
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD2 0x0000E000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD2(v) \
+ (((v) << 13) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD2)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET1 8
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET1 0x00001F00
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET1(v) \
+ (((v) << 8) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET1)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD3 5
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD3 0x000000E0
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD3(v) \
+ (((v) << 5) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_RSVD3)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET0 0
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET0 0x0000001F
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET0(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH0_OFFSET0)
+
+#define HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1 (0x00000950)
+#define HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_SET (0x00000954)
+#define HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_CLR (0x00000958)
+#define HW_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_TOG (0x0000095c)
+
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD0 29
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD0 0xE0000000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD0(v) \
+ (((v) << 29) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD0)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET3 24
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET3 0x1F000000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET3(v) \
+ (((v) << 24) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET3)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD1 21
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD1 0x00E00000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD1(v) \
+ (((v) << 21) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD1)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET2 16
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET2 0x001F0000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET2(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET2)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD2 13
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD2 0x0000E000
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD2(v) \
+ (((v) << 13) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD2)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET1 8
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET1 0x00001F00
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET1(v) \
+ (((v) << 8) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET1)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD3 5
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD3 0x000000E0
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD3(v) \
+ (((v) << 5) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_RSVD3)
+#define BP_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET0 0
+#define BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET0 0x0000001F
+#define BF_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET0(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_SHIFT_OFFSET_CH1_OFFSET0)
+
+#define HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0 (0x00000960)
+#define HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_SET (0x00000964)
+#define HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_CLR (0x00000968)
+#define HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_TOG (0x0000096c)
+
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_RSVD0 16
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_RSVD0 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_RSVD0(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_RSVD0)
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH3 12
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH3 0x0000F000
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH3(v) \
+ (((v) << 12) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH3)
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH2 8
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH2 0x00000F00
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH2(v) \
+ (((v) << 8) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH2)
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH1 4
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH1 0x000000F0
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH1(v) \
+ (((v) << 4) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH1)
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH0 0
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH0 0x0000000F
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH0_WIDTH0)
+
+#define HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1 (0x00000970)
+#define HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_SET (0x00000974)
+#define HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_CLR (0x00000978)
+#define HW_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_TOG (0x0000097c)
+
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_RSVD0 16
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_RSVD0 0xFFFF0000
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_RSVD0(v) \
+ (((v) << 16) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_RSVD0)
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH3 12
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH3 0x0000F000
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH3(v) \
+ (((v) << 12) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH3)
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH2 8
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH2 0x00000F00
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH2(v) \
+ (((v) << 8) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH2)
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH1 4
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH1 0x000000F0
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH1(v) \
+ (((v) << 4) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH1)
+#define BP_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH0 0
+#define BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH0 0x0000000F
+#define BF_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_DITHER_FETCH_SHIFT_WIDTH_CH1_WIDTH0)
+
+#define HW_PXP_DITHER_FETCH_ADDR_0_CH0 (0x00000980)
+
+#define BP_PXP_DITHER_FETCH_ADDR_0_CH0_INPUT_BASE_ADDR0 0
+#define BM_PXP_DITHER_FETCH_ADDR_0_CH0_INPUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_DITHER_FETCH_ADDR_0_CH0_INPUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_DITHER_FETCH_ADDR_1_CH0 (0x00000990)
+
+#define BP_PXP_DITHER_FETCH_ADDR_1_CH0_INPUT_BASE_ADDR1 0
+#define BM_PXP_DITHER_FETCH_ADDR_1_CH0_INPUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_DITHER_FETCH_ADDR_1_CH0_INPUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_DITHER_FETCH_ADDR_0_CH1 (0x000009a0)
+
+#define BP_PXP_DITHER_FETCH_ADDR_0_CH1_INPUT_BASE_ADDR0 0
+#define BM_PXP_DITHER_FETCH_ADDR_0_CH1_INPUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_DITHER_FETCH_ADDR_0_CH1_INPUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_DITHER_FETCH_ADDR_1_CH1 (0x000009b0)
+
+#define BP_PXP_DITHER_FETCH_ADDR_1_CH1_INPUT_BASE_ADDR1 0
+#define BM_PXP_DITHER_FETCH_ADDR_1_CH1_INPUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_DITHER_FETCH_ADDR_1_CH1_INPUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_DITHER_STORE_CTRL_CH0 (0x000009c0)
+#define HW_PXP_DITHER_STORE_CTRL_CH0_SET (0x000009c4)
+#define HW_PXP_DITHER_STORE_CTRL_CH0_CLR (0x000009c8)
+#define HW_PXP_DITHER_STORE_CTRL_CH0_TOG (0x000009cc)
+
+#define BM_PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN 0x80000000
+#define BF_PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN(v) \
+ (((v) << 31) & BM_PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN__1 0x1
+#define BP_PXP_DITHER_STORE_CTRL_CH0_RSVD0 25
+#define BM_PXP_DITHER_STORE_CTRL_CH0_RSVD0 0x7E000000
+#define BF_PXP_DITHER_STORE_CTRL_CH0_RSVD0(v) \
+ (((v) << 25) & BM_PXP_DITHER_STORE_CTRL_CH0_RSVD0)
+#define BM_PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL 0x01000000
+#define BF_PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL(v) \
+ (((v) << 24) & BM_PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL__1 0x1
+#define BP_PXP_DITHER_STORE_CTRL_CH0_RSVD1 18
+#define BM_PXP_DITHER_STORE_CTRL_CH0_RSVD1 0x00FC0000
+#define BF_PXP_DITHER_STORE_CTRL_CH0_RSVD1(v) \
+ (((v) << 18) & BM_PXP_DITHER_STORE_CTRL_CH0_RSVD1)
+#define BP_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES 16
+#define BM_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES 0x00030000
+#define BF_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_DITHER_STORE_CTRL_CH0_WR_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_DITHER_STORE_CTRL_CH0_RSVD2 12
+#define BM_PXP_DITHER_STORE_CTRL_CH0_RSVD2 0x0000F000
+#define BF_PXP_DITHER_STORE_CTRL_CH0_RSVD2(v) \
+ (((v) << 12) & BM_PXP_DITHER_STORE_CTRL_CH0_RSVD2)
+#define BM_PXP_DITHER_STORE_CTRL_CH0_FILL_DATA_EN 0x00000800
+#define BF_PXP_DITHER_STORE_CTRL_CH0_FILL_DATA_EN(v) \
+ (((v) << 11) & BM_PXP_DITHER_STORE_CTRL_CH0_FILL_DATA_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_FILL_DATA_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_FILL_DATA_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH0_PACK_IN_SEL 0x00000400
+#define BF_PXP_DITHER_STORE_CTRL_CH0_PACK_IN_SEL(v) \
+ (((v) << 10) & BM_PXP_DITHER_STORE_CTRL_CH0_PACK_IN_SEL)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_PACK_IN_SEL__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_PACK_IN_SEL__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH0_STORE_MEMORY_EN 0x00000200
+#define BF_PXP_DITHER_STORE_CTRL_CH0_STORE_MEMORY_EN(v) \
+ (((v) << 9) & BM_PXP_DITHER_STORE_CTRL_CH0_STORE_MEMORY_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_STORE_MEMORY_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_STORE_MEMORY_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH0_STORE_BYPASS_EN 0x00000100
+#define BF_PXP_DITHER_STORE_CTRL_CH0_STORE_BYPASS_EN(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_CTRL_CH0_STORE_BYPASS_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_STORE_BYPASS_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_STORE_BYPASS_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH0_RSVD3 0x00000080
+#define BF_PXP_DITHER_STORE_CTRL_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_DITHER_STORE_CTRL_CH0_RSVD3)
+#define BP_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM 5
+#define BM_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM 0x00000060
+#define BF_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM(v) \
+ (((v) << 5) & BM_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM__1 0x1
+#define BV_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM__2 0x2
+#define BV_PXP_DITHER_STORE_CTRL_CH0_ARRAY_LINE_NUM__3 0x3
+#define BM_PXP_DITHER_STORE_CTRL_CH0_ARRAY_EN 0x00000010
+#define BF_PXP_DITHER_STORE_CTRL_CH0_ARRAY_EN(v) \
+ (((v) << 4) & BM_PXP_DITHER_STORE_CTRL_CH0_ARRAY_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_ARRAY_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_ARRAY_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH0_HANDSHAKE_EN 0x00000008
+#define BF_PXP_DITHER_STORE_CTRL_CH0_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_DITHER_STORE_CTRL_CH0_HANDSHAKE_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_HANDSHAKE_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_HANDSHAKE_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH0_BLOCK_16 0x00000004
+#define BF_PXP_DITHER_STORE_CTRL_CH0_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_DITHER_STORE_CTRL_CH0_BLOCK_16)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_BLOCK_16__8x8 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_BLOCK_16__16x16 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH0_BLOCK_EN 0x00000002
+#define BF_PXP_DITHER_STORE_CTRL_CH0_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_DITHER_STORE_CTRL_CH0_BLOCK_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_BLOCK_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_BLOCK_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH0_CH_EN 0x00000001
+#define BF_PXP_DITHER_STORE_CTRL_CH0_CH_EN(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_CTRL_CH0_CH_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH0_CH_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH0_CH_EN__1 0x1
+
+#define HW_PXP_DITHER_STORE_CTRL_CH1 (0x000009d0)
+#define HW_PXP_DITHER_STORE_CTRL_CH1_SET (0x000009d4)
+#define HW_PXP_DITHER_STORE_CTRL_CH1_CLR (0x000009d8)
+#define HW_PXP_DITHER_STORE_CTRL_CH1_TOG (0x000009dc)
+
+#define BP_PXP_DITHER_STORE_CTRL_CH1_RSVD0 18
+#define BM_PXP_DITHER_STORE_CTRL_CH1_RSVD0 0xFFFC0000
+#define BF_PXP_DITHER_STORE_CTRL_CH1_RSVD0(v) \
+ (((v) << 18) & BM_PXP_DITHER_STORE_CTRL_CH1_RSVD0)
+#define BP_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES 16
+#define BM_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES 0x00030000
+#define BF_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_DITHER_STORE_CTRL_CH1_WR_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_DITHER_STORE_CTRL_CH1_RSVD1 11
+#define BM_PXP_DITHER_STORE_CTRL_CH1_RSVD1 0x0000F800
+#define BF_PXP_DITHER_STORE_CTRL_CH1_RSVD1(v) \
+ (((v) << 11) & BM_PXP_DITHER_STORE_CTRL_CH1_RSVD1)
+#define BM_PXP_DITHER_STORE_CTRL_CH1_PACK_IN_SEL 0x00000400
+#define BF_PXP_DITHER_STORE_CTRL_CH1_PACK_IN_SEL(v) \
+ (((v) << 10) & BM_PXP_DITHER_STORE_CTRL_CH1_PACK_IN_SEL)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_PACK_IN_SEL__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_PACK_IN_SEL__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH1_STORE_MEMORY_EN 0x00000200
+#define BF_PXP_DITHER_STORE_CTRL_CH1_STORE_MEMORY_EN(v) \
+ (((v) << 9) & BM_PXP_DITHER_STORE_CTRL_CH1_STORE_MEMORY_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_STORE_MEMORY_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_STORE_MEMORY_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH1_STORE_BYPASS_EN 0x00000100
+#define BF_PXP_DITHER_STORE_CTRL_CH1_STORE_BYPASS_EN(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_CTRL_CH1_STORE_BYPASS_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_STORE_BYPASS_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_STORE_BYPASS_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH1_RSVD3 0x00000080
+#define BF_PXP_DITHER_STORE_CTRL_CH1_RSVD3(v) \
+ (((v) << 7) & BM_PXP_DITHER_STORE_CTRL_CH1_RSVD3)
+#define BP_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM 5
+#define BM_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM 0x00000060
+#define BF_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM(v) \
+ (((v) << 5) & BM_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM__1 0x1
+#define BV_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM__2 0x2
+#define BV_PXP_DITHER_STORE_CTRL_CH1_ARRAY_LINE_NUM__3 0x3
+#define BM_PXP_DITHER_STORE_CTRL_CH1_ARRAY_EN 0x00000010
+#define BF_PXP_DITHER_STORE_CTRL_CH1_ARRAY_EN(v) \
+ (((v) << 4) & BM_PXP_DITHER_STORE_CTRL_CH1_ARRAY_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_ARRAY_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_ARRAY_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH1_HANDSHAKE_EN 0x00000008
+#define BF_PXP_DITHER_STORE_CTRL_CH1_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_DITHER_STORE_CTRL_CH1_HANDSHAKE_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_HANDSHAKE_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_HANDSHAKE_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH1_BLOCK_16 0x00000004
+#define BF_PXP_DITHER_STORE_CTRL_CH1_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_DITHER_STORE_CTRL_CH1_BLOCK_16)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_BLOCK_16__8x8 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_BLOCK_16__16x16 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH1_BLOCK_EN 0x00000002
+#define BF_PXP_DITHER_STORE_CTRL_CH1_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_DITHER_STORE_CTRL_CH1_BLOCK_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_BLOCK_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_BLOCK_EN__1 0x1
+#define BM_PXP_DITHER_STORE_CTRL_CH1_CH_EN 0x00000001
+#define BF_PXP_DITHER_STORE_CTRL_CH1_CH_EN(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_CTRL_CH1_CH_EN)
+#define BV_PXP_DITHER_STORE_CTRL_CH1_CH_EN__0 0x0
+#define BV_PXP_DITHER_STORE_CTRL_CH1_CH_EN__1 0x1
+
+#define HW_PXP_DITHER_STORE_STATUS_CH0 (0x000009e0)
+
+#define BP_PXP_DITHER_STORE_STATUS_CH0_STORE_BLOCK_Y 16
+#define BM_PXP_DITHER_STORE_STATUS_CH0_STORE_BLOCK_Y 0xFFFF0000
+#define BF_PXP_DITHER_STORE_STATUS_CH0_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_STATUS_CH0_STORE_BLOCK_Y)
+#define BP_PXP_DITHER_STORE_STATUS_CH0_STORE_BLOCK_X 0
+#define BM_PXP_DITHER_STORE_STATUS_CH0_STORE_BLOCK_X 0x0000FFFF
+#define BF_PXP_DITHER_STORE_STATUS_CH0_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_STATUS_CH0_STORE_BLOCK_X)
+
+#define HW_PXP_DITHER_STORE_STATUS_CH1 (0x000009f0)
+
+#define BP_PXP_DITHER_STORE_STATUS_CH1_STORE_BLOCK_Y 16
+#define BM_PXP_DITHER_STORE_STATUS_CH1_STORE_BLOCK_Y 0xFFFF0000
+#define BF_PXP_DITHER_STORE_STATUS_CH1_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_STATUS_CH1_STORE_BLOCK_Y)
+#define BP_PXP_DITHER_STORE_STATUS_CH1_STORE_BLOCK_X 0
+#define BM_PXP_DITHER_STORE_STATUS_CH1_STORE_BLOCK_X 0x0000FFFF
+#define BF_PXP_DITHER_STORE_STATUS_CH1_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_STATUS_CH1_STORE_BLOCK_X)
+
+#define HW_PXP_DITHER_STORE_SIZE_CH0 (0x00000a00)
+
+#define BP_PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT 16
+#define BM_PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT 0xFFFF0000
+#define BF_PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT)
+#define BP_PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH 0
+#define BM_PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH 0x0000FFFF
+#define BF_PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH)
+
+#define HW_PXP_DITHER_STORE_SIZE_CH1 (0x00000a10)
+
+#define BP_PXP_DITHER_STORE_SIZE_CH1_OUT_HEIGHT 16
+#define BM_PXP_DITHER_STORE_SIZE_CH1_OUT_HEIGHT 0xFFFF0000
+#define BF_PXP_DITHER_STORE_SIZE_CH1_OUT_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_SIZE_CH1_OUT_HEIGHT)
+#define BP_PXP_DITHER_STORE_SIZE_CH1_OUT_WIDTH 0
+#define BM_PXP_DITHER_STORE_SIZE_CH1_OUT_WIDTH 0x0000FFFF
+#define BF_PXP_DITHER_STORE_SIZE_CH1_OUT_WIDTH(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_SIZE_CH1_OUT_WIDTH)
+
+#define HW_PXP_DITHER_STORE_PITCH (0x00000a20)
+
+#define BP_PXP_DITHER_STORE_PITCH_CH1_OUT_PITCH 16
+#define BM_PXP_DITHER_STORE_PITCH_CH1_OUT_PITCH 0xFFFF0000
+#define BF_PXP_DITHER_STORE_PITCH_CH1_OUT_PITCH(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_PITCH_CH1_OUT_PITCH)
+#define BP_PXP_DITHER_STORE_PITCH_CH0_OUT_PITCH 0
+#define BM_PXP_DITHER_STORE_PITCH_CH0_OUT_PITCH 0x0000FFFF
+#define BF_PXP_DITHER_STORE_PITCH_CH0_OUT_PITCH(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_PITCH_CH0_OUT_PITCH)
+
+#define HW_PXP_DITHER_STORE_SHIFT_CTRL_CH0 (0x00000a30)
+#define HW_PXP_DITHER_STORE_SHIFT_CTRL_CH0_SET (0x00000a34)
+#define HW_PXP_DITHER_STORE_SHIFT_CTRL_CH0_CLR (0x00000a38)
+#define HW_PXP_DITHER_STORE_SHIFT_CTRL_CH0_TOG (0x00000a3c)
+
+#define BP_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD0 8
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD0 0xFFFFFF00
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD0(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD0)
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS 0x00000080
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(v) \
+ (((v) << 7) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS)
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS__0 0x0
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS__1 0x1
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD1 0x00000040
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD1(v) \
+ (((v) << 6) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD1)
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN 0x00000020
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(v) \
+ (((v) << 5) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN)
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN__0 0x0
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN__1 0x1
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN 0x00000010
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(v) \
+ (((v) << 4) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN)
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN__0 0x0
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN__1 0x1
+#define BP_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP 2
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP 0x0000000C
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 2) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP)
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__3 0x3
+#define BP_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD2 0
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD2 0x00000003
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD2(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH0_RSVD2)
+
+#define HW_PXP_DITHER_STORE_SHIFT_CTRL_CH1 (0x00000a40)
+#define HW_PXP_DITHER_STORE_SHIFT_CTRL_CH1_SET (0x00000a44)
+#define HW_PXP_DITHER_STORE_SHIFT_CTRL_CH1_CLR (0x00000a48)
+#define HW_PXP_DITHER_STORE_SHIFT_CTRL_CH1_TOG (0x00000a4c)
+
+#define BP_PXP_DITHER_STORE_SHIFT_CTRL_CH1_RSVD0 6
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_RSVD0 0xFFFFFFC0
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH1_RSVD0(v) \
+ (((v) << 6) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_RSVD0)
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN 0x00000020
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN(v) \
+ (((v) << 5) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN)
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN__0 0x0
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN__1 0x1
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN 0x00000010
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN(v) \
+ (((v) << 4) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN)
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN__0 0x0
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN__1 0x1
+#define BP_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP 2
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP 0x0000000C
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 2) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP)
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_DITHER_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__3 0x3
+#define BP_PXP_DITHER_STORE_SHIFT_CTRL_CH1_RSVD2 0
+#define BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_RSVD2 0x00000003
+#define BF_PXP_DITHER_STORE_SHIFT_CTRL_CH1_RSVD2(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_SHIFT_CTRL_CH1_RSVD2)
+
+#define HW_PXP_DITHER_STORE_ADDR_0_CH0 (0x00000a90)
+
+#define BP_PXP_DITHER_STORE_ADDR_0_CH0_OUT_BASE_ADDR0 0
+#define BM_PXP_DITHER_STORE_ADDR_0_CH0_OUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_DITHER_STORE_ADDR_1_CH0 (0x00000aa0)
+
+#define BP_PXP_DITHER_STORE_ADDR_1_CH0_OUT_BASE_ADDR1 0
+#define BM_PXP_DITHER_STORE_ADDR_1_CH0_OUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_DITHER_STORE_FILL_DATA_CH0 (0x00000ab0)
+
+#define BP_PXP_DITHER_STORE_FILL_DATA_CH0_FILL_DATA_CH0 0
+#define BM_PXP_DITHER_STORE_FILL_DATA_CH0_FILL_DATA_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_FILL_DATA_CH0_FILL_DATA_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_ADDR_0_CH1 (0x00000ac0)
+
+#define BP_PXP_DITHER_STORE_ADDR_0_CH1_OUT_BASE_ADDR0 0
+#define BM_PXP_DITHER_STORE_ADDR_0_CH1_OUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_DITHER_STORE_ADDR_1_CH1 (0x00000ad0)
+
+#define BP_PXP_DITHER_STORE_ADDR_1_CH1_OUT_BASE_ADDR1 0
+#define BM_PXP_DITHER_STORE_ADDR_1_CH1_OUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK0_H_CH0 (0x00000ae0)
+
+#define BP_PXP_DITHER_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK0_L_CH0 (0x00000af0)
+
+#define BP_PXP_DITHER_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK1_H_CH0 (0x00000b00)
+
+#define BP_PXP_DITHER_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK1_L_CH0 (0x00000b10)
+
+#define BP_PXP_DITHER_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK2_H_CH0 (0x00000b20)
+
+#define BP_PXP_DITHER_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK2_L_CH0 (0x00000b30)
+
+#define BP_PXP_DITHER_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK3_H_CH0 (0x00000b40)
+
+#define BP_PXP_DITHER_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK3_L_CH0 (0x00000b50)
+
+#define BP_PXP_DITHER_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK4_H_CH0 (0x00000b60)
+
+#define BP_PXP_DITHER_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK4_L_CH0 (0x00000b70)
+
+#define BP_PXP_DITHER_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK5_H_CH0 (0x00000b80)
+
+#define BP_PXP_DITHER_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK5_L_CH0 (0x00000b90)
+
+#define BP_PXP_DITHER_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK6_H_CH0 (0x00000ba0)
+
+#define BP_PXP_DITHER_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK6_L_CH0 (0x00000bb0)
+
+#define BP_PXP_DITHER_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK7_H_CH0 (0x00000bc0)
+
+#define BP_PXP_DITHER_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_MASK7_L_CH0 (0x00000bd0)
+
+#define BP_PXP_DITHER_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0 0
+#define BM_PXP_DITHER_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0 0xFFFFFFFF
+#define BF_PXP_DITHER_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0(v) (v)
+
+#define HW_PXP_DITHER_STORE_D_SHIFT_L_CH0 (0x00000be0)
+
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3 0x80000000
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(v) \
+ (((v) << 31) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3)
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD0 0x40000000
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD0)
+#define BP_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3 24
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3 0x3F000000
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(v) \
+ (((v) << 24) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3)
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2 0x00800000
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(v) \
+ (((v) << 23) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2)
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD1 0x00400000
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD1)
+#define BP_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2 16
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2 0x003F0000
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2)
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1 0x00008000
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(v) \
+ (((v) << 15) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1)
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD2 0x00004000
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD2)
+#define BP_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1 8
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1 0x00003F00
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1)
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0 0x00000080
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(v) \
+ (((v) << 7) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0)
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD3 0x00000040
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_RSVD3)
+#define BP_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0 0
+#define BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0 0x0000003F
+#define BF_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0)
+
+#define HW_PXP_DITHER_STORE_D_SHIFT_H_CH0 (0x00000bf0)
+
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7 0x80000000
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7(v) \
+ (((v) << 31) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7)
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD0 0x40000000
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD0)
+#define BP_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7 24
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7 0x3F000000
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7(v) \
+ (((v) << 24) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7)
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6 0x00800000
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6(v) \
+ (((v) << 23) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6)
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD1 0x00400000
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD1)
+#define BP_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6 16
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6 0x003F0000
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6)
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5 0x00008000
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5(v) \
+ (((v) << 15) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5)
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD2 0x00004000
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD2)
+#define BP_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5 8
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5 0x00003F00
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5)
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4 0x00000080
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4(v) \
+ (((v) << 7) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4)
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD3 0x00000040
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_RSVD3)
+#define BP_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4 0
+#define BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4 0x0000003F
+#define BF_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4)
+
+#define HW_PXP_DITHER_STORE_F_SHIFT_L_CH0 (0x00000c00)
+
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD0 0x80000000
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD0(v) \
+ (((v) << 31) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD0)
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3 0x40000000
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(v) \
+ (((v) << 30) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3)
+#define BP_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3 24
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3 0x3F000000
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(v) \
+ (((v) << 24) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3)
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD1 0x00800000
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD1(v) \
+ (((v) << 23) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD1)
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2 0x00400000
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(v) \
+ (((v) << 22) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2)
+#define BP_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2 16
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2 0x003F0000
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2)
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD2 0x00008000
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD2(v) \
+ (((v) << 15) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD2)
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1 0x00004000
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(v) \
+ (((v) << 14) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1)
+#define BP_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1 8
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1 0x00003F00
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1)
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD3 0x00000080
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_RSVD3)
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0 0x00000040
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(v) \
+ (((v) << 6) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0)
+#define BP_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0 0
+#define BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0 0x0000003F
+#define BF_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0)
+
+#define HW_PXP_DITHER_STORE_F_SHIFT_H_CH0 (0x00000c10)
+
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD0 0x80000000
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD0(v) \
+ (((v) << 31) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD0)
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7 0x40000000
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7(v) \
+ (((v) << 30) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7)
+#define BP_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7 24
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7 0x3F000000
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7(v) \
+ (((v) << 24) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7)
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD1 0x00800000
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD1(v) \
+ (((v) << 23) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD1)
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6 0x00400000
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6(v) \
+ (((v) << 22) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6)
+#define BP_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6 16
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6 0x003F0000
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6)
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD2 0x00008000
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD2(v) \
+ (((v) << 15) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD2)
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5 0x00004000
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5(v) \
+ (((v) << 14) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5)
+#define BP_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5 8
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5 0x00003F00
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5)
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD3 0x00000080
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_RSVD3)
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4 0x00000040
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4(v) \
+ (((v) << 6) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4)
+#define BP_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4 0
+#define BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4 0x0000003F
+#define BF_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4)
+
+#define HW_PXP_DITHER_STORE_F_MASK_L_CH0 (0x00000c20)
+
+#define BP_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK3 24
+#define BM_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK3 0xFF000000
+#define BF_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK3(v) \
+ (((v) << 24) & BM_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK3)
+#define BP_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK2 16
+#define BM_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK2 0x00FF0000
+#define BF_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK2(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK2)
+#define BP_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK1 8
+#define BM_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK1 0x0000FF00
+#define BF_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK1(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK1)
+#define BP_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK0 0
+#define BM_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK0 0x000000FF
+#define BF_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK0(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_F_MASK_L_CH0_F_MASK0)
+
+#define HW_PXP_DITHER_STORE_F_MASK_H_CH0 (0x00000c30)
+
+#define BP_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK7 24
+#define BM_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK7 0xFF000000
+#define BF_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK7(v) \
+ (((v) << 24) & BM_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK7)
+#define BP_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK6 16
+#define BM_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK6 0x00FF0000
+#define BF_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK6(v) \
+ (((v) << 16) & BM_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK6)
+#define BP_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK5 8
+#define BM_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK5 0x0000FF00
+#define BF_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK5(v) \
+ (((v) << 8) & BM_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK5)
+#define BP_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK4 0
+#define BM_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK4 0x000000FF
+#define BF_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK4(v) \
+ (((v) << 0) & BM_PXP_DITHER_STORE_F_MASK_H_CH0_F_MASK4)
+
+#define HW_PXP_WFA_FETCH_CTRL (0x00000c40)
+#define HW_PXP_WFA_FETCH_CTRL_SET (0x00000c44)
+#define HW_PXP_WFA_FETCH_CTRL_CLR (0x00000c48)
+#define HW_PXP_WFA_FETCH_CTRL_TOG (0x00000c4c)
+
+#define BM_PXP_WFA_FETCH_CTRL_BUF2_DONE_IRQ_EN 0x80000000
+#define BF_PXP_WFA_FETCH_CTRL_BUF2_DONE_IRQ_EN(v) \
+ (((v) << 31) & BM_PXP_WFA_FETCH_CTRL_BUF2_DONE_IRQ_EN)
+#define BM_PXP_WFA_FETCH_CTRL_BUF1_DONE_IRQ_EN 0x40000000
+#define BF_PXP_WFA_FETCH_CTRL_BUF1_DONE_IRQ_EN(v) \
+ (((v) << 30) & BM_PXP_WFA_FETCH_CTRL_BUF1_DONE_IRQ_EN)
+#define BM_PXP_WFA_FETCH_CTRL_BUF2_DONE_IRQ 0x20000000
+#define BF_PXP_WFA_FETCH_CTRL_BUF2_DONE_IRQ(v) \
+ (((v) << 29) & BM_PXP_WFA_FETCH_CTRL_BUF2_DONE_IRQ)
+#define BM_PXP_WFA_FETCH_CTRL_BUF1_DONE_IRQ 0x10000000
+#define BF_PXP_WFA_FETCH_CTRL_BUF1_DONE_IRQ(v) \
+ (((v) << 28) & BM_PXP_WFA_FETCH_CTRL_BUF1_DONE_IRQ)
+#define BP_PXP_WFA_FETCH_CTRL_RSVD0 24
+#define BM_PXP_WFA_FETCH_CTRL_RSVD0 0x0F000000
+#define BF_PXP_WFA_FETCH_CTRL_RSVD0(v) \
+ (((v) << 24) & BM_PXP_WFA_FETCH_CTRL_RSVD0)
+#define BP_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE 22
+#define BM_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE 0x00C00000
+#define BF_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE(v) \
+ (((v) << 22) & BM_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE)
+#define BV_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE__1 0x1
+#define BV_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE__2 0x2
+#define BV_PXP_WFA_FETCH_CTRL_BF2_LINE_MODE__3 0x3
+#define BP_PXP_WFA_FETCH_CTRL_BF2_BYTES_PP 20
+#define BM_PXP_WFA_FETCH_CTRL_BF2_BYTES_PP 0x00300000
+#define BF_PXP_WFA_FETCH_CTRL_BF2_BYTES_PP(v) \
+ (((v) << 20) & BM_PXP_WFA_FETCH_CTRL_BF2_BYTES_PP)
+#define BP_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE 18
+#define BM_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE 0x000C0000
+#define BF_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE(v) \
+ (((v) << 18) & BM_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE)
+#define BV_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE__1 0x1
+#define BV_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE__2 0x2
+#define BV_PXP_WFA_FETCH_CTRL_BF1_LINE_MODE__3 0x3
+#define BP_PXP_WFA_FETCH_CTRL_BF1_BYTES_PP 16
+#define BM_PXP_WFA_FETCH_CTRL_BF1_BYTES_PP 0x00030000
+#define BF_PXP_WFA_FETCH_CTRL_BF1_BYTES_PP(v) \
+ (((v) << 16) & BM_PXP_WFA_FETCH_CTRL_BF1_BYTES_PP)
+#define BP_PXP_WFA_FETCH_CTRL_RSVD1 14
+#define BM_PXP_WFA_FETCH_CTRL_RSVD1 0x0000C000
+#define BF_PXP_WFA_FETCH_CTRL_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFA_FETCH_CTRL_RSVD1)
+#define BM_PXP_WFA_FETCH_CTRL_BF2_BORDER_MODE 0x00002000
+#define BF_PXP_WFA_FETCH_CTRL_BF2_BORDER_MODE(v) \
+ (((v) << 13) & BM_PXP_WFA_FETCH_CTRL_BF2_BORDER_MODE)
+#define BV_PXP_WFA_FETCH_CTRL_BF2_BORDER_MODE__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF2_BORDER_MODE__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF2_BURST_LEN 0x00001000
+#define BF_PXP_WFA_FETCH_CTRL_BF2_BURST_LEN(v) \
+ (((v) << 12) & BM_PXP_WFA_FETCH_CTRL_BF2_BURST_LEN)
+#define BV_PXP_WFA_FETCH_CTRL_BF2_BURST_LEN__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF2_BURST_LEN__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF2_BYPASS_MODE 0x00000800
+#define BF_PXP_WFA_FETCH_CTRL_BF2_BYPASS_MODE(v) \
+ (((v) << 11) & BM_PXP_WFA_FETCH_CTRL_BF2_BYPASS_MODE)
+#define BV_PXP_WFA_FETCH_CTRL_BF2_BYPASS_MODE__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF2_BYPASS_MODE__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF2_HSK_MODE 0x00000400
+#define BF_PXP_WFA_FETCH_CTRL_BF2_HSK_MODE(v) \
+ (((v) << 10) & BM_PXP_WFA_FETCH_CTRL_BF2_HSK_MODE)
+#define BV_PXP_WFA_FETCH_CTRL_BF2_HSK_MODE__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF2_HSK_MODE__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF2_SRAM_IF 0x00000200
+#define BF_PXP_WFA_FETCH_CTRL_BF2_SRAM_IF(v) \
+ (((v) << 9) & BM_PXP_WFA_FETCH_CTRL_BF2_SRAM_IF)
+#define BV_PXP_WFA_FETCH_CTRL_BF2_SRAM_IF__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF2_SRAM_IF__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF2_EN 0x00000100
+#define BF_PXP_WFA_FETCH_CTRL_BF2_EN(v) \
+ (((v) << 8) & BM_PXP_WFA_FETCH_CTRL_BF2_EN)
+#define BV_PXP_WFA_FETCH_CTRL_BF2_EN__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF2_EN__1 0x1
+#define BP_PXP_WFA_FETCH_CTRL_RSVD2 6
+#define BM_PXP_WFA_FETCH_CTRL_RSVD2 0x000000C0
+#define BF_PXP_WFA_FETCH_CTRL_RSVD2(v) \
+ (((v) << 6) & BM_PXP_WFA_FETCH_CTRL_RSVD2)
+#define BM_PXP_WFA_FETCH_CTRL_BF1_BORDER_MODE 0x00000020
+#define BF_PXP_WFA_FETCH_CTRL_BF1_BORDER_MODE(v) \
+ (((v) << 5) & BM_PXP_WFA_FETCH_CTRL_BF1_BORDER_MODE)
+#define BV_PXP_WFA_FETCH_CTRL_BF1_BORDER_MODE__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF1_BORDER_MODE__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF1_BURST_LEN 0x00000010
+#define BF_PXP_WFA_FETCH_CTRL_BF1_BURST_LEN(v) \
+ (((v) << 4) & BM_PXP_WFA_FETCH_CTRL_BF1_BURST_LEN)
+#define BV_PXP_WFA_FETCH_CTRL_BF1_BURST_LEN__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF1_BURST_LEN__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF1_BYPASS_MODE 0x00000008
+#define BF_PXP_WFA_FETCH_CTRL_BF1_BYPASS_MODE(v) \
+ (((v) << 3) & BM_PXP_WFA_FETCH_CTRL_BF1_BYPASS_MODE)
+#define BV_PXP_WFA_FETCH_CTRL_BF1_BYPASS_MODE__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF1_BYPASS_MODE__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF1_HSK_MODE 0x00000004
+#define BF_PXP_WFA_FETCH_CTRL_BF1_HSK_MODE(v) \
+ (((v) << 2) & BM_PXP_WFA_FETCH_CTRL_BF1_HSK_MODE)
+#define BV_PXP_WFA_FETCH_CTRL_BF1_HSK_MODE__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF1_HSK_MODE__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF1_SRAM_IF 0x00000002
+#define BF_PXP_WFA_FETCH_CTRL_BF1_SRAM_IF(v) \
+ (((v) << 1) & BM_PXP_WFA_FETCH_CTRL_BF1_SRAM_IF)
+#define BV_PXP_WFA_FETCH_CTRL_BF1_SRAM_IF__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF1_SRAM_IF__1 0x1
+#define BM_PXP_WFA_FETCH_CTRL_BF1_EN 0x00000001
+#define BF_PXP_WFA_FETCH_CTRL_BF1_EN(v) \
+ (((v) << 0) & BM_PXP_WFA_FETCH_CTRL_BF1_EN)
+#define BV_PXP_WFA_FETCH_CTRL_BF1_EN__0 0x0
+#define BV_PXP_WFA_FETCH_CTRL_BF1_EN__1 0x1
+
+#define HW_PXP_WFA_FETCH_BUF1_ADDR (0x00000c50)
+
+#define BP_PXP_WFA_FETCH_BUF1_ADDR_BUF_ADDR 0
+#define BM_PXP_WFA_FETCH_BUF1_ADDR_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_WFA_FETCH_BUF1_ADDR_BUF_ADDR(v) (v)
+
+#define HW_PXP_WFA_FETCH_BUF1_PITCH (0x00000c60)
+
+#define BP_PXP_WFA_FETCH_BUF1_PITCH_RSVD 16
+#define BM_PXP_WFA_FETCH_BUF1_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_WFA_FETCH_BUF1_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_WFA_FETCH_BUF1_PITCH_RSVD)
+#define BP_PXP_WFA_FETCH_BUF1_PITCH_PITCH 0
+#define BM_PXP_WFA_FETCH_BUF1_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_WFA_FETCH_BUF1_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_WFA_FETCH_BUF1_PITCH_PITCH)
+
+#define HW_PXP_WFA_FETCH_BUF1_SIZE (0x00000c70)
+
+#define BP_PXP_WFA_FETCH_BUF1_SIZE_RSVD0 30
+#define BM_PXP_WFA_FETCH_BUF1_SIZE_RSVD0 0xC0000000
+#define BF_PXP_WFA_FETCH_BUF1_SIZE_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_FETCH_BUF1_SIZE_RSVD0)
+#define BP_PXP_WFA_FETCH_BUF1_SIZE_BUF_HEIGHT 16
+#define BM_PXP_WFA_FETCH_BUF1_SIZE_BUF_HEIGHT 0x3FFF0000
+#define BF_PXP_WFA_FETCH_BUF1_SIZE_BUF_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFA_FETCH_BUF1_SIZE_BUF_HEIGHT)
+#define BP_PXP_WFA_FETCH_BUF1_SIZE_RSVD1 14
+#define BM_PXP_WFA_FETCH_BUF1_SIZE_RSVD1 0x0000C000
+#define BF_PXP_WFA_FETCH_BUF1_SIZE_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFA_FETCH_BUF1_SIZE_RSVD1)
+#define BP_PXP_WFA_FETCH_BUF1_SIZE_BUF_WIDTH 0
+#define BM_PXP_WFA_FETCH_BUF1_SIZE_BUF_WIDTH 0x00003FFF
+#define BF_PXP_WFA_FETCH_BUF1_SIZE_BUF_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFA_FETCH_BUF1_SIZE_BUF_WIDTH)
+
+#define HW_PXP_WFA_FETCH_BUF2_ADDR (0x00000c80)
+
+#define BP_PXP_WFA_FETCH_BUF2_ADDR_BUF_ADDR 0
+#define BM_PXP_WFA_FETCH_BUF2_ADDR_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_WFA_FETCH_BUF2_ADDR_BUF_ADDR(v) (v)
+
+#define HW_PXP_WFA_FETCH_BUF2_PITCH (0x00000c90)
+
+#define BP_PXP_WFA_FETCH_BUF2_PITCH_RSVD 16
+#define BM_PXP_WFA_FETCH_BUF2_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_WFA_FETCH_BUF2_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_WFA_FETCH_BUF2_PITCH_RSVD)
+#define BP_PXP_WFA_FETCH_BUF2_PITCH_PITCH 0
+#define BM_PXP_WFA_FETCH_BUF2_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_WFA_FETCH_BUF2_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_WFA_FETCH_BUF2_PITCH_PITCH)
+
+#define HW_PXP_WFA_FETCH_BUF2_SIZE (0x00000ca0)
+
+#define BP_PXP_WFA_FETCH_BUF2_SIZE_RSVD0 30
+#define BM_PXP_WFA_FETCH_BUF2_SIZE_RSVD0 0xC0000000
+#define BF_PXP_WFA_FETCH_BUF2_SIZE_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_FETCH_BUF2_SIZE_RSVD0)
+#define BP_PXP_WFA_FETCH_BUF2_SIZE_BUF_HEIGHT 16
+#define BM_PXP_WFA_FETCH_BUF2_SIZE_BUF_HEIGHT 0x3FFF0000
+#define BF_PXP_WFA_FETCH_BUF2_SIZE_BUF_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFA_FETCH_BUF2_SIZE_BUF_HEIGHT)
+#define BP_PXP_WFA_FETCH_BUF2_SIZE_RSVD1 14
+#define BM_PXP_WFA_FETCH_BUF2_SIZE_RSVD1 0x0000C000
+#define BF_PXP_WFA_FETCH_BUF2_SIZE_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFA_FETCH_BUF2_SIZE_RSVD1)
+#define BP_PXP_WFA_FETCH_BUF2_SIZE_BUF_WIDTH 0
+#define BM_PXP_WFA_FETCH_BUF2_SIZE_BUF_WIDTH 0x00003FFF
+#define BF_PXP_WFA_FETCH_BUF2_SIZE_BUF_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFA_FETCH_BUF2_SIZE_BUF_WIDTH)
+
+#define HW_PXP_WFA_ARRAY_PIXEL0_MASK (0x00000cb0)
+
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL0_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_PIXEL1_MASK (0x00000cc0)
+
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_PIXEL1_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL1_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_PIXEL1_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL1_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_PIXEL1_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_PIXEL1_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_PIXEL1_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_PIXEL1_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_PIXEL2_MASK (0x00000cd0)
+
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_PIXEL2_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL2_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_PIXEL2_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL2_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_PIXEL2_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_PIXEL2_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_PIXEL2_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_PIXEL2_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_PIXEL3_MASK (0x00000ce0)
+
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_PIXEL3_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL3_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_PIXEL3_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL3_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_PIXEL3_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_PIXEL3_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_PIXEL3_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_PIXEL3_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_PIXEL4_MASK (0x00000cf0)
+
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_PIXEL4_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL4_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_PIXEL4_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL4_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_PIXEL4_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_PIXEL4_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_PIXEL4_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_PIXEL4_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_PIXEL5_MASK (0x00000d00)
+
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_PIXEL5_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL5_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_PIXEL5_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL5_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_PIXEL5_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_PIXEL5_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_PIXEL5_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_PIXEL5_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_PIXEL6_MASK (0x00000d10)
+
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_PIXEL6_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL6_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_PIXEL6_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL6_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_PIXEL6_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_PIXEL6_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_PIXEL6_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_PIXEL6_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_PIXEL7_MASK (0x00000d20)
+
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_PIXEL7_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL7_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_PIXEL7_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_PIXEL7_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_PIXEL7_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_PIXEL7_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_PIXEL7_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_PIXEL7_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG0_MASK (0x00000d30)
+
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG0_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG0_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG0_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG0_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG0_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG0_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG0_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG0_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG1_MASK (0x00000d40)
+
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG1_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG1_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG1_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG1_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG1_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG1_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG1_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG1_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG1_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG1_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG1_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG1_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG1_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG2_MASK (0x00000d50)
+
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG2_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG2_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG2_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG2_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG2_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG2_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG2_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG2_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG2_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG2_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG2_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG2_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG2_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG3_MASK (0x00000d60)
+
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG3_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG3_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG3_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG3_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG3_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG3_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG3_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG3_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG3_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG3_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG3_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG3_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG3_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG4_MASK (0x00000d70)
+
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG4_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG4_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG4_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG4_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG4_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG4_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG4_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG4_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG4_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG4_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG4_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG4_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG4_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG5_MASK (0x00000d80)
+
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG5_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG5_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG5_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG5_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG5_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG5_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG5_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG5_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG5_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG5_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG5_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG5_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG5_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG6_MASK (0x00000d90)
+
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG6_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG6_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG6_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG6_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG6_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG6_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG6_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG6_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG6_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG6_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG6_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG6_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG6_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG7_MASK (0x00000da0)
+
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG7_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG7_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG7_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG7_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG7_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG7_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG7_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG7_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG7_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG7_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG7_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG7_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG7_MASK_L_OFS)
+
+#define HW_PXP_WFA_FETCH_BUF1_CORD (0x00000db0)
+
+#define BP_PXP_WFA_FETCH_BUF1_CORD_RSVD0 30
+#define BM_PXP_WFA_FETCH_BUF1_CORD_RSVD0 0xC0000000
+#define BF_PXP_WFA_FETCH_BUF1_CORD_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_FETCH_BUF1_CORD_RSVD0)
+#define BP_PXP_WFA_FETCH_BUF1_CORD_YCORD 16
+#define BM_PXP_WFA_FETCH_BUF1_CORD_YCORD 0x3FFF0000
+#define BF_PXP_WFA_FETCH_BUF1_CORD_YCORD(v) \
+ (((v) << 16) & BM_PXP_WFA_FETCH_BUF1_CORD_YCORD)
+#define BP_PXP_WFA_FETCH_BUF1_CORD_RSVD1 14
+#define BM_PXP_WFA_FETCH_BUF1_CORD_RSVD1 0x0000C000
+#define BF_PXP_WFA_FETCH_BUF1_CORD_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFA_FETCH_BUF1_CORD_RSVD1)
+#define BP_PXP_WFA_FETCH_BUF1_CORD_XCORD 0
+#define BM_PXP_WFA_FETCH_BUF1_CORD_XCORD 0x00003FFF
+#define BF_PXP_WFA_FETCH_BUF1_CORD_XCORD(v) \
+ (((v) << 0) & BM_PXP_WFA_FETCH_BUF1_CORD_XCORD)
+
+#define HW_PXP_WFA_FETCH_BUF2_CORD (0x00000dc0)
+
+#define BP_PXP_WFA_FETCH_BUF2_CORD_RSVD0 30
+#define BM_PXP_WFA_FETCH_BUF2_CORD_RSVD0 0xC0000000
+#define BF_PXP_WFA_FETCH_BUF2_CORD_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_FETCH_BUF2_CORD_RSVD0)
+#define BP_PXP_WFA_FETCH_BUF2_CORD_YCORD 16
+#define BM_PXP_WFA_FETCH_BUF2_CORD_YCORD 0x3FFF0000
+#define BF_PXP_WFA_FETCH_BUF2_CORD_YCORD(v) \
+ (((v) << 16) & BM_PXP_WFA_FETCH_BUF2_CORD_YCORD)
+#define BP_PXP_WFA_FETCH_BUF2_CORD_RSVD1 14
+#define BM_PXP_WFA_FETCH_BUF2_CORD_RSVD1 0x0000C000
+#define BF_PXP_WFA_FETCH_BUF2_CORD_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFA_FETCH_BUF2_CORD_RSVD1)
+#define BP_PXP_WFA_FETCH_BUF2_CORD_XCORD 0
+#define BM_PXP_WFA_FETCH_BUF2_CORD_XCORD 0x00003FFF
+#define BF_PXP_WFA_FETCH_BUF2_CORD_XCORD(v) \
+ (((v) << 0) & BM_PXP_WFA_FETCH_BUF2_CORD_XCORD)
+
+#define HW_PXP_WFA_ARRAY_FLAG8_MASK (0x00000dd0)
+
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG8_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG8_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG8_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG8_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG8_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG8_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG8_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG8_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG8_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG8_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG8_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG8_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG8_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG9_MASK (0x00000de0)
+
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG9_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG9_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG9_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG9_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG9_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG9_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG9_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG9_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG9_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG9_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG9_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG9_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG9_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG10_MASK (0x00000df0)
+
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG10_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG10_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG10_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG10_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG10_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG10_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG10_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG10_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG10_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG10_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG10_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG10_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG10_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG11_MASK (0x00000e00)
+
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG11_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG11_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG11_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG11_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG11_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG11_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG11_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG11_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG11_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG11_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG11_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG11_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG11_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG12_MASK (0x00000e10)
+
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG12_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG12_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG12_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG12_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG12_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG12_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG12_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG12_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG12_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG12_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG12_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG12_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG12_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG13_MASK (0x00000e20)
+
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG13_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG13_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG13_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG13_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG13_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG13_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG13_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG13_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG13_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG13_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG13_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG13_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG13_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG14_MASK (0x00000e30)
+
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG14_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG14_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG14_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG14_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG14_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG14_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG14_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG14_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG14_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG14_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG14_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG14_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG14_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_FLAG15_MASK (0x00000e40)
+
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_RSVD0 30
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD0)
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_BUF_SEL 28
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFA_ARRAY_FLAG15_MASK_BUF_SEL)
+#define BV_PXP_WFA_ARRAY_FLAG15_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG15_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFA_ARRAY_FLAG15_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_RSVD1 26
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD1)
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_Y)
+#define BV_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_X)
+#define BV_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFA_ARRAY_FLAG15_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_RSVD2 22
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD2)
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_OFFSET_Y 20
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFA_ARRAY_FLAG15_MASK_OFFSET_Y)
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_RSVD3 18
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD3)
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_OFFSET_X 16
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_FLAG15_MASK_OFFSET_X)
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_RSVD4 13
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD4)
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_H_OFS 8
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_FLAG15_MASK_H_OFS)
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_RSVD5 5
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_FLAG15_MASK_RSVD5)
+#define BP_PXP_WFA_ARRAY_FLAG15_MASK_L_OFS 0
+#define BM_PXP_WFA_ARRAY_FLAG15_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFA_ARRAY_FLAG15_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_FLAG15_MASK_L_OFS)
+
+#define HW_PXP_WFA_ARRAY_REG0 (0x00000e50)
+
+#define BP_PXP_WFA_ARRAY_REG0_SW_PIXLE3 24
+#define BM_PXP_WFA_ARRAY_REG0_SW_PIXLE3 0xFF000000
+#define BF_PXP_WFA_ARRAY_REG0_SW_PIXLE3(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_REG0_SW_PIXLE3)
+#define BP_PXP_WFA_ARRAY_REG0_SW_PIXLE2 16
+#define BM_PXP_WFA_ARRAY_REG0_SW_PIXLE2 0x00FF0000
+#define BF_PXP_WFA_ARRAY_REG0_SW_PIXLE2(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_REG0_SW_PIXLE2)
+#define BP_PXP_WFA_ARRAY_REG0_SW_PIXLE1 8
+#define BM_PXP_WFA_ARRAY_REG0_SW_PIXLE1 0x0000FF00
+#define BF_PXP_WFA_ARRAY_REG0_SW_PIXLE1(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_REG0_SW_PIXLE1)
+#define BP_PXP_WFA_ARRAY_REG0_SW_PIXLE0 0
+#define BM_PXP_WFA_ARRAY_REG0_SW_PIXLE0 0x000000FF
+#define BF_PXP_WFA_ARRAY_REG0_SW_PIXLE0(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_REG0_SW_PIXLE0)
+
+#define HW_PXP_WFA_ARRAY_REG1 (0x00000e60)
+
+#define BP_PXP_WFA_ARRAY_REG1_SW_PIXLE7 24
+#define BM_PXP_WFA_ARRAY_REG1_SW_PIXLE7 0xFF000000
+#define BF_PXP_WFA_ARRAY_REG1_SW_PIXLE7(v) \
+ (((v) << 24) & BM_PXP_WFA_ARRAY_REG1_SW_PIXLE7)
+#define BP_PXP_WFA_ARRAY_REG1_SW_PIXLE6 16
+#define BM_PXP_WFA_ARRAY_REG1_SW_PIXLE6 0x00FF0000
+#define BF_PXP_WFA_ARRAY_REG1_SW_PIXLE6(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_REG1_SW_PIXLE6)
+#define BP_PXP_WFA_ARRAY_REG1_SW_PIXLE5 8
+#define BM_PXP_WFA_ARRAY_REG1_SW_PIXLE5 0x0000FF00
+#define BF_PXP_WFA_ARRAY_REG1_SW_PIXLE5(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_REG1_SW_PIXLE5)
+#define BP_PXP_WFA_ARRAY_REG1_SW_PIXLE4 0
+#define BM_PXP_WFA_ARRAY_REG1_SW_PIXLE4 0x000000FF
+#define BF_PXP_WFA_ARRAY_REG1_SW_PIXLE4(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_REG1_SW_PIXLE4)
+
+#define HW_PXP_WFA_ARRAY_REG2 (0x00000e70)
+
+#define BP_PXP_WFA_ARRAY_REG2_RSVD0 16
+#define BM_PXP_WFA_ARRAY_REG2_RSVD0 0xFFFF0000
+#define BF_PXP_WFA_ARRAY_REG2_RSVD0(v) \
+ (((v) << 16) & BM_PXP_WFA_ARRAY_REG2_RSVD0)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG15 0x00008000
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG15(v) \
+ (((v) << 15) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG15)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG14 0x00004000
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG14(v) \
+ (((v) << 14) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG14)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG13 0x00002000
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG13(v) \
+ (((v) << 13) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG13)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG12 0x00001000
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG12(v) \
+ (((v) << 12) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG12)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG11 0x00000800
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG11(v) \
+ (((v) << 11) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG11)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG10 0x00000400
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG10(v) \
+ (((v) << 10) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG10)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG9 0x00000200
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG9(v) \
+ (((v) << 9) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG9)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG8 0x00000100
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG8(v) \
+ (((v) << 8) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG8)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG7 0x00000080
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG7(v) \
+ (((v) << 7) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG7)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG6 0x00000040
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG6(v) \
+ (((v) << 6) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG6)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG5 0x00000020
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG5(v) \
+ (((v) << 5) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG5)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG4 0x00000010
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG4(v) \
+ (((v) << 4) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG4)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG3 0x00000008
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG3(v) \
+ (((v) << 3) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG3)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG2 0x00000004
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG2(v) \
+ (((v) << 2) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG2)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG1 0x00000002
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG1(v) \
+ (((v) << 1) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG1)
+#define BM_PXP_WFA_ARRAY_REG2_SW_FLAG0 0x00000001
+#define BF_PXP_WFA_ARRAY_REG2_SW_FLAG0(v) \
+ (((v) << 0) & BM_PXP_WFA_ARRAY_REG2_SW_FLAG0)
+
+#define HW_PXP_WFE_A_STORE_CTRL_CH0 (0x00000e80)
+#define HW_PXP_WFE_A_STORE_CTRL_CH0_SET (0x00000e84)
+#define HW_PXP_WFE_A_STORE_CTRL_CH0_CLR (0x00000e88)
+#define HW_PXP_WFE_A_STORE_CTRL_CH0_TOG (0x00000e8c)
+
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_ARBIT_EN 0x80000000
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_ARBIT_EN(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STORE_CTRL_CH0_ARBIT_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_ARBIT_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_ARBIT_EN__1 0x1
+#define BP_PXP_WFE_A_STORE_CTRL_CH0_RSVD0 25
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_RSVD0 0x7E000000
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_RSVD0(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STORE_CTRL_CH0_RSVD0)
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_COMBINE_2CHANNEL 0x01000000
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_COMBINE_2CHANNEL(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STORE_CTRL_CH0_COMBINE_2CHANNEL)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_COMBINE_2CHANNEL__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_COMBINE_2CHANNEL__1 0x1
+#define BP_PXP_WFE_A_STORE_CTRL_CH0_RSVD1 18
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_RSVD1 0x00FC0000
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_RSVD1(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STORE_CTRL_CH0_RSVD1)
+#define BP_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES 16
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES 0x00030000
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_WR_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_WFE_A_STORE_CTRL_CH0_RSVD2 12
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_RSVD2 0x0000F000
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_RSVD2(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STORE_CTRL_CH0_RSVD2)
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_FILL_DATA_EN 0x00000800
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_FILL_DATA_EN(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STORE_CTRL_CH0_FILL_DATA_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_FILL_DATA_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_FILL_DATA_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_PACK_IN_SEL 0x00000400
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_PACK_IN_SEL(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STORE_CTRL_CH0_PACK_IN_SEL)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_PACK_IN_SEL__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_PACK_IN_SEL__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_STORE_MEMORY_EN 0x00000200
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_STORE_MEMORY_EN(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STORE_CTRL_CH0_STORE_MEMORY_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_STORE_MEMORY_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_STORE_MEMORY_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_STORE_BYPASS_EN 0x00000100
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_STORE_BYPASS_EN(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_CTRL_CH0_STORE_BYPASS_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_STORE_BYPASS_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_STORE_BYPASS_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_RSVD3 0x00000080
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STORE_CTRL_CH0_RSVD3)
+#define BP_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM 5
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM 0x00000060
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM__1 0x1
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM__2 0x2
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_LINE_NUM__3 0x3
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_EN 0x00000010
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_EN(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_ARRAY_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_HANDSHAKE_EN 0x00000008
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STORE_CTRL_CH0_HANDSHAKE_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_HANDSHAKE_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_HANDSHAKE_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_16 0x00000004
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_16)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_16__8x8 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_16__16x16 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_EN 0x00000002
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_BLOCK_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH0_CH_EN 0x00000001
+#define BF_PXP_WFE_A_STORE_CTRL_CH0_CH_EN(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_CTRL_CH0_CH_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_CH_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH0_CH_EN__1 0x1
+
+#define HW_PXP_WFE_A_STORE_CTRL_CH1 (0x00000e90)
+#define HW_PXP_WFE_A_STORE_CTRL_CH1_SET (0x00000e94)
+#define HW_PXP_WFE_A_STORE_CTRL_CH1_CLR (0x00000e98)
+#define HW_PXP_WFE_A_STORE_CTRL_CH1_TOG (0x00000e9c)
+
+#define BP_PXP_WFE_A_STORE_CTRL_CH1_RSVD0 18
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_RSVD0 0xFFFC0000
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_RSVD0(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STORE_CTRL_CH1_RSVD0)
+#define BP_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES 16
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES 0x00030000
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_WFE_A_STORE_CTRL_CH1_RSVD1 11
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_RSVD1 0x0000F800
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_RSVD1(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STORE_CTRL_CH1_RSVD1)
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL 0x00000400
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN 0x00000200
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_STORE_BYPASS_EN 0x00000100
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_STORE_BYPASS_EN(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_CTRL_CH1_STORE_BYPASS_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_STORE_BYPASS_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_STORE_BYPASS_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_RSVD3 0x00000080
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_RSVD3(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STORE_CTRL_CH1_RSVD3)
+#define BP_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM 5
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM 0x00000060
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM__1 0x1
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM__2 0x2
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_LINE_NUM__3 0x3
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_EN 0x00000010
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_EN(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_ARRAY_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_HANDSHAKE_EN 0x00000008
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STORE_CTRL_CH1_HANDSHAKE_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_HANDSHAKE_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_HANDSHAKE_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_16 0x00000004
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_16)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_16__8x8 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_16__16x16 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_EN 0x00000002
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_BLOCK_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_CTRL_CH1_CH_EN 0x00000001
+#define BF_PXP_WFE_A_STORE_CTRL_CH1_CH_EN(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_CTRL_CH1_CH_EN)
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_CH_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_CTRL_CH1_CH_EN__1 0x1
+
+#define HW_PXP_WFE_A_STORE_STATUS_CH0 (0x00000ea0)
+
+#define BP_PXP_WFE_A_STORE_STATUS_CH0_STORE_BLOCK_Y 16
+#define BM_PXP_WFE_A_STORE_STATUS_CH0_STORE_BLOCK_Y 0xFFFF0000
+#define BF_PXP_WFE_A_STORE_STATUS_CH0_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_STATUS_CH0_STORE_BLOCK_Y)
+#define BP_PXP_WFE_A_STORE_STATUS_CH0_STORE_BLOCK_X 0
+#define BM_PXP_WFE_A_STORE_STATUS_CH0_STORE_BLOCK_X 0x0000FFFF
+#define BF_PXP_WFE_A_STORE_STATUS_CH0_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_STATUS_CH0_STORE_BLOCK_X)
+
+#define HW_PXP_WFE_A_STORE_STATUS_CH1 (0x00000eb0)
+
+#define BP_PXP_WFE_A_STORE_STATUS_CH1_STORE_BLOCK_Y 16
+#define BM_PXP_WFE_A_STORE_STATUS_CH1_STORE_BLOCK_Y 0xFFFF0000
+#define BF_PXP_WFE_A_STORE_STATUS_CH1_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_STATUS_CH1_STORE_BLOCK_Y)
+#define BP_PXP_WFE_A_STORE_STATUS_CH1_STORE_BLOCK_X 0
+#define BM_PXP_WFE_A_STORE_STATUS_CH1_STORE_BLOCK_X 0x0000FFFF
+#define BF_PXP_WFE_A_STORE_STATUS_CH1_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_STATUS_CH1_STORE_BLOCK_X)
+
+#define HW_PXP_WFE_A_STORE_SIZE_CH0 (0x00000ec0)
+
+#define BP_PXP_WFE_A_STORE_SIZE_CH0_OUT_HEIGHT 16
+#define BM_PXP_WFE_A_STORE_SIZE_CH0_OUT_HEIGHT 0xFFFF0000
+#define BF_PXP_WFE_A_STORE_SIZE_CH0_OUT_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_SIZE_CH0_OUT_HEIGHT)
+#define BP_PXP_WFE_A_STORE_SIZE_CH0_OUT_WIDTH 0
+#define BM_PXP_WFE_A_STORE_SIZE_CH0_OUT_WIDTH 0x0000FFFF
+#define BF_PXP_WFE_A_STORE_SIZE_CH0_OUT_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_SIZE_CH0_OUT_WIDTH)
+
+#define HW_PXP_WFE_A_STORE_SIZE_CH1 (0x00000ed0)
+
+#define BP_PXP_WFE_A_STORE_SIZE_CH1_OUT_HEIGHT 16
+#define BM_PXP_WFE_A_STORE_SIZE_CH1_OUT_HEIGHT 0xFFFF0000
+#define BF_PXP_WFE_A_STORE_SIZE_CH1_OUT_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_SIZE_CH1_OUT_HEIGHT)
+#define BP_PXP_WFE_A_STORE_SIZE_CH1_OUT_WIDTH 0
+#define BM_PXP_WFE_A_STORE_SIZE_CH1_OUT_WIDTH 0x0000FFFF
+#define BF_PXP_WFE_A_STORE_SIZE_CH1_OUT_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_SIZE_CH1_OUT_WIDTH)
+
+#define HW_PXP_WFE_A_STORE_PITCH (0x00000ee0)
+
+#define BP_PXP_WFE_A_STORE_PITCH_CH1_OUT_PITCH 16
+#define BM_PXP_WFE_A_STORE_PITCH_CH1_OUT_PITCH 0xFFFF0000
+#define BF_PXP_WFE_A_STORE_PITCH_CH1_OUT_PITCH(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_PITCH_CH1_OUT_PITCH)
+#define BP_PXP_WFE_A_STORE_PITCH_CH0_OUT_PITCH 0
+#define BM_PXP_WFE_A_STORE_PITCH_CH0_OUT_PITCH 0x0000FFFF
+#define BF_PXP_WFE_A_STORE_PITCH_CH0_OUT_PITCH(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_PITCH_CH0_OUT_PITCH)
+
+#define HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH0 (0x00000ef0)
+#define HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_SET (0x00000ef4)
+#define HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_CLR (0x00000ef8)
+#define HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_TOG (0x00000efc)
+
+#define BP_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD0 8
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD0 0xFFFFFF00
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD0(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD0)
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS 0x00000080
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS)
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS__0 0x0
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS__1 0x1
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD1 0x00000040
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD1(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD1)
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN 0x00000020
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN)
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN 0x00000010
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN)
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN__1 0x1
+#define BP_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP 2
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP 0x0000000C
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP)
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__3 0x3
+#define BP_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD2 0
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD2 0x00000003
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD2(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH0_RSVD2)
+
+#define HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH1 (0x00000f00)
+#define HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_SET (0x00000f04)
+#define HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_CLR (0x00000f08)
+#define HW_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_TOG (0x00000f0c)
+
+#define BP_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_RSVD0 6
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_RSVD0 0xFFFFFFC0
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_RSVD0(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_RSVD0)
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN 0x00000020
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN)
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN__1 0x1
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN 0x00000010
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN)
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN__0 0x0
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN__1 0x1
+#define BP_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP 2
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP 0x0000000C
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP)
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__3 0x3
+#define BP_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_RSVD2 0
+#define BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_RSVD2 0x00000003
+#define BF_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_RSVD2(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_SHIFT_CTRL_CH1_RSVD2)
+
+#define HW_PXP_WFE_A_STORE_ADDR_0_CH0 (0x00000f50)
+
+#define BP_PXP_WFE_A_STORE_ADDR_0_CH0_OUT_BASE_ADDR0 0
+#define BM_PXP_WFE_A_STORE_ADDR_0_CH0_OUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_ADDR_1_CH0 (0x00000f60)
+
+#define BP_PXP_WFE_A_STORE_ADDR_1_CH0_OUT_BASE_ADDR1 0
+#define BM_PXP_WFE_A_STORE_ADDR_1_CH0_OUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_WFE_A_STORE_FILL_DATA_CH0 (0x00000f70)
+
+#define BP_PXP_WFE_A_STORE_FILL_DATA_CH0_FILL_DATA_CH0 0
+#define BM_PXP_WFE_A_STORE_FILL_DATA_CH0_FILL_DATA_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_FILL_DATA_CH0_FILL_DATA_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_ADDR_0_CH1 (0x00000f80)
+
+#define BP_PXP_WFE_A_STORE_ADDR_0_CH1_OUT_BASE_ADDR0 0
+#define BM_PXP_WFE_A_STORE_ADDR_0_CH1_OUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_ADDR_1_CH1 (0x00000f90)
+
+#define BP_PXP_WFE_A_STORE_ADDR_1_CH1_OUT_BASE_ADDR1 0
+#define BM_PXP_WFE_A_STORE_ADDR_1_CH1_OUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK0_H_CH0 (0x00000fa0)
+
+#define BP_PXP_WFE_A_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK0_L_CH0 (0x00000fb0)
+
+#define BP_PXP_WFE_A_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK1_H_CH0 (0x00000fc0)
+
+#define BP_PXP_WFE_A_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK1_L_CH0 (0x00000fd0)
+
+#define BP_PXP_WFE_A_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK2_H_CH0 (0x00000fe0)
+
+#define BP_PXP_WFE_A_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK2_L_CH0 (0x00000ff0)
+
+#define BP_PXP_WFE_A_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK3_H_CH0 (0x00001000)
+
+#define BP_PXP_WFE_A_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK3_L_CH0 (0x00001010)
+
+#define BP_PXP_WFE_A_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK4_H_CH0 (0x00001020)
+
+#define BP_PXP_WFE_A_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK4_L_CH0 (0x00001030)
+
+#define BP_PXP_WFE_A_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK5_H_CH0 (0x00001040)
+
+#define BP_PXP_WFE_A_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK5_L_CH0 (0x00001050)
+
+#define BP_PXP_WFE_A_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK6_H_CH0 (0x00001060)
+
+#define BP_PXP_WFE_A_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK6_L_CH0 (0x00001070)
+
+#define BP_PXP_WFE_A_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK7_H_CH0 (0x00001080)
+
+#define BP_PXP_WFE_A_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_MASK7_L_CH0 (0x00001090)
+
+#define BP_PXP_WFE_A_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0 0
+#define BM_PXP_WFE_A_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_A_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0(v) (v)
+
+#define HW_PXP_WFE_A_STORE_D_SHIFT_L_CH0 (0x000010a0)
+
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3 0x80000000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD0 0x40000000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD0)
+#define BP_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3 24
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3 0x3F000000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2 0x00800000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD1 0x00400000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD1)
+#define BP_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2 16
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2 0x003F0000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1 0x00008000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD2 0x00004000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD2)
+#define BP_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1 8
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1 0x00003F00
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0 0x00000080
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD3 0x00000040
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_RSVD3)
+#define BP_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0 0
+#define BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0 0x0000003F
+#define BF_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0)
+
+#define HW_PXP_WFE_A_STORE_D_SHIFT_H_CH0 (0x000010b0)
+
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7 0x80000000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD0 0x40000000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD0)
+#define BP_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7 24
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7 0x3F000000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6 0x00800000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD1 0x00400000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD1)
+#define BP_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6 16
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6 0x003F0000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5 0x00008000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD2 0x00004000
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD2)
+#define BP_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5 8
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5 0x00003F00
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4 0x00000080
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4)
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD3 0x00000040
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_RSVD3)
+#define BP_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4 0
+#define BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4 0x0000003F
+#define BF_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4)
+
+#define HW_PXP_WFE_A_STORE_F_SHIFT_L_CH0 (0x000010c0)
+
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD0 0x80000000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD0(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD0)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3 0x40000000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3)
+#define BP_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3 24
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3 0x3F000000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD1 0x00800000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD1(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD1)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2 0x00400000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2)
+#define BP_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2 16
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2 0x003F0000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD2 0x00008000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD2(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD2)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1 0x00004000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1)
+#define BP_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1 8
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1 0x00003F00
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD3 0x00000080
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_RSVD3)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0 0x00000040
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0)
+#define BP_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0 0
+#define BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0 0x0000003F
+#define BF_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0)
+
+#define HW_PXP_WFE_A_STORE_F_SHIFT_H_CH0 (0x000010d0)
+
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD0 0x80000000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD0(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD0)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7 0x40000000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7)
+#define BP_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7 24
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7 0x3F000000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD1 0x00800000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD1(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD1)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6 0x00400000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6)
+#define BP_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6 16
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6 0x003F0000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD2 0x00008000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD2(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD2)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5 0x00004000
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5)
+#define BP_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5 8
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5 0x00003F00
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD3 0x00000080
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_RSVD3)
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4 0x00000040
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4)
+#define BP_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4 0
+#define BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4 0x0000003F
+#define BF_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4)
+
+#define HW_PXP_WFE_A_STORE_F_MASK_L_CH0 (0x000010e0)
+
+#define BP_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK3 24
+#define BM_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK3 0xFF000000
+#define BF_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK3)
+#define BP_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK2 16
+#define BM_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK2 0x00FF0000
+#define BF_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK2)
+#define BP_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK1 8
+#define BM_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK1 0x0000FF00
+#define BF_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK1)
+#define BP_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK0 0
+#define BM_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK0 0x000000FF
+#define BF_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK0)
+
+#define HW_PXP_WFE_A_STORE_F_MASK_H_CH0 (0x000010f0)
+
+#define BP_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK7 24
+#define BM_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK7 0xFF000000
+#define BF_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK7)
+#define BP_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK6 16
+#define BM_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK6 0x00FF0000
+#define BF_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK6)
+#define BP_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK5 8
+#define BM_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK5 0x0000FF00
+#define BF_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK5)
+#define BP_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK4 0
+#define BM_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK4 0x000000FF
+#define BF_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STORE_F_MASK_H_CH0_F_MASK4)
+
+#define HW_PXP_WFB_FETCH_CTRL (0x00001100)
+#define HW_PXP_WFB_FETCH_CTRL_SET (0x00001104)
+#define HW_PXP_WFB_FETCH_CTRL_CLR (0x00001108)
+#define HW_PXP_WFB_FETCH_CTRL_TOG (0x0000110c)
+
+#define BM_PXP_WFB_FETCH_CTRL_BUF2_DONE_IRQ_EN 0x80000000
+#define BF_PXP_WFB_FETCH_CTRL_BUF2_DONE_IRQ_EN(v) \
+ (((v) << 31) & BM_PXP_WFB_FETCH_CTRL_BUF2_DONE_IRQ_EN)
+#define BM_PXP_WFB_FETCH_CTRL_BUF1_DONE_IRQ_EN 0x40000000
+#define BF_PXP_WFB_FETCH_CTRL_BUF1_DONE_IRQ_EN(v) \
+ (((v) << 30) & BM_PXP_WFB_FETCH_CTRL_BUF1_DONE_IRQ_EN)
+#define BM_PXP_WFB_FETCH_CTRL_BUF2_DONE_IRQ 0x20000000
+#define BF_PXP_WFB_FETCH_CTRL_BUF2_DONE_IRQ(v) \
+ (((v) << 29) & BM_PXP_WFB_FETCH_CTRL_BUF2_DONE_IRQ)
+#define BM_PXP_WFB_FETCH_CTRL_BUF1_DONE_IRQ 0x10000000
+#define BF_PXP_WFB_FETCH_CTRL_BUF1_DONE_IRQ(v) \
+ (((v) << 28) & BM_PXP_WFB_FETCH_CTRL_BUF1_DONE_IRQ)
+#define BP_PXP_WFB_FETCH_CTRL_RSVD0 24
+#define BM_PXP_WFB_FETCH_CTRL_RSVD0 0x0F000000
+#define BF_PXP_WFB_FETCH_CTRL_RSVD0(v) \
+ (((v) << 24) & BM_PXP_WFB_FETCH_CTRL_RSVD0)
+#define BP_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE 22
+#define BM_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE 0x00C00000
+#define BF_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE(v) \
+ (((v) << 22) & BM_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE)
+#define BV_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE__1 0x1
+#define BV_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE__2 0x2
+#define BV_PXP_WFB_FETCH_CTRL_BF2_LINE_MODE__3 0x3
+#define BP_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP 20
+#define BM_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP 0x00300000
+#define BF_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP(v) \
+ (((v) << 20) & BM_PXP_WFB_FETCH_CTRL_BF2_BYTES_PP)
+#define BP_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE 18
+#define BM_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE 0x000C0000
+#define BF_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE(v) \
+ (((v) << 18) & BM_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE)
+#define BV_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE__1 0x1
+#define BV_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE__2 0x2
+#define BV_PXP_WFB_FETCH_CTRL_BF1_LINE_MODE__3 0x3
+#define BP_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP 16
+#define BM_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP 0x00030000
+#define BF_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP(v) \
+ (((v) << 16) & BM_PXP_WFB_FETCH_CTRL_BF1_BYTES_PP)
+#define BP_PXP_WFB_FETCH_CTRL_RSVD1 14
+#define BM_PXP_WFB_FETCH_CTRL_RSVD1 0x0000C000
+#define BF_PXP_WFB_FETCH_CTRL_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFB_FETCH_CTRL_RSVD1)
+#define BM_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE 0x00002000
+#define BF_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE(v) \
+ (((v) << 13) & BM_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE)
+#define BV_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF2_BORDER_MODE__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN 0x00001000
+#define BF_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN(v) \
+ (((v) << 12) & BM_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN)
+#define BV_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF2_BURST_LEN__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE 0x00000800
+#define BF_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE(v) \
+ (((v) << 11) & BM_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE)
+#define BV_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF2_BYPASS_MODE__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE 0x00000400
+#define BF_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE(v) \
+ (((v) << 10) & BM_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE)
+#define BV_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF2_HSK_MODE__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF 0x00000200
+#define BF_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF(v) \
+ (((v) << 9) & BM_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF)
+#define BV_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF2_SRAM_IF__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF2_EN 0x00000100
+#define BF_PXP_WFB_FETCH_CTRL_BF2_EN(v) \
+ (((v) << 8) & BM_PXP_WFB_FETCH_CTRL_BF2_EN)
+#define BV_PXP_WFB_FETCH_CTRL_BF2_EN__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF2_EN__1 0x1
+#define BP_PXP_WFB_FETCH_CTRL_RSVD2 6
+#define BM_PXP_WFB_FETCH_CTRL_RSVD2 0x000000C0
+#define BF_PXP_WFB_FETCH_CTRL_RSVD2(v) \
+ (((v) << 6) & BM_PXP_WFB_FETCH_CTRL_RSVD2)
+#define BM_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE 0x00000020
+#define BF_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE(v) \
+ (((v) << 5) & BM_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE)
+#define BV_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF1_BORDER_MODE__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN 0x00000010
+#define BF_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN(v) \
+ (((v) << 4) & BM_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN)
+#define BV_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF1_BURST_LEN__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE 0x00000008
+#define BF_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE(v) \
+ (((v) << 3) & BM_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE)
+#define BV_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF1_BYPASS_MODE__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE 0x00000004
+#define BF_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE(v) \
+ (((v) << 2) & BM_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE)
+#define BV_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF1_HSK_MODE__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF 0x00000002
+#define BF_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF(v) \
+ (((v) << 1) & BM_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF)
+#define BV_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF1_SRAM_IF__1 0x1
+#define BM_PXP_WFB_FETCH_CTRL_BF1_EN 0x00000001
+#define BF_PXP_WFB_FETCH_CTRL_BF1_EN(v) \
+ (((v) << 0) & BM_PXP_WFB_FETCH_CTRL_BF1_EN)
+#define BV_PXP_WFB_FETCH_CTRL_BF1_EN__0 0x0
+#define BV_PXP_WFB_FETCH_CTRL_BF1_EN__1 0x1
+
+#define HW_PXP_WFB_FETCH_BUF1_ADDR (0x00001110)
+
+#define BP_PXP_WFB_FETCH_BUF1_ADDR_BUF_ADDR 0
+#define BM_PXP_WFB_FETCH_BUF1_ADDR_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_WFB_FETCH_BUF1_ADDR_BUF_ADDR(v) (v)
+
+#define HW_PXP_WFB_FETCH_BUF1_PITCH (0x00001120)
+
+#define BP_PXP_WFB_FETCH_BUF1_PITCH_RSVD 16
+#define BM_PXP_WFB_FETCH_BUF1_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_WFB_FETCH_BUF1_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_WFB_FETCH_BUF1_PITCH_RSVD)
+#define BP_PXP_WFB_FETCH_BUF1_PITCH_PITCH 0
+#define BM_PXP_WFB_FETCH_BUF1_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_WFB_FETCH_BUF1_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_WFB_FETCH_BUF1_PITCH_PITCH)
+
+#define HW_PXP_WFB_FETCH_BUF1_SIZE (0x00001130)
+
+#define BP_PXP_WFB_FETCH_BUF1_SIZE_BUF_HEIGHT 16
+#define BM_PXP_WFB_FETCH_BUF1_SIZE_BUF_HEIGHT 0xFFFF0000
+#define BF_PXP_WFB_FETCH_BUF1_SIZE_BUF_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFB_FETCH_BUF1_SIZE_BUF_HEIGHT)
+#define BP_PXP_WFB_FETCH_BUF1_SIZE_BUF_WIDTH 0
+#define BM_PXP_WFB_FETCH_BUF1_SIZE_BUF_WIDTH 0x0000FFFF
+#define BF_PXP_WFB_FETCH_BUF1_SIZE_BUF_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFB_FETCH_BUF1_SIZE_BUF_WIDTH)
+
+#define HW_PXP_WFB_FETCH_BUF2_ADDR (0x00001140)
+
+#define BP_PXP_WFB_FETCH_BUF2_ADDR_BUF_ADDR 0
+#define BM_PXP_WFB_FETCH_BUF2_ADDR_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_WFB_FETCH_BUF2_ADDR_BUF_ADDR(v) (v)
+
+#define HW_PXP_WFB_FETCH_BUF2_PITCH (0x00001150)
+
+#define BP_PXP_WFB_FETCH_BUF2_PITCH_RSVD 16
+#define BM_PXP_WFB_FETCH_BUF2_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_WFB_FETCH_BUF2_PITCH_RSVD(v) \
+ (((v) << 16) & BM_PXP_WFB_FETCH_BUF2_PITCH_RSVD)
+#define BP_PXP_WFB_FETCH_BUF2_PITCH_PITCH 0
+#define BM_PXP_WFB_FETCH_BUF2_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_WFB_FETCH_BUF2_PITCH_PITCH(v) \
+ (((v) << 0) & BM_PXP_WFB_FETCH_BUF2_PITCH_PITCH)
+
+#define HW_PXP_WFB_FETCH_BUF2_SIZE (0x00001160)
+
+#define BP_PXP_WFB_FETCH_BUF2_SIZE_BUF_HEIGHT 16
+#define BM_PXP_WFB_FETCH_BUF2_SIZE_BUF_HEIGHT 0xFFFF0000
+#define BF_PXP_WFB_FETCH_BUF2_SIZE_BUF_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFB_FETCH_BUF2_SIZE_BUF_HEIGHT)
+#define BP_PXP_WFB_FETCH_BUF2_SIZE_BUF_WIDTH 0
+#define BM_PXP_WFB_FETCH_BUF2_SIZE_BUF_WIDTH 0x0000FFFF
+#define BF_PXP_WFB_FETCH_BUF2_SIZE_BUF_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFB_FETCH_BUF2_SIZE_BUF_WIDTH)
+
+#define HW_PXP_WFB_ARRAY_PIXEL0_MASK (0x00001170)
+
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_PIXEL0_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL0_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_PIXEL0_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_PIXEL0_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_PIXEL0_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_PIXEL0_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_PIXEL1_MASK (0x00001180)
+
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_PIXEL1_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL1_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_PIXEL1_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_PIXEL1_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_PIXEL1_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_PIXEL1_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_PIXEL2_MASK (0x00001190)
+
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_PIXEL2_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL2_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_PIXEL2_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_PIXEL2_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_PIXEL2_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_PIXEL2_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_PIXEL3_MASK (0x000011a0)
+
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_PIXEL3_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL3_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_PIXEL3_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_PIXEL3_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_PIXEL3_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_PIXEL3_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_PIXEL4_MASK (0x000011b0)
+
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_PIXEL4_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL4_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_PIXEL4_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_PIXEL4_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_PIXEL4_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_PIXEL4_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_PIXEL5_MASK (0x000011c0)
+
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_PIXEL5_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL5_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_PIXEL5_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL5_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_PIXEL5_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_PIXEL5_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_PIXEL5_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_PIXEL5_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_PIXEL6_MASK (0x000011d0)
+
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_PIXEL6_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL6_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_PIXEL6_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL6_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_PIXEL6_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_PIXEL6_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_PIXEL6_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_PIXEL6_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_PIXEL7_MASK (0x000011e0)
+
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_PIXEL7_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL7_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_PIXEL7_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_PIXEL7_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_PIXEL7_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_PIXEL7_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_PIXEL7_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_PIXEL7_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG0_MASK (0x000011f0)
+
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG0_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG0_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG0_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG0_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG0_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG0_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG0_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG0_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG0_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG1_MASK (0x00001200)
+
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG1_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG1_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG1_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG1_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG1_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG1_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG1_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG1_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG1_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG1_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG1_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG1_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG2_MASK (0x00001210)
+
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG2_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG2_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG2_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG2_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG2_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG2_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG2_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG2_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG2_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG2_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG2_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG2_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG3_MASK (0x00001220)
+
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG3_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG3_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG3_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG3_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG3_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG3_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG3_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG3_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG3_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG3_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG3_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG3_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG4_MASK (0x00001230)
+
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG4_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG4_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG4_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG4_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG4_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG4_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG4_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG4_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG4_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG4_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG4_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG4_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG5_MASK (0x00001240)
+
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG5_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG5_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG5_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG5_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG5_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG5_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG5_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG5_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG5_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG5_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG5_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG5_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG6_MASK (0x00001250)
+
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG6_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG6_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG6_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG6_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG6_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG6_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG6_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG6_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG6_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG6_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG6_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG6_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG7_MASK (0x00001260)
+
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG7_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG7_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG7_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG7_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG7_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG7_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG7_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG7_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG7_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG7_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG7_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG7_MASK_L_OFS)
+
+#define HW_PXP_WFB_FETCH_BUF1_CORD (0x00001270)
+
+#define BP_PXP_WFB_FETCH_BUF1_CORD_RSVD0 30
+#define BM_PXP_WFB_FETCH_BUF1_CORD_RSVD0 0xC0000000
+#define BF_PXP_WFB_FETCH_BUF1_CORD_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_FETCH_BUF1_CORD_RSVD0)
+#define BP_PXP_WFB_FETCH_BUF1_CORD_YCORD 16
+#define BM_PXP_WFB_FETCH_BUF1_CORD_YCORD 0x3FFF0000
+#define BF_PXP_WFB_FETCH_BUF1_CORD_YCORD(v) \
+ (((v) << 16) & BM_PXP_WFB_FETCH_BUF1_CORD_YCORD)
+#define BP_PXP_WFB_FETCH_BUF1_CORD_RSVD1 14
+#define BM_PXP_WFB_FETCH_BUF1_CORD_RSVD1 0x0000C000
+#define BF_PXP_WFB_FETCH_BUF1_CORD_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFB_FETCH_BUF1_CORD_RSVD1)
+#define BP_PXP_WFB_FETCH_BUF1_CORD_XCORD 0
+#define BM_PXP_WFB_FETCH_BUF1_CORD_XCORD 0x00003FFF
+#define BF_PXP_WFB_FETCH_BUF1_CORD_XCORD(v) \
+ (((v) << 0) & BM_PXP_WFB_FETCH_BUF1_CORD_XCORD)
+
+#define HW_PXP_WFB_FETCH_BUF2_CORD (0x00001280)
+
+#define BP_PXP_WFB_FETCH_BUF2_CORD_RSVD0 30
+#define BM_PXP_WFB_FETCH_BUF2_CORD_RSVD0 0xC0000000
+#define BF_PXP_WFB_FETCH_BUF2_CORD_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_FETCH_BUF2_CORD_RSVD0)
+#define BP_PXP_WFB_FETCH_BUF2_CORD_YCORD 16
+#define BM_PXP_WFB_FETCH_BUF2_CORD_YCORD 0x3FFF0000
+#define BF_PXP_WFB_FETCH_BUF2_CORD_YCORD(v) \
+ (((v) << 16) & BM_PXP_WFB_FETCH_BUF2_CORD_YCORD)
+#define BP_PXP_WFB_FETCH_BUF2_CORD_RSVD1 14
+#define BM_PXP_WFB_FETCH_BUF2_CORD_RSVD1 0x0000C000
+#define BF_PXP_WFB_FETCH_BUF2_CORD_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFB_FETCH_BUF2_CORD_RSVD1)
+#define BP_PXP_WFB_FETCH_BUF2_CORD_XCORD 0
+#define BM_PXP_WFB_FETCH_BUF2_CORD_XCORD 0x00003FFF
+#define BF_PXP_WFB_FETCH_BUF2_CORD_XCORD(v) \
+ (((v) << 0) & BM_PXP_WFB_FETCH_BUF2_CORD_XCORD)
+
+#define HW_PXP_WFB_ARRAY_FLAG8_MASK (0x00001290)
+
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG8_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG8_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG8_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG8_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG8_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG8_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG8_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG8_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG8_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG8_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG8_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG8_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG9_MASK (0x000012a0)
+
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG9_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG9_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG9_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG9_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG9_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG9_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG9_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG9_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG9_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG9_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG9_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG9_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG10_MASK (0x000012b0)
+
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG10_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG10_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG10_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG10_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG10_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG10_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG10_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG10_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG10_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG10_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG10_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG10_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG10_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG11_MASK (0x000012c0)
+
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG11_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG11_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG11_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG11_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG11_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG11_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG11_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG11_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG11_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG11_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG11_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG11_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG11_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG12_MASK (0x000012d0)
+
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG12_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG12_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG12_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG12_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG12_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG12_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG12_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG12_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG12_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG12_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG12_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG12_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG12_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG13_MASK (0x000012e0)
+
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG13_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG13_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG13_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG13_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG13_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG13_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG13_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG13_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG13_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG13_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG13_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG13_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG13_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG14_MASK (0x000012f0)
+
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG14_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG14_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG14_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG14_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG14_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG14_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG14_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG14_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG14_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG14_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG14_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG14_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG14_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_FLAG15_MASK (0x00001300)
+
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_RSVD0 30
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD0 0xC0000000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD0)
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_BUF_SEL 28
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_BUF_SEL 0x30000000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_WFB_ARRAY_FLAG15_MASK_BUF_SEL)
+#define BV_PXP_WFB_ARRAY_FLAG15_MASK_BUF_SEL__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG15_MASK_BUF_SEL__1 0x1
+#define BV_PXP_WFB_ARRAY_FLAG15_MASK_BUF_SEL__2 0x2
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_RSVD1 26
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD1 0x0C000000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_RSVD1(v) \
+ (((v) << 26) & BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD1)
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_Y 0x02000000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_Y(v) \
+ (((v) << 25) & BM_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_Y)
+#define BV_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_Y__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_Y__1 0x1
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_X 0x01000000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_X(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_X)
+#define BV_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_X__0 0x0
+#define BV_PXP_WFB_ARRAY_FLAG15_MASK_SIGN_X__1 0x1
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_RSVD2 22
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD2 0x00C00000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD2)
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_OFFSET_Y 20
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_OFFSET_Y 0x00300000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_OFFSET_Y(v) \
+ (((v) << 20) & BM_PXP_WFB_ARRAY_FLAG15_MASK_OFFSET_Y)
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_RSVD3 18
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD3 0x000C0000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_RSVD3(v) \
+ (((v) << 18) & BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD3)
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_OFFSET_X 16
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_OFFSET_X 0x00030000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_OFFSET_X(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_FLAG15_MASK_OFFSET_X)
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_RSVD4 13
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD4 0x0000E000
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_RSVD4(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD4)
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_H_OFS 8
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_H_OFS 0x00001F00
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_H_OFS(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_FLAG15_MASK_H_OFS)
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_RSVD5 5
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD5 0x000000E0
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_RSVD5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_FLAG15_MASK_RSVD5)
+#define BP_PXP_WFB_ARRAY_FLAG15_MASK_L_OFS 0
+#define BM_PXP_WFB_ARRAY_FLAG15_MASK_L_OFS 0x0000001F
+#define BF_PXP_WFB_ARRAY_FLAG15_MASK_L_OFS(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_FLAG15_MASK_L_OFS)
+
+#define HW_PXP_WFB_ARRAY_REG0 (0x00001310)
+
+#define BP_PXP_WFB_ARRAY_REG0_SW_PIXLE3 24
+#define BM_PXP_WFB_ARRAY_REG0_SW_PIXLE3 0xFF000000
+#define BF_PXP_WFB_ARRAY_REG0_SW_PIXLE3(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_REG0_SW_PIXLE3)
+#define BP_PXP_WFB_ARRAY_REG0_SW_PIXLE2 16
+#define BM_PXP_WFB_ARRAY_REG0_SW_PIXLE2 0x00FF0000
+#define BF_PXP_WFB_ARRAY_REG0_SW_PIXLE2(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_REG0_SW_PIXLE2)
+#define BP_PXP_WFB_ARRAY_REG0_SW_PIXLE1 8
+#define BM_PXP_WFB_ARRAY_REG0_SW_PIXLE1 0x0000FF00
+#define BF_PXP_WFB_ARRAY_REG0_SW_PIXLE1(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_REG0_SW_PIXLE1)
+#define BP_PXP_WFB_ARRAY_REG0_SW_PIXLE0 0
+#define BM_PXP_WFB_ARRAY_REG0_SW_PIXLE0 0x000000FF
+#define BF_PXP_WFB_ARRAY_REG0_SW_PIXLE0(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_REG0_SW_PIXLE0)
+
+#define HW_PXP_WFB_ARRAY_REG1 (0x00001320)
+
+#define BP_PXP_WFB_ARRAY_REG1_SW_PIXLE7 24
+#define BM_PXP_WFB_ARRAY_REG1_SW_PIXLE7 0xFF000000
+#define BF_PXP_WFB_ARRAY_REG1_SW_PIXLE7(v) \
+ (((v) << 24) & BM_PXP_WFB_ARRAY_REG1_SW_PIXLE7)
+#define BP_PXP_WFB_ARRAY_REG1_SW_PIXLE6 16
+#define BM_PXP_WFB_ARRAY_REG1_SW_PIXLE6 0x00FF0000
+#define BF_PXP_WFB_ARRAY_REG1_SW_PIXLE6(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_REG1_SW_PIXLE6)
+#define BP_PXP_WFB_ARRAY_REG1_SW_PIXLE5 8
+#define BM_PXP_WFB_ARRAY_REG1_SW_PIXLE5 0x0000FF00
+#define BF_PXP_WFB_ARRAY_REG1_SW_PIXLE5(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_REG1_SW_PIXLE5)
+#define BP_PXP_WFB_ARRAY_REG1_SW_PIXLE4 0
+#define BM_PXP_WFB_ARRAY_REG1_SW_PIXLE4 0x000000FF
+#define BF_PXP_WFB_ARRAY_REG1_SW_PIXLE4(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_REG1_SW_PIXLE4)
+
+#define HW_PXP_WFB_ARRAY_REG2 (0x00001330)
+
+#define BP_PXP_WFB_ARRAY_REG2_RSVD0 16
+#define BM_PXP_WFB_ARRAY_REG2_RSVD0 0xFFFF0000
+#define BF_PXP_WFB_ARRAY_REG2_RSVD0(v) \
+ (((v) << 16) & BM_PXP_WFB_ARRAY_REG2_RSVD0)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG15 0x00008000
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG15(v) \
+ (((v) << 15) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG15)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG14 0x00004000
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG14(v) \
+ (((v) << 14) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG14)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG13 0x00002000
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG13(v) \
+ (((v) << 13) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG13)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG12 0x00001000
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG12(v) \
+ (((v) << 12) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG12)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG11 0x00000800
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG11(v) \
+ (((v) << 11) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG11)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG10 0x00000400
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG10(v) \
+ (((v) << 10) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG10)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG9 0x00000200
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG9(v) \
+ (((v) << 9) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG9)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG8 0x00000100
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG8(v) \
+ (((v) << 8) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG8)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG7 0x00000080
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG7(v) \
+ (((v) << 7) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG7)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG6 0x00000040
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG6(v) \
+ (((v) << 6) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG6)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG5 0x00000020
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG5(v) \
+ (((v) << 5) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG5)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG4 0x00000010
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG4(v) \
+ (((v) << 4) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG4)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG3 0x00000008
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG3(v) \
+ (((v) << 3) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG3)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG2 0x00000004
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG2(v) \
+ (((v) << 2) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG2)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG1 0x00000002
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG1(v) \
+ (((v) << 1) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG1)
+#define BM_PXP_WFB_ARRAY_REG2_SW_FLAG0 0x00000001
+#define BF_PXP_WFB_ARRAY_REG2_SW_FLAG0(v) \
+ (((v) << 0) & BM_PXP_WFB_ARRAY_REG2_SW_FLAG0)
+
+#define HW_PXP_WFE_B_STORE_CTRL_CH0 (0x00001340)
+#define HW_PXP_WFE_B_STORE_CTRL_CH0_SET (0x00001344)
+#define HW_PXP_WFE_B_STORE_CTRL_CH0_CLR (0x00001348)
+#define HW_PXP_WFE_B_STORE_CTRL_CH0_TOG (0x0000134c)
+
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_ARBIT_EN 0x80000000
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_ARBIT_EN(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STORE_CTRL_CH0_ARBIT_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_ARBIT_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_ARBIT_EN__1 0x1
+#define BP_PXP_WFE_B_STORE_CTRL_CH0_RSVD0 25
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_RSVD0 0x7E000000
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_RSVD0(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STORE_CTRL_CH0_RSVD0)
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_COMBINE_2CHANNEL 0x01000000
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_COMBINE_2CHANNEL(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STORE_CTRL_CH0_COMBINE_2CHANNEL)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_COMBINE_2CHANNEL__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_COMBINE_2CHANNEL__1 0x1
+#define BP_PXP_WFE_B_STORE_CTRL_CH0_RSVD1 18
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_RSVD1 0x00FC0000
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_RSVD1(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STORE_CTRL_CH0_RSVD1)
+#define BP_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES 16
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES 0x00030000
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_WR_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_WFE_B_STORE_CTRL_CH0_RSVD2 12
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_RSVD2 0x0000F000
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_RSVD2(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STORE_CTRL_CH0_RSVD2)
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_FILL_DATA_EN 0x00000800
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_FILL_DATA_EN(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STORE_CTRL_CH0_FILL_DATA_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_FILL_DATA_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_FILL_DATA_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_PACK_IN_SEL 0x00000400
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_PACK_IN_SEL(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STORE_CTRL_CH0_PACK_IN_SEL)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_PACK_IN_SEL__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_PACK_IN_SEL__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_STORE_MEMORY_EN 0x00000200
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_STORE_MEMORY_EN(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STORE_CTRL_CH0_STORE_MEMORY_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_STORE_MEMORY_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_STORE_MEMORY_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_STORE_BYPASS_EN 0x00000100
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_STORE_BYPASS_EN(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_CTRL_CH0_STORE_BYPASS_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_STORE_BYPASS_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_STORE_BYPASS_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_RSVD3 0x00000080
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STORE_CTRL_CH0_RSVD3)
+#define BP_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM 5
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM 0x00000060
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM__1 0x1
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM__2 0x2
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_LINE_NUM__3 0x3
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_EN 0x00000010
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_EN(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_ARRAY_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_HANDSHAKE_EN 0x00000008
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STORE_CTRL_CH0_HANDSHAKE_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_HANDSHAKE_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_HANDSHAKE_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_16 0x00000004
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_16)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_16__8x8 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_16__16x16 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_EN 0x00000002
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_BLOCK_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH0_CH_EN 0x00000001
+#define BF_PXP_WFE_B_STORE_CTRL_CH0_CH_EN(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_CTRL_CH0_CH_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_CH_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH0_CH_EN__1 0x1
+
+#define HW_PXP_WFE_B_STORE_CTRL_CH1 (0x00001350)
+#define HW_PXP_WFE_B_STORE_CTRL_CH1_SET (0x00001354)
+#define HW_PXP_WFE_B_STORE_CTRL_CH1_CLR (0x00001358)
+#define HW_PXP_WFE_B_STORE_CTRL_CH1_TOG (0x0000135c)
+
+#define BP_PXP_WFE_B_STORE_CTRL_CH1_RSVD0 18
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_RSVD0 0xFFFC0000
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_RSVD0(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STORE_CTRL_CH1_RSVD0)
+#define BP_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES 16
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES 0x00030000
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_WR_NUM_BYTES__64_bytes 0x3
+#define BP_PXP_WFE_B_STORE_CTRL_CH1_RSVD1 11
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_RSVD1 0x0000F800
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_RSVD1(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STORE_CTRL_CH1_RSVD1)
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_PACK_IN_SEL 0x00000400
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_PACK_IN_SEL(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STORE_CTRL_CH1_PACK_IN_SEL)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_PACK_IN_SEL__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_PACK_IN_SEL__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_STORE_MEMORY_EN 0x00000200
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_STORE_MEMORY_EN(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STORE_CTRL_CH1_STORE_MEMORY_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_STORE_MEMORY_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_STORE_MEMORY_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_STORE_BYPASS_EN 0x00000100
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_STORE_BYPASS_EN(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_CTRL_CH1_STORE_BYPASS_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_STORE_BYPASS_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_STORE_BYPASS_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_RSVD3 0x00000080
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_RSVD3(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STORE_CTRL_CH1_RSVD3)
+#define BP_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM 5
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM 0x00000060
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM__1 0x1
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM__2 0x2
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_LINE_NUM__3 0x3
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_EN 0x00000010
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_EN(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_ARRAY_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_HANDSHAKE_EN 0x00000008
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_HANDSHAKE_EN(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STORE_CTRL_CH1_HANDSHAKE_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_HANDSHAKE_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_HANDSHAKE_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_16 0x00000004
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_16(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_16)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_16__8x8 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_16__16x16 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_EN 0x00000002
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_EN(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_BLOCK_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_CTRL_CH1_CH_EN 0x00000001
+#define BF_PXP_WFE_B_STORE_CTRL_CH1_CH_EN(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_CTRL_CH1_CH_EN)
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_CH_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_CTRL_CH1_CH_EN__1 0x1
+
+#define HW_PXP_WFE_B_STORE_STATUS_CH0 (0x00001360)
+
+#define BP_PXP_WFE_B_STORE_STATUS_CH0_STORE_BLOCK_Y 16
+#define BM_PXP_WFE_B_STORE_STATUS_CH0_STORE_BLOCK_Y 0xFFFF0000
+#define BF_PXP_WFE_B_STORE_STATUS_CH0_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_STATUS_CH0_STORE_BLOCK_Y)
+#define BP_PXP_WFE_B_STORE_STATUS_CH0_STORE_BLOCK_X 0
+#define BM_PXP_WFE_B_STORE_STATUS_CH0_STORE_BLOCK_X 0x0000FFFF
+#define BF_PXP_WFE_B_STORE_STATUS_CH0_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_STATUS_CH0_STORE_BLOCK_X)
+
+#define HW_PXP_WFE_B_STORE_STATUS_CH1 (0x00001370)
+
+#define BP_PXP_WFE_B_STORE_STATUS_CH1_STORE_BLOCK_Y 16
+#define BM_PXP_WFE_B_STORE_STATUS_CH1_STORE_BLOCK_Y 0xFFFF0000
+#define BF_PXP_WFE_B_STORE_STATUS_CH1_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_STATUS_CH1_STORE_BLOCK_Y)
+#define BP_PXP_WFE_B_STORE_STATUS_CH1_STORE_BLOCK_X 0
+#define BM_PXP_WFE_B_STORE_STATUS_CH1_STORE_BLOCK_X 0x0000FFFF
+#define BF_PXP_WFE_B_STORE_STATUS_CH1_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_STATUS_CH1_STORE_BLOCK_X)
+
+#define HW_PXP_WFE_B_STORE_SIZE_CH0 (0x00001380)
+
+#define BP_PXP_WFE_B_STORE_SIZE_CH0_OUT_HEIGHT 16
+#define BM_PXP_WFE_B_STORE_SIZE_CH0_OUT_HEIGHT 0xFFFF0000
+#define BF_PXP_WFE_B_STORE_SIZE_CH0_OUT_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_SIZE_CH0_OUT_HEIGHT)
+#define BP_PXP_WFE_B_STORE_SIZE_CH0_OUT_WIDTH 0
+#define BM_PXP_WFE_B_STORE_SIZE_CH0_OUT_WIDTH 0x0000FFFF
+#define BF_PXP_WFE_B_STORE_SIZE_CH0_OUT_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_SIZE_CH0_OUT_WIDTH)
+
+#define HW_PXP_WFE_B_STORE_SIZE_CH1 (0x00001390)
+
+#define BP_PXP_WFE_B_STORE_SIZE_CH1_OUT_HEIGHT 16
+#define BM_PXP_WFE_B_STORE_SIZE_CH1_OUT_HEIGHT 0xFFFF0000
+#define BF_PXP_WFE_B_STORE_SIZE_CH1_OUT_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_SIZE_CH1_OUT_HEIGHT)
+#define BP_PXP_WFE_B_STORE_SIZE_CH1_OUT_WIDTH 0
+#define BM_PXP_WFE_B_STORE_SIZE_CH1_OUT_WIDTH 0x0000FFFF
+#define BF_PXP_WFE_B_STORE_SIZE_CH1_OUT_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_SIZE_CH1_OUT_WIDTH)
+
+#define HW_PXP_WFE_B_STORE_PITCH (0x000013a0)
+
+#define BP_PXP_WFE_B_STORE_PITCH_CH1_OUT_PITCH 16
+#define BM_PXP_WFE_B_STORE_PITCH_CH1_OUT_PITCH 0xFFFF0000
+#define BF_PXP_WFE_B_STORE_PITCH_CH1_OUT_PITCH(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_PITCH_CH1_OUT_PITCH)
+#define BP_PXP_WFE_B_STORE_PITCH_CH0_OUT_PITCH 0
+#define BM_PXP_WFE_B_STORE_PITCH_CH0_OUT_PITCH 0x0000FFFF
+#define BF_PXP_WFE_B_STORE_PITCH_CH0_OUT_PITCH(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_PITCH_CH0_OUT_PITCH)
+
+#define HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH0 (0x000013b0)
+#define HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SET (0x000013b4)
+#define HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_CLR (0x000013b8)
+#define HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_TOG (0x000013bc)
+
+#define BP_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD0 8
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD0 0xFFFFFF00
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD0(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD0)
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS 0x00000080
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS)
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS__0 0x0
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS__1 0x1
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD1 0x00000040
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD1(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD1)
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN 0x00000020
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN)
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_2P_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN 0x00000010
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN)
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN__1 0x1
+#define BP_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP 2
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP 0x0000000C
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP)
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP__3 0x3
+#define BP_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD2 0
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD2 0x00000003
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD2(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH0_RSVD2)
+
+#define HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH1 (0x000013c0)
+#define HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_SET (0x000013c4)
+#define HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_CLR (0x000013c8)
+#define HW_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_TOG (0x000013cc)
+
+#define BP_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_RSVD0 6
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_RSVD0 0xFFFFFFC0
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_RSVD0(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_RSVD0)
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN 0x00000020
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN)
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_2P_EN__1 0x1
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN 0x00000010
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN)
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN__0 0x0
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUT_YUV422_1P_EN__1 0x1
+#define BP_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP 2
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP 0x0000000C
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP)
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__0 0x0
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__1 0x1
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__2 0x2
+#define BV_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP__3 0x3
+#define BP_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_RSVD2 0
+#define BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_RSVD2 0x00000003
+#define BF_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_RSVD2(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_SHIFT_CTRL_CH1_RSVD2)
+
+#define HW_PXP_WFE_B_STORE_ADDR_0_CH0 (0x00001410)
+
+#define BP_PXP_WFE_B_STORE_ADDR_0_CH0_OUT_BASE_ADDR0 0
+#define BM_PXP_WFE_B_STORE_ADDR_0_CH0_OUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_ADDR_1_CH0 (0x00001420)
+
+#define BP_PXP_WFE_B_STORE_ADDR_1_CH0_OUT_BASE_ADDR1 0
+#define BM_PXP_WFE_B_STORE_ADDR_1_CH0_OUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_ADDR_1_CH0_OUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_WFE_B_STORE_FILL_DATA_CH0 (0x00001430)
+
+#define BP_PXP_WFE_B_STORE_FILL_DATA_CH0_FILL_DATA_CH0 0
+#define BM_PXP_WFE_B_STORE_FILL_DATA_CH0_FILL_DATA_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_FILL_DATA_CH0_FILL_DATA_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_ADDR_0_CH1 (0x00001440)
+
+#define BP_PXP_WFE_B_STORE_ADDR_0_CH1_OUT_BASE_ADDR0 0
+#define BM_PXP_WFE_B_STORE_ADDR_0_CH1_OUT_BASE_ADDR0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_ADDR_1_CH1 (0x00001450)
+
+#define BP_PXP_WFE_B_STORE_ADDR_1_CH1_OUT_BASE_ADDR1 0
+#define BM_PXP_WFE_B_STORE_ADDR_1_CH1_OUT_BASE_ADDR1 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_ADDR_1_CH1_OUT_BASE_ADDR1(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK0_H_CH0 (0x00001460)
+
+#define BP_PXP_WFE_B_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK0_H_CH0_D_MASK0_H_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK0_L_CH0 (0x00001470)
+
+#define BP_PXP_WFE_B_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK1_H_CH0 (0x00001480)
+
+#define BP_PXP_WFE_B_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK1_H_CH0_D_MASK1_H_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK1_L_CH0 (0x00001490)
+
+#define BP_PXP_WFE_B_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK2_H_CH0 (0x000014a0)
+
+#define BP_PXP_WFE_B_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK2_H_CH0_D_MASK2_H_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK2_L_CH0 (0x000014b0)
+
+#define BP_PXP_WFE_B_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK2_L_CH0_D_MASK2_L_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK3_H_CH0 (0x000014c0)
+
+#define BP_PXP_WFE_B_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK3_H_CH0_D_MASK3_H_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK3_L_CH0 (0x000014d0)
+
+#define BP_PXP_WFE_B_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK4_H_CH0 (0x000014e0)
+
+#define BP_PXP_WFE_B_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK4_L_CH0 (0x000014f0)
+
+#define BP_PXP_WFE_B_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK4_L_CH0_D_MASK4_L_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK5_H_CH0 (0x00001500)
+
+#define BP_PXP_WFE_B_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK5_H_CH0_D_MASK5_H_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK5_L_CH0 (0x00001510)
+
+#define BP_PXP_WFE_B_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK5_L_CH0_D_MASK5_L_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK6_H_CH0 (0x00001520)
+
+#define BP_PXP_WFE_B_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK6_H_CH0_D_MASK6_H_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK6_L_CH0 (0x00001530)
+
+#define BP_PXP_WFE_B_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK6_L_CH0_D_MASK6_L_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK7_H_CH0 (0x00001540)
+
+#define BP_PXP_WFE_B_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK7_H_CH0_D_MASK7_H_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_MASK7_L_CH0 (0x00001550)
+
+#define BP_PXP_WFE_B_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0 0
+#define BM_PXP_WFE_B_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0 0xFFFFFFFF
+#define BF_PXP_WFE_B_STORE_D_MASK7_L_CH0_D_MASK7_L_CH0(v) (v)
+
+#define HW_PXP_WFE_B_STORE_D_SHIFT_L_CH0 (0x00001560)
+
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3 0x80000000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD0 0x40000000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD0)
+#define BP_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3 24
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3 0x3F000000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2 0x00800000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD1 0x00400000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD1)
+#define BP_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2 16
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2 0x003F0000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1 0x00008000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD2 0x00004000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD2)
+#define BP_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1 8
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1 0x00003F00
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0 0x00000080
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD3 0x00000040
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_RSVD3)
+#define BP_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0 0
+#define BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0 0x0000003F
+#define BF_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0)
+
+#define HW_PXP_WFE_B_STORE_D_SHIFT_H_CH0 (0x00001570)
+
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7 0x80000000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG7)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD0 0x40000000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD0)
+#define BP_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7 24
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7 0x3F000000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH7)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6 0x00800000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG6)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD1 0x00400000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD1)
+#define BP_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6 16
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6 0x003F0000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH6)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5 0x00008000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG5)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD2 0x00004000
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD2)
+#define BP_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5 8
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5 0x00003F00
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH5)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4 0x00000080
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_FLAG4)
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD3 0x00000040
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_RSVD3)
+#define BP_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4 0
+#define BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4 0x0000003F
+#define BF_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4)
+
+#define HW_PXP_WFE_B_STORE_F_SHIFT_L_CH0 (0x00001580)
+
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD0 0x80000000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD0(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD0)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3 0x40000000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3)
+#define BP_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3 24
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3 0x3F000000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD1 0x00800000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD1(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD1)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2 0x00400000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2)
+#define BP_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2 16
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2 0x003F0000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD2 0x00008000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD2(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD2)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1 0x00004000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1)
+#define BP_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1 8
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1 0x00003F00
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD3 0x00000080
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_RSVD3)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0 0x00000040
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0)
+#define BP_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0 0
+#define BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0 0x0000003F
+#define BF_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0)
+
+#define HW_PXP_WFE_B_STORE_F_SHIFT_H_CH0 (0x00001590)
+
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD0 0x80000000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD0(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD0)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7 0x40000000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG7)
+#define BP_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7 24
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7 0x3F000000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH7)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD1 0x00800000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD1(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD1)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6 0x00400000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG6)
+#define BP_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6 16
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6 0x003F0000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH6)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD2 0x00008000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD2(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD2)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5 0x00004000
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG5)
+#define BP_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5 8
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5 0x00003F00
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH5)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD3 0x00000080
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD3(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_RSVD3)
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4 0x00000040
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_FLAG4)
+#define BP_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4 0
+#define BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4 0x0000003F
+#define BF_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_F_SHIFT_H_CH0_F_SHIFT_WIDTH4)
+
+#define HW_PXP_WFE_B_STORE_F_MASK_L_CH0 (0x000015a0)
+
+#define BP_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK3 24
+#define BM_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK3 0xFF000000
+#define BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK3)
+#define BP_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK2 16
+#define BM_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK2 0x00FF0000
+#define BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK2)
+#define BP_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK1 8
+#define BM_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK1 0x0000FF00
+#define BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK1)
+#define BP_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK0 0
+#define BM_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK0 0x000000FF
+#define BF_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_F_MASK_L_CH0_F_MASK0)
+
+#define HW_PXP_WFE_B_STORE_F_MASK_H_CH0 (0x000015b0)
+
+#define BP_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK7 24
+#define BM_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK7 0xFF000000
+#define BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK7)
+#define BP_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK6 16
+#define BM_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK6 0x00FF0000
+#define BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK6)
+#define BP_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK5 8
+#define BM_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK5 0x0000FF00
+#define BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK5)
+#define BP_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK4 0
+#define BM_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK4 0x000000FF
+#define BF_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STORE_F_MASK_H_CH0_F_MASK4)
+
+#define HW_PXP_FETCH_WFE_A_DEBUG (0x000015c0)
+
+#define BP_PXP_FETCH_WFE_A_DEBUG_RSVD 29
+#define BM_PXP_FETCH_WFE_A_DEBUG_RSVD 0xE0000000
+#define BF_PXP_FETCH_WFE_A_DEBUG_RSVD(v) \
+ (((v) << 29) & BM_PXP_FETCH_WFE_A_DEBUG_RSVD)
+#define BM_PXP_FETCH_WFE_A_DEBUG_BUF_SEL 0x10000000
+#define BF_PXP_FETCH_WFE_A_DEBUG_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_FETCH_WFE_A_DEBUG_BUF_SEL)
+#define BV_PXP_FETCH_WFE_A_DEBUG_BUF_SEL__BF0 0x0
+#define BV_PXP_FETCH_WFE_A_DEBUG_BUF_SEL__BF1 0x1
+#define BP_PXP_FETCH_WFE_A_DEBUG_ITEM_SEL 24
+#define BM_PXP_FETCH_WFE_A_DEBUG_ITEM_SEL 0x0F000000
+#define BF_PXP_FETCH_WFE_A_DEBUG_ITEM_SEL(v) \
+ (((v) << 24) & BM_PXP_FETCH_WFE_A_DEBUG_ITEM_SEL)
+#define BP_PXP_FETCH_WFE_A_DEBUG_DEBUG_VALUE 0
+#define BM_PXP_FETCH_WFE_A_DEBUG_DEBUG_VALUE 0x00FFFFFF
+#define BF_PXP_FETCH_WFE_A_DEBUG_DEBUG_VALUE(v) \
+ (((v) << 0) & BM_PXP_FETCH_WFE_A_DEBUG_DEBUG_VALUE)
+
+#define HW_PXP_FETCH_WFE_B_DEBUG (0x000015d0)
+
+#define BP_PXP_FETCH_WFE_B_DEBUG_RSVD 29
+#define BM_PXP_FETCH_WFE_B_DEBUG_RSVD 0xE0000000
+#define BF_PXP_FETCH_WFE_B_DEBUG_RSVD(v) \
+ (((v) << 29) & BM_PXP_FETCH_WFE_B_DEBUG_RSVD)
+#define BM_PXP_FETCH_WFE_B_DEBUG_BUF_SEL 0x10000000
+#define BF_PXP_FETCH_WFE_B_DEBUG_BUF_SEL(v) \
+ (((v) << 28) & BM_PXP_FETCH_WFE_B_DEBUG_BUF_SEL)
+#define BV_PXP_FETCH_WFE_B_DEBUG_BUF_SEL__BF0 0x0
+#define BV_PXP_FETCH_WFE_B_DEBUG_BUF_SEL__BF1 0x1
+#define BP_PXP_FETCH_WFE_B_DEBUG_ITEM_SEL 24
+#define BM_PXP_FETCH_WFE_B_DEBUG_ITEM_SEL 0x0F000000
+#define BF_PXP_FETCH_WFE_B_DEBUG_ITEM_SEL(v) \
+ (((v) << 24) & BM_PXP_FETCH_WFE_B_DEBUG_ITEM_SEL)
+#define BP_PXP_FETCH_WFE_B_DEBUG_DEBUG_VALUE 0
+#define BM_PXP_FETCH_WFE_B_DEBUG_DEBUG_VALUE 0x00FFFFFF
+#define BF_PXP_FETCH_WFE_B_DEBUG_DEBUG_VALUE(v) \
+ (((v) << 0) & BM_PXP_FETCH_WFE_B_DEBUG_DEBUG_VALUE)
+
+#define HW_PXP_DITHER_CTRL (0x00001670)
+#define HW_PXP_DITHER_CTRL_SET (0x00001674)
+#define HW_PXP_DITHER_CTRL_CLR (0x00001678)
+#define HW_PXP_DITHER_CTRL_TOG (0x0000167c)
+
+#define BM_PXP_DITHER_CTRL_BUSY0 0x80000000
+#define BF_PXP_DITHER_CTRL_BUSY0(v) \
+ (((v) << 31) & BM_PXP_DITHER_CTRL_BUSY0)
+#define BM_PXP_DITHER_CTRL_BUSY1 0x40000000
+#define BF_PXP_DITHER_CTRL_BUSY1(v) \
+ (((v) << 30) & BM_PXP_DITHER_CTRL_BUSY1)
+#define BM_PXP_DITHER_CTRL_BUSY2 0x20000000
+#define BF_PXP_DITHER_CTRL_BUSY2(v) \
+ (((v) << 29) & BM_PXP_DITHER_CTRL_BUSY2)
+#define BP_PXP_DITHER_CTRL_RSVD0 25
+#define BM_PXP_DITHER_CTRL_RSVD0 0x1E000000
+#define BF_PXP_DITHER_CTRL_RSVD0(v) \
+ (((v) << 25) & BM_PXP_DITHER_CTRL_RSVD0)
+#define BM_PXP_DITHER_CTRL_ORDERED_ROUND_MODE 0x01000000
+#define BF_PXP_DITHER_CTRL_ORDERED_ROUND_MODE(v) \
+ (((v) << 24) & BM_PXP_DITHER_CTRL_ORDERED_ROUND_MODE)
+#define BV_PXP_DITHER_CTRL_ORDERED_ROUND_MODE__0 0x0
+#define BV_PXP_DITHER_CTRL_ORDERED_ROUND_MODE__1 0x1
+#define BM_PXP_DITHER_CTRL_FINAL_LUT_ENABLE 0x00800000
+#define BF_PXP_DITHER_CTRL_FINAL_LUT_ENABLE(v) \
+ (((v) << 23) & BM_PXP_DITHER_CTRL_FINAL_LUT_ENABLE)
+#define BV_PXP_DITHER_CTRL_FINAL_LUT_ENABLE__Disabled 0x0
+#define BV_PXP_DITHER_CTRL_FINAL_LUT_ENABLE__Enabled 0x1
+#define BP_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE 21
+#define BM_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE 0x00600000
+#define BF_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE(v) \
+ (((v) << 21) & BM_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE)
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE__0 0x0
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE__1 0x1
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE__2 0x2
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX2_SIZE__3 0x3
+#define BP_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE 19
+#define BM_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE 0x00180000
+#define BF_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE(v) \
+ (((v) << 19) & BM_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE)
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE__0 0x0
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE__1 0x1
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE__2 0x2
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX1_SIZE__3 0x3
+#define BP_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE 17
+#define BM_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE 0x00060000
+#define BF_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE(v) \
+ (((v) << 17) & BM_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE)
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE__0 0x0
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE__1 0x1
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE__2 0x2
+#define BV_PXP_DITHER_CTRL_IDX_MATRIX0_SIZE__3 0x3
+#define BP_PXP_DITHER_CTRL_LUT_MODE 15
+#define BM_PXP_DITHER_CTRL_LUT_MODE 0x00018000
+#define BF_PXP_DITHER_CTRL_LUT_MODE(v) \
+ (((v) << 15) & BM_PXP_DITHER_CTRL_LUT_MODE)
+#define BV_PXP_DITHER_CTRL_LUT_MODE__0 0x0
+#define BV_PXP_DITHER_CTRL_LUT_MODE__1 0x1
+#define BV_PXP_DITHER_CTRL_LUT_MODE__2 0x2
+#define BV_PXP_DITHER_CTRL_LUT_MODE__3 0x3
+#define BP_PXP_DITHER_CTRL_NUM_QUANT_BIT 12
+#define BM_PXP_DITHER_CTRL_NUM_QUANT_BIT 0x00007000
+#define BF_PXP_DITHER_CTRL_NUM_QUANT_BIT(v) \
+ (((v) << 12) & BM_PXP_DITHER_CTRL_NUM_QUANT_BIT)
+#define BV_PXP_DITHER_CTRL_NUM_QUANT_BIT__0 0x0
+#define BV_PXP_DITHER_CTRL_NUM_QUANT_BIT__1 0x1
+#define BV_PXP_DITHER_CTRL_NUM_QUANT_BIT__2 0x2
+#define BV_PXP_DITHER_CTRL_NUM_QUANT_BIT__3 0x3
+#define BV_PXP_DITHER_CTRL_NUM_QUANT_BIT__4 0x4
+#define BV_PXP_DITHER_CTRL_NUM_QUANT_BIT__5 0x5
+#define BV_PXP_DITHER_CTRL_NUM_QUANT_BIT__6 0x6
+#define BV_PXP_DITHER_CTRL_NUM_QUANT_BIT__7 0x7
+#define BP_PXP_DITHER_CTRL_DITHER_MODE2 9
+#define BM_PXP_DITHER_CTRL_DITHER_MODE2 0x00000E00
+#define BF_PXP_DITHER_CTRL_DITHER_MODE2(v) \
+ (((v) << 9) & BM_PXP_DITHER_CTRL_DITHER_MODE2)
+#define BV_PXP_DITHER_CTRL_DITHER_MODE2__0 0x0
+#define BV_PXP_DITHER_CTRL_DITHER_MODE2__1 0x1
+#define BV_PXP_DITHER_CTRL_DITHER_MODE2__2 0x2
+#define BV_PXP_DITHER_CTRL_DITHER_MODE2__3 0x3
+#define BV_PXP_DITHER_CTRL_DITHER_MODE2__4 0x4
+#define BV_PXP_DITHER_CTRL_DITHER_MODE2__5 0x5
+#define BV_PXP_DITHER_CTRL_DITHER_MODE2__6 0x6
+#define BV_PXP_DITHER_CTRL_DITHER_MODE2__7 0x7
+#define BP_PXP_DITHER_CTRL_DITHER_MODE1 6
+#define BM_PXP_DITHER_CTRL_DITHER_MODE1 0x000001C0
+#define BF_PXP_DITHER_CTRL_DITHER_MODE1(v) \
+ (((v) << 6) & BM_PXP_DITHER_CTRL_DITHER_MODE1)
+#define BV_PXP_DITHER_CTRL_DITHER_MODE1__0 0x0
+#define BV_PXP_DITHER_CTRL_DITHER_MODE1__1 0x1
+#define BV_PXP_DITHER_CTRL_DITHER_MODE1__2 0x2
+#define BV_PXP_DITHER_CTRL_DITHER_MODE1__3 0x3
+#define BV_PXP_DITHER_CTRL_DITHER_MODE1__4 0x4
+#define BV_PXP_DITHER_CTRL_DITHER_MODE1__5 0x5
+#define BV_PXP_DITHER_CTRL_DITHER_MODE1__6 0x6
+#define BV_PXP_DITHER_CTRL_DITHER_MODE1__7 0x7
+#define BP_PXP_DITHER_CTRL_DITHER_MODE0 3
+#define BM_PXP_DITHER_CTRL_DITHER_MODE0 0x00000038
+#define BF_PXP_DITHER_CTRL_DITHER_MODE0(v) \
+ (((v) << 3) & BM_PXP_DITHER_CTRL_DITHER_MODE0)
+#define BV_PXP_DITHER_CTRL_DITHER_MODE0__0 0x0
+#define BV_PXP_DITHER_CTRL_DITHER_MODE0__1 0x1
+#define BV_PXP_DITHER_CTRL_DITHER_MODE0__2 0x2
+#define BV_PXP_DITHER_CTRL_DITHER_MODE0__3 0x3
+#define BV_PXP_DITHER_CTRL_DITHER_MODE0__4 0x4
+#define BV_PXP_DITHER_CTRL_DITHER_MODE0__5 0x5
+#define BV_PXP_DITHER_CTRL_DITHER_MODE0__6 0x6
+#define BV_PXP_DITHER_CTRL_DITHER_MODE0__7 0x7
+#define BM_PXP_DITHER_CTRL_ENABLE2 0x00000004
+#define BF_PXP_DITHER_CTRL_ENABLE2(v) \
+ (((v) << 2) & BM_PXP_DITHER_CTRL_ENABLE2)
+#define BV_PXP_DITHER_CTRL_ENABLE2__Disabled 0x0
+#define BV_PXP_DITHER_CTRL_ENABLE2__Enabled 0x1
+#define BM_PXP_DITHER_CTRL_ENABLE1 0x00000002
+#define BF_PXP_DITHER_CTRL_ENABLE1(v) \
+ (((v) << 1) & BM_PXP_DITHER_CTRL_ENABLE1)
+#define BV_PXP_DITHER_CTRL_ENABLE1__Disabled 0x0
+#define BV_PXP_DITHER_CTRL_ENABLE1__Enabled 0x1
+#define BM_PXP_DITHER_CTRL_ENABLE0 0x00000001
+#define BF_PXP_DITHER_CTRL_ENABLE0(v) \
+ (((v) << 0) & BM_PXP_DITHER_CTRL_ENABLE0)
+#define BV_PXP_DITHER_CTRL_ENABLE0__Disabled 0x0
+#define BV_PXP_DITHER_CTRL_ENABLE0__Enabled 0x1
+
+#define HW_PXP_DITHER_FINAL_LUT_DATA0 (0x00001680)
+#define HW_PXP_DITHER_FINAL_LUT_DATA0_SET (0x00001684)
+#define HW_PXP_DITHER_FINAL_LUT_DATA0_CLR (0x00001688)
+#define HW_PXP_DITHER_FINAL_LUT_DATA0_TOG (0x0000168c)
+
+#define BP_PXP_DITHER_FINAL_LUT_DATA0_DATA3 24
+#define BM_PXP_DITHER_FINAL_LUT_DATA0_DATA3 0xFF000000
+#define BF_PXP_DITHER_FINAL_LUT_DATA0_DATA3(v) \
+ (((v) << 24) & BM_PXP_DITHER_FINAL_LUT_DATA0_DATA3)
+#define BP_PXP_DITHER_FINAL_LUT_DATA0_DATA2 16
+#define BM_PXP_DITHER_FINAL_LUT_DATA0_DATA2 0x00FF0000
+#define BF_PXP_DITHER_FINAL_LUT_DATA0_DATA2(v) \
+ (((v) << 16) & BM_PXP_DITHER_FINAL_LUT_DATA0_DATA2)
+#define BP_PXP_DITHER_FINAL_LUT_DATA0_DATA1 8
+#define BM_PXP_DITHER_FINAL_LUT_DATA0_DATA1 0x0000FF00
+#define BF_PXP_DITHER_FINAL_LUT_DATA0_DATA1(v) \
+ (((v) << 8) & BM_PXP_DITHER_FINAL_LUT_DATA0_DATA1)
+#define BP_PXP_DITHER_FINAL_LUT_DATA0_DATA0 0
+#define BM_PXP_DITHER_FINAL_LUT_DATA0_DATA0 0x000000FF
+#define BF_PXP_DITHER_FINAL_LUT_DATA0_DATA0(v) \
+ (((v) << 0) & BM_PXP_DITHER_FINAL_LUT_DATA0_DATA0)
+
+#define HW_PXP_DITHER_FINAL_LUT_DATA1 (0x00001690)
+#define HW_PXP_DITHER_FINAL_LUT_DATA1_SET (0x00001694)
+#define HW_PXP_DITHER_FINAL_LUT_DATA1_CLR (0x00001698)
+#define HW_PXP_DITHER_FINAL_LUT_DATA1_TOG (0x0000169c)
+
+#define BP_PXP_DITHER_FINAL_LUT_DATA1_DATA7 24
+#define BM_PXP_DITHER_FINAL_LUT_DATA1_DATA7 0xFF000000
+#define BF_PXP_DITHER_FINAL_LUT_DATA1_DATA7(v) \
+ (((v) << 24) & BM_PXP_DITHER_FINAL_LUT_DATA1_DATA7)
+#define BP_PXP_DITHER_FINAL_LUT_DATA1_DATA6 16
+#define BM_PXP_DITHER_FINAL_LUT_DATA1_DATA6 0x00FF0000
+#define BF_PXP_DITHER_FINAL_LUT_DATA1_DATA6(v) \
+ (((v) << 16) & BM_PXP_DITHER_FINAL_LUT_DATA1_DATA6)
+#define BP_PXP_DITHER_FINAL_LUT_DATA1_DATA5 8
+#define BM_PXP_DITHER_FINAL_LUT_DATA1_DATA5 0x0000FF00
+#define BF_PXP_DITHER_FINAL_LUT_DATA1_DATA5(v) \
+ (((v) << 8) & BM_PXP_DITHER_FINAL_LUT_DATA1_DATA5)
+#define BP_PXP_DITHER_FINAL_LUT_DATA1_DATA4 0
+#define BM_PXP_DITHER_FINAL_LUT_DATA1_DATA4 0x000000FF
+#define BF_PXP_DITHER_FINAL_LUT_DATA1_DATA4(v) \
+ (((v) << 0) & BM_PXP_DITHER_FINAL_LUT_DATA1_DATA4)
+
+#define HW_PXP_DITHER_FINAL_LUT_DATA2 (0x000016a0)
+#define HW_PXP_DITHER_FINAL_LUT_DATA2_SET (0x000016a4)
+#define HW_PXP_DITHER_FINAL_LUT_DATA2_CLR (0x000016a8)
+#define HW_PXP_DITHER_FINAL_LUT_DATA2_TOG (0x000016ac)
+
+#define BP_PXP_DITHER_FINAL_LUT_DATA2_DATA11 24
+#define BM_PXP_DITHER_FINAL_LUT_DATA2_DATA11 0xFF000000
+#define BF_PXP_DITHER_FINAL_LUT_DATA2_DATA11(v) \
+ (((v) << 24) & BM_PXP_DITHER_FINAL_LUT_DATA2_DATA11)
+#define BP_PXP_DITHER_FINAL_LUT_DATA2_DATA10 16
+#define BM_PXP_DITHER_FINAL_LUT_DATA2_DATA10 0x00FF0000
+#define BF_PXP_DITHER_FINAL_LUT_DATA2_DATA10(v) \
+ (((v) << 16) & BM_PXP_DITHER_FINAL_LUT_DATA2_DATA10)
+#define BP_PXP_DITHER_FINAL_LUT_DATA2_DATA9 8
+#define BM_PXP_DITHER_FINAL_LUT_DATA2_DATA9 0x0000FF00
+#define BF_PXP_DITHER_FINAL_LUT_DATA2_DATA9(v) \
+ (((v) << 8) & BM_PXP_DITHER_FINAL_LUT_DATA2_DATA9)
+#define BP_PXP_DITHER_FINAL_LUT_DATA2_DATA8 0
+#define BM_PXP_DITHER_FINAL_LUT_DATA2_DATA8 0x000000FF
+#define BF_PXP_DITHER_FINAL_LUT_DATA2_DATA8(v) \
+ (((v) << 0) & BM_PXP_DITHER_FINAL_LUT_DATA2_DATA8)
+
+#define HW_PXP_DITHER_FINAL_LUT_DATA3 (0x000016b0)
+#define HW_PXP_DITHER_FINAL_LUT_DATA3_SET (0x000016b4)
+#define HW_PXP_DITHER_FINAL_LUT_DATA3_CLR (0x000016b8)
+#define HW_PXP_DITHER_FINAL_LUT_DATA3_TOG (0x000016bc)
+
+#define BP_PXP_DITHER_FINAL_LUT_DATA3_DATA15 24
+#define BM_PXP_DITHER_FINAL_LUT_DATA3_DATA15 0xFF000000
+#define BF_PXP_DITHER_FINAL_LUT_DATA3_DATA15(v) \
+ (((v) << 24) & BM_PXP_DITHER_FINAL_LUT_DATA3_DATA15)
+#define BP_PXP_DITHER_FINAL_LUT_DATA3_DATA14 16
+#define BM_PXP_DITHER_FINAL_LUT_DATA3_DATA14 0x00FF0000
+#define BF_PXP_DITHER_FINAL_LUT_DATA3_DATA14(v) \
+ (((v) << 16) & BM_PXP_DITHER_FINAL_LUT_DATA3_DATA14)
+#define BP_PXP_DITHER_FINAL_LUT_DATA3_DATA13 8
+#define BM_PXP_DITHER_FINAL_LUT_DATA3_DATA13 0x0000FF00
+#define BF_PXP_DITHER_FINAL_LUT_DATA3_DATA13(v) \
+ (((v) << 8) & BM_PXP_DITHER_FINAL_LUT_DATA3_DATA13)
+#define BP_PXP_DITHER_FINAL_LUT_DATA3_DATA12 0
+#define BM_PXP_DITHER_FINAL_LUT_DATA3_DATA12 0x000000FF
+#define BF_PXP_DITHER_FINAL_LUT_DATA3_DATA12(v) \
+ (((v) << 0) & BM_PXP_DITHER_FINAL_LUT_DATA3_DATA12)
+
+#define HW_PXP_WFE_A_CTRL (0x000016c0)
+#define HW_PXP_WFE_A_CTRL_SET (0x000016c4)
+#define HW_PXP_WFE_A_CTRL_CLR (0x000016c8)
+#define HW_PXP_WFE_A_CTRL_TOG (0x000016cc)
+
+#define BM_PXP_WFE_A_CTRL_DONE 0x80000000
+#define BF_PXP_WFE_A_CTRL_DONE(v) \
+ (((v) << 31) & BM_PXP_WFE_A_CTRL_DONE)
+#define BP_PXP_WFE_A_CTRL_RSVD0 3
+#define BM_PXP_WFE_A_CTRL_RSVD0 0x7FFFFFF8
+#define BF_PXP_WFE_A_CTRL_RSVD0(v) \
+ (((v) << 3) & BM_PXP_WFE_A_CTRL_RSVD0)
+#define BM_PXP_WFE_A_CTRL_SW_RESET 0x00000004
+#define BF_PXP_WFE_A_CTRL_SW_RESET(v) \
+ (((v) << 2) & BM_PXP_WFE_A_CTRL_SW_RESET)
+#define BM_PXP_WFE_A_CTRL_RSVD1 0x00000002
+#define BF_PXP_WFE_A_CTRL_RSVD1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_CTRL_RSVD1)
+#define BM_PXP_WFE_A_CTRL_ENABLE 0x00000001
+#define BF_PXP_WFE_A_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PXP_WFE_A_CTRL_ENABLE)
+#define BV_PXP_WFE_A_CTRL_ENABLE__0 0x0
+#define BV_PXP_WFE_A_CTRL_ENABLE__1 0x1
+
+#define HW_PXP_WFE_A_DIMENSIONS (0x000016d0)
+
+#define BP_PXP_WFE_A_DIMENSIONS_RSVD0 28
+#define BM_PXP_WFE_A_DIMENSIONS_RSVD0 0xF0000000
+#define BF_PXP_WFE_A_DIMENSIONS_RSVD0(v) \
+ (((v) << 28) & BM_PXP_WFE_A_DIMENSIONS_RSVD0)
+#define BP_PXP_WFE_A_DIMENSIONS_HEIGHT 16
+#define BM_PXP_WFE_A_DIMENSIONS_HEIGHT 0x0FFF0000
+#define BF_PXP_WFE_A_DIMENSIONS_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFE_A_DIMENSIONS_HEIGHT)
+#define BP_PXP_WFE_A_DIMENSIONS_RSVD1 12
+#define BM_PXP_WFE_A_DIMENSIONS_RSVD1 0x0000F000
+#define BF_PXP_WFE_A_DIMENSIONS_RSVD1(v) \
+ (((v) << 12) & BM_PXP_WFE_A_DIMENSIONS_RSVD1)
+#define BP_PXP_WFE_A_DIMENSIONS_WIDTH 0
+#define BM_PXP_WFE_A_DIMENSIONS_WIDTH 0x00000FFF
+#define BF_PXP_WFE_A_DIMENSIONS_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFE_A_DIMENSIONS_WIDTH)
+
+#define HW_PXP_WFE_A_OFFSET (0x000016e0)
+
+#define BP_PXP_WFE_A_OFFSET_RSVD0 28
+#define BM_PXP_WFE_A_OFFSET_RSVD0 0xF0000000
+#define BF_PXP_WFE_A_OFFSET_RSVD0(v) \
+ (((v) << 28) & BM_PXP_WFE_A_OFFSET_RSVD0)
+#define BP_PXP_WFE_A_OFFSET_Y_OFFSET 16
+#define BM_PXP_WFE_A_OFFSET_Y_OFFSET 0x0FFF0000
+#define BF_PXP_WFE_A_OFFSET_Y_OFFSET(v) \
+ (((v) << 16) & BM_PXP_WFE_A_OFFSET_Y_OFFSET)
+#define BP_PXP_WFE_A_OFFSET_RSVD1 12
+#define BM_PXP_WFE_A_OFFSET_RSVD1 0x0000F000
+#define BF_PXP_WFE_A_OFFSET_RSVD1(v) \
+ (((v) << 12) & BM_PXP_WFE_A_OFFSET_RSVD1)
+#define BP_PXP_WFE_A_OFFSET_X_OFFSET 0
+#define BM_PXP_WFE_A_OFFSET_X_OFFSET 0x00000FFF
+#define BF_PXP_WFE_A_OFFSET_X_OFFSET(v) \
+ (((v) << 0) & BM_PXP_WFE_A_OFFSET_X_OFFSET)
+
+#define HW_PXP_WFE_A_SW_DATA_REGS (0x000016f0)
+
+#define BP_PXP_WFE_A_SW_DATA_REGS_VAL3 24
+#define BM_PXP_WFE_A_SW_DATA_REGS_VAL3 0xFF000000
+#define BF_PXP_WFE_A_SW_DATA_REGS_VAL3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_SW_DATA_REGS_VAL3)
+#define BP_PXP_WFE_A_SW_DATA_REGS_VAL2 16
+#define BM_PXP_WFE_A_SW_DATA_REGS_VAL2 0x00FF0000
+#define BF_PXP_WFE_A_SW_DATA_REGS_VAL2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_SW_DATA_REGS_VAL2)
+#define BP_PXP_WFE_A_SW_DATA_REGS_VAL1 8
+#define BM_PXP_WFE_A_SW_DATA_REGS_VAL1 0x0000FF00
+#define BF_PXP_WFE_A_SW_DATA_REGS_VAL1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_SW_DATA_REGS_VAL1)
+#define BP_PXP_WFE_A_SW_DATA_REGS_VAL0 0
+#define BM_PXP_WFE_A_SW_DATA_REGS_VAL0 0x000000FF
+#define BF_PXP_WFE_A_SW_DATA_REGS_VAL0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_SW_DATA_REGS_VAL0)
+
+#define HW_PXP_WFE_A_SW_FLAG_REGS (0x00001700)
+
+#define BP_PXP_WFE_A_SW_FLAG_REGS_RSVD 4
+#define BM_PXP_WFE_A_SW_FLAG_REGS_RSVD 0xFFFFFFF0
+#define BF_PXP_WFE_A_SW_FLAG_REGS_RSVD(v) \
+ (((v) << 4) & BM_PXP_WFE_A_SW_FLAG_REGS_RSVD)
+#define BM_PXP_WFE_A_SW_FLAG_REGS_VAL3 0x00000008
+#define BF_PXP_WFE_A_SW_FLAG_REGS_VAL3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_SW_FLAG_REGS_VAL3)
+#define BM_PXP_WFE_A_SW_FLAG_REGS_VAL2 0x00000004
+#define BF_PXP_WFE_A_SW_FLAG_REGS_VAL2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_SW_FLAG_REGS_VAL2)
+#define BM_PXP_WFE_A_SW_FLAG_REGS_VAL1 0x00000002
+#define BF_PXP_WFE_A_SW_FLAG_REGS_VAL1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_SW_FLAG_REGS_VAL1)
+#define BM_PXP_WFE_A_SW_FLAG_REGS_VAL0 0x00000001
+#define BF_PXP_WFE_A_SW_FLAG_REGS_VAL0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_SW_FLAG_REGS_VAL0)
+
+#define HW_PXP_WFE_A_STAGE1_MUX0 (0x00001710)
+#define HW_PXP_WFE_A_STAGE1_MUX0_SET (0x00001714)
+#define HW_PXP_WFE_A_STAGE1_MUX0_CLR (0x00001718)
+#define HW_PXP_WFE_A_STAGE1_MUX0_TOG (0x0000171c)
+
+#define BP_PXP_WFE_A_STAGE1_MUX0_RSVD0 30
+#define BM_PXP_WFE_A_STAGE1_MUX0_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE1_MUX0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE1_MUX0_RSVD0)
+#define BP_PXP_WFE_A_STAGE1_MUX0_MUX3 24
+#define BM_PXP_WFE_A_STAGE1_MUX0_MUX3 0x3F000000
+#define BF_PXP_WFE_A_STAGE1_MUX0_MUX3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE1_MUX0_MUX3)
+#define BP_PXP_WFE_A_STAGE1_MUX0_RSVD1 22
+#define BM_PXP_WFE_A_STAGE1_MUX0_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE1_MUX0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE1_MUX0_RSVD1)
+#define BP_PXP_WFE_A_STAGE1_MUX0_MUX2 16
+#define BM_PXP_WFE_A_STAGE1_MUX0_MUX2 0x003F0000
+#define BF_PXP_WFE_A_STAGE1_MUX0_MUX2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE1_MUX0_MUX2)
+#define BP_PXP_WFE_A_STAGE1_MUX0_RSVD2 14
+#define BM_PXP_WFE_A_STAGE1_MUX0_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE1_MUX0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE1_MUX0_RSVD2)
+#define BP_PXP_WFE_A_STAGE1_MUX0_MUX1 8
+#define BM_PXP_WFE_A_STAGE1_MUX0_MUX1 0x00003F00
+#define BF_PXP_WFE_A_STAGE1_MUX0_MUX1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE1_MUX0_MUX1)
+#define BP_PXP_WFE_A_STAGE1_MUX0_RSVD3 6
+#define BM_PXP_WFE_A_STAGE1_MUX0_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE1_MUX0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE1_MUX0_RSVD3)
+#define BP_PXP_WFE_A_STAGE1_MUX0_MUX0 0
+#define BM_PXP_WFE_A_STAGE1_MUX0_MUX0 0x0000003F
+#define BF_PXP_WFE_A_STAGE1_MUX0_MUX0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE1_MUX0_MUX0)
+
+#define HW_PXP_WFE_A_STAGE1_MUX1 (0x00001720)
+#define HW_PXP_WFE_A_STAGE1_MUX1_SET (0x00001724)
+#define HW_PXP_WFE_A_STAGE1_MUX1_CLR (0x00001728)
+#define HW_PXP_WFE_A_STAGE1_MUX1_TOG (0x0000172c)
+
+#define BP_PXP_WFE_A_STAGE1_MUX1_RSVD0 30
+#define BM_PXP_WFE_A_STAGE1_MUX1_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE1_MUX1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE1_MUX1_RSVD0)
+#define BP_PXP_WFE_A_STAGE1_MUX1_MUX7 24
+#define BM_PXP_WFE_A_STAGE1_MUX1_MUX7 0x3F000000
+#define BF_PXP_WFE_A_STAGE1_MUX1_MUX7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE1_MUX1_MUX7)
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__INC 0x0
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__DEC 0x1
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__ADD 0x2
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__MINUS 0x3
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__AND 0x4
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__OR 0x5
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__XOR 0x6
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__SHIFTLEFT 0x7
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__SHIFTRIGHT 0x8
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__BIT_AND 0x9
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__BIT_OR 0xa
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__BIT_CMP 0xb
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX7__NOP 0xc
+#define BP_PXP_WFE_A_STAGE1_MUX1_RSVD1 22
+#define BM_PXP_WFE_A_STAGE1_MUX1_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE1_MUX1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE1_MUX1_RSVD1)
+#define BP_PXP_WFE_A_STAGE1_MUX1_MUX6 16
+#define BM_PXP_WFE_A_STAGE1_MUX1_MUX6 0x003F0000
+#define BF_PXP_WFE_A_STAGE1_MUX1_MUX6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE1_MUX1_MUX6)
+#define BP_PXP_WFE_A_STAGE1_MUX1_RSVD2 14
+#define BM_PXP_WFE_A_STAGE1_MUX1_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE1_MUX1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE1_MUX1_RSVD2)
+#define BP_PXP_WFE_A_STAGE1_MUX1_MUX5 8
+#define BM_PXP_WFE_A_STAGE1_MUX1_MUX5 0x00003F00
+#define BF_PXP_WFE_A_STAGE1_MUX1_MUX5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE1_MUX1_MUX5)
+#define BP_PXP_WFE_A_STAGE1_MUX1_RSVD3 6
+#define BM_PXP_WFE_A_STAGE1_MUX1_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE1_MUX1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE1_MUX1_RSVD3)
+#define BP_PXP_WFE_A_STAGE1_MUX1_MUX4 0
+#define BM_PXP_WFE_A_STAGE1_MUX1_MUX4 0x0000003F
+#define BF_PXP_WFE_A_STAGE1_MUX1_MUX4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE1_MUX1_MUX4)
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__INC 0x0
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__DEC 0x1
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__ADD 0x2
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__MINUS 0x3
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__AND 0x4
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__OR 0x5
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__XOR 0x6
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__SHIFTLEFT 0x7
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__SHIFTRIGHT 0x8
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__BIT_AND 0x9
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__BIT_OR 0xa
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__BIT_CMP 0xb
+#define BV_PXP_WFE_A_STAGE1_MUX1_MUX4__NOP 0xc
+
+#define HW_PXP_WFE_A_STAGE1_MUX2 (0x00001730)
+#define HW_PXP_WFE_A_STAGE1_MUX2_SET (0x00001734)
+#define HW_PXP_WFE_A_STAGE1_MUX2_CLR (0x00001738)
+#define HW_PXP_WFE_A_STAGE1_MUX2_TOG (0x0000173c)
+
+#define BP_PXP_WFE_A_STAGE1_MUX2_RSVD0 30
+#define BM_PXP_WFE_A_STAGE1_MUX2_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE1_MUX2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE1_MUX2_RSVD0)
+#define BP_PXP_WFE_A_STAGE1_MUX2_MUX11 24
+#define BM_PXP_WFE_A_STAGE1_MUX2_MUX11 0x3F000000
+#define BF_PXP_WFE_A_STAGE1_MUX2_MUX11(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE1_MUX2_MUX11)
+#define BP_PXP_WFE_A_STAGE1_MUX2_RSVD1 22
+#define BM_PXP_WFE_A_STAGE1_MUX2_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE1_MUX2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE1_MUX2_RSVD1)
+#define BP_PXP_WFE_A_STAGE1_MUX2_MUX10 16
+#define BM_PXP_WFE_A_STAGE1_MUX2_MUX10 0x003F0000
+#define BF_PXP_WFE_A_STAGE1_MUX2_MUX10(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE1_MUX2_MUX10)
+#define BP_PXP_WFE_A_STAGE1_MUX2_RSVD2 14
+#define BM_PXP_WFE_A_STAGE1_MUX2_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE1_MUX2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE1_MUX2_RSVD2)
+#define BP_PXP_WFE_A_STAGE1_MUX2_MUX9 8
+#define BM_PXP_WFE_A_STAGE1_MUX2_MUX9 0x00003F00
+#define BF_PXP_WFE_A_STAGE1_MUX2_MUX9(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE1_MUX2_MUX9)
+#define BP_PXP_WFE_A_STAGE1_MUX2_RSVD3 6
+#define BM_PXP_WFE_A_STAGE1_MUX2_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE1_MUX2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE1_MUX2_RSVD3)
+#define BP_PXP_WFE_A_STAGE1_MUX2_MUX8 0
+#define BM_PXP_WFE_A_STAGE1_MUX2_MUX8 0x0000003F
+#define BF_PXP_WFE_A_STAGE1_MUX2_MUX8(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE1_MUX2_MUX8)
+
+#define HW_PXP_WFE_A_STAGE1_MUX3 (0x00001740)
+#define HW_PXP_WFE_A_STAGE1_MUX3_SET (0x00001744)
+#define HW_PXP_WFE_A_STAGE1_MUX3_CLR (0x00001748)
+#define HW_PXP_WFE_A_STAGE1_MUX3_TOG (0x0000174c)
+
+#define BP_PXP_WFE_A_STAGE1_MUX3_RSVD0 30
+#define BM_PXP_WFE_A_STAGE1_MUX3_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE1_MUX3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE1_MUX3_RSVD0)
+#define BP_PXP_WFE_A_STAGE1_MUX3_MUX15 24
+#define BM_PXP_WFE_A_STAGE1_MUX3_MUX15 0x3F000000
+#define BF_PXP_WFE_A_STAGE1_MUX3_MUX15(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE1_MUX3_MUX15)
+#define BP_PXP_WFE_A_STAGE1_MUX3_RSVD1 22
+#define BM_PXP_WFE_A_STAGE1_MUX3_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE1_MUX3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE1_MUX3_RSVD1)
+#define BP_PXP_WFE_A_STAGE1_MUX3_MUX14 16
+#define BM_PXP_WFE_A_STAGE1_MUX3_MUX14 0x003F0000
+#define BF_PXP_WFE_A_STAGE1_MUX3_MUX14(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE1_MUX3_MUX14)
+#define BP_PXP_WFE_A_STAGE1_MUX3_RSVD2 14
+#define BM_PXP_WFE_A_STAGE1_MUX3_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE1_MUX3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE1_MUX3_RSVD2)
+#define BP_PXP_WFE_A_STAGE1_MUX3_MUX13 8
+#define BM_PXP_WFE_A_STAGE1_MUX3_MUX13 0x00003F00
+#define BF_PXP_WFE_A_STAGE1_MUX3_MUX13(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE1_MUX3_MUX13)
+#define BP_PXP_WFE_A_STAGE1_MUX3_RSVD3 6
+#define BM_PXP_WFE_A_STAGE1_MUX3_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE1_MUX3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE1_MUX3_RSVD3)
+#define BP_PXP_WFE_A_STAGE1_MUX3_MUX12 0
+#define BM_PXP_WFE_A_STAGE1_MUX3_MUX12 0x0000003F
+#define BF_PXP_WFE_A_STAGE1_MUX3_MUX12(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE1_MUX3_MUX12)
+
+#define HW_PXP_WFE_A_STAGE1_MUX4 (0x00001750)
+#define HW_PXP_WFE_A_STAGE1_MUX4_SET (0x00001754)
+#define HW_PXP_WFE_A_STAGE1_MUX4_CLR (0x00001758)
+#define HW_PXP_WFE_A_STAGE1_MUX4_TOG (0x0000175c)
+
+#define BP_PXP_WFE_A_STAGE1_MUX4_RSVD0 24
+#define BM_PXP_WFE_A_STAGE1_MUX4_RSVD0 0xFF000000
+#define BF_PXP_WFE_A_STAGE1_MUX4_RSVD0(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE1_MUX4_RSVD0)
+#define BP_PXP_WFE_A_STAGE1_MUX4_RSVD1 16
+#define BM_PXP_WFE_A_STAGE1_MUX4_RSVD1 0x00FF0000
+#define BF_PXP_WFE_A_STAGE1_MUX4_RSVD1(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE1_MUX4_RSVD1)
+#define BP_PXP_WFE_A_STAGE1_MUX4_RSVD2 14
+#define BM_PXP_WFE_A_STAGE1_MUX4_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE1_MUX4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE1_MUX4_RSVD2)
+#define BP_PXP_WFE_A_STAGE1_MUX4_MUX17 8
+#define BM_PXP_WFE_A_STAGE1_MUX4_MUX17 0x00003F00
+#define BF_PXP_WFE_A_STAGE1_MUX4_MUX17(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE1_MUX4_MUX17)
+#define BP_PXP_WFE_A_STAGE1_MUX4_RSVD3 6
+#define BM_PXP_WFE_A_STAGE1_MUX4_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE1_MUX4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE1_MUX4_RSVD3)
+#define BP_PXP_WFE_A_STAGE1_MUX4_MUX16 0
+#define BM_PXP_WFE_A_STAGE1_MUX4_MUX16 0x0000003F
+#define BF_PXP_WFE_A_STAGE1_MUX4_MUX16(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE1_MUX4_MUX16)
+
+#define HW_PXP_WFE_A_STAGE2_MUX0 (0x00001760)
+#define HW_PXP_WFE_A_STAGE2_MUX0_SET (0x00001764)
+#define HW_PXP_WFE_A_STAGE2_MUX0_CLR (0x00001768)
+#define HW_PXP_WFE_A_STAGE2_MUX0_TOG (0x0000176c)
+
+#define BP_PXP_WFE_A_STAGE2_MUX0_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX0_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX0_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX0_MUX3 24
+#define BM_PXP_WFE_A_STAGE2_MUX0_MUX3 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX0_MUX3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX0_MUX3)
+#define BP_PXP_WFE_A_STAGE2_MUX0_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX0_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX0_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX0_MUX2 16
+#define BM_PXP_WFE_A_STAGE2_MUX0_MUX2 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX0_MUX2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX0_MUX2)
+#define BP_PXP_WFE_A_STAGE2_MUX0_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX0_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX0_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX0_MUX1 8
+#define BM_PXP_WFE_A_STAGE2_MUX0_MUX1 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX0_MUX1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX0_MUX1)
+#define BP_PXP_WFE_A_STAGE2_MUX0_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX0_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX0_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX0_MUX0 0
+#define BM_PXP_WFE_A_STAGE2_MUX0_MUX0 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX0_MUX0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX0_MUX0)
+
+#define HW_PXP_WFE_A_STAGE2_MUX1 (0x00001770)
+#define HW_PXP_WFE_A_STAGE2_MUX1_SET (0x00001774)
+#define HW_PXP_WFE_A_STAGE2_MUX1_CLR (0x00001778)
+#define HW_PXP_WFE_A_STAGE2_MUX1_TOG (0x0000177c)
+
+#define BP_PXP_WFE_A_STAGE2_MUX1_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX1_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX1_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX1_MUX7 24
+#define BM_PXP_WFE_A_STAGE2_MUX1_MUX7 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX1_MUX7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX1_MUX7)
+#define BP_PXP_WFE_A_STAGE2_MUX1_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX1_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX1_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX1_MUX6 16
+#define BM_PXP_WFE_A_STAGE2_MUX1_MUX6 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX1_MUX6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX1_MUX6)
+#define BP_PXP_WFE_A_STAGE2_MUX1_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX1_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX1_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX1_MUX5 8
+#define BM_PXP_WFE_A_STAGE2_MUX1_MUX5 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX1_MUX5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX1_MUX5)
+#define BP_PXP_WFE_A_STAGE2_MUX1_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX1_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX1_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX1_MUX4 0
+#define BM_PXP_WFE_A_STAGE2_MUX1_MUX4 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX1_MUX4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX1_MUX4)
+
+#define HW_PXP_WFE_A_STAGE2_MUX2 (0x00001780)
+#define HW_PXP_WFE_A_STAGE2_MUX2_SET (0x00001784)
+#define HW_PXP_WFE_A_STAGE2_MUX2_CLR (0x00001788)
+#define HW_PXP_WFE_A_STAGE2_MUX2_TOG (0x0000178c)
+
+#define BP_PXP_WFE_A_STAGE2_MUX2_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX2_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX2_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX2_MUX11 24
+#define BM_PXP_WFE_A_STAGE2_MUX2_MUX11 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX2_MUX11(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX2_MUX11)
+#define BP_PXP_WFE_A_STAGE2_MUX2_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX2_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX2_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX2_MUX10 16
+#define BM_PXP_WFE_A_STAGE2_MUX2_MUX10 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX2_MUX10(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX2_MUX10)
+#define BP_PXP_WFE_A_STAGE2_MUX2_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX2_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX2_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX2_MUX9 8
+#define BM_PXP_WFE_A_STAGE2_MUX2_MUX9 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX2_MUX9(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX2_MUX9)
+#define BP_PXP_WFE_A_STAGE2_MUX2_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX2_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX2_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX2_MUX8 0
+#define BM_PXP_WFE_A_STAGE2_MUX2_MUX8 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX2_MUX8(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX2_MUX8)
+
+#define HW_PXP_WFE_A_STAGE2_MUX3 (0x00001790)
+#define HW_PXP_WFE_A_STAGE2_MUX3_SET (0x00001794)
+#define HW_PXP_WFE_A_STAGE2_MUX3_CLR (0x00001798)
+#define HW_PXP_WFE_A_STAGE2_MUX3_TOG (0x0000179c)
+
+#define BP_PXP_WFE_A_STAGE2_MUX3_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX3_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX3_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX3_MUX15 24
+#define BM_PXP_WFE_A_STAGE2_MUX3_MUX15 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX3_MUX15(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX3_MUX15)
+#define BP_PXP_WFE_A_STAGE2_MUX3_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX3_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX3_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX3_MUX14 16
+#define BM_PXP_WFE_A_STAGE2_MUX3_MUX14 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX3_MUX14(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX3_MUX14)
+#define BP_PXP_WFE_A_STAGE2_MUX3_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX3_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX3_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX3_MUX13 8
+#define BM_PXP_WFE_A_STAGE2_MUX3_MUX13 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX3_MUX13(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX3_MUX13)
+#define BP_PXP_WFE_A_STAGE2_MUX3_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX3_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX3_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX3_MUX12 0
+#define BM_PXP_WFE_A_STAGE2_MUX3_MUX12 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX3_MUX12(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX3_MUX12)
+
+#define HW_PXP_WFE_A_STAGE2_MUX4 (0x000017a0)
+#define HW_PXP_WFE_A_STAGE2_MUX4_SET (0x000017a4)
+#define HW_PXP_WFE_A_STAGE2_MUX4_CLR (0x000017a8)
+#define HW_PXP_WFE_A_STAGE2_MUX4_TOG (0x000017ac)
+
+#define BP_PXP_WFE_A_STAGE2_MUX4_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX4_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX4_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX4_MUX19 24
+#define BM_PXP_WFE_A_STAGE2_MUX4_MUX19 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX4_MUX19(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX4_MUX19)
+#define BP_PXP_WFE_A_STAGE2_MUX4_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX4_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX4_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX4_MUX18 16
+#define BM_PXP_WFE_A_STAGE2_MUX4_MUX18 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX4_MUX18(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX4_MUX18)
+#define BP_PXP_WFE_A_STAGE2_MUX4_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX4_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX4_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX4_MUX17 8
+#define BM_PXP_WFE_A_STAGE2_MUX4_MUX17 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX4_MUX17(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX4_MUX17)
+#define BP_PXP_WFE_A_STAGE2_MUX4_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX4_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX4_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX4_MUX16 0
+#define BM_PXP_WFE_A_STAGE2_MUX4_MUX16 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX4_MUX16(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX4_MUX16)
+
+#define HW_PXP_WFE_A_STAGE2_MUX5 (0x000017b0)
+#define HW_PXP_WFE_A_STAGE2_MUX5_SET (0x000017b4)
+#define HW_PXP_WFE_A_STAGE2_MUX5_CLR (0x000017b8)
+#define HW_PXP_WFE_A_STAGE2_MUX5_TOG (0x000017bc)
+
+#define BP_PXP_WFE_A_STAGE2_MUX5_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX5_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX5_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX5_MUX23 24
+#define BM_PXP_WFE_A_STAGE2_MUX5_MUX23 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX5_MUX23(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX5_MUX23)
+#define BP_PXP_WFE_A_STAGE2_MUX5_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX5_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX5_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX5_MUX22 16
+#define BM_PXP_WFE_A_STAGE2_MUX5_MUX22 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX5_MUX22(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX5_MUX22)
+#define BP_PXP_WFE_A_STAGE2_MUX5_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX5_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX5_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX5_MUX21 8
+#define BM_PXP_WFE_A_STAGE2_MUX5_MUX21 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX5_MUX21(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX5_MUX21)
+#define BP_PXP_WFE_A_STAGE2_MUX5_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX5_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX5_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX5_MUX20 0
+#define BM_PXP_WFE_A_STAGE2_MUX5_MUX20 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX5_MUX20(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX5_MUX20)
+
+#define HW_PXP_WFE_A_STAGE2_MUX6 (0x000017c0)
+#define HW_PXP_WFE_A_STAGE2_MUX6_SET (0x000017c4)
+#define HW_PXP_WFE_A_STAGE2_MUX6_CLR (0x000017c8)
+#define HW_PXP_WFE_A_STAGE2_MUX6_TOG (0x000017cc)
+
+#define BP_PXP_WFE_A_STAGE2_MUX6_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX6_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX6_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX6_MUX27 24
+#define BM_PXP_WFE_A_STAGE2_MUX6_MUX27 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX6_MUX27(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX6_MUX27)
+#define BP_PXP_WFE_A_STAGE2_MUX6_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX6_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX6_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX6_MUX26 16
+#define BM_PXP_WFE_A_STAGE2_MUX6_MUX26 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX6_MUX26(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX6_MUX26)
+#define BP_PXP_WFE_A_STAGE2_MUX6_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX6_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX6_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX6_MUX25 8
+#define BM_PXP_WFE_A_STAGE2_MUX6_MUX25 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX6_MUX25(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX6_MUX25)
+#define BP_PXP_WFE_A_STAGE2_MUX6_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX6_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX6_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX6_MUX24 0
+#define BM_PXP_WFE_A_STAGE2_MUX6_MUX24 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX6_MUX24(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX6_MUX24)
+
+#define HW_PXP_WFE_A_STAGE2_MUX7 (0x000017d0)
+#define HW_PXP_WFE_A_STAGE2_MUX7_SET (0x000017d4)
+#define HW_PXP_WFE_A_STAGE2_MUX7_CLR (0x000017d8)
+#define HW_PXP_WFE_A_STAGE2_MUX7_TOG (0x000017dc)
+
+#define BP_PXP_WFE_A_STAGE2_MUX7_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX7_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX7_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX7_MUX31 24
+#define BM_PXP_WFE_A_STAGE2_MUX7_MUX31 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX7_MUX31(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX7_MUX31)
+#define BP_PXP_WFE_A_STAGE2_MUX7_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX7_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX7_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX7_MUX30 16
+#define BM_PXP_WFE_A_STAGE2_MUX7_MUX30 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX7_MUX30(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX7_MUX30)
+#define BP_PXP_WFE_A_STAGE2_MUX7_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX7_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX7_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX7_MUX29 8
+#define BM_PXP_WFE_A_STAGE2_MUX7_MUX29 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX7_MUX29(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX7_MUX29)
+#define BP_PXP_WFE_A_STAGE2_MUX7_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX7_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX7_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX7_MUX28 0
+#define BM_PXP_WFE_A_STAGE2_MUX7_MUX28 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX7_MUX28(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX7_MUX28)
+
+#define HW_PXP_WFE_A_STAGE2_MUX8 (0x000017e0)
+#define HW_PXP_WFE_A_STAGE2_MUX8_SET (0x000017e4)
+#define HW_PXP_WFE_A_STAGE2_MUX8_CLR (0x000017e8)
+#define HW_PXP_WFE_A_STAGE2_MUX8_TOG (0x000017ec)
+
+#define BP_PXP_WFE_A_STAGE2_MUX8_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX8_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX8_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX8_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX8_MUX35 24
+#define BM_PXP_WFE_A_STAGE2_MUX8_MUX35 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX8_MUX35(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX8_MUX35)
+#define BP_PXP_WFE_A_STAGE2_MUX8_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX8_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX8_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX8_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX8_MUX34 16
+#define BM_PXP_WFE_A_STAGE2_MUX8_MUX34 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX8_MUX34(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX8_MUX34)
+#define BP_PXP_WFE_A_STAGE2_MUX8_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX8_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX8_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX8_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX8_MUX33 8
+#define BM_PXP_WFE_A_STAGE2_MUX8_MUX33 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX8_MUX33(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX8_MUX33)
+#define BP_PXP_WFE_A_STAGE2_MUX8_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX8_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX8_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX8_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX8_MUX32 0
+#define BM_PXP_WFE_A_STAGE2_MUX8_MUX32 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX8_MUX32(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX8_MUX32)
+
+#define HW_PXP_WFE_A_STAGE2_MUX9 (0x000017f0)
+#define HW_PXP_WFE_A_STAGE2_MUX9_SET (0x000017f4)
+#define HW_PXP_WFE_A_STAGE2_MUX9_CLR (0x000017f8)
+#define HW_PXP_WFE_A_STAGE2_MUX9_TOG (0x000017fc)
+
+#define BP_PXP_WFE_A_STAGE2_MUX9_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX9_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX9_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX9_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX9_MUX39 24
+#define BM_PXP_WFE_A_STAGE2_MUX9_MUX39 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX9_MUX39(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX9_MUX39)
+#define BP_PXP_WFE_A_STAGE2_MUX9_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX9_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX9_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX9_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX9_MUX38 16
+#define BM_PXP_WFE_A_STAGE2_MUX9_MUX38 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX9_MUX38(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX9_MUX38)
+#define BP_PXP_WFE_A_STAGE2_MUX9_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX9_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX9_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX9_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX9_MUX37 8
+#define BM_PXP_WFE_A_STAGE2_MUX9_MUX37 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX9_MUX37(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX9_MUX37)
+#define BP_PXP_WFE_A_STAGE2_MUX9_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX9_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX9_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX9_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX9_MUX36 0
+#define BM_PXP_WFE_A_STAGE2_MUX9_MUX36 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX9_MUX36(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX9_MUX36)
+
+#define HW_PXP_WFE_A_STAGE2_MUX10 (0x00001800)
+#define HW_PXP_WFE_A_STAGE2_MUX10_SET (0x00001804)
+#define HW_PXP_WFE_A_STAGE2_MUX10_CLR (0x00001808)
+#define HW_PXP_WFE_A_STAGE2_MUX10_TOG (0x0000180c)
+
+#define BP_PXP_WFE_A_STAGE2_MUX10_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX10_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX10_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX10_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX10_MUX43 24
+#define BM_PXP_WFE_A_STAGE2_MUX10_MUX43 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX10_MUX43(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX10_MUX43)
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__INC 0x0
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__DEC 0x1
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__ADD 0x2
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__MINUS 0x3
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__AND 0x4
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__OR 0x5
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__XOR 0x6
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__SHIFTLEFT 0x7
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__SHIFTRIGHT 0x8
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__BIT_AND 0x9
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__BIT_OR 0xa
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__BIT_CMP 0xb
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX43__NOP 0xc
+#define BP_PXP_WFE_A_STAGE2_MUX10_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX10_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX10_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX10_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX10_MUX42 16
+#define BM_PXP_WFE_A_STAGE2_MUX10_MUX42 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX10_MUX42(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX10_MUX42)
+#define BP_PXP_WFE_A_STAGE2_MUX10_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX10_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX10_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX10_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX10_MUX41 8
+#define BM_PXP_WFE_A_STAGE2_MUX10_MUX41 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX10_MUX41(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX10_MUX41)
+#define BP_PXP_WFE_A_STAGE2_MUX10_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX10_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX10_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX10_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX10_MUX40 0
+#define BM_PXP_WFE_A_STAGE2_MUX10_MUX40 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX10_MUX40(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX10_MUX40)
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__INC 0x0
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__DEC 0x1
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__ADD 0x2
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__MINUS 0x3
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__AND 0x4
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__OR 0x5
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__XOR 0x6
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__SHIFTLEFT 0x7
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__SHIFTRIGHT 0x8
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__BIT_AND 0x9
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__BIT_OR 0xa
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__BIT_CMP 0xb
+#define BV_PXP_WFE_A_STAGE2_MUX10_MUX40__NOP 0xc
+
+#define HW_PXP_WFE_A_STAGE2_MUX11 (0x00001810)
+#define HW_PXP_WFE_A_STAGE2_MUX11_SET (0x00001814)
+#define HW_PXP_WFE_A_STAGE2_MUX11_CLR (0x00001818)
+#define HW_PXP_WFE_A_STAGE2_MUX11_TOG (0x0000181c)
+
+#define BP_PXP_WFE_A_STAGE2_MUX11_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_MUX11_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_MUX11_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_MUX11_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX11_MUX47 24
+#define BM_PXP_WFE_A_STAGE2_MUX11_MUX47 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_MUX11_MUX47(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_MUX11_MUX47)
+#define BP_PXP_WFE_A_STAGE2_MUX11_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_MUX11_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_MUX11_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_MUX11_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_MUX11_MUX46 16
+#define BM_PXP_WFE_A_STAGE2_MUX11_MUX46 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_MUX11_MUX46(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_MUX11_MUX46)
+#define BP_PXP_WFE_A_STAGE2_MUX11_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_MUX11_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_MUX11_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX11_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_MUX11_MUX45 8
+#define BM_PXP_WFE_A_STAGE2_MUX11_MUX45 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX11_MUX45(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX11_MUX45)
+#define BP_PXP_WFE_A_STAGE2_MUX11_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX11_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX11_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX11_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX11_MUX44 0
+#define BM_PXP_WFE_A_STAGE2_MUX11_MUX44 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX11_MUX44(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX11_MUX44)
+
+#define HW_PXP_WFE_A_STAGE2_MUX12 (0x00001820)
+#define HW_PXP_WFE_A_STAGE2_MUX12_SET (0x00001824)
+#define HW_PXP_WFE_A_STAGE2_MUX12_CLR (0x00001828)
+#define HW_PXP_WFE_A_STAGE2_MUX12_TOG (0x0000182c)
+
+#define BP_PXP_WFE_A_STAGE2_MUX12_RSVD0 14
+#define BM_PXP_WFE_A_STAGE2_MUX12_RSVD0 0xFFFFC000
+#define BF_PXP_WFE_A_STAGE2_MUX12_RSVD0(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_MUX12_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_MUX12_MUX49 8
+#define BM_PXP_WFE_A_STAGE2_MUX12_MUX49 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_MUX12_MUX49(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_MUX12_MUX49)
+#define BP_PXP_WFE_A_STAGE2_MUX12_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_MUX12_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_MUX12_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_MUX12_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_MUX12_MUX48 0
+#define BM_PXP_WFE_A_STAGE2_MUX12_MUX48 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_MUX12_MUX48(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_MUX12_MUX48)
+
+#define HW_PXP_WFE_A_STAGE3_MUX0 (0x00001830)
+#define HW_PXP_WFE_A_STAGE3_MUX0_SET (0x00001834)
+#define HW_PXP_WFE_A_STAGE3_MUX0_CLR (0x00001838)
+#define HW_PXP_WFE_A_STAGE3_MUX0_TOG (0x0000183c)
+
+#define BP_PXP_WFE_A_STAGE3_MUX0_RSVD0 30
+#define BM_PXP_WFE_A_STAGE3_MUX0_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE3_MUX0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE3_MUX0_RSVD0)
+#define BP_PXP_WFE_A_STAGE3_MUX0_MUX3 24
+#define BM_PXP_WFE_A_STAGE3_MUX0_MUX3 0x3F000000
+#define BF_PXP_WFE_A_STAGE3_MUX0_MUX3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE3_MUX0_MUX3)
+#define BP_PXP_WFE_A_STAGE3_MUX0_RSVD1 22
+#define BM_PXP_WFE_A_STAGE3_MUX0_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE3_MUX0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE3_MUX0_RSVD1)
+#define BP_PXP_WFE_A_STAGE3_MUX0_MUX2 16
+#define BM_PXP_WFE_A_STAGE3_MUX0_MUX2 0x003F0000
+#define BF_PXP_WFE_A_STAGE3_MUX0_MUX2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE3_MUX0_MUX2)
+#define BP_PXP_WFE_A_STAGE3_MUX0_RSVD2 14
+#define BM_PXP_WFE_A_STAGE3_MUX0_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE3_MUX0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE3_MUX0_RSVD2)
+#define BP_PXP_WFE_A_STAGE3_MUX0_MUX1 8
+#define BM_PXP_WFE_A_STAGE3_MUX0_MUX1 0x00003F00
+#define BF_PXP_WFE_A_STAGE3_MUX0_MUX1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE3_MUX0_MUX1)
+#define BP_PXP_WFE_A_STAGE3_MUX0_RSVD3 6
+#define BM_PXP_WFE_A_STAGE3_MUX0_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE3_MUX0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE3_MUX0_RSVD3)
+#define BP_PXP_WFE_A_STAGE3_MUX0_MUX0 0
+#define BM_PXP_WFE_A_STAGE3_MUX0_MUX0 0x0000003F
+#define BF_PXP_WFE_A_STAGE3_MUX0_MUX0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE3_MUX0_MUX0)
+
+#define HW_PXP_WFE_A_STAGE3_MUX1 (0x00001840)
+#define HW_PXP_WFE_A_STAGE3_MUX1_SET (0x00001844)
+#define HW_PXP_WFE_A_STAGE3_MUX1_CLR (0x00001848)
+#define HW_PXP_WFE_A_STAGE3_MUX1_TOG (0x0000184c)
+
+#define BP_PXP_WFE_A_STAGE3_MUX1_RSVD0 30
+#define BM_PXP_WFE_A_STAGE3_MUX1_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE3_MUX1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE3_MUX1_RSVD0)
+#define BP_PXP_WFE_A_STAGE3_MUX1_MUX7 24
+#define BM_PXP_WFE_A_STAGE3_MUX1_MUX7 0x3F000000
+#define BF_PXP_WFE_A_STAGE3_MUX1_MUX7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE3_MUX1_MUX7)
+#define BP_PXP_WFE_A_STAGE3_MUX1_RSVD1 22
+#define BM_PXP_WFE_A_STAGE3_MUX1_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE3_MUX1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE3_MUX1_RSVD1)
+#define BP_PXP_WFE_A_STAGE3_MUX1_MUX6 16
+#define BM_PXP_WFE_A_STAGE3_MUX1_MUX6 0x003F0000
+#define BF_PXP_WFE_A_STAGE3_MUX1_MUX6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE3_MUX1_MUX6)
+#define BP_PXP_WFE_A_STAGE3_MUX1_RSVD2 14
+#define BM_PXP_WFE_A_STAGE3_MUX1_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE3_MUX1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE3_MUX1_RSVD2)
+#define BP_PXP_WFE_A_STAGE3_MUX1_MUX5 8
+#define BM_PXP_WFE_A_STAGE3_MUX1_MUX5 0x00003F00
+#define BF_PXP_WFE_A_STAGE3_MUX1_MUX5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE3_MUX1_MUX5)
+#define BP_PXP_WFE_A_STAGE3_MUX1_RSVD3 6
+#define BM_PXP_WFE_A_STAGE3_MUX1_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE3_MUX1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE3_MUX1_RSVD3)
+#define BP_PXP_WFE_A_STAGE3_MUX1_MUX4 0
+#define BM_PXP_WFE_A_STAGE3_MUX1_MUX4 0x0000003F
+#define BF_PXP_WFE_A_STAGE3_MUX1_MUX4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE3_MUX1_MUX4)
+
+#define HW_PXP_WFE_A_STAGE3_MUX2 (0x00001850)
+#define HW_PXP_WFE_A_STAGE3_MUX2_SET (0x00001854)
+#define HW_PXP_WFE_A_STAGE3_MUX2_CLR (0x00001858)
+#define HW_PXP_WFE_A_STAGE3_MUX2_TOG (0x0000185c)
+
+#define BP_PXP_WFE_A_STAGE3_MUX2_RSVD0 30
+#define BM_PXP_WFE_A_STAGE3_MUX2_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE3_MUX2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE3_MUX2_RSVD0)
+#define BP_PXP_WFE_A_STAGE3_MUX2_MUX11 24
+#define BM_PXP_WFE_A_STAGE3_MUX2_MUX11 0x3F000000
+#define BF_PXP_WFE_A_STAGE3_MUX2_MUX11(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE3_MUX2_MUX11)
+#define BP_PXP_WFE_A_STAGE3_MUX2_RSVD1 22
+#define BM_PXP_WFE_A_STAGE3_MUX2_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE3_MUX2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE3_MUX2_RSVD1)
+#define BP_PXP_WFE_A_STAGE3_MUX2_MUX10 16
+#define BM_PXP_WFE_A_STAGE3_MUX2_MUX10 0x003F0000
+#define BF_PXP_WFE_A_STAGE3_MUX2_MUX10(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE3_MUX2_MUX10)
+#define BP_PXP_WFE_A_STAGE3_MUX2_RSVD2 14
+#define BM_PXP_WFE_A_STAGE3_MUX2_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE3_MUX2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE3_MUX2_RSVD2)
+#define BP_PXP_WFE_A_STAGE3_MUX2_MUX9 8
+#define BM_PXP_WFE_A_STAGE3_MUX2_MUX9 0x00003F00
+#define BF_PXP_WFE_A_STAGE3_MUX2_MUX9(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE3_MUX2_MUX9)
+#define BP_PXP_WFE_A_STAGE3_MUX2_RSVD3 6
+#define BM_PXP_WFE_A_STAGE3_MUX2_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE3_MUX2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE3_MUX2_RSVD3)
+#define BP_PXP_WFE_A_STAGE3_MUX2_MUX8 0
+#define BM_PXP_WFE_A_STAGE3_MUX2_MUX8 0x0000003F
+#define BF_PXP_WFE_A_STAGE3_MUX2_MUX8(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE3_MUX2_MUX8)
+
+#define HW_PXP_WFE_A_STAGE3_MUX3 (0x00001860)
+#define HW_PXP_WFE_A_STAGE3_MUX3_SET (0x00001864)
+#define HW_PXP_WFE_A_STAGE3_MUX3_CLR (0x00001868)
+#define HW_PXP_WFE_A_STAGE3_MUX3_TOG (0x0000186c)
+
+#define BP_PXP_WFE_A_STAGE3_MUX3_RSVD0 30
+#define BM_PXP_WFE_A_STAGE3_MUX3_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE3_MUX3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE3_MUX3_RSVD0)
+#define BP_PXP_WFE_A_STAGE3_MUX3_MUX15 24
+#define BM_PXP_WFE_A_STAGE3_MUX3_MUX15 0x3F000000
+#define BF_PXP_WFE_A_STAGE3_MUX3_MUX15(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE3_MUX3_MUX15)
+#define BP_PXP_WFE_A_STAGE3_MUX3_RSVD1 22
+#define BM_PXP_WFE_A_STAGE3_MUX3_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE3_MUX3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE3_MUX3_RSVD1)
+#define BP_PXP_WFE_A_STAGE3_MUX3_MUX14 16
+#define BM_PXP_WFE_A_STAGE3_MUX3_MUX14 0x003F0000
+#define BF_PXP_WFE_A_STAGE3_MUX3_MUX14(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE3_MUX3_MUX14)
+#define BP_PXP_WFE_A_STAGE3_MUX3_RSVD2 14
+#define BM_PXP_WFE_A_STAGE3_MUX3_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE3_MUX3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE3_MUX3_RSVD2)
+#define BP_PXP_WFE_A_STAGE3_MUX3_MUX13 8
+#define BM_PXP_WFE_A_STAGE3_MUX3_MUX13 0x00003F00
+#define BF_PXP_WFE_A_STAGE3_MUX3_MUX13(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE3_MUX3_MUX13)
+#define BP_PXP_WFE_A_STAGE3_MUX3_RSVD3 6
+#define BM_PXP_WFE_A_STAGE3_MUX3_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE3_MUX3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE3_MUX3_RSVD3)
+#define BP_PXP_WFE_A_STAGE3_MUX3_MUX12 0
+#define BM_PXP_WFE_A_STAGE3_MUX3_MUX12 0x0000003F
+#define BF_PXP_WFE_A_STAGE3_MUX3_MUX12(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE3_MUX3_MUX12)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT0_0 (0x00001870)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT31)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT30)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT29)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT28)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT27)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT26)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT25)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT24)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT23)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT22)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT21)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT20)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT19)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT18)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT17)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT16)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT15)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT14)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT13)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT12)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT11)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT10)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT9)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT8)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT7)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT6)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT5)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT4)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT3)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT2)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT1)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT0_0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT0_1 (0x00001880)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT63)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT62)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT61)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT60)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT59)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT58)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT57)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT56)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT55)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT54)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT53)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT52)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT51)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT50)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT49)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT48)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT47)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT46)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT45)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT44)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT43)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT42)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT41)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT40)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT39)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT38)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT37)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT36)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT35)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT34)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT33)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT0_1_LUTOUT32)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT0_2 (0x00001890)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT95)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT94)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT93)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT92)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT91)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT90)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT89)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT88)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT87)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT86)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT85)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT84)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT83)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT82)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT81)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT80)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT79)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT78)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT77)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT76)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT75)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT74)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT73)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT72)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT71)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT70)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT69)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT68)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT67)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT66)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT65)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT0_2_LUTOUT64)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT0_3 (0x000018a0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT127)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT126)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT125)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT124)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT123)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT122)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT121)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT120)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT119)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT118)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT117)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT116)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT115)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT114)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT113)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT112)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT111)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT110)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT109)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT108)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT107)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT106)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT105)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT104)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT103)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT102)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT101)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT100)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT99)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT98)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT97)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT0_3_LUTOUT96)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT0_4 (0x000018b0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT159)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT158)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT157)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT156)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT155)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT154)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT153)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT152)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT151)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT150)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT149)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT148)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT147)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT146)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT145)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT144)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT143)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT142)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT141)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT140)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT139)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT138)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT137)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT136)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT135)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT134)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT133)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT132)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT131)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT130)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT129)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT0_4_LUTOUT128)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT0_5 (0x000018c0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT191)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT190)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT189)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT188)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT187)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT186)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT185)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT184)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT183)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT182)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT181)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT180)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT179)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT178)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT177)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT176)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT175)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT174)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT173)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT172)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT171)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT170)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT169)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT168)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT167)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT166)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT165)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT164)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT163)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT162)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT161)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT0_5_LUTOUT160)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT0_6 (0x000018d0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT223)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT222)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT221)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT220)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT219)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT218)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT217)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT216)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT215)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT214)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT213)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT212)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT211)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT210)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT209)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT208)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT207)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT206)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT205)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT204)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT203)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT202)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT201)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT200)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT199)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT198)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT197)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT196)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT195)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT194)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT193)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT0_6_LUTOUT192)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT0_7 (0x000018e0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT255)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT254)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT253)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT252)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT251)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT250)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT249)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT248)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT247)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT246)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT245)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT244)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT243)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT242)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT241)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT240)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT239)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT238)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT237)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT236)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT235)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT234)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT233)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT232)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT231)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT230)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT229)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT228)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT227)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT226)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT225)
+#define BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT0_7_LUTOUT224)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT1_0 (0x000018f0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT31)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT30)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT29)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT28)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT27)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT26)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT25)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT24)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT23)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT22)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT21)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT20)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT19)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT18)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT17)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT16)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT15)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT14)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT13)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT12)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT11)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT10)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT9)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT8)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT7)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT6)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT5)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT4)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT3)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT2)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT1)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT1_0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT1_1 (0x00001900)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT63)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT62)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT61)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT60)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT59)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT58)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT57)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT56)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT55)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT54)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT53)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT52)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT51)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT50)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT49)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT48)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT47)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT46)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT45)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT44)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT43)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT42)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT41)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT40)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT39)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT38)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT37)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT36)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT35)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT34)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT33)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT1_1_LUTOUT32)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT1_2 (0x00001910)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT95)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT94)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT93)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT92)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT91)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT90)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT89)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT88)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT87)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT86)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT85)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT84)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT83)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT82)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT81)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT80)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT79)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT78)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT77)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT76)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT75)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT74)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT73)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT72)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT71)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT70)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT69)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT68)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT67)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT66)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT65)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT1_2_LUTOUT64)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT1_3 (0x00001920)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT127)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT126)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT125)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT124)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT123)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT122)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT121)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT120)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT119)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT118)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT117)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT116)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT115)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT114)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT113)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT112)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT111)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT110)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT109)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT108)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT107)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT106)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT105)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT104)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT103)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT102)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT101)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT100)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT99)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT98)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT97)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT1_3_LUTOUT96)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT1_4 (0x00001930)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT159)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT158)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT157)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT156)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT155)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT154)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT153)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT152)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT151)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT150)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT149)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT148)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT147)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT146)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT145)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT144)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT143)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT142)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT141)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT140)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT139)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT138)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT137)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT136)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT135)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT134)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT133)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT132)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT131)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT130)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT129)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT1_4_LUTOUT128)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT1_5 (0x00001940)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT191)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT190)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT189)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT188)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT187)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT186)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT185)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT184)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT183)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT182)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT181)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT180)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT179)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT178)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT177)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT176)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT175)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT174)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT173)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT172)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT171)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT170)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT169)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT168)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT167)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT166)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT165)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT164)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT163)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT162)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT161)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT1_5_LUTOUT160)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT1_6 (0x00001950)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT223)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT222)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT221)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT220)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT219)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT218)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT217)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT216)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT215)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT214)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT213)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT212)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT211)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT210)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT209)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT208)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT207)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT206)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT205)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT204)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT203)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT202)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT201)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT200)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT199)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT198)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT197)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT196)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT195)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT194)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT193)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT1_6_LUTOUT192)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT1_7 (0x00001960)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT255)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT254)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT253)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT252)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT251)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT250)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT249)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT248)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT247)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT246)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT245)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT244)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT243)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT242)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT241)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT240)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT239)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT238)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT237)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT236)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT235)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT234)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT233)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT232)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT231)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT230)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT229)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT228)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT227)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT226)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT225)
+#define BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT1_7_LUTOUT224)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT2_0 (0x00001970)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT31)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT30)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT29)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT28)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT27)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT26)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT25)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT24)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT23)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT22)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT21)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT20)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT19)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT18)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT17)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT16)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT15)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT14)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT13)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT12)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT11)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT10)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT9)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT8)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT7)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT6)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT5)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT4)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT3)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT2)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT1)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT2_0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT2_1 (0x00001980)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT63)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT62)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT61)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT60)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT59)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT58)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT57)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT56)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT55)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT54)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT53)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT52)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT51)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT50)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT49)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT48)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT47)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT46)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT45)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT44)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT43)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT42)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT41)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT40)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT39)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT38)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT37)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT36)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT35)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT34)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT33)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT2_1_LUTOUT32)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT2_2 (0x00001990)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT95)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT94)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT93)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT92)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT91)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT90)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT89)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT88)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT87)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT86)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT85)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT84)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT83)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT82)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT81)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT80)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT79)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT78)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT77)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT76)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT75)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT74)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT73)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT72)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT71)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT70)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT69)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT68)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT67)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT66)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT65)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT2_2_LUTOUT64)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT2_3 (0x000019a0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT127)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT126)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT125)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT124)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT123)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT122)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT121)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT120)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT119)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT118)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT117)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT116)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT115)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT114)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT113)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT112)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT111)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT110)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT109)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT108)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT107)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT106)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT105)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT104)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT103)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT102)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT101)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT100)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT99)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT98)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT97)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT2_3_LUTOUT96)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT2_4 (0x000019b0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT159)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT158)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT157)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT156)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT155)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT154)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT153)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT152)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT151)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT150)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT149)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT148)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT147)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT146)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT145)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT144)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT143)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT142)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT141)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT140)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT139)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT138)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT137)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT136)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT135)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT134)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT133)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT132)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT131)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT130)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT129)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT2_4_LUTOUT128)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT2_5 (0x000019c0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT191)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT190)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT189)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT188)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT187)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT186)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT185)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT184)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT183)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT182)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT181)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT180)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT179)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT178)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT177)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT176)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT175)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT174)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT173)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT172)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT171)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT170)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT169)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT168)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT167)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT166)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT165)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT164)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT163)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT162)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT161)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT2_5_LUTOUT160)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT2_6 (0x000019d0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT223)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT222)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT221)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT220)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT219)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT218)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT217)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT216)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT215)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT214)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT213)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT212)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT211)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT210)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT209)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT208)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT207)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT206)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT205)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT204)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT203)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT202)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT201)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT200)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT199)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT198)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT197)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT196)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT195)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT194)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT193)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT2_6_LUTOUT192)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT2_7 (0x000019e0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT255)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT254)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT253)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT252)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT251)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT250)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT249)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT248)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT247)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT246)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT245)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT244)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT243)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT242)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT241)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT240)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT239)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT238)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT237)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT236)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT235)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT234)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT233)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT232)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT231)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT230)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT229)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT228)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT227)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT226)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT225)
+#define BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT2_7_LUTOUT224)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT3_0 (0x000019f0)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT31)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT30)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT29)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT28)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT27)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT26)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT25)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT24)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT23)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT22)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT21)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT20)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT19)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT18)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT17)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT16)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT15)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT14)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT13)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT12)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT11)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT10)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT9)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT8)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT7)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT6)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT5)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT4)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT3)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT2)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT1)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT3_0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT3_1 (0x00001a00)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT63)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT62)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT61)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT60)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT59)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT58)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT57)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT56)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT55)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT54)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT53)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT52)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT51)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT50)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT49)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT48)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT47)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT46)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT45)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT44)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT43)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT42)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT41)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT40)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT39)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT38)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT37)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT36)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT35)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT34)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT33)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT3_1_LUTOUT32)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT3_2 (0x00001a10)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT95)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT94)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT93)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT92)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT91)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT90)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT89)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT88)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT87)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT86)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT85)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT84)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT83)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT82)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT81)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT80)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT79)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT78)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT77)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT76)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT75)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT74)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT73)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT72)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT71)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT70)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT69)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT68)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT67)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT66)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT65)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT3_2_LUTOUT64)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT3_3 (0x00001a20)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT127)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT126)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT125)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT124)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT123)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT122)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT121)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT120)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT119)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT118)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT117)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT116)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT115)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT114)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT113)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT112)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT111)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT110)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT109)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT108)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT107)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT106)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT105)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT104)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT103)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT102)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT101)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT100)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT99)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT98)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT97)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT3_3_LUTOUT96)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT3_4 (0x00001a30)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT159)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT158)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT157)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT156)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT155)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT154)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT153)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT152)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT151)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT150)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT149)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT148)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT147)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT146)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT145)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT144)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT143)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT142)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT141)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT140)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT139)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT138)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT137)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT136)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT135)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT134)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT133)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT132)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT131)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT130)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT129)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT3_4_LUTOUT128)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT3_5 (0x00001a40)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT191)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT190)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT189)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT188)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT187)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT186)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT185)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT184)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT183)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT182)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT181)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT180)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT179)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT178)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT177)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT176)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT175)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT174)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT173)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT172)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT171)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT170)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT169)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT168)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT167)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT166)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT165)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT164)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT163)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT162)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT161)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT3_5_LUTOUT160)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT3_6 (0x00001a50)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT223)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT222)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT221)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT220)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT219)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT218)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT217)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT216)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT215)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT214)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT213)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT212)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT211)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT210)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT209)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT208)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT207)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT206)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT205)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT204)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT203)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT202)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT201)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT200)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT199)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT198)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT197)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT196)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT195)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT194)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT193)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT3_6_LUTOUT192)
+
+#define HW_PXP_WFE_A_STG1_8X1_OUT3_7 (0x00001a60)
+
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT255)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT254)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT253)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT252)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT251)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT250)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT249)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT248)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT247)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT246)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT245)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT244)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT243)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT242)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT241)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT240)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT239)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT238)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT237)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT236)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT235)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT234)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT233)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT232)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT231)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT230)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT229)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT228)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT227)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT226)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT225)
+#define BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG1_8X1_OUT3_7_LUTOUT224)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT0_0 (0x00001a70)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT3 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT3 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT2 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT2 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT1 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT1 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT0_0_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT0 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT0 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT0_0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT0_1 (0x00001a80)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT7 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT7 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT7)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT6 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT6 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT6)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT5 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT5 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT5)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT0_1_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT4 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT4 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT0_1_LUTOUT4)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT0_2 (0x00001a90)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT11 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT11 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT11)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT10 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT10 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT10)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT9 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT9 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT9)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT0_2_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT8 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT8 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT0_2_LUTOUT8)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT0_3 (0x00001aa0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT15 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT15 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT15)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT14 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT14 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT14)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT13 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT13 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT13)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT0_3_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT12 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT12 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT0_3_LUTOUT12)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT0_4 (0x00001ab0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT19 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT19 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT19)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT18 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT18 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT18)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT17 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT17 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT17)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT0_4_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT16 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT16 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT0_4_LUTOUT16)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT0_5 (0x00001ac0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT23 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT23 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT23)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT22 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT22 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT22)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT21 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT21 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT21)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT0_5_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT20 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT20 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT0_5_LUTOUT20)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT0_6 (0x00001ad0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT27 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT27 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT27)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT26 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT26 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT26)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT25 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT25 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT25)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT0_6_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT24 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT24 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT0_6_LUTOUT24)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT0_7 (0x00001ae0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT31 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT31 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT31)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT30 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT30 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT30)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT29 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT29 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT29)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT0_7_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT28 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT28 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT0_7_LUTOUT28)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT1_0 (0x00001af0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT3 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT3 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT2 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT2 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT1 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT1 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT1_0_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT0 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT0 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT1_0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT1_1 (0x00001b00)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT7 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT7 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT7)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT6 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT6 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT6)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT5 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT5 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT5)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT1_1_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT4 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT4 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT1_1_LUTOUT4)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT1_2 (0x00001b10)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT11 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT11 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT11)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT10 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT10 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT10)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT9 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT9 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT9)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT1_2_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT8 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT8 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT1_2_LUTOUT8)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT1_3 (0x00001b20)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT15 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT15 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT15)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT14 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT14 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT14)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT13 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT13 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT13)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT1_3_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT12 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT12 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT1_3_LUTOUT12)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT1_4 (0x00001b30)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT19 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT19 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT19)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT18 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT18 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT18)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT17 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT17 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT17)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT1_4_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT16 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT16 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT1_4_LUTOUT16)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT1_5 (0x00001b40)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT23 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT23 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT23)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT22 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT22 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT22)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT21 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT21 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT21)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT1_5_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT20 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT20 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT1_5_LUTOUT20)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT1_6 (0x00001b50)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT27 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT27 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT27)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT26 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT26 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT26)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT25 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT25 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT25)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT1_6_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT24 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT24 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT1_6_LUTOUT24)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT1_7 (0x00001b60)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT31 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT31 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT31)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT30 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT30 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT30)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT29 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT29 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT29)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT1_7_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT28 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT28 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT1_7_LUTOUT28)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT2_0 (0x00001b70)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT3 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT3 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT2 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT2 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT1 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT1 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT2_0_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT0 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT0 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT2_0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT2_1 (0x00001b80)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT7 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT7 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT7)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT6 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT6 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT6)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT5 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT5 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT5)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT2_1_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT4 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT4 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT2_1_LUTOUT4)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT2_2 (0x00001b90)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT11 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT11 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT11)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT10 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT10 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT10)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT9 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT9 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT9)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT2_2_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT8 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT8 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT2_2_LUTOUT8)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT2_3 (0x00001ba0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT15 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT15 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT15)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT14 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT14 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT14)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT13 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT13 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT13)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT2_3_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT12 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT12 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT2_3_LUTOUT12)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT2_4 (0x00001bb0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT19 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT19 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT19)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT18 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT18 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT18)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT17 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT17 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT17)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT2_4_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT16 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT16 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT2_4_LUTOUT16)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT2_5 (0x00001bc0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT23 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT23 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT23)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT22 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT22 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT22)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT21 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT21 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT21)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT2_5_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT20 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT20 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT2_5_LUTOUT20)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT2_6 (0x00001bd0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT27 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT27 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT27)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT26 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT26 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT26)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT25 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT25 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT25)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT2_6_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT24 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT24 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT2_6_LUTOUT24)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT2_7 (0x00001be0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT31 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT31 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT31)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT30 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT30 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT30)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT29 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT29 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT29)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT2_7_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT28 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT28 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT2_7_LUTOUT28)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT3_0 (0x00001bf0)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT3 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT3 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT2 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT2 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT1 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT1 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT3_0_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT0 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT0 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT3_0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT3_1 (0x00001c00)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT7 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT7 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT7)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT6 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT6 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT6)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT5 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT5 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT5)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT3_1_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT4 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT4 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT3_1_LUTOUT4)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT3_2 (0x00001c10)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT11 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT11 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT11)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT10 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT10 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT10)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT9 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT9 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT9)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT3_2_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT8 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT8 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT3_2_LUTOUT8)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT3_3 (0x00001c20)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT15 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT15 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT15)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT14 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT14 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT14)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT13 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT13 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT13)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT3_3_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT12 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT12 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT3_3_LUTOUT12)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT3_4 (0x00001c30)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT19 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT19 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT19)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT18 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT18 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT18)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT17 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT17 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT17)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT3_4_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT16 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT16 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT3_4_LUTOUT16)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT3_5 (0x00001c40)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT23 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT23 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT23)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT22 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT22 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT22)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT21 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT21 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT21)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT3_5_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT20 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT20 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT3_5_LUTOUT20)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT3_6 (0x00001c50)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT27 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT27 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT27)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT26 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT26 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT26)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT25 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT25 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT25)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT3_6_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT24 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT24 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT3_6_LUTOUT24)
+
+#define HW_PXP_WFE_A_STG2_5X6_OUT3_7 (0x00001c60)
+
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD0 30
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT31 24
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT31 0x3F000000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT31)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD1 22
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT30 16
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT30 0x003F0000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT30)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD2 14
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT29 8
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT29 0x00003F00
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT29)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD3 6
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X6_OUT3_7_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT28 0
+#define BM_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT28 0x0000003F
+#define BF_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X6_OUT3_7_LUTOUT28)
+
+#define HW_PXP_WFE_A_STAGE2_5X6_MASKS_0 (0x00001c70)
+
+#define BP_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD0 29
+#define BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD0 0xE0000000
+#define BF_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD0(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK3 24
+#define BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK3 0x1F000000
+#define BF_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK3)
+#define BP_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD1 21
+#define BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD1 0x00E00000
+#define BF_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD1(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK2 16
+#define BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK2 0x001F0000
+#define BF_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK2)
+#define BP_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD2 13
+#define BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD2 0x0000E000
+#define BF_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD2(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK1 8
+#define BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK1 0x00001F00
+#define BF_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK1)
+#define BP_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD3 5
+#define BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD3 0x000000E0
+#define BF_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD3(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK0 0
+#define BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK0 0x0000001F
+#define BF_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_5X6_MASKS_0_MASK0)
+
+#define HW_PXP_WFE_A_STAGE2_5X6_ADDR_0 (0x00001c80)
+
+#define BP_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD0 30
+#define BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD0)
+#define BP_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR3 24
+#define BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR3 0x3F000000
+#define BF_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR3)
+#define BP_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD1 22
+#define BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD1)
+#define BP_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR2 16
+#define BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR2 0x003F0000
+#define BF_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR2)
+#define BP_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD2 14
+#define BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD2)
+#define BP_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR1 8
+#define BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR1 0x00003F00
+#define BF_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR1)
+#define BP_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD3 6
+#define BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_RSVD3)
+#define BP_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR0 0
+#define BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR0 0x0000003F
+#define BF_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STAGE2_5X6_ADDR_0_MUXADDR0)
+
+#define HW_PXP_WFE_A_STG2_5X1_OUT0 (0x00001c90)
+
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT31)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT30)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT29)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT28)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT27)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT26)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT25)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT24)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT23)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT22)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT21)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT20)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT19)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT18)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT17)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT16)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT15)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT14)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT13)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT12)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT11)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT10)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT9)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT8)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT7)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT6)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT5)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT4)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT3)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT2)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT1)
+#define BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X1_OUT0_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG2_5X1_OUT1 (0x00001ca0)
+
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT31 0x80000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT31)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT30 0x40000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT30)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT29 0x20000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT29)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT28 0x10000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT28)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT27 0x08000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT27)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT26 0x04000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT26)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT25 0x02000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT25)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT24 0x01000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT24)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT23 0x00800000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT23)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT22 0x00400000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT22)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT21 0x00200000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT21)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT20 0x00100000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT20)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT19 0x00080000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT19)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT18 0x00040000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT18)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT17 0x00020000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT17)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT16 0x00010000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT16)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT15 0x00008000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT15)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT14 0x00004000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT14)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT13 0x00002000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT13)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT12 0x00001000
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT12)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT11 0x00000800
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT11)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT10 0x00000400
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT10)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT9 0x00000200
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT9)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT8 0x00000100
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT8)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT7 0x00000080
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT7)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT6 0x00000040
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT6)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT5 0x00000020
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT5)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT4 0x00000010
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT4)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT3 0x00000008
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT3)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT2 0x00000004
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT2)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT1 0x00000002
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT1)
+#define BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT0 0x00000001
+#define BF_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X1_OUT1_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG2_5X1_OUT2 (0x00001cb0)
+
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT31 0x80000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT31)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT30 0x40000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT30)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT29 0x20000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT29)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT28 0x10000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT28)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT27 0x08000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT27)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT26 0x04000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT26)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT25 0x02000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT25)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT24 0x01000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT24)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT23 0x00800000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT23)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT22 0x00400000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT22)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT21 0x00200000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT21)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT20 0x00100000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT20)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT19 0x00080000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT19)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT18 0x00040000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT18)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT17 0x00020000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT17)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT16 0x00010000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT16)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT15 0x00008000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT15)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT14 0x00004000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT14)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT13 0x00002000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT13)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT12 0x00001000
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT12)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT11 0x00000800
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT11)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT10 0x00000400
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT10)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT9 0x00000200
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT9)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT8 0x00000100
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT8)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT7 0x00000080
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT7)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT6 0x00000040
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT6)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT5 0x00000020
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT5)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT4 0x00000010
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT4)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT3 0x00000008
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT3)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT2 0x00000004
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT2)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT1 0x00000002
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT1)
+#define BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT0 0x00000001
+#define BF_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X1_OUT2_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG2_5X1_OUT3 (0x00001cc0)
+
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT31 0x80000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT31)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT30 0x40000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT30)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT29 0x20000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT29)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT28 0x10000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT28)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT27 0x08000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT27)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT26 0x04000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT26)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT25 0x02000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT25)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT24 0x01000000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT24)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT23 0x00800000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT23)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT22 0x00400000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT22)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT21 0x00200000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT21)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT20 0x00100000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT20)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT19 0x00080000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT19)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT18 0x00040000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT18)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT17 0x00020000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT17)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT16 0x00010000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT16)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT15 0x00008000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT15)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT14 0x00004000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT14)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT13 0x00002000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT13)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT12 0x00001000
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT12)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT11 0x00000800
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT11)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT10 0x00000400
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT10)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT9 0x00000200
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT9)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT8 0x00000100
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT8)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT7 0x00000080
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT7)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT6 0x00000040
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT6)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT5 0x00000020
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT5)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT4 0x00000010
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT4)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT3 0x00000008
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT3)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT2 0x00000004
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT2)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT1 0x00000002
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT1)
+#define BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT0 0x00000001
+#define BF_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X1_OUT3_LUTOUT0)
+
+#define HW_PXP_WFE_A_STG2_5X1_MASKS (0x00001cd0)
+
+#define BP_PXP_WFE_A_STG2_5X1_MASKS_RSVD3 29
+#define BM_PXP_WFE_A_STG2_5X1_MASKS_RSVD3 0xE0000000
+#define BF_PXP_WFE_A_STG2_5X1_MASKS_RSVD3(v) \
+ (((v) << 29) & BM_PXP_WFE_A_STG2_5X1_MASKS_RSVD3)
+#define BP_PXP_WFE_A_STG2_5X1_MASKS_MASK3 24
+#define BM_PXP_WFE_A_STG2_5X1_MASKS_MASK3 0x1F000000
+#define BF_PXP_WFE_A_STG2_5X1_MASKS_MASK3(v) \
+ (((v) << 24) & BM_PXP_WFE_A_STG2_5X1_MASKS_MASK3)
+#define BP_PXP_WFE_A_STG2_5X1_MASKS_RSVD2 21
+#define BM_PXP_WFE_A_STG2_5X1_MASKS_RSVD2 0x00E00000
+#define BF_PXP_WFE_A_STG2_5X1_MASKS_RSVD2(v) \
+ (((v) << 21) & BM_PXP_WFE_A_STG2_5X1_MASKS_RSVD2)
+#define BP_PXP_WFE_A_STG2_5X1_MASKS_MASK2 16
+#define BM_PXP_WFE_A_STG2_5X1_MASKS_MASK2 0x001F0000
+#define BF_PXP_WFE_A_STG2_5X1_MASKS_MASK2(v) \
+ (((v) << 16) & BM_PXP_WFE_A_STG2_5X1_MASKS_MASK2)
+#define BP_PXP_WFE_A_STG2_5X1_MASKS_RSVD1 13
+#define BM_PXP_WFE_A_STG2_5X1_MASKS_RSVD1 0x0000E000
+#define BF_PXP_WFE_A_STG2_5X1_MASKS_RSVD1(v) \
+ (((v) << 13) & BM_PXP_WFE_A_STG2_5X1_MASKS_RSVD1)
+#define BP_PXP_WFE_A_STG2_5X1_MASKS_MASK1 8
+#define BM_PXP_WFE_A_STG2_5X1_MASKS_MASK1 0x00001F00
+#define BF_PXP_WFE_A_STG2_5X1_MASKS_MASK1(v) \
+ (((v) << 8) & BM_PXP_WFE_A_STG2_5X1_MASKS_MASK1)
+#define BP_PXP_WFE_A_STG2_5X1_MASKS_RSVD0 5
+#define BM_PXP_WFE_A_STG2_5X1_MASKS_RSVD0 0x000000E0
+#define BF_PXP_WFE_A_STG2_5X1_MASKS_RSVD0(v) \
+ (((v) << 5) & BM_PXP_WFE_A_STG2_5X1_MASKS_RSVD0)
+#define BP_PXP_WFE_A_STG2_5X1_MASKS_MASK0 0
+#define BM_PXP_WFE_A_STG2_5X1_MASKS_MASK0 0x0000001F
+#define BF_PXP_WFE_A_STG2_5X1_MASKS_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_A_STG2_5X1_MASKS_MASK0)
+
+#define HW_PXP_WFE_B_CTRL (0x00001d00)
+#define HW_PXP_WFE_B_CTRL_SET (0x00001d04)
+#define HW_PXP_WFE_B_CTRL_CLR (0x00001d08)
+#define HW_PXP_WFE_B_CTRL_TOG (0x00001d0c)
+
+#define BM_PXP_WFE_B_CTRL_DONE 0x80000000
+#define BF_PXP_WFE_B_CTRL_DONE(v) \
+ (((v) << 31) & BM_PXP_WFE_B_CTRL_DONE)
+#define BP_PXP_WFE_B_CTRL_RSVD0 3
+#define BM_PXP_WFE_B_CTRL_RSVD0 0x7FFFFFF8
+#define BF_PXP_WFE_B_CTRL_RSVD0(v) \
+ (((v) << 3) & BM_PXP_WFE_B_CTRL_RSVD0)
+#define BM_PXP_WFE_B_CTRL_SW_RESET 0x00000004
+#define BF_PXP_WFE_B_CTRL_SW_RESET(v) \
+ (((v) << 2) & BM_PXP_WFE_B_CTRL_SW_RESET)
+#define BM_PXP_WFE_B_CTRL_RSVD1 0x00000002
+#define BF_PXP_WFE_B_CTRL_RSVD1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_CTRL_RSVD1)
+#define BM_PXP_WFE_B_CTRL_ENABLE 0x00000001
+#define BF_PXP_WFE_B_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PXP_WFE_B_CTRL_ENABLE)
+#define BV_PXP_WFE_B_CTRL_ENABLE__0 0x0
+#define BV_PXP_WFE_B_CTRL_ENABLE__1 0x1
+
+#define HW_PXP_WFE_B_DIMENSIONS (0x00001d10)
+
+#define BP_PXP_WFE_B_DIMENSIONS_RSVD0 28
+#define BM_PXP_WFE_B_DIMENSIONS_RSVD0 0xF0000000
+#define BF_PXP_WFE_B_DIMENSIONS_RSVD0(v) \
+ (((v) << 28) & BM_PXP_WFE_B_DIMENSIONS_RSVD0)
+#define BP_PXP_WFE_B_DIMENSIONS_HEIGHT 16
+#define BM_PXP_WFE_B_DIMENSIONS_HEIGHT 0x0FFF0000
+#define BF_PXP_WFE_B_DIMENSIONS_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_WFE_B_DIMENSIONS_HEIGHT)
+#define BP_PXP_WFE_B_DIMENSIONS_RSVD1 12
+#define BM_PXP_WFE_B_DIMENSIONS_RSVD1 0x0000F000
+#define BF_PXP_WFE_B_DIMENSIONS_RSVD1(v) \
+ (((v) << 12) & BM_PXP_WFE_B_DIMENSIONS_RSVD1)
+#define BP_PXP_WFE_B_DIMENSIONS_WIDTH 0
+#define BM_PXP_WFE_B_DIMENSIONS_WIDTH 0x00000FFF
+#define BF_PXP_WFE_B_DIMENSIONS_WIDTH(v) \
+ (((v) << 0) & BM_PXP_WFE_B_DIMENSIONS_WIDTH)
+
+#define HW_PXP_WFE_B_OFFSET (0x00001d20)
+
+#define BP_PXP_WFE_B_OFFSET_RSVD0 28
+#define BM_PXP_WFE_B_OFFSET_RSVD0 0xF0000000
+#define BF_PXP_WFE_B_OFFSET_RSVD0(v) \
+ (((v) << 28) & BM_PXP_WFE_B_OFFSET_RSVD0)
+#define BP_PXP_WFE_B_OFFSET_Y_OFFSET 16
+#define BM_PXP_WFE_B_OFFSET_Y_OFFSET 0x0FFF0000
+#define BF_PXP_WFE_B_OFFSET_Y_OFFSET(v) \
+ (((v) << 16) & BM_PXP_WFE_B_OFFSET_Y_OFFSET)
+#define BP_PXP_WFE_B_OFFSET_RSVD1 12
+#define BM_PXP_WFE_B_OFFSET_RSVD1 0x0000F000
+#define BF_PXP_WFE_B_OFFSET_RSVD1(v) \
+ (((v) << 12) & BM_PXP_WFE_B_OFFSET_RSVD1)
+#define BP_PXP_WFE_B_OFFSET_X_OFFSET 0
+#define BM_PXP_WFE_B_OFFSET_X_OFFSET 0x00000FFF
+#define BF_PXP_WFE_B_OFFSET_X_OFFSET(v) \
+ (((v) << 0) & BM_PXP_WFE_B_OFFSET_X_OFFSET)
+
+#define HW_PXP_WFE_B_SW_DATA_REGS (0x00001d30)
+
+#define BP_PXP_WFE_B_SW_DATA_REGS_VAL3 24
+#define BM_PXP_WFE_B_SW_DATA_REGS_VAL3 0xFF000000
+#define BF_PXP_WFE_B_SW_DATA_REGS_VAL3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_SW_DATA_REGS_VAL3)
+#define BP_PXP_WFE_B_SW_DATA_REGS_VAL2 16
+#define BM_PXP_WFE_B_SW_DATA_REGS_VAL2 0x00FF0000
+#define BF_PXP_WFE_B_SW_DATA_REGS_VAL2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_SW_DATA_REGS_VAL2)
+#define BP_PXP_WFE_B_SW_DATA_REGS_VAL1 8
+#define BM_PXP_WFE_B_SW_DATA_REGS_VAL1 0x0000FF00
+#define BF_PXP_WFE_B_SW_DATA_REGS_VAL1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_SW_DATA_REGS_VAL1)
+#define BP_PXP_WFE_B_SW_DATA_REGS_VAL0 0
+#define BM_PXP_WFE_B_SW_DATA_REGS_VAL0 0x000000FF
+#define BF_PXP_WFE_B_SW_DATA_REGS_VAL0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_SW_DATA_REGS_VAL0)
+
+#define HW_PXP_WFE_B_SW_FLAG_REGS (0x00001d40)
+
+#define BP_PXP_WFE_B_SW_FLAG_REGS_RSVD 4
+#define BM_PXP_WFE_B_SW_FLAG_REGS_RSVD 0xFFFFFFF0
+#define BF_PXP_WFE_B_SW_FLAG_REGS_RSVD(v) \
+ (((v) << 4) & BM_PXP_WFE_B_SW_FLAG_REGS_RSVD)
+#define BM_PXP_WFE_B_SW_FLAG_REGS_VAL3 0x00000008
+#define BF_PXP_WFE_B_SW_FLAG_REGS_VAL3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_SW_FLAG_REGS_VAL3)
+#define BM_PXP_WFE_B_SW_FLAG_REGS_VAL2 0x00000004
+#define BF_PXP_WFE_B_SW_FLAG_REGS_VAL2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_SW_FLAG_REGS_VAL2)
+#define BM_PXP_WFE_B_SW_FLAG_REGS_VAL1 0x00000002
+#define BF_PXP_WFE_B_SW_FLAG_REGS_VAL1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_SW_FLAG_REGS_VAL1)
+#define BM_PXP_WFE_B_SW_FLAG_REGS_VAL0 0x00000001
+#define BF_PXP_WFE_B_SW_FLAG_REGS_VAL0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_SW_FLAG_REGS_VAL0)
+
+#define HW_PXP_WFE_B_STAGE1_MUX0 (0x00001d50)
+#define HW_PXP_WFE_B_STAGE1_MUX0_SET (0x00001d54)
+#define HW_PXP_WFE_B_STAGE1_MUX0_CLR (0x00001d58)
+#define HW_PXP_WFE_B_STAGE1_MUX0_TOG (0x00001d5c)
+
+#define BP_PXP_WFE_B_STAGE1_MUX0_RSVD0 30
+#define BM_PXP_WFE_B_STAGE1_MUX0_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE1_MUX0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE1_MUX0_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX0_MUX3 24
+#define BM_PXP_WFE_B_STAGE1_MUX0_MUX3 0x3F000000
+#define BF_PXP_WFE_B_STAGE1_MUX0_MUX3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE1_MUX0_MUX3)
+#define BP_PXP_WFE_B_STAGE1_MUX0_RSVD1 22
+#define BM_PXP_WFE_B_STAGE1_MUX0_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE1_MUX0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE1_MUX0_RSVD1)
+#define BP_PXP_WFE_B_STAGE1_MUX0_MUX2 16
+#define BM_PXP_WFE_B_STAGE1_MUX0_MUX2 0x003F0000
+#define BF_PXP_WFE_B_STAGE1_MUX0_MUX2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE1_MUX0_MUX2)
+#define BP_PXP_WFE_B_STAGE1_MUX0_RSVD2 14
+#define BM_PXP_WFE_B_STAGE1_MUX0_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE1_MUX0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE1_MUX0_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_MUX0_MUX1 8
+#define BM_PXP_WFE_B_STAGE1_MUX0_MUX1 0x00003F00
+#define BF_PXP_WFE_B_STAGE1_MUX0_MUX1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_MUX0_MUX1)
+#define BP_PXP_WFE_B_STAGE1_MUX0_RSVD3 6
+#define BM_PXP_WFE_B_STAGE1_MUX0_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE1_MUX0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX0_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_MUX0_MUX0 0
+#define BM_PXP_WFE_B_STAGE1_MUX0_MUX0 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX0_MUX0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX0_MUX0)
+
+#define HW_PXP_WFE_B_STAGE1_MUX1 (0x00001d60)
+#define HW_PXP_WFE_B_STAGE1_MUX1_SET (0x00001d64)
+#define HW_PXP_WFE_B_STAGE1_MUX1_CLR (0x00001d68)
+#define HW_PXP_WFE_B_STAGE1_MUX1_TOG (0x00001d6c)
+
+#define BP_PXP_WFE_B_STAGE1_MUX1_RSVD0 30
+#define BM_PXP_WFE_B_STAGE1_MUX1_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE1_MUX1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE1_MUX1_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX1_MUX7 24
+#define BM_PXP_WFE_B_STAGE1_MUX1_MUX7 0x3F000000
+#define BF_PXP_WFE_B_STAGE1_MUX1_MUX7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE1_MUX1_MUX7)
+#define BP_PXP_WFE_B_STAGE1_MUX1_RSVD1 22
+#define BM_PXP_WFE_B_STAGE1_MUX1_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE1_MUX1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE1_MUX1_RSVD1)
+#define BP_PXP_WFE_B_STAGE1_MUX1_MUX6 16
+#define BM_PXP_WFE_B_STAGE1_MUX1_MUX6 0x003F0000
+#define BF_PXP_WFE_B_STAGE1_MUX1_MUX6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE1_MUX1_MUX6)
+#define BP_PXP_WFE_B_STAGE1_MUX1_RSVD2 14
+#define BM_PXP_WFE_B_STAGE1_MUX1_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE1_MUX1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE1_MUX1_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_MUX1_MUX5 8
+#define BM_PXP_WFE_B_STAGE1_MUX1_MUX5 0x00003F00
+#define BF_PXP_WFE_B_STAGE1_MUX1_MUX5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_MUX1_MUX5)
+#define BP_PXP_WFE_B_STAGE1_MUX1_RSVD3 6
+#define BM_PXP_WFE_B_STAGE1_MUX1_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE1_MUX1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX1_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_MUX1_MUX4 0
+#define BM_PXP_WFE_B_STAGE1_MUX1_MUX4 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX1_MUX4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX1_MUX4)
+
+#define HW_PXP_WFE_B_STAGE1_MUX2 (0x00001d70)
+#define HW_PXP_WFE_B_STAGE1_MUX2_SET (0x00001d74)
+#define HW_PXP_WFE_B_STAGE1_MUX2_CLR (0x00001d78)
+#define HW_PXP_WFE_B_STAGE1_MUX2_TOG (0x00001d7c)
+
+#define BP_PXP_WFE_B_STAGE1_MUX2_RSVD0 30
+#define BM_PXP_WFE_B_STAGE1_MUX2_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE1_MUX2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE1_MUX2_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX2_MUX11 24
+#define BM_PXP_WFE_B_STAGE1_MUX2_MUX11 0x3F000000
+#define BF_PXP_WFE_B_STAGE1_MUX2_MUX11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE1_MUX2_MUX11)
+#define BP_PXP_WFE_B_STAGE1_MUX2_RSVD1 22
+#define BM_PXP_WFE_B_STAGE1_MUX2_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE1_MUX2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE1_MUX2_RSVD1)
+#define BP_PXP_WFE_B_STAGE1_MUX2_MUX10 16
+#define BM_PXP_WFE_B_STAGE1_MUX2_MUX10 0x003F0000
+#define BF_PXP_WFE_B_STAGE1_MUX2_MUX10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE1_MUX2_MUX10)
+#define BP_PXP_WFE_B_STAGE1_MUX2_RSVD2 14
+#define BM_PXP_WFE_B_STAGE1_MUX2_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE1_MUX2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE1_MUX2_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_MUX2_MUX9 8
+#define BM_PXP_WFE_B_STAGE1_MUX2_MUX9 0x00003F00
+#define BF_PXP_WFE_B_STAGE1_MUX2_MUX9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_MUX2_MUX9)
+#define BP_PXP_WFE_B_STAGE1_MUX2_RSVD3 6
+#define BM_PXP_WFE_B_STAGE1_MUX2_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE1_MUX2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX2_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_MUX2_MUX8 0
+#define BM_PXP_WFE_B_STAGE1_MUX2_MUX8 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX2_MUX8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX2_MUX8)
+
+#define HW_PXP_WFE_B_STAGE1_MUX3 (0x00001d80)
+#define HW_PXP_WFE_B_STAGE1_MUX3_SET (0x00001d84)
+#define HW_PXP_WFE_B_STAGE1_MUX3_CLR (0x00001d88)
+#define HW_PXP_WFE_B_STAGE1_MUX3_TOG (0x00001d8c)
+
+#define BP_PXP_WFE_B_STAGE1_MUX3_RSVD0 30
+#define BM_PXP_WFE_B_STAGE1_MUX3_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE1_MUX3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE1_MUX3_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX3_MUX15 24
+#define BM_PXP_WFE_B_STAGE1_MUX3_MUX15 0x3F000000
+#define BF_PXP_WFE_B_STAGE1_MUX3_MUX15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE1_MUX3_MUX15)
+#define BP_PXP_WFE_B_STAGE1_MUX3_RSVD1 22
+#define BM_PXP_WFE_B_STAGE1_MUX3_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE1_MUX3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE1_MUX3_RSVD1)
+#define BP_PXP_WFE_B_STAGE1_MUX3_MUX14 16
+#define BM_PXP_WFE_B_STAGE1_MUX3_MUX14 0x003F0000
+#define BF_PXP_WFE_B_STAGE1_MUX3_MUX14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE1_MUX3_MUX14)
+#define BP_PXP_WFE_B_STAGE1_MUX3_RSVD2 14
+#define BM_PXP_WFE_B_STAGE1_MUX3_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE1_MUX3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE1_MUX3_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_MUX3_MUX13 8
+#define BM_PXP_WFE_B_STAGE1_MUX3_MUX13 0x00003F00
+#define BF_PXP_WFE_B_STAGE1_MUX3_MUX13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_MUX3_MUX13)
+#define BP_PXP_WFE_B_STAGE1_MUX3_RSVD3 6
+#define BM_PXP_WFE_B_STAGE1_MUX3_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE1_MUX3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX3_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_MUX3_MUX12 0
+#define BM_PXP_WFE_B_STAGE1_MUX3_MUX12 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX3_MUX12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX3_MUX12)
+
+#define HW_PXP_WFE_B_STAGE1_MUX4 (0x00001d90)
+#define HW_PXP_WFE_B_STAGE1_MUX4_SET (0x00001d94)
+#define HW_PXP_WFE_B_STAGE1_MUX4_CLR (0x00001d98)
+#define HW_PXP_WFE_B_STAGE1_MUX4_TOG (0x00001d9c)
+
+#define BP_PXP_WFE_B_STAGE1_MUX4_RSVD0 30
+#define BM_PXP_WFE_B_STAGE1_MUX4_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE1_MUX4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE1_MUX4_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX4_MUX19 24
+#define BM_PXP_WFE_B_STAGE1_MUX4_MUX19 0x3F000000
+#define BF_PXP_WFE_B_STAGE1_MUX4_MUX19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE1_MUX4_MUX19)
+#define BP_PXP_WFE_B_STAGE1_MUX4_RSVD1 22
+#define BM_PXP_WFE_B_STAGE1_MUX4_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE1_MUX4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE1_MUX4_RSVD1)
+#define BP_PXP_WFE_B_STAGE1_MUX4_MUX18 16
+#define BM_PXP_WFE_B_STAGE1_MUX4_MUX18 0x003F0000
+#define BF_PXP_WFE_B_STAGE1_MUX4_MUX18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE1_MUX4_MUX18)
+#define BP_PXP_WFE_B_STAGE1_MUX4_RSVD2 14
+#define BM_PXP_WFE_B_STAGE1_MUX4_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE1_MUX4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE1_MUX4_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_MUX4_MUX17 8
+#define BM_PXP_WFE_B_STAGE1_MUX4_MUX17 0x00003F00
+#define BF_PXP_WFE_B_STAGE1_MUX4_MUX17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_MUX4_MUX17)
+#define BP_PXP_WFE_B_STAGE1_MUX4_RSVD3 6
+#define BM_PXP_WFE_B_STAGE1_MUX4_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE1_MUX4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX4_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_MUX4_MUX16 0
+#define BM_PXP_WFE_B_STAGE1_MUX4_MUX16 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX4_MUX16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX4_MUX16)
+
+#define HW_PXP_WFE_B_STAGE1_MUX5 (0x00001da0)
+#define HW_PXP_WFE_B_STAGE1_MUX5_SET (0x00001da4)
+#define HW_PXP_WFE_B_STAGE1_MUX5_CLR (0x00001da8)
+#define HW_PXP_WFE_B_STAGE1_MUX5_TOG (0x00001dac)
+
+#define BP_PXP_WFE_B_STAGE1_MUX5_RSVD0 30
+#define BM_PXP_WFE_B_STAGE1_MUX5_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE1_MUX5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE1_MUX5_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX5_MUX23 24
+#define BM_PXP_WFE_B_STAGE1_MUX5_MUX23 0x3F000000
+#define BF_PXP_WFE_B_STAGE1_MUX5_MUX23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE1_MUX5_MUX23)
+#define BP_PXP_WFE_B_STAGE1_MUX5_RSVD1 22
+#define BM_PXP_WFE_B_STAGE1_MUX5_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE1_MUX5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE1_MUX5_RSVD1)
+#define BP_PXP_WFE_B_STAGE1_MUX5_MUX22 16
+#define BM_PXP_WFE_B_STAGE1_MUX5_MUX22 0x003F0000
+#define BF_PXP_WFE_B_STAGE1_MUX5_MUX22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE1_MUX5_MUX22)
+#define BP_PXP_WFE_B_STAGE1_MUX5_RSVD2 14
+#define BM_PXP_WFE_B_STAGE1_MUX5_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE1_MUX5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE1_MUX5_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_MUX5_MUX21 8
+#define BM_PXP_WFE_B_STAGE1_MUX5_MUX21 0x00003F00
+#define BF_PXP_WFE_B_STAGE1_MUX5_MUX21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_MUX5_MUX21)
+#define BP_PXP_WFE_B_STAGE1_MUX5_RSVD3 6
+#define BM_PXP_WFE_B_STAGE1_MUX5_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE1_MUX5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX5_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_MUX5_MUX20 0
+#define BM_PXP_WFE_B_STAGE1_MUX5_MUX20 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX5_MUX20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX5_MUX20)
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__INC 0x0
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__DEC 0x1
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__ADD 0x2
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__MINUS 0x3
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__AND 0x4
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__OR 0x5
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__XOR 0x6
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__SHIFTLEFT 0x7
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__SHIFTRIGHT 0x8
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__BIT_AND 0x9
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__BIT_OR 0xa
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__BIT_CMP 0xb
+#define BV_PXP_WFE_B_STAGE1_MUX5_MUX20__NOP 0xc
+
+#define HW_PXP_WFE_B_STAGE1_MUX6 (0x00001db0)
+#define HW_PXP_WFE_B_STAGE1_MUX6_SET (0x00001db4)
+#define HW_PXP_WFE_B_STAGE1_MUX6_CLR (0x00001db8)
+#define HW_PXP_WFE_B_STAGE1_MUX6_TOG (0x00001dbc)
+
+#define BP_PXP_WFE_B_STAGE1_MUX6_RSVD0 30
+#define BM_PXP_WFE_B_STAGE1_MUX6_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE1_MUX6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE1_MUX6_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX6_MUX27 24
+#define BM_PXP_WFE_B_STAGE1_MUX6_MUX27 0x3F000000
+#define BF_PXP_WFE_B_STAGE1_MUX6_MUX27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE1_MUX6_MUX27)
+#define BP_PXP_WFE_B_STAGE1_MUX6_RSVD1 22
+#define BM_PXP_WFE_B_STAGE1_MUX6_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE1_MUX6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE1_MUX6_RSVD1)
+#define BP_PXP_WFE_B_STAGE1_MUX6_MUX26 16
+#define BM_PXP_WFE_B_STAGE1_MUX6_MUX26 0x003F0000
+#define BF_PXP_WFE_B_STAGE1_MUX6_MUX26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE1_MUX6_MUX26)
+#define BP_PXP_WFE_B_STAGE1_MUX6_RSVD2 14
+#define BM_PXP_WFE_B_STAGE1_MUX6_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE1_MUX6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE1_MUX6_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_MUX6_MUX25 8
+#define BM_PXP_WFE_B_STAGE1_MUX6_MUX25 0x00003F00
+#define BF_PXP_WFE_B_STAGE1_MUX6_MUX25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_MUX6_MUX25)
+#define BP_PXP_WFE_B_STAGE1_MUX6_RSVD3 6
+#define BM_PXP_WFE_B_STAGE1_MUX6_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE1_MUX6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX6_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_MUX6_MUX24 0
+#define BM_PXP_WFE_B_STAGE1_MUX6_MUX24 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX6_MUX24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX6_MUX24)
+
+#define HW_PXP_WFE_B_STAGE1_MUX7 (0x00001dc0)
+#define HW_PXP_WFE_B_STAGE1_MUX7_SET (0x00001dc4)
+#define HW_PXP_WFE_B_STAGE1_MUX7_CLR (0x00001dc8)
+#define HW_PXP_WFE_B_STAGE1_MUX7_TOG (0x00001dcc)
+
+#define BP_PXP_WFE_B_STAGE1_MUX7_RSVD0 30
+#define BM_PXP_WFE_B_STAGE1_MUX7_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE1_MUX7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE1_MUX7_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX7_MUX31 24
+#define BM_PXP_WFE_B_STAGE1_MUX7_MUX31 0x3F000000
+#define BF_PXP_WFE_B_STAGE1_MUX7_MUX31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE1_MUX7_MUX31)
+#define BP_PXP_WFE_B_STAGE1_MUX7_RSVD1 22
+#define BM_PXP_WFE_B_STAGE1_MUX7_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE1_MUX7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE1_MUX7_RSVD1)
+#define BP_PXP_WFE_B_STAGE1_MUX7_MUX30 16
+#define BM_PXP_WFE_B_STAGE1_MUX7_MUX30 0x003F0000
+#define BF_PXP_WFE_B_STAGE1_MUX7_MUX30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE1_MUX7_MUX30)
+#define BP_PXP_WFE_B_STAGE1_MUX7_RSVD2 14
+#define BM_PXP_WFE_B_STAGE1_MUX7_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE1_MUX7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE1_MUX7_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_MUX7_MUX29 8
+#define BM_PXP_WFE_B_STAGE1_MUX7_MUX29 0x00003F00
+#define BF_PXP_WFE_B_STAGE1_MUX7_MUX29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_MUX7_MUX29)
+#define BP_PXP_WFE_B_STAGE1_MUX7_RSVD3 6
+#define BM_PXP_WFE_B_STAGE1_MUX7_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE1_MUX7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX7_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_MUX7_MUX28 0
+#define BM_PXP_WFE_B_STAGE1_MUX7_MUX28 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX7_MUX28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX7_MUX28)
+
+#define HW_PXP_WFE_B_STAGE1_MUX8 (0x00001dd0)
+#define HW_PXP_WFE_B_STAGE1_MUX8_SET (0x00001dd4)
+#define HW_PXP_WFE_B_STAGE1_MUX8_CLR (0x00001dd8)
+#define HW_PXP_WFE_B_STAGE1_MUX8_TOG (0x00001ddc)
+
+#define BP_PXP_WFE_B_STAGE1_MUX8_RSVD0 6
+#define BM_PXP_WFE_B_STAGE1_MUX8_RSVD0 0xFFFFFFC0
+#define BF_PXP_WFE_B_STAGE1_MUX8_RSVD0(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE1_MUX8_RSVD0)
+#define BP_PXP_WFE_B_STAGE1_MUX8_MUX32 0
+#define BM_PXP_WFE_B_STAGE1_MUX8_MUX32 0x0000003F
+#define BF_PXP_WFE_B_STAGE1_MUX8_MUX32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_MUX8_MUX32)
+
+#define HW_PXP_WFE_B_STAGE2_MUX0 (0x00001de0)
+#define HW_PXP_WFE_B_STAGE2_MUX0_SET (0x00001de4)
+#define HW_PXP_WFE_B_STAGE2_MUX0_CLR (0x00001de8)
+#define HW_PXP_WFE_B_STAGE2_MUX0_TOG (0x00001dec)
+
+#define BP_PXP_WFE_B_STAGE2_MUX0_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX0_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX0_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX0_MUX3 24
+#define BM_PXP_WFE_B_STAGE2_MUX0_MUX3 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX0_MUX3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX0_MUX3)
+#define BP_PXP_WFE_B_STAGE2_MUX0_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX0_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX0_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX0_MUX2 16
+#define BM_PXP_WFE_B_STAGE2_MUX0_MUX2 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX0_MUX2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX0_MUX2)
+#define BP_PXP_WFE_B_STAGE2_MUX0_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX0_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX0_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX0_MUX1 8
+#define BM_PXP_WFE_B_STAGE2_MUX0_MUX1 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX0_MUX1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX0_MUX1)
+#define BP_PXP_WFE_B_STAGE2_MUX0_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX0_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX0_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX0_MUX0 0
+#define BM_PXP_WFE_B_STAGE2_MUX0_MUX0 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX0_MUX0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX0_MUX0)
+
+#define HW_PXP_WFE_B_STAGE2_MUX1 (0x00001df0)
+#define HW_PXP_WFE_B_STAGE2_MUX1_SET (0x00001df4)
+#define HW_PXP_WFE_B_STAGE2_MUX1_CLR (0x00001df8)
+#define HW_PXP_WFE_B_STAGE2_MUX1_TOG (0x00001dfc)
+
+#define BP_PXP_WFE_B_STAGE2_MUX1_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX1_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX1_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX1_MUX7 24
+#define BM_PXP_WFE_B_STAGE2_MUX1_MUX7 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX1_MUX7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX1_MUX7)
+#define BP_PXP_WFE_B_STAGE2_MUX1_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX1_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX1_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX1_MUX6 16
+#define BM_PXP_WFE_B_STAGE2_MUX1_MUX6 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX1_MUX6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX1_MUX6)
+#define BP_PXP_WFE_B_STAGE2_MUX1_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX1_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX1_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX1_MUX5 8
+#define BM_PXP_WFE_B_STAGE2_MUX1_MUX5 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX1_MUX5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX1_MUX5)
+#define BP_PXP_WFE_B_STAGE2_MUX1_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX1_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX1_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX1_MUX4 0
+#define BM_PXP_WFE_B_STAGE2_MUX1_MUX4 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX1_MUX4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX1_MUX4)
+
+#define HW_PXP_WFE_B_STAGE2_MUX2 (0x00001e00)
+#define HW_PXP_WFE_B_STAGE2_MUX2_SET (0x00001e04)
+#define HW_PXP_WFE_B_STAGE2_MUX2_CLR (0x00001e08)
+#define HW_PXP_WFE_B_STAGE2_MUX2_TOG (0x00001e0c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX2_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX2_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX2_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX2_MUX11 24
+#define BM_PXP_WFE_B_STAGE2_MUX2_MUX11 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX2_MUX11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX2_MUX11)
+#define BP_PXP_WFE_B_STAGE2_MUX2_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX2_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX2_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX2_MUX10 16
+#define BM_PXP_WFE_B_STAGE2_MUX2_MUX10 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX2_MUX10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX2_MUX10)
+#define BP_PXP_WFE_B_STAGE2_MUX2_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX2_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX2_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX2_MUX9 8
+#define BM_PXP_WFE_B_STAGE2_MUX2_MUX9 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX2_MUX9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX2_MUX9)
+#define BP_PXP_WFE_B_STAGE2_MUX2_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX2_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX2_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX2_MUX8 0
+#define BM_PXP_WFE_B_STAGE2_MUX2_MUX8 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX2_MUX8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX2_MUX8)
+
+#define HW_PXP_WFE_B_STAGE2_MUX3 (0x00001e10)
+#define HW_PXP_WFE_B_STAGE2_MUX3_SET (0x00001e14)
+#define HW_PXP_WFE_B_STAGE2_MUX3_CLR (0x00001e18)
+#define HW_PXP_WFE_B_STAGE2_MUX3_TOG (0x00001e1c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX3_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX3_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX3_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX3_MUX15 24
+#define BM_PXP_WFE_B_STAGE2_MUX3_MUX15 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX3_MUX15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX3_MUX15)
+#define BP_PXP_WFE_B_STAGE2_MUX3_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX3_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX3_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX3_MUX14 16
+#define BM_PXP_WFE_B_STAGE2_MUX3_MUX14 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX3_MUX14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX3_MUX14)
+#define BP_PXP_WFE_B_STAGE2_MUX3_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX3_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX3_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX3_MUX13 8
+#define BM_PXP_WFE_B_STAGE2_MUX3_MUX13 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX3_MUX13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX3_MUX13)
+#define BP_PXP_WFE_B_STAGE2_MUX3_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX3_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX3_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX3_MUX12 0
+#define BM_PXP_WFE_B_STAGE2_MUX3_MUX12 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX3_MUX12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX3_MUX12)
+
+#define HW_PXP_WFE_B_STAGE2_MUX4 (0x00001e20)
+#define HW_PXP_WFE_B_STAGE2_MUX4_SET (0x00001e24)
+#define HW_PXP_WFE_B_STAGE2_MUX4_CLR (0x00001e28)
+#define HW_PXP_WFE_B_STAGE2_MUX4_TOG (0x00001e2c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX4_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX4_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX4_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX4_MUX19 24
+#define BM_PXP_WFE_B_STAGE2_MUX4_MUX19 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX4_MUX19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX4_MUX19)
+#define BP_PXP_WFE_B_STAGE2_MUX4_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX4_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX4_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX4_MUX18 16
+#define BM_PXP_WFE_B_STAGE2_MUX4_MUX18 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX4_MUX18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX4_MUX18)
+#define BP_PXP_WFE_B_STAGE2_MUX4_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX4_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX4_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX4_MUX17 8
+#define BM_PXP_WFE_B_STAGE2_MUX4_MUX17 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX4_MUX17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX4_MUX17)
+#define BP_PXP_WFE_B_STAGE2_MUX4_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX4_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX4_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX4_MUX16 0
+#define BM_PXP_WFE_B_STAGE2_MUX4_MUX16 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX4_MUX16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX4_MUX16)
+
+#define HW_PXP_WFE_B_STAGE2_MUX5 (0x00001e30)
+#define HW_PXP_WFE_B_STAGE2_MUX5_SET (0x00001e34)
+#define HW_PXP_WFE_B_STAGE2_MUX5_CLR (0x00001e38)
+#define HW_PXP_WFE_B_STAGE2_MUX5_TOG (0x00001e3c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX5_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX5_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX5_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX5_MUX23 24
+#define BM_PXP_WFE_B_STAGE2_MUX5_MUX23 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX5_MUX23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX5_MUX23)
+#define BP_PXP_WFE_B_STAGE2_MUX5_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX5_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX5_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX5_MUX22 16
+#define BM_PXP_WFE_B_STAGE2_MUX5_MUX22 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX5_MUX22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX5_MUX22)
+#define BP_PXP_WFE_B_STAGE2_MUX5_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX5_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX5_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX5_MUX21 8
+#define BM_PXP_WFE_B_STAGE2_MUX5_MUX21 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX5_MUX21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX5_MUX21)
+#define BP_PXP_WFE_B_STAGE2_MUX5_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX5_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX5_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX5_MUX20 0
+#define BM_PXP_WFE_B_STAGE2_MUX5_MUX20 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX5_MUX20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX5_MUX20)
+
+#define HW_PXP_WFE_B_STAGE2_MUX6 (0x00001e40)
+#define HW_PXP_WFE_B_STAGE2_MUX6_SET (0x00001e44)
+#define HW_PXP_WFE_B_STAGE2_MUX6_CLR (0x00001e48)
+#define HW_PXP_WFE_B_STAGE2_MUX6_TOG (0x00001e4c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX6_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX6_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX6_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX6_MUX27 24
+#define BM_PXP_WFE_B_STAGE2_MUX6_MUX27 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX6_MUX27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX6_MUX27)
+#define BP_PXP_WFE_B_STAGE2_MUX6_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX6_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX6_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX6_MUX26 16
+#define BM_PXP_WFE_B_STAGE2_MUX6_MUX26 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX6_MUX26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX6_MUX26)
+#define BP_PXP_WFE_B_STAGE2_MUX6_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX6_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX6_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX6_MUX25 8
+#define BM_PXP_WFE_B_STAGE2_MUX6_MUX25 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX6_MUX25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX6_MUX25)
+#define BP_PXP_WFE_B_STAGE2_MUX6_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX6_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX6_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX6_MUX24 0
+#define BM_PXP_WFE_B_STAGE2_MUX6_MUX24 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX6_MUX24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX6_MUX24)
+
+#define HW_PXP_WFE_B_STAGE2_MUX7 (0x00001e50)
+#define HW_PXP_WFE_B_STAGE2_MUX7_SET (0x00001e54)
+#define HW_PXP_WFE_B_STAGE2_MUX7_CLR (0x00001e58)
+#define HW_PXP_WFE_B_STAGE2_MUX7_TOG (0x00001e5c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX7_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX7_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX7_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX7_MUX31 24
+#define BM_PXP_WFE_B_STAGE2_MUX7_MUX31 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX7_MUX31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX7_MUX31)
+#define BP_PXP_WFE_B_STAGE2_MUX7_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX7_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX7_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX7_MUX30 16
+#define BM_PXP_WFE_B_STAGE2_MUX7_MUX30 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX7_MUX30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX7_MUX30)
+#define BP_PXP_WFE_B_STAGE2_MUX7_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX7_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX7_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX7_MUX29 8
+#define BM_PXP_WFE_B_STAGE2_MUX7_MUX29 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX7_MUX29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX7_MUX29)
+#define BP_PXP_WFE_B_STAGE2_MUX7_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX7_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX7_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX7_MUX28 0
+#define BM_PXP_WFE_B_STAGE2_MUX7_MUX28 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX7_MUX28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX7_MUX28)
+
+#define HW_PXP_WFE_B_STAGE2_MUX8 (0x00001e60)
+#define HW_PXP_WFE_B_STAGE2_MUX8_SET (0x00001e64)
+#define HW_PXP_WFE_B_STAGE2_MUX8_CLR (0x00001e68)
+#define HW_PXP_WFE_B_STAGE2_MUX8_TOG (0x00001e6c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX8_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX8_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX8_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX8_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX8_MUX35 24
+#define BM_PXP_WFE_B_STAGE2_MUX8_MUX35 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX8_MUX35(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX8_MUX35)
+#define BP_PXP_WFE_B_STAGE2_MUX8_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX8_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX8_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX8_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX8_MUX34 16
+#define BM_PXP_WFE_B_STAGE2_MUX8_MUX34 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX8_MUX34(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX8_MUX34)
+#define BP_PXP_WFE_B_STAGE2_MUX8_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX8_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX8_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX8_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX8_MUX33 8
+#define BM_PXP_WFE_B_STAGE2_MUX8_MUX33 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX8_MUX33(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX8_MUX33)
+#define BP_PXP_WFE_B_STAGE2_MUX8_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX8_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX8_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX8_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX8_MUX32 0
+#define BM_PXP_WFE_B_STAGE2_MUX8_MUX32 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX8_MUX32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX8_MUX32)
+
+#define HW_PXP_WFE_B_STAGE2_MUX9 (0x00001e70)
+#define HW_PXP_WFE_B_STAGE2_MUX9_SET (0x00001e74)
+#define HW_PXP_WFE_B_STAGE2_MUX9_CLR (0x00001e78)
+#define HW_PXP_WFE_B_STAGE2_MUX9_TOG (0x00001e7c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX9_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX9_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX9_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX9_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX9_MUX39 24
+#define BM_PXP_WFE_B_STAGE2_MUX9_MUX39 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX9_MUX39(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX9_MUX39)
+#define BP_PXP_WFE_B_STAGE2_MUX9_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX9_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX9_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX9_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX9_MUX38 16
+#define BM_PXP_WFE_B_STAGE2_MUX9_MUX38 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX9_MUX38(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX9_MUX38)
+#define BP_PXP_WFE_B_STAGE2_MUX9_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX9_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX9_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX9_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX9_MUX37 8
+#define BM_PXP_WFE_B_STAGE2_MUX9_MUX37 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX9_MUX37(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX9_MUX37)
+#define BP_PXP_WFE_B_STAGE2_MUX9_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX9_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX9_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX9_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX9_MUX36 0
+#define BM_PXP_WFE_B_STAGE2_MUX9_MUX36 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX9_MUX36(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX9_MUX36)
+
+#define HW_PXP_WFE_B_STAGE2_MUX10 (0x00001e80)
+#define HW_PXP_WFE_B_STAGE2_MUX10_SET (0x00001e84)
+#define HW_PXP_WFE_B_STAGE2_MUX10_CLR (0x00001e88)
+#define HW_PXP_WFE_B_STAGE2_MUX10_TOG (0x00001e8c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX10_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX10_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX10_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX10_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX10_MUX43 24
+#define BM_PXP_WFE_B_STAGE2_MUX10_MUX43 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX10_MUX43(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX10_MUX43)
+#define BP_PXP_WFE_B_STAGE2_MUX10_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX10_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX10_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX10_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX10_MUX42 16
+#define BM_PXP_WFE_B_STAGE2_MUX10_MUX42 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX10_MUX42(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX10_MUX42)
+#define BP_PXP_WFE_B_STAGE2_MUX10_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX10_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX10_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX10_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX10_MUX41 8
+#define BM_PXP_WFE_B_STAGE2_MUX10_MUX41 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX10_MUX41(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX10_MUX41)
+#define BP_PXP_WFE_B_STAGE2_MUX10_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX10_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX10_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX10_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX10_MUX40 0
+#define BM_PXP_WFE_B_STAGE2_MUX10_MUX40 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX10_MUX40(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX10_MUX40)
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__INC 0x0
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__DEC 0x1
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__ADD 0x2
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__MINUS 0x3
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__AND 0x4
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__OR 0x5
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__XOR 0x6
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__SHIFTLEFT 0x7
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__SHIFTRIGHT 0x8
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__BIT_AND 0x9
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__BIT_OR 0xa
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__BIT_CMP 0xb
+#define BV_PXP_WFE_B_STAGE2_MUX10_MUX40__NOP 0xc
+
+#define HW_PXP_WFE_B_STAGE2_MUX11 (0x00001e90)
+#define HW_PXP_WFE_B_STAGE2_MUX11_SET (0x00001e94)
+#define HW_PXP_WFE_B_STAGE2_MUX11_CLR (0x00001e98)
+#define HW_PXP_WFE_B_STAGE2_MUX11_TOG (0x00001e9c)
+
+#define BP_PXP_WFE_B_STAGE2_MUX11_RSVD0 30
+#define BM_PXP_WFE_B_STAGE2_MUX11_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_MUX11_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_MUX11_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX11_MUX47 24
+#define BM_PXP_WFE_B_STAGE2_MUX11_MUX47 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_MUX11_MUX47(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_MUX11_MUX47)
+#define BP_PXP_WFE_B_STAGE2_MUX11_RSVD1 22
+#define BM_PXP_WFE_B_STAGE2_MUX11_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_MUX11_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_MUX11_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_MUX11_MUX46 16
+#define BM_PXP_WFE_B_STAGE2_MUX11_MUX46 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_MUX11_MUX46(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_MUX11_MUX46)
+#define BP_PXP_WFE_B_STAGE2_MUX11_RSVD2 14
+#define BM_PXP_WFE_B_STAGE2_MUX11_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_MUX11_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_MUX11_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_MUX11_MUX45 8
+#define BM_PXP_WFE_B_STAGE2_MUX11_MUX45 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_MUX11_MUX45(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_MUX11_MUX45)
+#define BP_PXP_WFE_B_STAGE2_MUX11_RSVD3 6
+#define BM_PXP_WFE_B_STAGE2_MUX11_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_MUX11_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX11_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_MUX11_MUX44 0
+#define BM_PXP_WFE_B_STAGE2_MUX11_MUX44 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX11_MUX44(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX11_MUX44)
+
+#define HW_PXP_WFE_B_STAGE2_MUX12 (0x00001ea0)
+#define HW_PXP_WFE_B_STAGE2_MUX12_SET (0x00001ea4)
+#define HW_PXP_WFE_B_STAGE2_MUX12_CLR (0x00001ea8)
+#define HW_PXP_WFE_B_STAGE2_MUX12_TOG (0x00001eac)
+
+#define BP_PXP_WFE_B_STAGE2_MUX12_RSVD0 6
+#define BM_PXP_WFE_B_STAGE2_MUX12_RSVD0 0xFFFFFFC0
+#define BF_PXP_WFE_B_STAGE2_MUX12_RSVD0(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_MUX12_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_MUX12_MUX48 0
+#define BM_PXP_WFE_B_STAGE2_MUX12_MUX48 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_MUX12_MUX48(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_MUX12_MUX48)
+
+#define HW_PXP_WFE_B_STAGE3_MUX0 (0x00001eb0)
+#define HW_PXP_WFE_B_STAGE3_MUX0_SET (0x00001eb4)
+#define HW_PXP_WFE_B_STAGE3_MUX0_CLR (0x00001eb8)
+#define HW_PXP_WFE_B_STAGE3_MUX0_TOG (0x00001ebc)
+
+#define BP_PXP_WFE_B_STAGE3_MUX0_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX0_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX0_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX0_MUX3 24
+#define BM_PXP_WFE_B_STAGE3_MUX0_MUX3 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX0_MUX3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX0_MUX3)
+#define BP_PXP_WFE_B_STAGE3_MUX0_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX0_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX0_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX0_MUX2 16
+#define BM_PXP_WFE_B_STAGE3_MUX0_MUX2 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX0_MUX2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX0_MUX2)
+#define BP_PXP_WFE_B_STAGE3_MUX0_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX0_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX0_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX0_MUX1 8
+#define BM_PXP_WFE_B_STAGE3_MUX0_MUX1 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX0_MUX1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX0_MUX1)
+#define BP_PXP_WFE_B_STAGE3_MUX0_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX0_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX0_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX0_MUX0 0
+#define BM_PXP_WFE_B_STAGE3_MUX0_MUX0 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX0_MUX0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX0_MUX0)
+
+#define HW_PXP_WFE_B_STAGE3_MUX1 (0x00001ec0)
+#define HW_PXP_WFE_B_STAGE3_MUX1_SET (0x00001ec4)
+#define HW_PXP_WFE_B_STAGE3_MUX1_CLR (0x00001ec8)
+#define HW_PXP_WFE_B_STAGE3_MUX1_TOG (0x00001ecc)
+
+#define BP_PXP_WFE_B_STAGE3_MUX1_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX1_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX1_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX1_MUX7 24
+#define BM_PXP_WFE_B_STAGE3_MUX1_MUX7 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX1_MUX7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX1_MUX7)
+#define BP_PXP_WFE_B_STAGE3_MUX1_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX1_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX1_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX1_MUX6 16
+#define BM_PXP_WFE_B_STAGE3_MUX1_MUX6 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX1_MUX6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX1_MUX6)
+#define BP_PXP_WFE_B_STAGE3_MUX1_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX1_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX1_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX1_MUX5 8
+#define BM_PXP_WFE_B_STAGE3_MUX1_MUX5 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX1_MUX5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX1_MUX5)
+#define BP_PXP_WFE_B_STAGE3_MUX1_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX1_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX1_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX1_MUX4 0
+#define BM_PXP_WFE_B_STAGE3_MUX1_MUX4 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX1_MUX4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX1_MUX4)
+
+#define HW_PXP_WFE_B_STAGE3_MUX2 (0x00001ed0)
+#define HW_PXP_WFE_B_STAGE3_MUX2_SET (0x00001ed4)
+#define HW_PXP_WFE_B_STAGE3_MUX2_CLR (0x00001ed8)
+#define HW_PXP_WFE_B_STAGE3_MUX2_TOG (0x00001edc)
+
+#define BP_PXP_WFE_B_STAGE3_MUX2_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX2_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX2_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX2_MUX11 24
+#define BM_PXP_WFE_B_STAGE3_MUX2_MUX11 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX2_MUX11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX2_MUX11)
+#define BP_PXP_WFE_B_STAGE3_MUX2_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX2_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX2_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX2_MUX10 16
+#define BM_PXP_WFE_B_STAGE3_MUX2_MUX10 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX2_MUX10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX2_MUX10)
+#define BP_PXP_WFE_B_STAGE3_MUX2_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX2_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX2_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX2_MUX9 8
+#define BM_PXP_WFE_B_STAGE3_MUX2_MUX9 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX2_MUX9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX2_MUX9)
+#define BP_PXP_WFE_B_STAGE3_MUX2_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX2_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX2_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX2_MUX8 0
+#define BM_PXP_WFE_B_STAGE3_MUX2_MUX8 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX2_MUX8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX2_MUX8)
+
+#define HW_PXP_WFE_B_STAGE3_MUX3 (0x00001ee0)
+#define HW_PXP_WFE_B_STAGE3_MUX3_SET (0x00001ee4)
+#define HW_PXP_WFE_B_STAGE3_MUX3_CLR (0x00001ee8)
+#define HW_PXP_WFE_B_STAGE3_MUX3_TOG (0x00001eec)
+
+#define BP_PXP_WFE_B_STAGE3_MUX3_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX3_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX3_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX3_MUX15 24
+#define BM_PXP_WFE_B_STAGE3_MUX3_MUX15 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX3_MUX15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX3_MUX15)
+#define BP_PXP_WFE_B_STAGE3_MUX3_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX3_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX3_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX3_MUX14 16
+#define BM_PXP_WFE_B_STAGE3_MUX3_MUX14 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX3_MUX14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX3_MUX14)
+#define BP_PXP_WFE_B_STAGE3_MUX3_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX3_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX3_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX3_MUX13 8
+#define BM_PXP_WFE_B_STAGE3_MUX3_MUX13 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX3_MUX13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX3_MUX13)
+#define BP_PXP_WFE_B_STAGE3_MUX3_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX3_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX3_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX3_MUX12 0
+#define BM_PXP_WFE_B_STAGE3_MUX3_MUX12 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX3_MUX12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX3_MUX12)
+
+#define HW_PXP_WFE_B_STAGE3_MUX4 (0x00001ef0)
+#define HW_PXP_WFE_B_STAGE3_MUX4_SET (0x00001ef4)
+#define HW_PXP_WFE_B_STAGE3_MUX4_CLR (0x00001ef8)
+#define HW_PXP_WFE_B_STAGE3_MUX4_TOG (0x00001efc)
+
+#define BP_PXP_WFE_B_STAGE3_MUX4_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX4_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX4_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX4_MUX19 24
+#define BM_PXP_WFE_B_STAGE3_MUX4_MUX19 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX4_MUX19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX4_MUX19)
+#define BP_PXP_WFE_B_STAGE3_MUX4_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX4_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX4_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX4_MUX18 16
+#define BM_PXP_WFE_B_STAGE3_MUX4_MUX18 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX4_MUX18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX4_MUX18)
+#define BP_PXP_WFE_B_STAGE3_MUX4_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX4_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX4_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX4_MUX17 8
+#define BM_PXP_WFE_B_STAGE3_MUX4_MUX17 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX4_MUX17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX4_MUX17)
+#define BP_PXP_WFE_B_STAGE3_MUX4_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX4_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX4_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX4_MUX16 0
+#define BM_PXP_WFE_B_STAGE3_MUX4_MUX16 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX4_MUX16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX4_MUX16)
+
+#define HW_PXP_WFE_B_STAGE3_MUX5 (0x00001f00)
+#define HW_PXP_WFE_B_STAGE3_MUX5_SET (0x00001f04)
+#define HW_PXP_WFE_B_STAGE3_MUX5_CLR (0x00001f08)
+#define HW_PXP_WFE_B_STAGE3_MUX5_TOG (0x00001f0c)
+
+#define BP_PXP_WFE_B_STAGE3_MUX5_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX5_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX5_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX5_MUX23 24
+#define BM_PXP_WFE_B_STAGE3_MUX5_MUX23 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX5_MUX23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX5_MUX23)
+#define BP_PXP_WFE_B_STAGE3_MUX5_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX5_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX5_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX5_MUX22 16
+#define BM_PXP_WFE_B_STAGE3_MUX5_MUX22 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX5_MUX22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX5_MUX22)
+#define BP_PXP_WFE_B_STAGE3_MUX5_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX5_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX5_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX5_MUX21 8
+#define BM_PXP_WFE_B_STAGE3_MUX5_MUX21 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX5_MUX21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX5_MUX21)
+#define BP_PXP_WFE_B_STAGE3_MUX5_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX5_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX5_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX5_MUX20 0
+#define BM_PXP_WFE_B_STAGE3_MUX5_MUX20 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX5_MUX20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX5_MUX20)
+
+#define HW_PXP_WFE_B_STAGE3_MUX6 (0x00001f10)
+#define HW_PXP_WFE_B_STAGE3_MUX6_SET (0x00001f14)
+#define HW_PXP_WFE_B_STAGE3_MUX6_CLR (0x00001f18)
+#define HW_PXP_WFE_B_STAGE3_MUX6_TOG (0x00001f1c)
+
+#define BP_PXP_WFE_B_STAGE3_MUX6_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX6_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX6_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX6_MUX27 24
+#define BM_PXP_WFE_B_STAGE3_MUX6_MUX27 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX6_MUX27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX6_MUX27)
+#define BP_PXP_WFE_B_STAGE3_MUX6_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX6_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX6_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX6_MUX26 16
+#define BM_PXP_WFE_B_STAGE3_MUX6_MUX26 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX6_MUX26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX6_MUX26)
+#define BP_PXP_WFE_B_STAGE3_MUX6_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX6_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX6_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX6_MUX25 8
+#define BM_PXP_WFE_B_STAGE3_MUX6_MUX25 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX6_MUX25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX6_MUX25)
+#define BP_PXP_WFE_B_STAGE3_MUX6_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX6_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX6_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX6_MUX24 0
+#define BM_PXP_WFE_B_STAGE3_MUX6_MUX24 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX6_MUX24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX6_MUX24)
+
+#define HW_PXP_WFE_B_STAGE3_MUX7 (0x00001f20)
+#define HW_PXP_WFE_B_STAGE3_MUX7_SET (0x00001f24)
+#define HW_PXP_WFE_B_STAGE3_MUX7_CLR (0x00001f28)
+#define HW_PXP_WFE_B_STAGE3_MUX7_TOG (0x00001f2c)
+
+#define BP_PXP_WFE_B_STAGE3_MUX7_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX7_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX7_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX7_MUX31 24
+#define BM_PXP_WFE_B_STAGE3_MUX7_MUX31 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX7_MUX31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX7_MUX31)
+#define BP_PXP_WFE_B_STAGE3_MUX7_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX7_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX7_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX7_MUX30 16
+#define BM_PXP_WFE_B_STAGE3_MUX7_MUX30 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX7_MUX30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX7_MUX30)
+#define BP_PXP_WFE_B_STAGE3_MUX7_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX7_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX7_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX7_MUX29 8
+#define BM_PXP_WFE_B_STAGE3_MUX7_MUX29 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX7_MUX29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX7_MUX29)
+#define BP_PXP_WFE_B_STAGE3_MUX7_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX7_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX7_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX7_MUX28 0
+#define BM_PXP_WFE_B_STAGE3_MUX7_MUX28 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX7_MUX28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX7_MUX28)
+
+#define HW_PXP_WFE_B_STAGE3_MUX8 (0x00001f30)
+#define HW_PXP_WFE_B_STAGE3_MUX8_SET (0x00001f34)
+#define HW_PXP_WFE_B_STAGE3_MUX8_CLR (0x00001f38)
+#define HW_PXP_WFE_B_STAGE3_MUX8_TOG (0x00001f3c)
+
+#define BP_PXP_WFE_B_STAGE3_MUX8_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX8_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX8_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX8_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX8_MUX35 24
+#define BM_PXP_WFE_B_STAGE3_MUX8_MUX35 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX8_MUX35(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX8_MUX35)
+#define BP_PXP_WFE_B_STAGE3_MUX8_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX8_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX8_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX8_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX8_MUX34 16
+#define BM_PXP_WFE_B_STAGE3_MUX8_MUX34 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX8_MUX34(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX8_MUX34)
+#define BP_PXP_WFE_B_STAGE3_MUX8_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX8_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX8_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX8_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX8_MUX33 8
+#define BM_PXP_WFE_B_STAGE3_MUX8_MUX33 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX8_MUX33(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX8_MUX33)
+#define BP_PXP_WFE_B_STAGE3_MUX8_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX8_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX8_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX8_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX8_MUX32 0
+#define BM_PXP_WFE_B_STAGE3_MUX8_MUX32 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX8_MUX32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX8_MUX32)
+
+#define HW_PXP_WFE_B_STAGE3_MUX9 (0x00001f40)
+#define HW_PXP_WFE_B_STAGE3_MUX9_SET (0x00001f44)
+#define HW_PXP_WFE_B_STAGE3_MUX9_CLR (0x00001f48)
+#define HW_PXP_WFE_B_STAGE3_MUX9_TOG (0x00001f4c)
+
+#define BP_PXP_WFE_B_STAGE3_MUX9_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX9_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX9_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX9_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX9_MUX39 24
+#define BM_PXP_WFE_B_STAGE3_MUX9_MUX39 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX9_MUX39(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX9_MUX39)
+#define BP_PXP_WFE_B_STAGE3_MUX9_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX9_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX9_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX9_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX9_MUX38 16
+#define BM_PXP_WFE_B_STAGE3_MUX9_MUX38 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX9_MUX38(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX9_MUX38)
+#define BP_PXP_WFE_B_STAGE3_MUX9_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX9_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX9_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX9_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX9_MUX37 8
+#define BM_PXP_WFE_B_STAGE3_MUX9_MUX37 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX9_MUX37(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX9_MUX37)
+#define BP_PXP_WFE_B_STAGE3_MUX9_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX9_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX9_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX9_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX9_MUX36 0
+#define BM_PXP_WFE_B_STAGE3_MUX9_MUX36 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX9_MUX36(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX9_MUX36)
+
+#define HW_PXP_WFE_B_STAGE3_MUX10 (0x00001f50)
+#define HW_PXP_WFE_B_STAGE3_MUX10_SET (0x00001f54)
+#define HW_PXP_WFE_B_STAGE3_MUX10_CLR (0x00001f58)
+#define HW_PXP_WFE_B_STAGE3_MUX10_TOG (0x00001f5c)
+
+#define BP_PXP_WFE_B_STAGE3_MUX10_RSVD0 30
+#define BM_PXP_WFE_B_STAGE3_MUX10_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STAGE3_MUX10_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE3_MUX10_RSVD0)
+#define BP_PXP_WFE_B_STAGE3_MUX10_MUX43 24
+#define BM_PXP_WFE_B_STAGE3_MUX10_MUX43 0x3F000000
+#define BF_PXP_WFE_B_STAGE3_MUX10_MUX43(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE3_MUX10_MUX43)
+#define BP_PXP_WFE_B_STAGE3_MUX10_RSVD1 22
+#define BM_PXP_WFE_B_STAGE3_MUX10_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STAGE3_MUX10_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE3_MUX10_RSVD1)
+#define BP_PXP_WFE_B_STAGE3_MUX10_MUX42 16
+#define BM_PXP_WFE_B_STAGE3_MUX10_MUX42 0x003F0000
+#define BF_PXP_WFE_B_STAGE3_MUX10_MUX42(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE3_MUX10_MUX42)
+#define BP_PXP_WFE_B_STAGE3_MUX10_RSVD2 14
+#define BM_PXP_WFE_B_STAGE3_MUX10_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STAGE3_MUX10_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE3_MUX10_RSVD2)
+#define BP_PXP_WFE_B_STAGE3_MUX10_MUX41 8
+#define BM_PXP_WFE_B_STAGE3_MUX10_MUX41 0x00003F00
+#define BF_PXP_WFE_B_STAGE3_MUX10_MUX41(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE3_MUX10_MUX41)
+#define BP_PXP_WFE_B_STAGE3_MUX10_RSVD3 6
+#define BM_PXP_WFE_B_STAGE3_MUX10_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STAGE3_MUX10_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE3_MUX10_RSVD3)
+#define BP_PXP_WFE_B_STAGE3_MUX10_MUX40 0
+#define BM_PXP_WFE_B_STAGE3_MUX10_MUX40 0x0000003F
+#define BF_PXP_WFE_B_STAGE3_MUX10_MUX40(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE3_MUX10_MUX40)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT0_0 (0x00001f60)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT3 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT3 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT3)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT2 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT2 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT2)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT1 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT1 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT1)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT0 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT0 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT0_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT0_1 (0x00001f70)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT7 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT7 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT7)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT6 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT6 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT6)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT5 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT5 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT5)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT4 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT4 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT0_1_LUTOUT4)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT0_2 (0x00001f80)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT11 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT11 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT11)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT10 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT10 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT10)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT9 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT9 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT9)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT8 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT8 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT0_2_LUTOUT8)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT0_3 (0x00001f90)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT15 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT15 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT15)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT14 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT14 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT14)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT13 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT13 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT13)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT12 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT12 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT0_3_LUTOUT12)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT0_4 (0x00001fa0)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT19 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT19 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT19)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT18 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT18 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT18)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT17 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT17 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT17)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT16 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT16 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT0_4_LUTOUT16)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT0_5 (0x00001fb0)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT23 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT23 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT23)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT22 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT22 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT22)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT21 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT21 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT21)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT20 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT20 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT0_5_LUTOUT20)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT0_6 (0x00001fc0)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT27 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT27 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT27)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT26 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT26 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT26)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT25 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT25 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT25)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT24 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT24 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT0_6_LUTOUT24)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT0_7 (0x00001fd0)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT31 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT31 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT31)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT30 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT30 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT30)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT29 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT29 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT29)
+#define BP_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT28 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT28 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT0_7_LUTOUT28)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT1_0 (0x00001fe0)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT3 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT3 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT3)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT2 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT2 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT2)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT1 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT1 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT1)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT0 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT0 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT1_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT1_1 (0x00001ff0)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT7 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT7 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT7)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT6 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT6 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT6)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT5 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT5 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT5)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT4 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT4 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT1_1_LUTOUT4)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT1_2 (0x00002000)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT11 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT11 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT11)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT10 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT10 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT10)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT9 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT9 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT9)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT8 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT8 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT1_2_LUTOUT8)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT1_3 (0x00002010)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT15 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT15 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT15)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT14 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT14 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT14)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT13 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT13 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT13)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT12 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT12 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT1_3_LUTOUT12)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT1_4 (0x00002020)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT19 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT19 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT19)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT18 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT18 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT18)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT17 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT17 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT17)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT16 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT16 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT1_4_LUTOUT16)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT1_5 (0x00002030)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT23 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT23 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT23)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT22 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT22 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT22)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT21 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT21 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT21)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT20 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT20 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT1_5_LUTOUT20)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT1_6 (0x00002040)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT27 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT27 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT27)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT26 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT26 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT26)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT25 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT25 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT25)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT24 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT24 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT1_6_LUTOUT24)
+
+#define HW_PXP_WFE_B_STG1_5X8_OUT1_7 (0x00002050)
+
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT31 24
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT31 0xFF000000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT31)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT30 16
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT30 0x00FF0000
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT30)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT29 8
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT29 0x0000FF00
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT29)
+#define BP_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT28 0
+#define BM_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT28 0x000000FF
+#define BF_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X8_OUT1_7_LUTOUT28)
+
+#define HW_PXP_WFE_B_STAGE1_5X8_MASKS_0 (0x00002060)
+
+#define BP_PXP_WFE_B_STAGE1_5X8_MASKS_0_RSVD2 13
+#define BM_PXP_WFE_B_STAGE1_5X8_MASKS_0_RSVD2 0xFFFFE000
+#define BF_PXP_WFE_B_STAGE1_5X8_MASKS_0_RSVD2(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STAGE1_5X8_MASKS_0_RSVD2)
+#define BP_PXP_WFE_B_STAGE1_5X8_MASKS_0_MASK1 8
+#define BM_PXP_WFE_B_STAGE1_5X8_MASKS_0_MASK1 0x00001F00
+#define BF_PXP_WFE_B_STAGE1_5X8_MASKS_0_MASK1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE1_5X8_MASKS_0_MASK1)
+#define BP_PXP_WFE_B_STAGE1_5X8_MASKS_0_RSVD3 5
+#define BM_PXP_WFE_B_STAGE1_5X8_MASKS_0_RSVD3 0x000000E0
+#define BF_PXP_WFE_B_STAGE1_5X8_MASKS_0_RSVD3(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STAGE1_5X8_MASKS_0_RSVD3)
+#define BP_PXP_WFE_B_STAGE1_5X8_MASKS_0_MASK0 0
+#define BM_PXP_WFE_B_STAGE1_5X8_MASKS_0_MASK0 0x0000001F
+#define BF_PXP_WFE_B_STAGE1_5X8_MASKS_0_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE1_5X8_MASKS_0_MASK0)
+
+#define HW_PXP_WFE_B_STG1_5X1_OUT0 (0x00002070)
+
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT31)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT30)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT29)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT28)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT27)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT26)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT25)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT24)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT23)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT22)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT21)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT20)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT19)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT18)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT17)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT16)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT15)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT14)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT13)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT12)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT11)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT10)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT9)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT8)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT7)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT6)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT5)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT4)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT3)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT2)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT1)
+#define BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X1_OUT0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG1_5X1_MASKS (0x00002080)
+
+#define BP_PXP_WFE_B_STG1_5X1_MASKS_RSVD0 5
+#define BM_PXP_WFE_B_STG1_5X1_MASKS_RSVD0 0xFFFFFFE0
+#define BF_PXP_WFE_B_STG1_5X1_MASKS_RSVD0(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_5X1_MASKS_RSVD0)
+#define BP_PXP_WFE_B_STG1_5X1_MASKS_MASK0 0
+#define BM_PXP_WFE_B_STG1_5X1_MASKS_MASK0 0x0000001F
+#define BF_PXP_WFE_B_STG1_5X1_MASKS_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_5X1_MASKS_MASK0)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT0_0 (0x00002090)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT0_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT0_1 (0x000020a0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT0_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT0_2 (0x000020b0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT0_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT0_3 (0x000020c0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT0_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT0_4 (0x000020d0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT0_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT0_5 (0x000020e0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT0_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT0_6 (0x000020f0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT0_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT0_7 (0x00002100)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT0_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT1_0 (0x00002110)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT1_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT1_1 (0x00002120)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT1_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT1_2 (0x00002130)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT1_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT1_3 (0x00002140)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT1_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT1_4 (0x00002150)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT1_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT1_5 (0x00002160)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT1_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT1_6 (0x00002170)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT1_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT1_7 (0x00002180)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT1_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT2_0 (0x00002190)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT2_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT2_1 (0x000021a0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT2_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT2_2 (0x000021b0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT2_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT2_3 (0x000021c0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT2_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT2_4 (0x000021d0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT2_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT2_5 (0x000021e0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT2_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT2_6 (0x000021f0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT2_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT2_7 (0x00002200)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT2_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT3_0 (0x00002210)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT3_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT3_1 (0x00002220)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT3_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT3_2 (0x00002230)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT3_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT3_3 (0x00002240)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT3_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT3_4 (0x00002250)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT3_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT3_5 (0x00002260)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT3_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT3_6 (0x00002270)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT3_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT3_7 (0x00002280)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT3_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT4_0 (0x00002290)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT4_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT4_1 (0x000022a0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT4_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT4_2 (0x000022b0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT4_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT4_3 (0x000022c0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT4_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT4_4 (0x000022d0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT4_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT4_5 (0x000022e0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT4_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT4_6 (0x000022f0)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT4_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG1_8X1_OUT4_7 (0x00002300)
+
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG1_8X1_OUT4_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT0_0 (0x00002310)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT3 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT3 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT2 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT2 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT1 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT1 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT0_0_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT0 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT0 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT0_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT0_1 (0x00002320)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT7 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT7 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT7)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT6 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT6 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT6)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT5 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT5 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT5)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT0_1_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT4 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT4 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT0_1_LUTOUT4)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT0_2 (0x00002330)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT11 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT11 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT11)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT10 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT10 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT10)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT9 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT9 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT9)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT0_2_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT8 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT8 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT0_2_LUTOUT8)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT0_3 (0x00002340)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT15 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT15 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT15)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT14 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT14 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT14)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT13 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT13 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT13)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT0_3_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT12 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT12 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT0_3_LUTOUT12)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT0_4 (0x00002350)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT19 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT19 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT19)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT18 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT18 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT18)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT17 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT17 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT17)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT0_4_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT16 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT16 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT0_4_LUTOUT16)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT0_5 (0x00002360)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT23 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT23 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT23)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT22 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT22 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT22)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT21 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT21 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT21)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT0_5_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT20 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT20 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT0_5_LUTOUT20)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT0_6 (0x00002370)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT27 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT27 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT27)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT26 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT26 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT26)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT25 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT25 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT25)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT0_6_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT24 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT24 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT0_6_LUTOUT24)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT0_7 (0x00002380)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT31 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT31 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT31)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT30 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT30 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT30)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT29 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT29 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT29)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT0_7_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT28 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT28 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT0_7_LUTOUT28)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT1_0 (0x00002390)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT3 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT3 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT2 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT2 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT1 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT1 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT1_0_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT0 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT0 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT1_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT1_1 (0x000023a0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT7 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT7 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT7)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT6 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT6 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT6)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT5 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT5 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT5)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT1_1_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT4 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT4 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT1_1_LUTOUT4)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT1_2 (0x000023b0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT11 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT11 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT11)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT10 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT10 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT10)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT9 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT9 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT9)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT1_2_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT8 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT8 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT1_2_LUTOUT8)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT1_3 (0x000023c0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT15 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT15 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT15)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT14 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT14 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT14)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT13 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT13 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT13)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT1_3_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT12 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT12 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT1_3_LUTOUT12)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT1_4 (0x000023d0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT19 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT19 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT19)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT18 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT18 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT18)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT17 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT17 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT17)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT1_4_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT16 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT16 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT1_4_LUTOUT16)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT1_5 (0x000023e0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT23 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT23 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT23)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT22 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT22 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT22)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT21 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT21 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT21)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT1_5_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT20 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT20 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT1_5_LUTOUT20)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT1_6 (0x000023f0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT27 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT27 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT27)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT26 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT26 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT26)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT25 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT25 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT25)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT1_6_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT24 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT24 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT1_6_LUTOUT24)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT1_7 (0x00002400)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT31 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT31 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT31)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT30 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT30 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT30)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT29 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT29 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT29)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT1_7_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT28 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT28 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT1_7_LUTOUT28)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT2_0 (0x00002410)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT3 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT3 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT2 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT2 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT1 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT1 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT2_0_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT0 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT0 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT2_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT2_1 (0x00002420)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT7 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT7 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT7)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT6 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT6 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT6)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT5 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT5 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT5)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT2_1_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT4 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT4 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT2_1_LUTOUT4)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT2_2 (0x00002430)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT11 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT11 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT11)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT10 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT10 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT10)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT9 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT9 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT9)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT2_2_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT8 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT8 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT2_2_LUTOUT8)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT2_3 (0x00002440)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT15 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT15 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT15)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT14 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT14 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT14)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT13 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT13 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT13)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT2_3_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT12 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT12 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT2_3_LUTOUT12)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT2_4 (0x00002450)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT19 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT19 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT19)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT18 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT18 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT18)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT17 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT17 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT17)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT2_4_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT16 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT16 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT2_4_LUTOUT16)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT2_5 (0x00002460)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT23 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT23 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT23)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT22 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT22 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT22)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT21 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT21 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT21)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT2_5_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT20 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT20 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT2_5_LUTOUT20)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT2_6 (0x00002470)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT27 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT27 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT27)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT26 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT26 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT26)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT25 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT25 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT25)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT2_6_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT24 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT24 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT2_6_LUTOUT24)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT2_7 (0x00002480)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT31 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT31 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT31)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT30 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT30 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT30)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT29 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT29 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT29)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT2_7_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT28 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT28 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT2_7_LUTOUT28)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT3_0 (0x00002490)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT3 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT3 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT2 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT2 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT1 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT1 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT3_0_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT0 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT0 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT3_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT3_1 (0x000024a0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT7 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT7 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT7(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT7)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT6 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT6 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT6(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT6)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT5 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT5 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT5(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT5)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT3_1_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT4 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT4 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT4(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT3_1_LUTOUT4)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT3_2 (0x000024b0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT11 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT11 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT11(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT11)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT10 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT10 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT10(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT10)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT9 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT9 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT9(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT9)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT3_2_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT8 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT8 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT8(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT3_2_LUTOUT8)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT3_3 (0x000024c0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT15 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT15 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT15(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT15)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT14 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT14 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT14(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT14)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT13 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT13 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT13(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT13)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT3_3_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT12 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT12 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT12(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT3_3_LUTOUT12)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT3_4 (0x000024e0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT19 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT19 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT19(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT19)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT18 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT18 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT18(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT18)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT17 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT17 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT17(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT17)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT3_4_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT16 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT16 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT16(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT3_4_LUTOUT16)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT3_5 (0x000024f0)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT23 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT23 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT23(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT23)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT22 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT22 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT22(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT22)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT21 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT21 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT21(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT21)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT3_5_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT20 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT20 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT20(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT3_5_LUTOUT20)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT3_6 (0x00002500)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT27 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT27 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT27(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT27)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT26 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT26 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT26(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT26)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT25 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT25 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT25(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT25)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT3_6_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT24 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT24 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT24(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT3_6_LUTOUT24)
+
+#define HW_PXP_WFE_B_STG2_5X6_OUT3_7 (0x00002510)
+
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD0 30
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD0 0xC0000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD0(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT31 24
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT31 0x3F000000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT31(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT31)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD1 22
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD1 0x00C00000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD1(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT30 16
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT30 0x003F0000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT30(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT30)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD2 14
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD2 0x0000C000
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD2(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT29 8
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT29 0x00003F00
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT29(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT29)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD3 6
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD3 0x000000C0
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD3(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X6_OUT3_7_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT28 0
+#define BM_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT28 0x0000003F
+#define BF_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT28(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X6_OUT3_7_LUTOUT28)
+
+#define HW_PXP_WFE_B_STAGE2_5X6_MASKS_0 (0x00002520)
+
+#define BP_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD3 29
+#define BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD3 0xE0000000
+#define BF_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD3(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK3 24
+#define BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK3 0x1F000000
+#define BF_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK3)
+#define BP_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD2 21
+#define BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD2 0x00E00000
+#define BF_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD2(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK2 16
+#define BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK2 0x001F0000
+#define BF_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK2)
+#define BP_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD1 13
+#define BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD1 0x0000E000
+#define BF_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD1(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK1 8
+#define BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK1 0x00001F00
+#define BF_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK1)
+#define BP_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD0 5
+#define BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD0 0x000000E0
+#define BF_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD0(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK0 0
+#define BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK0 0x0000001F
+#define BF_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_5X6_MASKS_0_MASK0)
+
+#define HW_PXP_WFE_B_STAGE2_5X6_ADDR_0 (0x00002530)
+
+#define BP_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD3 30
+#define BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD3 0xC0000000
+#define BF_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD3(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD3)
+#define BP_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR3 24
+#define BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR3 0x3F000000
+#define BF_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR3)
+#define BP_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD2 22
+#define BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD2 0x00C00000
+#define BF_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD2(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD2)
+#define BP_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR2 16
+#define BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR2 0x003F0000
+#define BF_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR2)
+#define BP_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD1 14
+#define BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD1 0x0000C000
+#define BF_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD1(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD1)
+#define BP_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR1 8
+#define BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR1 0x00003F00
+#define BF_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR1)
+#define BP_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD0 6
+#define BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD0 0x000000C0
+#define BF_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD0(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_RSVD0)
+#define BP_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR0 0
+#define BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR0 0x0000003F
+#define BF_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STAGE2_5X6_ADDR_0_MUXADDR0)
+
+#define HW_PXP_WFE_B_STG2_5X1_OUT0 (0x00002540)
+
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT31)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT30)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT29)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT28)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT27)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT26)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT25)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT24)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT23)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT22)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT21)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT20)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT19)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT18)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT17)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT16)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT15)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT14)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT13)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT12)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT11)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT10)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT9)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT8)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT7)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT6)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT5)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT4)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT3)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT2)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT1)
+#define BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X1_OUT0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG2_5X1_OUT1 (0x00002550)
+
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT31)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT30)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT29)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT28)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT27)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT26)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT25)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT24)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT23)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT22)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT21)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT20)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT19)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT18)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT17)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT16)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT15)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT14)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT13)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT12)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT11)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT10)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT9)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT8)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT7)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT6)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT5)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT4)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT3)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT2)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT1)
+#define BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X1_OUT1_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG2_5X1_OUT2 (0x00002560)
+
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT31)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT30)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT29)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT28)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT27)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT26)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT25)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT24)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT23)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT22)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT21)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT20)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT19)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT18)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT17)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT16)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT15)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT14)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT13)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT12)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT11)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT10)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT9)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT8)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT7)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT6)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT5)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT4)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT3)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT2)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT1)
+#define BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X1_OUT2_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG2_5X1_OUT3 (0x00002570)
+
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT31)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT30)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT29)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT28)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT27)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT26)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT25)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT24)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT23)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT22)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT21)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT20)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT19)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT18)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT17)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT16)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT15)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT14)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT13)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT12)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT11)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT10)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT9)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT8)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT7)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT6)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT5)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT4)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT3)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT2)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT1)
+#define BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X1_OUT3_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG2_5X1_MASKS (0x00002580)
+
+#define BP_PXP_WFE_B_STG2_5X1_MASKS_RSVD3 29
+#define BM_PXP_WFE_B_STG2_5X1_MASKS_RSVD3 0xE0000000
+#define BF_PXP_WFE_B_STG2_5X1_MASKS_RSVD3(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG2_5X1_MASKS_RSVD3)
+#define BP_PXP_WFE_B_STG2_5X1_MASKS_MASK3 24
+#define BM_PXP_WFE_B_STG2_5X1_MASKS_MASK3 0x1F000000
+#define BF_PXP_WFE_B_STG2_5X1_MASKS_MASK3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG2_5X1_MASKS_MASK3)
+#define BP_PXP_WFE_B_STG2_5X1_MASKS_RSVD2 21
+#define BM_PXP_WFE_B_STG2_5X1_MASKS_RSVD2 0x00E00000
+#define BF_PXP_WFE_B_STG2_5X1_MASKS_RSVD2(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG2_5X1_MASKS_RSVD2)
+#define BP_PXP_WFE_B_STG2_5X1_MASKS_MASK2 16
+#define BM_PXP_WFE_B_STG2_5X1_MASKS_MASK2 0x001F0000
+#define BF_PXP_WFE_B_STG2_5X1_MASKS_MASK2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG2_5X1_MASKS_MASK2)
+#define BP_PXP_WFE_B_STG2_5X1_MASKS_RSVD1 13
+#define BM_PXP_WFE_B_STG2_5X1_MASKS_RSVD1 0x0000E000
+#define BF_PXP_WFE_B_STG2_5X1_MASKS_RSVD1(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG2_5X1_MASKS_RSVD1)
+#define BP_PXP_WFE_B_STG2_5X1_MASKS_MASK1 8
+#define BM_PXP_WFE_B_STG2_5X1_MASKS_MASK1 0x00001F00
+#define BF_PXP_WFE_B_STG2_5X1_MASKS_MASK1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG2_5X1_MASKS_MASK1)
+#define BP_PXP_WFE_B_STG2_5X1_MASKS_RSVD0 5
+#define BM_PXP_WFE_B_STG2_5X1_MASKS_RSVD0 0x000000E0
+#define BF_PXP_WFE_B_STG2_5X1_MASKS_RSVD0(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG2_5X1_MASKS_RSVD0)
+#define BP_PXP_WFE_B_STG2_5X1_MASKS_MASK0 0
+#define BM_PXP_WFE_B_STG2_5X1_MASKS_MASK0 0x0000001F
+#define BF_PXP_WFE_B_STG2_5X1_MASKS_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG2_5X1_MASKS_MASK0)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT0_0 (0x00002590)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT0_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT0_1 (0x000025a0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT0_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT0_2 (0x000025b0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT0_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT0_3 (0x000025c0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT0_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT0_4 (0x000025d0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT0_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT0_5 (0x000025e0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT0_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT0_6 (0x000025f0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT0_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT0_7 (0x00002600)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT0_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT1_0 (0x00002610)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT1_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT1_1 (0x00002620)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT1_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT1_2 (0x00002630)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT1_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT1_3 (0x00002640)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT1_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT1_4 (0x00002650)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT1_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT1_5 (0x00002660)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT1_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT1_6 (0x00002670)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT1_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT1_7 (0x00002680)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT1_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT2_0 (0x00002690)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT2_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT2_1 (0x000026a0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT2_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT2_2 (0x000026b0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT2_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT2_3 (0x000026c0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT2_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT2_4 (0x000026d0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT2_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT2_5 (0x000026e0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT2_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT2_6 (0x000026f0)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT2_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT2_7 (0x00002700)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT2_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT3_0 (0x00002710)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT31 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT31(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT31)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT30 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT30(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT30)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT29 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT29(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT29)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT28 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT28(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT28)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT27 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT27(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT27)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT26 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT26(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT26)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT25 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT25(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT25)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT24 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT24(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT24)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT23 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT23(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT23)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT22 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT22(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT22)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT21 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT21(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT21)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT20 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT20(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT20)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT19 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT19(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT19)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT18 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT18(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT18)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT17 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT17(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT17)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT16 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT16(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT16)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT15 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT15(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT15)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT14 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT14(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT14)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT13 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT13(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT13)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT12 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT12(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT12)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT11 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT11(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT11)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT10 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT10(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT10)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT9 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT9(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT9)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT8 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT8(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT8)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT7 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT7(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT7)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT6 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT6(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT6)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT5 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT5(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT5)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT4 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT4(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT4)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT3 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT3(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT3)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT2 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT2(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT2)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT1 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT1(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT1)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT0 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT3_0_LUTOUT0)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT3_1 (0x00002720)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT63 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT63(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT63)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT62 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT62(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT62)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT61 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT61(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT61)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT60 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT60(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT60)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT59 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT59(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT59)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT58 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT58(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT58)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT57 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT57(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT57)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT56 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT56(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT56)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT55 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT55(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT55)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT54 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT54(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT54)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT53 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT53(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT53)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT52 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT52(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT52)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT51 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT51(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT51)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT50 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT50(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT50)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT49 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT49(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT49)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT48 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT48(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT48)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT47 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT47(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT47)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT46 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT46(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT46)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT45 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT45(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT45)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT44 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT44(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT44)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT43 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT43(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT43)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT42 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT42(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT42)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT41 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT41(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT41)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT40 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT40(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT40)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT39 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT39(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT39)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT38 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT38(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT38)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT37 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT37(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT37)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT36 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT36(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT36)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT35 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT35(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT35)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT34 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT34(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT34)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT33 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT33(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT33)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT32 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT32(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT3_1_LUTOUT32)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT3_2 (0x00002730)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT95 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT95(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT95)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT94 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT94(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT94)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT93 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT93(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT93)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT92 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT92(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT92)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT91 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT91(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT91)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT90 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT90(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT90)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT89 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT89(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT89)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT88 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT88(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT88)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT87 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT87(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT87)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT86 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT86(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT86)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT85 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT85(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT85)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT84 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT84(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT84)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT83 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT83(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT83)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT82 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT82(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT82)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT81 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT81(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT81)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT80 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT80(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT80)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT79 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT79(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT79)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT78 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT78(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT78)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT77 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT77(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT77)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT76 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT76(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT76)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT75 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT75(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT75)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT74 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT74(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT74)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT73 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT73(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT73)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT72 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT72(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT72)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT71 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT71(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT71)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT70 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT70(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT70)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT69 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT69(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT69)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT68 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT68(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT68)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT67 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT67(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT67)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT66 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT66(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT66)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT65 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT65(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT65)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT64 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT64(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT3_2_LUTOUT64)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT3_3 (0x00002740)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT127 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT127(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT127)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT126 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT126(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT126)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT125 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT125(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT125)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT124 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT124(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT124)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT123 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT123(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT123)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT122 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT122(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT122)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT121 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT121(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT121)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT120 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT120(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT120)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT119 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT119(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT119)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT118 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT118(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT118)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT117 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT117(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT117)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT116 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT116(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT116)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT115 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT115(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT115)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT114 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT114(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT114)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT113 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT113(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT113)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT112 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT112(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT112)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT111 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT111(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT111)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT110 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT110(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT110)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT109 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT109(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT109)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT108 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT108(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT108)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT107 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT107(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT107)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT106 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT106(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT106)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT105 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT105(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT105)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT104 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT104(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT104)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT103 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT103(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT103)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT102 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT102(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT102)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT101 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT101(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT101)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT100 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT100(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT100)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT99 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT99(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT99)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT98 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT98(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT98)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT97 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT97(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT97)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT96 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT96(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT3_3_LUTOUT96)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT3_4 (0x00002750)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT159 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT159(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT159)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT158 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT158(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT158)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT157 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT157(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT157)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT156 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT156(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT156)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT155 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT155(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT155)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT154 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT154(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT154)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT153 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT153(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT153)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT152 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT152(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT152)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT151 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT151(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT151)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT150 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT150(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT150)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT149 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT149(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT149)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT148 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT148(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT148)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT147 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT147(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT147)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT146 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT146(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT146)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT145 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT145(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT145)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT144 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT144(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT144)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT143 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT143(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT143)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT142 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT142(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT142)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT141 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT141(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT141)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT140 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT140(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT140)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT139 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT139(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT139)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT138 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT138(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT138)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT137 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT137(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT137)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT136 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT136(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT136)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT135 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT135(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT135)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT134 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT134(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT134)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT133 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT133(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT133)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT132 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT132(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT132)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT131 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT131(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT131)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT130 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT130(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT130)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT129 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT129(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT129)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT128 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT128(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT3_4_LUTOUT128)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT3_5 (0x00002760)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT191 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT191(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT191)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT190 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT190(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT190)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT189 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT189(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT189)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT188 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT188(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT188)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT187 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT187(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT187)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT186 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT186(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT186)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT185 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT185(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT185)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT184 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT184(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT184)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT183 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT183(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT183)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT182 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT182(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT182)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT181 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT181(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT181)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT180 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT180(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT180)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT179 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT179(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT179)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT178 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT178(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT178)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT177 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT177(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT177)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT176 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT176(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT176)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT175 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT175(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT175)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT174 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT174(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT174)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT173 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT173(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT173)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT172 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT172(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT172)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT171 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT171(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT171)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT170 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT170(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT170)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT169 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT169(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT169)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT168 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT168(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT168)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT167 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT167(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT167)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT166 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT166(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT166)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT165 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT165(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT165)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT164 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT164(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT164)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT163 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT163(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT163)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT162 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT162(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT162)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT161 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT161(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT161)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT160 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT160(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT3_5_LUTOUT160)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT3_6 (0x00002770)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT223 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT223(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT223)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT222 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT222(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT222)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT221 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT221(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT221)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT220 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT220(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT220)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT219 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT219(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT219)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT218 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT218(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT218)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT217 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT217(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT217)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT216 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT216(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT216)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT215 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT215(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT215)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT214 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT214(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT214)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT213 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT213(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT213)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT212 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT212(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT212)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT211 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT211(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT211)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT210 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT210(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT210)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT209 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT209(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT209)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT208 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT208(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT208)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT207 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT207(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT207)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT206 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT206(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT206)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT205 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT205(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT205)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT204 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT204(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT204)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT203 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT203(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT203)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT202 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT202(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT202)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT201 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT201(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT201)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT200 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT200(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT200)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT199 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT199(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT199)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT198 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT198(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT198)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT197 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT197(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT197)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT196 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT196(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT196)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT195 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT195(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT195)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT194 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT194(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT194)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT193 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT193(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT193)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT192 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT192(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT3_6_LUTOUT192)
+
+#define HW_PXP_WFE_B_STG3_F8X1_OUT3_7 (0x00002780)
+
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT255 0x80000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT255(v) \
+ (((v) << 31) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT255)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT254 0x40000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT254(v) \
+ (((v) << 30) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT254)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT253 0x20000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT253(v) \
+ (((v) << 29) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT253)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT252 0x10000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT252(v) \
+ (((v) << 28) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT252)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT251 0x08000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT251(v) \
+ (((v) << 27) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT251)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT250 0x04000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT250(v) \
+ (((v) << 26) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT250)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT249 0x02000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT249(v) \
+ (((v) << 25) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT249)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT248 0x01000000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT248(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT248)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT247 0x00800000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT247(v) \
+ (((v) << 23) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT247)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT246 0x00400000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT246(v) \
+ (((v) << 22) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT246)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT245 0x00200000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT245(v) \
+ (((v) << 21) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT245)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT244 0x00100000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT244(v) \
+ (((v) << 20) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT244)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT243 0x00080000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT243(v) \
+ (((v) << 19) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT243)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT242 0x00040000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT242(v) \
+ (((v) << 18) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT242)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT241 0x00020000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT241(v) \
+ (((v) << 17) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT241)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT240 0x00010000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT240(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT240)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT239 0x00008000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT239(v) \
+ (((v) << 15) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT239)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT238 0x00004000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT238(v) \
+ (((v) << 14) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT238)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT237 0x00002000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT237(v) \
+ (((v) << 13) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT237)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT236 0x00001000
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT236(v) \
+ (((v) << 12) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT236)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT235 0x00000800
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT235(v) \
+ (((v) << 11) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT235)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT234 0x00000400
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT234(v) \
+ (((v) << 10) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT234)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT233 0x00000200
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT233(v) \
+ (((v) << 9) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT233)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT232 0x00000100
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT232(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT232)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT231 0x00000080
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT231(v) \
+ (((v) << 7) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT231)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT230 0x00000040
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT230(v) \
+ (((v) << 6) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT230)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT229 0x00000020
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT229(v) \
+ (((v) << 5) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT229)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT228 0x00000010
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT228(v) \
+ (((v) << 4) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT228)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT227 0x00000008
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT227(v) \
+ (((v) << 3) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT227)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT226 0x00000004
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT226(v) \
+ (((v) << 2) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT226)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT225 0x00000002
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT225(v) \
+ (((v) << 1) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT225)
+#define BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT224 0x00000001
+#define BF_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT224(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_OUT3_7_LUTOUT224)
+
+#define HW_PXP_WFE_B_STG3_F8X1_MASKS (0x00002790)
+
+#define BP_PXP_WFE_B_STG3_F8X1_MASKS_MASK3 24
+#define BM_PXP_WFE_B_STG3_F8X1_MASKS_MASK3 0xFF000000
+#define BF_PXP_WFE_B_STG3_F8X1_MASKS_MASK3(v) \
+ (((v) << 24) & BM_PXP_WFE_B_STG3_F8X1_MASKS_MASK3)
+#define BP_PXP_WFE_B_STG3_F8X1_MASKS_MASK2 16
+#define BM_PXP_WFE_B_STG3_F8X1_MASKS_MASK2 0x00FF0000
+#define BF_PXP_WFE_B_STG3_F8X1_MASKS_MASK2(v) \
+ (((v) << 16) & BM_PXP_WFE_B_STG3_F8X1_MASKS_MASK2)
+#define BP_PXP_WFE_B_STG3_F8X1_MASKS_MASK1 8
+#define BM_PXP_WFE_B_STG3_F8X1_MASKS_MASK1 0x0000FF00
+#define BF_PXP_WFE_B_STG3_F8X1_MASKS_MASK1(v) \
+ (((v) << 8) & BM_PXP_WFE_B_STG3_F8X1_MASKS_MASK1)
+#define BP_PXP_WFE_B_STG3_F8X1_MASKS_MASK0 0
+#define BM_PXP_WFE_B_STG3_F8X1_MASKS_MASK0 0x000000FF
+#define BF_PXP_WFE_B_STG3_F8X1_MASKS_MASK0(v) \
+ (((v) << 0) & BM_PXP_WFE_B_STG3_F8X1_MASKS_MASK0)
+
+#define HW_PXP_ALU_A_CTRL (0x00002810)
+#define HW_PXP_ALU_A_CTRL_SET (0x00002814)
+#define HW_PXP_ALU_A_CTRL_CLR (0x00002818)
+#define HW_PXP_ALU_A_CTRL_TOG (0x0000281c)
+
+#define BP_PXP_ALU_A_CTRL_RSVD0 29
+#define BM_PXP_ALU_A_CTRL_RSVD0 0xE0000000
+#define BF_PXP_ALU_A_CTRL_RSVD0(v) \
+ (((v) << 29) & BM_PXP_ALU_A_CTRL_RSVD0)
+#define BM_PXP_ALU_A_CTRL_DONE 0x10000000
+#define BF_PXP_ALU_A_CTRL_DONE(v) \
+ (((v) << 28) & BM_PXP_ALU_A_CTRL_DONE)
+#define BP_PXP_ALU_A_CTRL_RSVD1 21
+#define BM_PXP_ALU_A_CTRL_RSVD1 0x0FE00000
+#define BF_PXP_ALU_A_CTRL_RSVD1(v) \
+ (((v) << 21) & BM_PXP_ALU_A_CTRL_RSVD1)
+#define BM_PXP_ALU_A_CTRL_DONE_IRQ_EN 0x00100000
+#define BF_PXP_ALU_A_CTRL_DONE_IRQ_EN(v) \
+ (((v) << 20) & BM_PXP_ALU_A_CTRL_DONE_IRQ_EN)
+#define BP_PXP_ALU_A_CTRL_RSVD2 17
+#define BM_PXP_ALU_A_CTRL_RSVD2 0x000E0000
+#define BF_PXP_ALU_A_CTRL_RSVD2(v) \
+ (((v) << 17) & BM_PXP_ALU_A_CTRL_RSVD2)
+#define BM_PXP_ALU_A_CTRL_DONE_IRQ_FLAG 0x00010000
+#define BF_PXP_ALU_A_CTRL_DONE_IRQ_FLAG(v) \
+ (((v) << 16) & BM_PXP_ALU_A_CTRL_DONE_IRQ_FLAG)
+#define BP_PXP_ALU_A_CTRL_RSVD3 13
+#define BM_PXP_ALU_A_CTRL_RSVD3 0x0000E000
+#define BF_PXP_ALU_A_CTRL_RSVD3(v) \
+ (((v) << 13) & BM_PXP_ALU_A_CTRL_RSVD3)
+#define BM_PXP_ALU_A_CTRL_BYPASS 0x00001000
+#define BF_PXP_ALU_A_CTRL_BYPASS(v) \
+ (((v) << 12) & BM_PXP_ALU_A_CTRL_BYPASS)
+#define BV_PXP_ALU_A_CTRL_BYPASS__0 0x0
+#define BV_PXP_ALU_A_CTRL_BYPASS__1 0x1
+#define BP_PXP_ALU_A_CTRL_RSVD4 9
+#define BM_PXP_ALU_A_CTRL_RSVD4 0x00000E00
+#define BF_PXP_ALU_A_CTRL_RSVD4(v) \
+ (((v) << 9) & BM_PXP_ALU_A_CTRL_RSVD4)
+#define BM_PXP_ALU_A_CTRL_SW_RESET 0x00000100
+#define BF_PXP_ALU_A_CTRL_SW_RESET(v) \
+ (((v) << 8) & BM_PXP_ALU_A_CTRL_SW_RESET)
+#define BP_PXP_ALU_A_CTRL_RSVD5 5
+#define BM_PXP_ALU_A_CTRL_RSVD5 0x000000E0
+#define BF_PXP_ALU_A_CTRL_RSVD5(v) \
+ (((v) << 5) & BM_PXP_ALU_A_CTRL_RSVD5)
+#define BM_PXP_ALU_A_CTRL_START 0x00000010
+#define BF_PXP_ALU_A_CTRL_START(v) \
+ (((v) << 4) & BM_PXP_ALU_A_CTRL_START)
+#define BP_PXP_ALU_A_CTRL_RSVD6 1
+#define BM_PXP_ALU_A_CTRL_RSVD6 0x0000000E
+#define BF_PXP_ALU_A_CTRL_RSVD6(v) \
+ (((v) << 1) & BM_PXP_ALU_A_CTRL_RSVD6)
+#define BM_PXP_ALU_A_CTRL_ENABLE 0x00000001
+#define BF_PXP_ALU_A_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PXP_ALU_A_CTRL_ENABLE)
+#define BV_PXP_ALU_A_CTRL_ENABLE__0 0x0
+#define BV_PXP_ALU_A_CTRL_ENABLE__1 0x1
+
+#define HW_PXP_ALU_A_BUF_SIZE (0x00002820)
+
+#define BP_PXP_ALU_A_BUF_SIZE_RSVD0 28
+#define BM_PXP_ALU_A_BUF_SIZE_RSVD0 0xF0000000
+#define BF_PXP_ALU_A_BUF_SIZE_RSVD0(v) \
+ (((v) << 28) & BM_PXP_ALU_A_BUF_SIZE_RSVD0)
+#define BP_PXP_ALU_A_BUF_SIZE_BUF_HEIGHT 16
+#define BM_PXP_ALU_A_BUF_SIZE_BUF_HEIGHT 0x0FFF0000
+#define BF_PXP_ALU_A_BUF_SIZE_BUF_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_ALU_A_BUF_SIZE_BUF_HEIGHT)
+#define BP_PXP_ALU_A_BUF_SIZE_RSVD1 12
+#define BM_PXP_ALU_A_BUF_SIZE_RSVD1 0x0000F000
+#define BF_PXP_ALU_A_BUF_SIZE_RSVD1(v) \
+ (((v) << 12) & BM_PXP_ALU_A_BUF_SIZE_RSVD1)
+#define BP_PXP_ALU_A_BUF_SIZE_BUF_WIDTH 0
+#define BM_PXP_ALU_A_BUF_SIZE_BUF_WIDTH 0x00000FFF
+#define BF_PXP_ALU_A_BUF_SIZE_BUF_WIDTH(v) \
+ (((v) << 0) & BM_PXP_ALU_A_BUF_SIZE_BUF_WIDTH)
+
+#define HW_PXP_ALU_A_INST_ENTRY (0x00002830)
+
+#define BP_PXP_ALU_A_INST_ENTRY_RSVD0 16
+#define BM_PXP_ALU_A_INST_ENTRY_RSVD0 0xFFFF0000
+#define BF_PXP_ALU_A_INST_ENTRY_RSVD0(v) \
+ (((v) << 16) & BM_PXP_ALU_A_INST_ENTRY_RSVD0)
+#define BP_PXP_ALU_A_INST_ENTRY_ENTRY_ADDR 0
+#define BM_PXP_ALU_A_INST_ENTRY_ENTRY_ADDR 0x0000FFFF
+#define BF_PXP_ALU_A_INST_ENTRY_ENTRY_ADDR(v) \
+ (((v) << 0) & BM_PXP_ALU_A_INST_ENTRY_ENTRY_ADDR)
+
+#define HW_PXP_ALU_A_PARAM (0x00002840)
+
+#define BP_PXP_ALU_A_PARAM_RSVD0 16
+#define BM_PXP_ALU_A_PARAM_RSVD0 0xFFFF0000
+#define BF_PXP_ALU_A_PARAM_RSVD0(v) \
+ (((v) << 16) & BM_PXP_ALU_A_PARAM_RSVD0)
+#define BP_PXP_ALU_A_PARAM_PARAM1 8
+#define BM_PXP_ALU_A_PARAM_PARAM1 0x0000FF00
+#define BF_PXP_ALU_A_PARAM_PARAM1(v) \
+ (((v) << 8) & BM_PXP_ALU_A_PARAM_PARAM1)
+#define BP_PXP_ALU_A_PARAM_PARAM0 0
+#define BM_PXP_ALU_A_PARAM_PARAM0 0x000000FF
+#define BF_PXP_ALU_A_PARAM_PARAM0(v) \
+ (((v) << 0) & BM_PXP_ALU_A_PARAM_PARAM0)
+
+#define HW_PXP_ALU_A_CONFIG (0x00002850)
+
+#define BP_PXP_ALU_A_CONFIG_BUF_ADDR 0
+#define BM_PXP_ALU_A_CONFIG_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_ALU_A_CONFIG_BUF_ADDR(v) (v)
+
+#define HW_PXP_ALU_A_LUT_CONFIG (0x00002860)
+#define HW_PXP_ALU_A_LUT_CONFIG_SET (0x00002864)
+#define HW_PXP_ALU_A_LUT_CONFIG_CLR (0x00002868)
+#define HW_PXP_ALU_A_LUT_CONFIG_TOG (0x0000286c)
+
+#define BP_PXP_ALU_A_LUT_CONFIG_RSVD0 6
+#define BM_PXP_ALU_A_LUT_CONFIG_RSVD0 0xFFFFFFC0
+#define BF_PXP_ALU_A_LUT_CONFIG_RSVD0(v) \
+ (((v) << 6) & BM_PXP_ALU_A_LUT_CONFIG_RSVD0)
+#define BP_PXP_ALU_A_LUT_CONFIG_MODE 4
+#define BM_PXP_ALU_A_LUT_CONFIG_MODE 0x00000030
+#define BF_PXP_ALU_A_LUT_CONFIG_MODE(v) \
+ (((v) << 4) & BM_PXP_ALU_A_LUT_CONFIG_MODE)
+#define BV_PXP_ALU_A_LUT_CONFIG_MODE__0 0x0
+#define BV_PXP_ALU_A_LUT_CONFIG_MODE__1 0x1
+#define BV_PXP_ALU_A_LUT_CONFIG_MODE__2 0x2
+#define BV_PXP_ALU_A_LUT_CONFIG_MODE__3 0x3
+#define BP_PXP_ALU_A_LUT_CONFIG_RSVD1 1
+#define BM_PXP_ALU_A_LUT_CONFIG_RSVD1 0x0000000E
+#define BF_PXP_ALU_A_LUT_CONFIG_RSVD1(v) \
+ (((v) << 1) & BM_PXP_ALU_A_LUT_CONFIG_RSVD1)
+#define BM_PXP_ALU_A_LUT_CONFIG_EN 0x00000001
+#define BF_PXP_ALU_A_LUT_CONFIG_EN(v) \
+ (((v) << 0) & BM_PXP_ALU_A_LUT_CONFIG_EN)
+
+#define HW_PXP_ALU_A_LUT_DATA0 (0x00002870)
+
+#define BP_PXP_ALU_A_LUT_DATA0_LUT_DATA_L 0
+#define BM_PXP_ALU_A_LUT_DATA0_LUT_DATA_L 0xFFFFFFFF
+#define BF_PXP_ALU_A_LUT_DATA0_LUT_DATA_L(v) (v)
+
+#define HW_PXP_ALU_A_LUT_DATA1 (0x00002880)
+
+#define BP_PXP_ALU_A_LUT_DATA1_LUT_DATA_H 0
+#define BM_PXP_ALU_A_LUT_DATA1_LUT_DATA_H 0xFFFFFFFF
+#define BF_PXP_ALU_A_LUT_DATA1_LUT_DATA_H(v) (v)
+
+#define HW_PXP_ALU_A_DBG (0x00002890)
+
+#define BP_PXP_ALU_A_DBG_DEBUG_SEL 24
+#define BM_PXP_ALU_A_DBG_DEBUG_SEL 0xFF000000
+#define BF_PXP_ALU_A_DBG_DEBUG_SEL(v) \
+ (((v) << 24) & BM_PXP_ALU_A_DBG_DEBUG_SEL)
+#define BP_PXP_ALU_A_DBG_DEBUG_VALUE 0
+#define BM_PXP_ALU_A_DBG_DEBUG_VALUE 0x00FFFFFF
+#define BF_PXP_ALU_A_DBG_DEBUG_VALUE(v) \
+ (((v) << 0) & BM_PXP_ALU_A_DBG_DEBUG_VALUE)
+
+#define HW_PXP_ALU_B_CTRL (0x000028a0)
+#define HW_PXP_ALU_B_CTRL_SET (0x000028a4)
+#define HW_PXP_ALU_B_CTRL_CLR (0x000028a8)
+#define HW_PXP_ALU_B_CTRL_TOG (0x000028ac)
+
+#define BP_PXP_ALU_B_CTRL_RSVD0 29
+#define BM_PXP_ALU_B_CTRL_RSVD0 0xE0000000
+#define BF_PXP_ALU_B_CTRL_RSVD0(v) \
+ (((v) << 29) & BM_PXP_ALU_B_CTRL_RSVD0)
+#define BM_PXP_ALU_B_CTRL_DONE 0x10000000
+#define BF_PXP_ALU_B_CTRL_DONE(v) \
+ (((v) << 28) & BM_PXP_ALU_B_CTRL_DONE)
+#define BP_PXP_ALU_B_CTRL_RSVD1 21
+#define BM_PXP_ALU_B_CTRL_RSVD1 0x0FE00000
+#define BF_PXP_ALU_B_CTRL_RSVD1(v) \
+ (((v) << 21) & BM_PXP_ALU_B_CTRL_RSVD1)
+#define BM_PXP_ALU_B_CTRL_DONE_IRQ_EN 0x00100000
+#define BF_PXP_ALU_B_CTRL_DONE_IRQ_EN(v) \
+ (((v) << 20) & BM_PXP_ALU_B_CTRL_DONE_IRQ_EN)
+#define BP_PXP_ALU_B_CTRL_RSVD2 17
+#define BM_PXP_ALU_B_CTRL_RSVD2 0x000E0000
+#define BF_PXP_ALU_B_CTRL_RSVD2(v) \
+ (((v) << 17) & BM_PXP_ALU_B_CTRL_RSVD2)
+#define BM_PXP_ALU_B_CTRL_DONE_IRQ_FLAG 0x00010000
+#define BF_PXP_ALU_B_CTRL_DONE_IRQ_FLAG(v) \
+ (((v) << 16) & BM_PXP_ALU_B_CTRL_DONE_IRQ_FLAG)
+#define BP_PXP_ALU_B_CTRL_RSVD3 13
+#define BM_PXP_ALU_B_CTRL_RSVD3 0x0000E000
+#define BF_PXP_ALU_B_CTRL_RSVD3(v) \
+ (((v) << 13) & BM_PXP_ALU_B_CTRL_RSVD3)
+#define BM_PXP_ALU_B_CTRL_BYPASS 0x00001000
+#define BF_PXP_ALU_B_CTRL_BYPASS(v) \
+ (((v) << 12) & BM_PXP_ALU_B_CTRL_BYPASS)
+#define BV_PXP_ALU_B_CTRL_BYPASS__0 0x0
+#define BV_PXP_ALU_B_CTRL_BYPASS__1 0x1
+#define BP_PXP_ALU_B_CTRL_RSVD4 9
+#define BM_PXP_ALU_B_CTRL_RSVD4 0x00000E00
+#define BF_PXP_ALU_B_CTRL_RSVD4(v) \
+ (((v) << 9) & BM_PXP_ALU_B_CTRL_RSVD4)
+#define BM_PXP_ALU_B_CTRL_SW_RESET 0x00000100
+#define BF_PXP_ALU_B_CTRL_SW_RESET(v) \
+ (((v) << 8) & BM_PXP_ALU_B_CTRL_SW_RESET)
+#define BP_PXP_ALU_B_CTRL_RSVD5 5
+#define BM_PXP_ALU_B_CTRL_RSVD5 0x000000E0
+#define BF_PXP_ALU_B_CTRL_RSVD5(v) \
+ (((v) << 5) & BM_PXP_ALU_B_CTRL_RSVD5)
+#define BM_PXP_ALU_B_CTRL_START 0x00000010
+#define BF_PXP_ALU_B_CTRL_START(v) \
+ (((v) << 4) & BM_PXP_ALU_B_CTRL_START)
+#define BP_PXP_ALU_B_CTRL_RSVD6 1
+#define BM_PXP_ALU_B_CTRL_RSVD6 0x0000000E
+#define BF_PXP_ALU_B_CTRL_RSVD6(v) \
+ (((v) << 1) & BM_PXP_ALU_B_CTRL_RSVD6)
+#define BM_PXP_ALU_B_CTRL_ENABLE 0x00000001
+#define BF_PXP_ALU_B_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PXP_ALU_B_CTRL_ENABLE)
+#define BV_PXP_ALU_B_CTRL_ENABLE__0 0x0
+#define BV_PXP_ALU_B_CTRL_ENABLE__1 0x1
+
+#define HW_PXP_ALU_B_BUF_SIZE (0x000028b0)
+
+#define BP_PXP_ALU_B_BUF_SIZE_RSVD0 28
+#define BM_PXP_ALU_B_BUF_SIZE_RSVD0 0xF0000000
+#define BF_PXP_ALU_B_BUF_SIZE_RSVD0(v) \
+ (((v) << 28) & BM_PXP_ALU_B_BUF_SIZE_RSVD0)
+#define BP_PXP_ALU_B_BUF_SIZE_BUF_HEIGHT 16
+#define BM_PXP_ALU_B_BUF_SIZE_BUF_HEIGHT 0x0FFF0000
+#define BF_PXP_ALU_B_BUF_SIZE_BUF_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_ALU_B_BUF_SIZE_BUF_HEIGHT)
+#define BP_PXP_ALU_B_BUF_SIZE_RSVD1 12
+#define BM_PXP_ALU_B_BUF_SIZE_RSVD1 0x0000F000
+#define BF_PXP_ALU_B_BUF_SIZE_RSVD1(v) \
+ (((v) << 12) & BM_PXP_ALU_B_BUF_SIZE_RSVD1)
+#define BP_PXP_ALU_B_BUF_SIZE_BUF_WIDTH 0
+#define BM_PXP_ALU_B_BUF_SIZE_BUF_WIDTH 0x00000FFF
+#define BF_PXP_ALU_B_BUF_SIZE_BUF_WIDTH(v) \
+ (((v) << 0) & BM_PXP_ALU_B_BUF_SIZE_BUF_WIDTH)
+
+#define HW_PXP_ALU_B_INST_ENTRY (0x000028c0)
+
+#define BP_PXP_ALU_B_INST_ENTRY_RSVD0 16
+#define BM_PXP_ALU_B_INST_ENTRY_RSVD0 0xFFFF0000
+#define BF_PXP_ALU_B_INST_ENTRY_RSVD0(v) \
+ (((v) << 16) & BM_PXP_ALU_B_INST_ENTRY_RSVD0)
+#define BP_PXP_ALU_B_INST_ENTRY_ENTRY_ADDR 0
+#define BM_PXP_ALU_B_INST_ENTRY_ENTRY_ADDR 0x0000FFFF
+#define BF_PXP_ALU_B_INST_ENTRY_ENTRY_ADDR(v) \
+ (((v) << 0) & BM_PXP_ALU_B_INST_ENTRY_ENTRY_ADDR)
+
+#define HW_PXP_ALU_B_PARAM (0x000028d0)
+
+#define BP_PXP_ALU_B_PARAM_RSVD0 16
+#define BM_PXP_ALU_B_PARAM_RSVD0 0xFFFF0000
+#define BF_PXP_ALU_B_PARAM_RSVD0(v) \
+ (((v) << 16) & BM_PXP_ALU_B_PARAM_RSVD0)
+#define BP_PXP_ALU_B_PARAM_PARAM1 8
+#define BM_PXP_ALU_B_PARAM_PARAM1 0x0000FF00
+#define BF_PXP_ALU_B_PARAM_PARAM1(v) \
+ (((v) << 8) & BM_PXP_ALU_B_PARAM_PARAM1)
+#define BP_PXP_ALU_B_PARAM_PARAM0 0
+#define BM_PXP_ALU_B_PARAM_PARAM0 0x000000FF
+#define BF_PXP_ALU_B_PARAM_PARAM0(v) \
+ (((v) << 0) & BM_PXP_ALU_B_PARAM_PARAM0)
+
+#define HW_PXP_ALU_B_CONFIG (0x000028e0)
+
+#define BP_PXP_ALU_B_CONFIG_BUF_ADDR 0
+#define BM_PXP_ALU_B_CONFIG_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_ALU_B_CONFIG_BUF_ADDR(v) (v)
+
+#define HW_PXP_ALU_B_LUT_CONFIG (0x000028f0)
+#define HW_PXP_ALU_B_LUT_CONFIG_SET (0x000028f4)
+#define HW_PXP_ALU_B_LUT_CONFIG_CLR (0x000028f8)
+#define HW_PXP_ALU_B_LUT_CONFIG_TOG (0x000028fc)
+
+#define BP_PXP_ALU_B_LUT_CONFIG_RSVD0 6
+#define BM_PXP_ALU_B_LUT_CONFIG_RSVD0 0xFFFFFFC0
+#define BF_PXP_ALU_B_LUT_CONFIG_RSVD0(v) \
+ (((v) << 6) & BM_PXP_ALU_B_LUT_CONFIG_RSVD0)
+#define BP_PXP_ALU_B_LUT_CONFIG_MODE 4
+#define BM_PXP_ALU_B_LUT_CONFIG_MODE 0x00000030
+#define BF_PXP_ALU_B_LUT_CONFIG_MODE(v) \
+ (((v) << 4) & BM_PXP_ALU_B_LUT_CONFIG_MODE)
+#define BV_PXP_ALU_B_LUT_CONFIG_MODE__0 0x0
+#define BV_PXP_ALU_B_LUT_CONFIG_MODE__1 0x1
+#define BV_PXP_ALU_B_LUT_CONFIG_MODE__2 0x2
+#define BV_PXP_ALU_B_LUT_CONFIG_MODE__3 0x3
+#define BP_PXP_ALU_B_LUT_CONFIG_RSVD1 1
+#define BM_PXP_ALU_B_LUT_CONFIG_RSVD1 0x0000000E
+#define BF_PXP_ALU_B_LUT_CONFIG_RSVD1(v) \
+ (((v) << 1) & BM_PXP_ALU_B_LUT_CONFIG_RSVD1)
+#define BM_PXP_ALU_B_LUT_CONFIG_EN 0x00000001
+#define BF_PXP_ALU_B_LUT_CONFIG_EN(v) \
+ (((v) << 0) & BM_PXP_ALU_B_LUT_CONFIG_EN)
+
+#define HW_PXP_ALU_B_LUT_DATA0 (0x00002900)
+
+#define BP_PXP_ALU_B_LUT_DATA0_LUT_DATA_L 0
+#define BM_PXP_ALU_B_LUT_DATA0_LUT_DATA_L 0xFFFFFFFF
+#define BF_PXP_ALU_B_LUT_DATA0_LUT_DATA_L(v) (v)
+
+#define HW_PXP_ALU_B_LUT_DATA1 (0x00002910)
+
+#define BP_PXP_ALU_B_LUT_DATA1_LUT_DATA_H 0
+#define BM_PXP_ALU_B_LUT_DATA1_LUT_DATA_H 0xFFFFFFFF
+#define BF_PXP_ALU_B_LUT_DATA1_LUT_DATA_H(v) (v)
+
+#define HW_PXP_ALU_B_DBG (0x00002920)
+
+#define BP_PXP_ALU_B_DBG_DEBUG_SEL 24
+#define BM_PXP_ALU_B_DBG_DEBUG_SEL 0xFF000000
+#define BF_PXP_ALU_B_DBG_DEBUG_SEL(v) \
+ (((v) << 24) & BM_PXP_ALU_B_DBG_DEBUG_SEL)
+#define BP_PXP_ALU_B_DBG_DEBUG_VALUE 0
+#define BM_PXP_ALU_B_DBG_DEBUG_VALUE 0x00FFFFFF
+#define BF_PXP_ALU_B_DBG_DEBUG_VALUE(v) \
+ (((v) << 0) & BM_PXP_ALU_B_DBG_DEBUG_VALUE)
+
+#define HW_PXP_HIST_A_CTRL (0x00002a00)
+
+#define BP_PXP_HIST_A_CTRL_RSVD4 27
+#define BM_PXP_HIST_A_CTRL_RSVD4 0xF8000000
+#define BF_PXP_HIST_A_CTRL_RSVD4(v) \
+ (((v) << 27) & BM_PXP_HIST_A_CTRL_RSVD4)
+#define BP_PXP_HIST_A_CTRL_PIXEL_WIDTH 24
+#define BM_PXP_HIST_A_CTRL_PIXEL_WIDTH 0x07000000
+#define BF_PXP_HIST_A_CTRL_PIXEL_WIDTH(v) \
+ (((v) << 24) & BM_PXP_HIST_A_CTRL_PIXEL_WIDTH)
+#define BM_PXP_HIST_A_CTRL_RSVD3 0x00800000
+#define BF_PXP_HIST_A_CTRL_RSVD3(v) \
+ (((v) << 23) & BM_PXP_HIST_A_CTRL_RSVD3)
+#define BP_PXP_HIST_A_CTRL_PIXEL_OFFSET 16
+#define BM_PXP_HIST_A_CTRL_PIXEL_OFFSET 0x007F0000
+#define BF_PXP_HIST_A_CTRL_PIXEL_OFFSET(v) \
+ (((v) << 16) & BM_PXP_HIST_A_CTRL_PIXEL_OFFSET)
+#define BP_PXP_HIST_A_CTRL_RSVD2 13
+#define BM_PXP_HIST_A_CTRL_RSVD2 0x0000E000
+#define BF_PXP_HIST_A_CTRL_RSVD2(v) \
+ (((v) << 13) & BM_PXP_HIST_A_CTRL_RSVD2)
+#define BP_PXP_HIST_A_CTRL_STATUS 8
+#define BM_PXP_HIST_A_CTRL_STATUS 0x00001F00
+#define BF_PXP_HIST_A_CTRL_STATUS(v) \
+ (((v) << 8) & BM_PXP_HIST_A_CTRL_STATUS)
+#define BP_PXP_HIST_A_CTRL_RSVD1 5
+#define BM_PXP_HIST_A_CTRL_RSVD1 0x000000E0
+#define BF_PXP_HIST_A_CTRL_RSVD1(v) \
+ (((v) << 5) & BM_PXP_HIST_A_CTRL_RSVD1)
+#define BM_PXP_HIST_A_CTRL_CLEAR 0x00000010
+#define BF_PXP_HIST_A_CTRL_CLEAR(v) \
+ (((v) << 4) & BM_PXP_HIST_A_CTRL_CLEAR)
+#define BP_PXP_HIST_A_CTRL_RSVD0 1
+#define BM_PXP_HIST_A_CTRL_RSVD0 0x0000000E
+#define BF_PXP_HIST_A_CTRL_RSVD0(v) \
+ (((v) << 1) & BM_PXP_HIST_A_CTRL_RSVD0)
+#define BM_PXP_HIST_A_CTRL_ENABLE 0x00000001
+#define BF_PXP_HIST_A_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PXP_HIST_A_CTRL_ENABLE)
+
+#define HW_PXP_HIST_A_MASK (0x00002a10)
+
+#define BP_PXP_HIST_A_MASK_MASK_VALUE1 24
+#define BM_PXP_HIST_A_MASK_MASK_VALUE1 0xFF000000
+#define BF_PXP_HIST_A_MASK_MASK_VALUE1(v) \
+ (((v) << 24) & BM_PXP_HIST_A_MASK_MASK_VALUE1)
+#define BP_PXP_HIST_A_MASK_MASK_VALUE0 16
+#define BM_PXP_HIST_A_MASK_MASK_VALUE0 0x00FF0000
+#define BF_PXP_HIST_A_MASK_MASK_VALUE0(v) \
+ (((v) << 16) & BM_PXP_HIST_A_MASK_MASK_VALUE0)
+#define BP_PXP_HIST_A_MASK_MASK_WIDTH 13
+#define BM_PXP_HIST_A_MASK_MASK_WIDTH 0x0000E000
+#define BF_PXP_HIST_A_MASK_MASK_WIDTH(v) \
+ (((v) << 13) & BM_PXP_HIST_A_MASK_MASK_WIDTH)
+#define BP_PXP_HIST_A_MASK_MASK_OFFSET 6
+#define BM_PXP_HIST_A_MASK_MASK_OFFSET 0x00001FC0
+#define BF_PXP_HIST_A_MASK_MASK_OFFSET(v) \
+ (((v) << 6) & BM_PXP_HIST_A_MASK_MASK_OFFSET)
+#define BP_PXP_HIST_A_MASK_MASK_MODE 4
+#define BM_PXP_HIST_A_MASK_MASK_MODE 0x00000030
+#define BF_PXP_HIST_A_MASK_MASK_MODE(v) \
+ (((v) << 4) & BM_PXP_HIST_A_MASK_MASK_MODE)
+#define BV_PXP_HIST_A_MASK_MASK_MODE__EQUAL 0x0
+#define BV_PXP_HIST_A_MASK_MASK_MODE__NOT_EQUAL 0x1
+#define BV_PXP_HIST_A_MASK_MASK_MODE__INSIDE 0x2
+#define BV_PXP_HIST_A_MASK_MASK_MODE__OUTSIDE 0x3
+#define BP_PXP_HIST_A_MASK_RSVD0 1
+#define BM_PXP_HIST_A_MASK_RSVD0 0x0000000E
+#define BF_PXP_HIST_A_MASK_RSVD0(v) \
+ (((v) << 1) & BM_PXP_HIST_A_MASK_RSVD0)
+#define BM_PXP_HIST_A_MASK_MASK_EN 0x00000001
+#define BF_PXP_HIST_A_MASK_MASK_EN(v) \
+ (((v) << 0) & BM_PXP_HIST_A_MASK_MASK_EN)
+
+#define HW_PXP_HIST_A_BUF_SIZE (0x00002a20)
+
+#define BP_PXP_HIST_A_BUF_SIZE_RSVD0 28
+#define BM_PXP_HIST_A_BUF_SIZE_RSVD0 0xF0000000
+#define BF_PXP_HIST_A_BUF_SIZE_RSVD0(v) \
+ (((v) << 28) & BM_PXP_HIST_A_BUF_SIZE_RSVD0)
+#define BP_PXP_HIST_A_BUF_SIZE_HEIGHT 16
+#define BM_PXP_HIST_A_BUF_SIZE_HEIGHT 0x0FFF0000
+#define BF_PXP_HIST_A_BUF_SIZE_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_HIST_A_BUF_SIZE_HEIGHT)
+#define BP_PXP_HIST_A_BUF_SIZE_RSVD1 12
+#define BM_PXP_HIST_A_BUF_SIZE_RSVD1 0x0000F000
+#define BF_PXP_HIST_A_BUF_SIZE_RSVD1(v) \
+ (((v) << 12) & BM_PXP_HIST_A_BUF_SIZE_RSVD1)
+#define BP_PXP_HIST_A_BUF_SIZE_WIDTH 0
+#define BM_PXP_HIST_A_BUF_SIZE_WIDTH 0x00000FFF
+#define BF_PXP_HIST_A_BUF_SIZE_WIDTH(v) \
+ (((v) << 0) & BM_PXP_HIST_A_BUF_SIZE_WIDTH)
+
+#define HW_PXP_HIST_A_TOTAL_PIXEL (0x00002a30)
+
+#define BP_PXP_HIST_A_TOTAL_PIXEL_RSVD0 24
+#define BM_PXP_HIST_A_TOTAL_PIXEL_RSVD0 0xFF000000
+#define BF_PXP_HIST_A_TOTAL_PIXEL_RSVD0(v) \
+ (((v) << 24) & BM_PXP_HIST_A_TOTAL_PIXEL_RSVD0)
+#define BP_PXP_HIST_A_TOTAL_PIXEL_TOTAL_PIXEL 0
+#define BM_PXP_HIST_A_TOTAL_PIXEL_TOTAL_PIXEL 0x00FFFFFF
+#define BF_PXP_HIST_A_TOTAL_PIXEL_TOTAL_PIXEL(v) \
+ (((v) << 0) & BM_PXP_HIST_A_TOTAL_PIXEL_TOTAL_PIXEL)
+
+#define HW_PXP_HIST_A_ACTIVE_AREA_X (0x00002a40)
+
+#define BP_PXP_HIST_A_ACTIVE_AREA_X_RSVD1 28
+#define BM_PXP_HIST_A_ACTIVE_AREA_X_RSVD1 0xF0000000
+#define BF_PXP_HIST_A_ACTIVE_AREA_X_RSVD1(v) \
+ (((v) << 28) & BM_PXP_HIST_A_ACTIVE_AREA_X_RSVD1)
+#define BP_PXP_HIST_A_ACTIVE_AREA_X_MAX_X_OFFSET 16
+#define BM_PXP_HIST_A_ACTIVE_AREA_X_MAX_X_OFFSET 0x0FFF0000
+#define BF_PXP_HIST_A_ACTIVE_AREA_X_MAX_X_OFFSET(v) \
+ (((v) << 16) & BM_PXP_HIST_A_ACTIVE_AREA_X_MAX_X_OFFSET)
+#define BP_PXP_HIST_A_ACTIVE_AREA_X_RSVD0 12
+#define BM_PXP_HIST_A_ACTIVE_AREA_X_RSVD0 0x0000F000
+#define BF_PXP_HIST_A_ACTIVE_AREA_X_RSVD0(v) \
+ (((v) << 12) & BM_PXP_HIST_A_ACTIVE_AREA_X_RSVD0)
+#define BP_PXP_HIST_A_ACTIVE_AREA_X_MIN_X_OFFSET 0
+#define BM_PXP_HIST_A_ACTIVE_AREA_X_MIN_X_OFFSET 0x00000FFF
+#define BF_PXP_HIST_A_ACTIVE_AREA_X_MIN_X_OFFSET(v) \
+ (((v) << 0) & BM_PXP_HIST_A_ACTIVE_AREA_X_MIN_X_OFFSET)
+
+#define HW_PXP_HIST_A_ACTIVE_AREA_Y (0x00002a50)
+
+#define BP_PXP_HIST_A_ACTIVE_AREA_Y_RSVD1 28
+#define BM_PXP_HIST_A_ACTIVE_AREA_Y_RSVD1 0xF0000000
+#define BF_PXP_HIST_A_ACTIVE_AREA_Y_RSVD1(v) \
+ (((v) << 28) & BM_PXP_HIST_A_ACTIVE_AREA_Y_RSVD1)
+#define BP_PXP_HIST_A_ACTIVE_AREA_Y_MAX_Y_OFFSET 16
+#define BM_PXP_HIST_A_ACTIVE_AREA_Y_MAX_Y_OFFSET 0x0FFF0000
+#define BF_PXP_HIST_A_ACTIVE_AREA_Y_MAX_Y_OFFSET(v) \
+ (((v) << 16) & BM_PXP_HIST_A_ACTIVE_AREA_Y_MAX_Y_OFFSET)
+#define BP_PXP_HIST_A_ACTIVE_AREA_Y_RSVD0 12
+#define BM_PXP_HIST_A_ACTIVE_AREA_Y_RSVD0 0x0000F000
+#define BF_PXP_HIST_A_ACTIVE_AREA_Y_RSVD0(v) \
+ (((v) << 12) & BM_PXP_HIST_A_ACTIVE_AREA_Y_RSVD0)
+#define BP_PXP_HIST_A_ACTIVE_AREA_Y_MIN_Y_OFFSET 0
+#define BM_PXP_HIST_A_ACTIVE_AREA_Y_MIN_Y_OFFSET 0x00000FFF
+#define BF_PXP_HIST_A_ACTIVE_AREA_Y_MIN_Y_OFFSET(v) \
+ (((v) << 0) & BM_PXP_HIST_A_ACTIVE_AREA_Y_MIN_Y_OFFSET)
+
+#define HW_PXP_HIST_A_RAW_STAT0 (0x00002a60)
+
+#define BP_PXP_HIST_A_RAW_STAT0_STAT0 0
+#define BM_PXP_HIST_A_RAW_STAT0_STAT0 0xFFFFFFFF
+#define BF_PXP_HIST_A_RAW_STAT0_STAT0(v) (v)
+
+#define HW_PXP_HIST_A_RAW_STAT1 (0x00002a70)
+
+#define BP_PXP_HIST_A_RAW_STAT1_STAT1 0
+#define BM_PXP_HIST_A_RAW_STAT1_STAT1 0xFFFFFFFF
+#define BF_PXP_HIST_A_RAW_STAT1_STAT1(v) (v)
+
+#define HW_PXP_HIST_B_CTRL (0x00002a80)
+
+#define BP_PXP_HIST_B_CTRL_RSVD4 27
+#define BM_PXP_HIST_B_CTRL_RSVD4 0xF8000000
+#define BF_PXP_HIST_B_CTRL_RSVD4(v) \
+ (((v) << 27) & BM_PXP_HIST_B_CTRL_RSVD4)
+#define BP_PXP_HIST_B_CTRL_PIXEL_WIDTH 24
+#define BM_PXP_HIST_B_CTRL_PIXEL_WIDTH 0x07000000
+#define BF_PXP_HIST_B_CTRL_PIXEL_WIDTH(v) \
+ (((v) << 24) & BM_PXP_HIST_B_CTRL_PIXEL_WIDTH)
+#define BM_PXP_HIST_B_CTRL_RSVD3 0x00800000
+#define BF_PXP_HIST_B_CTRL_RSVD3(v) \
+ (((v) << 23) & BM_PXP_HIST_B_CTRL_RSVD3)
+#define BP_PXP_HIST_B_CTRL_PIXEL_OFFSET 16
+#define BM_PXP_HIST_B_CTRL_PIXEL_OFFSET 0x007F0000
+#define BF_PXP_HIST_B_CTRL_PIXEL_OFFSET(v) \
+ (((v) << 16) & BM_PXP_HIST_B_CTRL_PIXEL_OFFSET)
+#define BP_PXP_HIST_B_CTRL_RSVD2 13
+#define BM_PXP_HIST_B_CTRL_RSVD2 0x0000E000
+#define BF_PXP_HIST_B_CTRL_RSVD2(v) \
+ (((v) << 13) & BM_PXP_HIST_B_CTRL_RSVD2)
+#define BP_PXP_HIST_B_CTRL_STATUS 8
+#define BM_PXP_HIST_B_CTRL_STATUS 0x00001F00
+#define BF_PXP_HIST_B_CTRL_STATUS(v) \
+ (((v) << 8) & BM_PXP_HIST_B_CTRL_STATUS)
+#define BP_PXP_HIST_B_CTRL_RSVD1 5
+#define BM_PXP_HIST_B_CTRL_RSVD1 0x000000E0
+#define BF_PXP_HIST_B_CTRL_RSVD1(v) \
+ (((v) << 5) & BM_PXP_HIST_B_CTRL_RSVD1)
+#define BM_PXP_HIST_B_CTRL_CLEAR 0x00000010
+#define BF_PXP_HIST_B_CTRL_CLEAR(v) \
+ (((v) << 4) & BM_PXP_HIST_B_CTRL_CLEAR)
+#define BP_PXP_HIST_B_CTRL_RSVD0 1
+#define BM_PXP_HIST_B_CTRL_RSVD0 0x0000000E
+#define BF_PXP_HIST_B_CTRL_RSVD0(v) \
+ (((v) << 1) & BM_PXP_HIST_B_CTRL_RSVD0)
+#define BM_PXP_HIST_B_CTRL_ENABLE 0x00000001
+#define BF_PXP_HIST_B_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PXP_HIST_B_CTRL_ENABLE)
+
+#define HW_PXP_HIST_B_MASK (0x00002a90)
+
+#define BP_PXP_HIST_B_MASK_MASK_VALUE1 24
+#define BM_PXP_HIST_B_MASK_MASK_VALUE1 0xFF000000
+#define BF_PXP_HIST_B_MASK_MASK_VALUE1(v) \
+ (((v) << 24) & BM_PXP_HIST_B_MASK_MASK_VALUE1)
+#define BP_PXP_HIST_B_MASK_MASK_VALUE0 16
+#define BM_PXP_HIST_B_MASK_MASK_VALUE0 0x00FF0000
+#define BF_PXP_HIST_B_MASK_MASK_VALUE0(v) \
+ (((v) << 16) & BM_PXP_HIST_B_MASK_MASK_VALUE0)
+#define BP_PXP_HIST_B_MASK_MASK_WIDTH 13
+#define BM_PXP_HIST_B_MASK_MASK_WIDTH 0x0000E000
+#define BF_PXP_HIST_B_MASK_MASK_WIDTH(v) \
+ (((v) << 13) & BM_PXP_HIST_B_MASK_MASK_WIDTH)
+#define BP_PXP_HIST_B_MASK_MASK_OFFSET 6
+#define BM_PXP_HIST_B_MASK_MASK_OFFSET 0x00001FC0
+#define BF_PXP_HIST_B_MASK_MASK_OFFSET(v) \
+ (((v) << 6) & BM_PXP_HIST_B_MASK_MASK_OFFSET)
+#define BP_PXP_HIST_B_MASK_MASK_MODE 4
+#define BM_PXP_HIST_B_MASK_MASK_MODE 0x00000030
+#define BF_PXP_HIST_B_MASK_MASK_MODE(v) \
+ (((v) << 4) & BM_PXP_HIST_B_MASK_MASK_MODE)
+#define BV_PXP_HIST_B_MASK_MASK_MODE__EQUAL 0x0
+#define BV_PXP_HIST_B_MASK_MASK_MODE__NOT_EQUAL 0x1
+#define BV_PXP_HIST_B_MASK_MASK_MODE__INSIDE 0x2
+#define BV_PXP_HIST_B_MASK_MASK_MODE__OUTSIDE 0x3
+#define BP_PXP_HIST_B_MASK_RSVD0 1
+#define BM_PXP_HIST_B_MASK_RSVD0 0x0000000E
+#define BF_PXP_HIST_B_MASK_RSVD0(v) \
+ (((v) << 1) & BM_PXP_HIST_B_MASK_RSVD0)
+#define BM_PXP_HIST_B_MASK_MASK_EN 0x00000001
+#define BF_PXP_HIST_B_MASK_MASK_EN(v) \
+ (((v) << 0) & BM_PXP_HIST_B_MASK_MASK_EN)
+
+#define HW_PXP_HIST_B_BUF_SIZE (0x00002aa0)
+
+#define BP_PXP_HIST_B_BUF_SIZE_RSVD0 28
+#define BM_PXP_HIST_B_BUF_SIZE_RSVD0 0xF0000000
+#define BF_PXP_HIST_B_BUF_SIZE_RSVD0(v) \
+ (((v) << 28) & BM_PXP_HIST_B_BUF_SIZE_RSVD0)
+#define BP_PXP_HIST_B_BUF_SIZE_HEIGHT 16
+#define BM_PXP_HIST_B_BUF_SIZE_HEIGHT 0x0FFF0000
+#define BF_PXP_HIST_B_BUF_SIZE_HEIGHT(v) \
+ (((v) << 16) & BM_PXP_HIST_B_BUF_SIZE_HEIGHT)
+#define BP_PXP_HIST_B_BUF_SIZE_RSVD1 12
+#define BM_PXP_HIST_B_BUF_SIZE_RSVD1 0x0000F000
+#define BF_PXP_HIST_B_BUF_SIZE_RSVD1(v) \
+ (((v) << 12) & BM_PXP_HIST_B_BUF_SIZE_RSVD1)
+#define BP_PXP_HIST_B_BUF_SIZE_WIDTH 0
+#define BM_PXP_HIST_B_BUF_SIZE_WIDTH 0x00000FFF
+#define BF_PXP_HIST_B_BUF_SIZE_WIDTH(v) \
+ (((v) << 0) & BM_PXP_HIST_B_BUF_SIZE_WIDTH)
+
+#define HW_PXP_HIST_B_TOTAL_PIXEL (0x00002ab0)
+
+#define BP_PXP_HIST_B_TOTAL_PIXEL_RSVD0 24
+#define BM_PXP_HIST_B_TOTAL_PIXEL_RSVD0 0xFF000000
+#define BF_PXP_HIST_B_TOTAL_PIXEL_RSVD0(v) \
+ (((v) << 24) & BM_PXP_HIST_B_TOTAL_PIXEL_RSVD0)
+#define BP_PXP_HIST_B_TOTAL_PIXEL_TOTAL_PIXEL 0
+#define BM_PXP_HIST_B_TOTAL_PIXEL_TOTAL_PIXEL 0x00FFFFFF
+#define BF_PXP_HIST_B_TOTAL_PIXEL_TOTAL_PIXEL(v) \
+ (((v) << 0) & BM_PXP_HIST_B_TOTAL_PIXEL_TOTAL_PIXEL)
+
+#define HW_PXP_HIST_B_ACTIVE_AREA_X (0x00002ac0)
+
+#define BP_PXP_HIST_B_ACTIVE_AREA_X_RSVD1 28
+#define BM_PXP_HIST_B_ACTIVE_AREA_X_RSVD1 0xF0000000
+#define BF_PXP_HIST_B_ACTIVE_AREA_X_RSVD1(v) \
+ (((v) << 28) & BM_PXP_HIST_B_ACTIVE_AREA_X_RSVD1)
+#define BP_PXP_HIST_B_ACTIVE_AREA_X_MAX_X_OFFSET 16
+#define BM_PXP_HIST_B_ACTIVE_AREA_X_MAX_X_OFFSET 0x0FFF0000
+#define BF_PXP_HIST_B_ACTIVE_AREA_X_MAX_X_OFFSET(v) \
+ (((v) << 16) & BM_PXP_HIST_B_ACTIVE_AREA_X_MAX_X_OFFSET)
+#define BP_PXP_HIST_B_ACTIVE_AREA_X_RSVD0 12
+#define BM_PXP_HIST_B_ACTIVE_AREA_X_RSVD0 0x0000F000
+#define BF_PXP_HIST_B_ACTIVE_AREA_X_RSVD0(v) \
+ (((v) << 12) & BM_PXP_HIST_B_ACTIVE_AREA_X_RSVD0)
+#define BP_PXP_HIST_B_ACTIVE_AREA_X_MIN_X_OFFSET 0
+#define BM_PXP_HIST_B_ACTIVE_AREA_X_MIN_X_OFFSET 0x00000FFF
+#define BF_PXP_HIST_B_ACTIVE_AREA_X_MIN_X_OFFSET(v) \
+ (((v) << 0) & BM_PXP_HIST_B_ACTIVE_AREA_X_MIN_X_OFFSET)
+
+#define HW_PXP_HIST_B_ACTIVE_AREA_Y (0x00002ad0)
+
+#define BP_PXP_HIST_B_ACTIVE_AREA_Y_RSVD1 28
+#define BM_PXP_HIST_B_ACTIVE_AREA_Y_RSVD1 0xF0000000
+#define BF_PXP_HIST_B_ACTIVE_AREA_Y_RSVD1(v) \
+ (((v) << 28) & BM_PXP_HIST_B_ACTIVE_AREA_Y_RSVD1)
+#define BP_PXP_HIST_B_ACTIVE_AREA_Y_MAX_Y_OFFSET 16
+#define BM_PXP_HIST_B_ACTIVE_AREA_Y_MAX_Y_OFFSET 0x0FFF0000
+#define BF_PXP_HIST_B_ACTIVE_AREA_Y_MAX_Y_OFFSET(v) \
+ (((v) << 16) & BM_PXP_HIST_B_ACTIVE_AREA_Y_MAX_Y_OFFSET)
+#define BP_PXP_HIST_B_ACTIVE_AREA_Y_RSVD0 12
+#define BM_PXP_HIST_B_ACTIVE_AREA_Y_RSVD0 0x0000F000
+#define BF_PXP_HIST_B_ACTIVE_AREA_Y_RSVD0(v) \
+ (((v) << 12) & BM_PXP_HIST_B_ACTIVE_AREA_Y_RSVD0)
+#define BP_PXP_HIST_B_ACTIVE_AREA_Y_MIN_Y_OFFSET 0
+#define BM_PXP_HIST_B_ACTIVE_AREA_Y_MIN_Y_OFFSET 0x00000FFF
+#define BF_PXP_HIST_B_ACTIVE_AREA_Y_MIN_Y_OFFSET(v) \
+ (((v) << 0) & BM_PXP_HIST_B_ACTIVE_AREA_Y_MIN_Y_OFFSET)
+
+#define HW_PXP_HIST_B_RAW_STAT0 (0x00002ae0)
+
+#define BP_PXP_HIST_B_RAW_STAT0_STAT0 0
+#define BM_PXP_HIST_B_RAW_STAT0_STAT0 0xFFFFFFFF
+#define BF_PXP_HIST_B_RAW_STAT0_STAT0(v) (v)
+
+#define HW_PXP_HIST_B_RAW_STAT1 (0x00002af0)
+
+#define BP_PXP_HIST_B_RAW_STAT1_STAT1 0
+#define BM_PXP_HIST_B_RAW_STAT1_STAT1 0xFFFFFFFF
+#define BF_PXP_HIST_B_RAW_STAT1_STAT1(v) (v)
+
+#define HW_PXP_HIST2_PARAM (0x00002b00)
+
+#define BP_PXP_HIST2_PARAM_RSVD 16
+#define BM_PXP_HIST2_PARAM_RSVD 0xFFFF0000
+#define BF_PXP_HIST2_PARAM_RSVD(v) \
+ (((v) << 16) & BM_PXP_HIST2_PARAM_RSVD)
+#define BP_PXP_HIST2_PARAM_RSVD1 14
+#define BM_PXP_HIST2_PARAM_RSVD1 0x0000C000
+#define BF_PXP_HIST2_PARAM_RSVD1(v) \
+ (((v) << 14) & BM_PXP_HIST2_PARAM_RSVD1)
+#define BP_PXP_HIST2_PARAM_VALUE1 8
+#define BM_PXP_HIST2_PARAM_VALUE1 0x00003F00
+#define BF_PXP_HIST2_PARAM_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST2_PARAM_VALUE1)
+#define BP_PXP_HIST2_PARAM_RSVD0 6
+#define BM_PXP_HIST2_PARAM_RSVD0 0x000000C0
+#define BF_PXP_HIST2_PARAM_RSVD0(v) \
+ (((v) << 6) & BM_PXP_HIST2_PARAM_RSVD0)
+#define BP_PXP_HIST2_PARAM_VALUE0 0
+#define BM_PXP_HIST2_PARAM_VALUE0 0x0000003F
+#define BF_PXP_HIST2_PARAM_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST2_PARAM_VALUE0)
+
+#define HW_PXP_HIST4_PARAM (0x00002b10)
+
+#define BP_PXP_HIST4_PARAM_RSVD3 30
+#define BM_PXP_HIST4_PARAM_RSVD3 0xC0000000
+#define BF_PXP_HIST4_PARAM_RSVD3(v) \
+ (((v) << 30) & BM_PXP_HIST4_PARAM_RSVD3)
+#define BP_PXP_HIST4_PARAM_VALUE3 24
+#define BM_PXP_HIST4_PARAM_VALUE3 0x3F000000
+#define BF_PXP_HIST4_PARAM_VALUE3(v) \
+ (((v) << 24) & BM_PXP_HIST4_PARAM_VALUE3)
+#define BP_PXP_HIST4_PARAM_RSVD2 22
+#define BM_PXP_HIST4_PARAM_RSVD2 0x00C00000
+#define BF_PXP_HIST4_PARAM_RSVD2(v) \
+ (((v) << 22) & BM_PXP_HIST4_PARAM_RSVD2)
+#define BP_PXP_HIST4_PARAM_VALUE2 16
+#define BM_PXP_HIST4_PARAM_VALUE2 0x003F0000
+#define BF_PXP_HIST4_PARAM_VALUE2(v) \
+ (((v) << 16) & BM_PXP_HIST4_PARAM_VALUE2)
+#define BP_PXP_HIST4_PARAM_RSVD1 14
+#define BM_PXP_HIST4_PARAM_RSVD1 0x0000C000
+#define BF_PXP_HIST4_PARAM_RSVD1(v) \
+ (((v) << 14) & BM_PXP_HIST4_PARAM_RSVD1)
+#define BP_PXP_HIST4_PARAM_VALUE1 8
+#define BM_PXP_HIST4_PARAM_VALUE1 0x00003F00
+#define BF_PXP_HIST4_PARAM_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST4_PARAM_VALUE1)
+#define BP_PXP_HIST4_PARAM_RSVD0 6
+#define BM_PXP_HIST4_PARAM_RSVD0 0x000000C0
+#define BF_PXP_HIST4_PARAM_RSVD0(v) \
+ (((v) << 6) & BM_PXP_HIST4_PARAM_RSVD0)
+#define BP_PXP_HIST4_PARAM_VALUE0 0
+#define BM_PXP_HIST4_PARAM_VALUE0 0x0000003F
+#define BF_PXP_HIST4_PARAM_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST4_PARAM_VALUE0)
+
+#define HW_PXP_HIST8_PARAM0 (0x00002b20)
+
+#define BP_PXP_HIST8_PARAM0_RSVD3 30
+#define BM_PXP_HIST8_PARAM0_RSVD3 0xC0000000
+#define BF_PXP_HIST8_PARAM0_RSVD3(v) \
+ (((v) << 30) & BM_PXP_HIST8_PARAM0_RSVD3)
+#define BP_PXP_HIST8_PARAM0_VALUE3 24
+#define BM_PXP_HIST8_PARAM0_VALUE3 0x3F000000
+#define BF_PXP_HIST8_PARAM0_VALUE3(v) \
+ (((v) << 24) & BM_PXP_HIST8_PARAM0_VALUE3)
+#define BP_PXP_HIST8_PARAM0_RSVD2 22
+#define BM_PXP_HIST8_PARAM0_RSVD2 0x00C00000
+#define BF_PXP_HIST8_PARAM0_RSVD2(v) \
+ (((v) << 22) & BM_PXP_HIST8_PARAM0_RSVD2)
+#define BP_PXP_HIST8_PARAM0_VALUE2 16
+#define BM_PXP_HIST8_PARAM0_VALUE2 0x003F0000
+#define BF_PXP_HIST8_PARAM0_VALUE2(v) \
+ (((v) << 16) & BM_PXP_HIST8_PARAM0_VALUE2)
+#define BP_PXP_HIST8_PARAM0_RSVD1 14
+#define BM_PXP_HIST8_PARAM0_RSVD1 0x0000C000
+#define BF_PXP_HIST8_PARAM0_RSVD1(v) \
+ (((v) << 14) & BM_PXP_HIST8_PARAM0_RSVD1)
+#define BP_PXP_HIST8_PARAM0_VALUE1 8
+#define BM_PXP_HIST8_PARAM0_VALUE1 0x00003F00
+#define BF_PXP_HIST8_PARAM0_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST8_PARAM0_VALUE1)
+#define BP_PXP_HIST8_PARAM0_RSVD0 6
+#define BM_PXP_HIST8_PARAM0_RSVD0 0x000000C0
+#define BF_PXP_HIST8_PARAM0_RSVD0(v) \
+ (((v) << 6) & BM_PXP_HIST8_PARAM0_RSVD0)
+#define BP_PXP_HIST8_PARAM0_VALUE0 0
+#define BM_PXP_HIST8_PARAM0_VALUE0 0x0000003F
+#define BF_PXP_HIST8_PARAM0_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST8_PARAM0_VALUE0)
+
+#define HW_PXP_HIST8_PARAM1 (0x00002b30)
+
+#define BP_PXP_HIST8_PARAM1_RSVD7 30
+#define BM_PXP_HIST8_PARAM1_RSVD7 0xC0000000
+#define BF_PXP_HIST8_PARAM1_RSVD7(v) \
+ (((v) << 30) & BM_PXP_HIST8_PARAM1_RSVD7)
+#define BP_PXP_HIST8_PARAM1_VALUE7 24
+#define BM_PXP_HIST8_PARAM1_VALUE7 0x3F000000
+#define BF_PXP_HIST8_PARAM1_VALUE7(v) \
+ (((v) << 24) & BM_PXP_HIST8_PARAM1_VALUE7)
+#define BP_PXP_HIST8_PARAM1_RSVD6 22
+#define BM_PXP_HIST8_PARAM1_RSVD6 0x00C00000
+#define BF_PXP_HIST8_PARAM1_RSVD6(v) \
+ (((v) << 22) & BM_PXP_HIST8_PARAM1_RSVD6)
+#define BP_PXP_HIST8_PARAM1_VALUE6 16
+#define BM_PXP_HIST8_PARAM1_VALUE6 0x003F0000
+#define BF_PXP_HIST8_PARAM1_VALUE6(v) \
+ (((v) << 16) & BM_PXP_HIST8_PARAM1_VALUE6)
+#define BP_PXP_HIST8_PARAM1_RSVD5 14
+#define BM_PXP_HIST8_PARAM1_RSVD5 0x0000C000
+#define BF_PXP_HIST8_PARAM1_RSVD5(v) \
+ (((v) << 14) & BM_PXP_HIST8_PARAM1_RSVD5)
+#define BP_PXP_HIST8_PARAM1_VALUE5 8
+#define BM_PXP_HIST8_PARAM1_VALUE5 0x00003F00
+#define BF_PXP_HIST8_PARAM1_VALUE5(v) \
+ (((v) << 8) & BM_PXP_HIST8_PARAM1_VALUE5)
+#define BP_PXP_HIST8_PARAM1_RSVD4 6
+#define BM_PXP_HIST8_PARAM1_RSVD4 0x000000C0
+#define BF_PXP_HIST8_PARAM1_RSVD4(v) \
+ (((v) << 6) & BM_PXP_HIST8_PARAM1_RSVD4)
+#define BP_PXP_HIST8_PARAM1_VALUE4 0
+#define BM_PXP_HIST8_PARAM1_VALUE4 0x0000003F
+#define BF_PXP_HIST8_PARAM1_VALUE4(v) \
+ (((v) << 0) & BM_PXP_HIST8_PARAM1_VALUE4)
+
+#define HW_PXP_HIST16_PARAM0 (0x00002b40)
+
+#define BP_PXP_HIST16_PARAM0_RSVD3 30
+#define BM_PXP_HIST16_PARAM0_RSVD3 0xC0000000
+#define BF_PXP_HIST16_PARAM0_RSVD3(v) \
+ (((v) << 30) & BM_PXP_HIST16_PARAM0_RSVD3)
+#define BP_PXP_HIST16_PARAM0_VALUE3 24
+#define BM_PXP_HIST16_PARAM0_VALUE3 0x3F000000
+#define BF_PXP_HIST16_PARAM0_VALUE3(v) \
+ (((v) << 24) & BM_PXP_HIST16_PARAM0_VALUE3)
+#define BP_PXP_HIST16_PARAM0_RSVD2 22
+#define BM_PXP_HIST16_PARAM0_RSVD2 0x00C00000
+#define BF_PXP_HIST16_PARAM0_RSVD2(v) \
+ (((v) << 22) & BM_PXP_HIST16_PARAM0_RSVD2)
+#define BP_PXP_HIST16_PARAM0_VALUE2 16
+#define BM_PXP_HIST16_PARAM0_VALUE2 0x003F0000
+#define BF_PXP_HIST16_PARAM0_VALUE2(v) \
+ (((v) << 16) & BM_PXP_HIST16_PARAM0_VALUE2)
+#define BP_PXP_HIST16_PARAM0_RSVD1 14
+#define BM_PXP_HIST16_PARAM0_RSVD1 0x0000C000
+#define BF_PXP_HIST16_PARAM0_RSVD1(v) \
+ (((v) << 14) & BM_PXP_HIST16_PARAM0_RSVD1)
+#define BP_PXP_HIST16_PARAM0_VALUE1 8
+#define BM_PXP_HIST16_PARAM0_VALUE1 0x00003F00
+#define BF_PXP_HIST16_PARAM0_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST16_PARAM0_VALUE1)
+#define BP_PXP_HIST16_PARAM0_RSVD0 6
+#define BM_PXP_HIST16_PARAM0_RSVD0 0x000000C0
+#define BF_PXP_HIST16_PARAM0_RSVD0(v) \
+ (((v) << 6) & BM_PXP_HIST16_PARAM0_RSVD0)
+#define BP_PXP_HIST16_PARAM0_VALUE0 0
+#define BM_PXP_HIST16_PARAM0_VALUE0 0x0000003F
+#define BF_PXP_HIST16_PARAM0_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST16_PARAM0_VALUE0)
+
+#define HW_PXP_HIST16_PARAM1 (0x00002b50)
+
+#define BP_PXP_HIST16_PARAM1_RSVD7 30
+#define BM_PXP_HIST16_PARAM1_RSVD7 0xC0000000
+#define BF_PXP_HIST16_PARAM1_RSVD7(v) \
+ (((v) << 30) & BM_PXP_HIST16_PARAM1_RSVD7)
+#define BP_PXP_HIST16_PARAM1_VALUE7 24
+#define BM_PXP_HIST16_PARAM1_VALUE7 0x3F000000
+#define BF_PXP_HIST16_PARAM1_VALUE7(v) \
+ (((v) << 24) & BM_PXP_HIST16_PARAM1_VALUE7)
+#define BP_PXP_HIST16_PARAM1_RSVD6 22
+#define BM_PXP_HIST16_PARAM1_RSVD6 0x00C00000
+#define BF_PXP_HIST16_PARAM1_RSVD6(v) \
+ (((v) << 22) & BM_PXP_HIST16_PARAM1_RSVD6)
+#define BP_PXP_HIST16_PARAM1_VALUE6 16
+#define BM_PXP_HIST16_PARAM1_VALUE6 0x003F0000
+#define BF_PXP_HIST16_PARAM1_VALUE6(v) \
+ (((v) << 16) & BM_PXP_HIST16_PARAM1_VALUE6)
+#define BP_PXP_HIST16_PARAM1_RSVD5 14
+#define BM_PXP_HIST16_PARAM1_RSVD5 0x0000C000
+#define BF_PXP_HIST16_PARAM1_RSVD5(v) \
+ (((v) << 14) & BM_PXP_HIST16_PARAM1_RSVD5)
+#define BP_PXP_HIST16_PARAM1_VALUE5 8
+#define BM_PXP_HIST16_PARAM1_VALUE5 0x00003F00
+#define BF_PXP_HIST16_PARAM1_VALUE5(v) \
+ (((v) << 8) & BM_PXP_HIST16_PARAM1_VALUE5)
+#define BP_PXP_HIST16_PARAM1_RSVD4 6
+#define BM_PXP_HIST16_PARAM1_RSVD4 0x000000C0
+#define BF_PXP_HIST16_PARAM1_RSVD4(v) \
+ (((v) << 6) & BM_PXP_HIST16_PARAM1_RSVD4)
+#define BP_PXP_HIST16_PARAM1_VALUE4 0
+#define BM_PXP_HIST16_PARAM1_VALUE4 0x0000003F
+#define BF_PXP_HIST16_PARAM1_VALUE4(v) \
+ (((v) << 0) & BM_PXP_HIST16_PARAM1_VALUE4)
+
+#define HW_PXP_HIST16_PARAM2 (0x00002b60)
+
+#define BP_PXP_HIST16_PARAM2_RSVD11 30
+#define BM_PXP_HIST16_PARAM2_RSVD11 0xC0000000
+#define BF_PXP_HIST16_PARAM2_RSVD11(v) \
+ (((v) << 30) & BM_PXP_HIST16_PARAM2_RSVD11)
+#define BP_PXP_HIST16_PARAM2_VALUE11 24
+#define BM_PXP_HIST16_PARAM2_VALUE11 0x3F000000
+#define BF_PXP_HIST16_PARAM2_VALUE11(v) \
+ (((v) << 24) & BM_PXP_HIST16_PARAM2_VALUE11)
+#define BP_PXP_HIST16_PARAM2_RSVD10 22
+#define BM_PXP_HIST16_PARAM2_RSVD10 0x00C00000
+#define BF_PXP_HIST16_PARAM2_RSVD10(v) \
+ (((v) << 22) & BM_PXP_HIST16_PARAM2_RSVD10)
+#define BP_PXP_HIST16_PARAM2_VALUE10 16
+#define BM_PXP_HIST16_PARAM2_VALUE10 0x003F0000
+#define BF_PXP_HIST16_PARAM2_VALUE10(v) \
+ (((v) << 16) & BM_PXP_HIST16_PARAM2_VALUE10)
+#define BP_PXP_HIST16_PARAM2_RSVD9 14
+#define BM_PXP_HIST16_PARAM2_RSVD9 0x0000C000
+#define BF_PXP_HIST16_PARAM2_RSVD9(v) \
+ (((v) << 14) & BM_PXP_HIST16_PARAM2_RSVD9)
+#define BP_PXP_HIST16_PARAM2_VALUE9 8
+#define BM_PXP_HIST16_PARAM2_VALUE9 0x00003F00
+#define BF_PXP_HIST16_PARAM2_VALUE9(v) \
+ (((v) << 8) & BM_PXP_HIST16_PARAM2_VALUE9)
+#define BP_PXP_HIST16_PARAM2_RSVD8 6
+#define BM_PXP_HIST16_PARAM2_RSVD8 0x000000C0
+#define BF_PXP_HIST16_PARAM2_RSVD8(v) \
+ (((v) << 6) & BM_PXP_HIST16_PARAM2_RSVD8)
+#define BP_PXP_HIST16_PARAM2_VALUE8 0
+#define BM_PXP_HIST16_PARAM2_VALUE8 0x0000003F
+#define BF_PXP_HIST16_PARAM2_VALUE8(v) \
+ (((v) << 0) & BM_PXP_HIST16_PARAM2_VALUE8)
+
+#define HW_PXP_HIST16_PARAM3 (0x00002b70)
+
+#define BP_PXP_HIST16_PARAM3_RSVD15 30
+#define BM_PXP_HIST16_PARAM3_RSVD15 0xC0000000
+#define BF_PXP_HIST16_PARAM3_RSVD15(v) \
+ (((v) << 30) & BM_PXP_HIST16_PARAM3_RSVD15)
+#define BP_PXP_HIST16_PARAM3_VALUE15 24
+#define BM_PXP_HIST16_PARAM3_VALUE15 0x3F000000
+#define BF_PXP_HIST16_PARAM3_VALUE15(v) \
+ (((v) << 24) & BM_PXP_HIST16_PARAM3_VALUE15)
+#define BP_PXP_HIST16_PARAM3_RSVD14 22
+#define BM_PXP_HIST16_PARAM3_RSVD14 0x00C00000
+#define BF_PXP_HIST16_PARAM3_RSVD14(v) \
+ (((v) << 22) & BM_PXP_HIST16_PARAM3_RSVD14)
+#define BP_PXP_HIST16_PARAM3_VALUE14 16
+#define BM_PXP_HIST16_PARAM3_VALUE14 0x003F0000
+#define BF_PXP_HIST16_PARAM3_VALUE14(v) \
+ (((v) << 16) & BM_PXP_HIST16_PARAM3_VALUE14)
+#define BP_PXP_HIST16_PARAM3_RSVD13 14
+#define BM_PXP_HIST16_PARAM3_RSVD13 0x0000C000
+#define BF_PXP_HIST16_PARAM3_RSVD13(v) \
+ (((v) << 14) & BM_PXP_HIST16_PARAM3_RSVD13)
+#define BP_PXP_HIST16_PARAM3_VALUE13 8
+#define BM_PXP_HIST16_PARAM3_VALUE13 0x00003F00
+#define BF_PXP_HIST16_PARAM3_VALUE13(v) \
+ (((v) << 8) & BM_PXP_HIST16_PARAM3_VALUE13)
+#define BP_PXP_HIST16_PARAM3_RSVD12 6
+#define BM_PXP_HIST16_PARAM3_RSVD12 0x000000C0
+#define BF_PXP_HIST16_PARAM3_RSVD12(v) \
+ (((v) << 6) & BM_PXP_HIST16_PARAM3_RSVD12)
+#define BP_PXP_HIST16_PARAM3_VALUE12 0
+#define BM_PXP_HIST16_PARAM3_VALUE12 0x0000003F
+#define BF_PXP_HIST16_PARAM3_VALUE12(v) \
+ (((v) << 0) & BM_PXP_HIST16_PARAM3_VALUE12)
+
+#define HW_PXP_HIST32_PARAM0 (0x00002b80)
+
+#define BP_PXP_HIST32_PARAM0_RSVD3 30
+#define BM_PXP_HIST32_PARAM0_RSVD3 0xC0000000
+#define BF_PXP_HIST32_PARAM0_RSVD3(v) \
+ (((v) << 30) & BM_PXP_HIST32_PARAM0_RSVD3)
+#define BP_PXP_HIST32_PARAM0_VALUE3 24
+#define BM_PXP_HIST32_PARAM0_VALUE3 0x3F000000
+#define BF_PXP_HIST32_PARAM0_VALUE3(v) \
+ (((v) << 24) & BM_PXP_HIST32_PARAM0_VALUE3)
+#define BP_PXP_HIST32_PARAM0_RSVD2 22
+#define BM_PXP_HIST32_PARAM0_RSVD2 0x00C00000
+#define BF_PXP_HIST32_PARAM0_RSVD2(v) \
+ (((v) << 22) & BM_PXP_HIST32_PARAM0_RSVD2)
+#define BP_PXP_HIST32_PARAM0_VALUE2 16
+#define BM_PXP_HIST32_PARAM0_VALUE2 0x003F0000
+#define BF_PXP_HIST32_PARAM0_VALUE2(v) \
+ (((v) << 16) & BM_PXP_HIST32_PARAM0_VALUE2)
+#define BP_PXP_HIST32_PARAM0_RSVD1 14
+#define BM_PXP_HIST32_PARAM0_RSVD1 0x0000C000
+#define BF_PXP_HIST32_PARAM0_RSVD1(v) \
+ (((v) << 14) & BM_PXP_HIST32_PARAM0_RSVD1)
+#define BP_PXP_HIST32_PARAM0_VALUE1 8
+#define BM_PXP_HIST32_PARAM0_VALUE1 0x00003F00
+#define BF_PXP_HIST32_PARAM0_VALUE1(v) \
+ (((v) << 8) & BM_PXP_HIST32_PARAM0_VALUE1)
+#define BP_PXP_HIST32_PARAM0_RSVD0 6
+#define BM_PXP_HIST32_PARAM0_RSVD0 0x000000C0
+#define BF_PXP_HIST32_PARAM0_RSVD0(v) \
+ (((v) << 6) & BM_PXP_HIST32_PARAM0_RSVD0)
+#define BP_PXP_HIST32_PARAM0_VALUE0 0
+#define BM_PXP_HIST32_PARAM0_VALUE0 0x0000003F
+#define BF_PXP_HIST32_PARAM0_VALUE0(v) \
+ (((v) << 0) & BM_PXP_HIST32_PARAM0_VALUE0)
+
+#define HW_PXP_HIST32_PARAM1 (0x00002b90)
+
+#define BP_PXP_HIST32_PARAM1_RSVD7 30
+#define BM_PXP_HIST32_PARAM1_RSVD7 0xC0000000
+#define BF_PXP_HIST32_PARAM1_RSVD7(v) \
+ (((v) << 30) & BM_PXP_HIST32_PARAM1_RSVD7)
+#define BP_PXP_HIST32_PARAM1_VALUE7 24
+#define BM_PXP_HIST32_PARAM1_VALUE7 0x3F000000
+#define BF_PXP_HIST32_PARAM1_VALUE7(v) \
+ (((v) << 24) & BM_PXP_HIST32_PARAM1_VALUE7)
+#define BP_PXP_HIST32_PARAM1_RSVD6 22
+#define BM_PXP_HIST32_PARAM1_RSVD6 0x00C00000
+#define BF_PXP_HIST32_PARAM1_RSVD6(v) \
+ (((v) << 22) & BM_PXP_HIST32_PARAM1_RSVD6)
+#define BP_PXP_HIST32_PARAM1_VALUE6 16
+#define BM_PXP_HIST32_PARAM1_VALUE6 0x003F0000
+#define BF_PXP_HIST32_PARAM1_VALUE6(v) \
+ (((v) << 16) & BM_PXP_HIST32_PARAM1_VALUE6)
+#define BP_PXP_HIST32_PARAM1_RSVD5 14
+#define BM_PXP_HIST32_PARAM1_RSVD5 0x0000C000
+#define BF_PXP_HIST32_PARAM1_RSVD5(v) \
+ (((v) << 14) & BM_PXP_HIST32_PARAM1_RSVD5)
+#define BP_PXP_HIST32_PARAM1_VALUE5 8
+#define BM_PXP_HIST32_PARAM1_VALUE5 0x00003F00
+#define BF_PXP_HIST32_PARAM1_VALUE5(v) \
+ (((v) << 8) & BM_PXP_HIST32_PARAM1_VALUE5)
+#define BP_PXP_HIST32_PARAM1_RSVD4 6
+#define BM_PXP_HIST32_PARAM1_RSVD4 0x000000C0
+#define BF_PXP_HIST32_PARAM1_RSVD4(v) \
+ (((v) << 6) & BM_PXP_HIST32_PARAM1_RSVD4)
+#define BP_PXP_HIST32_PARAM1_VALUE4 0
+#define BM_PXP_HIST32_PARAM1_VALUE4 0x0000003F
+#define BF_PXP_HIST32_PARAM1_VALUE4(v) \
+ (((v) << 0) & BM_PXP_HIST32_PARAM1_VALUE4)
+
+#define HW_PXP_HIST32_PARAM2 (0x00002ba0)
+
+#define BP_PXP_HIST32_PARAM2_RSVD11 30
+#define BM_PXP_HIST32_PARAM2_RSVD11 0xC0000000
+#define BF_PXP_HIST32_PARAM2_RSVD11(v) \
+ (((v) << 30) & BM_PXP_HIST32_PARAM2_RSVD11)
+#define BP_PXP_HIST32_PARAM2_VALUE11 24
+#define BM_PXP_HIST32_PARAM2_VALUE11 0x3F000000
+#define BF_PXP_HIST32_PARAM2_VALUE11(v) \
+ (((v) << 24) & BM_PXP_HIST32_PARAM2_VALUE11)
+#define BP_PXP_HIST32_PARAM2_RSVD10 22
+#define BM_PXP_HIST32_PARAM2_RSVD10 0x00C00000
+#define BF_PXP_HIST32_PARAM2_RSVD10(v) \
+ (((v) << 22) & BM_PXP_HIST32_PARAM2_RSVD10)
+#define BP_PXP_HIST32_PARAM2_VALUE10 16
+#define BM_PXP_HIST32_PARAM2_VALUE10 0x003F0000
+#define BF_PXP_HIST32_PARAM2_VALUE10(v) \
+ (((v) << 16) & BM_PXP_HIST32_PARAM2_VALUE10)
+#define BP_PXP_HIST32_PARAM2_RSVD9 14
+#define BM_PXP_HIST32_PARAM2_RSVD9 0x0000C000
+#define BF_PXP_HIST32_PARAM2_RSVD9(v) \
+ (((v) << 14) & BM_PXP_HIST32_PARAM2_RSVD9)
+#define BP_PXP_HIST32_PARAM2_VALUE9 8
+#define BM_PXP_HIST32_PARAM2_VALUE9 0x00003F00
+#define BF_PXP_HIST32_PARAM2_VALUE9(v) \
+ (((v) << 8) & BM_PXP_HIST32_PARAM2_VALUE9)
+#define BP_PXP_HIST32_PARAM2_RSVD8 6
+#define BM_PXP_HIST32_PARAM2_RSVD8 0x000000C0
+#define BF_PXP_HIST32_PARAM2_RSVD8(v) \
+ (((v) << 6) & BM_PXP_HIST32_PARAM2_RSVD8)
+#define BP_PXP_HIST32_PARAM2_VALUE8 0
+#define BM_PXP_HIST32_PARAM2_VALUE8 0x0000003F
+#define BF_PXP_HIST32_PARAM2_VALUE8(v) \
+ (((v) << 0) & BM_PXP_HIST32_PARAM2_VALUE8)
+
+#define HW_PXP_HIST32_PARAM3 (0x00002bb0)
+
+#define BP_PXP_HIST32_PARAM3_RSVD15 30
+#define BM_PXP_HIST32_PARAM3_RSVD15 0xC0000000
+#define BF_PXP_HIST32_PARAM3_RSVD15(v) \
+ (((v) << 30) & BM_PXP_HIST32_PARAM3_RSVD15)
+#define BP_PXP_HIST32_PARAM3_VALUE15 24
+#define BM_PXP_HIST32_PARAM3_VALUE15 0x3F000000
+#define BF_PXP_HIST32_PARAM3_VALUE15(v) \
+ (((v) << 24) & BM_PXP_HIST32_PARAM3_VALUE15)
+#define BP_PXP_HIST32_PARAM3_RSVD14 22
+#define BM_PXP_HIST32_PARAM3_RSVD14 0x00C00000
+#define BF_PXP_HIST32_PARAM3_RSVD14(v) \
+ (((v) << 22) & BM_PXP_HIST32_PARAM3_RSVD14)
+#define BP_PXP_HIST32_PARAM3_VALUE14 16
+#define BM_PXP_HIST32_PARAM3_VALUE14 0x003F0000
+#define BF_PXP_HIST32_PARAM3_VALUE14(v) \
+ (((v) << 16) & BM_PXP_HIST32_PARAM3_VALUE14)
+#define BP_PXP_HIST32_PARAM3_RSVD13 14
+#define BM_PXP_HIST32_PARAM3_RSVD13 0x0000C000
+#define BF_PXP_HIST32_PARAM3_RSVD13(v) \
+ (((v) << 14) & BM_PXP_HIST32_PARAM3_RSVD13)
+#define BP_PXP_HIST32_PARAM3_VALUE13 8
+#define BM_PXP_HIST32_PARAM3_VALUE13 0x00003F00
+#define BF_PXP_HIST32_PARAM3_VALUE13(v) \
+ (((v) << 8) & BM_PXP_HIST32_PARAM3_VALUE13)
+#define BP_PXP_HIST32_PARAM3_RSVD12 6
+#define BM_PXP_HIST32_PARAM3_RSVD12 0x000000C0
+#define BF_PXP_HIST32_PARAM3_RSVD12(v) \
+ (((v) << 6) & BM_PXP_HIST32_PARAM3_RSVD12)
+#define BP_PXP_HIST32_PARAM3_VALUE12 0
+#define BM_PXP_HIST32_PARAM3_VALUE12 0x0000003F
+#define BF_PXP_HIST32_PARAM3_VALUE12(v) \
+ (((v) << 0) & BM_PXP_HIST32_PARAM3_VALUE12)
+
+#define HW_PXP_HIST32_PARAM4 (0x00002bc0)
+
+#define BP_PXP_HIST32_PARAM4_RSVD3 30
+#define BM_PXP_HIST32_PARAM4_RSVD3 0xC0000000
+#define BF_PXP_HIST32_PARAM4_RSVD3(v) \
+ (((v) << 30) & BM_PXP_HIST32_PARAM4_RSVD3)
+#define BP_PXP_HIST32_PARAM4_VALUE19 24
+#define BM_PXP_HIST32_PARAM4_VALUE19 0x3F000000
+#define BF_PXP_HIST32_PARAM4_VALUE19(v) \
+ (((v) << 24) & BM_PXP_HIST32_PARAM4_VALUE19)
+#define BP_PXP_HIST32_PARAM4_RSVD2 22
+#define BM_PXP_HIST32_PARAM4_RSVD2 0x00C00000
+#define BF_PXP_HIST32_PARAM4_RSVD2(v) \
+ (((v) << 22) & BM_PXP_HIST32_PARAM4_RSVD2)
+#define BP_PXP_HIST32_PARAM4_VALUE18 16
+#define BM_PXP_HIST32_PARAM4_VALUE18 0x003F0000
+#define BF_PXP_HIST32_PARAM4_VALUE18(v) \
+ (((v) << 16) & BM_PXP_HIST32_PARAM4_VALUE18)
+#define BP_PXP_HIST32_PARAM4_RSVD1 14
+#define BM_PXP_HIST32_PARAM4_RSVD1 0x0000C000
+#define BF_PXP_HIST32_PARAM4_RSVD1(v) \
+ (((v) << 14) & BM_PXP_HIST32_PARAM4_RSVD1)
+#define BP_PXP_HIST32_PARAM4_VALUE17 8
+#define BM_PXP_HIST32_PARAM4_VALUE17 0x00003F00
+#define BF_PXP_HIST32_PARAM4_VALUE17(v) \
+ (((v) << 8) & BM_PXP_HIST32_PARAM4_VALUE17)
+#define BP_PXP_HIST32_PARAM4_RSVD0 6
+#define BM_PXP_HIST32_PARAM4_RSVD0 0x000000C0
+#define BF_PXP_HIST32_PARAM4_RSVD0(v) \
+ (((v) << 6) & BM_PXP_HIST32_PARAM4_RSVD0)
+#define BP_PXP_HIST32_PARAM4_VALUE16 0
+#define BM_PXP_HIST32_PARAM4_VALUE16 0x0000003F
+#define BF_PXP_HIST32_PARAM4_VALUE16(v) \
+ (((v) << 0) & BM_PXP_HIST32_PARAM4_VALUE16)
+
+#define HW_PXP_HIST32_PARAM5 (0x00002bd0)
+
+#define BP_PXP_HIST32_PARAM5_RSVD7 30
+#define BM_PXP_HIST32_PARAM5_RSVD7 0xC0000000
+#define BF_PXP_HIST32_PARAM5_RSVD7(v) \
+ (((v) << 30) & BM_PXP_HIST32_PARAM5_RSVD7)
+#define BP_PXP_HIST32_PARAM5_VALUE23 24
+#define BM_PXP_HIST32_PARAM5_VALUE23 0x3F000000
+#define BF_PXP_HIST32_PARAM5_VALUE23(v) \
+ (((v) << 24) & BM_PXP_HIST32_PARAM5_VALUE23)
+#define BP_PXP_HIST32_PARAM5_RSVD6 22
+#define BM_PXP_HIST32_PARAM5_RSVD6 0x00C00000
+#define BF_PXP_HIST32_PARAM5_RSVD6(v) \
+ (((v) << 22) & BM_PXP_HIST32_PARAM5_RSVD6)
+#define BP_PXP_HIST32_PARAM5_VALUE22 16
+#define BM_PXP_HIST32_PARAM5_VALUE22 0x003F0000
+#define BF_PXP_HIST32_PARAM5_VALUE22(v) \
+ (((v) << 16) & BM_PXP_HIST32_PARAM5_VALUE22)
+#define BP_PXP_HIST32_PARAM5_RSVD5 14
+#define BM_PXP_HIST32_PARAM5_RSVD5 0x0000C000
+#define BF_PXP_HIST32_PARAM5_RSVD5(v) \
+ (((v) << 14) & BM_PXP_HIST32_PARAM5_RSVD5)
+#define BP_PXP_HIST32_PARAM5_VALUE21 8
+#define BM_PXP_HIST32_PARAM5_VALUE21 0x00003F00
+#define BF_PXP_HIST32_PARAM5_VALUE21(v) \
+ (((v) << 8) & BM_PXP_HIST32_PARAM5_VALUE21)
+#define BP_PXP_HIST32_PARAM5_RSVD4 6
+#define BM_PXP_HIST32_PARAM5_RSVD4 0x000000C0
+#define BF_PXP_HIST32_PARAM5_RSVD4(v) \
+ (((v) << 6) & BM_PXP_HIST32_PARAM5_RSVD4)
+#define BP_PXP_HIST32_PARAM5_VALUE20 0
+#define BM_PXP_HIST32_PARAM5_VALUE20 0x0000003F
+#define BF_PXP_HIST32_PARAM5_VALUE20(v) \
+ (((v) << 0) & BM_PXP_HIST32_PARAM5_VALUE20)
+
+#define HW_PXP_HIST32_PARAM6 (0x00002be0)
+
+#define BP_PXP_HIST32_PARAM6_RSVD11 30
+#define BM_PXP_HIST32_PARAM6_RSVD11 0xC0000000
+#define BF_PXP_HIST32_PARAM6_RSVD11(v) \
+ (((v) << 30) & BM_PXP_HIST32_PARAM6_RSVD11)
+#define BP_PXP_HIST32_PARAM6_VALUE27 24
+#define BM_PXP_HIST32_PARAM6_VALUE27 0x3F000000
+#define BF_PXP_HIST32_PARAM6_VALUE27(v) \
+ (((v) << 24) & BM_PXP_HIST32_PARAM6_VALUE27)
+#define BP_PXP_HIST32_PARAM6_RSVD10 22
+#define BM_PXP_HIST32_PARAM6_RSVD10 0x00C00000
+#define BF_PXP_HIST32_PARAM6_RSVD10(v) \
+ (((v) << 22) & BM_PXP_HIST32_PARAM6_RSVD10)
+#define BP_PXP_HIST32_PARAM6_VALUE26 16
+#define BM_PXP_HIST32_PARAM6_VALUE26 0x003F0000
+#define BF_PXP_HIST32_PARAM6_VALUE26(v) \
+ (((v) << 16) & BM_PXP_HIST32_PARAM6_VALUE26)
+#define BP_PXP_HIST32_PARAM6_RSVD9 14
+#define BM_PXP_HIST32_PARAM6_RSVD9 0x0000C000
+#define BF_PXP_HIST32_PARAM6_RSVD9(v) \
+ (((v) << 14) & BM_PXP_HIST32_PARAM6_RSVD9)
+#define BP_PXP_HIST32_PARAM6_VALUE25 8
+#define BM_PXP_HIST32_PARAM6_VALUE25 0x00003F00
+#define BF_PXP_HIST32_PARAM6_VALUE25(v) \
+ (((v) << 8) & BM_PXP_HIST32_PARAM6_VALUE25)
+#define BP_PXP_HIST32_PARAM6_RSVD8 6
+#define BM_PXP_HIST32_PARAM6_RSVD8 0x000000C0
+#define BF_PXP_HIST32_PARAM6_RSVD8(v) \
+ (((v) << 6) & BM_PXP_HIST32_PARAM6_RSVD8)
+#define BP_PXP_HIST32_PARAM6_VALUE24 0
+#define BM_PXP_HIST32_PARAM6_VALUE24 0x0000003F
+#define BF_PXP_HIST32_PARAM6_VALUE24(v) \
+ (((v) << 0) & BM_PXP_HIST32_PARAM6_VALUE24)
+
+#define HW_PXP_HIST32_PARAM7 (0x00002bf0)
+
+#define BP_PXP_HIST32_PARAM7_RSVD15 30
+#define BM_PXP_HIST32_PARAM7_RSVD15 0xC0000000
+#define BF_PXP_HIST32_PARAM7_RSVD15(v) \
+ (((v) << 30) & BM_PXP_HIST32_PARAM7_RSVD15)
+#define BP_PXP_HIST32_PARAM7_VALUE31 24
+#define BM_PXP_HIST32_PARAM7_VALUE31 0x3F000000
+#define BF_PXP_HIST32_PARAM7_VALUE31(v) \
+ (((v) << 24) & BM_PXP_HIST32_PARAM7_VALUE31)
+#define BP_PXP_HIST32_PARAM7_RSVD14 22
+#define BM_PXP_HIST32_PARAM7_RSVD14 0x00C00000
+#define BF_PXP_HIST32_PARAM7_RSVD14(v) \
+ (((v) << 22) & BM_PXP_HIST32_PARAM7_RSVD14)
+#define BP_PXP_HIST32_PARAM7_VALUE30 16
+#define BM_PXP_HIST32_PARAM7_VALUE30 0x003F0000
+#define BF_PXP_HIST32_PARAM7_VALUE30(v) \
+ (((v) << 16) & BM_PXP_HIST32_PARAM7_VALUE30)
+#define BP_PXP_HIST32_PARAM7_RSVD13 14
+#define BM_PXP_HIST32_PARAM7_RSVD13 0x0000C000
+#define BF_PXP_HIST32_PARAM7_RSVD13(v) \
+ (((v) << 14) & BM_PXP_HIST32_PARAM7_RSVD13)
+#define BP_PXP_HIST32_PARAM7_VALUE29 8
+#define BM_PXP_HIST32_PARAM7_VALUE29 0x00003F00
+#define BF_PXP_HIST32_PARAM7_VALUE29(v) \
+ (((v) << 8) & BM_PXP_HIST32_PARAM7_VALUE29)
+#define BP_PXP_HIST32_PARAM7_RSVD2 6
+#define BM_PXP_HIST32_PARAM7_RSVD2 0x000000C0
+#define BF_PXP_HIST32_PARAM7_RSVD2(v) \
+ (((v) << 6) & BM_PXP_HIST32_PARAM7_RSVD2)
+#define BP_PXP_HIST32_PARAM7_VALUE28 0
+#define BM_PXP_HIST32_PARAM7_VALUE28 0x0000003F
+#define BF_PXP_HIST32_PARAM7_VALUE28(v) \
+ (((v) << 0) & BM_PXP_HIST32_PARAM7_VALUE28)
+
+#define HW_PXP_COMP_CTRL (0x00002c00)
+#define HW_PXP_COMP_CTRL_SET (0x00002c04)
+#define HW_PXP_COMP_CTRL_CLR (0x00002c08)
+#define HW_PXP_COMP_CTRL_TOG (0x00002c0c)
+
+#define BP_PXP_COMP_CTRL_RSVD0 9
+#define BM_PXP_COMP_CTRL_RSVD0 0xFFFFFE00
+#define BF_PXP_COMP_CTRL_RSVD0(v) \
+ (((v) << 9) & BM_PXP_COMP_CTRL_RSVD0)
+#define BM_PXP_COMP_CTRL_SW_RESET 0x00000100
+#define BF_PXP_COMP_CTRL_SW_RESET(v) \
+ (((v) << 8) & BM_PXP_COMP_CTRL_SW_RESET)
+#define BP_PXP_COMP_CTRL_RSVD1 1
+#define BM_PXP_COMP_CTRL_RSVD1 0x000000FE
+#define BF_PXP_COMP_CTRL_RSVD1(v) \
+ (((v) << 1) & BM_PXP_COMP_CTRL_RSVD1)
+#define BM_PXP_COMP_CTRL_START 0x00000001
+#define BF_PXP_COMP_CTRL_START(v) \
+ (((v) << 0) & BM_PXP_COMP_CTRL_START)
+
+#define HW_PXP_COMP_FORMAT0 (0x00002c10)
+#define HW_PXP_COMP_FORMAT0_SET (0x00002c14)
+#define HW_PXP_COMP_FORMAT0_CLR (0x00002c18)
+#define HW_PXP_COMP_FORMAT0_TOG (0x00002c1c)
+
+#define BP_PXP_COMP_FORMAT0_RSVD0 28
+#define BM_PXP_COMP_FORMAT0_RSVD0 0xF0000000
+#define BF_PXP_COMP_FORMAT0_RSVD0(v) \
+ (((v) << 28) & BM_PXP_COMP_FORMAT0_RSVD0)
+#define BP_PXP_COMP_FORMAT0_PIXEL_PITCH_64B 16
+#define BM_PXP_COMP_FORMAT0_PIXEL_PITCH_64B 0x0FFF0000
+#define BF_PXP_COMP_FORMAT0_PIXEL_PITCH_64B(v) \
+ (((v) << 16) & BM_PXP_COMP_FORMAT0_PIXEL_PITCH_64B)
+#define BP_PXP_COMP_FORMAT0_RSVD1 10
+#define BM_PXP_COMP_FORMAT0_RSVD1 0x0000FC00
+#define BF_PXP_COMP_FORMAT0_RSVD1(v) \
+ (((v) << 10) & BM_PXP_COMP_FORMAT0_RSVD1)
+#define BP_PXP_COMP_FORMAT0_MASK_INDEX 8
+#define BM_PXP_COMP_FORMAT0_MASK_INDEX 0x00000300
+#define BF_PXP_COMP_FORMAT0_MASK_INDEX(v) \
+ (((v) << 8) & BM_PXP_COMP_FORMAT0_MASK_INDEX)
+#define BP_PXP_COMP_FORMAT0_RSVD2 6
+#define BM_PXP_COMP_FORMAT0_RSVD2 0x000000C0
+#define BF_PXP_COMP_FORMAT0_RSVD2(v) \
+ (((v) << 6) & BM_PXP_COMP_FORMAT0_RSVD2)
+#define BP_PXP_COMP_FORMAT0_FIELD_NUM 4
+#define BM_PXP_COMP_FORMAT0_FIELD_NUM 0x00000030
+#define BF_PXP_COMP_FORMAT0_FIELD_NUM(v) \
+ (((v) << 4) & BM_PXP_COMP_FORMAT0_FIELD_NUM)
+#define BP_PXP_COMP_FORMAT0_RSVD3 1
+#define BM_PXP_COMP_FORMAT0_RSVD3 0x0000000E
+#define BF_PXP_COMP_FORMAT0_RSVD3(v) \
+ (((v) << 1) & BM_PXP_COMP_FORMAT0_RSVD3)
+#define BM_PXP_COMP_FORMAT0_FLAG_32B 0x00000001
+#define BF_PXP_COMP_FORMAT0_FLAG_32B(v) \
+ (((v) << 0) & BM_PXP_COMP_FORMAT0_FLAG_32B)
+
+#define HW_PXP_COMP_FORMAT1 (0x00002c20)
+
+#define BP_PXP_COMP_FORMAT1_D_LEN 29
+#define BM_PXP_COMP_FORMAT1_D_LEN 0xE0000000
+#define BF_PXP_COMP_FORMAT1_D_LEN(v) \
+ (((v) << 29) & BM_PXP_COMP_FORMAT1_D_LEN)
+#define BP_PXP_COMP_FORMAT1_D_OFFSET 24
+#define BM_PXP_COMP_FORMAT1_D_OFFSET 0x1F000000
+#define BF_PXP_COMP_FORMAT1_D_OFFSET(v) \
+ (((v) << 24) & BM_PXP_COMP_FORMAT1_D_OFFSET)
+#define BP_PXP_COMP_FORMAT1_C_LEN 21
+#define BM_PXP_COMP_FORMAT1_C_LEN 0x00E00000
+#define BF_PXP_COMP_FORMAT1_C_LEN(v) \
+ (((v) << 21) & BM_PXP_COMP_FORMAT1_C_LEN)
+#define BP_PXP_COMP_FORMAT1_C_OFFSET 16
+#define BM_PXP_COMP_FORMAT1_C_OFFSET 0x001F0000
+#define BF_PXP_COMP_FORMAT1_C_OFFSET(v) \
+ (((v) << 16) & BM_PXP_COMP_FORMAT1_C_OFFSET)
+#define BP_PXP_COMP_FORMAT1_B_LEN 13
+#define BM_PXP_COMP_FORMAT1_B_LEN 0x0000E000
+#define BF_PXP_COMP_FORMAT1_B_LEN(v) \
+ (((v) << 13) & BM_PXP_COMP_FORMAT1_B_LEN)
+#define BP_PXP_COMP_FORMAT1_B_OFFSET 8
+#define BM_PXP_COMP_FORMAT1_B_OFFSET 0x00001F00
+#define BF_PXP_COMP_FORMAT1_B_OFFSET(v) \
+ (((v) << 8) & BM_PXP_COMP_FORMAT1_B_OFFSET)
+#define BP_PXP_COMP_FORMAT1_A_LEN 5
+#define BM_PXP_COMP_FORMAT1_A_LEN 0x000000E0
+#define BF_PXP_COMP_FORMAT1_A_LEN(v) \
+ (((v) << 5) & BM_PXP_COMP_FORMAT1_A_LEN)
+#define BP_PXP_COMP_FORMAT1_A_OFFSET 0
+#define BM_PXP_COMP_FORMAT1_A_OFFSET 0x0000001F
+#define BF_PXP_COMP_FORMAT1_A_OFFSET(v) \
+ (((v) << 0) & BM_PXP_COMP_FORMAT1_A_OFFSET)
+
+#define HW_PXP_COMP_FORMAT2 (0x00002c30)
+
+#define BP_PXP_COMP_FORMAT2_RSVD 16
+#define BM_PXP_COMP_FORMAT2_RSVD 0xFFFF0000
+#define BF_PXP_COMP_FORMAT2_RSVD(v) \
+ (((v) << 16) & BM_PXP_COMP_FORMAT2_RSVD)
+#define BP_PXP_COMP_FORMAT2_D_RUNLEN 12
+#define BM_PXP_COMP_FORMAT2_D_RUNLEN 0x0000F000
+#define BF_PXP_COMP_FORMAT2_D_RUNLEN(v) \
+ (((v) << 12) & BM_PXP_COMP_FORMAT2_D_RUNLEN)
+#define BP_PXP_COMP_FORMAT2_C_RUNLEN 8
+#define BM_PXP_COMP_FORMAT2_C_RUNLEN 0x00000F00
+#define BF_PXP_COMP_FORMAT2_C_RUNLEN(v) \
+ (((v) << 8) & BM_PXP_COMP_FORMAT2_C_RUNLEN)
+#define BP_PXP_COMP_FORMAT2_B_RUNLEN 4
+#define BM_PXP_COMP_FORMAT2_B_RUNLEN 0x000000F0
+#define BF_PXP_COMP_FORMAT2_B_RUNLEN(v) \
+ (((v) << 4) & BM_PXP_COMP_FORMAT2_B_RUNLEN)
+#define BP_PXP_COMP_FORMAT2_A_RUNLEN 0
+#define BM_PXP_COMP_FORMAT2_A_RUNLEN 0x0000000F
+#define BF_PXP_COMP_FORMAT2_A_RUNLEN(v) \
+ (((v) << 0) & BM_PXP_COMP_FORMAT2_A_RUNLEN)
+
+#define HW_PXP_COMP_MASK0 (0x00002c40)
+
+#define BP_PXP_COMP_MASK0_VLD_MASK_LOW 0
+#define BM_PXP_COMP_MASK0_VLD_MASK_LOW 0xFFFFFFFF
+#define BF_PXP_COMP_MASK0_VLD_MASK_LOW(v) (v)
+
+#define HW_PXP_COMP_MASK1 (0x00002c50)
+
+#define BP_PXP_COMP_MASK1_VLD_MASK_HIGH 0
+#define BM_PXP_COMP_MASK1_VLD_MASK_HIGH 0xFFFFFFFF
+#define BF_PXP_COMP_MASK1_VLD_MASK_HIGH(v) (v)
+
+#define HW_PXP_COMP_BUFFER_SIZE (0x00002c60)
+
+#define BP_PXP_COMP_BUFFER_SIZE_RSVD0 29
+#define BM_PXP_COMP_BUFFER_SIZE_RSVD0 0xE0000000
+#define BF_PXP_COMP_BUFFER_SIZE_RSVD0(v) \
+ (((v) << 29) & BM_PXP_COMP_BUFFER_SIZE_RSVD0)
+#define BP_PXP_COMP_BUFFER_SIZE_PIXEL_WIDTH 16
+#define BM_PXP_COMP_BUFFER_SIZE_PIXEL_WIDTH 0x1FFF0000
+#define BF_PXP_COMP_BUFFER_SIZE_PIXEL_WIDTH(v) \
+ (((v) << 16) & BM_PXP_COMP_BUFFER_SIZE_PIXEL_WIDTH)
+#define BP_PXP_COMP_BUFFER_SIZE_RSVD1 13
+#define BM_PXP_COMP_BUFFER_SIZE_RSVD1 0x0000E000
+#define BF_PXP_COMP_BUFFER_SIZE_RSVD1(v) \
+ (((v) << 13) & BM_PXP_COMP_BUFFER_SIZE_RSVD1)
+#define BP_PXP_COMP_BUFFER_SIZE_PIXEL_LENGTH 0
+#define BM_PXP_COMP_BUFFER_SIZE_PIXEL_LENGTH 0x00001FFF
+#define BF_PXP_COMP_BUFFER_SIZE_PIXEL_LENGTH(v) \
+ (((v) << 0) & BM_PXP_COMP_BUFFER_SIZE_PIXEL_LENGTH)
+
+#define HW_PXP_COMP_SOURCE (0x00002c70)
+
+#define BP_PXP_COMP_SOURCE_SOURCE_ADDR 0
+#define BM_PXP_COMP_SOURCE_SOURCE_ADDR 0xFFFFFFFF
+#define BF_PXP_COMP_SOURCE_SOURCE_ADDR(v) (v)
+
+#define HW_PXP_COMP_TARGET (0x00002c80)
+
+#define BP_PXP_COMP_TARGET_TARGET_ADDR 0
+#define BM_PXP_COMP_TARGET_TARGET_ADDR 0xFFFFFFFF
+#define BF_PXP_COMP_TARGET_TARGET_ADDR(v) (v)
+
+#define HW_PXP_COMP_BUFFER_A (0x00002c90)
+
+#define BP_PXP_COMP_BUFFER_A_A_SRAM_ADDR 0
+#define BM_PXP_COMP_BUFFER_A_A_SRAM_ADDR 0xFFFFFFFF
+#define BF_PXP_COMP_BUFFER_A_A_SRAM_ADDR(v) (v)
+
+#define HW_PXP_COMP_BUFFER_B (0x00002ca0)
+
+#define BP_PXP_COMP_BUFFER_B_B_SRAM_ADDR 0
+#define BM_PXP_COMP_BUFFER_B_B_SRAM_ADDR 0xFFFFFFFF
+#define BF_PXP_COMP_BUFFER_B_B_SRAM_ADDR(v) (v)
+
+#define HW_PXP_COMP_BUFFER_C (0x00002cb0)
+
+#define BP_PXP_COMP_BUFFER_C_C_SRAM_ADDR 0
+#define BM_PXP_COMP_BUFFER_C_C_SRAM_ADDR 0xFFFFFFFF
+#define BF_PXP_COMP_BUFFER_C_C_SRAM_ADDR(v) (v)
+
+#define HW_PXP_COMP_BUFFER_D (0x00002cc0)
+
+#define BP_PXP_COMP_BUFFER_D_D_SRAM_ADDR 0
+#define BM_PXP_COMP_BUFFER_D_D_SRAM_ADDR 0xFFFFFFFF
+#define BF_PXP_COMP_BUFFER_D_D_SRAM_ADDR(v) (v)
+
+#define HW_PXP_COMP_DEBUG (0x00002cd0)
+
+#define BP_PXP_COMP_DEBUG_DEBUG_VALUE 8
+#define BM_PXP_COMP_DEBUG_DEBUG_VALUE 0xFFFFFF00
+#define BF_PXP_COMP_DEBUG_DEBUG_VALUE(v) \
+ (((v) << 8) & BM_PXP_COMP_DEBUG_DEBUG_VALUE)
+#define BP_PXP_COMP_DEBUG_DEBUG_SEL 0
+#define BM_PXP_COMP_DEBUG_DEBUG_SEL 0x000000FF
+#define BF_PXP_COMP_DEBUG_DEBUG_SEL(v) \
+ (((v) << 0) & BM_PXP_COMP_DEBUG_DEBUG_SEL)
+
+#define HW_PXP_BUS_MUX (0x00002ce0)
+
+#define BP_PXP_BUS_MUX_RSVD1 24
+#define BM_PXP_BUS_MUX_RSVD1 0xFF000000
+#define BF_PXP_BUS_MUX_RSVD1(v) \
+ (((v) << 24) & BM_PXP_BUS_MUX_RSVD1)
+#define BP_PXP_BUS_MUX_WR_SEL 16
+#define BM_PXP_BUS_MUX_WR_SEL 0x00FF0000
+#define BF_PXP_BUS_MUX_WR_SEL(v) \
+ (((v) << 16) & BM_PXP_BUS_MUX_WR_SEL)
+#define BP_PXP_BUS_MUX_RSVD0 8
+#define BM_PXP_BUS_MUX_RSVD0 0x0000FF00
+#define BF_PXP_BUS_MUX_RSVD0(v) \
+ (((v) << 8) & BM_PXP_BUS_MUX_RSVD0)
+#define BP_PXP_BUS_MUX_RD_SEL 0
+#define BM_PXP_BUS_MUX_RD_SEL 0x000000FF
+#define BF_PXP_BUS_MUX_RD_SEL(v) \
+ (((v) << 0) & BM_PXP_BUS_MUX_RD_SEL)
+
+#define HW_PXP_HANDSHAKE_READY_MUX0 (0x00002cf0)
+
+#define BP_PXP_HANDSHAKE_READY_MUX0_HSK7 28
+#define BM_PXP_HANDSHAKE_READY_MUX0_HSK7 0xF0000000
+#define BF_PXP_HANDSHAKE_READY_MUX0_HSK7(v) \
+ (((v) << 28) & BM_PXP_HANDSHAKE_READY_MUX0_HSK7)
+#define BP_PXP_HANDSHAKE_READY_MUX0_HSK6 24
+#define BM_PXP_HANDSHAKE_READY_MUX0_HSK6 0x0F000000
+#define BF_PXP_HANDSHAKE_READY_MUX0_HSK6(v) \
+ (((v) << 24) & BM_PXP_HANDSHAKE_READY_MUX0_HSK6)
+#define BP_PXP_HANDSHAKE_READY_MUX0_HSK5 20
+#define BM_PXP_HANDSHAKE_READY_MUX0_HSK5 0x00F00000
+#define BF_PXP_HANDSHAKE_READY_MUX0_HSK5(v) \
+ (((v) << 20) & BM_PXP_HANDSHAKE_READY_MUX0_HSK5)
+#define BP_PXP_HANDSHAKE_READY_MUX0_HSK4 16
+#define BM_PXP_HANDSHAKE_READY_MUX0_HSK4 0x000F0000
+#define BF_PXP_HANDSHAKE_READY_MUX0_HSK4(v) \
+ (((v) << 16) & BM_PXP_HANDSHAKE_READY_MUX0_HSK4)
+#define BP_PXP_HANDSHAKE_READY_MUX0_HSK3 12
+#define BM_PXP_HANDSHAKE_READY_MUX0_HSK3 0x0000F000
+#define BF_PXP_HANDSHAKE_READY_MUX0_HSK3(v) \
+ (((v) << 12) & BM_PXP_HANDSHAKE_READY_MUX0_HSK3)
+#define BP_PXP_HANDSHAKE_READY_MUX0_HSK2 8
+#define BM_PXP_HANDSHAKE_READY_MUX0_HSK2 0x00000F00
+#define BF_PXP_HANDSHAKE_READY_MUX0_HSK2(v) \
+ (((v) << 8) & BM_PXP_HANDSHAKE_READY_MUX0_HSK2)
+#define BP_PXP_HANDSHAKE_READY_MUX0_HSK1 4
+#define BM_PXP_HANDSHAKE_READY_MUX0_HSK1 0x000000F0
+#define BF_PXP_HANDSHAKE_READY_MUX0_HSK1(v) \
+ (((v) << 4) & BM_PXP_HANDSHAKE_READY_MUX0_HSK1)
+#define BP_PXP_HANDSHAKE_READY_MUX0_HSK0 0
+#define BM_PXP_HANDSHAKE_READY_MUX0_HSK0 0x0000000F
+#define BF_PXP_HANDSHAKE_READY_MUX0_HSK0(v) \
+ (((v) << 0) & BM_PXP_HANDSHAKE_READY_MUX0_HSK0)
+
+#define HW_PXP_HANDSHAKE_READY_MUX1 (0x00002d00)
+
+#define BP_PXP_HANDSHAKE_READY_MUX1_HSK15 28
+#define BM_PXP_HANDSHAKE_READY_MUX1_HSK15 0xF0000000
+#define BF_PXP_HANDSHAKE_READY_MUX1_HSK15(v) \
+ (((v) << 28) & BM_PXP_HANDSHAKE_READY_MUX1_HSK15)
+#define BP_PXP_HANDSHAKE_READY_MUX1_HSK14 24
+#define BM_PXP_HANDSHAKE_READY_MUX1_HSK14 0x0F000000
+#define BF_PXP_HANDSHAKE_READY_MUX1_HSK14(v) \
+ (((v) << 24) & BM_PXP_HANDSHAKE_READY_MUX1_HSK14)
+#define BP_PXP_HANDSHAKE_READY_MUX1_HSK13 20
+#define BM_PXP_HANDSHAKE_READY_MUX1_HSK13 0x00F00000
+#define BF_PXP_HANDSHAKE_READY_MUX1_HSK13(v) \
+ (((v) << 20) & BM_PXP_HANDSHAKE_READY_MUX1_HSK13)
+#define BP_PXP_HANDSHAKE_READY_MUX1_HSK12 16
+#define BM_PXP_HANDSHAKE_READY_MUX1_HSK12 0x000F0000
+#define BF_PXP_HANDSHAKE_READY_MUX1_HSK12(v) \
+ (((v) << 16) & BM_PXP_HANDSHAKE_READY_MUX1_HSK12)
+#define BP_PXP_HANDSHAKE_READY_MUX1_HSK11 12
+#define BM_PXP_HANDSHAKE_READY_MUX1_HSK11 0x0000F000
+#define BF_PXP_HANDSHAKE_READY_MUX1_HSK11(v) \
+ (((v) << 12) & BM_PXP_HANDSHAKE_READY_MUX1_HSK11)
+#define BP_PXP_HANDSHAKE_READY_MUX1_HSK10 8
+#define BM_PXP_HANDSHAKE_READY_MUX1_HSK10 0x00000F00
+#define BF_PXP_HANDSHAKE_READY_MUX1_HSK10(v) \
+ (((v) << 8) & BM_PXP_HANDSHAKE_READY_MUX1_HSK10)
+#define BP_PXP_HANDSHAKE_READY_MUX1_HSK9 4
+#define BM_PXP_HANDSHAKE_READY_MUX1_HSK9 0x000000F0
+#define BF_PXP_HANDSHAKE_READY_MUX1_HSK9(v) \
+ (((v) << 4) & BM_PXP_HANDSHAKE_READY_MUX1_HSK9)
+#define BP_PXP_HANDSHAKE_READY_MUX1_HSK8 0
+#define BM_PXP_HANDSHAKE_READY_MUX1_HSK8 0x0000000F
+#define BF_PXP_HANDSHAKE_READY_MUX1_HSK8(v) \
+ (((v) << 0) & BM_PXP_HANDSHAKE_READY_MUX1_HSK8)
+
+#define HW_PXP_HANDSHAKE_DONE_MUX0 (0x00002d10)
+
+#define BP_PXP_HANDSHAKE_DONE_MUX0_HSK7 28
+#define BM_PXP_HANDSHAKE_DONE_MUX0_HSK7 0xF0000000
+#define BF_PXP_HANDSHAKE_DONE_MUX0_HSK7(v) \
+ (((v) << 28) & BM_PXP_HANDSHAKE_DONE_MUX0_HSK7)
+#define BP_PXP_HANDSHAKE_DONE_MUX0_HSK6 24
+#define BM_PXP_HANDSHAKE_DONE_MUX0_HSK6 0x0F000000
+#define BF_PXP_HANDSHAKE_DONE_MUX0_HSK6(v) \
+ (((v) << 24) & BM_PXP_HANDSHAKE_DONE_MUX0_HSK6)
+#define BP_PXP_HANDSHAKE_DONE_MUX0_HSK5 20
+#define BM_PXP_HANDSHAKE_DONE_MUX0_HSK5 0x00F00000
+#define BF_PXP_HANDSHAKE_DONE_MUX0_HSK5(v) \
+ (((v) << 20) & BM_PXP_HANDSHAKE_DONE_MUX0_HSK5)
+#define BP_PXP_HANDSHAKE_DONE_MUX0_HSK4 16
+#define BM_PXP_HANDSHAKE_DONE_MUX0_HSK4 0x000F0000
+#define BF_PXP_HANDSHAKE_DONE_MUX0_HSK4(v) \
+ (((v) << 16) & BM_PXP_HANDSHAKE_DONE_MUX0_HSK4)
+#define BP_PXP_HANDSHAKE_DONE_MUX0_HSK3 12
+#define BM_PXP_HANDSHAKE_DONE_MUX0_HSK3 0x0000F000
+#define BF_PXP_HANDSHAKE_DONE_MUX0_HSK3(v) \
+ (((v) << 12) & BM_PXP_HANDSHAKE_DONE_MUX0_HSK3)
+#define BP_PXP_HANDSHAKE_DONE_MUX0_HSK2 8
+#define BM_PXP_HANDSHAKE_DONE_MUX0_HSK2 0x00000F00
+#define BF_PXP_HANDSHAKE_DONE_MUX0_HSK2(v) \
+ (((v) << 8) & BM_PXP_HANDSHAKE_DONE_MUX0_HSK2)
+#define BP_PXP_HANDSHAKE_DONE_MUX0_HSK1 4
+#define BM_PXP_HANDSHAKE_DONE_MUX0_HSK1 0x000000F0
+#define BF_PXP_HANDSHAKE_DONE_MUX0_HSK1(v) \
+ (((v) << 4) & BM_PXP_HANDSHAKE_DONE_MUX0_HSK1)
+#define BP_PXP_HANDSHAKE_DONE_MUX0_HSK0 0
+#define BM_PXP_HANDSHAKE_DONE_MUX0_HSK0 0x0000000F
+#define BF_PXP_HANDSHAKE_DONE_MUX0_HSK0(v) \
+ (((v) << 0) & BM_PXP_HANDSHAKE_DONE_MUX0_HSK0)
+
+#define HW_PXP_HANDSHAKE_DONE_MUX1 (0x00002d20)
+
+#define BP_PXP_HANDSHAKE_DONE_MUX1_HSK15 28
+#define BM_PXP_HANDSHAKE_DONE_MUX1_HSK15 0xF0000000
+#define BF_PXP_HANDSHAKE_DONE_MUX1_HSK15(v) \
+ (((v) << 28) & BM_PXP_HANDSHAKE_DONE_MUX1_HSK15)
+#define BP_PXP_HANDSHAKE_DONE_MUX1_HSK14 24
+#define BM_PXP_HANDSHAKE_DONE_MUX1_HSK14 0x0F000000
+#define BF_PXP_HANDSHAKE_DONE_MUX1_HSK14(v) \
+ (((v) << 24) & BM_PXP_HANDSHAKE_DONE_MUX1_HSK14)
+#define BP_PXP_HANDSHAKE_DONE_MUX1_HSK13 20
+#define BM_PXP_HANDSHAKE_DONE_MUX1_HSK13 0x00F00000
+#define BF_PXP_HANDSHAKE_DONE_MUX1_HSK13(v) \
+ (((v) << 20) & BM_PXP_HANDSHAKE_DONE_MUX1_HSK13)
+#define BP_PXP_HANDSHAKE_DONE_MUX1_HSK12 16
+#define BM_PXP_HANDSHAKE_DONE_MUX1_HSK12 0x000F0000
+#define BF_PXP_HANDSHAKE_DONE_MUX1_HSK12(v) \
+ (((v) << 16) & BM_PXP_HANDSHAKE_DONE_MUX1_HSK12)
+#define BP_PXP_HANDSHAKE_DONE_MUX1_HSK11 12
+#define BM_PXP_HANDSHAKE_DONE_MUX1_HSK11 0x0000F000
+#define BF_PXP_HANDSHAKE_DONE_MUX1_HSK11(v) \
+ (((v) << 12) & BM_PXP_HANDSHAKE_DONE_MUX1_HSK11)
+#define BP_PXP_HANDSHAKE_DONE_MUX1_HSK10 8
+#define BM_PXP_HANDSHAKE_DONE_MUX1_HSK10 0x00000F00
+#define BF_PXP_HANDSHAKE_DONE_MUX1_HSK10(v) \
+ (((v) << 8) & BM_PXP_HANDSHAKE_DONE_MUX1_HSK10)
+#define BP_PXP_HANDSHAKE_DONE_MUX1_HSK9 4
+#define BM_PXP_HANDSHAKE_DONE_MUX1_HSK9 0x000000F0
+#define BF_PXP_HANDSHAKE_DONE_MUX1_HSK9(v) \
+ (((v) << 4) & BM_PXP_HANDSHAKE_DONE_MUX1_HSK9)
+#define BP_PXP_HANDSHAKE_DONE_MUX1_HSK8 0
+#define BM_PXP_HANDSHAKE_DONE_MUX1_HSK8 0x0000000F
+#define BF_PXP_HANDSHAKE_DONE_MUX1_HSK8(v) \
+ (((v) << 0) & BM_PXP_HANDSHAKE_DONE_MUX1_HSK8)
+
+#define HW_PXP_HANDSHAKE_CPU_FETCH (0x00002d30)
+#define HW_PXP_HANDSHAKE_CPU_FETCH_SET (0x00002d34)
+#define HW_PXP_HANDSHAKE_CPU_FETCH_CLR (0x00002d38)
+#define HW_PXP_HANDSHAKE_CPU_FETCH_TOG (0x00002d3c)
+
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW1_HSK_EN 0x80000000
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW1_HSK_EN(v) \
+ (((v) << 31) & BM_PXP_HANDSHAKE_CPU_FETCH_SW1_HSK_EN)
+#define BP_PXP_HANDSHAKE_CPU_FETCH_RSVD1 22
+#define BM_PXP_HANDSHAKE_CPU_FETCH_RSVD1 0x7FC00000
+#define BF_PXP_HANDSHAKE_CPU_FETCH_RSVD1(v) \
+ (((v) << 22) & BM_PXP_HANDSHAKE_CPU_FETCH_RSVD1)
+#define BP_PXP_HANDSHAKE_CPU_FETCH_SW1_BUF_LINES 20
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW1_BUF_LINES 0x00300000
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW1_BUF_LINES(v) \
+ (((v) << 20) & BM_PXP_HANDSHAKE_CPU_FETCH_SW1_BUF_LINES)
+#define BV_PXP_HANDSHAKE_CPU_FETCH_SW1_BUF_LINES__LINE_4 0x0
+#define BV_PXP_HANDSHAKE_CPU_FETCH_SW1_BUF_LINES__LINE_8 0x1
+#define BV_PXP_HANDSHAKE_CPU_FETCH_SW1_BUF_LINES__LINE_16 0x2
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW1_B1_DONE 0x00080000
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW1_B1_DONE(v) \
+ (((v) << 19) & BM_PXP_HANDSHAKE_CPU_FETCH_SW1_B1_DONE)
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW1_B0_DONE 0x00040000
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW1_B0_DONE(v) \
+ (((v) << 18) & BM_PXP_HANDSHAKE_CPU_FETCH_SW1_B0_DONE)
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW1_B1_READY 0x00020000
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW1_B1_READY(v) \
+ (((v) << 17) & BM_PXP_HANDSHAKE_CPU_FETCH_SW1_B1_READY)
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW1_B0_READY 0x00010000
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW1_B0_READY(v) \
+ (((v) << 16) & BM_PXP_HANDSHAKE_CPU_FETCH_SW1_B0_READY)
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW0_HSK_EN 0x00008000
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW0_HSK_EN(v) \
+ (((v) << 15) & BM_PXP_HANDSHAKE_CPU_FETCH_SW0_HSK_EN)
+#define BP_PXP_HANDSHAKE_CPU_FETCH_RSVD0 6
+#define BM_PXP_HANDSHAKE_CPU_FETCH_RSVD0 0x00007FC0
+#define BF_PXP_HANDSHAKE_CPU_FETCH_RSVD0(v) \
+ (((v) << 6) & BM_PXP_HANDSHAKE_CPU_FETCH_RSVD0)
+#define BP_PXP_HANDSHAKE_CPU_FETCH_SW0_BUF_LINES 4
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW0_BUF_LINES 0x00000030
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW0_BUF_LINES(v) \
+ (((v) << 4) & BM_PXP_HANDSHAKE_CPU_FETCH_SW0_BUF_LINES)
+#define BV_PXP_HANDSHAKE_CPU_FETCH_SW0_BUF_LINES__LINE_4 0x0
+#define BV_PXP_HANDSHAKE_CPU_FETCH_SW0_BUF_LINES__LINE_8 0x1
+#define BV_PXP_HANDSHAKE_CPU_FETCH_SW0_BUF_LINES__LINE_16 0x2
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW0_B1_DONE 0x00000008
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW0_B1_DONE(v) \
+ (((v) << 3) & BM_PXP_HANDSHAKE_CPU_FETCH_SW0_B1_DONE)
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW0_B0_DONE 0x00000004
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW0_B0_DONE(v) \
+ (((v) << 2) & BM_PXP_HANDSHAKE_CPU_FETCH_SW0_B0_DONE)
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW0_B1_READY 0x00000002
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW0_B1_READY(v) \
+ (((v) << 1) & BM_PXP_HANDSHAKE_CPU_FETCH_SW0_B1_READY)
+#define BM_PXP_HANDSHAKE_CPU_FETCH_SW0_B0_READY 0x00000001
+#define BF_PXP_HANDSHAKE_CPU_FETCH_SW0_B0_READY(v) \
+ (((v) << 0) & BM_PXP_HANDSHAKE_CPU_FETCH_SW0_B0_READY)
+
+#define HW_PXP_HANDSHAKE_CPU_STORE (0x00002d40)
+#define HW_PXP_HANDSHAKE_CPU_STORE_SET (0x00002d44)
+#define HW_PXP_HANDSHAKE_CPU_STORE_CLR (0x00002d48)
+#define HW_PXP_HANDSHAKE_CPU_STORE_TOG (0x00002d4c)
+
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW1_HSK_EN 0x80000000
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW1_HSK_EN(v) \
+ (((v) << 31) & BM_PXP_HANDSHAKE_CPU_STORE_SW1_HSK_EN)
+#define BP_PXP_HANDSHAKE_CPU_STORE_RSVD1 22
+#define BM_PXP_HANDSHAKE_CPU_STORE_RSVD1 0x7FC00000
+#define BF_PXP_HANDSHAKE_CPU_STORE_RSVD1(v) \
+ (((v) << 22) & BM_PXP_HANDSHAKE_CPU_STORE_RSVD1)
+#define BP_PXP_HANDSHAKE_CPU_STORE_SW1_BUF_LINES 20
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW1_BUF_LINES 0x00300000
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW1_BUF_LINES(v) \
+ (((v) << 20) & BM_PXP_HANDSHAKE_CPU_STORE_SW1_BUF_LINES)
+#define BV_PXP_HANDSHAKE_CPU_STORE_SW1_BUF_LINES__LINE_4 0x0
+#define BV_PXP_HANDSHAKE_CPU_STORE_SW1_BUF_LINES__LINE_8 0x1
+#define BV_PXP_HANDSHAKE_CPU_STORE_SW1_BUF_LINES__LINE_16 0x2
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW1_B1_DONE 0x00080000
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW1_B1_DONE(v) \
+ (((v) << 19) & BM_PXP_HANDSHAKE_CPU_STORE_SW1_B1_DONE)
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW1_B0_DONE 0x00040000
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW1_B0_DONE(v) \
+ (((v) << 18) & BM_PXP_HANDSHAKE_CPU_STORE_SW1_B0_DONE)
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW1_B1_READY 0x00020000
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW1_B1_READY(v) \
+ (((v) << 17) & BM_PXP_HANDSHAKE_CPU_STORE_SW1_B1_READY)
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW1_B0_READY 0x00010000
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW1_B0_READY(v) \
+ (((v) << 16) & BM_PXP_HANDSHAKE_CPU_STORE_SW1_B0_READY)
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW0_HSK_EN 0x00008000
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW0_HSK_EN(v) \
+ (((v) << 15) & BM_PXP_HANDSHAKE_CPU_STORE_SW0_HSK_EN)
+#define BP_PXP_HANDSHAKE_CPU_STORE_RSVD0 6
+#define BM_PXP_HANDSHAKE_CPU_STORE_RSVD0 0x00007FC0
+#define BF_PXP_HANDSHAKE_CPU_STORE_RSVD0(v) \
+ (((v) << 6) & BM_PXP_HANDSHAKE_CPU_STORE_RSVD0)
+#define BP_PXP_HANDSHAKE_CPU_STORE_SW0_BUF_LINES 4
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW0_BUF_LINES 0x00000030
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW0_BUF_LINES(v) \
+ (((v) << 4) & BM_PXP_HANDSHAKE_CPU_STORE_SW0_BUF_LINES)
+#define BV_PXP_HANDSHAKE_CPU_STORE_SW0_BUF_LINES__LINE_4 0x0
+#define BV_PXP_HANDSHAKE_CPU_STORE_SW0_BUF_LINES__LINE_8 0x1
+#define BV_PXP_HANDSHAKE_CPU_STORE_SW0_BUF_LINES__LINE_16 0x2
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW0_B1_DONE 0x00000008
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW0_B1_DONE(v) \
+ (((v) << 3) & BM_PXP_HANDSHAKE_CPU_STORE_SW0_B1_DONE)
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW0_B0_DONE 0x00000004
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW0_B0_DONE(v) \
+ (((v) << 2) & BM_PXP_HANDSHAKE_CPU_STORE_SW0_B0_DONE)
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW0_B1_READY 0x00000002
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW0_B1_READY(v) \
+ (((v) << 1) & BM_PXP_HANDSHAKE_CPU_STORE_SW0_B1_READY)
+#define BM_PXP_HANDSHAKE_CPU_STORE_SW0_B0_READY 0x00000001
+#define BF_PXP_HANDSHAKE_CPU_STORE_SW0_B0_READY(v) \
+ (((v) << 0) & BM_PXP_HANDSHAKE_CPU_STORE_SW0_B0_READY)
+#endif /* __ARCH_ARM___PXP_H */
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index a27d350f69e3..d47573a31e17 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -24,10 +24,10 @@
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
-#include <linux/pm_wakeirq.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/acpi.h>
+#include <linux/pinctrl/consumer.h>
#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
@@ -36,7 +36,9 @@ struct usb_extcon_info {
struct extcon_dev *edev;
struct gpio_desc *id_gpiod;
+ struct gpio_desc *vbus_gpiod;
int id_irq;
+ int vbus_irq;
unsigned long debounce_jiffies;
struct delayed_work wq_detcable;
@@ -48,31 +50,47 @@ static const unsigned int usb_extcon_cable[] = {
EXTCON_NONE,
};
+/*
+ * "USB" = VBUS and "USB-HOST" = !ID, so we have:
+ * Both "USB" and "USB-HOST" can't be set as active at the
+ * same time so if "USB-HOST" is active (i.e. ID is 0) we keep "USB" inactive
+ * even if VBUS is on.
+ *
+ * State | ID | VBUS
+ * ----------------------------------------
+ * [1] USB | H | H
+ * [2] none | H | L
+ * [3] USB-HOST | L | H
+ * [4] USB-HOST | L | L
+ *
+ * In case we have only one of these signals:
+ * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1.
+ * - ID only - we want to distinguish between [1] and [4], so VBUS = ID.
+*/
static void usb_extcon_detect_cable(struct work_struct *work)
{
- int id;
+ int id, vbus;
struct usb_extcon_info *info = container_of(to_delayed_work(work),
struct usb_extcon_info,
wq_detcable);
- /* check ID and update cable state */
- id = gpiod_get_value_cansleep(info->id_gpiod);
- if (id) {
- /*
- * ID = 1 means USB HOST cable detached.
- * As we don't have event for USB peripheral cable attached,
- * we simulate USB peripheral attach here.
- */
+ /* check ID and VBUS and update cable state */
+ id = info->id_gpiod ?
+ gpiod_get_value_cansleep(info->id_gpiod) : 1;
+ vbus = info->vbus_gpiod ?
+ gpiod_get_value_cansleep(info->vbus_gpiod) : id;
+
+ /* at first we clean states which are no longer active */
+ if (id)
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false);
- extcon_set_state_sync(info->edev, EXTCON_USB, true);
- } else {
- /*
- * ID = 0 means USB HOST cable attached.
- * As we don't have event for USB peripheral cable detached,
- * we simulate USB peripheral detach here.
- */
+ if (!vbus)
extcon_set_state_sync(info->edev, EXTCON_USB, false);
+
+ if (!id) {
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);
+ } else {
+ if (vbus)
+ extcon_set_state_sync(info->edev, EXTCON_USB, true);
}
}
@@ -101,12 +119,21 @@ static int usb_extcon_probe(struct platform_device *pdev)
return -ENOMEM;
info->dev = dev;
- info->id_gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
- if (IS_ERR(info->id_gpiod)) {
- dev_err(dev, "failed to get ID GPIO\n");
- return PTR_ERR(info->id_gpiod);
+ info->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id", GPIOD_IN);
+ info->vbus_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus",
+ GPIOD_IN);
+
+ if (!info->id_gpiod && !info->vbus_gpiod) {
+ dev_err(dev, "failed to get gpios\n");
+ return -ENODEV;
}
+ if (IS_ERR(info->id_gpiod))
+ return PTR_ERR(info->id_gpiod);
+
+ if (IS_ERR(info->vbus_gpiod))
+ return PTR_ERR(info->vbus_gpiod);
+
info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
if (IS_ERR(info->edev)) {
dev_err(dev, "failed to allocate extcon device\n");
@@ -119,32 +146,56 @@ static int usb_extcon_probe(struct platform_device *pdev)
return ret;
}
- ret = gpiod_set_debounce(info->id_gpiod,
- USB_GPIO_DEBOUNCE_MS * 1000);
+ if (info->id_gpiod)
+ ret = gpiod_set_debounce(info->id_gpiod,
+ USB_GPIO_DEBOUNCE_MS * 1000);
+ if (!ret && info->vbus_gpiod)
+ ret = gpiod_set_debounce(info->vbus_gpiod,
+ USB_GPIO_DEBOUNCE_MS * 1000);
+
if (ret < 0)
info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEBOUNCE_MS);
INIT_DELAYED_WORK(&info->wq_detcable, usb_extcon_detect_cable);
- info->id_irq = gpiod_to_irq(info->id_gpiod);
- if (info->id_irq < 0) {
- dev_err(dev, "failed to get ID IRQ\n");
- return info->id_irq;
+ if (info->id_gpiod) {
+ info->id_irq = gpiod_to_irq(info->id_gpiod);
+ if (info->id_irq < 0) {
+ dev_err(dev, "failed to get ID IRQ\n");
+ return info->id_irq;
+ }
+
+ ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+ usb_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ pdev->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for ID IRQ\n");
+ return ret;
+ }
}
- ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
- usb_irq_handler,
- IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- pdev->name, info);
- if (ret < 0) {
- dev_err(dev, "failed to request handler for ID IRQ\n");
- return ret;
+ if (info->vbus_gpiod) {
+ info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
+ if (info->vbus_irq < 0) {
+ dev_err(dev, "failed to get VBUS IRQ\n");
+ return info->vbus_irq;
+ }
+
+ ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+ usb_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ pdev->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for VBUS IRQ\n");
+ return ret;
+ }
}
platform_set_drvdata(pdev, info);
- device_init_wakeup(dev, true);
- dev_pm_set_wake_irq(dev, info->id_irq);
+ device_set_wakeup_capable(&pdev->dev, true);
/* Perform initial detection */
usb_extcon_detect_cable(&info->wq_detcable.work);
@@ -157,8 +208,6 @@ static int usb_extcon_remove(struct platform_device *pdev)
struct usb_extcon_info *info = platform_get_drvdata(pdev);
cancel_delayed_work_sync(&info->wq_detcable);
-
- dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
return 0;
@@ -170,12 +219,35 @@ static int usb_extcon_suspend(struct device *dev)
struct usb_extcon_info *info = dev_get_drvdata(dev);
int ret = 0;
+ if (device_may_wakeup(dev)) {
+ if (info->id_gpiod) {
+ ret = enable_irq_wake(info->id_irq);
+ if (ret)
+ return ret;
+ }
+ if (info->vbus_gpiod) {
+ ret = enable_irq_wake(info->vbus_irq);
+ if (ret) {
+ if (info->id_gpiod)
+ disable_irq_wake(info->id_irq);
+
+ return ret;
+ }
+ }
+ }
+
/*
* We don't want to process any IRQs after this point
* as GPIOs used behind I2C subsystem might not be
* accessible until resume completes. So disable IRQ.
*/
- disable_irq(info->id_irq);
+ if (info->id_gpiod)
+ disable_irq(info->id_irq);
+ if (info->vbus_gpiod)
+ disable_irq(info->vbus_irq);
+
+ if (!device_may_wakeup(dev))
+ pinctrl_pm_select_sleep_state(dev);
return ret;
}
@@ -185,10 +257,33 @@ static int usb_extcon_resume(struct device *dev)
struct usb_extcon_info *info = dev_get_drvdata(dev);
int ret = 0;
- enable_irq(info->id_irq);
if (!device_may_wakeup(dev))
- queue_delayed_work(system_power_efficient_wq,
- &info->wq_detcable, 0);
+ pinctrl_pm_select_default_state(dev);
+
+ if (device_may_wakeup(dev)) {
+ if (info->id_gpiod) {
+ ret = disable_irq_wake(info->id_irq);
+ if (ret)
+ return ret;
+ }
+ if (info->vbus_gpiod) {
+ ret = disable_irq_wake(info->vbus_irq);
+ if (ret) {
+ if (info->id_gpiod)
+ enable_irq_wake(info->id_irq);
+
+ return ret;
+ }
+ }
+ }
+
+ if (info->id_gpiod)
+ enable_irq(info->id_irq);
+ if (info->vbus_gpiod)
+ enable_irq(info->vbus_irq);
+
+ queue_delayed_work(system_power_efficient_wq,
+ &info->wq_detcable, 0);
return ret;
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 12d417a4d4a8..09ab72f2ea01 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -321,7 +321,6 @@ config GPIO_MVEBU
config GPIO_MXC
def_bool y
- depends on ARCH_MXC
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
@@ -443,6 +442,12 @@ config GPIO_VF610
help
Say yes here to support Vybrid vf610 GPIOs.
+config GPIO_IMX_RPMSG
+ bool "NXP i.MX7ULP RPMSG GPIO support"
+ depends on ARCH_MXC && RPMSG && GPIOLIB
+ help
+ This driver support i.MX7ULP RPMSG virtual GPIOs.
+
config GPIO_VR41XX
tristate "NEC VR4100 series General-purpose I/O Uint support"
depends on CPU_VR41XX
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index d074c2299393..95f52f4a97ce 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -124,6 +124,7 @@ obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o
obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
+obj-$(CONFIG_GPIO_IMX_RPMSG) += gpio-imx-rpmsg.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index a6607faf2fdf..fbca09c92686 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -138,6 +138,9 @@ static int gen_74x164_probe(struct spi_device *spi)
chip->registers = nregs;
chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
+ of_property_read_u8_array(spi->dev.of_node, "registers-default",
+ chip->buffer, chip->registers);
+
chip->gpio_chip.can_sleep = true;
chip->gpio_chip.parent = &spi->dev;
chip->gpio_chip.owner = THIS_MODULE;
diff --git a/drivers/gpio/gpio-imx-rpmsg.c b/drivers/gpio/gpio-imx-rpmsg.c
new file mode 100644
index 000000000000..9bfd1880fc57
--- /dev/null
+++ b/drivers/gpio/gpio-imx-rpmsg.c
@@ -0,0 +1,322 @@
+/*
+ * 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
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/imx_rpmsg.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos.h>
+#include <linux/rpmsg.h>
+#include <linux/virtio.h>
+
+#define IMX_RPMSG_GPIO_PER_PORT 32
+#define RPMSG_TIMEOUT 1000
+
+enum gpio_input_trigger_type {
+ GPIO_RPMSG_TRI_IGNORE,
+ GPIO_RPMSG_TRI_RISING,
+ GPIO_RPMSG_TRI_FALLING,
+ GPIO_RPMSG_TRI_BOTH_EDGE,
+ GPIO_RPMSG_TRI_LOW_LEVEL,
+ GPIO_RPMSG_TRI_HIGH_LEVEL,
+};
+
+enum gpio_rpmsg_header_type {
+ GPIO_RPMSG_SETUP,
+ GPIO_RPMSG_REPLY,
+ GPIO_RPMSG_NOTIFY,
+};
+
+enum gpio_rpmsg_header_cmd {
+ GPIO_RPMSG_INPUT_INIT,
+ GPIO_RPMSG_OUTPUT_INIT,
+ GPIO_RPMSG_INPUT_GET,
+};
+
+struct gpio_rpmsg_data {
+ struct imx_rpmsg_head header;
+ u8 pin_idx;
+ u8 port_idx;
+ union {
+ u8 event;
+ u8 retcode;
+ u8 value;
+ } out;
+ union {
+ u8 wakeup;
+ u8 value;
+ } in;
+} __packed __aligned(8);
+
+struct imx_rpmsg_gpio_port {
+ struct gpio_chip gc;
+ struct gpio_rpmsg_data msg;
+ int idx;
+};
+
+struct imx_gpio_rpmsg_info {
+ struct rpmsg_device *rpdev;
+ struct gpio_rpmsg_data *notify_msg;
+ struct gpio_rpmsg_data *reply_msg;
+ struct pm_qos_request pm_qos_req;
+ struct completion cmd_complete;
+ struct mutex lock;
+};
+
+static struct imx_gpio_rpmsg_info gpio_rpmsg;
+
+static int gpio_send_message(struct imx_rpmsg_gpio_port *port,
+ struct gpio_rpmsg_data *msg, struct imx_gpio_rpmsg_info *info)
+{
+ int err;
+
+ if (!info->rpdev) {
+ dev_dbg(&info->rpdev->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 gpio_rpmsg_data));
+
+ if (err) {
+ dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err);
+ goto err_out;
+ }
+
+ 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->reply_msg->out.retcode != 0) {
+ dev_err(&info->rpdev->dev, "rpmsg not ack %d!\n",
+ info->reply_msg->out.retcode);
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ /* copy the reply message */
+ memcpy(&port->msg, info->reply_msg, sizeof(*info->reply_msg));
+
+ err = 0;
+
+err_out:
+ pm_qos_remove_request(&info->pm_qos_req);
+ mutex_unlock(&info->lock);
+
+ return err;
+}
+
+static int gpio_rpmsg_cb(struct rpmsg_device *rpdev,
+ void *data, int len, void *priv, u32 src)
+{
+ struct gpio_rpmsg_data *msg = (struct gpio_rpmsg_data *)data;
+
+ if (msg->header.type == GPIO_RPMSG_REPLY) {
+ gpio_rpmsg.reply_msg = msg;
+ complete(&gpio_rpmsg.cmd_complete);
+ } else if (msg->header.type == GPIO_RPMSG_NOTIFY) {
+ gpio_rpmsg.notify_msg = msg;
+ /* TBD for interrupt handler */
+ } else
+ dev_err(&gpio_rpmsg.rpdev->dev, "wrong command type!\n");
+
+ return 0;
+}
+
+static int imx_rpmsg_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct imx_rpmsg_gpio_port *port = gpiochip_get_data(gc);
+ struct gpio_rpmsg_data msg;
+ int ret;
+
+ memset(&msg, 0, sizeof(struct gpio_rpmsg_data));
+ msg.header.cate = IMX_RPMSG_GPIO;
+ msg.header.major = IMX_RMPSG_MAJOR;
+ msg.header.minor = IMX_RMPSG_MINOR;
+ msg.header.type = GPIO_RPMSG_SETUP;
+ msg.header.cmd = GPIO_RPMSG_INPUT_GET;
+ msg.pin_idx = gpio;
+ msg.port_idx = port->idx;
+
+ ret = gpio_send_message(port, &msg, &gpio_rpmsg);
+ if (!ret)
+ return !!port->msg.in.value;
+
+ return ret;
+}
+
+static int imx_rpmsg_gpio_direction_input(struct gpio_chip *gc,
+ unsigned int gpio)
+{
+ struct imx_rpmsg_gpio_port *port = gpiochip_get_data(gc);
+ struct gpio_rpmsg_data msg;
+
+ memset(&msg, 0, sizeof(struct gpio_rpmsg_data));
+ msg.header.cate = IMX_RPMSG_GPIO;
+ msg.header.major = IMX_RMPSG_MAJOR;
+ msg.header.minor = IMX_RMPSG_MINOR;
+ msg.header.type = GPIO_RPMSG_SETUP;
+ msg.header.cmd = GPIO_RPMSG_INPUT_INIT;
+ msg.pin_idx = gpio;
+ msg.port_idx = port->idx;
+
+ /* TBD: get event trigger and wakeup from GPIO descriptor */
+ msg.out.event = GPIO_RPMSG_TRI_IGNORE;
+ msg.in.wakeup = 0;
+
+ return gpio_send_message(port, &msg, &gpio_rpmsg);
+}
+
+static inline void imx_rpmsg_gpio_direction_output_init(struct gpio_chip *gc,
+ unsigned int gpio, int val, struct gpio_rpmsg_data *msg)
+{
+ struct imx_rpmsg_gpio_port *port = gpiochip_get_data(gc);
+
+ msg->header.cate = IMX_RPMSG_GPIO;
+ msg->header.major = IMX_RMPSG_MAJOR;
+ msg->header.minor = IMX_RMPSG_MINOR;
+ msg->header.type = GPIO_RPMSG_SETUP;
+ msg->header.cmd = GPIO_RPMSG_OUTPUT_INIT;
+ msg->pin_idx = gpio;
+ msg->port_idx = port->idx;
+ msg->out.value = val;
+}
+
+static void imx_rpmsg_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct imx_rpmsg_gpio_port *port = gpiochip_get_data(gc);
+ struct gpio_rpmsg_data msg;
+
+ memset(&msg, 0, sizeof(struct gpio_rpmsg_data));
+ imx_rpmsg_gpio_direction_output_init(gc, gpio, val, &msg);
+ gpio_send_message(port, &msg, &gpio_rpmsg);
+}
+
+static int imx_rpmsg_gpio_direction_output(struct gpio_chip *gc,
+ unsigned int gpio, int val)
+{
+ struct imx_rpmsg_gpio_port *port = gpiochip_get_data(gc);
+ struct gpio_rpmsg_data msg;
+
+ memset(&msg, 0, sizeof(struct gpio_rpmsg_data));
+ imx_rpmsg_gpio_direction_output_init(gc, gpio, val, &msg);
+ return gpio_send_message(port, &msg, &gpio_rpmsg);
+}
+
+static int gpio_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+ gpio_rpmsg.rpdev = rpdev;
+ dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+ rpdev->src, rpdev->dst);
+
+ init_completion(&gpio_rpmsg.cmd_complete);
+ mutex_init(&gpio_rpmsg.lock);
+
+ return 0;
+}
+
+static struct rpmsg_device_id gpio_rpmsg_id_table[] = {
+ { .name = "rpmsg-io-channel" },
+ {},
+};
+
+static struct rpmsg_driver gpio_rpmsg_driver = {
+ .drv.name = "gpio_rpmsg",
+ .drv.owner = THIS_MODULE,
+ .id_table = gpio_rpmsg_id_table,
+ .probe = gpio_rpmsg_probe,
+ .callback = gpio_rpmsg_cb,
+};
+
+static int imx_rpmsg_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct imx_rpmsg_gpio_port *port;
+ struct gpio_chip *gc;
+ int ret;
+
+ port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ ret = of_property_read_u32(np, "port_idx", &port->idx);
+ if (ret)
+ return ret;
+
+ gc = &port->gc;
+ gc->of_node = np;
+ gc->parent = dev;
+ gc->label = "imx-rpmsg-gpio";
+ gc->ngpio = IMX_RPMSG_GPIO_PER_PORT;
+ gc->base = of_alias_get_id(np, "gpio") * IMX_RPMSG_GPIO_PER_PORT;
+
+ gc->direction_input = imx_rpmsg_gpio_direction_input;
+ gc->direction_output = imx_rpmsg_gpio_direction_output;
+ gc->get = imx_rpmsg_gpio_get;
+ gc->set = imx_rpmsg_gpio_set;
+
+ platform_set_drvdata(pdev, port);
+
+ ret = devm_gpiochip_add_data(dev, gc, port);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct of_device_id imx_rpmsg_gpio_dt_ids[] = {
+ { .compatible = "fsl,imx-rpmsg-gpio" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx_rpmsg_gpio_driver = {
+ .driver = {
+ .name = "gpio-imx-rpmsg",
+ .of_match_table = imx_rpmsg_gpio_dt_ids,
+ },
+ .probe = imx_rpmsg_gpio_probe,
+};
+
+static int __init gpio_imx_rpmsg_init(void)
+{
+ int ret;
+
+ ret = register_rpmsg_driver(&gpio_rpmsg_driver);
+ if (ret)
+ return ret;
+
+ return platform_driver_register(&imx_rpmsg_gpio_driver);
+}
+device_initcall(gpio_imx_rpmsg_init);
+
+MODULE_AUTHOR("NXP Semiconductor");
+MODULE_DESCRIPTION("NXP i.MX7ULP rpmsg gpio driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index fe731f094257..f645dbd11e52 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/platform_data/pca953x.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <linux/of_platform.h>
@@ -813,6 +814,10 @@ static int pca953x_probe(struct i2c_client *client,
lockdep_set_subclass(&chip->i2c_lock,
i2c_adapter_depth(client->adapter));
+ ret = device_reset(&client->dev);
+ if (ret == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
/* initialize cached registers from their original values.
* we can't share this chip with another i2c master.
*/
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 3edb09cb9ee0..68567cabcdee 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -43,6 +43,7 @@ struct vf610_gpio_port {
#define GPIO_PCOR 0x08
#define GPIO_PTOR 0x0c
#define GPIO_PDIR 0x10
+#define GPIO_PDDR 0x14
#define PORT_PCR(n) ((n) * 0x4)
#define PORT_PCR_IRQC_OFFSET 16
@@ -79,8 +80,16 @@ static inline u32 vf610_gpio_readl(void __iomem *reg)
static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct vf610_gpio_port *port = gpiochip_get_data(gc);
+ unsigned long mask = BIT(gpio);
+
+ mask &= vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
- return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) & BIT(gpio));
+ if (mask)
+ return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDOR)
+ & BIT(gpio));
+ else
+ return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR)
+ & BIT(gpio));
}
static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
@@ -88,6 +97,8 @@ static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
struct vf610_gpio_port *port = gpiochip_get_data(gc);
unsigned long mask = BIT(gpio);
+ vf610_gpio_writel(mask, port->gpio_base + GPIO_PDDR);
+
if (val)
vf610_gpio_writel(mask, port->gpio_base + GPIO_PSOR);
else
@@ -96,6 +107,13 @@ static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
+ struct vf610_gpio_port *port = gpiochip_get_data(chip);
+ unsigned long mask = BIT(gpio);
+ u32 val;
+
+ val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
+ val &= ~mask;
+ vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
return pinctrl_gpio_direction_input(chip->base + gpio);
}
@@ -262,6 +280,14 @@ static int vf610_gpio_probe(struct platform_device *pdev)
/* Clear the interrupt status register for all GPIO's */
vf610_gpio_writel(~0, port->base + PORT_ISFR);
+ /*
+ * At imx7ulp, any interrupts can wake system up from "standby" mode,
+ * so, mask interrupt at suspend mode by default, and the user
+ * can still enable wakeup through /sys entry.
+ */
+ if (of_machine_is_compatible("fsl,imx7ulp"))
+ vf610_gpio_irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
+
ret = gpiochip_irqchip_add(gc, &vf610_gpio_irq_chip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
if (ret) {
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 483059a22b1b..3409a59d1fdb 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -160,6 +160,12 @@ config DRM_VGEM
as used by Mesa's software renderer for enhanced performance.
If M is selected the module will be called vgem.
+config DRM_VIVANTE
+ tristate "Vivante GCCore"
+ depends on DRM
+ help
+ Choose this option if you have a Vivante graphics card.
+ If M is selected, the module will be called vivante.
source "drivers/gpu/drm/exynos/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 25c720454017..e9682a2fc9ad 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_DRM) += drm.o
obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
obj-$(CONFIG_DRM_ARM) += arm/
obj-$(CONFIG_DRM_TTM) += ttm/
+obj-$(CONFIG_DRM_VIVANTE) += vivante/
obj-$(CONFIG_DRM_TDFX) += tdfx/
obj-$(CONFIG_DRM_R128) += r128/
obj-$(CONFIG_HSA_AMD) += amd/amdkfd/
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 3ce391c239b0..a1ca3f774c29 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -247,8 +247,9 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder)
else if (imx_ldb_ch == &ldb->channel[1])
lvds_mux = &ldb->lvds_mux[1];
- regmap_update_bits(ldb->regmap, lvds_mux->reg, lvds_mux->mask,
- mux << lvds_mux->shift);
+ if (lvds_mux)
+ regmap_update_bits(ldb->regmap, lvds_mux->reg, lvds_mux->mask,
+ mux << lvds_mux->shift);
}
regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
@@ -270,6 +271,12 @@ imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder,
int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder);
u32 bus_format = imx_ldb_ch->bus_format;
+ if (mux < 0) {
+ dev_warn(ldb->dev,
+ "%s: cannot get valid mux id\n", __func__);
+ return;
+ }
+
if (mode->clock > 170000) {
dev_warn(ldb->dev,
"%s: mode exceeds 170 MHz pixel clock\n", __func__);
diff --git a/drivers/gpu/drm/vivante/Makefile b/drivers/gpu/drm/vivante/Makefile
new file mode 100644
index 000000000000..d87c8e8752a6
--- /dev/null
+++ b/drivers/gpu/drm/vivante/Makefile
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# Copyright (C) 2005 - 2013 by Vivante Corp.
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+#
+# Makefile for the drm device driver. This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+vivante-y := vivante_drv.o
+
+obj-$(CONFIG_DRM_VIVANTE) += vivante.o
diff --git a/drivers/gpu/drm/vivante/vivante_drv.c b/drivers/gpu/drm/vivante/vivante_drv.c
new file mode 100644
index 000000000000..a19d21276214
--- /dev/null
+++ b/drivers/gpu/drm/vivante/vivante_drv.c
@@ -0,0 +1,131 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2013 by Vivante Corp.
+*
+* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+/* vivante_drv.c -- vivante driver -*- linux-c -*-
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ * Daryll Strauss <daryll@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include "drmP.h"
+#include "vivante_drv.h"
+
+#include "drm_pciids.h"
+#include "drm_legacy.h"
+
+static char platformdevicename[] = "Vivante GCCore";
+static struct platform_device *pplatformdev;
+
+
+int viv_set_busid(struct drm_device *dev, struct drm_master *master)
+{
+ int id;
+
+ id = dev->platformdev->id;
+ if (id < 0)
+ id = 0;
+
+ master->unique = kasprintf(GFP_KERNEL, "platform:%s:%02d",
+ dev->platformdev->name, id);
+ if (!master->unique)
+ return -ENOMEM;
+
+ master->unique_len = strlen(master->unique);
+ return 0;
+}
+
+static const struct file_operations viv_driver_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+ .mmap = drm_legacy_mmap,
+ .poll = drm_poll,
+ .llseek = noop_llseek,
+};
+
+static struct drm_driver driver = {
+ .fops = &viv_driver_fops,
+ .set_busid = viv_set_busid,
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
+ .driver_features = DRIVER_LEGACY,
+};
+
+static int __init vivante_init(void)
+{
+ int retcode;
+
+ pplatformdev = platform_device_register_simple(platformdevicename,
+ -1, NULL, 0);
+ if (pplatformdev == NULL)
+ printk(KERN_ERR"Platform device is null\n");
+
+ retcode = drm_platform_init(&driver, pplatformdev);
+
+ return retcode;
+}
+
+static void __exit vivante_exit(void)
+{
+ if (pplatformdev) {
+ /* The drvdata is set in drm_get_platform_dev() */
+ drm_put_dev(platform_get_drvdata(pplatformdev));
+ platform_device_unregister(pplatformdev);
+ pplatformdev = NULL;
+ }
+}
+
+module_init(vivante_init);
+module_exit(vivante_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/vivante/vivante_drv.h b/drivers/gpu/drm/vivante/vivante_drv.h
new file mode 100644
index 000000000000..03f5884ce19b
--- /dev/null
+++ b/drivers/gpu/drm/vivante/vivante_drv.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2013 by Vivante Corp.
+*
+* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+/* vivante_drv.h -- Vivante DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 12:32:32 2012 by John Zhao
+ */
+/*
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __VIVANTE_DRV_H__
+#define __VIVANTE_DRV_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR "Vivante Inc."
+
+#define DRIVER_NAME "vivante"
+#define DRIVER_DESC "Vivante GCCore"
+#define DRIVER_DATE "20120216"
+
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+#endif
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 45cef3d2c75c..3105d8b3f0b3 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -825,6 +825,15 @@ config SENSORS_MAX1668
This driver can also be built as a module. If so, the module
will be called max1668.
+config SENSORS_MAX17135
+ tristate "Maxim MAX17135 EPD temperature sensor"
+ depends on I2C
+ help
+ If you say yes here you get support for MAX17135 PMIC sensor.
+
+ This driver can also be built as a module. If so, the module
+ will be called max17135_sensor.
+
config SENSORS_MAX197
tristate "Maxim MAX197 and compatibles"
help
@@ -1506,7 +1515,7 @@ config SENSORS_ADS7871
config SENSORS_AMC6821
tristate "Texas Instruments AMC6821"
- depends on I2C
+ depends on I2C
help
If you say yes here you get support for the Texas Instruments
AMC6821 hardware monitoring chips.
@@ -1857,4 +1866,18 @@ config SENSORS_ATK0110
endif # ACPI
+config SENSORS_MAG3110
+ tristate "Freescale MAG3110 e-compass sensor"
+ depends on I2C && SYSFS
+ help
+ If you say yes here you get support for the Freescale MAG3110
+ e-compass sensor.
+ This driver can also be built as a module. If so, the module
+ will be called mag3110.
+
+config MXC_MMA8451
+ tristate "MMA8451 device driver"
+ depends on I2C
+ default y
+
endif # HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index aecf4ba17460..28a22f6c7391 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
obj-$(CONFIG_SENSORS_MAX16065) += max16065.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_MAX1668) += max1668.o
+obj-$(CONFIG_SENSORS_MAX17135) += max17135-hwmon.o
obj-$(CONFIG_SENSORS_MAX197) += max197.o
obj-$(CONFIG_SENSORS_MAX31722) += max31722.o
obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
@@ -166,6 +167,8 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
obj-$(CONFIG_SENSORS_XGENE) += xgene-hwmon.o
+obj-$(CONFIG_SENSORS_MAG3110) += mag3110.o
+obj-$(CONFIG_MXC_MMA8451) += mxc_mma8451.o
obj-$(CONFIG_PMBUS) += pmbus/
diff --git a/drivers/hwmon/mag3110.c b/drivers/hwmon/mag3110.c
new file mode 100644
index 000000000000..c38fd6e0da52
--- /dev/null
+++ b/drivers/hwmon/mag3110.c
@@ -0,0 +1,654 @@
+/*
+ *
+ * Copyright (C) 2011-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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/hwmon.h>
+#include <linux/input.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#define MAG3110_DRV_NAME "mag3110"
+#define MAG3110_ID (0xC4)
+#define MAG3110_XYZ_DATA_LEN (6)
+#define MAG3110_STATUS_ZYXDR (0x08)
+#define MAG3110_AC_MASK (0x01)
+#define MAG3110_AC_OFFSET (0)
+#define MAG3110_DR_MODE_MASK (0x7 << 5)
+#define MAG3110_DR_MODE_OFFSET (5)
+
+#define POLL_INTERVAL_MAX (500)
+#define POLL_INTERVAL (100)
+#define INT_TIMEOUT (1000)
+#define DEFAULT_POSITION (2)
+
+/* register enum for mag3110 registers */
+enum {
+ MAG3110_DR_STATUS = 0x00,
+ MAG3110_OUT_X_MSB,
+ MAG3110_OUT_X_LSB,
+ MAG3110_OUT_Y_MSB,
+ MAG3110_OUT_Y_LSB,
+ MAG3110_OUT_Z_MSB,
+ MAG3110_OUT_Z_LSB,
+ MAG3110_WHO_AM_I,
+
+ MAG3110_OFF_X_MSB,
+ MAG3110_OFF_X_LSB,
+ MAG3110_OFF_Y_MSB,
+ MAG3110_OFF_Y_LSB,
+ MAG3110_OFF_Z_MSB,
+ MAG3110_OFF_Z_LSB,
+
+ MAG3110_DIE_TEMP,
+
+ MAG3110_CTRL_REG1 = 0x10,
+ MAG3110_CTRL_REG2,
+};
+
+enum {
+ MAG_STANDBY,
+ MAG_ACTIVED
+};
+
+struct mag3110_data {
+ struct i2c_client *client;
+ struct input_polled_dev *poll_dev;
+ struct device *hwmon_dev;
+ wait_queue_head_t waitq;
+ bool data_ready;
+ u8 ctl_reg1;
+ int active;
+ int position;
+ int use_irq;
+};
+
+static short MAGHAL[8][3][3] = {
+ { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
+ { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} },
+ { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} },
+ { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} },
+
+ { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} },
+ { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} },
+ { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
+ { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} },
+};
+
+static struct mag3110_data *mag3110_pdata;
+static DEFINE_MUTEX(mag3110_lock);
+
+/*
+ * This function do one mag3110 register read.
+ */
+static int mag3110_adjust_position(short *x, short *y, short *z)
+{
+ short rawdata[3], data[3];
+ int i, j;
+ int position = mag3110_pdata->position;
+ if (position < 0 || position > 7)
+ position = 0;
+ rawdata[0] = *x;
+ rawdata[1] = *y;
+ rawdata[2] = *z;
+ for (i = 0; i < 3; i++) {
+ data[i] = 0;
+ for (j = 0; j < 3; j++)
+ data[i] += rawdata[j] * MAGHAL[position][i][j];
+ }
+ *x = data[0];
+ *y = data[1];
+ *z = data[2];
+ return 0;
+}
+
+static int mag3110_read_reg(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+/*
+ * This function do one mag3110 register write.
+ */
+static int mag3110_write_reg(struct i2c_client *client, u8 reg, char value)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, reg, value);
+ if (ret < 0)
+ dev_err(&client->dev, "i2c write failed\n");
+ return ret;
+}
+
+/*
+ * This function do multiple mag3110 registers read.
+ */
+static int mag3110_read_block_data(struct i2c_client *client, u8 reg,
+ int count, u8 *addr)
+{
+ if (i2c_smbus_read_i2c_block_data(client, reg, count, addr) < count) {
+ dev_err(&client->dev, "i2c block read failed\n");
+ return -1;
+ }
+
+ return count;
+}
+
+/*
+ * Initialization function
+ */
+static int mag3110_init_client(struct i2c_client *client)
+{
+ int val, ret;
+
+ /* enable automatic resets */
+ val = 0x80;
+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG2, val);
+
+ /* set default data rate to 10HZ */
+ val = mag3110_read_reg(client, MAG3110_CTRL_REG1);
+ val |= (0x0 << MAG3110_DR_MODE_OFFSET);
+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, val);
+
+ return ret;
+}
+
+/*
+ * read sensor data from mag3110
+ */
+static int mag3110_read_data(short *x, short *y, short *z)
+{
+ struct mag3110_data *data;
+ u8 tmp_data[MAG3110_XYZ_DATA_LEN];
+ int retry = 3;
+ int result;
+
+ if (!mag3110_pdata || mag3110_pdata->active == MAG_STANDBY)
+ return -EINVAL;
+
+ data = mag3110_pdata;
+ if (data->use_irq && !wait_event_interruptible_timeout
+ (data->waitq, data->data_ready != 0,
+ msecs_to_jiffies(INT_TIMEOUT))) {
+ dev_dbg(&data->client->dev, "interrupt not received\n");
+ return -ETIME;
+ }
+
+ do {
+ msleep(1);
+ result = i2c_smbus_read_byte_data(data->client,
+ MAG3110_DR_STATUS);
+ retry--;
+ } while (!(result & MAG3110_STATUS_ZYXDR) && retry > 0);
+ /* Clear data_ready flag after data is read out */
+ if (retry == 0)
+ return -EINVAL;
+
+ data->data_ready = 0;
+
+ while (i2c_smbus_read_byte_data(data->client, MAG3110_DR_STATUS)) {
+ if (mag3110_read_block_data(data->client,
+ MAG3110_OUT_X_MSB, MAG3110_XYZ_DATA_LEN,
+ tmp_data) < 0)
+ return -1;
+ }
+
+ *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+ *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+ *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+
+ return 0;
+}
+
+static void report_abs(void)
+{
+ struct input_dev *idev;
+ short x, y, z;
+
+ mutex_lock(&mag3110_lock);
+ if (mag3110_read_data(&x, &y, &z) != 0)
+ goto out;
+ mag3110_adjust_position(&x, &y, &z);
+ idev = mag3110_pdata->poll_dev->input;
+ input_report_abs(idev, ABS_X, x);
+ input_report_abs(idev, ABS_Y, y);
+ input_report_abs(idev, ABS_Z, z);
+ input_sync(idev);
+out:
+ mutex_unlock(&mag3110_lock);
+}
+
+static void mag3110_dev_poll(struct input_polled_dev *dev)
+{
+ report_abs();
+}
+
+static irqreturn_t mag3110_irq_handler(int irq, void *dev_id)
+{
+ int result;
+ u8 tmp_data[MAG3110_XYZ_DATA_LEN];
+ result = i2c_smbus_read_byte_data(mag3110_pdata->client,
+ MAG3110_DR_STATUS);
+ if (!(result & MAG3110_STATUS_ZYXDR))
+ return IRQ_NONE;
+
+ mag3110_pdata->data_ready = 1;
+
+ if (mag3110_pdata->active == MAG_STANDBY)
+ /*
+ * Since the mode will be changed, sometimes irq will
+ * be handled in StandBy mode because of interrupt latency.
+ * So just clear the interrutp flag via reading block data.
+ */
+ mag3110_read_block_data(mag3110_pdata->client,
+ MAG3110_OUT_X_MSB,
+ MAG3110_XYZ_DATA_LEN, tmp_data);
+ else
+ wake_up_interruptible(&mag3110_pdata->waitq);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t mag3110_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client;
+ int val;
+ mutex_lock(&mag3110_lock);
+ client = mag3110_pdata->client;
+ val = mag3110_read_reg(client, MAG3110_CTRL_REG1) & MAG3110_AC_MASK;
+
+ mutex_unlock(&mag3110_lock);
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t mag3110_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client;
+ int reg, ret;
+ long enable;
+ u8 tmp_data[MAG3110_XYZ_DATA_LEN];
+
+ ret = kstrtol(buf, 10, &enable);
+ if (ret) {
+ dev_err(dev, "string to long error\n");
+ return ret;
+ }
+
+ mutex_lock(&mag3110_lock);
+ client = mag3110_pdata->client;
+
+ reg = mag3110_read_reg(client, MAG3110_CTRL_REG1);
+ if (enable && mag3110_pdata->active == MAG_STANDBY) {
+ reg |= MAG3110_AC_MASK;
+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
+ if (!ret)
+ mag3110_pdata->active = MAG_ACTIVED;
+ } else if (!enable && mag3110_pdata->active == MAG_ACTIVED) {
+ reg &= ~MAG3110_AC_MASK;
+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
+ if (!ret)
+ mag3110_pdata->active = MAG_STANDBY;
+ }
+
+ /* Read out MSB data to clear interrupt flag */
+ msleep(100);
+ mag3110_read_block_data(mag3110_pdata->client, MAG3110_OUT_X_MSB,
+ MAG3110_XYZ_DATA_LEN, tmp_data);
+ mutex_unlock(&mag3110_lock);
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
+ mag3110_enable_show, mag3110_enable_store);
+
+static ssize_t mag3110_dr_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client;
+ int val;
+
+ client = mag3110_pdata->client;
+ val = (mag3110_read_reg(client, MAG3110_CTRL_REG1)
+ & MAG3110_DR_MODE_MASK) >> MAG3110_DR_MODE_OFFSET;
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t mag3110_dr_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client;
+ int reg, ret;
+ unsigned long val;
+
+ /* This must be done when mag3110 is disabled */
+ if ((kstrtoul(buf, 10, &val) < 0) || (val > 7))
+ return -EINVAL;
+
+ client = mag3110_pdata->client;
+ reg = mag3110_read_reg(client, MAG3110_CTRL_REG1) &
+ ~MAG3110_DR_MODE_MASK;
+ reg |= (val << MAG3110_DR_MODE_OFFSET);
+ /* MAG3110_CTRL_REG1 bit 5-7: data rate mode */
+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(dr_mode, S_IWUSR | S_IRUGO,
+ mag3110_dr_mode_show, mag3110_dr_mode_store);
+
+static ssize_t mag3110_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int val;
+ mutex_lock(&mag3110_lock);
+ val = mag3110_pdata->position;
+ mutex_unlock(&mag3110_lock);
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t mag3110_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ long position;
+ int ret;
+ ret = kstrtol(buf, 10, &position);
+ if (ret) {
+ dev_err(dev, "string to long error\n");
+ return ret;
+ }
+
+ mutex_lock(&mag3110_lock);
+ mag3110_pdata->position = (int)position;
+ mutex_unlock(&mag3110_lock);
+ return count;
+}
+
+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
+ mag3110_position_show, mag3110_position_store);
+
+static struct attribute *mag3110_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_dr_mode.attr,
+ &dev_attr_position.attr,
+ NULL
+};
+
+static const struct attribute_group mag3110_attr_group = {
+ .attrs = mag3110_attributes,
+};
+
+static int mag3110_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter;
+ struct input_dev *idev = NULL;
+ struct mag3110_data *data;
+ int ret = 0;
+ struct regulator *vdd, *vdd_io;
+ u32 pos = 0;
+ struct device_node *of_node = client->dev.of_node;
+ u32 irq_flag;
+ struct irq_data *irq_data = NULL;
+ bool shared_irq = of_property_read_bool(of_node, "shared-interrupt");
+
+ vdd = NULL;
+ vdd_io = NULL;
+
+ vdd = devm_regulator_get(&client->dev, "vdd");
+ if (!IS_ERR(vdd)) {
+ ret = regulator_enable(vdd);
+ if (ret) {
+ dev_err(&client->dev, "vdd set voltage error\n");
+ return ret;
+ }
+ }
+
+ vdd_io = devm_regulator_get(&client->dev, "vddio");
+ if (!IS_ERR(vdd_io)) {
+ ret = regulator_enable(vdd_io);
+ if (ret) {
+ dev_err(&client->dev, "vddio set voltage error\n");
+ return ret;
+ }
+ }
+
+ adapter = to_i2c_adapter(client->dev.parent);
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -EIO;
+
+ dev_info(&client->dev, "check mag3110 chip ID\n");
+ ret = mag3110_read_reg(client, MAG3110_WHO_AM_I);
+
+ if (MAG3110_ID != ret) {
+ dev_err(&client->dev,
+ "read chip ID 0x%x is not equal to 0x%x!\n", ret,
+ MAG3110_ID);
+ return -EINVAL;
+ }
+ data = kzalloc(sizeof(struct mag3110_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ data->client = client;
+ i2c_set_clientdata(client, data);
+ /* Init queue */
+ init_waitqueue_head(&data->waitq);
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ dev_err(&client->dev, "hwmon register failed!\n");
+ ret = PTR_ERR(data->hwmon_dev);
+ goto error_rm_dev_sysfs;
+ }
+
+ if (client->irq > 0) {
+ data->use_irq = 1;
+ irq_data = irq_get_irq_data(client->irq);
+ }
+
+ /*input poll device register */
+ data->poll_dev = input_allocate_polled_device();
+ if (!data->poll_dev) {
+ dev_err(&client->dev, "alloc poll device failed!\n");
+ ret = -ENOMEM;
+ goto error_rm_hwmon_dev;
+ }
+ data->poll_dev->poll = mag3110_dev_poll;
+ data->poll_dev->poll_interval = POLL_INTERVAL;
+ data->poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
+ idev = data->poll_dev->input;
+ idev->name = MAG3110_DRV_NAME;
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(idev, ABS_X, -15000, 15000, 0, 0);
+ input_set_abs_params(idev, ABS_Y, -15000, 15000, 0, 0);
+ input_set_abs_params(idev, ABS_Z, -15000, 15000, 0, 0);
+ ret = input_register_polled_device(data->poll_dev);
+ if (ret) {
+ dev_err(&client->dev, "register poll device failed!\n");
+ goto error_free_poll_dev;
+ }
+
+ /*create device group in sysfs as user interface */
+ ret = sysfs_create_group(&idev->dev.kobj, &mag3110_attr_group);
+ if (ret) {
+ dev_err(&client->dev, "create device file failed!\n");
+ ret = -EINVAL;
+ goto error_rm_poll_dev;
+ }
+
+ if (data->use_irq) {
+ irq_flag = irqd_get_trigger_type(irq_data);
+ irq_flag |= IRQF_ONESHOT;
+ if (shared_irq)
+ irq_flag |= IRQF_SHARED;
+ ret = request_threaded_irq(client->irq, NULL, mag3110_irq_handler,
+ irq_flag, client->dev.driver->name, idev);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to register irq %d!\n",
+ client->irq);
+ goto error_rm_dev_sysfs;
+ }
+ }
+
+ /* Initialize mag3110 chip */
+ mag3110_init_client(client);
+ mag3110_pdata = data;
+ mag3110_pdata->active = MAG_STANDBY;
+ ret = of_property_read_u32(of_node, "position", &pos);
+ if (ret)
+ pos = DEFAULT_POSITION;
+ mag3110_pdata->position = (int)pos;
+ dev_info(&client->dev, "mag3110 is probed\n");
+ return 0;
+error_rm_dev_sysfs:
+ sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group);
+error_rm_poll_dev:
+ input_unregister_polled_device(data->poll_dev);
+error_free_poll_dev:
+ input_free_polled_device(data->poll_dev);
+error_rm_hwmon_dev:
+ hwmon_device_unregister(data->hwmon_dev);
+
+ kfree(data);
+ mag3110_pdata = NULL;
+
+ return ret;
+}
+
+static int mag3110_remove(struct i2c_client *client)
+{
+ struct mag3110_data *data;
+ int ret;
+
+ data = i2c_get_clientdata(client);
+
+ data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1);
+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
+ data->ctl_reg1 & ~MAG3110_AC_MASK);
+
+ free_irq(client->irq, data);
+ input_unregister_polled_device(data->poll_dev);
+ input_free_polled_device(data->poll_dev);
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group);
+ kfree(data);
+ mag3110_pdata = NULL;
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int mag3110_suspend(struct device *dev)
+{
+ int ret = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mag3110_data *data = i2c_get_clientdata(client);
+
+ if (data->active == MAG_ACTIVED) {
+ data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1);
+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
+ data->ctl_reg1 & ~MAG3110_AC_MASK);
+ }
+ return ret;
+}
+
+static int mag3110_resume(struct device *dev)
+{
+ int ret = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mag3110_data *data = i2c_get_clientdata(client);
+ u8 tmp_data[MAG3110_XYZ_DATA_LEN];
+
+ if (data->active == MAG_ACTIVED) {
+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
+ data->ctl_reg1);
+
+ if (data->ctl_reg1 & MAG3110_AC_MASK) {
+ /* Read out MSB data to clear interrupt
+ flag automatically */
+ mag3110_read_block_data(client, MAG3110_OUT_X_MSB,
+ MAG3110_XYZ_DATA_LEN, tmp_data);
+ }
+ }
+ return ret;
+}
+
+static const struct dev_pm_ops mag3110_dev_pm_ops = {
+ .suspend = mag3110_suspend,
+ .resume = mag3110_resume,
+};
+#define MAG3110_DEV_PM_OPS (&mag3110_dev_pm_ops)
+
+#else
+#define MAG3110_DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id mag3110_id[] = {
+ {MAG3110_DRV_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, mag3110_id);
+static struct i2c_driver mag3110_driver = {
+ .driver = {
+ .name = MAG3110_DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = MAG3110_DEV_PM_OPS,
+ },
+ .probe = mag3110_probe,
+ .remove = mag3110_remove,
+ .id_table = mag3110_id,
+};
+
+static int __init mag3110_init(void)
+{
+ return i2c_add_driver(&mag3110_driver);
+}
+
+static void __exit mag3110_exit(void)
+{
+ i2c_del_driver(&mag3110_driver);
+}
+
+module_init(mag3110_init);
+module_exit(mag3110_exit);
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale mag3110 3-axis magnetometer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/max17135-hwmon.c b/drivers/hwmon/max17135-hwmon.c
new file mode 100644
index 000000000000..c8ddb252a616
--- /dev/null
+++ b/drivers/hwmon/max17135-hwmon.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+/*
+ * max17135.c
+ *
+ * Based on the MAX1619 driver.
+ * Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru>
+ * Jean Delvare <khali@linux-fr.org>
+ *
+ * The MAX17135 is a sensor chip made by Maxim.
+ * It reports up to two temperatures (its own plus up to
+ * one external one).
+ */
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/max17135.h>
+
+/*
+ * Conversions
+ */
+static int temp_from_reg(int val)
+{
+ return val >> 8;
+}
+
+/*
+ * Functions declaration
+ */
+static int max17135_sensor_probe(struct platform_device *pdev);
+static int max17135_sensor_remove(struct platform_device *pdev);
+
+static const struct platform_device_id max17135_sns_id[] = {
+ { "max17135-sns", 0},
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, max17135_sns_id);
+
+/*
+ * Driver data (common to all clients)
+ */
+static struct platform_driver max17135_sensor_driver = {
+ .probe = max17135_sensor_probe,
+ .remove = max17135_sensor_remove,
+ .id_table = max17135_sns_id,
+ .driver = {
+ .name = "max17135_sensor",
+ },
+};
+
+/*
+ * Client data (each client gets its own)
+ */
+struct max17135_data {
+ struct device *hwmon_dev;
+};
+
+/*
+ * Sysfs stuff
+ */
+static ssize_t show_temp_input1(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned int reg_val;
+ max17135_reg_read(REG_MAX17135_INT_TEMP, &reg_val);
+ return snprintf(buf, PAGE_SIZE, "%d\n", temp_from_reg(reg_val));
+}
+
+static ssize_t show_temp_input2(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned int reg_val;
+ max17135_reg_read(REG_MAX17135_EXT_TEMP, &reg_val);
+ return snprintf(buf, PAGE_SIZE, "%d\n", temp_from_reg(reg_val));
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
+static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
+
+static struct attribute *max17135_attributes[] = {
+ &dev_attr_temp1_input.attr,
+ &dev_attr_temp2_input.attr,
+ NULL
+};
+
+static const struct attribute_group max17135_group = {
+ .attrs = max17135_attributes,
+};
+
+/*
+ * Real code
+ */
+static int max17135_sensor_probe(struct platform_device *pdev)
+{
+ struct max17135_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct max17135_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(&pdev->dev.kobj, &max17135_group);
+ if (err)
+ goto exit_free;
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove_files;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+
+exit_remove_files:
+ sysfs_remove_group(&pdev->dev.kobj, &max17135_group);
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int max17135_sensor_remove(struct platform_device *pdev)
+{
+ struct max17135_data *data = platform_get_drvdata(pdev);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&pdev->dev.kobj, &max17135_group);
+
+ kfree(data);
+ return 0;
+}
+
+static int __init sensors_max17135_init(void)
+{
+ return platform_driver_register(&max17135_sensor_driver);
+}
+module_init(sensors_max17135_init);
+
+static void __exit sensors_max17135_exit(void)
+{
+ platform_driver_unregister(&max17135_sensor_driver);
+}
+module_exit(sensors_max17135_exit);
+
+MODULE_DESCRIPTION("MAX17135 sensor driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/hwmon/mxc_mma8451.c b/drivers/hwmon/mxc_mma8451.c
new file mode 100644
index 000000000000..f20fb8e5ef78
--- /dev/null
+++ b/drivers/hwmon/mxc_mma8451.c
@@ -0,0 +1,598 @@
+/*
+ * mma8451.c - Linux kernel modules for 3-Axis Orientation/Motion
+ * Detection Sensor
+ *
+ * Copyright (C) 2010-2014 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/input-polldev.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#define MMA8451_I2C_ADDR 0x1C
+#define MMA8451_ID 0x1A
+#define MMA8452_ID 0x2A
+#define MMA8453_ID 0x3A
+
+#define POLL_INTERVAL_MIN 1
+#define POLL_INTERVAL_MAX 500
+#define POLL_INTERVAL 100 /* msecs */
+#define INPUT_FUZZ 32
+#define INPUT_FLAT 32
+#define MODE_CHANGE_DELAY_MS 100
+
+#define MMA8451_STATUS_ZYXDR 0x08
+#define MMA8451_BUF_SIZE 7
+#define DEFAULT_POSITION 0
+
+/* register enum for mma8451 registers */
+enum {
+ MMA8451_STATUS = 0x00,
+ MMA8451_OUT_X_MSB,
+ MMA8451_OUT_X_LSB,
+ MMA8451_OUT_Y_MSB,
+ MMA8451_OUT_Y_LSB,
+ MMA8451_OUT_Z_MSB,
+ MMA8451_OUT_Z_LSB,
+
+ MMA8451_F_SETUP = 0x09,
+ MMA8451_TRIG_CFG,
+ MMA8451_SYSMOD,
+ MMA8451_INT_SOURCE,
+ MMA8451_WHO_AM_I,
+ MMA8451_XYZ_DATA_CFG,
+ MMA8451_HP_FILTER_CUTOFF,
+
+ MMA8451_PL_STATUS,
+ MMA8451_PL_CFG,
+ MMA8451_PL_COUNT,
+ MMA8451_PL_BF_ZCOMP,
+ MMA8451_P_L_THS_REG,
+
+ MMA8451_FF_MT_CFG,
+ MMA8451_FF_MT_SRC,
+ MMA8451_FF_MT_THS,
+ MMA8451_FF_MT_COUNT,
+
+ MMA8451_TRANSIENT_CFG = 0x1D,
+ MMA8451_TRANSIENT_SRC,
+ MMA8451_TRANSIENT_THS,
+ MMA8451_TRANSIENT_COUNT,
+
+ MMA8451_PULSE_CFG,
+ MMA8451_PULSE_SRC,
+ MMA8451_PULSE_THSX,
+ MMA8451_PULSE_THSY,
+ MMA8451_PULSE_THSZ,
+ MMA8451_PULSE_TMLT,
+ MMA8451_PULSE_LTCY,
+ MMA8451_PULSE_WIND,
+
+ MMA8451_ASLP_COUNT,
+ MMA8451_CTRL_REG1,
+ MMA8451_CTRL_REG2,
+ MMA8451_CTRL_REG3,
+ MMA8451_CTRL_REG4,
+ MMA8451_CTRL_REG5,
+
+ MMA8451_OFF_X,
+ MMA8451_OFF_Y,
+ MMA8451_OFF_Z,
+
+ MMA8451_REG_END,
+};
+
+/* The sensitivity is represented in counts/g. In 2g mode the
+sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512
+counts/g and in 8g mode the sensitivity is 256 counts/g.
+ */
+enum {
+ MODE_2G = 0,
+ MODE_4G,
+ MODE_8G,
+};
+
+enum {
+ MMA_STANDBY = 0,
+ MMA_ACTIVED,
+};
+
+/* mma8451 status */
+struct mma8451_status {
+ u8 mode;
+ u8 ctl_reg1;
+ int active;
+ int position;
+};
+
+static struct mma8451_status mma_status;
+static struct input_polled_dev *mma8451_idev;
+static struct device *hwmon_dev;
+static struct i2c_client *mma8451_i2c_client;
+
+static int senstive_mode = MODE_2G;
+static int ACCHAL[8][3][3] = {
+ { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} },
+ { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} },
+ { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
+ { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} },
+
+ { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
+ { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} },
+ { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} },
+ { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} },
+};
+
+static DEFINE_MUTEX(mma8451_lock);
+static int mma8451_adjust_position(short *x, short *y, short *z)
+{
+ short rawdata[3], data[3];
+ int i, j;
+ int position = mma_status.position;
+ if (position < 0 || position > 7)
+ position = 0;
+ rawdata[0] = *x;
+ rawdata[1] = *y;
+ rawdata[2] = *z;
+ for (i = 0; i < 3; i++) {
+ data[i] = 0;
+ for (j = 0; j < 3; j++)
+ data[i] += rawdata[j] * ACCHAL[position][i][j];
+ }
+ *x = data[0];
+ *y = data[1];
+ *z = data[2];
+ return 0;
+}
+
+static int mma8451_change_mode(struct i2c_client *client, int mode)
+{
+ int result;
+
+ mma_status.ctl_reg1 = 0;
+ result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 0);
+ if (result < 0)
+ goto out;
+ mma_status.active = MMA_STANDBY;
+
+ result = i2c_smbus_write_byte_data(client, MMA8451_XYZ_DATA_CFG,
+ mode);
+ if (result < 0)
+ goto out;
+ mdelay(MODE_CHANGE_DELAY_MS);
+ mma_status.mode = mode;
+
+ return 0;
+out:
+ dev_err(&client->dev, "error when init mma8451:(%d)", result);
+ return result;
+}
+
+static int mma8451_read_data(short *x, short *y, short *z)
+{
+ u8 tmp_data[MMA8451_BUF_SIZE];
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(mma8451_i2c_client,
+ MMA8451_OUT_X_MSB, 7, tmp_data);
+ if (ret < MMA8451_BUF_SIZE) {
+ dev_err(&mma8451_i2c_client->dev, "i2c block read failed\n");
+ return -EIO;
+ }
+
+ *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+ *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+ *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+ return 0;
+}
+
+static void report_abs(void)
+{
+ short x, y, z;
+ int result;
+ int retry = 3;
+
+ mutex_lock(&mma8451_lock);
+ if (mma_status.active == MMA_STANDBY)
+ goto out;
+ /* wait for the data ready */
+ do {
+ result = i2c_smbus_read_byte_data(mma8451_i2c_client,
+ MMA8451_STATUS);
+ retry--;
+ msleep(1);
+ } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0);
+ if (retry == 0)
+ goto out;
+ if (mma8451_read_data(&x, &y, &z) != 0)
+ goto out;
+ mma8451_adjust_position(&x, &y, &z);
+ input_report_abs(mma8451_idev->input, ABS_X, x);
+ input_report_abs(mma8451_idev->input, ABS_Y, y);
+ input_report_abs(mma8451_idev->input, ABS_Z, z);
+ input_sync(mma8451_idev->input);
+out:
+ mutex_unlock(&mma8451_lock);
+}
+
+static void mma8451_dev_poll(struct input_polled_dev *dev)
+{
+ report_abs();
+}
+
+static ssize_t mma8451_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client;
+ u8 val;
+ int enable;
+
+ mutex_lock(&mma8451_lock);
+ client = mma8451_i2c_client;
+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
+ if ((val & 0x01) && mma_status.active == MMA_ACTIVED)
+ enable = 1;
+ else
+ enable = 0;
+ mutex_unlock(&mma8451_lock);
+ return sprintf(buf, "%d\n", enable);
+}
+
+static ssize_t mma8451_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client;
+ int ret;
+ unsigned long enable;
+ u8 val = 0;
+
+ ret = kstrtoul(buf, 10, &enable);
+ if (ret) {
+ dev_err(dev, "string transform error\n");
+ return ret;
+ }
+
+ mutex_lock(&mma8451_lock);
+ client = mma8451_i2c_client;
+ enable = (enable > 0) ? 1 : 0;
+ if (enable && mma_status.active == MMA_STANDBY) {
+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
+ ret =
+ i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
+ val | 0x01);
+ if (!ret)
+ mma_status.active = MMA_ACTIVED;
+
+ } else if (enable == 0 && mma_status.active == MMA_ACTIVED) {
+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
+ ret =
+ i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
+ val & 0xFE);
+ if (!ret)
+ mma_status.active = MMA_STANDBY;
+
+ }
+ mutex_unlock(&mma8451_lock);
+ return count;
+}
+
+static ssize_t mma8451_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int position = 0;
+ mutex_lock(&mma8451_lock);
+ position = mma_status.position;
+ mutex_unlock(&mma8451_lock);
+ return sprintf(buf, "%d\n", position);
+}
+
+static ssize_t mma8451_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long position;
+ int ret;
+ ret = kstrtoul(buf, 10, &position);
+ if (ret) {
+ dev_err(dev, "string transform error\n");
+ return ret;
+ }
+
+ mutex_lock(&mma8451_lock);
+ mma_status.position = (int)position;
+ mutex_unlock(&mma8451_lock);
+ return count;
+}
+
+static ssize_t mma8451_scalemode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int mode = 0;
+ mutex_lock(&mma8451_lock);
+ mode = (int)mma_status.mode;
+ mutex_unlock(&mma8451_lock);
+
+ return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t mma8451_scalemode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long mode;
+ int ret, active_save;
+ struct i2c_client *client = mma8451_i2c_client;
+
+ ret = kstrtoul(buf, 10, &mode);
+ if (ret) {
+ dev_err(dev, "string transform error\n");
+ goto out;
+ }
+
+ if (mode > MODE_8G) {
+ dev_warn(dev, "not supported mode\n");
+ ret = count;
+ goto out;
+ }
+
+ mutex_lock(&mma8451_lock);
+ if (mode == mma_status.mode) {
+ ret = count;
+ goto out_unlock;
+ }
+
+ active_save = mma_status.active;
+ ret = mma8451_change_mode(client, mode);
+ if (ret)
+ goto out_unlock;
+
+ if (active_save == MMA_ACTIVED) {
+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 1);
+
+ if (ret)
+ goto out_unlock;
+ mma_status.active = active_save;
+ }
+
+out_unlock:
+ mutex_unlock(&mma8451_lock);
+out:
+ return ret;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
+ mma8451_enable_show, mma8451_enable_store);
+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
+ mma8451_position_show, mma8451_position_store);
+static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO,
+ mma8451_scalemode_show, mma8451_scalemode_store);
+
+static struct attribute *mma8451_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_position.attr,
+ &dev_attr_scalemode.attr,
+ NULL
+};
+
+static const struct attribute_group mma8451_attr_group = {
+ .attrs = mma8451_attributes,
+};
+
+static int mma8451_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result, client_id;
+ struct input_dev *idev;
+ struct i2c_adapter *adapter;
+ u32 pos;
+ struct device_node *of_node = client->dev.of_node;
+ struct regulator *vdd, *vdd_io;
+
+ mma8451_i2c_client = client;
+
+ vdd = devm_regulator_get(&client->dev, "vdd");
+ if (!IS_ERR(vdd)) {
+ result = regulator_enable(vdd);
+ if (result) {
+ dev_err(&client->dev, "vdd set voltage error\n");
+ return result;
+ }
+ }
+
+ vdd_io = devm_regulator_get(&client->dev, "vddio");
+ if (!IS_ERR(vdd_io)) {
+ result = regulator_enable(vdd_io);
+ if (result) {
+ dev_err(&client->dev, "vddio set voltage error\n");
+ return result;
+ }
+ }
+
+ adapter = to_i2c_adapter(client->dev.parent);
+ result = i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA);
+ if (!result)
+ goto err_out;
+
+ client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I);
+ if (client_id != MMA8451_ID && client_id != MMA8452_ID
+ && client_id != MMA8453_ID) {
+ dev_err(&client->dev,
+ "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n",
+ result, MMA8451_ID, MMA8452_ID);
+ result = -EINVAL;
+ goto err_out;
+ }
+
+ /* Initialize the MMA8451 chip */
+ result = mma8451_change_mode(client, senstive_mode);
+ if (result) {
+ dev_err(&client->dev,
+ "error when init mma8451 chip:(%d)\n", result);
+ goto err_out;
+ }
+
+ hwmon_dev = hwmon_device_register(&client->dev);
+ if (!hwmon_dev) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "error when register hwmon device\n");
+ goto err_out;
+ }
+
+ mma8451_idev = input_allocate_polled_device();
+ if (!mma8451_idev) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "alloc poll device failed!\n");
+ goto err_alloc_poll_device;
+ }
+ mma8451_idev->poll = mma8451_dev_poll;
+ mma8451_idev->poll_interval = POLL_INTERVAL;
+ mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN;
+ mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX;
+ idev = mma8451_idev->input;
+ idev->name = "mma845x";
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+
+ input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
+ input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
+ input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
+
+ result = input_register_polled_device(mma8451_idev);
+ if (result) {
+ dev_err(&client->dev, "register poll device failed!\n");
+ goto err_register_polled_device;
+ }
+ result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group);
+ if (result) {
+ dev_err(&client->dev, "create device file failed!\n");
+ result = -EINVAL;
+ goto err_register_polled_device;
+ }
+
+ result = of_property_read_u32(of_node, "position", &pos);
+ if (result)
+ pos = DEFAULT_POSITION;
+ mma_status.position = (int)pos;
+
+ return 0;
+err_register_polled_device:
+ input_free_polled_device(mma8451_idev);
+err_alloc_poll_device:
+ hwmon_device_unregister(&client->dev);
+err_out:
+ return result;
+}
+
+static int mma8451_stop_chip(struct i2c_client *client)
+{
+ int ret = 0;
+ if (mma_status.active == MMA_ACTIVED) {
+ mma_status.ctl_reg1 = i2c_smbus_read_byte_data(client,
+ MMA8451_CTRL_REG1);
+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
+ mma_status.ctl_reg1 & 0xFE);
+ }
+ return ret;
+}
+
+static int mma8451_remove(struct i2c_client *client)
+{
+ int ret;
+ ret = mma8451_stop_chip(client);
+ hwmon_device_unregister(hwmon_dev);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mma8451_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ return mma8451_stop_chip(client);
+}
+
+static int mma8451_resume(struct device *dev)
+{
+ int ret = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ if (mma_status.active == MMA_ACTIVED)
+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
+ mma_status.ctl_reg1);
+ return ret;
+
+}
+#endif
+
+static const struct i2c_device_id mma8451_id[] = {
+ {"mma8451", 0},
+};
+
+MODULE_DEVICE_TABLE(i2c, mma8451_id);
+
+static SIMPLE_DEV_PM_OPS(mma8451_pm_ops, mma8451_suspend, mma8451_resume);
+static struct i2c_driver mma8451_driver = {
+ .driver = {
+ .name = "mma8451",
+ .owner = THIS_MODULE,
+ .pm = &mma8451_pm_ops,
+ },
+ .probe = mma8451_probe,
+ .remove = mma8451_remove,
+ .id_table = mma8451_id,
+};
+
+static int __init mma8451_init(void)
+{
+ /* register driver */
+ int res;
+
+ res = i2c_add_driver(&mma8451_driver);
+ if (res < 0) {
+ printk(KERN_INFO "add mma8451 i2c driver failed\n");
+ return -ENODEV;
+ }
+ return res;
+}
+
+static void __exit mma8451_exit(void)
+{
+ i2c_del_driver(&mma8451_driver);
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MMA8451 3-Axis Orientation/Motion Detection Sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(mma8451_init);
+module_exit(mma8451_exit);
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d252276feadf..7cff9ecb4f6d 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -597,6 +597,16 @@ config I2C_IMX
This driver can also be built as a module. If so, the module
will be called i2c-imx.
+config I2C_IMX_LPI2C
+ tristate "IMX Low Power I2C interface"
+ depends on ARCH_MXC || COMPILE_TEST
+ help
+ Say Y here if you want to use the Low Power IIC bus controller
+ on the Freescale i.MX processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-imx-lpi2c.
+
config I2C_IOP3XX
tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 29764cc20a44..05195cdd4bea 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_I2C_HIX5HD2) += i2c-hix5hd2.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IMG) += i2c-img-scb.o
obj-$(CONFIG_I2C_IMX) += i2c-imx.o
+obj-$(CONFIG_I2C_IMX_LPI2C) += i2c-imx-lpi2c.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_JZ4780) += i2c-jz4780.o
obj-$(CONFIG_I2C_KEMPLD) += i2c-kempld.o
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
new file mode 100644
index 000000000000..bdfb2cf021b0
--- /dev/null
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -0,0 +1,667 @@
+/*
+ * This is i.MX low power i2c controller driver.
+ *
+ * Copyright 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
+ * 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/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "imx-lpi2c"
+
+#define LPI2C_PARAM 0x04 /* i2c RX/TX FIFO size */
+#define LPI2C_MCR 0x10 /* i2c contrl register */
+#define LPI2C_MSR 0x14 /* i2c status register */
+#define LPI2C_MIER 0x18 /* i2c interrupt enable */
+#define LPI2C_MCFGR0 0x20 /* i2c master configuration */
+#define LPI2C_MCFGR1 0x24 /* i2c master configuration */
+#define LPI2C_MCFGR2 0x28 /* i2c master configuration */
+#define LPI2C_MCFGR3 0x2C /* i2c master configuration */
+#define LPI2C_MCCR0 0x48 /* i2c master clk configuration */
+#define LPI2C_MCCR1 0x50 /* i2c master clk configuration */
+#define LPI2C_MFCR 0x58 /* i2c master FIFO control */
+#define LPI2C_MFSR 0x5C /* i2c master FIFO status */
+#define LPI2C_MTDR 0x60 /* i2c master TX data register */
+#define LPI2C_MRDR 0x70 /* i2c master RX data register */
+
+/* i2c command */
+#define TRAN_DATA 0X00
+#define RECV_DATA 0X01
+#define GEN_STOP 0X02
+#define RECV_DISCARD 0X03
+#define GEN_START 0X04
+#define START_NACK 0X05
+#define START_HIGH 0X06
+#define START_HIGH_NACK 0X07
+
+#define MCR_MEN BIT(0)
+#define MCR_RST BIT(1)
+#define MCR_DOZEN BIT(2)
+#define MCR_DBGEN BIT(3)
+#define MCR_RTF BIT(8)
+#define MCR_RRF BIT(9)
+#define MSR_TDF BIT(0)
+#define MSR_RDF BIT(1)
+#define MSR_SDF BIT(9)
+#define MSR_NDF BIT(10)
+#define MSR_ALF BIT(11)
+#define MSR_MBF BIT(24)
+#define MSR_BBF BIT(25)
+#define MIER_TDIE BIT(0)
+#define MIER_RDIE BIT(1)
+#define MIER_SDIE BIT(9)
+#define MIER_NDIE BIT(10)
+#define MCFGR1_AUTOSTOP BIT(8)
+#define MCFGR1_IGNACK BIT(9)
+#define MRDR_RXEMPTY BIT(14)
+
+#define I2C_CLK_RATIO 2
+#define CHUNK_DATA 256
+
+#define LPI2C_RX_FIFOSIZE 4
+#define LPI2C_TX_FIFOSIZE 4
+
+#define LPI2C_DEFAULT_RATE 200000
+#define STARDARD_MAX_BITRATE 400000
+#define FAST_MAX_BITRATE 1000000
+#define FAST_PLUS_MAX_BITRATE 3400000
+#define HIGHSPEED_MAX_BITRATE 5000000
+
+enum lpi2c_imx_mode {
+ STANDARD, /* 100+Kbps */
+ FAST, /* 400+Kbps */
+ FAST_PLUS, /* 1.0+Mbps */
+ HS, /* 3.4+Mbps */
+ ULTRA_FAST, /* 5.0+Mbps */
+};
+
+enum lpi2c_imx_pincfg {
+ TWO_PIN_OD,
+ TWO_PIN_OO,
+ TWO_PIN_PP,
+ FOUR_PIN_PP,
+};
+
+struct lpi2c_imx_struct {
+ struct i2c_adapter adapter;
+ struct clk *clk;
+ void __iomem *base;
+ __u8 *rx_buf;
+ __u8 *tx_buf;
+ struct completion complete;
+ unsigned int msglen;
+ unsigned int delivered;
+ unsigned int block_data;
+ unsigned int bitrate;
+ enum lpi2c_imx_mode mode;
+};
+
+static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
+ unsigned int enable)
+{
+ writel(enable, lpi2c_imx->base + LPI2C_MIER);
+}
+
+static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned long orig_jiffies = jiffies;
+ unsigned int temp;
+
+ while (1) {
+ temp = readl(lpi2c_imx->base + LPI2C_MSR);
+
+ /* check for arbitration lost, clear if set */
+ if (temp & MSR_ALF) {
+ writel(temp, lpi2c_imx->base + LPI2C_MSR);
+ return -EAGAIN;
+ }
+
+ if (temp & (MSR_BBF | MSR_MBF))
+ break;
+
+ if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
+ dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
+ return -ETIMEDOUT;
+ }
+ schedule();
+ }
+
+ return 0;
+}
+
+static void lpi2c_imx_set_mode(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned int bitrate = lpi2c_imx->bitrate;
+ enum lpi2c_imx_mode mode;
+
+ if (bitrate < STARDARD_MAX_BITRATE)
+ mode = STANDARD;
+ else if (bitrate < FAST_MAX_BITRATE)
+ mode = FAST;
+ else if (bitrate < FAST_PLUS_MAX_BITRATE)
+ mode = FAST_PLUS;
+ else if (bitrate < HIGHSPEED_MAX_BITRATE)
+ mode = HS;
+ else
+ mode = ULTRA_FAST;
+
+ lpi2c_imx->mode = mode;
+}
+
+static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx,
+ struct i2c_msg *msgs)
+{
+ unsigned int temp;
+ u8 read;
+
+ temp = readl(lpi2c_imx->base + LPI2C_MCR);
+ temp |= MCR_RRF | MCR_RTF;
+ writel(temp, lpi2c_imx->base + LPI2C_MCR);
+ writel(0x7f00, lpi2c_imx->base + LPI2C_MSR);
+
+ read = msgs->flags & I2C_M_RD;
+ temp = (msgs->addr << 1 | read) | (GEN_START << 8);
+ writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+
+ return lpi2c_imx_bus_busy(lpi2c_imx);
+}
+
+static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned long orig_jiffies = jiffies;
+ unsigned int temp;
+
+ writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
+
+ do {
+ temp = readl(lpi2c_imx->base + LPI2C_MSR);
+ if (temp & MSR_SDF)
+ break;
+
+ if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
+ dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n");
+ break;
+ }
+ schedule();
+
+ } while (1);
+}
+
+/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
+static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ u8 prescale, filt, sethold, clkhi, clklo, datavd;
+ unsigned int clk_rate, clk_cycle;
+ enum lpi2c_imx_pincfg pincfg;
+ unsigned int temp;
+
+ lpi2c_imx_set_mode(lpi2c_imx);
+
+ clk_rate = clk_get_rate(lpi2c_imx->clk);
+ if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
+ filt = 0;
+ else
+ filt = 2;
+
+ for (prescale = 0; prescale <= 7; prescale++) {
+ clk_cycle = clk_rate / ((1 << prescale) * lpi2c_imx->bitrate)
+ - 3 - (filt >> 1);
+ clkhi = (clk_cycle + I2C_CLK_RATIO) / (I2C_CLK_RATIO + 1);
+ clklo = clk_cycle - clkhi;
+ if (clklo < 64)
+ break;
+ }
+
+ if (prescale > 7)
+ return -EINVAL;
+
+ /* set MCFGR1: PINCFG, PRESCALE, IGNACK */
+ if (lpi2c_imx->mode == ULTRA_FAST)
+ pincfg = TWO_PIN_OO;
+ else
+ pincfg = TWO_PIN_OD;
+ temp = prescale | pincfg << 24;
+
+ if (lpi2c_imx->mode == ULTRA_FAST)
+ temp |= MCFGR1_IGNACK;
+
+ writel(temp, lpi2c_imx->base + LPI2C_MCFGR1);
+
+ /* set MCFGR2: FILTSDA, FILTSCL */
+ temp = (filt << 16) | (filt << 24);
+ writel(temp, lpi2c_imx->base + LPI2C_MCFGR2);
+
+ /* set MCCR: DATAVD, SETHOLD, CLKHI, CLKLO */
+ sethold = clkhi;
+ datavd = clkhi >> 1;
+ temp = datavd << 24 | sethold << 16 | clkhi << 8 | clklo;
+
+ if (lpi2c_imx->mode == HS)
+ writel(temp, lpi2c_imx->base + LPI2C_MCCR1);
+ else
+ writel(temp, lpi2c_imx->base + LPI2C_MCCR0);
+
+ return 0;
+}
+
+static int lpi2c_imx_master_enable(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned int temp;
+ int ret;
+
+ ret = clk_enable(lpi2c_imx->clk);
+ if (ret)
+ return ret;
+
+ temp = MCR_RST;
+ writel(temp, lpi2c_imx->base + LPI2C_MCR);
+ writel(0, lpi2c_imx->base + LPI2C_MCR);
+
+ ret = lpi2c_imx_config(lpi2c_imx);
+ if (ret)
+ goto clk_disable;
+
+ temp = readl(lpi2c_imx->base + LPI2C_MCR);
+ temp |= MCR_MEN;
+ writel(temp, lpi2c_imx->base + LPI2C_MCR);
+
+ return 0;
+
+clk_disable:
+ clk_disable(lpi2c_imx->clk);
+
+ return ret;
+}
+
+static int lpi2c_imx_master_disable(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ u32 temp;
+
+ temp = readl(lpi2c_imx->base + LPI2C_MCR);
+ temp &= ~MCR_MEN;
+ writel(temp, lpi2c_imx->base + LPI2C_MCR);
+
+ clk_disable(lpi2c_imx->clk);
+
+ return 0;
+}
+
+static int lpi2c_imx_msg_complete(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned long timeout;
+
+ timeout = wait_for_completion_timeout(&lpi2c_imx->complete, HZ);
+
+ return timeout ? 0 : -ETIMEDOUT;
+}
+
+static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned long orig_jiffies = jiffies;
+ u32 txcnt;
+
+ do {
+ txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff;
+
+ if (readl(lpi2c_imx->base + LPI2C_MSR) & MSR_NDF) {
+ dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n");
+ return -EIO;
+ }
+
+ if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
+ dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n");
+ return -ETIMEDOUT;
+ }
+ schedule();
+
+ } while (txcnt);
+
+ return 0;
+}
+
+static void lpi2c_imx_set_tx_watermark(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ writel(LPI2C_TX_FIFOSIZE >> 1, lpi2c_imx->base + LPI2C_MFCR);
+}
+
+static void lpi2c_imx_set_rx_watermark(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned int temp, remaining;
+
+ remaining = lpi2c_imx->msglen - lpi2c_imx->delivered;
+
+ if (remaining > (LPI2C_RX_FIFOSIZE >> 1))
+ temp = LPI2C_RX_FIFOSIZE >> 1;
+ else
+ temp = 0;
+
+ writel(temp << 16, lpi2c_imx->base + LPI2C_MFCR);
+}
+
+static void lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned int data, txcnt;
+
+ txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff;
+
+ while (txcnt < LPI2C_TX_FIFOSIZE) {
+ if (lpi2c_imx->delivered == lpi2c_imx->msglen)
+ break;
+
+ data = lpi2c_imx->tx_buf[lpi2c_imx->delivered++];
+ writel(data, lpi2c_imx->base + LPI2C_MTDR);
+ txcnt++;
+ }
+
+ if (lpi2c_imx->delivered < lpi2c_imx->msglen)
+ lpi2c_imx_intctrl(lpi2c_imx, MIER_TDIE | MIER_NDIE);
+ else
+ complete(&lpi2c_imx->complete);
+}
+
+static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
+{
+ unsigned int blocklen, remaining;
+ unsigned int temp, data;
+
+ do {
+ data = readl(lpi2c_imx->base + LPI2C_MRDR);
+ if (data & MRDR_RXEMPTY)
+ break;
+
+ lpi2c_imx->rx_buf[lpi2c_imx->delivered++] = data & 0xff;
+ } while (1);
+
+ /*
+ * First byte is the length of remaining packet in the SMBus block
+ * data read. Add it to msgs->len.
+ */
+ if (lpi2c_imx->block_data) {
+ blocklen = lpi2c_imx->rx_buf[0];
+ lpi2c_imx->msglen += blocklen;
+ }
+
+ remaining = lpi2c_imx->msglen - lpi2c_imx->delivered;
+
+ if (!remaining) {
+ complete(&lpi2c_imx->complete);
+ return;
+ }
+
+ /* not finished, still waiting for rx data */
+ lpi2c_imx_set_rx_watermark(lpi2c_imx);
+
+ /* multiple receive commands */
+ if (lpi2c_imx->block_data) {
+ lpi2c_imx->block_data = 0;
+ temp = remaining;
+ temp |= (RECV_DATA << 8);
+ writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+ } else if (!(lpi2c_imx->delivered & 0xff)) {
+ temp = (remaining > CHUNK_DATA ? CHUNK_DATA : remaining) - 1;
+ temp |= (RECV_DATA << 8);
+ writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+ }
+
+ lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE);
+}
+
+static void lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx,
+ struct i2c_msg *msgs)
+{
+ lpi2c_imx->tx_buf = msgs->buf;
+ lpi2c_imx_set_tx_watermark(lpi2c_imx);
+ lpi2c_imx_write_txfifo(lpi2c_imx);
+}
+
+static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx,
+ struct i2c_msg *msgs)
+{
+ unsigned int temp;
+
+ lpi2c_imx->rx_buf = msgs->buf;
+ lpi2c_imx->block_data = msgs->flags & I2C_M_RECV_LEN;
+
+ lpi2c_imx_set_rx_watermark(lpi2c_imx);
+ temp = msgs->len > CHUNK_DATA ? CHUNK_DATA - 1 : msgs->len - 1;
+ temp |= (RECV_DATA << 8);
+ writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+
+ lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE);
+}
+
+static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg *msgs, int num)
+{
+ struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(adapter);
+ unsigned int temp;
+ int i, result;
+
+ result = lpi2c_imx_master_enable(lpi2c_imx);
+ if (result)
+ return result;
+
+ for (i = 0; i < num; i++) {
+ result = lpi2c_imx_start(lpi2c_imx, &msgs[i]);
+ if (result)
+ goto disable;
+
+ /* quick smbus */
+ if (num == 1 && msgs[0].len == 0)
+ goto stop;
+
+ lpi2c_imx->delivered = 0;
+ lpi2c_imx->msglen = msgs[i].len;
+ init_completion(&lpi2c_imx->complete);
+
+ if (msgs[i].flags & I2C_M_RD)
+ lpi2c_imx_read(lpi2c_imx, &msgs[i]);
+ else
+ lpi2c_imx_write(lpi2c_imx, &msgs[i]);
+
+ result = lpi2c_imx_msg_complete(lpi2c_imx);
+ if (result)
+ goto stop;
+
+ if (!(msgs[i].flags & I2C_M_RD)) {
+ result = lpi2c_imx_txfifo_empty(lpi2c_imx);
+ if (result)
+ goto stop;
+ }
+ }
+
+stop:
+ lpi2c_imx_stop(lpi2c_imx);
+
+ temp = readl(lpi2c_imx->base + LPI2C_MSR);
+ if ((temp & MSR_NDF) && !result)
+ result = -EIO;
+
+disable:
+ lpi2c_imx_master_disable(lpi2c_imx);
+
+ dev_dbg(&lpi2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
+ (result < 0) ? "error" : "success msg",
+ (result < 0) ? result : num);
+
+ return (result < 0) ? result : num;
+}
+
+static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
+{
+ struct lpi2c_imx_struct *lpi2c_imx = dev_id;
+ unsigned int temp;
+
+ lpi2c_imx_intctrl(lpi2c_imx, 0);
+ temp = readl(lpi2c_imx->base + LPI2C_MSR);
+
+ if (temp & MSR_NDF) {
+ complete(&lpi2c_imx->complete);
+ goto ret;
+ }
+
+ if (temp & MSR_RDF)
+ lpi2c_imx_read_rxfifo(lpi2c_imx);
+ else if (temp & MSR_TDF)
+ lpi2c_imx_write_txfifo(lpi2c_imx);
+
+ret:
+ return IRQ_HANDLED;
+}
+
+static u32 lpi2c_imx_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA;
+}
+
+static struct i2c_algorithm lpi2c_imx_algo = {
+ .master_xfer = lpi2c_imx_xfer,
+ .functionality = lpi2c_imx_func,
+};
+
+static const struct of_device_id lpi2c_imx_of_match[] = {
+ { .compatible = "fsl,imx7ulp-lpi2c" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match);
+
+static int lpi2c_imx_probe(struct platform_device *pdev)
+{
+ struct lpi2c_imx_struct *lpi2c_imx;
+ struct resource *res;
+ int irq, ret;
+
+ lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL);
+ if (!lpi2c_imx)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ lpi2c_imx->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(lpi2c_imx->base))
+ return PTR_ERR(lpi2c_imx->base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "can't get irq number\n");
+ return irq;
+ }
+
+ lpi2c_imx->adapter.owner = THIS_MODULE;
+ lpi2c_imx->adapter.algo = &lpi2c_imx_algo;
+ lpi2c_imx->adapter.dev.parent = &pdev->dev;
+ lpi2c_imx->adapter.dev.of_node = pdev->dev.of_node;
+ strlcpy(lpi2c_imx->adapter.name, pdev->name,
+ sizeof(lpi2c_imx->adapter.name));
+
+ lpi2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(lpi2c_imx->clk)) {
+ dev_err(&pdev->dev, "can't get I2C peripheral clock\n");
+ return PTR_ERR(lpi2c_imx->clk);
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "clock-frequency", &lpi2c_imx->bitrate);
+ if (ret)
+ lpi2c_imx->bitrate = LPI2C_DEFAULT_RATE;
+
+ ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0,
+ pdev->name, lpi2c_imx);
+ if (ret) {
+ dev_err(&pdev->dev, "can't claim irq %d\n", irq);
+ return ret;
+ }
+
+ i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
+ platform_set_drvdata(pdev, lpi2c_imx);
+
+ ret = clk_prepare(lpi2c_imx->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "clk prepare failed %d\n", ret);
+ return ret;
+ }
+
+ ret = i2c_add_adapter(&lpi2c_imx->adapter);
+ if (ret)
+ goto clk_unprepare;
+
+ dev_info(&lpi2c_imx->adapter.dev, "LPI2C adapter registered\n");
+
+ return 0;
+
+clk_unprepare:
+ clk_unprepare(lpi2c_imx->clk);
+
+ return ret;
+}
+
+static int lpi2c_imx_remove(struct platform_device *pdev)
+{
+ struct lpi2c_imx_struct *lpi2c_imx = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&lpi2c_imx->adapter);
+
+ clk_unprepare(lpi2c_imx->clk);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lpi2c_imx_suspend(struct device *dev)
+{
+ pinctrl_pm_select_sleep_state(dev);
+ return 0;
+}
+
+static int lpi2c_imx_resume(struct device *dev)
+{
+ pinctrl_pm_select_default_state(dev);
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(imx_lpi2c_pm, lpi2c_imx_suspend, lpi2c_imx_resume);
+#define IMX_LPI2C_PM (&imx_lpi2c_pm)
+#else
+#define IMX_LPI2C_PM NULL
+#endif
+
+static struct platform_driver lpi2c_imx_driver = {
+ .probe = lpi2c_imx_probe,
+ .remove = lpi2c_imx_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = lpi2c_imx_of_match,
+ .pm = IMX_LPI2C_PM,
+ },
+};
+
+module_platform_driver(lpi2c_imx_driver);
+
+MODULE_AUTHOR("Gao Pan <pandy.gao@nxp.com>");
+MODULE_DESCRIPTION("I2C adapter driver for LPI2C bus");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 47fc1f1acff7..b396bdb4c7f2 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1100,8 +1100,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
}
/* Request IRQ */
- ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
- pdev->name, i2c_imx);
+ ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr,
+ IRQF_NO_SUSPEND, pdev->name, i2c_imx);
if (ret) {
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
goto clk_disable;
@@ -1209,6 +1209,7 @@ static int i2c_imx_runtime_suspend(struct device *dev)
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
clk_disable_unprepare(i2c_imx->clk);
+ pinctrl_pm_select_sleep_state(dev);
return 0;
}
@@ -1218,6 +1219,7 @@ static int i2c_imx_runtime_resume(struct device *dev)
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
int ret;
+ pinctrl_pm_select_default_state(dev);
ret = clk_prepare_enable(i2c_imx->clk);
if (ret)
dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
@@ -1225,7 +1227,20 @@ static int i2c_imx_runtime_resume(struct device *dev)
return ret;
}
+static int i2c_imx_suspend(struct device *dev)
+{
+ pinctrl_pm_select_sleep_state(dev);
+ return 0;
+}
+
+static int i2c_imx_resume(struct device *dev)
+{
+ pinctrl_pm_select_default_state(dev);
+ return 0;
+}
+
static const struct dev_pm_ops i2c_imx_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend, i2c_imx_resume)
SET_RUNTIME_PM_OPS(i2c_imx_runtime_suspend,
i2c_imx_runtime_resume, NULL)
};
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index d1bde6d2721e..12d3e352a867 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -1,7 +1,7 @@
/*
* Freescale Vybrid vf610 ADC driver
*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-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 as published by
@@ -819,6 +819,7 @@ static int vf610_adc_probe(struct platform_device *pdev)
struct resource *mem;
int irq;
int ret;
+ u32 channels;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct vf610_adc));
if (!indio_dev) {
@@ -877,13 +878,18 @@ static int vf610_adc_probe(struct platform_device *pdev)
init_completion(&info->completion);
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "num-channels", &channels);
+ if (ret)
+ channels = ARRAY_SIZE(vf610_adc_iio_channels);
+
indio_dev->name = dev_name(&pdev->dev);
indio_dev->dev.parent = &pdev->dev;
indio_dev->dev.of_node = pdev->dev.of_node;
indio_dev->info = &vf610_adc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = vf610_adc_iio_channels;
- indio_dev->num_channels = ARRAY_SIZE(vf610_adc_iio_channels);
+ indio_dev->num_channels = (int)channels;
ret = clk_prepare_enable(info->clk);
if (ret) {
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index cbd75cf44739..13a129536373 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -416,9 +416,18 @@ config KEYBOARD_MPR121
To compile this driver as a module, choose M here: the
module will be called mpr121_touchkey.
+config KEYBOARD_RPMSG
+ tristate "i.MX Rpmsg Keys Driver"
+ depends on (SOC_IMX7ULP)
+ depends on RPMSG
+ depends on OF
+ help
+ This is rpmsg keys driver on i.mx7ulp, because some keys located
+ in M4 side.
+
config KEYBOARD_SNVS_PWRKEY
tristate "IMX SNVS Power Key Driver"
- depends on SOC_IMX6SX
+ depends on (SOC_IMX6SX || SOC_IMX6UL || SOC_IMX7)
depends on OF
help
This is the snvs powerkey driver for the Freescale i.MX application
@@ -427,6 +436,14 @@ config KEYBOARD_SNVS_PWRKEY
To compile this driver as a module, choose M here; the
module will be called snvs_pwrkey.
+config KEYBOARD_PF1550_ONKEY
+ tristate "PF1550 OnKey Driver"
+ depends on MFD_PF1550
+ depends on OF
+ help
+ This is onkey driver for PF1550 pmic, onkey can trigger release
+ and 1s(push hold), 2s, 3s, 4s, 8s interrupt for long press detect
+
config KEYBOARD_IMX
tristate "IMX keypad support"
depends on ARCH_MXC
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index d9f4cfcf3410..0a613ac5b21f 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -50,9 +50,11 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o
obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o
obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o
obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o
+obj-$(CONFIG_KEYBOARD_RPMSG) += rpmsg-keys.o
obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o
obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
obj-$(CONFIG_KEYBOARD_SNVS_PWRKEY) += snvs_pwrkey.o
+obj-$(CONFIG_KEYBOARD_PF1550_ONKEY) += pf1550_onkey.o
obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o
obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ec876b5b1382..a7a52e6a19b8 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -1807,7 +1807,8 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
static int __init atkbd_init(void)
{
- dmi_check_system(atkbd_dmi_quirk_table);
+ if (!dmi_check_system(atkbd_dmi_quirk_table))
+ return -ENODEV;
return serio_register_driver(&atkbd_drv);
}
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 9b8079ca0fb4..50023867c255 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -849,6 +849,8 @@ static int gpio_keys_suspend(struct device *dev)
mutex_unlock(&input->mutex);
}
+ pinctrl_pm_select_sleep_state(dev);
+
return 0;
}
@@ -859,6 +861,8 @@ static int gpio_keys_resume(struct device *dev)
int error = 0;
int i;
+ pinctrl_pm_select_default_state(dev);
+
if (device_may_wakeup(dev)) {
for (i = 0; i < ddata->pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index 2165f3dd328b..9b14cab768d5 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -1,6 +1,7 @@
/*
* Driver for the IMX keypad port.
* Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
+ * 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
@@ -267,6 +268,7 @@ static void imx_keypad_check_for_events(unsigned long data)
reg_val |= KBD_STAT_KDIE;
reg_val &= ~KBD_STAT_KRIE;
writew(reg_val, keypad->mmio_base + KPSR);
+ pm_relax(keypad->input_dev->dev.parent);
} else {
/*
* Some keys are still pressed. Schedule a rescan in
@@ -280,11 +282,6 @@ static void imx_keypad_check_for_events(unsigned long data)
reg_val = readw(keypad->mmio_base + KPSR);
reg_val |= KBD_STAT_KPKR | KBD_STAT_KRSS;
writew(reg_val, keypad->mmio_base + KPSR);
-
- reg_val = readw(keypad->mmio_base + KPSR);
- reg_val |= KBD_STAT_KRIE;
- reg_val &= ~KBD_STAT_KDIE;
- writew(reg_val, keypad->mmio_base + KPSR);
}
}
@@ -302,6 +299,7 @@ static irqreturn_t imx_keypad_irq_handler(int irq, void *dev_id)
writew(reg_val, keypad->mmio_base + KPSR);
if (keypad->enabled) {
+ pm_stay_awake(keypad->input_dev->dev.parent);
/* The matrix is supposed to be changed */
keypad->stable_count = 0;
@@ -530,11 +528,12 @@ static int imx_keypad_probe(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused imx_kbd_suspend(struct device *dev)
+static int __maybe_unused imx_kbd_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_keypad *kbd = platform_get_drvdata(pdev);
struct input_dev *input_dev = kbd->input_dev;
+ unsigned short reg_val = readw(kbd->mmio_base + KPSR);
/* imx kbd can wake up system even clock is disabled */
mutex_lock(&input_dev->mutex);
@@ -544,13 +543,20 @@ static int __maybe_unused imx_kbd_suspend(struct device *dev)
mutex_unlock(&input_dev->mutex);
- if (device_may_wakeup(&pdev->dev))
+ if (device_may_wakeup(&pdev->dev)) {
+ if (reg_val & KBD_STAT_KPKD)
+ reg_val |= KBD_STAT_KRIE;
+ if (reg_val & KBD_STAT_KPKR)
+ reg_val |= KBD_STAT_KDIE;
+ writew(reg_val, kbd->mmio_base + KPSR);
+
enable_irq_wake(kbd->irq);
+ }
return 0;
}
-static int __maybe_unused imx_kbd_resume(struct device *dev)
+static int __maybe_unused imx_kbd_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_keypad *kbd = platform_get_drvdata(pdev);
@@ -574,7 +580,10 @@ err_clk:
return ret;
}
-static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
+static const struct dev_pm_ops imx_kbd_pm_ops = {
+ .suspend_noirq = imx_kbd_suspend_noirq,
+ .resume_noirq = imx_kbd_resume_noirq,
+};
static struct platform_driver imx_keypad_driver = {
.driver = {
diff --git a/drivers/input/keyboard/pf1550_onkey.c b/drivers/input/keyboard/pf1550_onkey.c
new file mode 100644
index 000000000000..2ba0d155ef99
--- /dev/null
+++ b/drivers/input/keyboard/pf1550_onkey.c
@@ -0,0 +1,206 @@
+/*
+ * Driver for the PF1550 ON_KEY
+ * Copyright (C) 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
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/pf1550.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+struct onkey_drv_data {
+ struct device *dev;
+ struct pf1550_dev *pf1550;
+ int irq;
+ int keycode;
+ int wakeup;
+ struct input_dev *input;
+};
+
+static struct pf1550_irq_info pf1550_onkey_irqs[] = {
+ { PF1550_ONKEY_IRQ_PUSHI, "release" },
+ { PF1550_ONKEY_IRQ_1SI, "1S" },
+ { PF1550_ONKEY_IRQ_2SI, "2S" },
+ { PF1550_ONKEY_IRQ_3SI, "3S" },
+ { PF1550_ONKEY_IRQ_4SI, "4S" },
+ { PF1550_ONKEY_IRQ_8SI, "8S" },
+};
+
+static irqreturn_t pf1550_onkey_irq_handler(int irq, void *data)
+{
+ struct onkey_drv_data *onkey = data;
+ int i, state, irq_type = -1;
+
+ onkey->irq = irq;
+
+ for (i = 0; i < ARRAY_SIZE(pf1550_onkey_irqs); i++)
+ if (onkey->irq == pf1550_onkey_irqs[i].virq)
+ irq_type = pf1550_onkey_irqs[i].irq;
+ switch (irq_type) {
+ case PF1550_ONKEY_IRQ_PUSHI:
+ state = 0;
+ break;
+ case PF1550_ONKEY_IRQ_1SI:
+ case PF1550_ONKEY_IRQ_2SI:
+ case PF1550_ONKEY_IRQ_3SI:
+ case PF1550_ONKEY_IRQ_4SI:
+ case PF1550_ONKEY_IRQ_8SI:
+ state = 1;
+ break;
+ default:
+ dev_err(onkey->dev, "onkey interrupt: irq %d occurred\n",
+ irq_type);
+ return IRQ_HANDLED;
+ }
+
+ input_event(onkey->input, EV_KEY, onkey->keycode, state);
+ input_sync(onkey->input);
+
+ return IRQ_HANDLED;
+}
+
+static int pf1550_onkey_probe(struct platform_device *pdev)
+{
+ struct onkey_drv_data *onkey;
+ struct input_dev *input = NULL;
+ struct device_node *np = pdev->dev.of_node;
+ struct pf1550_dev *pf1550 = dev_get_drvdata(pdev->dev.parent);
+ int i, error;
+
+ if (!np)
+ return -ENODEV;
+
+ onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
+ if (!onkey)
+ return -ENOMEM;
+
+ if (of_property_read_u32(np, "linux,keycode", &onkey->keycode)) {
+ onkey->keycode = KEY_POWER;
+ dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n");
+ }
+
+ onkey->wakeup = of_property_read_bool(np, "wakeup");
+
+ input = devm_input_allocate_device(&pdev->dev);
+ if (!input) {
+ dev_err(&pdev->dev, "failed to allocate the input device\n");
+ return -ENOMEM;
+ }
+
+ input->name = pdev->name;
+ input->phys = "pf1550-onkey/input0";
+ input->id.bustype = BUS_HOST;
+
+ input_set_capability(input, EV_KEY, onkey->keycode);
+
+ for (i = 0; i < ARRAY_SIZE(pf1550_onkey_irqs); i++) {
+ struct pf1550_irq_info *onkey_irq =
+ &pf1550_onkey_irqs[i];
+ unsigned int virq = 0;
+
+ virq = regmap_irq_get_virq(pf1550->irq_data_onkey,
+ onkey_irq->irq);
+ if (!virq)
+ return -EINVAL;
+
+ onkey_irq->virq = virq;
+
+ error = devm_request_threaded_irq(&pdev->dev, virq, NULL,
+ pf1550_onkey_irq_handler,
+ IRQF_NO_SUSPEND,
+ onkey_irq->name, onkey);
+ if (error) {
+ dev_err(&pdev->dev,
+ "failed: irq request (IRQ: %d, error :%d)\n",
+ onkey_irq->irq, error);
+ return error;
+ }
+ }
+
+ error = input_register_device(input);
+ if (error < 0) {
+ dev_err(&pdev->dev, "failed to register input device\n");
+ input_free_device(input);
+ return error;
+ }
+
+ onkey->input = input;
+ onkey->pf1550 = pf1550;
+ platform_set_drvdata(pdev, onkey);
+
+ device_init_wakeup(&pdev->dev, onkey->wakeup);
+
+ return 0;
+}
+
+static int pf1550_onkey_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
+
+ if (!device_may_wakeup(&pdev->dev))
+ regmap_write(onkey->pf1550->regmap,
+ PF1550_PMIC_REG_ONKEY_INT_MASK0,
+ ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
+ ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI);
+ else
+ enable_irq_wake(onkey->pf1550->irq);
+
+ return 0;
+}
+
+static int pf1550_onkey_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
+
+ if (!device_may_wakeup(&pdev->dev))
+ regmap_write(onkey->pf1550->regmap,
+ PF1550_PMIC_REG_ONKEY_INT_MASK0,
+ ~(ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
+ ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI));
+ else
+ disable_irq_wake(onkey->pf1550->irq);
+
+ return 0;
+}
+
+static const struct of_device_id pf1550_onkey_ids[] = {
+ { .compatible = "fsl,pf1550-onkey" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pf1550_onkey_ids);
+
+static SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend,
+ pf1550_onkey_resume);
+
+static struct platform_driver pf1550_onkey_driver = {
+ .driver = {
+ .name = "pf1550-onkey",
+ .pm = &pf1550_onkey_pm_ops,
+ .of_match_table = pf1550_onkey_ids,
+ },
+ .probe = pf1550_onkey_probe,
+};
+module_platform_driver(pf1550_onkey_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION(" PF1550 onkey Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/rpmsg-keys.c b/drivers/input/keyboard/rpmsg-keys.c
new file mode 100644
index 000000000000..f6012e87f9a6
--- /dev/null
+++ b/drivers/input/keyboard/rpmsg-keys.c
@@ -0,0 +1,310 @@
+/*
+ * 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 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/input.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/rpmsg.h>
+#include <linux/uaccess.h>
+#include <linux/virtio.h>
+
+#define RPMSG_TIMEOUT 1000
+
+enum key_cmd_type {
+ KEY_RPMSG_SETUP,
+ KEY_RPMSG_REPLY,
+ KEY_RPMSG_NOTIFY,
+};
+
+enum keys_type {
+ KEY_PRESS = 1,
+ KEY_RELEASE,
+ KEY_BOTH,
+};
+
+struct key_rpmsg_data {
+ struct imx_rpmsg_head header;
+ u8 key_index;
+ union {
+ u8 event;
+ u8 retcode;
+ };
+ u8 wakeup;
+} __attribute__((packed));
+
+struct rpmsg_keys_button {
+ unsigned int code;
+ enum keys_type type;
+ int wakeup;
+ struct input_dev *input;
+};
+
+struct rpmsg_keys_drvdata {
+ struct input_dev *input;
+ struct rpmsg_device *rpdev;
+ struct device *dev;
+ struct key_rpmsg_data *msg;
+ bool ack;
+ struct pm_qos_request pm_qos_req;
+ struct delayed_work keysetup_work;
+ struct completion cmd_complete;
+ int nbuttons;
+ struct rpmsg_keys_button buttons[0];
+};
+
+static struct rpmsg_keys_drvdata *keys_rpmsg;
+
+static int key_send_message(struct key_rpmsg_data *msg,
+ struct rpmsg_keys_drvdata *info, bool ack)
+{
+ int err;
+
+ if (!info->rpdev) {
+ dev_dbg(info->dev,
+ "rpmsg channel not ready, m4 image ready?\n");
+ return -EINVAL;
+ }
+
+ pm_qos_add_request(&info->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, 0);
+
+ if (ack) {
+ info->ack = true;
+ reinit_completion(&info->cmd_complete);
+ }
+
+ err = rpmsg_send(info->rpdev->ept, (void *)msg,
+ sizeof(struct key_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->retcode != 0) {
+ dev_err(&info->rpdev->dev, "rpmsg not ack %d!\n",
+ info->msg->retcode);
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ err = 0;
+ }
+
+err_out:
+ info->ack = true;
+ pm_qos_remove_request(&info->pm_qos_req);
+
+ return err;
+}
+
+static int keys_rpmsg_cb(struct rpmsg_device *rpdev,
+ void *data, int len, void *priv, u32 src)
+{
+ struct key_rpmsg_data *msg = (struct key_rpmsg_data *)data;
+
+ if (msg->header.type == KEY_RPMSG_REPLY) {
+ keys_rpmsg->msg = msg;
+ complete(&keys_rpmsg->cmd_complete);
+ return 0;
+ } else if (msg->header.type == KEY_RPMSG_NOTIFY) {
+ keys_rpmsg->msg = msg;
+ keys_rpmsg->ack = false;
+ } else
+ dev_err(&keys_rpmsg->rpdev->dev, "wrong command type!\n");
+
+ input_event(keys_rpmsg->input, EV_KEY, msg->key_index, msg->event);
+ input_sync(keys_rpmsg->input);
+
+ return 0;
+}
+
+static void keys_init_handler(struct work_struct *work)
+{
+ struct key_rpmsg_data msg;
+ int i;
+
+ /* setup keys */
+ for (i = 0; i < keys_rpmsg->nbuttons; i++) {
+ struct rpmsg_keys_button *button = &keys_rpmsg->buttons[i];
+
+ msg.header.cate = IMX_RPMSG_KEY;
+ msg.header.major = IMX_RMPSG_MAJOR;
+ msg.header.minor = IMX_RMPSG_MINOR;
+ msg.header.type = KEY_RPMSG_SETUP;
+ msg.header.cmd = 0;
+ msg.key_index = button->code;
+ msg.wakeup = button->wakeup;
+ msg.event = button->type;
+ if (key_send_message(&msg, keys_rpmsg, true))
+ dev_err(&keys_rpmsg->rpdev->dev,
+ "key %d setup failed!\n", button->code);
+ }
+}
+
+static int keys_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+ keys_rpmsg->rpdev = rpdev;
+
+ dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+ rpdev->src, rpdev->dst);
+
+ init_completion(&keys_rpmsg->cmd_complete);
+
+ INIT_DELAYED_WORK(&keys_rpmsg->keysetup_work,
+ keys_init_handler);
+ schedule_delayed_work(&keys_rpmsg->keysetup_work,
+ msecs_to_jiffies(100));
+
+ return 0;
+}
+
+static struct rpmsg_device_id keys_rpmsg_id_table[] = {
+ { .name = "rpmsg-keypad-channel" },
+ { },
+};
+
+static struct rpmsg_driver keys_rpmsg_driver = {
+ .drv.name = "key_rpmsg",
+ .drv.owner = THIS_MODULE,
+ .id_table = keys_rpmsg_id_table,
+ .probe = keys_rpmsg_probe,
+ .callback = keys_rpmsg_cb,
+};
+
+static struct rpmsg_keys_drvdata *
+rpmsg_keys_get_devtree_pdata(struct device *dev)
+{
+ struct device_node *node, *pp;
+ struct rpmsg_keys_drvdata *ddata;
+ struct rpmsg_keys_button *button;
+ int nbuttons;
+ int i;
+
+ node = dev->of_node;
+ if (!node)
+ return ERR_PTR(-ENODEV);
+
+ nbuttons = of_get_child_count(node);
+ if (nbuttons == 0)
+ return ERR_PTR(-ENODEV);
+
+ ddata = devm_kzalloc(dev,
+ sizeof(*ddata) + nbuttons *
+ sizeof(struct rpmsg_keys_button),
+ GFP_KERNEL);
+ if (!ddata)
+ return ERR_PTR(-ENOMEM);
+
+ ddata->nbuttons = nbuttons;
+
+ i = 0;
+ for_each_child_of_node(node, pp) {
+ button = &ddata->buttons[i++];
+
+ if (of_property_read_u32(pp, "linux,code", &button->code)) {
+ dev_err(dev, "Button without keycode: 0x%x\n",
+ button->code);
+ return ERR_PTR(-EINVAL);
+ }
+
+ button->wakeup = !!of_get_property(pp, "rpmsg-key,wakeup",
+ NULL);
+ button->type = KEY_BOTH;
+ }
+
+ return ddata;
+}
+
+static int rpmsg_keys_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rpmsg_keys_drvdata *ddata;
+ int i, error;
+ struct input_dev *input;
+
+ ddata = rpmsg_keys_get_devtree_pdata(dev);
+ if (IS_ERR(ddata))
+ return PTR_ERR(ddata);
+
+ input = devm_input_allocate_device(dev);
+ if (!input) {
+ dev_err(dev, "failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ ddata->input = input;
+
+ keys_rpmsg = ddata;
+ platform_set_drvdata(pdev, ddata);
+
+ input->name = pdev->name;
+ input->phys = "rpmsg-keys/input0";
+ input->dev.parent = &pdev->dev;
+
+ input->id.bustype = BUS_HOST;
+
+ for (i = 0; i < ddata->nbuttons; i++) {
+ struct rpmsg_keys_button *button = &ddata->buttons[i];
+
+ input_set_capability(input, EV_KEY, button->code);
+ }
+
+ error = input_register_device(input);
+ if (error) {
+ dev_err(dev, "Unable to register input device, error: %d\n",
+ error);
+ goto err_out;
+ }
+
+ return register_rpmsg_driver(&keys_rpmsg_driver);
+err_out:
+ return error;
+}
+
+static const struct of_device_id rpmsg_keys_of_match[] = {
+ { .compatible = "fsl,rpmsg-keys", },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, rpmsg_keys_of_match);
+
+static struct platform_driver rpmsg_keys_device_driver = {
+ .probe = rpmsg_keys_probe,
+ .driver = {
+ .name = "rpmsg-keys",
+ .of_match_table = of_match_ptr(rpmsg_keys_of_match)
+ }
+};
+
+module_platform_driver(rpmsg_keys_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robin Gong <yibin.gong@nxp.com>");
+MODULE_DESCRIPTION("Keyboard driver based on rpmsg");
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 7ffb614ce566..c6aefc266fbb 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -831,4 +831,29 @@ config INPUT_HISI_POWERKEY
To compile this driver as a module, choose M here: the
module will be called hisi_powerkey.
+config INPUT_MPL3115
+ tristate "MPL3115 pressure temperature sensor"
+ depends on I2C && SYSFS
+ help
+ If you say yes here you get support for the Freescale MPL3115
+ pressure temperature sensor.
+
+ This driver can also be built as a module. If so, the module
+ will be called mpl3115
+
+config SENSOR_FXLS8471
+ tristate "FXLS8471 motion sensor device driver"
+ depends on I2C
+ default n
+
+config INPUT_ISL29023
+ tristate "Intersil ISL29023 ambient light sensor"
+ depends on I2C && SYSFS
+ help
+ If you say yes here you get support for the Intersil ISL29023
+ ambient light sensor.
+
+ This driver can also be built as a module. If so, the module
+ will be called isl29023.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 0b6d025f0487..cac4fcad3801 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -78,3 +78,6 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
+obj-$(CONFIG_INPUT_MPL3115) += mpl3115.o
+obj-$(CONFIG_SENSOR_FXLS8471) += fxls8471.o fxls8471_i2c.o
+obj-$(CONFIG_INPUT_ISL29023) += isl29023.o
diff --git a/drivers/input/misc/fxls8471.c b/drivers/input/misc/fxls8471.c
new file mode 100644
index 000000000000..e77ef1b137a3
--- /dev/null
+++ b/drivers/input/misc/fxls8471.c
@@ -0,0 +1,582 @@
+/*
+ * fxls8471.c - Linux kernel modules for 3-Axis Accel sensor
+ * 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.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/input-polldev.h>
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+#include "fxls8471.h"
+
+#define SENSOR_IOCTL_BASE 'S'
+#define SENSOR_GET_MODEL_NAME _IOR(SENSOR_IOCTL_BASE, 0, char *)
+#define SENSOR_GET_POWER_STATUS _IOR(SENSOR_IOCTL_BASE, 2, int)
+#define SENSOR_SET_POWER_STATUS _IOR(SENSOR_IOCTL_BASE, 3, int)
+#define SENSOR_GET_DELAY_TIME _IOR(SENSOR_IOCTL_BASE, 4, int)
+#define SENSOR_SET_DELAY_TIME _IOR(SENSOR_IOCTL_BASE, 5, int)
+#define SENSOR_GET_RAW_DATA _IOR(SENSOR_IOCTL_BASE, 6, short[3])
+
+#define FXLS8471_POSITION_DEFAULT 2
+#define FXLS8471_DELAY_DEFAULT 200
+
+#define FXLS8471_STATUS_ZYXDR 0x08
+#define FXLS8471_BUF_SIZE 6
+
+struct fxls8471_data fxls8471_dev;
+
+static int fxls8471_position_setting[8][3][3] = {
+ {{0, -1, 0}, {1, 0, 0}, {0, 0, 1} },
+ {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1} },
+ {{0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
+ {{1, 0, 0}, {0, 1, 0}, {0, 0, 1} },
+
+ {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
+ {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1} },
+ {{0, 1, 0}, {1, 0, 0}, {0, 0, -1} },
+ {{1, 0, 0}, {0, -1, 0}, {0, 0, -1} },
+};
+
+static int fxls8471_bus_write(struct fxls8471_data *pdata, u8 reg, u8 val)
+{
+ if (pdata && pdata->write)
+ return pdata->write(pdata, reg, val);
+ return -EIO;
+}
+
+static int fxls8471_bus_read(struct fxls8471_data *pdata, u8 reg)
+{
+ if (pdata && pdata->read)
+ return pdata->read(pdata, reg);
+ return -EIO;
+}
+
+static int fxls8471_bus_read_block(struct fxls8471_data *pdata, u8 reg, u8 len,
+ u8 *val)
+{
+ if (pdata && pdata->read_block)
+ return pdata->read_block(pdata, reg, len, val);
+ return -EIO;
+}
+
+static int fxls8471_data_convert(struct fxls8471_data *pdata,
+ struct fxls8471_data_axis *axis_data)
+{
+ short rawdata[3], data[3];
+ int i, j;
+ int position = atomic_read(&pdata->position);
+
+ if (position < 0 || position > 7)
+ position = 0;
+ rawdata[0] = axis_data->x;
+ rawdata[1] = axis_data->y;
+ rawdata[2] = axis_data->z;
+ for (i = 0; i < 3; i++) {
+ data[i] = 0;
+ for (j = 0; j < 3; j++)
+ data[i] +=
+ rawdata[j] *
+ fxls8471_position_setting[position][i][j];
+ }
+ axis_data->x = data[0];
+ axis_data->y = data[1];
+ axis_data->z = data[2];
+ return 0;
+}
+
+static int fxls8471_device_init(struct fxls8471_data *pdata)
+{
+ int result;
+ result = fxls8471_bus_write(pdata, FXLS8471_CTRL_REG1, 0);
+ if (result < 0)
+ goto out;
+
+ result = fxls8471_bus_write(pdata, FXLS8471_XYZ_DATA_CFG, MODE_2G);
+ if (result < 0)
+ goto out;
+
+ if (pdata->irq) {
+ result = fxls8471_bus_write(pdata, FXLS8471_CTRL_REG5, 0x01);
+ if (result < 0)
+ goto out;
+ result = fxls8471_bus_write(pdata, FXLS8471_CTRL_REG4, 0x01);
+ if (result < 0)
+ goto out;
+ }
+ atomic_set(&pdata->active, STANDBY);
+ return 0;
+out:
+ printk("FXLS8471 device init error\n");
+ return result;
+
+}
+
+static int fxls8471_change_mode(struct fxls8471_data *pdata, int mode)
+{
+ u8 val;
+ int ret;
+ val = fxls8471_bus_read(pdata, FXLS8471_CTRL_REG1);
+ if (mode == ACTIVED)
+ val |= 0x01;
+ else
+ val &= (~0x01);
+ ret = fxls8471_bus_write(pdata, FXLS8471_CTRL_REG1, val);
+ return ret;
+}
+
+static int fxls8471_set_delay(struct fxls8471_data *pdata, int delay)
+{
+ u8 val;
+ val = fxls8471_bus_read(pdata, FXLS8471_CTRL_REG1);
+ /* set sensor standby */
+ fxls8471_bus_write(pdata, FXLS8471_CTRL_REG1, (val & ~0x01));
+ val &= ~(0x7 << 3);
+ if (delay <= 10)
+ val |= 0x02 << 3;
+ else if (delay <= 20)
+ val |= 0x03 << 3;
+ else if (delay <= 67)
+ val |= 0x04 << 3;
+ else
+ val |= 0x05 << 3;
+ /* set sensor standby */
+ fxls8471_bus_write(pdata, FXLS8471_CTRL_REG1, val);
+ return 0;
+}
+
+static int fxls8471_change_range(struct fxls8471_data *pdata, int range)
+{
+ int ret;
+
+ ret = fxls8471_bus_write(pdata, FXLS8471_XYZ_DATA_CFG, range);
+
+ return ret;
+}
+
+static int fxls8471_read_data(struct fxls8471_data *pdata,
+ struct fxls8471_data_axis *data)
+{
+ u8 tmp_data[FXLS8471_BUF_SIZE];
+ int ret;
+ ret = fxls8471_bus_read_block(pdata, FXLS8471_OUT_X_MSB,
+ FXLS8471_BUF_SIZE, tmp_data);
+ if (ret < FXLS8471_BUF_SIZE) {
+ printk(KERN_ERR "FXLS8471 read sensor block data error\n");
+ return -EIO;
+ }
+ data->x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+ data->y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+ data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+ return 0;
+}
+
+/* fxls8471 miscdevice */
+static long fxls8471_ioctl(struct file *file, unsigned int reg,
+ unsigned long arg)
+{
+ struct fxls8471_data *pdata = file->private_data;
+ void __user *argp = (void __user *)arg;
+ long ret = 0;
+ short sdata[3];
+ int enable;
+ int delay;
+ struct fxls8471_data_axis data;
+ if (!pdata) {
+ printk(KERN_ERR "FXLS8471 struct datt point is NULL.");
+ return -EFAULT;
+ }
+ switch (reg) {
+ case SENSOR_GET_MODEL_NAME:
+ if (copy_to_user(argp, "fxls8471", strlen("fxls8471") + 1)) {
+ printk(KERN_ERR
+ "SENSOR_GET_MODEL_NAME copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ break;
+ case SENSOR_GET_POWER_STATUS:
+ enable = atomic_read(&pdata->active);
+ if (copy_to_user(argp, &enable, sizeof(int))) {
+ printk(KERN_ERR
+ "SENSOR_SET_POWER_STATUS copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ break;
+ case SENSOR_SET_POWER_STATUS:
+ if (copy_from_user(&enable, argp, sizeof(int))) {
+ printk(KERN_ERR
+ "SENSOR_SET_POWER_STATUS copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ if (pdata) {
+ ret =
+ fxls8471_change_mode(pdata,
+ enable ? ACTIVED : STANDBY);
+ if (!ret)
+ atomic_set(&pdata->active, enable);
+ }
+ break;
+ case SENSOR_GET_DELAY_TIME:
+ delay = atomic_read(&pdata->delay);
+ if (copy_to_user(argp, &delay, sizeof(delay))) {
+ printk(KERN_ERR
+ "SENSOR_GET_DELAY_TIME copy_to_user failed.");
+ return -EFAULT;
+ }
+ break;
+ case SENSOR_SET_DELAY_TIME:
+ if (copy_from_user(&delay, argp, sizeof(int))) {
+ printk(KERN_ERR
+ "SENSOR_GET_DELAY_TIME copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ if (pdata && delay > 0 && delay <= 500) {
+ ret = fxls8471_set_delay(pdata, delay);
+ if (!ret)
+ atomic_set(&pdata->delay, delay);
+ }
+ break;
+ case SENSOR_GET_RAW_DATA:
+ ret = fxls8471_read_data(pdata, &data);
+ if (!ret) {
+ fxls8471_data_convert(pdata, &data);
+ sdata[0] = data.x;
+ sdata[1] = data.y;
+ sdata[2] = data.z;
+ if (copy_to_user(argp, sdata, sizeof(sdata))) {
+ printk(KERN_ERR
+ "SENSOR_GET_RAW_DATA copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ }
+ break;
+ default:
+ ret = -1;
+ }
+ return ret;
+}
+
+static int fxls8471_open(struct inode *inode, struct file *file)
+{
+ file->private_data = &fxls8471_dev;
+ return nonseekable_open(inode, file);
+}
+
+static int fxls8471_release(struct inode *inode, struct file *file)
+{
+ /* note: releasing the wdt in NOWAYOUT-mode does not stop it */
+ return 0;
+}
+
+static const struct file_operations fxls8471_fops = {
+ .owner = THIS_MODULE,
+ .open = fxls8471_open,
+ .release = fxls8471_release,
+ .unlocked_ioctl = fxls8471_ioctl,
+};
+
+static struct miscdevice fxls8471_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "FreescaleAccelerometer",
+ .fops = &fxls8471_fops,
+};
+
+static ssize_t fxls8471_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ int enable = 0;
+ enable = atomic_read(&pdata->active);
+ return sprintf(buf, "%d\n", enable);
+}
+
+static ssize_t fxls8471_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ int ret;
+ unsigned long enable;
+
+ if (kstrtoul(buf, 10, &enable) < 0)
+ return -EINVAL;
+ enable = (enable > 0) ? 1 : 0;
+ ret = fxls8471_change_mode(pdata, (enable > 0 ? ACTIVED : STANDBY));
+ if (!ret) {
+ atomic_set(&pdata->active, enable);
+ if (enable)
+ printk(KERN_INFO "mma enable setting actived\n");
+ else
+ printk(KERN_INFO "mma enable setting standby\n");
+ }
+ return count;
+}
+
+static ssize_t fxls8471_poll_delay_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ int delay = 0;
+ delay = atomic_read(&pdata->delay);
+ return sprintf(buf, "%d\n", delay);
+}
+
+static ssize_t fxls8471_poll_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ int ret;
+ unsigned long delay;
+
+ if (kstrtoul(buf, 10, &delay) < 0)
+ return -EINVAL;
+ ret = fxls8471_set_delay(pdata, delay);
+ if (!ret)
+ atomic_set(&pdata->delay, delay);
+
+ return count;
+}
+
+static ssize_t fxls8471_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ int position = 0;
+ position = atomic_read(&pdata->position);
+ return sprintf(buf, "%d\n", position);
+}
+
+static ssize_t fxls8471_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ unsigned long position;
+
+ if (kstrtoul(buf, 10, &position) < 0)
+ return -EINVAL;
+ atomic_set(&pdata->position, position);
+
+ return count;
+}
+
+static ssize_t fxls8471_data_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ int ret = 0;
+ struct fxls8471_data_axis data;
+ ret = fxls8471_read_data(pdata, &data);
+ if (!ret)
+ fxls8471_data_convert(pdata, &data);
+ return sprintf(buf, "%d,%d,%d\n", data.x, data.y, data.z);
+}
+
+static ssize_t fxls8471_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ int range = 0;
+
+ range = atomic_read(&pdata->range);
+ return sprintf(buf, "%d\n", range);
+}
+
+static ssize_t fxls8471_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fxls8471_data *pdata = &fxls8471_dev;
+ int ret;
+ unsigned long range;
+
+ if (kstrtoul(buf, 10, &range) < 0)
+ return -EINVAL;
+
+ if (range == atomic_read(&pdata->range))
+ return count;
+
+ if (atomic_read(&pdata->active))
+ printk(KERN_INFO "Pls set the sensor standby and then actived\n");
+ ret = fxls8471_change_range(pdata, range);
+ if (!ret)
+ atomic_set(&pdata->range, range);
+
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, fxls8471_enable_show, fxls8471_enable_store);
+static DEVICE_ATTR(poll_delay, S_IWUSR | S_IRUGO, fxls8471_poll_delay_show,
+ fxls8471_poll_delay_store);
+
+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, fxls8471_position_show,
+ fxls8471_position_store);
+
+static DEVICE_ATTR(data, S_IWUSR | S_IRUGO, fxls8471_data_show, NULL);
+
+static DEVICE_ATTR(range, S_IWUSR | S_IRUGO, fxls8471_range_show, fxls8471_range_store);
+
+static struct attribute *fxls8471_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_poll_delay.attr,
+ &dev_attr_position.attr,
+ &dev_attr_data.attr,
+ &dev_attr_range.attr,
+ NULL
+};
+
+static const struct attribute_group fxls8471_attr_group = {
+ .attrs = fxls8471_attributes,
+};
+
+static irqreturn_t fxls8471_irq_handler(int irq, void *dev)
+{
+ int ret;
+ u8 int_src;
+ struct fxls8471_data *pdata = (struct fxls8471_data *)dev;
+ struct fxls8471_data_axis data;
+ int_src = fxls8471_bus_read(pdata, FXLS8471_INT_SOURCE);
+ /* data ready interrupt */
+ if (int_src & 0x01) {
+ ret = fxls8471_read_data(pdata, &data);
+ if (!ret) {
+ fxls8471_data_convert(pdata, &data);
+ input_report_abs(pdata->idev, ABS_X, data.x);
+ input_report_abs(pdata->idev, ABS_Y, data.y);
+ input_report_abs(pdata->idev, ABS_Z, data.z);
+ input_sync(pdata->idev);
+ }
+
+ }
+ return IRQ_HANDLED;
+}
+
+int fxls8471_driver_init(struct fxls8471_data *pdata)
+{
+ int result, chip_id;
+
+ chip_id = fxls8471_bus_read(pdata, FXLS8471_WHO_AM_I);
+
+ if (chip_id != FXSL8471_ID) {
+ printk(KERN_ERR "read sensor who am i (0x%x)error !\n",
+ chip_id);
+ result = -EINVAL;
+ goto err_out;
+ }
+ /* Initialize the FXLS8471 chip */
+ pdata->chip_id = chip_id;
+ atomic_set(&pdata->delay, FXLS8471_DELAY_DEFAULT);
+ atomic_set(&pdata->position, FXLS8471_POSITION_DEFAULT);
+ result = misc_register(&fxls8471_device);
+ if (result != 0) {
+ printk(KERN_ERR "register acc miscdevice error");
+ goto err_out;
+ }
+
+ result =
+ sysfs_create_group(&fxls8471_device.this_device->kobj,
+ &fxls8471_attr_group);
+ if (result) {
+ printk(KERN_ERR "create device file failed!\n");
+ result = -EINVAL;
+ goto err_create_sysfs;
+ }
+ /*create data input device */
+ pdata->idev = input_allocate_device();
+ if (!pdata->idev) {
+ result = -ENOMEM;
+ printk(KERN_ERR "alloc fxls8471 input device failed!\n");
+ goto err_alloc_input_device;
+ }
+ pdata->idev->name = "FreescaleAccelerometer";
+ pdata->idev->id.bustype = BUS_I2C;
+ pdata->idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(pdata->idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
+ input_set_abs_params(pdata->idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
+ input_set_abs_params(pdata->idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
+ result = input_register_device(pdata->idev);
+ if (result) {
+ printk(KERN_ERR "register fxls8471 input device failed!\n");
+ goto err_register_input_device;
+ }
+ if (pdata->irq) {
+ result =
+ request_threaded_irq(pdata->irq, NULL, fxls8471_irq_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ pdata->idev->name, pdata);
+ if (result < 0) {
+ printk(KERN_ERR "failed to register MMA8x5x irq %d!\n",
+ pdata->irq);
+ goto err_register_irq;
+ }
+ }
+ fxls8471_device_init(pdata);
+ printk("fxls8471 device driver probe successfully\n");
+ return 0;
+err_register_irq:
+ input_unregister_device(pdata->idev);
+err_register_input_device:
+ input_free_device(pdata->idev);
+err_alloc_input_device:
+ sysfs_remove_group(&fxls8471_device.this_device->kobj,
+ &fxls8471_attr_group);
+err_create_sysfs:
+ misc_deregister(&fxls8471_device);
+err_out:
+ return result;
+}
+EXPORT_SYMBOL_GPL(fxls8471_driver_init);
+
+int fxls8471_driver_remove(struct fxls8471_data *pdata)
+{
+ fxls8471_change_mode(pdata, STANDBY);
+ misc_deregister(&fxls8471_device);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fxls8471_driver_remove);
+
+#ifdef CONFIG_PM_SLEEP
+int fxls8471_driver_suspend(struct fxls8471_data *pdata)
+{
+ if (atomic_read(&pdata->active))
+ fxls8471_change_mode(pdata, STANDBY);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fxls8471_driver_suspend);
+
+int fxls8471_driver_resume(struct fxls8471_data *pdata)
+{
+ if (atomic_read(&pdata->active))
+ fxls8471_change_mode(pdata, ACTIVED);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fxls8471_driver_resume);
+
+#endif
diff --git a/drivers/input/misc/fxls8471.h b/drivers/input/misc/fxls8471.h
new file mode 100644
index 000000000000..6820ad1c0517
--- /dev/null
+++ b/drivers/input/misc/fxls8471.h
@@ -0,0 +1,94 @@
+/*
+ * fxls8471.h - Linux kernel modules for 3-Axis Accel sensor
+ * 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.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _FXSL8471_H
+#define _FXSL8471_H
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/input.h>
+
+#define FXSL8471_ID 0x6a
+
+/* register enum for fxls8471 registers */
+enum { FXLS8471_STATUS = 0x00, FXLS8471_OUT_X_MSB, FXLS8471_OUT_X_LSB,
+ FXLS8471_OUT_Y_MSB, FXLS8471_OUT_Y_LSB, FXLS8471_OUT_Z_MSB,
+ FXLS8471_OUT_Z_LSB, FXLS8471_F_SETUP =
+ 0x09, FXLS8471_TRIG_CFG, FXLS8471_SYSMOD,
+ FXLS8471_INT_SOURCE, FXLS8471_WHO_AM_I,
+ FXLS8471_XYZ_DATA_CFG, FXLS8471_HP_FILTER_CUTOFF,
+ FXLS8471_PL_STATUS, FXLS8471_PL_CFG, FXLS8471_PL_COUNT,
+ FXLS8471_PL_BF_ZCOMP, FXLS8471_P_L_THS_REG,
+ FXLS8471_FF_MT_CFG, FXLS8471_FF_MT_SRC, FXLS8471_FF_MT_THS,
+ FXLS8471_FF_MT_COUNT, FXLS8471_TRANSIENT_CFG =
+ 0x1D, FXLS8471_TRANSIENT_SRC, FXLS8471_TRANSIENT_THS,
+ FXLS8471_TRANSIENT_COUNT, FXLS8471_PULSE_CFG,
+ FXLS8471_PULSE_SRC, FXLS8471_PULSE_THSX, FXLS8471_PULSE_THSY,
+ FXLS8471_PULSE_THSZ, FXLS8471_PULSE_TMLT,
+ FXLS8471_PULSE_LTCY, FXLS8471_PULSE_WIND,
+ FXLS8471_ASLP_COUNT, FXLS8471_CTRL_REG1, FXLS8471_CTRL_REG2,
+ FXLS8471_CTRL_REG3, FXLS8471_CTRL_REG4, FXLS8471_CTRL_REG5,
+ FXLS8471_OFF_X, FXLS8471_OFF_Y, FXLS8471_OFF_Z,
+ FXLS8471_REG_END,
+};
+
+enum { STANDBY = 0, ACTIVED,
+};
+
+enum { MODE_2G = 0, MODE_4G, MODE_8G,
+};
+
+struct fxls8471_data_axis {
+ short x;
+ short y;
+ short z;
+};
+
+struct fxls8471_data {
+ void *bus_priv;
+ u16 bus_type;
+ int irq;
+ s32 (*write)(struct fxls8471_data *pdata, u8 reg, u8 val);
+ s32 (*read)(struct fxls8471_data *pdata, u8 reg);
+ s32 (*read_block)(struct fxls8471_data *pdata, u8 reg, u8 len,
+ u8 *val);
+ struct input_dev *idev;
+ atomic_t active;
+ atomic_t delay;
+ atomic_t position;
+ atomic_t range;
+ u8 chip_id;
+};
+
+extern struct fxls8471_data fxls8471_dev;
+
+int fxls8471_driver_init(struct fxls8471_data *pdata);
+int fxls8471_driver_remove(struct fxls8471_data *pdata);
+int fxls8471_driver_suspend(struct fxls8471_data *pdata);
+int fxls8471_driver_resume(struct fxls8471_data *pdata);
+
+#endif /* */
diff --git a/drivers/input/misc/fxls8471_i2c.c b/drivers/input/misc/fxls8471_i2c.c
new file mode 100644
index 000000000000..f752ddd0d14b
--- /dev/null
+++ b/drivers/input/misc/fxls8471_i2c.c
@@ -0,0 +1,111 @@
+/*
+ * fxls8471-i2c.c - Linux kernel modules for 3-Axis Smart Orientation
+ * /Motion Sensor
+ * Version : 01.00
+ * Time : Dec.26, 2012
+ * Author : rick zhang <rick.zhang@freescale.com>
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include "fxls8471.h"
+
+static s32 fxls8471_i2c_write(struct fxls8471_data *pdata, u8 reg, u8 val)
+{
+ struct i2c_client *client = (struct i2c_client *)pdata->bus_priv;
+ return i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static int fxls8471_i2c_read(struct fxls8471_data *pdata, u8 reg)
+{
+ struct i2c_client *client = (struct i2c_client *)pdata->bus_priv;
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int fxls8471_i2c_read_block(struct fxls8471_data *pdata, u8 reg, u8 len,
+ u8 *val)
+{
+ struct i2c_client *client = (struct i2c_client *)pdata->bus_priv;
+ return i2c_smbus_read_i2c_block_data(client, reg, len, val);
+}
+
+static int fxls8471_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ fxls8471_dev.bus_priv = client;
+ fxls8471_dev.bus_type = BUS_I2C;
+ fxls8471_dev.irq = client->irq;
+ fxls8471_dev.read = fxls8471_i2c_read;
+ fxls8471_dev.write = fxls8471_i2c_write;
+ fxls8471_dev.read_block = fxls8471_i2c_read_block;
+ i2c_set_clientdata(client, &fxls8471_dev);
+ return fxls8471_driver_init(&fxls8471_dev);
+}
+
+static int fxls8471_i2c_remove(struct i2c_client *client)
+{
+ return fxls8471_driver_remove(&fxls8471_dev);
+}
+
+#ifdef CONFIG_PM
+static int fxls8471_i2c_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return fxls8471_driver_suspend(i2c_get_clientdata(client));
+}
+
+static int fxls8471_i2c_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return fxls8471_driver_resume(i2c_get_clientdata(client));
+}
+
+#else /* */
+#define fxls8471_i2c_suspend NULL
+#define fxls8471_i2c_resume NULL
+#endif /* */
+static const struct i2c_device_id fxls8471_i2c_id[] = {
+ {"fxls8471", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, fxls8471_i2c_id);
+
+static SIMPLE_DEV_PM_OPS(fxls8471_pm_ops, fxls8471_i2c_suspend,
+ fxls8471_i2c_resume);
+
+static struct i2c_driver fxls8471_i2c_driver = {
+ .driver = {
+ .name = "fxls8471",
+ .owner = THIS_MODULE,
+ .pm = &fxls8471_pm_ops,
+ },
+ .probe = fxls8471_i2c_probe,
+ .remove = fxls8471_i2c_remove,
+ .id_table = fxls8471_i2c_id,
+};
+
+module_i2c_driver(fxls8471_i2c_driver);
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("FXLS8471 3-Axis Acc Sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/isl29023.c b/drivers/input/misc/isl29023.c
new file mode 100644
index 000000000000..ebe8d3a304d1
--- /dev/null
+++ b/drivers/input/misc/isl29023.c
@@ -0,0 +1,1075 @@
+/*
+ * Copyright (C) 2011-2014 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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/isl29023.h>
+
+#define ISL29023_DRV_NAME "isl29023"
+#define DRIVER_VERSION "1.0"
+
+#define ISL29023_COMMAND1 (0x00)
+#define ISL29023_MODE_SHIFT (5)
+#define ISL29023_MODE_MASK (0x7 << ISL29023_MODE_SHIFT)
+#define ISL29023_INT_FLAG_SHIFT (2)
+#define ISL29023_INT_FLAG_MASK (0x1 << ISL29023_INT_FLAG_SHIFT)
+#define ISL29023_INT_PERSISTS_SHIFT (0)
+#define ISL29023_INT_PERSISTS_MASK (0x3 << ISL29023_INT_PERSISTS_SHIFT)
+
+#define ISL29023_COMMAND2 (0x01)
+#define ISL29023_RES_SHIFT (2)
+#define ISL29023_RES_MASK (0x3 << ISL29023_RES_SHIFT)
+#define ISL29023_RANGE_SHIFT (0)
+#define ISL29023_RANGE_MASK (0x3 << ISL29023_RANGE_SHIFT)
+
+#define ISL29023_REG_LSB_SENSOR (0x02)
+#define ISL29023_REG_MSB_SENSOR (0x03)
+#define ISL29023_REG_IRQ_TH_LO_LSB (0x04)
+#define ISL29023_REG_IRQ_TH_LO_MSB (0x05)
+#define ISL29023_REG_IRQ_TH_HI_LSB (0x06)
+#define ISL29023_REG_IRQ_TH_HI_MSB (0x07)
+
+#define ISL29023_NUM_CACHABLE_REGS 8
+#define DEF_RANGE 2
+#define DEFAULT_REGISTOR_VAL 499
+
+struct isl29023_data {
+ struct i2c_client *client;
+ struct mutex lock;
+ struct input_dev *input;
+ struct work_struct work;
+ struct workqueue_struct *workqueue;
+ char phys[32];
+ u8 reg_cache[ISL29023_NUM_CACHABLE_REGS];
+ u8 mode_before_suspend;
+ u8 mode_before_interrupt;
+ u16 rext;
+};
+
+static int gain_range[] = {
+ 1000, 4000, 16000, 64000
+};
+
+/*
+ * register access helpers
+ */
+static int __isl29023_read_reg(struct i2c_client *client,
+ u32 reg, u8 mask, u8 shift)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ return (data->reg_cache[reg] & mask) >> shift;
+}
+
+static int __isl29023_write_reg(struct i2c_client *client,
+ u32 reg, u8 mask, u8 shift, u8 val)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ int ret = 0;
+ u8 tmp;
+
+ if (reg >= ISL29023_NUM_CACHABLE_REGS)
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ tmp = data->reg_cache[reg];
+ tmp &= ~mask;
+ tmp |= val << shift;
+
+ ret = i2c_smbus_write_byte_data(client, reg, tmp);
+ if (!ret)
+ data->reg_cache[reg] = tmp;
+
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
+/*
+ * internally used functions
+ */
+static int isl29023_get_int_persists(struct i2c_client *client)
+{
+ return __isl29023_read_reg(client, ISL29023_COMMAND1,
+ ISL29023_INT_PERSISTS_MASK, ISL29023_INT_PERSISTS_SHIFT);
+}
+
+static int isl29023_set_int_persists(struct i2c_client *client,
+ int int_persists)
+{
+ return __isl29023_write_reg(client, ISL29023_COMMAND1,
+ ISL29023_INT_PERSISTS_MASK, ISL29023_INT_PERSISTS_SHIFT,
+ int_persists);
+}
+
+/*
+ * interrupt flag
+ */
+static int isl29023_get_int_flag(struct i2c_client *client)
+{
+ return __isl29023_read_reg(client, ISL29023_COMMAND1,
+ ISL29023_INT_FLAG_MASK, ISL29023_INT_FLAG_SHIFT);
+}
+
+static int isl29023_set_int_flag(struct i2c_client *client, int flag)
+{
+ return __isl29023_write_reg(client, ISL29023_COMMAND1,
+ ISL29023_INT_FLAG_MASK, ISL29023_INT_FLAG_SHIFT, flag);
+}
+
+/*
+ * interrupt lt
+ */
+static int isl29023_get_int_lt(struct i2c_client *client)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ int lsb, msb, lt;
+
+ mutex_lock(&data->lock);
+ lsb = i2c_smbus_read_byte_data(client, ISL29023_REG_IRQ_TH_LO_LSB);
+
+ if (lsb < 0) {
+ mutex_unlock(&data->lock);
+ return lsb;
+ }
+
+ msb = i2c_smbus_read_byte_data(client, ISL29023_REG_IRQ_TH_LO_MSB);
+ mutex_unlock(&data->lock);
+
+ if (msb < 0)
+ return msb;
+
+ lt = ((msb << 8) | lsb);
+
+ return lt;
+}
+
+static int isl29023_set_int_lt(struct i2c_client *client, int lt)
+{
+ int ret = 0;
+ struct isl29023_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->lock);
+ ret = i2c_smbus_write_byte_data(client, ISL29023_REG_IRQ_TH_LO_LSB,
+ lt & 0xff);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, ISL29023_REG_IRQ_TH_LO_MSB,
+ (lt >> 8) & 0xff);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ data->reg_cache[ISL29023_REG_IRQ_TH_LO_MSB] = (lt >> 8) & 0xff;
+ data->reg_cache[ISL29023_REG_IRQ_TH_LO_LSB] = lt & 0xff;
+ mutex_unlock(&data->lock);
+
+ return ret;
+}
+
+/*
+ * interrupt ht
+ */
+static int isl29023_get_int_ht(struct i2c_client *client)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ int lsb, msb, ht;
+
+ mutex_lock(&data->lock);
+ lsb = i2c_smbus_read_byte_data(client, ISL29023_REG_IRQ_TH_HI_LSB);
+
+ if (lsb < 0) {
+ mutex_unlock(&data->lock);
+ return lsb;
+ }
+
+ msb = i2c_smbus_read_byte_data(client, ISL29023_REG_IRQ_TH_HI_MSB);
+ mutex_unlock(&data->lock);
+
+ if (msb < 0)
+ return msb;
+
+ ht = ((msb << 8) | lsb);
+
+ return ht;
+}
+
+static int isl29023_set_int_ht(struct i2c_client *client, int ht)
+{
+ int ret = 0;
+ struct isl29023_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->lock);
+ ret = i2c_smbus_write_byte_data(client, ISL29023_REG_IRQ_TH_HI_LSB,
+ ht & 0xff);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, ISL29023_REG_IRQ_TH_HI_MSB,
+ (ht >> 8) & 0xff);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ data->reg_cache[ISL29023_REG_IRQ_TH_HI_MSB] = (ht >> 8) & 0xff;
+ data->reg_cache[ISL29023_REG_IRQ_TH_HI_LSB] = ht & 0xff;
+ mutex_unlock(&data->lock);
+
+ return ret;
+}
+
+/*
+ * range
+ */
+static int isl29023_get_range(struct i2c_client *client)
+{
+ return __isl29023_read_reg(client, ISL29023_COMMAND2,
+ ISL29023_RANGE_MASK, ISL29023_RANGE_SHIFT);
+}
+
+static int isl29023_set_range(struct i2c_client *client, int range)
+{
+ return __isl29023_write_reg(client, ISL29023_COMMAND2,
+ ISL29023_RANGE_MASK, ISL29023_RANGE_SHIFT, range);
+}
+
+/*
+ * resolution
+ */
+static int isl29023_get_resolution(struct i2c_client *client)
+{
+ return __isl29023_read_reg(client, ISL29023_COMMAND2,
+ ISL29023_RES_MASK, ISL29023_RES_SHIFT);
+}
+
+static int isl29023_set_resolution(struct i2c_client *client, int res)
+{
+ return __isl29023_write_reg(client, ISL29023_COMMAND2,
+ ISL29023_RES_MASK, ISL29023_RES_SHIFT, res);
+}
+
+/*
+ * mode
+ */
+static int isl29023_get_mode(struct i2c_client *client)
+{
+ return __isl29023_read_reg(client, ISL29023_COMMAND1,
+ ISL29023_MODE_MASK, ISL29023_MODE_SHIFT);
+}
+
+static int isl29023_set_mode(struct i2c_client *client, int mode)
+{
+ return __isl29023_write_reg(client, ISL29023_COMMAND1,
+ ISL29023_MODE_MASK, ISL29023_MODE_SHIFT, mode);
+}
+
+/*
+ * power_state
+ */
+static int isl29023_set_power_state(struct i2c_client *client, int state)
+{
+ return __isl29023_write_reg(client, ISL29023_COMMAND1,
+ ISL29023_MODE_MASK, ISL29023_MODE_SHIFT,
+ state ?
+ ISL29023_ALS_ONCE_MODE : ISL29023_PD_MODE);
+}
+
+static int isl29023_get_power_state(struct i2c_client *client)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ u8 cmdreg = data->reg_cache[ISL29023_COMMAND1];
+
+ if (cmdreg & ISL29023_MODE_MASK)
+ return 1;
+ else
+ return 0;
+}
+
+static int isl29023_get_adc_value(struct i2c_client *client)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ int lsb, msb, range, bitdepth;
+
+ mutex_lock(&data->lock);
+ lsb = i2c_smbus_read_byte_data(client, ISL29023_REG_LSB_SENSOR);
+
+ if (lsb < 0) {
+ mutex_unlock(&data->lock);
+ return lsb;
+ }
+
+ msb = i2c_smbus_read_byte_data(client, ISL29023_REG_MSB_SENSOR);
+ mutex_unlock(&data->lock);
+
+ if (msb < 0)
+ return msb;
+
+ range = isl29023_get_range(client);
+ bitdepth = (4 - isl29023_get_resolution(client)) * 4;
+ return (((msb << 8) | lsb) * ((gain_range[range] * 499) / data->rext))
+ >> bitdepth;
+}
+
+static int isl29023_get_int_lt_value(struct i2c_client *client)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ int lsb, msb, range, bitdepth;
+
+ mutex_lock(&data->lock);
+ lsb = i2c_smbus_read_byte_data(client, ISL29023_REG_IRQ_TH_LO_LSB);
+
+ if (lsb < 0) {
+ mutex_unlock(&data->lock);
+ return lsb;
+ }
+
+ msb = i2c_smbus_read_byte_data(client, ISL29023_REG_IRQ_TH_LO_MSB);
+ mutex_unlock(&data->lock);
+
+ if (msb < 0)
+ return msb;
+
+ range = isl29023_get_range(client);
+ bitdepth = (4 - isl29023_get_resolution(client)) * 4;
+ return (((msb << 8) | lsb) * ((gain_range[range] * 499) / data->rext))
+ >> bitdepth;
+}
+
+static int isl29023_get_int_ht_value(struct i2c_client *client)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ int lsb, msb, range, bitdepth;
+
+ mutex_lock(&data->lock);
+ lsb = i2c_smbus_read_byte_data(client, ISL29023_REG_IRQ_TH_HI_LSB);
+
+ if (lsb < 0) {
+ mutex_unlock(&data->lock);
+ return lsb;
+ }
+
+ msb = i2c_smbus_read_byte_data(client, ISL29023_REG_IRQ_TH_HI_MSB);
+ mutex_unlock(&data->lock);
+
+ if (msb < 0)
+ return msb;
+
+ range = isl29023_get_range(client);
+ bitdepth = (4 - isl29023_get_resolution(client)) * 4;
+ return (((msb << 8) | lsb) * ((gain_range[range] * 499) / data->rext))
+ >> bitdepth;
+}
+
+/*
+ * sysfs layer
+ */
+
+/*
+ * interrupt persists
+ */
+static ssize_t isl29023_show_int_persists(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%i\n", isl29023_get_int_persists(client));
+}
+
+static ssize_t isl29023_store_int_persists(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val;
+ int ret;
+
+ if ((kstrtoul(buf, 10, &val) < 0) ||
+ (val > ISL29023_INT_PERSISTS_16))
+ return -EINVAL;
+
+ ret = isl29023_set_int_persists(client, val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(int_persists, S_IWUSR | S_IRUGO,
+ isl29023_show_int_persists, isl29023_store_int_persists);
+
+/*
+ *interrupt flag
+ */
+static ssize_t isl29023_show_int_flag(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%i\n", isl29023_get_int_flag(client));
+}
+
+static ssize_t isl29023_store_int_flag(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val;
+ int ret;
+
+ if ((kstrtoul(buf, 10, &val) < 0) || (val > 1))
+ return -EINVAL;
+
+ ret = isl29023_set_int_flag(client, val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(int_flag, S_IWUSR | S_IRUGO,
+ isl29023_show_int_flag, isl29023_store_int_flag);
+
+/*
+ * interrupt lt
+ */
+static ssize_t isl29023_show_int_lt(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%i\n", isl29023_get_int_lt(client));
+}
+
+static ssize_t isl29023_store_int_lt(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val;
+ int ret;
+
+ if ((kstrtoul(buf, 16, &val) < 0) || (val > 0xffff))
+ return -EINVAL;
+
+ ret = isl29023_set_int_lt(client, val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(int_lt, S_IWUSR | S_IRUGO,
+ isl29023_show_int_lt, isl29023_store_int_lt);
+
+/*
+ *interrupt ht
+ */
+static ssize_t isl29023_show_int_ht(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%i\n", isl29023_get_int_ht(client));
+}
+
+static ssize_t isl29023_store_int_ht(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val;
+ int ret;
+
+ if ((kstrtoul(buf, 16, &val) < 0) || (val > 0xffff))
+ return -EINVAL;
+
+ ret = isl29023_set_int_ht(client, val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(int_ht, S_IWUSR | S_IRUGO,
+ isl29023_show_int_ht, isl29023_store_int_ht);
+
+/*
+ * range
+ */
+static ssize_t isl29023_show_range(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%i\n", isl29023_get_range(client));
+}
+
+static ssize_t isl29023_store_range(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val;
+ int ret;
+
+ if ((kstrtoul(buf, 10, &val) < 0) || (val > ISL29023_RANGE_64K))
+ return -EINVAL;
+
+ ret = isl29023_set_range(client, val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(range, S_IWUSR | S_IRUGO,
+ isl29023_show_range, isl29023_store_range);
+
+
+/*
+ * resolution
+ */
+static ssize_t isl29023_show_resolution(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%d\n", isl29023_get_resolution(client));
+}
+
+static ssize_t isl29023_store_resolution(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val;
+ int ret;
+
+ if ((kstrtoul(buf, 10, &val) < 0) || (val > ISL29023_RES_4))
+ return -EINVAL;
+
+ ret = isl29023_set_resolution(client, val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(resolution, S_IWUSR | S_IRUGO,
+ isl29023_show_resolution, isl29023_store_resolution);
+
+/*
+ *mode
+ */
+static ssize_t isl29023_show_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%d\n", isl29023_get_mode(client));
+}
+
+static ssize_t isl29023_store_mode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val;
+ int ret;
+
+ if ((kstrtoul(buf, 10, &val) < 0) ||
+ (val > ISL29023_IR_CONT_MODE))
+ return -EINVAL;
+
+ /* clear the interrupt flag */
+ i2c_smbus_read_byte_data(client, ISL29023_COMMAND1);
+ ret = isl29023_set_mode(client, val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO,
+ isl29023_show_mode, isl29023_store_mode);
+
+
+/*
+ *power state
+ */
+static ssize_t isl29023_show_power_state(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%d\n", isl29023_get_power_state(client));
+}
+
+static ssize_t isl29023_store_power_state(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val;
+ int ret;
+
+ if ((kstrtoul(buf, 10, &val) < 0) || (val > 1))
+ return -EINVAL;
+
+ ret = isl29023_set_power_state(client, val);
+ return ret ? ret : count;
+}
+
+static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
+ isl29023_show_power_state, isl29023_store_power_state);
+
+/*
+ * lux
+ */
+static ssize_t isl29023_show_lux(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ /* No LUX data if not operational */
+ if (!isl29023_get_power_state(client))
+ return -EBUSY;
+
+ return sprintf(buf, "%d\n", isl29023_get_adc_value(client));
+}
+
+static DEVICE_ATTR(lux, S_IRUGO, isl29023_show_lux, NULL);
+
+/*
+ * lux interrupt low threshold
+ */
+static ssize_t isl29023_show_int_lt_lux(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ /* No LUX data if not operational */
+ if (isl29023_get_mode(client) != ISL29023_ALS_ONCE_MODE &&
+ isl29023_get_mode(client) != ISL29023_ALS_CONT_MODE)
+ return -EIO;
+
+ return sprintf(buf, "%d\n", isl29023_get_int_lt_value(client));
+}
+
+static ssize_t isl29023_store_int_lt_lux(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ unsigned long val, lux_data;
+ int range, bitdepth, ret;
+ u8 lsb, msb;
+
+ if ((kstrtoul(buf, 10, &val) < 0))
+ return -EINVAL;
+
+ /* No LUX data if not operational */
+ if (isl29023_get_mode(client) != ISL29023_ALS_ONCE_MODE &&
+ isl29023_get_mode(client) != ISL29023_ALS_CONT_MODE)
+ return -EIO;
+
+ if (val > (gain_range[isl29023_get_range(client)]*499/data->rext))
+ return -EINVAL;
+
+ range = isl29023_get_range(client);
+ bitdepth = (4 - isl29023_get_resolution(client)) * 4;
+ lux_data = ((unsigned long)(val << bitdepth)) /
+ ((gain_range[range] * 499) / data->rext);
+ lux_data &= 0xffff;
+
+ msb = lux_data >> 8;
+ lsb = lux_data & 0xff;
+
+ mutex_lock(&data->lock);
+ ret = i2c_smbus_write_byte_data(client, ISL29023_REG_IRQ_TH_LO_LSB,
+ lsb);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, ISL29023_REG_IRQ_TH_LO_MSB,
+ msb);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ data->reg_cache[ISL29023_REG_IRQ_TH_LO_MSB] = msb;
+ data->reg_cache[ISL29023_REG_IRQ_TH_LO_LSB] = lsb;
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(int_lt_lux, S_IWUSR | S_IRUGO,
+ isl29023_show_int_lt_lux, isl29023_store_int_lt_lux);
+
+/*
+ * lux interrupt high threshold
+ */
+static ssize_t isl29023_show_int_ht_lux(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ /* No LUX data if not operational */
+ if (isl29023_get_mode(client) != ISL29023_ALS_ONCE_MODE &&
+ isl29023_get_mode(client) != ISL29023_ALS_CONT_MODE)
+ return -EIO;
+
+ return sprintf(buf, "%d\n", isl29023_get_int_ht_value(client));
+}
+
+static ssize_t isl29023_store_int_ht_lux(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ unsigned long val, lux_data;
+ int range, bitdepth, ret;
+ u8 lsb, msb;
+
+ if ((kstrtoul(buf, 10, &val) < 0))
+ return -EINVAL;
+
+ /* No LUX data if not operational */
+ if (isl29023_get_mode(client) != ISL29023_ALS_ONCE_MODE &&
+ isl29023_get_mode(client) != ISL29023_ALS_CONT_MODE)
+ return -EIO;
+
+ if (val > (gain_range[isl29023_get_range(client)]*499/data->rext))
+ return -EINVAL;
+
+ range = isl29023_get_range(client);
+ bitdepth = (4 - isl29023_get_resolution(client)) * 4;
+ lux_data = ((unsigned long)(val << bitdepth)) /
+ ((gain_range[range] * 499) / data->rext);
+ lux_data &= 0xffff;
+
+ msb = lux_data >> 8;
+ lsb = lux_data & 0xff;
+
+ mutex_lock(&data->lock);
+ ret = i2c_smbus_write_byte_data(client, ISL29023_REG_IRQ_TH_HI_LSB,
+ lsb);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ ret = i2c_smbus_write_byte_data(client, ISL29023_REG_IRQ_TH_HI_MSB,
+ msb);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ data->reg_cache[ISL29023_REG_IRQ_TH_HI_MSB] = msb;
+ data->reg_cache[ISL29023_REG_IRQ_TH_HI_LSB] = lsb;
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(int_ht_lux, S_IWUSR | S_IRUGO,
+ isl29023_show_int_ht_lux, isl29023_store_int_ht_lux);
+
+static struct attribute *isl29023_attributes[] = {
+ &dev_attr_int_persists.attr,
+ &dev_attr_range.attr,
+ &dev_attr_resolution.attr,
+ &dev_attr_mode.attr,
+ &dev_attr_power_state.attr,
+ &dev_attr_lux.attr,
+ &dev_attr_int_lt_lux.attr,
+ &dev_attr_int_ht_lux.attr,
+ &dev_attr_int_lt.attr,
+ &dev_attr_int_ht.attr,
+ &dev_attr_int_flag.attr,
+ NULL
+};
+
+static const struct attribute_group isl29023_attr_group = {
+ .attrs = isl29023_attributes,
+};
+
+static int isl29023_init_client(struct i2c_client *client)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+ int i;
+
+ /* read all the registers once to fill the cache.
+ * if one of the reads fails, we consider the init failed */
+ for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) {
+ int v = i2c_smbus_read_byte_data(client, i);
+ if (v < 0)
+ return -ENODEV;
+
+ data->reg_cache[i] = v;
+ }
+
+ /* set defaults */
+ isl29023_set_int_persists(client, ISL29023_INT_PERSISTS_8);
+ isl29023_set_int_ht(client, 0xffff);
+ isl29023_set_int_lt(client, 0x0);
+ isl29023_set_range(client, ISL29023_RANGE_16K);
+ isl29023_set_resolution(client, ISL29023_RES_16);
+ isl29023_set_mode(client, ISL29023_ALS_ONCE_MODE);
+ isl29023_set_int_flag(client, 0);
+ isl29023_set_power_state(client, 0);
+
+ return 0;
+}
+
+static void isl29023_work(struct work_struct *work)
+{
+ struct isl29023_data *data =
+ container_of(work, struct isl29023_data, work);
+ struct i2c_client *client = data->client;
+ int lux;
+
+ /* Clear interrupt flag */
+ isl29023_set_int_flag(client, 0);
+
+ data->mode_before_interrupt = isl29023_get_mode(client);
+ lux = isl29023_get_adc_value(client);
+
+ /* To clear the interrpt status */
+ isl29023_set_power_state(client, ISL29023_PD_MODE);
+ isl29023_set_mode(client, data->mode_before_interrupt);
+
+ msleep(100);
+
+ input_report_abs(data->input, ABS_MISC, lux);
+ input_sync(data->input);
+}
+
+static irqreturn_t isl29023_irq_handler(int irq, void *handle)
+{
+ struct isl29023_data *data = handle;
+ int cmd_1;
+ cmd_1 = i2c_smbus_read_byte_data(data->client, ISL29023_COMMAND1);
+ if (!(cmd_1 & ISL29023_INT_FLAG_MASK))
+ return IRQ_NONE;
+
+ queue_work(data->workqueue, &data->work);
+ return IRQ_HANDLED;
+}
+
+/*
+ * I2C layer
+ */
+static int isl29023_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct isl29023_data *data;
+ struct input_dev *input_dev;
+ int err = 0;
+ struct regulator *vdd = NULL;
+ u32 rext = 0;
+ struct device_node *of_node = client->dev.of_node;
+ struct irq_data *irq_data = irq_get_irq_data(client->irq);
+ u32 irq_flag;
+ bool shared_irq;
+
+ vdd = devm_regulator_get(&client->dev, "vdd");
+ if (!IS_ERR(vdd)) {
+ err = regulator_enable(vdd);
+ if (err) {
+ dev_err(&client->dev, "vdd set voltage error\n");
+ return err;
+ }
+ }
+
+ err = of_property_read_u32(of_node, "rext", &rext);
+ if (err)
+ rext = DEFAULT_REGISTOR_VAL;
+ shared_irq = of_property_read_bool(of_node, "shared-interrupt");
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
+ return -EIO;
+
+ data = kzalloc(sizeof(struct isl29023_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->client = client;
+ data->rext = (u16)rext;
+ snprintf(data->phys, sizeof(data->phys),
+ "%s", dev_name(&client->dev));
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->lock);
+
+ /* initialize the ISL29023 chip */
+ err = isl29023_init_client(client);
+ if (err)
+ goto exit_kfree;
+
+ /* register sysfs hooks */
+ err = sysfs_create_group(&client->dev.kobj, &isl29023_attr_group);
+ if (err)
+ goto exit_kfree;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto exit_kfree;
+ }
+
+ data->input = input_dev;
+ input_dev->name = "isl29023 light sensor";
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->phys = data->phys;
+
+ __set_bit(EV_ABS, input_dev->evbit);
+ input_set_abs_params(input_dev, ABS_MISC, 0,
+ gain_range[DEF_RANGE]*499/data->rext, 0, 0);
+
+ err = input_register_device(input_dev);
+ if (err)
+ goto exit_free_input;
+
+ irq_flag = irqd_get_trigger_type(irq_data);
+ irq_flag |= IRQF_ONESHOT;
+ if (shared_irq)
+ irq_flag |= IRQF_SHARED;
+ err = request_threaded_irq(client->irq, NULL,
+ isl29023_irq_handler, irq_flag,
+ client->dev.driver->name, data);
+ if (err < 0) {
+ dev_err(&client->dev, "failed to register irq %d!\n",
+ client->irq);
+ goto exit_free_input;
+ }
+
+ data->workqueue = create_singlethread_workqueue("isl29023");
+ INIT_WORK(&data->work, isl29023_work);
+ if (data->workqueue == NULL) {
+ dev_err(&client->dev, "couldn't create workqueue\n");
+ err = -ENOMEM;
+ goto exit_free_interrupt;
+ }
+
+ dev_info(&client->dev, "driver version %s enabled\n", DRIVER_VERSION);
+ return 0;
+
+exit_free_interrupt:
+ free_irq(client->irq, data);
+exit_free_input:
+ input_free_device(input_dev);
+exit_kfree:
+ kfree(data);
+ return err;
+}
+
+static int isl29023_remove(struct i2c_client *client)
+{
+ struct isl29023_data *data = i2c_get_clientdata(client);
+
+ cancel_work_sync(&data->work);
+ destroy_workqueue(data->workqueue);
+ free_irq(client->irq, data);
+ input_unregister_device(data->input);
+ input_free_device(data->input);
+ sysfs_remove_group(&client->dev.kobj, &isl29023_attr_group);
+ isl29023_set_power_state(client, 0);
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int isl29023_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct isl29023_data *data = i2c_get_clientdata(client);
+
+ data->mode_before_suspend = isl29023_get_mode(client);
+ return isl29023_set_power_state(client, ISL29023_PD_MODE);
+}
+
+static int isl29023_resume(struct device *dev)
+{
+ int i;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct isl29023_data *data = i2c_get_clientdata(client);
+
+ /* restore registers from cache */
+ for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++)
+ if (i2c_smbus_write_byte_data(client, i, data->reg_cache[i]))
+ return -EIO;
+
+ return isl29023_set_mode(client, data->mode_before_suspend);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(isl29023_pm_ops, isl29023_suspend, isl29023_resume);
+
+static const struct i2c_device_id isl29023_id[] = {
+ { ISL29023_DRV_NAME, 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, isl29023_id);
+
+static struct i2c_driver isl29023_driver = {
+ .driver = {
+ .name = ISL29023_DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &isl29023_pm_ops,
+ },
+ .probe = isl29023_probe,
+ .remove = isl29023_remove,
+ .id_table = isl29023_id,
+};
+
+static int __init isl29023_init(void)
+{
+ return i2c_add_driver(&isl29023_driver);
+}
+
+static void __exit isl29023_exit(void)
+{
+ i2c_del_driver(&isl29023_driver);
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("ISL29023 ambient light sensor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(isl29023_init);
+module_exit(isl29023_exit);
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
index 19c73574458e..7df8e6d1f337 100644
--- a/drivers/input/misc/mma8450.c
+++ b/drivers/input/misc/mma8450.c
@@ -1,7 +1,7 @@
/*
* Driver for Freescale's 3-Axis Accelerometer MMA8450
*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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
@@ -25,6 +25,7 @@
#include <linux/i2c.h>
#include <linux/input-polldev.h>
#include <linux/of_device.h>
+#include <linux/mutex.h>
#define MMA8450_DRV_NAME "mma8450"
@@ -51,11 +52,22 @@
#define MMA8450_CTRL_REG1 0x38
#define MMA8450_CTRL_REG2 0x39
+#define MMA8450_ID 0xC6
+#define MMA8450_WHO_AM_I 0x0F
+
+enum {
+ MODE_STANDBY = 0,
+ MODE_2G,
+ MODE_4G,
+ MODE_8G,
+};
/* mma8450 status */
struct mma8450 {
struct i2c_client *client;
struct input_polled_dev *idev;
+ struct mutex mma8450_lock;
+ u8 mode;
};
static int mma8450_read(struct mma8450 *m, unsigned off)
@@ -112,16 +124,19 @@ static void mma8450_poll(struct input_polled_dev *dev)
int ret;
u8 buf[6];
- ret = mma8450_read(m, MMA8450_STATUS);
- if (ret < 0)
- return;
+ mutex_lock(&m->mma8450_lock);
- if (!(ret & MMA8450_STATUS_ZXYDR))
+ ret = mma8450_read(m, MMA8450_STATUS);
+ if (ret < 0 || !(ret & MMA8450_STATUS_ZXYDR)) {
+ mutex_unlock(&m->mma8450_lock);
return;
+ }
ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf));
- if (ret < 0)
+ if (ret < 0) {
+ mutex_unlock(&m->mma8450_lock);
return;
+ }
x = ((int)(s8)buf[1] << 4) | (buf[0] & 0xf);
y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf);
@@ -131,10 +146,12 @@ static void mma8450_poll(struct input_polled_dev *dev)
input_report_abs(dev->input, ABS_Y, y);
input_report_abs(dev->input, ABS_Z, z);
input_sync(dev->input);
+
+ mutex_unlock(&m->mma8450_lock);
}
/* Initialize the MMA8450 chip */
-static void mma8450_open(struct input_polled_dev *dev)
+static s32 mma8450_open(struct input_polled_dev *dev)
{
struct mma8450 *m = dev->private;
int err;
@@ -142,18 +159,20 @@ static void mma8450_open(struct input_polled_dev *dev)
/* enable all events from X/Y/Z, no FIFO */
err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
if (err)
- return;
+ return err;
/*
* Sleep mode poll rate - 50Hz
* System output data rate - 400Hz
- * Full scale selection - Active, +/- 2G
+ * Standby mode
*/
- err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
- if (err < 0)
- return;
-
+ err = mma8450_write(m, MMA8450_CTRL_REG1, MODE_STANDBY);
+ if (err)
+ return err;
+ m->mode = MODE_STANDBY;
msleep(MODE_CHANGE_DELAY_MS);
+
+ return 0;
}
static void mma8450_close(struct input_polled_dev *dev)
@@ -164,6 +183,76 @@ static void mma8450_close(struct input_polled_dev *dev)
mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
}
+static ssize_t mma8450_scalemode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int mode = 0;
+ struct mma8450 *m;
+ struct i2c_client *client = to_i2c_client(dev);
+
+ m = i2c_get_clientdata(client);
+
+ mutex_lock(&m->mma8450_lock);
+ mode = (int)m->mode;
+ mutex_unlock(&m->mma8450_lock);
+
+ return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t mma8450_scalemode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long mode;
+ int ret;
+ struct mma8450 *m = NULL;
+ struct i2c_client *client = to_i2c_client(dev);
+
+ ret = kstrtoul(buf, 10, &mode);
+ if (ret) {
+ dev_err(dev, "string transform error\n");
+ return ret;
+ }
+
+ if (mode > MODE_8G) {
+ dev_warn(dev, "not supported mode %d\n", (int)mode);
+ return count;
+ }
+
+ m = i2c_get_clientdata(client);
+
+ mutex_lock(&m->mma8450_lock);
+ if (mode == m->mode) {
+ mutex_unlock(&m->mma8450_lock);
+ return count;
+ }
+
+ ret = mma8450_write(m, MMA8450_CTRL_REG1, mode);
+ if (ret < 0) {
+ mutex_unlock(&m->mma8450_lock);
+ return ret;
+ }
+
+ msleep(MODE_CHANGE_DELAY_MS);
+ m->mode = (u8)mode;
+ mutex_unlock(&m->mma8450_lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO,
+ mma8450_scalemode_show, mma8450_scalemode_store);
+
+static struct attribute *mma8450_attributes[] = {
+ &dev_attr_scalemode.attr,
+ NULL
+};
+
+static const struct attribute_group mma8450_attr_group = {
+ .attrs = mma8450_attributes,
+};
+
/*
* I2C init/probing/exit functions
*/
@@ -172,7 +261,24 @@ static int mma8450_probe(struct i2c_client *c,
{
struct input_polled_dev *idev;
struct mma8450 *m;
- int err;
+ int err, client_id;
+ struct i2c_adapter *adapter = NULL;
+
+ adapter = to_i2c_adapter(c->dev.parent);
+ err = i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA);
+ if (!err)
+ return err;
+
+ client_id = i2c_smbus_read_byte_data(c, MMA8450_WHO_AM_I);
+
+ if (MMA8450_ID != client_id) {
+ dev_err(&c->dev,
+ "read chip ID 0x%x is not equal to 0x%x!\n", client_id,
+ MMA8450_ID);
+ return -EINVAL;
+ }
m = devm_kzalloc(&c->dev, sizeof(*m), GFP_KERNEL);
if (!m)
@@ -184,6 +290,7 @@ static int mma8450_probe(struct i2c_client *c,
m->client = c;
m->idev = idev;
+ i2c_set_clientdata(c, m);
idev->private = m;
idev->input->name = MMA8450_DRV_NAME;
@@ -191,8 +298,6 @@ static int mma8450_probe(struct i2c_client *c,
idev->poll = mma8450_poll;
idev->poll_interval = POLL_INTERVAL;
idev->poll_interval_max = POLL_INTERVAL_MAX;
- idev->open = mma8450_open;
- idev->close = mma8450_close;
__set_bit(EV_ABS, idev->input->evbit);
input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
@@ -205,7 +310,40 @@ static int mma8450_probe(struct i2c_client *c,
return err;
}
- i2c_set_clientdata(c, m);
+ mutex_init(&m->mma8450_lock);
+
+ err = mma8450_open(idev);
+ if (err) {
+ dev_err(&c->dev, "failed to initialize mma8450\n");
+ goto err_unreg_dev;
+ }
+
+ err = sysfs_create_group(&c->dev.kobj, &mma8450_attr_group);
+ if (err) {
+ dev_err(&c->dev, "create device file failed!\n");
+ err = -EINVAL;
+ goto err_close;
+ }
+
+ return 0;
+
+err_close:
+ mma8450_close(idev);
+err_unreg_dev:
+ mutex_destroy(&m->mma8450_lock);
+ input_unregister_polled_device(idev);
+ return err;
+}
+
+static int mma8450_remove(struct i2c_client *c)
+{
+ struct mma8450 *m = i2c_get_clientdata(c);
+ struct input_polled_dev *idev = m->idev;
+
+ sysfs_remove_group(&c->dev.kobj, &mma8450_attr_group);
+ mma8450_close(idev);
+ mutex_destroy(&m->mma8450_lock);
+ input_unregister_polled_device(idev);
return 0;
}
@@ -228,6 +366,7 @@ static struct i2c_driver mma8450_driver = {
.of_match_table = mma8450_dt_ids,
},
.probe = mma8450_probe,
+ .remove = mma8450_remove,
.id_table = mma8450_id,
};
diff --git a/drivers/input/misc/mpl3115.c b/drivers/input/misc/mpl3115.c
new file mode 100644
index 000000000000..b272cf38a645
--- /dev/null
+++ b/drivers/input/misc/mpl3115.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2010-2015 Freescale , 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/input-polldev.h>
+
+#define MPL3115_DRV_NAME "mpl3115"
+#define ABS_TEMPTERAURE ABS_MISC
+
+#define INPUT_FUZZ 32
+#define INPUT_FLAT 32
+#define MPL_ACTIVED 1
+#define MPL_STANDBY 0
+#define POLL_INTERVAL_MAX 500
+#define POLL_INTERVAL 100
+#define POLL_INTERVAL_MIN 1
+#define MPL3115_ID 0xc4
+#define MPLL_ACTIVE_MASK 0x01
+#define MPL3115_STATUS_DR 0x08
+
+/* MPL3115A register address */
+#define MPL3115_STATUS 0x00
+#define MPL3115_PRESSURE_DATA 0x01
+#define MPL3115_DR_STATUS 0x06
+#define MPL3115_DELTA_DATA 0x07
+#define MPL3115_WHO_AM_I 0x0c
+#define MPL3115_FIFO_STATUS 0x0d
+#define MPL3115_FIFO_DATA 0x0e
+#define MPL3115_FIFO_SETUP 0x0e
+#define MPL3115_TIME_DELAY 0x10
+#define MPL3115_SYS_MODE 0x11
+#define MPL3115_INT_SORCE 0x12
+#define MPL3115_PT_DATA_CFG 0x13
+#define MPL3115_BAR_IN_MSB 0x14
+#define MPL3115_P_ARLARM_MSB 0x16
+#define MPL3115_T_ARLARM 0x18
+#define MPL3115_P_ARLARM_WND_MSB 0x19
+#define MPL3115_T_ARLARM_WND 0x1b
+#define MPL3115_P_MIN_DATA 0x1c
+#define MPL3115_T_MIN_DATA 0x1f
+#define MPL3115_P_MAX_DATA 0x21
+#define MPL3115_T_MAX_DATA 0x24
+#define MPL3115_CTRL_REG1 0x26
+#define MPL3115_CTRL_REG2 0x27
+#define MPL3115_CTRL_REG3 0x28
+#define MPL3115_CTRL_REG4 0x29
+#define MPL3115_CTRL_REG5 0x2a
+#define MPL3115_OFFSET_P 0x2b
+#define MPL3115_OFFSET_T 0x2c
+#define MPL3115_OFFSET_H 0x2d
+
+#define DATA_SHIFT_BIT(data, bit) ((data << bit) & (0xff << bit))
+
+struct mpl3115_data {
+ struct i2c_client *client;
+ struct input_polled_dev *poll_dev;
+ struct mutex data_lock;
+ int active;
+};
+
+static int mpl3115_i2c_read(struct i2c_client *client, u8 reg, u8 *values, u8 length)
+{
+ return i2c_smbus_read_i2c_block_data(client, reg, length, values);
+}
+
+static int mpl3115_i2c_write(struct i2c_client *client, u8 reg, const u8 *values, u8 length)
+{
+ return i2c_smbus_write_i2c_block_data(client, reg, length, values);
+}
+
+static ssize_t mpl3115_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int val;
+ u8 sysmode;
+
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mpl3115_data *pdata = (struct mpl3115_data *)(poll_dev->private);
+ struct i2c_client *client = pdata->client;
+ mutex_lock(&pdata->data_lock);
+ mpl3115_i2c_read(client, MPL3115_CTRL_REG1, &sysmode, 1);
+ sysmode &= MPLL_ACTIVE_MASK;
+ val = (sysmode ? 1 : 0);
+ mutex_unlock(&pdata->data_lock);
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t mpl3115_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, enable;
+ u8 val;
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mpl3115_data *pdata = (struct mpl3115_data *)(poll_dev->private);
+ struct i2c_client *client = pdata->client;
+
+ enable = simple_strtoul(buf, NULL, 10);
+ mutex_lock(&pdata->data_lock);
+ mpl3115_i2c_read(client, MPL3115_CTRL_REG1, &val, 1);
+ if (enable && pdata->active == MPL_STANDBY) {
+ val |= MPLL_ACTIVE_MASK;
+ ret = mpl3115_i2c_write(client, MPL3115_CTRL_REG1, &val, 1);
+ if (!ret)
+ pdata->active = MPL_ACTIVED;
+ printk("mpl3115 set active\n");
+ } else if (!enable && pdata->active == MPL_ACTIVED) {
+ val &= ~MPLL_ACTIVE_MASK;
+ ret = mpl3115_i2c_write(client, MPL3115_CTRL_REG1, &val, 1);
+ if (!ret)
+ pdata->active = MPL_STANDBY;
+ printk("mpl3115 set inactive\n");
+ }
+ mutex_unlock(&pdata->data_lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, mpl3115_enable_show, mpl3115_enable_store);
+
+static struct attribute *mpl3115_attributes[] = {
+ &dev_attr_enable.attr,
+ NULL
+};
+
+static const struct attribute_group mpl3115_attr_group = {
+ .attrs = mpl3115_attributes,
+};
+
+static void mpl3115_device_init(struct i2c_client *client)
+{
+ u8 val[8];
+
+ val[0] = 0x28;
+ mpl3115_i2c_write(client, MPL3115_CTRL_REG1, val, 1);
+}
+
+static int mpl3115_read_data(struct i2c_client *client, int *pres, short *temp)
+{
+ u8 tmp[5];
+
+ mpl3115_i2c_read(client, MPL3115_PRESSURE_DATA, tmp, 5);
+ *pres = (DATA_SHIFT_BIT(tmp[0], 24) | DATA_SHIFT_BIT(tmp[1], 16) | DATA_SHIFT_BIT(tmp[2], 8)) >> 12;
+ *temp = (DATA_SHIFT_BIT(tmp[3], 8) | DATA_SHIFT_BIT(tmp[4], 0)) >> 4;
+ return 0;
+}
+
+static void report_abs(struct mpl3115_data *pdata)
+{
+ struct input_dev *idev;
+ int pressure = 0;
+ short temperature = 0;
+
+ mutex_lock(&pdata->data_lock);
+ if (pdata->active == MPL_STANDBY)
+ goto out;
+ idev = pdata->poll_dev->input;
+ mpl3115_read_data(pdata->client, &pressure, &temperature);
+ input_report_abs(idev, ABS_PRESSURE, pressure);
+ input_report_abs(idev, ABS_TEMPTERAURE, temperature);
+ input_sync(idev);
+out:
+ mutex_unlock(&pdata->data_lock);
+}
+
+static void mpl3115_dev_poll(struct input_polled_dev *dev)
+{
+ struct mpl3115_data *pdata = (struct mpl3115_data *)dev->private;
+
+ report_abs(pdata);
+}
+
+static int mpl3115_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result, client_id;
+ struct input_dev *idev;
+ struct i2c_adapter *adapter;
+ struct mpl3115_data *pdata;
+ adapter = to_i2c_adapter(client->dev.parent);
+ result = i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA);
+ if (!result)
+ goto err_out;
+
+ client_id = i2c_smbus_read_byte_data(client, MPL3115_WHO_AM_I);
+ printk("read mpl3115 chip id 0x%x\n", client_id);
+ if (client_id != MPL3115_ID) {
+ dev_err(&client->dev,
+ "read chip ID 0x%x is not equal to 0x%x!\n",
+ result, MPL3115_ID);
+ result = -EINVAL;
+ goto err_out;
+ }
+ pdata = kzalloc(sizeof(struct mpl3115_data), GFP_KERNEL);
+ if (!pdata)
+ goto err_out;
+ pdata->client = client;
+ i2c_set_clientdata(client, pdata);
+ mutex_init(&pdata->data_lock);
+ pdata->poll_dev = input_allocate_polled_device();
+ if (!pdata->poll_dev) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "alloc poll device failed!\n");
+ goto err_alloc_data;
+ }
+ pdata->poll_dev->poll = mpl3115_dev_poll;
+ pdata->poll_dev->private = pdata;
+ pdata->poll_dev->poll_interval = POLL_INTERVAL;
+ pdata->poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
+ pdata->poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
+ idev = pdata->poll_dev->input;
+ idev->name = MPL3115_DRV_NAME;
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+
+ input_set_abs_params(idev, ABS_PRESSURE, -0x7FFFFFFF, 0x7FFFFFFF, 0, 0);
+ input_set_abs_params(idev, ABS_TEMPTERAURE, -0x7FFFFFFF, 0x7FFFFFFF, 0, 0);
+ result = input_register_polled_device(pdata->poll_dev);
+ if (result) {
+ dev_err(&client->dev, "register poll device failed!\n");
+ goto error_free_poll_dev;
+ }
+ result = sysfs_create_group(&idev->dev.kobj, &mpl3115_attr_group);
+ if (result) {
+ dev_err(&client->dev, "create device file failed!\n");
+ result = -EINVAL;
+ goto error_register_polled_device;
+ }
+ mpl3115_device_init(client);
+ printk("mpl3115 device driver probe successfully");
+ return 0;
+error_register_polled_device:
+ input_unregister_polled_device(pdata->poll_dev);
+error_free_poll_dev:
+ input_free_polled_device(pdata->poll_dev);
+err_alloc_data:
+ kfree(pdata);
+err_out:
+ return result;
+}
+
+static int mpl3115_stop_chip(struct i2c_client *client)
+{
+ u8 val;
+ int ret;
+
+ mpl3115_i2c_read(client, MPL3115_CTRL_REG1, &val, 1);
+ val &= ~MPLL_ACTIVE_MASK;
+ ret = mpl3115_i2c_write(client, MPL3115_CTRL_REG1, &val, 1);
+
+ return 0;
+}
+static int mpl3115_start_chip(struct i2c_client *client)
+{
+ u8 val;
+ int ret;
+
+ mpl3115_i2c_read(client, MPL3115_CTRL_REG1, &val, 1);
+ val |= MPLL_ACTIVE_MASK;
+ ret = mpl3115_i2c_write(client, MPL3115_CTRL_REG1, &val, 1);
+
+ return 0;
+}
+static int mpl3115_remove(struct i2c_client *client)
+{
+ struct mpl3115_data *pdata = i2c_get_clientdata(client);
+ struct input_dev *idev = pdata->poll_dev->input;
+
+ mpl3115_stop_chip(client);
+ sysfs_remove_group(&idev->dev.kobj, &mpl3115_attr_group);
+ input_unregister_polled_device(pdata->poll_dev);
+ kfree(pdata);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mpl3115_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mpl3115_data *pdata = i2c_get_clientdata(client);
+ if (pdata->active == MPL_ACTIVED)
+ mpl3115_stop_chip(client);
+ return 0;
+}
+
+static int mpl3115_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mpl3115_data *pdata = i2c_get_clientdata(client);
+ if (pdata->active == MPL_ACTIVED)
+ mpl3115_start_chip(client);
+ return 0;
+}
+#endif
+
+static const struct i2c_device_id mpl3115_id[] = {
+ {MPL3115_DRV_NAME, 0},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, mpl3115_id);
+
+static SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend, mpl3115_resume);
+static struct i2c_driver mpl3115_driver = {
+ .driver = {
+ .name = MPL3115_DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &mpl3115_pm_ops,
+ },
+ .probe = mpl3115_probe,
+ .remove = mpl3115_remove,
+ .id_table = mpl3115_id,
+};
+
+module_i2c_driver(mpl3115_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MPL3115 Smart Pressure Sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index efca0133e266..c6cd111d374a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -46,6 +46,19 @@ config TOUCHSCREEN_ADS7846
To compile this driver as a module, choose M here: the
module will be called ads7846.
+config TOUCHSCREEN_CT36X_WLD
+ default y
+ tristate "CT36X based touchscreens for WLD"
+ help
+ Say Y here if you have a touchscreen interface using the
+ CT36X controller, i2c touchscreen
+ controller.
+
+ If unsure, say N (but it's safe to say "Y").
+
+ To compile this driver as a module, choose M here: the
+ module will be called vtl_ts.
+
config TOUCHSCREEN_AD7877
tristate "AD7877 based touchscreens"
depends on SPI_MASTER
@@ -314,6 +327,18 @@ config TOUCHSCREEN_EGALAX_SERIAL
To compile this driver as a module, choose M here: the
module will be called egalax_ts_serial.
+config TOUCHSCREEN_ELAN_TS
+ tristate "ELAN touchscreen input driver"
+ depends on I2C
+ help
+ Say Y here if you have an I2C ELAN touchscreen
+ attached.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called elan-touch.
+
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
@@ -1215,3 +1240,5 @@ config TOUCHSCREEN_ROHM_BU21023
module will be called bu21023_ts.
endif
+
+source "drivers/input/touchscreen/focaltech_touch/Kconfig"
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 81b86451782d..7037a08af011 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -35,8 +35,10 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_EKTF2127) += ektf2127.o
obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
+obj-$(CONFIG_TOUCHSCREEN_ELAN_TS) += elan_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_touch/
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
@@ -96,6 +98,7 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_CT36X_WLD) += vtl/
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 1ce3ecbe37f8..fc21a7459e3e 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -1188,6 +1188,7 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
struct ads7846_platform_data *pdata;
struct device_node *node = dev->of_node;
const struct of_device_id *match;
+ int ret;
if (!node) {
dev_err(dev, "Device does not have associated DT data\n");
@@ -1233,8 +1234,11 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol);
of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep);
- of_property_read_u32(node, "ti,pendown-gpio-debounce",
+ ret = of_property_read_u32(node, "ti,pendown-gpio-debounce",
&pdata->gpio_pendown_debounce);
+ if (!ret)
+ dev_info(dev, "Set pendown gpio debounce time to %d microseconds\n",
+ pdata->gpio_pendown_debounce);
pdata->wakeup = of_property_read_bool(node, "wakeup-source") ||
of_property_read_bool(node, "linux,wakeup");
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index 1afc08b08155..d5f41cbb599e 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -186,6 +186,20 @@ static int egalax_ts_probe(struct i2c_client *client,
ts->client = client;
ts->input_dev = input_dev;
+ /* HannStar (HSD100PXN1 Rev: 1-A00C11 F/W:0634) LVDS touch
+ * screen needs to trigger I2C event to device FW at booting
+ * first, and then the FW can switch to I2C interface.
+ * Otherwise, the FW can’t work with I2C interface. So here
+ * just use the exist function egalax_firmware_version() to
+ * send a I2C command to the device, make sure the device FW
+ * switch to I2C interface.
+ */
+ error = egalax_firmware_version(client);
+ if (error) {
+ dev_err(&client->dev, "Failed to switch to I2C interface\n");
+ return error;
+ }
+
/* controller may be in sleep, wake it up. */
error = egalax_wake_up_device(client);
if (error) {
diff --git a/drivers/input/touchscreen/elan_ts.c b/drivers/input/touchscreen/elan_ts.c
new file mode 100644
index 000000000000..8590a947b624
--- /dev/null
+++ b/drivers/input/touchscreen/elan_ts.c
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2007-2008 HTC Corporation.
+ *
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
+ *
+ * This driver is adapted from elan8232_i2c.c written by Shan-Fu Chiou
+ * <sfchiou@gmail.com> and Jay Tu <jay_tu@htc.com>.
+ * This driver is also adapted from the ELAN Touch Screen driver
+ * written by Stanley Zeng <stanley.zeng@emc.com.tw>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/input.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/hrtimer.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+
+static const char ELAN_TS_NAME[] = "elan-touch";
+
+#define ELAN_TS_X_MAX 1088
+#define ELAN_TS_Y_MAX 768
+#define ELAN_USER_X_MAX 800
+#define ELAN_USER_Y_MAX 600
+#define IDX_PACKET_SIZE 8
+
+enum {
+ hello_packet = 0x55,
+ idx_coordinate_packet = 0x5a,
+};
+
+enum {
+ idx_finger_state = 7,
+};
+
+static struct workqueue_struct *elan_wq;
+
+static struct elan_data {
+ int intr_gpio;
+ int use_irq;
+ struct hrtimer timer;
+ struct work_struct work;
+ struct i2c_client *client;
+ struct input_dev *input;
+ wait_queue_head_t wait;
+} elan_touch_data;
+
+/*--------------------------------------------------------------*/
+static int elan_touch_detect_int_level(void)
+{
+ int v;
+ v = gpio_get_value(elan_touch_data.intr_gpio);
+
+ return v;
+}
+
+static int __elan_touch_poll(struct i2c_client *client)
+{
+ int status = 0, retry = 20;
+
+ do {
+ status = elan_touch_detect_int_level();
+ retry--;
+ mdelay(20);
+ } while (status == 1 && retry > 0);
+
+ return status == 0 ? 0 : -ETIMEDOUT;
+}
+
+static int elan_touch_poll(struct i2c_client *client)
+{
+ return __elan_touch_poll(client);
+}
+
+static int __hello_packet_handler(struct i2c_client *client)
+{
+ int rc;
+ uint8_t buf_recv[4] = { 0 };
+
+ rc = elan_touch_poll(client);
+
+ if (rc < 0)
+ return -EINVAL;
+
+ rc = i2c_master_recv(client, buf_recv, 4);
+
+ if (rc != 4) {
+ return rc;
+ } else {
+ int i;
+ pr_info("hello packet: [0x%02x 0x%02x 0x%02x 0x%02x]\n",
+ buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]);
+
+ for (i = 0; i < 4; i++)
+ if (buf_recv[i] != hello_packet)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline int elan_touch_parse_xy(uint8_t *data, uint16_t *x,
+ uint16_t *y)
+{
+ *x = (data[0] & 0xf0);
+ *x <<= 4;
+ *x |= data[1];
+ if (*x >= ELAN_TS_X_MAX)
+ *x = ELAN_TS_X_MAX;
+ *x = ((((ELAN_TS_X_MAX -
+ *x) * 1000) / ELAN_TS_X_MAX) * ELAN_USER_X_MAX) / 1000;
+
+ *y = (data[0] & 0x0f);
+ *y <<= 8;
+ *y |= data[2];
+ if (*y >= ELAN_TS_Y_MAX)
+ *y = ELAN_TS_Y_MAX;
+ *y = ((((ELAN_TS_Y_MAX -
+ *y) * 1000) / ELAN_TS_Y_MAX) * ELAN_USER_Y_MAX) / 1000;
+
+ return 0;
+}
+
+/* __elan_touch_init -- hand shaking with touch panel
+ *
+ * 1.recv hello packet
+ */
+static int __elan_touch_init(struct i2c_client *client)
+{
+ int rc;
+ rc = __hello_packet_handler(client);
+ if (rc < 0)
+ goto hand_shake_failed;
+
+hand_shake_failed:
+ return rc;
+}
+
+static int elan_touch_recv_data(struct i2c_client *client, uint8_t *buf)
+{
+ int rc, bytes_to_recv = IDX_PACKET_SIZE;
+
+ if (buf == NULL)
+ return -EINVAL;
+
+ memset(buf, 0, bytes_to_recv);
+ rc = i2c_master_recv(client, buf, bytes_to_recv);
+ if (rc != bytes_to_recv)
+ return -EINVAL;
+
+ return rc;
+}
+
+static void elan_touch_report_data(struct i2c_client *client, uint8_t *buf)
+{
+ switch (buf[0]) {
+ case idx_coordinate_packet:
+ {
+ uint16_t x1, x2, y1, y2;
+ uint8_t finger_stat;
+
+ finger_stat = (buf[idx_finger_state] & 0x06) >> 1;
+
+ if (finger_stat == 0) {
+ input_report_key(elan_touch_data.input, BTN_TOUCH, 0);
+ input_report_key(elan_touch_data.input, BTN_2, 0);
+ } else if (finger_stat == 1) {
+ elan_touch_parse_xy(&buf[1], &x1, &y1);
+ input_report_abs(elan_touch_data.input, ABS_X, x1);
+ input_report_abs(elan_touch_data.input, ABS_Y, y1);
+ input_report_key(elan_touch_data.input, BTN_TOUCH, 1);
+ input_report_key(elan_touch_data.input, BTN_2, 0);
+ } else if (finger_stat == 2) {
+ elan_touch_parse_xy(&buf[1], &x1, &y1);
+ input_report_abs(elan_touch_data.input, ABS_X, x1);
+ input_report_abs(elan_touch_data.input, ABS_Y, y1);
+ input_report_key(elan_touch_data.input, BTN_TOUCH, 1);
+ elan_touch_parse_xy(&buf[4], &x2, &y2);
+ input_report_abs(elan_touch_data.input, ABS_HAT0X, x2);
+ input_report_abs(elan_touch_data.input, ABS_HAT0Y, y2);
+ input_report_key(elan_touch_data.input, BTN_2, 1);
+ }
+ input_sync(elan_touch_data.input);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+static void elan_touch_work_func(struct work_struct *work)
+{
+ int rc;
+ uint8_t buf[IDX_PACKET_SIZE] = { 0 };
+ struct i2c_client *client = elan_touch_data.client;
+
+ if (elan_touch_detect_int_level())
+ return;
+
+ rc = elan_touch_recv_data(client, buf);
+ if (rc < 0)
+ return;
+
+ elan_touch_report_data(client, buf);
+}
+
+static irqreturn_t elan_touch_ts_interrupt(int irq, void *dev_id)
+{
+ queue_work(elan_wq, &elan_touch_data.work);
+
+ return IRQ_HANDLED;
+}
+
+static enum hrtimer_restart elan_touch_timer_func(struct hrtimer *timer)
+{
+ queue_work(elan_wq, &elan_touch_data.work);
+ hrtimer_start(&elan_touch_data.timer, ktime_set(0, 12500000),
+ HRTIMER_MODE_REL);
+
+ return HRTIMER_NORESTART;
+}
+
+static int elan_touch_register_interrupt(struct i2c_client *client)
+{
+ int err = 0;
+
+ if (client->irq) {
+ elan_touch_data.use_irq = 1;
+ err =
+ request_irq(client->irq, elan_touch_ts_interrupt,
+ IRQF_TRIGGER_FALLING, ELAN_TS_NAME,
+ &elan_touch_data);
+
+ if (err < 0) {
+ pr_info("%s(%s): Can't allocate irq %d\n", __FILE__,
+ __func__, client->irq);
+ elan_touch_data.use_irq = 0;
+ }
+ }
+
+ if (!elan_touch_data.use_irq) {
+ hrtimer_init(&elan_touch_data.timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ elan_touch_data.timer.function = elan_touch_timer_func;
+ hrtimer_start(&elan_touch_data.timer, ktime_set(1, 0),
+ HRTIMER_MODE_REL);
+ }
+
+ pr_info("elan ts starts in %s mode.\n",
+ elan_touch_data.use_irq == 1 ? "interrupt" : "polling");
+
+ return 0;
+}
+
+static int elan_touch_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device_node *np = client->dev.of_node;
+ int gpio_elan_cs, gpio_elan_rst, err = 0;
+
+ if (!np)
+ return -ENODEV;
+
+ elan_touch_data.intr_gpio = of_get_named_gpio(np, "gpio_intr", 0);
+ if (!gpio_is_valid(elan_touch_data.intr_gpio))
+ return -ENODEV;
+
+ err = devm_gpio_request_one(&client->dev, elan_touch_data.intr_gpio,
+ GPIOF_IN, "gpio_elan_intr");
+ if (err < 0) {
+ dev_err(&client->dev,
+ "request gpio failed: %d\n", err);
+ return err;
+ }
+
+ /* elan touch init */
+ gpio_elan_cs = of_get_named_gpio(np, "gpio_elan_cs", 0);
+ if (!gpio_is_valid(gpio_elan_cs))
+ return -ENODEV;
+
+ err = devm_gpio_request_one(&client->dev, gpio_elan_cs,
+ GPIOF_OUT_INIT_HIGH, "gpio_elan_cs");
+ if (err < 0) {
+ dev_err(&client->dev,
+ "request gpio failed: %d\n", err);
+ return err;
+ }
+ gpio_set_value(gpio_elan_cs, 0);
+
+ gpio_elan_rst = of_get_named_gpio(np, "gpio_elan_rst", 0);
+ if (!gpio_is_valid(gpio_elan_rst))
+ return -ENODEV;
+
+ err = devm_gpio_request_one(&client->dev, gpio_elan_rst,
+ GPIOF_OUT_INIT_HIGH, "gpio_elan_rst");
+ if (err < 0) {
+ dev_err(&client->dev,
+ "request gpio failed: %d\n", err);
+ return err;
+ }
+ gpio_set_value(gpio_elan_rst, 0);
+ msleep(10);
+ gpio_set_value(gpio_elan_rst, 1);
+
+ gpio_set_value(gpio_elan_cs, 1);
+ msleep(100);
+
+ elan_wq = create_singlethread_workqueue("elan_wq");
+ if (!elan_wq) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ elan_touch_data.client = client;
+ strlcpy(client->name, ELAN_TS_NAME, I2C_NAME_SIZE);
+
+ INIT_WORK(&elan_touch_data.work, elan_touch_work_func);
+
+ elan_touch_data.input = input_allocate_device();
+ if (elan_touch_data.input == NULL) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ err = __elan_touch_init(client);
+ if (err < 0) {
+ dev_err(&client->dev, "elan - Read Hello Packet Failed\n");
+ goto fail;
+ }
+
+ elan_touch_data.input->name = ELAN_TS_NAME;
+ elan_touch_data.input->id.bustype = BUS_I2C;
+
+ set_bit(EV_SYN, elan_touch_data.input->evbit);
+
+ set_bit(EV_KEY, elan_touch_data.input->evbit);
+ set_bit(BTN_TOUCH, elan_touch_data.input->keybit);
+ set_bit(BTN_2, elan_touch_data.input->keybit);
+
+ set_bit(EV_ABS, elan_touch_data.input->evbit);
+ set_bit(ABS_X, elan_touch_data.input->absbit);
+ set_bit(ABS_Y, elan_touch_data.input->absbit);
+ set_bit(ABS_HAT0X, elan_touch_data.input->absbit);
+ set_bit(ABS_HAT0Y, elan_touch_data.input->absbit);
+
+ input_set_abs_params(elan_touch_data.input, ABS_X, 0, ELAN_USER_X_MAX,
+ 0, 0);
+ input_set_abs_params(elan_touch_data.input, ABS_Y, 0, ELAN_USER_Y_MAX,
+ 0, 0);
+ input_set_abs_params(elan_touch_data.input, ABS_HAT0X, 0,
+ ELAN_USER_X_MAX, 0, 0);
+ input_set_abs_params(elan_touch_data.input, ABS_HAT0Y, 0,
+ ELAN_USER_Y_MAX, 0, 0);
+
+ err = input_register_device(elan_touch_data.input);
+ if (err < 0)
+ goto fail;
+
+ elan_touch_register_interrupt(elan_touch_data.client);
+
+ return 0;
+
+fail:
+ input_free_device(elan_touch_data.input);
+ if (elan_wq)
+ destroy_workqueue(elan_wq);
+ return err;
+}
+
+static int elan_touch_remove(struct i2c_client *client)
+{
+ if (elan_wq)
+ destroy_workqueue(elan_wq);
+
+ input_unregister_device(elan_touch_data.input);
+
+ if (elan_touch_data.use_irq)
+ free_irq(client->irq, client);
+ else
+ hrtimer_cancel(&elan_touch_data.timer);
+ return 0;
+}
+
+/* -------------------------------------------------------------------- */
+static const struct i2c_device_id elan_touch_id[] = {
+ {"elan-touch", 0},
+ {}
+};
+
+static const struct of_device_id elan_dt_ids[] = {
+ {
+ .compatible = "elan,elan-touch",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, elan_dt_ids);
+
+static int elan_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int elan_resume(struct device *dev)
+{
+ uint8_t buf[IDX_PACKET_SIZE] = { 0 };
+
+ if (0 == elan_touch_detect_int_level()) {
+ dev_dbg(dev, "Got touch during suspend period.\n");
+ /*
+ * if touch screen during suspend, recv and drop the
+ * data, then touch interrupt pin will return high after
+ * receving data.
+ */
+ elan_touch_recv_data(elan_touch_data.client, buf);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops elan_dev_pm_ops = {
+ .suspend = elan_suspend,
+ .resume = elan_resume,
+};
+
+static struct i2c_driver elan_touch_driver = {
+ .probe = elan_touch_probe,
+ .remove = elan_touch_remove,
+ .id_table = elan_touch_id,
+ .driver = {
+ .name = "elan-touch",
+ .owner = THIS_MODULE,
+ .of_match_table = elan_dt_ids,
+#ifdef CONFIG_PM
+ .pm = &elan_dev_pm_ops,
+#endif
+ },
+};
+
+static int __init elan_touch_init(void)
+{
+ return i2c_add_driver(&elan_touch_driver);
+}
+
+static void __exit elan_touch_exit(void)
+{
+ i2c_del_driver(&elan_touch_driver);
+}
+
+module_init(elan_touch_init);
+module_exit(elan_touch_exit);
+
+MODULE_AUTHOR("Stanley Zeng <stanley.zeng@emc.com.tw>");
+MODULE_DESCRIPTION("ELAN Touch Screen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/focaltech_touch/Kconfig b/drivers/input/touchscreen/focaltech_touch/Kconfig
new file mode 100644
index 000000000000..e1ec3b91202e
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/Kconfig
@@ -0,0 +1,16 @@
+#
+# Focaltech Touchscreen driver configuration
+#
+
+config TOUCHSCREEN_FTS
+ bool "Focaltech Touchscreen"
+ depends on I2C
+ default n
+ help
+ Say Y here if you have Focaltech touch panel.
+ If unsure, say N.
+
+config TOUCHSCREEN_FTS_DIRECTORY
+ string "Focaltech ts directory name"
+ default "focaltech_touch"
+ depends on TOUCHSCREEN_FTS
diff --git a/drivers/input/touchscreen/focaltech_touch/Makefile b/drivers/input/touchscreen/focaltech_touch/Makefile
new file mode 100644
index 000000000000..1b2b8ec8acd4
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the focaltech touchscreen drivers.
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_core.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_esdcheck.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_ex_mode.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_gesture.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_point_report_check.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_sensor.o
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_common.h b/drivers/input/touchscreen/focaltech_touch/focaltech_common.h
new file mode 100644
index 000000000000..ae4807c7b700
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_common.h
@@ -0,0 +1,211 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+/*****************************************************************************
+*
+* File Name: focaltech_common.h
+*
+* Author: Focaltech Driver Team
+*
+* Created: 2016-08-16
+*
+* Abstract:
+*
+* Reference:
+*
+*****************************************************************************/
+
+#ifndef __LINUX_FOCALTECH_COMMON_H__
+#define __LINUX_FOCALTECH_COMMON_H__
+
+#include "focaltech_config.h"
+
+/*****************************************************************************
+* Macro definitions using #define
+*****************************************************************************/
+#define FTS_DRIVER_VERSION "Focaltech V1.2 20161229"
+
+#define FLAGBIT(x) (0x00000001 << (x))
+#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) << (x))
+
+#define FLAG_ICSERIALS_LEN 5
+#define FLAG_IDC_BIT 11
+
+#define FTS_CHIP_TYPE_MAPPING { \
+ {0x01, 0x58, 0x22, 0x58, 0x22, 0x00, 0x00, 0x58, 0x2C}, \
+ {0x02, 0x54, 0x22, 0x54, 0x22, 0x00, 0x00, 0x54, 0x2C}, \
+ {0x03, 0x64, 0x26, 0x64, 0x26, 0x00, 0x00, 0x79, 0x1C}, \
+ {0x04, 0x33, 0x67, 0x64, 0x26, 0x00, 0x00, 0x79, 0x1C}, \
+ {0x05, 0x87, 0x16, 0x87, 0x16, 0x87, 0xA6, 0x00, 0x00}, \
+ {0x06, 0x87, 0x36, 0x87, 0x36, 0x87, 0xC6, 0x00, 0x00}, \
+ {0x07, 0x80, 0x06, 0x80, 0x06, 0x80, 0xC6, 0x80, 0xB6}, \
+ {0x08, 0x86, 0x06, 0x86, 0x06, 0x86, 0xA6, 0x00, 0x00}, \
+ {0x09, 0x86, 0x07, 0x86, 0x07, 0x86, 0xA7, 0x00, 0x00}, \
+ {0x0A, 0xE7, 0x16, 0x87, 0x16, 0xE7, 0xA6, 0x87, 0xB6}, \
+}
+
+#define I2C_BUFFER_LENGTH_MAXINUM 256
+#define FILE_NAME_LENGTH 128
+#define ENABLE 1
+#define DISABLE 0
+/*register address*/
+#define FTS_REG_INT_CNT 0x8F
+#define FTS_REG_FLOW_WORK_CNT 0x91
+#define FTS_REG_WORKMODE 0x00
+#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40
+#define FTS_REG_WORKMODE_WORK_VALUE 0x00
+#define FTS_REG_CHIP_ID 0xA3
+#define FTS_REG_CHIP_ID2 0x9F
+#define FTS_REG_POWER_MODE 0xA5
+#define FTS_REG_POWER_MODE_SLEEP_VALUE 0x03
+#define FTS_REG_FW_VER 0xA6
+#define FTS_REG_VENDOR_ID 0xA8
+#define FTS_REG_LCD_BUSY_NUM 0xAB
+#define FTS_REG_FACE_DEC_MODE_EN 0xB0
+#define FTS_REG_GLOVE_MODE_EN 0xC0
+#define FTS_REG_COVER_MODE_EN 0xC1
+#define FTS_REG_CHARGER_MODE_EN 0x8B
+#define FTS_REG_GESTURE_EN 0xD0
+#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3
+#define FTS_REG_ESD_SATURATE 0xED
+
+/*****************************************************************************
+* Alternative mode (When something goes wrong, the modules may be able to solve the problem.)
+*****************************************************************************/
+/*
+ * point report check
+ * default: disable
+ */
+#define FTS_POINT_REPORT_CHECK_EN 0
+
+/*****************************************************************************
+* Global variable or extern global variabls/functions
+*****************************************************************************/
+struct ft_chip_t {
+ unsigned long type;
+ unsigned char chip_idh;
+ unsigned char chip_idl;
+ unsigned char rom_idh;
+ unsigned char rom_idl;
+ unsigned char pramboot_idh;
+ unsigned char pramboot_idl;
+ unsigned char bootloader_idh;
+ unsigned char bootloader_idl;
+};
+
+/* i2c communication*/
+int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue);
+int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue);
+int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen,
+ char *readbuf, int readlen);
+int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen);
+int fts_i2c_init(void);
+int fts_i2c_exit(void);
+
+/* Gesture functions */
+#if FTS_GESTURE_EN
+int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client);
+int fts_gesture_exit(struct i2c_client *client);
+void fts_gesture_recovery(struct i2c_client *client);
+int fts_gesture_readdata(struct i2c_client *client);
+int fts_gesture_suspend(struct i2c_client *i2c_client);
+int fts_gesture_resume(struct i2c_client *client);
+#endif
+
+/* Apk and functions */
+#if FTS_APK_NODE_EN
+int fts_create_apk_debug_channel(struct i2c_client *client);
+void fts_release_apk_debug_channel(void);
+#endif
+
+/* ADB functions */
+#if FTS_SYSFS_NODE_EN
+int fts_create_sysfs(struct i2c_client *client);
+int fts_remove_sysfs(struct i2c_client *client);
+#endif
+
+/* ESD */
+#if FTS_ESDCHECK_EN
+int fts_esdcheck_init(void);
+int fts_esdcheck_exit(void);
+int fts_esdcheck_switch(bool enable);
+int fts_esdcheck_proc_busy(bool proc_debug);
+int fts_esdcheck_set_intr(bool intr);
+int fts_esdcheck_suspend(void);
+int fts_esdcheck_resume(void);
+int fts_esdcheck_get_status(void);
+#endif
+
+/* Production test */
+#if FTS_TEST_EN
+int fts_test_init(struct i2c_client *client);
+int fts_test_exit(struct i2c_client *client);
+#endif
+
+/* Point Report Check*/
+#if FTS_POINT_REPORT_CHECK_EN
+int fts_point_report_check_init(void);
+int fts_point_report_check_exit(void);
+void fts_point_report_check_queue_work(void);
+#endif
+
+/* Other */
+extern int g_show_log;
+int fts_reset_proc(int hdelayms);
+int fts_wait_tp_to_valid(struct i2c_client *client);
+void fts_tp_state_recovery(struct i2c_client *client);
+int fts_ex_mode_init(struct i2c_client *client);
+int fts_ex_mode_exit(struct i2c_client *client);
+int fts_ex_mode_recovery(struct i2c_client *client);
+
+void fts_irq_disable(void);
+void fts_irq_enable(void);
+
+/*****************************************************************************
+* DEBUG function define here
+*****************************************************************************/
+#if FTS_DEBUG_EN
+#define FTS_DEBUG_LEVEL 1
+
+#if (FTS_DEBUG_LEVEL == 2)
+#define FTS_DEBUG(fmt, args...) \
+ printk(KERN_ERR "[FTS][%s]"fmt"\n", __func__, ##args)
+#else
+#define FTS_DEBUG(fmt, args...) \
+ printk(KERN_ERR "[FTS]"fmt"\n", ##args)
+#endif
+
+#define FTS_FUNC_ENTER() \
+ printk(KERN_ERR "[FTS]%s: Enter\n", __func__)
+#define FTS_FUNC_EXIT() \
+ printk(KERN_ERR "[FTS]%s: Exit(%d)\n", __func__, __LINE__)
+#else
+#define FTS_DEBUG(fmt, args...)
+#define FTS_FUNC_ENTER()
+#define FTS_FUNC_EXIT()
+#endif
+
+#define FTS_INFO(fmt, args...) do { \
+ if (g_show_log) \
+ printk(KERN_ERR "[FTS][Info]"fmt"\n", ##args); \
+ } while (0)
+
+#define FTS_ERROR(fmt, args...) do { \
+ if (g_show_log) \
+ printk(KERN_ERR "[FTS][Error]"fmt"\n", ##args); \
+ } while (0)
+
+#endif /* __LINUX_FOCALTECH_COMMON_H__ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_config.h b/drivers/input/touchscreen/focaltech_touch/focaltech_config.h
new file mode 100644
index 000000000000..87b622e77942
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_config.h
@@ -0,0 +1,219 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+/************************************************************************
+*
+* File Name: focaltech_config.h
+*
+* Author: Focaltech Driver Team
+*
+* Created: 2016-08-08
+*
+* Abstract: global configurations
+*
+* Version: v1.0
+*
+************************************************************************/
+#ifndef _LINUX_FOCLATECH_CONFIG_H_
+#define _LINUX_FOCLATECH_CONFIG_H_
+
+/**************************************************/
+/****** G: A, I: B, S: C, U: D ******************/
+/****** chip type defines, do not modify *********/
+#define _FT8716 0x87160805
+#define _FT8736 0x87360806
+#define _FT8006 0x80060807
+#define _FT8606 0x86060808
+#define _FT8607 0x86070809
+#define _FTE716 0xE716080a
+
+#define _FT5416 0x54160002
+#define _FT5426 0x54260002
+#define _FT5435 0x54350002
+#define _FT5436 0x54360002
+#define _FT5526 0x55260002
+#define _FT5526I 0x5526B002
+#define _FT5446 0x54460002
+#define _FT5346 0x53460002
+#define _FT5446I 0x5446B002
+#define _FT5346I 0x5346B002
+#define _FT7661 0x76610002
+#define _FT7511 0x75110002
+#define _FT7421 0x74210002
+#define _FT7681 0x76810002
+#define _FT3C47U 0x3C47D002
+#define _FT3417 0x34170002
+#define _FT3517 0x35170002
+#define _FT3327 0x33270002
+#define _FT3427 0x34270002
+
+#define _FT5626 0x56260001
+#define _FT5726 0x57260001
+#define _FT5826B 0x5826B001
+#define _FT5826S 0x5826C001
+#define _FT7811 0x78110001
+#define _FT3D47 0x3D470001
+#define _FT3617 0x36170001
+#define _FT3717 0x37170001
+#define _FT3817B 0x3817B001
+
+#define _FT6236U 0x6236D003
+#define _FT6336G 0x6336A003
+#define _FT6336U 0x6336D003
+#define _FT6436U 0x6436D003
+
+#define _FT3267 0x32670004
+#define _FT3367 0x33670004
+
+/******************* Enables *********************/
+/*********** 1 to enable, 0 to disable ***********/
+
+/*
+ * show debug log info
+ * enable it for debug, disable it for release
+ */
+#define FTS_DEBUG_EN 0
+
+/*
+ * Linux MultiTouch Protocol
+ * 1: Protocol B(default), 0: Protocol A
+ */
+#define FTS_MT_PROTOCOL_B_EN 1
+
+/*
+ * Report Pressure in multitouch
+ * 1:enable(default),0:disable
+*/
+#define FTS_REPORT_PRESSURE_EN 1
+
+/*
+ * Force touch support
+ * different pressure for multitouch
+ * 1: true pressure for force touch
+ * 0: constant pressure(default)
+ */
+#define FTS_FORCE_TOUCH_EN 0
+
+/*
+ * Gesture function enable
+ * default: disable
+ */
+#define FTS_GESTURE_EN 0
+
+/*
+ * ESD check & protection
+ * default: disable
+ */
+#define FTS_ESDCHECK_EN 0
+
+/*
+ * Production test enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_TEST_EN 0
+
+/*
+ * Glove mode enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_GLOVE_EN 0
+/*
+ * cover enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_COVER_EN 0
+/*
+ * Charger enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_CHARGER_EN 0
+
+/*
+ * Proximity sensor
+ * default: disable
+ */
+#define FTS_PSENSOR_EN 0
+
+/*
+ * Nodes for tools, please keep enable
+ */
+#define FTS_SYSFS_NODE_EN 1
+#define FTS_APK_NODE_EN 1
+
+/*
+ * Customer power enable
+ * enable it when customer need control TP power
+ * default: disable
+ */
+#define FTS_POWER_SOURCE_CUST_EN 0
+
+/****************************************************/
+
+/********************** Upgrade ****************************/
+/*
+ * auto upgrade, please keep enable
+ */
+#define FTS_AUTO_UPGRADE_EN 1
+
+/*
+ * auto upgrade for lcd cfg
+ * default: 0
+ */
+#define FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN 0
+
+/* auto cb check
+ * default: disable
+ */
+#define FTS_AUTO_CLB_EN 0
+
+/*
+ * FW_APP.i file for upgrade
+ * define your own fw_app, the sample one is invalid
+ */
+#define FTS_UPGRADE_FW_APP "include/firmware/FT8716_app_sample.i"
+
+/*
+ * lcd_cfg.i file for lcd cfg upgrade
+ * define your own lcd_cfg.i, the sample one is invalid
+ */
+#define FTS_UPGRADE_LCD_CFG "include/firmware/lcd_cfg.i"
+
+/* get vedor id from flash
+ * default: enable
+ */
+#define FTS_GET_VENDOR_ID 0
+
+/*
+ * vendor_id(s) for the ic
+ * you need confirm vendor_id for upgrade
+ * if only one vendor, ignore vendor_2_id, otherwise
+ * you need define both of them
+ */
+#define FTS_VENDOR_1_ID 0x8d
+#define FTS_VENDOR_2_ID 0x8d
+
+/*
+ * upgrade stress test for debug
+ * enable it for upgrade debug if needed
+ * default: disable
+ */
+#define FTS_UPGRADE_STRESS_TEST 0
+/* stress test times, default: 1000 */
+#define FTS_UPGRADE_TEST_NUMBER 1000
+
+/*********************************************************/
+
+#endif /* _LINUX_FOCLATECH_CONFIG_H_ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
new file mode 100644
index 000000000000..38aa6c88f7e0
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
@@ -0,0 +1,1439 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+/*****************************************************************************
+*
+* File Name: focaltech_core.c
+*
+* Author: Focaltech Driver Team
+*
+* Created: 2016-08-08
+*
+* Abstract:
+*
+* Reference:
+*
+*****************************************************************************/
+
+/*****************************************************************************
+* Included header files
+*****************************************************************************/
+#include "focaltech_core.h"
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#define FTS_SUSPEND_LEVEL 1 /* Early-suspend level */
+#endif
+
+/*****************************************************************************
+* Private constant and macro definitions using #define
+*****************************************************************************/
+#define FTS_DRIVER_NAME "fts_ts"
+#define INTERVAL_READ_REG 20
+#define TIMEOUT_READ_REG 300
+#if FTS_POWER_SOURCE_CUST_EN
+#define FTS_VTG_MIN_UV 2600000
+#define FTS_VTG_MAX_UV 3300000
+#define FTS_I2C_VTG_MIN_UV 1800000
+#define FTS_I2C_VTG_MAX_UV 1800000
+#endif
+#define FTS_READ_TOUCH_BUFFER_DIVIDED 0
+/*****************************************************************************
+* Global variable or extern global variabls/functions
+******************************************************************************/
+struct i2c_client *fts_i2c_client;
+struct fts_ts_data *fts_wq_data;
+struct input_dev *fts_input_dev;
+
+#if FTS_DEBUG_EN
+int g_show_log = 1;
+#else
+int g_show_log;
+#endif
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+char g_sz_debug[1024] = { 0 };
+#endif
+
+/*****************************************************************************
+* Static function prototypes
+*****************************************************************************/
+static void fts_release_all_finger(void);
+static int fts_ts_suspend(struct device *dev);
+static int fts_ts_resume(struct device *dev);
+
+static bool fts_chip_idc(struct fts_ts_data *data)
+{
+ return ((data->pdata->fts_chip_type & FLAGBIT(FLAG_IDC_BIT)) ==
+ FLAGBIT(FLAG_IDC_BIT));
+}
+
+/*****************************************************************************
+* Name: fts_wait_tp_to_valid
+* Brief: Read chip id until TP FW become valid,
+* need call when reset/power on/resume...
+* 1. Read Chip ID per INTERVAL_READ_REG(20ms)
+* 2. Timeout: TIMEOUT_READ_REG(300ms)
+* Input:
+* Output:
+* Return: 0 - Get correct Device ID
+*****************************************************************************/
+int fts_wait_tp_to_valid(struct i2c_client *client)
+{
+ int ret = 0;
+ int cnt = 0;
+ u8 reg_value = 0;
+
+ do {
+ ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &reg_value);
+ if (ret < 0)
+ FTS_INFO("TP Not Ready, ReadData = 0x%x", reg_value);
+ else {
+ FTS_INFO("TP Ready, Device ID = 0x%x", reg_value);
+ return 0;
+ }
+ cnt++;
+ msleep(INTERVAL_READ_REG);
+ } while ((cnt * INTERVAL_READ_REG) < TIMEOUT_READ_REG);
+
+ /* error: not get correct reg data */
+ return -1;
+}
+
+/*****************************************************************************
+* Name: fts_recover_state
+* Brief: Need execute this function when reset
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+void fts_tp_state_recovery(struct i2c_client *client)
+{
+ /* wait tp stable */
+ fts_wait_tp_to_valid(client);
+ /* recover TP charger state 0x8B */
+ /* recover TP glove state 0xC0 */
+ /* recover TP cover state 0xC1 */
+ fts_ex_mode_recovery(client);
+ /* recover TP gesture state 0xD0 */
+#if FTS_GESTURE_EN
+ fts_gesture_recovery(client);
+#endif
+
+ fts_release_all_finger();
+}
+
+/*****************************************************************************
+* Name: fts_reset_proc
+* Brief: Execute reset operation
+* Input: hdelayms - delay time unit:ms
+* Output:
+* Return:
+*****************************************************************************/
+int fts_reset_proc(int hdelayms)
+{
+ gpio_direction_output(fts_wq_data->pdata->reset_gpio, 0);
+ msleep(20);
+ gpio_direction_output(fts_wq_data->pdata->reset_gpio, 1);
+ msleep(hdelayms);
+
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_irq_disable
+* Brief: disable irq
+* Input:
+* sync:
+* Output:
+* Return:
+*****************************************************************************/
+void fts_irq_disable(void)
+{
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&fts_wq_data->irq_lock, irqflags);
+
+ if (!fts_wq_data->irq_disable) {
+ disable_irq(fts_wq_data->client->irq);
+ fts_wq_data->irq_disable = 1;
+ }
+
+ spin_unlock_irqrestore(&fts_wq_data->irq_lock, irqflags);
+}
+
+/*****************************************************************************
+* Name: fts_irq_enable
+* Brief: enable irq
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+void fts_irq_enable(void)
+{
+ unsigned long irqflags = 0;
+
+ spin_lock_irqsave(&fts_wq_data->irq_lock, irqflags);
+
+ if (fts_wq_data->irq_disable) {
+ enable_irq(fts_wq_data->client->irq);
+ fts_wq_data->irq_disable = 0;
+ }
+
+ spin_unlock_irqrestore(&fts_wq_data->irq_lock, irqflags);
+}
+
+/*****************************************************************************
+* Name: fts_input_dev_init
+* Brief: input dev init
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_input_dev_init(struct i2c_client *client,
+ struct fts_ts_data *data,
+ struct input_dev *input_dev,
+ struct fts_ts_platform_data *pdata)
+{
+ int err, len;
+
+ FTS_FUNC_ENTER();
+
+ /* Init and register Input device */
+ input_dev->name = FTS_DRIVER_NAME;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = &client->dev;
+
+ input_set_drvdata(input_dev, data);
+ i2c_set_clientdata(client, data);
+
+ __set_bit(EV_KEY, input_dev->evbit);
+ if (data->pdata->have_key) {
+ FTS_DEBUG("set key capabilities");
+ for (len = 0; len < data->pdata->key_number; len++) {
+ input_set_capability(input_dev, EV_KEY,
+ data->pdata->keys[len]);
+ }
+ }
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+#if FTS_MT_PROTOCOL_B_EN
+ input_mt_init_slots(input_dev, pdata->max_touch_number,
+ INPUT_MT_DIRECT);
+#else
+ input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 0x0f, 0, 0);
+#endif
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
+ pdata->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
+ pdata->y_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0);
+#if FTS_REPORT_PRESSURE_EN
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
+#endif
+
+ err = input_register_device(input_dev);
+ if (err) {
+ FTS_ERROR("Input device registration failed");
+ goto free_inputdev;
+ }
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+
+free_inputdev:
+ input_free_device(input_dev);
+ FTS_FUNC_EXIT();
+ return err;
+
+}
+
+/*****************************************************************************
+* Power Control
+*****************************************************************************/
+#if FTS_POWER_SOURCE_CUST_EN
+static int fts_power_source_init(struct fts_ts_data *data)
+{
+ int rc;
+
+ FTS_FUNC_ENTER();
+
+ data->vdd = regulator_get(&data->client->dev, "vdd");
+ if (IS_ERR(data->vdd)) {
+ rc = PTR_ERR(data->vdd);
+ FTS_ERROR("Regulator get failed vdd rc=%d", rc);
+ }
+
+ if (regulator_count_voltages(data->vdd) > 0) {
+ rc = regulator_set_voltage(data->vdd, FTS_VTG_MIN_UV,
+ FTS_VTG_MAX_UV);
+ if (rc) {
+ FTS_ERROR("Regulator set_vtg failed vdd rc=%d", rc);
+ goto reg_vdd_put;
+ }
+ }
+
+ data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
+ if (IS_ERR(data->vcc_i2c)) {
+ rc = PTR_ERR(data->vcc_i2c);
+ FTS_ERROR("Regulator get failed vcc_i2c rc=%d", rc);
+ goto reg_vdd_set_vtg;
+ }
+
+ if (regulator_count_voltages(data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(data->vcc_i2c, FTS_I2C_VTG_MIN_UV,
+ FTS_I2C_VTG_MAX_UV);
+ if (rc) {
+ FTS_ERROR("Regulator set_vtg failed vcc_i2c rc=%d", rc);
+ goto reg_vcc_i2c_put;
+ }
+ }
+
+ FTS_FUNC_EXIT();
+ return 0;
+
+reg_vcc_i2c_put:
+ regulator_put(data->vcc_i2c);
+reg_vdd_set_vtg:
+ if (regulator_count_voltages(data->vdd) > 0)
+ regulator_set_voltage(data->vdd, 0, FTS_VTG_MAX_UV);
+reg_vdd_put:
+ regulator_put(data->vdd);
+ FTS_FUNC_EXIT();
+ return rc;
+}
+
+static int fts_power_source_ctrl(struct fts_ts_data *data, int enable)
+{
+ int rc;
+
+ FTS_FUNC_ENTER();
+ if (enable) {
+ rc = regulator_enable(data->vdd);
+ if (rc)
+ FTS_ERROR("Regulator vdd enable failed rc=%d", rc);
+
+ rc = regulator_enable(data->vcc_i2c);
+ if (rc)
+ FTS_ERROR("Regulator vcc_i2c enable failed rc=%d", rc);
+ } else {
+ rc = regulator_disable(data->vdd);
+ if (rc)
+ FTS_ERROR("Regulator vdd disable failed rc=%d", rc);
+ rc = regulator_disable(data->vcc_i2c);
+ if (rc)
+ FTS_ERROR("Regulator vcc_i2c disable failed rc=%d", rc);
+ }
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+#endif
+
+/*****************************************************************************
+* Reprot related
+*****************************************************************************/
+/*****************************************************************************
+* Name: fts_release_all_finger
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static void fts_release_all_finger(void)
+{
+#if FTS_MT_PROTOCOL_B_EN
+ unsigned int finger_count = 0;
+
+ for (finger_count = 0;
+ finger_count < fts_wq_data->pdata->max_touch_number;
+ finger_count++) {
+ input_mt_slot(fts_input_dev, finger_count);
+ input_mt_report_slot_state(fts_input_dev, MT_TOOL_FINGER,
+ false);
+ }
+#else
+ input_mt_sync(fts_input_dev);
+#endif
+ input_report_key(fts_input_dev, BTN_TOUCH, 0);
+ input_sync(fts_input_dev);
+}
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+static void fts_show_touch_buffer(u8 *buf, int point_num)
+{
+ int len = point_num * FTS_ONE_TCH_LEN;
+ int count = 0;
+ int i;
+
+ memset(g_sz_debug, 0, 1024);
+ if (len > (POINT_READ_BUF - 3))
+ len = POINT_READ_BUF - 3;
+ else if (len == 0) {
+ len += FTS_ONE_TCH_LEN;
+
+ count += sprintf(g_sz_debug, "%02X,%02X,%02X", buf[0], buf[1], buf[2]);
+ for (i = 0; i < len; i++)
+ count += sprintf(g_sz_debug + count, ",%02X", buf[i + 3]);
+
+ FTS_DEBUG("buffer: %s", g_sz_debug);
+}
+#endif
+
+static int fts_input_dev_report_key_event(struct ts_event *event,
+ struct fts_ts_data *data)
+{
+ int i;
+
+ if (data->pdata->have_key) {
+ if ((1 == event->touch_point || 1 == event->point_num)
+ && (event->au16_y[0] == data->pdata->key_y_coord)) {
+
+ if (event->point_num == 0) {
+ FTS_DEBUG("Keys All Up!");
+ for (i = 0; i < data->pdata->key_number; i++) {
+ input_report_key(data->input_dev,
+ data->pdata->keys[i],
+ 0);
+ }
+ } else {
+ for (i = 0; i < data->pdata->key_number; i++) {
+ if (event->au16_x[0] >
+ (data->pdata->key_x_coords[i] -
+ FTS_KEY_WIDTH)
+ && event->au16_x[0] <
+ (data->pdata->key_x_coords[i] +
+ FTS_KEY_WIDTH)) {
+
+ if (event->au8_touch_event[i] ==
+ 0
+ || event->au8_touch_event[i]
+ == 2) {
+ input_report_key
+ (data->input_dev,
+ data->pdata->keys
+ [i], 1);
+ FTS_DEBUG
+ ("Key%d(%d, %d) DOWN!",
+ i,
+ event->au16_x[0],
+ event->au16_y[0]);
+ } else {
+ input_report_key
+ (data->input_dev,
+ data->pdata->keys
+ [i], 0);
+ FTS_DEBUG
+ ("Key%d(%d, %d) Up!",
+ i,
+ event->au16_x[0],
+ event->au16_y[0]);
+ }
+ break;
+ }
+ }
+ }
+ input_sync(data->input_dev);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+#if FTS_MT_PROTOCOL_B_EN
+static int fts_input_dev_report_b(struct ts_event *event,
+ struct fts_ts_data *data)
+{
+ int i = 0;
+ int uppoint = 0;
+ int touchs = 0;
+
+ for (i = 0; i < event->touch_point; i++) {
+ input_mt_slot(data->input_dev, event->au8_finger_id[i]);
+
+ if (event->au8_touch_event[i] == FTS_TOUCH_DOWN
+ || event->au8_touch_event[i] == FTS_TOUCH_CONTACT) {
+ input_mt_report_slot_state(data->input_dev,
+ MT_TOOL_FINGER, true);
+
+#if FTS_REPORT_PRESSURE_EN
+#if FTS_FORCE_TOUCH_EN
+ if (event->pressure[i] <= 0) {
+ FTS_ERROR("[B]Illegal pressure: %d",
+ event->pressure[i]);
+ event->pressure[i] = 1;
+ }
+#else
+ event->pressure[i] = 0x3f;
+#endif
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ event->pressure[i]);
+#endif
+
+ if (event->area[i] <= 0) {
+ FTS_ERROR("[B]Illegal touch-major: %d",
+ event->area[i]);
+ event->area[i] = 1;
+ }
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ event->area[i]);
+
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->au16_x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->au16_y[i]);
+ touchs |= BIT(event->au8_finger_id[i]);
+ data->touchs |= BIT(event->au8_finger_id[i]);
+
+#if FTS_REPORT_PRESSURE_EN
+ FTS_DEBUG("[B]P%d(%d, %d)[p:%d,tm:%d] DOWN!",
+ event->au8_finger_id[i], event->au16_x[i],
+ event->au16_y[i], event->pressure[i],
+ event->area[i]);
+#else
+ FTS_DEBUG("[B]P%d(%d, %d)[tm:%d] DOWN!",
+ event->au8_finger_id[i], event->au16_x[i],
+ event->au16_y[i], event->area[i]);
+#endif
+ } else {
+ uppoint++;
+ input_mt_report_slot_state(data->input_dev,
+ MT_TOOL_FINGER, false);
+#if FTS_REPORT_PRESSURE_EN
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE, 0);
+#endif
+ data->touchs &= ~BIT(event->au8_finger_id[i]);
+ FTS_DEBUG("[B]P%d UP!", event->au8_finger_id[i]);
+ }
+ }
+
+ if (unlikely(data->touchs ^ touchs)) {
+ for (i = 0; i < data->pdata->max_touch_number; i++) {
+ if (BIT(i) & (data->touchs ^ touchs)) {
+ FTS_DEBUG("[B]P%d UP!", i);
+ input_mt_slot(data->input_dev, i);
+ input_mt_report_slot_state(data->input_dev,
+ MT_TOOL_FINGER,
+ false);
+#if FTS_REPORT_PRESSURE_EN
+ input_report_abs(data->input_dev,
+ ABS_MT_PRESSURE, 0);
+#endif
+ }
+ }
+ }
+
+ data->touchs = touchs;
+ if (event->touch_point == uppoint) {
+ FTS_DEBUG("Points All Up!");
+ input_report_key(data->input_dev, BTN_TOUCH, 0);
+ } else {
+ input_report_key(data->input_dev, BTN_TOUCH,
+ event->touch_point > 0);
+ }
+
+ input_sync(data->input_dev);
+
+ return 0;
+
+}
+
+#else
+static int fts_input_dev_report_a(struct ts_event *event,
+ struct fts_ts_data *data)
+{
+ int i = 0;
+ int uppoint = 0;
+ int touchs = 0;
+
+ for (i = 0; i < event->touch_point; i++) {
+
+ if (event->au8_touch_event[i] == FTS_TOUCH_DOWN
+ || event->au8_touch_event[i] == FTS_TOUCH_CONTACT) {
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+ event->au8_finger_id[i]);
+#if FTS_REPORT_PRESSURE_EN
+#if FTS_FORCE_TOUCH_EN
+ if (event->pressure[i] <= 0) {
+ FTS_ERROR("[B]Illegal pressure: %d",
+ event->pressure[i]);
+ event->pressure[i] = 1;
+ }
+#else
+ event->pressure[i] = 0x3f;
+#endif
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ event->pressure[i]);
+#endif
+
+ if (event->area[i] <= 0) {
+ FTS_ERROR("[B]Illegal touch-major: %d",
+ event->area[i]);
+ event->area[i] = 1;
+ }
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ event->area[i]);
+
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->au16_x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->au16_y[i]);
+
+ input_mt_sync(data->input_dev);
+
+#if FTS_REPORT_PRESSURE_EN
+ FTS_DEBUG("[B]P%d(%d, %d)[p:%d,tm:%d] DOWN!",
+ event->au8_finger_id[i], event->au16_x[i],
+ event->au16_y[i], event->pressure[i],
+ event->area[i]);
+#else
+ FTS_DEBUG("[B]P%d(%d, %d)[tm:%d] DOWN!",
+ event->au8_finger_id[i], event->au16_x[i],
+ event->au16_y[i], event->area[i]);
+#endif
+ } else {
+ uppoint++;
+ }
+ }
+
+ data->touchs = touchs;
+ if (event->touch_point == uppoint) {
+ FTS_DEBUG("Points All Up!");
+ input_report_key(data->input_dev, BTN_TOUCH, 0);
+ input_mt_sync(data->input_dev);
+ } else {
+ input_report_key(data->input_dev, BTN_TOUCH,
+ event->touch_point > 0);
+ }
+
+ input_sync(data->input_dev);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+* Name: fts_read_touchdata
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_read_touchdata(struct fts_ts_data *data)
+{
+ u8 buf[POINT_READ_BUF] = { 0 };
+ u8 pointid = FTS_MAX_ID;
+ int ret = -1;
+ int i;
+ struct ts_event *event = &(data->event);
+
+#if FTS_GESTURE_EN
+ {
+ u8 state;
+
+ if (data->suspended) {
+ fts_i2c_read_reg(data->client, FTS_REG_GESTURE_EN,
+ &state);
+ if (state == 1) {
+ fts_gesture_readdata(data->client);
+ return 1;
+ }
+ }
+ }
+#endif
+
+#if FTS_PSENSOR_EN
+ if ((fts_sensor_read_data(data) != 0) && (data->suspended == 1))
+ return 1;
+#endif
+
+#if FTS_READ_TOUCH_BUFFER_DIVIDED
+ memset(buf, 0xFF, POINT_READ_BUF);
+ memset(event, 0, sizeof(struct ts_event));
+
+ buf[0] = 0x00;
+ ret = fts_i2c_read(data->client, buf, 1, buf, (3 + FTS_ONE_TCH_LEN));
+ if (ret < 0) {
+ FTS_ERROR("%s read touchdata failed.", __func__);
+ return ret;
+ }
+ event->touch_point = 0;
+ event->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F;
+ if (event->point_num > data->pdata->max_touch_number)
+ event->point_num = data->pdata->max_touch_number;
+
+ if (event->point_num > 1) {
+ buf[9] = 0x09;
+ fts_i2c_read(data->client, buf + 9, 1, buf + 9,
+ (event->point_num - 1) * FTS_ONE_TCH_LEN);
+ }
+#else
+ ret = fts_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
+ if (ret < 0) {
+ FTS_ERROR("[B]Read touchdata failed, ret: %d", ret);
+ return ret;
+ }
+#if FTS_POINT_REPORT_CHECK_EN
+ fts_point_report_check_queue_work();
+#endif
+
+ memset(event, 0, sizeof(struct ts_event));
+ event->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F;
+ if (event->point_num > data->pdata->max_touch_number)
+ event->point_num = data->pdata->max_touch_number;
+ event->touch_point = 0;
+#endif
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+ fts_show_touch_buffer(buf, event->point_num);
+#endif
+
+ for (i = 0; i < data->pdata->max_touch_number; i++) {
+ pointid = (buf[FTS_TOUCH_ID_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+ if (pointid >= FTS_MAX_ID)
+ break;
+
+ event->touch_point++;
+ event->au16_x[i] =
+ (s16) (buf[FTS_TOUCH_X_H_POS + FTS_ONE_TCH_LEN * i] & 0x0F)
+ << 8 | (s16) buf[FTS_TOUCH_X_L_POS + FTS_ONE_TCH_LEN * i];
+ event->au16_y[i] =
+ (s16) (buf[FTS_TOUCH_Y_H_POS + FTS_ONE_TCH_LEN * i] & 0x0F)
+ << 8 | (s16) buf[FTS_TOUCH_Y_L_POS + FTS_ONE_TCH_LEN * i];
+ event->au8_touch_event[i] =
+ buf[FTS_TOUCH_EVENT_POS + FTS_ONE_TCH_LEN * i] >> 6;
+
+ if (data->pdata->swap)
+ swap(event->au16_x[i], event->au16_y[i]);
+
+ if (data->pdata->scaling_down_half) {
+ event->au16_x[i] = event->au16_x[i] >> 1;
+ event->au16_y[i] = event->au16_y[i] >> 1;
+ }
+
+ event->au8_finger_id[i] =
+ (buf[FTS_TOUCH_ID_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+ event->area[i] =
+ (buf[FTS_TOUCH_AREA_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+ event->pressure[i] =
+ (s16) buf[FTS_TOUCH_PRE_POS + FTS_ONE_TCH_LEN * i];
+
+ if (0 == event->area[i])
+ event->area[i] = 0x09;
+
+ if (0 == event->pressure[i])
+ event->pressure[i] = 0x3f;
+
+ if ((event->au8_touch_event[i] == 0
+ || event->au8_touch_event[i] == 2)
+ && (event->point_num == 0))
+ break;
+ }
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_report_value
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static void fts_report_value(struct fts_ts_data *data)
+{
+ struct ts_event *event = &data->event;
+
+ FTS_DEBUG("point number: %d, touch point: %d", event->point_num,
+ event->touch_point);
+
+ if (0 == fts_input_dev_report_key_event(event, data))
+ return;
+#if FTS_MT_PROTOCOL_B_EN
+ fts_input_dev_report_b(event, data);
+#else
+ fts_input_dev_report_a(event, data);
+#endif
+
+ return;
+
+}
+
+/*****************************************************************************
+* Name: fts_ts_interrupt
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static irqreturn_t fts_ts_interrupt(int irq, void *dev_id)
+{
+ struct fts_ts_data *fts_ts = dev_id;
+ int ret = -1;
+
+ if (!fts_ts) {
+ FTS_ERROR("[INTR]: Invalid fts_ts");
+ return IRQ_HANDLED;
+ }
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_set_intr(1);
+#endif
+
+ ret = fts_read_touchdata(fts_wq_data);
+
+ if (ret == 0)
+ fts_report_value(fts_wq_data);
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_set_intr(0);
+#endif
+
+ return IRQ_HANDLED;
+}
+
+/*****************************************************************************
+* Name: fts_gpio_configure
+* Brief: Configure IRQ&RESET GPIO
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_gpio_configure(struct fts_ts_data *data)
+{
+ int err = 0;
+
+ FTS_FUNC_ENTER();
+ /* request irq gpio */
+ if (gpio_is_valid(data->pdata->irq_gpio)) {
+ err = gpio_request(data->pdata->irq_gpio, "fts_irq_gpio");
+ if (err) {
+ FTS_ERROR("[GPIO]irq gpio request failed");
+ goto err_irq_gpio_req;
+ }
+
+ err = gpio_direction_input(data->pdata->irq_gpio);
+ if (err) {
+ FTS_ERROR("[GPIO]set_direction for irq gpio failed");
+ goto err_irq_gpio_dir;
+ }
+ }
+ /* request reset gpio */
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ err = gpio_request(data->pdata->reset_gpio, "fts_reset_gpio");
+ if (err) {
+ FTS_ERROR("[GPIO]reset gpio request failed");
+ goto err_irq_gpio_dir;
+ }
+
+ err = gpio_direction_output(data->pdata->reset_gpio, 1);
+ if (err) {
+ FTS_ERROR("[GPIO]set_direction for reset gpio failed");
+ goto err_reset_gpio_dir;
+ }
+ }
+
+ FTS_FUNC_EXIT();
+ return 0;
+
+err_reset_gpio_dir:
+ if (gpio_is_valid(data->pdata->reset_gpio))
+ gpio_free(data->pdata->reset_gpio);
+err_irq_gpio_dir:
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->irq_gpio);
+err_irq_gpio_req:
+ FTS_FUNC_EXIT();
+ return err;
+}
+
+/*****************************************************************************
+* Name: fts_get_dt_coords
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_get_dt_coords(struct device *dev, char *name,
+ struct fts_ts_platform_data *pdata)
+{
+ u32 coords[FTS_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FTS_COORDS_ARR_SIZE) {
+ FTS_ERROR("invalid %s", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ FTS_ERROR("Unable to read %s", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "focaltech,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ FTS_ERROR("unsupported property %s", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_parse_dt
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+
+ FTS_FUNC_ENTER();
+
+ pdata->fts_chip_type = _FT5416;
+ rc = of_property_read_u32(np, "focaltech,panel-type",
+ &pdata->fts_chip_type);
+ if (rc)
+ FTS_ERROR("Panel type is undefined, use default panel FT5416");
+
+ rc = fts_get_dt_coords(dev, "focaltech,display-coords", pdata);
+ if (rc)
+ FTS_ERROR("Unable to get display-coords");
+
+ /* key */
+ pdata->have_key = of_property_read_bool(np, "focaltech,have-key");
+ if (pdata->have_key) {
+ rc = of_property_read_u32(np, "focaltech,key-number",
+ &pdata->key_number);
+ if (rc)
+ FTS_ERROR("Key number undefined!");
+ rc = of_property_read_u32_array(np, "focaltech,keys",
+ pdata->keys, pdata->key_number);
+ if (rc)
+ FTS_ERROR("Keys undefined!");
+ rc = of_property_read_u32(np, "focaltech,key-y-coord",
+ &pdata->key_y_coord);
+ if (rc)
+ FTS_ERROR("Key Y Coord undefined!");
+ rc = of_property_read_u32_array(np, "focaltech,key-x-coords",
+ pdata->key_x_coords,
+ pdata->key_number);
+ if (rc)
+ FTS_ERROR("Key X Coords undefined!");
+
+ FTS_DEBUG("%d: (%d, %d, %d), [%d, %d, %d][%d]",
+ pdata->key_number, pdata->keys[0], pdata->keys[1],
+ pdata->keys[2], pdata->key_x_coords[0],
+ pdata->key_x_coords[1], pdata->key_x_coords[2],
+ pdata->key_y_coord);
+ }
+
+ /* reset, irq gpio info */
+ pdata->reset_gpio =
+ of_get_named_gpio_flags(np, "focaltech,reset-gpio", 0,
+ &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ FTS_ERROR("Unable to get reset_gpio");
+
+ pdata->irq_gpio =
+ of_get_named_gpio_flags(np, "focaltech,irq-gpio", 0,
+ &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ FTS_ERROR("Unable to get irq_gpio");
+
+ rc = of_property_read_u32(np, "focaltech,max-touch-number", &temp_val);
+ if (!rc) {
+ pdata->max_touch_number = temp_val;
+ FTS_DEBUG("max_touch_number=%d", pdata->max_touch_number);
+ } else {
+ FTS_ERROR("Unable to get max-touch-number");
+ pdata->max_touch_number = FTS_MAX_POINTS;
+ }
+
+ pdata->swap = of_property_read_bool(np, "focaltech,swap-xy");
+ pdata->scaling_down_half = of_property_read_bool(np,
+ "focaltech,scaling-down-half");
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+#if defined(CONFIG_FB)
+/*****************************************************************************
+* Name: fb_notifier_callback
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct fts_ts_data *fts_data =
+ container_of(self, struct fts_ts_data, fb_notif);
+
+ if (evdata && evdata->data && event == FB_EVENT_BLANK && fts_data
+ && fts_data->client) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ fts_ts_resume(&fts_data->client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ fts_ts_suspend(&fts_data->client->dev);
+ }
+
+ return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+/*****************************************************************************
+* Name: fts_ts_early_suspend
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static void fts_ts_early_suspend(struct early_suspend *handler)
+{
+ struct fts_ts_data *data = container_of(handler,
+ struct fts_ts_data,
+ early_suspend);
+
+ fts_ts_suspend(&data->client->dev);
+}
+
+/*****************************************************************************
+* Name: fts_ts_late_resume
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static void fts_ts_late_resume(struct early_suspend *handler)
+{
+ struct fts_ts_data *data = container_of(handler,
+ struct fts_ts_data,
+ early_suspend);
+
+ fts_ts_resume(&data->client->dev);
+}
+#endif
+
+/*****************************************************************************
+* Name: fts_ts_probe
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct fts_ts_platform_data *pdata;
+ struct fts_ts_data *data;
+ struct input_dev *input_dev;
+ int err;
+
+ FTS_FUNC_ENTER();
+ /* 1. Get Platform data */
+ if (client->dev.of_node) {
+ pdata =
+ devm_kzalloc(&client->dev,
+ sizeof(struct fts_ts_platform_data),
+ GFP_KERNEL);
+ if (!pdata) {
+ FTS_ERROR("[MEMORY]Failed to allocate memory");
+ FTS_FUNC_EXIT();
+ return -ENOMEM;
+ }
+ err = fts_parse_dt(&client->dev, pdata);
+ if (err)
+ FTS_ERROR("[DTS]DT parsing failed");
+ } else
+ pdata = client->dev.platform_data;
+
+ if (!pdata) {
+ FTS_ERROR("Invalid pdata");
+ FTS_FUNC_EXIT();
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ FTS_ERROR("I2C not supported");
+ FTS_FUNC_EXIT();
+ return -ENODEV;
+ }
+
+ data =
+ devm_kzalloc(&client->dev, sizeof(struct fts_ts_data), GFP_KERNEL);
+ if (!data) {
+ FTS_ERROR("[MEMORY]Failed to allocate memory");
+ FTS_FUNC_EXIT();
+ return -ENOMEM;
+ }
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ FTS_ERROR("[INPUT]Failed to allocate input device");
+ FTS_FUNC_EXIT();
+ return -ENOMEM;
+ }
+
+ data->input_dev = input_dev;
+ data->client = client;
+ data->pdata = pdata;
+
+ fts_wq_data = data;
+ fts_i2c_client = client;
+ fts_input_dev = input_dev;
+
+ spin_lock_init(&fts_wq_data->irq_lock);
+
+ fts_input_dev_init(client, data, input_dev, pdata);
+
+#if FTS_POWER_SOURCE_CUST_EN
+ fts_power_source_init(data);
+ fts_power_source_ctrl(data, 1);
+#endif
+
+ err = fts_gpio_configure(data);
+ if (err < 0) {
+ FTS_ERROR("[GPIO]Failed to configure the gpios");
+ goto free_gpio;
+ }
+
+ fts_reset_proc(200);
+ fts_wait_tp_to_valid(client);
+
+ err =
+ request_threaded_irq(client->irq, NULL, fts_ts_interrupt,
+ pdata->irq_gpio_flags | IRQF_ONESHOT |
+ IRQF_TRIGGER_FALLING, client->dev.driver->name,
+ data);
+ if (err) {
+ FTS_ERROR("Request irq failed!");
+ goto free_gpio;
+ }
+
+ fts_irq_disable();
+
+#if FTS_PSENSOR_EN
+ if (fts_sensor_init(data) != 0) {
+ FTS_ERROR("fts_sensor_init failed!");
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+#endif
+
+#if FTS_POINT_REPORT_CHECK_EN
+ fts_point_report_check_init();
+#endif
+
+ fts_ex_mode_init(client);
+
+#if FTS_GESTURE_EN
+ fts_gesture_init(input_dev, client);
+#endif
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_init();
+#endif
+
+ fts_irq_enable();
+
+#if FTS_TEST_EN
+ fts_test_init(client);
+#endif
+
+#if defined(CONFIG_FB)
+ data->fb_notif.notifier_call = fb_notifier_callback;
+ err = fb_register_client(&data->fb_notif);
+ if (err)
+ FTS_ERROR("[FB]Unable to register fb_notifier: %d", err);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ data->early_suspend.level =
+ EARLY_SUSPEND_LEVEL_BLANK_SCREEN + FTS_SUSPEND_LEVEL;
+ data->early_suspend.suspend = fts_ts_early_suspend;
+ data->early_suspend.resume = fts_ts_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+
+ FTS_FUNC_EXIT();
+ return 0;
+
+free_gpio:
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->reset_gpio);
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+ return err;
+
+}
+
+/*****************************************************************************
+* Name: fts_ts_remove
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_ts_remove(struct i2c_client *client)
+{
+ struct fts_ts_data *data = i2c_get_clientdata(client);
+
+ FTS_FUNC_ENTER();
+ cancel_work_sync(&data->touch_event_work);
+
+#if FTS_PSENSOR_EN
+ fts_sensor_remove(data);
+#endif
+
+#if FTS_POINT_REPORT_CHECK_EN
+ fts_point_report_check_exit();
+#endif
+
+ fts_ex_mode_exit(client);
+
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&data->fb_notif))
+ FTS_ERROR("Error occurred while unregistering fb_notifier.");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ free_irq(client->irq, data);
+
+ if (gpio_is_valid(data->pdata->reset_gpio))
+ gpio_free(data->pdata->reset_gpio);
+
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->irq_gpio);
+
+ input_unregister_device(data->input_dev);
+
+#if FTS_TEST_EN
+ fts_test_exit(client);
+#endif
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_exit();
+#endif
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_ts_suspend
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_ts_suspend(struct device *dev)
+{
+ struct fts_ts_data *data = dev_get_drvdata(dev);
+ int retval = 0;
+
+ FTS_FUNC_ENTER();
+ if (data->suspended) {
+ FTS_INFO("Already in suspend state");
+ FTS_FUNC_EXIT();
+ return -1;
+ }
+
+ fts_release_all_finger();
+
+#if FTS_GESTURE_EN
+ retval = fts_gesture_suspend(data->client);
+ if (retval == 0) {
+ /* Enter into gesture mode(suspend) */
+ retval = enable_irq_wake(fts_wq_data->client->irq);
+ if (retval)
+ FTS_ERROR("%s: set_irq_wake failed", __func__);
+ data->suspended = true;
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+#endif
+
+#if FTS_PSENSOR_EN
+ if (fts_sensor_suspend(data) != 0) {
+ enable_irq_wake(data->client->irq);
+ data->suspended = true;
+ return 0;
+ }
+#endif
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_suspend();
+#endif
+
+ fts_irq_disable();
+
+ /* TP enter sleep mode */
+ retval =
+ fts_i2c_write_reg(data->client, FTS_REG_POWER_MODE,
+ FTS_REG_POWER_MODE_SLEEP_VALUE);
+ if (retval < 0)
+ FTS_ERROR("Set TP to sleep mode fail, ret=%d!", retval);
+ data->suspended = true;
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_ts_resume
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_ts_resume(struct device *dev)
+{
+ struct fts_ts_data *data = dev_get_drvdata(dev);
+
+ FTS_FUNC_ENTER();
+ if (!data->suspended) {
+ FTS_DEBUG("Already in awake state");
+ FTS_FUNC_EXIT();
+ return -1;
+ }
+
+ if (!fts_chip_idc(data))
+ fts_reset_proc(200);
+
+ fts_tp_state_recovery(data->client);
+
+#if FTS_GESTURE_EN
+ if (fts_gesture_resume(data->client) == 0) {
+ int err;
+
+ err = disable_irq_wake(data->client->irq);
+ if (err)
+ FTS_ERROR("%s: disable_irq_wake failed", __func__);
+ data->suspended = false;
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+#endif
+
+#if FTS_PSENSOR_EN
+ if (fts_sensor_resume(data) != 0) {
+ disable_irq_wake(data->client->irq);
+ data->suspended = false;
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+#endif
+
+ data->suspended = false;
+
+ fts_irq_enable();
+
+#if FTS_ESDCHECK_EN
+ fts_esdcheck_resume();
+#endif
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+* I2C Driver
+*****************************************************************************/
+static const struct i2c_device_id fts_ts_id[] = {
+ {FTS_DRIVER_NAME, 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, fts_ts_id);
+
+static struct of_device_id fts_match_table[] = {
+ {.compatible = "focaltech,fts",},
+ {},
+};
+
+static struct i2c_driver fts_ts_driver = {
+ .probe = fts_ts_probe,
+ .remove = fts_ts_remove,
+ .driver = {
+ .name = FTS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = fts_match_table,
+ },
+ .id_table = fts_ts_id,
+};
+
+/*****************************************************************************
+* Name: fts_ts_init
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int __init fts_ts_init(void)
+{
+ int ret = 0;
+
+ FTS_FUNC_ENTER();
+ ret = i2c_add_driver(&fts_ts_driver);
+ if (ret != 0)
+ FTS_ERROR("Focaltech touch screen driver init failed!");
+ FTS_FUNC_EXIT();
+ return ret;
+}
+
+/*****************************************************************************
+* Name: fts_ts_exit
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static void __exit fts_ts_exit(void)
+{
+ i2c_del_driver(&fts_ts_driver);
+}
+
+module_init(fts_ts_init);
+module_exit(fts_ts_exit);
+
+MODULE_AUTHOR("FocalTech Driver Team");
+MODULE_DESCRIPTION("FocalTech Touchscreen Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.h b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h
new file mode 100644
index 000000000000..b8ef41f58420
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h
@@ -0,0 +1,189 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+/*****************************************************************************
+*
+* File Name: focaltech_core.h
+
+* Author: Focaltech Driver Team
+*
+* Created: 2016-08-08
+*
+* Abstract:
+*
+* Reference:
+*
+*****************************************************************************/
+
+#ifndef __LINUX_FOCALTECH_CORE_H__
+#define __LINUX_FOCALTECH_CORE_H__
+/*****************************************************************************
+* Included header files
+*****************************************************************************/
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
+#include <linux/debugfs.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/mount.h>
+#include <linux/netdevice.h>
+#include <linux/unistd.h>
+#include <linux/ioctl.h>
+#include "focaltech_common.h"
+
+/*****************************************************************************
+* Private constant and macro definitions using #define
+*****************************************************************************/
+#define LEN_FLASH_ECC_MAX 0xFFFE
+
+#define FTS_WORKQUEUE_NAME "fts_wq"
+
+#define FTS_MAX_POINTS 10
+#define FTS_KEY_WIDTH 50
+#define FTS_ONE_TCH_LEN 6
+#define POINT_READ_BUF (3 + FTS_ONE_TCH_LEN * FTS_MAX_POINTS)
+
+#define FTS_MAX_ID 0x0F
+#define FTS_TOUCH_X_H_POS 3
+#define FTS_TOUCH_X_L_POS 4
+#define FTS_TOUCH_Y_H_POS 5
+#define FTS_TOUCH_Y_L_POS 6
+#define FTS_TOUCH_PRE_POS 7
+#define FTS_TOUCH_AREA_POS 8
+#define FTS_TOUCH_POINT_NUM 2
+#define FTS_TOUCH_EVENT_POS 3
+#define FTS_TOUCH_ID_POS 5
+#define FTS_COORDS_ARR_SIZE 4
+
+#define FTS_TOUCH_DOWN 0
+#define FTS_TOUCH_UP 1
+#define FTS_TOUCH_CONTACT 2
+
+#define FTS_SYSFS_ECHO_ON(buf) ((strnicmp(buf, "1", 1) == 0) || \
+ (strnicmp(buf, "on", 2) == 0))
+#define FTS_SYSFS_ECHO_OFF(buf) ((strnicmp(buf, "0", 1) == 0) || \
+ (strnicmp(buf, "off", 3) == 0))
+
+/*****************************************************************************
+* Private enumerations, structures and unions using typedef
+*****************************************************************************/
+
+struct fts_ts_platform_data {
+ u32 fts_chip_type;
+ u32 irq_gpio;
+ u32 irq_gpio_flags;
+ u32 reset_gpio;
+ u32 reset_gpio_flags;
+ bool have_key;
+ u32 key_number;
+ u32 keys[4];
+ u32 key_y_coord;
+ u32 key_x_coords[4];
+ u32 x_max;
+ u32 y_max;
+ u32 x_min;
+ u32 y_min;
+ u32 max_touch_number;
+
+ bool swap;
+ bool scaling_down_half;
+};
+
+struct ts_event {
+ u16 au16_x[FTS_MAX_POINTS]; /*x coordinate */
+ u16 au16_y[FTS_MAX_POINTS]; /*y coordinate */
+ u16 pressure[FTS_MAX_POINTS];
+ /* touch event: 0 -- down; 1-- up; 2 -- contact */
+ u8 au8_touch_event[FTS_MAX_POINTS];
+ u8 au8_finger_id[FTS_MAX_POINTS]; /*touch ID */
+ u8 area[FTS_MAX_POINTS];
+ u8 touch_point;
+ u8 point_num;
+};
+
+struct fts_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ const struct fts_ts_platform_data *pdata;
+#if FTS_PSENSOR_EN
+ struct fts_psensor_platform_data *psensor_pdata;
+#endif
+ struct work_struct touch_event_work;
+ struct workqueue_struct *ts_workqueue;
+ struct regulator *vdd;
+ struct regulator *vcc_i2c;
+ spinlock_t irq_lock;
+ u16 addr;
+ bool suspended;
+ u8 fw_ver[3];
+ u8 fw_vendor_id;
+ int touchs;
+ int irq_disable;
+
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+};
+
+#if FTS_PSENSOR_EN
+struct fts_psensor_platform_data {
+ struct input_dev *input_psensor_dev;
+ struct sensors_classdev ps_cdev;
+ int tp_psensor_opened;
+ char tp_psensor_data; /* 0 near, 1 far */
+ struct fts_ts_data *data;
+};
+
+int fts_sensor_init(struct fts_ts_data *data);
+int fts_sensor_read_data(struct fts_ts_data *data);
+int fts_sensor_suspend(struct fts_ts_data *data);
+int fts_sensor_resume(struct fts_ts_data *data);
+int fts_sensor_remove(struct fts_ts_data *data);
+#endif
+
+/*****************************************************************************
+* Static variables
+*****************************************************************************/
+extern struct i2c_client *fts_i2c_client;
+extern struct fts_ts_data *fts_wq_data;
+extern struct input_dev *fts_input_dev;
+
+#endif /* __LINUX_FOCALTECH_CORE_H__ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c b/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c
new file mode 100644
index 000000000000..565507d02523
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c
@@ -0,0 +1,473 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+/*****************************************************************************
+*
+* File Name: focaltech_esdcheck.c
+*
+* Author: luoguojin
+*
+* Created: 2016-08-03
+*
+* Abstract: ESD check function
+*
+* Version: v1.0
+*
+* Revision History:
+* v1.0:
+* First release. By luougojin 2016-08-03
+*****************************************************************************/
+
+/*****************************************************************************
+* Included header files
+*****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_ESDCHECK_EN
+/*****************************************************************************
+* Private constant and macro definitions using #define
+*****************************************************************************/
+#define ESDCHECK_WAIT_TIME 1000
+
+/*****************************************************************************
+* Private enumerations, structures and unions using typedef
+*****************************************************************************/
+struct fts_esdcheck_st {
+ u8 active:1;
+ u8 suspend:1;
+ u8 proc_debug:1; /* apk or adb is accessing I2C */
+ u8 intr:1; /* 1- Interrupt trigger */
+ u8 unused:4;
+ u8 flow_work_hold_cnt;
+ u8 flow_work_cnt_last;
+ u32 hardware_reset_cnt;
+ u32 i2c_nack_cnt;
+ u32 i2c_dataerror_cnt;
+};
+
+/*****************************************************************************
+* Static variables
+*****************************************************************************/
+static struct delayed_work fts_esdcheck_work;
+static struct workqueue_struct *fts_esdcheck_workqueue;
+static struct fts_esdcheck_st fts_esdcheck_data;
+
+/*****************************************************************************
+* Global variable or extern global variabls/functions
+*****************************************************************************/
+
+/*****************************************************************************
+* Static function prototypes
+*****************************************************************************/
+
+/*****************************************************************************
+* functions body
+*****************************************************************************/
+/*****************************************************************************
+* Name: lcd_esdcheck
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+int lcd_need_reset;
+static int tp_need_recovery; /* LCD reset cause Tp reset */
+int idc_esdcheck_lcderror(void)
+{
+ u8 val;
+ int ret;
+
+ FTS_DEBUG("[ESD]Check LCD ESD");
+ if ((tp_need_recovery == 1) && (lcd_need_reset == 0)) {
+ tp_need_recovery = 0;
+ /* LCD reset, need recover TP state */
+ fts_tp_state_recovery(fts_i2c_client);
+ }
+
+ ret = fts_i2c_read_reg(fts_i2c_client, FTS_REG_ESD_SATURATE, &val);
+ if (ret < 0) {
+ FTS_ERROR("[ESD]: Read ESD_SATURATE(0xED) failed ret=%d!", ret);
+ return -EIO;
+ }
+
+ if (val == 0xAA) {
+ /*
+ * 1. Set flag lcd_need_reset = 1;
+ * 2. LCD driver need reset(recovery) LCD and
+ * set lcd_need_reset to 0
+ * 3. recover TP state
+ */
+ FTS_INFO("LCD ESD, Execute LCD reset!");
+ lcd_need_reset = 1;
+ tp_need_recovery = 1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_tp_reset
+* Brief: esd check algorithm
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_esdcheck_tp_reset(void)
+{
+ FTS_FUNC_ENTER();
+
+ fts_esdcheck_data.flow_work_hold_cnt = 0;
+ fts_esdcheck_data.hardware_reset_cnt++;
+
+ fts_reset_proc(200);
+ fts_tp_state_recovery(fts_i2c_client);
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+* Name: get_chip_id
+* Brief: Read Chip Id 3 times
+* Input:
+* Output:
+* Return: 1 - Read Chip Id 3 times failed
+* 0 - Read Chip Id pass
+*****************************************************************************/
+static bool get_chip_id(void)
+{
+ int err = 0;
+ int i = 0;
+ u8 reg_value = 0;
+ u8 reg_addr = 0;
+
+ for (i = 0; i < 3; i++) {
+ reg_addr = FTS_REG_CHIP_ID;
+ err = fts_i2c_read(fts_i2c_client, &reg_addr, 1, &reg_value, 1);
+
+ if (err < 0) {
+ FTS_ERROR("[ESD]: Read Reg 0xA3 failed ret = %d!!",
+ err);
+ fts_esdcheck_data.i2c_nack_cnt++;
+ } else {
+ /* Upgrade sometimes can't detect */
+ if ((reg_value == chip_types.chip_idh)
+ || (reg_value == 0xEF))
+ break;
+ else
+ fts_esdcheck_data.i2c_dataerror_cnt++;
+ }
+ }
+
+ /* if can't get correct data in 3 times, then need hardware reset */
+ if (i >= 3) {
+ FTS_ERROR
+ ("[ESD]: Read Chip id 3 times failed,"
+ "need execute TP reset!!");
+ return 1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Name: get_flow_cnt
+* Brief: Read flow cnt(0x91)
+* Input:
+* Output:
+* Return: 1 - Reg 0x91(flow cnt) abnormal: hold a value for 5 times
+* 0 - Reg 0x91(flow cnt) normal
+*****************************************************************************/
+static bool get_flow_cnt(void)
+{
+ int err = 0;
+ u8 reg_value = 0;
+ u8 reg_addr = 0;
+
+ reg_addr = FTS_REG_FLOW_WORK_CNT;
+ err = fts_i2c_read(fts_i2c_client, &reg_addr, 1, &reg_value, 1);
+ if (err < 0) {
+ FTS_ERROR("[ESD]: Read Reg 0x91 failed ret = %d!!", err);
+ fts_esdcheck_data.i2c_nack_cnt++;
+ } else {
+ if (reg_value == fts_esdcheck_data.flow_work_cnt_last)
+ fts_esdcheck_data.flow_work_hold_cnt++;
+ else
+ fts_esdcheck_data.flow_work_hold_cnt = 0;
+
+ fts_esdcheck_data.flow_work_cnt_last = reg_value;
+ }
+
+ /*
+ * if read flow work cnt 5 times and the value are
+ * all the same, then need hardware_reset
+ */
+ if (fts_esdcheck_data.flow_work_hold_cnt >= 5) {
+ FTS_DEBUG("[ESD]: Flow Work Cnt(reg0x91) keep a value"
+ "for 5 times, need execute TP reset!!");
+ return 1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Name: esdcheck_algorithm
+* Brief: esd check algorithm
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int esdcheck_algorithm(void)
+{
+ int err = 0;
+ u8 reg_value = 0;
+ u8 reg_addr = 0;
+ bool hardware_reset = 0;
+
+ /* 1. esdcheck is interrupt, then return */
+ if (fts_esdcheck_data.intr == 1) {
+ FTS_INFO("[ESD]: In interrupt state,"
+ "not check esd, return immediately!!");
+ return 0;
+ }
+
+ /* 2. check power state, if suspend, no need check esd */
+ if (fts_esdcheck_data.suspend == 1) {
+ FTS_INFO("[ESD]: In suspend, not check esd,"
+ "return immediately!!");
+ /* because in suspend state, adb can be used,
+ * when upgrade FW, will active ESD check(active = 1)
+ * But in suspend, then will don't queue_delayed_work,
+ * when resume, don't check ESD again
+ */
+ fts_esdcheck_data.active = 0;
+ return 0;
+ }
+
+ /*
+ * 3. check fts_esdcheck_data.proc_debug state,
+ * if 1-proc busy, no need check esd
+ */
+ if (fts_esdcheck_data.proc_debug == 1) {
+ FTS_INFO("[ESD]: In apk or adb command mode,"
+ "not check esd, return immediately!!");
+ return 0;
+ }
+
+ /* 4. In factory mode, can't check esd */
+ reg_addr = FTS_REG_WORKMODE;
+ err = fts_i2c_read(fts_i2c_client, &reg_addr, 1, &reg_value, 1);
+ if (err < 0) {
+ fts_esdcheck_data.i2c_nack_cnt++;
+ } else if ((reg_value & 0x70) == FTS_REG_WORKMODE_FACTORY_VALUE) {
+ FTS_INFO("[ESD]: In factory mode,"
+ "not check esd, return immediately!!");
+ return 0;
+ }
+
+ /* 5. Get Chip ID */
+ hardware_reset = get_chip_id();
+
+ /*
+ * 6. get Flow work cnt: 0x91 If no change for 5 times,
+ * then ESD and reset
+ */
+ if (!hardware_reset)
+ hardware_reset = get_flow_cnt();
+
+ /* 7. If need hardware reset, then handle it here */
+ if (hardware_reset == 1)
+ fts_esdcheck_tp_reset();
+
+ FTS_INFO("[ESD]: NoACK=%d, Error Data=%d, Hardware Reset=%d\n",
+ fts_esdcheck_data.i2c_nack_cnt,
+ fts_esdcheck_data.i2c_dataerror_cnt,
+ fts_esdcheck_data.hardware_reset_cnt);
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_func
+* Brief: fts_esdcheck_func
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static void esdcheck_func(struct work_struct *work)
+{
+ FTS_FUNC_ENTER();
+
+ idc_esdcheck_lcderror();
+
+ esdcheck_algorithm();
+
+ if (fts_esdcheck_data.suspend == 0) {
+ queue_delayed_work(fts_esdcheck_workqueue, &fts_esdcheck_work,
+ msecs_to_jiffies(ESDCHECK_WAIT_TIME));
+ }
+
+ FTS_FUNC_EXIT();
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_set_intr
+* Brief: interrupt flag (main used in interrupt tp report)
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+int fts_esdcheck_set_intr(bool intr)
+{
+ /* interrupt don't add debug message */
+ fts_esdcheck_data.intr = intr;
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_get_status(void)
+* Brief: get current status
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+int fts_esdcheck_get_status(void)
+{
+ /* interrupt don't add debug message */
+ return fts_esdcheck_data.active;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_proc_busy
+* Brief: When APK or ADB command access TP via driver,
+* then need set proc_debug,
+* then will not check ESD.
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+int fts_esdcheck_proc_busy(bool proc_debug)
+{
+ fts_esdcheck_data.proc_debug = proc_debug;
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_switch
+* Brief: FTS esd check function switch.
+* Input: enable: 1 - Enable esd check
+* 0 - Disable esd check
+* Output:
+* Return:
+*****************************************************************************/
+int fts_esdcheck_switch(bool enable)
+{
+ FTS_FUNC_ENTER();
+ if (enable == 1) {
+ if (fts_esdcheck_data.active == 0) {
+ FTS_INFO("[ESD]: ESD check start!!");
+ fts_esdcheck_data.active = 1;
+ queue_delayed_work(fts_esdcheck_workqueue,
+ &fts_esdcheck_work,
+ msecs_to_jiffies
+ (ESDCHECK_WAIT_TIME));
+ }
+ } else {
+ if (fts_esdcheck_data.active == 1) {
+ FTS_INFO("[ESD]: ESD check stop!!");
+ fts_esdcheck_data.active = 0;
+ cancel_delayed_work_sync(&fts_esdcheck_work);
+ }
+ }
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_suspend
+* Brief: Run when tp enter into suspend
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+int fts_esdcheck_suspend(void)
+{
+ FTS_FUNC_ENTER();
+ fts_esdcheck_switch(DISABLE);
+ fts_esdcheck_data.suspend = 1;
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_resume
+* Brief: Run when tp resume
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+int fts_esdcheck_resume(void)
+{
+ FTS_FUNC_ENTER();
+ fts_esdcheck_switch(ENABLE);
+ fts_esdcheck_data.suspend = 0;
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_init
+* Brief: Init and create a queue work to check esd
+* Input:
+* Output:
+* Return: < 0: Fail to create esd check queue
+*****************************************************************************/
+int fts_esdcheck_init(void)
+{
+ FTS_FUNC_ENTER();
+
+ INIT_DELAYED_WORK(&fts_esdcheck_work, esdcheck_func);
+ fts_esdcheck_workqueue = create_workqueue("fts_esdcheck_wq");
+ if (fts_esdcheck_workqueue == NULL)
+ FTS_INFO("[ESD]: Failed to create esd work queue!!");
+
+ memset((u8 *) &fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
+
+ fts_esdcheck_switch(ENABLE);
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_esdcheck_exit
+* Brief: When FTS TP driver is removed,
+* then call this function to destroy work queue
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+int fts_esdcheck_exit(void)
+{
+ FTS_FUNC_ENTER();
+
+ destroy_workqueue(fts_esdcheck_workqueue);
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+#endif /* FTS_ESDCHECK_EN */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c
new file mode 100644
index 000000000000..6ab5d47170cc
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c
@@ -0,0 +1,357 @@
+/*
+ *
+ * FocalTech ftxxxx TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+/*****************************************************************************
+*
+* File Name: focaltech_ex_mode.c
+*
+* Author: Liu WeiGuang
+*
+* Created: 2016-08-31
+*
+* Abstract:
+*
+* Reference:
+*
+*****************************************************************************/
+
+/*****************************************************************************
+* 1.Included header files
+*****************************************************************************/
+#include "focaltech_core.h"
+
+/*****************************************************************************
+* 2.Private constant and macro definitions using #define
+*****************************************************************************/
+
+/*****************************************************************************
+* 3.Private enumerations, structures and unions using typedef
+*****************************************************************************/
+struct fts_mode_flag {
+ int fts_glove_mode_flag;
+ int fts_cover_mode_flag;
+ int fts_charger_mode_flag;
+};
+
+struct fts_mode_flag g_fts_mode_flag;
+
+/*****************************************************************************
+* 4.Static variables
+*****************************************************************************/
+
+/*****************************************************************************
+* 5.Global variable or extern global variabls/functions
+*****************************************************************************/
+int fts_enter_glove_mode(struct i2c_client *client, int mode);
+int fts_glove_init(struct i2c_client *client);
+int fts_glove_exit(struct i2c_client *client);
+
+int fts_enter_cover_mode(struct i2c_client *client, int mode);
+int fts_cover_init(struct i2c_client *client);
+int fts_cover_exit(struct i2c_client *client);
+
+int fts_enter_charger_mode(struct i2c_client *client, int mode);
+int fts_charger_init(struct i2c_client *client);
+int fts_charger_exit(struct i2c_client *client);
+
+/*****************************************************************************
+* 6.Static function prototypes
+*******************************************************************************/
+
+#if FTS_GLOVE_EN
+static ssize_t fts_touch_glove_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "Glove: %s\n",
+ g_fts_mode_flag.fts_glove_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_glove_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ if (!g_fts_mode_flag.fts_glove_mode_flag) {
+ FTS_INFO("[Mode]enter glove mode");
+ ret = fts_enter_glove_mode(fts_i2c_client, true);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_glove_mode_flag = true;
+ }
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ if (g_fts_mode_flag.fts_glove_mode_flag) {
+ FTS_INFO("[Mode]exit glove mode");
+ ret = fts_enter_glove_mode(fts_i2c_client, false);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_glove_mode_flag = false;
+ }
+ }
+ FTS_INFO("[Mode]glove mode status: %d",
+ g_fts_mode_flag.fts_glove_mode_flag);
+ return count;
+}
+
+/************************************************************************
+* Name: fts_enter_glove_mode
+* Brief: change glove mode
+* Input: glove mode
+* Output: no
+* Return: success >=0, otherwise failed
+***********************************************************************/
+int fts_enter_glove_mode(struct i2c_client *client, int mode)
+{
+ int ret = 0;
+ static u8 buf_addr[2] = { 0 };
+ static u8 buf_value[2] = { 0 };
+
+ buf_addr[0] = FTS_REG_GLOVE_MODE_EN;
+
+ if (mode)
+ buf_value[0] = 0x01;
+ else
+ buf_value[0] = 0x00;
+
+ ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+ if (ret < 0)
+ FTS_ERROR("[Mode]fts_enter_glove_mode write value fail");
+
+ return ret;
+
+}
+
+/* read and write glove mode
+* read example: cat fts_touch_glove_mode---read glove mode
+* write example:echo 01 > fts_touch_glove_mode ---write glove mode to 01
+*
+*/
+static DEVICE_ATTR(fts_glove_mode, S_IRUGO | S_IWUSR, fts_touch_glove_show,
+ fts_touch_glove_store);
+
+#endif
+
+#if FTS_COVER_EN
+static ssize_t fts_touch_cover_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "Cover: %s\n",
+ g_fts_mode_flag.fts_cover_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_cover_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ if (!g_fts_mode_flag.fts_cover_mode_flag) {
+ FTS_INFO("[Mode]enter cover mode");
+ ret = fts_enter_cover_mode(fts_i2c_client, true);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_cover_mode_flag = true;
+ }
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ if (g_fts_mode_flag.fts_cover_mode_flag) {
+ FTS_INFO("[Mode]exit cover mode");
+ ret = fts_enter_cover_mode(fts_i2c_client, false);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_cover_mode_flag = false;
+ }
+ }
+ FTS_INFO("[Mode]cover mode status: %d",
+ g_fts_mode_flag.fts_cover_mode_flag);
+ return count;
+}
+
+/************************************************************************
+* Name: fts_enter_cover_mode
+* Brief: change cover mode
+* Input: cover mode
+* Output: no
+* Return: success >=0, otherwise failed
+***********************************************************************/
+int fts_enter_cover_mode(struct i2c_client *client, int mode)
+{
+ int ret = 0;
+ static u8 buf_addr[2] = { 0 };
+ static u8 buf_value[2] = { 0 };
+
+ buf_addr[0] = FTS_REG_COVER_MODE_EN;
+
+ if (mode)
+ buf_value[0] = 0x01;
+ else
+ buf_value[0] = 0x00;
+
+ ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+ if (ret < 0)
+ FTS_ERROR("[Mode] fts_enter_cover_mode write value fail\n");
+
+ return ret;
+
+}
+
+/* read and write cover mode
+* read example: cat fts_touch_cover_mode---read cover mode
+* write example:echo 01 > fts_touch_cover_mode ---write cover mode to 01
+*
+*/
+static DEVICE_ATTR(fts_cover_mode, S_IRUGO | S_IWUSR, fts_touch_cover_show,
+ fts_touch_cover_store);
+
+#endif
+
+#if FTS_CHARGER_EN
+static ssize_t fts_touch_charger_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "Charger: %s\n",
+ g_fts_mode_flag.fts_charger_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_charger_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ if (!g_fts_mode_flag.fts_charger_mode_flag) {
+ FTS_INFO("[Mode]enter charger mode");
+ ret = fts_enter_charger_mode(fts_i2c_client, true);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_charger_mode_flag = true;
+ }
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ if (g_fts_mode_flag.fts_charger_mode_flag) {
+ FTS_INFO("[Mode]exit charger mode");
+ ret = fts_enter_charger_mode(fts_i2c_client, false);
+ if (ret >= 0)
+ g_fts_mode_flag.fts_charger_mode_flag = false;
+ }
+ }
+ FTS_INFO("[Mode]charger mode status: %d",
+ g_fts_mode_flag.fts_charger_mode_flag);
+ return count;
+}
+
+/************************************************************************
+* Name: fts_enter_charger_mode
+* Brief: change charger mode
+* Input: charger mode
+* Output: no
+* Return: success >=0, otherwise failed
+***********************************************************************/
+int fts_enter_charger_mode(struct i2c_client *client, int mode)
+{
+ int ret = 0;
+ static u8 buf_addr[2] = { 0 };
+ static u8 buf_value[2] = { 0 };
+
+ buf_addr[0] = FTS_REG_CHARGER_MODE_EN;
+
+ if (mode)
+ buf_value[0] = 0x01;
+ else
+ buf_value[0] = 0x00;
+
+ ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+ if (ret < 0)
+ FTS_DEBUG("[Mode]fts_enter_charger_mode write value fail");
+
+ return ret;
+
+}
+
+/* read and write charger mode
+* read example: cat fts_touch_charger_mode---read charger mode
+* write example:echo 01 > fts_touch_charger_mode ---write charger mode to 01
+*
+*/
+static DEVICE_ATTR(fts_charger_mode, S_IRUGO | S_IWUSR, fts_touch_charger_show,
+ fts_touch_charger_store);
+
+#endif
+
+static struct attribute *fts_touch_mode_attrs[] = {
+#if FTS_GLOVE_EN
+ &dev_attr_fts_glove_mode.attr,
+#endif
+
+#if FTS_COVER_EN
+ &dev_attr_fts_cover_mode.attr,
+#endif
+
+#if FTS_CHARGER_EN
+ &dev_attr_fts_charger_mode.attr,
+#endif
+
+ NULL,
+};
+
+static struct attribute_group fts_touch_mode_group = {
+ .attrs = fts_touch_mode_attrs,
+};
+
+int fts_ex_mode_init(struct i2c_client *client)
+{
+ int err = 0;
+
+ g_fts_mode_flag.fts_glove_mode_flag = false;
+ g_fts_mode_flag.fts_cover_mode_flag = false;
+ g_fts_mode_flag.fts_charger_mode_flag = false;
+
+ err = sysfs_create_group(&client->dev.kobj, &fts_touch_mode_group);
+ if (0 != err) {
+ FTS_ERROR("[Mode]create sysfs failed.");
+ sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
+ return -EIO;
+ }
+
+ FTS_DEBUG("[Mode]create sysfs succeeded");
+
+ return err;
+
+}
+
+int fts_ex_mode_exit(struct i2c_client *client)
+{
+ sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
+ return 0;
+}
+
+int fts_ex_mode_recovery(struct i2c_client *client)
+{
+ int ret = 0;
+#if FTS_GLOVE_EN
+ if (g_fts_mode_flag.fts_glove_mode_flag)
+ ret = fts_enter_glove_mode(client, true);
+#endif
+
+#if FTS_COVER_EN
+ if (g_fts_mode_flag.fts_cover_mode_flag)
+ ret = fts_enter_cover_mode(client, true);
+#endif
+
+#if FTS_CHARGER_EN
+ if (g_fts_mode_flag.fts_charger_mode_flag)
+ ret = fts_enter_charger_mode(client, true);
+#endif
+
+ return ret;
+}
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c b/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c
new file mode 100644
index 000000000000..9faabb8681bb
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c
@@ -0,0 +1,652 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+/*****************************************************************************
+*
+* File Name: focaltech_gestrue.c
+*
+* Author: Focaltech Driver Team
+*
+* Created: 2016-08-08
+*
+* Abstract:
+*
+* Reference:
+*
+*****************************************************************************/
+
+/*****************************************************************************
+* 1.Included header files
+*****************************************************************************/
+#include "focaltech_core.h"
+#if FTS_GESTURE_EN
+/******************************************************************************
+* Private constant and macro definitions using #define
+*****************************************************************************/
+#define KEY_GESTURE_U KEY_U
+#define KEY_GESTURE_UP KEY_UP
+#define KEY_GESTURE_DOWN KEY_DOWN
+#define KEY_GESTURE_LEFT KEY_LEFT
+#define KEY_GESTURE_RIGHT KEY_RIGHT
+#define KEY_GESTURE_O KEY_O
+#define KEY_GESTURE_E KEY_E
+#define KEY_GESTURE_M KEY_M
+#define KEY_GESTURE_L KEY_L
+#define KEY_GESTURE_W KEY_W
+#define KEY_GESTURE_S KEY_S
+#define KEY_GESTURE_V KEY_V
+#define KEY_GESTURE_C KEY_C
+#define KEY_GESTURE_Z KEY_Z
+
+#define GESTURE_LEFT 0x20
+#define GESTURE_RIGHT 0x21
+#define GESTURE_UP 0x22
+#define GESTURE_DOWN 0x23
+#define GESTURE_DOUBLECLICK 0x24
+#define GESTURE_O 0x30
+#define GESTURE_W 0x31
+#define GESTURE_M 0x32
+#define GESTURE_E 0x33
+#define GESTURE_L 0x44
+#define GESTURE_S 0x46
+#define GESTURE_V 0x54
+#define GESTURE_Z 0x41
+#define GESTURE_C 0x34
+#define FTS_GESTRUE_POINTS 255
+#define FTS_GESTRUE_POINTS_HEADER 8
+#define FTS_GESTURE_OUTPUT_ADRESS 0xD3
+/*****************************************************************************
+* Private enumerations, structures and unions using typedef
+*****************************************************************************/
+struct fts_gesture_st {
+ u8 header[FTS_GESTRUE_POINTS_HEADER];
+ u16 coordinate_x[FTS_GESTRUE_POINTS];
+ u16 coordinate_y[FTS_GESTRUE_POINTS];
+ u8 mode;
+ u8 active;
+};
+
+/*****************************************************************************
+* Static variables
+*****************************************************************************/
+static struct fts_gesture_st fts_gesture_data;
+extern struct fts_ts_data *fts_wq_data;
+
+/*****************************************************************************
+* Global variable or extern global variabls/functions
+*****************************************************************************/
+
+/*****************************************************************************
+* Static function prototypes
+*****************************************************************************/
+static ssize_t fts_gesture_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t fts_gesture_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count);
+static ssize_t fts_gesture_buf_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t fts_gesture_buf_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+/* sysfs gesture node
+ * read example: cat fts_gesture_mode ---read gesture mode
+ * write example:echo 01 > fts_gesture_mode ---write gesture mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_gesture_mode, S_IRUGO | S_IWUSR, fts_gesture_show,
+ fts_gesture_store);
+/*
+ * read example: cat fts_gesture_buf ---read gesture buf
+ */
+static DEVICE_ATTR(fts_gesture_buf, S_IRUGO | S_IWUSR, fts_gesture_buf_show,
+ fts_gesture_buf_store);
+static struct attribute *fts_gesture_mode_attrs[] = {
+
+ &dev_attr_fts_gesture_mode.attr,
+ &dev_attr_fts_gesture_buf.attr,
+ NULL,
+};
+
+static struct attribute_group fts_gesture_group = {
+ .attrs = fts_gesture_mode_attrs,
+};
+
+/************************************************************************
+* Name: fts_gesture_show
+* Brief: no
+* Input: device, device attribute, char buf
+* Output: no
+* Return:
+***********************************************************************/
+static ssize_t fts_gesture_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+ u8 val;
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ mutex_lock(&fts_input_dev->mutex);
+ fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &val);
+ count =
+ sprintf(buf, "Gesture Mode: %s\n",
+ fts_gesture_data.mode ? "On" : "Off");
+ count += sprintf(buf + count, "Reg(0xD0) = %d\n", val);
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+
+/************************************************************************
+* Name: fts_gesture_store
+* Brief: no
+* Input: device, device attribute, char buf, char count
+* Output: no
+* Return:
+***********************************************************************/
+static ssize_t fts_gesture_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ mutex_lock(&fts_input_dev->mutex);
+
+ if (FTS_SYSFS_ECHO_ON(buf)) {
+ FTS_INFO("[GESTURE]enable gesture");
+ fts_gesture_data.mode = ENABLE;
+ } else if (FTS_SYSFS_ECHO_OFF(buf)) {
+ FTS_INFO("[GESTURE]disable gesture");
+ fts_gesture_data.mode = DISABLE;
+ }
+
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+
+/************************************************************************
+* Name: fts_gesture_buf_show
+* Brief: no
+* Input: device, device attribute, char buf
+* Output: no
+* Return:
+***********************************************************************/
+static ssize_t fts_gesture_buf_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+ int i = 0;
+
+ mutex_lock(&fts_input_dev->mutex);
+ count =
+ snprintf(buf, PAGE_SIZE, "Gesture ID: 0x%x\n",
+ fts_gesture_data.header[0]);
+ count +=
+ snprintf(buf + count, PAGE_SIZE, "Gesture PointNum: %d\n",
+ fts_gesture_data.header[1]);
+ count += snprintf(buf + count, PAGE_SIZE, "Gesture Point Buf:\n");
+ for (i = 0; i < fts_gesture_data.header[1]; i++) {
+ count +=
+ snprintf(buf + count, PAGE_SIZE, "%3d(%4d,%4d) ", i,
+ fts_gesture_data.coordinate_x[i],
+ fts_gesture_data.coordinate_y[i]);
+ if ((i + 1) % 4 == 0)
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
+ }
+ count += snprintf(buf + count, PAGE_SIZE, "\n");
+ mutex_unlock(&fts_input_dev->mutex);
+
+ return count;
+}
+
+/************************************************************************
+* Name: fts_gesture_buf_store
+* Brief: no
+* Input: device, device attribute, char buf, char count
+* Output: no
+* Return:
+***********************************************************************/
+static ssize_t fts_gesture_buf_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+/*****************************************************************************
+* Name: fts_create_gesture_sysfs
+* Brief:
+* Input:
+* Output: None
+* Return: 0-success or error
+*****************************************************************************/
+int fts_create_gesture_sysfs(struct i2c_client *client)
+{
+ int ret = 0;
+
+ ret = sysfs_create_group(&client->dev.kobj, &fts_gesture_group);
+ if (ret != 0) {
+ FTS_ERROR
+ ("[GESTURE]fts_gesture_mode_group(sysfs) create failed!");
+ sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
+ return ret;
+ }
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_gesture_recovery
+* Brief: recovery gesture state when reset
+* Input:
+* Output: None
+* Return:
+*****************************************************************************/
+void fts_gesture_recovery(struct i2c_client *client)
+{
+ if (fts_gesture_data.mode && fts_gesture_data.active) {
+ fts_i2c_write_reg(client, 0xD1, 0xff);
+ fts_i2c_write_reg(client, 0xD2, 0xff);
+ fts_i2c_write_reg(client, 0xD5, 0xff);
+ fts_i2c_write_reg(client, 0xD6, 0xff);
+ fts_i2c_write_reg(client, 0xD7, 0xff);
+ fts_i2c_write_reg(client, 0xD8, 0xff);
+ fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, ENABLE);
+ }
+}
+
+/*****************************************************************************
+* Name: fts_gesture_init
+* Brief:
+* Input:
+* Output: None
+* Return: None
+*****************************************************************************/
+int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client)
+{
+ FTS_FUNC_ENTER();
+ input_set_capability(input_dev, EV_KEY, KEY_POWER);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
+ input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);
+
+ __set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
+ __set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
+ __set_bit(KEY_GESTURE_UP, input_dev->keybit);
+ __set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
+ __set_bit(KEY_GESTURE_U, input_dev->keybit);
+ __set_bit(KEY_GESTURE_O, input_dev->keybit);
+ __set_bit(KEY_GESTURE_E, input_dev->keybit);
+ __set_bit(KEY_GESTURE_M, input_dev->keybit);
+ __set_bit(KEY_GESTURE_W, input_dev->keybit);
+ __set_bit(KEY_GESTURE_L, input_dev->keybit);
+ __set_bit(KEY_GESTURE_S, input_dev->keybit);
+ __set_bit(KEY_GESTURE_V, input_dev->keybit);
+ __set_bit(KEY_GESTURE_C, input_dev->keybit);
+ __set_bit(KEY_GESTURE_Z, input_dev->keybit);
+
+ fts_create_gesture_sysfs(client);
+ fts_gesture_data.mode = 0;
+ fts_gesture_data.active = 0;
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/************************************************************************
+* Name: fts_gesture_exit
+* Brief: remove sys
+* Input: i2c info
+* Output: no
+* Return: no
+***********************************************************************/
+int fts_gesture_exit(struct i2c_client *client)
+{
+ sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_check_gesture
+* Brief:
+* Input:
+* Output: None
+* Return: None
+*****************************************************************************/
+static void fts_check_gesture(struct input_dev *input_dev, int gesture_id)
+{
+ char *envp[2];
+ int gesture;
+
+ FTS_FUNC_ENTER();
+ switch (gesture_id) {
+ case GESTURE_LEFT:
+ envp[0] = "GESTURE=LEFT";
+ gesture = KEY_GESTURE_LEFT;
+ break;
+ case GESTURE_RIGHT:
+ envp[0] = "GESTURE=RIGHT";
+ gesture = KEY_GESTURE_RIGHT;
+ break;
+ case GESTURE_UP:
+ envp[0] = "GESTURE=UP";
+ gesture = KEY_GESTURE_UP;
+ break;
+ case GESTURE_DOWN:
+ envp[0] = "GESTURE=DOWN";
+ gesture = KEY_GESTURE_DOWN;
+ break;
+ case GESTURE_DOUBLECLICK:
+ envp[0] = "GESTURE=DOUBLE_CLICK";
+ gesture = KEY_POWER;
+ break;
+ case GESTURE_O:
+ envp[0] = "GESTURE=O";
+ gesture = KEY_GESTURE_O;
+ break;
+ case GESTURE_W:
+ envp[0] = "GESTURE=W";
+ gesture = KEY_GESTURE_W;
+ break;
+ case GESTURE_M:
+ envp[0] = "GESTURE=M";
+ gesture = KEY_GESTURE_M;
+ break;
+ case GESTURE_E:
+ envp[0] = "GESTURE=E";
+ gesture = KEY_GESTURE_E;
+ break;
+ case GESTURE_L:
+ envp[0] = "GESTURE=L";
+ gesture = KEY_GESTURE_L;
+ break;
+ case GESTURE_S:
+ envp[0] = "GESTURE=S";
+ gesture = KEY_GESTURE_S;
+ break;
+ case GESTURE_V:
+ envp[0] = "GESTURE=V";
+ gesture = KEY_GESTURE_V;
+ break;
+ case GESTURE_Z:
+ envp[0] = "GESTURE=Z";
+ gesture = KEY_GESTURE_Z;
+ break;
+ case GESTURE_C:
+ envp[0] = "GESTURE=C";
+ gesture = KEY_GESTURE_C;
+ break;
+ default:
+ envp[0] = "GESTURE=NONE";
+ gesture = -1;
+ break;
+ }
+ FTS_DEBUG("envp[0]: %s", envp[0]);
+ /* report event key */
+ /*if (gesture != -1)
+ {
+ input_report_key(input_dev, gesture, 1);
+ input_sync(input_dev);
+ input_report_key(input_dev, gesture, 0);
+ input_sync(input_dev);
+ } */
+
+ envp[1] = NULL;
+ kobject_uevent_env(&fts_wq_data->client->dev.kobj, KOBJ_CHANGE, envp);
+ sysfs_notify(&fts_wq_data->client->dev.kobj, NULL, "GESTURE_ID");
+
+ FTS_FUNC_EXIT();
+}
+
+/************************************************************************
+* Name: fts_gesture_readdata
+* Brief: read data from TP register
+* Input: no
+* Output: no
+* Return: fail <0
+***********************************************************************/
+static int fts_gesture_read_buffer(struct i2c_client *client, u8 *buf,
+ int read_bytes)
+{
+ int remain_bytes;
+ int ret;
+ int i;
+
+ if (read_bytes <= I2C_BUFFER_LENGTH_MAXINUM) {
+ ret = fts_i2c_read(client, buf, 1, buf, read_bytes);
+ } else {
+ ret =
+ fts_i2c_read(client, buf, 1, buf,
+ I2C_BUFFER_LENGTH_MAXINUM);
+ remain_bytes = read_bytes - I2C_BUFFER_LENGTH_MAXINUM;
+ for (i = 1; remain_bytes > 0; i++) {
+ if (remain_bytes <= I2C_BUFFER_LENGTH_MAXINUM)
+ ret =
+ fts_i2c_read(client, buf, 0,
+ buf +
+ I2C_BUFFER_LENGTH_MAXINUM * i,
+ remain_bytes);
+ else
+ ret =
+ fts_i2c_read(client, buf, 0,
+ buf +
+ I2C_BUFFER_LENGTH_MAXINUM * i,
+ I2C_BUFFER_LENGTH_MAXINUM);
+ remain_bytes -= I2C_BUFFER_LENGTH_MAXINUM;
+ }
+ }
+
+ return ret;
+}
+
+/************************************************************************
+* Name: fts_gesture_readdata
+* Brief: read data from TP register
+* Input: no
+* Output: no
+* Return: fail <0
+***********************************************************************/
+int fts_gesture_readdata(struct i2c_client *client)
+{
+ u8 buf[FTS_GESTRUE_POINTS * 4] = { 0 };
+ int ret = -1;
+ int i = 0;
+ int gestrue_id = 0;
+ int read_bytes = 0;
+ u8 pointnum;
+
+ FTS_FUNC_ENTER();
+ /* init variable before read gesture point */
+ memset(fts_gesture_data.header, 0, FTS_GESTRUE_POINTS_HEADER);
+ memset(fts_gesture_data.coordinate_x, 0,
+ FTS_GESTRUE_POINTS * sizeof(u16));
+ memset(fts_gesture_data.coordinate_y, 0,
+ FTS_GESTRUE_POINTS * sizeof(u16));
+
+ buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
+ ret = fts_i2c_read(client, buf, 1, buf, FTS_GESTRUE_POINTS_HEADER);
+ if (ret < 0) {
+ FTS_ERROR("[GESTURE]Read gesture header data failed!!");
+ FTS_FUNC_EXIT();
+ return ret;
+ }
+
+ /* FW recognize gesture */
+ if (chip_types.chip_idh == 0x54 || chip_types.chip_idh == 0x58
+ || chip_types.chip_idh == 0x86 || chip_types.chip_idh == 0x87
+ || chip_types.chip_idh == 0x64) {
+ memcpy(fts_gesture_data.header, buf, FTS_GESTRUE_POINTS_HEADER);
+ gestrue_id = buf[0];
+ pointnum = buf[1];
+ read_bytes = ((int)pointnum) * 4 + 2;
+ buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
+ FTS_DEBUG("[GESTURE]PointNum=%d", pointnum);
+ ret = fts_gesture_read_buffer(client, buf, read_bytes);
+ if (ret < 0) {
+ FTS_ERROR("[GESTURE]Read gesture touch data failed!!");
+ FTS_FUNC_EXIT();
+ return ret;
+ }
+
+ fts_check_gesture(fts_input_dev, gestrue_id);
+ for (i = 0; i < pointnum; i++) {
+ fts_gesture_data.coordinate_x[i] =
+ (((s16) buf[0 + (4 * i + 2)]) & 0x0F) << 8 |
+ (((s16) buf[1 + (4 * i + 2)]) & 0xFF);
+ fts_gesture_data.coordinate_y[i] =
+ (((s16) buf[2 + (4 * i + 2)]) & 0x0F) << 8 |
+ (((s16) buf[3 + (4 * i + 2)]) & 0xFF);
+ }
+ FTS_FUNC_EXIT();
+ return 0;
+ }
+ /* other IC's gestrue in driver */
+ if (0x24 == buf[0]) {
+ gestrue_id = 0x24;
+ fts_check_gesture(fts_input_dev, gestrue_id);
+ FTS_DEBUG("[GESTURE]%d check_gesture gestrue_id", gestrue_id);
+ FTS_FUNC_EXIT();
+ return -1;
+ }
+
+ /* Host Driver recognize gesture */
+ pointnum = buf[1];
+ read_bytes = ((int)pointnum) * 4 + 2;
+ buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
+ ret = fts_gesture_read_buffer(client, buf, read_bytes);
+ if (ret < 0) {
+ FTS_ERROR ("[GESTURE]Driver recognize gesture -"
+ "Read gesture touch data failed!!");
+ FTS_FUNC_EXIT();
+ return ret;
+ }
+
+ /*
+ * Host Driver recognize gesture, need gesture lib.a
+ * Not use now for compatibility
+ gestrue_id = fetch_object_sample(buf, pointnum);
+ */
+ gestrue_id = 0x24;
+ fts_check_gesture(fts_input_dev, gestrue_id);
+ FTS_DEBUG("[GESTURE]%d read gestrue_id", gestrue_id);
+
+ for (i = 0; i < pointnum; i++) {
+ fts_gesture_data.coordinate_x[i] =
+ (((s16) buf[0 + (4 * i + 8)]) & 0x0F) << 8 |
+ (((s16) buf[1 + (4 * i + 8)]) & 0xFF);
+ fts_gesture_data.coordinate_y[i] =
+ (((s16) buf[2 + (4 * i + 8)]) & 0x0F) << 8 |
+ (((s16) buf[3 + (4 * i + 8)]) & 0xFF);
+ }
+ FTS_FUNC_EXIT();
+ return -1;
+}
+
+/*****************************************************************************
+* Name: fts_gesture_suspend
+* Brief:
+* Input:
+* Output: None
+* Return: None
+*****************************************************************************/
+int fts_gesture_suspend(struct i2c_client *i2c_client)
+{
+ int i;
+ u8 state;
+
+ FTS_FUNC_ENTER();
+
+ /* gesture not enable, return immediately */
+ if (fts_gesture_data.mode == 0) {
+ FTS_DEBUG("gesture is disabled");
+ FTS_FUNC_EXIT();
+ return -1;
+ }
+
+ for (i = 0; i < 5; i++) {
+ fts_i2c_write_reg(i2c_client, 0xd1, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd2, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd5, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd6, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd7, 0xff);
+ fts_i2c_write_reg(i2c_client, 0xd8, 0xff);
+ fts_i2c_write_reg(i2c_client, FTS_REG_GESTURE_EN, 0x01);
+ msleep(1);
+ fts_i2c_read_reg(i2c_client, FTS_REG_GESTURE_EN, &state);
+ if (state == 1)
+ break;
+ }
+
+ if (i >= 5) {
+ FTS_ERROR("[GESTURE]Enter into gesture(suspend) failed!\n");
+ FTS_FUNC_EXIT();
+ return -1;
+ }
+
+ fts_gesture_data.active = 1;
+ FTS_DEBUG("[GESTURE]Enter into gesture(suspend) successfully!");
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_gesture_resume
+* Brief:
+* Input:
+* Output: None
+* Return: None
+*****************************************************************************/
+int fts_gesture_resume(struct i2c_client *client)
+{
+ int i;
+ u8 state;
+
+ FTS_FUNC_ENTER();
+
+ /* gesture not enable, return immediately */
+ if (fts_gesture_data.mode == 0) {
+ FTS_DEBUG("gesture is disabled");
+ FTS_FUNC_EXIT();
+ return -1;
+ }
+
+ fts_gesture_data.active = 0;
+ for (i = 0; i < 5; i++) {
+ fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, 0x00);
+ msleep(1);
+ fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
+ if (state == 0)
+ break;
+ }
+
+ if (i >= 5)
+ FTS_ERROR("[GESTURE]Clear gesture(resume) failed!\n");
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+#endif
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c b/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c
new file mode 100644
index 000000000000..75cd917eae2b
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c
@@ -0,0 +1,209 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+/************************************************************************
+*
+* File Name: focaltech_i2c.c
+*
+* Author: fupeipei
+*
+* Created: 2016-08-04
+*
+* Abstract: i2c communication with TP
+*
+* Version: v1.0
+*
+* Revision History:
+* v1.0:
+* First release. By fupeipei 2016-08-04
+************************************************************************/
+
+/*****************************************************************************
+* Included header files
+*****************************************************************************/
+#include "focaltech_core.h"
+
+/*****************************************************************************
+* Private constant and macro definitions using #define
+*****************************************************************************/
+
+/*****************************************************************************
+* Private enumerations, structures and unions using typedef
+*****************************************************************************/
+
+/*****************************************************************************
+* Static variables
+*****************************************************************************/
+static DEFINE_MUTEX(i2c_rw_access);
+
+/*****************************************************************************
+* Global variable or extern global variabls/functions
+*****************************************************************************/
+
+/*****************************************************************************
+* Static function prototypes
+*****************************************************************************/
+
+/*****************************************************************************
+* functions body
+*****************************************************************************/
+
+/************************************************************************
+* Name: fts_i2c_read
+* Brief: i2c read
+* Input: i2c info, write buf, write len, read buf, read len
+* Output: get data in the 3rd buf
+* Return: fail <0
+***********************************************************************/
+int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen,
+ char *readbuf, int readlen)
+{
+ int ret = 0;
+
+ mutex_lock(&i2c_rw_access);
+
+ if (readlen > 0) {
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0) {
+ FTS_ERROR("[IIC]: i2c_transfer(write)"
+ "error,ret=%d!!", ret);
+ }
+ } else {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0) {
+ FTS_ERROR("[IIC]: i2c_transfer(read)"
+ "error, ret=%d!!", ret);
+ }
+ }
+ }
+
+ mutex_unlock(&i2c_rw_access);
+ return ret;
+}
+
+/************************************************************************
+* Name: fts_i2c_write
+* Brief: i2c write
+* Input: i2c info, write buf, write len
+* Output: no
+* Return: fail <0
+***********************************************************************/
+int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen)
+{
+ int ret = 0;
+
+ mutex_lock(&i2c_rw_access);
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0) {
+ FTS_ERROR("%s: i2c_transfer(write) error, ret=%d",
+ __func__, ret);
+ }
+ }
+ mutex_unlock(&i2c_rw_access);
+
+ return ret;
+}
+
+/************************************************************************
+* Name: fts_i2c_write_reg
+* Brief: write register
+* Input: i2c info, reg address, reg value
+* Output: no
+* Return: fail <0
+***********************************************************************/
+int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue)
+{
+ u8 buf[2] = { 0 };
+
+ buf[0] = regaddr;
+ buf[1] = regvalue;
+ return fts_i2c_write(client, buf, sizeof(buf));
+}
+
+/************************************************************************
+* Name: fts_i2c_read_reg
+* Brief: read register
+* Input: i2c info, reg address, reg value
+* Output: get reg value
+* Return: fail <0
+***********************************************************************/
+int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue)
+{
+ return fts_i2c_read(client, &regaddr, 1, regvalue, 1);
+}
+
+/************************************************************************
+* Name: fts_i2c_init
+* Brief: fts i2c init
+* Input:
+* Output:
+* Return:
+***********************************************************************/
+int fts_i2c_init(void)
+{
+ FTS_FUNC_ENTER();
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+
+/************************************************************************
+* Name: fts_i2c_exit
+* Brief: fts i2c exit
+* Input:
+* Output:
+* Return:
+***********************************************************************/
+int fts_i2c_exit(void)
+{
+ FTS_FUNC_ENTER();
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c b/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c
new file mode 100644
index 000000000000..0fa561748f75
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c
@@ -0,0 +1,151 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+/*****************************************************************************
+*
+* File Name: focaltech_point_report_check.c
+*
+* Author: WangTao
+*
+* Created: 2016-11-16
+*
+* Abstract: point report check function
+*
+* Version: v1.0
+*
+* Revision History:
+* v1.0:
+* First release. By WangTao 2016-11-16
+*****************************************************************************/
+
+/*****************************************************************************
+* Included header files
+*****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_POINT_REPORT_CHECK_EN
+/*****************************************************************************
+* Private constant and macro definitions using #define
+*****************************************************************************/
+#define POINT_REPORT_CHECK_WAIT_TIME 200
+
+/*****************************************************************************
+* Private enumerations, structures and unions using typedef
+*****************************************************************************/
+
+/*****************************************************************************
+* Static variables
+*****************************************************************************/
+static struct delayed_work fts_point_report_check_work;
+static struct workqueue_struct *fts_point_report_check_workqueue;
+
+/*****************************************************************************
+* Global variable or extern global variabls/functions
+*****************************************************************************/
+
+/*****************************************************************************
+* Static function prototypes
+*****************************************************************************/
+
+/*****************************************************************************
+* functions body
+*****************************************************************************/
+
+/*****************************************************************************
+* Name: fts_point_report_check_func
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static void fts_point_report_check_func(struct work_struct *work)
+{
+
+#if FTS_MT_PROTOCOL_B_EN
+ unsigned int finger_count = 0;
+
+ FTS_FUNC_ENTER();
+
+ for (finger_count = 0; finger_count < FTS_MAX_POINTS; finger_count++) {
+ input_mt_slot(fts_input_dev, finger_count);
+ input_mt_report_slot_state(fts_input_dev, MT_TOOL_FINGER,
+ false);
+ }
+#else
+ input_mt_sync(fts_input_dev);
+#endif
+ input_report_key(fts_input_dev, BTN_TOUCH, 0);
+ input_sync(fts_input_dev);
+
+ FTS_FUNC_EXIT();
+}
+
+void fts_point_report_check_queue_work(void)
+{
+
+ cancel_delayed_work(&fts_point_report_check_work);
+ queue_delayed_work(fts_point_report_check_workqueue,
+ &fts_point_report_check_work,
+ msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME));
+
+}
+
+/*****************************************************************************
+* Name: fts_point_report_check_init
+* Brief:
+* Input:
+* Output:
+* Return: < 0: Fail to create esd check queue
+*****************************************************************************/
+int fts_point_report_check_init(void)
+{
+ FTS_FUNC_ENTER();
+
+ INIT_DELAYED_WORK(&fts_point_report_check_work,
+ fts_point_report_check_func);
+ fts_point_report_check_workqueue =
+ create_workqueue("fts_point_report_check_func_wq");
+ if (fts_point_report_check_workqueue == NULL) {
+ FTS_ERROR("[POINT_REPORT]: Failed to create"
+ "fts_point_report_check_workqueue!!");
+ } else {
+ FTS_DEBUG("[POINT_REPORT]: Success to create"
+ "fts_point_report_check_workqueue!!");
+ }
+
+ FTS_FUNC_EXIT();
+
+ return 0;
+}
+
+/*****************************************************************************
+* Name: fts_point_report_check_exit
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+int fts_point_report_check_exit(void)
+{
+ FTS_FUNC_ENTER();
+
+ destroy_workqueue(fts_point_report_check_workqueue);
+
+ FTS_FUNC_EXIT();
+ return 0;
+}
+#endif /* FTS_POINT_REPORT_CHECK_EN */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c b/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c
new file mode 100644
index 000000000000..4a62ee65eaa6
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c
@@ -0,0 +1,311 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+/*****************************************************************************
+*
+* File Name: focaltech_esdcheck.c
+*
+* Author: Focaltech Driver Team
+*
+* Created: 2016-08-03
+*
+* Abstract: Sensor
+*
+* Version: v1.0
+*
+* Revision History:
+* v1.0:
+* First release. By luougojin 2016-08-03
+*****************************************************************************/
+
+/*****************************************************************************
+* Included header files
+*****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_PSENSOR_EN
+/*****************************************************************************
+* Private constant and macro definitions using #define
+*****************************************************************************/
+/* psensor register address*/
+#define FTS_REG_PSENSOR_ENABLE 0xB0
+#define FTS_REG_PSENSOR_STATUS 0x01
+
+/* psensor register bits*/
+#define FTS_PSENSOR_ENABLE_MASK 0x01
+#define FTS_PSENSOR_STATUS_NEAR 0xC0
+#define FTS_PSENSOR_STATUS_FAR 0xE0
+#define FTS_PSENSOR_FAR_TO_NEAR 0
+#define FTS_PSENSOR_NEAR_TO_FAR 1
+#define FTS_PSENSOR_ORIGINAL_STATE_FAR 1
+#define FTS_PSENSOR_WAKEUP_TIMEOUT 500
+
+/*****************************************************************************
+* Static variables
+*****************************************************************************/
+static struct sensors_classdev __maybe_unused sensors_proximity_cdev = {
+ .name = "fts-proximity",
+ .vendor = "FocalTech",
+ .version = 1,
+ .handle = SENSORS_PROXIMITY_HANDLE,
+ .type = SENSOR_TYPE_PROXIMITY,
+ .max_range = "5.0",
+ .resolution = "5.0",
+ .sensor_power = "0.1",
+ .min_delay = 0,
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+ .enabled = 0,
+ .delay_msec = 200,
+ .sensors_enable = NULL,
+ .sensors_poll_delay = NULL,
+};
+
+/*****************************************************************************
+* functions body
+*****************************************************************************/
+/*****************************************************************************
+* Name: fts_psensor_support_enabled
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static inline bool fts_psensor_support_enabled(void)
+{
+ /*return config_enabled(CONFIG_TOUCHSCREEN_FTS_PSENSOR); */
+ return FTS_PSENSOR_EN;
+}
+
+/*****************************************************************************
+* Name: fts_psensor_enable
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static void fts_psensor_enable(struct fts_ts_data *data, int enable)
+{
+ u8 state;
+ int ret = -1;
+
+ if (data->client == NULL)
+ return;
+
+ fts_i2c_read_reg(data->client, FTS_REG_PSENSOR_ENABLE, &state);
+ if (enable)
+ state |= FTS_PSENSOR_ENABLE_MASK;
+ else
+ state &= ~FTS_PSENSOR_ENABLE_MASK;
+
+ ret = fts_i2c_write_reg(data->client, FTS_REG_PSENSOR_ENABLE, state);
+ if (ret < 0)
+ FTS_ERROR("write psensor switch command failed");
+}
+
+/*****************************************************************************
+* Name: fts_psensor_enable_set
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_psensor_enable_set(struct sensors_classdev *sensors_cdev,
+ unsigned int enable)
+{
+ struct fts_psensor_platform_data *psensor_pdata =
+ container_of(sensors_cdev,
+ struct fts_psensor_platform_data, ps_cdev);
+ struct fts_ts_data *data = psensor_pdata->data;
+ struct input_dev *input_dev = data->psensor_pdata->input_psensor_dev;
+
+ mutex_lock(&input_dev->mutex);
+ fts_psensor_enable(data, enable);
+ psensor_pdata->tp_psensor_data = FTS_PSENSOR_ORIGINAL_STATE_FAR;
+ if (enable)
+ psensor_pdata->tp_psensor_opened = 1;
+ else
+ psensor_pdata->tp_psensor_opened = 0;
+ mutex_unlock(&input_dev->mutex);
+ return enable;
+}
+
+/*****************************************************************************
+* Name: fts_read_tp_psensor_data
+* Brief:
+* Input:
+* Output:
+* Return:
+*****************************************************************************/
+static int fts_read_tp_psensor_data(struct fts_ts_data *data)
+{
+ u8 psensor_status;
+ char tmp;
+ int ret = 1;
+
+ fts_i2c_read_reg(data->client, FTS_REG_PSENSOR_STATUS, &psensor_status);
+
+ tmp = data->psensor_pdata->tp_psensor_data;
+ if (psensor_status == FTS_PSENSOR_STATUS_NEAR)
+ data->psensor_pdata->tp_psensor_data = FTS_PSENSOR_FAR_TO_NEAR;
+ else if (psensor_status == FTS_PSENSOR_STATUS_FAR)
+ data->psensor_pdata->tp_psensor_data = FTS_PSENSOR_NEAR_TO_FAR;
+
+ if (tmp != data->psensor_pdata->tp_psensor_data) {
+ FTS_ERROR("%s sensor data changed", __func__);
+ ret = 0;
+ }
+ return ret;
+}
+
+int fts_sensor_read_data(struct fts_ts_data *data)
+{
+ int ret = 0;
+
+ if (fts_psensor_support_enabled()
+ && data->psensor_pdata->tp_psensor_opened) {
+ ret = fts_read_tp_psensor_data(data);
+ if (!ret) {
+ if (data->suspended) {
+ pm_wakeup_event(&data->client->dev,
+ FTS_PSENSOR_WAKEUP_TIMEOUT);
+ }
+ input_report_abs(data->psensor_pdata->input_psensor_dev,
+ ABS_DISTANCE,
+ data->psensor_pdata->tp_psensor_data);
+ input_sync(data->psensor_pdata->input_psensor_dev);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int fts_sensor_suspend(struct fts_ts_data *data)
+{
+ int ret = 0;
+
+ if (fts_psensor_support_enabled()
+ && device_may_wakeup(&data->client->dev)
+ && data->psensor_pdata->tp_psensor_opened) {
+ ret = enable_irq_wake(data->client->irq);
+ if (ret != 0)
+ FTS_ERROR("%s: set_irq_wake failed", __func__);
+ data->suspended = true;
+ return 1;
+ }
+
+ return 0;
+}
+
+int fts_sensor_resume(struct fts_ts_data *data)
+{
+ int ret = 0;
+
+ if (fts_psensor_support_enabled()
+ && device_may_wakeup(&data->client->dev)
+ && data->psensor_pdata->tp_psensor_opened) {
+ ret = disable_irq_wake(data->client->irq);
+ if (ret)
+ FTS_ERROR("%s: disable_irq_wake failed", __func__);
+ data->suspended = false;
+ return 1;
+ }
+
+ return 0;
+}
+
+int fts_sensor_init(struct fts_ts_data *data)
+{
+ struct fts_psensor_platform_data *psensor_pdata;
+ struct input_dev *psensor_input_dev;
+ int err;
+
+ if (fts_psensor_support_enabled()) {
+ device_init_wakeup(&data->client->dev, 1);
+ psensor_pdata =
+ devm_kzalloc(&data->client->dev,
+ sizeof(struct fts_psensor_platform_data),
+ GFP_KERNEL);
+ if (!psensor_pdata) {
+ FTS_ERROR("Failed to allocate memory");
+ goto irq_free;
+ }
+ data->psensor_pdata = psensor_pdata;
+
+ psensor_input_dev = input_allocate_device();
+ if (!psensor_input_dev) {
+ FTS_ERROR("Failed to allocate device");
+ goto free_psensor_pdata;
+ }
+
+ __set_bit(EV_ABS, psensor_input_dev->evbit);
+ input_set_abs_params(psensor_input_dev, ABS_DISTANCE, 0, 1, 0,
+ 0);
+ psensor_input_dev->name = "proximity";
+ psensor_input_dev->id.bustype = BUS_I2C;
+ psensor_input_dev->dev.parent = &data->client->dev;
+ data->psensor_pdata->input_psensor_dev = psensor_input_dev;
+
+ err = input_register_device(psensor_input_dev);
+ if (err) {
+ FTS_ERROR("Unable to register device, err=%d", err);
+ goto free_psensor_input_dev;
+ }
+
+ psensor_pdata->ps_cdev = sensors_proximity_cdev;
+ psensor_pdata->ps_cdev.sensors_enable = fts_psensor_enable_set;
+ psensor_pdata->data = data;
+
+ err =
+ sensors_classdev_register(&data->client->dev,
+ &psensor_pdata->ps_cdev);
+ if (err)
+ goto unregister_psensor_input_device;
+ }
+
+ return 0;
+unregister_psensor_input_device:
+ if (fts_psensor_support_enabled())
+ input_unregister_device(data->psensor_pdata->input_psensor_dev);
+free_psensor_input_dev:
+ if (fts_psensor_support_enabled())
+ input_free_device(data->psensor_pdata->input_psensor_dev);
+free_psensor_pdata:
+ if (fts_psensor_support_enabled()) {
+ devm_kfree(&data->client->dev, psensor_pdata);
+ data->psensor_pdata = NULL;
+ }
+irq_free:
+ if (fts_psensor_support_enabled())
+ device_init_wakeup(&data->client->dev, 0);
+ free_irq(data->client->irq, data);
+
+ return 1;
+}
+
+int fts_sensor_remove(struct fts_ts_data *data)
+{
+ if (fts_psensor_support_enabled()) {
+ device_init_wakeup(&data->client->dev, 0);
+ sensors_classdev_unregister(&data->psensor_pdata->ps_cdev);
+ input_unregister_device(data->psensor_pdata->input_psensor_dev);
+ devm_kfree(&data->client->dev, data->psensor_pdata);
+ data->psensor_pdata = NULL;
+ }
+ return 0;
+}
+#endif /* FTS_PSENSOR_EN */
diff --git a/drivers/input/touchscreen/focaltech_touch/include/firmware/FT8716_app_sample.i b/drivers/input/touchscreen/focaltech_touch/include/firmware/FT8716_app_sample.i
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/include/firmware/FT8716_app_sample.i
diff --git a/drivers/input/touchscreen/focaltech_touch/include/firmware/lcd_cfg.i b/drivers/input/touchscreen/focaltech_touch/include/firmware/lcd_cfg.i
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/include/firmware/lcd_cfg.i
diff --git a/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8606_Pramboot_V0.7_20150507.i b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8606_Pramboot_V0.7_20150507.i
new file mode 100644
index 000000000000..f031758e0207
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8606_Pramboot_V0.7_20150507.i
@@ -0,0 +1,244 @@
+0x2, 0x9, 0x9b, 0xca, 0x39, 0x12, 0xc, 0x4b, 0xda, 0x39, 0x32, 0x2, 0x0, 0x3,
+ 0x6d, 0x22, 0x80, 0x13, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0xe5, 0xb5, 0x7a, 0xb, 0xb0, 0xb, 0x14, 0xb, 0x24, 0xbd, 0x32, 0x38,
+ 0xe9, 0x22, 0xff, 0x2, 0xa, 0x70, 0xa9, 0xc2, 0xb4, 0x74, 0x5, 0x12, 0xc,
+ 0x36, 0x12, 0xc, 0x1d, 0xa9, 0xd2, 0xb4, 0x30, 0xe0, 0x2, 0xd3, 0x22, 0xc3,
+ 0x22, 0x2, 0x0, 0xf9, 0xca, 0x3b, 0x7a, 0xd, 0x8, 0x7f, 0x31, 0xe5, 0x23,
+ 0xb4, 0x80, 0x2, 0x80, 0x3, 0x2, 0x0, 0xdc, 0x7f, 0x13, 0x5e, 0x34, 0x0,
+ 0x7f, 0x7d, 0x23, 0x7e, 0x34, 0x0, 0x80, 0x9d, 0x32, 0x7a, 0x35, 0xe, 0x7e,
+ 0x35, 0xc, 0xbe, 0x35, 0xe, 0x38, 0x2, 0x80, 0x5d, 0x7e, 0x35, 0xe, 0x7a,
+ 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x8, 0xf3, 0x7e, 0x35, 0xc,
+ 0x9e, 0x35, 0xe, 0x7a, 0x35, 0xc, 0x7e, 0x35, 0xe, 0x6d, 0x22, 0x2f, 0x31,
+ 0x7e, 0x1d, 0x8, 0x2e, 0x35, 0xe, 0x7a, 0x1d, 0x8, 0x80, 0x27, 0x7e, 0x34,
+ 0x0, 0x80, 0x7a, 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x8, 0xf3,
+ 0x7e, 0x35, 0xc, 0x9e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0xc, 0x7e, 0x1d, 0x8,
+ 0x2e, 0x34, 0x0, 0x80, 0x7a, 0x1d, 0x8, 0x2e, 0x38, 0x0, 0x80, 0x7e, 0x35,
+ 0xc, 0xbe, 0x34, 0x0, 0x80, 0x50, 0xd0, 0x4d, 0x33, 0x68, 0x26, 0x7a, 0x35,
+ 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x8, 0xf3, 0x80, 0x19, 0x74, 0x2,
+ 0x12, 0x8, 0x3d, 0x5e, 0x70, 0xf4, 0x12, 0x9, 0xe7, 0x7e, 0x35, 0xc, 0x7a,
+ 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x6, 0x42, 0xd3, 0xda, 0x3b,
+ 0x22, 0xa9, 0xc0, 0x93, 0x75, 0x38, 0x0, 0x32, 0xc, 0x60, 0xf3, 0x9f, 0x46,
+ 0xb9, 0x2, 0xfd, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x7c, 0x6b, 0xc2, 0x2, 0xe5, 0x21, 0x14, 0x78, 0x3, 0x2, 0x2,
+ 0xbf, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0x30, 0x1b, 0xb1, 0x78, 0x3, 0x2,
+ 0x2, 0x7c, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0x8d, 0x1b, 0xb1, 0x78, 0x3,
+ 0x2, 0x2, 0xa6, 0x24, 0xf9, 0x78, 0x3, 0x2, 0x2, 0xbb, 0x24, 0xaf, 0x78,
+ 0x3, 0x2, 0x3, 0x29, 0x24, 0xfd, 0x68, 0x2d, 0x14, 0x78, 0x3, 0x2, 0x2,
+ 0xc2, 0x14, 0x78, 0x3, 0x2, 0x2, 0xbf, 0x1b, 0xb2, 0x78, 0x3, 0x2, 0x2,
+ 0xbf, 0x24, 0xda, 0x68, 0x19, 0x24, 0xe6, 0x68, 0x12, 0x24, 0xeb, 0x68,
+ 0x2e, 0x24, 0xf3, 0x78, 0x3, 0x2, 0x2, 0xbf, 0x24, 0x77, 0x68, 0x3, 0x2,
+ 0x3, 0x33, 0x2, 0x3, 0x30, 0xbe, 0x60, 0x4, 0x50, 0xc, 0x75, 0x16, 0x0,
+ 0x7c, 0x16, 0x2e, 0x10, 0x24, 0x7c, 0xb7, 0xa5, 0xf7, 0xa5, 0xbe, 0x0, 0x2,
+ 0x80, 0x3, 0x2, 0x3, 0x33, 0xd2, 0x2, 0x22, 0x7c, 0xb6, 0x24, 0x0, 0x78,
+ 0x3, 0x2, 0x3, 0x33, 0x1b, 0xb1, 0x68, 0x1e, 0x14, 0x68, 0x1e, 0x14, 0x68,
+ 0x1e, 0x14, 0x68, 0x1e, 0xb, 0xb2, 0x78, 0x33, 0x30, 0x1, 0x7, 0x7e, 0x8,
+ 0x0, 0x3e, 0x2, 0x2, 0x4d, 0x7e, 0x8, 0x1, 0x4a, 0x2, 0x2, 0x4d, 0x2, 0x2,
+ 0xe7, 0x2, 0x2, 0xee, 0x2, 0x3, 0x6, 0xa, 0x27, 0x7e, 0xd, 0x39, 0xb, 0x16,
+ 0xb, 0xa, 0x30, 0x2d, 0x32, 0x1b, 0xa, 0x30, 0x6d, 0x33, 0x7e, 0xd, 0x39,
+ 0x79, 0x30, 0x0, 0x6, 0x22, 0x7c, 0xb7, 0x62, 0x16, 0x7e, 0x2d, 0x39, 0x2e,
+ 0x54, 0x0, 0x6, 0xb, 0x2a, 0x20, 0x7d, 0x12, 0xb, 0x14, 0x1b, 0x2a, 0x10,
+ 0x7e, 0xd, 0x39, 0x2d, 0x12, 0x39, 0x70, 0x0, 0x8, 0x7e, 0xd, 0x39, 0x69,
+ 0x50, 0x0, 0x4, 0x69, 0x20, 0x0, 0x6, 0xbd, 0x25, 0x50, 0x3, 0x2, 0x3, 0x33,
+ 0xb2, 0x1, 0x7a, 0xd, 0x33, 0x7e, 0x34, 0x0, 0x2, 0x2, 0x3, 0x25, 0x7c,
+ 0xb6, 0x1b, 0xb1, 0x68, 0x1d, 0x14, 0x68, 0x1d, 0xb, 0xb1, 0x68, 0x3, 0x2,
+ 0x3, 0x33, 0x30, 0x1, 0x6, 0x7e, 0x8, 0x0, 0x3e, 0x80, 0x4, 0x7e, 0x8, 0x1,
+ 0x4a, 0x7a, 0xd, 0x39, 0x2, 0x2, 0xd6, 0x2, 0x2, 0xe7, 0xa, 0x57, 0x6d,
+ 0x44, 0x7e, 0xd, 0x39, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12,
+ 0x79, 0x30, 0x0, 0x2, 0x1b, 0xa, 0x20, 0x7e, 0x1d, 0x39, 0x7a, 0x1d, 0x33,
+ 0xd2, 0x2, 0x7e, 0x34, 0x0, 0x1, 0x2, 0x3, 0x25, 0xbe, 0x60, 0x1, 0x68, 0x9,
+ 0xa5, 0xbe, 0x2, 0x5, 0x7a, 0x71, 0x3d, 0xd2, 0x3, 0xd2, 0x2, 0x22, 0x75,
+ 0xe6, 0x0, 0xe4, 0x7e, 0x34, 0x1, 0x4, 0x7e, 0x24, 0x0, 0xff, 0x7a, 0x1b,
+ 0xb0, 0x7e, 0x34, 0x1, 0x5, 0x7a, 0x1b, 0xb0, 0xd2, 0x4, 0x22, 0xa5, 0xbe,
+ 0x1, 0x4, 0x7a, 0x71, 0x37, 0x22, 0xa5, 0xbe, 0x2, 0x2, 0x80, 0x3, 0x2, 0x3,
+ 0x33, 0x7a, 0x71, 0x22, 0x22, 0x7a, 0x71, 0x32, 0x22, 0xd2, 0x2, 0x22, 0x1b,
+ 0x61, 0x68, 0x21, 0x1b, 0x60, 0x68, 0x24, 0x1b, 0x60, 0x68, 0x38, 0x1b,
+ 0x60, 0x68, 0x40, 0xb, 0x62, 0x78, 0x5d, 0xa, 0x37, 0x7d, 0x3, 0x6d, 0x11,
+ 0x7e, 0x1d, 0x39, 0x79, 0x11, 0x0, 0x2, 0x1b, 0x1a, 0x0, 0x22, 0xa, 0x57,
+ 0x7c, 0xab, 0xe4, 0x80, 0x2, 0xa, 0x57, 0x6d, 0x44, 0x7e, 0xd, 0x39, 0x69,
+ 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12, 0x79, 0x30, 0x0, 0x2, 0x1b, 0xa,
+ 0x20, 0x22, 0x7c, 0x67, 0x6c, 0x77, 0x7e, 0xd, 0x39, 0x79, 0x30, 0x0, 0x4,
+ 0x22, 0xa, 0x27, 0x7e, 0xd, 0x39, 0xb, 0x16, 0xb, 0xa, 0x30, 0x2d, 0x32,
+ 0x1b, 0xa, 0x30, 0x7e, 0x34, 0x0, 0x3, 0x7a, 0x35, 0x2e, 0x22, 0x7e, 0x34,
+ 0x0, 0x4, 0x7a, 0x35, 0x2e, 0x75, 0x16, 0x0, 0x22, 0xca, 0x3b, 0x7a, 0x15,
+ 0x8, 0x7f, 0x31, 0x7e, 0x35, 0x8, 0xbe, 0x34, 0x0, 0x0, 0x38, 0x4f, 0x7e,
+ 0x34, 0xff, 0xff, 0x7a, 0x35, 0x8, 0x75, 0xe, 0x1, 0x80, 0x43, 0x7e, 0x34,
+ 0x0, 0x80, 0x7a, 0x35, 0x11, 0x7f, 0x13, 0x7e, 0x8, 0x2, 0x56, 0x12, 0xc,
+ 0x1, 0x7e, 0x35, 0x8, 0x9e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0x8, 0x2e, 0x38,
+ 0x0, 0x80, 0x6d, 0x33, 0x7a, 0x35, 0xf, 0x7e, 0x35, 0xf, 0x9, 0x63, 0x2,
+ 0x56, 0x7e, 0xd, 0xa, 0x7e, 0xb, 0x70, 0x6c, 0x76, 0x7a, 0xb, 0x70, 0x7e,
+ 0x35, 0xf, 0xb, 0x34, 0x7a, 0x35, 0xf, 0xbe, 0x34, 0x0, 0x80, 0x78, 0xe0,
+ 0x7e, 0x35, 0x8, 0xbe, 0x34, 0x0, 0x80, 0x38, 0xb4, 0xe5, 0xe, 0x60, 0x5,
+ 0xb, 0x34, 0x7a, 0x35, 0x8, 0x7e, 0x35, 0x8, 0x7a, 0x35, 0x11, 0x7f, 0x13,
+ 0x7e, 0x8, 0x2, 0x56, 0x12, 0xc, 0x1, 0x6d, 0x33, 0x80, 0x17, 0x7e, 0x35,
+ 0xf, 0x9, 0x63, 0x2, 0x56, 0x7e, 0xd, 0xa, 0x7e, 0xb, 0x70, 0x6c, 0x76,
+ 0x7a, 0xb, 0x70, 0x7e, 0x35, 0xf, 0xb, 0x34, 0x7a, 0x35, 0xf, 0x7e, 0x35,
+ 0x8, 0xbe, 0x35, 0xf, 0x38, 0xde, 0xda, 0x3b, 0x22, 0x80, 0x18, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe5, 0x3d, 0x70, 0xa, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7d, 0x23, 0x1b, 0x34, 0x4d, 0x22,
+ 0x78, 0xe0, 0x22, 0x56, 0x30, 0x2e, 0x36, 0x4d, 0x61, 0x79, 0x20, 0x30,
+ 0x37, 0x20, 0x32, 0x30, 0x31, 0x35, 0x0, 0x46, 0x54, 0x53, 0x38, 0x36, 0x30,
+ 0x36, 0x5f, 0x70, 0x72, 0x61, 0x6d, 0x62, 0x6f, 0x6f, 0x74, 0x12, 0xb, 0xbd,
+ 0x2, 0x5, 0x66, 0x7e, 0x35, 0x2e, 0x1b, 0x34, 0x68, 0x57, 0x1b, 0x35, 0x78,
+ 0x3, 0x2, 0x4, 0xb3, 0x1b, 0x34, 0x78, 0x3, 0x2, 0x4, 0xdd, 0xb, 0x35, 0x68,
+ 0x3, 0x2, 0x5, 0x52, 0x6d, 0x33, 0x7a, 0x35, 0x2e, 0x7a, 0x35, 0x30, 0x30,
+ 0x5, 0x5, 0x12, 0xb, 0xf0, 0xc2, 0x5, 0x7e, 0xd, 0x33, 0x69, 0x30, 0x0, 0x4,
+ 0x7a, 0x35, 0xc, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2e, 0x14, 0x0, 0x8,
+ 0x12, 0x0, 0x46, 0xd2, 0x5, 0x7e, 0x2d, 0x33, 0x69, 0x12, 0x0, 0x4, 0x69,
+ 0x32, 0x0, 0x2, 0xb, 0x2a, 0x20, 0x12, 0x9, 0x48, 0x2e, 0x34, 0x10, 0x0,
+ 0x2, 0x5, 0x4f, 0x6d, 0x33, 0x7a, 0x35, 0x2e, 0x7e, 0x34, 0x1, 0x0, 0x7a,
+ 0x35, 0x11, 0x7e, 0xd, 0x33, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2e,
+ 0x14, 0x0, 0x8, 0x12, 0xc, 0x1, 0x20, 0x0, 0x3, 0x2, 0x5, 0x52, 0x7e, 0x1d,
+ 0x33, 0x29, 0xb1, 0x0, 0x8, 0xf5, 0x91, 0x2, 0x5, 0x52, 0x6d, 0x33, 0x7a,
+ 0x35, 0x2e, 0x7a, 0x35, 0x30, 0x7e, 0x18, 0x0, 0x16, 0x7a, 0x1d, 0xa, 0x7e,
+ 0xd, 0x33, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x69, 0x10, 0x0, 0x4, 0x12,
+ 0x3, 0x34, 0x12, 0xb, 0xf0, 0x7e, 0x34, 0xf0, 0x55, 0x2, 0x5, 0x4f, 0x6d,
+ 0x33, 0x7a, 0x35, 0x2e, 0x7a, 0x35, 0x30, 0xe5, 0x37, 0xb4, 0xa, 0x15, 0xe5,
+ 0x23, 0xb4, 0x80, 0xb, 0xe4, 0x12, 0xa, 0x32, 0x74, 0x1, 0x12, 0xa, 0x32,
+ 0x80, 0x4e, 0x12, 0x6, 0xd8, 0x80, 0x49, 0xe5, 0x37, 0xb4, 0xb, 0x27, 0xe5,
+ 0x23, 0xb4, 0x80, 0x11, 0x7e, 0xf0, 0x1, 0x7c, 0xbf, 0x12, 0x5, 0x6d, 0xb,
+ 0xf0, 0xbe, 0xf0, 0x11, 0x78, 0xf4, 0x80, 0x2e, 0x7e, 0xf0, 0x4, 0x7c, 0xbf,
+ 0x12, 0x5, 0x6d, 0xb, 0xf0, 0xbe, 0xf0, 0x40, 0x78, 0xf4, 0x80, 0x1d, 0xe5,
+ 0x37, 0xa, 0x3b, 0x9e, 0x34, 0x0, 0x80, 0x7c, 0xe7, 0x6c, 0xdd, 0x80, 0x9,
+ 0x7c, 0xbe, 0x12, 0x5, 0x6d, 0xb, 0xe0, 0xb, 0xd0, 0xe5, 0x22, 0xbc, 0xbd,
+ 0x38, 0xf1, 0x12, 0xb, 0xf0, 0x7e, 0x34, 0xf0, 0xaa, 0x7a, 0x35, 0x30, 0x30,
+ 0x4, 0x11, 0x7e, 0x34, 0x13, 0x88, 0x12, 0x3, 0xdd, 0x7e, 0x34, 0x13, 0x88,
+ 0x12, 0x3, 0xdd, 0x75, 0xe9, 0xff, 0x30, 0x6, 0x3, 0x2, 0x4, 0x26, 0x22,
+ 0xca, 0xf8, 0x7c, 0xfb, 0xe5, 0x23, 0xb4, 0x80, 0x4a, 0xd2, 0x7, 0x12, 0xb,
+ 0xdd, 0x74, 0x20, 0xca, 0xb8, 0xa, 0x3f, 0x6d, 0x22, 0x74, 0xc, 0x2f, 0x11,
+ 0x14, 0x78, 0xfb, 0xda, 0xb8, 0x12, 0xb, 0x44, 0xa9, 0xd2, 0xb4, 0x12, 0xc,
+ 0x41, 0x12, 0x0, 0x2e, 0x50, 0x9, 0x7e, 0x35, 0x17, 0xbe, 0x34, 0x1, 0xf4,
+ 0x28, 0xf2, 0x7e, 0x35, 0x17, 0xbe, 0x34, 0x1, 0xf4, 0x38, 0x6, 0x12, 0xc,
+ 0x5c, 0x2, 0x6, 0x3f, 0xc2, 0x86, 0x7e, 0x34, 0x13, 0x88, 0x12, 0x3, 0xdd,
+ 0xd2, 0x86, 0x2, 0x6, 0x3f, 0x74, 0x1, 0x12, 0x7, 0xd5, 0x74, 0x1, 0x6d,
+ 0x33, 0x12, 0x9, 0xe7, 0xe4, 0x12, 0x8, 0x3d, 0x5e, 0x34, 0x80, 0x0, 0x7c,
+ 0x4f, 0x6c, 0x55, 0x3e, 0x24, 0x4d, 0x32, 0x12, 0x9, 0xe7, 0x74, 0x4, 0x6d,
+ 0x33, 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0, 0x50, 0x12, 0x9, 0xe7, 0x7e, 0x34,
+ 0x0, 0x19, 0x12, 0x3, 0xdd, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x51, 0x12, 0x9,
+ 0xe7, 0x7e, 0x34, 0xa2, 0x1c, 0x12, 0x3, 0xdd, 0x74, 0x4, 0x7e, 0x34, 0x0,
+ 0x11, 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0, 0x19, 0x12, 0x3, 0xdd, 0x74, 0x4,
+ 0x7e, 0x34, 0x0, 0x10, 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0, 0x19, 0x12, 0x3,
+ 0xdd, 0x74, 0x4, 0x6d, 0x33, 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0, 0x5, 0x12,
+ 0x3, 0xdd, 0xe4, 0x12, 0x7, 0xd5, 0x74, 0x4, 0x7e, 0x34, 0xff, 0xf7, 0x12,
+ 0x9, 0xe7, 0xda, 0xf8, 0x22, 0xca, 0x3b, 0x7f, 0x30, 0x7c, 0xb6, 0xf5, 0x12,
+ 0x7c, 0xb7, 0xf5, 0x13, 0x74, 0x1, 0x7e, 0x35, 0x10, 0x1e, 0x34, 0x1b, 0x34,
+ 0x4e, 0x60, 0x80, 0x12, 0x9, 0xe7, 0x12, 0x7, 0xd5, 0xa9, 0xc2, 0xb4, 0xa9,
+ 0xc6, 0xb3, 0x75, 0xb5, 0x2, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75,
+ 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x85, 0x12, 0xb5, 0xa9,
+ 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x85, 0x13, 0xb5, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0x6d, 0x33, 0x80, 0x2a, 0x7f, 0x13, 0x2e, 0x35,
+ 0x14, 0x7e, 0x1b, 0xb0, 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0x7e, 0x35, 0x14, 0x5e, 0x34, 0x0, 0x1, 0xbe, 0x34, 0x0, 0x1, 0x78,
+ 0x7, 0x7e, 0x34, 0x0, 0x78, 0x12, 0x3, 0xdd, 0x7e, 0x35, 0x14, 0xb, 0x34,
+ 0x7a, 0x35, 0x14, 0x7e, 0x35, 0x10, 0xbe, 0x35, 0x14, 0x38, 0xcb, 0xa9,
+ 0xd2, 0xb4, 0x7e, 0x34, 0x0, 0x5, 0x12, 0x3, 0xdd, 0xe4, 0x12, 0x7, 0xd5,
+ 0xda, 0x3b, 0x22, 0xe5, 0x23, 0xb4, 0x80, 0x16, 0xd2, 0x7, 0x12, 0xb, 0xdd,
+ 0xa9, 0xc2, 0xb4, 0x74, 0x60, 0x12, 0xc, 0x36, 0xa9, 0xd2, 0xb4, 0x12, 0x0,
+ 0x2e, 0x40, 0xfb, 0x22, 0x74, 0x1, 0x12, 0x7, 0xd5, 0xe4, 0x6d, 0x33, 0x12,
+ 0x9, 0xe7, 0x74, 0x1, 0x6d, 0x33, 0x12, 0x9, 0xe7, 0x74, 0x4, 0x6d, 0x33,
+ 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0, 0x54, 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0,
+ 0x19, 0x12, 0x3, 0xdd, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x55, 0x12, 0x9, 0xe7,
+ 0x7e, 0x34, 0xa2, 0x1c, 0x12, 0x3, 0xdd, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x15,
+ 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0, 0xa0, 0x12, 0x3, 0xdd, 0x74, 0x4, 0x7e,
+ 0x34, 0x0, 0x14, 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0, 0x19, 0x12, 0x3, 0xdd,
+ 0x74, 0x4, 0x7e, 0x34, 0x0, 0x4, 0x12, 0x9, 0xe7, 0x7e, 0x34, 0x0, 0x5,
+ 0x12, 0x3, 0xdd, 0xe4, 0x12, 0x7, 0xd5, 0x74, 0x4, 0x7e, 0x34, 0xff, 0xf7,
+ 0x2, 0x9, 0xe7, 0x7c, 0x7b, 0x7e, 0xa0, 0xef, 0xe5, 0x21, 0x24, 0xfd, 0x68,
+ 0x38, 0x1b, 0xb1, 0x68, 0x22, 0x24, 0x9f, 0x68, 0x3d, 0x1b, 0xb2, 0x68,
+ 0x3e, 0x24, 0x9e, 0x68, 0x35, 0x24, 0x3c, 0x78, 0x4c, 0xa5, 0xbf, 0x0, 0x5,
+ 0x7e, 0xa0, 0x86, 0x80, 0x43, 0xa5, 0xbf, 0x1, 0x3f, 0x7e, 0xa0, 0xa6, 0x80,
+ 0x3a, 0xa5, 0xbf, 0x0, 0x5, 0x7e, 0xa1, 0x23, 0x80, 0x31, 0xa5, 0xbf, 0x1,
+ 0x2d, 0x7e, 0xa1, 0x3d, 0x80, 0x28, 0xa, 0x17, 0x7e, 0x1d, 0x39, 0x2d, 0x31,
+ 0x29, 0xa1, 0x0, 0x8, 0x80, 0x1b, 0x7e, 0xa1, 0x16, 0x80, 0x16, 0xa5, 0xbf,
+ 0x0, 0x9, 0x7e, 0x35, 0x30, 0xa, 0x56, 0x7c, 0xab, 0x80, 0x9, 0xa5, 0xbf,
+ 0x1, 0x5, 0x7e, 0x55, 0x30, 0x7c, 0xab, 0x7c, 0xba, 0x22, 0xca, 0x79, 0xbe,
+ 0xb0, 0x0, 0x28, 0x2e, 0x74, 0x6, 0x12, 0x8, 0x3d, 0x7d, 0x73, 0x6c, 0xff,
+ 0x7e, 0xf0, 0xa5, 0x7d, 0x37, 0x12, 0x9, 0xe7, 0x6c, 0xff, 0x7e, 0xf0, 0xf,
+ 0x7d, 0x37, 0x12, 0x9, 0xe7, 0x6c, 0xff, 0x7e, 0xf0, 0x6a, 0x7d, 0x37, 0x12,
+ 0x9, 0xe7, 0x7e, 0x34, 0x0, 0x5, 0x12, 0x3, 0xdd, 0x80, 0x30, 0x74, 0x1,
+ 0x7e, 0x34, 0xdf, 0xff, 0x12, 0x9, 0xe7, 0x74, 0x6, 0x12, 0x8, 0x3d, 0x7d,
+ 0x73, 0x6c, 0xff, 0x7d, 0x37, 0x12, 0x9, 0xe7, 0x7d, 0x37, 0x12, 0x9, 0xe7,
+ 0x7d, 0x37, 0x12, 0x9, 0xe7, 0x74, 0x2, 0x12, 0x8, 0x3d, 0x7d, 0x73, 0x4e,
+ 0xf0, 0x1, 0x7d, 0x37, 0x12, 0x9, 0xe7, 0xda, 0x79, 0x22, 0xa9, 0xc2, 0xb4,
+ 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3,
+ 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0,
+ 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xf5, 0xb5, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7e, 0x71,
+ 0xb5, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7e, 0xa1,
+ 0xb5, 0xa9, 0xd2, 0xb4, 0x7c, 0x47, 0x6c, 0x55, 0xa, 0x3a, 0x4d, 0x32, 0x22,
+ 0xca, 0xf8, 0x7e, 0xf0, 0x70, 0x75, 0x91, 0x0, 0xc2, 0x90, 0xc2, 0x91, 0x20,
+ 0x87, 0x3, 0x7e, 0xf1, 0xe4, 0x30, 0x6, 0x30, 0x7e, 0x34, 0x0, 0x2, 0x7a,
+ 0x35, 0x11, 0x7e, 0x18, 0x7, 0x80, 0x7e, 0x8, 0x0, 0x8, 0x12, 0xc, 0x1,
+ 0xe5, 0x8, 0xbe, 0xb0, 0xff, 0x68, 0x17, 0xe5, 0x8, 0x60, 0x13, 0xe5, 0x9,
+ 0xa, 0x2b, 0xe5, 0x8, 0xa, 0x3b, 0x2d, 0x32, 0xbe, 0x34, 0x0, 0xff, 0x78,
+ 0x3, 0x7e, 0xf1, 0x8, 0x5e, 0xf0, 0xfe, 0x7a, 0xf1, 0x92, 0xd2, 0xe8, 0xc2,
+ 0xc0, 0xa9, 0xd5, 0xb7, 0xd2, 0xbd, 0xd2, 0xad, 0xda, 0xf8, 0x22, 0x7f,
+ 0x70, 0xd2, 0x7, 0x12, 0xb, 0xdd, 0x74, 0x2, 0x12, 0xb, 0x44, 0x6d, 0x33,
+ 0x80, 0x12, 0x7f, 0x7, 0x2d, 0x13, 0x7e, 0xb, 0xb0, 0xf5, 0xb5, 0xa9, 0x36,
+ 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xb, 0x34, 0x7e, 0x25, 0x10, 0xbd, 0x23, 0x38,
+ 0xe7, 0xa9, 0xd2, 0xb4, 0x12, 0xc, 0x41, 0x12, 0x0, 0x2e, 0x50, 0x9, 0x7e,
+ 0x35, 0x17, 0xbe, 0x34, 0x1, 0xf4, 0x28, 0xf2, 0x7e, 0x35, 0x17, 0xbe, 0x34,
+ 0x1, 0xf4, 0x38, 0x3, 0x2, 0xc, 0x5c, 0xc2, 0x86, 0x7e, 0x34, 0x13, 0x88,
+ 0x12, 0x3, 0xdd, 0xd2, 0x86, 0x22, 0x6d, 0x0, 0x74, 0x10, 0x4d, 0x0, 0x78,
+ 0xb, 0x4d, 0x22, 0x78, 0x27, 0x8d, 0x31, 0x7d, 0x12, 0x6d, 0x22, 0x22, 0x7d,
+ 0x43, 0x7d, 0x32, 0x6d, 0x22, 0x2f, 0x11, 0x2d, 0x44, 0x50, 0x2, 0xa5, 0xf,
+ 0xbf, 0x10, 0x40, 0x4, 0x9f, 0x10, 0xb, 0x90, 0x14, 0x78, 0xed, 0x7f, 0x1,
+ 0x6d, 0x22, 0x7d, 0x34, 0x22, 0x7d, 0x41, 0x7d, 0x13, 0x8d, 0x24, 0x7d, 0x2,
+ 0x2f, 0x0, 0x40, 0x4, 0xbd, 0x4, 0x40, 0x4, 0x9d, 0x4, 0xb, 0x14, 0x14,
+ 0x78, 0xf1, 0x7d, 0x23, 0x7d, 0x31, 0x7d, 0x10, 0x6d, 0x0, 0x22, 0x75, 0x84,
+ 0x1, 0x7e, 0x44, 0x1f, 0xff, 0xe4, 0x7a, 0x49, 0xb0, 0x1b, 0x44, 0x78, 0xf9,
+ 0x7e, 0xf8, 0x2, 0xd5, 0xd2, 0x5, 0xc2, 0x6, 0x75, 0x16, 0x0, 0x75, 0x17,
+ 0x0, 0x75, 0x18, 0x0, 0xd2, 0x0, 0xc2, 0x2, 0xc2, 0x3, 0xc2, 0x4, 0x75,
+ 0x21, 0x0, 0x75, 0x22, 0x0, 0x75, 0x23, 0x80, 0x75, 0x2e, 0x0, 0x75, 0x2f,
+ 0x0, 0x75, 0x30, 0x0, 0x75, 0x31, 0x0, 0x75, 0x32, 0x0, 0x75, 0x37, 0xb,
+ 0x75, 0x38, 0x0, 0x75, 0x3d, 0x1, 0x2, 0x4, 0x20, 0x7d, 0x23, 0xa, 0x36,
+ 0x7c, 0xa5, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x1, 0xa9, 0x36,
+ 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9,
+ 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xf5,
+ 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7a, 0x71, 0xb5, 0xa9,
+ 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7a, 0xa1, 0xb5, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0xa9, 0xd2, 0xb4, 0x22, 0x7c, 0xab, 0xd2, 0x7, 0x12,
+ 0xb, 0xdd, 0x74, 0xd8, 0xa, 0x3a, 0x7d, 0x23, 0x6d, 0x33, 0x12, 0xb, 0x44,
+ 0xa9, 0xd2, 0xb4, 0x12, 0xc, 0x41, 0x12, 0x0, 0x2e, 0x50, 0x9, 0x7e, 0x35,
+ 0x17, 0xbe, 0x34, 0x5, 0xdc, 0x28, 0xf2, 0x7e, 0x35, 0x17, 0xbe, 0x34, 0x5,
+ 0xdc, 0x38, 0x3, 0x2, 0xc, 0x5c, 0xc2, 0x86, 0x7e, 0x34, 0x13, 0x88, 0x12,
+ 0x3, 0xdd, 0xd2, 0x86, 0x22, 0xca, 0x2b, 0xca, 0x1b, 0xca, 0xb, 0xd2, 0x0,
+ 0x30, 0x90, 0x1c, 0xc2, 0x90, 0x7e, 0x71, 0x91, 0xe5, 0x38, 0x70, 0x3, 0x7a,
+ 0x71, 0x21, 0xe5, 0x38, 0x12, 0x1, 0x20, 0x5, 0x38, 0x30, 0x2, 0x6, 0xe4,
+ 0x12, 0x7, 0x67, 0xf5, 0x91, 0x30, 0x91, 0xb, 0xc2, 0x91, 0x5, 0x38, 0xe5,
+ 0x38, 0x12, 0x7, 0x67, 0xf5, 0x91, 0xda, 0xb, 0xda, 0x1b, 0xda, 0x2b, 0x32,
+ 0xca, 0xf8, 0x7c, 0xfb, 0xe5, 0x23, 0xb4, 0x81, 0x23, 0x74, 0x2, 0x12, 0x8,
+ 0x3d, 0x4c, 0xff, 0x78, 0x8, 0xa9, 0xc0, 0xca, 0x5e, 0x70, 0xdf, 0x80, 0x6,
+ 0xa9, 0xd0, 0xca, 0x4e, 0x70, 0x20, 0x74, 0x2, 0x12, 0x9, 0xe7, 0x74, 0x2,
+ 0x12, 0x8, 0x3d, 0x80, 0x8, 0xe5, 0x23, 0xb4, 0x80, 0x3, 0x12, 0xb, 0x16,
+ 0xda, 0xf8, 0x22, 0xd2, 0x7, 0x12, 0xb, 0xdd, 0xa9, 0xc2, 0xb4, 0x74, 0x9f,
+ 0x12, 0xc, 0x36, 0x12, 0xc, 0x1d, 0xa9, 0xd2, 0xb4, 0x60, 0x3, 0xb4, 0xff,
+ 0x1a, 0x75, 0x23, 0x81, 0xa9, 0xd5, 0xca, 0xa9, 0xd0, 0xca, 0x75, 0xed,
+ 0x9f, 0x75, 0xad, 0x20, 0xa9, 0xd1, 0xea, 0xa9, 0xc1, 0xea, 0x74, 0x1, 0x2,
+ 0xa, 0xac, 0x22, 0xd2, 0x7, 0x12, 0xb, 0xdd, 0xa9, 0xc2, 0xb4, 0x74, 0x5,
+ 0x12, 0xc, 0x36, 0x12, 0xc, 0x1d, 0x7c, 0xab, 0xa9, 0xd2, 0xb4, 0x5e, 0xa0,
+ 0xe3, 0xa9, 0xc2, 0xb4, 0x74, 0x1, 0x12, 0xc, 0x36, 0x7c, 0xba, 0x12, 0xc,
+ 0x36, 0xa9, 0xd2, 0xb4, 0x12, 0x0, 0x2e, 0x40, 0xfb, 0x22, 0x7c, 0xab, 0x7d,
+ 0x12, 0x7c, 0xb3, 0xf5, 0x14, 0x7c, 0x36, 0x7c, 0x25, 0xa, 0x4, 0x7c, 0xb3,
+ 0xf5, 0x13, 0x7c, 0xb7, 0xf5, 0x12, 0xa9, 0xc2, 0xb4, 0x7c, 0xba, 0x12, 0xc,
+ 0x36, 0xe5, 0x14, 0x12, 0xc, 0x36, 0xe5, 0x13, 0x12, 0xc, 0x36, 0xe5, 0x12,
+ 0x2, 0xc, 0x36, 0x7d, 0x52, 0xf5, 0x15, 0x7c, 0xb6, 0x7c, 0xa5, 0xa, 0x44,
+ 0xf5, 0x14, 0x7f, 0x21, 0xf5, 0x13, 0xa9, 0xc2, 0xb4, 0x74, 0xb, 0x12, 0xc,
+ 0x36, 0xe5, 0x15, 0x12, 0xc, 0x36, 0xe5, 0x14, 0x12, 0xc, 0x36, 0xe5, 0x13,
+ 0x12, 0xc, 0x36, 0xe4, 0x2, 0xc, 0x36, 0xd2, 0xcf, 0x85, 0x3d, 0xcc, 0x75,
+ 0xec, 0xff, 0x75, 0xee, 0xff, 0x75, 0xeb, 0x3, 0x75, 0xac, 0x40, 0xa9, 0xc5,
+ 0xca, 0x75, 0xed, 0xf, 0x75, 0xad, 0xb0, 0xa9, 0xd7, 0x94, 0xa9, 0xd4, 0x94,
+ 0x22, 0x12, 0xb, 0x9c, 0xa9, 0xa6, 0x94, 0xb3, 0x92, 0x6, 0x30, 0x6, 0x6,
+ 0x12, 0xc, 0x2a, 0x12, 0xa, 0xe3, 0x12, 0x8, 0x9a, 0x12, 0xc, 0xf, 0xd2,
+ 0xaf, 0x30, 0x3, 0xfd, 0x2, 0xc, 0x54, 0xa9, 0xc2, 0xb4, 0x30, 0x7, 0x4,
+ 0x74, 0x6, 0x80, 0x2, 0x74, 0x4, 0x12, 0xc, 0x36, 0xa9, 0xd2, 0xb4, 0x22,
+ 0xe5, 0x32, 0xb4, 0xc, 0xb, 0xc2, 0x86, 0x7e, 0x34, 0x0, 0x64, 0x12, 0x3,
+ 0xdd, 0xd2, 0x86, 0x22, 0x12, 0xb, 0x71, 0x7e, 0x35, 0x11, 0x12, 0x0, 0xe,
+ 0xa9, 0xd2, 0xb4, 0xd3, 0x22, 0xc2, 0x8c, 0x43, 0x89, 0x2, 0x75, 0x8c, 0x1,
+ 0x75, 0x8a, 0x0, 0xd2, 0xa9, 0x22, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc,
+ 0xa9, 0xc6, 0xb3, 0xe5, 0xb5, 0x22, 0xd2, 0xc8, 0x75, 0xb3, 0x13, 0xa9,
+ 0xd1, 0xb4, 0xa9, 0xc0, 0xb4, 0x22, 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc,
+ 0xa9, 0xc6, 0xb3, 0xd3, 0x22, 0xc2, 0x8c, 0x6d, 0x33, 0x7a, 0x35, 0x17,
+ 0xd2, 0x8c, 0x22, 0x7e, 0x35, 0x17, 0xb, 0x34, 0x7a, 0x35, 0x17, 0x22, 0x85,
+ 0x3d, 0xcc, 0xe5, 0x3d, 0x2, 0xa, 0xac, 0x2, 0xc, 0x4b, 0xff,
diff --git a/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8607_Pramboot_V0.3_20160727.i b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8607_Pramboot_V0.3_20160727.i
new file mode 100644
index 000000000000..ebb31f1ebc7c
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8607_Pramboot_V0.3_20160727.i
@@ -0,0 +1,248 @@
+0x2, 0x9, 0xb2, 0xca, 0x39, 0x12, 0xc, 0x71, 0xda, 0x39, 0x32, 0x2, 0x0, 0x3,
+ 0x6d, 0x22, 0x80, 0x13, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0xe5, 0xb5, 0x7a, 0xb, 0xb0, 0xb, 0x14, 0xb, 0x24, 0xbd, 0x32, 0x38,
+ 0xe9, 0x22, 0xff, 0x2, 0xa, 0x87, 0xa9, 0xc2, 0xb4, 0x74, 0x5, 0x12, 0xc,
+ 0x5c, 0x12, 0xc, 0x43, 0xa9, 0xd2, 0xb4, 0x30, 0xe0, 0x2, 0xd3, 0x22, 0xc3,
+ 0x22, 0x2, 0x0, 0xf9, 0xca, 0x3b, 0x7a, 0xd, 0x8, 0x7f, 0x31, 0xe5, 0x23,
+ 0xb4, 0x80, 0x2, 0x80, 0x3, 0x2, 0x0, 0xdc, 0x7f, 0x13, 0x5e, 0x34, 0x0,
+ 0x7f, 0x7d, 0x23, 0x7e, 0x34, 0x0, 0x80, 0x9d, 0x32, 0x7a, 0x35, 0xe, 0x7e,
+ 0x35, 0xc, 0xbe, 0x35, 0xe, 0x38, 0x2, 0x80, 0x5d, 0x7e, 0x35, 0xe, 0x7a,
+ 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x9, 0xa, 0x7e, 0x35, 0xc,
+ 0x9e, 0x35, 0xe, 0x7a, 0x35, 0xc, 0x7e, 0x35, 0xe, 0x6d, 0x22, 0x2f, 0x31,
+ 0x7e, 0x1d, 0x8, 0x2e, 0x35, 0xe, 0x7a, 0x1d, 0x8, 0x80, 0x27, 0x7e, 0x34,
+ 0x0, 0x80, 0x7a, 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x9, 0xa,
+ 0x7e, 0x35, 0xc, 0x9e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0xc, 0x7e, 0x1d, 0x8,
+ 0x2e, 0x34, 0x0, 0x80, 0x7a, 0x1d, 0x8, 0x2e, 0x38, 0x0, 0x80, 0x7e, 0x35,
+ 0xc, 0xbe, 0x34, 0x0, 0x80, 0x50, 0xd0, 0x4d, 0x33, 0x68, 0x26, 0x7a, 0x35,
+ 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x9, 0xa, 0x80, 0x19, 0x74, 0x2,
+ 0x12, 0x8, 0xad, 0x5e, 0x70, 0xf4, 0x12, 0x9, 0xfe, 0x7e, 0x35, 0xc, 0x7a,
+ 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x6, 0x42, 0xd3, 0xda, 0x3b,
+ 0x22, 0xa9, 0xc0, 0x93, 0x75, 0x38, 0x0, 0x32, 0xc, 0x86, 0xf3, 0x79, 0x96,
+ 0x69, 0x34, 0xcb, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x7c, 0x6b, 0xc2, 0x2, 0xe5, 0x21, 0x14, 0x78, 0x3, 0x2, 0x2,
+ 0xcd, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0x30, 0x1b, 0xb1, 0x78, 0x3, 0x2,
+ 0x2, 0x7c, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0x8d, 0x1b, 0xb1, 0x78, 0x3,
+ 0x2, 0x2, 0xb4, 0x24, 0xf9, 0x78, 0x3, 0x2, 0x2, 0xc9, 0x24, 0xaf, 0x78,
+ 0x3, 0x2, 0x3, 0x37, 0x24, 0xfd, 0x68, 0x2d, 0x14, 0x78, 0x3, 0x2, 0x2,
+ 0xd0, 0x14, 0x78, 0x3, 0x2, 0x2, 0xcd, 0x1b, 0xb2, 0x78, 0x3, 0x2, 0x2,
+ 0xcd, 0x24, 0xda, 0x68, 0x19, 0x24, 0xe6, 0x68, 0x12, 0x24, 0xeb, 0x68,
+ 0x2e, 0x24, 0xf3, 0x78, 0x3, 0x2, 0x2, 0xcd, 0x24, 0x77, 0x68, 0x3, 0x2,
+ 0x3, 0x41, 0x2, 0x3, 0x3e, 0xbe, 0x60, 0x4, 0x50, 0xc, 0x75, 0x16, 0x0,
+ 0x7c, 0x16, 0x2e, 0x10, 0x24, 0x7c, 0xb7, 0xa5, 0xf7, 0xa5, 0xbe, 0x0, 0x2,
+ 0x80, 0x3, 0x2, 0x3, 0x41, 0xd2, 0x2, 0x22, 0x7c, 0xb6, 0x24, 0x0, 0x78,
+ 0x3, 0x2, 0x3, 0x41, 0x1b, 0xb1, 0x68, 0x1e, 0x14, 0x68, 0x1e, 0x14, 0x68,
+ 0x1e, 0x14, 0x68, 0x1e, 0xb, 0xb2, 0x78, 0x33, 0x30, 0x1, 0x7, 0x7e, 0x8,
+ 0x0, 0x3e, 0x2, 0x2, 0x4d, 0x7e, 0x8, 0x1, 0x4a, 0x2, 0x2, 0x4d, 0x2, 0x2,
+ 0xf5, 0x2, 0x2, 0xfc, 0x2, 0x3, 0x14, 0xa, 0x27, 0x7e, 0xd, 0x39, 0xb, 0x16,
+ 0xb, 0xa, 0x30, 0x2d, 0x32, 0x1b, 0xa, 0x30, 0x6d, 0x33, 0x7e, 0xd, 0x39,
+ 0x79, 0x30, 0x0, 0x6, 0x22, 0x7c, 0xb7, 0x62, 0x16, 0x7e, 0x2d, 0x39, 0x2e,
+ 0x54, 0x0, 0x6, 0xb, 0x2a, 0x20, 0x7d, 0x12, 0xb, 0x14, 0x1b, 0x2a, 0x10,
+ 0x7e, 0xd, 0x39, 0x2d, 0x12, 0x39, 0x70, 0x0, 0x8, 0x7e, 0xd, 0x39, 0x69,
+ 0x50, 0x0, 0x4, 0x69, 0x20, 0x0, 0x6, 0xbd, 0x25, 0x50, 0x3, 0x2, 0x3, 0x41,
+ 0xb2, 0x1, 0x7a, 0xd, 0x33, 0x7e, 0x34, 0x0, 0x2, 0x2, 0x3, 0x33, 0x7c,
+ 0xb6, 0x1b, 0xb1, 0x68, 0x1d, 0x14, 0x68, 0x1d, 0xb, 0xb1, 0x68, 0x3, 0x2,
+ 0x3, 0x41, 0x30, 0x1, 0x6, 0x7e, 0x8, 0x0, 0x3e, 0x80, 0x4, 0x7e, 0x8, 0x1,
+ 0x4a, 0x7a, 0xd, 0x39, 0x2, 0x2, 0xe4, 0x2, 0x2, 0xf5, 0xa, 0x57, 0x6d,
+ 0x44, 0x7e, 0xd, 0x39, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12,
+ 0x79, 0x30, 0x0, 0x2, 0x1b, 0xa, 0x20, 0x7e, 0x1d, 0x39, 0x7a, 0x1d, 0x33,
+ 0xd2, 0x2, 0x7e, 0x34, 0x0, 0x1, 0x2, 0x3, 0x33, 0xbe, 0x60, 0x1, 0x68, 0x9,
+ 0xa5, 0xbe, 0x2, 0x5, 0x7a, 0x71, 0x3d, 0xd2, 0x3, 0xd2, 0x2, 0x22, 0x75,
+ 0xe6, 0x0, 0xe4, 0x7e, 0x34, 0x1, 0x4, 0x7e, 0x24, 0x0, 0xff, 0x7a, 0x1b,
+ 0xb0, 0x7e, 0x34, 0x1, 0x5, 0x7a, 0x1b, 0xb0, 0x7e, 0x34, 0x1, 0x8, 0x7a,
+ 0x1b, 0xb0, 0x7e, 0x34, 0x1, 0x9, 0x7a, 0x1b, 0xb0, 0xd2, 0x4, 0x22, 0xa5,
+ 0xbe, 0x1, 0x4, 0x7a, 0x71, 0x37, 0x22, 0xa5, 0xbe, 0x2, 0x2, 0x80, 0x3,
+ 0x2, 0x3, 0x41, 0x7a, 0x71, 0x22, 0x22, 0x7a, 0x71, 0x32, 0x22, 0xd2, 0x2,
+ 0x22, 0x1b, 0x61, 0x68, 0x21, 0x1b, 0x60, 0x68, 0x24, 0x1b, 0x60, 0x68,
+ 0x38, 0x1b, 0x60, 0x68, 0x40, 0xb, 0x62, 0x78, 0x5d, 0xa, 0x37, 0x7d, 0x3,
+ 0x6d, 0x11, 0x7e, 0x1d, 0x39, 0x79, 0x11, 0x0, 0x2, 0x1b, 0x1a, 0x0, 0x22,
+ 0xa, 0x57, 0x7c, 0xab, 0xe4, 0x80, 0x2, 0xa, 0x57, 0x6d, 0x44, 0x7e, 0xd,
+ 0x39, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12, 0x79, 0x30, 0x0,
+ 0x2, 0x1b, 0xa, 0x20, 0x22, 0x7c, 0x67, 0x6c, 0x77, 0x7e, 0xd, 0x39, 0x79,
+ 0x30, 0x0, 0x4, 0x22, 0xa, 0x27, 0x7e, 0xd, 0x39, 0xb, 0x16, 0xb, 0xa, 0x30,
+ 0x2d, 0x32, 0x1b, 0xa, 0x30, 0x7e, 0x34, 0x0, 0x3, 0x7a, 0x35, 0x2e, 0x22,
+ 0x7e, 0x34, 0x0, 0x4, 0x7a, 0x35, 0x2e, 0x75, 0x16, 0x0, 0x22, 0xca, 0x3b,
+ 0x7a, 0x15, 0x8, 0x7f, 0x31, 0x75, 0xe, 0x0, 0x7e, 0x35, 0x8, 0xbe, 0x34,
+ 0x0, 0x0, 0x38, 0x4f, 0x7e, 0x34, 0xff, 0xff, 0x7a, 0x35, 0x8, 0x75, 0xe,
+ 0x1, 0x80, 0x43, 0x7e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0x11, 0x7f, 0x13, 0x7e,
+ 0x8, 0x2, 0x56, 0x12, 0xc, 0x27, 0x7e, 0x35, 0x8, 0x9e, 0x34, 0x0, 0x80,
+ 0x7a, 0x35, 0x8, 0x2e, 0x38, 0x0, 0x80, 0x6d, 0x33, 0x7a, 0x35, 0xf, 0x7e,
+ 0x35, 0xf, 0x9, 0x63, 0x2, 0x56, 0x7e, 0xd, 0xa, 0x7e, 0xb, 0x70, 0x6c,
+ 0x76, 0x7a, 0xb, 0x70, 0x7e, 0x35, 0xf, 0xb, 0x34, 0x7a, 0x35, 0xf, 0xbe,
+ 0x34, 0x0, 0x80, 0x78, 0xe0, 0x7e, 0x35, 0x8, 0xbe, 0x34, 0x0, 0x80, 0x38,
+ 0xb4, 0xe5, 0xe, 0x60, 0x5, 0xb, 0x34, 0x7a, 0x35, 0x8, 0x7e, 0x35, 0x8,
+ 0x7a, 0x35, 0x11, 0x7f, 0x13, 0x7e, 0x8, 0x2, 0x56, 0x12, 0xc, 0x27, 0x6d,
+ 0x33, 0x80, 0x17, 0x7e, 0x35, 0xf, 0x9, 0x63, 0x2, 0x56, 0x7e, 0xd, 0xa,
+ 0x7e, 0xb, 0x70, 0x6c, 0x76, 0x7a, 0xb, 0x70, 0x7e, 0x35, 0xf, 0xb, 0x34,
+ 0x7a, 0x35, 0xf, 0x7e, 0x35, 0x8, 0xbe, 0x35, 0xf, 0x38, 0xde, 0xda, 0x3b,
+ 0x22, 0xe5, 0x32, 0xb4, 0xc, 0xb, 0xc2, 0x86, 0x7e, 0x34, 0x0, 0x64, 0x12,
+ 0xb, 0xb0, 0xd2, 0x86, 0x22, 0xff, 0x56, 0x30, 0x2e, 0x33, 0x4a, 0x75, 0x6c,
+ 0x20, 0x32, 0x37, 0x20, 0x32, 0x30, 0x31, 0x36, 0x0, 0x46, 0x54, 0x53, 0x38,
+ 0x36, 0x30, 0x37, 0x5f, 0x70, 0x72, 0x61, 0x6d, 0x62, 0x6f, 0x6f, 0x74,
+ 0x12, 0xb, 0xf4, 0x2, 0x5, 0x66, 0x7e, 0x35, 0x2e, 0x1b, 0x34, 0x68, 0x57,
+ 0x1b, 0x35, 0x78, 0x3, 0x2, 0x4, 0xb3, 0x1b, 0x34, 0x78, 0x3, 0x2, 0x4,
+ 0xdd, 0xb, 0x35, 0x68, 0x3, 0x2, 0x5, 0x52, 0x6d, 0x33, 0x7a, 0x35, 0x2e,
+ 0x7a, 0x35, 0x30, 0x30, 0x5, 0x5, 0x12, 0x3, 0xee, 0xc2, 0x5, 0x7e, 0xd,
+ 0x33, 0x69, 0x30, 0x0, 0x4, 0x7a, 0x35, 0xc, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa,
+ 0x20, 0x2e, 0x14, 0x0, 0x8, 0x12, 0x0, 0x46, 0xd2, 0x5, 0x7e, 0x2d, 0x33,
+ 0x69, 0x12, 0x0, 0x4, 0x69, 0x32, 0x0, 0x2, 0xb, 0x2a, 0x20, 0x12, 0x9,
+ 0x5f, 0x2e, 0x34, 0x10, 0x0, 0x2, 0x5, 0x4f, 0x6d, 0x33, 0x7a, 0x35, 0x2e,
+ 0x7e, 0x34, 0x1, 0x0, 0x7a, 0x35, 0x11, 0x7e, 0xd, 0x33, 0x69, 0x30, 0x0,
+ 0x2, 0xb, 0xa, 0x20, 0x2e, 0x14, 0x0, 0x8, 0x12, 0xc, 0x27, 0x20, 0x0, 0x3,
+ 0x2, 0x5, 0x52, 0x7e, 0x1d, 0x33, 0x29, 0xb1, 0x0, 0x8, 0xf5, 0x91, 0x2,
+ 0x5, 0x52, 0x6d, 0x33, 0x7a, 0x35, 0x2e, 0x7a, 0x35, 0x30, 0x7e, 0x18, 0x0,
+ 0x16, 0x7a, 0x1d, 0xa, 0x7e, 0xd, 0x33, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa,
+ 0x20, 0x69, 0x10, 0x0, 0x4, 0x12, 0x3, 0x42, 0x12, 0x3, 0xee, 0x7e, 0x34,
+ 0xf0, 0x55, 0x2, 0x5, 0x4f, 0x6d, 0x33, 0x7a, 0x35, 0x2e, 0x7a, 0x35, 0x30,
+ 0xe5, 0x37, 0xb4, 0xa, 0x15, 0xe5, 0x23, 0xb4, 0x80, 0xb, 0xe4, 0x12, 0xa,
+ 0x49, 0x74, 0x1, 0x12, 0xa, 0x49, 0x80, 0x4e, 0x12, 0x6, 0xd8, 0x80, 0x49,
+ 0xe5, 0x37, 0xb4, 0xb, 0x27, 0xe5, 0x23, 0xb4, 0x80, 0x11, 0x7e, 0xf0, 0x1,
+ 0x7c, 0xbf, 0x12, 0x5, 0x6d, 0xb, 0xf0, 0xbe, 0xf0, 0x11, 0x78, 0xf4, 0x80,
+ 0x2e, 0x7e, 0xf0, 0x4, 0x7c, 0xbf, 0x12, 0x5, 0x6d, 0xb, 0xf0, 0xbe, 0xf0,
+ 0x40, 0x78, 0xf4, 0x80, 0x1d, 0xe5, 0x37, 0xa, 0x3b, 0x9e, 0x34, 0x0, 0x80,
+ 0x7c, 0xe7, 0x6c, 0xdd, 0x80, 0x9, 0x7c, 0xbe, 0x12, 0x5, 0x6d, 0xb, 0xe0,
+ 0xb, 0xd0, 0xe5, 0x22, 0xbc, 0xbd, 0x38, 0xf1, 0x12, 0x3, 0xee, 0x7e, 0x34,
+ 0xf0, 0xaa, 0x7a, 0x35, 0x30, 0x30, 0x4, 0x11, 0x7e, 0x34, 0x13, 0x88, 0x12,
+ 0xb, 0xb0, 0x7e, 0x34, 0x13, 0x88, 0x12, 0xb, 0xb0, 0x75, 0xe9, 0xff, 0x30,
+ 0x6, 0x3, 0x2, 0x4, 0x26, 0x22, 0xca, 0xf8, 0x7c, 0xfb, 0xe5, 0x23, 0xb4,
+ 0x80, 0x4a, 0xd2, 0x7, 0x12, 0xc, 0x14, 0x74, 0x20, 0xca, 0xb8, 0xa, 0x3f,
+ 0x6d, 0x22, 0x74, 0xc, 0x2f, 0x11, 0x14, 0x78, 0xfb, 0xda, 0xb8, 0x12, 0xb,
+ 0x2b, 0xa9, 0xd2, 0xb4, 0x12, 0xc, 0x67, 0x12, 0x0, 0x2e, 0x50, 0x9, 0x7e,
+ 0x35, 0x17, 0xbe, 0x34, 0x1, 0xf4, 0x28, 0xf2, 0x7e, 0x35, 0x17, 0xbe, 0x34,
+ 0x1, 0xf4, 0x38, 0x6, 0x12, 0xc, 0x82, 0x2, 0x6, 0x3f, 0xc2, 0x86, 0x7e,
+ 0x34, 0x13, 0x88, 0x12, 0xb, 0xb0, 0xd2, 0x86, 0x2, 0x6, 0x3f, 0x74, 0x1,
+ 0x12, 0x8, 0x45, 0x74, 0x1, 0x6d, 0x33, 0x12, 0x9, 0xfe, 0xe4, 0x12, 0x8,
+ 0xad, 0x5e, 0x34, 0x80, 0x0, 0x7c, 0x4f, 0x6c, 0x55, 0x3e, 0x24, 0x4d, 0x32,
+ 0x12, 0x9, 0xfe, 0x74, 0x4, 0x6d, 0x33, 0x12, 0x9, 0xfe, 0x7e, 0x34, 0x0,
+ 0x50, 0x12, 0x9, 0xfe, 0x7e, 0x34, 0x0, 0x19, 0x12, 0xb, 0xb0, 0x74, 0x4,
+ 0x7e, 0x34, 0x0, 0x51, 0x12, 0x9, 0xfe, 0x7e, 0x34, 0xa2, 0x1c, 0x12, 0xb,
+ 0xb0, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x11, 0x12, 0x9, 0xfe, 0x7e, 0x34, 0x0,
+ 0x19, 0x12, 0xb, 0xb0, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x10, 0x12, 0x9, 0xfe,
+ 0x7e, 0x34, 0x0, 0x19, 0x12, 0xb, 0xb0, 0x74, 0x4, 0x6d, 0x33, 0x12, 0x9,
+ 0xfe, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xb, 0xb0, 0xe4, 0x12, 0x8, 0x45, 0x74,
+ 0x4, 0x7e, 0x34, 0xff, 0xf7, 0x12, 0x9, 0xfe, 0xda, 0xf8, 0x22, 0xca, 0x3b,
+ 0x7f, 0x30, 0x7c, 0xb6, 0xf5, 0x12, 0x7c, 0xb7, 0xf5, 0x13, 0x74, 0x1, 0x7e,
+ 0x35, 0x10, 0x1e, 0x34, 0x1b, 0x34, 0x4e, 0x60, 0x80, 0x12, 0x9, 0xfe, 0x12,
+ 0x8, 0x45, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x2, 0xa9, 0x36,
+ 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9,
+ 0xc6, 0xb3, 0x85, 0x12, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3,
+ 0x85, 0x13, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x6d, 0x33,
+ 0x80, 0x2a, 0x7f, 0x13, 0x2e, 0x35, 0x14, 0x7e, 0x1b, 0xb0, 0xf5, 0xb5,
+ 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7e, 0x35, 0x14, 0x5e, 0x34, 0x0,
+ 0x1, 0xbe, 0x34, 0x0, 0x1, 0x78, 0x7, 0x7e, 0x34, 0x0, 0x78, 0x12, 0xb,
+ 0xb0, 0x7e, 0x35, 0x14, 0xb, 0x34, 0x7a, 0x35, 0x14, 0x7e, 0x35, 0x10, 0xbe,
+ 0x35, 0x14, 0x38, 0xcb, 0xa9, 0xd2, 0xb4, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xb,
+ 0xb0, 0xe4, 0x12, 0x8, 0x45, 0xda, 0x3b, 0x22, 0xe5, 0x23, 0xb4, 0x80, 0x16,
+ 0xd2, 0x7, 0x12, 0xc, 0x14, 0xa9, 0xc2, 0xb4, 0x74, 0x60, 0x12, 0xc, 0x5c,
+ 0xa9, 0xd2, 0xb4, 0x12, 0x0, 0x2e, 0x40, 0xfb, 0x22, 0x74, 0x1, 0x12, 0x8,
+ 0x45, 0xe4, 0x6d, 0x33, 0x12, 0x9, 0xfe, 0x74, 0x1, 0x6d, 0x33, 0x12, 0x9,
+ 0xfe, 0x74, 0x4, 0x6d, 0x33, 0x12, 0x9, 0xfe, 0x7e, 0x34, 0x0, 0x54, 0x12,
+ 0x9, 0xfe, 0x7e, 0x34, 0x0, 0x19, 0x12, 0xb, 0xb0, 0x74, 0x4, 0x7e, 0x34,
+ 0x0, 0x55, 0x12, 0x9, 0xfe, 0x7e, 0x34, 0xa2, 0x1c, 0x12, 0xb, 0xb0, 0x74,
+ 0x4, 0x7e, 0x34, 0x0, 0x15, 0x12, 0x9, 0xfe, 0x7e, 0x34, 0x0, 0xa0, 0x12,
+ 0xb, 0xb0, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x14, 0x12, 0x9, 0xfe, 0x7e, 0x34,
+ 0x0, 0x19, 0x12, 0xb, 0xb0, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x4, 0x12, 0x9,
+ 0xfe, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xb, 0xb0, 0xe4, 0x12, 0x8, 0x45, 0x74,
+ 0x4, 0x7e, 0x34, 0xff, 0xf7, 0x2, 0x9, 0xfe, 0xca, 0xf8, 0xc2, 0x7, 0x7e,
+ 0xf0, 0x70, 0x75, 0x91, 0x0, 0xc2, 0x90, 0xc2, 0x91, 0x20, 0x7, 0x10, 0x7e,
+ 0xf1, 0xe4, 0xbe, 0xf0, 0x2, 0x40, 0x5, 0xbe, 0xf0, 0xfd, 0x28, 0x3, 0x7e,
+ 0xf0, 0x70, 0x30, 0x6, 0x38, 0x7e, 0x34, 0x0, 0x2, 0x7a, 0x35, 0x11, 0x7e,
+ 0x18, 0x7, 0x80, 0x7e, 0x8, 0x0, 0x8, 0x12, 0xc, 0x27, 0xe5, 0x8, 0xbe,
+ 0xb0, 0xff, 0x68, 0x19, 0xe5, 0x8, 0x60, 0x15, 0xe5, 0x9, 0xa, 0x2b, 0xe5,
+ 0x8, 0xa, 0x3b, 0x2d, 0x32, 0xbe, 0x34, 0x0, 0xff, 0x78, 0x5, 0x7e, 0xf1,
+ 0x8, 0xd2, 0x7, 0x20, 0x7, 0x3, 0x7e, 0xf0, 0x70, 0x5e, 0xf0, 0xfe, 0x7a,
+ 0xf1, 0x92, 0xd2, 0xe8, 0xc2, 0xc0, 0xa9, 0xd5, 0xb7, 0xd2, 0xbd, 0xd2,
+ 0xad, 0xda, 0xf8, 0x22, 0x7c, 0x7b, 0x7e, 0xa0, 0xef, 0xe5, 0x21, 0x24,
+ 0xfd, 0x68, 0x38, 0x1b, 0xb1, 0x68, 0x22, 0x24, 0x9f, 0x68, 0x3d, 0x1b,
+ 0xb2, 0x68, 0x3e, 0x24, 0x9e, 0x68, 0x35, 0x24, 0x3c, 0x78, 0x4c, 0xa5,
+ 0xbf, 0x0, 0x5, 0x7e, 0xa0, 0x86, 0x80, 0x43, 0xa5, 0xbf, 0x1, 0x3f, 0x7e,
+ 0xa0, 0xa7, 0x80, 0x3a, 0xa5, 0xbf, 0x0, 0x5, 0x7e, 0xa1, 0x23, 0x80, 0x31,
+ 0xa5, 0xbf, 0x1, 0x2d, 0x7e, 0xa1, 0x3d, 0x80, 0x28, 0xa, 0x17, 0x7e, 0x1d,
+ 0x39, 0x2d, 0x31, 0x29, 0xa1, 0x0, 0x8, 0x80, 0x1b, 0x7e, 0xa1, 0x16, 0x80,
+ 0x16, 0xa5, 0xbf, 0x0, 0x9, 0x7e, 0x35, 0x30, 0xa, 0x56, 0x7c, 0xab, 0x80,
+ 0x9, 0xa5, 0xbf, 0x1, 0x5, 0x7e, 0x55, 0x30, 0x7c, 0xab, 0x7c, 0xba, 0x22,
+ 0xca, 0x79, 0xbe, 0xb0, 0x0, 0x28, 0x2e, 0x74, 0x6, 0x12, 0x8, 0xad, 0x7d,
+ 0x73, 0x6c, 0xff, 0x7e, 0xf0, 0xa5, 0x7d, 0x37, 0x12, 0x9, 0xfe, 0x6c, 0xff,
+ 0x7e, 0xf0, 0xf, 0x7d, 0x37, 0x12, 0x9, 0xfe, 0x6c, 0xff, 0x7e, 0xf0, 0x6a,
+ 0x7d, 0x37, 0x12, 0x9, 0xfe, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xb, 0xb0, 0x80,
+ 0x30, 0x74, 0x1, 0x7e, 0x34, 0xdf, 0xff, 0x12, 0x9, 0xfe, 0x74, 0x6, 0x12,
+ 0x8, 0xad, 0x7d, 0x73, 0x6c, 0xff, 0x7d, 0x37, 0x12, 0x9, 0xfe, 0x7d, 0x37,
+ 0x12, 0x9, 0xfe, 0x7d, 0x37, 0x12, 0x9, 0xfe, 0x74, 0x2, 0x12, 0x8, 0xad,
+ 0x7d, 0x73, 0x4e, 0xf0, 0x1, 0x7d, 0x37, 0x12, 0x9, 0xfe, 0xda, 0x79, 0x22,
+ 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x5, 0xa9, 0x36, 0xb3, 0xfc,
+ 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3,
+ 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xf5, 0xb5, 0xa9,
+ 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc,
+ 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3,
+ 0x7e, 0x71, 0xb5, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3,
+ 0x7e, 0xa1, 0xb5, 0xa9, 0xd2, 0xb4, 0x7c, 0x47, 0x6c, 0x55, 0xa, 0x3a, 0x4d,
+ 0x32, 0x22, 0x7f, 0x70, 0xd2, 0x7, 0x12, 0xc, 0x14, 0x74, 0x2, 0x12, 0xb,
+ 0x2b, 0x6d, 0x33, 0x80, 0x12, 0x7f, 0x7, 0x2d, 0x13, 0x7e, 0xb, 0xb0, 0xf5,
+ 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xb, 0x34, 0x7e, 0x25, 0x10,
+ 0xbd, 0x23, 0x38, 0xe7, 0xa9, 0xd2, 0xb4, 0x12, 0xc, 0x67, 0x12, 0x0, 0x2e,
+ 0x50, 0x9, 0x7e, 0x35, 0x17, 0xbe, 0x34, 0x1, 0xf4, 0x28, 0xf2, 0x7e, 0x35,
+ 0x17, 0xbe, 0x34, 0x1, 0xf4, 0x38, 0x3, 0x2, 0xc, 0x82, 0xc2, 0x86, 0x7e,
+ 0x34, 0x13, 0x88, 0x12, 0xb, 0xb0, 0xd2, 0x86, 0x22, 0x6d, 0x0, 0x74, 0x10,
+ 0x4d, 0x0, 0x78, 0xb, 0x4d, 0x22, 0x78, 0x27, 0x8d, 0x31, 0x7d, 0x12, 0x6d,
+ 0x22, 0x22, 0x7d, 0x43, 0x7d, 0x32, 0x6d, 0x22, 0x2f, 0x11, 0x2d, 0x44,
+ 0x50, 0x2, 0xa5, 0xf, 0xbf, 0x10, 0x40, 0x4, 0x9f, 0x10, 0xb, 0x90, 0x14,
+ 0x78, 0xed, 0x7f, 0x1, 0x6d, 0x22, 0x7d, 0x34, 0x22, 0x7d, 0x41, 0x7d, 0x13,
+ 0x8d, 0x24, 0x7d, 0x2, 0x2f, 0x0, 0x40, 0x4, 0xbd, 0x4, 0x40, 0x4, 0x9d,
+ 0x4, 0xb, 0x14, 0x14, 0x78, 0xf1, 0x7d, 0x23, 0x7d, 0x31, 0x7d, 0x10, 0x6d,
+ 0x0, 0x22, 0x75, 0x84, 0x1, 0x7e, 0x44, 0x1f, 0xff, 0xe4, 0x7a, 0x49, 0xb0,
+ 0x1b, 0x44, 0x78, 0xf9, 0x7e, 0xf8, 0x2, 0xd5, 0xd2, 0x5, 0xc2, 0x6, 0x75,
+ 0x16, 0x0, 0x75, 0x17, 0x0, 0x75, 0x18, 0x0, 0xd2, 0x0, 0xc2, 0x2, 0xc2,
+ 0x3, 0xc2, 0x4, 0x75, 0x21, 0x0, 0x75, 0x22, 0x0, 0x75, 0x23, 0x80, 0x75,
+ 0x2e, 0x0, 0x75, 0x2f, 0x0, 0x75, 0x30, 0x0, 0x75, 0x31, 0x0, 0x75, 0x32,
+ 0x0, 0x75, 0x37, 0xb, 0x75, 0x38, 0x0, 0x75, 0x3d, 0x1, 0x2, 0x4, 0x20,
+ 0x7d, 0x23, 0xa, 0x36, 0x7c, 0xa5, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75,
+ 0xb5, 0x1, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9,
+ 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc,
+ 0xa9, 0xc6, 0xb3, 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3,
+ 0x7a, 0x71, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7a, 0xa1,
+ 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xa9, 0xd2, 0xb4, 0x22,
+ 0x7c, 0xab, 0xd2, 0x7, 0x12, 0xc, 0x14, 0x74, 0xd8, 0xa, 0x3a, 0x7d, 0x23,
+ 0x6d, 0x33, 0x12, 0xb, 0x2b, 0xa9, 0xd2, 0xb4, 0x12, 0xc, 0x67, 0x12, 0x0,
+ 0x2e, 0x50, 0x9, 0x7e, 0x35, 0x17, 0xbe, 0x34, 0x5, 0xdc, 0x28, 0xf2, 0x7e,
+ 0x35, 0x17, 0xbe, 0x34, 0x5, 0xdc, 0x38, 0x3, 0x2, 0xc, 0x82, 0xc2, 0x86,
+ 0x7e, 0x34, 0x13, 0x88, 0x12, 0xb, 0xb0, 0xd2, 0x86, 0x22, 0xca, 0x2b, 0xca,
+ 0x1b, 0xca, 0xb, 0xd2, 0x0, 0x30, 0x90, 0x1c, 0xc2, 0x90, 0x7e, 0x71, 0x91,
+ 0xe5, 0x38, 0x70, 0x3, 0x7a, 0x71, 0x21, 0xe5, 0x38, 0x12, 0x1, 0x20, 0x5,
+ 0x38, 0x30, 0x2, 0x6, 0xe4, 0x12, 0x7, 0xd7, 0xf5, 0x91, 0x30, 0x91, 0xb,
+ 0xc2, 0x91, 0x5, 0x38, 0xe5, 0x38, 0x12, 0x7, 0xd7, 0xf5, 0x91, 0xda, 0xb,
+ 0xda, 0x1b, 0xda, 0x2b, 0x32, 0xd2, 0x7, 0x12, 0xc, 0x14, 0xa9, 0xc2, 0xb4,
+ 0x74, 0x9f, 0x12, 0xc, 0x5c, 0x12, 0xc, 0x43, 0xa9, 0xd2, 0xb4, 0x60, 0x3,
+ 0xb4, 0xff, 0x1a, 0x75, 0x23, 0x81, 0xa9, 0xd5, 0xca, 0xa9, 0xd0, 0xca,
+ 0x75, 0xed, 0x9f, 0x75, 0xad, 0x20, 0xa9, 0xd1, 0xea, 0xa9, 0xc1, 0xea,
+ 0x74, 0x1, 0x2, 0xb, 0x58, 0x2, 0xa, 0xf8, 0xd2, 0x7, 0x12, 0xc, 0x14, 0xa9,
+ 0xc2, 0xb4, 0x74, 0x5, 0x12, 0xc, 0x5c, 0x12, 0xc, 0x43, 0x7c, 0xab, 0xa9,
+ 0xd2, 0xb4, 0xd2, 0x7, 0x12, 0xc, 0x14, 0x5e, 0xa0, 0xe3, 0xa9, 0xc2, 0xb4,
+ 0x74, 0x1, 0x12, 0xc, 0x5c, 0x7c, 0xba, 0x12, 0xc, 0x5c, 0xa9, 0xd2, 0xb4,
+ 0x12, 0x0, 0x2e, 0x40, 0xfb, 0x22, 0x7c, 0xab, 0x7d, 0x12, 0x7c, 0xb3, 0xf5,
+ 0x14, 0x7c, 0x36, 0x7c, 0x25, 0xa, 0x4, 0x7c, 0xb3, 0xf5, 0x13, 0x7c, 0xb7,
+ 0xf5, 0x12, 0xa9, 0xc2, 0xb4, 0x7c, 0xba, 0x12, 0xc, 0x5c, 0xe5, 0x14, 0x12,
+ 0xc, 0x5c, 0xe5, 0x13, 0x12, 0xc, 0x5c, 0xe5, 0x12, 0x2, 0xc, 0x5c, 0xca,
+ 0xf8, 0x7c, 0xfb, 0xe5, 0x23, 0xb4, 0x81, 0x21, 0x74, 0x2, 0x12, 0x8, 0xad,
+ 0x4c, 0xff, 0x78, 0x8, 0xa9, 0xc0, 0xca, 0x5e, 0x70, 0xdf, 0x80, 0x6, 0xa9,
+ 0xd0, 0xca, 0x4e, 0x70, 0x20, 0x74, 0x2, 0x12, 0x9, 0xfe, 0x74, 0x2, 0x12,
+ 0x8, 0xad, 0xda, 0xf8, 0x22, 0x7d, 0x52, 0xf5, 0x15, 0x7c, 0xb6, 0x7c, 0xa5,
+ 0xa, 0x44, 0xf5, 0x14, 0x7f, 0x21, 0xf5, 0x13, 0xa9, 0xc2, 0xb4, 0x74, 0xb,
+ 0x12, 0xc, 0x5c, 0xe5, 0x15, 0x12, 0xc, 0x5c, 0xe5, 0x14, 0x12, 0xc, 0x5c,
+ 0xe5, 0x13, 0x12, 0xc, 0x5c, 0xe4, 0x2, 0xc, 0x5c, 0x80, 0x18, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe5, 0x3d, 0x70, 0xa, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7d, 0x23, 0x1b, 0x34, 0x4d, 0x22,
+ 0x78, 0xe0, 0x22, 0xd2, 0xcf, 0x85, 0x3d, 0xcc, 0x75, 0xec, 0xff, 0x75,
+ 0xee, 0xff, 0x75, 0xeb, 0x3, 0x75, 0xac, 0x40, 0xa9, 0xc5, 0xca, 0x75, 0xed,
+ 0xf, 0x75, 0xad, 0xb0, 0xa9, 0xd7, 0x94, 0xa9, 0xd4, 0x94, 0x22, 0x12, 0xb,
+ 0xd3, 0xa9, 0xa6, 0x94, 0xb3, 0x92, 0x6, 0x30, 0x6, 0x6, 0x12, 0xc, 0x50,
+ 0x12, 0xa, 0xc3, 0x12, 0x7, 0x67, 0x12, 0xc, 0x35, 0xd2, 0xaf, 0x30, 0x3,
+ 0xfd, 0x2, 0xc, 0x7a, 0xa9, 0xc2, 0xb4, 0x30, 0x7, 0x4, 0x74, 0x6, 0x80,
+ 0x2, 0x74, 0x4, 0x12, 0xc, 0x5c, 0xa9, 0xd2, 0xb4, 0x22, 0x12, 0xb, 0x85,
+ 0x7e, 0x35, 0x11, 0x12, 0x0, 0xe, 0xa9, 0xd2, 0xb4, 0xd3, 0x22, 0xc2, 0x8c,
+ 0x43, 0x89, 0x2, 0x75, 0x8c, 0x1, 0x75, 0x8a, 0x0, 0xd2, 0xa9, 0x22, 0x75,
+ 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xe5, 0xb5, 0x22, 0xd2,
+ 0xc8, 0x75, 0xb3, 0x13, 0xa9, 0xd1, 0xb4, 0xa9, 0xc0, 0xb4, 0x22, 0xf5,
+ 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xd3, 0x22, 0xc2, 0x8c,
+ 0x6d, 0x33, 0x7a, 0x35, 0x17, 0xd2, 0x8c, 0x22, 0x7e, 0x35, 0x17, 0xb, 0x34,
+ 0x7a, 0x35, 0x17, 0x22, 0x85, 0x3d, 0xcc, 0xe5, 0x3d, 0x2, 0xb, 0x58, 0x2,
+ 0xc, 0x71, 0xff,
diff --git a/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8716_Pramboot_V0.5_20160723.i b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8716_Pramboot_V0.5_20160723.i
new file mode 100644
index 000000000000..805c8bfaf191
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8716_Pramboot_V0.5_20160723.i
@@ -0,0 +1,303 @@
+0x2, 0x3, 0x83, 0xca, 0x39, 0x12, 0xf, 0x3c, 0xda, 0x39, 0x32, 0x2, 0x0, 0x3,
+ 0x6d, 0x22, 0x80, 0x13, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0xe5, 0xb5, 0x7a, 0xb, 0xb0, 0xb, 0x14, 0xb, 0x24, 0xbd, 0x32, 0x38,
+ 0xe9, 0x22, 0xff, 0x2, 0xd, 0xf, 0xe5, 0x33, 0xb4, 0xc, 0xf, 0xc2, 0x86,
+ 0xc2, 0x87, 0x7e, 0x34, 0x0, 0x64, 0x12, 0xe, 0x86, 0xd2, 0x86, 0xd2, 0x87,
+ 0x22, 0x2, 0x0, 0xf9, 0xca, 0x3b, 0x7a, 0xd, 0x10, 0x7f, 0x31, 0xe5, 0x24,
+ 0xb4, 0x80, 0x2, 0x80, 0x3, 0x2, 0x0, 0xdc, 0x7f, 0x13, 0x5e, 0x34, 0x0,
+ 0x7f, 0x7d, 0x23, 0x7e, 0x34, 0x0, 0x80, 0x9d, 0x32, 0x7a, 0x35, 0x16, 0x7e,
+ 0x35, 0x14, 0xbe, 0x35, 0x16, 0x38, 0x2, 0x80, 0x5d, 0x7e, 0x35, 0x16, 0x7a,
+ 0x35, 0x18, 0x7f, 0x13, 0x7e, 0xd, 0x10, 0x12, 0xa, 0xe6, 0x7e, 0x35, 0x14,
+ 0x9e, 0x35, 0x16, 0x7a, 0x35, 0x14, 0x7e, 0x35, 0x16, 0x6d, 0x22, 0x2f,
+ 0x31, 0x7e, 0x1d, 0x10, 0x2e, 0x35, 0x16, 0x7a, 0x1d, 0x10, 0x80, 0x27,
+ 0x7e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0x18, 0x7f, 0x13, 0x7e, 0xd, 0x10, 0x12,
+ 0xa, 0xe6, 0x7e, 0x35, 0x14, 0x9e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0x14, 0x7e,
+ 0x1d, 0x10, 0x2e, 0x34, 0x0, 0x80, 0x7a, 0x1d, 0x10, 0x2e, 0x38, 0x0, 0x80,
+ 0x7e, 0x35, 0x14, 0xbe, 0x34, 0x0, 0x80, 0x50, 0xd0, 0x4d, 0x33, 0x68, 0x26,
+ 0x7a, 0x35, 0x18, 0x7f, 0x13, 0x7e, 0xd, 0x10, 0x12, 0xa, 0xe6, 0x80, 0x19,
+ 0x74, 0x2, 0x12, 0xa, 0x89, 0x5e, 0x70, 0xf4, 0x12, 0xc, 0x86, 0x7e, 0x35,
+ 0x14, 0x7a, 0x35, 0x18, 0x7f, 0x13, 0x7e, 0xd, 0x10, 0x12, 0x8, 0xe, 0xd3,
+ 0xda, 0x3b, 0x22, 0xa9, 0xc0, 0x93, 0x75, 0x39, 0x0, 0x32, 0xf, 0x60, 0xf0,
+ 0x9f, 0x4c, 0xf1, 0xb3, 0xe, 0xce, 0xb9, 0x31, 0x46, 0xff, 0x0, 0xff, 0x0,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x7c, 0x6b, 0xc2, 0x2, 0xe5, 0x22, 0x14, 0x78, 0x3,
+ 0x2, 0x2, 0xda, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0x3d, 0x1b, 0xb1, 0x78,
+ 0x3, 0x2, 0x2, 0x89, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0x9a, 0x1b, 0xb1,
+ 0x78, 0x3, 0x2, 0x2, 0xc1, 0x24, 0xf9, 0x78, 0x3, 0x2, 0x2, 0xd6, 0x24,
+ 0xaf, 0x78, 0x3, 0x2, 0x3, 0x3b, 0x24, 0xfd, 0x68, 0x3a, 0x14, 0x78, 0x3,
+ 0x2, 0x2, 0xdd, 0x14, 0x78, 0x3, 0x2, 0x2, 0xda, 0x1b, 0xb2, 0x78, 0x3, 0x2,
+ 0x2, 0xda, 0x24, 0xda, 0x68, 0x26, 0x24, 0xe6, 0x68, 0x1f, 0x24, 0xeb, 0x68,
+ 0x3b, 0x24, 0xf3, 0x78, 0x3, 0x2, 0x2, 0xda, 0x24, 0xe4, 0x78, 0x3, 0x2,
+ 0x3, 0x46, 0x14, 0x78, 0x3, 0x2, 0x2, 0xda, 0x24, 0x94, 0x68, 0x3, 0x2, 0x3,
+ 0x82, 0x2, 0x3, 0x42, 0xbe, 0x60, 0x4, 0x50, 0xc, 0x75, 0x3f, 0x0, 0x7c,
+ 0x16, 0x2e, 0x10, 0x25, 0x7c, 0xb7, 0xa5, 0xf7, 0xa5, 0xbe, 0x0, 0x2, 0x80,
+ 0x3, 0x2, 0x3, 0x82, 0xd2, 0x2, 0x22, 0x7c, 0xb6, 0x24, 0x0, 0x78, 0x3, 0x2,
+ 0x3, 0x82, 0x1b, 0xb1, 0x68, 0x1e, 0x14, 0x68, 0x1e, 0x14, 0x68, 0x1e, 0x14,
+ 0x68, 0x1e, 0xb, 0xb2, 0x78, 0x33, 0x30, 0x1, 0x7, 0x7e, 0x8, 0x0, 0x44,
+ 0x2, 0x2, 0x5a, 0x7e, 0x8, 0x1, 0x50, 0x2, 0x2, 0x5a, 0x2, 0x2, 0xfb, 0x2,
+ 0x3, 0x2, 0x2, 0x3, 0x1a, 0xa, 0x27, 0x7e, 0xd, 0x3a, 0xb, 0x16, 0xb, 0xa,
+ 0x30, 0x2d, 0x32, 0x1b, 0xa, 0x30, 0x6d, 0x33, 0x7e, 0xd, 0x3a, 0x79, 0x30,
+ 0x0, 0x6, 0x22, 0x7c, 0xb7, 0x62, 0x3f, 0x7e, 0x2d, 0x3a, 0x2e, 0x54, 0x0,
+ 0x6, 0xb, 0x2a, 0x20, 0x7d, 0x12, 0xb, 0x14, 0x1b, 0x2a, 0x10, 0x7e, 0xd,
+ 0x3a, 0x2d, 0x12, 0x39, 0x70, 0x0, 0x8, 0x7e, 0xd, 0x3a, 0x69, 0x50, 0x0,
+ 0x4, 0x69, 0x20, 0x0, 0x6, 0xbd, 0x25, 0x50, 0x3, 0x2, 0x3, 0x82, 0xb2, 0x1,
+ 0x7a, 0xd, 0x34, 0x7e, 0x34, 0x0, 0x2, 0x2, 0x3, 0x7f, 0x7c, 0xb6, 0x1b,
+ 0xb1, 0x68, 0x1d, 0x14, 0x68, 0x1d, 0xb, 0xb1, 0x68, 0x3, 0x2, 0x3, 0x82,
+ 0x30, 0x1, 0x6, 0x7e, 0x8, 0x0, 0x44, 0x80, 0x4, 0x7e, 0x8, 0x1, 0x50, 0x7a,
+ 0xd, 0x3a, 0x2, 0x2, 0xf3, 0x2, 0x2, 0xfb, 0xa, 0x57, 0x6d, 0x44, 0x7e, 0xd,
+ 0x3a, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12, 0x79, 0x30, 0x0,
+ 0x2, 0x1b, 0xa, 0x20, 0x7e, 0x1d, 0x3a, 0x7a, 0x1d, 0x34, 0xd2, 0x2, 0x7e,
+ 0x34, 0x0, 0x1, 0x2, 0x3, 0x7f, 0xbe, 0x60, 0x1, 0x68, 0x9, 0xa5, 0xbe, 0x2,
+ 0x5, 0x7a, 0x71, 0x3e, 0xd2, 0x3, 0xd2, 0x2, 0x22, 0x75, 0xe6, 0x0, 0xe4,
+ 0x7e, 0x34, 0x1, 0x4, 0x7e, 0x24, 0x0, 0xff, 0x7a, 0x1b, 0xb0, 0x7e, 0x34,
+ 0x1, 0x5, 0x7a, 0x1b, 0xb0, 0x7e, 0x34, 0x1, 0x8, 0x7a, 0x1b, 0xb0, 0x7e,
+ 0x34, 0x1, 0x9, 0x7a, 0x1b, 0xb0, 0xd2, 0x4, 0x22, 0xa5, 0xbe, 0x1, 0x4,
+ 0x7a, 0x71, 0x38, 0x22, 0xa5, 0xbe, 0x2, 0x2, 0x80, 0x3, 0x2, 0x3, 0x82,
+ 0x7a, 0x71, 0x23, 0x22, 0x7a, 0x71, 0x33, 0x22, 0xd2, 0x2, 0x22, 0x7c, 0xb6,
+ 0x1b, 0xb1, 0x68, 0x18, 0x14, 0x68, 0x1c, 0x14, 0x68, 0x31, 0x14, 0x68,
+ 0x3a, 0xb, 0xb2, 0x68, 0x3, 0x2, 0x3, 0x82, 0xa, 0x37, 0x7d, 0x3, 0x6d,
+ 0x11, 0x80, 0x59, 0xa, 0x57, 0x7c, 0xab, 0xe4, 0x80, 0x2, 0xa, 0x57, 0x6d,
+ 0x44, 0x7e, 0xd, 0x3a, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12,
+ 0x79, 0x30, 0x0, 0x2, 0x1b, 0xa, 0x20, 0x22, 0x7c, 0x67, 0x6c, 0x77, 0x7e,
+ 0xd, 0x3a, 0x79, 0x30, 0x0, 0x4, 0x22, 0xa, 0x27, 0x7e, 0xd, 0x3a, 0xb,
+ 0x16, 0xb, 0xa, 0x30, 0x2d, 0x32, 0x1b, 0xa, 0x30, 0x7e, 0x34, 0x0, 0x3,
+ 0x80, 0x44, 0x7e, 0x34, 0x0, 0x4, 0x7a, 0x35, 0x2f, 0x75, 0x3f, 0x0, 0x22,
+ 0x1b, 0x61, 0x68, 0x15, 0xb, 0x60, 0x78, 0x34, 0x7c, 0x27, 0x6c, 0x33, 0x6d,
+ 0x0, 0x7e, 0x1d, 0x3a, 0x79, 0x11, 0x0, 0x2, 0x1b, 0x1a, 0x0, 0x22, 0xa,
+ 0x57, 0x6d, 0x44, 0x7e, 0xd, 0x3a, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20,
+ 0x2f, 0x12, 0x79, 0x30, 0x0, 0x2, 0x1b, 0xa, 0x20, 0xe4, 0x7a, 0xb3, 0x2,
+ 0xe4, 0x7e, 0x34, 0x0, 0x5, 0x7a, 0x35, 0x2f, 0x22, 0x75, 0x84, 0x1, 0x7e,
+ 0x44, 0x1f, 0xff, 0xe4, 0x7a, 0x49, 0xb0, 0x1b, 0x44, 0x78, 0xf9, 0x7e,
+ 0xf8, 0x2, 0xe8, 0xd2, 0x7, 0xc2, 0x8, 0x75, 0x3f, 0x0, 0x75, 0x40, 0x87,
+ 0x75, 0x41, 0xa6, 0x75, 0x42, 0x0, 0x75, 0x43, 0x0, 0xd2, 0x0, 0xc2, 0x2,
+ 0xc2, 0x3, 0xc2, 0x4, 0x75, 0x22, 0x0, 0x75, 0x23, 0x0, 0x75, 0x24, 0x80,
+ 0x75, 0x2f, 0x0, 0x75, 0x30, 0x0, 0x75, 0x31, 0x0, 0x75, 0x32, 0x0, 0x75,
+ 0x33, 0x0, 0x75, 0x38, 0xb, 0x75, 0x39, 0x0, 0x75, 0x3e, 0x1, 0x7e, 0x4,
+ 0x0, 0xff, 0x7e, 0x14, 0xf, 0x50, 0xb, 0xa, 0x40, 0x5d, 0x44, 0x68, 0x1a,
+ 0x69, 0x20, 0x0, 0x2, 0xb, 0xe, 0xb, 0x44, 0x80, 0xa, 0x7e, 0xb, 0xb0, 0x7a,
+ 0x29, 0xb0, 0xb, 0x24, 0xb, 0xc, 0x1b, 0x44, 0x78, 0xf2, 0x80, 0xdf, 0x2,
+ 0x4, 0x20, 0xff, 0xff, 0x56, 0x30, 0x2e, 0x35, 0x4a, 0x75, 0x6c, 0x20, 0x32,
+ 0x33, 0x20, 0x32, 0x30, 0x31, 0x36, 0x0, 0x46, 0x54, 0x53, 0x38, 0x37, 0x31,
+ 0x36, 0x5f, 0x70, 0x72, 0x61, 0x6d, 0x62, 0x6f, 0x6f, 0x74, 0x12, 0xe, 0x63,
+ 0x2, 0x5, 0xbc, 0x7e, 0x35, 0x2f, 0x1b, 0x34, 0x68, 0x60, 0x1b, 0x35, 0x78,
+ 0x3, 0x2, 0x4, 0xbc, 0x1b, 0x34, 0x78, 0x3, 0x2, 0x4, 0xe6, 0x1b, 0x34,
+ 0x78, 0x3, 0x2, 0x5, 0x96, 0x2e, 0x34, 0x0, 0x3, 0x68, 0x3, 0x2, 0x5, 0xa8,
+ 0x6d, 0x33, 0x7a, 0x35, 0x2f, 0x7a, 0x35, 0x31, 0x30, 0x7, 0x5, 0x12, 0x0,
+ 0x2e, 0xc2, 0x7, 0x7e, 0xd, 0x34, 0x69, 0x30, 0x0, 0x4, 0x7a, 0x35, 0x14,
+ 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2e, 0x14, 0x0, 0x8, 0x12, 0x0, 0x46,
+ 0xd2, 0x7, 0x7e, 0x2d, 0x34, 0x69, 0x12, 0x0, 0x4, 0x69, 0x32, 0x0, 0x2,
+ 0xb, 0x2a, 0x20, 0x12, 0xb, 0xe2, 0x2e, 0x34, 0x10, 0x0, 0x2, 0x5, 0x91,
+ 0x6d, 0x33, 0x7a, 0x35, 0x2f, 0x7e, 0x34, 0x1, 0x0, 0x7a, 0x35, 0x15, 0x7e,
+ 0xd, 0x34, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2e, 0x14, 0x0, 0x8, 0x12,
+ 0xe, 0xf2, 0x20, 0x0, 0x3, 0x2, 0x5, 0xa8, 0x7e, 0x1d, 0x34, 0x29, 0xb1,
+ 0x0, 0x8, 0xf5, 0x91, 0x2, 0x5, 0xa8, 0x6d, 0x33, 0x7a, 0x35, 0x2f, 0x7a,
+ 0x35, 0x31, 0x7e, 0x18, 0x0, 0x3f, 0x7a, 0x1d, 0xe, 0x7e, 0xd, 0x34, 0x69,
+ 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x69, 0x10, 0x0, 0x4, 0x12, 0x7, 0x62, 0x12,
+ 0x0, 0x2e, 0x7e, 0x34, 0xf0, 0x55, 0x2, 0x5, 0x91, 0x7e, 0x18, 0x10, 0x0,
+ 0x7a, 0x1d, 0x8, 0xd2, 0x5, 0x6d, 0x33, 0x7a, 0x35, 0x2f, 0x7a, 0x35, 0x31,
+ 0xe5, 0x38, 0xb4, 0xa, 0x17, 0xe5, 0x24, 0xb4, 0x80, 0xc, 0xe4, 0x12, 0xc,
+ 0xd1, 0x74, 0x1, 0x12, 0xc, 0xd1, 0x2, 0x5, 0x7f, 0x12, 0x8, 0xa4, 0x2, 0x5,
+ 0x7f, 0xe5, 0x38, 0xb4, 0xb, 0x27, 0xe5, 0x24, 0xb4, 0x80, 0x11, 0x7e, 0xf0,
+ 0x1, 0x7c, 0xbf, 0x12, 0x5, 0xc3, 0xb, 0xf0, 0xbe, 0xf0, 0x11, 0x78, 0xf4,
+ 0x80, 0x51, 0x7e, 0xf0, 0x4, 0x7c, 0xbf, 0x12, 0x5, 0xc3, 0xb, 0xf0, 0xbe,
+ 0xf0, 0x40, 0x78, 0xf4, 0x80, 0x40, 0xe5, 0x38, 0xa, 0x3b, 0x9e, 0x34, 0x0,
+ 0x80, 0x7c, 0xe7, 0xe5, 0x24, 0xb4, 0x80, 0x10, 0xa, 0x3e, 0x6d, 0x22, 0x74,
+ 0xc, 0x2f, 0x11, 0x14, 0x78, 0xfb, 0x7a, 0x1d, 0x8, 0x80, 0xe, 0xa, 0x3e,
+ 0x6d, 0x22, 0x74, 0xa, 0x2f, 0x11, 0x14, 0x78, 0xfb, 0x7a, 0x1d, 0x8, 0x6c,
+ 0xdd, 0x80, 0x9, 0x7c, 0xbe, 0x12, 0x5, 0xc3, 0xb, 0xe0, 0xb, 0xd0, 0xe5,
+ 0x23, 0xbc, 0xbd, 0x38, 0xf1, 0x7e, 0x1d, 0x8, 0x12, 0xe, 0xd, 0x92, 0x5,
+ 0x12, 0x0, 0x2e, 0x30, 0x5, 0x1b, 0x7e, 0x34, 0xf0, 0xaa, 0x7a, 0x35, 0x31,
+ 0x80, 0x12, 0x6d, 0x33, 0x7a, 0x35, 0x2f, 0x7a, 0x35, 0x31, 0x7e, 0xd, 0x34,
+ 0x69, 0x30, 0x0, 0x2, 0x12, 0x6, 0x98, 0x30, 0x4, 0x11, 0x7e, 0x34, 0x13,
+ 0x88, 0x12, 0xe, 0x86, 0x7e, 0x34, 0x13, 0x88, 0x12, 0xe, 0x86, 0x75, 0xe9,
+ 0xff, 0x30, 0x8, 0x3, 0x2, 0x4, 0x26, 0x22, 0xca, 0xf8, 0x7c, 0xfb, 0xe5,
+ 0x24, 0xb4, 0x80, 0x4a, 0xd2, 0x6, 0x12, 0xe, 0xdf, 0x74, 0x20, 0xca, 0xb8,
+ 0xa, 0x3f, 0x6d, 0x22, 0x74, 0xc, 0x2f, 0x11, 0x14, 0x78, 0xfb, 0xda, 0xb8,
+ 0x12, 0xd, 0xb3, 0xa9, 0xd2, 0xb4, 0x12, 0xf, 0x32, 0x12, 0xe, 0xca, 0x50,
+ 0x9, 0x7e, 0x35, 0x42, 0xbe, 0x34, 0x1, 0xf4, 0x28, 0xf2, 0x7e, 0x35, 0x42,
+ 0xbe, 0x34, 0x1, 0xf4, 0x38, 0x6, 0x12, 0xf, 0x4d, 0x2, 0x6, 0x95, 0xc2,
+ 0x86, 0x7e, 0x34, 0x13, 0x88, 0x12, 0xe, 0x86, 0xd2, 0x86, 0x2, 0x6, 0x95,
+ 0x74, 0x1, 0x12, 0xa, 0x21, 0x74, 0x1, 0x6d, 0x33, 0x12, 0xc, 0x86, 0xe4,
+ 0x12, 0xa, 0x89, 0x5e, 0x34, 0x80, 0x0, 0x7c, 0x4f, 0x6c, 0x55, 0x3e, 0x24,
+ 0x4d, 0x32, 0x12, 0xc, 0x86, 0x74, 0x4, 0x6d, 0x33, 0x12, 0xc, 0x86, 0x7e,
+ 0x34, 0x0, 0x50, 0x12, 0xc, 0x86, 0x7e, 0x34, 0x0, 0x19, 0x12, 0xe, 0x86,
+ 0x74, 0x4, 0x7e, 0x34, 0x0, 0x51, 0x12, 0xc, 0x86, 0x7e, 0x34, 0xa2, 0x1c,
+ 0x12, 0xe, 0x86, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x11, 0x12, 0xc, 0x86, 0x7e,
+ 0x34, 0x0, 0x19, 0x12, 0xe, 0x86, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x10, 0x12,
+ 0xc, 0x86, 0x7e, 0x34, 0x0, 0x19, 0x12, 0xe, 0x86, 0x74, 0x4, 0x6d, 0x33,
+ 0x12, 0xc, 0x86, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xe, 0x86, 0xe4, 0x12, 0xa,
+ 0x21, 0x74, 0x4, 0x7e, 0x34, 0xff, 0xf7, 0x12, 0xc, 0x86, 0xda, 0xf8, 0x22,
+ 0xca, 0xf8, 0xe4, 0x7a, 0xb3, 0x2, 0xe4, 0xe5, 0x24, 0xbe, 0xb0, 0x80, 0x68,
+ 0x9, 0x74, 0x1, 0x7a, 0xb3, 0x2, 0xe4, 0x2, 0x7, 0x5f, 0xbe, 0x34, 0xff,
+ 0xff, 0x68, 0x6, 0xbe, 0x34, 0x0, 0x12, 0x50, 0x4, 0x7e, 0x34, 0x0, 0x12,
+ 0x7d, 0x13, 0x6d, 0x0, 0x74, 0xc, 0x2f, 0x0, 0x14, 0x78, 0xfb, 0x7a, 0xd,
+ 0xc, 0x7c, 0xb7, 0x12, 0x5, 0xc3, 0x7e, 0x1d, 0xc, 0x12, 0xe, 0xd, 0xe4,
+ 0x33, 0x7c, 0xfb, 0xbe, 0xf0, 0x1, 0x78, 0xa, 0x7e, 0xb3, 0x2, 0xe4, 0x44,
+ 0x2, 0x7a, 0xb3, 0x2, 0xe4, 0x6c, 0xaa, 0xa, 0x3a, 0x19, 0xa3, 0x2, 0xdc,
+ 0xb, 0xa0, 0xbe, 0xa0, 0x8, 0x78, 0xf3, 0x7e, 0x34, 0x0, 0x8, 0x7a, 0x35,
+ 0x14, 0x7e, 0x1d, 0xc, 0x7e, 0x8, 0x2, 0xdc, 0x12, 0x0, 0x46, 0x6c, 0xaa,
+ 0xe4, 0xa, 0x4a, 0x19, 0xb4, 0x2, 0xdc, 0xb, 0xa0, 0xbe, 0xa0, 0x8, 0x78,
+ 0xf3, 0x7e, 0x34, 0x0, 0x8, 0x7a, 0x35, 0x15, 0x7e, 0x1d, 0xc, 0x7e, 0x8,
+ 0x2, 0xdc, 0x12, 0xe, 0xf2, 0x7e, 0xf0, 0x1, 0x6c, 0xaa, 0xa, 0x3a, 0x9,
+ 0xb3, 0x2, 0xdc, 0xbc, 0xba, 0x68, 0x4, 0x6c, 0xff, 0x80, 0x7, 0xb, 0xa0,
+ 0xbe, 0xa0, 0x8, 0x40, 0xeb, 0xbe, 0xf0, 0x1, 0x78, 0xa, 0x7e, 0xb3, 0x2,
+ 0xe4, 0x44, 0x4, 0x7a, 0xb3, 0x2, 0xe4, 0x7e, 0xb3, 0x2, 0xe4, 0x44, 0x1,
+ 0x7a, 0xb3, 0x2, 0xe4, 0xda, 0xf8, 0x22, 0xca, 0x3b, 0x7a, 0x15, 0xc, 0x7f,
+ 0x31, 0x75, 0x12, 0x0, 0x7e, 0x35, 0xc, 0xbe, 0x34, 0x0, 0x0, 0x38, 0x4f,
+ 0x7e, 0x34, 0xff, 0xff, 0x7a, 0x35, 0xc, 0x75, 0x12, 0x1, 0x80, 0x43, 0x7e,
+ 0x34, 0x0, 0x80, 0x7a, 0x35, 0x15, 0x7f, 0x13, 0x7e, 0x8, 0x2, 0x5c, 0x12,
+ 0xe, 0xf2, 0x7e, 0x35, 0xc, 0x9e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0xc, 0x2e,
+ 0x38, 0x0, 0x80, 0x6d, 0x33, 0x7a, 0x35, 0x13, 0x7e, 0x35, 0x13, 0x9, 0x63,
+ 0x2, 0x5c, 0x7e, 0xd, 0xe, 0x7e, 0xb, 0x70, 0x6c, 0x76, 0x7a, 0xb, 0x70,
+ 0x7e, 0x35, 0x13, 0xb, 0x34, 0x7a, 0x35, 0x13, 0xbe, 0x34, 0x0, 0x80, 0x78,
+ 0xe0, 0x7e, 0x35, 0xc, 0xbe, 0x34, 0x0, 0x80, 0x38, 0xb4, 0xe5, 0x12, 0x60,
+ 0x5, 0xb, 0x34, 0x7a, 0x35, 0xc, 0x7e, 0x35, 0xc, 0x7a, 0x35, 0x15, 0x7f,
+ 0x13, 0x7e, 0x8, 0x2, 0x5c, 0x12, 0xe, 0xf2, 0x6d, 0x33, 0x80, 0x17, 0x7e,
+ 0x35, 0x13, 0x9, 0x63, 0x2, 0x5c, 0x7e, 0xd, 0xe, 0x7e, 0xb, 0x70, 0x6c,
+ 0x76, 0x7a, 0xb, 0x70, 0x7e, 0x35, 0x13, 0xb, 0x34, 0x7a, 0x35, 0x13, 0x7e,
+ 0x35, 0xc, 0xbe, 0x35, 0x13, 0x38, 0xde, 0xda, 0x3b, 0x22, 0xca, 0x3b, 0x7f,
+ 0x30, 0x7c, 0xb6, 0xf5, 0x1a, 0x7c, 0xb7, 0xf5, 0x1b, 0x74, 0x1, 0x7e, 0x35,
+ 0x18, 0x1e, 0x34, 0x1b, 0x34, 0x4e, 0x60, 0x80, 0x12, 0xc, 0x86, 0x12, 0xa,
+ 0x21, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x2, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0x85, 0x1a, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x85,
+ 0x1b, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x6d, 0x33, 0x80,
+ 0x2a, 0x7f, 0x13, 0x2e, 0x35, 0x1c, 0x7e, 0x1b, 0xb0, 0xf5, 0xb5, 0xa9,
+ 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7e, 0x35, 0x1c, 0x5e, 0x34, 0x0, 0x1,
+ 0xbe, 0x34, 0x0, 0x1, 0x78, 0x7, 0x7e, 0x34, 0x0, 0x78, 0x12, 0xe, 0x86,
+ 0x7e, 0x35, 0x1c, 0xb, 0x34, 0x7a, 0x35, 0x1c, 0x7e, 0x35, 0x18, 0xbe, 0x35,
+ 0x1c, 0x38, 0xcb, 0xa9, 0xd2, 0xb4, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xe, 0x86,
+ 0xe4, 0x12, 0xa, 0x21, 0xda, 0x3b, 0x22, 0xe5, 0x24, 0xb4, 0x80, 0x16, 0xd2,
+ 0x6, 0x12, 0xe, 0xdf, 0xa9, 0xc2, 0xb4, 0x74, 0x60, 0x12, 0xf, 0x27, 0xa9,
+ 0xd2, 0xb4, 0x12, 0xe, 0xca, 0x40, 0xfb, 0x22, 0x74, 0x1, 0x12, 0xa, 0x21,
+ 0xe4, 0x6d, 0x33, 0x12, 0xc, 0x86, 0x74, 0x1, 0x6d, 0x33, 0x12, 0xc, 0x86,
+ 0x74, 0x4, 0x6d, 0x33, 0x12, 0xc, 0x86, 0x7e, 0x34, 0x0, 0x54, 0x12, 0xc,
+ 0x86, 0x7e, 0x34, 0x0, 0x19, 0x12, 0xe, 0x86, 0x74, 0x4, 0x7e, 0x34, 0x0,
+ 0x55, 0x12, 0xc, 0x86, 0x7e, 0x34, 0xa2, 0x1c, 0x12, 0xe, 0x86, 0x74, 0x4,
+ 0x7e, 0x34, 0x0, 0x15, 0x12, 0xc, 0x86, 0x7e, 0x34, 0x0, 0xa0, 0x12, 0xe,
+ 0x86, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x14, 0x12, 0xc, 0x86, 0x7e, 0x34, 0x0,
+ 0x19, 0x12, 0xe, 0x86, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x4, 0x12, 0xc, 0x86,
+ 0x7e, 0x34, 0x0, 0x5, 0x12, 0xe, 0x86, 0xe4, 0x12, 0xa, 0x21, 0x74, 0x4,
+ 0x7e, 0x34, 0xff, 0xf7, 0x2, 0xc, 0x86, 0x7c, 0x7b, 0x7e, 0xa0, 0xef, 0xe5,
+ 0x22, 0x24, 0xfd, 0x68, 0x3c, 0x1b, 0xb1, 0x68, 0x26, 0x24, 0x9f, 0x68,
+ 0x41, 0x1b, 0xb2, 0x68, 0x42, 0x24, 0x9e, 0x68, 0x39, 0x24, 0xe3, 0x68,
+ 0x52, 0x24, 0x59, 0x78, 0x52, 0xa5, 0xbf, 0x0, 0x5, 0x7e, 0xa1, 0x40, 0x80,
+ 0x49, 0xa5, 0xbf, 0x1, 0x45, 0x7e, 0xa1, 0x41, 0x80, 0x40, 0xa5, 0xbf, 0x0,
+ 0x5, 0x7e, 0xa1, 0x24, 0x80, 0x37, 0xa5, 0xbf, 0x1, 0x33, 0x7e, 0xa1, 0x3e,
+ 0x80, 0x2e, 0xa, 0x17, 0x7e, 0x1d, 0x3a, 0x2d, 0x31, 0x29, 0xa1, 0x0, 0x8,
+ 0x80, 0x21, 0x7e, 0xa1, 0x3f, 0x80, 0x1c, 0xa5, 0xbf, 0x0, 0x9, 0x7e, 0x35,
+ 0x31, 0xa, 0x56, 0x7c, 0xab, 0x80, 0xf, 0xa5, 0xbf, 0x1, 0xb, 0x7e, 0x55,
+ 0x31, 0x7c, 0xab, 0x80, 0x4, 0x7e, 0xa3, 0x2, 0xe4, 0x7c, 0xba, 0x22, 0xca,
+ 0x79, 0x6c, 0xee, 0x7e, 0xf0, 0x70, 0x75, 0x91, 0x0, 0xc2, 0x90, 0xc2, 0x91,
+ 0x30, 0x8, 0x31, 0x7e, 0x34, 0x0, 0x2, 0x7a, 0x35, 0x15, 0x9f, 0x11, 0x7e,
+ 0x8, 0x0, 0xc, 0x12, 0xe, 0xf2, 0xe5, 0xc, 0xbe, 0xb0, 0xff, 0x68, 0x1a,
+ 0xe5, 0xc, 0x60, 0x16, 0xe5, 0xd, 0xa, 0x2b, 0xe5, 0xc, 0xa, 0x3b, 0x2d,
+ 0x32, 0xbe, 0x34, 0x0, 0xff, 0x78, 0x6, 0x7e, 0xf1, 0xc, 0x7e, 0xe0, 0x1,
+ 0x4c, 0xee, 0x78, 0x1c, 0xa9, 0xd1, 0xcb, 0xd2, 0xcc, 0x12, 0xc, 0x35, 0x7c,
+ 0xfb, 0xc2, 0xcc, 0xa9, 0xc1, 0xcb, 0xbe, 0xf0, 0x2, 0x40, 0x5, 0xbe, 0xf0,
+ 0xfd, 0x28, 0x3, 0x7e, 0xf0, 0x70, 0x7c, 0xbf, 0x54, 0xfe, 0xf5, 0x92, 0xd2,
+ 0xe8, 0xc2, 0xc0, 0xa9, 0xd5, 0xb7, 0xd2, 0xbd, 0xd2, 0xad, 0xda, 0x79,
+ 0x22, 0xca, 0x79, 0xbe, 0xb0, 0x0, 0x28, 0x2e, 0x74, 0x6, 0x12, 0xa, 0x89,
+ 0x7d, 0x73, 0x6c, 0xff, 0x7e, 0xf0, 0xa5, 0x7d, 0x37, 0x12, 0xc, 0x86, 0x6c,
+ 0xff, 0x7e, 0xf0, 0xf, 0x7d, 0x37, 0x12, 0xc, 0x86, 0x6c, 0xff, 0x7e, 0xf0,
+ 0x6a, 0x7d, 0x37, 0x12, 0xc, 0x86, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xe, 0x86,
+ 0x80, 0x30, 0x74, 0x1, 0x7e, 0x34, 0xdf, 0xff, 0x12, 0xc, 0x86, 0x74, 0x6,
+ 0x12, 0xa, 0x89, 0x7d, 0x73, 0x6c, 0xff, 0x7d, 0x37, 0x12, 0xc, 0x86, 0x7d,
+ 0x37, 0x12, 0xc, 0x86, 0x7d, 0x37, 0x12, 0xc, 0x86, 0x74, 0x2, 0x12, 0xa,
+ 0x89, 0x7d, 0x73, 0x4e, 0xf0, 0x1, 0x7d, 0x37, 0x12, 0xc, 0x86, 0xda, 0x79,
+ 0x22, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x5, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xf5, 0xb5,
+ 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0x7e, 0x71, 0xb5, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0x7e, 0xa1, 0xb5, 0xa9, 0xd2, 0xb4, 0x7c, 0x47, 0x6c, 0x55, 0xa, 0x3a,
+ 0x4d, 0x32, 0x22, 0x7f, 0x70, 0xd2, 0x6, 0x12, 0xe, 0xdf, 0x74, 0x2, 0x12,
+ 0xd, 0xb3, 0x6d, 0x33, 0x80, 0x12, 0x7f, 0x7, 0x2d, 0x13, 0x7e, 0xb, 0xb0,
+ 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xb, 0x34, 0x7e, 0x25,
+ 0x18, 0xbd, 0x23, 0x38, 0xe7, 0xa9, 0xd2, 0xb4, 0x12, 0xf, 0x32, 0x12, 0xe,
+ 0xca, 0x50, 0x9, 0x7e, 0x35, 0x42, 0xbe, 0x34, 0x1, 0xf4, 0x28, 0xf2, 0x7e,
+ 0x35, 0x42, 0xbe, 0x34, 0x1, 0xf4, 0x38, 0x3, 0x2, 0xf, 0x4d, 0xc2, 0x86,
+ 0x7e, 0x34, 0x13, 0x88, 0x12, 0xe, 0x86, 0xd2, 0x86, 0x22, 0xa9, 0xd1, 0xcb,
+ 0xd2, 0xcc, 0x7e, 0x34, 0x0, 0x4, 0x7e, 0x8, 0x2, 0x5c, 0x74, 0xc, 0x12,
+ 0xb, 0x8f, 0xa9, 0xd1, 0xcb, 0xc2, 0xcc, 0x6c, 0xaa, 0x7e, 0x70, 0x2, 0xac,
+ 0x7a, 0x7e, 0x8, 0x2, 0x5c, 0x2d, 0x13, 0xb, 0xa, 0x30, 0x7d, 0x23, 0x7c,
+ 0x45, 0x6c, 0x55, 0xa, 0x36, 0x4d, 0x32, 0x1b, 0xa, 0x30, 0xb, 0xa0, 0xbe,
+ 0xa0, 0xc, 0x78, 0xde, 0x7e, 0x37, 0x2, 0x6c, 0x7d, 0x23, 0xa, 0x54, 0x7c,
+ 0xa7, 0xb4, 0xe7, 0xb, 0xbe, 0xa0, 0x16, 0x78, 0x6, 0x75, 0x40, 0xe7, 0x75,
+ 0x41, 0xa6, 0x22, 0x7e, 0x24, 0x0, 0x1, 0x7e, 0x7f, 0x2, 0xe5, 0x79, 0x27,
+ 0x0, 0x6, 0x7e, 0x7f, 0x2, 0xe5, 0x69, 0x27, 0x0, 0x6, 0x4d, 0x22, 0x78,
+ 0xf4, 0x5e, 0x60, 0x7f, 0x1b, 0x7a, 0x30, 0x7e, 0x1f, 0x2, 0xe5, 0x69, 0x31,
+ 0x0, 0x8, 0x4d, 0x33, 0x68, 0xf4, 0x6c, 0xaa, 0x80, 0x20, 0x6d, 0x44, 0x7e,
+ 0x1f, 0x2, 0xe5, 0x1b, 0x1a, 0x40, 0x7e, 0x1f, 0x2, 0xe5, 0x69, 0x41, 0x0,
+ 0x8, 0x4d, 0x44, 0x68, 0xf4, 0x69, 0x41, 0x0, 0x2, 0x1b, 0xa, 0x40, 0xb,
+ 0x15, 0xb, 0xa0, 0xbc, 0xba, 0x38, 0xdc, 0x22, 0x6d, 0x0, 0x74, 0x10, 0x4d,
+ 0x0, 0x78, 0xb, 0x4d, 0x22, 0x78, 0x27, 0x8d, 0x31, 0x7d, 0x12, 0x6d, 0x22,
+ 0x22, 0x7d, 0x43, 0x7d, 0x32, 0x6d, 0x22, 0x2f, 0x11, 0x2d, 0x44, 0x50, 0x2,
+ 0xa5, 0xf, 0xbf, 0x10, 0x40, 0x4, 0x9f, 0x10, 0xb, 0x90, 0x14, 0x78, 0xed,
+ 0x7f, 0x1, 0x6d, 0x22, 0x7d, 0x34, 0x22, 0x7d, 0x41, 0x7d, 0x13, 0x8d, 0x24,
+ 0x7d, 0x2, 0x2f, 0x0, 0x40, 0x4, 0xbd, 0x4, 0x40, 0x4, 0x9d, 0x4, 0xb, 0x14,
+ 0x14, 0x78, 0xf1, 0x7d, 0x23, 0x7d, 0x31, 0x7d, 0x10, 0x6d, 0x0, 0x22, 0x7e,
+ 0x34, 0x0, 0x2, 0x7e, 0xf, 0x2, 0xe5, 0x79, 0x30, 0x0, 0x4, 0x7e, 0x34, 0x0,
+ 0x1, 0x7e, 0xf, 0x2, 0xe5, 0x79, 0x30, 0x0, 0x6, 0x7e, 0xf, 0x2, 0xe5, 0x69,
+ 0x30, 0x0, 0x6, 0x4d, 0x33, 0x78, 0xf4, 0x7e, 0x34, 0x0, 0x4, 0x1b, 0xa,
+ 0x30, 0x7e, 0xf, 0x2, 0xe5, 0x69, 0x30, 0x0, 0x8, 0x4d, 0x33, 0x68, 0xf4,
+ 0x6d, 0x33, 0x1b, 0xa, 0x30, 0x7e, 0x1f, 0x2, 0xe5, 0x69, 0x11, 0x0, 0x8,
+ 0x4d, 0x11, 0x68, 0xf4, 0x69, 0x51, 0x0, 0x2, 0x5e, 0x54, 0x0, 0xfe, 0x22,
+ 0x7d, 0x23, 0xa, 0x36, 0x7c, 0xa5, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75,
+ 0xb5, 0x1, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9,
+ 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc,
+ 0xa9, 0xc6, 0xb3, 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3,
+ 0x7a, 0x71, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7a, 0xa1,
+ 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xa9, 0xd2, 0xb4, 0x22,
+ 0x7c, 0xab, 0xd2, 0x6, 0x12, 0xe, 0xdf, 0x74, 0xd8, 0xa, 0x3a, 0x7d, 0x23,
+ 0x6d, 0x33, 0x12, 0xd, 0xb3, 0xa9, 0xd2, 0xb4, 0x12, 0xf, 0x32, 0x12, 0xe,
+ 0xca, 0x50, 0x9, 0x7e, 0x35, 0x42, 0xbe, 0x34, 0x5, 0xdc, 0x28, 0xf2, 0x7e,
+ 0x35, 0x42, 0xbe, 0x34, 0x5, 0xdc, 0x38, 0x3, 0x2, 0xf, 0x4d, 0xc2, 0x86,
+ 0x7e, 0x34, 0x13, 0x88, 0x12, 0xe, 0x86, 0xd2, 0x86, 0x22, 0xca, 0x2b, 0xca,
+ 0x1b, 0xca, 0xb, 0xd2, 0x0, 0x30, 0x90, 0x1c, 0xc2, 0x90, 0x7e, 0x71, 0x91,
+ 0xe5, 0x39, 0x70, 0x3, 0x7a, 0x71, 0x22, 0xe5, 0x39, 0x12, 0x1, 0x20, 0x5,
+ 0x39, 0x30, 0x2, 0x6, 0xe4, 0x12, 0x9, 0x33, 0xf5, 0x91, 0x30, 0x91, 0xb,
+ 0xc2, 0x91, 0x5, 0x39, 0xe5, 0x39, 0x12, 0x9, 0x33, 0xf5, 0x91, 0xda, 0xb,
+ 0xda, 0x1b, 0xda, 0x2b, 0x32, 0xd2, 0x6, 0x12, 0xe, 0xdf, 0xa9, 0xc2, 0xb4,
+ 0x74, 0x9f, 0x12, 0xf, 0x27, 0x12, 0xf, 0xe, 0xa9, 0xd2, 0xb4, 0x60, 0x3,
+ 0xb4, 0xff, 0x1a, 0x75, 0x24, 0x81, 0xa9, 0xd5, 0xca, 0xa9, 0xd0, 0xca,
+ 0x75, 0xed, 0x9f, 0x75, 0xad, 0x20, 0xa9, 0xd1, 0xea, 0xa9, 0xc1, 0xea,
+ 0x74, 0x1, 0x2, 0xd, 0xe0, 0x2, 0xd, 0x80, 0xd2, 0x6, 0x12, 0xe, 0xdf, 0xa9,
+ 0xc2, 0xb4, 0x74, 0x5, 0x12, 0xf, 0x27, 0x12, 0xf, 0xe, 0x7c, 0xab, 0xa9,
+ 0xd2, 0xb4, 0xd2, 0x6, 0x12, 0xe, 0xdf, 0x5e, 0xa0, 0xe3, 0xa9, 0xc2, 0xb4,
+ 0x74, 0x1, 0x12, 0xf, 0x27, 0x7c, 0xba, 0x12, 0xf, 0x27, 0xa9, 0xd2, 0xb4,
+ 0x12, 0xe, 0xca, 0x40, 0xfb, 0x22, 0x7c, 0xab, 0x7d, 0x12, 0x7c, 0xb3, 0xf5,
+ 0x1c, 0x7c, 0x36, 0x7c, 0x25, 0xa, 0x4, 0x7c, 0xb3, 0xf5, 0x1b, 0x7c, 0xb7,
+ 0xf5, 0x1a, 0xa9, 0xc2, 0xb4, 0x7c, 0xba, 0x12, 0xf, 0x27, 0xe5, 0x1c, 0x12,
+ 0xf, 0x27, 0xe5, 0x1b, 0x12, 0xf, 0x27, 0xe5, 0x1a, 0x2, 0xf, 0x27, 0xca,
+ 0xf8, 0x7c, 0xfb, 0xe5, 0x24, 0xb4, 0x81, 0x21, 0x74, 0x2, 0x12, 0xa, 0x89,
+ 0x4c, 0xff, 0x78, 0x8, 0xa9, 0xc0, 0xca, 0x5e, 0x70, 0xdf, 0x80, 0x6, 0xa9,
+ 0xd0, 0xca, 0x4e, 0x70, 0x20, 0x74, 0x2, 0x12, 0xc, 0x86, 0x74, 0x2, 0x12,
+ 0xa, 0x89, 0xda, 0xf8, 0x22, 0xd2, 0x6, 0x7e, 0x14, 0x0, 0x8, 0x7a, 0x15,
+ 0x15, 0x7e, 0x8, 0x2, 0xdc, 0x12, 0xe, 0xf2, 0x6c, 0xaa, 0xa, 0x3a, 0x9,
+ 0xb3, 0x2, 0xdc, 0xbe, 0xb0, 0xff, 0x68, 0x4, 0xc2, 0x6, 0x80, 0x7, 0xb,
+ 0xa0, 0xbe, 0xa0, 0x8, 0x40, 0xea, 0xa2, 0x6, 0x22, 0x7d, 0x52, 0xf5, 0x19,
+ 0x7c, 0xb6, 0x7c, 0xa5, 0xa, 0x44, 0xf5, 0x18, 0x7f, 0x21, 0xf5, 0x17, 0xa9,
+ 0xc2, 0xb4, 0x74, 0xb, 0x12, 0xf, 0x27, 0xe5, 0x19, 0x12, 0xf, 0x27, 0xe5,
+ 0x18, 0x12, 0xf, 0x27, 0xe5, 0x17, 0x12, 0xf, 0x27, 0xe4, 0x2, 0xf, 0x27,
+ 0x12, 0xe, 0xa9, 0x12, 0xb, 0x3b, 0xa9, 0xa6, 0x94, 0xb3, 0x92, 0x8, 0x30,
+ 0x8, 0x6, 0x12, 0xf, 0x1b, 0x12, 0xd, 0x4b, 0x12, 0x9, 0xab, 0x12, 0xf, 0x0,
+ 0xd2, 0xaf, 0x30, 0x3, 0xfd, 0x2, 0xf, 0x45, 0x80, 0x18, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe5, 0x3e, 0x70, 0xa, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7d, 0x23, 0x1b, 0x34, 0x4d, 0x22, 0x78,
+ 0xe0, 0x22, 0xd2, 0xcf, 0x85, 0x3e, 0xcc, 0x75, 0xec, 0xff, 0x75, 0xee,
+ 0xff, 0x75, 0xeb, 0x3, 0x75, 0xac, 0xc0, 0xa9, 0xc5, 0xca, 0x75, 0xed, 0xf,
+ 0x75, 0xad, 0xb0, 0xa9, 0xd7, 0x94, 0xa9, 0xd4, 0x94, 0x22, 0xa9, 0xc2,
+ 0xb4, 0x74, 0x5, 0x12, 0xf, 0x27, 0x12, 0xf, 0xe, 0xa9, 0xd2, 0xb4, 0x30,
+ 0xe0, 0x2, 0xd3, 0x22, 0xc3, 0x22, 0xa9, 0xc2, 0xb4, 0x30, 0x6, 0x4, 0x74,
+ 0x6, 0x80, 0x2, 0x74, 0x4, 0x12, 0xf, 0x27, 0xa9, 0xd2, 0xb4, 0x22, 0x12,
+ 0xe, 0x38, 0x7e, 0x35, 0x15, 0x12, 0x0, 0xe, 0xa9, 0xd2, 0xb4, 0xd3, 0x22,
+ 0xc2, 0x8c, 0x43, 0x89, 0x2, 0x75, 0x8c, 0x1, 0x75, 0x8a, 0x0, 0xd2, 0xa9,
+ 0x22, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xe5, 0xb5,
+ 0x22, 0xd2, 0xc8, 0x75, 0xb3, 0x13, 0xa9, 0xd1, 0xb4, 0xa9, 0xc0, 0xb4,
+ 0x22, 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xd3, 0x22,
+ 0xc2, 0x8c, 0x6d, 0x33, 0x7a, 0x35, 0x42, 0xd2, 0x8c, 0x22, 0x7e, 0x35,
+ 0x42, 0xb, 0x34, 0x7a, 0x35, 0x42, 0x22, 0x85, 0x3e, 0xcc, 0xe5, 0x3e, 0x2,
+ 0xd, 0xe0, 0x2, 0xf, 0x3c, 0x0, 0x1, 0x2, 0xe4, 0x0, 0x0, 0x4, 0x2, 0xe5,
+ 0x0, 0x0, 0x9c, 0x0, 0x0, 0x0, 0xff,
diff --git a/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8736_Pramboot_V0.4_20160627.i b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8736_Pramboot_V0.4_20160627.i
new file mode 100644
index 000000000000..b1e3b1c08564
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8736_Pramboot_V0.4_20160627.i
@@ -0,0 +1,288 @@
+0x2, 0x8, 0x9e, 0xca, 0x39, 0x12, 0xe, 0x6c, 0xda, 0x39, 0x32, 0x2, 0x0, 0x3,
+ 0x6d, 0x22, 0x80, 0x13, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6,
+ 0xb3, 0xe5, 0xb5, 0x7a, 0xb, 0xb0, 0xb, 0x14, 0xb, 0x24, 0xbd, 0x32, 0x38,
+ 0xe9, 0x22, 0xff, 0x2, 0xc, 0x47, 0xa9, 0xc2, 0xb4, 0x74, 0x5, 0x12, 0xe,
+ 0x4d, 0x12, 0xe, 0x34, 0xa9, 0xd2, 0xb4, 0x30, 0xe0, 0x2, 0xd3, 0x22, 0xc3,
+ 0x22, 0x2, 0x0, 0xf9, 0xca, 0x3b, 0x7a, 0xd, 0x8, 0x7f, 0x31, 0xe5, 0x23,
+ 0xb4, 0x80, 0x2, 0x80, 0x3, 0x2, 0x0, 0xdc, 0x7f, 0x13, 0x5e, 0x34, 0x0,
+ 0x7f, 0x7d, 0x23, 0x7e, 0x34, 0x0, 0x80, 0x9d, 0x32, 0x7a, 0x35, 0xe, 0x7e,
+ 0x35, 0xc, 0xbe, 0x35, 0xe, 0x38, 0x2, 0x80, 0x5d, 0x7e, 0x35, 0xe, 0x7a,
+ 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0xa, 0xba, 0x7e, 0x35, 0xc,
+ 0x9e, 0x35, 0xe, 0x7a, 0x35, 0xc, 0x7e, 0x35, 0xe, 0x6d, 0x22, 0x2f, 0x31,
+ 0x7e, 0x1d, 0x8, 0x2e, 0x35, 0xe, 0x7a, 0x1d, 0x8, 0x80, 0x27, 0x7e, 0x34,
+ 0x0, 0x80, 0x7a, 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0xa, 0xba,
+ 0x7e, 0x35, 0xc, 0x9e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0xc, 0x7e, 0x1d, 0x8,
+ 0x2e, 0x34, 0x0, 0x80, 0x7a, 0x1d, 0x8, 0x2e, 0x38, 0x0, 0x80, 0x7e, 0x35,
+ 0xc, 0xbe, 0x34, 0x0, 0x80, 0x50, 0xd0, 0x4d, 0x33, 0x68, 0x26, 0x7a, 0x35,
+ 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0xa, 0xba, 0x80, 0x19, 0x74, 0x2,
+ 0x12, 0xa, 0x5d, 0x5e, 0x70, 0xf4, 0x12, 0x3, 0xb4, 0x7e, 0x35, 0xc, 0x7a,
+ 0x35, 0x10, 0x7f, 0x13, 0x7e, 0xd, 0x8, 0x12, 0x6, 0xeb, 0xd3, 0xda, 0x3b,
+ 0x22, 0xa9, 0xc0, 0x93, 0x75, 0x38, 0x0, 0x32, 0xe, 0x8a, 0xf1, 0x75, 0xf4,
+ 0xf8, 0xb, 0x7, 0xca, 0xca, 0x35, 0x35, 0xff, 0xff, 0xff, 0x0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x70, 0x8f, 0x0, 0xff, 0xff, 0x0, 0xff, 0xac, 0xff, 0xac, 0x1,
+ 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0x6b, 0xc2, 0x2, 0xe5, 0x21,
+ 0x14, 0x78, 0x3, 0x2, 0x3, 0x3f, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0xb0,
+ 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0xfc, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x3, 0xd,
+ 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x3, 0x26, 0x24, 0xf9, 0x78, 0x3, 0x2, 0x3,
+ 0x3b, 0x24, 0xaf, 0x78, 0x3, 0x2, 0x3, 0xa9, 0x24, 0xfd, 0x68, 0x2d, 0x14,
+ 0x78, 0x3, 0x2, 0x3, 0x42, 0x14, 0x78, 0x3, 0x2, 0x3, 0x3f, 0x1b, 0xb2,
+ 0x78, 0x3, 0x2, 0x3, 0x3f, 0x24, 0xda, 0x68, 0x19, 0x24, 0xe6, 0x68, 0x12,
+ 0x24, 0xeb, 0x68, 0x2e, 0x24, 0xf3, 0x78, 0x3, 0x2, 0x3, 0x3f, 0x24, 0x77,
+ 0x68, 0x3, 0x2, 0x3, 0xb3, 0x2, 0x3, 0xb0, 0xbe, 0x60, 0x4, 0x50, 0xc, 0x75,
+ 0x16, 0x0, 0x7c, 0x16, 0x2e, 0x10, 0x24, 0x7c, 0xb7, 0xa5, 0xf7, 0xa5, 0xbe,
+ 0x0, 0x2, 0x80, 0x3, 0x2, 0x3, 0xb3, 0xd2, 0x2, 0x22, 0x7c, 0xb6, 0x24, 0x0,
+ 0x78, 0x3, 0x2, 0x3, 0xb3, 0x1b, 0xb1, 0x68, 0x1e, 0x14, 0x68, 0x1e, 0x14,
+ 0x68, 0x1e, 0x14, 0x68, 0x1e, 0xb, 0xb2, 0x78, 0x33, 0x30, 0x1, 0x7, 0x7e,
+ 0x8, 0x0, 0x3e, 0x2, 0x2, 0xcd, 0x7e, 0x8, 0x1, 0x4a, 0x2, 0x2, 0xcd, 0x2,
+ 0x3, 0x67, 0x2, 0x3, 0x6e, 0x2, 0x3, 0x86, 0xa, 0x27, 0x7e, 0xd, 0x39, 0xb,
+ 0x16, 0xb, 0xa, 0x30, 0x2d, 0x32, 0x1b, 0xa, 0x30, 0x6d, 0x33, 0x7e, 0xd,
+ 0x39, 0x79, 0x30, 0x0, 0x6, 0x22, 0x7c, 0xb7, 0x62, 0x16, 0x7e, 0x2d, 0x39,
+ 0x2e, 0x54, 0x0, 0x6, 0xb, 0x2a, 0x20, 0x7d, 0x12, 0xb, 0x14, 0x1b, 0x2a,
+ 0x10, 0x7e, 0xd, 0x39, 0x2d, 0x12, 0x39, 0x70, 0x0, 0x8, 0x7e, 0xd, 0x39,
+ 0x69, 0x50, 0x0, 0x4, 0x69, 0x20, 0x0, 0x6, 0xbd, 0x25, 0x50, 0x3, 0x2, 0x3,
+ 0xb3, 0xb2, 0x1, 0x7a, 0xd, 0x33, 0x7e, 0x34, 0x0, 0x2, 0x2, 0x3, 0xa5,
+ 0x7c, 0xb6, 0x1b, 0xb1, 0x68, 0x1d, 0x14, 0x68, 0x1d, 0xb, 0xb1, 0x68, 0x3,
+ 0x2, 0x3, 0xb3, 0x30, 0x1, 0x6, 0x7e, 0x8, 0x0, 0x3e, 0x80, 0x4, 0x7e, 0x8,
+ 0x1, 0x4a, 0x7a, 0xd, 0x39, 0x2, 0x3, 0x56, 0x2, 0x3, 0x67, 0xa, 0x57, 0x6d,
+ 0x44, 0x7e, 0xd, 0x39, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12,
+ 0x79, 0x30, 0x0, 0x2, 0x1b, 0xa, 0x20, 0x7e, 0x1d, 0x39, 0x7a, 0x1d, 0x33,
+ 0xd2, 0x2, 0x7e, 0x34, 0x0, 0x1, 0x2, 0x3, 0xa5, 0xbe, 0x60, 0x1, 0x68, 0x9,
+ 0xa5, 0xbe, 0x2, 0x5, 0x7a, 0x71, 0x3d, 0xd2, 0x3, 0xd2, 0x2, 0x22, 0x75,
+ 0xe6, 0x0, 0xe4, 0x7e, 0x34, 0x1, 0x4, 0x7e, 0x24, 0x0, 0xff, 0x7a, 0x1b,
+ 0xb0, 0x7e, 0x34, 0x1, 0x5, 0x7a, 0x1b, 0xb0, 0xd2, 0x4, 0x22, 0xa5, 0xbe,
+ 0x1, 0x4, 0x7a, 0x71, 0x37, 0x22, 0xa5, 0xbe, 0x2, 0x2, 0x80, 0x3, 0x2, 0x3,
+ 0xb3, 0x7a, 0x71, 0x22, 0x22, 0x7a, 0x71, 0x32, 0x22, 0xd2, 0x2, 0x22, 0x1b,
+ 0x61, 0x68, 0x21, 0x1b, 0x60, 0x68, 0x24, 0x1b, 0x60, 0x68, 0x38, 0x1b,
+ 0x60, 0x68, 0x40, 0xb, 0x62, 0x78, 0x5d, 0xa, 0x37, 0x7d, 0x3, 0x6d, 0x11,
+ 0x7e, 0x1d, 0x39, 0x79, 0x11, 0x0, 0x2, 0x1b, 0x1a, 0x0, 0x22, 0xa, 0x57,
+ 0x7c, 0xab, 0xe4, 0x80, 0x2, 0xa, 0x57, 0x6d, 0x44, 0x7e, 0xd, 0x39, 0x69,
+ 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12, 0x79, 0x30, 0x0, 0x2, 0x1b, 0xa,
+ 0x20, 0x22, 0x7c, 0x67, 0x6c, 0x77, 0x7e, 0xd, 0x39, 0x79, 0x30, 0x0, 0x4,
+ 0x22, 0xa, 0x27, 0x7e, 0xd, 0x39, 0xb, 0x16, 0xb, 0xa, 0x30, 0x2d, 0x32,
+ 0x1b, 0xa, 0x30, 0x7e, 0x34, 0x0, 0x3, 0x7a, 0x35, 0x2e, 0x22, 0x7e, 0x34,
+ 0x0, 0x4, 0x7a, 0x35, 0x2e, 0x75, 0x16, 0x0, 0x22, 0x7d, 0x23, 0xa, 0x36,
+ 0x7c, 0xa5, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x1, 0xa9, 0x36,
+ 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9,
+ 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xf5,
+ 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7a, 0x71, 0xb5, 0xa9,
+ 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7a, 0xa1, 0xb5, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0xa9, 0xd2, 0xb4, 0x22, 0xff, 0x56, 0x30, 0x2e,
+ 0x32, 0x5f, 0x4a, 0x75, 0x6e, 0x20, 0x32, 0x37, 0x20, 0x32, 0x30, 0x31,
+ 0x36, 0x46, 0x54, 0x53, 0x38, 0x37, 0x33, 0x36, 0x5f, 0x50, 0x72, 0x61,
+ 0x6d, 0x62, 0x6f, 0x6f, 0x74, 0x12, 0xd, 0x73, 0x2, 0x5, 0x66, 0x7e, 0x35,
+ 0x2e, 0x1b, 0x34, 0x68, 0x57, 0x1b, 0x35, 0x78, 0x3, 0x2, 0x4, 0xb3, 0x1b,
+ 0x34, 0x78, 0x3, 0x2, 0x4, 0xdd, 0xb, 0x35, 0x68, 0x3, 0x2, 0x5, 0x52, 0x6d,
+ 0x33, 0x7a, 0x35, 0x2e, 0x7a, 0x35, 0x30, 0x30, 0x5, 0x5, 0x12, 0xe, 0x7,
+ 0xc2, 0x5, 0x7e, 0xd, 0x33, 0x69, 0x30, 0x0, 0x4, 0x7a, 0x35, 0xc, 0x69,
+ 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2e, 0x14, 0x0, 0x8, 0x12, 0x0, 0x46, 0xd2,
+ 0x5, 0x7e, 0x2d, 0x33, 0x69, 0x12, 0x0, 0x4, 0x69, 0x32, 0x0, 0x2, 0xb,
+ 0x2a, 0x20, 0x12, 0xb, 0xb6, 0x2e, 0x34, 0x10, 0x0, 0x2, 0x5, 0x4f, 0x6d,
+ 0x33, 0x7a, 0x35, 0x2e, 0x7e, 0x34, 0x1, 0x0, 0x7a, 0x35, 0x11, 0x7e, 0xd,
+ 0x33, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2e, 0x14, 0x0, 0x8, 0x12, 0xe,
+ 0x18, 0x20, 0x0, 0x3, 0x2, 0x5, 0x52, 0x7e, 0x1d, 0x33, 0x29, 0xb1, 0x0,
+ 0x8, 0xf5, 0x91, 0x2, 0x5, 0x52, 0x6d, 0x33, 0x7a, 0x35, 0x2e, 0x7a, 0x35,
+ 0x30, 0x7e, 0x18, 0x0, 0x16, 0x7a, 0x1d, 0xa, 0x7e, 0xd, 0x33, 0x69, 0x30,
+ 0x0, 0x2, 0xb, 0xa, 0x20, 0x69, 0x10, 0x0, 0x4, 0x12, 0x6, 0x42, 0x12, 0xe,
+ 0x7, 0x7e, 0x34, 0xf0, 0x55, 0x2, 0x5, 0x4f, 0x6d, 0x33, 0x7a, 0x35, 0x2e,
+ 0x7a, 0x35, 0x30, 0xe5, 0x37, 0xb4, 0xa, 0x15, 0xe5, 0x23, 0xb4, 0x80, 0xb,
+ 0xe4, 0x12, 0xc, 0x9, 0x74, 0x1, 0x12, 0xc, 0x9, 0x80, 0x4e, 0x12, 0x7,
+ 0x81, 0x80, 0x49, 0xe5, 0x37, 0xb4, 0xb, 0x27, 0xe5, 0x23, 0xb4, 0x80, 0x11,
+ 0x7e, 0xf0, 0x1, 0x7c, 0xbf, 0x12, 0x5, 0x6d, 0xb, 0xf0, 0xbe, 0xf0, 0x11,
+ 0x78, 0xf4, 0x80, 0x2e, 0x7e, 0xf0, 0x4, 0x7c, 0xbf, 0x12, 0x5, 0x6d, 0xb,
+ 0xf0, 0xbe, 0xf0, 0x40, 0x78, 0xf4, 0x80, 0x1d, 0xe5, 0x37, 0xa, 0x3b, 0x9e,
+ 0x34, 0x0, 0x80, 0x7c, 0xe7, 0x6c, 0xdd, 0x80, 0x9, 0x7c, 0xbe, 0x12, 0x5,
+ 0x6d, 0xb, 0xe0, 0xb, 0xd0, 0xe5, 0x22, 0xbc, 0xbd, 0x38, 0xf1, 0x12, 0xe,
+ 0x7, 0x7e, 0x34, 0xf0, 0xaa, 0x7a, 0x35, 0x30, 0x30, 0x4, 0x11, 0x7e, 0x34,
+ 0x13, 0x88, 0x12, 0xd, 0x96, 0x7e, 0x34, 0x13, 0x88, 0x12, 0xd, 0x96, 0x75,
+ 0xe9, 0xff, 0x30, 0x6, 0x3, 0x2, 0x4, 0x26, 0x22, 0xca, 0xf8, 0x7c, 0xfb,
+ 0xe5, 0x23, 0xb4, 0x80, 0x4a, 0xd2, 0x7, 0x12, 0xd, 0xf4, 0x74, 0x20, 0xca,
+ 0xb8, 0xa, 0x3f, 0x6d, 0x22, 0x74, 0xc, 0x2f, 0x11, 0x14, 0x78, 0xfb, 0xda,
+ 0xb8, 0x12, 0xd, 0x1b, 0xa9, 0xd2, 0xb4, 0x12, 0xe, 0x62, 0x12, 0x0, 0x2e,
+ 0x50, 0x9, 0x7e, 0x35, 0x19, 0xbe, 0x34, 0x1, 0xf4, 0x28, 0xf2, 0x7e, 0x35,
+ 0x19, 0xbe, 0x34, 0x1, 0xf4, 0x38, 0x6, 0x12, 0xe, 0x7d, 0x2, 0x6, 0x3f,
+ 0xc2, 0x86, 0x7e, 0x34, 0x13, 0x88, 0x12, 0xd, 0x96, 0xd2, 0x86, 0x2, 0x6,
+ 0x3f, 0x74, 0x1, 0x12, 0x9, 0xf5, 0x74, 0x1, 0x6d, 0x33, 0x12, 0x3, 0xb4,
+ 0xe4, 0x12, 0xa, 0x5d, 0x5e, 0x34, 0x80, 0x0, 0x7c, 0x4f, 0x6c, 0x55, 0x3e,
+ 0x24, 0x4d, 0x32, 0x12, 0x3, 0xb4, 0x74, 0x4, 0x6d, 0x33, 0x12, 0x3, 0xb4,
+ 0x7e, 0x34, 0x0, 0x50, 0x12, 0x3, 0xb4, 0x7e, 0x34, 0x0, 0x19, 0x12, 0xd,
+ 0x96, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x51, 0x12, 0x3, 0xb4, 0x7e, 0x34, 0xa2,
+ 0x1c, 0x12, 0xd, 0x96, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x11, 0x12, 0x3, 0xb4,
+ 0x7e, 0x34, 0x0, 0x19, 0x12, 0xd, 0x96, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x10,
+ 0x12, 0x3, 0xb4, 0x7e, 0x34, 0x0, 0x19, 0x12, 0xd, 0x96, 0x74, 0x4, 0x6d,
+ 0x33, 0x12, 0x3, 0xb4, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xd, 0x96, 0xe4, 0x12,
+ 0x9, 0xf5, 0x74, 0x4, 0x7e, 0x34, 0xff, 0xf7, 0x12, 0x3, 0xb4, 0xda, 0xf8,
+ 0x22, 0xca, 0x3b, 0x7a, 0x15, 0x8, 0x7f, 0x31, 0x7e, 0x35, 0x8, 0xbe, 0x34,
+ 0x0, 0x0, 0x38, 0x4f, 0x7e, 0x34, 0xff, 0xff, 0x7a, 0x35, 0x8, 0x75, 0xe,
+ 0x1, 0x80, 0x43, 0x7e, 0x34, 0x0, 0x80, 0x7a, 0x35, 0x11, 0x7f, 0x13, 0x7e,
+ 0x8, 0x2, 0x56, 0x12, 0xe, 0x18, 0x7e, 0x35, 0x8, 0x9e, 0x34, 0x0, 0x80,
+ 0x7a, 0x35, 0x8, 0x2e, 0x38, 0x0, 0x80, 0x6d, 0x33, 0x7a, 0x35, 0xf, 0x7e,
+ 0x35, 0xf, 0x9, 0x63, 0x2, 0x56, 0x7e, 0xd, 0xa, 0x7e, 0xb, 0x70, 0x6c,
+ 0x76, 0x7a, 0xb, 0x70, 0x7e, 0x35, 0xf, 0xb, 0x34, 0x7a, 0x35, 0xf, 0xbe,
+ 0x34, 0x0, 0x80, 0x78, 0xe0, 0x7e, 0x35, 0x8, 0xbe, 0x34, 0x0, 0x80, 0x38,
+ 0xb4, 0xe5, 0xe, 0x60, 0x5, 0xb, 0x34, 0x7a, 0x35, 0x8, 0x7e, 0x35, 0x8,
+ 0x7a, 0x35, 0x11, 0x7f, 0x13, 0x7e, 0x8, 0x2, 0x56, 0x12, 0xe, 0x18, 0x6d,
+ 0x33, 0x80, 0x17, 0x7e, 0x35, 0xf, 0x9, 0x63, 0x2, 0x56, 0x7e, 0xd, 0xa,
+ 0x7e, 0xb, 0x70, 0x6c, 0x76, 0x7a, 0xb, 0x70, 0x7e, 0x35, 0xf, 0xb, 0x34,
+ 0x7a, 0x35, 0xf, 0x7e, 0x35, 0x8, 0xbe, 0x35, 0xf, 0x38, 0xde, 0xda, 0x3b,
+ 0x22, 0xca, 0x3b, 0x7f, 0x30, 0x7c, 0xb6, 0xf5, 0x12, 0x7c, 0xb7, 0xf5,
+ 0x13, 0x74, 0x1, 0x7e, 0x35, 0x10, 0x1e, 0x34, 0x1b, 0x34, 0x4e, 0x60, 0x80,
+ 0x12, 0x3, 0xb4, 0x12, 0x9, 0xf5, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6, 0xb3, 0x75,
+ 0xb5, 0x2, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9,
+ 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x85, 0x12, 0xb5, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0x85, 0x13, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9,
+ 0xc6, 0xb3, 0x6d, 0x33, 0x80, 0x2a, 0x7f, 0x13, 0x2e, 0x35, 0x14, 0x7e,
+ 0x1b, 0xb0, 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7e,
+ 0x35, 0x14, 0x5e, 0x34, 0x0, 0x1, 0xbe, 0x34, 0x0, 0x1, 0x78, 0x7, 0x7e,
+ 0x34, 0x0, 0x78, 0x12, 0xd, 0x96, 0x7e, 0x35, 0x14, 0xb, 0x34, 0x7a, 0x35,
+ 0x14, 0x7e, 0x35, 0x10, 0xbe, 0x35, 0x14, 0x38, 0xcb, 0xa9, 0xd2, 0xb4,
+ 0x7e, 0x34, 0x0, 0x5, 0x12, 0xd, 0x96, 0xe4, 0x12, 0x9, 0xf5, 0xda, 0x3b,
+ 0x22, 0xe5, 0x23, 0xb4, 0x80, 0x16, 0xd2, 0x7, 0x12, 0xd, 0xf4, 0xa9, 0xc2,
+ 0xb4, 0x74, 0x60, 0x12, 0xe, 0x4d, 0xa9, 0xd2, 0xb4, 0x12, 0x0, 0x2e, 0x40,
+ 0xfb, 0x22, 0x74, 0x1, 0x12, 0x9, 0xf5, 0xe4, 0x6d, 0x33, 0x12, 0x3, 0xb4,
+ 0x74, 0x1, 0x6d, 0x33, 0x12, 0x3, 0xb4, 0x74, 0x4, 0x6d, 0x33, 0x12, 0x3,
+ 0xb4, 0x7e, 0x34, 0x0, 0x54, 0x12, 0x3, 0xb4, 0x7e, 0x34, 0x0, 0x19, 0x12,
+ 0xd, 0x96, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x55, 0x12, 0x3, 0xb4, 0x7e, 0x34,
+ 0xa2, 0x1c, 0x12, 0xd, 0x96, 0x74, 0x4, 0x7e, 0x34, 0x0, 0x15, 0x12, 0x3,
+ 0xb4, 0x7e, 0x34, 0x0, 0xa0, 0x12, 0xd, 0x96, 0x74, 0x4, 0x7e, 0x34, 0x0,
+ 0x14, 0x12, 0x3, 0xb4, 0x7e, 0x34, 0x0, 0x19, 0x12, 0xd, 0x96, 0x74, 0x4,
+ 0x7e, 0x34, 0x0, 0x4, 0x12, 0x3, 0xb4, 0x7e, 0x34, 0x0, 0x5, 0x12, 0xd,
+ 0x96, 0xe4, 0x12, 0x9, 0xf5, 0x74, 0x4, 0x7e, 0x34, 0xff, 0xf7, 0x2, 0x3,
+ 0xb4, 0xca, 0xf8, 0x7e, 0xf0, 0x70, 0xc2, 0x7, 0x75, 0x91, 0x0, 0xc2, 0x90,
+ 0xc2, 0x91, 0x30, 0x6, 0x4e, 0x7e, 0x34, 0x0, 0x6, 0x7a, 0x35, 0x11, 0x7e,
+ 0x18, 0xf, 0x80, 0x7e, 0x8, 0x2, 0xd6, 0x12, 0xe, 0x18, 0x7e, 0xb3, 0x2,
+ 0xd6, 0x7e, 0x73, 0x2, 0xd7, 0x12, 0xd, 0xda, 0x92, 0x7, 0x30, 0x7, 0x6,
+ 0x7e, 0xf3, 0x2, 0xd6, 0x80, 0x26, 0x7e, 0x34, 0x0, 0x6, 0x7a, 0x35, 0x11,
+ 0x7e, 0x18, 0x11, 0x20, 0x7e, 0x8, 0x2, 0xf6, 0x12, 0xe, 0x18, 0x7e, 0xb3,
+ 0x2, 0xf6, 0x7e, 0x73, 0x2, 0xf7, 0x12, 0xd, 0xda, 0x92, 0x7, 0x30, 0x7,
+ 0x4, 0x7e, 0xf3, 0x2, 0xf6, 0x20, 0x6, 0x18, 0xd2, 0xcc, 0x12, 0xe, 0x58,
+ 0x7c, 0xab, 0xc2, 0xcc, 0x7c, 0x7a, 0x6e, 0x70, 0xff, 0x12, 0xd, 0xda, 0x92,
+ 0x7, 0x30, 0x7, 0x2, 0x7c, 0xfa, 0x5e, 0xf0, 0xfe, 0x7a, 0xf1, 0x92, 0xd2,
+ 0xe8, 0xc2, 0xc0, 0xa9, 0xd5, 0xb7, 0xd2, 0xbd, 0xd2, 0xad, 0xda, 0xf8,
+ 0x22, 0x75, 0x84, 0x1, 0x7e, 0x44, 0x1f, 0xff, 0xe4, 0x7a, 0x49, 0xb0, 0x1b,
+ 0x44, 0x78, 0xf9, 0x7e, 0xf8, 0x3, 0x19, 0xd2, 0x5, 0xc2, 0x6, 0x75, 0x16,
+ 0x0, 0x75, 0x17, 0x87, 0x75, 0x18, 0xc6, 0x75, 0x19, 0x0, 0x75, 0x1a, 0x0,
+ 0xd2, 0x0, 0xc2, 0x2, 0xc2, 0x3, 0xc2, 0x4, 0x75, 0x21, 0x0, 0x75, 0x22,
+ 0x0, 0x75, 0x23, 0x80, 0x75, 0x2e, 0x0, 0x75, 0x2f, 0x0, 0x75, 0x30, 0x0,
+ 0x75, 0x31, 0x0, 0x75, 0x32, 0x0, 0x75, 0x37, 0xb, 0x75, 0x38, 0x0, 0x75,
+ 0x3d, 0x1, 0x7e, 0x4, 0x0, 0xff, 0x7e, 0x14, 0xe, 0x80, 0xb, 0xa, 0x40,
+ 0x5d, 0x44, 0x68, 0x1a, 0x69, 0x20, 0x0, 0x2, 0xb, 0xe, 0xb, 0x44, 0x80,
+ 0xa, 0x7e, 0xb, 0xb0, 0x7a, 0x29, 0xb0, 0xb, 0x24, 0xb, 0xc, 0x1b, 0x44,
+ 0x78, 0xf2, 0x80, 0xdf, 0x2, 0x4, 0x20, 0xca, 0x79, 0x7d, 0x73, 0x12, 0xe,
+ 0x62, 0x7e, 0x34, 0x0, 0x1, 0x7e, 0xf, 0x3, 0x16, 0x79, 0x30, 0x0, 0x4,
+ 0x7e, 0xf, 0x3, 0x16, 0x79, 0x30, 0x0, 0x6, 0x7e, 0x1f, 0x3, 0x16, 0x69,
+ 0x11, 0x0, 0x6, 0x4d, 0x11, 0x68, 0x9, 0x7e, 0x15, 0x19, 0xbe, 0x14, 0x0,
+ 0x3c, 0x28, 0xeb, 0x1b, 0x1a, 0x70, 0x7e, 0xf, 0x3, 0x16, 0x69, 0x30, 0x0,
+ 0x8, 0x4d, 0x33, 0x78, 0x9, 0x7e, 0x35, 0x19, 0xbe, 0x34, 0x0, 0x3c, 0x28,
+ 0xeb, 0x6d, 0x33, 0x1b, 0xa, 0x30, 0x7e, 0x1f, 0x3, 0x16, 0x69, 0x11, 0x0,
+ 0x8, 0x4d, 0x11, 0x78, 0x9, 0x7e, 0x15, 0x19, 0xbe, 0x14, 0x0, 0x3c, 0x28,
+ 0xeb, 0x69, 0x71, 0x0, 0x2, 0x12, 0xe, 0x7d, 0x7d, 0x37, 0xda, 0x79, 0x22,
+ 0x7c, 0x7b, 0x7e, 0xa0, 0xef, 0xe5, 0x21, 0x24, 0xfd, 0x68, 0x38, 0x1b,
+ 0xb1, 0x68, 0x22, 0x24, 0x9f, 0x68, 0x3d, 0x1b, 0xb2, 0x68, 0x3e, 0x24,
+ 0x9e, 0x68, 0x35, 0x24, 0x3c, 0x78, 0x4c, 0xa5, 0xbf, 0x0, 0x5, 0x7e, 0xa1,
+ 0x17, 0x80, 0x43, 0xa5, 0xbf, 0x1, 0x3f, 0x7e, 0xa1, 0x18, 0x80, 0x3a, 0xa5,
+ 0xbf, 0x0, 0x5, 0x7e, 0xa1, 0x23, 0x80, 0x31, 0xa5, 0xbf, 0x1, 0x2d, 0x7e,
+ 0xa1, 0x3d, 0x80, 0x28, 0xa, 0x17, 0x7e, 0x1d, 0x39, 0x2d, 0x31, 0x29, 0xa1,
+ 0x0, 0x8, 0x80, 0x1b, 0x7e, 0xa1, 0x16, 0x80, 0x16, 0xa5, 0xbf, 0x0, 0x9,
+ 0x7e, 0x35, 0x30, 0xa, 0x56, 0x7c, 0xab, 0x80, 0x9, 0xa5, 0xbf, 0x1, 0x5,
+ 0x7e, 0x55, 0x30, 0x7c, 0xab, 0x7c, 0xba, 0x22, 0xca, 0x79, 0xbe, 0xb0, 0x0,
+ 0x28, 0x2e, 0x74, 0x6, 0x12, 0xa, 0x5d, 0x7d, 0x73, 0x6c, 0xff, 0x7e, 0xf0,
+ 0xa5, 0x7d, 0x37, 0x12, 0x3, 0xb4, 0x6c, 0xff, 0x7e, 0xf0, 0xf, 0x7d, 0x37,
+ 0x12, 0x3, 0xb4, 0x6c, 0xff, 0x7e, 0xf0, 0x6a, 0x7d, 0x37, 0x12, 0x3, 0xb4,
+ 0x7e, 0x34, 0x0, 0x5, 0x12, 0xd, 0x96, 0x80, 0x30, 0x74, 0x1, 0x7e, 0x34,
+ 0xdf, 0xff, 0x12, 0x3, 0xb4, 0x74, 0x6, 0x12, 0xa, 0x5d, 0x7d, 0x73, 0x6c,
+ 0xff, 0x7d, 0x37, 0x12, 0x3, 0xb4, 0x7d, 0x37, 0x12, 0x3, 0xb4, 0x7d, 0x37,
+ 0x12, 0x3, 0xb4, 0x74, 0x2, 0x12, 0xa, 0x5d, 0x7d, 0x73, 0x4e, 0xf0, 0x1,
+ 0x7d, 0x37, 0x12, 0x3, 0xb4, 0xda, 0x79, 0x22, 0xa9, 0xc2, 0xb4, 0xa9, 0xc6,
+ 0xb3, 0x75, 0xb5, 0x5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5,
+ 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36,
+ 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9,
+ 0xc6, 0xb3, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x75,
+ 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7e, 0x71, 0xb5, 0x75,
+ 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9, 0xc6, 0xb3, 0x7e, 0xa1, 0xb5, 0xa9,
+ 0xd2, 0xb4, 0x7c, 0x47, 0x6c, 0x55, 0xa, 0x3a, 0x4d, 0x32, 0x22, 0x7f, 0x70,
+ 0xd2, 0x7, 0x12, 0xd, 0xf4, 0x74, 0x2, 0x12, 0xd, 0x1b, 0x6d, 0x33, 0x80,
+ 0x12, 0x7f, 0x7, 0x2d, 0x13, 0x7e, 0xb, 0xb0, 0xf5, 0xb5, 0xa9, 0x36, 0xb3,
+ 0xfc, 0xa9, 0xc6, 0xb3, 0xb, 0x34, 0x7e, 0x25, 0x10, 0xbd, 0x23, 0x38, 0xe7,
+ 0xa9, 0xd2, 0xb4, 0x12, 0xe, 0x62, 0x12, 0x0, 0x2e, 0x50, 0x9, 0x7e, 0x35,
+ 0x19, 0xbe, 0x34, 0x1, 0xf4, 0x28, 0xf2, 0x7e, 0x35, 0x19, 0xbe, 0x34, 0x1,
+ 0xf4, 0x38, 0x3, 0x2, 0xe, 0x7d, 0xc2, 0x86, 0x7e, 0x34, 0x13, 0x88, 0x12,
+ 0xd, 0x96, 0xd2, 0x86, 0x22, 0xa9, 0xd1, 0xcb, 0xd2, 0xcc, 0x7e, 0x34, 0x0,
+ 0x4, 0x7e, 0x8, 0x2, 0x56, 0x74, 0xc, 0x12, 0xb, 0x63, 0xa9, 0xd1, 0xcb,
+ 0xc2, 0xcc, 0x6c, 0xaa, 0x7e, 0x70, 0x2, 0xac, 0x7a, 0x7e, 0x8, 0x2, 0x56,
+ 0x2d, 0x13, 0xb, 0xa, 0x30, 0x7d, 0x23, 0x7c, 0x45, 0x6c, 0x55, 0xa, 0x36,
+ 0x4d, 0x32, 0x1b, 0xa, 0x30, 0xb, 0xa0, 0xbe, 0xa0, 0xc, 0x78, 0xde, 0x7e,
+ 0x37, 0x2, 0x66, 0x7d, 0x23, 0xa, 0x54, 0x7c, 0xa7, 0xb4, 0xe7, 0xb, 0xbe,
+ 0xa0, 0x36, 0x78, 0x6, 0x75, 0x17, 0xe7, 0x75, 0x18, 0xc6, 0x22, 0x7e, 0x24,
+ 0x0, 0x1, 0x7e, 0x7f, 0x3, 0x16, 0x79, 0x27, 0x0, 0x6, 0x7e, 0x7f, 0x3,
+ 0x16, 0x69, 0x27, 0x0, 0x6, 0x4d, 0x22, 0x78, 0xf4, 0x5e, 0x60, 0x7f, 0x1b,
+ 0x7a, 0x30, 0x7e, 0x1f, 0x3, 0x16, 0x69, 0x31, 0x0, 0x8, 0x4d, 0x33, 0x68,
+ 0xf4, 0x6c, 0xaa, 0x80, 0x20, 0x6d, 0x44, 0x7e, 0x1f, 0x3, 0x16, 0x1b, 0x1a,
+ 0x40, 0x7e, 0x1f, 0x3, 0x16, 0x69, 0x41, 0x0, 0x8, 0x4d, 0x44, 0x68, 0xf4,
+ 0x69, 0x41, 0x0, 0x2, 0x1b, 0xa, 0x40, 0xb, 0x15, 0xb, 0xa0, 0xbc, 0xba,
+ 0x38, 0xdc, 0x22, 0x6d, 0x0, 0x74, 0x10, 0x4d, 0x0, 0x78, 0xb, 0x4d, 0x22,
+ 0x78, 0x27, 0x8d, 0x31, 0x7d, 0x12, 0x6d, 0x22, 0x22, 0x7d, 0x43, 0x7d,
+ 0x32, 0x6d, 0x22, 0x2f, 0x11, 0x2d, 0x44, 0x50, 0x2, 0xa5, 0xf, 0xbf, 0x10,
+ 0x40, 0x4, 0x9f, 0x10, 0xb, 0x90, 0x14, 0x78, 0xed, 0x7f, 0x1, 0x6d, 0x22,
+ 0x7d, 0x34, 0x22, 0x7d, 0x41, 0x7d, 0x13, 0x8d, 0x24, 0x7d, 0x2, 0x2f, 0x0,
+ 0x40, 0x4, 0xbd, 0x4, 0x40, 0x4, 0x9d, 0x4, 0xb, 0x14, 0x14, 0x78, 0xf1,
+ 0x7d, 0x23, 0x7d, 0x31, 0x7d, 0x10, 0x6d, 0x0, 0x22, 0x7c, 0xab, 0xd2, 0x7,
+ 0x12, 0xd, 0xf4, 0x74, 0xd8, 0xa, 0x3a, 0x7d, 0x23, 0x6d, 0x33, 0x12, 0xd,
+ 0x1b, 0xa9, 0xd2, 0xb4, 0x12, 0xe, 0x62, 0x12, 0x0, 0x2e, 0x50, 0x9, 0x7e,
+ 0x35, 0x19, 0xbe, 0x34, 0x5, 0xdc, 0x28, 0xf2, 0x7e, 0x35, 0x19, 0xbe, 0x34,
+ 0x5, 0xdc, 0x38, 0x3, 0x2, 0xe, 0x7d, 0xc2, 0x86, 0x7e, 0x34, 0x13, 0x88,
+ 0x12, 0xd, 0x96, 0xd2, 0x86, 0x22, 0xca, 0x2b, 0xca, 0x1b, 0xca, 0xb, 0xd2,
+ 0x0, 0x30, 0x90, 0x1c, 0xc2, 0x90, 0x7e, 0x71, 0x91, 0xe5, 0x38, 0x70, 0x3,
+ 0x7a, 0x71, 0x21, 0xe5, 0x38, 0x12, 0x1, 0xa0, 0x5, 0x38, 0x30, 0x2, 0x6,
+ 0xe4, 0x12, 0x9, 0x87, 0xf5, 0x91, 0x30, 0x91, 0xb, 0xc2, 0x91, 0x5, 0x38,
+ 0xe5, 0x38, 0x12, 0x9, 0x87, 0xf5, 0x91, 0xda, 0xb, 0xda, 0x1b, 0xda, 0x2b,
+ 0x32, 0xca, 0xf8, 0x7c, 0xfb, 0xe5, 0x23, 0xb4, 0x81, 0x23, 0x74, 0x2, 0x12,
+ 0xa, 0x5d, 0x4c, 0xff, 0x78, 0x8, 0xa9, 0xc0, 0xca, 0x5e, 0x70, 0xdf, 0x80,
+ 0x6, 0xa9, 0xd0, 0xca, 0x4e, 0x70, 0x20, 0x74, 0x2, 0x12, 0x3, 0xb4, 0x74,
+ 0x2, 0x12, 0xa, 0x5d, 0x80, 0x8, 0xe5, 0x23, 0xb4, 0x80, 0x3, 0x12, 0xc,
+ 0xed, 0xda, 0xf8, 0x22, 0xd2, 0x7, 0x12, 0xd, 0xf4, 0xa9, 0xc2, 0xb4, 0x74,
+ 0x9f, 0x12, 0xe, 0x4d, 0x12, 0xe, 0x34, 0xa9, 0xd2, 0xb4, 0x60, 0x3, 0xb4,
+ 0xff, 0x1a, 0x75, 0x23, 0x81, 0xa9, 0xd5, 0xca, 0xa9, 0xd0, 0xca, 0x75,
+ 0xed, 0x9f, 0x75, 0xad, 0x20, 0xa9, 0xd1, 0xea, 0xa9, 0xc1, 0xea, 0x74, 0x1,
+ 0x2, 0xc, 0x83, 0x22, 0xd2, 0x7, 0x12, 0xd, 0xf4, 0xa9, 0xc2, 0xb4, 0x74,
+ 0x5, 0x12, 0xe, 0x4d, 0x12, 0xe, 0x34, 0x7c, 0xab, 0xa9, 0xd2, 0xb4, 0x5e,
+ 0xa0, 0xe3, 0xa9, 0xc2, 0xb4, 0x74, 0x1, 0x12, 0xe, 0x4d, 0x7c, 0xba, 0x12,
+ 0xe, 0x4d, 0xa9, 0xd2, 0xb4, 0x12, 0x0, 0x2e, 0x40, 0xfb, 0x22, 0x7c, 0xab,
+ 0x7d, 0x12, 0x7c, 0xb3, 0xf5, 0x14, 0x7c, 0x36, 0x7c, 0x25, 0xa, 0x4, 0x7c,
+ 0xb3, 0xf5, 0x13, 0x7c, 0xb7, 0xf5, 0x12, 0xa9, 0xc2, 0xb4, 0x7c, 0xba,
+ 0x12, 0xe, 0x4d, 0xe5, 0x14, 0x12, 0xe, 0x4d, 0xe5, 0x13, 0x12, 0xe, 0x4d,
+ 0xe5, 0x12, 0x2, 0xe, 0x4d, 0x7d, 0x52, 0xf5, 0x15, 0x7c, 0xb6, 0x7c, 0xa5,
+ 0xa, 0x44, 0xf5, 0x14, 0x7f, 0x21, 0xf5, 0x13, 0xa9, 0xc2, 0xb4, 0x74, 0xb,
+ 0x12, 0xe, 0x4d, 0xe5, 0x15, 0x12, 0xe, 0x4d, 0xe5, 0x14, 0x12, 0xe, 0x4d,
+ 0xe5, 0x13, 0x12, 0xe, 0x4d, 0xe4, 0x2, 0xe, 0x4d, 0x12, 0xd, 0xb9, 0x12,
+ 0xb, 0xf, 0xa9, 0xa6, 0x94, 0xb3, 0x92, 0x6, 0x30, 0x6, 0x6, 0x12, 0xe,
+ 0x41, 0x12, 0xc, 0xba, 0x12, 0x8, 0x10, 0x12, 0xe, 0x26, 0xd2, 0xaf, 0x30,
+ 0x3, 0xfd, 0x2, 0xe, 0x75, 0x80, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xe5, 0x3d, 0x70, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7d, 0x23, 0x1b, 0x34, 0x4d, 0x22, 0x78, 0xe0, 0x22, 0xd2,
+ 0xcf, 0x85, 0x3d, 0xcc, 0x75, 0xec, 0xff, 0x75, 0xee, 0xff, 0x75, 0xeb, 0x3,
+ 0x75, 0xac, 0x40, 0xa9, 0xc5, 0xca, 0x75, 0xed, 0xf, 0x75, 0xad, 0xb0, 0xa9,
+ 0xd7, 0x94, 0xa9, 0xd4, 0x94, 0x22, 0xa, 0x27, 0xa, 0x3b, 0x2d, 0x32, 0xbe,
+ 0x34, 0x0, 0xff, 0x78, 0xc, 0xbe, 0xb0, 0x2, 0x40, 0x7, 0xbe, 0xb0, 0xfe,
+ 0x38, 0x2, 0xd3, 0x22, 0xc3, 0x22, 0xa9, 0xc2, 0xb4, 0x30, 0x7, 0x4, 0x74,
+ 0x6, 0x80, 0x2, 0x74, 0x4, 0x12, 0xe, 0x4d, 0xa9, 0xd2, 0xb4, 0x22, 0xe5,
+ 0x32, 0xb4, 0xc, 0xb, 0xc2, 0x86, 0x7e, 0x34, 0x0, 0x64, 0x12, 0xd, 0x96,
+ 0xd2, 0x86, 0x22, 0x12, 0xd, 0x48, 0x7e, 0x35, 0x11, 0x12, 0x0, 0xe, 0xa9,
+ 0xd2, 0xb4, 0xd3, 0x22, 0xc2, 0x8c, 0x43, 0x89, 0x2, 0x75, 0x8c, 0x1, 0x75,
+ 0x8a, 0x0, 0xd2, 0xa9, 0x22, 0x75, 0xb5, 0x0, 0xa9, 0x36, 0xb3, 0xfc, 0xa9,
+ 0xc6, 0xb3, 0xe5, 0xb5, 0x22, 0xd2, 0xc8, 0x75, 0xb3, 0x13, 0xa9, 0xd1,
+ 0xb4, 0xa9, 0xc0, 0xb4, 0x22, 0xf5, 0xb5, 0xa9, 0x36, 0xb3, 0xfc, 0xa9,
+ 0xc6, 0xb3, 0xd3, 0x22, 0x7e, 0x34, 0x0, 0x4, 0x12, 0x9, 0x19, 0x7d, 0x53,
+ 0x22, 0xc2, 0x8c, 0x6d, 0x33, 0x7a, 0x35, 0x19, 0xd2, 0x8c, 0x22, 0x7e,
+ 0x35, 0x19, 0xb, 0x34, 0x7a, 0x35, 0x19, 0x22, 0x85, 0x3d, 0xcc, 0xe5, 0x3d,
+ 0x2, 0xc, 0x83, 0x2, 0xe, 0x6c, 0x0, 0x4, 0x3, 0x16, 0x0, 0x0, 0x9c, 0x0,
+ 0x0, 0x0,
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
index 82079cde849c..4c4d559e0d04 100644
--- a/drivers/input/touchscreen/max11801_ts.c
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -2,7 +2,7 @@
* Driver for MAXI MAX11801 - A Resistive touch screen controller with
* i2c interface
*
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc.
* Author: Zhang Jiejing <jiejing.zhang@freescale.com>
*
* Based on mcs5000_ts.c
@@ -38,6 +38,10 @@
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
/* Register Address define */
#define GENERNAL_STATUS_REG 0x00
@@ -53,13 +57,30 @@
#define AUX_MESURE_CONF_REG 0x0a
#define OP_MODE_CONF_REG 0x0b
+#define Panel_Setup_X (0x69 << 1)
+#define Panel_Setup_Y (0x6b << 1)
+
+#define XY_combined_measurement (0x70 << 1)
+#define X_measurement (0x78 << 1)
+#define Y_measurement (0x7a << 1)
+#define AUX_measurement (0x76 << 1)
+
/* FIFO is found only in max11800 and max11801 */
#define FIFO_RD_CMD (0x50 << 1)
#define MAX11801_FIFO_INT (1 << 2)
#define MAX11801_FIFO_OVERFLOW (1 << 3)
+#define MAX11801_EDGE_INT (1 << 1)
+
+#define FIFO_RD_X_MSB (0x52 << 1)
+#define FIFO_RD_X_LSB (0x53 << 1)
+#define FIFO_RD_Y_MSB (0x54 << 1)
+#define FIFO_RD_Y_LSB (0x55 << 1)
+#define FIFO_RD_AUX_MSB (0x5a << 1)
+#define FIFO_RD_AUX_LSB (0x5b << 1)
#define XY_BUFSIZE 4
#define XY_BUF_OFFSET 4
+#define AUX_BUFSIZE 2
#define MAX11801_MAX_X 0xfff
#define MAX11801_MAX_Y 0xfff
@@ -84,6 +105,64 @@ struct max11801_data {
struct input_dev *input_dev;
};
+static struct i2c_client *max11801_client;
+static unsigned int max11801_workmode;
+static u8 aux_buf[AUX_BUFSIZE];
+
+static int max11801_dcm_write_command(struct i2c_client *client, int command)
+{
+ return i2c_smbus_write_byte(client, command);
+}
+
+static int max11801_dcm_sample_aux(struct i2c_client *client)
+{
+ int ret;
+ int aux = 0;
+ int sample_data;
+
+ /* AUX_measurement */
+ max11801_dcm_write_command(client, AUX_measurement);
+ mdelay(5);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_MSB,
+ 1, &aux_buf[0]);
+ if (ret < 0) {
+ dev_err(&client->dev, "FIFO_RD_AUX_MSB read failed (%d)\n",
+ ret);
+ return ret;
+ }
+ mdelay(5);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_LSB,
+ 1, &aux_buf[1]);
+ if (ret < 0) {
+ dev_err(&client->dev, "FIFO_RD_AUX_LSB read failed (%d)\n",
+ ret);
+ return ret;
+ }
+
+ aux = (aux_buf[0] << 4) + (aux_buf[1] >> 4);
+ /*
+ * voltage = (9170*aux)/7371;
+ * voltage is (26.2*3150*aux)/(16.2*0xFFF)
+ * V(aux)=3150*sample/0xFFF,V(battery)=212*V(aux)/81
+ * sample_data = (14840*aux)/7371-1541;
+ */
+ sample_data = (14840 * aux) / 7371;
+
+ return sample_data;
+}
+
+int max11801_read_adc(void)
+{
+ int adc_data;
+
+ if (!max11801_client)
+ return -ENODEV;
+ adc_data = max11801_dcm_sample_aux(max11801_client);
+
+ return adc_data;
+}
+EXPORT_SYMBOL_GPL(max11801_read_adc);
+
static u8 read_register(struct i2c_client *client, int addr)
{
/* XXX: The chip ignores LSB of register address */
@@ -104,29 +183,62 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
u8 buf[XY_BUFSIZE];
int x = -1;
int y = -1;
+ u8 command = FIFO_RD_X_MSB;
status = read_register(data->client, GENERNAL_STATUS_REG);
-
- if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) {
+ if ((!max11801_workmode && (status & (MAX11801_FIFO_INT |
+ MAX11801_FIFO_OVERFLOW))) || (max11801_workmode && (status &
+ MAX11801_EDGE_INT))) {
status = read_register(data->client, GENERNAL_STATUS_REG);
-
- ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
- XY_BUFSIZE, buf);
-
- /*
- * We should get 4 bytes buffer that contains X,Y
- * and event tag
- */
- if (ret < XY_BUFSIZE)
- goto out;
+ if (!max11801_workmode) {
+ /* ACM mode */
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
+ XY_BUFSIZE, buf);
+ /*
+ * We should get 4 bytes buffer that contains X,Y
+ * and event tag
+ */
+ if (ret < XY_BUFSIZE)
+ goto out;
+ } else {
+ /* DCM mode */
+ /* X = panel setup */
+ max11801_dcm_write_command(client, Panel_Setup_X);
+ /* X_measurement */
+ max11801_dcm_write_command(client, X_measurement);
+ for (i = 0; i < 2; i++) {
+ ret = i2c_smbus_read_i2c_block_data(client,
+ command, 1, &buf[i]);
+ if (ret < 1)
+ goto out;
+
+ command = FIFO_RD_X_LSB;
+ }
+
+ /* Y = panel setup */
+ max11801_dcm_write_command(client, Panel_Setup_Y);
+ /* Y_measurement */
+ max11801_dcm_write_command(client, Y_measurement);
+ command = FIFO_RD_Y_MSB;
+ for (i = 2; i < XY_BUFSIZE; i++) {
+ ret = i2c_smbus_read_i2c_block_data(client,
+ command, 1, &buf[i]);
+ if (ret < 1)
+ goto out;
+
+ command = FIFO_RD_Y_LSB;
+ }
+ }
for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) {
- if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
+ if ((buf[i + 1] & MEASURE_TAG_MASK) ==
+ MEASURE_X_TAG)
x = (buf[i] << XY_BUF_OFFSET) +
- (buf[i + 1] >> XY_BUF_OFFSET);
- else if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
+ (buf[i + 1] >> XY_BUF_OFFSET);
+ else if ((buf[i + 1] & MEASURE_TAG_MASK) ==
+ MEASURE_Y_TAG)
y = (buf[i] << XY_BUF_OFFSET) +
- (buf[i + 1] >> XY_BUF_OFFSET);
+ (buf[i + 1] >> XY_BUF_OFFSET);
}
if ((buf[1] & EVENT_TAG_MASK) != (buf[3] & EVENT_TAG_MASK))
@@ -137,18 +249,17 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
/* fall through */
case EVENT_MIDDLE:
input_report_abs(data->input_dev, ABS_X, x);
+ y = MAX11801_MAX_Y - y; /* Calibration */
input_report_abs(data->input_dev, ABS_Y, y);
input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
input_sync(data->input_dev);
break;
-
case EVENT_RELEASE:
input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
input_sync(data->input_dev);
break;
-
case EVENT_FIFO_END:
- break;
+ break;
}
}
out:
@@ -159,18 +270,37 @@ static void max11801_ts_phy_init(struct max11801_data *data)
{
struct i2c_client *client = data->client;
- /* Average X,Y, take 16 samples, average eight media sample */
+ max11801_client = client;
+ /* Average X,Y, take 16 samples average eight media sample */
max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
/* X,Y panel setup time set to 20us */
max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
- /* Rough pullup time (2uS), Fine pullup time (10us) */
+ /* Rough pullup time (2uS), Fine pullup time (10us) */
max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
- /* Auto mode init period = 5ms , scan period = 5ms*/
+ /* Auto mode init period = 5ms, scan period = 5ms */
max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
/* Aperture X,Y set to +- 4LSB */
max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
- /* Enable Power, enable Automode, enable Aperture, enable Average X,Y */
- max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
+ /*
+ * Enable Power, enable Automode, enable Aperture,
+ * enable Average X,Y
+ */
+ if (!max11801_workmode)
+ max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
+ else {
+ max11801_write_reg(client, OP_MODE_CONF_REG, 0x16);
+ /*
+ * Delay initial=1ms, Sampling time 2us
+ * Averaging sample depth 2
+ * samples, Resolution 12bit
+ */
+ max11801_write_reg(client, AUX_MESURE_CONF_REG, 0x76);
+ /*
+ * Use edge interrupt with
+ * direct conversion mode
+ */
+ max11801_write_reg(client, GENERNAL_CONF_REG, 0xf3);
+ }
}
static int max11801_ts_probe(struct i2c_client *client,
@@ -179,6 +309,7 @@ static int max11801_ts_probe(struct i2c_client *client,
struct max11801_data *data;
struct input_dev *input_dev;
int error;
+ struct device_node *of_node = client->dev.of_node;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
input_dev = devm_input_allocate_device(&client->dev);
@@ -201,6 +332,9 @@ static int max11801_ts_probe(struct i2c_client *client,
input_set_abs_params(input_dev, ABS_Y, 0, MAX11801_MAX_Y, 0, 0);
input_set_drvdata(input_dev, data);
+ if (of_property_read_u32(of_node, "work-mode", &max11801_workmode))
+ max11801_workmode = *(int *)(client->dev).platform_data;
+
max11801_ts_phy_init(data);
error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
@@ -226,9 +360,17 @@ static const struct i2c_device_id max11801_ts_id[] = {
};
MODULE_DEVICE_TABLE(i2c, max11801_ts_id);
+static const struct of_device_id max11801_ts_dt_ids[] = {
+ { .compatible = "maxim,max11801", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, max11801_ts_dt_ids);
+
static struct i2c_driver max11801_ts_driver = {
.driver = {
.name = "max11801_ts",
+ .owner = THIS_MODULE,
+ .of_match_table = max11801_ts_dt_ids,
},
.id_table = max11801_ts_id,
.probe = max11801_ts_probe,
diff --git a/drivers/input/touchscreen/vtl/Makefile b/drivers/input/touchscreen/vtl/Makefile
new file mode 100644
index 000000000000..2ee7f7aefe43
--- /dev/null
+++ b/drivers/input/touchscreen/vtl/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the VTL touchscreen driver.
+#
+
+obj-y += vtl_ts.o
diff --git a/drivers/input/touchscreen/vtl/vtl_ts.c b/drivers/input/touchscreen/vtl/vtl_ts.c
new file mode 100644
index 000000000000..f7bef9e81158
--- /dev/null
+++ b/drivers/input/touchscreen/vtl/vtl_ts.c
@@ -0,0 +1,496 @@
+/*
+ * VTL CTP driver
+ *
+ * Copyright (C) 2013 VTL Corporation
+ * 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.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/pm_qos.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define FORCE_SINGLE_EVENT 1
+
+#include "vtl_ts.h"
+
+#define MIN_X 0x00
+#define MIN_Y 0x00
+#define MAX_X 1023
+#define MAX_Y 767
+#define MAX_AREA 0xff
+#define MAX_FINGERS 2
+
+
+/* Global or static variables */
+struct ts_driver g_driver;
+
+static struct ts_info g_ts = {
+ .driver = &g_driver,
+};
+static struct ts_info *pg_ts = &g_ts;
+
+static struct i2c_device_id vtl_ts_id[] = {
+ { DRIVER_NAME, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, vtl_ts_id);
+
+
+static int vtl_ts_config(struct ts_info *ts)
+{
+ struct device *dev;
+
+ DEBUG();
+
+ dev = &ts->driver->client->dev;
+
+ /* ts config */
+ ts->config_info.touch_point_number = TOUCH_POINT_NUM;
+
+ pr_info("Configuring vtl\n");
+ ts->config_info.screen_max_x = SCREEN_MAX_X;
+ ts->config_info.screen_max_y = SCREEN_MAX_y;
+ return 0;
+}
+
+void vtl_ts_free_gpio(void)
+{
+ struct ts_info *ts;
+
+ ts = pg_ts;
+ DEBUG();
+
+ gpio_free(ts->config_info.irq_gpio_number);
+}
+
+void vtl_ts_hw_reset(void)
+{
+ struct ts_info *ts;
+
+ ts = pg_ts;
+ DEBUG();
+
+ gpio_set_value(ts->config_info.rst_gpio_number, 0);
+ mdelay(50);
+ gpio_set_value(ts->config_info.rst_gpio_number, 1);
+}
+
+static irqreturn_t vtl_ts_irq(int irq, void *dev)
+{
+ struct ts_info *ts;
+
+ ts = pg_ts;
+ DEBUG();
+
+ queue_work(ts->driver->workqueue, &ts->driver->event_work);
+
+ return IRQ_HANDLED;
+}
+
+static union ts_xy_data *vtl_read_xy_data(struct ts_info *ts)
+{
+ struct i2c_msg msgs;
+ int err;
+
+ DEBUG();
+
+ msgs.addr = ts->driver->client->addr;
+ msgs.flags = 0x01;
+ msgs.len = sizeof(ts->xy_data.buf);
+ msgs.buf = ts->xy_data.buf;
+
+ err = i2c_transfer(ts->driver->client->adapter, &msgs, 1);
+ if (err != 1) {
+ pr_err("___%s:i2c read err___\n", __func__);
+ return NULL;
+ }
+ return &ts->xy_data;
+}
+
+static void vtl_report_xy_coord(struct input_dev *input_dev,
+ union ts_xy_data *xy_data,
+ unsigned char touch_point_number)
+{
+ struct ts_info *ts;
+ int id;
+ int sync;
+ int x, y;
+ unsigned int press;
+ static unsigned int release;
+
+ ts = pg_ts;
+ DEBUG();
+
+ /* report points */
+ sync = 0; press = 0;
+ for (id = 0; id < touch_point_number; id++) {
+ if ((xy_data->point[id].xhi != 0xFF) &&
+ (xy_data->point[id].yhi != 0xFF) &&
+ ((xy_data->point[id].status == 1) ||
+ (xy_data->point[id].status == 2))) {
+ x = (xy_data->point[id].xhi<<4) |
+ (xy_data->point[id].xlo&0xF);
+ y = (xy_data->point[id].yhi<<4) |
+ (xy_data->point[id].ylo&0xF);
+
+ if (ts->config_info.exchange_x_y_flag)
+ swap(x, y);
+
+ if (ts->config_info.revert_x_flag)
+ x = ts->config_info.screen_max_x - x;
+
+ if (ts->config_info.revert_y_flag)
+ y = ts->config_info.screen_max_y - y;
+#ifndef FORCE_SINGLE_EVENT
+ input_mt_slot(input_dev, xy_data->point[id].id - 1);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, true);
+ input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 30);
+ input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, 128);
+#else
+ input_report_abs(input_dev, ABS_X, x);
+ input_report_abs(input_dev, ABS_Y, y);
+ input_report_key(input_dev, BTN_TOUCH, 1);
+ input_report_abs(input_dev, ABS_PRESSURE, 1);
+#endif
+ sync = 1;
+ press |= 0x01 << (xy_data->point[id].id - 1);
+ }
+ }
+
+ release &= (release ^ press); /*release point flag */
+ for (id = 0; id < touch_point_number; id++) {
+ if (release & (0x01 << id)) {
+#ifndef FORCE_SINGLE_EVENT
+ input_mt_slot(input_dev, id);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, false);
+#else
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ input_report_abs(input_dev, ABS_PRESSURE, 0);
+#endif
+ sync = 1;
+ }
+
+ }
+ release = press;
+
+ if (sync)
+ input_sync(input_dev);
+}
+
+static void vtl_ts_workfunc(struct work_struct *work)
+{
+
+ union ts_xy_data *xy_data;
+ struct input_dev *input_dev;
+ unsigned char touch_point_number;
+
+ DEBUG();
+
+ input_dev = pg_ts->driver->input_dev;
+ touch_point_number = pg_ts->config_info.touch_point_number;
+
+ xy_data = vtl_read_xy_data(pg_ts);
+ if (xy_data != NULL)
+ vtl_report_xy_coord(input_dev, xy_data, touch_point_number);
+ else
+ pr_err("____xy_data error___\n");
+}
+
+#ifdef CONFIG_PM_SLEEP
+int vtl_ts_suspend(struct device *dev)
+{
+ struct ts_info *ts;
+
+ ts = pg_ts;
+ DEBUG();
+
+ disable_irq(ts->config_info.irq_number);
+ cancel_work_sync(&ts->driver->event_work);
+
+ return 0;
+}
+
+int vtl_ts_resume(struct device *dev)
+{
+ struct ts_info *ts;
+
+ ts = pg_ts;
+ DEBUG();
+
+ /* Hardware reset */
+ vtl_ts_hw_reset();
+ enable_irq(ts->config_info.irq_number);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void vtl_ts_early_suspend(struct early_suspend *handler)
+{
+ struct ts_info *ts;
+
+ ts = pg_ts;
+ DEBUG();
+
+ vtl_ts_suspend(ts->driver->client, PMSG_SUSPEND);
+}
+
+static void vtl_ts_early_resume(struct early_suspend *handler)
+{
+ struct ts_info *ts;
+
+ ts = pg_ts;
+ DEBUG();
+
+ vtl_ts_resume(ts->driver->client);
+}
+#endif
+
+int vtl_ts_remove(struct i2c_client *client)
+{
+ struct ts_info *ts;
+
+ ts = pg_ts;
+ DEBUG();
+
+ /* Driver clean up */
+
+ free_irq(ts->config_info.irq_number, ts);
+ vtl_ts_free_gpio();
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts->driver->early_suspend);
+#endif
+
+ cancel_work_sync(&ts->driver->event_work);
+ destroy_workqueue(ts->driver->workqueue);
+
+ input_unregister_device(ts->driver->input_dev);
+ input_free_device(ts->driver->input_dev);
+
+ if (ts->driver->proc_entry != NULL)
+ remove_proc_entry(DRIVER_NAME, NULL);
+
+ return 0;
+}
+
+static int init_input_dev(struct ts_info *ts)
+{
+ struct input_dev *input_dev;
+ struct device *dev;
+ int err;
+
+ DEBUG();
+
+ dev = &ts->driver->client->dev;
+
+ /* allocate input device */
+ ts->driver->input_dev = devm_input_allocate_device(dev);
+ if (ts->driver->input_dev == NULL) {
+ dev_err(dev, "Unable to allocate input device for device %s\n",
+ DRIVER_NAME);
+ return -1;
+ }
+
+ input_dev = ts->driver->input_dev;
+
+ input_dev->name = "VTL for wld";
+ input_dev->phys = "I2C";
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->id.vendor = 0xaaaa;
+ input_dev->id.product = 0x5555;
+ input_dev->id.version = 0x0001;
+ input_dev->dev.parent = dev;
+
+ /* config input device */
+ __set_bit(EV_SYN, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(EV_ABS, input_dev->evbit);
+
+#ifdef FORCE_SINGLE_EVENT
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, MIN_X, MAX_X, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, MIN_Y, MAX_Y, 0, 0);
+#else
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ input_mt_init_slots(input_dev, TOUCH_POINT_NUM, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+ ts->config_info.screen_max_x, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+ ts->config_info.screen_max_y, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+#endif
+ /* register input device */
+ err = input_register_device(input_dev);
+ if (err) {
+ dev_err(dev, "Unable to register input device for device %s\n",
+ DRIVER_NAME);
+ return -1;
+ }
+
+ return 0;
+}
+
+int ct36x_test_tp(struct i2c_client *client)
+{
+ struct i2c_msg msgs;
+ char buf;
+
+ msgs.addr = 0x7F;
+ msgs.flags = 0x01;
+ msgs.len = 1;
+ msgs.buf = &buf;
+
+ if (i2c_transfer(client->adapter, &msgs, 1) != 1)
+ return -1;
+
+ return 0;
+}
+
+int vtl_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int err = -1;
+ struct ts_info *ts;
+ struct device *dev;
+
+ ts = pg_ts;
+ ts->driver->client = client;
+ dev = &ts->driver->client->dev;
+
+ /*Probing TouchScreen*/
+ pr_info("Probing vtl touchscreen, touchscreen node found\n");
+ if (ct36x_test_tp(client) < 0) {
+ pr_err("vtl tp not found\n");
+ goto ERR_TS_CONFIG;
+ }
+
+ /* Request platform resources (gpio/interrupt pins) */
+ err = vtl_ts_config(ts);
+ if (err) {
+ dev_err(dev, "VTL touch screen config Failed.\n");
+ goto ERR_TS_CONFIG;
+ }
+
+ /*Requestion GPIO*/
+ ts->config_info.rst_gpio_number = of_get_gpio(client->dev.of_node, 0);
+ if (gpio_is_valid(ts->config_info.rst_gpio_number)) {
+ err = devm_gpio_request(dev,
+ ts->config_info.rst_gpio_number, NULL);
+ if (err) {
+ dev_err(dev, "Unable to request GPIO %d\n",
+ ts->config_info.rst_gpio_number);
+ return err;
+ }
+ }
+
+ /* Check I2C Functionality */
+ err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
+ if (!err) {
+ dev_err(dev, "Check I2C Functionality Failed.\n");
+ return -ENODEV;
+ }
+
+ err = devm_request_threaded_irq(dev, client->irq,
+ NULL, vtl_ts_irq,
+ IRQF_ONESHOT,
+ client->name, ts);
+ if (err) {
+ dev_err(&client->dev, "VTL Failed to register interrupt\n");
+
+ goto ERR_IRQ_REQ;
+ }
+
+ vtl_ts_hw_reset();
+
+ /*init input dev*/
+ err = init_input_dev(ts);
+ if (err) {
+
+ dev_err(dev, "init input dev failed.\n");
+ goto ERR_INIT_INPUT;
+ }
+
+ /* register early suspend */
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->driver->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ts->driver->early_suspend.suspend = vtl_ts_early_suspend;
+ ts->driver->early_suspend.resume = vtl_ts_early_resume;
+ register_early_suspend(&ts->driver->early_suspend);
+#endif
+ /* Create work queue */
+ INIT_WORK(&ts->driver->event_work, vtl_ts_workfunc);
+ ts->driver->workqueue = create_singlethread_workqueue(DRIVER_NAME);
+
+ return 0;
+
+ERR_IRQ_REQ:
+ cancel_work_sync(&ts->driver->event_work);
+ destroy_workqueue(ts->driver->workqueue);
+
+ERR_INIT_INPUT:
+ input_free_device(ts->driver->input_dev);
+ gpio_free(ts->config_info.rst_gpio_number);
+ERR_TS_CONFIG:
+
+ return err;
+}
+
+
+static SIMPLE_DEV_PM_OPS(vtl_ts_pm_ops, vtl_ts_suspend, vtl_ts_resume);
+
+static const struct of_device_id vtl_ts_dt_ids[] = {
+ { .compatible = "vtl,ct365", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, vtl_ts_dt_ids);
+
+
+static struct i2c_driver vtl_ts_driver = {
+ .probe = vtl_ts_probe,
+ .remove = vtl_ts_remove,
+ .id_table = vtl_ts_id,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .pm = &vtl_ts_pm_ops,
+ .of_match_table = of_match_ptr(vtl_ts_dt_ids),
+ },
+};
+
+module_i2c_driver(vtl_ts_driver);
+
+MODULE_AUTHOR("VTL");
+MODULE_DESCRIPTION("VTL TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/vtl/vtl_ts.h b/drivers/input/touchscreen/vtl/vtl_ts.h
new file mode 100644
index 000000000000..9f61565d6639
--- /dev/null
+++ b/drivers/input/touchscreen/vtl/vtl_ts.h
@@ -0,0 +1,181 @@
+/*
+ * VTL CTP driver
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc
+ *
+ * Using code from:
+ * - github.com/qdk0901/q98_source:drivers/input/touchscreen/vtl/vtl_ts.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#ifndef _TS_CORE_H_
+#define _TS_CORE_H_
+
+#include <linux/gpio.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+
+#ifdef TS_DEBUG
+#define DEBUG() pr_debug("___%s___\n", __func__)
+#else
+#define DEBUG()
+#endif
+
+
+/* platform define */
+#define COMMON 0x01 /* Samsung,Freescale,Amlogic,actions */
+#define ROCKCHIP 0X02
+#define ALLWINER 0X03
+#define MTK 0X04
+
+/* vtl touch IC define */
+#define CT36X 0x01
+#define CT360 0x02
+
+/* xy data protocol */
+#define OLD_PROTOCOL 0x01
+#define NEW_PROTOCOL 0x02
+
+
+/* vtl ts driver config */
+
+/*platform config*/
+#define PLATFORM COMMON
+
+/*vtl ts driver name*/
+#define DRIVER_NAME "vtl_ts"
+
+/*vtl chip ID*/
+#define CHIP_ID CT36X
+
+#define XY_DATA_PROTOCOL NEW_PROTOCOL
+
+
+/* maybe not use,please refer to the function
+ * vtl_ts_config() in the file "vtl_ts.c"
+ */
+#define SCREEN_MAX_X 1024
+#define SCREEN_MAX_y 600
+
+#define TS_IRQ_GPIO_NUM /* RK30_PIN4_PC2 */
+#define TS_RST_GPIO_NUM /* RK30_PIN4_PD0 */
+#define TS_I2C_SPEED 400000 /* for rockchip */
+
+
+/* priate define and declare */
+#if (CHIP_ID == CT360)
+#define TOUCH_POINT_NUM 1
+#elif (CHIP_ID == CT36X)
+#define TOUCH_POINT_NUM 1
+#endif
+
+
+#if (CHIP_ID == CT360)
+struct xy_data {
+#if (XY_DATA_PROTOCOL == OLD_PROTOCOL)
+ unsigned char status:4; /* Action information, 1:Down;
+ 2: Move; 3: Up */
+ unsigned char id:4; /* ID information, from 1 to
+ CFG_MAX_POINT_NUM */
+#endif
+ unsigned char xhi; /* X coordinate Hi */
+ unsigned char yhi; /* Y coordinate Hi */
+ unsigned char ylo:4; /* Y coordinate Lo */
+ unsigned char xlo:4; /* X coordinate Lo */
+#if (XY_DATA_PROTOCOL == NEW_PROTOCOL)
+ unsigned char status:4; /* Action information, 1: Down;
+ 2: Move; 3: Up */
+ unsigned char id:4; /* ID information, from 1 to
+ CFG_MAX_POINT_NUM */
+#endif
+};
+#else
+struct xy_data {
+#if (XY_DATA_PROTOCOL == OLD_PROTOCOL)
+ unsigned char status:3; /* Action information, 1: Down;
+ 2: Move; 3: Up */
+ unsigned char id:5; /* ID information, from 1 to
+ CFG_MAX_POINT_NUM */
+#endif
+ unsigned char xhi; /* X coordinate Hi */
+ unsigned char yhi; /* Y coordinate Hi */
+ unsigned char ylo:4; /* Y coordinate Lo */
+ unsigned char xlo:4; /* X coordinate Lo */
+#if (XY_DATA_PROTOCOL == NEW_PROTOCOL)
+ unsigned char status:3; /* Action information, 1: Down;
+ 2: Move; 3: Up */
+ unsigned char id:5; /* ID information, from 1 to
+ CFG_MAX_POINT_NUM */
+#endif
+ unsigned char area; /* Touch area */
+ unsigned char pressure; /* Touch Pressure */
+};
+#endif
+
+
+union ts_xy_data {
+ struct xy_data point[TOUCH_POINT_NUM];
+ unsigned char buf[TOUCH_POINT_NUM * sizeof(struct xy_data)];
+};
+
+
+struct ts_driver {
+
+ struct i2c_client *client;
+
+ /* input devices */
+ struct input_dev *input_dev;
+
+ struct proc_dir_entry *proc_entry;
+
+ /* Work thread settings */
+ struct work_struct event_work;
+ struct workqueue_struct *workqueue;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+};
+
+struct ts_config_info {
+
+ unsigned int screen_max_x;
+ unsigned int screen_max_y;
+ unsigned int irq_gpio_number;
+ unsigned int irq_number;
+ unsigned int rst_gpio_number;
+ unsigned char touch_point_number;
+ unsigned char ctp_used;
+ unsigned char i2c_bus_number;
+ unsigned char revert_x_flag;
+ unsigned char revert_y_flag;
+ unsigned char exchange_x_y_flag;
+ int (*tp_enter_init)(void);
+ void (*tp_exit_init)(int state);
+};
+
+
+struct ts_chip_info {
+ unsigned char chip_id;
+};
+
+struct ts_info {
+
+ struct ts_driver *driver;
+ struct ts_config_info config_info;
+ struct ts_chip_info chip_info;
+ union ts_xy_data xy_data;
+};
+
+#endif
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 5ff803efdc03..8579ec170b70 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -114,6 +114,22 @@ config VIDEO_S3C_CAMIF
To compile this driver as a module, choose M here: the module
will be called s3c-camif.
+config VIDEO_MXC_OUTPUT
+ tristate "MXC Video For Linux Video Output"
+ depends on VIDEO_DEV && ARCH_MXC && FB_MXC
+ select VIDEOBUF_DMA_CONTIG
+ ---help---
+ This is the video4linux2 output driver based on MXC module.
+
+config VIDEO_MXC_CAPTURE
+ tristate "MXC Video For Linux Video Capture"
+ depends on VIDEO_V4L2
+ ---help---
+ This is the video4linux2 capture driver based on i.MX video-in module.
+
+source "drivers/media/platform/mxc/capture/Kconfig"
+source "drivers/media/platform/mxc/output/Kconfig"
+source "drivers/media/platform/mxc/subdev/Kconfig"
source "drivers/media/platform/soc_camera/Kconfig"
source "drivers/media/platform/exynos4-is/Kconfig"
source "drivers/media/platform/am437x/Kconfig"
@@ -134,6 +150,7 @@ config VIDEO_TI_CAL
In TI Technical Reference Manual this module is referred as
Camera Interface Subsystem (CAMSS).
+
endif # V4L_PLATFORM_DRIVERS
menuconfig V4L_MEM2MEM_DRIVERS
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 40b18d12726e..b9245205ad0e 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -61,6 +61,12 @@ obj-$(CONFIG_VIDEO_RCAR_VIN) += rcar-vin/
obj-$(CONFIG_VIDEO_ATMEL_ISC) += atmel/
+obj-$(CONFIG_VIDEO_MXC_OUTPUT) += mxc/output/
+
+obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc/capture/
+obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc/subdev/
+obj-$(CONFIG_VIDEO_MXC_OUTPUT) += mxc/output/
+
ccflags-y += -I$(srctree)/drivers/media/i2c
obj-$(CONFIG_VIDEO_MEDIATEK_VPU) += mtk-vpu/
diff --git a/drivers/media/platform/mxc/capture/Kconfig b/drivers/media/platform/mxc/capture/Kconfig
new file mode 100644
index 000000000000..1edd5bd65fa6
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/Kconfig
@@ -0,0 +1,83 @@
+if VIDEO_MXC_CAPTURE
+config VIDEO_V4L2_MXC_INT_DEVICE
+ tristate
+
+menu "MXC Camera/V4L2 PRP Features support"
+config VIDEO_MXC_IPU_CAMERA
+ bool
+ select VIDEO_V4L2_MXC_INT_DEVICE
+ depends on VIDEO_MXC_CAPTURE && MXC_IPU
+ default y
+
+config MXC_CAMERA_OV5640
+ tristate "OmniVision ov5640 camera support"
+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C
+ ---help---
+ If you plan to use the ov5640 Camera with your MXC system, say Y here.
+
+config MXC_CAMERA_OV5642
+ tristate "OmniVision ov5642 camera support"
+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C
+ ---help---
+ If you plan to use the ov5642 Camera with your MXC system, say Y here.
+
+config MXC_CAMERA_OV5640_MIPI
+ tristate "OmniVision ov5640 camera support using mipi"
+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C && MXC_MIPI_CSI2
+ ---help---
+ If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here.
+
+config MXC_TVIN_ADV7180
+ tristate "Analog Device adv7180 TV Decoder Input support"
+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C
+ ---help---
+ If you plan to use the adv7180 video decoder with your MXC system, say Y here.
+
+choice
+ prompt "Select Overlay Rounting"
+ default MXC_IPU_DEVICE_QUEUE_SDC
+ depends on VIDEO_MXC_IPU_CAMERA && FB_MXC_SYNC_PANEL
+
+config MXC_IPU_DEVICE_QUEUE_SDC
+ tristate "Queue ipu device for overlay library"
+ depends on VIDEO_MXC_IPU_CAMERA
+ ---help---
+ Use case CSI->MEM->IPU DEVICE->SDC:
+ Images from sensor will be frist recieved in memory,then
+ queue to ipu device for processing if needed, and displaying
+ it on synchronous display with SDC use case.
+
+config MXC_IPU_PRP_VF_SDC
+ bool "Pre-Processor VF SDC library"
+ depends on VIDEO_MXC_IPU_CAMERA
+ ---help---
+ Use case PRP_VF_SDC:
+ Preprocessing image from smart sensor for viewfinder and
+ displaying it on synchronous display with SDC use case.
+ If SDC BG is selected, Rotation will not be supported.
+ CSI -> IC (PRP VF) -> MEM
+ MEM -> IC (ROT) -> MEM
+ MEM -> SDC (FG/BG)
+
+endchoice
+
+config MXC_IPU_PRP_ENC
+ tristate "Pre-processor Encoder library"
+ depends on VIDEO_MXC_IPU_CAMERA
+ default y
+ ---help---
+ Use case PRP_ENC:
+ Preprocessing image from smart sensor for encoder.
+ CSI -> IC (PRP ENC) -> MEM
+
+config MXC_IPU_CSI_ENC
+ tristate "IPU CSI Encoder library"
+ depends on VIDEO_MXC_IPU_CAMERA
+ default y
+ ---help---
+ Use case IPU_CSI_ENC:
+ Get raw image with CSI from smart sensor for encoder.
+ CSI -> MEM
+endmenu
+
+endif
diff --git a/drivers/media/platform/mxc/capture/Makefile b/drivers/media/platform/mxc/capture/Makefile
new file mode 100644
index 000000000000..6c04faf70800
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/Makefile
@@ -0,0 +1,21 @@
+ifeq ($(CONFIG_VIDEO_MXC_IPU_CAMERA),y)
+ obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc_v4l2_capture.o
+ obj-$(CONFIG_MXC_IPU_PRP_VF_SDC) += ipu_prp_vf_sdc.o ipu_prp_vf_sdc_bg.o
+ obj-$(CONFIG_MXC_IPU_DEVICE_QUEUE_SDC) += ipu_fg_overlay_sdc.o ipu_bg_overlay_sdc.o
+ obj-$(CONFIG_MXC_IPU_PRP_ENC) += ipu_prp_enc.o ipu_still.o
+ obj-$(CONFIG_MXC_IPU_CSI_ENC) += ipu_csi_enc.o ipu_still.o
+endif
+
+ov5640_camera_int-objs := ov5640.o
+obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera_int.o
+
+ov5642_camera-objs := ov5642.o
+obj-$(CONFIG_MXC_CAMERA_OV5642) += ov5642_camera.o
+
+ov5640_camera_mipi_int-objs := ov5640_mipi.o
+obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi_int.o
+
+adv7180_tvin-objs := adv7180.o
+obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o
+
+obj-$(CONFIG_VIDEO_V4L2_MXC_INT_DEVICE) += v4l2-int-device.o
diff --git a/drivers/media/platform/mxc/capture/adv7180.c b/drivers/media/platform/mxc/capture/adv7180.c
new file mode 100644
index 000000000000..abd615927a48
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/adv7180.c
@@ -0,0 +1,1380 @@
+/*
+ * Copyright 2005-2014 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 adv7180.c
+ *
+ * @brief Analog Device ADV7180 video decoder functions
+ *
+ * @ingroup Camera
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.h"
+
+#define ADV7180_VOLTAGE_ANALOG 1800000
+#define ADV7180_VOLTAGE_DIGITAL_CORE 1800000
+#define ADV7180_VOLTAGE_DIGITAL_IO 3300000
+#define ADV7180_VOLTAGE_PLL 1800000
+
+static struct regulator *dvddio_regulator;
+static struct regulator *dvdd_regulator;
+static struct regulator *avdd_regulator;
+static struct regulator *pvdd_regulator;
+static int pwn_gpio;
+
+static int adv7180_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *id);
+static int adv7180_detach(struct i2c_client *client);
+
+static const struct i2c_device_id adv7180_id[] = {
+ {"adv7180", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, adv7180_id);
+
+static struct i2c_driver adv7180_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "adv7180",
+ },
+ .probe = adv7180_probe,
+ .remove = adv7180_detach,
+ .id_table = adv7180_id,
+};
+
+/*!
+ * Maintains the information on the current state of the sensor.
+ */
+struct sensor {
+ struct sensor_data sen;
+ v4l2_std_id std_id;
+} adv7180_data;
+
+
+/*! List of input video formats supported. The video formats is corresponding
+ * with v4l2 id in video_fmt_t
+ */
+typedef enum {
+ ADV7180_NTSC = 0, /*!< Locked on (M) NTSC video signal. */
+ ADV7180_PAL, /*!< (B, G, H, I, N)PAL video signal. */
+ ADV7180_NOT_LOCKED, /*!< Not locked on a signal. */
+} video_fmt_idx;
+
+/*! Number of video standards supported (including 'not locked' signal). */
+#define ADV7180_STD_MAX (ADV7180_PAL + 1)
+
+/*! Video format structure. */
+typedef struct {
+ int v4l2_id; /*!< Video for linux ID. */
+ char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */
+ u16 raw_width; /*!< Raw width. */
+ u16 raw_height; /*!< Raw height. */
+ u16 active_width; /*!< Active width. */
+ u16 active_height; /*!< Active height. */
+ int frame_rate; /*!< Frame rate. */
+} video_fmt_t;
+
+/*! Description of video formats supported.
+ *
+ * PAL: raw=720x625, active=720x576.
+ * NTSC: raw=720x525, active=720x480.
+ */
+static video_fmt_t video_fmts[] = {
+ { /*! NTSC */
+ .v4l2_id = V4L2_STD_NTSC,
+ .name = "NTSC",
+ .raw_width = 720, /* SENS_FRM_WIDTH */
+ .raw_height = 525, /* SENS_FRM_HEIGHT */
+ .active_width = 720, /* ACT_FRM_WIDTH plus 1 */
+ .active_height = 480, /* ACT_FRM_WIDTH plus 1 */
+ .frame_rate = 30,
+ },
+ { /*! (B, G, H, I, N) PAL */
+ .v4l2_id = V4L2_STD_PAL,
+ .name = "PAL",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ .frame_rate = 25,
+ },
+ { /*! Unlocked standard */
+ .v4l2_id = V4L2_STD_ALL,
+ .name = "Autodetect",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ .frame_rate = 0,
+ },
+};
+
+/*!* Standard index of ADV7180. */
+static video_fmt_idx video_idx = ADV7180_PAL;
+
+/*! @brief This mutex is used to provide mutual exclusion.
+ *
+ * Create a mutex that can be used to provide mutually exclusive
+ * read/write access to the globally accessible data structures
+ * and variables that were defined above.
+ */
+static DEFINE_MUTEX(mutex);
+
+#define IF_NAME "adv7180"
+#define ADV7180_INPUT_CTL 0x00 /* Input Control */
+#define ADV7180_STATUS_1 0x10 /* Status #1 */
+#define ADV7180_BRIGHTNESS 0x0a /* Brightness */
+#define ADV7180_IDENT 0x11 /* IDENT */
+#define ADV7180_VSYNC_FIELD_CTL_1 0x31 /* VSYNC Field Control #1 */
+#define ADV7180_MANUAL_WIN_CTL 0x3d /* Manual Window Control */
+#define ADV7180_SD_SATURATION_CB 0xe3 /* SD Saturation Cb */
+#define ADV7180_SD_SATURATION_CR 0xe4 /* SD Saturation Cr */
+#define ADV7180_PWR_MNG 0x0f /* Power Management */
+
+/* supported controls */
+/* This hasn't been fully implemented yet.
+ * This is how it should work, though. */
+static struct v4l2_queryctrl adv7180_qctrl[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0, /* check this value */
+ .maximum = 255, /* check this value */
+ .step = 1, /* check this value */
+ .default_value = 127, /* check this value */
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0, /* check this value */
+ .maximum = 255, /* check this value */
+ .step = 0x1, /* check this value */
+ .default_value = 127, /* check this value */
+ .flags = 0,
+ }
+};
+
+static inline void adv7180_power_down(int enable)
+{
+ gpio_set_value_cansleep(pwn_gpio, !enable);
+ msleep(2);
+}
+
+static int adv7180_regulator_enable(struct device *dev)
+{
+ int ret = 0;
+
+ dvddio_regulator = devm_regulator_get(dev, "DOVDD");
+
+ if (!IS_ERR(dvddio_regulator)) {
+ regulator_set_voltage(dvddio_regulator,
+ ADV7180_VOLTAGE_DIGITAL_IO,
+ ADV7180_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(dvddio_regulator);
+ if (ret) {
+ dev_err(dev, "set io voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set io voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get io voltage\n");
+ }
+
+ dvdd_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(dvdd_regulator)) {
+ regulator_set_voltage(dvdd_regulator,
+ ADV7180_VOLTAGE_DIGITAL_CORE,
+ ADV7180_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(dvdd_regulator);
+ if (ret) {
+ dev_err(dev, "set core voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set core voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get core voltage\n");
+ }
+
+ avdd_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(avdd_regulator)) {
+ regulator_set_voltage(avdd_regulator,
+ ADV7180_VOLTAGE_ANALOG,
+ ADV7180_VOLTAGE_ANALOG);
+ ret = regulator_enable(avdd_regulator);
+ if (ret) {
+ dev_err(dev, "set analog voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set analog voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get analog voltage\n");
+ }
+
+ pvdd_regulator = devm_regulator_get(dev, "PVDD");
+ if (!IS_ERR(pvdd_regulator)) {
+ regulator_set_voltage(pvdd_regulator,
+ ADV7180_VOLTAGE_PLL,
+ ADV7180_VOLTAGE_PLL);
+ ret = regulator_enable(pvdd_regulator);
+ if (ret) {
+ dev_err(dev, "set pll voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set pll voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get pll voltage\n");
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************
+ * I2C transfert.
+ ***********************************************************************/
+
+/*! Read one register from a ADV7180 i2c slave device.
+ *
+ * @param *reg register in the device we wish to access.
+ *
+ * @return 0 if success, an error code otherwise.
+ */
+static inline int adv7180_read(u8 reg)
+{
+ int val;
+
+ val = i2c_smbus_read_byte_data(adv7180_data.sen.i2c_client, reg);
+ if (val < 0) {
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:read reg error: reg=%2x\n", __func__, reg);
+ return -1;
+ }
+ return val;
+}
+
+/*! Write one register of a ADV7180 i2c slave device.
+ *
+ * @param *reg register in the device we wish to access.
+ *
+ * @return 0 if success, an error code otherwise.
+ */
+static int adv7180_write_reg(u8 reg, u8 val)
+{
+ s32 ret;
+
+ ret = i2c_smbus_write_byte_data(adv7180_data.sen.i2c_client, reg, val);
+ if (ret < 0) {
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:write reg error:reg=%2x,val=%2x\n", __func__,
+ reg, val);
+ return -1;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * mxc_v4l2_capture interface.
+ ***********************************************************************/
+
+/*!
+ * Return attributes of current video standard.
+ * Since this device autodetects the current standard, this function also
+ * sets the values that need to be changed if the standard changes.
+ * There is no set std equivalent function.
+ *
+ * @return None.
+ */
+static void adv7180_get_std(v4l2_std_id *std)
+{
+ int status_1, standard, idx;
+ bool locked;
+
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_get_std\n");
+
+ status_1 = adv7180_read(ADV7180_STATUS_1);
+ locked = status_1 & 0x1;
+ standard = status_1 & 0x70;
+
+ mutex_lock(&mutex);
+ *std = V4L2_STD_ALL;
+ idx = ADV7180_NOT_LOCKED;
+ if (locked) {
+ if (standard == 0x40) {
+ *std = V4L2_STD_PAL;
+ idx = ADV7180_PAL;
+ } else if (standard == 0) {
+ *std = V4L2_STD_NTSC;
+ idx = ADV7180_NTSC;
+ }
+ }
+ mutex_unlock(&mutex);
+
+ /* This assumes autodetect which this device uses. */
+ if (*std != adv7180_data.std_id) {
+ video_idx = idx;
+ adv7180_data.std_id = *std;
+ adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width;
+ adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height;
+ }
+}
+
+/***********************************************************************
+ * IOCTL Functions from v4l2_int_ioctl_desc.
+ ***********************************************************************/
+
+/*!
+ * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num
+ * s: pointer to standard V4L2 device structure
+ * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure
+ *
+ * Gets slave interface parameters.
+ * Calculates the required xclk value to support the requested
+ * clock parameters in p. This value is returned in the p
+ * parameter.
+ *
+ * vidioc_int_g_ifparm returns platform-specific information about the
+ * interface settings used by the sensor.
+ *
+ * Called on open.
+ */
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_ifparm\n");
+
+ if (s == NULL) {
+ pr_err(" ERROR!! no slave device set!\n");
+ return -1;
+ }
+
+ /* Initialize structure to 0s then set any non-0 values. */
+ memset(p, 0, sizeof(*p));
+ p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.nobt_hs_inv = 1;
+ p->u.bt656.bt_sync_correct = 1;
+
+ /* ADV7180 has a dedicated clock so no clock settings needed. */
+
+ return 0;
+}
+
+/*!
+ * Sets the camera power.
+ *
+ * s pointer to the camera device
+ * on if 1, power is to be turned on. 0 means power is to be turned off
+ *
+ * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num
+ * @s: pointer to standard V4L2 device structure
+ * @on: power state to which device is to be set
+ *
+ * Sets devices power state to requrested state, if possible.
+ * This is called on open, close, suspend and resume.
+ */
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ struct sensor *sensor = s->priv;
+
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_s_power\n");
+
+ if (on && !sensor->sen.on) {
+ if (adv7180_write_reg(ADV7180_PWR_MNG, 0x04) != 0)
+ return -EIO;
+
+ /*
+ * FIXME:Additional 400ms to wait the chip to be stable?
+ * This is a workaround for preview scrolling issue.
+ */
+ msleep(400);
+ } else if (!on && sensor->sen.on) {
+ if (adv7180_write_reg(ADV7180_PWR_MNG, 0x24) != 0)
+ return -EIO;
+ }
+
+ sensor->sen.on = on;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor *sensor = s->priv;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_parm\n");
+
+ switch (a->type) {
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->sen.streamcap.capability;
+ cparm->timeperframe = sensor->sen.streamcap.timeperframe;
+ cparm->capturemode = sensor->sen.streamcap.capturemode;
+ break;
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ break;
+
+ default:
+ pr_debug("ioctl_g_parm:type is unknown %d\n", a->type);
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ *
+ * This driver cannot change these settings.
+ */
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_parm\n");
+
+ switch (a->type) {
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+ struct sensor *sensor = s->priv;
+
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_fmt_cap\n");
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pr_debug(" Returning size of %dx%d\n",
+ sensor->sen.pix.width, sensor->sen.pix.height);
+ f->fmt.pix = sensor->sen.pix;
+ break;
+
+ case V4L2_BUF_TYPE_PRIVATE: {
+ v4l2_std_id std;
+ adv7180_get_std(&std);
+ f->fmt.pix.pixelformat = (u32)std;
+ }
+ break;
+
+ default:
+ f->fmt.pix = sensor->sen.pix;
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control information
+ * from the video_control[] array. Otherwise, returns -EINVAL if the
+ * control is not supported.
+ */
+static int ioctl_queryctrl(struct v4l2_int_device *s,
+ struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_queryctrl\n");
+
+ for (i = 0; i < ARRAY_SIZE(adv7180_qctrl); i++)
+ if (qc->id && qc->id == adv7180_qctrl[i].id) {
+ memcpy(qc, &(adv7180_qctrl[i]),
+ sizeof(*qc));
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array. Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int ret = 0;
+ int sat = 0;
+
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n");
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_BRIGHTNESS\n");
+ adv7180_data.sen.brightness = adv7180_read(ADV7180_BRIGHTNESS);
+ vc->value = adv7180_data.sen.brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_CONTRAST\n");
+ vc->value = adv7180_data.sen.contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_SATURATION\n");
+ sat = adv7180_read(ADV7180_SD_SATURATION_CB);
+ adv7180_data.sen.saturation = sat;
+ vc->value = adv7180_data.sen.saturation;
+ break;
+ case V4L2_CID_HUE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_HUE\n");
+ vc->value = adv7180_data.sen.hue;
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_DO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_RED_BALANCE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_RED_BALANCE\n");
+ vc->value = adv7180_data.sen.red;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_BLUE_BALANCE\n");
+ vc->value = adv7180_data.sen.blue;
+ break;
+ case V4L2_CID_GAMMA:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_GAMMA\n");
+ break;
+ case V4L2_CID_EXPOSURE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_EXPOSURE\n");
+ vc->value = adv7180_data.sen.ae_mode;
+ break;
+ case V4L2_CID_AUTOGAIN:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTOGAIN\n");
+ break;
+ case V4L2_CID_GAIN:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_GAIN\n");
+ break;
+ case V4L2_CID_HFLIP:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_HFLIP\n");
+ break;
+ case V4L2_CID_VFLIP:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_VFLIP\n");
+ break;
+ default:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " Default case\n");
+ vc->value = 0;
+ ret = -EPERM;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array). Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int retval = 0;
+ u8 tmp;
+
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n");
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_BRIGHTNESS\n");
+ tmp = vc->value;
+ adv7180_write_reg(ADV7180_BRIGHTNESS, tmp);
+ adv7180_data.sen.brightness = vc->value;
+ break;
+ case V4L2_CID_CONTRAST:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_CONTRAST\n");
+ break;
+ case V4L2_CID_SATURATION:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_SATURATION\n");
+ tmp = vc->value;
+ adv7180_write_reg(ADV7180_SD_SATURATION_CB, tmp);
+ adv7180_write_reg(ADV7180_SD_SATURATION_CR, tmp);
+ adv7180_data.sen.saturation = vc->value;
+ break;
+ case V4L2_CID_HUE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_HUE\n");
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_DO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_RED_BALANCE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_RED_BALANCE\n");
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_BLUE_BALANCE\n");
+ break;
+ case V4L2_CID_GAMMA:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_GAMMA\n");
+ break;
+ case V4L2_CID_EXPOSURE:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_EXPOSURE\n");
+ break;
+ case V4L2_CID_AUTOGAIN:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTOGAIN\n");
+ break;
+ case V4L2_CID_GAIN:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_GAIN\n");
+ break;
+ case V4L2_CID_HFLIP:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_HFLIP\n");
+ break;
+ case V4L2_CID_VFLIP:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " V4L2_CID_VFLIP\n");
+ break;
+ default:
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ " Default case\n");
+ retval = -EPERM;
+ break;
+ }
+
+ return retval;
+}
+
+/*!
+ * ioctl_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_framesizes(struct v4l2_int_device *s,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index >= 1)
+ return -EINVAL;
+
+ fsize->discrete.width = video_fmts[video_idx].active_width;
+ fsize->discrete.height = video_fmts[video_idx].active_height;
+
+ return 0;
+}
+
+/*!
+ * ioctl_enum_frameintervals - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
+ struct v4l2_frmivalenum *fival)
+{
+ video_fmt_t fmt;
+ int i;
+
+ if (fival->index != 0)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(video_fmts) - 1; i++) {
+ fmt = video_fmts[i];
+ if (fival->width == fmt.active_width &&
+ fival->height == fmt.active_height) {
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1;
+ fival->discrete.denominator = fmt.frame_rate;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ * VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+ ((struct v4l2_dbg_chip_ident *)id)->match.type =
+ V4L2_CHIP_MATCH_I2C_DRIVER;
+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
+ "adv7180_decoder");
+ ((struct v4l2_dbg_chip_ident *)id)->ident = V4L2_IDENT_ADV7180;
+
+ return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_init\n");
+ return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_dev_init\n");
+ return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module.
+ */
+static struct v4l2_int_ioctl_desc adv7180_ioctl_desc[] = {
+
+ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init},
+
+ /*!
+ * Delinitialise the dev. at slave detach.
+ * The complement of ioctl_dev_init.
+ */
+/* {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *)ioctl_dev_exit}, */
+
+ {vidioc_int_s_power_num, (v4l2_int_ioctl_func*)ioctl_s_power},
+ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*)ioctl_g_ifparm},
+/* {vidioc_int_g_needs_reset_num,
+ (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */
+/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */
+ {vidioc_int_init_num, (v4l2_int_ioctl_func*)ioctl_init},
+
+ /*!
+ * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
+ */
+/* {vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap}, */
+
+ /*!
+ * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.
+ * This ioctl is used to negotiate the image capture size and
+ * pixel format without actually making it take effect.
+ */
+/* {vidioc_int_try_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */
+
+ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*)ioctl_g_fmt_cap},
+
+ /*!
+ * If the requested format is supported, configures the HW to use that
+ * format, returns error code if format not supported or HW can't be
+ * correctly configured.
+ */
+/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */
+
+ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm},
+ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm},
+ {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func*)ioctl_queryctrl},
+ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*)ioctl_g_ctrl},
+ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl},
+ {vidioc_int_enum_framesizes_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_framesizes},
+ {vidioc_int_enum_frameintervals_num,
+ (v4l2_int_ioctl_func *)
+ ioctl_enum_frameintervals},
+ {vidioc_int_g_chip_ident_num,
+ (v4l2_int_ioctl_func *)ioctl_g_chip_ident},
+};
+
+static struct v4l2_int_slave adv7180_slave = {
+ .ioctls = adv7180_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(adv7180_ioctl_desc),
+};
+
+static struct v4l2_int_device adv7180_int_device = {
+ .module = THIS_MODULE,
+ .name = "adv7180",
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &adv7180_slave,
+ },
+};
+
+
+/***********************************************************************
+ * I2C client and driver.
+ ***********************************************************************/
+
+/*! ADV7180 Reset function.
+ *
+ * @return None.
+ */
+static void adv7180_hard_reset(bool cvbs)
+{
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "In adv7180:adv7180_hard_reset\n");
+
+ if (cvbs) {
+ /* Set CVBS input on AIN1 */
+ adv7180_write_reg(ADV7180_INPUT_CTL, 0x00);
+ } else {
+ /*
+ * Set YPbPr input on AIN1,4,5 and normal
+ * operations(autodection of all stds).
+ */
+ adv7180_write_reg(ADV7180_INPUT_CTL, 0x09);
+ }
+
+ /* Datasheet recommends */
+ adv7180_write_reg(0x01, 0xc8);
+ adv7180_write_reg(0x02, 0x04);
+ adv7180_write_reg(0x03, 0x00);
+ adv7180_write_reg(0x04, 0x45);
+ adv7180_write_reg(0x05, 0x00);
+ adv7180_write_reg(0x06, 0x02);
+ adv7180_write_reg(0x07, 0x7F);
+ adv7180_write_reg(0x08, 0x80);
+ adv7180_write_reg(0x0A, 0x00);
+ adv7180_write_reg(0x0B, 0x00);
+ adv7180_write_reg(0x0C, 0x36);
+ adv7180_write_reg(0x0D, 0x7C);
+ adv7180_write_reg(0x0E, 0x00);
+ adv7180_write_reg(0x0F, 0x00);
+ adv7180_write_reg(0x13, 0x00);
+ adv7180_write_reg(0x14, 0x12);
+ adv7180_write_reg(0x15, 0x00);
+ adv7180_write_reg(0x16, 0x00);
+ adv7180_write_reg(0x17, 0x01);
+ adv7180_write_reg(0x18, 0x93);
+ adv7180_write_reg(0xF1, 0x19);
+ adv7180_write_reg(0x1A, 0x00);
+ adv7180_write_reg(0x1B, 0x00);
+ adv7180_write_reg(0x1C, 0x00);
+ adv7180_write_reg(0x1D, 0x40);
+ adv7180_write_reg(0x1E, 0x00);
+ adv7180_write_reg(0x1F, 0x00);
+ adv7180_write_reg(0x20, 0x00);
+ adv7180_write_reg(0x21, 0x00);
+ adv7180_write_reg(0x22, 0x00);
+ adv7180_write_reg(0x23, 0xC0);
+ adv7180_write_reg(0x24, 0x00);
+ adv7180_write_reg(0x25, 0x00);
+ adv7180_write_reg(0x26, 0x00);
+ adv7180_write_reg(0x27, 0x58);
+ adv7180_write_reg(0x28, 0x00);
+ adv7180_write_reg(0x29, 0x00);
+ adv7180_write_reg(0x2A, 0x00);
+ adv7180_write_reg(0x2B, 0xE1);
+ adv7180_write_reg(0x2C, 0xAE);
+ adv7180_write_reg(0x2D, 0xF4);
+ adv7180_write_reg(0x2E, 0x00);
+ adv7180_write_reg(0x2F, 0xF0);
+ adv7180_write_reg(0x30, 0x00);
+ adv7180_write_reg(0x31, 0x12);
+ adv7180_write_reg(0x32, 0x41);
+ adv7180_write_reg(0x33, 0x84);
+ adv7180_write_reg(0x34, 0x00);
+ adv7180_write_reg(0x35, 0x02);
+ adv7180_write_reg(0x36, 0x00);
+ adv7180_write_reg(0x37, 0x01);
+ adv7180_write_reg(0x38, 0x80);
+ adv7180_write_reg(0x39, 0xC0);
+ adv7180_write_reg(0x3A, 0x10);
+ adv7180_write_reg(0x3B, 0x05);
+ adv7180_write_reg(0x3C, 0x58);
+ adv7180_write_reg(0x3D, 0xB2);
+ adv7180_write_reg(0x3E, 0x64);
+ adv7180_write_reg(0x3F, 0xE4);
+ adv7180_write_reg(0x40, 0x90);
+ adv7180_write_reg(0x41, 0x01);
+ adv7180_write_reg(0x42, 0x7E);
+ adv7180_write_reg(0x43, 0xA4);
+ adv7180_write_reg(0x44, 0xFF);
+ adv7180_write_reg(0x45, 0xB6);
+ adv7180_write_reg(0x46, 0x12);
+ adv7180_write_reg(0x48, 0x00);
+ adv7180_write_reg(0x49, 0x00);
+ adv7180_write_reg(0x4A, 0x00);
+ adv7180_write_reg(0x4B, 0x00);
+ adv7180_write_reg(0x4C, 0x00);
+ adv7180_write_reg(0x4D, 0xEF);
+ adv7180_write_reg(0x4E, 0x08);
+ adv7180_write_reg(0x4F, 0x08);
+ adv7180_write_reg(0x50, 0x08);
+ adv7180_write_reg(0x51, 0x24);
+ adv7180_write_reg(0x52, 0x0B);
+ adv7180_write_reg(0x53, 0x4E);
+ adv7180_write_reg(0x54, 0x80);
+ adv7180_write_reg(0x55, 0x00);
+ adv7180_write_reg(0x56, 0x10);
+ adv7180_write_reg(0x57, 0x00);
+ adv7180_write_reg(0x58, 0x00);
+ adv7180_write_reg(0x59, 0x00);
+ adv7180_write_reg(0x5A, 0x00);
+ adv7180_write_reg(0x5B, 0x00);
+ adv7180_write_reg(0x5C, 0x00);
+ adv7180_write_reg(0x5D, 0x00);
+ adv7180_write_reg(0x5E, 0x00);
+ adv7180_write_reg(0x5F, 0x00);
+ adv7180_write_reg(0x60, 0x00);
+ adv7180_write_reg(0x61, 0x00);
+ adv7180_write_reg(0x62, 0x20);
+ adv7180_write_reg(0x63, 0x00);
+ adv7180_write_reg(0x64, 0x00);
+ adv7180_write_reg(0x65, 0x00);
+ adv7180_write_reg(0x66, 0x00);
+ adv7180_write_reg(0x67, 0x03);
+ adv7180_write_reg(0x68, 0x01);
+ adv7180_write_reg(0x69, 0x00);
+ adv7180_write_reg(0x6A, 0x00);
+ adv7180_write_reg(0x6B, 0xC0);
+ adv7180_write_reg(0x6C, 0x00);
+ adv7180_write_reg(0x6D, 0x00);
+ adv7180_write_reg(0x6E, 0x00);
+ adv7180_write_reg(0x6F, 0x00);
+ adv7180_write_reg(0x70, 0x00);
+ adv7180_write_reg(0x71, 0x00);
+ adv7180_write_reg(0x72, 0x00);
+ adv7180_write_reg(0x73, 0x10);
+ adv7180_write_reg(0x74, 0x04);
+ adv7180_write_reg(0x75, 0x01);
+ adv7180_write_reg(0x76, 0x00);
+ adv7180_write_reg(0x77, 0x3F);
+ adv7180_write_reg(0x78, 0xFF);
+ adv7180_write_reg(0x79, 0xFF);
+ adv7180_write_reg(0x7A, 0xFF);
+ adv7180_write_reg(0x7B, 0x1E);
+ adv7180_write_reg(0x7C, 0xC0);
+ adv7180_write_reg(0x7D, 0x00);
+ adv7180_write_reg(0x7E, 0x00);
+ adv7180_write_reg(0x7F, 0x00);
+ adv7180_write_reg(0x80, 0x00);
+ adv7180_write_reg(0x81, 0xC0);
+ adv7180_write_reg(0x82, 0x04);
+ adv7180_write_reg(0x83, 0x00);
+ adv7180_write_reg(0x84, 0x0C);
+ adv7180_write_reg(0x85, 0x02);
+ adv7180_write_reg(0x86, 0x03);
+ adv7180_write_reg(0x87, 0x63);
+ adv7180_write_reg(0x88, 0x5A);
+ adv7180_write_reg(0x89, 0x08);
+ adv7180_write_reg(0x8A, 0x10);
+ adv7180_write_reg(0x8B, 0x00);
+ adv7180_write_reg(0x8C, 0x40);
+ adv7180_write_reg(0x8D, 0x00);
+ adv7180_write_reg(0x8E, 0x40);
+ adv7180_write_reg(0x8F, 0x00);
+ adv7180_write_reg(0x90, 0x00);
+ adv7180_write_reg(0x91, 0x50);
+ adv7180_write_reg(0x92, 0x00);
+ adv7180_write_reg(0x93, 0x00);
+ adv7180_write_reg(0x94, 0x00);
+ adv7180_write_reg(0x95, 0x00);
+ adv7180_write_reg(0x96, 0x00);
+ adv7180_write_reg(0x97, 0xF0);
+ adv7180_write_reg(0x98, 0x00);
+ adv7180_write_reg(0x99, 0x00);
+ adv7180_write_reg(0x9A, 0x00);
+ adv7180_write_reg(0x9B, 0x00);
+ adv7180_write_reg(0x9C, 0x00);
+ adv7180_write_reg(0x9D, 0x00);
+ adv7180_write_reg(0x9E, 0x00);
+ adv7180_write_reg(0x9F, 0x00);
+ adv7180_write_reg(0xA0, 0x00);
+ adv7180_write_reg(0xA1, 0x00);
+ adv7180_write_reg(0xA2, 0x00);
+ adv7180_write_reg(0xA3, 0x00);
+ adv7180_write_reg(0xA4, 0x00);
+ adv7180_write_reg(0xA5, 0x00);
+ adv7180_write_reg(0xA6, 0x00);
+ adv7180_write_reg(0xA7, 0x00);
+ adv7180_write_reg(0xA8, 0x00);
+ adv7180_write_reg(0xA9, 0x00);
+ adv7180_write_reg(0xAA, 0x00);
+ adv7180_write_reg(0xAB, 0x00);
+ adv7180_write_reg(0xAC, 0x00);
+ adv7180_write_reg(0xAD, 0x00);
+ adv7180_write_reg(0xAE, 0x60);
+ adv7180_write_reg(0xAF, 0x00);
+ adv7180_write_reg(0xB0, 0x00);
+ adv7180_write_reg(0xB1, 0x60);
+ adv7180_write_reg(0xB2, 0x1C);
+ adv7180_write_reg(0xB3, 0x54);
+ adv7180_write_reg(0xB4, 0x00);
+ adv7180_write_reg(0xB5, 0x00);
+ adv7180_write_reg(0xB6, 0x00);
+ adv7180_write_reg(0xB7, 0x13);
+ adv7180_write_reg(0xB8, 0x03);
+ adv7180_write_reg(0xB9, 0x33);
+ adv7180_write_reg(0xBF, 0x02);
+ adv7180_write_reg(0xC0, 0x00);
+ adv7180_write_reg(0xC1, 0x00);
+ adv7180_write_reg(0xC2, 0x00);
+ adv7180_write_reg(0xC3, 0x00);
+ adv7180_write_reg(0xC4, 0x00);
+ adv7180_write_reg(0xC5, 0x81);
+ adv7180_write_reg(0xC6, 0x00);
+ adv7180_write_reg(0xC7, 0x00);
+ adv7180_write_reg(0xC8, 0x00);
+ adv7180_write_reg(0xC9, 0x04);
+ adv7180_write_reg(0xCC, 0x69);
+ adv7180_write_reg(0xCD, 0x00);
+ adv7180_write_reg(0xCE, 0x01);
+ adv7180_write_reg(0xCF, 0xB4);
+ adv7180_write_reg(0xD0, 0x00);
+ adv7180_write_reg(0xD1, 0x10);
+ adv7180_write_reg(0xD2, 0xFF);
+ adv7180_write_reg(0xD3, 0xFF);
+ adv7180_write_reg(0xD4, 0x7F);
+ adv7180_write_reg(0xD5, 0x7F);
+ adv7180_write_reg(0xD6, 0x3E);
+ adv7180_write_reg(0xD7, 0x08);
+ adv7180_write_reg(0xD8, 0x3C);
+ adv7180_write_reg(0xD9, 0x08);
+ adv7180_write_reg(0xDA, 0x3C);
+ adv7180_write_reg(0xDB, 0x9B);
+ adv7180_write_reg(0xDC, 0xAC);
+ adv7180_write_reg(0xDD, 0x4C);
+ adv7180_write_reg(0xDE, 0x00);
+ adv7180_write_reg(0xDF, 0x00);
+ adv7180_write_reg(0xE0, 0x14);
+ adv7180_write_reg(0xE1, 0x80);
+ adv7180_write_reg(0xE2, 0x80);
+ adv7180_write_reg(0xE3, 0x80);
+ adv7180_write_reg(0xE4, 0x80);
+ adv7180_write_reg(0xE5, 0x25);
+ adv7180_write_reg(0xE6, 0x44);
+ adv7180_write_reg(0xE7, 0x63);
+ adv7180_write_reg(0xE8, 0x65);
+ adv7180_write_reg(0xE9, 0x14);
+ adv7180_write_reg(0xEA, 0x63);
+ adv7180_write_reg(0xEB, 0x55);
+ adv7180_write_reg(0xEC, 0x55);
+ adv7180_write_reg(0xEE, 0x00);
+ adv7180_write_reg(0xEF, 0x4A);
+ adv7180_write_reg(0xF0, 0x44);
+ adv7180_write_reg(0xF1, 0x0C);
+ adv7180_write_reg(0xF2, 0x32);
+ adv7180_write_reg(0xF3, 0x00);
+ adv7180_write_reg(0xF4, 0x3F);
+ adv7180_write_reg(0xF5, 0xE0);
+ adv7180_write_reg(0xF6, 0x69);
+ adv7180_write_reg(0xF7, 0x10);
+ adv7180_write_reg(0xF8, 0x00);
+ adv7180_write_reg(0xF9, 0x03);
+ adv7180_write_reg(0xFA, 0xFA);
+ adv7180_write_reg(0xFB, 0x40);
+}
+
+/*! ADV7180 I2C attach function.
+ *
+ * @param *adapter struct i2c_adapter *.
+ *
+ * @return Error code indicating success or failure.
+ */
+
+/*!
+ * ADV7180 I2C probe function.
+ * Function set in i2c_driver struct.
+ * Called by insmod.
+ *
+ * @param *adapter I2C adapter descriptor.
+ *
+ * @return Error code indicating success or failure.
+ */
+static int adv7180_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rev_id;
+ int ret = 0;
+ u32 cvbs = true;
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+
+ printk(KERN_ERR"DBG sensor data is at %p\n", &adv7180_data);
+
+ /* ov5640 pinctrl */
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(dev, "setup pinctrl failed\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio)) {
+ dev_err(dev, "no sensor pwdn pin available\n");
+ return -ENODEV;
+ }
+ ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "adv7180_pwdn");
+ if (ret < 0) {
+ dev_err(dev, "no power pin available!\n");
+ return ret;
+ }
+
+ adv7180_regulator_enable(dev);
+
+ adv7180_power_down(0);
+
+ msleep(1);
+
+ /* Set initial values for the sensor struct. */
+ memset(&adv7180_data, 0, sizeof(adv7180_data));
+ adv7180_data.sen.i2c_client = client;
+ adv7180_data.sen.streamcap.timeperframe.denominator = 30;
+ adv7180_data.sen.streamcap.timeperframe.numerator = 1;
+ adv7180_data.std_id = V4L2_STD_ALL;
+ video_idx = ADV7180_NOT_LOCKED;
+ adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width;
+ adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height;
+ adv7180_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */
+ adv7180_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */
+ adv7180_data.sen.on = true;
+
+ adv7180_data.sen.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(adv7180_data.sen.sensor_clk)) {
+ dev_err(dev, "get mclk failed\n");
+ return PTR_ERR(adv7180_data.sen.sensor_clk);
+ }
+
+ ret = of_property_read_u32(dev->of_node, "mclk",
+ &adv7180_data.sen.mclk);
+ if (ret) {
+ dev_err(dev, "mclk frequency is invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(
+ dev->of_node, "mclk_source",
+ (u32 *) &(adv7180_data.sen.mclk_source));
+ if (ret) {
+ dev_err(dev, "mclk_source invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "csi_id",
+ &(adv7180_data.sen.csi));
+ if (ret) {
+ dev_err(dev, "csi_id invalid\n");
+ return ret;
+ }
+
+ clk_prepare_enable(adv7180_data.sen.sensor_clk);
+
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:adv7180 probe i2c address is 0x%02X\n",
+ __func__, adv7180_data.sen.i2c_client->addr);
+
+ /*! Read the revision ID of the tvin chip */
+ rev_id = adv7180_read(ADV7180_IDENT);
+ dev_dbg(dev,
+ "%s:Analog Device adv7%2X0 detected!\n", __func__,
+ rev_id);
+
+ ret = of_property_read_u32(dev->of_node, "cvbs", &(cvbs));
+ if (ret) {
+ dev_err(dev, "cvbs setting is not found\n");
+ cvbs = true;
+ }
+
+ /*! ADV7180 initialization. */
+ adv7180_hard_reset(cvbs);
+
+ pr_debug(" type is %d (expect %d)\n",
+ adv7180_int_device.type, v4l2_int_type_slave);
+ pr_debug(" num ioctls is %d\n",
+ adv7180_int_device.u.slave->num_ioctls);
+
+ /* This function attaches this structure to the /dev/video0 device.
+ * The pointer in priv points to the adv7180_data structure here.*/
+ adv7180_int_device.priv = &adv7180_data;
+ ret = v4l2_int_device_register(&adv7180_int_device);
+
+ clk_disable_unprepare(adv7180_data.sen.sensor_clk);
+
+ return ret;
+}
+
+/*!
+ * ADV7180 I2C detach function.
+ * Called on rmmod.
+ *
+ * @param *client struct i2c_client*.
+ *
+ * @return Error code indicating success or failure.
+ */
+static int adv7180_detach(struct i2c_client *client)
+{
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:Removing %s video decoder @ 0x%02X from adapter %s\n",
+ __func__, IF_NAME, client->addr << 1, client->adapter->name);
+
+ /* Power down via i2c */
+ adv7180_write_reg(ADV7180_PWR_MNG, 0x24);
+
+ if (dvddio_regulator)
+ regulator_disable(dvddio_regulator);
+
+ if (dvdd_regulator)
+ regulator_disable(dvdd_regulator);
+
+ if (avdd_regulator)
+ regulator_disable(avdd_regulator);
+
+ if (pvdd_regulator)
+ regulator_disable(pvdd_regulator);
+
+ v4l2_int_device_unregister(&adv7180_int_device);
+
+ return 0;
+}
+
+/*!
+ * ADV7180 init function.
+ * Called on insmod.
+ *
+ * @return Error code indicating success or failure.
+ */
+static __init int adv7180_init(void)
+{
+ u8 err = 0;
+
+ pr_debug("In adv7180_init\n");
+
+ /* Tells the i2c driver what functions to call for this driver. */
+ err = i2c_add_driver(&adv7180_i2c_driver);
+ if (err != 0)
+ pr_err("%s:driver registration failed, error=%d\n",
+ __func__, err);
+
+ return err;
+}
+
+/*!
+ * ADV7180 cleanup function.
+ * Called on rmmod.
+ *
+ * @return Error code indicating success or failure.
+ */
+static void __exit adv7180_clean(void)
+{
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_clean\n");
+ i2c_del_driver(&adv7180_i2c_driver);
+}
+
+module_init(adv7180_init);
+module_exit(adv7180_clean);
+
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("Anolog Device ADV7180 video decoder driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c b/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c
new file mode 100644
index 000000000000..193cbd5ec0f7
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c
@@ -0,0 +1,552 @@
+
+/*
+ * Copyright 2004-2015 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 ipu_bg_overlay_sdc_bg.c
+ *
+ * @brief IPU Use case for PRP-VF back-ground
+ *
+ * @ingroup IPU
+ */
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/ipu.h>
+#include <linux/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+static int csi_buffer_num;
+static u32 bpp, csi_mem_bufsize = 3;
+static u32 out_format;
+static struct ipu_soc *disp_ipu;
+static u32 offset;
+
+static void csi_buf_work_func(struct work_struct *work)
+{
+ int err = 0;
+ cam_data *cam =
+ container_of(work, struct _cam_data, csi_work_struct);
+
+ struct ipu_task task;
+ memset(&task, 0, sizeof(task));
+
+ if (csi_buffer_num)
+ task.input.paddr = cam->vf_bufs[0];
+ else
+ task.input.paddr = cam->vf_bufs[1];
+ task.input.width = cam->crop_current.width;
+ task.input.height = cam->crop_current.height;
+ task.input.format = IPU_PIX_FMT_UYVY;
+
+ task.output.paddr = offset;
+ task.output.width = cam->overlay_fb->var.xres;
+ task.output.height = cam->overlay_fb->var.yres;
+ task.output.format = out_format;
+ task.output.rotate = cam->rotation;
+ task.output.crop.pos.x = cam->win.w.left;
+ task.output.crop.pos.y = cam->win.w.top;
+ if (cam->win.w.width > 1024 || cam->win.w.height > 1024) {
+ task.output.crop.w = cam->overlay_fb->var.xres;
+ task.output.crop.h = cam->overlay_fb->var.yres;
+ } else {
+ task.output.crop.w = cam->win.w.width;
+ task.output.crop.h = cam->win.w.height;
+ }
+again:
+ err = ipu_check_task(&task);
+ if (err != IPU_CHECK_OK) {
+ if (err > IPU_CHECK_ERR_MIN) {
+ if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) {
+ task.input.crop.w -= 8;
+ goto again;
+ }
+ if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) {
+ task.input.crop.h -= 8;
+ goto again;
+ }
+ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) {
+ task.output.width -= 8;
+ task.output.crop.w = task.output.width;
+ goto again;
+ }
+ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) {
+ task.output.height -= 8;
+ task.output.crop.h = task.output.height;
+ goto again;
+ }
+ printk(KERN_ERR "check ipu taks fail\n");
+ return;
+ }
+ printk(KERN_ERR "check ipu taks fail\n");
+ return;
+ }
+ err = ipu_queue_task(&task);
+ if (err < 0)
+ printk(KERN_ERR "queue ipu task error\n");
+}
+
+static void get_disp_ipu(cam_data *cam)
+{
+ if (cam->output > 2)
+ disp_ipu = ipu_get_soc(1); /* using DISP4 */
+ else
+ disp_ipu = ipu_get_soc(0);
+}
+
+
+/*!
+ * csi ENC callback function.
+ *
+ * @param irq int irq line
+ * @param dev_id void * device id
+ *
+ * @return status IRQ_HANDLED for handled
+ */
+static irqreturn_t csi_enc_callback(int irq, void *dev_id)
+{
+ cam_data *cam = (cam_data *) dev_id;
+ ipu_channel_t chan = (irq == IPU_IRQ_CSI0_OUT_EOF) ?
+ CSI_MEM0 : CSI_MEM1;
+
+ ipu_select_buffer(cam->ipu, chan,
+ IPU_OUTPUT_BUFFER, csi_buffer_num);
+ schedule_work(&cam->csi_work_struct);
+ csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0;
+ return IRQ_HANDLED;
+}
+
+static int csi_enc_setup(cam_data *cam)
+{
+ ipu_channel_params_t params;
+ u32 pixel_fmt;
+ int err = 0, sensor_protocol = 0;
+ ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ if (!cam) {
+ printk(KERN_ERR "cam private is NULL\n");
+ return -ENXIO;
+ }
+
+ memset(&params, 0, sizeof(ipu_channel_params_t));
+ params.csi_mem.csi = cam->csi;
+
+ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
+ switch (sensor_protocol) {
+ case IPU_CSI_CLK_MODE_GATED_CLK:
+ case IPU_CSI_CLK_MODE_NONGATED_CLK:
+ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
+ params.csi_mem.interlaced = false;
+ break;
+ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
+ params.csi_mem.interlaced = true;
+ break;
+ default:
+ printk(KERN_ERR "sensor protocol unsupported\n");
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id) {
+ params.csi_mem.mipi_en = true;
+ params.csi_mem.mipi_vc =
+ mipi_csi2_get_virtual_channel(mipi_csi2_info);
+ params.csi_mem.mipi_id =
+ mipi_csi2_get_datatype(mipi_csi2_info);
+
+ mipi_csi2_pixelclk_enable(mipi_csi2_info);
+ } else {
+ params.csi_mem.mipi_en = false;
+ params.csi_mem.mipi_vc = 0;
+ params.csi_mem.mipi_id = 0;
+ }
+ } else {
+ params.csi_mem.mipi_en = false;
+ params.csi_mem.mipi_vc = 0;
+ params.csi_mem.mipi_id = 0;
+ }
+ }
+#endif
+
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0],
+ (dma_addr_t) cam->vf_bufs[0]);
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1],
+ (dma_addr_t) cam->vf_bufs[1]);
+ }
+ csi_mem_bufsize =
+ cam->crop_current.width * cam->crop_current.height * 2;
+ cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize);
+ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
+ cam->vf_bufs_size[0],
+ (dma_addr_t *) &
+ cam->vf_bufs[0],
+ GFP_DMA |
+ GFP_KERNEL);
+ if (cam->vf_bufs_vaddr[0] == NULL) {
+ printk(KERN_ERR "Error to allocate vf buffer\n");
+ err = -ENOMEM;
+ goto out_2;
+ }
+ cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize);
+ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
+ cam->vf_bufs_size[1],
+ (dma_addr_t *) &
+ cam->vf_bufs[1],
+ GFP_DMA |
+ GFP_KERNEL);
+ if (cam->vf_bufs_vaddr[1] == NULL) {
+ printk(KERN_ERR "Error to allocate vf buffer\n");
+ err = -ENOMEM;
+ goto out_1;
+ }
+ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
+
+ err = ipu_init_channel(cam->ipu, chan, &params);
+ if (err != 0) {
+ printk(KERN_ERR "ipu_init_channel %d\n", err);
+ goto out_1;
+ }
+
+ pixel_fmt = IPU_PIX_FMT_UYVY;
+ err = ipu_init_channel_buffer(
+ cam->ipu, chan, IPU_OUTPUT_BUFFER, pixel_fmt,
+ cam->crop_current.width, cam->crop_current.height,
+ cam->crop_current.width, IPU_ROTATE_NONE,
+ cam->vf_bufs[0], cam->vf_bufs[1], 0,
+ cam->offset.u_offset, cam->offset.u_offset);
+ if (err != 0) {
+ printk(KERN_ERR "CSI_MEM output buffer\n");
+ goto out_1;
+ }
+ err = ipu_enable_channel(cam->ipu, chan);
+ if (err < 0) {
+ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
+ goto out_1;
+ }
+
+ csi_buffer_num = 0;
+
+ ipu_select_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER, 0);
+ ipu_select_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER, 1);
+ return err;
+out_1:
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0],
+ (dma_addr_t) cam->vf_bufs[0]);
+ cam->vf_bufs_vaddr[0] = NULL;
+ cam->vf_bufs[0] = 0;
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1],
+ (dma_addr_t) cam->vf_bufs[1]);
+ cam->vf_bufs_vaddr[1] = NULL;
+ cam->vf_bufs[1] = 0;
+ }
+out_2:
+ return err;
+}
+
+/*!
+ * Enable encoder task
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int csi_enc_enabling_tasks(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+
+ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi);
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi,
+ csi_enc_callback, 0, "Mxc Camera", cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error registering CSI_OUT_EOF irq\n");
+ return err;
+ }
+
+ INIT_WORK(&cam->csi_work_struct, csi_buf_work_func);
+
+ err = csi_enc_setup(cam);
+ if (err != 0) {
+ printk(KERN_ERR "csi_enc_setup %d\n", err);
+ goto out1;
+ }
+
+ return err;
+out1:
+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);
+ return err;
+}
+
+/*!
+ * bg_overlay_start - start the overlay task
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ */
+static int bg_overlay_start(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+
+ if (!cam) {
+ printk(KERN_ERR "private is NULL\n");
+ return -EIO;
+ }
+
+ if (cam->overlay_active == true) {
+ pr_debug("already start.\n");
+ return 0;
+ }
+
+ get_disp_ipu(cam);
+
+ out_format = cam->v4l2_fb.fmt.pixelformat;
+ if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) {
+ bpp = 3, csi_mem_bufsize = 3;
+ pr_info("BGR24\n");
+ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) {
+ bpp = 2, csi_mem_bufsize = 2;
+ pr_info("RGB565\n");
+ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) {
+ bpp = 4, csi_mem_bufsize = 4;
+ pr_info("BGR32\n");
+ } else {
+ printk(KERN_ERR
+ "unsupported fix format from the framebuffer.\n");
+ return -EINVAL;
+ }
+
+ offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top +
+ csi_mem_bufsize * cam->win.w.left;
+
+ if (cam->v4l2_fb.base == 0)
+ printk(KERN_ERR "invalid frame buffer address.\n");
+ else
+ offset += (u32) cam->v4l2_fb.base;
+
+ csi_mem_bufsize = cam->win.w.width * cam->win.w.height
+ * csi_mem_bufsize;
+
+ err = csi_enc_enabling_tasks(cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error csi enc enable fail\n");
+ return err;
+ }
+
+ cam->overlay_active = true;
+ return err;
+}
+
+/*!
+ * bg_overlay_stop - stop the overlay task
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ */
+static int bg_overlay_stop(void *private)
+{
+ int err = 0;
+ cam_data *cam = (cam_data *) private;
+ ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ if (cam->overlay_active == false)
+ return 0;
+
+ err = ipu_disable_channel(cam->ipu, chan, true);
+
+ ipu_uninit_channel(cam->ipu, chan);
+
+ csi_buffer_num = 0;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id)
+ mipi_csi2_pixelclk_disable(mipi_csi2_info);
+ }
+ }
+#endif
+
+ flush_work(&cam->csi_work_struct);
+ cancel_work_sync(&cam->csi_work_struct);
+
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
+ cam->vf_bufs_vaddr[0] = NULL;
+ cam->vf_bufs[0] = 0;
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
+ cam->vf_bufs_vaddr[1] = NULL;
+ cam->vf_bufs[1] = 0;
+ }
+ if (cam->rot_vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->rot_vf_buf_size[0],
+ cam->rot_vf_bufs_vaddr[0],
+ cam->rot_vf_bufs[0]);
+ cam->rot_vf_bufs_vaddr[0] = NULL;
+ cam->rot_vf_bufs[0] = 0;
+ }
+ if (cam->rot_vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->rot_vf_buf_size[1],
+ cam->rot_vf_bufs_vaddr[1],
+ cam->rot_vf_bufs[1]);
+ cam->rot_vf_bufs_vaddr[1] = NULL;
+ cam->rot_vf_bufs[1] = 0;
+ }
+
+ cam->overlay_active = false;
+ return err;
+}
+
+/*!
+ * Enable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int bg_overlay_enable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int bg_overlay_disable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ /* free csi eof irq firstly.
+ * when disable csi, wait for idmac eof.
+ * it requests eof irq again */
+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);
+
+ return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select bg as the working path
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ * @return status
+ */
+int bg_overlay_sdc_select(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ if (cam) {
+ cam->vf_start_sdc = bg_overlay_start;
+ cam->vf_stop_sdc = bg_overlay_stop;
+ cam->vf_enable_csi = bg_overlay_enable_csi;
+ cam->vf_disable_csi = bg_overlay_disable_csi;
+ cam->overlay_active = false;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(bg_overlay_sdc_select);
+
+/*!
+ * function to de-select bg as the working path
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ * @return status
+ */
+int bg_overlay_sdc_deselect(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ if (cam) {
+ cam->vf_start_sdc = NULL;
+ cam->vf_stop_sdc = NULL;
+ cam->vf_enable_csi = NULL;
+ cam->vf_disable_csi = NULL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(bg_overlay_sdc_deselect);
+
+/*!
+ * Init background overlay task.
+ *
+ * @return Error code indicating success or failure
+ */
+__init int bg_overlay_sdc_init(void)
+{
+ return 0;
+}
+
+/*!
+ * Deinit background overlay task.
+ *
+ * @return Error code indicating success or failure
+ */
+void __exit bg_overlay_sdc_exit(void)
+{
+}
+
+module_init(bg_overlay_sdc_init);
+module_exit(bg_overlay_sdc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_csi_enc.c b/drivers/media/platform/mxc/capture/ipu_csi_enc.c
new file mode 100644
index 000000000000..3a824a9659e7
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ipu_csi_enc.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2009-2015 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 ipu_csi_enc.c
+ *
+ * @brief CSI Use case for video capture
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/ipu.h>
+#include <linux/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+#ifdef CAMERA_DBG
+ #define CAMERA_TRACE(x) (printk)x
+#else
+ #define CAMERA_TRACE(x)
+#endif
+
+/*
+ * Function definitions
+ */
+
+/*!
+ * csi ENC callback function.
+ *
+ * @param irq int irq line
+ * @param dev_id void * device id
+ *
+ * @return status IRQ_HANDLED for handled
+ */
+static irqreturn_t csi_enc_callback(int irq, void *dev_id)
+{
+ cam_data *cam = (cam_data *) dev_id;
+
+ if (cam->enc_callback == NULL)
+ return IRQ_HANDLED;
+
+ cam->enc_callback(irq, dev_id);
+ return IRQ_HANDLED;
+}
+
+/*!
+ * CSI ENC enable channel setup function
+ *
+ * @param cam struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int csi_enc_setup(cam_data *cam)
+{
+ ipu_channel_params_t params;
+ u32 pixel_fmt;
+ int err = 0, sensor_protocol = 0;
+ dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
+ ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ CAMERA_TRACE("In csi_enc_setup\n");
+ if (!cam) {
+ printk(KERN_ERR "cam private is NULL\n");
+ return -ENXIO;
+ }
+
+ memset(&params, 0, sizeof(ipu_channel_params_t));
+ params.csi_mem.csi = cam->csi;
+
+ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
+ switch (sensor_protocol) {
+ case IPU_CSI_CLK_MODE_GATED_CLK:
+ case IPU_CSI_CLK_MODE_NONGATED_CLK:
+ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
+ params.csi_mem.interlaced = false;
+ break;
+ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
+ params.csi_mem.interlaced = true;
+ break;
+ default:
+ printk(KERN_ERR "sensor protocol unsupported\n");
+ return -EINVAL;
+ }
+
+ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
+ pixel_fmt = IPU_PIX_FMT_YUV420P;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420)
+ pixel_fmt = IPU_PIX_FMT_YVU420P;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
+ pixel_fmt = IPU_PIX_FMT_YUV422P;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
+ pixel_fmt = IPU_PIX_FMT_UYVY;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pixel_fmt = IPU_PIX_FMT_YUYV;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
+ pixel_fmt = IPU_PIX_FMT_NV12;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
+ pixel_fmt = IPU_PIX_FMT_BGR24;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
+ pixel_fmt = IPU_PIX_FMT_RGB24;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
+ pixel_fmt = IPU_PIX_FMT_RGB565;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
+ pixel_fmt = IPU_PIX_FMT_BGR32;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
+ pixel_fmt = IPU_PIX_FMT_RGB32;
+ else {
+ printk(KERN_ERR "format not supported\n");
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id) {
+ params.csi_mem.mipi_en = true;
+ params.csi_mem.mipi_vc =
+ mipi_csi2_get_virtual_channel(mipi_csi2_info);
+ params.csi_mem.mipi_id =
+ mipi_csi2_get_datatype(mipi_csi2_info);
+
+ mipi_csi2_pixelclk_enable(mipi_csi2_info);
+ } else {
+ params.csi_mem.mipi_en = false;
+ params.csi_mem.mipi_vc = 0;
+ params.csi_mem.mipi_id = 0;
+ }
+ } else {
+ params.csi_mem.mipi_en = false;
+ params.csi_mem.mipi_vc = 0;
+ params.csi_mem.mipi_id = 0;
+ }
+ }
+#endif
+
+ err = ipu_init_channel(cam->ipu, chan, &params);
+ if (err != 0) {
+ printk(KERN_ERR "ipu_init_channel %d\n", err);
+ return err;
+ }
+
+ err = ipu_init_channel_buffer(cam->ipu,
+ chan,
+ IPU_OUTPUT_BUFFER,
+ pixel_fmt, cam->v2f.fmt.pix.width,
+ cam->v2f.fmt.pix.height,
+ cam->v2f.fmt.pix.bytesperline,
+ IPU_ROTATE_NONE,
+ dummy, dummy, 0,
+ cam->offset.u_offset,
+ cam->offset.v_offset);
+ if (err != 0) {
+ printk(KERN_ERR "CSI_MEM output buffer\n");
+ return err;
+ }
+ err = ipu_enable_channel(cam->ipu, chan);
+ if (err < 0) {
+ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
+ return err;
+ }
+
+ return err;
+}
+
+/*!
+ * function to update physical buffer address for encorder IDMA channel
+ *
+ * @param *private pointer to the cam_data structure
+ * @param eba physical buffer address for encorder IDMA channel
+ *
+ * @return status
+ */
+static int csi_enc_eba_update(void *private, dma_addr_t eba)
+{
+ int err = 0;
+ cam_data *cam = (cam_data *) private;
+ struct ipu_soc *ipu = cam->ipu;
+ int *buffer_num = &cam->ping_pong_csi;
+ ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+
+ pr_debug("eba %x\n", eba);
+ err = ipu_update_channel_buffer(ipu, chan, IPU_OUTPUT_BUFFER,
+ *buffer_num, eba);
+ if (err != 0) {
+ ipu_clear_buffer_ready(ipu, chan, IPU_OUTPUT_BUFFER,
+ *buffer_num);
+
+ err = ipu_update_channel_buffer(ipu, chan,
+ IPU_OUTPUT_BUFFER, *buffer_num, eba);
+ if (err != 0) {
+ pr_err("ERROR: v4l2 capture: fail to update "
+ "buf%d\n", *buffer_num);
+ return err;
+ }
+ }
+
+ ipu_select_buffer(ipu, chan, IPU_OUTPUT_BUFFER, *buffer_num);
+
+ *buffer_num = (*buffer_num == 0) ? 1 : 0;
+
+ return 0;
+}
+
+/*!
+ * Enable encoder task
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int csi_enc_enabling_tasks(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+ uint32_t irq = (cam->csi == 0) ?
+ IPU_IRQ_CSI0_OUT_EOF : IPU_IRQ_CSI1_OUT_EOF;
+
+ CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");
+
+ cam->dummy_frame.vaddress = dma_alloc_coherent(0,
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+ &cam->dummy_frame.paddress,
+ GFP_DMA | GFP_KERNEL);
+ if (cam->dummy_frame.vaddress == 0) {
+ pr_err("ERROR: v4l2 capture: Allocate dummy frame "
+ "failed.\n");
+ return -ENOBUFS;
+ }
+ cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE;
+ cam->dummy_frame.buffer.length =
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+ cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
+
+ ipu_clear_irq(cam->ipu, irq);
+ err = ipu_request_irq(
+ cam->ipu, irq, csi_enc_callback, 0, "Mxc Camera", cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error registering rot irq\n");
+ return err;
+ }
+
+ err = csi_enc_setup(cam);
+ if (err != 0) {
+ printk(KERN_ERR "csi_enc_setup %d\n", err);
+ return err;
+ }
+
+ return err;
+}
+
+/*!
+ * Disable encoder task
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return int
+ */
+static int csi_enc_disabling_tasks(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+ ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ err = ipu_disable_channel(cam->ipu, chan, true);
+
+ ipu_uninit_channel(cam->ipu, chan);
+
+ if (cam->dummy_frame.vaddress != 0) {
+ dma_free_coherent(0, cam->dummy_frame.buffer.length,
+ cam->dummy_frame.vaddress,
+ cam->dummy_frame.paddress);
+ cam->dummy_frame.vaddress = 0;
+ }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id)
+ mipi_csi2_pixelclk_disable(mipi_csi2_info);
+ }
+ }
+#endif
+
+ return err;
+}
+
+/*!
+ * Enable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int csi_enc_enable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int csi_enc_disable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ uint32_t irq = (cam->csi == 0) ?
+ IPU_IRQ_CSI0_OUT_EOF : IPU_IRQ_CSI1_OUT_EOF;
+
+ /* free csi eof irq firstly.
+ * when disable csi, wait for idmac eof.
+ * it requests eof irq again */
+ ipu_free_irq(cam->ipu, irq, cam);
+
+ return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select CSI ENC as the working path
+ *
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return int
+ */
+int csi_enc_select(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+
+ if (cam) {
+ cam->enc_update_eba = csi_enc_eba_update;
+ cam->enc_enable = csi_enc_enabling_tasks;
+ cam->enc_disable = csi_enc_disabling_tasks;
+ cam->enc_enable_csi = csi_enc_enable_csi;
+ cam->enc_disable_csi = csi_enc_disable_csi;
+ } else {
+ err = -EIO;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(csi_enc_select);
+
+/*!
+ * function to de-select CSI ENC as the working path
+ *
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return int
+ */
+int csi_enc_deselect(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+
+ if (cam) {
+ cam->enc_update_eba = NULL;
+ cam->enc_enable = NULL;
+ cam->enc_disable = NULL;
+ cam->enc_enable_csi = NULL;
+ cam->enc_disable_csi = NULL;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(csi_enc_deselect);
+
+/*!
+ * Init the Encorder channels
+ *
+ * @return Error code indicating success or failure
+ */
+__init int csi_enc_init(void)
+{
+ return 0;
+}
+
+/*!
+ * Deinit the Encorder channels
+ *
+ */
+void __exit csi_enc_exit(void)
+{
+}
+
+module_init(csi_enc_init);
+module_exit(csi_enc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("CSI ENC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c b/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c
new file mode 100644
index 000000000000..4d6b1365bb0d
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c
@@ -0,0 +1,638 @@
+/*
+ * Copyright 2004-2015 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 ipu_foreground_sdc.c
+ *
+ * @brief IPU Use case for PRP-VF
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/console.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/mipi_csi2.h>
+
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+#ifdef CAMERA_DBG
+ #define CAMERA_TRACE(x) (printk)x
+#else
+ #define CAMERA_TRACE(x)
+#endif
+
+static int csi_buffer_num, buffer_num;
+static u32 csi_mem_bufsize;
+static struct ipu_soc *disp_ipu;
+static struct fb_info *fbi;
+static struct fb_var_screeninfo fbvar;
+static u32 vf_out_format;
+static void csi_buf_work_func(struct work_struct *work)
+{
+ int err = 0;
+ cam_data *cam =
+ container_of(work, struct _cam_data, csi_work_struct);
+
+ struct ipu_task task;
+ memset(&task, 0, sizeof(task));
+
+ if (csi_buffer_num)
+ task.input.paddr = cam->vf_bufs[0];
+ else
+ task.input.paddr = cam->vf_bufs[1];
+ task.input.width = cam->crop_current.width;
+ task.input.height = cam->crop_current.height;
+ task.input.format = IPU_PIX_FMT_NV12;
+
+ if (buffer_num == 0)
+ task.output.paddr = fbi->fix.smem_start +
+ (fbi->fix.line_length * fbvar.yres);
+ else
+ task.output.paddr = fbi->fix.smem_start;
+ task.output.width = cam->win.w.width;
+ task.output.height = cam->win.w.height;
+ task.output.format = vf_out_format;
+ task.output.rotate = cam->rotation;
+again:
+ err = ipu_check_task(&task);
+ if (err != IPU_CHECK_OK) {
+ if (err > IPU_CHECK_ERR_MIN) {
+ if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) {
+ task.input.crop.w -= 8;
+ goto again;
+ }
+ if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) {
+ task.input.crop.h -= 8;
+ goto again;
+ }
+ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) {
+ task.output.width -= 8;
+ task.output.crop.w = task.output.width;
+ goto again;
+ }
+ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) {
+ task.output.height -= 8;
+ task.output.crop.h = task.output.height;
+ goto again;
+ }
+ printk(KERN_ERR "check ipu taks fail\n");
+ return;
+ }
+ printk(KERN_ERR "check ipu taks fail\n");
+ return;
+ }
+ err = ipu_queue_task(&task);
+ if (err < 0)
+ printk(KERN_ERR "queue ipu task error\n");
+ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, buffer_num);
+ buffer_num = (buffer_num == 0) ? 1 : 0;
+}
+
+static void get_disp_ipu(cam_data *cam)
+{
+ if (cam->output > 2)
+ disp_ipu = ipu_get_soc(1); /* using DISP4 */
+ else
+ disp_ipu = ipu_get_soc(0);
+}
+
+/*!
+ * csi ENC callback function.
+ *
+ * @param irq int irq line
+ * @param dev_id void * device id
+ *
+ * @return status IRQ_HANDLED for handled
+ */
+static irqreturn_t csi_enc_callback(int irq, void *dev_id)
+{
+ cam_data *cam = (cam_data *) dev_id;
+ ipu_channel_t chan = (irq == IPU_IRQ_CSI0_OUT_EOF) ?
+ CSI_MEM0 : CSI_MEM1;
+
+ ipu_select_buffer(cam->ipu, chan,
+ IPU_OUTPUT_BUFFER, csi_buffer_num);
+
+ if ((cam->crop_current.width != cam->win.w.width) ||
+ (cam->crop_current.height != cam->win.w.height) ||
+ (vf_out_format != IPU_PIX_FMT_NV12) ||
+ (cam->rotation >= IPU_ROTATE_VERT_FLIP))
+ schedule_work(&cam->csi_work_struct);
+ csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0;
+ return IRQ_HANDLED;
+}
+
+static int csi_enc_setup(cam_data *cam)
+{
+ ipu_channel_params_t params;
+ int err = 0, sensor_protocol = 0;
+ ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ CAMERA_TRACE("In csi_enc_setup\n");
+ if (!cam) {
+ printk(KERN_ERR "cam private is NULL\n");
+ return -ENXIO;
+ }
+
+ memset(&params, 0, sizeof(ipu_channel_params_t));
+ params.csi_mem.csi = cam->csi;
+
+ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
+ switch (sensor_protocol) {
+ case IPU_CSI_CLK_MODE_GATED_CLK:
+ case IPU_CSI_CLK_MODE_NONGATED_CLK:
+ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
+ params.csi_mem.interlaced = false;
+ break;
+ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
+ params.csi_mem.interlaced = true;
+ break;
+ default:
+ printk(KERN_ERR "sensor protocol unsupported\n");
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id) {
+ params.csi_mem.mipi_en = true;
+ params.csi_mem.mipi_vc =
+ mipi_csi2_get_virtual_channel(mipi_csi2_info);
+ params.csi_mem.mipi_id =
+ mipi_csi2_get_datatype(mipi_csi2_info);
+
+ mipi_csi2_pixelclk_enable(mipi_csi2_info);
+ } else {
+ params.csi_mem.mipi_en = false;
+ params.csi_mem.mipi_vc = 0;
+ params.csi_mem.mipi_id = 0;
+ }
+ } else {
+ params.csi_mem.mipi_en = false;
+ params.csi_mem.mipi_vc = 0;
+ params.csi_mem.mipi_id = 0;
+ }
+ }
+#endif
+
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0],
+ (dma_addr_t) cam->vf_bufs[0]);
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1],
+ (dma_addr_t) cam->vf_bufs[1]);
+ }
+ csi_mem_bufsize = cam->crop_current.width *
+ cam->crop_current.height * 3/2;
+ cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize);
+ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
+ cam->vf_bufs_size[0],
+ (dma_addr_t *) &
+ cam->vf_bufs[0],
+ GFP_DMA |
+ GFP_KERNEL);
+ if (cam->vf_bufs_vaddr[0] == NULL) {
+ printk(KERN_ERR "Error to allocate vf buffer\n");
+ err = -ENOMEM;
+ goto out_2;
+ }
+ cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize);
+ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
+ cam->vf_bufs_size[1],
+ (dma_addr_t *) &
+ cam->vf_bufs[1],
+ GFP_DMA |
+ GFP_KERNEL);
+ if (cam->vf_bufs_vaddr[1] == NULL) {
+ printk(KERN_ERR "Error to allocate vf buffer\n");
+ err = -ENOMEM;
+ goto out_1;
+ }
+ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
+
+ err = ipu_init_channel(cam->ipu, chan, &params);
+ if (err != 0) {
+ printk(KERN_ERR "ipu_init_channel %d\n", err);
+ goto out_1;
+ }
+
+ if ((cam->crop_current.width == cam->win.w.width) &&
+ (cam->crop_current.height == cam->win.w.height) &&
+ (vf_out_format == IPU_PIX_FMT_NV12) &&
+ (cam->rotation < IPU_ROTATE_VERT_FLIP)) {
+ err = ipu_init_channel_buffer(cam->ipu, chan,
+ IPU_OUTPUT_BUFFER, IPU_PIX_FMT_NV12,
+ cam->crop_current.width,
+ cam->crop_current.height,
+ cam->crop_current.width, IPU_ROTATE_NONE,
+ fbi->fix.smem_start +
+ (fbi->fix.line_length * fbvar.yres),
+ fbi->fix.smem_start, 0,
+ cam->offset.u_offset, cam->offset.u_offset);
+ } else {
+ err = ipu_init_channel_buffer(cam->ipu, chan,
+ IPU_OUTPUT_BUFFER, IPU_PIX_FMT_NV12,
+ cam->crop_current.width,
+ cam->crop_current.height,
+ cam->crop_current.width, IPU_ROTATE_NONE,
+ cam->vf_bufs[0], cam->vf_bufs[1], 0,
+ cam->offset.u_offset, cam->offset.u_offset);
+ }
+ if (err != 0) {
+ printk(KERN_ERR "CSI_MEM output buffer\n");
+ goto out_1;
+ }
+ err = ipu_enable_channel(cam->ipu, chan);
+ if (err < 0) {
+ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
+ goto out_1;
+ }
+
+ csi_buffer_num = 0;
+
+ ipu_select_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER, 0);
+ ipu_select_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER, 1);
+ return err;
+out_1:
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0],
+ (dma_addr_t) cam->vf_bufs[0]);
+ cam->vf_bufs_vaddr[0] = NULL;
+ cam->vf_bufs[0] = 0;
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1],
+ (dma_addr_t) cam->vf_bufs[1]);
+ cam->vf_bufs_vaddr[1] = NULL;
+ cam->vf_bufs[1] = 0;
+ }
+out_2:
+ return err;
+}
+
+/*!
+ * Enable encoder task
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int csi_enc_enabling_tasks(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+ CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");
+
+ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi);
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi,
+ csi_enc_callback, 0, "Mxc Camera", cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error registering CSI_OUT_EOF irq\n");
+ return err;
+ }
+
+ INIT_WORK(&cam->csi_work_struct, csi_buf_work_func);
+
+ err = csi_enc_setup(cam);
+ if (err != 0) {
+ printk(KERN_ERR "csi_enc_setup %d\n", err);
+ goto out1;
+ }
+
+ return err;
+out1:
+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);
+ return err;
+}
+
+/*
+ * Function definitions
+ */
+
+/*!
+ * foreground_start - start the vf task
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ */
+static int foreground_start(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0, i = 0, screen_size;
+ char *base;
+
+ if (!cam) {
+ printk(KERN_ERR "private is NULL\n");
+ return -EIO;
+ }
+
+ if (cam->overlay_active == true) {
+ pr_debug("already started.\n");
+ return 0;
+ }
+
+ get_disp_ipu(cam);
+
+ for (i = 0; i < num_registered_fb; i++) {
+ char *idstr = registered_fb[i]->fix.id;
+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
+ fbi = registered_fb[i];
+ break;
+ }
+ }
+
+ if (fbi == NULL) {
+ printk(KERN_ERR "DISP FG fb not found\n");
+ return -EPERM;
+ }
+
+ fbvar = fbi->var;
+
+ /* Store the overlay frame buffer's original std */
+ cam->fb_origin_std = fbvar.nonstd;
+
+ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
+ /* Use DP to do CSC so that we can get better performance */
+ vf_out_format = IPU_PIX_FMT_NV12;
+ fbvar.nonstd = vf_out_format;
+ } else {
+ vf_out_format = IPU_PIX_FMT_RGB565;
+ fbvar.nonstd = 0;
+ }
+
+ fbvar.bits_per_pixel = 16;
+ fbvar.xres = fbvar.xres_virtual = cam->win.w.width;
+ fbvar.yres = cam->win.w.height;
+ fbvar.yres_virtual = cam->win.w.height * 2;
+ fbvar.yoffset = 0;
+ fbvar.vmode &= ~FB_VMODE_YWRAP;
+ fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG;
+ fbvar.activate |= FB_ACTIVATE_FORCE;
+ fb_set_var(fbi, &fbvar);
+
+ ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left,
+ cam->win.w.top);
+
+ /* Fill black color for framebuffer */
+ base = (char *) fbi->screen_base;
+ screen_size = fbi->var.xres * fbi->var.yres;
+ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
+ memset(base, 0, screen_size);
+ base += screen_size;
+ for (i = 0; i < screen_size / 2; i++, base++)
+ *base = 0x80;
+ } else {
+ for (i = 0; i < screen_size * 2; i++, base++)
+ *base = 0x00;
+ }
+
+ console_lock();
+ fb_blank(fbi, FB_BLANK_UNBLANK);
+ console_unlock();
+
+ /* correct display ch buffer address */
+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+ 0, fbi->fix.smem_start +
+ (fbi->fix.line_length * fbvar.yres));
+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+ 1, fbi->fix.smem_start);
+
+ err = csi_enc_enabling_tasks(cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error csi enc enable fail\n");
+ return err;
+ }
+
+ cam->overlay_active = true;
+ return err;
+
+}
+
+/*!
+ * foreground_stop - stop the vf task
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ */
+static int foreground_stop(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0, i = 0;
+ struct fb_info *fbi = NULL;
+ struct fb_var_screeninfo fbvar;
+ ipu_channel_t chan = (cam->csi == 0) ? CSI_MEM0 : CSI_MEM1;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ if (cam->overlay_active == false)
+ return 0;
+
+ err = ipu_disable_channel(cam->ipu, chan, true);
+
+ ipu_uninit_channel(cam->ipu, chan);
+
+ csi_buffer_num = 0;
+ buffer_num = 0;
+
+ for (i = 0; i < num_registered_fb; i++) {
+ char *idstr = registered_fb[i]->fix.id;
+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
+ fbi = registered_fb[i];
+ break;
+ }
+ }
+
+ if (fbi == NULL) {
+ printk(KERN_ERR "DISP FG fb not found\n");
+ return -EPERM;
+ }
+
+ console_lock();
+ fb_blank(fbi, FB_BLANK_POWERDOWN);
+ console_unlock();
+
+ /* Set the overlay frame buffer std to what it is used to be */
+ fbvar = fbi->var;
+ fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG;
+ fbvar.nonstd = cam->fb_origin_std;
+ fbvar.activate |= FB_ACTIVATE_FORCE;
+ fb_set_var(fbi, &fbvar);
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id)
+ mipi_csi2_pixelclk_disable(mipi_csi2_info);
+ }
+ }
+#endif
+
+ flush_work(&cam->csi_work_struct);
+ cancel_work_sync(&cam->csi_work_struct);
+
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0],
+ (dma_addr_t) cam->vf_bufs[0]);
+ cam->vf_bufs_vaddr[0] = NULL;
+ cam->vf_bufs[0] = 0;
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1],
+ (dma_addr_t) cam->vf_bufs[1]);
+ cam->vf_bufs_vaddr[1] = NULL;
+ cam->vf_bufs[1] = 0;
+ }
+
+ cam->overlay_active = false;
+ return err;
+}
+
+/*!
+ * Enable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int foreground_enable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int foreground_disable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ /* free csi eof irq firstly.
+ * when disable csi, wait for idmac eof.
+ * it requests eof irq again */
+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);
+
+ return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select foreground as the working path
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ * @return status
+ */
+int foreground_sdc_select(void *private)
+{
+ cam_data *cam;
+ int err = 0;
+ if (private) {
+ cam = (cam_data *) private;
+ cam->vf_start_sdc = foreground_start;
+ cam->vf_stop_sdc = foreground_stop;
+ cam->vf_enable_csi = foreground_enable_csi;
+ cam->vf_disable_csi = foreground_disable_csi;
+ cam->overlay_active = false;
+ } else
+ err = -EIO;
+
+ return err;
+}
+EXPORT_SYMBOL(foreground_sdc_select);
+
+/*!
+ * function to de-select foreground as the working path
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ * @return int
+ */
+int foreground_sdc_deselect(void *private)
+{
+ cam_data *cam;
+
+ if (private) {
+ cam = (cam_data *) private;
+ cam->vf_start_sdc = NULL;
+ cam->vf_stop_sdc = NULL;
+ cam->vf_enable_csi = NULL;
+ cam->vf_disable_csi = NULL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(foreground_sdc_deselect);
+
+/*!
+ * Init viewfinder task.
+ *
+ * @return Error code indicating success or failure
+ */
+__init int foreground_sdc_init(void)
+{
+ return 0;
+}
+
+/*!
+ * Deinit viewfinder task.
+ *
+ * @return Error code indicating success or failure
+ */
+void __exit foreground_sdc_exit(void)
+{
+}
+
+module_init(foreground_sdc_init);
+module_exit(foreground_sdc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP VF SDC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_enc.c b/drivers/media/platform/mxc/capture/ipu_prp_enc.c
new file mode 100644
index 000000000000..1e4420b952f8
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ipu_prp_enc.c
@@ -0,0 +1,597 @@
+/*
+ * Copyright 2004-2015 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 ipu_prp_enc.c
+ *
+ * @brief IPU Use case for PRP-ENC
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/ipu.h>
+#include <linux/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+#ifdef CAMERA_DBG
+ #define CAMERA_TRACE(x) (printk)x
+#else
+ #define CAMERA_TRACE(x)
+#endif
+
+static ipu_rotate_mode_t grotation = IPU_ROTATE_NONE;
+
+/*
+ * Function definitions
+ */
+
+/*!
+ * IPU ENC callback function.
+ *
+ * @param irq int irq line
+ * @param dev_id void * device id
+ *
+ * @return status IRQ_HANDLED for handled
+ */
+static irqreturn_t prp_enc_callback(int irq, void *dev_id)
+{
+ cam_data *cam = (cam_data *) dev_id;
+
+ if (cam->enc_callback == NULL)
+ return IRQ_HANDLED;
+
+ cam->enc_callback(irq, dev_id);
+
+ return IRQ_HANDLED;
+}
+
+/*!
+ * PrpENC enable channel setup function
+ *
+ * @param cam struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_enc_setup(cam_data *cam)
+{
+ ipu_channel_params_t enc;
+ int err = 0;
+ dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ CAMERA_TRACE("In prp_enc_setup\n");
+ if (!cam) {
+ printk(KERN_ERR "cam private is NULL\n");
+ return -ENXIO;
+ }
+ memset(&enc, 0, sizeof(ipu_channel_params_t));
+
+ ipu_csi_get_window_size(cam->ipu, &enc.csi_prp_enc_mem.in_width,
+ &enc.csi_prp_enc_mem.in_height, cam->csi);
+
+ enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
+ enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width;
+ enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height;
+ enc.csi_prp_enc_mem.csi = cam->csi;
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+ enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height;
+ enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width;
+ }
+
+ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P;
+ pr_info("YUV420\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YVU420P;
+ pr_info("YVU420\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P;
+ pr_info("YUV422P\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV;
+ pr_info("YUYV\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY;
+ pr_info("UYVY\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12;
+ pr_info("NV12\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24;
+ pr_info("BGR24\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24;
+ pr_info("RGB24\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565;
+ pr_info("RGB565\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32;
+ pr_info("BGR32\n");
+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) {
+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32;
+ pr_info("RGB32\n");
+ } else {
+ printk(KERN_ERR "format not supported\n");
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id) {
+ enc.csi_prp_enc_mem.mipi_en = true;
+ enc.csi_prp_enc_mem.mipi_vc =
+ mipi_csi2_get_virtual_channel(mipi_csi2_info);
+ enc.csi_prp_enc_mem.mipi_id =
+ mipi_csi2_get_datatype(mipi_csi2_info);
+
+ mipi_csi2_pixelclk_enable(mipi_csi2_info);
+ } else {
+ enc.csi_prp_enc_mem.mipi_en = false;
+ enc.csi_prp_enc_mem.mipi_vc = 0;
+ enc.csi_prp_enc_mem.mipi_id = 0;
+ }
+ } else {
+ enc.csi_prp_enc_mem.mipi_en = false;
+ enc.csi_prp_enc_mem.mipi_vc = 0;
+ enc.csi_prp_enc_mem.mipi_id = 0;
+ }
+ }
+#endif
+
+ err = ipu_init_channel(cam->ipu, CSI_PRP_ENC_MEM, &enc);
+ if (err != 0) {
+ printk(KERN_ERR "ipu_init_channel %d\n", err);
+ return err;
+ }
+
+ grotation = cam->rotation;
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+ if (cam->rot_enc_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->rot_enc_buf_size[0],
+ cam->rot_enc_bufs_vaddr[0],
+ cam->rot_enc_bufs[0]);
+ }
+ if (cam->rot_enc_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->rot_enc_buf_size[1],
+ cam->rot_enc_bufs_vaddr[1],
+ cam->rot_enc_bufs[1]);
+ }
+ cam->rot_enc_buf_size[0] =
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+ cam->rot_enc_bufs_vaddr[0] =
+ (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0],
+ &cam->rot_enc_bufs[0],
+ GFP_DMA | GFP_KERNEL);
+ if (!cam->rot_enc_bufs_vaddr[0]) {
+ printk(KERN_ERR "alloc enc_bufs0\n");
+ return -ENOMEM;
+ }
+ cam->rot_enc_buf_size[1] =
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+ cam->rot_enc_bufs_vaddr[1] =
+ (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1],
+ &cam->rot_enc_bufs[1],
+ GFP_DMA | GFP_KERNEL);
+ if (!cam->rot_enc_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->rot_enc_buf_size[0],
+ cam->rot_enc_bufs_vaddr[0],
+ cam->rot_enc_bufs[0]);
+ cam->rot_enc_bufs_vaddr[0] = NULL;
+ cam->rot_enc_bufs[0] = 0;
+ printk(KERN_ERR "alloc enc_bufs1\n");
+ return -ENOMEM;
+ }
+
+ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM,
+ IPU_OUTPUT_BUFFER,
+ enc.csi_prp_enc_mem.out_pixel_fmt,
+ enc.csi_prp_enc_mem.out_width,
+ enc.csi_prp_enc_mem.out_height,
+ enc.csi_prp_enc_mem.out_width,
+ IPU_ROTATE_NONE,
+ cam->rot_enc_bufs[0],
+ cam->rot_enc_bufs[1], 0, 0, 0);
+ if (err != 0) {
+ printk(KERN_ERR "CSI_PRP_ENC_MEM err\n");
+ return err;
+ }
+
+ err = ipu_init_channel(cam->ipu, MEM_ROT_ENC_MEM, NULL);
+ if (err != 0) {
+ printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n");
+ return err;
+ }
+
+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM,
+ IPU_INPUT_BUFFER,
+ enc.csi_prp_enc_mem.out_pixel_fmt,
+ enc.csi_prp_enc_mem.out_width,
+ enc.csi_prp_enc_mem.out_height,
+ enc.csi_prp_enc_mem.out_width,
+ cam->rotation,
+ cam->rot_enc_bufs[0],
+ cam->rot_enc_bufs[1], 0, 0, 0);
+ if (err != 0) {
+ printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n");
+ return err;
+ }
+
+ err =
+ ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM,
+ IPU_OUTPUT_BUFFER,
+ enc.csi_prp_enc_mem.out_pixel_fmt,
+ enc.csi_prp_enc_mem.out_height,
+ enc.csi_prp_enc_mem.out_width,
+ cam->v2f.fmt.pix.bytesperline /
+ bytes_per_pixel(enc.csi_prp_enc_mem.
+ out_pixel_fmt),
+ IPU_ROTATE_NONE,
+ dummy, dummy, 0,
+ cam->offset.u_offset,
+ cam->offset.v_offset);
+ if (err != 0) {
+ printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n");
+ return err;
+ }
+
+ err = ipu_link_channels(cam->ipu,
+ CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
+ if (err < 0) {
+ printk(KERN_ERR
+ "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n");
+ return err;
+ }
+
+ err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM);
+ if (err < 0) {
+ printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
+ return err;
+ }
+ err = ipu_enable_channel(cam->ipu, MEM_ROT_ENC_MEM);
+ if (err < 0) {
+ printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n");
+ return err;
+ }
+
+ ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM,
+ IPU_OUTPUT_BUFFER, 0);
+ ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM,
+ IPU_OUTPUT_BUFFER, 1);
+ } else {
+ err =
+ ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM,
+ IPU_OUTPUT_BUFFER,
+ enc.csi_prp_enc_mem.out_pixel_fmt,
+ enc.csi_prp_enc_mem.out_width,
+ enc.csi_prp_enc_mem.out_height,
+ cam->v2f.fmt.pix.bytesperline /
+ bytes_per_pixel(enc.csi_prp_enc_mem.
+ out_pixel_fmt),
+ cam->rotation,
+ dummy, dummy, 0,
+ cam->offset.u_offset,
+ cam->offset.v_offset);
+ if (err != 0) {
+ printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n");
+ return err;
+ }
+ err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM);
+ if (err < 0) {
+ printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
+ return err;
+ }
+ }
+
+ return err;
+}
+
+/*!
+ * function to update physical buffer address for encorder IDMA channel
+ *
+ * @param private pointer to cam_data structure
+ * @param eba physical buffer address for encorder IDMA channel
+ *
+ * @return status
+ */
+static int prp_enc_eba_update(void *private, dma_addr_t eba)
+{
+ int err = 0;
+ cam_data *cam = (cam_data *) private;
+ struct ipu_soc *ipu = cam->ipu;
+ int *buffer_num = &cam->ping_pong_csi;
+
+ pr_debug("eba %x\n", eba);
+ if (grotation >= IPU_ROTATE_90_RIGHT) {
+ err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM,
+ IPU_OUTPUT_BUFFER, *buffer_num,
+ eba);
+ } else {
+ err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM,
+ IPU_OUTPUT_BUFFER, *buffer_num,
+ eba);
+ }
+ if (err != 0) {
+ if (grotation >= IPU_ROTATE_90_RIGHT) {
+ ipu_clear_buffer_ready(ipu, MEM_ROT_ENC_MEM,
+ IPU_OUTPUT_BUFFER,
+ *buffer_num);
+ err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM,
+ IPU_OUTPUT_BUFFER,
+ *buffer_num,
+ eba);
+ } else {
+ ipu_clear_buffer_ready(ipu, CSI_PRP_ENC_MEM,
+ IPU_OUTPUT_BUFFER,
+ *buffer_num);
+ err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM,
+ IPU_OUTPUT_BUFFER,
+ *buffer_num,
+ eba);
+ }
+
+ if (err != 0) {
+ pr_err("ERROR: v4l2 capture: fail to update "
+ "buf%d\n", *buffer_num);
+ return err;
+ }
+ }
+
+ if (grotation >= IPU_ROTATE_90_RIGHT) {
+ ipu_select_buffer(ipu, MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER,
+ *buffer_num);
+ } else {
+ ipu_select_buffer(ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER,
+ *buffer_num);
+ }
+
+ *buffer_num = (*buffer_num == 0) ? 1 : 0;
+ return 0;
+}
+
+/*!
+ * Enable encoder task
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_enc_enabling_tasks(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+ CAMERA_TRACE("IPU:In prp_enc_enabling_tasks\n");
+
+ cam->dummy_frame.vaddress = dma_alloc_coherent(0,
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+ &cam->dummy_frame.paddress,
+ GFP_DMA | GFP_KERNEL);
+ if (cam->dummy_frame.vaddress == 0) {
+ pr_err("ERROR: v4l2 capture: Allocate dummy frame "
+ "failed.\n");
+ return -ENOBUFS;
+ }
+ cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE;
+ cam->dummy_frame.buffer.length =
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+ cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
+
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF,
+ prp_enc_callback, 0, "Mxc Camera", cam);
+ } else {
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF,
+ prp_enc_callback, 0, "Mxc Camera", cam);
+ }
+ if (err != 0) {
+ printk(KERN_ERR "Error registering rot irq\n");
+ return err;
+ }
+
+ err = prp_enc_setup(cam);
+ if (err != 0) {
+ printk(KERN_ERR "prp_enc_setup %d\n", err);
+ return err;
+ }
+
+ return err;
+}
+
+/*!
+ * Disable encoder task
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return int
+ */
+static int prp_enc_disabling_tasks(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF, cam);
+ ipu_unlink_channels(cam->ipu, CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
+ }
+
+ err = ipu_disable_channel(cam->ipu, CSI_PRP_ENC_MEM, true);
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT)
+ err |= ipu_disable_channel(cam->ipu, MEM_ROT_ENC_MEM, true);
+
+ ipu_uninit_channel(cam->ipu, CSI_PRP_ENC_MEM);
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT)
+ ipu_uninit_channel(cam->ipu, MEM_ROT_ENC_MEM);
+
+ if (cam->dummy_frame.vaddress != 0) {
+ dma_free_coherent(0, cam->dummy_frame.buffer.length,
+ cam->dummy_frame.vaddress,
+ cam->dummy_frame.paddress);
+ cam->dummy_frame.vaddress = 0;
+ }
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id)
+ mipi_csi2_pixelclk_disable(mipi_csi2_info);
+ }
+ }
+#endif
+
+ return err;
+}
+
+/*!
+ * Enable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_enc_enable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_enc_disable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ /* free csi eof irq firstly.
+ * when disable csi, wait for idmac eof.
+ * it requests eof irq again */
+ if (cam->rotation < IPU_ROTATE_90_RIGHT)
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF, cam);
+
+ return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select PRP-ENC as the working path
+ *
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return int
+ */
+int prp_enc_select(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+
+ if (cam) {
+ cam->enc_update_eba = prp_enc_eba_update;
+ cam->enc_enable = prp_enc_enabling_tasks;
+ cam->enc_disable = prp_enc_disabling_tasks;
+ cam->enc_enable_csi = prp_enc_enable_csi;
+ cam->enc_disable_csi = prp_enc_disable_csi;
+ } else {
+ err = -EIO;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(prp_enc_select);
+
+/*!
+ * function to de-select PRP-ENC as the working path
+ *
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return int
+ */
+int prp_enc_deselect(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+
+ if (cam) {
+ cam->enc_update_eba = NULL;
+ cam->enc_enable = NULL;
+ cam->enc_disable = NULL;
+ cam->enc_enable_csi = NULL;
+ cam->enc_disable_csi = NULL;
+ if (cam->rot_enc_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->rot_enc_buf_size[0],
+ cam->rot_enc_bufs_vaddr[0],
+ cam->rot_enc_bufs[0]);
+ cam->rot_enc_bufs_vaddr[0] = NULL;
+ cam->rot_enc_bufs[0] = 0;
+ }
+ if (cam->rot_enc_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->rot_enc_buf_size[1],
+ cam->rot_enc_bufs_vaddr[1],
+ cam->rot_enc_bufs[1]);
+ cam->rot_enc_bufs_vaddr[1] = NULL;
+ cam->rot_enc_bufs[1] = 0;
+ }
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(prp_enc_deselect);
+
+/*!
+ * Init the Encorder channels
+ *
+ * @return Error code indicating success or failure
+ */
+__init int prp_enc_init(void)
+{
+ return 0;
+}
+
+/*!
+ * Deinit the Encorder channels
+ *
+ */
+void __exit prp_enc_exit(void)
+{
+}
+
+module_init(prp_enc_init);
+module_exit(prp_enc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP ENC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_sw.h b/drivers/media/platform/mxc/capture/ipu_prp_sw.h
new file mode 100644
index 000000000000..be02ab061e20
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ipu_prp_sw.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2004-2014 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 ipu_prp_sw.h
+ *
+ * @brief This file contains the IPU PRP use case driver header.
+ *
+ * @ingroup IPU
+ */
+
+#ifndef _INCLUDE_IPU__PRP_SW_H_
+#define _INCLUDE_IPU__PRP_SW_H_
+
+int csi_enc_select(void *private);
+int csi_enc_deselect(void *private);
+int prp_enc_select(void *private);
+int prp_enc_deselect(void *private);
+#ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+int prp_vf_sdc_select(void *private);
+int prp_vf_sdc_deselect(void *private);
+int prp_vf_sdc_select_bg(void *private);
+int prp_vf_sdc_deselect_bg(void *private);
+#else
+int foreground_sdc_select(void *private);
+int foreground_sdc_deselect(void *private);
+int bg_overlay_sdc_select(void *private);
+int bg_overlay_sdc_deselect(void *private);
+#endif
+int prp_still_select(void *private);
+int prp_still_deselect(void *private);
+
+#endif
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c b/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c
new file mode 100644
index 000000000000..b9610f1ed820
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c
@@ -0,0 +1,582 @@
+/*
+ * Copyright 2004-2014 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 ipu_prp_vf_sdc.c
+ *
+ * @brief IPU Use case for PRP-VF
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/console.h>
+#include <linux/ipu.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <mach/hardware.h>
+#include <mach/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+static int buffer_num;
+static struct ipu_soc *disp_ipu;
+
+static void get_disp_ipu(cam_data *cam)
+{
+ if (cam->output > 2)
+ disp_ipu = ipu_get_soc(1); /* using DISP4 */
+ else
+ disp_ipu = ipu_get_soc(0);
+}
+
+static irqreturn_t prpvf_rot_eof_callback(int irq, void *dev_id)
+{
+ cam_data *cam = dev_id;
+ pr_debug("buffer_num %d\n", buffer_num);
+
+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+ ipu_select_buffer(disp_ipu, MEM_FG_SYNC,
+ IPU_INPUT_BUFFER, buffer_num);
+ buffer_num = (buffer_num == 0) ? 1 : 0;
+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_OUTPUT_BUFFER, buffer_num);
+ } else {
+ ipu_select_buffer(disp_ipu, MEM_FG_SYNC,
+ IPU_INPUT_BUFFER, buffer_num);
+ buffer_num = (buffer_num == 0) ? 1 : 0;
+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+ IPU_OUTPUT_BUFFER, buffer_num);
+ }
+ return IRQ_HANDLED;
+}
+/*
+ * Function definitions
+ */
+
+/*!
+ * prpvf_start - start the vf task
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ */
+static int prpvf_start(void *private)
+{
+ struct fb_var_screeninfo fbvar;
+ struct fb_info *fbi = NULL;
+ cam_data *cam = (cam_data *) private;
+ ipu_channel_params_t vf;
+ u32 vf_out_format = 0;
+ u32 size = 2, temp = 0;
+ int err = 0, i = 0;
+ short *tmp, color;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ if (!cam) {
+ printk(KERN_ERR "private is NULL\n");
+ return -EIO;
+ }
+
+ if (cam->overlay_active == true) {
+ pr_debug("already started.\n");
+ return 0;
+ }
+
+ get_disp_ipu(cam);
+
+ for (i = 0; i < num_registered_fb; i++) {
+ char *idstr = registered_fb[i]->fix.id;
+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
+ fbi = registered_fb[i];
+ break;
+ }
+ }
+
+ if (fbi == NULL) {
+ printk(KERN_ERR "DISP FG fb not found\n");
+ return -EPERM;
+ }
+
+ fbvar = fbi->var;
+
+ /* Store the overlay frame buffer's original std */
+ cam->fb_origin_std = fbvar.nonstd;
+
+ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) {
+ /* Use DP to do CSC so that we can get better performance */
+ vf_out_format = IPU_PIX_FMT_UYVY;
+ fbvar.nonstd = vf_out_format;
+ color = 0x80;
+ } else {
+ vf_out_format = IPU_PIX_FMT_RGB565;
+ fbvar.nonstd = 0;
+ color = 0x0;
+ }
+
+ fbvar.bits_per_pixel = 16;
+ fbvar.xres = fbvar.xres_virtual = cam->win.w.width;
+ fbvar.yres = cam->win.w.height;
+ fbvar.yres_virtual = cam->win.w.height * 2;
+ fbvar.yoffset = 0;
+ fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG;
+ fbvar.activate |= FB_ACTIVATE_FORCE;
+ fb_set_var(fbi, &fbvar);
+
+ ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left,
+ cam->win.w.top);
+
+ /* Fill black color for framebuffer */
+ tmp = (short *) fbi->screen_base;
+ for (i = 0; i < (fbi->fix.line_length * fbi->var.yres)/2;
+ i++, tmp++)
+ *tmp = color;
+
+ console_lock();
+ fb_blank(fbi, FB_BLANK_UNBLANK);
+ console_unlock();
+
+ /* correct display ch buffer address */
+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+ 0, fbi->fix.smem_start +
+ (fbi->fix.line_length * fbvar.yres));
+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+ 1, fbi->fix.smem_start);
+
+ memset(&vf, 0, sizeof(ipu_channel_params_t));
+ ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width,
+ &vf.csi_prp_vf_mem.in_height, cam->csi);
+ vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
+ vf.csi_prp_vf_mem.out_width = cam->win.w.width;
+ vf.csi_prp_vf_mem.out_height = cam->win.w.height;
+ vf.csi_prp_vf_mem.csi = cam->csi;
+ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
+ vf.csi_prp_vf_mem.out_width = cam->win.w.height;
+ vf.csi_prp_vf_mem.out_height = cam->win.w.width;
+ }
+ vf.csi_prp_vf_mem.out_pixel_fmt = vf_out_format;
+ size = cam->win.w.width * cam->win.w.height * size;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id) {
+ vf.csi_prp_vf_mem.mipi_en = true;
+ vf.csi_prp_vf_mem.mipi_vc =
+ mipi_csi2_get_virtual_channel(mipi_csi2_info);
+ vf.csi_prp_vf_mem.mipi_id =
+ mipi_csi2_get_datatype(mipi_csi2_info);
+
+ mipi_csi2_pixelclk_enable(mipi_csi2_info);
+ } else {
+ vf.csi_prp_vf_mem.mipi_en = false;
+ vf.csi_prp_vf_mem.mipi_vc = 0;
+ vf.csi_prp_vf_mem.mipi_id = 0;
+ }
+ } else {
+ vf.csi_prp_vf_mem.mipi_en = false;
+ vf.csi_prp_vf_mem.mipi_vc = 0;
+ vf.csi_prp_vf_mem.mipi_id = 0;
+ }
+ }
+#endif
+
+ err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf);
+ if (err != 0)
+ goto out_5;
+
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0],
+ (dma_addr_t) cam->vf_bufs[0]);
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1],
+ (dma_addr_t) cam->vf_bufs[1]);
+ }
+ cam->vf_bufs_size[0] = PAGE_ALIGN(size);
+ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
+ cam->vf_bufs_size[0],
+ (dma_addr_t *) &
+ cam->vf_bufs[0],
+ GFP_DMA |
+ GFP_KERNEL);
+ if (cam->vf_bufs_vaddr[0] == NULL) {
+ printk(KERN_ERR "Error to allocate vf buffer\n");
+ err = -ENOMEM;
+ goto out_4;
+ }
+ cam->vf_bufs_size[1] = PAGE_ALIGN(size);
+ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
+ cam->vf_bufs_size[1],
+ (dma_addr_t *) &
+ cam->vf_bufs[1],
+ GFP_DMA |
+ GFP_KERNEL);
+ if (cam->vf_bufs_vaddr[1] == NULL) {
+ printk(KERN_ERR "Error to allocate vf buffer\n");
+ err = -ENOMEM;
+ goto out_3;
+ }
+ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);
+
+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
+ IPU_OUTPUT_BUFFER,
+ vf_out_format,
+ vf.csi_prp_vf_mem.out_width,
+ vf.csi_prp_vf_mem.out_height,
+ vf.csi_prp_vf_mem.out_width,
+ IPU_ROTATE_NONE,
+ cam->vf_bufs[0], cam->vf_bufs[1],
+ 0, 0, 0);
+ if (err != 0)
+ goto out_3;
+
+ err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL);
+ if (err != 0) {
+ printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n");
+ goto out_3;
+ }
+
+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_INPUT_BUFFER,
+ vf_out_format,
+ vf.csi_prp_vf_mem.out_width,
+ vf.csi_prp_vf_mem.out_height,
+ vf.csi_prp_vf_mem.out_width,
+ cam->vf_rotation,
+ cam->vf_bufs[0],
+ cam->vf_bufs[1],
+ 0, 0, 0);
+ if (err != 0) {
+ printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n");
+ goto out_2;
+ }
+
+ if (cam->vf_rotation < IPU_ROTATE_90_RIGHT) {
+ temp = vf.csi_prp_vf_mem.out_width;
+ vf.csi_prp_vf_mem.out_width =
+ vf.csi_prp_vf_mem.out_height;
+ vf.csi_prp_vf_mem.out_height = temp;
+ }
+
+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_OUTPUT_BUFFER,
+ vf_out_format,
+ vf.csi_prp_vf_mem.out_height,
+ vf.csi_prp_vf_mem.out_width,
+ vf.csi_prp_vf_mem.out_height,
+ IPU_ROTATE_NONE,
+ fbi->fix.smem_start +
+ (fbi->fix.line_length *
+ fbi->var.yres),
+ fbi->fix.smem_start, 0, 0, 0);
+
+ if (err != 0) {
+ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
+ goto out_2;
+ }
+
+ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF);
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF,
+ prpvf_rot_eof_callback,
+ 0, "Mxc Camera", cam);
+ if (err < 0) {
+ printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_ROT_OUT_EOF\n");
+ goto out_2;
+ }
+
+ err = ipu_link_channels(cam->ipu,
+ CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
+ if (err < 0) {
+ printk(KERN_ERR
+ "Error link CSI_PRP_VF_MEM-MEM_ROT_VF_MEM\n");
+ goto out_1;
+ }
+
+ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
+ ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM);
+
+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+ IPU_OUTPUT_BUFFER, 0);
+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+ IPU_OUTPUT_BUFFER, 1);
+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_OUTPUT_BUFFER, 0);
+ } else {
+ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
+ IPU_OUTPUT_BUFFER,
+ vf_out_format, cam->win.w.width,
+ cam->win.w.height,
+ cam->win.w.width,
+ cam->vf_rotation,
+ fbi->fix.smem_start +
+ (fbi->fix.line_length *
+ fbi->var.yres),
+ fbi->fix.smem_start, 0, 0, 0);
+ if (err != 0) {
+ printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
+ goto out_4;
+ }
+ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF);
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF,
+ prpvf_rot_eof_callback,
+ 0, "Mxc Camera", cam);
+ if (err < 0) {
+ printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_OUT_EOF\n");
+ goto out_4;
+ }
+
+ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
+
+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+ IPU_OUTPUT_BUFFER, 0);
+ }
+
+ cam->overlay_active = true;
+ return err;
+
+out_1:
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL);
+out_2:
+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP)
+ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
+out_3:
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0],
+ (dma_addr_t) cam->vf_bufs[0]);
+ cam->vf_bufs_vaddr[0] = NULL;
+ cam->vf_bufs[0] = 0;
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1],
+ (dma_addr_t) cam->vf_bufs[1]);
+ cam->vf_bufs_vaddr[1] = NULL;
+ cam->vf_bufs[1] = 0;
+ }
+out_4:
+ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
+out_5:
+ return err;
+}
+
+/*!
+ * prpvf_stop - stop the vf task
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ */
+static int prpvf_stop(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0, i = 0;
+ struct fb_info *fbi = NULL;
+ struct fb_var_screeninfo fbvar;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ if (cam->overlay_active == false)
+ return 0;
+
+ for (i = 0; i < num_registered_fb; i++) {
+ char *idstr = registered_fb[i]->fix.id;
+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
+ fbi = registered_fb[i];
+ break;
+ }
+ }
+
+ if (fbi == NULL) {
+ printk(KERN_ERR "DISP FG fb not found\n");
+ return -EPERM;
+ }
+
+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+ ipu_unlink_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, cam);
+ }
+ buffer_num = 0;
+
+ ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true);
+
+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+ ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true);
+ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
+ }
+ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
+
+ console_lock();
+ fb_blank(fbi, FB_BLANK_POWERDOWN);
+ console_unlock();
+
+ /* Set the overlay frame buffer std to what it is used to be */
+ fbvar = fbi->var;
+ fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG;
+ fbvar.nonstd = cam->fb_origin_std;
+ fbvar.activate |= FB_ACTIVATE_FORCE;
+ fb_set_var(fbi, &fbvar);
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id)
+ mipi_csi2_pixelclk_disable(mipi_csi2_info);
+ }
+ }
+#endif
+
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0],
+ (dma_addr_t) cam->vf_bufs[0]);
+ cam->vf_bufs_vaddr[0] = NULL;
+ cam->vf_bufs[0] = 0;
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1],
+ (dma_addr_t) cam->vf_bufs[1]);
+ cam->vf_bufs_vaddr[1] = NULL;
+ cam->vf_bufs[1] = 0;
+ }
+
+ cam->overlay_active = false;
+ return err;
+}
+
+/*!
+ * Enable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_vf_enable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_vf_disable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ /* free csi eof irq firstly.
+ * when disable csi, wait for idmac eof.
+ * it requests eof irq again */
+ if (cam->vf_rotation < IPU_ROTATE_VERT_FLIP)
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
+
+ return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select PRP-VF as the working path
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ * @return status
+ */
+int prp_vf_sdc_select(void *private)
+{
+ cam_data *cam;
+ int err = 0;
+ if (private) {
+ cam = (cam_data *) private;
+ cam->vf_start_sdc = prpvf_start;
+ cam->vf_stop_sdc = prpvf_stop;
+ cam->vf_enable_csi = prp_vf_enable_csi;
+ cam->vf_disable_csi = prp_vf_disable_csi;
+ cam->overlay_active = false;
+ } else
+ err = -EIO;
+
+ return err;
+}
+EXPORT_SYMBOL(prp_vf_sdc_select);
+
+/*!
+ * function to de-select PRP-VF as the working path
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ * @return int
+ */
+int prp_vf_sdc_deselect(void *private)
+{
+ cam_data *cam;
+
+ if (private) {
+ cam = (cam_data *) private;
+ cam->vf_start_sdc = NULL;
+ cam->vf_stop_sdc = NULL;
+ cam->vf_enable_csi = NULL;
+ cam->vf_disable_csi = NULL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(prp_vf_sdc_deselect);
+
+/*!
+ * Init viewfinder task.
+ *
+ * @return Error code indicating success or failure
+ */
+__init int prp_vf_sdc_init(void)
+{
+ return 0;
+}
+
+/*!
+ * Deinit viewfinder task.
+ *
+ * @return Error code indicating success or failure
+ */
+void __exit prp_vf_sdc_exit(void)
+{
+}
+
+module_init(prp_vf_sdc_init);
+module_exit(prp_vf_sdc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP VF SDC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c b/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c
new file mode 100644
index 000000000000..a24d82dfca63
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c
@@ -0,0 +1,521 @@
+/*
+ * Copyright 2004-2014 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 ipu_prp_vf_sdc_bg.c
+ *
+ * @brief IPU Use case for PRP-VF back-ground
+ *
+ * @ingroup IPU
+ */
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/ipu.h>
+#include <linux/module.h>
+#include <mach/mipi_csi2.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+static int buffer_num;
+static int buffer_ready;
+static struct ipu_soc *disp_ipu;
+
+static void get_disp_ipu(cam_data *cam)
+{
+ if (cam->output > 2)
+ disp_ipu = ipu_get_soc(1); /* using DISP4 */
+ else
+ disp_ipu = ipu_get_soc(0);
+}
+
+/*
+ * Function definitions
+ */
+
+/*!
+ * SDC V-Sync callback function.
+ *
+ * @param irq int irq line
+ * @param dev_id void * device id
+ *
+ * @return status IRQ_HANDLED for handled
+ */
+static irqreturn_t prpvf_sdc_vsync_callback(int irq, void *dev_id)
+{
+ cam_data *cam = dev_id;
+ if (buffer_ready > 0) {
+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_OUTPUT_BUFFER, 0);
+ buffer_ready--;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*!
+ * VF EOF callback function.
+ *
+ * @param irq int irq line
+ * @param dev_id void * device id
+ *
+ * @return status IRQ_HANDLED for handled
+ */
+static irqreturn_t prpvf_vf_eof_callback(int irq, void *dev_id)
+{
+ cam_data *cam = dev_id;
+ pr_debug("buffer_ready %d buffer_num %d\n", buffer_ready, buffer_num);
+
+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_INPUT_BUFFER, buffer_num);
+ buffer_num = (buffer_num == 0) ? 1 : 0;
+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM,
+ IPU_OUTPUT_BUFFER, buffer_num);
+ buffer_ready++;
+ return IRQ_HANDLED;
+}
+
+/*!
+ * prpvf_start - start the vf task
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ */
+static int prpvf_start(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ ipu_channel_params_t vf;
+ u32 format;
+ u32 offset;
+ u32 bpp, size = 3;
+ int err = 0;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ if (!cam) {
+ printk(KERN_ERR "private is NULL\n");
+ return -EIO;
+ }
+
+ if (cam->overlay_active == true) {
+ pr_debug("already start.\n");
+ return 0;
+ }
+
+ get_disp_ipu(cam);
+
+ format = cam->v4l2_fb.fmt.pixelformat;
+ if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) {
+ bpp = 3, size = 3;
+ pr_info("BGR24\n");
+ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) {
+ bpp = 2, size = 2;
+ pr_info("RGB565\n");
+ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) {
+ bpp = 4, size = 4;
+ pr_info("BGR32\n");
+ } else {
+ printk(KERN_ERR
+ "unsupported fix format from the framebuffer.\n");
+ return -EINVAL;
+ }
+
+ offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top +
+ size * cam->win.w.left;
+
+ if (cam->v4l2_fb.base == 0)
+ printk(KERN_ERR "invalid frame buffer address.\n");
+ else
+ offset += (u32) cam->v4l2_fb.base;
+
+ memset(&vf, 0, sizeof(ipu_channel_params_t));
+ ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width,
+ &vf.csi_prp_vf_mem.in_height, cam->csi);
+ vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
+ vf.csi_prp_vf_mem.out_width = cam->win.w.width;
+ vf.csi_prp_vf_mem.out_height = cam->win.w.height;
+ vf.csi_prp_vf_mem.csi = cam->csi;
+ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
+ vf.csi_prp_vf_mem.out_width = cam->win.w.height;
+ vf.csi_prp_vf_mem.out_height = cam->win.w.width;
+ }
+ vf.csi_prp_vf_mem.out_pixel_fmt = format;
+ size = cam->win.w.width * cam->win.w.height * size;
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id) {
+ vf.csi_prp_vf_mem.mipi_en = true;
+ vf.csi_prp_vf_mem.mipi_vc =
+ mipi_csi2_get_virtual_channel(mipi_csi2_info);
+ vf.csi_prp_vf_mem.mipi_id =
+ mipi_csi2_get_datatype(mipi_csi2_info);
+
+ mipi_csi2_pixelclk_enable(mipi_csi2_info);
+ } else {
+ vf.csi_prp_vf_mem.mipi_en = false;
+ vf.csi_prp_vf_mem.mipi_vc = 0;
+ vf.csi_prp_vf_mem.mipi_id = 0;
+ }
+ } else {
+ vf.csi_prp_vf_mem.mipi_en = false;
+ vf.csi_prp_vf_mem.mipi_vc = 0;
+ vf.csi_prp_vf_mem.mipi_id = 0;
+ }
+ }
+#endif
+
+ err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf);
+ if (err != 0)
+ goto out_4;
+
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
+ }
+ cam->vf_bufs_size[0] = PAGE_ALIGN(size);
+ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
+ cam->vf_bufs_size[0],
+ &cam->vf_bufs[0],
+ GFP_DMA |
+ GFP_KERNEL);
+ if (cam->vf_bufs_vaddr[0] == NULL) {
+ printk(KERN_ERR "Error to allocate vf buffer\n");
+ err = -ENOMEM;
+ goto out_3;
+ }
+ cam->vf_bufs_size[1] = PAGE_ALIGN(size);
+ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
+ cam->vf_bufs_size[1],
+ &cam->vf_bufs[1],
+ GFP_DMA |
+ GFP_KERNEL);
+ if (cam->vf_bufs_vaddr[1] == NULL) {
+ printk(KERN_ERR "Error to allocate vf buffer\n");
+ err = -ENOMEM;
+ goto out_3;
+ }
+
+ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM,
+ IPU_OUTPUT_BUFFER,
+ format, vf.csi_prp_vf_mem.out_width,
+ vf.csi_prp_vf_mem.out_height,
+ vf.csi_prp_vf_mem.out_width,
+ IPU_ROTATE_NONE,
+ cam->vf_bufs[0],
+ cam->vf_bufs[1],
+ 0, 0, 0);
+ if (err != 0) {
+ printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
+ goto out_3;
+ }
+ err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL);
+ if (err != 0) {
+ printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n");
+ goto out_3;
+ }
+
+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_INPUT_BUFFER,
+ format, vf.csi_prp_vf_mem.out_width,
+ vf.csi_prp_vf_mem.out_height,
+ vf.csi_prp_vf_mem.out_width,
+ cam->vf_rotation,
+ cam->vf_bufs[0],
+ cam->vf_bufs[1],
+ 0, 0, 0);
+ if (err != 0) {
+ printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n");
+ goto out_2;
+ }
+
+ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_OUTPUT_BUFFER,
+ format,
+ vf.csi_prp_vf_mem.out_height,
+ vf.csi_prp_vf_mem.out_width,
+ cam->overlay_fb->var.xres * bpp,
+ IPU_ROTATE_NONE,
+ offset, 0, 0, 0, 0);
+
+ if (err != 0) {
+ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
+ goto out_2;
+ }
+ } else {
+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM,
+ IPU_OUTPUT_BUFFER,
+ format,
+ vf.csi_prp_vf_mem.out_width,
+ vf.csi_prp_vf_mem.out_height,
+ cam->overlay_fb->var.xres * bpp,
+ IPU_ROTATE_NONE,
+ offset, 0, 0, 0, 0);
+ if (err != 0) {
+ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n");
+ goto out_2;
+ }
+ }
+
+ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF);
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF,
+ prpvf_vf_eof_callback,
+ 0, "Mxc Camera", cam);
+ if (err != 0) {
+ printk(KERN_ERR
+ "Error registering IPU_IRQ_PRP_VF_OUT_EOF irq.\n");
+ goto out_2;
+ }
+
+ ipu_clear_irq(disp_ipu, IPU_IRQ_BG_SF_END);
+ err = ipu_request_irq(disp_ipu, IPU_IRQ_BG_SF_END,
+ prpvf_sdc_vsync_callback,
+ 0, "Mxc Camera", cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error registering IPU_IRQ_BG_SF_END irq.\n");
+ goto out_1;
+ }
+
+ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
+ ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM);
+
+ buffer_num = 0;
+ buffer_ready = 0;
+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 0);
+
+ cam->overlay_active = true;
+ return err;
+
+out_1:
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL);
+out_2:
+ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
+out_3:
+ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
+out_4:
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
+ cam->vf_bufs_vaddr[0] = NULL;
+ cam->vf_bufs[0] = 0;
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
+ cam->vf_bufs_vaddr[1] = NULL;
+ cam->vf_bufs[1] = 0;
+ }
+ if (cam->rot_vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->rot_vf_buf_size[0],
+ cam->rot_vf_bufs_vaddr[0],
+ cam->rot_vf_bufs[0]);
+ cam->rot_vf_bufs_vaddr[0] = NULL;
+ cam->rot_vf_bufs[0] = 0;
+ }
+ if (cam->rot_vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->rot_vf_buf_size[1],
+ cam->rot_vf_bufs_vaddr[1],
+ cam->rot_vf_bufs[1]);
+ cam->rot_vf_bufs_vaddr[1] = NULL;
+ cam->rot_vf_bufs[1] = 0;
+ }
+ return err;
+}
+
+/*!
+ * prpvf_stop - stop the vf task
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ */
+static int prpvf_stop(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+#ifdef CONFIG_MXC_MIPI_CSI2
+ void *mipi_csi2_info;
+ int ipu_id;
+ int csi_id;
+#endif
+
+ if (cam->overlay_active == false)
+ return 0;
+
+ ipu_free_irq(disp_ipu, IPU_IRQ_BG_SF_END, cam);
+
+ ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true);
+ ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true);
+ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM);
+ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
+
+#ifdef CONFIG_MXC_MIPI_CSI2
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ if (mipi_csi2_info) {
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);
+
+ if (cam->ipu == ipu_get_soc(ipu_id)
+ && cam->csi == csi_id)
+ mipi_csi2_pixelclk_disable(mipi_csi2_info);
+ }
+ }
+#endif
+
+ if (cam->vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->vf_bufs_size[0],
+ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]);
+ cam->vf_bufs_vaddr[0] = NULL;
+ cam->vf_bufs[0] = 0;
+ }
+ if (cam->vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->vf_bufs_size[1],
+ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]);
+ cam->vf_bufs_vaddr[1] = NULL;
+ cam->vf_bufs[1] = 0;
+ }
+ if (cam->rot_vf_bufs_vaddr[0]) {
+ dma_free_coherent(0, cam->rot_vf_buf_size[0],
+ cam->rot_vf_bufs_vaddr[0],
+ cam->rot_vf_bufs[0]);
+ cam->rot_vf_bufs_vaddr[0] = NULL;
+ cam->rot_vf_bufs[0] = 0;
+ }
+ if (cam->rot_vf_bufs_vaddr[1]) {
+ dma_free_coherent(0, cam->rot_vf_buf_size[1],
+ cam->rot_vf_bufs_vaddr[1],
+ cam->rot_vf_bufs[1]);
+ cam->rot_vf_bufs_vaddr[1] = NULL;
+ cam->rot_vf_bufs[1] = 0;
+ }
+
+ buffer_num = 0;
+ buffer_ready = 0;
+ cam->overlay_active = false;
+ return 0;
+}
+
+/*!
+ * Enable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_vf_enable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ return ipu_enable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * Disable csi
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_vf_disable_csi(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ /* free csi eof irq firstly.
+ * when disable csi, wait for idmac eof.
+ * it requests eof irq again */
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
+
+ return ipu_disable_csi(cam->ipu, cam->csi);
+}
+
+/*!
+ * function to select PRP-VF as the working path
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ * @return status
+ */
+int prp_vf_sdc_select_bg(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ if (cam) {
+ cam->vf_start_sdc = prpvf_start;
+ cam->vf_stop_sdc = prpvf_stop;
+ cam->vf_enable_csi = prp_vf_enable_csi;
+ cam->vf_disable_csi = prp_vf_disable_csi;
+ cam->overlay_active = false;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(prp_vf_sdc_select_bg);
+
+/*!
+ * function to de-select PRP-VF as the working path
+ *
+ * @param private cam_data * mxc v4l2 main structure
+ *
+ * @return status
+ */
+int prp_vf_sdc_deselect_bg(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ if (cam) {
+ cam->vf_start_sdc = NULL;
+ cam->vf_stop_sdc = NULL;
+ cam->vf_enable_csi = NULL;
+ cam->vf_disable_csi = NULL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(prp_vf_sdc_deselect_bg);
+
+/*!
+ * Init viewfinder task.
+ *
+ * @return Error code indicating success or failure
+ */
+__init int prp_vf_sdc_init_bg(void)
+{
+ return 0;
+}
+
+/*!
+ * Deinit viewfinder task.
+ *
+ * @return Error code indicating success or failure
+ */
+void __exit prp_vf_sdc_exit_bg(void)
+{
+}
+
+module_init(prp_vf_sdc_init_bg);
+module_exit(prp_vf_sdc_exit_bg);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_still.c b/drivers/media/platform/mxc/capture/ipu_still.c
new file mode 100644
index 000000000000..b18c3cf873cc
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ipu_still.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2004-2014 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 ipu_still.c
+ *
+ * @brief IPU Use case for still image capture
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/module.h>
+#include <linux/semaphore.h>
+#include <linux/sched.h>
+#include <linux/ipu.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+static int callback_eof_flag;
+#ifndef CONFIG_MXC_IPU_V1
+static int buffer_num;
+#endif
+
+#ifdef CONFIG_MXC_IPU_V1
+static int callback_flag;
+/*
+ * Function definitions
+ */
+/*!
+ * CSI EOF callback function.
+ *
+ * @param irq int irq line
+ * @param dev_id void * device id
+ *
+ * @return status IRQ_HANDLED for handled
+ */
+static irqreturn_t prp_csi_eof_callback(int irq, void *dev_id)
+{
+ cam_data *cam = devid;
+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
+ callback_flag%2 ? 1 : 0);
+ if (callback_flag == 0)
+ ipu_enable_channel(cam->ipu, CSI_MEM);
+
+ callback_flag++;
+ return IRQ_HANDLED;
+}
+#endif
+
+/*!
+ * CSI callback function.
+ *
+ * @param irq int irq line
+ * @param dev_id void * device id
+ *
+ * @return status IRQ_HANDLED for handled
+ */
+static irqreturn_t prp_still_callback(int irq, void *dev_id)
+{
+ cam_data *cam = (cam_data *) dev_id;
+
+ callback_eof_flag++;
+ if (callback_eof_flag < 5) {
+#ifndef CONFIG_MXC_IPU_V1
+ buffer_num = (buffer_num == 0) ? 1 : 0;
+ ipu_select_buffer(cam->ipu, CSI_MEM,
+ IPU_OUTPUT_BUFFER, buffer_num);
+#endif
+ } else {
+ cam->still_counter++;
+ wake_up_interruptible(&cam->still_queue);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*!
+ * start csi->mem task
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_still_start(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ u32 pixel_fmt;
+ int err;
+ ipu_channel_params_t params;
+
+ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
+ pixel_fmt = IPU_PIX_FMT_YUV420P;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
+ pixel_fmt = IPU_PIX_FMT_NV12;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
+ pixel_fmt = IPU_PIX_FMT_YUV422P;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
+ pixel_fmt = IPU_PIX_FMT_UYVY;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+ pixel_fmt = IPU_PIX_FMT_YUYV;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
+ pixel_fmt = IPU_PIX_FMT_BGR24;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
+ pixel_fmt = IPU_PIX_FMT_RGB24;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
+ pixel_fmt = IPU_PIX_FMT_RGB565;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
+ pixel_fmt = IPU_PIX_FMT_BGR32;
+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
+ pixel_fmt = IPU_PIX_FMT_RGB32;
+ else {
+ printk(KERN_ERR "format not supported\n");
+ return -EINVAL;
+ }
+
+ memset(&params, 0, sizeof(params));
+ err = ipu_init_channel(cam->ipu, CSI_MEM, &params);
+ if (err != 0)
+ return err;
+
+ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
+ pixel_fmt, cam->v2f.fmt.pix.width,
+ cam->v2f.fmt.pix.height,
+ cam->v2f.fmt.pix.width, IPU_ROTATE_NONE,
+ cam->still_buf[0], cam->still_buf[1], 0,
+ 0, 0);
+ if (err != 0)
+ return err;
+
+#ifdef CONFIG_MXC_IPU_V1
+ ipu_clear_irq(IPU_IRQ_SENSOR_OUT_EOF);
+ err = ipu_request_irq(IPU_IRQ_SENSOR_OUT_EOF, prp_still_callback,
+ 0, "Mxc Camera", cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error registering irq.\n");
+ return err;
+ }
+ callback_flag = 0;
+ callback_eof_flag = 0;
+ ipu_clear_irq(IPU_IRQ_SENSOR_EOF);
+ err = ipu_request_irq(IPU_IRQ_SENSOR_EOF, prp_csi_eof_callback,
+ 0, "Mxc Camera", cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error IPU_IRQ_SENSOR_EOF\n");
+ return err;
+ }
+#else
+ callback_eof_flag = 0;
+ buffer_num = 0;
+
+ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,
+ prp_still_callback,
+ 0, "Mxc Camera", cam);
+ if (err != 0) {
+ printk(KERN_ERR "Error registering irq.\n");
+ return err;
+ }
+
+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0);
+ ipu_enable_channel(cam->ipu, CSI_MEM);
+ ipu_enable_csi(cam->ipu, cam->csi);
+#endif
+
+ return err;
+}
+
+/*!
+ * stop csi->mem encoder task
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+static int prp_still_stop(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+
+#ifdef CONFIG_MXC_IPU_V1
+ ipu_free_irq(IPU_IRQ_SENSOR_EOF, NULL);
+ ipu_free_irq(IPU_IRQ_SENSOR_OUT_EOF, cam);
+#else
+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);
+#endif
+
+ ipu_disable_csi(cam->ipu, cam->csi);
+ ipu_disable_channel(cam->ipu, CSI_MEM, true);
+ ipu_uninit_channel(cam->ipu, CSI_MEM);
+
+ return err;
+}
+
+/*!
+ * function to select CSI_MEM as the working path
+ *
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+int prp_still_select(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+
+ if (cam) {
+ cam->csi_start = prp_still_start;
+ cam->csi_stop = prp_still_stop;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(prp_still_select);
+
+/*!
+ * function to de-select CSI_MEM as the working path
+ *
+ * @param private struct cam_data * mxc capture instance
+ *
+ * @return status
+ */
+int prp_still_deselect(void *private)
+{
+ cam_data *cam = (cam_data *) private;
+ int err = 0;
+
+ err = prp_still_stop(cam);
+
+ if (cam) {
+ cam->csi_start = NULL;
+ cam->csi_stop = NULL;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(prp_still_deselect);
+
+/*!
+ * Init the Encorder channels
+ *
+ * @return Error code indicating success or failure
+ */
+__init int prp_still_init(void)
+{
+ return 0;
+}
+
+/*!
+ * Deinit the Encorder channels
+ *
+ */
+void __exit prp_still_exit(void)
+{
+}
+
+module_init(prp_still_init);
+module_exit(prp_still_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IPU PRP STILL IMAGE Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
new file mode 100644
index 000000000000..3d7adecaa325
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
@@ -0,0 +1,3148 @@
+/*
+ * Copyright 2004-2015 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 drivers/media/video/mxc/capture/mxc_v4l2_capture.c
+ *
+ * @brief Mxc Video For Linux 2 driver
+ *
+ * @ingroup MXC_V4L2_CAPTURE
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/mxcfb.h>
+#include <linux/of_device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include "v4l2-int-device.h"
+#include <linux/fsl_devices.h>
+#include "mxc_v4l2_capture.h"
+#include "ipu_prp_sw.h"
+
+#define init_MUTEX(sem) sema_init(sem, 1)
+
+static struct platform_device_id imx_v4l2_devtype[] = {
+ {
+ .name = "v4l2-capture-imx5",
+ .driver_data = IMX5_V4L2,
+ }, {
+ .name = "v4l2-capture-imx6",
+ .driver_data = IMX6_V4L2,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imx_v4l2_devtype);
+
+static const struct of_device_id mxc_v4l2_dt_ids[] = {
+ {
+ .compatible = "fsl,imx6q-v4l2-capture",
+ .data = &imx_v4l2_devtype[IMX6_V4L2],
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, mxc_v4l2_dt_ids);
+
+static int video_nr = -1;
+
+/*! This data is used for the output to the display. */
+#define MXC_V4L2_CAPTURE_NUM_OUTPUTS 6
+#define MXC_V4L2_CAPTURE_NUM_INPUTS 2
+static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = {
+ {
+ .index = 0,
+ .name = "DISP3 BG",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
+ {
+ .index = 1,
+ .name = "DISP3 BG - DI1",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
+ {
+ .index = 2,
+ .name = "DISP3 FG",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
+ {
+ .index = 3,
+ .name = "DISP4 BG",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
+ {
+ .index = 4,
+ .name = "DISP4 BG - DI1",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
+ {
+ .index = 5,
+ .name = "DISP4 FG",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
+};
+
+static struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = {
+ {
+ .index = 0,
+ .name = "CSI IC MEM",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 0,
+ .tuner = 0,
+ .std = V4L2_STD_UNKNOWN,
+ .status = 0,
+ },
+ {
+ .index = 1,
+ .name = "CSI MEM",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 0,
+ .tuner = 0,
+ .std = V4L2_STD_UNKNOWN,
+ .status = V4L2_IN_ST_NO_POWER,
+ },
+};
+
+/*! List of TV input video formats supported. The video formats is corresponding
+ * to the v4l2_id in video_fmt_t.
+ * Currently, only PAL and NTSC is supported. Needs to be expanded in the
+ * future.
+ */
+typedef enum {
+ TV_NTSC = 0, /*!< Locked on (M) NTSC video signal. */
+ TV_PAL, /*!< (B, G, H, I, N)PAL video signal. */
+ TV_NOT_LOCKED, /*!< Not locked on a signal. */
+} video_fmt_idx;
+
+/*! Number of video standards supported (including 'not locked' signal). */
+#define TV_STD_MAX (TV_NOT_LOCKED + 1)
+
+/*! Video format structure. */
+typedef struct {
+ int v4l2_id; /*!< Video for linux ID. */
+ char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */
+ u16 raw_width; /*!< Raw width. */
+ u16 raw_height; /*!< Raw height. */
+ u16 active_width; /*!< Active width. */
+ u16 active_height; /*!< Active height. */
+ u16 active_top; /*!< Active top. */
+ u16 active_left; /*!< Active left. */
+} video_fmt_t;
+
+/*!
+ * Description of video formats supported.
+ *
+ * PAL: raw=720x625, active=720x576.
+ * NTSC: raw=720x525, active=720x480.
+ */
+static video_fmt_t video_fmts[] = {
+ { /*! NTSC */
+ .v4l2_id = V4L2_STD_NTSC,
+ .name = "NTSC",
+ .raw_width = 720, /* SENS_FRM_WIDTH */
+ .raw_height = 525, /* SENS_FRM_HEIGHT */
+ .active_width = 720, /* ACT_FRM_WIDTH */
+ .active_height = 480, /* ACT_FRM_HEIGHT */
+ .active_top = 13,
+ .active_left = 0,
+ },
+ { /*! (B, G, H, I, N) PAL */
+ .v4l2_id = V4L2_STD_PAL,
+ .name = "PAL",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ .active_top = 0,
+ .active_left = 0,
+ },
+ { /*! Unlocked standard */
+ .v4l2_id = V4L2_STD_ALL,
+ .name = "Autodetect",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ .active_top = 0,
+ .active_left = 0,
+ },
+};
+
+/*!* Standard index of TV. */
+static video_fmt_idx video_index = TV_NOT_LOCKED;
+
+static int mxc_v4l2_master_attach(struct v4l2_int_device *slave);
+static void mxc_v4l2_master_detach(struct v4l2_int_device *slave);
+static int start_preview(cam_data *cam);
+static int stop_preview(cam_data *cam);
+
+/*! Information about this driver. */
+static struct v4l2_int_master mxc_v4l2_master = {
+ .attach = mxc_v4l2_master_attach,
+ .detach = mxc_v4l2_master_detach,
+};
+
+/***************************************************************************
+ * Functions for handling Frame buffers.
+ **************************************************************************/
+
+/*!
+ * Free frame buffers
+ *
+ * @param cam Structure cam_data *
+ *
+ * @return status 0 success.
+ */
+static int mxc_free_frame_buf(cam_data *cam)
+{
+ int i;
+
+ pr_debug("MVC: In mxc_free_frame_buf\n");
+
+ for (i = 0; i < FRAME_NUM; i++) {
+ if (cam->frame[i].vaddress != 0) {
+ dma_free_coherent(0, cam->frame[i].buffer.length,
+ cam->frame[i].vaddress,
+ cam->frame[i].paddress);
+ cam->frame[i].vaddress = 0;
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ * Allocate frame buffers
+ *
+ * @param cam Structure cam_data*
+ * @param count int number of buffer need to allocated
+ *
+ * @return status -0 Successfully allocated a buffer, -ENOBUFS failed.
+ */
+static int mxc_allocate_frame_buf(cam_data *cam, int count)
+{
+ int i;
+
+ pr_debug("In MVC:mxc_allocate_frame_buf - size=%d\n",
+ cam->v2f.fmt.pix.sizeimage);
+
+ for (i = 0; i < count; i++) {
+ cam->frame[i].vaddress =
+ dma_alloc_coherent(0,
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+ &cam->frame[i].paddress,
+ GFP_DMA | GFP_KERNEL);
+ if (cam->frame[i].vaddress == 0) {
+ pr_err("ERROR: v4l2 capture: "
+ "mxc_allocate_frame_buf failed.\n");
+ mxc_free_frame_buf(cam);
+ return -ENOBUFS;
+ }
+ cam->frame[i].buffer.index = i;
+ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
+ cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cam->frame[i].buffer.length =
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
+ cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP;
+ cam->frame[i].buffer.m.offset = cam->frame[i].paddress;
+ cam->frame[i].index = i;
+ }
+
+ return 0;
+}
+
+/*!
+ * Free frame buffers status
+ *
+ * @param cam Structure cam_data *
+ *
+ * @return none
+ */
+static void mxc_free_frames(cam_data *cam)
+{
+ int i;
+
+ pr_debug("In MVC:mxc_free_frames\n");
+
+ for (i = 0; i < FRAME_NUM; i++)
+ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
+
+ cam->enc_counter = 0;
+ INIT_LIST_HEAD(&cam->ready_q);
+ INIT_LIST_HEAD(&cam->working_q);
+ INIT_LIST_HEAD(&cam->done_q);
+}
+
+/*!
+ * Return the buffer status
+ *
+ * @param cam Structure cam_data *
+ * @param buf Structure v4l2_buffer *
+ *
+ * @return status 0 success, EINVAL failed.
+ */
+static int mxc_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf)
+{
+ pr_debug("In MVC:mxc_v4l2_buffer_status\n");
+
+ if (buf->index < 0 || buf->index >= FRAME_NUM) {
+ pr_err("ERROR: v4l2 capture: mxc_v4l2_buffer_status buffers "
+ "not allocated\n");
+ return -EINVAL;
+ }
+
+ memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf));
+ return 0;
+}
+
+static int mxc_v4l2_release_bufs(cam_data *cam)
+{
+ pr_debug("In MVC:mxc_v4l2_release_bufs\n");
+ return 0;
+}
+
+static int mxc_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf)
+{
+ pr_debug("In MVC:mxc_v4l2_prepare_bufs\n");
+
+ if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length <
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage)) {
+ pr_err("ERROR: v4l2 capture: mxc_v4l2_prepare_bufs buffers "
+ "not allocated,index=%d, length=%d\n", buf->index,
+ buf->length);
+ return -EINVAL;
+ }
+
+ cam->frame[buf->index].buffer.index = buf->index;
+ cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED;
+ cam->frame[buf->index].buffer.length = buf->length;
+ cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress
+ = buf->m.offset;
+ cam->frame[buf->index].buffer.type = buf->type;
+ cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR;
+ cam->frame[buf->index].index = buf->index;
+
+ return 0;
+}
+
+/***************************************************************************
+ * Functions for handling the video stream.
+ **************************************************************************/
+
+/*!
+ * Indicates whether the palette is supported.
+ *
+ * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32
+ *
+ * @return 0 if failed
+ */
+static inline int valid_mode(u32 palette)
+{
+ return ((palette == V4L2_PIX_FMT_RGB565) ||
+ (palette == V4L2_PIX_FMT_BGR24) ||
+ (palette == V4L2_PIX_FMT_RGB24) ||
+ (palette == V4L2_PIX_FMT_BGR32) ||
+ (palette == V4L2_PIX_FMT_RGB32) ||
+ (palette == V4L2_PIX_FMT_YUV422P) ||
+ (palette == V4L2_PIX_FMT_UYVY) ||
+ (palette == V4L2_PIX_FMT_YUYV) ||
+ (palette == V4L2_PIX_FMT_YUV420) ||
+ (palette == V4L2_PIX_FMT_YVU420) ||
+ (palette == V4L2_PIX_FMT_NV12));
+}
+
+/*!
+ * Start the encoder job
+ *
+ * @param cam structure cam_data *
+ *
+ * @return status 0 Success
+ */
+static int mxc_streamon(cam_data *cam)
+{
+ struct mxc_v4l_frame *frame;
+ unsigned long lock_flags;
+ int err = 0;
+
+ pr_debug("In MVC:mxc_streamon\n");
+
+ if (NULL == cam) {
+ pr_err("ERROR! cam parameter is NULL\n");
+ return -1;
+ }
+
+ if (cam->capture_on) {
+ pr_err("ERROR: v4l2 capture: Capture stream has been turned "
+ " on\n");
+ return -1;
+ }
+
+ if (list_empty(&cam->ready_q)) {
+ pr_err("ERROR: v4l2 capture: mxc_streamon buffer has not been "
+ "queued yet\n");
+ return -EINVAL;
+ }
+ if (cam->enc_update_eba &&
+ cam->ready_q.prev == cam->ready_q.next) {
+ pr_err("ERROR: v4l2 capture: mxc_streamon buffer need "
+ "ping pong at least two buffers\n");
+ return -EINVAL;
+ }
+
+ cam->capture_pid = current->pid;
+
+ if (cam->overlay_on == true)
+ stop_preview(cam);
+
+ if (cam->enc_enable) {
+ err = cam->enc_enable(cam);
+ if (err != 0)
+ return err;
+ }
+
+ spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
+ cam->ping_pong_csi = 0;
+ cam->local_buf_num = 0;
+ if (cam->enc_update_eba) {
+ frame =
+ list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
+ list_del(cam->ready_q.next);
+ list_add_tail(&frame->queue, &cam->working_q);
+ frame->ipu_buf_num = cam->ping_pong_csi;
+ err = cam->enc_update_eba(cam, frame->buffer.m.offset);
+
+ frame =
+ list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
+ list_del(cam->ready_q.next);
+ list_add_tail(&frame->queue, &cam->working_q);
+ frame->ipu_buf_num = cam->ping_pong_csi;
+ err |= cam->enc_update_eba(cam, frame->buffer.m.offset);
+ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
+ } else {
+ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
+ return -EINVAL;
+ }
+
+ if (cam->overlay_on == true)
+ start_preview(cam);
+
+ if (cam->enc_enable_csi) {
+ err = cam->enc_enable_csi(cam);
+ if (err != 0)
+ return err;
+ }
+
+ cam->capture_on = true;
+
+ return err;
+}
+
+/*!
+ * Shut down the encoder job
+ *
+ * @param cam structure cam_data *
+ *
+ * @return status 0 Success
+ */
+static int mxc_streamoff(cam_data *cam)
+{
+ int err = 0;
+
+ pr_debug("In MVC:mxc_streamoff\n");
+
+ if (cam->capture_on == false)
+ return 0;
+
+ /* For both CSI--MEM and CSI--IC--MEM
+ * 1. wait for idmac eof
+ * 2. disable csi first
+ * 3. disable idmac
+ * 4. disable smfc (CSI--MEM channel)
+ */
+ if (mxc_capture_inputs[cam->current_input].name != NULL) {
+ if (cam->enc_disable_csi) {
+ err = cam->enc_disable_csi(cam);
+ if (err != 0)
+ return err;
+ }
+ if (cam->enc_disable) {
+ err = cam->enc_disable(cam);
+ if (err != 0)
+ return err;
+ }
+ }
+
+ mxc_free_frames(cam);
+ mxc_capture_inputs[cam->current_input].status |= V4L2_IN_ST_NO_POWER;
+ cam->capture_on = false;
+ return err;
+}
+
+/*!
+ * Valid and adjust the overlay window size, position
+ *
+ * @param cam structure cam_data *
+ * @param win struct v4l2_window *
+ *
+ * @return 0
+ */
+static int verify_preview(cam_data *cam, struct v4l2_window *win)
+{
+ int i = 0, width_bound = 0, height_bound = 0;
+ int *width, *height;
+ unsigned int ipu_ch = CHAN_NONE;
+ struct fb_info *bg_fbi = NULL, *fbi = NULL;
+ bool foregound_fb = false;
+ mm_segment_t old_fs;
+
+ pr_debug("In MVC: verify_preview\n");
+
+ do {
+ fbi = (struct fb_info *)registered_fb[i];
+ if (fbi == NULL) {
+ pr_err("ERROR: verify_preview frame buffer NULL.\n");
+ return -1;
+ }
+
+ /* Which DI supports 2 layers? */
+ if (((strncmp(fbi->fix.id, "DISP3 BG", 8) == 0) &&
+ (cam->output < 3)) ||
+ ((strncmp(fbi->fix.id, "DISP4 BG", 8) == 0) &&
+ (cam->output >= 3))) {
+ if (fbi->fbops->fb_ioctl) {
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN,
+ (unsigned long)&ipu_ch);
+ set_fs(old_fs);
+ }
+ if (ipu_ch == MEM_BG_SYNC) {
+ bg_fbi = fbi;
+ pr_debug("Found background frame buffer.\n");
+ }
+ }
+
+ /* Found the frame buffer to preview on. */
+ if (strcmp(fbi->fix.id,
+ mxc_capture_outputs[cam->output].name) == 0) {
+ if (((strcmp(fbi->fix.id, "DISP3 FG") == 0) &&
+ (cam->output < 3)) ||
+ ((strcmp(fbi->fix.id, "DISP4 FG") == 0) &&
+ (cam->output >= 3)))
+ foregound_fb = true;
+
+ cam->overlay_fb = fbi;
+ break;
+ }
+ } while (++i < FB_MAX);
+
+ if (foregound_fb) {
+ width_bound = bg_fbi->var.xres;
+ height_bound = bg_fbi->var.yres;
+
+ if (win->w.width + win->w.left > bg_fbi->var.xres ||
+ win->w.height + win->w.top > bg_fbi->var.yres) {
+ pr_err("ERROR: FG window position exceeds.\n");
+ return -1;
+ }
+ } else {
+ /* 4 bytes alignment for BG */
+ width_bound = cam->overlay_fb->var.xres;
+ height_bound = cam->overlay_fb->var.yres;
+
+ if (cam->overlay_fb->var.bits_per_pixel == 24)
+ win->w.left -= win->w.left % 4;
+ else if (cam->overlay_fb->var.bits_per_pixel == 16)
+ win->w.left -= win->w.left % 2;
+
+ if (win->w.width + win->w.left > cam->overlay_fb->var.xres)
+ win->w.width = cam->overlay_fb->var.xres - win->w.left;
+ if (win->w.height + win->w.top > cam->overlay_fb->var.yres)
+ win->w.height = cam->overlay_fb->var.yres - win->w.top;
+ }
+
+ /* stride line limitation */
+ win->w.height -= win->w.height % 8;
+ win->w.width -= win->w.width % 8;
+
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+ height = &win->w.width;
+ width = &win->w.height;
+ } else {
+ width = &win->w.width;
+ height = &win->w.height;
+ }
+
+ if (*width == 0 || *height == 0) {
+ pr_err("ERROR: v4l2 capture: width or height"
+ " too small.\n");
+ return -EINVAL;
+ }
+
+ if ((cam->crop_bounds.width / *width > 8) ||
+ ((cam->crop_bounds.width / *width == 8) &&
+ (cam->crop_bounds.width % *width))) {
+ *width = cam->crop_bounds.width / 8;
+ if (*width % 8)
+ *width += 8 - *width % 8;
+ if (*width + win->w.left > width_bound) {
+ pr_err("ERROR: v4l2 capture: width exceeds "
+ "resize limit.\n");
+ return -1;
+ }
+ pr_err("ERROR: v4l2 capture: width exceeds limit. "
+ "Resize to %d.\n",
+ *width);
+ }
+
+ if ((cam->crop_bounds.height / *height > 8) ||
+ ((cam->crop_bounds.height / *height == 8) &&
+ (cam->crop_bounds.height % *height))) {
+ *height = cam->crop_bounds.height / 8;
+ if (*height % 8)
+ *height += 8 - *height % 8;
+ if (*height + win->w.top > height_bound) {
+ pr_err("ERROR: v4l2 capture: height exceeds "
+ "resize limit.\n");
+ return -1;
+ }
+ pr_err("ERROR: v4l2 capture: height exceeds limit "
+ "resize to %d.\n",
+ *height);
+ }
+
+ return 0;
+}
+
+/*!
+ * start the viewfinder job
+ *
+ * @param cam structure cam_data *
+ *
+ * @return status 0 Success
+ */
+static int start_preview(cam_data *cam)
+{
+ int err = 0;
+
+ pr_debug("MVC: start_preview\n");
+
+ if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY)
+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+ err = prp_vf_sdc_select(cam);
+ #else
+ err = foreground_sdc_select(cam);
+ #endif
+ else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY)
+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+ err = prp_vf_sdc_select_bg(cam);
+ #else
+ err = bg_overlay_sdc_select(cam);
+ #endif
+ if (err != 0)
+ return err;
+
+ if (cam->vf_start_sdc) {
+ err = cam->vf_start_sdc(cam);
+ if (err != 0)
+ return err;
+ }
+
+ if (cam->vf_enable_csi)
+ err = cam->vf_enable_csi(cam);
+
+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+ __func__,
+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+ __func__,
+ cam->crop_bounds.width, cam->crop_bounds.height);
+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+ __func__,
+ cam->crop_defrect.width, cam->crop_defrect.height);
+ pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+ __func__,
+ cam->crop_current.width, cam->crop_current.height);
+
+ return err;
+}
+
+/*!
+ * shut down the viewfinder job
+ *
+ * @param cam structure cam_data *
+ *
+ * @return status 0 Success
+ */
+static int stop_preview(cam_data *cam)
+{
+ int err = 0;
+
+ if (cam->vf_disable_csi) {
+ err = cam->vf_disable_csi(cam);
+ if (err != 0)
+ return err;
+ }
+
+ if (cam->vf_stop_sdc) {
+ err = cam->vf_stop_sdc(cam);
+ if (err != 0)
+ return err;
+ }
+
+ if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY)
+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+ err = prp_vf_sdc_deselect(cam);
+ #else
+ err = foreground_sdc_deselect(cam);
+ #endif
+ else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY)
+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+ err = prp_vf_sdc_deselect_bg(cam);
+ #else
+ err = bg_overlay_sdc_deselect(cam);
+ #endif
+
+ return err;
+}
+
+/***************************************************************************
+ * VIDIOC Functions.
+ **************************************************************************/
+
+/*!
+ * V4L2 - mxc_v4l2_g_fmt function
+ *
+ * @param cam structure cam_data *
+ *
+ * @param f structure v4l2_format *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f)
+{
+ int retval = 0;
+
+ pr_debug("In MVC: mxc_v4l2_g_fmt type=%d\n", f->type);
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+ f->fmt.pix = cam->v2f.fmt.pix;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
+ f->fmt.win = cam->win;
+ break;
+ default:
+ pr_debug(" type is invalid\n");
+ retval = -EINVAL;
+ }
+
+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+ __func__,
+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+ __func__,
+ cam->crop_bounds.width, cam->crop_bounds.height);
+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+ __func__,
+ cam->crop_defrect.width, cam->crop_defrect.height);
+ pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+ __func__,
+ cam->crop_current.width, cam->crop_current.height);
+
+ return retval;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_s_fmt function
+ *
+ * @param cam structure cam_data *
+ *
+ * @param f structure v4l2_format *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
+{
+ int retval = 0;
+ int size = 0;
+ int bytesperline = 0;
+ int *width, *height;
+
+ pr_debug("In MVC: mxc_v4l2_s_fmt\n");
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+ if (!valid_mode(f->fmt.pix.pixelformat)) {
+ pr_err("ERROR: v4l2 capture: mxc_v4l2_s_fmt: format "
+ "not supported\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Force the capture window resolution to be crop bounds
+ * for CSI MEM input mode.
+ */
+ if (strcmp(mxc_capture_inputs[cam->current_input].name,
+ "CSI MEM") == 0) {
+ f->fmt.pix.width = cam->crop_current.width;
+ f->fmt.pix.height = cam->crop_current.height;
+ }
+
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
+ height = &f->fmt.pix.width;
+ width = &f->fmt.pix.height;
+ } else {
+ width = &f->fmt.pix.width;
+ height = &f->fmt.pix.height;
+ }
+
+ /* stride line limitation */
+ *width -= *width % 8;
+ *height -= *height % 8;
+
+ if (*width == 0 || *height == 0) {
+ pr_err("ERROR: v4l2 capture: width or height"
+ " too small.\n");
+ return -EINVAL;
+ }
+
+ if ((cam->crop_current.width / *width > 8) ||
+ ((cam->crop_current.width / *width == 8) &&
+ (cam->crop_current.width % *width))) {
+ *width = cam->crop_current.width / 8;
+ if (*width % 8)
+ *width += 8 - *width % 8;
+ pr_err("ERROR: v4l2 capture: width exceeds limit "
+ "resize to %d.\n",
+ *width);
+ }
+
+ if ((cam->crop_current.height / *height > 8) ||
+ ((cam->crop_current.height / *height == 8) &&
+ (cam->crop_current.height % *height))) {
+ *height = cam->crop_current.height / 8;
+ if (*height % 8)
+ *height += 8 - *height % 8;
+ pr_err("ERROR: v4l2 capture: height exceeds limit "
+ "resize to %d.\n",
+ *height);
+ }
+
+ switch (f->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB565:
+ size = f->fmt.pix.width * f->fmt.pix.height * 2;
+ bytesperline = f->fmt.pix.width * 2;
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ size = f->fmt.pix.width * f->fmt.pix.height * 3;
+ bytesperline = f->fmt.pix.width * 3;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ size = f->fmt.pix.width * f->fmt.pix.height * 3;
+ bytesperline = f->fmt.pix.width * 3;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ size = f->fmt.pix.width * f->fmt.pix.height * 4;
+ bytesperline = f->fmt.pix.width * 4;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ size = f->fmt.pix.width * f->fmt.pix.height * 4;
+ bytesperline = f->fmt.pix.width * 4;
+ break;
+ case V4L2_PIX_FMT_YUV422P:
+ size = f->fmt.pix.width * f->fmt.pix.height * 2;
+ bytesperline = f->fmt.pix.width;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUYV:
+ size = f->fmt.pix.width * f->fmt.pix.height * 2;
+ bytesperline = f->fmt.pix.width * 2;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
+ bytesperline = f->fmt.pix.width;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
+ bytesperline = f->fmt.pix.width;
+ break;
+ default:
+ break;
+ }
+
+ if (f->fmt.pix.bytesperline < bytesperline)
+ f->fmt.pix.bytesperline = bytesperline;
+ else
+ bytesperline = f->fmt.pix.bytesperline;
+
+ if (f->fmt.pix.sizeimage < size)
+ f->fmt.pix.sizeimage = size;
+ else
+ size = f->fmt.pix.sizeimage;
+
+ cam->v2f.fmt.pix = f->fmt.pix;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
+ retval = verify_preview(cam, &f->fmt.win);
+ cam->win = f->fmt.win;
+ break;
+ default:
+ retval = -EINVAL;
+ }
+
+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+ __func__,
+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+ __func__,
+ cam->crop_bounds.width, cam->crop_bounds.height);
+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+ __func__,
+ cam->crop_defrect.width, cam->crop_defrect.height);
+ pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+ __func__,
+ cam->crop_current.width, cam->crop_current.height);
+
+ return retval;
+}
+
+/*!
+ * get control param
+ *
+ * @param cam structure cam_data *
+ *
+ * @param c structure v4l2_control *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
+{
+ int status = 0;
+
+ pr_debug("In MVC:mxc_v4l2_g_ctrl\n");
+
+ /* probably don't need to store the values that can be retrieved,
+ * locally, but they are for now. */
+ switch (c->id) {
+ case V4L2_CID_HFLIP:
+ /* This is handled in the ipu. */
+ if (cam->rotation == IPU_ROTATE_HORIZ_FLIP)
+ c->value = 1;
+ break;
+ case V4L2_CID_VFLIP:
+ /* This is handled in the ipu. */
+ if (cam->rotation == IPU_ROTATE_VERT_FLIP)
+ c->value = 1;
+ break;
+ case V4L2_CID_MXC_ROT:
+ /* This is handled in the ipu. */
+ c->value = cam->rotation;
+ break;
+ case V4L2_CID_BRIGHTNESS:
+ if (cam->sensor) {
+ c->value = cam->bright;
+ status = vidioc_int_g_ctrl(cam->sensor, c);
+ cam->bright = c->value;
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ status = -ENODEV;
+ }
+ break;
+ case V4L2_CID_HUE:
+ if (cam->sensor) {
+ c->value = cam->hue;
+ status = vidioc_int_g_ctrl(cam->sensor, c);
+ cam->hue = c->value;
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ status = -ENODEV;
+ }
+ break;
+ case V4L2_CID_CONTRAST:
+ if (cam->sensor) {
+ c->value = cam->contrast;
+ status = vidioc_int_g_ctrl(cam->sensor, c);
+ cam->contrast = c->value;
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ status = -ENODEV;
+ }
+ break;
+ case V4L2_CID_SATURATION:
+ if (cam->sensor) {
+ c->value = cam->saturation;
+ status = vidioc_int_g_ctrl(cam->sensor, c);
+ cam->saturation = c->value;
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ status = -ENODEV;
+ }
+ break;
+ case V4L2_CID_RED_BALANCE:
+ if (cam->sensor) {
+ c->value = cam->red;
+ status = vidioc_int_g_ctrl(cam->sensor, c);
+ cam->red = c->value;
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ status = -ENODEV;
+ }
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ if (cam->sensor) {
+ c->value = cam->blue;
+ status = vidioc_int_g_ctrl(cam->sensor, c);
+ cam->blue = c->value;
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ status = -ENODEV;
+ }
+ break;
+ case V4L2_CID_BLACK_LEVEL:
+ if (cam->sensor) {
+ c->value = cam->ae_mode;
+ status = vidioc_int_g_ctrl(cam->sensor, c);
+ cam->ae_mode = c->value;
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ status = -ENODEV;
+ }
+ break;
+ default:
+ pr_err("ERROR: v4l2 capture: unsupported ioctrl!\n");
+ }
+
+ return status;
+}
+
+/*!
+ * V4L2 - set_control function
+ * V4L2_CID_PRIVATE_BASE is the extention for IPU preprocessing.
+ * 0 for normal operation
+ * 1 for vertical flip
+ * 2 for horizontal flip
+ * 3 for horizontal and vertical flip
+ * 4 for 90 degree rotation
+ * @param cam structure cam_data *
+ *
+ * @param c structure v4l2_control *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
+{
+ int i, ret = 0;
+ int tmp_rotation = IPU_ROTATE_NONE;
+ struct sensor_data *sensor_data;
+
+ pr_debug("In MVC:mxc_v4l2_s_ctrl\n");
+
+ switch (c->id) {
+ case V4L2_CID_HFLIP:
+ /* This is done by the IPU */
+ if (c->value == 1) {
+ if ((cam->rotation != IPU_ROTATE_VERT_FLIP) &&
+ (cam->rotation != IPU_ROTATE_180))
+ cam->rotation = IPU_ROTATE_HORIZ_FLIP;
+ else
+ cam->rotation = IPU_ROTATE_180;
+ } else {
+ if (cam->rotation == IPU_ROTATE_HORIZ_FLIP)
+ cam->rotation = IPU_ROTATE_NONE;
+ if (cam->rotation == IPU_ROTATE_180)
+ cam->rotation = IPU_ROTATE_VERT_FLIP;
+ }
+ break;
+ case V4L2_CID_VFLIP:
+ /* This is done by the IPU */
+ if (c->value == 1) {
+ if ((cam->rotation != IPU_ROTATE_HORIZ_FLIP) &&
+ (cam->rotation != IPU_ROTATE_180))
+ cam->rotation = IPU_ROTATE_VERT_FLIP;
+ else
+ cam->rotation = IPU_ROTATE_180;
+ } else {
+ if (cam->rotation == IPU_ROTATE_VERT_FLIP)
+ cam->rotation = IPU_ROTATE_NONE;
+ if (cam->rotation == IPU_ROTATE_180)
+ cam->rotation = IPU_ROTATE_HORIZ_FLIP;
+ }
+ break;
+ case V4L2_CID_MXC_ROT:
+ case V4L2_CID_MXC_VF_ROT:
+ /* This is done by the IPU */
+ switch (c->value) {
+ case V4L2_MXC_ROTATE_NONE:
+ tmp_rotation = IPU_ROTATE_NONE;
+ break;
+ case V4L2_MXC_ROTATE_VERT_FLIP:
+ tmp_rotation = IPU_ROTATE_VERT_FLIP;
+ break;
+ case V4L2_MXC_ROTATE_HORIZ_FLIP:
+ tmp_rotation = IPU_ROTATE_HORIZ_FLIP;
+ break;
+ case V4L2_MXC_ROTATE_180:
+ tmp_rotation = IPU_ROTATE_180;
+ break;
+ case V4L2_MXC_ROTATE_90_RIGHT:
+ tmp_rotation = IPU_ROTATE_90_RIGHT;
+ break;
+ case V4L2_MXC_ROTATE_90_RIGHT_VFLIP:
+ tmp_rotation = IPU_ROTATE_90_RIGHT_VFLIP;
+ break;
+ case V4L2_MXC_ROTATE_90_RIGHT_HFLIP:
+ tmp_rotation = IPU_ROTATE_90_RIGHT_HFLIP;
+ break;
+ case V4L2_MXC_ROTATE_90_LEFT:
+ tmp_rotation = IPU_ROTATE_90_LEFT;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC
+ if (c->id == V4L2_CID_MXC_VF_ROT)
+ cam->vf_rotation = tmp_rotation;
+ else
+ cam->rotation = tmp_rotation;
+ #else
+ cam->rotation = tmp_rotation;
+ #endif
+
+ break;
+ case V4L2_CID_HUE:
+ if (cam->sensor) {
+ cam->hue = c->value;
+ ret = vidioc_int_s_ctrl(cam->sensor, c);
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ ret = -ENODEV;
+ }
+ break;
+ case V4L2_CID_CONTRAST:
+ if (cam->sensor) {
+ cam->contrast = c->value;
+ ret = vidioc_int_s_ctrl(cam->sensor, c);
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ ret = -ENODEV;
+ }
+ break;
+ case V4L2_CID_BRIGHTNESS:
+ if (cam->sensor) {
+ cam->bright = c->value;
+ ret = vidioc_int_s_ctrl(cam->sensor, c);
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ ret = -ENODEV;
+ }
+ break;
+ case V4L2_CID_SATURATION:
+ if (cam->sensor) {
+ cam->saturation = c->value;
+ ret = vidioc_int_s_ctrl(cam->sensor, c);
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ ret = -ENODEV;
+ }
+ break;
+ case V4L2_CID_RED_BALANCE:
+ if (cam->sensor) {
+ cam->red = c->value;
+ ret = vidioc_int_s_ctrl(cam->sensor, c);
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ ret = -ENODEV;
+ }
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ if (cam->sensor) {
+ cam->blue = c->value;
+ ret = vidioc_int_s_ctrl(cam->sensor, c);
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ ret = -ENODEV;
+ }
+ break;
+ case V4L2_CID_EXPOSURE:
+ if (cam->sensor) {
+ cam->ae_mode = c->value;
+ ret = vidioc_int_s_ctrl(cam->sensor, c);
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ ret = -ENODEV;
+ }
+ break;
+ case V4L2_CID_MXC_FLASH:
+#ifdef CONFIG_MXC_IPU_V1
+ ipu_csi_flash_strobe(true);
+#endif
+ break;
+ case V4L2_CID_MXC_SWITCH_CAM:
+ if (cam->sensor == cam->all_sensors[c->value])
+ break;
+
+ /* power down other cameraes before enable new one */
+ for (i = 0; i < cam->sensor_index; i++) {
+ if (i != c->value) {
+ vidioc_int_dev_exit(cam->all_sensors[i]);
+ vidioc_int_s_power(cam->all_sensors[i], 0);
+ if (cam->mclk_on[cam->mclk_source]) {
+ ipu_csi_enable_mclk_if(cam->ipu,
+ CSI_MCLK_I2C,
+ cam->mclk_source,
+ false, false);
+ cam->mclk_on[cam->mclk_source] =
+ false;
+ }
+ }
+ }
+ sensor_data = cam->all_sensors[c->value]->priv;
+ if (sensor_data->io_init)
+ sensor_data->io_init();
+ cam->sensor = cam->all_sensors[c->value];
+ cam->mclk_source = sensor_data->mclk_source;
+ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
+ cam->mclk_source, true, true);
+ cam->mclk_on[cam->mclk_source] = true;
+ vidioc_int_s_power(cam->sensor, 1);
+ vidioc_int_dev_init(cam->sensor);
+ break;
+ default:
+ pr_debug(" default case\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_s_param function
+ * Allows setting of capturemode and frame rate.
+ *
+ * @param cam structure cam_data *
+ * @param parm structure v4l2_streamparm *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
+{
+ struct v4l2_ifparm ifparm;
+ struct v4l2_format cam_fmt;
+ struct v4l2_streamparm currentparm;
+ ipu_csi_signal_cfg_t csi_param;
+ u32 current_fps, parm_fps;
+ int err = 0;
+
+ pr_debug("In mxc_v4l2_s_param\n");
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ pr_err(KERN_ERR "mxc_v4l2_s_param invalid type\n");
+ return -EINVAL;
+ }
+
+ /* Stop the viewfinder */
+ if (cam->overlay_on == true)
+ stop_preview(cam);
+
+ currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ /* First check that this device can support the changes requested. */
+ err = vidioc_int_g_parm(cam->sensor, &currentparm);
+ if (err) {
+ pr_err("%s: vidioc_int_g_parm returned an error %d\n",
+ __func__, err);
+ goto exit;
+ }
+
+ current_fps = currentparm.parm.capture.timeperframe.denominator
+ / currentparm.parm.capture.timeperframe.numerator;
+ parm_fps = parm->parm.capture.timeperframe.denominator
+ / parm->parm.capture.timeperframe.numerator;
+
+ pr_debug(" Current capabilities are %x\n",
+ currentparm.parm.capture.capability);
+ pr_debug(" Current capturemode is %d change to %d\n",
+ currentparm.parm.capture.capturemode,
+ parm->parm.capture.capturemode);
+ pr_debug(" Current framerate is %d change to %d\n",
+ current_fps, parm_fps);
+
+ /* This will change any camera settings needed. */
+ err = vidioc_int_s_parm(cam->sensor, parm);
+ if (err) {
+ pr_err("%s: vidioc_int_s_parm returned an error %d\n",
+ __func__, err);
+ goto exit;
+ }
+
+ /* If resolution changed, need to re-program the CSI */
+ /* Get new values. */
+ vidioc_int_g_ifparm(cam->sensor, &ifparm);
+
+ csi_param.data_width = 0;
+ csi_param.clk_mode = 0;
+ csi_param.ext_vsync = 0;
+ csi_param.Vsync_pol = 0;
+ csi_param.Hsync_pol = 0;
+ csi_param.pixclk_pol = 0;
+ csi_param.data_pol = 0;
+ csi_param.sens_clksrc = 0;
+ csi_param.pack_tight = 0;
+ csi_param.force_eof = 0;
+ csi_param.data_en_pol = 0;
+ csi_param.data_fmt = 0;
+ csi_param.csi = cam->csi;
+ csi_param.mclk = 0;
+
+ pr_debug(" clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr);
+ if (ifparm.u.bt656.clock_curr == 0)
+ csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
+ else
+ csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
+
+ csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
+
+ if (ifparm.u.bt656.mode == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT) {
+ csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
+ } else if (ifparm.u.bt656.mode
+ == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT) {
+ csi_param.data_width = IPU_CSI_DATA_WIDTH_10;
+ } else {
+ csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
+ }
+
+ csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv;
+ csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv;
+ csi_param.ext_vsync = ifparm.u.bt656.bt_sync_correct;
+
+ /* if the capturemode changed, the size bounds will have changed. */
+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
+ pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n",
+ cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
+
+ csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
+
+ cam->crop_bounds.top = cam->crop_bounds.left = 0;
+ cam->crop_bounds.width = cam_fmt.fmt.pix.width;
+ cam->crop_bounds.height = cam_fmt.fmt.pix.height;
+
+ /*
+ * Set the default current cropped resolution to be the same with
+ * the cropping boundary(except for tvin module).
+ */
+ if (cam->device_type != 1) {
+ cam->crop_current.width = cam->crop_bounds.width;
+ cam->crop_current.height = cam->crop_bounds.height;
+ }
+
+ /* This essentially loses the data at the left and bottom of the image
+ * giving a digital zoom image, if crop_current is less than the full
+ * size of the image. */
+ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
+ cam->crop_current.height, cam->csi);
+ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
+ cam->crop_current.top,
+ cam->csi);
+ ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width,
+ cam->crop_bounds.height,
+ cam_fmt.fmt.pix.pixelformat, csi_param);
+
+
+exit:
+ if (cam->overlay_on == true)
+ start_preview(cam);
+
+ return err;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_s_std function
+ *
+ * Sets the TV standard to be used.
+ *
+ * @param cam structure cam_data *
+ * @param parm structure v4l2_streamparm *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_std(cam_data *cam, v4l2_std_id e)
+{
+ pr_debug("In mxc_v4l2_s_std %Lx\n", e);
+
+ if (e == V4L2_STD_PAL) {
+ pr_debug(" Setting standard to PAL %Lx\n", V4L2_STD_PAL);
+ cam->standard.id = V4L2_STD_PAL;
+ video_index = TV_PAL;
+ } else if (e == V4L2_STD_NTSC) {
+ pr_debug(" Setting standard to NTSC %Lx\n",
+ V4L2_STD_NTSC);
+ /* Get rid of the white dot line in NTSC signal input */
+ cam->standard.id = V4L2_STD_NTSC;
+ video_index = TV_NTSC;
+ } else {
+ cam->standard.id = V4L2_STD_ALL;
+ video_index = TV_NOT_LOCKED;
+ pr_err("ERROR: unrecognized std! %Lx (PAL=%Lx, NTSC=%Lx\n",
+ e, V4L2_STD_PAL, V4L2_STD_NTSC);
+ }
+
+ cam->standard.index = video_index;
+ strcpy(cam->standard.name, video_fmts[video_index].name);
+ cam->crop_bounds.width = video_fmts[video_index].raw_width;
+ cam->crop_bounds.height = video_fmts[video_index].raw_height;
+ cam->crop_current.width = video_fmts[video_index].active_width;
+ cam->crop_current.height = video_fmts[video_index].active_height;
+ cam->crop_current.top = video_fmts[video_index].active_top;
+ cam->crop_current.left = video_fmts[video_index].active_left;
+
+ return 0;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_g_std function
+ *
+ * Gets the TV standard from the TV input device.
+ *
+ * @param cam structure cam_data *
+ *
+ * @param e structure v4l2_streamparm *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_g_std(cam_data *cam, v4l2_std_id *e)
+{
+ struct v4l2_format tv_fmt;
+
+ pr_debug("In mxc_v4l2_g_std\n");
+
+ if (cam->device_type == 1) {
+ /* Use this function to get what the TV-In device detects the
+ * format to be. pixelformat is used to return the std value
+ * since the interface has no vidioc_g_std.*/
+ tv_fmt.type = V4L2_BUF_TYPE_PRIVATE;
+ vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt);
+
+ /* If the TV-in automatically detects the standard, then if it
+ * changes, the settings need to change. */
+ if (cam->standard_autodetect) {
+ if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) {
+ pr_debug("MVC: mxc_v4l2_g_std: "
+ "Changing standard\n");
+ mxc_v4l2_s_std(cam, tv_fmt.fmt.pix.pixelformat);
+ }
+ }
+
+ *e = tv_fmt.fmt.pix.pixelformat;
+ }
+
+ return 0;
+}
+
+/*!
+ * Dequeue one V4L capture buffer
+ *
+ * @param cam structure cam_data *
+ * @param buf structure v4l2_buffer *
+ *
+ * @return status 0 success, EINVAL invalid frame number,
+ * ETIME timeout, ERESTARTSYS interrupted by user
+ */
+static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
+{
+ int retval = 0;
+ struct mxc_v4l_frame *frame;
+ unsigned long lock_flags;
+
+ pr_debug("In MVC:mxc_v4l_dqueue\n");
+
+ if (!wait_event_interruptible_timeout(cam->enc_queue,
+ cam->enc_counter != 0,
+ 10 * HZ)) {
+ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout "
+ "enc_counter %x\n",
+ cam->enc_counter);
+ return -ETIME;
+ } else if (signal_pending(current)) {
+ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() "
+ "interrupt received\n");
+ return -ERESTARTSYS;
+ }
+
+ if (down_interruptible(&cam->busy_lock))
+ return -EBUSY;
+
+ spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags);
+ cam->enc_counter--;
+
+ frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue);
+ list_del(cam->done_q.next);
+ if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) {
+ frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE;
+ } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
+ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
+ "Buffer not filled.\n");
+ frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
+ retval = -EINVAL;
+ } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) {
+ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
+ "Buffer not queued.\n");
+ retval = -EINVAL;
+ }
+
+ cam->frame[frame->index].buffer.field = cam->device_type ?
+ V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
+
+ buf->bytesused = cam->v2f.fmt.pix.sizeimage;
+ buf->index = frame->index;
+ buf->flags = frame->buffer.flags;
+ buf->m = cam->frame[frame->index].buffer.m;
+ buf->timestamp = cam->frame[frame->index].buffer.timestamp;
+ buf->field = cam->frame[frame->index].buffer.field;
+ spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags);
+
+ up(&cam->busy_lock);
+ return retval;
+}
+
+/*!
+ * V4L interface - open function
+ *
+ * @param file structure file *
+ *
+ * @return status 0 success, ENODEV invalid device instance,
+ * ENODEV timeout, ERESTARTSYS interrupted by user
+ */
+static int mxc_v4l_open(struct file *file)
+{
+ struct v4l2_ifparm ifparm;
+ struct v4l2_format cam_fmt;
+ ipu_csi_signal_cfg_t csi_param;
+ struct video_device *dev = video_devdata(file);
+ cam_data *cam = video_get_drvdata(dev);
+ int err = 0;
+ struct sensor_data *sensor;
+
+ pr_debug("\nIn MVC: mxc_v4l_open\n");
+ pr_debug(" device name is %s\n", dev->name);
+
+ if (!cam) {
+ pr_err("ERROR: v4l2 capture: Internal error, "
+ "cam_data not found!\n");
+ return -EBADF;
+ }
+
+ if (cam->sensor == NULL ||
+ cam->sensor->type != v4l2_int_type_slave) {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ return -EAGAIN;
+ }
+
+ sensor = cam->sensor->priv;
+ if (!sensor) {
+ pr_err("%s: Internal error, sensor_data is not found!\n",
+ __func__);
+ return -EBADF;
+ }
+
+ down(&cam->busy_lock);
+ err = 0;
+ if (signal_pending(current))
+ goto oops;
+
+ if (cam->open_count++ == 0) {
+ wait_event_interruptible(cam->power_queue,
+ cam->low_power == false);
+
+ if (strcmp(mxc_capture_inputs[cam->current_input].name,
+ "CSI MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
+ err = csi_enc_select(cam);
+#endif
+ } else if (strcmp(mxc_capture_inputs[cam->current_input].name,
+ "CSI IC MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
+ err = prp_enc_select(cam);
+#endif
+ }
+
+ cam->enc_counter = 0;
+ INIT_LIST_HEAD(&cam->ready_q);
+ INIT_LIST_HEAD(&cam->working_q);
+ INIT_LIST_HEAD(&cam->done_q);
+
+ vidioc_int_g_ifparm(cam->sensor, &ifparm);
+
+ csi_param.sens_clksrc = 0;
+
+ csi_param.clk_mode = 0;
+ csi_param.data_pol = 0;
+ csi_param.ext_vsync = 0;
+
+ csi_param.pack_tight = 0;
+ csi_param.force_eof = 0;
+ csi_param.data_en_pol = 0;
+
+ csi_param.mclk = ifparm.u.bt656.clock_curr;
+
+ csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
+
+ if (ifparm.u.bt656.mode
+ == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT)
+ csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
+ else if (ifparm.u.bt656.mode
+ == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT)
+ csi_param.data_width = IPU_CSI_DATA_WIDTH_10;
+ else
+ csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
+
+
+ csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv;
+ csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv;
+
+ csi_param.csi = cam->csi;
+
+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
+
+ /* Reset the sizes. Needed to prevent carryover of last
+ * operation.*/
+ cam->crop_bounds.top = cam->crop_bounds.left = 0;
+ cam->crop_bounds.width = cam_fmt.fmt.pix.width;
+ cam->crop_bounds.height = cam_fmt.fmt.pix.height;
+
+ /* This also is the max crop size for this device. */
+ cam->crop_defrect.top = cam->crop_defrect.left = 0;
+ cam->crop_defrect.width = cam_fmt.fmt.pix.width;
+ cam->crop_defrect.height = cam_fmt.fmt.pix.height;
+
+ /* At this point, this is also the current image size. */
+ cam->crop_current.top = cam->crop_current.left = 0;
+ cam->crop_current.width = cam_fmt.fmt.pix.width;
+ cam->crop_current.height = cam_fmt.fmt.pix.height;
+
+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+ __func__,
+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+ __func__,
+ cam->crop_bounds.width, cam->crop_bounds.height);
+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+ __func__,
+ cam->crop_defrect.width, cam->crop_defrect.height);
+ pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+ __func__,
+ cam->crop_current.width, cam->crop_current.height);
+
+ csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
+ pr_debug("On Open: Input to ipu size is %d x %d\n",
+ cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
+ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
+ cam->crop_current.height,
+ cam->csi);
+ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
+ cam->crop_current.top,
+ cam->csi);
+ ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width,
+ cam->crop_bounds.height,
+ cam_fmt.fmt.pix.pixelformat,
+ csi_param);
+ clk_prepare_enable(sensor->sensor_clk);
+ vidioc_int_s_power(cam->sensor, 1);
+ vidioc_int_init(cam->sensor);
+ vidioc_int_dev_init(cam->sensor);
+ }
+
+ file->private_data = dev;
+
+oops:
+ up(&cam->busy_lock);
+ return err;
+}
+
+/*!
+ * V4L interface - close function
+ *
+ * @param file struct file *
+ *
+ * @return 0 success
+ */
+static int mxc_v4l_close(struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ int err = 0;
+ cam_data *cam = video_get_drvdata(dev);
+ struct sensor_data *sensor;
+ pr_debug("In MVC:mxc_v4l_close\n");
+
+ if (!cam) {
+ pr_err("ERROR: v4l2 capture: Internal error, "
+ "cam_data not found!\n");
+ return -EBADF;
+ }
+
+ if (!cam->sensor) {
+ pr_err("%s: Internal error, camera is not found!\n",
+ __func__);
+ return -EBADF;
+ }
+
+ sensor = cam->sensor->priv;
+ if (!sensor) {
+ pr_err("%s: Internal error, sensor_data is not found!\n",
+ __func__);
+ return -EBADF;
+ }
+
+ down(&cam->busy_lock);
+
+ /* for the case somebody hit the ctrl C */
+ if (cam->overlay_pid == current->pid && cam->overlay_on) {
+ err = stop_preview(cam);
+ cam->overlay_on = false;
+ }
+ if (cam->capture_pid == current->pid) {
+ err |= mxc_streamoff(cam);
+ wake_up_interruptible(&cam->enc_queue);
+ }
+
+ if (--cam->open_count == 0) {
+ vidioc_int_s_power(cam->sensor, 0);
+ clk_disable_unprepare(sensor->sensor_clk);
+ wait_event_interruptible(cam->power_queue,
+ cam->low_power == false);
+ pr_debug("mxc_v4l_close: release resource\n");
+
+ if (strcmp(mxc_capture_inputs[cam->current_input].name,
+ "CSI MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
+ err |= csi_enc_deselect(cam);
+#endif
+ } else if (strcmp(mxc_capture_inputs[cam->current_input].name,
+ "CSI IC MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
+ err |= prp_enc_deselect(cam);
+#endif
+ }
+
+ mxc_free_frame_buf(cam);
+ file->private_data = NULL;
+
+ /* capture off */
+ wake_up_interruptible(&cam->enc_queue);
+ mxc_free_frames(cam);
+ cam->enc_counter++;
+ }
+
+ up(&cam->busy_lock);
+
+ return err;
+}
+
+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC) || \
+ defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) || \
+ defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
+/*
+ * V4L interface - read function
+ *
+ * @param file struct file *
+ * @param read buf char *
+ * @param count size_t
+ * @param ppos structure loff_t *
+ *
+ * @return bytes read
+ */
+static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
+ loff_t *ppos)
+{
+ int err = 0;
+ u8 *v_address[2];
+ struct video_device *dev = video_devdata(file);
+ cam_data *cam = video_get_drvdata(dev);
+
+ if (down_interruptible(&cam->busy_lock))
+ return -EINTR;
+
+ /* Stop the viewfinder */
+ if (cam->overlay_on == true)
+ stop_preview(cam);
+
+ v_address[0] = dma_alloc_coherent(0,
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+ &cam->still_buf[0],
+ GFP_DMA | GFP_KERNEL);
+
+ v_address[1] = dma_alloc_coherent(0,
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+ &cam->still_buf[1],
+ GFP_DMA | GFP_KERNEL);
+
+ if (!v_address[0] || !v_address[1]) {
+ err = -ENOBUFS;
+ goto exit0;
+ }
+
+ err = prp_still_select(cam);
+ if (err != 0) {
+ err = -EIO;
+ goto exit0;
+ }
+
+ cam->still_counter = 0;
+ err = cam->csi_start(cam);
+ if (err != 0) {
+ err = -EIO;
+ goto exit1;
+ }
+
+ if (!wait_event_interruptible_timeout(cam->still_queue,
+ cam->still_counter != 0,
+ 10 * HZ)) {
+ pr_err("ERROR: v4l2 capture: mxc_v4l_read timeout counter %x\n",
+ cam->still_counter);
+ err = -ETIME;
+ goto exit1;
+ }
+ err = copy_to_user(buf, v_address[1], cam->v2f.fmt.pix.sizeimage);
+
+exit1:
+ prp_still_deselect(cam);
+
+exit0:
+ if (v_address[0] != 0)
+ dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[0],
+ cam->still_buf[0]);
+ if (v_address[1] != 0)
+ dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[1],
+ cam->still_buf[1]);
+
+ cam->still_buf[0] = cam->still_buf[1] = 0;
+
+ if (cam->overlay_on == true)
+ start_preview(cam);
+
+ up(&cam->busy_lock);
+ if (err < 0)
+ return err;
+
+ return cam->v2f.fmt.pix.sizeimage - err;
+}
+#endif
+
+/*!
+ * V4L interface - ioctl function
+ *
+ * @param file struct file*
+ *
+ * @param ioctlnr unsigned int
+ *
+ * @param arg void*
+ *
+ * @return 0 success, ENODEV for invalid device instance,
+ * -1 for other errors.
+ */
+static long mxc_v4l_do_ioctl(struct file *file,
+ unsigned int ioctlnr, void *arg)
+{
+ struct video_device *dev = video_devdata(file);
+ cam_data *cam = video_get_drvdata(dev);
+ int retval = 0;
+ unsigned long lock_flags;
+
+ pr_debug("In MVC: mxc_v4l_do_ioctl %x\n", ioctlnr);
+ wait_event_interruptible(cam->power_queue, cam->low_power == false);
+ /* make this _really_ smp-safe */
+ if (ioctlnr != VIDIOC_DQBUF)
+ if (down_interruptible(&cam->busy_lock))
+ return -EBUSY;
+
+ switch (ioctlnr) {
+ /*!
+ * V4l2 VIDIOC_QUERYCAP ioctl
+ */
+ case VIDIOC_QUERYCAP: {
+ struct v4l2_capability *cap = arg;
+ pr_debug(" case VIDIOC_QUERYCAP\n");
+ strcpy(cap->driver, "mxc_v4l2");
+ cap->version = KERNEL_VERSION(0, 1, 11);
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_VIDEO_OVERLAY |
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_READWRITE;
+ cap->card[0] = '\0';
+ cap->bus_info[0] = '\0';
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_G_FMT ioctl
+ */
+ case VIDIOC_G_FMT: {
+ struct v4l2_format *gf = arg;
+ pr_debug(" case VIDIOC_G_FMT\n");
+ retval = mxc_v4l2_g_fmt(cam, gf);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_S_DEST_CROP ioctl
+ */
+ case VIDIOC_S_DEST_CROP: {
+ struct v4l2_mxc_dest_crop *of = arg;
+ pr_debug(" case VIDIOC_S_DEST_CROP\n");
+ cam->offset.u_offset = of->offset.u_offset;
+ cam->offset.v_offset = of->offset.v_offset;
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_S_FMT ioctl
+ */
+ case VIDIOC_S_FMT: {
+ struct v4l2_format *sf = arg;
+ pr_debug(" case VIDIOC_S_FMT\n");
+ retval = mxc_v4l2_s_fmt(cam, sf);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_REQBUFS ioctl
+ */
+ case VIDIOC_REQBUFS: {
+ struct v4l2_requestbuffers *req = arg;
+ pr_debug(" case VIDIOC_REQBUFS\n");
+
+ if (req->count > FRAME_NUM) {
+ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
+ "not enough buffers\n");
+ req->count = FRAME_NUM;
+ }
+
+ if ((req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
+ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
+ "wrong buffer type\n");
+ retval = -EINVAL;
+ break;
+ }
+
+ mxc_streamoff(cam);
+ if (req->memory & V4L2_MEMORY_MMAP) {
+ mxc_free_frame_buf(cam);
+ retval = mxc_allocate_frame_buf(cam, req->count);
+ }
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_QUERYBUF ioctl
+ */
+ case VIDIOC_QUERYBUF: {
+ struct v4l2_buffer *buf = arg;
+ int index = buf->index;
+ pr_debug(" case VIDIOC_QUERYBUF\n");
+
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ pr_err("ERROR: v4l2 capture: "
+ "VIDIOC_QUERYBUFS: "
+ "wrong buffer type\n");
+ retval = -EINVAL;
+ break;
+ }
+
+ if (buf->memory & V4L2_MEMORY_MMAP) {
+ memset(buf, 0, sizeof(buf));
+ buf->index = index;
+ }
+
+ down(&cam->param_lock);
+ if (buf->memory & V4L2_MEMORY_USERPTR) {
+ mxc_v4l2_release_bufs(cam);
+ retval = mxc_v4l2_prepare_bufs(cam, buf);
+ }
+
+ if (buf->memory & V4L2_MEMORY_MMAP)
+ retval = mxc_v4l2_buffer_status(cam, buf);
+ up(&cam->param_lock);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_QBUF ioctl
+ */
+ case VIDIOC_QBUF: {
+ struct v4l2_buffer *buf = arg;
+ int index = buf->index;
+ pr_debug(" case VIDIOC_QBUF\n");
+
+ spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
+ if ((cam->frame[index].buffer.flags & 0x7) ==
+ V4L2_BUF_FLAG_MAPPED) {
+ cam->frame[index].buffer.flags |=
+ V4L2_BUF_FLAG_QUEUED;
+ list_add_tail(&cam->frame[index].queue,
+ &cam->ready_q);
+ } else if (cam->frame[index].buffer.
+ flags & V4L2_BUF_FLAG_QUEUED) {
+ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
+ "buffer already queued\n");
+ retval = -EINVAL;
+ } else if (cam->frame[index].buffer.
+ flags & V4L2_BUF_FLAG_DONE) {
+ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
+ "overwrite done buffer.\n");
+ cam->frame[index].buffer.flags &=
+ ~V4L2_BUF_FLAG_DONE;
+ cam->frame[index].buffer.flags |=
+ V4L2_BUF_FLAG_QUEUED;
+ retval = -EINVAL;
+ }
+
+ buf->flags = cam->frame[index].buffer.flags;
+ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_DQBUF ioctl
+ */
+ case VIDIOC_DQBUF: {
+ struct v4l2_buffer *buf = arg;
+ pr_debug(" case VIDIOC_DQBUF\n");
+
+ if ((cam->enc_counter == 0) &&
+ (file->f_flags & O_NONBLOCK)) {
+ retval = -EAGAIN;
+ break;
+ }
+
+ retval = mxc_v4l_dqueue(cam, buf);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_STREAMON ioctl
+ */
+ case VIDIOC_STREAMON: {
+ pr_debug(" case VIDIOC_STREAMON\n");
+ retval = mxc_streamon(cam);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_STREAMOFF ioctl
+ */
+ case VIDIOC_STREAMOFF: {
+ pr_debug(" case VIDIOC_STREAMOFF\n");
+ retval = mxc_streamoff(cam);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_G_CTRL ioctl
+ */
+ case VIDIOC_G_CTRL: {
+ pr_debug(" case VIDIOC_G_CTRL\n");
+ retval = mxc_v4l2_g_ctrl(cam, arg);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_S_CTRL ioctl
+ */
+ case VIDIOC_S_CTRL: {
+ pr_debug(" case VIDIOC_S_CTRL\n");
+ retval = mxc_v4l2_s_ctrl(cam, arg);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_CROPCAP ioctl
+ */
+ case VIDIOC_CROPCAP: {
+ struct v4l2_cropcap *cap = arg;
+ pr_debug(" case VIDIOC_CROPCAP\n");
+ if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+ retval = -EINVAL;
+ break;
+ }
+ cap->bounds = cam->crop_bounds;
+ cap->defrect = cam->crop_defrect;
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_G_CROP ioctl
+ */
+ case VIDIOC_G_CROP: {
+ struct v4l2_crop *crop = arg;
+ pr_debug(" case VIDIOC_G_CROP\n");
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+ retval = -EINVAL;
+ break;
+ }
+ crop->c = cam->crop_current;
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_S_CROP ioctl
+ */
+ case VIDIOC_S_CROP: {
+ struct v4l2_crop *crop = arg;
+ struct v4l2_rect *b = &cam->crop_bounds;
+ pr_debug(" case VIDIOC_S_CROP\n");
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+ retval = -EINVAL;
+ break;
+ }
+
+ crop->c.top = (crop->c.top < b->top) ? b->top
+ : crop->c.top;
+ if (crop->c.top > b->top + b->height)
+ crop->c.top = b->top + b->height - 1;
+ if (crop->c.height > b->top + b->height - crop->c.top)
+ crop->c.height =
+ b->top + b->height - crop->c.top;
+
+ crop->c.left = (crop->c.left < b->left) ? b->left
+ : crop->c.left;
+ if (crop->c.left > b->left + b->width)
+ crop->c.left = b->left + b->width - 1;
+ if (crop->c.width > b->left - crop->c.left + b->width)
+ crop->c.width =
+ b->left - crop->c.left + b->width;
+
+ crop->c.width -= crop->c.width % 8;
+ crop->c.left -= crop->c.left % 4;
+ cam->crop_current = crop->c;
+
+ pr_debug(" Cropping Input to ipu size %d x %d\n",
+ cam->crop_current.width,
+ cam->crop_current.height);
+ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
+ cam->crop_current.height,
+ cam->csi);
+ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
+ cam->crop_current.top,
+ cam->csi);
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_OVERLAY ioctl
+ */
+ case VIDIOC_OVERLAY: {
+ int *on = arg;
+ pr_debug(" VIDIOC_OVERLAY on=%d\n", *on);
+ if (*on) {
+ cam->overlay_on = true;
+ cam->overlay_pid = current->pid;
+ retval = start_preview(cam);
+ }
+ if (!*on) {
+ retval = stop_preview(cam);
+ cam->overlay_on = false;
+ }
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_G_FBUF ioctl
+ */
+ case VIDIOC_G_FBUF: {
+ struct v4l2_framebuffer *fb = arg;
+ pr_debug(" case VIDIOC_G_FBUF\n");
+ *fb = cam->v4l2_fb;
+ fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
+ break;
+ }
+
+ /*!
+ * V4l2 VIDIOC_S_FBUF ioctl
+ */
+ case VIDIOC_S_FBUF: {
+ struct v4l2_framebuffer *fb = arg;
+ pr_debug(" case VIDIOC_S_FBUF\n");
+ cam->v4l2_fb = *fb;
+ break;
+ }
+
+ case VIDIOC_G_PARM: {
+ struct v4l2_streamparm *parm = arg;
+ pr_debug(" case VIDIOC_G_PARM\n");
+ if (cam->sensor)
+ retval = vidioc_int_g_parm(cam->sensor, parm);
+ else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ retval = -ENODEV;
+ }
+ break;
+ }
+
+ case VIDIOC_S_PARM: {
+ struct v4l2_streamparm *parm = arg;
+ pr_debug(" case VIDIOC_S_PARM\n");
+ if (cam->sensor)
+ retval = mxc_v4l2_s_param(cam, parm);
+ else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ retval = -ENODEV;
+ }
+ break;
+ }
+
+ /* linux v4l2 bug, kernel c0485619 user c0405619 */
+ case VIDIOC_ENUMSTD: {
+ struct v4l2_standard *e = arg;
+ pr_debug(" case VIDIOC_ENUMSTD\n");
+ *e = cam->standard;
+ break;
+ }
+
+ case VIDIOC_G_STD: {
+ v4l2_std_id *e = arg;
+ pr_debug(" case VIDIOC_G_STD\n");
+ if (cam->sensor)
+ retval = mxc_v4l2_g_std(cam, e);
+ else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ retval = -ENODEV;
+ }
+ break;
+ }
+
+ case VIDIOC_S_STD: {
+ v4l2_std_id *e = arg;
+ pr_debug(" case VIDIOC_S_STD\n");
+ retval = mxc_v4l2_s_std(cam, *e);
+
+ break;
+ }
+
+ case VIDIOC_ENUMOUTPUT: {
+ struct v4l2_output *output = arg;
+ pr_debug(" case VIDIOC_ENUMOUTPUT\n");
+ if (output->index >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) {
+ retval = -EINVAL;
+ break;
+ }
+ *output = mxc_capture_outputs[output->index];
+
+ break;
+ }
+ case VIDIOC_G_OUTPUT: {
+ int *p_output_num = arg;
+ pr_debug(" case VIDIOC_G_OUTPUT\n");
+ *p_output_num = cam->output;
+ break;
+ }
+
+ case VIDIOC_S_OUTPUT: {
+ int *p_output_num = arg;
+ pr_debug(" case VIDIOC_S_OUTPUT\n");
+ if (*p_output_num >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) {
+ retval = -EINVAL;
+ break;
+ }
+ cam->output = *p_output_num;
+ break;
+ }
+
+ case VIDIOC_ENUMINPUT: {
+ struct v4l2_input *input = arg;
+ pr_debug(" case VIDIOC_ENUMINPUT\n");
+ if (input->index >= MXC_V4L2_CAPTURE_NUM_INPUTS) {
+ retval = -EINVAL;
+ break;
+ }
+ *input = mxc_capture_inputs[input->index];
+ break;
+ }
+
+ case VIDIOC_G_INPUT: {
+ int *index = arg;
+ pr_debug(" case VIDIOC_G_INPUT\n");
+ *index = cam->current_input;
+ break;
+ }
+
+ case VIDIOC_S_INPUT: {
+ int *index = arg;
+ pr_debug(" case VIDIOC_S_INPUT\n");
+ if (*index >= MXC_V4L2_CAPTURE_NUM_INPUTS) {
+ retval = -EINVAL;
+ break;
+ }
+
+ if (*index == cam->current_input)
+ break;
+
+ if ((mxc_capture_inputs[cam->current_input].status &
+ V4L2_IN_ST_NO_POWER) == 0) {
+ retval = mxc_streamoff(cam);
+ if (retval)
+ break;
+ mxc_capture_inputs[cam->current_input].status |=
+ V4L2_IN_ST_NO_POWER;
+ }
+
+ if (strcmp(mxc_capture_inputs[*index].name, "CSI MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
+ retval = csi_enc_select(cam);
+ if (retval)
+ break;
+#endif
+ } else if (strcmp(mxc_capture_inputs[*index].name,
+ "CSI IC MEM") == 0) {
+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
+ retval = prp_enc_select(cam);
+ if (retval)
+ break;
+#endif
+ }
+
+ mxc_capture_inputs[*index].status &= ~V4L2_IN_ST_NO_POWER;
+ cam->current_input = *index;
+ break;
+ }
+ case VIDIOC_ENUM_FMT: {
+ struct v4l2_fmtdesc *f = arg;
+ if (cam->sensor)
+ retval = vidioc_int_enum_fmt_cap(cam->sensor, f);
+ else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ retval = -ENODEV;
+ }
+ break;
+ }
+ case VIDIOC_ENUM_FRAMESIZES: {
+ struct v4l2_frmsizeenum *fsize = arg;
+ if (cam->sensor)
+ retval = vidioc_int_enum_framesizes(cam->sensor, fsize);
+ else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ retval = -ENODEV;
+ }
+ break;
+ }
+ case VIDIOC_ENUM_FRAMEINTERVALS: {
+ struct v4l2_frmivalenum *fival = arg;
+ if (cam->sensor) {
+ retval = vidioc_int_enum_frameintervals(cam->sensor,
+ fival);
+ } else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ retval = -ENODEV;
+ }
+ break;
+ }
+ case VIDIOC_DBG_G_CHIP_IDENT: {
+ struct v4l2_dbg_chip_ident *p = arg;
+ p->ident = V4L2_IDENT_NONE;
+ p->revision = 0;
+ if (cam->sensor)
+ retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p);
+ else {
+ pr_err("ERROR: v4l2 capture: slave not found!\n");
+ retval = -ENODEV;
+ }
+ break;
+ }
+ case VIDIOC_TRY_FMT:
+ case VIDIOC_QUERYCTRL:
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_G_FREQUENCY:
+ case VIDIOC_S_FREQUENCY:
+ default:
+ pr_debug(" case default or not supported\n");
+ retval = -EINVAL;
+ break;
+ }
+
+ if (ioctlnr != VIDIOC_DQBUF)
+ up(&cam->busy_lock);
+ return retval;
+}
+
+/*
+ * V4L interface - ioctl function
+ *
+ * @return None
+ */
+static long mxc_v4l_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ pr_debug("In MVC:mxc_v4l_ioctl\n");
+ return video_usercopy(file, cmd, arg, mxc_v4l_do_ioctl);
+}
+
+/*!
+ * V4L interface - mmap function
+ *
+ * @param file structure file *
+ *
+ * @param vma structure vm_area_struct *
+ *
+ * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error
+ */
+static int mxc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct video_device *dev = video_devdata(file);
+ unsigned long size;
+ int res = 0;
+ cam_data *cam = video_get_drvdata(dev);
+
+ pr_debug("In MVC:mxc_mmap\n");
+ pr_debug(" pgoff=0x%lx, start=0x%lx, end=0x%lx\n",
+ vma->vm_pgoff, vma->vm_start, vma->vm_end);
+
+ /* make this _really_ smp-safe */
+ if (down_interruptible(&cam->busy_lock))
+ return -EINTR;
+
+ size = vma->vm_end - vma->vm_start;
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start,
+ vma->vm_pgoff, size, vma->vm_page_prot)) {
+ pr_err("ERROR: v4l2 capture: mxc_mmap: "
+ "remap_pfn_range failed\n");
+ res = -ENOBUFS;
+ goto mxc_mmap_exit;
+ }
+
+ vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
+
+mxc_mmap_exit:
+ up(&cam->busy_lock);
+ return res;
+}
+
+/*!
+ * V4L interface - poll function
+ *
+ * @param file structure file *
+ *
+ * @param wait structure poll_table_struct *
+ *
+ * @return status POLLIN | POLLRDNORM
+ */
+static unsigned int mxc_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct video_device *dev = video_devdata(file);
+ cam_data *cam = video_get_drvdata(dev);
+ wait_queue_head_t *queue = NULL;
+ int res = POLLIN | POLLRDNORM;
+
+ pr_debug("In MVC:mxc_poll\n");
+
+ if (down_interruptible(&cam->busy_lock))
+ return -EINTR;
+
+ queue = &cam->enc_queue;
+ poll_wait(file, queue, wait);
+
+ up(&cam->busy_lock);
+
+ return res;
+}
+
+/*!
+ * This structure defines the functions to be called in this driver.
+ */
+static struct v4l2_file_operations mxc_v4l_fops = {
+ .owner = THIS_MODULE,
+ .open = mxc_v4l_open,
+ .release = mxc_v4l_close,
+ .read = mxc_v4l_read,
+ .unlocked_ioctl = mxc_v4l_ioctl,
+ .mmap = mxc_mmap,
+ .poll = mxc_poll,
+};
+
+static struct video_device mxc_v4l_template = {
+ .name = "Mxc Camera",
+ .fops = &mxc_v4l_fops,
+ .release = video_device_release,
+};
+
+/*!
+ * This function can be used to release any platform data on closing.
+ */
+static void camera_platform_release(struct device *device)
+{
+}
+
+/*!
+ * Camera V4l2 callback function.
+ *
+ * @param mask u32
+ *
+ * @param dev void device structure
+ *
+ * @return status
+ */
+static void camera_callback(u32 mask, void *dev)
+{
+ struct mxc_v4l_frame *done_frame;
+ struct mxc_v4l_frame *ready_frame;
+ struct timeval cur_time;
+
+ cam_data *cam = (cam_data *) dev;
+ if (cam == NULL)
+ return;
+
+ pr_debug("In MVC:camera_callback\n");
+
+ spin_lock(&cam->queue_int_lock);
+ spin_lock(&cam->dqueue_int_lock);
+ if (!list_empty(&cam->working_q)) {
+ do_gettimeofday(&cur_time);
+
+ done_frame = list_entry(cam->working_q.next,
+ struct mxc_v4l_frame,
+ queue);
+
+ if (done_frame->ipu_buf_num != cam->local_buf_num)
+ goto next;
+
+ /*
+ * Set the current time to done frame buffer's
+ * timestamp. Users can use this information to judge
+ * the frame's usage.
+ */
+ done_frame->buffer.timestamp = cur_time;
+
+ if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
+ done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE;
+ done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
+
+ /* Added to the done queue */
+ list_del(cam->working_q.next);
+ list_add_tail(&done_frame->queue, &cam->done_q);
+
+ /* Wake up the queue */
+ cam->enc_counter++;
+ wake_up_interruptible(&cam->enc_queue);
+ } else
+ pr_err("ERROR: v4l2 capture: camera_callback: "
+ "buffer not queued\n");
+ }
+
+next:
+ if (!list_empty(&cam->ready_q)) {
+ ready_frame = list_entry(cam->ready_q.next,
+ struct mxc_v4l_frame,
+ queue);
+ if (cam->enc_update_eba)
+ if (cam->enc_update_eba(
+ cam,
+ ready_frame->buffer.m.offset) == 0) {
+ list_del(cam->ready_q.next);
+ list_add_tail(&ready_frame->queue,
+ &cam->working_q);
+ ready_frame->ipu_buf_num = cam->local_buf_num;
+ }
+ } else {
+ if (cam->enc_update_eba)
+ cam->enc_update_eba(
+ cam, cam->dummy_frame.buffer.m.offset);
+ }
+
+ cam->local_buf_num = (cam->local_buf_num == 0) ? 1 : 0;
+ spin_unlock(&cam->dqueue_int_lock);
+ spin_unlock(&cam->queue_int_lock);
+
+ return;
+}
+
+/*!
+ * initialize cam_data structure
+ *
+ * @param cam structure cam_data *
+ *
+ * @return status 0 Success
+ */
+static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
+{
+ const struct of_device_id *of_id =
+ of_match_device(mxc_v4l2_dt_ids, &pdev->dev);
+ struct device_node *np = pdev->dev.of_node;
+ int ipu_id, csi_id, mclk_source;
+ int ret = 0;
+ struct v4l2_device *v4l2_dev;
+
+ pr_debug("In MVC: init_camera_struct\n");
+
+ ret = of_property_read_u32(np, "ipu_id", &ipu_id);
+ if (ret) {
+ dev_err(&pdev->dev, "ipu_id missing or invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "csi_id", &csi_id);
+ if (ret) {
+ dev_err(&pdev->dev, "csi_id missing or invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "mclk_source", &mclk_source);
+ if (ret) {
+ dev_err(&pdev->dev, "sensor mclk missing or invalid\n");
+ return ret;
+ }
+
+ /* Default everything to 0 */
+ memset(cam, 0, sizeof(cam_data));
+
+ /* get devtype to distinguish if the cpu is imx5 or imx6
+ * IMX5_V4L2 specify the cpu is imx5
+ * IMX6_V4L2 specify the cpu is imx6q or imx6sdl
+ */
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ cam->devtype = pdev->id_entry->driver_data;
+
+ cam->ipu = ipu_get_soc(ipu_id);
+ if (cam->ipu == NULL) {
+ pr_err("ERROR: v4l2 capture: failed to get ipu\n");
+ return -EINVAL;
+ } else if (cam->ipu == ERR_PTR(-ENODEV)) {
+ pr_err("ERROR: v4l2 capture: get invalid ipu\n");
+ return -ENODEV;
+ }
+
+ init_MUTEX(&cam->param_lock);
+ init_MUTEX(&cam->busy_lock);
+
+ cam->video_dev = video_device_alloc();
+ if (cam->video_dev == NULL)
+ return -ENODEV;
+
+ *(cam->video_dev) = mxc_v4l_template;
+
+ video_set_drvdata(cam->video_dev, cam);
+ dev_set_drvdata(&pdev->dev, (void *)cam);
+ cam->video_dev->minor = -1;
+
+ v4l2_dev = kzalloc(sizeof(*v4l2_dev), GFP_KERNEL);
+ if (!v4l2_dev) {
+ dev_err(&pdev->dev, "failed to allocate v4l2_dev structure\n");
+ video_device_release(cam->video_dev);
+ return -ENOMEM;
+ }
+
+ if (v4l2_device_register(&pdev->dev, v4l2_dev) < 0) {
+ dev_err(&pdev->dev, "register v4l2 device failed\n");
+ video_device_release(cam->video_dev);
+ kfree(v4l2_dev);
+ return -ENODEV;
+ }
+ cam->video_dev->v4l2_dev = v4l2_dev;
+
+ init_waitqueue_head(&cam->enc_queue);
+ init_waitqueue_head(&cam->still_queue);
+
+ /* setup cropping */
+ cam->crop_bounds.left = 0;
+ cam->crop_bounds.width = 640;
+ cam->crop_bounds.top = 0;
+ cam->crop_bounds.height = 480;
+ cam->crop_current = cam->crop_defrect = cam->crop_bounds;
+ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width,
+ cam->crop_current.height, cam->csi);
+ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left,
+ cam->crop_current.top, cam->csi);
+ cam->streamparm.parm.capture.capturemode = 0;
+
+ cam->standard.index = 0;
+ cam->standard.id = V4L2_STD_UNKNOWN;
+ cam->standard.frameperiod.denominator = 30;
+ cam->standard.frameperiod.numerator = 1;
+ cam->standard.framelines = 480;
+ cam->standard_autodetect = true;
+ cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod;
+ cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+ cam->overlay_on = false;
+ cam->capture_on = false;
+ cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY;
+
+ cam->v2f.fmt.pix.sizeimage = 352 * 288 * 3 / 2;
+ cam->v2f.fmt.pix.bytesperline = 288 * 3 / 2;
+ cam->v2f.fmt.pix.width = 288;
+ cam->v2f.fmt.pix.height = 352;
+ cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
+ cam->win.w.width = 160;
+ cam->win.w.height = 160;
+ cam->win.w.left = 0;
+ cam->win.w.top = 0;
+
+ cam->ipu_id = ipu_id;
+ cam->csi = csi_id;
+ cam->mclk_source = mclk_source;
+ cam->mclk_on[cam->mclk_source] = false;
+
+ cam->enc_callback = camera_callback;
+ init_waitqueue_head(&cam->power_queue);
+ spin_lock_init(&cam->queue_int_lock);
+ spin_lock_init(&cam->dqueue_int_lock);
+
+ cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL);
+ cam->self->module = THIS_MODULE;
+ sprintf(cam->self->name, "mxc_v4l2_cap%d", cam->csi);
+ cam->self->type = v4l2_int_type_master;
+ cam->self->u.master = &mxc_v4l2_master;
+
+ return 0;
+}
+
+static ssize_t show_streaming(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct video_device *video_dev = container_of(dev,
+ struct video_device, dev);
+ cam_data *cam = video_get_drvdata(video_dev);
+
+ if (cam->capture_on)
+ return sprintf(buf, "stream on\n");
+ else
+ return sprintf(buf, "stream off\n");
+}
+static DEVICE_ATTR(fsl_v4l2_capture_property, S_IRUGO, show_streaming, NULL);
+
+static ssize_t show_overlay(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct video_device *video_dev = container_of(dev,
+ struct video_device, dev);
+ cam_data *cam = video_get_drvdata(video_dev);
+
+ if (cam->overlay_on)
+ return sprintf(buf, "overlay on\n");
+ else
+ return sprintf(buf, "overlay off\n");
+}
+static DEVICE_ATTR(fsl_v4l2_overlay_property, S_IRUGO, show_overlay, NULL);
+
+static ssize_t show_csi(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct video_device *video_dev = container_of(dev,
+ struct video_device, dev);
+ cam_data *cam = video_get_drvdata(video_dev);
+
+ return sprintf(buf, "ipu%d_csi%d\n", cam->ipu_id, cam->csi);
+}
+static DEVICE_ATTR(fsl_csi_property, S_IRUGO, show_csi, NULL);
+
+/*!
+ * This function is called to probe the devices if registered.
+ *
+ * @param pdev the device structure used to give information on which device
+ * to probe
+ *
+ * @return The function returns 0 on success and -1 on failure.
+ */
+static int mxc_v4l2_probe(struct platform_device *pdev)
+{
+ /* Create cam and initialize it. */
+ cam_data *cam = kmalloc(sizeof(cam_data), GFP_KERNEL);
+ if (cam == NULL) {
+ pr_err("ERROR: v4l2 capture: failed to register camera\n");
+ return -1;
+ }
+
+ init_camera_struct(cam, pdev);
+ pdev->dev.release = camera_platform_release;
+
+ /* Set up the v4l2 device and register it*/
+ cam->self->priv = cam;
+ v4l2_int_device_register(cam->self);
+
+ /* register v4l video device */
+ if (video_register_device(cam->video_dev, VFL_TYPE_GRABBER, video_nr)
+ < 0) {
+ kfree(cam);
+ cam = NULL;
+ pr_err("ERROR: v4l2 capture: video_register_device failed\n");
+ return -1;
+ }
+ pr_debug(" Video device registered: %s #%d\n",
+ cam->video_dev->name, cam->video_dev->minor);
+
+ if (device_create_file(&cam->video_dev->dev,
+ &dev_attr_fsl_v4l2_capture_property))
+ dev_err(&pdev->dev, "Error on creating sysfs file"
+ " for capture\n");
+
+ if (device_create_file(&cam->video_dev->dev,
+ &dev_attr_fsl_v4l2_overlay_property))
+ dev_err(&pdev->dev, "Error on creating sysfs file"
+ " for overlay\n");
+
+ if (device_create_file(&cam->video_dev->dev,
+ &dev_attr_fsl_csi_property))
+ dev_err(&pdev->dev, "Error on creating sysfs file"
+ " for csi number\n");
+
+ return 0;
+}
+
+/*!
+ * This function is called to remove the devices when device unregistered.
+ *
+ * @param pdev the device structure used to give information on which device
+ * to remove
+ *
+ * @return The function returns 0 on success and -1 on failure.
+ */
+static int mxc_v4l2_remove(struct platform_device *pdev)
+{
+ cam_data *cam = (cam_data *)platform_get_drvdata(pdev);
+ if (cam->open_count) {
+ pr_err("ERROR: v4l2 capture:camera open "
+ "-- setting ops to NULL\n");
+ return -EBUSY;
+ } else {
+ struct v4l2_device *v4l2_dev = cam->video_dev->v4l2_dev;
+ device_remove_file(&cam->video_dev->dev,
+ &dev_attr_fsl_v4l2_capture_property);
+ device_remove_file(&cam->video_dev->dev,
+ &dev_attr_fsl_v4l2_overlay_property);
+ device_remove_file(&cam->video_dev->dev,
+ &dev_attr_fsl_csi_property);
+
+ pr_info("V4L2 freeing image input device\n");
+ v4l2_int_device_unregister(cam->self);
+ video_unregister_device(cam->video_dev);
+
+ mxc_free_frame_buf(cam);
+ kfree(cam);
+
+ v4l2_device_unregister(v4l2_dev);
+ kfree(v4l2_dev);
+ }
+
+ pr_info("V4L2 unregistering video\n");
+ return 0;
+}
+
+/*!
+ * This function is called to put the sensor in a low power state.
+ * Refer to the document driver-model/driver.txt in the kernel source tree
+ * for more information.
+ *
+ * @param pdev the device structure used to give information on which I2C
+ * to suspend
+ * @param state the power state the device is entering
+ *
+ * @return The function returns 0 on success and -1 on failure.
+ */
+static int mxc_v4l2_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ cam_data *cam = platform_get_drvdata(pdev);
+
+ pr_debug("In MVC:mxc_v4l2_suspend\n");
+
+ if (cam == NULL)
+ return -1;
+
+ down(&cam->busy_lock);
+
+ cam->low_power = true;
+
+ if (cam->overlay_on == true)
+ stop_preview(cam);
+ if (cam->capture_on == true) {
+ if (cam->enc_disable_csi)
+ cam->enc_disable_csi(cam);
+
+ if (cam->enc_disable)
+ cam->enc_disable(cam);
+ }
+
+ if (cam->sensor && cam->open_count) {
+ if (cam->mclk_on[cam->mclk_source]) {
+ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
+ cam->mclk_source,
+ false, false);
+ cam->mclk_on[cam->mclk_source] = false;
+ }
+ vidioc_int_s_power(cam->sensor, 0);
+ }
+
+ up(&cam->busy_lock);
+
+ return 0;
+}
+
+/*!
+ * This function is called to bring the sensor back from a low power state.
+ * Refer to the document driver-model/driver.txt in the kernel source tree
+ * for more information.
+ *
+ * @param pdev the device structure
+ *
+ * @return The function returns 0 on success and -1 on failure
+ */
+static int mxc_v4l2_resume(struct platform_device *pdev)
+{
+ cam_data *cam = platform_get_drvdata(pdev);
+
+ pr_debug("In MVC:mxc_v4l2_resume\n");
+
+ if (cam == NULL)
+ return -1;
+
+ down(&cam->busy_lock);
+
+ cam->low_power = false;
+ wake_up_interruptible(&cam->power_queue);
+
+ if (cam->sensor && cam->open_count) {
+ vidioc_int_s_power(cam->sensor, 1);
+
+ if (!cam->mclk_on[cam->mclk_source]) {
+ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
+ cam->mclk_source,
+ true, true);
+ cam->mclk_on[cam->mclk_source] = true;
+ }
+ }
+
+ if (cam->overlay_on == true)
+ start_preview(cam);
+ if (cam->capture_on == true) {
+ if (cam->enc_enable)
+ cam->enc_enable(cam);
+
+ if (cam->enc_enable_csi)
+ cam->enc_enable_csi(cam);
+ }
+
+ up(&cam->busy_lock);
+
+ return 0;
+}
+
+/*!
+ * This structure contains pointers to the power management callback functions.
+ */
+static struct platform_driver mxc_v4l2_driver = {
+ .driver = {
+ .name = "mxc_v4l2_capture",
+ .owner = THIS_MODULE,
+ .of_match_table = mxc_v4l2_dt_ids,
+ },
+ .id_table = imx_v4l2_devtype,
+ .probe = mxc_v4l2_probe,
+ .remove = mxc_v4l2_remove,
+ .suspend = mxc_v4l2_suspend,
+ .resume = mxc_v4l2_resume,
+ .shutdown = NULL,
+};
+
+/*!
+ * Initializes the camera driver.
+ */
+static int mxc_v4l2_master_attach(struct v4l2_int_device *slave)
+{
+ cam_data *cam = slave->u.slave->master->priv;
+ struct v4l2_format cam_fmt;
+ int i;
+ struct sensor_data *sdata = slave->priv;
+
+ pr_debug("In MVC: mxc_v4l2_master_attach\n");
+ pr_debug(" slave.name = %s\n", slave->name);
+ pr_debug(" master.name = %s\n", slave->u.slave->master->name);
+
+ if (slave == NULL) {
+ pr_err("ERROR: v4l2 capture: slave parameter not valid.\n");
+ return -1;
+ }
+
+ if (sdata->csi != cam->csi) {
+ pr_debug("%s: csi doesn't match\n", __func__);
+ return -1;
+ }
+
+ cam->sensor = slave;
+
+ if (cam->sensor_index < MXC_SENSOR_NUM) {
+ cam->all_sensors[cam->sensor_index] = slave;
+ cam->sensor_index++;
+ } else {
+ pr_err("ERROR: v4l2 capture: slave number exceeds "
+ "the maximum.\n");
+ return -1;
+ }
+
+ for (i = 0; i < cam->sensor_index; i++) {
+ vidioc_int_dev_exit(cam->all_sensors[i]);
+ vidioc_int_s_power(cam->all_sensors[i], 0);
+ }
+
+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
+
+ /* Used to detect TV in (type 1) vs. camera (type 0)*/
+ cam->device_type = cam_fmt.fmt.pix.priv;
+
+ /* Set the input size to the ipu for this device */
+ cam->crop_bounds.top = cam->crop_bounds.left = 0;
+ cam->crop_bounds.width = cam_fmt.fmt.pix.width;
+ cam->crop_bounds.height = cam_fmt.fmt.pix.height;
+
+ /* This also is the max crop size for this device. */
+ cam->crop_defrect.top = cam->crop_defrect.left = 0;
+ cam->crop_defrect.width = cam_fmt.fmt.pix.width;
+ cam->crop_defrect.height = cam_fmt.fmt.pix.height;
+
+ /* At this point, this is also the current image size. */
+ cam->crop_current.top = cam->crop_current.left = 0;
+ cam->crop_current.width = cam_fmt.fmt.pix.width;
+ cam->crop_current.height = cam_fmt.fmt.pix.height;
+
+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
+ __func__,
+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
+ __func__,
+ cam->crop_bounds.width, cam->crop_bounds.height);
+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
+ __func__,
+ cam->crop_defrect.width, cam->crop_defrect.height);
+ pr_debug("End of %s: crop_current widthxheight %d x %d\n",
+ __func__,
+ cam->crop_current.width, cam->crop_current.height);
+
+ return 0;
+}
+
+/*!
+ * Disconnects the camera driver.
+ */
+static void mxc_v4l2_master_detach(struct v4l2_int_device *slave)
+{
+ unsigned int i;
+ cam_data *cam = slave->u.slave->master->priv;
+
+ pr_debug("In MVC:mxc_v4l2_master_detach\n");
+
+ if (cam->sensor_index > 1) {
+ for (i = 0; i < cam->sensor_index; i++) {
+ if (cam->all_sensors[i] != slave)
+ continue;
+ /* Move all the sensors behind this
+ * sensor one step forward
+ */
+ for (; i <= MXC_SENSOR_NUM - 2; i++)
+ cam->all_sensors[i] = cam->all_sensors[i+1];
+ break;
+ }
+ /* Point current sensor to the last one */
+ cam->sensor = cam->all_sensors[cam->sensor_index - 2];
+ } else
+ cam->sensor = NULL;
+
+ cam->sensor_index--;
+ vidioc_int_dev_exit(slave);
+}
+
+/*!
+ * Entry point for the V4L2
+ *
+ * @return Error code indicating success or failure
+ */
+static __init int camera_init(void)
+{
+ u8 err = 0;
+
+ pr_debug("In MVC:camera_init\n");
+
+ /* Register the device driver structure. */
+ err = platform_driver_register(&mxc_v4l2_driver);
+ if (err != 0) {
+ pr_err("ERROR: v4l2 capture:camera_init: "
+ "platform_driver_register failed.\n");
+ return err;
+ }
+
+ return err;
+}
+
+/*!
+ * Exit and cleanup for the V4L2
+ */
+static void __exit camera_exit(void)
+{
+ pr_debug("In MVC: camera_exit\n");
+
+ platform_driver_unregister(&mxc_v4l2_driver);
+}
+
+module_init(camera_init);
+module_exit(camera_exit);
+
+module_param(video_nr, int, 0444);
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("V4L2 capture driver for Mxc based cameras");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("video");
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
new file mode 100644
index 000000000000..f6717752d4b9
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2004-2015 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
+ */
+
+/*!
+ * @defgroup MXC_V4L2_CAPTURE MXC V4L2 Video Capture Driver
+ */
+/*!
+ * @file mxc_v4l2_capture.h
+ *
+ * @brief mxc V4L2 capture device API Header file
+ *
+ * It include all the defines for frame operations, also three structure defines
+ * use case ops structure, common v4l2 driver structure and frame structure.
+ *
+ * @ingroup MXC_V4L2_CAPTURE
+ */
+#ifndef __MXC_V4L2_CAPTURE_H__
+#define __MXC_V4L2_CAPTURE_H__
+
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/mxc_v4l2.h>
+#include <linux/completion.h>
+#include <linux/dmaengine.h>
+#include <linux/pxp_dma.h>
+#include <linux/ipu-v3.h>
+#include <linux/platform_data/dma-imx.h>
+
+#include <media/v4l2-dev.h>
+#include "v4l2-int-device.h"
+
+
+#define FRAME_NUM 10
+#define MXC_SENSOR_NUM 2
+
+enum imx_v4l2_devtype {
+ IMX5_V4L2,
+ IMX6_V4L2,
+};
+
+/*!
+ * v4l2 frame structure.
+ */
+struct mxc_v4l_frame {
+ u32 paddress;
+ void *vaddress;
+ int count;
+ int width;
+ int height;
+
+ struct v4l2_buffer buffer;
+ struct list_head queue;
+ int index;
+ union {
+ int ipu_buf_num;
+ int csi_buf_num;
+ };
+};
+
+/* Only for old version. Will go away soon. */
+typedef struct {
+ u8 clk_mode;
+ u8 ext_vsync;
+ u8 Vsync_pol;
+ u8 Hsync_pol;
+ u8 pixclk_pol;
+ u8 data_pol;
+ u8 data_width;
+ u8 pack_tight;
+ u8 force_eof;
+ u8 data_en_pol;
+ u16 width;
+ u16 height;
+ u32 pixel_fmt;
+ u32 mclk;
+ u16 active_width;
+ u16 active_height;
+} sensor_interface;
+
+/* Sensor control function */
+/* Only for old version. Will go away soon. */
+struct camera_sensor {
+ void (*set_color) (int bright, int saturation, int red, int green,
+ int blue);
+ void (*get_color) (int *bright, int *saturation, int *red, int *green,
+ int *blue);
+ void (*set_ae_mode) (int ae_mode);
+ void (*get_ae_mode) (int *ae_mode);
+ sensor_interface *(*config) (int *frame_rate, int high_quality);
+ sensor_interface *(*reset) (void);
+ void (*get_std) (v4l2_std_id *std);
+ void (*set_std) (v4l2_std_id std);
+ unsigned int csi;
+};
+
+/*!
+ * common v4l2 driver structure.
+ */
+typedef struct _cam_data {
+ struct video_device *video_dev;
+ int device_type;
+
+ /* semaphore guard against SMP multithreading */
+ struct semaphore busy_lock;
+
+ int open_count;
+
+ /* params lock for this camera */
+ struct semaphore param_lock;
+
+ /* Encoder */
+ struct list_head ready_q;
+ struct list_head done_q;
+ struct list_head working_q;
+ int ping_pong_csi;
+ spinlock_t queue_int_lock;
+ spinlock_t dqueue_int_lock;
+ struct mxc_v4l_frame frame[FRAME_NUM];
+ struct mxc_v4l_frame dummy_frame;
+ wait_queue_head_t enc_queue;
+ int enc_counter;
+ dma_addr_t rot_enc_bufs[2];
+ void *rot_enc_bufs_vaddr[2];
+ int rot_enc_buf_size[2];
+ enum v4l2_buf_type type;
+
+ /* still image capture */
+ wait_queue_head_t still_queue;
+ int still_counter;
+ dma_addr_t still_buf[2];
+ void *still_buf_vaddr;
+
+ /* overlay */
+ struct v4l2_window win;
+ struct v4l2_framebuffer v4l2_fb;
+ dma_addr_t vf_bufs[2];
+ void *vf_bufs_vaddr[2];
+ int vf_bufs_size[2];
+ dma_addr_t rot_vf_bufs[2];
+ void *rot_vf_bufs_vaddr[2];
+ int rot_vf_buf_size[2];
+ bool overlay_active;
+ int output;
+ struct fb_info *overlay_fb;
+ int fb_origin_std;
+ struct work_struct csi_work_struct;
+
+ /* v4l2 format */
+ struct v4l2_format v2f;
+ struct v4l2_format input_fmt; /* camera in */
+ bool bswapenable;
+ int rotation; /* for IPUv1 and IPUv3, this means encoder rotation */
+ int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */
+ struct v4l2_mxc_offset offset;
+
+ /* V4l2 control bit */
+ int bright;
+ int hue;
+ int contrast;
+ int saturation;
+ int red;
+ int green;
+ int blue;
+ int ae_mode;
+
+ /* standard */
+ struct v4l2_streamparm streamparm;
+ struct v4l2_standard standard;
+ bool standard_autodetect;
+
+ /* crop */
+ struct v4l2_rect crop_bounds;
+ struct v4l2_rect crop_defrect;
+ struct v4l2_rect crop_current;
+
+ int (*enc_update_eba) (void *private, dma_addr_t eba);
+ int (*enc_enable) (void *private);
+ int (*enc_disable) (void *private);
+ int (*enc_enable_csi) (void *private);
+ int (*enc_disable_csi) (void *private);
+ void (*enc_callback) (u32 mask, void *dev);
+ int (*vf_start_adc) (void *private);
+ int (*vf_stop_adc) (void *private);
+ int (*vf_start_sdc) (void *private);
+ int (*vf_stop_sdc) (void *private);
+ int (*vf_enable_csi) (void *private);
+ int (*vf_disable_csi) (void *private);
+ int (*csi_start) (void *private);
+ int (*csi_stop) (void *private);
+
+ /* misc status flag */
+ bool overlay_on;
+ bool capture_on;
+ int overlay_pid;
+ int capture_pid;
+ bool low_power;
+ wait_queue_head_t power_queue;
+ unsigned int ipu_id;
+ unsigned int csi;
+ u8 mclk_source;
+ bool mclk_on[2]; /* two mclk sources at most now */
+ int current_input;
+
+ int local_buf_num;
+
+ /* camera sensor interface */
+ struct camera_sensor *cam_sensor; /* old version */
+ struct v4l2_int_device *all_sensors[MXC_SENSOR_NUM];
+ struct v4l2_int_device *sensor;
+ struct v4l2_int_device *self;
+ int sensor_index;
+ void *ipu;
+ void *csi_soc;
+ enum imx_v4l2_devtype devtype;
+
+ /* v4l2 buf elements related to PxP DMA */
+ struct completion pxp_tx_cmpl;
+ struct pxp_channel *pxp_chan;
+ struct pxp_config_data pxp_conf;
+ struct dma_async_tx_descriptor *txd;
+ dma_cookie_t cookie;
+ struct scatterlist sg[2];
+} cam_data;
+
+struct sensor_data {
+ const struct ov5642_platform_data *platform_data;
+ struct v4l2_int_device *v4l2_int_device;
+ struct i2c_client *i2c_client;
+ struct v4l2_pix_format pix;
+ struct v4l2_captureparm streamcap;
+ bool on;
+
+ /* control settings */
+ int brightness;
+ int hue;
+ int contrast;
+ int saturation;
+ int red;
+ int green;
+ int blue;
+ int ae_mode;
+
+ u32 mclk;
+ u8 mclk_source;
+ struct clk *sensor_clk;
+ int csi;
+
+ void (*io_init)(void);
+};
+
+void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi);
+#endif /* __MXC_V4L2_CAPTURE_H__ */
diff --git a/drivers/media/platform/mxc/capture/ov5640.c b/drivers/media/platform/mxc/capture/ov5640.c
new file mode 100644
index 000000000000..ec8b8090201d
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ov5640.c
@@ -0,0 +1,1950 @@
+/*
+ * Copyright (C) 2012-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/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.h"
+
+#define OV5640_VOLTAGE_ANALOG 2800000
+#define OV5640_VOLTAGE_DIGITAL_CORE 1500000
+#define OV5640_VOLTAGE_DIGITAL_IO 1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5640_XCLK_MIN 6000000
+#define OV5640_XCLK_MAX 24000000
+
+#define OV5640_CHIP_ID_HIGH_BYTE 0x300A
+#define OV5640_CHIP_ID_LOW_BYTE 0x300B
+
+enum ov5640_mode {
+ ov5640_mode_MIN = 0,
+ ov5640_mode_VGA_640_480 = 0,
+ ov5640_mode_QVGA_320_240 = 1,
+ ov5640_mode_NTSC_720_480 = 2,
+ ov5640_mode_PAL_720_576 = 3,
+ ov5640_mode_720P_1280_720 = 4,
+ ov5640_mode_1080P_1920_1080 = 5,
+ ov5640_mode_QSXGA_2592_1944 = 6,
+ ov5640_mode_QCIF_176_144 = 7,
+ ov5640_mode_XGA_1024_768 = 8,
+ ov5640_mode_MAX = 8
+};
+
+enum ov5640_frame_rate {
+ ov5640_15_fps,
+ ov5640_30_fps
+};
+
+static int ov5640_framerates[] = {
+ [ov5640_15_fps] = 15,
+ [ov5640_30_fps] = 30,
+};
+
+struct reg_value {
+ u16 u16RegAddr;
+ u8 u8Val;
+ u8 u8Mask;
+ u32 u32Delay_ms;
+};
+
+struct ov5640_mode_info {
+ enum ov5640_mode mode;
+ u32 width;
+ u32 height;
+ struct reg_value *init_data_ptr;
+ u32 init_data_size;
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct sensor_data ov5640_data;
+static int pwn_gpio, rst_gpio;
+static int prev_sysclk;
+static int AE_Target = 52, night_mode;
+static int prev_HTS;
+static int AE_high, AE_low;
+
+static struct reg_value ov5640_global_init_setting[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
+ {0x3034, 0x1a, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0},
+ {0x3630, 0x36, 0, 0}, {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0},
+ {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0},
+ {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0},
+ {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0},
+ {0x3906, 0x10, 0, 0}, {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0},
+ {0x3600, 0x08, 0, 0}, {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0},
+ {0x3620, 0x52, 0, 0}, {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0},
+ {0x3a13, 0x43, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+ {0x3635, 0x13, 0, 0}, {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0},
+ {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0},
+ {0x3c05, 0x98, 0, 0}, {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0},
+ {0x3c0b, 0x40, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0},
+ {0x3812, 0x00, 0, 0}, {0x3708, 0x64, 0, 0}, {0x4001, 0x02, 0, 0},
+ {0x4005, 0x1a, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
+ {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x5000, 0xa7, 0, 0},
+ {0x3008, 0x02, 0, 0},
+};
+
+static struct reg_value ov5640_init_setting_30fps_VGA[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
+ {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x46, 0, 0},
+ {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
+ {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
+ {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+ {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
+ {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
+ {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
+ {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
+ {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
+ {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
+ {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
+ {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, {0x5000, 0xa7, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0},
+ {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0},
+ {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0}, {0x518a, 0x54, 0, 0},
+ {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x50, 0, 0},
+ {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x6c, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x09, 0, 0},
+ {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0}, {0x5381, 0x1e, 0, 0},
+ {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, {0x5384, 0x0a, 0, 0},
+ {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0},
+ {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0},
+ {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0},
+ {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0},
+ {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0},
+ {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0},
+ {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, {0x5481, 0x08, 0, 0},
+ {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, {0x5484, 0x51, 0, 0},
+ {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, {0x5487, 0x7d, 0, 0},
+ {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, {0x548a, 0x9a, 0, 0},
+ {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, {0x548d, 0xcd, 0, 0},
+ {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, {0x5490, 0x1d, 0, 0},
+ {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x10, 0, 0},
+ {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, {0x558b, 0xf8, 0, 0},
+ {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, {0x5802, 0x0f, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, {0x5805, 0x26, 0, 0},
+ {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, {0x5808, 0x05, 0, 0},
+ {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, {0x580b, 0x0d, 0, 0},
+ {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, {0x580e, 0x00, 0, 0},
+ {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, {0x5811, 0x09, 0, 0},
+ {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x00, 0, 0},
+ {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, {0x5817, 0x08, 0, 0},
+ {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, {0x581a, 0x05, 0, 0},
+ {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, {0x581d, 0x0e, 0, 0},
+ {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, {0x5820, 0x11, 0, 0},
+ {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, {0x5823, 0x28, 0, 0},
+ {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, {0x5829, 0x26, 0, 0},
+ {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, {0x582c, 0x24, 0, 0},
+ {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, {0x582f, 0x22, 0, 0},
+ {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, {0x5832, 0x24, 0, 0},
+ {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, {0x5835, 0x22, 0, 0},
+ {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, {0x5838, 0x44, 0, 0},
+ {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, {0x583b, 0x28, 0, 0},
+ {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, {0x5025, 0x00, 0, 0},
+ {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0},
+ {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0},
+ {0x3008, 0x02, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
+ {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
+ {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
+ {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
+ {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+ {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+ {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
+ {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
+ {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+ {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
+ {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
+ {0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
+ {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
+ {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+ {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
+ {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
+ {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
+ {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
+ {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
+ {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+
+static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
+ {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
+ {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0xee, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x05, 0, 0},
+ {0x3807, 0xc3, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0},
+ {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x0b, 0, 0},
+ {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
+ {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
+ {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
+ {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
+ {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
+ {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
+ {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9f, 0, 0}, {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0},
+ {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0},
+ {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
+ {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
+ {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
+ {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
+ {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
+ {
+ {ov5640_mode_VGA_640_480, 640, 480,
+ ov5640_setting_15fps_VGA_640_480,
+ ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
+ {ov5640_mode_QVGA_320_240, 320, 240,
+ ov5640_setting_15fps_QVGA_320_240,
+ ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
+ {ov5640_mode_NTSC_720_480, 720, 480,
+ ov5640_setting_15fps_NTSC_720_480,
+ ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
+ {ov5640_mode_PAL_720_576, 720, 576,
+ ov5640_setting_15fps_PAL_720_576,
+ ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
+ {ov5640_mode_720P_1280_720, 1280, 720,
+ ov5640_setting_15fps_720P_1280_720,
+ ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
+ {ov5640_mode_1080P_1920_1080, 1920, 1080,
+ ov5640_setting_15fps_1080P_1920_1080,
+ ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
+ {ov5640_mode_QSXGA_2592_1944, 2592, 1944,
+ ov5640_setting_15fps_QSXGA_2592_1944,
+ ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
+ {ov5640_mode_QCIF_176_144, 176, 144,
+ ov5640_setting_15fps_QCIF_176_144,
+ ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
+ {ov5640_mode_XGA_1024_768, 1024, 768,
+ ov5640_setting_15fps_XGA_1024_768,
+ ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
+ },
+ {
+ {ov5640_mode_VGA_640_480, 640, 480,
+ ov5640_setting_30fps_VGA_640_480,
+ ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
+ {ov5640_mode_QVGA_320_240, 320, 240,
+ ov5640_setting_30fps_QVGA_320_240,
+ ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
+ {ov5640_mode_NTSC_720_480, 720, 480,
+ ov5640_setting_30fps_NTSC_720_480,
+ ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
+ {ov5640_mode_PAL_720_576, 720, 576,
+ ov5640_setting_30fps_PAL_720_576,
+ ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
+ {ov5640_mode_720P_1280_720, 1280, 720,
+ ov5640_setting_30fps_720P_1280_720,
+ ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
+ {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0},
+ {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
+ {ov5640_mode_QCIF_176_144, 176, 144,
+ ov5640_setting_30fps_QCIF_176_144,
+ ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
+ {ov5640_mode_XGA_1024_768, 1024, 768,
+ ov5640_setting_30fps_XGA_1024_768,
+ ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
+ },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+
+static int ov5640_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *device_id);
+static int ov5640_remove(struct i2c_client *client);
+
+static s32 ov5640_read_reg(u16 reg, u8 *val);
+static s32 ov5640_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5640_id[] = {
+ {"ov564x", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ov564x",
+ },
+ .probe = ov5640_probe,
+ .remove = ov5640_remove,
+ .id_table = ov5640_id,
+};
+
+static inline void ov5640_power_down(int enable)
+{
+ gpio_set_value(pwn_gpio, enable);
+
+ msleep(2);
+}
+
+static inline void ov5640_reset(void)
+{
+ /* camera reset */
+ gpio_set_value(rst_gpio, 1);
+
+ /* camera power down */
+ gpio_set_value(pwn_gpio, 1);
+ msleep(5);
+ gpio_set_value(pwn_gpio, 0);
+ msleep(5);
+ gpio_set_value(rst_gpio, 0);
+ msleep(1);
+ gpio_set_value(rst_gpio, 1);
+ msleep(5);
+ gpio_set_value(pwn_gpio, 1);
+}
+
+static int ov5640_regulator_enable(struct device *dev)
+{
+ int ret = 0;
+
+ io_regulator = devm_regulator_get(dev, "DOVDD");
+ if (!IS_ERR(io_regulator)) {
+ regulator_set_voltage(io_regulator,
+ OV5640_VOLTAGE_DIGITAL_IO,
+ OV5640_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(io_regulator);
+ if (ret) {
+ dev_err(dev, "set io voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set io voltage ok\n");
+ }
+ } else {
+ io_regulator = NULL;
+ dev_warn(dev, "cannot get io voltage\n");
+ }
+
+ core_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(core_regulator)) {
+ regulator_set_voltage(core_regulator,
+ OV5640_VOLTAGE_DIGITAL_CORE,
+ OV5640_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(core_regulator);
+ if (ret) {
+ dev_err(dev, "set core voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set core voltage ok\n");
+ }
+ } else {
+ core_regulator = NULL;
+ dev_warn(dev, "cannot get core voltage\n");
+ }
+
+ analog_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(analog_regulator)) {
+ regulator_set_voltage(analog_regulator,
+ OV5640_VOLTAGE_ANALOG,
+ OV5640_VOLTAGE_ANALOG);
+ ret = regulator_enable(analog_regulator);
+ if (ret) {
+ dev_err(dev, "set analog voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set analog voltage ok\n");
+ }
+ } else {
+ analog_regulator = NULL;
+ dev_warn(dev, "cannot get analog voltage\n");
+ }
+
+ return ret;
+}
+
+static s32 ov5640_write_reg(u16 reg, u8 val)
+{
+ u8 au8Buf[3] = {0};
+
+ au8Buf[0] = reg >> 8;
+ au8Buf[1] = reg & 0xff;
+ au8Buf[2] = val;
+
+ if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x\n",
+ __func__, reg, val);
+ return -1;
+ }
+
+ return 0;
+}
+
+static s32 ov5640_read_reg(u16 reg, u8 *val)
+{
+ u8 au8RegBuf[2] = {0};
+ u8 u8RdVal = 0;
+
+ au8RegBuf[0] = reg >> 8;
+ au8RegBuf[1] = reg & 0xff;
+
+ if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
+ pr_err("%s:write reg error:reg=%x\n",
+ __func__, reg);
+ return -1;
+ }
+
+ if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
+ pr_err("%s:read reg error:reg=%x,val=%x\n",
+ __func__, reg, u8RdVal);
+ return -1;
+ }
+
+ *val = u8RdVal;
+
+ return u8RdVal;
+}
+
+static void ov5640_soft_reset(void)
+{
+ /* sysclk from pad */
+ ov5640_write_reg(0x3103, 0x11);
+
+ /* software reset */
+ ov5640_write_reg(0x3008, 0x82);
+
+ /* delay at least 5ms */
+ msleep(10);
+}
+
+/* set sensor driver capability
+ * 0x302c[7:6] - strength
+ 00 - 1x
+ 01 - 2x
+ 10 - 3x
+ 11 - 4x
+ */
+static int ov5640_driver_capability(int strength)
+{
+ u8 temp = 0;
+
+ if (strength > 4 || strength < 1) {
+ pr_err("The valid driver capability of ov5640 is 1x~4x\n");
+ return -EINVAL;
+ }
+
+ ov5640_read_reg(0x302c, &temp);
+
+ temp &= ~0xc0; /* clear [7:6] */
+ temp |= ((strength - 1) << 6); /* set [7:6] */
+
+ ov5640_write_reg(0x302c, temp);
+
+ return 0;
+}
+
+/* calculate sysclk */
+static int ov5640_get_sysclk(void)
+{
+ int xvclk = ov5640_data.mclk / 10000;
+ int sysclk;
+ int temp1, temp2;
+ int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv;
+ int sclk_rdiv_map[] = {1, 2, 4, 8};
+ u8 regval = 0;
+
+ temp1 = ov5640_read_reg(0x3034, &regval);
+ temp2 = temp1 & 0x0f;
+ if (temp2 == 8 || temp2 == 10) {
+ Bit_div2x = temp2 / 2;
+ } else {
+ pr_err("ov5640: unsupported bit mode %d\n", temp2);
+ return -1;
+ }
+
+ temp1 = ov5640_read_reg(0x3035, &regval);
+ SysDiv = temp1 >> 4;
+ if (SysDiv == 0)
+ SysDiv = 16;
+
+ temp1 = ov5640_read_reg(0x3036, &regval);
+ Multiplier = temp1;
+ temp1 = ov5640_read_reg(0x3037, &regval);
+ PreDiv = temp1 & 0x0f;
+ Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
+
+ temp1 = ov5640_read_reg(0x3108, &regval);
+ temp2 = temp1 & 0x03;
+
+ sclk_rdiv = sclk_rdiv_map[temp2];
+ VCO = xvclk * Multiplier / PreDiv;
+ sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
+
+ return sysclk;
+}
+
+/* read HTS from register settings */
+static int ov5640_get_HTS(void)
+{
+ int HTS;
+ u8 temp = 0;
+
+ HTS = ov5640_read_reg(0x380c, &temp);
+ HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
+ return HTS;
+}
+
+/* read VTS from register settings */
+static int ov5640_get_VTS(void)
+{
+ int VTS;
+ u8 temp = 0;
+
+ VTS = ov5640_read_reg(0x380e, &temp);
+ VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
+
+ return VTS;
+}
+
+/* write VTS to registers */
+static int ov5640_set_VTS(int VTS)
+{
+ int temp;
+
+ temp = VTS & 0xff;
+ ov5640_write_reg(0x380f, temp);
+
+ temp = VTS>>8;
+ ov5640_write_reg(0x380e, temp);
+ return 0;
+}
+
+/* read shutter, in number of line period */
+static int ov5640_get_shutter(void)
+{
+ int shutter;
+ u8 regval;
+
+ shutter = (ov5640_read_reg(0x03500, &regval) & 0x0f);
+
+ shutter = (shutter<<8) + ov5640_read_reg(0x3501, &regval);
+ shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &regval)>>4);
+
+ return shutter;
+}
+
+/* write shutter, in number of line period */
+static int ov5640_set_shutter(int shutter)
+{
+ int temp;
+
+ shutter = shutter & 0xffff;
+ temp = shutter & 0x0f;
+ temp = temp<<4;
+ ov5640_write_reg(0x3502, temp);
+
+ temp = shutter & 0xfff;
+ temp = temp>>4;
+ ov5640_write_reg(0x3501, temp);
+
+ temp = shutter>>12;
+ ov5640_write_reg(0x3500, temp);
+
+ return 0;
+}
+
+/* read gain, 16 = 1x */
+static int ov5640_get_gain16(void)
+{
+ int gain16;
+ u8 regval;
+
+ gain16 = ov5640_read_reg(0x350a, &regval) & 0x03;
+ gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &regval);
+
+ return gain16;
+}
+
+/* write gain, 16 = 1x */
+static int ov5640_set_gain16(int gain16)
+{
+ int temp;
+
+ gain16 = gain16 & 0x3ff;
+ temp = gain16 & 0xff;
+
+ ov5640_write_reg(0x350b, temp);
+ temp = gain16>>8;
+
+ ov5640_write_reg(0x350a, temp);
+ return 0;
+}
+
+/* get banding filter value */
+static int ov5640_get_light_freq(void)
+{
+ int temp, temp1, light_frequency;
+ u8 regval;
+
+ temp = ov5640_read_reg(0x3c01, &regval);
+ if (temp & 0x80) {
+ /* manual */
+ temp1 = ov5640_read_reg(0x3c00, &regval);
+ if (temp1 & 0x04) {
+ /* 50Hz */
+ light_frequency = 50;
+ } else {
+ /* 60Hz */
+ light_frequency = 60;
+ }
+ } else {
+ /* auto */
+ temp1 = ov5640_read_reg(0x3c0c, &regval);
+ if (temp1 & 0x01) {
+ /* 50Hz */
+ light_frequency = 50;
+ } else {
+ /* 60Hz */
+ light_frequency = 60;
+ }
+ }
+
+ return light_frequency;
+}
+
+static void ov5640_set_bandingfilter(void)
+{
+ int prev_VTS;
+ int band_step60, max_band60, band_step50, max_band50;
+
+ /* read preview PCLK */
+ prev_sysclk = ov5640_get_sysclk();
+
+ /* read preview HTS */
+ prev_HTS = ov5640_get_HTS();
+
+ /* read preview VTS */
+ prev_VTS = ov5640_get_VTS();
+
+ /* calculate banding filter */
+ /* 60Hz */
+ band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
+ ov5640_write_reg(0x3a0a, (band_step60 >> 8));
+ ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
+
+ max_band60 = (int)((prev_VTS-4)/band_step60);
+ ov5640_write_reg(0x3a0d, max_band60);
+
+ /* 50Hz */
+ band_step50 = prev_sysclk * 100/prev_HTS;
+ ov5640_write_reg(0x3a08, (band_step50 >> 8));
+ ov5640_write_reg(0x3a09, (band_step50 & 0xff));
+
+ max_band50 = (int)((prev_VTS-4)/band_step50);
+ ov5640_write_reg(0x3a0e, max_band50);
+}
+
+/* stable in high */
+static int ov5640_set_AE_target(int target)
+{
+ int fast_high, fast_low;
+
+ AE_low = target * 23 / 25; /* 0.92 */
+ AE_high = target * 27 / 25; /* 1.08 */
+ fast_high = AE_high << 1;
+
+ if (fast_high > 255)
+ fast_high = 255;
+ fast_low = AE_low >> 1;
+
+ ov5640_write_reg(0x3a0f, AE_high);
+ ov5640_write_reg(0x3a10, AE_low);
+ ov5640_write_reg(0x3a1b, AE_high);
+ ov5640_write_reg(0x3a1e, AE_low);
+ ov5640_write_reg(0x3a11, fast_high);
+ ov5640_write_reg(0x3a1f, fast_low);
+
+ return 0;
+}
+
+/* enable = 0 to turn off night mode
+ enable = 1 to turn on night mode */
+static int ov5640_set_night_mode(int enable)
+{
+ u8 mode;
+
+ ov5640_read_reg(0x3a00, &mode);
+
+ if (enable) {
+ /* night mode on */
+ mode |= 0x04;
+ ov5640_write_reg(0x3a00, mode);
+ } else {
+ /* night mode off */
+ mode &= 0xfb;
+ ov5640_write_reg(0x3a00, mode);
+ }
+
+ return 0;
+}
+
+/* enable = 0 to turn off AEC/AGC
+ enable = 1 to turn on AEC/AGC */
+static void ov5640_turn_on_AE_AG(int enable)
+{
+ u8 ae_ag_ctrl;
+
+ ov5640_read_reg(0x3503, &ae_ag_ctrl);
+ if (enable) {
+ /* turn on auto AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
+ } else {
+ /* turn off AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl | 0x03;
+ }
+ ov5640_write_reg(0x3503, ae_ag_ctrl);
+}
+
+/* download ov5640 settings to sensor through i2c */
+static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+{
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int i, retval = 0;
+
+ for (i = 0; i < ArySize; ++i, ++pModeSetting) {
+ Delay_ms = pModeSetting->u32Delay_ms;
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u8Val;
+ Mask = pModeSetting->u8Mask;
+
+ if (Mask) {
+ retval = ov5640_read_reg(RegAddr, &RegVal);
+ if (retval < 0)
+ goto err;
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = ov5640_write_reg(RegAddr, Val);
+ if (retval < 0)
+ goto err;
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+ }
+err:
+ return retval;
+}
+
+static int ov5640_init_mode(void)
+{
+ struct reg_value *pModeSetting = NULL;
+ int ArySize = 0, retval = 0;
+
+ ov5640_soft_reset();
+
+ pModeSetting = ov5640_global_init_setting;
+ ArySize = ARRAY_SIZE(ov5640_global_init_setting);
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ pModeSetting = ov5640_init_setting_30fps_VGA;
+ ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ /* change driver capability to 2x according to validation board.
+ * if the image is not stable, please increase the driver strength.
+ */
+ ov5640_driver_capability(2);
+ ov5640_set_bandingfilter();
+ ov5640_set_AE_target(AE_Target);
+ ov5640_set_night_mode(night_mode);
+
+ /* skip 9 vysnc: start capture at 10th vsync */
+ msleep(300);
+
+ /* turn off night mode */
+ night_mode = 0;
+ ov5640_data.pix.width = 640;
+ ov5640_data.pix.height = 480;
+err:
+ return retval;
+}
+
+/* change to or back to subsampling mode set the mode directly
+ * image size below 1280 * 960 is subsampling mode */
+static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+
+ if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
+ pr_err("Wrong ov5640 mode detected!\n");
+ return -1;
+ }
+
+ pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5640_data.pix.width = ov5640_mode_info_data[frame_rate][mode].width;
+ ov5640_data.pix.height = ov5640_mode_info_data[frame_rate][mode].height;
+
+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* set ov5640 to subsampling mode */
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+
+ /* turn on AE AG for subsampling mode, in case the firmware didn't */
+ ov5640_turn_on_AE_AG(1);
+
+ /* calculate banding filter */
+ ov5640_set_bandingfilter();
+
+ /* set AE target */
+ ov5640_set_AE_target(AE_Target);
+
+ /* update night mode setting */
+ ov5640_set_night_mode(night_mode);
+
+ /* skip 9 vysnc: start capture at 10th vsync */
+ if (mode == ov5640_mode_XGA_1024_768 && frame_rate == ov5640_30_fps) {
+ pr_warning("ov5640: actual frame rate of XGA is 22.5fps\n");
+ /* 1/22.5 * 9*/
+ msleep(400);
+ return retval;
+ }
+
+ if (frame_rate == ov5640_15_fps) {
+ /* 1/15 * 9*/
+ msleep(600);
+ } else if (frame_rate == ov5640_30_fps) {
+ /* 1/30 * 9*/
+ msleep(300);
+ }
+
+ return retval;
+}
+
+/* change to scaling mode go through exposure calucation
+ * image size above 1280 * 960 is scaling mode */
+static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ int prev_shutter, prev_gain16, average;
+ int cap_shutter, cap_gain16;
+ int cap_sysclk, cap_HTS, cap_VTS;
+ int light_freq, cap_bandfilt, cap_maxband;
+ long cap_gain16_shutter;
+ u8 temp;
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+
+ /* check if the input mode and frame rate is valid */
+ pModeSetting =
+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5640_data.pix.width =
+ ov5640_mode_info_data[frame_rate][mode].width;
+ ov5640_data.pix.height =
+ ov5640_mode_info_data[frame_rate][mode].height;
+
+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* read preview shutter */
+ prev_shutter = ov5640_get_shutter();
+
+ /* read preview gain */
+ prev_gain16 = ov5640_get_gain16();
+
+ /* get average */
+ average = ov5640_read_reg(0x56a1, &temp);
+
+ /* turn off night mode for capture */
+ ov5640_set_night_mode(0);
+
+ /* turn off overlay */
+ ov5640_write_reg(0x3022, 0x06);
+
+ /* Write capture setting */
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ /* turn off AE AG when capture image. */
+ ov5640_turn_on_AE_AG(0);
+
+ /* read capture VTS */
+ cap_VTS = ov5640_get_VTS();
+ cap_HTS = ov5640_get_HTS();
+ cap_sysclk = ov5640_get_sysclk();
+
+ /* calculate capture banding filter */
+ light_freq = ov5640_get_light_freq();
+ if (light_freq == 60) {
+ /* 60Hz */
+ cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
+ } else {
+ /* 50Hz */
+ cap_bandfilt = cap_sysclk * 100 / cap_HTS;
+ }
+ cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
+ /* calculate capture shutter/gain16 */
+ if (average > AE_low && average < AE_high) {
+ /* in stable range */
+ cap_gain16_shutter =
+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
+ prev_HTS/cap_HTS * AE_Target / average;
+ } else {
+ cap_gain16_shutter =
+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
+ prev_HTS/cap_HTS;
+ }
+
+ /* gain to shutter */
+ if (cap_gain16_shutter < (cap_bandfilt * 16)) {
+ /* shutter < 1/100 */
+ cap_shutter = cap_gain16_shutter/16;
+ if (cap_shutter < 1)
+ cap_shutter = 1;
+ cap_gain16 = cap_gain16_shutter/cap_shutter;
+ if (cap_gain16 < 16)
+ cap_gain16 = 16;
+ } else {
+ if (cap_gain16_shutter > (cap_bandfilt*cap_maxband*16)) {
+ /* exposure reach max */
+ cap_shutter = cap_bandfilt*cap_maxband;
+ cap_gain16 = cap_gain16_shutter / cap_shutter;
+ } else {
+ /* 1/100 < cap_shutter =< max, cap_shutter = n/100 */
+ cap_shutter =
+ ((int)(cap_gain16_shutter/16/cap_bandfilt))
+ * cap_bandfilt;
+ cap_gain16 = cap_gain16_shutter / cap_shutter;
+ }
+ }
+
+ /* write capture gain */
+ ov5640_set_gain16(cap_gain16);
+
+ /* write capture shutter */
+ if (cap_shutter > (cap_VTS - 4)) {
+ cap_VTS = cap_shutter + 4;
+ ov5640_set_VTS(cap_VTS);
+ }
+
+ ov5640_set_shutter(cap_shutter);
+
+ /* skip 2 vysnc: start capture at 3rd vsync
+ * frame rate of QSXGA and 1080P is 7.5fps: 1/7.5 * 2
+ */
+ pr_warning("ov5640: the actual frame rate of %s is 7.5fps\n",
+ mode == ov5640_mode_1080P_1920_1080 ? "1080P" : "QSXGA");
+ msleep(267);
+err:
+ return retval;
+}
+
+static int ov5640_change_mode(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ int retval = 0;
+
+ if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
+ pr_err("Wrong ov5640 mode detected!\n");
+ return -1;
+ }
+
+ if (mode == ov5640_mode_1080P_1920_1080 ||
+ mode == ov5640_mode_QSXGA_2592_1944) {
+ /* change to scaling mode go through exposure calucation
+ * image size above 1280 * 960 is scaling mode */
+ retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
+ } else {
+ /* change back to subsampling modem download firmware directly
+ * image size below 1280 * 960 is subsampling mode */
+ retval = ov5640_change_mode_direct(frame_rate, mode);
+ }
+
+ return retval;
+}
+
+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ if (s == NULL) {
+ pr_err(" ERROR!! no slave device set!\n");
+ return -1;
+ }
+
+ memset(p, 0, sizeof(*p));
+ p->u.bt656.clock_curr = ov5640_data.mclk;
+ pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk);
+ p->if_type = V4L2_IF_TYPE_BT656;
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.clock_min = OV5640_XCLK_MIN;
+ p->u.bt656.clock_max = OV5640_XCLK_MAX;
+ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
+
+ return 0;
+}
+
+/*!
+ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ struct sensor_data *sensor = s->priv;
+
+ if (on && !sensor->on) {
+ if (io_regulator)
+ if (regulator_enable(io_regulator) != 0)
+ return -EIO;
+ if (core_regulator)
+ if (regulator_enable(core_regulator) != 0)
+ return -EIO;
+ if (analog_regulator)
+ if (regulator_enable(analog_regulator) != 0)
+ return -EIO;
+ /* Make sure power on */
+ ov5640_power_down(0);
+ } else if (!on && sensor->on) {
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+ if (core_regulator)
+ regulator_disable(core_regulator);
+ if (io_regulator)
+ regulator_disable(io_regulator);
+
+ ov5640_power_down(1);
+}
+
+ sensor->on = on;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor_data *sensor = s->priv;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ int ret = 0;
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->streamcap.capability;
+ cparm->timeperframe = sensor->streamcap.timeperframe;
+ cparm->capturemode = sensor->streamcap.capturemode;
+ ret = 0;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor_data *sensor = s->priv;
+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5640_frame_rate frame_rate;
+ int ret = 0;
+
+ /* Make sure power on */
+ ov5640_power_down(0);
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ /* Check that the new frame rate is allowed. */
+ if ((timeperframe->numerator == 0) ||
+ (timeperframe->denominator == 0)) {
+ timeperframe->denominator = DEFAULT_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps > MAX_FPS) {
+ timeperframe->denominator = MAX_FPS;
+ timeperframe->numerator = 1;
+ } else if (tgt_fps < MIN_FPS) {
+ timeperframe->denominator = MIN_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ /* Actual frame rate we use */
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5640_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5640_30_fps;
+ else {
+ pr_err(" The camera frame rate is not supported!\n");
+ return -EINVAL;
+ }
+
+ ret = ov5640_change_mode(frame_rate,
+ a->parm.capture.capturemode);
+ if (ret < 0)
+ return ret;
+
+ sensor->streamcap.timeperframe = *timeperframe;
+ sensor->streamcap.capturemode = a->parm.capture.capturemode;
+
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_debug(" type is not " \
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+ a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+ struct sensor_data *sensor = s->priv;
+
+ f->fmt.pix = sensor->pix;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array. Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int ret = 0;
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ vc->value = ov5640_data.brightness;
+ break;
+ case V4L2_CID_HUE:
+ vc->value = ov5640_data.hue;
+ break;
+ case V4L2_CID_CONTRAST:
+ vc->value = ov5640_data.contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ vc->value = ov5640_data.saturation;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ vc->value = ov5640_data.red;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ vc->value = ov5640_data.blue;
+ break;
+ case V4L2_CID_EXPOSURE:
+ vc->value = ov5640_data.ae_mode;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array). Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int retval = 0;
+
+ pr_debug("In ov5640:ioctl_s_ctrl %d\n",
+ vc->id);
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ break;
+ case V4L2_CID_CONTRAST:
+ break;
+ case V4L2_CID_SATURATION:
+ break;
+ case V4L2_CID_HUE:
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ break;
+ case V4L2_CID_RED_BALANCE:
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ break;
+ case V4L2_CID_GAMMA:
+ break;
+ case V4L2_CID_EXPOSURE:
+ break;
+ case V4L2_CID_AUTOGAIN:
+ break;
+ case V4L2_CID_GAIN:
+ break;
+ case V4L2_CID_HFLIP:
+ break;
+ case V4L2_CID_VFLIP:
+ break;
+ default:
+ retval = -EPERM;
+ break;
+ }
+
+ return retval;
+}
+
+/*!
+ * ioctl_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_framesizes(struct v4l2_int_device *s,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ fsize->pixel_format = ov5640_data.pix.pixelformat;
+ fsize->discrete.width =
+ max(ov5640_mode_info_data[0][fsize->index].width,
+ ov5640_mode_info_data[1][fsize->index].width);
+ fsize->discrete.height =
+ max(ov5640_mode_info_data[0][fsize->index].height,
+ ov5640_mode_info_data[1][fsize->index].height);
+ return 0;
+}
+
+/*!
+ * ioctl_enum_frameintervals - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
+ struct v4l2_frmivalenum *fival)
+{
+ int i, j, count;
+
+ if (fival->index < 0 || fival->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ if (fival->width == 0 || fival->height == 0 ||
+ fival->pixel_format == 0) {
+ pr_warning("Please assign pixelformat, width and height.\n");
+ return -EINVAL;
+ }
+
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1;
+
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
+ for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
+ if (fival->pixel_format == ov5640_data.pix.pixelformat
+ && fival->width == ov5640_mode_info_data[i][j].width
+ && fival->height == ov5640_mode_info_data[i][j].height
+ && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
+ count++;
+ }
+ if (fival->index == (count - 1)) {
+ fival->discrete.denominator =
+ ov5640_framerates[i];
+ return 0;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ * VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+ ((struct v4l2_dbg_chip_ident *)id)->match.type =
+ V4L2_CHIP_MATCH_I2C_DRIVER;
+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5640_camera");
+
+ return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+
+ return 0;
+}
+
+/*!
+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
+ * @s: pointer to standard V4L2 device structure
+ * @fmt: pointer to standard V4L2 fmt description structure
+ *
+ * Return 0.
+ */
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_fmtdesc *fmt)
+{
+ if (fmt->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ fmt->pixelformat = ov5640_data.pix.pixelformat;
+
+ return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ struct sensor_data *sensor = s->priv;
+ u32 tgt_xclk; /* target xclk */
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5640_frame_rate frame_rate;
+ int ret;
+
+ ov5640_data.on = true;
+
+ /* mclk */
+ tgt_xclk = ov5640_data.mclk;
+ tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
+ tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
+ ov5640_data.mclk = tgt_xclk;
+
+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+ clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk);
+
+ /* Default camera frame rate is set in probe */
+ tgt_fps = sensor->streamcap.timeperframe.denominator /
+ sensor->streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5640_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5640_30_fps;
+ else
+ return -EINVAL; /* Only support 15fps or 30fps now. */
+
+ ret = ov5640_init_mode();
+ return ret;
+}
+
+/*!
+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Delinitialise the device when slave detaches to the master.
+ */
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+ return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module and links them to the
+ * enumeration.
+ */
+static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = {
+ { vidioc_int_dev_init_num,
+ (v4l2_int_ioctl_func *)ioctl_dev_init },
+ { vidioc_int_dev_exit_num,
+ ioctl_dev_exit},
+ { vidioc_int_s_power_num,
+ (v4l2_int_ioctl_func *)ioctl_s_power },
+ { vidioc_int_g_ifparm_num,
+ (v4l2_int_ioctl_func *)ioctl_g_ifparm },
+ { vidioc_int_init_num,
+ (v4l2_int_ioctl_func *)ioctl_init },
+ { vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
+ { vidioc_int_g_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
+ { vidioc_int_g_parm_num,
+ (v4l2_int_ioctl_func *)ioctl_g_parm },
+ { vidioc_int_s_parm_num,
+ (v4l2_int_ioctl_func *)ioctl_s_parm },
+ { vidioc_int_g_ctrl_num,
+ (v4l2_int_ioctl_func *)ioctl_g_ctrl },
+ { vidioc_int_s_ctrl_num,
+ (v4l2_int_ioctl_func *)ioctl_s_ctrl },
+ { vidioc_int_enum_framesizes_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
+ { vidioc_int_enum_frameintervals_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
+ { vidioc_int_g_chip_ident_num,
+ (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
+};
+
+static struct v4l2_int_slave ov5640_slave = {
+ .ioctls = ov5640_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc),
+};
+
+static struct v4l2_int_device ov5640_int_device = {
+ .module = THIS_MODULE,
+ .name = "ov564x",
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &ov5640_slave,
+ },
+};
+
+/*!
+ * ov5640 I2C probe function
+ *
+ * @param adapter struct i2c_adapter *
+ * @return Error code indicating success or failure
+ */
+static int ov5640_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+ int retval;
+ u8 chip_id_high, chip_id_low;
+
+ /* ov5640 pinctrl */
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(dev, "setup pinctrl failed\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio)) {
+ dev_err(dev, "no sensor pwdn pin available\n");
+ return -ENODEV;
+ }
+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_pwdn");
+ if (retval < 0)
+ return retval;
+
+ /* request reset pin */
+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(rst_gpio)) {
+ dev_err(dev, "no sensor reset pin available\n");
+ return -EINVAL;
+ }
+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_reset");
+ if (retval < 0)
+ return retval;
+
+ /* Set initial values for the sensor struct. */
+ memset(&ov5640_data, 0, sizeof(ov5640_data));
+ ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(ov5640_data.sensor_clk)) {
+ dev_err(dev, "get mclk failed\n");
+ return PTR_ERR(ov5640_data.sensor_clk);
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk",
+ &ov5640_data.mclk);
+ if (retval) {
+ dev_err(dev, "mclk frequency is invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk_source",
+ (u32 *) &(ov5640_data.mclk_source));
+ if (retval) {
+ dev_err(dev, "mclk_source invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "csi_id",
+ &(ov5640_data.csi));
+ if (retval) {
+ dev_err(dev, "csi_id invalid\n");
+ return retval;
+ }
+
+ clk_prepare_enable(ov5640_data.sensor_clk);
+
+ ov5640_data.io_init = ov5640_reset;
+ ov5640_data.i2c_client = client;
+ ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ ov5640_data.pix.width = 640;
+ ov5640_data.pix.height = 480;
+ ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+ V4L2_CAP_TIMEPERFRAME;
+ ov5640_data.streamcap.capturemode = 0;
+ ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+ ov5640_data.streamcap.timeperframe.numerator = 1;
+
+ ov5640_regulator_enable(&client->dev);
+
+ ov5640_reset();
+
+ ov5640_power_down(0);
+
+ retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
+ if (retval < 0 || chip_id_high != 0x56) {
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ pr_warning("camera ov5640 is not found\n");
+ return -ENODEV;
+ }
+ retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
+ if (retval < 0 || chip_id_low != 0x40) {
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ pr_warning("camera ov5640 is not found\n");
+ return -ENODEV;
+ }
+
+ ov5640_power_down(1);
+
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+
+ ov5640_int_device.priv = &ov5640_data;
+ retval = v4l2_int_device_register(&ov5640_int_device);
+
+ pr_info("camera ov5640 is found\n");
+ return retval;
+}
+
+/*!
+ * ov5640 I2C detach function
+ *
+ * @param client struct i2c_client *
+ * @return Error code indicating success or failure
+ */
+static int ov5640_remove(struct i2c_client *client)
+{
+ v4l2_int_device_unregister(&ov5640_int_device);
+
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+
+ if (core_regulator)
+ regulator_disable(core_regulator);
+
+ if (io_regulator)
+ regulator_disable(io_regulator);
+
+ return 0;
+}
+
+module_i2c_driver(ov5640_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5640 Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/capture/ov5640_mipi.c b/drivers/media/platform/mxc/capture/ov5640_mipi.c
new file mode 100644
index 000000000000..0d146b534f61
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ov5640_mipi.c
@@ -0,0 +1,2142 @@
+/*
+ * 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.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/fsl_devices.h>
+#include <linux/mipi_csi2.h>
+#include <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.h"
+
+#define OV5640_VOLTAGE_ANALOG 2800000
+#define OV5640_VOLTAGE_DIGITAL_CORE 1500000
+#define OV5640_VOLTAGE_DIGITAL_IO 1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5640_XCLK_MIN 6000000
+#define OV5640_XCLK_MAX 24000000
+
+#define OV5640_CHIP_ID_HIGH_BYTE 0x300A
+#define OV5640_CHIP_ID_LOW_BYTE 0x300B
+
+enum ov5640_mode {
+ ov5640_mode_MIN = 0,
+ ov5640_mode_VGA_640_480 = 0,
+ ov5640_mode_QVGA_320_240 = 1,
+ ov5640_mode_NTSC_720_480 = 2,
+ ov5640_mode_PAL_720_576 = 3,
+ ov5640_mode_720P_1280_720 = 4,
+ ov5640_mode_1080P_1920_1080 = 5,
+ ov5640_mode_QSXGA_2592_1944 = 6,
+ ov5640_mode_QCIF_176_144 = 7,
+ ov5640_mode_XGA_1024_768 = 8,
+ ov5640_mode_MAX = 8,
+ ov5640_mode_INIT = 0xff, /*only for sensor init*/
+};
+
+enum ov5640_frame_rate {
+ ov5640_15_fps,
+ ov5640_30_fps
+};
+
+static int ov5640_framerates[] = {
+ [ov5640_15_fps] = 15,
+ [ov5640_30_fps] = 30,
+};
+
+/* image size under 1280 * 960 are SUBSAMPLING
+ * image size upper 1280 * 960 are SCALING
+ */
+enum ov5640_downsize_mode {
+ SUBSAMPLING,
+ SCALING,
+};
+
+struct reg_value {
+ u16 u16RegAddr;
+ u8 u8Val;
+ u8 u8Mask;
+ u32 u32Delay_ms;
+};
+
+struct ov5640_mode_info {
+ enum ov5640_mode mode;
+ enum ov5640_downsize_mode dn_mode;
+ u32 width;
+ u32 height;
+ struct reg_value *init_data_ptr;
+ u32 init_data_size;
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct sensor_data ov5640_data;
+static int pwn_gpio, rst_gpio;
+
+static struct reg_value ov5640_init_setting_30fps_VGA[] = {
+
+ {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
+ {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
+ {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
+ {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
+ {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
+ {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+ {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
+ {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
+ {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
+ {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
+ {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
+ {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
+ {0x3c01, 0xa4, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
+ {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
+ {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
+ {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
+ {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0},
+ {0x518a, 0x54, 0, 0}, {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0},
+ {0x518d, 0x50, 0, 0}, {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0},
+ {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0},
+ {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0},
+ {0x5199, 0x6c, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0},
+ {0x519c, 0x09, 0, 0}, {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0},
+ {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0},
+ {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0},
+ {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0},
+ {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0},
+ {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0},
+ {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0},
+ {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0},
+ {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0},
+ {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0},
+ {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0},
+ {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0},
+ {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0},
+ {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0},
+ {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0},
+ {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0},
+ {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0},
+ {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0},
+ {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0},
+ {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0},
+ {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0},
+ {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0},
+ {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0},
+ {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0},
+ {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0},
+ {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0},
+ {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0},
+ {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0},
+ {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0},
+ {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0},
+ {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0},
+ {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0},
+ {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0},
+ {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0},
+ {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0},
+ {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0},
+ {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0},
+ {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0},
+ {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
+};
+
+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
+
+ {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
+ {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
+
+ {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
+ {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+ {0x380b, 0x00, 0, 0}, {0x3035, 0x12, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
+ {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3808, 0x04, 0, 0},
+ {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
+ {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
+ {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
+ {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
+ {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
+ {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
+ {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
+ {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
+ {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
+ {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
+ {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
+ {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
+ {0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
+ {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
+ {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
+ {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+ {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, {0x4005, 0x1a, 0, 0},
+ {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
+ {0x3035, 0x41, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
+ {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
+ {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
+ {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+ {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
+ {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+ {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+ {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
+ {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
+ {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
+ {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
+ {0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
+ {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
+ {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
+ {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
+ {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0},
+ {0x3503, 0, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
+ {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+ {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+ {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x54, 0, 1}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
+ {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
+ {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
+ {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
+ {0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
+ {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
+ {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
+ {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
+ {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
+ {0x4202, 0x0f, 0, 0}, /* stream off the sensor */
+ {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, /*disable flip*/
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
+ {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+ {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+ {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70},
+ {0x4202, 0x00, 0, 0}, /* stream on the sensor */
+};
+
+static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
+ {
+ {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480,
+ ov5640_setting_15fps_VGA_640_480,
+ ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
+ {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320, 240,
+ ov5640_setting_15fps_QVGA_320_240,
+ ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
+ {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
+ ov5640_setting_15fps_NTSC_720_480,
+ ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
+ {ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
+ ov5640_setting_15fps_PAL_720_576,
+ ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
+ {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
+ ov5640_setting_15fps_720P_1280_720,
+ ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
+ {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
+ ov5640_setting_15fps_1080P_1920_1080,
+ ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
+ {ov5640_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
+ ov5640_setting_15fps_QSXGA_2592_1944,
+ ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
+ {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
+ ov5640_setting_15fps_QCIF_176_144,
+ ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
+ {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768,
+ ov5640_setting_15fps_XGA_1024_768,
+ ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
+ },
+ {
+ {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480,
+ ov5640_setting_30fps_VGA_640_480,
+ ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
+ {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320, 240,
+ ov5640_setting_30fps_QVGA_320_240,
+ ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
+ {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
+ ov5640_setting_30fps_NTSC_720_480,
+ ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
+ {ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
+ ov5640_setting_30fps_PAL_720_576,
+ ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
+ {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
+ ov5640_setting_30fps_720P_1280_720,
+ ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
+ {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
+ ov5640_setting_30fps_1080P_1920_1080,
+ ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
+ {ov5640_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
+ {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
+ ov5640_setting_30fps_QCIF_176_144,
+ ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
+ {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768,
+ ov5640_setting_30fps_XGA_1024_768,
+ ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
+ },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+static struct regulator *gpo_regulator;
+
+static int ov5640_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *device_id);
+static int ov5640_remove(struct i2c_client *client);
+
+static s32 ov5640_read_reg(u16 reg, u8 *val);
+static s32 ov5640_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5640_id[] = {
+ {"ov564x_mipi", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ov564x_mipi",
+ },
+ .probe = ov5640_probe,
+ .remove = ov5640_remove,
+ .id_table = ov5640_id,
+};
+
+static void ov5640_standby(s32 enable)
+{
+ if (enable)
+ gpio_set_value(pwn_gpio, 1);
+ else
+ gpio_set_value(pwn_gpio, 0);
+
+ msleep(100);
+}
+
+static void ov5640_reset(void)
+{
+ /* camera reset */
+ gpio_set_value(rst_gpio, 1);
+
+ /* camera power dowmn */
+ gpio_set_value(pwn_gpio, 1);
+ msleep(5);
+
+ gpio_set_value(pwn_gpio, 0);
+ msleep(5);
+
+ gpio_set_value(rst_gpio, 0);
+ msleep(1);
+
+ gpio_set_value(rst_gpio, 1);
+ msleep(5);
+
+ gpio_set_value(pwn_gpio, 1);
+}
+
+static int ov5640_power_on(struct device *dev)
+{
+ int ret = 0;
+
+ io_regulator = devm_regulator_get(dev, "DOVDD");
+ if (!IS_ERR(io_regulator)) {
+ regulator_set_voltage(io_regulator,
+ OV5640_VOLTAGE_DIGITAL_IO,
+ OV5640_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(io_regulator);
+ if (ret) {
+ pr_err("%s:io set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:io set voltage ok\n", __func__);
+ }
+ } else {
+ pr_err("%s: cannot get io voltage error\n", __func__);
+ io_regulator = NULL;
+ }
+
+ core_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(core_regulator)) {
+ regulator_set_voltage(core_regulator,
+ OV5640_VOLTAGE_DIGITAL_CORE,
+ OV5640_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(core_regulator);
+ if (ret) {
+ pr_err("%s:core set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:core set voltage ok\n", __func__);
+ }
+ } else {
+ core_regulator = NULL;
+ pr_err("%s: cannot get core voltage error\n", __func__);
+ }
+
+ analog_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(analog_regulator)) {
+ regulator_set_voltage(analog_regulator,
+ OV5640_VOLTAGE_ANALOG,
+ OV5640_VOLTAGE_ANALOG);
+ ret = regulator_enable(analog_regulator);
+ if (ret) {
+ pr_err("%s:analog set voltage error\n",
+ __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:analog set voltage ok\n", __func__);
+ }
+ } else {
+ analog_regulator = NULL;
+ pr_err("%s: cannot get analog voltage error\n", __func__);
+ }
+
+ return ret;
+}
+
+static s32 ov5640_write_reg(u16 reg, u8 val)
+{
+ u8 au8Buf[3] = {0};
+
+ au8Buf[0] = reg >> 8;
+ au8Buf[1] = reg & 0xff;
+ au8Buf[2] = val;
+
+ if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x\n",
+ __func__, reg, val);
+ return -1;
+ }
+
+ return 0;
+}
+
+static s32 ov5640_read_reg(u16 reg, u8 *val)
+{
+ u8 au8RegBuf[2] = {0};
+ u8 u8RdVal = 0;
+
+ au8RegBuf[0] = reg >> 8;
+ au8RegBuf[1] = reg & 0xff;
+
+ if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
+ pr_err("%s:write reg error:reg=%x\n",
+ __func__, reg);
+ return -1;
+ }
+
+ if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
+ pr_err("%s:read reg error:reg=%x,val=%x\n",
+ __func__, reg, u8RdVal);
+ return -1;
+ }
+
+ *val = u8RdVal;
+
+ return u8RdVal;
+}
+
+static int prev_sysclk, prev_HTS;
+static int AE_low, AE_high, AE_Target = 52;
+
+static void OV5640_stream_on(void)
+{
+ ov5640_write_reg(0x4202, 0x00);
+}
+
+static void OV5640_stream_off(void)
+{
+ ov5640_write_reg(0x4202, 0x0f);
+}
+
+
+static int OV5640_get_sysclk(void)
+{
+ /* calculate sysclk */
+ int xvclk = ov5640_data.mclk / 10000;
+ int temp1, temp2;
+ int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv;
+ int Bit_div2x = 1, sclk_rdiv, sysclk;
+ u8 temp;
+
+ int sclk_rdiv_map[] = {1, 2, 4, 8};
+
+ temp1 = ov5640_read_reg(0x3034, &temp);
+ temp2 = temp1 & 0x0f;
+ if (temp2 == 8 || temp2 == 10)
+ Bit_div2x = temp2 / 2;
+
+ temp1 = ov5640_read_reg(0x3035, &temp);
+ SysDiv = temp1>>4;
+ if (SysDiv == 0)
+ SysDiv = 16;
+
+ temp1 = ov5640_read_reg(0x3036, &temp);
+ Multiplier = temp1;
+
+ temp1 = ov5640_read_reg(0x3037, &temp);
+ PreDiv = temp1 & 0x0f;
+ Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
+
+ temp1 = ov5640_read_reg(0x3108, &temp);
+ temp2 = temp1 & 0x03;
+ sclk_rdiv = sclk_rdiv_map[temp2];
+
+ VCO = xvclk * Multiplier / PreDiv;
+
+ sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
+
+ return sysclk;
+}
+
+static void OV5640_set_night_mode(void)
+{
+ /* read HTS from register settings */
+ u8 mode;
+
+ ov5640_read_reg(0x3a00, &mode);
+ mode &= 0xfb;
+ ov5640_write_reg(0x3a00, mode);
+}
+
+static int OV5640_get_HTS(void)
+{
+ /* read HTS from register settings */
+ int HTS;
+ u8 temp;
+
+ HTS = ov5640_read_reg(0x380c, &temp);
+ HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
+
+ return HTS;
+}
+
+static int OV5640_get_VTS(void)
+{
+ /* read VTS from register settings */
+ int VTS;
+ u8 temp;
+
+ /* total vertical size[15:8] high byte */
+ VTS = ov5640_read_reg(0x380e, &temp);
+
+ VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
+
+ return VTS;
+}
+
+static int OV5640_set_VTS(int VTS)
+{
+ /* write VTS to registers */
+ int temp;
+
+ temp = VTS & 0xff;
+ ov5640_write_reg(0x380f, temp);
+
+ temp = VTS>>8;
+ ov5640_write_reg(0x380e, temp);
+
+ return 0;
+}
+
+static int OV5640_get_shutter(void)
+{
+ /* read shutter, in number of line period */
+ int shutter;
+ u8 temp;
+
+ shutter = (ov5640_read_reg(0x03500, &temp) & 0x0f);
+ shutter = (shutter<<8) + ov5640_read_reg(0x3501, &temp);
+ shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &temp)>>4);
+
+ return shutter;
+}
+
+static int OV5640_set_shutter(int shutter)
+{
+ /* write shutter, in number of line period */
+ int temp;
+
+ shutter = shutter & 0xffff;
+
+ temp = shutter & 0x0f;
+ temp = temp<<4;
+ ov5640_write_reg(0x3502, temp);
+
+ temp = shutter & 0xfff;
+ temp = temp>>4;
+ ov5640_write_reg(0x3501, temp);
+
+ temp = shutter>>12;
+ ov5640_write_reg(0x3500, temp);
+
+ return 0;
+}
+
+static int OV5640_get_gain16(void)
+{
+ /* read gain, 16 = 1x */
+ int gain16;
+ u8 temp;
+
+ gain16 = ov5640_read_reg(0x350a, &temp) & 0x03;
+ gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &temp);
+
+ return gain16;
+}
+
+static int OV5640_set_gain16(int gain16)
+{
+ /* write gain, 16 = 1x */
+ u8 temp;
+ gain16 = gain16 & 0x3ff;
+
+ temp = gain16 & 0xff;
+ ov5640_write_reg(0x350b, temp);
+
+ temp = gain16>>8;
+ ov5640_write_reg(0x350a, temp);
+
+ return 0;
+}
+
+static int OV5640_get_light_freq(void)
+{
+ /* get banding filter value */
+ int temp, temp1, light_freq = 0;
+ u8 tmp;
+
+ temp = ov5640_read_reg(0x3c01, &tmp);
+
+ if (temp & 0x80) {
+ /* manual */
+ temp1 = ov5640_read_reg(0x3c00, &tmp);
+ if (temp1 & 0x04) {
+ /* 50Hz */
+ light_freq = 50;
+ } else {
+ /* 60Hz */
+ light_freq = 60;
+ }
+ } else {
+ /* auto */
+ temp1 = ov5640_read_reg(0x3c0c, &tmp);
+ if (temp1 & 0x01) {
+ /* 50Hz */
+ light_freq = 50;
+ } else {
+ /* 60Hz */
+ }
+ }
+ return light_freq;
+}
+
+static void OV5640_set_bandingfilter(void)
+{
+ int prev_VTS;
+ int band_step60, max_band60, band_step50, max_band50;
+
+ /* read preview PCLK */
+ prev_sysclk = OV5640_get_sysclk();
+ /* read preview HTS */
+ prev_HTS = OV5640_get_HTS();
+
+ /* read preview VTS */
+ prev_VTS = OV5640_get_VTS();
+
+ /* calculate banding filter */
+ /* 60Hz */
+ band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
+ ov5640_write_reg(0x3a0a, (band_step60 >> 8));
+ ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
+
+ max_band60 = (int)((prev_VTS-4)/band_step60);
+ ov5640_write_reg(0x3a0d, max_band60);
+
+ /* 50Hz */
+ band_step50 = prev_sysclk * 100/prev_HTS;
+ ov5640_write_reg(0x3a08, (band_step50 >> 8));
+ ov5640_write_reg(0x3a09, (band_step50 & 0xff));
+
+ max_band50 = (int)((prev_VTS-4)/band_step50);
+ ov5640_write_reg(0x3a0e, max_band50);
+}
+
+static int OV5640_set_AE_target(int target)
+{
+ /* stable in high */
+ int fast_high, fast_low;
+ AE_low = target * 23 / 25; /* 0.92 */
+ AE_high = target * 27 / 25; /* 1.08 */
+
+ fast_high = AE_high<<1;
+ if (fast_high > 255)
+ fast_high = 255;
+
+ fast_low = AE_low >> 1;
+
+ ov5640_write_reg(0x3a0f, AE_high);
+ ov5640_write_reg(0x3a10, AE_low);
+ ov5640_write_reg(0x3a1b, AE_high);
+ ov5640_write_reg(0x3a1e, AE_low);
+ ov5640_write_reg(0x3a11, fast_high);
+ ov5640_write_reg(0x3a1f, fast_low);
+
+ return 0;
+}
+
+static void OV5640_turn_on_AE_AG(int enable)
+{
+ u8 ae_ag_ctrl;
+
+ ov5640_read_reg(0x3503, &ae_ag_ctrl);
+ if (enable) {
+ /* turn on auto AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
+ } else {
+ /* turn off AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl | 0x03;
+ }
+ ov5640_write_reg(0x3503, ae_ag_ctrl);
+}
+
+static bool binning_on(void)
+{
+ u8 temp;
+ ov5640_read_reg(0x3821, &temp);
+ temp &= 0xfe;
+ if (temp)
+ return true;
+ else
+ return false;
+}
+
+static void ov5640_set_virtual_channel(int channel)
+{
+ u8 channel_id;
+
+ ov5640_read_reg(0x4814, &channel_id);
+ channel_id &= ~(3 << 6);
+ ov5640_write_reg(0x4814, channel_id | (channel << 6));
+}
+
+/* download ov5640 settings to sensor through i2c */
+static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+{
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int i, retval = 0;
+
+ for (i = 0; i < ArySize; ++i, ++pModeSetting) {
+ Delay_ms = pModeSetting->u32Delay_ms;
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u8Val;
+ Mask = pModeSetting->u8Mask;
+
+ if (Mask) {
+ retval = ov5640_read_reg(RegAddr, &RegVal);
+ if (retval < 0)
+ goto err;
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = ov5640_write_reg(RegAddr, Val);
+ if (retval < 0)
+ goto err;
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+ }
+err:
+ return retval;
+}
+
+/* sensor changes between scaling and subsampling
+ * go through exposure calcualtion
+ */
+static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ u8 average;
+ int prev_shutter, prev_gain16;
+ int cap_shutter, cap_gain16;
+ int cap_sysclk, cap_HTS, cap_VTS;
+ int light_freq, cap_bandfilt, cap_maxband;
+ long cap_gain16_shutter;
+ int retval = 0;
+
+ /* check if the input mode and frame rate is valid */
+ pModeSetting =
+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5640_data.pix.width =
+ ov5640_mode_info_data[frame_rate][mode].width;
+ ov5640_data.pix.height =
+ ov5640_mode_info_data[frame_rate][mode].height;
+
+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* auto focus */
+ /* OV5640_auto_focus();//if no af function, just skip it */
+
+ /* turn off AE/AG */
+ OV5640_turn_on_AE_AG(0);
+
+ /* read preview shutter */
+ prev_shutter = OV5640_get_shutter();
+ if ((binning_on()) && (mode != ov5640_mode_720P_1280_720)
+ && (mode != ov5640_mode_1080P_1920_1080))
+ prev_shutter *= 2;
+
+ /* read preview gain */
+ prev_gain16 = OV5640_get_gain16();
+
+ /* get average */
+ ov5640_read_reg(0x56a1, &average);
+
+ /* turn off night mode for capture */
+ OV5640_set_night_mode();
+
+ /* turn off overlay */
+ /* ov5640_write_reg(0x3022, 0x06);//if no af function, just skip it */
+
+ OV5640_stream_off();
+
+ /* Write capture setting */
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ /* read capture VTS */
+ cap_VTS = OV5640_get_VTS();
+ cap_HTS = OV5640_get_HTS();
+ cap_sysclk = OV5640_get_sysclk();
+
+ /* calculate capture banding filter */
+ light_freq = OV5640_get_light_freq();
+ if (light_freq == 60) {
+ /* 60Hz */
+ cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
+ } else {
+ /* 50Hz */
+ cap_bandfilt = cap_sysclk * 100 / cap_HTS;
+ }
+ cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
+
+ /* calculate capture shutter/gain16 */
+ if (average > AE_low && average < AE_high) {
+ /* in stable range */
+ cap_gain16_shutter =
+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
+ * prev_HTS/cap_HTS * AE_Target / average;
+ } else {
+ cap_gain16_shutter =
+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
+ * prev_HTS/cap_HTS;
+ }
+
+ /* gain to shutter */
+ if (cap_gain16_shutter < (cap_bandfilt * 16)) {
+ /* shutter < 1/100 */
+ cap_shutter = cap_gain16_shutter/16;
+ if (cap_shutter < 1)
+ cap_shutter = 1;
+
+ cap_gain16 = cap_gain16_shutter/cap_shutter;
+ if (cap_gain16 < 16)
+ cap_gain16 = 16;
+ } else {
+ if (cap_gain16_shutter >
+ (cap_bandfilt * cap_maxband * 16)) {
+ /* exposure reach max */
+ cap_shutter = cap_bandfilt * cap_maxband;
+ cap_gain16 = cap_gain16_shutter / cap_shutter;
+ } else {
+ /* 1/100 < (cap_shutter = n/100) =< max */
+ cap_shutter =
+ ((int) (cap_gain16_shutter/16 / cap_bandfilt))
+ *cap_bandfilt;
+ cap_gain16 = cap_gain16_shutter / cap_shutter;
+ }
+ }
+
+ /* write capture gain */
+ OV5640_set_gain16(cap_gain16);
+
+ /* write capture shutter */
+ if (cap_shutter > (cap_VTS - 4)) {
+ cap_VTS = cap_shutter + 4;
+ OV5640_set_VTS(cap_VTS);
+ }
+ OV5640_set_shutter(cap_shutter);
+
+ OV5640_stream_on();
+
+err:
+ return retval;
+}
+
+/* if sensor changes inside scaling or subsampling
+ * change mode directly
+ * */
+static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+
+ /* check if the input mode and frame rate is valid */
+ pModeSetting =
+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5640_data.pix.width =
+ ov5640_mode_info_data[frame_rate][mode].width;
+ ov5640_data.pix.height =
+ ov5640_mode_info_data[frame_rate][mode].height;
+
+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* turn off AE/AG */
+ OV5640_turn_on_AE_AG(0);
+
+ OV5640_stream_off();
+
+ /* Write capture setting */
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ OV5640_stream_on();
+
+ OV5640_turn_on_AE_AG(1);
+
+err:
+ return retval;
+}
+
+static int ov5640_init_mode(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode, enum ov5640_mode orig_mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+ void *mipi_csi2_info;
+ u32 mipi_reg, msec_wait4stable = 0;
+ enum ov5640_downsize_mode dn_mode, orig_dn_mode;
+
+ if ((mode > ov5640_mode_MAX || mode < ov5640_mode_MIN)
+ && (mode != ov5640_mode_INIT)) {
+ pr_err("Wrong ov5640 mode detected!\n");
+ return -1;
+ }
+
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ /* initial mipi dphy */
+ if (!mipi_csi2_info) {
+ printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
+ __func__, __FILE__);
+ return -1;
+ }
+
+ if (!mipi_csi2_get_status(mipi_csi2_info))
+ mipi_csi2_enable(mipi_csi2_info);
+
+ if (!mipi_csi2_get_status(mipi_csi2_info)) {
+ pr_err("Can not enable mipi csi2 driver!\n");
+ return -1;
+ }
+
+ mipi_csi2_set_lanes(mipi_csi2_info);
+
+ /*Only reset MIPI CSI2 HW at sensor initialize*/
+ if (mode == ov5640_mode_INIT)
+ mipi_csi2_reset(mipi_csi2_info);
+
+ if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_UYVY)
+ mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_YUV422);
+ else if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_RGB565)
+ mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_RGB565);
+ else
+ pr_err("currently this sensor format can not be supported!\n");
+
+ dn_mode = ov5640_mode_info_data[frame_rate][mode].dn_mode;
+ orig_dn_mode = ov5640_mode_info_data[frame_rate][orig_mode].dn_mode;
+ if (mode == ov5640_mode_INIT) {
+ pModeSetting = ov5640_init_setting_30fps_VGA;
+ ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
+
+ ov5640_data.pix.width = 640;
+ ov5640_data.pix.height = 480;
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ pModeSetting = ov5640_setting_30fps_VGA_640_480;
+ ArySize = ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480);
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ } else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
+ (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
+ /* change between subsampling and scaling
+ * go through exposure calucation */
+ retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
+ } else {
+ /* change inside subsampling or scaling
+ * download firmware directly */
+ retval = ov5640_change_mode_direct(frame_rate, mode);
+ }
+
+ if (retval < 0)
+ goto err;
+
+ OV5640_set_AE_target(AE_Target);
+ OV5640_get_light_freq();
+ OV5640_set_bandingfilter();
+ ov5640_set_virtual_channel(ov5640_data.csi);
+
+ /* add delay to wait for sensor stable */
+ if (mode == ov5640_mode_QSXGA_2592_1944) {
+ /* dump the first two frames: 1/7.5*2
+ * the frame rate of QSXGA is 7.5fps */
+ msec_wait4stable = 267;
+ } else if (frame_rate == ov5640_15_fps) {
+ /* dump the first nine frames: 1/15*9 */
+ msec_wait4stable = 600;
+ } else if (frame_rate == ov5640_30_fps) {
+ /* dump the first nine frames: 1/30*9 */
+ msec_wait4stable = 300;
+ }
+ msleep(msec_wait4stable);
+
+ if (mipi_csi2_info) {
+ unsigned int i;
+
+ i = 0;
+
+ /* wait for mipi sensor ready */
+ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
+ while ((mipi_reg == 0x200) && (i < 10)) {
+ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
+ i++;
+ msleep(10);
+ }
+
+ if (i >= 10) {
+ pr_err("mipi csi2 can not receive sensor clk!\n");
+ return -1;
+ }
+
+ i = 0;
+
+ /* wait for mipi stable */
+ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
+ while ((mipi_reg != 0x0) && (i < 10)) {
+ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
+ i++;
+ msleep(10);
+ }
+
+ if (i >= 10) {
+ pr_err("mipi csi2 can not reveive data correctly!\n");
+ return -1;
+ }
+ }
+err:
+ return retval;
+}
+
+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ if (s == NULL) {
+ pr_err(" ERROR!! no slave device set!\n");
+ return -1;
+ }
+
+ memset(p, 0, sizeof(*p));
+ p->u.bt656.clock_curr = ov5640_data.mclk;
+ pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk);
+ p->if_type = V4L2_IF_TYPE_BT656;
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.clock_min = OV5640_XCLK_MIN;
+ p->u.bt656.clock_max = OV5640_XCLK_MAX;
+ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
+
+ return 0;
+}
+
+/*!
+ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ struct sensor_data *sensor = s->priv;
+
+ if (on && !sensor->on) {
+ if (io_regulator)
+ if (regulator_enable(io_regulator) != 0)
+ return -EIO;
+ if (core_regulator)
+ if (regulator_enable(core_regulator) != 0)
+ return -EIO;
+ if (gpo_regulator)
+ if (regulator_enable(gpo_regulator) != 0)
+ return -EIO;
+ if (analog_regulator)
+ if (regulator_enable(analog_regulator) != 0)
+ return -EIO;
+ /* Make sure power on */
+ ov5640_standby(0);
+ } else if (!on && sensor->on) {
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+ if (core_regulator)
+ regulator_disable(core_regulator);
+ if (io_regulator)
+ regulator_disable(io_regulator);
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+
+ ov5640_standby(1);
+ }
+
+ sensor->on = on;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor_data *sensor = s->priv;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ int ret = 0;
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->streamcap.capability;
+ cparm->timeperframe = sensor->streamcap.timeperframe;
+ cparm->capturemode = sensor->streamcap.capturemode;
+ ret = 0;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor_data *sensor = s->priv;
+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5640_frame_rate frame_rate;
+ enum ov5640_mode orig_mode;
+ int ret = 0;
+
+ /* Make sure power on */
+ ov5640_standby(0);
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ /* Check that the new frame rate is allowed. */
+ if ((timeperframe->numerator == 0) ||
+ (timeperframe->denominator == 0)) {
+ timeperframe->denominator = DEFAULT_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps > MAX_FPS) {
+ timeperframe->denominator = MAX_FPS;
+ timeperframe->numerator = 1;
+ } else if (tgt_fps < MIN_FPS) {
+ timeperframe->denominator = MIN_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ /* Actual frame rate we use */
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5640_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5640_30_fps;
+ else {
+ pr_err(" The camera frame rate is not supported!\n");
+ return -EINVAL;
+ }
+
+ orig_mode = sensor->streamcap.capturemode;
+ ret = ov5640_init_mode(frame_rate,
+ (u32)a->parm.capture.capturemode, orig_mode);
+ if (ret < 0)
+ return ret;
+
+ sensor->streamcap.timeperframe = *timeperframe;
+ sensor->streamcap.capturemode =
+ (u32)a->parm.capture.capturemode;
+
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_debug(" type is not " \
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+ a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+ struct sensor_data *sensor = s->priv;
+
+ f->fmt.pix = sensor->pix;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array. Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int ret = 0;
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ vc->value = ov5640_data.brightness;
+ break;
+ case V4L2_CID_HUE:
+ vc->value = ov5640_data.hue;
+ break;
+ case V4L2_CID_CONTRAST:
+ vc->value = ov5640_data.contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ vc->value = ov5640_data.saturation;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ vc->value = ov5640_data.red;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ vc->value = ov5640_data.blue;
+ break;
+ case V4L2_CID_EXPOSURE:
+ vc->value = ov5640_data.ae_mode;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array). Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int retval = 0;
+
+ pr_debug("In ov5640:ioctl_s_ctrl %d\n",
+ vc->id);
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ break;
+ case V4L2_CID_CONTRAST:
+ break;
+ case V4L2_CID_SATURATION:
+ break;
+ case V4L2_CID_HUE:
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ break;
+ case V4L2_CID_RED_BALANCE:
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ break;
+ case V4L2_CID_GAMMA:
+ break;
+ case V4L2_CID_EXPOSURE:
+ break;
+ case V4L2_CID_AUTOGAIN:
+ break;
+ case V4L2_CID_GAIN:
+ break;
+ case V4L2_CID_HFLIP:
+ break;
+ case V4L2_CID_VFLIP:
+ break;
+ default:
+ retval = -EPERM;
+ break;
+ }
+
+ return retval;
+}
+
+/*!
+ * ioctl_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_framesizes(struct v4l2_int_device *s,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ fsize->pixel_format = ov5640_data.pix.pixelformat;
+ fsize->discrete.width =
+ max(ov5640_mode_info_data[0][fsize->index].width,
+ ov5640_mode_info_data[1][fsize->index].width);
+ fsize->discrete.height =
+ max(ov5640_mode_info_data[0][fsize->index].height,
+ ov5640_mode_info_data[1][fsize->index].height);
+ return 0;
+}
+
+/*!
+ * ioctl_enum_frameintervals - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
+ struct v4l2_frmivalenum *fival)
+{
+ int i, j, count = 0;
+
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1;
+
+ for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++)
+ for (j = 0; j < (ov5640_mode_MAX + 1); j++)
+ if (fival->pixel_format == ov5640_data.pix.pixelformat
+ && fival->width == ov5640_mode_info_data[i][j].width
+ && fival->height == ov5640_mode_info_data[i][j].height
+ && ov5640_mode_info_data[i][j].init_data_ptr != NULL
+ && fival->index == count++) {
+ fival->discrete.denominator =
+ ov5640_framerates[i];
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ * VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+ ((struct v4l2_dbg_chip_ident *)id)->match.type =
+ V4L2_CHIP_MATCH_I2C_DRIVER;
+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
+ "ov5640_mipi_camera");
+
+ return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+
+ return 0;
+}
+
+/*!
+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
+ * @s: pointer to standard V4L2 device structure
+ * @fmt: pointer to standard V4L2 fmt description structure
+ *
+ * Return 0.
+ */
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_fmtdesc *fmt)
+{
+ if (fmt->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ fmt->pixelformat = ov5640_data.pix.pixelformat;
+
+ return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ struct sensor_data *sensor = s->priv;
+ u32 tgt_xclk; /* target xclk */
+ u32 tgt_fps; /* target frames per secound */
+ int ret;
+ enum ov5640_frame_rate frame_rate;
+ void *mipi_csi2_info;
+
+ ov5640_data.on = true;
+
+ /* mclk */
+ tgt_xclk = ov5640_data.mclk;
+ tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
+ tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
+ ov5640_data.mclk = tgt_xclk;
+
+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+
+ /* Default camera frame rate is set in probe */
+ tgt_fps = sensor->streamcap.timeperframe.denominator /
+ sensor->streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5640_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5640_30_fps;
+ else
+ return -EINVAL; /* Only support 15fps or 30fps now. */
+
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ /* enable mipi csi2 */
+ if (mipi_csi2_info)
+ mipi_csi2_enable(mipi_csi2_info);
+ else {
+ printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
+ __func__, __FILE__);
+ return -EPERM;
+ }
+
+ ret = ov5640_init_mode(frame_rate, ov5640_mode_INIT, ov5640_mode_INIT);
+
+ return ret;
+}
+
+/*!
+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Delinitialise the device when slave detaches to the master.
+ */
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+ void *mipi_csi2_info;
+
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ /* disable mipi csi2 */
+ if (mipi_csi2_info)
+ if (mipi_csi2_get_status(mipi_csi2_info))
+ mipi_csi2_disable(mipi_csi2_info);
+
+ return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module and links them to the
+ * enumeration.
+ */
+static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = {
+ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *) ioctl_dev_init},
+ {vidioc_int_dev_exit_num, ioctl_dev_exit},
+ {vidioc_int_s_power_num, (v4l2_int_ioctl_func *) ioctl_s_power},
+ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *) ioctl_g_ifparm},
+/* {vidioc_int_g_needs_reset_num,
+ (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */
+/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */
+ {vidioc_int_init_num, (v4l2_int_ioctl_func *) ioctl_init},
+ {vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap},
+/* {vidioc_int_try_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */
+ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap},
+/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, */
+ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm},
+ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm},
+/* {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *)ioctl_queryctrl}, */
+ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl},
+ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl},
+ {vidioc_int_enum_framesizes_num,
+ (v4l2_int_ioctl_func *) ioctl_enum_framesizes},
+ {vidioc_int_enum_frameintervals_num,
+ (v4l2_int_ioctl_func *) ioctl_enum_frameintervals},
+ {vidioc_int_g_chip_ident_num,
+ (v4l2_int_ioctl_func *) ioctl_g_chip_ident},
+};
+
+static struct v4l2_int_slave ov5640_slave = {
+ .ioctls = ov5640_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc),
+};
+
+static struct v4l2_int_device ov5640_int_device = {
+ .module = THIS_MODULE,
+ .name = "ov564x",
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &ov5640_slave,
+ },
+};
+
+/*!
+ * ov5640 I2C probe function
+ *
+ * @param adapter struct i2c_adapter *
+ * @return Error code indicating success or failure
+ */
+static int ov5640_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ int retval;
+ u8 chip_id_high, chip_id_low;
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio)) {
+ dev_warn(dev, "no sensor pwdn pin available");
+ return -EINVAL;
+ }
+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_mipi_pwdn");
+ if (retval < 0)
+ return retval;
+
+ /* request reset pin */
+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(rst_gpio)) {
+ dev_warn(dev, "no sensor reset pin available");
+ return -EINVAL;
+ }
+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_mipi_reset");
+ if (retval < 0)
+ return retval;
+
+ /* Set initial values for the sensor struct. */
+ memset(&ov5640_data, 0, sizeof(ov5640_data));
+ ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(ov5640_data.sensor_clk)) {
+ /* assuming clock enabled by default */
+ ov5640_data.sensor_clk = NULL;
+ dev_err(dev, "clock-frequency missing or invalid\n");
+ return PTR_ERR(ov5640_data.sensor_clk);
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk",
+ &(ov5640_data.mclk));
+ if (retval) {
+ dev_err(dev, "mclk missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk_source",
+ (u32 *) &(ov5640_data.mclk_source));
+ if (retval) {
+ dev_err(dev, "mclk_source missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "csi_id",
+ &(ov5640_data.csi));
+ if (retval) {
+ dev_err(dev, "csi id missing or invalid\n");
+ return retval;
+ }
+
+ clk_prepare_enable(ov5640_data.sensor_clk);
+
+ ov5640_data.io_init = ov5640_reset;
+ ov5640_data.i2c_client = client;
+ ov5640_data.pix.pixelformat = V4L2_PIX_FMT_UYVY;
+ ov5640_data.pix.width = 640;
+ ov5640_data.pix.height = 480;
+ ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+ V4L2_CAP_TIMEPERFRAME;
+ ov5640_data.streamcap.capturemode = 0;
+ ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+ ov5640_data.streamcap.timeperframe.numerator = 1;
+
+ ov5640_power_on(dev);
+
+ ov5640_reset();
+
+ ov5640_standby(0);
+
+ retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
+ if (retval < 0 || chip_id_high != 0x56) {
+ pr_warning("camera ov5640_mipi is not found\n");
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ return -ENODEV;
+ }
+ retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
+ if (retval < 0 || chip_id_low != 0x40) {
+ pr_warning("camera ov5640_mipi is not found\n");
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ return -ENODEV;
+ }
+
+ ov5640_standby(1);
+
+ ov5640_int_device.priv = &ov5640_data;
+ retval = v4l2_int_device_register(&ov5640_int_device);
+
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+
+ pr_info("camera ov5640_mipi is found\n");
+ return retval;
+}
+
+/*!
+ * ov5640 I2C detach function
+ *
+ * @param client struct i2c_client *
+ * @return Error code indicating success or failure
+ */
+static int ov5640_remove(struct i2c_client *client)
+{
+ v4l2_int_device_unregister(&ov5640_int_device);
+
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+
+ if (core_regulator)
+ regulator_disable(core_regulator);
+
+ if (io_regulator)
+ regulator_disable(io_regulator);
+
+ return 0;
+}
+
+/*!
+ * ov5640 init function
+ * Called by insmod ov5640_camera.ko.
+ *
+ * @return Error code indicating success or failure
+ */
+static __init int ov5640_init(void)
+{
+ u8 err;
+
+ err = i2c_add_driver(&ov5640_i2c_driver);
+ if (err != 0)
+ pr_err("%s:driver registration failed, error=%d\n",
+ __func__, err);
+
+ return err;
+}
+
+/*!
+ * OV5640 cleanup function
+ * Called on rmmod ov5640_camera.ko
+ *
+ * @return Error code indicating success or failure
+ */
+static void __exit ov5640_clean(void)
+{
+ i2c_del_driver(&ov5640_i2c_driver);
+}
+
+module_init(ov5640_init);
+module_exit(ov5640_clean);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5640 MIPI Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/capture/ov5642.c b/drivers/media/platform/mxc/capture/ov5642.c
new file mode 100644
index 000000000000..be6122205c18
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ov5642.c
@@ -0,0 +1,4252 @@
+/*
+ * Copyright (C) 2012-2014 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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/fsl_devices.h>
+#include <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.h"
+
+#define OV5642_VOLTAGE_ANALOG 2800000
+#define OV5642_VOLTAGE_DIGITAL_CORE 1500000
+#define OV5642_VOLTAGE_DIGITAL_IO 1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5642_XCLK_MIN 6000000
+#define OV5642_XCLK_MAX 24000000
+
+#define OV5642_CHIP_ID_HIGH_BYTE 0x300A
+#define OV5642_CHIP_ID_LOW_BYTE 0x300B
+
+enum ov5642_mode {
+ ov5642_mode_MIN = 0,
+ ov5642_mode_VGA_640_480 = 0,
+ ov5642_mode_QVGA_320_240 = 1,
+ ov5642_mode_NTSC_720_480 = 2,
+ ov5642_mode_PAL_720_576 = 3,
+ ov5642_mode_720P_1280_720 = 4,
+ ov5642_mode_1080P_1920_1080 = 5,
+ ov5642_mode_QSXGA_2592_1944 = 6,
+ ov5642_mode_QCIF_176_144 = 7,
+ ov5642_mode_XGA_1024_768 = 8,
+ ov5642_mode_MAX = 8
+};
+
+enum ov5642_frame_rate {
+ ov5642_15_fps,
+ ov5642_30_fps
+};
+
+static int ov5642_framerates[] = {
+ [ov5642_15_fps] = 15,
+ [ov5642_30_fps] = 30,
+};
+
+struct reg_value {
+ u16 u16RegAddr;
+ u8 u8Val;
+ u8 u8Mask;
+ u32 u32Delay_ms;
+};
+
+struct ov5642_mode_info {
+ enum ov5642_mode mode;
+ u32 width;
+ u32 height;
+ struct reg_value *init_data_ptr;
+ u32 init_data_size;
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct sensor_data ov5642_data;
+static int pwn_gpio, rst_gpio;
+
+static struct reg_value ov5642_rot_none_VGA[] = {
+ {0x3818, 0xc1, 0x00, 0x00}, {0x3621, 0x87, 0x00, 0x00},
+};
+
+static struct reg_value ov5642_rot_vert_flip_VGA[] = {
+ {0x3818, 0x20, 0xbf, 0x00}, {0x3621, 0x20, 0xff, 0x00},
+};
+
+static struct reg_value ov5642_rot_horiz_flip_VGA[] = {
+ {0x3818, 0x81, 0x00, 0x01}, {0x3621, 0xa7, 0x00, 0x00},
+};
+
+static struct reg_value ov5642_rot_180_VGA[] = {
+ {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00},
+};
+
+
+static struct reg_value ov5642_rot_none_FULL[] = {
+ {0x3818, 0xc0, 0x00, 0x00}, {0x3621, 0x09, 0x00, 0x00},
+};
+
+static struct reg_value ov5642_rot_vert_flip_FULL[] = {
+ {0x3818, 0x20, 0xbf, 0x01}, {0x3621, 0x20, 0xff, 0x00},
+};
+
+static struct reg_value ov5642_rot_horiz_flip_FULL[] = {
+ {0x3818, 0x80, 0x00, 0x01}, {0x3621, 0x29, 0x00, 0x00},
+};
+
+static struct reg_value ov5642_rot_180_FULL[] = {
+ {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00},
+};
+
+
+static struct reg_value ov5642_initial_setting[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c00, 0x04, 0, 0}, {0x3c01, 0x80, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0},
+ {0x5182, 0x00, 0, 0}, {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0},
+ {0x5001, 0xff, 0, 0}, {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0},
+ {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0},
+ {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0},
+ {0x350b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0},
+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0},
+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+ {0x3801, 0x80, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0},
+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x0b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 300},
+};
+
+static struct reg_value ov5642_setting_15fps_QCIF_176_144[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+ {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
+ {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
+ {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
+ {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+ {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
+ {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_QCIF_176_144[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x10, 0, 0},
+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+ {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
+ {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
+ {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
+ {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+ {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
+ {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_QSXGA_2592_1944[] = {
+ {0x3503, 0x07, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0},
+ {0x3002, 0x00, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
+ {0x3005, 0xff, 0, 0}, {0x3006, 0xff, 0, 0}, {0x3007, 0x3f, 0, 0},
+ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3818, 0xc0, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+ {0x3602, 0xe4, 0, 0}, {0x3612, 0xac, 0, 0}, {0x3613, 0x44, 0, 0},
+ {0x3622, 0x60, 0, 0}, {0x3623, 0x22, 0, 0}, {0x3604, 0x48, 0, 0},
+ {0x3705, 0xda, 0, 0}, {0x370a, 0x80, 0, 0}, {0x3801, 0x95, 0, 0},
+ {0x3803, 0x0e, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x20, 0, 0},
+ {0x3806, 0x07, 0, 0}, {0x3807, 0x98, 0, 0}, {0x3808, 0x0a, 0, 0},
+ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
+ {0x380f, 0xd0, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3815, 0x44, 0, 0},
+ {0x3824, 0x11, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
+ {0x3a00, 0x78, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
+ {0x5682, 0x0a, 0, 0}, {0x5683, 0x20, 0, 0}, {0x5686, 0x07, 0, 0},
+ {0x5687, 0x98, 0, 0}, {0x5001, 0xff, 0, 0}, {0x589b, 0x00, 0, 0},
+ {0x589a, 0xc0, 0, 0}, {0x4407, 0x04, 0, 0}, {0x3008, 0x02, 0, 0},
+ {0x460b, 0x37, 0, 0}, {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x3815, 0x01, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0},
+ {0x5002, 0xe0, 0, 0}, {0x530a, 0x01, 0, 0}, {0x530d, 0x10, 0, 0},
+ {0x530c, 0x04, 0, 0}, {0x5312, 0x20, 0, 0}, {0x5282, 0x01, 0, 0},
+ {0x3010, 0x10, 0, 0}, {0x3012, 0x00, 0, 0},
+};
+
+
+static struct reg_value ov5642_setting_VGA_2_QVGA[] = {
+ {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
+ {0x380b, 0xf0, 0, 0}, {0x3815, 0x04, 0, 0},
+};
+
+static struct reg_value ov5642_setting_QSXGA_2_VGA[] = {
+ {0x3503, 0x00, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0},
+ {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
+ {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x3818, 0xc1, 0, 0}, {0x3621, 0x87, 0, 0},
+ {0x350c, 0x03, 0, 0}, {0x350d, 0xe8, 0, 0}, {0x3602, 0xfc, 0, 0},
+ {0x3612, 0xff, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3622, 0x60, 0, 0},
+ {0x3623, 0x01, 0, 0}, {0x3604, 0x48, 0, 0}, {0x3705, 0xdb, 0, 0},
+ {0x370a, 0x81, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0},
+ {0x3807, 0xc0, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x0c, 0, 0},
+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+ {0x3810, 0x40, 0, 0}, {0x3815, 0x04, 0, 0}, {0x3824, 0x11, 0, 0},
+ {0x3825, 0xb4, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x5682, 0x05, 0, 0},
+ {0x5683, 0x00, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0},
+ {0x5001, 0xff, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x4407, 0x0c, 0, 0}, {0x3008, 0x02, 0, 0}, {0x460b, 0x37, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4713, 0x02, 0, 0},
+ {0x471c, 0xd0, 0, 0}, {0x3815, 0x04, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x3002, 0x5c, 0, 0}, {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0},
+ {0x530a, 0x01, 0, 0}, {0x530d, 0x0c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x5312, 0x40, 0, 0}, {0x5282, 0x00, 0, 0},
+ {0x3012, 0x02, 0, 0}, {0x3010, 0x00, 0, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_VGA_640_480[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_VGA_640_480[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0},
+ {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+
+static struct reg_value ov5642_setting_30fps_XGA_1024_768[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+ {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_XGA_1024_768[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0},
+ {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+ {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_QVGA_320_240[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0},
+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3808, 0x01, 0, 0},
+ {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_NTSC_720_480[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0},
+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+ {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0},
+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0},
+ {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x302c, 0x60, 0x60, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_PAL_720_576[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0},
+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0},
+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0},
+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xd8, 0, 0},
+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0},
+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0},
+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0},
+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0},
+ {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0},
+ {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x5682, 0x04, 0, 0},
+ {0x5683, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0},
+ {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0},
+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0},
+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0},
+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0},
+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0},
+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0},
+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0},
+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0},
+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0},
+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0},
+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0},
+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0},
+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x302c, 0x60, 0x60, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_720P_1280_720[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
+ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
+ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
+ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
+ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
+ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
+ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
+ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
+ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
+ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
+ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
+ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
+ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
+ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
+ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
+ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
+ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
+ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
+ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0},
+ {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0},
+ {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0},
+ {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0},
+ {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0},
+ {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0},
+ {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0},
+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0},
+ {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0},
+ {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0},
+ {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0},
+ {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0},
+ {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, {0x3010, 0x30, 0, 0},
+ {0x3a08, 0x06, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x05, 0, 0},
+ {0x3a0b, 0x50, 0, 0}, {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x07, 0, 0},
+};
+
+static struct reg_value ov5642_setting_30fps_720P_1280_720[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
+ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
+ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
+ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
+ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
+ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
+ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
+ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
+ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
+ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
+ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
+ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
+ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
+ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
+ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
+ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
+ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
+ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
+ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0},
+ {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0},
+ {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0},
+ {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0},
+ {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0},
+ {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0},
+ {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0},
+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0},
+ {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0},
+ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0},
+ {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0},
+ {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0},
+ {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0},
+ {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_1080P_1920_1080[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0},
+ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0},
+ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0},
+ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0},
+ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0},
+ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0},
+ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0},
+ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0},
+ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0},
+ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0},
+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0},
+ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0},
+ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0},
+ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0},
+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0},
+ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0},
+ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0},
+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0},
+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0},
+ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0},
+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0},
+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0},
+ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0},
+ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0},
+ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0},
+ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0},
+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0},
+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0},
+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0},
+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0},
+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0},
+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0},
+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0},
+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0},
+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0},
+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0},
+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0},
+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0},
+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0},
+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0},
+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0},
+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0},
+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0},
+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0},
+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0},
+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0},
+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0},
+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0},
+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0},
+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0},
+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0},
+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0},
+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0},
+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0},
+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0},
+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0},
+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0},
+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0},
+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0},
+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0},
+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0},
+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0},
+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0},
+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0},
+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0},
+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0},
+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0},
+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0},
+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0},
+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0},
+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0},
+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0},
+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0},
+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0},
+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0},
+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0},
+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0},
+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0},
+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0},
+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0},
+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0},
+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0},
+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0},
+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0},
+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0},
+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0},
+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0},
+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0},
+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0},
+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0},
+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0},
+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0},
+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0},
+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0},
+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0},
+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0},
+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0},
+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0},
+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0},
+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0},
+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0},
+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0},
+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0},
+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0},
+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0},
+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0},
+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0},
+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0},
+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0},
+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0},
+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0},
+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0},
+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0},
+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0},
+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0},
+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0},
+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0},
+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0},
+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0},
+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0},
+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0},
+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0},
+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0},
+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0},
+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0},
+ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x07, 0, 0},
+ {0x350c, 0x04, 0, 0}, {0x350d, 0x58, 0, 0}, {0x3801, 0x8a, 0, 0},
+ {0x3803, 0x0a, 0, 0}, {0x3804, 0x07, 0, 0}, {0x3805, 0x80, 0, 0},
+ {0x3806, 0x04, 0, 0}, {0x3807, 0x39, 0, 0}, {0x3808, 0x07, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
+ {0x380c, 0x09, 0, 0}, {0x380d, 0xd6, 0, 0}, {0x380e, 0x04, 0, 0},
+ {0x380f, 0x58, 0, 0}, {0x381c, 0x11, 0, 0}, {0x381d, 0xba, 0, 0},
+ {0x381e, 0x04, 0, 0}, {0x381f, 0x48, 0, 0}, {0x3820, 0x04, 0, 0},
+ {0x3821, 0x18, 0, 0}, {0x3a08, 0x14, 0, 0}, {0x3a09, 0xe0, 0, 0},
+ {0x3a0a, 0x11, 0, 0}, {0x3a0b, 0x60, 0, 0}, {0x3a0d, 0x04, 0, 0},
+ {0x3a0e, 0x03, 0, 0}, {0x5682, 0x07, 0, 0}, {0x5683, 0x60, 0, 0},
+ {0x5686, 0x04, 0, 0}, {0x5687, 0x1c, 0, 0}, {0x5001, 0x7f, 0, 0},
+ {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, {0x460c, 0x20, 0, 0},
+ {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x471d, 0x05, 0, 0},
+ {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, {0x501f, 0x00, 0, 0},
+ {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0},
+ {0x5002, 0xe0, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_QVGA_320_240[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+ {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
+ {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
+ {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
+ {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+ {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
+ {0x380b, 0xf0, 0, 0}, {0x3a00, 0x78, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_NTSC_720_480[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+ {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
+ {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
+ {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
+ {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+ {0x3824, 0x11, 0, 0}, {0x3825, 0xb4, 0, 0}, {0x3826, 0x00, 0, 0},
+ {0x3827, 0x3d, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0xd0, 0, 0}, {0x380A, 0x01, 0, 0}, {0x380B, 0xe0, 0, 0},
+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0},
+ {0x3807, 0x55, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0x55, 0, 0},
+ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+};
+
+static struct reg_value ov5642_setting_15fps_PAL_720_576[] = {
+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0},
+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0},
+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0},
+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0},
+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0},
+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0},
+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0},
+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0},
+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0},
+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0},
+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0},
+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0},
+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0},
+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0},
+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0},
+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0},
+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0},
+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0},
+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0},
+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0},
+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0},
+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0},
+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0},
+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0},
+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0},
+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0},
+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0},
+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0},
+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0},
+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0},
+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0},
+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0},
+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0},
+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0},
+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0},
+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0},
+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0},
+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0},
+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0},
+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0},
+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0},
+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0},
+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0},
+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0},
+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0},
+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0},
+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0},
+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0},
+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0},
+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0},
+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0},
+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0},
+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0},
+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0},
+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0},
+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0},
+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0},
+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0},
+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0},
+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0},
+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0},
+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0},
+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0},
+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0},
+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0},
+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0},
+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0},
+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0},
+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0},
+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0},
+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0},
+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0},
+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0},
+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0},
+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0},
+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0},
+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0},
+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0},
+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0},
+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0},
+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0},
+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0},
+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0},
+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0},
+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0},
+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0},
+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0},
+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0},
+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0},
+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0},
+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0},
+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0},
+ {0x518f, 0x58, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0},
+ {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0},
+ {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0},
+ {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0},
+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0},
+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0},
+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0},
+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0},
+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0},
+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0},
+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0},
+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0},
+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0},
+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0},
+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0},
+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0},
+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0},
+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0},
+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0},
+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0},
+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0},
+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0},
+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0},
+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0},
+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0},
+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0},
+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0},
+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0},
+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0},
+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0},
+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0},
+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0},
+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0},
+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0},
+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0},
+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0},
+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0},
+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0},
+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0},
+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0},
+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0},
+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0},
+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0},
+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0},
+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0},
+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0},
+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0},
+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0},
+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0},
+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0},
+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0},
+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0},
+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0},
+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0},
+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0},
+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0},
+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0},
+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0},
+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0},
+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0},
+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0},
+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0},
+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0},
+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0},
+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0},
+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0},
+ {0x3824, 0x11, 0, 0}, {0x3825, 0xdc, 0, 0}, {0x3826, 0x00, 0, 0},
+ {0x3827, 0x08, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0},
+ {0x3809, 0xd0, 0, 0}, {0x380A, 0x02, 0, 0}, {0x380B, 0x40, 0, 0},
+ {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0},
+ {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xc0, 0, 0},
+ {0x5682, 0x04, 0, 0}, {0x5683, 0xb0, 0, 0},
+};
+
+static struct ov5642_mode_info ov5642_mode_info_data[2][ov5642_mode_MAX + 1] = {
+ {
+ {ov5642_mode_VGA_640_480, 640, 480,
+ ov5642_setting_15fps_VGA_640_480,
+ ARRAY_SIZE(ov5642_setting_15fps_VGA_640_480)},
+ {ov5642_mode_QVGA_320_240, 320, 240,
+ ov5642_setting_15fps_QVGA_320_240,
+ ARRAY_SIZE(ov5642_setting_15fps_QVGA_320_240)},
+ {ov5642_mode_NTSC_720_480, 720, 480,
+ ov5642_setting_15fps_NTSC_720_480,
+ ARRAY_SIZE(ov5642_setting_15fps_NTSC_720_480)},
+ {ov5642_mode_PAL_720_576, 720, 576,
+ ov5642_setting_15fps_PAL_720_576,
+ ARRAY_SIZE(ov5642_setting_15fps_PAL_720_576)},
+ {ov5642_mode_720P_1280_720, 1280, 720,
+ ov5642_setting_15fps_720P_1280_720,
+ ARRAY_SIZE(ov5642_setting_15fps_720P_1280_720)},
+ {ov5642_mode_1080P_1920_1080, 1920, 1080,
+ ov5642_setting_15fps_1080P_1920_1080,
+ ARRAY_SIZE(ov5642_setting_15fps_1080P_1920_1080)},
+ {ov5642_mode_QSXGA_2592_1944, 2592, 1944,
+ ov5642_setting_15fps_QSXGA_2592_1944,
+ ARRAY_SIZE(ov5642_setting_15fps_QSXGA_2592_1944)},
+ {ov5642_mode_QCIF_176_144, 176, 144,
+ ov5642_setting_15fps_QCIF_176_144,
+ ARRAY_SIZE(ov5642_setting_15fps_QCIF_176_144)},
+ {ov5642_mode_XGA_1024_768, 1024, 768,
+ ov5642_setting_15fps_XGA_1024_768,
+ ARRAY_SIZE(ov5642_setting_15fps_XGA_1024_768)},
+ },
+ {
+ {ov5642_mode_VGA_640_480, 640, 480,
+ ov5642_setting_30fps_VGA_640_480,
+ ARRAY_SIZE(ov5642_setting_30fps_VGA_640_480)},
+ {ov5642_mode_QVGA_320_240, 320, 240,
+ ov5642_setting_30fps_QVGA_320_240,
+ ARRAY_SIZE(ov5642_setting_30fps_QVGA_320_240)},
+ {ov5642_mode_NTSC_720_480, 720, 480,
+ ov5642_setting_30fps_NTSC_720_480,
+ ARRAY_SIZE(ov5642_setting_30fps_NTSC_720_480)},
+ {ov5642_mode_PAL_720_576, 720, 576,
+ ov5642_setting_30fps_PAL_720_576,
+ ARRAY_SIZE(ov5642_setting_30fps_PAL_720_576)},
+ {ov5642_mode_720P_1280_720, 1280, 720,
+ ov5642_setting_30fps_720P_1280_720,
+ ARRAY_SIZE(ov5642_setting_30fps_720P_1280_720)},
+ {ov5642_mode_1080P_1920_1080, 0, 0, NULL, 0},
+ {ov5642_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
+ {ov5642_mode_QCIF_176_144, 176, 144,
+ ov5642_setting_30fps_QCIF_176_144,
+ ARRAY_SIZE(ov5642_setting_30fps_QCIF_176_144)},
+ {ov5642_mode_XGA_1024_768, 1024, 768,
+ ov5642_setting_30fps_XGA_1024_768,
+ ARRAY_SIZE(ov5642_setting_30fps_XGA_1024_768)},
+ },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+static struct regulator *gpo_regulator;
+
+static int ov5642_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *device_id);
+static int ov5642_remove(struct i2c_client *client);
+
+static s32 ov5642_read_reg(u16 reg, u8 *val);
+static s32 ov5642_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5642_id[] = {
+ {"ov5642", 0},
+ {"ov564x", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5642_id);
+
+static struct i2c_driver ov5642_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ov5642",
+ },
+ .probe = ov5642_probe,
+ .remove = ov5642_remove,
+ .id_table = ov5642_id,
+};
+
+static void ov5642_standby(s32 enable)
+{
+ if (enable)
+ gpio_set_value(pwn_gpio, 1);
+ else
+ gpio_set_value(pwn_gpio, 0);
+
+ msleep(2);
+}
+
+static void ov5642_reset(void)
+{
+ /* camera reset */
+ gpio_set_value(rst_gpio, 1);
+
+ /* camera power down */
+ gpio_set_value(pwn_gpio, 1);
+ msleep(5);
+
+ gpio_set_value(pwn_gpio, 0);
+ msleep(5);
+
+ gpio_set_value(rst_gpio, 0);
+ msleep(1);
+
+ gpio_set_value(rst_gpio, 1);
+ msleep(5);
+
+ gpio_set_value(pwn_gpio, 1);
+}
+
+static int ov5642_power_on(struct device *dev)
+{
+ int ret = 0;
+
+ io_regulator = devm_regulator_get(dev, "DOVDD");
+ if (!IS_ERR(io_regulator)) {
+ regulator_set_voltage(io_regulator,
+ OV5642_VOLTAGE_DIGITAL_IO,
+ OV5642_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(io_regulator);
+ if (ret) {
+ pr_err("%s:io set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:io set voltage ok\n", __func__);
+ }
+ } else {
+ pr_err("%s: cannot get io voltage error\n", __func__);
+ io_regulator = NULL;
+ }
+
+ core_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(core_regulator)) {
+ regulator_set_voltage(core_regulator,
+ OV5642_VOLTAGE_DIGITAL_CORE,
+ OV5642_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(core_regulator);
+ if (ret) {
+ pr_err("%s:core set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:core set voltage ok\n", __func__);
+ }
+ } else {
+ core_regulator = NULL;
+ pr_err("%s: cannot get core voltage error\n", __func__);
+ }
+
+ analog_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(analog_regulator)) {
+ regulator_set_voltage(analog_regulator,
+ OV5642_VOLTAGE_ANALOG,
+ OV5642_VOLTAGE_ANALOG);
+ ret = regulator_enable(analog_regulator);
+ if (ret) {
+ pr_err("%s:analog set voltage error\n",
+ __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:analog set voltage ok\n", __func__);
+ }
+ } else {
+ analog_regulator = NULL;
+ pr_err("%s: cannot get analog voltage error\n", __func__);
+ }
+
+ return ret;
+}
+
+static s32 ov5642_write_reg(u16 reg, u8 val)
+{
+ u8 au8Buf[3] = {0};
+
+ au8Buf[0] = reg >> 8;
+ au8Buf[1] = reg & 0xff;
+ au8Buf[2] = val;
+
+ if (i2c_master_send(ov5642_data.i2c_client, au8Buf, 3) < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x\n",
+ __func__, reg, val);
+ return -1;
+ }
+
+ return 0;
+}
+
+static s32 ov5642_read_reg(u16 reg, u8 *val)
+{
+ u8 au8RegBuf[2] = {0};
+ u8 u8RdVal = 0;
+
+ au8RegBuf[0] = reg >> 8;
+ au8RegBuf[1] = reg & 0xff;
+
+ if (2 != i2c_master_send(ov5642_data.i2c_client, au8RegBuf, 2)) {
+ pr_err("%s:write reg error:reg=%x\n",
+ __func__, reg);
+ return -1;
+ }
+
+ if (1 != i2c_master_recv(ov5642_data.i2c_client, &u8RdVal, 1)) {
+ pr_err("%s:read reg error:reg=%x,val=%x\n",
+ __func__, reg, u8RdVal);
+ return -1;
+ }
+
+ *val = u8RdVal;
+
+ return u8RdVal;
+}
+
+static int ov5642_set_rot_mode(struct reg_value *rot_mode)
+{
+ s32 i = 0;
+ s32 iModeSettingArySize = 2;
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int retval = 0;
+ for (i = 0; i < iModeSettingArySize; ++i, ++rot_mode) {
+ Delay_ms = rot_mode->u32Delay_ms;
+ RegAddr = rot_mode->u16RegAddr;
+ Val = rot_mode->u8Val;
+ Mask = rot_mode->u8Mask;
+
+ if (Mask) {
+ retval = ov5642_read_reg(RegAddr, &RegVal);
+ if (retval < 0) {
+ pr_err("%s, read reg 0x%x failed\n",
+ __func__, RegAddr);
+ goto err;
+ }
+
+ Val |= RegVal;
+ Val &= Mask;
+ }
+
+ retval = ov5642_write_reg(RegAddr, Val);
+ if (retval < 0) {
+ pr_err("%s, write reg 0x%x failed\n",
+ __func__, RegAddr);
+ goto err;
+ }
+
+ if (Delay_ms)
+ mdelay(Delay_ms);
+ }
+err:
+ return retval;
+}
+static int ov5642_init_mode(enum ov5642_frame_rate frame_rate,
+ enum ov5642_mode mode);
+static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate,
+ enum ov5642_mode mode);
+static int ov5642_change_mode(enum ov5642_frame_rate new_frame_rate,
+ enum ov5642_frame_rate old_frame_rate,
+ enum ov5642_mode new_mode,
+ enum ov5642_mode orig_mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 i = 0;
+ s32 iModeSettingArySize = 0;
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int retval = 0;
+
+ if (new_mode > ov5642_mode_MAX || new_mode < ov5642_mode_MIN) {
+ pr_err("Wrong ov5642 mode detected!\n");
+ return -1;
+ }
+
+ if ((new_frame_rate == old_frame_rate) &&
+ (new_mode == ov5642_mode_VGA_640_480) &&
+ (orig_mode == ov5642_mode_QSXGA_2592_1944)) {
+ pModeSetting = ov5642_setting_QSXGA_2_VGA;
+ iModeSettingArySize = ARRAY_SIZE(ov5642_setting_QSXGA_2_VGA);
+ ov5642_data.pix.width = 640;
+ ov5642_data.pix.height = 480;
+ } else if ((new_frame_rate == old_frame_rate) &&
+ (new_mode == ov5642_mode_QVGA_320_240) &&
+ (orig_mode == ov5642_mode_VGA_640_480)) {
+ pModeSetting = ov5642_setting_VGA_2_QVGA;
+ iModeSettingArySize = ARRAY_SIZE(ov5642_setting_VGA_2_QVGA);
+ ov5642_data.pix.width = 320;
+ ov5642_data.pix.height = 240;
+ } else {
+ retval = ov5642_write_snapshot_para(new_frame_rate, new_mode);
+ goto err;
+ }
+
+ if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 ||
+ pModeSetting == NULL || iModeSettingArySize == 0)
+ return -EINVAL;
+
+ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
+ Delay_ms = pModeSetting->u32Delay_ms;
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u8Val;
+ Mask = pModeSetting->u8Mask;
+
+ if (Mask) {
+ retval = ov5642_read_reg(RegAddr, &RegVal);
+ if (retval < 0) {
+ pr_err("read reg error addr=0x%x", RegAddr);
+ goto err;
+ }
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = ov5642_write_reg(RegAddr, Val);
+ if (retval < 0) {
+ pr_err("write reg error addr=0x%x", RegAddr);
+ goto err;
+ }
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+ }
+err:
+ return retval;
+}
+static int ov5642_init_mode(enum ov5642_frame_rate frame_rate,
+ enum ov5642_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 i = 0;
+ s32 iModeSettingArySize = 0;
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int retval = 0;
+
+ if (mode > ov5642_mode_MAX || mode < ov5642_mode_MIN) {
+ pr_err("Wrong ov5642 mode detected!\n");
+ return -1;
+ }
+
+ pModeSetting = ov5642_mode_info_data[frame_rate][mode].init_data_ptr;
+ iModeSettingArySize =
+ ov5642_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5642_data.pix.width = ov5642_mode_info_data[frame_rate][mode].width;
+ ov5642_data.pix.height = ov5642_mode_info_data[frame_rate][mode].height;
+
+ if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 ||
+ pModeSetting == NULL || iModeSettingArySize == 0)
+ return -EINVAL;
+
+ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
+ Delay_ms = pModeSetting->u32Delay_ms;
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u8Val;
+ Mask = pModeSetting->u8Mask;
+
+ if (Mask) {
+ retval = ov5642_read_reg(RegAddr, &RegVal);
+ if (retval < 0) {
+ pr_err("read reg error addr=0x%x", RegAddr);
+ goto err;
+ }
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = ov5642_write_reg(RegAddr, Val);
+ if (retval < 0) {
+ pr_err("write reg error addr=0x%x", RegAddr);
+ goto err;
+ }
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+ }
+err:
+ return retval;
+}
+
+static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate,
+ enum ov5642_mode mode)
+{
+ int ret = 0;
+ bool m_60Hz = false;
+ u16 cap_frame_rate = 50;
+ u16 g_prev_frame_rate = 225;
+
+ u8 ev_low, ev_mid, ev_high;
+ u8 ret_l, ret_m, ret_h, gain, lines_10ms;
+ u16 ulcap_ev, icap_gain, prev_maxlines;
+ u32 ulcap_ev_gain, cap_maxlines, g_prev_ev;
+
+ ov5642_write_reg(0x3503, 0x07);
+
+ ret_h = ret_m = ret_l = 0;
+ g_prev_ev = 0;
+ ov5642_read_reg(0x3500, &ret_h);
+ ov5642_read_reg(0x3501, &ret_m);
+ ov5642_read_reg(0x3502, &ret_l);
+ g_prev_ev = (ret_h << 12) + (ret_m << 4) + (ret_l >> 4);
+
+ ret_h = ret_m = ret_l = 0;
+ prev_maxlines = 0;
+ ov5642_read_reg(0x380e, &ret_h);
+ ov5642_read_reg(0x380f, &ret_l);
+ prev_maxlines = (ret_h << 8) + ret_l;
+ /*Read back AGC Gain for preview*/
+ gain = 0;
+ ov5642_read_reg(0x350b, &gain);
+
+ ret = ov5642_init_mode(frame_rate, mode);
+ if (ret < 0)
+ return ret;
+
+ ret_h = ret_m = ret_l = 0;
+ ov5642_read_reg(0x380e, &ret_h);
+ ov5642_read_reg(0x380f, &ret_l);
+ cap_maxlines = (ret_h << 8) + ret_l;
+ if (m_60Hz == true)
+ lines_10ms = cap_frame_rate * cap_maxlines/12000;
+ else
+ lines_10ms = cap_frame_rate * cap_maxlines/10000;
+
+ if (prev_maxlines == 0)
+ prev_maxlines = 1;
+
+ ulcap_ev = (g_prev_ev*(cap_frame_rate)*(cap_maxlines))/
+ (((prev_maxlines)*(g_prev_frame_rate)));
+ icap_gain = (gain & 0x0f) + 16;
+ if (gain & 0x10)
+ icap_gain = icap_gain << 1;
+
+ if (gain & 0x20)
+ icap_gain = icap_gain << 1;
+
+ if (gain & 0x40)
+ icap_gain = icap_gain << 1;
+
+ if (gain & 0x80)
+ icap_gain = icap_gain << 1;
+
+ ulcap_ev_gain = 2 * ulcap_ev * icap_gain;
+
+ if (ulcap_ev_gain < cap_maxlines*16) {
+ ulcap_ev = ulcap_ev_gain/16;
+ if (ulcap_ev > lines_10ms) {
+ ulcap_ev /= lines_10ms;
+ ulcap_ev *= lines_10ms;
+ }
+ } else
+ ulcap_ev = cap_maxlines;
+
+ if (ulcap_ev == 0)
+ ulcap_ev = 1;
+
+ icap_gain = (ulcap_ev_gain*2/ulcap_ev + 1)/2;
+ ev_low = ((unsigned char)ulcap_ev)<<4;
+ ev_mid = (unsigned char)(ulcap_ev >> 4) & 0xff;
+ ev_high = (unsigned char)(ulcap_ev >> 12);
+
+ gain = 0;
+ if (icap_gain > 31) {
+ gain |= 0x10;
+ icap_gain = icap_gain >> 1;
+ }
+ if (icap_gain > 31) {
+ gain |= 0x20;
+ icap_gain = icap_gain >> 1;
+ }
+ if (icap_gain > 31) {
+ gain |= 0x40;
+ icap_gain = icap_gain >> 1;
+ }
+ if (icap_gain > 31) {
+ gain |= 0x80;
+ icap_gain = icap_gain >> 1;
+ }
+ if (icap_gain > 16)
+ gain |= ((icap_gain - 16) & 0x0f);
+
+ if (gain == 0x10)
+ gain = 0x11;
+
+ ov5642_write_reg(0x350b, gain);
+ ov5642_write_reg(0x3502, ev_low);
+ ov5642_write_reg(0x3501, ev_mid);
+ ov5642_write_reg(0x3500, ev_high);
+ msleep(500);
+
+ return ret ;
+}
+
+
+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ if (s == NULL) {
+ pr_err(" ERROR!! no slave device set!\n");
+ return -1;
+ }
+
+ memset(p, 0, sizeof(*p));
+ p->u.bt656.clock_curr = ov5642_data.mclk;
+ pr_debug(" clock_curr=mclk=%d\n", ov5642_data.mclk);
+ p->if_type = V4L2_IF_TYPE_BT656;
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.clock_min = OV5642_XCLK_MIN;
+ p->u.bt656.clock_max = OV5642_XCLK_MAX;
+ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
+
+ return 0;
+}
+
+/*!
+ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ struct sensor_data *sensor = s->priv;
+
+ if (on && !sensor->on) {
+ if (io_regulator)
+ if (regulator_enable(io_regulator) != 0)
+ return -EIO;
+ if (core_regulator)
+ if (regulator_enable(core_regulator) != 0)
+ return -EIO;
+ if (gpo_regulator)
+ if (regulator_enable(gpo_regulator) != 0)
+ return -EIO;
+ if (analog_regulator)
+ if (regulator_enable(analog_regulator) != 0)
+ return -EIO;
+ /* Make sure power on */
+ ov5642_standby(0);
+ } else if (!on && sensor->on) {
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+ if (core_regulator)
+ regulator_disable(core_regulator);
+ if (io_regulator)
+ regulator_disable(io_regulator);
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+
+ ov5642_standby(1);
+ }
+
+ sensor->on = on;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor_data *sensor = s->priv;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ int ret = 0;
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->streamcap.capability;
+ cparm->timeperframe = sensor->streamcap.timeperframe;
+ cparm->capturemode = sensor->streamcap.capturemode;
+ ret = 0;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor_data *sensor = s->priv;
+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+ u32 tgt_fps, old_fps; /* target frames per secound */
+ enum ov5642_frame_rate new_frame_rate, old_frame_rate;
+ int ret = 0;
+
+ /* Make sure power on */
+ ov5642_standby(0);
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ /* Check that the new frame rate is allowed. */
+ if ((timeperframe->numerator == 0) ||
+ (timeperframe->denominator == 0)) {
+ timeperframe->denominator = DEFAULT_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps > MAX_FPS) {
+ timeperframe->denominator = MAX_FPS;
+ timeperframe->numerator = 1;
+ } else if (tgt_fps < MIN_FPS) {
+ timeperframe->denominator = MIN_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ /* Actual frame rate we use */
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps == 15)
+ new_frame_rate = ov5642_15_fps;
+ else if (tgt_fps == 30)
+ new_frame_rate = ov5642_30_fps;
+ else {
+ pr_err(" The camera frame rate is not supported!\n");
+ return -EINVAL;
+ }
+
+ if (sensor->streamcap.timeperframe.numerator != 0)
+ old_fps = sensor->streamcap.timeperframe.denominator /
+ sensor->streamcap.timeperframe.numerator;
+ else
+ old_fps = 30;
+
+ if (old_fps == 15)
+ old_frame_rate = ov5642_15_fps;
+ else if (old_fps == 30)
+ old_frame_rate = ov5642_30_fps;
+ else {
+ pr_warning(" No valid frame rate set!\n");
+ old_frame_rate = ov5642_30_fps;
+ }
+
+ ret = ov5642_change_mode(new_frame_rate, old_frame_rate,
+ a->parm.capture.capturemode,
+ sensor->streamcap.capturemode);
+ if (ret < 0)
+ return ret;
+
+ sensor->streamcap.timeperframe = *timeperframe;
+ sensor->streamcap.capturemode =
+ (u32)a->parm.capture.capturemode;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_debug(" type is not " \
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+ a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+ struct sensor_data *sensor = s->priv;
+
+ f->fmt.pix = sensor->pix;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array. Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int ret = 0;
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ vc->value = ov5642_data.brightness;
+ break;
+ case V4L2_CID_HUE:
+ vc->value = ov5642_data.hue;
+ break;
+ case V4L2_CID_CONTRAST:
+ vc->value = ov5642_data.contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ vc->value = ov5642_data.saturation;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ vc->value = ov5642_data.red;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ vc->value = ov5642_data.blue;
+ break;
+ case V4L2_CID_EXPOSURE:
+ vc->value = ov5642_data.ae_mode;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array). Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int retval = 0;
+ struct sensor_data *sensor = s->priv;
+ __u32 captureMode = sensor->streamcap.capturemode;
+ struct reg_value *rot_mode = NULL;
+
+ pr_debug("In ov5642:ioctl_s_ctrl %d\n",
+ vc->id);
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ break;
+ case V4L2_CID_CONTRAST:
+ break;
+ case V4L2_CID_SATURATION:
+ break;
+ case V4L2_CID_HUE:
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ break;
+ case V4L2_CID_RED_BALANCE:
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ break;
+ case V4L2_CID_GAMMA:
+ break;
+ case V4L2_CID_EXPOSURE:
+ break;
+ case V4L2_CID_AUTOGAIN:
+ break;
+ case V4L2_CID_GAIN:
+ break;
+ case V4L2_CID_HFLIP:
+ break;
+ case V4L2_CID_VFLIP:
+ break;
+ case V4L2_CID_MXC_ROT:
+ case V4L2_CID_MXC_VF_ROT:
+ switch (vc->value) {
+ case V4L2_MXC_ROTATE_NONE:
+ if (captureMode == ov5642_mode_QSXGA_2592_1944)
+ rot_mode = ov5642_rot_none_FULL;
+ else
+ rot_mode = ov5642_rot_none_VGA;
+
+ if (ov5642_set_rot_mode(rot_mode))
+ retval = -EPERM;
+ break;
+ case V4L2_MXC_ROTATE_VERT_FLIP:
+ if (captureMode == ov5642_mode_QSXGA_2592_1944)
+ rot_mode = ov5642_rot_vert_flip_FULL;
+ else
+ rot_mode = ov5642_rot_vert_flip_VGA ;
+
+ if (ov5642_set_rot_mode(rot_mode))
+ retval = -EPERM;
+ break;
+ case V4L2_MXC_ROTATE_HORIZ_FLIP:
+ if (captureMode == ov5642_mode_QSXGA_2592_1944)
+ rot_mode = ov5642_rot_horiz_flip_FULL;
+ else
+ rot_mode = ov5642_rot_horiz_flip_VGA;
+
+ if (ov5642_set_rot_mode(rot_mode))
+ retval = -EPERM;
+ break;
+ case V4L2_MXC_ROTATE_180:
+ if (captureMode == ov5642_mode_QSXGA_2592_1944)
+ rot_mode = ov5642_rot_180_FULL;
+ else
+ rot_mode = ov5642_rot_180_VGA;
+
+ if (ov5642_set_rot_mode(rot_mode))
+ retval = -EPERM;
+ break;
+ default:
+ retval = -EPERM;
+ break;
+ }
+ break;
+ default:
+ retval = -EPERM;
+ break;
+ }
+
+ return retval;
+}
+
+/*!
+ * ioctl_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_framesizes(struct v4l2_int_device *s,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index > ov5642_mode_MAX)
+ return -EINVAL;
+
+ fsize->pixel_format = ov5642_data.pix.pixelformat;
+ fsize->discrete.width =
+ max(ov5642_mode_info_data[0][fsize->index].width,
+ ov5642_mode_info_data[1][fsize->index].width);
+ fsize->discrete.height =
+ max(ov5642_mode_info_data[0][fsize->index].height,
+ ov5642_mode_info_data[1][fsize->index].height);
+ return 0;
+}
+
+/*!
+ * ioctl_enum_frameintervals - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
+ struct v4l2_frmivalenum *fival)
+{
+ int i, j, count;
+
+ if (fival->index < 0 || fival->index > ov5642_mode_MAX)
+ return -EINVAL;
+
+ if (fival->pixel_format == 0 || fival->width == 0 ||
+ fival->height == 0) {
+ pr_warning("Please assign pixelformat, width and height.\n");
+ return -EINVAL;
+ }
+
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1;
+
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(ov5642_mode_info_data); i++) {
+ for (j = 0; j < (ov5642_mode_MAX + 1); j++) {
+ if (fival->pixel_format == ov5642_data.pix.pixelformat
+ && fival->width == ov5642_mode_info_data[i][j].width
+ && fival->height == ov5642_mode_info_data[i][j].height
+ && ov5642_mode_info_data[i][j].init_data_ptr != NULL) {
+ count++;
+ }
+ if (fival->index == (count - 1)) {
+ fival->discrete.denominator =
+ ov5642_framerates[i];
+ return 0;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ * VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+ ((struct v4l2_dbg_chip_ident *)id)->match.type =
+ V4L2_CHIP_MATCH_I2C_DRIVER;
+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5642_camera");
+
+ return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+
+ return 0;
+}
+
+/*!
+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
+ * @s: pointer to standard V4L2 device structure
+ * @fmt: pointer to standard V4L2 fmt description structure
+ *
+ * Return 0.
+ */
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_fmtdesc *fmt)
+{
+ if (fmt->index > 0) /* only 1 pixelformat support so far */
+ return -EINVAL;
+
+ fmt->pixelformat = ov5642_data.pix.pixelformat;
+
+ return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 i = 0;
+ s32 iModeSettingArySize = 0;
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int retval = 0;
+
+ struct sensor_data *sensor = s->priv;
+ u32 tgt_xclk; /* target xclk */
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5642_frame_rate frame_rate;
+
+ ov5642_data.on = true;
+
+ /* mclk */
+ tgt_xclk = ov5642_data.mclk;
+ tgt_xclk = min(tgt_xclk, (u32)OV5642_XCLK_MAX);
+ tgt_xclk = max(tgt_xclk, (u32)OV5642_XCLK_MIN);
+ ov5642_data.mclk = tgt_xclk;
+
+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+
+ /* Default camera frame rate is set in probe */
+ tgt_fps = sensor->streamcap.timeperframe.denominator /
+ sensor->streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5642_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5642_30_fps;
+ else
+ return -EINVAL; /* Only support 15fps or 30fps now. */
+
+ pModeSetting = ov5642_initial_setting;
+ iModeSettingArySize = ARRAY_SIZE(ov5642_initial_setting);
+
+ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
+ Delay_ms = pModeSetting->u32Delay_ms;
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u8Val;
+ Mask = pModeSetting->u8Mask;
+ if (Mask) {
+ retval = ov5642_read_reg(RegAddr, &RegVal);
+ if (retval < 0)
+ goto err;
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = ov5642_write_reg(RegAddr, Val);
+ if (retval < 0)
+ goto err;
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+ }
+err:
+ return retval;
+}
+
+/*!
+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Delinitialise the device when slave detaches to the master.
+ */
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+ return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module and links them to the
+ * enumeration.
+ */
+static struct v4l2_int_ioctl_desc ov5642_ioctl_desc[] = {
+ { vidioc_int_dev_init_num,
+ (v4l2_int_ioctl_func *)ioctl_dev_init },
+ { vidioc_int_dev_exit_num, ioctl_dev_exit},
+ { vidioc_int_s_power_num,
+ (v4l2_int_ioctl_func *)ioctl_s_power },
+ { vidioc_int_g_ifparm_num,
+ (v4l2_int_ioctl_func *)ioctl_g_ifparm },
+/* { vidioc_int_g_needs_reset_num,
+ (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, */
+/* { vidioc_int_reset_num,
+ (v4l2_int_ioctl_func *)ioctl_reset }, */
+ { vidioc_int_init_num,
+ (v4l2_int_ioctl_func *)ioctl_init },
+ { vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
+/* { vidioc_int_try_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, */
+ { vidioc_int_g_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
+/* { vidioc_int_s_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, */
+ { vidioc_int_g_parm_num,
+ (v4l2_int_ioctl_func *)ioctl_g_parm },
+ { vidioc_int_s_parm_num,
+ (v4l2_int_ioctl_func *)ioctl_s_parm },
+/* { vidioc_int_queryctrl_num,
+ (v4l2_int_ioctl_func *)ioctl_queryctrl }, */
+ { vidioc_int_g_ctrl_num,
+ (v4l2_int_ioctl_func *)ioctl_g_ctrl },
+ { vidioc_int_s_ctrl_num,
+ (v4l2_int_ioctl_func *)ioctl_s_ctrl },
+ { vidioc_int_enum_framesizes_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
+ { vidioc_int_enum_frameintervals_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
+ { vidioc_int_g_chip_ident_num,
+ (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
+};
+
+static struct v4l2_int_slave ov5642_slave = {
+ .ioctls = ov5642_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(ov5642_ioctl_desc),
+};
+
+static struct v4l2_int_device ov5642_int_device = {
+ .module = THIS_MODULE,
+ .name = "ov5642",
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &ov5642_slave,
+ },
+};
+
+/*!
+ * ov5642 I2C probe function
+ *
+ * @param adapter struct i2c_adapter *
+ * @return Error code indicating success or failure
+ */
+static int ov5642_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+ int retval;
+ u8 chip_id_high, chip_id_low;
+
+ /* ov5642 pinctrl */
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(dev, "ov5642 setup pinctrl failed!");
+ return PTR_ERR(pinctrl);
+ }
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio)) {
+ dev_warn(dev, "no sensor pwdn pin available");
+ return -EINVAL;
+ }
+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5642_pwdn");
+ if (retval < 0)
+ return retval;
+
+ /* request reset pin */
+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(rst_gpio)) {
+ dev_warn(dev, "no sensor reset pin available");
+ return -EINVAL;
+ }
+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5642_reset");
+ if (retval < 0)
+ return retval;
+
+ /* Set initial values for the sensor struct. */
+ memset(&ov5642_data, 0, sizeof(ov5642_data));
+ ov5642_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(ov5642_data.sensor_clk)) {
+ /* assuming clock enabled by default */
+ ov5642_data.sensor_clk = NULL;
+ dev_err(dev, "clock-frequency missing or invalid\n");
+ return PTR_ERR(ov5642_data.sensor_clk);
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk",
+ (u32 *) &(ov5642_data.mclk));
+ if (retval) {
+ dev_err(dev, "mclk missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk_source",
+ (u32 *) &(ov5642_data.mclk_source));
+ if (retval) {
+ dev_err(dev, "mclk_source missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "csi_id",
+ &(ov5642_data.csi));
+ if (retval) {
+ dev_err(dev, "csi_id missing or invalid\n");
+ return retval;
+ }
+
+ clk_prepare_enable(ov5642_data.sensor_clk);
+
+ ov5642_data.io_init = ov5642_reset;
+ ov5642_data.i2c_client = client;
+ ov5642_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ ov5642_data.pix.width = 640;
+ ov5642_data.pix.height = 480;
+ ov5642_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+ V4L2_CAP_TIMEPERFRAME;
+ ov5642_data.streamcap.capturemode = 0;
+ ov5642_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+ ov5642_data.streamcap.timeperframe.numerator = 1;
+
+ ov5642_power_on(&client->dev);
+
+ ov5642_reset();
+
+ ov5642_standby(0);
+
+ retval = ov5642_read_reg(OV5642_CHIP_ID_HIGH_BYTE, &chip_id_high);
+ if (retval < 0 || chip_id_high != 0x56) {
+ pr_warning("camera ov5642 is not found\n");
+ clk_disable_unprepare(ov5642_data.sensor_clk);
+ return -ENODEV;
+ }
+ retval = ov5642_read_reg(OV5642_CHIP_ID_LOW_BYTE, &chip_id_low);
+ if (retval < 0 || chip_id_low != 0x42) {
+ pr_warning("camera ov5642 is not found\n");
+ clk_disable_unprepare(ov5642_data.sensor_clk);
+ return -ENODEV;
+ }
+
+ ov5642_standby(1);
+
+ ov5642_int_device.priv = &ov5642_data;
+ retval = v4l2_int_device_register(&ov5642_int_device);
+
+ clk_disable_unprepare(ov5642_data.sensor_clk);
+
+ pr_info("camera ov5642 is found\n");
+ return retval;
+}
+
+/*!
+ * ov5642 I2C detach function
+ *
+ * @param client struct i2c_client *
+ * @return Error code indicating success or failure
+ */
+static int ov5642_remove(struct i2c_client *client)
+{
+ v4l2_int_device_unregister(&ov5642_int_device);
+
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+
+ if (core_regulator)
+ regulator_disable(core_regulator);
+
+ if (io_regulator)
+ regulator_disable(io_regulator);
+
+ return 0;
+}
+
+/*!
+ * ov5642 init function
+ * Called by insmod ov5642_camera.ko.
+ *
+ * @return Error code indicating success or failure
+ */
+static __init int ov5642_init(void)
+{
+ u8 err;
+
+ err = i2c_add_driver(&ov5642_i2c_driver);
+ if (err != 0)
+ pr_err("%s:driver registration failed, error=%d\n",
+ __func__, err);
+
+ return err;
+}
+
+/*!
+ * OV5642 cleanup function
+ * Called on rmmod ov5642_camera.ko
+ *
+ * @return Error code indicating success or failure
+ */
+static void __exit ov5642_clean(void)
+{
+ i2c_del_driver(&ov5642_i2c_driver);
+}
+
+module_init(ov5642_init);
+module_exit(ov5642_clean);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5642 Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/capture/v4l2-int-device.c b/drivers/media/platform/mxc/capture/v4l2-int-device.c
new file mode 100644
index 000000000000..e49da150f887
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/v4l2-int-device.c
@@ -0,0 +1,165 @@
+/*
+ * drivers/media/video/v4l2-int-device.c
+ *
+ * V4L2 internal ioctl interface.
+ *
+ * Copyright 2005-2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/sort.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+#include "v4l2-int-device.h"
+
+static DEFINE_MUTEX(mutex);
+static LIST_HEAD(int_list);
+
+void v4l2_int_device_try_attach_all(void)
+{
+ struct v4l2_int_device *m, *s;
+
+ list_for_each_entry(m, &int_list, head) {
+ if (m->type != v4l2_int_type_master)
+ continue;
+
+ list_for_each_entry(s, &int_list, head) {
+ if (s->type != v4l2_int_type_slave)
+ continue;
+
+ /* Slave is connected? */
+ if (s->u.slave->master)
+ continue;
+
+ /* Slave wants to attach to master? */
+ if (s->u.slave->attach_to[0] != 0
+ && strncmp(m->name, s->u.slave->attach_to,
+ V4L2NAMESIZE))
+ continue;
+
+ if (!try_module_get(m->module))
+ continue;
+
+ s->u.slave->master = m;
+ if (m->u.master->attach(s)) {
+ s->u.slave->master = NULL;
+ module_put(m->module);
+ continue;
+ }
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(v4l2_int_device_try_attach_all);
+
+static int ioctl_sort_cmp(const void *a, const void *b)
+{
+ const struct v4l2_int_ioctl_desc *d1 = a, *d2 = b;
+
+ if (d1->num > d2->num)
+ return 1;
+
+ if (d1->num < d2->num)
+ return -1;
+
+ return 0;
+}
+
+int v4l2_int_device_register(struct v4l2_int_device *d)
+{
+ if (d->type == v4l2_int_type_slave)
+ sort(d->u.slave->ioctls, d->u.slave->num_ioctls,
+ sizeof(struct v4l2_int_ioctl_desc),
+ &ioctl_sort_cmp, NULL);
+ mutex_lock(&mutex);
+ list_add(&d->head, &int_list);
+ v4l2_int_device_try_attach_all();
+ mutex_unlock(&mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_int_device_register);
+
+void v4l2_int_device_unregister(struct v4l2_int_device *d)
+{
+ mutex_lock(&mutex);
+ list_del(&d->head);
+ if (d->type == v4l2_int_type_slave
+ && d->u.slave->master != NULL) {
+ d->u.slave->master->u.master->detach(d);
+ module_put(d->u.slave->master->module);
+ d->u.slave->master = NULL;
+ }
+ mutex_unlock(&mutex);
+}
+EXPORT_SYMBOL_GPL(v4l2_int_device_unregister);
+
+/* Adapted from search_extable in extable.c. */
+static v4l2_int_ioctl_func *find_ioctl(struct v4l2_int_slave *slave, int cmd,
+ v4l2_int_ioctl_func *no_such_ioctl)
+{
+ const struct v4l2_int_ioctl_desc *first = slave->ioctls;
+ const struct v4l2_int_ioctl_desc *last =
+ first + slave->num_ioctls - 1;
+
+ while (first <= last) {
+ const struct v4l2_int_ioctl_desc *mid;
+
+ mid = (last - first) / 2 + first;
+
+ if (mid->num < cmd)
+ first = mid + 1;
+ else if (mid->num > cmd)
+ last = mid - 1;
+ else
+ return mid->func;
+ }
+
+ return no_such_ioctl;
+}
+
+static int no_such_ioctl_0(struct v4l2_int_device *d)
+{
+ return -ENOIOCTLCMD;
+}
+
+int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd)
+{
+ return ((v4l2_int_ioctl_func_0 *)
+ find_ioctl(d->u.slave, cmd,
+ (v4l2_int_ioctl_func *)no_such_ioctl_0))(d);
+}
+EXPORT_SYMBOL_GPL(v4l2_int_ioctl_0);
+
+static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg)
+{
+ return ((v4l2_int_ioctl_func_1 *)
+ find_ioctl(d->u.slave, cmd,
+ (v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg);
+}
+EXPORT_SYMBOL_GPL(v4l2_int_ioctl_1);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/v4l2-int-device.h b/drivers/media/platform/mxc/capture/v4l2-int-device.h
new file mode 100644
index 000000000000..810d87f28794
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/v4l2-int-device.h
@@ -0,0 +1,309 @@
+/*
+ * include/media/v4l2-int-device.h
+ *
+ * V4L2 internal ioctl interface.
+ *
+ * Copyright 2005-2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef V4L2_INT_DEVICE_H
+#define V4L2_INT_DEVICE_H
+
+#include <media/v4l2-common.h>
+
+#define V4L2NAMESIZE 32
+
+/*
+ *
+ * The internal V4L2 device interface core.
+ *
+ */
+
+enum v4l2_int_type {
+ v4l2_int_type_master = 1,
+ v4l2_int_type_slave
+};
+
+struct module;
+
+struct v4l2_int_device;
+
+struct v4l2_int_master {
+ int (*attach)(struct v4l2_int_device *slave);
+ void (*detach)(struct v4l2_int_device *slave);
+};
+
+typedef int (v4l2_int_ioctl_func)(struct v4l2_int_device *);
+typedef int (v4l2_int_ioctl_func_0)(struct v4l2_int_device *);
+typedef int (v4l2_int_ioctl_func_1)(struct v4l2_int_device *, void *);
+
+struct v4l2_int_ioctl_desc {
+ int num;
+ v4l2_int_ioctl_func *func;
+};
+
+struct v4l2_int_slave {
+ /* Don't touch master. */
+ struct v4l2_int_device *master;
+
+ char attach_to[V4L2NAMESIZE];
+
+ int num_ioctls;
+ struct v4l2_int_ioctl_desc *ioctls;
+};
+
+struct v4l2_int_device {
+ /* Don't touch head. */
+ struct list_head head;
+
+ struct module *module;
+
+ char name[V4L2NAMESIZE];
+
+ enum v4l2_int_type type;
+ union {
+ struct v4l2_int_master *master;
+ struct v4l2_int_slave *slave;
+ } u;
+
+ void *priv;
+};
+
+void v4l2_int_device_try_attach_all(void);
+
+int v4l2_int_device_register(struct v4l2_int_device *d);
+void v4l2_int_device_unregister(struct v4l2_int_device *d);
+
+int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd);
+int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg);
+
+/*
+ *
+ * Types and definitions for IOCTL commands.
+ *
+ */
+
+enum v4l2_power {
+ V4L2_POWER_OFF = 0,
+ V4L2_POWER_ON,
+ V4L2_POWER_STANDBY,
+};
+
+/* Slave interface type. */
+enum v4l2_if_type {
+ /*
+ * Parallel 8-, 10- or 12-bit interface, used by for example
+ * on certain image sensors.
+ */
+ V4L2_IF_TYPE_BT656,
+};
+
+enum v4l2_if_type_bt656_mode {
+ /*
+ * Modes without Bt synchronisation codes. Separate
+ * synchronisation signal lines are used.
+ */
+ V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT,
+ V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT,
+ V4L2_IF_TYPE_BT656_MODE_NOBT_12BIT,
+ /*
+ * Use Bt synchronisation codes. The vertical and horizontal
+ * synchronisation is done based on synchronisation codes.
+ */
+ V4L2_IF_TYPE_BT656_MODE_BT_8BIT,
+ V4L2_IF_TYPE_BT656_MODE_BT_10BIT,
+};
+
+struct v4l2_if_type_bt656 {
+ /*
+ * 0: Frame begins when vsync is high.
+ * 1: Frame begins when vsync changes from low to high.
+ */
+ unsigned frame_start_on_rising_vs:1;
+ /* Use Bt synchronisation codes for sync correction. */
+ unsigned bt_sync_correct:1;
+ /* Swap every two adjacent image data elements. */
+ unsigned swap:1;
+ /* Inverted latch clock polarity from slave. */
+ unsigned latch_clk_inv:1;
+ /* Hs polarity. 0 is active high, 1 active low. */
+ unsigned nobt_hs_inv:1;
+ /* Vs polarity. 0 is active high, 1 active low. */
+ unsigned nobt_vs_inv:1;
+ enum v4l2_if_type_bt656_mode mode;
+ /* Minimum accepted bus clock for slave (in Hz). */
+ u32 clock_min;
+ /* Maximum accepted bus clock for slave. */
+ u32 clock_max;
+ /*
+ * Current wish of the slave. May only change in response to
+ * ioctls that affect image capture.
+ */
+ u32 clock_curr;
+};
+
+struct v4l2_ifparm {
+ enum v4l2_if_type if_type;
+ union {
+ struct v4l2_if_type_bt656 bt656;
+ } u;
+};
+
+/* IOCTL command numbers. */
+enum v4l2_int_ioctl_num {
+ /*
+ *
+ * "Proper" V4L ioctls, as in struct video_device.
+ *
+ */
+ vidioc_int_enum_fmt_cap_num = 1,
+ vidioc_int_g_fmt_cap_num,
+ vidioc_int_s_fmt_cap_num,
+ vidioc_int_try_fmt_cap_num,
+ vidioc_int_queryctrl_num,
+ vidioc_int_g_ctrl_num,
+ vidioc_int_s_ctrl_num,
+ vidioc_int_cropcap_num,
+ vidioc_int_g_crop_num,
+ vidioc_int_s_crop_num,
+ vidioc_int_g_parm_num,
+ vidioc_int_s_parm_num,
+ vidioc_int_querystd_num,
+ vidioc_int_s_std_num,
+ vidioc_int_s_video_routing_num,
+
+ /*
+ *
+ * Strictly internal ioctls.
+ *
+ */
+ /* Initialise the device when slave attaches to the master. */
+ vidioc_int_dev_init_num = 1000,
+ /* Delinitialise the device at slave detach. */
+ vidioc_int_dev_exit_num,
+ /* Set device power state. */
+ vidioc_int_s_power_num,
+ /*
+ * Get slave private data, e.g. platform-specific slave
+ * configuration used by the master.
+ */
+ vidioc_int_g_priv_num,
+ /* Get slave interface parameters. */
+ vidioc_int_g_ifparm_num,
+ /* Does the slave need to be reset after VIDIOC_DQBUF? */
+ vidioc_int_g_needs_reset_num,
+ vidioc_int_enum_framesizes_num,
+ vidioc_int_enum_frameintervals_num,
+
+ /*
+ *
+ * VIDIOC_INT_* ioctls.
+ *
+ */
+ /* VIDIOC_INT_RESET */
+ vidioc_int_reset_num,
+ /* VIDIOC_INT_INIT */
+ vidioc_int_init_num,
+ /* VIDIOC_DBG_G_CHIP_IDENT */
+ vidioc_int_g_chip_ident_num,
+
+ /*
+ *
+ * Start of private ioctls.
+ *
+ */
+ vidioc_int_priv_start_num = 2000,
+};
+
+/*
+ *
+ * IOCTL wrapper functions for better type checking.
+ *
+ */
+
+#define V4L2_INT_WRAPPER_0(name) \
+ static inline int vidioc_int_##name(struct v4l2_int_device *d) \
+ { \
+ return v4l2_int_ioctl_0(d, vidioc_int_##name##_num); \
+ } \
+ \
+ static inline struct v4l2_int_ioctl_desc \
+ vidioc_int_##name##_cb(int (*func) \
+ (struct v4l2_int_device *)) \
+ { \
+ struct v4l2_int_ioctl_desc desc; \
+ \
+ desc.num = vidioc_int_##name##_num; \
+ desc.func = (v4l2_int_ioctl_func *)func; \
+ \
+ return desc; \
+ }
+
+#define V4L2_INT_WRAPPER_1(name, arg_type, asterisk) \
+ static inline int vidioc_int_##name(struct v4l2_int_device *d, \
+ arg_type asterisk arg) \
+ { \
+ return v4l2_int_ioctl_1(d, vidioc_int_##name##_num, \
+ (void *)(unsigned long)arg); \
+ } \
+ \
+ static inline struct v4l2_int_ioctl_desc \
+ vidioc_int_##name##_cb(int (*func) \
+ (struct v4l2_int_device *, \
+ arg_type asterisk)) \
+ { \
+ struct v4l2_int_ioctl_desc desc; \
+ \
+ desc.num = vidioc_int_##name##_num; \
+ desc.func = (v4l2_int_ioctl_func *)func; \
+ \
+ return desc; \
+ }
+
+V4L2_INT_WRAPPER_1(enum_fmt_cap, struct v4l2_fmtdesc, *);
+V4L2_INT_WRAPPER_1(g_fmt_cap, struct v4l2_format, *);
+V4L2_INT_WRAPPER_1(s_fmt_cap, struct v4l2_format, *);
+V4L2_INT_WRAPPER_1(try_fmt_cap, struct v4l2_format, *);
+V4L2_INT_WRAPPER_1(queryctrl, struct v4l2_queryctrl, *);
+V4L2_INT_WRAPPER_1(g_ctrl, struct v4l2_control, *);
+V4L2_INT_WRAPPER_1(s_ctrl, struct v4l2_control, *);
+V4L2_INT_WRAPPER_1(cropcap, struct v4l2_cropcap, *);
+V4L2_INT_WRAPPER_1(g_crop, struct v4l2_crop, *);
+V4L2_INT_WRAPPER_1(s_crop, struct v4l2_crop, *);
+V4L2_INT_WRAPPER_1(g_parm, struct v4l2_streamparm, *);
+V4L2_INT_WRAPPER_1(s_parm, struct v4l2_streamparm, *);
+V4L2_INT_WRAPPER_1(querystd, v4l2_std_id, *);
+V4L2_INT_WRAPPER_1(s_std, v4l2_std_id, *);
+V4L2_INT_WRAPPER_1(s_video_routing, struct v4l2_routing, *);
+
+V4L2_INT_WRAPPER_0(dev_init);
+V4L2_INT_WRAPPER_0(dev_exit);
+V4L2_INT_WRAPPER_1(s_power, enum v4l2_power, /*dummy arg*/);
+V4L2_INT_WRAPPER_1(g_priv, void, *);
+V4L2_INT_WRAPPER_1(g_ifparm, struct v4l2_ifparm, *);
+V4L2_INT_WRAPPER_1(g_needs_reset, void, *);
+V4L2_INT_WRAPPER_1(enum_framesizes, struct v4l2_frmsizeenum, *);
+V4L2_INT_WRAPPER_1(enum_frameintervals, struct v4l2_frmivalenum, *);
+
+V4L2_INT_WRAPPER_0(reset);
+V4L2_INT_WRAPPER_0(init);
+V4L2_INT_WRAPPER_1(g_chip_ident, int, *);
+
+#endif
diff --git a/drivers/media/platform/mxc/output/Kconfig b/drivers/media/platform/mxc/output/Kconfig
new file mode 100644
index 000000000000..237f8a88b5cb
--- /dev/null
+++ b/drivers/media/platform/mxc/output/Kconfig
@@ -0,0 +1,16 @@
+config VIDEO_MXC_IPU_OUTPUT
+ tristate "IPU v4l2 output support"
+ depends on VIDEO_MXC_OUTPUT && MXC_IPU
+ ---help---
+ This is the video4linux2 driver for IPU post processing video output.
+
+config VIDEO_MXC_PXP_V4L2
+ tristate "MXC PxP V4L2 driver"
+ depends on VIDEO_DEV && VIDEO_V4L2
+ select VIDEOBUF_DMA_CONTIG
+ ---help---
+ This is a video4linux driver for the Freescale PxP
+ (Pixel Pipeline). This module supports output overlay of
+ the MXC framebuffer on a video stream.
+
+ To compile this driver as a module, choose M here.
diff --git a/drivers/media/platform/mxc/output/Makefile b/drivers/media/platform/mxc/output/Makefile
new file mode 100644
index 000000000000..88f1a9fb735d
--- /dev/null
+++ b/drivers/media/platform/mxc/output/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_VIDEO_MXC_IPU_OUTPUT) += mxc_vout.o
+obj-$(CONFIG_VIDEO_MXC_PXP_V4L2) += mxc_pxp_v4l2.o
diff --git a/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c
new file mode 100644
index 000000000000..16da4d3e3347
--- /dev/null
+++ b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c
@@ -0,0 +1,1346 @@
+/*
+ * Copyright (C) 2010-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+/*
+ * Based on STMP378X PxP driver
+ * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/vmalloc.h>
+#include <linux/videodev2.h>
+#include <linux/dmaengine.h>
+#include <linux/pxp_dma.h>
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/mxcfb.h>
+#include <linux/platform_data/dma-imx.h>
+
+#include <media/videobuf-dma-contig.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+
+#include "mxc_pxp_v4l2.h"
+
+#define PXP_DRIVER_NAME "pxp-v4l2"
+#define PXP_DRIVER_MAJOR 2
+#define PXP_DRIVER_MINOR 0
+
+#define PXP_DEF_BUFS 2
+#define PXP_MIN_PIX 8
+
+#define V4L2_OUTPUT_TYPE_INTERNAL 4
+
+static int video_nr = -1; /* -1 ==> auto assign */
+static struct pxp_data_format pxp_s0_formats[] = {
+ {
+ .name = "24-bit RGB",
+ .bpp = 4,
+ .fourcc = V4L2_PIX_FMT_RGB24,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ }, {
+ .name = "16-bit RGB 5:6:5",
+ .bpp = 2,
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ }, {
+ .name = "16-bit RGB 5:5:5",
+ .bpp = 2,
+ .fourcc = V4L2_PIX_FMT_RGB555,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ }, {
+ .name = "YUV 4:2:0 Planar",
+ .bpp = 2,
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ }, {
+ .name = "YUV 4:2:2 Planar",
+ .bpp = 2,
+ .fourcc = V4L2_PIX_FMT_YUV422P,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ }, {
+ .name = "UYVY",
+ .bpp = 2,
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ }, {
+ .name = "YUYV",
+ .bpp = 2,
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ }, {
+ .name = "YUV32",
+ .bpp = 4,
+ .fourcc = V4L2_PIX_FMT_YUV32,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+};
+
+static unsigned int v4l2_fmt_to_pxp_fmt(u32 v4l2_pix_fmt)
+{
+ u32 pxp_fmt = 0;
+
+ if (v4l2_pix_fmt == V4L2_PIX_FMT_RGB24)
+ pxp_fmt = PXP_PIX_FMT_XRGB32;
+ else if (v4l2_pix_fmt == V4L2_PIX_FMT_RGB565)
+ pxp_fmt = PXP_PIX_FMT_RGB565;
+ else if (v4l2_pix_fmt == V4L2_PIX_FMT_RGB555)
+ pxp_fmt = PXP_PIX_FMT_RGB555;
+ else if (v4l2_pix_fmt == V4L2_PIX_FMT_YUV420)
+ pxp_fmt = PXP_PIX_FMT_YUV420P;
+ else if (v4l2_pix_fmt == V4L2_PIX_FMT_YUV422P)
+ pxp_fmt = PXP_PIX_FMT_YUV422P;
+ else if (v4l2_pix_fmt == V4L2_PIX_FMT_UYVY)
+ pxp_fmt = PXP_PIX_FMT_UYVY;
+ else if (v4l2_pix_fmt == V4L2_PIX_FMT_YUV32)
+ pxp_fmt = PXP_PIX_FMT_VUY444;
+ else if (v4l2_pix_fmt == V4L2_PIX_FMT_YUYV)
+ pxp_fmt = PXP_PIX_FMT_YUYV;
+
+ return pxp_fmt;
+}
+struct v4l2_queryctrl pxp_controls[] = {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Horizontal Flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vertical Flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_PRIVATE_BASE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Rotation",
+ .minimum = 0,
+ .maximum = 270,
+ .step = 90,
+ .default_value = 0,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_PRIVATE_BASE + 1,
+ .name = "Background Color",
+ .minimum = 0,
+ .maximum = 0xFFFFFF,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }, {
+ .id = V4L2_CID_PRIVATE_BASE + 2,
+ .name = "Set S0 Chromakey",
+ .minimum = -1,
+ .maximum = 0xFFFFFF,
+ .step = 1,
+ .default_value = -1,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }, {
+ .id = V4L2_CID_PRIVATE_BASE + 3,
+ .name = "YUV Colorspace",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },
+};
+
+static void free_dma_buf(struct pxps *pxp, struct dma_mem *buf)
+{
+ dma_free_coherent(&pxp->pdev->dev, buf->size, buf->vaddr, buf->paddr);
+ dev_dbg(&pxp->pdev->dev,
+ "free dma size:0x%x, paddr:0x%x\n",
+ buf->size, buf->paddr);
+ memset(buf, 0, sizeof(*buf));
+}
+
+static int alloc_dma_buf(struct pxps *pxp, struct dma_mem *buf)
+{
+
+ buf->vaddr = dma_alloc_coherent(&pxp->pdev->dev, buf->size, &buf->paddr,
+ GFP_DMA | GFP_KERNEL);
+ if (!buf->vaddr) {
+ dev_err(&pxp->pdev->dev,
+ "cannot get dma buf size:0x%x\n", buf->size);
+ return -ENOMEM;
+ }
+ dev_dbg(&pxp->pdev->dev,
+ "alloc dma buf size:0x%x, paddr:0x%x\n", buf->size, buf->paddr);
+ return 0;
+}
+
+/* callback function */
+static void video_dma_done(void *arg)
+{
+ struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
+ struct dma_chan *chan = tx_desc->txd.chan;
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct pxps *pxp = pxp_chan->client;
+ struct videobuf_buffer *vb;
+
+ dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n",
+ tx_desc->txd.cookie,
+ pxp->active ? sg_dma_address(&pxp->active->sg[0]) : 0);
+
+ spin_lock(&pxp->lock);
+ if (pxp->active) {
+ vb = &pxp->active->vb;
+
+ list_del_init(&vb->queue);
+ vb->state = VIDEOBUF_DONE;
+ do_gettimeofday(&vb->ts);
+ vb->field_count++;
+ wake_up(&vb->done);
+ }
+
+ if (list_empty(&pxp->outq)) {
+ pxp->active = NULL;
+ spin_unlock(&pxp->lock);
+
+ return;
+ }
+
+ pxp->active = list_entry(pxp->outq.next,
+ struct pxp_buffer, vb.queue);
+ pxp->active->vb.state = VIDEOBUF_ACTIVE;
+ spin_unlock(&pxp->lock);
+}
+
+static bool chan_filter(struct dma_chan *chan, void *arg)
+{
+ if (imx_dma_is_pxp(chan))
+ return true;
+ else
+ return false;
+}
+
+static int acquire_dma_channel(struct pxps *pxp)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+ struct pxp_channel **pchan = &pxp->pxp_channel[0];
+
+ if (*pchan) {
+ struct videobuf_buffer *vb, *_vb;
+ dma_release_channel(&(*pchan)->dma_chan);
+ *pchan = NULL;
+ pxp->active = NULL;
+ list_for_each_entry_safe(vb, _vb, &pxp->outq, queue) {
+ list_del_init(&vb->queue);
+ vb->state = VIDEOBUF_ERROR;
+ wake_up(&vb->done);
+ }
+ }
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_PRIVATE, mask);
+ chan = dma_request_channel(mask, chan_filter, NULL);
+ if (!chan)
+ return -EBUSY;
+
+ *pchan = to_pxp_channel(chan);
+ (*pchan)->client = pxp;
+
+ return 0;
+}
+
+static int _get_fbinfo(struct fb_info **fbi)
+{
+ int i;
+ for (i = 0; i < num_registered_fb; i++) {
+ char *idstr = registered_fb[i]->fix.id;
+ if (strncmp(idstr, "mxs", 3) == 0) {
+ *fbi = registered_fb[i];
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
+static int pxp_set_fbinfo(struct pxps *pxp)
+{
+ struct v4l2_framebuffer *fb = &pxp->fb;
+ int err;
+
+ err = _get_fbinfo(&pxp->fbi);
+ if (err)
+ return err;
+
+ fb->fmt.width = pxp->fbi->var.xres;
+ fb->fmt.height = pxp->fbi->var.yres;
+ pxp->pxp_conf.out_param.stride = pxp->fbi->var.xres;
+ if (pxp->fbi->var.bits_per_pixel == 16)
+ fb->fmt.pixelformat = V4L2_PIX_FMT_RGB565;
+ else
+ fb->fmt.pixelformat = V4L2_PIX_FMT_RGB24;
+
+ fb->base = (void *)pxp->fbi->fix.smem_start;
+
+ return 0;
+}
+
+static int _get_cur_fb_blank(struct pxps *pxp)
+{
+ struct fb_info *fbi;
+ mm_segment_t old_fs;
+ int err = 0;
+
+ err = _get_fbinfo(&fbi);
+ if (err)
+ return err;
+
+ if (fbi->fbops->fb_ioctl) {
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_BLANK,
+ (unsigned int)(&pxp->fb_blank));
+ set_fs(old_fs);
+ }
+
+ return err;
+}
+
+static int pxp_show_buf(struct pxps *pxp, unsigned long paddr)
+{
+ struct fb_info *fbi = pxp->fbi;
+ int ret = -EINVAL;
+
+ if (paddr == 0) {
+ dev_err(&pxp->pdev->dev, "Invalid paddr\n");
+ return ret;
+ }
+
+ console_lock();
+ fbi->fix.smem_start = paddr;
+ ret = fb_pan_display(fbi, &fbi->var);
+ console_unlock();
+
+ return ret;
+}
+
+static int set_fb_blank(int blank)
+{
+ struct fb_info *fbi;
+ int err = 0;
+
+ err = _get_fbinfo(&fbi);
+ if (err)
+ return err;
+
+ console_lock();
+ fb_blank(fbi, blank);
+ console_unlock();
+
+ return err;
+}
+
+static int pxp_set_cstate(struct pxps *pxp, struct v4l2_control *vc)
+{
+
+ if (vc->id == V4L2_CID_HFLIP) {
+ pxp->pxp_conf.proc_data.hflip = vc->value;
+ } else if (vc->id == V4L2_CID_VFLIP) {
+ pxp->pxp_conf.proc_data.vflip = vc->value;
+ } else if (vc->id == V4L2_CID_PRIVATE_BASE) {
+ if (vc->value % 90)
+ return -ERANGE;
+ pxp->pxp_conf.proc_data.rotate = vc->value;
+ } else if (vc->id == V4L2_CID_PRIVATE_BASE + 1) {
+ pxp->pxp_conf.proc_data.bgcolor = vc->value;
+ } else if (vc->id == V4L2_CID_PRIVATE_BASE + 2) {
+ pxp->pxp_conf.s0_param.color_key = vc->value;
+ } else if (vc->id == V4L2_CID_PRIVATE_BASE + 3) {
+ pxp->pxp_conf.proc_data.yuv = vc->value;
+ }
+
+ return 0;
+}
+
+static int pxp_get_cstate(struct pxps *pxp, struct v4l2_control *vc)
+{
+ if (vc->id == V4L2_CID_HFLIP)
+ vc->value = pxp->pxp_conf.proc_data.hflip;
+ else if (vc->id == V4L2_CID_VFLIP)
+ vc->value = pxp->pxp_conf.proc_data.vflip;
+ else if (vc->id == V4L2_CID_PRIVATE_BASE)
+ vc->value = pxp->pxp_conf.proc_data.rotate;
+ else if (vc->id == V4L2_CID_PRIVATE_BASE + 1)
+ vc->value = pxp->pxp_conf.proc_data.bgcolor;
+ else if (vc->id == V4L2_CID_PRIVATE_BASE + 2)
+ vc->value = pxp->pxp_conf.s0_param.color_key;
+ else if (vc->id == V4L2_CID_PRIVATE_BASE + 3)
+ vc->value = pxp->pxp_conf.proc_data.yuv;
+
+ return 0;
+}
+
+static int pxp_enumoutput(struct file *file, void *fh,
+ struct v4l2_output *o)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ if (o->index > 1)
+ return -EINVAL;
+
+ memset(o, 0, sizeof(struct v4l2_output));
+ if (o->index == 0) {
+ strcpy(o->name, "PxP Display Output");
+ pxp->output = 0;
+ } else {
+ strcpy(o->name, "PxP Virtual Output");
+ pxp->output = 1;
+ }
+ o->type = V4L2_OUTPUT_TYPE_INTERNAL;
+ o->std = 0;
+ o->reserved[0] = pxp->outbuf.paddr;
+
+ return 0;
+}
+
+static int pxp_g_output(struct file *file, void *fh,
+ unsigned int *i)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ *i = pxp->output;
+
+ return 0;
+}
+
+static int pxp_s_output(struct file *file, void *fh,
+ unsigned int i)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ struct v4l2_pix_format *fmt = (struct v4l2_pix_format*)(&pxp->fb.fmt);
+ u32 size;
+ int ret, bpp;
+
+ if (i > 1)
+ return -EINVAL;
+
+ /* Output buffer is same format as fbdev */
+ if (fmt->pixelformat == V4L2_PIX_FMT_RGB24 ||
+ fmt->pixelformat == V4L2_PIX_FMT_YUV32)
+ bpp = 4;
+ else
+ bpp = 2;
+
+ size = fmt->width * fmt->height * bpp;
+ if (size > pxp->outbuf.size) {
+ if (pxp->outbuf.vaddr)
+ free_dma_buf(pxp, &pxp->outbuf);
+ pxp->outbuf.size = size;
+ ret = alloc_dma_buf(pxp, &pxp->outbuf);
+ if (ret < 0)
+ return ret;
+ }
+ memset(pxp->outbuf.vaddr, 0x0, pxp->outbuf.size);
+
+ pxp->pxp_conf.out_param.width = fmt->width;
+ pxp->pxp_conf.out_param.height = fmt->height;
+ if (fmt->pixelformat == V4L2_PIX_FMT_RGB24)
+ pxp->pxp_conf.out_param.pixel_fmt = PXP_PIX_FMT_XRGB32;
+ else
+ pxp->pxp_conf.out_param.pixel_fmt = PXP_PIX_FMT_RGB565;
+
+ return 0;
+}
+
+static int pxp_enum_fmt_video_output(struct file *file, void *fh,
+ struct v4l2_fmtdesc *fmt)
+{
+ enum v4l2_buf_type type = fmt->type;
+ unsigned int index = fmt->index;
+
+ if (fmt->index >= ARRAY_SIZE(pxp_s0_formats))
+ return -EINVAL;
+
+ memset(fmt, 0, sizeof(struct v4l2_fmtdesc));
+ fmt->index = index;
+ fmt->type = type;
+ fmt->pixelformat = pxp_s0_formats[index].fourcc;
+ strcpy(fmt->description, pxp_s0_formats[index].name);
+
+ return 0;
+}
+
+static int pxp_g_fmt_video_output(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ struct pxp_data_format *fmt = pxp->s0_fmt;
+
+ pf->width = pxp->pxp_conf.s0_param.width;
+ pf->height = pxp->pxp_conf.s0_param.height;
+ pf->pixelformat = fmt->fourcc;
+ pf->field = V4L2_FIELD_NONE;
+ pf->bytesperline = fmt->bpp * pf->width;
+ pf->sizeimage = pf->bytesperline * pf->height;
+ pf->colorspace = fmt->colorspace;
+ pf->priv = 0;
+
+ return 0;
+}
+
+static struct pxp_data_format *pxp_get_format(struct v4l2_format *f)
+{
+ struct pxp_data_format *fmt;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pxp_s0_formats); i++) {
+ fmt = &pxp_s0_formats[i];
+ if (fmt->fourcc == f->fmt.pix.pixelformat)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(pxp_s0_formats))
+ return NULL;
+
+ return &pxp_s0_formats[i];
+}
+
+static int pxp_try_fmt_video_output(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ int w = f->fmt.pix.width;
+ int h = f->fmt.pix.height;
+ struct pxp_data_format *fmt = pxp_get_format(f);
+
+ if (!fmt)
+ return -EINVAL;
+
+ w = min(w, 2040);
+ w = max(w, 8);
+ h = min(h, 2040);
+ h = max(h, 8);
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.width = w;
+ f->fmt.pix.height = h;
+ f->fmt.pix.pixelformat = fmt->fourcc;
+
+ return 0;
+}
+
+static int pxp_s_fmt_video_output(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+ int ret;
+
+ ret = acquire_dma_channel(pxp);
+ if (ret < 0)
+ return ret;
+
+ ret = pxp_try_fmt_video_output(file, fh, f);
+ if (ret == 0) {
+ pxp->s0_fmt = pxp_get_format(f);
+ pxp->pxp_conf.s0_param.pixel_fmt =
+ v4l2_fmt_to_pxp_fmt(pxp->s0_fmt->fourcc);
+ pxp->pxp_conf.s0_param.width = pf->width;
+ pxp->pxp_conf.s0_param.height = pf->height;
+ }
+
+
+ return ret;
+}
+
+static int pxp_g_fmt_output_overlay(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ struct v4l2_window *wf = &f->fmt.win;
+
+ memset(wf, 0, sizeof(struct v4l2_window));
+ wf->chromakey = pxp->s1_chromakey;
+ wf->global_alpha = pxp->global_alpha;
+ wf->field = V4L2_FIELD_NONE;
+ wf->clips = NULL;
+ wf->clipcount = 0;
+ wf->bitmap = NULL;
+ wf->w.left = pxp->pxp_conf.proc_data.srect.left;
+ wf->w.top = pxp->pxp_conf.proc_data.srect.top;
+ wf->w.width = pxp->pxp_conf.proc_data.srect.width;
+ wf->w.height = pxp->pxp_conf.proc_data.srect.height;
+
+ return 0;
+}
+
+static int pxp_try_fmt_output_overlay(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ struct v4l2_window *wf = &f->fmt.win;
+ struct v4l2_rect srect;
+ u32 s1_chromakey = wf->chromakey;
+ u8 global_alpha = wf->global_alpha;
+
+ memcpy(&srect, &(wf->w), sizeof(struct v4l2_rect));
+
+ pxp_g_fmt_output_overlay(file, fh, f);
+
+ wf->chromakey = s1_chromakey;
+ wf->global_alpha = global_alpha;
+
+ /* Constrain parameters to the input buffer */
+ wf->w.left = srect.left;
+ wf->w.top = srect.top;
+ wf->w.width = min(srect.width,
+ ((__u32)pxp->pxp_conf.s0_param.width - wf->w.left));
+ wf->w.height = min(srect.height,
+ ((__u32)pxp->pxp_conf.s0_param.height - wf->w.top));
+
+ return 0;
+}
+
+static int pxp_s_fmt_output_overlay(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ struct v4l2_window *wf = &f->fmt.win;
+ int ret = pxp_try_fmt_output_overlay(file, fh, f);
+
+ if (ret == 0) {
+ pxp->global_alpha = wf->global_alpha;
+ pxp->s1_chromakey = wf->chromakey;
+ pxp->pxp_conf.proc_data.srect.left = wf->w.left;
+ pxp->pxp_conf.proc_data.srect.top = wf->w.top;
+ pxp->pxp_conf.proc_data.srect.width = wf->w.width;
+ pxp->pxp_conf.proc_data.srect.height = wf->w.height;
+ pxp->pxp_conf.ol_param[0].global_alpha = pxp->global_alpha;
+ pxp->pxp_conf.ol_param[0].color_key = pxp->s1_chromakey;
+ pxp->pxp_conf.ol_param[0].color_key_enable =
+ pxp->s1_chromakey_state;
+ }
+
+ return ret;
+}
+
+static int pxp_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *r)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ return videobuf_reqbufs(&pxp->s0_vbq, r);
+}
+
+static int pxp_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *b)
+{
+ int ret;
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ ret = videobuf_querybuf(&pxp->s0_vbq, b);
+ if (!ret) {
+ struct videobuf_buffer *vb = pxp->s0_vbq.bufs[b->index];
+ if (b->flags & V4L2_BUF_FLAG_MAPPED)
+ b->m.offset = videobuf_to_dma_contig(vb);
+ }
+
+ return ret;
+}
+
+static int pxp_qbuf(struct file *file, void *priv,
+ struct v4l2_buffer *b)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ return videobuf_qbuf(&pxp->s0_vbq, b);
+}
+
+static int pxp_dqbuf(struct file *file, void *priv,
+ struct v4l2_buffer *b)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ return videobuf_dqbuf(&pxp->s0_vbq, b, file->f_flags & O_NONBLOCK);
+}
+
+static int pxp_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type t)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ int ret = 0;
+
+ if (t != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ _get_cur_fb_blank(pxp);
+ set_fb_blank(FB_BLANK_UNBLANK);
+
+ ret = videobuf_streamon(&pxp->s0_vbq);
+
+ if (!ret && (pxp->output == 0))
+ pxp_show_buf(pxp, pxp->outbuf.paddr);
+
+ return ret;
+}
+
+static int pxp_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type t)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ int ret = 0;
+
+ if ((t != V4L2_BUF_TYPE_VIDEO_OUTPUT))
+ return -EINVAL;
+
+ ret = videobuf_streamoff(&pxp->s0_vbq);
+
+ pxp_show_buf(pxp, (unsigned long)pxp->fb.base);
+
+ if (pxp->fb_blank)
+ set_fb_blank(FB_BLANK_POWERDOWN);
+
+ return ret;
+}
+
+static int pxp_buf_setup(struct videobuf_queue *q,
+ unsigned int *count, unsigned *size)
+{
+ struct pxps *pxp = q->priv_data;
+
+ *size = pxp->pxp_conf.s0_param.width *
+ pxp->pxp_conf.s0_param.height * pxp->s0_fmt->bpp;
+
+ if (0 == *count)
+ *count = PXP_DEF_BUFS;
+
+ return 0;
+}
+
+static void pxp_buf_free(struct videobuf_queue *q, struct pxp_buffer *buf)
+{
+ struct videobuf_buffer *vb = &buf->vb;
+
+ BUG_ON(in_interrupt());
+
+ pr_debug("%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ /*
+ * This waits until this buffer is out of danger, i.e., until it is no
+ * longer in STATE_QUEUED or STATE_ACTIVE
+ */
+ videobuf_waiton(q, vb, 0, 0);
+
+ videobuf_dma_contig_free(q, vb);
+ buf->txd = NULL;
+
+ vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int pxp_buf_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ struct pxps *pxp = q->priv_data;
+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ struct pxp_buffer *buf = container_of(vb, struct pxp_buffer, vb);
+ struct pxp_tx_desc *desc;
+ int ret = 0;
+ int i, length;
+
+ if (!pxp->outbuf.paddr) {
+ dev_err(&pxp->pdev->dev, "Not allocate memory for "
+ "PxP Out buffer?\n");
+ return -ENOMEM;
+ }
+
+ vb->width = pxp->pxp_conf.s0_param.width;
+ vb->height = pxp->pxp_conf.s0_param.height;
+ vb->size = vb->width * vb->height * pxp->s0_fmt->bpp;
+ vb->field = V4L2_FIELD_NONE;
+ if (vb->state != VIDEOBUF_NEEDS_INIT)
+ pxp_buf_free(q, buf);
+
+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
+ struct pxp_channel *pchan = pxp->pxp_channel[0];
+ struct scatterlist *sg = &buf->sg[0];
+
+ /* This actually (allocates and) maps buffers */
+ ret = videobuf_iolock(q, vb, NULL);
+ if (ret) {
+ pr_err("fail to call videobuf_iolock, ret = %d\n", ret);
+ goto fail;
+ }
+
+ /*
+ * sg[0] for input(S0)
+ * Sg[1] for output
+ */
+ sg_init_table(sg, 3);
+
+ buf->txd = pchan->dma_chan.device->device_prep_slave_sg(
+ &pchan->dma_chan, sg, 3, DMA_FROM_DEVICE,
+ DMA_PREP_INTERRUPT, NULL);
+ if (!buf->txd) {
+ ret = -EIO;
+ goto fail;
+ }
+
+ buf->txd->callback_param = buf->txd;
+ buf->txd->callback = video_dma_done;
+
+ desc = to_tx_desc(buf->txd);
+ length = desc->len;
+ for (i = 0; i < length; i++) {
+ if (i == 0) {/* S0 */
+ memcpy(&desc->proc_data, proc_data,
+ sizeof(struct pxp_proc_data));
+ pxp_conf->s0_param.paddr =
+ videobuf_to_dma_contig(vb);
+ memcpy(&desc->layer_param.s0_param,
+ &pxp_conf->s0_param,
+ sizeof(struct pxp_layer_param));
+ } else if (i == 1) { /* Output */
+ /* we should always pass the output
+ * width and height which is the value
+ * after been rotated.
+ */
+ pxp_conf->out_param.width =
+ pxp->fb.fmt.width;
+ pxp_conf->out_param.height =
+ pxp->fb.fmt.height;
+
+ pxp_conf->out_param.paddr = pxp->outbuf.paddr;
+ memcpy(&desc->layer_param.out_param,
+ &pxp_conf->out_param,
+ sizeof(struct pxp_layer_param));
+ } else if (pxp_conf->ol_param[0].combine_enable) {
+ /* Overlay */
+ pxp_conf->ol_param[0].paddr =
+ (dma_addr_t)pxp->fb.base;
+ pxp_conf->ol_param[0].width = pxp->fb.fmt.width;
+ pxp_conf->ol_param[0].height =
+ pxp->fb.fmt.height;
+ pxp_conf->ol_param[0].pixel_fmt =
+ pxp_conf->out_param.pixel_fmt;
+ memcpy(&desc->layer_param.ol_param,
+ &pxp_conf->ol_param[0],
+ sizeof(struct pxp_layer_param));
+ }
+
+ desc = desc->next;
+ }
+
+ vb->state = VIDEOBUF_PREPARED;
+ }
+
+ return 0;
+
+fail:
+ pxp_buf_free(q, buf);
+ return ret;
+}
+
+
+static void pxp_buf_queue(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ struct pxps *pxp = q->priv_data;
+ struct pxp_buffer *buf = container_of(vb, struct pxp_buffer, vb);
+ struct dma_async_tx_descriptor *txd = buf->txd;
+ struct pxp_channel *pchan = pxp->pxp_channel[0];
+ dma_cookie_t cookie;
+
+ BUG_ON(!irqs_disabled());
+
+ list_add_tail(&vb->queue, &pxp->outq);
+
+ if (!pxp->active) {
+ pxp->active = buf;
+ vb->state = VIDEOBUF_ACTIVE;
+ } else {
+ vb->state = VIDEOBUF_QUEUED;
+ }
+
+ spin_unlock_irq(&pxp->lock);
+
+ cookie = txd->tx_submit(txd);
+ dev_dbg(&pxp->pdev->dev, "Submitted cookie %d DMA 0x%08x\n",
+ cookie, sg_dma_address(&buf->sg[0]));
+ mdelay(5);
+ /* trigger ePxP */
+ dma_async_issue_pending(&pchan->dma_chan);
+
+ spin_lock_irq(&pxp->lock);
+
+ if (cookie >= 0)
+ return;
+
+ /* Submit error */
+ pr_err("%s: Submit error\n", __func__);
+ vb->state = VIDEOBUF_PREPARED;
+
+ list_del_init(&vb->queue);
+
+ if (pxp->active == buf)
+ pxp->active = NULL;
+}
+
+static void pxp_buf_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ struct pxps *pxp = q->priv_data;
+ struct pxp_buffer *buf = container_of(vb, struct pxp_buffer, vb);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pxp->lock, flags);
+ if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) &&
+ !list_empty(&vb->queue)) {
+ vb->state = VIDEOBUF_ERROR;
+
+ list_del_init(&vb->queue);
+ if (pxp->active == buf)
+ pxp->active = NULL;
+ }
+ spin_unlock_irqrestore(&pxp->lock, flags);
+
+ pxp_buf_free(q, buf);
+}
+
+static struct videobuf_queue_ops pxp_vbq_ops = {
+ .buf_setup = pxp_buf_setup,
+ .buf_prepare = pxp_buf_prepare,
+ .buf_queue = pxp_buf_queue,
+ .buf_release = pxp_buf_release,
+};
+
+static int pxp_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ memset(cap, 0, sizeof(*cap));
+ strcpy(cap->driver, "pxp");
+ strcpy(cap->card, "pxp");
+ strlcpy(cap->bus_info, dev_name(&pxp->pdev->dev),
+ sizeof(cap->bus_info));
+
+ cap->version = (PXP_DRIVER_MAJOR << 8) + PXP_DRIVER_MINOR;
+
+ cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+ return 0;
+}
+
+static int pxp_g_fbuf(struct file *file, void *priv,
+ struct v4l2_framebuffer *fb)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ memset(fb, 0, sizeof(*fb));
+
+ fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY |
+ V4L2_FBUF_CAP_CHROMAKEY |
+ V4L2_FBUF_CAP_LOCAL_ALPHA |
+ V4L2_FBUF_CAP_GLOBAL_ALPHA;
+
+ if (pxp->global_alpha_state)
+ fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ if (pxp->s1_chromakey_state)
+ fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+
+ return 0;
+}
+
+static int pxp_s_fbuf(struct file *file, void *priv,
+ const struct v4l2_framebuffer *fb)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ pxp->overlay_state =
+ (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
+ pxp->global_alpha_state =
+ (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
+ pxp->s1_chromakey_state =
+ (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
+
+ pxp->pxp_conf.ol_param[0].combine_enable = pxp->overlay_state;
+ pxp->pxp_conf.ol_param[0].global_alpha_enable = pxp->global_alpha_state;
+
+ return 0;
+}
+
+static int pxp_g_crop(struct file *file, void *fh,
+ struct v4l2_crop *c)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ if (c->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY)
+ return -EINVAL;
+
+ c->c.left = pxp->pxp_conf.proc_data.drect.left;
+ c->c.top = pxp->pxp_conf.proc_data.drect.top;
+ c->c.width = pxp->pxp_conf.proc_data.drect.width;
+ c->c.height = pxp->pxp_conf.proc_data.drect.height;
+
+ return 0;
+}
+
+static int pxp_s_crop(struct file *file, void *fh,
+ const struct v4l2_crop *c)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ int l = c->c.left;
+ int t = c->c.top;
+ int w = c->c.width;
+ int h = c->c.height;
+ int fbw = pxp->fb.fmt.width;
+ int fbh = pxp->fb.fmt.height;
+
+ if (c->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY)
+ return -EINVAL;
+
+ /* Constrain parameters to FB limits */
+ w = min(w, fbw);
+ w = max(w, PXP_MIN_PIX);
+ h = min(h, fbh);
+ h = max(h, PXP_MIN_PIX);
+
+ /* Round up values to PxP pixel block */
+ l = roundup(l, PXP_MIN_PIX);
+ t = roundup(t, PXP_MIN_PIX);
+ w = roundup(w, PXP_MIN_PIX);
+ h = roundup(h, PXP_MIN_PIX);
+
+ if ((l + w) > fbw)
+ l = 0;
+ if ((t + h) > fbh)
+ t = 0;
+
+ pxp->pxp_conf.proc_data.drect.left = l;
+ pxp->pxp_conf.proc_data.drect.top = t;
+ pxp->pxp_conf.proc_data.drect.width = w;
+ pxp->pxp_conf.proc_data.drect.height = h;
+
+ memset(pxp->outbuf.vaddr, 0x0, pxp->outbuf.size);
+
+ return 0;
+}
+
+static int pxp_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
+ if (qc->id && qc->id == pxp_controls[i].id) {
+ memcpy(qc, &(pxp_controls[i]), sizeof(*qc));
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int pxp_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *vc)
+{
+ int i;
+
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
+ if (vc->id == pxp_controls[i].id)
+ return pxp_get_cstate(pxp, vc);
+
+ return -EINVAL;
+}
+
+static int pxp_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *vc)
+{
+ int i;
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
+ if (vc->id == pxp_controls[i].id) {
+ if (vc->value < pxp_controls[i].minimum ||
+ vc->value > pxp_controls[i].maximum)
+ return -ERANGE;
+ return pxp_set_cstate(pxp, vc);
+ }
+
+ memset(pxp->outbuf.vaddr, 0x0, pxp->outbuf.size);
+
+ return -EINVAL;
+}
+
+void pxp_release(struct video_device *vfd)
+{
+ struct pxps *pxp = video_get_drvdata(vfd);
+
+ spin_lock(&pxp->lock);
+ video_device_release(vfd);
+ spin_unlock(&pxp->lock);
+}
+
+static int pxp_open(struct file *file)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ int ret = 0;
+
+ mutex_lock(&pxp->mutex);
+ pxp->users++;
+
+ if (pxp->users > 1) {
+ pxp->users--;
+ ret = -EBUSY;
+ goto out;
+ }
+out:
+ mutex_unlock(&pxp->mutex);
+ if (ret)
+ return ret;
+
+ ret = pxp_set_fbinfo(pxp);
+ if (ret) {
+ dev_err(&pxp->pdev->dev, "failed to call pxp_set_fbinfo\n");
+ return ret;
+ }
+
+ videobuf_queue_dma_contig_init(&pxp->s0_vbq,
+ &pxp_vbq_ops,
+ &pxp->pdev->dev,
+ &pxp->lock,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT,
+ V4L2_FIELD_NONE,
+ sizeof(struct pxp_buffer),
+ pxp,
+ NULL);
+ dev_dbg(&pxp->pdev->dev, "call pxp_open\n");
+
+ return 0;
+}
+
+static int pxp_close(struct file *file)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+
+ pxp_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ videobuf_stop(&pxp->s0_vbq);
+ videobuf_mmap_free(&pxp->s0_vbq);
+ pxp->active = NULL;
+
+ mutex_lock(&pxp->mutex);
+ pxp->users--;
+ mutex_unlock(&pxp->mutex);
+
+ return 0;
+}
+
+static int pxp_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct pxps *pxp = video_get_drvdata(video_devdata(file));
+ int ret;
+
+ ret = videobuf_mmap_mapper(&pxp->s0_vbq, vma);
+
+ return ret;
+}
+
+static const struct v4l2_file_operations pxp_fops = {
+ .owner = THIS_MODULE,
+ .open = pxp_open,
+ .release = pxp_close,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = pxp_mmap,
+};
+
+static const struct v4l2_ioctl_ops pxp_ioctl_ops = {
+ .vidioc_querycap = pxp_querycap,
+
+ .vidioc_reqbufs = pxp_reqbufs,
+ .vidioc_querybuf = pxp_querybuf,
+ .vidioc_qbuf = pxp_qbuf,
+ .vidioc_dqbuf = pxp_dqbuf,
+
+ .vidioc_streamon = pxp_streamon,
+ .vidioc_streamoff = pxp_streamoff,
+
+ .vidioc_enum_output = pxp_enumoutput,
+ .vidioc_g_output = pxp_g_output,
+ .vidioc_s_output = pxp_s_output,
+
+ .vidioc_enum_fmt_vid_out = pxp_enum_fmt_video_output,
+ .vidioc_try_fmt_vid_out = pxp_try_fmt_video_output,
+ .vidioc_g_fmt_vid_out = pxp_g_fmt_video_output,
+ .vidioc_s_fmt_vid_out = pxp_s_fmt_video_output,
+
+ .vidioc_try_fmt_vid_out_overlay = pxp_try_fmt_output_overlay,
+ .vidioc_g_fmt_vid_out_overlay = pxp_g_fmt_output_overlay,
+ .vidioc_s_fmt_vid_out_overlay = pxp_s_fmt_output_overlay,
+
+ .vidioc_g_fbuf = pxp_g_fbuf,
+ .vidioc_s_fbuf = pxp_s_fbuf,
+
+ .vidioc_g_crop = pxp_g_crop,
+ .vidioc_s_crop = pxp_s_crop,
+
+ .vidioc_queryctrl = pxp_queryctrl,
+ .vidioc_g_ctrl = pxp_g_ctrl,
+ .vidioc_s_ctrl = pxp_s_ctrl,
+};
+
+static const struct video_device pxp_template = {
+ .name = "PxP",
+ .vfl_type = V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_OVERLAY |
+ V4L2_CAP_STREAMING,
+ .vfl_dir = VFL_DIR_TX,
+ .fops = &pxp_fops,
+ .release = pxp_release,
+ .minor = -1,
+ .ioctl_ops = &pxp_ioctl_ops,
+};
+
+static const struct of_device_id imx_pxpv4l2_dt_ids[] = {
+ { .compatible = "fsl,imx6sl-pxp-v4l2", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_pxpv4l2_dt_ids);
+
+static int pxp_probe(struct platform_device *pdev)
+{
+ struct pxps *pxp;
+ struct v4l2_device *v4l2_dev;
+ int err = 0;
+
+ pxp = kzalloc(sizeof(*pxp), GFP_KERNEL);
+ if (!pxp) {
+ dev_err(&pdev->dev, "failed to allocate control object\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ dev_set_drvdata(&pdev->dev, pxp);
+
+ v4l2_dev = kzalloc(sizeof(*v4l2_dev), GFP_KERNEL);
+ if (!v4l2_dev) {
+ dev_err(&pdev->dev, "failed to allocate v4l2_dev structure\n");
+ err = -ENOMEM;
+ goto freeirq;
+ }
+
+ err = v4l2_device_register(&pdev->dev, v4l2_dev);
+ if (err) {
+ dev_err(&pdev->dev, "register v4l2 device failed\n");
+ goto freev4l2;
+ }
+
+ INIT_LIST_HEAD(&pxp->outq);
+ spin_lock_init(&pxp->lock);
+ mutex_init(&pxp->mutex);
+
+ pxp->pdev = pdev;
+
+ pxp->vdev = video_device_alloc();
+ if (!pxp->vdev) {
+ dev_err(&pdev->dev, "video_device_alloc() failed\n");
+ err = -ENOMEM;
+ goto relv4l2;
+ }
+
+ memcpy(pxp->vdev, &pxp_template, sizeof(pxp_template));
+ pxp->vdev->v4l2_dev = v4l2_dev;
+ video_set_drvdata(pxp->vdev, pxp);
+
+ err = video_register_device(pxp->vdev, VFL_TYPE_GRABBER, video_nr);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register video device\n");
+ goto freevdev;
+ }
+
+ dev_info(&pdev->dev, "initialized\n");
+
+exit:
+ return err;
+
+freevdev:
+ video_device_release(pxp->vdev);
+relv4l2:
+ v4l2_device_unregister(v4l2_dev);
+freev4l2:
+ kfree(v4l2_dev);
+freeirq:
+ kfree(pxp);
+
+ return err;
+}
+
+static int pxp_remove(struct platform_device *pdev)
+{
+ struct pxps *pxp = platform_get_drvdata(pdev);
+ struct v4l2_device *v4l2_dev = pxp->vdev->v4l2_dev;
+
+ video_unregister_device(pxp->vdev);
+ video_device_release(pxp->vdev);
+ v4l2_device_unregister(v4l2_dev);
+ kfree(v4l2_dev);
+
+ free_dma_buf(pxp, &pxp->outbuf);
+
+ kfree(pxp);
+
+ return 0;
+}
+
+static struct platform_driver pxp_driver = {
+ .driver = {
+ .name = PXP_DRIVER_NAME,
+ .of_match_table = of_match_ptr(imx_pxpv4l2_dt_ids),
+ },
+ .probe = pxp_probe,
+ .remove = pxp_remove,
+};
+
+module_platform_driver(pxp_driver);
+
+module_param(video_nr, int, 0444);
+MODULE_DESCRIPTION("MXC PxP V4L2 driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/output/mxc_pxp_v4l2.h b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.h
new file mode 100644
index 000000000000..8abb4c17f3fd
--- /dev/null
+++ b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+/*
+ * Based on STMP378X PxP driver
+ * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+#ifndef _MXC_PXP_V4L2_H
+#define _MXC_PXP_V4L2_H
+
+#include <linux/dmaengine.h>
+#include <linux/pxp_dma.h>
+
+struct pxp_buffer {
+ /* Must be first! */
+ struct videobuf_buffer vb;
+
+ /* One descriptor per scatterlist (per frame) */
+ struct dma_async_tx_descriptor *txd;
+
+ struct scatterlist sg[3];
+};
+
+struct dma_mem {
+ void *vaddr;
+ dma_addr_t paddr;
+ size_t size;
+};
+
+struct pxps {
+ struct platform_device *pdev;
+
+ spinlock_t lock;
+ struct mutex mutex;
+ int users;
+
+ struct video_device *vdev;
+
+ struct videobuf_queue s0_vbq;
+ struct pxp_buffer *active;
+ struct list_head outq;
+ struct pxp_channel *pxp_channel[1]; /* We need 1 channel */
+ struct pxp_config_data pxp_conf;
+ struct dma_mem outbuf;
+
+ int output;
+
+ /* Current S0 configuration */
+ struct pxp_data_format *s0_fmt;
+
+ struct fb_info *fbi;
+ struct v4l2_framebuffer fb;
+
+ /* Output overlay support */
+ int overlay_state;
+ int global_alpha_state;
+ u8 global_alpha;
+ int s1_chromakey_state;
+ u32 s1_chromakey;
+
+ int fb_blank;
+};
+
+struct pxp_data_format {
+ char *name;
+ unsigned int bpp;
+ u32 fourcc;
+ enum v4l2_colorspace colorspace;
+};
+
+#endif
diff --git a/drivers/media/platform/mxc/output/mxc_vout.c b/drivers/media/platform/mxc/output/mxc_vout.c
new file mode 100644
index 000000000000..f1ee36d65c89
--- /dev/null
+++ b/drivers/media/platform/mxc/output/mxc_vout.c
@@ -0,0 +1,2331 @@
+/*
+ * Copyright (C) 2011-2015 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
+ */
+
+#include <linux/console.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/ipu-v3.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <linux/mxc_v4l2.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+
+#include <media/videobuf-dma-contig.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+
+#define UYVY_BLACK (0x00800080)
+#define RGB_BLACK (0x0)
+#define UV_BLACK (0x80)
+#define Y_BLACK (0x0)
+
+#define MAX_FB_NUM 6
+#define FB_BUFS 3
+#define VDOA_FB_BUFS (FB_BUFS - 1)
+#define VALID_HEIGHT_1080P (1080)
+#define FRAME_HEIGHT_1080P (1088)
+#define FRAME_WIDTH_1080P (1920)
+#define CHECK_TILED_1080P_DISPLAY(vout) \
+ ((((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12) || \
+ ((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12F)) &&\
+ ((vout)->task.input.width == FRAME_WIDTH_1080P) && \
+ ((vout)->task.input.height == FRAME_HEIGHT_1080P) && \
+ ((vout)->task.input.crop.w == FRAME_WIDTH_1080P) && \
+ (((vout)->task.input.crop.h == FRAME_HEIGHT_1080P) || \
+ ((vout)->task.input.crop.h == VALID_HEIGHT_1080P)) && \
+ ((vout)->task.output.width == FRAME_WIDTH_1080P) && \
+ ((vout)->task.output.height == VALID_HEIGHT_1080P) && \
+ ((vout)->task.output.crop.w == FRAME_WIDTH_1080P) && \
+ ((vout)->task.output.crop.h == VALID_HEIGHT_1080P))
+#define CHECK_TILED_1080P_STREAM(vout) \
+ ((((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12) || \
+ ((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12F)) &&\
+ ((vout)->task.input.width == FRAME_WIDTH_1080P) && \
+ ((vout)->task.input.crop.w == FRAME_WIDTH_1080P) && \
+ ((vout)->task.input.height == FRAME_HEIGHT_1080P) && \
+ ((vout)->task.input.crop.h == FRAME_HEIGHT_1080P))
+#define IS_PLANAR_PIXEL_FORMAT(format) \
+ (format == IPU_PIX_FMT_NV12 || \
+ format == IPU_PIX_FMT_YUV420P2 || \
+ format == IPU_PIX_FMT_YUV420P || \
+ format == IPU_PIX_FMT_YVU420P || \
+ format == IPU_PIX_FMT_YUV422P || \
+ format == IPU_PIX_FMT_YVU422P || \
+ format == IPU_PIX_FMT_YUV444P)
+
+#define NSEC_PER_FRAME_30FPS (33333333)
+
+struct mxc_vout_fb {
+ char *name;
+ int ipu_id;
+ struct v4l2_rect crop_bounds;
+ unsigned int disp_fmt;
+ bool disp_support_csc;
+ bool disp_support_windows;
+};
+
+struct dma_mem {
+ void *vaddr;
+ dma_addr_t paddr;
+ size_t size;
+};
+
+struct mxc_vout_output {
+ int open_cnt;
+ struct fb_info *fbi;
+ unsigned long fb_smem_start;
+ unsigned long fb_smem_len;
+ struct video_device *vfd;
+ struct mutex mutex;
+ struct mutex task_lock;
+ struct mutex accs_lock;
+ enum v4l2_buf_type type;
+
+ struct videobuf_queue vbq;
+ spinlock_t vbq_lock;
+
+ struct list_head queue_list;
+ struct list_head active_list;
+
+ struct v4l2_rect crop_bounds;
+ unsigned int disp_fmt;
+ struct mxcfb_pos win_pos;
+ bool disp_support_windows;
+ bool disp_support_csc;
+
+ bool fmt_init;
+ bool release;
+ bool linear_bypass_pp;
+ bool vdoa_1080p;
+ bool tiled_bypass_pp;
+ struct v4l2_rect in_rect;
+ struct ipu_task task;
+ struct ipu_task vdoa_task;
+ struct dma_mem vdoa_work;
+ struct dma_mem vdoa_output[VDOA_FB_BUFS];
+
+ bool timer_stop;
+ struct hrtimer timer;
+ struct workqueue_struct *v4l_wq;
+ struct work_struct disp_work;
+ unsigned long frame_count;
+ unsigned long vdi_frame_cnt;
+ ktime_t start_ktime;
+
+ int ctrl_rotate;
+ int ctrl_vflip;
+ int ctrl_hflip;
+
+ dma_addr_t disp_bufs[FB_BUFS];
+
+ struct videobuf_buffer *pre1_vb;
+ struct videobuf_buffer *pre2_vb;
+
+ bool input_crop;
+};
+
+struct mxc_vout_dev {
+ struct device *dev;
+ struct v4l2_device v4l2_dev;
+ struct mxc_vout_output *out[MAX_FB_NUM];
+ int out_num;
+};
+
+/* Driver Configuration macros */
+#define VOUT_NAME "mxc_vout"
+
+/* Variables configurable through module params*/
+static int debug;
+static int vdi_rate_double;
+static int video_nr = 16;
+
+static int mxc_vidioc_s_input_crop(struct mxc_vout_output *vout,
+ const struct v4l2_crop *crop);
+static int mxc_vidioc_g_input_crop(struct mxc_vout_output *vout,
+ struct v4l2_crop *crop);
+/* Module parameters */
+module_param(video_nr, int, S_IRUGO);
+MODULE_PARM_DESC(video_nr, "video device numbers");
+module_param(debug, int, 0600);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+module_param(vdi_rate_double, int, 0600);
+MODULE_PARM_DESC(vdi_rate_double, "vdi frame rate double on/off");
+
+static const struct v4l2_fmtdesc mxc_formats[] = {
+ {
+ .description = "RGB565",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ },
+ {
+ .description = "BGR24",
+ .pixelformat = V4L2_PIX_FMT_BGR24,
+ },
+ {
+ .description = "RGB24",
+ .pixelformat = V4L2_PIX_FMT_RGB24,
+ },
+ {
+ .description = "RGB32",
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ },
+ {
+ .description = "BGR32",
+ .pixelformat = V4L2_PIX_FMT_BGR32,
+ },
+ {
+ .description = "NV12",
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ },
+ {
+ .description = "UYVY",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ },
+ {
+ .description = "YUYV",
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ },
+ {
+ .description = "YUV422 planar",
+ .pixelformat = V4L2_PIX_FMT_YUV422P,
+ },
+ {
+ .description = "YUV444",
+ .pixelformat = V4L2_PIX_FMT_YUV444,
+ },
+ {
+ .description = "YUV420",
+ .pixelformat = V4L2_PIX_FMT_YUV420,
+ },
+ {
+ .description = "YVU420",
+ .pixelformat = V4L2_PIX_FMT_YVU420,
+ },
+ {
+ .description = "TILED NV12P",
+ .pixelformat = IPU_PIX_FMT_TILED_NV12,
+ },
+ {
+ .description = "TILED NV12F",
+ .pixelformat = IPU_PIX_FMT_TILED_NV12F,
+ },
+ {
+ .description = "YUV444 planar",
+ .pixelformat = IPU_PIX_FMT_YUV444P,
+ },
+};
+
+#define NUM_MXC_VOUT_FORMATS (ARRAY_SIZE(mxc_formats))
+
+#define DEF_INPUT_WIDTH 320
+#define DEF_INPUT_HEIGHT 240
+
+static int mxc_vidioc_streamoff(struct file *file, void *fh,
+ enum v4l2_buf_type i);
+
+static struct mxc_vout_fb g_fb_setting[MAX_FB_NUM];
+static int config_disp_output(struct mxc_vout_output *vout);
+static void release_disp_output(struct mxc_vout_output *vout);
+
+static DEFINE_MUTEX(gfb_mutex);
+static DEFINE_MUTEX(gfbi_mutex);
+
+static unsigned int get_frame_size(struct mxc_vout_output *vout)
+{
+ unsigned int size;
+
+ if (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format)
+ size = TILED_NV12_FRAME_SIZE(vout->task.input.width,
+ vout->task.input.height);
+ else if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) {
+ size = TILED_NV12_FRAME_SIZE(vout->task.input.width,
+ vout->task.input.height/2);
+ size *= 2;
+ } else
+ size = vout->task.input.width * vout->task.input.height *
+ fmt_to_bpp(vout->task.input.format)/8;
+
+ return size;
+}
+
+static void free_dma_buf(struct mxc_vout_output *vout, struct dma_mem *buf)
+{
+ dma_free_coherent(vout->vbq.dev, buf->size, buf->vaddr, buf->paddr);
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "free dma size:0x%x, paddr:0x%x\n",
+ buf->size, buf->paddr);
+ memset(buf, 0, sizeof(*buf));
+}
+
+static int alloc_dma_buf(struct mxc_vout_output *vout, struct dma_mem *buf)
+{
+
+ buf->vaddr = dma_alloc_coherent(vout->vbq.dev, buf->size, &buf->paddr,
+ GFP_DMA | GFP_KERNEL);
+ if (!buf->vaddr) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "cannot get dma buf size:0x%x\n", buf->size);
+ return -ENOMEM;
+ }
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "alloc dma buf size:0x%x, paddr:0x%x\n", buf->size, buf->paddr);
+ return 0;
+}
+
+static ipu_channel_t get_ipu_channel(struct fb_info *fbi)
+{
+ ipu_channel_t ipu_ch = CHAN_NONE;
+ mm_segment_t old_fs;
+
+ if (fbi->fbops->fb_ioctl) {
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN,
+ (unsigned long)&ipu_ch);
+ set_fs(old_fs);
+ }
+
+ return ipu_ch;
+}
+
+static unsigned int get_ipu_fmt(struct fb_info *fbi)
+{
+ mm_segment_t old_fs;
+ unsigned int fb_fmt = 0;
+
+ if (fbi->fbops->fb_ioctl) {
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_DIFMT,
+ (unsigned long)&fb_fmt);
+ set_fs(old_fs);
+ }
+
+ return fb_fmt;
+}
+
+static void update_display_setting(void)
+{
+ int i;
+ struct fb_info *fbi;
+ struct v4l2_rect bg_crop_bounds[2];
+
+ mutex_lock(&gfb_mutex);
+ for (i = 0; i < num_registered_fb; i++) {
+ fbi = registered_fb[i];
+
+ memset(&g_fb_setting[i], 0, sizeof(struct mxc_vout_fb));
+
+ if (!strncmp(fbi->fix.id, "DISP3", 5))
+ g_fb_setting[i].ipu_id = 0;
+ else
+ g_fb_setting[i].ipu_id = 1;
+
+ g_fb_setting[i].name = fbi->fix.id;
+ g_fb_setting[i].crop_bounds.left = 0;
+ g_fb_setting[i].crop_bounds.top = 0;
+ g_fb_setting[i].crop_bounds.width = fbi->var.xres;
+ g_fb_setting[i].crop_bounds.height = fbi->var.yres;
+ g_fb_setting[i].disp_fmt = get_ipu_fmt(fbi);
+
+ if (get_ipu_channel(fbi) == MEM_BG_SYNC) {
+ bg_crop_bounds[g_fb_setting[i].ipu_id] =
+ g_fb_setting[i].crop_bounds;
+ g_fb_setting[i].disp_support_csc = true;
+ } else if (get_ipu_channel(fbi) == MEM_FG_SYNC) {
+ g_fb_setting[i].disp_support_csc = true;
+ g_fb_setting[i].disp_support_windows = true;
+ }
+ }
+
+ for (i = 0; i < num_registered_fb; i++) {
+ fbi = registered_fb[i];
+
+ if (get_ipu_channel(fbi) == MEM_FG_SYNC)
+ g_fb_setting[i].crop_bounds =
+ bg_crop_bounds[g_fb_setting[i].ipu_id];
+ }
+ mutex_unlock(&gfb_mutex);
+}
+
+/* called after g_fb_setting filled by update_display_setting */
+static int update_setting_from_fbi(struct mxc_vout_output *vout,
+ struct fb_info *fbi)
+{
+ int i;
+ bool found = false;
+
+ mutex_lock(&gfbi_mutex);
+
+ update_display_setting();
+
+ for (i = 0; i < MAX_FB_NUM; i++) {
+ if (g_fb_setting[i].name) {
+ if (!strcmp(fbi->fix.id, g_fb_setting[i].name)) {
+ vout->crop_bounds = g_fb_setting[i].crop_bounds;
+ vout->disp_fmt = g_fb_setting[i].disp_fmt;
+ vout->disp_support_csc =
+ g_fb_setting[i].disp_support_csc;
+ vout->disp_support_windows =
+ g_fb_setting[i].disp_support_windows;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ v4l2_err(vout->vfd->v4l2_dev, "can not find output\n");
+ mutex_unlock(&gfbi_mutex);
+ return -EINVAL;
+ }
+ strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name));
+
+ memset(&vout->task, 0, sizeof(struct ipu_task));
+
+ vout->task.input.width = DEF_INPUT_WIDTH;
+ vout->task.input.height = DEF_INPUT_HEIGHT;
+ vout->task.input.crop.pos.x = 0;
+ vout->task.input.crop.pos.y = 0;
+ vout->task.input.crop.w = DEF_INPUT_WIDTH;
+ vout->task.input.crop.h = DEF_INPUT_HEIGHT;
+ vout->input_crop = false;
+
+ vout->task.output.width = vout->crop_bounds.width;
+ vout->task.output.height = vout->crop_bounds.height;
+ vout->task.output.crop.pos.x = 0;
+ vout->task.output.crop.pos.y = 0;
+ vout->task.output.crop.w = vout->crop_bounds.width;
+ vout->task.output.crop.h = vout->crop_bounds.height;
+ if (colorspaceofpixel(vout->disp_fmt) == YUV_CS)
+ vout->task.output.format = IPU_PIX_FMT_UYVY;
+ else
+ vout->task.output.format = IPU_PIX_FMT_RGB565;
+
+ mutex_unlock(&gfbi_mutex);
+ return 0;
+}
+
+static inline unsigned long get_jiffies(struct timeval *t)
+{
+ struct timeval cur;
+
+ if (t->tv_usec >= 1000000) {
+ t->tv_sec += t->tv_usec / 1000000;
+ t->tv_usec = t->tv_usec % 1000000;
+ }
+
+ do_gettimeofday(&cur);
+ if ((t->tv_sec < cur.tv_sec)
+ || ((t->tv_sec == cur.tv_sec) && (t->tv_usec < cur.tv_usec)))
+ return jiffies;
+
+ if (t->tv_usec < cur.tv_usec) {
+ cur.tv_sec = t->tv_sec - cur.tv_sec - 1;
+ cur.tv_usec = t->tv_usec + 1000000 - cur.tv_usec;
+ } else {
+ cur.tv_sec = t->tv_sec - cur.tv_sec;
+ cur.tv_usec = t->tv_usec - cur.tv_usec;
+ }
+
+ return jiffies + timeval_to_jiffies(&cur);
+}
+
+static bool deinterlace_3_field(struct mxc_vout_output *vout)
+{
+ return (vout->task.input.deinterlace.enable &&
+ (vout->task.input.deinterlace.motion != HIGH_MOTION));
+}
+
+static int set_field_fmt(struct mxc_vout_output *vout, enum v4l2_field field)
+{
+ struct ipu_deinterlace *deinterlace = &vout->task.input.deinterlace;
+
+ switch (field) {
+ /* Images are in progressive format, not interlaced */
+ case V4L2_FIELD_NONE:
+ case V4L2_FIELD_ANY:
+ deinterlace->enable = false;
+ deinterlace->field_fmt = 0;
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "Progressive frame.\n");
+ break;
+ case V4L2_FIELD_INTERLACED_TB:
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "Enable deinterlace TB.\n");
+ deinterlace->enable = true;
+ deinterlace->field_fmt = IPU_DEINTERLACE_FIELD_TOP;
+ break;
+ case V4L2_FIELD_INTERLACED_BT:
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "Enable deinterlace BT.\n");
+ deinterlace->enable = true;
+ deinterlace->field_fmt = IPU_DEINTERLACE_FIELD_BOTTOM;
+ break;
+ default:
+ v4l2_err(vout->vfd->v4l2_dev,
+ "field format:%d not supported yet!\n", field);
+ return -EINVAL;
+ }
+
+ if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) {
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "tiled fmt enable deinterlace.\n");
+ deinterlace->enable = true;
+ }
+
+ if (deinterlace->enable && vdi_rate_double)
+ deinterlace->field_fmt |= IPU_DEINTERLACE_RATE_EN;
+
+ return 0;
+}
+
+static bool is_pp_bypass(struct mxc_vout_output *vout)
+{
+ if ((IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format))
+ return false;
+ if ((vout->task.input.width == vout->task.output.width) &&
+ (vout->task.input.height == vout->task.output.height) &&
+ (vout->task.input.crop.w == vout->task.output.crop.w) &&
+ (vout->task.input.crop.h == vout->task.output.crop.h) &&
+ (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) &&
+ !vout->task.input.deinterlace.enable) {
+ if (vout->disp_support_csc)
+ return true;
+ else if (!need_csc(vout->task.input.format, vout->disp_fmt))
+ return true;
+ /*
+ * input crop show to full output which can show based on
+ * xres_virtual/yres_virtual
+ */
+ } else if ((vout->task.input.crop.w == vout->task.output.crop.w) &&
+ (vout->task.output.crop.w == vout->task.output.width) &&
+ (vout->task.input.crop.h == vout->task.output.crop.h) &&
+ (vout->task.output.crop.h ==
+ vout->task.output.height) &&
+ (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) &&
+ !vout->task.input.deinterlace.enable) {
+ if (vout->disp_support_csc)
+ return true;
+ else if (!need_csc(vout->task.input.format, vout->disp_fmt))
+ return true;
+ }
+ return false;
+}
+
+static void setup_buf_timer(struct mxc_vout_output *vout,
+ struct videobuf_buffer *vb)
+{
+ ktime_t expiry_time, now;
+
+ /* if timestamp is 0, then default to 30fps */
+ if ((vb->ts.tv_sec == 0) && (vb->ts.tv_usec == 0))
+ expiry_time = ktime_add_ns(vout->start_ktime,
+ NSEC_PER_FRAME_30FPS * vout->frame_count);
+ else
+ expiry_time = timeval_to_ktime(vb->ts);
+
+ now = hrtimer_cb_get_time(&vout->timer);
+ if ((now.tv64 > expiry_time.tv64)) {
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "warning: timer timeout already expired.\n");
+ expiry_time = now;
+ }
+
+ hrtimer_start(&vout->timer, expiry_time, HRTIMER_MODE_ABS);
+
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "timer handler next "
+ "schedule: %lldnsecs\n", expiry_time.tv64);
+}
+
+static int show_buf(struct mxc_vout_output *vout, int idx,
+ struct ipu_pos *ipos)
+{
+ struct fb_info *fbi = vout->fbi;
+ struct fb_var_screeninfo var;
+ int ret;
+ u32 fb_base = 0;
+
+ memcpy(&var, &fbi->var, sizeof(var));
+
+ if (vout->linear_bypass_pp || vout->tiled_bypass_pp) {
+ /*
+ * crack fb base
+ * NOTE: should not do other fb operation during v4l2
+ */
+ console_lock();
+ fb_base = fbi->fix.smem_start;
+ fbi->fix.smem_start = vout->task.output.paddr;
+ fbi->var.yoffset = ipos->y + 1;
+ var.xoffset = ipos->x;
+ var.yoffset = ipos->y;
+ var.vmode |= FB_VMODE_YWRAP;
+ ret = fb_pan_display(fbi, &var);
+ fbi->fix.smem_start = fb_base;
+ console_unlock();
+ } else {
+ console_lock();
+ var.yoffset = idx * fbi->var.yres;
+ var.vmode &= ~FB_VMODE_YWRAP;
+ ret = fb_pan_display(fbi, &var);
+ console_unlock();
+ }
+
+ return ret;
+}
+
+static void disp_work_func(struct work_struct *work)
+{
+ struct mxc_vout_output *vout =
+ container_of(work, struct mxc_vout_output, disp_work);
+ struct videobuf_queue *q = &vout->vbq;
+ struct videobuf_buffer *vb, *vb_next = NULL;
+ unsigned long flags = 0;
+ struct ipu_pos ipos;
+ int ret = 0;
+ u32 in_fmt = 0, in_width = 0, in_height = 0;
+ u32 vdi_cnt = 0;
+ u32 vdi_frame;
+ u32 index = 0;
+ u32 ocrop_h = 0;
+ u32 o_height = 0;
+ u32 tiled_interlaced = 0;
+ bool tiled_fmt = false;
+
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work begin one frame\n");
+
+ spin_lock_irqsave(q->irqlock, flags);
+
+ if (list_empty(&vout->active_list)) {
+ v4l2_warn(vout->vfd->v4l2_dev,
+ "no entry in active_list, should not be here\n");
+ spin_unlock_irqrestore(q->irqlock, flags);
+ return;
+ }
+
+ vb = list_first_entry(&vout->active_list,
+ struct videobuf_buffer, queue);
+ ret = set_field_fmt(vout, vb->field);
+ if (ret < 0) {
+ spin_unlock_irqrestore(q->irqlock, flags);
+ return;
+ }
+ if (deinterlace_3_field(vout)) {
+ if (list_is_singular(&vout->active_list)) {
+ if (list_empty(&vout->queue_list)) {
+ vout->timer_stop = true;
+ spin_unlock_irqrestore(q->irqlock, flags);
+ v4l2_warn(vout->vfd->v4l2_dev,
+ "no enough entry for 3 fields "
+ "deinterlacer\n");
+ return;
+ }
+
+ /*
+ * We need to use the next vb even if it is
+ * not on the active list.
+ */
+ vb_next = list_first_entry(&vout->queue_list,
+ struct videobuf_buffer, queue);
+ } else
+ vb_next = list_first_entry(vout->active_list.next,
+ struct videobuf_buffer, queue);
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "cur field_fmt:%d, next field_fmt:%d.\n",
+ vb->field, vb_next->field);
+ /* repeat the last field during field format changing */
+ if ((vb->field != vb_next->field) &&
+ (vb_next->field != V4L2_FIELD_NONE))
+ vb_next = vb;
+ }
+
+ spin_unlock_irqrestore(q->irqlock, flags);
+
+vdi_frame_rate_double:
+ mutex_lock(&vout->task_lock);
+
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "v4l2 frame_cnt:%ld, vb_field:%d, fmt:%d\n",
+ vout->frame_count, vb->field,
+ vout->task.input.deinterlace.field_fmt);
+ if (vb->memory == V4L2_MEMORY_USERPTR)
+ vout->task.input.paddr = vb->baddr;
+ else
+ vout->task.input.paddr = videobuf_to_dma_contig(vb);
+
+ if (vout->task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN)
+ index = vout->vdi_frame_cnt % FB_BUFS;
+ else
+ index = vout->frame_count % FB_BUFS;
+ if (vout->linear_bypass_pp) {
+ vout->task.output.paddr = vout->task.input.paddr;
+ ipos.x = vout->task.input.crop.pos.x;
+ ipos.y = vout->task.input.crop.pos.y;
+ } else {
+ if (deinterlace_3_field(vout)) {
+ if (vb->memory == V4L2_MEMORY_USERPTR)
+ vout->task.input.paddr_n = vb_next->baddr;
+ else
+ vout->task.input.paddr_n =
+ videobuf_to_dma_contig(vb_next);
+ }
+ vout->task.output.paddr = vout->disp_bufs[index];
+ if (vout->vdoa_1080p) {
+ o_height = vout->task.output.height;
+ ocrop_h = vout->task.output.crop.h;
+ vout->task.output.height = FRAME_HEIGHT_1080P;
+ vout->task.output.crop.h = FRAME_HEIGHT_1080P;
+ }
+ tiled_fmt =
+ (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format);
+ if (vout->tiled_bypass_pp) {
+ ipos.x = vout->task.input.crop.pos.x;
+ ipos.y = vout->task.input.crop.pos.y;
+ } else if (tiled_fmt) {
+ vout->vdoa_task.input.paddr = vout->task.input.paddr;
+ if (deinterlace_3_field(vout))
+ vout->vdoa_task.input.paddr_n =
+ vout->task.input.paddr_n;
+ vout->vdoa_task.output.paddr = vout->vdoa_work.paddr;
+ ret = ipu_queue_task(&vout->vdoa_task);
+ if (ret < 0) {
+ mutex_unlock(&vout->task_lock);
+ goto err;
+ }
+ vout->task.input.paddr = vout->vdoa_task.output.paddr;
+ in_fmt = vout->task.input.format;
+ in_width = vout->task.input.width;
+ in_height = vout->task.input.height;
+ vout->task.input.format = vout->vdoa_task.output.format;
+ vout->task.input.width = vout->vdoa_task.output.width;
+ vout->task.input.height = vout->vdoa_task.output.height;
+ if (vout->task.input.deinterlace.enable) {
+ tiled_interlaced = 1;
+ vout->task.input.deinterlace.enable = 0;
+ }
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "tiled queue task\n");
+ }
+ ret = ipu_queue_task(&vout->task);
+ if ((!vout->tiled_bypass_pp) && tiled_fmt) {
+ vout->task.input.format = in_fmt;
+ vout->task.input.width = in_width;
+ vout->task.input.height = in_height;
+ }
+ if (tiled_interlaced)
+ vout->task.input.deinterlace.enable = 1;
+ if (ret < 0) {
+ mutex_unlock(&vout->task_lock);
+ goto err;
+ }
+ if (vout->vdoa_1080p) {
+ vout->task.output.crop.h = ocrop_h;
+ vout->task.output.height = o_height;
+ }
+ }
+
+ mutex_unlock(&vout->task_lock);
+
+ ret = show_buf(vout, index, &ipos);
+ if (ret < 0)
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "show buf with ret %d\n", ret);
+
+ if (vout->task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN) {
+ vdi_frame = vout->task.input.deinterlace.field_fmt
+ & IPU_DEINTERLACE_RATE_FRAME1;
+ if (vdi_frame)
+ vout->task.input.deinterlace.field_fmt &=
+ ~IPU_DEINTERLACE_RATE_FRAME1;
+ else
+ vout->task.input.deinterlace.field_fmt |=
+ IPU_DEINTERLACE_RATE_FRAME1;
+ vout->vdi_frame_cnt++;
+ vdi_cnt++;
+ if (vdi_cnt < IPU_DEINTERLACE_MAX_FRAME)
+ goto vdi_frame_rate_double;
+ }
+ spin_lock_irqsave(q->irqlock, flags);
+
+ list_del(&vb->queue);
+
+ /*
+ * The videobuf before the last one has been shown. Set
+ * VIDEOBUF_DONE state here to avoid tearing issue in ic bypass
+ * case, which makes sure a buffer being shown will not be
+ * dequeued to be overwritten. It also brings side-effect that
+ * the last 2 buffers can not be dequeued correctly, apps need
+ * to take care of it.
+ */
+ if (vout->pre2_vb) {
+ vout->pre2_vb->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vout->pre2_vb->done);
+ vout->pre2_vb = NULL;
+ }
+
+ if (vout->linear_bypass_pp) {
+ vout->pre2_vb = vout->pre1_vb;
+ vout->pre1_vb = vb;
+ } else {
+ if (vout->pre1_vb) {
+ vout->pre1_vb->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vout->pre1_vb->done);
+ vout->pre1_vb = NULL;
+ }
+ vb->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vb->done);
+ }
+
+ vout->frame_count++;
+
+ /* pick next queue buf to setup timer */
+ if (list_empty(&vout->queue_list))
+ vout->timer_stop = true;
+ else {
+ vb = list_first_entry(&vout->queue_list,
+ struct videobuf_buffer, queue);
+ setup_buf_timer(vout, vb);
+ }
+
+ spin_unlock_irqrestore(q->irqlock, flags);
+
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work finish one frame\n");
+
+ return;
+err:
+ v4l2_err(vout->vfd->v4l2_dev, "display work fail ret = %d\n", ret);
+ vout->timer_stop = true;
+ vb->state = VIDEOBUF_ERROR;
+ return;
+}
+
+static enum hrtimer_restart mxc_vout_timer_handler(struct hrtimer *timer)
+{
+ struct mxc_vout_output *vout = container_of(timer,
+ struct mxc_vout_output,
+ timer);
+ struct videobuf_queue *q = &vout->vbq;
+ struct videobuf_buffer *vb;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(q->irqlock, flags);
+
+ /*
+ * put first queued entry into active, if previous entry did not
+ * finish, setup current entry's timer again.
+ */
+ if (list_empty(&vout->queue_list)) {
+ spin_unlock_irqrestore(q->irqlock, flags);
+ return HRTIMER_NORESTART;
+ }
+
+ /* move videobuf from queued list to active list */
+ vb = list_first_entry(&vout->queue_list,
+ struct videobuf_buffer, queue);
+ list_del(&vb->queue);
+ list_add_tail(&vb->queue, &vout->active_list);
+
+ if (queue_work(vout->v4l_wq, &vout->disp_work) == 0) {
+ v4l2_warn(vout->vfd->v4l2_dev,
+ "disp work was in queue already, queue buf again next time\n");
+ list_del(&vb->queue);
+ list_add(&vb->queue, &vout->queue_list);
+ spin_unlock_irqrestore(q->irqlock, flags);
+ return HRTIMER_NORESTART;
+ }
+
+ vb->state = VIDEOBUF_ACTIVE;
+
+ spin_unlock_irqrestore(q->irqlock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
+/* Video buffer call backs */
+
+/*
+ * Buffer setup function is called by videobuf layer when REQBUF ioctl is
+ * called. This is used to setup buffers and return size and count of
+ * buffers allocated. After the call to this buffer, videobuf layer will
+ * setup buffer queue depending on the size and count of buffers
+ */
+static int mxc_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+ unsigned int *size)
+{
+ struct mxc_vout_output *vout = q->priv_data;
+ unsigned int frame_size;
+
+ if (!vout)
+ return -EINVAL;
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
+ return -EINVAL;
+
+ frame_size = get_frame_size(vout);
+ *size = PAGE_ALIGN(frame_size);
+
+ return 0;
+}
+
+/*
+ * This function will be called when VIDIOC_QBUF ioctl is called.
+ * It prepare buffers before give out for the display. This function
+ * converts user space virtual address into physical address if userptr memory
+ * exchange mechanism is used.
+ */
+static int mxc_vout_buffer_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ vb->state = VIDEOBUF_PREPARED;
+ return 0;
+}
+
+/*
+ * Buffer queue funtion will be called from the videobuf layer when _QBUF
+ * ioctl is called. It is used to enqueue buffer, which is ready to be
+ * displayed.
+ * This function is protected by q->irqlock.
+ */
+static void mxc_vout_buffer_queue(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ struct mxc_vout_output *vout = q->priv_data;
+ struct videobuf_buffer *active_vb;
+
+ list_add_tail(&vb->queue, &vout->queue_list);
+ vb->state = VIDEOBUF_QUEUED;
+
+ if (vout->timer_stop) {
+ if (deinterlace_3_field(vout) &&
+ !list_empty(&vout->active_list)) {
+ active_vb = list_first_entry(&vout->active_list,
+ struct videobuf_buffer, queue);
+ setup_buf_timer(vout, active_vb);
+ } else {
+ setup_buf_timer(vout, vb);
+ }
+ vout->timer_stop = false;
+ }
+}
+
+/*
+ * Buffer release function is called from videobuf layer to release buffer
+ * which are already allocated
+ */
+static void mxc_vout_buffer_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int mxc_vout_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ int ret;
+ struct mxc_vout_output *vout = file->private_data;
+
+ if (!vout)
+ return -ENODEV;
+
+ ret = videobuf_mmap_mapper(&vout->vbq, vma);
+ if (ret < 0)
+ v4l2_err(vout->vfd->v4l2_dev,
+ "offset invalid [offset=0x%lx]\n",
+ (vma->vm_pgoff << PAGE_SHIFT));
+
+ return ret;
+}
+
+static int mxc_vout_release(struct file *file)
+{
+ unsigned int ret = 0;
+ struct videobuf_queue *q;
+ struct mxc_vout_output *vout = file->private_data;
+
+ if (!vout)
+ return 0;
+
+ mutex_lock(&vout->accs_lock);
+ if (--vout->open_cnt == 0) {
+ q = &vout->vbq;
+ if (q->streaming)
+ mxc_vidioc_streamoff(file, vout, vout->type);
+ else {
+ release_disp_output(vout);
+ videobuf_queue_cancel(q);
+ }
+ destroy_workqueue(vout->v4l_wq);
+ ret = videobuf_mmap_free(q);
+ }
+
+ mutex_unlock(&vout->accs_lock);
+ return ret;
+}
+
+static long mxc_vout_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct mxc_vout_output *vout = file->private_data;
+ struct v4l2_crop crop;
+ int ret;
+
+ switch (cmd) {
+ case VIDIOC_S_INPUT_CROP:
+ if (copy_from_user(&crop, (void __user *)arg, sizeof(struct v4l2_crop)))
+ return -EFAULT;
+ ret = mxc_vidioc_s_input_crop(vout, &crop);
+ break;
+ case VIDIOC_G_INPUT_CROP:
+ mxc_vidioc_g_input_crop(vout, &crop);
+ ret = copy_from_user((void __user *)arg, &crop, sizeof(struct v4l2_crop));
+ break;
+ default:
+ ret = video_ioctl2(file, cmd, arg);
+ }
+ return ret;
+}
+
+static int mxc_vout_open(struct file *file)
+{
+ struct mxc_vout_output *vout = NULL;
+ int ret = 0;
+
+ vout = video_drvdata(file);
+
+ if (vout == NULL)
+ return -ENODEV;
+
+ mutex_lock(&vout->accs_lock);
+ if (vout->open_cnt++ == 0) {
+ vout->ctrl_rotate = 0;
+ vout->ctrl_vflip = 0;
+ vout->ctrl_hflip = 0;
+ ret = update_setting_from_fbi(vout, vout->fbi);
+ if (ret < 0)
+ goto err;
+
+ vout->v4l_wq = create_singlethread_workqueue("v4l2q");
+ if (!vout->v4l_wq) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "Could not create work queue\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ INIT_WORK(&vout->disp_work, disp_work_func);
+
+ INIT_LIST_HEAD(&vout->queue_list);
+ INIT_LIST_HEAD(&vout->active_list);
+
+ vout->fmt_init = false;
+ vout->frame_count = 0;
+ vout->vdi_frame_cnt = 0;
+
+ vout->win_pos.x = 0;
+ vout->win_pos.y = 0;
+ vout->release = true;
+ }
+
+ file->private_data = vout;
+
+err:
+ mutex_unlock(&vout->accs_lock);
+ return ret;
+}
+
+/*
+ * V4L2 ioctls
+ */
+static int mxc_vidioc_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct mxc_vout_output *vout = fh;
+
+ strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
+ strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
+ cap->bus_info[0] = '\0';
+ cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+ return 0;
+}
+
+static int mxc_vidioc_enum_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_fmtdesc *fmt)
+{
+ if (fmt->index >= NUM_MXC_VOUT_FORMATS)
+ return -EINVAL;
+
+ strlcpy(fmt->description, mxc_formats[fmt->index].description,
+ sizeof(fmt->description));
+ fmt->pixelformat = mxc_formats[fmt->index].pixelformat;
+
+ return 0;
+}
+
+static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mxc_vout_output *vout = fh;
+
+ f->fmt.pix.width = vout->task.input.width;
+ f->fmt.pix.height = vout->task.input.height;
+ f->fmt.pix.pixelformat = vout->task.input.format;
+ f->fmt.pix.sizeimage = get_frame_size(vout);
+
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "frame_size:0x%x, pix_fmt:0x%x\n",
+ f->fmt.pix.sizeimage,
+ vout->task.input.format);
+
+ return 0;
+}
+
+static inline int ipu_try_task(struct mxc_vout_output *vout)
+{
+ int ret;
+ struct ipu_task *task = &vout->task;
+
+again:
+ ret = ipu_check_task(task);
+ if (ret != IPU_CHECK_OK) {
+ if (ret > IPU_CHECK_ERR_MIN) {
+ if (ret == IPU_CHECK_ERR_SPLIT_INPUTW_OVER ||
+ ret == IPU_CHECK_ERR_W_DOWNSIZE_OVER) {
+ task->input.crop.w -= 8;
+ goto again;
+ }
+ if (ret == IPU_CHECK_ERR_SPLIT_INPUTH_OVER ||
+ ret == IPU_CHECK_ERR_H_DOWNSIZE_OVER) {
+ task->input.crop.h -= 8;
+ goto again;
+ }
+ if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) {
+ if (vout->disp_support_windows) {
+ task->output.width -= 8;
+ task->output.crop.w =
+ task->output.width;
+ } else
+ task->output.crop.w -= 8;
+ goto again;
+ }
+ if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) {
+ if (vout->disp_support_windows) {
+ task->output.height -= 8;
+ task->output.crop.h =
+ task->output.height;
+ } else
+ task->output.crop.h -= 8;
+ goto again;
+ }
+ ret = -EINVAL;
+ }
+ } else
+ ret = 0;
+
+ return ret;
+}
+
+static inline int vdoaipu_try_task(struct mxc_vout_output *vout)
+{
+ int ret;
+ int is_1080p_stream;
+ int in_width, in_height;
+ size_t size;
+ struct ipu_task *ipu_task = &vout->task;
+ struct ipu_crop *icrop = &ipu_task->input.crop;
+ struct ipu_task *vdoa_task = &vout->vdoa_task;
+ u32 deinterlace = 0;
+ u32 in_fmt;
+
+ if (vout->task.input.deinterlace.enable)
+ deinterlace = 1;
+
+ memset(vdoa_task, 0, sizeof(*vdoa_task));
+ vdoa_task->output.format = IPU_PIX_FMT_NV12;
+ memcpy(&vdoa_task->input, &ipu_task->input,
+ sizeof(ipu_task->input));
+ if ((icrop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (icrop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN)) {
+ vdoa_task->input.crop.w =
+ ALIGN(icrop->w, IPU_PIX_FMT_TILED_NV12_MBALIGN);
+ vdoa_task->input.crop.h =
+ ALIGN(icrop->h, IPU_PIX_FMT_TILED_NV12_MBALIGN);
+ }
+ vdoa_task->output.width = vdoa_task->input.crop.w;
+ vdoa_task->output.height = vdoa_task->input.crop.h;
+ vdoa_task->output.crop.w = vdoa_task->input.crop.w;
+ vdoa_task->output.crop.h = vdoa_task->input.crop.h;
+
+ size = PAGE_ALIGN(vdoa_task->input.crop.w *
+ vdoa_task->input.crop.h *
+ fmt_to_bpp(vdoa_task->output.format)/8);
+ if (size > vout->vdoa_work.size) {
+ if (vout->vdoa_work.vaddr)
+ free_dma_buf(vout, &vout->vdoa_work);
+ vout->vdoa_work.size = size;
+ ret = alloc_dma_buf(vout, &vout->vdoa_work);
+ if (ret < 0)
+ return ret;
+ }
+ ret = ipu_check_task(vdoa_task);
+ if (ret != IPU_CHECK_OK)
+ return -EINVAL;
+
+ is_1080p_stream = CHECK_TILED_1080P_STREAM(vout);
+ if (is_1080p_stream)
+ ipu_task->input.crop.h = VALID_HEIGHT_1080P;
+ in_fmt = ipu_task->input.format;
+ in_width = ipu_task->input.width;
+ in_height = ipu_task->input.height;
+ ipu_task->input.format = vdoa_task->output.format;
+ ipu_task->input.height = vdoa_task->output.height;
+ ipu_task->input.width = vdoa_task->output.width;
+ if (deinterlace)
+ ipu_task->input.deinterlace.enable = 0;
+ ret = ipu_try_task(vout);
+ if (deinterlace)
+ ipu_task->input.deinterlace.enable = 1;
+ ipu_task->input.format = in_fmt;
+ ipu_task->input.width = in_width;
+ ipu_task->input.height = in_height;
+
+ return ret;
+}
+
+static int mxc_vout_try_task(struct mxc_vout_output *vout)
+{
+ int ret = 0;
+ struct ipu_output *output = &vout->task.output;
+ struct ipu_input *input = &vout->task.input;
+ struct ipu_crop *crop = &input->crop;
+ u32 o_height = 0;
+ u32 ocrop_h = 0;
+ bool tiled_fmt = false;
+ bool tiled_need_pp = false;
+
+ vout->vdoa_1080p = CHECK_TILED_1080P_DISPLAY(vout);
+ if (vout->vdoa_1080p) {
+ input->crop.h = FRAME_HEIGHT_1080P;
+ o_height = output->height;
+ ocrop_h = output->crop.h;
+ output->height = FRAME_HEIGHT_1080P;
+ output->crop.h = FRAME_HEIGHT_1080P;
+ }
+
+ if ((IPU_PIX_FMT_TILED_NV12 == input->format) ||
+ (IPU_PIX_FMT_TILED_NV12F == input->format)) {
+ if ((input->width % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (input->height % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN)) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "ERR: tiled fmt needs 16 pixel align.\n");
+ return -EINVAL;
+ }
+ if ((crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))
+ tiled_need_pp = true;
+ } else {
+ crop->w -= crop->w % 8;
+ crop->h -= crop->h % 8;
+ }
+ /* assume task.output already set by S_CROP */
+ vout->linear_bypass_pp = is_pp_bypass(vout);
+ if (vout->linear_bypass_pp) {
+ v4l2_info(vout->vfd->v4l2_dev, "Bypass IC.\n");
+ output->format = input->format;
+ } else {
+ /* if need CSC, choose IPU-DP or IPU_IC do it */
+ if (vout->disp_support_csc) {
+ if (colorspaceofpixel(input->format) == YUV_CS)
+ output->format = IPU_PIX_FMT_UYVY;
+ else
+ output->format = IPU_PIX_FMT_RGB565;
+ } else {
+ if (colorspaceofpixel(vout->disp_fmt) == YUV_CS)
+ output->format = IPU_PIX_FMT_UYVY;
+ else
+ output->format = IPU_PIX_FMT_RGB565;
+ }
+
+ vout->tiled_bypass_pp = false;
+ if ((IPU_PIX_FMT_TILED_NV12 == input->format) ||
+ (IPU_PIX_FMT_TILED_NV12F == input->format)) {
+ /* check resize/rotate/flip, or csc task */
+ if (!(tiled_need_pp ||
+ (IPU_ROTATE_NONE != output->rotate) ||
+ (input->crop.w != output->crop.w) ||
+ (input->crop.h != output->crop.h) ||
+ (!vout->disp_support_csc &&
+ (colorspaceofpixel(vout->disp_fmt) == RGB_CS)))
+ ) {
+ /* IC bypass */
+ output->format = IPU_PIX_FMT_NV12;
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "tiled bypass pp\n");
+ vout->tiled_bypass_pp = true;
+ }
+ tiled_fmt = true;
+ }
+
+ if ((!vout->tiled_bypass_pp) && tiled_fmt)
+ ret = vdoaipu_try_task(vout);
+ else
+ ret = ipu_try_task(vout);
+ }
+
+ if (vout->vdoa_1080p) {
+ output->height = o_height;
+ output->crop.h = ocrop_h;
+ }
+
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "icrop.w:%u, icrop.h:%u, iw:%u, ih:%u,"
+ "ocrop.w:%u, ocrop.h:%u, ow:%u, oh:%u\n",
+ input->crop.w, input->crop.h,
+ input->width, input->height,
+ output->crop.w, output->crop.h,
+ output->width, output->height);
+ return ret;
+}
+
+static int mxc_vout_try_format(struct mxc_vout_output *vout,
+ struct v4l2_format *f)
+{
+ int ret = 0;
+
+ if ((f->fmt.pix.field != V4L2_FIELD_NONE) &&
+ (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format)) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "progressive tiled fmt should used V4L2_FIELD_NONE!\n");
+ return -EINVAL;
+ }
+
+ if (vout->input_crop == false) {
+ vout->task.input.crop.pos.x = 0;
+ vout->task.input.crop.pos.y = 0;
+ vout->task.input.crop.w = f->fmt.pix.width;
+ vout->task.input.crop.h = f->fmt.pix.height;
+ }
+
+ vout->task.input.width = f->fmt.pix.width;
+ vout->task.input.height = f->fmt.pix.height;
+ vout->task.input.format = f->fmt.pix.pixelformat;
+
+ ret = set_field_fmt(vout, f->fmt.pix.field);
+ if (ret < 0)
+ return ret;
+
+ ret = mxc_vout_try_task(vout);
+ if (!ret) {
+ f->fmt.pix.width = vout->task.input.crop.w;
+ f->fmt.pix.height = vout->task.input.crop.h;
+ }
+
+ return ret;
+}
+
+static bool mxc_vout_need_fb_reconfig(struct mxc_vout_output *vout,
+ struct mxc_vout_output *pre_vout)
+{
+ if (!vout->vbq.streaming)
+ return false;
+
+ if (vout->tiled_bypass_pp)
+ return true;
+
+ if (vout->linear_bypass_pp != pre_vout->linear_bypass_pp)
+ return true;
+
+ /* cropped output resolution or format are changed */
+ if (vout->task.output.format != pre_vout->task.output.format ||
+ vout->task.output.crop.w != pre_vout->task.output.crop.w ||
+ vout->task.output.crop.h != pre_vout->task.output.crop.h)
+ return true;
+
+ /* overlay: window position or resolution are changed */
+ if (vout->disp_support_windows &&
+ (vout->win_pos.x != pre_vout->win_pos.x ||
+ vout->win_pos.y != pre_vout->win_pos.y ||
+ vout->task.output.width != pre_vout->task.output.width ||
+ vout->task.output.height != pre_vout->task.output.height))
+ return true;
+
+ /* background: cropped position is changed */
+ if (!vout->disp_support_windows &&
+ (vout->task.output.crop.pos.x !=
+ pre_vout->task.output.crop.pos.x ||
+ vout->task.output.crop.pos.y !=
+ pre_vout->task.output.crop.pos.y))
+ return true;
+
+ return false;
+}
+
+static int mxc_vidioc_s_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mxc_vout_output *vout = fh;
+ int ret = 0;
+
+ if (vout->vbq.streaming)
+ return -EBUSY;
+
+ mutex_lock(&vout->task_lock);
+ ret = mxc_vout_try_format(vout, f);
+ if (ret >= 0)
+ vout->fmt_init = true;
+ mutex_unlock(&vout->task_lock);
+
+ return ret;
+}
+
+static int mxc_vidioc_cropcap(struct file *file, void *fh,
+ struct v4l2_cropcap *cropcap)
+{
+ struct mxc_vout_output *vout = fh;
+
+ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ cropcap->bounds = vout->crop_bounds;
+ cropcap->defrect = vout->crop_bounds;
+
+ return 0;
+}
+
+static int mxc_vidioc_g_crop(struct file *file, void *fh,
+ struct v4l2_crop *crop)
+{
+ struct mxc_vout_output *vout = fh;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ if (vout->disp_support_windows) {
+ crop->c.left = vout->win_pos.x;
+ crop->c.top = vout->win_pos.y;
+ crop->c.width = vout->task.output.width;
+ crop->c.height = vout->task.output.height;
+ } else {
+ if (vout->task.output.crop.w && vout->task.output.crop.h) {
+ crop->c.left = vout->task.output.crop.pos.x;
+ crop->c.top = vout->task.output.crop.pos.y;
+ crop->c.width = vout->task.output.crop.w;
+ crop->c.height = vout->task.output.crop.h;
+ } else {
+ crop->c.left = 0;
+ crop->c.top = 0;
+ crop->c.width = vout->task.output.width;
+ crop->c.height = vout->task.output.height;
+ }
+ }
+
+ return 0;
+}
+
+static int mxc_vidioc_s_crop(struct file *file, void *fh,
+ const struct v4l2_crop *crop)
+{
+ struct mxc_vout_output *vout = fh, *pre_vout;
+ struct v4l2_rect *b = &vout->crop_bounds;
+ struct v4l2_crop fix_up_crop;
+ int ret = 0;
+
+ memcpy(&fix_up_crop, crop, sizeof(*crop));
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ if (crop->c.width < 0 || crop->c.height < 0)
+ return -EINVAL;
+
+ if (crop->c.width == 0)
+ fix_up_crop.c.width = b->width - b->left;
+ if (crop->c.height == 0)
+ fix_up_crop.c.height = b->height - b->top;
+
+ if (crop->c.top < b->top)
+ fix_up_crop.c.top = b->top;
+ if (crop->c.top >= b->top + b->height)
+ fix_up_crop.c.top = b->top + b->height - 1;
+ if (crop->c.height > b->top - crop->c.top + b->height)
+ fix_up_crop.c.height =
+ b->top - fix_up_crop.c.top + b->height;
+
+ if (crop->c.left < b->left)
+ fix_up_crop.c.left = b->left;
+ if (crop->c.left >= b->left + b->width)
+ fix_up_crop.c.left = b->left + b->width - 1;
+ if (crop->c.width > b->left - crop->c.left + b->width)
+ fix_up_crop.c.width =
+ b->left - fix_up_crop.c.left + b->width;
+
+ /* stride line limitation */
+ fix_up_crop.c.height -= fix_up_crop.c.height % 8;
+ fix_up_crop.c.width -= fix_up_crop.c.width % 8;
+ if ((fix_up_crop.c.width <= 0) || (fix_up_crop.c.height <= 0) ||
+ ((fix_up_crop.c.left + fix_up_crop.c.width) >
+ (b->left + b->width)) ||
+ ((fix_up_crop.c.top + fix_up_crop.c.height) >
+ (b->top + b->height))) {
+ v4l2_err(vout->vfd->v4l2_dev, "s_crop err: %d, %d, %d, %d",
+ fix_up_crop.c.left, fix_up_crop.c.top,
+ fix_up_crop.c.width, fix_up_crop.c.height);
+ return -EINVAL;
+ }
+
+ /* the same setting, return */
+ if (vout->disp_support_windows) {
+ if ((vout->win_pos.x == fix_up_crop.c.left) &&
+ (vout->win_pos.y == fix_up_crop.c.top) &&
+ (vout->task.output.crop.w == fix_up_crop.c.width) &&
+ (vout->task.output.crop.h == fix_up_crop.c.height))
+ return 0;
+ } else {
+ if ((vout->task.output.crop.pos.x == fix_up_crop.c.left) &&
+ (vout->task.output.crop.pos.y == fix_up_crop.c.top) &&
+ (vout->task.output.crop.w == fix_up_crop.c.width) &&
+ (vout->task.output.crop.h == fix_up_crop.c.height))
+ return 0;
+ }
+
+ pre_vout = vmalloc(sizeof(*pre_vout));
+ if (!pre_vout)
+ return -ENOMEM;
+
+ /* wait current work finish */
+ if (vout->vbq.streaming)
+ flush_workqueue(vout->v4l_wq);
+
+ mutex_lock(&vout->task_lock);
+
+ memcpy(pre_vout, vout, sizeof(*vout));
+
+ if (vout->disp_support_windows) {
+ vout->task.output.crop.pos.x = 0;
+ vout->task.output.crop.pos.y = 0;
+ vout->win_pos.x = fix_up_crop.c.left;
+ vout->win_pos.y = fix_up_crop.c.top;
+ vout->task.output.width = fix_up_crop.c.width;
+ vout->task.output.height = fix_up_crop.c.height;
+ } else {
+ vout->task.output.crop.pos.x = fix_up_crop.c.left;
+ vout->task.output.crop.pos.y = fix_up_crop.c.top;
+ }
+
+ vout->task.output.crop.w = fix_up_crop.c.width;
+ vout->task.output.crop.h = fix_up_crop.c.height;
+
+ /*
+ * must S_CROP before S_FMT, for fist time S_CROP, will not check
+ * ipu task, it will check in S_FMT, after S_FMT, S_CROP should
+ * check ipu task too.
+ */
+ if (vout->fmt_init) {
+ memcpy(&vout->task.input.crop, &vout->in_rect,
+ sizeof(vout->in_rect));
+ ret = mxc_vout_try_task(vout);
+ if (ret < 0) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "vout check task failed\n");
+ memcpy(vout, pre_vout, sizeof(*vout));
+ goto done;
+ }
+
+ if (mxc_vout_need_fb_reconfig(vout, pre_vout)) {
+ ret = config_disp_output(vout);
+ if (ret < 0)
+ v4l2_err(vout->vfd->v4l2_dev,
+ "Config display output failed\n");
+ }
+ }
+
+done:
+ vfree(pre_vout);
+ mutex_unlock(&vout->task_lock);
+
+ return ret;
+}
+
+static int mxc_vidioc_queryctrl(struct file *file, void *fh,
+ struct v4l2_queryctrl *ctrl)
+{
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ROTATE:
+ ret = v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0);
+ break;
+ case V4L2_CID_VFLIP:
+ ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
+ break;
+ case V4L2_CID_HFLIP:
+ ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
+ break;
+ case V4L2_CID_MXC_MOTION:
+ ret = v4l2_ctrl_query_fill(ctrl, 0, 2, 1, 0);
+ break;
+ default:
+ ctrl->name[0] = '\0';
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int mxc_vidioc_g_ctrl(struct file *file, void *fh,
+ struct v4l2_control *ctrl)
+{
+ int ret = 0;
+ struct mxc_vout_output *vout = fh;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ROTATE:
+ ctrl->value = vout->ctrl_rotate;
+ break;
+ case V4L2_CID_VFLIP:
+ ctrl->value = vout->ctrl_vflip;
+ break;
+ case V4L2_CID_HFLIP:
+ ctrl->value = vout->ctrl_hflip;
+ break;
+ case V4L2_CID_MXC_MOTION:
+ if (vout->task.input.deinterlace.enable)
+ ctrl->value = vout->task.input.deinterlace.motion;
+ else
+ ctrl->value = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static void setup_task_rotation(struct mxc_vout_output *vout)
+{
+ if (vout->ctrl_rotate == 0) {
+ if (vout->ctrl_vflip && vout->ctrl_hflip)
+ vout->task.output.rotate = IPU_ROTATE_180;
+ else if (vout->ctrl_vflip)
+ vout->task.output.rotate = IPU_ROTATE_VERT_FLIP;
+ else if (vout->ctrl_hflip)
+ vout->task.output.rotate = IPU_ROTATE_HORIZ_FLIP;
+ else
+ vout->task.output.rotate = IPU_ROTATE_NONE;
+ } else if (vout->ctrl_rotate == 90) {
+ if (vout->ctrl_vflip && vout->ctrl_hflip)
+ vout->task.output.rotate = IPU_ROTATE_90_LEFT;
+ else if (vout->ctrl_vflip)
+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_VFLIP;
+ else if (vout->ctrl_hflip)
+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_HFLIP;
+ else
+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT;
+ } else if (vout->ctrl_rotate == 180) {
+ if (vout->ctrl_vflip && vout->ctrl_hflip)
+ vout->task.output.rotate = IPU_ROTATE_NONE;
+ else if (vout->ctrl_vflip)
+ vout->task.output.rotate = IPU_ROTATE_HORIZ_FLIP;
+ else if (vout->ctrl_hflip)
+ vout->task.output.rotate = IPU_ROTATE_VERT_FLIP;
+ else
+ vout->task.output.rotate = IPU_ROTATE_180;
+ } else if (vout->ctrl_rotate == 270) {
+ if (vout->ctrl_vflip && vout->ctrl_hflip)
+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT;
+ else if (vout->ctrl_vflip)
+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_HFLIP;
+ else if (vout->ctrl_hflip)
+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_VFLIP;
+ else
+ vout->task.output.rotate = IPU_ROTATE_90_LEFT;
+ }
+}
+
+static int mxc_vidioc_s_ctrl(struct file *file, void *fh,
+ struct v4l2_control *ctrl)
+{
+ int ret = 0;
+ struct mxc_vout_output *vout = fh, *pre_vout;
+
+ pre_vout = vmalloc(sizeof(*pre_vout));
+ if (!pre_vout)
+ return -ENOMEM;
+
+ /* wait current work finish */
+ if (vout->vbq.streaming)
+ flush_workqueue(vout->v4l_wq);
+
+ mutex_lock(&vout->task_lock);
+
+ memcpy(pre_vout, vout, sizeof(*vout));
+
+ switch (ctrl->id) {
+ case V4L2_CID_ROTATE:
+ {
+ vout->ctrl_rotate = (ctrl->value/90) * 90;
+ if (vout->ctrl_rotate > 270)
+ vout->ctrl_rotate = 270;
+ setup_task_rotation(vout);
+ break;
+ }
+ case V4L2_CID_VFLIP:
+ {
+ vout->ctrl_vflip = ctrl->value;
+ setup_task_rotation(vout);
+ break;
+ }
+ case V4L2_CID_HFLIP:
+ {
+ vout->ctrl_hflip = ctrl->value;
+ setup_task_rotation(vout);
+ break;
+ }
+ case V4L2_CID_MXC_MOTION:
+ {
+ vout->task.input.deinterlace.motion = ctrl->value;
+ break;
+ }
+ default:
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (vout->fmt_init) {
+ memcpy(&vout->task.input.crop, &vout->in_rect,
+ sizeof(vout->in_rect));
+ ret = mxc_vout_try_task(vout);
+ if (ret < 0) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "vout check task failed\n");
+ memcpy(vout, pre_vout, sizeof(*vout));
+ goto done;
+ }
+
+ if (mxc_vout_need_fb_reconfig(vout, pre_vout)) {
+ ret = config_disp_output(vout);
+ if (ret < 0)
+ v4l2_err(vout->vfd->v4l2_dev,
+ "Config display output failed\n");
+ }
+ }
+
+done:
+ vfree(pre_vout);
+ mutex_unlock(&vout->task_lock);
+
+ return ret;
+}
+
+static int mxc_vidioc_reqbufs(struct file *file, void *fh,
+ struct v4l2_requestbuffers *req)
+{
+ int ret = 0;
+ struct mxc_vout_output *vout = fh;
+ struct videobuf_queue *q = &vout->vbq;
+
+ if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ /* should not be here after streaming, videobuf_reqbufs will control */
+ mutex_lock(&vout->task_lock);
+
+ ret = videobuf_reqbufs(q, req);
+
+ mutex_unlock(&vout->task_lock);
+ return ret;
+}
+
+static int mxc_vidioc_querybuf(struct file *file, void *fh,
+ struct v4l2_buffer *b)
+{
+ int ret;
+ struct mxc_vout_output *vout = fh;
+
+ ret = videobuf_querybuf(&vout->vbq, b);
+ if (!ret) {
+ /* return physical address */
+ struct videobuf_buffer *vb = vout->vbq.bufs[b->index];
+ if (b->flags & V4L2_BUF_FLAG_MAPPED)
+ b->m.offset = videobuf_to_dma_contig(vb);
+ }
+
+ return ret;
+}
+
+static int mxc_vidioc_qbuf(struct file *file, void *fh,
+ struct v4l2_buffer *buffer)
+{
+ struct mxc_vout_output *vout = fh;
+
+ return videobuf_qbuf(&vout->vbq, buffer);
+}
+
+static int mxc_vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+ struct mxc_vout_output *vout = fh;
+
+ if (!vout->vbq.streaming)
+ return -EINVAL;
+
+ if (file->f_flags & O_NONBLOCK)
+ return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 1);
+ else
+ return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 0);
+}
+
+static int mxc_vidioc_s_input_crop(struct mxc_vout_output *vout,
+ const struct v4l2_crop *crop)
+{
+ int ret = 0;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ if (crop->c.width < 0 || crop->c.height < 0)
+ return -EINVAL;
+
+ vout->task.input.crop.pos.x = crop->c.left;
+ vout->task.input.crop.pos.y = crop->c.top;
+ vout->task.input.crop.w = crop->c.width;
+ vout->task.input.crop.h = crop->c.height;
+
+ vout->input_crop = true;
+ memcpy(&vout->in_rect, &vout->task.input.crop, sizeof(vout->in_rect));
+
+ return ret;
+}
+
+static int mxc_vidioc_g_input_crop(struct mxc_vout_output *vout,
+ struct v4l2_crop *crop)
+{
+ int ret = 0;
+
+ crop->c.left = vout->task.input.crop.pos.x;
+ crop->c.top = vout->task.input.crop.pos.y;
+ crop->c.width = vout->task.input.crop.w;
+ crop->c.height = vout->task.input.crop.h;
+
+ return ret;
+}
+
+static int set_window_position(struct mxc_vout_output *vout,
+ struct mxcfb_pos *pos)
+{
+ struct fb_info *fbi = vout->fbi;
+ mm_segment_t old_fs;
+ int ret = 0;
+
+ if (vout->disp_support_windows) {
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = fbi->fbops->fb_ioctl(fbi, MXCFB_SET_OVERLAY_POS,
+ (unsigned long)pos);
+ set_fs(old_fs);
+ }
+
+ return ret;
+}
+
+static int config_disp_output(struct mxc_vout_output *vout)
+{
+ struct dma_mem *buf = NULL;
+ struct fb_info *fbi = vout->fbi;
+ struct fb_var_screeninfo var;
+ struct mxcfb_pos pos;
+ int i, fb_num, ret;
+ u32 fb_base;
+ u32 size;
+ u32 display_buf_size;
+ u32 *pixel = NULL;
+ u32 color;
+ int j;
+
+ memcpy(&var, &fbi->var, sizeof(var));
+ fb_base = fbi->fix.smem_start;
+
+ var.xres = vout->task.output.width;
+ var.yres = vout->task.output.height;
+ if (vout->linear_bypass_pp || vout->tiled_bypass_pp) {
+ fb_num = 1;
+ /* input crop */
+ if (vout->task.input.width > vout->task.output.width)
+ var.xres_virtual = vout->task.input.width;
+ else
+ var.xres_virtual = var.xres;
+ if (vout->task.input.height > vout->task.output.height)
+ var.yres_virtual = vout->task.input.height;
+ else
+ var.yres_virtual = var.yres;
+ var.rotate = vout->task.output.rotate;
+ var.vmode |= FB_VMODE_YWRAP;
+ } else {
+ fb_num = FB_BUFS;
+ var.xres_virtual = var.xres;
+ var.yres_virtual = fb_num * var.yres;
+ var.vmode &= ~FB_VMODE_YWRAP;
+ }
+ var.bits_per_pixel = fmt_to_bpp(vout->task.output.format);
+ var.nonstd = vout->task.output.format;
+
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "set display fb to %d %d\n",
+ var.xres, var.yres);
+
+ /*
+ * To setup the overlay fb from scratch without
+ * the last time overlay fb position or resolution's
+ * impact, we take the following steps:
+ * - blank fb
+ * - set fb position to the starting point
+ * - reconfigure fb
+ * - set fb position to a specific point
+ * - unblank fb
+ * This procedure applies to non-overlay fbs as well.
+ */
+ console_lock();
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_blank(fbi, FB_BLANK_POWERDOWN);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+
+ pos.x = 0;
+ pos.y = 0;
+ ret = set_window_position(vout, &pos);
+ if (ret < 0) {
+ v4l2_err(vout->vfd->v4l2_dev, "failed to set fb position "
+ "to starting point\n");
+ return ret;
+ }
+
+ /* Init display channel through fb API */
+ var.yoffset = 0;
+ var.activate |= FB_ACTIVATE_FORCE;
+ console_lock();
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ ret = fb_set_var(fbi, &var);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+ if (ret < 0) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "ERR:%s fb_set_var ret:%d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = set_window_position(vout, &vout->win_pos);
+ if (ret < 0) {
+ v4l2_err(vout->vfd->v4l2_dev, "failed to set fb position\n");
+ return ret;
+ }
+
+ if (vout->linear_bypass_pp || vout->tiled_bypass_pp)
+ display_buf_size = fbi->fix.line_length * fbi->var.yres_virtual;
+ else
+ display_buf_size = fbi->fix.line_length * fbi->var.yres;
+ for (i = 0; i < fb_num; i++)
+ vout->disp_bufs[i] = fbi->fix.smem_start + i * display_buf_size;
+ if (vout->tiled_bypass_pp) {
+ size = PAGE_ALIGN(vout->task.input.crop.w *
+ vout->task.input.crop.h *
+ fmt_to_bpp(vout->task.output.format)/8);
+ if (size > vout->vdoa_output[0].size) {
+ for (i = 0; i < VDOA_FB_BUFS; i++) {
+ buf = &vout->vdoa_output[i];
+ if (buf->vaddr)
+ free_dma_buf(vout, buf);
+ buf->size = size;
+ ret = alloc_dma_buf(vout, buf);
+ if (ret < 0)
+ goto err;
+ }
+ }
+ for (i = fb_num; i < (fb_num + VDOA_FB_BUFS); i++)
+ vout->disp_bufs[i] =
+ vout->vdoa_output[i - fb_num].paddr;
+ }
+ vout->fb_smem_len = fbi->fix.smem_len;
+ vout->fb_smem_start = fbi->fix.smem_start;
+ if (fb_base != fbi->fix.smem_start) {
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "realloc fb mem size:0x%x@0x%lx,old paddr @0x%x\n",
+ fbi->fix.smem_len, fbi->fix.smem_start, fb_base);
+ }
+
+ /* fill black when video config changed */
+ color = colorspaceofpixel(vout->task.output.format) == YUV_CS ?
+ UYVY_BLACK : RGB_BLACK;
+ if (IS_PLANAR_PIXEL_FORMAT(vout->task.output.format)) {
+ size = display_buf_size * 8 /
+ fmt_to_bpp(vout->task.output.format);
+ memset(fbi->screen_base, Y_BLACK, size);
+ memset(fbi->screen_base + size, UV_BLACK,
+ display_buf_size - size);
+ } else {
+ pixel = (u32 *)fbi->screen_base;
+ for (i = 0; i < ((display_buf_size * fb_num) >> 2); i++)
+ *pixel++ = color;
+ }
+ console_lock();
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ ret = fb_blank(fbi, FB_BLANK_UNBLANK);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+ vout->release = false;
+
+ return ret;
+err:
+ for (j = i - 1; j >= 0; j--) {
+ buf = &vout->vdoa_output[j];
+ if (buf->vaddr)
+ free_dma_buf(vout, buf);
+ }
+ return ret;
+}
+
+static inline void wait_for_vsync(struct mxc_vout_output *vout)
+{
+ struct fb_info *fbi = vout->fbi;
+ mm_segment_t old_fs;
+
+ if (fbi->fbops->fb_ioctl) {
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fbi->fbops->fb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC,
+ (unsigned long)NULL);
+ set_fs(old_fs);
+ }
+
+ return;
+}
+
+static void release_disp_output(struct mxc_vout_output *vout)
+{
+ struct fb_info *fbi = vout->fbi;
+ struct mxcfb_pos pos;
+
+ if (vout->release)
+ return;
+ console_lock();
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_blank(fbi, FB_BLANK_POWERDOWN);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+
+ /* restore pos to 0,0 avoid fb pan display hang? */
+ pos.x = 0;
+ pos.y = 0;
+ set_window_position(vout, &pos);
+
+ if (get_ipu_channel(fbi) == MEM_BG_SYNC) {
+ console_lock();
+ fbi->fix.smem_start = vout->disp_bufs[0];
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_blank(fbi, FB_BLANK_UNBLANK);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+
+ }
+
+ vout->release = true;
+}
+
+static int mxc_vidioc_streamon(struct file *file, void *fh,
+ enum v4l2_buf_type i)
+{
+ struct mxc_vout_output *vout = fh;
+ struct videobuf_queue *q = &vout->vbq;
+ int ret;
+
+ if (q->streaming) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "video output already run\n");
+ ret = -EBUSY;
+ goto done;
+ }
+
+ if (deinterlace_3_field(vout) && list_is_singular(&q->stream)) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "deinterlacing: need queue 2 frame before streamon\n");
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = config_disp_output(vout);
+ if (ret < 0) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "Config display output failed\n");
+ goto done;
+ }
+
+ hrtimer_init(&vout->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+ vout->timer.function = mxc_vout_timer_handler;
+ vout->timer_stop = true;
+ vout->frame_count = 0;
+ vout->vdi_frame_cnt = 0;
+
+ vout->start_ktime = hrtimer_cb_get_time(&vout->timer);
+
+ vout->pre1_vb = NULL;
+ vout->pre2_vb = NULL;
+
+ ret = videobuf_streamon(q);
+done:
+ return ret;
+}
+
+static int mxc_vidioc_streamoff(struct file *file, void *fh,
+ enum v4l2_buf_type i)
+{
+ struct mxc_vout_output *vout = fh;
+ struct videobuf_queue *q = &vout->vbq;
+ int ret = 0;
+
+ if (q->streaming) {
+ flush_workqueue(vout->v4l_wq);
+
+ hrtimer_cancel(&vout->timer);
+
+ /*
+ * Wait for 2 vsyncs to make sure
+ * frames are drained on triple
+ * buffer.
+ */
+ wait_for_vsync(vout);
+ wait_for_vsync(vout);
+
+ release_disp_output(vout);
+
+ ret = videobuf_streamoff(&vout->vbq);
+ }
+ INIT_LIST_HEAD(&vout->queue_list);
+ INIT_LIST_HEAD(&vout->active_list);
+
+ return ret;
+}
+
+static const struct v4l2_ioctl_ops mxc_vout_ioctl_ops = {
+ .vidioc_querycap = mxc_vidioc_querycap,
+ .vidioc_enum_fmt_vid_out = mxc_vidioc_enum_fmt_vid_out,
+ .vidioc_g_fmt_vid_out = mxc_vidioc_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = mxc_vidioc_s_fmt_vid_out,
+ .vidioc_cropcap = mxc_vidioc_cropcap,
+ .vidioc_g_crop = mxc_vidioc_g_crop,
+ .vidioc_s_crop = mxc_vidioc_s_crop,
+ .vidioc_queryctrl = mxc_vidioc_queryctrl,
+ .vidioc_g_ctrl = mxc_vidioc_g_ctrl,
+ .vidioc_s_ctrl = mxc_vidioc_s_ctrl,
+ .vidioc_reqbufs = mxc_vidioc_reqbufs,
+ .vidioc_querybuf = mxc_vidioc_querybuf,
+ .vidioc_qbuf = mxc_vidioc_qbuf,
+ .vidioc_dqbuf = mxc_vidioc_dqbuf,
+ .vidioc_streamon = mxc_vidioc_streamon,
+ .vidioc_streamoff = mxc_vidioc_streamoff,
+};
+
+static const struct v4l2_file_operations mxc_vout_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = mxc_vout_ioctl,
+ .mmap = mxc_vout_mmap,
+ .open = mxc_vout_open,
+ .release = mxc_vout_release,
+};
+
+static struct video_device mxc_vout_template = {
+ .name = "MXC Video Output",
+ .fops = &mxc_vout_fops,
+ .ioctl_ops = &mxc_vout_ioctl_ops,
+ .release = video_device_release,
+};
+
+static struct videobuf_queue_ops mxc_vout_vbq_ops = {
+ .buf_setup = mxc_vout_buffer_setup,
+ .buf_prepare = mxc_vout_buffer_prepare,
+ .buf_release = mxc_vout_buffer_release,
+ .buf_queue = mxc_vout_buffer_queue,
+};
+
+static void mxc_vout_free_output(struct mxc_vout_dev *dev)
+{
+ int i;
+ int j;
+ struct mxc_vout_output *vout;
+ struct video_device *vfd;
+
+ for (i = 0; i < dev->out_num; i++) {
+ vout = dev->out[i];
+ vfd = vout->vfd;
+ if (vout->vdoa_work.vaddr)
+ free_dma_buf(vout, &vout->vdoa_work);
+ for (j = 0; j < VDOA_FB_BUFS; j++) {
+ if (vout->vdoa_output[j].vaddr)
+ free_dma_buf(vout, &vout->vdoa_output[j]);
+ }
+ if (vfd) {
+ if (!video_is_registered(vfd))
+ video_device_release(vfd);
+ else
+ video_unregister_device(vfd);
+ }
+ kfree(vout);
+ }
+}
+
+static int mxc_vout_setup_output(struct mxc_vout_dev *dev)
+{
+ struct videobuf_queue *q;
+ struct fb_info *fbi;
+ struct mxc_vout_output *vout;
+ int i, ret = 0;
+
+ update_display_setting();
+
+ /* all output/overlay based on fb */
+ for (i = 0; i < num_registered_fb; i++) {
+ fbi = registered_fb[i];
+
+ vout = kzalloc(sizeof(struct mxc_vout_output), GFP_KERNEL);
+ if (!vout) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ dev->out[dev->out_num] = vout;
+ dev->out_num++;
+
+ vout->fbi = fbi;
+ vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ vout->vfd = video_device_alloc();
+ if (!vout->vfd) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ *vout->vfd = mxc_vout_template;
+ vout->vfd->v4l2_dev = &dev->v4l2_dev;
+ vout->vfd->lock = &vout->mutex;
+ vout->vfd->vfl_dir = VFL_DIR_TX;
+
+ mutex_init(&vout->mutex);
+ mutex_init(&vout->task_lock);
+ mutex_init(&vout->accs_lock);
+
+ strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name));
+
+ video_set_drvdata(vout->vfd, vout);
+
+ if (video_register_device(vout->vfd,
+ VFL_TYPE_GRABBER, video_nr + i) < 0) {
+ ret = -ENODEV;
+ break;
+ }
+
+ q = &vout->vbq;
+ q->dev = dev->dev;
+ spin_lock_init(&vout->vbq_lock);
+ videobuf_queue_dma_contig_init(q, &mxc_vout_vbq_ops, q->dev,
+ &vout->vbq_lock, vout->type, V4L2_FIELD_NONE,
+ sizeof(struct videobuf_buffer), vout, NULL);
+
+ v4l2_info(vout->vfd->v4l2_dev, "V4L2 device registered as %s\n",
+ video_device_node_name(vout->vfd));
+
+ }
+
+ return ret;
+}
+
+static int mxc_vout_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct mxc_vout_dev *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->dev = &pdev->dev;
+ dev->dev->dma_mask = kmalloc(sizeof(*dev->dev->dma_mask), GFP_KERNEL);
+ *dev->dev->dma_mask = DMA_BIT_MASK(32);
+ dev->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ ret = v4l2_device_register(dev->dev, &dev->v4l2_dev);
+ if (ret) {
+ dev_err(dev->dev, "v4l2_device_register failed\n");
+ goto free_dev;
+ }
+
+ ret = mxc_vout_setup_output(dev);
+ if (ret < 0)
+ goto rel_vdev;
+
+ return 0;
+
+rel_vdev:
+ mxc_vout_free_output(dev);
+ v4l2_device_unregister(&dev->v4l2_dev);
+free_dev:
+ kfree(dev);
+ return ret;
+}
+
+static int mxc_vout_remove(struct platform_device *pdev)
+{
+ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+ struct mxc_vout_dev *dev = container_of(v4l2_dev, struct
+ mxc_vout_dev, v4l2_dev);
+
+ mxc_vout_free_output(dev);
+ v4l2_device_unregister(v4l2_dev);
+ kfree(dev);
+ return 0;
+}
+
+static const struct of_device_id mxc_v4l2_dt_ids[] = {
+ { .compatible = "fsl,mxc_v4l2_output", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver mxc_vout_driver = {
+ .driver = {
+ .name = "mxc_v4l2_output",
+ .of_match_table = mxc_v4l2_dt_ids,
+ },
+ .probe = mxc_vout_probe,
+ .remove = mxc_vout_remove,
+};
+
+static int __init mxc_vout_init(void)
+{
+ if (platform_driver_register(&mxc_vout_driver) != 0) {
+ printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void mxc_vout_cleanup(void)
+{
+ platform_driver_unregister(&mxc_vout_driver);
+}
+
+module_init(mxc_vout_init);
+module_exit(mxc_vout_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("V4L2-driver for MXC video output");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/subdev/Kconfig b/drivers/media/platform/mxc/subdev/Kconfig
new file mode 100644
index 000000000000..b8e0ebb1a5e5
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/Kconfig
@@ -0,0 +1,38 @@
+if VIDEO_MXC_CAPTURE
+
+config VIDEO_MXC_CSI_CAMERA
+ tristate "CSI camera support"
+ depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
+ ---help---
+ This is the video4linux2 capture driver based on CSI module.
+
+config MXC_CAMERA_OV5640
+ tristate "OmniVision ov5640 camera support"
+ depends on VIDEO_MXC_CAPTURE && I2C
+ ---help---
+ If you plan to use the ov5640 Camera with your MXC system, say Y here.
+
+config MXC_VADC
+ tristate "mxc VADC support"
+ depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
+ ---help---
+ If you plan to use the VADC with your MXC system, say Y here.
+
+config MXC_MIPI_CSI
+ tristate "mxc mipi csi driver"
+ depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
+ ---help---
+ This is a V4L2 driver for i.MX7D SoC MIPI-CSI2 receiver devices.
+
+config MXC_CAMERA_OV5640_MIPI
+ tristate "OmniVision ov5640 camera support using mipi"
+ depends on MXC_MIPI_CSI && I2C
+ ---help---
+ If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here.
+
+config MXC_CAMERA_OV5647_MIPI
+ tristate "OmniVision ov5647 camera support using mipi"
+ depends on MXC_MIPI_CSI && I2C
+ ---help---
+ If you plan to use the ov5647 Camera with mipi interface in your MXC system, say Y here.
+endif
diff --git a/drivers/media/platform/mxc/subdev/Makefile b/drivers/media/platform/mxc/subdev/Makefile
new file mode 100644
index 000000000000..25b0d64dff8f
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/Makefile
@@ -0,0 +1,14 @@
+#Makefile for mxc csi driver
+
+obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += mx6s_capture.o
+obj-$(CONFIG_MXC_VADC) += mxc_vadc.o
+obj-$(CONFIG_MXC_MIPI_CSI) += mxc_mipi_csi.o
+
+ov5640_camera-objs := ov5640.o
+obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera.o
+
+ov5640_camera_mipi-objs := ov5640_mipi.o
+obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi.o
+
+ov5647_camera_mipi-objs := ov5647_mipi.o
+obj-$(CONFIG_MXC_CAMERA_OV5647_MIPI) += ov5647_camera_mipi.o
diff --git a/drivers/media/platform/mxc/subdev/mx6s_capture.c b/drivers/media/platform/mxc/subdev/mx6s_capture.c
new file mode 100644
index 000000000000..63eb54944828
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/mx6s_capture.c
@@ -0,0 +1,1970 @@
+/*
+ * Copyright (C) 2014-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 mx6s_csi.c
+ *
+ * @brief mx6sx CMOS Sensor interface functions
+ *
+ * @ingroup CSI
+ */
+#include <asm/dma.h>
+#include <linux/busfreq-imx.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/gcd.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/media-bus-format.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-of.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define MX6S_CAM_DRV_NAME "mx6s-csi"
+#define MX6S_CAM_VERSION "0.0.1"
+#define MX6S_CAM_DRIVER_DESCRIPTION "i.MX6S_CSI"
+
+#define MAX_VIDEO_MEM 64
+
+/* reset values */
+#define CSICR1_RESET_VAL 0x40000800
+#define CSICR2_RESET_VAL 0x0
+#define CSICR3_RESET_VAL 0x0
+
+/* csi control reg 1 */
+#define BIT_SWAP16_EN (0x1 << 31)
+#define BIT_EXT_VSYNC (0x1 << 30)
+#define BIT_EOF_INT_EN (0x1 << 29)
+#define BIT_PRP_IF_EN (0x1 << 28)
+#define BIT_CCIR_MODE (0x1 << 27)
+#define BIT_COF_INT_EN (0x1 << 26)
+#define BIT_SF_OR_INTEN (0x1 << 25)
+#define BIT_RF_OR_INTEN (0x1 << 24)
+#define BIT_SFF_DMA_DONE_INTEN (0x1 << 22)
+#define BIT_STATFF_INTEN (0x1 << 21)
+#define BIT_FB2_DMA_DONE_INTEN (0x1 << 20)
+#define BIT_FB1_DMA_DONE_INTEN (0x1 << 19)
+#define BIT_RXFF_INTEN (0x1 << 18)
+#define BIT_SOF_POL (0x1 << 17)
+#define BIT_SOF_INTEN (0x1 << 16)
+#define BIT_MCLKDIV (0xF << 12)
+#define BIT_HSYNC_POL (0x1 << 11)
+#define BIT_CCIR_EN (0x1 << 10)
+#define BIT_MCLKEN (0x1 << 9)
+#define BIT_FCC (0x1 << 8)
+#define BIT_PACK_DIR (0x1 << 7)
+#define BIT_CLR_STATFIFO (0x1 << 6)
+#define BIT_CLR_RXFIFO (0x1 << 5)
+#define BIT_GCLK_MODE (0x1 << 4)
+#define BIT_INV_DATA (0x1 << 3)
+#define BIT_INV_PCLK (0x1 << 2)
+#define BIT_REDGE (0x1 << 1)
+#define BIT_PIXEL_BIT (0x1 << 0)
+
+#define SHIFT_MCLKDIV 12
+
+/* control reg 3 */
+#define BIT_FRMCNT (0xFFFF << 16)
+#define BIT_FRMCNT_RST (0x1 << 15)
+#define BIT_DMA_REFLASH_RFF (0x1 << 14)
+#define BIT_DMA_REFLASH_SFF (0x1 << 13)
+#define BIT_DMA_REQ_EN_RFF (0x1 << 12)
+#define BIT_DMA_REQ_EN_SFF (0x1 << 11)
+#define BIT_STATFF_LEVEL (0x7 << 8)
+#define BIT_HRESP_ERR_EN (0x1 << 7)
+#define BIT_RXFF_LEVEL (0x7 << 4)
+#define BIT_TWO_8BIT_SENSOR (0x1 << 3)
+#define BIT_ZERO_PACK_EN (0x1 << 2)
+#define BIT_ECC_INT_EN (0x1 << 1)
+#define BIT_ECC_AUTO_EN (0x1 << 0)
+
+#define SHIFT_FRMCNT 16
+#define SHIFT_RXFIFO_LEVEL 4
+
+/* csi status reg */
+#define BIT_ADDR_CH_ERR_INT (0x1 << 28)
+#define BIT_FIELD0_INT (0x1 << 27)
+#define BIT_FIELD1_INT (0x1 << 26)
+#define BIT_SFF_OR_INT (0x1 << 25)
+#define BIT_RFF_OR_INT (0x1 << 24)
+#define BIT_DMA_TSF_DONE_SFF (0x1 << 22)
+#define BIT_STATFF_INT (0x1 << 21)
+#define BIT_DMA_TSF_DONE_FB2 (0x1 << 20)
+#define BIT_DMA_TSF_DONE_FB1 (0x1 << 19)
+#define BIT_RXFF_INT (0x1 << 18)
+#define BIT_EOF_INT (0x1 << 17)
+#define BIT_SOF_INT (0x1 << 16)
+#define BIT_F2_INT (0x1 << 15)
+#define BIT_F1_INT (0x1 << 14)
+#define BIT_COF_INT (0x1 << 13)
+#define BIT_HRESP_ERR_INT (0x1 << 7)
+#define BIT_ECC_INT (0x1 << 1)
+#define BIT_DRDY (0x1 << 0)
+
+/* csi control reg 18 */
+#define BIT_CSI_ENABLE (0x1 << 31)
+#define BIT_MIPI_DATA_FORMAT_RAW8 (0x2a << 25)
+#define BIT_MIPI_DATA_FORMAT_RAW10 (0x2b << 25)
+#define BIT_MIPI_DATA_FORMAT_YUV422_8B (0x1e << 25)
+#define BIT_MIPI_DATA_FORMAT_MASK (0x3F << 25)
+#define BIT_MIPI_DATA_FORMAT_OFFSET 25
+#define BIT_DATA_FROM_MIPI (0x1 << 22)
+#define BIT_MIPI_YU_SWAP (0x1 << 21)
+#define BIT_MIPI_DOUBLE_CMPNT (0x1 << 20)
+#define BIT_BASEADDR_CHG_ERR_EN (0x1 << 9)
+#define BIT_BASEADDR_SWITCH_SEL (0x1 << 5)
+#define BIT_BASEADDR_SWITCH_EN (0x1 << 4)
+#define BIT_PARALLEL24_EN (0x1 << 3)
+#define BIT_DEINTERLACE_EN (0x1 << 2)
+#define BIT_TVDECODER_IN_EN (0x1 << 1)
+#define BIT_NTSC_EN (0x1 << 0)
+
+#define CSI_MCLK_VF 1
+#define CSI_MCLK_ENC 2
+#define CSI_MCLK_RAW 4
+#define CSI_MCLK_I2C 8
+
+#define CSI_CSICR1 0x0
+#define CSI_CSICR2 0x4
+#define CSI_CSICR3 0x8
+#define CSI_STATFIFO 0xC
+#define CSI_CSIRXFIFO 0x10
+#define CSI_CSIRXCNT 0x14
+#define CSI_CSISR 0x18
+
+#define CSI_CSIDBG 0x1C
+#define CSI_CSIDMASA_STATFIFO 0x20
+#define CSI_CSIDMATS_STATFIFO 0x24
+#define CSI_CSIDMASA_FB1 0x28
+#define CSI_CSIDMASA_FB2 0x2C
+#define CSI_CSIFBUF_PARA 0x30
+#define CSI_CSIIMAG_PARA 0x34
+
+#define CSI_CSICR18 0x48
+#define CSI_CSICR19 0x4c
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+#define MX6SX_MAX_SENSORS 1
+
+struct csi_signal_cfg_t {
+ unsigned data_width:3;
+ unsigned clk_mode:2;
+ unsigned ext_vsync:1;
+ unsigned Vsync_pol:1;
+ unsigned Hsync_pol:1;
+ unsigned pixclk_pol:1;
+ unsigned data_pol:1;
+ unsigned sens_clksrc:1;
+};
+
+struct csi_config_t {
+ /* control reg 1 */
+ unsigned int swap16_en:1;
+ unsigned int ext_vsync:1;
+ unsigned int eof_int_en:1;
+ unsigned int prp_if_en:1;
+ unsigned int ccir_mode:1;
+ unsigned int cof_int_en:1;
+ unsigned int sf_or_inten:1;
+ unsigned int rf_or_inten:1;
+ unsigned int sff_dma_done_inten:1;
+ unsigned int statff_inten:1;
+ unsigned int fb2_dma_done_inten:1;
+ unsigned int fb1_dma_done_inten:1;
+ unsigned int rxff_inten:1;
+ unsigned int sof_pol:1;
+ unsigned int sof_inten:1;
+ unsigned int mclkdiv:4;
+ unsigned int hsync_pol:1;
+ unsigned int ccir_en:1;
+ unsigned int mclken:1;
+ unsigned int fcc:1;
+ unsigned int pack_dir:1;
+ unsigned int gclk_mode:1;
+ unsigned int inv_data:1;
+ unsigned int inv_pclk:1;
+ unsigned int redge:1;
+ unsigned int pixel_bit:1;
+
+ /* control reg 3 */
+ unsigned int frmcnt:16;
+ unsigned int frame_reset:1;
+ unsigned int dma_reflash_rff:1;
+ unsigned int dma_reflash_sff:1;
+ unsigned int dma_req_en_rff:1;
+ unsigned int dma_req_en_sff:1;
+ unsigned int statff_level:3;
+ unsigned int hresp_err_en:1;
+ unsigned int rxff_level:3;
+ unsigned int two_8bit_sensor:1;
+ unsigned int zero_pack_en:1;
+ unsigned int ecc_int_en:1;
+ unsigned int ecc_auto_en:1;
+ /* fifo counter */
+ unsigned int rxcnt;
+};
+
+/*
+ * Basic structures
+ */
+struct mx6s_fmt {
+ char name[32];
+ u32 fourcc; /* v4l2 format id */
+ u32 pixelformat;
+ u32 mbus_code;
+ int bpp;
+};
+
+static struct mx6s_fmt formats[] = {
+ {
+ .name = "UYVY-16",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .bpp = 2,
+ }, {
+ .name = "YUYV-16",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .bpp = 2,
+ }, {
+ .name = "YUV32 (X-Y-U-V)",
+ .fourcc = V4L2_PIX_FMT_YUV32,
+ .pixelformat = V4L2_PIX_FMT_YUV32,
+ .mbus_code = MEDIA_BUS_FMT_AYUV8_1X32,
+ .bpp = 4,
+ }, {
+ .name = "RAWRGB8 (SBGGR8)",
+ .fourcc = V4L2_PIX_FMT_SBGGR8,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .bpp = 1,
+ }
+};
+
+struct mx6s_buf_internal {
+ struct list_head queue;
+ int bufnum;
+ bool discard;
+};
+
+/* buffer for one video frame */
+struct mx6s_buffer {
+ /* common v4l buffer stuff -- must be first */
+ struct vb2_v4l2_buffer vb;
+ struct mx6s_buf_internal internal;
+};
+
+struct mx6s_csi_mux {
+ struct regmap *gpr;
+ u8 req_gpr;
+ u8 req_bit;
+};
+
+struct mx6s_csi_dev {
+ struct device *dev;
+ struct video_device *vdev;
+ struct v4l2_subdev *sd;
+ struct v4l2_device v4l2_dev;
+
+ struct vb2_queue vb2_vidq;
+ struct v4l2_ctrl_handler ctrl_handler;
+
+ struct mutex lock;
+ spinlock_t slock;
+
+ /* clock */
+ struct clk *clk_disp_axi;
+ struct clk *clk_disp_dcic;
+ struct clk *clk_csi_mclk;
+
+ void __iomem *regbase;
+ int irq;
+
+ u32 type;
+ u32 bytesperline;
+ v4l2_std_id std;
+ struct mx6s_fmt *fmt;
+ struct v4l2_pix_format pix;
+ u32 mbus_code;
+
+ unsigned int frame_count;
+
+ struct list_head capture;
+ struct list_head active_bufs;
+ struct list_head discard;
+
+ void *discard_buffer;
+ dma_addr_t discard_buffer_dma;
+ size_t discard_size;
+ struct mx6s_buf_internal buf_discard[2];
+
+ struct v4l2_async_subdev asd;
+ struct v4l2_async_notifier subdev_notifier;
+ struct v4l2_async_subdev *async_subdevs[2];
+
+ bool csi_mux_mipi;
+ const bool *rx_fifo_rst;
+ struct mx6s_csi_mux csi_mux;
+};
+
+static const struct of_device_id mx6s_csi_dt_ids[];
+
+static inline int csi_read(struct mx6s_csi_dev *csi, unsigned int offset)
+{
+ return __raw_readl(csi->regbase + offset);
+}
+static inline void csi_write(struct mx6s_csi_dev *csi, unsigned int value,
+ unsigned int offset)
+{
+ __raw_writel(value, csi->regbase + offset);
+}
+
+static inline struct mx6s_csi_dev
+ *notifier_to_mx6s_dev(struct v4l2_async_notifier *n)
+{
+ return container_of(n, struct mx6s_csi_dev, subdev_notifier);
+}
+
+struct mx6s_fmt *format_by_fourcc(int fourcc)
+{
+ int i;
+
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (formats[i].pixelformat == fourcc)
+ return formats + i;
+ }
+
+ pr_err("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
+ return NULL;
+}
+
+struct mx6s_fmt *format_by_mbus(u32 code)
+{
+ int i;
+
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (formats[i].mbus_code == code)
+ return formats + i;
+ }
+
+ pr_err("unknown mbus:0x%x\n", code);
+ return NULL;
+}
+
+static struct mx6s_buffer *mx6s_ibuf_to_buf(struct mx6s_buf_internal *int_buf)
+{
+ return container_of(int_buf, struct mx6s_buffer, internal);
+}
+
+void csi_clk_enable(struct mx6s_csi_dev *csi_dev)
+{
+ clk_prepare_enable(csi_dev->clk_disp_axi);
+ clk_prepare_enable(csi_dev->clk_disp_dcic);
+ clk_prepare_enable(csi_dev->clk_csi_mclk);
+}
+
+void csi_clk_disable(struct mx6s_csi_dev *csi_dev)
+{
+ clk_disable_unprepare(csi_dev->clk_csi_mclk);
+ clk_disable_unprepare(csi_dev->clk_disp_dcic);
+ clk_disable_unprepare(csi_dev->clk_disp_axi);
+}
+
+static void csihw_reset(struct mx6s_csi_dev *csi_dev)
+{
+ __raw_writel(__raw_readl(csi_dev->regbase + CSI_CSICR3)
+ | BIT_FRMCNT_RST,
+ csi_dev->regbase + CSI_CSICR3);
+
+ __raw_writel(CSICR1_RESET_VAL, csi_dev->regbase + CSI_CSICR1);
+ __raw_writel(CSICR2_RESET_VAL, csi_dev->regbase + CSI_CSICR2);
+ __raw_writel(CSICR3_RESET_VAL, csi_dev->regbase + CSI_CSICR3);
+}
+
+static void csisw_reset(struct mx6s_csi_dev *csi_dev)
+{
+ int cr1, cr3, cr18, isr;
+
+ /* Disable csi */
+ cr18 = csi_read(csi_dev, CSI_CSICR18);
+ cr18 &= ~BIT_CSI_ENABLE;
+ csi_write(csi_dev, cr18, CSI_CSICR18);
+
+ /* Clear RX FIFO */
+ cr1 = csi_read(csi_dev, CSI_CSICR1);
+ csi_write(csi_dev, cr1 & ~BIT_FCC, CSI_CSICR1);
+ cr1 = csi_read(csi_dev, CSI_CSICR1);
+ csi_write(csi_dev, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1);
+
+ /* DMA reflash */
+ cr3 = csi_read(csi_dev, CSI_CSICR3);
+ cr3 |= BIT_DMA_REFLASH_RFF | BIT_FRMCNT_RST;
+ csi_write(csi_dev, cr3, CSI_CSICR3);
+
+ msleep(2);
+
+ cr1 = csi_read(csi_dev, CSI_CSICR1);
+ csi_write(csi_dev, cr1 | BIT_FCC, CSI_CSICR1);
+
+ isr = csi_read(csi_dev, CSI_CSISR);
+ csi_write(csi_dev, isr, CSI_CSISR);
+
+ /* Ensable csi */
+ cr18 |= BIT_CSI_ENABLE;
+ csi_write(csi_dev, cr18, CSI_CSICR18);
+}
+
+/*!
+ * csi_init_interface
+ * Init csi interface
+ */
+static void csi_init_interface(struct mx6s_csi_dev *csi_dev)
+{
+ unsigned int val = 0;
+ unsigned int imag_para;
+
+ val |= BIT_SOF_POL;
+ val |= BIT_REDGE;
+ val |= BIT_GCLK_MODE;
+ val |= BIT_HSYNC_POL;
+ val |= BIT_FCC;
+ val |= 1 << SHIFT_MCLKDIV;
+ val |= BIT_MCLKEN;
+ __raw_writel(val, csi_dev->regbase + CSI_CSICR1);
+
+ imag_para = (640 << 16) | 960;
+ __raw_writel(imag_para, csi_dev->regbase + CSI_CSIIMAG_PARA);
+
+ val = BIT_DMA_REFLASH_RFF;
+ __raw_writel(val, csi_dev->regbase + CSI_CSICR3);
+}
+
+static void csi_enable_int(struct mx6s_csi_dev *csi_dev, int arg)
+{
+ unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
+
+ cr1 |= BIT_SOF_INTEN;
+ cr1 |= BIT_RFF_OR_INT;
+ if (arg == 1) {
+ /* still capture needs DMA intterrupt */
+ cr1 |= BIT_FB1_DMA_DONE_INTEN;
+ cr1 |= BIT_FB2_DMA_DONE_INTEN;
+ }
+ __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
+}
+
+static void csi_disable_int(struct mx6s_csi_dev *csi_dev)
+{
+ unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
+
+ cr1 &= ~BIT_SOF_INTEN;
+ cr1 &= ~BIT_RFF_OR_INT;
+ cr1 &= ~BIT_FB1_DMA_DONE_INTEN;
+ cr1 &= ~BIT_FB2_DMA_DONE_INTEN;
+ __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
+}
+
+static void csi_enable(struct mx6s_csi_dev *csi_dev, int arg)
+{
+ unsigned long cr = __raw_readl(csi_dev->regbase + CSI_CSICR18);
+
+ if (arg == 1)
+ cr |= BIT_CSI_ENABLE;
+ else
+ cr &= ~BIT_CSI_ENABLE;
+ __raw_writel(cr, csi_dev->regbase + CSI_CSICR18);
+}
+
+static void csi_buf_stride_set(struct mx6s_csi_dev *csi_dev, u32 stride)
+{
+ __raw_writel(stride, csi_dev->regbase + CSI_CSIFBUF_PARA);
+}
+
+static void csi_deinterlace_enable(struct mx6s_csi_dev *csi_dev, bool enable)
+{
+ unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
+
+ if (enable == true)
+ cr18 |= BIT_DEINTERLACE_EN;
+ else
+ cr18 &= ~BIT_DEINTERLACE_EN;
+
+ __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
+}
+
+static void csi_deinterlace_mode(struct mx6s_csi_dev *csi_dev, int mode)
+{
+ unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
+
+ if (mode == V4L2_STD_NTSC)
+ cr18 |= BIT_NTSC_EN;
+ else
+ cr18 &= ~BIT_NTSC_EN;
+
+ __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
+}
+
+static void csi_tvdec_enable(struct mx6s_csi_dev *csi_dev, bool enable)
+{
+ unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);
+ unsigned long cr1 = __raw_readl(csi_dev->regbase + CSI_CSICR1);
+
+ if (enable == true) {
+ cr18 |= (BIT_TVDECODER_IN_EN |
+ BIT_BASEADDR_SWITCH_EN |
+ BIT_BASEADDR_SWITCH_SEL |
+ BIT_BASEADDR_CHG_ERR_EN);
+ cr1 |= BIT_CCIR_MODE;
+ cr1 &= ~(BIT_SOF_POL | BIT_REDGE);
+ } else {
+ cr18 &= ~(BIT_TVDECODER_IN_EN |
+ BIT_BASEADDR_SWITCH_EN |
+ BIT_BASEADDR_SWITCH_SEL |
+ BIT_BASEADDR_CHG_ERR_EN);
+ cr1 &= ~BIT_CCIR_MODE;
+ cr1 |= BIT_SOF_POL | BIT_REDGE;
+ }
+
+ __raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
+ __raw_writel(cr1, csi_dev->regbase + CSI_CSICR1);
+}
+
+static void csi_dmareq_rff_enable(struct mx6s_csi_dev *csi_dev)
+{
+ unsigned long cr3 = __raw_readl(csi_dev->regbase + CSI_CSICR3);
+ unsigned long cr2 = __raw_readl(csi_dev->regbase + CSI_CSICR2);
+
+ /* Burst Type of DMA Transfer from RxFIFO. INCR16 */
+ cr2 |= 0xC0000000;
+
+ cr3 |= BIT_DMA_REQ_EN_RFF;
+ cr3 |= BIT_HRESP_ERR_EN;
+ cr3 &= ~BIT_RXFF_LEVEL;
+ cr3 |= 0x2 << 4;
+
+ __raw_writel(cr3, csi_dev->regbase + CSI_CSICR3);
+ __raw_writel(cr2, csi_dev->regbase + CSI_CSICR2);
+}
+
+static void csi_dmareq_rff_disable(struct mx6s_csi_dev *csi_dev)
+{
+ unsigned long cr3 = __raw_readl(csi_dev->regbase + CSI_CSICR3);
+
+ cr3 &= ~BIT_DMA_REQ_EN_RFF;
+ cr3 &= ~BIT_HRESP_ERR_EN;
+ __raw_writel(cr3, csi_dev->regbase + CSI_CSICR3);
+}
+
+static void csi_set_imagpara(struct mx6s_csi_dev *csi,
+ int width, int height)
+{
+ int imag_para = 0;
+ unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3);
+
+ imag_para = (width << 16) | height;
+ __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA);
+
+ /* reflash the embeded DMA controller */
+ __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3);
+}
+
+static void csi_error_recovery(struct mx6s_csi_dev *csi_dev)
+{
+ u32 cr1, cr3, cr18;
+ /* software reset */
+
+ /* Disable csi */
+ cr18 = csi_read(csi_dev, CSI_CSICR18);
+ cr18 &= ~BIT_CSI_ENABLE;
+ csi_write(csi_dev, cr18, CSI_CSICR18);
+
+ /* Clear RX FIFO */
+ cr1 = csi_read(csi_dev, CSI_CSICR1);
+ csi_write(csi_dev, cr1 & ~BIT_FCC, CSI_CSICR1);
+ cr1 = csi_read(csi_dev, CSI_CSICR1);
+ csi_write(csi_dev, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1);
+
+ cr1 = csi_read(csi_dev, CSI_CSICR1);
+ csi_write(csi_dev, cr1 | BIT_FCC, CSI_CSICR1);
+
+ /* DMA reflash */
+ cr3 = csi_read(csi_dev, CSI_CSICR3);
+ cr3 |= BIT_DMA_REFLASH_RFF;
+ csi_write(csi_dev, cr3, CSI_CSICR3);
+
+ /* Ensable csi */
+ cr18 |= BIT_CSI_ENABLE;
+ csi_write(csi_dev, cr18, CSI_CSICR18);
+}
+
+/*
+ * Videobuf operations
+ */
+static int mx6s_videobuf_setup(struct vb2_queue *vq,
+ unsigned int *count, unsigned int *num_planes,
+ unsigned int sizes[], struct device *alloc_devs[])
+{
+ struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
+
+ dev_dbg(csi_dev->dev, "count=%d, size=%d\n", *count, sizes[0]);
+
+ alloc_devs[0] = csi_dev->dev;
+
+ sizes[0] = csi_dev->pix.sizeimage;
+
+ pr_debug("size=%d\n", sizes[0]);
+ if (0 == *count)
+ *count = 32;
+ if (!*num_planes &&
+ sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
+ *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0];
+
+ *num_planes = 1;
+
+ return 0;
+}
+
+static int mx6s_videobuf_prepare(struct vb2_buffer *vb)
+{
+ struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vb->vb2_queue);
+ int ret = 0;
+
+ dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+
+#ifdef DEBUG
+ /*
+ * This can be useful if you want to see if we actually fill
+ * the buffer with something
+ */
+ if (vb2_plane_vaddr(vb, 0))
+ memset((void *)vb2_plane_vaddr(vb, 0),
+ 0xaa, vb2_get_plane_payload(vb, 0));
+#endif
+
+ vb2_set_plane_payload(vb, 0, csi_dev->pix.sizeimage);
+ if (vb2_plane_vaddr(vb, 0) &&
+ vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ return 0;
+
+out:
+ return ret;
+}
+
+static void mx6s_videobuf_queue(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vb->vb2_queue);
+ struct mx6s_buffer *buf = container_of(vbuf, struct mx6s_buffer, vb);
+ unsigned long flags;
+
+ dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+
+ spin_lock_irqsave(&csi_dev->slock, flags);
+
+ list_add_tail(&buf->internal.queue, &csi_dev->capture);
+
+ spin_unlock_irqrestore(&csi_dev->slock, flags);
+}
+
+static void mx6s_update_csi_buf(struct mx6s_csi_dev *csi_dev,
+ unsigned long phys, int bufnum)
+{
+ if (bufnum == 1)
+ csi_write(csi_dev, phys, CSI_CSIDMASA_FB2);
+ else
+ csi_write(csi_dev, phys, CSI_CSIDMASA_FB1);
+}
+
+static void mx6s_csi_init(struct mx6s_csi_dev *csi_dev)
+{
+ csi_clk_enable(csi_dev);
+ csihw_reset(csi_dev);
+ csi_init_interface(csi_dev);
+ csi_dmareq_rff_disable(csi_dev);
+}
+
+static void mx6s_csi_deinit(struct mx6s_csi_dev *csi_dev)
+{
+ csihw_reset(csi_dev);
+ csi_init_interface(csi_dev);
+ csi_dmareq_rff_disable(csi_dev);
+ csi_clk_disable(csi_dev);
+}
+
+static int mx6s_csi_enable(struct mx6s_csi_dev *csi_dev)
+{
+ struct v4l2_pix_format *pix = &csi_dev->pix;
+ unsigned long flags;
+ unsigned long val;
+ int timeout, timeout2;
+
+ csisw_reset(csi_dev);
+
+ if (pix->field == V4L2_FIELD_INTERLACED)
+ csi_tvdec_enable(csi_dev, true);
+
+ /* For mipi csi input only */
+ if (csi_dev->csi_mux_mipi == true) {
+ csi_dmareq_rff_enable(csi_dev);
+ csi_enable_int(csi_dev, 1);
+ csi_enable(csi_dev, 1);
+ return 0;
+ }
+
+ local_irq_save(flags);
+ for (timeout = 10000000; timeout > 0; timeout--) {
+ if (csi_read(csi_dev, CSI_CSISR) & BIT_SOF_INT) {
+ val = csi_read(csi_dev, CSI_CSICR3);
+ csi_write(csi_dev, val | BIT_DMA_REFLASH_RFF,
+ CSI_CSICR3);
+ /* Wait DMA reflash done */
+ for (timeout2 = 1000000; timeout2 > 0; timeout2--) {
+ if (csi_read(csi_dev, CSI_CSICR3) &
+ BIT_DMA_REFLASH_RFF)
+ cpu_relax();
+ else
+ break;
+ }
+ if (timeout2 <= 0) {
+ pr_err("timeout when wait for reflash done.\n");
+ local_irq_restore(flags);
+ return -ETIME;
+ }
+ /* For imx6sl csi, DMA FIFO will auto start when sensor ready to work,
+ * so DMA should enable right after FIFO reset, otherwise dma will lost data
+ * and image will split.
+ */
+ csi_dmareq_rff_enable(csi_dev);
+ csi_enable_int(csi_dev, 1);
+ csi_enable(csi_dev, 1);
+ break;
+ } else
+ cpu_relax();
+ }
+ if (timeout <= 0) {
+ pr_err("timeout when wait for SOF\n");
+ local_irq_restore(flags);
+ return -ETIME;
+ }
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static void mx6s_csi_disable(struct mx6s_csi_dev *csi_dev)
+{
+ struct v4l2_pix_format *pix = &csi_dev->pix;
+
+ csi_dmareq_rff_disable(csi_dev);
+ csi_disable_int(csi_dev);
+
+ /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */
+ csi_write(csi_dev, 0, CSI_CSIDMASA_FB1);
+ csi_write(csi_dev, 0, CSI_CSIDMASA_FB2);
+
+ csi_buf_stride_set(csi_dev, 0);
+
+ if (pix->field == V4L2_FIELD_INTERLACED) {
+ csi_deinterlace_enable(csi_dev, false);
+ csi_tvdec_enable(csi_dev, false);
+ }
+
+ csi_enable(csi_dev, 0);
+}
+
+static int mx6s_configure_csi(struct mx6s_csi_dev *csi_dev)
+{
+ struct v4l2_pix_format *pix = &csi_dev->pix;
+ u32 cr1, cr18;
+ u32 width;
+
+ if (pix->field == V4L2_FIELD_INTERLACED) {
+ csi_deinterlace_enable(csi_dev, true);
+ csi_buf_stride_set(csi_dev, csi_dev->pix.width);
+ csi_deinterlace_mode(csi_dev, csi_dev->std);
+ } else {
+ csi_deinterlace_enable(csi_dev, false);
+ csi_buf_stride_set(csi_dev, 0);
+ }
+
+ switch (csi_dev->fmt->pixelformat) {
+ case V4L2_PIX_FMT_YUV32:
+ case V4L2_PIX_FMT_SBGGR8:
+ width = pix->width;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUYV:
+ if (csi_dev->csi_mux_mipi == true)
+ width = pix->width;
+ else
+ /* For parallel 8-bit sensor input */
+ width = pix->width * 2;
+ break;
+ default:
+ pr_debug(" case not supported\n");
+ return -EINVAL;
+ }
+ csi_set_imagpara(csi_dev, width, pix->height);
+
+ if (csi_dev->csi_mux_mipi == true) {
+ cr1 = csi_read(csi_dev, CSI_CSICR1);
+ cr1 &= ~BIT_GCLK_MODE;
+ csi_write(csi_dev, cr1, CSI_CSICR1);
+
+ cr18 = csi_read(csi_dev, CSI_CSICR18);
+ cr18 &= BIT_MIPI_DATA_FORMAT_MASK;
+ cr18 |= BIT_DATA_FROM_MIPI;
+
+ switch (csi_dev->fmt->pixelformat) {
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUYV:
+ cr18 |= BIT_MIPI_DATA_FORMAT_YUV422_8B;
+ break;
+ case V4L2_PIX_FMT_SBGGR8:
+ cr18 |= BIT_MIPI_DATA_FORMAT_RAW8;
+ break;
+ default:
+ pr_debug(" fmt not supported\n");
+ return -EINVAL;
+ }
+
+ csi_write(csi_dev, cr18, CSI_CSICR18);
+ }
+ return 0;
+}
+
+static int mx6s_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
+ struct vb2_buffer *vb;
+ struct mx6s_buffer *buf;
+ unsigned long phys;
+ unsigned long flags;
+
+ if (count < 2)
+ return -ENOBUFS;
+
+ /*
+ * I didn't manage to properly enable/disable
+ * a per frame basis during running transfers,
+ * thus we allocate a buffer here and use it to
+ * discard frames when no buffer is available.
+ * Feel free to work on this ;)
+ */
+ csi_dev->discard_size = csi_dev->pix.sizeimage;
+ csi_dev->discard_buffer = dma_alloc_coherent(csi_dev->v4l2_dev.dev,
+ PAGE_ALIGN(csi_dev->discard_size),
+ &csi_dev->discard_buffer_dma,
+ GFP_DMA | GFP_KERNEL);
+ if (!csi_dev->discard_buffer)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&csi_dev->slock, flags);
+
+ csi_dev->buf_discard[0].discard = true;
+ list_add_tail(&csi_dev->buf_discard[0].queue,
+ &csi_dev->discard);
+
+ csi_dev->buf_discard[1].discard = true;
+ list_add_tail(&csi_dev->buf_discard[1].queue,
+ &csi_dev->discard);
+
+ /* csi buf 0 */
+ buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
+ internal.queue);
+ buf->internal.bufnum = 0;
+ vb = &buf->vb.vb2_buf;
+ vb->state = VB2_BUF_STATE_ACTIVE;
+
+ phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+ mx6s_update_csi_buf(csi_dev, phys, buf->internal.bufnum);
+ list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
+
+ /* csi buf 1 */
+ buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
+ internal.queue);
+ buf->internal.bufnum = 1;
+ vb = &buf->vb.vb2_buf;
+ vb->state = VB2_BUF_STATE_ACTIVE;
+
+ phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+ mx6s_update_csi_buf(csi_dev, phys, buf->internal.bufnum);
+ list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
+
+ spin_unlock_irqrestore(&csi_dev->slock, flags);
+
+ return mx6s_csi_enable(csi_dev);
+}
+
+static void mx6s_stop_streaming(struct vb2_queue *vq)
+{
+ struct mx6s_csi_dev *csi_dev = vb2_get_drv_priv(vq);
+ unsigned long flags;
+ struct mx6s_buffer *buf, *tmp;
+ void *b;
+
+ mx6s_csi_disable(csi_dev);
+
+ spin_lock_irqsave(&csi_dev->slock, flags);
+
+ list_for_each_entry_safe(buf, tmp,
+ &csi_dev->active_bufs, internal.queue) {
+ list_del_init(&buf->internal.queue);
+ if (buf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ }
+
+ list_for_each_entry_safe(buf, tmp,
+ &csi_dev->capture, internal.queue) {
+ list_del_init(&buf->internal.queue);
+ if (buf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ }
+
+ INIT_LIST_HEAD(&csi_dev->capture);
+ INIT_LIST_HEAD(&csi_dev->active_bufs);
+ INIT_LIST_HEAD(&csi_dev->discard);
+
+ b = csi_dev->discard_buffer;
+ csi_dev->discard_buffer = NULL;
+
+ spin_unlock_irqrestore(&csi_dev->slock, flags);
+
+ dma_free_coherent(csi_dev->v4l2_dev.dev,
+ csi_dev->discard_size, b,
+ csi_dev->discard_buffer_dma);
+}
+
+static struct vb2_ops mx6s_videobuf_ops = {
+ .queue_setup = mx6s_videobuf_setup,
+ .buf_prepare = mx6s_videobuf_prepare,
+ .buf_queue = mx6s_videobuf_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = mx6s_start_streaming,
+ .stop_streaming = mx6s_stop_streaming,
+};
+
+static void mx6s_csi_frame_done(struct mx6s_csi_dev *csi_dev,
+ int bufnum, bool err)
+{
+ struct mx6s_buf_internal *ibuf;
+ struct mx6s_buffer *buf;
+ struct vb2_buffer *vb;
+ unsigned long phys;
+
+ ibuf = list_first_entry(&csi_dev->active_bufs, struct mx6s_buf_internal,
+ queue);
+
+ if (ibuf->discard) {
+ /*
+ * Discard buffer must not be returned to user space.
+ * Just return it to the discard queue.
+ */
+ list_move_tail(csi_dev->active_bufs.next, &csi_dev->discard);
+ } else {
+ buf = mx6s_ibuf_to_buf(ibuf);
+
+ vb = &buf->vb.vb2_buf;
+ phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+ if (bufnum == 1) {
+ if (csi_read(csi_dev, CSI_CSIDMASA_FB2) != phys) {
+ dev_err(csi_dev->dev, "%lx != %x\n", phys,
+ csi_read(csi_dev, CSI_CSIDMASA_FB2));
+ }
+ } else {
+ if (csi_read(csi_dev, CSI_CSIDMASA_FB1) != phys) {
+ dev_err(csi_dev->dev, "%lx != %x\n", phys,
+ csi_read(csi_dev, CSI_CSIDMASA_FB1));
+ }
+ }
+ dev_dbg(csi_dev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb,
+ vb2_plane_vaddr(vb, 0),
+ vb2_get_plane_payload(vb, 0));
+
+ list_del_init(&buf->internal.queue);
+ vb->timestamp =ktime_get_ns();
+ to_vb2_v4l2_buffer(vb)->sequence = csi_dev->frame_count;
+ if (err)
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+ else
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ }
+
+ csi_dev->frame_count++;
+
+ /* Config discard buffer to active_bufs */
+ if (list_empty(&csi_dev->capture)) {
+ if (list_empty(&csi_dev->discard)) {
+ dev_warn(csi_dev->dev,
+ "%s: trying to access empty discard list\n",
+ __func__);
+ return;
+ }
+
+ ibuf = list_first_entry(&csi_dev->discard,
+ struct mx6s_buf_internal, queue);
+ ibuf->bufnum = bufnum;
+
+ list_move_tail(csi_dev->discard.next, &csi_dev->active_bufs);
+
+ mx6s_update_csi_buf(csi_dev,
+ csi_dev->discard_buffer_dma, bufnum);
+ return;
+ }
+
+ buf = list_first_entry(&csi_dev->capture, struct mx6s_buffer,
+ internal.queue);
+
+ buf->internal.bufnum = bufnum;
+
+ list_move_tail(csi_dev->capture.next, &csi_dev->active_bufs);
+
+ vb = &buf->vb.vb2_buf;
+ vb->state = VB2_BUF_STATE_ACTIVE;
+
+ phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+ mx6s_update_csi_buf(csi_dev, phys, bufnum);
+}
+
+static irqreturn_t mx6s_csi_irq_handler(int irq, void *data)
+{
+ struct mx6s_csi_dev *csi_dev = data;
+ unsigned long status;
+ u32 cr3, cr18;
+
+ spin_lock(&csi_dev->slock);
+
+ status = csi_read(csi_dev, CSI_CSISR);
+ csi_write(csi_dev, status, CSI_CSISR);
+
+ if (list_empty(&csi_dev->active_bufs)) {
+ dev_warn(csi_dev->dev,
+ "%s: called while active list is empty\n",
+ __func__);
+
+ spin_unlock(&csi_dev->slock);
+ return IRQ_HANDLED;
+ }
+
+ if (status & BIT_RFF_OR_INT) {
+ dev_warn(csi_dev->dev, "%s Rx fifo overflow\n", __func__);
+ if (*csi_dev->rx_fifo_rst)
+ csi_error_recovery(csi_dev);
+ }
+
+ if (status & BIT_HRESP_ERR_INT) {
+ dev_warn(csi_dev->dev, "%s Hresponse error detected\n",
+ __func__);
+ csi_error_recovery(csi_dev);
+ }
+
+ if (status & BIT_ADDR_CH_ERR_INT) {
+ /* Disable csi */
+ cr18 = csi_read(csi_dev, CSI_CSICR18);
+ cr18 &= ~BIT_CSI_ENABLE;
+ csi_write(csi_dev, cr18, CSI_CSICR18);
+
+ /* DMA reflash */
+ cr3 = csi_read(csi_dev, CSI_CSICR3);
+ cr3 |= BIT_DMA_REFLASH_RFF;
+ csi_write(csi_dev, cr3, CSI_CSICR3);
+
+ /* Ensable csi */
+ cr18 |= BIT_CSI_ENABLE;
+ csi_write(csi_dev, cr18, CSI_CSICR18);
+
+ pr_debug("base address switching Change Err.\n");
+ }
+
+ if ((status & BIT_DMA_TSF_DONE_FB1) &&
+ (status & BIT_DMA_TSF_DONE_FB2)) {
+ /* For both FB1 and FB2 interrupter bits set case,
+ * CSI DMA is work in one of FB1 and FB2 buffer,
+ * but software can not know the state.
+ * Skip it to avoid base address updated
+ * when csi work in field0 and field1 will write to
+ * new base address.
+ * PDM TKT230775 */
+ pr_debug("Skip two frames\n");
+ } else if (status & BIT_DMA_TSF_DONE_FB1) {
+ mx6s_csi_frame_done(csi_dev, 0, false);
+ } else if (status & BIT_DMA_TSF_DONE_FB2) {
+ mx6s_csi_frame_done(csi_dev, 1, false);
+ }
+
+ spin_unlock(&csi_dev->slock);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * File operations for the device
+ */
+static int mx6s_csi_open(struct file *file)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+ struct vb2_queue *q = &csi_dev->vb2_vidq;
+ int ret = 0;
+
+ file->private_data = csi_dev;
+
+ if (mutex_lock_interruptible(&csi_dev->lock))
+ return -ERESTARTSYS;
+
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR;
+ q->drv_priv = csi_dev;
+ q->ops = &mx6s_videobuf_ops;
+ q->mem_ops = &vb2_dma_contig_memops;
+ q->buf_struct_size = sizeof(struct mx6s_buffer);
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &csi_dev->lock;
+
+ ret = vb2_queue_init(q);
+ if (ret < 0)
+ goto unlock;
+
+ pm_runtime_get_sync(csi_dev->dev);
+
+ request_bus_freq(BUS_FREQ_HIGH);
+
+ v4l2_subdev_call(sd, core, s_power, 1);
+ mx6s_csi_init(csi_dev);
+
+ mutex_unlock(&csi_dev->lock);
+
+ return ret;
+unlock:
+ mutex_unlock(&csi_dev->lock);
+ return ret;
+}
+
+static int mx6s_csi_close(struct file *file)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+
+ mutex_lock(&csi_dev->lock);
+
+ vb2_queue_release(&csi_dev->vb2_vidq);
+
+ mx6s_csi_deinit(csi_dev);
+ v4l2_subdev_call(sd, core, s_power, 0);
+
+ mutex_unlock(&csi_dev->lock);
+
+ file->private_data = NULL;
+
+ release_bus_freq(BUS_FREQ_HIGH);
+
+ pm_runtime_put_sync_suspend(csi_dev->dev);
+ return 0;
+}
+
+static ssize_t mx6s_csi_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ int ret;
+
+ dev_dbg(csi_dev->dev, "read called, buf %p\n", buf);
+
+ mutex_lock(&csi_dev->lock);
+ ret = vb2_read(&csi_dev->vb2_vidq, buf, count, ppos,
+ file->f_flags & O_NONBLOCK);
+ mutex_unlock(&csi_dev->lock);
+ return ret;
+}
+
+static int mx6s_csi_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ int ret;
+
+ if (mutex_lock_interruptible(&csi_dev->lock))
+ return -ERESTARTSYS;
+ ret = vb2_mmap(&csi_dev->vb2_vidq, vma);
+ mutex_unlock(&csi_dev->lock);
+
+ pr_debug("vma start=0x%08lx, size=%ld, ret=%d\n",
+ (unsigned long)vma->vm_start,
+ (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+ ret);
+
+ return ret;
+}
+
+static struct v4l2_file_operations mx6s_csi_fops = {
+ .owner = THIS_MODULE,
+ .open = mx6s_csi_open,
+ .release = mx6s_csi_close,
+ .read = mx6s_csi_read,
+ .poll = vb2_fop_poll,
+ .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+ .mmap = mx6s_csi_mmap,
+};
+
+/*
+ * Video node IOCTLs
+ */
+static int mx6s_vidioc_enum_input(struct file *file, void *priv,
+ struct v4l2_input *inp)
+{
+ if (inp->index != 0)
+ return -EINVAL;
+
+ /* default is camera */
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ strcpy(inp->name, "Camera");
+
+ return 0;
+}
+
+static int mx6s_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+ *i = 0;
+
+ return 0;
+}
+
+static int mx6s_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+ if (i > 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int mx6s_vidioc_querystd(struct file *file, void *priv, v4l2_std_id *a)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+
+ return v4l2_subdev_call(sd, video, querystd, a);
+}
+
+static int mx6s_vidioc_s_std(struct file *file, void *priv, v4l2_std_id a)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+
+ return v4l2_subdev_call(sd, video, s_std, a);
+}
+
+static int mx6s_vidioc_g_std(struct file *file, void *priv, v4l2_std_id *a)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+
+ return v4l2_subdev_call(sd, video, g_std, a);
+}
+
+static int mx6s_vidioc_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *p)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+ WARN_ON(priv != file->private_data);
+
+ return vb2_reqbufs(&csi_dev->vb2_vidq, p);
+}
+
+static int mx6s_vidioc_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *p)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ int ret;
+
+ WARN_ON(priv != file->private_data);
+
+ ret = vb2_querybuf(&csi_dev->vb2_vidq, p);
+
+ if (!ret) {
+ /* return physical address */
+ struct vb2_buffer *vb = csi_dev->vb2_vidq.bufs[p->index];
+ if (p->flags & V4L2_BUF_FLAG_MAPPED)
+ p->m.offset = vb2_dma_contig_plane_dma_addr(vb, 0);
+ }
+ return ret;
+}
+
+static int mx6s_vidioc_qbuf(struct file *file, void *priv,
+ struct v4l2_buffer *p)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+ WARN_ON(priv != file->private_data);
+
+ return vb2_qbuf(&csi_dev->vb2_vidq, p);
+}
+
+static int mx6s_vidioc_dqbuf(struct file *file, void *priv,
+ struct v4l2_buffer *p)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+ WARN_ON(priv != file->private_data);
+
+ return vb2_dqbuf(&csi_dev->vb2_vidq, p, file->f_flags & O_NONBLOCK);
+}
+
+static int mx6s_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .index = f->index,
+ };
+ struct mx6s_fmt *fmt;
+ int ret;
+
+ WARN_ON(priv != file->private_data);
+
+ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
+ if (ret < 0) {
+ /* no more formats */
+ dev_dbg(csi_dev->dev, "No more fmt\n");
+ return -EINVAL;
+ }
+
+ fmt = format_by_mbus(code.code);
+ if (!fmt) {
+ dev_err(csi_dev->dev, "mbus (0x%08x) invalid.\n", code.code);
+ return -EINVAL;
+ }
+
+ strlcpy(f->description, fmt->name, sizeof(f->description));
+ f->pixelformat = fmt->pixelformat;
+
+ return 0;
+}
+
+static int mx6s_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct mx6s_fmt *fmt;
+ int ret;
+
+ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ if (!fmt) {
+ dev_err(csi_dev->dev, "Fourcc format (0x%08x) invalid.",
+ f->fmt.pix.pixelformat);
+ return -EINVAL;
+ }
+
+ if (f->fmt.pix.width == 0 || f->fmt.pix.height == 0) {
+ dev_err(csi_dev->dev, "width %d, height %d is too small.\n",
+ f->fmt.pix.width, f->fmt.pix.height);
+ return -EINVAL;
+ }
+
+ v4l2_fill_mbus_format(&format.format, pix, fmt->mbus_code);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
+ v4l2_fill_pix_format(pix, &format.format);
+
+ if (pix->field != V4L2_FIELD_INTERLACED)
+ pix->field = V4L2_FIELD_NONE;
+
+ pix->sizeimage = fmt->bpp * pix->height * pix->width;
+ pix->bytesperline = fmt->bpp * pix->width;
+
+ return ret;
+}
+
+/*
+ * The real work of figuring out a workable format.
+ */
+
+static int mx6s_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ int ret;
+
+ ret = mx6s_vidioc_try_fmt_vid_cap(file, csi_dev, f);
+ if (ret < 0)
+ return ret;
+
+ csi_dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ csi_dev->mbus_code = csi_dev->fmt->mbus_code;
+ csi_dev->pix.width = f->fmt.pix.width;
+ csi_dev->pix.height = f->fmt.pix.height;
+ csi_dev->pix.sizeimage = f->fmt.pix.sizeimage;
+ csi_dev->pix.field = f->fmt.pix.field;
+ csi_dev->type = f->type;
+ dev_dbg(csi_dev->dev, "set to pixelformat '%4.6s'\n",
+ (char *)&csi_dev->fmt->name);
+
+ /* Config csi */
+ mx6s_configure_csi(csi_dev);
+
+ return 0;
+}
+
+static int mx6s_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+ WARN_ON(priv != file->private_data);
+
+ f->fmt.pix = csi_dev->pix;
+
+ return 0;
+}
+
+static int mx6s_vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+ WARN_ON(priv != file->private_data);
+
+ /* cap->name is set by the friendly caller:-> */
+ strlcpy(cap->driver, MX6S_CAM_DRV_NAME, sizeof(cap->driver));
+ strlcpy(cap->card, MX6S_CAM_DRIVER_DESCRIPTION, sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+ dev_name(csi_dev->dev));
+
+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int mx6s_vidioc_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type i)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+ int ret;
+
+ WARN_ON(priv != file->private_data);
+
+ if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ ret = vb2_streamon(&csi_dev->vb2_vidq, i);
+ if (!ret)
+ v4l2_subdev_call(sd, video, s_stream, 1);
+
+ return ret;
+}
+
+static int mx6s_vidioc_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type i)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+
+ WARN_ON(priv != file->private_data);
+
+ if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ /*
+ * This calls buf_release from host driver's videobuf_queue_ops for all
+ * remaining buffers. When the last buffer is freed, stop capture
+ */
+ vb2_streamoff(&csi_dev->vb2_vidq, i);
+
+ v4l2_subdev_call(sd, video, s_stream, 0);
+
+ return 0;
+}
+
+static int mx6s_vidioc_cropcap(struct file *file, void *fh,
+ struct v4l2_cropcap *a)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ dev_dbg(csi_dev->dev, "VIDIOC_CROPCAP not implemented\n");
+
+ return 0;
+}
+
+static int mx6s_vidioc_g_crop(struct file *file, void *priv,
+ struct v4l2_crop *a)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ dev_dbg(csi_dev->dev, "VIDIOC_G_CROP not implemented\n");
+
+ return 0;
+}
+
+static int mx6s_vidioc_s_crop(struct file *file, void *priv,
+ const struct v4l2_crop *a)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ dev_dbg(csi_dev->dev, "VIDIOC_S_CROP not implemented\n");
+
+ return 0;
+}
+
+static int mx6s_vidioc_g_parm(struct file *file, void *priv,
+ struct v4l2_streamparm *a)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+
+ return v4l2_subdev_call(sd, video, g_parm, a);
+}
+
+static int mx6s_vidioc_s_parm(struct file *file, void *priv,
+ struct v4l2_streamparm *a)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+
+ return v4l2_subdev_call(sd, video, s_parm, a);
+}
+
+static int mx6s_vidioc_enum_framesizes(struct file *file, void *priv,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+ struct mx6s_fmt *fmt;
+ struct v4l2_subdev_frame_size_enum fse = {
+ .index = fsize->index,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ int ret;
+
+ fmt = format_by_fourcc(fsize->pixel_format);
+ if (fmt->pixelformat != fsize->pixel_format)
+ return -EINVAL;
+ fse.code = fmt->mbus_code;
+
+ ret = v4l2_subdev_call(sd, pad, enum_frame_size, NULL, &fse);
+ if (ret)
+ return ret;
+
+ if (fse.min_width == fse.max_width &&
+ fse.min_height == fse.max_height) {
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = fse.min_width;
+ fsize->discrete.height = fse.min_height;
+ return 0;
+ }
+
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->stepwise.min_width = fse.min_width;
+ fsize->stepwise.max_width = fse.max_width;
+ fsize->stepwise.min_height = fse.min_height;
+ fsize->stepwise.max_height = fse.max_height;
+ fsize->stepwise.step_width = 1;
+ fsize->stepwise.step_height = 1;
+
+ return 0;
+}
+
+static int mx6s_vidioc_enum_frameintervals(struct file *file, void *priv,
+ struct v4l2_frmivalenum *interval)
+{
+ struct mx6s_csi_dev *csi_dev = video_drvdata(file);
+ struct v4l2_subdev *sd = csi_dev->sd;
+ struct mx6s_fmt *fmt;
+ struct v4l2_subdev_frame_interval_enum fie = {
+ .index = interval->index,
+ .width = interval->width,
+ .height = interval->height,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ int ret;
+
+ fmt = format_by_fourcc(interval->pixel_format);
+ if (fmt->pixelformat != interval->pixel_format)
+ return -EINVAL;
+ fie.code = fmt->mbus_code;
+
+ ret = v4l2_subdev_call(sd, pad, enum_frame_interval, NULL, &fie);
+ if (ret)
+ return ret;
+ interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ interval->discrete = fie.interval;
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops mx6s_csi_ioctl_ops = {
+ .vidioc_querycap = mx6s_vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = mx6s_vidioc_enum_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = mx6s_vidioc_try_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = mx6s_vidioc_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = mx6s_vidioc_s_fmt_vid_cap,
+ .vidioc_cropcap = mx6s_vidioc_cropcap,
+ .vidioc_s_crop = mx6s_vidioc_s_crop,
+ .vidioc_g_crop = mx6s_vidioc_g_crop,
+ .vidioc_reqbufs = mx6s_vidioc_reqbufs,
+ .vidioc_querybuf = mx6s_vidioc_querybuf,
+ .vidioc_qbuf = mx6s_vidioc_qbuf,
+ .vidioc_dqbuf = mx6s_vidioc_dqbuf,
+ .vidioc_g_std = mx6s_vidioc_g_std,
+ .vidioc_s_std = mx6s_vidioc_s_std,
+ .vidioc_querystd = mx6s_vidioc_querystd,
+ .vidioc_enum_input = mx6s_vidioc_enum_input,
+ .vidioc_g_input = mx6s_vidioc_g_input,
+ .vidioc_s_input = mx6s_vidioc_s_input,
+ .vidioc_streamon = mx6s_vidioc_streamon,
+ .vidioc_streamoff = mx6s_vidioc_streamoff,
+ .vidioc_g_parm = mx6s_vidioc_g_parm,
+ .vidioc_s_parm = mx6s_vidioc_s_parm,
+ .vidioc_enum_framesizes = mx6s_vidioc_enum_framesizes,
+ .vidioc_enum_frameintervals = mx6s_vidioc_enum_frameintervals,
+};
+
+static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *subdev,
+ struct v4l2_async_subdev *asd)
+{
+ struct mx6s_csi_dev *csi_dev = notifier_to_mx6s_dev(notifier);
+
+ /* Find platform data for this sensor subdev */
+ if (csi_dev->asd.match.of.node == subdev->dev->of_node)
+ csi_dev->sd = subdev;
+
+ if (subdev == NULL)
+ return -EINVAL;
+
+ v4l2_info(&csi_dev->v4l2_dev, "Registered sensor subdevice: %s\n",
+ subdev->name);
+
+ return 0;
+}
+
+static int mx6s_csi_mux_sel(struct mx6s_csi_dev *csi_dev)
+{
+ struct device_node *np = csi_dev->dev->of_node;
+ struct device_node *node;
+ phandle phandle;
+ u32 out_val[3];
+ int ret;
+
+ ret = of_property_read_u32_array(np, "csi-mux-mipi", out_val, 3);
+ if (ret) {
+ dev_dbg(csi_dev->dev, "no csi-mux-mipi property found\n");
+ csi_dev->csi_mux_mipi = false;
+ } else {
+ phandle = *out_val;
+
+ node = of_find_node_by_phandle(phandle);
+ if (!node) {
+ dev_dbg(csi_dev->dev, "not find gpr node by phandle\n");
+ ret = PTR_ERR(node);
+ }
+ csi_dev->csi_mux.gpr = syscon_node_to_regmap(node);
+ if (IS_ERR(csi_dev->csi_mux.gpr)) {
+ dev_err(csi_dev->dev, "failed to get gpr regmap\n");
+ ret = PTR_ERR(csi_dev->csi_mux.gpr);
+ }
+ of_node_put(node);
+ if (ret < 0)
+ return ret;
+
+ csi_dev->csi_mux.req_gpr = out_val[1];
+ csi_dev->csi_mux.req_bit = out_val[2];
+
+ regmap_update_bits(csi_dev->csi_mux.gpr, csi_dev->csi_mux.req_gpr,
+ 1 << csi_dev->csi_mux.req_bit, 1 << csi_dev->csi_mux.req_bit);
+
+ csi_dev->csi_mux_mipi = true;
+ }
+ return ret;
+}
+
+static int mx6sx_register_subdevs(struct mx6s_csi_dev *csi_dev)
+{
+ struct device_node *parent = csi_dev->dev->of_node;
+ struct device_node *node, *port, *rem;
+ int ret;
+
+ /* Attach sensors linked to csi receivers */
+ for_each_available_child_of_node(parent, node) {
+ if (of_node_cmp(node->name, "port"))
+ continue;
+
+ /* The csi node can have only port subnode. */
+ port = of_get_next_child(node, NULL);
+ if (!port)
+ continue;
+ rem = of_graph_get_remote_port_parent(port);
+ of_node_put(port);
+ if (rem == NULL) {
+ v4l2_info(&csi_dev->v4l2_dev,
+ "Remote device at %s not found\n",
+ port->full_name);
+ return -1;
+ }
+
+ csi_dev->asd.match_type = V4L2_ASYNC_MATCH_OF;
+ csi_dev->asd.match.of.node = rem;
+ csi_dev->async_subdevs[0] = &csi_dev->asd;
+
+ of_node_put(rem);
+ break;
+ }
+
+ csi_dev->subdev_notifier.subdevs = csi_dev->async_subdevs;
+ csi_dev->subdev_notifier.num_subdevs = 1;
+ csi_dev->subdev_notifier.bound = subdev_notifier_bound;
+
+ ret = v4l2_async_notifier_register(&csi_dev->v4l2_dev,
+ &csi_dev->subdev_notifier);
+ if (ret)
+ dev_err(csi_dev->dev,
+ "Error register async notifier regoster\n");
+
+ return ret;
+}
+
+static int mx6s_csi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id;
+ struct mx6s_csi_dev *csi_dev;
+ struct video_device *vdev;
+ struct resource *res;
+ int ret = 0;
+
+ dev_dbg(dev, "initialising\n");
+
+ /* Prepare our private structure */
+ csi_dev = devm_kzalloc(dev, sizeof(struct mx6s_csi_dev), GFP_ATOMIC);
+ if (!csi_dev) {
+ dev_err(dev, "Can't allocate private structure\n");
+ return -ENODEV;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ csi_dev->irq = platform_get_irq(pdev, 0);
+ if (res == NULL || csi_dev->irq < 0) {
+ dev_err(dev, "Missing platform resources data\n");
+ return -ENODEV;
+ }
+
+ csi_dev->regbase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(csi_dev->regbase)) {
+ dev_err(dev, "Failed platform resources map\n");
+ return -ENODEV;
+ }
+
+ /* init video dma queues */
+ INIT_LIST_HEAD(&csi_dev->capture);
+ INIT_LIST_HEAD(&csi_dev->active_bufs);
+ INIT_LIST_HEAD(&csi_dev->discard);
+
+ csi_dev->clk_disp_axi = devm_clk_get(dev, "disp-axi");
+ if (IS_ERR(csi_dev->clk_disp_axi)) {
+ dev_err(dev, "Could not get csi axi clock\n");
+ return -ENODEV;
+ }
+
+ csi_dev->clk_disp_dcic = devm_clk_get(dev, "disp_dcic");
+ if (IS_ERR(csi_dev->clk_disp_dcic)) {
+ dev_err(dev, "Could not get disp dcic clock\n");
+ return -ENODEV;
+ }
+
+ csi_dev->clk_csi_mclk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(csi_dev->clk_csi_mclk)) {
+ dev_err(dev, "Could not get csi mclk clock\n");
+ return -ENODEV;
+ }
+
+ csi_dev->dev = dev;
+
+ mx6s_csi_mux_sel(csi_dev);
+
+ of_id = of_match_node(mx6s_csi_dt_ids, csi_dev->dev->of_node);
+ if (!of_id)
+ return -EINVAL;
+ csi_dev->rx_fifo_rst = of_id->data;
+
+ snprintf(csi_dev->v4l2_dev.name,
+ sizeof(csi_dev->v4l2_dev.name), "CSI");
+
+ ret = v4l2_device_register(dev, &csi_dev->v4l2_dev);
+ if (ret < 0) {
+ dev_err(dev, "v4l2_device_register() failed: %d\n", ret);
+ return -ENODEV;
+ }
+
+ /* initialize locks */
+ mutex_init(&csi_dev->lock);
+ spin_lock_init(&csi_dev->slock);
+
+ /* Allocate memory for video device */
+ vdev = video_device_alloc();
+ if (vdev == NULL) {
+ ret = -ENOMEM;
+ goto err_vdev;
+ }
+
+ snprintf(vdev->name, sizeof(vdev->name), "mx6s-csi");
+
+ vdev->v4l2_dev = &csi_dev->v4l2_dev;
+ vdev->fops = &mx6s_csi_fops;
+ vdev->ioctl_ops = &mx6s_csi_ioctl_ops;
+ vdev->release = video_device_release;
+ vdev->lock = &csi_dev->lock;
+
+ vdev->queue = &csi_dev->vb2_vidq;
+
+ csi_dev->vdev = vdev;
+
+ video_set_drvdata(csi_dev->vdev, csi_dev);
+ mutex_lock(&csi_dev->lock);
+
+ ret = video_register_device(csi_dev->vdev, VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ video_device_release(csi_dev->vdev);
+ mutex_unlock(&csi_dev->lock);
+ goto err_vdev;
+ }
+
+ /* install interrupt handler */
+ if (devm_request_irq(dev, csi_dev->irq, mx6s_csi_irq_handler,
+ 0, "csi", (void *)csi_dev)) {
+ mutex_unlock(&csi_dev->lock);
+ dev_err(dev, "Request CSI IRQ failed.\n");
+ ret = -ENODEV;
+ goto err_irq;
+ }
+
+ mutex_unlock(&csi_dev->lock);
+
+ ret = mx6sx_register_subdevs(csi_dev);
+ if (ret < 0)
+ goto err_irq;
+
+ pm_runtime_enable(csi_dev->dev);
+ return 0;
+
+err_irq:
+ video_unregister_device(csi_dev->vdev);
+err_vdev:
+ v4l2_device_unregister(&csi_dev->v4l2_dev);
+ return ret;
+}
+
+static int mx6s_csi_remove(struct platform_device *pdev)
+{
+ struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+ struct mx6s_csi_dev *csi_dev =
+ container_of(v4l2_dev, struct mx6s_csi_dev, v4l2_dev);
+
+ v4l2_async_notifier_unregister(&csi_dev->subdev_notifier);
+
+ video_unregister_device(csi_dev->vdev);
+ v4l2_device_unregister(&csi_dev->v4l2_dev);
+
+ pm_runtime_disable(csi_dev->dev);
+ return 0;
+}
+
+static int mx6s_csi_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "csi v4l2 busfreq high release.\n");
+ return 0;
+}
+
+static int mx6s_csi_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "csi v4l2 busfreq high request.\n");
+ return 0;
+}
+
+static const struct dev_pm_ops mx6s_csi_pm_ops = {
+ SET_RUNTIME_PM_OPS(mx6s_csi_runtime_suspend, mx6s_csi_runtime_resume, NULL)
+};
+
+static const u8 mx6s_fifo_rst = true;
+static const u8 mx6sl_fifo_rst = false;
+
+static const struct of_device_id mx6s_csi_dt_ids[] = {
+ { .compatible = "fsl,imx6s-csi",
+ .data = &mx6s_fifo_rst,
+ },
+ { .compatible = "fsl,imx6sl-csi",
+ .data = &mx6sl_fifo_rst,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mx6s_csi_dt_ids);
+
+static struct platform_driver mx6s_csi_driver = {
+ .driver = {
+ .name = MX6S_CAM_DRV_NAME,
+ .of_match_table = of_match_ptr(mx6s_csi_dt_ids),
+ .pm = &mx6s_csi_pm_ops,
+ },
+ .probe = mx6s_csi_probe,
+ .remove = mx6s_csi_remove,
+};
+
+module_platform_driver(mx6s_csi_driver);
+
+MODULE_DESCRIPTION("i.MX6Sx SoC Camera Host driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MX6S_CAM_VERSION);
diff --git a/drivers/media/platform/mxc/subdev/mxc_mipi_csi.c b/drivers/media/platform/mxc/subdev/mxc_mipi_csi.c
new file mode 100644
index 000000000000..4371d6508bda
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/mxc_mipi_csi.c
@@ -0,0 +1,1248 @@
+/*
+ * Freescale i.MX7 SoC series MIPI-CSI V3.3 receiver driver
+ *
+ * Copyright (C) 2015-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
+ */
+/*
+ * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver
+ *
+ * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-of.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-device.h>
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+#define CSIS_DRIVER_NAME "mxc_mipi-csi"
+#define CSIS_SUBDEV_NAME CSIS_DRIVER_NAME
+#define CSIS_MAX_ENTITIES 2
+#define CSIS0_MAX_LANES 4
+#define CSIS1_MAX_LANES 2
+
+#define MIPI_CSIS_DEF_PIX_WIDTH 640
+#define MIPI_CSIS_DEF_PIX_HEIGHT 480
+
+/* Register map definition */
+
+/* CSIS version */
+#define MIPI_CSIS_VERSION 0x00
+
+/* CSIS common control */
+#define MIPI_CSIS_CMN_CTRL 0x04
+#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW (1 << 16)
+#define MIPI_CSIS_CMN_CTRL_INTER_MODE (1 << 10)
+#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET 8
+#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK (3 << 8)
+#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL (1 << 2)
+#define MIPI_CSIS_CMN_CTRL_RESET (1 << 1)
+#define MIPI_CSIS_CMN_CTRL_ENABLE (1 << 0)
+
+/* CSIS clock control */
+#define MIPI_CSIS_CLK_CTRL 0x08
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x) (x << 28)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x) (x << 24)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x) (x << 20)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x) (x << 16)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK (0xf << 4)
+#define MIPI_CSIS_CLK_CTRL_WCLK_SRC (1 << 0)
+
+/* CSIS Interrupt mask */
+#define MIPI_CSIS_INTMSK 0x10
+#define MIPI_CSIS_INTMSK_EVEN_BEFORE (1 << 31)
+#define MIPI_CSIS_INTMSK_EVEN_AFTER (1 << 30)
+#define MIPI_CSIS_INTMSK_ODD_BEFORE (1 << 29)
+#define MIPI_CSIS_INTMSK_ODD_AFTER (1 << 28)
+#define MIPI_CSIS_INTMSK_FRAME_START (1 << 24)
+#define MIPI_CSIS_INTMSK_FRAME_END (1 << 20)
+#define MIPI_CSIS_INTMSK_ERR_SOT_HS (1 << 16)
+#define MIPI_CSIS_INTMSK_ERR_LOST_FS (1 << 12)
+#define MIPI_CSIS_INTMSK_ERR_LOST_FE (1 << 8)
+#define MIPI_CSIS_INTMSK_ERR_OVER (1 << 4)
+#define MIPI_CSIS_INTMSK_ERR_WRONG_CFG (1 << 3)
+#define MIPI_CSIS_INTMSK_ERR_ECC (1 << 2)
+#define MIPI_CSIS_INTMSK_ERR_CRC (1 << 1)
+#define MIPI_CSIS_INTMSK_ERR_UNKNOWN (1 << 0)
+
+/* CSIS Interrupt source */
+#define MIPI_CSIS_INTSRC 0x14
+#define MIPI_CSIS_INTSRC_EVEN_BEFORE (1 << 31)
+#define MIPI_CSIS_INTSRC_EVEN_AFTER (1 << 30)
+#define MIPI_CSIS_INTSRC_EVEN (0x3 << 30)
+#define MIPI_CSIS_INTSRC_ODD_BEFORE (1 << 29)
+#define MIPI_CSIS_INTSRC_ODD_AFTER (1 << 28)
+#define MIPI_CSIS_INTSRC_ODD (0x3 << 28)
+#define MIPI_CSIS_INTSRC_NON_IMAGE_DATA (0xf << 28)
+#define MIPI_CSIS_INTSRC_FRAME_START (1 << 24)
+#define MIPI_CSIS_INTSRC_FRAME_END (1 << 20)
+#define MIPI_CSIS_INTSRC_ERR_SOT_HS (1 << 16)
+#define MIPI_CSIS_INTSRC_ERR_LOST_FS (1 << 12)
+#define MIPI_CSIS_INTSRC_ERR_LOST_FE (1 << 8)
+#define MIPI_CSIS_INTSRC_ERR_OVER (1 << 4)
+#define MIPI_CSIS_INTSRC_ERR_WRONG_CFG (1 << 3)
+#define MIPI_CSIS_INTSRC_ERR_ECC (1 << 2)
+#define MIPI_CSIS_INTSRC_ERR_CRC (1 << 1)
+#define MIPI_CSIS_INTSRC_ERR_UNKNOWN (1 << 0)
+#define MIPI_CSIS_INTSRC_ERRORS 0xfffff
+
+/* D-PHY status control */
+#define MIPI_CSIS_DPHYSTATUS 0x20
+#define MIPI_CSIS_DPHYSTATUS_ULPS_DAT (1 << 8)
+#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_DAT (1 << 4)
+#define MIPI_CSIS_DPHYSTATUS_ULPS_CLK (1 << 1)
+#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_CLK (1 << 0)
+
+/* D-PHY common control */
+#define MIPI_CSIS_DPHYCTRL 0x24
+#define MIPI_CSIS_DPHYCTRL_HSS_MASK (0xff << 24)
+#define MIPI_CSIS_DPHYCTRL_HSS_OFFSET 24
+#define MIPI_CSIS_DPHYCTRL_SCLKS_MASK (0x3 << 22)
+#define MIPI_CSIS_DPHYCTRL_SCLKS_OFFSET 22
+#define MIPI_CSIS_DPHYCTRL_DPDN_SWAP_CLK (1 << 6)
+#define MIPI_CSIS_DPHYCTRL_DPDN_SWAP_DAT (1 << 5)
+#define MIPI_CSIS_DPHYCTRL_ENABLE_DAT (1 << 1)
+#define MIPI_CSIS_DPHYCTRL_ENABLE_CLK (1 << 0)
+#define MIPI_CSIS_DPHYCTRL_ENABLE (0x1f << 0)
+
+/* D-PHY Master and Slave Control register Low */
+#define MIPI_CSIS_DPHYBCTRL_L 0x30
+/* D-PHY Master and Slave Control register High */
+#define MIPI_CSIS_DPHYBCTRL_H 0x34
+/* D-PHY Slave Control register Low */
+#define MIPI_CSIS_DPHYSCTRL_L 0x38
+/* D-PHY Slave Control register High */
+#define MIPI_CSIS_DPHYSCTRL_H 0x3c
+
+
+/* ISP Configuration register */
+#define MIPI_CSIS_ISPCONFIG_CH0 0x40
+#define MIPI_CSIS_ISPCONFIG_CH1 0x50
+#define MIPI_CSIS_ISPCONFIG_CH2 0x60
+#define MIPI_CSIS_ISPCONFIG_CH3 0x70
+
+#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK (0xff << 24)
+#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x) (x << 24)
+#define MIPI_CSIS_ISPCFG_DOUBLE_CMPNT (1 << 12)
+#define MIPI_CSIS_ISPCFG_ALIGN_32BIT (1 << 11)
+#define MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT (0x1e << 2)
+#define MIPI_CSIS_ISPCFG_FMT_RAW8 (0x2a << 2)
+#define MIPI_CSIS_ISPCFG_FMT_RAW10 (0x2b << 2)
+#define MIPI_CSIS_ISPCFG_FMT_RAW12 (0x2c << 2)
+/* User defined formats, x = 1...4 */
+#define MIPI_CSIS_ISPCFG_FMT_USER(x) ((0x30 + x - 1) << 2)
+#define MIPI_CSIS_ISPCFG_FMT_MASK (0x3f << 2)
+
+/* ISP Image Resolution register */
+#define MIPI_CSIS_ISPRESOL_CH0 0x44
+#define MIPI_CSIS_ISPRESOL_CH1 0x54
+#define MIPI_CSIS_ISPRESOL_CH2 0x64
+#define MIPI_CSIS_ISPRESOL_CH3 0x74
+#define CSIS_MAX_PIX_WIDTH 0xffff
+#define CSIS_MAX_PIX_HEIGHT 0xffff
+
+/* ISP SYNC register */
+#define MIPI_CSIS_ISPSYNC_CH0 0x48
+#define MIPI_CSIS_ISPSYNC_CH1 0x58
+#define MIPI_CSIS_ISPSYNC_CH2 0x68
+#define MIPI_CSIS_ISPSYNC_CH3 0x78
+
+#define MIPI_CSIS_ISPSYNC_HSYNC_LINTV_OFFSET 18
+#define MIPI_CSIS_ISPSYNC_VSYNC_SINTV_OFFSET 12
+#define MIPI_CSIS_ISPSYNC_VSYNC_EINTV_OFFSET 0
+
+/* Non-image packet data buffers */
+#define MIPI_CSIS_PKTDATA_ODD 0x2000
+#define MIPI_CSIS_PKTDATA_EVEN 0x3000
+#define MIPI_CSIS_PKTDATA_SIZE SZ_4K
+
+#define DEFAULT_SCLK_CSIS_FREQ 166000000UL
+
+enum {
+ ST_POWERED = 1,
+ ST_STREAMING = 2,
+ ST_SUSPENDED = 4,
+};
+
+struct mipi_csis_event {
+ u32 mask;
+ const char * const name;
+ unsigned int counter;
+};
+
+static const struct mipi_csis_event mipi_csis_events[] = {
+ /* Errors */
+ { MIPI_CSIS_INTSRC_ERR_SOT_HS, "SOT Error" },
+ { MIPI_CSIS_INTSRC_ERR_LOST_FS, "Lost Frame Start Error" },
+ { MIPI_CSIS_INTSRC_ERR_LOST_FE, "Lost Frame End Error" },
+ { MIPI_CSIS_INTSRC_ERR_OVER, "FIFO Overflow Error" },
+ { MIPI_CSIS_INTSRC_ERR_ECC, "ECC Error" },
+ { MIPI_CSIS_INTSRC_ERR_CRC, "CRC Error" },
+ { MIPI_CSIS_INTSRC_ERR_UNKNOWN, "Unknown Error" },
+ /* Non-image data receive events */
+ { MIPI_CSIS_INTSRC_EVEN_BEFORE, "Non-image data before even frame" },
+ { MIPI_CSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" },
+ { MIPI_CSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" },
+ { MIPI_CSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" },
+ /* Frame start/end */
+ { MIPI_CSIS_INTSRC_FRAME_START, "Frame Start" },
+ { MIPI_CSIS_INTSRC_FRAME_END, "Frame End" },
+};
+#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events)
+
+struct csis_pktbuf {
+ u32 *data;
+ unsigned int len;
+};
+
+struct csis_hw_reset {
+ struct regmap *src;
+ u8 req_src;
+ u8 rst_bit;
+};
+
+/**
+ * struct csi_state - the driver's internal state data structure
+ * @lock: mutex serializing the subdev and power management operations,
+ * protecting @format and @flags members
+ * @sd: v4l2_subdev associated with CSIS device instance
+ * @index: the hardware instance index
+ * @pdev: CSIS platform device
+ * @phy: pointer to the CSIS generic PHY
+ * @regs: mmaped I/O registers memory
+ * @supplies: CSIS regulator supplies
+ * @clock: CSIS clocks
+ * @irq: requested s5p-mipi-csis irq number
+ * @flags: the state variable for power and streaming control
+ * @clock_frequency: device bus clock frequency
+ * @hs_settle: HS-RX settle time
+ * @clk_settle: Clk settle time
+ * @num_lanes: number of MIPI-CSI data lanes used
+ * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
+ * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
+ * @csis_fmt: current CSIS pixel format
+ * @format: common media bus format for the source and sink pad
+ * @slock: spinlock protecting structure members below
+ * @pkt_buf: the frame embedded (non-image) data buffer
+ * @events: MIPI-CSIS event (error) counters
+ */
+struct csi_state {
+ struct mutex lock;
+ struct device *dev;
+ struct v4l2_subdev mipi_sd;
+ struct v4l2_subdev *sensor_sd;
+ struct v4l2_device v4l2_dev;
+
+ u8 index;
+ struct platform_device *pdev;
+ struct phy *phy;
+ void __iomem *regs;
+ struct clk *mipi_clk;
+ struct clk *phy_clk;
+ int irq;
+ u32 flags;
+
+ u32 clk_frequency;
+ u32 hs_settle;
+ u32 clk_settle;
+ u32 num_lanes;
+ u32 max_num_lanes;
+ u8 wclk_ext;
+
+ const struct csis_pix_format *csis_fmt;
+ struct v4l2_mbus_framefmt format;
+
+ spinlock_t slock;
+ struct csis_pktbuf pkt_buf;
+ struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
+
+ struct v4l2_async_subdev asd;
+ struct v4l2_async_notifier subdev_notifier;
+ struct v4l2_async_subdev *async_subdevs[2];
+
+ struct csis_hw_reset hw_reset;
+ struct regulator *mipi_phy_regulator;
+};
+
+/**
+ * struct csis_pix_format - CSIS pixel format description
+ * @pix_width_alignment: horizontal pixel alignment, width will be
+ * multiple of 2^pix_width_alignment
+ * @code: corresponding media bus code
+ * @fmt_reg: MIPI_CSIS_CONFIG register value
+ * @data_alignment: MIPI-CSI data alignment in bits
+ */
+struct csis_pix_format {
+ unsigned int pix_width_alignment;
+ u32 code;
+ u32 fmt_reg;
+ u8 data_alignment;
+};
+
+static const struct csis_pix_format mipi_csis_formats[] = {
+ {
+ .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT,
+ .data_alignment = 16,
+ }, {
+ .code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT,
+ .data_alignment = 16,
+ }, {
+ .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8,
+ .data_alignment = 8,
+ }
+};
+
+#define mipi_csis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
+#define mipi_csis_read(__csis, __r) readl(__csis->regs + __r)
+
+static struct csi_state *mipi_sd_to_csi_state(struct v4l2_subdev *sdev)
+{
+ return container_of(sdev, struct csi_state, mipi_sd);
+}
+
+static inline struct csi_state
+ *notifier_to_mipi_dev(struct v4l2_async_notifier *n)
+{
+ return container_of(n, struct csi_state, subdev_notifier);
+}
+
+static const struct csis_pix_format *find_csis_format(u32 code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++)
+ if (code == mipi_csis_formats[i].code)
+ return &mipi_csis_formats[i];
+ return NULL;
+}
+
+static void mipi_csis_enable_interrupts(struct csi_state *state, bool on)
+{
+ u32 val = mipi_csis_read(state, MIPI_CSIS_INTMSK);
+ if (on)
+ val |= 0xf00fffff;
+ else
+ val &= ~0xf00fffff;
+ mipi_csis_write(state, MIPI_CSIS_INTMSK, val);
+}
+
+static void mipi_csis_sw_reset(struct csi_state *state)
+{
+ u32 val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+
+ mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val | MIPI_CSIS_CMN_CTRL_RESET);
+ udelay(10);
+}
+
+static int mipi_csis_phy_init(struct csi_state *state)
+{
+ int ret;
+
+ state->mipi_phy_regulator = devm_regulator_get(state->dev,
+ "mipi-phy");
+
+ ret = regulator_set_voltage(state->mipi_phy_regulator,
+ 1000000, 1000000);
+
+ return ret;
+}
+
+static int mipi_csis_phy_reset(struct csi_state *state)
+{
+ struct device_node *np = state->dev->of_node;
+ struct device_node *node;
+ phandle phandle;
+ u32 out_val[3];
+ int ret;
+
+ ret = of_property_read_u32_array(np, "csis-phy-reset", out_val, 3);
+ if (ret) {
+ dev_dbg(state->dev, "no csis-hw-reset property found\n");
+ } else {
+ phandle = *out_val;
+
+ node = of_find_node_by_phandle(phandle);
+ if (!node) {
+ dev_dbg(state->dev, "not find src node by phandle\n");
+ ret = PTR_ERR(node);
+ }
+ state->hw_reset.src = syscon_node_to_regmap(node);
+ if (IS_ERR(state->hw_reset.src)) {
+ dev_err(state->dev, "failed to get src regmap\n");
+ ret = PTR_ERR(state->hw_reset.src);
+ }
+ of_node_put(node);
+ if (ret < 0)
+ return ret;
+
+ state->hw_reset.req_src = out_val[1];
+ state->hw_reset.rst_bit = out_val[2];
+
+ /* reset mipi phy */
+ regmap_update_bits(state->hw_reset.src, state->hw_reset.req_src,
+ 1 << state->hw_reset.rst_bit, 1 << state->hw_reset.rst_bit);
+ msleep(20);
+ regmap_update_bits(state->hw_reset.src, state->hw_reset.req_src,
+ 1 << state->hw_reset.rst_bit, 0);
+
+ }
+ return ret;
+}
+
+static void mipi_csis_system_enable(struct csi_state *state, int on)
+{
+ u32 val, mask;
+
+ val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+ if (on)
+ val |= MIPI_CSIS_CMN_CTRL_ENABLE;
+ else
+ val &= ~MIPI_CSIS_CMN_CTRL_ENABLE;
+ mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
+
+ val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL);
+ val &= ~MIPI_CSIS_DPHYCTRL_ENABLE;
+ if (on) {
+ mask = (1 << (state->num_lanes + 1)) - 1;
+ val |= (mask & MIPI_CSIS_DPHYCTRL_ENABLE);
+ }
+ mipi_csis_write(state, MIPI_CSIS_DPHYCTRL, val);
+}
+
+/* Called with the state.lock mutex held */
+static void __mipi_csis_set_format(struct csi_state *state)
+{
+ struct v4l2_mbus_framefmt *mf = &state->format;
+ u32 val;
+
+ v4l2_dbg(1, debug, &state->mipi_sd, "fmt: %#x, %d x %d\n",
+ mf->code, mf->width, mf->height);
+
+ /* Color format */
+ val = mipi_csis_read(state, MIPI_CSIS_ISPCONFIG_CH0);
+ val = (val & ~MIPI_CSIS_ISPCFG_FMT_MASK) | state->csis_fmt->fmt_reg;
+ mipi_csis_write(state, MIPI_CSIS_ISPCONFIG_CH0, val);
+
+ /* Pixel resolution */
+ val = mf->width | (mf->height << 16);
+ mipi_csis_write(state, MIPI_CSIS_ISPRESOL_CH0, val);
+}
+
+static void mipi_csis_set_hsync_settle(struct csi_state *state,
+ int hs_settle, int clk_settle)
+{
+ u32 val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL);
+
+ val = (val & ~MIPI_CSIS_DPHYCTRL_HSS_MASK) |
+ (hs_settle << 24) | (clk_settle << 22);
+
+ mipi_csis_write(state, MIPI_CSIS_DPHYCTRL, val);
+}
+
+static void mipi_csis_set_params(struct csi_state *state)
+{
+ u32 val;
+
+ val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+ val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
+ val |= (state->num_lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
+ mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
+
+ __mipi_csis_set_format(state);
+
+ mipi_csis_set_hsync_settle(state, state->hs_settle, state->clk_settle);
+
+ val = mipi_csis_read(state, MIPI_CSIS_ISPCONFIG_CH0);
+ if (state->csis_fmt->data_alignment == 32)
+ val |= MIPI_CSIS_ISPCFG_ALIGN_32BIT;
+ else /* Normal output */
+ val &= ~MIPI_CSIS_ISPCFG_ALIGN_32BIT;
+ mipi_csis_write(state, MIPI_CSIS_ISPCONFIG_CH0, val);
+
+ val = (0 << MIPI_CSIS_ISPSYNC_HSYNC_LINTV_OFFSET) |
+ (0 << MIPI_CSIS_ISPSYNC_VSYNC_SINTV_OFFSET) |
+ (0 << MIPI_CSIS_ISPSYNC_VSYNC_EINTV_OFFSET);
+ mipi_csis_write(state, MIPI_CSIS_ISPSYNC_CH0, val);
+
+ val = mipi_csis_read(state, MIPI_CSIS_CLK_CTRL);
+ val &= ~MIPI_CSIS_CLK_CTRL_WCLK_SRC;
+ if (state->wclk_ext)
+ val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC;
+ val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15);
+ val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK;
+ mipi_csis_write(state, MIPI_CSIS_CLK_CTRL, val);
+
+ mipi_csis_write(state, MIPI_CSIS_DPHYBCTRL_L, 0x1f4);
+ mipi_csis_write(state, MIPI_CSIS_DPHYBCTRL_H, 0);
+
+ /* Update the shadow register. */
+ val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+ mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW |
+ MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL);
+}
+
+static void mipi_csis_clk_enable(struct csi_state *state)
+{
+ clk_prepare_enable(state->mipi_clk);
+ clk_prepare_enable(state->phy_clk);
+}
+
+static void mipi_csis_clk_disable(struct csi_state *state)
+{
+ clk_disable_unprepare(state->mipi_clk);
+ clk_disable_unprepare(state->phy_clk);
+}
+
+static int mipi_csis_clk_get(struct csi_state *state)
+{
+ struct device *dev = &state->pdev->dev;
+ int ret = true;
+
+ state->mipi_clk = devm_clk_get(dev, "mipi_clk");
+ if (IS_ERR(state->mipi_clk)) {
+ dev_err(dev, "Could not get mipi csi clock\n");
+ return -ENODEV;
+ }
+
+ state->phy_clk = devm_clk_get(dev, "phy_clk");
+ if (IS_ERR(state->phy_clk)) {
+ dev_err(dev, "Could not get mipi phy clock\n");
+ return -ENODEV;
+ }
+
+ /* Set clock rate */
+ if (state->clk_frequency)
+ ret = clk_set_rate(state->mipi_clk,
+ state->clk_frequency);
+ else
+ dev_WARN(dev, "No clock frequency specified!\n");
+ if (ret < 0) {
+ dev_err(dev, "set rate filed, rate=%d\n", state->clk_frequency);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static void dump_regs(struct csi_state *state, const char *label)
+{
+ struct {
+ u32 offset;
+ const char * const name;
+ } registers[] = {
+ { 0x00, "CTRL" },
+ { 0x04, "DPHYCTRL" },
+ { 0x08, "CONFIG" },
+ { 0x0c, "DPHYSTS" },
+ { 0x10, "INTMSK" },
+ { 0x2c, "RESOL" },
+ { 0x38, "SDW_CONFIG" },
+ };
+ u32 i;
+
+ v4l2_info(&state->mipi_sd, "--- %s ---\n", label);
+
+ for (i = 0; i < ARRAY_SIZE(registers); i++) {
+ u32 cfg = mipi_csis_read(state, registers[i].offset);
+ v4l2_info(&state->mipi_sd, "%10s: 0x%08x\n", registers[i].name, cfg);
+ }
+}
+
+static void mipi_csis_start_stream(struct csi_state *state)
+{
+ mipi_csis_sw_reset(state);
+ mipi_csis_set_params(state);
+ mipi_csis_system_enable(state, true);
+ mipi_csis_enable_interrupts(state, true);
+}
+
+static void mipi_csis_stop_stream(struct csi_state *state)
+{
+ mipi_csis_enable_interrupts(state, false);
+ mipi_csis_system_enable(state, false);
+}
+
+static void mipi_csis_clear_counters(struct csi_state *state)
+{
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&state->slock, flags);
+ for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++)
+ state->events[i].counter = 0;
+ spin_unlock_irqrestore(&state->slock, flags);
+}
+
+static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
+{
+ int i = non_errors ? MIPI_CSIS_NUM_EVENTS : MIPI_CSIS_NUM_EVENTS - 4;
+ unsigned long flags;
+
+ spin_lock_irqsave(&state->slock, flags);
+
+ for (i--; i >= 0; i--) {
+ if (state->events[i].counter > 0 || debug)
+ v4l2_info(&state->mipi_sd, "%s events: %d\n",
+ state->events[i].name,
+ state->events[i].counter);
+ }
+ spin_unlock_irqrestore(&state->slock, flags);
+}
+
+/*
+ * V4L2 subdev operations
+ */
+static int mipi_csis_s_power(struct v4l2_subdev *mipi_sd, int on)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ struct device *dev = &state->pdev->dev;
+
+ v4l2_subdev_call(state->sensor_sd, core, s_power, on);
+
+ if (on)
+ return pm_runtime_get_sync(dev);
+
+ return pm_runtime_put_sync(dev);
+}
+
+static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ int ret = 0;
+
+ v4l2_dbg(1, debug, mipi_sd, "%s: %d, state: 0x%x\n",
+ __func__, enable, state->flags);
+
+ if (enable) {
+ mipi_csis_clear_counters(state);
+ ret = pm_runtime_get_sync(&state->pdev->dev);
+ if (ret && ret != 1)
+ return ret;
+ }
+
+ mutex_lock(&state->lock);
+ if (enable) {
+ if (state->flags & ST_SUSPENDED) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+ mipi_csis_start_stream(state);
+ v4l2_subdev_call(state->sensor_sd, video, s_stream, true);
+ state->flags |= ST_STREAMING;
+ } else {
+ v4l2_subdev_call(state->sensor_sd, video, s_stream, false);
+ mipi_csis_stop_stream(state);
+ state->flags &= ~ST_STREAMING;
+ if (debug > 0)
+ mipi_csis_log_counters(state, true);
+ }
+unlock:
+ mutex_unlock(&state->lock);
+ if (!enable)
+ pm_runtime_put(&state->pdev->dev);
+
+ return ret == 1 ? 0 : ret;
+}
+
+static int mipi_csis_enum_mbus_code(struct v4l2_subdev *mipi_sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ struct v4l2_subdev *sensor_sd = state->sensor_sd;
+ struct csis_pix_format const *csis_fmt;
+ int ret;
+
+ ret = v4l2_subdev_call(sensor_sd, pad, enum_mbus_code, NULL, code);
+ if (ret < 0)
+ return -EINVAL;
+
+ csis_fmt = find_csis_format(code->code);
+ if (csis_fmt == NULL) {
+ dev_err(state->dev, "format not match\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ struct v4l2_subdev *sensor_sd = state->sensor_sd;
+ struct csis_pix_format const *csis_fmt;
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
+
+ csis_fmt = find_csis_format(mf->code);
+ if (csis_fmt == NULL)
+ csis_fmt = &mipi_csis_formats[0];
+
+ v4l2_subdev_call(sensor_sd, pad, set_fmt, NULL, format);
+
+ mf->code = csis_fmt->code;
+ v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
+ csis_fmt->pix_width_alignment,
+ &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
+ 0);
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
+ state->format.code = mf->code;
+ state->format.width = mf->width;
+ state->format.height = mf->height;
+
+ mutex_lock(&state->lock);
+ state->csis_fmt = csis_fmt;
+ mutex_unlock(&state->lock);
+
+ return 0;
+}
+
+static int mipi_csis_get_fmt(struct v4l2_subdev *mipi_sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+ if (format->pad)
+ return -EINVAL;
+
+ return v4l2_subdev_call(sensor_sd, pad, get_fmt, NULL, format);
+}
+
+static int mipi_csis_s_rx_buffer(struct v4l2_subdev *mipi_sd, void *buf,
+ unsigned int *size)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ unsigned long flags;
+
+ *size = min_t(unsigned int, *size, MIPI_CSIS_PKTDATA_SIZE);
+
+ spin_lock_irqsave(&state->slock, flags);
+ state->pkt_buf.data = buf;
+ state->pkt_buf.len = *size;
+ spin_unlock_irqrestore(&state->slock, flags);
+
+ return 0;
+}
+
+static int mipi_csis_s_parm(struct v4l2_subdev *mipi_sd, struct v4l2_streamparm *a)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+ return v4l2_subdev_call(sensor_sd, video, s_parm, a);
+}
+
+static int mipi_csis_g_parm(struct v4l2_subdev *mipi_sd, struct v4l2_streamparm *a)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+ return v4l2_subdev_call(sensor_sd, video, g_parm, a);
+}
+
+static int mipi_csis_enum_framesizes(struct v4l2_subdev *mipi_sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+ return v4l2_subdev_call(sensor_sd, pad, enum_frame_size, NULL, fse);
+}
+
+static int mipi_csis_enum_frameintervals(struct v4l2_subdev *mipi_sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+ struct v4l2_subdev *sensor_sd = state->sensor_sd;
+
+ return v4l2_subdev_call(sensor_sd, pad, enum_frame_interval, NULL, fie);
+}
+
+static int mipi_csis_log_status(struct v4l2_subdev *mipi_sd)
+{
+ struct csi_state *state = mipi_sd_to_csi_state(mipi_sd);
+
+ mutex_lock(&state->lock);
+ mipi_csis_log_counters(state, true);
+ if (debug && (state->flags & ST_POWERED))
+ dump_regs(state, __func__);
+ mutex_unlock(&state->lock);
+ return 0;
+}
+
+static struct v4l2_subdev_core_ops mipi_csis_core_ops = {
+ .s_power = mipi_csis_s_power,
+ .log_status = mipi_csis_log_status,
+};
+
+static struct v4l2_subdev_video_ops mipi_csis_video_ops = {
+ .s_rx_buffer = mipi_csis_s_rx_buffer,
+ .s_stream = mipi_csis_s_stream,
+
+ .s_parm = mipi_csis_s_parm,
+ .g_parm = mipi_csis_g_parm,
+};
+
+static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = {
+ .enum_frame_size = mipi_csis_enum_framesizes,
+ .enum_frame_interval = mipi_csis_enum_frameintervals,
+ .enum_mbus_code = mipi_csis_enum_mbus_code,
+ .get_fmt = mipi_csis_get_fmt,
+ .set_fmt = mipi_csis_set_fmt,
+};
+
+static struct v4l2_subdev_ops mipi_csis_subdev_ops = {
+ .core = &mipi_csis_core_ops,
+ .video = &mipi_csis_video_ops,
+ .pad = &mipi_csis_pad_ops,
+};
+
+static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
+{
+ struct csi_state *state = dev_id;
+ struct csis_pktbuf *pktbuf = &state->pkt_buf;
+ unsigned long flags;
+ u32 status;
+
+ status = mipi_csis_read(state, MIPI_CSIS_INTSRC);
+
+ spin_lock_irqsave(&state->slock, flags);
+
+ if ((status & MIPI_CSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
+ u32 offset;
+
+ if (status & MIPI_CSIS_INTSRC_EVEN)
+ offset = MIPI_CSIS_PKTDATA_EVEN;
+ else
+ offset = MIPI_CSIS_PKTDATA_ODD;
+
+ memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
+ pktbuf->data = NULL;
+ rmb();
+ }
+
+ /* Update the event/error counters */
+ if ((status & MIPI_CSIS_INTSRC_ERRORS) || debug) {
+ int i;
+ for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) {
+ if (!(status & state->events[i].mask))
+ continue;
+ state->events[i].counter++;
+ v4l2_dbg(2, debug, &state->mipi_sd, "%s: %d\n",
+ state->events[i].name,
+ state->events[i].counter);
+ }
+ v4l2_dbg(2, debug, &state->mipi_sd, "status: %08x\n", status);
+ }
+ spin_unlock_irqrestore(&state->slock, flags);
+
+ mipi_csis_write(state, MIPI_CSIS_INTSRC, status);
+ return IRQ_HANDLED;
+}
+
+static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *subdev,
+ struct v4l2_async_subdev *asd)
+{
+ struct csi_state *state = notifier_to_mipi_dev(notifier);
+
+ /* Find platform data for this sensor subdev */
+ if (state->asd.match.of.node == subdev->dev->of_node)
+ state->sensor_sd = subdev;
+
+ if (subdev == NULL)
+ return -EINVAL;
+
+ v4l2_info(&state->v4l2_dev, "Registered sensor subdevice: %s\n",
+ subdev->name);
+
+ return 0;
+}
+
+static int mipi_csis_parse_dt(struct platform_device *pdev,
+ struct csi_state *state)
+{
+ struct device_node *node = pdev->dev.of_node;
+
+ if (of_property_read_u32(node, "clock-frequency",
+ &state->clk_frequency))
+ state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
+ if (of_property_read_u32(node, "bus-width",
+ &state->max_num_lanes))
+ return -EINVAL;
+
+ node = of_graph_get_next_endpoint(node, NULL);
+ if (!node) {
+ dev_err(&pdev->dev, "No port node at %s\n",
+ pdev->dev.of_node->full_name);
+ return -EINVAL;
+ }
+
+ /* Get MIPI CSI-2 bus configration from the endpoint node. */
+ of_property_read_u32(node, "csis-hs-settle",
+ &state->hs_settle);
+
+ of_property_read_u32(node, "csis-clk-settle",
+ &state->clk_settle);
+ state->wclk_ext = of_property_read_bool(node,
+ "csis-wclk");
+
+ of_property_read_u32(node, "data-lanes",
+ &state->num_lanes);
+ of_node_put(node);
+
+ return 0;
+}
+
+static int mipi_csis_pm_resume(struct device *dev, bool runtime);
+static const struct of_device_id mipi_csis_of_match[];
+
+/* register parent dev */
+static int mipi_csis_subdev_host(struct csi_state *state)
+{
+ struct device_node *parent = state->dev->of_node;
+ struct device_node *node, *port, *rem;
+ int ret;
+
+ /* Attach sensors linked to csi receivers */
+ for_each_available_child_of_node(parent, node) {
+ if (of_node_cmp(node->name, "port"))
+ continue;
+
+ /* The csi node can have only port subnode. */
+ port = of_get_next_child(node, NULL);
+ if (!port)
+ continue;
+ rem = of_graph_get_remote_port_parent(port);
+ of_node_put(port);
+ if (rem == NULL) {
+ v4l2_info(&state->v4l2_dev,
+ "Remote device at %s not found\n",
+ port->full_name);
+ return -1;
+ }
+
+ state->asd.match_type = V4L2_ASYNC_MATCH_OF;
+ state->asd.match.of.node = rem;
+ state->async_subdevs[0] = &state->asd;
+
+ of_node_put(rem);
+ break;
+ }
+
+ state->subdev_notifier.subdevs = state->async_subdevs;
+ state->subdev_notifier.num_subdevs = 1;
+ state->subdev_notifier.bound = subdev_notifier_bound;
+
+ ret = v4l2_async_notifier_register(&state->v4l2_dev,
+ &state->subdev_notifier);
+ if (ret)
+ dev_err(state->dev,
+ "Error register async notifier regoster\n");
+
+ return ret;
+}
+
+/* init subdev */
+static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
+ struct platform_device *pdev,
+ const struct v4l2_subdev_ops *ops)
+{
+ struct csi_state *state = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ v4l2_subdev_init(mipi_sd, ops);
+ mipi_sd->owner = THIS_MODULE;
+ snprintf(mipi_sd->name, sizeof(mipi_sd->name), "%s.%d",
+ CSIS_SUBDEV_NAME, state->index);
+ mipi_sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ mipi_sd->dev = &pdev->dev;
+
+ state->csis_fmt = &mipi_csis_formats[0];
+ state->format.code = mipi_csis_formats[0].code;
+ state->format.width = MIPI_CSIS_DEF_PIX_WIDTH;
+ state->format.height = MIPI_CSIS_DEF_PIX_HEIGHT;
+
+ /* This allows to retrieve the platform device id by the host driver */
+ v4l2_set_subdevdata(mipi_sd, pdev);
+
+ ret = v4l2_async_register_subdev(mipi_sd);
+ if (ret < 0)
+ dev_err(&pdev->dev, "%s--Async register faialed, ret=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int mipi_csis_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct v4l2_subdev *mipi_sd;
+ struct resource *mem_res;
+ struct csi_state *state;
+ int ret = -ENOMEM;
+
+ state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ mutex_init(&state->lock);
+ spin_lock_init(&state->slock);
+
+ state->pdev = pdev;
+ mipi_sd = &state->mipi_sd;
+ state->dev = dev;
+
+ ret = mipi_csis_parse_dt(pdev, state);
+ if (ret < 0)
+ return ret;
+
+ if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
+ dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
+ state->num_lanes, state->max_num_lanes);
+ return -EINVAL;
+ }
+
+ mipi_csis_phy_init(state);
+ mipi_csis_phy_reset(state);
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ state->regs = devm_ioremap_resource(dev, mem_res);
+ if (IS_ERR(state->regs))
+ return PTR_ERR(state->regs);
+
+ state->irq = platform_get_irq(pdev, 0);
+ if (state->irq < 0) {
+ dev_err(dev, "Failed to get irq\n");
+ return state->irq;
+ }
+
+ ret = mipi_csis_clk_get(state);
+ if (ret < 0)
+ return ret;
+
+ mipi_csis_clk_enable(state);
+
+ ret = devm_request_irq(dev, state->irq, mipi_csis_irq_handler,
+ 0, dev_name(dev), state);
+ if (ret) {
+ dev_err(dev, "Interrupt request failed\n");
+ goto e_clkdis;
+ }
+
+ /* First register a v4l2 device */
+ ret = v4l2_device_register(dev, &state->v4l2_dev);
+ if (ret) {
+ v4l2_err(dev->driver,
+ "Unable to register v4l2 device.\n");
+ goto e_clkdis;
+ }
+ v4l2_info(&state->v4l2_dev, "mipi csi v4l2 device registered\n");
+
+ /* .. and a pointer to the subdev. */
+ platform_set_drvdata(pdev, state);
+
+ ret = mipi_csis_subdev_init(&state->mipi_sd, pdev, &mipi_csis_subdev_ops);
+ if (ret < 0)
+ goto e_sd_mipi;
+
+ memcpy(state->events, mipi_csis_events, sizeof(state->events));
+
+ /* subdev host register */
+ ret = mipi_csis_subdev_host(state);
+ if (ret < 0)
+ goto e_sd_host;
+
+ pm_runtime_enable(dev);
+ if (!pm_runtime_enabled(dev)) {
+ ret = mipi_csis_pm_resume(dev, true);
+ if (ret < 0)
+ goto e_sd_host;
+ }
+
+ dev_info(&pdev->dev,
+ "lanes: %d, hs_settle: %d, clk_settle: %d, wclk: %d, freq: %u\n",
+ state->num_lanes, state->hs_settle, state->clk_settle,
+ state->wclk_ext, state->clk_frequency);
+ return 0;
+
+e_sd_host:
+ v4l2_async_notifier_unregister(&state->subdev_notifier);
+ v4l2_device_unregister(&state->v4l2_dev);
+e_sd_mipi:
+ v4l2_async_unregister_subdev(&state->mipi_sd);
+e_clkdis:
+ mipi_csis_clk_disable(state);
+ return ret;
+}
+
+static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct csi_state *state = platform_get_drvdata(pdev);
+ struct v4l2_subdev *mipi_sd = &state->mipi_sd;
+ int ret = 0;
+
+ v4l2_dbg(1, debug, mipi_sd, "%s: flags: 0x%x\n",
+ __func__, state->flags);
+
+ mutex_lock(&state->lock);
+ if (state->flags & ST_POWERED) {
+ mipi_csis_stop_stream(state);
+ ret = regulator_disable(state->mipi_phy_regulator);
+ if (ret)
+ goto unlock;
+ mipi_csis_clk_disable(state);
+ state->flags &= ~ST_POWERED;
+ if (!runtime)
+ state->flags |= ST_SUSPENDED;
+ }
+ unlock:
+ mutex_unlock(&state->lock);
+ return ret ? -EAGAIN : 0;
+}
+
+static int mipi_csis_pm_resume(struct device *dev, bool runtime)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct csi_state *state = platform_get_drvdata(pdev);
+ struct v4l2_subdev *mipi_sd = &state->mipi_sd;
+ int ret = 0;
+
+ v4l2_dbg(1, debug, mipi_sd, "%s: flags: 0x%x\n",
+ __func__, state->flags);
+
+ mutex_lock(&state->lock);
+ if (!runtime && !(state->flags & ST_SUSPENDED))
+ goto unlock;
+
+ if (!(state->flags & ST_POWERED)) {
+ ret = regulator_enable(state->mipi_phy_regulator);
+ if (!ret) {
+ state->flags |= ST_POWERED;
+ } else {
+ goto unlock;
+ }
+ mipi_csis_clk_enable(state);
+ }
+ if (state->flags & ST_STREAMING)
+ mipi_csis_start_stream(state);
+
+ state->flags &= ~ST_SUSPENDED;
+ unlock:
+ mutex_unlock(&state->lock);
+ return ret ? -EAGAIN : 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mipi_csis_suspend(struct device *dev)
+{
+ return mipi_csis_pm_suspend(dev, false);
+}
+
+static int mipi_csis_resume(struct device *dev)
+{
+ return mipi_csis_pm_resume(dev, false);
+}
+#endif
+
+static int mipi_csis_runtime_suspend(struct device *dev)
+{
+ return mipi_csis_pm_suspend(dev, true);
+}
+
+static int mipi_csis_runtime_resume(struct device *dev)
+{
+ return mipi_csis_pm_resume(dev, true);
+}
+
+static int mipi_csis_remove(struct platform_device *pdev)
+{
+ struct csi_state *state = platform_get_drvdata(pdev);
+
+ v4l2_async_unregister_subdev(&state->mipi_sd);
+ v4l2_async_notifier_unregister(&state->subdev_notifier);
+ v4l2_device_unregister(&state->v4l2_dev);
+
+ pm_runtime_disable(&pdev->dev);
+ mipi_csis_pm_suspend(&pdev->dev, true);
+ mipi_csis_clk_disable(state);
+ pm_runtime_set_suspended(&pdev->dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops mipi_csis_pm_ops = {
+ SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume,
+ NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume)
+};
+
+static const struct of_device_id mipi_csis_of_match[] = {
+ { .compatible = "fsl,imx7d-mipi-csi",},
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
+
+static struct platform_driver mipi_csis_driver = {
+ .probe = mipi_csis_probe,
+ .remove = mipi_csis_remove,
+ .driver = {
+ .of_match_table = mipi_csis_of_match,
+ .name = CSIS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &mipi_csis_pm_ops,
+ },
+};
+
+module_platform_driver(mipi_csis_driver);
+
+MODULE_DESCRIPTION("Freescale MIPI-CSI2 receiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/subdev/mxc_vadc.c b/drivers/media/platform/mxc/subdev/mxc_vadc.c
new file mode 100644
index 000000000000..2a844ca8ab5d
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/mxc_vadc.c
@@ -0,0 +1,830 @@
+/*
+ * 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.
+
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/media-bus-format.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include "mxc_vadc.h"
+
+/* Resource names for the VADC driver. */
+#define VAFE_REGS_ADDR_RES_NAME "vadc-vafe"
+#define VDEC_REGS_ADDR_RES_NAME "vadc-vdec"
+
+#define reg32_write(addr, val) __raw_writel(val, addr)
+#define reg32_read(addr) __raw_readl(addr)
+#define reg32setbit(addr, bitpos) \
+ reg32_write((addr), (reg32_read((addr)) | (1<<(bitpos))))
+
+#define reg32clrbit(addr, bitpos) \
+ reg32_write((addr), (reg32_read((addr)) & (0xFFFFFFFF ^ (1<<(bitpos)))))
+
+#define GPC_CNTR 0x00
+#define IMX6SX_GPC_CNTR_VADC_ANALOG_OFF_MASK BIT(17)
+#define IMX6SX_GPC_CNTR_VADC_POWER_DOWN_MASK BIT(18)
+
+void __iomem *vafe_regbase;
+void __iomem *vdec_regbase;
+
+
+/* List of input video formats supported. The video formats is corresponding
+ * with v4l2 id in video_fmt
+ */
+enum video_fmt_idx {
+ VADC_NTSC = 0, /* Locked on (M) NTSC video signal. */
+ VADC_PAL, /* (B, G, H, I, N)PAL video signal. */
+};
+
+/* Number of video standards supported (including 'not locked' signal). */
+#define VADC_STD_MAX (VADC_PAL + 1)
+
+/* Video format structure. */
+struct video_fmt{
+ v4l2_std_id v4l2_std; /* Video for linux ID. */
+ char name[16]; /* Name (e.g., "NTSC", "PAL", etc.) */
+ u16 raw_width; /* Raw width. */
+ u16 raw_height; /* Raw height. */
+ u16 active_width; /* Active width. */
+ u16 active_height; /* Active height. */
+ u16 framerates;
+};
+
+/*
+ * Maintains the information on the current state of the sensor.
+ */
+struct vadc_state {
+ struct v4l2_device v4l2_dev;
+ struct v4l2_subdev sd;
+ struct video_fmt *fmt;
+
+ struct clk *vadc_clk;
+ struct clk *csi_clk;
+ struct regmap *gpr;
+ void __iomem *gpc_reg;
+
+ u32 vadc_in;
+ u32 csi_id;
+};
+
+static int vadc_querystd(struct v4l2_subdev *sd, v4l2_std_id *std);
+
+/* Description of video formats supported.
+ *
+ * PAL: raw=720x625, active=720x576.
+ * NTSC: raw=720x525, active=720x480.
+ */
+static struct video_fmt video_fmts[] = {
+ /* NTSC */
+ {
+ .v4l2_std = V4L2_STD_NTSC,
+ .name = "NTSC",
+ .raw_width = 720,
+ .raw_height = 525,
+ .active_width = 720,
+ .active_height = 480,
+ .framerates = 30,
+ },
+ /* (B, G, H, I, N) PAL */
+ {
+ .v4l2_std = V4L2_STD_PAL,
+ .name = "PAL",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ .framerates = 25,
+ },
+};
+
+static void afe_voltage_clampingmode(void)
+{
+ reg32_write(AFE_CLAMP, 0x07);
+ reg32_write(AFE_CLMPAMP, 0x60);
+ reg32_write(AFE_CLMPDAT, 0xF0);
+}
+
+static void afe_alwayson_clampingmode(void)
+{
+ reg32_write(AFE_CLAMP, 0x15);
+ reg32_write(AFE_CLMPDAT, 0x08);
+ reg32_write(AFE_CLMPAMP, 0x00);
+}
+
+static void afe_init(void)
+{
+ pr_debug("%s\n", __func__);
+
+ reg32_write(AFE_PDBUF, 0x1f);
+ reg32_write(AFE_PDADC, 0x0f);
+ reg32_write(AFE_PDSARH, 0x01);
+ reg32_write(AFE_PDSARL, 0xff);
+ reg32_write(AFE_PDADCRFH, 0x01);
+ reg32_write(AFE_PDADCRFL, 0xff);
+ reg32_write(AFE_ICTRL, 0x3a);
+ reg32_write(AFE_ICTLSTG, 0x1e);
+
+ reg32_write(AFE_RCTRLSTG, 0x1e);
+ reg32_write(AFE_INPBUF, 0x035);
+ reg32_write(AFE_INPFLT, 0x02);
+ reg32_write(AFE_ADCDGN, 0x40);
+ reg32_write(AFE_TSTSEL, 0x10);
+
+ reg32_write(AFE_ACCTST, 0x07);
+
+ reg32_write(AFE_BGREG, 0x08);
+
+ reg32_write(AFE_ADCGN, 0x09);
+
+ /* set current controlled clamping
+ * always on, low current */
+ reg32_write(AFE_CLAMP, 0x11);
+ reg32_write(AFE_CLMPAMP, 0x08);
+}
+
+static void vdec_mode_timing_init(int std)
+{
+ if (std == V4L2_STD_NTSC) {
+ /* NTSC 720x480 */
+ reg32_write(VDEC_HACTS, 0x66);
+ reg32_write(VDEC_HACTE, 0x24);
+
+ reg32_write(VDEC_VACTS, 0x29);
+ reg32_write(VDEC_VACTE, 0x04);
+
+ /* set V Position */
+ reg32_write(VDEC_VRTPOS, 0x2);
+ } else if (std == V4L2_STD_PAL) {
+ /* PAL 720x576 */
+ reg32_write(VDEC_HACTS, 0x66);
+ reg32_write(VDEC_HACTE, 0x24);
+
+ reg32_write(VDEC_VACTS, 0x29);
+ reg32_write(VDEC_VACTE, 0x04);
+
+ /* set V Position */
+ reg32_write(VDEC_VRTPOS, 0x6);
+ } else
+ pr_debug("Error not support video mode\n");
+
+ /* set H Position */
+ reg32_write(VDEC_HZPOS, 0x60);
+
+ /* set H ignore start */
+ reg32_write(VDEC_HSIGS, 0xf8);
+
+ /* set H ignore end */
+ reg32_write(VDEC_HSIGE, 0x18);
+}
+
+/*
+* vdec_init()
+* Initialises the VDEC registers
+* Returns: nothing
+*/
+static void vdec_init(struct vadc_state *vadc)
+{
+ v4l2_std_id std;
+
+ pr_debug("%s\n", __func__);
+
+ /* Get work mode PAL or NTSC */
+ vadc_querystd(&vadc->sd, &std);
+
+ vdec_mode_timing_init(std);
+
+ /* vcr detect threshold high, automatic detections */
+ reg32_write(VDEC_VSCON2, 0);
+
+ reg32_write(VDEC_BASE + 0x110, 0x01);
+
+ /* set the noramp mode on the Hloop PLL. */
+ reg32_write(VDEC_BASE+(0x14*4), 0x10);
+
+ /* set the YC relative delay.*/
+ reg32_write(VDEC_YCDEL, 0x90);
+
+ /* setup the Hpll */
+ reg32_write(VDEC_BASE+(0x13*4), 0x13);
+
+ /* setup the 2d comb */
+ /* set the gain of the Hdetail output to 3
+ * set the notch alpha gain to 1 */
+ reg32_write(VDEC_CFC2, 0x34);
+
+ /* setup various 2d comb bits.*/
+ reg32_write(VDEC_BASE+(0x02*4), 0x01);
+ reg32_write(VDEC_BASE+(0x03*4), 0x18);
+ reg32_write(VDEC_BASE+(0x04*4), 0x34);
+
+ /* set the start of the burst gate */
+ reg32_write(VDEC_BRSTGT, 0x30);
+
+ /* set 1f motion gain */
+ reg32_write(VDEC_BASE+(0x0f*4), 0x20);
+
+ /* set the 1F chroma motion detector thresh
+ * for colour reverse detection */
+ reg32_write(VDEC_THSH1, 0x02);
+ reg32_write(VDEC_BASE+(0x4a*4), 0x20);
+ reg32_write(VDEC_BASE+(0x4b*4), 0x08);
+
+ reg32_write(VDEC_BASE+(0x4c*4), 0x08);
+
+ /* set the threshold for the narrow/wide adaptive chroma BW */
+ reg32_write(VDEC_BASE+(0x20*4), 0x20);
+
+ /* turn up the colour with the new colour gain reg */
+ /* hue: */
+ reg32_write(VDEC_HUE, 0x00);
+
+ /* cbgain: 22 B4 */
+ reg32_write(VDEC_CBGN, 0xb4);
+ /* cr gain 80 */
+ reg32_write(VDEC_CRGN, 0x80);
+ /* luma gain (contrast) */
+ reg32_write(VDEC_CNTR, 0x80);
+
+ /* setup the signed black level register, brightness */
+ reg32_write(VDEC_BRT, 0x00);
+
+ /* filter the standard detection
+ * enable the comb for the ntsc443 */
+ reg32_write(VDEC_STDDBG, 0x20);
+
+ /* setup chroma kill thresh for no chroma */
+ reg32_write(VDEC_CHBTH, 0x0);
+
+ /* set chroma loop to wider BW
+ * no set it to normal BW. i fixed the bw problem.*/
+ reg32_write(VDEC_YCDEL, 0x00);
+
+ /* set the compensation in the chroma loop for the Hloop
+ * set the ratio for the nonarithmetic 3d comb modes.*/
+ reg32_write(VDEC_BASE + (0x1d*4), 0x90);
+
+ /* set the threshold for the nonarithmetic mode for the 2d comb
+ * the higher the value the more Fc Fh offset
+ * we will tolerate before turning off the comb. */
+ reg32_write(VDEC_BASE + (0x33*4), 0xa0);
+
+ /* setup the bluescreen output colour */
+ reg32_write(VDEC_BASE + (0x3d*4), 35);
+ reg32_write(VDEC_BLSCRCR, 114);
+ reg32_write(VDEC_BLSCRCB, 212);
+
+ /* disable the active blanking */
+ reg32_write(VDEC_BASE + (0x15*4), 0x02);
+
+ /* setup the luma agc for automatic gain. */
+ reg32_write(VDEC_LMAGC2, 0x5e);
+ reg32_write(VDEC_LMAGC1, 0x81);
+
+ /* setup chroma agc */
+ reg32_write(VDEC_CHAGC2, 0xa0);
+ reg32_write(VDEC_CHAGC1, 0x01);
+
+ /* setup the MV thresh lower nibble
+ * setup the sync top cap, upper nibble */
+ reg32_write(VDEC_BASE + (0x3a*4), 0x80);
+ reg32_write(VDEC_SHPIMP, 0x00);
+
+ /* setup the vsync block */
+ reg32_write(VDEC_VSCON1, 0x87);
+
+ /* set the nosignal threshold
+ * set the vsync threshold */
+ reg32_write(VDEC_VSSGTH, 0x35);
+
+ /* set length for min hphase filter
+ * (or saturate limit if saturate is chosen) */
+ reg32_write(VDEC_BASE + (0x45*4), 0x40);
+
+ /* enable the internal resampler,
+ * select min filter not saturate for
+ * hphase noise filter for vcr detect.
+ * enable vcr pause mode different field lengths */
+ reg32_write(VDEC_BASE + (0x46*4), 0x90);
+
+ /* disable VCR detection, lock to the Hsync rather than the Vsync */
+ reg32_write(VDEC_VSCON2, 0x04);
+
+ /* set tiplevel goal for dc clamp. */
+ reg32_write(VDEC_BASE + (0x3c*4), 0xB0);
+
+ /* override SECAM detection and force SECAM off */
+ reg32_write(VDEC_BASE + (0x2f*4), 0x20);
+
+ /* Set r3d_hardblend in 3D control2 reg */
+ reg32_write(VDEC_BASE + (0x0c*4), 0x04);
+}
+
+/* set Input selector & input pull-downs */
+static void vadc_s_routing(int vadc_in)
+{
+ switch (vadc_in) {
+ case 0:
+ reg32_write(AFE_INPFLT, 0x02);
+ reg32_write(AFE_OFFDRV, 0x00);
+ reg32_write(AFE_INPCONFIG, 0x1e);
+ break;
+ case 1:
+ reg32_write(AFE_INPFLT, 0x02);
+ reg32_write(AFE_OFFDRV, 0x00);
+ reg32_write(AFE_INPCONFIG, 0x2d);
+ break;
+ case 2:
+ reg32_write(AFE_INPFLT, 0x02);
+ reg32_write(AFE_OFFDRV, 0x00);
+ reg32_write(AFE_INPCONFIG, 0x4b);
+ break;
+ case 3:
+ reg32_write(AFE_INPFLT, 0x02);
+ reg32_write(AFE_OFFDRV, 0x00);
+ reg32_write(AFE_INPCONFIG, 0x87);
+ break;
+ default:
+ pr_debug("error video input %d\n", vadc_in);
+ }
+}
+
+static void vadc_power_up(struct vadc_state *state)
+{
+ /* Power on vadc analog */
+ reg32clrbit(state->gpc_reg + GPC_CNTR, 17);
+
+ /* Power down vadc ext power */
+ reg32clrbit(state->gpc_reg + GPC_CNTR, 18);
+
+ /* software reset afe */
+ regmap_update_bits(state->gpr, IOMUXC_GPR1,
+ IMX6SX_GPR1_VADC_SW_RST_MASK,
+ IMX6SX_GPR1_VADC_SW_RST_RESET);
+
+ msleep(10);
+
+ /* clock config for vadc */
+ reg32_write(VDEC_BASE + 0x320, 0xe3);
+ reg32_write(VDEC_BASE + 0x324, 0x38);
+ reg32_write(VDEC_BASE + 0x328, 0x8e);
+ reg32_write(VDEC_BASE + 0x32c, 0x23);
+
+ /* Release reset bit */
+ regmap_update_bits(state->gpr, IOMUXC_GPR1,
+ IMX6SX_GPR1_VADC_SW_RST_MASK,
+ IMX6SX_GPR1_VADC_SW_RST_RELEASE);
+
+ /* Power on vadc ext power */
+ reg32setbit(state->gpc_reg + GPC_CNTR, 18);
+}
+
+static void vadc_power_down(struct vadc_state *state)
+{
+ /* Power down vadc analog */
+ reg32setbit(state->gpc_reg + GPC_CNTR, 17);
+
+ /* Power down vadc ext power */
+ reg32clrbit(state->gpc_reg + GPC_CNTR, 18);
+
+}
+static void vadc_init(struct vadc_state *vadc)
+{
+ pr_debug("%s\n", __func__);
+
+ vadc_power_up(vadc);
+
+ afe_init();
+
+ /* select Video Input 0-3 */
+ vadc_s_routing(vadc->vadc_in);
+
+ afe_voltage_clampingmode();
+
+ vdec_init(vadc);
+
+ /*
+ * current control loop will move sinewave input off below
+ * the bottom of the signal range visible
+ * when the testbus is viewed as magnitude,
+ * so have to break before this point while capturing ENOB data:
+ */
+ afe_alwayson_clampingmode();
+}
+
+static inline struct vadc_state *to_state(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct vadc_state, sd);
+}
+
+static int vadc_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ struct vadc_state *state = to_state(sd);
+
+ *std = state->fmt->v4l2_std;
+ return 0;
+}
+
+/*!
+ * Return attributes of current video standard.
+ * Since this device autodetects the current standard, this function also
+ * sets the values that need to be changed if the standard changes.
+ * There is no set std equivalent function.
+ *
+ * @return None.
+ */
+static int vadc_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ struct vadc_state *state = to_state(sd);
+ int mod;
+ int idx;
+ int i;
+
+ /* Read auto mode detected result */
+ printk(KERN_INFO"wait vadc auto detect video mode....\n");
+ for (i = 0; i < 10; i++) {
+ msleep(200);
+ mod = reg32_read(VDEC_VIDMOD);
+ /* Check video signal states */
+ if ((mod & VDEC_VIDMOD_SIGNAL_MASK)
+ == VDEC_VIDMOD_SIGNAL_DETECT)
+ break;
+ }
+ if (i == 10)
+ printk(KERN_INFO"Timeout detect video signal mod=0x%x\n", mod);
+
+ if ((mod & VDEC_VIDMOD_PAL_MASK) || (mod & VDEC_VIDMOD_M625_MASK))
+ idx = VADC_PAL;
+ else
+ idx = VADC_NTSC;
+
+ *std = video_fmts[idx].v4l2_std;
+ state->fmt = &video_fmts[idx];
+
+ printk(KERN_INFO"video mode %s\n", video_fmts[idx].name);
+ return 0;
+}
+
+static int vadc_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ /* support only one format */
+ if (code->pad || code->index >= 1)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_AYUV8_1X32;
+ return 0;
+}
+
+static int vadc_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct vadc_state *state = to_state(sd);
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
+
+ fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ fmt->field = V4L2_FIELD_INTERLACED;
+ fmt->width = 720;
+ fmt->height = state->fmt->v4l2_std & V4L2_STD_NTSC ? 480 : 576;
+
+ return 0;
+}
+
+static int vadc_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ return vadc_get_fmt(sd, cfg, format);
+}
+
+static int vadc_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct vadc_state *state = to_state(sd);
+ if (fse->index >= 1)
+ return -EINVAL;
+
+ fse->min_width = state->fmt->active_width;
+ fse->max_width = state->fmt->active_width;
+ fse->min_height = state->fmt->active_height;
+ fse->max_height = state->fmt->active_height;
+
+ return 0;
+}
+static int vadc_enum_frameintervals(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ struct vadc_state *state = to_state(sd);
+
+ if (fie->index < 0 || fie->index >= 1)
+ return -EINVAL;
+
+ fie->interval.numerator = 1;
+
+ fie->interval.denominator = state->fmt->framerates;
+
+ return 0;
+}
+
+static int vadc_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+ struct vadc_state *state = to_state(sd);
+
+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (parms->parm.capture.timeperframe.denominator
+ != state->fmt->framerates)
+ parms->parm.capture.timeperframe.denominator
+ = state->fmt->framerates;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops vadc_video_ops = {
+ .querystd = vadc_querystd,
+ .s_parm = vadc_s_parm,
+ .g_std = vadc_g_std,
+};
+
+
+static const struct v4l2_subdev_pad_ops vadc_pad_ops = {
+ .get_fmt = vadc_get_fmt,
+ .set_fmt = vadc_set_fmt,
+ .enum_mbus_code = vadc_enum_mbus_code,
+ .enum_frame_size = vadc_enum_framesizes,
+ .enum_frame_interval = vadc_enum_frameintervals,
+};
+
+static const struct v4l2_subdev_ops vadc_ops = {
+ .video = &vadc_video_ops,
+ .pad = &vadc_pad_ops,
+};
+
+static const struct of_device_id fsl_vadc_dt_ids[] = {
+ { .compatible = "fsl,imx6sx-vadc", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_vadc_dt_ids);
+
+static int vadc_of_init(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *gpc_np;
+ struct vadc_state *state = platform_get_drvdata(pdev);
+ int csi_id;
+ int ret;
+
+ /* Get csi_id to setting vadc to csi mux in gpr */
+ ret = of_property_read_u32(np, "csi_id", &csi_id);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read of property csi_id\n");
+ return ret;
+ }
+
+ state->csi_id = csi_id;
+
+ /* remap GPR register */
+ state->gpr = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "gpr");
+ if (IS_ERR(state->gpr)) {
+ dev_dbg(&pdev->dev, "can not get gpr\n");
+ return -ENOMEM;
+ }
+
+ /* Configuration vadc-to-csi 0 or 1 */
+ if (csi_id) {
+ regmap_update_bits(state->gpr, IOMUXC_GPR5,
+ IMX6SX_GPR5_CSI2_MUX_CTRL_MASK,
+ IMX6SX_GPR5_CSI2_MUX_CTRL_CVD);
+ } else {
+ regmap_update_bits(state->gpr, IOMUXC_GPR5,
+ IMX6SX_GPR5_CSI1_MUX_CTRL_MASK,
+ IMX6SX_GPR5_CSI1_MUX_CTRL_CVD);
+ }
+
+ /* Get default vadc_in number */
+ ret = of_property_read_u32(np, "vadc_in", &state->vadc_in);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read of property vadc_in\n");
+ return ret;
+ }
+
+ /* map GPC register */
+ gpc_np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+ state->gpc_reg = of_iomap(gpc_np, 0);
+ if (!state->gpc_reg) {
+ dev_err(&pdev->dev, "ioremap failed with gpc base\n");
+ goto error;
+ }
+
+ return ret;
+
+error:
+ iounmap(state->gpc_reg);
+ return ret;
+}
+
+static void vadc_v4l2_subdev_init(struct v4l2_subdev *sd,
+ struct platform_device *pdev,
+ const struct v4l2_subdev_ops *ops)
+{
+ struct vadc_state *state = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ v4l2_subdev_init(sd, ops);
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ sd->owner = pdev->dev.driver->owner;
+ sd->dev = &pdev->dev;
+
+ /* initialize name */
+ snprintf(sd->name, sizeof(sd->name), "%s",
+ pdev->dev.driver->name);
+
+ v4l2_set_subdevdata(sd, state);
+
+ ret = v4l2_async_register_subdev(sd);
+ if (ret < 0)
+ dev_err(&pdev->dev, "%s--Async register faialed, ret=%d\n", __func__, ret);
+}
+
+static int vadc_probe(struct platform_device *pdev)
+{
+ struct vadc_state *state;
+ struct v4l2_subdev *sd;
+ struct resource *res;
+ int ret = 0;
+
+ state = devm_kzalloc(&pdev->dev, sizeof(struct vadc_state), GFP_KERNEL);
+ if (!state) {
+ dev_err(&pdev->dev, "Cannot allocate device data\n");
+ return -ENOMEM;
+ }
+
+ /* Set initial values for the sensor struct. */
+ state->fmt = &video_fmts[VADC_NTSC];
+
+ sd = &state->sd;
+
+ /* map vafe address */
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, VAFE_REGS_ADDR_RES_NAME);
+ if (!res) {
+ dev_err(&pdev->dev, "No vafe base address found.\n");
+ return -ENOMEM;
+ }
+ vafe_regbase = devm_ioremap_resource(&pdev->dev, res);
+ if (!vafe_regbase) {
+ dev_err(&pdev->dev, "ioremap failed with vafe base\n");
+ return -ENOMEM;
+ }
+
+ /* map vdec address */
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, VDEC_REGS_ADDR_RES_NAME);
+ if (!res) {
+ dev_err(&pdev->dev, "No vdec base address found.\n");
+ return -ENODEV;
+ }
+ vdec_regbase = devm_ioremap_resource(&pdev->dev, res);
+ if (!vdec_regbase) {
+ dev_err(&pdev->dev, "ioremap failed with vdec base\n");
+ return -ENOMEM;
+ }
+
+ /* Get clock */
+ state->vadc_clk = devm_clk_get(&pdev->dev, "vadc");
+ if (IS_ERR(state->vadc_clk)) {
+ ret = PTR_ERR(state->vadc_clk);
+ return ret;
+ }
+
+ state->csi_clk = devm_clk_get(&pdev->dev, "csi");
+ if (IS_ERR(state->csi_clk)) {
+ ret = PTR_ERR(state->csi_clk);
+ return ret;
+ }
+
+ /* clock */
+ clk_prepare_enable(state->csi_clk);
+ clk_prepare_enable(state->vadc_clk);
+
+ platform_set_drvdata(pdev, state);
+
+ vadc_v4l2_subdev_init(sd, pdev, &vadc_ops);
+
+ pm_runtime_enable(&pdev->dev);
+
+ pm_runtime_get_sync(&pdev->dev);
+ /* Init VADC */
+ ret = vadc_of_init(pdev);
+ if (ret < 0)
+ goto err;
+ vadc_init(state);
+
+ pr_info("vadc driver loaded\n");
+
+ return 0;
+err:
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ v4l2_async_unregister_subdev(&state->sd);
+ clk_disable_unprepare(state->csi_clk);
+ clk_disable_unprepare(state->vadc_clk);
+ return ret;
+}
+
+static int vadc_remove(struct platform_device *pdev)
+{
+ struct vadc_state *state = platform_get_drvdata(pdev);
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ v4l2_async_unregister_subdev(&state->sd);
+ clk_disable_unprepare(state->csi_clk);
+ clk_disable_unprepare(state->vadc_clk);
+
+ vadc_power_down(state);
+ return true;
+}
+
+static int vadc_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct vadc_state *state = platform_get_drvdata(pdev);
+
+ clk_disable(state->csi_clk);
+ clk_disable(state->vadc_clk);
+
+ vadc_power_down(state);
+
+ return 0;
+}
+
+static int vadc_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct vadc_state *state = platform_get_drvdata(pdev);
+
+ clk_enable(state->csi_clk);
+ clk_enable(state->vadc_clk);
+
+ vadc_init(state);
+ return 0;
+}
+
+static const struct dev_pm_ops vadc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(vadc_suspend, vadc_resume)
+};
+
+static struct platform_driver vadc_driver = {
+ .driver = {
+ .name = "fsl_vadc",
+ .of_match_table = of_match_ptr(fsl_vadc_dt_ids),
+ .pm = &vadc_pm_ops,
+ },
+ .probe = vadc_probe,
+ .remove = vadc_remove,
+};
+
+module_platform_driver(vadc_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("fsl VADC/VDEC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/subdev/mxc_vadc.h b/drivers/media/platform/mxc/subdev/mxc_vadc.h
new file mode 100644
index 000000000000..d5c1389cbc58
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/mxc_vadc.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2011-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef MXC_VDEC_H
+#define MXC_VDEC_H
+
+/*** define base address ***/
+#define VDEC_BASE vdec_regbase
+#define AFE_BASE vafe_regbase
+
+/* AFE - Register offsets */
+#define AFE_BLOCK_ID_OFFSET 0x00000000
+#define AFE_PDBUF_OFFSET 0x00000004
+#define AFE_SWRST_OFFSET 0x00000008
+#define AFE_TSTSEL_OFFSET 0x0000000c
+#define AFE_TSTMSC_OFFSET 0x00000010
+#define AFE_ENPADIO_OFFSET 0x00000014
+#define AFE_BGREG_OFFSET 0x00000018
+#define AFE_ACCESSAR_ID_OFFSET 0x00000400
+#define AFE_PDADC_OFFSET 0x00000404
+#define AFE_PDSARH_OFFSET 0x00000408
+#define AFE_PDSARL_OFFSET 0x0000040C
+#define AFE_PDADCRFH_OFFSET 0x00000410
+#define AFE_PDADCRFL_OFFSET 0x00000414
+#define AFE_ACCTST_OFFSET 0x00000418
+#define AFE_ADCGN_OFFSET 0x0000041C
+#define AFE_ICTRL_OFFSET 0x00000420
+#define AFE_ICTLSTG_OFFSET 0x00000424
+#define AFE_RCTRLSTG_OFFSET 0x00000428
+#define AFE_TCTRLSTG_OFFSET 0x0000042c
+#define AFE_REFMOD_OFFSET 0x00000430
+#define AFE_REFTRIML_OFFSET 0x00000434
+#define AFE_REFTRIMH_OFFSET 0x00000438
+#define AFE_ADCR_OFFSET 0x0000043c
+#define AFE_DUMMY0_OFFSET 0x00000440
+#define AFE_DUMMY1_OFFSET 0x00000444
+#define AFE_DUMMY2_OFFSET 0x00000448
+#define AFE_DACAMP_OFFSET 0x0000044c
+#define AFE_CLMPTST_OFFSET 0x00000450
+#define AFE_CLMPDAT_OFFSET 0x00000454
+#define AFE_CLMPAMP_OFFSET 0x00000458
+#define AFE_CLAMP_OFFSET 0x0000045c
+#define AFE_INPBUF_OFFSET 0x00000460
+#define AFE_INPFLT_OFFSET 0x00000464
+#define AFE_ADCDGN_OFFSET 0x00000468
+#define AFE_OFFDRV_OFFSET 0x0000046c
+#define AFE_INPCONFIG_OFFSET 0x00000470
+#define AFE_PROGDELAY_OFFSET 0x00000474
+#define AFE_ADCOMT_OFFSET 0x00000478
+#define AFE_ALGDELAY_OFFSET 0x0000047c
+#define AFE_ACC_ID_OFFSET 0x00000800
+#define AFE_ACCSTA_OFFSET 0x00000804
+#define AFE_ACCNOSLI_OFFSET 0x00000808
+#define AFE_ACCCALCON_OFFSET 0x0000080c
+#define AFE_BWEWRICTRL_OFFSET 0x00000810
+#define AFE_SELSLI_OFFSET 0x00000814
+#define AFE_SELBYT_OFFSET 0x00000818
+#define AFE_REDVAL_OFFSET 0x00000820
+#define AFE_WRIBYT_OFFSET 0x00000824
+
+/* AFE Register per module */
+#define AFE_BLOCK_ID (AFE_BASE + AFE_BLOCK_ID_OFFSET)
+#define AFE_PDBUF (AFE_BASE + AFE_PDBUF_OFFSET)
+#define AFE_SWRST (AFE_BASE + AFE_SWRST_OFFSET)
+#define AFE_TSTSEL (AFE_BASE + AFE_TSTSEL_OFFSET)
+#define AFE_TSTMSC (AFE_BASE + AFE_TSTMSC_OFFSET)
+#define AFE_ENPADIO (AFE_BASE + AFE_ENPADIO_OFFSET)
+#define AFE_BGREG (AFE_BASE + AFE_BGREG_OFFSET)
+#define AFE_ACCESSAR_ID (AFE_BASE + AFE_ACCESSAR_ID_OFFSET)
+#define AFE_PDADC (AFE_BASE + AFE_PDADC_OFFSET)
+#define AFE_PDSARH (AFE_BASE + AFE_PDSARH_OFFSET)
+#define AFE_PDSARL (AFE_BASE + AFE_PDSARL_OFFSET)
+#define AFE_PDADCRFH (AFE_BASE + AFE_PDADCRFH_OFFSET)
+#define AFE_PDADCRFL (AFE_BASE + AFE_PDADCRFL_OFFSET)
+#define AFE_ACCTST (AFE_BASE + AFE_ACCTST_OFFSET)
+#define AFE_ADCGN (AFE_BASE + AFE_ADCGN_OFFSET)
+#define AFE_ICTRL (AFE_BASE + AFE_ICTRL_OFFSET)
+#define AFE_ICTLSTG (AFE_BASE + AFE_ICTLSTG_OFFSET)
+#define AFE_RCTRLSTG (AFE_BASE + AFE_RCTRLSTG_OFFSET)
+#define AFE_TCTRLSTG (AFE_BASE + AFE_TCTRLSTG_OFFSET)
+#define AFE_REFMOD (AFE_BASE + AFE_REFMOD_OFFSET)
+#define AFE_REFTRIML (AFE_BASE + AFE_REFTRIML_OFFSET)
+#define AFE_REFTRIMH (AFE_BASE + AFE_REFTRIMH_OFFSET)
+#define AFE_ADCR (AFE_BASE + AFE_ADCR_OFFSET)
+#define AFE_DUMMY0 (AFE_BASE + AFE_DUMMY0_OFFSET)
+#define AFE_DUMMY1 (AFE_BASE + AFE_DUMMY1_OFFSET)
+#define AFE_DUMMY2 (AFE_BASE + AFE_DUMMY2_OFFSET)
+#define AFE_DACAMP (AFE_BASE + AFE_DACAMP_OFFSET)
+#define AFE_CLMPTST (AFE_BASE + AFE_CLMPTST_OFFSET)
+#define AFE_CLMPDAT (AFE_BASE + AFE_CLMPDAT_OFFSET)
+#define AFE_CLMPAMP (AFE_BASE + AFE_CLMPAMP_OFFSET)
+#define AFE_CLAMP (AFE_BASE + AFE_CLAMP_OFFSET)
+#define AFE_INPBUF (AFE_BASE + AFE_INPBUF_OFFSET)
+#define AFE_INPFLT (AFE_BASE + AFE_INPFLT_OFFSET)
+#define AFE_ADCDGN (AFE_BASE + AFE_ADCDGN_OFFSET)
+#define AFE_OFFDRV (AFE_BASE + AFE_OFFDRV_OFFSET)
+#define AFE_INPCONFIG (AFE_BASE + AFE_INPCONFIG_OFFSET)
+#define AFE_PROGDELAY (AFE_BASE + AFE_PROGDELAY_OFFSET)
+#define AFE_ADCOMT (AFE_BASE + AFE_ADCOMT_OFFSET)
+#define AFE_ALGDELAY (AFE_BASE + AFE_ALGDELAY_OFFSET)
+#define AFE_ACC_ID (AFE_BASE + AFE_ACC_ID_OFFSET)
+#define AFE_ACCSTA (AFE_BASE + AFE_ACCSTA_OFFSET)
+#define AFE_ACCNOSLI (AFE_BASE + AFE_ACCNOSLI_OFFSET)
+#define AFE_ACCCALCON (AFE_BASE + AFE_ACCCALCON_OFFSET)
+#define AFE_BWEWRICTRL (AFE_BASE + AFE_BWEWRICTRL_OFFSET)
+#define AFE_SELSLI (AFE_BASE + AFE_SELSLI_OFFSET)
+#define AFE_SELBYT (AFE_BASE + AFE_SELBYT_OFFSET)
+#define AFE_REDVAL (AFE_BASE + AFE_REDVAL_OFFSET)
+#define AFE_WRIBYT (AFE_BASE + AFE_WRIBYT_OFFSET)
+
+/* VDEC - Register offsets */
+#define VDEC_CFC1_OFFSET 0x00000000
+#define VDEC_CFC2_OFFSET 0x00000004
+#define VDEC_BRSTGT_OFFSET 0x00000024
+#define VDEC_HZPOS_OFFSET 0x00000040
+#define VDEC_VRTPOS_OFFSET 0x00000044
+#define VDEC_HVSHIFT_OFFSET 0x00000054
+#define VDEC_HSIGS_OFFSET 0x00000058
+#define VDEC_HSIGE_OFFSET 0x0000005C
+#define VDEC_VSCON1_OFFSET 0x00000060
+#define VDEC_VSCON2_OFFSET 0x00000064
+#define VDEC_YCDEL_OFFSET 0x0000006C
+#define VDEC_AFTCLP_OFFSET 0x00000070
+#define VDEC_DCOFF_OFFSET 0x00000078
+#define VDEC_CSID_OFFSET 0x00000084
+#define VDEC_CBGN_OFFSET 0x00000088
+#define VDEC_CRGN_OFFSET 0x0000008C
+#define VDEC_CNTR_OFFSET 0x00000090
+#define VDEC_BRT_OFFSET 0x00000094
+#define VDEC_HUE_OFFSET 0x00000098
+#define VDEC_CHBTH_OFFSET 0x0000009C
+#define VDEC_SHPIMP_OFFSET 0x000000A4
+#define VDEC_CHPLLIM_OFFSET 0x000000A8
+#define VDEC_VIDMOD_OFFSET 0x000000AC
+#define VDEC_VIDSTS_OFFSET 0x000000B0
+#define VDEC_NOISE_OFFSET 0x000000B4
+#define VDEC_STDDBG_OFFSET 0x000000B8
+#define VDEC_MANOVR_OFFSET 0x000000BC
+#define VDEC_VSSGTH_OFFSET 0x000000C8
+#define VDEC_DBGFBH_OFFSET 0x000000D0
+#define VDEC_DBGFBL_OFFSET 0x000000D4
+#define VDEC_HACTS_OFFSET 0x000000D8
+#define VDEC_HACTE_OFFSET 0x000000DC
+#define VDEC_VACTS_OFFSET 0x000000E0
+#define VDEC_VACTE_OFFSET 0x000000E4
+#define VDEC_HSTIP_OFFSET 0x000000EC
+#define VDEC_BLSCRY_OFFSET 0x000000F4
+#define VDEC_BLSCRCR_OFFSET 0x000000F8
+#define VDEC_BLSCRCB_OFFSET 0x000000FC
+#define VDEC_LMAGC1_OFFSET 0x00000100
+#define VDEC_LMAGC2_OFFSET 0x00000104
+#define VDEC_CHAGC1_OFFSET 0x00000108
+#define VDEC_CHAGC2_OFFSET 0x0000010C
+#define VDEC_MINTH_OFFSET 0x00000114
+#define VDEC_VFRQOH_OFFSET 0x0000011C
+#define VDEC_VFRQOL_OFFSET 0x00000120
+#define VDEC_THSH1_OFFSET 0x00000124
+#define VDEC_THSH2_OFFSET 0x00000128
+#define VDEC_NCHTH_OFFSET 0x0000012C
+#define VDEC_TH1F_OFFSET 0x00000130
+
+/* VDEC Register per module */
+#define VDEC_CFC1 (VDEC_BASE + VDEC_CFC1_OFFSET)
+#define VDEC_CFC2 (VDEC_BASE + VDEC_CFC2_OFFSET)
+#define VDEC_BRSTGT (VDEC_BASE + VDEC_BRSTGT_OFFSET)
+#define VDEC_HZPOS (VDEC_BASE + VDEC_HZPOS_OFFSET)
+#define VDEC_VRTPOS (VDEC_BASE + VDEC_VRTPOS_OFFSET)
+#define VDEC_HVSHIFT (VDEC_BASE + VDEC_HVSHIFT_OFFSET)
+#define VDEC_HSIGS (VDEC_BASE + VDEC_HSIGS_OFFSET)
+#define VDEC_HSIGE (VDEC_BASE + VDEC_HSIGE_OFFSET)
+#define VDEC_VSCON1 (VDEC_BASE + VDEC_VSCON1_OFFSET)
+#define VDEC_VSCON2 (VDEC_BASE + VDEC_VSCON2_OFFSET)
+#define VDEC_YCDEL (VDEC_BASE + VDEC_YCDEL_OFFSET)
+#define VDEC_AFTCLP (VDEC_BASE + VDEC_AFTCLP_OFFSET)
+#define VDEC_DCOFF (VDEC_BASE + VDEC_DCOFF_OFFSET)
+#define VDEC_CSID (VDEC_BASE + VDEC_CSID_OFFSET)
+#define VDEC_CBGN (VDEC_BASE + VDEC_CBGN_OFFSET)
+#define VDEC_CRGN (VDEC_BASE + VDEC_CRGN_OFFSET)
+#define VDEC_CNTR (VDEC_BASE + VDEC_CNTR_OFFSET)
+#define VDEC_BRT (VDEC_BASE + VDEC_BRT_OFFSET)
+#define VDEC_HUE (VDEC_BASE + VDEC_HUE_OFFSET)
+#define VDEC_CHBTH (VDEC_BASE + VDEC_CHBTH_OFFSET)
+#define VDEC_SHPIMP (VDEC_BASE + VDEC_SHPIMP_OFFSET)
+#define VDEC_CHPLLIM (VDEC_BASE + VDEC_CHPLLIM_OFFSET)
+#define VDEC_VIDMOD (VDEC_BASE + VDEC_VIDMOD_OFFSET)
+#define VDEC_VIDSTS (VDEC_BASE + VDEC_VIDSTS_OFFSET)
+#define VDEC_NOISE (VDEC_BASE + VDEC_NOISE_OFFSET)
+#define VDEC_STDDBG (VDEC_BASE + VDEC_STDDBG_OFFSET)
+#define VDEC_MANOVR (VDEC_BASE + VDEC_MANOVR_OFFSET)
+#define VDEC_VSSGTH (VDEC_BASE + VDEC_VSSGTH_OFFSET)
+#define VDEC_DBGFBH (VDEC_BASE + VDEC_DBGFBH_OFFSET)
+#define VDEC_DBGFBL (VDEC_BASE + VDEC_DBGFBL_OFFSET)
+#define VDEC_HACTS (VDEC_BASE + VDEC_HACTS_OFFSET)
+#define VDEC_HACTE (VDEC_BASE + VDEC_HACTE_OFFSET)
+#define VDEC_VACTS (VDEC_BASE + VDEC_VACTS_OFFSET)
+#define VDEC_VACTE (VDEC_BASE + VDEC_VACTE_OFFSET)
+#define VDEC_HSTIP (VDEC_BASE + VDEC_HSTIP_OFFSET)
+#define VDEC_BLSCRY (VDEC_BASE + VDEC_BLSCRY_OFFSET)
+#define VDEC_BLSCRCR (VDEC_BASE + VDEC_BLSCRCR_OFFSET)
+#define VDEC_BLSCRCB (VDEC_BASE + VDEC_BLSCRCB_OFFSET)
+#define VDEC_LMAGC1 (VDEC_BASE + VDEC_LMAGC1_OFFSET)
+#define VDEC_LMAGC2 (VDEC_BASE + VDEC_LMAGC2_OFFSET)
+#define VDEC_CHAGC1 (VDEC_BASE + VDEC_CHAGC1_OFFSET)
+#define VDEC_CHAGC2 (VDEC_BASE + VDEC_CHAGC2_OFFSET)
+#define VDEC_MINTH (VDEC_BASE + VDEC_MINTH_OFFSET)
+#define VDEC_VFRQOH (VDEC_BASE + VDEC_VFRQOH_OFFSET)
+#define VDEC_VFRQOL (VDEC_BASE + VDEC_VFRQOL_OFFSET)
+#define VDEC_THSH1 (VDEC_BASE + VDEC_THSH1_OFFSET)
+#define VDEC_THSH2 (VDEC_BASE + VDEC_THSH2_OFFSET)
+#define VDEC_NCHTH (VDEC_BASE + VDEC_NCHTH_OFFSET)
+#define VDEC_TH1F (VDEC_BASE + VDEC_TH1F_OFFSET)
+
+#define VDEC_VIDMOD_SIGNAL_MASK 0x0F
+#define VDEC_VIDMOD_SIGNAL_DETECT 0x0F
+
+#define VDEC_VIDMOD_M625_SHIFT 4
+#define VDEC_VIDMOD_M625_MASK (1 << VDEC_VIDMOD_M625_SHIFT)
+
+#define VDEC_VIDMOD_PAL_SHIFT 7
+#define VDEC_VIDMOD_PAL_MASK (1 << VDEC_VIDMOD_PAL_SHIFT)
+/*** define base address ***/
+
+#endif
diff --git a/drivers/media/platform/mxc/subdev/ov5640.c b/drivers/media/platform/mxc/subdev/ov5640.c
new file mode 100644
index 000000000000..70e2a8321fd0
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/ov5640.c
@@ -0,0 +1,1895 @@
+/*
+ * Copyright (C) 2012-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/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define OV5640_VOLTAGE_ANALOG 2800000
+#define OV5640_VOLTAGE_DIGITAL_CORE 1500000
+#define OV5640_VOLTAGE_DIGITAL_IO 1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5640_XCLK_MIN 6000000
+#define OV5640_XCLK_MAX 24000000
+
+#define OV5640_CHIP_ID_HIGH_BYTE 0x300A
+#define OV5640_CHIP_ID_LOW_BYTE 0x300B
+
+enum ov5640_mode {
+ ov5640_mode_MIN = 0,
+ ov5640_mode_VGA_640_480 = 0,
+ ov5640_mode_QVGA_320_240 = 1,
+ ov5640_mode_NTSC_720_480 = 2,
+ ov5640_mode_PAL_720_576 = 3,
+ ov5640_mode_720P_1280_720 = 4,
+ ov5640_mode_1080P_1920_1080 = 5,
+ ov5640_mode_QSXGA_2592_1944 = 6,
+ ov5640_mode_QCIF_176_144 = 7,
+ ov5640_mode_XGA_1024_768 = 8,
+ ov5640_mode_MAX = 8
+};
+
+enum ov5640_frame_rate {
+ ov5640_15_fps,
+ ov5640_30_fps
+};
+
+static int ov5640_framerates[] = {
+ [ov5640_15_fps] = 15,
+ [ov5640_30_fps] = 30,
+};
+
+struct ov5640_datafmt {
+ u32 code;
+ enum v4l2_colorspace colorspace;
+};
+
+struct reg_value {
+ u16 u16RegAddr;
+ u8 u8Val;
+ u8 u8Mask;
+ u32 u32Delay_ms;
+};
+
+struct ov5640_mode_info {
+ enum ov5640_mode mode;
+ u32 width;
+ u32 height;
+ struct reg_value *init_data_ptr;
+ u32 init_data_size;
+};
+
+struct ov5640 {
+ struct v4l2_subdev subdev;
+ struct i2c_client *i2c_client;
+ struct v4l2_pix_format pix;
+ const struct ov5640_datafmt *fmt;
+ struct v4l2_captureparm streamcap;
+ bool on;
+
+ /* control settings */
+ int brightness;
+ int hue;
+ int contrast;
+ int saturation;
+ int red;
+ int green;
+ int blue;
+ int ae_mode;
+
+ u32 mclk;
+ u8 mclk_source;
+ struct clk *sensor_clk;
+ int csi;
+
+ void (*io_init)(void);
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct ov5640 ov5640_data;
+static int pwn_gpio, rst_gpio;
+static int prev_sysclk;
+static int AE_Target = 52, night_mode;
+static int prev_HTS;
+static int AE_high, AE_low;
+
+static struct reg_value ov5640_global_init_setting[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
+ {0x3034, 0x1a, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0},
+ {0x3630, 0x36, 0, 0}, {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0},
+ {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0},
+ {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0},
+ {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0},
+ {0x3906, 0x10, 0, 0}, {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0},
+ {0x3600, 0x08, 0, 0}, {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0},
+ {0x3620, 0x52, 0, 0}, {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0},
+ {0x3a13, 0x43, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
+ {0x3635, 0x13, 0, 0}, {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0},
+ {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0},
+ {0x3c05, 0x98, 0, 0}, {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0},
+ {0x3c0b, 0x40, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0},
+ {0x3812, 0x00, 0, 0}, {0x3708, 0x64, 0, 0}, {0x4001, 0x02, 0, 0},
+ {0x4005, 0x1a, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
+ {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x5000, 0xa7, 0, 0},
+ {0x3008, 0x02, 0, 0},
+};
+
+static struct reg_value ov5640_init_setting_30fps_VGA[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
+ {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x46, 0, 0},
+ {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
+ {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
+ {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+ {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
+ {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
+ {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
+ {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
+ {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
+ {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
+ {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
+ {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, {0x5000, 0xa7, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0},
+ {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
+ {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0},
+ {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0}, {0x518a, 0x54, 0, 0},
+ {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x50, 0, 0},
+ {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0}, {0x5190, 0x46, 0, 0},
+ {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
+ {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
+ {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x6c, 0, 0},
+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x09, 0, 0},
+ {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0}, {0x5381, 0x1e, 0, 0},
+ {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, {0x5384, 0x0a, 0, 0},
+ {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0},
+ {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0},
+ {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0},
+ {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0},
+ {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0},
+ {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0},
+ {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, {0x5481, 0x08, 0, 0},
+ {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, {0x5484, 0x51, 0, 0},
+ {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, {0x5487, 0x7d, 0, 0},
+ {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, {0x548a, 0x9a, 0, 0},
+ {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, {0x548d, 0xcd, 0, 0},
+ {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, {0x5490, 0x1d, 0, 0},
+ {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x10, 0, 0},
+ {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, {0x558b, 0xf8, 0, 0},
+ {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, {0x5802, 0x0f, 0, 0},
+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, {0x5805, 0x26, 0, 0},
+ {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, {0x5808, 0x05, 0, 0},
+ {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, {0x580b, 0x0d, 0, 0},
+ {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, {0x580e, 0x00, 0, 0},
+ {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, {0x5811, 0x09, 0, 0},
+ {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x00, 0, 0},
+ {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, {0x5817, 0x08, 0, 0},
+ {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, {0x581a, 0x05, 0, 0},
+ {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, {0x581d, 0x0e, 0, 0},
+ {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, {0x5820, 0x11, 0, 0},
+ {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, {0x5823, 0x28, 0, 0},
+ {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, {0x5826, 0x08, 0, 0},
+ {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, {0x5829, 0x26, 0, 0},
+ {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, {0x582c, 0x24, 0, 0},
+ {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, {0x582f, 0x22, 0, 0},
+ {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, {0x5832, 0x24, 0, 0},
+ {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, {0x5835, 0x22, 0, 0},
+ {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, {0x5838, 0x44, 0, 0},
+ {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, {0x583b, 0x28, 0, 0},
+ {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, {0x5025, 0x00, 0, 0},
+ {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0},
+ {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0},
+ {0x3008, 0x02, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
+ {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
+ {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
+ {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
+ {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+ {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
+ {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
+ {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
+ {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+ {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
+ {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
+ {0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
+ {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
+ {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+ {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
+ {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
+ {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
+ {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
+ {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
+ {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+
+static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
+ {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
+ {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0xee, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x05, 0, 0},
+ {0x3807, 0xc3, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0},
+ {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x0b, 0, 0},
+ {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
+ {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
+ {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
+ {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
+ {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
+ {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
+ {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
+ {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0},
+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
+ {0x3807, 0x9f, 0, 0}, {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0},
+ {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0},
+ {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
+ {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
+ {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
+ {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
+ {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
+ {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
+};
+
+static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
+ {
+ {ov5640_mode_VGA_640_480, 640, 480,
+ ov5640_setting_15fps_VGA_640_480,
+ ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
+ {ov5640_mode_QVGA_320_240, 320, 240,
+ ov5640_setting_15fps_QVGA_320_240,
+ ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
+ {ov5640_mode_NTSC_720_480, 720, 480,
+ ov5640_setting_15fps_NTSC_720_480,
+ ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
+ {ov5640_mode_PAL_720_576, 720, 576,
+ ov5640_setting_15fps_PAL_720_576,
+ ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
+ {ov5640_mode_720P_1280_720, 1280, 720,
+ ov5640_setting_15fps_720P_1280_720,
+ ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
+ {ov5640_mode_1080P_1920_1080, 1920, 1080,
+ ov5640_setting_15fps_1080P_1920_1080,
+ ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
+ {ov5640_mode_QSXGA_2592_1944, 2592, 1944,
+ ov5640_setting_15fps_QSXGA_2592_1944,
+ ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
+ {ov5640_mode_QCIF_176_144, 176, 144,
+ ov5640_setting_15fps_QCIF_176_144,
+ ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
+ {ov5640_mode_XGA_1024_768, 1024, 768,
+ ov5640_setting_15fps_XGA_1024_768,
+ ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
+ },
+ {
+ {ov5640_mode_VGA_640_480, 640, 480,
+ ov5640_setting_30fps_VGA_640_480,
+ ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
+ {ov5640_mode_QVGA_320_240, 320, 240,
+ ov5640_setting_30fps_QVGA_320_240,
+ ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
+ {ov5640_mode_NTSC_720_480, 720, 480,
+ ov5640_setting_30fps_NTSC_720_480,
+ ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
+ {ov5640_mode_PAL_720_576, 720, 576,
+ ov5640_setting_30fps_PAL_720_576,
+ ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
+ {ov5640_mode_720P_1280_720, 1280, 720,
+ ov5640_setting_30fps_720P_1280_720,
+ ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
+ {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0},
+ {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
+ {ov5640_mode_QCIF_176_144, 176, 144,
+ ov5640_setting_30fps_QCIF_176_144,
+ ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
+ {ov5640_mode_XGA_1024_768, 1024, 768,
+ ov5640_setting_30fps_XGA_1024_768,
+ ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
+ },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+
+static int ov5640_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *device_id);
+static int ov5640_remove(struct i2c_client *client);
+
+static s32 ov5640_read_reg(u16 reg, u8 *val);
+static s32 ov5640_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5640_id[] = {
+ {"ov5640", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ov5640",
+ },
+ .probe = ov5640_probe,
+ .remove = ov5640_remove,
+ .id_table = ov5640_id,
+};
+
+static const struct ov5640_datafmt ov5640_colour_fmts[] = {
+ {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+};
+
+static struct ov5640 *to_ov5640(const struct i2c_client *client)
+{
+ return container_of(i2c_get_clientdata(client), struct ov5640, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct ov5640_datafmt
+ *ov5640_find_datafmt(u32 code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ov5640_colour_fmts); i++)
+ if (ov5640_colour_fmts[i].code == code)
+ return ov5640_colour_fmts + i;
+
+ return NULL;
+}
+
+static inline void ov5640_power_down(int enable)
+{
+ gpio_set_value_cansleep(pwn_gpio, enable);
+
+ msleep(2);
+}
+
+static inline void ov5640_reset(void)
+{
+ /* camera reset */
+ gpio_set_value_cansleep(rst_gpio, 1);
+
+ /* camera power down */
+ gpio_set_value_cansleep(pwn_gpio, 1);
+ msleep(5);
+ gpio_set_value_cansleep(pwn_gpio, 0);
+ msleep(5);
+ gpio_set_value_cansleep(rst_gpio, 0);
+ msleep(1);
+ gpio_set_value_cansleep(rst_gpio, 1);
+ msleep(5);
+ gpio_set_value_cansleep(pwn_gpio, 1);
+}
+
+static int ov5640_regulator_enable(struct device *dev)
+{
+ int ret = 0;
+
+ io_regulator = devm_regulator_get(dev, "DOVDD");
+ if (!IS_ERR(io_regulator)) {
+ regulator_set_voltage(io_regulator,
+ OV5640_VOLTAGE_DIGITAL_IO,
+ OV5640_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(io_regulator);
+ if (ret) {
+ dev_err(dev, "set io voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set io voltage ok\n");
+ }
+ } else {
+ io_regulator = NULL;
+ dev_warn(dev, "cannot get io voltage\n");
+ }
+
+ core_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(core_regulator)) {
+ regulator_set_voltage(core_regulator,
+ OV5640_VOLTAGE_DIGITAL_CORE,
+ OV5640_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(core_regulator);
+ if (ret) {
+ dev_err(dev, "set core voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set core voltage ok\n");
+ }
+ } else {
+ core_regulator = NULL;
+ dev_warn(dev, "cannot get core voltage\n");
+ }
+
+ analog_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(analog_regulator)) {
+ regulator_set_voltage(analog_regulator,
+ OV5640_VOLTAGE_ANALOG,
+ OV5640_VOLTAGE_ANALOG);
+ ret = regulator_enable(analog_regulator);
+ if (ret) {
+ dev_err(dev, "set analog voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set analog voltage ok\n");
+ }
+ } else {
+ analog_regulator = NULL;
+ dev_warn(dev, "cannot get analog voltage\n");
+ }
+
+ return ret;
+}
+
+static s32 ov5640_write_reg(u16 reg, u8 val)
+{
+ u8 au8Buf[3] = {0};
+
+ au8Buf[0] = reg >> 8;
+ au8Buf[1] = reg & 0xff;
+ au8Buf[2] = val;
+
+ if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x\n",
+ __func__, reg, val);
+ return -1;
+ }
+
+ return 0;
+}
+
+static s32 ov5640_read_reg(u16 reg, u8 *val)
+{
+ u8 au8RegBuf[2] = {0};
+ u8 u8RdVal = 0;
+
+ au8RegBuf[0] = reg >> 8;
+ au8RegBuf[1] = reg & 0xff;
+
+ if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
+ pr_err("%s:write reg error:reg=%x\n",
+ __func__, reg);
+ return -1;
+ }
+
+ if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
+ pr_err("%s:read reg error:reg=%x,val=%x\n",
+ __func__, reg, u8RdVal);
+ return -1;
+ }
+
+ *val = u8RdVal;
+
+ return u8RdVal;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov5640_get_register(struct v4l2_subdev *sd,
+ struct v4l2_dbg_register *reg)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int ret;
+ u8 val;
+
+ if (reg->reg & ~0xffff)
+ return -EINVAL;
+
+ reg->size = 1;
+
+ ret = ov5640_read_reg(reg->reg, &val);
+ if (!ret)
+ reg->val = (__u64)val;
+
+ return ret;
+}
+
+static int ov5640_set_register(struct v4l2_subdev *sd,
+ const struct v4l2_dbg_register *reg)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ if (reg->reg & ~0xffff || reg->val & ~0xff)
+ return -EINVAL;
+
+ return ov5640_write_reg(reg->reg, reg->val);
+}
+#endif
+
+static void ov5640_soft_reset(void)
+{
+ /* sysclk from pad */
+ ov5640_write_reg(0x3103, 0x11);
+
+ /* software reset */
+ ov5640_write_reg(0x3008, 0x82);
+
+ /* delay at least 5ms */
+ msleep(10);
+}
+
+/* set sensor driver capability
+ * 0x302c[7:6] - strength
+ 00 - 1x
+ 01 - 2x
+ 10 - 3x
+ 11 - 4x
+ */
+static int ov5640_driver_capability(int strength)
+{
+ u8 temp = 0;
+
+ if (strength > 4 || strength < 1) {
+ pr_err("The valid driver capability of ov5640 is 1x~4x\n");
+ return -EINVAL;
+ }
+
+ ov5640_read_reg(0x302c, &temp);
+
+ temp &= ~0xc0; /* clear [7:6] */
+ temp |= ((strength - 1) << 6); /* set [7:6] */
+
+ ov5640_write_reg(0x302c, temp);
+
+ return 0;
+}
+
+/* calculate sysclk */
+static int ov5640_get_sysclk(void)
+{
+ int xvclk = ov5640_data.mclk / 10000;
+ int sysclk;
+ int temp1, temp2;
+ int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv;
+ int sclk_rdiv_map[] = {1, 2, 4, 8};
+ u8 regval = 0;
+
+ temp1 = ov5640_read_reg(0x3034, &regval);
+ temp2 = temp1 & 0x0f;
+ if (temp2 == 8 || temp2 == 10) {
+ Bit_div2x = temp2 / 2;
+ } else {
+ pr_err("ov5640: unsupported bit mode %d\n", temp2);
+ return -1;
+ }
+
+ temp1 = ov5640_read_reg(0x3035, &regval);
+ SysDiv = temp1 >> 4;
+ if (SysDiv == 0)
+ SysDiv = 16;
+
+ temp1 = ov5640_read_reg(0x3036, &regval);
+ Multiplier = temp1;
+ temp1 = ov5640_read_reg(0x3037, &regval);
+ PreDiv = temp1 & 0x0f;
+ Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
+
+ temp1 = ov5640_read_reg(0x3108, &regval);
+ temp2 = temp1 & 0x03;
+
+ sclk_rdiv = sclk_rdiv_map[temp2];
+ VCO = xvclk * Multiplier / PreDiv;
+ sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
+
+ return sysclk;
+}
+
+/* read HTS from register settings */
+static int ov5640_get_HTS(void)
+{
+ int HTS;
+ u8 temp = 0;
+
+ HTS = ov5640_read_reg(0x380c, &temp);
+ HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
+ return HTS;
+}
+
+/* read VTS from register settings */
+static int ov5640_get_VTS(void)
+{
+ int VTS;
+ u8 temp = 0;
+
+ VTS = ov5640_read_reg(0x380e, &temp);
+ VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
+
+ return VTS;
+}
+
+/* write VTS to registers */
+static int ov5640_set_VTS(int VTS)
+{
+ int temp;
+
+ temp = VTS & 0xff;
+ ov5640_write_reg(0x380f, temp);
+
+ temp = VTS>>8;
+ ov5640_write_reg(0x380e, temp);
+ return 0;
+}
+
+/* read shutter, in number of line period */
+static int ov5640_get_shutter(void)
+{
+ int shutter;
+ u8 regval;
+
+ shutter = (ov5640_read_reg(0x03500, &regval) & 0x0f);
+
+ shutter = (shutter<<8) + ov5640_read_reg(0x3501, &regval);
+ shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &regval)>>4);
+
+ return shutter;
+}
+
+/* write shutter, in number of line period */
+static int ov5640_set_shutter(int shutter)
+{
+ int temp;
+
+ shutter = shutter & 0xffff;
+ temp = shutter & 0x0f;
+ temp = temp<<4;
+ ov5640_write_reg(0x3502, temp);
+
+ temp = shutter & 0xfff;
+ temp = temp>>4;
+ ov5640_write_reg(0x3501, temp);
+
+ temp = shutter>>12;
+ ov5640_write_reg(0x3500, temp);
+
+ return 0;
+}
+
+/* read gain, 16 = 1x */
+static int ov5640_get_gain16(void)
+{
+ int gain16;
+ u8 regval;
+
+ gain16 = ov5640_read_reg(0x350a, &regval) & 0x03;
+ gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &regval);
+
+ return gain16;
+}
+
+/* write gain, 16 = 1x */
+static int ov5640_set_gain16(int gain16)
+{
+ int temp;
+
+ gain16 = gain16 & 0x3ff;
+ temp = gain16 & 0xff;
+
+ ov5640_write_reg(0x350b, temp);
+ temp = gain16>>8;
+
+ ov5640_write_reg(0x350a, temp);
+ return 0;
+}
+
+/* get banding filter value */
+static int ov5640_get_light_freq(void)
+{
+ int temp, temp1, light_frequency;
+ u8 regval;
+
+ temp = ov5640_read_reg(0x3c01, &regval);
+ if (temp & 0x80) {
+ /* manual */
+ temp1 = ov5640_read_reg(0x3c00, &regval);
+ if (temp1 & 0x04) {
+ /* 50Hz */
+ light_frequency = 50;
+ } else {
+ /* 60Hz */
+ light_frequency = 60;
+ }
+ } else {
+ /* auto */
+ temp1 = ov5640_read_reg(0x3c0c, &regval);
+ if (temp1 & 0x01) {
+ /* 50Hz */
+ light_frequency = 50;
+ } else {
+ /* 60Hz */
+ light_frequency = 60;
+ }
+ }
+
+ return light_frequency;
+}
+
+static void ov5640_set_bandingfilter(void)
+{
+ int prev_VTS;
+ int band_step60, max_band60, band_step50, max_band50;
+
+ /* read preview PCLK */
+ prev_sysclk = ov5640_get_sysclk();
+
+ /* read preview HTS */
+ prev_HTS = ov5640_get_HTS();
+
+ /* read preview VTS */
+ prev_VTS = ov5640_get_VTS();
+
+ /* calculate banding filter */
+ /* 60Hz */
+ band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
+ ov5640_write_reg(0x3a0a, (band_step60 >> 8));
+ ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
+
+ max_band60 = (int)((prev_VTS-4)/band_step60);
+ ov5640_write_reg(0x3a0d, max_band60);
+
+ /* 50Hz */
+ band_step50 = prev_sysclk * 100/prev_HTS;
+ ov5640_write_reg(0x3a08, (band_step50 >> 8));
+ ov5640_write_reg(0x3a09, (band_step50 & 0xff));
+
+ max_band50 = (int)((prev_VTS-4)/band_step50);
+ ov5640_write_reg(0x3a0e, max_band50);
+}
+
+/* stable in high */
+static int ov5640_set_AE_target(int target)
+{
+ int fast_high, fast_low;
+
+ AE_low = target * 23 / 25; /* 0.92 */
+ AE_high = target * 27 / 25; /* 1.08 */
+ fast_high = AE_high << 1;
+
+ if (fast_high > 255)
+ fast_high = 255;
+ fast_low = AE_low >> 1;
+
+ ov5640_write_reg(0x3a0f, AE_high);
+ ov5640_write_reg(0x3a10, AE_low);
+ ov5640_write_reg(0x3a1b, AE_high);
+ ov5640_write_reg(0x3a1e, AE_low);
+ ov5640_write_reg(0x3a11, fast_high);
+ ov5640_write_reg(0x3a1f, fast_low);
+
+ return 0;
+}
+
+/* enable = 0 to turn off night mode
+ enable = 1 to turn on night mode */
+static int ov5640_set_night_mode(int enable)
+{
+ u8 mode;
+
+ ov5640_read_reg(0x3a00, &mode);
+
+ if (enable) {
+ /* night mode on */
+ mode |= 0x04;
+ ov5640_write_reg(0x3a00, mode);
+ } else {
+ /* night mode off */
+ mode &= 0xfb;
+ ov5640_write_reg(0x3a00, mode);
+ }
+
+ return 0;
+}
+
+/* enable = 0 to turn off AEC/AGC
+ enable = 1 to turn on AEC/AGC */
+static void ov5640_turn_on_AE_AG(int enable)
+{
+ u8 ae_ag_ctrl;
+
+ ov5640_read_reg(0x3503, &ae_ag_ctrl);
+ if (enable) {
+ /* turn on auto AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
+ } else {
+ /* turn off AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl | 0x03;
+ }
+ ov5640_write_reg(0x3503, ae_ag_ctrl);
+}
+
+/* download ov5640 settings to sensor through i2c */
+static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+{
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int i, retval = 0;
+
+ for (i = 0; i < ArySize; ++i, ++pModeSetting) {
+ Delay_ms = pModeSetting->u32Delay_ms;
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u8Val;
+ Mask = pModeSetting->u8Mask;
+
+ if (Mask) {
+ retval = ov5640_read_reg(RegAddr, &RegVal);
+ if (retval < 0)
+ goto err;
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = ov5640_write_reg(RegAddr, Val);
+ if (retval < 0)
+ goto err;
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+ }
+err:
+ return retval;
+}
+
+static int ov5640_init_mode(void)
+{
+ struct reg_value *pModeSetting = NULL;
+ int ArySize = 0, retval = 0;
+
+ ov5640_soft_reset();
+
+ pModeSetting = ov5640_global_init_setting;
+ ArySize = ARRAY_SIZE(ov5640_global_init_setting);
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ pModeSetting = ov5640_init_setting_30fps_VGA;
+ ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ /* change driver capability to 2x according to validation board.
+ * if the image is not stable, please increase the driver strength.
+ */
+ ov5640_driver_capability(2);
+ ov5640_set_bandingfilter();
+ ov5640_set_AE_target(AE_Target);
+ ov5640_set_night_mode(night_mode);
+
+ /* skip 9 vysnc: start capture at 10th vsync */
+ msleep(300);
+
+ /* turn off night mode */
+ night_mode = 0;
+ ov5640_data.pix.width = 640;
+ ov5640_data.pix.height = 480;
+err:
+ return retval;
+}
+
+/* change to or back to subsampling mode set the mode directly
+ * image size below 1280 * 960 is subsampling mode */
+static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+
+ if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
+ pr_err("Wrong ov5640 mode detected!\n");
+ return -1;
+ }
+
+ pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5640_data.pix.width = ov5640_mode_info_data[frame_rate][mode].width;
+ ov5640_data.pix.height = ov5640_mode_info_data[frame_rate][mode].height;
+
+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* set ov5640 to subsampling mode */
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+
+ /* turn on AE AG for subsampling mode, in case the firmware didn't */
+ ov5640_turn_on_AE_AG(1);
+
+ /* calculate banding filter */
+ ov5640_set_bandingfilter();
+
+ /* set AE target */
+ ov5640_set_AE_target(AE_Target);
+
+ /* update night mode setting */
+ ov5640_set_night_mode(night_mode);
+
+ /* skip 9 vysnc: start capture at 10th vsync */
+ if (mode == ov5640_mode_XGA_1024_768 && frame_rate == ov5640_30_fps) {
+ pr_warning("ov5640: actual frame rate of XGA is 22.5fps\n");
+ /* 1/22.5 * 9*/
+ msleep(400);
+ return retval;
+ }
+
+ if (frame_rate == ov5640_15_fps) {
+ /* 1/15 * 9*/
+ msleep(600);
+ } else if (frame_rate == ov5640_30_fps) {
+ /* 1/30 * 9*/
+ msleep(300);
+ }
+
+ return retval;
+}
+
+/* change to scaling mode go through exposure calucation
+ * image size above 1280 * 960 is scaling mode */
+static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ int prev_shutter, prev_gain16, average;
+ int cap_shutter, cap_gain16;
+ int cap_sysclk, cap_HTS, cap_VTS;
+ int light_freq, cap_bandfilt, cap_maxband;
+ long cap_gain16_shutter;
+ u8 temp;
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+
+ /* check if the input mode and frame rate is valid */
+ pModeSetting =
+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5640_data.pix.width =
+ ov5640_mode_info_data[frame_rate][mode].width;
+ ov5640_data.pix.height =
+ ov5640_mode_info_data[frame_rate][mode].height;
+
+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* read preview shutter */
+ prev_shutter = ov5640_get_shutter();
+
+ /* read preview gain */
+ prev_gain16 = ov5640_get_gain16();
+
+ /* get average */
+ average = ov5640_read_reg(0x56a1, &temp);
+
+ /* turn off night mode for capture */
+ ov5640_set_night_mode(0);
+
+ /* turn off overlay */
+ ov5640_write_reg(0x3022, 0x06);
+
+ /* Write capture setting */
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ /* turn off AE AG when capture image. */
+ ov5640_turn_on_AE_AG(0);
+
+ /* read capture VTS */
+ cap_VTS = ov5640_get_VTS();
+ cap_HTS = ov5640_get_HTS();
+ cap_sysclk = ov5640_get_sysclk();
+
+ /* calculate capture banding filter */
+ light_freq = ov5640_get_light_freq();
+ if (light_freq == 60) {
+ /* 60Hz */
+ cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
+ } else {
+ /* 50Hz */
+ cap_bandfilt = cap_sysclk * 100 / cap_HTS;
+ }
+ cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
+ /* calculate capture shutter/gain16 */
+ if (average > AE_low && average < AE_high) {
+ /* in stable range */
+ cap_gain16_shutter =
+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
+ prev_HTS/cap_HTS * AE_Target / average;
+ } else {
+ cap_gain16_shutter =
+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
+ prev_HTS/cap_HTS;
+ }
+
+ /* gain to shutter */
+ if (cap_gain16_shutter < (cap_bandfilt * 16)) {
+ /* shutter < 1/100 */
+ cap_shutter = cap_gain16_shutter/16;
+ if (cap_shutter < 1)
+ cap_shutter = 1;
+ cap_gain16 = cap_gain16_shutter/cap_shutter;
+ if (cap_gain16 < 16)
+ cap_gain16 = 16;
+ } else {
+ if (cap_gain16_shutter > (cap_bandfilt*cap_maxband*16)) {
+ /* exposure reach max */
+ cap_shutter = cap_bandfilt*cap_maxband;
+ cap_gain16 = cap_gain16_shutter / cap_shutter;
+ } else {
+ /* 1/100 < cap_shutter =< max, cap_shutter = n/100 */
+ cap_shutter =
+ ((int)(cap_gain16_shutter/16/cap_bandfilt))
+ * cap_bandfilt;
+ cap_gain16 = cap_gain16_shutter / cap_shutter;
+ }
+ }
+
+ /* write capture gain */
+ ov5640_set_gain16(cap_gain16);
+
+ /* write capture shutter */
+ if (cap_shutter > (cap_VTS - 4)) {
+ cap_VTS = cap_shutter + 4;
+ ov5640_set_VTS(cap_VTS);
+ }
+
+ ov5640_set_shutter(cap_shutter);
+
+ /* skip 2 vysnc: start capture at 3rd vsync
+ * frame rate of QSXGA and 1080P is 7.5fps: 1/7.5 * 2
+ */
+ pr_warning("ov5640: the actual frame rate of %s is 7.5fps\n",
+ mode == ov5640_mode_1080P_1920_1080 ? "1080P" : "QSXGA");
+ msleep(267);
+err:
+ return retval;
+}
+
+static int ov5640_change_mode(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ int retval = 0;
+
+ if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
+ pr_err("Wrong ov5640 mode detected!\n");
+ return -1;
+ }
+
+ if (mode == ov5640_mode_1080P_1920_1080 ||
+ mode == ov5640_mode_QSXGA_2592_1944) {
+ /* change to scaling mode go through exposure calucation
+ * image size above 1280 * 960 is scaling mode */
+ retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
+ } else {
+ /* change back to subsampling modem download firmware directly
+ * image size below 1280 * 960 is subsampling mode */
+ retval = ov5640_change_mode_direct(frame_rate, mode);
+ }
+
+ return retval;
+}
+
+/*!
+ * ov5640_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ov5640_s_power(struct v4l2_subdev *sd, int on)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+
+ if (on)
+ clk_enable(ov5640_data.sensor_clk);
+ else
+ clk_disable(ov5640_data.sensor_clk);
+
+ sensor->on = on;
+
+ return 0;
+}
+
+/*!
+ * ov5640_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ov5640_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ int ret = 0;
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->streamcap.capability;
+ cparm->timeperframe = sensor->streamcap.timeperframe;
+ cparm->capturemode = sensor->streamcap.capturemode;
+ ret = 0;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ov5640_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5640_frame_rate frame_rate;
+ int ret = 0;
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ /* Check that the new frame rate is allowed. */
+ if ((timeperframe->numerator == 0) ||
+ (timeperframe->denominator == 0)) {
+ timeperframe->denominator = DEFAULT_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps > MAX_FPS) {
+ timeperframe->denominator = MAX_FPS;
+ timeperframe->numerator = 1;
+ } else if (tgt_fps < MIN_FPS) {
+ timeperframe->denominator = MIN_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ /* Actual frame rate we use */
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5640_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5640_30_fps;
+ else {
+ pr_err(" The camera frame rate is not supported!\n");
+ goto error;
+ }
+
+ ret = ov5640_change_mode(frame_rate,
+ a->parm.capture.capturemode);
+ if (ret < 0)
+ goto error;
+
+ sensor->streamcap.timeperframe = *timeperframe;
+ sensor->streamcap.capturemode = a->parm.capture.capturemode;
+
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_debug(" type is not " \
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+ a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+error:
+ return ret;
+}
+
+static int ov5640_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ const struct ov5640_datafmt *fmt = ov5640_find_datafmt(mf->code);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+
+ if (format->pad)
+ return -EINVAL;
+
+ if (!fmt) {
+ mf->code = ov5640_colour_fmts[0].code;
+ mf->colorspace = ov5640_colour_fmts[0].colorspace;
+ }
+
+ mf->field = V4L2_FIELD_NONE;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
+ sensor->fmt = fmt;
+
+ return 0;
+}
+
+static int ov5640_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+ const struct ov5640_datafmt *fmt = sensor->fmt;
+
+ if (format->pad)
+ return -EINVAL;
+
+ mf->code = fmt->code;
+ mf->colorspace = fmt->colorspace;
+ mf->field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+static int ov5640_enum_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->pad || code->index >= ARRAY_SIZE(ov5640_colour_fmts))
+ return -EINVAL;
+
+ code->code = ov5640_colour_fmts[code->index].code;
+ return 0;
+}
+
+/*!
+ * ov5640_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5640_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ fse->max_width =
+ max(ov5640_mode_info_data[0][fse->index].width,
+ ov5640_mode_info_data[1][fse->index].width);
+ fse->min_width = fse->max_width;
+ fse->max_height =
+ max(ov5640_mode_info_data[0][fse->index].height,
+ ov5640_mode_info_data[1][fse->index].height);
+ fse->min_height = fse->max_height;
+ return 0;
+}
+
+/*!
+ * ov5640_enum_frameintervals - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5640_enum_frameintervals(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ int i, j, count;
+
+ if (fie->index < 0 || fie->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ if (fie->width == 0 || fie->height == 0 ||
+ fie->code == 0) {
+ pr_warning("Please assign pixel format, width and height.\n");
+ return -EINVAL;
+ }
+
+ fie->interval.numerator = 1;
+
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
+ for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
+ if (fie->width == ov5640_mode_info_data[i][j].width
+ && fie->height == ov5640_mode_info_data[i][j].height
+ && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
+ count++;
+ }
+ if (fie->index == (count - 1)) {
+ fie->interval.denominator =
+ ov5640_framerates[i];
+ return 0;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ov5640_set_clk_rate(void)
+{
+ u32 tgt_xclk; /* target xclk */
+ int ret;
+
+ /* mclk */
+ tgt_xclk = ov5640_data.mclk;
+ tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
+ tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
+ ov5640_data.mclk = tgt_xclk;
+
+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+ ret = clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk);
+ if (ret < 0)
+ pr_debug("set rate filed, rate=%d\n", ov5640_data.mclk);
+ return ret;
+}
+
+/*!
+ * dev_init - V4L2 sensor init
+ * @s: pointer to standard V4L2 device structure
+ *
+ */
+static int init_device(void)
+{
+ u32 tgt_xclk; /* target xclk */
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5640_frame_rate frame_rate;
+ int ret;
+
+ ov5640_data.on = true;
+
+ /* mclk */
+ tgt_xclk = ov5640_data.mclk;
+
+ /* Default camera frame rate is set in probe */
+ tgt_fps = ov5640_data.streamcap.timeperframe.denominator /
+ ov5640_data.streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5640_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5640_30_fps;
+ else
+ return -EINVAL; /* Only support 15fps or 30fps now. */
+
+ ret = ov5640_init_mode();
+
+ return ret;
+}
+
+static struct v4l2_subdev_video_ops ov5640_subdev_video_ops = {
+ .g_parm = ov5640_g_parm,
+ .s_parm = ov5640_s_parm,
+};
+
+static const struct v4l2_subdev_pad_ops ov5640_subdev_pad_ops = {
+ .enum_frame_size = ov5640_enum_framesizes,
+ .enum_frame_interval = ov5640_enum_frameintervals,
+ .enum_mbus_code = ov5640_enum_code,
+ .set_fmt = ov5640_set_fmt,
+ .get_fmt = ov5640_get_fmt,
+};
+
+static struct v4l2_subdev_core_ops ov5640_subdev_core_ops = {
+ .s_power = ov5640_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .g_register = ov5640_get_register,
+ .s_register = ov5640_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5640_subdev_ops = {
+ .core = &ov5640_subdev_core_ops,
+ .video = &ov5640_subdev_video_ops,
+ .pad = &ov5640_subdev_pad_ops,
+};
+
+/*!
+ * ov5640 I2C probe function
+ *
+ * @param adapter struct i2c_adapter *
+ * @return Error code indicating success or failure
+ */
+static int ov5640_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+ int retval;
+ u8 chip_id_high, chip_id_low;
+
+ /* ov5640 pinctrl */
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(dev, "setup pinctrl failed\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio)) {
+ dev_err(dev, "no sensor pwdn pin available\n");
+ return -ENODEV;
+ }
+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_pwdn");
+ if (retval < 0)
+ return retval;
+
+ /* request reset pin */
+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(rst_gpio)) {
+ dev_err(dev, "no sensor reset pin available\n");
+ return -EINVAL;
+ }
+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_reset");
+ if (retval < 0)
+ return retval;
+
+ /* Set initial values for the sensor struct. */
+ memset(&ov5640_data, 0, sizeof(ov5640_data));
+ ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(ov5640_data.sensor_clk)) {
+ dev_err(dev, "get mclk failed\n");
+ return PTR_ERR(ov5640_data.sensor_clk);
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk",
+ &ov5640_data.mclk);
+ if (retval) {
+ dev_err(dev, "mclk frequency is invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk_source",
+ (u32 *) &(ov5640_data.mclk_source));
+ if (retval) {
+ dev_err(dev, "mclk_source invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "csi_id",
+ &(ov5640_data.csi));
+ if (retval) {
+ dev_err(dev, "csi_id invalid\n");
+ return retval;
+ }
+
+ /* Set mclk rate before clk on */
+ ov5640_set_clk_rate();
+
+ clk_prepare_enable(ov5640_data.sensor_clk);
+
+ ov5640_data.io_init = ov5640_reset;
+ ov5640_data.i2c_client = client;
+ ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ ov5640_data.pix.width = 640;
+ ov5640_data.pix.height = 480;
+ ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+ V4L2_CAP_TIMEPERFRAME;
+ ov5640_data.streamcap.capturemode = 0;
+ ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+ ov5640_data.streamcap.timeperframe.numerator = 1;
+
+ ov5640_regulator_enable(&client->dev);
+
+ ov5640_reset();
+
+ ov5640_power_down(0);
+
+ retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
+ if (retval < 0 || chip_id_high != 0x56) {
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ pr_warning("camera ov5640 is not found\n");
+ return -ENODEV;
+ }
+ retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
+ if (retval < 0 || chip_id_low != 0x40) {
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ pr_warning("camera ov5640 is not found\n");
+ return -ENODEV;
+ }
+
+ retval = init_device();
+ if (retval < 0) {
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ pr_warning("camera ov5640 init failed\n");
+ ov5640_power_down(1);
+ return retval;
+ }
+
+ clk_disable(ov5640_data.sensor_clk);
+
+ v4l2_i2c_subdev_init(&ov5640_data.subdev, client, &ov5640_subdev_ops);
+
+ retval = v4l2_async_register_subdev(&ov5640_data.subdev);
+ if (retval < 0)
+ dev_err(&client->dev,
+ "%s--Async register failed, ret=%d\n", __func__, retval);
+
+ pr_info("camera ov5640, is found\n");
+ return retval;
+}
+
+/*!
+ * ov5640 I2C detach function
+ *
+ * @param client struct i2c_client *
+ * @return Error code indicating success or failure
+ */
+static int ov5640_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+ v4l2_async_unregister_subdev(sd);
+
+ clk_unprepare(ov5640_data.sensor_clk);
+
+ ov5640_power_down(1);
+
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+
+ if (core_regulator)
+ regulator_disable(core_regulator);
+
+ if (io_regulator)
+ regulator_disable(io_regulator);
+
+ return 0;
+}
+
+module_i2c_driver(ov5640_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5640 Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/subdev/ov5640_mipi.c b/drivers/media/platform/mxc/subdev/ov5640_mipi.c
new file mode 100644
index 000000000000..4ea4f6a1c719
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/ov5640_mipi.c
@@ -0,0 +1,1660 @@
+/*
+ * 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
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define OV5640_VOLTAGE_ANALOG 2800000
+#define OV5640_VOLTAGE_DIGITAL_CORE 1500000
+#define OV5640_VOLTAGE_DIGITAL_IO 1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5640_XCLK_MIN 6000000
+#define OV5640_XCLK_MAX 24000000
+
+#define OV5640_CHIP_ID_HIGH_BYTE 0x300A
+#define OV5640_CHIP_ID_LOW_BYTE 0x300B
+
+enum ov5640_mode {
+ ov5640_mode_MIN = 0,
+ ov5640_mode_VGA_640_480 = 0,
+ ov5640_mode_NTSC_720_480 = 1,
+ ov5640_mode_720P_1280_720 = 2,
+ ov5640_mode_1080P_1920_1080 = 3,
+ ov5640_mode_QSXGA_2592_1944 = 4,
+ ov5640_mode_MAX = 5,
+ ov5640_mode_INIT = 0xff, /*only for sensor init*/
+};
+
+enum ov5640_frame_rate {
+ ov5640_15_fps,
+ ov5640_30_fps
+};
+
+static int ov5640_framerates[] = {
+ [ov5640_15_fps] = 15,
+ [ov5640_30_fps] = 30,
+};
+
+struct ov5640_datafmt {
+ u32 code;
+ enum v4l2_colorspace colorspace;
+};
+
+/* image size under 1280 * 960 are SUBSAMPLING
+ * image size upper 1280 * 960 are SCALING
+ */
+enum ov5640_downsize_mode {
+ SUBSAMPLING,
+ SCALING,
+};
+
+struct reg_value {
+ u16 u16RegAddr;
+ u8 u8Val;
+ u8 u8Mask;
+ u32 u32Delay_ms;
+};
+
+struct ov5640_mode_info {
+ enum ov5640_mode mode;
+ enum ov5640_downsize_mode dn_mode;
+ u32 width;
+ u32 height;
+ struct reg_value *init_data_ptr;
+ u32 init_data_size;
+};
+
+struct ov5640 {
+ struct v4l2_subdev subdev;
+ struct i2c_client *i2c_client;
+ struct v4l2_pix_format pix;
+ const struct ov5640_datafmt *fmt;
+ struct v4l2_captureparm streamcap;
+ bool on;
+
+ /* control settings */
+ int brightness;
+ int hue;
+ int contrast;
+ int saturation;
+ int red;
+ int green;
+ int blue;
+ int ae_mode;
+
+ u32 mclk;
+ u8 mclk_source;
+ struct clk *sensor_clk;
+ int csi;
+
+ void (*io_init)(void);
+};
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct ov5640 ov5640_data;
+static int pwn_gpio, rst_gpio;
+
+static struct reg_value ov5640_init_setting_30fps_VGA[] = {
+
+ {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
+ {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
+ {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
+ {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
+ {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
+ {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+ {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
+ {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
+ {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
+ {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
+ {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
+ {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
+ {0x3c01, 0xa4, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
+ {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
+ {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x30, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
+ {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
+ {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
+ {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0},
+ {0x518a, 0x54, 0, 0}, {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0},
+ {0x518d, 0x50, 0, 0}, {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0},
+ {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0},
+ {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0},
+ {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0},
+ {0x5199, 0x6c, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0},
+ {0x519c, 0x09, 0, 0}, {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0},
+ {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0},
+ {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0},
+ {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0},
+ {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0},
+ {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0},
+ {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0},
+ {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0},
+ {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0},
+ {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0},
+ {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0},
+ {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0},
+ {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0},
+ {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0},
+ {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0},
+ {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0},
+ {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0},
+ {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0},
+ {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0},
+ {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0},
+ {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0},
+ {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0},
+ {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0},
+ {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0},
+ {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0},
+ {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0},
+ {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0},
+ {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0},
+ {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0},
+ {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0},
+ {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0},
+ {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0},
+ {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0},
+ {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0},
+ {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0},
+ {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0},
+ {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0},
+ {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0},
+ {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0},
+ {0x3a1f, 0x14, 0, 0}, {0x3008, 0x42, 0, 0}, {0x3c00, 0x04, 0, 300},
+};
+
+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+ {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0x00, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+ {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
+ {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
+ {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
+ {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
+ {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, {0x4005, 0x1a, 0, 0},
+ {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
+};
+
+static struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
+ {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+ {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+ {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
+ {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
+ {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
+ {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
+ {0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
+ {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
+ {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
+ {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
+ {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0},
+ {0x3503, 0, 0, 0},
+};
+
+static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x4202, 0x0f, 0, 0}, /* stream off the sensor */
+ {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, /*disable flip*/
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
+ {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+ {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+ {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70}, {0x3008, 0x02, 0, 0},
+ {0x4202, 0x00, 0, 0}, /* stream on the sensor */
+};
+
+static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
+ {
+ {ov5640_mode_VGA_640_480, -1, 0, 0, NULL, 0},
+ {ov5640_mode_NTSC_720_480, -1, 0, 0, NULL, 0},
+ {ov5640_mode_720P_1280_720, -1, 0, 0, NULL, 0},
+ {ov5640_mode_1080P_1920_1080, -1, 0, 0, NULL, 0},
+ {ov5640_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
+ ov5640_setting_15fps_QSXGA_2592_1944,
+ ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
+ },
+ {
+ {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480,
+ ov5640_setting_30fps_VGA_640_480,
+ ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
+ {ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
+ ov5640_setting_30fps_NTSC_720_480,
+ ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
+ {ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
+ ov5640_setting_30fps_720P_1280_720,
+ ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
+ {ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
+ ov5640_setting_30fps_1080P_1920_1080,
+ ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
+ {ov5640_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
+ },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+static struct regulator *gpo_regulator;
+
+static int ov5640_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *device_id);
+static int ov5640_remove(struct i2c_client *client);
+
+static s32 ov5640_read_reg(u16 reg, u8 *val);
+static s32 ov5640_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5640_id[] = {
+ {"ov5640_mipi", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ov5640_mipi",
+ },
+ .probe = ov5640_probe,
+ .remove = ov5640_remove,
+ .id_table = ov5640_id,
+};
+
+static const struct ov5640_datafmt ov5640_colour_fmts[] = {
+ {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+};
+
+static struct ov5640 *to_ov5640(const struct i2c_client *client)
+{
+ return container_of(i2c_get_clientdata(client), struct ov5640, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct ov5640_datafmt
+ *ov5640_find_datafmt(u32 code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ov5640_colour_fmts); i++)
+ if (ov5640_colour_fmts[i].code == code)
+ return ov5640_colour_fmts + i;
+
+ return NULL;
+}
+
+static inline void ov5640_power_down(int enable)
+{
+ if (pwn_gpio < 0)
+ return;
+
+ if (!enable)
+ gpio_set_value_cansleep(pwn_gpio, 0);
+ else
+ gpio_set_value_cansleep(pwn_gpio, 1);
+
+ msleep(2);
+}
+
+static void ov5640_reset(void)
+{
+ if (rst_gpio < 0 || pwn_gpio < 0)
+ return;
+
+ /* camera reset */
+ gpio_set_value(rst_gpio, 1);
+
+ /* camera power dowmn */
+ gpio_set_value(pwn_gpio, 1);
+ msleep(5);
+
+ gpio_set_value(pwn_gpio, 0);
+ msleep(5);
+
+ gpio_set_value(rst_gpio, 0);
+ msleep(1);
+
+ gpio_set_value(rst_gpio, 1);
+ msleep(5);
+
+ gpio_set_value(pwn_gpio, 1);
+}
+
+static int ov5640_regulator_enable(struct device *dev)
+{
+ int ret = 0;
+
+ io_regulator = devm_regulator_get(dev, "DOVDD");
+ if (!IS_ERR(io_regulator)) {
+ regulator_set_voltage(io_regulator,
+ OV5640_VOLTAGE_DIGITAL_IO,
+ OV5640_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(io_regulator);
+ if (ret) {
+ pr_err("%s:io set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:io set voltage ok\n", __func__);
+ }
+ } else {
+ pr_err("%s: cannot get io voltage error\n", __func__);
+ io_regulator = NULL;
+ }
+
+ core_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(core_regulator)) {
+ regulator_set_voltage(core_regulator,
+ OV5640_VOLTAGE_DIGITAL_CORE,
+ OV5640_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(core_regulator);
+ if (ret) {
+ pr_err("%s:core set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:core set voltage ok\n", __func__);
+ }
+ } else {
+ core_regulator = NULL;
+ pr_err("%s: cannot get core voltage error\n", __func__);
+ }
+
+ analog_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(analog_regulator)) {
+ regulator_set_voltage(analog_regulator,
+ OV5640_VOLTAGE_ANALOG,
+ OV5640_VOLTAGE_ANALOG);
+ ret = regulator_enable(analog_regulator);
+ if (ret) {
+ pr_err("%s:analog set voltage error\n",
+ __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:analog set voltage ok\n", __func__);
+ }
+ } else {
+ analog_regulator = NULL;
+ pr_err("%s: cannot get analog voltage error\n", __func__);
+ }
+
+ return ret;
+}
+
+static s32 ov5640_write_reg(u16 reg, u8 val)
+{
+ u8 au8Buf[3] = {0};
+
+ au8Buf[0] = reg >> 8;
+ au8Buf[1] = reg & 0xff;
+ au8Buf[2] = val;
+
+ if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x\n",
+ __func__, reg, val);
+ return -1;
+ }
+
+ return 0;
+}
+
+static s32 ov5640_read_reg(u16 reg, u8 *val)
+{
+ u8 au8RegBuf[2] = {0};
+ u8 u8RdVal = 0;
+
+ au8RegBuf[0] = reg >> 8;
+ au8RegBuf[1] = reg & 0xff;
+
+ if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
+ pr_err("%s:write reg error:reg=%x\n",
+ __func__, reg);
+ return -1;
+ }
+
+ if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
+ pr_err("%s:read reg error:reg=%x,val=%x\n",
+ __func__, reg, u8RdVal);
+ return -1;
+ }
+
+ *val = u8RdVal;
+
+ return u8RdVal;
+}
+
+static int prev_sysclk, prev_HTS;
+static int AE_low, AE_high, AE_Target = 52;
+
+static void OV5640_stream_on(void)
+{
+ ov5640_write_reg(0x4202, 0x00);
+}
+
+static void OV5640_stream_off(void)
+{
+ ov5640_write_reg(0x4202, 0x0f);
+ ov5640_write_reg(0x3008, 0x42);
+}
+
+static int OV5640_get_sysclk(void)
+{
+ /* calculate sysclk */
+ int xvclk = ov5640_data.mclk / 10000;
+ int temp1, temp2;
+ int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv;
+ int Bit_div2x = 1, sclk_rdiv, sysclk;
+ u8 temp;
+
+ int sclk_rdiv_map[] = {1, 2, 4, 8};
+
+ temp1 = ov5640_read_reg(0x3034, &temp);
+ temp2 = temp1 & 0x0f;
+ if (temp2 == 8 || temp2 == 10)
+ Bit_div2x = temp2 / 2;
+
+ temp1 = ov5640_read_reg(0x3035, &temp);
+ SysDiv = temp1>>4;
+ if (SysDiv == 0)
+ SysDiv = 16;
+
+ temp1 = ov5640_read_reg(0x3036, &temp);
+ Multiplier = temp1;
+
+ temp1 = ov5640_read_reg(0x3037, &temp);
+ PreDiv = temp1 & 0x0f;
+ Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
+
+ temp1 = ov5640_read_reg(0x3108, &temp);
+ temp2 = temp1 & 0x03;
+ sclk_rdiv = sclk_rdiv_map[temp2];
+
+ VCO = xvclk * Multiplier / PreDiv;
+
+ sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
+
+ return sysclk;
+}
+
+static void OV5640_set_night_mode(void)
+{
+ /* read HTS from register settings */
+ u8 mode;
+
+ ov5640_read_reg(0x3a00, &mode);
+ mode &= 0xfb;
+ ov5640_write_reg(0x3a00, mode);
+}
+
+static int OV5640_get_HTS(void)
+{
+ /* read HTS from register settings */
+ int HTS;
+ u8 temp;
+
+ HTS = ov5640_read_reg(0x380c, &temp);
+ HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
+
+ return HTS;
+}
+
+static int OV5640_get_VTS(void)
+{
+ /* read VTS from register settings */
+ int VTS;
+ u8 temp;
+
+ /* total vertical size[15:8] high byte */
+ VTS = ov5640_read_reg(0x380e, &temp);
+
+ VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
+
+ return VTS;
+}
+
+static int OV5640_set_VTS(int VTS)
+{
+ /* write VTS to registers */
+ int temp;
+
+ temp = VTS & 0xff;
+ ov5640_write_reg(0x380f, temp);
+
+ temp = VTS>>8;
+ ov5640_write_reg(0x380e, temp);
+
+ return 0;
+}
+
+static int OV5640_get_shutter(void)
+{
+ /* read shutter, in number of line period */
+ int shutter;
+ u8 temp;
+
+ shutter = (ov5640_read_reg(0x03500, &temp) & 0x0f);
+ shutter = (shutter<<8) + ov5640_read_reg(0x3501, &temp);
+ shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &temp)>>4);
+
+ return shutter;
+}
+
+static int OV5640_set_shutter(int shutter)
+{
+ /* write shutter, in number of line period */
+ int temp;
+
+ shutter = shutter & 0xffff;
+
+ temp = shutter & 0x0f;
+ temp = temp<<4;
+ ov5640_write_reg(0x3502, temp);
+
+ temp = shutter & 0xfff;
+ temp = temp>>4;
+ ov5640_write_reg(0x3501, temp);
+
+ temp = shutter>>12;
+ ov5640_write_reg(0x3500, temp);
+
+ return 0;
+}
+
+static int OV5640_get_gain16(void)
+{
+ /* read gain, 16 = 1x */
+ int gain16;
+ u8 temp;
+
+ gain16 = ov5640_read_reg(0x350a, &temp) & 0x03;
+ gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &temp);
+
+ return gain16;
+}
+
+static int OV5640_set_gain16(int gain16)
+{
+ /* write gain, 16 = 1x */
+ u8 temp;
+ gain16 = gain16 & 0x3ff;
+
+ temp = gain16 & 0xff;
+ ov5640_write_reg(0x350b, temp);
+
+ temp = gain16>>8;
+ ov5640_write_reg(0x350a, temp);
+
+ return 0;
+}
+
+static int OV5640_get_light_freq(void)
+{
+ /* get banding filter value */
+ int temp, temp1, light_freq = 0;
+ u8 tmp;
+
+ temp = ov5640_read_reg(0x3c01, &tmp);
+
+ if (temp & 0x80) {
+ /* manual */
+ temp1 = ov5640_read_reg(0x3c00, &tmp);
+ if (temp1 & 0x04) {
+ /* 50Hz */
+ light_freq = 50;
+ } else {
+ /* 60Hz */
+ light_freq = 60;
+ }
+ } else {
+ /* auto */
+ temp1 = ov5640_read_reg(0x3c0c, &tmp);
+ if (temp1 & 0x01) {
+ /* 50Hz */
+ light_freq = 50;
+ } else {
+ /* 60Hz */
+ }
+ }
+ return light_freq;
+}
+
+static void OV5640_set_bandingfilter(void)
+{
+ int prev_VTS;
+ int band_step60, max_band60, band_step50, max_band50;
+
+ /* read preview PCLK */
+ prev_sysclk = OV5640_get_sysclk();
+ /* read preview HTS */
+ prev_HTS = OV5640_get_HTS();
+
+ /* read preview VTS */
+ prev_VTS = OV5640_get_VTS();
+
+ /* calculate banding filter */
+ /* 60Hz */
+ band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
+ ov5640_write_reg(0x3a0a, (band_step60 >> 8));
+ ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
+
+ max_band60 = (int)((prev_VTS-4)/band_step60);
+ ov5640_write_reg(0x3a0d, max_band60);
+
+ /* 50Hz */
+ band_step50 = prev_sysclk * 100/prev_HTS;
+ ov5640_write_reg(0x3a08, (band_step50 >> 8));
+ ov5640_write_reg(0x3a09, (band_step50 & 0xff));
+
+ max_band50 = (int)((prev_VTS-4)/band_step50);
+ ov5640_write_reg(0x3a0e, max_band50);
+}
+
+static int OV5640_set_AE_target(int target)
+{
+ /* stable in high */
+ int fast_high, fast_low;
+ AE_low = target * 23 / 25; /* 0.92 */
+ AE_high = target * 27 / 25; /* 1.08 */
+
+ fast_high = AE_high<<1;
+ if (fast_high > 255)
+ fast_high = 255;
+
+ fast_low = AE_low >> 1;
+
+ ov5640_write_reg(0x3a0f, AE_high);
+ ov5640_write_reg(0x3a10, AE_low);
+ ov5640_write_reg(0x3a1b, AE_high);
+ ov5640_write_reg(0x3a1e, AE_low);
+ ov5640_write_reg(0x3a11, fast_high);
+ ov5640_write_reg(0x3a1f, fast_low);
+
+ return 0;
+}
+
+static void OV5640_turn_on_AE_AG(int enable)
+{
+ u8 ae_ag_ctrl;
+
+ ov5640_read_reg(0x3503, &ae_ag_ctrl);
+ if (enable) {
+ /* turn on auto AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
+ } else {
+ /* turn off AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl | 0x03;
+ }
+ ov5640_write_reg(0x3503, ae_ag_ctrl);
+}
+
+static bool binning_on(void)
+{
+ u8 temp;
+ ov5640_read_reg(0x3821, &temp);
+ temp &= 0xfe;
+ if (temp)
+ return true;
+ else
+ return false;
+}
+
+static void ov5640_set_virtual_channel(int channel)
+{
+ u8 channel_id;
+
+ ov5640_read_reg(0x4814, &channel_id);
+ channel_id &= ~(3 << 6);
+ ov5640_write_reg(0x4814, channel_id | (channel << 6));
+}
+
+/* download ov5640 settings to sensor through i2c */
+static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+{
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int i, retval = 0;
+
+ for (i = 0; i < ArySize; ++i, ++pModeSetting) {
+ Delay_ms = pModeSetting->u32Delay_ms;
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u8Val;
+ Mask = pModeSetting->u8Mask;
+
+ if (Mask) {
+ retval = ov5640_read_reg(RegAddr, &RegVal);
+ if (retval < 0)
+ goto err;
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = ov5640_write_reg(RegAddr, Val);
+ if (retval < 0)
+ goto err;
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+ }
+err:
+ return retval;
+}
+
+/* sensor changes between scaling and subsampling
+ * go through exposure calcualtion
+ */
+static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ u8 average;
+ int prev_shutter, prev_gain16;
+ int cap_shutter, cap_gain16;
+ int cap_sysclk, cap_HTS, cap_VTS;
+ int light_freq, cap_bandfilt, cap_maxband;
+ long cap_gain16_shutter;
+ int retval = 0;
+
+ /* check if the input mode and frame rate is valid */
+ pModeSetting =
+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5640_data.pix.width =
+ ov5640_mode_info_data[frame_rate][mode].width;
+ ov5640_data.pix.height =
+ ov5640_mode_info_data[frame_rate][mode].height;
+
+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* auto focus */
+ /* OV5640_auto_focus();//if no af function, just skip it */
+
+ /* turn off AE/AG */
+ OV5640_turn_on_AE_AG(0);
+
+ /* read preview shutter */
+ prev_shutter = OV5640_get_shutter();
+ if ((binning_on()) && (mode != ov5640_mode_720P_1280_720)
+ && (mode != ov5640_mode_1080P_1920_1080))
+ prev_shutter *= 2;
+
+ /* read preview gain */
+ prev_gain16 = OV5640_get_gain16();
+
+ /* get average */
+ ov5640_read_reg(0x56a1, &average);
+
+ /* turn off night mode for capture */
+ OV5640_set_night_mode();
+
+ /* turn off overlay */
+ /* ov5640_write_reg(0x3022, 0x06);//if no af function, just skip it */
+
+ OV5640_stream_off();
+
+ /* Write capture setting */
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ /* read capture VTS */
+ cap_VTS = OV5640_get_VTS();
+ cap_HTS = OV5640_get_HTS();
+ cap_sysclk = OV5640_get_sysclk();
+
+ /* calculate capture banding filter */
+ light_freq = OV5640_get_light_freq();
+ if (light_freq == 60) {
+ /* 60Hz */
+ cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
+ } else {
+ /* 50Hz */
+ cap_bandfilt = cap_sysclk * 100 / cap_HTS;
+ }
+ cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
+
+ /* calculate capture shutter/gain16 */
+ if (average > AE_low && average < AE_high) {
+ /* in stable range */
+ cap_gain16_shutter =
+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
+ * prev_HTS/cap_HTS * AE_Target / average;
+ } else {
+ cap_gain16_shutter =
+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk
+ * prev_HTS/cap_HTS;
+ }
+
+ /* gain to shutter */
+ if (cap_gain16_shutter < (cap_bandfilt * 16)) {
+ /* shutter < 1/100 */
+ cap_shutter = cap_gain16_shutter/16;
+ if (cap_shutter < 1)
+ cap_shutter = 1;
+
+ cap_gain16 = cap_gain16_shutter/cap_shutter;
+ if (cap_gain16 < 16)
+ cap_gain16 = 16;
+ } else {
+ if (cap_gain16_shutter >
+ (cap_bandfilt * cap_maxband * 16)) {
+ /* exposure reach max */
+ cap_shutter = cap_bandfilt * cap_maxband;
+ cap_gain16 = cap_gain16_shutter / cap_shutter;
+ } else {
+ /* 1/100 < (cap_shutter = n/100) =< max */
+ cap_shutter =
+ ((int) (cap_gain16_shutter/16 / cap_bandfilt))
+ *cap_bandfilt;
+ cap_gain16 = cap_gain16_shutter / cap_shutter;
+ }
+ }
+
+ /* write capture gain */
+ OV5640_set_gain16(cap_gain16);
+
+ /* write capture shutter */
+ if (cap_shutter > (cap_VTS - 4)) {
+ cap_VTS = cap_shutter + 4;
+ OV5640_set_VTS(cap_VTS);
+ }
+ OV5640_set_shutter(cap_shutter);
+
+err:
+ return retval;
+}
+
+/* if sensor changes inside scaling or subsampling
+ * change mode directly
+ * */
+static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+
+ /* check if the input mode and frame rate is valid */
+ pModeSetting =
+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5640_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5640_data.pix.width =
+ ov5640_mode_info_data[frame_rate][mode].width;
+ ov5640_data.pix.height =
+ ov5640_mode_info_data[frame_rate][mode].height;
+
+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* turn off AE/AG */
+ OV5640_turn_on_AE_AG(0);
+
+ OV5640_stream_off();
+
+ /* Write capture setting */
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ OV5640_turn_on_AE_AG(1);
+
+err:
+ return retval;
+}
+
+static int ov5640_init_mode(enum ov5640_frame_rate frame_rate,
+ enum ov5640_mode mode, enum ov5640_mode orig_mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+ u32 msec_wait4stable = 0;
+ enum ov5640_downsize_mode dn_mode, orig_dn_mode;
+
+ if ((mode > ov5640_mode_MAX || mode < ov5640_mode_MIN)
+ && (mode != ov5640_mode_INIT)) {
+ pr_err("Wrong ov5640 mode detected!\n");
+ return -1;
+ }
+
+ dn_mode = ov5640_mode_info_data[frame_rate][mode].dn_mode;
+ orig_dn_mode = ov5640_mode_info_data[frame_rate][orig_mode].dn_mode;
+ if (mode == ov5640_mode_INIT) {
+ pModeSetting = ov5640_init_setting_30fps_VGA;
+ ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
+
+ ov5640_data.pix.width = 640;
+ ov5640_data.pix.height = 480;
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ pModeSetting = ov5640_setting_30fps_VGA_640_480;
+ ArySize = ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480);
+ retval = ov5640_download_firmware(pModeSetting, ArySize);
+ } else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
+ (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
+ /* change between subsampling and scaling
+ * go through exposure calucation */
+ retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
+ } else {
+ /* change inside subsampling or scaling
+ * download firmware directly */
+ retval = ov5640_change_mode_direct(frame_rate, mode);
+ }
+
+ if (retval < 0)
+ goto err;
+
+ OV5640_set_AE_target(AE_Target);
+ OV5640_get_light_freq();
+ OV5640_set_bandingfilter();
+ ov5640_set_virtual_channel(ov5640_data.csi);
+
+ /* add delay to wait for sensor stable */
+ if (mode == ov5640_mode_QSXGA_2592_1944) {
+ /* dump the first two frames: 1/7.5*2
+ * the frame rate of QSXGA is 7.5fps */
+ msec_wait4stable = 267;
+ } else {
+ /* dump the first eighteen frames: 1/30*18 */
+ msec_wait4stable = 600;
+ }
+ msleep(msec_wait4stable);
+
+err:
+ return retval;
+}
+
+/*!
+ * ov5640_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ov5640_s_power(struct v4l2_subdev *sd, int on)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+
+ if (on && !sensor->on) {
+ if (io_regulator)
+ if (regulator_enable(io_regulator) != 0)
+ return -EIO;
+ if (core_regulator)
+ if (regulator_enable(core_regulator) != 0)
+ return -EIO;
+ if (gpo_regulator)
+ if (regulator_enable(gpo_regulator) != 0)
+ return -EIO;
+ if (analog_regulator)
+ if (regulator_enable(analog_regulator) != 0)
+ return -EIO;
+ } else if (!on && sensor->on) {
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+ if (core_regulator)
+ regulator_disable(core_regulator);
+ if (io_regulator)
+ regulator_disable(io_regulator);
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+ }
+
+ sensor->on = on;
+
+ return 0;
+}
+
+/*!
+ * ov5640_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ov5640_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ int ret = 0;
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->streamcap.capability;
+ cparm->timeperframe = sensor->streamcap.timeperframe;
+ cparm->capturemode = sensor->streamcap.capturemode;
+ ret = 0;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ov5640_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5640_frame_rate frame_rate;
+ enum ov5640_mode orig_mode;
+ int ret = 0;
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ /* Check that the new frame rate is allowed. */
+ if ((timeperframe->numerator == 0) ||
+ (timeperframe->denominator == 0)) {
+ timeperframe->denominator = DEFAULT_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps > MAX_FPS) {
+ timeperframe->denominator = MAX_FPS;
+ timeperframe->numerator = 1;
+ } else if (tgt_fps < MIN_FPS) {
+ timeperframe->denominator = MIN_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ /* Actual frame rate we use */
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5640_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5640_30_fps;
+ else {
+ pr_err(" The camera frame rate is not supported!\n");
+ return -EINVAL;
+ }
+
+ orig_mode = sensor->streamcap.capturemode;
+ ret = ov5640_init_mode(frame_rate,
+ (u32)a->parm.capture.capturemode, orig_mode);
+ if (ret < 0)
+ return ret;
+
+ sensor->streamcap.timeperframe = *timeperframe;
+ sensor->streamcap.capturemode =
+ (u32)a->parm.capture.capturemode;
+
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_debug(" type is not " \
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+ a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int ov5640_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ const struct ov5640_datafmt *fmt = ov5640_find_datafmt(mf->code);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+
+ if (!fmt) {
+ mf->code = ov5640_colour_fmts[0].code;
+ mf->colorspace = ov5640_colour_fmts[0].colorspace;
+ }
+
+ mf->field = V4L2_FIELD_NONE;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
+ sensor->fmt = fmt;
+
+ return 0;
+}
+
+
+static int ov5640_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5640 *sensor = to_ov5640(client);
+ const struct ov5640_datafmt *fmt = sensor->fmt;
+
+ if (format->pad)
+ return -EINVAL;
+
+ mf->code = fmt->code;
+ mf->colorspace = fmt->colorspace;
+ mf->field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+static int ov5640_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->pad || code->index >= ARRAY_SIZE(ov5640_colour_fmts))
+ return -EINVAL;
+
+ code->code = ov5640_colour_fmts[code->index].code;
+ return 0;
+}
+
+/*!
+ * ov5640_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5640_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ fse->max_width =
+ max(ov5640_mode_info_data[0][fse->index].width,
+ ov5640_mode_info_data[1][fse->index].width);
+ fse->min_width = fse->max_width;
+ fse->max_height =
+ max(ov5640_mode_info_data[0][fse->index].height,
+ ov5640_mode_info_data[1][fse->index].height);
+ fse->min_height = fse->max_height;
+ return 0;
+}
+
+/*!
+ * ov5640_enum_frameintervals - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5640_enum_frameintervals(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ int i, j, count = 0;
+
+ if (fie->index < 0 || fie->index > ov5640_mode_MAX)
+ return -EINVAL;
+
+ if (fie->width == 0 || fie->height == 0 ||
+ fie->code == 0) {
+ pr_warning("Please assign pixel format, width and height.\n");
+ return -EINVAL;
+ }
+
+ fie->interval.numerator = 1;
+
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
+ for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
+ if (fie->width == ov5640_mode_info_data[i][j].width
+ && fie->height == ov5640_mode_info_data[i][j].height
+ && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
+ count++;
+ }
+ if (fie->index == (count - 1)) {
+ fie->interval.denominator =
+ ov5640_framerates[i];
+ return 0;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+/*!
+ * dev_init - V4L2 sensor init
+ * @s: pointer to standard V4L2 device structure
+ *
+ */
+static int init_device(void)
+{
+ u32 tgt_xclk; /* target xclk */
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5640_frame_rate frame_rate;
+ int ret;
+
+ ov5640_data.on = true;
+
+ /* mclk */
+ tgt_xclk = ov5640_data.mclk;
+ tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
+ tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
+ ov5640_data.mclk = tgt_xclk;
+
+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+
+ /* Default camera frame rate is set in probe */
+ tgt_fps = ov5640_data.streamcap.timeperframe.denominator /
+ ov5640_data.streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5640_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5640_30_fps;
+ else
+ return -EINVAL; /* Only support 15fps or 30fps now. */
+
+ ret = ov5640_init_mode(frame_rate, ov5640_mode_INIT, ov5640_mode_INIT);
+
+ return ret;
+}
+
+static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ if (enable)
+ OV5640_stream_on();
+ else
+ OV5640_stream_off();
+ return 0;
+}
+
+static struct v4l2_subdev_video_ops ov5640_subdev_video_ops = {
+ .g_parm = ov5640_g_parm,
+ .s_parm = ov5640_s_parm,
+ .s_stream = ov5640_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops ov5640_subdev_pad_ops = {
+ .enum_frame_size = ov5640_enum_framesizes,
+ .enum_frame_interval = ov5640_enum_frameintervals,
+ .enum_mbus_code = ov5640_enum_mbus_code,
+ .set_fmt = ov5640_set_fmt,
+ .get_fmt = ov5640_get_fmt,
+};
+
+static struct v4l2_subdev_core_ops ov5640_subdev_core_ops = {
+ .s_power = ov5640_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .g_register = ov5640_get_register,
+ .s_register = ov5640_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5640_subdev_ops = {
+ .core = &ov5640_subdev_core_ops,
+ .video = &ov5640_subdev_video_ops,
+ .pad = &ov5640_subdev_pad_ops,
+};
+
+
+/*!
+ * ov5640 I2C probe function
+ *
+ * @param adapter struct i2c_adapter *
+ * @return Error code indicating success or failure
+ */
+static int ov5640_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+ int retval;
+ u8 chip_id_high, chip_id_low;
+
+ /* ov5640 pinctrl */
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(dev, "no pin available\n");
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio))
+ dev_warn(dev, "no sensor pwdn pin available");
+ else {
+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_mipi_pwdn");
+ if (retval < 0) {
+ dev_warn(dev, "Failed to set power pin\n");
+ dev_warn(dev, "retval=%d\n", retval);
+ return retval;
+ }
+ }
+
+ /* request reset pin */
+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(rst_gpio))
+ dev_warn(dev, "no sensor reset pin available");
+ else {
+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_mipi_reset");
+ if (retval < 0) {
+ dev_warn(dev, "Failed to set reset pin\n");
+ return retval;
+ }
+ }
+
+ /* Set initial values for the sensor struct. */
+ memset(&ov5640_data, 0, sizeof(ov5640_data));
+ ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(ov5640_data.sensor_clk)) {
+ /* assuming clock enabled by default */
+ ov5640_data.sensor_clk = NULL;
+ dev_err(dev, "clock-frequency missing or invalid\n");
+ return PTR_ERR(ov5640_data.sensor_clk);
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk",
+ &(ov5640_data.mclk));
+ if (retval) {
+ dev_err(dev, "mclk missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk_source",
+ (u32 *) &(ov5640_data.mclk_source));
+ if (retval) {
+ dev_err(dev, "mclk_source missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "csi_id",
+ &(ov5640_data.csi));
+ if (retval) {
+ dev_err(dev, "csi id missing or invalid\n");
+ return retval;
+ }
+
+ clk_prepare_enable(ov5640_data.sensor_clk);
+
+ ov5640_data.io_init = ov5640_reset;
+ ov5640_data.i2c_client = client;
+ ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ ov5640_data.pix.width = 640;
+ ov5640_data.pix.height = 480;
+ ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+ V4L2_CAP_TIMEPERFRAME;
+ ov5640_data.streamcap.capturemode = 0;
+ ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+ ov5640_data.streamcap.timeperframe.numerator = 1;
+
+ ov5640_regulator_enable(&client->dev);
+
+ ov5640_reset();
+
+ ov5640_power_down(0);
+
+ retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
+ if (retval < 0 || chip_id_high != 0x56) {
+ pr_warning("camera ov5640_mipi is not found\n");
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ return -ENODEV;
+ }
+ retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
+ if (retval < 0 || chip_id_low != 0x40) {
+ pr_warning("camera ov5640_mipi is not found\n");
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ return -ENODEV;
+ }
+
+ retval = init_device();
+ if (retval < 0) {
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+ pr_warning("camera ov5640 init failed\n");
+ ov5640_power_down(1);
+ return retval;
+ }
+
+ v4l2_i2c_subdev_init(&ov5640_data.subdev, client, &ov5640_subdev_ops);
+
+ ov5640_data.subdev.grp_id = 678;
+ retval = v4l2_async_register_subdev(&ov5640_data.subdev);
+ if (retval < 0)
+ dev_err(&client->dev,
+ "%s--Async register failed, ret=%d\n", __func__, retval);
+
+ OV5640_stream_off();
+ pr_info("camera ov5640_mipi is found\n");
+ return retval;
+}
+
+/*!
+ * ov5640 I2C detach function
+ *
+ * @param client struct i2c_client *
+ * @return Error code indicating success or failure
+ */
+static int ov5640_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+ v4l2_async_unregister_subdev(sd);
+
+ clk_disable_unprepare(ov5640_data.sensor_clk);
+
+ ov5640_power_down(1);
+
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+
+ if (core_regulator)
+ regulator_disable(core_regulator);
+
+ if (io_regulator)
+ regulator_disable(io_regulator);
+
+ return 0;
+}
+
+module_i2c_driver(ov5640_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5640 MIPI Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/subdev/ov5647_mipi.c b/drivers/media/platform/mxc/subdev/ov5647_mipi.c
new file mode 100644
index 000000000000..109f77438f51
--- /dev/null
+++ b/drivers/media/platform/mxc/subdev/ov5647_mipi.c
@@ -0,0 +1,1721 @@
+/*
+ * Copyright (C) 2011-2015 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
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define OV5647_VOLTAGE_ANALOG 2800000
+#define OV5647_VOLTAGE_DIGITAL_CORE 1500000
+#define OV5647_VOLTAGE_DIGITAL_IO 1800000
+
+#define MIN_FPS 15
+#define MAX_FPS 30
+#define DEFAULT_FPS 30
+
+#define OV5647_XCLK_MIN 6000000
+#define OV5647_XCLK_MAX 24000000
+
+#define OV5647_CHIP_ID_HIGH_BYTE 0x300A
+#define OV5647_CHIP_ID_LOW_BYTE 0x300B
+
+enum ov5647_mode {
+ ov5647_mode_MIN = 0,
+ ov5647_mode_VGA_640_480 = 0,
+ ov5647_mode_720P_1280_720 = 1,
+ ov5647_mode_1080P_1920_1080 = 2,
+ ov5647_mode_QSXGA_2592_1944 = 3,
+ ov5647_mode_MAX = 3,
+ ov5647_mode_INIT = 0xff, /*only for sensor init*/
+};
+
+enum ov5647_frame_rate {
+ ov5647_15_fps,
+ ov5647_30_fps
+};
+
+static int ov5647_framerates[] = {
+ [ov5647_15_fps] = 15,
+ [ov5647_30_fps] = 30,
+};
+
+struct ov5647_datafmt {
+ u32 code;
+ enum v4l2_colorspace colorspace;
+};
+
+/* image size under 1280 * 960 are SUBSAMPLING
+ * image size upper 1280 * 960 are SCALING
+ */
+enum ov5647_downsize_mode {
+ SUBSAMPLING,
+ SCALING,
+};
+
+struct reg_value {
+ u16 u16RegAddr;
+ u8 u8Val;
+ u8 u8Mask;
+ u32 u32Delay_ms;
+};
+
+struct ov5647_mode_info {
+ enum ov5647_mode mode;
+ enum ov5647_downsize_mode dn_mode;
+ u32 width;
+ u32 height;
+ struct reg_value *init_data_ptr;
+ u32 init_data_size;
+};
+
+struct otp_struct {
+ int customer_id;
+ int module_integrator_id;
+ int lens_id;
+ int rg_ratio;
+ int bg_ratio;
+ int user_data[3];
+ int light_rg;
+ int light_bg;
+};
+
+struct ov5647 {
+ struct v4l2_subdev subdev;
+ struct i2c_client *i2c_client;
+ struct v4l2_pix_format pix;
+ const struct ov5647_datafmt *fmt;
+ struct v4l2_captureparm streamcap;
+ bool on;
+
+ /* control settings */
+ int brightness;
+ int hue;
+ int contrast;
+ int saturation;
+ int red;
+ int green;
+ int blue;
+ int ae_mode;
+
+ u32 mclk;
+ u8 mclk_source;
+ struct clk *sensor_clk;
+ int csi;
+
+ void (*io_init)(void);
+};
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+static struct ov5647 ov5647_data;
+static int pwn_gpio, rst_gpio;
+static int prev_sysclk, prev_HTS;
+static int AE_low, AE_high, AE_Target = 52;
+
+/* R/G and B/G of typical camera module is defined here,
+ * the typical camera module is selected by CameraAnalyzer. */
+static int RG_Ratio_Typical = 0x70;
+static int BG_Ratio_Typical = 0x70;
+
+
+static struct reg_value ov5647_init_setting[] = {
+
+ {0x0100, 0x00, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x69, 0, 0}, {0x303c, 0x11, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x370c, 0x0f, 0, 0}, {0x3612, 0x59, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x5000, 0x06, 0, 0}, {0x5002, 0x40, 0, 0},
+ {0x5003, 0x08, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x3000, 0xff, 0, 0},
+ {0x3001, 0xff, 0, 0}, {0x3002, 0xff, 0, 0}, {0x301d, 0xf0, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3c01, 0x80, 0, 0},
+ {0x3b07, 0x0c, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
+ {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3814, 0x31, 0, 0},
+ {0x3815, 0x31, 0, 0}, {0x3708, 0x64, 0, 0}, {0x3709, 0x52, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
+ {0x380b, 0xc0, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x18, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x0e, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x27, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x95, 0, 0},
+ {0x3630, 0x2e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0},
+ {0x3634, 0x44, 0, 0}, {0x3620, 0x64, 0, 0}, {0x3621, 0xe0, 0, 0},
+ {0x3600, 0x37, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+ {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x3731, 0x02, 0, 0},
+ {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3f05, 0x02, 0, 0},
+ {0x3f06, 0x10, 0, 0}, {0x3f01, 0x0a, 0, 0}, {0x3a08, 0x01, 0, 0},
+ {0x3a09, 0x27, 0, 0}, {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0f, 0x58, 0, 0},
+ {0x3a10, 0x50, 0, 0}, {0x3a1b, 0x58, 0, 0}, {0x3a1e, 0x50, 0, 0},
+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x28, 0, 0}, {0x4001, 0x02, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x4000, 0x09, 0, 0}, {0x4050, 0x6e, 0, 0},
+ {0x4051, 0x8f, 0, 0}, {0x4837, 0x17, 0, 0}, {0x3503, 0x03, 0, 0},
+ {0x3501, 0x44, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350a, 0x00, 0, 0},
+ {0x350b, 0x7f, 0, 0}, {0x5001, 0x01, 0, 0}, {0x5002, 0x41, 0, 0},
+ {0x5180, 0x08, 0, 0}, {0x5186, 0x04, 0, 0}, {0x5187, 0x00, 0, 0},
+ {0x5188, 0x04, 0, 0}, {0x5189, 0x00, 0, 0}, {0x518a, 0x04, 0, 0},
+ {0x518b, 0x00, 0, 0}, {0x5000, 0x86, 0, 0}, {0x5800, 0x11, 0, 0},
+ {0x5801, 0x0a, 0, 0}, {0x5802, 0x09, 0, 0}, {0x5803, 0x09, 0, 0},
+ {0x5804, 0x0a, 0, 0}, {0x5805, 0x0f, 0, 0}, {0x5806, 0x07, 0, 0},
+ {0x5807, 0x05, 0, 0}, {0x5808, 0x03, 0, 0}, {0x5809, 0x03, 0, 0},
+ {0x580a, 0x05, 0, 0}, {0x580b, 0x07, 0, 0}, {0x580c, 0x05, 0, 0},
+ {0x580d, 0x02, 0, 0}, {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0},
+ {0x5810, 0x02, 0, 0}, {0x5811, 0x05, 0, 0}, {0x5812, 0x05, 0, 0},
+ {0x5813, 0x02, 0, 0}, {0x5814, 0x00, 0, 0}, {0x5815, 0x00, 0, 0},
+ {0x5816, 0x01, 0, 0}, {0x5817, 0x05, 0, 0}, {0x5818, 0x08, 0, 0},
+ {0x5819, 0x05, 0, 0}, {0x581a, 0x03, 0, 0}, {0x581b, 0x03, 0, 0},
+ {0x581c, 0x04, 0, 0}, {0x581d, 0x07, 0, 0}, {0x581e, 0x10, 0, 0},
+ {0x581f, 0x0b, 0, 0}, {0x5820, 0x09, 0, 0}, {0x5821, 0x09, 0, 0},
+ {0x5822, 0x09, 0, 0}, {0x5823, 0x0e, 0, 0}, {0x5824, 0x28, 0, 0},
+ {0x5825, 0x1a, 0, 0}, {0x5826, 0x1a, 0, 0}, {0x5827, 0x1a, 0, 0},
+ {0x5828, 0x46, 0, 0}, {0x5829, 0x2a, 0, 0}, {0x582a, 0x26, 0, 0},
+ {0x582b, 0x44, 0, 0}, {0x582c, 0x26, 0, 0}, {0x582d, 0x2a, 0, 0},
+ {0x582e, 0x28, 0, 0}, {0x582f, 0x42, 0, 0}, {0x5830, 0x40, 0, 0},
+ {0x5831, 0x42, 0, 0}, {0x5832, 0x28, 0, 0}, {0x5833, 0x0a, 0, 0},
+ {0x5834, 0x16, 0, 0}, {0x5835, 0x44, 0, 0}, {0x5836, 0x26, 0, 0},
+ {0x5837, 0x2a, 0, 0}, {0x5838, 0x28, 0, 0}, {0x5839, 0x0a, 0, 0},
+ {0x583a, 0x0a, 0, 0}, {0x583b, 0x0a, 0, 0}, {0x583c, 0x26, 0, 0},
+ {0x583d, 0xbe, 0, 0}, {0x0100, 0x01, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, {0x3017, 0xe0, 0, 0},
+ {0x301c, 0xfc, 0, 0}, {0x3636, 0x06, 0, 0}, {0x3016, 0x08, 0, 0},
+ {0x3827, 0xec, 0, 0}, {0x3018, 0x44, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3106, 0xf5, 0, 0}, {0x3034, 0x18, 0, 0}, {0x301c, 0xf8, 0, 0},
+};
+
+static struct reg_value ov5647_setting_60fps_VGA_640_480[] = {
+ {0x0100, 0x00, 0, 0}, {0x3035, 0x11, 0, 0},
+ {0x3036, 0x46, 0, 0}, {0x303c, 0x11, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3820, 0x41, 0, 0}, {0x370c, 0x0f, 0, 0}, {0x3612, 0x59, 0, 0},
+ {0x3618, 0x00, 0, 0}, {0x5000, 0x06, 0, 0}, {0x5002, 0x40, 0, 0},
+ {0x5003, 0x08, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x3000, 0xff, 0, 0},
+ {0x3001, 0xff, 0, 0}, {0x3002, 0xff, 0, 0}, {0x301d, 0xf0, 0, 0},
+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3c01, 0x80, 0, 0},
+ {0x3b07, 0x0c, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x3c, 0, 0},
+ {0x380e, 0x01, 0, 0}, {0x380f, 0xf8, 0, 0}, {0x3814, 0x71, 0, 0},
+ {0x3815, 0x71, 0, 0}, {0x3708, 0x64, 0, 0}, {0x3709, 0x52, 0, 0},
+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
+ {0x380b, 0xe0, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x10, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x2f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+ {0x3630, 0x2e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0},
+ {0x3634, 0x44, 0, 0}, {0x3620, 0x64, 0, 0}, {0x3621, 0xe0, 0, 0},
+ {0x3600, 0x37, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
+ {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x3731, 0x02, 0, 0},
+ {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3f05, 0x02, 0, 0},
+ {0x3f06, 0x10, 0, 0}, {0x3f01, 0x0a, 0, 0}, {0x3a08, 0x01, 0, 0},
+ {0x3a09, 0x2e, 0, 0}, {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xfb, 0, 0},
+ {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x3a0f, 0x58, 0, 0},
+ {0x3a10, 0x50, 0, 0}, {0x3a1b, 0x58, 0, 0}, {0x3a1e, 0x50, 0, 0},
+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x28, 0, 0}, {0x4001, 0x02, 0, 0},
+ {0x4004, 0x02, 0, 0}, {0x4000, 0x09, 0, 0}, {0x4050, 0x6e, 0, 0},
+ {0x4051, 0x8f, 0, 0}, {0x0100, 0x01, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, {0x3017, 0xe0, 0, 0},
+ {0x301c, 0xfc, 0, 0}, {0x3636, 0x06, 0, 0}, {0x3016, 0x08, 0, 0},
+ {0x3827, 0xec, 0, 0}, {0x3018, 0x44, 0, 0}, {0x3035, 0x21, 0, 0},
+ {0x3106, 0xf5, 0, 0}, {0x3034, 0x18, 0, 0}, {0x301c, 0xf8, 0, 0},
+};
+
+static struct reg_value ov5647_setting_30fps_720P_1280_720[] = {
+ {0x0100, 0x00, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
+ {0x3612, 0x59, 0, 0}, {0x3618, 0x00, 0, 0}, {0x380c, 0x09, 0, 0},
+ {0x380d, 0xe8, 0, 0}, {0x380e, 0x04, 0, 0}, {0x380f, 0x50, 0, 0},
+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3709, 0x52, 0, 0},
+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
+ {0x380b, 0xd0, 0, 0}, {0x3801, 0x18, 0, 0}, {0x3802, 0x00, 0, 0},
+ {0x3803, 0xf8, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x27, 0, 0},
+ {0x3806, 0x06, 0, 0}, {0x3807, 0xa7, 0, 0}, {0x3a09, 0xbe, 0, 0},
+ {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x74, 0, 0}, {0x3a0d, 0x02, 0, 0},
+ {0x3a0e, 0x01, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4005, 0x18, 0, 0},
+ {0x0100, 0x01, 0, 0},
+};
+
+static struct reg_value ov5647_setting_30fps_1080P_1920_1080[] = {
+ {0x0100, 0x00, 0, 0}, {0x3820, 0x00, 0, 0}, {0x3821, 0x06, 0, 0},
+ {0x3612, 0x5b, 0, 0}, {0x3618, 0x04, 0, 0}, {0x380c, 0x09, 0, 0},
+ {0x380d, 0xe8, 0, 0}, {0x380e, 0x04, 0, 0}, {0x380f, 0x50, 0, 0},
+ {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3709, 0x12, 0, 0},
+ {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0},
+ {0x380b, 0x38, 0, 0}, {0x3801, 0x5c, 0, 0}, {0x3802, 0x01, 0, 0},
+ {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xe3, 0, 0},
+ {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3a09, 0x4b, 0, 0},
+ {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x13, 0, 0}, {0x3a0d, 0x04, 0, 0},
+ {0x3a0e, 0x03, 0, 0}, {0x4004, 0x04, 0, 0}, {0x4005, 0x18, 0, 0},
+ {0x0100, 0x01, 0, 0},
+};
+
+static struct reg_value ov5647_setting_15fps_QSXGA_2592_1944[] = {
+ {0x0100, 0x00, 0, 0}, {0x3820, 0x00, 0, 0}, {0x3821, 0x06, 0, 0},
+ {0x3612, 0x5b, 0, 0}, {0x3618, 0x04, 0, 0}, {0x380c, 0x0b, 0, 0},
+ {0x380d, 0x10, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb8, 0, 0},
+ {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3709, 0x12, 0, 0},
+ {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+ {0x380b, 0x98, 0, 0}, {0x3801, 0x0c, 0, 0}, {0x3802, 0x00, 0, 0},
+ {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x33, 0, 0},
+ {0x3806, 0x07, 0, 0}, {0x3807, 0xa3, 0, 0}, {0x3a09, 0x28, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0d, 0x08, 0, 0},
+ {0x3a0e, 0x06, 0, 0}, {0x4004, 0x04, 0, 0}, {0x4005, 0x1a, 0, 0},
+ {0x0100, 0x01, 0, 0},
+};
+
+static struct ov5647_mode_info ov5647_mode_info_data[2][ov5647_mode_MAX + 1] = {
+ {
+ {ov5647_mode_VGA_640_480, -1, 0, 0, NULL, 0},
+ {ov5647_mode_720P_1280_720, -1, 0, 0, NULL, 0},
+ {ov5647_mode_1080P_1920_1080, -1, 0, 0, NULL, 0},
+ {ov5647_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
+ ov5647_setting_15fps_QSXGA_2592_1944,
+ ARRAY_SIZE(ov5647_setting_15fps_QSXGA_2592_1944)},
+ },
+ {
+ /* Actually VGA working in 60fps mode */
+ {ov5647_mode_VGA_640_480, SUBSAMPLING, 640, 480,
+ ov5647_setting_60fps_VGA_640_480,
+ ARRAY_SIZE(ov5647_setting_60fps_VGA_640_480)},
+ {ov5647_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
+ ov5647_setting_30fps_720P_1280_720,
+ ARRAY_SIZE(ov5647_setting_30fps_720P_1280_720)},
+ {ov5647_mode_1080P_1920_1080, SCALING, 1920, 1080,
+ ov5647_setting_30fps_1080P_1920_1080,
+ ARRAY_SIZE(ov5647_setting_30fps_1080P_1920_1080)},
+ {ov5647_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
+ },
+};
+
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+static struct regulator *gpo_regulator;
+
+static int ov5647_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *device_id);
+static int ov5647_remove(struct i2c_client *client);
+
+static s32 ov5647_read_reg(u16 reg, u8 *val);
+static s32 ov5647_write_reg(u16 reg, u8 val);
+
+static const struct i2c_device_id ov5647_id[] = {
+ {"ov5647_mipi", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ov5647_id);
+
+static struct i2c_driver ov5647_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ov5647_mipi",
+ },
+ .probe = ov5647_probe,
+ .remove = ov5647_remove,
+ .id_table = ov5647_id,
+};
+
+static const struct ov5647_datafmt ov5647_colour_fmts[] = {
+ {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_JPEG},
+};
+
+static struct ov5647 *to_ov5647(const struct i2c_client *client)
+{
+ return container_of(i2c_get_clientdata(client), struct ov5647, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct ov5647_datafmt
+ *ov5647_find_datafmt(u32 code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ov5647_colour_fmts); i++)
+ if (ov5647_colour_fmts[i].code == code)
+ return ov5647_colour_fmts + i;
+
+ return NULL;
+}
+
+static inline void ov5647_power_down(int enable)
+{
+ if (pwn_gpio < 0)
+ return;
+
+ /* 19x19 pwdn pin invert by mipi daughter card */
+ if (!enable)
+ gpio_set_value_cansleep(pwn_gpio, 1);
+ else
+ gpio_set_value_cansleep(pwn_gpio, 0);
+
+ msleep(2);
+}
+
+static void ov5647_reset(void)
+{
+ if (rst_gpio < 0 || pwn_gpio < 0)
+ return;
+
+ /* camera reset */
+ gpio_set_value_cansleep(rst_gpio, 1);
+
+ /* camera power dowmn */
+ gpio_set_value_cansleep(pwn_gpio, 1);
+ msleep(5);
+
+ gpio_set_value_cansleep(pwn_gpio, 0);
+ msleep(5);
+
+ gpio_set_value_cansleep(rst_gpio, 0);
+ msleep(1);
+
+ gpio_set_value_cansleep(rst_gpio, 1);
+ msleep(5);
+
+ gpio_set_value_cansleep(pwn_gpio, 1);
+}
+
+static int ov5647_regulator_enable(struct device *dev)
+{
+ int ret = 0;
+
+ io_regulator = devm_regulator_get(dev, "DOVDD");
+ if (!IS_ERR(io_regulator)) {
+ regulator_set_voltage(io_regulator,
+ OV5647_VOLTAGE_DIGITAL_IO,
+ OV5647_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(io_regulator);
+ if (ret) {
+ pr_err("%s:io set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:io set voltage ok\n", __func__);
+ }
+ } else {
+ pr_err("%s: cannot get io voltage error\n", __func__);
+ io_regulator = NULL;
+ }
+
+ core_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(core_regulator)) {
+ regulator_set_voltage(core_regulator,
+ OV5647_VOLTAGE_DIGITAL_CORE,
+ OV5647_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(core_regulator);
+ if (ret) {
+ pr_err("%s:core set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:core set voltage ok\n", __func__);
+ }
+ } else {
+ core_regulator = NULL;
+ pr_err("%s: cannot get core voltage error\n", __func__);
+ }
+
+ analog_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(analog_regulator)) {
+ regulator_set_voltage(analog_regulator,
+ OV5647_VOLTAGE_ANALOG,
+ OV5647_VOLTAGE_ANALOG);
+ ret = regulator_enable(analog_regulator);
+ if (ret) {
+ pr_err("%s:analog set voltage error\n",
+ __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:analog set voltage ok\n", __func__);
+ }
+ } else {
+ analog_regulator = NULL;
+ pr_err("%s: cannot get analog voltage error\n", __func__);
+ }
+
+ return ret;
+}
+
+static s32 ov5647_write_reg(u16 reg, u8 val)
+{
+ u8 au8Buf[3] = {0};
+
+ au8Buf[0] = reg >> 8;
+ au8Buf[1] = reg & 0xff;
+ au8Buf[2] = val;
+
+ if (i2c_master_send(ov5647_data.i2c_client, au8Buf, 3) < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x\n",
+ __func__, reg, val);
+ return -1;
+ }
+
+ return 0;
+}
+
+static s32 ov5647_read_reg(u16 reg, u8 *val)
+{
+ u8 au8RegBuf[2] = {0};
+ u8 u8RdVal = 0;
+
+ au8RegBuf[0] = reg >> 8;
+ au8RegBuf[1] = reg & 0xff;
+
+ if (2 != i2c_master_send(ov5647_data.i2c_client, au8RegBuf, 2)) {
+ pr_err("%s:write reg error:reg=%x\n",
+ __func__, reg);
+ return -1;
+ }
+
+ if (1 != i2c_master_recv(ov5647_data.i2c_client, &u8RdVal, 1)) {
+ pr_err("%s:read reg error:reg=%x,val=%x\n",
+ __func__, reg, u8RdVal);
+ return -1;
+ }
+
+ *val = u8RdVal;
+
+ return u8RdVal;
+}
+
+/* index: index of otp group. (0, 1, 2)
+ * return:
+ * 0, group index is empty
+ * 1, group index has invalid data
+ * 2, group index has valid data */
+static int ov5647_check_otp(int index)
+{
+ int i;
+ int address;
+ u8 temp;
+
+ /* read otp into buffer */
+ ov5647_write_reg(0x3d21, 0x01);
+ msleep(20);
+ address = 0x3d05 + index * 9;
+ temp = ov5647_read_reg(address, &temp);
+
+ /* disable otp read */
+ ov5647_write_reg(0x3d21, 0x00);
+
+ /* clear otp buffer */
+ for (i = 0; i < 32; i++)
+ ov5647_write_reg(0x3d00 + i, 0x00);
+
+ if (!temp)
+ return 0;
+ else if ((!(temp & 0x80)) && (temp & 0x7f))
+ return 2;
+ else
+ return 1;
+}
+
+/* index: index of otp group. (0, 1, 2)
+ * return: 0 */
+static int ov5647_read_otp(int index, struct otp_struct *otp_ptr)
+{
+ int i;
+ int address;
+ u8 temp;
+
+ /* read otp into buffer */
+ ov5647_write_reg(0x3d21, 0x01);
+ msleep(2);
+ address = 0x3d05 + index * 9;
+ temp = ov5647_read_reg(address, &temp);
+ (*otp_ptr).customer_id = temp & 0x7f;
+
+ (*otp_ptr).module_integrator_id = ov5647_read_reg(address, &temp);
+ (*otp_ptr).lens_id = ov5647_read_reg(address + 1, &temp);
+ (*otp_ptr).rg_ratio = ov5647_read_reg(address + 2, &temp);
+ (*otp_ptr).bg_ratio = ov5647_read_reg(address + 3, &temp);
+ (*otp_ptr).user_data[0] = ov5647_read_reg(address + 4, &temp);
+ (*otp_ptr).user_data[1] = ov5647_read_reg(address + 5, &temp);
+ (*otp_ptr).user_data[2] = ov5647_read_reg(address + 6, &temp);
+ (*otp_ptr).light_rg = ov5647_read_reg(address + 7, &temp);
+ (*otp_ptr).light_bg = ov5647_read_reg(address + 8, &temp);
+
+ /* disable otp read */
+ ov5647_write_reg(0x3d21, 0x00);
+
+ /* clear otp buffer */
+ for (i = 0; i < 32; i++)
+ ov5647_write_reg(0x3d00 + i, 0x00);
+
+ return 0;
+}
+
+/* R_gain, sensor red gain of AWB, 0x400 =1
+ * G_gain, sensor green gain of AWB, 0x400 =1
+ * B_gain, sensor blue gain of AWB, 0x400 =1
+ * return 0 */
+static int ov5647_update_awb_gain(int R_gain, int G_gain, int B_gain)
+{
+ if (R_gain > 0x400) {
+ ov5647_write_reg(0x5186, R_gain >> 8);
+ ov5647_write_reg(0x5187, R_gain & 0x00ff);
+ }
+ if (G_gain > 0x400) {
+ ov5647_write_reg(0x5188, G_gain >> 8);
+ ov5647_write_reg(0x5189, G_gain & 0x00ff);
+ }
+ if (B_gain > 0x400) {
+ ov5647_write_reg(0x518a, B_gain >> 8);
+ ov5647_write_reg(0x518b, B_gain & 0x00ff);
+ }
+
+ return 0;
+}
+
+/* call this function after OV5647 initialization
+ * return value:
+ * 0 update success
+ * 1 no OTP */
+static int ov5647_update_otp(void)
+{
+ struct otp_struct current_otp;
+ int i;
+ int otp_index;
+ int temp;
+ int R_gain, G_gain, B_gain, G_gain_R, G_gain_B;
+ int rg, bg;
+
+ /* R/G and B/G of current camera module is read out from sensor OTP
+ * check first OTP with valid data */
+ for (i = 0; i < 3; i++) {
+ temp = ov5647_check_otp(i);
+ if (temp == 2) {
+ otp_index = i;
+ break;
+ }
+ }
+ if (i == 3) {
+ /* no valid wb OTP data */
+ printk(KERN_WARNING "No valid wb otp data\n");
+ return 1;
+ }
+
+ ov5647_read_otp(otp_index, &current_otp);
+ if (current_otp.light_rg == 0)
+ rg = current_otp.rg_ratio;
+ else
+ rg = current_otp.rg_ratio * (current_otp.light_rg + 128) / 256;
+
+ if (current_otp.light_bg == 0)
+ bg = current_otp.bg_ratio;
+ else
+ bg = current_otp.bg_ratio * (current_otp.light_bg + 128) / 256;
+
+ /* calculate G gain
+ * 0x400 = 1x gain */
+ if (bg < BG_Ratio_Typical) {
+ if (rg < RG_Ratio_Typical) {
+ /* current_otp.bg_ratio < BG_Ratio_typical &&
+ * current_otp.rg_ratio < RG_Ratio_typical */
+ G_gain = 0x400;
+ B_gain = 0x400 * BG_Ratio_Typical / bg;
+ R_gain = 0x400 * RG_Ratio_Typical / rg;
+ } else {
+ /* current_otp.bg_ratio < BG_Ratio_typical &&
+ * current_otp.rg_ratio >= RG_Ratio_typical */
+ R_gain = 0x400;
+ G_gain = 0x400 * rg / RG_Ratio_Typical;
+ B_gain = G_gain * BG_Ratio_Typical / bg;
+ }
+ } else {
+ if (rg < RG_Ratio_Typical) {
+ /* current_otp.bg_ratio >= BG_Ratio_typical &&
+ * current_otp.rg_ratio < RG_Ratio_typical */
+ B_gain = 0x400;
+ G_gain = 0x400 * bg / BG_Ratio_Typical;
+ R_gain = G_gain * RG_Ratio_Typical / rg;
+ } else {
+ /* current_otp.bg_ratio >= BG_Ratio_typical &&
+ * current_otp.rg_ratio >= RG_Ratio_typical */
+ G_gain_B = 0x400 * bg / BG_Ratio_Typical;
+ G_gain_R = 0x400 * rg / RG_Ratio_Typical;
+ if (G_gain_B > G_gain_R) {
+ B_gain = 0x400;
+ G_gain = G_gain_B;
+ R_gain = G_gain * RG_Ratio_Typical / rg;
+ } else {
+ R_gain = 0x400;
+ G_gain = G_gain_R;
+ B_gain = G_gain * BG_Ratio_Typical / bg;
+ }
+ }
+ }
+ ov5647_update_awb_gain(R_gain, G_gain, B_gain);
+ return 0;
+}
+
+static void ov5647_stream_on(void)
+{
+ ov5647_write_reg(0x4202, 0x00);
+}
+
+static void ov5647_stream_off(void)
+{
+ ov5647_write_reg(0x4202, 0x0f);
+ /* both clock and data lane in LP00 */
+ ov5647_write_reg(0x0100, 0x00);
+}
+
+static int ov5647_get_sysclk(void)
+{
+ /* calculate sysclk */
+ int xvclk = ov5647_data.mclk / 10000;
+ int sysclk, temp1, temp2;
+ int pre_div02x, div_cnt7b, sdiv0, pll_rdiv, bit_div2x, sclk_div, VCO;
+ int pre_div02x_map[] = {2, 2, 4, 6, 8, 3, 12, 5, 16, 2, 2, 2, 2, 2, 2, 2};
+ int sdiv0_map[] = {16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ int pll_rdiv_map[] = {1, 2};
+ int bit_div2x_map[] = {2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 5, 2, 2, 2, 2, 2};
+ int sclk_div_map[] = {1, 2, 4, 1};
+ u8 temp;
+
+ temp1 = ov5647_read_reg(0x3037, &temp);
+ temp2 = temp1 & 0x0f;
+ pre_div02x = pre_div02x_map[temp2];
+ temp2 = (temp1 >> 4) & 0x01;
+ pll_rdiv = pll_rdiv_map[temp2];
+ temp1 = ov5647_read_reg(0x3036, &temp);
+
+ div_cnt7b = temp1;
+
+ VCO = xvclk * 2 / pre_div02x * div_cnt7b;
+ temp1 = ov5647_read_reg(0x3035, &temp);
+ temp2 = temp1 >> 4;
+ sdiv0 = sdiv0_map[temp2];
+ temp1 = ov5647_read_reg(0x3034, &temp);
+ temp2 = temp1 & 0x0f;
+ bit_div2x = bit_div2x_map[temp2];
+ temp1 = ov5647_read_reg(0x3106, &temp);
+ temp2 = (temp1 >> 2) & 0x03;
+ sclk_div = sclk_div_map[temp2];
+ sysclk = VCO * 2 / sdiv0 / pll_rdiv / bit_div2x / sclk_div;
+ return sysclk;
+}
+
+static void ov5647_set_night_mode(void)
+{
+ /* read HTS from register settings */
+ u8 mode;
+
+ ov5647_read_reg(0x3a00, &mode);
+ mode &= 0xfb;
+ ov5647_write_reg(0x3a00, mode);
+}
+
+static int ov5647_get_HTS(void)
+{
+ /* read HTS from register settings */
+ int HTS;
+ u8 temp;
+
+ HTS = ov5647_read_reg(0x380c, &temp);
+ HTS = (HTS << 8) + ov5647_read_reg(0x380d, &temp);
+
+ return HTS;
+}
+
+static int ov5647_soft_reset(void)
+{
+ /* soft reset ov5647 */
+
+ ov5647_write_reg(0x0103, 0x1);
+ msleep(5);
+
+ return 0;
+}
+
+static int ov5647_get_VTS(void)
+{
+ /* read VTS from register settings */
+ int VTS;
+ u8 temp;
+
+ /* total vertical size[15:8] high byte */
+ VTS = ov5647_read_reg(0x380e, &temp);
+
+ VTS = (VTS << 8) + ov5647_read_reg(0x380f, &temp);
+
+ return VTS;
+}
+
+static int ov5647_set_VTS(int VTS)
+{
+ /* write VTS to registers */
+ int temp;
+
+ temp = VTS & 0xff;
+ ov5647_write_reg(0x380f, temp);
+
+ temp = VTS >> 8;
+ ov5647_write_reg(0x380e, temp);
+
+ return 0;
+}
+
+static int ov5647_get_shutter(void)
+{
+ /* read shutter, in number of line period */
+ int shutter;
+ u8 temp;
+
+ shutter = (ov5647_read_reg(0x03500, &temp) & 0x0f);
+ shutter = (shutter << 8) + ov5647_read_reg(0x3501, &temp);
+ shutter = (shutter << 4) + (ov5647_read_reg(0x3502, &temp)>>4);
+
+ return shutter;
+}
+
+static int ov5647_set_shutter(int shutter)
+{
+ /* write shutter, in number of line period */
+ int temp;
+
+ shutter = shutter & 0xffff;
+
+ temp = shutter & 0x0f;
+ temp = temp << 4;
+ ov5647_write_reg(0x3502, temp);
+
+ temp = shutter & 0xfff;
+ temp = temp >> 4;
+ ov5647_write_reg(0x3501, temp);
+
+ temp = shutter >> 12;
+ ov5647_write_reg(0x3500, temp);
+
+ return 0;
+}
+
+static int ov5647_get_gain16(void)
+{
+ /* read gain, 16 = 1x */
+ int gain16;
+ u8 temp;
+
+ gain16 = ov5647_read_reg(0x350a, &temp) & 0x03;
+ gain16 = (gain16 << 8) + ov5647_read_reg(0x350b, &temp);
+
+ return gain16;
+}
+
+static int ov5647_set_gain16(int gain16)
+{
+ /* write gain, 16 = 1x */
+ u8 temp;
+ gain16 = gain16 & 0x3ff;
+
+ temp = gain16 & 0xff;
+ ov5647_write_reg(0x350b, temp);
+
+ temp = gain16 >> 8;
+ ov5647_write_reg(0x350a, temp);
+
+ return 0;
+}
+
+static int ov5647_get_light_freq(void)
+{
+ /* get banding filter value */
+ int temp, temp1, light_freq = 0;
+ u8 tmp;
+
+ temp = ov5647_read_reg(0x3c01, &tmp);
+
+ if (temp & 0x80) {
+ /* manual */
+ temp1 = ov5647_read_reg(0x3c00, &tmp);
+ if (temp1 & 0x04) {
+ /* 50Hz */
+ light_freq = 50;
+ } else {
+ /* 60Hz */
+ light_freq = 60;
+ }
+ } else {
+ /* auto */
+ temp1 = ov5647_read_reg(0x3c0c, &tmp);
+ if (temp1 & 0x01) {
+ /* 50Hz */
+ light_freq = 50;
+ } else {
+ /* 60Hz */
+ }
+ }
+ return light_freq;
+}
+
+static void ov5647_set_bandingfilter(void)
+{
+ int prev_VTS;
+ int band_step60, max_band60, band_step50, max_band50;
+
+ /* read preview PCLK */
+ prev_sysclk = ov5647_get_sysclk();
+ /* read preview HTS */
+ prev_HTS = ov5647_get_HTS();
+
+ /* read preview VTS */
+ prev_VTS = ov5647_get_VTS();
+
+ /* calculate banding filter */
+ /* 60Hz */
+ band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
+ ov5647_write_reg(0x3a0a, (band_step60 >> 8));
+ ov5647_write_reg(0x3a0b, (band_step60 & 0xff));
+
+ max_band60 = (int)((prev_VTS-4)/band_step60);
+ ov5647_write_reg(0x3a0d, max_band60);
+
+ /* 50Hz */
+ band_step50 = prev_sysclk * 100/prev_HTS;
+ ov5647_write_reg(0x3a08, (band_step50 >> 8));
+ ov5647_write_reg(0x3a09, (band_step50 & 0xff));
+
+ max_band50 = (int)((prev_VTS-4)/band_step50);
+ ov5647_write_reg(0x3a0e, max_band50);
+}
+
+static int ov5647_set_AE_target(int target)
+{
+ /* stable in high */
+ int fast_high, fast_low;
+ AE_low = target * 23 / 25; /* 0.92 */
+ AE_high = target * 27 / 25; /* 1.08 */
+
+ fast_high = AE_high<<1;
+ if (fast_high > 255)
+ fast_high = 255;
+
+ fast_low = AE_low >> 1;
+
+ ov5647_write_reg(0x3a0f, AE_high);
+ ov5647_write_reg(0x3a10, AE_low);
+ ov5647_write_reg(0x3a1b, AE_high);
+ ov5647_write_reg(0x3a1e, AE_low);
+ ov5647_write_reg(0x3a11, fast_high);
+ ov5647_write_reg(0x3a1f, fast_low);
+
+ return 0;
+}
+
+static void ov5647_turn_on_AE_AG(int enable)
+{
+ u8 ae_ag_ctrl;
+
+ ov5647_read_reg(0x3503, &ae_ag_ctrl);
+ if (enable) {
+ /* turn on auto AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
+ } else {
+ /* turn off AE/AG */
+ ae_ag_ctrl = ae_ag_ctrl | 0x03;
+ }
+ ov5647_write_reg(0x3503, ae_ag_ctrl);
+}
+
+static void ov5647_set_virtual_channel(int channel)
+{
+ u8 channel_id;
+
+ ov5647_read_reg(0x4814, &channel_id);
+ channel_id &= ~(3 << 6);
+ ov5647_write_reg(0x4814, channel_id | (channel << 6));
+}
+
+/* download ov5647 settings to sensor through i2c */
+static int ov5647_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+{
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u8 Mask = 0;
+ register u8 Val = 0;
+ u8 RegVal = 0;
+ int i, retval = 0;
+
+ for (i = 0; i < ArySize; ++i, ++pModeSetting) {
+ Delay_ms = pModeSetting->u32Delay_ms;
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u8Val;
+ Mask = pModeSetting->u8Mask;
+
+ if (Mask) {
+ retval = ov5647_read_reg(RegAddr, &RegVal);
+ if (retval < 0)
+ goto err;
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = ov5647_write_reg(RegAddr, Val);
+ if (retval < 0)
+ goto err;
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+ }
+err:
+ return retval;
+}
+
+/* sensor changes between scaling and subsampling
+ * go through exposure calcualtion
+ */
+static int ov5647_change_mode_exposure_calc(enum ov5647_frame_rate frame_rate,
+ enum ov5647_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int pre_shutter, pre_gain16;
+ int cap_shutter, cap_gain16;
+ int pre_sysclk, pre_HTS;
+ int cap_sysclk, cap_HTS, cap_VTS;
+ long cap_gain16_shutter;
+ int retval = 0;
+
+ /* check if the input mode and frame rate is valid */
+ pModeSetting =
+ ov5647_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5647_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5647_data.pix.width =
+ ov5647_mode_info_data[frame_rate][mode].width;
+ ov5647_data.pix.height =
+ ov5647_mode_info_data[frame_rate][mode].height;
+
+ if (ov5647_data.pix.width == 0 || ov5647_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ ov5647_stream_off();
+
+ /* turn off night mode for capture */
+ ov5647_set_night_mode();
+
+ pre_shutter = ov5647_get_shutter();
+ pre_gain16 = ov5647_get_gain16();
+ pre_HTS = ov5647_get_HTS();
+ pre_sysclk = ov5647_get_sysclk();
+
+ /* Write capture setting */
+ retval = ov5647_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ /* read capture VTS */
+ cap_VTS = ov5647_get_VTS();
+ cap_HTS = ov5647_get_HTS();
+ cap_sysclk = ov5647_get_sysclk();
+
+ /* calculate capture shutter/gain16 */
+ cap_shutter = pre_shutter * cap_sysclk/pre_sysclk * pre_HTS / cap_HTS;
+
+ if (cap_shutter < 16) {
+ cap_gain16_shutter = pre_shutter * pre_gain16 *
+ cap_sysclk / pre_sysclk * pre_HTS / cap_HTS;
+ cap_shutter = ((int)(cap_gain16_shutter / 16));
+ if (cap_shutter < 1)
+ cap_shutter = 1;
+ cap_gain16 = ((int)(cap_gain16_shutter / cap_shutter));
+ if (cap_gain16 < 16)
+ cap_gain16 = 16;
+ } else
+ cap_gain16 = pre_gain16;
+
+ /* gain to shutter */
+ while ((cap_gain16 > 32) &&
+ (cap_shutter < ((int)((cap_VTS - 4) / 2)))) {
+ cap_gain16 = cap_gain16 / 2;
+ cap_shutter = cap_shutter * 2;
+ }
+ /* write capture gain */
+ ov5647_set_gain16(cap_gain16);
+
+ /* write capture shutter */
+ if (cap_shutter > (cap_VTS - 4)) {
+ cap_VTS = cap_shutter + 4;
+ ov5647_set_VTS(cap_VTS);
+ }
+ ov5647_set_shutter(cap_shutter);
+
+err:
+ return retval;
+}
+
+/* if sensor changes inside scaling or subsampling
+ * change mode directly
+ * */
+static int ov5647_change_mode_direct(enum ov5647_frame_rate frame_rate,
+ enum ov5647_mode mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+
+ /* check if the input mode and frame rate is valid */
+ pModeSetting =
+ ov5647_mode_info_data[frame_rate][mode].init_data_ptr;
+ ArySize =
+ ov5647_mode_info_data[frame_rate][mode].init_data_size;
+
+ ov5647_data.pix.width =
+ ov5647_mode_info_data[frame_rate][mode].width;
+ ov5647_data.pix.height =
+ ov5647_mode_info_data[frame_rate][mode].height;
+
+ if (ov5647_data.pix.width == 0 || ov5647_data.pix.height == 0 ||
+ pModeSetting == NULL || ArySize == 0)
+ return -EINVAL;
+
+ /* turn off AE/AG */
+ ov5647_turn_on_AE_AG(0);
+
+ ov5647_stream_off();
+
+ /* Write capture setting */
+ retval = ov5647_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+
+ ov5647_turn_on_AE_AG(1);
+
+err:
+ return retval;
+}
+
+static int ov5647_init_mode(enum ov5647_frame_rate frame_rate,
+ enum ov5647_mode mode, enum ov5647_mode orig_mode)
+{
+ struct reg_value *pModeSetting = NULL;
+ s32 ArySize = 0;
+ int retval = 0;
+ u32 msec_wait4stable = 0;
+ enum ov5647_downsize_mode dn_mode, orig_dn_mode;
+
+ if ((mode > ov5647_mode_MAX || mode < ov5647_mode_MIN)
+ && (mode != ov5647_mode_INIT)) {
+ pr_err("Wrong ov5647 mode detected!\n");
+ return -1;
+ }
+
+ dn_mode = ov5647_mode_info_data[frame_rate][mode].dn_mode;
+ orig_dn_mode = ov5647_mode_info_data[frame_rate][orig_mode].dn_mode;
+ if (mode == ov5647_mode_INIT) {
+ ov5647_soft_reset();
+ pModeSetting = ov5647_init_setting;
+ ArySize = ARRAY_SIZE(ov5647_init_setting);
+ retval = ov5647_download_firmware(pModeSetting, ArySize);
+ if (retval < 0)
+ goto err;
+ pModeSetting = ov5647_setting_60fps_VGA_640_480;
+ ArySize = ARRAY_SIZE(ov5647_setting_60fps_VGA_640_480);
+ retval = ov5647_download_firmware(pModeSetting, ArySize);
+
+ ov5647_data.pix.width = 640;
+ ov5647_data.pix.height = 480;
+ } else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
+ (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
+ /* change between subsampling and scaling
+ * go through exposure calucation */
+ retval = ov5647_change_mode_exposure_calc(frame_rate, mode);
+ } else {
+ /* change inside subsampling or scaling
+ * download firmware directly */
+ retval = ov5647_change_mode_direct(frame_rate, mode);
+ }
+
+ if (retval < 0)
+ goto err;
+
+ ov5647_set_AE_target(AE_Target);
+ ov5647_get_light_freq();
+ ov5647_set_bandingfilter();
+ ov5647_set_virtual_channel(ov5647_data.csi);
+
+ /* add delay to wait for sensor stable */
+ if (mode == ov5647_mode_QSXGA_2592_1944) {
+ /* dump the first two frames: 1/7.5*2
+ * the frame rate of QSXGA is 7.5fps */
+ msec_wait4stable = 267;
+ } else if (frame_rate == ov5647_15_fps) {
+ /* dump the first nine frames: 1/15*9 */
+ msec_wait4stable = 600;
+ } else if (frame_rate == ov5647_30_fps) {
+ /* dump the first nine frames: 1/30*9 */
+ msec_wait4stable = 300;
+ }
+ msleep(msec_wait4stable);
+
+err:
+ return retval;
+}
+
+/*!
+ * ov5647_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ov5647_s_power(struct v4l2_subdev *sd, int on)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5647 *sensor = to_ov5647(client);
+
+ if (on && !sensor->on) {
+ if (io_regulator)
+ if (regulator_enable(io_regulator) != 0)
+ return -EIO;
+ if (core_regulator)
+ if (regulator_enable(core_regulator) != 0)
+ return -EIO;
+ if (gpo_regulator)
+ if (regulator_enable(gpo_regulator) != 0)
+ return -EIO;
+ if (analog_regulator)
+ if (regulator_enable(analog_regulator) != 0)
+ return -EIO;
+ } else if (!on && sensor->on) {
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+ if (core_regulator)
+ regulator_disable(core_regulator);
+ if (io_regulator)
+ regulator_disable(io_regulator);
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+ }
+
+ sensor->on = on;
+
+ return 0;
+}
+
+/*!
+ * ov5647_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ov5647_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5647 *sensor = to_ov5647(client);
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ int ret = 0;
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->streamcap.capability;
+ cparm->timeperframe = sensor->streamcap.timeperframe;
+ cparm->capturemode = sensor->streamcap.capturemode;
+ ret = 0;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ov5460_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 sub device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ov5647_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5647 *sensor = to_ov5647(client);
+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5647_frame_rate frame_rate;
+ enum ov5647_mode orig_mode;
+ int ret = 0;
+
+ /* Make sure power on */
+ ov5647_power_down(0);
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ /* Check that the new frame rate is allowed. */
+ if ((timeperframe->numerator == 0) ||
+ (timeperframe->denominator == 0)) {
+ timeperframe->denominator = DEFAULT_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps > MAX_FPS) {
+ timeperframe->denominator = MAX_FPS;
+ timeperframe->numerator = 1;
+ } else if (tgt_fps < MIN_FPS) {
+ timeperframe->denominator = MIN_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ /* Actual frame rate we use */
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5647_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5647_30_fps;
+ else {
+ pr_err(" The camera frame rate is not supported!\n");
+ return -EINVAL;
+ }
+
+ orig_mode = sensor->streamcap.capturemode;
+ ret = ov5647_init_mode(frame_rate,
+ (u32)a->parm.capture.capturemode, orig_mode);
+ if (ret < 0)
+ return ret;
+
+ sensor->streamcap.timeperframe = *timeperframe;
+ sensor->streamcap.capturemode =
+ (u32)a->parm.capture.capturemode;
+
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_debug("type is not " \
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+ a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug("type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int ov5647_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ const struct ov5647_datafmt *fmt = ov5647_find_datafmt(mf->code);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5647 *sensor = to_ov5647(client);
+
+ if (!fmt) {
+ mf->code = ov5647_colour_fmts[0].code;
+ mf->colorspace = ov5647_colour_fmts[0].colorspace;
+ }
+
+ mf->field = V4L2_FIELD_NONE;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
+ sensor->fmt = fmt;
+
+ return 0;
+}
+
+static int ov5647_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ov5647 *sensor = to_ov5647(client);
+ const struct ov5647_datafmt *fmt = sensor->fmt;
+
+ if (format->pad)
+ return -EINVAL;
+
+ mf->code = fmt->code;
+ mf->colorspace = fmt->colorspace;
+ mf->field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+static int ov5647_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->pad || code->index >= ARRAY_SIZE(ov5647_colour_fmts))
+ return -EINVAL;
+
+ code->code = ov5647_colour_fmts[code->index].code;
+ return 0;
+}
+
+/*!
+ * ov5647_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5647_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index > ov5647_mode_MAX)
+ return -EINVAL;
+
+ fse->max_width =
+ max(ov5647_mode_info_data[0][fse->index].width,
+ ov5647_mode_info_data[1][fse->index].width);
+ fse->min_width = fse->max_width;
+ fse->max_height =
+ max(ov5647_mode_info_data[0][fse->index].height,
+ ov5647_mode_info_data[1][fse->index].height);
+ fse->min_height = fse->max_height;
+ return 0;
+}
+
+/*!
+ * ov5647_enum_frameintervals - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ov5647_enum_frameintervals(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ int i, j, count;
+
+ if (fie->index < 0 || fie->index > ov5647_mode_MAX)
+ return -EINVAL;
+
+ if (fie->width == 0 || fie->height == 0 ||
+ fie->code == 0) {
+ pr_warning("Please assign pixel format, width and height.\n");
+ return -EINVAL;
+ }
+
+ fie->interval.numerator = 1;
+
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(ov5647_mode_info_data); i++) {
+ for (j = 0; j < (ov5647_mode_MAX + 1); j++) {
+ if (fie->width == ov5647_mode_info_data[i][j].width
+ && fie->height == ov5647_mode_info_data[i][j].height
+ && ov5647_mode_info_data[i][j].init_data_ptr != NULL) {
+ count++;
+ }
+ if (fie->index == (count - 1)) {
+ fie->interval.denominator =
+ ov5647_framerates[i];
+ return 0;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+/*!
+ * dev_init - V4L2 sensor init
+ * @s: pointer to standard V4L2 device structure
+ *
+ */
+static int init_device(void)
+{
+ u32 tgt_xclk; /* target xclk */
+ u32 tgt_fps; /* target frames per secound */
+ enum ov5647_frame_rate frame_rate;
+ int ret;
+
+ ov5647_data.on = true;
+
+ /* mclk */
+ tgt_xclk = ov5647_data.mclk;
+ tgt_xclk = min(tgt_xclk, (u32)OV5647_XCLK_MAX);
+ tgt_xclk = max(tgt_xclk, (u32)OV5647_XCLK_MIN);
+ ov5647_data.mclk = tgt_xclk;
+
+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
+
+ /* Default camera frame rate is set in probe */
+ tgt_fps = ov5647_data.streamcap.timeperframe.denominator /
+ ov5647_data.streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 15)
+ frame_rate = ov5647_15_fps;
+ else if (tgt_fps == 30)
+ frame_rate = ov5647_30_fps;
+ else
+ return -EINVAL; /* Only support 15fps or 30fps now. */
+
+ ret = ov5647_init_mode(frame_rate, ov5647_mode_INIT, ov5647_mode_INIT);
+
+ ov5647_update_otp();
+ return ret;
+}
+
+static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ if (enable)
+ ov5647_stream_on();
+ else
+ ov5647_stream_off();
+ return 0;
+}
+
+static struct v4l2_subdev_video_ops ov5647_subdev_video_ops = {
+ .g_parm = ov5647_g_parm,
+ .s_parm = ov5647_s_parm,
+ .s_stream = ov5647_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops ov5647_subdev_pad_ops = {
+ .enum_frame_size = ov5647_enum_framesizes,
+ .enum_frame_interval = ov5647_enum_frameintervals,
+ .enum_mbus_code = ov5647_enum_mbus_code,
+ .set_fmt = ov5647_set_fmt,
+ .get_fmt = ov5647_get_fmt,
+};
+
+static struct v4l2_subdev_core_ops ov5647_subdev_core_ops = {
+ .s_power = ov5647_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .g_register = ov5647_get_register,
+ .s_register = ov5647_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5647_subdev_ops = {
+ .core = &ov5647_subdev_core_ops,
+ .video = &ov5647_subdev_video_ops,
+ .pad = &ov5647_subdev_pad_ops,
+};
+
+
+/*!
+ * ov5647 I2C probe function
+ *
+ * @param adapter struct i2c_adapter *
+ * @return Error code indicating success or failure
+ */
+static int ov5647_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+ int retval;
+ u8 chip_id_high, chip_id_low;
+
+ /* ov5647 pinctrl */
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl)) {
+ dev_warn(dev, "no pin available\n");
+ }
+
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio)) {
+ dev_warn(dev, "no sensor pwdn pin available\n");
+ pwn_gpio = -1;
+ } else {
+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5647_mipi_pwdn");
+ if (retval < 0) {
+ dev_warn(dev, "Failed to set power pin\n");
+ return retval;
+ }
+ }
+
+ /* request reset pin */
+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(rst_gpio)) {
+ dev_warn(dev, "no sensor reset pin available\n");
+ rst_gpio = -1;
+ } else {
+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5647_mipi_reset");
+ if (retval < 0) {
+ dev_warn(dev, "Failed to set reset pin\n");
+ return retval;
+ }
+ }
+
+ /* Set initial values for the sensor struct. */
+ memset(&ov5647_data, 0, sizeof(ov5647_data));
+ ov5647_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(ov5647_data.sensor_clk)) {
+ /* assuming clock enabled by default */
+ ov5647_data.sensor_clk = NULL;
+ dev_err(dev, "clock-frequency missing or invalid\n");
+ return PTR_ERR(ov5647_data.sensor_clk);
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk",
+ &(ov5647_data.mclk));
+ if (retval) {
+ dev_err(dev, "mclk missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk_source",
+ (u32 *) &(ov5647_data.mclk_source));
+ if (retval) {
+ dev_err(dev, "mclk_source missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "csi_id",
+ &(ov5647_data.csi));
+ if (retval) {
+ dev_err(dev, "csi id missing or invalid\n");
+ return retval;
+ }
+
+ clk_prepare_enable(ov5647_data.sensor_clk);
+
+ ov5647_data.io_init = ov5647_reset;
+ ov5647_data.i2c_client = client;
+ ov5647_data.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
+ ov5647_data.pix.width = 640;
+ ov5647_data.pix.height = 480;
+ ov5647_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+ V4L2_CAP_TIMEPERFRAME;
+ ov5647_data.streamcap.capturemode = 0;
+ ov5647_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
+ ov5647_data.streamcap.timeperframe.numerator = 1;
+
+ ov5647_regulator_enable(&client->dev);
+
+ ov5647_reset();
+
+ ov5647_power_down(0);
+
+ retval = ov5647_read_reg(OV5647_CHIP_ID_HIGH_BYTE, &chip_id_high);
+ if (retval < 0 || chip_id_high != 0x56) {
+ pr_warning("camera ov5647_mipi is not found\n");
+ clk_disable_unprepare(ov5647_data.sensor_clk);
+ return -ENODEV;
+ }
+ retval = ov5647_read_reg(OV5647_CHIP_ID_LOW_BYTE, &chip_id_low);
+ if (retval < 0 || chip_id_low != 0x47) {
+ pr_warning("camera ov5647_mipi is not found\n");
+ clk_disable_unprepare(ov5647_data.sensor_clk);
+ return -ENODEV;
+ }
+
+ retval = init_device();
+ if (retval < 0) {
+ clk_disable_unprepare(ov5647_data.sensor_clk);
+ pr_warning("camera ov5647 init failed\n");
+ ov5647_power_down(1);
+ return retval;
+ }
+
+ v4l2_i2c_subdev_init(&ov5647_data.subdev, client, &ov5647_subdev_ops);
+
+ ov5647_data.subdev.grp_id = 678;
+ retval = v4l2_async_register_subdev(&ov5647_data.subdev);
+ if (retval < 0)
+ dev_err(&client->dev,
+ "%s--Async register failed, ret=%d\n", __func__, retval);
+
+ ov5647_stream_off();
+ pr_info("camera ov5647_mipi is found\n");
+ return retval;
+}
+
+/*!
+ * ov5647 I2C detach function
+ *
+ * @param client struct i2c_client *
+ * @return Error code indicating success or failure
+ */
+static int ov5647_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+ v4l2_async_unregister_subdev(sd);
+
+ clk_disable_unprepare(ov5647_data.sensor_clk);
+
+ ov5647_power_down(1);
+
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+
+ if (core_regulator)
+ regulator_disable(core_regulator);
+
+ if (io_regulator)
+ regulator_disable(io_regulator);
+
+ return 0;
+}
+
+module_i2c_driver(ov5647_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("OV5647 MIPI Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c
index 271f725b17e8..1ed7a15dd360 100644
--- a/drivers/media/radio/radio-si476x.c
+++ b/drivers/media/radio/radio-si476x.c
@@ -775,7 +775,8 @@ static int si476x_radio_s_hw_freq_seek(struct file *file, void *priv,
rangelow = si476x_to_v4l2(radio->core, rangelow);
else
goto unlock;
- }
+ } else
+ rangelow = seek->rangelow;
if (!seek->rangehigh) {
err = regmap_read(radio->core->regmap,
SI476X_PROP_SEEK_BAND_TOP,
@@ -784,7 +785,8 @@ static int si476x_radio_s_hw_freq_seek(struct file *file, void *priv,
rangehigh = si476x_to_v4l2(radio->core, rangehigh);
else
goto unlock;
- }
+ } else
+ rangehigh = seek->rangehigh;
if (rangelow > rangehigh) {
err = -EINVAL;
@@ -1008,6 +1010,14 @@ static int si476x_radio_s_ctrl(struct v4l2_ctrl *ctrl)
}
break;
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->val)
+ retval = regmap_write(radio->core->regmap,
+ SI476X_PROP_AUDIO_MUTE, 3);
+ else
+ retval = regmap_write(radio->core->regmap,
+ SI476X_PROP_AUDIO_MUTE, 0);
+ break;
default:
retval = -EINVAL;
break;
@@ -1527,6 +1537,16 @@ static int si476x_radio_probe(struct platform_device *pdev)
goto exit;
}
+ ctrl = v4l2_ctrl_new_std(&radio->ctrl_handler, &si476x_ctrl_ops,
+ V4L2_CID_AUDIO_MUTE,
+ 0, 1, 1, 0);
+ rval = radio->ctrl_handler.error;
+ if (ctrl == NULL && rval) {
+ dev_err(&pdev->dev, "Could not initialize V4L2_CID_AUDIO_MUTE control %d\n",
+ rval);
+ goto exit;
+ }
+
if (si476x_core_has_diversity(radio->core)) {
si476x_ctrls[SI476X_IDX_DIVERSITY_MODE].def =
si476x_phase_diversity_mode_to_idx(radio->core->diversity_mode);
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 5bada202b2d3..76996b516406 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -220,7 +220,14 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
v4l2_async_cleanup(sd);
/* If we handled USB devices, we'd have to lock the parent too */
+ /*
+ * If anyone calls v4l2_async_notifier_unregister() recursively from
+ * device_release_driver(), code will deadlock at list_lock,
+ * so unlock list_lock when device_release_driver() called.
+ */
+ mutex_unlock(&list_lock);
device_release_driver(d);
+ mutex_lock(&list_lock);
if (notifier->unbind)
notifier->unbind(notifier, sd, sd->asd);
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 8be561ab2615..206cff6b0c97 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -360,6 +360,34 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
if (lock)
mutex_unlock(lock);
+ } else if (vdev->fops->ioctl) {
+ /* This code path is a replacement for the BKL. It is a major
+ * hack but it will have to do for those drivers that are not
+ * yet converted to use unlocked_ioctl.
+ *
+ * All drivers implement struct v4l2_device, so we use the
+ * lock defined there to serialize the ioctls.
+ *
+ * However, if the driver sleeps, then it blocks all ioctls
+ * since the lock is still held. This is very common for
+ * VIDIOC_DQBUF since that normally waits for a frame to arrive.
+ * As a result any other ioctl calls will proceed very, very
+ * slowly since each call will have to wait for the VIDIOC_QBUF
+ * to finish. Things that should take 0.01s may now take 10-20
+ * seconds.
+ *
+ * The workaround is to *not* take the lock for VIDIOC_DQBUF.
+ * This actually works OK for videobuf-based drivers, since
+ * videobuf will take its own internal lock.
+ */
+ struct mutex *m = &vdev->v4l2_dev->ioctl_lock;
+
+ if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m))
+ return -ERESTARTSYS;
+ if (video_is_registered(vdev))
+ ret = vdev->fops->ioctl(filp, cmd, arg);
+ if (cmd != VIDIOC_DQBUF)
+ mutex_unlock(m);
} else
ret = -ENOTTY;
@@ -567,6 +595,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
set_bit(_IOC_NR(VIDIOC_DBG_G_REGISTER), valid_ioctls);
set_bit(_IOC_NR(VIDIOC_DBG_S_REGISTER), valid_ioctls);
#endif
+ SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident);
/* yes, really vidioc_subscribe_event */
SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event);
SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event);
diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
index 62bbed76dbbc..e4d15ee44a6d 100644
--- a/drivers/media/v4l2-core/v4l2-device.c
+++ b/drivers/media/v4l2-core/v4l2-device.c
@@ -37,6 +37,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
INIT_LIST_HEAD(&v4l2_dev->subdevs);
spin_lock_init(&v4l2_dev->lock);
+ mutex_init(&v4l2_dev->ioctl_lock);
v4l2_prio_init(&v4l2_dev->prio);
kref_init(&v4l2_dev->ref);
get_device(dev);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 4510e8a37244..74f657b050be 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -28,6 +28,8 @@
#include <media/v4l2-device.h>
#include <media/videobuf2-v4l2.h>
#include <media/v4l2-mc.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/videobuf2-core.h>
#include <trace/events/v4l2.h>
@@ -653,6 +655,20 @@ static void v4l_print_decoder_cmd(const void *arg, bool write_only)
pr_info("pts=%llu\n", p->stop.pts);
}
+static void v4l_print_dbg_chip_ident(const void *arg, bool write_only)
+{
+ const struct v4l2_dbg_chip_ident *p = arg;
+
+ pr_cont("type=%u, ", p->match.type);
+ if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
+ pr_cont("name=%.*s, ",
+ (int)sizeof(p->match.name), p->match.name);
+ else
+ pr_cont("addr=%u, ", p->match.addr);
+ pr_cont("chip_ident=%u, revision=0x%x\n",
+ p->ident, p->revision);
+}
+
static void v4l_print_dbg_chip_info(const void *arg, bool write_only)
{
const struct v4l2_dbg_chip_info *p = arg;
@@ -1288,9 +1304,12 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_SE401: descr = "GSPCA SE401"; break;
case V4L2_PIX_FMT_S5C_UYVY_JPG: descr = "S5C73MX interleaved UYVY/JPEG"; break;
default:
- WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat);
- if (fmt->description[0])
+ if (!fmt->description[0])
+ WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat);
+ else {
+ pr_debug("Custom device pixelformat 0x%08x '%s'\n", fmt->pixelformat, fmt->description);
return;
+ }
flags = 0;
snprintf(fmt->description, sz, "%c%c%c%c%s",
(char)(fmt->pixelformat & 0x7f),
@@ -2312,6 +2331,18 @@ static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops,
#endif
}
+static int v4l_dbg_g_chip_ident(const struct v4l2_ioctl_ops *ops,
+ struct file *file, void *fh, void *arg)
+{
+ struct v4l2_dbg_chip_ident *p = arg;
+
+ p->ident = V4L2_IDENT_NONE;
+ p->revision = 0;
+ if (p->match.type == V4L2_CHIP_MATCH_SUBDEV)
+ return -EINVAL;
+ return ops->vidioc_g_chip_ident(file, fh, p);
+}
+
static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
@@ -2566,6 +2597,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0),
IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0),
IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0),
+ IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_IDENT, v4l_dbg_g_chip_ident, v4l_print_dbg_chip_ident, 0),
IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO),
IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_dv_timings, bt.flags)),
IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0),
diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c
index def84753c4c3..793a281d0dc2 100644
--- a/drivers/media/v4l2-core/videobuf-core.c
+++ b/drivers/media/v4l2-core/videobuf-core.c
@@ -594,6 +594,13 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b)
buf->baddr != b->m.userptr)
q->ops->buf_release(q, buf);
buf->baddr = b->m.userptr;
+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
+ || q->type == V4L2_BUF_TYPE_VBI_OUTPUT
+ || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
+ || q->type == V4L2_BUF_TYPE_SDR_OUTPUT) {
+ buf->field = b->field;
+ buf->ts = b->timestamp;
+ }
break;
case V4L2_MEMORY_OVERLAY:
buf->boff = b->m.offset;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c6df6442ba2b..d54271959669 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -335,6 +335,27 @@ config MFD_MX25_TSADC
i.MX25 processors. They consist of a conversion queue for general
purpose ADC and a queue for Touchscreens.
+config MFD_MXC_HDMI
+ tristate "Freescale HDMI Core"
+ select MFD_CORE
+ help
+ This is the core driver for the Freescale i.MX6 on-chip HDMI.
+ This MFD driver connects with the video and audio drivers for HDMI.
+
+config MFD_PF1550
+ tristate "Freescale Semiconductor PF1550 PMIC Support"
+ depends on I2C=y
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ Say yes here to add support for Freescale Semiconductor PF1550.
+ This is a companion Power Management IC with regulators, ONKEY,
+ and charger control on chip.
+ This driver provides common support for accessing the device;
+ additional drivers must be enabled in order to use the functionality
+ of the device.
+
config MFD_HI6421_PMIC
tristate "HiSilicon Hi6421 PMU/Codec IC"
depends on OF
@@ -560,6 +581,14 @@ config MFD_MAX14577
additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_MAX17135
+ tristate "Maxim MAX17135 EPD PMIC core"
+ depends on I2C
+
+ help
+ This is the MAX17135 PMIC support. It includes
+ core support for communication with the MAX17135 chip.
+
config MFD_MAX77620
bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support"
depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9834e669d985..8ce82586c7b7 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -94,6 +94,8 @@ obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
+obj-$(CONFIG_MFD_PF1550) += pf1550.o
+
obj-$(CONFIG_MFD_CORE) += mfd-core.o
obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o
@@ -132,6 +134,7 @@ obj-$(CONFIG_MFD_DA9063) += da9063.o
obj-$(CONFIG_MFD_DA9150) += da9150-core.o
obj-$(CONFIG_MFD_MAX14577) += max14577.o
+obj-$(CONFIG_MFD_MAX17135) += max17135-core.o
obj-$(CONFIG_MFD_MAX77620) += max77620.o
obj-$(CONFIG_MFD_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
@@ -204,6 +207,7 @@ obj-$(CONFIG_MFD_HI655X_PMIC) += hi655x-pmic.o
obj-$(CONFIG_MFD_DLN2) += dln2.o
obj-$(CONFIG_MFD_RT5033) += rt5033.o
obj-$(CONFIG_MFD_SKY81452) += sky81452.o
+obj-$(CONFIG_MFD_MXC_HDMI) += mxc-hdmi-core.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o
diff --git a/drivers/mfd/max17135-core.c b/drivers/mfd/max17135-core.c
new file mode 100644
index 000000000000..f663f8068067
--- /dev/null
+++ b/drivers/mfd/max17135-core.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2010-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*!
+ * @file pmic/core/max17135.c
+ * @brief This file contains MAX17135 specific PMIC code. This implementaion
+ * may differ for each PMIC chip.
+ *
+ * @ingroup PMIC_CORE
+ */
+
+/*
+ * Includes
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/pmic_status.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max17135.h>
+#include <asm/mach-types.h>
+
+static int max17135_detect(struct i2c_client *client,
+ struct i2c_board_info *info);
+struct i2c_client *max17135_client;
+static struct regulator *gpio_regulator;
+
+static struct mfd_cell max17135_devs[] = {
+ { .name = "max17135-pmic", },
+ { .name = "max17135-sns", },
+};
+
+static const unsigned short normal_i2c[] = {0x48, I2C_CLIENT_END};
+
+int max17135_reg_read(int reg_num, unsigned int *reg_val)
+{
+ int result;
+
+ if (max17135_client == NULL)
+ return PMIC_ERROR;
+
+ if ((reg_num == REG_MAX17135_EXT_TEMP) ||
+ (reg_num == REG_MAX17135_INT_TEMP)) {
+ result = i2c_smbus_read_word_data(max17135_client, reg_num);
+ if (result < 0) {
+ dev_err(&max17135_client->dev,
+ "Unable to read MAX17135 register via I2C\n");
+ return PMIC_ERROR;
+ }
+ /* Swap bytes for dword read */
+ result = (result >> 8) | ((result & 0xFF) << 8);
+ } else {
+ result = i2c_smbus_read_byte_data(max17135_client, reg_num);
+ if (result < 0) {
+ dev_err(&max17135_client->dev,
+ "Unable to read MAX17135 register via I2C\n");
+ return PMIC_ERROR;
+ }
+ }
+
+ *reg_val = result;
+ return PMIC_SUCCESS;
+}
+
+int max17135_reg_write(int reg_num, const unsigned int reg_val)
+{
+ int result;
+
+ if (max17135_client == NULL)
+ return PMIC_ERROR;
+
+ result = i2c_smbus_write_byte_data(max17135_client, reg_num, reg_val);
+ if (result < 0) {
+ dev_err(&max17135_client->dev,
+ "Unable to write MAX17135 register via I2C\n");
+ return PMIC_ERROR;
+ }
+
+ return PMIC_SUCCESS;
+}
+
+#ifdef CONFIG_OF
+static struct max17135_platform_data *max17135_i2c_parse_dt_pdata(
+ struct device *dev)
+{
+ struct max17135_platform_data *pdata;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "could not allocate memory for pdata\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return pdata;
+}
+#else
+static struct max17135_platform_data *max17135_i2c_parse_dt_pdata(
+ struct device *dev)
+{
+ return NULL;
+}
+#endif /* !CONFIG_OF */
+
+static int max17135_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max17135 *max17135;
+ struct max17135_platform_data *pdata = client->dev.platform_data;
+ struct device_node *np = client->dev.of_node;
+ int ret = 0;
+
+ if (!np)
+ return -ENODEV;
+
+ gpio_regulator = devm_regulator_get(&client->dev, "SENSOR");
+ if (!IS_ERR(gpio_regulator)) {
+ ret = regulator_enable(gpio_regulator);
+ if (ret) {
+ dev_err(&client->dev, "gpio set voltage error\n");
+ return ret;
+ }
+ }
+
+ /* Create the PMIC data structure */
+ max17135 = kzalloc(sizeof(struct max17135), GFP_KERNEL);
+ if (max17135 == NULL)
+ return -ENOMEM;
+
+ /* Initialize the PMIC data structure */
+ i2c_set_clientdata(client, max17135);
+ max17135->dev = &client->dev;
+ max17135->i2c_client = client;
+
+ max17135_client = client;
+ ret = max17135_detect(client, NULL);
+ if (ret)
+ goto err1;
+
+ mfd_add_devices(max17135->dev, -1, max17135_devs,
+ ARRAY_SIZE(max17135_devs),
+ NULL, 0, NULL);
+
+ if (max17135->dev->of_node) {
+ pdata = max17135_i2c_parse_dt_pdata(max17135->dev);
+ if (IS_ERR(pdata)) {
+ ret = PTR_ERR(pdata);
+ goto err2;
+ }
+
+ }
+ max17135->pdata = pdata;
+
+ dev_info(&client->dev, "PMIC MAX17135 for eInk display\n");
+
+ return ret;
+err2:
+ mfd_remove_devices(max17135->dev);
+err1:
+ kfree(max17135);
+
+ return ret;
+}
+
+
+static int max17135_remove(struct i2c_client *i2c)
+{
+ struct max17135 *max17135 = i2c_get_clientdata(i2c);
+
+ mfd_remove_devices(max17135->dev);
+ return 0;
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max17135_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ u8 chip_rev, chip_id;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ /* detection */
+ if (i2c_smbus_read_byte_data(client,
+ REG_MAX17135_PRODUCT_REV) != 0) {
+ dev_err(&adapter->dev,
+ "Max17135 PMIC not found!\n");
+ return -ENODEV;
+ }
+
+ /* identification */
+ chip_rev = i2c_smbus_read_byte_data(client,
+ REG_MAX17135_PRODUCT_REV);
+ chip_id = i2c_smbus_read_byte_data(client,
+ REG_MAX17135_PRODUCT_ID);
+
+ if (chip_rev != 0x00 || chip_id != 0x4D) { /* identification failed */
+ dev_info(&adapter->dev,
+ "Unsupported chip (man_id=0x%02X, "
+ "chip_id=0x%02X).\n", chip_rev, chip_id);
+ return -ENODEV;
+ }
+
+ if (info)
+ strlcpy(info->type, "max17135_sensor", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static const struct i2c_device_id max17135_id[] = {
+ { "max17135", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max17135_id);
+
+static const struct of_device_id max17135_dt_ids[] = {
+ {
+ .compatible = "maxim,max17135",
+ .data = (void *) &max17135_id[0],
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, max17135_dt_ids);
+
+
+static struct i2c_driver max17135_driver = {
+ .driver = {
+ .name = "max17135",
+ .owner = THIS_MODULE,
+ .of_match_table = max17135_dt_ids,
+ },
+ .probe = max17135_probe,
+ .remove = max17135_remove,
+ .id_table = max17135_id,
+ .detect = max17135_detect,
+ .address_list = &normal_i2c[0],
+};
+
+static int __init max17135_init(void)
+{
+ return i2c_add_driver(&max17135_driver);
+}
+
+static void __exit max17135_exit(void)
+{
+ i2c_del_driver(&max17135_driver);
+}
+
+/*
+ * Module entry points
+ */
+subsys_initcall(max17135_init);
+module_exit(max17135_exit);
diff --git a/drivers/mfd/mxc-hdmi-core.c b/drivers/mfd/mxc-hdmi-core.c
new file mode 100644
index 000000000000..6435b3d7fd60
--- /dev/null
+++ b/drivers/mfd/mxc-hdmi-core.c
@@ -0,0 +1,821 @@
+/*
+ * Copyright (C) 2011-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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <asm/mach-types.h>
+
+#include <video/mxc_hdmi.h>
+#include <linux/ipu-v3.h>
+#include <video/mxc_edid.h>
+#include "../mxc/ipu3/ipu_prv.h"
+#include <linux/mfd/mxc-hdmi-core.h>
+#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+
+struct mxc_hdmi_data {
+ struct platform_device *pdev;
+ unsigned long __iomem *reg_base;
+ unsigned long reg_phys_base;
+ struct device *dev;
+};
+
+static void __iomem *hdmi_base;
+static struct clk *isfr_clk;
+static struct clk *iahb_clk;
+static struct clk *mipi_core_clk;
+static spinlock_t irq_spinlock;
+static spinlock_t edid_spinlock;
+static unsigned int sample_rate;
+static unsigned long pixel_clk_rate;
+static struct clk *pixel_clk;
+static int hdmi_ratio;
+int mxc_hdmi_ipu_id;
+int mxc_hdmi_disp_id;
+static struct mxc_edid_cfg hdmi_core_edid_cfg;
+static int hdmi_core_init;
+static unsigned int hdmi_dma_running;
+static struct snd_pcm_substream *hdmi_audio_stream_playback;
+static unsigned int hdmi_cable_state;
+static unsigned int hdmi_blank_state;
+static unsigned int hdmi_abort_state;
+static spinlock_t hdmi_audio_lock, hdmi_blank_state_lock, hdmi_cable_state_lock;
+
+unsigned int hdmi_set_cable_state(unsigned int state)
+{
+ unsigned long flags;
+ struct snd_pcm_substream *substream = hdmi_audio_stream_playback;
+
+ spin_lock_irqsave(&hdmi_cable_state_lock, flags);
+ hdmi_cable_state = state;
+ spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
+
+#ifndef CONFIG_MFD_MXC_HDMI_ANDROID
+ if (check_hdmi_state() && substream && hdmi_abort_state) {
+ hdmi_abort_state = 0;
+ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(hdmi_set_cable_state);
+
+unsigned int hdmi_set_blank_state(unsigned int state)
+{
+ unsigned long flags;
+ struct snd_pcm_substream *substream = hdmi_audio_stream_playback;
+
+ spin_lock_irqsave(&hdmi_blank_state_lock, flags);
+ hdmi_blank_state = state;
+ spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
+
+#ifndef CONFIG_MFD_MXC_HDMI_ANDROID
+ if (check_hdmi_state() && substream && hdmi_abort_state) {
+ hdmi_abort_state = 0;
+ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
+ }
+#endif
+
+ return 0;
+}
+EXPORT_SYMBOL(hdmi_set_blank_state);
+
+#ifdef CONFIG_SND_SOC_IMX_HDMI_DMA
+static void hdmi_audio_abort_stream(struct snd_pcm_substream *substream)
+{
+ unsigned long flags;
+
+ snd_pcm_stream_lock_irqsave(substream, flags);
+
+#ifndef CONFIG_MFD_MXC_HDMI_ANDROID
+ if (snd_pcm_running(substream)) {
+ hdmi_abort_state = 1;
+ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
+ }
+#else
+ if (snd_pcm_running(substream))
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+#endif
+
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+}
+
+int mxc_hdmi_abort_stream(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&hdmi_audio_lock, flags);
+ if (hdmi_audio_stream_playback)
+ hdmi_audio_abort_stream(hdmi_audio_stream_playback);
+ spin_unlock_irqrestore(&hdmi_audio_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(mxc_hdmi_abort_stream);
+#else
+int mxc_hdmi_abort_stream(void)
+{
+ return 0;
+}
+EXPORT_SYMBOL(mxc_hdmi_abort_stream);
+#endif
+
+int check_hdmi_state(void)
+{
+ unsigned long flags1, flags2;
+ unsigned int ret;
+
+ spin_lock_irqsave(&hdmi_cable_state_lock, flags1);
+ spin_lock_irqsave(&hdmi_blank_state_lock, flags2);
+
+ ret = hdmi_cable_state && hdmi_blank_state;
+
+ spin_unlock_irqrestore(&hdmi_blank_state_lock, flags2);
+ spin_unlock_irqrestore(&hdmi_cable_state_lock, flags1);
+
+ return ret;
+}
+EXPORT_SYMBOL(check_hdmi_state);
+
+#ifdef CONFIG_SND_SOC_IMX_HDMI_DMA
+int mxc_hdmi_register_audio(struct snd_pcm_substream *substream)
+{
+ unsigned long flags, flags1;
+ int ret = 0;
+
+ if (!substream)
+ return -EINVAL;
+
+ snd_pcm_stream_lock_irqsave(substream, flags);
+
+ if (check_hdmi_state()) {
+ spin_lock_irqsave(&hdmi_audio_lock, flags1);
+ if (hdmi_audio_stream_playback) {
+ pr_err("%s unconsist hdmi auido stream!\n", __func__);
+ ret = -EINVAL;
+ }
+ hdmi_audio_stream_playback = substream;
+ hdmi_abort_state = 0;
+ spin_unlock_irqrestore(&hdmi_audio_lock, flags1);
+ } else
+ ret = -EINVAL;
+
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(mxc_hdmi_register_audio);
+#endif
+
+void mxc_hdmi_unregister_audio(struct snd_pcm_substream *substream)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hdmi_audio_lock, flags);
+ hdmi_audio_stream_playback = NULL;
+ hdmi_abort_state = 0;
+ spin_unlock_irqrestore(&hdmi_audio_lock, flags);
+}
+EXPORT_SYMBOL(mxc_hdmi_unregister_audio);
+
+u8 hdmi_readb(unsigned int reg)
+{
+ u8 value;
+
+ value = __raw_readb(hdmi_base + reg);
+
+ return value;
+}
+EXPORT_SYMBOL(hdmi_readb);
+
+#ifdef DEBUG
+static bool overflow_lo;
+static bool overflow_hi;
+
+bool hdmi_check_overflow(void)
+{
+ u8 val, lo, hi;
+
+ val = hdmi_readb(HDMI_IH_FC_STAT2);
+ lo = (val & HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW) != 0;
+ hi = (val & HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW) != 0;
+
+ if ((lo != overflow_lo) || (hi != overflow_hi)) {
+ pr_debug("%s LowPriority=%d HighPriority=%d <=======================\n",
+ __func__, lo, hi);
+ overflow_lo = lo;
+ overflow_hi = hi;
+ return true;
+ }
+ return false;
+}
+#else
+bool hdmi_check_overflow(void)
+{
+ return false;
+}
+#endif
+EXPORT_SYMBOL(hdmi_check_overflow);
+
+void hdmi_writeb(u8 value, unsigned int reg)
+{
+ hdmi_check_overflow();
+ __raw_writeb(value, hdmi_base + reg);
+ hdmi_check_overflow();
+}
+EXPORT_SYMBOL(hdmi_writeb);
+
+void hdmi_mask_writeb(u8 data, unsigned int reg, u8 shift, u8 mask)
+{
+ u8 value = hdmi_readb(reg) & ~mask;
+ value |= (data << shift) & mask;
+ hdmi_writeb(value, reg);
+}
+EXPORT_SYMBOL(hdmi_mask_writeb);
+
+unsigned int hdmi_read4(unsigned int reg)
+{
+ /* read a four byte address from registers */
+ return (hdmi_readb(reg + 3) << 24) |
+ (hdmi_readb(reg + 2) << 16) |
+ (hdmi_readb(reg + 1) << 8) |
+ hdmi_readb(reg);
+}
+EXPORT_SYMBOL(hdmi_read4);
+
+void hdmi_write4(unsigned int value, unsigned int reg)
+{
+ /* write a four byte address to hdmi regs */
+ hdmi_writeb(value & 0xff, reg);
+ hdmi_writeb((value >> 8) & 0xff, reg + 1);
+ hdmi_writeb((value >> 16) & 0xff, reg + 2);
+ hdmi_writeb((value >> 24) & 0xff, reg + 3);
+}
+EXPORT_SYMBOL(hdmi_write4);
+
+static void initialize_hdmi_ih_mutes(void)
+{
+ u8 ih_mute;
+
+ /*
+ * Boot up defaults are:
+ * HDMI_IH_MUTE = 0x03 (disabled)
+ * HDMI_IH_MUTE_* = 0x00 (enabled)
+ */
+
+ /* Disable top level interrupt bits in HDMI block */
+ ih_mute = hdmi_readb(HDMI_IH_MUTE) |
+ HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+ HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
+
+ hdmi_writeb(ih_mute, HDMI_IH_MUTE);
+
+ /* by default mask all interrupts */
+ hdmi_writeb(0xff, HDMI_VP_MASK);
+ hdmi_writeb(0xff, HDMI_FC_MASK0);
+ hdmi_writeb(0xff, HDMI_FC_MASK1);
+ hdmi_writeb(0xff, HDMI_FC_MASK2);
+ hdmi_writeb(0xff, HDMI_PHY_MASK0);
+ hdmi_writeb(0xff, HDMI_PHY_I2CM_INT_ADDR);
+ hdmi_writeb(0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
+ hdmi_writeb(0xff, HDMI_AUD_INT);
+ hdmi_writeb(0xff, HDMI_AUD_SPDIFINT);
+ hdmi_writeb(0xff, HDMI_AUD_HBR_MASK);
+ hdmi_writeb(0xff, HDMI_GP_MASK);
+ hdmi_writeb(0xff, HDMI_A_APIINTMSK);
+ hdmi_writeb(0xff, HDMI_CEC_MASK);
+ hdmi_writeb(0xff, HDMI_I2CM_INT);
+ hdmi_writeb(0xff, HDMI_I2CM_CTLINT);
+
+ /* Disable interrupts in the IH_MUTE_* registers */
+ hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT1);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT2);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_AS_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_PHY_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_I2CM_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_CEC_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_VP_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+ /* Enable top level interrupt bits in HDMI block */
+ ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+ HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
+ hdmi_writeb(ih_mute, HDMI_IH_MUTE);
+}
+
+static void hdmi_set_clock_regenerator_n(unsigned int value)
+{
+ u8 val;
+
+ if (!hdmi_dma_running) {
+ hdmi_writeb(value & 0xff, HDMI_AUD_N1);
+ hdmi_writeb(0, HDMI_AUD_N2);
+ hdmi_writeb(0, HDMI_AUD_N3);
+ }
+
+ hdmi_writeb(value & 0xff, HDMI_AUD_N1);
+ hdmi_writeb((value >> 8) & 0xff, HDMI_AUD_N2);
+ hdmi_writeb((value >> 16) & 0x0f, HDMI_AUD_N3);
+
+ /* nshift factor = 0 */
+ val = hdmi_readb(HDMI_AUD_CTS3);
+ val &= ~HDMI_AUD_CTS3_N_SHIFT_MASK;
+ hdmi_writeb(val, HDMI_AUD_CTS3);
+}
+
+static void hdmi_set_clock_regenerator_cts(unsigned int cts)
+{
+ u8 val;
+
+ if (!hdmi_dma_running) {
+ hdmi_writeb(cts & 0xff, HDMI_AUD_CTS1);
+ hdmi_writeb(0, HDMI_AUD_CTS2);
+ hdmi_writeb(0, HDMI_AUD_CTS3);
+ }
+
+ /* Must be set/cleared first */
+ val = hdmi_readb(HDMI_AUD_CTS3);
+ val &= ~HDMI_AUD_CTS3_CTS_MANUAL;
+ hdmi_writeb(val, HDMI_AUD_CTS3);
+
+ hdmi_writeb(cts & 0xff, HDMI_AUD_CTS1);
+ hdmi_writeb((cts >> 8) & 0xff, HDMI_AUD_CTS2);
+ hdmi_writeb(((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
+ HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+}
+
+static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
+ unsigned int ratio)
+{
+ unsigned int n = (128 * freq) / 1000;
+
+ switch (freq) {
+ case 32000:
+ if (pixel_clk == 25174000)
+ n = (ratio == 150) ? 9152 : 4576;
+ else if (pixel_clk == 27020000)
+ n = (ratio == 150) ? 8192 : 4096;
+ else if (pixel_clk == 74170000 || pixel_clk == 148350000)
+ n = 11648;
+ else if (pixel_clk == 297000000)
+ n = (ratio == 150) ? 6144 : 3072;
+ else
+ n = 4096;
+ break;
+
+ case 44100:
+ if (pixel_clk == 25174000)
+ n = 7007;
+ else if (pixel_clk == 74170000)
+ n = 17836;
+ else if (pixel_clk == 148350000)
+ n = (ratio == 150) ? 17836 : 8918;
+ else if (pixel_clk == 297000000)
+ n = (ratio == 150) ? 9408 : 4704;
+ else
+ n = 6272;
+ break;
+
+ case 48000:
+ if (pixel_clk == 25174000)
+ n = (ratio == 150) ? 9152 : 6864;
+ else if (pixel_clk == 27020000)
+ n = (ratio == 150) ? 8192 : 6144;
+ else if (pixel_clk == 74170000)
+ n = 11648;
+ else if (pixel_clk == 148350000)
+ n = (ratio == 150) ? 11648 : 5824;
+ else if (pixel_clk == 297000000)
+ n = (ratio == 150) ? 10240 : 5120;
+ else
+ n = 6144;
+ break;
+
+ case 88200:
+ n = hdmi_compute_n(44100, pixel_clk, ratio) * 2;
+ break;
+
+ case 96000:
+ n = hdmi_compute_n(48000, pixel_clk, ratio) * 2;
+ break;
+
+ case 176400:
+ n = hdmi_compute_n(44100, pixel_clk, ratio) * 4;
+ break;
+
+ case 192000:
+ n = hdmi_compute_n(48000, pixel_clk, ratio) * 4;
+ break;
+
+ default:
+ break;
+ }
+
+ return n;
+}
+
+static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
+ unsigned int ratio)
+{
+ unsigned int cts = 0;
+ switch (freq) {
+ case 32000:
+ if (pixel_clk == 297000000) {
+ cts = 222750;
+ break;
+ } else if (pixel_clk == 25174000) {
+ cts = 28125;
+ break;
+ }
+ case 48000:
+ case 96000:
+ case 192000:
+ switch (pixel_clk) {
+ case 25200000:
+ case 27000000:
+ case 54000000:
+ case 74250000:
+ case 148500000:
+ cts = pixel_clk / 1000;
+ break;
+ case 297000000:
+ cts = 247500;
+ break;
+ case 25174000:
+ cts = 28125l;
+ break;
+ /*
+ * All other TMDS clocks are not supported by
+ * DWC_hdmi_tx. The TMDS clocks divided or
+ * multiplied by 1,001 coefficients are not
+ * supported.
+ */
+ default:
+ break;
+ }
+ break;
+ case 44100:
+ case 88200:
+ case 176400:
+ switch (pixel_clk) {
+ case 25200000:
+ cts = 28000;
+ break;
+ case 25174000:
+ cts = 31250;
+ break;
+ case 27000000:
+ cts = 30000;
+ break;
+ case 54000000:
+ cts = 60000;
+ break;
+ case 74250000:
+ cts = 82500;
+ break;
+ case 148500000:
+ cts = 165000;
+ break;
+ case 297000000:
+ cts = 247500;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (ratio == 100)
+ return cts;
+ else
+ return (cts * ratio) / 100;
+}
+
+static void hdmi_set_clk_regenerator(void)
+{
+ unsigned int clk_n, clk_cts;
+
+ clk_n = hdmi_compute_n(sample_rate, pixel_clk_rate, hdmi_ratio);
+ clk_cts = hdmi_compute_cts(sample_rate, pixel_clk_rate, hdmi_ratio);
+
+ if (clk_cts == 0) {
+ pr_debug("%s: pixel clock not supported: %d\n",
+ __func__, (int)pixel_clk_rate);
+ return;
+ }
+
+ pr_debug("%s: samplerate=%d ratio=%d pixelclk=%d N=%d cts=%d\n",
+ __func__, sample_rate, hdmi_ratio, (int)pixel_clk_rate,
+ clk_n, clk_cts);
+
+ hdmi_set_clock_regenerator_cts(clk_cts);
+ hdmi_set_clock_regenerator_n(clk_n);
+}
+
+static int hdmi_core_get_of_property(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int err;
+ int ipu_id, disp_id;
+
+ err = of_property_read_u32(np, "ipu_id", &ipu_id);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property ipu_id fail\n");
+ return err;
+ }
+ err = of_property_read_u32(np, "disp_id", &disp_id);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property disp_id fail\n");
+ return err;
+ }
+
+ mxc_hdmi_ipu_id = ipu_id;
+ mxc_hdmi_disp_id = disp_id;
+
+ return err;
+}
+
+/* Need to run this before phy is enabled the first time to prevent
+ * overflow condition in HDMI_IH_FC_STAT2 */
+void hdmi_init_clk_regenerator(void)
+{
+ if (pixel_clk_rate == 0) {
+ pixel_clk_rate = 74250000;
+ hdmi_set_clk_regenerator();
+ }
+}
+EXPORT_SYMBOL(hdmi_init_clk_regenerator);
+
+void hdmi_clk_regenerator_update_pixel_clock(u32 pixclock)
+{
+
+ if (!pixclock)
+ return;
+ /* Translate pixel clock in ps (pico seconds) to Hz */
+ pixel_clk_rate = PICOS2KHZ(pixclock) * 1000UL;
+ hdmi_set_clk_regenerator();
+}
+EXPORT_SYMBOL(hdmi_clk_regenerator_update_pixel_clock);
+
+void hdmi_set_dma_mode(unsigned int dma_running)
+{
+ hdmi_dma_running = dma_running;
+ hdmi_set_clk_regenerator();
+}
+EXPORT_SYMBOL(hdmi_set_dma_mode);
+
+void hdmi_set_sample_rate(unsigned int rate)
+{
+ sample_rate = rate;
+}
+EXPORT_SYMBOL(hdmi_set_sample_rate);
+
+void hdmi_set_edid_cfg(struct mxc_edid_cfg *cfg)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&edid_spinlock, flags);
+ memcpy(&hdmi_core_edid_cfg, cfg, sizeof(struct mxc_edid_cfg));
+ spin_unlock_irqrestore(&edid_spinlock, flags);
+}
+EXPORT_SYMBOL(hdmi_set_edid_cfg);
+
+void hdmi_get_edid_cfg(struct mxc_edid_cfg *cfg)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&edid_spinlock, flags);
+ memcpy(cfg, &hdmi_core_edid_cfg, sizeof(struct mxc_edid_cfg));
+ spin_unlock_irqrestore(&edid_spinlock, flags);
+}
+EXPORT_SYMBOL(hdmi_get_edid_cfg);
+
+void hdmi_set_registered(int registered)
+{
+ hdmi_core_init = registered;
+}
+EXPORT_SYMBOL(hdmi_set_registered);
+
+int hdmi_get_registered(void)
+{
+ return hdmi_core_init;
+}
+EXPORT_SYMBOL(hdmi_get_registered);
+
+static int mxc_hdmi_core_probe(struct platform_device *pdev)
+{
+ struct mxc_hdmi_data *hdmi_data;
+ struct resource *res;
+ unsigned long flags;
+ int ret = 0;
+
+#ifdef DEBUG
+ overflow_lo = false;
+ overflow_hi = false;
+#endif
+
+ hdmi_core_init = 0;
+ hdmi_dma_running = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOENT;
+
+ ret = hdmi_core_get_of_property(pdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "get hdmi of property fail\n");
+ return -ENOENT;
+ }
+
+ hdmi_data = devm_kzalloc(&pdev->dev, sizeof(struct mxc_hdmi_data), GFP_KERNEL);
+ if (!hdmi_data) {
+ dev_err(&pdev->dev, "Couldn't allocate mxc hdmi mfd device\n");
+ return -ENOMEM;
+ }
+ hdmi_data->pdev = pdev;
+
+ pixel_clk = NULL;
+ sample_rate = 48000;
+ pixel_clk_rate = 0;
+ hdmi_ratio = 100;
+
+ spin_lock_init(&irq_spinlock);
+ spin_lock_init(&edid_spinlock);
+
+
+ spin_lock_init(&hdmi_cable_state_lock);
+ spin_lock_init(&hdmi_blank_state_lock);
+ spin_lock_init(&hdmi_audio_lock);
+
+ spin_lock_irqsave(&hdmi_cable_state_lock, flags);
+ hdmi_cable_state = 0;
+ spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
+
+ spin_lock_irqsave(&hdmi_blank_state_lock, flags);
+ hdmi_blank_state = 0;
+ spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
+
+ spin_lock_irqsave(&hdmi_audio_lock, flags);
+ hdmi_audio_stream_playback = NULL;
+ hdmi_abort_state = 0;
+ spin_unlock_irqrestore(&hdmi_audio_lock, flags);
+
+ mipi_core_clk = clk_get(&hdmi_data->pdev->dev, "mipi_core");
+ if (IS_ERR(mipi_core_clk)) {
+ ret = PTR_ERR(mipi_core_clk);
+ dev_err(&hdmi_data->pdev->dev,
+ "Unable to get mipi core clk: %d\n", ret);
+ goto eclkg;
+ }
+
+ ret = clk_prepare_enable(mipi_core_clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Cannot enable mipi core clock: %d\n", ret);
+ goto eclke;
+ }
+
+ isfr_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_isfr");
+ if (IS_ERR(isfr_clk)) {
+ ret = PTR_ERR(isfr_clk);
+ dev_err(&hdmi_data->pdev->dev,
+ "Unable to get HDMI isfr clk: %d\n", ret);
+ goto eclkg1;
+ }
+
+ ret = clk_prepare_enable(isfr_clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Cannot enable HDMI clock: %d\n", ret);
+ goto eclke1;
+ }
+
+ pr_debug("%s isfr_clk:%d\n", __func__,
+ (int)clk_get_rate(isfr_clk));
+
+ iahb_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_iahb");
+ if (IS_ERR(iahb_clk)) {
+ ret = PTR_ERR(iahb_clk);
+ dev_err(&hdmi_data->pdev->dev,
+ "Unable to get HDMI iahb clk: %d\n", ret);
+ goto eclkg2;
+ }
+
+ ret = clk_prepare_enable(iahb_clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Cannot enable HDMI clock: %d\n", ret);
+ goto eclke2;
+ }
+
+ hdmi_data->reg_phys_base = res->start;
+ if (!request_mem_region(res->start, resource_size(res),
+ dev_name(&pdev->dev))) {
+ dev_err(&pdev->dev, "request_mem_region failed\n");
+ ret = -EBUSY;
+ goto emem;
+ }
+
+ hdmi_data->reg_base = ioremap(res->start, resource_size(res));
+ if (!hdmi_data->reg_base) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto eirq;
+ }
+ hdmi_base = hdmi_data->reg_base;
+
+ pr_debug("\n%s hdmi hw base = 0x%08x\n\n", __func__, (int)res->start);
+
+ initialize_hdmi_ih_mutes();
+
+ /* Disable HDMI clocks until video/audio sub-drivers are initialized */
+ clk_disable_unprepare(isfr_clk);
+ clk_disable_unprepare(iahb_clk);
+ clk_disable_unprepare(mipi_core_clk);
+
+ /* Replace platform data coming in with a local struct */
+ platform_set_drvdata(pdev, hdmi_data);
+
+ return ret;
+
+eirq:
+ release_mem_region(res->start, resource_size(res));
+emem:
+ clk_disable_unprepare(iahb_clk);
+eclke2:
+ clk_put(iahb_clk);
+eclkg2:
+ clk_disable_unprepare(isfr_clk);
+eclke1:
+ clk_put(isfr_clk);
+eclkg1:
+ clk_disable_unprepare(mipi_core_clk);
+eclke:
+ clk_put(mipi_core_clk);
+eclkg:
+ return ret;
+}
+
+
+static int __exit mxc_hdmi_core_remove(struct platform_device *pdev)
+{
+ struct mxc_hdmi_data *hdmi_data = platform_get_drvdata(pdev);
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ iounmap(hdmi_data->reg_base);
+ release_mem_region(res->start, resource_size(res));
+
+ return 0;
+}
+
+static const struct of_device_id imx_hdmi_dt_ids[] = {
+ { .compatible = "fsl,imx6q-hdmi-core", },
+ { .compatible = "fsl,imx6dl-hdmi-core", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver mxc_hdmi_core_driver = {
+ .driver = {
+ .name = "mxc_hdmi_core",
+ .of_match_table = imx_hdmi_dt_ids,
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(mxc_hdmi_core_remove),
+};
+
+static int __init mxc_hdmi_core_init(void)
+{
+ return platform_driver_probe(&mxc_hdmi_core_driver,
+ mxc_hdmi_core_probe);
+}
+
+static void __exit mxc_hdmi_core_exit(void)
+{
+ platform_driver_unregister(&mxc_hdmi_core_driver);
+}
+
+subsys_initcall(mxc_hdmi_core_init);
+module_exit(mxc_hdmi_core_exit);
+
+MODULE_DESCRIPTION("Core driver for Freescale i.Mx on-chip HDMI");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/pf1550.c b/drivers/mfd/pf1550.c
new file mode 100644
index 000000000000..44c92f466a99
--- /dev/null
+++ b/drivers/mfd/pf1550.c
@@ -0,0 +1,311 @@
+/*
+ * pf1550.c - mfd core driver for the PF1550
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Robin Gong <yibin.gong@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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.
+ *
+ * This driver is based on max77693.c
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/pf1550.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+static const struct mfd_cell pf1550_devs[] = {
+ {
+ .name = "pf1550-regulator",
+ .of_compatible = "fsl,pf1550-regulator",
+ },
+ {
+ .name = "pf1550-onkey",
+ .of_compatible = "fsl,pf1550-onkey",
+ },
+ {
+ .name = "pf1550-charger",
+ .of_compatible = "fsl,pf1550-charger",
+ },
+};
+
+static const struct regmap_config pf1550_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = PF1550_PMIC_REG_END,
+};
+
+static const struct regmap_irq pf1550_regulator_irqs[] = {
+ { .reg_offset = 0, .mask = PMIC_IRQ_SW1_LS, },
+ { .reg_offset = 0, .mask = PMIC_IRQ_SW2_LS, },
+ { .reg_offset = 0, .mask = PMIC_IRQ_SW3_LS, },
+
+ { .reg_offset = 3, .mask = PMIC_IRQ_SW1_HS, },
+ { .reg_offset = 3, .mask = PMIC_IRQ_SW2_HS, },
+ { .reg_offset = 3, .mask = PMIC_IRQ_SW3_HS, },
+
+ { .reg_offset = 16, .mask = PMIC_IRQ_LDO1_FAULT, },
+ { .reg_offset = 16, .mask = PMIC_IRQ_LDO2_FAULT, },
+ { .reg_offset = 16, .mask = PMIC_IRQ_LDO3_FAULT, },
+
+ { .reg_offset = 22, .mask = PMIC_IRQ_TEMP_110, },
+ { .reg_offset = 22, .mask = PMIC_IRQ_TEMP_125, },
+};
+
+static const struct regmap_irq_chip pf1550_regulator_irq_chip = {
+ .name = "pf1550-regulator",
+ .status_base = PF1550_PMIC_REG_SW_INT_STAT0,
+ .mask_base = PF1550_PMIC_REG_SW_INT_MASK0,
+ .mask_invert = false,
+ .num_regs = 23,
+ .irqs = pf1550_regulator_irqs,
+ .num_irqs = ARRAY_SIZE(pf1550_regulator_irqs),
+};
+
+static const struct regmap_irq pf1550_onkey_irqs[] = {
+ { .reg_offset = 0, .mask = ONKEY_IRQ_PUSHI, },
+ { .reg_offset = 0, .mask = ONKEY_IRQ_1SI, },
+ { .reg_offset = 0, .mask = ONKEY_IRQ_2SI, },
+ { .reg_offset = 0, .mask = ONKEY_IRQ_3SI, },
+ { .reg_offset = 0, .mask = ONKEY_IRQ_4SI, },
+ { .reg_offset = 0, .mask = ONKEY_IRQ_8SI, },
+};
+
+static const struct regmap_irq_chip pf1550_onkey_irq_chip = {
+ .name = "pf1550-onkey",
+ .status_base = PF1550_PMIC_REG_ONKEY_INT_STAT0,
+ .ack_base = PF1550_PMIC_REG_ONKEY_INT_STAT0,
+ .mask_base = PF1550_PMIC_REG_ONKEY_INT_MASK0,
+ .mask_invert = false,
+ .use_ack = 1,
+ .init_ack_masked = 1,
+ .num_regs = 1,
+ .irqs = pf1550_onkey_irqs,
+ .num_irqs = ARRAY_SIZE(pf1550_onkey_irqs),
+};
+
+static const struct regmap_irq pf1550_charger_irqs[] = {
+ { .reg_offset = 0, .mask = CHARG_IRQ_BAT2SOCI, },
+ { .reg_offset = 0, .mask = CHARG_IRQ_BATI, },
+ { .reg_offset = 0, .mask = CHARG_IRQ_CHGI, },
+ { .reg_offset = 0, .mask = CHARG_IRQ_VBUSI, },
+ { .reg_offset = 0, .mask = CHARG_IRQ_THMI, },
+};
+
+static const struct regmap_irq_chip pf1550_charger_irq_chip = {
+ .name = "pf1550-charger",
+ .status_base = PF1550_CHARG_REG_CHG_INT,
+ .mask_base = PF1550_CHARG_REG_CHG_INT_MASK,
+ .mask_invert = false,
+ .num_regs = 1,
+ .irqs = pf1550_charger_irqs,
+ .num_irqs = ARRAY_SIZE(pf1550_charger_irqs),
+};
+
+int pf1550_read_otp(struct pf1550_dev *pf1550, unsigned int index,
+ unsigned int *val)
+{
+ int ret = 0;
+
+ ret = regmap_write(pf1550->regmap, PF1550_PMIC_REG_KEY, 0x15);
+ if (ret)
+ goto read_err;
+ ret = regmap_write(pf1550->regmap, PF1550_CHARG_REG_CHGR_KEY2, 0x50);
+ if (ret)
+ goto read_err;
+ ret = regmap_write(pf1550->regmap, PF1550_TEST_REG_KEY3, 0xAB);
+ if (ret)
+ goto read_err;
+ ret = regmap_write(pf1550->regmap, PF1550_TEST_REG_FMRADDR, index);
+ if (ret)
+ goto read_err;
+ ret = regmap_read(pf1550->regmap, PF1550_TEST_REG_FMRDATA, val);
+ if (ret)
+ goto read_err;
+
+ return 0;
+
+read_err:
+ dev_err(pf1550->dev, "read otp reg %x found!\n", index);
+ return ret;
+}
+
+static int pf1550_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct pf1550_dev *pf1550;
+ unsigned int reg_data = 0;
+ int ret = 0;
+
+ pf1550 = devm_kzalloc(&i2c->dev,
+ sizeof(struct pf1550_dev), GFP_KERNEL);
+ if (!pf1550)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, pf1550);
+ pf1550->dev = &i2c->dev;
+ pf1550->i2c = i2c;
+ pf1550->irq = i2c->irq;
+
+ pf1550->regmap = devm_regmap_init_i2c(i2c, &pf1550_regmap_config);
+ if (IS_ERR(pf1550->regmap)) {
+ ret = PTR_ERR(pf1550->regmap);
+ dev_err(pf1550->dev, "failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regmap_read(pf1550->regmap, PF1550_PMIC_REG_DEVICE_ID, &reg_data);
+ if (ret < 0 || reg_data != 0x7c) {
+ dev_err(pf1550->dev, "device not found!\n");
+ return ret;
+ }
+
+ pf1550->type = PF1550;
+ dev_info(pf1550->dev, "pf1550 found.\n");
+
+ ret = regmap_add_irq_chip(pf1550->regmap, pf1550->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &pf1550_regulator_irq_chip,
+ &pf1550->irq_data_regulator);
+ if (ret) {
+ dev_err(pf1550->dev, "failed to add irq1 chip: %d\n", ret);
+ goto err_regulator_irq;
+ }
+
+ ret = regmap_add_irq_chip(pf1550->regmap, pf1550->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &pf1550_onkey_irq_chip,
+ &pf1550->irq_data_onkey);
+ if (ret) {
+ dev_err(pf1550->dev, "failed to add irq3 chip: %d\n", ret);
+ goto err_onkey_irq;
+ }
+
+ ret = regmap_add_irq_chip(pf1550->regmap, pf1550->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &pf1550_charger_irq_chip,
+ &pf1550->irq_data_charger);
+ if (ret) {
+ dev_err(pf1550->dev, "failed to add irq4 chip: %d\n", ret);
+ goto err_charger_irq;
+ }
+
+ ret = mfd_add_devices(pf1550->dev, -1, pf1550_devs,
+ ARRAY_SIZE(pf1550_devs), NULL, 0, NULL);
+ if (ret < 0)
+ goto err_mfd;
+
+ return ret;
+
+err_mfd:
+ mfd_remove_devices(pf1550->dev);
+err_charger_irq:
+ regmap_del_irq_chip(pf1550->irq, pf1550->irq_data_charger);
+err_onkey_irq:
+ regmap_del_irq_chip(pf1550->irq, pf1550->irq_data_regulator);
+err_regulator_irq:
+ return ret;
+}
+
+static int pf1550_i2c_remove(struct i2c_client *i2c)
+{
+ struct pf1550_dev *pf1550 = i2c_get_clientdata(i2c);
+
+ mfd_remove_devices(pf1550->dev);
+
+ regmap_del_irq_chip(pf1550->irq, pf1550->irq_data_regulator);
+ regmap_del_irq_chip(pf1550->irq, pf1550->irq_data_onkey);
+ regmap_del_irq_chip(pf1550->irq, pf1550->irq_data_charger);
+
+ return 0;
+}
+
+static const struct i2c_device_id pf1550_i2c_id[] = {
+ { "pf1550", PF1550 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pf1550_i2c_id);
+
+static int pf1550_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct pf1550_dev *pf1550 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(pf1550->irq);
+ disable_irq(pf1550->irq);
+ }
+
+ return 0;
+}
+
+static int pf1550_resume(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct pf1550_dev *pf1550 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(pf1550->irq);
+ enable_irq(pf1550->irq);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops pf1550_pm = {
+ .suspend = pf1550_suspend,
+ .resume = pf1550_resume,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id pf1550_dt_match[] = {
+ { .compatible = "fsl,pf1550" },
+ {},
+};
+#endif
+
+static struct i2c_driver pf1550_i2c_driver = {
+ .driver = {
+ .name = "pf1550",
+ .owner = THIS_MODULE,
+ .pm = &pf1550_pm,
+ .of_match_table = of_match_ptr(pf1550_dt_match),
+ },
+ .probe = pf1550_i2c_probe,
+ .remove = pf1550_i2c_remove,
+ .id_table = pf1550_i2c_id,
+};
+
+static int __init pf1550_i2c_init(void)
+{
+ return i2c_add_driver(&pf1550_i2c_driver);
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(pf1550_i2c_init);
+
+static void __exit pf1550_i2c_exit(void)
+{
+ i2c_del_driver(&pf1550_i2c_driver);
+}
+module_exit(pf1550_i2c_exit);
+
+MODULE_DESCRIPTION("Freescale PF1550 multi-function core driver");
+MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c
index c180b7533bba..3caa23990414 100644
--- a/drivers/mfd/si476x-i2c.c
+++ b/drivers/mfd/si476x-i2c.c
@@ -303,7 +303,7 @@ int si476x_core_set_power_state(struct si476x_core *core,
*/
udelay(100);
- err = si476x_core_start(core, false);
+ err = si476x_core_start(core, true);
if (err < 0)
goto disable_regulators;
@@ -312,7 +312,7 @@ int si476x_core_set_power_state(struct si476x_core *core,
case SI476X_POWER_DOWN:
core->power_state = next_state;
- err = si476x_core_stop(core, false);
+ err = si476x_core_stop(core, true);
if (err < 0)
core->power_state = SI476X_POWER_INCONSISTENT;
disable_regulators:
@@ -740,8 +740,15 @@ static int si476x_core_probe(struct i2c_client *client,
memcpy(&core->pinmux, &pdata->pinmux,
sizeof(struct si476x_pinmux));
} else {
- dev_err(&client->dev, "No platform data provided\n");
- return -EINVAL;
+ dev_warn(&client->dev, "Using default platform data.\n");
+ core->power_up_parameters.xcload = 0x28;
+ core->power_up_parameters.func = SI476X_FUNC_FM_RECEIVER;
+ core->power_up_parameters.freq = SI476X_FREQ_37P209375_MHZ;
+ core->diversity_mode = SI476X_PHDIV_DISABLED;
+ core->pinmux.dclk = SI476X_DCLK_DAUDIO;
+ core->pinmux.dfs = SI476X_DFS_DAUDIO;
+ core->pinmux.dout = SI476X_DOUT_I2S_OUTPUT;
+ core->pinmux.xout = SI476X_XOUT_TRISTATE;
}
core->supplies[0].supply = "vd";
@@ -800,12 +807,19 @@ static int si476x_core_probe(struct i2c_client *client,
core->chip_id = id->driver_data;
+ /* Power down si476x first */
+ core->power_state = SI476X_POWER_UP_FULL;
+ si476x_core_set_power_state(core, SI476X_POWER_DOWN);
+
rval = si476x_core_get_revision_info(core);
if (rval < 0) {
rval = -ENODEV;
goto free_kfifo;
}
+ if (of_property_read_bool(client->dev.of_node, "revision-a10"))
+ core->revision = SI476X_REVISION_A10;
+
cell_num = 0;
cell = &core->cells[SI476X_RADIO_CELL];
@@ -821,6 +835,7 @@ static int si476x_core_probe(struct i2c_client *client,
core->pinmux.xout == SI476X_XOUT_TRISTATE) {
cell = &core->cells[SI476X_CODEC_CELL];
cell->name = "si476x-codec";
+ cell->of_compatible = "si476x-codec";
cell_num++;
}
#endif
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 64971baf11fa..1a1cd2e7c590 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -335,6 +335,26 @@ config ISL29020
This driver can also be built as a module. If so, the module
will be called isl29020.
+config SENSORS_FXOS8700
+ tristate "Freescale FXOS8700 M+G combo sensor"
+ depends on I2C && SYSFS
+ help
+ If you say yes here you get support for the Freescale FXOS8700
+ m+g combo sensor.
+
+ This driver can also be built as a module. If so, the module
+ will be called fxos8700.
+
+config SENSORS_FXAS2100X
+ tristate "Freescale FXAS2100X gyroscope sensor"
+ depends on I2C && SYSFS
+ help
+ If you say yes here you get support for the Freescale FXAS2100X
+ gyroscope sensor.
+
+ This driver can also be built as a module. If so, the module
+ will be called fxas2100x.
+
config SENSORS_TSL2550
tristate "Taos TSL2550 ambient light sensor"
depends on I2C && SYSFS
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 31983366090a..9c7cce275dc8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -16,6 +16,8 @@ obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o
+obj-$(CONFIG_SENSORS_FXOS8700) += fxos8700.o
+obj-$(CONFIG_SENSORS_FXAS2100X) += fxas2100x.o
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 5afe4cd16569..67eb81aecfe4 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -249,7 +249,7 @@ static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
u32 val;
memset(chip, 0, sizeof(*chip));
- strncpy(chip->name, "at25", sizeof(chip->name));
+ strlcpy(chip->name, "at25", sizeof(chip->name));
if (device_property_read_u32(dev, "size", &val) == 0 ||
device_property_read_u32(dev, "at25,byte-len", &val) == 0) {
diff --git a/drivers/misc/fxas2100x.c b/drivers/misc/fxas2100x.c
new file mode 100644
index 000000000000..3ac718067a75
--- /dev/null
+++ b/drivers/misc/fxas2100x.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2012-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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/input-polldev.h>
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+
+#define SENSOR_IOCTL_BASE 'S'
+#define SENSOR_GET_MODEL_NAME _IOR(SENSOR_IOCTL_BASE, 0, char *)
+#define SENSOR_GET_POWER_STATUS _IOR(SENSOR_IOCTL_BASE, 2, int)
+#define SENSOR_SET_POWER_STATUS _IOR(SENSOR_IOCTL_BASE, 3, int)
+#define SENSOR_GET_DELAY_TIME _IOR(SENSOR_IOCTL_BASE, 4, int)
+#define SENSOR_SET_DELAY_TIME _IOR(SENSOR_IOCTL_BASE, 5, int)
+#define SENSOR_GET_RAW_DATA _IOR(SENSOR_IOCTL_BASE, 6, short[3])
+
+#define FXAS2100X_I2C_ADDR 0x20
+#define FXAS21000_CHIP_ID 0xD1
+#define FXAS21002_CHID_ID_1 0xD6
+#define FXAS21002_CHID_ID_2 0xD7
+
+#define FXAS2100X_POSITION_DEFAULT 2
+#define FXAS2100X_DELAY_DEFAULT 200
+
+#define FXAS2100X_STATUS_ZYXDR 0x08
+#define FXAS2100X_BUF_SIZE 6
+
+#define FXAS2100X_POLL_INTERVAL 400
+#define FXAS2100X_POLL_MAX 800
+#define FXAS2100X_POLL_MIN 200
+#define ABSMIN_GYRO_VAL -32768
+#define ABSMAX_GYRO_VAL 32768
+
+#define FXAS2100X_DRIVER "fxas2100x"
+
+/* register enum for fxas2100x registers */
+enum {
+ FXAS2100X_STATUS = 0x00,
+ FXAS2100X_OUT_X_MSB,
+ FXAS2100X_OUT_X_LSB,
+ FXAS2100X_OUT_Y_MSB,
+ FXAS2100X_OUT_Y_LSB,
+ FXAS2100X_OUT_Z_MSB,
+ FXAS2100X_OUT_Z_LSB,
+ FXAS2100X_DR_STATUS,
+ FXAS2100X_F_STATUS,
+ FXAS2100X_F_SETUP,
+ FXAS2100X_F_EVENT,
+ FXAS2100X_INT_SRC_FLAG,
+ FXAS2100X_WHO_AM_I,
+ FXAS2100X_CTRL_REG0,
+ FXAS2100X_RT_CFG,
+ FXAS2100X_RT_SRC,
+ FXAS2100X_RT_THS,
+ FXAS2100X_RT_COUNT,
+ FXAS2100X_TEMP,
+ FXAS2100X_CTRL_REG1,
+ FXAS2100X_CTRL_REG2,
+ FXAS2100X_CTRL_REG3, /* fxos21002 special */
+ FXAS2100X_REG_END,
+};
+
+enum {
+ STANDBY = 0,
+ ACTIVED,
+};
+
+struct fxas2100x_data_axis {
+ short x;
+ short y;
+ short z;
+};
+
+struct fxas2100x_data {
+ struct i2c_client *client;
+ struct input_polled_dev *input_polled;
+ atomic_t active;
+ atomic_t active_poll;
+ atomic_t delay;
+ atomic_t position;
+ u8 chip_id;
+};
+
+static struct fxas2100x_data *g_fxas2100x_data;
+
+static int fxas2100x_position_setting[8][3][3] = {
+ { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} },
+ { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} },
+ { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
+ { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} },
+ { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
+ { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} },
+ { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} },
+ { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} },
+};
+
+static int fxas2100x_data_convert(struct fxas2100x_data *pdata,
+ struct fxas2100x_data_axis *axis_data)
+{
+ short rawdata[3], data[3];
+ int i, j;
+ int position = atomic_read(&pdata->position);
+
+ if (position < 0 || position > 7)
+ position = 0;
+ rawdata[0] = axis_data->x;
+ rawdata[1] = axis_data->y;
+ rawdata[2] = axis_data->z;
+ for (i = 0; i < 3; i++) {
+ data[i] = 0;
+ for (j = 0; j < 3; j++)
+ data[i] += rawdata[j] * fxas2100x_position_setting[position][i][j];
+ }
+ axis_data->x = data[0];
+ axis_data->y = data[1];
+ axis_data->z = data[2];
+ return 0;
+}
+
+static int fxas2100x_device_init(struct i2c_client *client)
+{
+ int result;
+ u8 val;
+ struct fxas2100x_data *pdata = i2c_get_clientdata(client);
+ if (pdata->chip_id == FXAS21000_CHIP_ID)
+ val = (0x01 << 2); /* fxas21000 dr 200HZ */
+ else
+ val = (0x02 << 2); /* fxas21002 dr 200HZ */
+ result = i2c_smbus_write_byte_data(client, FXAS2100X_CTRL_REG1, val);
+ if (result < 0)
+ goto out;
+ atomic_set(&pdata->active, STANDBY);
+ return 0;
+out:
+ dev_err(&client->dev, "error when init fxas2100x:(%d)", result);
+ return result;
+}
+
+static int fxas2100x_change_mode(struct i2c_client *client, int mode)
+{
+ u8 val;
+ int ret;
+ if (mode == ACTIVED) {
+ val = i2c_smbus_read_byte_data(client, FXAS2100X_CTRL_REG1);
+ val &= ~0x03;
+ val |= 0x02;
+ /* set bit 1 */
+ ret = i2c_smbus_write_byte_data(client, FXAS2100X_CTRL_REG1, val);
+ } else {
+ val = i2c_smbus_read_byte_data(client, FXAS2100X_CTRL_REG1);
+ val &= (~0x03);
+ /* clear bit 0,1 */
+ ret = i2c_smbus_write_byte_data(client, FXAS2100X_CTRL_REG1, val);
+ }
+ return ret;
+}
+
+static int fxas2100x_set_delay(struct i2c_client *client, int delay)
+{
+ return 0;
+}
+
+static int fxas2100x_device_stop(struct i2c_client *client)
+{
+ u8 val;
+ val = i2c_smbus_read_byte_data(client, FXAS2100X_CTRL_REG1);
+ val &= ~0x03;
+ i2c_smbus_write_byte_data(client, FXAS2100X_CTRL_REG1, val);
+ return 0;
+}
+
+static int fxas2100x_read_data(struct fxas2100x_data *pdata,
+ struct fxas2100x_data_axis *data)
+{
+ struct i2c_client * client = pdata->client;
+ int x, y, z;
+ u8 tmp_data[FXAS2100X_BUF_SIZE];
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, FXAS2100X_OUT_X_MSB,
+ FXAS2100X_BUF_SIZE, tmp_data);
+ if (ret < FXAS2100X_BUF_SIZE) {
+ dev_err(&client->dev, "i2c block read failed\n");
+ return -EIO;
+ }
+ data->x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+ data->y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+ data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+ if (pdata->chip_id == FXAS21000_CHIP_ID) {
+ x = data->x;
+ y = data->y;
+ z = data->z;
+ x = x * 4 / 5;
+ y = y * 4 / 5;
+ z = z * 4 / 5;
+ data->x = x;
+ data->y = y;
+ data->z = z;
+ }
+
+ return 0;
+}
+
+/* fxas2100x miscdevice */
+static long fxas2100x_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct fxas2100x_data *pdata = file->private_data;
+ void __user *argp = (void __user *)arg;
+ struct fxas2100x_data_axis data;
+ long ret = 0;
+ short sdata[3];
+ int enable;
+ int delay;
+
+ if (!pdata) {
+ printk(KERN_ERR "FXAS2100X struct datt point is NULL.");
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+ case SENSOR_GET_MODEL_NAME:
+ if (copy_to_user(argp, "FXAS2100X GYRO", strlen("FXAS2100X GYRO") + 1)) {
+ printk(KERN_ERR "SENSOR_GET_MODEL_NAME copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ break;
+ case SENSOR_GET_POWER_STATUS:
+ enable = atomic_read(&pdata->active);
+ if (copy_to_user(argp, &enable, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_SET_POWER_STATUS copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ break;
+ case SENSOR_SET_POWER_STATUS:
+ if (copy_from_user(&enable, argp, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_SET_POWER_STATUS copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ if (pdata->client) {
+ ret = fxas2100x_change_mode(pdata->client, enable ? ACTIVED : STANDBY);
+ if (!ret)
+ atomic_set(&pdata->active, enable);
+ }
+ break;
+ case SENSOR_GET_DELAY_TIME:
+ delay = atomic_read(&pdata->delay);
+ if (copy_to_user(argp, &delay, sizeof(delay))) {
+ printk(KERN_ERR "SENSOR_GET_DELAY_TIME copy_to_user failed.");
+ return -EFAULT;
+ }
+ break;
+ case SENSOR_SET_DELAY_TIME:
+ if (copy_from_user(&delay, argp, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_GET_DELAY_TIME copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ if (pdata->client && delay > 0 && delay <= 500) {
+ ret = fxas2100x_set_delay(pdata->client, delay);
+ if (!ret)
+ atomic_set(&pdata->delay, delay);
+ }
+ break;
+ case SENSOR_GET_RAW_DATA:
+ ret = fxas2100x_read_data(pdata, &data);
+ if (!ret) {
+ fxas2100x_data_convert(pdata, &data);
+ sdata[0] = data.x;
+ sdata[1] = data.y;
+ sdata[2] = data.z;
+ if (copy_to_user(argp, sdata, sizeof(sdata))) {
+ printk(KERN_ERR "SENSOR_GET_RAW_DATA copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ }
+ break;
+ default:
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int fxas2100x_open(struct inode *inode, struct file *file)
+{
+ file->private_data = g_fxas2100x_data;
+ return nonseekable_open(inode, file);
+}
+
+static int fxas2100x_release(struct inode *inode, struct file *file)
+{
+ /* note: releasing the wdt in NOWAYOUT-mode does not stop it */
+ return 0;
+}
+
+static const struct file_operations fxas2100x_fops = {
+ .owner = THIS_MODULE,
+ .open = fxas2100x_open,
+ .release = fxas2100x_release,
+ .unlocked_ioctl = fxas2100x_ioctl,
+};
+
+static struct miscdevice fxas2100x_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "FreescaleGyroscope",
+ .fops = &fxas2100x_fops,
+};
+
+static ssize_t fxas2100x_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxas2100x_data *pdata = g_fxas2100x_data;
+ int enable = 0;
+ enable = atomic_read(&pdata->active);
+ return sprintf(buf, "%d\n", enable);
+}
+
+static ssize_t fxas2100x_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fxas2100x_data *pdata = g_fxas2100x_data;
+ struct i2c_client *client = pdata->client;
+ int ret;
+ unsigned long enable;
+
+ if (kstrtoul(buf, 10, &enable) < 0)
+ return -EINVAL;
+
+ enable = (enable > 0) ? 1 : 0;
+ ret = fxas2100x_change_mode(client, (enable > 0 ? ACTIVED : STANDBY));
+ if (!ret) {
+ atomic_set(&pdata->active, enable);
+ atomic_set(&pdata->active_poll, enable);
+ dev_err(dev, "mma enable setting active \n");
+ }
+ return count;
+}
+
+static ssize_t fxas2100x_poll_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxas2100x_data *pdata = g_fxas2100x_data;
+ int delay = 0;
+
+ delay = atomic_read(&pdata->delay);
+ return sprintf(buf, "%d\n", delay);
+}
+
+static ssize_t fxas2100x_poll_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fxas2100x_data *pdata = g_fxas2100x_data;
+ struct i2c_client *client = pdata->client;
+ int ret;
+ int delay;
+
+ delay = simple_strtoul(buf, NULL, 10);
+ ret = fxas2100x_set_delay(client, delay);
+ if (!ret)
+ atomic_set(&pdata->delay, delay);
+ return count;
+}
+
+static ssize_t fxas2100x_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxas2100x_data *pdata = g_fxas2100x_data;
+ int position = 0;
+
+ position = atomic_read(&pdata->position);
+ return sprintf(buf, "%d\n", position);
+}
+
+static ssize_t fxas2100x_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fxas2100x_data *pdata = g_fxas2100x_data;
+ int position;
+
+ position = simple_strtoul(buf, NULL, 10);
+ atomic_set(&pdata->position, position);
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, fxas2100x_enable_show, fxas2100x_enable_store);
+static DEVICE_ATTR(poll_delay, S_IWUSR | S_IRUGO, fxas2100x_poll_delay_show, fxas2100x_poll_delay_store);
+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, fxas2100x_position_show, fxas2100x_position_store);
+
+static struct attribute *fxas2100x_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_poll_delay.attr,
+ &dev_attr_position.attr,
+ NULL
+};
+
+static const struct attribute_group fxas2100x_attr_group = {
+ .attrs = fxas2100x_attributes,
+};
+
+static void fxas2100x_poll(struct input_polled_dev *dev)
+{
+ struct fxas2100x_data *pdata = g_fxas2100x_data;
+ struct input_dev *idev = pdata->input_polled->input;
+ struct fxas2100x_data_axis data;
+ int ret;
+
+ if (!(atomic_read(&pdata->active_poll)))
+ return;
+
+ ret = fxas2100x_read_data(pdata, &data);
+ if (!ret) {
+ fxas2100x_data_convert(pdata, &data);
+ input_report_abs(idev, ABS_X, data.x);
+ input_report_abs(idev, ABS_Y, data.y);
+ input_report_abs(idev, ABS_Z, data.z);
+ input_sync(idev);
+ }
+}
+
+static int fxas2100x_register_polled_device(struct fxas2100x_data *pdata)
+{
+ struct input_polled_dev *ipoll_dev;
+ struct input_dev *idev;
+ int error;
+
+ ipoll_dev = input_allocate_polled_device();
+ if (!ipoll_dev)
+ return -ENOMEM;
+
+ ipoll_dev->private = pdata;
+ ipoll_dev->poll = fxas2100x_poll;
+ ipoll_dev->poll_interval = FXAS2100X_POLL_INTERVAL;
+ ipoll_dev->poll_interval_min = FXAS2100X_POLL_MIN;
+ ipoll_dev->poll_interval_max = FXAS2100X_POLL_MAX;
+ idev = ipoll_dev->input;
+ idev->name = FXAS2100X_DRIVER;
+ idev->id.bustype = BUS_I2C;
+ idev->dev.parent = &pdata->client->dev;
+
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(idev, ABS_X, ABSMIN_GYRO_VAL, ABSMAX_GYRO_VAL, 0, 0);
+ input_set_abs_params(idev, ABS_Y, ABSMIN_GYRO_VAL, ABSMAX_GYRO_VAL, 0, 0);
+ input_set_abs_params(idev, ABS_Z, ABSMIN_GYRO_VAL, ABSMAX_GYRO_VAL, 0, 0);
+
+ error = input_register_polled_device(ipoll_dev);
+ if (error) {
+ input_free_polled_device(ipoll_dev);
+ return error;
+ }
+
+ pdata->input_polled = ipoll_dev;
+ return 0;
+}
+
+static int fxas2100x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result, chip_id;
+ struct fxas2100x_data *pdata;
+ struct i2c_adapter *adapter;
+
+ adapter = to_i2c_adapter(client->dev.parent);
+ result = i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA);
+ if (!result)
+ goto err_out;
+
+ chip_id = i2c_smbus_read_byte_data(client, FXAS2100X_WHO_AM_I);
+ if (chip_id != FXAS21000_CHIP_ID && chip_id != FXAS21002_CHID_ID_1 &&
+ chip_id != FXAS21002_CHID_ID_2) {
+ dev_err(&client->dev,
+ "read chip ID 0x%x is not equal to 0x%x for fxas21000 or 0x%x/0x%x fxas21002!\n",
+ chip_id, FXAS21000_CHIP_ID, FXAS21002_CHID_ID_1, FXAS21002_CHID_ID_2);
+ result = -EINVAL;
+ goto err_out;
+ }
+
+ pdata = kzalloc(sizeof(struct fxas2100x_data), GFP_KERNEL);
+ if (!pdata) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "alloc data memory error!\n");
+ goto err_out;
+ }
+
+ /* Initialize the FXAS2100X chip */
+ g_fxas2100x_data = pdata;
+ pdata->client = client;
+ pdata->chip_id = chip_id;
+ atomic_set(&pdata->delay, FXAS2100X_DELAY_DEFAULT);
+ atomic_set(&pdata->position, FXAS2100X_POSITION_DEFAULT);
+ i2c_set_clientdata(client, pdata);
+ result = misc_register(&fxas2100x_device);
+ if (result != 0) {
+ dev_err(&client->dev, "register acc miscdevice error");
+ goto err_regsiter_misc;
+ }
+
+ /* for debug */
+ if (client->irq <= 0) {
+ result = fxas2100x_register_polled_device(g_fxas2100x_data);
+ if (result)
+ dev_err(&client->dev,
+ "IRQ GPIO conf. error %d, error %d\n",
+ client->irq, result);
+ }
+
+ result = sysfs_create_group(&fxas2100x_device.this_device->kobj,
+ &fxas2100x_attr_group);
+ if (result) {
+ dev_err(&client->dev, "create device file failed!\n");
+ result = -EINVAL;
+ goto err_create_sysfs;
+ }
+ fxas2100x_device_init(client);
+ dev_info(&client->dev, "fxas2100x device driver probe successfully\n");
+ return 0;
+err_create_sysfs:
+ misc_deregister(&fxas2100x_device);
+err_regsiter_misc:
+ kfree(pdata);
+err_out:
+ return result;
+}
+
+static int fxas2100x_remove(struct i2c_client *client)
+{
+ struct fxas2100x_data *pdata = i2c_get_clientdata(client);
+ fxas2100x_device_stop(client);
+ if (client->irq <= 0) {
+ input_unregister_polled_device(pdata->input_polled);
+ input_free_polled_device(pdata->input_polled);
+ }
+ misc_deregister(&fxas2100x_device);
+ if (pdata != NULL)
+ kfree(pdata);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int fxas2100x_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fxas2100x_data *pdata = i2c_get_clientdata(client);
+
+ if (atomic_read(&pdata->active))
+ fxas2100x_device_stop(client);
+ return 0;
+}
+
+static int fxas2100x_resume(struct device *dev)
+{
+ int val = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fxas2100x_data *pdata = i2c_get_clientdata(client);
+
+ if (atomic_read(&pdata->active)) {
+ val = i2c_smbus_read_byte_data(client, FXAS2100X_CTRL_REG1);
+ val &= ~0x03;
+ val |= 0x02;
+ i2c_smbus_write_byte_data(client, FXAS2100X_CTRL_REG1, val);
+ }
+ return 0;
+
+}
+#endif
+
+static const struct i2c_device_id fxas2100x_id[] = {
+ { "fxas2100x", 0 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, fxas2100x_id);
+
+static SIMPLE_DEV_PM_OPS(fxas2100x_pm_ops, fxas2100x_suspend, fxas2100x_resume);
+static struct i2c_driver fxas2100x_driver = {
+ .driver = {
+ .name = FXAS2100X_DRIVER,
+ .owner = THIS_MODULE,
+ .pm = &fxas2100x_pm_ops,
+ },
+ .probe = fxas2100x_probe,
+ .remove = fxas2100x_remove,
+ .id_table = fxas2100x_id,
+};
+
+module_i2c_driver(fxas2100x_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("FXAS2100X 3-Axis Gyrosope Sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/fxos8700.c b/drivers/misc/fxos8700.c
new file mode 100644
index 000000000000..326e2accde1b
--- /dev/null
+++ b/drivers/misc/fxos8700.c
@@ -0,0 +1,970 @@
+/*
+ * Copyright (C) 2012-2013 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/input-polldev.h>
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+
+/*register define*/
+#define FXOS8700_STATUS 0x00
+#define FXOS8700_OUT_X_MSB 0x01
+#define FXOS8700_OUT_X_LSB 0x02
+#define FXOS8700_OUT_Y_MSB 0x03
+#define FXOS8700_OUT_Y_LSB 0x04
+#define FXOS8700_OUT_Z_MSB 0x05
+#define FXOS8700_OUT_Z_LSB 0x06
+#define FXOS8700_F_SETUP 0x09
+#define FXOS8700_TRIG_CFG 0x0a
+#define FXOS8700_SYSMOD 0x0B
+#define FXOS8700_INT_SOURCE 0x0c
+#define FXOS8700_WHO_AM_I 0x0d
+#define FXOS8700_XYZ_DATA_CFG 0x0e
+#define FXOS8700_HP_FILTER_CUTOFF 0x0f
+#define FXOS8700_PL_STATUS 0x10
+#define FXOS8700_PL_CFG 0x11
+#define FXOS8700_PL_COUNT 0x12
+#define FXOS8700_PL_BF_ZCOMP 0x13
+#define FXOS8700_PL_P_L_THS_REG 0x14
+#define FXOS8700_FFMT_CFG 0x15
+#define FXOS8700_FFMT_SRC 0x16
+#define FXOS8700_FFMT_THS 0x17
+#define FXOS8700_FFMT_COUNT 0x18
+#define FXOS8700_TRANSIDENT1_CFG 0x1d
+#define FXOS8700_TRANSIDENT1_SRC 0x1e
+#define FXOS8700_TRANSIDENT1_THS 0x1f
+#define FXOS8700_TRANSIDENT1_COUNT 0x20
+#define FXOS8700_PULSE_CFG 0x21
+#define FXOS8700_PULSE_SRC 0x22
+#define FXOS8700_PULSE_THSX 0x23
+#define FXOS8700_PULSE_THSY 0x24
+#define FXOS8700_PULSE_THSZ 0x25
+#define FXOS8700_PULSE_TMLT 0x26
+#define FXOS8700_PULSE_LTCY 0x27
+#define FXOS8700_PULSE_WIND 0x28
+#define FXOS8700_ATSLP_COUNT 0x29
+#define FXOS8700_CTRL_REG1 0x2a
+#define FXOS8700_CTRL_REG2 0x2b
+#define FXOS8700_CTRL_REG3 0x2c
+#define FXOS8700_CTRL_REG4 0x2d
+#define FXOS8700_CTRL_REG5 0x2e
+#define FXOS8700_OFF_X 0x2f
+#define FXOS8700_OFF_Y 0x30
+#define FXOS8700_OFF_Z 0x31
+#define FXOS8700_M_DR_STATUS 0x32
+#define FXOS8700_M_OUT_X_MSB 0x33
+#define FXOS8700_M_OUT_X_LSB 0x34
+#define FXOS8700_M_OUT_Y_MSB 0x35
+#define FXOS8700_M_OUT_Y_LSB 0x36
+#define FXOS8700_M_OUT_Z_MSB 0x37
+#define FXOS8700_M_OUT_Z_LSB 0x38
+#define FXOS8700_CMP_X_MSB 0x39
+#define FXOS8700_CMP_X_LSB 0x3a
+#define FXOS8700_CMP_Y_MSB 0x3b
+#define FXOS8700_CMP_Y_LSB 0x3c
+#define FXOS8700_CMP_Z_MSB 0x3d
+#define FXOS8700_CMP_Z_LSB 0x3e
+#define FXOS8700_M_OFF_X_MSB 0x3f
+#define FXOS8700_M_OFF_X_LSB 0x40
+#define FXOS8700_M_OFF_Y_MSB 0x41
+#define FXOS8700_M_OFF_Y_LSB 0x42
+#define FXOS8700_M_OFF_Z_MSB 0x43
+#define FXOS8700_M_OFF_Z_LSB 0x44
+#define FXOS8700_MAX_X_MSB 0x45
+#define FXOS8700_MAX_X_LSB 0x46
+#define FXOS8700_MAX_Y_MSB 0x47
+#define FXOS8700_MAX_Y_LSB 0x48
+#define FXOS8700_MAX_Z_MSB 0x49
+#define FXOS8700_MAX_Z_LSB 0x4a
+#define FXOS8700_MIN_X_MSB 0x4b
+#define FXOS8700_MIN_X_LSB 0x4c
+#define FXOS8700_MIN_Y_MSB 0x4d
+#define FXOS8700_MIN_Y_LSB 0x4e
+#define FXOS8700_MIN_Z_MSB 0x4f
+#define FXOS8700_MIN_Z_LSB 0x50
+#define FXOS8700_M_TEMP 0x51
+#define FXOS8700_MAG_THS_CFG 0x52
+#define FXOS8700_MAG_THS_SRC 0x53
+#define FXOS8700_MAG_THS_THS_X1 0x54
+#define FXOS8700_MAG_THS_THS_X0 0x55
+#define FXOS8700_MAG_THS_THS_Y1 0x56
+#define FXOS8700_MAG_THS_THS_Y0 0x57
+#define FXOS8700_MAG_THS_THS_Z1 0x58
+#define FXOS8700_MAG_THS_THS_Z0 0x59
+#define FXOS8700_MAG_THS_CUNT 0x5a
+#define FXOS8700_M_CTRL_REG1 0x5b
+#define FXOS8700_M_CTRL_REG2 0x5c
+#define FXOS8700_M_CTRL_REG3 0x5d
+#define FXOS8700_M_INT_SOURCE 0x5e
+#define FXOS8700_G_VECM_CFG 0x5f
+#define FXOS8700_G_VECM_THS_MSB 0x60
+#define FXOS8700_G_VECM_THS_LSB 0x61
+#define FXOS8700_G_VECM_CNT 0x62
+#define FXOS8700_G_VECM_INITX_MSB 0x63
+#define FXOS8700_G_VECM_INITX_LSB 0x64
+#define FXOS8700_G_VECM_INITY_MSB 0x65
+#define FXOS8700_G_VECM_INITY_LSB 0x66
+#define FXOS8700_G_VECM_INITZ_MSB 0x67
+#define FXOS8700_G_VECM_INITZ_LSB 0x68
+#define FXOS8700_M_VECM_CFG 0x69
+#define FXOS8700_M_VECM_THS_MSB 0x6a
+#define FXOS8700_M_VECM_THS_LSB 0x6b
+#define FXOS8700_M_VECM_CNT 0x6d
+#define FXOS8700_M_VECM_INITX_MSB 0x6d
+#define FXOS8700_M_VECM_INITX_LSB 0x6e
+#define FXOS8700_M_VECM_INITY_MSB 0x6f
+#define FXOS8700_M_VECM_INITY_LSB 0x70
+#define FXOS8700_M_VECM_INITZ_MSB 0x71
+#define FXOS8700_M_VECM_INITZ_LSB 0x72
+#define FXOS8700_G_FFMT_THS_X1 0x73
+#define FXOS8700_G_FFMT_THS_X0 0x74
+#define FXOS8700_G_FFMT_THS_Y1 0x75
+#define FXOS8700_G_FFMT_THS_Y0 0x76
+#define FXOS8700_G_FFMT_THS_Z1 0x77
+#define FXOS8700_G_FFMT_THS_Z0 0x78
+#define FXOS8700_G_TRAN_INIT_MSB 0x79
+#define FXOS8700_G_TRAN_INIT_LSB_X 0x7a
+#define FXOS8700_G_TRAN_INIT_LSB_Y 0x7b
+#define FXOS8700_G_TRAN_INIT_LSB_Z 0x7d
+#define FXOS8700_TM_NVM_LOCK 0x7e
+#define FXOS8700_NVM_DATA0_35 0x80
+#define FXOS8700_NVM_DATA_BNK3 0xa4
+#define FXOS8700_NVM_DATA_BNK2 0xa5
+#define FXOS8700_NVM_DATA_BNK1 0xa6
+#define FXOS8700_NVM_DATA_BNK0 0xa7
+
+#define SENSOR_IOCTL_BASE 'S'
+#define SENSOR_GET_MODEL_NAME _IOR(SENSOR_IOCTL_BASE, 0, char *)
+#define SENSOR_GET_POWER_STATUS _IOR(SENSOR_IOCTL_BASE, 2, int)
+#define SENSOR_SET_POWER_STATUS _IOR(SENSOR_IOCTL_BASE, 3, int)
+#define SENSOR_GET_DELAY_TIME _IOR(SENSOR_IOCTL_BASE, 4, int)
+#define SENSOR_SET_DELAY_TIME _IOR(SENSOR_IOCTL_BASE, 5, int)
+#define SENSOR_GET_RAW_DATA _IOR(SENSOR_IOCTL_BASE, 6, short[3])
+
+#define FXOS8700_I2C_ADDR 0x1E
+#define FXOS8700_DEVICE_ID 0xC7
+#define FXOS8700_PRE_DEVICE_ID 0xC4
+#define FXOS8700_DATA_BUF_SIZE 6
+#define FXOS8700_DELAY_DEFAULT 200 /* msecs */
+#define FXOS8700_POSITION_DEFAULT 1 /* msecs */
+
+#define FXOS8700_TYPE_ACC 0x00
+#define FXOS8700_TYPE_MAG 0x01
+#define FXOS8700_STANDBY 0x00
+#define FXOS8700_ACTIVED 0x01
+
+#define ABS_STATUS ABS_WHEEL
+#define FXOS8700_DRIVER "fxos8700"
+
+#define ABSMAX_ACC_VAL 0x01FF
+#define ABSMIN_ACC_VAL -(ABSMAX_ACC_VAL)
+#define FXOS8700_POLL_INTERVAL 400
+#define FXOS8700_POLL_MAX 800
+#define FXOS8700_POLL_MIN 100
+
+enum { MODE_2G = 0, MODE_4G, MODE_8G,
+};
+
+struct fxos8700_data_axis {
+ short x;
+ short y;
+ short z;
+};
+
+struct fxos8700_data {
+ struct i2c_client *client;
+ struct input_polled_dev *input_polled;
+ struct miscdevice *acc_miscdev;
+ struct miscdevice *mag_miscdev;
+ atomic_t acc_delay;
+ atomic_t mag_delay;
+ atomic_t acc_active;
+ atomic_t acc_active_poll;
+ atomic_t mag_active_poll;
+ atomic_t mag_active;
+ atomic_t position;
+ atomic_t range;
+};
+
+static struct fxos8700_data *g_fxos8700_data;
+static int fxos8700_position_settings[8][3][3] = {
+ { { 0, -1, 0}, { 1, 0, 0}, {0, 0, 1} },
+ { {-1, 0, 0}, { 0, -1, 0}, {0, 0, 1} },
+ { { 0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
+ { { 1, 0, 0}, { 0, 1, 0}, {0, 0, 1} },
+ { { 0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
+ { {-1, 0, 0}, { 0, 1, 0}, {0, 0, -1} },
+ { { 0, 1, 0}, { 1, 0, 0}, {0, 0, -1} },
+ { { 1, 0, 0}, { 0, -1, 0}, {0, 0, -1} },
+};
+
+static int fxos8700_data_convert(struct fxos8700_data_axis *axis_data, int position)
+{
+ short rawdata[3], data[3];
+ int i, j;
+ if (position < 0 || position > 7)
+ position = 0;
+ rawdata[0] = axis_data->x;
+ rawdata[1] = axis_data->y;
+ rawdata[2] = axis_data->z;
+ for (i = 0; i < 3 ; i++) {
+ data[i] = 0;
+ for (j = 0; j < 3; j++)
+ data[i] += rawdata[j] * fxos8700_position_settings[position][i][j];
+ }
+
+ axis_data->x = data[0];
+ axis_data->y = data[1];
+ axis_data->z = data[2];
+ return 0;
+}
+
+static int fxos8700_change_mode(struct i2c_client *client, int type, int active)
+{
+ u8 data;
+ int acc_act, mag_act;
+ struct fxos8700_data *pdata = i2c_get_clientdata(client);
+
+ acc_act = atomic_read(&pdata->acc_active);
+ mag_act = atomic_read(&pdata->mag_active);
+ data = i2c_smbus_read_byte_data(client, FXOS8700_CTRL_REG1);
+ if (type == FXOS8700_TYPE_ACC)
+ acc_act = active;
+ else
+ mag_act = active;
+ if (acc_act == FXOS8700_ACTIVED || mag_act == FXOS8700_ACTIVED)
+ data |= 0x01;
+ else
+ data &= ~0x01;
+ i2c_smbus_write_byte_data(client, FXOS8700_CTRL_REG1, data);
+
+ return 0;
+}
+
+static int fxos8700_change_range(struct i2c_client *client, int range)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, FXOS8700_XYZ_DATA_CFG, range);
+
+ return ret;
+}
+static int fxos8700_set_odr(struct i2c_client *client, int type, int delay)
+{
+ return 0;
+}
+
+static int fxos8700_device_init(struct i2c_client *client)
+{
+ int result;
+ struct fxos8700_data *pdata = i2c_get_clientdata(client);
+
+ /* standby mode */
+ result = i2c_smbus_write_byte_data(client, FXOS8700_CTRL_REG1, 0x00);
+ if (result < 0)
+ goto out;
+ result = i2c_smbus_write_byte_data(client, FXOS8700_M_CTRL_REG1, 0x1F);
+ if (result < 0)
+ goto out;
+ result = i2c_smbus_write_byte_data(client, FXOS8700_M_CTRL_REG2, 0x5c);
+ if (result < 0)
+ goto out;
+ result = i2c_smbus_write_byte_data(client, FXOS8700_CTRL_REG1, 0x03 << 3);
+ if (result < 0)
+ goto out;
+ result = i2c_smbus_write_byte_data(client, FXOS8700_XYZ_DATA_CFG,
+ MODE_2G);
+ if (result < 0)
+ goto out;
+
+ atomic_set(&pdata->acc_active, FXOS8700_STANDBY);
+ atomic_set(&pdata->mag_active, FXOS8700_STANDBY);
+ atomic_set(&pdata->position, FXOS8700_POSITION_DEFAULT);
+ atomic_set(&pdata->range, MODE_2G);
+ return 0;
+out:
+ dev_err(&client->dev, "Error when init fxos8700 device:(%d)", result);
+ return result;
+}
+
+static int fxos8700_device_stop(struct i2c_client *client)
+{
+ i2c_smbus_write_byte_data(client, FXOS8700_CTRL_REG1, 0x00);
+ return 0;
+}
+
+static int
+fxos8700_read_data(struct i2c_client *client, struct fxos8700_data_axis *data, int type)
+{
+ u8 tmp_data[FXOS8700_DATA_BUF_SIZE];
+ int ret;
+ u8 reg;
+
+ if (type == FXOS8700_TYPE_ACC)
+ reg = FXOS8700_OUT_X_MSB;
+ else
+ reg = FXOS8700_M_OUT_X_MSB;
+
+ ret = i2c_smbus_read_i2c_block_data(client, reg, FXOS8700_DATA_BUF_SIZE, tmp_data);
+ if (ret < FXOS8700_DATA_BUF_SIZE) {
+ dev_err(&client->dev, "i2c block read %s failed\n",
+ (type == FXOS8700_TYPE_ACC ? "acc" : "mag"));
+ return -EIO;
+ }
+ data->x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+ data->y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+ data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+ return 0;
+}
+
+static long fxos8700_acc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct fxos8700_data *pdata = file->private_data;
+ void __user *argp = (void __user *)arg;
+ struct fxos8700_data_axis data;
+ long ret = 0;
+ short sdata[3];
+ int enable;
+ int delay;
+ int position;
+
+ if (!pdata) {
+ printk(KERN_ERR "fxos8700 struct datt point is NULL.");
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+ case SENSOR_GET_MODEL_NAME:
+ if (copy_to_user(argp, "FXOS8700 ACC", strlen("FXOS8700 ACC") + 1)) {
+ printk(KERN_ERR "SENSOR_GET_MODEL_NAME copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ break;
+ case SENSOR_GET_POWER_STATUS:
+ enable = atomic_read(&pdata->acc_active);
+ if (copy_to_user(argp, &enable, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_SET_POWER_STATUS copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ break;
+ case SENSOR_SET_POWER_STATUS:
+ if (copy_from_user(&enable, argp, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_SET_POWER_STATUS copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ if (pdata->client) {
+ ret = fxos8700_change_mode(pdata->client, FXOS8700_TYPE_ACC,
+ enable ? FXOS8700_ACTIVED : FXOS8700_STANDBY);
+ if (!ret)
+ atomic_set(&pdata->acc_active, enable);
+ }
+ break;
+ case SENSOR_GET_DELAY_TIME:
+ delay = atomic_read(&pdata->acc_delay);
+ if (copy_to_user(argp, &delay, sizeof(delay))) {
+ printk(KERN_ERR "SENSOR_GET_DELAY_TIME copy_to_user failed.");
+ return -EFAULT;
+ }
+ break;
+ case SENSOR_SET_DELAY_TIME:
+ if (copy_from_user(&delay, argp, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_SET_DELAY_TIME copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ if (pdata->client && delay > 0 && delay <= 500) {
+ ret = fxos8700_set_odr(pdata->client, FXOS8700_TYPE_ACC, delay);
+ if (!ret)
+ atomic_set(&pdata->acc_delay, delay);
+ }
+ break;
+ case SENSOR_GET_RAW_DATA:
+ position = atomic_read(&pdata->position);
+ ret = fxos8700_read_data(pdata->client, &data, FXOS8700_TYPE_ACC);
+ if (!ret) {
+ fxos8700_data_convert(&data, position);
+ sdata[0] = data.x;
+ sdata[1] = data.y;
+ sdata[2] = data.z;
+ if (copy_to_user(argp, sdata, sizeof(sdata))) {
+ printk(KERN_ERR "SENSOR_GET_RAW_DATA copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ }
+ break;
+ default:
+ ret = -1;
+ }
+ return ret;
+}
+
+static int fxos8700_acc_open(struct inode *inode, struct file *file)
+{
+ file->private_data = g_fxos8700_data;
+ return nonseekable_open(inode, file);
+}
+
+static int fxos8700_acc_release(struct inode *inode, struct file *file)
+{
+ /* note: releasing the wdt in NOWAYOUT-mode does not stop it */
+ return 0;
+}
+
+static const struct file_operations fxos8700_acc_fops = {
+ .owner = THIS_MODULE,
+ .open = fxos8700_acc_open,
+ .release = fxos8700_acc_release,
+ .unlocked_ioctl = fxos8700_acc_ioctl,
+};
+
+/* mag char miscdevice */
+static long fxos8700_mag_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct fxos8700_data *pdata = file->private_data;
+ void __user *argp = (void __user *)arg;
+ struct fxos8700_data_axis data;
+ long ret = 0;
+ short sdata[3];
+ int enable;
+ int delay;
+ int position;
+
+ if (!pdata) {
+ printk(KERN_ERR "fxos8700 struct datt point is NULL.");
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+ case SENSOR_GET_MODEL_NAME:
+ if (copy_to_user(argp, "FXOS8700 MAG", strlen("FXOS8700 MAG") + 1)) {
+ printk(KERN_ERR "SENSOR_GET_MODEL_NAME copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ break;
+ case SENSOR_GET_POWER_STATUS:
+ enable = atomic_read(&pdata->mag_active);
+ if (copy_to_user(argp, &enable, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_SET_POWER_STATUS copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ break;
+ case SENSOR_SET_POWER_STATUS:
+ if (copy_from_user(&enable, argp, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_SET_POWER_STATUS copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ if (pdata->client) {
+ ret = fxos8700_change_mode(pdata->client, FXOS8700_TYPE_MAG,
+ enable ? FXOS8700_ACTIVED : FXOS8700_STANDBY);
+ if (!ret)
+ atomic_set(&pdata->mag_active, enable);
+ }
+ break;
+ case SENSOR_GET_DELAY_TIME:
+ delay = atomic_read(&pdata->mag_delay);
+ if (copy_to_user(argp, &delay, sizeof(delay))) {
+ printk(KERN_ERR "SENSOR_GET_DELAY_TIME copy_to_user failed.");
+ return -EFAULT;
+ }
+ break;
+ case SENSOR_SET_DELAY_TIME:
+ if (copy_from_user(&delay, argp, sizeof(int))) {
+ printk(KERN_ERR "SENSOR_SET_DELAY_TIME copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ if (pdata->client && delay > 0 && delay <= 500) {
+ ret = fxos8700_set_odr(pdata->client, FXOS8700_TYPE_MAG, delay);
+ if (!ret)
+ atomic_set(&pdata->mag_delay, delay);
+ }
+ break;
+ case SENSOR_GET_RAW_DATA:
+ position = atomic_read(&pdata->position);
+ ret = fxos8700_read_data(pdata->client, &data, FXOS8700_TYPE_MAG);
+ if (!ret) {
+ fxos8700_data_convert(&data, position);
+ sdata[0] = data.x;
+ sdata[1] = data.y;
+ sdata[2] = data.z;
+ if (copy_to_user(argp, sdata, sizeof(sdata))) {
+ printk(KERN_ERR "SENSOR_GET_RAW_DATA copy_to_user failed.");
+ ret = -EFAULT;
+ }
+ }
+ break;
+ default:
+ ret = -1;
+ }
+ return ret;
+}
+
+static int fxos8700_mag_open(struct inode *inode, struct file *file)
+{
+ file->private_data = g_fxos8700_data;
+ return nonseekable_open(inode, file);
+}
+
+static int fxos8700_mag_release(struct inode *inode, struct file *file)
+{
+ /* note: releasing the wdt in NOWAYOUT-mode does not stop it */
+ return 0;
+}
+
+static const struct file_operations fxos8700_mag_fops = {
+ .owner = THIS_MODULE,
+ .open = fxos8700_mag_open,
+ .release = fxos8700_mag_release,
+ .unlocked_ioctl = fxos8700_mag_ioctl,
+};
+
+static struct miscdevice fxos8700_acc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "FreescaleAccelerometer",
+ .fops = &fxos8700_acc_fops,
+};
+
+static struct miscdevice fxos8700_mag_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "FreescaleMagnetometer",
+ .fops = &fxos8700_mag_fops,
+};
+
+static ssize_t fxos8700_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct miscdevice *misc_dev = dev_get_drvdata(dev);
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ int enable = 0;
+
+ if (pdata->acc_miscdev == misc_dev)
+ enable = atomic_read(&pdata->acc_active);
+ if (pdata->mag_miscdev == misc_dev)
+ enable = atomic_read(&pdata->mag_active);
+
+ return sprintf(buf, "%d\n", enable);
+}
+
+static ssize_t fxos8700_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct miscdevice *misc_dev = dev_get_drvdata(dev);
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ struct i2c_client *client = pdata->client;
+ unsigned long enable;
+ int type;
+ int ret;
+
+ if (kstrtoul(buf, 10, &enable) < 0)
+ return -EINVAL;
+
+ if (misc_dev == pdata->acc_miscdev)
+ type = FXOS8700_TYPE_ACC;
+ if (misc_dev == pdata->mag_miscdev)
+ type = FXOS8700_TYPE_MAG;
+ enable = (enable > 0 ? FXOS8700_ACTIVED : FXOS8700_STANDBY);
+ ret = fxos8700_change_mode(client, type, enable);
+ if (!ret) {
+ if (type == FXOS8700_TYPE_ACC) {
+ atomic_set(&pdata->acc_active, enable);
+ atomic_set(&pdata->acc_active_poll, enable);
+ } else {
+ atomic_set(&pdata->mag_active, enable);
+ atomic_set(&pdata->mag_active_poll, enable);
+ }
+ }
+ return count;
+}
+
+static ssize_t fxos8700_poll_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct miscdevice *misc_dev = dev_get_drvdata(dev);
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ int poll_delay = 0;
+
+ if (pdata->acc_miscdev == misc_dev)
+ poll_delay = atomic_read(&pdata->acc_delay);
+ if (pdata->mag_miscdev == misc_dev)
+ poll_delay = atomic_read(&pdata->mag_delay);
+
+ return sprintf(buf, "%d\n", poll_delay);
+}
+
+
+static ssize_t fxos8700_poll_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct miscdevice *misc_dev = dev_get_drvdata(dev);
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ struct i2c_client *client = pdata->client;
+ unsigned long delay;
+ int type;
+ int ret;
+
+ if (kstrtoul(buf, 10, &delay) < 0)
+ return -EINVAL;
+
+ if (misc_dev == pdata->acc_miscdev)
+ type = FXOS8700_TYPE_ACC;
+ if (misc_dev == pdata->mag_miscdev)
+ type = FXOS8700_TYPE_MAG;
+ ret = fxos8700_set_odr(client, type, delay);
+ if (!ret) {
+ if (type == FXOS8700_TYPE_ACC)
+ atomic_set(&pdata->acc_delay, delay);
+ else
+ atomic_set(&pdata->mag_delay, delay);
+ }
+ return count;
+}
+
+static ssize_t fxos8700_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ unsigned long position = atomic_read(&pdata->position);
+
+ return sprintf(buf, "%ld\n", position);
+}
+
+static ssize_t fxos8700_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long position;
+ struct fxos8700_data *pdata = g_fxos8700_data;
+
+ if (kstrtoul(buf, 10, &position) < 0)
+ return -EINVAL;
+
+ atomic_set(&pdata->position, position);
+ return count;
+}
+
+static ssize_t fxos8700_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ unsigned long range = atomic_read(&pdata->range);
+
+ return sprintf(buf, "%ld\n", range);
+}
+
+static ssize_t fxos8700_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long range;
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ struct i2c_client *client = pdata->client;
+ int ret;
+
+ if (kstrtoul(buf, 10, &range) < 0)
+ return -EINVAL;
+
+ if (range == atomic_read(&pdata->range))
+ return count;
+
+ if (atomic_read(&pdata->acc_active) | atomic_read(&pdata->mag_active))
+ printk(KERN_INFO "Pls set the sensor standby and then actived\n");
+ ret = fxos8700_change_range(client, range);
+ if (!ret)
+ atomic_set(&pdata->range, range);
+
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, fxos8700_enable_show, fxos8700_enable_store);
+static DEVICE_ATTR(poll_delay, S_IWUSR | S_IRUGO, fxos8700_poll_delay_show, fxos8700_poll_delay_store);
+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, fxos8700_position_show, fxos8700_position_store);
+static DEVICE_ATTR(range, S_IWUSR | S_IRUGO, fxos8700_range_show, fxos8700_range_store);
+
+static struct attribute *fxos8700_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_poll_delay.attr,
+ &dev_attr_position.attr,
+ &dev_attr_range.attr,
+ NULL
+};
+
+static const struct attribute_group fxos8700_attr_group = {
+ .attrs = fxos8700_attributes,
+};
+
+static int fxos8700_register_sysfs_device(struct fxos8700_data *pdata)
+{
+ struct miscdevice *misc_dev = NULL;
+ int err = -1;
+
+ /* register sysfs for acc */
+ misc_dev = pdata->acc_miscdev;
+ err = sysfs_create_group(&misc_dev->this_device->kobj, &fxos8700_attr_group);
+ if (err)
+ goto out;
+
+ /* register sysfs for mag */
+ misc_dev = pdata->mag_miscdev;
+ err = sysfs_create_group(&misc_dev->this_device->kobj, &fxos8700_attr_group);
+ if (err)
+ goto err_register_sysfs;
+ return 0;
+err_register_sysfs:
+ misc_dev = pdata->acc_miscdev;
+ sysfs_remove_group(&misc_dev->this_device->kobj, &fxos8700_attr_group);
+ printk("reigster mag sysfs error\n");
+out:
+ printk("reigster acc sysfs error\n");
+ return err;
+}
+
+static int fxos8700_unregister_sysfs_device(struct fxos8700_data *pdata)
+{
+ struct miscdevice *misc_dev;
+ misc_dev = pdata->acc_miscdev;
+ sysfs_remove_group(&misc_dev->this_device->kobj, &fxos8700_attr_group);
+
+ misc_dev = pdata->mag_miscdev;
+ sysfs_remove_group(&misc_dev->this_device->kobj, &fxos8700_attr_group);
+ return 0;
+}
+
+static void fxos8700_report(struct input_polled_dev *dev, int type)
+{
+ struct fxos8700_data_axis data;
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ struct input_dev *idev = pdata->input_polled->input;
+ int position;
+ int ret;
+
+ position = atomic_read(&pdata->position);
+ ret = fxos8700_read_data(pdata->client, &data, type);
+ if (!ret) {
+ fxos8700_data_convert(&data, position);
+ input_report_abs(idev, ABS_X, data.x);
+ input_report_abs(idev, ABS_Y, data.y);
+ input_report_abs(idev, ABS_Z, data.z);
+ input_sync(idev);
+ }
+}
+
+static void fxos8700_poll(struct input_polled_dev *dev)
+{
+ struct fxos8700_data *pdata = g_fxos8700_data;
+ int type;
+
+ if (!(atomic_read(&pdata->acc_active_poll) ||
+ atomic_read(&pdata->mag_active_poll)))
+ return;
+
+ if (atomic_read(&pdata->acc_active_poll))
+ type = FXOS8700_TYPE_ACC;
+ if (atomic_read(&pdata->mag_active_poll))
+ type =FXOS8700_TYPE_MAG;
+ fxos8700_report(dev, type);
+}
+
+static int fxo8700_register_polled_device(struct fxos8700_data *pdata)
+{
+ struct input_polled_dev *ipoll_dev;
+ struct input_dev *idev;
+ int error;
+
+ ipoll_dev = input_allocate_polled_device();
+ if (!ipoll_dev)
+ return -ENOMEM;
+
+ ipoll_dev->private = pdata;
+ ipoll_dev->poll = fxos8700_poll;
+ ipoll_dev->poll_interval = FXOS8700_POLL_INTERVAL;
+ ipoll_dev->poll_interval_min = FXOS8700_POLL_MIN;
+ ipoll_dev->poll_interval_max = FXOS8700_POLL_MAX;
+ idev = ipoll_dev->input;
+ idev->name = FXOS8700_DRIVER;
+ idev->id.bustype = BUS_I2C;
+ idev->dev.parent = &pdata->client->dev;
+
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+ input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+ input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+
+ error = input_register_polled_device(ipoll_dev);
+ if (error) {
+ input_free_polled_device(ipoll_dev);
+ return error;
+ }
+
+ pdata->input_polled = ipoll_dev;
+
+ return 0;
+}
+
+static int fxos8700_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result, client_id;
+ struct fxos8700_data *pdata;
+ struct i2c_adapter *adapter;
+
+ adapter = to_i2c_adapter(client->dev.parent);
+ result = i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA);
+ if (!result)
+ goto err_out;
+
+ client_id = i2c_smbus_read_byte_data(client, FXOS8700_WHO_AM_I);
+ if (client_id != FXOS8700_DEVICE_ID && client_id != FXOS8700_PRE_DEVICE_ID) {
+ dev_err(&client->dev,
+ "read chip ID 0x%x is not equal to 0x%x or 0x%x\n",
+ result, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);
+ result = -EINVAL;
+ goto err_out;
+ }
+ pdata = kzalloc(sizeof(struct fxos8700_data), GFP_KERNEL);
+ if (!pdata) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "alloc data memory error!\n");
+ goto err_out;
+ }
+ g_fxos8700_data = pdata;
+ pdata->client = client;
+ atomic_set(&pdata->acc_delay, FXOS8700_DELAY_DEFAULT);
+ atomic_set(&pdata->mag_delay, FXOS8700_DELAY_DEFAULT);
+ i2c_set_clientdata(client, pdata);
+
+ result = misc_register(&fxos8700_acc_device);
+ if (result != 0) {
+ printk(KERN_ERR "register acc miscdevice error");
+ goto err_regsiter_acc_misc;
+ }
+ pdata->acc_miscdev = &fxos8700_acc_device;
+
+ result = misc_register(&fxos8700_mag_device);
+ if (result != 0) {
+ printk(KERN_ERR "register acc miscdevice error");
+ goto err_regsiter_mag_misc;
+ }
+ pdata->mag_miscdev = &fxos8700_mag_device;
+
+ /* for debug */
+ if (client->irq <= 0) {
+ result = fxo8700_register_polled_device(g_fxos8700_data);
+ if (result)
+ dev_err(&client->dev,
+ "IRQ GPIO conf. error %d, error %d\n",
+ client->irq, result);
+ }
+
+ result = fxos8700_register_sysfs_device(pdata);
+ if (result) {
+ dev_err(&client->dev, "create device file failed!\n");
+ result = -EINVAL;
+ goto err_register_sys;
+ }
+ fxos8700_device_init(client);
+ printk("fxos8700 device driver probe successfully");
+ return 0;
+err_register_sys:
+ misc_deregister(&fxos8700_mag_device);
+ pdata->mag_miscdev = NULL;
+err_regsiter_mag_misc:
+ misc_deregister(&fxos8700_acc_device);
+ pdata->acc_miscdev = NULL;
+err_regsiter_acc_misc:
+ i2c_set_clientdata(client, NULL);
+ kfree(pdata);
+err_out:
+ return result;
+}
+
+static int fxos8700_remove(struct i2c_client *client)
+{
+ struct fxos8700_data *pdata = i2c_get_clientdata(client);
+ if (!pdata)
+ return 0;
+ fxos8700_device_stop(client);
+ if (client->irq <= 0) {
+ input_unregister_polled_device(pdata->input_polled);
+ input_free_polled_device(pdata->input_polled);
+ }
+ fxos8700_unregister_sysfs_device(pdata);
+ misc_deregister(&fxos8700_acc_device);
+ misc_deregister(&fxos8700_mag_device);
+ kfree(pdata);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int fxos8700_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fxos8700_data *pdata = i2c_get_clientdata(client);
+ if (atomic_read(&pdata->acc_active) || atomic_read(&pdata->mag_active))
+ fxos8700_device_stop(client);
+ return 0;
+}
+
+static int fxos8700_resume(struct device *dev)
+{
+ int ret = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fxos8700_data *pdata = i2c_get_clientdata(client);
+ if (atomic_read(&pdata->acc_active))
+ fxos8700_change_mode(client, FXOS8700_TYPE_ACC, FXOS8700_ACTIVED);
+ if (atomic_read(&pdata->mag_active))
+ fxos8700_change_mode(client, FXOS8700_TYPE_MAG, FXOS8700_ACTIVED);
+ return ret;
+}
+#endif
+
+static const struct i2c_device_id fxos8700_id[] = {
+ {"fxos8700", 0},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, fxos8700_id);
+
+static SIMPLE_DEV_PM_OPS(fxos8700_pm_ops, fxos8700_suspend, fxos8700_resume);
+static struct i2c_driver fxos8700_driver = {
+ .driver = {
+ .name = FXOS8700_DRIVER,
+ .owner = THIS_MODULE,
+ .pm = &fxos8700_pm_ops,
+ },
+ .probe = fxos8700_probe,
+ .remove = fxos8700_remove,
+ .id_table = fxos8700_id,
+};
+
+module_i2c_driver(fxos8700_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index f84b53d6ce50..6c02b3dba583 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -26,7 +26,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#define SRAM_GRANULARITY 32
+#define SRAM_GRANULARITY 4096
struct sram_partition {
void __iomem *base;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 709a872ed484..fb674d8c3fcc 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2225,7 +2225,14 @@ again:
return ERR_PTR(-ENOMEM);
spin_lock(&mmc_blk_lock);
- ret = ida_get_new(&mmc_blk_ida, &devidx);
+ devidx = mmc_get_reserved_index(card->host);
+ if (devidx >= 0)
+ devidx = ida_simple_get(&mmc_blk_ida, devidx, devidx,
+ GFP_NOWAIT);
+ ret = 0;
+ if (devidx < 0)
+ ret = ida_get_new_above(&mmc_blk_ida,
+ mmc_first_nonreserved_index(), &devidx);
spin_unlock(&mmc_blk_lock);
if (ret == -EAGAIN)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 2553d903a82b..a4439305bc4d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -16,6 +16,7 @@
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/of.h>
#include <linux/pagemap.h>
#include <linux/err.h>
#include <linux/leds.h>
@@ -2832,7 +2833,8 @@ void mmc_start_host(struct mmc_host *host)
mmc_release_host(host);
mmc_gpiod_request_cd_irq(host);
- _mmc_detect_change(host, 0, false);
+ if (!(host->caps2 & MMC_CAP2_CD_POST))
+ _mmc_detect_change(host, 0, false);
}
void mmc_stop_host(struct mmc_host *host)
@@ -3026,10 +3028,49 @@ void mmc_init_context_info(struct mmc_host *host)
init_waitqueue_head(&host->context_info.wait);
}
+static int __mmc_max_reserved_idx = -1;
+
+/**
+ * mmc_first_nonreserved_index() - get the first index that is not reserved
+ */
+int mmc_first_nonreserved_index(void)
+{
+ return __mmc_max_reserved_idx + 1;
+}
+EXPORT_SYMBOL(mmc_first_nonreserved_index);
+
+/**
+ * mmc_get_reserved_index() - get the index reserved for this host
+ *
+ * Return: The index reserved for this host or negative error value if
+ * no index is reserved for this host
+ */
+int mmc_get_reserved_index(struct mmc_host *host)
+{
+ return of_alias_get_id(host->parent->of_node, "mmc");
+}
+EXPORT_SYMBOL(mmc_get_reserved_index);
+
+static void mmc_of_reserve_idx(void)
+{
+ int max;
+
+ max = of_alias_max_index("mmc");
+ if (max < 0)
+ return;
+
+ __mmc_max_reserved_idx = max;
+
+ pr_debug("MMC: reserving %d slots for of aliases\n",
+ __mmc_max_reserved_idx + 1);
+}
+
static int __init mmc_init(void)
{
int ret;
+ mmc_of_reserve_idx();
+
ret = mmc_register_bus();
if (ret)
return ret;
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index c8451ce557ae..01b35c0d0d36 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -56,6 +56,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
struct mmc_ios *ios = &host->ios;
const char *str;
+ if (host->card)
+ mmc_get_card(host->card);
+
seq_printf(s, "clock:\t\t%u Hz\n", ios->clock);
if (host->actual_clock)
seq_printf(s, "actual clock:\t%u Hz\n", host->actual_clock);
@@ -192,6 +195,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
}
seq_printf(s, "driver type:\t%u (%s)\n", ios->drv_type, str);
+ if (host->card)
+ mmc_put_card(host->card);
+
return 0;
}
@@ -211,7 +217,11 @@ static int mmc_clock_opt_get(void *data, u64 *val)
{
struct mmc_host *host = data;
+ if (host->card)
+ mmc_get_card(host->card);
*val = host->ios.clock;
+ if (host->card)
+ mmc_put_card(host->card);
return 0;
}
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 848b3453517e..f0dcddc34997 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -228,6 +228,8 @@ int mmc_of_parse(struct mmc_host *host)
/* Parse Card Detection */
if (device_property_read_bool(dev, "non-removable")) {
host->caps |= MMC_CAP_NONREMOVABLE;
+ if (device_property_read_bool(dev, "cd-post"))
+ host->caps2 |= MMC_CAP2_CD_POST;
} else {
cd_cap_invert = device_property_read_bool(dev, "cd-inverted");
@@ -299,6 +301,8 @@ int mmc_of_parse(struct mmc_host *host)
if (device_property_read_bool(dev, "wakeup-source") ||
device_property_read_bool(dev, "enable-sdio-wakeup")) /* legacy */
host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+ if (device_property_read_bool(dev, "pm-ignore-notify"))
+ host->pm_caps |= MMC_PM_IGNORE_PM_NOTIFY;
if (device_property_read_bool(dev, "mmc-ddr-1_8v"))
host->caps |= MMC_CAP_1_8V_DDR;
if (device_property_read_bool(dev, "mmc-ddr-1_2v"))
@@ -333,6 +337,8 @@ int mmc_of_parse(struct mmc_host *host)
EXPORT_SYMBOL(mmc_of_parse);
+int mmc_max_reserved_idx(void);
+
/**
* mmc_alloc_host - initialise the per-host structure.
* @extra: sizeof private data structure
@@ -344,6 +350,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
int err;
struct mmc_host *host;
+ int alias_id, min_idx, max_idx;
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host)
@@ -351,6 +358,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
/* scanning will be enabled when we're ready */
host->rescan_disable = 1;
+ host->parent = dev;
again:
if (!ida_pre_get(&mmc_host_ida, GFP_KERNEL)) {
@@ -359,7 +367,24 @@ again:
}
spin_lock(&mmc_host_lock);
- err = ida_get_new(&mmc_host_ida, &host->index);
+
+ alias_id = mmc_get_reserved_index(host);
+ if (alias_id >= 0) {
+ min_idx = alias_id;
+ max_idx = alias_id + 1;
+ } else {
+ min_idx = mmc_first_nonreserved_index();
+ max_idx = 0;
+ }
+
+ err = ida_get_new_above(&mmc_host_ida, min_idx, &host->index);
+ if (!err) {
+ if (host->index > max_idx) {
+ ida_remove(&mmc_host_ida, host->index);
+ err = -ENOSPC;
+ }
+ }
+
spin_unlock(&mmc_host_lock);
if (err == -EAGAIN) {
@@ -371,7 +396,6 @@ again:
dev_set_name(&host->class_dev, "mmc%d", host->index);
- host->parent = dev;
host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class;
device_initialize(&host->class_dev);
@@ -429,7 +453,8 @@ int mmc_add_host(struct mmc_host *host)
#endif
mmc_start_host(host);
- mmc_register_pm_notifier(host);
+ if (!(host->pm_caps& MMC_PM_IGNORE_PM_NOTIFY))
+ mmc_register_pm_notifier(host);
return 0;
}
@@ -446,7 +471,8 @@ EXPORT_SYMBOL(mmc_add_host);
*/
void mmc_remove_host(struct mmc_host *host)
{
- mmc_unregister_pm_notifier(host);
+ if (!(host->pm_caps& MMC_PM_IGNORE_PM_NOTIFY))
+ mmc_unregister_pm_notifier(host);
mmc_stop_host(host);
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index ad6e9798e949..fd389cb1efd9 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -523,6 +523,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
goto out;
/*
+ * WORKAROUND: for Sandisk eMMC cards, it might need certain delay
+ * before sending CMD13 after CMD6
+ */
+ mdelay(1);
+
+ /*
* CRC errors shall only be ignored in cases were CMD13 is used to poll
* to detect busy completion.
*/
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index f09148a4ab55..c24665968cc2 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -485,6 +485,13 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
else {
mmc_set_timing(card->host, timing);
mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr);
+
+ /*
+ * FIXME: Sandisk SD3.0 cards DDR50 mode requires such
+ * delay to get stable, without this delay we may encounter
+ * CRC errors after switch to DDR50 mode
+ */
+ mmc_delay(100);
}
return 0;
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index bd44ba8116d1..9e4951fbcfe4 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -784,6 +784,37 @@ err:
return err;
}
+int sdio_reset_comm(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ u32 ocr;
+ u32 rocr;
+ int err;
+
+ mmc_claim_host(host);
+ mmc_go_idle(host);
+ mmc_set_clock(host, host->f_min);
+ err = mmc_send_io_op_cond(host, 0, &ocr);
+ if (err)
+ goto err;
+ rocr = mmc_select_voltage(host, ocr);
+ if (!rocr) {
+ err = -EINVAL;
+ goto err;
+ }
+ err = mmc_sdio_init_card(host, rocr, card, 0);
+ if (err)
+ goto err;
+ mmc_release_host(host);
+ return 0;
+err:
+ pr_err("%s: Error resetting SDIO communications (%d)\n",
+ mmc_hostname(host), err);
+ mmc_release_host(host);
+ return err;
+}
+EXPORT_SYMBOL(sdio_reset_comm);
+
/*
* Host is being removed. Free up the current card.
*/
@@ -802,9 +833,22 @@ static void mmc_sdio_remove(struct mmc_host *host)
}
mmc_remove_card(host->card);
+ /* clear rescan_entered in case force remove */
+ host->rescan_entered = 0;
host->card = NULL;
}
+void mmc_sdio_force_remove(struct mmc_host *host)
+{
+ mmc_sdio_remove(host);
+
+ mmc_claim_host(host);
+ mmc_detach_bus(host);
+ mmc_power_off(host);
+ mmc_release_host(host);
+}
+EXPORT_SYMBOL_GPL(mmc_sdio_force_remove);
+
/*
* Card detection - card is alive.
*/
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 5274f503a39a..28123c52ba06 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -178,7 +178,7 @@ config MMC_SDHCI_CNS3XXX
config MMC_SDHCI_ESDHC_IMX
tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
- depends on ARCH_MXC
+ depends on ARCH_MXC || COMPILE_TEST
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
help
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 445fc47dc3e7..df5efd381b8d 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -11,12 +11,14 @@
* the Free Software Foundation; either version 2 of the License.
*/
+#include <linux/busfreq-imx.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/module.h>
+#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
@@ -69,6 +71,7 @@
#define ESDHC_STROBE_DLL_CTRL 0x70
#define ESDHC_STROBE_DLL_CTRL_ENABLE (1 << 0)
#define ESDHC_STROBE_DLL_CTRL_RESET (1 << 1)
+#define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET 0x7
#define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT 3
#define ESDHC_STROBE_DLL_STATUS 0x74
@@ -141,9 +144,35 @@
/* The IP supports HS400 mode */
#define ESDHC_FLAG_HS400 BIT(9)
+/* The IP state got lost in low power mode */
+#define ESDHC_FLAG_STATE_LOST_IN_LPMODE BIT(10)
+
+/* The IP has errata ERR010450
+ * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't
+ * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
+ */
+#define ESDHC_FLAG_ERR010450 BIT(11)
+/* need request bus freq during low power */
+#define ESDHC_FLAG_BUSFREQ BIT(12)
+/* need request pmqos during low power */
+#define ESDHC_FLAG_PMQOS BIT(13)
+
/* A higher clock ferquency than this rate requires strobell dll control */
#define ESDHC_STROBE_DLL_CLK_FREQ 100000000
+static struct mmc_host *wifi_mmc_host;
+void wifi_card_detect(bool on)
+{
+ WARN_ON(!wifi_mmc_host);
+ if (on) {
+ mmc_detect_change(wifi_mmc_host, 0);
+ } else {
+ if (wifi_mmc_host->card)
+ mmc_sdio_force_remove(wifi_mmc_host);
+ }
+}
+EXPORT_SYMBOL(wifi_card_detect);
+
struct esdhc_soc_data {
u32 flags;
};
@@ -171,18 +200,36 @@ static struct esdhc_soc_data usdhc_imx6q_data = {
static struct esdhc_soc_data usdhc_imx6sl_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536
- | ESDHC_FLAG_HS200,
+ | ESDHC_FLAG_HS200 | ESDHC_FLAG_BUSFREQ,
};
static struct esdhc_soc_data usdhc_imx6sx_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
- | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200,
+ | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+ | ESDHC_FLAG_STATE_LOST_IN_LPMODE
+ | ESDHC_FLAG_BUSFREQ,
+};
+
+static struct esdhc_soc_data usdhc_imx6ull_data = {
+ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+ | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+ | ESDHC_FLAG_STATE_LOST_IN_LPMODE
+ | ESDHC_FLAG_ERR010450
+ | ESDHC_FLAG_BUSFREQ,
};
static struct esdhc_soc_data usdhc_imx7d_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
- | ESDHC_FLAG_HS400,
+ | ESDHC_FLAG_HS400 | ESDHC_FLAG_STATE_LOST_IN_LPMODE
+ | ESDHC_FLAG_BUSFREQ,
+};
+
+static struct esdhc_soc_data usdhc_imx7ulp_data = {
+ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+ | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+ | ESDHC_FLAG_STATE_LOST_IN_LPMODE
+ | ESDHC_FLAG_PMQOS,
};
struct pltfm_imx_data {
@@ -202,6 +249,7 @@ struct pltfm_imx_data {
WAIT_FOR_INT, /* sent CMD12, waiting for response INT */
} multiblock_status;
u32 is_ddr;
+ struct pm_qos_request pm_qos_req;
};
static const struct platform_device_id imx_esdhc_devtype[] = {
@@ -228,7 +276,9 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
{ .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, },
{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
{ .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
+ { .compatible = "fsl,imx6ull-usdhc", .data = &usdhc_imx6ull_data, },
{ .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, },
+ { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
@@ -609,6 +659,13 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
mask = 0xffff & ~(ESDHC_CTRL_BUSWIDTH_MASK | ESDHC_CTRL_D3CD);
esdhc_clrset_le(host, mask, new_val, reg);
+
+ /*
+ * The imx6q ROM code will change the default watermark
+ * level setting to something insane. Change it back here.
+ */
+ if (esdhc_is_usdhc(imx_data))
+ writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
return;
}
esdhc_clrset_le(host, 0xff, val, reg);
@@ -680,6 +737,13 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+ if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) {
+ if (imx_data->is_ddr)
+ clock = clock > 45000000 ? 45000000 : clock;
+ else
+ clock = clock > 150000000 ? 150000000 : clock;
+ }
+
while (host_clock / pre_div / 16 > clock && pre_div < 256)
pre_div *= 2;
@@ -875,7 +939,8 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
* for the uSDHC loopback read clock
*/
v = ESDHC_STROBE_DLL_CTRL_ENABLE |
- (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
+ (ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET
+ << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
/* wait 1us to make sure strobe dll status register stable */
udelay(1);
@@ -889,6 +954,28 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
}
}
+static void esdhc_reset_tuning(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+ u16 ctrl;
+
+ /* Rest the tuning circurt */
+ if (esdhc_is_usdhc(imx_data)) {
+ if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
+ ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL);
+ ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
+ ctrl &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
+ writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL);
+ writel(0 << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
+ } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
+ ctrl = readl(host->ioaddr + SDHCI_ACMD12_ERR);
+ ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
+ writel(ctrl, host->ioaddr + SDHCI_ACMD12_ERR);
+ }
+ }
+}
+
static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
{
u32 m;
@@ -906,6 +993,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
case MMC_TIMING_UHS_SDR25:
case MMC_TIMING_UHS_SDR50:
case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_SD_HS:
+ case MMC_TIMING_MMC_HS:
case MMC_TIMING_MMC_HS200:
writel(m, host->ioaddr + ESDHC_MIX_CTRL);
break;
@@ -932,6 +1021,9 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
host->ops->set_clock(host, host->clock);
esdhc_set_strobe_dll(host);
break;
+ case MMC_TIMING_LEGACY:
+ esdhc_reset_tuning(host);
+ break;
}
esdhc_change_pinstate(host, timing);
@@ -1106,6 +1198,12 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
if (mmc_gpio_get_cd(host->mmc) >= 0)
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ if (of_get_property(np, "wifi-host", NULL)) {
+ wifi_mmc_host = host->mmc;
+ host->quirks2 |= SDHCI_QUIRK2_SDIO_IRQ_THREAD;
+ dev_info(mmc_dev(host->mmc), "assigned as wifi host\n");
+ }
+
return 0;
}
#else
@@ -1224,6 +1322,14 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
pltfm_host->clk = imx_data->clk_per;
pltfm_host->clock = clk_get_rate(pltfm_host->clk);
+
+ if (imx_data->socdata->flags & ESDHC_FLAG_BUSFREQ)
+ request_bus_freq(BUS_FREQ_HIGH);
+
+ if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
+ pm_qos_add_request(&imx_data->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, 0);
+
clk_prepare_enable(imx_data->clk_per);
clk_prepare_enable(imx_data->clk_ipg);
clk_prepare_enable(imx_data->clk_ahb);
@@ -1247,6 +1353,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (esdhc_is_usdhc(imx_data)) {
host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
host->mmc->caps |= MMC_CAP_1_8V_DDR;
+
if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
@@ -1275,6 +1382,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
sdhci_esdhc_imx_hwinit(host);
+ device_set_wakeup_capable(&pdev->dev, 1);
+
err = sdhci_add_host(host);
if (err)
goto disable_clk;
@@ -1291,6 +1400,11 @@ disable_clk:
clk_disable_unprepare(imx_data->clk_per);
clk_disable_unprepare(imx_data->clk_ipg);
clk_disable_unprepare(imx_data->clk_ahb);
+ if (imx_data->socdata->flags & ESDHC_FLAG_BUSFREQ)
+ release_bus_freq(BUS_FREQ_HIGH);
+
+ if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
+ pm_qos_remove_request(&imx_data->pm_qos_req);
free_sdhci:
sdhci_pltfm_free(pdev);
return err;
@@ -1303,6 +1417,9 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+ if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
+ pm_qos_remove_request(&imx_data->pm_qos_req);
+
pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
@@ -1312,6 +1429,8 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
clk_disable_unprepare(imx_data->clk_per);
clk_disable_unprepare(imx_data->clk_ipg);
clk_disable_unprepare(imx_data->clk_ahb);
+ if (imx_data->socdata->flags & ESDHC_FLAG_BUSFREQ)
+ release_bus_freq(BUS_FREQ_HIGH);
sdhci_pltfm_free(pdev);
@@ -1322,18 +1441,45 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
static int sdhci_esdhc_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+ int ret;
+
+#ifdef CONFIG_PM
+ pm_runtime_get_sync(host->mmc->parent);
+#endif
+
+ if ((imx_data->socdata->flags & ESDHC_FLAG_STATE_LOST_IN_LPMODE) &&
+ (host->tuning_mode != SDHCI_TUNING_MODE_1)) {
+ mmc_retune_timer_stop(host->mmc);
+ mmc_retune_needed(host->mmc);
+ }
+
+ ret = sdhci_suspend_host(host);
+
+ pinctrl_pm_select_sleep_state(dev);
- return sdhci_suspend_host(host);
+ return ret;
}
static int sdhci_esdhc_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
+ int ret;
+
+ pinctrl_pm_select_default_state(dev);
/* re-initialize hw state in case it's lost in low power mode */
sdhci_esdhc_imx_hwinit(host);
- return sdhci_resume_host(host);
+ ret = sdhci_resume_host(host);
+
+#ifdef CONFIG_PM
+ pm_runtime_mark_last_busy(host->mmc->parent);
+ pm_runtime_put_autosuspend(host->mmc->parent);
+#endif
+
+ return ret;
}
#endif
@@ -1353,6 +1499,12 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev)
}
clk_disable_unprepare(imx_data->clk_ahb);
+ if (imx_data->socdata->flags & ESDHC_FLAG_BUSFREQ)
+ release_bus_freq(BUS_FREQ_HIGH);
+
+ if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
+ pm_qos_remove_request(&imx_data->pm_qos_req);
+
return ret;
}
@@ -1362,6 +1514,13 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
+ if (imx_data->socdata->flags & ESDHC_FLAG_BUSFREQ)
+ request_bus_freq(BUS_FREQ_HIGH);
+
+ if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
+ pm_qos_add_request(&imx_data->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, 0);
+
if (!sdhci_sdio_irq_enabled(host)) {
clk_prepare_enable(imx_data->clk_per);
clk_prepare_enable(imx_data->clk_ipg);
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index ad49bfaf5bf8..464843705f08 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -2,7 +2,7 @@
* sdhci-pltfm.c Support for SDHCI platform devices
* Copyright (c) 2009 Intel Corporation
*
- * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007, 2011, 2015 Freescale Semiconductor, Inc.
* Copyright (c) 2009 MontaVista Software, Inc.
*
* Authors: Xiaobo Xie <X.Xie@freescale.com>
@@ -212,14 +212,20 @@ EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister);
static int sdhci_pltfm_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
+ int ret;
- return sdhci_suspend_host(host);
+ ret = sdhci_suspend_host(host);
+ pinctrl_pm_select_sleep_state(dev);
+
+ return ret;
}
static int sdhci_pltfm_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
+ pinctrl_pm_select_default_state(dev);
+
return sdhci_resume_host(host);
}
#endif
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7d275e72903a..cac9951cca71 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -117,9 +117,10 @@ static inline bool sdhci_data_line_cmd(struct mmc_command *cmd)
static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
{
u32 present;
+ int gpio_cd = mmc_gpio_get_cd(host->mmc);
if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
- !mmc_card_is_removable(host->mmc))
+ !mmc_card_is_removable(host->mmc) || (gpio_cd >= 0))
return;
if (enable) {
@@ -1997,7 +1998,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
break;
case MMC_TIMING_UHS_SDR104:
- case MMC_TIMING_UHS_DDR50:
break;
case MMC_TIMING_UHS_SDR50:
@@ -2005,6 +2005,11 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
break;
/* FALLTHROUGH */
+ case MMC_TIMING_UHS_DDR50:
+ if (host->flags & SDHCI_DDR50_NEEDS_TUNING)
+ break;
+ /* FALLTHROUGH */
+
default:
goto out_unlock;
}
@@ -2127,9 +2132,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- /* eMMC spec does not require a delay between tuning cycles */
- if (opcode == MMC_SEND_TUNING_BLOCK)
- mdelay(1);
+ /* Add 1ms delay for SD and eMMC */
+ mdelay(1);
} while (ctrl & SDHCI_CTRL_EXEC_TUNING);
/*
@@ -2661,6 +2665,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
struct sdhci_host *host = dev_id;
u32 intmask, mask, unexpected = 0;
int max_loops = 16;
+ int cardint = 0;
spin_lock(&host->lock);
@@ -2729,9 +2734,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
if ((intmask & SDHCI_INT_CARD_INT) &&
(host->ier & SDHCI_INT_CARD_INT)) {
- sdhci_enable_sdio_irq_nolock(host, false);
- host->thread_isr |= SDHCI_INT_CARD_INT;
- result = IRQ_WAKE_THREAD;
+ if (host->mmc->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD) {
+ sdhci_enable_sdio_irq_nolock(host, false);
+ host->thread_isr |= SDHCI_INT_CARD_INT;
+ result = IRQ_WAKE_THREAD;
+ } else {
+ cardint = 1;
+ }
}
intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
@@ -2758,6 +2767,9 @@ out:
sdhci_dumpregs(host);
}
+ if (cardint && host->mmc->sdio_irqs)
+ mmc_signal_sdio_irq(host->mmc);
+
return result;
}
@@ -2780,12 +2792,13 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
}
if (isr & SDHCI_INT_CARD_INT) {
- sdio_run_irqs(host->mmc);
-
- spin_lock_irqsave(&host->lock, flags);
- if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
- sdhci_enable_sdio_irq_nolock(host, true);
- spin_unlock_irqrestore(&host->lock, flags);
+ if (host->mmc->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD) {
+ sdio_run_irqs(host->mmc);
+ spin_lock_irqsave(&host->lock, flags);
+ if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
+ sdhci_enable_sdio_irq_nolock(host, true);
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
}
return isr ? IRQ_HANDLED : IRQ_NONE;
@@ -2808,6 +2821,7 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
*/
void sdhci_enable_irq_wakeups(struct sdhci_host *host)
{
+ int gpio_cd = mmc_gpio_get_cd(host->mmc);
u8 val;
u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE
| SDHCI_WAKE_ON_INT;
@@ -2817,7 +2831,8 @@ void sdhci_enable_irq_wakeups(struct sdhci_host *host)
val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
val |= mask ;
/* Avoid fake wake up */
- if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) {
+ if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION ||
+ (gpio_cd >= 0)) {
val &= ~(SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE);
irq_val &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
}
@@ -2849,7 +2864,7 @@ int sdhci_suspend_host(struct sdhci_host *host)
host->ier = 0;
sdhci_writel(host, 0, SDHCI_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- free_irq(host->irq, host);
+ disable_irq(host->irq);
} else {
sdhci_enable_irq_wakeups(host);
enable_irq_wake(host->irq);
@@ -2862,7 +2877,6 @@ EXPORT_SYMBOL_GPL(sdhci_suspend_host);
int sdhci_resume_host(struct sdhci_host *host)
{
struct mmc_host *mmc = host->mmc;
- int ret = 0;
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma)
@@ -2882,11 +2896,7 @@ int sdhci_resume_host(struct sdhci_host *host)
}
if (!device_may_wakeup(mmc_dev(host->mmc))) {
- ret = request_threaded_irq(host->irq, sdhci_irq,
- sdhci_thread_irq, IRQF_SHARED,
- mmc_hostname(host->mmc), host);
- if (ret)
- return ret;
+ enable_irq(host->irq);
} else {
sdhci_disable_irq_wakeups(host);
disable_irq_wake(host->irq);
@@ -2894,7 +2904,7 @@ int sdhci_resume_host(struct sdhci_host *host)
sdhci_enable_card_detection(host);
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(sdhci_resume_host);
@@ -3284,7 +3294,8 @@ int sdhci_setup_host(struct sdhci_host *host)
}
mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
- mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
+ if (!(host->quirks2 & SDHCI_QUIRK2_SDIO_IRQ_THREAD))
+ mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
host->flags |= SDHCI_AUTO_CMD12;
@@ -3316,11 +3327,6 @@ int sdhci_setup_host(struct sdhci_host *host)
if (host->caps & SDHCI_CAN_DO_HISPD)
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
- if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
- mmc_card_is_removable(mmc) &&
- mmc_gpio_get_cd(host->mmc) < 0)
- mmc->caps |= MMC_CAP_NEEDS_POLL;
-
/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
if (!IS_ERR(mmc->supply.vqmmc)) {
ret = regulator_enable(mmc->supply.vqmmc);
@@ -3339,6 +3345,7 @@ int sdhci_setup_host(struct sdhci_host *host)
if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) {
host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
SDHCI_SUPPORT_DDR50);
+ mmc->caps2 |= MMC_CAP2_DDR52_3_3V;
}
/* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
@@ -3478,10 +3485,11 @@ int sdhci_setup_host(struct sdhci_host *host)
goto unreg;
}
- if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ if (((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) ||
- (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V)))
+ (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V))) &&
+ !(mmc->caps2 & MMC_CAP2_DDR52_3_3V))
host->flags |= SDHCI_SIGNALING_180;
if (mmc->caps2 & MMC_CAP2_HSX00_1_2V)
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 2570455b219a..d9bddd02699b 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -425,6 +425,9 @@ struct sdhci_host {
#define SDHCI_QUIRK2_ACMD23_BROKEN (1<<14)
/* Broken Clock divider zero in controller */
#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1<<15)
+/* Host or Card can't support no thread sdio irq */
+#define SDHCI_QUIRK2_SDIO_IRQ_THREAD (1<<16)
+
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
@@ -449,6 +452,7 @@ struct sdhci_host {
#define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */
#define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */
#define SDHCI_SDR50_NEEDS_TUNING (1<<4) /* SDR50 needs tuning */
+#define SDHCI_DDR50_NEEDS_TUNING (1<<5) /* DDR50 needs tuning */
#define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */
#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */
#define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 99bb9a1f6e16..f46b1ccff165 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -30,7 +30,7 @@ obj-$(CONFIG_MTD_SWAP) += mtdswap.o
nftl-objs := nftlcore.o nftlmount.o
inftl-objs := inftlcore.o inftlmount.o
+obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
-obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-$(CONFIG_MTD_UBI) += ubi/
diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/gpmi-nand/bch-regs.h
index 05bb91f2f4c4..a84d72b2f61a 100644
--- a/drivers/mtd/nand/gpmi-nand/bch-regs.h
+++ b/drivers/mtd/nand/gpmi-nand/bch-regs.h
@@ -1,7 +1,7 @@
/*
* Freescale GPMI NAND Flash Driver
*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2015 Freescale Semiconductor, Inc.
* Copyright 2008 Embedded Alley Solutions, Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -30,7 +30,13 @@
#define BM_BCH_CTRL_COMPLETE_IRQ (1 << 0)
#define HW_BCH_STATUS0 0x00000010
+
#define HW_BCH_MODE 0x00000020
+#define BP_BCH_MODE_ERASE_THRESHOLD 0
+#define BM_BCH_MODE_ERASE_THRESHOLD (0xff << BP_BCH_MODE_ERASE_THRESHOLD)
+#define BF_BCH_MODE_ERASE_THRESHOLD(v) \
+ (((v) << BP_BCH_MODE_ERASE_THRESHOLD) & BM_BCH_MODE_ERASE_THRESHOLD)
+
#define HW_BCH_ENCODEPTR 0x00000030
#define HW_BCH_DATAPTR 0x00000040
#define HW_BCH_METAPTR 0x00000050
@@ -54,7 +60,7 @@
#define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11
#define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0)
#define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \
- (GPMI_IS_MX6(x) \
+ ((GPMI_IS_MX6(x) || GPMI_IS_MX7(x)) \
? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \
& MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \
: (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \
@@ -65,7 +71,7 @@
#define MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14 \
(0x1 << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14)
#define BF_BCH_FLASH0LAYOUT0_GF(v, x) \
- ((GPMI_IS_MX6(x) && ((v) == 14)) \
+ (((GPMI_IS_MX6(x) || GPMI_IS_MX7(x)) && ((v) == 14))\
? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14) \
& MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14) \
: 0 \
@@ -77,7 +83,7 @@
#define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \
(0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)
#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \
- (GPMI_IS_MX6(x) \
+ ((GPMI_IS_MX6(x) || GPMI_IS_MX7(x)) \
? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \
: ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \
)
@@ -96,7 +102,7 @@
#define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11
#define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN)
#define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \
- (GPMI_IS_MX6(x) \
+ ((GPMI_IS_MX6(x) || GPMI_IS_MX7(x)) \
? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \
& MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \
: (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \
@@ -107,7 +113,7 @@
#define MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14 \
(0x1 << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14)
#define BF_BCH_FLASH0LAYOUT1_GF(v, x) \
- ((GPMI_IS_MX6(x) && ((v) == 14)) \
+ (((GPMI_IS_MX6(x) || GPMI_IS_MX7(x)) && ((v) == 14))\
? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14) \
& MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14) \
: 0 \
@@ -119,10 +125,14 @@
#define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \
(0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE)
#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \
- (GPMI_IS_MX6(x) \
+ ((GPMI_IS_MX6(x) || GPMI_IS_MX7(x)) \
? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
: ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
)
#define HW_BCH_VERSION 0x00000160
+#define HW_BCH_DEBUG1 0x00000170
+#define BP_BCH_DEBUG1_ERASED_ZERO_COUNT 0
+#define BM_BCH_DEBUG1_ERASED_ZERO_COUNT \
+ (0x1ff << BP_BCH_DEBUG1_ERASED_ZERO_COUNT)
#endif
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 141bd70a49c2..2b927839ee05 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -1,7 +1,7 @@
/*
* Freescale GPMI NAND Flash Driver
*
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2016 Freescale Semiconductor, Inc.
* Copyright (C) 2008 Embedded Alley Solutions, Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -21,11 +21,17 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/debugfs.h>
+
#include "gpmi-nand.h"
#include "gpmi-regs.h"
#include "bch-regs.h"
+/* export the bch geometry to dbgfs */
+static struct debugfs_blob_wrapper dbg_bch_geo;
+
static struct timing_threshod timing_default_threshold = {
.max_data_setup_cycles = (BM_GPMI_TIMING0_DATA_SETUP >>
BP_GPMI_TIMING0_DATA_SETUP),
@@ -124,7 +130,7 @@ error:
return -ETIMEDOUT;
}
-static int __gpmi_enable_clk(struct gpmi_nand_data *this, bool v)
+int __gpmi_enable_clk(struct gpmi_nand_data *this, bool v)
{
struct clk *clk;
int ret;
@@ -151,17 +157,17 @@ err_clk:
return ret;
}
-#define gpmi_enable_clk(x) __gpmi_enable_clk(x, true)
-#define gpmi_disable_clk(x) __gpmi_enable_clk(x, false)
-
int gpmi_init(struct gpmi_nand_data *this)
{
struct resources *r = &this->resources;
int ret;
- ret = gpmi_enable_clk(this);
- if (ret)
+ ret = pm_runtime_get_sync(this->dev);
+ if (ret < 0) {
+ dev_err(this->dev, "Failed to enable clock\n");
return ret;
+ }
+
ret = gpmi_reset_block(r->gpmi_regs, false);
if (ret)
goto err_out;
@@ -194,10 +200,10 @@ int gpmi_init(struct gpmi_nand_data *this)
*/
writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
- gpmi_disable_clk(this);
- return 0;
err_out:
- gpmi_disable_clk(this);
+ pm_runtime_mark_last_busy(this->dev);
+ pm_runtime_put_autosuspend(this->dev);
+
return ret;
}
@@ -226,7 +232,8 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
"ECC Strength : %u\n"
"Page Size in Bytes : %u\n"
"Metadata Size in Bytes : %u\n"
- "ECC Chunk Size in Bytes: %u\n"
+ "ECC Chunk0 Size in Bytes: %u\n"
+ "ECC Chunkn Size in Bytes: %u\n"
"ECC Chunk Count : %u\n"
"Payload Size in Bytes : %u\n"
"Auxiliary Size in Bytes: %u\n"
@@ -237,7 +244,8 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
geo->ecc_strength,
geo->page_size,
geo->metadata_size,
- geo->ecc_chunk_size,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
geo->ecc_chunk_count,
geo->payload_size,
geo->auxiliary_size,
@@ -246,13 +254,43 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
geo->block_mark_bit_offset);
}
+int bch_create_debugfs(struct gpmi_nand_data *this)
+{
+ struct bch_geometry *bch_geo = &this->bch_geometry;
+ struct dentry *dbg_root;
+
+ dbg_root = debugfs_create_dir("gpmi-nand", NULL);
+ if (!dbg_root) {
+ dev_err(this->dev, "failed to create debug directory\n");
+ return -EINVAL;
+ }
+
+ dbg_bch_geo.data = (void *)bch_geo;
+ dbg_bch_geo.size = sizeof(struct bch_geometry);
+ if (!debugfs_create_blob("bch_geometry", S_IRUGO,
+ dbg_root, &dbg_bch_geo)) {
+ dev_err(this->dev, "failed to create debug bch geometry\n");
+ return -EINVAL;
+ }
+
+ /* create raw mode flag */
+ if (!debugfs_create_file("raw_mode", S_IRUGO,
+ dbg_root, NULL, NULL)) {
+ dev_err(this->dev, "failed to create raw mode flag\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/* Configures the geometry for BCH. */
int bch_set_geometry(struct gpmi_nand_data *this)
{
struct resources *r = &this->resources;
struct bch_geometry *bch_geo = &this->bch_geometry;
unsigned int block_count;
- unsigned int block_size;
+ unsigned int block0_size;
+ unsigned int blockn_size;
unsigned int metadata_size;
unsigned int ecc_strength;
unsigned int page_size;
@@ -263,15 +301,18 @@ int bch_set_geometry(struct gpmi_nand_data *this)
return !0;
block_count = bch_geo->ecc_chunk_count - 1;
- block_size = bch_geo->ecc_chunk_size;
+ block0_size = bch_geo->ecc_chunk0_size;
+ blockn_size = bch_geo->ecc_chunkn_size;
metadata_size = bch_geo->metadata_size;
ecc_strength = bch_geo->ecc_strength >> 1;
page_size = bch_geo->page_size;
gf_len = bch_geo->gf_len;
- ret = gpmi_enable_clk(this);
- if (ret)
+ ret = pm_runtime_get_sync(this->dev);
+ if (ret < 0) {
+ dev_err(this->dev, "Failed to enable clock\n");
return ret;
+ }
/*
* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
@@ -290,15 +331,20 @@ int bch_set_geometry(struct gpmi_nand_data *this)
| BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
| BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this)
| BF_BCH_FLASH0LAYOUT0_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this),
+ | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block0_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT0);
writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
| BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this)
| BF_BCH_FLASH0LAYOUT1_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
+ | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(blockn_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT1);
+ /* Set erase threshold to ecc strength for mx6ul, mx6qp and mx7 */
+ if (GPMI_IS_MX6QP(this) || GPMI_IS_MX7(this) || GPMI_IS_MX6UL(this))
+ writel(BF_BCH_MODE_ERASE_THRESHOLD(ecc_strength),
+ r->bch_regs + HW_BCH_MODE);
+
/* Set *all* chip selects to use layout 0. */
writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
@@ -306,10 +352,10 @@ int bch_set_geometry(struct gpmi_nand_data *this)
writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
r->bch_regs + HW_BCH_CTRL_SET);
- gpmi_disable_clk(this);
- return 0;
err_out:
- gpmi_disable_clk(this);
+ pm_runtime_mark_last_busy(this->dev);
+ pm_runtime_put_autosuspend(this->dev);
+
return ret;
}
@@ -948,9 +994,14 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
nand->select_chip(mtd, -1);
+ pm_runtime_get_sync(this->dev);
+ clk_disable_unprepare(r->clock[0]);
/* [3] set the main IO clock, 100MHz for mode 5, 80MHz for mode 4. */
rate = (mode == 5) ? 100000000 : 80000000;
clk_set_rate(r->clock[0], rate);
+ clk_prepare_enable(r->clock[0]);
+ pm_runtime_mark_last_busy(this->dev);
+ pm_runtime_put_autosuspend(this->dev);
/* Let the gpmi_begin() re-compute the timing again. */
this->flags &= ~GPMI_TIMING_INIT_OK;
@@ -973,7 +1024,8 @@ int gpmi_extra_init(struct gpmi_nand_data *this)
struct nand_chip *chip = &this->nand;
/* Enable the asynchronous EDO feature. */
- if (GPMI_IS_MX6(this) && chip->onfi_version) {
+ if ((GPMI_IS_MX6(this) || GPMI_IS_MX7(this))
+ && chip->onfi_version) {
int mode = onfi_get_async_timing_mode(chip);
/* We only support the timing mode 4 and mode 5. */
@@ -1001,9 +1053,9 @@ void gpmi_begin(struct gpmi_nand_data *this)
int ret;
/* Enable the clock. */
- ret = gpmi_enable_clk(this);
- if (ret) {
- dev_err(this->dev, "We failed in enable the clk\n");
+ ret = pm_runtime_get_sync(this->dev);
+ if (ret < 0) {
+ dev_err(this->dev, "Failed to enable clock\n");
goto err_out;
}
@@ -1075,7 +1127,8 @@ err_out:
void gpmi_end(struct gpmi_nand_data *this)
{
- gpmi_disable_clk(this);
+ pm_runtime_mark_last_busy(this->dev);
+ pm_runtime_put_autosuspend(this->dev);
}
/* Clears a BCH interrupt. */
@@ -1095,12 +1148,13 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
if (GPMI_IS_MX23(this)) {
mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
- } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6(this)) {
+ } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6(this) ||
+ GPMI_IS_MX7(this)) {
/*
* In the imx6, all the ready/busy pins are bound
* together. So we only need to check chip 0.
*/
- if (GPMI_IS_MX6(this))
+ if (GPMI_IS_MX6(this) || GPMI_IS_MX7(this))
chip = 0;
/* MX28 shares the same R/B register as MX6Q. */
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 6c062b8251d2..290160344606 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -1,7 +1,7 @@
/*
* Freescale GPMI NAND Flash Driver
*
- * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc.
* Copyright (C) 2008 Embedded Alley Solutions, Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,8 @@
#include <linux/mtd/partitions.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/busfreq-imx.h>
+#include <linux/pm_runtime.h>
#include "gpmi-nand.h"
#include "bch-regs.h"
@@ -33,6 +35,8 @@
#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch"
#define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch"
+#define GPMI_RPM_TIMEOUT 50 /* ms */
+
/* add our owner bbt descriptor */
static uint8_t scan_ff_pattern[] = { 0xff };
static struct nand_bbt_descr gpmi_bbt_descr = {
@@ -104,12 +108,36 @@ static const struct gpmi_devdata gpmi_devdata_imx6q = {
.max_chain_delay = 12,
};
+static const struct gpmi_devdata gpmi_devdata_imx6qp = {
+ .type = IS_MX6QP,
+ .bch_max_ecc_strength = 40,
+ .max_chain_delay = 12,
+};
+
static const struct gpmi_devdata gpmi_devdata_imx6sx = {
.type = IS_MX6SX,
.bch_max_ecc_strength = 62,
.max_chain_delay = 12,
};
+static const struct gpmi_devdata gpmi_devdata_imx7d = {
+ .type = IS_MX7D,
+ .bch_max_ecc_strength = 62,
+ .max_chain_delay = 12,
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx6ul = {
+ .type = IS_MX6UL,
+ .bch_max_ecc_strength = 40,
+ .max_chain_delay = 12,
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx6ull = {
+ .type = IS_MX6ULL,
+ .bch_max_ecc_strength = 40,
+ .max_chain_delay = 12,
+};
+
static irqreturn_t bch_irq(int irq, void *cookie)
{
struct gpmi_nand_data *this = cookie;
@@ -163,6 +191,36 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
return geo->ecc_strength <= this->devdata->bch_max_ecc_strength;
}
+static inline bool bbm_in_data_chunk(struct gpmi_nand_data *this,
+ unsigned int *chunk_num)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = &this->nand.mtd;
+ unsigned int i, j;
+
+ if (geo->ecc_chunk0_size != geo->ecc_chunkn_size) {
+ dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
+ return false;
+ }
+
+ i = (mtd->writesize * 8 - geo->metadata_size * 8) /
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8);
+
+ j = (mtd->writesize * 8 - geo->metadata_size * 8) -
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8) * i;
+
+ if (j < geo->ecc_chunkn_size * 8) {
+ *chunk_num = i+1;
+ dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
+ geo->ecc_strength, *chunk_num);
+ return true;
+ }
+
+ return false;
+}
+
/*
* If we can get the ECC information from the nand chip, we do not
* need to calculate them ourselves.
@@ -192,13 +250,14 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this)
chip->ecc_strength_ds, chip->ecc_step_ds);
return -EINVAL;
}
- geo->ecc_chunk_size = chip->ecc_step_ds;
+ geo->ecc_chunk0_size = chip->ecc_step_ds;
+ geo->ecc_chunkn_size = chip->ecc_step_ds;
geo->ecc_strength = round_up(chip->ecc_strength_ds, 2);
if (!gpmi_check_ecc(this))
return -EINVAL;
/* Keep the C >= O */
- if (geo->ecc_chunk_size < mtd->oobsize) {
+ if (geo->ecc_chunkn_size < mtd->oobsize) {
dev_err(this->dev,
"unsupported nand chip. ecc size: %d, oob size : %d\n",
chip->ecc_step_ds, mtd->oobsize);
@@ -208,7 +267,7 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this)
/* The default value, see comment in the legacy_set_geometry(). */
geo->metadata_size = 10;
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/*
* Now, the NAND chip with 2K page(data chunk is 512byte) shows below:
@@ -280,6 +339,131 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this)
return 0;
}
+static int set_geometry_for_large_oob(struct gpmi_nand_data *this)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = &this->nand.mtd;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ unsigned int block_mark_bit_offset;
+ unsigned int max_ecc;
+ unsigned int bbm_chunk;
+ unsigned int i;
+
+
+ /* sanity check for the minimum ecc nand required */
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
+ return -EINVAL;
+ geo->ecc_strength = chip->ecc_strength_ds;
+
+ /* check if platform can support this nand */
+ if (!gpmi_check_ecc(this)) {
+ dev_err(this->dev,
+ "unsupported NAND chip,\
+ minimum ecc required %d\n"
+ , geo->ecc_strength);
+ return -EINVAL;
+ }
+
+ /* calculate the maximum ecc platform can support*/
+ geo->metadata_size = 10;
+ geo->gf_len = 14;
+ geo->ecc_chunk0_size = 1024;
+ geo->ecc_chunkn_size = 1024;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
+ max_ecc = min(get_ecc_strength(this),
+ this->devdata->bch_max_ecc_strength);
+
+ /* search a supported ecc strength that makes bbm */
+ /* located in data chunk */
+ geo->ecc_strength = chip->ecc_strength_ds;
+ while (!(geo->ecc_strength > max_ecc)) {
+ if (bbm_in_data_chunk(this, &bbm_chunk))
+ goto geo_setting;
+ geo->ecc_strength += 2;
+ }
+
+ /* if none of them works, keep using the minimum ecc */
+ /* nand required but changing ecc page layout */
+ geo->ecc_strength = chip->ecc_strength_ds;
+ /* add extra ecc for meta data */
+ geo->ecc_chunk0_size = 0;
+ geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
+ geo->ecc_for_meta = 1;
+ /* check if oob can afford this extra ecc chunk */
+ if (mtd->oobsize * 8 < geo->metadata_size * 8 +
+ geo->gf_len * geo->ecc_strength
+ * geo->ecc_chunk_count) {
+ dev_err(this->dev, "unsupported NAND chip with new layout\n");
+ return -EINVAL;
+ }
+
+ /* calculate in which chunk bbm located */
+ bbm_chunk = (mtd->writesize * 8 - geo->metadata_size * 8 -
+ geo->gf_len * geo->ecc_strength) /
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8) + 1;
+
+geo_setting:
+
+ geo->page_size = mtd->writesize + mtd->oobsize;
+ geo->payload_size = mtd->writesize;
+
+ /*
+ * The auxiliary buffer contains the metadata and the ECC status. The
+ * metadata is padded to the nearest 32-bit boundary. The ECC status
+ * contains one byte for every ECC chunk, and is also padded to the
+ * nearest 32-bit boundary.
+ */
+ geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4);
+ geo->auxiliary_size = ALIGN(geo->metadata_size, 4)
+ + ALIGN(geo->ecc_chunk_count, 4);
+
+ if (!this->swap_block_mark)
+ return 0;
+
+ /* calculate the number of ecc chunk behind the bbm */
+ i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
+
+ block_mark_bit_offset = mtd->writesize * 8 -
+ (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
+ + geo->metadata_size * 8);
+
+ geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+ geo->block_mark_bit_offset = block_mark_bit_offset % 8;
+
+ dev_dbg(this->dev, "BCH Geometry :\n"
+ "GF length : %u\n"
+ "ECC Strength : %u\n"
+ "Page Size in Bytes : %u\n"
+ "Metadata Size in Bytes : %u\n"
+ "ECC Chunk0 Size in Bytes: %u\n"
+ "ECC Chunkn Size in Bytes: %u\n"
+ "ECC Chunk Count : %u\n"
+ "Payload Size in Bytes : %u\n"
+ "Auxiliary Size in Bytes: %u\n"
+ "Auxiliary Status Offset: %u\n"
+ "Block Mark Byte Offset : %u\n"
+ "Block Mark Bit Offset : %u\n"
+ "Block Mark in chunk : %u\n"
+ "Ecc for Meta data : %u\n",
+ geo->gf_len,
+ geo->ecc_strength,
+ geo->page_size,
+ geo->metadata_size,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
+ geo->ecc_chunk_count,
+ geo->payload_size,
+ geo->auxiliary_size,
+ geo->auxiliary_status_offset,
+ geo->block_mark_byte_offset,
+ geo->block_mark_bit_offset,
+ bbm_chunk,
+ geo->ecc_for_meta);
+
+ return 0;
+}
+
static int legacy_set_geometry(struct gpmi_nand_data *this)
{
struct bch_geometry *geo = &this->bch_geometry;
@@ -299,20 +483,22 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
geo->gf_len = 13;
/* The default for chunk size. */
- geo->ecc_chunk_size = 512;
- while (geo->ecc_chunk_size < mtd->oobsize) {
- geo->ecc_chunk_size *= 2; /* keep C >= O */
+ geo->ecc_chunk0_size = 512;
+ geo->ecc_chunkn_size = 512;
+ while (geo->ecc_chunkn_size < mtd->oobsize) {
+ geo->ecc_chunk0_size *= 2; /* keep C >= O */
+ geo->ecc_chunkn_size *= 2; /* keep C >= O */
geo->gf_len = 14;
}
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/* We use the same ECC strength for all chunks. */
geo->ecc_strength = get_ecc_strength(this);
if (!gpmi_check_ecc(this)) {
dev_err(this->dev,
"ecc strength: %d cannot be supported by the controller (%d)\n"
- "try to use minimum ecc strength that NAND chip required\n",
+ "try to use maximum ecc strength that NAND chip required\n",
geo->ecc_strength,
this->devdata->bch_max_ecc_strength);
return -EINVAL;
@@ -394,11 +580,26 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
int common_nfc_set_geometry(struct gpmi_nand_data *this)
{
- if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc"))
- || legacy_set_geometry(this))
- return set_geometry_by_ecc_info(this);
+ struct mtd_info *mtd = &this->nand.mtd;
+ struct nand_chip *chip = mtd_to_nand(mtd);
- return 0;
+ if (chip->ecc_strength_ds > this->devdata->bch_max_ecc_strength) {
+ dev_err(this->dev,
+ "unsupported NAND chip, minimum ecc required %d\n"
+ , chip->ecc_strength_ds);
+ return -EINVAL;
+ }
+
+ if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
+ (mtd->oobsize < 1024)) || this->legacy_bch_geometry) {
+ dev_warn(this->dev, "use legacy bch geometry\n");
+ return legacy_set_geometry(this);
+ }
+
+ if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
+ return set_geometry_for_large_oob(this);
+
+ return set_geometry_by_ecc_info(this);
}
struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
@@ -602,6 +803,10 @@ static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = {
"gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
};
+static char *extra_clks_for_mx7d[GPMI_CLK_MAX] = {
+ "gpmi_bch_apb",
+};
+
static int gpmi_get_clks(struct gpmi_nand_data *this)
{
struct resources *r = &this->resources;
@@ -619,6 +824,8 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
/* Get extra clocks */
if (GPMI_IS_MX6(this))
extra_clks = extra_clks_for_mx6q;
+ if (GPMI_IS_MX7(this))
+ extra_clks = extra_clks_for_mx7d;
if (!extra_clks)
return 0;
@@ -635,7 +842,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
r->clock[i] = clk;
}
- if (GPMI_IS_MX6(this))
+ if (GPMI_IS_MX6(this) || GPMI_IS_MX7(this))
/*
* Set the default value for the gpmi clock.
*
@@ -651,6 +858,15 @@ err_clock:
return err;
}
+static int init_rpm(struct gpmi_nand_data *this)
+{
+ pm_runtime_enable(this->dev);
+ pm_runtime_set_autosuspend_delay(this->dev, GPMI_RPM_TIMEOUT);
+ pm_runtime_use_autosuspend(this->dev);
+
+ return 0;
+}
+
static int acquire_resources(struct gpmi_nand_data *this)
{
int ret;
@@ -674,6 +890,7 @@ static int acquire_resources(struct gpmi_nand_data *this)
ret = gpmi_get_clks(this);
if (ret)
goto exit_clock;
+
return 0;
exit_clock:
@@ -1026,6 +1243,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
+ void __iomem *bch_regs = this->resources.bch_regs;
void *payload_virt;
dma_addr_t payload_phys;
void *auxiliary_virt;
@@ -1034,6 +1252,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
unsigned char *status;
unsigned int max_bitflips = 0;
int ret;
+ int flag = 0;
dev_dbg(this->dev, "page number is : %d\n", page);
ret = read_page_prepare(this, buf, nfc_geo->payload_size,
@@ -1071,9 +1290,17 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
payload_virt, payload_phys);
for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) {
- if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED))
+ if (*status == STATUS_GOOD)
continue;
+ if (*status == STATUS_ERASED) {
+ if (GPMI_IS_MX6QP(this) || GPMI_IS_MX7(this) ||
+ GPMI_IS_MX6UL(this))
+ if (readl(bch_regs + HW_BCH_DEBUG1))
+ flag = 1;
+ continue;
+ }
+
if (*status == STATUS_UNCORRECTABLE) {
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *eccbuf = this->raw_buffer;
@@ -1083,7 +1310,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
/* Read ECC bytes into our internal raw_buffer */
offset = nfc_geo->metadata_size * 8;
- offset += ((8 * nfc_geo->ecc_chunk_size) + eccbits) * (i + 1);
+ offset += ((8 * nfc_geo->ecc_chunkn_size) + eccbits) * (i + 1);
offset -= eccbits;
bitoffset = offset % 8;
eccbytes = DIV_ROUND_UP(offset + eccbits, 8);
@@ -1120,16 +1347,16 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
if (i == 0) {
/* The first block includes metadata */
flips = nand_check_erased_ecc_chunk(
- buf + i * nfc_geo->ecc_chunk_size,
- nfc_geo->ecc_chunk_size,
+ buf + i * nfc_geo->ecc_chunkn_size,
+ nfc_geo->ecc_chunkn_size,
eccbuf, eccbytes,
auxiliary_virt,
nfc_geo->metadata_size,
nfc_geo->ecc_strength);
} else {
flips = nand_check_erased_ecc_chunk(
- buf + i * nfc_geo->ecc_chunk_size,
- nfc_geo->ecc_chunk_size,
+ buf + i * nfc_geo->ecc_chunkn_size,
+ nfc_geo->ecc_chunkn_size,
eccbuf, eccbytes,
NULL, 0,
nfc_geo->ecc_strength);
@@ -1165,6 +1392,10 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
}
+ /* if bitflip occurred in erased page, change data to all 0xff */
+ if (flag)
+ memset(buf, 0xff, nfc_geo->payload_size);
+
return max_bitflips;
}
@@ -1209,9 +1440,23 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
}
}
+ /*
+ * if there is an ECC dedicate for meta:
+ * - need to add an extra ECC size when calculating col and page_size,
+ * if the meta size is NOT zero.
+ *
+ * - chunk0 size need to set to the same size as other chunks,
+ * if the meta size is zero.
+ */
+
meta = geo->metadata_size;
if (first) {
- col = meta + (size + ecc_parity_size) * first;
+ if (geo->ecc_for_meta)
+ col = meta + ecc_parity_size
+ + (size + ecc_parity_size) * first;
+ else
+ col = meta + (size + ecc_parity_size) * first;
+
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
meta = 0;
@@ -1224,21 +1469,37 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
/* change the BCH registers and bch_geometry{} */
n = last - first + 1;
- page_size = meta + (size + ecc_parity_size) * n;
+
+ if (geo->ecc_for_meta && meta)
+ page_size = meta + ecc_parity_size
+ + (size + ecc_parity_size) * n;
+ else
+ page_size = meta + (size + ecc_parity_size) * n;
r1_new &= ~(BM_BCH_FLASH0LAYOUT0_NBLOCKS |
BM_BCH_FLASH0LAYOUT0_META_SIZE);
- r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1)
+ r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(
+ (geo->ecc_for_meta && meta) ? n : n - 1)
| BF_BCH_FLASH0LAYOUT0_META_SIZE(meta);
+
+ /* set chunk0 size if meta size is 0 */
+ if (!meta) {
+ if (GPMI_IS_MX6(this) || GPMI_IS_MX7(this))
+ r1_new &= ~MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE;
+ else
+ r1_new &= ~BM_BCH_FLASH0LAYOUT0_DATA0_SIZE;
+ r1_new |= BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(size, this);
+ }
writel(r1_new, bch_regs + HW_BCH_FLASH0LAYOUT0);
r2_new &= ~BM_BCH_FLASH0LAYOUT1_PAGE_SIZE;
r2_new |= BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size);
writel(r2_new, bch_regs + HW_BCH_FLASH0LAYOUT1);
- geo->ecc_chunk_count = n;
+ geo->ecc_chunk_count = (geo->ecc_for_meta && meta) ? n + 1 : n;
geo->payload_size = n * size;
geo->page_size = page_size;
+ geo->metadata_size = meta;
geo->auxiliary_status_offset = ALIGN(meta, 4);
dev_dbg(this->dev, "page:%d(%d:%d)%d, chunk:(%d:%d), BCH PG size:%d\n",
@@ -1460,7 +1721,7 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
- int eccsize = nfc_geo->ecc_chunk_size;
+ int eccsize = nfc_geo->ecc_chunkn_size;
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *tmp_buf = this->raw_buffer;
size_t src_bit_off;
@@ -1468,6 +1729,7 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
size_t oob_byte_off;
uint8_t *oob = chip->oob_poi;
int step;
+ int ecc_chunk_count;
chip->read_buf(mtd, tmp_buf,
mtd->writesize + mtd->oobsize);
@@ -1495,9 +1757,21 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
oob_bit_off = nfc_geo->metadata_size * 8;
src_bit_off = oob_bit_off;
+ ecc_chunk_count = nfc_geo->ecc_chunk_count;
+ /* if bch requires dedicate ecc for meta */
+ if (nfc_geo->ecc_for_meta) {
+ if (oob_required)
+ gpmi_copy_bits(oob, oob_bit_off,
+ tmp_buf, src_bit_off,
+ eccbits);
+
+ src_bit_off += eccbits;
+ oob_bit_off += eccbits;
+ ecc_chunk_count = nfc_geo->ecc_chunk_count - 1;
+ }
/* Extract interleaved payload data and ECC bits */
- for (step = 0; step < nfc_geo->ecc_chunk_count; step++) {
+ for (step = 0; step < ecc_chunk_count; step++) {
if (buf)
gpmi_copy_bits(buf, step * eccsize * 8,
tmp_buf, src_bit_off,
@@ -1505,7 +1779,7 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
src_bit_off += eccsize * 8;
/* Align last ECC block to align a byte boundary */
- if (step == nfc_geo->ecc_chunk_count - 1 &&
+ if (step == ecc_chunk_count - 1 &&
(oob_bit_off + eccbits) % 8)
eccbits += 8 - ((oob_bit_off + eccbits) % 8);
@@ -1549,7 +1823,7 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
- int eccsize = nfc_geo->ecc_chunk_size;
+ int eccsize = nfc_geo->ecc_chunkn_size;
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *tmp_buf = this->raw_buffer;
uint8_t *oob = chip->oob_poi;
@@ -1557,6 +1831,7 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
size_t oob_bit_off;
size_t oob_byte_off;
int step;
+ int ecc_chunk_count;
/*
* Initialize all bits to 1 in case we don't have a buffer for the
@@ -1573,16 +1848,28 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
memcpy(tmp_buf, oob, nfc_geo->metadata_size);
oob_bit_off = nfc_geo->metadata_size * 8;
dst_bit_off = oob_bit_off;
+ ecc_chunk_count = nfc_geo->ecc_chunk_count;
+
+ /* if bch requires dedicate ecc for meta */
+ if (nfc_geo->ecc_for_meta) {
+ if (oob_required)
+ gpmi_copy_bits(tmp_buf, dst_bit_off,
+ oob, oob_bit_off, eccbits);
+
+ dst_bit_off += eccbits;
+ oob_bit_off += eccbits;
+ ecc_chunk_count = nfc_geo->ecc_chunk_count - 1;
+ }
/* Interleave payload data and ECC bits */
- for (step = 0; step < nfc_geo->ecc_chunk_count; step++) {
+ for (step = 0; step < ecc_chunk_count; step++) {
if (buf)
gpmi_copy_bits(tmp_buf, dst_bit_off,
buf, step * eccsize * 8, eccsize * 8);
dst_bit_off += eccsize * 8;
/* Align last ECC block to align a byte boundary */
- if (step == nfc_geo->ecc_chunk_count - 1 &&
+ if (step == ecc_chunk_count - 1 &&
(oob_bit_off + eccbits) % 8)
eccbits += 8 - ((oob_bit_off + eccbits) % 8);
@@ -1872,7 +2159,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this)
*/
chipnr = block >> (chip->chip_shift - chip->phys_erase_shift);
page = block << (chip->phys_erase_shift - chip->page_shift);
- byte = block << chip->phys_erase_shift;
+ byte = (loff_t) block << chip->phys_erase_shift;
/* Send the command to read the conventional block mark. */
chip->select_chip(mtd, chipnr);
@@ -1947,6 +2234,11 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
if (ret)
return ret;
+ /* Save the geometry to debugfs*/
+ ret = bch_create_debugfs(this);
+ if (ret)
+ return ret;
+
/* Init the nand_ecc_ctrl{} */
ecc->read_page = gpmi_ecc_read_page;
ecc->write_page = gpmi_ecc_write_page;
@@ -1957,7 +2249,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
ecc->read_oob_raw = gpmi_ecc_read_oob_raw;
ecc->write_oob_raw = gpmi_ecc_write_oob_raw;
ecc->mode = NAND_ECC_HW;
- ecc->size = bch_geo->ecc_chunk_size;
+ ecc->size = bch_geo->ecc_chunkn_size;
ecc->strength = bch_geo->ecc_strength;
mtd_set_ooblayout(mtd, &gpmi_ooblayout_ops);
@@ -1966,7 +2258,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
* (1) the chip is imx6, and
* (2) the size of the ECC parity is byte aligned.
*/
- if (GPMI_IS_MX6(this) &&
+ if ((GPMI_IS_MX6(this) || GPMI_IS_MX7(this)) &&
((bch_geo->gf_len * bch_geo->ecc_strength) % 8) == 0) {
ecc->read_subpage = gpmi_ecc_read_subpage;
chip->options |= NAND_SUBPAGE_READ;
@@ -2022,7 +2314,8 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
if (ret)
goto err_out;
- ret = nand_scan_ident(mtd, GPMI_IS_MX6(this) ? 2 : 1, NULL);
+ ret = nand_scan_ident(mtd, GPMI_IS_MX6(this) || GPMI_IS_MX7(this)\
+ ? 2 : 1, NULL);
if (ret)
goto err_out;
@@ -2032,6 +2325,10 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
if (of_property_read_bool(this->dev->of_node,
"fsl,no-blockmark-swap"))
this->swap_block_mark = false;
+
+ if (of_property_read_bool(this->dev->of_node,
+ "fsl,legacy-bch-geometry"))
+ this->legacy_bch_geometry = true;
}
dev_dbg(this->dev, "Blockmark swapping %sabled\n",
this->swap_block_mark ? "en" : "dis");
@@ -2073,9 +2370,21 @@ static const struct of_device_id gpmi_nand_id_table[] = {
.compatible = "fsl,imx6q-gpmi-nand",
.data = &gpmi_devdata_imx6q,
}, {
+ .compatible = "fsl,imx6qp-gpmi-nand",
+ .data = (void *)&gpmi_devdata_imx6qp,
+ }, {
.compatible = "fsl,imx6sx-gpmi-nand",
.data = &gpmi_devdata_imx6sx,
- }, {}
+ }, {
+ .compatible = "fsl,imx6ul-gpmi-nand",
+ .data = (void *)&gpmi_devdata_imx6ul,
+ }, {
+ .compatible = "fsl,imx7d-gpmi-nand",
+ .data = (void *)&gpmi_devdata_imx7d,
+ }, {
+ .compatible = "fsl,imx6ull-gpmi-nand",
+ .data = (void *)&gpmi_devdata_imx6ull,
+ }, { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
@@ -2105,6 +2414,10 @@ static int gpmi_nand_probe(struct platform_device *pdev)
if (ret)
goto exit_acquire_resources;
+ ret = init_rpm(this);
+ if (ret)
+ goto exit_nfc_init;
+
ret = init_hardware(this);
if (ret)
goto exit_nfc_init;
@@ -2129,6 +2442,7 @@ static int gpmi_nand_remove(struct platform_device *pdev)
struct gpmi_nand_data *this = platform_get_drvdata(pdev);
gpmi_nand_exit(this);
+ pm_runtime_disable(this->dev);
release_resources(this);
return 0;
}
@@ -2139,6 +2453,7 @@ static int gpmi_pm_suspend(struct device *dev)
struct gpmi_nand_data *this = dev_get_drvdata(dev);
release_dma_channels(this);
+ pinctrl_pm_select_sleep_state(dev);
return 0;
}
@@ -2147,6 +2462,8 @@ static int gpmi_pm_resume(struct device *dev)
struct gpmi_nand_data *this = dev_get_drvdata(dev);
int ret;
+ pinctrl_pm_select_default_state(dev);
+
ret = acquire_dma_channels(this);
if (ret < 0)
return ret;
@@ -2173,7 +2490,33 @@ static int gpmi_pm_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
+#define gpmi_enable_clk(x) __gpmi_enable_clk(x, true)
+#define gpmi_disable_clk(x) __gpmi_enable_clk(x, false)
+
+int gpmi_runtime_suspend(struct device *dev)
+{
+ struct gpmi_nand_data *this = dev_get_drvdata(dev);
+
+ gpmi_disable_clk(this);
+ release_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+
+int gpmi_runtime_resume(struct device *dev)
+{
+ struct gpmi_nand_data *this = dev_get_drvdata(dev);
+ int ret;
+
+ ret = gpmi_enable_clk(this);
+ if (ret)
+ return ret;
+
+ request_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+
static const struct dev_pm_ops gpmi_pm_ops = {
+ SET_RUNTIME_PM_OPS(gpmi_runtime_suspend, gpmi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume)
};
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index 4e49a1f5fa27..63243bcab1eb 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -1,7 +1,7 @@
/*
* Freescale GPMI NAND Flash Driver
*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010-2016 Freescale Semiconductor, Inc.
* Copyright (C) 2008 Embedded Alley Solutions, Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -39,9 +39,9 @@ struct resources {
* @page_size: The size, in bytes, of a physical page, including
* both data and OOB.
* @metadata_size: The size, in bytes, of the metadata.
- * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note
- * the first chunk in the page includes both data and
- * metadata, so it's a bit larger than this value.
+ * @ecc_chunk0_size: The size, in bytes, of a first ECC chunk.
+ * @ecc_chunkn_size: The size, in bytes, of a single ECC chunk after
+ * the first chunk in the page.
* @ecc_chunk_count: The number of ECC chunks in the page,
* @payload_size: The size, in bytes, of the payload buffer.
* @auxiliary_size: The size, in bytes, of the auxiliary buffer.
@@ -51,19 +51,23 @@ struct resources {
* which the underlying physical block mark appears.
* @block_mark_bit_offset: The bit offset into the ECC-based page view at
* which the underlying physical block mark appears.
+ * @ecc_for_meta: The flag to indicate if there is a dedicate ecc
+ * for meta.
*/
struct bch_geometry {
unsigned int gf_len;
unsigned int ecc_strength;
unsigned int page_size;
unsigned int metadata_size;
- unsigned int ecc_chunk_size;
+ unsigned int ecc_chunk0_size;
+ unsigned int ecc_chunkn_size;
unsigned int ecc_chunk_count;
unsigned int payload_size;
unsigned int auxiliary_size;
unsigned int auxiliary_status_offset;
unsigned int block_mark_byte_offset;
unsigned int block_mark_bit_offset;
+ unsigned int ecc_for_meta; /* ECC for meta data */
};
/**
@@ -123,7 +127,11 @@ enum gpmi_type {
IS_MX23,
IS_MX28,
IS_MX6Q,
- IS_MX6SX
+ IS_MX6QP,
+ IS_MX6SX,
+ IS_MX7D,
+ IS_MX6UL,
+ IS_MX6ULL,
};
struct gpmi_devdata {
@@ -189,6 +197,8 @@ struct gpmi_nand_data {
dma_addr_t auxiliary_phys;
void *raw_buffer;
+ /* legacy bch geometry flag */
+ bool legacy_bch_geometry;
/* DMA channels */
#define DMA_CHANS 8
@@ -275,10 +285,12 @@ extern int start_dma_with_bch_irq(struct gpmi_nand_data *,
struct dma_async_tx_descriptor *);
/* GPMI-NAND helper function library */
+extern int __gpmi_enable_clk(struct gpmi_nand_data *, bool v);
extern int gpmi_init(struct gpmi_nand_data *);
extern int gpmi_extra_init(struct gpmi_nand_data *);
extern void gpmi_clear_bch(struct gpmi_nand_data *);
extern void gpmi_dump_info(struct gpmi_nand_data *);
+extern int bch_create_debugfs(struct gpmi_nand_data *);
extern int bch_set_geometry(struct gpmi_nand_data *);
extern int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip);
extern int gpmi_send_command(struct gpmi_nand_data *);
@@ -304,7 +316,13 @@ void gpmi_copy_bits(u8 *dst, size_t dst_bit_off,
#define GPMI_IS_MX23(x) ((x)->devdata->type == IS_MX23)
#define GPMI_IS_MX28(x) ((x)->devdata->type == IS_MX28)
#define GPMI_IS_MX6Q(x) ((x)->devdata->type == IS_MX6Q)
+#define GPMI_IS_MX6QP(x) ((x)->devdata->type == IS_MX6QP)
#define GPMI_IS_MX6SX(x) ((x)->devdata->type == IS_MX6SX)
+#define GPMI_IS_MX7D(x) ((x)->devdata->type == IS_MX7D)
+#define GPMI_IS_MX6UL(x) ((x)->devdata->type == IS_MX6UL)
+#define GPMI_IS_MX6ULL(x) ((x)->devdata->type == IS_MX6ULL)
-#define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6SX(x))
+#define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6QP(x)\
+ || GPMI_IS_MX6SX(x) || GPMI_IS_MX6UL(x) || GPMI_IS_MX6ULL(x))
+#define GPMI_IS_MX7(x) (GPMI_IS_MX7D(x))
#endif
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c
index 5c82e4ef1904..47f675098d63 100644
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
@@ -1,7 +1,7 @@
/*
* Freescale QuadSPI driver.
*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-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 as published by
@@ -41,9 +41,14 @@
#define QUADSPI_QUIRK_TKT253890 (1 << 2)
/* Controller cannot wake up from wait mode, TKT245618 */
#define QUADSPI_QUIRK_TKT245618 (1 << 3)
+/* Need low level code to control the clock */
+#define QUADSPI_QUIRK_LL_CLK (1 << 4)
/* The registers */
#define QUADSPI_MCR 0x00
+#define MX6SX_QUADSPI_MCR_TX_DDR_DELAY_EN_SHIFT 29
+#define MX6SX_QUADSPI_MCR_TX_DDR_DELAY_EN_MASK \
+ (1 << MX6SX_QUADSPI_MCR_TX_DDR_DELAY_EN_SHIFT)
#define QUADSPI_MCR_RESERVED_SHIFT 16
#define QUADSPI_MCR_RESERVED_MASK (0xF << QUADSPI_MCR_RESERVED_SHIFT)
#define QUADSPI_MCR_MDIS_SHIFT 14
@@ -61,6 +66,11 @@
#define QUADSPI_MCR_SWRSTSD_SHIFT 0
#define QUADSPI_MCR_SWRSTSD_MASK (1 << QUADSPI_MCR_SWRSTSD_SHIFT)
+#define QUADSPI_FLSHCR 0x0c
+#define QUADSPI_FLSHCR_TDH_SHIFT 16
+#define QUADSPI_FLSHCR_TDH_MASK (3 << QUADSPI_FLSHCR_TDH_SHIFT)
+#define QUADSPI_FLSHCR_TDH_DDR_EN (1 << QUADSPI_FLSHCR_TDH_SHIFT)
+
#define QUADSPI_IPCR 0x08
#define QUADSPI_IPCR_SEQID_SHIFT 24
#define QUADSPI_IPCR_SEQID_MASK (0xF << QUADSPI_IPCR_SEQID_SHIFT)
@@ -205,15 +215,49 @@
#define SEQID_RDCR 9
#define SEQID_EN4B 10
#define SEQID_BRWR 11
+#define SEQID_RD_EVCR 12
+#define SEQID_WD_EVCR 13
+
+/* last two lut slots for dynamic luts*/
+#define SEQID_DYNAMIC_CMD0 14
+#define SEQID_DYNAMIC_CMD1 15
+
+#define QUADSPI_MIN_IOMAP SZ_4M
-#define QUADSPI_MIN_IOMAP SZ_4M
+/* dynamic lut configs */
+#define MAX_LUT_REGS 4
+struct lut_desc {
+ u8 cmd;
+ u32 lut[MAX_LUT_REGS];
+};
+/*
+ * define two lut_des in the struct because many commands use in pairs.
+ * To add a single command, just leave the second desc as blank.
+ */
+struct lut_desc_pair {
+ struct lut_desc lut_desc0;
+ struct lut_desc lut_desc1;
+};
+
+struct lut_desc_pair current_lut_pair;
+
+static const struct lut_desc_pair dynamic_lut_table[] = {
+ /* VCR RD/WR pair */
+ { {SPINOR_OP_RD_VCR, {LUT0(CMD, PAD1, SPINOR_OP_RD_EVCR) |
+ LUT1(FSL_READ, PAD1, 0x1)} },
+ {SPINOR_OP_WR_VCR, {LUT0(CMD, PAD1, SPINOR_OP_WD_EVCR) |
+ LUT1(FSL_WRITE, PAD1, 0x1)} },
+ },
+ {/* sentinel */},
+};
enum fsl_qspi_devtype {
FSL_QUADSPI_VYBRID,
FSL_QUADSPI_IMX6SX,
FSL_QUADSPI_IMX7D,
FSL_QUADSPI_IMX6UL,
FSL_QUADSPI_LS1021A,
+ FSL_QUADSPI_IMX7ULP,
};
struct fsl_qspi_devtype_data {
@@ -267,6 +311,15 @@ static struct fsl_qspi_devtype_data ls1021a_data = {
.driver_data = 0,
};
+static struct fsl_qspi_devtype_data imx7ulp_data = {
+ .devtype = FSL_QUADSPI_IMX7ULP,
+ .rxfifo = 64,
+ .txfifo = 64,
+ .ahb_buf_size = 128,
+ .driver_data = QUADSPI_QUIRK_LL_CLK
+ | QUADSPI_QUIRK_TKT253890
+};
+
#define FSL_QSPI_MAX_CHIP 4
struct fsl_qspi {
struct spi_nor nor[FSL_QSPI_MAX_CHIP];
@@ -285,6 +338,7 @@ struct fsl_qspi {
unsigned int chip_base_addr; /* We may support two chips. */
bool has_second_chip;
bool big_endian;
+ u32 ddr_smp;
struct mutex lock;
struct pm_qos_request pm_qos_req;
};
@@ -309,6 +363,11 @@ static inline int needs_wakeup_wait_mode(struct fsl_qspi *q)
return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT245618;
}
+static inline int needs_ll_handle_clock(struct fsl_qspi *q)
+{
+ return q->devtype_data->driver_data & QUADSPI_QUIRK_LL_CLK;
+}
+
/*
* R/W functions for big- or little-endian registers:
* The qSPI controller's endian is independent of the CPU core's endian.
@@ -372,8 +431,10 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
{
void __iomem *base = q->iobase;
int rxfifo = q->devtype_data->rxfifo;
+ struct spi_nor *nor = &q->nor[0];
+ u8 addrlen = (nor->addr_width == 3) ? ADDR24BIT : ADDR32BIT;
u32 lut_base;
- u8 cmd, addrlen, dummy;
+ u8 op, dm;
int i;
fsl_qspi_unlock_lut(q);
@@ -382,24 +443,57 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
for (i = 0; i < QUADSPI_LUT_NUM; i++)
qspi_writel(q, 0, base + QUADSPI_LUT_BASE + i * 4);
- /* Quad Read */
+ /* Quad Read and DDR Quad Read*/
lut_base = SEQID_QUAD_READ * 4;
-
- if (q->nor_size <= SZ_16M) {
- cmd = SPINOR_OP_READ_1_1_4;
- addrlen = ADDR24BIT;
- dummy = 8;
- } else {
- /* use the 4-byte address */
- cmd = SPINOR_OP_READ_1_1_4;
- addrlen = ADDR32BIT;
- dummy = 8;
- }
-
- qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
+ op = nor->read_opcode;
+ dm = nor->read_dummy;
+ if (nor->flash_read == SPI_NOR_QUAD) {
+ if (op == SPINOR_OP_READ_1_1_4 || op == SPINOR_OP_READ4_1_1_4) {
+ /* read mode : 1-1-4 */
+ qspi_writel(q, LUT0(CMD, PAD1, op) | LUT1(ADDR, PAD1, addrlen),
+ base + QUADSPI_LUT(lut_base));
+
+ qspi_writel(q, LUT0(DUMMY, PAD1, dm) | LUT1(FSL_READ, PAD4, rxfifo),
+ base + QUADSPI_LUT(lut_base + 1));
+ } else {
+ dev_err(nor->dev, "Unsupported opcode : 0x%.2x\n", op);
+ }
+ } else if (nor->flash_read == SPI_NOR_NORMAL) {
+ writel(LUT0(CMD, PAD1, op) | LUT1(ADDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
- qspi_writel(q, LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo),
+ writel(LUT0(FSL_READ, PAD1, rxfifo) | LUT1(JMP_ON_CS, PAD1, 0),
base + QUADSPI_LUT(lut_base + 1));
+ } else if (nor->flash_read == SPI_NOR_DDR_QUAD) {
+ if (op == SPINOR_OP_READ_1_4_4_D ||
+ op == SPINOR_OP_READ4_1_4_4_D) {
+ /* read mode : 1-4-4, such as Spansion s25fl128s. */
+ qspi_writel(q, LUT0(CMD, PAD1, op)
+ | LUT1(ADDR_DDR, PAD4, addrlen),
+ base + QUADSPI_LUT(lut_base));
+
+ qspi_writel(q, LUT0(MODE_DDR, PAD4, 0xff)
+ | LUT1(DUMMY, PAD1, dm),
+ base + QUADSPI_LUT(lut_base + 1));
+
+ qspi_writel(q, LUT0(FSL_READ_DDR, PAD4, rxfifo)
+ | LUT1(JMP_ON_CS, PAD1, 0),
+ base + QUADSPI_LUT(lut_base + 2));
+ } else if (op == SPINOR_OP_READ_1_1_4_D) {
+ /* read mode : 1-1-4, such as Micron N25Q256A. */
+ qspi_writel(q, LUT0(CMD, PAD1, op)
+ | LUT1(ADDR_DDR, PAD1, addrlen),
+ base + QUADSPI_LUT(lut_base));
+
+ qspi_writel(q, LUT0(DUMMY, PAD1, dm)
+ | LUT1(FSL_READ_DDR, PAD4, rxfifo),
+ base + QUADSPI_LUT(lut_base + 1));
+
+ qspi_writel(q, LUT0(JMP_ON_CS, PAD1, 0),
+ base + QUADSPI_LUT(lut_base + 2));
+ } else {
+ dev_err(nor->dev, "Unsupported opcode : 0x%.2x\n", op);
+ }
+ }
/* Write enable */
lut_base = SEQID_WREN * 4;
@@ -408,18 +502,8 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
/* Page Program */
lut_base = SEQID_PP * 4;
-
- if (q->nor_size <= SZ_16M) {
- cmd = SPINOR_OP_PP;
- addrlen = ADDR24BIT;
- } else {
- /* use the 4-byte address */
- cmd = SPINOR_OP_PP;
- addrlen = ADDR32BIT;
- }
-
- qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
- base + QUADSPI_LUT(lut_base));
+ qspi_writel(q, LUT0(CMD, PAD1, nor->program_opcode) | LUT1(ADDR, PAD1, addrlen),
+ base + QUADSPI_LUT(lut_base));
qspi_writel(q, LUT0(FSL_WRITE, PAD1, 0),
base + QUADSPI_LUT(lut_base + 1));
@@ -431,12 +515,8 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
/* Erase a sector */
lut_base = SEQID_SE * 4;
-
- cmd = q->nor[0].erase_opcode;
- addrlen = q->nor_size <= SZ_16M ? ADDR24BIT : ADDR32BIT;
-
- qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
- base + QUADSPI_LUT(lut_base));
+ qspi_writel(q, LUT0(CMD, PAD1, nor->erase_opcode) | LUT1(ADDR, PAD1, addrlen),
+ base + QUADSPI_LUT(lut_base));
/* Erase the whole chip */
lut_base = SEQID_CHIP_ERASE * 4;
@@ -476,14 +556,85 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR),
base + QUADSPI_LUT(lut_base));
+ /* Read EVCR register */
+ lut_base = SEQID_RD_EVCR * 4;
+ writel(LUT0(CMD, PAD1, SPINOR_OP_RD_EVCR), base + QUADSPI_LUT(lut_base));
+
+ /* Write EVCR register */
+ lut_base = SEQID_WD_EVCR * 4;
+ writel(LUT0(CMD, PAD1, SPINOR_OP_WD_EVCR), base + QUADSPI_LUT(lut_base));
fsl_qspi_lock_lut(q);
}
+static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q);
+static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q);
+
+static int fsl_qspi_update_dynamic_lut(struct fsl_qspi *q, int index)
+{
+ void __iomem *base = q->iobase;
+ u32 lut_base;
+ int i;
+ int size;
+
+ fsl_qspi_unlock_lut(q);
+
+ lut_base = SEQID_DYNAMIC_CMD0 * 4;
+ size = ARRAY_SIZE(dynamic_lut_table[index].lut_desc0.lut);
+ for (i = 0; i < size; i++) {
+ writel(dynamic_lut_table[index].lut_desc0.lut[i],
+ base + QUADSPI_LUT(lut_base + i));
+ }
+
+ lut_base = SEQID_DYNAMIC_CMD1 * 4;
+ size = ARRAY_SIZE(dynamic_lut_table[index].lut_desc1.lut);
+ for (i = 0; i < size; i++) {
+ writel(dynamic_lut_table[index].lut_desc1.lut[i],
+ base + QUADSPI_LUT(lut_base + i));
+ }
+
+ fsl_qspi_lock_lut(q);
+
+ return 0;
+}
+
+static int fsl_qspi_search_dynamic_lut(struct fsl_qspi *q, u8 cmd)
+{
+ int i;
+ int ret = 0;
+
+ if (cmd == current_lut_pair.lut_desc0.cmd)
+ return SEQID_DYNAMIC_CMD0;
+ if (cmd == current_lut_pair.lut_desc1.cmd)
+ return SEQID_DYNAMIC_CMD1;
+ for (i = 0; i < ARRAY_SIZE(dynamic_lut_table); i++) {
+ if (cmd == dynamic_lut_table[i].lut_desc0.cmd)
+ ret = SEQID_DYNAMIC_CMD0;
+ if (cmd == dynamic_lut_table[i].lut_desc1.cmd)
+ ret = SEQID_DYNAMIC_CMD1;
+ if (ret) {
+ if (fsl_qspi_update_dynamic_lut(q, i)) {
+ pr_err(" failed to update dynamic lut\n");
+ return 0;
+ }
+ current_lut_pair = dynamic_lut_table[i];
+ return ret;
+ }
+ }
+ return ret;
+}
+
/* Get the SEQID for the command */
static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd)
{
+ int ret;
+
switch (cmd) {
+ case SPINOR_OP_READ_1_1_4_D:
+ case SPINOR_OP_READ_1_4_4_D:
+ case SPINOR_OP_READ4_1_4_4_D:
+ case SPINOR_OP_READ4_1_1_4:
case SPINOR_OP_READ_1_1_4:
+ case SPINOR_OP_READ:
return SEQID_QUAD_READ;
case SPINOR_OP_WREN:
return SEQID_WREN;
@@ -491,6 +642,7 @@ static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd)
return SEQID_WRDI;
case SPINOR_OP_RDSR:
return SEQID_RDSR;
+ case SPINOR_OP_BE_4K:
case SPINOR_OP_SE:
return SEQID_SE;
case SPINOR_OP_CHIP_ERASE:
@@ -507,9 +659,16 @@ static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd)
return SEQID_EN4B;
case SPINOR_OP_BRWR:
return SEQID_BRWR;
+ case SPINOR_OP_RD_EVCR:
+ return SEQID_RD_EVCR;
+ case SPINOR_OP_WD_EVCR:
+ return SEQID_WD_EVCR;
default:
if (cmd == q->nor[0].erase_opcode)
return SEQID_SE;
+ ret = fsl_qspi_search_dynamic_lut(q, cmd);
+ if (ret)
+ return ret;
dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd);
break;
}
@@ -680,6 +839,8 @@ static void fsl_qspi_set_map_addr(struct fsl_qspi *q)
static void fsl_qspi_init_abh_read(struct fsl_qspi *q)
{
void __iomem *base = q->iobase;
+ struct spi_nor *nor = &q->nor[0];
+ u32 reg, reg2;
int seqid;
/* AHB configuration for access buffer 0/1/2 .*/
@@ -701,9 +862,40 @@ static void fsl_qspi_init_abh_read(struct fsl_qspi *q)
qspi_writel(q, 0, base + QUADSPI_BUF2IND);
/* Set the default lut sequence for AHB Read. */
- seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode);
+ seqid = fsl_qspi_get_seqid(q, nor->read_opcode);
qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT,
q->iobase + QUADSPI_BFGENCR);
+
+ /* enable the DDR quad read */
+ if (nor->flash_read == SPI_NOR_DDR_QUAD) {
+ reg = readl(q->iobase + QUADSPI_MCR);
+
+ /* Firstly, disable the module */
+ qspi_writel(q, reg | QUADSPI_MCR_MDIS_MASK,
+ q->iobase + QUADSPI_MCR);
+
+ /* Set the Sampling Register for DDR */
+ reg2 = readl(q->iobase + QUADSPI_SMPR);
+ reg2 &= ~QUADSPI_SMPR_DDRSMP_MASK;
+ reg2 |= ((q->ddr_smp << QUADSPI_SMPR_DDRSMP_SHIFT) &
+ QUADSPI_SMPR_DDRSMP_MASK);
+ qspi_writel(q, reg2, q->iobase + QUADSPI_SMPR);
+
+ /* Enable the module again (enable the DDR too) */
+ reg |= QUADSPI_MCR_DDR_EN_MASK;
+ if (q->devtype_data->devtype == FSL_QUADSPI_IMX6SX)
+ reg |= MX6SX_QUADSPI_MCR_TX_DDR_DELAY_EN_MASK;
+
+ qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
+
+ if ((q->devtype_data->devtype == FSL_QUADSPI_IMX6UL) ||
+ (q->devtype_data->devtype == FSL_QUADSPI_IMX7D)) {
+ reg = readl(q->iobase + QUADSPI_FLSHCR);
+ reg &= ~QUADSPI_FLSHCR_TDH_MASK;
+ reg |= QUADSPI_FLSHCR_TDH_DDR_EN;
+ qspi_writel(q, reg, q->iobase + QUADSPI_FLSHCR);
+ }
+ }
}
/* This function was used to prepare and enable QSPI clock */
@@ -750,13 +942,21 @@ static int fsl_qspi_nor_setup(struct fsl_qspi *q)
/* the default frequency, we will change it in the future. */
ret = clk_set_rate(q->clk, 66000000);
- if (ret)
+ if (ret && !needs_ll_handle_clock(q))
return ret;
ret = fsl_qspi_clk_prep_enable(q);
if (ret)
return ret;
+ if ((q->devtype_data->devtype == FSL_QUADSPI_IMX6UL) ||
+ (q->devtype_data->devtype == FSL_QUADSPI_IMX7D)) {
+ /* clear the DDR_EN bit for 6UL and 7D */
+ reg = readl(base + QUADSPI_MCR);
+ writel(~(QUADSPI_MCR_DDR_EN_MASK) & reg, base + QUADSPI_MCR);
+ udelay(1);
+ }
+
/* Reset the module */
qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
base + QUADSPI_MCR);
@@ -800,7 +1000,7 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q)
fsl_qspi_clk_disable_unprep(q);
ret = clk_set_rate(q->clk, rate);
- if (ret)
+ if (ret && !needs_ll_handle_clock(q))
return ret;
ret = fsl_qspi_clk_prep_enable(q);
@@ -809,6 +1009,7 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q)
/* Init the LUT table again. */
fsl_qspi_init_lut(q);
+ fsl_qspi_update_dynamic_lut(q, 0);
/* Init for AHB read */
fsl_qspi_init_abh_read(q);
@@ -822,6 +1023,8 @@ static const struct of_device_id fsl_qspi_dt_ids[] = {
{ .compatible = "fsl,imx7d-qspi", .data = (void *)&imx7d_data, },
{ .compatible = "fsl,imx6ul-qspi", .data = (void *)&imx6ul_data, },
{ .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, },
+ { .compatible = "fsl,imx6ull-qspi", .data = (void *)&imx6ul_data, },
+ { .compatible = "fsl,imx7ulp-qspi", .data = (void *)&imx7ulp_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids);
@@ -997,6 +1200,10 @@ static int fsl_qspi_probe(struct platform_device *pdev)
/* find the resources */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI");
+ if (!res) {
+ dev_err(dev, "QuadSPI get resource IORESOURCE_MEM failed\n");
+ return -ENODEV;
+ }
q->iobase = devm_ioremap_resource(dev, res);
if (IS_ERR(q->iobase))
return PTR_ERR(q->iobase);
@@ -1004,6 +1211,11 @@ static int fsl_qspi_probe(struct platform_device *pdev)
q->big_endian = of_property_read_bool(np, "big-endian");
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"QuadSPI-memory");
+ if (!res) {
+ dev_err(dev,
+ "QuadSPI-memory get resource IORESOURCE_MEM failed\n");
+ return -ENODEV;
+ }
if (!devm_request_mem_region(dev, res->start, resource_size(res),
res->name)) {
dev_err(dev, "can't request region for resource %pR\n", res);
@@ -1021,6 +1233,12 @@ static int fsl_qspi_probe(struct platform_device *pdev)
if (IS_ERR(q->clk))
return PTR_ERR(q->clk);
+ /* find ddrsmp value */
+ ret = of_property_read_u32(dev->of_node, "ddrsmp",
+ &q->ddr_smp);
+ if (ret)
+ q->ddr_smp = 0;
+
ret = fsl_qspi_clk_prep_enable(q);
if (ret) {
dev_err(dev, "can not enable the clock\n");
@@ -1052,6 +1270,9 @@ static int fsl_qspi_probe(struct platform_device *pdev)
/* iterate the subnodes. */
for_each_available_child_of_node(dev->of_node, np) {
+ enum read_mode mode = SPI_NOR_QUAD;
+ u32 dummy = 0;
+
/* skip the holes */
if (!q->has_second_chip)
i *= 2;
@@ -1078,10 +1299,16 @@ static int fsl_qspi_probe(struct platform_device *pdev)
if (ret < 0)
goto mutex_failed;
+ /* Can we enable the DDR Quad Read? */
+ ret = of_property_read_u32(np, "spi-nor,ddr-quad-read-dummy",
+ &dummy);
+ if (!ret && dummy > 0)
+ mode = SPI_NOR_DDR_QUAD;
+
/* set the chip address for READID */
fsl_qspi_set_base_addr(q, nor);
- ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
+ ret = spi_nor_scan(nor, NULL, mode);
if (ret)
goto mutex_failed;
@@ -1162,6 +1389,7 @@ static int fsl_qspi_remove(struct platform_device *pdev)
static int fsl_qspi_suspend(struct platform_device *pdev, pm_message_t state)
{
+ pinctrl_pm_select_sleep_state(&pdev->dev);
return 0;
}
@@ -1170,6 +1398,8 @@ static int fsl_qspi_resume(struct platform_device *pdev)
int ret;
struct fsl_qspi *q = platform_get_drvdata(pdev);
+ pinctrl_pm_select_default_state(&pdev->dev);
+
ret = fsl_qspi_clk_prep_enable(q);
if (ret)
return ret;
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 21dde5249085..0b6134f48d66 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -3,7 +3,8 @@
* influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c
*
* Copyright (C) 2005, Intec Automation Inc.
- * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -75,6 +76,7 @@ struct flash_info {
* bit. Must be used with
* SPI_NOR_HAS_LOCK.
*/
+#define SPI_NOR_DDR_QUAD_READ BIT(10) /* Flash supports DDR Quad Read */
};
#define JEDEC_MFR(info) ((info)->id[0])
@@ -146,6 +148,21 @@ static int read_cr(struct spi_nor *nor)
static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
{
switch (nor->flash_read) {
+ case SPI_NOR_DDR_QUAD:
+ {
+ struct device_node *np = spi_nor_get_flash_node(nor);
+ u32 dummy;
+
+ /*
+ * The m25p80.c can not support the DDR quad read.
+ * We set the dummy cycles to 8 by default. The SPI NOR
+ * controller driver can set it in its child DT node.
+ * We parse it out here.
+ */
+ if (!of_property_read_u32(np, "spi-nor,ddr-quad-read-dummy",
+ &dummy))
+ return dummy;
+ }
case SPI_NOR_FAST:
case SPI_NOR_DUAL:
case SPI_NOR_QUAD:
@@ -869,10 +886,12 @@ static const struct flash_info spi_nor_ids[] = {
{ "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
{ "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
{ "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
+ { "mx25r6435f", INFO(0xc22817, 0, 64 * 1024, 128, 0) },
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+ { "mx25l51245g", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_DDR_QUAD_READ) },
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) },
{ "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
@@ -883,7 +902,7 @@ static const struct flash_info spi_nor_ids[] = {
{ "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
{ "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
{ "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_DDR_QUAD_READ) },
{ "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
{ "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
{ "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
@@ -906,6 +925,7 @@ static const struct flash_info spi_nor_ids[] = {
{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
{ "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
{ "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
+ { "s25fl128s", INFO(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_QUAD_READ | SPI_NOR_DDR_QUAD_READ) },
{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
@@ -1172,9 +1192,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
ssize_t written;
page_offset = (to + i) & (nor->page_size - 1);
- WARN_ONCE(page_offset,
- "Writing at offset %zu into a NOR page. Writing partial pages may decrease reliability and increase wear of NOR flash.",
- page_offset);
/* the size of data remaining on the first page */
page_remain = min_t(size_t,
nor->page_size - page_offset, len - i);
@@ -1272,6 +1289,35 @@ static int spansion_quad_enable(struct spi_nor *nor)
return 0;
}
+static int set_ddr_quad_mode(struct spi_nor *nor, const struct flash_info *info)
+{
+ int status;
+
+ switch (JEDEC_MFR(info)) {
+ case CFI_MFR_AMD: /* Spansion, actually */
+ status = spansion_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev,
+ "Spansion DDR quad-read not enabled\n");
+ return status;
+ }
+ return status;
+ case CFI_MFR_MACRONIX:
+ status = macronix_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev,
+ "Macronix DDR quad-read not enabled\n");
+ return status;
+ }
+ return status;
+ case CFI_MFR_ST: /* Micron, actually */
+ /* DTR quad read works with the Extended SPI protocol. */
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
{
int status;
@@ -1440,8 +1486,15 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
if (info->flags & SPI_NOR_NO_FR)
nor->flash_read = SPI_NOR_NORMAL;
- /* Quad/Dual-read mode takes precedence over fast/normal */
- if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
+ /* DDR Quad/Quad/Dual-read mode takes precedence over fast/normal */
+ if (mode == SPI_NOR_DDR_QUAD && info->flags & SPI_NOR_DDR_QUAD_READ) {
+ ret = set_ddr_quad_mode(nor, info);
+ if (ret) {
+ dev_err(dev, "DDR quad mode not supported\n");
+ return ret;
+ }
+ nor->flash_read = SPI_NOR_DDR_QUAD;
+ } else if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
ret = set_quad_mode(nor, info);
if (ret) {
dev_err(dev, "quad mode not supported\n");
@@ -1454,6 +1507,18 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
/* Default commands */
switch (nor->flash_read) {
+ case SPI_NOR_DDR_QUAD:
+ if (JEDEC_MFR(info) == CFI_MFR_AMD) { /* Spansion */
+ nor->read_opcode = SPINOR_OP_READ_1_4_4_D;
+ } else if (JEDEC_MFR(info) == CFI_MFR_ST) {
+ nor->read_opcode = SPINOR_OP_READ_1_1_4_D;
+ } else if (JEDEC_MFR(info) == CFI_MFR_MACRONIX) {
+ nor->read_opcode = SPINOR_OP_READ_1_4_4_D;
+ } else {
+ dev_err(dev, "DDR Quad Read is not supported.\n");
+ return -EINVAL;
+ }
+ break;
case SPI_NOR_QUAD:
nor->read_opcode = SPINOR_OP_READ_1_1_4;
break;
@@ -1481,6 +1546,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
/* Dedicated 4-byte command set */
switch (nor->flash_read) {
+ case SPI_NOR_DDR_QUAD:
+ nor->read_opcode = SPINOR_OP_READ4_1_4_4_D;
+ break;
case SPI_NOR_QUAD:
nor->read_opcode = SPINOR_OP_READ4_1_1_4;
break;
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 85d54f37e28f..d7059e538e69 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -628,7 +628,7 @@ static int io_init(struct ubi_device *ubi, int max_beb_per1024)
dbg_gen("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
dbg_gen("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
- if (ubi->mtd->numeraseregions != 0) {
+ if (ubi->mtd->numeraseregions > 1) {
/*
* Some flashes have several erase regions. Different regions
* may have different eraseblock size and other
diff --git a/drivers/mxc/Kconfig b/drivers/mxc/Kconfig
new file mode 100644
index 000000000000..3dfa29bffdce
--- /dev/null
+++ b/drivers/mxc/Kconfig
@@ -0,0 +1,24 @@
+# drivers/mxc/Kconfig
+
+if ARCH_MXC
+
+menu "MXC support drivers"
+
+config MXC_IPU
+ bool "Image Processing Unit Driver"
+ select MXC_IPU_V3
+ help
+ If you plan to use the Image Processing unit, say
+ Y here. IPU is needed by Framebuffer and V4L2 drivers.
+
+source "drivers/mxc/mlb/Kconfig"
+source "drivers/mxc/ipu3/Kconfig"
+source "drivers/mxc/gpu-viv/Kconfig"
+source "drivers/mxc/sim/Kconfig"
+source "drivers/mxc/mipi/Kconfig"
+source "drivers/mxc/vpu/Kconfig"
+source "drivers/mxc/hdmi-cec/Kconfig"
+
+endmenu
+
+endif
diff --git a/drivers/mxc/Makefile b/drivers/mxc/Makefile
new file mode 100644
index 000000000000..8374cfa5492a
--- /dev/null
+++ b/drivers/mxc/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_MXC_MLB) += mlb/
+obj-$(CONFIG_MXC_SIM) += sim/
+obj-$(CONFIG_MXC_VPU) += vpu/
+obj-$(CONFIG_MXC_IPU_V3) += ipu3/
+obj-$(CONFIG_MXC_HDMI_CEC) += hdmi-cec/
+obj-$(CONFIG_MXC_GPU_VIV) += gpu-viv/
+obj-$(CONFIG_MXC_MIPI_CSI2) += mipi/
diff --git a/drivers/mxc/gpu-viv/Kbuild b/drivers/mxc/gpu-viv/Kbuild
new file mode 100644
index 000000000000..06e0b254c2d8
--- /dev/null
+++ b/drivers/mxc/gpu-viv/Kbuild
@@ -0,0 +1,308 @@
+##############################################################################
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2014 - 2017 Vivante Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+##############################################################################
+#
+# The GPL License (GPL)
+#
+# Copyright (C) 2014 - 2017 Vivante Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; 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.
+#
+##############################################################################
+#
+# Note: This software is released under dual MIT and GPL licenses. A
+# recipient may use this file under the terms of either the MIT license or
+# GPL License. If you wish to use only one license not the other, you can
+# indicate your decision by deleting one of the above license notices in your
+# version of this file.
+#
+##############################################################################
+
+
+#
+# Linux build file for kernel HAL driver.
+#
+AQROOT := $(srctree)/drivers/mxc/gpu-viv
+
+include $(AQROOT)/config
+
+soc_vendor := $(firstword $(subst -, ,$(SOC_PLATFORM)))
+soc_board := $(lastword $(subst -, ,$(SOC_PLATFORM)))
+
+KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+OS_KERNEL_DIR := hal/os/linux/kernel
+ARCH_KERNEL_DIR := hal/kernel/arch
+ARCH_VG_KERNEL_DIR := hal/kernel/archvg
+HAL_KERNEL_DIR := hal/kernel
+TA_DIR := hal/security_v1
+HOST := $(shell hostname)
+
+# Include platform config if exists.
+-include $(AQROOT)/$(OS_KERNEL_DIR)/platform/$(soc_vendor)/gc_hal_kernel_platform_$(soc_board).config
+
+MODULE_NAME ?= galcore
+CUSTOMER_ALLOCATOR_OBJS ?=
+ALLOCATOR_ARRAY_H_LOCATION ?= $(OS_KERNEL_DIR)/allocator/default/
+
+EXTRA_CFLAGS += -Werror
+
+OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_math.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_os.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_debugfs.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_allocator.o \
+ $(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_user_memory.o \
+ $(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_dma.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o \
+ $(OS_KERNEL_DIR)/platform/$(soc_vendor)/gc_hal_kernel_platform_$(soc_board).o
+
+ifneq ($(CONFIG_DMA_SHARED_BUFFER),)
+OBJS += $(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_dmabuf.o
+endif
+
+ifneq ($(CONFIG_IOMMU_SUPPORT),)
+OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_iommu.o
+endif
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_async_command.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_db.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_debug.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_power.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_security_v1.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_context.o \
+ $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
+
+ifeq ($(VIVANTE_ENABLE_3D), 1)
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_recorder.o
+endif
+
+ifeq ($(VIVANTE_ENABLE_VG), 1)
+OBJS +=\
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_vg.o\
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command_vg.o\
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt_vg.o\
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu_vg.o\
+ $(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_command_vg.o\
+ $(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_vg.o
+endif
+
+ifneq ($(CONFIG_SYNC),)
+EXTRA_CFLAGS += -Idrivers/staging/android
+
+OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
+else
+ ifneq ($(CONFIG_SYNC_FILE),)
+ OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
+ endif
+endif
+
+ifeq ($(SECURITY), 1)
+OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_security_channel.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_security.o
+endif
+
+ifneq ($(CUSTOMER_ALLOCATOR_OBJS),)
+OBJS += $(CUSTOMER_ALLOCATOR_OBJS)
+endif
+
+OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_security_channel_emulator.o \
+ $(TA_DIR)/gc_hal_ta.o \
+ $(TA_DIR)/gc_hal_ta_hardware.o \
+ $(TA_DIR)/gc_hal_ta_mmu.o \
+ $(TA_DIR)/os/emulator/gc_hal_ta_emulator.o
+
+ifeq ($(KERNELRELEASE), )
+
+.PHONY: all clean install
+
+# Define targets.
+all:
+ @$(MAKE) V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
+
+clean:
+ @rm -rf $(OBJS)
+ @rm -rf modules.order Module.symvers .tmp_versions
+ @find $(AQROOT) -name ".gc_*.cmd" | xargs rm -f
+
+install: all
+ @mkdir -p $(SDK_DIR)/drivers
+ @cp $(MODULE_NAME).ko $(SDK_DIR)/drivers
+
+else
+
+
+EXTRA_CFLAGS += -DLINUX -DDRIVER
+
+ifeq ($(FLAREON),1)
+EXTRA_CFLAGS += -DFLAREON
+endif
+
+ifeq ($(DEBUG), 1)
+EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
+else
+EXTRA_CFLAGS += -DDBG=0
+endif
+
+ifeq ($(NO_DMA_COHERENT), 1)
+EXTRA_CFLAGS += -DNO_DMA_COHERENT
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifneq ($(USE_PLATFORM_DRIVER), 0)
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
+else
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
+endif
+
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
+EXTRA_CFLAGS += -DVIVANTE_PROFILER_CONTEXT=1
+
+ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
+else
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
+endif
+
+ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
+else
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
+endif
+
+ifeq ($(FORCE_ALL_VIDEO_MEMORY_CACHED), 1)
+EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=1
+else
+EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=0
+endif
+
+ifeq ($(NONPAGED_MEMORY_CACHEABLE), 1)
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=1
+else
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=0
+endif
+
+ifeq ($(NONPAGED_MEMORY_BUFFERABLE), 1)
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=1
+else
+EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=0
+endif
+
+ifeq ($(CACHE_FUNCTION_UNIMPLEMENTED), 1)
+EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=1
+else
+EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=0
+endif
+
+ifeq ($(VIVANTE_ENABLE_3D),0)
+EXTRA_CFLAGS += -DgcdENABLE_3D=0
+else
+EXTRA_CFLAGS += -DgcdENABLE_3D=1
+endif
+
+ifeq ($(VIVANTE_ENABLE_2D),0)
+EXTRA_CFLAGS += -DgcdENABLE_2D=0
+else
+EXTRA_CFLAGS += -DgcdENABLE_2D=1
+endif
+
+ifeq ($(VIVANTE_ENABLE_VG),0)
+EXTRA_CFLAGS += -DgcdENABLE_VG=0
+else
+EXTRA_CFLAGS += -DgcdENABLE_VG=1
+endif
+
+ifeq ($(USE_BANK_ALIGNMENT), 1)
+ EXTRA_CFLAGS += -DgcdENABLE_BANK_ALIGNMENT=1
+ ifneq ($(BANK_BIT_START), 0)
+ ifneq ($(BANK_BIT_END), 0)
+ EXTRA_CFLAGS += -DgcdBANK_BIT_START=$(BANK_BIT_START)
+ EXTRA_CFLAGS += -DgcdBANK_BIT_END=$(BANK_BIT_END)
+ endif
+ endif
+
+ ifneq ($(BANK_CHANNEL_BIT), 0)
+ EXTRA_CFLAGS += -DgcdBANK_CHANNEL_BIT=$(BANK_CHANNEL_BIT)
+ endif
+endif
+
+ifeq ($(gcdFPGA_BUILD), 1)
+EXTRA_CFLAGS += -DgcdFPGA_BUILD=1
+else
+EXTRA_CFLAGS += -DgcdFPGA_BUILD=0
+endif
+
+ifeq ($(SECURITY), 1)
+EXTRA_CFLAGS += -DgcdSECURITY=1
+endif
+
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/arch
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/os/linux/kernel
+EXTRA_CFLAGS += -I$(AQROOT)/$(ALLOCATOR_ARRAY_H_LOCATION)
+EXTRA_CFLAGS += -I$(AQROOT)/hal/security_v1/
+
+ifneq ($(CONFIG_ARM), )
+EXTRA_CFLAGS += -Iarch/arm/mm
+endif
+
+ifeq ($(VIVANTE_ENABLE_VG), 1)
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/archvg
+endif
+
+EXTRA_CFLAGS += -DHOST=\"$(HOST)\"
+
+EXTRA_CFLAGS += -DgcdENABLE_TRUST_APPLICATION=1
+
+obj-$(CONFIG_MXC_GPU_VIV) = $(MODULE_NAME).o
+
+$(MODULE_NAME)-objs = $(OBJS)
+
+endif
diff --git a/drivers/mxc/gpu-viv/Kconfig b/drivers/mxc/gpu-viv/Kconfig
new file mode 100644
index 000000000000..ae0c127911e7
--- /dev/null
+++ b/drivers/mxc/gpu-viv/Kconfig
@@ -0,0 +1,9 @@
+menu "MXC Vivante GPU support"
+ depends on SOC_IMX6 || ARCH_FSL_IMX8QM
+
+config MXC_GPU_VIV
+ tristate "MXC Vivante GPU support"
+ ---help---
+ Say Y to get the GPU driver support.
+
+endmenu
diff --git a/drivers/mxc/gpu-viv/config b/drivers/mxc/gpu-viv/config
new file mode 100644
index 000000000000..fa3287a9dd21
--- /dev/null
+++ b/drivers/mxc/gpu-viv/config
@@ -0,0 +1,73 @@
+##############################################################################
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2014 - 2017 Vivante Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+##############################################################################
+#
+# The GPL License (GPL)
+#
+# Copyright (C) 2014 - 2017 Vivante Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; 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.
+#
+##############################################################################
+#
+# Note: This software is released under dual MIT and GPL licenses. A
+# recipient may use this file under the terms of either the MIT license or
+# GPL License. If you wish to use only one license not the other, you can
+# indicate your decision by deleting one of the above license notices in your
+# version of this file.
+#
+##############################################################################
+
+
+ARCH_TYPE ?= arm
+SDK_DIR ?= $(AQROOT)/build/sdk
+VIVANTE_ENABLE_3D ?= 1
+VIVANTE_ENABLE_2D ?= 1
+VIVANTE_ENABLE_VG ?= 1
+NO_DMA_COHERENT ?= 0
+USE_PLATFORM_DRIVER ?= 1
+ENABLE_GPU_CLOCK_BY_DRIVER ?= 0
+FORCE_ALL_VIDEO_MEMORY_CACHED ?= 0
+NONPAGED_MEMORY_CACHEABLE ?= 0
+NONPAGED_MEMORY_BUFFERABLE ?= 1
+CACHE_FUNCTION_UNIMPLEMENTED ?= 0
+USE_BANK_ALIGNMENT ?= 1
+BANK_BIT_START ?= 13
+BANK_BIT_END ?= 15
+BANK_CHANNEL_BIT ?= 12
+SECURITY ?= 0
+SOC_PLATFORM ?= freescale-imx6
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c
new file mode 100644
index 000000000000..2e5c24488236
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.c
@@ -0,0 +1,3150 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_context.h"
+#include "gc_hal_kernel_buffer.h"
+
+/******************************************************************************\
+******************************** Debugging Macro *******************************
+\******************************************************************************/
+
+/* Zone used for header/footer. */
+#define _GC_OBJ_ZONE gcvZONE_HARDWARE
+
+
+/******************************************************************************\
+************************** Context State Buffer Helpers ************************
+\******************************************************************************/
+
+#define _STATE(reg) \
+ _State(\
+ Context, index, \
+ reg ## _Address >> 2, \
+ reg ## _ResetValue, \
+ reg ## _Count, \
+ gcvFALSE, gcvFALSE \
+ )
+
+#define _STATE_COUNT(reg, count) \
+ _State(\
+ Context, index, \
+ reg ## _Address >> 2, \
+ reg ## _ResetValue, \
+ count, \
+ gcvFALSE, gcvFALSE \
+ )
+
+#define _STATE_COUNT_OFFSET(reg, offset, count) \
+ _State(\
+ Context, index, \
+ (reg ## _Address >> 2) + offset, \
+ reg ## _ResetValue, \
+ count, \
+ gcvFALSE, gcvFALSE \
+ )
+
+#define _STATE_MIRROR_COUNT(reg, mirror, count) \
+ _StateMirror(\
+ Context, \
+ reg ## _Address >> 2, \
+ count, \
+ mirror ## _Address >> 2 \
+ )
+
+#define _STATE_HINT(reg) \
+ _State(\
+ Context, index, \
+ reg ## _Address >> 2, \
+ reg ## _ResetValue, \
+ reg ## _Count, \
+ gcvFALSE, gcvTRUE \
+ )
+
+#define _STATE_HINT_BLOCK(reg, block, count) \
+ _State(\
+ Context, index, \
+ (reg ## _Address >> 2) + (block << reg ## _BLK), \
+ reg ## _ResetValue, \
+ count, \
+ gcvFALSE, gcvTRUE \
+ )
+
+#define _STATE_COUNT_OFFSET_HINT(reg, offset, count) \
+ _State(\
+ Context, index, \
+ (reg ## _Address >> 2) + offset, \
+ reg ## _ResetValue, \
+ count, \
+ gcvFALSE, gcvTRUE \
+ )
+
+#define _STATE_X(reg) \
+ _State(\
+ Context, index, \
+ reg ## _Address >> 2, \
+ reg ## _ResetValue, \
+ reg ## _Count, \
+ gcvTRUE, gcvFALSE \
+ )
+
+#define _STATE_INIT_VALUE(reg, value) \
+ _State(\
+ Context, index, \
+ reg ## _Address >> 2, \
+ value, \
+ reg ## _Count, \
+ gcvFALSE, gcvFALSE \
+ )
+
+#define _CLOSE_RANGE() \
+ _TerminateStateBlock(Context, index)
+
+#define _ENABLE(reg, field) \
+ do \
+ { \
+ if (gcmVERIFYFIELDVALUE(data, reg, MASK_ ## field, ENABLED)) \
+ { \
+ enable |= gcmFIELDMASK(reg, field); \
+ } \
+ } \
+ while (gcvFALSE)
+
+#define _BLOCK_COUNT(reg) \
+ ((reg ## _Count) >> (reg ## _BLK))
+
+
+/******************************************************************************\
+*********************** Support Functions and Definitions **********************
+\******************************************************************************/
+
+#define gcdSTATE_MASK \
+ (gcmSETFIELDVALUE(0, AQ_COMMAND_NOP_COMMAND, OPCODE, NOP) | 0xC0FFEE)
+
+#if gcdENABLE_3D
+static gctUINT32
+_TerminateStateBlock(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index
+ )
+{
+ gctUINT32_PTR buffer;
+ gctUINT32 align;
+
+ /* Determine if we need alignment. */
+ align = (Index & 1) ? 1 : 0;
+
+ /* Address correct index. */
+ buffer = (Context->buffer == gcvNULL)
+ ? gcvNULL
+ : Context->buffer->logical;
+
+ /* Flush the current state block; make sure no pairing with the states
+ to follow happens. */
+ if (align && (buffer != gcvNULL))
+ {
+ buffer[Index] = 0xDEADDEAD;
+ }
+
+ /* Reset last address. */
+ Context->lastAddress = ~0U;
+
+ /* Return alignment requirement. */
+ return align;
+}
+#endif
+
+
+#if gcdENABLE_3D
+static gctUINT32
+_FlushPipe(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index,
+ IN gcePIPE_SELECT Pipe
+ )
+{
+ gctUINT32 flushSlots;
+ gctBOOL txCacheFix;
+ gctBOOL fcFlushStall;
+ gctBOOL iCacheInvalidate;
+ gctBOOL halti5;
+ gctBOOL snapPages;
+ gctBOOL hwTFB;
+
+ txCacheFix
+ = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX);
+
+ fcFlushStall
+ = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_FC_FLUSH_STALL);
+
+ iCacheInvalidate
+ = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_SHADER_HAS_INSTRUCTION_CACHE);
+
+ halti5
+ = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_HALTI5);
+
+ snapPages
+ = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_SNAPPAGE_CMD_FIX) &&
+ gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_SNAPPAGE_CMD);
+
+
+ hwTFB
+ = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_HW_TFB);
+
+ flushSlots = 6;
+
+ if (Pipe == gcvPIPE_3D)
+ {
+ if (!txCacheFix)
+ {
+ /* Semaphore stall */
+ flushSlots += 4;
+ }
+
+ /* VST cache */
+ flushSlots += 2;
+ }
+
+ if (fcFlushStall)
+ {
+ /* Flush tile status cache. */
+ flushSlots += 6;
+ }
+
+ if (iCacheInvalidate && !halti5)
+ {
+ flushSlots += 12;
+ }
+
+ if (hwTFB)
+ {
+ flushSlots += 2;
+ }
+
+ /* Snap pages */
+ if (snapPages)
+ {
+ flushSlots += 2;
+ }
+
+ if (Context->buffer != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Address correct index. */
+ buffer = Context->buffer->logical + Index;
+
+ if (Pipe == gcvPIPE_3D && !txCacheFix)
+ {
+ /* Semaphore from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* Stall from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ /* Flush the current pipe. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = (Pipe == gcvPIPE_2D)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 10:10) - (0 ? 10:10) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 10:10) - (0 ?
+ 10:10) + 1))))))) << (0 ? 10:10))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 10:10) - (0 ? 10:10) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 10:10) - (0 ?
+ 10:10) + 1))))))) << (0 ? 10:10)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11)));
+
+ if (hwTFB)
+ {
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x7003) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = 0x12345678;
+ }
+
+ /* Flush VST in separate cmd. */
+ if (Pipe == gcvPIPE_3D)
+ {
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+ }
+
+ /* Semaphore from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* Stall from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ if (fcFlushStall)
+ {
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ /* Semaphore from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* Stall from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ if (iCacheInvalidate && !halti5)
+ {
+ /* Invalidate I$ after pipe is stalled */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0218) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x021A) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ?
+ 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0218) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x021A) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ?
+ 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5)));
+
+ /* Semaphore from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* Stall from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ if (snapPages)
+ {
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x13 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x04 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x10 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+
+ *buffer++
+ = 0;
+ }
+ }
+
+ /* Number of slots taken by flushing pipe. */
+ return flushSlots;
+}
+#endif
+
+#if gcdENABLE_3D
+static gctUINT32
+_SemaphoreStall(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index
+ )
+{
+ if (Context->buffer != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Address correct index. */
+ buffer = Context->buffer->logical + Index;
+
+ /* Semaphore from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* Stall from FE to PE. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ /* Semaphore/stall takes 4 slots. */
+ return 4;
+}
+#endif
+
+#if (gcdENABLE_3D || gcdENABLE_2D)
+static gctUINT32
+_SwitchPipe(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index,
+ IN gcePIPE_SELECT Pipe
+ )
+{
+ gctUINT32 slots = 2;
+
+ if (Context->buffer != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Address correct index. */
+ buffer = Context->buffer->logical + Index;
+
+ /* LoadState(AQPipeSelect, 1), pipe. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer
+ = (Pipe == gcvPIPE_2D)
+ ? 0x1
+ : 0x0;
+ }
+
+ Context->pipeSelectBytes = slots * gcmSIZEOF(gctUINT32);
+
+ return slots;
+}
+#endif
+
+#if gcdENABLE_3D
+static gctUINT32
+_State(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Index,
+ IN gctUINT32 Address,
+ IN gctUINT32 Value,
+ IN gctUINT32 Size,
+ IN gctBOOL FixedPoint,
+ IN gctBOOL Hinted
+ )
+{
+ gctUINT32_PTR buffer;
+ gctUINT32 align;
+ gctUINT32 i;
+
+ /* Determine if we need alignment. */
+ align = (Index & 1) ? 1 : 0;
+
+ /* Address correct index. */
+ buffer = (Context->buffer == gcvNULL)
+ ? gcvNULL
+ : Context->buffer->logical;
+
+ if ((buffer == gcvNULL) && (Address + Size > Context->maxState))
+ {
+ /* Determine maximum state. */
+ Context->maxState = Address + Size;
+ }
+
+ if (buffer == gcvNULL)
+ {
+ /* Update number of states. */
+ Context->numStates += Size;
+ }
+
+ /* Do we need a new entry? */
+ if ((Address != Context->lastAddress) || (FixedPoint != Context->lastFixed))
+ {
+ if (buffer != gcvNULL)
+ {
+ if (align)
+ {
+ /* Add filler. */
+ buffer[Index++] = 0xDEADDEAD;
+ }
+
+ /* LoadState(Address, Count). */
+ gcmkASSERT((Index & 1) == 0);
+
+ if (FixedPoint)
+ {
+ buffer[Index]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Size) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+ }
+ else
+ {
+ buffer[Index]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Size) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+ }
+
+ /* Walk all the states. */
+ for (i = 0; i < (gctUINT32)Size; i += 1)
+ {
+ /* Set state to uninitialized value. */
+ buffer[Index + 1 + i] = Value;
+
+ /* Set index in state mapping table. */
+ Context->map[Address + i].index = (gctUINT)Index + 1 + i;
+
+#if gcdSECURE_USER
+ /* Save hint. */
+ if (Context->hint != gcvNULL)
+ {
+ Context->hint[Address + i] = Hinted;
+ }
+#endif
+ }
+ }
+
+ /* Save information for this LoadState. */
+ Context->lastIndex = (gctUINT)Index;
+ Context->lastAddress = Address + (gctUINT32)Size;
+ Context->lastSize = Size;
+ Context->lastFixed = FixedPoint;
+
+ /* Return size for load state. */
+ return align + 1 + Size;
+ }
+
+ /* Append this state to the previous one. */
+ if (buffer != gcvNULL)
+ {
+ /* Update last load state. */
+ buffer[Context->lastIndex] =
+ ((((gctUINT32) (buffer[Context->lastIndex])) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Context->lastSize + Size) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ /* Walk all the states. */
+ for (i = 0; i < (gctUINT32)Size; i += 1)
+ {
+ /* Set state to uninitialized value. */
+ buffer[Index + i] = Value;
+
+ /* Set index in state mapping table. */
+ Context->map[Address + i].index = (gctUINT)Index + i;
+
+#if gcdSECURE_USER
+ /* Save hint. */
+ if (Context->hint != gcvNULL)
+ {
+ Context->hint[Address + i] = Hinted;
+ }
+#endif
+ }
+ }
+
+ /* Update last address and size. */
+ Context->lastAddress += (gctUINT32)Size;
+ Context->lastSize += Size;
+
+ /* Return number of slots required. */
+ return Size;
+}
+
+static gctUINT32
+_StateMirror(
+ IN gckCONTEXT Context,
+ IN gctUINT32 Address,
+ IN gctUINT32 Size,
+ IN gctUINT32 AddressMirror
+ )
+{
+ gctUINT32 i;
+
+ /* Process when buffer is set. */
+ if (Context->buffer != gcvNULL)
+ {
+ /* Walk all states. */
+ for (i = 0; i < Size; i++)
+ {
+ /* Copy the mapping address. */
+ Context->map[Address + i].index =
+ Context->map[AddressMirror + i].index;
+
+#if gcdSECURE_USER
+ Context->hint[Address + i] =
+ Context->hint[AddressMirror + i];
+#endif
+ }
+ }
+
+ /* Return the number of required maps. */
+ return Size;
+}
+#endif
+
+#if (gcdENABLE_3D || gcdENABLE_2D)
+static gceSTATUS
+_InitializeContextBuffer(
+ IN gckCONTEXT Context
+ )
+{
+ gctUINT32_PTR buffer;
+ gctUINT32 index;
+
+#if gcdENABLE_3D
+ gctBOOL halti0, halti1, halti2, halti3, halti4, halti5;
+ gctUINT i;
+ gctUINT vertexUniforms, fragmentUniforms, vsConstBase, psConstBase, constMax;
+ gctBOOL unifiedUniform;
+ gctBOOL hasGS, hasTS;
+ gctBOOL genericAttrib;
+ gctBOOL hasICache;
+ gctBOOL hasICachePrefetch;
+ gctUINT numRT = 0;
+ gctUINT numSamplers = 32;
+ gctBOOL hasTXdesc;
+ gctBOOL hasSecurity;
+ gctBOOL hasRobustness;
+ gctBOOL multiCoreBlockSetCfg2;
+#endif
+
+ gckHARDWARE hardware;
+
+ gcmkHEADER();
+
+ hardware = Context->hardware;
+
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Reset the buffer index. */
+ index = 0;
+
+ /* Reset the last state address. */
+ Context->lastAddress = ~0U;
+
+ /* Get the buffer pointer. */
+ buffer = (Context->buffer == gcvNULL)
+ ? gcvNULL
+ : Context->buffer->logical;
+
+
+ /**************************************************************************/
+ /* Build 2D states. *******************************************************/
+
+
+#if gcdENABLE_3D
+ /**************************************************************************/
+ /* Build 3D states. *******************************************************/
+
+ halti0 = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_HALTI0);
+ halti1 = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_HALTI1);
+ halti2 = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_HALTI2);
+ halti3 = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_HALTI3);
+ halti4 = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_HALTI4);
+ halti5 = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_HALTI5);
+ hasGS = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_GEOMETRY_SHADER);
+ hasTS = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_TESSELLATION);
+ genericAttrib = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_GENERIC_ATTRIB);
+ hasICache = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_SHADER_HAS_INSTRUCTION_CACHE);
+ hasTXdesc = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_TX_DESCRIPTOR);
+ hasSecurity = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_SECURITY);
+ hasRobustness = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_ROBUSTNESS);
+ hasICachePrefetch = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_SH_INSTRUCTION_PREFETCH);
+ multiCoreBlockSetCfg2 = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_MULTI_CORE_BLOCK_SET_CONFIG2);
+
+ /* Multi render target. */
+ if (halti2 ||
+ (Context->hardware->identity.chipModel == gcv900 && Context->hardware->identity.chipRevision == 0x5250)
+ )
+ {
+ numRT = 8;
+ }
+ else if (halti0)
+ {
+ numRT = 4;
+ }
+ else
+ {
+ numRT = 1;
+ }
+
+ if (hasGS && hasTS)
+ {
+ numSamplers = 80;
+ }
+
+ /* Query how many uniforms can support. */
+ {if (Context->hardware->identity.numConstants > 256){ unifiedUniform = gcvTRUE;
+if (halti5){ vsConstBase = 0xD000;
+ psConstBase = 0xD800;
+}else{ vsConstBase = 0xC000;
+ psConstBase = 0xC000;
+}if ((Context->hardware->identity.chipModel == gcv880) && ((Context->hardware->identity.chipRevision & 0xfff0) == 0x5120)){ vertexUniforms = 512;
+ fragmentUniforms = 64;
+ constMax = 576;
+}else{ vertexUniforms = gcmMIN(512, Context->hardware->identity.numConstants - 64);
+ fragmentUniforms = gcmMIN(512, Context->hardware->identity.numConstants - 64);
+ constMax = Context->hardware->identity.numConstants;
+}}else if (Context->hardware->identity.numConstants == 256){ if (Context->hardware->identity.chipModel == gcv2000 && (Context->hardware->identity.chipRevision == 0x5118 || Context->hardware->identity.chipRevision == 0x5140)) { unifiedUniform = gcvFALSE;
+ vsConstBase = 0x1400;
+ psConstBase = 0x1C00;
+ vertexUniforms = 256;
+ fragmentUniforms = 64;
+ constMax = 320;
+ } else { unifiedUniform = gcvFALSE;
+ vsConstBase = 0x1400;
+ psConstBase = 0x1C00;
+ vertexUniforms = 256;
+ fragmentUniforms = 256;
+ constMax = 512;
+ }}else{ unifiedUniform = gcvFALSE;
+ vsConstBase = 0x1400;
+ psConstBase = 0x1C00;
+ vertexUniforms = 168;
+ fragmentUniforms = 64;
+ constMax = 232;
+}};
+
+
+#if !gcdENABLE_UNIFIED_CONSTANT
+ if (Context->hardware->identity.numConstants > 256)
+ {
+ unifiedUniform = gcvTRUE;
+ }
+ else
+ {
+ unifiedUniform = gcvFALSE;
+ }
+#endif
+
+ /* Store the 3D entry index. */
+ Context->entryOffset3D = (gctUINT)index * gcmSIZEOF(gctUINT32);
+
+ /* Switch to 3D pipe. */
+ index += _SwitchPipe(Context, index, gcvPIPE_3D);
+
+ /* Current context pointer. */
+#if gcdDEBUG
+ index += _State(Context, index, 0x03850 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+#endif
+
+ index += _FlushPipe(Context, index, gcvPIPE_3D);
+
+ /* Global states. */
+ if (hasSecurity)
+ {
+ index += _State(Context, index, 0x03900 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ index += _State(Context, index, 0x03904 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ index += _State(Context, index, 0x03814 >> 2, 0x00000001, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ index += _State(Context, index, 0x03818 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0381C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x03888 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x038C0 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03884 >> 2, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:0) - (0 ? 2:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:0) - (0 ? 2:0) + 1))))))) << (0 ?
+ 2:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 2:0) - (0 ? 2:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 2:0) - (0 ? 2:0) + 1))))))) << (0 ? 2:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 20:16) - (0 ? 20:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:16) - (0 ?
+ 20:16) + 1))))))) << (0 ? 20:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 20:16) - (0 ? 20:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:16) - (0 ?
+ 20:16) + 1))))))) << (0 ? 20:16))), 1, gcvFALSE, gcvFALSE);
+ }
+ else
+ {
+ index += _State(Context, index, 0x03820 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03828 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0382C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03834 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03838 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03854 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (hasGS)
+ {
+ index += _State(Context, index, 0x0388C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ index += _State(Context, index, 0x0384C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ /* Front End states. */
+ if (halti5)
+ {
+ index += _State(Context, index, 0x17800 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ index += _State(Context, index, 0x007C4 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x17880 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x17900 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x17980 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x17A00 >> 2, 0x3F800000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x007D0 >> 2, 0x00000000, 2, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x007D8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x17A80 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ }
+ else
+ {
+ index += _State(Context, index, 0x00600 >> 2, 0x00000000, (halti0 ? 16 : 12), gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ if (genericAttrib)
+ {
+ index += _State(Context, index, 0x006C0 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00700 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00740 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00780 >> 2, 0x3F800000, 16, gcvFALSE, gcvFALSE);
+ }
+ }
+
+ if (halti2 || (Context->hardware->identity.streamCount > 8))
+ {
+ index += _State(Context, index, 0x14600 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14640 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14680 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ }
+ else if (Context->hardware->identity.streamCount > 1)
+ {
+ index += _State(Context, index, 0x00680 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x006A0 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ }
+ else
+ {
+ index += _State(Context, index, 0x0064C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x00650 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ }
+ index += _State(Context, index, 0x00644 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x00648 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00674 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00678 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0067C >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+
+ if (hasRobustness)
+ {
+ index += _State(Context, index, 0x146C0 >> 2, 0x00000000, 16, gcvFALSE, gcvTRUE);
+ index += _CLOSE_RANGE();
+ index += _State(Context, index, 0x007F8 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _CLOSE_RANGE();
+ }
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x008B8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x15600 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+ else
+ {
+ /* This register is programed by all chips, which program all DECODE_SELECT as VS
+ ** except SAMPLER_DECODE_SELECT.
+ */
+ index += _State(Context, index, 0x00860 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (hasICache)
+ {
+ /* I-Cache states. */
+ index += _State(Context, index, 0x00868 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0086C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0304C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01028 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+
+ if (hasICachePrefetch)
+ {
+ if (halti5)
+ {
+ index += _State(Context, index, 0x15604 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01094 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ }
+ else
+ {
+ index += _State(Context, index, 0x00890 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0104C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ }
+ index += _CLOSE_RANGE();
+ }
+ }
+
+ /* Vertex Shader states. */
+ index += _State(Context, index, 0x00804 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00808 >> 2, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:0) - (0 ? 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))), 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0080C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00830 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x00898 >> 2, 0x00000000, 2, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x008A0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00870 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x008A8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x008C0 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x008E0 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ }
+ else
+ {
+ index += _State(Context, index, 0x00810 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00820 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ }
+
+ index += _CLOSE_RANGE();
+
+ /* GS */
+ if (hasGS)
+ {
+ index += _State(Context, index, 0x01100 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01104 >> 2, 0x00000001, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01108 >> 2, 0x01000001, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0110C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01110 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01114 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0111C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01140 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01144 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01148 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0114C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01154 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01120 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+
+ /* TCS & TES */
+
+ if (hasTS)
+ {
+ index += _State(Context, index, 0x007C0 >> 2, 0x00000003, 1, gcvFALSE, gcvFALSE);
+
+ index += _State(Context, index, 0x14A14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A1C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A40 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A00 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A08 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x14A10 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A20 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A44 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14A4C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ index += _CLOSE_RANGE();
+
+ index += _State(Context, index, 0x14B18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B1C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B20 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B08 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B0C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x14B14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B40 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B24 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B2C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14B34 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ index += _State(Context, index, 0x14B00 >> 2, 0x00040000, 1, gcvFALSE, gcvFALSE);
+
+ }
+
+ index += _CLOSE_RANGE();
+
+ /* TFB */
+ if (gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_HW_TFB))
+ {
+ index += _State(Context, index, 0x1C000 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x1C008 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x1C040 >> 2) + (0 << 4), 0x00000000, 4, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x1C080 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x1C0C0 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x1C100 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x1C800 >> 2, 0x00000000, 128*4, gcvFALSE, gcvFALSE);
+
+ index += _State(Context, index, 0x1C014 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _CLOSE_RANGE();
+
+ }
+
+ /* Primitive Assembly states. */
+ index += _State(Context, index, 0x00A00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A04 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A08 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A0C >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A10 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A1C >> 2, 0x3F000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A28 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A2C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A30 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A34 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A38 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A3C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A80 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A84 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00A8C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A88 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x00AA8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00A90 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ }
+ else
+ {
+ index += _State(Context, index, 0x00A40 >> 2, 0x00000000, Context->hardware->identity.varyingsCount, gcvFALSE, gcvFALSE);
+ }
+
+ index += _State(Context, index, 0x03A00 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03A04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03A08 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (multiCoreBlockSetCfg2)
+ {
+ index += _State(Context, index, 0x03A0C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x03A10 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ /* Setup states. */
+ index += _State(Context, index, 0x00C00 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00C04 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00C08 >> 2, 0x45000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00C0C >> 2, 0x45000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00C10 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00C14 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00C18 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00C1C >> 2, 0x42000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00C20 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+ index += _State(Context, index, 0x00C24 >> 2, 0x00000000, 1, gcvTRUE, gcvFALSE);
+
+ /* Raster states. */
+ index += _State(Context, index, 0x00E00 >> 2, 0x000000F1, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E10 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E04 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E40 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E08 >> 2, 0x17000031, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E24 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00E20 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (halti2)
+ {
+ index += _State(Context, index, 0x00E0C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x00E34 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+
+ /* Pixel Shader states. */
+ index += _State(Context, index, 0x01004 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0100C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01010 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01030 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01034 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (halti2)
+ {
+ index += _State(Context, index, 0x01040 >> 2, 0x00000000, 2, gcvFALSE, gcvFALSE);
+ }
+
+ if (numRT == 8)
+ {
+ index += _State(Context, index, 0x0102C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01038 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti4)
+ {
+ index += _State(Context, index, 0x01054 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x01080 >> 2, 0x00000000, 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01058 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01098 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+
+ index += _CLOSE_RANGE();
+
+ /* Texture states. */
+ if (hasTXdesc)
+ {
+ /* Texture descriptor states */
+ index += _State(Context, index, 0x14C40 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ index += _State(Context, index, 0x16C00 >> 2, 0x00000000, numSamplers, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x16E00 >> 2, 0x00000000, numSamplers, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x17000 >> 2, 0x00000000, numSamplers, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x17200 >> 2, 0x00000000, numSamplers, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x17400 >> 2, 0x00000000, numSamplers, gcvFALSE, gcvFALSE);
+
+ index += _State(Context, index, (0x15C00 >> 2) + (0 << 0), 0x00000000, numSamplers, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x15E00 >> 2, 0x00000000, numSamplers, gcvFALSE, gcvFALSE);
+
+ index += _CLOSE_RANGE();
+
+ _StateMirror(Context, 0x16000 >> 2, numSamplers , 0x16C00 >> 2);
+ _StateMirror(Context, 0x16200 >> 2, numSamplers , 0x16E00 >> 2);
+ _StateMirror(Context, 0x16400 >> 2, numSamplers , 0x17000 >> 2);
+ _StateMirror(Context, 0x16600 >> 2, numSamplers , 0x17200 >> 2);
+ _StateMirror(Context, 0x16800 >> 2, numSamplers , 0x17400 >> 2);
+ _StateMirror(Context, 0x15800 >> 2, numSamplers , 0x15C00 >> 2);
+ _StateMirror(Context, 0x15A00 >> 2, numSamplers , 0x15E00 >> 2);
+ }
+ else
+ {
+ index += _State(Context, index, 0x02000 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02040 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02080 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x020C0 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02100 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02140 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02180 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x021C0 >> 2, 0x00321000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02200 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x02240 >> 2, 0x00000000, 12, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, (0x02400 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02440 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02480 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x024C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02500 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02540 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02580 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x025C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02600 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02640 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02680 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x026C0 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02700 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x02740 >> 2) + (0 << 4), 0x00000000, 12, gcvFALSE, gcvTRUE);
+ index += _CLOSE_RANGE();
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_TEXTURE_LINEAR))
+ {
+ /*
+ * Linear stride LODn will overwrite LOD0 on GC880,GC2000.
+ * And only LOD0 is valid for this register.
+ */
+ gctUINT count = halti1 ? 14 : 1;
+
+ for (i = 0; i < 12; i += 1)
+ {
+ index += _State(Context, index, (0x02C00 >> 2) + i * 16, 0x00000000, count, gcvFALSE, gcvFALSE);
+ }
+ }
+
+ if (halti1)
+ {
+ gctUINT texBlockCount;
+ gctUINT gcregTXLogSizeResetValue;
+
+ /* Enable the integer filter pipe for all texture samplers
+ so that the floating point filter clock will shut off until
+ we start using the floating point filter.
+ */
+ gcregTXLogSizeResetValue = ((((gctUINT32) (0x00000000)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 29:29) - (0 ? 29:29) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 29:29) - (0 ?
+ 29:29) + 1))))))) << (0 ? 29:29))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 29:29) - (0 ? 29:29) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 29:29) - (0 ?
+ 29:29) + 1))))))) << (0 ? 29:29)));
+
+ /* New texture block. */
+ index += _State(Context, index, 0x10000 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10080 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10100 >> 2, gcregTXLogSizeResetValue, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10180 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10200 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10280 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10300 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10380 >> 2, 0x00321000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10400 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10480 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_TX_FILTER))
+ {
+ index += _State(Context, index, 0x12000 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x12400 >> 2, 0x00000000, 256, gcvFALSE, gcvFALSE);
+ }
+
+ texBlockCount = ((512) >> (4));
+
+ for (i = 0; i < texBlockCount; i += 1)
+ {
+ index += _State(Context, index, (0x10800 >> 2) + (i << 4), 0x00000000, 14, gcvFALSE, gcvTRUE);
+ }
+ }
+
+ if (gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_TEX_BASELOD))
+ {
+ index += _State(Context, index, 0x10700 >> 2, 0x00000F00, 32, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti3 ||
+ gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_TX_SUPPORT_DEC))
+ {
+ index += _State(Context, index, 0x10780 >> 2, 0x00030000, 32, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti4)
+ {
+ index += _State(Context, index, 0x11200 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x11280 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ }
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_TX_FRAC_PRECISION_6BIT))
+ {
+ index += _State(Context, index, 0x11000 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x11080 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x11100 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x11180 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x11300 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ }
+
+ /* ASTC */
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_TEXTURE_ASTC))
+ {
+ index += _State(Context, index, 0x10500 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10580 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10600 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x10680 >> 2, 0x00000000, 32, gcvFALSE, gcvFALSE);
+ }
+ }
+
+ if (halti3)
+ {
+ index += _State(Context, index, 0x14C00 >> 2, 0x00000000, 16, gcvFALSE, gcvFALSE);
+ }
+
+ /* Thread walker states. */
+ index += _State(Context, index, 0x00900 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00904 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00908 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0090C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00910 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00914 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00918 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00924 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0091C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_SHADER_ENHANCEMENTS2))
+ {
+ index += _State(Context, index, 0x00940 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00944 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00948 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0094C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00950 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00954 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x00958 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0095C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00960 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ index += _CLOSE_RANGE();
+
+ /* VS/PS Start/End PC register */
+ if (halti5)
+ {
+ index += _State(Context, index, 0x00874 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x008BC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0087C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01090 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+ else if (hasICache)
+ {
+ /* New Shader instruction PC registers(20bit). */
+ index += _State(Context, index, 0x00874 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00878 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0087C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00880 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+ else
+ {
+ if (Context->hardware->identity.instructionCount <= 256)
+ {
+ /* old shader instruction PC registers (12bit)*/
+ index += _State(Context, index, 0x00800 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00838 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+
+ index += _State(Context, index, 0x01000 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01018 >> 2, 0x01000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+ else
+ {
+ /* New Shader instruction PC registers (16bit) */
+ index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0101C >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+ }
+
+
+ if (!hasICachePrefetch)
+ {
+ /* This unified one need SELECT bit to steer */
+ if (Context->hardware->identity.instructionCount > 1024)
+ {
+ for (i = 0;
+ i < Context->hardware->identity.instructionCount << 2;
+ i += 256 << 2
+ )
+ {
+ index += _State(Context, index, (0x20000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+ }
+ /* This unified one is steered by base adddress, it's automatical. */
+ else if (Context->hardware->identity.instructionCount > 256)
+ {
+ /* VS instruction memory. */
+ for (i = 0;
+ i < Context->hardware->identity.instructionCount << 2;
+ i += 256 << 2
+ )
+ {
+ index += _State(Context, index, (0x0C000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+
+ _StateMirror(Context, 0x08000 >> 2, Context->hardware->identity.instructionCount << 2 , 0x0C000 >> 2);
+ }
+ /* if (Context->hardware->identity.instructionCount <= 256). This is non-unified one. */
+ else
+ {
+ index += _State(Context, index, 0x04000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ index += _State(Context, index, 0x06000 >> 2, 0x00000000, 1024, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+ }
+
+ if (unifiedUniform)
+ {
+ gctINT numConstants = Context->hardware->identity.numConstants;
+
+ /* Base Offset register */
+ index += _State(Context, index, 0x01024 >> 2, 0x00000100, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x00864 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+
+ for (i = 0;
+ numConstants > 0;
+ i += 256 << 2,
+ numConstants -= 256
+ )
+ {
+ if (halti5)
+ {
+ if (numConstants >= 256)
+ {
+ index += _State(Context, index, (0x36000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
+ }
+ else
+ {
+ index += _State(Context, index, (0x36000 >> 2) + i, 0x00000000, numConstants << 2, gcvFALSE, gcvFALSE);
+ }
+ index += _CLOSE_RANGE();
+ }
+ else
+ {
+ if (numConstants >= 256)
+ {
+ index += _State(Context, index, (0x30000 >> 2) + i, 0x00000000, 256 << 2, gcvFALSE, gcvFALSE);
+ }
+ else
+ {
+ index += _State(Context, index, (0x30000 >> 2) + i, 0x00000000, numConstants << 2, gcvFALSE, gcvFALSE);
+ }
+
+ index += _CLOSE_RANGE();
+ }
+ }
+
+ if (halti5)
+ {
+ _StateMirror(Context, 0x34000 >> 2, Context->hardware->identity.numConstants << 2 , 0x36000 >> 2);
+ }
+ }
+#if gcdENABLE_UNIFIED_CONSTANT
+ else
+#endif
+ {
+ index += _State(Context, index, 0x05000 >> 2, 0x00000000, vertexUniforms * 4, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x07000 >> 2, 0x00000000, fragmentUniforms * 4, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti1)
+ {
+ index += _State(Context, index, 0x00884 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x008B0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ /* Store the index of the "XD" entry. */
+ Context->entryOffsetXDFrom3D = (gctUINT)index * gcmSIZEOF(gctUINT32);
+
+
+ /* Pixel Engine states. */
+ index += _State(Context, index, 0x01400 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01404 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01408 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0140C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01414 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01418 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0141C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01420 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01424 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01428 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x0142C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01434 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01454 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01458 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x014A0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014A8 >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014AC >> 2, 0xFFFFFFFF, 1, gcvFALSE, gcvFALSE);
+
+ if(gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_HALF_FLOAT_PIPE) )
+ {
+ index += _State(Context, index, 0x014B0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014B4 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+ index += _State(Context, index, 0x014A4 >> 2, 0x000E400C, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01580 >> 2, 0x00000000, 3, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x014B8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+ if (halti3)
+ {
+ index += _State(Context, index, 0x0103C >> 2, 0x76543210, 1, gcvFALSE, gcvFALSE);
+ }
+ /* Composition states. */
+ index += _State(Context, index, 0x03008 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+
+
+ index += _State(Context, index, (0x01460 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+
+ if (Context->hardware->identity.pixelPipes == 1)
+ {
+ index += _State(Context, index, 0x01430 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01410 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ }
+
+ if (Context->hardware->identity.pixelPipes > 1 || halti0)
+ {
+ index += _State(Context, index, (0x01480 >> 2) + (0 << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ index += _State(Context, index, (0x01500 >> 2) + (i << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+ }
+
+ if (numRT == 8)
+ {
+ for (i = 0; i < 7; i++)
+ {
+ index += _State(Context, index, (0x14800 >> 2) + (i << 3), 0x00000000, Context->hardware->identity.pixelPipes, gcvFALSE, gcvTRUE);
+ }
+ index += _State(Context, index, 0x14900 >> 2, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ }
+
+
+ if (halti3)
+ {
+ index += _State(Context, index, 0x014BC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti4)
+ {
+ index += _State(Context, index, 0x014C0 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ }
+
+ if (hasGS)
+ {
+ index += _State(Context, index, 0x038A0 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ }
+
+ if (halti5)
+ {
+ index += _State(Context, index, 0x14920 >> 2, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14940 >> 2, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14960 >> 2, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x14980 >> 2, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x149A0 >> 2, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ }
+
+ if (hasRobustness)
+ {
+ index += _State(Context, index, 0x149C0 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x014C4 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ }
+
+ /* Memory Controller */
+ index += _State(Context, index, 0x01654 >> 2, 0x00200000, 1, gcvFALSE, gcvFALSE);
+
+ index += _CLOSE_RANGE();
+ index += _State(Context, index, 0x01658 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0165C >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01660 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01664 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01668 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x0166C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01670 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01674 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x016A4 >> 2, 0x00000000, 1, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x016AC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x016A8 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01720 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x01740 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, 0x01760 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+
+
+ if (halti2)
+ {
+ index += _State(Context, index, 0x01780 >> 2, 0x00000000, 8, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, 0x016BC >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, (0x017A0 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, (0x017C0 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x017E0 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvTRUE);
+ index += _State(Context, index, (0x01A00 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, (0x01A20 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ index += _State(Context, index, (0x01A40 >> 2) + 1, 0x00000000, 7, gcvFALSE, gcvFALSE);
+ }
+
+ index += _CLOSE_RANGE();
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_BUG_FIXES18))
+ {
+ index += _State(Context, index, 0x03860 >> 2, 0x6, 1, gcvFALSE, gcvFALSE);
+ index += _CLOSE_RANGE();
+ }
+
+ if (halti3)
+ {
+ index += _State(Context, index, 0x01A80 >> 2, 0x00000000, 8, gcvFALSE, gcvTRUE);
+ index += _CLOSE_RANGE();
+ }
+
+ if (hasSecurity || hasRobustness)
+ {
+ index += _State(Context, index, 0x001AC >> 2, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))), 1, gcvFALSE, gcvFALSE);
+ }
+
+ /* Semaphore/stall. */
+ index += _SemaphoreStall(Context, index);
+#endif
+
+ /**************************************************************************/
+ /* Link to another address. ***********************************************/
+
+ Context->linkIndex3D = (gctUINT)index;
+
+ if (buffer != gcvNULL)
+ {
+ buffer[index + 0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ buffer[index + 1]
+ = 0;
+ }
+
+ index += 2;
+
+ /* Store the end of the context buffer. */
+ Context->bufferSize = index * gcmSIZEOF(gctUINT32);
+
+
+ /**************************************************************************/
+ /* Pipe switch for the case where neither 2D nor 3D are used. *************/
+
+ /* Store the 3D entry index. */
+ Context->entryOffsetXDFrom2D = (gctUINT)index * gcmSIZEOF(gctUINT32);
+
+ /* Switch to 3D pipe. */
+ index += _SwitchPipe(Context, index, gcvPIPE_3D);
+
+ /* Store the location of the link. */
+ Context->linkIndexXD = (gctUINT)index;
+
+ if (buffer != gcvNULL)
+ {
+ buffer[index + 0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ buffer[index + 1]
+ = 0;
+ }
+
+ index += 2;
+
+
+ /**************************************************************************/
+ /* Save size for buffer. **************************************************/
+
+ Context->totalSize = index * gcmSIZEOF(gctUINT32);
+
+#if gcdENABLE_3D
+ psConstBase = psConstBase;
+ vsConstBase = vsConstBase;
+ constMax = constMax;
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
+
+static gceSTATUS
+_DestroyContext(
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ if (Context != gcvNULL)
+ {
+ gcsCONTEXT_PTR bufferHead;
+
+ /* Free context buffers. */
+ for (bufferHead = Context->buffer; Context->buffer != gcvNULL;)
+ {
+ /* Get a shortcut to the current buffer. */
+ gcsCONTEXT_PTR buffer = Context->buffer;
+
+ /* Get the next buffer. */
+ gcsCONTEXT_PTR next = buffer->next;
+
+ /* Last item? */
+ if (next == bufferHead)
+ {
+ next = gcvNULL;
+ }
+
+ /* Destroy the signal. */
+ if (buffer->signal != gcvNULL)
+ {
+ gcmkONERROR(gckOS_DestroySignal(
+ Context->os, buffer->signal
+ ));
+
+ buffer->signal = gcvNULL;
+ }
+
+ /* Free state delta map. */
+ if (buffer->logical != gcvNULL)
+ {
+ if (Context->hardware->kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckEVENT_DestroyVirtualCommandBuffer(
+ Context->hardware->kernel->eventObj,
+ Context->totalSize,
+ buffer->physical,
+ buffer->logical,
+ gcvKERNEL_PIXEL
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckEVENT_FreeContiguousMemory(
+ Context->hardware->kernel->eventObj,
+ Context->totalSize,
+ buffer->physical,
+ buffer->logical,
+ gcvKERNEL_PIXEL
+ ));
+ }
+
+ buffer->logical = gcvNULL;
+ }
+
+ /* Free context buffer. */
+ gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, buffer));
+
+ /* Remove from the list. */
+ Context->buffer = next;
+ }
+
+#if gcdSECURE_USER
+ /* Free the hint array. */
+ if (Context->hint != gcvNULL)
+ {
+ gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->hint));
+ }
+#endif
+
+ /* Mark the gckCONTEXT object as unknown. */
+ Context->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckCONTEXT object. */
+ gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context));
+ }
+
+OnError:
+ return status;
+}
+
+#if (gcdENABLE_3D || gcdENABLE_2D)
+static gceSTATUS
+_AllocateContextBuffer(
+ IN gckCONTEXT Context,
+ IN gcsCONTEXT_PTR Buffer
+ )
+{
+ gceSTATUS status;
+ gctPOINTER pointer;
+ gctUINT32 address;
+ gctSIZE_T totalSize = Context->totalSize;
+
+ if (Context->hardware->kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_AllocateVirtualCommandBuffer(
+ Context->hardware->kernel,
+ gcvFALSE,
+ &totalSize,
+ &Buffer->physical,
+ &pointer
+ ));
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Context->hardware->kernel,
+ pointer,
+ gcvFALSE,
+ Buffer->physical,
+ &address
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_AllocateContiguous(
+ Context->os,
+ gcvFALSE,
+ &totalSize,
+ &Buffer->physical,
+ &pointer
+ ));
+
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ Context->hardware,
+ pointer,
+ gcvFALSE,
+ &address
+ ));
+ }
+
+ Buffer->logical = pointer;
+ Buffer->address = address;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+#endif
+
+/******************************************************************************\
+**************************** Context Management API ****************************
+\******************************************************************************/
+
+/******************************************************************************\
+**
+** gckCONTEXT_Construct
+**
+** Construct a new gckCONTEXT object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctUINT32 ProcessID
+** Current process ID.
+**
+** gckHARDWARE Hardware
+** Pointer to gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gckCONTEXT * Context
+** Pointer to a variable thet will receive the gckCONTEXT object
+** pointer.
+*/
+#if (gcdENABLE_3D || gcdENABLE_2D)
+gceSTATUS
+gckCONTEXT_Construct(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 ProcessID,
+ OUT gckCONTEXT * Context
+ )
+{
+ gceSTATUS status;
+ gckCONTEXT context = gcvNULL;
+ gctUINT32 allocationSize;
+ gctUINT i;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%08X Hardware=0x%08X", Os, Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Context != gcvNULL);
+
+
+ /**************************************************************************/
+ /* Allocate and initialize basic fields of gckCONTEXT. ********************/
+
+ /* The context object size. */
+ allocationSize = gcmSIZEOF(struct _gckCONTEXT);
+
+ /* Allocate the object. */
+ gcmkONERROR(gckOS_Allocate(
+ Os, allocationSize, &pointer
+ ));
+
+ context = pointer;
+
+ /* Reset the entire object. */
+ gcmkONERROR(gckOS_ZeroMemory(context, allocationSize));
+
+ /* Initialize the gckCONTEXT object. */
+ context->object.type = gcvOBJ_CONTEXT;
+ context->os = Os;
+ context->hardware = Hardware;
+
+
+#if !gcdENABLE_3D
+ context->entryPipe = gcvPIPE_2D;
+ context->exitPipe = gcvPIPE_2D;
+#elif gcdCMD_NO_2D_CONTEXT
+ context->entryPipe = gcvPIPE_3D;
+ context->exitPipe = gcvPIPE_3D;
+#else
+ context->entryPipe
+ = (((((gctUINT32) (context->hardware->identity.chipFeatures)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) )
+ ? gcvPIPE_2D
+ : gcvPIPE_3D;
+ context->exitPipe = gcvPIPE_3D;
+#endif
+
+ /* Get the command buffer requirements. */
+ gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
+ Hardware,
+ gcvENGINE_RENDER,
+ &context->alignment,
+ &context->reservedHead,
+ gcvNULL
+ ));
+
+ /**************************************************************************/
+ /* Get the size of the context buffer. ************************************/
+
+ gcmkONERROR(_InitializeContextBuffer(context));
+
+ if (context->maxState > 0)
+ {
+ /**************************************************************************/
+ /* Allocate and reset the state mapping table. ****************************/
+ if (context->hardware->kernel->command->stateMap == gcvNULL)
+ {
+ /* Allocate the state mapping table. */
+ gcmkONERROR(gckOS_Allocate(
+ Os,
+ gcmSIZEOF(gcsSTATE_MAP) * context->maxState,
+ &pointer
+ ));
+
+ context->map = pointer;
+
+ /* Zero the state mapping table. */
+ gcmkONERROR(gckOS_ZeroMemory(
+ context->map, gcmSIZEOF(gcsSTATE_MAP) * context->maxState
+ ));
+
+ context->hardware->kernel->command->stateMap = pointer;
+ }
+ else
+ {
+ context->map = context->hardware->kernel->command->stateMap;
+ }
+
+ /**************************************************************************/
+ /* Allocate the hint array. ***********************************************/
+
+#if gcdSECURE_USER
+ /* Allocate hints. */
+ gcmkONERROR(gckOS_Allocate(
+ Os,
+ gcmSIZEOF(gctBOOL) * context->maxState,
+ &pointer
+ ));
+
+ context->hint = pointer;
+#endif
+ }
+
+ /**************************************************************************/
+ /* Allocate the context and state delta buffers. **************************/
+
+ for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i += 1)
+ {
+ /* Allocate a context buffer. */
+ gcsCONTEXT_PTR buffer;
+
+ /* Allocate the context buffer structure. */
+ gcmkONERROR(gckOS_Allocate(
+ Os,
+ gcmSIZEOF(gcsCONTEXT),
+ &pointer
+ ));
+
+ buffer = pointer;
+
+ /* Reset the context buffer structure. */
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ buffer, gcmSIZEOF(gcsCONTEXT)
+ ));
+
+ /* Append to the list. */
+ if (context->buffer == gcvNULL)
+ {
+ buffer->next = buffer;
+ context->buffer = buffer;
+ }
+ else
+ {
+ buffer->next = context->buffer->next;
+ context->buffer->next = buffer;
+ }
+
+ /* Set the number of delta in the order of creation. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ buffer->num = i;
+#endif
+
+ /* Create the busy signal. */
+ gcmkONERROR(gckOS_CreateSignal(
+ Os, gcvFALSE, &buffer->signal
+ ));
+
+ /* Set the signal, buffer is currently not busy. */
+ gcmkONERROR(gckOS_Signal(
+ Os, buffer->signal, gcvTRUE
+ ));
+
+ /* Create a new physical context buffer. */
+ gcmkONERROR(_AllocateContextBuffer(
+ context, buffer
+ ));
+
+ /* Set gckEVENT object pointer. */
+ buffer->eventObj = Hardware->kernel->eventObj;
+
+ /* Set the pointers to the LINK commands. */
+ if (context->linkIndex2D != 0)
+ {
+ buffer->link2D = &buffer->logical[context->linkIndex2D];
+ }
+
+ if (context->linkIndex3D != 0)
+ {
+ buffer->link3D = &buffer->logical[context->linkIndex3D];
+ }
+
+ if (context->linkIndexXD != 0)
+ {
+ gctPOINTER xdLink;
+ gctUINT32 xdEntryAddress;
+ gctUINT32 xdEntrySize;
+ gctUINT32 linkBytes;
+
+ /* Determine LINK parameters. */
+ xdLink
+ = &buffer->logical[context->linkIndexXD];
+
+ xdEntryAddress
+ = buffer->address
+ + context->entryOffsetXDFrom3D;
+
+ xdEntrySize
+ = context->bufferSize
+ - context->entryOffsetXDFrom3D;
+
+ /* Query LINK size. */
+ gcmkONERROR(gckHARDWARE_Link(
+ Hardware, gcvNULL, 0, 0, &linkBytes, gcvNULL, gcvNULL
+ ));
+
+ /* Generate a LINK. */
+ gcmkONERROR(gckHARDWARE_Link(
+ Hardware,
+ xdLink,
+ xdEntryAddress,
+ xdEntrySize,
+ &linkBytes,
+ gcvNULL,
+ gcvNULL
+ ));
+ }
+ }
+
+
+ /**************************************************************************/
+ /* Initialize the context buffers. ****************************************/
+
+ /* Initialize the current context buffer. */
+ gcmkONERROR(_InitializeContextBuffer(context));
+
+ /* Make all created contexts equal. */
+ {
+ gcsCONTEXT_PTR currContext, tempContext;
+
+ /* Set the current context buffer. */
+ currContext = context->buffer;
+
+ /* Get the next context buffer. */
+ tempContext = currContext->next;
+
+ /* Loop through all buffers. */
+ while (tempContext != currContext)
+ {
+ if (tempContext == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ /* Copy the current context. */
+ gckOS_MemCopy(
+ tempContext->logical,
+ currContext->logical,
+ context->totalSize
+ );
+
+ /* Get the next context buffer. */
+ tempContext = tempContext->next;
+ }
+ }
+
+ /* Return pointer to the gckCONTEXT object. */
+ *Context = context;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Context=0x%08X", *Context);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back on error. */
+ gcmkVERIFY_OK(_DestroyContext(context));
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/******************************************************************************\
+**
+** gckCONTEXT_Destroy
+**
+** Destroy a gckCONTEXT object.
+**
+** INPUT:
+**
+** gckCONTEXT Context
+** Pointer to an gckCONTEXT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCONTEXT_Destroy(
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Context=0x%08X", Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+ /* Destroy the context and all related objects. */
+ status = _DestroyContext(Context);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/******************************************************************************\
+**
+** gckCONTEXT_Update
+**
+** Merge all pending state delta buffers into the current context buffer.
+**
+** INPUT:
+**
+** gckCONTEXT Context
+** Pointer to an gckCONTEXT object.
+**
+** gctUINT32 ProcessID
+** Current process ID.
+**
+** gcsSTATE_DELTA_PTR StateDelta
+** Pointer to the state delta.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCONTEXT_Update(
+ IN gckCONTEXT Context,
+ IN gctUINT32 ProcessID,
+ IN gcsSTATE_DELTA_PTR StateDelta
+ )
+{
+#if gcdENABLE_3D
+ gceSTATUS status = gcvSTATUS_OK;
+ gcsSTATE_DELTA _stateDelta;
+ gckKERNEL kernel;
+ gcsCONTEXT_PTR buffer;
+ gcsSTATE_MAP_PTR map;
+ gctBOOL needCopy = gcvFALSE;
+ gcsSTATE_DELTA_PTR nDelta;
+ gcsSTATE_DELTA_PTR uDelta = gcvNULL;
+ gcsSTATE_DELTA_PTR kDelta = gcvNULL;
+ gcsSTATE_DELTA_RECORD_PTR record;
+ gcsSTATE_DELTA_RECORD_PTR recordArray = gcvNULL;
+ gctUINT elementCount;
+ gctUINT address;
+ gctUINT32 mask;
+ gctUINT32 data;
+ gctUINT index;
+ gctUINT i, j;
+ gctUINT32 dirtyRecordArraySize = 0;
+
+#if gcdSECURE_USER
+ gcskSECURE_CACHE_PTR cache;
+#endif
+
+ gcmkHEADER_ARG(
+ "Context=0x%08X ProcessID=%d StateDelta=0x%08X",
+ Context, ProcessID, StateDelta
+ );
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+ /* Get a shortcut to the kernel object. */
+ kernel = Context->hardware->kernel;
+
+ /* Check wehther we need to copy the structures or not. */
+ gcmkONERROR(gckOS_QueryNeedCopy(Context->os, ProcessID, &needCopy));
+
+ /* Get the current context buffer. */
+ buffer = Context->buffer;
+
+ /* Wait until the context buffer becomes available; this will
+ also reset the signal and mark the buffer as busy. */
+ gcmkONERROR(gckOS_WaitSignal(
+ Context->os, buffer->signal, gcvFALSE, gcvINFINITE
+ ));
+
+#if gcdSECURE_USER
+ /* Get the cache form the database. */
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
+#endif
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE) && 1 && gcdENABLE_3D
+ /* Update current context token. */
+ buffer->logical[Context->map[0x0E14].index]
+ = (gctUINT32)gcmPTR2INT32(Context);
+#endif
+
+ /* Are there any pending deltas? */
+ if (buffer->deltaCount != 0)
+ {
+ /* Get the state map. */
+ map = Context->map;
+
+ /* Get the first delta item. */
+ uDelta = buffer->delta;
+
+ /* Reset the vertex stream count. */
+ elementCount = 0;
+
+ /* Merge all pending deltas. */
+ for (i = 0; i < buffer->deltaCount; i += 1)
+ {
+ /* Get access to the state delta. */
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ kernel, needCopy,
+ &_stateDelta,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ dirtyRecordArraySize
+ = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * kDelta->recordCount;
+
+ if (dirtyRecordArraySize)
+ {
+ /* Get access to the state records. */
+ gcmkONERROR(gckOS_MapUserPointer(
+ kernel->os,
+ gcmUINT64_TO_PTR(kDelta->recordArray),
+ dirtyRecordArraySize,
+ (gctPOINTER *) &recordArray
+ ));
+ }
+
+ /* Merge all pending states. */
+ for (j = 0; j < kDelta->recordCount; j += 1)
+ {
+ if (j >= Context->numStates)
+ {
+ break;
+ }
+
+ /* Get the current state record. */
+ record = &recordArray[j];
+
+ /* Get the state address. */
+ gcmkONERROR(gckOS_ReadMappedPointer(kernel->os, &record->address, &address));
+
+ /* Make sure the state is a part of the mapping table. */
+ if (address >= Context->maxState)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): State 0x%04X (0x%04X) is not mapped.\n",
+ __FUNCTION__, __LINE__,
+ address, address << 2
+ );
+
+ continue;
+ }
+
+ /* Get the state index. */
+ index = map[address].index;
+
+ /* Skip the state if not mapped. */
+ if (index == 0)
+ {
+ continue;
+ }
+
+ /* Get the data mask. */
+ gcmkONERROR(gckOS_ReadMappedPointer(kernel->os, &record->mask, &mask));
+
+ /* Get the new data value. */
+ gcmkONERROR(gckOS_ReadMappedPointer(kernel->os, &record->data, &data));
+
+ /* Masked states that are being completly reset or regular states. */
+ if ((mask == 0) || (mask == ~0U))
+ {
+ /* Process special states. */
+ if (address == 0x0595)
+ {
+ /* Force auto-disable to be disabled. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 13:13) - (0 ? 13:13) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:13) - (0 ?
+ 13:13) + 1))))))) << (0 ? 13:13))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 13:13) - (0 ? 13:13) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:13) - (0 ?
+ 13:13) + 1))))))) << (0 ? 13:13)));
+ }
+
+#if gcdSECURE_USER
+ /* Do we need to convert the logical address? */
+ if (Context->hint[address])
+ {
+ /* Map handle into physical address. */
+ gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
+ kernel, cache, (gctPOINTER) &data
+ ));
+ }
+#endif
+
+ /* Set new data. */
+ buffer->logical[index] = data;
+ }
+
+ /* Masked states that are being set partially. */
+ else
+ {
+ buffer->logical[index]
+ = (~mask & buffer->logical[index])
+ | (mask & data);
+ }
+ }
+
+ /* Get the element count. */
+ if (kDelta->elementCount != 0)
+ {
+ elementCount = kDelta->elementCount;
+ }
+
+ /* Dereference delta. */
+ kDelta->refCount -= 1;
+ gcmkASSERT(kDelta->refCount >= 0);
+
+ /* Get the next state delta. */
+ nDelta = gcmUINT64_TO_PTR(kDelta->next);
+
+ if (dirtyRecordArraySize)
+ {
+ /* Get access to the state records. */
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ kernel->os,
+ gcmUINT64_TO_PTR(kDelta->recordArray),
+ dirtyRecordArraySize,
+ recordArray
+ ));
+
+ recordArray = gcvNULL;
+ }
+
+ /* Close access to the current state delta. */
+ gcmkONERROR(gckKERNEL_CloseUserData(
+ kernel, needCopy,
+ gcvTRUE,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ /* Update the user delta pointer. */
+ uDelta = nDelta;
+ }
+
+ /* Hardware disables all input attribute when the attribute 0 is programmed,
+ it then reenables those attributes that were explicitely programmed by
+ the software. Because of this we cannot program the entire array of
+ values, otherwise we'll get all attributes reenabled, but rather program
+ only those that are actully needed by the software.
+ elementCount = attribCount + 1 to make sure 0 is a flag to indicate if UMD
+ touches it.
+ */
+ if (elementCount != 0)
+ {
+ gctUINT base;
+ gctUINT nopCount;
+ gctUINT32_PTR nop;
+ gctUINT fe2vsCount;
+ gctUINT attribCount = elementCount -1;
+ gctUINT32 feAttributeStatgeAddr = 0x0180;
+ if (gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_HALTI5))
+ {
+ fe2vsCount = 32;
+ base = map[0x5E00].index;
+ feAttributeStatgeAddr = 0x5E00;
+ }
+ else if (gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_HALTI0))
+ {
+ fe2vsCount = 16;
+ base = map[0x0180].index;
+ }
+ else
+ {
+ fe2vsCount = 12;
+ base = map[0x0180].index;
+ }
+
+ /* Set the proper state count. */
+ if (attribCount == 0)
+ {
+ gcmkASSERT(gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_ZERO_ATTRIB_SUPPORT));
+
+ buffer->logical[base - 1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (feAttributeStatgeAddr) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ /* Set the proper state count. */
+ buffer->logical[base + 1] =
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x01F2) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+ buffer->logical[base + 2] = 0x1;
+ attribCount = 3;
+ }
+ else
+ {
+ buffer->logical[base - 1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 26:26) - (0 ? 26:26) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:26) - (0 ?
+ 26:26) + 1))))))) << (0 ? 26:26)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (attribCount) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (feAttributeStatgeAddr) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+ }
+
+ /* Determine the number of NOP commands. */
+ nopCount = (fe2vsCount / 2) - (attribCount / 2);
+ /* Determine the location of the first NOP. */
+ nop = &buffer->logical[base + (attribCount | 1)];
+
+ /* Fill the unused space with NOPs. */
+ for (i = 0; i < nopCount; i += 1)
+ {
+ if (nop >= buffer->logical + Context->totalSize)
+ {
+ break;
+ }
+
+ /* Generate a NOP command. */
+ *nop = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ /* Advance. */
+ nop += 2;
+ }
+ }
+ /* Reset pending deltas. */
+ buffer->deltaCount = 0;
+ buffer->delta = gcvNULL;
+ }
+
+ if (StateDelta)
+ {
+ /* Set state delta user pointer. */
+ uDelta = StateDelta;
+
+ /* Get access to the state delta. */
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ kernel, needCopy,
+ &_stateDelta,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ /* State delta cannot be attached to anything yet. */
+ if (kDelta->refCount != 0)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): kDelta->refCount = %d (has to be 0).\n",
+ __FUNCTION__, __LINE__,
+ kDelta->refCount
+ );
+ }
+
+ /* Attach to all contexts. */
+ buffer = Context->buffer;
+
+ do
+ {
+ /* Attach to the context if nothing is attached yet. If a delta
+ is allready attached, all we need to do is to increment
+ the number of deltas in the context. */
+ if (buffer->delta == gcvNULL)
+ {
+ buffer->delta = uDelta;
+ }
+
+ /* Update reference count. */
+ kDelta->refCount += 1;
+
+ /* Update counters. */
+ buffer->deltaCount += 1;
+
+ /* Get the next context buffer. */
+ buffer = buffer->next;
+
+ if (buffer == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+ }
+ while (Context->buffer != buffer);
+
+ /* Close access to the current state delta. */
+ gcmkONERROR(gckKERNEL_CloseUserData(
+ kernel, needCopy,
+ gcvTRUE,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ }
+ /* Schedule an event to mark the context buffer as available. */
+ gcmkONERROR(gckEVENT_Signal(
+ buffer->eventObj, buffer->signal, gcvKERNEL_PIXEL
+ ));
+
+ /* Advance to the next context buffer. */
+ Context->buffer = buffer->next;
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Get access to the state records. */
+ if (kDelta != gcvNULL && recordArray != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ kernel->os,
+ gcmUINT64_TO_PTR(kDelta->recordArray),
+ dirtyRecordArraySize,
+ (gctPOINTER *) &recordArray
+ ));
+ }
+
+ /* Close access to the current state delta. */
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ kernel, needCopy,
+ gcvTRUE,
+ uDelta, gcmSIZEOF(gcsSTATE_DELTA),
+ (gctPOINTER *) &kDelta
+ ));
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#else
+ return gcvSTATUS_OK;
+#endif
+}
+
+gceSTATUS
+gckCONTEXT_MapBuffer(
+ IN gckCONTEXT Context,
+ OUT gctUINT32 *Physicals,
+ OUT gctUINT64 *Logicals,
+ OUT gctUINT32 *Bytes
+ )
+{
+ gceSTATUS status;
+ int i = 0;
+ gctSIZE_T pageCount;
+ gckVIRTUAL_COMMAND_BUFFER_PTR commandBuffer;
+ gckKERNEL kernel = Context->hardware->kernel;
+ gctPOINTER logical;
+ gctPHYS_ADDR physical;
+
+ gcsCONTEXT_PTR buffer;
+
+ gcmkHEADER();
+
+ gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+ buffer = Context->buffer;
+
+ for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i++)
+ {
+ if (kernel->virtualCommandBuffer)
+ {
+ commandBuffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)buffer->physical;
+ physical = commandBuffer->virtualBuffer.physical;
+
+ gcmkONERROR(gckOS_CreateUserVirtualMapping(
+ kernel->os,
+ physical,
+ Context->totalSize,
+ &logical,
+ &pageCount));
+ }
+ else
+ {
+ physical = buffer->physical;
+
+ gcmkONERROR(gckOS_MapMemory(
+ kernel->os,
+ physical,
+ Context->totalSize,
+ &logical));
+ }
+
+ Physicals[i] = gcmPTR_TO_NAME(physical);
+
+ Logicals[i] = gcmPTR_TO_UINT64(logical);
+
+ buffer = buffer->next;
+ }
+
+ *Bytes = (gctUINT)Context->totalSize;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h
new file mode 100644
index 000000000000..cc5817200137
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_context.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_context_h_
+#define __gc_hal_kernel_context_h_
+
+#include "gc_hal_kernel_buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Maps state locations within the context buffer. */
+typedef struct _gcsSTATE_MAP * gcsSTATE_MAP_PTR;
+typedef struct _gcsSTATE_MAP
+{
+ /* Index of the state in the context buffer. */
+ gctUINT index;
+
+ /* State mask. */
+ gctUINT32 mask;
+}
+gcsSTATE_MAP;
+
+/* Context buffer. */
+typedef struct _gcsCONTEXT * gcsCONTEXT_PTR;
+typedef struct _gcsCONTEXT
+{
+ /* For debugging: the number of context buffer in the order of creation. */
+ gctUINT num;
+
+ /* Pointer to gckEVENT object. */
+ gckEVENT eventObj;
+
+ /* Context busy signal. */
+ gctSIGNAL signal;
+
+ /* Physical address of the context buffer. */
+ gctPHYS_ADDR physical;
+
+ /* Logical address of the context buffer. */
+ gctUINT32_PTR logical;
+
+ /* Hardware address of the context buffer. */
+ gctUINT32 address;
+
+ /* Pointer to the LINK commands. */
+ gctPOINTER link2D;
+ gctPOINTER link3D;
+
+ /* The number of pending state deltas. */
+ gctUINT deltaCount;
+
+ /* Pointer to the first delta to be applied. */
+ gcsSTATE_DELTA_PTR delta;
+
+ /* Next context buffer. */
+ gcsCONTEXT_PTR next;
+}
+gcsCONTEXT;
+
+typedef struct _gcsRECORD_ARRAY_MAP * gcsRECORD_ARRAY_MAP_PTR;
+struct _gcsRECORD_ARRAY_MAP
+{
+ /* User pointer key. */
+ gctUINT64 key;
+
+ /* Kernel memory buffer. */
+ gcsSTATE_DELTA_RECORD_PTR kData;
+
+ /* Next map. */
+ gcsRECORD_ARRAY_MAP_PTR next;
+
+};
+
+#define USE_SW_RESET 1
+
+/* gckCONTEXT structure that hold the current context. */
+struct _gckCONTEXT
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* Command buffer alignment. */
+ gctUINT32 alignment;
+ gctUINT32 reservedHead;
+
+ /* Context buffer metrics. */
+ gctSIZE_T maxState;
+ gctUINT32 numStates;
+ gctUINT32 totalSize;
+ gctUINT32 bufferSize;
+ gctUINT32 linkIndex2D;
+ gctUINT32 linkIndex3D;
+ gctUINT32 linkIndexXD;
+ gctUINT32 entryOffset3D;
+ gctUINT32 entryOffsetXDFrom2D;
+ gctUINT32 entryOffsetXDFrom3D;
+
+ /* State mapping. */
+ gcsSTATE_MAP_PTR map;
+
+ /* List of context buffers. */
+ gcsCONTEXT_PTR buffer;
+
+ /* Requested pipe select for context. */
+ gcePIPE_SELECT entryPipe;
+ gcePIPE_SELECT exitPipe;
+
+ /* Variables used for building state buffer. */
+ gctUINT32 lastAddress;
+ gctSIZE_T lastSize;
+ gctUINT32 lastIndex;
+ gctBOOL lastFixed;
+
+ gctUINT32 pipeSelectBytes;
+
+ /* Hint array. */
+#if gcdSECURE_USER
+ gctBOOL_PTR hint;
+#endif
+
+#if VIVANTE_PROFILER_CONTEXT
+ gcsPROFILER_COUNTERS latestProfiler;
+ gcsPROFILER_COUNTERS histroyProfiler;
+ gcsPROFILER_COUNTERS preProfiler;
+#endif
+ gcsPROFILER_NEW_COUNTERS_PART1 latestNewProfiler_part1;
+ gcsPROFILER_NEW_COUNTERS_PART1 histroyNewProfiler_part1;
+ gcsPROFILER_NEW_COUNTERS_PART1 preNewProfiler_part1;
+ gcsPROFILER_NEW_COUNTERS_PART2 latestNewProfiler_part2;
+ gcsPROFILER_NEW_COUNTERS_PART2 histroyNewProfiler_part2;
+ gcsPROFILER_NEW_COUNTERS_PART2 preNewProfiler_part2;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_context_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
new file mode 100644
index 000000000000..e98cd907654d
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
@@ -0,0 +1,15300 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#if VIVANTE_PROFILER_CONTEXT
+#include "gc_hal_kernel_context.h"
+#endif
+
+#include "gc_feature_database.h"
+
+#define _GC_OBJ_ZONE gcvZONE_HARDWARE
+
+#define gcmSEMAPHORESTALL(buffer) \
+ do \
+ { \
+ /* Arm the PE-FE Semaphore. */ \
+ *buffer++ \
+ = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE, LOAD_STATE) \
+ | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT, 1) \
+ | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, 0x0E02); \
+ \
+ *buffer++ \
+ = gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END) \
+ | gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE);\
+ \
+ /* STALL FE until PE is done flushing. */ \
+ *buffer++ \
+ = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
+ \
+ *buffer++ \
+ = gcmSETFIELDVALUE(0, STALL_STALL, SOURCE, FRONT_END) \
+ | gcmSETFIELDVALUE(0, STALL_STALL, DESTINATION, PIXEL_ENGINE); \
+ } while(0)
+
+typedef struct _gcsiDEBUG_REGISTERS * gcsiDEBUG_REGISTERS_PTR;
+typedef struct _gcsiDEBUG_REGISTERS
+{
+ gctSTRING module;
+ gctUINT index;
+ gctUINT shift;
+ gctUINT data;
+ gctUINT count;
+ gctUINT32 pipeMask;
+ gctUINT32 selectStart;
+}
+gcsiDEBUG_REGISTERS;
+
+typedef struct _gcsFE_STACK
+{
+ gctSTRING name;
+ gctINT count;
+ gctUINT32 highSelect;
+ gctUINT32 lowSelect;
+ gctUINT32 linkSelect;
+ gctUINT32 clear;
+ gctUINT32 next;
+}
+gcsFE_STACK;
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+static gctBOOL
+_IsHardwareMatch(
+ IN gckHARDWARE Hardware,
+ IN gctINT32 ChipModel,
+ IN gctUINT32 ChipRevision
+ )
+{
+ return ((Hardware->identity.chipModel == ChipModel) &&
+ (Hardware->identity.chipRevision == ChipRevision));
+}
+
+static gceSTATUS
+_ResetGPU(
+ IN gckHARDWARE Hardware,
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+static void
+_GetEcoID(
+ IN gckHARDWARE Hardware,
+ IN OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+ )
+{
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x000E8,
+ &Identity->ecoID
+ ));
+
+ /* VIV: PXA1088. */
+ if (_IsHardwareMatch(Hardware, 0x1000, 0x5037) && (Identity->chipDate == 0x20120617))
+ {
+ Identity->ecoID = 1;
+ }
+
+ /* VIV: BG2CT*/
+ if (_IsHardwareMatch(Hardware, 0x320, 0x5303) && (Identity->chipDate == 0x20140511))
+ {
+ Identity->ecoID = 1;
+ }
+
+ /* VIV: Hope this is the end of list. */
+}
+
+static gceSTATUS
+_IdentifyHardwareByDatabase(
+ IN gckHARDWARE Hardware,
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+ )
+{
+ gceSTATUS status;
+ gctUINT32 chipIdentity;
+ gctUINT32 debugControl0;
+ gcsFEATURE_DATABASE *database;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Get chip date. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00028, &Identity->chipDate));
+
+ /***************************************************************************
+ ** Get chip ID and revision.
+ */
+
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00018,
+ &chipIdentity));
+
+ /* Special case for older graphic cores. */
+ if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+ {
+ Identity->chipModel = gcv500;
+ Identity->chipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+ }
+
+ else
+ {
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00020,
+ (gctUINT32_PTR) &Identity->chipModel));
+
+ if (((Identity->chipModel & 0xFF00) == 0x0400)
+ && (Identity->chipModel != 0x0420)
+ && (Identity->chipModel != 0x0428))
+ {
+ Identity->chipModel = (gceCHIPMODEL) (Identity->chipModel & 0x0400);
+ }
+
+ /* Read CHIP_REV register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00024,
+ &Identity->chipRevision));
+
+ if ((Identity->chipModel == gcv300)
+ && (Identity->chipRevision == 0x2201)
+ )
+ {
+ gctUINT32 chipDate;
+ gctUINT32 chipTime;
+
+ /* Read date and time registers. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00028,
+ &chipDate));
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x0002C,
+ &chipTime));
+
+ if ((chipDate == 0x20080814) && (chipTime == 0x12051100))
+ {
+ /* This IP has an ECO; put the correct revision in it. */
+ Identity->chipRevision = 0x1051;
+ }
+ }
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x000A8,
+ &Identity->productID));
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipModel=%X",
+ Identity->chipModel);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Identity: chipRevision=%X",
+ Identity->chipRevision);
+
+ _GetEcoID(Hardware, Identity);
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00030,
+ &Identity->customerID));
+
+ /***************************************************************************
+ ** Get chip features.
+ */
+
+ database =
+ Hardware->featureDatabase =
+ gcQueryFeatureDB(
+ Hardware->identity.chipModel,
+ Hardware->identity.chipRevision,
+ Hardware->identity.productID,
+ Hardware->identity.ecoID,
+ Hardware->identity.customerID);
+
+ if (database == gcvNULL)
+ {
+ gcmkPRINT("[galcore]: Feature database is not found,"
+ "chipModel=0x%0x, chipRevision=0x%x, productID=0x%x, ecoID=0x%x, customerID=0x%x",
+ Hardware->identity.chipModel,
+ Hardware->identity.chipRevision,
+ Hardware->identity.productID,
+ Hardware->identity.ecoID,
+ Hardware->identity.customerID);
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ Identity->pixelPipes = database->NumPixelPipes;
+ Identity->resolvePipes = database->NumResolvePipes;
+ Identity->instructionCount = database->InstructionCount;
+ Identity->numConstants = database->NumberOfConstants;
+ Identity->varyingsCount = database->VaryingCount;
+ Identity->gpuCoreCount = database->CoreCount;
+ Identity->streamCount = database->Streams;
+
+ if (Identity->chipModel == gcv320)
+ {
+ gctUINT32 data;
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os,
+ Core,
+ 0x0002C,
+ &data));
+
+ if ((data != 33956864) &&
+ ((Identity->chipRevision == 0x5007) ||
+ (Identity->chipRevision == 0x5220)))
+ {
+ Hardware->maxOutstandingReads = 0xFF &
+ (Identity->chipRevision == 0x5220 ? 8 :
+ (Identity->chipRevision == 0x5007 ? 12 : 0));
+ }
+ }
+
+ if (_IsHardwareMatch(Hardware, gcv880, 0x5107))
+ {
+ Hardware->maxOutstandingReads = 0x00010;
+ }
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00470, &debugControl0));
+
+ if (debugControl0 & (1 << 16))
+ {
+ Identity->chipFlags |= gcvCHIP_FLAG_MSAA_COHERENCEY_ECO_FIX;
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_GetHardwareSignature(
+ IN gckHARDWARE Hardware,
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gcsHARDWARE_SIGNATURE * Signature
+ )
+{
+ gceSTATUS status;
+
+ gctUINT32 chipIdentity;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /***************************************************************************
+ ** Get chip ID and revision.
+ */
+
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00018,
+ &chipIdentity));
+
+ /* Special case for older graphic cores. */
+ if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+ {
+ Signature->chipModel = gcv500;
+ Signature->chipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+ }
+
+ else
+ {
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00020,
+ (gctUINT32_PTR) &Signature->chipModel));
+
+ /* Read CHIP_REV register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00024,
+ &Signature->chipRevision));
+ }
+
+ /***************************************************************************
+ ** Get chip features.
+ */
+
+ /* Read chip feature register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x0001C,
+ &Signature->chipFeatures));
+
+ if (((Signature->chipModel == gcv500) && (Signature->chipRevision < 2))
+ || ((Signature->chipModel == gcv300) && (Signature->chipRevision < 0x2000))
+ )
+ {
+ /* GC500 rev 1.x and GC300 rev < 2.0 doesn't have these registers. */
+ Signature->chipMinorFeatures = 0;
+ Signature->chipMinorFeatures1 = 0;
+ Signature->chipMinorFeatures2 = 0;
+ }
+ else
+ {
+ /* Read chip minor feature register #0. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00034,
+ &Signature->chipMinorFeatures));
+
+ if (((((gctUINT32) (Signature->chipMinorFeatures)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ?
+ 21:21) - (0 ? 21:21) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 21:21) - (0 ?
+ 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 21:21) - (0 ? 21:21) + 1)))))))
+ )
+ {
+ /* Read chip minor features register #1. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00074,
+ &Signature->chipMinorFeatures1));
+
+ /* Read chip minor features register #2. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00084,
+ &Signature->chipMinorFeatures2));
+ }
+ else
+ {
+ /* Chip doesn't has minor features register #1 or 2 or 3 or 4 or 5. */
+ Signature->chipMinorFeatures1 = 0;
+ Signature->chipMinorFeatures2 = 0;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/* Set to 1 to enable module clock gating debug function.
+* Following options take effect when it is set to 1.
+*/
+#define gcdDEBUG_MODULE_CLOCK_GATING 0
+/* Set to 1 to disable module clock gating of all modules. */
+#define gcdDISABLE_MODULE_CLOCK_GATING 0
+/* Set to 1 to disable module clock gating of each module. */
+#define gcdDISABLE_STARVE_MODULE_CLOCK_GATING 0
+#define gcdDISABLE_FE_CLOCK_GATING 0
+#define gcdDISABLE_PE_CLOCK_GATING 0
+#define gcdDISABLE_SH_CLOCK_GATING 0
+#define gcdDISABLE_PA_CLOCK_GATING 0
+#define gcdDISABLE_SE_CLOCK_GATING 0
+#define gcdDISABLE_RA_CLOCK_GATING 0
+#define gcdDISABLE_RA_EZ_CLOCK_GATING 0
+#define gcdDISABLE_RA_HZ_CLOCK_GATING 0
+#define gcdDISABLE_TX_CLOCK_GATING 0
+#define gcdDISABLE_TFB_CLOCK_GATING 0
+#define gcdDISABLE_GPIPE_CLOCK_GATING 0
+#define gcdDISABLE_BLT_CLOCK_GATING 0
+#define gcdDISABLE_TPG_CLOCK_GATING 0
+#define gcdDISABLE_VX_CLOCK_GATING 0
+
+#if gcdDEBUG_MODULE_CLOCK_GATING
+gceSTATUS
+_ConfigureModuleLevelClockGating(
+ gckHARDWARE Hardware
+ )
+{
+ gctUINT32 data;
+
+ gcmkVERIFY_OK(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &data));
+
+#if gcdDISABLE_FE_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)));
+#endif
+
+#if gcdDISABLE_PE_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ?
+ 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2)));
+#endif
+
+#if gcdDISABLE_SH_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ?
+ 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3)));
+#endif
+
+#if gcdDISABLE_PA_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ?
+ 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4)));
+#endif
+
+#if gcdDISABLE_SE_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ?
+ 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5)));
+#endif
+
+#if gcdDISABLE_RA_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:6) - (0 ?
+ 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6)));
+#endif
+
+#if gcdDISABLE_TX_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:7) - (0 ? 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ?
+ 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7)));
+#endif
+
+#if gcdDISABLE_RA_EZ_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16)));
+#endif
+
+#if gcdDISABLE_RA_HZ_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ?
+ 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ?
+ 17:17) + 1))))))) << (0 ? 17:17)));
+#endif
+
+#if gcdDISABLE_TFB_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19)));
+#endif
+
+#if gcdDISABLE_GPIPE_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 22:22) - (0 ? 22:22) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 22:22) - (0 ?
+ 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 22:22) - (0 ? 22:22) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 22:22) - (0 ?
+ 22:22) + 1))))))) << (0 ? 22:22)));
+#endif
+
+#if gcdDISABLE_BLT_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
+ 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
+ 20:20) + 1))))))) << (0 ? 20:20)));
+#endif
+
+#if gcdDISABLE_TPG_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 18:18) - (0 ? 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 18:18) - (0 ?
+ 18:18) + 1))))))) << (0 ? 18:18))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 18:18) - (0 ? 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 18:18) - (0 ?
+ 18:18) + 1))))))) << (0 ? 18:18)));
+#endif
+
+#if gcdDISABLE_VX_CLOCK_GATING
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 21:21) - (0 ? 21:21) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 21:21) - (0 ?
+ 21:21) + 1))))))) << (0 ? 21:21))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 21:21) - (0 ? 21:21) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 21:21) - (0 ?
+ 21:21) + 1))))))) << (0 ? 21:21)));
+#endif
+
+ gcmkVERIFY_OK(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ data));
+
+#if gcdDISABLE_STARVE_MODULE_CLOCK_GATING
+ gcmkVERIFY_OK(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress +
+ 0x00100,
+ &data));
+
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ?
+ 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2)));
+
+ gcmkVERIFY_OK(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00100,
+ data));
+
+#endif
+
+#if gcdDISABLE_MODULE_CLOCK_GATING
+ gcmkVERIFY_OK(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress +
+ 0x00100,
+ &data));
+
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)));
+
+
+ gcmkVERIFY_OK(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00100,
+ data));
+#endif
+
+ return gcvSTATUS_OK;
+}
+#endif
+
+#if gcdPOWEROFF_TIMEOUT
+void
+_PowerTimerFunction(
+ gctPOINTER Data
+ )
+{
+ gckHARDWARE hardware = (gckHARDWARE)Data;
+ gcmkVERIFY_OK(
+ gckHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
+}
+#endif
+
+static gceSTATUS
+_VerifyDMA(
+ IN gckOS Os,
+ IN gceCORE Core,
+ gctUINT32_PTR Address1,
+ gctUINT32_PTR Address2,
+ gctUINT32_PTR State1,
+ gctUINT32_PTR State2
+ )
+{
+ gceSTATUS status;
+ gctUINT32 i;
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00660, State1));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00660, State1));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00664, Address1));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00664, Address1));
+
+ for (i = 0; i < 500; i += 1)
+ {
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00660, State2));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00660, State2));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00664, Address2));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00664, Address2));
+
+ if (*Address1 != *Address2)
+ {
+ break;
+ }
+
+ if (*State1 != *State2)
+ {
+ break;
+ }
+ }
+
+OnError:
+ return status;
+}
+
+static gceSTATUS
+_DumpDebugRegisters(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gcsiDEBUG_REGISTERS_PTR Descriptor
+ )
+{
+/* If this value is changed, print formats need to be changed too. */
+#define REG_PER_LINE 8
+ gceSTATUS status = gcvSTATUS_OK;
+ gctUINT32 select;
+ gctUINT i, j, pipe;
+ gctUINT32 datas[REG_PER_LINE];
+ gctUINT32 oldControl, control;
+
+ gcmkHEADER_ARG("Os=0x%X Descriptor=0x%X", Os, Descriptor);
+
+ /* Record control. */
+ gckOS_ReadRegisterEx(Os, Core, 0x0, &oldControl);
+
+ for (pipe = 0; pipe < 2; pipe++)
+ {
+ if (!(Descriptor->pipeMask & (1 << pipe)))
+ {
+ continue;
+ }
+
+ gcmkPRINT_N(8, " %s[%d] debug registers:\n", Descriptor->module, pipe);
+
+ /* Switch pipe. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x0, &control));
+ control &= ~(0xF << 20);
+ control |= (pipe << 20);
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x0, control));
+
+ gcmkASSERT(Descriptor->count % REG_PER_LINE);
+
+ for (i = 0; i < Descriptor->count; i += REG_PER_LINE)
+ {
+ /* Select of first one in the group. */
+ select = i + Descriptor->selectStart;
+
+ /* Read a group of registers. */
+ for (j = 0; j < REG_PER_LINE; j++)
+ {
+ /* Shift select to right position. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, (select + j) << Descriptor->shift));
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &datas[j]));
+ }
+
+ gcmkPRINT_N(32, " [%02X] %08X %08X %08X %08X %08X %08X %08X %08X\n",
+ select, datas[0], datas[1], datas[2], datas[3], datas[4], datas[5], datas[6], datas[7]);
+ }
+ }
+
+ /* Restore control. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x0, oldControl));
+
+OnError:
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_DumpLinkStack(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gcsiDEBUG_REGISTERS_PTR Descriptor
+ )
+{
+ /* Get wrptr */
+ gctUINT32 shift = Descriptor->shift;
+ gctUINT32 pointerSelect = 0xE << shift;
+ gctUINT32 pointer, wrPtr, rdPtr, links[16];
+ gctUINT32 stackSize = 16;
+ gctUINT32 oldestPtr = 0;
+ gctUINT32 i;
+
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, pointerSelect));
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &pointer));
+
+ wrPtr = (pointer & 0xF0) >> 4;
+ rdPtr = pointer & 0xF;
+
+ /* Move rdptr to the oldest one (next one to the latest one. ) */
+ oldestPtr = (wrPtr + 1) % stackSize;
+
+ while (rdPtr != oldestPtr)
+ {
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, 0x0));
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, 0xF << shift));
+
+
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, pointerSelect));
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &pointer));
+
+ rdPtr = pointer & 0xF;
+ }
+
+ gcmkPRINT(" Link stack:");
+
+ /* Read from stack bottom*/
+ for (i = 0; i < stackSize; i++)
+ {
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, 0xD << shift));
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &links[i]));
+
+ /* Advance rdPtr. */
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, 0x0));
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, 0xF << shift));
+ }
+
+ /* Print. */
+ for (i = 0; i < stackSize; i += 4)
+ {
+ gcmkPRINT_N(32, " [0x%02X] 0x%08X [0x%02X] 0x%08X [0x%02X] 0x%08X [0x%02X] 0x%08X\n",
+ i, links[i], i + 1, links[i + 1], i + 2, links[i + 2], i + 3, links[i + 3]);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_DumpFEStack(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gcsiDEBUG_REGISTERS_PTR Descriptor
+ )
+{
+ gctUINT i;
+ gctINT j;
+ gctUINT32 stack[32][2];
+ gctUINT32 link[32];
+
+ static gcsFE_STACK _feStacks[] =
+ {
+ { "PRE_STACK", 32, 0x1A, 0x9A, 0x00, 0x1B, 0x1E },
+ { "CMD_STACK", 32, 0x1C, 0x9C, 0x1E, 0x1D, 0x1E },
+ };
+
+ for (i = 0; i < gcmCOUNTOF(_feStacks); i++)
+ {
+ gckOS_WriteRegisterEx(Os, Core, Descriptor->index, _feStacks[i].clear);
+
+ for (j = 0; j < _feStacks[i].count; j++)
+ {
+ gckOS_WriteRegisterEx(Os, Core, Descriptor->index, _feStacks[i].highSelect);
+
+ gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &stack[j][0]);
+
+ gckOS_WriteRegisterEx(Os, Core, Descriptor->index, _feStacks[i].lowSelect);
+
+ gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &stack[j][1]);
+
+ gckOS_WriteRegisterEx(Os, Core, Descriptor->index, _feStacks[i].next);
+
+ if (_feStacks[i].linkSelect)
+ {
+ gckOS_WriteRegisterEx(Os, Core, Descriptor->index, _feStacks[i].linkSelect);
+
+ gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &link[j]);
+ }
+ }
+
+ gcmkPRINT(" %s:", _feStacks[i].name);
+
+ for (j = 31; j >= 3; j -= 4)
+ {
+ gcmkPRINT(" %08X %08X %08X %08X %08X %08X %08X %08X",
+ stack[j][0], stack[j][1], stack[j - 1][0], stack[j - 1][1],
+ stack[j - 2][0], stack[j - 2][1], stack[j - 3][0], stack[j - 3][1]);
+ }
+
+ if (_feStacks[i].linkSelect)
+ {
+ gcmkPRINT(" LINK_STACK:");
+
+ for (j = 31; j >= 3; j -= 4)
+ {
+ gcmkPRINT(" %08X %08X %08X %08X %08X %08X %08X %08X",
+ link[j], link[j], link[j - 1], link[j - 1],
+ link[j - 2], link[j - 2], link[j - 3], link[j - 3]);
+ }
+ }
+
+ }
+
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_IsGPUPresent(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gcsHARDWARE_SIGNATURE signature;
+ gctUINT32 control;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &control));
+
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1)));
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ control));
+
+ gckOS_ZeroMemory((gctPOINTER)&signature, gcmSIZEOF(gcsHARDWARE_SIGNATURE));
+
+ /* Identify the hardware. */
+ gcmkONERROR(_GetHardwareSignature(Hardware,
+ Hardware->os,
+ Hardware->core,
+ &signature));
+
+ /* Check if these are the same values as saved before. */
+ if ((Hardware->signature.chipModel != signature.chipModel)
+ || (Hardware->signature.chipRevision != signature.chipRevision)
+ || (Hardware->signature.chipFeatures != signature.chipFeatures)
+ || (Hardware->signature.chipMinorFeatures != signature.chipMinorFeatures)
+ || (Hardware->signature.chipMinorFeatures1 != signature.chipMinorFeatures1)
+ || (Hardware->signature.chipMinorFeatures2 != signature.chipMinorFeatures2)
+ )
+ {
+ gcmkPRINT("[galcore]: GPU is not present.");
+ gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+_FlushCache(
+ gckHARDWARE Hardware,
+ gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctUINT32 bytes, requested;
+ gctPOINTER buffer;
+
+ /* Get the size of the flush command. */
+ gcmkONERROR(gckHARDWARE_Flush(Hardware,
+ gcvFLUSH_ALL,
+ gcvNULL,
+ &requested));
+
+ /* Reserve space in the command queue. */
+ gcmkONERROR(gckCOMMAND_Reserve(Command,
+ requested,
+ &buffer,
+ &bytes));
+
+ /* Append a flush. */
+ gcmkONERROR(gckHARDWARE_Flush(
+ Hardware, gcvFLUSH_ALL, buffer, &bytes
+ ));
+
+ /* Execute the command queue. */
+ gcmkONERROR(gckCOMMAND_Execute(Command, requested));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+static gctBOOL
+_IsGPUIdle(
+ IN gctUINT32 Idle
+ )
+{
+ return Idle == 0x7FFFFFFF;
+}
+
+gctBOOL
+_QueryFeatureDatabase(
+ IN gckHARDWARE Hardware,
+ IN gceFEATURE Feature
+ )
+{
+ gctBOOL available;
+
+ gcsFEATURE_DATABASE *database = Hardware->featureDatabase;
+
+ gcmkHEADER_ARG("Hardware=0x%x Feature=%d", Hardware, Feature);
+
+ /* Only features needed by common kernel logic added here. */
+ switch (Feature)
+ {
+ case gcvFEATURE_END_EVENT:
+ available = gcvFALSE;
+ break;
+
+ case gcvFEATURE_MC20:
+ available = database->REG_MC20;
+ break;
+
+ case gcvFEATURE_EARLY_Z:
+ available = database->REG_NoEZ == 0;
+ break;
+
+ case gcvFEATURE_HZ:
+ available = database->REG_HierarchicalZ;
+ break;
+
+ case gcvFEATURE_NEW_HZ:
+ available = database->REG_NewHZ;
+ break;
+
+ case gcvFEATURE_FAST_MSAA:
+ available = database->REG_FastMSAA;
+ break;
+
+ case gcvFEATURE_SMALL_MSAA:
+ available = database->REG_SmallMSAA;
+ break;
+
+ case gcvFEATURE_DYNAMIC_FREQUENCY_SCALING:
+ /* This feature doesn't apply for 2D cores. */
+ available = database->REG_DynamicFrequencyScaling && database->REG_Pipe3D;
+
+ if (Hardware->identity.chipModel == gcv1000 &&
+ (Hardware->identity.chipRevision == 0x5039 ||
+ Hardware->identity.chipRevision == 0x5040))
+ {
+ available = gcvFALSE;
+ }
+ break;
+
+ case gcvFEATURE_ACE:
+ available = database->REG_ACE;
+ break;
+
+ case gcvFEATURE_HALTI2:
+ available = database->REG_Halti2;
+ break;
+
+ case gcvFEATURE_PIPE_2D:
+ available = database->REG_Pipe2D;
+ break;
+
+ case gcvFEATURE_PIPE_3D:
+#if gcdENABLE_3D
+ available = database->REG_Pipe3D;
+#else
+ available = gcvFALSE;
+#endif
+ break;
+
+ case gcvFEATURE_FC_FLUSH_STALL:
+ available = database->REG_FcFlushStall;
+ break;
+
+ case gcvFEATURE_BLT_ENGINE:
+ available = database->REG_BltEngine;
+ break;
+
+ case gcvFEATURE_HALTI0:
+ available = database->REG_Halti0;
+ break;
+
+ case gcvFEATURE_FE_ALLOW_STALL_PREFETCH_ENG:
+ available = database->REG_FEAllowStallPrefetchEng;
+ break;
+
+ case gcvFEATURE_MMU:
+ available = database->REG_MMU;
+ break;
+
+ case gcvFEATURE_FENCE:
+ available = database->REG_Halti5;
+ break;
+
+ case gcvFEATURE_TEX_BASELOD:
+ available = database->REG_Halti2;
+
+ if (_IsHardwareMatch(Hardware, gcv900, 0x5250))
+ {
+ available = gcvTRUE;
+ }
+ break;
+
+ case gcvFEATURE_TEX_CACHE_FLUSH_FIX:
+ available = database->REG_Halti5;
+ break;
+
+ case gcvFEATURE_BUG_FIXES1:
+ available = database->REG_BugFixes1;
+ break;
+
+ case gcvFEATURE_MULTI_SOURCE_BLT:
+ available = database->REG_MultiSourceBlt;
+ break;
+
+ case gcvFEATURE_HALTI5:
+ available = database->REG_Halti5;
+ break;
+
+ case gcvFEATURE_FAST_CLEAR:
+ available = database->REG_FastClear;
+
+ if (Hardware->identity.chipModel == gcv700)
+ {
+ available = gcvFALSE;
+ }
+ break;
+
+ case gcvFEATURE_BUG_FIXES7:
+ available = database->REG_BugFixes7;
+ break;
+
+ case gcvFEATURE_ZCOMPRESSION:
+ available = database->REG_ZCompression;
+ break;
+
+ case gcvFEATURE_SHADER_HAS_INSTRUCTION_CACHE:
+ available = database->REG_InstructionCache;
+ break;
+
+ case gcvFEATURE_YUV420_TILER:
+ available = database->REG_YUV420Tiler;
+ break;
+
+ case gcvFEATURE_2DPE20:
+ available = database->REG_2DPE20;
+ break;
+
+ case gcvFEATURE_DITHER_AND_FILTER_PLUS_ALPHA_2D:
+ available = database->REG_DitherAndFilterPlusAlpha2D;
+ break;
+
+ case gcvFEATURE_ONE_PASS_2D_FILTER:
+ available = database->REG_OnePass2DFilter;
+ break;
+
+ case gcvFEATURE_HALTI1:
+ available = database->REG_Halti1;
+ break;
+
+ case gcvFEATURE_HALTI3:
+ available = database->REG_Halti3;
+ break;
+
+ case gcvFEATURE_HALTI4:
+ available = database->REG_Halti4;
+ break;
+
+ case gcvFEATURE_GEOMETRY_SHADER:
+ available = database->REG_GeometryShader;
+ break;
+
+ case gcvFEATURE_TESSELLATION:
+ available = database->REG_TessellationShaders;
+ break;
+
+ case gcvFEATURE_GENERIC_ATTRIB:
+ available = database->REG_Generics;
+ break;
+
+ case gcvFEATURE_TEXTURE_LINEAR:
+ available = database->REG_LinearTextureSupport;
+ break;
+
+ case gcvFEATURE_TX_FILTER:
+ available = database->REG_TXFilter;
+ break;
+
+ case gcvFEATURE_TX_SUPPORT_DEC:
+ available = database->REG_TXSupportDEC;
+ break;
+
+ case gcvFEATURE_TX_FRAC_PRECISION_6BIT:
+ available = database->REG_TX6bitFrac;
+ break;
+
+ case gcvFEATURE_TEXTURE_ASTC:
+ available = database->REG_TXEnhancements4 && !database->NO_ASTC;
+ break;
+
+ case gcvFEATURE_SHADER_ENHANCEMENTS2:
+ available = database->REG_SHEnhancements2;
+ break;
+
+ case gcvFEATURE_BUG_FIXES18:
+ available = database->REG_BugFixes18;
+ break;
+
+ case gcvFEATURE_64K_L2_CACHE:
+ available = gcvFALSE;
+ break;
+
+ case gcvFEATURE_BUG_FIXES4:
+ available = database->REG_BugFixes4;
+ break;
+
+ case gcvFEATURE_BUG_FIXES12:
+ available = database->REG_BugFixes12;
+ break;
+
+ case gcvFEATURE_HW_TFB:
+ available = database->HWTFB;
+ break;
+
+ case gcvFEATURE_SNAPPAGE_CMD_FIX:
+ available = database->SH_SNAP2PAGE_FIX;
+ break;
+
+ case gcvFEATURE_SECURITY:
+ available = database->SECURITY;
+ break;
+
+ case gcvFEATURE_TX_DESCRIPTOR:
+ available = database->REG_Halti5;
+ break;
+
+ case gcvFEATURE_TX_DESC_CACHE_CLOCKGATE_FIX:
+ available = database->TX_DESC_CACHE_CLOCKGATE_FIX;
+ break;
+
+ case gcvFEATURE_ROBUSTNESS:
+ available = database->ROBUSTNESS;
+ break;
+
+ case gcvFEATURE_SNAPPAGE_CMD:
+ available = database->SNAPPAGE_CMD;
+ break;
+
+ case gcvFEATURE_HALF_FLOAT_PIPE:
+ available = database->REG_HalfFloatPipe;
+ break;
+
+ case gcvFEATURE_SH_INSTRUCTION_PREFETCH:
+ available = database->SH_ICACHE_PREFETCH;
+ break;
+
+ case gcvFEATURE_FE_NEED_DUMMYDRAW:
+ available = database->FE_NEED_DUMMYDRAW;
+ break;
+
+ case gcvFEATURE_DEC300_COMPRESSION:
+ available = database->REG_DEC;
+ break;
+
+ case gcvFEATURE_DEC400_COMPRESSION:
+ available = database->G2D_DEC400;
+ break;
+
+ case gcvFEATURE_TPC_COMPRESSION:
+ available = database->REG_ThirdPartyCompression;
+ break;
+
+ case gcvFEATURE_TPCV11_COMPRESSION:
+ available = database->G2D_3rd_PARTY_COMPRESSION_1_1;
+ break;
+
+ case gcvFEATURE_USC_DEFER_FILL_FIX:
+ available = database->USC_DEFER_FILL_FIX;
+ break;
+
+ case gcvFEATURE_USC:
+ available = database->REG_Halti5;
+ break;
+
+ case gcvFEATURE_RA_CG_FIX:
+ available = database->RA_CG_FIX;
+ break;
+
+ case gcvFEATURE_ZERO_ATTRIB_SUPPORT:
+ available = database->REG_Halti4;
+ break;
+
+ case gcvFEATURE_SH_CLOCK_GATE_FIX:
+ available = database->SH_CLOCK_GATE_FIX;
+ break;
+
+ case gcvFEATURE_GPIPE_CLOCK_GATE_FIX:
+ available = gcvFALSE;
+ break;
+
+ case gcvFEATURE_NEW_GPIPE:
+ available = database->NEW_GPIPE;
+ break;
+
+ case gcvFEATURE_MULTI_CORE_BLOCK_SET_CONFIG2:
+ available = database->MULTI_CORE_BLOCK_SET_CONFIG2;
+ break;
+
+ case gcvFEATURE_SECURITY_AHB:
+ available = database->SECURITY_AHB;
+ break;
+
+ default:
+ gcmkFATAL("Invalid feature has been requested.");
+ available = gcvFALSE;
+ }
+
+ gcmkFOOTER_ARG("%d", available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE);
+ return available;
+}
+
+static void
+_ConfigurePolicyID(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 policyID;
+ gctUINT32 auxBit = ~0U;
+ gctUINT32 axiConfig;
+ gckOS os = Hardware->os;
+ gceCORE core = Hardware->core;
+ gctUINT32 i;
+ gctUINT32 offset;
+ gctUINT32 shift;
+ gctUINT32 currentAxiConfig;
+
+ status = gckOS_GetPolicyID(os, gcvSURF_TYPE_UNKNOWN, &policyID, &axiConfig);
+
+ if (status == gcvSTATUS_NOT_SUPPORTED)
+ {
+ /* No customized policyID setting. */
+ return;
+ }
+
+ for (i = 0; i < 16; i++)
+ {
+ /* Mapping 16 surface type.*/
+ status = gckOS_GetPolicyID(os, (gceSURF_TYPE) i, &policyID, &axiConfig);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ if (auxBit == ~0U)
+ {
+ /* There is a customized policyID setting for this type. */
+ auxBit = (policyID >> 4) & 0x1;
+ }
+ else
+ {
+ /* Check whether this bit changes. */
+ if (auxBit != ((policyID >> 4) & 0x1))
+ {
+ gcmkPRINT("[galcore]: AUX_BIT changes");
+ return;
+ }
+ }
+
+ offset = policyID >> 1;
+
+ shift = (policyID & 0x1) * 16;
+
+ axiConfig &= 0xFFFF;
+
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+ os,
+ core,
+ (0x0070 + offset) << 2,
+ &currentAxiConfig
+ ));
+
+ currentAxiConfig |= (axiConfig << shift);
+
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(
+ os,
+ core,
+ (0x0070 + offset) << 2,
+ currentAxiConfig
+ ));
+ }
+ }
+
+ if (auxBit != ~0U)
+ {
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(
+ os,
+ core,
+ 0x000EC,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:8) - (0 ?
+ 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8))) | (((gctUINT32) ((gctUINT32) (auxBit) & ((gctUINT32) ((((1 ? 8:8) - (0 ?
+ 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8)))
+ ));
+ }
+}
+
+/*
+* State timer helper must be called with powerMutex held.
+*/
+void
+gckSTATETIMER_Reset(
+ IN gcsSTATETIMER * StateTimer,
+ IN gctUINT64 Start
+ )
+{
+ gctUINT64 now;
+
+ if (Start)
+ {
+ now = Start;
+ }
+ else
+ {
+ gckOS_GetProfileTick(&now);
+ }
+
+ StateTimer->recent = StateTimer->start = now;
+
+ gckOS_ZeroMemory(StateTimer->elapse, gcmSIZEOF(StateTimer->elapse));
+}
+
+void
+gckSTATETIMER_Accumulate(
+ IN gcsSTATETIMER * StateTimer,
+ IN gceCHIPPOWERSTATE OldState
+ )
+{
+ gctUINT64 now;
+ gctUINT64 elapse;
+
+ gckOS_GetProfileTick(&now);
+
+ elapse = now - StateTimer->recent;
+
+ StateTimer->recent = now;
+
+ StateTimer->elapse[OldState] += elapse;
+}
+
+void
+gckSTATETIMER_Query(
+ IN gcsSTATETIMER * StateTimer,
+ IN gceCHIPPOWERSTATE State,
+ OUT gctUINT64_PTR Start,
+ OUT gctUINT64_PTR End,
+ OUT gctUINT64_PTR On,
+ OUT gctUINT64_PTR Off,
+ OUT gctUINT64_PTR Idle,
+ OUT gctUINT64_PTR Suspend
+ )
+{
+ *Start = StateTimer->start;
+
+ gckSTATETIMER_Accumulate(StateTimer, State);
+
+ *End = StateTimer->recent;
+
+ *On = StateTimer->elapse[gcvPOWER_ON];
+ *Off = StateTimer->elapse[gcvPOWER_OFF];
+ *Idle = StateTimer->elapse[gcvPOWER_IDLE];
+ *Suspend = StateTimer->elapse[gcvPOWER_SUSPEND];
+
+ gckSTATETIMER_Reset(StateTimer, StateTimer->recent);
+}
+
+/******************************************************************************\
+****************************** gckHARDWARE API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckHARDWARE_Construct
+**
+** Construct a new gckHARDWARE object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an initialized gckOS object.
+**
+** gceCORE Core
+** Specified core.
+**
+** OUTPUT:
+**
+** gckHARDWARE * Hardware
+** Pointer to a variable that will hold the pointer to the gckHARDWARE
+** object.
+*/
+gceSTATUS
+gckHARDWARE_Construct(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gckHARDWARE * Hardware
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware = gcvNULL;
+ gctUINT16 data = 0xff00;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+ /* Enable the GPU. */
+ gcmkONERROR(gckOS_SetGPUPower(Os, Core, gcvTRUE, gcvTRUE));
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ 0x00000900));
+
+ /* Allocate the gckHARDWARE object. */
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckHARDWARE),
+ &pointer));
+
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckHARDWARE));
+
+ hardware = (gckHARDWARE) pointer;
+
+ /* Initialize the gckHARDWARE object. */
+ hardware->object.type = gcvOBJ_HARDWARE;
+ hardware->os = Os;
+ hardware->core = Core;
+
+ gcmkONERROR(_GetHardwareSignature(hardware, Os, Core, &hardware->signature));
+
+ /* Identify the hardware. */
+ gcmkONERROR(_IdentifyHardwareByDatabase(hardware, Os, Core, &hardware->identity));
+
+ hardware->mmuVersion = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_MMU);
+
+ /* Get the system's physical base address for old MMU */
+ if (hardware->mmuVersion == 0)
+ {
+ gcmkONERROR(gckOS_GetBaseAddress(Os, &hardware->baseAddress));
+ }
+
+ /* Determine the hardware type */
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_PIPE_3D)
+ && gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_PIPE_2D)
+ )
+ {
+ hardware->type = gcvHARDWARE_3D2D;
+ }
+ else
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_PIPE_2D))
+ {
+ hardware->type = gcvHARDWARE_2D;
+ }
+ else
+ {
+ hardware->type = gcvHARDWARE_3D;
+ }
+
+ hardware->powerBaseAddress
+ = ((hardware->identity.chipModel == gcv300)
+ && (hardware->identity.chipRevision < 0x2000))
+ ? 0x0100
+ : 0x0000;
+
+ /* VIV: Don't do sftware reset here for 0x2000, 0xfff5450 to workaround #12789. */
+ if(!(_IsHardwareMatch(hardware, gcv2000, 0xffff5450)))
+ {
+ /* _ResetGPU need powerBaseAddress. */
+ status = _ResetGPU(hardware, Os, Core);
+
+ if (status != gcvSTATUS_OK)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "_ResetGPU failed: status=%d\n", status);
+ }
+ }
+
+#if gcdDEC_ENABLE_AHB
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, gcvCORE_DEC, 0x18180, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 22:22) - (0 ? 22:22) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 22:22) - (0 ?
+ 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 22:22) - (0 ? 22:22) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 22:22) - (0 ?
+ 22:22) + 1))))))) << (0 ? 22:22)))));
+#endif
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_64K_L2_CACHE) == gcvFALSE)
+ {
+ /* VIV: On all cores without 64k L2, we disable L2, no matter whether L2 exists or not. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x0055C,
+ 0x00FFFFFF));
+ }
+
+ hardware->powerMutex = gcvNULL;
+
+ /* Determine whether bug fixes #1 are present. */
+ hardware->extraEventStates = (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_BUG_FIXES1) == gcvFALSE);
+
+ /* Check if big endian */
+ hardware->bigEndian = (*(gctUINT8 *)&data == 0xff);
+
+ /* Initialize the fast clear. */
+ gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
+
+#if !gcdENABLE_128B_MERGE
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_MULTI_SOURCE_BLT))
+ {
+ /* 128B merge is turned on by default. Disable it. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00558, 0));
+ }
+
+#endif
+
+ {
+ gctUINT32 value;
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00090, &value));
+#if gcdDEC_ENABLE_AHB
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_DEC300_COMPRESSION))
+ {
+ value |= ~0xFFFFFFBF;
+ }
+ else
+#endif
+ {
+ value &= 0xFFFFFFBF;
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00090, value));
+ }
+
+ /* Set power state to ON. */
+ hardware->chipPowerState = gcvPOWER_ON;
+ hardware->clockState = gcvTRUE;
+ hardware->powerState = gcvTRUE;
+ hardware->lastWaitLink = ~0U;
+ hardware->lastEnd = ~0U;
+ hardware->globalSemaphore = gcvNULL;
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ hardware->powerOnFscaleVal = 64;
+#endif
+
+ gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerMutex));
+ gcmkONERROR(gckOS_CreateSemaphore(Os, &hardware->globalSemaphore));
+ hardware->startIsr = gcvNULL;
+ hardware->stopIsr = gcvNULL;
+
+#if gcdPOWEROFF_TIMEOUT
+ hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
+
+ gcmkVERIFY_OK(gckOS_CreateTimer(Os,
+ _PowerTimerFunction,
+ (gctPOINTER)hardware,
+ &hardware->powerOffTimer));
+#endif
+
+ gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
+ gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pendingEvent));
+
+ status = gckOS_QueryOption(Os, "powerManagement", (gctUINT32*)&hardware->powerManagement);
+
+ if (status == gcvSTATUS_NOT_SUPPORTED)
+ {
+ /* Enable power management by default. */
+ hardware->powerManagement = gcvTRUE;
+ }
+
+ /* Disable profiler by default */
+ hardware->gpuProfiler = gcvFALSE;
+ status = gckOS_QueryOption(Os, "gpuProfiler", (gctUINT32*)&hardware->gpuProfiler);
+ if (status == gcvSTATUS_NOT_SUPPORTED)
+ {
+ /* Enable power management by default. */
+ hardware->gpuProfiler= gcvFALSE;
+ }
+
+#if defined(LINUX) || defined(__QNXNTO__) || defined(UNDER_CE)
+ if (hardware->mmuVersion)
+ {
+ hardware->stallFEPrefetch
+ = gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_FE_ALLOW_STALL_PREFETCH_ENG);
+ }
+ else
+#endif
+ {
+ hardware->stallFEPrefetch = gcvTRUE;
+ }
+
+ gcmkONERROR(gckOS_QueryOption(Os, "mmu", (gctUINT32_PTR)&hardware->enableMMU));
+
+ hardware->minFscaleValue = 1;
+ hardware->waitCount = 200;
+
+ gckSTATETIMER_Reset(&hardware->powerStateTimer, 0);
+
+#if gcdLINK_QUEUE_SIZE
+ gcmkONERROR(gckQUEUE_Allocate(hardware->os, &hardware->linkQueue, gcdLINK_QUEUE_SIZE));
+#endif
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_SECURITY))
+ {
+ gctUINT32 ta = 0;
+
+ gcmkASSERT(gcvSTATUS_TRUE == gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_SECURITY_AHB));
+
+ status = gckOS_QueryOption(Os, "TA", &ta);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ hardware->secureMode = ta ? gcvSECURE_IN_TA : gcvSECURE_IN_NORMAL;
+ }
+ }
+ else if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_SECURITY_AHB))
+ {
+ hardware->secureMode = gcvSECURE_IN_NORMAL;
+ }
+
+ if (hardware->secureMode == gcvSECURE_IN_NORMAL)
+ {
+ hardware->pagetableArray.size = 4096;
+
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ hardware->os,
+ gcvFALSE,
+ &hardware->pagetableArray.size,
+ &hardware->pagetableArray.physical,
+ &hardware->pagetableArray.logical
+ ));
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ hardware->os,
+ hardware->pagetableArray.logical,
+ &hardware->pagetableArray.address
+ ));
+ }
+
+ /* Return pointer to the gckHARDWARE object. */
+ *Hardware = hardware;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (hardware != gcvNULL)
+ {
+ /* Turn off the power. */
+ gcmkVERIFY_OK(gckOS_SetGPUPower(Os, Core, gcvFALSE, gcvFALSE));
+
+ if (hardware->globalSemaphore != gcvNULL)
+ {
+ /* Destroy the global semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(Os,
+ hardware->globalSemaphore));
+ }
+
+ if (hardware->powerMutex != gcvNULL)
+ {
+ /* Destroy the power mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, hardware->powerMutex));
+ }
+
+#if gcdPOWEROFF_TIMEOUT
+ if (hardware->powerOffTimer != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
+ }
+#endif
+
+ if (hardware->pageTableDirty != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
+ }
+
+ if (hardware->pendingEvent != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pendingEvent));
+ }
+
+ if (hardware->pagetableArray.logical != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ Os,
+ hardware->pagetableArray.size,
+ hardware->pagetableArray.physical,
+ hardware->pagetableArray.logical
+ ));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, hardware));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Destroy
+**
+** Destroy an gckHARDWARE object.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Destroy(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Destroy the power semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(Hardware->os,
+ Hardware->globalSemaphore));
+
+ /* Destroy the power mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerMutex));
+
+#if gcdPOWEROFF_TIMEOUT
+ gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
+#endif
+
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
+
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pendingEvent));
+
+#if gcdLINK_QUEUE_SIZE
+ gckQUEUE_Free(Hardware->os, &Hardware->linkQueue);
+#endif
+
+ if (Hardware->pagetableArray.logical != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ Hardware->os,
+ Hardware->pagetableArray.size,
+ Hardware->pagetableArray.physical,
+ Hardware->pagetableArray.logical
+ ));
+ }
+
+ /* Mark the object as unknown. */
+ Hardware->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the object. */
+ gcmkONERROR(gcmkOS_SAFE_FREE(Hardware->os, Hardware));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_GetType
+**
+** Get the hardware type.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gceHARDWARE_TYPE * Type
+** Pointer to a variable that receives the type of hardware object.
+*/
+gceSTATUS
+gckHARDWARE_GetType(
+ IN gckHARDWARE Hardware,
+ OUT gceHARDWARE_TYPE * Type
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+ gcmkVERIFY_ARGUMENT(Type != gcvNULL);
+
+ *Type = Hardware->type;
+
+ gcmkFOOTER_ARG("*Type=%d", *Type);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_InitializeHardware
+**
+** Initialize the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 control;
+ gctUINT32 data;
+ gctUINT32 regPMC = 0;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Disable isolate GPU bit. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19)))));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &control));
+
+ /* Enable debug register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11)))));
+
+ /* Reset memory counters. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0003C,
+ ~0U));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0003C,
+ 0));
+
+ if (Hardware->mmuVersion == 0)
+ {
+ /* Program the base addesses. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0041C,
+ Hardware->baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00418,
+ Hardware->baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00428,
+ Hardware->baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00420,
+ Hardware->baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00424,
+ Hardware->baseAddress));
+ }
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress +
+ 0x00100,
+ &data));
+
+ /* Enable clock gating. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)));
+
+ if ((Hardware->identity.chipRevision == 0x4301)
+ || (Hardware->identity.chipRevision == 0x4302)
+ )
+ {
+ /* Disable stall module level clock gating for 4.3.0.1 and 4.3.0.2
+ ** revisions. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1)));
+ }
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00100,
+ data));
+
+#if gcdENABLE_3D
+ /* Disable PE clock gating on revs < 5.0 when HZ is present without a
+ ** bug fix. */
+ if ((Hardware->identity.chipRevision < 0x5000)
+ && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HZ)
+ && !gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BUG_FIXES4)
+ )
+ {
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ /* Disable PE clock gating. */
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ?
+ 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2)));
+ }
+#endif
+
+ if (Hardware->identity.chipModel == gcv4000 &&
+ ((Hardware->identity.chipRevision == 0x5208) || (Hardware->identity.chipRevision == 0x5222)))
+ {
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:23) - (0 ? 23:23) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:23) - (0 ?
+ 23:23) + 1))))))) << (0 ? 23:23))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 23:23) - (0 ? 23:23) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:23) - (0 ?
+ 23:23) + 1))))))) << (0 ? 23:23)))));
+ }
+
+ if ((Hardware->identity.chipModel == gcv1000 &&
+ (Hardware->identity.chipRevision == 0x5039 ||
+ Hardware->identity.chipRevision == 0x5040))
+ ||
+ (Hardware->identity.chipModel == gcv2000 &&
+ Hardware->identity.chipRevision == 0x5140)
+ )
+ {
+ gctUINT32 pulseEater;
+
+ pulseEater = ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16)));
+
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ ((((gctUINT32) (pulseEater)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ?
+ 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ?
+ 17:17) + 1))))))) << (0 ? 17:17)))));
+ }
+
+ if ((gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI2) == gcvSTATUS_FALSE)
+ || (Hardware->identity.chipRevision < 0x5422)
+ )
+ {
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:15) - (0 ? 15:15) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:15) - (0 ?
+ 15:15) + 1))))))) << (0 ? 15:15))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 15:15) - (0 ? 15:15) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:15) - (0 ?
+ 15:15) + 1))))))) << (0 ? 15:15)));
+ }
+
+ if (_IsHardwareMatch(Hardware, gcv2000, 0x5108))
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00480,
+ &data));
+
+ /* Set FE bus to one, TX bus to zero */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ?
+ 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:7) - (0 ? 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:7) - (0 ?
+ 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7)));
+
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00480,
+ data));
+ }
+
+ gcmkONERROR(
+ gckHARDWARE_SetMMU(Hardware,
+ Hardware->kernel->mmu->area[0].pageTableLogical));
+
+ if (Hardware->identity.chipModel >= gcv400
+ && Hardware->identity.chipModel != gcv420
+ && !gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BUG_FIXES12))
+ {
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ /* Disable PA clock gating. */
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ?
+ 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4)));
+ }
+
+ /* Limit 2D outstanding request. */
+ if (Hardware->maxOutstandingReads)
+ {
+ gctUINT32 data;
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00414,
+ &data));
+
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (Hardware->maxOutstandingReads & 0xFF) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)));
+
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00414,
+ data));
+ }
+
+ if (_IsHardwareMatch(Hardware, gcv1000, 0x5035))
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00414,
+ &data));
+
+ /* Disable HZ-L2. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12)));
+
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00414,
+ data));
+ }
+
+ if (_IsHardwareMatch(Hardware, gcv4000, 0x5222)
+ || _IsHardwareMatch(Hardware, gcv2000, 0x5108)
+ || (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TX_DESCRIPTOR)
+ && !gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TX_DESC_CACHE_CLOCKGATE_FIX)
+ )
+ )
+ {
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ /* Disable TX clock gating. */
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:7) - (0 ? 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ?
+ 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7)));
+ }
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_NEW_GPIPE) &&
+ !gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_GPIPE_CLOCK_GATE_FIX))
+ {
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ /* Disable GPIPE clock gating. */
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 22:22) - (0 ? 22:22) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 22:22) - (0 ?
+ 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 22:22) - (0 ? 22:22) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 22:22) - (0 ?
+ 22:22) + 1))))))) << (0 ? 22:22)));
+ }
+
+ if (_IsHardwareMatch(Hardware, gcv880, 0x5106))
+ {
+ Hardware->kernel->timeOut = 140 * 1000;
+ }
+
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ /* Disable RA HZ clock gating. */
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ?
+ 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ?
+ 17:17) + 1))))))) << (0 ? 17:17)));
+
+ /* Disable RA EZ clock gating. */
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16)));
+
+ if ((gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI5)
+ && !gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_RA_CG_FIX)
+ )
+ )
+ {
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ /* Disable RA clock gating. */
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:6) - (0 ?
+ 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6)));
+ }
+
+ if ((gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI5)
+ && !gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_SH_CLOCK_GATE_FIX)
+ )
+ )
+ {
+ if (regPMC == 0)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &regPMC));
+ }
+
+ /* Disable SH clock gating. */
+ regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ?
+ 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3)));
+ }
+
+ if (regPMC != 0)
+ {
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ regPMC));
+ }
+
+ if (_IsHardwareMatch(Hardware, gcv2000, 0x5108)
+ || (_IsHardwareMatch(Hardware, gcv2000, 0xffff5450))
+ || _IsHardwareMatch(Hardware, gcv320, 0x5007)
+ || _IsHardwareMatch(Hardware, gcv320, 0x5303)
+ || _IsHardwareMatch(Hardware, gcv880, 0x5106)
+ || _IsHardwareMatch(Hardware, gcv400, 0x4645)
+ )
+ {
+ /* Update GPU AXI cache atttribute. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00008,
+ 0x00002200));
+ }
+
+
+ if ((Hardware->identity.chipRevision > 0x5420)
+ && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_3D))
+ {
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ &data));
+
+ /* Disable internal DFS. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 18:18) - (0 ? 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 18:18) - (0 ?
+ 18:18) + 1))))))) << (0 ? 18:18))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 18:18) - (0 ? 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 18:18) - (0 ?
+ 18:18) + 1))))))) << (0 ? 18:18)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ data));
+ }
+
+
+ /* VIV: #15495. */
+ if (_IsHardwareMatch(Hardware, gcv2500, 0x5422))
+ {
+ gcmkONERROR(gckOS_ReadRegisterEx(
+ Hardware->os, Hardware->core, 0x00090, &data));
+
+ /* AXI switch setup to SPLIT_TO64 mode */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(
+ Hardware->os, Hardware->core, 0x00090, data));
+ }
+
+ _ConfigurePolicyID(Hardware);
+
+#if gcdDEBUG_MODULE_CLOCK_GATING
+ _ConfigureModuleLevelClockGating(Hardware);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryMemory
+**
+** Query the amount of memory available on the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * InternalSize
+** Pointer to a variable that will hold the size of the internal video
+** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
+** internal memory will be returned.
+**
+** gctUINT32 * InternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * InternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctSIZE_T * ExternalSize
+** Pointer to a variable that will hold the size of the external video
+** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
+** external memory will be returned.
+**
+** gctUINT32 * ExternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * ExternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * HorizontalTileSize
+** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
+** gcvNULL, no horizontal pixel per tile will be returned.
+**
+** gctUINT32 * VerticalTileSize
+** Number of vertical pixels per tile. If 'VerticalTileSize' is
+** gcvNULL, no vertical pixel per tile will be returned.
+*/
+gceSTATUS
+gckHARDWARE_QueryMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (InternalSize != gcvNULL)
+ {
+ /* No internal memory. */
+ *InternalSize = 0;
+ }
+
+ if (ExternalSize != gcvNULL)
+ {
+ /* No external memory. */
+ *ExternalSize = 0;
+ }
+
+ if (HorizontalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *HorizontalTileSize = 4;
+ }
+
+ if (VerticalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *VerticalTileSize = 4;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*InternalSize=%lu *InternalBaseAddress=0x%08x "
+ "*InternalAlignment=0x%08x *ExternalSize=%lu "
+ "*ExternalBaseAddress=0x%08x *ExtenalAlignment=0x%08x "
+ "*HorizontalTileSize=%u *VerticalTileSize=%u",
+ gcmOPT_VALUE(InternalSize),
+ gcmOPT_VALUE(InternalBaseAddress),
+ gcmOPT_VALUE(InternalAlignment),
+ gcmOPT_VALUE(ExternalSize),
+ gcmOPT_VALUE(ExternalBaseAddress),
+ gcmOPT_VALUE(ExternalAlignment),
+ gcmOPT_VALUE(HorizontalTileSize),
+ gcmOPT_VALUE(VerticalTileSize));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryChipIdentity
+**
+** Query the identity of the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+** Pointer to the identity structure.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+ IN gckHARDWARE Hardware,
+ OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Identity != gcvNULL);
+
+ *Identity = Hardware->identity;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SplitMemory
+**
+** Split a hardware specific memory address into a pool and offset.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT32 Address
+** Address in hardware specific format.
+**
+** OUTPUT:
+**
+** gcePOOL * Pool
+** Pointer to a variable that will hold the pool type for the address.
+**
+** gctUINT32 * Offset
+** Pointer to a variable that will hold the offset for the address.
+*/
+gceSTATUS
+gckHARDWARE_SplitMemory(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Addres=0x%08x", Hardware, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
+
+ if (Hardware->mmuVersion == 0)
+ {
+ /* Dispatch on memory type. */
+ switch ((((((gctUINT32) (Address)) >> (0 ? 31:31)) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) ))
+ {
+ case 0x0:
+ /* System memory. */
+ *Pool = gcvPOOL_SYSTEM;
+ break;
+
+ case 0x1:
+ /* Virtual memory. */
+ *Pool = gcvPOOL_VIRTUAL;
+ break;
+
+ default:
+ /* Invalid memory type. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Return offset of address. */
+ *Offset = (((((gctUINT32) (Address)) >> (0 ? 30:0)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 30:0) - (0 ? 30:0) + 1)))))) );
+ }
+ else
+ {
+ *Pool = gcvPOOL_SYSTEM;
+ *Offset = Address;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Pool=%d *Offset=0x%08x", *Pool, *Offset);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Execute
+**
+** Kickstart the hardware's command processor with an initialized command
+** buffer.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT32 Address
+** Hardware address of command buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes for the prefetch unit (until after the first LINK).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+ gctUINT32 control;
+
+ gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Bytes=%lu",
+ Hardware, Address, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Enable all events. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00014, ~0U));
+
+ /* Write address register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00654, Address));
+
+ /* Build control register. */
+ control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) ((Bytes + 7) >> 3) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ /* Set big endian */
+ if (Hardware->bigEndian)
+ {
+ control |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 21:20) - (0 ? 21:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 21:20) - (0 ?
+ 21:20) + 1))))))) << (0 ? 21:20))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ?
+ 21:20) - (0 ? 21:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 21:20) - (0 ?
+ 21:20) + 1))))))) << (0 ? 21:20)));
+ }
+
+ /* Make sure writing to command buffer and previous AHB register is done. */
+ gcmkONERROR(gckOS_MemoryBarrier(Hardware->os, gcvNULL));
+
+ /* Write control register. */
+ switch (Hardware->secureMode)
+ {
+ case gcvSECURE_NONE:
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00658, control));
+ break;
+ case gcvSECURE_IN_NORMAL:
+
+#if defined(__KERNEL__)
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00658, control));
+#endif
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x003A4, control));
+
+ break;
+#if gcdENABLE_TRUST_APPLICATION
+ case gcvSECURE_IN_TA:
+ /* Send message to TA. */
+ gcmkONERROR(gckKERNEL_SecurityStartCommand(Hardware->kernel, Address, (gctUINT32)Bytes));
+ break;
+#endif
+ default:
+ break;
+ }
+
+ /* Increase execute count. */
+ Hardware->executeCount++;
+
+ /* Record last execute address. */
+ Hardware->lastExecuteAddress = Address;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Started command buffer @ 0x%08x",
+ Address);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_WaitLink
+**
+** Append a WAIT/LINK command sequence at the specified location in the command
+** queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** WAIT/LINK command sequence at or gcvNULL just to query the size of the
+** WAIT/LINK command sequence.
+**
+** gctUINT32 Address
+** GPU address of current location inside the command queue.
+**
+** gctUINT32 Offset
+** Offset into command buffer required for alignment.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the WAIT/LINK command
+** sequence. If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** by the WAIT/LINK command sequence. If 'Bytes' is gcvNULL, nothing will
+** be returned.
+**
+** gctUINT32 * WaitOffset
+** Pointer to a variable that will receive the offset of the WAIT command
+** from the specified logcial pointer.
+** If 'WaitOffset' is gcvNULL nothing will be returned.
+**
+** gctSIZE_T * WaitSize
+** Pointer to a variable that will receive the number of bytes used by
+** the WAIT command. If 'LinkSize' is gcvNULL nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_WaitLink(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gctUINT32 Offset,
+ IN OUT gctUINT32 * Bytes,
+ OUT gctUINT32 * WaitOffset,
+ OUT gctUINT32 * WaitSize
+ )
+{
+ gceSTATUS status;
+ gctUINT32_PTR logical;
+ gctUINT32 bytes;
+ gctBOOL useL2;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x *Bytes=%lu",
+ Hardware, Logical, Offset, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+ useL2 = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_64K_L2_CACHE);
+
+ /* Compute number of bytes required. */
+ if (useL2)
+ {
+ bytes = gcmALIGN(Offset + 24, 8) - Offset;
+ }
+ else
+ {
+ bytes = gcmALIGN(Offset + 16, 8) - Offset;
+ }
+
+ /* Cast the input pointer. */
+ logical = (gctUINT32_PTR) Logical;
+
+ if (logical != gcvNULL)
+ {
+ /* Not enough space? */
+ if (*Bytes < bytes)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ gcmkASSERT(Address != ~0U);
+
+ /* Store the WAIT/LINK address. */
+ Hardware->lastWaitLink = Address;
+
+ /* Append WAIT(count). */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (Hardware->waitCount) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ logical++;
+
+ if (useL2)
+ {
+ /* LoadState(AQFlush, 1), flush. */
+ *logical++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+ }
+
+ /* Append LINK(2, address). */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *logical++ = Address;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: WAIT %u", Address, Hardware->waitCount
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: LINK 0x%08x, #%lu",
+ Address + 8, Address, bytes
+ );
+
+ if (WaitOffset != gcvNULL)
+ {
+ /* Return the offset pointer to WAIT command. */
+ *WaitOffset = 0;
+ }
+
+ if (WaitSize != gcvNULL)
+ {
+ /* Return number of bytes used by the WAIT command. */
+ if (useL2)
+ {
+ *WaitSize = 16;
+ }
+ else
+ {
+ *WaitSize = 8;
+ }
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the WAIT/LINK command
+ ** sequence. */
+ *Bytes = bytes;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu *WaitOffset=0x%x *WaitSize=%lu",
+ gcmOPT_VALUE(Bytes), gcmOPT_VALUE(WaitOffset),
+ gcmOPT_VALUE(WaitSize));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_End
+**
+** Append an END command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** END command at or gcvNULL just to query the size of the END command.
+**
+** gctUINT32 Address
+** GPU address of current location inside the command queue.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the END command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the END command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_End(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gctUINT32 address;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append END. */
+ logical[0] =
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ /* Record the count of execution which is finised by this END. */
+ logical[1] =
+ Hardware->executeCount;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
+
+ /* Make sure the CPU writes out the data to memory. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, Logical));
+
+
+ gcmkASSERT(Address != ~0U);
+ address = Address;
+
+ Hardware->lastEnd = address;
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_ChipEnable(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gceCORE_3D_MASK ChipEnable,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gckOS os = Hardware->os;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x ChipEnable=0x%x *Bytes=%lu",
+ Hardware, Logical, ChipEnable, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append CHIPENABLE. */
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x0D & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | ChipEnable
+ );
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: CHIPENABLE 0x%x", Logical, ChipEnable);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the CHIPENABLE command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Nop
+**
+** Append a NOP command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** NOP command at or gcvNULL just to query the size of the NOP command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the NOP command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Nop(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append NOP. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the NOP command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Event
+**
+** Append an EVENT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the EVENT command at or gcvNULL just to query the size of the EVENT
+** command.
+**
+** gctUINT8 Event
+** Event ID to program.
+**
+** gceKERNEL_WHERE FromWhere
+** Location of the pipe to send the event.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the EVENT command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the EVENT command. If 'Bytes' is gcvNULL, nothing will be
+** returned.
+*/
+gceSTATUS
+gckHARDWARE_Event(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT8 Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT size;
+ gctUINT32 destination = 0;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+ gctBOOL blt;
+ gctBOOL extraEventStates;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
+ Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+ gcmkVERIFY_ARGUMENT(Event < 32);
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BLT_ENGINE))
+ {
+ /* Send all event from blt. */
+ if (FromWhere == gcvKERNEL_PIXEL)
+ {
+ FromWhere = gcvKERNEL_BLT;
+ }
+ }
+
+ blt = FromWhere == gcvKERNEL_BLT ? gcvTRUE : gcvFALSE;
+
+ /* Determine the size of the command. */
+
+ extraEventStates = Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL);
+
+ size = extraEventStates
+ ? gcmALIGN(8 + (1 + 5) * 4, 8) /* EVENT + 5 STATES */
+ : 8;
+
+ if (blt)
+ {
+ size += 16;
+ }
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < size)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ switch (FromWhere)
+ {
+ case gcvKERNEL_COMMAND:
+ /* From command processor. */
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+ break;
+
+ case gcvKERNEL_PIXEL:
+ /* From pixel engine. */
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+ break;
+
+ case gcvKERNEL_BLT:
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:7) - (0 ? 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (blt)
+ {
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x502E) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ /* Append EVENT(Event, destination). */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++
+ = ((((gctUINT32) (destination)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) ((gctUINT32) (Event) & ((gctUINT32) ((((1 ? 4:0) - (0 ?
+ 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0)));
+
+ if (blt)
+ {
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x502E) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+
+ /* Make sure the event ID gets written out before GPU can access it. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ {
+ gctPHYS_ADDR_T phys;
+ gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: EVENT %d", phys, Event);
+ }
+#endif
+
+ /* Append the extra states. These are needed for the chips that do not
+ ** support back-to-back events due to the async interface. The extra
+ ** states add the necessary delay to ensure that event IDs do not
+ ** collide. */
+ if (extraEventStates)
+ {
+ *logical++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0100) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+ *logical++ = 0;
+ *logical++ = 0;
+ *logical++ = 0;
+ *logical++ = 0;
+ *logical++ = 0;
+ }
+
+#if gcdINTERRUPT_STATISTIC
+ if (Event < gcmCOUNTOF(Hardware->kernel->eventObj->queues))
+ {
+ gckOS_AtomSetMask(Hardware->pendingEvent, 1 << Event);
+ }
+#endif
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the EVENT command. */
+ *Bytes = size;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_PipeSelect
+**
+** Append a PIPESELECT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the PIPESELECT command at or gcvNULL just to query the size of the
+** PIPESELECT command.
+**
+** gcePIPE_SELECT Pipe
+** Pipe value to select.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the PIPESELECT command.
+** If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the PIPESELECT command. If 'Bytes' is gcvNULL, nothing will be
+** returned.
+*/
+gceSTATUS
+gckHARDWARE_PipeSelect(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gcePIPE_SELECT Pipe,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Pipe=%d *Bytes=%lu",
+ Hardware, Logical, Pipe, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ /* Append a PipeSelect. */
+ if (Logical != gcvNULL)
+ {
+ gctUINT32 flush, stall;
+
+ if (*Bytes < 32)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ flush = (Pipe == gcvPIPE_2D)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
+
+ stall = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* LoadState(AQFlush, 1), flush. */
+ gcmkONERROR(gckOS_WriteMemory(
+ Hardware->os,
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ ));
+
+ gcmkONERROR(gckOS_WriteMemory(
+ Hardware->os,
+ logical + 1,
+ flush
+ ));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH 0x%x", logical, flush);
+
+ /* LoadState(AQSempahore, 1), stall. */
+ gcmkONERROR(gckOS_WriteMemory(
+ Hardware->os,
+ logical + 2,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ ));
+
+ gcmkONERROR(gckOS_WriteMemory(
+ Hardware->os,
+ logical + 3,
+ stall
+ ));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: SEMAPHORE 0x%x", logical + 2, stall);
+
+ /* Stall, stall. */
+ gcmkONERROR(gckOS_WriteMemory(
+ Hardware->os,
+ logical + 4,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ ));
+
+ gcmkONERROR(gckOS_WriteMemory(
+ Hardware->os,
+ logical + 5,
+ stall
+ ));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: STALL 0x%x", logical + 4, stall);
+
+ /* LoadState(AQPipeSelect, 1), pipe. */
+ gcmkONERROR(gckOS_WriteMemory(
+ Hardware->os,
+ logical + 6,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ ));
+
+ gcmkONERROR(gckOS_WriteMemory(
+ Hardware->os,
+ logical + 7,
+ (Pipe == gcvPIPE_2D)
+ ? 0x1
+ : 0x0
+ ));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: PIPE %d", logical + 6, Pipe);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the PIPESELECT command. */
+ *Bytes = 32;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Link
+**
+** Append a LINK command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the LINK command at or gcvNULL just to query the size of the LINK
+** command.
+**
+** gctUINT32 FetchAddress
+** Hardware address of destination of LINK.
+**
+** gctSIZE_T FetchSize
+** Number of bytes in destination of LINK.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the LINK command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the LINK command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Link(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT32 FetchSize,
+ IN OUT gctUINT32 * Bytes,
+ OUT gctUINT32 * Low,
+ OUT gctUINT32 * High
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T bytes;
+ gctUINT32 link;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x FetchAddress=0x%x FetchSize=%lu "
+ "*Bytes=%lu",
+ Hardware, Logical, FetchAddress, FetchSize,
+ gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ gcmkONERROR(
+ gckOS_WriteMemory(Hardware->os, logical + 1, FetchAddress));
+
+ if (High)
+ {
+ *High = FetchAddress;
+ }
+
+ /* Make sure the address got written before the LINK command. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+ /* Compute number of 64-byte aligned bytes to fetch. */
+ bytes = gcmALIGN(FetchAddress + FetchSize, 64) - FetchAddress;
+
+ /* Append LINK(bytes / 8), FetchAddress. */
+ link = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ gcmkONERROR(
+ gckOS_WriteMemory(Hardware->os, logical, link));
+
+ if (Low)
+ {
+ *Low = link;
+ }
+
+ /* Memory barrier. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the LINK command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_FenceRender(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FenceAddress,
+ IN gctUINT64 FenceData,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gckOS os = Hardware->os;
+ gctUINT32_PTR logical = (gctUINT32_PTR)Logical;
+
+ gctUINT32 dataLow = (gctUINT32)FenceData;
+ gctUINT32 dataHigh = (gctUINT32)(FenceData >> 32);
+
+ if (logical)
+ {
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E1A) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ FenceAddress
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E26) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ dataHigh
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E1B) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ dataLow
+ );
+ }
+ else
+ {
+ *Bytes = gcdRENDER_FENCE_LENGTH;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_FenceBlt(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FenceAddress,
+ IN gctUINT64 FenceData,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gckOS os = Hardware->os;
+ gctUINT32_PTR logical = (gctUINT32_PTR)Logical;
+
+ gctUINT32 dataLow = (gctUINT32)FenceData;
+ gctUINT32 dataHigh = (gctUINT32)(FenceData >> 32);
+
+ if (logical)
+ {
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x502E) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x5029) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ FenceAddress
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x502D) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ dataHigh
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x502A) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ dataLow
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x502E) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16)))
+ );
+
+ gcmkWRITE_MEMORY(
+ logical,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ );
+ }
+ else
+ {
+ *Bytes = gcdBLT_FENCE_LENGTH;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_Fence(
+ IN gckHARDWARE Hardware,
+ IN gceENGINE Engine,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FenceAddress,
+ IN gctUINT64 FenceData,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ if (Engine == gcvENGINE_RENDER)
+ {
+ return gckHARDWARE_FenceRender(Hardware, Logical, FenceAddress, FenceData, Bytes);
+ }
+ else
+ {
+ return gckHARDWARE_FenceBlt(Hardware, Logical, FenceAddress, FenceData, Bytes);
+ }
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_UpdateQueueTail
+**
+** Update the tail of the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the start of the command queue.
+**
+** gctUINT32 Offset
+** Offset into the command queue of the tail (last command).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x",
+ Hardware, Logical, Offset);
+
+ /* Verify the hardware. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Force a barrier. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, Logical));
+
+ /* Notify gckKERNEL object of change. */
+ gcmkONERROR(
+ gckKERNEL_Notify(Hardware->kernel,
+ gcvNOTIFY_COMMAND_QUEUE,
+ gcvFALSE));
+
+ if (status == gcvSTATUS_CHIP_NOT_READY)
+ {
+ gcmkONERROR(gcvSTATUS_DEVICE);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_ConvertLogical
+**
+** Convert a logical system address into a hardware specific address.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address to convert.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the memory in user space.
+**
+** gctUINT32* Address
+** Return hardware specific address.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ OUT gctUINT32 * Address
+ )
+{
+ gctUINT32 address;
+ gceSTATUS status;
+ gctPHYS_ADDR_T physical;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x InUserSpace=%d",
+ Hardware, Logical, InUserSpace);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Convert logical address into a physical address. */
+ if (InUserSpace)
+ {
+ gcmkONERROR(gckOS_UserLogicalToPhysical(Hardware->os, Logical, &physical));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, Logical, &physical));
+ }
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ /* For old MMU, get GPU address according to baseAddress. */
+ if (Hardware->mmuVersion == 0)
+ {
+ /* Subtract base address to get a GPU address. */
+ gcmkASSERT(address >= Hardware->baseAddress);
+ address -= Hardware->baseAddress;
+ }
+
+ /* Return hardware specific address. */
+ *Address = (Hardware->mmuVersion == 0)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ?
+ 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ?
+ 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 30:0) - (0 ? 30:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ?
+ 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ?
+ 30:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ?
+ 30:0)))
+ : address;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Interrupt
+**
+** Process an interrupt.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL InterruptValid
+** If gcvTRUE, this function will read the interrupt acknowledge
+** register, stores the data, and return whether or not the interrupt
+** is ours or not. If gcvFALSE, this functions will read the interrupt
+** acknowledge register and combine it with any stored value to handle
+** the event notifications.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Interrupt(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL InterruptValid
+ )
+{
+ gckEVENT eventObj;
+ gctUINT32 data = 0;
+ gctUINT32 dataEx;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Extract gckEVENT object. */
+ eventObj = Hardware->kernel->eventObj;
+ gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
+
+ if (InterruptValid)
+ {
+ /* Read AQIntrAcknowledge register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00010,
+ &data));
+
+ if (data == 0)
+ {
+ /* Not our interrupt. */
+ status = gcvSTATUS_NOT_OUR_INTERRUPT;
+ }
+ else
+ {
+
+#if gcdINTERRUPT_STATISTIC
+ gckOS_AtomClearMask(Hardware->pendingEvent, data);
+#endif
+
+ /* Inform gckEVENT of the interrupt. */
+ status = gckEVENT_Interrupt(eventObj,
+ data);
+ }
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BLT_ENGINE))
+ {
+ /* Read BLT interrupt. */
+ gcmkONERROR(gckOS_ReadRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x000D4,
+ &dataEx
+ ));
+
+ if (dataEx & 0x80000000)
+ {
+ /* Descriptor fetched, update counter. */
+ gckFE_UpdateAvaiable(Hardware, &Hardware->kernel->asyncCommand->fe);
+
+ dataEx &= ~0x80000000;
+ }
+
+ if (dataEx)
+ {
+ status = gckEVENT_Interrupt(Hardware->kernel->asyncEvent,
+ dataEx
+ );
+ }
+ }
+ }
+ else
+ {
+ /* Handle events. */
+ status = gckEVENT_Notify(eventObj, 0);
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BLT_ENGINE))
+ {
+ status = gckEVENT_Notify(Hardware->kernel->asyncEvent, 0);
+ }
+ }
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryCommandBuffer
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Alignment
+** Pointer to a variable receiving the alignment for each command.
+**
+** gctSIZE_T * ReservedHead
+** Pointer to a variable receiving the number of reserved bytes at the
+** head of each command buffer.
+**
+** gctSIZE_T * ReservedTail
+** Pointer to a variable receiving the number of bytes reserved at the
+** tail of each command buffer.
+*/
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+ IN gckHARDWARE Hardware,
+ IN gceENGINE Engine,
+ OUT gctUINT32 * Alignment,
+ OUT gctUINT32 * ReservedHead,
+ OUT gctUINT32 * ReservedTail
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Alignment != gcvNULL)
+ {
+ /* Align every 8 bytes. */
+ *Alignment = 8;
+ }
+
+ if (ReservedHead != gcvNULL)
+ {
+ /* Reserve space for SelectPipe(). */
+ *ReservedHead = 32;
+ }
+
+ if (ReservedTail != gcvNULL)
+ {
+ if (Engine == gcvENGINE_RENDER)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+ else
+ {
+ *ReservedTail = gcdBLT_FENCE_LENGTH;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Alignment=%lu *ReservedHead=%lu *ReservedTail=%lu",
+ gcmOPT_VALUE(Alignment), gcmOPT_VALUE(ReservedHead),
+ gcmOPT_VALUE(ReservedTail));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QuerySystemMemory
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * SystemSize
+** Pointer to a variable that receives the maximum size of the system
+** memory.
+**
+** gctUINT32 * SystemBaseAddress
+** Poinetr to a variable that receives the base address for system
+** memory.
+*/
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (SystemSize != gcvNULL)
+ {
+ /* Maximum system memory can be 2GB. */
+ *SystemSize = 1U << 31;
+ }
+
+ if (SystemBaseAddress != gcvNULL)
+ {
+ /* Set system memory base address. */
+ *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ?
+ 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ?
+ 31:31) + 1))))))) << (0 ? 31:31)));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*SystemSize=%lu *SystemBaseAddress=%lu",
+ gcmOPT_VALUE(SystemSize), gcmOPT_VALUE(SystemBaseAddress));
+ return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_3D
+/*******************************************************************************
+**
+** gckHARDWARE_QueryShaderCaps
+**
+** Query the shader capabilities.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT * VertexUniforms
+** Pointer to a variable receiving the number of uniforms in the vertex
+** shader.
+**
+** gctUINT * FragmentUniforms
+** Pointer to a variable receiving the number of uniforms in the
+** fragment shader.
+**
+** gctBOOL * UnifiedUnforms
+** Pointer to a variable receiving whether the uniformas are unified.
+*/
+gceSTATUS
+gckHARDWARE_QueryShaderCaps(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT * VertexUniforms,
+ OUT gctUINT * FragmentUniforms,
+ OUT gctBOOL * UnifiedUnforms
+ )
+{
+ gctBOOL unifiedConst;
+ gctUINT32 vsConstMax;
+ gctUINT32 psConstMax;
+ gctUINT32 vsConstBase;
+ gctUINT32 psConstBase;
+ gctUINT32 ConstMax;
+ gctBOOL halti5;
+
+ gcmkHEADER_ARG("Hardware=0x%x VertexUniforms=0x%x "
+ "FragmentUniforms=0x%x UnifiedUnforms=0x%x",
+ Hardware, VertexUniforms,
+ FragmentUniforms, UnifiedUnforms);
+
+ halti5 = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI5);
+
+ {if (Hardware->identity.numConstants > 256){ unifiedConst = gcvTRUE;
+if (halti5){ vsConstBase = 0xD000;
+ psConstBase = 0xD800;
+}else{ vsConstBase = 0xC000;
+ psConstBase = 0xC000;
+}if ((Hardware->identity.chipModel == gcv880) && ((Hardware->identity.chipRevision & 0xfff0) == 0x5120)){ vsConstMax = 512;
+ psConstMax = 64;
+ ConstMax = 576;
+}else{ vsConstMax = gcmMIN(512, Hardware->identity.numConstants - 64);
+ psConstMax = gcmMIN(512, Hardware->identity.numConstants - 64);
+ ConstMax = Hardware->identity.numConstants;
+}}else if (Hardware->identity.numConstants == 256){ if (Hardware->identity.chipModel == gcv2000 && (Hardware->identity.chipRevision == 0x5118 || Hardware->identity.chipRevision == 0x5140)) { unifiedConst = gcvFALSE;
+ vsConstBase = 0x1400;
+ psConstBase = 0x1C00;
+ vsConstMax = 256;
+ psConstMax = 64;
+ ConstMax = 320;
+ } else { unifiedConst = gcvFALSE;
+ vsConstBase = 0x1400;
+ psConstBase = 0x1C00;
+ vsConstMax = 256;
+ psConstMax = 256;
+ ConstMax = 512;
+ }}else{ unifiedConst = gcvFALSE;
+ vsConstBase = 0x1400;
+ psConstBase = 0x1C00;
+ vsConstMax = 168;
+ psConstMax = 64;
+ ConstMax = 232;
+}};
+
+
+ if (VertexUniforms != gcvNULL)
+ {
+ /* Return the vs shader const count. */
+ *VertexUniforms = vsConstMax;
+ }
+
+ if (FragmentUniforms != gcvNULL)
+ {
+ /* Return the ps shader const count. */
+ *FragmentUniforms = psConstMax;
+ }
+
+ if (UnifiedUnforms != gcvNULL)
+ {
+ /* Return whether the uniformas are unified. */
+ *UnifiedUnforms = unifiedConst;
+ }
+
+ psConstBase = psConstBase;
+ vsConstBase = vsConstBase;
+ ConstMax = ConstMax;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetMMU
+**
+** Set the page table base address.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the page table.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_SetMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = 0;
+ gctUINT32 idle;
+ gctUINT32 timer = 0, delay = 1;
+ gctPHYS_ADDR_T physical;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Hardware->mmuVersion == 0)
+ {
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Convert the logical address into physical address. */
+ gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, Logical, &physical));
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Setting page table to 0x%08X",
+ address);
+
+ /* Write the AQMemoryFePageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00400,
+ address));
+
+ /* Write the AQMemoryRaPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00410,
+ address));
+
+ /* Write the AQMemoryTxPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00404,
+ address));
+
+
+ /* Write the AQMemoryPePageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00408,
+ address));
+
+ /* Write the AQMemoryPezPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0040C,
+ address));
+ }
+ else if (Hardware->enableMMU == gcvTRUE && Hardware->secureMode != gcvSECURE_IN_TA)
+ {
+ /* Prepared command sequence contains an END,
+ ** so update lastEnd and store executeCount to END command.
+ */
+ gcsHARDWARE_FUNCTION *function = &Hardware->functions[gcvHARDWARE_FUNCTION_MMU];
+ gctUINT32_PTR endLogical = (gctUINT32_PTR)function->endLogical;
+
+ Hardware->lastEnd = function->endAddress;
+
+ *(endLogical + 1) = Hardware->executeCount + 1;
+
+ if (Hardware->secureMode == gcvSECURE_IN_NORMAL)
+ {
+ /* Set up base address of page table array. */
+ gcmkONERROR(gckOS_WriteRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x0038C,
+ (gctUINT32)(Hardware->pagetableArray.address & 0xFFFFFFFF)
+ ));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x00390,
+ (gctUINT32)((Hardware->pagetableArray.address >> 32) & 0xFFFFFFFF)
+ ));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x00394,
+ 1
+ ));
+ }
+
+ /* Execute prepared command sequence. */
+ gcmkONERROR(gckHARDWARE_Execute(
+ Hardware,
+ function->address,
+ function->bytes
+ ));
+
+#if gcdLINK_QUEUE_SIZE
+ {
+ gcuQUEUEDATA data;
+
+ gcmkVERIFY_OK(gckOS_GetProcessID(&data.linkData.pid));
+
+ data.linkData.start = function->address;
+ data.linkData.end = function->address + function->bytes;
+ data.linkData.linkLow = 0;
+ data.linkData.linkHigh = 0;
+
+ gckQUEUE_Enqueue(&Hardware->linkQueue, &data);
+ }
+#endif
+
+ /* Wait until MMU configure finishes. */
+ do
+ {
+ gckOS_Delay(Hardware->os, delay);
+
+ gcmkONERROR(gckOS_ReadRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x00004,
+ &idle));
+
+ timer += delay;
+ delay *= 2;
+
+#if gcdGPU_TIMEOUT
+ if (timer >= Hardware->kernel->timeOut)
+ {
+ gckHARDWARE_DumpGPUState(Hardware);
+ gckCOMMAND_DumpExecutingBuffer(Hardware->kernel->command);
+
+ /* Even if hardware is not reset correctly, let software
+ ** continue to avoid software stuck. Software will timeout again
+ ** and try to recover GPU in next timeout.
+ */
+ gcmkONERROR(gcvSTATUS_DEVICE);
+ }
+#endif
+ }
+ while (!(((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ));
+
+ /* Enable MMU. */
+ if (Hardware->secureMode == gcvSECURE_IN_NORMAL)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x00388,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x0018C,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (gcvTRUE) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)))
+ ));
+ }
+ }
+
+ /* Return the status. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_FlushMMU
+**
+** Flush the page table.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_FlushMMU(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gckCOMMAND command;
+ gctUINT32_PTR buffer;
+ gctUINT32 bufferSize;
+ gctPOINTER pointer = gcvNULL;
+ gctUINT32 flushSize;
+ gctUINT32 count, offset;
+ gctUINT32 address;
+ gctBOOL bltEngine;
+ gctUINT32 semaphore, stall;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Verify the gckCOMMAND object pointer. */
+ command = Hardware->kernel->command;
+
+ /* Flush the memory controller. */
+ if (Hardware->mmuVersion == 0)
+ {
+ gcmkONERROR(gckCOMMAND_Reserve(
+ command, 8, &pointer, &bufferSize
+ ));
+
+ buffer = (gctUINT32_PTR) pointer;
+
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+
+ gcmkONERROR(gckCOMMAND_Execute(command, 8));
+ }
+ else
+ {
+ flushSize = 10 * 4;
+ offset = 2;
+
+ bltEngine = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BLT_ENGINE);
+
+ if (bltEngine)
+ {
+ flushSize += 4 * 4;
+ }
+
+ gcmkONERROR(gckCOMMAND_Reserve(
+ command, flushSize, &pointer, &bufferSize
+ ));
+
+ buffer = (gctUINT32_PTR) pointer;
+
+ count = ((gctUINT)bufferSize - flushSize + 7) >> 3;
+
+ address = command->address + command->offset;
+
+ /* LINK to next slot to flush FE FIFO. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) ((bltEngine ? 6 : 4)) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = address + offset * gcmSIZEOF(gctUINT32);
+
+ /* Flush MMU cache. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = (((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) & ((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:7) - (0 ? 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))));
+
+ if (bltEngine)
+ {
+ /* Blt lock. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x502E) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ /* Arm the PE-FE Semaphore. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ semaphore = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+
+ if (Hardware->stallFEPrefetch)
+ {
+ semaphore |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 29:28) - (0 ? 29:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 29:28) - (0 ?
+ 29:28) + 1))))))) << (0 ? 29:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ?
+ 29:28) - (0 ? 29:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 29:28) - (0 ?
+ 29:28) + 1))))))) << (0 ? 29:28)));
+ }
+
+ if (bltEngine)
+ {
+ semaphore |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x10 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+ else
+ {
+ semaphore |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ *buffer++
+ = semaphore;
+
+ /* STALL FE until PE is done flushing. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ stall = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+
+ if (Hardware->stallFEPrefetch)
+ {
+ stall |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 29:28) - (0 ? 29:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 29:28) - (0 ?
+ 29:28) + 1))))))) << (0 ? 29:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ?
+ 29:28) - (0 ? 29:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 29:28) - (0 ?
+ 29:28) + 1))))))) << (0 ? 29:28)));
+ }
+
+ if (bltEngine)
+ {
+ stall |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x10 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+ else
+ {
+ stall |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ *buffer++
+ = stall;
+
+ if (bltEngine)
+ {
+ /* Blt unlock. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x502E) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ /* LINK to next slot to flush FE FIFO. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (count) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = address + flushSize;
+
+ gcmkONERROR(gckCOMMAND_Execute(command, flushSize));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetMMUStates(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER MtlbAddress,
+ IN gceMMU_MODE Mode,
+ IN gctPOINTER SafeAddress,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gceSTATUS status;
+ gctUINT32 config, address;
+ gctUINT32 extMtlb, extSafeAddrss, configEx = 0;
+ gctPHYS_ADDR_T physical;
+ gctUINT32_PTR buffer;
+ gctBOOL ace;
+ gctUINT32 reserveBytes = 16 + 4 * 4;
+ gcsMMU_TABLE_ARRAY_ENTRY * entry;
+
+ gctBOOL config2D;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Hardware->mmuVersion != 0);
+
+ entry = (gcsMMU_TABLE_ARRAY_ENTRY *) Hardware->pagetableArray.logical;
+
+ ace = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_ACE);
+
+ if (ace)
+ {
+ reserveBytes += 8;
+ }
+
+ config2D = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_3D)
+ && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_2D);
+
+ if (config2D)
+ {
+ reserveBytes +=
+ /* Pipe Select. */
+ 4 * 4
+ /* Configure MMU States. */
+ + 4 * 4
+ /* Semaphore stall */
+ + 4 * 8;
+
+ if (ace)
+ {
+ reserveBytes += 8;
+ }
+ }
+
+ /* Convert logical address into physical address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Hardware->os, MtlbAddress, &physical));
+
+ config = (gctUINT32)(physical & 0xFFFFFFFF);
+ extMtlb = (gctUINT32)(physical >> 32);
+
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Hardware->os, SafeAddress, &physical));
+
+ address = (gctUINT32)(physical & 0xFFFFFFFF);
+ extSafeAddrss = (gctUINT32)(physical >> 32);
+
+ if (address & 0x3F)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ if (ace)
+ {
+ configEx = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (extSafeAddrss) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (extMtlb) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)));
+ }
+
+ switch (Mode)
+ {
+ case gcvMMU_MODE_1K:
+ if (config & 0x3FF)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ break;
+
+ case gcvMMU_MODE_4K:
+ if (config & 0xFFF)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (Logical != gcvNULL)
+ {
+ buffer = Logical;
+
+ if (Hardware->secureMode == gcvSECURE_IN_NORMAL)
+ {
+ /* Setup page table array entry. */
+ entry->low = config;
+ entry->high = (gctUINT32)(physical >> 32);
+
+ /* Setup command buffer to load index 0 of page table array. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x006B) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = (((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) &((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ?
+ 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ?
+ 16:16))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))));
+ }
+ else
+ {
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++ = config;
+ }
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++ = address;
+
+ if (ace)
+ {
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0068) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = configEx;
+ }
+
+ do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);
+;
+
+
+ if (config2D)
+ {
+ /* LoadState(AQPipeSelect, 1), pipe. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++ = 0x1;
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++ = config;
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++ = address;
+
+ if (ace)
+ {
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0068) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = configEx;
+ }
+
+ do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);
+;
+
+
+ /* LoadState(AQPipeSelect, 1), pipe. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++ = 0x0;
+
+ do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);
+;
+
+ }
+
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ *Bytes = reserveBytes;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER_NO();
+ return status;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+/*******************************************************************************
+**
+** gckHARDWARE_ConfigMMU
+**
+** Append a MMU Configuration command sequence at the specified location in the command
+** queue. That command sequence consists of mmu configuration, LINK and WAIT/LINK.
+** LINK is fetched and paresed with new mmu configuration.
+**
+** If MMU Configuration is not changed between commit, change last WAIT/LINK to
+** link to ENTRY.
+**
+** -+-----------+-----------+-----------------------------------------
+** | WAIT/LINK | WAIT/LINK |
+** -+-----------+-----------+-----------------------------------------
+** | /|\
+** \|/ |
+** +--------------------+
+** | ENTRY | ... | LINK |
+** +--------------------+
+**
+** If MMU Configuration is changed between commit, change last WAIT/LINK to
+** link to MMU CONFIGURATION command sequence, and there are an EVNET and
+** an END at the end of this command sequence, when interrupt handler
+** receives this event, it will start FE at ENTRY to continue the command
+** buffer execution.
+**
+** -+-----------+-------------------+---------+---------+-----------+--
+** | WAIT/LINK | MMU CONFIGURATION | EVENT | END | WAIT/LINK |
+** -+-----------+-------------------+---------+---------+-----------+--
+** | /|\ /|\
+** +-------------+ |
+** +--------------------+
+** | ENTRY | ... | LINK |
+** +--------------------+
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** command sequence at or gcvNULL just to query the size of the
+** command sequence.
+**
+** gctPOINTER MtlbLogical
+** Pointer to the current Master TLB.
+**
+** gctUINT32 Offset
+** Offset into command buffer required for alignment.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the command
+** sequence. If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** by the command sequence. If 'Bytes' is gcvNULL, nothing will
+** be returned.
+**
+** gctUINT32 * WaitLinkOffset
+** Pointer to a variable that will receive the offset of the WAIT/LINK command
+** from the specified logcial pointer.
+** If 'WaitLinkOffset' is gcvNULL nothing will be returned.
+**
+** gctSIZE_T * WaitLinkBytes
+** Pointer to a variable that will receive the number of bytes used by
+** the WAIT command.
+** If 'WaitLinkBytes' is gcvNULL nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_ConfigMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctPOINTER MtlbLogical,
+ IN gctUINT32 Offset,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctSIZE_T * WaitLinkOffset,
+ OUT gctSIZE_T * WaitLinkBytes
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T bytes, bytesAligned;
+ gctUINT32 config;
+ gctUINT32_PTR buffer = (gctUINT32_PTR) Logical;
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+ gctUINT32 event;
+ gctSIZE_T stCmds; /* semaphore stall cmd size */;
+
+ gcmkHEADER_ARG("Hardware=0x%08X Logical=0x%08x MtlbLogical=0x%08X",
+ Hardware, Logical, MtlbLogical);
+
+ stCmds = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX) ? 0 : 4;
+
+ bytes
+ /* Semaphore stall states. */
+ = stCmds * 4
+ /* Flush cache states. */
+ + 20 * 4
+ /* MMU configuration states. */
+ + 6 * 4
+ /* EVENT. */
+ + 2 * 4
+ /* END. */
+ + 2 * 4
+ /* WAIT/LINK. */
+ + 4 * 4;
+
+ /* Compute number of bytes required. */
+ bytesAligned = gcmALIGN(Offset + bytes, 8) - Offset;
+
+ if (buffer != gcvNULL)
+ {
+ if (MtlbLogical == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Get physical address of this command buffer segment. */
+ gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, buffer, &physical));
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ /* Get physical address of Master TLB. */
+ gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, MtlbLogical, &physical));
+
+ gcmkSAFECASTPHYSADDRT(config, physical);
+
+ config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+
+ if (stCmds)
+ {
+ /* Arm the PE-FE Semaphore. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* STALL FE until PE is done flushing. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ /* Flush cache. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ AQ_FLUSH_VSHL1_CACHE) - (0 ? AQ_FLUSH_VSHL1_CACHE) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
+ AQ_FLUSH_VSHL1_CACHE) - (0 ? AQ_FLUSH_VSHL1_CACHE) + 1))))))) << (0 ? AQ_FLUSH_VSHL1_CACHE))) | (((gctUINT32) (AQ_FLUSH_VSHL1_CACHE_ENABLE & ((gctUINT32) ((((1 ?
+ AQ_FLUSH_VSHL1_CACHE) - (0 ? AQ_FLUSH_VSHL1_CACHE) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
+ AQ_FLUSH_VSHL1_CACHE) - (0 ? AQ_FLUSH_VSHL1_CACHE) + 1))))))) << (0 ? AQ_FLUSH_VSHL1_CACHE)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ AQ_FLUSH_PSHL1_CACHE) - (0 ? AQ_FLUSH_PSHL1_CACHE) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
+ AQ_FLUSH_PSHL1_CACHE) - (0 ? AQ_FLUSH_PSHL1_CACHE) + 1))))))) << (0 ? AQ_FLUSH_PSHL1_CACHE))) | (((gctUINT32) (AQ_FLUSH_PSHL1_CACHE_ENABLE & ((gctUINT32) ((((1 ?
+ AQ_FLUSH_PSHL1_CACHE) - (0 ? AQ_FLUSH_PSHL1_CACHE) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
+ AQ_FLUSH_PSHL1_CACHE) - (0 ? AQ_FLUSH_PSHL1_CACHE) + 1))))))) << (0 ? AQ_FLUSH_PSHL1_CACHE)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+
+ /* Flush VTS in separate command */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+
+ /* Flush tile status cache. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ /* Arm the PE-FE Semaphore. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* STALL FE until PE is done flushing. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* LINK to next slot to flush FE FIFO. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = address + (stCmds + 12) * gcmSIZEOF(gctUINT32);
+
+ /* Configure MMU. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = (((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) & ((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:7) - (0 ? 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))));
+
+ /* Arm the PE-FE Semaphore. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* STALL FE until PE is done flushing. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* LINK to next slot to flush FE FIFO. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = physical + (stCmds + 20) * 4;
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = config;
+
+ /* Arm the PE-FE Semaphore. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* STALL FE until PE is done flushing. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* Event 29. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ event = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+ event = ((((gctUINT32) (event)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) ((gctUINT32) (29) & ((gctUINT32) ((((1 ? 4:0) - (0 ?
+ 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0)));
+
+ *buffer++
+ = event;
+
+ /* Append END. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ *Bytes = bytesAligned;
+ }
+
+ if (WaitLinkOffset != gcvNULL)
+ {
+ *WaitLinkOffset = bytes - 4 * 4;
+ }
+
+ if (WaitLinkBytes != gcvNULL)
+ {
+ *WaitLinkBytes = 4 * 4;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckHARDWARE_BuildVirtualAddress
+**
+** Build a virtual address.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctUINT32 Index
+** Index into page table.
+**
+** gctUINT32 Offset
+** Offset into page.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable receiving te hardware address.
+*/
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Index=%u Offset=%u", Hardware, Index, Offset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Build virtual address. */
+ *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ?
+ 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ?
+ 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 30:0) - (0 ? 30:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ?
+ 30:0))) | (((gctUINT32) ((gctUINT32) (Offset | (Index << 12)) & ((gctUINT32) ((((1 ?
+ 30:0) - (0 ? 30:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ?
+ 30:0)));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_GetIdle(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Wait,
+ OUT gctUINT32 * Data
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle = 0;
+ gctINT retry, poll, pollCount;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Hardware=0x%x Wait=%d", Hardware, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+
+ /* If we have to wait, try 100 polls per millisecond. */
+ pollCount = Wait ? 100 : 1;
+
+ /* At most, try for 1 second. */
+ for (retry = 0; retry < 1000; ++retry)
+ {
+ /* If we have to wait, try 100 polls per millisecond. */
+ for (poll = pollCount; poll > 0; --poll)
+ {
+ /* Read register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
+
+ /* Read the current FE address. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00664,
+ &address));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00664,
+ &address));
+
+ /* See if we have to wait for FE idle. */
+ if (_IsGPUIdle(idle)
+ && (address == Hardware->lastEnd + 8)
+ )
+ {
+ /* FE is idle. */
+ break;
+ }
+ }
+
+ /* Check if we need to wait for FE and FE is busy. */
+ if (Wait && !_IsGPUIdle(idle))
+ {
+ /* Wait a little. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "%s: Waiting for idle: 0x%08X",
+ __FUNCTION__, idle);
+
+ gcmkVERIFY_OK(gckOS_Delay(Hardware->os, 1));
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* Return idle to caller. */
+ *Data = idle;
+
+#if defined(EMULATOR)
+ /* Wait a little while until CModel FE gets END.
+ * END is supposed to be appended by caller.
+ */
+ gckOS_Delay(Hardware->os, 100);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+ IN gckHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT32 pipe;
+ gctUINT32 flush = 0;
+ gctUINT32 flushVST = 0;
+ gctBOOL flushTileStatus;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+ gctBOOL halti5;
+ gctBOOL flushICache;
+ gctBOOL flushTXDescCache;
+ gctBOOL flushTFB;
+ gctBOOL hwTFB;
+
+ gcmkHEADER_ARG("Hardware=0x%x Flush=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Flush, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get current pipe. */
+ pipe = Hardware->kernel->command->pipeSelect;
+
+ halti5 = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI5);
+
+ hwTFB = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HW_TFB);
+
+ /* Flush tile status cache. */
+ flushTileStatus = Flush & gcvFLUSH_TILE_STATUS;
+
+ /* Flush Icache for halti5 hardware as we dont do it when program or context switches*/
+ flushICache = (Flush & gcvFLUSH_ICACHE) && halti5;
+
+ /* Flush texture descriptor cache */
+ flushTXDescCache = Flush & gcvFLUSH_TXDESC;
+
+ /* Flush USC cache for TFB client */
+ flushTFB = (Flush & gcvFLUSH_TFBHEADER) && hwTFB;
+
+ /* Flush TFB for vertex buffer */
+ if (hwTFB && (Flush & gcvFLUSH_VERTEX))
+ {
+ flushTFB = gcvTRUE;
+ }
+
+ /* Flush 3D color cache. */
+ if ((Flush & gcvFLUSH_COLOR) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
+ }
+
+ /* Flush 3D depth cache. */
+ if ((Flush & gcvFLUSH_DEPTH) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ /* Flush 3D texture cache. */
+ if ((Flush & gcvFLUSH_TEXTURE) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
+ flushVST = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+ }
+
+ /* Flush 2D cache. */
+ if ((Flush & gcvFLUSH_2D) && (pipe == 0x1))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
+ }
+
+ /* Flush L2 cache. */
+ if ((Flush & gcvFLUSH_L2) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+ }
+
+ /* Vertex buffer and texture could be touched by SHL1 for SSBO and image load/store */
+ if ((Flush & (gcvFLUSH_VERTEX | gcvFLUSH_TEXTURE)) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 10:10) - (0 ? 10:10) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 10:10) - (0 ?
+ 10:10) + 1))))))) << (0 ? 10:10))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 10:10) - (0 ? 10:10) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 10:10) - (0 ?
+ 10:10) + 1))))))) << (0 ? 10:10)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11)));
+ }
+
+ /* See if there is a valid flush. */
+ if ((flush == 0) &&
+ (flushTileStatus == gcvFALSE) &&
+ (flushICache == gcvFALSE) &&
+ (flushTXDescCache == gcvFALSE) &&
+ (flushTFB == gcvFALSE))
+ {
+ if (Bytes != gcvNULL)
+ {
+ /* No bytes required. */
+ *Bytes = 0;
+ }
+ }
+ else
+ {
+ gctUINT32 reserveBytes = 0;
+ gctBOOL txCacheFix = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX)
+ ? gcvTRUE : gcvFALSE;
+
+ /* Determine reserve bytes. */
+ if (!txCacheFix || flushICache || flushTXDescCache)
+ {
+ /* Semaphore/Stall */
+ reserveBytes += 4 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flush)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flushVST)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flushTileStatus)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flushICache)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flushTXDescCache)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ if (flushTFB)
+ {
+ reserveBytes += 2 * gcmSIZEOF(gctUINT32);
+ }
+
+ /* Semaphore/Stall */
+ reserveBytes += 4 * gcmSIZEOF(gctUINT32);
+
+ /* Copy to command queue. */
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < reserveBytes)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ if (!txCacheFix || flushICache || flushTXDescCache)
+ {
+ /* Semaphore. */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* Stall. */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ if (flush)
+ {
+ /* Append LOAD_STATE to AQFlush. */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++ = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: FLUSH 0x%x", logical - 1, flush);
+ }
+
+ if (flushVST)
+ {
+ /* Append LOAD_STATE to AQFlush. */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++ = flushVST;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: FLUSH 0x%x", logical - 1, flush);
+ }
+
+ if (flushTileStatus)
+ {
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH TILE STATUS 0x%x", logical - 1, logical[-1]);
+ }
+
+ if (flushICache)
+ {
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x022C) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ?
+ 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ?
+ 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ?
+ 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH Icache 0x%x", logical - 1, logical[-1]);
+
+ }
+
+ if (flushTXDescCache)
+ {
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x5311) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH Icache 0x%x", logical - 1, logical[-1]);
+
+ }
+
+ if (flushTFB)
+ {
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x7003) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++
+ = 0x12345678;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH TFB cache 0x%x", logical - 1, logical[-1]);
+
+ }
+
+ /* Semaphore. */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* Stall. */
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)));
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* bytes required. */
+ *Bytes = reserveBytes;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetFastClear(
+ IN gckHARDWARE Hardware,
+ IN gctINT Enable,
+ IN gctINT Compression
+ )
+{
+#if gcdENABLE_3D
+ gctUINT32 debug;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Enable=%d Compression=%d",
+ Hardware, Enable, Compression);
+
+ /* Only process if fast clear is available. */
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_FAST_CLEAR))
+ {
+ if (Enable == -1)
+ {
+ /* Determine automatic value for fast clear. */
+ Enable = ((Hardware->identity.chipModel != gcv500)
+ || (Hardware->identity.chipRevision >= 3)
+ ) ? 1 : 0;
+ }
+
+ if (Compression == -1)
+ {
+ /* Determine automatic value for compression. */
+ Compression = Enable & gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_ZCOMPRESSION);
+ }
+
+ /* Read AQMemoryDebug register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00414, &debug));
+
+ /* Set fast clear bypass. */
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
+ 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ?
+ 20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
+ 20:20) + 1))))))) << (0 ? 20:20)));
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BUG_FIXES7) ||
+ (Hardware->identity.chipModel >= gcv4000))
+ {
+ /* Set compression bypass. */
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 21:21) - (0 ? 21:21) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 21:21) - (0 ?
+ 21:21) + 1))))))) << (0 ? 21:21))) | (((gctUINT32) ((gctUINT32) (Compression == 0) & ((gctUINT32) ((((1 ?
+ 21:21) - (0 ? 21:21) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 21:21) - (0 ?
+ 21:21) + 1))))))) << (0 ? 21:21)));
+ }
+
+ /* Write back AQMemoryDebug register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00414,
+ debug));
+
+ /* Store fast clear and comprersison flags. */
+ Hardware->allowFastClear = Enable;
+ Hardware->allowCompression = Compression;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "FastClear=%d Compression=%d", Enable, Compression);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#else
+ return gcvSTATUS_OK;
+#endif
+}
+
+typedef enum
+{
+ gcvPOWER_FLAG_INITIALIZE = 1 << 0,
+ gcvPOWER_FLAG_STALL = 1 << 1,
+ gcvPOWER_FLAG_STOP = 1 << 2,
+ gcvPOWER_FLAG_START = 1 << 3,
+ gcvPOWER_FLAG_RELEASE = 1 << 4,
+ gcvPOWER_FLAG_DELAY = 1 << 5,
+ gcvPOWER_FLAG_SAVE = 1 << 6,
+ gcvPOWER_FLAG_ACQUIRE = 1 << 7,
+ gcvPOWER_FLAG_POWER_OFF = 1 << 8,
+ gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
+ gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
+}
+gcePOWER_FLAGS;
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+static gctCONST_STRING
+_PowerEnum(gceCHIPPOWERSTATE State)
+{
+ const gctCONST_STRING states[] =
+ {
+ gcmSTRING(gcvPOWER_ON),
+ gcmSTRING(gcvPOWER_OFF),
+ gcmSTRING(gcvPOWER_IDLE),
+ gcmSTRING(gcvPOWER_SUSPEND),
+ gcmSTRING(gcvPOWER_SUSPEND_ATPOWERON),
+ gcmSTRING(gcvPOWER_OFF_ATPOWERON),
+ gcmSTRING(gcvPOWER_IDLE_BROADCAST),
+ gcmSTRING(gcvPOWER_SUSPEND_BROADCAST),
+ gcmSTRING(gcvPOWER_OFF_BROADCAST),
+ gcmSTRING(gcvPOWER_OFF_RECOVERY),
+ gcmSTRING(gcvPOWER_OFF_TIMEOUT),
+ gcmSTRING(gcvPOWER_ON_AUTO)
+ };
+
+ if ((State >= gcvPOWER_ON) && (State <= gcvPOWER_ON_AUTO))
+ {
+ return states[State - gcvPOWER_ON];
+ }
+
+ return "unknown";
+}
+#endif
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetPowerManagementState
+**
+** Set GPU to a specified power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE State
+** Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+ IN gckHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ )
+{
+ gceSTATUS status;
+ gckCOMMAND command = gcvNULL;
+ gckOS os;
+ gctUINT flag, clock;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL mutexAcquired = gcvFALSE;
+ gctBOOL stall = gcvTRUE;
+ gctBOOL broadcast = gcvFALSE;
+#if gcdPOWEROFF_TIMEOUT
+ gctBOOL timeout = gcvFALSE;
+ gctBOOL isAfter = gcvFALSE;
+ gctUINT32 currentTime;
+#endif
+ gctUINT32 process, thread;
+ gctBOOL commandStarted = gcvFALSE;
+ gctBOOL isrStarted = gcvFALSE;
+
+#if gcdENABLE_PROFILING
+ gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
+ initTime, offTime, startTime, totalTime;
+#endif
+ gctBOOL global = gcvFALSE;
+ gctBOOL globalAcquired = gcvFALSE;
+
+ /* State transition flags. */
+ static const gctUINT flags[4][4] =
+ {
+ /* gcvPOWER_ON */
+ { /* ON */ 0,
+ /* OFF */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL,
+ /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_OFF */
+ { /* ON */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY,
+ /* OFF */ 0,
+ /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY,
+ /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_IDLE */
+ { /* ON */ gcvPOWER_FLAG_RELEASE,
+ /* OFF */ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ 0,
+ /* SUSPEND */ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_SUSPEND */
+ { /* ON */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_CLOCK_ON,
+ /* OFF */ gcvPOWER_FLAG_SAVE |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_CLOCK_ON,
+ /* SUSPEND */ 0,
+ },
+ };
+
+ /* Clocks. */
+ static const gctUINT clocks[4] =
+ {
+ /* gcvPOWER_ON */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) | (((gctUINT32) ((gctUINT32) (64) & ((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))),
+
+ /* gcvPOWER_OFF */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))),
+
+ /* gcvPOWER_IDLE */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))),
+
+ /* gcvPOWER_SUSPEND */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))),
+ };
+
+ gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Switching to power state %d(%s)",
+ State, _PowerEnum(State));
+#endif
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get the gckOS object pointer. */
+ os = Hardware->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Get the gckCOMMAND object pointer. */
+ gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
+ command = Hardware->kernel->command;
+ gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+ /* Start profiler. */
+ gcmkPROFILE_INIT(freq, time);
+
+ /* Convert the broadcast power state. */
+ switch (State)
+ {
+ case gcvPOWER_SUSPEND_ATPOWERON:
+ /* Convert to SUSPEND and don't wait for STALL. */
+ State = gcvPOWER_SUSPEND;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_OFF_ATPOWERON:
+ /* Convert to OFF and don't wait for STALL. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_IDLE_BROADCAST:
+ /* Convert to IDLE and note we are inside broadcast. */
+ State = gcvPOWER_IDLE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_SUSPEND_BROADCAST:
+ /* Convert to SUSPEND and note we are inside broadcast. */
+ State = gcvPOWER_SUSPEND;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_BROADCAST:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_RECOVERY:
+ /* Convert to OFF and note we are inside recovery. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_ON_AUTO:
+ /* Convert to ON and note we are inside recovery. */
+ State = gcvPOWER_ON;
+ break;
+
+ case gcvPOWER_ON:
+ case gcvPOWER_IDLE:
+ case gcvPOWER_SUSPEND:
+ case gcvPOWER_OFF:
+ /* Mark as global power management. */
+ global = gcvTRUE;
+ break;
+
+#if gcdPOWEROFF_TIMEOUT
+ case gcvPOWER_OFF_TIMEOUT:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ /* Check time out */
+ timeout = gcvTRUE;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ if (Hardware->powerManagement == gcvFALSE
+ && State != gcvPOWER_ON
+ )
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Get current process and thread IDs. */
+ gcmkONERROR(gckOS_GetProcessID(&process));
+ gcmkONERROR(gckOS_GetThreadID(&thread));
+
+ if (broadcast)
+ {
+ /* Try to acquire the power mutex. */
+ status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Check if we already own this mutex. */
+ if ((Hardware->powerProcess == process)
+ && (Hardware->powerThread == thread)
+ )
+ {
+ /* Bail out on recursive power management. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ else if (State != gcvPOWER_ON)
+ {
+ /* Called from IST,
+ ** so waiting here will cause deadlock,
+ ** if lock holder call gckCOMMAND_Stall() */
+ status = gcvSTATUS_OK;
+ goto OnError;
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os,
+ Hardware->powerMutex,
+ gcvINFINITE));
+ }
+ }
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+ }
+
+ /* Get time until mtuex acquired. */
+ gcmkPROFILE_QUERY(time, mutexTime);
+
+ Hardware->powerProcess = process;
+ Hardware->powerThread = thread;
+ mutexAcquired = gcvTRUE;
+
+ /* Grab control flags and clock. */
+ flag = flags[Hardware->chipPowerState][State];
+ clock = clocks[State];
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ if (State == gcvPOWER_ON)
+ {
+ clock = ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 8:2) - (0 ? 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) | (((gctUINT32) ((gctUINT32) (Hardware->powerOnFscaleVal) & ((gctUINT32) ((((1 ?
+ 8:2) - (0 ? 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2)));
+ }
+#endif
+
+ if (State == gcvPOWER_SUSPEND && Hardware->chipPowerState == gcvPOWER_OFF && broadcast)
+ {
+#if gcdPOWER_SUSPEND_WHEN_IDLE
+ /* Do nothing */
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#else
+ /* Clock should be on when switch power from off to suspend */
+ clock = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 8:2) - (0 ? 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ?
+ 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) ;
+#endif
+ }
+
+#if gcdPOWEROFF_TIMEOUT
+ if (timeout)
+ {
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ gcmkONERROR(
+ gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
+
+ /* powerOffTime is pushed forward, give up.*/
+ if (isAfter
+ /* Expect a transition start from IDLE or SUSPEND. */
+ || (Hardware->chipPowerState == gcvPOWER_ON)
+ || (Hardware->chipPowerState == gcvPOWER_OFF)
+ )
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Power Off GPU[%d] at %u [supposed to be at %u]",
+ Hardware->core, currentTime, Hardware->powerOffTime);
+ }
+#endif
+
+ if (flag == 0)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* If this is an internal power management, we have to check if we can grab
+ ** the global power semaphore. If we cannot, we have to wait until the
+ ** external world changes power management. */
+ if (!global)
+ {
+ /* Try to acquire the global semaphore. */
+ status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
+ {
+ /* Called from thread routine which should NEVER sleep.*/
+ status = gcvSTATUS_OK;
+ goto OnError;
+ }
+
+ /* Release the power mutex. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Releasing the power mutex.");
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+ mutexAcquired = gcvFALSE;
+
+ /* Wait for the semaphore. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Waiting for global semaphore.");
+ gcmkONERROR(gckOS_AcquireSemaphore(os, Hardware->globalSemaphore));
+ globalAcquired = gcvTRUE;
+
+ /* Acquire the power mutex. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Reacquiring the power mutex.");
+ gcmkONERROR(gckOS_AcquireMutex(os,
+ Hardware->powerMutex,
+ gcvINFINITE));
+ mutexAcquired = gcvTRUE;
+
+ /* chipPowerState may be changed by external world during the time
+ ** we give up powerMutex, so updating flag now is necessary. */
+ flag = flags[Hardware->chipPowerState][State];
+
+ if (flag == 0)
+ {
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
+ globalAcquired = gcvFALSE;
+
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+ mutexAcquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ /* Error. */
+ gcmkONERROR(status);
+ }
+
+ /* Release the global semaphore again. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
+ globalAcquired = gcvFALSE;
+ }
+ else
+ {
+ if (State == gcvPOWER_OFF || State == gcvPOWER_SUSPEND || State == gcvPOWER_IDLE)
+ {
+ /* Acquire the global semaphore if it has not been acquired. */
+ status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
+ if (status == gcvSTATUS_OK)
+ {
+ globalAcquired = gcvTRUE;
+ }
+ else if (status != gcvSTATUS_TIMEOUT)
+ {
+ /* Other errors. */
+ gcmkONERROR(status);
+ }
+ /* Ignore gcvSTATUS_TIMEOUT and leave globalAcquired as gcvFALSE.
+ ** gcvSTATUS_TIMEOUT means global semaphore has already
+ ** been acquired before this operation, so even if we fail,
+ ** we should not release it in our error handling. It should be
+ ** released by the next successful global gcvPOWER_ON. */
+ }
+
+ /* Global power management can't be aborted, so sync with
+ ** proceeding last commit. */
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+ acquired = gcvTRUE;
+
+ /* avoid acquiring again. */
+ flag &= ~gcvPOWER_FLAG_ACQUIRE;
+ }
+ }
+
+ if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
+ {
+ /* Turn on the power. */
+ gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
+
+ /* Mark clock and power as enabled. */
+ Hardware->clockState = gcvTRUE;
+ Hardware->powerState = gcvTRUE;
+
+ for (;;)
+ {
+ /* Check if GPU is present and awake. */
+ status = _IsGPUPresent(Hardware);
+
+ /* Check if the GPU is not responding. */
+ if (status == gcvSTATUS_GPU_NOT_RESPONDING)
+ {
+ /* Turn off the power and clock. */
+ gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvFALSE, gcvFALSE));
+
+ Hardware->clockState = gcvFALSE;
+ Hardware->powerState = gcvFALSE;
+
+ /* Wait a little. */
+ gckOS_Delay(os, 1);
+
+ /* Turn on the power and clock. */
+ gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
+
+ Hardware->clockState = gcvTRUE;
+ Hardware->powerState = gcvTRUE;
+
+ /* We need to initialize the hardware and start the command
+ * processor. */
+ flag |= gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_START;
+ }
+ else
+ {
+ /* Test for error. */
+ gcmkONERROR(status);
+
+ /* Break out of loop. */
+ break;
+ }
+ }
+ }
+
+ /* Get time until powered on. */
+ gcmkPROFILE_QUERY(time, onTime);
+
+ if ((flag & gcvPOWER_FLAG_STALL) && stall)
+ {
+ gctBOOL idle;
+ gctINT32 atomValue;
+
+ /* For global operation, all pending commits have already been
+ ** blocked by globalSemaphore or powerSemaphore.*/
+ if (!global)
+ {
+ /* Check commit atom. */
+ gcmkONERROR(gckOS_AtomGet(os, command->atomCommit, &atomValue));
+
+ if (atomValue > 0)
+ {
+ /* Commits are pending - abort power management. */
+ status = broadcast ? gcvSTATUS_CHIP_NOT_READY
+ : gcvSTATUS_MORE_DATA;
+ goto OnError;
+ }
+ }
+
+ if (broadcast)
+ {
+ /* Check for idle. */
+ gcmkONERROR(gckHARDWARE_QueryIdle(Hardware, &idle));
+
+ if (!idle)
+ {
+ status = gcvSTATUS_CHIP_NOT_READY;
+ goto OnError;
+ }
+ }
+
+ else
+ {
+ /* Wait to finish all commands. */
+ gcmkONERROR(gckCOMMAND_Stall(command, gcvTRUE));
+ }
+ }
+
+ /* Get time until stalled. */
+ gcmkPROFILE_QUERY(time, stallTime);
+
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+ acquired = gcvTRUE;
+ }
+
+ if (flag & gcvPOWER_FLAG_STOP)
+ {
+ /* Stop the command parser. */
+ gcmkONERROR(gckCOMMAND_Stop(command));
+
+ /* Stop the Isr. */
+ if (Hardware->stopIsr)
+ {
+ gcmkONERROR(Hardware->stopIsr(Hardware->isrContext));
+ }
+ }
+
+ /* Flush Cache before Power Off. */
+ if (flag & gcvPOWER_FLAG_POWER_OFF)
+ {
+ if (Hardware->clockState == gcvFALSE)
+ {
+ /* Turn off the GPU power. */
+ gcmkONERROR(
+ gckOS_SetGPUPower(os,
+ Hardware->core,
+ gcvTRUE,
+ gcvTRUE));
+
+ Hardware->clockState = gcvTRUE;
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_DYNAMIC_FREQUENCY_SCALING) != gcvTRUE)
+ {
+ /* Write the clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os,
+ Hardware->core,
+ 0x00000,
+ clocks[0]));
+
+ /* Done loading the frequency scaler. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clocks[0])) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9)))));
+ }
+ }
+
+ gcmkONERROR(gckCOMMAND_Start(command));
+
+ gcmkONERROR(_FlushCache(Hardware, command));
+
+ gckOS_Delay(gcvNULL, 1);
+
+ /* Stop the command parser. */
+ gcmkONERROR(gckCOMMAND_Stop(command));
+
+ flag |= gcvPOWER_FLAG_CLOCK_OFF;
+ }
+
+ /* Get time until stopped. */
+ gcmkPROFILE_QUERY(time, stopTime);
+
+ /* Only process this when hardware is enabled. */
+ if (Hardware->clockState && Hardware->powerState
+ /* Don't touch clock control if dynamic frequency scaling is available. */
+ && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_DYNAMIC_FREQUENCY_SCALING) != gcvTRUE
+ )
+ {
+ if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+ {
+ if (Hardware->identity.chipModel == gcv4000
+ && ((Hardware->identity.chipRevision == 0x5208) || (Hardware->identity.chipRevision == 0x5222)))
+ {
+ clock &= ~2U;
+ }
+ }
+
+ /* Write the clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Done loading the frequency scaler. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9)))));
+ }
+
+ if (flag & gcvPOWER_FLAG_DELAY)
+ {
+ /* Wait for the specified amount of time to settle coming back from
+ ** power-off or suspend state. */
+ gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
+ }
+
+ /* Get time until delayed. */
+ gcmkPROFILE_QUERY(time, delayTime);
+
+ if (flag & gcvPOWER_FLAG_INITIALIZE)
+ {
+ /* Initialize hardware. */
+ gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
+
+ gcmkONERROR(gckHARDWARE_SetFastClear(Hardware,
+ Hardware->allowFastClear,
+ Hardware->allowCompression));
+
+ /* Force the command queue to reload the next context. */
+ command->currContext = gcvNULL;
+
+ /* Trigger a possible dummy draw. */
+ command->dummyDraw = gcvTRUE;
+ }
+
+ /* Get time until initialized. */
+ gcmkPROFILE_QUERY(time, initTime);
+
+ if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+ {
+ /* Turn off the GPU power. */
+ gcmkONERROR(
+ gckOS_SetGPUPower(os,
+ Hardware->core,
+ (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE,
+ (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+ : gcvTRUE));
+
+ /* Save current hardware power and clock states. */
+ Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE;
+ Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+ : gcvTRUE;
+ }
+
+ /* Get time until off. */
+ gcmkPROFILE_QUERY(time, offTime);
+
+ if (flag & gcvPOWER_FLAG_START)
+ {
+ /* Start the command processor. */
+ gcmkONERROR(gckCOMMAND_Start(command));
+ commandStarted = gcvTRUE;
+
+ if (Hardware->startIsr)
+ {
+ /* Start the Isr. */
+ gcmkONERROR(Hardware->startIsr(Hardware->isrContext));
+ isrStarted = gcvTRUE;
+ }
+ }
+
+ /* Get time until started. */
+ gcmkPROFILE_QUERY(time, startTime);
+
+ if (flag & gcvPOWER_FLAG_RELEASE)
+ {
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
+ acquired = gcvFALSE;
+
+ if (global)
+ {
+ /* Verify global semaphore has been acquired already before
+ ** we release it.
+ ** If it was acquired, gckOS_TryAcquireSemaphore will return
+ ** gcvSTATUS_TIMEOUT and we release it. Otherwise, global
+ ** semaphore will be acquried now, but it still is released
+ ** immediately. */
+ status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
+ if (status != gcvSTATUS_TIMEOUT)
+ {
+ gcmkONERROR(status);
+ }
+
+ /* Release the global semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
+ globalAcquired = gcvFALSE;
+ }
+ }
+
+ gckSTATETIMER_Accumulate(&Hardware->powerStateTimer, Hardware->chipPowerState);
+
+ /* Save the new power state. */
+ Hardware->chipPowerState = State;
+
+#if gcdDVFS
+ if (State == gcvPOWER_ON && Hardware->kernel->dvfs)
+ {
+ gckDVFS_Start(Hardware->kernel->dvfs);
+ }
+#endif
+
+#if gcdPOWEROFF_TIMEOUT
+ /* Reset power off time */
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
+
+ if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
+ {
+ /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
+ gcmkVERIFY_OK(gckOS_StartTimer(os,
+ Hardware->powerOffTimer,
+ Hardware->powerOffTimeout));
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
+
+ /* Cancel running timer when GPU enters ON or OFF. */
+ gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
+ }
+#endif
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* Get total time. */
+ gcmkPROFILE_QUERY(time, totalTime);
+#if gcdENABLE_PROFILING
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
+ freq, mutexTime, onTime, stallTime, stopTime);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ " delay:%llu init:%llu off:%llu start:%llu total:%llu",
+ delayTime, initTime, offTime, startTime, totalTime);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (commandStarted)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Stop(command));
+ }
+
+ if (isrStarted)
+ {
+ gcmkVERIFY_OK(Hardware->stopIsr(Hardware->isrContext));
+ }
+
+ if (acquired)
+ {
+ /* Release semaphore. */
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
+ command->powerSemaphore));
+ }
+
+ if (globalAcquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
+ Hardware->globalSemaphore));
+ }
+
+ if (mutexAcquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryPowerManagementState
+**
+** Get GPU power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE* State
+** Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(State != gcvNULL);
+
+ /* Return the statue. */
+ *State = Hardware->chipPowerState;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*State=%d", *State);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetPowerManagement
+**
+** Configure GPU power management function.
+** Only used in driver initialization stage.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL PowerManagement
+** Power Mangement State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetPowerManagement(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL PowerManagement
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if(_IsHardwareMatch(Hardware, gcv7000, 0x6008))
+ {
+ PowerManagement = gcvFALSE;
+ }
+
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE));
+
+ Hardware->powerManagement = PowerManagement;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetGpuProfiler
+**
+** Configure GPU profiler function.
+** Only used in driver initialization stage.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL GpuProfiler
+** GOU Profiler State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetGpuProfiler(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL GpuProfiler
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (GpuProfiler == gcvTRUE)
+ {
+ gctUINT32 data = 0;
+
+ /* Need to disable clock gating when doing profiling. */
+ gcmkVERIFY_OK(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress +
+ 0x00100,
+ &data));
+
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)));
+
+
+ gcmkVERIFY_OK(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00100,
+ data));
+ }
+
+ Hardware->gpuProfiler = GpuProfiler;
+
+ if (GpuProfiler == gcvTRUE)
+ {
+ Hardware->waitCount = 200 * 100;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+gceSTATUS
+gckHARDWARE_SetFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 FscaleValue
+ )
+{
+ gceSTATUS status;
+ gctUINT32 clock;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x FscaleValue=%d", Hardware, FscaleValue);
+
+ gcmkVERIFY_ARGUMENT(FscaleValue > 0 && FscaleValue <= 64);
+
+ gcmkONERROR(
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ Hardware->powerOnFscaleVal = FscaleValue;
+
+ if (Hardware->chipPowerState == gcvPOWER_ON)
+ {
+ gctUINT32 data;
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &data));
+
+ /* Disable all clock gating. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ?
+ 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ?
+ 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ?
+ 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ?
+ 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:6) - (0 ?
+ 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:7) - (0 ? 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ?
+ 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 8:8) - (0 ? 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ?
+ 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11)))));
+
+ clock = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 8:2) - (0 ? 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2))) | (((gctUINT32) ((gctUINT32) (FscaleValue) & ((gctUINT32) ((((1 ?
+ 8:2) - (0 ? 8:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ?
+ 8:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Done loading the frequency scaler. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9)))));
+
+ /* Restore all clock gating. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ data));
+ }
+
+ gcmkVERIFY(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT * FscaleValue,
+ IN gctUINT * MinFscaleValue,
+ IN gctUINT * MaxFscaleValue
+ )
+{
+ *FscaleValue = Hardware->powerOnFscaleVal;
+ *MinFscaleValue = Hardware->minFscaleValue;
+ *MaxFscaleValue = 64;
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_SetMinFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT MinFscaleValue
+ )
+{
+ if (MinFscaleValue >= 1 && MinFscaleValue <= 64)
+ {
+ Hardware->minFscaleValue = MinFscaleValue;
+ }
+
+ return gcvSTATUS_OK;
+}
+#endif
+
+#if gcdPOWEROFF_TIMEOUT
+gceSTATUS
+gckHARDWARE_SetPowerOffTimeout(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Timeout
+)
+{
+ gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
+
+ Hardware->powerOffTimeout = Timeout;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+gceSTATUS
+gckHARDWARE_QueryPowerOffTimeout(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32* Timeout
+)
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ *Timeout = Hardware->powerOffTimeout;
+
+ gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
+ return gcvSTATUS_OK;
+}
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+ IN gckHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle, address;
+ gctBOOL isIdle;
+
+#if gcdINTERRUPT_STATISTIC
+ gctINT32 pendingInterrupt;
+#endif
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
+
+ /* We are idle when the power is not ON. */
+ if (Hardware->chipPowerState != gcvPOWER_ON)
+ {
+ isIdle = gcvTRUE;
+ }
+
+ else
+ {
+ /* Read idle register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
+
+ /* Pipe must be idle. */
+ if (idle != 0x7ffffffe)
+ {
+ /* Something is busy. */
+ isIdle = gcvFALSE;
+ }
+
+ else
+ {
+#if gcdSECURITY
+ isIdle = gcvTRUE;
+ address = 0;
+#else
+ /* Read the current FE address. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00664,
+ &address));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00664,
+ &address));
+
+ /* Test if address is inside the last WAIT/LINK sequence. */
+ if ((address >= Hardware->lastWaitLink)
+ && (address <= Hardware->lastWaitLink + 16)
+ )
+ {
+ /* FE is in last WAIT/LINK and the pipe is idle. */
+ isIdle = gcvTRUE;
+ }
+ else
+ {
+ /* FE is not in WAIT/LINK yet. */
+ isIdle = gcvFALSE;
+ }
+#endif
+ }
+ }
+
+#if gcdINTERRUPT_STATISTIC
+ gcmkONERROR(gckOS_AtomGet(
+ Hardware->os,
+ Hardware->kernel->eventObj->interruptCount,
+ &pendingInterrupt
+ ));
+
+ if (pendingInterrupt)
+ {
+ isIdle = gcvFALSE;
+ }
+#endif
+
+ *IsIdle = isIdle;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** Handy macros that will help in reading those debug registers.
+*/
+
+#define gcmkREAD_DEBUG_REGISTER(control, block, index, data) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ index))); \
+ gcmkONERROR(\
+ gckOS_ReadRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &profiler->data))
+
+#define gcmkREAD_DEBUG_REGISTER_PART1(control, block, index, data) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ index))); \
+ gcmkONERROR(\
+ gckOS_ReadRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &profiler_part1->data))
+
+#define gcmkREAD_DEBUG_REGISTER_PART2(control, block, index, data) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ index))); \
+ gcmkONERROR(\
+ gckOS_ReadRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &profiler_part2->data))
+#if USE_SW_RESET
+#define gcmkREAD_DEBUG_REGISTER_Q(control, block, index, data) \
+ gcmkREAD_DEBUG_REGISTER(control, block, index, data); \
+ tempCounterValue = profiler->data; \
+ profiler->data = CalcDelta(profiler->data, profilerHistory.data); \
+ profilerHistory.data = tempCounterValue
+
+#else
+#define gcmkREAD_DEBUG_REGISTER_Q(control, block, index, data) \
+ gcmkREAD_DEBUG_REGISTER(control, block, index, data)
+
+#endif
+
+#define gcmkREAD_DEBUG_REGISTER_N(control, block, index, data) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ index))); \
+ gcmkONERROR(\
+ gckOS_ReadRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &data))
+
+#define gcmkRESET_DEBUG_REGISTER(control, block, value) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ value))); \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+ Hardware->core, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ 0)))
+
+
+/*******************************************************************************
+**
+** gckHARDWARE_ProfileEngine2D
+**
+** Read the profile registers available in the 2D engine and sets them in the
+** profile. The function will also reset the pixelsRendered counter every time.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** OPTIONAL gcs2D_PROFILE_PTR Profile
+** Pointer to a gcs2D_Profile structure.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+ IN gckHARDWARE Hardware,
+ OPTIONAL gcs2D_PROFILE_PTR Profile
+ )
+{
+ gceSTATUS status;
+ gcs2D_PROFILE_PTR profiler = Profile;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Profile != gcvNULL)
+ {
+ /* Read the cycle count. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &Profile->cycleCount));
+
+ /* Read pixels rendered by 2D engine. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pixelsRendered));
+
+ /* Reset counter. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if VIVANTE_PROFILER
+
+#if !VIVANTE_PROFILER_ALL_COUNTER
+static gctUINT32
+CalcDelta(
+ IN gctUINT32 new,
+ IN gctUINT32 old
+ )
+{
+ if (new >= old)
+ {
+ return new - old;
+ }
+ else
+ {
+ return (gctUINT32)((gctUINT64)new + 0x100000000ll - old);
+ }
+}
+#endif
+
+#if USE_SW_RESET
+#define gcmkRESET_PROFILE_DATA(counterName, preCounters) \
+ temp = profiler->counterName; \
+ profiler->counterName = CalcDelta(temp, Context->preCounters.counterName); \
+ Context->preCounters.counterName = temp
+
+#define gcmkRESET_PROFILE_DATA_PART1(counterName, preCounters) \
+ temp = profiler_part1->counterName; \
+ profiler_part1->counterName = CalcDelta(temp, Context->preCounters.counterName); \
+ Context->preCounters.counterName = temp
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ OUT gcsPROFILER_COUNTERS * Counters
+ )
+{
+ gceSTATUS status;
+ gcsPROFILER_COUNTERS * profiler = Counters;
+ gctUINT i, clock;
+ gctUINT32 colorKilled, colorDrawn, depthKilled, depthDrawn;
+ gctUINT32 totalRead, totalWrite;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 resetValue = 0xF;
+ gctBOOL hasNewCounters = gcvFALSE;
+ gctUINT32 mc_axi_max_min_latency;
+ static gcsPROFILER_COUNTERS profilerHistory;
+ static gctBOOL isFirstFrame = gcvTRUE;
+ gctUINT32 tempCounterValue;
+ gctUINT32 totalColorKilled = 0;
+ gctUINT32 totalDepthKilled = 0;
+ gctUINT32 totalColorDrawn = 0;
+ gctUINT32 totalDepthDrawn = 0;
+
+ gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ if (isFirstFrame)
+ {
+ gckOS_ZeroMemory(&profilerHistory, sizeof(gcsPROFILER_COUNTERS));
+ isFirstFrame = gcvFALSE;
+ }
+
+ chipModel = Hardware->identity.chipModel;
+ chipRevision = Hardware->identity.chipRevision;
+ if ((chipModel == gcv5000 && chipRevision == 0x5434) || (chipModel == gcv3000 && chipRevision == 0x5435))
+ {
+ resetValue = 0xFF;
+ hasNewCounters = gcvTRUE;
+ }
+
+ /* Read the counters. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &profiler->gpuCyclesCounter));
+
+ /* This counter should be equal to 0x00438. Currently it's not displayed in vAnalyzer */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler->gpuTotalCyclesCounter));
+
+ if (chipModel == gcv2100 || chipModel == gcv2000 || chipModel == gcv880)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler->gpuIdleCyclesCounter));
+ }
+ else
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0007C,
+ &profiler->gpuIdleCyclesCounter));
+ }
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ profiler->gpuTotalRead64BytesPerFrame = 0;
+ profiler->gpuTotalWrite64BytesPerFrame = 0;
+ profiler->pe_pixel_count_killed_by_color_pipe = 0;
+ profiler->pe_pixel_count_killed_by_depth_pipe = 0;
+ profiler->pe_pixel_count_drawn_by_color_pipe = 0;
+ profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
+
+ /* Walk through all avaiable pixel pipes. */
+ for (i = 0; i < Hardware->identity.pixelPipes; ++i)
+ {
+ /* Select proper pipe. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20)))));
+
+ /* BW */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &totalRead));
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &totalWrite));
+
+ profiler->gpuTotalRead64BytesPerFrame += totalRead;
+ profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
+
+ /* PE */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &colorKilled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &depthKilled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &colorDrawn));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &depthDrawn));
+
+#if USE_SW_RESET
+ totalColorKilled += colorKilled;
+ totalDepthKilled += depthKilled;
+ totalColorDrawn += colorDrawn;
+ totalDepthDrawn += depthDrawn;
+#else
+ profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
+ profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
+ profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
+ profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
+#endif
+ }
+
+#if USE_SW_RESET
+ profiler->pe_pixel_count_killed_by_color_pipe = CalcDelta(totalColorKilled, profilerHistory.pe_pixel_count_killed_by_color_pipe);
+ profiler->pe_pixel_count_killed_by_depth_pipe = CalcDelta(totalDepthKilled, profilerHistory.pe_pixel_count_killed_by_depth_pipe);
+ profiler->pe_pixel_count_drawn_by_color_pipe = CalcDelta(totalColorDrawn, profilerHistory.pe_pixel_count_drawn_by_color_pipe);
+ profiler->pe_pixel_count_drawn_by_depth_pipe = CalcDelta(totalDepthDrawn, profilerHistory.pe_pixel_count_drawn_by_depth_pipe);
+ profilerHistory.pe_pixel_count_killed_by_color_pipe = totalColorKilled;
+ profilerHistory.pe_pixel_count_killed_by_depth_pipe = totalDepthKilled;
+ profilerHistory.pe_pixel_count_drawn_by_color_pipe = totalColorDrawn;
+ profilerHistory.pe_pixel_count_drawn_by_depth_pipe = totalDepthDrawn;
+#endif
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Reset counters. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+#endif
+
+ /* SH */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->ps_inst_counter)); tempCounterValue = profiler->ps_inst_counter;
+ profiler->ps_inst_counter = CalcDelta(profiler->ps_inst_counter, profilerHistory.ps_inst_counter);
+ profilerHistory.ps_inst_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->rendered_pixel_counter)); tempCounterValue = profiler->rendered_pixel_counter;
+ profiler->rendered_pixel_counter = CalcDelta(profiler->rendered_pixel_counter,
+ profilerHistory.rendered_pixel_counter); profilerHistory.rendered_pixel_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->vs_inst_counter)); tempCounterValue = profiler->vs_inst_counter;
+ profiler->vs_inst_counter = CalcDelta(profiler->vs_inst_counter, profilerHistory.vs_inst_counter);
+ profilerHistory.vs_inst_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->rendered_vertice_counter)); tempCounterValue = profiler->rendered_vertice_counter;
+ profiler->rendered_vertice_counter = CalcDelta(profiler->rendered_vertice_counter,
+ profilerHistory.rendered_vertice_counter); profilerHistory.rendered_vertice_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->vtx_branch_inst_counter)); tempCounterValue = profiler->vtx_branch_inst_counter;
+ profiler->vtx_branch_inst_counter = CalcDelta(profiler->vtx_branch_inst_counter,
+ profilerHistory.vtx_branch_inst_counter); profilerHistory.vtx_branch_inst_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->vtx_texld_inst_counter)); tempCounterValue = profiler->vtx_texld_inst_counter;
+ profiler->vtx_texld_inst_counter = CalcDelta(profiler->vtx_texld_inst_counter,
+ profilerHistory.vtx_texld_inst_counter); profilerHistory.vtx_texld_inst_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->pxl_branch_inst_counter)); tempCounterValue = profiler->pxl_branch_inst_counter;
+ profiler->pxl_branch_inst_counter = CalcDelta(profiler->pxl_branch_inst_counter,
+ profilerHistory.pxl_branch_inst_counter); profilerHistory.pxl_branch_inst_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->pxl_texld_inst_counter)); tempCounterValue = profiler->pxl_texld_inst_counter;
+ profiler->pxl_texld_inst_counter = CalcDelta(profiler->pxl_texld_inst_counter,
+ profilerHistory.pxl_texld_inst_counter); profilerHistory.pxl_texld_inst_counter = tempCounterValue;
+
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (19) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->vs_non_idle_starve_count)); tempCounterValue = profiler->vs_non_idle_starve_count;
+ profiler->vs_non_idle_starve_count = CalcDelta(profiler->vs_non_idle_starve_count,
+ profilerHistory.vs_non_idle_starve_count); profilerHistory.vs_non_idle_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->vs_starve_count)); tempCounterValue = profiler->vs_starve_count;
+ profiler->vs_starve_count = CalcDelta(profiler->vs_starve_count, profilerHistory.vs_starve_count);
+ profilerHistory.vs_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->vs_stall_count)); tempCounterValue = profiler->vs_stall_count;
+ profiler->vs_stall_count = CalcDelta(profiler->vs_stall_count, profilerHistory.vs_stall_count);
+ profilerHistory.vs_stall_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (21) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->vs_process_count)); tempCounterValue = profiler->vs_process_count;
+ profiler->vs_process_count = CalcDelta(profiler->vs_process_count, profilerHistory.vs_process_count);
+ profilerHistory.vs_process_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (20) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->ps_non_idle_starve_count)); tempCounterValue = profiler->ps_non_idle_starve_count;
+ profiler->ps_non_idle_starve_count = CalcDelta(profiler->ps_non_idle_starve_count,
+ profilerHistory.ps_non_idle_starve_count); profilerHistory.ps_non_idle_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (17) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->ps_starve_count)); tempCounterValue = profiler->ps_starve_count;
+ profiler->ps_starve_count = CalcDelta(profiler->ps_starve_count, profilerHistory.ps_starve_count);
+ profilerHistory.ps_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (18) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->ps_stall_count)); tempCounterValue = profiler->ps_stall_count;
+ profiler->ps_stall_count = CalcDelta(profiler->ps_stall_count, profilerHistory.ps_stall_count);
+ profilerHistory.ps_stall_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (22) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->ps_process_count)); tempCounterValue = profiler->ps_process_count;
+ profiler->ps_process_count = CalcDelta(profiler->ps_process_count, profilerHistory.ps_process_count);
+ profilerHistory.ps_process_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->shader_cycle_count)); tempCounterValue = profiler->shader_cycle_count;
+ profiler->shader_cycle_count = CalcDelta(profiler->shader_cycle_count,
+ profilerHistory.shader_cycle_count); profilerHistory.shader_cycle_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (23) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->tx_non_idle_starve_count)); tempCounterValue = profiler->tx_non_idle_starve_count;
+ profiler->tx_non_idle_starve_count = CalcDelta(profiler->tx_non_idle_starve_count,
+ profilerHistory.tx_non_idle_starve_count); profilerHistory.tx_non_idle_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (24) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->tx_starve_count)); tempCounterValue = profiler->tx_starve_count;
+ profiler->tx_starve_count = CalcDelta(profiler->tx_starve_count, profilerHistory.tx_starve_count);
+ profilerHistory.tx_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (25) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->tx_stall_count)); tempCounterValue = profiler->tx_stall_count;
+ profiler->tx_stall_count = CalcDelta(profiler->tx_stall_count, profilerHistory.tx_stall_count);
+ profilerHistory.tx_stall_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (26) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C,
+ &profiler->tx_process_count)); tempCounterValue = profiler->tx_process_count;
+ profiler->tx_process_count = CalcDelta(profiler->tx_process_count, profilerHistory.tx_process_count);
+ profilerHistory.tx_process_count = tempCounterValue;
+
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+));
+#endif
+
+ /* PA */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_input_vtx_counter)); tempCounterValue = profiler->pa_input_vtx_counter;
+ profiler->pa_input_vtx_counter = CalcDelta(profiler->pa_input_vtx_counter,
+ profilerHistory.pa_input_vtx_counter); profilerHistory.pa_input_vtx_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_input_prim_counter)); tempCounterValue = profiler->pa_input_prim_counter;
+ profiler->pa_input_prim_counter = CalcDelta(profiler->pa_input_prim_counter,
+ profilerHistory.pa_input_prim_counter); profilerHistory.pa_input_prim_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_output_prim_counter)); tempCounterValue = profiler->pa_output_prim_counter;
+ profiler->pa_output_prim_counter = CalcDelta(profiler->pa_output_prim_counter,
+ profilerHistory.pa_output_prim_counter); profilerHistory.pa_output_prim_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_depth_clipped_counter)); tempCounterValue = profiler->pa_depth_clipped_counter;
+ profiler->pa_depth_clipped_counter = CalcDelta(profiler->pa_depth_clipped_counter,
+ profilerHistory.pa_depth_clipped_counter); profilerHistory.pa_depth_clipped_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_trivial_rejected_counter)); tempCounterValue = profiler->pa_trivial_rejected_counter;
+ profiler->pa_trivial_rejected_counter = CalcDelta(profiler->pa_trivial_rejected_counter,
+ profilerHistory.pa_trivial_rejected_counter); profilerHistory.pa_trivial_rejected_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_culled_counter)); tempCounterValue = profiler->pa_culled_counter;
+ profiler->pa_culled_counter = CalcDelta(profiler->pa_culled_counter, profilerHistory.pa_culled_counter);
+ profilerHistory.pa_culled_counter = tempCounterValue;
+
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_starve_count)); tempCounterValue = profiler->pa_starve_count;
+ profiler->pa_starve_count = CalcDelta(profiler->pa_starve_count, profilerHistory.pa_starve_count);
+ profilerHistory.pa_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_stall_count)); tempCounterValue = profiler->pa_stall_count;
+ profiler->pa_stall_count = CalcDelta(profiler->pa_stall_count, profilerHistory.pa_stall_count);
+ profilerHistory.pa_stall_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_process_count)); tempCounterValue = profiler->pa_process_count;
+ profiler->pa_process_count = CalcDelta(profiler->pa_process_count, profilerHistory.pa_process_count);
+ profilerHistory.pa_process_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460,
+ &profiler->pa_non_idle_starve_count)); tempCounterValue = profiler->pa_non_idle_starve_count;
+ profiler->pa_non_idle_starve_count = CalcDelta(profiler->pa_non_idle_starve_count,
+ profilerHistory.pa_non_idle_starve_count); profilerHistory.pa_non_idle_starve_count = tempCounterValue;
+
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+#endif
+
+ /* SE */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_triangle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_lines_count));
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_receive_triangle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_send_triangle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_receive_lines_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_send_lines_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (19) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_process_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (20) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_non_idle_starve_count));
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))
+));
+
+ /* RA */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_valid_pixel_count)); tempCounterValue = profiler->ra_valid_pixel_count;
+ profiler->ra_valid_pixel_count = CalcDelta(profiler->ra_valid_pixel_count,
+ profilerHistory.ra_valid_pixel_count); profilerHistory.ra_valid_pixel_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_total_quad_count)); tempCounterValue = profiler->ra_total_quad_count;
+ profiler->ra_total_quad_count = CalcDelta(profiler->ra_total_quad_count,
+ profilerHistory.ra_total_quad_count); profilerHistory.ra_total_quad_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_valid_quad_count_after_early_z)); tempCounterValue = profiler->ra_valid_quad_count_after_early_z;
+ profiler->ra_valid_quad_count_after_early_z = CalcDelta(profiler->ra_valid_quad_count_after_early_z,
+ profilerHistory.ra_valid_quad_count_after_early_z); profilerHistory.ra_valid_quad_count_after_early_z = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_total_primitive_count)); tempCounterValue = profiler->ra_total_primitive_count;
+ profiler->ra_total_primitive_count = CalcDelta(profiler->ra_total_primitive_count,
+ profilerHistory.ra_total_primitive_count); profilerHistory.ra_total_primitive_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_pipe_cache_miss_counter)); tempCounterValue = profiler->ra_pipe_cache_miss_counter;
+ profiler->ra_pipe_cache_miss_counter = CalcDelta(profiler->ra_pipe_cache_miss_counter,
+ profilerHistory.ra_pipe_cache_miss_counter); profilerHistory.ra_pipe_cache_miss_counter = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_prefetch_cache_miss_counter)); tempCounterValue = profiler->ra_prefetch_cache_miss_counter;
+ profiler->ra_prefetch_cache_miss_counter = CalcDelta(profiler->ra_prefetch_cache_miss_counter,
+ profilerHistory.ra_prefetch_cache_miss_counter); profilerHistory.ra_prefetch_cache_miss_counter = tempCounterValue;
+
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_non_idle_starve_count)); tempCounterValue = profiler->ra_non_idle_starve_count;
+ profiler->ra_non_idle_starve_count = CalcDelta(profiler->ra_non_idle_starve_count,
+ profilerHistory.ra_non_idle_starve_count); profilerHistory.ra_non_idle_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_starve_count)); tempCounterValue = profiler->ra_starve_count;
+ profiler->ra_starve_count = CalcDelta(profiler->ra_starve_count, profilerHistory.ra_starve_count);
+ profilerHistory.ra_starve_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_stall_count)); tempCounterValue = profiler->ra_stall_count;
+ profiler->ra_stall_count = CalcDelta(profiler->ra_stall_count, profilerHistory.ra_stall_count);
+ profilerHistory.ra_stall_count = tempCounterValue;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448,
+ &profiler->ra_process_count)); tempCounterValue = profiler->ra_process_count;
+ profiler->ra_process_count = CalcDelta(profiler->ra_process_count, profilerHistory.ra_process_count);
+ profilerHistory.ra_process_count = tempCounterValue;
+
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+#endif
+
+ /* TX */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_trilinear_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_discarded_texture_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_texture_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_in_8B_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_hit_texel_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_texel_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+));
+
+ /* MC */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+
+ /* HI */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))
+));
+
+ if (hasNewCounters)
+ {
+ /* latency */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0056C,
+ &mc_axi_max_min_latency));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00570,
+ &profiler->mc_axi_total_latency));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00574,
+ &profiler->mc_axi_sample_count));
+
+ /* Reset Latency counters */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00568,
+ 0x10a));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00568,
+ 0xa));
+
+ profiler->mc_axi_min_latency = (mc_axi_max_min_latency & 0x0fff0000) >> 16;
+ profiler->mc_axi_max_latency = (mc_axi_max_min_latency & 0x00000fff);
+ if (profiler->mc_axi_min_latency == 4095)
+ profiler->mc_axi_min_latency = 0;
+
+ /* FE */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->fe_draw_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->fe_out_vertex_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->fe_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->fe_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+
+#if VIVANTE_PROFILER_CONTEXT
+#define gcmkUPDATE_PROFILE_DATA(data) \
+ profilerHistroy->data += profiler->data
+
+#define gcmkUPDATE_PROFILE_DATA_PART1(data) \
+ profilerHistroy_part1->data += profiler_part1->data
+#define gcmkUPDATE_PROFILE_DATA_PART2(data) \
+ profilerHistroy_part2->data += profiler_part2->data
+
+gceSTATUS
+gckHARDWARE_QueryContextProfile(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ IN gckCONTEXT Context,
+ OUT gcsPROFILER_COUNTERS * Counters
+ )
+{
+ gceSTATUS status;
+ gckCOMMAND command = Hardware->kernel->command;
+ gcsPROFILER_COUNTERS * profiler = Counters;
+
+ gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Acquire the context sequnence mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ command->os, command->mutexContextSeq, gcvINFINITE
+ ));
+
+ /* Read the counters. */
+ gcmkVERIFY_OK(gckOS_MemCopy(
+ profiler, &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
+ ));
+
+#if VIVANTE_PROFILER_ALL_COUNTER
+ {
+ gctUINT32 tid, i;
+ static gctUINT32 frameNum = 0;
+ gcmkONERROR(gckOS_GetThreadID(&tid));
+ gcmkPRINT("TID: %d: Frame #%d\n", tid, frameNum);
+
+ gcmkPRINT("TID: %d; GPU cycles: cycle: %u, total: %u, idle: %u\n", tid,
+ profiler->gpuCyclesCounter,
+ profiler->gpuTotalCyclesCounter,
+ profiler->gpuIdleCyclesCounter);
+
+ gcmkPRINT("TID: %d; BW: read: %u, write: %u\n", tid,
+ profiler->gpuTotalRead64BytesPerFrame,
+ profiler->gpuTotalWrite64BytesPerFrame);
+
+ gcmkPRINT("TID: %d; Latency: min: %u, max: %u, total: %u, sample count: %u\n", tid,
+ profiler->mc_axi_min_latency,
+ profiler->mc_axi_max_latency,
+ profiler->mc_axi_total_latency,
+ profiler->mc_axi_sample_count);
+
+ for (i = 0; i < MODULE_FRONT_END_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; FE counter #%d: %u\n", tid,i,profiler->feCounters[i]);
+ }
+ for (i = 0; i < MODULE_PRIMITIVE_ASSEMBLY_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; PA counter #%d: %u\n", tid,i,profiler->paCounters[i]);
+ }
+ for (i = 0; i < MODULE_SHADER_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; SH counter #%d: %u\n", tid,i,profiler->shCounters[i]);
+ }
+ for (i = 0; i < MODULE_SETUP_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; SE counter #%d: %u\n", tid,i,profiler->seCounters[i]);
+ }
+ for (i = 0; i < MODULE_FRONT_END_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; RA counter #%d: %u\n", tid,i,profiler->raCounters[i]);
+ }
+ for (i = 0; i < MODULE_PRIMITIVE_ASSEMBLY_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; PE counter #%d: %u\n", tid,i,profiler->peCounters[i]);
+ }
+ for (i = 0; i < MODULE_TEXTURE_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; TX counter #%d: %u\n", tid,i,profiler->txCounters[i]);
+ }
+ for (i = 0; i < MODULE_SHADER_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; MC counter #%d: %u\n", tid,i,profiler->mcCounters[i]);
+ }
+ for (i = 0; i < MODULE_SETUP_COUNTER_NUM; i++)
+ {
+ gcmkPRINT("TID: %d; HI counter #%d: %u\n", tid,i,profiler->hiCounters[i]);
+ }
+ frameNum++;
+ }
+#endif
+
+ /* Reset counters. */
+ if (Reset)
+ {
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
+ ));
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ command->os, command->mutexContextSeq
+ ));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_UpdateContextProfile(
+ IN gckHARDWARE Hardware,
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status;
+ gcsPROFILER_COUNTERS * profiler = &Context->latestProfiler;
+ gcsPROFILER_COUNTERS * profilerHistroy = &Context->histroyProfiler;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 i;
+ gctUINT32 resetValue = 0xF;
+ gctBOOL hasNewCounters = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x Context=0x%x", Hardware, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+ chipModel = Hardware->identity.chipModel;
+ chipRevision = Hardware->identity.chipRevision;
+ if ((chipModel == gcv5000 && chipRevision == 0x5434) || (chipModel == gcv3000 && chipRevision == 0x5435))
+ {
+ resetValue = 0xFF;
+ hasNewCounters = gcvTRUE;
+ }
+
+ /* Read the counters. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &profiler->gpuCyclesCounter));
+ gcmkUPDATE_PROFILE_DATA(gpuCyclesCounter);
+
+ /* This counter should be equal to 0x00438. Currently it's not displayed in vAnalyzer */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler->gpuTotalCyclesCounter));
+ gcmkUPDATE_PROFILE_DATA(gpuTotalCyclesCounter);
+
+ if (chipModel == gcv2100 || chipModel == gcv2000 || chipModel == gcv880)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler->gpuIdleCyclesCounter));
+ }
+ else
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0007C,
+ &profiler->gpuIdleCyclesCounter));
+ }
+ gcmkUPDATE_PROFILE_DATA(gpuIdleCyclesCounter);
+
+#if !VIVANTE_PROFILER_ALL_COUNTER
+ {
+ gctUINT clock;
+ gctUINT32 colorKilled = 0, colorDrawn = 0, depthKilled = 0, depthDrawn = 0;
+ gctUINT32 totalRead, totalWrite;
+ gctUINT32 mc_axi_max_min_latency;
+
+ gctUINT32 temp;
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ profiler->gpuTotalRead64BytesPerFrame = 0;
+ profiler->gpuTotalWrite64BytesPerFrame = 0;
+ profiler->pe_pixel_count_killed_by_color_pipe = 0;
+ profiler->pe_pixel_count_killed_by_depth_pipe = 0;
+ profiler->pe_pixel_count_drawn_by_color_pipe = 0;
+ profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
+
+ /* Walk through all avaiable pixel pipes. */
+ for (i = 0; i < Hardware->identity.pixelPipes; ++i)
+ {
+ /* Select proper pipe. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20)))));
+
+ /* BW */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &totalRead));
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &totalWrite));
+
+ profiler->gpuTotalRead64BytesPerFrame += totalRead;
+ profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
+
+ /* PE */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &colorKilled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &depthKilled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &colorDrawn));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &depthDrawn));
+
+ profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
+ profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
+ profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
+ profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
+ }
+
+ gcmkUPDATE_PROFILE_DATA(gpuTotalRead64BytesPerFrame);
+ gcmkUPDATE_PROFILE_DATA(gpuTotalWrite64BytesPerFrame);
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA(pe_pixel_count_killed_by_color_pipe, preProfiler);
+ gcmkRESET_PROFILE_DATA(pe_pixel_count_killed_by_depth_pipe, preProfiler);
+ gcmkRESET_PROFILE_DATA(pe_pixel_count_drawn_by_color_pipe, preProfiler);
+ gcmkRESET_PROFILE_DATA(pe_pixel_count_drawn_by_depth_pipe, preProfiler);
+#endif
+ gcmkUPDATE_PROFILE_DATA(pe_pixel_count_killed_by_color_pipe);
+ gcmkUPDATE_PROFILE_DATA(pe_pixel_count_killed_by_depth_pipe);
+ gcmkUPDATE_PROFILE_DATA(pe_pixel_count_drawn_by_color_pipe);
+ gcmkUPDATE_PROFILE_DATA(pe_pixel_count_drawn_by_depth_pipe);
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Reset counters. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+#endif
+
+ /* SH */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_pixel_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_vertice_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_branch_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_texld_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_branch_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_texld_inst_counter));
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (19) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (21) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_process_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (20) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (17) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (18) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (22) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_process_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->shader_cycle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (23) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->tx_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (24) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->tx_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (25) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->tx_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (26) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->tx_process_count));
+ }
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA(ps_inst_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(rendered_pixel_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(vs_inst_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(rendered_vertice_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(vtx_branch_inst_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(vtx_texld_inst_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(pxl_branch_inst_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(pxl_texld_inst_counter, preProfiler);
+ if (hasNewCounters)
+ {
+ gcmkRESET_PROFILE_DATA(vs_non_idle_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(vs_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(vs_stall_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(vs_process_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ps_non_idle_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ps_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ps_stall_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ps_process_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(shader_cycle_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(tx_non_idle_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(tx_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(tx_stall_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(tx_process_count, preProfiler);
+ }
+#endif
+ gcmkUPDATE_PROFILE_DATA(ps_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(rendered_pixel_counter);
+ gcmkUPDATE_PROFILE_DATA(vs_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(rendered_vertice_counter);
+ gcmkUPDATE_PROFILE_DATA(vtx_branch_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(vtx_texld_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(pxl_branch_inst_counter);
+ gcmkUPDATE_PROFILE_DATA(pxl_texld_inst_counter);
+ if (hasNewCounters)
+ {
+ gcmkUPDATE_PROFILE_DATA(vs_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA(vs_starve_count);
+ gcmkUPDATE_PROFILE_DATA(vs_stall_count);
+ gcmkUPDATE_PROFILE_DATA(vs_process_count);
+ gcmkUPDATE_PROFILE_DATA(ps_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA(ps_starve_count);
+ gcmkUPDATE_PROFILE_DATA(ps_stall_count);
+ gcmkUPDATE_PROFILE_DATA(ps_process_count);
+ gcmkUPDATE_PROFILE_DATA(shader_cycle_count);
+ gcmkUPDATE_PROFILE_DATA(tx_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA(tx_starve_count);
+ gcmkUPDATE_PROFILE_DATA(tx_stall_count);
+ gcmkUPDATE_PROFILE_DATA(tx_process_count);
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+));
+#endif
+
+ /* PA */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_vtx_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_prim_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_output_prim_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_depth_clipped_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_trivial_rejected_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_culled_counter));
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_process_count));
+ }
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA(pa_input_vtx_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(pa_input_prim_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(pa_output_prim_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(pa_depth_clipped_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(pa_trivial_rejected_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(pa_culled_counter, preProfiler);
+ if (hasNewCounters)
+ {
+ gcmkRESET_PROFILE_DATA(pa_non_idle_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(pa_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(pa_stall_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(pa_process_count, preProfiler);
+ }
+#endif
+ gcmkUPDATE_PROFILE_DATA(pa_input_vtx_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_input_prim_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_output_prim_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_depth_clipped_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_trivial_rejected_counter);
+ gcmkUPDATE_PROFILE_DATA(pa_culled_counter);
+ if (hasNewCounters)
+ {
+ gcmkUPDATE_PROFILE_DATA(pa_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA(pa_starve_count);
+ gcmkUPDATE_PROFILE_DATA(pa_stall_count);
+ gcmkUPDATE_PROFILE_DATA(pa_process_count);
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+#endif
+
+ /* SE */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_triangle_count));
+ gcmkUPDATE_PROFILE_DATA(se_culled_triangle_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_lines_count));
+ gcmkUPDATE_PROFILE_DATA(se_culled_lines_count);
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_starve_count));
+ gcmkUPDATE_PROFILE_DATA(se_starve_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_stall_count));
+ gcmkUPDATE_PROFILE_DATA(se_stall_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_receive_triangle_count));
+ gcmkUPDATE_PROFILE_DATA(se_receive_triangle_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_send_triangle_count));
+ gcmkUPDATE_PROFILE_DATA(se_send_triangle_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_receive_lines_count));
+ gcmkUPDATE_PROFILE_DATA(se_receive_lines_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_send_lines_count));
+ gcmkUPDATE_PROFILE_DATA(se_send_lines_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (19) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_process_count));
+ gcmkUPDATE_PROFILE_DATA(se_process_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (20) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_non_idle_starve_count));
+ gcmkUPDATE_PROFILE_DATA(se_non_idle_starve_count);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))
+));
+
+ /* RA */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_pixel_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_quad_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_primitive_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_pipe_cache_miss_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_process_count));
+ }
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA(ra_valid_pixel_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ra_total_quad_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ra_valid_quad_count_after_early_z, preProfiler);
+ gcmkRESET_PROFILE_DATA(ra_total_primitive_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ra_pipe_cache_miss_counter, preProfiler);
+ gcmkRESET_PROFILE_DATA(ra_prefetch_cache_miss_counter, preProfiler);
+ if (hasNewCounters)
+ {
+ gcmkRESET_PROFILE_DATA(ra_non_idle_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ra_starve_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ra_stall_count, preProfiler);
+ gcmkRESET_PROFILE_DATA(ra_process_count, preProfiler);
+ }
+#endif
+ gcmkUPDATE_PROFILE_DATA(ra_valid_pixel_count);
+ gcmkUPDATE_PROFILE_DATA(ra_total_quad_count);
+ gcmkUPDATE_PROFILE_DATA(ra_valid_quad_count_after_early_z);
+ gcmkUPDATE_PROFILE_DATA(ra_total_primitive_count);
+ gcmkUPDATE_PROFILE_DATA(ra_pipe_cache_miss_counter);
+ gcmkUPDATE_PROFILE_DATA(ra_prefetch_cache_miss_counter);
+ if (hasNewCounters)
+ {
+ gcmkUPDATE_PROFILE_DATA(ra_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA(ra_starve_count);
+ gcmkUPDATE_PROFILE_DATA(ra_stall_count);
+ gcmkUPDATE_PROFILE_DATA(ra_process_count);
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+#endif
+
+ /* TX */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
+ gcmkUPDATE_PROFILE_DATA(tx_total_bilinear_requests);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_trilinear_requests));
+ gcmkUPDATE_PROFILE_DATA(tx_total_trilinear_requests);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_discarded_texture_requests));
+ gcmkUPDATE_PROFILE_DATA(tx_total_discarded_texture_requests);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_texture_requests));
+ gcmkUPDATE_PROFILE_DATA(tx_total_texture_requests);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_count));
+ gcmkUPDATE_PROFILE_DATA(tx_mem_read_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_in_8B_count));
+ gcmkUPDATE_PROFILE_DATA(tx_mem_read_in_8B_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_count));
+ gcmkUPDATE_PROFILE_DATA(tx_cache_miss_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_hit_texel_count));
+ gcmkUPDATE_PROFILE_DATA(tx_cache_hit_texel_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_texel_count));
+ gcmkUPDATE_PROFILE_DATA(tx_cache_miss_texel_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+));
+
+ /* MC */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
+ gcmkUPDATE_PROFILE_DATA(mc_total_read_req_8B_from_pipeline);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
+ gcmkUPDATE_PROFILE_DATA(mc_total_read_req_8B_from_IP);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
+ gcmkUPDATE_PROFILE_DATA(mc_total_write_req_8B_from_pipeline);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+
+ /* read latency counters */
+ if (hasNewCounters)
+ {
+ /* latency */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0056C,
+ &mc_axi_max_min_latency));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00570,
+ &profiler->mc_axi_total_latency));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00574,
+ &profiler->mc_axi_sample_count));
+
+ /* Reset Latency counters */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00568,
+ 0x10a));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00568,
+ 0xa));
+
+ profiler->mc_axi_min_latency = (mc_axi_max_min_latency & 0x0fff0000) >> 16;
+ profiler->mc_axi_max_latency = (mc_axi_max_min_latency & 0x00000fff);
+ if (profiler->mc_axi_min_latency == 4095)
+ profiler->mc_axi_min_latency = 0;
+
+ gcmkUPDATE_PROFILE_DATA(mc_axi_min_latency);
+ gcmkUPDATE_PROFILE_DATA(mc_axi_max_latency);
+ gcmkUPDATE_PROFILE_DATA(mc_axi_total_latency);
+ gcmkUPDATE_PROFILE_DATA(mc_axi_sample_count);
+
+ /* FE */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->fe_draw_count));
+ gcmkUPDATE_PROFILE_DATA(fe_draw_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->fe_out_vertex_count));
+ gcmkUPDATE_PROFILE_DATA(fe_draw_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->fe_stall_count));
+ gcmkUPDATE_PROFILE_DATA(fe_draw_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->fe_starve_count));
+ gcmkUPDATE_PROFILE_DATA(fe_draw_count);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+ }
+
+ /* HI */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
+ gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_read_request_stalled);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
+ gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_write_request_stalled);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
+ gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_write_data_stalled);
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))
+));
+ }
+
+#else
+ {
+ gctUINT32 mc_axi_max_min_latency;
+ gctUINT clock;
+ gctUINT32 totalRead, totalWrite;
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ profiler->gpuTotalRead64BytesPerFrame = 0;
+ profiler->gpuTotalWrite64BytesPerFrame = 0;
+
+ /* Walk through all avaiable pixel pipes. */
+ for (i = 0; i < Hardware->identity.pixelPipes; ++i)
+ {
+ /* Select proper pipe. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20)))));
+
+ /* BW */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &totalRead));
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &totalWrite));
+
+ profiler->gpuTotalRead64BytesPerFrame += totalRead;
+ profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
+ }
+
+ gcmkUPDATE_PROFILE_DATA(gpuTotalRead64BytesPerFrame);
+ gcmkUPDATE_PROFILE_DATA(gpuTotalWrite64BytesPerFrame);
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Reset counters. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
+
+ /* read latency counters */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0056C,
+ &mc_axi_max_min_latency));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00570,
+ &profiler->mc_axi_total_latency));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00574,
+ &profiler->mc_axi_sample_count));
+
+ /* Reset Latency counters */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00568,
+ 0x10a));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00568,
+ 0xa));
+
+ profiler->mc_axi_min_latency = (mc_axi_max_min_latency & 0x0fff0000) >> 16;
+ profiler->mc_axi_max_latency = (mc_axi_max_min_latency & 0x00000fff);
+ if (profiler->mc_axi_min_latency == 4095)
+ profiler->mc_axi_min_latency = 0;
+
+ gcmkUPDATE_PROFILE_DATA(mc_axi_min_latency);
+ gcmkUPDATE_PROFILE_DATA(mc_axi_max_latency);
+ gcmkUPDATE_PROFILE_DATA(mc_axi_total_latency);
+ gcmkUPDATE_PROFILE_DATA(mc_axi_sample_count);
+
+ /* FE */
+ for (i = 0; i < MODULE_FRONT_END_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler->feCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(feCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+
+ /* PA */
+ for (i = 0; i < MODULE_FRONT_END_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->paCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(paCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+
+ /* SH */
+ for (i = 0; i < MODULE_SHADER_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->shCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(shCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+));
+
+ /* SE */
+ for (i = 0; i < MODULE_SETUP_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->seCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(seCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))
+));
+
+ /* RA */
+ for (i = 0; i < MODULE_RASTERIZER_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->raCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(raCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+
+ /* TX */
+ for (i = 0; i < MODULE_TEXTURE_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->txCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(txCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+));
+
+ /* PE */
+ for (i = 0; i < MODULE_PIXEL_ENGINE_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->peCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(peCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+
+ /* MC */
+ for (i = 0; i < MODULE_MEMORY_CONTROLLER_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mcCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(mcCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+
+ /* HI */
+ for (i = 0; i < MODULE_HOST_INTERFACE_COUNTER_NUM; i++)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hiCounters[i]));
+ gcmkUPDATE_PROFILE_DATA(hiCounters[i]);
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))
+));
+
+ }
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryContextNewProfile(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ IN gckCONTEXT Context,
+ OUT gcsPROFILER_NEW_COUNTERS_PART1 * Counters_part1,
+ OUT gcsPROFILER_NEW_COUNTERS_PART2 * Counters_part2
+)
+{
+ gceSTATUS status;
+ gckCOMMAND command = Hardware->kernel->command;
+ gcsPROFILER_NEW_COUNTERS_PART1 * profiler_part1 = Counters_part1;
+ gcsPROFILER_NEW_COUNTERS_PART2 * profiler_part2 = Counters_part2;
+
+ gcmkHEADER_ARG("Hardware=0x%x Counters_part1=0x%x, Counters_part2=0x%x", Hardware, Counters_part1, Counters_part2);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /*
+ * User-space can attach to whatever context it desires, leading first to a
+ * memory NULL pointer dereference when copying the counters, and later
+ * invocation of this function will dead-lock trying to acquire a lock that
+ * was already acquired. The context is converted to a pointer so even if
+ * user-space supplies another context would be transformed to a NULL value.
+ */
+ if ((Context == NULL) || (&Context->histroyNewProfiler_part1 == NULL) ||
+ (&Context->histroyNewProfiler_part2 == NULL)) {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Acquire the context sequnence mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ command->os, command->mutexContextSeq, gcvINFINITE
+ ));
+
+ /* Read the counters. */
+ if (Counters_part1)
+ {
+ gcmkVERIFY_OK(gckOS_MemCopy(
+ profiler_part1, &Context->histroyNewProfiler_part1, gcmSIZEOF(gcsPROFILER_NEW_COUNTERS_PART1)
+ ));
+ }
+ else if (Counters_part2)
+ {
+ gcmkVERIFY_OK(gckOS_MemCopy(
+ profiler_part2, &Context->histroyNewProfiler_part2, gcmSIZEOF(gcsPROFILER_NEW_COUNTERS_PART2)
+ ));
+ }
+
+ /* Reset counters. */
+ if (Reset)
+ {
+ if (Counters_part1)
+ {
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ &Context->histroyNewProfiler_part1, gcmSIZEOF(gcsPROFILER_NEW_COUNTERS_PART1)
+ ));
+ }
+ else if (Counters_part2)
+ {
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ &Context->histroyNewProfiler_part2, gcmSIZEOF(gcsPROFILER_NEW_COUNTERS_PART2)
+ ));
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ command->os, command->mutexContextSeq
+ ));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_UpdateContextNewProfile(
+ IN gckHARDWARE Hardware,
+ IN gckCONTEXT Context
+)
+{
+ gceSTATUS status;
+ gcsPROFILER_NEW_COUNTERS_PART1 * profiler_part1 = &Context->latestNewProfiler_part1;
+ gcsPROFILER_NEW_COUNTERS_PART1 * profilerHistroy_part1 = &Context->histroyNewProfiler_part1;
+ gcsPROFILER_NEW_COUNTERS_PART2 * profiler_part2 = &Context->latestNewProfiler_part2;
+ gcsPROFILER_NEW_COUNTERS_PART2 * profilerHistroy_part2 = &Context->histroyNewProfiler_part2;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 i;
+ gctUINT32 resetValue = 0xF;
+ gctBOOL hasNewCounters = gcvFALSE;
+ gctUINT32 clock;
+ gctUINT32 colorKilled = 0, colorDrawn = 0, depthKilled = 0, depthDrawn = 0;
+ gctUINT32 totalRead, totalWrite;
+ gctUINT32 mc_axi_max_min_latency;
+ gctUINT32 temp;
+ gckCOMMAND command = Hardware->kernel->command;
+
+ gcmkHEADER_ARG("Hardware=0x%x Context=0x%x", Hardware, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
+
+ /* Acquire the context sequnence mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ command->os, command->mutexContextSeq, gcvINFINITE
+ ));
+
+ chipModel = Hardware->identity.chipModel;
+ chipRevision = Hardware->identity.chipRevision;
+ if ((chipModel == gcv5000 && chipRevision == 0x5434) || (chipModel == gcv3000 && chipRevision == 0x5435))
+ {
+ resetValue = 0xFF;
+ hasNewCounters = gcvTRUE;
+ }
+
+ if (chipModel == gcv2100 || chipModel == gcv2000 || chipModel == gcv880)
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &profiler_part2->hi_total_cycle_count));
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler_part2->hi_total_idle_cycle_count));
+ }
+ else
+ {
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &profiler_part2->hi_total_cycle_count));
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0007C,
+ &profiler_part2->hi_total_idle_cycle_count));
+ }
+ gcmkUPDATE_PROFILE_DATA_PART2(hi_total_cycle_count);
+ gcmkUPDATE_PROFILE_DATA_PART2(hi_total_idle_cycle_count);
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ profiler_part2->hi_total_read_8B_count = 0;
+ profiler_part2->hi_total_write_8B_count = 0;
+ profiler_part1->pe0_pixel_count_drawn_by_color_pipe = 0;
+ profiler_part1->pe0_pixel_count_drawn_by_depth_pipe = 0;
+ profiler_part1->pe0_pixel_count_killed_by_color_pipe = 0;
+ profiler_part1->pe0_pixel_count_killed_by_depth_pipe = 0;
+ profiler_part1->pe1_pixel_count_drawn_by_color_pipe = 0;
+ profiler_part1->pe1_pixel_count_drawn_by_depth_pipe = 0;
+ profiler_part1->pe1_pixel_count_killed_by_color_pipe = 0;
+ profiler_part1->pe1_pixel_count_killed_by_depth_pipe = 0;
+
+ /* Walk through all avaiable pixel pipes. */
+ for (i = 0; i < Hardware->identity.pixelPipes; ++i)
+ {
+ /* Select proper pipe. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20)))));
+
+ /* BW */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &totalRead));
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &totalWrite));
+
+ profiler_part2->hi_total_read_8B_count += totalRead;
+ profiler_part2->hi_total_write_8B_count += totalWrite;
+
+ /* PE */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &colorKilled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &depthKilled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &colorDrawn));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454,
+ &depthDrawn));
+
+ if (i == 0)
+ {
+ profiler_part1->pe0_pixel_count_killed_by_color_pipe = colorKilled;
+ profiler_part1->pe0_pixel_count_killed_by_depth_pipe = depthKilled;
+ profiler_part1->pe0_pixel_count_drawn_by_color_pipe = colorDrawn;
+ profiler_part1->pe0_pixel_count_drawn_by_depth_pipe = depthDrawn;
+ }
+ else if (i == 1)
+ {
+ profiler_part1->pe1_pixel_count_killed_by_color_pipe = colorKilled;
+ profiler_part1->pe1_pixel_count_killed_by_depth_pipe = depthKilled;
+ profiler_part1->pe1_pixel_count_drawn_by_color_pipe = colorDrawn;
+ profiler_part1->pe1_pixel_count_drawn_by_depth_pipe = depthDrawn;
+ }
+ }
+
+ gcmkUPDATE_PROFILE_DATA_PART2(hi_total_read_8B_count);
+ gcmkUPDATE_PROFILE_DATA_PART2(hi_total_write_8B_count);
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA_PART1(pe0_pixel_count_killed_by_color_pipe, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pe0_pixel_count_killed_by_depth_pipe, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pe0_pixel_count_drawn_by_color_pipe, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pe0_pixel_count_drawn_by_depth_pipe, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pe1_pixel_count_killed_by_color_pipe, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pe1_pixel_count_killed_by_depth_pipe, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pe1_pixel_count_drawn_by_color_pipe, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pe1_pixel_count_drawn_by_depth_pipe, preNewProfiler_part1);
+#endif
+ gcmkUPDATE_PROFILE_DATA_PART1(pe0_pixel_count_killed_by_color_pipe);
+ gcmkUPDATE_PROFILE_DATA_PART1(pe0_pixel_count_killed_by_depth_pipe);
+ gcmkUPDATE_PROFILE_DATA_PART1(pe0_pixel_count_drawn_by_color_pipe);
+ gcmkUPDATE_PROFILE_DATA_PART1(pe0_pixel_count_drawn_by_depth_pipe);
+ gcmkUPDATE_PROFILE_DATA_PART1(pe1_pixel_count_killed_by_color_pipe);
+ gcmkUPDATE_PROFILE_DATA_PART1(pe1_pixel_count_killed_by_depth_pipe);
+ gcmkUPDATE_PROFILE_DATA_PART1(pe1_pixel_count_drawn_by_color_pipe);
+ gcmkUPDATE_PROFILE_DATA_PART1(pe1_pixel_count_drawn_by_depth_pipe);
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Reset counters. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+#endif
+
+ /* FE */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler_part1->fe_draw_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler_part1->fe_out_vertex_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler_part1->fe_cache_miss_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler_part1->fe_cache_lk_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (17) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler_part1->fe_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (18) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00450, &profiler_part1->fe_process_count));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+
+ gcmkUPDATE_PROFILE_DATA_PART1(fe_draw_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(fe_out_vertex_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(fe_cache_miss_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(fe_cache_lk_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(fe_process_count);
+
+ /* SH */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->ps_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->ps_rendered_pixel_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->vs_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->vs_rendered_vertice_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->vs_branch_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->vs_texld_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->ps_branch_inst_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->ps_texld_inst_counter));
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (19) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->vs_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->vs_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->vs_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (21) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->vs_process_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (20) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->ps_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (17) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->ps_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (18) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->ps_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (22) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->ps_process_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->shader_cycle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (23) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->tx_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (24) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->tx_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (25) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->tx_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (26) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler_part1->tx_process_count));
+ }
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA_PART1(ps_inst_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ps_rendered_pixel_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(vs_inst_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(vs_rendered_vertice_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(vs_branch_inst_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(vs_texld_inst_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ps_branch_inst_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ps_texld_inst_counter, preNewProfiler_part1);
+ if (hasNewCounters)
+ {
+ gcmkRESET_PROFILE_DATA_PART1(vs_non_idle_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(vs_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(vs_stall_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(vs_process_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ps_non_idle_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ps_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ps_stall_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ps_process_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(shader_cycle_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(tx_non_idle_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(tx_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(tx_stall_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(tx_process_count, preNewProfiler_part1);
+ }
+#endif
+ gcmkUPDATE_PROFILE_DATA_PART1(ps_inst_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(ps_rendered_pixel_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(vs_inst_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(vs_rendered_vertice_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(vs_branch_inst_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(vs_texld_inst_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(ps_branch_inst_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(ps_texld_inst_counter);
+ if (hasNewCounters)
+ {
+ gcmkUPDATE_PROFILE_DATA_PART1(vs_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(vs_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(vs_stall_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(vs_process_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ps_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ps_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ps_stall_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ps_process_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(shader_cycle_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_stall_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_process_count);
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+));
+#endif
+
+ /* PA */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_input_vtx_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_input_prim_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_output_prim_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_depth_clipped_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_trivial_rejected_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_culled_prim_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_droped_prim_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_frustum_clipped_prim_counter));
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler_part1->pa_process_count));
+ }
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA_PART1(pa_input_vtx_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_input_prim_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_output_prim_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_depth_clipped_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_trivial_rejected_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_culled_prim_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_droped_prim_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_frustum_clipped_prim_counter, preNewProfiler_part1);
+ if (hasNewCounters)
+ {
+ gcmkRESET_PROFILE_DATA_PART1(pa_non_idle_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_stall_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(pa_process_count, preNewProfiler_part1);
+ }
+#endif
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_input_vtx_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_input_prim_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_output_prim_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_depth_clipped_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_trivial_rejected_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_culled_prim_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_droped_prim_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_frustum_clipped_prim_counter);
+ if (hasNewCounters)
+ {
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_stall_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(pa_process_count);
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+#endif
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_clipped_triangle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_clipped_line_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (17) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_culled_triangle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (18) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_culled_lines_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (19) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_trivial_rejected_line_count));
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_receive_triangle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_send_triangle_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_receive_lines_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_send_lines_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_process_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (20) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler_part1->se_non_idle_starve_count));
+ }
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))
+));
+
+ gcmkUPDATE_PROFILE_DATA_PART1(se_clipped_triangle_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_clipped_line_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_culled_triangle_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_culled_lines_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_trivial_rejected_line_count);
+ if (hasNewCounters)
+ {
+ gcmkUPDATE_PROFILE_DATA_PART1(se_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_stall_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_receive_triangle_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_send_triangle_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_receive_lines_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_send_lines_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_process_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(se_non_idle_starve_count);
+ }
+
+ /* RA */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_valid_pixel_count_to_render));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_total_quad_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_valid_quad_count_after_early_z));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_input_prim_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_pipe_cache_miss_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_prefetch_cache_miss_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_eez_culled_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (17) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_pipe_hz_cache_miss_counter));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (18) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_prefetch_hz_cache_miss_counter));
+ if (hasNewCounters)
+ {
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_non_idle_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_starve_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_stall_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler_part1->ra_process_count));
+ }
+#if USE_SW_RESET
+ gcmkRESET_PROFILE_DATA_PART1(ra_valid_pixel_count_to_render, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_total_quad_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_valid_quad_count_after_early_z, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_input_prim_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_pipe_cache_miss_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_prefetch_cache_miss_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_eez_culled_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_pipe_hz_cache_miss_counter, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_prefetch_hz_cache_miss_counter, preNewProfiler_part1);
+ if (hasNewCounters)
+ {
+ gcmkRESET_PROFILE_DATA_PART1(ra_non_idle_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_starve_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_stall_count, preNewProfiler_part1);
+ gcmkRESET_PROFILE_DATA_PART1(ra_process_count, preNewProfiler_part1);
+ }
+#endif
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_valid_pixel_count_to_render);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_total_quad_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_valid_quad_count_after_early_z);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_input_prim_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_pipe_cache_miss_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_prefetch_cache_miss_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_eez_culled_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_pipe_hz_cache_miss_counter);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_prefetch_hz_cache_miss_counter);
+ if (hasNewCounters)
+ {
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_non_idle_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_starve_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_stall_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(ra_process_count);
+ }
+#if !USE_SW_RESET
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+#endif
+
+ /* TX */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler_part1->tx_total_bilinear_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler_part1->tx_total_trilinear_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler_part1->tx_total_discarded_texture_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler_part1->tx_total_texture_requests));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler_part1->tx_mc0_miss_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler_part1->tx_mc0_request_byte_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler_part1->tx_mc1_miss_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler_part1->tx_mc1_request_byte_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+));
+
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_total_bilinear_requests);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_total_trilinear_requests);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_total_discarded_texture_requests);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_total_texture_requests);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_mc0_miss_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_mc0_request_byte_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_mc1_miss_count);
+ gcmkUPDATE_PROFILE_DATA_PART1(tx_mc1_request_byte_count);
+
+ /* MC */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_read_req_8B_from_colorpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_read_req_8B_sentout_from_colorpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_write_req_8B_from_colorpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_read_req_sentout_from_colorpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_write_req_from_colorpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_read_req_8B_from_depthpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_read_req_8B_sentout_from_depthpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_write_req_8B_from_depthpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_read_req_sentout_from_depthpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_write_req_from_depthpipe));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_read_req_8B_from_others));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_write_req_8B_from_others));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_read_req_from_others));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler_part2->mcc_total_write_req_from_others));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0)))
+));
+
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_read_req_8B_from_colorpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_read_req_8B_sentout_from_colorpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_write_req_8B_from_colorpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_read_req_sentout_from_colorpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_write_req_from_colorpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_read_req_8B_from_depthpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_read_req_8B_sentout_from_depthpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_write_req_8B_from_depthpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_read_req_sentout_from_depthpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_write_req_from_depthpipe);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_read_req_8B_from_others);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_write_req_8B_from_others);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_read_req_from_others);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_total_write_req_from_others);
+
+ /* read latency counters */
+ if (hasNewCounters)
+ {
+ /* latency */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0056C,
+ &mc_axi_max_min_latency));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00570,
+ &profiler_part2->mcc_axi_total_latency));
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00574,
+ &profiler_part2->mcc_axi_sample_count));
+
+ /* Reset Latency counters */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00568,
+ 0x10a));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00568,
+ 0xa));
+
+ profiler_part2->mcc_axi_min_latency = (mc_axi_max_min_latency & 0xffff0000) >> 16;
+ profiler_part2->mcc_axi_max_latency = (mc_axi_max_min_latency & 0x0000ffff);
+ if (profiler_part2->mcc_axi_min_latency == 4095)
+ profiler_part2->mcc_axi_min_latency = 0;
+
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_axi_min_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_axi_max_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_axi_total_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(mcc_axi_sample_count);
+ }
+
+ /* HI */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler_part2->hi0_axi_cycles_read_request_stalled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler_part2->hi0_axi_cycles_write_request_stalled));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler_part2->hi0_axi_cycles_write_data_stalled));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))
+));
+
+ gcmkUPDATE_PROFILE_DATA_PART2(hi0_axi_cycles_read_request_stalled);
+ gcmkUPDATE_PROFILE_DATA_PART2(hi0_axi_cycles_write_request_stalled);
+ gcmkUPDATE_PROFILE_DATA_PART2(hi0_axi_cycles_write_data_stalled);
+
+ /* L2 */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_total_axi0_read_request_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_total_axi0_write_request_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_total_axi1_write_request_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_total_read_transactions_request_by_axi0));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_total_read_transactions_request_by_axi1));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_total_write_transactions_request_by_axi0));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_total_write_transactions_request_by_axi1));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (16) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_axi0_minmax_latency));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (17) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_axi0_total_latency));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (18) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_axi0_total_request_count));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (19) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_axi1_minmax_latency));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (20) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_axi1_total_latency));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (21) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00564, &profiler_part2->l2_axi1_total_request_count));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) ));
+gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16)))
+));
+
+ profiler_part2->l2_axi0_min_latency = (profiler_part2->l2_axi0_minmax_latency & 0xffff0000) >> 16;
+ profiler_part2->l2_axi0_max_latency = (profiler_part2->l2_axi0_minmax_latency & 0x0000ffff);
+ profiler_part2->l2_axi1_min_latency = (profiler_part2->l2_axi0_minmax_latency & 0xffff0000) >> 16;
+ profiler_part2->l2_axi1_max_latency = (profiler_part2->l2_axi0_minmax_latency & 0x0000ffff);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_total_axi0_read_request_count);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_total_axi1_read_request_count);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_total_axi0_write_request_count);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_total_axi1_write_request_count);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_total_read_transactions_request_by_axi0);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_total_read_transactions_request_by_axi1);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_total_write_transactions_request_by_axi0);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_total_write_transactions_request_by_axi1);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_axi0_min_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_axi0_max_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_axi0_total_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_axi0_total_request_count);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_axi1_min_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_axi1_max_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_axi1_total_latency);
+ gcmkUPDATE_PROFILE_DATA_PART2(l2_axi1_total_request_count);
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ command->os, command->mutexContextSeq
+ ));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ gckOS_ReleaseMutex(
+ command->os, command->mutexContextSeq
+ );
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+gceSTATUS
+gckHARDWARE_InitProfiler(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 control;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &control));
+ /* Enable debug register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ?
+ 11:11) + 1))))))) << (0 ? 11:11)))));
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_ResetGPU(
+ IN gckHARDWARE Hardware,
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ gctUINT32 control, idle;
+ gceSTATUS status;
+
+ for (;;)
+ {
+ /* Disable clock gating. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ Hardware->powerBaseAddress +
+ 0x00104,
+ 0x00000000));
+
+ control = ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ?
+ 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ?
+ 17:17) + 1))))))) << (0 ? 17:17)));
+
+ /* Disable pulse-eater. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x0010C,
+ control));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x0010C,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)))));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x0010C,
+ control));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ?
+ 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9)))));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ 0x00000900));
+
+ /* Wait for clock being stable. */
+ gcmkONERROR(gckOS_Delay(Os, 1));
+
+ /* Isolate the GPU. */
+ control = ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ control));
+
+ /* Set soft reset. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Wait for reset. */
+ gcmkONERROR(gckOS_Delay(Os, 1));
+
+ /* Reset soft reset bit. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Reset GPU isolation. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ Core,
+ 0x00000,
+ control));
+
+ /* Read idle register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ Core,
+ 0x00004,
+ &idle));
+
+ if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
+ {
+ continue;
+ }
+
+ /* Read reset register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ Core,
+ 0x00000,
+ &control));
+
+ if (((((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) ) == 0)
+ || ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
+ )
+ {
+ continue;
+ }
+
+ /* GPU is idle. */
+ break;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return the error. */
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_Reset(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
+
+ /* Record context ID in debug register before reset. */
+ gcmkONERROR(gckHARDWARE_UpdateContextID(Hardware));
+
+ /* Hardware reset. */
+ status = gckOS_ResetGPU(Hardware->os, Hardware->core);
+
+ if (gcmIS_ERROR(status))
+ {
+ if (Hardware->identity.chipRevision < 0x4600)
+ {
+ /* Not supported - we need the isolation bit. */
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ /* Soft reset. */
+ gcmkONERROR(_ResetGPU(Hardware, Hardware->os, Hardware->core));
+ }
+
+ /* Force the command queue to reload the next context. */
+ Hardware->kernel->command->currContext = gcvNULL;
+
+ /* Initialize hardware. */
+ gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
+
+ /* Jump to address into which GPU should run if it doesn't stuck. */
+ gcmkONERROR(gckHARDWARE_Execute(Hardware, Hardware->kernel->restoreAddress, 16));
+
+ gcmkPRINT("[galcore]: recovery done");
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkPRINT("[galcore]: Hardware not reset successfully, give up");
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Test if we have a new Memory Controller. */
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_MC20))
+ {
+ /* No base address required. */
+ *BaseAddress = 0;
+ }
+ else
+ {
+ /* Get the base address from the OS. */
+ *BaseAddress = Hardware->baseAddress;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 State,
+ OUT gctBOOL_PTR NeedBase
+ )
+{
+ gctBOOL need = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x State=0x%08x", Hardware, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(NeedBase != gcvNULL);
+
+ /* Make sure this is a load state. */
+ if (((((gctUINT32) (State)) >> (0 ? 31:27) & ((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))))
+ {
+#if gcdENABLE_3D
+ /* Get the state address. */
+ switch ((((((gctUINT32) (State)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) ))
+ {
+ case 0x0596:
+ case 0x0597:
+ case 0x0599:
+ case 0x059A:
+ case 0x05A9:
+ /* These states need a TRUE physical address. */
+ need = gcvTRUE;
+ break;
+ }
+#else
+ /* 2D addresses don't need a base address. */
+#endif
+ }
+
+ /* Return the flag. */
+ *NeedBase = need;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*NeedBase=%d", *NeedBase);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_SetIsrManager(
+ IN gckHARDWARE Hardware,
+ IN gctISRMANAGERFUNC StartIsr,
+ IN gctISRMANAGERFUNC StopIsr,
+ IN gctPOINTER Context
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Hardware=0x%x, StartIsr=0x%x, StopIsr=0x%x, Context=0x%x",
+ Hardware, StartIsr, StopIsr, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (StartIsr == gcvNULL ||
+ StopIsr == gcvNULL)
+ {
+ status = gcvSTATUS_INVALID_ARGUMENT;
+
+ gcmkFOOTER();
+ return status;
+ }
+
+ Hardware->startIsr = StartIsr;
+ Hardware->stopIsr = StopIsr;
+ Hardware->isrContext = Context;
+
+ /* Success. */
+ gcmkFOOTER();
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Compose
+**
+** Start a composition.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Compose(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Size,
+ IN gctUINT8 EventID
+ )
+{
+#if gcdENABLE_3D
+ gceSTATUS status;
+ gctUINT32_PTR triggerState;
+
+ gcmkHEADER_ARG("Hardware=0x%x Physical=0x%x Logical=0x%x"
+ " Offset=%d Size=%d EventID=%d",
+ Hardware, Physical, Logical, Offset, Size, EventID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(((Size + 8) & 63) == 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Program the trigger state. */
+ triggerState = (gctUINT32_PTR) ((gctUINT8_PTR) Logical + Offset + Size);
+ triggerState[0] = 0x0C03;
+ triggerState[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:4) - (0 ?
+ 5:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:4) - (0 ? 5:4) + 1))))))) << (0 ?
+ 5:4))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 5:4) - (0 ? 5:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 5:4) - (0 ? 5:4) + 1))))))) << (0 ? 5:4)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:8) - (0 ?
+ 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ?
+ 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 24:24) - (0 ?
+ 24:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ?
+ 24:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 24:24) - (0 ?
+ 24:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 24:24) - (0 ? 24:24) + 1))))))) << (0 ?
+ 24:24)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ?
+ 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ?
+ 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ?
+ 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ?
+ 12:12)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:16) - (0 ?
+ 20:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:16) - (0 ? 20:16) + 1))))))) << (0 ?
+ 20:16))) | (((gctUINT32) ((gctUINT32) (EventID) & ((gctUINT32) ((((1 ?
+ 20:16) - (0 ? 20:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:16) - (0 ?
+ 20:16) + 1))))))) << (0 ? 20:16)))
+ ;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the wait/link. */
+ gcmkONERROR(gckOS_CacheClean(
+ Hardware->os, ProcessID, gcvNULL,
+ (gctUINT32)Physical, Logical, Offset + Size
+ ));
+#endif
+
+ /* Start composition. */
+ gcmkONERROR(gckOS_WriteRegisterEx(
+ Hardware->os, Hardware->core, 0x00554,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
+ ));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#else
+ /* Return the status. */
+ return gcvSTATUS_NOT_SUPPORTED;
+#endif
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_IsFeatureAvailable
+**
+** Verifies whether the specified feature is available in hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gceFEATURE Feature
+** Feature to be verified.
+*/
+gceSTATUS
+gckHARDWARE_IsFeatureAvailable(
+ IN gckHARDWARE Hardware,
+ IN gceFEATURE Feature
+ )
+{
+ gctBOOL available;
+
+ gcmkHEADER_ARG("Hardware=0x%x Feature=%d", Hardware, Feature);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ available = _QueryFeatureDatabase(Hardware, Feature);
+
+ /* Return result. */
+ gcmkFOOTER_ARG("%d", available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE);
+ return available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_DumpMMUException
+**
+** Dump the MMU debug info on an MMU exception.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_DumpMMUException(
+ IN gckHARDWARE Hardware
+ )
+{
+ gctUINT32 mmu = 0;
+ gctUINT32 mmuStatus = 0;
+ gctUINT32 address = 0;
+ gctUINT32 i = 0;
+ gctUINT32 mtlb = 0;
+ gctUINT32 stlb = 0;
+ gctUINT32 offset = 0;
+#if gcdPROCESS_ADDRESS_SPACE
+ gcsDATABASE_PTR database;
+#endif
+ gctUINT32 mmuStatusRegAddress;
+ gctUINT32 mmuExceptionAddress;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+#if gcdENABLE_TRUST_APPLICATION
+ if (Hardware->secureMode == gcvSECURE_IN_TA)
+ {
+ gcmkVERIFY_OK(gckKERNEL_SecurityDumpMMUException(Hardware->kernel));
+
+ gckMMU_DumpRecentFreedAddress(Hardware->kernel->mmu);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ else
+#endif
+ if (Hardware->secureMode == gcvSECURE_NONE)
+ {
+ mmuStatusRegAddress = 0x00188;
+ mmuExceptionAddress = 0x00190;
+ }
+ else
+ {
+ mmuStatusRegAddress = 0x00384;
+ mmuExceptionAddress = 0x00380;
+ }
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkPRINT("GPU[%d](ChipModel=0x%x ChipRevision=0x%x):\n",
+ Hardware->core,
+ Hardware->identity.chipModel,
+ Hardware->identity.chipRevision);
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("*** MMU ERROR DUMP ***\n");
+ gcmkPRINT("**************************\n");
+
+
+ gcmkVERIFY_OK(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ mmuStatusRegAddress,
+ &mmuStatus));
+
+ gcmkPRINT(" MMU status = 0x%08X\n", mmuStatus);
+
+ for (i = 0; i < 4; i += 1)
+ {
+ mmu = mmuStatus & 0xF;
+ mmuStatus >>= 4;
+
+ if (mmu == 0)
+ {
+ continue;
+ }
+
+ switch (mmu)
+ {
+ case 1:
+ gcmkPRINT(" MMU%d: slave not present\n", i);
+ break;
+
+ case 2:
+ gcmkPRINT(" MMU%d: page not present\n", i);
+ break;
+
+ case 3:
+ gcmkPRINT(" MMU%d: write violation\n", i);
+ break;
+
+ case 4:
+ gcmkPRINT(" MMU%d: out of bound", i);
+ break;
+
+ case 5:
+ gcmkPRINT(" MMU%d: read security violation", i);
+ break;
+
+ case 6:
+ gcmkPRINT(" MMU%d: write security violation", i);
+ break;
+
+ default:
+ gcmkPRINT(" MMU%d: unknown state\n", i);
+ }
+
+ gcmkVERIFY_OK(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ mmuExceptionAddress + i * 4,
+ &address));
+
+ mtlb = (address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+ stlb = (address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+ offset = address & gcdMMU_OFFSET_4K_MASK;
+
+ gcmkPRINT(" MMU%d: exception address = 0x%08X\n", i, address);
+
+ gcmkPRINT(" MTLB entry = %d\n", mtlb);
+
+ gcmkPRINT(" STLB entry = %d\n", stlb);
+
+ gcmkPRINT(" Offset = 0x%08X (%d)\n", offset, offset);
+
+ gckMMU_DumpPageTableEntry(Hardware->kernel->mmu, address);
+
+#if gcdPROCESS_ADDRESS_SPACE
+ for (i = 0; i < gcmCOUNTOF(Hardware->kernel->db->db); ++i)
+ {
+ for (database = Hardware->kernel->db->db[i];
+ database != gcvNULL;
+ database = database->next)
+ {
+ gcmkPRINT(" database [%d] :", database->processID);
+ gckMMU_DumpPageTableEntry(database->mmu, address);
+ }
+ }
+#endif
+
+ gckMMU_DumpRecentFreedAddress(Hardware->kernel->mmu);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_HandleFault(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+ gctUINT32 mmu, mmuStatus, address = gcvINVALID_ADDRESS, i = 0;
+ gctUINT32 mmuStatusRegAddress;
+ gctUINT32 mmuExceptionAddress;
+
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 entryValue;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ if (Hardware->secureMode == gcvSECURE_NONE)
+ {
+ mmuStatusRegAddress = 0x00188;
+ mmuExceptionAddress = 0x00190;
+ }
+ else
+ {
+ mmuStatusRegAddress = 0x00384;
+ mmuExceptionAddress = 0x00380;
+ }
+
+ /* Get MMU exception address. */
+#if gcdENABLE_TRUST_APPLICATION
+ if (Hardware->secureMode == gcvSECURE_IN_TA)
+ {
+ gckKERNEL_ReadMMUException(Hardware->kernel, &mmuStatus, &address);
+ }
+ else
+#endif
+ {
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ mmuStatusRegAddress,
+ &mmuStatus
+ ));
+
+ gcmkPRINT(" MMU status = 0x%08X\n", mmuStatus);
+
+ for (i = 0; i < 4; i += 1)
+ {
+ mmu = mmuStatus & 0xF;
+ mmuStatus >>= 4;
+
+ if (mmu == 0)
+ {
+ continue;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ mmuExceptionAddress + i * 4,
+ &address
+ ));
+
+ break;
+ }
+ }
+
+ if (address != gcvINVALID_ADDRESS)
+ {
+ address &= ~gcdMMU_PAGE_4K_MASK;
+
+ /* Try to allocate memory and setup map for exception address. */
+ gcmkONERROR(gckVIDMEM_FindVIDMEM(Hardware->kernel, address, &node, &entryValue));
+
+#if gcdENABLE_TRUST_APPLICATION
+ if (Hardware->secureMode == gcvSECURE_IN_TA)
+ {
+ gckKERNEL_HandleMMUException(
+ Hardware->kernel,
+ mmuStatus,
+ entryValue,
+ address
+ );
+ }
+ else
+#endif
+ {
+ gctUINT32_PTR entry;
+
+ /* Setup page table. */
+ gcmkONERROR(gckMMU_GetPageEntry(Hardware->kernel->mmu, address, &entry));
+
+ gckMMU_SetPage(Hardware->kernel->mmu, entryValue, gcvTRUE, entry);
+
+ /* Resume hardware execution. */
+ gcmkVERIFY_OK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ mmuExceptionAddress + i * 4,
+ *entry
+ ));
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_DumpGPUState
+**
+** Dump the GPU debug registers.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_DumpGPUState(
+ IN gckHARDWARE Hardware
+ )
+{
+ static gctCONST_STRING _cmdState[] =
+ {
+ "PAR_IDLE_ST", "PAR_DEC_ST", "PAR_ADR0_ST", "PAR_LOAD0_ST",
+ "PAR_ADR1_ST", "PAR_LOAD1_ST", "PAR_3DADR_ST", "PAR_3DCMD_ST",
+ "PAR_3DCNTL_ST", "PAR_3DIDXCNTL_ST", "PAR_INITREQDMA_ST",
+ "PAR_DRAWIDX_ST", "PAR_DRAW_ST", "PAR_2DRECT0_ST", "PAR_2DRECT1_ST",
+ "PAR_2DDATA0_ST", "PAR_2DDATA1_ST", "PAR_WAITFIFO_ST", "PAR_WAIT_ST",
+ "PAR_LINK_ST", "PAR_END_ST", "PAR_STALL_ST"
+ };
+
+ static gctCONST_STRING _cmdDmaState[] =
+ {
+ "CMD_IDLE_ST", "CMD_START_ST", "CMD_REQ_ST", "CMD_END_ST"
+ };
+
+ static gctCONST_STRING _cmdFetState[] =
+ {
+ "FET_IDLE_ST", "FET_RAMVALID_ST", "FET_VALID_ST"
+ };
+
+ static gctCONST_STRING _reqDmaState[] =
+ {
+ "REQ_IDLE_ST", "REQ_WAITIDX_ST", "REQ_CAL_ST"
+ };
+
+ static gctCONST_STRING _calState[] =
+ {
+ "CAL_IDLE_ST", "CAL_LDADR_ST", "CAL_IDXCALC_ST"
+ };
+
+ static gctCONST_STRING _veReqState[] =
+ {
+ "VER_IDLE_ST", "VER_CKCACHE_ST", "VER_MISS_ST"
+ };
+
+ static gcsiDEBUG_REGISTERS _dbgRegs[] =
+ {
+ { "RA", 0x474, 16, 0x448, 256, 0x1, 0x00 },
+ { "TX", 0x474, 24, 0x44C, 128, 0x1, 0x00 },
+ { "FE", 0x470, 0, 0x450, 256, 0x1, 0x00 },
+ { "PE", 0x470, 16, 0x454, 256, 0x3, 0x00 },
+ { "DE", 0x470, 8, 0x458, 256, 0x1, 0x00 },
+ { "SH", 0x470, 24, 0x45C, 256, 0x1, 0x00 },
+ { "PA", 0x474, 0, 0x460, 256, 0x1, 0x00 },
+ { "SE", 0x474, 8, 0x464, 256, 0x1, 0x00 },
+ { "MC", 0x478, 0, 0x468, 256, 0x3, 0x00 },
+ { "HI", 0x478, 8, 0x46C, 256, 0x1, 0x00 },
+ { "TPG", 0x474, 24, 0x44C, 32, 0x2, 0x80 },
+ { "TFB", 0x474, 24, 0x44C, 32, 0x2, 0xA0 },
+ { "USC", 0x474, 24, 0x44C, 64, 0x2, 0xC0 },
+ { "L2", 0x478, 0, 0x564, 256, 0x1, 0x00 },
+ { "BLT", 0x478, 24, 0x1A4, 256, 0x1, 0x00 }
+ };
+
+ static gctUINT32 _otherRegs[] =
+ {
+ 0x040, 0x044, 0x04C, 0x050, 0x054, 0x058, 0x05C, 0x060,
+ 0x43c, 0x440, 0x444, 0x414, 0x100
+ };
+
+ gceSTATUS status;
+ gckKERNEL kernel = gcvNULL;
+ gctUINT32 idle = 0, axi = 0;
+ gctUINT32 dmaAddress1 = 0, dmaAddress2 = 0;
+ gctUINT32 dmaState1 = 0, dmaState2 = 0;
+ gctUINT32 dmaLow = 0, dmaHigh = 0;
+ gctUINT32 cmdState = 0, cmdDmaState = 0, cmdFetState = 0;
+ gctUINT32 dmaReqState = 0, calState = 0, veReqState = 0;
+ gctUINT i;
+ gctUINT pipe = 0, pixelPipes = 0;
+ gctUINT32 control = 0, oldControl = 0;
+ gckOS os = Hardware->os;
+ gceCORE core = Hardware->core;
+
+ gcmkHEADER_ARG("Hardware=0x%X", Hardware);
+
+ kernel = Hardware->kernel;
+
+ gcmkPRINT_N(12, "GPU[%d](ChipModel=0x%x ChipRevision=0x%x):\n",
+ core,
+ Hardware->identity.chipModel,
+ Hardware->identity.chipRevision);
+
+ pixelPipes = Hardware->identity.pixelPipes
+ ? Hardware->identity.pixelPipes
+ : 1;
+
+ /* Reset register values. */
+ idle = axi =
+ dmaState1 = dmaState2 =
+ dmaAddress1 = dmaAddress2 =
+ dmaLow = dmaHigh = 0;
+
+ /* Verify whether DMA is running. */
+ gcmkONERROR(_VerifyDMA(
+ os, core, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
+ ));
+
+ cmdState = dmaState2 & 0x1F;
+ cmdDmaState = (dmaState2 >> 8) & 0x03;
+ cmdFetState = (dmaState2 >> 10) & 0x03;
+ dmaReqState = (dmaState2 >> 12) & 0x03;
+ calState = (dmaState2 >> 14) & 0x03;
+ veReqState = (dmaState2 >> 16) & 0x03;
+
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x00004, &idle));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x0000C, &axi));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x00668, &dmaLow));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x00668, &dmaLow));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x0066C, &dmaHigh));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x0066C, &dmaHigh));
+
+ gcmkPRINT_N(0, "**************************\n");
+ gcmkPRINT_N(0, "*** GPU STATE DUMP ***\n");
+ gcmkPRINT_N(0, "**************************\n");
+
+ gcmkPRINT_N(4, " axi = 0x%08X\n", axi);
+
+ gcmkPRINT_N(4, " idle = 0x%08X\n", idle);
+ if ((idle & 0x00000001) == 0) gcmkPRINT_N(0, " FE not idle\n");
+ if ((idle & 0x00000002) == 0) gcmkPRINT_N(0, " DE not idle\n");
+ if ((idle & 0x00000004) == 0) gcmkPRINT_N(0, " PE not idle\n");
+ if ((idle & 0x00000008) == 0) gcmkPRINT_N(0, " SH not idle\n");
+ if ((idle & 0x00000010) == 0) gcmkPRINT_N(0, " PA not idle\n");
+ if ((idle & 0x00000020) == 0) gcmkPRINT_N(0, " SE not idle\n");
+ if ((idle & 0x00000040) == 0) gcmkPRINT_N(0, " RA not idle\n");
+ if ((idle & 0x00000080) == 0) gcmkPRINT_N(0, " TX not idle\n");
+ if ((idle & 0x00000100) == 0) gcmkPRINT_N(0, " VG not idle\n");
+ if ((idle & 0x00000200) == 0) gcmkPRINT_N(0, " IM not idle\n");
+ if ((idle & 0x00000400) == 0) gcmkPRINT_N(0, " FP not idle\n");
+ if ((idle & 0x00000800) == 0) gcmkPRINT_N(0, " TS not idle\n");
+ if ((idle & 0x00001000) == 0) gcmkPRINT_N(0, " BL not idle\n");
+ if ((idle & 0x00002000) == 0) gcmkPRINT_N(0, " BP not idle\n");
+ if ((idle & 0x00004000) == 0) gcmkPRINT_N(0, " MC not idle\n");
+ if ((idle & 0x80000000) != 0) gcmkPRINT_N(0, " AXI low power mode\n");
+
+ if (
+ (dmaAddress1 == dmaAddress2)
+ && (dmaState1 == dmaState2)
+ )
+ {
+ gcmkPRINT_N(0, " DMA appears to be stuck at this address:\n");
+ gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1);
+ }
+ else
+ {
+ if (dmaAddress1 == dmaAddress2)
+ {
+ gcmkPRINT_N(0, " DMA address is constant, but state is changing:\n");
+ gcmkPRINT_N(4, " 0x%08X\n", dmaState1);
+ gcmkPRINT_N(4, " 0x%08X\n", dmaState2);
+ }
+ else
+ {
+ gcmkPRINT_N(0, " DMA is running; known addresses are:\n");
+ gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1);
+ gcmkPRINT_N(4, " 0x%08X\n", dmaAddress2);
+ }
+ }
+
+ gcmkPRINT_N(4, " dmaLow = 0x%08X\n", dmaLow);
+ gcmkPRINT_N(4, " dmaHigh = 0x%08X\n", dmaHigh);
+ gcmkPRINT_N(4, " dmaState = 0x%08X\n", dmaState2);
+ gcmkPRINT_N(8, " command state = %d (%s)\n", cmdState, _cmdState [cmdState]);
+ gcmkPRINT_N(8, " command DMA state = %d (%s)\n", cmdDmaState, _cmdDmaState[cmdDmaState]);
+ gcmkPRINT_N(8, " command fetch state = %d (%s)\n", cmdFetState, _cmdFetState[cmdFetState]);
+ gcmkPRINT_N(8, " DMA request state = %d (%s)\n", dmaReqState, _reqDmaState[dmaReqState]);
+ gcmkPRINT_N(8, " cal state = %d (%s)\n", calState, _calState [calState]);
+ gcmkPRINT_N(8, " VE request state = %d (%s)\n", veReqState, _veReqState [veReqState]);
+
+ gcmkPRINT_N(0, " Debug registers:\n");
+
+ for (i = 0; i < gcmCOUNTOF(_dbgRegs); i += 1)
+ {
+ gcmkONERROR(_DumpDebugRegisters(os, core, &_dbgRegs[i]));
+ }
+
+ /* Record control. */
+ gckOS_ReadRegisterEx(os, core, 0x0, &oldControl);
+
+ for (pipe = 0; pipe < pixelPipes; pipe++)
+ {
+ gcmkPRINT_N(4, " Other Registers[%d]:\n", pipe);
+
+ /* Switch pipe. */
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x0, &control));
+ control &= ~(0xF << 20);
+ control |= (pipe << 20);
+ gcmkONERROR(gckOS_WriteRegisterEx(os, core, 0x0, control));
+
+ for (i = 0; i < gcmCOUNTOF(_otherRegs); i += 1)
+ {
+ gctUINT32 read;
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, _otherRegs[i], &read));
+ gcmkPRINT_N(12, " [0x%04X] 0x%08X\n", _otherRegs[i], read);
+ }
+
+ if (Hardware->mmuVersion)
+ {
+ gcmkPRINT(" MMU status from MC[%d]:", pipe);
+
+ gckHARDWARE_DumpMMUException(Hardware);
+ }
+ }
+
+ /* Restore control. */
+ gcmkONERROR(gckOS_WriteRegisterEx(os, core, 0x0, oldControl));
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI0))
+ {
+ /* FE debug register. */
+ gcmkVERIFY_OK(_DumpLinkStack(os, core, &_dbgRegs[2]));
+ }
+
+ _DumpFEStack(os, core, &_dbgRegs[2]);
+
+ gcmkPRINT_N(0, "**************************\n");
+ gcmkPRINT_N(0, "***** SW COUNTERS *****\n");
+ gcmkPRINT_N(0, "**************************\n");
+ gcmkPRINT_N(4, " Execute Count = 0x%08X\n", Hardware->executeCount);
+ gcmkPRINT_N(4, " Execute Addr = 0x%08X\n", Hardware->lastExecuteAddress);
+ gcmkPRINT_N(4, " End Addr = 0x%08X\n", Hardware->lastEnd);
+
+ /* dump stack. */
+ gckOS_DumpCallStack(os);
+
+OnError:
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckHARDWARE_ReadPerformanceRegister(
+ IN gckHARDWARE Hardware,
+ IN gctUINT PerformanceAddress,
+ IN gctUINT IndexAddress,
+ IN gctUINT IndexShift,
+ IN gctUINT Index,
+ OUT gctUINT32_PTR Value
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x PerformanceAddress=0x%x IndexAddress=0x%x "
+ "IndexShift=%u Index=%u",
+ Hardware, PerformanceAddress, IndexAddress, IndexShift,
+ Index);
+
+ /* Write the index. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ IndexAddress,
+ Index << IndexShift));
+
+ /* Read the register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ PerformanceAddress,
+ Value));
+
+ /* Test for reset. */
+ if (Index == 15)
+ {
+ /* Index another register to get out of reset. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, IndexAddress, 0));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=0x%x", *Value);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetFrameInfo(
+ IN gckHARDWARE Hardware,
+ OUT gcsHAL_FRAME_INFO * FrameInfo
+ )
+{
+ gceSTATUS status;
+ gctUINT i, clock;
+ gcsHAL_FRAME_INFO info;
+#if gcdFRAME_DB_RESET
+ gctUINT reset;
+#endif
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Get profile tick. */
+ gcmkONERROR(gckOS_GetProfileTick(&info.ticks));
+
+ /* Read SH counters and reset them. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 4,
+ &info.shaderCycles));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 9,
+ &info.vsInstructionCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 12,
+ &info.vsTextureCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 7,
+ &info.psInstructionCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 14,
+ &info.psTextureCount));
+#if gcdFRAME_DB_RESET
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0045C,
+ 0x00470,
+ 24,
+ 15,
+ &reset));
+#endif
+
+ /* Read PA counters and reset them. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 3,
+ &info.vertexCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 4,
+ &info.primitiveCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 7,
+ &info.rejectedPrimitives));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 8,
+ &info.culledPrimitives));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 6,
+ &info.clippedPrimitives));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 5,
+ &info.outPrimitives));
+#if gcdFRAME_DB_RESET
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00460,
+ 0x00474,
+ 0,
+ 15,
+ &reset));
+#endif
+
+ /* Read RA counters and reset them. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 3,
+ &info.inPrimitives));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 11,
+ &info.culledQuadCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 1,
+ &info.totalQuadCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 2,
+ &info.quadCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 0,
+ &info.totalPixelCount));
+#if gcdFRAME_DB_RESET
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00448,
+ 0x00474,
+ 16,
+ 15,
+ &reset));
+#endif
+
+ /* Read TX counters and reset them. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 0,
+ &info.bilinearRequests));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 1,
+ &info.trilinearRequests));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 8,
+ &info.txHitCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 9,
+ &info.txMissCount));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 6,
+ &info.txBytes8));
+#if gcdFRAME_DB_RESET
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x0044C,
+ 0x00474,
+ 24,
+ 15,
+ &reset));
+#endif
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ /* Walk through all avaiable pixel pipes. */
+ for (i = 0; i < Hardware->identity.pixelPipes; ++i)
+ {
+ /* Select proper pipe. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20)))));
+
+ /* Read cycle registers. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ &info.cycles[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0007C,
+ &info.idleCycles[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00438,
+ &info.mcCycles[i]));
+
+ /* Read bandwidth registers. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0005C,
+ &info.readRequests[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &info.readBytes8[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00050,
+ &info.writeRequests[i]));
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &info.writeBytes8[i]));
+
+ /* Read PE counters. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 0,
+ &info.colorKilled[i]));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 2,
+ &info.colorDrawn[i]));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 1,
+ &info.depthKilled[i]));
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 3,
+ &info.depthDrawn[i]));
+ }
+
+ /* Zero out remaning reserved counters. */
+ for (; i < 8; ++i)
+ {
+ info.readBytes8[i] = 0;
+ info.writeBytes8[i] = 0;
+ info.cycles[i] = 0;
+ info.idleCycles[i] = 0;
+ info.mcCycles[i] = 0;
+ info.readRequests[i] = 0;
+ info.writeRequests[i] = 0;
+ info.colorKilled[i] = 0;
+ info.colorDrawn[i] = 0;
+ info.depthKilled[i] = 0;
+ info.depthDrawn[i] = 0;
+ }
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+
+ /* Reset cycle and bandwidth counters. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0003C,
+ 1));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0003C,
+ 0));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00078,
+ 0));
+
+#if gcdFRAME_DB_RESET
+ /* Reset PE counters. */
+ gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
+ Hardware,
+ 0x00454,
+ 0x00470,
+ 16,
+ 15,
+ &reset));
+#endif
+
+ /* Copy to user. */
+ gcmkONERROR(gckOS_CopyToUserData(Hardware->os,
+ &info,
+ FrameInfo,
+ gcmSIZEOF(info)));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_DumpGpuProfile(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctUINT clock, i;
+ gctUINT32 totalRead, totalWrite, read, write;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Read clock control register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ &clock));
+
+ totalRead = 0;
+ totalWrite = 0;
+
+ /* Walk through all avaiable pixel pipes. */
+ for (i = 0; i < Hardware->identity.pixelPipes; ++i)
+ {
+ /* Select proper pipe. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ?
+ 23:20) - (0 ? 23:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:20) - (0 ?
+ 23:20) + 1))))))) << (0 ? 23:20)))));
+
+ /* BW */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00040,
+ &read));
+ totalRead += read;
+
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00044,
+ &write));
+ totalWrite += write;
+ }
+
+ gcmkPRINT("==============GPU Profile: read request : %d\n", totalRead);
+ gcmkPRINT("==============GPU Profile: write request: %d\n", totalWrite);
+
+ /* Reset clock control register. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00000,
+ clock));
+ /* Reset counters. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdDVFS
+#define READ_FROM_EATER1 0
+
+gceSTATUS
+gckHARDWARE_QueryLoad(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32 * Load
+ )
+{
+ gctUINT32 debug1;
+ gceSTATUS status;
+ gcmkHEADER_ARG("Hardware=0x%X", Hardware);
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Load != gcvNULL);
+
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
+
+ if (Hardware->chipPowerState == gcvPOWER_ON)
+ {
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00110,
+ Load));
+#if READ_FROM_EATER1
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00134,
+ Load));
+#endif
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00114,
+ &debug1));
+
+ /* Patch result of 0x110 with result of 0x114. */
+ if ((debug1 & 0xFF) == 1)
+ {
+ *Load &= ~0xFF;
+ *Load |= 1;
+ }
+
+ if (((debug1 & 0xFF00) >> 8) == 1)
+ {
+ *Load &= ~(0xFF << 8);
+ *Load |= 1 << 8;
+ }
+
+ if (((debug1 & 0xFF0000) >> 16) == 1)
+ {
+ *Load &= ~(0xFF << 16);
+ *Load |= 1 << 16;
+ }
+
+ if (((debug1 & 0xFF000000) >> 24) == 1)
+ {
+ *Load &= ~(0xFF << 24);
+ *Load |= 1 << 24;
+ }
+ }
+ else
+ {
+ status = gcvSTATUS_INVALID_REQUEST;
+ }
+
+OnError:
+
+ gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetDVFSPeroid(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32 Frequency
+ )
+{
+ gceSTATUS status;
+ gctUINT32 period;
+ gctUINT32 eater;
+
+#if READ_FROM_EATER1
+ gctUINT32 period1;
+ gctUINT32 eater1;
+#endif
+
+ gcmkHEADER_ARG("Hardware=0x%X Frequency=%d", Hardware, Frequency);
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ period = 0;
+
+ while((64 << period) < (gcdDVFS_ANAYLSE_WINDOW * Frequency * 1000) )
+ {
+ period++;
+ }
+
+#if READ_FROM_EATER1
+ /*
+ * Peroid = F * 1000 * 1000 / (60 * 16 * 1024);
+ */
+ period1 = Frequency * 6250 / 6114;
+#endif
+
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
+
+ if (Hardware->chipPowerState == gcvPOWER_ON)
+ {
+ /* Get current configure. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ &eater));
+
+ /* Change peroid. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ ((((gctUINT32) (eater)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8))) | (((gctUINT32) ((gctUINT32) (period) & ((gctUINT32) ((((1 ? 15:8) - (0 ?
+ 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ?
+ 15:8)))));
+
+#if READ_FROM_EATER1
+ /* Config eater1. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00130,
+ &eater1));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x00130,
+ ((((gctUINT32) (eater1)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:16) - (0 ? 31:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:16) - (0 ?
+ 31:16) + 1))))))) << (0 ? 31:16))) | (((gctUINT32) ((gctUINT32) (period1) & ((gctUINT32) ((((1 ?
+ 31:16) - (0 ? 31:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:16) - (0 ?
+ 31:16) + 1))))))) << (0 ? 31:16)))));
+#endif
+ }
+ else
+ {
+ status = gcvSTATUS_INVALID_REQUEST;
+ }
+
+OnError:
+ gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_InitDVFS(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 data;
+
+ gcmkHEADER_ARG("Hardware=0x%X", Hardware);
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ &data));
+
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 18:18) - (0 ? 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 18:18) - (0 ?
+ 18:18) + 1))))))) << (0 ? 18:18))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 18:18) - (0 ? 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 18:18) - (0 ?
+ 18:18) + 1))))))) << (0 ? 18:18)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
+ 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
+ 20:20) + 1))))))) << (0 ? 20:20)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 23:23) - (0 ? 23:23) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:23) - (0 ?
+ 23:23) + 1))))))) << (0 ? 23:23))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 23:23) - (0 ? 23:23) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:23) - (0 ?
+ 23:23) + 1))))))) << (0 ? 23:23)));
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 22:22) - (0 ? 22:22) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 22:22) - (0 ?
+ 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 22:22) - (0 ? 22:22) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 22:22) - (0 ?
+ 22:22) + 1))))))) << (0 ? 22:22)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "DVFS Configure=0x%X",
+ data);
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
+ Hardware->core,
+ 0x0010C,
+ data));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckHARDWARE_PrepareFunctions
+**
+** Generate command buffer snippets which will be used by gckHARDWARE, by which
+** gckHARDWARE can manipulate GPU by FE command without using gckCOMMAND to avoid
+** race condition and deadlock.
+**
+** Notice:
+** 1. Each snippet can only be executed when GPU is idle.
+** 2. Execution is triggered by AHB (0x658)
+** 3. Each snippet followed by END so software can sync with GPU by checking GPU
+** idle
+** 4. It is transparent to gckCOMMAND command buffer.
+**
+** Existing Snippets:
+** 1. MMU Configure
+** For new MMU, after GPU is reset, FE execute this command sequence to enable MMU.
+*/
+gceSTATUS
+gckHARDWARE_PrepareFunctions(
+ gckHARDWARE Hardware
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gctUINT32 offset = 0;
+ gctUINT32 endBytes;
+ gctUINT32 flushBytes;
+ gctUINT8_PTR logical;
+ gctUINT32 address;
+ gcsHARDWARE_FUNCTION *function;
+ gceDUMMY_DRAW_TYPE dummyDrawType = gcvDUMMY_DRAW_INVALID;
+
+ gcmkHEADER_ARG("%x", Hardware);
+
+ os = Hardware->os;
+
+ gcmkVERIFY_OK(gckOS_GetPageSize(os, &Hardware->mmuFuncBytes));
+ Hardware->auxFuncBytes = Hardware->mmuFuncBytes;
+
+ gcmkONERROR(gckHARDWARE_End(
+ Hardware,
+ gcvNULL,
+ ~0U,
+ &endBytes
+ ));
+
+ if (Hardware->mmuVersion > 0)
+ {
+ gctUINT32 mmuBytes;
+ gctPHYS_ADDR_T physical = 0;
+
+ /* Allocate mmu command buffer within 32bit space */
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ os,
+ gcvFALSE,
+ &Hardware->mmuFuncBytes,
+ &Hardware->mmuFuncPhysical,
+ &Hardware->mmuFuncLogical
+ ));
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ os,
+ Hardware->mmuFuncLogical,
+ &physical
+ ));
+
+ if (physical & 0xFFFFFFFF00000000ULL)
+ {
+ gcmkFATAL("%s(%d): Command buffer physical address (0x%llx) for MMU setup exceeds 32bits",
+ __FUNCTION__, __LINE__, physical);
+ }
+
+ function = &Hardware->functions[gcvHARDWARE_FUNCTION_MMU];
+ function->logical = (gctUINT8_PTR)Hardware->mmuFuncLogical;
+ gcmkSAFECASTPHYSADDRT(function->address, physical);
+
+ gcmkONERROR(gckMMU_FillFlatMapping(
+ Hardware->kernel->mmu,
+ function->address,
+ Hardware->mmuFuncBytes
+ ));
+
+ gcmkONERROR(gckHARDWARE_SetMMUStates(
+ Hardware,
+ Hardware->kernel->mmu->mtlbLogical,
+ gcvMMU_MODE_4K,
+ Hardware->kernel->mmu->safePageLogical,
+ function->logical,
+ &mmuBytes
+ ));
+
+ function->endAddress = function->address + mmuBytes;
+ function->endLogical = function->logical + mmuBytes;
+
+ gcmkONERROR(gckHARDWARE_End(
+ Hardware,
+ function->endLogical,
+ function->endAddress,
+ &endBytes
+ ));
+
+ function->bytes = mmuBytes + endBytes;
+ }
+
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (Hardware->kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_AllocateVirtualCommandBuffer(
+ Hardware->kernel,
+ gcvFALSE,
+ &Hardware->auxFuncBytes,
+ &Hardware->auxFuncPhysical,
+ &Hardware->auxFuncLogical
+ ));
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Hardware->kernel,
+ Hardware->auxFuncLogical,
+ gcvFALSE,
+ Hardware->auxFuncPhysical,
+ &Hardware->auxFuncAddress
+ ));
+ }
+ else
+#endif
+ {
+ gctPHYS_ADDR_T physical = 0;
+
+ /* Allocate a command buffer. */
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ os,
+ gcvFALSE,
+ &Hardware->auxFuncBytes,
+ &Hardware->auxFuncPhysical,
+ &Hardware->auxFuncLogical
+ ));
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ os,
+ Hardware->auxFuncLogical,
+ &physical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(Hardware->auxFuncAddress, physical);
+
+ gcmkONERROR(gckMMU_FillFlatMapping(
+ Hardware->kernel->mmu,
+ Hardware->auxFuncAddress,
+ Hardware->auxFuncBytes
+ ));
+ }
+
+ /*
+ ** All cache flush command sequence.
+ */
+ function = &Hardware->functions[gcvHARDWARE_FUNCTION_FLUSH];
+
+ function->logical = logical = (gctUINT8_PTR)Hardware->auxFuncLogical + offset;
+
+ function->address = Hardware->auxFuncAddress + offset;
+
+ /* Get the size of the flush command. */
+ gcmkONERROR(gckHARDWARE_Flush(Hardware, gcvFLUSH_ALL, gcvNULL, &flushBytes));
+
+ /* Append a flush. */
+ gcmkONERROR(gckHARDWARE_Flush(Hardware, gcvFLUSH_ALL, logical, &flushBytes));
+
+ offset += flushBytes;
+
+ logical = (gctUINT8_PTR)Hardware->auxFuncLogical + offset;
+ address = Hardware->auxFuncAddress + offset;
+
+ gcmkONERROR(gckHARDWARE_End(Hardware, logical, address, &endBytes));
+
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (Hardware->kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Hardware->kernel,
+ logical,
+ gcvFALSE,
+ Hardware->auxFuncPhysical,
+ &Hardware->lastEnd
+ ));
+ }
+#endif
+
+ offset += endBytes;
+
+ function->bytes = flushBytes + endBytes;
+
+ function->endAddress = function->address + flushBytes;
+ function->endLogical = function->logical + flushBytes;
+
+ /*
+ ** BLT Engine event command
+ */
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BLT_ENGINE))
+ {
+ gctUINT8 i;
+ gctUINT32 eventBytes;
+
+ function = &Hardware->functions[gcvHARDWARE_FUNCTION_BLT_EVENT];
+
+ function->logical = logical = (gctUINT8_PTR)Hardware->auxFuncLogical + offset;
+ function->address = Hardware->auxFuncAddress + offset;
+
+ gcmkONERROR(gckHARDWARE_Event(Hardware, gcvNULL, 0, gcvKERNEL_BLT, &eventBytes));
+
+ for (i = 0; i < 29; i++)
+ {
+ gcmkONERROR(gckHARDWARE_Event(
+ Hardware,
+ logical + i * eventBytes,
+ i,
+ gcvKERNEL_BLT,
+ &eventBytes
+ ));
+
+ offset += eventBytes;
+ }
+
+ function->bytes = eventBytes * 29;
+ }
+
+ /************************************************************************************
+ * Dummy draw.
+ */
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_FE_NEED_DUMMYDRAW))
+ {
+ dummyDrawType = gcvDUMMY_DRAW_GC400;
+ }
+
+ if (!gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_USC_DEFER_FILL_FIX) &&
+ gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_USC))
+ {
+ dummyDrawType = gcvDUMMY_DRAW_V60;
+ }
+
+ if (dummyDrawType != gcvDUMMY_DRAW_INVALID)
+ {
+ gctUINT32 dummyDrawBytes;
+
+ function = &Hardware->functions[gcvHARDWARE_FUNCTION_DUMMY_DRAW];
+
+ function->logical = logical = (gctUINT8_PTR)Hardware->auxFuncLogical + offset;
+ function->address = Hardware->auxFuncAddress + offset;
+
+ /* Append a dummy draw. */
+ gcmkONERROR(gckHARDWARE_DummyDraw(Hardware, logical, function->address, dummyDrawType, &dummyDrawBytes));
+
+ offset += dummyDrawBytes;
+
+ logical += dummyDrawBytes;
+ address = function->address + dummyDrawBytes;
+
+ gcmkONERROR(gckHARDWARE_End(Hardware, logical, address, &endBytes));
+
+ offset += endBytes;
+
+ function->endAddress = function->address + dummyDrawBytes;
+ function->endLogical = function->logical + dummyDrawBytes;
+
+ function->bytes = dummyDrawBytes + endBytes;
+ }
+ gcmkASSERT(offset < Hardware->auxFuncBytes)
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_DestroyFunctions(
+ gckHARDWARE Hardware
+ )
+{
+ gcmkHEADER_ARG("%x", Hardware);
+
+ if (Hardware->auxFuncPhysical)
+ {
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (Hardware->kernel->virtualCommandBuffer)
+ {
+ gcmkVERIFY_OK(gckKERNEL_FreeVirtualMemory(
+ Hardware->auxFuncPhysical,
+ Hardware->auxFuncLogical,
+ gcvFALSE
+ ));
+ }
+ else
+#endif
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ Hardware->os,
+ Hardware->auxFuncBytes,
+ Hardware->auxFuncPhysical,
+ Hardware->auxFuncLogical
+ ));
+ }
+ }
+
+ if (Hardware->mmuFuncPhysical)
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ Hardware->os,
+ Hardware->mmuFuncBytes,
+ Hardware->mmuFuncPhysical,
+ Hardware->mmuFuncLogical
+ ));
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_ExecuteFunctions(
+ IN gckHARDWARE Hardware,
+ IN gceHARDWARE_FUNCTION Function
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle;
+ gctUINT32 timer = 0, delay = 1;
+ gcsHARDWARE_FUNCTION * function = &Hardware->functions[Function];
+ gctUINT32 address = function->address - Hardware->baseAddress;
+
+ /* Execute prepared command sequence. */
+ gcmkONERROR(gckHARDWARE_Execute(
+ Hardware,
+ address,
+ function->bytes
+ ));
+
+#if gcdLINK_QUEUE_SIZE
+ {
+ gcuQUEUEDATA data;
+
+ gcmkVERIFY_OK(gckOS_GetProcessID(&data.linkData.pid));
+
+ data.linkData.start = address;
+ data.linkData.end = address + function->bytes;
+ data.linkData.linkLow = 0;
+ data.linkData.linkHigh = 0;
+
+ gckQUEUE_Enqueue(&Hardware->linkQueue, &data);
+ }
+#endif
+
+ gcmkDUMPCOMMAND(
+ Hardware->os,
+ function->logical,
+ function->bytes,
+ gceDUMP_BUFFER_KERNEL,
+ gcvTRUE
+ );
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.execute]");
+#endif
+
+ /* Wait until GPU idle. */
+ do
+ {
+ gckOS_Delay(Hardware->os, delay);
+
+ gcmkONERROR(gckOS_ReadRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x00004,
+ &idle));
+
+ timer += delay;
+ delay *= 2;
+
+#if gcdGPU_TIMEOUT
+ if (timer >= Hardware->kernel->timeOut)
+ {
+ gckHARDWARE_DumpGPUState(Hardware);
+ gckCOMMAND_DumpExecutingBuffer(Hardware->kernel->command);
+
+ /* Even if hardware is not reset correctly, let software
+ ** continue to avoid software stuck. Software will timeout again
+ ** and try to recover GPU in next timeout.
+ */
+ gcmkONERROR(gcvSTATUS_DEVICE);
+ }
+#endif
+ }
+ while (!_IsGPUIdle(idle));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_AddressInHardwareFuncions(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gctPOINTER *Pointer
+ )
+{
+ if (Address >= Hardware->auxFuncAddress && Address <= Hardware->auxFuncAddress - 1 + Hardware->auxFuncBytes)
+ {
+ *Pointer = (gctUINT8_PTR)Hardware->auxFuncLogical
+ + (Address - Hardware->auxFuncAddress)
+ ;
+
+ return gcvSTATUS_OK;
+ }
+
+ return gcvSTATUS_NOT_FOUND;
+}
+
+gceSTATUS
+gckHARDWARE_QueryStateTimer(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT64_PTR Start,
+ OUT gctUINT64_PTR End,
+ OUT gctUINT64_PTR On,
+ OUT gctUINT64_PTR Off,
+ OUT gctUINT64_PTR Idle,
+ OUT gctUINT64_PTR Suspend
+ )
+{
+ gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
+
+ gckSTATETIMER_Query(
+ &Hardware->powerStateTimer, Hardware->chipPowerState, Start, End, On, Off, Idle, Suspend);
+
+ gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_WaitFence(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT64 FenceData,
+ IN gctUINT32 FenceAddress,
+ OUT gctUINT32 *Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR)Logical;
+
+ gctUINT32 dataLow = (gctUINT32)FenceData;
+ gctUINT32 dataHigh = (gctUINT32)(FenceData >> 32);
+
+ if (logical)
+ {
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E26) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++
+ = dataHigh;
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x01FA) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *logical++
+ = dataLow;
+
+ *logical++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x0F & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (Hardware->waitCount) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 17:16) - (0 ? 17:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:16) - (0 ?
+ 17:16) + 1))))))) << (0 ? 17:16))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ?
+ 17:16) - (0 ? 17:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:16) - (0 ?
+ 17:16) + 1))))))) << (0 ? 17:16)));
+
+ *logical++
+ = FenceAddress;
+ }
+ else
+ {
+ *Bytes = 6 * gcmSIZEOF(gctUINT32);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_UpdateContextID(
+ IN gckHARDWARE Hardware
+ )
+{
+ static gcsiDEBUG_REGISTERS fe = { "FE", 0x470, 0, 0x450, 256, 0x1, 0x00 };
+ gckOS os = Hardware->os;
+ gceCORE core = Hardware->core;
+ gctUINT32 contextIDLow, contextIDHigh;
+ gceSTATUS status;
+
+ gcmkONERROR(gckOS_WriteRegisterEx(os, core, fe.index, 0x53 << fe.shift));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, fe.data, &contextIDLow));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(os, core, fe.index, 0x54 << fe.shift));
+ gcmkONERROR(gckOS_ReadRegisterEx(os, core, fe.data, &contextIDHigh));
+
+ Hardware->contextID = ((gctUINT64)contextIDHigh << 32) + contextIDLow;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckFE_Initialize(
+ IN gckHARDWARE Hardware,
+ OUT gckFE FE
+ )
+{
+ gceSTATUS status;
+ gctUINT32 data;
+
+ gcmkHEADER();
+
+ gckOS_ZeroMemory(FE, gcmSIZEOF(gcsFE));
+
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x007E4,
+ &data
+ ));
+
+ gcmkONERROR(gckOS_AtomConstruct(Hardware->os, &FE->freeDscriptors));
+
+ data = (((((gctUINT32) (data)) >> (0 ? 6:0)) & ((gctUINT32) ((((1 ? 6:0) - (0 ? 6:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:0) - (0 ? 6:0) + 1)))))) );
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, _GC_OBJ_ZONE, "free descriptor=%d", data);
+
+ gcmkONERROR(gckOS_AtomSet(Hardware->os, FE->freeDscriptors, data));
+
+ /* Enable interrupts. */
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x000D8, ~0U);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ if (FE->freeDscriptors)
+ {
+ gckOS_AtomDestroy(Hardware->os, FE->freeDscriptors);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+void
+gckFE_UpdateAvaiable(
+ IN gckHARDWARE Hardware,
+ OUT gckFE FE
+ )
+{
+ gctUINT32 data;
+ gctINT32 oldValue;
+
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x007E4,
+ &data
+ ));
+
+ data = (((((gctUINT32) (data)) >> (0 ? 6:0)) & ((gctUINT32) ((((1 ? 6:0) - (0 ? 6:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:0) - (0 ? 6:0) + 1)))))) );
+
+ while (data--)
+ {
+ gckOS_AtomIncrement(Hardware->os, FE->freeDscriptors, &oldValue);
+ }
+}
+
+gceSTATUS
+gckFE_ReserveSlot(
+ IN gckHARDWARE Hardware,
+ IN gckFE FE,
+ OUT gctBOOL * Available
+ )
+{
+ gctINT32 oldValue;
+
+ gckOS_AtomDecrement(Hardware->os, FE->freeDscriptors, &oldValue);
+
+ if (oldValue > 0)
+ {
+ /* Get one slot. */
+ *Available = gcvTRUE;
+ }
+ else
+ {
+ /* No available slot, restore decreased one.*/
+ gckOS_AtomIncrement(Hardware->os, FE->freeDscriptors, &oldValue);
+ *Available = gcvFALSE;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+void
+gckFE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gckFE FE,
+ IN gcsFEDescriptor * Desc
+ )
+{
+ gckOS_WriteRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x007DC,
+ Desc->start
+ );
+
+ gckOS_MemoryBarrier(
+ Hardware->os,
+ gcvNULL
+ );
+
+ gckOS_WriteRegisterEx(
+ Hardware->os,
+ Hardware->core,
+ 0x007E0,
+ Desc->end
+ );
+}
+
+gceSTATUS
+gckHARDWARE_DummyDraw(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gceDUMMY_DRAW_TYPE DummyDrawType,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT32 dummyDraw_gc400[] = {
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0193) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0x000000,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0194) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0180) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ?
+ 3:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ?
+ 3:0))) | (((gctUINT32) (0x8 & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:12) - (0 ?
+ 13:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ?
+ 13:12))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 13:12) - (0 ?
+ 13:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ?
+ 13:12)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ?
+ 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ?
+ 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ?
+ 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ?
+ 23:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ?
+ 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ?
+ 31:24))) | (((gctUINT32) ((gctUINT32) (4 * gcmSIZEOF(float)) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1))))))) << (0 ? 31:24)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ?
+ 7:7) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ?
+ 7:7))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E05) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0202) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0208) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0201) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0204) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 5:0) - (0 ?
+ 5:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:0) - (0 ? 5:0) + 1))))))) << (0 ?
+ 5:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x1000) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0x0, 0x0, 0x0, 0x0,
+ 0xDEADDEAD,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0203) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:0) - (0 ?
+ 6:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:0) - (0 ? 6:0) + 1))))))) << (0 ?
+ 6:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:0) - (0 ?
+ 6:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:0) - (0 ? 6:0) + 1))))))) << (0 ?
+ 6:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x020E) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0200) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 1,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x020C) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0x000F003F,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x028C) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ?
+ 11:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ?
+ 11:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:8) - (0 ?
+ 11:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ?
+ 11:8))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0500) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x028D) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 13:12) - (0 ?
+ 13:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ?
+ 13:12))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 13:12) - (0 ? 13:12) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 13:12) - (0 ? 13:12) + 1))))))) << (0 ? 13:12)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:8) - (0 ?
+ 9:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:8) - (0 ? 9:8) + 1))))))) << (0 ?
+ 9:8))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 9:8) - (0 ? 9:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 9:8) - (0 ? 9:8) + 1))))))) << (0 ? 9:8)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:16) - (0 ?
+ 17:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:16) - (0 ? 17:16) + 1))))))) << (0 ?
+ 17:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 17:16) - (0 ? 17:16) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 17:16) - (0 ? 17:16) + 1))))))) << (0 ? 17:16))),
+
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0300) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0301) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0302) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0303) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ 0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0289) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ?
+ 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ?
+ 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ?
+ 3:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ?
+ 3:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x05 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ?
+ 3:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ?
+ 3:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:0) - (0 ?
+ 23:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:0) - (0 ? 23:0) + 1))))))) << (0 ?
+ 23:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:0) - (0 ?
+ 23:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:0) - (0 ? 23:0) + 1))))))) << (0 ?
+ 23:0))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:0) - (0 ?
+ 23:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:0) - (0 ? 23:0) + 1))))))) << (0 ?
+ 23:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:0) - (0 ?
+ 23:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:0) - (0 ? 23:0) + 1))))))) << (0 ?
+ 23:0))),
+ };
+
+ gctUINT32 dummyDraw_v60[] = {
+
+ /* Semaphore from FE to PE. */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ?
+ 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))),
+
+ /* Stall from FE to PE. */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ?
+ 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x021A) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (0x0) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E06) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) ((gctUINT32) (0x0) & ((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 14:12) - (0 ? 14:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 14:12) - (0 ?
+ 14:12) + 1))))))) << (0 ? 14:12))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 14:12) - (0 ? 14:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 14:12) - (0 ?
+ 14:12) + 1))))))) << (0 ? 14:12)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 17:16) - (0 ? 17:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:16) - (0 ?
+ 17:16) + 1))))))) << (0 ? 17:16))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 17:16) - (0 ? 17:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:16) - (0 ?
+ 17:16) + 1))))))) << (0 ? 17:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 7:4) - (0 ? 7:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:4) - (0 ? 7:4) + 1))))))) << (0 ?
+ 7:4))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:4) - (0 ?
+ 7:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:4) - (0 ? 7:4) + 1))))))) << (0 ?
+ 7:4))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0401) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 0x0,
+ 0x2,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ (gctUINT32)~0x0,
+
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x020C) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 0xffffffff,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E07) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 2,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E08) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 2,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0420) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:0) - (0 ?
+ 2:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:0) - (0 ? 2:0) + 1))))))) << (0 ?
+ 2:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 2:0) - (0 ?
+ 2:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:0) - (0 ? 2:0) + 1))))))) << (0 ?
+ 2:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0424) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 1,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0403) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 3,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E21) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:0) - (0 ?
+ 2:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:0) - (0 ? 2:0) + 1))))))) << (0 ?
+ 2:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 2:0) - (0 ? 2:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 2:0) - (0 ? 2:0) + 1))))))) << (0 ? 2:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x040A) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x2000) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1 << 2) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 0x07801033,0x3fc00900,0x00000040,0x00390008,
+ (gctUINT32)~0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x021F) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 0x0,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0240) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:4) - (0 ? 6:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:4) - (0 ? 6:4) + 1))))))) << (0 ?
+ 6:4))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 6:4) - (0 ? 6:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 6:4) - (0 ? 6:4) + 1))))))) << (0 ? 6:4)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 8:8) - (0 ? 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 26:24) - (0 ? 26:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:24) - (0 ?
+ 26:24) + 1))))))) << (0 ? 26:24))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ?
+ 26:24) - (0 ? 26:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:24) - (0 ?
+ 26:24) + 1))))))) << (0 ? 26:24))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0241) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (31) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:16) - (0 ? 31:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:16) - (0 ?
+ 31:16) + 1))))))) << (0 ? 31:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:16) - (0 ? 31:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:16) - (0 ?
+ 31:16) + 1))))))) << (0 ? 31:16))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0244) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:0) - (0 ?
+ 9:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:0) - (0 ? 9:0) + 1))))))) << (0 ?
+ 9:0))) | (((gctUINT32) ((gctUINT32) (31) & ((gctUINT32) ((((1 ? 9:0) - (0 ?
+ 9:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:0) - (0 ? 9:0) + 1))))))) << (0 ?
+ 9:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:16) - (0 ? 31:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:16) - (0 ?
+ 31:16) + 1))))))) << (0 ? 31:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 31:16) - (0 ? 31:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:16) - (0 ?
+ 31:16) + 1))))))) << (0 ? 31:16))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0247) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+
+ (32+(4*(((gcsFEATURE_DATABASE *)Hardware->featureDatabase)->NumShaderCores)-1))/(4*(((gcsFEATURE_DATABASE *)Hardware->featureDatabase)->NumShaderCores)),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0248) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ 1,
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ?
+ 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))),
+
+ /* Semaphore from FE to PE. */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ?
+ 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))),
+
+ /* Stall from FE to PE. */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))),
+
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ?
+ 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))),
+
+ /* Invalidate I cache.*/
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x022C) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))),
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ?
+ 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ?
+ 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ?
+ 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ?
+ 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))),
+ };
+
+ gctUINT32 bytes = 0;
+ gctUINT32_PTR dummyDraw = gcvNULL;
+
+
+ switch(DummyDrawType)
+ {
+ case gcvDUMMY_DRAW_GC400:
+ dummyDraw = dummyDraw_gc400;
+ bytes = gcmSIZEOF(dummyDraw_gc400);
+ *(dummyDraw + 1) = Address;
+ break;
+ case gcvDUMMY_DRAW_V60:
+ dummyDraw = dummyDraw_v60;
+ bytes = gcmSIZEOF(dummyDraw_v60);
+ break;
+ default:
+ /* other chip no need dummy draw.*/
+ gcmkASSERT(0);
+ break;
+ };
+
+ if (Logical != gcvNULL)
+ {
+ gckOS_MemCopy(Logical, dummyDraw, bytes);
+ }
+
+ *Bytes = bytes;
+
+ return gcvSTATUS_OK;
+}
+
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
new file mode 100644
index 000000000000..0d7275b300c1
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
@@ -0,0 +1,365 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_hardware_h_
+#define __gc_hal_kernel_hardware_h_
+
+#if gcdENABLE_VG
+#include "gc_hal_kernel_hardware_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ gcvHARDWARE_FUNCTION_MMU,
+ gcvHARDWARE_FUNCTION_FLUSH,
+
+ /* BLT engine command sequence. */
+ gcvHARDWARE_FUNCTION_BLT_EVENT,
+ gcvHARDWARE_FUNCTION_DUMMY_DRAW,
+ gcvHARDWARE_FUNCTION_NUM,
+}
+gceHARDWARE_FUNCTION;
+
+
+typedef struct _gcsHARWARE_FUNCTION
+{
+ /* Entry of the function. */
+ gctUINT32 address;
+
+ /* CPU address of the function. */
+ gctUINT8_PTR logical;
+
+ /* Bytes of the function. */
+ gctUINT32 bytes;
+
+ /* Hardware address of END in this function. */
+ gctUINT32 endAddress;
+
+ /* Logical of END in this function. */
+ gctUINT8_PTR endLogical;
+}
+gcsHARDWARE_FUNCTION;
+
+typedef struct _gcsSTATETIMER
+{
+ gctUINT64 start;
+ gctUINT64 recent;
+
+ /* Elapse of each power state. */
+ gctUINT64 elapse[4];
+}
+gcsSTATETIMER;
+
+typedef struct _gcsHARDWARE_SIGNATURE
+{
+ /* Chip model. */
+ gceCHIPMODEL chipModel;
+
+ /* Revision value.*/
+ gctUINT32 chipRevision;
+
+ /* Supported feature fields. */
+ gctUINT32 chipFeatures;
+
+ /* Supported minor feature fields. */
+ gctUINT32 chipMinorFeatures;
+
+ /* Supported minor feature 1 fields. */
+ gctUINT32 chipMinorFeatures1;
+
+ /* Supported minor feature 2 fields. */
+ gctUINT32 chipMinorFeatures2;
+}
+gcsHARDWARE_SIGNATURE;
+
+typedef struct _gcsMMU_TABLE_ARRAY_ENTRY
+{
+ gctUINT32 low;
+ gctUINT32 high;
+}
+gcsMMU_TABLE_ARRAY_ENTRY;
+
+typedef struct _gcsHARDWARE_PAGETABLE_ARRAY
+{
+ /* Number of entries in page table array. */
+ gctUINT num;
+
+ /* Size in bytes of array. */
+ gctSIZE_T size;
+
+ /* Physical address of array. */
+ gctPHYS_ADDR_T address;
+
+ /* Memory descriptor. */
+ gctPHYS_ADDR physical;
+
+ /* Logical address of array. */
+ gctPOINTER logical;
+}
+gcsHARDWARE_PAGETABLE_ARRAY;
+
+/* gckHARDWARE object. */
+struct _gckHARDWARE
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gctKERNEL object. */
+ gckKERNEL kernel;
+
+ /* Pointer to gctOS object. */
+ gckOS os;
+
+ /* Core */
+ gceCORE core;
+
+ /* Chip characteristics. */
+ gcsHAL_QUERY_CHIP_IDENTITY identity;
+ gctBOOL allowFastClear;
+ gctBOOL allowCompression;
+ gctUINT32 powerBaseAddress;
+ gctBOOL extraEventStates;
+
+ /* Big endian */
+ gctBOOL bigEndian;
+
+ /* Base address. */
+ gctUINT32 baseAddress;
+
+ /* Chip status */
+ gctPOINTER powerMutex;
+ gctUINT32 powerProcess;
+ gctUINT32 powerThread;
+ gceCHIPPOWERSTATE chipPowerState;
+ gctUINT32 lastWaitLink;
+ gctUINT32 lastEnd;
+ gctBOOL clockState;
+ gctBOOL powerState;
+ gctPOINTER globalSemaphore;
+
+ gctISRMANAGERFUNC startIsr;
+ gctISRMANAGERFUNC stopIsr;
+ gctPOINTER isrContext;
+
+ gctUINT32 mmuVersion;
+
+ /* Whether use new MMU. It is meaningless
+ ** for old MMU since old MMU is always enabled.
+ */
+ gctBOOL enableMMU;
+
+ /* Type */
+ gceHARDWARE_TYPE type;
+
+#if gcdPOWEROFF_TIMEOUT
+ gctUINT32 powerOffTime;
+ gctUINT32 powerOffTimeout;
+ gctPOINTER powerOffTimer;
+#endif
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ gctUINT32 powerOnFscaleVal;
+#endif
+ gctPOINTER pageTableDirty;
+
+#if gcdLINK_QUEUE_SIZE
+ struct _gckQUEUE linkQueue;
+#endif
+
+ gctBOOL powerManagement;
+ gctBOOL gpuProfiler;
+
+ gctBOOL stallFEPrefetch;
+
+ gctUINT32 minFscaleValue;
+ gctUINT waitCount;
+
+ gctPOINTER pendingEvent;
+
+ /* Function used by gckHARDWARE. */
+ gctPHYS_ADDR mmuFuncPhysical;
+ gctPOINTER mmuFuncLogical;
+ gctSIZE_T mmuFuncBytes;
+
+ gctPHYS_ADDR auxFuncPhysical;
+ gctPOINTER auxFuncLogical;
+ gctUINT32 auxFuncAddress;
+ gctSIZE_T auxFuncBytes;
+
+ gcsHARDWARE_FUNCTION functions[gcvHARDWARE_FUNCTION_NUM];
+
+ gcsSTATETIMER powerStateTimer;
+ gctUINT32 executeCount;
+ gctUINT32 lastExecuteAddress;
+
+ /* Head for hardware list in gckMMU. */
+ gcsLISTHEAD mmuHead;
+
+ gctPOINTER featureDatabase;
+
+ gcsHARDWARE_SIGNATURE signature;
+
+ gctUINT32 maxOutstandingReads;
+
+ gcsHARDWARE_PAGETABLE_ARRAY pagetableArray;
+
+ gceSECURE_MODE secureMode;
+
+ gctUINT64 contextID;
+};
+
+typedef struct _gcsFEDescriptor
+{
+ gctUINT32 start;
+ gctUINT32 end;
+}
+gcsFEDescriptor;
+
+typedef struct _gcsFE * gckFE;
+typedef struct _gcsFE
+{
+ gckOS os;
+
+ /* Number of free descriptors. */
+ gctPOINTER freeDscriptors;
+}
+gcsFE;
+
+gceSTATUS
+gckFE_Initialize(
+ IN gckHARDWARE Hardware,
+ OUT gckFE FE
+ );
+
+gceSTATUS
+gckFE_ReserveSlot(
+ IN gckHARDWARE Hardware,
+ IN gckFE FE,
+ OUT gctBOOL * Available
+ );
+
+void
+gckFE_UpdateAvaiable(
+ IN gckHARDWARE Hardware,
+ OUT gckFE FE
+ );
+
+void
+gckFE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gckFE FE,
+ IN gcsFEDescriptor * Desc
+ );
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 State,
+ OUT gctBOOL_PTR NeedBase
+ );
+
+gceSTATUS
+gckHARDWARE_GetFrameInfo(
+ IN gckHARDWARE Hardware,
+ OUT gcsHAL_FRAME_INFO * FrameInfo
+ );
+
+gceSTATUS
+gckHARDWARE_DumpGpuProfile(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_HandleFault(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_ExecuteFunctions(
+ IN gckHARDWARE Hardware,
+ IN gceHARDWARE_FUNCTION Function
+ );
+
+gceSTATUS
+gckHARDWARE_DummyDraw(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gceDUMMY_DRAW_TYPE DummyDrawType,
+ IN OUT gctUINT32 * Bytes
+ );
+
+#define gcmkWRITE_MEMORY(logical, data) \
+ do { \
+ gcmkVERIFY_OK(gckOS_WriteMemory(os, logical, data)); \
+ logical++; \
+ }\
+ while (0) ; \
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c
new file mode 100644
index 000000000000..e4380a4bc280
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_recorder.c
@@ -0,0 +1,728 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_context.h"
+
+/*
+ * -----------------------
+ * HARDWARE STATE RECORDER
+ * -----------------------
+ *
+ * State mirror buffer is used to 'mirror' hardware states since hardware
+ * states can't be dumpped. It is a context buffer which stores 'global'
+ * context.
+ *
+ * For each commit, state recorder
+ * 1) Records context buffer (if there is) and command buffers in this commit.
+ * 2) Parse those buffers to estimate the state changed.
+ * 3) Stores result to a mirror buffer.
+ *
+ * == Commit 0 ====================================================================
+ *
+ * Context Buffer 0
+ *
+ * Command Buffer 0
+ *
+ * Mirror Buffer 0 <- Context Buffer 0 + Command Buffer 0
+ *
+ * == Commit 1 ====================================================================
+ *
+ * Command Buffer 1
+ *
+ * Mirror Buffer 1 <- Command buffer 1 + Mirror Buffer 0
+ *
+ * == Commit 2 ====================================================================
+ *
+ * Context Buffer 2 (optional)
+ *
+ * Command Buffer 2
+ *
+ * Mirror Buffer 2 <- Command buffer 2 + Context Buffer 2 + Mirror Buffer 1
+ *
+ * == Commit N ====================================================================
+ *
+ * For Commit N, these buffers are needed to reproduce hardware's behavior in
+ * this commit.
+ *
+ * Mirror Buffer [N - 1] : State Mirror accumlated by past commits,
+ * which is used to restore hardware state.
+ * Context Buffer [N] :
+ * Command Buffer [N] : Command buffer executed by hardware in this commit.
+ *
+ * If sequence of states programming matters, hardware's behavior can't be reproduced,
+ * but the state values stored in mirror buffer are assuring.
+ */
+
+/* Queue size. */
+#define gcdNUM_RECORDS 6
+
+typedef struct _gcsPARSER_HANDLER * gckPARSER_HANDLER;
+
+typedef void
+(*HandlerFunction)(
+ IN gckPARSER_HANDLER Handler,
+ IN gctUINT32 Addr,
+ IN gctUINT32 Data
+ );
+
+typedef struct _gcsPARSER_HANDLER
+{
+ gctUINT32 type;
+ gctUINT32 cmd;
+ gctPOINTER private;
+ HandlerFunction function;
+}
+gcsPARSER_HANDLER;
+
+typedef struct _gcsPARSER * gckPARSER;
+typedef struct _gcsPARSER
+{
+ gctUINT8_PTR currentCmdBufferAddr;
+
+ /* Current command. */
+ gctUINT32 lo;
+ gctUINT32 hi;
+
+ gctUINT8 cmdOpcode;
+ gctUINT16 cmdAddr;
+ gctUINT32 cmdSize;
+ gctUINT32 cmdRectCount;
+ gctUINT8 skip;
+ gctUINT32 skipCount;
+
+ gctBOOL allow;
+ gctBOOL stop;
+
+ /* Callback used by parser to handle a command. */
+ gckPARSER_HANDLER commandHandler;
+}
+gcsPARSER;
+
+typedef struct _gcsMIRROR
+{
+ gctUINT32_PTR logical[gcdNUM_RECORDS];
+ gctUINT32 bytes;
+ gcsSTATE_MAP_PTR map;
+ gctSIZE_T maxState;
+}
+gcsMIRROR;
+
+typedef struct _gcsDELTA
+{
+ gctUINT64 commitStamp;
+ gctUINT32_PTR command;
+ gctUINT32 commandBytes;
+ gctUINT32_PTR context;
+ gctUINT32 contextBytes;
+}
+gcsDELTA;
+
+typedef struct _gcsRECORDER
+{
+ gckOS os;
+ gcsMIRROR mirror;
+ gcsDELTA deltas[gcdNUM_RECORDS];
+
+ /* Index of current record. */
+ gctUINT index;
+
+ /* Number of records. */
+ gctUINT num;
+
+ /* Plugin used by gckPARSER. */
+ gcsPARSER_HANDLER recorderHandler;
+ gckPARSER parser;
+}
+gcsRECORDER;
+
+
+/******************************************************************************\
+***************************** Command Buffer Parser ****************************
+\******************************************************************************/
+
+/*
+** Command buffer parser checks command buffer in FE's view to make sure there
+** is no format error.
+**
+** Parser provide a callback mechnisam, so plug-in can be added to implement
+** other functions.
+*/
+
+static void
+_HandleLoadState(
+ IN OUT gckPARSER Parser
+ )
+{
+ gctUINT i;
+ gctUINT32_PTR data = (gctUINT32_PTR)Parser->currentCmdBufferAddr;
+ gctUINT32 cmdAddr = Parser->cmdAddr;
+
+ if (Parser->commandHandler == gcvNULL
+ || Parser->commandHandler->cmd != 0x01
+ )
+ {
+ /* No handler for this command. */
+ return;
+ }
+
+ for (i = 0; i < Parser->cmdSize; i++)
+ {
+ Parser->commandHandler->function(Parser->commandHandler, cmdAddr, *data);
+
+ /* Advance to next state. */
+ cmdAddr++;
+ data++;
+ }
+}
+
+static void
+_GetCommand(
+ IN OUT gckPARSER Parser
+ )
+{
+ gctUINT32 * buffer = (gctUINT32 *)Parser->currentCmdBufferAddr;
+
+ gctUINT16 cmdRectCount;
+ gctUINT16 cmdDataCount;
+
+ Parser->hi = buffer[0];
+ Parser->lo = buffer[1];
+
+ Parser->cmdOpcode = (((((gctUINT32) (Parser->hi)) >> (0 ? 31:27)) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) );
+ Parser->cmdRectCount = 1;
+
+ switch (Parser->cmdOpcode)
+ {
+ case 0x01:
+ /* Extract count. */
+ Parser->cmdSize = (((((gctUINT32) (Parser->hi)) >> (0 ? 25:16)) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1)))))) );
+ if (Parser->cmdSize == 0)
+ {
+ /* 0 means 1024. */
+ Parser->cmdSize = 1024;
+ }
+ Parser->skip = (Parser->cmdSize & 0x1) ? 0 : 1;
+
+ /* Extract address. */
+ Parser->cmdAddr = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) );
+
+ Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 4;
+ Parser->skipCount = Parser->cmdSize + Parser->skip;
+ break;
+
+ case 0x05:
+ Parser->cmdSize = 4;
+ Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
+ break;
+
+ case 0x06:
+ Parser->cmdSize = 5;
+ Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
+ break;
+
+ case 0x0C:
+ Parser->cmdSize = 3;
+ Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
+ break;
+
+ case 0x09:
+ Parser->cmdSize = 2;
+ Parser->cmdAddr = 0x0F16;
+ Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
+ break;
+
+ case 0x04:
+ Parser->cmdSize = 1;
+ Parser->cmdAddr = 0x0F06;
+
+ cmdRectCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
+ cmdDataCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 26:16)) & ((gctUINT32) ((((1 ? 26:16) - (0 ? 26:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:16) - (0 ? 26:16) + 1)))))) );
+
+ Parser->skipCount = gcmALIGN(Parser->cmdSize, 2)
+ + cmdRectCount * 2
+ + gcmALIGN(cmdDataCount, 2);
+
+ Parser->cmdRectCount = cmdRectCount;
+ break;
+
+ case 0x03:
+ Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
+ Parser->skipCount = 0;
+ break;
+
+ case 0x02:
+ Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
+ Parser->skipCount = 0;
+ break;
+
+ case 0x07:
+ Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
+ Parser->skipCount = 0;
+ break;
+
+ case 0x08:
+ /* Commands after LINK isn't executed, skip them. */
+ Parser->stop = gcvTRUE;
+ break;
+
+ default:
+ /* Unknown command is a risk. */
+ Parser->allow = gcvFALSE;
+ break;
+ }
+}
+
+static void
+_ParseCommand(
+ IN OUT gckPARSER Parser
+ )
+{
+ switch(Parser->cmdOpcode)
+ {
+ case 0x01:
+ _HandleLoadState(Parser);
+ break;
+ case 0x05:
+ case 0x06:
+ case 0x0C:
+ break;
+ case 0x04:
+ break;
+ default:
+ break;
+ }
+
+ /* Advance to next command. */
+ Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr
+ + (Parser->skipCount << 2);
+}
+
+gceSTATUS
+gckPARSER_Parse(
+ IN gckPARSER Parser,
+ IN gctUINT8_PTR Buffer,
+ IN gctUINT32 Bytes
+ )
+{
+ gckPARSER parser = Parser;
+ gctUINT8_PTR end = (gctUINT8_PTR)Buffer + Bytes;
+
+ /* Initialize parser. */
+ parser->currentCmdBufferAddr = (gctUINT8_PTR)Buffer;
+ parser->skip = 0;
+ parser->allow = gcvTRUE;
+ parser->stop = gcvFALSE;
+
+ /* Go through command buffer until reaching the end
+ ** or meeting an error. */
+ do
+ {
+ _GetCommand(parser);
+
+ _ParseCommand(parser);
+ }
+ while ((parser->currentCmdBufferAddr < end)
+ && (parser->allow == gcvTRUE)
+ && (parser->stop == gcvFALSE)
+ );
+
+ if (parser->allow == gcvFALSE)
+ {
+ /* Error detected. */
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckPARSER_RegisterCommandHandler
+**
+** Register a command handler which will be called when parser get a command.
+**
+*/
+gceSTATUS
+gckPARSER_RegisterCommandHandler(
+ IN gckPARSER Parser,
+ IN gckPARSER_HANDLER Handler
+ )
+{
+ Parser->commandHandler = Handler;
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckPARSER_Construct(
+ IN gckOS Os,
+ IN gckPARSER_HANDLER Handler,
+ OUT gckPARSER * Parser
+ )
+{
+ gceSTATUS status;
+ gckPARSER pointer;
+
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsPARSER), (gctPOINTER *)&pointer));
+
+ /* Put it here temp, should have a more general plug-in mechnisam. */
+ pointer->commandHandler = Handler;
+
+ *Parser = pointer;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+void
+gckPARSER_Destroy(
+ IN gckOS Os,
+ IN gckPARSER Parser
+ )
+{
+ gcmkOS_SAFE_FREE(Os, Parser);
+}
+
+/******************************************************************************\
+**************************** Hardware States Recorder **************************
+\******************************************************************************/
+
+static void
+_RecodeState(
+ IN gckPARSER_HANDLER Handler,
+ IN gctUINT32 Addr,
+ IN gctUINT32 Data
+ )
+{
+ gcmkVERIFY_OK(gckRECORDER_UpdateMirror(Handler->private, Addr, Data));
+}
+
+static gctUINT
+_Previous(
+ IN gctUINT Index
+ )
+{
+ if (Index == 0)
+ {
+ return gcdNUM_RECORDS - 1;
+ }
+
+ return Index - 1;
+}
+
+static gctUINT
+_Next(
+ IN gctUINT Index
+ )
+{
+ return (Index + 1) % gcdNUM_RECORDS;
+}
+
+gceSTATUS
+gckRECORDER_Construct(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ OUT gckRECORDER * Recorder
+ )
+{
+ gceSTATUS status;
+ gckCONTEXT context = gcvNULL;
+ gckRECORDER recorder = gcvNULL;
+ gctSIZE_T mapSize;
+ gctUINT i;
+ gctBOOL virtualCommandBuffer = Hardware->kernel->virtualCommandBuffer;
+
+ /* MMU is not ready now. */
+ Hardware->kernel->virtualCommandBuffer = gcvFALSE;
+
+ gcmkONERROR(gckCONTEXT_Construct(Os, Hardware, 0, &context));
+
+ /* Restore. */
+ Hardware->kernel->virtualCommandBuffer = virtualCommandBuffer;
+
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsRECORDER), (gctPOINTER *)&recorder));
+
+ gckOS_ZeroMemory(recorder, gcmSIZEOF(gcsRECORDER));
+
+ /* Copy state map. */
+ recorder->mirror.maxState = context->maxState;
+
+ mapSize = context->maxState * gcmSIZEOF(gcsSTATE_MAP);
+
+ gcmkONERROR(gckOS_Allocate(Os, mapSize, (gctPOINTER *)&recorder->mirror.map));
+
+ gckOS_MemCopy(recorder->mirror.map, context->map, mapSize);
+
+ /* Copy context buffer. */
+ recorder->mirror.bytes = context->totalSize;
+
+ for (i = 0; i < gcdNUM_RECORDS; i++)
+ {
+ gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->mirror.logical[i]));
+ gckOS_MemCopy(recorder->mirror.logical[i], context->buffer->logical, context->totalSize);
+ }
+
+ for (i = 0; i < gcdNUM_RECORDS; i++)
+ {
+ gcmkONERROR(gckOS_Allocate(Os, gcdCMD_BUFFER_SIZE, (gctPOINTER *)&recorder->deltas[i].command));
+ gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->deltas[i].context));
+ }
+
+ recorder->index = 0;
+ recorder->num = 0;
+
+ /* Initialize Parser plugin. */
+ recorder->recorderHandler.cmd = 0x01;
+ recorder->recorderHandler.private = recorder;
+ recorder->recorderHandler.function = _RecodeState;
+
+ gcmkONERROR(gckPARSER_Construct(Os, &recorder->recorderHandler, &recorder->parser));
+
+ recorder->os = Os;
+
+ *Recorder = recorder;
+
+ gckCONTEXT_Destroy(context);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (context)
+ {
+ gckCONTEXT_Destroy(context);
+ }
+
+ if (recorder)
+ {
+ gckRECORDER_Destory(Os, recorder);
+ }
+
+ return status;
+}
+
+gceSTATUS
+gckRECORDER_Destory(
+ IN gckOS Os,
+ IN gckRECORDER Recorder
+ )
+{
+ gctUINT i;
+
+ if (Recorder->mirror.map)
+ {
+ gcmkOS_SAFE_FREE(Os, Recorder->mirror.map);
+ }
+
+ for (i = 0; i < gcdNUM_RECORDS; i++)
+ {
+ if (Recorder->mirror.logical[i])
+ {
+ gcmkOS_SAFE_FREE(Os, Recorder->mirror.logical[i]);
+ }
+ }
+
+ for (i = 0; i < gcdNUM_RECORDS; i++)
+ {
+ if (Recorder->deltas[i].command)
+ {
+ gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].command);
+ }
+
+ if (Recorder->deltas[i].context)
+ {
+ gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].context);
+ }
+ }
+
+ if (Recorder->parser)
+ {
+ gckPARSER_Destroy(Os, Recorder->parser);
+ }
+
+ gcmkOS_SAFE_FREE(Os, Recorder);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckRECORDER_UpdateMirror(
+ IN gckRECORDER Recorder,
+ IN gctUINT32 State,
+ IN gctUINT32 Data
+ )
+{
+ gctUINT32 index;
+ gcsSTATE_MAP_PTR map = Recorder->mirror.map;
+ gctUINT32_PTR buffer = Recorder->mirror.logical[Recorder->index];
+
+ if (State >= Recorder->mirror.maxState)
+ {
+ /* Ignore them just like HW does. */
+ return gcvSTATUS_OK;
+ }
+
+ index = map[State].index;
+
+ if (index)
+ {
+ buffer[index] = Data;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+void
+gckRECORDER_AdvanceIndex(
+ IN gckRECORDER Recorder,
+ IN gctUINT64 CommitStamp
+ )
+{
+ /* Get next record. */
+ gctUINT next = (Recorder->index + 1) % gcdNUM_RECORDS;
+
+ /* Record stamp of this commit. */
+ Recorder->deltas[Recorder->index].commitStamp = CommitStamp;
+
+ /* Mirror of next record is mirror of this record and delta in next record. */
+ gckOS_MemCopy(Recorder->mirror.logical[next],
+ Recorder->mirror.logical[Recorder->index], Recorder->mirror.bytes);
+
+ /* Advance to next record. */
+ Recorder->index = next;
+
+ Recorder->num = gcmMIN(Recorder->num + 1, gcdNUM_RECORDS - 1);
+
+
+ /* Reset delta. */
+ Recorder->deltas[Recorder->index].commandBytes = 0;
+ Recorder->deltas[Recorder->index].contextBytes = 0;
+}
+
+void
+gckRECORDER_Record(
+ IN gckRECORDER Recorder,
+ IN gctUINT8_PTR CommandBuffer,
+ IN gctUINT32 CommandBytes,
+ IN gctUINT8_PTR ContextBuffer,
+ IN gctUINT32 ContextBytes
+ )
+{
+ gcsDELTA * delta = &Recorder->deltas[Recorder->index];
+
+ if (CommandBytes != 0xFFFFFFFF)
+ {
+ gckPARSER_Parse(Recorder->parser, CommandBuffer, CommandBytes);
+ gckOS_MemCopy(delta->command, CommandBuffer, CommandBytes);
+ delta->commandBytes = CommandBytes;
+ }
+
+ if (ContextBytes != 0xFFFFFFFF)
+ {
+ gckPARSER_Parse(Recorder->parser, ContextBuffer, ContextBytes);
+ gckOS_MemCopy(delta->context, ContextBuffer, ContextBytes);
+ delta->contextBytes = ContextBytes;
+ }
+}
+
+void
+gckRECORDER_Dump(
+ IN gckRECORDER Recorder
+ )
+{
+ gctUINT last = Recorder->index;
+ gctUINT previous;
+ gctUINT i;
+ gcsMIRROR *mirror = &Recorder->mirror;
+ gcsDELTA *delta;
+ gckOS os = Recorder->os;
+
+ for (i = 0; i < Recorder->num; i++)
+ {
+ last = _Previous(last);
+ }
+
+ for (i = 0; i < Recorder->num; i++)
+ {
+ delta = &Recorder->deltas[last];
+
+ /* Dump record */
+ gcmkPRINT("#[commit %llu]", delta->commitStamp);
+
+ if (delta->commitStamp)
+ {
+ previous = _Previous(last);
+
+ gcmkPRINT("#[mirror]");
+ gckOS_DumpBuffer(os, mirror->logical[previous], mirror->bytes, gceDUMP_BUFFER_CONTEXT, gcvTRUE);
+ gcmkPRINT("@[kernel.execute]");
+ }
+
+ if (delta->contextBytes)
+ {
+ gckOS_DumpBuffer(os, delta->context, delta->contextBytes, gceDUMP_BUFFER_CONTEXT, gcvTRUE);
+ gcmkPRINT("@[kernel.execute]");
+ }
+
+ gckOS_DumpBuffer(os, delta->command, delta->commandBytes, gceDUMP_BUFFER_USER, gcvTRUE);
+ gcmkPRINT("@[kernel.execute]");
+
+ last = _Next(last);
+ }
+}
+
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c
new file mode 100644
index 000000000000..04a994425e69
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.c
@@ -0,0 +1,1192 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+
+#if gcdENABLE_VG
+
+#include "gc_hal_kernel_hardware_command_vg.h"
+
+#define _GC_OBJ_ZONE gcvZONE_COMMAND
+
+/******************************************************************************\
+****************************** gckVGCOMMAND API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_InitializeInfo
+**
+** Initialize architecture dependent command buffer information.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to the Command object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVGCOMMAND_InitializeInfo(
+ IN gckVGCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ do
+ {
+ /* Reset interrupts. */
+ Command->info.feBufferInt = -1;
+ Command->info.tsOverflowInt = -1;
+
+ /* Set command buffer attributes. */
+ Command->info.addressAlignment = 64;
+ Command->info.commandAlignment = 8;
+
+ /* Determine command alignment address mask. */
+ Command->info.addressMask = ((((gctUINT32) (Command->info.addressAlignment - 1)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) ((gctUINT32) (0 ) & ((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0)));
+
+ /* Query the number of bytes needed by the STATE command. */
+ gcmkERR_BREAK(gckVGCOMMAND_StateCommand(
+ Command, 0x0, gcvNULL, (gctUINT32)~0, 0,
+ &Command->info.stateCommandSize
+ ));
+
+ /* Query the number of bytes needed by the RESTART command. */
+ gcmkERR_BREAK(gckVGCOMMAND_RestartCommand(
+ Command, gcvNULL, (gctUINT32)~0, 0,
+ &Command->info.restartCommandSize
+ ));
+
+ /* Query the number of bytes needed by the FETCH command. */
+ gcmkERR_BREAK(gckVGCOMMAND_FetchCommand(
+ Command, gcvNULL, (gctUINT32)~0, 0,
+ &Command->info.fetchCommandSize
+ ));
+
+ /* Query the number of bytes needed by the CALL command. */
+ gcmkERR_BREAK(gckVGCOMMAND_CallCommand(
+ Command, gcvNULL, (gctUINT32)~0, 0,
+ &Command->info.callCommandSize
+ ));
+
+ /* Query the number of bytes needed by the RETURN command. */
+ gcmkERR_BREAK(gckVGCOMMAND_ReturnCommand(
+ Command, gcvNULL,
+ &Command->info.returnCommandSize
+ ));
+
+ /* Query the number of bytes needed by the EVENT command. */
+ gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
+ Command, gcvNULL, gcvBLOCK_PIXEL, -1,
+ &Command->info.eventCommandSize
+ ));
+
+ /* Query the number of bytes needed by the END command. */
+ gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+ Command, gcvNULL, -1,
+ &Command->info.endCommandSize
+ ));
+
+ /* Determine the tail reserve size. */
+ Command->info.staticTailSize = gcmMAX(
+ Command->info.fetchCommandSize,
+ gcmMAX(
+ Command->info.returnCommandSize,
+ Command->info.endCommandSize
+ )
+ );
+
+ /* Determine the maximum tail size. */
+ Command->info.dynamicTailSize
+ = Command->info.staticTailSize
+ + Command->info.eventCommandSize * gcvBLOCK_COUNT;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_StateCommand
+**
+** Append a STATE command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctUINT32 Pipe
+** Harwdare destination pipe.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** STATE command at or gcvNULL to query the size of the command.
+**
+** gctUINT32 Address
+** Starting register address of the state buffer.
+** If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctUINT32 Count
+** Number of states in state buffer.
+** If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the STATE command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the STATE command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_StateCommand(
+ IN gckVGCOMMAND Command,
+ IN gctUINT32 Pipe,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gctUINT32 Count,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Pipe=0x%x Logical=0x%x Address=0x%x Count=0x%x Bytes = 0x%x",
+ Command, Pipe, Logical, Address, Count, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append STATE. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 11:0) - (0 ? 11:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ?
+ 11:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 11:0) - (0 ?
+ 11:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ?
+ 11:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 27:16) - (0 ? 27:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 27:16) - (0 ?
+ 27:16) + 1))))))) << (0 ? 27:16))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ?
+ 27:16) - (0 ? 27:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 27:16) - (0 ?
+ 27:16) + 1))))))) << (0 ? 27:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 13:12) - (0 ? 13:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:12) - (0 ?
+ 13:12) + 1))))))) << (0 ? 13:12))) | (((gctUINT32) ((gctUINT32) (Pipe) & ((gctUINT32) ((((1 ?
+ 13:12) - (0 ? 13:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:12) - (0 ?
+ 13:12) + 1))))))) << (0 ? 13:12)))
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the STATE command. */
+ *Bytes = 4 * (Count + 1);
+ }
+ }
+ else
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append LOAD_STATE. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (Address) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the STATE command. */
+ *Bytes = 4 * (Count + 1);
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_RestartCommand
+**
+** Form a RESTART command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** RESTART command at or gcvNULL to query the size of the command.
+**
+** gctUINT32 FetchAddress
+** The address of another command buffer to be executed by this RESTART
+** command. If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctUINT FetchCount
+** The number of 64-bit data quantities in another command buffer to
+** be executed by this RESTART command. If 'Logical' is gcvNULL, this
+** argument is ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the RESTART command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the RESTART command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_RestartCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+ Command, Logical, FetchAddress, FetchCount, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+ gctUINT32 beginEndMark;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Determine Begin/End flag. */
+ beginEndMark = (FetchCount > 0)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 24:24) - (0 ? 24:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 24:24) - (0 ?
+ 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 24:24) - (0 ? 24:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 24:24) - (0 ?
+ 24:24) + 1))))))) << (0 ? 24:24)))
+ : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 24:24) - (0 ? 24:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 24:24) - (0 ?
+ 24:24) + 1))))))) << (0 ? 24:24))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 24:24) - (0 ? 24:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 24:24) - (0 ?
+ 24:24) + 1))))))) << (0 ? 24:24)));
+
+ /* Append RESTART. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x9 & ((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 20:0) - (0 ? 20:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ?
+ 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ?
+ 20:0) - (0 ? 20:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ?
+ 20:0)))
+ | beginEndMark
+ );
+
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[1],
+ FetchAddress
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the RESTART command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_FetchCommand
+**
+** Form a FETCH command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** FETCH command at or gcvNULL to query the size of the command.
+**
+** gctUINT32 FetchAddress
+** The address of another command buffer to be executed by this FETCH
+** command. If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctUINT FetchCount
+** The number of 64-bit data quantities in another command buffer to
+** be executed by this FETCH command. If 'Logical' is gcvNULL, this
+** argument is ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the FETCH command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the FETCH command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_FetchCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+ Command, Logical, FetchAddress, FetchCount, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append FETCH. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x5 & ((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 20:0) - (0 ? 20:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ?
+ 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ?
+ 20:0) - (0 ? 20:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ?
+ 20:0)))
+ );
+
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[1],
+ gcmkFIXADDRESS(FetchAddress)
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the FETCH command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append LINK. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ );
+
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[1],
+ gcmkFIXADDRESS(FetchAddress)
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the LINK command. */
+ *Bytes = 8;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_CallCommand
+**
+** Append a CALL command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** CALL command at or gcvNULL to query the size of the command.
+**
+** gctUINT32 FetchAddress
+** The address of another command buffer to be executed by this CALL
+** command. If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gctUINT FetchCount
+** The number of 64-bit data quantities in another command buffer to
+** be executed by this CALL command. If 'Logical' is gcvNULL, this
+** argument is ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the CALL command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the CALL command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_CallCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x FetchAddress=0x%x FetchCount=0x%x Bytes = 0x%x",
+ Command, Logical, FetchAddress, FetchCount, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append CALL. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x6 & ((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 20:0) - (0 ? 20:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ?
+ 20:0))) | (((gctUINT32) ((gctUINT32) (FetchCount) & ((gctUINT32) ((((1 ?
+ 20:0) - (0 ? 20:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:0) - (0 ? 20:0) + 1))))))) << (0 ?
+ 20:0)))
+ );
+
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[1],
+ gcmkFIXADDRESS(FetchAddress)
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the CALL command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_ReturnCommand
+**
+** Append a RETURN command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to an gckVGCOMMAND object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** RETURN command at or gcvNULL to query the size of the command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the RETURN command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the RETURN command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_ReturnCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x Bytes = 0x%x",
+ Command, Logical, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append RETURN. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x7 & ((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28)))
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the RETURN command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_EventCommand
+**
+** Form an EVENT command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to the Command object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** EVENT command at or gcvNULL to query the size of the command.
+**
+** gctINT32 InterruptId
+** The ID of the interrupt to generate.
+** If 'Logical' is gcvNULL, this argument is ignored.
+**
+** gceBLOCK Block
+** Block that will generate the interrupt.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the EVENT command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the END command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_EventCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gceBLOCK Block,
+ IN gctINT32 InterruptId,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x Block=0x%x InterruptId=0x%x Bytes = 0x%x",
+ Command, Logical, Block, InterruptId, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ typedef struct _gcsEVENTSTATES
+ {
+ /* Chips before VG21 use these values. */
+ gctUINT eventFromFE;
+ gctUINT eventFromPE;
+
+ /* VG21 chips and later use SOURCE field. */
+ gctUINT eventSource;
+ }
+ gcsEVENTSTATES;
+
+ static gcsEVENTSTATES states[] =
+ {
+ /* gcvBLOCK_COMMAND */
+ {
+ (gctUINT)~0,
+ (gctUINT)~0,
+ (gctUINT)~0
+ },
+
+ /* gcvBLOCK_TESSELLATOR */
+ {
+ 0x0,
+ 0x1,
+ 0x10
+ },
+
+ /* gcvBLOCK_TESSELLATOR2 */
+ {
+ 0x0,
+ 0x1,
+ 0x12
+ },
+
+ /* gcvBLOCK_TESSELLATOR3 */
+ {
+ 0x0,
+ 0x1,
+ 0x14
+ },
+
+ /* gcvBLOCK_RASTER */
+ {
+ 0x0,
+ 0x1,
+ 0x07,
+ },
+
+ /* gcvBLOCK_VG */
+ {
+ 0x0,
+ 0x1,
+ 0x0F
+ },
+
+ /* gcvBLOCK_VG2 */
+ {
+ 0x0,
+ 0x1,
+ 0x11
+ },
+
+ /* gcvBLOCK_VG3 */
+ {
+ 0x0,
+ 0x1,
+ 0x13
+ },
+
+ /* gcvBLOCK_PIXEL */
+ {
+ 0x0,
+ 0x1,
+ 0x07
+ },
+ };
+
+ /* Verify block ID. */
+ gcmkVERIFY_ARGUMENT(gcmIS_VALID_INDEX(Block, states));
+
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Verify the event ID. */
+ gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+ gcmkVERIFY_ARGUMENT(InterruptId <= ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))));
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append EVENT. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x3 & ((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 11:0) - (0 ? 11:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ?
+ 11:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 11:0) - (0 ?
+ 11:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:0) - (0 ? 11:0) + 1))))))) << (0 ?
+ 11:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 27:16) - (0 ? 27:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 27:16) - (0 ?
+ 27:16) + 1))))))) << (0 ? 27:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 27:16) - (0 ? 27:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 27:16) - (0 ?
+ 27:16) + 1))))))) << (0 ? 27:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 13:12) - (0 ? 13:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:12) - (0 ?
+ 13:12) + 1))))))) << (0 ? 13:12))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 13:12) - (0 ? 13:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:12) - (0 ?
+ 13:12) + 1))))))) << (0 ? 13:12)))
+ );
+
+ /* Determine chip version. */
+ if (Command->vg21)
+ {
+ /* Get the event source for the block. */
+ gctUINT eventSource = states[Block].eventSource;
+
+ /* Supported? */
+ if (eventSource == ~0)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8))) | (((gctUINT32) ((gctUINT32) (eventSource) & ((gctUINT32) ((((1 ?
+ 12:8) - (0 ? 12:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ?
+ 12:8)));
+ }
+ else
+ {
+ /* Get the event source for the block. */
+ gctUINT eventFromFE = states[Block].eventFromFE;
+ gctUINT eventFromPE = states[Block].eventFromPE;
+
+ /* Supported? */
+ if (eventFromFE == ~0)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ buffer[1]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) ((gctUINT32) (eventFromFE) & ((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) ((gctUINT32) (eventFromPE) & ((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6)));
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Make sure the events are directly supported for the block. */
+ if (states[Block].eventSource == ~0)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Verify the event ID. */
+ gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+ gcmkVERIFY_ARGUMENT(InterruptId <= ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))));
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append EVENT. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ );
+
+ /* Determine event source. */
+ if (Block == gcvBLOCK_COMMAND)
+ {
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[1],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 5:5) - (0 ? 5:5) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ?
+ 5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
+ );
+ }
+ else
+ {
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[1],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)))
+ );
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the EVENT and END commands. */
+ *Bytes = 8;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGCOMMAND_EndCommand
+**
+** Form an END command at the specified location in the command buffer.
+**
+** INPUT:
+**
+** gckVGCOMMAND Command
+** Pointer to the Command object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command buffer to append
+** END command at or gcvNULL to query the size of the command.
+**
+** gctINT32 InterruptId
+** The ID of the interrupt to generate.
+** If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the END command.
+** If 'Logical' is gcvNULL, the value from this argument is ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the END command. If 'Bytes' is gcvNULL, nothing is returned.
+*/
+gceSTATUS
+gckVGCOMMAND_EndCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctINT32 InterruptId,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Logical=0x%x InterruptId=0x%x Bytes = 0x%x",
+ Command, Logical, InterruptId, Bytes);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->fe20)
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR buffer;
+
+ /* Verify the event ID. */
+ gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+
+ /* Cast the buffer pointer. */
+ buffer = (gctUINT32_PTR) Logical;
+
+ /* Append END. */
+ gckOS_WriteMemory(
+ Command->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 31:28) - (0 ? 31:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:28) - (0 ?
+ 31:28) + 1))))))) << (0 ? 31:28)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0)))
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+ }
+ else
+ {
+ if (Logical != gcvNULL)
+ {
+ gctUINT32_PTR memory;
+
+ /* Verify the event ID. */
+ gcmkVERIFY_ARGUMENT(InterruptId >= 0);
+
+ /* Cast the buffer pointer. */
+ memory = (gctUINT32_PTR) Logical;
+
+ /* Append EVENT. */
+ gckOS_WriteMemory(
+ Command->os,
+ &memory[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ );
+
+ gckOS_WriteMemory(
+ Command->os,
+ &memory[1],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0))) | (((gctUINT32) ((gctUINT32) (InterruptId) & ((gctUINT32) ((((1 ?
+ 4:0) - (0 ? 4:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ?
+ 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 6:6) - (0 ? 6:6) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ?
+ 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)))
+ );
+
+ /* Append END. */
+ gckOS_WriteMemory(
+ Command->os,
+ &memory[2],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ );
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the EVENT and END commands. */
+ *Bytes = 16;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+#endif /* gcdENABLE_VG */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h
new file mode 100644
index 000000000000..f645b678895b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_command_vg.h
@@ -0,0 +1,353 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_hardware_command_vg_h_
+#define __gc_hal_kernel_hardware_command_vg_h_
+
+/******************************************************************************\
+******************* Task and Interrupt Management Structures. ******************
+\******************************************************************************/
+
+/* Task storage header. */
+typedef struct _gcsTASK_STORAGE * gcsTASK_STORAGE_PTR;
+typedef struct _gcsTASK_STORAGE
+{
+ /* Next allocated storage buffer. */
+ gcsTASK_STORAGE_PTR next;
+}
+gcsTASK_STORAGE;
+
+/* Task container header. */
+typedef struct _gcsTASK_CONTAINER * gcsTASK_CONTAINER_PTR;
+typedef struct _gcsTASK_CONTAINER
+{
+ /* The number of tasks left to be processed in the container. */
+ gctINT referenceCount;
+
+ /* Size of the buffer. */
+ gctUINT size;
+
+ /* Link to the previous and the next allocated containers. */
+ gcsTASK_CONTAINER_PTR allocPrev;
+ gcsTASK_CONTAINER_PTR allocNext;
+
+ /* Link to the previous and the next containers in the free list. */
+ gcsTASK_CONTAINER_PTR freePrev;
+ gcsTASK_CONTAINER_PTR freeNext;
+}
+gcsTASK_CONTAINER;
+
+/* Kernel space task master table entry. */
+typedef struct _gcsBLOCK_TASK_ENTRY * gcsBLOCK_TASK_ENTRY_PTR;
+typedef struct _gcsBLOCK_TASK_ENTRY
+{
+ /* Pointer to the current task container for the block. */
+ gcsTASK_CONTAINER_PTR container;
+
+ /* Pointer to the current task data within the container. */
+ gcsTASK_HEADER_PTR task;
+
+ /* Pointer to the last link task within the container. */
+ gcsTASK_LINK_PTR link;
+
+ /* Number of interrupts allocated for this block. */
+ gctUINT interruptCount;
+
+ /* The index of the current interrupt. */
+ gctUINT interruptIndex;
+
+ /* Interrupt semaphore. */
+ gctSEMAPHORE interruptSemaphore;
+
+ /* Interrupt value array. */
+ gctINT32 interruptArray[32];
+}
+gcsBLOCK_TASK_ENTRY;
+
+
+/******************************************************************************\
+********************* Command Queue Management Structures. *********************
+\******************************************************************************/
+
+/* Command queue kernel element pointer. */
+typedef struct _gcsKERNEL_CMDQUEUE * gcsKERNEL_CMDQUEUE_PTR;
+
+/* Command queue object handler function type. */
+typedef gceSTATUS (* gctOBJECT_HANDLER) (
+ gckVGKERNEL Kernel,
+ gcsKERNEL_CMDQUEUE_PTR Entry
+ );
+
+/* Command queue kernel element. */
+typedef struct _gcsKERNEL_CMDQUEUE
+{
+ /* The number of buffers in the queue. */
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* Pointer to the object handler function. */
+ gctOBJECT_HANDLER handler;
+}
+gcsKERNEL_CMDQUEUE;
+
+/* Command queue header. */
+typedef struct _gcsKERNEL_QUEUE_HEADER * gcsKERNEL_QUEUE_HEADER_PTR;
+typedef struct _gcsKERNEL_QUEUE_HEADER
+{
+ /* The size of the buffer in bytes. */
+ gctUINT size;
+
+ /* The number of pending entries to be processed. */
+ volatile gctUINT pending;
+
+ /* The current command queue entry. */
+ gcsKERNEL_CMDQUEUE_PTR currentEntry;
+
+ /* Next buffer. */
+ gcsKERNEL_QUEUE_HEADER_PTR next;
+}
+gcsKERNEL_QUEUE_HEADER;
+
+
+/******************************************************************************\
+******************************* gckVGCOMMAND Object *******************************
+\******************************************************************************/
+
+/* gckVGCOMMAND object. */
+struct _gckVGCOMMAND
+{
+ /***************************************************************************
+ ** Object data and pointers.
+ */
+
+ gcsOBJECT object;
+ gckVGKERNEL kernel;
+ gckOS os;
+ gckVGHARDWARE hardware;
+
+ /* Features. */
+ gctBOOL fe20;
+ gctBOOL vg20;
+ gctBOOL vg21;
+
+
+ /***************************************************************************
+ ** Enable command queue dumping.
+ */
+
+ gctBOOL enableDumping;
+
+
+ /***************************************************************************
+ ** Bus Error interrupt.
+ */
+
+ gctINT32 busErrorInt;
+
+
+ /***************************************************************************
+ ** Command buffer information.
+ */
+
+ gcsCOMMAND_BUFFER_INFO info;
+
+
+ /***************************************************************************
+ ** Synchronization objects.
+ */
+
+ gctPOINTER queueMutex;
+ gctPOINTER taskMutex;
+ gctPOINTER commitMutex;
+
+
+ /***************************************************************************
+ ** Task management.
+ */
+
+ /* The head of the storage buffer linked list. */
+ gcsTASK_STORAGE_PTR taskStorage;
+
+ /* Allocation size. */
+ gctUINT taskStorageGranularity;
+ gctUINT taskStorageUsable;
+
+ /* The free container list. */
+ gcsTASK_CONTAINER_PTR taskFreeHead;
+ gcsTASK_CONTAINER_PTR taskFreeTail;
+
+ /* Task table */
+ gcsBLOCK_TASK_ENTRY taskTable[gcvBLOCK_COUNT];
+
+
+ /***************************************************************************
+ ** Command queue.
+ */
+
+ /* Pointer to the allocated queue memory. */
+ gcsKERNEL_QUEUE_HEADER_PTR queue;
+
+ /* Pointer to the current available queue from which new queue entries
+ will be allocated. */
+ gcsKERNEL_QUEUE_HEADER_PTR queueHead;
+
+ /* If different from queueHead, points to the command queue which is
+ currently being executed by the hardware. */
+ gcsKERNEL_QUEUE_HEADER_PTR queueTail;
+
+ /* Points to the queue to merge the tail with when the tail is processed. */
+ gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
+
+ /* Queue overflow counter. */
+ gctUINT queueOverflow;
+
+
+ /***************************************************************************
+ ** Context.
+ */
+
+ /* Context counter used for unique ID. */
+ gctUINT64 contextCounter;
+
+ /* Current context ID. */
+ gctUINT64 currentContext;
+
+ /* Command queue power semaphore. */
+ gctPOINTER powerSemaphore;
+ gctINT32 powerStallInt;
+ gcsCMDBUFFER_PTR powerStallBuffer;
+ gctSIGNAL powerStallSignal;
+
+};
+
+/******************************************************************************\
+************************ gckVGCOMMAND Object Internal API. ***********************
+\******************************************************************************/
+
+/* Initialize architecture dependent command buffer information. */
+gceSTATUS
+gckVGCOMMAND_InitializeInfo(
+ IN gckVGCOMMAND Command
+ );
+
+/* Form a STATE command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_StateCommand(
+ IN gckVGCOMMAND Command,
+ IN gctUINT32 Pipe,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gctUINT32 Count,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form a RESTART command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_RestartCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form a FETCH command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_FetchCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form a CALL command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_CallCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT FetchCount,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form a RETURN command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_ReturnCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form an EVENT command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_EventCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gceBLOCK Block,
+ IN gctINT32 InterruptId,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Form an END command at the specified location in the command buffer. */
+gceSTATUS
+gckVGCOMMAND_EndCommand(
+ IN gckVGCOMMAND Command,
+ IN gctPOINTER Logical,
+ IN gctINT32 InterruptId,
+ IN OUT gctUINT32 * Bytes
+ );
+
+#endif /* __gc_hal_kernel_hardware_command_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c
new file mode 100644
index 000000000000..a852913599c7
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c
@@ -0,0 +1,2308 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_hardware_command_vg.h"
+
+#include "gc_feature_database.h"
+
+#if gcdENABLE_VG
+
+#define _GC_OBJ_ZONE gcvZONE_HARDWARE
+
+typedef enum
+{
+ gcvPOWER_FLAG_INITIALIZE = 1 << 0,
+ gcvPOWER_FLAG_STALL = 1 << 1,
+ gcvPOWER_FLAG_STOP = 1 << 2,
+ gcvPOWER_FLAG_START = 1 << 3,
+ gcvPOWER_FLAG_RELEASE = 1 << 4,
+ gcvPOWER_FLAG_DELAY = 1 << 5,
+ gcvPOWER_FLAG_SAVE = 1 << 6,
+ gcvPOWER_FLAG_ACQUIRE = 1 << 7,
+ gcvPOWER_FLAG_POWER_OFF = 1 << 8,
+ gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
+ gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
+ gcvPOWER_FLAG_NOP = 1 << 11,
+}
+gcePOWER_FLAGS;
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+static gceSTATUS
+_ResetGPU(
+ IN gckOS Os
+ )
+{
+ gctUINT32 control, idle;
+ gceSTATUS status;
+
+ /* Read register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ &control));
+
+ for (;;)
+ {
+ /* Disable clock gating. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00104,
+ 0x00000000));
+
+ /* Wait for clock being stable. */
+ gcmkONERROR(gckOS_Delay(Os, 1));
+
+ /* Isolate the GPU. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ control));
+
+ /* Set soft reset. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Wait for reset. */
+ gcmkONERROR(gckOS_Delay(Os, 1));
+
+ /* Reset soft reset bit. */
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
+ 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Reset GPU isolation. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
+ 19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
+ 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(gckOS_WriteRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ control));
+
+ /* Read idle register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00004,
+ &idle));
+
+ if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
+ {
+ continue;
+ }
+
+ /* Read reset register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(Os,
+ gcvCORE_VG,
+ 0x00000,
+ &control));
+
+ if (((((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) ) == 0)
+ || ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
+ )
+ {
+ continue;
+ }
+
+ /* GPU is idle. */
+ break;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return the error. */
+ return status;
+}
+
+
+static gceSTATUS
+_IdentifyHardware(
+ IN gckOS Os,
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPMODEL * ChipModel,
+ OUT gctUINT32 * ChipRevision,
+ OUT gctUINT32 * ChipFeatures,
+ OUT gctUINT32 * ChipMinorFeatures,
+ OUT gctUINT32 * ChipMinorFeatures2
+ )
+{
+ gceSTATUS status;
+ gctUINT32 chipIdentity;
+
+ do
+ {
+ /* Read chip identity register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG, 0x00018, &chipIdentity));
+
+ /* Special case for older graphic cores. */
+ if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+ {
+ *ChipModel = gcv500;
+ *ChipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+ }
+
+ else
+ {
+ /* Read chip identity register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
+ 0x00020,
+ (gctUINT32 *) ChipModel));
+
+ /* Read CHIP_REV register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
+ 0x00024,
+ ChipRevision));
+ }
+
+ /* Read chip feature register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x0001C, ChipFeatures
+ ));
+
+ /* Read chip minor feature register. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x00034, ChipMinorFeatures
+ ));
+
+ /* Read chip minor feature register #2. */
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x00074, ChipMinorFeatures2
+ ));
+
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x000A8, &Hardware->productID
+ ));
+
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x000E8, &Hardware->ecoID
+ ));
+
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(
+ Os, gcvCORE_VG, 0x00030, &Hardware->customerID
+ ));
+
+ gcmkTRACE(
+ gcvLEVEL_VERBOSE,
+ "ChipModel=0x%08X\n"
+ "ChipRevision=0x%08X\n"
+ "ChipFeatures=0x%08X\n"
+ "ChipMinorFeatures=0x%08X\n"
+ "ChipMinorFeatures2=0x%08X\n",
+ *ChipModel,
+ *ChipRevision,
+ *ChipFeatures,
+ *ChipMinorFeatures,
+ *ChipMinorFeatures2
+ );
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return the status. */
+ return status;
+}
+
+#if gcdPOWEROFF_TIMEOUT
+void
+_VGPowerTimerFunction(
+ gctPOINTER Data
+ )
+{
+ gckVGHARDWARE hardware = (gckVGHARDWARE)Data;
+ gcmkVERIFY_OK(
+ gckVGHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
+}
+#endif
+
+/******************************************************************************\
+****************************** gckVGHARDWARE API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_Construct
+**
+** Construct a new gckVGHARDWARE object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an initialized gckOS object.
+**
+** OUTPUT:
+**
+** gckVGHARDWARE * Hardware
+** Pointer to a variable that will hold the pointer to the gckVGHARDWARE
+** object.
+*/
+gceSTATUS
+gckVGHARDWARE_Construct(
+ IN gckOS Os,
+ OUT gckVGHARDWARE * Hardware
+ )
+{
+ gckVGHARDWARE hardware = gcvNULL;
+ gceSTATUS status;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 chipFeatures;
+ gctUINT32 chipMinorFeatures;
+ gctUINT32 chipMinorFeatures2;
+ gcsFEATURE_DATABASE * database;
+
+ gcmkHEADER_ARG("Os=0x%x Hardware=0x%x ", Os, Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+ do
+ {
+ gcmkERR_BREAK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvTRUE, gcvTRUE));
+
+ status = _ResetGPU(Os);
+
+ if (status != gcvSTATUS_OK)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "_ResetGPU failed: status=%d\n", status);
+ }
+
+ /* Allocate the gckVGHARDWARE object. */
+ gcmkERR_BREAK(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckVGHARDWARE), (gctPOINTER *) &hardware
+ ));
+
+ /* Identify the hardware. */
+ gcmkERR_BREAK(_IdentifyHardware(Os, hardware,
+ &chipModel, &chipRevision,
+ &chipFeatures, &chipMinorFeatures, &chipMinorFeatures2
+ ));
+
+ /* Initialize the gckVGHARDWARE object. */
+ hardware->object.type = gcvOBJ_HARDWARE;
+ hardware->os = Os;
+
+ /* Set chip identity. */
+ hardware->chipModel = chipModel;
+ hardware->chipRevision = chipRevision;
+ hardware->chipFeatures = chipFeatures;
+ hardware->chipMinorFeatures = chipMinorFeatures;
+ hardware->chipMinorFeatures2 = chipMinorFeatures2;
+
+ hardware->powerMutex = gcvNULL;
+ hardware->chipPowerState = gcvPOWER_ON;
+ hardware->chipPowerStateGlobal = gcvPOWER_ON;
+ hardware->clockState = gcvTRUE;
+ hardware->powerState = gcvTRUE;
+
+#if gcdPOWEROFF_TIMEOUT
+ hardware->powerOffTime = 0;
+ hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
+
+ gcmkVERIFY_OK(gckOS_CreateTimer(Os,
+ _VGPowerTimerFunction,
+ (gctPOINTER)hardware,
+ &hardware->powerOffTimer));
+#endif
+
+ database = hardware->featureDatabase = gcQueryFeatureDB(
+ hardware->chipModel,
+ hardware->chipRevision,
+ hardware->productID,
+ hardware->ecoID,
+ hardware->customerID
+ );
+
+ if (database == gcvNULL)
+ {
+ gcmkPRINT("[galcore]: Feature database is not found,"
+ "chipModel=0x%0x, chipRevision=0x%x, productID=0x%x, ecoID=0x%x",
+ hardware->chipModel,
+ hardware->chipRevision,
+ hardware->productID,
+ hardware->ecoID);
+ /* gcmkERR_BREAK(gcvSTATUS_NOT_FOUND); */
+ }
+
+ /* Determine whether FE 2.0 is present. */
+ hardware->fe20 = ((((gctUINT32) (hardware->chipFeatures)) >> (0 ?
+ 28:28) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
+ 28:28) - (0 ? 28:28) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 28:28) - (0 ?
+ 28:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 28:28) - (0 ? 28:28) + 1)))))));
+
+ /* Determine whether VG 2.0 is present. */
+ hardware->vg20 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ?
+ 13:13) & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
+ 13:13) - (0 ? 13:13) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 13:13) - (0 ?
+ 13:13) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:13) - (0 ? 13:13) + 1)))))));
+
+ /* Determine whether VG 2.1 is present. */
+ hardware->vg21 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ?
+ 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
+ 18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ?
+ 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
+
+ /* Determine whether fc is present. */
+ hardware->fc = (((((gctUINT32) (hardware->chipFeatures)) >> (0 ? 0:0 )) & ((gctUINT32) ((((1 ? 0:0 ) - (0 ? 0:0 ) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0 ) - (0 ? 0:0 ) + 1)))))) );
+
+
+ /* Set default event mask. */
+ hardware->eventMask = 0xFFFFFFFF;
+
+ gcmkERR_BREAK(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
+
+ /* Set fast clear to auto. */
+ gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(hardware, -1));
+
+ gcmkERR_BREAK(gckOS_CreateMutex(Os, &hardware->powerMutex));
+
+ /* Enable power management by default. */
+ hardware->powerManagement = gcvTRUE;
+
+ /* Return pointer to the gckVGHARDWARE object. */
+ *Hardware = hardware;
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+#if gcdPOWEROFF_TIMEOUT
+ if (hardware != gcvNULL && hardware->powerOffTimer != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
+ }
+#endif
+
+ gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
+
+ if (hardware != gcvNULL && hardware->pageTableDirty != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
+ }
+
+ if (hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_Free(Os, hardware));
+ }
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_Destroy
+**
+** Destroy an gckVGHARDWARE object.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_Destroy(
+ IN gckVGHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Mark the object as unknown. */
+ Hardware->object.type = gcvOBJ_UNKNOWN;
+
+ if (Hardware->powerMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(
+ Hardware->os, Hardware->powerMutex));
+ }
+
+#if gcdPOWEROFF_TIMEOUT
+ gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
+#endif
+
+ if (Hardware->pageTableDirty != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
+ }
+
+ /* Free the object. */
+ status = gckOS_Free(Hardware->os, Hardware);
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_QueryMemory
+**
+** Query the amount of memory available on the hardware.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * InternalSize
+** Pointer to a variable that will hold the size of the internal video
+** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
+** internal memory will be returned.
+**
+** gctUINT32 * InternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * InternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctSIZE_T * ExternalSize
+** Pointer to a variable that will hold the size of the external video
+** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
+** external memory will be returned.
+**
+** gctUINT32 * ExternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * ExternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * HorizontalTileSize
+** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
+** gcvNULL, no horizontal pixel per tile will be returned.
+**
+** gctUINT32 * VerticalTileSize
+** Number of vertical pixels per tile. If 'VerticalTileSize' is
+** gcvNULL, no vertical pixel per tile will be returned.
+*/
+gceSTATUS
+gckVGHARDWARE_QueryMemory(
+ IN gckVGHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x InternalSize=0x%x InternalBaseAddress=0x%x InternalAlignment=0x%x"
+ "ExternalSize=0x%x ExternalBaseAddress=0x%x ExternalAlignment=0x%x HorizontalTileSize=0x%x VerticalTileSize=0x%x",
+ Hardware, InternalSize, InternalBaseAddress, InternalAlignment,
+ ExternalSize, ExternalBaseAddress, ExternalAlignment, HorizontalTileSize, VerticalTileSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (InternalSize != gcvNULL)
+ {
+ /* No internal memory. */
+ *InternalSize = 0;
+ }
+
+ if (ExternalSize != gcvNULL)
+ {
+ /* No external memory. */
+ *ExternalSize = 0;
+ }
+
+ if (HorizontalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *HorizontalTileSize = 4;
+ }
+
+ if (VerticalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *VerticalTileSize = 4;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_QueryChipIdentity
+**
+** Query the identity of the hardware.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** gceCHIPMODEL * ChipModel
+** If 'ChipModel' is not gcvNULL, the variable it points to will
+** receive the model of the chip.
+**
+** gctUINT32 * ChipRevision
+** If 'ChipRevision' is not gcvNULL, the variable it points to will
+** receive the revision of the chip.
+**
+** gctUINT32 * ChipFeatures
+** If 'ChipFeatures' is not gcvNULL, the variable it points to will
+** receive the feature set of the chip.
+**
+** gctUINT32 * ChipMinorFeatures
+** If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
+** will receive the minor feature set of the chip.
+**
+** gctUINT32 * ChipMinorFeatures2
+** If 'ChipMinorFeatures2' is not gcvNULL, the variable it points to
+** will receive the minor feature set of the chip.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_QueryChipIdentity(
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPMODEL * ChipModel,
+ OUT gctUINT32 * ChipRevision,
+ OUT gctUINT32 * ProductID,
+ OUT gctUINT32 * EcoID,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures,
+ OUT gctUINT32* ChipMinorFeatures2
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x ChipModel=0x%x ChipRevision=0x%x ChipFeatures = 0x%x ChipMinorFeatures = 0x%x ChipMinorFeatures2 = 0x%x",
+ Hardware, ChipModel, ChipRevision, ChipFeatures, ChipMinorFeatures, ChipMinorFeatures2);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Return chip model. */
+ if (ChipModel != gcvNULL)
+ {
+ *ChipModel = Hardware->chipModel;
+ }
+
+ /* Return revision number. */
+ if (ChipRevision != gcvNULL)
+ {
+ *ChipRevision = Hardware->chipRevision;
+ }
+
+ /* Return feature set. */
+ if (ChipFeatures != gcvNULL)
+ {
+ gctUINT32 features = Hardware->chipFeatures;
+
+ if (Hardware->fc)
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0)));
+ }
+
+ /* Mark 2D pipe as available for GC500.0 since it did not have this *\
+ \* bit. */
+ if ((Hardware->chipModel == gcv500)
+ && (Hardware->chipRevision == 0)
+ )
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+ }
+
+ /* Mark 2D pipe as available for GC300 since it did not have this *\
+ \* bit. */
+ if (Hardware->chipModel == gcv300)
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
+ 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+ }
+
+ *ChipFeatures = features;
+ }
+
+ /* Return minor feature set. */
+ if (ChipMinorFeatures != gcvNULL)
+ {
+ *ChipMinorFeatures = Hardware->chipMinorFeatures;
+ }
+
+ /* Return minor feature set #2. */
+ if (ChipMinorFeatures2 != gcvNULL)
+ {
+ *ChipMinorFeatures2 = Hardware->chipMinorFeatures2;
+ }
+
+ *ProductID = Hardware->productID;
+ *EcoID = Hardware->ecoID;
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_ConvertFormat
+**
+** Convert an API format to hardware parameters.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** gceSURF_FORMAT Format
+** API format to convert.
+**
+** OUTPUT:
+**
+** gctUINT32 * BitsPerPixel
+** Pointer to a variable that will hold the number of bits per pixel.
+**
+** gctUINT32 * BytesPerTile
+** Pointer to a variable that will hold the number of bytes per tile.
+*/
+gceSTATUS
+gckVGHARDWARE_ConvertFormat(
+ IN gckVGHARDWARE Hardware,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT32 * BitsPerPixel,
+ OUT gctUINT32 * BytesPerTile
+ )
+{
+ gctUINT32 bitsPerPixel;
+ gctUINT32 bytesPerTile;
+
+ gcmkHEADER_ARG("Hardware=0x%x Format=0x%x BitsPerPixel=0x%x BytesPerTile = 0x%x",
+ Hardware, Format, BitsPerPixel, BytesPerTile);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Dispatch on format. */
+ switch (Format)
+ {
+ case gcvSURF_A1:
+ case gcvSURF_L1:
+ /* 1-bpp format. */
+ bitsPerPixel = 1;
+ bytesPerTile = (1 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_A4:
+ /* 4-bpp format. */
+ bitsPerPixel = 4;
+ bytesPerTile = (4 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_INDEX8:
+ case gcvSURF_A8:
+ case gcvSURF_L8:
+ /* 8-bpp format. */
+ bitsPerPixel = 8;
+ bytesPerTile = (8 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_YV12:
+ /* 12-bpp planar YUV formats. */
+ bitsPerPixel = 12;
+ bytesPerTile = (12 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_NV12:
+ /* 12-bpp planar YUV formats. */
+ bitsPerPixel = 12;
+ bytesPerTile = (12 * 4 * 4) / 8;
+ break;
+
+ /* 4444 variations. */
+ case gcvSURF_X4R4G4B4:
+ case gcvSURF_A4R4G4B4:
+ case gcvSURF_R4G4B4X4:
+ case gcvSURF_R4G4B4A4:
+ case gcvSURF_B4G4R4X4:
+ case gcvSURF_B4G4R4A4:
+ case gcvSURF_X4B4G4R4:
+ case gcvSURF_A4B4G4R4:
+
+ /* 1555 variations. */
+ case gcvSURF_X1R5G5B5:
+ case gcvSURF_A1R5G5B5:
+ case gcvSURF_R5G5B5X1:
+ case gcvSURF_R5G5B5A1:
+ case gcvSURF_X1B5G5R5:
+ case gcvSURF_A1B5G5R5:
+ case gcvSURF_B5G5R5X1:
+ case gcvSURF_B5G5R5A1:
+
+ /* 565 variations. */
+ case gcvSURF_R5G6B5:
+ case gcvSURF_B5G6R5:
+
+ case gcvSURF_A8L8:
+ case gcvSURF_YUY2:
+ case gcvSURF_UYVY:
+ case gcvSURF_D16:
+ /* 16-bpp format. */
+ bitsPerPixel = 16;
+ bytesPerTile = (16 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_X8R8G8B8:
+ case gcvSURF_A8R8G8B8:
+ case gcvSURF_X8B8G8R8:
+ case gcvSURF_A8B8G8R8:
+ case gcvSURF_R8G8B8X8:
+ case gcvSURF_R8G8B8A8:
+ case gcvSURF_B8G8R8X8:
+ case gcvSURF_B8G8R8A8:
+ case gcvSURF_D32:
+ /* 32-bpp format. */
+ bitsPerPixel = 32;
+ bytesPerTile = (32 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_D24S8:
+ /* 24-bpp format. */
+ bitsPerPixel = 32;
+ bytesPerTile = (32 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_DXT1:
+ case gcvSURF_ETC1:
+ bitsPerPixel = 4;
+ bytesPerTile = (4 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_DXT2:
+ case gcvSURF_DXT3:
+ case gcvSURF_DXT4:
+ case gcvSURF_DXT5:
+ bitsPerPixel = 8;
+ bytesPerTile = (8 * 4 * 4) / 8;
+ break;
+
+ default:
+ /* Invalid format. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Set the result. */
+ if (BitsPerPixel != gcvNULL)
+ {
+ * BitsPerPixel = bitsPerPixel;
+ }
+
+ if (BytesPerTile != gcvNULL)
+ {
+ * BytesPerTile = bytesPerTile;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_SplitMemory
+**
+** Split a hardware specific memory address into a pool and offset.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** gctUINT32 Address
+** Address in hardware specific format.
+**
+** OUTPUT:
+**
+** gcePOOL * Pool
+** Pointer to a variable that will hold the pool type for the address.
+**
+** gctUINT32 * Offset
+** Pointer to a variable that will hold the offset for the address.
+*/
+gceSTATUS
+gckVGHARDWARE_SplitMemory(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Pool=0x%x Offset = 0x%x",
+ Hardware, Address, Pool, Offset);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
+
+ /* Dispatch on memory type. */
+ switch ((((((gctUINT32) (Address)) >> (0 ? 1:0)) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1)))))) ))
+ {
+ case 0x0:
+ /* System memory. */
+ *Pool = gcvPOOL_SYSTEM;
+ break;
+
+ case 0x2:
+ /* Virtual memory. */
+ *Pool = gcvPOOL_VIRTUAL;
+ break;
+
+ default:
+ /* Invalid memory type. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Return offset of address. */
+ *Offset = ((((gctUINT32) (Address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:0) - (0 ?
+ 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0)));
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_Execute
+**
+** Kickstart the hardware's command processor with an initialized command
+** buffer.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to the gckVGHARDWARE object.
+**
+** gctUINT32 Address
+** Address of the command buffer.
+**
+** gctSIZE_T Count
+** Number of command-sized data units to be executed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_Execute(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Address,
+ IN gctUINT32 Count
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Count=0x%x",
+ Hardware, Address, Count);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ do
+ {
+ /* Enable all events. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00014,
+ Hardware->eventMask
+ ));
+
+ if (Hardware->fe20)
+ {
+ /* Write address register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00500,
+ gcmkFIXADDRESS(Address)
+ ));
+
+ /* Write control register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00504,
+ Count
+ ));
+ }
+ else
+ {
+ /* Write address register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00654,
+ gcmkFIXADDRESS(Address)
+ ));
+
+ /* Write control register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(
+ Hardware->os,
+ gcvCORE_VG,
+ 0x00658,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) |
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ ));
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_AlignToTile
+**
+** Align the specified width and height to tile boundaries.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to an gckVGHARDWARE object.
+**
+** gceSURF_TYPE Type
+** Type of alignment.
+**
+** gctUINT32 * Width
+** Pointer to the width to be aligned. If 'Width' is gcvNULL, no width
+** will be aligned.
+**
+** gctUINT32 * Height
+** Pointer to the height to be aligned. If 'Height' is gcvNULL, no height
+** will be aligned.
+**
+** OUTPUT:
+**
+** gctUINT32 * Width
+** Pointer to a variable that will receive the aligned width.
+**
+** gctUINT32 * Height
+** Pointer to a variable that will receive the aligned height.
+*/
+gceSTATUS
+gckVGHARDWARE_AlignToTile(
+ IN gckVGHARDWARE Hardware,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32 * Width,
+ IN OUT gctUINT32 * Height
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Type=0x%x Width=0x%x Height=0x%x",
+ Hardware, Type, Width, Height);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Width != gcvNULL)
+ {
+ /* Align the width. */
+ *Width = gcmALIGN(*Width, (Type == gcvSURF_TEXTURE) ? 4 : 16);
+ }
+
+ if (Height != gcvNULL)
+ {
+ /* Special case for VG images. */
+ if ((*Height == 0) && (Type == gcvSURF_IMAGE))
+ {
+ *Height = 4;
+ }
+ else
+ {
+ /* Align the height. */
+ *Height = gcmALIGN(*Height, 4);
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_ConvertLogical
+**
+** Convert a logical system address into a hardware specific address.
+**
+** INPUT:
+**
+** gckVGHARDWARE Hardware
+** Pointer to an gckVGHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address to convert.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the memory in user space.
+**
+** gctUINT32* Address
+** Return hardware specific address.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVGHARDWARE_ConvertLogical(
+ IN gckVGHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ OUT gctUINT32 * Address
+ )
+{
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x InUserSpace=%d Address=0x%x",
+ Hardware, Logical, InUserSpace, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ do
+ {
+ /* Convert logical address into a physical address. */
+ if (InUserSpace)
+ {
+ gcmkERR_BREAK(gckOS_UserLogicalToPhysical(
+ Hardware->os, Logical, &physical
+ ));
+ }
+ else
+ {
+ gcmkERR_BREAK(gckOS_GetPhysicalAddress(
+ Hardware->os, Logical, &physical
+ ));
+ }
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ /* Return hardware specific address. */
+ *Address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_QuerySystemMemory
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * SystemSize
+** Pointer to a variable that receives the maximum size of the system
+** memory.
+**
+** gctUINT32 * SystemBaseAddress
+** Poinetr to a variable that receives the base address for system
+** memory.
+*/
+gceSTATUS gckVGHARDWARE_QuerySystemMemory(
+ IN gckVGHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x SystemSize=0x%x SystemBaseAddress=0x%x",
+ Hardware, SystemSize, SystemBaseAddress);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (SystemSize != gcvNULL)
+ {
+ /* Maximum system memory can be 2GB. */
+ *SystemSize = (gctSIZE_T)(1 << 31);
+ }
+
+ if (SystemBaseAddress != gcvNULL)
+ {
+ /* Set system memory base address. */
+ *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_SetMMU
+**
+** Set the page table base address.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckVGHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the page table.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGHARDWARE_SetMMU(
+ IN gckVGHARDWARE Hardware,
+ IN gctPOINTER Logical
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = 0;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x",
+ Hardware, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ do
+ {
+ /* Convert the logical address into an hardware address. */
+ gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical,
+ gcvFALSE, &address));
+
+ /* Write the AQMemoryFePageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00400,
+ gcmkFIXADDRESS(address)));
+
+ /* Write the AQMemoryTxPageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00404,
+ gcmkFIXADDRESS(address)));
+
+ /* Write the AQMemoryPePageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00408,
+ gcmkFIXADDRESS(address)));
+
+ /* Write the AQMemoryPezPageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x0040C,
+ gcmkFIXADDRESS(address)));
+
+ /* Write the AQMemoryRaPageTable register. */
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00410,
+ gcmkFIXADDRESS(address)));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_FlushMMU
+**
+** Flush the page table.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGHARDWARE_FlushMMU(
+ IN gckVGHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gckVGCOMMAND command;
+
+ gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ do
+ {
+ gcsCMDBUFFER_PTR commandBuffer;
+ gctUINT32_PTR buffer;
+
+ /* Create a shortcut to the command buffer object. */
+ command = Hardware->kernel->command;
+
+ /* Allocate command buffer space. */
+ gcmkERR_BREAK(gckVGCOMMAND_Allocate(
+ command, 8, &commandBuffer, (gctPOINTER *) &buffer
+ ));
+
+ gckOS_WriteMemory(
+ Hardware->os,
+ &buffer[0],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)))
+ );
+
+ gckOS_WriteMemory(
+ Hardware->os,
+ &buffer[1],
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
+ 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
+ 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
+ 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
+ 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)))
+ );
+
+ gcmkERR_BREAK(gckVGCOMMAND_Execute(
+ command,
+ commandBuffer
+ ));
+ }
+ while(gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_BuildVirtualAddress
+**
+** Build a virtual address.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckVGHARDWARE object.
+**
+** gctUINT32 Index
+** Index into page table.
+**
+** gctUINT32 Offset
+** Offset into page.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable receiving te hardware address.
+*/
+gceSTATUS gckVGHARDWARE_BuildVirtualAddress(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ )
+{
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Hardware=0x%x Index=0x%x Offset=0x%x Address=0x%x",
+ Hardware, Index, Offset, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Build virtual address. */
+ address = (Index << 12) | Offset;
+
+ /* Set virtual type. */
+ address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
+ 1:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
+
+ /* Set the result. */
+ *Address = address;
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGHARDWARE_GetIdle(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32 * Data
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Hardware=0x%x Data=0x%x", Hardware, Data);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ /* Read register and return. */
+ status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, Data);
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVGHARDWARE_SetFastClear(
+ IN gckVGHARDWARE Hardware,
+ IN gctINT Enable
+ )
+{
+ gctUINT32 debug;
+ gceSTATUS status;
+
+ if (!Hardware->fc)
+ {
+ return gcvSTATUS_OK;
+ }
+
+ do
+ {
+ if (Enable == -1)
+ {
+ Enable = (Hardware->chipModel > gcv500) ||
+ ((Hardware->chipModel == gcv500) && (Hardware->chipRevision >= 3));
+ }
+
+ gcmkERR_BREAK(gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00414,
+ &debug));
+
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
+ 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ?
+ 20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
+ 20:20) + 1))))))) << (0 ? 20:20)));
+
+#ifdef AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ?
+ AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ?
+ AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ?
+ AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION)));
+#endif
+
+ gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00414,
+ debug));
+
+ Hardware->allowFastClear = Enable;
+
+ status = gcvFALSE;
+ }
+ while (gcvFALSE);
+
+ return status;
+}
+
+gceSTATUS
+gckVGHARDWARE_ReadInterrupt(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32_PTR IDs
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Hardware=0x%x IDs=0x%x", Hardware, IDs);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(IDs != gcvNULL);
+
+ /* Read AQIntrAcknowledge register. */
+ status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
+ 0x00010,
+ IDs);
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS _CommandStall(
+ gckVGHARDWARE Hardware)
+{
+ gceSTATUS status;
+ gckVGCOMMAND command;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ do
+ {
+ gctUINT32_PTR buffer;
+ command = Hardware->kernel->command;
+
+ /* Allocate command buffer space. */
+ gcmkERR_BREAK(gckVGCOMMAND_Allocate(
+ command, 8, &command->powerStallBuffer,
+ (gctPOINTER *) &buffer
+ ));
+
+ gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
+ command, buffer, gcvBLOCK_PIXEL,
+ command->powerStallInt, gcvNULL));
+
+ gcmkERR_BREAK(gckVGCOMMAND_Execute(
+ command,
+ command->powerStallBuffer
+ ));
+
+ /* Wait the signal. */
+ gcmkERR_BREAK(gckOS_WaitSignal(
+ command->os,
+ command->powerStallSignal,
+ gcvTRUE,
+ command->kernel->kernel->timeOut));
+
+
+ }
+ while(gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetPowerManagementState
+**
+** Set GPU to a specified power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE State
+** Power State.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_SetPowerManagementState(
+ IN gckVGHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ )
+{
+ gceSTATUS status;
+ gckVGCOMMAND command = gcvNULL;
+ gckOS os;
+ gctUINT flag/*, clock*/;
+
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL stall = gcvTRUE;
+ gctBOOL commitMutex = gcvFALSE;
+ gctBOOL mutexAcquired = gcvFALSE;
+
+#if gcdPOWEROFF_TIMEOUT
+ gctBOOL timeout = gcvFALSE;
+ gctBOOL isAfter = gcvFALSE;
+ gctUINT32 currentTime;
+#endif
+
+ gctBOOL broadcast = gcvFALSE;
+ gctUINT32 process, thread;
+ gctBOOL global = gcvFALSE;
+
+#if gcdENABLE_PROFILING
+ gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
+ initTime, offTime, startTime, totalTime;
+#endif
+
+ /* State transition flags. */
+ static const gctUINT flags[4][4] =
+ {
+ /* gcvPOWER_ON */
+ { /* ON */ 0,
+ /* OFF */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_NOP,
+ /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_OFF */
+ { /* ON */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY,
+ /* OFF */ 0,
+ /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY,
+ /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_IDLE */
+ { /* ON */ gcvPOWER_FLAG_NOP,
+ /* OFF */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ 0,
+ /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_SUSPEND */
+ { /* ON */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_CLOCK_ON,
+ /* OFF */ gcvPOWER_FLAG_SAVE |
+ gcvPOWER_FLAG_POWER_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_CLOCK_ON,
+ /* SUSPEND */ 0,
+ },
+ };
+
+ gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Switching to power state %d",
+ State);
+#endif
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get the gckOS object pointer. */
+ os = Hardware->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Get the gckCOMMAND object pointer. */
+ gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
+ command = Hardware->kernel->command;
+ gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+ if (Hardware->powerManagement == gcvFALSE)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Start profiler. */
+ gcmkPROFILE_INIT(freq, time);
+
+ /* Convert the broadcast power state. */
+ switch (State)
+ {
+ case gcvPOWER_SUSPEND_ATPOWERON:
+ /* Convert to SUSPEND and don't wait for STALL. */
+ State = gcvPOWER_SUSPEND;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_OFF_ATPOWERON:
+ /* Convert to OFF and don't wait for STALL. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_IDLE_BROADCAST:
+ /* Convert to IDLE and note we are inside broadcast. */
+ State = gcvPOWER_IDLE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_SUSPEND_BROADCAST:
+ /* Convert to SUSPEND and note we are inside broadcast. */
+ State = gcvPOWER_SUSPEND;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_BROADCAST:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_RECOVERY:
+ /* Convert to OFF and note we are inside recovery. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_ON_AUTO:
+ /* Convert to ON and note we are inside recovery. */
+ State = gcvPOWER_ON;
+ break;
+
+ case gcvPOWER_ON:
+ case gcvPOWER_IDLE:
+ case gcvPOWER_SUSPEND:
+ case gcvPOWER_OFF:
+ /* Mark as global power management. */
+ global = gcvTRUE;
+ break;
+
+#if gcdPOWEROFF_TIMEOUT
+ case gcvPOWER_OFF_TIMEOUT:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ /* Check time out */
+ timeout = gcvTRUE;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ /* Get current process and thread IDs. */
+ gcmkONERROR(gckOS_GetProcessID(&process));
+ gcmkONERROR(gckOS_GetThreadID(&thread));
+
+ /* Acquire the power mutex. */
+ if (broadcast)
+ {
+ /* Try to acquire the power mutex. */
+ status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Check if we already own this mutex. */
+ if ((Hardware->powerProcess == process)
+ && (Hardware->powerThread == thread)
+ )
+ {
+ /* Bail out on recursive power management. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ else if (State == gcvPOWER_IDLE)
+ {
+ /* gcvPOWER_IDLE_BROADCAST is from IST,
+ ** so waiting here will cause deadlock,
+ ** if lock holder call gckCOMMAND_Stall() */
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os,
+ Hardware->powerMutex,
+ gcvINFINITE));
+ }
+ }
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+ }
+
+ /* Get time until mtuex acquired. */
+ gcmkPROFILE_QUERY(time, mutexTime);
+
+ Hardware->powerProcess = process;
+ Hardware->powerThread = thread;
+ mutexAcquired = gcvTRUE;
+
+ /* Grab control flags and clock. */
+ flag = flags[Hardware->chipPowerState][State];
+ /*clock = clocks[State];*/
+
+#if gcdPOWEROFF_TIMEOUT
+ if (timeout)
+ {
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ gcmkONERROR(
+ gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
+
+ /* powerOffTime is pushed forward, give up.*/
+ if (isAfter
+ /* Expect a transition start from IDLE. */
+ || (Hardware->chipPowerState == gcvPOWER_ON)
+ || (Hardware->chipPowerState == gcvPOWER_OFF)
+ )
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ }
+#endif
+
+ if (flag == 0)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* internal power control */
+ if (!global)
+ {
+ if (Hardware->chipPowerStateGlobal == gcvPOWER_OFF)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+ acquired = gcvTRUE;
+
+ /* avoid acquiring again. */
+ flag &= ~gcvPOWER_FLAG_ACQUIRE;
+ }
+ }
+
+ if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
+ {
+ /* Turn on the power. */
+ gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvTRUE, gcvTRUE));
+
+ /* Mark clock and power as enabled. */
+ Hardware->clockState = gcvTRUE;
+ Hardware->powerState = gcvTRUE;
+ }
+
+ /* Get time until powered on. */
+ gcmkPROFILE_QUERY(time, onTime);
+
+ if ((flag & gcvPOWER_FLAG_STALL) && stall)
+ {
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ command->os,
+ command->commitMutex,
+ gcvINFINITE
+ ));
+
+ commitMutex = gcvTRUE;
+
+ gcmkONERROR(_CommandStall(Hardware));
+ }
+
+ /* Get time until stalled. */
+ gcmkPROFILE_QUERY(time, stallTime);
+
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+
+ acquired = gcvTRUE;
+ }
+
+
+ /* Get time until stopped. */
+ gcmkPROFILE_QUERY(time, stopTime);
+
+
+ if (flag & gcvPOWER_FLAG_DELAY)
+ {
+ /* Wait for the specified amount of time to settle coming back from
+ ** power-off or suspend state. */
+ gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
+ }
+
+ /* Get time until delayed. */
+ gcmkPROFILE_QUERY(time, delayTime);
+
+ if (flag & gcvPOWER_FLAG_INITIALIZE)
+ {
+
+ /* Initialize GPU here, replaced by InitializeHardware later */
+ gcmkONERROR(gckVGHARDWARE_SetMMU(Hardware, Hardware->kernel->mmu->pageTableLogical));
+ gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(Hardware, -1));
+
+ /* Force the command queue to reload the next context. */
+ command->currentContext = 0;
+ }
+
+ /* Get time until initialized. */
+ gcmkPROFILE_QUERY(time, initTime);
+
+ if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+ {
+ /* Turn off the GPU power. */
+ gcmkONERROR(
+ gckOS_SetGPUPower(os,
+ gcvCORE_VG,
+ (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE,
+ (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+ : gcvTRUE));
+
+ /* Save current hardware power and clock states. */
+ Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE;
+ Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
+ : gcvTRUE;
+ }
+
+ /* Get time until off. */
+ gcmkPROFILE_QUERY(time, offTime);
+
+
+ /* Get time until started. */
+ gcmkPROFILE_QUERY(time, startTime);
+
+ if (flag & gcvPOWER_FLAG_RELEASE)
+ {
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
+ acquired = gcvFALSE;
+ }
+
+ /* Save the new power state. */
+ Hardware->chipPowerState = State;
+
+ if (global)
+ {
+ /* Save the new power state. */
+ Hardware->chipPowerStateGlobal = State;
+ }
+
+ if (commitMutex)
+ {
+ /* Acquire the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ command->os,
+ command->commitMutex
+ ));
+ }
+
+#if gcdPOWEROFF_TIMEOUT
+ /* Reset power off time */
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
+
+ if (State == gcvPOWER_IDLE)
+ {
+ /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
+ gcmkVERIFY_OK(gckOS_StartTimer(os,
+ Hardware->powerOffTimer,
+ Hardware->powerOffTimeout));
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
+
+ /* Cancel running timer when GPU enters ON or OFF. */
+ gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
+ }
+#endif
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* Get total time. */
+ gcmkPROFILE_QUERY(time, totalTime);
+#if gcdENABLE_PROFILING
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
+ freq, mutexTime, onTime, stallTime, stopTime);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ " delay:%llu init:%llu off:%llu start:%llu total:%llu",
+ delayTime, initTime, offTime, startTime, totalTime);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ if (acquired)
+ {
+ /* Release semaphore. */
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
+ command->powerSemaphore));
+ }
+
+ if (mutexAcquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+ }
+
+ if (commitMutex)
+ {
+ /* Acquire the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ command->os,
+ command->commitMutex
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryPowerManagementState
+**
+** Get GPU power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE* State
+** Power State.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_QueryPowerManagementState(
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(State != gcvNULL);
+
+ /* Return the statue. */
+ *State = Hardware->chipPowerState;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*State=%d", *State);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGHARDWARE_SetPowerManagement
+**
+** Configure GPU power management function.
+** Only used in driver initialization stage.
+**
+** INPUT:
+**
+** gckVGHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL PowerManagement
+** Power Mangement State.
+**
+*/
+gceSTATUS
+gckVGHARDWARE_SetPowerManagement(
+ IN gckVGHARDWARE Hardware,
+ IN gctBOOL PowerManagement
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ Hardware->powerManagement = PowerManagement;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdPOWEROFF_TIMEOUT
+gceSTATUS
+gckVGHARDWARE_SetPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Timeout
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
+
+ Hardware->powerOffTimeout = Timeout;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+gceSTATUS
+gckVGHARDWARE_QueryPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32* Timeout
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ *Timeout = Hardware->powerOffTimeout;
+
+ gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
+ return gcvSTATUS_OK;
+}
+#endif
+
+gceSTATUS
+gckVGHARDWARE_QueryIdle(
+ IN gckVGHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
+
+ /* We are idle when the power is not ON. */
+ if (Hardware->chipPowerState != gcvPOWER_ON)
+ {
+ *IsIdle = gcvTRUE;
+ }
+
+ else
+ {
+ /* Read idle register. */
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, &idle));
+
+ /* Pipe must be idle. */
+ if (((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 8:8)) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 10:10)) & ((gctUINT32) ((((1 ? 10:10) - (0 ? 10:10) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 10:10) - (0 ? 10:10) + 1)))))) ) != 1)
+ || ((((((gctUINT32) (idle)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ) != 1)
+ )
+ {
+ /* Something is busy. */
+ *IsIdle = gcvFALSE;
+ }
+
+ else
+ {
+ *IsIdle = gcvTRUE;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif /* gcdENABLE_VG */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h
new file mode 100644
index 000000000000..18c50bc32dcf
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_hardware_vg_h_
+#define __gc_hal_kernel_hardware_vg_h_
+
+/* gckHARDWARE object. */
+struct _gckVGHARDWARE
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckKERNEL object. */
+ gckVGKERNEL kernel;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Chip characteristics. */
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 productID;
+ gctUINT32 ecoID;
+ gctUINT32 customerID;
+ gctUINT32 chipFeatures;
+ gctUINT32 chipMinorFeatures;
+ gctUINT32 chipMinorFeatures2;
+ gctBOOL allowFastClear;
+
+ /* Features. */
+ gctBOOL fe20;
+ gctBOOL vg20;
+ gctBOOL vg21;
+ gctBOOL fc;
+
+ /* Event mask. */
+ gctUINT32 eventMask;
+
+ gctBOOL clockState;
+ gctBOOL powerState;
+ gctPOINTER powerMutex;
+ gctUINT32 powerProcess;
+ gctUINT32 powerThread;
+ gceCHIPPOWERSTATE chipPowerState;
+ gceCHIPPOWERSTATE chipPowerStateGlobal;
+ gctISRMANAGERFUNC startIsr;
+ gctISRMANAGERFUNC stopIsr;
+ gctPOINTER isrContext;
+ gctPOINTER pageTableDirty;
+#if gcdPOWEROFF_TIMEOUT
+ gctUINT32 powerOffTime;
+ gctUINT32 powerOffTimeout;
+ gctPOINTER powerOffTimer;
+#endif
+
+ gctBOOL powerManagement;
+
+ gctPOINTER featureDatabase;
+};
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
new file mode 100644
index 000000000000..1238e1babe40
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
@@ -0,0 +1,6137 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdDEC_ENABLE_AHB
+#include "viv_dec300_main.h"
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/*******************************************************************************
+***** Version Signature *******************************************************/
+
+#define _gcmTXT2STR(t) #t
+#define gcmTXT2STR(t) _gcmTXT2STR(t)
+const char * _VERSION = "\n\0$VERSION$"
+ gcmTXT2STR(gcvVERSION_MAJOR) "."
+ gcmTXT2STR(gcvVERSION_MINOR) "."
+ gcmTXT2STR(gcvVERSION_PATCH) ":"
+ gcmTXT2STR(gcvVERSION_BUILD) "$\n";
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#define gcmDEFINE2TEXT(d) #d
+gctCONST_STRING _DispatchText[] =
+{
+ gcmDEFINE2TEXT(gcvHAL_QUERY_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_QUERY_CHIP_IDENTITY),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_NON_PAGED_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_FREE_NON_PAGED_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_FREE_CONTIGUOUS_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_RELEASE_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_MAP_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_UNMAP_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_MAP_USER_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_UNMAP_USER_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_LOCK_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_UNLOCK_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_EVENT_COMMIT),
+ gcmDEFINE2TEXT(gcvHAL_USER_SIGNAL),
+ gcmDEFINE2TEXT(gcvHAL_SIGNAL),
+ gcmDEFINE2TEXT(gcvHAL_WRITE_DATA),
+ gcmDEFINE2TEXT(gcvHAL_COMMIT),
+ gcmDEFINE2TEXT(gcvHAL_STALL),
+ gcmDEFINE2TEXT(gcvHAL_READ_REGISTER),
+ gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER),
+ gcmDEFINE2TEXT(gcvHAL_GET_PROFILE_SETTING),
+ gcmDEFINE2TEXT(gcvHAL_SET_PROFILE_SETTING),
+ gcmDEFINE2TEXT(gcvHAL_READ_ALL_PROFILE_REGISTERS),
+ gcmDEFINE2TEXT(gcvHAL_PROFILE_REGISTERS_2D),
+#if VIVANTE_PROFILER_PERDRAW
+ gcmDEFINE2TEXT(gcvHAL_READ_PROFILER_REGISTER_SETTING),
+#endif
+ gcmDEFINE2TEXT(gcvHAL_READ_ALL_PROFILE_NEW_REGISTERS),
+ gcmDEFINE2TEXT(gcvHAL_READ_PROFILER_NEW_REGISTER_SETTING),
+ gcmDEFINE2TEXT(gcvHAL_SET_POWER_MANAGEMENT_STATE),
+ gcmDEFINE2TEXT(gcvHAL_QUERY_POWER_MANAGEMENT_STATE),
+ gcmDEFINE2TEXT(gcvHAL_GET_BASE_ADDRESS),
+ gcmDEFINE2TEXT(gcvHAL_SET_IDLE),
+ gcmDEFINE2TEXT(gcvHAL_QUERY_KERNEL_SETTINGS),
+ gcmDEFINE2TEXT(gcvHAL_RESET),
+ gcmDEFINE2TEXT(gcvHAL_MAP_PHYSICAL),
+ gcmDEFINE2TEXT(gcvHAL_DEBUG),
+ gcmDEFINE2TEXT(gcvHAL_CACHE),
+ gcmDEFINE2TEXT(gcvHAL_TIMESTAMP),
+ gcmDEFINE2TEXT(gcvHAL_DATABASE),
+ gcmDEFINE2TEXT(gcvHAL_VERSION),
+ gcmDEFINE2TEXT(gcvHAL_CHIP_INFO),
+ gcmDEFINE2TEXT(gcvHAL_ATTACH),
+ gcmDEFINE2TEXT(gcvHAL_DETACH),
+ gcmDEFINE2TEXT(gcvHAL_COMPOSE),
+ gcmDEFINE2TEXT(gcvHAL_SET_TIMEOUT),
+ gcmDEFINE2TEXT(gcvHAL_GET_FRAME_INFO),
+ gcmDEFINE2TEXT(gcvHAL_DUMP_GPU_PROFILE),
+ gcmDEFINE2TEXT(gcvHAL_QUERY_COMMAND_BUFFER),
+ gcmDEFINE2TEXT(gcvHAL_COMMIT_DONE),
+ gcmDEFINE2TEXT(gcvHAL_DUMP_GPU_STATE),
+ gcmDEFINE2TEXT(gcvHAL_DUMP_EVENT),
+ gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER),
+ gcmDEFINE2TEXT(gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER),
+ gcmDEFINE2TEXT(gcvHAL_SET_FSCALE_VALUE),
+ gcmDEFINE2TEXT(gcvHAL_GET_FSCALE_VALUE),
+ gcmDEFINE2TEXT(gcvHAL_NAME_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_IMPORT_VIDEO_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_QUERY_RESET_TIME_STAMP),
+ gcmDEFINE2TEXT(gcvHAL_READ_REGISTER_EX),
+ gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER_EX),
+ gcmDEFINE2TEXT(gcvHAL_CREATE_NATIVE_FENCE),
+ gcmDEFINE2TEXT(gcvHAL_DESTROY_MMU),
+ gcmDEFINE2TEXT(gcvHAL_SHBUF),
+ gcmDEFINE2TEXT(gcvHAL_GET_VIDEO_MEMORY_FD),
+ gcmDEFINE2TEXT(gcvHAL_CONFIG_POWER_MANAGEMENT),
+ gcmDEFINE2TEXT(gcvHAL_WRAP_USER_MEMORY),
+ gcmDEFINE2TEXT(gcvHAL_WAIT_FENCE),
+ gcmDEFINE2TEXT(gcvHAL_GET_VIDEO_MEMORY_FD),
+ gcmDEFINE2TEXT(gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY),
+};
+#endif
+
+#if gcdGPU_TIMEOUT && gcdINTERRUPT_STATISTIC
+void
+_MonitorTimerFunction(
+ gctPOINTER Data
+ )
+{
+ gckKERNEL kernel = (gckKERNEL)Data;
+ gctINT32 pendingInterrupt;
+ gctBOOL reset = gcvFALSE;
+ gctINT32 mask;
+ gctUINT32 advance = kernel->timeOut/2;
+
+#if gcdENABLE_VG
+ if (kernel->core == gcvCORE_VG)
+ {
+ return;
+ }
+#endif
+
+ if (kernel->monitorTimerStop)
+ {
+ /* Stop. */
+ return;
+ }
+
+ gckOS_AtomGet(kernel->os, kernel->eventObj->interruptCount, &pendingInterrupt);
+
+ if (pendingInterrupt < 0)
+ {
+ gctINT i = 0 - pendingInterrupt;
+ gctINT pendingMask;
+
+ gcmkVERIFY_OK(gckOS_AtomGet(
+ kernel->os,
+ kernel->hardware->pendingEvent,
+ &pendingMask
+ ));
+
+ gcmkPRINT("[galcore]: Number of pending interrupt is %d mask is %x",
+ pendingInterrupt, pendingMask);
+
+ while (i--)
+ {
+ /* Ignore counting which should not exist. */
+ gckOS_AtomIncrement(kernel->os, kernel->eventObj->interruptCount, &pendingInterrupt);
+ }
+
+ gckOS_AtomGet(kernel->os, kernel->eventObj->interruptCount, &pendingInterrupt);
+ }
+
+ if (kernel->monitoring == gcvFALSE)
+ {
+ if (pendingInterrupt)
+ {
+ /* Begin to mointor GPU state. */
+ kernel->monitoring = gcvTRUE;
+
+ /* Record current state. */
+ kernel->lastCommitStamp = kernel->eventObj->lastCommitStamp;
+ kernel->restoreAddress = kernel->hardware->lastWaitLink;
+ gcmkVERIFY_OK(gckOS_AtomGet(
+ kernel->os,
+ kernel->hardware->pendingEvent,
+ &kernel->restoreMask
+ ));
+
+ /* Clear timeout. */
+ kernel->timer = 0;
+ }
+ }
+ else
+ {
+ if (pendingInterrupt)
+ {
+ gcmkVERIFY_OK(gckOS_AtomGet(
+ kernel->os,
+ kernel->hardware->pendingEvent,
+ &mask
+ ));
+
+ if (kernel->eventObj->lastCommitStamp == kernel->lastCommitStamp
+ && kernel->hardware->lastWaitLink == kernel->restoreAddress
+ && mask == kernel->restoreMask
+ )
+ {
+ /* GPU state is not changed, accumlate timeout. */
+ kernel->timer += advance;
+
+ if (kernel->timer >= kernel->timeOut)
+ {
+ /* GPU stuck, trigger reset. */
+ reset = gcvTRUE;
+ }
+ }
+ else
+ {
+ /* GPU state changed, cancel current timeout.*/
+ kernel->monitoring = gcvFALSE;
+ }
+ }
+ else
+ {
+ /* GPU finish all jobs, cancel current timeout*/
+ kernel->monitoring = gcvFALSE;
+ }
+ }
+
+ if (reset)
+ {
+ gckKERNEL_Recovery(kernel);
+
+ /* Work in this timeout is done. */
+ kernel->monitoring = gcvFALSE;
+ }
+
+ gcmkVERIFY_OK(gckOS_StartTimer(kernel->os, kernel->monitorTimer, advance));
+}
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+_MapCommandBuffer(
+ IN gckKERNEL Kernel
+ )
+{
+ gceSTATUS status;
+ gctUINT32 i;
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+ gckMMU mmu;
+
+ gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+ {
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ Kernel->os,
+ Kernel->command->queues[i].logical,
+ &physical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ gcmkONERROR(gckMMU_FlatMapping(mmu, address, 1));
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+#endif
+
+void
+_DumpDriverConfigure(
+ IN gckKERNEL Kernel
+ )
+{
+ gcmkPRINT_N(0, "**************************\n");
+ gcmkPRINT_N(0, "*** GPU DRV CONFIG ***\n");
+ gcmkPRINT_N(0, "**************************\n");
+
+ gcmkPRINT("Galcore version %d.%d.%d.%d\n",
+ gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
+
+ gckOS_DumpParam();
+}
+
+void
+_DumpState(
+ IN gckKERNEL Kernel
+ )
+{
+ /* Dump GPU Debug registers. */
+ gcmkVERIFY_OK(gckHARDWARE_DumpGPUState(Kernel->hardware));
+
+ gcmkVERIFY_OK(gckCOMMAND_DumpExecutingBuffer(Kernel->command));
+
+ /* Dump Pending event. */
+ gcmkVERIFY_OK(gckEVENT_Dump(Kernel->eventObj));
+
+ /* Dump Process DB. */
+ gcmkVERIFY_OK(gckKERNEL_DumpProcessDB(Kernel));
+
+#if gcdRECORD_COMMAND
+ /* Dump record. */
+ gckRECORDER_Dump(Kernel->command->recorder);
+#endif
+}
+
+static gceHARDWARE_TYPE
+_GetHardwareType(
+ IN gckKERNEL Kernel
+ )
+{
+ gceHARDWARE_TYPE type;
+ gcmkHEADER();
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+#if gcdENABLE_VG
+ if (Kernel->vg)
+ {
+ type = gcvHARDWARE_VG;
+ }
+ else
+#endif
+ {
+ type = Kernel->hardware->type;
+ }
+
+ gcmkFOOTER_ARG("type=%d", type);
+ return type;
+}
+
+gceSTATUS
+_SetRecovery(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Recovery,
+ IN gctUINT32 StuckDump
+ )
+{
+ Kernel->recovery = Recovery;
+
+ if (Recovery == gcvFALSE)
+ {
+ /* Dump stuck information if Recovery is disabled. */
+ Kernel->stuckDump = gcmMAX(StuckDump, gcvSTUCK_DUMP_USER_COMMAND);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Construct
+**
+** Construct a new gckKERNEL object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gceCORE Core
+** Specified core.
+**
+** IN gctPOINTER Context
+** Pointer to a driver defined context.
+**
+** IN gckDB SharedDB,
+** Pointer to a shared DB.
+**
+** OUTPUT:
+**
+** gckKERNEL * Kernel
+** Pointer to a variable that will hold the pointer to the gckKERNEL
+** object.
+*/
+
+gceSTATUS
+gckKERNEL_Construct(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT ChipID,
+ IN gctPOINTER Context,
+ IN gckDEVICE Device,
+ IN gckDB SharedDB,
+ OUT gckKERNEL * Kernel
+ )
+{
+ gckKERNEL kernel = gcvNULL;
+ gceSTATUS status;
+ gctSIZE_T i;
+ gctPOINTER pointer = gcvNULL;
+ gctUINT32 recovery;
+ gctUINT32 stuckDump;
+
+ gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+
+ /* Allocate the gckKERNEL object. */
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckKERNEL),
+ &pointer));
+
+ /* Zero the object. */
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckKERNEL));
+
+ kernel = pointer;
+
+ /* Initialize the gckKERNEL object. */
+ kernel->object.type = gcvOBJ_KERNEL;
+ kernel->os = Os;
+ kernel->core = Core;
+ kernel->device = Device;
+ kernel->chipID = ChipID;
+
+#if gcdENABLE_TRUST_APPLICATION
+ /* Connect to security service for this GPU. */
+ gcmkONERROR(gckKERNEL_SecurityOpen(kernel, kernel->core, &kernel->securityChannel));
+#endif
+
+ if (SharedDB == gcvNULL)
+ {
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckDB),
+ &pointer));
+
+ kernel->db = pointer;
+ kernel->dbCreated = gcvTRUE;
+ kernel->db->freeDatabase = gcvNULL;
+ kernel->db->freeRecord = gcvNULL;
+ kernel->db->dbMutex = gcvNULL;
+ kernel->db->lastDatabase = gcvNULL;
+ kernel->db->idleTime = 0;
+ kernel->db->lastIdle = 0;
+ kernel->db->lastSlowdown = 0;
+
+ for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
+ {
+ kernel->db->db[i] = gcvNULL;
+ }
+
+ /* Construct a database mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->dbMutex));
+
+ /* Construct a video memory name database. */
+ gcmkONERROR(gckKERNEL_CreateIntegerDatabase(kernel, &kernel->db->nameDatabase));
+
+ /* Construct a video memory name database mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->nameDatabaseMutex));
+
+ /* Construct a pointer name database. */
+ gcmkONERROR(gckKERNEL_CreateIntegerDatabase(kernel, &kernel->db->pointerDatabase));
+
+ /* Construct a pointer name database mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->pointerDatabaseMutex));
+
+ /* Initialize on fault vidmem list. */
+ gcsLIST_Init(&kernel->db->onFaultVidmemList);
+ }
+ else
+ {
+ kernel->db = SharedDB;
+ kernel->dbCreated = gcvFALSE;
+ }
+
+ for (i = 0; i < gcmCOUNTOF(kernel->timers); ++i)
+ {
+ kernel->timers[i].startTime = 0;
+ kernel->timers[i].stopTime = 0;
+ }
+
+ /* Save context. */
+ kernel->context = Context;
+
+ /* Construct atom holding number of clients. */
+ kernel->atomClients = gcvNULL;
+ gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
+
+ kernel->recovery = gcvTRUE;
+ kernel->stuckDump = gcvSTUCK_DUMP_NONE;
+
+ /* Override default recovery and stuckDump setting. */
+ status = gckOS_QueryOption(Os, "recovery", &recovery);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ status = gckOS_QueryOption(Os, "stuckDump", &stuckDump);
+
+ gcmkASSERT(status == gcvSTATUS_OK);
+
+ _SetRecovery(kernel, recovery, stuckDump);
+ }
+
+ /* Need the kernel reference before gckKERNEL_Construct() completes.
+ gckOS_MapPagesEx() is called to map kernel virtual command buffers. */
+ *Kernel = kernel;
+
+ kernel->virtualBufferHead =
+ kernel->virtualBufferTail = gcvNULL;
+
+ gcmkONERROR(
+ gckOS_CreateMutex(Os, (gctPOINTER)&kernel->virtualBufferLock));
+
+#if gcdENABLE_VG
+ kernel->vg = gcvNULL;
+
+ if (Core == gcvCORE_VG)
+ {
+ /* Construct the gckMMU object. */
+ gcmkONERROR(
+ gckVGKERNEL_Construct(Os, Context, kernel, &kernel->vg));
+
+ kernel->timeOut = gcdGPU_TIMEOUT;
+ }
+ else
+#endif
+ {
+ /* Construct the gckHARDWARE object. */
+ gcmkONERROR(
+ gckHARDWARE_Construct(Os, kernel->core, &kernel->hardware));
+
+ /* Set pointer to gckKERNEL object in gckHARDWARE object. */
+ kernel->hardware->kernel = kernel;
+
+ kernel->timeOut = kernel->hardware->type == gcvHARDWARE_2D
+ ? gcdGPU_2D_TIMEOUT
+ : gcdGPU_TIMEOUT
+ ;
+
+#if (defined(LINUX) || defined(__QNXNTO__)) && !defined(EMULATOR) && !gcdALLOC_CMD_FROM_RESERVE
+ kernel->virtualCommandBuffer = gcvTRUE;
+#else
+ kernel->virtualCommandBuffer = gcvFALSE;
+#endif
+
+#if defined(UNDER_CE) && USE_KERNEL_VIRTUAL_BUFFERS
+ kernel->virtualCommandBuffer = gcvTRUE;
+#endif
+
+#if gcdSECURITY || gcdDISABLE_GPU_VIRTUAL_ADDRESS
+ kernel->virtualCommandBuffer = gcvFALSE;
+#endif
+
+#if gcdSHARED_PAGETABLE
+ /* Construct the gckMMU object. */
+ gcmkONERROR(
+ gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
+#else
+ if (Device == gcvNULL)
+ {
+ /* Construct the gckMMU object. */
+ gcmkONERROR(
+ gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
+ }
+ else
+ {
+ gcmkONERROR(gckDEVICE_GetMMU(Device, kernel->hardware->type, &kernel->mmu));
+
+ if (kernel->mmu == gcvNULL)
+ {
+ gcmkONERROR(
+ gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
+
+ gcmkONERROR(
+ gckDEVICE_SetMMU(Device, kernel->hardware->type, kernel->mmu));
+ }
+ }
+
+ gcmkVERIFY_OK(gckMMU_AttachHardware(kernel->mmu, kernel->hardware));
+#endif
+
+ /* Construct the gckCOMMAND object. */
+ gcmkONERROR(
+ gckCOMMAND_Construct(kernel, &kernel->command));
+
+ if (gckHARDWARE_IsFeatureAvailable(kernel->hardware, gcvFEATURE_BLT_ENGINE))
+ {
+ /* Construct the gckASYNC_COMMAND object for BLT engine. */
+ gcmkONERROR(gckASYNC_COMMAND_Construct(kernel, &kernel->asyncCommand));
+
+ /* Construct gckEVENT for BLT. */
+ gcmkONERROR(gckEVENT_Construct(kernel, &kernel->asyncEvent));
+
+ kernel->asyncEvent->asyncCommand = kernel->asyncCommand;
+
+ kernel->command->asyncCommand = kernel->asyncCommand;
+ }
+
+ /* Construct the gckEVENT object. */
+ gcmkONERROR(
+ gckEVENT_Construct(kernel, &kernel->eventObj));
+
+ gcmkVERIFY_OK(gckOS_GetTime(&kernel->resetTimeStamp));
+
+ gcmkONERROR(gckHARDWARE_PrepareFunctions(kernel->hardware));
+
+ /* Initialize the hardware. */
+ gcmkONERROR(
+ gckHARDWARE_InitializeHardware(kernel->hardware));
+
+#if gcdDVFS
+ if (gckHARDWARE_IsFeatureAvailable(kernel->hardware,
+ gcvFEATURE_DYNAMIC_FREQUENCY_SCALING))
+ {
+ gcmkONERROR(gckDVFS_Construct(kernel->hardware, &kernel->dvfs));
+ gcmkONERROR(gckDVFS_Start(kernel->dvfs));
+ }
+#endif
+
+#if COMMAND_PROCESSOR_VERSION == 1
+ /* Start the command queue. */
+ gcmkONERROR(gckCOMMAND_Start(kernel->command));
+#endif
+ }
+
+#if VIVANTE_PROFILER
+ /* Initialize profile setting */
+ kernel->profileEnable = gcvFALSE;
+ kernel->profileCleanRegister = gcvTRUE;
+ kernel->profileSyncMode = gcvTRUE;
+#endif
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ gcmkONERROR(gckOS_CreateSyncTimeline(Os, Core, &kernel->timeline));
+#endif
+
+#if gcdSECURITY
+ /* Connect to security service for this GPU. */
+ gcmkONERROR(gckKERNEL_SecurityOpen(kernel, kernel->core, &kernel->securityChannel));
+#endif
+
+#if gcdGPU_TIMEOUT && gcdINTERRUPT_STATISTIC
+ if (kernel->timeOut)
+ {
+ gcmkVERIFY_OK(gckOS_CreateTimer(
+ Os,
+ (gctTIMERFUNCTION)_MonitorTimerFunction,
+ (gctPOINTER)kernel,
+ &kernel->monitorTimer
+ ));
+
+ kernel->monitoring = gcvFALSE;
+
+ kernel->monitorTimerStop = gcvFALSE;
+
+ gcmkVERIFY_OK(gckOS_StartTimer(
+ Os,
+ kernel->monitorTimer,
+ 100
+ ));
+ }
+#endif
+
+ /* Return pointer to the gckKERNEL object. */
+ *Kernel = kernel;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
+ return gcvSTATUS_OK;
+
+OnError:
+ *Kernel = gcvNULL;
+
+ if (kernel != gcvNULL)
+ {
+ gckKERNEL_Destroy(kernel);
+ }
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Destroy
+**
+** Destroy an gckKERNEL object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Destroy(
+ IN gckKERNEL Kernel
+ )
+{
+ gctSIZE_T i;
+ gcsDATABASE_PTR database, databaseNext;
+ gcsDATABASE_RECORD_PTR record, recordNext;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+#if QNX_SINGLE_THREADED_DEBUGGING
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->debugMutex));
+#endif
+
+ /* Destroy the database. */
+ if (Kernel->dbCreated)
+ {
+ for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
+ {
+ if (Kernel->db->db[i] != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckKERNEL_DestroyProcessDB(Kernel, Kernel->db->db[i]->processID));
+ }
+ }
+
+ /* Free all databases. */
+ for (database = Kernel->db->freeDatabase;
+ database != gcvNULL;
+ database = databaseNext)
+ {
+ databaseNext = database->next;
+
+ if (database->counterMutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, database->counterMutex));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, database));
+ }
+
+ if (Kernel->db->lastDatabase != gcvNULL)
+ {
+ if (Kernel->db->lastDatabase->counterMutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->lastDatabase->counterMutex));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel->db->lastDatabase));
+ }
+
+ /* Free all database records. */
+ for (record = Kernel->db->freeRecord; record != gcvNULL; record = recordNext)
+ {
+ recordNext = record->next;
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
+ }
+
+ if (Kernel->db->dbMutex)
+ {
+ /* Destroy the database mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ if (Kernel->db->nameDatabase)
+ {
+ /* Destroy video memory name database. */
+ gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Kernel->db->nameDatabase));
+ }
+
+ if (Kernel->db->nameDatabaseMutex)
+ {
+ /* Destroy video memory name database mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->nameDatabaseMutex));
+ }
+
+ if (Kernel->db->pointerDatabase)
+ {
+ /* Destroy id-pointer database. */
+ gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Kernel->db->pointerDatabase));
+ }
+
+ if (Kernel->db->pointerDatabaseMutex)
+ {
+ /* Destroy id-pointer database mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ }
+
+ if (Kernel->db)
+ {
+ /* Destroy the database. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel->db));
+ }
+
+ /* Notify stuck timer to quit. */
+ Kernel->monitorTimerStop = gcvTRUE;
+ }
+
+#if gcdENABLE_VG
+ if (Kernel->vg)
+ {
+ gcmkVERIFY_OK(gckVGKERNEL_Destroy(Kernel->vg));
+ }
+ else
+#endif
+ {
+ if (Kernel->command)
+ {
+ /* Destroy the gckCOMMNAND object. */
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel->command));
+ }
+
+ if (Kernel->asyncCommand)
+ {
+ gcmkVERIFY_OK(gckASYNC_COMMAND_Destroy(Kernel->asyncCommand));
+ }
+
+ if (Kernel->asyncEvent)
+ {
+ gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->asyncEvent));
+ }
+
+ if (Kernel->eventObj)
+ {
+ /* Destroy the gckEVENT object. */
+ gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->eventObj));
+ }
+
+ gcmkVERIFY_OK(gckHARDWARE_DestroyFunctions(Kernel->hardware));
+
+ if (Kernel->mmu)
+ {
+#if gcdSHARED_PAGETABLE
+ /* Destroy the gckMMU object. */
+ gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
+#else
+ if (Kernel->mmu->hardware == Kernel->hardware)
+ {
+ /* Destroy the gckMMU object. */
+ gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
+ }
+#endif
+ }
+
+ if (Kernel->hardware)
+ {
+ /* Destroy the gckHARDWARE object. */
+ gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
+ }
+ }
+
+ if (Kernel->atomClients)
+ {
+ /* Detsroy the client atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->atomClients));
+ }
+
+ if (Kernel->virtualBufferLock)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->virtualBufferLock));
+ }
+
+#if gcdDVFS
+ if (Kernel->dvfs)
+ {
+ gcmkVERIFY_OK(gckDVFS_Stop(Kernel->dvfs));
+ gcmkVERIFY_OK(gckDVFS_Destroy(Kernel->dvfs));
+ }
+#endif
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ if (Kernel->timeline)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySyncTimeline(Kernel->os, Kernel->timeline));
+ }
+#endif
+
+#if gcdSECURITY
+ if (Kernel->securityChannel)
+ {
+ gcmkVERIFY_OK(gckKERNEL_SecurityClose(Kernel->securityChannel));
+ }
+#endif
+
+ if (Kernel->monitorTimer)
+ {
+ gcmkVERIFY_OK(gckOS_StopTimer(Kernel->os, Kernel->monitorTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Kernel->os, Kernel->monitorTimer));
+ }
+
+ /* Mark the gckKERNEL object as unknown. */
+ Kernel->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckKERNEL object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** _AllocateMemory
+**
+** Private function to walk all required memory pools to allocate the requested
+** amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS
+gckKERNEL_AllocateLinearMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcePOOL * Pool,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+ IN gctUINT32 Flag,
+ OUT gctUINT32 * Node
+ )
+{
+ gcePOOL pool;
+ gceSTATUS status;
+ gckVIDMEM videoMemory;
+ gctINT loopCount;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctBOOL tileStatusInVirtual;
+ gctBOOL contiguous = gcvFALSE;
+ gctBOOL cacheable = gcvFALSE;
+ gctBOOL secure = gcvFALSE;
+ gctSIZE_T bytes = Bytes;
+ gctUINT32 handle = 0;
+ gceDATABASE_TYPE type;
+
+ gcmkHEADER_ARG("Kernel=0x%x *Pool=%d Bytes=%lu Alignment=%lu Type=%d",
+ Kernel, *Pool, Bytes, Alignment, Type);
+
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes != 0);
+
+ /* Get basic type. */
+ Type &= 0xFF;
+
+ /* Check flags. */
+ contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
+ cacheable = Flag & gcvALLOC_FLAG_CACHEABLE;
+ secure = Flag & gcvALLOC_FLAG_SECURITY;
+
+#if gcdALLOC_ON_FAULT
+ /* VIV: Force all render target is allocated on fault. */
+ if (Type == gcvSURF_RENDER_TARGET)
+ {
+ Flag |= gcvALLOC_FLAG_ALLOC_ON_FAULT;
+ }
+#endif
+
+ if (Flag & gcvALLOC_FLAG_ALLOC_ON_FAULT)
+ {
+ *Pool = gcvPOOL_VIRTUAL;
+ }
+
+AllocateMemory:
+
+ /* Get initial pool. */
+ switch (pool = *Pool)
+ {
+ case gcvPOOL_DEFAULT:
+ case gcvPOOL_LOCAL:
+ pool = gcvPOOL_LOCAL_INTERNAL;
+ loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+ break;
+
+ case gcvPOOL_UNIFIED:
+ pool = gcvPOOL_SYSTEM;
+ loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+ break;
+
+ case gcvPOOL_CONTIGUOUS:
+ loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
+ break;
+
+ default:
+ loopCount = 1;
+ break;
+ }
+
+ while (loopCount-- > 0)
+ {
+ if (pool == gcvPOOL_VIRTUAL)
+ {
+ /* Create a gcuVIDMEM_NODE for virtual memory. */
+ gcmkONERROR(
+ gckVIDMEM_ConstructVirtual(Kernel, Flag | gcvALLOC_FLAG_NON_CONTIGUOUS, Bytes, &node));
+
+ bytes = node->Virtual.bytes;
+ node->Virtual.type = Type;
+
+ /* Success. */
+ break;
+ }
+
+ else
+ if (pool == gcvPOOL_CONTIGUOUS)
+ {
+#if gcdCONTIGUOUS_SIZE_LIMIT
+ if (Bytes > gcdCONTIGUOUS_SIZE_LIMIT && contiguous == gcvFALSE)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ }
+ else
+#endif
+ {
+ /* Create a gcuVIDMEM_NODE from contiguous memory. */
+ status = gckVIDMEM_ConstructVirtual(
+ Kernel,
+ Flag | gcvALLOC_FLAG_CONTIGUOUS,
+ Bytes,
+ &node);
+ }
+
+ if (gcmIS_SUCCESS(status))
+ {
+ bytes = node->Virtual.bytes;
+ node->Virtual.type = Type;
+
+ /* Memory allocated. */
+ break;
+ }
+ }
+
+ else
+ /* gcvPOOL_SYSTEM can't be cacheable. */
+ if (cacheable == gcvFALSE && secure == gcvFALSE)
+ {
+ /* Get pointer to gckVIDMEM object for pool. */
+ status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Allocate memory. */
+#if defined(gcdLINEAR_SIZE_LIMIT)
+ /* 512 KB */
+ if (Bytes > gcdLINEAR_SIZE_LIMIT)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ }
+ else
+#endif
+ {
+ status = gckVIDMEM_AllocateLinear(Kernel,
+ videoMemory,
+ Bytes,
+ Alignment,
+ Type,
+ (*Pool == gcvPOOL_SYSTEM),
+ &node);
+ }
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Memory allocated. */
+ node->VidMem.pool = pool;
+ bytes = node->VidMem.bytes;
+ break;
+ }
+ }
+ }
+
+ if (pool == gcvPOOL_LOCAL_INTERNAL)
+ {
+ /* Advance to external memory. */
+ pool = gcvPOOL_LOCAL_EXTERNAL;
+ }
+
+ else
+ if (pool == gcvPOOL_LOCAL_EXTERNAL)
+ {
+ /* Advance to contiguous system memory. */
+ pool = gcvPOOL_SYSTEM;
+ }
+
+ else
+ if (pool == gcvPOOL_SYSTEM)
+ {
+ /* Advance to contiguous memory. */
+ pool = gcvPOOL_CONTIGUOUS;
+ }
+
+ else
+ if (pool == gcvPOOL_CONTIGUOUS)
+ {
+#if gcdENABLE_VG
+ if (Kernel->vg)
+ {
+ tileStatusInVirtual = gcvFALSE;
+ }
+ else
+#endif
+ {
+ tileStatusInVirtual =
+ gckHARDWARE_IsFeatureAvailable(Kernel->hardware,
+ gcvFEATURE_MC20);
+ }
+
+ if (Type == gcvSURF_TILE_STATUS && tileStatusInVirtual != gcvTRUE)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ if (contiguous)
+ {
+ break;
+ }
+
+ /* Advance to virtual memory. */
+ pool = gcvPOOL_VIRTUAL;
+ }
+
+ else
+ {
+ /* Out of pools. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ if (contiguous)
+ {
+ /* Broadcast OOM message. */
+ status = gckOS_Broadcast(Kernel->os, Kernel->hardware, gcvBROADCAST_OUT_OF_MEMORY);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Get some memory. */
+ gckOS_Delay(gcvNULL, 1);
+ goto AllocateMemory;
+ }
+ }
+
+ /* Nothing allocated. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Allocate handle for this video memory. */
+ gcmkONERROR(
+ gckVIDMEM_NODE_Allocate(Kernel, node, Type, pool, &handle));
+
+ /* Return node and pool used for allocation. */
+ *Node = handle;
+ *Pool = pool;
+
+ /* Encode surface type and pool to database type. */
+ type = gcvDB_VIDEO_MEMORY
+ | (Type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+ | (pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
+
+ /* Record in process db. */
+ gcmkONERROR(
+ gckKERNEL_AddProcessDB(Kernel,
+ ProcessID,
+ type,
+ gcmINT2PTR(handle),
+ gcvNULL,
+ bytes));
+
+ /* Return status. */
+ gcmkFOOTER_ARG("*Pool=%d *Node=0x%x", *Pool, *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (handle)
+ {
+ /* Destroy handle allocated. */
+ gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(Kernel, ProcessID, handle));
+ }
+
+ if (node)
+ {
+ /* Free video memory allocated. */
+ gcmkVERIFY_OK(gckVIDMEM_Free(Kernel, node));
+ }
+
+ /* For some case like chrome with webgl test, it needs too much memory so that it invokes oom_killer
+ * And the case is killed by oom_killer, the user wants not to see the crash and hope the case iteself handles the condition
+ * So the patch reports the out_of_memory to the case */
+ if ( status == gcvSTATUS_OUT_OF_MEMORY && (Flag & gcvALLOC_FLAG_MEMLIMIT) )
+ gcmkPRINT("The running case is out_of_memory");
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_ReleaseVideoMemory
+**
+** Release handle of a video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** ProcessID of current process.
+**
+** gctUINT32 Handle
+** Handle of video memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_ReleaseVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE nodeObject;
+ gceDATABASE_TYPE type;
+
+ gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d Handle=%d",
+ Kernel, ProcessID, Handle);
+
+ gcmkONERROR(
+ gckVIDMEM_HANDLE_Lookup(Kernel, ProcessID, Handle, &nodeObject));
+
+ type = gcvDB_VIDEO_MEMORY
+ | (nodeObject->type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+ | (nodeObject->pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
+
+ gcmkONERROR(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ ProcessID,
+ type,
+ gcmINT2PTR(Handle)));
+
+ gckVIDMEM_HANDLE_Dereference(Kernel, ProcessID, Handle);
+
+ gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_LockVideoMemory
+**
+** Lock a video memory node. It will generate a cpu virtual address used
+** by software and a GPU address used by GPU.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gceCORE Core
+** GPU to which video memory is locked.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS
+gckKERNEL_LockVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gceCORE Core,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL FromUser,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE nodeObject = gcvNULL;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctBOOL locked = gcvFALSE;
+ gctBOOL asynchronous = gcvFALSE;
+#ifndef __QNXNTO__
+ gctPOINTER pointer = gcvNULL;
+#endif
+
+ gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d",
+ Kernel, ProcessID);
+
+ gcmkONERROR(
+ gckVIDMEM_HANDLE_LookupAndReference(Kernel,
+ Interface->u.LockVideoMemory.node,
+ &nodeObject));
+
+ node = nodeObject->node;
+
+ Interface->u.LockVideoMemory.gid = 0;
+
+ /* Lock video memory. */
+ gcmkONERROR(
+ gckVIDMEM_Lock(Kernel,
+ nodeObject,
+ Interface->u.LockVideoMemory.cacheable,
+ &Interface->u.LockVideoMemory.address,
+ &Interface->u.LockVideoMemory.gid,
+ &Interface->u.LockVideoMemory.physicalAddress));
+
+ locked = gcvTRUE;
+
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ /* Map video memory address into user space. */
+#ifdef __QNXNTO__
+ if (node->VidMem.logical == gcvNULL)
+ {
+ gcmkONERROR(
+ gckKERNEL_MapVideoMemory(Kernel,
+ FromUser,
+ Interface->u.LockVideoMemory.address,
+ ProcessID,
+ node->VidMem.bytes,
+ &node->VidMem.logical));
+ }
+ gcmkASSERT(node->VidMem.logical != gcvNULL);
+
+ Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->VidMem.logical);
+#else
+ gcmkONERROR(
+ gckKERNEL_MapVideoMemoryEx(Kernel,
+ Core,
+ FromUser,
+ Interface->u.LockVideoMemory.address,
+ &pointer));
+
+ Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(pointer);
+#endif
+ }
+ else
+ {
+ Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckVIDMEM_Node_Lock(
+ Kernel,
+ nodeObject,
+ &Interface->u.LockVideoMemory.address
+ ));
+#endif
+
+
+#if gcdSECURE_USER
+ /* Return logical address as physical address. */
+ Interface->u.LockVideoMemory.address =
+ (gctUINT32)(Interface->u.LockVideoMemory.memory);
+#endif
+ gcmkONERROR(
+ gckKERNEL_AddProcessDB(Kernel,
+ ProcessID, gcvDB_VIDEO_MEMORY_LOCKED,
+ gcmINT2PTR(Interface->u.LockVideoMemory.node),
+ gcvNULL,
+ 0));
+
+ gckVIDMEM_HANDLE_Reference(
+ Kernel, ProcessID, (gctUINT32)Interface->u.LockVideoMemory.node);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (locked)
+ {
+ /* Roll back the lock. */
+ gcmkVERIFY_OK(gckVIDMEM_Unlock(Kernel,
+ nodeObject,
+ gcvSURF_TYPE_UNKNOWN,
+ &asynchronous));
+
+ if (gcvTRUE == asynchronous)
+ {
+ /* Bottom Half */
+ gcmkVERIFY_OK(gckVIDMEM_Unlock(Kernel,
+ nodeObject,
+ gcvSURF_TYPE_UNKNOWN,
+ gcvNULL));
+ }
+ }
+
+ if (nodeObject != gcvNULL)
+ {
+ gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_UnlockVideoMemory
+**
+** Unlock a video memory node.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** ProcessID of current process.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS
+gckKERNEL_UnlockVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE nodeObject;
+#if gcdSECURE_USER
+ gcuVIDMEM_NODE_PTR node;
+#endif
+
+ gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d",
+ Kernel, ProcessID);
+
+ gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
+ Kernel,
+ ProcessID,
+ (gctUINT32)Interface->u.UnlockVideoMemory.node,
+ &nodeObject));
+
+#if gcdSECURE_USER
+ node = nodeObject->node;
+
+ /* Unlock video memory. */
+ /* Save node information before it disappears. */
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ logical = gcvNULL;
+ bytes = 0;
+ }
+ else
+ {
+ logical = node->Virtual.logical;
+ bytes = node->Virtual.bytes;
+ }
+#endif
+
+ /* Unlock video memory. */
+ gcmkONERROR(gckVIDMEM_Unlock(
+ Kernel,
+ nodeObject,
+ Interface->u.UnlockVideoMemory.type,
+ &Interface->u.UnlockVideoMemory.asynchroneous));
+
+#if gcdSECURE_USER
+ /* Flush the translation cache for virtual surfaces. */
+ if (logical != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
+ cache,
+ logical,
+ bytes));
+ }
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_BottomHalfUnlockVideoMemory
+**
+** Unlock video memory from gpu.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID owning this memory.
+**
+** gctPOINTER Pointer
+** Video memory to be unlock.
+*/
+gceSTATUS
+gckKERNEL_BottomHalfUnlockVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Node
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE BottomHalfUnlockNode = gcvNULL;
+
+ do
+ {
+ /* Remove record from process db. */
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Kernel,
+ ProcessID,
+ gcvDB_VIDEO_MEMORY_LOCKED,
+ gcmINT2PTR(Node)));
+
+ gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(
+ Kernel,
+ ProcessID,
+ Node,
+ &BottomHalfUnlockNode));
+
+ gckVIDMEM_HANDLE_Dereference(Kernel, ProcessID, Node);
+
+ /* Unlock video memory. */
+ gcmkERR_BREAK(gckVIDMEM_Unlock(
+ Kernel,
+ BottomHalfUnlockNode,
+ gcvSURF_TYPE_UNKNOWN,
+ gcvNULL));
+
+ gcmkERR_BREAK(gckVIDMEM_NODE_Dereference(
+ Kernel,
+ BottomHalfUnlockNode));
+ }
+ while (gcvFALSE);
+
+ return gcvSTATUS_OK;
+}
+
+
+gceSTATUS
+gckKERNEL_QueryDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gctINT i;
+
+ gceDATABASE_TYPE type[3] = {
+ gcvDB_VIDEO_MEMORY | (gcvPOOL_SYSTEM << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
+ gcvDB_VIDEO_MEMORY | (gcvPOOL_CONTIGUOUS << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
+ gcvDB_VIDEO_MEMORY | (gcvPOOL_VIRTUAL << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
+ };
+
+ gcmkHEADER();
+
+ /* Query video memory. */
+ gcmkONERROR(
+ gckKERNEL_QueryProcessDB(Kernel,
+ Interface->u.Database.processID,
+ !Interface->u.Database.validProcessID,
+ gcvDB_VIDEO_MEMORY,
+ &Interface->u.Database.vidMem));
+
+ /* Query non-paged memory. */
+ gcmkONERROR(
+ gckKERNEL_QueryProcessDB(Kernel,
+ Interface->u.Database.processID,
+ !Interface->u.Database.validProcessID,
+ gcvDB_NON_PAGED,
+ &Interface->u.Database.nonPaged));
+
+ /* Query contiguous memory. */
+ gcmkONERROR(
+ gckKERNEL_QueryProcessDB(Kernel,
+ Interface->u.Database.processID,
+ !Interface->u.Database.validProcessID,
+ gcvDB_CONTIGUOUS,
+ &Interface->u.Database.contiguous));
+
+ /* Query GPU idle time. */
+ gcmkONERROR(
+ gckKERNEL_QueryProcessDB(Kernel,
+ Interface->u.Database.processID,
+ !Interface->u.Database.validProcessID,
+ gcvDB_IDLE,
+ &Interface->u.Database.gpuIdle));
+ for (i = 0; i < 3; i++)
+ {
+ /* Query each video memory pool. */
+ gcmkONERROR(
+ gckKERNEL_QueryProcessDB(Kernel,
+ Interface->u.Database.processID,
+ !Interface->u.Database.validProcessID,
+ type[i],
+ &Interface->u.Database.vidMemPool[i]));
+ }
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gckKERNEL_DumpVidMemUsage(Kernel, Interface->u.Database.processID);
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_ConfigPowerManagement(
+ IN gckKERNEL Kernel,
+ IN OUT gcsHAL_INTERFACE * Interface
+)
+{
+ gceSTATUS status;
+ gctBOOL enable = Interface->u.ConfigPowerManagement.enable;
+
+ gcmkHEADER();
+
+ gcmkONERROR(gckHARDWARE_SetPowerManagement(Kernel->hardware, enable));
+
+ if (enable == gcvFALSE)
+ {
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Kernel->hardware, gcvPOWER_ON));
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_WrapUserMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gctUINT32 * Node
+ )
+{
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctUINT32 handle;
+ gceDATABASE_TYPE databaseRecordType;
+
+ gcmkHEADER_ARG("Kernel=0x%X Desc=%x", Kernel, Desc);
+
+ gcmkONERROR(gckVIDMEM_ConstructVirtualFromUserMemory(
+ Kernel,
+ Desc,
+ &node
+ ));
+
+ /* Allocate handle for this video memory. */
+ gcmkONERROR(gckVIDMEM_NODE_Allocate(
+ Kernel,
+ node,
+ gcvSURF_BITMAP,
+ gcvPOOL_VIRTUAL,
+ &handle
+ ));
+
+ /* Wrapped node is treated as gcvPOOL_VIRTUAL, but in statistic view,
+ * it is gcvPOOL_USER.
+ */
+ databaseRecordType
+ = gcvDB_VIDEO_MEMORY
+ | (gcvSURF_BITMAP << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+ | (gcvPOOL_VIRTUAL << gcdDB_VIDEO_MEMORY_POOL_SHIFT)
+ ;
+
+ /* Record in process db. */
+ gcmkONERROR(gckKERNEL_AddProcessDB(
+ Kernel,
+ ProcessID,
+ databaseRecordType,
+ gcmINT2PTR(handle),
+ gcvNULL,
+ node->Virtual.bytes
+ ));
+
+ /* Return handle of the node. */
+ *Node = handle;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_WaitFence(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Handle,
+ IN gctUINT32 TimeOut
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE node;
+ gctUINT32 processID;
+ gckCOMMAND command = Kernel->command;
+ gckASYNC_COMMAND asyncCommand = Kernel->asyncCommand;
+ gckFENCE fence = gcvNULL;
+ gctUINT i;
+
+ gckOS_GetProcessID(&processID);
+
+ gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
+
+ /* Wait for fence of all engines. */
+ for (i = 0; i < gcvENGINE_COUNT; i++)
+ {
+ gckFENCE_SYNC sync = &node->sync[i];
+
+ if (i == gcvENGINE_RENDER)
+ {
+ fence = command->fence;
+ }
+ else
+ {
+ fence = asyncCommand->fence;
+ }
+
+ if (sync->commitStamp <= *(gctUINT64_PTR)fence->logical)
+ {
+ continue;
+ }
+ else
+ {
+ gckOS_Signal(Kernel->os, sync->signal, gcvFALSE);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, &fence->mutex, gcvINFINITE));
+
+ /* Add to waiting list. */
+ gcsLIST_AddTail(&sync->head, &fence->waitingList);
+
+ gcmkASSERT(sync->inList == gcvFALSE);
+
+ sync->inList = gcvTRUE;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, &fence->mutex));
+
+ /* Wait. */
+ status = gckOS_WaitSignal(Kernel->os, sync->signal, gcvTRUE, TimeOut);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, &fence->mutex, gcvINFINITE));
+
+ if (sync->inList)
+ {
+ gcsLIST_Del(&sync->head);
+ sync->inList = gcvFALSE;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, &fence->mutex));
+ }
+ }
+
+ gckVIDMEM_NODE_Dereference(Kernel, node);
+
+OnError:
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Dispatch
+**
+** Dispatch a command received from the user HAL layer.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL FromUser
+** whether the call is from the user space.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS
+gckKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gckDEVICE Device,
+ IN gctBOOL FromUser,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctPHYS_ADDR physical = gcvNULL;
+ gctSIZE_T bytes;
+ gctPOINTER logical = gcvNULL;
+#if (gcdENABLE_3D || gcdENABLE_2D)
+ gckCONTEXT context = gcvNULL;
+#endif
+ gckKERNEL kernel = Kernel;
+ gctUINT32 processID;
+#if gcdSECURE_USER
+ gcskSECURE_CACHE_PTR cache;
+ gctPOINTER logical;
+#endif
+ gctUINT64 paddr = gcvINVALID_ADDRESS;
+#if !USE_NEW_LINUX_SIGNAL
+ gctSIGNAL signal;
+#endif
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
+
+ gctBOOL powerMutexAcquired = gcvFALSE;
+ gctBOOL commitMutexAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
+ Kernel, FromUser, Interface);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "Dispatching command %d (%s)",
+ Interface->command, _DispatchText[Interface->command]);
+#endif
+#if QNX_SINGLE_THREADED_DEBUGGING
+ gckOS_AcquireMutex(Kernel->os, Kernel->debugMutex, gcvINFINITE);
+#endif
+
+ /* Get the current process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+#if gcdSECURE_USER
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
+#endif
+
+ /* Dispatch on command. */
+ switch (Interface->command)
+ {
+ case gcvHAL_GET_BASE_ADDRESS:
+ /* Get base address. */
+ Interface->u.GetBaseAddress.baseAddress = Kernel->hardware->baseAddress;
+ Interface->u.GetBaseAddress.flatMappingStart = Kernel->mmu->flatMappingStart;
+ Interface->u.GetBaseAddress.flatMappingEnd = Kernel->mmu->flatMappingEnd;
+ break;
+
+ case gcvHAL_QUERY_VIDEO_MEMORY:
+ /* Query video memory size. */
+ gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
+ break;
+
+ case gcvHAL_QUERY_CHIP_IDENTITY:
+ /* Query chip identity. */
+ gcmkONERROR(
+ gckHARDWARE_QueryChipIdentity(
+ Kernel->hardware,
+ &Interface->u.QueryChipIdentity));
+ break;
+
+ case gcvHAL_MAP_MEMORY:
+ physical = gcmINT2PTR(Interface->u.MapMemory.physical);
+
+ /* Map memory. */
+ gcmkONERROR(
+ gckKERNEL_MapMemory(Kernel,
+ physical,
+ (gctSIZE_T) Interface->u.MapMemory.bytes,
+ &logical));
+
+ Interface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_MAP_MEMORY,
+ logical,
+ physical,
+ (gctSIZE_T) Interface->u.MapMemory.bytes));
+ break;
+
+ case gcvHAL_UNMAP_MEMORY:
+ physical = gcmINT2PTR(Interface->u.UnmapMemory.physical);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ processID, gcvDB_MAP_MEMORY,
+ gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
+
+ /* Unmap memory. */
+ gcmkONERROR(
+ gckKERNEL_UnmapMemory(Kernel,
+ physical,
+ (gctSIZE_T) Interface->u.UnmapMemory.bytes,
+ gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
+ break;
+
+ case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
+ bytes = (gctSIZE_T) Interface->u.AllocateNonPagedMemory.bytes;
+
+ /* Allocate non-paged memory. */
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemory(
+ Kernel->os,
+ FromUser,
+ &bytes,
+ &physical,
+ &logical));
+
+ Interface->u.AllocateNonPagedMemory.bytes = bytes;
+ Interface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
+ Interface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_NON_PAGED,
+ logical,
+ gcmINT2PTR(Interface->u.AllocateNonPagedMemory.physical),
+ bytes));
+ break;
+
+ case gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER:
+ bytes = (gctSIZE_T) Interface->u.AllocateVirtualCommandBuffer.bytes;
+
+ gcmkONERROR(
+ gckKERNEL_AllocateVirtualCommandBuffer(
+ Kernel,
+ FromUser,
+ &bytes,
+ &physical,
+ &logical));
+
+ Interface->u.AllocateVirtualCommandBuffer.bytes = bytes;
+ Interface->u.AllocateVirtualCommandBuffer.logical = gcmPTR_TO_UINT64(logical);
+ Interface->u.AllocateVirtualCommandBuffer.physical = gcmPTR_TO_NAME(physical);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_COMMAND_BUFFER,
+ logical,
+ gcmINT2PTR(Interface->u.AllocateVirtualCommandBuffer.physical),
+ bytes));
+ break;
+
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ physical = gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ processID, gcvDB_NON_PAGED,
+ gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+
+ /* Unmap user logical out of physical memory first. */
+ gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
+ physical,
+ (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
+ gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+
+ /* Free non-paged memory. */
+ gcmkONERROR(
+ gckOS_FreeNonPagedMemory(Kernel->os,
+ (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
+ physical,
+ gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+
+#if gcdSECURE_USER
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Kernel,
+ cache,
+ gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical),
+ (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes));
+#endif
+
+ gcmRELEASE_NAME(Interface->u.FreeNonPagedMemory.physical);
+ break;
+
+ case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+ bytes = (gctSIZE_T) Interface->u.AllocateContiguousMemory.bytes;
+
+ /* Allocate contiguous memory. */
+ gcmkONERROR(gckOS_AllocateContiguous(
+ Kernel->os,
+ FromUser,
+ &bytes,
+ &physical,
+ &logical));
+
+ Interface->u.AllocateContiguousMemory.bytes = bytes;
+ Interface->u.AllocateContiguousMemory.logical = gcmPTR_TO_UINT64(logical);
+ Interface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
+
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ Kernel->hardware,
+ logical,
+ gcvTRUE,
+ &Interface->u.AllocateContiguousMemory.address));
+
+ gcmkVERIFY_OK(gckKERNEL_AddProcessDB(
+ Kernel,
+ processID, gcvDB_CONTIGUOUS,
+ logical,
+ gcmINT2PTR(Interface->u.AllocateContiguousMemory.physical),
+ bytes));
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ physical = gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ processID, gcvDB_CONTIGUOUS,
+ gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+
+ /* Unmap user logical out of physical memory first. */
+ gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
+ physical,
+ (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
+ gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
+
+ /* Free contiguous memory. */
+ gcmkONERROR(
+ gckOS_FreeContiguous(Kernel->os,
+ physical,
+ gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
+ (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes));
+
+#if gcdSECURE_USER
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Kernel,
+ cache,
+ gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
+ (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes));
+#endif
+
+ gcmRELEASE_NAME(Interface->u.FreeContiguousMemory.physical);
+ break;
+
+ case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+
+ break;
+
+ case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+ /* Allocate memory. */
+ gcmkONERROR(
+ gckKERNEL_AllocateLinearMemory(Kernel, processID,
+ &Interface->u.AllocateLinearVideoMemory.pool,
+ Interface->u.AllocateLinearVideoMemory.bytes,
+ Interface->u.AllocateLinearVideoMemory.alignment,
+ Interface->u.AllocateLinearVideoMemory.type,
+ Interface->u.AllocateLinearVideoMemory.flag,
+ &Interface->u.AllocateLinearVideoMemory.node));
+ break;
+
+ case gcvHAL_RELEASE_VIDEO_MEMORY:
+ /* Release video memory. */
+ gcmkONERROR(gckKERNEL_ReleaseVideoMemory(
+ Kernel, processID,
+ (gctUINT32)Interface->u.ReleaseVideoMemory.node
+ ));
+ break;
+
+ case gcvHAL_LOCK_VIDEO_MEMORY:
+ /* Lock video memory. */
+ gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, Kernel->core, processID, FromUser, Interface));
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ /* Unlock video memory. */
+ gcmkONERROR(gckKERNEL_UnlockVideoMemory(Kernel, processID, Interface));
+ break;
+
+ case gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY:
+ gcmkERR_BREAK(gckKERNEL_BottomHalfUnlockVideoMemory(Kernel, processID,
+ Interface->u.BottomHalfUnlockVideoMemory.node));
+ break;
+
+ case gcvHAL_EVENT_COMMIT:
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os,
+ Kernel->device->commitMutex,
+ gcvINFINITE
+ ));
+
+ commitMutexAcquired = gcvTRUE;
+ /* Commit an event queue. */
+ if (Interface->u.Event.engine == gcvENGINE_BLT)
+ {
+ if (!gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_BLT_ENGINE))
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ gcmkONERROR(gckEVENT_Commit(
+ Kernel->asyncEvent, gcmUINT64_TO_PTR(Interface->u.Event.queue)));
+ }
+ else
+ {
+ gcmkONERROR(gckEVENT_Commit(
+ Kernel->eventObj, gcmUINT64_TO_PTR(Interface->u.Event.queue)));
+ }
+
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->device->commitMutex));
+ commitMutexAcquired = gcvFALSE;
+ break;
+
+ case gcvHAL_COMMIT:
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os,
+ Kernel->device->commitMutex,
+ gcvINFINITE
+ ));
+ commitMutexAcquired = gcvTRUE;
+
+ /* Commit a command and context buffer. */
+ if (Interface->u.Commit.engine == gcvENGINE_BLT)
+ {
+ gctUINT64 *commandBuffers = gcmUINT64_TO_PTR(Interface->u.Commit.commandBuffer);
+
+ if (!gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_BLT_ENGINE))
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ gcmkONERROR(gckASYNC_COMMAND_Commit(
+ Kernel->asyncCommand,
+ gcmUINT64_TO_PTR(commandBuffers[0]),
+ gcmUINT64_TO_PTR(Interface->u.Commit.queue)
+ ));
+
+ gcmkONERROR(gckEVENT_Commit(
+ Kernel->asyncEvent,
+ gcmUINT64_TO_PTR(Interface->u.Commit.queue)
+ ));
+ }
+ else
+ {
+
+
+ status = gckCOMMAND_Commit(Kernel->command,
+ Interface->u.Commit.contexts[0] ?
+ gcmNAME_TO_PTR(Interface->u.Commit.contexts[0]) : gcvNULL,
+ gcmUINT64_TO_PTR(Interface->u.Commit.commandBuffers[0]),
+ gcmUINT64_TO_PTR(Interface->u.Commit.deltas[0]),
+ gcmUINT64_TO_PTR(Interface->u.Commit.queue),
+ processID,
+ Interface->u.Commit.shared,
+ Interface->u.Commit.index,
+ &Interface->u.Commit.commitStamp,
+ &Interface->u.Commit.contextSwitched
+ );
+
+ if (status != gcvSTATUS_INTERRUPTED)
+ {
+ gcmkONERROR(status);
+ }
+
+ if (Interface->u.Commit.count > 1 && Interface->u.Commit.engine == gcvENGINE_RENDER)
+ {
+ gctUINT32 i;
+
+ for (i = 1; i < Interface->u.Commit.count; i++)
+ {
+ gceHARDWARE_TYPE type = Interface->hardwareType;
+ gckKERNEL kernel = Device->map[type].kernels[i];
+
+ status = gckCOMMAND_Commit(kernel->command,
+ Interface->u.Commit.contexts[i] ?
+ gcmNAME_TO_PTR(Interface->u.Commit.contexts[i]) : gcvNULL,
+ Interface->u.Commit.commandBuffers[i] ?
+ gcmUINT64_TO_PTR(Interface->u.Commit.commandBuffers[i]) : gcmUINT64_TO_PTR(Interface->u.Commit.commandBuffers[0]),
+ gcmUINT64_TO_PTR(Interface->u.Commit.deltas[i]),
+ gcvNULL,
+ processID,
+ Interface->u.Commit.shared,
+ Interface->u.Commit.commandBuffers[i] ?
+ Interface->u.Commit.index : i,
+ &Interface->u.Commit.commitStamp,
+ &Interface->u.Commit.contextSwitched
+ );
+
+ if (status != gcvSTATUS_INTERRUPTED)
+ {
+ gcmkONERROR(status);
+ }
+ }
+ }
+ }
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->device->commitMutex));
+ commitMutexAcquired = gcvFALSE;
+
+ break;
+
+ case gcvHAL_STALL:
+ /* Stall the command queue. */
+ gcmkONERROR(gckCOMMAND_Stall(Kernel->command, gcvFALSE));
+
+ break;
+
+ case gcvHAL_MAP_USER_MEMORY:
+
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+
+ break;
+
+#if !USE_NEW_LINUX_SIGNAL
+ case gcvHAL_USER_SIGNAL:
+ /* Dispatch depends on the user signal subcommands. */
+ switch(Interface->u.UserSignal.command)
+ {
+ case gcvUSER_SIGNAL_CREATE:
+ /* Create a signal used in the user space. */
+ gcmkONERROR(
+ gckOS_CreateUserSignal(Kernel->os,
+ Interface->u.UserSignal.manualReset,
+ &Interface->u.UserSignal.id));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id),
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvUSER_SIGNAL_DESTROY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id)));
+
+ /* Destroy the signal. */
+ gcmkONERROR(
+ gckOS_DestroyUserSignal(Kernel->os,
+ Interface->u.UserSignal.id));
+ break;
+
+ case gcvUSER_SIGNAL_SIGNAL:
+ /* Signal the signal. */
+ gcmkONERROR(
+ gckOS_SignalUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.state));
+ break;
+
+ case gcvUSER_SIGNAL_WAIT:
+ /* Wait on the signal. */
+ status = gckOS_WaitUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.wait);
+ break;
+
+ case gcvUSER_SIGNAL_MAP:
+ gcmkONERROR(
+ gckOS_MapSignal(Kernel->os,
+ (gctSIGNAL)(gctUINTPTR_T)Interface->u.UserSignal.id,
+ (gctHANDLE)(gctUINTPTR_T)processID,
+ &signal));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id),
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvUSER_SIGNAL_UNMAP:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id)));
+
+ /* Destroy the signal. */
+ gcmkONERROR(
+ gckOS_DestroyUserSignal(Kernel->os,
+ Interface->u.UserSignal.id));
+ break;
+
+ default:
+ /* Invalid user signal command. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+ break;
+#endif
+
+ case gcvHAL_SET_POWER_MANAGEMENT_STATE:
+ /* Set the power management state. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(
+ Kernel->hardware,
+ Interface->u.SetPowerManagement.state));
+ break;
+
+ case gcvHAL_QUERY_POWER_MANAGEMENT_STATE:
+ /* Chip is not idle. */
+ Interface->u.QueryPowerManagement.isIdle = gcvFALSE;
+
+ /* Query the power management state. */
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
+ Kernel->hardware,
+ &Interface->u.QueryPowerManagement.state));
+
+ /* Query the idle state. */
+ gcmkONERROR(
+ gckHARDWARE_QueryIdle(Kernel->hardware,
+ &Interface->u.QueryPowerManagement.isIdle));
+ break;
+
+ case gcvHAL_READ_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ {
+ gceCHIPPOWERSTATE power;
+
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE));
+ powerMutexAcquired = gcvTRUE;
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
+ &power));
+ if (power == gcvPOWER_ON)
+ {
+ /* Read a register. */
+ gcmkONERROR(gckOS_ReadRegisterEx(
+ Kernel->os,
+ Kernel->core,
+ Interface->u.ReadRegisterData.address,
+ &Interface->u.ReadRegisterData.data));
+ }
+ else
+ {
+ /* Chip is in power-state. */
+ Interface->u.ReadRegisterData.data = 0;
+ status = gcvSTATUS_CHIP_NOT_READY;
+ }
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+ powerMutexAcquired = gcvFALSE;
+ }
+#else
+ /* No access from user land to read registers. */
+ Interface->u.ReadRegisterData.data = 0;
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_WRITE_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ {
+ gceCHIPPOWERSTATE power;
+
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE));
+ powerMutexAcquired = gcvTRUE;
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
+ &power));
+ if (power == gcvPOWER_ON)
+ {
+ /* Write a register. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Kernel->os,
+ Kernel->core,
+ Interface->u.WriteRegisterData.address,
+ Interface->u.WriteRegisterData.data));
+ }
+ else
+ {
+ /* Chip is in power-state. */
+ Interface->u.WriteRegisterData.data = 0;
+ status = gcvSTATUS_CHIP_NOT_READY;
+ }
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+ powerMutexAcquired = gcvFALSE;
+ }
+#else
+ /* No access from user land to write registers. */
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_READ_ALL_PROFILE_REGISTERS:
+#if VIVANTE_PROFILER && VIVANTE_PROFILER_CONTEXT
+ if (Kernel->profileSyncMode)
+ {
+ /* Read profile data according to the context. */
+ gcmkONERROR(
+ gckHARDWARE_QueryContextProfile(
+ Kernel->hardware,
+ Kernel->profileCleanRegister,
+ gcmNAME_TO_PTR(Interface->u.RegisterProfileData.context),
+ &Interface->u.RegisterProfileData.counters));
+ }
+ else
+ {
+ /* Read all 3D profile registers. */
+ gcmkONERROR(
+ gckHARDWARE_QueryProfileRegisters(
+ Kernel->hardware,
+ Kernel->profileCleanRegister,
+ &Interface->u.RegisterProfileData.counters));
+ }
+#elif VIVANTE_PROFILER
+ /* Read all 3D profile registers. */
+ gcmkONERROR(
+ gckHARDWARE_QueryProfileRegisters(
+ Kernel->hardware,
+ Kernel->profileCleanRegister,
+ &Interface->u.RegisterProfileData.counters));
+#else
+ status = gcvSTATUS_OK;
+#endif
+ break;
+
+ case gcvHAL_READ_ALL_PROFILE_NEW_REGISTERS_PART1:
+ if (Kernel->profileSyncMode)
+ {
+ /* Read profile data according to the context. */
+ gcmkONERROR(
+ gckHARDWARE_QueryContextNewProfile(
+ Kernel->hardware,
+ Kernel->profileCleanRegister,
+ gcmNAME_TO_PTR(Interface->u.RegisterProfileNewData_part1.context),
+ &Interface->u.RegisterProfileNewData_part1.newCounters,
+ gcvNULL));
+ }
+ break;
+ case gcvHAL_READ_ALL_PROFILE_NEW_REGISTERS_PART2:
+ if (Kernel->profileSyncMode)
+ {
+ /* Read profile data according to the context. */
+ gcmkONERROR(
+ gckHARDWARE_QueryContextNewProfile(
+ Kernel->hardware,
+ Kernel->profileCleanRegister,
+ gcmNAME_TO_PTR(Interface->u.RegisterProfileNewData_part2.context),
+ gcvNULL,
+ &Interface->u.RegisterProfileNewData_part2.newCounters));
+ }
+ break;
+
+ case gcvHAL_GET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+ /* Get profile setting */
+ Interface->u.GetProfileSetting.enable = Kernel->profileEnable;
+ Interface->u.GetProfileSetting.syncMode = Kernel->profileSyncMode;
+#endif
+
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_SET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+#if VIVANTE_PROFILER_PROBE
+ gckHARDWARE_InitProfiler(Kernel->hardware);
+#else
+ /* Set profile setting */
+ if(Kernel->hardware->gpuProfiler)
+ {
+ Kernel->profileEnable = Interface->u.SetProfileSetting.enable;
+ Kernel->profileSyncMode = Interface->u.SetProfileSetting.syncMode;
+
+ if (Kernel->profileEnable)
+ {
+ gcmkONERROR(gckHARDWARE_InitProfiler(Kernel->hardware));
+ }
+
+ }
+ else
+ {
+ status = gcvSTATUS_NOT_SUPPORTED;
+ break;
+ }
+#endif
+#endif
+
+ status = gcvSTATUS_OK;
+ break;
+
+#if VIVANTE_PROFILER_PERDRAW
+ case gcvHAL_READ_PROFILER_REGISTER_SETTING:
+ #if VIVANTE_PROFILER
+ Kernel->profileCleanRegister = Interface->u.SetProfilerRegisterClear.bclear;
+ #endif
+ status = gcvSTATUS_OK;
+ break;
+#endif
+ case gcvHAL_READ_PROFILER_NEW_REGISTER_SETTING:
+ Kernel->profileCleanRegister = Interface->u.SetProfilerRegisterClear.bclear;
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_QUERY_KERNEL_SETTINGS:
+ /* Get kernel settings. */
+ gcmkONERROR(
+ gckKERNEL_QuerySettings(Kernel,
+ &Interface->u.QueryKernelSettings.settings));
+ break;
+
+ case gcvHAL_RESET:
+ /* Reset the hardware. */
+ gcmkONERROR(
+ gckHARDWARE_Reset(Kernel->hardware));
+ break;
+
+ case gcvHAL_DEBUG:
+ /* Set debug level and zones. */
+ if (Interface->u.Debug.set)
+ {
+ gckOS_SetDebugLevel(Interface->u.Debug.level);
+ gckOS_SetDebugZones(Interface->u.Debug.zones,
+ Interface->u.Debug.enable);
+ }
+
+ if (Interface->u.Debug.message[0] != '\0')
+ {
+ /* Print a message to the debugger. */
+ if (Interface->u.Debug.type == gcvMESSAGE_TEXT)
+ {
+ gckOS_DumpBuffer(Kernel->os,
+ Interface->u.Debug.message,
+ gcmSIZEOF(Interface->u.Debug.message),
+ gceDUMP_BUFFER_FROM_USER,
+ gcvTRUE);
+ }
+ else
+ {
+ gckOS_DumpBuffer(Kernel->os,
+ Interface->u.Debug.message,
+ Interface->u.Debug.messageSize,
+ gceDUMP_BUFFER_FROM_USER,
+ gcvTRUE);
+ }
+ }
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_DUMP_GPU_STATE:
+ {
+ gceCHIPPOWERSTATE power;
+
+ _DumpDriverConfigure(Kernel);
+
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
+ Kernel->hardware,
+ &power
+ ));
+
+ if (power == gcvPOWER_ON)
+ {
+ Interface->u.ReadRegisterData.data = 1;
+
+ _DumpState(Kernel);
+ }
+ else
+ {
+ Interface->u.ReadRegisterData.data = 0;
+ status = gcvSTATUS_CHIP_NOT_READY;
+
+ gcmkPRINT("[galcore]: Can't dump state if GPU isn't POWER ON.");
+ }
+ }
+ break;
+
+ case gcvHAL_DUMP_EVENT:
+ break;
+
+ case gcvHAL_CACHE:
+
+ logical = gcmUINT64_TO_PTR(Interface->u.Cache.logical);
+
+ bytes = (gctSIZE_T) Interface->u.Cache.bytes;
+ switch(Interface->u.Cache.operation)
+ {
+ case gcvCACHE_FLUSH:
+ /* Clean and invalidate the cache. */
+ status = gckOS_CacheFlush(Kernel->os,
+ processID,
+ physical,
+ paddr,
+ logical,
+ bytes);
+ break;
+ case gcvCACHE_CLEAN:
+ /* Clean the cache. */
+ status = gckOS_CacheClean(Kernel->os,
+ processID,
+ physical,
+ paddr,
+ logical,
+ bytes);
+ break;
+ case gcvCACHE_INVALIDATE:
+ /* Invalidate the cache. */
+ status = gckOS_CacheInvalidate(Kernel->os,
+ processID,
+ physical,
+ paddr,
+ logical,
+ bytes);
+ break;
+
+ case gcvCACHE_MEMORY_BARRIER:
+ status = gckOS_MemoryBarrier(Kernel->os,
+ logical);
+ break;
+ default:
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+ break;
+
+ case gcvHAL_TIMESTAMP:
+ /* Check for invalid timer. */
+ if ((Interface->u.TimeStamp.timer >= gcmCOUNTOF(Kernel->timers))
+ || (Interface->u.TimeStamp.request != 2))
+ {
+ Interface->u.TimeStamp.timeDelta = 0;
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Return timer results and reset timer. */
+ {
+ gcsTIMER_PTR timer = &(Kernel->timers[Interface->u.TimeStamp.timer]);
+ gctUINT64 timeDelta = 0;
+
+ if (timer->stopTime < timer->startTime )
+ {
+ Interface->u.TimeStamp.timeDelta = 0;
+ gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
+ }
+
+ timeDelta = timer->stopTime - timer->startTime;
+
+ /* Check truncation overflow. */
+ Interface->u.TimeStamp.timeDelta = (gctINT32) timeDelta;
+ /*bit0~bit30 is available*/
+ if (timeDelta>>31)
+ {
+ Interface->u.TimeStamp.timeDelta = 0;
+ gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
+ }
+
+ status = gcvSTATUS_OK;
+ }
+ break;
+
+ case gcvHAL_DATABASE:
+ gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
+ break;
+
+ case gcvHAL_VERSION:
+ Interface->u.Version.major = gcvVERSION_MAJOR;
+ Interface->u.Version.minor = gcvVERSION_MINOR;
+ Interface->u.Version.patch = gcvVERSION_PATCH;
+ Interface->u.Version.build = gcvVERSION_BUILD;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "KERNEL version %d.%d.%d build %u",
+ gcvVERSION_MAJOR, gcvVERSION_MINOR,
+ gcvVERSION_PATCH, gcvVERSION_BUILD);
+#endif
+ break;
+
+ case gcvHAL_CHIP_INFO:
+ /* Only if not support multi-core */
+ Interface->u.ChipInfo.count = 1;
+ Interface->u.ChipInfo.types[0] = Kernel->hardware->type;
+ break;
+
+#if (gcdENABLE_3D || gcdENABLE_2D)
+ case gcvHAL_ATTACH:
+ /* Attach user process. */
+ gcmkONERROR(
+ gckCOMMAND_Attach(Kernel->command,
+ &context,
+ &bytes,
+ &Interface->u.Attach.numStates,
+ processID));
+
+ Interface->u.Attach.maxState = bytes;
+ Interface->u.Attach.context = gcmPTR_TO_NAME(context);
+
+ if (Interface->u.Attach.map == gcvTRUE)
+ {
+ gcmkVERIFY_OK(
+ gckCONTEXT_MapBuffer(context,
+ Interface->u.Attach.physicals,
+ Interface->u.Attach.logicals,
+ &Interface->u.Attach.bytes));
+ }
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_CONTEXT,
+ gcmINT2PTR(Interface->u.Attach.context),
+ gcvNULL,
+ 0));
+ break;
+#endif
+
+ case gcvHAL_DETACH:
+ gcmkVERIFY_OK(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ processID, gcvDB_CONTEXT,
+ gcmINT2PTR(Interface->u.Detach.context)));
+
+ /* Detach user process. */
+ gcmkONERROR(
+ gckCOMMAND_Detach(Kernel->command,
+ gcmNAME_TO_PTR(Interface->u.Detach.context)));
+
+ gcmRELEASE_NAME(Interface->u.Detach.context);
+ break;
+
+ case gcvHAL_COMPOSE:
+ Interface->u.Compose.physical = gcmPTR_TO_UINT64(gcmNAME_TO_PTR(Interface->u.Compose.physical));
+ /* Start composition. */
+ gcmkONERROR(
+ gckEVENT_Compose(Kernel->eventObj,
+ &Interface->u.Compose));
+ break;
+
+ case gcvHAL_GET_FRAME_INFO:
+ gcmkONERROR(gckHARDWARE_GetFrameInfo(
+ Kernel->hardware,
+ gcmUINT64_TO_PTR(Interface->u.GetFrameInfo.frameInfo)));
+ break;
+
+ case gcvHAL_DUMP_GPU_PROFILE:
+ gcmkONERROR(gckHARDWARE_DumpGpuProfile(Kernel->hardware));
+ break;
+
+ case gcvHAL_SET_FSCALE_VALUE:
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ status = gckHARDWARE_SetFscaleValue(Kernel->hardware,
+ Interface->u.SetFscaleValue.value);
+#else
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+ case gcvHAL_GET_FSCALE_VALUE:
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ status = gckHARDWARE_GetFscaleValue(Kernel->hardware,
+ &Interface->u.GetFscaleValue.value,
+ &Interface->u.GetFscaleValue.minValue,
+ &Interface->u.GetFscaleValue.maxValue);
+#else
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_NAME_VIDEO_MEMORY:
+ gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
+ Interface->u.NameVideoMemory.handle,
+ &Interface->u.NameVideoMemory.name));
+ break;
+
+ case gcvHAL_IMPORT_VIDEO_MEMORY:
+ gcmkONERROR(gckVIDMEM_NODE_Import(Kernel,
+ Interface->u.ImportVideoMemory.name,
+ &Interface->u.ImportVideoMemory.handle));
+
+ gcmkONERROR(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_VIDEO_MEMORY,
+ gcmINT2PTR(Interface->u.ImportVideoMemory.handle),
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvHAL_GET_VIDEO_MEMORY_FD:
+ gcmkONERROR(gckVIDMEM_NODE_GetFd(
+ Kernel,
+ Interface->u.GetVideoMemoryFd.handle,
+ &Interface->u.GetVideoMemoryFd.fd
+ ));
+
+ /* No need to add it to processDB because OS will release all fds when
+ ** process quits.
+ */
+ break;
+
+ case gcvHAL_QUERY_RESET_TIME_STAMP:
+ Interface->u.QueryResetTimeStamp.timeStamp = Kernel->resetTimeStamp;
+ Interface->u.QueryResetTimeStamp.contextID = Kernel->hardware->contextID;
+ break;
+
+ case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+ buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)gcmNAME_TO_PTR(Interface->u.FreeVirtualCommandBuffer.physical);
+
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Kernel,
+ processID,
+ gcvDB_COMMAND_BUFFER,
+ gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
+
+ gcmkONERROR(gckOS_DestroyUserVirtualMapping(
+ Kernel->os,
+ buffer->virtualBuffer.physical,
+ (gctSIZE_T)Interface->u.FreeVirtualCommandBuffer.bytes,
+ gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
+
+ gcmkONERROR(gckKERNEL_DestroyVirtualCommandBuffer(
+ Kernel,
+ (gctSIZE_T)Interface->u.FreeVirtualCommandBuffer.bytes,
+ (gctPHYS_ADDR)buffer,
+ gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
+
+ gcmRELEASE_NAME(Interface->u.FreeVirtualCommandBuffer.physical);
+ break;
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ case gcvHAL_CREATE_NATIVE_FENCE:
+ {
+ gctINT fenceFD;
+ gctSIGNAL signal =
+ gcmUINT64_TO_PTR(Interface->u.CreateNativeFence.signal);
+
+ gcmkONERROR(
+ gckOS_CreateNativeFence(Kernel->os,
+ Kernel->timeline,
+ signal,
+ &fenceFD));
+
+ Interface->u.CreateNativeFence.fenceFD = fenceFD;
+ }
+ break;
+
+ case gcvHAL_WAIT_NATIVE_FENCE:
+ {
+ gctINT fenceFD;
+ gctUINT32 timeout;
+
+ fenceFD = Interface->u.WaitNativeFence.fenceFD;
+ timeout = Interface->u.WaitNativeFence.timeout;
+
+ gcmkONERROR(
+ gckOS_WaitNativeFence(Kernel->os,
+ Kernel->timeline,
+ fenceFD,
+ timeout));
+ }
+ break;
+#endif
+
+ case gcvHAL_SHBUF:
+ {
+ gctSHBUF shBuf;
+ gctPOINTER uData;
+ gctUINT32 bytes;
+
+ switch (Interface->u.ShBuf.command)
+ {
+ case gcvSHBUF_CREATE:
+ bytes = Interface->u.ShBuf.bytes;
+
+ /* Create. */
+ gcmkONERROR(gckKERNEL_CreateShBuffer(Kernel, bytes, &shBuf));
+
+ Interface->u.ShBuf.id = gcmPTR_TO_UINT64(shBuf);
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID,
+ gcvDB_SHBUF,
+ shBuf,
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvSHBUF_DESTROY:
+ shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+
+ /* Check db first to avoid illegal destroy in the process. */
+ gcmkONERROR(
+ gckKERNEL_RemoveProcessDB(Kernel,
+ processID,
+ gcvDB_SHBUF,
+ shBuf));
+
+ gcmkONERROR(gckKERNEL_DestroyShBuffer(Kernel, shBuf));
+ break;
+
+ case gcvSHBUF_MAP:
+ shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+
+ /* Map for current process access. */
+ gcmkONERROR(gckKERNEL_MapShBuffer(Kernel, shBuf));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID,
+ gcvDB_SHBUF,
+ shBuf,
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvSHBUF_WRITE:
+ shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+ uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
+ bytes = Interface->u.ShBuf.bytes;
+
+ /* Write. */
+ gcmkONERROR(
+ gckKERNEL_WriteShBuffer(Kernel, shBuf, uData, bytes));
+ break;
+
+ case gcvSHBUF_READ:
+ shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
+ uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
+ bytes = Interface->u.ShBuf.bytes;
+
+ /* Read. */
+ gcmkONERROR(
+ gckKERNEL_ReadShBuffer(Kernel,
+ shBuf,
+ uData,
+ bytes,
+ &bytes));
+
+ /* Return copied size. */
+ Interface->u.ShBuf.bytes = bytes;
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ break;
+ }
+ }
+ break;
+
+
+ case gcvHAL_CONFIG_POWER_MANAGEMENT:
+ gcmkONERROR(gckKERNEL_ConfigPowerManagement(Kernel, Interface));
+ break;
+
+ case gcvHAL_WRAP_USER_MEMORY:
+ gcmkONERROR(gckKERNEL_WrapUserMemory(
+ Kernel,
+ processID,
+ &Interface->u.WrapUserMemory.desc,
+ &Interface->u.WrapUserMemory.node
+ ));
+ break;
+
+ case gcvHAL_WAIT_FENCE:
+ gcmkONERROR(gckKERNEL_WaitFence(
+ Kernel,
+ Interface->u.WaitFence.handle,
+ Interface->u.WaitFence.timeOut
+ ));
+ break;
+
+#if gcdDEC_ENABLE_AHB
+ case gcvHAL_DEC300_READ:
+ gcmkONERROR(viv_dec300_read(
+ Interface->u.DEC300Read.enable,
+ Interface->u.DEC300Read.readId,
+ Interface->u.DEC300Read.format,
+ Interface->u.DEC300Read.strides,
+ Interface->u.DEC300Read.is3D,
+ Interface->u.DEC300Read.isMSAA,
+ Interface->u.DEC300Read.clearValue,
+ Interface->u.DEC300Read.isTPC,
+ Interface->u.DEC300Read.isTPCCompressed,
+ Interface->u.DEC300Read.surfAddrs,
+ Interface->u.DEC300Read.tileAddrs
+ ));
+ break;
+
+ case gcvHAL_DEC300_WRITE:
+ gcmkONERROR(viv_dec300_write(
+ Interface->u.DEC300Write.enable,
+ Interface->u.DEC300Write.readId,
+ Interface->u.DEC300Write.writeId,
+ Interface->u.DEC300Write.format,
+ Interface->u.DEC300Write.surfAddr,
+ Interface->u.DEC300Write.tileAddr
+ ));
+ break;
+
+ case gcvHAL_DEC300_FLUSH:
+ gcmkONERROR(viv_dec300_flush(0));
+ break;
+
+ case gcvHAL_DEC300_FLUSH_WAIT:
+ gcmkONERROR(viv_dec300_flush_done(&Interface->u.DEC300FlushWait.done));
+ break;
+#endif
+
+
+ default:
+ /* Invalid command. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+OnError:
+ /* Save status. */
+ Interface->status = status;
+
+#if QNX_SINGLE_THREADED_DEBUGGING
+ gckOS_ReleaseMutex(Kernel->os, Kernel->debugMutex);
+#endif
+
+ if (powerMutexAcquired == gcvTRUE)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
+ }
+
+ if (commitMutexAcquired == gcvTRUE)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->device->commitMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_AttachProcess
+**
+** Attach or detach a process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL Attach
+** gcvTRUE if a new process gets attached or gcFALSE when a process
+** gets detatched.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_AttachProcess(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach
+ )
+{
+ gceSTATUS status;
+ gctUINT32 processID;
+
+ gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Get current process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ gcmkONERROR(gckKERNEL_AttachProcessEx(Kernel, Attach, processID));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_AttachProcessEx
+**
+** Attach or detach a process with the given PID. Can be paired with gckKERNEL_AttachProcess
+** provided the programmer is aware of the consequences.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL Attach
+** gcvTRUE if a new process gets attached or gcFALSE when a process
+** gets detatched.
+**
+** gctUINT32 PID
+** PID of the process to attach or detach.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_AttachProcessEx(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach,
+ IN gctUINT32 PID
+ )
+{
+ gceSTATUS status;
+ gctINT32 old;
+
+ gcmkHEADER_ARG("Kernel=0x%x Attach=%d PID=%d", Kernel, Attach, PID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (Attach)
+ {
+ /* Increment the number of clients attached. */
+ gcmkONERROR(
+ gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old));
+
+ if (old == 0)
+ {
+#if gcdENABLE_VG
+ if (Kernel->vg == gcvNULL)
+#endif
+ {
+ gcmkONERROR(gckOS_Broadcast(Kernel->os,
+ Kernel->hardware,
+ gcvBROADCAST_FIRST_PROCESS));
+ }
+ }
+
+ if (Kernel->dbCreated)
+ {
+ /* Create the process database. */
+ gcmkONERROR(gckKERNEL_CreateProcessDB(Kernel, PID));
+ }
+
+#if gcdPROCESS_ADDRESS_SPACE
+ /* Map kernel command buffer in the process's own MMU. */
+ gcmkONERROR(_MapCommandBuffer(Kernel));
+#endif
+ }
+ else
+ {
+ if (Kernel->dbCreated)
+ {
+ /* Clean up the process database. */
+ gcmkONERROR(gckKERNEL_DestroyProcessDB(Kernel, PID));
+
+ /* Save the last know process ID. */
+ Kernel->db->lastProcessID = PID;
+ }
+
+#if gcdENABLE_VG
+ if (Kernel->vg == gcvNULL)
+#endif
+ {
+ status = gckEVENT_Submit(Kernel->eventObj, gcvTRUE, gcvFALSE);
+
+ if (status == gcvSTATUS_INTERRUPTED && Kernel->eventObj->submitTimer)
+ {
+ gcmkONERROR(gckOS_StartTimer(Kernel->os,
+ Kernel->eventObj->submitTimer,
+ 1));
+ }
+ else
+ {
+ gcmkONERROR(status);
+ }
+ }
+
+ /* Decrement the number of clients attached. */
+ gcmkONERROR(
+ gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
+
+ if (old == 1)
+ {
+#if gcdENABLE_VG
+ if (Kernel->vg == gcvNULL)
+#endif
+ {
+ /* Last client detached, switch to SUSPEND power state. */
+ gcmkONERROR(gckOS_Broadcast(Kernel->os,
+ Kernel->hardware,
+ gcvBROADCAST_LAST_PROCESS));
+ }
+
+ /* Flush the debug cache. */
+ gcmkDEBUGFLUSH(~0U);
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+ IN gckKERNEL Kernel,
+ IN gcskSECURE_CACHE_PTR Cache,
+ IN OUT gctPOINTER * Data
+ )
+{
+ gceSTATUS status;
+ static gctBOOL baseAddressValid = gcvFALSE;
+ static gctUINT32 baseAddress;
+ gctBOOL needBase;
+ gcskLOGICAL_CACHE_PTR slot;
+
+ gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x *Data=0x%x",
+ Kernel, Cache, gcmOPT_POINTER(Data));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (!baseAddressValid)
+ {
+ /* Get base address. */
+ gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));
+
+ baseAddressValid = gcvTRUE;
+ }
+
+ /* Does this state load need a base address? */
+ gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
+ ((gctUINT32_PTR) Data)[-1],
+ &needBase));
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
+ {
+ gcskLOGICAL_CACHE_PTR next;
+ gctINT i;
+
+ /* Walk all used cache slots. */
+ for (i = 1, slot = Cache->cache[0].next, next = gcvNULL;
+ (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+ ++i, slot = slot->next
+ )
+ {
+ if (slot->logical == *Data)
+ {
+ /* Bail out. */
+ next = slot;
+ break;
+ }
+ }
+
+ /* See if we had a miss. */
+ if (next == gcvNULL)
+ {
+ /* Use the tail of the cache. */
+ slot = Cache->cache[0].prev;
+
+ /* Initialize the cache line. */
+ slot->logical = *Data;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+ }
+
+ /* Move slot to head of list. */
+ if (slot != Cache->cache[0].next)
+ {
+ /* Unlink. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Move to head of chain. */
+ slot->prev = &Cache->cache[0];
+ slot->next = Cache->cache[0].next;
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+ }
+ }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+ {
+ gctINT i;
+ gcskLOGICAL_CACHE_PTR next = gcvNULL;
+ gcskLOGICAL_CACHE_PTR oldestSlot = gcvNULL;
+ slot = gcvNULL;
+
+ if (Cache->cacheIndex != gcvNULL)
+ {
+ /* Walk the cache forwards. */
+ for (i = 1, slot = Cache->cacheIndex;
+ (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+ ++i, slot = slot->next)
+ {
+ if (slot->logical == *Data)
+ {
+ /* Bail out. */
+ next = slot;
+ break;
+ }
+
+ /* Determine age of this slot. */
+ if ((oldestSlot == gcvNULL)
+ || (oldestSlot->stamp > slot->stamp)
+ )
+ {
+ oldestSlot = slot;
+ }
+ }
+
+ if (next == gcvNULL)
+ {
+ /* Walk the cache backwards. */
+ for (slot = Cache->cacheIndex->prev;
+ (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+ ++i, slot = slot->prev)
+ {
+ if (slot->logical == *Data)
+ {
+ /* Bail out. */
+ next = slot;
+ break;
+ }
+
+ /* Determine age of this slot. */
+ if ((oldestSlot == gcvNULL)
+ || (oldestSlot->stamp > slot->stamp)
+ )
+ {
+ oldestSlot = slot;
+ }
+ }
+ }
+ }
+
+ /* See if we had a miss. */
+ if (next == gcvNULL)
+ {
+ if (Cache->cacheFree != 0)
+ {
+ slot = &Cache->cache[Cache->cacheFree];
+ gcmkASSERT(slot->logical == gcvNULL);
+
+ ++ Cache->cacheFree;
+ if (Cache->cacheFree >= gcmCOUNTOF(Cache->cache))
+ {
+ Cache->cacheFree = 0;
+ }
+ }
+ else
+ {
+ /* Use the oldest cache slot. */
+ gcmkASSERT(oldestSlot != gcvNULL);
+ slot = oldestSlot;
+
+ /* Unlink from the chain. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Append to the end. */
+ slot->prev = Cache->cache[0].prev;
+ slot->next = &Cache->cache[0];
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+ }
+
+ /* Initialize the cache line. */
+ slot->logical = *Data;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+ }
+
+ /* Save time stamp. */
+ slot->stamp = ++ Cache->cacheStamp;
+
+ /* Save current slot for next lookup. */
+ Cache->cacheIndex = slot;
+ }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ {
+ gctINT i;
+ gctUINT32 data = gcmPTR2INT32(*Data);
+ gctUINT32 key, index;
+ gcskLOGICAL_CACHE_PTR hash;
+
+ /* Generate a hash key. */
+ key = (data >> 24) + (data >> 16) + (data >> 8) + data;
+ index = key % gcmCOUNTOF(Cache->hash);
+
+ /* Get the hash entry. */
+ hash = &Cache->hash[index];
+
+ for (slot = hash->nextHash, i = 0;
+ (slot != gcvNULL) && (i < gcdSECURE_CACHE_SLOTS);
+ slot = slot->nextHash, ++i
+ )
+ {
+ if (slot->logical == (*Data))
+ {
+ break;
+ }
+ }
+
+ if (slot == gcvNULL)
+ {
+ /* Grab from the tail of the cache. */
+ slot = Cache->cache[0].prev;
+
+ /* Unlink slot from any hash table it is part of. */
+ if (slot->prevHash != gcvNULL)
+ {
+ slot->prevHash->nextHash = slot->nextHash;
+ }
+ if (slot->nextHash != gcvNULL)
+ {
+ slot->nextHash->prevHash = slot->prevHash;
+ }
+
+ /* Initialize the cache line. */
+ slot->logical = *Data;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+
+ if (hash->nextHash != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "Hash Collision: logical=0x%x key=0x%08x",
+ *Data, key);
+ }
+
+ /* Insert the slot at the head of the hash list. */
+ slot->nextHash = hash->nextHash;
+ if (slot->nextHash != gcvNULL)
+ {
+ slot->nextHash->prevHash = slot;
+ }
+ slot->prevHash = hash;
+ hash->nextHash = slot;
+ }
+
+ /* Move slot to head of list. */
+ if (slot != Cache->cache[0].next)
+ {
+ /* Unlink. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Move to head of chain. */
+ slot->prev = &Cache->cache[0];
+ slot->next = Cache->cache[0].next;
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+ }
+ }
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
+ {
+ gctUINT32 index = (gcmPTR2INT32(*Data) % gcdSECURE_CACHE_SLOTS) + 1;
+
+ /* Get cache slot. */
+ slot = &Cache->cache[index];
+
+ /* Check for cache miss. */
+ if (slot->logical != *Data)
+ {
+ /* Initialize the cache line. */
+ slot->logical = *Data;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
+ }
+ }
+#endif
+
+ /* Return DMA address. */
+ *Data = gcmINT2PTR(slot->dma + (needBase ? baseAddress : 0));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_FlushTranslationCache(
+ IN gckKERNEL Kernel,
+ IN gcskSECURE_CACHE_PTR Cache,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gctINT i;
+ gcskLOGICAL_CACHE_PTR slot;
+ gctUINT8_PTR ptr;
+
+ gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x Logical=0x%x Bytes=%lu",
+ Kernel, Cache, Logical, Bytes);
+
+ /* Do we need to flush the entire cache? */
+ if (Logical == gcvNULL)
+ {
+ /* Clear all cache slots. */
+ for (i = 1; i <= gcdSECURE_CACHE_SLOTS; ++i)
+ {
+ Cache->cache[i].logical = gcvNULL;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ Cache->cache[i].nextHash = gcvNULL;
+ Cache->cache[i].prevHash = gcvNULL;
+#endif
+}
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ /* Zero the hash table. */
+ for (i = 0; i < gcmCOUNTOF(Cache->hash); ++i)
+ {
+ Cache->hash[i].nextHash = gcvNULL;
+ }
+#endif
+
+ /* Reset the cache functionality. */
+ Cache->cacheIndex = gcvNULL;
+ Cache->cacheFree = 1;
+ Cache->cacheStamp = 0;
+ }
+
+ else
+ {
+ gctUINT8_PTR low = (gctUINT8_PTR) Logical;
+ gctUINT8_PTR high = low + Bytes;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
+ gcskLOGICAL_CACHE_PTR next;
+
+ /* Walk all used cache slots. */
+ for (i = 1, slot = Cache->cache[0].next;
+ (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+ ++i, slot = next
+ )
+ {
+ /* Save pointer to next slot. */
+ next = slot->next;
+
+ /* Test if this slot falls within the range to flush. */
+ ptr = (gctUINT8_PTR) slot->logical;
+ if ((ptr >= low) && (ptr < high))
+ {
+ /* Unlink slot. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Append slot to tail of cache. */
+ slot->prev = Cache->cache[0].prev;
+ slot->next = &Cache->cache[0];
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+
+ /* Mark slot as empty. */
+ slot->logical = gcvNULL;
+ }
+ }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+ gcskLOGICAL_CACHE_PTR next;
+
+ for (i = 1, slot = Cache->cache[0].next;
+ (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
+ ++i, slot = next)
+ {
+ /* Save pointer to next slot. */
+ next = slot->next;
+
+ /* Test if this slot falls within the range to flush. */
+ ptr = (gctUINT8_PTR) slot->logical;
+ if ((ptr >= low) && (ptr < high))
+ {
+ /* Test if this slot is the current slot. */
+ if (slot == Cache->cacheIndex)
+ {
+ /* Move to next or previous slot. */
+ Cache->cacheIndex = (slot->next->logical != gcvNULL)
+ ? slot->next
+ : (slot->prev->logical != gcvNULL)
+ ? slot->prev
+ : gcvNULL;
+ }
+
+ /* Unlink slot from cache. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Insert slot to head of cache. */
+ slot->prev = &Cache->cache[0];
+ slot->next = Cache->cache[0].next;
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+
+ /* Mark slot as empty. */
+ slot->logical = gcvNULL;
+ slot->stamp = 0;
+ }
+ }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ gctINT j;
+ gcskLOGICAL_CACHE_PTR hash, next;
+
+ /* Walk all hash tables. */
+ for (i = 0, hash = Cache->hash;
+ i < gcmCOUNTOF(Cache->hash);
+ ++i, ++hash)
+ {
+ /* Walk all slots in the hash. */
+ for (j = 0, slot = hash->nextHash;
+ (j < gcdSECURE_CACHE_SLOTS) && (slot != gcvNULL);
+ ++j, slot = next)
+ {
+ /* Save pointer to next slot. */
+ next = slot->next;
+
+ /* Test if this slot falls within the range to flush. */
+ ptr = (gctUINT8_PTR) slot->logical;
+ if ((ptr >= low) && (ptr < high))
+ {
+ /* Unlink slot from hash table. */
+ if (slot->prevHash == hash)
+ {
+ hash->nextHash = slot->nextHash;
+ }
+ else
+ {
+ slot->prevHash->nextHash = slot->nextHash;
+ }
+
+ if (slot->nextHash != gcvNULL)
+ {
+ slot->nextHash->prevHash = slot->prevHash;
+ }
+
+ /* Unlink slot from cache. */
+ slot->prev->next = slot->next;
+ slot->next->prev = slot->prev;
+
+ /* Append slot to tail of cache. */
+ slot->prev = Cache->cache[0].prev;
+ slot->next = &Cache->cache[0];
+ slot->prev->next = slot;
+ slot->next->prev = slot;
+
+ /* Mark slot as empty. */
+ slot->logical = gcvNULL;
+ slot->prevHash = gcvNULL;
+ slot->nextHash = gcvNULL;
+ }
+ }
+ }
+
+#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
+ gctUINT32 index;
+
+ /* Loop while inside the range. */
+ for (i = 1; (low < high) && (i <= gcdSECURE_CACHE_SLOTS); ++i)
+ {
+ /* Get index into cache for this range. */
+ index = (gcmPTR2INT32(low) % gcdSECURE_CACHE_SLOTS) + 1;
+ slot = &Cache->cache[index];
+
+ /* Test if this slot falls within the range to flush. */
+ ptr = (gctUINT8_PTR) slot->logical;
+ if ((ptr >= low) && (ptr < high))
+ {
+ /* Remove entry from cache. */
+ slot->logical = gcvNULL;
+ }
+
+ /* Next block. */
+ low += gcdSECURE_CACHE_SLOTS;
+ }
+#endif
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckKERNEL_Recovery
+**
+** Try to recover the GPU from a fatal error.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+ IN gckKERNEL Kernel
+ )
+{
+ gceSTATUS status;
+ gckEVENT eventObj;
+ gckHARDWARE hardware;
+#if gcdSECURE_USER
+ gctUINT32 processID;
+ gcskSECURE_CACHE_PTR cache;
+#endif
+ gctUINT32 mask = 0;
+ gctUINT32 i = 0, count = 0;
+#if gcdINTERRUPT_STATISTIC
+ gctINT32 oldValue;
+#endif
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Validate the arguemnts. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Grab gckEVENT object. */
+ eventObj = Kernel->eventObj;
+ gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
+
+ /* Grab gckHARDWARE object. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+#if gcdSECURE_USER
+ /* Flush the secure mapping cache. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
+ gcmkONERROR(gckKERNEL_FlushTranslationCache(Kernel, cache, gcvNULL, 0));
+#endif
+
+ if (Kernel->stuckDump == gcvSTUCK_DUMP_NONE)
+ {
+ gcmkPRINT("[galcore]: GPU[%d] hang, automatic recovery.", Kernel->core);
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->device->stuckDumpMutex, gcvINFINITE));
+
+ _DumpDriverConfigure(Kernel);
+ _DumpState(Kernel);
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->device->stuckDumpMutex));
+ }
+
+ if (Kernel->recovery == gcvFALSE)
+ {
+ gcmkPRINT("[galcore]: Stop driver to keep scene.");
+
+ /* Stop monitor timer. */
+ Kernel->monitorTimerStop = gcvTRUE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Issuing a soft reset for the GPU. */
+ gcmkONERROR(gckHARDWARE_Reset(hardware));
+
+ mask = Kernel->restoreMask;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (mask & (1 << i))
+ {
+ count++;
+ }
+ }
+
+ /* Handle all outstanding events now. */
+ gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, mask));
+
+#if gcdINTERRUPT_STATISTIC
+ while (count--)
+ {
+ gcmkONERROR(gckOS_AtomDecrement(
+ Kernel->os,
+ eventObj->interruptCount,
+ &oldValue
+ ));
+ }
+
+ gckOS_AtomClearMask(Kernel->hardware->pendingEvent, mask);
+#endif
+
+ gcmkONERROR(gckEVENT_Notify(eventObj, 1));
+
+ gcmkVERIFY_OK(gckOS_GetTime(&Kernel->resetTimeStamp));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_OpenUserData
+**
+** Get access to the user data.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL NeedCopy
+** The flag indicating whether or not the data should be copied.
+**
+** gctPOINTER StaticStorage
+** Pointer to the kernel storage where the data is to be copied if
+** NeedCopy is gcvTRUE.
+**
+** gctPOINTER UserPointer
+** User pointer to the data.
+**
+** gctSIZE_T Size
+** Size of the data.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to the kernel pointer that will be pointing to the data.
+*/
+gceSTATUS
+gckKERNEL_OpenUserData(
+ IN gckKERNEL Kernel,
+ IN gctBOOL NeedCopy,
+ IN gctPOINTER StaticStorage,
+ IN gctPOINTER UserPointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG(
+ "Kernel=0x%08X NeedCopy=%d StaticStorage=0x%08X "
+ "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
+ Kernel, NeedCopy, StaticStorage, UserPointer, Size, KernelPointer
+ );
+
+ /* Validate the arguemnts. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(!NeedCopy || (StaticStorage != gcvNULL));
+ gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+
+ if (NeedCopy)
+ {
+ /* Copy the user data to the static storage. */
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Kernel->os, StaticStorage, UserPointer, Size
+ ));
+
+ /* Set the kernel pointer. */
+ * KernelPointer = StaticStorage;
+ }
+ else
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ /* Map the user pointer. */
+ gcmkONERROR(gckOS_MapUserPointer(
+ Kernel->os, UserPointer, Size, &pointer
+ ));
+
+ /* Set the kernel pointer. */
+ * KernelPointer = pointer;
+ }
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_CloseUserData
+**
+** Release resources associated with the user data connection opened by
+** gckKERNEL_OpenUserData.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL NeedCopy
+** The flag indicating whether or not the data should be copied.
+**
+** gctBOOL FlushData
+** If gcvTRUE, the data is written back to the user.
+**
+** gctPOINTER UserPointer
+** User pointer to the data.
+**
+** gctSIZE_T Size
+** Size of the data.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Kernel pointer to the data.
+*/
+gceSTATUS
+gckKERNEL_CloseUserData(
+ IN gckKERNEL Kernel,
+ IN gctBOOL NeedCopy,
+ IN gctBOOL FlushData,
+ IN gctPOINTER UserPointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctPOINTER pointer;
+
+ gcmkHEADER_ARG(
+ "Kernel=0x%08X NeedCopy=%d FlushData=%d "
+ "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
+ Kernel, NeedCopy, FlushData, UserPointer, Size, KernelPointer
+ );
+
+ /* Validate the arguemnts. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+
+ /* Get a shortcut to the kernel pointer. */
+ pointer = * KernelPointer;
+
+ if (pointer != gcvNULL)
+ {
+ if (NeedCopy)
+ {
+ if (FlushData)
+ {
+ gcmkONERROR(gckOS_CopyToUserData(
+ Kernel->os, * KernelPointer, UserPointer, Size
+ ));
+ }
+ }
+ else
+ {
+ /* Unmap record from kernel memory. */
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Kernel->os,
+ UserPointer,
+ Size,
+ * KernelPointer
+ ));
+ }
+
+ /* Reset the kernel pointer. */
+ * KernelPointer = gcvNULL;
+ }
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_AllocateVirtualCommandBuffer(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gceSTATUS status;
+ gckOS os = Kernel->os;
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
+
+ gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+ os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+ gcmkVERIFY_ARGUMENT(*Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gcmkONERROR(
+ gckOS_Allocate(
+ os,
+ sizeof(gckVIRTUAL_COMMAND_BUFFER),
+ (gctPOINTER)&buffer
+ ));
+
+ gcmkONERROR(gckOS_ZeroMemory(buffer, sizeof(gckVIRTUAL_COMMAND_BUFFER)));
+
+ gcmkONERROR(
+ gckKERNEL_AllocateVirtualMemory(
+ Kernel,
+ gcvFALSE,
+ InUserSpace,
+ Bytes,
+ (gctPHYS_ADDR *)&buffer,
+ Logical
+ ));
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, Kernel->virtualBufferLock, gcvINFINITE));
+
+ if (Kernel->virtualBufferHead == gcvNULL)
+ {
+ Kernel->virtualBufferHead =
+ Kernel->virtualBufferTail = buffer;
+ }
+ else
+ {
+ buffer->prev = Kernel->virtualBufferTail;
+ Kernel->virtualBufferTail->next = buffer;
+ Kernel->virtualBufferTail = buffer;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Kernel->virtualBufferLock));
+
+ *Physical = buffer;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkVERIFY_OK(gckOS_Free(os, buffer));
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_DestroyVirtualCommandBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ )
+{
+ gckOS os;
+ gckKERNEL kernel;
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)Physical;
+
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(buffer != gcvNULL);
+
+ kernel = buffer->virtualBuffer.kernel;
+ os = kernel->os;
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, kernel->virtualBufferLock, gcvINFINITE));
+
+ if (buffer == kernel->virtualBufferHead)
+ {
+ if ((kernel->virtualBufferHead = buffer->next) == gcvNULL)
+ {
+ kernel->virtualBufferTail = gcvNULL;
+ }
+ }
+ else
+ {
+ buffer->prev->next = buffer->next;
+
+ if (buffer == kernel->virtualBufferTail)
+ {
+ kernel->virtualBufferTail = buffer->prev;
+ }
+ else
+ {
+ buffer->next->prev = buffer->prev;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, kernel->virtualBufferLock));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_FreeVirtualMemory(
+ Physical,
+ Logical,
+ gcvFALSE
+ ));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckKERNEL_AllocateVirtualMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL NonPaged,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gckOS os = Kernel->os;
+ gceSTATUS status;
+ gctPOINTER logical = gcvNULL;
+ gctSIZE_T pageCount;
+ gctSIZE_T bytes = *Bytes;
+ gckVIRTUAL_BUFFER_PTR buffer = gcvNULL;
+ gckMMU mmu = gcvNULL;
+ gctUINT32 flag = gcvALLOC_FLAG_NON_CONTIGUOUS;
+
+ gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+ os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+ gcmkVERIFY_ARGUMENT(*Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ if (*Physical == gcvNULL)
+ {
+ gcmkONERROR(gckOS_Allocate(os,
+ sizeof(gckVIRTUAL_BUFFER),
+ (gctPOINTER)&buffer));
+
+ gcmkONERROR(gckOS_ZeroMemory(buffer, sizeof(gckVIRTUAL_BUFFER)));
+ }
+ else
+ {
+ buffer = *Physical;
+ }
+
+ buffer->bytes = bytes;
+
+ if (NonPaged)
+ {
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ os,
+ InUserSpace,
+ &bytes,
+ &buffer->physical,
+ &logical
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_AllocatePagedMemoryEx(os,
+ flag,
+ bytes,
+ gcvNULL,
+ &buffer->physical));
+ }
+
+ if (NonPaged)
+ {
+ gctSIZE_T pageSize;
+ gcmkONERROR(gckOS_GetPageSize(os, &pageSize));
+
+ pageCount = (bytes + pageSize - 1) / pageSize;
+
+ if (InUserSpace)
+ {
+ *Logical =
+ buffer->userLogical = logical;
+ }
+ else
+ {
+ *Logical =
+ buffer->kernelLogical = logical;
+ }
+ }
+ else
+ {
+ if (InUserSpace)
+ {
+ gcmkONERROR(gckOS_CreateUserVirtualMapping(os,
+ buffer->physical,
+ bytes,
+ &logical,
+ &pageCount));
+
+ *Logical =
+ buffer->userLogical = logical;
+ }
+ else
+ {
+ gcmkONERROR(gckOS_CreateKernelVirtualMapping(os,
+ buffer->physical,
+ bytes,
+ &logical,
+ &pageCount));
+
+ *Logical =
+ buffer->kernelLogical = logical;
+ }
+
+ }
+
+ buffer->pageCount = pageCount;
+ buffer->kernel = Kernel;
+
+ gcmkONERROR(gckOS_GetProcessID(&buffer->pid));
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
+ buffer->mmu = mmu;
+#else
+ mmu = Kernel->mmu;
+#endif
+
+ gcmkONERROR(gckMMU_AllocatePages(mmu,
+ pageCount,
+ &buffer->pageTable,
+ &buffer->gpuAddress));
+
+#if gcdENABLE_TRUST_APPLICATION
+ if (Kernel->hardware->secureMode == gcvSECURE_IN_TA)
+ {
+ gcmkONERROR(gckKERNEL_MapInTrustApplicaiton(
+ Kernel,
+ logical,
+ buffer->physical,
+ buffer->gpuAddress,
+ pageCount
+ ));
+ }
+ else
+#endif
+ {
+ gcmkONERROR(gckOS_MapPagesEx(os,
+ Kernel->core,
+ buffer->physical,
+ pageCount,
+ buffer->gpuAddress,
+ buffer->pageTable,
+ gcvFALSE,
+ gcvSURF_TYPE_UNKNOWN
+ ));
+ }
+
+ gcmkONERROR(gckMMU_Flush(mmu, gcvSURF_INDEX));
+
+ if (*Physical == gcvNULL)
+ *Physical = buffer;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "gpuAddress = %x pageCount = %d kernelLogical = %x userLogical=%x",
+ buffer->gpuAddress, buffer->pageCount,
+ buffer->kernelLogical, buffer->userLogical);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (buffer && buffer->gpuAddress)
+ {
+ gcmkVERIFY_OK(
+ gckMMU_FreePages(mmu, gcvFALSE, buffer->gpuAddress, buffer->pageTable, buffer->pageCount));
+ }
+
+ if (NonPaged && buffer->physical)
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ os,
+ bytes,
+ buffer->physical,
+ logical
+ ));
+ }
+ else
+ {
+ if (buffer && buffer->userLogical)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DestroyUserVirtualMapping(os,
+ buffer->physical,
+ bytes,
+ (NonPaged ? 0 : buffer->userLogical)));
+ }
+
+ if (buffer && buffer->kernelLogical)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DestroyKernelVirtualMapping(os,
+ buffer->physical,
+ bytes,
+ (NonPaged ? 0 : buffer->kernelLogical)));
+ }
+
+ if (buffer && buffer->physical)
+ {
+ gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, bytes));
+ }
+ }
+
+ if (*Physical == gcvNULL)
+ gcmkVERIFY_OK(gckOS_Free(os, buffer));
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+
+}
+
+gceSTATUS
+gckKERNEL_FreeVirtualMemory(
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctBOOL NonPaged
+ )
+{
+ gckOS os;
+ gckKERNEL kernel;
+ gckMMU mmu;
+ gckVIRTUAL_BUFFER_PTR buffer = (gckVIRTUAL_BUFFER_PTR)Physical;
+
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(buffer != gcvNULL);
+
+ kernel = buffer->kernel;
+ os = kernel->os;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
+#else
+ mmu = kernel->mmu;
+#endif
+
+ if (!buffer->userLogical && !NonPaged)
+ {
+ gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(os,
+ buffer->physical,
+ buffer->bytes,
+ Logical));
+ }
+
+ gcmkVERIFY_OK(
+ gckMMU_FreePages(mmu, gcvFALSE, buffer->gpuAddress, buffer->pageTable, buffer->pageCount));
+
+ gcmkVERIFY_OK(gckOS_UnmapPages(os, buffer->pageCount, buffer->gpuAddress));
+
+ if (NonPaged)
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ os,
+ buffer->bytes,
+ buffer->physical,
+ Logical
+ ));
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, buffer->bytes));
+ }
+
+ gcmkVERIFY_OK(gckOS_Free(os, buffer));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckKERNEL_GetGPUAddress(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ IN gctPHYS_ADDR Physical,
+ OUT gctUINT32 * Address
+ )
+{
+ gckVIRTUAL_BUFFER_PTR buffer = Physical;
+ gctPOINTER start;
+
+ gcmkHEADER_ARG("Logical = %x InUserSpace=%d.", Logical, InUserSpace);
+
+ if (InUserSpace)
+ {
+ start = buffer->userLogical;
+ }
+ else
+ {
+ start = buffer->kernelLogical;
+ }
+
+ gcmkASSERT(Logical >= start
+ && (Logical < (gctPOINTER)((gctUINT8_PTR)start + buffer->bytes)));
+
+ * Address = buffer->gpuAddress + (gctUINT32)((gctUINT8_PTR)Logical - (gctUINT8_PTR)start);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckKERNEL_QueryGPUAddress(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GpuAddress,
+ OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
+ )
+{
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
+ gctUINT32 start;
+ gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
+
+ /* Walk all command buffers. */
+ for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
+ {
+ start = (gctUINT32)buffer->virtualBuffer.gpuAddress;
+
+ if (GpuAddress >= start && GpuAddress <= (start - 1 + buffer->virtualBuffer.pageCount * 4096))
+ {
+ /* Find a range matched. */
+ *Buffer = buffer;
+ status = gcvSTATUS_OK;
+ break;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
+
+ return status;
+}
+
+static void
+gckQUEUE_Dequeue(
+ IN gckQUEUE LinkQueue
+ )
+{
+ gcmkASSERT(LinkQueue->count == LinkQueue->size);
+
+ LinkQueue->count--;
+ LinkQueue->front = (LinkQueue->front + 1) % gcdLINK_QUEUE_SIZE;
+}
+
+void
+gckQUEUE_Enqueue(
+ IN gckQUEUE LinkQueue,
+ IN gcuQUEUEDATA *Data
+ )
+{
+ gcuQUEUEDATA * datas = LinkQueue->datas;
+
+ if (LinkQueue->count == LinkQueue->size)
+ {
+ gckQUEUE_Dequeue(LinkQueue);
+ }
+
+ gcmkASSERT(LinkQueue->count < LinkQueue->size);
+
+ LinkQueue->count++;
+
+ datas[LinkQueue->rear] = *Data;
+
+ LinkQueue->rear = (LinkQueue->rear + 1) % LinkQueue->size;
+}
+
+void
+gckQUEUE_GetData(
+ IN gckQUEUE LinkQueue,
+ IN gctUINT32 Index,
+ OUT gcuQUEUEDATA ** Data
+ )
+{
+ gcuQUEUEDATA * datas = LinkQueue->datas;
+
+ gcmkASSERT(Index >= 0 && Index < LinkQueue->size);
+
+ *Data = &datas[(Index + LinkQueue->front) % LinkQueue->size];
+}
+
+gceSTATUS
+gckQUEUE_Allocate(
+ IN gckOS Os,
+ IN gckQUEUE Queue,
+ IN gctUINT32 Size
+ )
+{
+ gceSTATUS status;
+
+ gcmkONERROR(gckOS_Allocate(
+ Os,
+ gcmSIZEOF(struct _gckLINKDATA) * Size,
+ (gctPOINTER *)&Queue->datas
+ ));
+
+ Queue->size = Size;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckQUEUE_Free(
+ IN gckOS Os,
+ IN gckQUEUE Queue
+ )
+{
+ if (Queue->datas)
+ {
+ gcmkVERIFY_OK(gckOS_Free(Os, (gctPOINTER)Queue->datas));
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/******************************************************************************\
+*************************** Pointer - ID translation ***************************
+\******************************************************************************/
+#define gcdID_TABLE_LENGTH 1024
+typedef struct _gcsINTEGERDB * gckINTEGERDB;
+typedef struct _gcsINTEGERDB
+{
+ gckOS os;
+ gctPOINTER* table;
+ gctPOINTER mutex;
+ gctUINT32 tableLen;
+ gctUINT32 currentID;
+ gctUINT32 unused;
+}
+gcsINTEGERDB;
+
+gceSTATUS
+gckKERNEL_CreateIntegerDatabase(
+ IN gckKERNEL Kernel,
+ OUT gctPOINTER * Database
+ )
+{
+ gceSTATUS status;
+ gckINTEGERDB database = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
+
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Database != gcvNULL);
+
+ /* Allocate a database. */
+ gcmkONERROR(gckOS_Allocate(
+ Kernel->os, gcmSIZEOF(gcsINTEGERDB), (gctPOINTER *)&database));
+
+ gcmkONERROR(gckOS_ZeroMemory(database, gcmSIZEOF(gcsINTEGERDB)));
+
+ /* Allocate a pointer table. */
+ gcmkONERROR(gckOS_Allocate(
+ Kernel->os, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH, (gctPOINTER *)&database->table));
+
+ gcmkONERROR(gckOS_ZeroMemory(database->table, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH));
+
+ /* Allocate a database mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->mutex));
+
+ /* Initialize. */
+ database->currentID = 0;
+ database->unused = gcdID_TABLE_LENGTH;
+ database->os = Kernel->os;
+ database->tableLen = gcdID_TABLE_LENGTH;
+
+ *Database = database;
+
+ gcmkFOOTER_ARG("*Database=0x%08X", *Database);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Rollback. */
+ if (database)
+ {
+ if (database->table)
+ {
+ gcmkOS_SAFE_FREE(Kernel->os, database->table);
+ }
+
+ gcmkOS_SAFE_FREE(Kernel->os, database);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_DestroyIntegerDatabase(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Database
+ )
+{
+ gckINTEGERDB database = Database;
+
+ gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
+
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Database != gcvNULL);
+
+ /* Destroy pointer table. */
+ gcmkOS_SAFE_FREE(Kernel->os, database->table);
+
+ /* Destroy database mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, database->mutex));
+
+ /* Destroy database. */
+ gcmkOS_SAFE_FREE(Kernel->os, database);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckKERNEL_AllocateIntegerId(
+ IN gctPOINTER Database,
+ IN gctPOINTER Pointer,
+ OUT gctUINT32 * Id
+ )
+{
+ gceSTATUS status;
+ gckINTEGERDB database = Database;
+ gctUINT32 i, unused, currentID, tableLen;
+ gctPOINTER * table;
+ gckOS os = database->os;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Database=0x%08X Pointer=0x%08X", Database, Pointer);
+
+ gcmkVERIFY_ARGUMENT(Id != gcvNULL);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (database->unused < 1)
+ {
+ /* Extend table. */
+ gcmkONERROR(
+ gckOS_Allocate(os,
+ gcmSIZEOF(gctPOINTER) * (database->tableLen + gcdID_TABLE_LENGTH),
+ (gctPOINTER *)&table));
+
+ gcmkONERROR(gckOS_ZeroMemory(table + database->tableLen,
+ gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH));
+
+ /* Copy data from old table. */
+ gckOS_MemCopy(table,
+ database->table,
+ database->tableLen * gcmSIZEOF(gctPOINTER));
+
+ gcmkOS_SAFE_FREE(os, database->table);
+
+ /* Update databse with new allocated table. */
+ database->table = table;
+ database->currentID = database->tableLen;
+ database->tableLen += gcdID_TABLE_LENGTH;
+ database->unused += gcdID_TABLE_LENGTH;
+ }
+
+ table = database->table;
+ currentID = database->currentID;
+ tableLen = database->tableLen;
+ unused = database->unused;
+
+ /* Connect id with pointer. */
+ table[currentID] = Pointer;
+
+ *Id = currentID + 1;
+
+ /* Update the currentID. */
+ if (--unused > 0)
+ {
+ for (i = 0; i < tableLen; i++)
+ {
+ if (++currentID >= tableLen)
+ {
+ /* Wrap to the begin. */
+ currentID = 0;
+ }
+
+ if (table[currentID] == gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ database->table = table;
+ database->currentID = currentID;
+ database->tableLen = tableLen;
+ database->unused = unused;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_ARG("*Id=%d", *Id);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_FreeIntegerId(
+ IN gctPOINTER Database,
+ IN gctUINT32 Id
+ )
+{
+ gceSTATUS status;
+ gckINTEGERDB database = Database;
+ gckOS os = database->os;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (!(Id > 0 && Id <= database->tableLen))
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ Id -= 1;
+
+ database->table[Id] = gcvNULL;
+
+ if (database->unused++ == 0)
+ {
+ database->currentID = Id;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_QueryIntegerId(
+ IN gctPOINTER Database,
+ IN gctUINT32 Id,
+ OUT gctPOINTER * Pointer
+ )
+{
+ gceSTATUS status;
+ gckINTEGERDB database = Database;
+ gctPOINTER pointer;
+ gckOS os = database->os;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (!(Id > 0 && Id <= database->tableLen))
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ Id -= 1;
+
+ pointer = database->table[Id];
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ acquired = gcvFALSE;
+
+ if (pointer)
+ {
+ *Pointer = pointer;
+ }
+ else
+ {
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ gcmkFOOTER_ARG("*Pointer=0x%08X", *Pointer);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+
+gctUINT32
+gckKERNEL_AllocateNameFromPointer(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Pointer
+ )
+{
+ gceSTATUS status;
+ gctUINT32 name;
+ gctPOINTER database = Kernel->db->pointerDatabase;
+
+ gcmkHEADER_ARG("Kernel=0x%X Pointer=0x%X", Kernel, Pointer);
+
+ gcmkONERROR(
+ gckKERNEL_AllocateIntegerId(database, Pointer, &name));
+
+ gcmkFOOTER_ARG("name=%d", name);
+ return name;
+
+OnError:
+ gcmkFOOTER();
+ return 0;
+}
+
+gctPOINTER
+gckKERNEL_QueryPointerFromName(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name
+ )
+{
+ gceSTATUS status;
+ gctPOINTER pointer = gcvNULL;
+ gctPOINTER database = Kernel->db->pointerDatabase;
+
+ gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
+
+ /* Lookup in database to get pointer. */
+ gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, &pointer));
+
+ gcmkFOOTER_ARG("pointer=0x%X", pointer);
+ return pointer;
+
+OnError:
+ gcmkFOOTER();
+ return gcvNULL;
+}
+
+gceSTATUS
+gckKERNEL_DeleteName(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name
+ )
+{
+ gctPOINTER database = Kernel->db->pointerDatabase;
+
+ gcmkHEADER_ARG("Kernel=0x%X Name=0x%X", Kernel, Name);
+
+ /* Free name if exists. */
+ gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(database, Name));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+***** Shared Buffer ************************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_CreateShBuffer
+**
+** Create shared buffer.
+** The shared buffer can be used across processes. Other process needs call
+** gckKERNEL_MapShBuffer before use it.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 Size
+** Specify the shared buffer size.
+**
+** OUTPUT:
+**
+** gctSHBUF * ShBuf
+** Pointer to hold return shared buffer handle.
+*/
+gceSTATUS
+gckKERNEL_CreateShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Size,
+ OUT gctSHBUF * ShBuf
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%X, Size=%u", Kernel, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (Size == 0)
+ {
+ /* Invalid size. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+ else if (Size > 1024)
+ {
+ /* Limite shared buffer size. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Create a shared buffer structure. */
+ gcmkONERROR(
+ gckOS_Allocate(Kernel->os,
+ sizeof (gcsSHBUF),
+ (gctPOINTER *)&shBuf));
+
+ /* Initialize shared buffer. */
+ shBuf->id = 0;
+ shBuf->reference = gcvNULL;
+ shBuf->size = Size;
+ shBuf->data = gcvNULL;
+
+ /* Allocate integer id for this shared buffer. */
+ gcmkONERROR(
+ gckKERNEL_AllocateIntegerId(Kernel->db->pointerDatabase,
+ shBuf,
+ &shBuf->id));
+
+ /* Allocate atom. */
+ gcmkONERROR(gckOS_AtomConstruct(Kernel->os, &shBuf->reference));
+
+ /* Set default reference count to 1. */
+ gcmkVERIFY_OK(gckOS_AtomSet(Kernel->os, shBuf->reference, 1));
+
+ /* Return integer id. */
+ *ShBuf = (gctSHBUF)(gctUINTPTR_T)shBuf->id;
+
+ gcmkFOOTER_ARG("*ShBuf=%u", shBuf->id);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Error roll back. */
+ if (shBuf != gcvNULL)
+ {
+ if (shBuf->id != 0)
+ {
+ gcmkVERIFY_OK(
+ gckKERNEL_FreeIntegerId(Kernel->db->pointerDatabase,
+ shBuf->id));
+ }
+
+ gcmkOS_SAFE_FREE(Kernel->os, shBuf);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_DestroyShBuffer
+**
+** Destroy shared buffer.
+** This will decrease reference of specified shared buffer and do actual
+** destroy when no reference on it.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSHBUF ShBuf
+** Specify the shared buffer to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_DestroyShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf;
+ gctINT32 oldValue = 0;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u",
+ Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
+
+ /* Acquire mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os,
+ Kernel->db->pointerDatabaseMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Find shared buffer structure. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+ (gctUINT32)(gctUINTPTR_T)ShBuf,
+ (gctPOINTER)&shBuf));
+
+ gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
+
+ /* Decrease the reference count. */
+ gckOS_AtomDecrement(Kernel->os, shBuf->reference, &oldValue);
+
+ if (oldValue == 1)
+ {
+ /* Free integer id. */
+ gcmkVERIFY_OK(
+ gckKERNEL_FreeIntegerId(Kernel->db->pointerDatabase,
+ shBuf->id));
+
+ /* Free atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, shBuf->reference));
+
+ if (shBuf->data)
+ {
+ gcmkOS_SAFE_FREE(Kernel->os, shBuf->data);
+ shBuf->data = gcvNULL;
+ }
+
+ /* Free the shared buffer. */
+ gcmkOS_SAFE_FREE(Kernel->os, shBuf);
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapShBuffer
+**
+** Map shared buffer into this process so that it can be used in this process.
+** This will increase reference count on the specified shared buffer.
+** Call gckKERNEL_DestroyShBuffer to dereference.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSHBUF ShBuf
+** Specify the shared buffer to be mapped.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_MapShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf;
+ gctINT32 oldValue = 0;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u",
+ Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
+
+ /* Acquire mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os,
+ Kernel->db->pointerDatabaseMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Find shared buffer structure. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+ (gctUINT32)(gctUINTPTR_T)ShBuf,
+ (gctPOINTER)&shBuf));
+
+ gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
+
+ /* Increase the reference count. */
+ gckOS_AtomIncrement(Kernel->os, shBuf->reference, &oldValue);
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_WriteShBuffer
+**
+** Write user data into shared buffer.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSHBUF ShBuf
+** Specify the shared buffer to be written to.
+**
+** gctPOINTER UserData
+** User mode pointer to hold the source data.
+**
+** gctUINT32 ByteCount
+** Specify number of bytes to write. If this is larger than
+** shared buffer size, gcvSTATUS_INVALID_ARGUMENT is returned.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_WriteShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf,
+ IN gctPOINTER UserData,
+ IN gctUINT32 ByteCount
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u UserData=0x%X ByteCount=%u",
+ Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf, UserData, ByteCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
+
+ /* Acquire mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os,
+ Kernel->db->pointerDatabaseMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Find shared buffer structure. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+ (gctUINT32)(gctUINTPTR_T)ShBuf,
+ (gctPOINTER)&shBuf));
+
+ gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
+
+ if ((ByteCount > shBuf->size) ||
+ (ByteCount == 0) ||
+ (UserData == gcvNULL))
+ {
+ /* Exceeds buffer max size or invalid. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (shBuf->data == gcvNULL)
+ {
+ /* Allocate buffer data when first time write. */
+ gcmkONERROR(gckOS_Allocate(Kernel->os, ByteCount, &shBuf->data));
+ }
+
+ /* Copy data from user. */
+ gcmkONERROR(
+ gckOS_CopyFromUserData(Kernel->os,
+ shBuf->data,
+ UserData,
+ ByteCount));
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (shBuf && shBuf->data)
+ {
+ gcmkOS_SAFE_FREE(Kernel->os, shBuf->data);
+ shBuf->data = gcvNULL;
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_ReadShBuffer
+**
+** Read data from shared buffer and copy to user pointer.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSHBUF ShBuf
+** Specify the shared buffer to be read from.
+**
+** gctPOINTER UserData
+** User mode pointer to save output data.
+**
+** gctUINT32 ByteCount
+** Specify number of bytes to read.
+** If this is larger than shared buffer size, only avaiable bytes are
+** copied. If smaller, copy requested size.
+**
+** OUTPUT:
+**
+** gctUINT32 * BytesRead
+** Pointer to hold how many bytes actually read from shared buffer.
+*/
+gceSTATUS
+gckKERNEL_ReadShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf,
+ IN gctPOINTER UserData,
+ IN gctUINT32 ByteCount,
+ OUT gctUINT32 * BytesRead
+ )
+{
+ gceSTATUS status;
+ gcsSHBUF_PTR shBuf;
+ gctUINT32 bytes;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u UserData=0x%X ByteCount=%u",
+ Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf, UserData, ByteCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
+
+ /* Acquire mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os,
+ Kernel->db->pointerDatabaseMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Find shared buffer structure. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
+ (gctUINT32)(gctUINTPTR_T)ShBuf,
+ (gctPOINTER)&shBuf));
+
+ gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
+
+ if (shBuf->data == gcvNULL)
+ {
+ *BytesRead = 0;
+
+ /* No data in shared buffer, skip copy. */
+ status = gcvSTATUS_SKIP;
+ goto OnError;
+ }
+ else if (ByteCount == 0)
+ {
+ /* Invalid size to read. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Determine bytes to copy. */
+ bytes = (ByteCount < shBuf->size) ? ByteCount : shBuf->size;
+
+ /* Copy data to user. */
+ gcmkONERROR(
+ gckOS_CopyToUserData(Kernel->os,
+ shBuf->data,
+ UserData,
+ bytes));
+
+ /* Return copied size. */
+ *BytesRead = bytes;
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_ARG("*BytesRead=%u", bytes);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************\
+*************************** List Helper *****************************************
+\*******************************************************************************/
+
+static void
+_ListAdd(
+ gcsLISTHEAD_PTR New,
+ gcsLISTHEAD_PTR Prev,
+ gcsLISTHEAD_PTR Next
+ )
+{
+ Next->prev = New;
+ New->next = Next;
+ New->prev = Prev;
+ Prev->next = New;
+}
+
+void
+_ListDel(
+ gcsLISTHEAD_PTR Prev,
+ gcsLISTHEAD_PTR Next
+ )
+{
+ Next->prev = Prev;
+ Prev->next = Next;
+}
+
+void
+gcsLIST_Init(
+ gcsLISTHEAD_PTR Node
+ )
+{
+ Node->prev = Node;
+ Node->next = Node;
+}
+
+void
+gcsLIST_Add(
+ gcsLISTHEAD_PTR New,
+ gcsLISTHEAD_PTR Head
+ )
+{
+ _ListAdd(New, Head, Head->next);
+}
+
+void
+gcsLIST_AddTail(
+ gcsLISTHEAD_PTR New,
+ gcsLISTHEAD_PTR Head
+ )
+{
+ _ListAdd(New, Head->prev, Head);
+}
+
+void
+gcsLIST_Del(
+ gcsLISTHEAD_PTR Node
+ )
+{
+ _ListDel(Node->prev, Node->next);
+}
+
+gctBOOL
+gcsLIST_Empty(
+ gcsLISTHEAD_PTR Head
+ )
+{
+ return Head->next == Head;
+}
+
+/*******************************************************************************\
+********************************* Fence *****************************************
+\*******************************************************************************/
+
+gceSTATUS
+gckFENCE_Create(
+ IN gckOS Os,
+ IN gckKERNEL Kernel,
+ OUT gckFENCE * Fence
+ )
+{
+ gceSTATUS status;
+ gckFENCE fence = gcvNULL;
+ gctSIZE_T pageSize = 4096;
+
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsFENCE), (gctPOINTER *)&fence));
+ gcmkONERROR(gckOS_ZeroMemory(fence, gcmSIZEOF(gcsFENCE)));
+ gcmkONERROR(gckOS_CreateMutex(Os, (gctPOINTER *)&fence->mutex));
+
+ fence->kernel = Kernel;
+
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (Kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_AllocateVirtualMemory(
+ Kernel,
+ gcvFALSE,
+ gcvFALSE,
+ &pageSize,
+ &fence->physical,
+ &fence->logical
+ ));
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Kernel,
+ fence->logical,
+ gcvFALSE,
+ fence->physical,
+ &fence->address
+ ));
+ }
+ else
+#endif
+ {
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ Os,
+ gcvFALSE,
+ &pageSize,
+ &fence->physical,
+ &fence->logical
+ ));
+
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ Kernel->hardware,
+ fence->logical,
+ gcvFALSE,
+ &fence->address
+ ));
+
+ gcmkONERROR(gckMMU_FillFlatMapping(
+ Kernel->mmu, fence->address, pageSize
+ ));
+ }
+
+ gcsLIST_Init(&fence->waitingList);
+
+ *Fence = fence;
+
+ return gcvSTATUS_OK;
+OnError:
+ if (fence)
+ {
+ gckFENCE_Destory(Os, fence);
+ }
+
+ return status;
+}
+
+gceSTATUS
+gckFENCE_Destory(
+ IN gckOS Os,
+ OUT gckFENCE Fence
+ )
+{
+ if (Fence->mutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Fence->mutex));
+ }
+
+ if (Fence->logical)
+ {
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (Fence->kernel->virtualCommandBuffer)
+ {
+ gcmkVERIFY_OK(gckKERNEL_FreeVirtualMemory(
+ Fence->physical,
+ Fence->logical,
+ gcvFALSE
+ ));
+ }
+ else
+#endif
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ Os,
+ 4096,
+ Fence->physical,
+ Fence->logical
+ ));
+ }
+ }
+
+ gcmkOS_SAFE_FREE(Os, Fence);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckFENCE_Signal
+**
+** Signal all completed nodes.
+**
+**
+*/
+gceSTATUS
+gckFENCE_Signal(
+ IN gckOS Os,
+ IN gckFENCE Fence
+ )
+{
+ gcsLISTHEAD_PTR list = &Fence->waitingList;
+ gcsLISTHEAD_PTR nodeHead, nodeTemp;
+ gckFENCE_SYNC sync;
+ gckOS os = Os;
+ gctUINT64 stamp = *(gctUINT64 *)Fence->logical;
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(os, Fence->mutex, gcvINFINITE));
+
+ gcmkLIST_FOR_EACH_SAFE(nodeHead, nodeTemp, list)
+ {
+ sync = gcmCONTAINEROF(nodeHead, _gcsFENCE_SYNC, head);
+
+ /* Signal all nodes which are complete. */
+ if (sync->commitStamp <= stamp && sync->inList)
+ {
+ /* Signal. */
+ gckOS_Signal(os, sync->signal, gcvTRUE);
+
+ /* Remove from wait list. */
+ gcsLIST_Del(nodeHead);
+
+ /* Mark node not in waiting list. */
+ sync->inList = gcvFALSE;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Fence->mutex));
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDEVICE_Construct(
+ IN gckOS Os,
+ OUT gckDEVICE * Device
+ )
+{
+ gceSTATUS status;
+ gckDEVICE device;
+ gctUINT i;
+
+ gcmkHEADER();
+
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsDEVICE), (gctPOINTER *)&device));
+
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ device->coreInfoArray[i].type = gcvHARDWARE_INVALID;
+ }
+
+ gckOS_ZeroMemory(device, gcmSIZEOF(gcsDEVICE));
+
+ gcmkONERROR(gckOS_CreateMutex(Os, &device->stuckDumpMutex));
+ gcmkONERROR(gckOS_CreateMutex(Os, &device->commitMutex));
+
+ device->os = Os;
+
+ *Device = device;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ if (device != gcvNULL)
+ {
+ gckDEVICE_Destroy(Os, device);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckDEVICE_AddCore(
+ IN gckDEVICE Device,
+ IN gceCORE Core,
+ IN gctUINT ChipID,
+ IN gctPOINTER Context,
+ IN gckKERNEL * Kernel
+ )
+{
+ gceSTATUS status;
+ gcsCORE_INFO * info = Device->coreInfoArray;
+ gceHARDWARE_TYPE type = (gceHARDWARE_TYPE)((gctUINT)gcvHARDWARE_INVALID);
+ gctUINT32 index = Device->coreNum;
+ gctUINT32 i;
+ gcsCORE_LIST *coreList;
+ gceHARDWARE_TYPE kernelType;
+ gckKERNEL kernel;
+
+ gcmkASSERT(Device->coreNum < gcvCORE_COUNT);
+
+ if (Core >= gcvCORE_MAJOR && Core <= gcvCORE_3D_MAX)
+ {
+ /* Chip ID is only used for 3D cores. */
+ if (ChipID == gcvCHIP_ID_DEFAULT)
+ {
+ /* Apply default chipID if it is not set. */
+ ChipID = Core;
+ }
+ }
+
+ /* Construct gckKERNEL for this core. */
+ gcmkONERROR(gckKERNEL_Construct(
+ Device->os, Core, ChipID, Context, Device, Device->database, Kernel));
+
+ kernel = *Kernel;
+
+ if (Device->database == gcvNULL)
+ {
+ Device->database = kernel->db;
+ }
+
+ kernelType = _GetHardwareType(kernel);
+
+ if (kernelType >= gcvHARDWARE_NUM_TYPES)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ info[index].type = kernelType;
+ info[index].core = Core;
+ info[index].kernel = kernel;
+ info[index].chipID = ChipID;
+
+ if (index == 0)
+ {
+ /* First core, map all type/core to it. */
+ for (; type != gcvHARDWARE_NUM_TYPES; type = (gceHARDWARE_TYPE)((gctUINT)type + 1))
+ {
+ Device->map[type].num = 0;
+
+ for (i = 0 ; i < 4; i++)
+ {
+ Device->map[type].kernels[i] = kernel;
+ }
+ }
+ }
+
+ /* Get core list of this type. */
+ coreList = &Device->map[kernelType];
+
+ /* Setup gceHARDWARE_TYPE to gceCORE mapping. */
+ coreList->kernels[coreList->num++] = kernel;
+
+ if (kernelType == gcvHARDWARE_3D2D)
+ {
+ coreList = &Device->map[gcvHARDWARE_3D];
+ coreList->kernels[coreList->num++] = kernel;
+ }
+
+ /* Advance total core number. */
+ Device->coreNum++;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckDEVICE_ChipInfo(
+ IN gckDEVICE Device,
+ IN gcsHAL_INTERFACE_PTR Interface
+ )
+{
+ gctUINT i;
+ gcsCORE_INFO * info = Device->coreInfoArray;
+
+ for (i = 0; i < Device->coreNum; i++)
+ {
+ Interface->u.ChipInfo.types[i] = info[i].type;
+ Interface->u.ChipInfo.ids[i] = info[i].chipID;
+ }
+
+ Interface->u.ChipInfo.count = Device->coreNum;
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDEVICE_Version(
+ IN gckDEVICE Device,
+ IN gcsHAL_INTERFACE_PTR Interface
+ )
+{
+ Interface->u.Version.major = gcvVERSION_MAJOR;
+ Interface->u.Version.minor = gcvVERSION_MINOR;
+ Interface->u.Version.patch = gcvVERSION_PATCH;
+ Interface->u.Version.build = gcvVERSION_BUILD;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "KERNEL version %d.%d.%d build %u",
+ gcvVERSION_MAJOR, gcvVERSION_MINOR,
+ gcvVERSION_PATCH, gcvVERSION_BUILD);
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDEVICE_Destroy(
+ IN gckOS Os,
+ IN gckDEVICE Device
+ )
+{
+ gctINT i;
+ gcsCORE_INFO * info = Device->coreInfoArray;
+
+ for (i = Device->coreNum - 1; i >= 0 ; i--)
+ {
+ if (info[i].kernel != gcvNULL)
+ {
+ gckKERNEL_Destroy(info[i].kernel);
+ }
+ }
+
+ if (Device->commitMutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Device->commitMutex));
+ }
+ if (Device->stuckDumpMutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Device->stuckDumpMutex));
+ }
+
+ gcmkOS_SAFE_FREE(Os, Device);
+
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+gckDEVICE_SetTimeOut(
+ IN gckDEVICE Device,
+ IN gcsHAL_INTERFACE_PTR Interface
+ )
+{
+#if gcdGPU_TIMEOUT
+ gckKERNEL kernel;
+ gctUINT i;
+ gceHARDWARE_TYPE type = Interface->hardwareType;
+ gcsCORE_LIST *coreList;
+
+ coreList = &Device->map[type];
+
+ for (i = 0; i < coreList->num; i++)
+ {
+ kernel = coreList->kernels[i];
+
+ kernel->timeOut = Interface->u.SetTimeOut.timeOut;
+ }
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+
+gceSTATUS
+gckDEVICE_Dispatch(
+ IN gckDEVICE Device,
+ IN gcsHAL_INTERFACE_PTR Interface
+ )
+{
+ gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+ gckKERNEL kernel;
+ gceHARDWARE_TYPE type = Interface->hardwareType;
+ gctUINT32 coreIndex = Interface->coreIndex;
+
+ switch (Interface->command)
+ {
+ case gcvHAL_CHIP_INFO:
+ status = gckDEVICE_ChipInfo(Device, Interface);
+ break;
+
+ case gcvHAL_VERSION:
+ status = gckDEVICE_Version(Device, Interface);
+ break;
+
+ case gcvHAL_SET_TIMEOUT:
+ status = gckDEVICE_SetTimeOut(Device, Interface);
+ break;
+
+ default:
+ status = gcvSTATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Dispatch handled in this layer. */
+ Interface->status = status;
+ }
+ else
+ {
+ /* Need go through gckKERNEL dispatch. */
+ kernel = Device->map[type].kernels[coreIndex];
+
+
+#if gcdENABLE_VG
+ if (kernel->vg)
+ {
+ status = gckVGKERNEL_Dispatch(kernel, gcvTRUE, Interface);
+ }
+ else
+#endif
+ {
+ status = gckKERNEL_Dispatch(kernel, Device, gcvTRUE, Interface);
+ }
+
+ /* Interface->status is handled in gckKERNEL_Dispatch(). */
+ }
+
+ return status;
+}
+
+gceSTATUS
+gckDEVICE_GetMMU(
+ IN gckDEVICE Device,
+ IN gceHARDWARE_TYPE Type,
+ IN gckMMU *Mmu
+ )
+{
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(Type < gcvHARDWARE_NUM_TYPES);
+
+ *Mmu = Device->mmus[Type];
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDEVICE_SetMMU(
+ IN gckDEVICE Device,
+ IN gceHARDWARE_TYPE Type,
+ IN gckMMU Mmu
+ )
+{
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(Type < gcvHARDWARE_NUM_TYPES);
+
+ Device->mmus[Type] = Mmu;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckDEVICE_QueryGPUAddress
+**
+** Search GPUAddress in other core's address space, whose type is same as current
+** core. It is used to find correct command buffer which is shared by mulitple
+** core.
+**
+*/
+gceSTATUS
+gckDEVICE_QueryGPUAddress(
+ IN gckDEVICE Device,
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPUAddress,
+ OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
+ )
+{
+ gceSTATUS status = gcvSTATUS_NOT_FOUND;
+ gctUINT i;
+ gceHARDWARE_TYPE kernelType;
+
+ kernelType = _GetHardwareType(Kernel);
+
+ if (Device != gcvNULL)
+ {
+ for (i = 0; i < Device->coreNum; i++)
+ {
+ if (Device->coreInfoArray[i].type == kernelType)
+ {
+ /* Search other core's command buffer list whose type is same. */
+ status = gckKERNEL_QueryGPUAddress(
+ Device->coreInfoArray[i].kernel, GPUAddress, Buffer);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ status = gckKERNEL_QueryGPUAddress(Kernel, GPUAddress, Buffer);
+ }
+
+ return status;
+}
+
+#if gcdENABLE_TRUST_APPLICATION
+gceSTATUS
+gckKERNEL_MapInTrustApplicaiton(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctPHYS_ADDR Physical,
+ IN gctUINT32 GPUAddress,
+ IN gctSIZE_T PageCount
+ )
+{
+ gceSTATUS status;
+ gctUINT32 * physicalArrayLogical = gcvNULL;
+ gctSIZE_T bytes;
+ gctPOINTER logical = Logical;
+ gctUINT32 i;
+ gctSIZE_T pageSize;
+ gctUINT32 pageMask;
+
+ gcmkHEADER();
+
+ gcmkVERIFY_OK(gckOS_GetPageSize(Kernel->os, &pageSize));
+
+ pageMask = (gctUINT32)pageSize - 1;
+
+ bytes = PageCount * gcmSIZEOF(gctUINT32);
+
+ gcmkONERROR(gckOS_Allocate(
+ Kernel->os,
+ bytes,
+ (gctPOINTER *)&physicalArrayLogical
+ ));
+
+ /* Fill in physical array. */
+ for (i = 0; i < PageCount; i++)
+ {
+ gctPHYS_ADDR_T phys;
+ status = gckOS_PhysicalToPhysicalAddress(
+ Kernel->os,
+ Physical,
+ i * 4096,
+ &phys
+ );
+
+ if (status == gcvSTATUS_NOT_SUPPORTED)
+ {
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ Kernel->os,
+ logical,
+ &phys
+ ));
+ }
+
+ phys &= ~pageMask;
+
+ gcmkSAFECASTPHYSADDRT(physicalArrayLogical[i], phys);
+
+ logical = (gctUINT8_PTR)logical + 4096;
+ }
+
+ gcmkONERROR(gckKERNEL_SecurityMapMemory(
+ Kernel,
+ physicalArrayLogical,
+ 0,
+ (gctUINT32)PageCount,
+ &GPUAddress
+ ));
+
+ gcmkVERIFY_OK(gckOS_Free(
+ Kernel->os,
+ physicalArrayLogical
+ ))
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if(physicalArrayLogical != gcvNULL)
+ gcmkVERIFY_OK(gckOS_Free(
+ Kernel->os,
+ (gctPOINTER)physicalArrayLogical
+ ));
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+***** Test Code ****************************************************************
+*******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
new file mode 100644
index 000000000000..d71da8a53b5e
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
@@ -0,0 +1,2014 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_h_
+#define __gc_hal_kernel_h_
+
+#include "gc_hal.h"
+#include "gc_hal_kernel_hardware.h"
+#include "gc_hal_driver.h"
+
+#include "gc_hal_kernel_mutex.h"
+
+#if gcdENABLE_VG
+#include "gc_hal_kernel_vg.h"
+#endif
+
+#if gcdSECURITY || gcdENABLE_TRUST_APPLICATION
+#include "gc_hal_security_interface.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+***** New MMU Defination *******************************************************/
+#define gcdMMU_MTLB_SHIFT 22
+#define gcdMMU_STLB_4K_SHIFT 12
+#define gcdMMU_STLB_64K_SHIFT 16
+
+#define gcdMMU_MTLB_BITS (32 - gcdMMU_MTLB_SHIFT)
+#define gcdMMU_PAGE_4K_BITS gcdMMU_STLB_4K_SHIFT
+#define gcdMMU_STLB_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_4K_BITS)
+#define gcdMMU_PAGE_64K_BITS gcdMMU_STLB_64K_SHIFT
+#define gcdMMU_STLB_64K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_64K_BITS)
+
+#define gcdMMU_MTLB_ENTRY_NUM (1 << gcdMMU_MTLB_BITS)
+#define gcdMMU_MTLB_SIZE (gcdMMU_MTLB_ENTRY_NUM << 2)
+#define gcdMMU_STLB_4K_ENTRY_NUM (1 << gcdMMU_STLB_4K_BITS)
+#define gcdMMU_STLB_4K_SIZE (gcdMMU_STLB_4K_ENTRY_NUM << 2)
+#define gcdMMU_PAGE_4K_SIZE (1 << gcdMMU_STLB_4K_SHIFT)
+#define gcdMMU_STLB_64K_ENTRY_NUM (1 << gcdMMU_STLB_64K_BITS)
+#define gcdMMU_STLB_64K_SIZE (gcdMMU_STLB_64K_ENTRY_NUM << 2)
+#define gcdMMU_PAGE_64K_SIZE (1 << gcdMMU_STLB_64K_SHIFT)
+
+#define gcdMMU_MTLB_MASK (~((1U << gcdMMU_MTLB_SHIFT)-1))
+#define gcdMMU_STLB_4K_MASK ((~0U << gcdMMU_STLB_4K_SHIFT) ^ gcdMMU_MTLB_MASK)
+#define gcdMMU_PAGE_4K_MASK (gcdMMU_PAGE_4K_SIZE - 1)
+#define gcdMMU_STLB_64K_MASK ((~((1U << gcdMMU_STLB_64K_SHIFT)-1)) ^ gcdMMU_MTLB_MASK)
+#define gcdMMU_PAGE_64K_MASK (gcdMMU_PAGE_64K_SIZE - 1)
+
+/* Page offset definitions. */
+#define gcdMMU_OFFSET_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_4K_BITS)
+#define gcdMMU_OFFSET_4K_MASK ((1U << gcdMMU_OFFSET_4K_BITS) - 1)
+#define gcdMMU_OFFSET_16K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_16K_BITS)
+#define gcdMMU_OFFSET_16K_MASK ((1U << gcdMMU_OFFSET_16K_BITS) - 1)
+
+#define gcdMMU_MTLB_ENTRY_HINTS_BITS 6
+#define gcdMMU_MTLB_ENTRY_STLB_MASK (~((1U << gcdMMU_MTLB_ENTRY_HINTS_BITS) - 1))
+
+#define gcdMMU_MTLB_PRESENT 0x00000001
+#define gcdMMU_MTLB_EXCEPTION 0x00000002
+#define gcdMMU_MTLB_4K_PAGE 0x00000000
+
+#define gcdMMU_STLB_PRESENT 0x00000001
+#define gcdMMU_STLB_EXCEPTION 0x00000002
+#define gcdMMU_STLB_4K_PAGE 0x00000000
+
+/*******************************************************************************
+***** Stuck Dump Level ********************************************************/
+
+/* Dump nonthing when stuck happens. */
+#define gcvSTUCK_DUMP_NONE 0
+
+/* Dump GPU state and memory near stuck point. */
+#define gcvSTUCK_DUMP_NEARBY_MEMORY 1
+
+/* Beside gcvSTUCK_DUMP_NEARBY_MEMORY, dump context buffer and user command buffer. */
+#define gcvSTUCK_DUMP_USER_COMMAND 2
+
+/* Beside gcvSTUCK_DUMP_USER_COMMAND, commit will be stall
+** to make sure command causing stuck isn't missed. */
+#define gcvSTUCK_DUMP_STALL_COMMAND 3
+
+/* Beside gcvSTUCK_DUMP_USER_COMMAND, dump kernel command buffer. */
+#define gcvSTUCK_DUMP_ALL_COMMAND 4
+
+/*******************************************************************************
+***** Process Secure Cache ****************************************************/
+
+#define gcdSECURE_CACHE_LRU 1
+#define gcdSECURE_CACHE_LINEAR 2
+#define gcdSECURE_CACHE_HASH 3
+#define gcdSECURE_CACHE_TABLE 4
+
+#define gcvPAGE_TABLE_DIRTY_BIT_OTHER (1 << 0)
+#define gcvPAGE_TABLE_DIRTY_BIT_FE (1 << 1)
+
+typedef struct _gcskLOGICAL_CACHE * gcskLOGICAL_CACHE_PTR;
+typedef struct _gcskLOGICAL_CACHE gcskLOGICAL_CACHE;
+struct _gcskLOGICAL_CACHE
+{
+ /* Logical address. */
+ gctPOINTER logical;
+
+ /* DMAable address. */
+ gctUINT32 dma;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ /* Pointer to the previous and next hash tables. */
+ gcskLOGICAL_CACHE_PTR nextHash;
+ gcskLOGICAL_CACHE_PTR prevHash;
+#endif
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+ /* Pointer to the previous and next slot. */
+ gcskLOGICAL_CACHE_PTR next;
+ gcskLOGICAL_CACHE_PTR prev;
+#endif
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
+ /* Time stamp. */
+ gctUINT64 stamp;
+#endif
+};
+
+typedef struct _gcskSECURE_CACHE * gcskSECURE_CACHE_PTR;
+typedef struct _gcskSECURE_CACHE
+{
+ /* Cache memory. */
+ gcskLOGICAL_CACHE cache[1 + gcdSECURE_CACHE_SLOTS];
+
+ /* Last known index for LINEAR mode. */
+ gcskLOGICAL_CACHE_PTR cacheIndex;
+
+ /* Current free slot for LINEAR mode. */
+ gctUINT32 cacheFree;
+
+ /* Time stamp for LINEAR mode. */
+ gctUINT64 cacheStamp;
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ /* Hash table for HASH mode. */
+ gcskLOGICAL_CACHE hash[256];
+#endif
+}
+gcskSECURE_CACHE;
+
+/*******************************************************************************
+***** Process Database Management *********************************************/
+
+typedef enum _gceDATABASE_TYPE
+{
+ gcvDB_VIDEO_MEMORY = 1, /* Video memory created. */
+ gcvDB_COMMAND_BUFFER, /* Command Buffer. */
+ gcvDB_NON_PAGED, /* Non paged memory. */
+ gcvDB_CONTIGUOUS, /* Contiguous memory. */
+ gcvDB_SIGNAL, /* Signal. */
+ gcvDB_VIDEO_MEMORY_LOCKED, /* Video memory locked. */
+ gcvDB_CONTEXT, /* Context */
+ gcvDB_IDLE, /* GPU idle. */
+ gcvDB_MAP_MEMORY, /* Map memory */
+ gcvDB_MAP_USER_MEMORY, /* Map user memory */
+ gcvDB_SHBUF, /* Shared buffer. */
+
+ gcvDB_NUM_TYPES,
+}
+gceDATABASE_TYPE;
+
+#define gcdDATABASE_TYPE_MASK 0x000000FF
+#define gcdDB_VIDEO_MEMORY_TYPE_MASK 0x0000FF00
+#define gcdDB_VIDEO_MEMORY_TYPE_SHIFT 8
+
+#define gcdDB_VIDEO_MEMORY_POOL_MASK 0x00FF0000
+#define gcdDB_VIDEO_MEMORY_POOL_SHIFT 16
+
+typedef struct _gcsDATABASE_RECORD * gcsDATABASE_RECORD_PTR;
+typedef struct _gcsDATABASE_RECORD
+{
+ /* Pointer to kernel. */
+ gckKERNEL kernel;
+
+ /* Pointer to next database record. */
+ gcsDATABASE_RECORD_PTR next;
+
+ /* Type of record. */
+ gceDATABASE_TYPE type;
+
+ /* Data for record. */
+ gctPOINTER data;
+ gctPHYS_ADDR physical;
+ gctSIZE_T bytes;
+}
+gcsDATABASE_RECORD;
+
+typedef struct _gcsDATABASE * gcsDATABASE_PTR;
+typedef struct _gcsDATABASE
+{
+ /* Pointer to next entry is hash list. */
+ gcsDATABASE_PTR next;
+ gctSIZE_T slot;
+
+ /* Process ID. */
+ gctUINT32 processID;
+
+ /* Sizes to query. */
+ gcsDATABASE_COUNTERS vidMem;
+ gcsDATABASE_COUNTERS nonPaged;
+ gcsDATABASE_COUNTERS contiguous;
+ gcsDATABASE_COUNTERS mapUserMemory;
+ gcsDATABASE_COUNTERS mapMemory;
+
+ gcsDATABASE_COUNTERS vidMemType[gcvSURF_NUM_TYPES];
+ /* Counter for each video memory pool. */
+ gcsDATABASE_COUNTERS vidMemPool[gcvPOOL_NUMBER_OF_POOLS];
+ gctPOINTER counterMutex;
+
+ /* Idle time management. */
+ gctUINT64 lastIdle;
+ gctUINT64 idle;
+
+ /* Pointer to database. */
+ gcsDATABASE_RECORD_PTR list[48];
+
+#if gcdSECURE_USER
+ /* Secure cache. */
+ gcskSECURE_CACHE cache;
+#endif
+
+ gctPOINTER handleDatabase;
+ gctPOINTER handleDatabaseMutex;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gckMMU mmu;
+#endif
+}
+gcsDATABASE;
+
+typedef struct _gcsFDPRIVATE * gcsFDPRIVATE_PTR;
+typedef struct _gcsFDPRIVATE
+{
+ gctINT (* release) (gcsFDPRIVATE_PTR Private);
+}
+gcsFDPRIVATE;
+
+typedef struct _gcsRECORDER * gckRECORDER;
+
+
+/* Create a process database that will contain all its allocations. */
+gceSTATUS
+gckKERNEL_CreateProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID
+ );
+
+/* Add a record to the process database. */
+gceSTATUS
+gckKERNEL_AddProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Size
+ );
+
+/* Remove a record to the process database. */
+gceSTATUS
+gckKERNEL_RemoveProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer
+ );
+
+/* Destroy the process database. */
+gceSTATUS
+gckKERNEL_DestroyProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID
+ );
+
+/* Find a record to the process database. */
+gceSTATUS
+gckKERNEL_FindProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 ThreadID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer,
+ OUT gcsDATABASE_RECORD_PTR Record
+ );
+
+/* Query the process database. */
+gceSTATUS
+gckKERNEL_QueryProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL LastProcessID,
+ IN gceDATABASE_TYPE Type,
+ OUT gcuDATABASE_INFO * Info
+ );
+
+/* Dump the process database. */
+gceSTATUS
+gckKERNEL_DumpProcessDB(
+ IN gckKERNEL Kernel
+ );
+
+/* Dump the video memory usage for process specified. */
+gceSTATUS
+gckKERNEL_DumpVidMemUsage(
+ IN gckKERNEL Kernel,
+ IN gctINT32 ProcessID
+ );
+
+gceSTATUS
+gckKERNEL_FindDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL LastProcessID,
+ OUT gcsDATABASE_PTR * Database
+ );
+
+gceSTATUS
+gckKERNEL_FindHandleDatbase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gctPOINTER * HandleDatabase,
+ OUT gctPOINTER * HandleDatabaseMutex
+ );
+
+gceSTATUS
+gckKERNEL_GetProcessMMU(
+ IN gckKERNEL Kernel,
+ OUT gckMMU * Mmu
+ );
+
+gceSTATUS
+gckMMU_FlatMapping(
+ IN gckMMU Mmu,
+ IN gctUINT32 Physical,
+ IN gctUINT32 NumPages
+ );
+
+gceSTATUS
+gckMMU_GetPageEntry(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address,
+ IN gctUINT32_PTR *PageTable
+ );
+
+gceSTATUS
+gckMMU_FreePagesEx(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address,
+ IN gctSIZE_T PageCount
+ );
+
+gceSTATUS
+gckMMU_AttachHardware(
+ IN gckMMU Mmu,
+ IN gckHARDWARE Hardware
+ );
+
+void
+gckMMU_DumpRecentFreedAddress(
+ IN gckMMU Mmu
+ );
+
+gceSTATUS
+gckKERNEL_CreateIntegerDatabase(
+ IN gckKERNEL Kernel,
+ OUT gctPOINTER * Database
+ );
+
+gceSTATUS
+gckKERNEL_DestroyIntegerDatabase(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Database
+ );
+
+gceSTATUS
+gckKERNEL_AllocateIntegerId(
+ IN gctPOINTER Database,
+ IN gctPOINTER Pointer,
+ OUT gctUINT32 * Id
+ );
+
+gceSTATUS
+gckKERNEL_FreeIntegerId(
+ IN gctPOINTER Database,
+ IN gctUINT32 Id
+ );
+
+gceSTATUS
+gckKERNEL_QueryIntegerId(
+ IN gctPOINTER Database,
+ IN gctUINT32 Id,
+ OUT gctPOINTER * Pointer
+ );
+
+/* Pointer rename */
+gctUINT32
+gckKERNEL_AllocateNameFromPointer(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Pointer
+ );
+
+gctPOINTER
+gckKERNEL_QueryPointerFromName(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name
+ );
+
+gceSTATUS
+gckKERNEL_DeleteName(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name
+ );
+
+#if gcdSECURE_USER
+/* Get secure cache from the process database. */
+gceSTATUS
+gckKERNEL_GetProcessDBCache(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gcskSECURE_CACHE_PTR * Cache
+ );
+#endif
+
+/*******************************************************************************
+********* Timer Management ****************************************************/
+typedef struct _gcsTIMER * gcsTIMER_PTR;
+typedef struct _gcsTIMER
+{
+ /* Start and Stop time holders. */
+ gctUINT64 startTime;
+ gctUINT64 stopTime;
+}
+gcsTIMER;
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+/* gckDB object. */
+struct _gckDB
+{
+ /* Database management. */
+ gcsDATABASE_PTR db[16];
+ gctPOINTER dbMutex;
+ gcsDATABASE_PTR freeDatabase;
+ gcsDATABASE_RECORD_PTR freeRecord;
+ gcsDATABASE_PTR lastDatabase;
+ gctUINT32 lastProcessID;
+ gctUINT64 lastIdle;
+ gctUINT64 idleTime;
+ gctUINT64 lastSlowdown;
+ gctUINT64 lastSlowdownIdle;
+ gctPOINTER nameDatabase;
+ gctPOINTER nameDatabaseMutex;
+
+ gctPOINTER pointerDatabase;
+ gctPOINTER pointerDatabaseMutex;
+
+ gcsLISTHEAD onFaultVidmemList;
+ gctPOINTER onFaultVidmemListMutex;
+};
+
+typedef struct _gckVIRTUAL_BUFFER * gckVIRTUAL_BUFFER_PTR;
+typedef struct _gckVIRTUAL_BUFFER
+{
+ gctPHYS_ADDR physical;
+ gctPOINTER userLogical;
+ gctPOINTER kernelLogical;
+ gctSIZE_T bytes;
+ gctSIZE_T pageCount;
+ gctPOINTER pageTable;
+ gctUINT32 gpuAddress;
+ gctUINT pid;
+ gckKERNEL kernel;
+#if gcdPROCESS_ADDRESS_SPACE
+ gckMMU mmu;
+#endif
+}
+gckVIRTUAL_BUFFER;
+
+typedef struct _gckVIRTUAL_COMMAND_BUFFER * gckVIRTUAL_COMMAND_BUFFER_PTR;
+typedef struct _gckVIRTUAL_COMMAND_BUFFER
+{
+ gckVIRTUAL_BUFFER virtualBuffer;
+ gckVIRTUAL_COMMAND_BUFFER_PTR next;
+ gckVIRTUAL_COMMAND_BUFFER_PTR prev;
+}
+gckVIRTUAL_COMMAND_BUFFER;
+
+/* gckKERNEL object. */
+struct _gckKERNEL
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Core */
+ gceCORE core;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* Pointer to gckCOMMAND object. */
+ gckCOMMAND command;
+
+ /* Pointer to gckEVENT object. */
+ gckEVENT eventObj;
+
+ /* Pointer to context. */
+ gctPOINTER context;
+
+ /* Pointer to gckMMU object. */
+ gckMMU mmu;
+
+ /* Arom holding number of clients. */
+ gctPOINTER atomClients;
+
+#if VIVANTE_PROFILER
+ /* Enable profiling */
+ gctBOOL profileEnable;
+ /* profiling sync mode*/
+ gctBOOL profileSyncMode;
+ /* Clear profile register or not*/
+ gctBOOL profileCleanRegister;
+#endif
+
+#ifdef QNX_SINGLE_THREADED_DEBUGGING
+ gctPOINTER debugMutex;
+#endif
+
+ /* Database management. */
+ gckDB db;
+ gctBOOL dbCreated;
+
+ gctUINT64 resetTimeStamp;
+
+ /* Pointer to gckEVENT object. */
+ gcsTIMER timers[8];
+ gctUINT32 timeOut;
+
+#if gcdENABLE_VG
+ gckVGKERNEL vg;
+#endif
+
+ /* Virtual command buffer list. */
+ gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferHead;
+ gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferTail;
+ gctPOINTER virtualBufferLock;
+
+ /* Enable virtual command buffer. */
+ gctBOOL virtualCommandBuffer;
+
+#if gcdDVFS
+ gckDVFS dvfs;
+#endif
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+ gctHANDLE timeline;
+#endif
+
+ /* Enable recovery. */
+ gctBOOL recovery;
+
+ /* Level of dump information after stuck. */
+ gctUINT stuckDump;
+
+#if gcdSECURITY || gcdENABLE_TRUST_APPLICATION
+ gctUINT32 securityChannel;
+#endif
+
+ /* Timer to monitor GPU stuck. */
+ gctPOINTER monitorTimer;
+
+ /* Flag to quit monitor timer. */
+ gctBOOL monitorTimerStop;
+
+ /* Monitor states. */
+ gctBOOL monitoring;
+ gctUINT32 lastCommitStamp;
+ gctUINT32 timer;
+ gctUINT32 restoreAddress;
+ gctINT32 restoreMask;
+
+ /* 3DBLIT */
+ gckASYNC_COMMAND asyncCommand;
+ gckEVENT asyncEvent;
+
+ /* Pointer to gckDEVICE object. */
+ gckDEVICE device;
+
+ gctUINT chipID;
+};
+
+struct _FrequencyHistory
+{
+ gctUINT32 frequency;
+ gctUINT32 count;
+};
+
+/* gckDVFS object. */
+struct _gckDVFS
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gctPOINTER timer;
+ gctUINT32 pollingTime;
+ gctBOOL stop;
+ gctUINT32 totalConfig;
+ gctUINT32 loads[8];
+ gctUINT8 currentScale;
+ struct _FrequencyHistory frequencyHistory[16];
+};
+
+typedef struct _gcsFENCE * gckFENCE;
+typedef struct _gcsFENCE
+{
+ /* Pointer to required object. */
+ gckKERNEL kernel;
+
+ /* Fence location. */
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+ gctUINT32 address;
+
+ gcsLISTHEAD waitingList;
+ gctPOINTER mutex;
+}
+gcsFENCE;
+
+/* A sync point attached to fence. */
+typedef struct _gcsFENCE_SYNC * gckFENCE_SYNC;
+typedef struct _gcsFENCE_SYNC
+{
+ /* Stamp of commit access this node. */
+ gctUINT64 commitStamp;
+
+ /* Attach to waiting list. */
+ gcsLISTHEAD head;
+
+ gctPOINTER signal;
+
+ gctBOOL inList;
+}
+gcsFENCE_SYNC;
+
+/* gckCOMMAND object. */
+struct _gckCOMMAND
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to required object. */
+ gckKERNEL kernel;
+ gckOS os;
+
+ /* Number of bytes per page. */
+ gctUINT32 pageSize;
+
+ /* Current pipe select. */
+ gcePIPE_SELECT pipeSelect;
+
+ /* Command queue running flag. */
+ gctBOOL running;
+
+ /* Idle flag and commit stamp. */
+ gctBOOL idle;
+ gctUINT64 commitStamp;
+
+ /* Command queue mutex. */
+ gctPOINTER mutexQueue;
+
+ /* Context switching mutex. */
+ gctPOINTER mutexContext;
+
+#if VIVANTE_PROFILER_CONTEXT
+ /* Context sequence mutex. */
+ gctPOINTER mutexContextSeq;
+#endif
+
+ /* Command queue power semaphore. */
+ gctPOINTER powerSemaphore;
+
+ /* Current command queue. */
+ struct _gcskCOMMAND_QUEUE
+ {
+ gctSIGNAL signal;
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+ gctUINT32 address;
+ }
+ queues[gcdCOMMAND_QUEUES];
+
+ gctPHYS_ADDR virtualMemory;
+ gctUINT32 physical;
+ gctPOINTER logical;
+ gctUINT32 address;
+ gctUINT32 offset;
+ gctINT index;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gctUINT wrapCount;
+#endif
+
+ /* The command queue is new. */
+ gctBOOL newQueue;
+
+ /* Context management. */
+ gckCONTEXT currContext;
+ gctPOINTER stateMap;
+
+ /* Pointer to last WAIT command. */
+ gctUINT32 waitPhysical;
+ gctPOINTER waitLogical;
+ gctUINT32 waitAddress;
+ gctUINT32 waitSize;
+
+ /* Command buffer alignment. */
+ gctUINT32 alignment;
+ gctUINT32 reservedHead;
+
+ /* Commit counter. */
+ gctPOINTER atomCommit;
+
+ /* Kernel process ID. */
+ gctUINT32 kernelProcessID;
+
+ /* End Event signal. */
+ gctSIGNAL endEventSignal;
+
+#if gcdSECURE_USER
+ /* Hint array copy buffer. */
+ gctBOOL hintArrayAllocated;
+ gctUINT hintArraySize;
+ gctUINT32_PTR hintArray;
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gckMMU currentMmu;
+#endif
+
+#if gcdRECORD_COMMAND
+ gckRECORDER recorder;
+#endif
+
+ gctPOINTER kList;
+
+ gckFENCE fence;
+
+ /* For getting state from async command buffer. */
+ gckASYNC_COMMAND asyncCommand;
+
+ gctBOOL dummyDraw;
+};
+
+typedef struct _gcsEVENT * gcsEVENT_PTR;
+
+/* Structure holding one event to be processed. */
+typedef struct _gcsEVENT
+{
+ /* Pointer to next event in queue. */
+ gcsEVENT_PTR next;
+
+ /* Event information. */
+ gcsHAL_INTERFACE info;
+
+ /* Process ID owning the event. */
+ gctUINT32 processID;
+
+#ifdef __QNXNTO__
+ /* Kernel. */
+ gckKERNEL kernel;
+#endif
+
+ gctBOOL fromKernel;
+}
+gcsEVENT;
+
+/* Structure holding a list of events to be processed by an interrupt. */
+typedef struct _gcsEVENT_QUEUE * gcsEVENT_QUEUE_PTR;
+typedef struct _gcsEVENT_QUEUE
+{
+ /* Time stamp. */
+ gctUINT64 stamp;
+
+ /* Source of the event. */
+ gceKERNEL_WHERE source;
+
+ /* Pointer to head of event queue. */
+ gcsEVENT_PTR head;
+
+ /* Pointer to tail of event queue. */
+ gcsEVENT_PTR tail;
+
+ /* Next list of events. */
+ gcsEVENT_QUEUE_PTR next;
+
+ /* Current commit stamp. */
+ gctUINT64 commitStamp;
+}
+gcsEVENT_QUEUE;
+
+/*
+ gcdREPO_LIST_COUNT defines the maximum number of event queues with different
+ hardware module sources that may coexist at the same time. Only two sources
+ are supported - gcvKERNEL_COMMAND and gcvKERNEL_PIXEL. gcvKERNEL_COMMAND
+ source is used only for managing the kernel command queue and is only issued
+ when the current command queue gets full. Since we commit event queues every
+ time we commit command buffers, in the worst case we can have up to three
+ pending event queues:
+ - gcvKERNEL_PIXEL
+ - gcvKERNEL_COMMAND (queue overflow)
+ - gcvKERNEL_PIXEL
+*/
+#define gcdREPO_LIST_COUNT 3
+
+/* gckEVENT object. */
+struct _gckEVENT
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to required objects. */
+ gckOS os;
+ gckKERNEL kernel;
+
+ /* Pointer to gckASYNC_COMMAND object. */
+ gckASYNC_COMMAND asyncCommand;
+
+ /* Time stamp. */
+ gctUINT64 stamp;
+ gctUINT32 lastCommitStamp;
+
+ /* Queue mutex. */
+ gctPOINTER eventQueueMutex;
+
+ /* Array of event queues. */
+ gcsEVENT_QUEUE queues[29];
+ gctINT32 freeQueueCount;
+ gctUINT8 lastID;
+
+ /* Pending events. */
+ gctPOINTER pending;
+
+ /* List of free event structures and its mutex. */
+ gcsEVENT_PTR freeEventList;
+ gctSIZE_T freeEventCount;
+ gctPOINTER freeEventMutex;
+
+ /* Event queues. */
+ gcsEVENT_QUEUE_PTR queueHead;
+ gcsEVENT_QUEUE_PTR queueTail;
+ gcsEVENT_QUEUE_PTR freeList;
+ gcsEVENT_QUEUE repoList[gcdREPO_LIST_COUNT];
+ gctPOINTER eventListMutex;
+
+ gctPOINTER submitTimer;
+
+#if gcdINTERRUPT_STATISTIC
+ gctPOINTER interruptCount;
+#endif
+
+ gctINT notifyState;
+};
+
+/* Free all events belonging to a process. */
+gceSTATUS
+gckEVENT_FreeProcess(
+ IN gckEVENT Event,
+ IN gctUINT32 ProcessID
+ );
+
+gceSTATUS
+gckEVENT_Stop(
+ IN gckEVENT Event,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gctSIGNAL Signal,
+ IN OUT gctUINT32 * waitSize
+ );
+
+typedef struct _gcsLOCK_INFO * gcsLOCK_INFO_PTR;
+typedef struct _gcsLOCK_INFO
+{
+ gctUINT32 GPUAddresses[gcdMAX_GPU_COUNT];
+ gctPOINTER pageTables[gcdMAX_GPU_COUNT];
+ gctUINT32 lockeds[gcdMAX_GPU_COUNT];
+ gckKERNEL lockKernels[gcdMAX_GPU_COUNT];
+ gckMMU lockMmus[gcdMAX_GPU_COUNT];
+}
+gcsLOCK_INFO;
+
+typedef struct _gcsGPU_MAP * gcsGPU_MAP_PTR;
+typedef struct _gcsGPU_MAP
+{
+ gctINT pid;
+ gcsLOCK_INFO lockInfo;
+ gcsGPU_MAP_PTR prev;
+ gcsGPU_MAP_PTR next;
+}
+gcsGPU_MAP;
+
+/* gcuVIDMEM_NODE structure. */
+typedef union _gcuVIDMEM_NODE
+{
+ /* Allocated from gckVIDMEM. */
+ struct _gcsVIDMEM_NODE_VIDMEM
+ {
+ /* Owner of this node. */
+ gckVIDMEM memory;
+
+ /* Dual-linked list of nodes. */
+ gcuVIDMEM_NODE_PTR next;
+ gcuVIDMEM_NODE_PTR prev;
+
+ /* Dual linked list of free nodes. */
+ gcuVIDMEM_NODE_PTR nextFree;
+ gcuVIDMEM_NODE_PTR prevFree;
+
+ /* Information for this node. */
+ gctSIZE_T offset;
+ gctSIZE_T bytes;
+ gctUINT32 alignment;
+
+#ifdef __QNXNTO__
+ /* Client virtual address. */
+ gctPOINTER logical;
+#endif
+
+ /* Locked counter. */
+ gctINT32 locked;
+
+ /* Memory pool. */
+ gcePOOL pool;
+ gctUINT32 physical;
+
+ /* Process ID owning this memory. */
+ gctUINT32 processID;
+
+#if gcdENABLE_VG
+ gctPOINTER kernelVirtual;
+#endif
+ }
+ VidMem;
+
+ /* Allocated from gckOS. */
+ struct _gcsVIDMEM_NODE_VIRTUAL
+ {
+ /* Pointer to gckKERNEL object. */
+ gckKERNEL kernel;
+
+ /* Information for this node. */
+ /* Contiguously allocated? */
+ gctBOOL contiguous;
+ /* mdl record pointer... a kmalloc address. Process agnostic. */
+ gctPHYS_ADDR physical;
+ gctSIZE_T bytes;
+ /* do_mmap_pgoff address... mapped per-process. */
+ gctPOINTER logical;
+
+#if gcdENABLE_VG
+ /* Physical address of this node, only meaningful when it is contiguous. */
+ gctUINT64 physicalAddress;
+
+ /* Kernel logical of this node. */
+ gctPOINTER kernelVirtual;
+#endif
+
+ /* Customer private handle */
+ gctUINT32 gid;
+
+ /* Page table information. */
+ /* Used only when node is not contiguous */
+ gctSIZE_T pageCount;
+
+ /* Used only when node is not contiguous */
+ gctPOINTER pageTables[gcdMAX_GPU_COUNT];
+ /* Actual physical address */
+ gctUINT32 addresses[gcdMAX_GPU_COUNT];
+
+ /* Locked counter. */
+ gctINT32 lockeds[gcdMAX_GPU_COUNT];
+
+ /* Surface type. */
+ gceSURF_TYPE type;
+
+ /* Secure GPU virtual address. */
+ gctBOOL secure;
+
+ gctBOOL onFault;
+
+ gcsLISTHEAD head;
+ }
+ Virtual;
+}
+gcuVIDMEM_NODE;
+
+/* gckVIDMEM object. */
+struct _gckVIDMEM
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Information for this video memory heap. */
+ gctUINT32 baseAddress;
+ gctSIZE_T bytes;
+ gctSIZE_T freeBytes;
+
+ /* Mapping for each type of surface. */
+ gctINT mapping[gcvSURF_NUM_TYPES];
+
+ /* Sentinel nodes for up to 8 banks. */
+ gcuVIDMEM_NODE sentinel[8];
+
+ /* Allocation threshold. */
+ gctSIZE_T threshold;
+
+ /* The heap mutex. */
+ gctPOINTER mutex;
+};
+
+typedef struct _gcsVIDMEM_NODE
+{
+ /* Pointer to gcuVIDMEM_NODE. */
+ gcuVIDMEM_NODE_PTR node;
+
+ /* Mutex to protect node. */
+ gctPOINTER mutex;
+
+ /* Reference count. */
+ gctPOINTER reference;
+
+ /* Name for client to import. */
+ gctUINT32 name;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ /* Head of mapping list. */
+ gcsGPU_MAP_PTR mapHead;
+
+ /* Tail of mapping list. */
+ gcsGPU_MAP_PTR mapTail;
+
+ gctPOINTER mapMutex;
+#endif
+
+ /* Surface Type. */
+ gceSURF_TYPE type;
+
+ /* Pool from which node is allocated. */
+ gcePOOL pool;
+
+ gcsFENCE_SYNC sync[gcvENGINE_COUNT];
+}
+gcsVIDMEM_NODE;
+
+typedef struct _gcsVIDMEM_HANDLE * gckVIDMEM_HANDLE;
+typedef struct _gcsVIDMEM_HANDLE
+{
+ /* Pointer to gckVIDMEM_NODE. */
+ gckVIDMEM_NODE node;
+
+ /* Handle for current process. */
+ gctUINT32 handle;
+
+ /* Reference count for this handle. */
+ gctPOINTER reference;
+}
+gcsVIDMEM_HANDLE;
+
+typedef struct _gcsSHBUF * gcsSHBUF_PTR;
+typedef struct _gcsSHBUF
+{
+ /* ID. */
+ gctUINT32 id;
+
+ /* Reference count. */
+ gctPOINTER reference;
+
+ /* Data size. */
+ gctUINT32 size;
+
+ /* Data. */
+ gctPOINTER data;
+}
+gcsSHBUF;
+
+typedef struct _gcsCORE_INFO
+{
+ gceHARDWARE_TYPE type;
+ gceCORE core;
+ gckKERNEL kernel;
+ gctUINT chipID;
+}
+gcsCORE_INFO;
+
+typedef struct _gcsCORE_LIST
+{
+ gckKERNEL kernels[gcvCORE_COUNT];
+ gctUINT32 num;
+}
+gcsCORE_LIST;
+
+/* A gckDEVICE is a group of cores (gckKERNEL in software). */
+typedef struct _gcsDEVICE
+{
+ gcsCORE_INFO coreInfoArray[gcvCORE_COUNT];
+ gctUINT32 coreNum;
+ gcsCORE_LIST map[gcvHARDWARE_NUM_TYPES];
+
+ gckOS os;
+
+ /* Process resource database. */
+ gckDB database;
+
+ /* Same hardware type shares one MMU. */
+ gckMMU mmus[gcvHARDWARE_NUM_TYPES];
+
+ /* Mutex to make sure stuck dump for multiple cores doesn't interleave. */
+ gctPOINTER stuckDumpMutex;
+
+ /* Mutex for multi-core combine mode command submission */
+ gctPOINTER commitMutex;
+}
+gcsDEVICE;
+
+gceSTATUS
+gckVIDMEM_HANDLE_Reference(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle
+ );
+
+gceSTATUS
+gckVIDMEM_HANDLE_Dereference(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle
+ );
+
+gceSTATUS
+gckVIDMEM_NODE_Allocate(
+ IN gckKERNEL Kernel,
+ IN gcuVIDMEM_NODE_PTR VideoNode,
+ IN gceSURF_TYPE Type,
+ IN gcePOOL Pool,
+ IN gctUINT32 * Handle
+ );
+
+gceSTATUS
+gckVIDMEM_Node_Lock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ OUT gctUINT32 *Address
+ );
+
+gceSTATUS
+gckVIDMEM_NODE_Unlock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gctUINT32 ProcessID
+ );
+
+gceSTATUS
+gckVIDMEM_NODE_Dereference(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node
+ );
+
+gceSTATUS
+gckVIDMEM_NODE_Name(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Handle,
+ IN gctUINT32 * Name
+ );
+
+gceSTATUS
+gckVIDMEM_NODE_Import(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name,
+ IN gctUINT32 * Handle
+ );
+
+gceSTATUS
+gckVIDMEM_NODE_GetFd(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Handle,
+ OUT gctINT * Fd
+ );
+
+gceSTATUS
+gckVIDMEM_HANDLE_LookupAndReference(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Handle,
+ OUT gckVIDMEM_NODE * Node
+ );
+
+gceSTATUS
+gckVIDMEM_HANDLE_Lookup(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle,
+ OUT gckVIDMEM_NODE * Node
+ );
+
+gceSTATUS
+gckVIDMEM_ConstructVirtualFromUserMemory(
+ IN gckKERNEL Kernel,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+gceSTATUS
+gckVIDMEM_FindVIDMEM(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 HardwareAddress,
+ OUT gcuVIDMEM_NODE_PTR * Node,
+ OUT gctUINT32_PTR PageTableEntryValue
+ );
+
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckEVENT_DestroyMmu(
+ IN gckEVENT Event,
+ IN gckMMU Mmu,
+ IN gceKERNEL_WHERE FromWhere
+ );
+#endif
+
+typedef struct _gcsADDRESS_AREA * gcsADDRESS_AREA_PTR;
+typedef struct _gcsADDRESS_AREA
+{
+ /* Page table information. */
+ gctSIZE_T pageTableSize;
+ gctPHYS_ADDR pageTablePhysical;
+ gctUINT32_PTR pageTableLogical;
+ gctUINT32 pageTableEntries;
+
+ /* Free entries. */
+ gctUINT32 heapList;
+ gctBOOL freeNodes;
+
+ gctUINT32 dynamicMappingStart;
+ gctUINT32 dynamicMappingEnd;
+
+ gctUINT32_PTR mapLogical;
+}
+gcsADDRESS_AREA;
+
+/* gckMMU object. */
+struct _gckMMU
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* The page table mutex. */
+ gctPOINTER pageTableMutex;
+
+ /* Master TLB information. */
+ gctSIZE_T mtlbSize;
+ gctPHYS_ADDR mtlbPhysical;
+ gctUINT32_PTR mtlbLogical;
+ gctUINT32 mtlbEntries;
+
+ gctPOINTER staticSTLB;
+ /*Track all static STLB allocations */
+ gctPOINTER staticStlbAllocs;
+ gctBOOL enabled;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gctPOINTER pageTableDirty[gcdMAX_GPU_COUNT];
+ gctPOINTER stlbs;
+#endif
+
+ gctPOINTER safePageLogical;
+ gctPHYS_ADDR safePagePhysical;
+ gctUINT32 safeAddress;
+ gctSIZE_T safePageSize;
+
+ gctUINT32 flatMappingStart;
+ gctUINT32 flatMappingEnd;
+
+ /* List of hardware which uses this MMU. */
+ gcsLISTHEAD hardwareList;
+
+ struct _gckQUEUE recentFreedAddresses;
+
+ gcsADDRESS_AREA area[gcvADDRESS_AREA_COUNT];
+};
+
+typedef struct _gcsASYNC_COMMAND
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gckKERNEL kernel;
+
+ gctPOINTER mutex;
+ gcsFE fe;
+
+ gctUINT32 reservedTail;
+ gctUINT64 commitStamp;
+
+ gckFENCE fence;
+
+ gctPOINTER kList;
+}
+gcsASYNC_COMMAND;
+
+
+gceSTATUS
+gckOS_CreateKernelVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ );
+
+gceSTATUS
+gckOS_DestroyKernelVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+gceSTATUS
+gckOS_CreateUserVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ );
+
+gceSTATUS
+gckOS_DestroyUserVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+gceSTATUS
+gckOS_GetFd(
+ IN gctSTRING Name,
+ IN gcsFDPRIVATE_PTR Private,
+ OUT gctINT *Fd
+ );
+
+/*******************************************************************************
+**
+** gckOS_ReadMappedPointer
+**
+** Read pointer mapped from user pointer which returned by gckOS_MapUserPointer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Pointer returned by gckOS_MapUserPointer.
+**
+** gctUINT32_PTR Data
+** Pointer to hold 32 bits data.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ReadMappedPointer(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32_PTR Data
+ );
+
+gceSTATUS
+gckKERNEL_AllocateVirtualCommandBuffer(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+gceSTATUS
+gckKERNEL_DestroyVirtualCommandBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+gceSTATUS
+gckKERNEL_AllocateVirtualMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL NonPaged,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+gceSTATUS
+gckKERNEL_FreeVirtualMemory(
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctBOOL NonPaged
+ );
+
+gceSTATUS
+gckKERNEL_GetGPUAddress(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ IN gctPHYS_ADDR Physical,
+ OUT gctUINT32 * Address
+ );
+
+gceSTATUS
+gckKERNEL_QueryGPUAddress(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GpuAddress,
+ OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
+ );
+
+gceSTATUS
+gckKERNEL_AttachProcess(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach
+ );
+
+gceSTATUS
+gckKERNEL_AttachProcessEx(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach,
+ IN gctUINT32 PID
+ );
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+ IN gckKERNEL Kernel,
+ IN gcskSECURE_CACHE_PTR Cache,
+ IN OUT gctPOINTER * Data
+ );
+
+gceSTATUS
+gckKERNEL_FlushTranslationCache(
+ IN gckKERNEL Kernel,
+ IN gcskSECURE_CACHE_PTR Cache,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+ IN gckHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ );
+
+gceSTATUS
+gckHARDWARE_WaitFence(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT64 FenceData,
+ IN gctUINT32 FenceAddress,
+ OUT gctUINT32 *Bytes
+ );
+
+gceSTATUS
+gckHARDWARE_AddressInHardwareFuncions(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gctPOINTER *Pointer
+ );
+
+gceSTATUS
+gckHARDWARE_UpdateContextID(
+ IN gckHARDWARE Hardware
+ );
+
+#if gcdSECURITY
+gceSTATUS
+gckKERNEL_SecurityOpen(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPU,
+ OUT gctUINT32 *Channel
+ );
+
+/*
+** Close a security service channel
+*/
+gceSTATUS
+gckKERNEL_SecurityClose(
+ IN gctUINT32 Channel
+ );
+
+/*
+** Security service interface.
+*/
+gceSTATUS
+gckKERNEL_SecurityCallService(
+ IN gctUINT32 Channel,
+ IN OUT gcsTA_INTERFACE * Interface
+ );
+
+gceSTATUS
+gckKERNEL_SecurityStartCommand(
+ IN gckKERNEL Kernel
+ );
+
+gceSTATUS
+gckKERNEL_SecurityAllocateSecurityMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Bytes,
+ OUT gctUINT32 * Handle
+ );
+
+gceSTATUS
+gckKERNEL_SecurityExecute(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Buffer,
+ IN gctUINT32 Bytes
+ );
+
+gceSTATUS
+gckKERNEL_SecurityMapMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 *PhysicalArray,
+ IN gctUINT32 PageCount,
+ OUT gctUINT32 * GPUAddress
+ );
+
+gceSTATUS
+gckKERNEL_SecurityUnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPUAddress,
+ IN gctUINT32 PageCount
+ );
+
+#endif
+
+#if gcdENABLE_TRUST_APPLICATION
+gceSTATUS
+gckKERNEL_SecurityOpen(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPU,
+ OUT gctUINT32 *Channel
+ );
+
+/*
+** Close a security service channel
+*/
+gceSTATUS
+gckKERNEL_SecurityClose(
+ IN gctUINT32 Channel
+ );
+
+/*
+** Security service interface.
+*/
+gceSTATUS
+gckKERNEL_SecurityCallService(
+ IN gctUINT32 Channel,
+ IN OUT gcsTA_INTERFACE * Interface
+ );
+
+gceSTATUS
+gckKERNEL_SecurityStartCommand(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Address,
+ IN gctUINT32 Bytes
+ );
+
+gceSTATUS
+gckKERNEL_SecurityMapMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 *PhysicalArray,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctUINT32 PageCount,
+ OUT gctUINT32 * GPUAddress
+ );
+
+gceSTATUS
+gckKERNEL_SecurityUnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPUAddress,
+ IN gctUINT32 PageCount
+ );
+
+gceSTATUS
+gckKERNEL_SecurityDumpMMUException(
+ IN gckKERNEL Kernel
+ );
+
+gceSTATUS
+gckKERNEL_ReadMMUException(
+ IN gckKERNEL Kernel,
+ IN gctUINT32_PTR MMUStatus,
+ IN gctUINT32_PTR MMUException
+ );
+
+gceSTATUS
+gckKERNEL_HandleMMUException(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 MMUStatus,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctUINT32 GPUAddres
+ );
+#endif
+
+gceSTATUS
+gckKERNEL_CreateShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Size,
+ OUT gctSHBUF * ShBuf
+ );
+
+gceSTATUS
+gckKERNEL_DestroyShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf
+ );
+
+gceSTATUS
+gckKERNEL_MapShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf
+ );
+
+gceSTATUS
+gckKERNEL_WriteShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf,
+ IN gctPOINTER UserData,
+ IN gctUINT32 ByteCount
+ );
+
+gceSTATUS
+gckKERNEL_ReadShBuffer(
+ IN gckKERNEL Kernel,
+ IN gctSHBUF ShBuf,
+ IN gctPOINTER UserData,
+ IN gctUINT32 ByteCount,
+ OUT gctUINT32 * BytesRead
+ );
+
+
+/******************************************************************************\
+******************************* gckCONTEXT Object *******************************
+\******************************************************************************/
+
+gceSTATUS
+gckCONTEXT_Construct(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 ProcessID,
+ OUT gckCONTEXT * Context
+ );
+
+gceSTATUS
+gckCONTEXT_Destroy(
+ IN gckCONTEXT Context
+ );
+
+gceSTATUS
+gckCONTEXT_Update(
+ IN gckCONTEXT Context,
+ IN gctUINT32 ProcessID,
+ IN gcsSTATE_DELTA_PTR StateDelta
+ );
+
+gceSTATUS
+gckCONTEXT_MapBuffer(
+ IN gckCONTEXT Context,
+ OUT gctUINT32 *Physicals,
+ OUT gctUINT64 *Logicals,
+ OUT gctUINT32 *Bytes
+ );
+
+void
+gckQUEUE_Enqueue(
+ IN gckQUEUE LinkQueue,
+ IN gcuQUEUEDATA *Data
+ );
+
+void
+gckQUEUE_GetData(
+ IN gckQUEUE LinkQueue,
+ IN gctUINT32 Index,
+ OUT gcuQUEUEDATA ** Data
+ );
+
+gceSTATUS
+gckQUEUE_Allocate(
+ IN gckOS Os,
+ IN gckQUEUE Queue,
+ IN gctUINT32 Size
+ );
+
+gceSTATUS
+gckQUEUE_Free(
+ IN gckOS Os,
+ IN gckQUEUE Queue
+ );
+
+/******************************************************************************\
+****************************** gckRECORDER Object ******************************
+\******************************************************************************/
+gceSTATUS
+gckRECORDER_Construct(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ OUT gckRECORDER * Recorder
+ );
+
+gceSTATUS
+gckRECORDER_Destory(
+ IN gckOS Os,
+ IN gckRECORDER Recorder
+ );
+
+void
+gckRECORDER_AdvanceIndex(
+ gckRECORDER Recorder,
+ gctUINT64 CommitStamp
+ );
+
+void
+gckRECORDER_Record(
+ gckRECORDER Recorder,
+ gctUINT8_PTR CommandBuffer,
+ gctUINT32 CommandBytes,
+ gctUINT8_PTR ContextBuffer,
+ gctUINT32 ContextBytes
+ );
+
+void
+gckRECORDER_Dump(
+ gckRECORDER Recorder
+ );
+
+gceSTATUS
+gckRECORDER_UpdateMirror(
+ gckRECORDER Recorder,
+ gctUINT32 State,
+ gctUINT32 Data
+ );
+
+/******************************************************************************\
+*************************** gckASYNC_COMMAND Object ****************************
+\******************************************************************************/
+gceSTATUS
+gckASYNC_COMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckASYNC_COMMAND * Command
+ );
+
+gceSTATUS
+gckASYNC_COMMAND_Destroy(
+ IN gckASYNC_COMMAND Command
+ );
+
+gceSTATUS
+gckASYNC_COMMAND_Commit(
+ IN gckASYNC_COMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcsQUEUE_PTR EventQueue
+ );
+
+gceSTATUS
+gckASYNC_COMMAND_EnterCommit(
+ IN gckASYNC_COMMAND Command
+ );
+
+gceSTATUS
+gckASYNC_COMMAND_ExitCommit(
+ IN gckASYNC_COMMAND Command
+ );
+
+gceSTATUS
+gckASYNC_COMMAND_Execute(
+ IN gckASYNC_COMMAND Command,
+ IN gctUINT32 Start,
+ IN gctUINT32 End
+ );
+
+void
+gcsLIST_Init(
+ gcsLISTHEAD_PTR Node
+ );
+
+void
+gcsLIST_Add(
+ gcsLISTHEAD_PTR New,
+ gcsLISTHEAD_PTR Head
+ );
+
+void
+gcsLIST_AddTail(
+ gcsLISTHEAD_PTR New,
+ gcsLISTHEAD_PTR Head
+ );
+
+void
+gcsLIST_Del(
+ gcsLISTHEAD_PTR Node
+ );
+
+gctBOOL
+gcsLIST_Empty(
+ gcsLISTHEAD_PTR Head
+ );
+
+#define gcmkLIST_FOR_EACH(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define gcmkLIST_FOR_EACH_SAFE(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+gceSTATUS
+gckFENCE_Create(
+ IN gckOS Os,
+ IN gckKERNEL Kernel,
+ OUT gckFENCE * Fence
+ );
+
+gceSTATUS
+gckFENCE_Destory(
+ IN gckOS Os,
+ OUT gckFENCE Fence
+ );
+
+gceSTATUS
+gckFENCE_Signal(
+ IN gckOS Os,
+ IN gckFENCE Fence
+ );
+
+gceSTATUS
+gckDEVICE_Construct(
+ IN gckOS Os,
+ OUT gckDEVICE * Device
+ );
+
+gceSTATUS
+gckDEVICE_AddCore(
+ IN gckDEVICE Device,
+ IN gceCORE Core,
+ IN gctUINT chipID,
+ IN gctPOINTER Context,
+ IN gckKERNEL * Kernel
+ );
+
+gceSTATUS
+gckDEVICE_Destroy(
+ IN gckOS Os,
+ IN gckDEVICE Device
+ );
+
+gceSTATUS
+gckDEVICE_Dispatch(
+ IN gckDEVICE Device,
+ IN gcsHAL_INTERFACE_PTR Interface
+ );
+
+gceSTATUS
+gckDEVICE_GetMMU(
+ IN gckDEVICE Device,
+ IN gceHARDWARE_TYPE Type,
+ IN gckMMU *Mmu
+ );
+
+gceSTATUS
+gckDEVICE_SetMMU(
+ IN gckDEVICE Device,
+ IN gceHARDWARE_TYPE Type,
+ IN gckMMU Mmu
+ );
+
+gceSTATUS
+gckDEVICE_QueryGPUAddress(
+ IN gckDEVICE Device,
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPUAddress,
+ OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
+ );
+
+#if gcdENABLE_TRUST_APPLICATION
+gceSTATUS
+gckKERNEL_MapInTrustApplicaiton(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctPHYS_ADDR Physical,
+ IN gctUINT32 GPUAddress,
+ IN gctSIZE_T PageCount
+ );
+#endif
+
+#if gcdSECURITY || gcdENABLE_TRUST_APPLICATION
+gceSTATUS
+gckOS_OpenSecurityChannel(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctUINT32 *Channel
+ );
+
+gceSTATUS
+gckOS_CloseSecurityChannel(
+ IN gctUINT32 Channel
+ );
+
+gceSTATUS
+gckOS_CallSecurityService(
+ IN gctUINT32 Channel,
+ IN gcsTA_INTERFACE * Interface
+ );
+
+gceSTATUS
+gckOS_InitSecurityChannel(
+ OUT gctUINT32 Channel
+ );
+
+gceSTATUS
+gckOS_AllocatePageArray(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageArrayLogical,
+ OUT gctPHYS_ADDR * PageArrayPhysical
+ );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_async_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_async_command.c
new file mode 100644
index 000000000000..f52b0d369632
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_async_command.c
@@ -0,0 +1,454 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_kernel_context.h"
+
+#define _GC_OBJ_ZONE gcvZONE_ASYNC_COMMAND
+
+static gceSTATUS
+_HandlePatchList(
+ IN gckASYNC_COMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ IN gctBOOL NeedCopy
+ )
+{
+ gceSTATUS status;
+ gcsPATCH_LIST * uList;
+ gcsPATCH_LIST * previous;
+ gcsPATCH_LIST * kList;
+
+ gcmkHEADER_ARG(
+ "Command=0x%x CommandBuffer=0x%x NeedCopy=%d",
+ Command, CommandBuffer, NeedCopy
+ );
+
+ uList = gcmUINT64_TO_PTR(CommandBuffer->patchHead);
+
+ while (uList)
+ {
+ gctUINT i;
+
+ kList = gcvNULL;
+ previous = uList;
+
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ Command->kernel,
+ NeedCopy,
+ Command->kList,
+ uList,
+ gcmSIZEOF(gcsPATCH_LIST),
+ (gctPOINTER *)&kList
+ ));
+
+ for (i = 0; i < kList->count; i++)
+ {
+ gcsPATCH * patch = &kList->patch[i];
+
+ /* Touch video memory node. */
+ gcmkVERIFY_OK(gckVIDMEM_SetCommitStamp(Command->kernel, gcvENGINE_BLT, patch->handle, Command->commitStamp));
+ }
+
+ uList = kList->next;
+
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ Command->kernel,
+ NeedCopy,
+ gcvFALSE,
+ previous,
+ gcmSIZEOF(gcsPATCH_LIST),
+ (gctPOINTER *)&kList
+ ));
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (kList)
+ {
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ Command->kernel,
+ NeedCopy,
+ gcvFALSE,
+ previous,
+ gcmSIZEOF(gcsPATCH_LIST),
+ (gctPOINTER *)&kList
+ ));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+
+gceSTATUS
+gckASYNC_COMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckASYNC_COMMAND * Command
+ )
+{
+ gceSTATUS status;
+ gckASYNC_COMMAND command;
+ gckOS os = Kernel->os;
+
+ gcmkHEADER();
+
+ /* Allocate gckASYNC_COMMAND object. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsASYNC_COMMAND), (gctPOINTER *)&command));
+
+ gckOS_ZeroMemory(command, gcmSIZEOF(gcsASYNC_COMMAND));
+
+ /* Mutex to protect gckFE. */
+ gcmkONERROR(gckOS_CreateMutex(os, &command->mutex));
+
+ /* Initialize gckFE. */
+ gckFE_Initialize(Kernel->hardware, &command->fe);
+
+ /* Initialize gckASYNC_COMMAND object. */
+ command->os = os;
+ command->kernel = Kernel;
+ command->hardware = Kernel->hardware;
+
+ gcmkVERIFY_OK(gckHARDWARE_QueryCommandBuffer(
+ Kernel->hardware,
+ gcvENGINE_BLT,
+ gcvNULL,
+ gcvNULL,
+ &command->reservedTail
+ ));
+
+ gcmkONERROR(gckFENCE_Create(
+ os, Kernel, &command->fence
+ ));
+
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsPATCH_LIST), &command->kList));
+
+ /* Commit stamp start from 1. */
+ command->commitStamp = 1;
+
+ *Command = command;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Rollback. */
+ gckASYNC_COMMAND_Destroy(command);
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckASYNC_COMMAND_Destroy(
+ IN gckASYNC_COMMAND Command
+ )
+{
+ gcmkHEADER();
+
+ if (Command)
+ {
+ if (Command->mutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutex));
+ }
+
+ if (Command->fence)
+ {
+ gcmkVERIFY_OK(gckFENCE_Destory(Command->os, Command->fence));
+ }
+
+ if (Command->kList)
+ {
+ gcmkOS_SAFE_FREE(Command->os, Command->kList);
+ }
+
+ if (Command->fe.freeDscriptors)
+ {
+ gcmkOS_SAFE_FREE(Command->os, Command->fe.freeDscriptors);
+ }
+
+ gcmkOS_SAFE_FREE(Command->os, Command);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckASYNC_COMMAND_Commit(
+ IN gckASYNC_COMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcsQUEUE_PTR EventQueue
+ )
+{
+ gceSTATUS status;
+ gctBOOL available = gcvFALSE;
+ gctBOOL acquired = gcvFALSE;
+ gcoCMDBUF commandBufferObject = gcvNULL;
+ struct _gcoCMDBUF _commandBufferObject;
+ gctUINT8_PTR commandBufferLogical;
+ gctUINT8_PTR commandBufferTail;
+ gctUINT commandBufferSize;
+ gctUINT32 commandBufferAddress;
+ gcsFEDescriptor descriptor;
+ gctUINT32 pipeBytes;
+ gctUINT32 fenceBytes;
+ gctBOOL needCopy;
+ gcmkHEADER();
+
+ gckHARDWARE_PipeSelect(Command->hardware, gcvNULL, gcvPIPE_3D, &pipeBytes);
+
+ gckOS_QueryNeedCopy(Command->os, 0, &needCopy);
+
+ gcmkVERIFY_OK(_HandlePatchList(Command, CommandBuffer, needCopy));
+
+ /* Open user passed gcoCMDBUF object. */
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ Command->kernel,
+ needCopy,
+ &_commandBufferObject,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *)&commandBufferObject
+ ));
+
+ gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
+
+ /* Compute the command buffer entry and the size. */
+ commandBufferLogical
+ = (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
+ + commandBufferObject->startOffset
+ + pipeBytes;
+
+ commandBufferSize
+ = commandBufferObject->offset
+ + Command->reservedTail
+ - commandBufferObject->startOffset
+ - pipeBytes;
+
+ commandBufferTail
+ = commandBufferLogical
+ + commandBufferSize
+ - Command->reservedTail;
+
+ /* Get the hardware address. */
+ if (Command->kernel && Command->kernel->virtualCommandBuffer)
+ {
+ gckKERNEL kernel = Command->kernel;
+ gckVIRTUAL_COMMAND_BUFFER_PTR virtualCommandBuffer
+ = gcmNAME_TO_PTR(commandBufferObject->physical);
+
+ if (virtualCommandBuffer == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Command->kernel,
+ commandBufferLogical,
+ gcvTRUE,
+ virtualCommandBuffer,
+ &commandBufferAddress
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ Command->hardware,
+ commandBufferLogical,
+ gcvTRUE,
+ &commandBufferAddress
+ ));
+ }
+
+ gcmkONERROR(gckHARDWARE_Fence(
+ Command->hardware,
+ gcvENGINE_BLT,
+ commandBufferTail,
+ Command->fence->address,
+ Command->commitStamp,
+ &fenceBytes
+ ));
+
+ descriptor.start = commandBufferAddress;
+ descriptor.end = commandBufferAddress + commandBufferSize;
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ commandBufferLogical,
+ commandBufferSize,
+ gceDUMP_BUFFER_USER,
+ gcvFALSE
+ );
+
+ gckOS_AcquireMutex(Command->os, Command->mutex, gcvINFINITE);
+ acquired = gcvTRUE;
+
+ /* Acquire a slot. */
+ for(;;)
+ {
+ gcmkONERROR(gckFE_ReserveSlot(Command->hardware, &Command->fe, &available));
+
+ if (available)
+ {
+ break;
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, _GC_OBJ_ZONE, "No available slot, have to wait");
+
+ gckOS_Delay(Command->os, 1);
+ }
+ }
+
+ /* Send descriptor. */
+ gckFE_Execute(Command->hardware, &Command->fe, &descriptor);
+
+ Command->commitStamp++;
+
+ gckOS_ReleaseMutex(Command->os, Command->mutex);
+ acquired = gcvFALSE;
+
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ Command->kernel,
+ needCopy,
+ gcvFALSE,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *)&commandBufferObject
+ ));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gckOS_ReleaseMutex(Command->os, Command->mutex);
+ }
+
+ if (commandBufferObject)
+ {
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ Command->kernel,
+ needCopy,
+ gcvFALSE,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *)&commandBufferObject
+ ));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckASYNC_COMMAND_EnterCommit(
+ IN gckASYNC_COMMAND Command
+ )
+{
+ return gckOS_AcquireMutex(Command->os, Command->mutex, gcvINFINITE);
+}
+
+
+gceSTATUS
+gckASYNC_COMMAND_ExitCommit(
+ IN gckASYNC_COMMAND Command
+ )
+{
+ return gckOS_ReleaseMutex(Command->os, Command->mutex);
+}
+
+gceSTATUS
+gckASYNC_COMMAND_Execute(
+ IN gckASYNC_COMMAND Command,
+ IN gctUINT32 Start,
+ IN gctUINT32 End
+ )
+{
+ gceSTATUS status;
+ gcsFEDescriptor descriptor;
+ gctBOOL available;
+
+ descriptor.start = Start;
+ descriptor.end = End;
+
+ /* Acquire a slot. */
+ for(;;)
+ {
+ gcmkONERROR(gckFE_ReserveSlot(Command->hardware, &Command->fe, &available));
+
+ if (available)
+ {
+ break;
+ }
+ else
+ {
+ gckOS_Delay(Command->os, 1);
+ }
+ }
+
+ /* Send descriptor. */
+ gckFE_Execute(Command->hardware, &Command->fe, &descriptor);
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
new file mode 100644
index 000000000000..59a4fcc306c5
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
@@ -0,0 +1,3556 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_kernel_context.h"
+
+#define _GC_OBJ_ZONE gcvZONE_COMMAND
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** _NewQueue
+**
+** Allocate a new command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** OUTPUT:
+**
+** gckCOMMAND Command
+** gckCOMMAND object has been updated with a new command queue.
+*/
+static gceSTATUS
+_NewQueue(
+ IN OUT gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctINT currentIndex, newIndex;
+ gctPHYS_ADDR_T physical;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Switch to the next command buffer. */
+ currentIndex = Command->index;
+ newIndex = (currentIndex + 1) % gcdCOMMAND_QUEUES;
+
+ /* Wait for availability. */
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.waitsignal]");
+#endif
+
+ gcmkONERROR(gckOS_WaitSignal(
+ Command->os,
+ Command->queues[newIndex].signal,
+ gcvFALSE,
+ gcvINFINITE
+ ));
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ if (newIndex < currentIndex)
+ {
+ Command->wrapCount += 1;
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ 2 * 4,
+ "%s(%d): queue array wrapped around.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ 3 * 4,
+ "%s(%d): total queue wrap arounds %d.\n",
+ __FUNCTION__, __LINE__, Command->wrapCount
+ );
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ 3 * 4,
+ "%s(%d): switched to queue %d.\n",
+ __FUNCTION__, __LINE__, newIndex
+ );
+#endif
+
+ /* Update gckCOMMAND object with new command queue. */
+ Command->index = newIndex;
+ Command->newQueue = gcvTRUE;
+ Command->virtualMemory = Command->queues[newIndex].physical;
+ Command->logical = Command->queues[newIndex].logical;
+ Command->address = Command->queues[newIndex].address;
+ Command->offset = 0;
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ Command->os,
+ Command->logical,
+ &physical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(Command->physical, physical);
+
+ if (currentIndex != -1)
+ {
+ /* Mark the command queue as available. */
+ gcmkONERROR(gckEVENT_Signal(
+ Command->kernel->eventObj,
+ Command->queues[currentIndex].signal,
+ gcvKERNEL_COMMAND
+ ));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("Command->index=%d", Command->index);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_IncrementCommitAtom(
+ IN gckCOMMAND Command,
+ IN gctBOOL Increment
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware;
+ gctINT32 atomValue;
+ gctBOOL powerAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Extract the gckHARDWARE and gckEVENT objects. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Grab the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, hardware->powerMutex, gcvINFINITE
+ ));
+ powerAcquired = gcvTRUE;
+
+ /* Increment the commit atom. */
+ if (Increment)
+ {
+ gcmkONERROR(gckOS_AtomIncrement(
+ Command->os, Command->atomCommit, &atomValue
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_AtomDecrement(
+ Command->os, Command->atomCommit, &atomValue
+ ));
+ }
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(
+ Command->os, hardware->powerMutex
+ ));
+ powerAcquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (powerAcquired)
+ {
+ /* Release the power mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ Command->os, hardware->powerMutex
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdSECURE_USER
+static gceSTATUS
+_ProcessHints(
+ IN gckCOMMAND Command,
+ IN gctUINT32 ProcessID,
+ IN gcoCMDBUF CommandBuffer
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gckKERNEL kernel;
+ gctBOOL needCopy = gcvFALSE;
+ gcskSECURE_CACHE_PTR cache;
+ gctUINT8_PTR commandBufferLogical;
+ gctUINT8_PTR hintedData;
+ gctUINT32_PTR hintArray;
+ gctUINT i, hintCount;
+
+ gcmkHEADER_ARG(
+ "Command=0x%08X ProcessID=%d CommandBuffer=0x%08X",
+ Command, ProcessID, CommandBuffer
+ );
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Reset state array pointer. */
+ hintArray = gcvNULL;
+
+ /* Get the kernel object. */
+ kernel = Command->kernel;
+
+ /* Get the cache form the database. */
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
+
+ /* Determine the start of the command buffer. */
+ commandBufferLogical
+ = (gctUINT8_PTR) CommandBuffer->logical
+ + CommandBuffer->startOffset;
+
+ /* Determine the number of records in the state array. */
+ hintCount = CommandBuffer->hintArrayTail - CommandBuffer->hintArray;
+
+ /* Check wehther we need to copy the structures or not. */
+ gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
+
+ /* Get access to the state array. */
+ if (needCopy)
+ {
+ gctUINT copySize;
+
+ if (Command->hintArrayAllocated &&
+ (Command->hintArraySize < CommandBuffer->hintArraySize))
+ {
+ gcmkONERROR(gcmkOS_SAFE_FREE(Command->os, gcmUINT64_TO_PTR(Command->hintArray)));
+ Command->hintArraySize = gcvFALSE;
+ }
+
+ if (!Command->hintArrayAllocated)
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkONERROR(gckOS_Allocate(
+ Command->os,
+ CommandBuffer->hintArraySize,
+ &pointer
+ ));
+
+ Command->hintArray = gcmPTR_TO_UINT64(pointer);
+ Command->hintArrayAllocated = gcvTRUE;
+ Command->hintArraySize = CommandBuffer->hintArraySize;
+ }
+
+ hintArray = gcmUINT64_TO_PTR(Command->hintArray);
+ copySize = hintCount * gcmSIZEOF(gctUINT32);
+
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Command->os,
+ hintArray,
+ gcmUINT64_TO_PTR(CommandBuffer->hintArray),
+ copySize
+ ));
+ }
+ else
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkONERROR(gckOS_MapUserPointer(
+ Command->os,
+ gcmUINT64_TO_PTR(CommandBuffer->hintArray),
+ CommandBuffer->hintArraySize,
+ &pointer
+ ));
+
+ hintArray = pointer;
+ }
+
+ /* Scan through the buffer. */
+ for (i = 0; i < hintCount; i += 1)
+ {
+ /* Determine the location of the hinted data. */
+ hintedData = commandBufferLogical + hintArray[i];
+
+ /* Map handle into physical address. */
+ gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
+ kernel, cache, (gctPOINTER) hintedData
+ ));
+ }
+
+OnError:
+ /* Get access to the state array. */
+ if (!needCopy && (hintArray != gcvNULL))
+ {
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ gcmUINT64_TO_PTR(CommandBuffer->hintArray),
+ CommandBuffer->hintArraySize,
+ hintArray
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+#if !gcdNULL_DRIVER
+static gceSTATUS
+_FlushMMU(
+ IN gckCOMMAND Command
+ )
+{
+#if gcdSECURITY
+ return gcvSTATUS_OK;
+#else
+ gceSTATUS status;
+ gctUINT32 oldValue;
+ gckHARDWARE hardware = Command->kernel->hardware;
+ gctBOOL pause = gcvFALSE;
+
+ gctUINT8_PTR pointer;
+ gctUINT32 address;
+ gctUINT32 eventBytes;
+ gctUINT32 endBytes;
+ gctUINT32 bufferSize;
+ gctUINT32 executeBytes;
+ gctUINT32 waitLinkBytes;
+
+ gcmkONERROR(gckOS_AtomicExchange(Command->os,
+ hardware->pageTableDirty,
+ 0,
+ &oldValue));
+
+ if (oldValue)
+ {
+ /* Page Table is upated, flush mmu before commit. */
+ gcmkONERROR(gckHARDWARE_FlushMMU(hardware));
+
+ if ((oldValue & gcvPAGE_TABLE_DIRTY_BIT_FE)
+ && (!hardware->stallFEPrefetch)
+ )
+ {
+ pause = gcvTRUE;
+ }
+ }
+
+ if (pause)
+ {
+ /* Query size. */
+ gcmkONERROR(gckHARDWARE_Event(hardware, gcvNULL, 0, gcvKERNEL_PIXEL, &eventBytes));
+ gcmkONERROR(gckHARDWARE_End(hardware, gcvNULL, ~0U, &endBytes));
+
+ executeBytes = eventBytes + endBytes;
+
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ hardware,
+ gcvNULL,
+ ~0U,
+ Command->offset + executeBytes,
+ &waitLinkBytes,
+ gcvNULL,
+ gcvNULL
+ ));
+
+ /* Reserve space. */
+ gcmkONERROR(gckCOMMAND_Reserve(
+ Command,
+ executeBytes,
+ (gctPOINTER *)&pointer,
+ &bufferSize
+ ));
+
+ /* Pointer to reserved address. */
+ address = Command->address + Command->offset;
+
+ /* Append EVENT(29). */
+ gcmkONERROR(gckHARDWARE_Event(
+ hardware,
+ pointer,
+ 29,
+ gcvKERNEL_PIXEL,
+ &eventBytes
+ ));
+
+ /* Append END. */
+ pointer += eventBytes;
+ address += eventBytes;
+
+ gcmkONERROR(gckHARDWARE_End(hardware, pointer, address, &endBytes));
+
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (hardware->kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ hardware->kernel,
+ pointer,
+ gcvFALSE,
+ Command->virtualMemory,
+ &hardware->lastEnd
+ ));
+ }
+#endif
+
+ gcmkONERROR(gckCOMMAND_Execute(Command, executeBytes));
+ }
+
+ return gcvSTATUS_OK;
+OnError:
+ return status;
+#endif
+}
+
+static gceSTATUS
+_DummyDraw(
+ IN gckCOMMAND Command
+ )
+{
+#if gcdSECURITY
+ return gcvSTATUS_OK;
+#else
+ gceSTATUS status;
+ gckHARDWARE hardware = Command->kernel->hardware;
+
+ gctUINT8_PTR pointer;
+ gctUINT32 bufferSize;
+
+ gctUINT32 dummyDrawBytes;
+ gceDUMMY_DRAW_TYPE dummyDrawType = gcvDUMMY_DRAW_INVALID;
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_FE_NEED_DUMMYDRAW))
+ {
+ dummyDrawType = gcvDUMMY_DRAW_GC400;
+ }
+
+ if (!gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_USC_DEFER_FILL_FIX) &&
+ gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_USC))
+ {
+ dummyDrawType = gcvDUMMY_DRAW_V60;
+ }
+
+ if (dummyDrawType != gcvDUMMY_DRAW_INVALID)
+ {
+ gckHARDWARE_DummyDraw(hardware, gcvNULL, Command->queues[0].address, dummyDrawType, &dummyDrawBytes);
+
+ /* Reserve space. */
+ gcmkONERROR(gckCOMMAND_Reserve(
+ Command,
+ dummyDrawBytes,
+ (gctPOINTER *)&pointer,
+ &bufferSize
+ ));
+
+ gckHARDWARE_DummyDraw(hardware, pointer, Command->queues[0].address, dummyDrawType, &dummyDrawBytes);
+
+ gcmkONERROR(gckCOMMAND_Execute(Command, dummyDrawBytes));
+ }
+
+ return gcvSTATUS_OK;
+OnError:
+ return status;
+#endif
+}
+
+#endif
+
+static void
+_DumpBuffer(
+ IN gctPOINTER Buffer,
+ IN gctUINT32 GpuAddress,
+ IN gctSIZE_T Size
+ )
+{
+ gctSIZE_T i, line, left;
+ gctUINT32_PTR data = Buffer;
+
+ line = Size / 32;
+ left = Size % 32;
+
+ for (i = 0; i < line; i++)
+ {
+ gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
+ data += 8;
+ GpuAddress += 8 * 4;
+ }
+
+ switch(left)
+ {
+ case 28:
+ gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
+ break;
+ case 24:
+ gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5]);
+ break;
+ case 20:
+ gcmkPRINT("%08X : %08X %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3], data[4]);
+ break;
+ case 16:
+ gcmkPRINT("%08X : %08X %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2], data[3]);
+ break;
+ case 12:
+ gcmkPRINT("%08X : %08X %08X %08X",
+ GpuAddress, data[0], data[1], data[2]);
+ break;
+ case 8:
+ gcmkPRINT("%08X : %08X %08X",
+ GpuAddress, data[0], data[1]);
+ break;
+ case 4:
+ gcmkPRINT("%08X : %08X",
+ GpuAddress, data[0]);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+_DumpKernelCommandBuffer(
+ IN gckCOMMAND Command
+ )
+{
+ gctINT i;
+ gctUINT64 physical = 0;
+ gctUINT32 address;
+ gctPOINTER entry = gcvNULL;
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+ {
+ entry = Command->queues[i].logical;
+
+ gckOS_GetPhysicalAddress(Command->os, entry, &physical);
+
+ gcmkPRINT("Kernel command buffer %d\n", i);
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ _DumpBuffer(entry, address, Command->pageSize);
+ }
+}
+
+#if !gcdNULL_DRIVER
+static gceSTATUS
+_HandlePatchList(
+ IN gckCOMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ IN gctBOOL NeedCopy,
+ OUT gctUINT64 *AsyncCommandStamp
+ )
+{
+ gceSTATUS status;
+ gcsPATCH_LIST * uList;
+ gcsPATCH_LIST * previous;
+ gcsPATCH_LIST * kList;
+ gctUINT64 asyncStamp = 0;
+
+ gcmkHEADER_ARG(
+ "Command=0x%x CommandBuffer=0x%x NeedCopy=%d",
+ Command, CommandBuffer, NeedCopy
+ );
+
+ uList = gcmUINT64_TO_PTR(CommandBuffer->patchHead);
+
+ while (uList)
+ {
+ gctUINT i;
+
+ kList = gcvNULL;
+ previous = uList;
+
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ Command->kernel,
+ NeedCopy,
+ Command->kList,
+ uList,
+ gcmSIZEOF(gcsPATCH_LIST),
+ (gctPOINTER *)&kList
+ ));
+
+ for (i = 0; i < kList->count; i++)
+ {
+ gctUINT64 stamp = 0;
+ gcsPATCH * patch = &kList->patch[i];
+
+ /* Touch video memory node. */
+ gcmkVERIFY_OK(gckVIDMEM_SetCommitStamp(Command->kernel, gcvENGINE_RENDER, patch->handle, Command->commitStamp));
+
+ /* Get stamp touched async command buffer. */
+ gcmkVERIFY_OK(gckVIDMEM_GetCommitStamp(Command->kernel, gcvENGINE_BLT, patch->handle, &stamp));
+
+ /* Find latest one. */
+ asyncStamp = gcmMAX(asyncStamp, stamp);
+ }
+
+ uList = kList->next;
+
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ Command->kernel,
+ NeedCopy,
+ gcvFALSE,
+ previous,
+ gcmSIZEOF(gcsPATCH_LIST),
+ (gctPOINTER *)&kList
+ ));
+ }
+
+ if ((Command->asyncCommand != gcvNULL)
+ && (*(gctUINT64 *)Command->asyncCommand->fence->logical > asyncStamp)
+ )
+ {
+ /* No need to wait for async command buffer. */
+ *AsyncCommandStamp = 0;
+ }
+ else
+ {
+ /* Need to add a fence wait. */
+ *AsyncCommandStamp = asyncStamp;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (kList)
+ {
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ Command->kernel,
+ NeedCopy,
+ gcvFALSE,
+ previous,
+ gcmSIZEOF(gcsPATCH_LIST),
+ (gctPOINTER *)&kList
+ ));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_WaitForAsyncCommandStamp(
+ IN gckCOMMAND Command,
+ IN gctUINT64 Stamp
+ )
+{
+ gctUINT32 bytes;
+ gceSTATUS status;
+ gctUINT32 fenceAddress;
+ gctUINT32 bufferSize;
+ gctPOINTER pointer;
+ gcmkHEADER_ARG("Stamp = 0x%llx", Stamp);
+
+ fenceAddress = Command->asyncCommand->fence->address;
+
+ gcmkONERROR(gckHARDWARE_WaitFence(Command->kernel->hardware,
+ gcvNULL,
+ Stamp,
+ fenceAddress,
+ &bytes
+ ));
+
+ gcmkONERROR(gckCOMMAND_Reserve(
+ Command,
+ bytes,
+ &pointer,
+ &bufferSize
+ ));
+
+ gcmkONERROR(gckHARDWARE_WaitFence(
+ Command->kernel->hardware,
+ pointer,
+ Stamp,
+ fenceAddress,
+ &bytes
+ ));
+
+ gcmkONERROR(gckCOMMAND_Execute(Command, bytes));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/******************************************************************************\
+**************** Helper functions for parsing gcoCMDBUF ************************
+\******************************************************************************/
+static void
+_GetCMDBUFSize(
+ IN gcoCMDBUF CommandBuffer,
+ OUT gctUINT_PTR CommandBufferSize
+ )
+{
+ *CommandBufferSize
+ = CommandBuffer->offset
+ + CommandBuffer->reservedTail
+ - CommandBuffer->startOffset;
+}
+
+static void
+_GetCMDBUFTail(
+ IN gcoCMDBUF CommandBuffer,
+ OUT gctUINT8_PTR * Tail
+ )
+{
+ gctUINT8_PTR commandBufferLogical;
+ gctUINT commandBufferSize;
+
+ commandBufferLogical
+ = (gctUINT8_PTR) gcmUINT64_TO_PTR(CommandBuffer->logical)
+ + CommandBuffer->startOffset;
+
+ _GetCMDBUFSize(CommandBuffer, &commandBufferSize);
+
+ *Tail
+ = commandBufferLogical
+ + commandBufferSize
+ - CommandBuffer->reservedTail;
+}
+
+static void
+_ParseCMDBUFTail(
+ IN gckHARDWARE Hardware,
+ IN gcoCMDBUF CommandBuffer,
+ OUT gctUINT8_PTR * Fence,
+ OUT gctUINT8_PTR * Link
+ )
+{
+ gctUINT8_PTR tail;
+
+ _GetCMDBUFTail(CommandBuffer, &tail);
+
+ if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_FENCE))
+ {
+ *Fence = tail;
+ *Link = tail + gcdRENDER_FENCE_LENGTH;
+ }
+ else
+ {
+ *Fence = gcvNULL;
+ *Link = tail;
+ }
+}
+
+static gceSTATUS
+_GetCMDBUFEntry(
+ IN gckCOMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ OUT gctUINT32_PTR EntryAddress,
+ OUT gctUINT32_PTR EntryBytes
+ )
+{
+ gceSTATUS status;
+ gctUINT8_PTR commandBufferLogical;
+ gctUINT commandBufferSize;
+ gckVIRTUAL_COMMAND_BUFFER_PTR virtualCommandBuffer;
+ gctUINT32 commandBufferAddress;
+ gctUINT offset;
+
+ commandBufferLogical
+ = (gctUINT8_PTR) gcmUINT64_TO_PTR(CommandBuffer->logical)
+ + CommandBuffer->startOffset;
+
+ /* Get the hardware address. */
+ if (Command->kernel->virtualCommandBuffer)
+ {
+ gckKERNEL kernel = Command->kernel;
+
+ virtualCommandBuffer = gcmNAME_TO_PTR(CommandBuffer->physical);
+
+ if (virtualCommandBuffer == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Command->kernel,
+ commandBufferLogical,
+ gcvTRUE,
+ virtualCommandBuffer,
+ &commandBufferAddress
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ gcvTRUE,
+ &commandBufferAddress
+ ));
+ }
+
+ /* Get offset. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware, gcvNULL, gcvPIPE_3D, &offset
+ ));
+
+ _GetCMDBUFSize(CommandBuffer, &commandBufferSize);
+
+ *EntryAddress = commandBufferAddress + offset;
+ *EntryBytes = commandBufferSize - offset;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+/*******************************************************************************
+**
+** Link a list of command buffer together to make them atomic.
+** Fence will be added in the last command buffer.
+*/
+static gceSTATUS
+_ProcessUserCommandBufferList(
+ IN gckCOMMAND Command,
+ IN gcoCMDBUF CommandBufferListHead,
+ OUT gcoCMDBUF * CommandBufferListTail
+ )
+{
+ gceSTATUS status;
+ gctBOOL needCopy;
+
+ struct _gcoCMDBUF _commandBufferObject;
+ gcoCMDBUF currentCMDBUF;
+ struct _gcoCMDBUF _nextCMDBUF;
+ gcoCMDBUF currentCMDBUFUser = CommandBufferListHead;
+
+ gckOS_QueryNeedCopy(Command->os, 0, &needCopy);
+
+ /* Open first gcoCMDBUF object as currentCMDBUF. */
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ Command->kernel,
+ needCopy,
+ &_commandBufferObject,
+ currentCMDBUFUser,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *)&currentCMDBUF
+ ));
+
+ /* Iterate the list. */
+ while (currentCMDBUF->nextCMDBUF != 0)
+ {
+ gcoCMDBUF nextCMDBUFUser;
+ gcoCMDBUF nextCMDBUF;
+ gctUINT8_PTR fenceLogical = gcvNULL;
+ gctUINT8_PTR linkLogical;
+ gctUINT32 linkBytes = 8;
+ gctUINT32 linkLow;
+ gctUINT32 linkHigh;
+
+ gctUINT32 entryAddress = 0;
+ gctUINT32 entryBytes = 0;
+
+ nextCMDBUFUser
+ = gcmUINT64_TO_PTR(currentCMDBUF->nextCMDBUF);
+
+ /* Open next gcoCMDBUF object as nextCMDBUF. */
+ gcmkONERROR(gckKERNEL_OpenUserData(
+ Command->kernel,
+ needCopy,
+ &_nextCMDBUF,
+ nextCMDBUFUser,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *)&nextCMDBUF
+ ));
+
+ /* Get the start hardware address of nextCMDBUF. */
+ gcmkONERROR(_GetCMDBUFEntry(Command,
+ nextCMDBUF,
+ &entryAddress,
+ &entryBytes
+ ));
+
+ /* Process current gcoCMDBUF object. */
+ _ParseCMDBUFTail(
+ Command->kernel->hardware,
+ currentCMDBUF,
+ &fenceLogical,
+ &linkLogical
+ );
+
+ /* Don't send fence in the middle of gcoCMDBUF list. */
+ if (fenceLogical != gcvNULL)
+ {
+ gctUINT i = gcdRENDER_FENCE_LENGTH / gcmSIZEOF(gctUINT32) / 2;
+
+ /* Fill NOPs in space reserved for fence. */
+ while (i--)
+ {
+ gctSIZE_T nopBytes = 8;
+ gcmkONERROR(gckHARDWARE_Nop(Command->kernel->hardware, fenceLogical, &nopBytes));
+ fenceLogical += nopBytes;
+ }
+ }
+
+ /* Generate a LINK from the end of current command buffer
+ ** to the start of next command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ Command->kernel->hardware,
+ linkLogical,
+ entryAddress,
+ entryBytes,
+ &linkBytes,
+ &linkLow,
+ &linkHigh
+ ));
+
+ /* Close current gcoCMDBUF object which is processed. */
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ Command->kernel,
+ needCopy,
+ gcvFALSE,
+ currentCMDBUFUser,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *)&currentCMDBUF
+ ));
+
+ /* Advance to next gcoCMDBUF object. */
+ currentCMDBUFUser = nextCMDBUFUser;
+ currentCMDBUF = nextCMDBUF;
+ }
+
+ gcmkVERIFY_OK(gckKERNEL_CloseUserData(
+ Command->kernel,
+ needCopy,
+ gcvFALSE,
+ currentCMDBUFUser,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *)&currentCMDBUF
+ ));
+
+ /* Return the tail of the list. */
+ *CommandBufferListTail = currentCMDBUFUser;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+#endif
+
+/******************************************************************************\
+****************************** gckCOMMAND API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckCOMMAND_Construct
+**
+** Construct a new gckCOMMAND object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gckCOMMAND * Command
+** Pointer to a variable that will hold the pointer to the gckCOMMAND
+** object.
+*/
+gceSTATUS
+gckCOMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckCOMMAND * Command
+ )
+{
+ gckOS os;
+ gckCOMMAND command = gcvNULL;
+ gceSTATUS status;
+ gctINT i;
+ gctPOINTER pointer = gcvNULL;
+ gctSIZE_T pageSize;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Command != gcvNULL);
+
+ /* Extract the gckOS object. */
+ os = Kernel->os;
+
+ /* Allocate the gckCOMMAND structure. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckCOMMAND), &pointer));
+ command = pointer;
+
+ /* Reset the entire object. */
+ gcmkONERROR(gckOS_ZeroMemory(command, gcmSIZEOF(struct _gckCOMMAND)));
+
+ /* Initialize the gckCOMMAND object.*/
+ command->object.type = gcvOBJ_COMMAND;
+ command->kernel = Kernel;
+ command->os = os;
+
+ /* Get the command buffer requirements. */
+ gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
+ Kernel->hardware,
+ gcvENGINE_RENDER,
+ &command->alignment,
+ &command->reservedHead,
+ gcvNULL
+ ));
+
+ /* Create the command queue mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &command->mutexQueue));
+
+ /* Create the context switching mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContext));
+
+#if VIVANTE_PROFILER_CONTEXT
+ /* Create the context switching mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContextSeq));
+#endif
+
+ /* Create the power management semaphore. */
+ gcmkONERROR(gckOS_CreateSemaphore(os, &command->powerSemaphore));
+
+ /* Create the commit atom. */
+ gcmkONERROR(gckOS_AtomConstruct(os, &command->atomCommit));
+
+ /* Get the page size from teh OS. */
+ gcmkONERROR(gckOS_GetPageSize(os, &pageSize));
+
+ gcmkSAFECASTSIZET(command->pageSize, pageSize);
+
+ /* Get process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&command->kernelProcessID));
+
+ /* Set hardware to pipe 0. */
+ command->pipeSelect = gcvPIPE_INVALID;
+
+ /* Pre-allocate the command queues. */
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (Kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_AllocateVirtualCommandBuffer(
+ Kernel,
+ gcvFALSE,
+ &pageSize,
+ &command->queues[i].physical,
+ &command->queues[i].logical
+ ));
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Kernel,
+ command->queues[i].logical,
+ gcvFALSE,
+ command->queues[i].physical,
+ &command->queues[i].address
+ ));
+ }
+ else
+#endif
+ {
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ os,
+ gcvFALSE,
+ &pageSize,
+ &command->queues[i].physical,
+ &command->queues[i].logical
+ ));
+
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ Kernel->hardware,
+ command->queues[i].logical,
+ gcvFALSE,
+ &command->queues[i].address
+ ));
+
+ gcmkONERROR(gckMMU_FillFlatMapping(
+ Kernel->mmu, command->queues[i].address, pageSize
+ ));
+ }
+
+ gcmkONERROR(gckOS_CreateSignal(
+ os, gcvFALSE, &command->queues[i].signal
+ ));
+
+ gcmkONERROR(gckOS_Signal(
+ os, command->queues[i].signal, gcvTRUE
+ ));
+ }
+
+#if gcdRECORD_COMMAND
+ gcmkONERROR(gckRECORDER_Construct(os, Kernel->hardware, &command->recorder));
+#endif
+
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsPATCH_LIST), &command->kList));
+
+ gcmkONERROR(gckFENCE_Create(
+ os, Kernel, &command->fence
+ ));
+
+ /* No command queue in use yet. */
+ command->index = -1;
+ command->logical = gcvNULL;
+ command->newQueue = gcvFALSE;
+
+ /* Command is not yet running. */
+ command->running = gcvFALSE;
+
+ /* Command queue is idle. */
+ command->idle = gcvTRUE;
+
+ /* Commit stamp start from 1. */
+ command->commitStamp = 1;
+
+ /* END event signal not created. */
+ command->endEventSignal = gcvNULL;
+
+ command->dummyDraw = gcvTRUE;
+
+ /* Return pointer to the gckCOMMAND object. */
+ *Command = command;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Command=0x%x", *Command);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (command != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(command));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Destroy
+**
+** Destroy an gckCOMMAND object.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Destroy(
+ IN gckCOMMAND Command
+ )
+{
+ gctINT i;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Stop the command queue. */
+ gcmkVERIFY_OK(gckCOMMAND_Stop(Command));
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ if (Command->queues[i].signal)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(
+ Command->os, Command->queues[i].signal
+ ));
+ }
+
+ if (Command->queues[i].logical)
+ {
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (Command->kernel->virtualCommandBuffer)
+ {
+ gcmkVERIFY_OK(gckKERNEL_DestroyVirtualCommandBuffer(
+ Command->kernel,
+ Command->pageSize,
+ Command->queues[i].physical,
+ Command->queues[i].logical
+ ));
+ }
+ else
+#endif
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
+ Command->os,
+ Command->pageSize,
+ Command->queues[i].physical,
+ Command->queues[i].logical
+ ));
+ }
+ }
+ }
+
+ /* END event signal. */
+ if (Command->endEventSignal != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(
+ Command->os, Command->endEventSignal
+ ));
+ }
+
+ if (Command->mutexContext)
+ {
+ /* Delete the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContext));
+ }
+
+#if VIVANTE_PROFILER_CONTEXT
+ if (Command->mutexContextSeq != gcvNULL)
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContextSeq));
+#endif
+
+ if (Command->mutexQueue)
+ {
+ /* Delete the command queue mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexQueue));
+ }
+
+ if (Command->powerSemaphore)
+ {
+ /* Destroy the power management semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(Command->os, Command->powerSemaphore));
+ }
+
+ if (Command->atomCommit)
+ {
+ /* Destroy the commit atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Command->os, Command->atomCommit));
+ }
+
+#if gcdSECURE_USER
+ /* Free state array. */
+ if (Command->hintArrayAllocated)
+ {
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, gcmUINT64_TO_PTR(Command->hintArray)));
+ Command->hintArrayAllocated = gcvFALSE;
+ }
+#endif
+
+#if gcdRECORD_COMMAND
+ gckRECORDER_Destory(Command->os, Command->recorder);
+#endif
+
+ if (Command->stateMap)
+ {
+ gcmkOS_SAFE_FREE(Command->os, Command->stateMap);
+ }
+
+ if (Command->kList)
+ {
+ gcmkOS_SAFE_FREE(Command->os, Command->kList);
+ }
+
+ if (Command->fence)
+ {
+ gcmkVERIFY_OK(gckFENCE_Destory(Command->os, Command->fence));
+ }
+
+ /* Mark object as unknown. */
+ Command->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckCOMMAND object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, Command));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_EnterCommit
+**
+** Acquire command queue synchronization objects.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to destroy.
+**
+** gctBOOL FromPower
+** Determines whether the call originates from inside the power
+** management or not.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_EnterCommit(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware;
+ gctBOOL atomIncremented = gcvFALSE;
+ gctBOOL semaAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Extract the gckHARDWARE and gckEVENT objects. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ if (!FromPower)
+ {
+ /* Increment COMMIT atom to let power management know that a commit is
+ ** in progress. */
+ gcmkONERROR(_IncrementCommitAtom(Command, gcvTRUE));
+ atomIncremented = gcvTRUE;
+
+ /* Notify the system the GPU has a commit. */
+ gcmkONERROR(gckOS_Broadcast(Command->os,
+ hardware,
+ gcvBROADCAST_GPU_COMMIT));
+
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(Command->os,
+ Command->powerSemaphore));
+ semaAcquired = gcvTRUE;
+ }
+
+ /* Grab the conmmand queue mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Command->os,
+ Command->mutexQueue,
+ gcvINFINITE));
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (semaAcquired)
+ {
+ /* Release the power management semaphore. */
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
+ Command->os, Command->powerSemaphore
+ ));
+ }
+
+ if (atomIncremented)
+ {
+ /* Decrement the commit atom. */
+ gcmkVERIFY_OK(_IncrementCommitAtom(
+ Command, gcvFALSE
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_ExitCommit
+**
+** Release command queue synchronization objects.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to destroy.
+**
+** gctBOOL FromPower
+** Determines whether the call originates from inside the power
+** management or not.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_ExitCommit(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+ if (!FromPower)
+ {
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(Command->os,
+ Command->powerSemaphore));
+
+ /* Decrement the commit atom. */
+ gcmkONERROR(_IncrementCommitAtom(Command, gcvFALSE));
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Start
+**
+** Start up the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to start.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Start(
+ IN gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware;
+ gctUINT32 waitOffset = 0;
+ gctUINT32 waitLinkBytes;
+ gctPOINTER logical;
+ gctUINT32 physical;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->running)
+ {
+ /* Command queue already running. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Extract the gckHARDWARE object. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Query the size of WAIT/LINK command sequence. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ hardware,
+ gcvNULL,
+ ~0U,
+ Command->offset,
+ &waitLinkBytes,
+ gcvNULL,
+ gcvNULL
+ ));
+
+ if ((Command->pageSize - Command->offset < waitLinkBytes)
+ || (Command->logical == gcvNULL)
+ )
+ {
+ /* Start at beginning of a new queue. */
+ gcmkONERROR(_NewQueue(Command));
+ }
+
+ logical = (gctUINT8_PTR) Command->logical + Command->offset;
+ physical = Command->physical + Command->offset;
+ address = Command->address + Command->offset;
+
+ /* Append WAIT/LINK. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ hardware,
+ logical,
+ address,
+ 0,
+ &waitLinkBytes,
+ &waitOffset,
+ &Command->waitSize
+ ));
+
+ Command->waitLogical = (gctUINT8_PTR) logical + waitOffset;
+ Command->waitPhysical = physical + waitOffset;
+ Command->waitAddress = address + waitOffset;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the wait/link. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ physical,
+ logical,
+ waitLinkBytes
+ ));
+#endif
+
+ /* Adjust offset. */
+ Command->offset += waitLinkBytes;
+ Command->newQueue = gcvFALSE;
+
+#if gcdSECURITY
+ /* Start FE by calling security service. */
+ gckKERNEL_SecurityStartCommand(
+ Command->kernel
+ );
+#else
+ /* Enable command processor. */
+ gcmkONERROR(gckHARDWARE_Execute(
+ hardware,
+ address,
+ waitLinkBytes
+ ));
+#endif
+
+ /* Command queue is running. */
+ Command->running = gcvTRUE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Stop
+**
+** Stop the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to stop.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stop(
+ IN gckCOMMAND Command
+ )
+{
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gctUINT32 idle;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (!Command->running)
+ {
+ /* Command queue is not running. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Extract the gckHARDWARE object. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware,
+ gcvFEATURE_END_EVENT) == gcvSTATUS_TRUE)
+ {
+ /* Allocate the signal. */
+ if (Command->endEventSignal == gcvNULL)
+ {
+ gcmkONERROR(gckOS_CreateSignal(Command->os,
+ gcvTRUE,
+ &Command->endEventSignal));
+ }
+
+ /* Append the END EVENT command to trigger the signal. */
+ gcmkONERROR(gckEVENT_Stop(Command->kernel->eventObj,
+ Command->kernelProcessID,
+ Command->waitPhysical,
+ Command->waitLogical,
+ Command->waitAddress,
+ Command->endEventSignal,
+ &Command->waitSize));
+ }
+ else
+ {
+ /* Replace last WAIT with END. */
+ gcmkONERROR(gckHARDWARE_End(
+ hardware,
+ Command->waitLogical,
+ Command->waitAddress,
+ &Command->waitSize
+ ));
+
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (hardware->kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ hardware->kernel,
+ Command->waitLogical,
+ gcvFALSE,
+ Command->virtualMemory,
+ &hardware->lastEnd
+ ));
+ }
+#endif
+
+#if gcdSECURITY
+ gcmkONERROR(gckKERNEL_SecurityExecute(
+ Command->kernel, Command->waitLogical, 8
+ ));
+#endif
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
+ Command->logical,
+ Command->offset));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the END. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)Command->waitPhysical,
+ Command->waitLogical,
+ Command->waitSize
+ ));
+#endif
+
+ /* Wait for idle. */
+ gcmkONERROR(gckHARDWARE_GetIdle(hardware, gcvTRUE, &idle));
+ }
+
+ /* Command queue is no longer running. */
+ Command->running = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Commit
+**
+** Commit a command buffer to the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to a gckCOMMAND object.
+**
+** gckCONTEXT Context
+** Pointer to a gckCONTEXT object.
+**
+** gcoCMDBUF CommandBuffer
+** Pointer to a gcoCMDBUF object.
+**
+** gcsSTATE_DELTA_PTR StateDelta
+** Pointer to the state delta.
+**
+** gctUINT32 ProcessID
+** Current process ID.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Commit(
+ IN gckCOMMAND Command,
+ IN gckCONTEXT Context,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcsSTATE_DELTA_PTR StateDelta,
+ IN gcsQUEUE_PTR EventQueue,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL Shared,
+ IN gctUINT32 Index,
+ OUT gctUINT64_PTR CommitStamp,
+ OUT gctBOOL_PTR ContextSwitched
+ )
+{
+ gceSTATUS status;
+ gctBOOL commitEntered = gcvFALSE;
+ gctBOOL contextAcquired = gcvFALSE;
+ gckHARDWARE hardware;
+ gctBOOL needCopy = gcvFALSE;
+ gcsQUEUE_PTR eventRecord = gcvNULL;
+ gcsQUEUE _eventRecord;
+ gcsQUEUE_PTR nextEventRecord;
+ gctBOOL commandBufferMapped = gcvFALSE;
+ gcoCMDBUF commandBufferObject = gcvNULL;
+ gctBOOL stall = gcvFALSE;
+ gctBOOL contextSwitched = gcvFALSE;
+
+#if !gcdNULL_DRIVER
+ gcsCONTEXT_PTR contextBuffer;
+ struct _gcoCMDBUF _commandBufferObject;
+ gctPHYS_ADDR_T commandBufferPhysical;
+ gctUINT8_PTR commandBufferLogical = gcvNULL;
+ gctUINT32 commandBufferAddress = 0;
+ gctUINT8_PTR commandBufferLink = gcvNULL;
+ gctUINT8_PTR commandBufferTail = gcvNULL;
+ gctUINT8_PTR commandBufferFence = gcvNULL;
+ gctUINT commandBufferSize;
+ gctSIZE_T nopBytes;
+ gctUINT32 pipeBytes;
+ gctUINT32 linkBytes;
+ gctSIZE_T bytes;
+ gctUINT32 offset;
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ gctPHYS_ADDR entryPhysical;
+#endif
+ gctPOINTER entryLogical;
+ gctUINT32 entryAddress;
+ gctUINT32 entryBytes;
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ gctPHYS_ADDR exitPhysical;
+ gctPOINTER exitLogical;
+#endif
+ gctUINT32 exitAddress;
+ gctUINT32 exitBytes;
+ gctUINT32 waitLinkPhysical;
+ gctPOINTER waitLinkLogical;
+ gctUINT32 waitLinkAddress;
+ gctUINT32 waitLinkBytes;
+ gctUINT32 waitPhysical;
+ gctPOINTER waitLogical;
+ gctUINT32 waitAddress;
+ gctUINT32 waitOffset;
+ gctUINT32 waitSize;
+
+#ifdef __QNXNTO__
+ gctPOINTER userCommandBufferLogical = gcvNULL;
+ gctBOOL userCommandBufferLogicalMapped = gcvFALSE;
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gckMMU mmu;
+ gctUINT32 oldValue;
+#endif
+
+#if gcdDUMP_COMMAND
+ gctPOINTER contextDumpLogical = gcvNULL;
+ gctSIZE_T contextDumpBytes = 0;
+ gctPOINTER bufferDumpLogical = gcvNULL;
+ gctSIZE_T bufferDumpBytes = 0;
+# endif
+ gctUINT32 exitLinkLow = 0, exitLinkHigh = 0;
+ gctUINT32 entryLinkLow = 0, entryLinkHigh = 0;
+ gctUINT32 commandLinkLow = 0, commandLinkHigh = 0;
+
+ gckVIRTUAL_COMMAND_BUFFER_PTR virtualCommandBuffer = gcvNULL;
+ gctUINT64 asyncCommandStamp = 0;
+ gcoCMDBUF lastCommandBuffer = gcvNULL;
+#endif
+
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG(
+ "Command=0x%x CommandBuffer=0x%x ProcessID=%d",
+ Command, CommandBuffer, ProcessID
+ );
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+#if !gcdNULL_DRIVER
+ gcmkONERROR(_ProcessUserCommandBufferList(
+ Command,
+ CommandBuffer,
+ &lastCommandBuffer
+ ));
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckKERNEL_GetProcessMMU(Command->kernel, &mmu));
+
+ gcmkONERROR(gckOS_AtomicExchange(Command->os,
+ mmu->pageTableDirty[Command->kernel->core],
+ 0,
+ &oldValue));
+#else
+#endif
+
+ /* Acquire the command queue. */
+ gcmkONERROR(gckCOMMAND_EnterCommit(Command, gcvFALSE));
+ commitEntered = gcvTRUE;
+
+ /* Acquire the context switching mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, Command->mutexContext, gcvINFINITE
+ ));
+ contextAcquired = gcvTRUE;
+
+ /* Extract the gckHARDWARE and gckEVENT objects. */
+ hardware = Command->kernel->hardware;
+
+ /* Check wehther we need to copy the structures or not. */
+ gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
+
+#if gcdNULL_DRIVER
+ /* Context switch required? */
+ if ((Context != gcvNULL) && (Command->currContext != Context))
+ {
+ /* Yes, merge in the deltas. */
+ gckCONTEXT_Update(Context, ProcessID, StateDelta);
+
+ /* Update the current context. */
+ Command->currContext = Context;
+
+ contextSwitched = gcvTRUE;
+ }
+#else
+ if (needCopy)
+ {
+ commandBufferObject = &_commandBufferObject;
+
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Command->os,
+ commandBufferObject,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF)
+ ));
+
+ gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
+ }
+ else
+ {
+ gcmkONERROR(gckOS_MapUserPointer(
+ Command->os,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ &pointer
+ ));
+
+ commandBufferObject = pointer;
+
+ gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
+ commandBufferMapped = gcvTRUE;
+ }
+
+ gcmkONERROR(_HandlePatchList(Command, commandBufferObject, needCopy, &asyncCommandStamp));
+
+ /* Query the size of NOP command. */
+ gcmkONERROR(gckHARDWARE_Nop(
+ hardware, gcvNULL, &nopBytes
+ ));
+
+ /* Query the size of pipe select command sequence. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ hardware, gcvNULL, gcvPIPE_3D, &pipeBytes
+ ));
+
+ /* Query the size of LINK command. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware, gcvNULL, 0, 0, &linkBytes, gcvNULL, gcvNULL
+ ));
+
+ /* Compute the command buffer entry and the size. */
+ commandBufferLogical
+ = (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
+ + commandBufferObject->startOffset;
+
+ /* Get the hardware address. */
+ if (Command->kernel->virtualCommandBuffer)
+ {
+ gckKERNEL kernel = Command->kernel;
+
+ virtualCommandBuffer = gcmNAME_TO_PTR(commandBufferObject->physical);
+
+ if (virtualCommandBuffer == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Command->kernel,
+ commandBufferLogical,
+ gcvTRUE,
+ virtualCommandBuffer,
+ &commandBufferAddress
+ ));
+ }
+ else
+ {
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ hardware,
+ commandBufferLogical,
+ gcvTRUE,
+ &commandBufferAddress
+ ));
+ }
+
+#ifdef __QNXNTO__
+ userCommandBufferLogical = (gctPOINTER) commandBufferLogical;
+
+ gcmkONERROR(gckOS_MapUserPointer(
+ Command->os,
+ userCommandBufferLogical,
+ 0,
+ &pointer));
+
+ commandBufferLogical = pointer;
+
+ userCommandBufferLogicalMapped = gcvTRUE;
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ Command->os,
+ commandBufferLogical,
+ &commandBufferPhysical
+ ));
+#else
+ /* Get the physical address. */
+ gcmkONERROR(gckOS_UserLogicalToPhysical(
+ Command->os,
+ commandBufferLogical,
+ &commandBufferPhysical
+ ));
+#endif
+
+ commandBufferSize
+ = commandBufferObject->offset
+ + commandBufferObject->reservedTail
+ - commandBufferObject->startOffset;
+
+ gcmkONERROR(_FlushMMU(Command));
+
+ if (Command->dummyDraw == gcvTRUE &&
+ Context != gcvNULL)
+ {
+ Command->dummyDraw = gcvFALSE;
+ gcmkONERROR(_DummyDraw(Command));
+ }
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_FENCE) && asyncCommandStamp != 0)
+ {
+ gcmkONERROR(_WaitForAsyncCommandStamp(Command, asyncCommandStamp));
+ }
+
+ /* Get the current offset. */
+ offset = Command->offset;
+
+ /* Compute number of bytes left in current kernel command queue. */
+ bytes = Command->pageSize - offset;
+
+ /* Query the size of WAIT/LINK command sequence. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ hardware,
+ gcvNULL,
+ ~0U,
+ offset,
+ &waitLinkBytes,
+ gcvNULL,
+ gcvNULL
+ ));
+
+ /* Is there enough space in the current command queue? */
+ if (bytes < waitLinkBytes)
+ {
+ /* No, create a new one. */
+ gcmkONERROR(_NewQueue(Command));
+
+ /* Get the new current offset. */
+ offset = Command->offset;
+
+ /* Recompute the number of bytes in the new kernel command queue. */
+ bytes = Command->pageSize - offset;
+ gcmkASSERT(bytes >= waitLinkBytes);
+ }
+
+ /* Compute the location if WAIT/LINK command sequence. */
+ waitLinkPhysical = Command->physical + offset;
+ waitLinkLogical = (gctUINT8_PTR) Command->logical + offset;
+ waitLinkAddress = Command->address + offset;
+
+ /* Context switch required? */
+ if (Context == gcvNULL)
+ {
+ /* See if we have to switch pipes for the command buffer. */
+ if (commandBufferObject->entryPipe == Command->pipeSelect)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the entry command buffer pipes
+ ** are different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Compute the entry. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
+#endif
+ entryLogical = commandBufferLogical + offset;
+ entryAddress = commandBufferAddress + offset;
+ entryBytes = commandBufferSize - offset;
+
+ Command->currContext = gcvNULL;
+ }
+#if gcdDEBUG_OPTION && gcdDEBUG_FORCE_CONTEXT_UPDATE
+ else if (1)
+#else
+ else if (Command->currContext != Context)
+#endif
+ {
+ /* Get the current context buffer. */
+ contextBuffer = Context->buffer;
+
+ /* Yes, merge in the deltas. */
+ gcmkONERROR(gckCONTEXT_Update(Context, ProcessID, StateDelta));
+
+ contextSwitched = gcvTRUE;
+
+ /***************************************************************
+ ** SWITCHING CONTEXT.
+ */
+
+ /* Determine context buffer entry offset. */
+ offset = (Command->pipeSelect == gcvPIPE_3D)
+
+ /* Skip pipe switching sequence. */
+ ? Context->entryOffset3D + Context->pipeSelectBytes
+
+ /* Do not skip pipe switching sequence. */
+ : Context->entryOffset3D;
+
+ /* Compute the entry. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
+#endif
+ entryLogical = (gctUINT8_PTR) contextBuffer->logical + offset;
+ entryAddress = contextBuffer->address + offset;
+ entryBytes = Context->bufferSize - offset;
+
+ /* See if we have to switch pipes between the context
+ and command buffers. */
+ if (commandBufferObject->entryPipe == gcvPIPE_3D)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the initial context pipes are
+ different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Generate a LINK from the context buffer to
+ the command buffer. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ contextBuffer->link3D,
+ commandBufferAddress + offset,
+ commandBufferSize - offset,
+ &linkBytes,
+ &commandLinkLow,
+ &commandLinkHigh
+ ));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the context buffer cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)entryPhysical,
+ entryLogical,
+ entryBytes
+ ));
+#endif
+
+ /* Update the current context. */
+ Command->currContext = Context;
+
+#if gcdDUMP_COMMAND
+ contextDumpLogical = entryLogical;
+ contextDumpBytes = entryBytes;
+#endif
+
+#if gcdSECURITY
+ /* Commit context buffer to trust zone. */
+ gckKERNEL_SecurityExecute(
+ Command->kernel,
+ entryLogical,
+ entryBytes - 8
+ );
+#endif
+
+#if gcdRECORD_COMMAND
+ gckRECORDER_Record(
+ Command->recorder,
+ gcvNULL,
+ 0xFFFFFFFF,
+ entryLogical,
+ entryBytes
+ );
+#endif
+ }
+
+ /* Same context. */
+ else
+ {
+ /* See if we have to switch pipes for the command buffer. */
+ if (commandBufferObject->entryPipe == Command->pipeSelect)
+ {
+ /* Skip pipe switching sequence. */
+ offset = pipeBytes;
+ }
+ else
+ {
+ /* The current hardware and the entry command buffer pipes
+ ** are different, switch to the correct pipe. */
+ gcmkONERROR(gckHARDWARE_PipeSelect(
+ Command->kernel->hardware,
+ commandBufferLogical,
+ commandBufferObject->entryPipe,
+ &pipeBytes
+ ));
+
+ /* Do not skip pipe switching sequence. */
+ offset = 0;
+ }
+
+ /* Compute the entry. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
+#endif
+ entryLogical = commandBufferLogical + offset;
+ entryAddress = commandBufferAddress + offset;
+ entryBytes = commandBufferSize - offset;
+ }
+
+#if gcdDUMP_COMMAND
+ bufferDumpLogical = commandBufferLogical + offset;
+ bufferDumpBytes = commandBufferSize - offset;
+#endif
+
+#if gcdSECURE_USER
+ /* Process user hints. */
+ gcmkONERROR(_ProcessHints(Command, ProcessID, commandBufferObject));
+#endif
+
+ /* Determine the location to jump to for the command buffer being
+ ** scheduled. */
+ if (Command->newQueue)
+ {
+ /* New command queue, jump to the beginning of it. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ exitPhysical = Command->physical;
+ exitLogical = Command->logical;
+#endif
+ exitAddress = Command->address;
+ exitBytes = Command->offset + waitLinkBytes;
+ }
+ else
+ {
+ /* Still within the preexisting command queue, jump to the new
+ WAIT/LINK command sequence. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ exitPhysical = waitLinkPhysical;
+ exitLogical = waitLinkLogical;
+#endif
+ exitAddress = waitLinkAddress;
+ exitBytes = waitLinkBytes;
+ }
+
+ /* Add a new WAIT/LINK command sequence. When the command buffer which is
+ currently being scheduled is fully executed by the GPU, the FE will
+ jump to this WAIT/LINK sequence. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ hardware,
+ waitLinkLogical,
+ waitLinkAddress,
+ offset,
+ &waitLinkBytes,
+ &waitOffset,
+ &waitSize
+ ));
+
+ /* Compute the location if WAIT command. */
+ waitPhysical = waitLinkPhysical + waitOffset;
+ waitLogical = (gctUINT8_PTR) waitLinkLogical + waitOffset;
+ waitAddress = waitLinkAddress + waitOffset;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the command queue cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)exitPhysical,
+ exitLogical,
+ exitBytes
+ ));
+#endif
+
+ /* Determine the location of the TAIL in the command buffer. */
+ commandBufferTail
+ = commandBufferLogical
+ + commandBufferSize
+ - commandBufferObject->reservedTail;
+
+ if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_FENCE))
+ {
+ /* Determine the location of the FENCE command in the command buffer. */
+ commandBufferFence = commandBufferTail;
+
+ /* Determine the location of the LINK command in the command buffer. */
+ commandBufferLink = commandBufferTail + gcdRENDER_FENCE_LENGTH;
+ }
+ else
+ {
+ /* Determine the location of the LINK command in the command buffer. */
+ commandBufferLink = commandBufferTail;
+ }
+
+ /* Generate command which writes out commit stamp. */
+ if (commandBufferFence)
+ {
+ gctUINT32 bytes;
+
+ gcmkONERROR(gckHARDWARE_Fence(
+ hardware,
+ gcvENGINE_RENDER,
+ commandBufferFence,
+ Command->fence->address,
+ Command->commitStamp,
+ &bytes
+ ));
+ }
+
+ /* Generate a LINK from the end of the command buffer being scheduled
+ back to the kernel command queue. */
+#if !gcdSECURITY
+ if (Shared == gcvFALSE)
+ {
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ commandBufferLink,
+ exitAddress,
+ exitBytes,
+ &linkBytes,
+ &exitLinkLow,
+ &exitLinkHigh
+ ));
+ }
+ else
+ {
+ gctUINT8_PTR link = commandBufferLink + Index * 16;
+ gctSIZE_T bytes = 8;
+
+ gcmkONERROR(gckHARDWARE_ChipEnable(
+ hardware,
+ link,
+ (gceCORE_3D_MASK)(1 << hardware->kernel->chipID),
+ &bytes
+ ));
+
+ link += bytes;
+
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ link,
+ exitAddress,
+ exitBytes,
+ &linkBytes,
+ &exitLinkLow,
+ &exitLinkHigh
+ ));
+
+ link += linkBytes;
+ }
+#endif
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the command buffer cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ ProcessID,
+ gcvNULL,
+ (gctUINT32)commandBufferPhysical,
+ commandBufferLogical,
+ commandBufferSize
+ ));
+#endif
+
+#if gcdRECORD_COMMAND
+ gckRECORDER_Record(
+ Command->recorder,
+ commandBufferLogical + offset,
+ commandBufferSize - offset,
+ gcvNULL,
+ 0xFFFFFFFF
+ );
+
+ gckRECORDER_AdvanceIndex(Command->recorder, Command->commitStamp);
+#endif
+
+#if gcdSECURITY
+ /* Submit command buffer to trust zone. */
+ gckKERNEL_SecurityExecute(
+ Command->kernel,
+ commandBufferLogical + offset,
+ commandBufferSize - offset - 8
+ );
+#else
+ /* Generate a LINK from the previous WAIT/LINK command sequence to the
+ entry determined above (either the context or the command buffer).
+ This LINK replaces the WAIT instruction from the previous WAIT/LINK
+ pair, therefore we use WAIT metrics for generation of this LINK.
+ This action will execute the entire sequence. */
+ gcmkONERROR(gckHARDWARE_Link(
+ hardware,
+ Command->waitLogical,
+ entryAddress,
+ entryBytes,
+ &Command->waitSize,
+ &entryLinkLow,
+ &entryLinkHigh
+ ));
+#endif
+
+#if gcdLINK_QUEUE_SIZE
+ if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_USER_COMMAND)
+ {
+ gcuQUEUEDATA data;
+
+ gcmkVERIFY_OK(gckOS_GetProcessID(&data.linkData.pid));
+
+ data.linkData.start = entryAddress;
+ data.linkData.end = entryAddress + entryBytes;
+ data.linkData.linkLow = entryLinkLow;
+ data.linkData.linkHigh = entryLinkHigh;
+
+ gckQUEUE_Enqueue(&hardware->linkQueue, &data);
+
+ if (commandBufferAddress + offset != entryAddress)
+ {
+ data.linkData.start = commandBufferAddress + offset;
+ data.linkData.end = commandBufferAddress + commandBufferSize;
+ data.linkData.linkLow = commandLinkLow;
+ data.linkData.linkHigh = commandLinkHigh;
+
+ gckQUEUE_Enqueue(&hardware->linkQueue, &data);
+ }
+
+ if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_ALL_COMMAND)
+ {
+ data.linkData.start = exitAddress;
+ data.linkData.end = exitAddress + exitBytes;
+ data.linkData.linkLow = exitLinkLow;
+ data.linkData.linkHigh = exitLinkHigh;
+
+ /* Dump kernel command.*/
+ gckQUEUE_Enqueue(&hardware->linkQueue, &data);
+ }
+ }
+#endif
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the link. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)Command->waitPhysical,
+ Command->waitLogical,
+ Command->waitSize
+ ));
+#endif
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ Command->waitLogical,
+ Command->waitSize,
+ gceDUMP_BUFFER_LINK,
+ gcvFALSE
+ );
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ contextDumpLogical,
+ contextDumpBytes,
+ gceDUMP_BUFFER_CONTEXT,
+ gcvFALSE
+ );
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ bufferDumpLogical,
+ bufferDumpBytes,
+ gceDUMP_BUFFER_USER,
+ gcvFALSE
+ );
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ waitLinkLogical,
+ waitLinkBytes,
+ gceDUMP_BUFFER_WAITLINK,
+ gcvFALSE
+ );
+
+ /* Update the current pipe. */
+ Command->pipeSelect = commandBufferObject->exitPipe;
+
+ /* Update command queue offset. */
+ Command->offset += waitLinkBytes;
+ Command->newQueue = gcvFALSE;
+
+ /* Update address of last WAIT. */
+ Command->waitPhysical = waitPhysical;
+ Command->waitLogical = waitLogical;
+ Command->waitAddress = waitAddress;
+ Command->waitSize = waitSize;
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(gckHARDWARE_UpdateQueueTail(
+ hardware, Command->logical, Command->offset
+ ));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.commit]");
+#endif
+#endif /* gcdNULL_DRIVER */
+
+ /* Release the context switching mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ contextAcquired = gcvFALSE;
+
+ *CommitStamp = Command->commitStamp;
+ *ContextSwitched = contextSwitched;
+
+ Command->commitStamp++;
+
+ stall = gcvFALSE;
+
+#if gcdLINK_QUEUE_SIZE
+ if (Command->kernel->stuckDump == gcvSTUCK_DUMP_STALL_COMMAND)
+ {
+ if ((Command->commitStamp % (gcdLINK_QUEUE_SIZE/2)) == 0)
+ {
+ /* If only context buffer and command buffer is recorded,
+ ** each commit costs 2 slot in queue, to make sure command
+ ** causing stuck is recorded, number of pending command buffer
+ ** is limited to (gckLINK_QUEUE_SIZE/2)
+ */
+ stall = gcvTRUE;
+ }
+ }
+#endif
+
+ /* Release the command queue. */
+ gcmkONERROR(gckCOMMAND_ExitCommit(Command, gcvFALSE));
+ commitEntered = gcvFALSE;
+
+ if ((Command->kernel->hardware->gpuProfiler == gcvTRUE) &&
+ (Command->kernel->profileEnable == gcvTRUE) &&
+ (Command->kernel->profileSyncMode == gcvTRUE))
+ {
+ gcmkONERROR(gckCOMMAND_Stall(Command, gcvTRUE));
+
+ if (Command->currContext)
+ {
+ gcmkONERROR(gckHARDWARE_UpdateContextNewProfile(
+ hardware,
+ Command->currContext));
+ }
+ }
+
+ /* Loop while there are records in the queue. */
+ while (EventQueue != gcvNULL)
+ {
+ if (needCopy)
+ {
+ /* Point to stack record. */
+ eventRecord = &_eventRecord;
+
+ /* Copy the data from the client. */
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Command->os, eventRecord, EventQueue, gcmSIZEOF(gcsQUEUE)
+ ));
+ }
+ else
+ {
+ /* Map record into kernel memory. */
+ gcmkONERROR(gckOS_MapUserPointer(Command->os,
+ EventQueue,
+ gcmSIZEOF(gcsQUEUE),
+ &pointer));
+
+ eventRecord = pointer;
+ }
+
+ /* Append event record to event queue. */
+ gcmkONERROR(gckEVENT_AddList(
+ Command->kernel->eventObj, &eventRecord->iface, gcvKERNEL_PIXEL, gcvTRUE, gcvFALSE
+ ));
+
+ /* Next record in the queue. */
+ nextEventRecord = gcmUINT64_TO_PTR(eventRecord->next);
+
+ if (!needCopy)
+ {
+ /* Unmap record from kernel memory. */
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Command->os, EventQueue, gcmSIZEOF(gcsQUEUE), (gctPOINTER *) eventRecord
+ ));
+
+ eventRecord = gcvNULL;
+ }
+
+ EventQueue = nextEventRecord;
+ }
+
+ if (Command->kernel->eventObj->queueHead == gcvNULL
+ && Command->kernel->hardware->powerManagement == gcvTRUE)
+ {
+ /* Commit done event by which work thread knows all jobs done. */
+ gcmkVERIFY_OK(
+ gckEVENT_CommitDone(Command->kernel->eventObj, gcvKERNEL_PIXEL, Command->currContext));
+ }
+
+ /* Submit events. */
+ status = gckEVENT_Submit(Command->kernel->eventObj, gcvTRUE, gcvFALSE);
+ if (status == gcvSTATUS_INTERRUPTED)
+ {
+ gcmkTRACE(
+ gcvLEVEL_INFO,
+ "%s(%d): Intterupted in gckEVENT_Submit",
+ __FUNCTION__, __LINE__
+ );
+ status = gcvSTATUS_OK;
+ }
+ else
+ {
+ gcmkONERROR(status);
+ }
+
+#ifdef __QNXNTO__
+ if (userCommandBufferLogicalMapped)
+ {
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Command->os,
+ userCommandBufferLogical,
+ 0,
+ commandBufferLogical));
+
+ userCommandBufferLogicalMapped = gcvFALSE;
+ }
+#endif
+
+ /* Unmap the command buffer pointer. */
+ if (commandBufferMapped)
+ {
+ gcmkONERROR(gckOS_UnmapUserPointer(
+ Command->os,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ commandBufferObject
+ ));
+
+ commandBufferMapped = gcvFALSE;
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if ((eventRecord != gcvNULL) && !needCopy)
+ {
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ EventQueue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) eventRecord
+ ));
+ }
+
+ if (contextAcquired)
+ {
+ /* Release the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ }
+
+ if (commitEntered)
+ {
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Command, gcvFALSE));
+ }
+
+#ifdef __QNXNTO__
+ if (userCommandBufferLogicalMapped)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ userCommandBufferLogical,
+ 0,
+ commandBufferLogical));
+ }
+#endif
+
+ /* Unmap the command buffer pointer. */
+ if (commandBufferMapped)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ commandBufferObject
+ ));
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Reserve
+**
+** Reserve space in the command queue. Also acquire the command queue mutex.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctSIZE_T RequestedBytes
+** Number of bytes previously reserved.
+**
+** OUTPUT:
+**
+** gctPOINTER * Buffer
+** Pointer to a variable that will receive the address of the reserved
+** space.
+**
+** gctSIZE_T * BufferSize
+** Pointer to a variable that will receive the number of bytes
+** available in the command queue.
+*/
+gceSTATUS
+gckCOMMAND_Reserve(
+ IN gckCOMMAND Command,
+ IN gctUINT32 RequestedBytes,
+ OUT gctPOINTER * Buffer,
+ OUT gctUINT32 * BufferSize
+ )
+{
+ gceSTATUS status;
+ gctUINT32 bytes;
+ gctUINT32 requiredBytes;
+ gctUINT32 requestedAligned;
+
+ gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Compute aligned number of reuested bytes. */
+ requestedAligned = gcmALIGN(RequestedBytes, Command->alignment);
+
+ /* Another WAIT/LINK command sequence will have to be appended after
+ the requested area being reserved. Compute the number of bytes
+ required for WAIT/LINK at the location after the reserved area. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ Command->kernel->hardware,
+ gcvNULL,
+ ~0U,
+ Command->offset + requestedAligned,
+ &requiredBytes,
+ gcvNULL,
+ gcvNULL
+ ));
+
+ /* Compute total number of bytes required. */
+ requiredBytes += requestedAligned;
+
+ /* Compute number of bytes available in command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ /* Is there enough space in the current command queue? */
+ if (bytes < requiredBytes)
+ {
+ /* Create a new command queue. */
+ gcmkONERROR(_NewQueue(Command));
+
+ /* Recompute the number of bytes in the new kernel command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ /* Still not enough space? */
+ if (bytes < requiredBytes)
+ {
+ /* Rare case, not enough room in command queue. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+ }
+
+ /* Return pointer to empty slot command queue. */
+ *Buffer = (gctUINT8 *) Command->logical + Command->offset;
+
+ /* Return number of bytes left in command queue. */
+ *BufferSize = bytes;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Buffer=0x%x *BufferSize=%lu", *Buffer, *BufferSize);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Execute
+**
+** Execute a previously reserved command queue by appending a WAIT/LINK command
+** sequence after it and modifying the last WAIT into a LINK command. The
+** command FIFO mutex will be released whether this function succeeds or not.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctSIZE_T RequestedBytes
+** Number of bytes previously reserved.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Execute(
+ IN gckCOMMAND Command,
+ IN gctUINT32 RequestedBytes
+ )
+{
+ gceSTATUS status;
+
+ gctUINT32 waitLinkPhysical;
+ gctUINT8_PTR waitLinkLogical;
+ gctUINT32 waitLinkAddress;
+ gctUINT32 waitLinkOffset;
+ gctUINT32 waitLinkBytes;
+
+ gctUINT32 waitPhysical;
+ gctPOINTER waitLogical;
+ gctUINT32 waitAddress;
+ gctUINT32 waitOffset;
+ gctUINT32 waitBytes;
+
+ gctUINT32 linkLow, linkHigh;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ gctPHYS_ADDR execPhysical;
+#endif
+ gctPOINTER execLogical;
+ gctUINT32 execAddress;
+ gctUINT32 execBytes;
+
+ gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Compute offset for WAIT/LINK. */
+ waitLinkOffset = Command->offset + RequestedBytes;
+
+ /* Compute number of bytes left in command queue. */
+ waitLinkBytes = Command->pageSize - waitLinkOffset;
+
+ /* Compute the location if WAIT/LINK command sequence. */
+ waitLinkPhysical = Command->physical + waitLinkOffset;
+ waitLinkLogical = (gctUINT8_PTR) Command->logical + waitLinkOffset;
+ waitLinkAddress = Command->address + waitLinkOffset;
+
+ /* Append WAIT/LINK in command queue. */
+ gcmkONERROR(gckHARDWARE_WaitLink(
+ Command->kernel->hardware,
+ waitLinkLogical,
+ waitLinkAddress,
+ waitLinkOffset,
+ &waitLinkBytes,
+ &waitOffset,
+ &waitBytes
+ ));
+
+ /* Compute the location if WAIT command. */
+ waitPhysical = waitLinkPhysical + waitOffset;
+ waitLogical = waitLinkLogical + waitOffset;
+ waitAddress = waitLinkAddress + waitOffset;
+
+ /* Determine the location to jump to for the command buffer being
+ ** scheduled. */
+ if (Command->newQueue)
+ {
+ /* New command queue, jump to the beginning of it. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ execPhysical = Command->physical;
+#endif
+ execLogical = Command->logical;
+ execAddress = Command->address;
+ execBytes = waitLinkOffset + waitLinkBytes;
+ }
+ else
+ {
+ /* Still within the preexisting command queue, jump directly to the
+ reserved area. */
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ execPhysical = (gctUINT8 *) Command->physical + Command->offset;
+#endif
+ execLogical = (gctUINT8 *) Command->logical + Command->offset;
+ execAddress = Command->address + Command->offset;
+ execBytes = RequestedBytes + waitLinkBytes;
+ }
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)execPhysical,
+ execLogical,
+ execBytes
+ ));
+#endif
+
+ /* Convert the last WAIT into a LINK. */
+ gcmkONERROR(gckHARDWARE_Link(
+ Command->kernel->hardware,
+ Command->waitLogical,
+ execAddress,
+ execBytes,
+ &Command->waitSize,
+ &linkLow,
+ &linkHigh
+ ));
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Command->os,
+ Command->kernelProcessID,
+ gcvNULL,
+ (gctUINT32)Command->waitPhysical,
+ Command->waitLogical,
+ Command->waitSize
+ ));
+#endif
+
+#if gcdLINK_QUEUE_SIZE
+ if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_ALL_COMMAND)
+ {
+ gcuQUEUEDATA data;
+
+ gcmkVERIFY_OK(gckOS_GetProcessID(&data.linkData.pid));
+
+ data.linkData.start = execAddress;
+ data.linkData.end = execAddress + execBytes;
+ data.linkData.linkLow = linkLow;
+ data.linkData.linkHigh = linkHigh;
+
+ gckQUEUE_Enqueue(&Command->kernel->hardware->linkQueue, &data);
+ }
+#endif
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ Command->waitLogical,
+ Command->waitSize,
+ gceDUMP_BUFFER_LINK,
+ gcvFALSE
+ );
+
+ gcmkDUMPCOMMAND(
+ Command->os,
+ execLogical,
+ execBytes,
+ gceDUMP_BUFFER_KERNEL,
+ gcvFALSE
+ );
+
+ /* Update the pointer to the last WAIT. */
+ Command->waitPhysical = waitPhysical;
+ Command->waitLogical = waitLogical;
+ Command->waitAddress = waitAddress;
+ Command->waitSize = waitBytes;
+
+ /* Update the command queue. */
+ Command->offset += RequestedBytes + waitLinkBytes;
+ Command->newQueue = gcvFALSE;
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(gckHARDWARE_UpdateQueueTail(
+ Command->kernel->hardware, Command->logical, Command->offset
+ ));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.execute]");
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Stall
+**
+** The calling thread will be suspended until the command queue has been
+** completed.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctBOOL FromPower
+** Determines whether the call originates from inside the power
+** management or not.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stall(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ )
+{
+#if gcdNULL_DRIVER
+ /* Do nothing with infinite hardware. */
+ return gcvSTATUS_OK;
+#else
+ gckOS os;
+ gckHARDWARE hardware;
+ gckEVENT eventObject;
+ gceSTATUS status;
+ gctSIGNAL signal = gcvNULL;
+ gctUINT timer = 0;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Extract the gckOS object pointer. */
+ os = Command->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckHARDWARE object pointer. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Extract the gckEVENT object pointer. */
+ eventObject = Command->kernel->eventObj;
+ gcmkVERIFY_OBJECT(eventObject, gcvOBJ_EVENT);
+
+ /* Allocate the signal. */
+ gcmkONERROR(gckOS_CreateSignal(os, gcvTRUE, &signal));
+
+ /* Append the EVENT command to trigger the signal. */
+ gcmkONERROR(gckEVENT_Signal(eventObject, signal, gcvKERNEL_PIXEL));
+
+ /* Submit the event queue. */
+ gcmkONERROR(gckEVENT_Submit(eventObject, gcvTRUE, FromPower));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.stall]");
+#endif
+
+ if (status == gcvSTATUS_CHIP_NOT_READY)
+ {
+ /* Error. */
+ goto OnError;
+ }
+
+ do
+ {
+ /* Wait for the signal. */
+ status = gckOS_WaitSignal(os, signal, gcvTRUE, gcdGPU_ADVANCETIMER);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gctUINT32 idle;
+
+ /* Read idle register. */
+ gcmkVERIFY_OK(gckHARDWARE_GetIdle(
+ hardware, gcvFALSE, &idle
+ ));
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): idle=%08x",
+ __FUNCTION__, __LINE__, idle
+ );
+
+ gcmkVERIFY_OK(gckOS_MemoryBarrier(os, gcvNULL));
+#endif
+
+ /* Advance timer. */
+ timer += gcdGPU_ADVANCETIMER;
+ }
+ else if (status == gcvSTATUS_INTERRUPTED)
+ {
+ gcmkONERROR(gcvSTATUS_INTERRUPTED);
+ }
+
+ }
+ while (gcmIS_ERROR(status));
+
+ /* Bail out on timeout. */
+ if (gcmIS_ERROR(status))
+ {
+ /* Broadcast the stuck GPU. */
+ gcmkONERROR(gckOS_Broadcast(
+ os, hardware, gcvBROADCAST_GPU_STUCK
+ ));
+ }
+
+ /* Delete the signal. */
+ gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (signal != gcvNULL)
+ {
+ /* Free the signal. */
+ gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#endif
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Attach
+**
+** Attach user process.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to a gckCOMMAND object.
+**
+** gctUINT32 ProcessID
+** Current process ID.
+**
+** OUTPUT:
+**
+** gckCONTEXT * Context
+** Pointer to a variable that will receive a pointer to a new
+** gckCONTEXT object.
+**
+** gctSIZE_T * StateCount
+** Pointer to a variable that will receive the number of states
+** in the context buffer.
+*/
+#if (gcdENABLE_3D || gcdENABLE_2D)
+gceSTATUS
+gckCOMMAND_Attach(
+ IN gckCOMMAND Command,
+ OUT gckCONTEXT * Context,
+ OUT gctSIZE_T * MaxState,
+ OUT gctUINT32 * NumStates,
+ IN gctUINT32 ProcessID
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Acquire the context switching mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, Command->mutexContext, gcvINFINITE
+ ));
+ acquired = gcvTRUE;
+
+ /* Construct a gckCONTEXT object. */
+ gcmkONERROR(gckCONTEXT_Construct(
+ Command->os,
+ Command->kernel->hardware,
+ ProcessID,
+ Context
+ ));
+
+ /* Return the number of states in the context. */
+ * MaxState = (* Context)->maxState;
+ * NumStates = (* Context)->numStates;
+
+ /* Release the context switching mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Context=0x%x", *Context);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Release mutex. */
+ if (acquired)
+ {
+ /* Release the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ acquired = gcvFALSE;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckCOMMAND_Detach
+**
+** Detach user process.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to a gckCOMMAND object.
+**
+** gckCONTEXT Context
+** Pointer to a gckCONTEXT object to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Detach(
+ IN gckCOMMAND Command,
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x Context=0x%x", Command, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Acquire the context switching mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(
+ Command->os, Command->mutexContext, gcvINFINITE
+ ));
+ acquired = gcvTRUE;
+
+ /* Construct a gckCONTEXT object. */
+ gcmkONERROR(gckCONTEXT_Destroy(Context));
+
+ if (Command->currContext == Context)
+ {
+ /* Detach from gckCOMMAND object if the destoryed context is current context. */
+ Command->currContext = gcvNULL;
+ }
+
+ /* Release the context switching mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ acquired = gcvFALSE;
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Release mutex. */
+ if (acquired)
+ {
+ /* Release the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ acquired = gcvFALSE;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_DumpExecutingBuffer
+**
+** Dump the command buffer which GPU is executing.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to a gckCOMMAND object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_DumpExecutingBuffer(
+ IN gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer = gcvNULL;
+ gctUINT32 gpuAddress;
+ gctSIZE_T pageCount;
+ gctPOINTER entry = gcvNULL;
+ gckOS os = Command->os;
+ gckKERNEL kernel = Command->kernel;
+ gctUINT32 i;
+ gctUINT32 dumpRear;
+ gckQUEUE queue = &kernel->hardware->linkQueue;
+ gctSIZE_T bytes;
+ gckLINKDATA linkData;
+ gcuQUEUEDATA * queueData;
+ gctUINT32 offset;
+ gctPOINTER entryDump;
+ gctUINT32 pid;
+ gctUINT8 processName[24] = {0};
+ gctPHYS_ADDR_T cpuPhysical;
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("**** COMMAND BUF DUMP ****\n");
+ gcmkPRINT("**************************\n");
+
+ gcmkPRINT(" Submitted commit stamp = %lld", Command->commitStamp - 1);
+ gcmkPRINT(" Executed commit stamp = %lld", *(gctUINT64_PTR)Command->fence->logical);
+
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(os, kernel->core, 0x664, &gpuAddress));
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(os, kernel->core, 0x664, &gpuAddress));
+
+ gcmkPRINT("DMA Address 0x%08X, memory around:", gpuAddress);
+
+ /* Search and dump memory around DMA address. */
+ if (kernel->virtualCommandBuffer)
+ {
+ status = gckDEVICE_QueryGPUAddress(kernel->device, kernel, gpuAddress, &buffer);
+ }
+ else
+ {
+ status = gcvSTATUS_OK;
+ }
+
+ if (gcmIS_SUCCESS(status))
+ {
+ if (kernel->virtualCommandBuffer)
+ {
+ gcmkVERIFY_OK(gckOS_CreateKernelVirtualMapping(
+ os, buffer->virtualBuffer.physical, buffer->virtualBuffer.bytes, &entry, &pageCount));
+
+ offset = gpuAddress - buffer->virtualBuffer.gpuAddress;
+
+ entryDump = entry;
+
+ /* Dump one pages. */
+ bytes = 4096;
+
+ /* Align to page. */
+ offset &= 0xfffff000;
+
+ /* Kernel address of page where stall point stay. */
+ entryDump = (gctUINT8_PTR)entryDump + offset;
+
+ /* Align to page. */
+ gpuAddress &= 0xfffff000;
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_GPUPhysicalToCPUPhysical(os, gpuAddress, &cpuPhysical));
+
+ gcmkVERIFY_OK(gckOS_MapPhysical(os, (gctUINT32) cpuPhysical, 4096, &entry));
+
+ /* Align to page start. */
+ entryDump = (gctPOINTER)((gctUINTPTR_T)entry & ~0xFFF);
+ gpuAddress = gpuAddress & ~0xFFF;
+ bytes = 4096;
+ }
+
+ gcmkPRINT("User Command Buffer:\n");
+ _DumpBuffer(entryDump, gpuAddress, bytes);
+
+ if (kernel->virtualCommandBuffer)
+ {
+ gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(
+ os, buffer->virtualBuffer.physical, buffer->virtualBuffer.bytes, entry));
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_UnmapPhysical(os, entry, 4096));
+ }
+ }
+ else
+ {
+ _DumpKernelCommandBuffer(Command);
+ }
+
+ /* Dump link queue. */
+ if (queue->count)
+ {
+ gcmkPRINT("Dump Level is %d, dump %d valid record in link queue:",
+ Command->kernel->stuckDump, queue->count);
+
+ dumpRear = queue->count;
+
+ for (i = 0; i < dumpRear; i++)
+ {
+ gckQUEUE_GetData(queue, i, &queueData);
+
+ linkData = &queueData->linkData;
+
+ /* Get gpu address of this command buffer. */
+ gpuAddress = linkData->start;
+ bytes = linkData->end - gpuAddress;
+
+ pid = linkData->pid;
+
+ gckOS_GetProcessNameByPid(pid, 16, processName);
+
+ if (kernel->virtualCommandBuffer)
+ {
+ buffer = gcvNULL;
+
+ /* Get the whole buffer. */
+ status = gckDEVICE_QueryGPUAddress(kernel->device, kernel, gpuAddress, &buffer);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Get kernel address of kernel command buffer. */
+ status = gckCOMMAND_AddressInKernelCommandBuffer(
+ kernel->command, gpuAddress, &entry);
+
+ if (gcmIS_ERROR(status))
+ {
+ status = gckHARDWARE_AddressInHardwareFuncions(
+ kernel->hardware, gpuAddress, &entry);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkPRINT("Buffer [%08X - %08X] not found, may be freed",
+ linkData->start,
+ linkData->end);
+ continue;
+ }
+ }
+
+ offset = 0;
+ gcmkPRINT("Kernel Command Buffer: %08X, %08X", linkData->linkLow, linkData->linkHigh);
+ }
+ else
+ {
+ /* Get kernel logical for dump. */
+ if (buffer->virtualBuffer.kernelLogical)
+ {
+ /* Get kernel logical directly if it is a context buffer. */
+ entry = buffer->virtualBuffer.kernelLogical;
+ gcmkPRINT("Context Buffer: %08X, %08X PID:%d %s",
+ linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
+ }
+ else
+ {
+ /* Make it accessiable by kernel if it is a user command buffer. */
+ gcmkVERIFY_OK(
+ gckOS_CreateKernelVirtualMapping(os,
+ buffer->virtualBuffer.physical,
+ buffer->virtualBuffer.bytes,
+ &entry,
+ &pageCount));
+ gcmkPRINT("User Command Buffer: %08X, %08X PID:%d %s",
+ linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
+ }
+
+ offset = gpuAddress - buffer->virtualBuffer.gpuAddress;
+ }
+
+ /* Dump from the entry. */
+ _DumpBuffer((gctUINT8_PTR)entry + offset, gpuAddress, bytes);
+
+ /* Release kernel logical address if neccessary. */
+ if (buffer && !buffer->virtualBuffer.kernelLogical)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DestroyKernelVirtualMapping(os,
+ buffer->virtualBuffer.physical,
+ buffer->virtualBuffer.bytes,
+ entry));
+ }
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_GPUPhysicalToCPUPhysical(os, gpuAddress, &cpuPhysical));
+
+ gcmkVERIFY_OK(gckOS_MapPhysical(os, (gctUINT32) cpuPhysical, bytes, &entry));
+
+ gcmkPRINT("Command Buffer: %08X, %08X PID:%d %s",
+ linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
+
+ _DumpBuffer((gctUINT8_PTR)entry, gpuAddress, bytes);
+
+ gcmkVERIFY_OK(gckOS_UnmapPhysical(os, entry, bytes));
+ }
+ }
+ }
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckCOMMAND_AddressInKernelCommandBuffer(
+ IN gckCOMMAND Command,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Pointer
+ )
+{
+ gctINT i;
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+ {
+ if ((Address >= Command->queues[i].address)
+ && (Address < (Command->queues[i].address + Command->pageSize))
+ )
+ {
+ *Pointer = (gctUINT8_PTR)Command->queues[i].logical
+ + (Address - Command->queues[i].address)
+ ;
+
+ return gcvSTATUS_OK;
+ }
+ }
+
+ return gcvSTATUS_NOT_FOUND;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
new file mode 100644
index 000000000000..4890779a3c71
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
@@ -0,0 +1,3948 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+#include "gc_hal_kernel_hardware_command_vg.h"
+
+#define _GC_OBJ_ZONE gcvZONE_COMMAND
+
+#ifdef __QNXNTO__
+extern gceSTATUS
+drv_signal_mgr_add(
+ gctUINT32 Pid,
+ gctINT32 Coid,
+ gctINT32 Rcvid,
+ gctUINT64 Signal,
+ gctPOINTER *Handle);
+#endif
+
+/******************************************************************************\
+*********************************** Debugging **********************************
+\******************************************************************************/
+
+#define gcvDISABLE_TIMEOUT 1
+#define gcvDUMP_COMMAND_BUFFER 0
+#define gcvDUMP_COMMAND_LINES 0
+
+
+#if gcvDEBUG || defined(EMULATOR) || gcvDISABLE_TIMEOUT
+# define gcvQUEUE_TIMEOUT ~0
+#else
+# define gcvQUEUE_TIMEOUT 10
+#endif
+
+
+/******************************************************************************\
+********************************** Definitions *********************************
+\******************************************************************************/
+
+/* Minimum buffer size. */
+#define gcvMINUMUM_BUFFER \
+ gcmSIZEOF(gcsKERNEL_QUEUE_HEADER) + \
+ gcmSIZEOF(gcsKERNEL_CMDQUEUE) * 2
+
+#define gcmDECLARE_INTERRUPT_HANDLER(Block, Number) \
+ static gceSTATUS \
+ _EventHandler_##Block##_##Number( \
+ IN gckVGKERNEL Kernel \
+ )
+
+#define gcmDEFINE_INTERRUPT_HANDLER(Block, Number) \
+ gcmDECLARE_INTERRUPT_HANDLER(Block, Number) \
+ { \
+ return _EventHandler_Block( \
+ Kernel, \
+ &Kernel->command->taskTable[gcvBLOCK_##Block], \
+ gcvFALSE \
+ ); \
+ }
+
+#define gcmDEFINE_INTERRUPT_HANDLER_ENTRY(Block, Number) \
+ { gcvBLOCK_##Block, _EventHandler_##Block##_##Number }
+
+/* Block interrupt handling table entry. */
+typedef struct _gcsBLOCK_INTERRUPT_HANDLER * gcsBLOCK_INTERRUPT_HANDLER_PTR;
+typedef struct _gcsBLOCK_INTERRUPT_HANDLER
+{
+ gceBLOCK block;
+ gctINTERRUPT_HANDLER handler;
+}
+gcsBLOCK_INTERRUPT_HANDLER;
+
+/* Queue control functions. */
+typedef struct _gcsQUEUE_UPDATE_CONTROL * gcsQUEUE_UPDATE_CONTROL_PTR;
+typedef struct _gcsQUEUE_UPDATE_CONTROL
+{
+ gctOBJECT_HANDLER execute;
+ gctOBJECT_HANDLER update;
+ gctOBJECT_HANDLER lastExecute;
+ gctOBJECT_HANDLER lastUpdate;
+}
+gcsQUEUE_UPDATE_CONTROL;
+
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+static gceSTATUS
+_FlushMMU(
+ IN gckVGCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctUINT32 oldValue;
+ gckVGHARDWARE hardware = Command->hardware;
+
+ gcmkONERROR(gckOS_AtomicExchange(Command->os,
+ hardware->pageTableDirty,
+ 0,
+ &oldValue));
+
+ if (oldValue)
+ {
+ /* Page Table is upated, flush mmu before commit. */
+ gcmkONERROR(gckVGHARDWARE_FlushMMU(hardware));
+ }
+
+ return gcvSTATUS_OK;
+OnError:
+ return status;
+}
+
+static gceSTATUS
+_WaitForIdle(
+ IN gckVGCOMMAND Command,
+ IN gcsKERNEL_QUEUE_HEADER_PTR Queue
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctUINT32 idle;
+ gctUINT timeout = 0;
+
+ /* Loop while not idle. */
+ while (Queue->pending)
+ {
+ /* Did we reach the timeout limit? */
+ if (timeout == gcvQUEUE_TIMEOUT)
+ {
+ /* Hardware is probably dead... */
+ return gcvSTATUS_TIMEOUT;
+ }
+
+ /* Sleep for 100ms. */
+ gcmkERR_BREAK(gckOS_Delay(Command->os, 100));
+
+ /* Not the first loop? */
+ if (timeout > 0)
+ {
+ /* Read IDLE register. */
+ gcmkVERIFY_OK(gckVGHARDWARE_GetIdle(Command->hardware, &idle));
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_COMMAND,
+ "%s: timeout, IDLE=%08X\n",
+ __FUNCTION__, idle
+ );
+ }
+
+ /* Increment the timeout counter. */
+ timeout += 1;
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gctINT32
+_GetNextInterrupt(
+ IN gckVGCOMMAND Command,
+ IN gceBLOCK Block
+ )
+{
+ gctUINT index;
+ gcsBLOCK_TASK_ENTRY_PTR entry;
+ gctINT32 interrupt;
+
+ /* Get the block entry. */
+ entry = &Command->taskTable[Block];
+
+ /* Make sure we have initialized interrupts. */
+ gcmkASSERT(entry->interruptCount > 0);
+
+ /* Decrement the interrupt usage semaphore. */
+ gcmkVERIFY_OK(gckOS_DecrementSemaphore(
+ Command->os, entry->interruptSemaphore
+ ));
+
+ /* Get the value index. */
+ index = entry->interruptIndex;
+
+ /* Get the interrupt value. */
+ interrupt = entry->interruptArray[index];
+
+ /* Must be a valid value. */
+ gcmkASSERT((interrupt >= 0) && (interrupt <= 31));
+
+ /* Advance the index to the next value. */
+ index += 1;
+
+ /* Set the new index. */
+ entry->interruptIndex = (index == entry->interruptCount)
+ ? 0
+ : index;
+
+ /* Return interrupt value. */
+ return interrupt;
+}
+
+
+/******************************************************************************\
+***************************** Task Storage Management **************************
+\******************************************************************************/
+
+/* Minimum task buffer size. */
+#define gcvMIN_TASK_BUFFER \
+( \
+ gcmSIZEOF(gcsTASK_CONTAINER) + 128 \
+)
+
+/* Free list terminator. */
+#define gcvFREE_TASK_TERMINATOR \
+( \
+ (gcsTASK_CONTAINER_PTR) gcmINT2PTR(~0) \
+)
+
+
+/*----------------------------------------------------------------------------*/
+/*------------------- Allocated Task Buffer List Management ------------------*/
+
+static void
+_InsertTaskBuffer(
+ IN gcsTASK_CONTAINER_PTR AddAfter,
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ gcsTASK_CONTAINER_PTR addBefore;
+
+ /* Cannot add before the first buffer. */
+ gcmkASSERT(AddAfter != gcvNULL);
+
+ /* Create a shortcut to the next buffer. */
+ addBefore = AddAfter->allocNext;
+
+ /* Initialize the links. */
+ Buffer->allocPrev = AddAfter;
+ Buffer->allocNext = addBefore;
+
+ /* Link to the previous buffer. */
+ AddAfter->allocNext = Buffer;
+
+ /* Link to the next buffer. */
+ if (addBefore != gcvNULL)
+ {
+ addBefore->allocPrev = Buffer;
+ }
+}
+
+static void
+_RemoveTaskBuffer(
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ gcsTASK_CONTAINER_PTR prev;
+ gcsTASK_CONTAINER_PTR next;
+
+ /* Cannot remove the first buffer. */
+ gcmkASSERT(Buffer->allocPrev != gcvNULL);
+
+ /* Create shortcuts to the previous and next buffers. */
+ prev = Buffer->allocPrev;
+ next = Buffer->allocNext;
+
+ /* Tail buffer? */
+ if (next == gcvNULL)
+ {
+ /* Remove from the list. */
+ prev->allocNext = gcvNULL;
+ }
+
+ /* Buffer from the middle. */
+ else
+ {
+ prev->allocNext = next;
+ next->allocPrev = prev;
+ }
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*--------------------- Free Task Buffer List Management ---------------------*/
+
+static void
+_AppendToFreeList(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ /* Cannot be a part of the free list already. */
+ gcmkASSERT(Buffer->freePrev == gcvNULL);
+ gcmkASSERT(Buffer->freeNext == gcvNULL);
+
+ /* First buffer to add? */
+ if (Command->taskFreeHead == gcvNULL)
+ {
+ /* Terminate the links. */
+ Buffer->freePrev = gcvFREE_TASK_TERMINATOR;
+ Buffer->freeNext = gcvFREE_TASK_TERMINATOR;
+
+ /* Initialize the list pointer. */
+ Command->taskFreeHead = Command->taskFreeTail = Buffer;
+ }
+
+ /* Not the first, add after the tail. */
+ else
+ {
+ /* Initialize the new tail buffer. */
+ Buffer->freePrev = Command->taskFreeTail;
+ Buffer->freeNext = gcvFREE_TASK_TERMINATOR;
+
+ /* Add after the tail. */
+ Command->taskFreeTail->freeNext = Buffer;
+ Command->taskFreeTail = Buffer;
+ }
+}
+
+static void
+_RemoveFromFreeList(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ /* Has to be a part of the free list. */
+ gcmkASSERT(Buffer->freePrev != gcvNULL);
+ gcmkASSERT(Buffer->freeNext != gcvNULL);
+
+ /* Head buffer? */
+ if (Buffer->freePrev == gcvFREE_TASK_TERMINATOR)
+ {
+ /* Tail buffer as well? */
+ if (Buffer->freeNext == gcvFREE_TASK_TERMINATOR)
+ {
+ /* Reset the list pointer. */
+ Command->taskFreeHead = Command->taskFreeTail = gcvNULL;
+ }
+
+ /* No, just the head. */
+ else
+ {
+ /* Update the head. */
+ Command->taskFreeHead = Buffer->freeNext;
+
+ /* Terminate the next buffer. */
+ Command->taskFreeHead->freePrev = gcvFREE_TASK_TERMINATOR;
+ }
+ }
+
+ /* Not the head. */
+ else
+ {
+ /* Tail buffer? */
+ if (Buffer->freeNext == gcvFREE_TASK_TERMINATOR)
+ {
+ /* Update the tail. */
+ Command->taskFreeTail = Buffer->freePrev;
+
+ /* Terminate the previous buffer. */
+ Command->taskFreeTail->freeNext = gcvFREE_TASK_TERMINATOR;
+ }
+
+ /* A buffer in the middle. */
+ else
+ {
+ /* Remove the buffer from the list. */
+ Buffer->freePrev->freeNext = Buffer->freeNext;
+ Buffer->freeNext->freePrev = Buffer->freePrev;
+ }
+ }
+
+ /* Reset free list pointers. */
+ Buffer->freePrev = gcvNULL;
+ Buffer->freeNext = gcvNULL;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*-------------------------- Task Buffer Allocation --------------------------*/
+
+static void
+_SplitTaskBuffer(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_CONTAINER_PTR Buffer,
+ IN gctUINT Size
+ )
+{
+ /* Determine the size of the new buffer. */
+ gctINT splitBufferSize = Buffer->size - Size;
+ gcmkASSERT(splitBufferSize >= 0);
+
+ /* Is the split buffer big enough to become a separate buffer? */
+ if (splitBufferSize >= gcvMIN_TASK_BUFFER)
+ {
+ /* Place the new path data. */
+ gcsTASK_CONTAINER_PTR splitBuffer = (gcsTASK_CONTAINER_PTR)
+ (
+ (gctUINT8_PTR) Buffer + Size
+ );
+
+ /* Set the trimmed buffer size. */
+ Buffer->size = Size;
+
+ /* Initialize the split buffer. */
+ splitBuffer->referenceCount = 0;
+ splitBuffer->size = splitBufferSize;
+ splitBuffer->freePrev = gcvNULL;
+ splitBuffer->freeNext = gcvNULL;
+
+ /* Link in. */
+ _InsertTaskBuffer(Buffer, splitBuffer);
+ _AppendToFreeList(Command, splitBuffer);
+ }
+}
+
+static gceSTATUS
+_AllocateTaskContainer(
+ IN gckVGCOMMAND Command,
+ IN gctUINT Size,
+ OUT gcsTASK_CONTAINER_PTR * Buffer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x Size=0x%x, Buffer ==0x%x", Command, Size, Buffer);
+
+ /* Verify arguments. */
+ gcmkVERIFY_ARGUMENT(Buffer != gcvNULL);
+
+ do
+ {
+ gcsTASK_STORAGE_PTR storage;
+ gcsTASK_CONTAINER_PTR buffer;
+
+ /* Adjust the size. */
+ Size += gcmSIZEOF(gcsTASK_CONTAINER);
+
+ /* Adjust the allocation size if not big enough. */
+ if (Size > Command->taskStorageUsable)
+ {
+ Command->taskStorageGranularity
+ = gcmALIGN(Size + gcmSIZEOF(gcsTASK_STORAGE), 1024);
+
+ Command->taskStorageUsable
+ = Command->taskStorageGranularity - gcmSIZEOF(gcsTASK_STORAGE);
+ }
+
+ /* Is there a free buffer available? */
+ else if (Command->taskFreeHead != gcvNULL)
+ {
+ /* Set the initial free buffer. */
+ gcsTASK_CONTAINER_PTR buffer = Command->taskFreeHead;
+
+ do
+ {
+ /* Is the buffer big enough? */
+ if (buffer->size >= Size)
+ {
+ /* Remove the buffer from the free list. */
+ _RemoveFromFreeList(Command, buffer);
+
+ /* Split the buffer. */
+ _SplitTaskBuffer(Command, buffer, Size);
+
+ /* Set the result. */
+ * Buffer = buffer;
+
+ gcmkFOOTER_ARG("*Buffer=0x%x",*Buffer);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+
+ /* Get the next free buffer. */
+ buffer = buffer->freeNext;
+ }
+ while (buffer != gcvFREE_TASK_TERMINATOR);
+ }
+
+ /* Allocate a container. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Command->os,
+ Command->taskStorageGranularity,
+ (gctPOINTER *) &storage
+ ));
+
+ /* Link in the storage buffer. */
+ storage->next = Command->taskStorage;
+ Command->taskStorage = storage;
+
+ /* Place the task buffer. */
+ buffer = (gcsTASK_CONTAINER_PTR) (storage + 1);
+
+ /* Determine the size of the buffer. */
+ buffer->size
+ = Command->taskStorageGranularity
+ - gcmSIZEOF(gcsTASK_STORAGE);
+
+ /* Initialize the task buffer. */
+ buffer->referenceCount = 0;
+ buffer->allocPrev = gcvNULL;
+ buffer->allocNext = gcvNULL;
+ buffer->freePrev = gcvNULL;
+ buffer->freeNext = gcvNULL;
+
+ /* Split the buffer. */
+ _SplitTaskBuffer(Command, buffer, Size);
+
+ /* Set the result. */
+ * Buffer = buffer;
+
+ gcmkFOOTER_ARG("*Buffer=0x%x",*Buffer);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+static void
+_FreeTaskContainer(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_CONTAINER_PTR Buffer
+ )
+{
+ gcsTASK_CONTAINER_PTR prev;
+ gcsTASK_CONTAINER_PTR next;
+ gcsTASK_CONTAINER_PTR merged;
+
+ gctUINT32 mergedSize;
+
+ /* Verify arguments. */
+ gcmkASSERT(Buffer != gcvNULL);
+ gcmkASSERT(Buffer->freePrev == gcvNULL);
+ gcmkASSERT(Buffer->freeNext == gcvNULL);
+
+ /* Get shortcuts to the previous and next path data buffers. */
+ prev = Buffer->allocPrev;
+ next = Buffer->allocNext;
+
+ /* Is the previous path data buffer already free? */
+ if (prev && prev->freeNext)
+ {
+ /* The previous path data buffer is the one that remains. */
+ merged = prev;
+
+ /* Is the next path data buffer already free? */
+ if (next && next->freeNext)
+ {
+ /* Merge all three path data buffers into the previous. */
+ mergedSize = prev->size + Buffer->size + next->size;
+
+ /* Remove the next path data buffer. */
+ _RemoveFromFreeList(Command, next);
+ _RemoveTaskBuffer(next);
+ }
+ else
+ {
+ /* Merge the current path data buffer into the previous. */
+ mergedSize = prev->size + Buffer->size;
+ }
+
+ /* Delete the current path data buffer. */
+ _RemoveTaskBuffer(Buffer);
+
+ /* Set new size. */
+ merged->size = mergedSize;
+ }
+ else
+ {
+ /* The current path data buffer is the one that remains. */
+ merged = Buffer;
+
+ /* Is the next buffer already free? */
+ if (next && next->freeNext)
+ {
+ /* Merge the next into the current. */
+ mergedSize = Buffer->size + next->size;
+
+ /* Remove the next buffer. */
+ _RemoveFromFreeList(Command, next);
+ _RemoveTaskBuffer(next);
+
+ /* Set new size. */
+ merged->size = mergedSize;
+ }
+
+ /* Add the current buffer into the free list. */
+ _AppendToFreeList(Command, merged);
+ }
+}
+
+gceSTATUS
+_RemoveRecordFromProcesDB(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_HEADER_PTR Task
+ )
+{
+ gceSTATUS status;
+ gcsTASK_PTR task = (gcsTASK_PTR)((gctUINT8_PTR)Task - sizeof(gcsTASK));
+ gcsTASK_FREE_VIDEO_MEMORY_PTR freeVideoMemory;
+ gcsTASK_UNLOCK_VIDEO_MEMORY_PTR unlockVideoMemory;
+ gctINT pid;
+ gctUINT32 size,id;
+ gctUINT32 handle;
+ gckKERNEL kernel = Command->kernel->kernel;
+ gckVIDMEM_NODE unlockNode = gcvNULL;
+ gckVIDMEM_NODE nodeObject = gcvNULL;
+ gceDATABASE_TYPE type;
+
+ /* Get the total size of all tasks. */
+
+ gcmkVERIFY_OK(gckOS_GetProcessID((gctUINT32_PTR)&pid));
+ gcmkVERIFY_OK(gckOS_ReadMappedPointer(Command->os, &task->size, &size));
+
+ do
+ {
+ gcmkVERIFY_OK(gckOS_ReadMappedPointer(Command->os, &Task->id, &id));
+ switch (id)
+ {
+ case gcvTASK_FREE_VIDEO_MEMORY:
+ freeVideoMemory = (gcsTASK_FREE_VIDEO_MEMORY_PTR)Task;
+
+ gcmkVERIFY_OK(gckOS_ReadMappedPointer(Command->os, &freeVideoMemory->node, &handle));
+
+ status = gckVIDMEM_HANDLE_Lookup(
+ Command->kernel->kernel,
+ pid,
+ handle,
+ &nodeObject);
+
+ if (gcmIS_ERROR(status))
+ {
+ return status;
+ }
+
+ gckVIDMEM_HANDLE_Dereference(kernel, pid, handle);
+ gcmkVERIFY_OK(gckOS_WriteMemory(Command->os, &freeVideoMemory->node, gcmALL_TO_UINT32(nodeObject)));
+
+ type = gcvDB_VIDEO_MEMORY
+ | (nodeObject->type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
+ | (nodeObject->pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
+
+ /* Remove record from process db. */
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Command->kernel->kernel,
+ pid,
+ type,
+ gcmINT2PTR(handle)));
+
+ /* Advance to next task. */
+ size -= sizeof(gcsTASK_FREE_VIDEO_MEMORY);
+ Task = (gcsTASK_HEADER_PTR)(freeVideoMemory + 1);
+
+ break;
+ case gcvTASK_UNLOCK_VIDEO_MEMORY:
+ unlockVideoMemory = (gcsTASK_UNLOCK_VIDEO_MEMORY_PTR)Task;
+
+ gcmkVERIFY_OK(gckOS_ReadMappedPointer(Command->os, &unlockVideoMemory->node, &handle));
+ /* Remove record from process db. */
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Command->kernel->kernel,
+ pid,
+ gcvDB_VIDEO_MEMORY_LOCKED,
+ gcmUINT64_TO_PTR(handle)));
+
+
+ status = gckVIDMEM_HANDLE_Lookup(
+ Command->kernel->kernel,
+ pid,
+ handle,
+ &unlockNode);
+
+ if (gcmIS_ERROR(status))
+ {
+ return status;
+ }
+
+ gckVIDMEM_HANDLE_Dereference(kernel, pid, handle);
+ gcmkVERIFY_OK(gckOS_WriteMemory(Command->os, &unlockVideoMemory->node, gcmALL_TO_UINT32(unlockNode)));
+
+ /* Advance to next task. */
+ size -= sizeof(gcsTASK_UNLOCK_VIDEO_MEMORY);
+ Task = (gcsTASK_HEADER_PTR)(unlockVideoMemory + 1);
+
+ break;
+ default:
+ /* Skip the whole task. */
+ size = 0;
+ break;
+ }
+ }
+ while(size);
+
+ return gcvSTATUS_OK;
+}
+
+/******************************************************************************\
+********************************* Task Scheduling ******************************
+\******************************************************************************/
+
+static gceSTATUS
+_ScheduleTasks(
+ IN gckVGCOMMAND Command,
+ IN gcsTASK_MASTER_TABLE_PTR TaskTable,
+ IN gctUINT8_PTR PreviousEnd
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gctINT block;
+ gcsTASK_CONTAINER_PTR container;
+ gcsTASK_MASTER_ENTRY_PTR userTaskEntry;
+ gcsBLOCK_TASK_ENTRY_PTR kernelTaskEntry;
+ gcsTASK_PTR userTask;
+ gcsTASK userTaskObject;
+ gctUINT8_PTR kernelTask;
+ gctINT32 interrupt;
+ gctUINT8_PTR eventCommand;
+ gctBOOL needCopy = gcvFALSE;
+ gctINT pid;
+#ifdef __QNXNTO__
+ gcsTASK_PTR oldUserTask = gcvNULL;
+ gctPOINTER pointer;
+#endif
+
+ /* Nothing to schedule? */
+ if (TaskTable->size == 0)
+ {
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ Command->os,
+ Command->taskMutex,
+ gcvINFINITE
+ ));
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d)\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkVERIFY_OK(gckOS_GetProcessID((gctUINT32_PTR)&pid));
+ gcmkVERIFY_OK(gckOS_QueryNeedCopy(Command->os, pid, &needCopy));
+ do
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " number of tasks scheduled = %d\n"
+ " size of event data in bytes = %d\n",
+ TaskTable->count,
+ TaskTable->size
+ );
+
+ /* Allocate task buffer. */
+ gcmkERR_BREAK(_AllocateTaskContainer(
+ Command,
+ TaskTable->size,
+ &container
+ ));
+
+ /* Determine the task data pointer. */
+ kernelTask = (gctUINT8_PTR) (container + 1);
+
+ /* Initialize the reference count. */
+ container->referenceCount = TaskTable->count;
+
+ /* Process tasks. */
+ for (block = gcvBLOCK_COUNT - 1; block >= 0; block -= 1)
+ {
+ /* Get the current user table entry. */
+ userTaskEntry = &TaskTable->table[block];
+
+ /* Are there tasks scheduled? */
+ if (userTaskEntry->head == gcvNULL)
+ {
+ /* No, skip to the next block. */
+ continue;
+ }
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " processing tasks for block %d\n",
+ block
+ );
+
+ /* Get the current kernel table entry. */
+ kernelTaskEntry = &Command->taskTable[block];
+
+ /* Are there tasks for the current block scheduled? */
+ if (kernelTaskEntry->container == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " first task container for the block added\n",
+ block
+ );
+
+ /* Nothing yet, set the container buffer pointer. */
+ kernelTaskEntry->container = container;
+ kernelTaskEntry->task = (gcsTASK_HEADER_PTR) kernelTask;
+ }
+
+ /* Yes, append to the end. */
+ else
+ {
+ kernelTaskEntry->link->cotainer = container;
+ kernelTaskEntry->link->task = (gcsTASK_HEADER_PTR) kernelTask;
+ }
+
+ /* Set initial task. */
+ userTask = userTaskEntry->head;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " copying user tasks over to the kernel\n"
+ );
+
+ /* Copy tasks. */
+ do
+ {
+ gcsTASK_HEADER_PTR taskHeader;
+#ifdef __QNXNTO__
+ oldUserTask = userTask;
+
+ gcmkERR_BREAK(gckOS_MapUserPointer(
+ Command->os,
+ oldUserTask,
+ 0,
+ &pointer));
+
+ userTask = pointer;
+#endif
+ taskHeader = (gcsTASK_HEADER_PTR) (userTask + 1);
+ if(needCopy)
+ {
+ gcmkERR_BREAK(gckOS_CopyFromUserData(
+ Command->os,
+ &userTaskObject,
+ userTask,
+ gcmSIZEOF(gcsTASK)
+ ));
+ userTask = &userTaskObject;
+ }
+
+ gcmkVERIFY_OK(_RemoveRecordFromProcesDB(Command, taskHeader));
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " task ID = %d, size = %d\n",
+ ((gcsTASK_HEADER_PTR) (userTask + 1))->id,
+ userTask->size
+ );
+
+ /* Copy the task data. */
+ if(needCopy)
+ {
+ gcmkERR_BREAK(gckOS_CopyFromUserData(
+ Command->os,
+ kernelTask,
+ taskHeader,
+ userTask->size
+ ));
+ }
+ else
+ {
+
+ gcmkERR_BREAK(gckOS_MemCopy(
+ kernelTask, taskHeader, userTask->size
+ ));
+ }
+#ifdef __QNXNTO__
+ if (taskHeader->id == gcvTASK_SIGNAL)
+ {
+ gcsTASK_SIGNAL_PTR taskSignal = (gcsTASK_SIGNAL_PTR)kernelTask;
+ gctPOINTER signal;
+ gctUINT32 pid;
+
+ gcmkVERIFY_OK(gckOS_GetProcessID(&pid));
+
+ taskSignal->coid = TaskTable->coid;
+ taskSignal->rcvid = TaskTable->rcvid;
+
+ gcmkERR_BREAK(drv_signal_mgr_add(
+ pid,
+ taskSignal->coid,
+ taskSignal->rcvid,
+ gcmPTR_TO_UINT64(taskSignal->signal),
+ &signal));
+
+ taskSignal->signal = signal;
+ }
+#endif
+
+ /* Advance to the next task. */
+ kernelTask += userTask->size;
+ userTask = userTask->next;
+
+#ifdef __QNXNTO__
+ gcmkERR_BREAK(gckOS_UnmapUserPointer(
+ Command->os,
+ oldUserTask,
+ 0,
+ pointer));
+#endif
+ }
+ while (userTask != gcvNULL);
+
+ /* Update link pointer in the header. */
+ kernelTaskEntry->link = (gcsTASK_LINK_PTR) kernelTask;
+
+ /* Initialize link task. */
+ kernelTaskEntry->link->id = gcvTASK_LINK;
+ kernelTaskEntry->link->cotainer = gcvNULL;
+ kernelTaskEntry->link->task = gcvNULL;
+
+ /* Advance the task data pointer. */
+ kernelTask += gcmSIZEOF(gcsTASK_LINK);
+ }
+ }
+ while (gcvFALSE);
+
+ /* Release the mutex. */
+ gcmkERR_BREAK(gckOS_ReleaseMutex(
+ Command->os,
+ Command->taskMutex
+ ));
+
+ /* Assign interrupts to the blocks. */
+ eventCommand = PreviousEnd;
+
+ for (block = gcvBLOCK_COUNT - 1; block >= 0; block -= 1)
+ {
+ /* Get the current user table entry. */
+ userTaskEntry = &TaskTable->table[block];
+
+ /* Are there tasks scheduled? */
+ if (userTaskEntry->head == gcvNULL)
+ {
+ /* No, skip to the next block. */
+ continue;
+ }
+
+ /* Get the interrupt number. */
+ interrupt = _GetNextInterrupt(Command, block);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): block = %d interrupt = %d\n",
+ __FUNCTION__, __LINE__,
+ block, interrupt
+ );
+
+ /* Determine the command position. */
+ eventCommand -= Command->info.eventCommandSize;
+
+ /* Append an EVENT command. */
+ gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
+ Command, eventCommand, block, interrupt, gcvNULL
+ ));
+ }
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+******************************** Memory Management *****************************
+\******************************************************************************/
+
+static gceSTATUS
+_HardwareToKernel(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM memory;
+ gctUINT32 offset;
+ gctUINT32 nodePhysical;
+ gctPOINTER *logical;
+ gctSIZE_T bytes;
+ status = gcvSTATUS_OK;
+
+ memory = Node->VidMem.memory;
+
+ if (memory->object.type == gcvOBJ_VIDMEM)
+ {
+ nodePhysical = memory->baseAddress
+ + (gctUINT32)Node->VidMem.offset
+ + Node->VidMem.alignment;
+ bytes = Node->VidMem.bytes;
+ logical = &Node->VidMem.kernelVirtual;
+ }
+ else
+ {
+ gcmkSAFECASTPHYSADDRT(nodePhysical, Node->Virtual.physicalAddress);
+ bytes = Node->Virtual.bytes;
+ logical = &Node->Virtual.kernelVirtual;
+ }
+
+ if (*logical == gcvNULL)
+ {
+ status = gckOS_MapPhysical(Os, nodePhysical, bytes, logical);
+
+ if (gcmkIS_ERROR(status))
+ {
+ return status;
+ }
+ }
+
+ offset = Address - nodePhysical;
+ *KernelPointer = (gctPOINTER)((gctUINT8_PTR)(*logical) + offset);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_ConvertUserCommandBufferPointer(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR UserCommandBuffer,
+ OUT gcsCMDBUFFER_PTR * KernelCommandBuffer
+ )
+{
+ gceSTATUS status, last;
+ gcsCMDBUFFER_PTR mappedUserCommandBuffer = gcvNULL;
+ gcsCMDBUFFER _CommandBufferObject;
+ gckKERNEL kernel = Command->kernel->kernel;
+ gctUINT32 pid;
+ gckVIDMEM_NODE node;
+ gctBOOL needCopy = gcvFALSE;
+
+ gckOS_GetProcessID(&pid);
+
+ do
+ {
+ gctUINT32 headerAddress;
+
+ gcmkERR_BREAK(gckOS_QueryNeedCopy(Command->os, pid, &needCopy));
+ if(needCopy)
+ {
+ gcmkERR_BREAK(gckOS_CopyFromUserData(
+ Command->os,
+ &_CommandBufferObject,
+ UserCommandBuffer,
+ gcmSIZEOF(gcsCMDBUFFER)
+ ));
+ mappedUserCommandBuffer = &_CommandBufferObject;
+ }
+ else
+ {
+ /* Map the command buffer structure into the kernel space. */
+ gcmkERR_BREAK(gckOS_MapUserPointer(
+ Command->os,
+ UserCommandBuffer,
+ gcmSIZEOF(gcsCMDBUFFER),
+ (gctPOINTER *) &mappedUserCommandBuffer
+ ));
+ }
+ /* Determine the address of the header. */
+ headerAddress
+ = mappedUserCommandBuffer->address
+ - mappedUserCommandBuffer->bufferOffset;
+
+ gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(
+ kernel,
+ pid,
+ gcmPTR2INT32(mappedUserCommandBuffer->node),
+ &node));
+
+ /* Translate the logical address to the kernel space. */
+ gcmkERR_BREAK(_HardwareToKernel(
+ Command->os,
+ node->node,
+ headerAddress,
+ (gctPOINTER *) KernelCommandBuffer
+ ));
+ }
+ while (gcvFALSE);
+
+ /* Unmap the user command buffer. */
+ if (mappedUserCommandBuffer != gcvNULL && needCopy == gcvFALSE)
+ {
+ gcmkCHECK_STATUS(gckOS_UnmapUserPointer(
+ Command->os,
+ UserCommandBuffer,
+ gcmSIZEOF(gcsCMDBUFFER),
+ mappedUserCommandBuffer
+ ));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_AllocateLinear(
+ IN gckVGCOMMAND Command,
+ IN gctUINT Size,
+ IN gctUINT Alignment,
+ OUT gcuVIDMEM_NODE_PTR * Node,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Logical
+ )
+{
+ gceSTATUS status, last;
+ gctPOINTER logical;
+ gctPHYS_ADDR physical;
+ gctUINT32 address;
+ gctSIZE_T size = Size;
+ gctPHYS_ADDR_T paddr;
+
+ do
+ {
+ gcmkERR_BREAK(gckOS_AllocateContiguous(
+ Command->os,
+ gcvFALSE,
+ &size,
+ &physical,
+ &logical
+ ));
+
+ gcmkERR_BREAK(gckOS_GetPhysicalAddress(Command->os, logical, &paddr));
+
+ gcmkSAFECASTPHYSADDRT(address, paddr);
+
+ /* Set return values. */
+ * Node = physical;
+ * Address = address;
+ * Logical = logical;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (physical != gcvNULL)
+ {
+ /* Free the command buffer. */
+ gcmkCHECK_STATUS(gckOS_FreeContiguous(Command->os, physical, logical, size));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_FreeLinear(
+ IN gckVGKERNEL Kernel,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctPOINTER Logical
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ do
+ {
+ gcmkERR_BREAK(gckOS_FreeContiguous(Kernel->os, Node, Logical, 1));
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+gceSTATUS
+_AllocateCommandBuffer(
+ IN gckVGCOMMAND Command,
+ IN gctSIZE_T Size,
+ OUT gcsCMDBUFFER_PTR * CommandBuffer
+ )
+{
+ gceSTATUS status, last;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gcsCMDBUFFER_PTR commandBuffer = gcvNULL;
+
+ do
+ {
+ gctUINT alignedHeaderSize;
+ gctUINT requestedSize;
+ gctUINT allocationSize;
+ gctUINT32 address = 0;
+ gctUINT8_PTR endCommand;
+
+ /* Determine the aligned header size. */
+ alignedHeaderSize
+ = (gctUINT32)gcmALIGN(gcmSIZEOF(gcsCMDBUFFER), Command->info.addressAlignment);
+
+ /* Align the requested size. */
+ requestedSize
+ = (gctUINT32)gcmALIGN(Size, Command->info.commandAlignment);
+
+ /* Determine the size of the buffer to allocate. */
+ allocationSize
+ = alignedHeaderSize
+ + requestedSize
+ + (gctUINT32)Command->info.staticTailSize;
+
+ /* Allocate the command buffer. */
+ gcmkERR_BREAK(_AllocateLinear(
+ Command,
+ allocationSize,
+ Command->info.addressAlignment,
+ &node,
+ &address,
+ (gctPOINTER *) &commandBuffer
+ ));
+
+ /* Initialize the structure. */
+ commandBuffer->completion = gcvVACANT_BUFFER;
+ commandBuffer->node = node;
+ commandBuffer->address = address + alignedHeaderSize;
+ commandBuffer->bufferOffset = alignedHeaderSize;
+ commandBuffer->size = requestedSize;
+ commandBuffer->offset = requestedSize;
+ commandBuffer->nextAllocated = gcvNULL;
+ commandBuffer->nextSubBuffer = gcvNULL;
+
+ /* Determine the data count. */
+ commandBuffer->dataCount
+ = (requestedSize + Command->info.staticTailSize)
+ / Command->info.commandAlignment;
+
+ /* Determine the location of the END command. */
+ endCommand
+ = (gctUINT8_PTR) commandBuffer
+ + alignedHeaderSize
+ + requestedSize;
+
+ /* Append an END command. */
+ gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+ Command,
+ endCommand,
+ Command->info.feBufferInt,
+ gcvNULL
+ ));
+
+ /* Set the return pointer. */
+ * CommandBuffer = commandBuffer;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (node != gcvNULL)
+ {
+ /* Free the command buffer. */
+ gcmkCHECK_STATUS(_FreeLinear(Command->kernel, node, commandBuffer));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_FreeCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ )
+{
+ gceSTATUS status;
+
+ /* Free the buffer. */
+ status = _FreeLinear(Kernel, CommandBuffer->node, CommandBuffer);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+****************************** TS Overflow Handler *****************************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_TSOverflow(
+ IN gckVGKERNEL Kernel
+ )
+{
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): **** TS OVERFLOW ENCOUNTERED ****\n",
+ __FUNCTION__, __LINE__
+ );
+
+ return gcvSTATUS_OK;
+}
+
+
+/******************************************************************************\
+****************************** Bus Error Handler *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_BusError(
+ IN gckVGKERNEL Kernel
+ )
+{
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): **** BUS ERROR ENCOUNTERED ****\n",
+ __FUNCTION__, __LINE__
+ );
+
+ return gcvSTATUS_OK;
+}
+
+/******************************************************************************\
+****************************** Power Stall Handler *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_PowerStall(
+ IN gckVGKERNEL Kernel
+ )
+{
+ /* Signal. */
+ return gckOS_Signal(
+ Kernel->os,
+ Kernel->command->powerStallSignal,
+ gcvTRUE);
+}
+
+/******************************************************************************\
+******************************** Task Routines *********************************
+\******************************************************************************/
+
+typedef gceSTATUS (* gctTASKROUTINE) (
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskLink(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskCluster(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskIncrement(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskDecrement(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskSignal(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskLockdown(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskUnlockVideoMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskFreeVideoMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskFreeContiguousMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gceSTATUS
+_TaskUnmapUserMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ );
+
+static gctTASKROUTINE _taskRoutine[] =
+{
+ _TaskLink, /* gcvTASK_LINK */
+ _TaskCluster, /* gcvTASK_CLUSTER */
+ _TaskIncrement, /* gcvTASK_INCREMENT */
+ _TaskDecrement, /* gcvTASK_DECREMENT */
+ _TaskSignal, /* gcvTASK_SIGNAL */
+ _TaskLockdown, /* gcvTASK_LOCKDOWN */
+ _TaskUnlockVideoMemory, /* gcvTASK_UNLOCK_VIDEO_MEMORY */
+ _TaskFreeVideoMemory, /* gcvTASK_FREE_VIDEO_MEMORY */
+ _TaskFreeContiguousMemory, /* gcvTASK_FREE_CONTIGUOUS_MEMORY */
+ _TaskUnmapUserMemory, /* gcvTASK_UNMAP_USER_MEMORY */
+};
+
+static gceSTATUS
+_TaskLink(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ /* Cast the task pointer. */
+ gcsTASK_LINK_PTR task = (gcsTASK_LINK_PTR) TaskHeader->task;
+
+ /* Save the pointer to the container. */
+ gcsTASK_CONTAINER_PTR container = TaskHeader->container;
+
+ /* No more tasks in the list? */
+ if (task->task == gcvNULL)
+ {
+ /* Reset the entry. */
+ TaskHeader->container = gcvNULL;
+ TaskHeader->task = gcvNULL;
+ TaskHeader->link = gcvNULL;
+ }
+ else
+ {
+ /* Update the entry. */
+ TaskHeader->container = task->cotainer;
+ TaskHeader->task = task->task;
+ }
+
+ /* Decrement the task buffer reference. */
+ gcmkASSERT(container->referenceCount >= 0);
+ if (container->referenceCount == 0)
+ {
+ /* Free the container. */
+ _FreeTaskContainer(Command, container);
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_TaskCluster(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ /* Cast the task pointer. */
+ gcsTASK_CLUSTER_PTR cluster = (gcsTASK_CLUSTER_PTR) TaskHeader->task;
+
+ /* Get the number of tasks. */
+ gctUINT taskCount = cluster->taskCount;
+
+ /* Advance to the next task. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (cluster + 1);
+
+ /* Perform all tasks in the cluster. */
+ while (taskCount)
+ {
+ /* Perform the current task. */
+ gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+ Command,
+ TaskHeader
+ ));
+
+ /* Update the task count. */
+ taskCount -= 1;
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskIncrement(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_INCREMENT_PTR task = (gcsTASK_INCREMENT_PTR) TaskHeader->task;
+
+ /* Convert physical into logical address. */
+ gctUINT32_PTR logical;
+ gcmkERR_BREAK(gckOS_MapPhysical(
+ Command->os,
+ task->address,
+ gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &logical
+ ));
+
+ /* Increment data. */
+ (* logical) += 1;
+
+ /* Unmap the physical memory. */
+ gcmkERR_BREAK(gckOS_UnmapPhysical(
+ Command->os,
+ logical,
+ gcmSIZEOF(gctUINT32)
+ ));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskDecrement(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_DECREMENT_PTR task = (gcsTASK_DECREMENT_PTR) TaskHeader->task;
+
+ /* Convert physical into logical address. */
+ gctUINT32_PTR logical;
+ gcmkERR_BREAK(gckOS_MapPhysical(
+ Command->os,
+ task->address,
+ gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &logical
+ ));
+
+ /* Decrement data. */
+ (* logical) -= 1;
+
+ /* Unmap the physical memory. */
+ gcmkERR_BREAK(gckOS_UnmapPhysical(
+ Command->os,
+ logical,
+ gcmSIZEOF(gctUINT32)
+ ));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskSignal(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_SIGNAL_PTR task = (gcsTASK_SIGNAL_PTR) TaskHeader->task;
+
+
+ /* Map the signal into kernel space. */
+#ifdef __QNXNTO__
+ status = gckOS_UserSignal(
+ Command->os, task->signal, task->rcvid, task->coid
+ );
+#else
+ status = gckOS_UserSignal(
+ Command->os, task->signal, task->process
+ );
+#endif /* __QNXNTO__ */
+
+ if (gcmIS_ERROR(status))
+ {
+ if (status == gcvSTATUS_NOT_FOUND)
+ {
+ status = gcvSTATUS_OK;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskLockdown(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+ gctUINT32_PTR userCounter = gcvNULL;
+ gctUINT32_PTR kernelCounter = gcvNULL;
+ gctSIGNAL signal = gcvNULL;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_LOCKDOWN_PTR task = (gcsTASK_LOCKDOWN_PTR) TaskHeader->task;
+
+ /* Convert physical addresses into logical. */
+ gcmkERR_BREAK(gckOS_MapPhysical(
+ Command->os,
+ task->userCounter,
+ gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &userCounter
+ ));
+
+ gcmkERR_BREAK(gckOS_MapPhysical(
+ Command->os,
+ task->kernelCounter,
+ gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &kernelCounter
+ ));
+
+ /* Update the kernel counter. */
+ (* kernelCounter) += 1;
+
+ /* Are the counters equal? */
+ if ((* userCounter) == (* kernelCounter))
+ {
+ /* Map the signal into kernel space. */
+ gcmkERR_BREAK(gckOS_MapSignal(
+ Command->os, task->signal, task->process, &signal
+ ));
+
+ if (signal == gcvNULL)
+ {
+ /* Signal. */
+ gcmkERR_BREAK(gckOS_Signal(
+ Command->os, task->signal, gcvTRUE
+ ));
+ }
+ else
+ {
+ /* Signal. */
+ gcmkERR_BREAK(gckOS_Signal(
+ Command->os, signal, gcvTRUE
+ ));
+ }
+ }
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Destroy the mapped signal. */
+ if (signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(
+ Command->os, signal
+ ));
+ }
+
+ /* Unmap the physical memory. */
+ if (kernelCounter != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapPhysical(
+ Command->os,
+ kernelCounter,
+ gcmSIZEOF(gctUINT32)
+ ));
+ }
+
+ if (userCounter != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapPhysical(
+ Command->os,
+ userCounter,
+ gcmSIZEOF(gctUINT32)
+ ));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskUnlockVideoMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_UNLOCK_VIDEO_MEMORY_PTR task
+ = (gcsTASK_UNLOCK_VIDEO_MEMORY_PTR) TaskHeader->task;
+
+ /* Unlock video memory. */
+ gcmkERR_BREAK(gckVIDMEM_Unlock(
+ Command->kernel->kernel,
+ (gckVIDMEM_NODE)gcmUINT64_TO_PTR(task->node),
+ gcvSURF_TYPE_UNKNOWN,
+ gcvNULL));
+
+ gcmkERR_BREAK(gckVIDMEM_NODE_Dereference(
+ Command->kernel->kernel,
+ gcmUINT64_TO_PTR(task->node)));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskFreeVideoMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_FREE_VIDEO_MEMORY_PTR task
+ = (gcsTASK_FREE_VIDEO_MEMORY_PTR) TaskHeader->task;
+
+ /* Free video memory. */
+ gcmkERR_BREAK(gckVIDMEM_NODE_Dereference(
+ Command->kernel->kernel,
+ gcmINT2PTR(task->node)));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskFreeContiguousMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR task
+ = (gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR) TaskHeader->task;
+
+ /* Free contiguous memory. */
+ gcmkERR_BREAK(gckOS_FreeContiguous(
+ Command->os, task->physical, task->logical, task->bytes
+ ));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_TaskUnmapUserMemory(
+ gckVGCOMMAND Command,
+ gcsBLOCK_TASK_ENTRY_PTR TaskHeader
+ )
+{
+ gceSTATUS status;
+ gctPOINTER info;
+
+ do
+ {
+ /* Cast the task pointer. */
+ gcsTASK_UNMAP_USER_MEMORY_PTR task
+ = (gcsTASK_UNMAP_USER_MEMORY_PTR) TaskHeader->task;
+
+ info = gckKERNEL_QueryPointerFromName(
+ Command->kernel->kernel, gcmALL_TO_UINT32(task->info));
+
+ /* Unmap the user memory. */
+ gcmkERR_BREAK(gckOS_UnmapUserMemory(
+ Command->os, gcvCORE_VG, task->memory, task->size, info, task->address
+ ));
+
+ /* Update the reference counter. */
+ TaskHeader->container->referenceCount -= 1;
+
+ /* Update the task pointer. */
+ TaskHeader->task = (gcsTASK_HEADER_PTR) (task + 1);
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+/******************************************************************************\
+************ Hardware Block Interrupt Handlers For Scheduled Events ************
+\******************************************************************************/
+
+static gceSTATUS
+_EventHandler_Block(
+ IN gckVGKERNEL Kernel,
+ IN gcsBLOCK_TASK_ENTRY_PTR TaskHeader,
+ IN gctBOOL ProcessAll
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK, last;
+
+ gcmkHEADER_ARG("Kernel=0x%x TaskHeader=0x%x ProcessAll=0x%x", Kernel, TaskHeader, ProcessAll);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (TaskHeader->task == gcvNULL)
+ {
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+ }
+
+ do
+ {
+ gckVGCOMMAND command;
+
+ /* Get the command buffer object. */
+ command = Kernel->command;
+
+ /* Increment the interrupt usage semaphore. */
+ gcmkERR_BREAK(gckOS_IncrementSemaphore(
+ command->os, TaskHeader->interruptSemaphore
+ ));
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ command->os,
+ command->taskMutex,
+ gcvINFINITE
+ ));
+
+ /* Verify inputs. */
+ gcmkASSERT(TaskHeader != gcvNULL);
+ gcmkASSERT(TaskHeader->container != gcvNULL);
+ gcmkASSERT(TaskHeader->task != gcvNULL);
+ gcmkASSERT(TaskHeader->link != gcvNULL);
+
+ /* Process tasks. */
+ do
+ {
+ /* Process the current task. */
+ gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+ command,
+ TaskHeader
+ ));
+
+ /* Is the next task is LINK? */
+ if (TaskHeader->task->id == gcvTASK_LINK)
+ {
+ gcmkERR_BREAK(_taskRoutine[TaskHeader->task->id](
+ command,
+ TaskHeader
+ ));
+
+ /* Done. */
+ break;
+ }
+ }
+ while (ProcessAll);
+
+ /* Release the mutex. */
+ gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+ command->os,
+ command->taskMutex
+ ));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+gcmDECLARE_INTERRUPT_HANDLER(COMMAND, 0)
+{
+ gceSTATUS status, last;
+
+ gcmkHEADER_ARG("Kernel=0x%x ", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+
+ do
+ {
+ gckVGCOMMAND command;
+ gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
+ gcsKERNEL_QUEUE_HEADER_PTR queueTail;
+ gcsKERNEL_CMDQUEUE_PTR entry;
+ gctUINT entryCount;
+
+ /* Get the command buffer object. */
+ command = Kernel->command;
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ command->os,
+ command->queueMutex,
+ gcvINFINITE
+ ));
+
+ /* Get the current queue. */
+ queueTail = command->queueTail;
+
+ /* Get the current queue entry. */
+ entry = queueTail->currentEntry;
+
+ /* Get the number of entries in the queue. */
+ entryCount = queueTail->pending;
+
+ /* Process all entries. */
+ while (entryCount > 0)
+ {
+ /* Call post-execution function. */
+ status = entry->handler(Kernel, entry);
+
+ /* Failed? */
+ if (gcmkIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR,
+ gcvZONE_COMMAND,
+ "[%s] line %d: post action failed.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+
+ /* Executed the next buffer? */
+ if (status == gcvSTATUS_EXECUTED)
+ {
+ /* Update the queue. */
+ queueTail->pending = entryCount;
+ queueTail->currentEntry = entry;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+
+ /* Break out of the loop. */
+ break;
+ }
+
+ /* Advance to the next entry. */
+ entry += 1;
+ entryCount -= 1;
+
+ /* Last entry? */
+ if (entryCount == 0)
+ {
+ /* Reset the queue to idle. */
+ queueTail->pending = 0;
+
+ /* Get a shortcut to the queue to merge with. */
+ mergeQueue = command->mergeQueue;
+
+ /* Merge the queues if necessary. */
+ if (mergeQueue != queueTail)
+ {
+ gcmkASSERT(mergeQueue < queueTail);
+ gcmkASSERT(mergeQueue->next == queueTail);
+
+ mergeQueue->size
+ += gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+ + queueTail->size;
+
+ mergeQueue->next = queueTail->next;
+ }
+
+ /* Advance to the next queue. */
+ queueTail = queueTail->next;
+
+ /* Did it wrap around? */
+ if (command->queue == queueTail)
+ {
+ /* Reset merge queue. */
+ command->mergeQueue = queueTail;
+ }
+
+ /* Set new queue. */
+ command->queueTail = queueTail;
+
+ /* Is the next queue scheduled? */
+ if (queueTail->pending > 0)
+ {
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* The first entry must be a command buffer. */
+ commandBuffer = queueTail->currentEntry->commandBuffer;
+
+ /* Start the command processor. */
+ status = gckVGHARDWARE_Execute(
+ command->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Failed? */
+ if (gcmkIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR,
+ gcvZONE_COMMAND,
+ "[%s] line %d: failed to start the next queue.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+ }
+ else
+ {
+ status = gckVGHARDWARE_SetPowerManagementState(
+ Kernel->command->hardware, gcvPOWER_IDLE_BROADCAST
+ );
+ }
+
+ /* Break out of the loop. */
+ break;
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+ command->os,
+ command->queueMutex
+ ));
+ }
+ while (gcvFALSE);
+
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+/* Define standard block interrupt handlers. */
+gcmDEFINE_INTERRUPT_HANDLER(TESSELLATOR, 0)
+gcmDEFINE_INTERRUPT_HANDLER(VG, 0)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 0)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 1)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 2)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 3)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 4)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 5)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 6)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 7)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 8)
+gcmDEFINE_INTERRUPT_HANDLER(PIXEL, 9)
+
+/* The entries in the array are arranged by event priority. */
+static gcsBLOCK_INTERRUPT_HANDLER _blockHandlers[] =
+{
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(TESSELLATOR, 0),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(VG, 0),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 0),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 1),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 2),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 3),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 4),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 5),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 6),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 7),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 8),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(PIXEL, 9),
+ gcmDEFINE_INTERRUPT_HANDLER_ENTRY(COMMAND, 0),
+};
+
+
+/******************************************************************************\
+************************* Static Command Buffer Handlers ***********************
+\******************************************************************************/
+
+static gceSTATUS
+_UpdateStaticCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d)\n",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_ExecuteStaticCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* Cast the command buffer header. */
+ commandBuffer = Entry->commandBuffer;
+
+ /* Set to update the command buffer next time. */
+ Entry->handler = _UpdateStaticCommandBuffer;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+ __FUNCTION__, __LINE__,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Kernel->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+
+ /* Success. */
+ return gcvSTATUS_EXECUTED;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_UpdateLastStaticCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+#if gcvDEBUG || gcdFORCE_MESSAGES
+ /* Get the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Validate the command buffer. */
+ gcmkASSERT(commandBuffer->completion != gcvNULL);
+ gcmkASSERT(commandBuffer->completion != gcvVACANT_BUFFER);
+
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): processing all tasks scheduled for FE.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Perform scheduled tasks. */
+ return _EventHandler_Block(
+ Kernel,
+ &Kernel->command->taskTable[gcvBLOCK_COMMAND],
+ gcvTRUE
+ );
+}
+
+static gceSTATUS
+_ExecuteLastStaticCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Set to update the command buffer next time. */
+ Entry->handler = _UpdateLastStaticCommandBuffer;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+ __FUNCTION__, __LINE__,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Kernel->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+
+ /* Success. */
+ return gcvSTATUS_EXECUTED;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+************************* Dynamic Command Buffer Handlers **********************
+\******************************************************************************/
+
+static gceSTATUS
+_UpdateDynamicCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d)\n",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_ExecuteDynamicCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Set to update the command buffer next time. */
+ Entry->handler = _UpdateDynamicCommandBuffer;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+ __FUNCTION__, __LINE__,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Kernel->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+
+ /* Success. */
+ return gcvSTATUS_EXECUTED;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_UpdateLastDynamicCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+#if gcvDEBUG || gcdFORCE_MESSAGES
+ /* Get the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Validate the command buffer. */
+ gcmkASSERT(commandBuffer->completion != gcvNULL);
+ gcmkASSERT(commandBuffer->completion != gcvVACANT_BUFFER);
+
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): processing all tasks scheduled for FE.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Perform scheduled tasks. */
+ return _EventHandler_Block(
+ Kernel,
+ &Kernel->command->taskTable[gcvBLOCK_COMMAND],
+ gcvTRUE
+ );
+}
+
+static gceSTATUS
+_ExecuteLastDynamicCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Cast the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = Entry->commandBuffer;
+
+ /* Set to update the command buffer next time. */
+ Entry->handler = _UpdateLastDynamicCommandBuffer;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s(%d): executing next buffer @ 0x%08X, data count = %d\n",
+ __FUNCTION__, __LINE__,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ );
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Kernel->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+
+ /* Success. */
+ return gcvSTATUS_EXECUTED;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+********************************* Other Handlers *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_FreeKernelCommandBuffer(
+ IN gckVGKERNEL Kernel,
+ IN gcsKERNEL_CMDQUEUE_PTR Entry
+ )
+{
+ gceSTATUS status;
+
+ /* Free the command buffer. */
+ status = _FreeCommandBuffer(Kernel, Entry->commandBuffer);
+
+ /* Return status. */
+ return status;
+}
+
+
+/******************************************************************************\
+******************************* Queue Management *******************************
+\******************************************************************************/
+
+#if gcvDUMP_COMMAND_BUFFER
+static void
+_DumpCommandQueue(
+ IN gckVGCOMMAND Command,
+ IN gcsKERNEL_QUEUE_HEADER_PTR QueueHeader,
+ IN gctUINT EntryCount
+ )
+{
+ gcsKERNEL_CMDQUEUE_PTR entry;
+ gctUINT queueIndex;
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ static gctUINT arrayCount = 0;
+#endif
+
+ /* Is dumpinng enabled? */
+ if (!Commad->enableDumping)
+ {
+ return;
+ }
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ "COMMAND QUEUE DUMP: %d entries\n", EntryCount
+ );
+#endif
+
+ /* Get the pointer to the first entry. */
+ entry = QueueHeader->currentEntry;
+
+ /* Iterate through the queue. */
+ for (queueIndex = 0; queueIndex < EntryCount; queueIndex += 1)
+ {
+ gcsCMDBUFFER_PTR buffer;
+ gctUINT bufferCount;
+ gctUINT bufferIndex;
+ gctUINT i, count;
+ gctUINT size;
+ gctUINT32_PTR data;
+
+#if gcvDUMP_COMMAND_LINES
+ gctUINT lineNumber;
+#endif
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_COMMAND,
+ "ENTRY %d\n", queueIndex
+ );
+#endif
+
+ /* Reset the count. */
+ bufferCount = 0;
+
+ /* Set the initial buffer. */
+ buffer = entry->commandBuffer;
+
+ /* Loop through all subbuffers. */
+ while (buffer)
+ {
+ /* Update the count. */
+ bufferCount += 1;
+
+ /* Advance to the next subbuffer. */
+ buffer = buffer->nextSubBuffer;
+ }
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+ if (bufferCount > 1)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ " COMMAND BUFFER SET: %d buffers.\n",
+ bufferCount
+ );
+ }
+#endif
+
+ /* Reset the buffer index. */
+ bufferIndex = 0;
+
+ /* Set the initial buffer. */
+ buffer = entry->commandBuffer;
+
+ /* Loop through all subbuffers. */
+ while (buffer)
+ {
+ /* Determine the size of the buffer. */
+ size = buffer->dataCount * Command->info.commandAlignment;
+
+#if !defined(gcvCOMMAND_BUFFER_NAME)
+ /* A single buffer? */
+ if (bufferCount == 1)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ " COMMAND BUFFER: count=%d (0x%X), size=%d bytes @ %08X.\n",
+ buffer->dataCount,
+ buffer->dataCount,
+ size,
+ buffer->address
+ );
+ }
+ else
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ " COMMAND BUFFER %d: count=%d (0x%X), size=%d bytes @ %08X\n",
+ bufferIndex,
+ buffer->dataCount,
+ buffer->dataCount,
+ size,
+ buffer->address
+ );
+ }
+#endif
+
+ /* Determine the number of double words to print. */
+ count = size / 4;
+
+ /* Determine the buffer location. */
+ data = (gctUINT32_PTR)
+ (
+ (gctUINT8_PTR) buffer + buffer->bufferOffset
+ );
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ "unsigned int _" gcvCOMMAND_BUFFER_NAME "_%d[] =\n",
+ arrayCount
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ "{\n"
+ );
+
+ arrayCount += 1;
+#endif
+
+#if gcvDUMP_COMMAND_LINES
+ /* Reset the line number. */
+ lineNumber = 0;
+#endif
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ count -= 2;
+#endif
+
+ for (i = 0; i < count; i += 1)
+ {
+ if ((i % 8) == 0)
+ {
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "\t");
+#else
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, " ");
+#endif
+ }
+
+#if gcvDUMP_COMMAND_LINES
+ if (lineNumber == gcvDUMP_COMMAND_LINES)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, " . . . . . . . . .\n");
+ break;
+ }
+#endif
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "0x%08X", data[i]);
+
+ if (i + 1 == count)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, "\n");
+
+#if gcvDUMP_COMMAND_LINES
+ lineNumber += 1;
+#endif
+ }
+ else
+ {
+ if (((i + 1) % 8) == 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, ",\n");
+
+#if gcvDUMP_COMMAND_LINES
+ lineNumber += 1;
+#endif
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_COMMAND, ", ");
+ }
+ }
+ }
+
+#if defined(gcvCOMMAND_BUFFER_NAME)
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO,
+ gcvZONE_COMMAND,
+ "};\n\n"
+ );
+#endif
+
+ /* Advance to the next subbuffer. */
+ buffer = buffer->nextSubBuffer;
+ bufferIndex += 1;
+ }
+
+ /* Advance to the next entry. */
+ entry += 1;
+ }
+}
+#endif
+
+static gceSTATUS
+_LockCurrentQueue(
+ IN gckVGCOMMAND Command,
+ OUT gcsKERNEL_CMDQUEUE_PTR * Entries,
+ OUT gctUINT_PTR EntryCount
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gcsKERNEL_QUEUE_HEADER_PTR queueHead;
+
+ /* Get a shortcut to the head of the queue. */
+ queueHead = Command->queueHead;
+
+ /* Is the head buffer still being worked on? */
+ if (queueHead->pending)
+ {
+ /* Increment overflow count. */
+ Command->queueOverflow += 1;
+
+ /* Wait until the head becomes idle. */
+ gcmkERR_BREAK(_WaitForIdle(Command, queueHead));
+ }
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ Command->os,
+ Command->queueMutex,
+ gcvINFINITE
+ ));
+
+ /* Determine the first queue entry. */
+ queueHead->currentEntry = (gcsKERNEL_CMDQUEUE_PTR)
+ (
+ (gctUINT8_PTR) queueHead + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+ );
+
+ /* Set the pointer to the first entry. */
+ * Entries = queueHead->currentEntry;
+
+ /* Determine the number of available entries. */
+ * EntryCount = queueHead->size / gcmSIZEOF(gcsKERNEL_CMDQUEUE);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+static gceSTATUS
+_UnlockCurrentQueue(
+ IN gckVGCOMMAND Command,
+ IN gctUINT EntryCount
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+#if !gcdENABLE_INFINITE_SPEED_HW
+ gcsKERNEL_QUEUE_HEADER_PTR queueTail;
+ gcsKERNEL_QUEUE_HEADER_PTR queueHead;
+ gcsKERNEL_QUEUE_HEADER_PTR queueNext;
+ gctUINT queueSize;
+ gctUINT newSize;
+ gctUINT unusedSize;
+
+ /* Get shortcut to the head and to the tail of the queue. */
+ queueTail = Command->queueTail;
+ queueHead = Command->queueHead;
+
+ /* Dump the command buffer. */
+#if gcvDUMP_COMMAND_BUFFER
+ _DumpCommandQueue(Command, queueHead, EntryCount);
+#endif
+
+ /* Get a shortcut to the current queue size. */
+ queueSize = queueHead->size;
+
+ /* Determine the new queue size. */
+ newSize = EntryCount * gcmSIZEOF(gcsKERNEL_CMDQUEUE);
+ gcmkASSERT(newSize <= queueSize);
+
+ /* Determine the size of the unused area. */
+ unusedSize = queueSize - newSize;
+
+ /* Is the unused area big enough to become a buffer? */
+ if (unusedSize >= gcvMINUMUM_BUFFER)
+ {
+ gcsKERNEL_QUEUE_HEADER_PTR nextHead;
+
+ /* Place the new header. */
+ nextHead = (gcsKERNEL_QUEUE_HEADER_PTR)
+ (
+ (gctUINT8_PTR) queueHead
+ + gcmSIZEOF(gcsKERNEL_QUEUE_HEADER)
+ + newSize
+ );
+
+ /* Initialize the buffer. */
+ nextHead->size = unusedSize - gcmSIZEOF(gcsKERNEL_QUEUE_HEADER);
+ nextHead->pending = 0;
+
+ /* Link the buffer in. */
+ nextHead->next = queueHead->next;
+ queueHead->next = nextHead;
+ queueNext = nextHead;
+
+ /* Update the size of the current buffer. */
+ queueHead->size = newSize;
+ }
+
+ /* Not big enough. */
+ else
+ {
+ /* Determine the next queue. */
+ queueNext = queueHead->next;
+ }
+
+ /* Mark the buffer as busy. */
+ queueHead->pending = EntryCount;
+
+ /* Advance to the next buffer. */
+ Command->queueHead = queueNext;
+
+ /* Start the command processor if the queue was empty. */
+ if (queueTail == queueHead)
+ {
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* The first entry must be a command buffer. */
+ commandBuffer = queueTail->currentEntry->commandBuffer;
+
+ /* Start the command processor. */
+ gcmkERR_BREAK(gckVGHARDWARE_Execute(
+ Command->hardware,
+ commandBuffer->address,
+ commandBuffer->dataCount
+ ));
+ }
+
+ /* The queue was not empty. */
+ else
+ {
+ /* Advance the merge buffer if needed. */
+ if (queueHead == Command->mergeQueue)
+ {
+ Command->mergeQueue = queueNext;
+ }
+ }
+#endif
+
+ /* Release the mutex. */
+ gcmkERR_BREAK(gckOS_ReleaseMutex(
+ Command->os,
+ Command->queueMutex
+ ));
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+
+
+/******************************************************************************\
+****************************** gckVGCOMMAND API Code *****************************
+\******************************************************************************/
+gceSTATUS
+gckVGCOMMAND_Construct(
+ IN gckVGKERNEL Kernel,
+ IN gctUINT TaskGranularity,
+ IN gctUINT QueueSize,
+ OUT gckVGCOMMAND * Command
+ )
+{
+ gceSTATUS status, last;
+ gckVGCOMMAND command = gcvNULL;
+ gcsKERNEL_QUEUE_HEADER_PTR queue;
+ gctUINT i, j;
+
+ gcmkHEADER_ARG("Kernel=0x%x TaskGranularity=0x%x QueueSize=0x%x Command=0x%x",
+ Kernel, TaskGranularity, QueueSize, Command);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(QueueSize >= gcvMINUMUM_BUFFER);
+ gcmkVERIFY_ARGUMENT(Command != gcvNULL);
+
+ do
+ {
+ /***********************************************************************
+ ** Generic object initialization.
+ */
+
+ /* Allocate the gckVGCOMMAND structure. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Kernel->os,
+ gcmSIZEOF(struct _gckVGCOMMAND),
+ (gctPOINTER *) &command
+ ));
+
+ /* Initialize the object. */
+ command->object.type = gcvOBJ_COMMAND;
+
+ /* Set the object pointers. */
+ command->kernel = Kernel;
+ command->os = Kernel->os;
+ command->hardware = Kernel->hardware;
+
+ /* Reset pointers. */
+ command->queue = gcvNULL;
+ command->queueMutex = gcvNULL;
+ command->taskMutex = gcvNULL;
+ command->commitMutex = gcvNULL;
+
+ command->powerStallBuffer = gcvNULL;
+ command->powerStallSignal = gcvNULL;
+ command->powerSemaphore = gcvNULL;
+
+ /* Reset context states. */
+ command->contextCounter = 0;
+ command->currentContext = 0;
+
+ /* Enable command buffer dumping. */
+ command->enableDumping = gcvTRUE;
+
+ /* Set features. */
+ command->fe20 = Kernel->hardware->fe20;
+ command->vg20 = Kernel->hardware->vg20;
+ command->vg21 = Kernel->hardware->vg21;
+
+ /* Reset task table .*/
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ command->taskTable, gcmSIZEOF(command->taskTable)
+ ));
+
+ /* Query command buffer attributes. */
+ gcmkERR_BREAK(gckVGCOMMAND_InitializeInfo(command));
+
+ /* Create the control mutexes. */
+ gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->queueMutex));
+ gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->taskMutex));
+ gcmkERR_BREAK(gckOS_CreateMutex(Kernel->os, &command->commitMutex));
+
+ /* Create the power management semaphore. */
+ gcmkERR_BREAK(gckOS_CreateSemaphore(Kernel->os,
+ &command->powerSemaphore));
+
+ gcmkERR_BREAK(gckOS_CreateSignal(Kernel->os,
+ gcvFALSE, &command->powerStallSignal));
+
+ /***********************************************************************
+ ** Command queue initialization.
+ */
+
+ /* Allocate the command queue. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Kernel->os,
+ QueueSize,
+ (gctPOINTER *) &command->queue
+ ));
+
+ /* Initialize the command queue. */
+ queue = command->queue;
+
+ queue->size = QueueSize - gcmSIZEOF(gcsKERNEL_QUEUE_HEADER);
+ queue->pending = 0;
+ queue->next = queue;
+
+ command->queueHead =
+ command->queueTail =
+ command->mergeQueue = command->queue;
+
+ command->queueOverflow = 0;
+
+
+ /***********************************************************************
+ ** Enable TS overflow interrupt.
+ */
+
+ command->info.tsOverflowInt = 0;
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+ Kernel->interrupt,
+ &command->info.tsOverflowInt,
+ _EventHandler_TSOverflow
+ ));
+
+ /* Mask out the interrupt. */
+ /* Kernel->hardware->eventMask &= ~(1 << command->info.tsOverflowInt); */
+
+
+ /***********************************************************************
+ ** Enable Bus Error interrupt.
+ */
+
+ /* Hardwired to bit 31. */
+ command->busErrorInt = 31;
+
+ /* Enable the interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+ Kernel->interrupt,
+ &command->busErrorInt,
+ _EventHandler_BusError
+ ));
+
+
+ command->powerStallInt = 30;
+ /* Enable the interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+ Kernel->interrupt,
+ &command->powerStallInt,
+ _EventHandler_PowerStall
+ ));
+
+ /***********************************************************************
+ ** Task management initialization.
+ */
+
+ command->taskStorage = gcvNULL;
+ command->taskStorageGranularity = TaskGranularity;
+ command->taskStorageUsable = TaskGranularity - gcmSIZEOF(gcsTASK_STORAGE);
+
+ command->taskFreeHead = gcvNULL;
+ command->taskFreeTail = gcvNULL;
+
+ /* Enable block handlers. */
+ for (i = 0; i < gcmCOUNTOF(_blockHandlers); i += 1)
+ {
+ /* Get the target hardware block. */
+ gceBLOCK block = _blockHandlers[i].block;
+
+ /* Get the interrupt array entry. */
+ gcsBLOCK_TASK_ENTRY_PTR entry = &command->taskTable[block];
+
+ /* Determine the interrupt value index. */
+ gctUINT index = entry->interruptCount;
+
+ /* Create the block semaphore. */
+ if (entry->interruptSemaphore == gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
+ command->os, &entry->interruptSemaphore
+ ));
+ }
+
+ /* Enable auto-detection. */
+ entry->interruptArray[index] = -1;
+
+ /* Enable interrupt for the block. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+ Kernel->interrupt,
+ &entry->interruptArray[index],
+ _blockHandlers[i].handler
+ ));
+
+ /* Update the number of registered interrupts. */
+ entry->interruptCount += 1;
+
+ /* Inrement the semaphore to allow the usage of the registered
+ interrupt. */
+ gcmkERR_BREAK(gckOS_IncrementSemaphore(
+ command->os, entry->interruptSemaphore
+ ));
+
+ }
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+
+ /* Get the FE interrupt. */
+ command->info.feBufferInt
+ = command->taskTable[gcvBLOCK_COMMAND].interruptArray[0];
+
+ /* Return gckVGCOMMAND object pointer. */
+ *Command = command;
+
+ gcmkFOOTER_ARG("*Command=0x%x",*Command);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (command != gcvNULL)
+ {
+ /* Disable block handlers. */
+ for (i = 0; i < gcvBLOCK_COUNT; i += 1)
+ {
+ /* Get the task table entry. */
+ gcsBLOCK_TASK_ENTRY_PTR entry = &command->taskTable[i];
+
+ /* Destroy the semaphore. */
+ if (entry->interruptSemaphore != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DestroySemaphore(
+ command->os, entry->interruptSemaphore
+ ));
+ }
+
+ /* Disable all enabled interrupts. */
+ for (j = 0; j < entry->interruptCount; j += 1)
+ {
+ /* Must be a valid value. */
+ gcmkASSERT(entry->interruptArray[j] >= 0);
+ gcmkASSERT(entry->interruptArray[j] <= 31);
+
+ /* Disable the interrupt. */
+ gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+ Kernel->interrupt,
+ entry->interruptArray[j]
+ ));
+ }
+ }
+
+ /* Disable the bus error interrupt. */
+ gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+ Kernel->interrupt,
+ command->busErrorInt
+ ));
+
+ /* Disable TS overflow interrupt. */
+ if (command->info.tsOverflowInt != -1)
+ {
+ gcmkCHECK_STATUS(gckVGINTERRUPT_Disable(
+ Kernel->interrupt,
+ command->info.tsOverflowInt
+ ));
+ }
+
+ /* Delete the commit mutex. */
+ if (command->commitMutex != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DeleteMutex(
+ Kernel->os, command->commitMutex
+ ));
+ }
+
+ /* Delete the command queue mutex. */
+ if (command->taskMutex != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DeleteMutex(
+ Kernel->os, command->taskMutex
+ ));
+ }
+
+ /* Delete the command queue mutex. */
+ if (command->queueMutex != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DeleteMutex(
+ Kernel->os, command->queueMutex
+ ));
+ }
+
+ /* Delete the command queue. */
+ if (command->queue != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_Free(
+ Kernel->os, command->queue
+ ));
+ }
+
+ if (command->powerSemaphore != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(
+ Kernel->os, command->powerSemaphore));
+ }
+
+ if (command->powerStallSignal != gcvNULL)
+ {
+ /* Create the power management semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySignal(
+ Kernel->os,
+ command->powerStallSignal));
+ }
+
+ /* Free the gckVGCOMMAND structure. */
+ gcmkCHECK_STATUS(gckOS_Free(
+ Kernel->os, command
+ ));
+ }
+
+ gcmkFOOTER();
+ /* Return the error. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Destroy(
+ OUT gckVGCOMMAND Command
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ do
+ {
+ gctUINT i;
+ gcsTASK_STORAGE_PTR nextStorage;
+
+ if (Command->queueHead != gcvNULL)
+ {
+ /* Wait until the head becomes idle. */
+ gcmkERR_BREAK(_WaitForIdle(Command, Command->queueHead));
+ }
+
+ /* Disable block handlers. */
+ for (i = 0; i < gcvBLOCK_COUNT; i += 1)
+ {
+ /* Get the interrupt array entry. */
+ gcsBLOCK_TASK_ENTRY_PTR entry = &Command->taskTable[i];
+
+ /* Determine the index of the last interrupt in the array. */
+ gctINT index = entry->interruptCount - 1;
+
+ /* Destroy the semaphore. */
+ if (entry->interruptSemaphore != gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_DestroySemaphore(
+ Command->os, entry->interruptSemaphore
+ ));
+ }
+
+ /* Disable all enabled interrupts. */
+ while (index >= 0)
+ {
+ /* Must be a valid value. */
+ gcmkASSERT(entry->interruptArray[index] >= 0);
+ gcmkASSERT(entry->interruptArray[index] <= 31);
+
+ /* Disable the interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+ Command->kernel->interrupt,
+ entry->interruptArray[index]
+ ));
+
+ /* Update to the next interrupt. */
+ index -= 1;
+ entry->interruptCount -= 1;
+ }
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+ }
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+
+ /* Disable the bus error interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+ Command->kernel->interrupt,
+ Command->busErrorInt
+ ));
+
+ /* Disable TS overflow interrupt. */
+ if (Command->info.tsOverflowInt != -1)
+ {
+ gcmkERR_BREAK(gckVGINTERRUPT_Disable(
+ Command->kernel->interrupt,
+ Command->info.tsOverflowInt
+ ));
+
+ Command->info.tsOverflowInt = -1;
+ }
+
+ /* Delete the commit mutex. */
+ if (Command->commitMutex != gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_DeleteMutex(
+ Command->os, Command->commitMutex
+ ));
+
+ Command->commitMutex = gcvNULL;
+ }
+
+ /* Delete the command queue mutex. */
+ if (Command->taskMutex != gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_DeleteMutex(
+ Command->os, Command->taskMutex
+ ));
+
+ Command->taskMutex = gcvNULL;
+ }
+
+ /* Delete the command queue mutex. */
+ if (Command->queueMutex != gcvNULL)
+ {
+ gcmkERR_BREAK(gckOS_DeleteMutex(
+ Command->os, Command->queueMutex
+ ));
+
+ Command->queueMutex = gcvNULL;
+ }
+
+ if (Command->powerSemaphore != gcvNULL)
+ {
+ /* Destroy the power management semaphore. */
+ gcmkERR_BREAK(gckOS_DestroySemaphore(
+ Command->os, Command->powerSemaphore));
+ }
+
+ if (Command->powerStallSignal != gcvNULL)
+ {
+ /* Create the power management semaphore. */
+ gcmkERR_BREAK(gckOS_DestroySignal(
+ Command->os,
+ Command->powerStallSignal));
+ }
+
+ if (Command->queue != gcvNULL)
+ {
+ /* Delete the command queue. */
+ gcmkERR_BREAK(gckOS_Free(
+ Command->os, Command->queue
+ ));
+ }
+
+ /* Destroy all allocated buffers. */
+ while (Command->taskStorage)
+ {
+ /* Copy the buffer pointer. */
+ nextStorage = Command->taskStorage->next;
+
+ /* Free the current container. */
+ gcmkERR_BREAK(gckOS_Free(
+ Command->os, Command->taskStorage
+ ));
+
+ /* Advance to the next one. */
+ Command->taskStorage = nextStorage;
+ }
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+
+ /* Mark the object as unknown. */
+ Command->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVGCOMMAND structure. */
+ gcmkERR_BREAK(gckOS_Free(Command->os, Command));
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Restore the object type if failed. */
+ Command->object.type = gcvOBJ_COMMAND;
+
+ gcmkFOOTER();
+ /* Return the error. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_QueryCommandBuffer(
+ IN gckVGCOMMAND Command,
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ )
+{
+ gcmkHEADER_ARG("Command=0x%x Information=0x%x", Command, Information);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(Information != gcvNULL);
+
+ /* Copy the information. */
+ gcmkVERIFY_OK(gckOS_MemCopy(
+ Information, &Command->info, sizeof(gcsCOMMAND_BUFFER_INFO)
+ ));
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGCOMMAND_Allocate(
+ IN gckVGCOMMAND Command,
+ IN gctSIZE_T Size,
+ OUT gcsCMDBUFFER_PTR * CommandBuffer,
+ OUT gctPOINTER * Data
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x Size=0x%x CommandBuffer=0x%x Data=0x%x",
+ Command, Size, CommandBuffer, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ do
+ {
+ /* Allocate the buffer. */
+ gcmkERR_BREAK(_AllocateCommandBuffer(Command, Size, CommandBuffer));
+
+ /* Determine the data pointer. */
+ * Data = (gctUINT8_PTR) (*CommandBuffer) + (* CommandBuffer)->bufferOffset;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Free(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x",
+ Command, CommandBuffer);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(CommandBuffer != gcvNULL);
+
+ /* Free command buffer. */
+ status = _FreeCommandBuffer(Command->kernel, CommandBuffer);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Execute(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x",
+ Command, CommandBuffer);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(CommandBuffer != gcvNULL);
+
+ do
+ {
+ gctUINT queueLength;
+ gcsKERNEL_CMDQUEUE_PTR kernelEntry;
+
+ /* Lock the current queue. */
+ gcmkERR_BREAK(_LockCurrentQueue(
+ Command, &kernelEntry, &queueLength
+ ));
+
+ /* Set the buffer. */
+ kernelEntry->commandBuffer = CommandBuffer;
+ kernelEntry->handler = _FreeKernelCommandBuffer;
+
+ /* Lock the current queue. */
+ gcmkERR_BREAK(_UnlockCurrentQueue(
+ Command, 1
+ ));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+gceSTATUS
+gckVGCOMMAND_Commit(
+ IN gckVGCOMMAND Command,
+ IN gcsVGCONTEXT_PTR Context,
+ IN gcsVGCMDQUEUE_PTR Queue,
+ IN gctUINT EntryCount,
+ IN gcsTASK_MASTER_TABLE_PTR TaskTable
+ )
+{
+ /*
+ The first buffer is executed through a direct gckVGHARDWARE_Execute call,
+ therefore only an update is needed after the execution is over. All
+ consequent buffers need to be executed upon the first update call from
+ the FE interrupt handler.
+ */
+ static gcsQUEUE_UPDATE_CONTROL _dynamicBuffer[] =
+ {
+ {
+ _UpdateDynamicCommandBuffer,
+ _UpdateDynamicCommandBuffer,
+ _UpdateLastDynamicCommandBuffer,
+ _UpdateLastDynamicCommandBuffer
+ },
+ {
+ _ExecuteDynamicCommandBuffer,
+ _UpdateDynamicCommandBuffer,
+ _ExecuteLastDynamicCommandBuffer,
+ _UpdateLastDynamicCommandBuffer
+ }
+ };
+
+ static gcsQUEUE_UPDATE_CONTROL _staticBuffer[] =
+ {
+ {
+ _UpdateStaticCommandBuffer,
+ _UpdateStaticCommandBuffer,
+ _UpdateLastStaticCommandBuffer,
+ _UpdateLastStaticCommandBuffer
+ },
+ {
+ _ExecuteStaticCommandBuffer,
+ _UpdateStaticCommandBuffer,
+ _ExecuteLastStaticCommandBuffer,
+ _UpdateLastStaticCommandBuffer
+ }
+ };
+
+ gceSTATUS status, last;
+ struct _gcsTASK_MASTER_TABLE _TaskTable;
+#ifdef __QNXNTO__
+ gcsVGCONTEXT_PTR userContext = gcvNULL;
+ gctBOOL userContextMapped = gcvFALSE;
+ gcsTASK_MASTER_TABLE_PTR userTaskTable = gcvNULL;
+ gctBOOL userTaskTableMapped = gcvFALSE;
+ gctPOINTER pointer = gcvNULL;
+#endif
+ struct _gcsVGCONTEXT _Context;
+ gctBOOL needCopy = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x Context=0x%x Queue=0x%x EntryCount=0x%x TaskTable=0x%x",
+ Command, Context, Queue, EntryCount, TaskTable);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+ gcmkVERIFY_ARGUMENT(Context != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+ gcmkVERIFY_ARGUMENT(EntryCount > 1);
+
+ do
+ {
+ gctBOOL haveFETasks;
+ gctUINT queueSize = 0;
+ gcsVGCMDQUEUE_PTR mappedQueue=gcvNULL;
+ gcsVGCMDQUEUE_PTR userEntry=gcvNULL;
+ gcsKERNEL_CMDQUEUE_PTR kernelEntry;
+ gcsQUEUE_UPDATE_CONTROL_PTR queueControl;
+ gctUINT currentLength;
+ gctUINT queueLength;
+ gctUINT entriesQueued;
+ gctUINT8_PTR previousEnd;
+ gctBOOL previousDynamic;
+ gctBOOL previousExecuted;
+ gctUINT controlIndex;
+ gctINT pid;
+#ifdef __QNXNTO__
+ /* Map the context into the kernel space. */
+ userContext = Context;
+
+ gcmkERR_BREAK(gckOS_MapUserPointer(
+ Command->os,
+ userContext,
+ gcmSIZEOF(*userContext),
+ &pointer));
+
+ Context = pointer;
+
+ userContextMapped = gcvTRUE;
+
+ /* Map the taskTable into the kernel space. */
+ userTaskTable = TaskTable;
+
+ gcmkERR_BREAK(gckOS_MapUserPointer(
+ Command->os,
+ userTaskTable,
+ gcmSIZEOF(*userTaskTable),
+ &pointer));
+
+ TaskTable = pointer;
+
+ userTaskTableMapped = gcvTRUE;
+
+ /* Update the signal info. */
+ TaskTable->coid = Context->coid;
+ TaskTable->rcvid = Context->rcvid;
+#endif
+
+ gcmkERR_BREAK(gckOS_GetProcessID((gctUINT32_PTR)&pid));
+ gcmkERR_BREAK(gckOS_QueryNeedCopy(Command->os, pid, &needCopy));
+ if(needCopy)
+ {
+ gcmkERR_BREAK(gckOS_CopyFromUserData(
+ Command->os,
+ &_TaskTable,
+ TaskTable,
+ gcmSIZEOF(struct _gcsTASK_MASTER_TABLE)
+ ));
+ TaskTable = &_TaskTable;
+ /* Determine whether there are FE tasks to be performed. */
+ gcmkERR_BREAK(gckOS_CopyFromUserData(
+ Command->os,
+ &_Context,
+ Context,
+ gcmSIZEOF(struct _gcsVGCONTEXT)
+ ));
+ Context = &_Context;
+ }
+
+ gcmkERR_BREAK(gckVGHARDWARE_SetPowerManagementState(
+ Command->hardware, gcvPOWER_ON_AUTO
+ ));
+
+ /* Acquire the power semaphore. */
+ gcmkERR_BREAK(gckOS_AcquireSemaphore(
+ Command->os, Command->powerSemaphore
+ ));
+
+ /* Acquire the mutex. */
+ status = gckOS_AcquireMutex(
+ Command->os,
+ Command->commitMutex,
+ gcvINFINITE
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
+ Command->os, Command->powerSemaphore));
+ break;
+ }
+
+ do
+ {
+ gcmkERR_BREAK(_FlushMMU(Command));
+
+ /* Assign a context ID if not yet assigned. */
+ if (Context->id == 0)
+ {
+ /* Assign the next context number. */
+ Context->id = ++ Command->contextCounter;
+ /* See if we overflowed. */
+ if (Command->contextCounter == 0)
+ {
+ /* We actually did overflow, wow... */
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ break;
+ }
+ }
+
+ /* The first entry in the queue is always the context buffer.
+ Verify whether the user context is the same as the current
+ context and if that's the case, skip the first entry. */
+ if (Context->id == Command->currentContext)
+ {
+ /* Same context as before, skip the first entry. */
+ EntryCount -= 1;
+ Queue += 1;
+
+ /* Set the signal to avoid user waiting. */
+#ifdef __QNXNTO__
+ gcmkERR_BREAK(gckOS_UserSignal(
+ Command->os,
+ Context->userSignal,
+ Context->rcvid,
+ Context->coid
+ ));
+#else
+ gcmkERR_BREAK(gckOS_UserSignal(
+ Command->os, Context->signal, Context->process
+ ));
+#endif
+ }
+ else
+ {
+ /* Different user context - keep the first entry.
+ Set the user context as the current one. */
+ Command->currentContext = Context->id;
+ }
+
+ /* Reset pointers. */
+ queueControl = gcvNULL;
+ previousEnd = gcvNULL;
+
+ haveFETasks = (TaskTable->table[gcvBLOCK_COMMAND].head != gcvNULL);
+
+ /* Determine the size of the queue. */
+ queueSize = EntryCount * gcmSIZEOF(gcsVGCMDQUEUE);
+ if(needCopy)
+ {
+ gctPOINTER pointer = gcvNULL;
+ gcmkERR_BREAK(gckOS_Allocate(
+ Command->os,
+ queueSize,
+ &pointer
+ ));
+ userEntry = pointer;
+ mappedQueue = pointer;
+ gcmkERR_BREAK(gckOS_CopyFromUserData(
+ Command->os,
+ userEntry,
+ Queue,
+ queueSize
+ ));
+ }
+ else
+ {
+ /* Map the command queue into the kernel space. */
+ gcmkERR_BREAK(gckOS_MapUserPointer(
+ Command->os,
+ Queue,
+ queueSize,
+ (gctPOINTER *) &mappedQueue
+ ));
+ userEntry = mappedQueue;
+ }
+ /* Set the first entry. */
+
+ /* Process the command queue. */
+ while (EntryCount)
+ {
+ /* Lock the current queue. */
+ gcmkERR_BREAK(_LockCurrentQueue(
+ Command, &kernelEntry, &queueLength
+ ));
+
+ /* Determine the number of entries to process. */
+ currentLength = (queueLength < EntryCount)
+ ? queueLength
+ : EntryCount;
+
+ /* Update the number of the entries left to process. */
+ EntryCount -= currentLength;
+
+ /* Reset previous flags. */
+ previousDynamic = gcvFALSE;
+ previousExecuted = gcvFALSE;
+
+ /* Set the initial control index. */
+ controlIndex = 0;
+
+ /* Process entries. */
+ for (entriesQueued = 0; entriesQueued < currentLength; entriesQueued += 1)
+ {
+ /* Get the kernel pointer to the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer = gcvNULL;
+ gcmkERR_BREAK(_ConvertUserCommandBufferPointer(
+ Command,
+ userEntry->commandBuffer,
+ &commandBuffer
+ ));
+
+ /* Is it a dynamic command buffer? */
+ if (userEntry->dynamic)
+ {
+ /* Select dynamic buffer control functions. */
+ queueControl = &_dynamicBuffer[controlIndex];
+ }
+
+ /* No, a static command buffer. */
+ else
+ {
+ /* Select static buffer control functions. */
+ queueControl = &_staticBuffer[controlIndex];
+ }
+
+ /* Set the command buffer pointer to the entry. */
+ kernelEntry->commandBuffer = commandBuffer;
+
+ /* If the previous entry was a dynamic command buffer,
+ link it to the current. */
+ if (previousDynamic)
+ {
+ gcmkERR_BREAK(gckVGCOMMAND_FetchCommand(
+ Command,
+ previousEnd,
+ commandBuffer->address,
+ commandBuffer->dataCount,
+ gcvNULL
+ ));
+
+ /* The buffer will be auto-executed, only need to
+ update it after it has been executed. */
+ kernelEntry->handler = queueControl->update;
+
+ /* The buffer is only being updated. */
+ previousExecuted = gcvFALSE;
+ }
+ else
+ {
+ /* Set the buffer up for execution. */
+ kernelEntry->handler = queueControl->execute;
+
+ /* The buffer is being updated. */
+ previousExecuted = gcvTRUE;
+ }
+
+ /* The current buffer's END command becomes the last END. */
+ previousEnd
+ = ((gctUINT8_PTR) commandBuffer)
+ + commandBuffer->bufferOffset
+ + commandBuffer->dataCount * Command->info.commandAlignment
+ - Command->info.staticTailSize;
+
+ /* Update the last entry info. */
+ previousDynamic = userEntry->dynamic;
+
+ /* Advance entries. */
+ userEntry ++;
+ kernelEntry ++;
+
+ /* Update the control index. */
+ controlIndex = 1;
+ }
+
+ /* If the previous entry was a dynamic command buffer,
+ terminate it with an END. */
+ if (previousDynamic)
+ {
+ gcmkERR_BREAK(gckVGCOMMAND_EndCommand(
+ Command,
+ previousEnd,
+ Command->info.feBufferInt,
+ gcvNULL
+ ));
+ }
+
+ /* Last buffer? */
+ if (EntryCount == 0)
+ {
+ /* Modify the last command buffer's routines to handle
+ tasks if any.*/
+ if (haveFETasks)
+ {
+ if (previousExecuted)
+ {
+ kernelEntry[-1].handler = queueControl->lastExecute;
+ }
+ else
+ {
+ kernelEntry[-1].handler = queueControl->lastUpdate;
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkERR_BREAK(gckOS_ReleaseMutex(
+ Command->os,
+ Command->queueMutex
+ ));
+ /* Schedule tasks. */
+ gcmkERR_BREAK(_ScheduleTasks(Command, TaskTable, previousEnd));
+
+ /* Acquire the mutex. */
+ gcmkERR_BREAK(gckOS_AcquireMutex(
+ Command->os,
+ Command->queueMutex,
+ gcvINFINITE
+ ));
+ }
+
+ /* Unkock and schedule the current queue for execution. */
+ gcmkERR_BREAK(_UnlockCurrentQueue(
+ Command, currentLength
+ ));
+ }
+ }
+ while (gcvFALSE);
+
+ if (mappedQueue)
+ {
+ if(!needCopy)
+ {
+ /* Unmap the user command buffer. */
+ gcmkERR_BREAK(gckOS_UnmapUserPointer(
+ Command->os,
+ Queue,
+ queueSize,
+ mappedQueue
+ ));
+ }
+ else
+ {
+ gcmkERR_BREAK(gckOS_Free(Command->os, mappedQueue));
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+ Command->os,
+ Command->commitMutex
+ ));
+
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
+ Command->os, Command->powerSemaphore));
+ }
+ while (gcvFALSE);
+#ifdef __QNXNTO__
+ if (userContextMapped)
+ {
+ /* Unmap the user context. */
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ userContext,
+ gcmSIZEOF(*userContext),
+ Context));
+ }
+
+ if (userTaskTableMapped)
+ {
+ /* Unmap the user taskTable. */
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(
+ Command->os,
+ userTaskTable,
+ gcmSIZEOF(*userTaskTable),
+ TaskTable));
+ }
+#endif
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
new file mode 100644
index 000000000000..3faa3896975c
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
@@ -0,0 +1,1880 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_DATABASE
+
+/*******************************************************************************
+***** Private fuctions ********************************************************/
+
+#define _GetSlot(database, x) \
+ (gctUINT32)(gcmPTR_TO_UINT64(x) % gcmCOUNTOF(database->list))
+
+/*******************************************************************************
+** gckKERNEL_NewDatabase
+**
+** Create a new database structure and insert it to the head of the hash list.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** ProcessID that identifies the database.
+**
+** OUTPUT:
+**
+** gcsDATABASE_PTR * Database
+** Pointer to a variable receiving the database structure pointer on
+** success.
+*/
+static gceSTATUS
+gckKERNEL_NewDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gcsDATABASE_PTR * Database
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gctPOINTER pointer = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+ gctSIZE_T slot;
+ gcsDATABASE_PTR existingDatabase;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Compute the hash for the database. */
+ slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
+
+ /* Walk the hash list. */
+ for (existingDatabase = Kernel->db->db[slot];
+ existingDatabase != gcvNULL;
+ existingDatabase = existingDatabase->next)
+ {
+ if (existingDatabase->processID == ProcessID)
+ {
+ /* One process can't be added twice. */
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+ }
+
+ if (Kernel->db->freeDatabase != gcvNULL)
+ {
+ /* Allocate a database from the free list. */
+ database = Kernel->db->freeDatabase;
+ Kernel->db->freeDatabase = database->next;
+ }
+ else
+ {
+ /* Allocate a new database from the heap. */
+ gcmkONERROR(gckOS_Allocate(Kernel->os,
+ gcmSIZEOF(gcsDATABASE),
+ &pointer));
+
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsDATABASE));
+
+ database = pointer;
+
+ gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->counterMutex));
+ }
+
+ /* Insert the database into the hash. */
+ database->next = Kernel->db->db[slot];
+ Kernel->db->db[slot] = database;
+
+ /* Save the hash slot. */
+ database->slot = slot;
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Return the database. */
+ *Database = database;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Database=0x%x", *Database);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (pointer)
+ {
+ gcmkOS_SAFE_FREE(Kernel->os, pointer);
+ }
+
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_FindDatabase
+**
+** Find a database identified by a process ID and move it to the head of the
+** hash list.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** ProcessID that identifies the database.
+**
+** gctBOOL LastProcessID
+** gcvTRUE if searching for the last known process ID. gcvFALSE if
+** we need to search for the process ID specified by the ProcessID
+** argument.
+**
+** OUTPUT:
+**
+** gcsDATABASE_PTR * Database
+** Pointer to a variable receiving the database structure pointer on
+** success.
+*/
+gceSTATUS
+gckKERNEL_FindDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL LastProcessID,
+ OUT gcsDATABASE_PTR * Database
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database, previous;
+ gctSIZE_T slot;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d LastProcessID=%d",
+ Kernel, ProcessID, LastProcessID);
+
+ /* Compute the hash for the database. */
+ slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Check whether we are getting the last known database. */
+ if (LastProcessID)
+ {
+ /* Use last database. */
+ database = Kernel->db->lastDatabase;
+
+ if (database == gcvNULL)
+ {
+ /* Database not found. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+ }
+ else
+ {
+ /* Walk the hash list. */
+ for (previous = gcvNULL, database = Kernel->db->db[slot];
+ database != gcvNULL;
+ database = database->next)
+ {
+ if (database->processID == ProcessID)
+ {
+ /* Found it! */
+ break;
+ }
+
+ previous = database;
+ }
+
+ if (database == gcvNULL)
+ {
+ /* Database not found. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ if (previous != gcvNULL)
+ {
+ /* Move database to the head of the hash list. */
+ previous->next = database->next;
+ database->next = Kernel->db->db[slot];
+ Kernel->db->db[slot] = database;
+ }
+ }
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Return the database. */
+ *Database = database;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Database=0x%x", *Database);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_DeleteDatabase
+**
+** Remove a database from the hash list and delete its structure.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gcsDATABASE_PTR Database
+** Pointer to the database structure to remove.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+static gceSTATUS
+gckKERNEL_DeleteDatabase(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_PTR database;
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Check slot value. */
+ gcmkVERIFY_ARGUMENT(Database->slot < gcmCOUNTOF(Kernel->db->db));
+
+ if (Database->slot < gcmCOUNTOF(Kernel->db->db))
+ {
+ /* Check if database if the head of the hash list. */
+ if (Kernel->db->db[Database->slot] == Database)
+ {
+ /* Remove the database from the hash list. */
+ Kernel->db->db[Database->slot] = Database->next;
+ }
+ else
+ {
+ /* Walk the has list to find the database. */
+ for (database = Kernel->db->db[Database->slot];
+ database != gcvNULL;
+ database = database->next
+ )
+ {
+ /* Check if the next list entry is this database. */
+ if (database->next == Database)
+ {
+ /* Remove the database from the hash list. */
+ database->next = Database->next;
+ break;
+ }
+ }
+
+ if (database == gcvNULL)
+ {
+ /* Ouch! Something got corrupted. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+ }
+ }
+
+ if (Kernel->db->lastDatabase != gcvNULL)
+ {
+ /* Insert database to the free list. */
+ Kernel->db->lastDatabase->next = Kernel->db->freeDatabase;
+ Kernel->db->freeDatabase = Kernel->db->lastDatabase;
+ }
+
+ /* Keep database as the last database. */
+ Kernel->db->lastDatabase = Database;
+
+ /* Destory handle db. */
+ gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Database->handleDatabase));
+ Database->handleDatabase = gcvNULL;
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Database->handleDatabaseMutex));
+ Database->handleDatabaseMutex = gcvNULL;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ /* Destory process MMU. */
+ gcmkVERIFY_OK(gckEVENT_DestroyMmu(Kernel->eventObj, Database->mmu, gcvKERNEL_PIXEL));
+ Database->mmu = gcvNULL;
+#endif
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_NewRecord
+**
+** Create a new database record structure and insert it to the head of the
+** database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gcsDATABASE_PTR Database
+** Pointer to a database structure.
+**
+** OUTPUT:
+**
+** gcsDATABASE_RECORD_PTR * Record
+** Pointer to a variable receiving the database record structure
+** pointer on success.
+*/
+static gceSTATUS
+gckKERNEL_NewRecord(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database,
+ IN gctUINT32 Slot,
+ OUT gcsDATABASE_RECORD_PTR * Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_RECORD_PTR record = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (Kernel->db->freeRecord != gcvNULL)
+ {
+ /* Allocate the record from the free list. */
+ record = Kernel->db->freeRecord;
+ Kernel->db->freeRecord = record->next;
+ }
+ else
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ /* Allocate the record from the heap. */
+ gcmkONERROR(gckOS_Allocate(Kernel->os,
+ gcmSIZEOF(gcsDATABASE_RECORD),
+ &pointer));
+
+ record = pointer;
+ }
+
+ /* Insert the record in the database. */
+ record->next = Database->list[Slot];
+ Database->list[Slot] = record;
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Return the record. */
+ *Record = record;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Record=0x%x", *Record);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+ if (record != gcvNULL)
+ {
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_DeleteRecord
+**
+** Remove a database record from the database and delete its structure.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gcsDATABASE_PTR Database
+** Pointer to a database structure.
+**
+** gceDATABASE_TYPE Type
+** Type of the record to remove.
+**
+** gctPOINTER Data
+** Data of the record to remove.
+**
+** OUTPUT:
+**
+** gctSIZE_T_PTR Bytes
+** Pointer to a variable that receives the size of the record deleted.
+** Can be gcvNULL if the size is not required.
+*/
+static gceSTATUS
+gckKERNEL_DeleteRecord(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Data,
+ OUT gctSIZE_T_PTR Bytes OPTIONAL
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_RECORD_PTR record, previous;
+ gctUINT32 slot = _GetSlot(Database, Data);
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
+ Kernel, Database, Type, Data);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Scan the database for this record. */
+ for (record = Database->list[slot], previous = gcvNULL;
+ record != gcvNULL;
+ record = record->next
+ )
+ {
+ if ((record->type == Type)
+ && (record->data == Data)
+ )
+ {
+ /* Found it! */
+ break;
+ }
+
+ previous = record;
+ }
+
+ if (record == gcvNULL)
+ {
+ /* Ouch! This record is not found? */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return size of record. */
+ *Bytes = record->bytes;
+ }
+
+ /* Remove record from database. */
+ if (previous == gcvNULL)
+ {
+ Database->list[slot] = record->next;
+ }
+ else
+ {
+ previous->next = record->next;
+ }
+
+ /* Insert record in free list. */
+ record->next = Kernel->db->freeRecord;
+ Kernel->db->freeRecord = record;
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_FindRecord
+**
+** Find a database record from the database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gcsDATABASE_PTR Database
+** Pointer to a database structure.
+**
+** gceDATABASE_TYPE Type
+** Type of the record to remove.
+**
+** gctPOINTER Data
+** Data of the record to remove.
+**
+** OUTPUT:
+**
+** gctSIZE_T_PTR Bytes
+** Pointer to a variable that receives the size of the record deleted.
+** Can be gcvNULL if the size is not required.
+*/
+static gceSTATUS
+gckKERNEL_FindRecord(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Data,
+ OUT gcsDATABASE_RECORD_PTR Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_RECORD_PTR record;
+ gctUINT32 slot = _GetSlot(Database, Data);
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
+ Kernel, Database, Type, Data);
+
+ /* Acquire the database mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Scan the database for this record. */
+ for (record = Database->list[slot];
+ record != gcvNULL;
+ record = record->next
+ )
+ {
+ if ((record->type == Type)
+ && (record->data == Data)
+ )
+ {
+ /* Found it! */
+ break;
+ }
+ }
+
+ if (record == gcvNULL)
+ {
+ /* Ouch! This record is not found? */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ if (Record != gcvNULL)
+ {
+ /* Return information of record. */
+ gcmkONERROR(
+ gckOS_MemCopy(Record, record, sizeof(gcsDATABASE_RECORD)));
+ }
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("Record=0x%x", Record);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+***** Public API **************************************************************/
+
+/*******************************************************************************
+** gckKERNEL_CreateProcessDB
+**
+** Create a new process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_CreateProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database = gcvNULL;
+ gctUINT32 i;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Create a new database. */
+ gcmkONERROR(gckKERNEL_NewDatabase(Kernel, ProcessID, &database));
+
+ /* Initialize the database. */
+ database->processID = ProcessID;
+ database->vidMem.bytes = 0;
+ database->vidMem.maxBytes = 0;
+ database->vidMem.totalBytes = 0;
+ database->nonPaged.bytes = 0;
+ database->nonPaged.maxBytes = 0;
+ database->nonPaged.totalBytes = 0;
+ database->contiguous.bytes = 0;
+ database->contiguous.maxBytes = 0;
+ database->contiguous.totalBytes = 0;
+ database->mapMemory.bytes = 0;
+ database->mapMemory.maxBytes = 0;
+ database->mapMemory.totalBytes = 0;
+ database->mapUserMemory.bytes = 0;
+ database->mapUserMemory.maxBytes = 0;
+ database->mapUserMemory.totalBytes = 0;
+
+ for (i = 0; i < gcmCOUNTOF(database->list); i++)
+ {
+ database->list[i] = gcvNULL;
+ }
+
+ for (i = 0; i < gcvSURF_NUM_TYPES; i++)
+ {
+ database->vidMemType[i].bytes = 0;
+ database->vidMemType[i].maxBytes = 0;
+ database->vidMemType[i].totalBytes = 0;
+ }
+
+ for (i = 0; i < gcvPOOL_NUMBER_OF_POOLS; i++)
+ {
+ database->vidMemPool[i].bytes = 0;
+ database->vidMemPool[i].maxBytes = 0;
+ database->vidMemPool[i].totalBytes = 0;
+ }
+
+ gcmkASSERT(database->handleDatabase == gcvNULL);
+ gcmkONERROR(
+ gckKERNEL_CreateIntegerDatabase(Kernel, &database->handleDatabase));
+
+ gcmkASSERT(database->handleDatabaseMutex == gcvNULL);
+ gcmkONERROR(
+ gckOS_CreateMutex(Kernel->os, &database->handleDatabaseMutex));
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkASSERT(database->mmu == gcvNULL);
+ gcmkONERROR(
+ gckMMU_Construct(Kernel, gcdMMU_SIZE, &database->mmu));
+#endif
+
+#if gcdSECURE_USER
+ {
+ gctINT slot;
+ gcskSECURE_CACHE * cache = &database->cache;
+
+ /* Setup the linked list of cache nodes. */
+ for (slot = 1; slot <= gcdSECURE_CACHE_SLOTS; ++slot)
+ {
+ cache->cache[slot].logical = gcvNULL;
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+ cache->cache[slot].prev = &cache->cache[slot - 1];
+ cache->cache[slot].next = &cache->cache[slot + 1];
+# endif
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ cache->cache[slot].nextHash = gcvNULL;
+ cache->cache[slot].prevHash = gcvNULL;
+# endif
+ }
+
+#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
+ /* Setup the head and tail of the cache. */
+ cache->cache[0].next = &cache->cache[1];
+ cache->cache[0].prev = &cache->cache[gcdSECURE_CACHE_SLOTS];
+ cache->cache[0].logical = gcvNULL;
+
+ /* Fix up the head and tail pointers. */
+ cache->cache[0].next->prev = &cache->cache[0];
+ cache->cache[0].prev->next = &cache->cache[0];
+# endif
+
+#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
+ /* Zero out the hash table. */
+ for (slot = 0; slot < gcmCOUNTOF(cache->hash); ++slot)
+ {
+ cache->hash[slot].logical = gcvNULL;
+ cache->hash[slot].nextHash = gcvNULL;
+ }
+# endif
+
+ /* Initialize cache index. */
+ cache->cacheIndex = gcvNULL;
+ cache->cacheFree = 1;
+ cache->cacheStamp = 0;
+ }
+#endif
+
+ /* Reset idle timer. */
+ Kernel->db->lastIdle = 0;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_AddProcessDB
+**
+** Add a record to a process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** gceDATABASE_TYPE TYPE
+** Type of the record to add.
+**
+** gctPOINTER Pointer
+** Data of the record to add.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the record to add.
+**
+** gctSIZE_T Size
+** Size of the record to add.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_AddProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gcsDATABASE_RECORD_PTR record = gcvNULL;
+ gcsDATABASE_COUNTERS * count;
+ gctUINT32 vidMemType;
+ gcePOOL vidMemPool;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x "
+ "Physical=0x%x Size=%lu",
+ Kernel, ProcessID, Type, Pointer, Physical, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Decode type. */
+ vidMemType = (Type & gcdDB_VIDEO_MEMORY_TYPE_MASK) >> gcdDB_VIDEO_MEMORY_TYPE_SHIFT;
+ vidMemPool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
+
+ Type &= gcdDATABASE_TYPE_MASK;
+
+ /* Special case the idle record. */
+ if (Type == gcvDB_IDLE)
+ {
+ gctUINT64 time;
+
+ /* Get the current profile time. */
+ gcmkONERROR(gckOS_GetProfileTick(&time));
+
+ if ((ProcessID == 0) && (Kernel->db->lastIdle != 0))
+ {
+ /* Out of idle, adjust time it was idle. */
+ Kernel->db->idleTime += time - Kernel->db->lastIdle;
+ Kernel->db->lastIdle = 0;
+ }
+ else if (ProcessID == 1)
+ {
+ /* Save current idle time. */
+ Kernel->db->lastIdle = time;
+ }
+
+#if gcdDYNAMIC_SPEED
+ {
+ /* Test for first call. */
+ if (Kernel->db->lastSlowdown == 0)
+ {
+ /* Save milliseconds. */
+ Kernel->db->lastSlowdown = time;
+ Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
+ }
+ else
+ {
+ /* Compute ellapsed time in milliseconds. */
+ gctUINT delta = gckOS_ProfileToMS(time - Kernel->db->lastSlowdown);
+
+ /* Test for end of period. */
+ if (delta >= gcdDYNAMIC_SPEED)
+ {
+ /* Compute number of idle milliseconds. */
+ gctUINT idle = gckOS_ProfileToMS(
+ Kernel->db->idleTime - Kernel->db->lastSlowdownIdle);
+
+ /* Broadcast to slow down the GPU. */
+ gcmkONERROR(gckOS_BroadcastCalibrateSpeed(Kernel->os,
+ Kernel->hardware,
+ idle,
+ delta));
+
+ /* Save current time. */
+ Kernel->db->lastSlowdown = time;
+ Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
+ }
+ }
+ }
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ /* Create a new record in the database. */
+ gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, _GetSlot(database, Pointer), &record));
+
+ /* Initialize the record. */
+ record->kernel = Kernel;
+ record->type = Type;
+ record->data = Pointer;
+ record->physical = Physical;
+ record->bytes = Size;
+
+ /* Get pointer to counters. */
+ switch (Type)
+ {
+ case gcvDB_VIDEO_MEMORY:
+ count = &database->vidMem;
+ break;
+
+ case gcvDB_NON_PAGED:
+ count = &database->nonPaged;
+ break;
+
+ case gcvDB_CONTIGUOUS:
+ count = &database->contiguous;
+ break;
+
+ case gcvDB_MAP_MEMORY:
+ count = &database->mapMemory;
+ break;
+
+ case gcvDB_MAP_USER_MEMORY:
+ count = &database->mapUserMemory;
+ break;
+
+ default:
+ count = gcvNULL;
+ break;
+ }
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
+
+ if (count != gcvNULL)
+ {
+ /* Adjust counters. */
+ count->totalBytes += Size;
+ count->bytes += Size;
+ count->allocCount++;
+
+ if (count->bytes > count->maxBytes)
+ {
+ count->maxBytes = count->bytes;
+ }
+ }
+
+ if (Type == gcvDB_VIDEO_MEMORY)
+ {
+ count = &database->vidMemType[vidMemType];
+
+ /* Adjust counters. */
+ count->totalBytes += Size;
+ count->bytes += Size;
+ count->allocCount++;
+
+ if (count->bytes > count->maxBytes)
+ {
+ count->maxBytes = count->bytes;
+ }
+
+ count = &database->vidMemPool[vidMemPool];
+
+ /* Adjust counters. */
+ count->totalBytes += Size;
+ count->bytes += Size;
+ count->allocCount++;
+
+ if (count->bytes > count->maxBytes)
+ {
+ count->maxBytes = count->bytes;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_RemoveProcessDB
+**
+** Remove a record from a process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** gceDATABASE_TYPE TYPE
+** Type of the record to remove.
+**
+** gctPOINTER Pointer
+** Data of the record to remove.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_RemoveProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gctSIZE_T bytes = 0;
+ gctUINT32 vidMemType;
+ gcePOOL vidMemPool;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
+ Kernel, ProcessID, Type, Pointer);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+ /* Decode type. */
+ vidMemType = (Type & gcdDB_VIDEO_MEMORY_TYPE_MASK) >> gcdDB_VIDEO_MEMORY_TYPE_SHIFT;
+ vidMemPool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
+
+ Type &= gcdDATABASE_TYPE_MASK;
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ /* Delete the record. */
+ gcmkONERROR(
+ gckKERNEL_DeleteRecord(Kernel, database, Type, Pointer, &bytes));
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
+
+ /* Update counters. */
+ switch (Type)
+ {
+ case gcvDB_VIDEO_MEMORY:
+ database->vidMem.bytes -= bytes;
+ database->vidMem.freeCount++;
+ database->vidMemType[vidMemType].bytes -= bytes;
+ database->vidMemType[vidMemType].freeCount++;
+ database->vidMemPool[vidMemPool].bytes -= bytes;
+ database->vidMemPool[vidMemPool].freeCount++;
+ break;
+
+ case gcvDB_NON_PAGED:
+ database->nonPaged.bytes -= bytes;
+ database->nonPaged.freeCount++;
+ break;
+
+ case gcvDB_CONTIGUOUS:
+ database->contiguous.bytes -= bytes;
+ database->contiguous.freeCount++;
+ break;
+
+ case gcvDB_MAP_MEMORY:
+ database->mapMemory.bytes -= bytes;
+ database->mapMemory.freeCount++;
+ break;
+
+ case gcvDB_MAP_USER_MEMORY:
+ database->mapUserMemory.bytes -= bytes;
+ database->mapUserMemory.freeCount++;
+ break;
+
+ default:
+ break;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_FindProcessDB
+**
+** Find a record from a process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** gceDATABASE_TYPE TYPE
+** Type of the record to remove.
+**
+** gctPOINTER Pointer
+** Data of the record to remove.
+**
+** OUTPUT:
+**
+** gcsDATABASE_RECORD_PTR Record
+** Copy of record.
+*/
+gceSTATUS
+gckKERNEL_FindProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 ThreadID,
+ IN gceDATABASE_TYPE Type,
+ IN gctPOINTER Pointer,
+ OUT gcsDATABASE_RECORD_PTR Record
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
+ Kernel, ProcessID, ThreadID, Type, Pointer);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ /* Find the record. */
+ gcmkONERROR(
+ gckKERNEL_FindRecord(Kernel, database, Type, Pointer, Record));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_DestroyProcessDB
+**
+** Destroy a process database. If the database contains any records, the data
+** inside those records will be deleted as well. This aids in the cleanup if
+** a process has died unexpectedly or has memory leaks.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_DestroyProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gcsDATABASE_RECORD_PTR record, next;
+ gctBOOL asynchronous = gcvTRUE;
+ gckVIDMEM_NODE nodeObject;
+ gctPHYS_ADDR physical;
+ gckKERNEL kernel = Kernel;
+ gctUINT32 handle;
+ gctUINT32 i;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): VidMem: total=%lu max=%lu",
+ ProcessID, database->vidMem.totalBytes,
+ database->vidMem.maxBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): NonPaged: total=%lu max=%lu",
+ ProcessID, database->nonPaged.totalBytes,
+ database->nonPaged.maxBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): Contiguous: total=%lu max=%lu",
+ ProcessID, database->contiguous.totalBytes,
+ database->contiguous.maxBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): Idle time=%llu",
+ ProcessID, Kernel->db->idleTime);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): Map: total=%lu max=%lu",
+ ProcessID, database->mapMemory.totalBytes,
+ database->mapMemory.maxBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
+ "DB(%d): Map: total=%lu max=%lu",
+ ProcessID, database->mapUserMemory.totalBytes,
+ database->mapUserMemory.maxBytes);
+
+ if (database->list != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "Process %d has entries in its database:",
+ ProcessID);
+ }
+
+ for(i = 0; i < gcmCOUNTOF(database->list); i++)
+ {
+
+ /* Walk all records. */
+ for (record = database->list[i]; record != gcvNULL; record = next)
+ {
+ /* Next next record. */
+ next = record->next;
+
+ /* Dispatch on record type. */
+ switch (record->type)
+ {
+ case gcvDB_VIDEO_MEMORY:
+ gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(record->kernel,
+ ProcessID,
+ gcmPTR2INT32(record->data),
+ &nodeObject));
+
+ /* Free the video memory. */
+ gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(record->kernel,
+ ProcessID,
+ gcmPTR2INT32(record->data)));
+
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(record->kernel,
+ nodeObject));
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: VIDEO_MEMORY 0x%x (status=%d)",
+ record->data, status);
+ break;
+
+ case gcvDB_NON_PAGED:
+ physical = gcmNAME_TO_PTR(record->physical);
+ /* Unmap user logical memory first. */
+ status = gckOS_UnmapUserLogical(Kernel->os,
+ physical,
+ record->bytes,
+ record->data);
+
+ /* Free the non paged memory. */
+ status = gckEVENT_FreeNonPagedMemory(record->kernel->eventObj,
+ record->bytes,
+ physical,
+ record->data,
+ gcvKERNEL_PIXEL);
+ gcmRELEASE_NAME(record->physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)",
+ record->data, record->bytes, status);
+ break;
+
+ case gcvDB_COMMAND_BUFFER:
+ /* Free the command buffer. */
+ status = gckEVENT_DestroyVirtualCommandBuffer(record->kernel->eventObj,
+ record->bytes,
+ gcmNAME_TO_PTR(record->physical),
+ record->data,
+ gcvKERNEL_PIXEL);
+ gcmRELEASE_NAME(record->physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: COMMAND_BUFFER 0x%x, bytes=%lu (status=%d)",
+ record->data, record->bytes, status);
+ break;
+
+ case gcvDB_CONTIGUOUS:
+ physical = gcmNAME_TO_PTR(record->physical);
+ /* Unmap user logical memory first. */
+ status = gckOS_UnmapUserLogical(Kernel->os,
+ physical,
+ record->bytes,
+ record->data);
+
+ /* Free the contiguous memory. */
+ status = gckEVENT_FreeContiguousMemory(record->kernel->eventObj,
+ record->bytes,
+ physical,
+ record->data,
+ gcvKERNEL_PIXEL);
+ gcmRELEASE_NAME(record->physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)",
+ record->data, record->bytes, status);
+ break;
+
+ case gcvDB_SIGNAL:
+#if USE_NEW_LINUX_SIGNAL
+ status = gcvSTATUS_NOT_SUPPORTED;
+#else
+ /* Free the user signal. */
+ status = gckOS_DestroyUserSignal(Kernel->os,
+ gcmPTR2INT32(record->data));
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: SIGNAL %d (status=%d)",
+ (gctINT)(gctUINTPTR_T)record->data, status);
+ break;
+
+ case gcvDB_VIDEO_MEMORY_LOCKED:
+ handle = gcmPTR2INT32(record->data);
+
+ gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(record->kernel,
+ ProcessID,
+ handle,
+ &nodeObject));
+
+ /* Unlock what we still locked */
+ status = gckVIDMEM_Unlock(record->kernel,
+ nodeObject,
+ nodeObject->type,
+ &asynchronous);
+
+#if gcdENABLE_VG
+ if (record->kernel->core == gcvCORE_VG)
+ {
+ if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
+ {
+ status = gckVIDMEM_Unlock(record->kernel,
+ nodeObject,
+ nodeObject->type,
+ gcvNULL);
+ }
+
+ gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(record->kernel,
+ ProcessID,
+ handle));
+
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(record->kernel,
+ nodeObject));
+ }
+ else
+#endif
+ {
+ gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(record->kernel,
+ ProcessID,
+ handle));
+
+ if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
+ {
+ status = gckEVENT_Unlock(record->kernel->eventObj,
+ gcvKERNEL_PIXEL,
+ nodeObject,
+ nodeObject->type);
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(record->kernel,
+ nodeObject));
+ }
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)",
+ record->data, status);
+ break;
+
+ case gcvDB_CONTEXT:
+ status = gckCOMMAND_Detach(record->kernel->command, gcmNAME_TO_PTR(record->data));
+ gcmRELEASE_NAME(record->data);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: CONTEXT 0x%x (status=%d)",
+ record->data, status);
+ break;
+
+ case gcvDB_MAP_MEMORY:
+ /* Unmap memory. */
+ status = gckKERNEL_UnmapMemory(record->kernel,
+ record->physical,
+ record->bytes,
+ record->data);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: MAP MEMORY %d (status=%d)",
+ gcmPTR2INT32(record->data), status);
+ break;
+
+ case gcvDB_MAP_USER_MEMORY:
+ status = gckOS_UnmapUserMemory(Kernel->os,
+ Kernel->core,
+ record->physical,
+ record->bytes,
+ gcmNAME_TO_PTR(record->data),
+ 0);
+ gcmRELEASE_NAME(record->data);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: MAP USER MEMORY %d (status=%d)",
+ gcmPTR2INT32(record->data), status);
+ break;
+
+ case gcvDB_SHBUF:
+ /* Free shared buffer. */
+ status = gckKERNEL_DestroyShBuffer(record->kernel,
+ (gctSHBUF) record->data);
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
+ "DB: SHBUF %u (status=%d)",
+ (gctUINT32)(gctUINTPTR_T) record->data, status);
+ break;
+
+ default:
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE,
+ "DB: Correcupted record=0x%08x type=%d",
+ record, record->type);
+ break;
+ }
+
+ /* Delete the record. */
+ gcmkONERROR(gckKERNEL_DeleteRecord(Kernel,
+ database,
+ record->type,
+ record->data,
+ gcvNULL));
+ }
+
+ }
+
+ /* Delete the database. */
+ gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckKERNEL_QueryProcessDB
+**
+** Query a process database for the current usage of a particular record type.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** gctBOOL LastProcessID
+** gcvTRUE if searching for the last known process ID. gcvFALSE if
+** we need to search for the process ID specified by the ProcessID
+** argument.
+**
+** gceDATABASE_TYPE Type
+** Type of the record to query.
+**
+** OUTPUT:
+**
+** gcuDATABASE_INFO * Info
+** Pointer to a variable that receives the requested information.
+*/
+gceSTATUS
+gckKERNEL_QueryProcessDB(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL LastProcessID,
+ IN gceDATABASE_TYPE Type,
+ OUT gcuDATABASE_INFO * Info
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gcePOOL vidMemPool;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
+ Kernel, ProcessID, Type, Info);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+ /* Deocde pool. */
+ vidMemPool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
+
+ Type &= gcdDATABASE_TYPE_MASK;
+
+ /* Find the database. */
+ gcmkONERROR(
+ gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));
+
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
+
+ /* Get pointer to counters. */
+ switch (Type)
+ {
+ case gcvDB_VIDEO_MEMORY:
+ if (vidMemPool != gcvPOOL_UNKNOWN)
+ {
+ gckOS_MemCopy(&Info->counters,
+ &database->vidMemPool[vidMemPool],
+ gcmSIZEOF(database->vidMemPool[vidMemPool]));
+ }
+ else
+ {
+ gckOS_MemCopy(&Info->counters,
+ &database->vidMem,
+ gcmSIZEOF(database->vidMem));
+ }
+ break;
+
+ case gcvDB_NON_PAGED:
+ gckOS_MemCopy(&Info->counters,
+ &database->nonPaged,
+ gcmSIZEOF(database->vidMem));
+ break;
+
+ case gcvDB_CONTIGUOUS:
+ gckOS_MemCopy(&Info->counters,
+ &database->contiguous,
+ gcmSIZEOF(database->vidMem));
+ break;
+
+ case gcvDB_IDLE:
+ Info->time = Kernel->db->idleTime;
+ Kernel->db->idleTime = 0;
+ break;
+
+ case gcvDB_MAP_MEMORY:
+ gckOS_MemCopy(&Info->counters,
+ &database->mapMemory,
+ gcmSIZEOF(database->mapMemory));
+ break;
+
+ case gcvDB_MAP_USER_MEMORY:
+ gckOS_MemCopy(&Info->counters,
+ &database->mapUserMemory,
+ gcmSIZEOF(database->mapUserMemory));
+ break;
+
+ default:
+ break;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_FindHandleDatbase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gctPOINTER * HandleDatabase,
+ OUT gctPOINTER * HandleDatabaseMutex
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d",
+ Kernel, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ *HandleDatabase = database->handleDatabase;
+ *HandleDatabaseMutex = database->handleDatabaseMutex;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckKERNEL_GetProcessMMU(
+ IN gckKERNEL Kernel,
+ OUT gckMMU * Mmu
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gctUINT32 processID;
+
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, processID, gcvFALSE, &database));
+
+ *Mmu = database->mmu;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+#endif
+
+#if gcdSECURE_USER
+/*******************************************************************************
+** gckKERNEL_GetProcessDBCache
+**
+** Get teh secure cache from a process database.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to a gckKERNEL object.
+**
+** gctUINT32 ProcessID
+** Process ID used to identify the database.
+**
+** OUTPUT:
+**
+** gcskSECURE_CACHE_PTR * Cache
+** Pointer to a variable that receives the secure cache pointer.
+*/
+gceSTATUS
+gckKERNEL_GetProcessDBCache(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ OUT gcskSECURE_CACHE_PTR * Cache
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Cache != gcvNULL);
+
+ /* Find the database. */
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ /* Return the pointer to the cache. */
+ *Cache = &database->cache;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Cache=0x%x", *Cache);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckKERNEL_DumpProcessDB(
+ IN gckKERNEL Kernel
+ )
+{
+ gcsDATABASE_PTR database;
+ gctINT i, pid;
+ gctUINT8 name[24];
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Acquire the database mutex. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("*** PROCESS DB DUMP ***\n");
+ gcmkPRINT("**************************\n");
+
+ gcmkPRINT_N(8, "%-8s%s\n", "PID", "NAME");
+ /* Walk the databases. */
+ for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
+ {
+ for (database = Kernel->db->db[i];
+ database != gcvNULL;
+ database = database->next)
+ {
+ pid = database->processID;
+
+ gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));
+
+ gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
+
+ gcmkPRINT_N(8, "%-8d%s\n", pid, name);
+ }
+ }
+
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+void
+_DumpCounter(
+ IN gcsDATABASE_COUNTERS * Counter,
+ IN gctCONST_STRING Name
+ )
+{
+ gcmkPRINT("%s:", Name);
+ gcmkPRINT(" Currently allocated : %10lld", Counter->bytes);
+ gcmkPRINT(" Maximum allocated : %10lld", Counter->maxBytes);
+ gcmkPRINT(" Total allocated : %10lld", Counter->totalBytes);
+}
+
+gceSTATUS
+gckKERNEL_DumpVidMemUsage(
+ IN gckKERNEL Kernel,
+ IN gctINT32 ProcessID
+ )
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gcsDATABASE_COUNTERS * counter;
+ gctUINT32 i = 0;
+
+ static gctCONST_STRING surfaceTypes[] = {
+ "UNKNOWN",
+ "INDEX",
+ "VERTEX",
+ "TEXTURE",
+ "RENDER_TARGET",
+ "DEPTH",
+ "BITMAP",
+ "TILE_STATUS",
+ "IMAGE",
+ "MASK",
+ "SCISSOR",
+ "HIERARCHICAL_DEPTH",
+ "ICACHE",
+ "TXDESC",
+ "FENCE",
+ "TFBHEADER",
+ };
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d",
+ Kernel, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Find the database. */
+ gcmkONERROR(
+ gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ gcmkPRINT("VidMem Usage (Process %d):", ProcessID);
+
+ /* Get pointer to counters. */
+ counter = &database->vidMem;
+
+ _DumpCounter(counter, "Total Video Memory");
+
+ for (i = 0; i < gcvSURF_NUM_TYPES; i++)
+ {
+ counter = &database->vidMemType[i];
+
+ _DumpCounter(counter, surfaceTypes[i]);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c
new file mode 100644
index 000000000000..dbf00f00fa73
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_debug.c
@@ -0,0 +1,2852 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+#include <gc_hal_kernel_debug.h>
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS _lastError = gcvSTATUS_OK;
+static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
+/*
+_debugZones config value
+Please Reference define in gc_hal_base.h
+*/
+static gctUINT32 _debugZones = gcvZONE_NONE;
+
+/******************************************************************************\
+********************************* Debug Switches *******************************
+\******************************************************************************/
+
+/*
+ gcdBUFFERED_OUTPUT
+
+ When set to non-zero, all output is collected into a buffer with the
+ specified size. Once the buffer gets full, the debug buffer will be
+ printed to the console. gcdBUFFERED_SIZE determines the size of the buffer.
+*/
+#define gcdBUFFERED_OUTPUT 0
+
+/*
+ gcdBUFFERED_SIZE
+
+ When set to non-zero, all output is collected into a buffer with the
+ specified size. Once the buffer gets full, the debug buffer will be
+ printed to the console.
+*/
+#define gcdBUFFERED_SIZE (1024 * 1024 * 2)
+
+/*
+ gcdDMA_BUFFER_COUNT
+
+ If greater then zero, the debugger will attempt to find the command buffer
+ where DMA is currently executing and then print this buffer and
+ (gcdDMA_BUFFER_COUNT - 1) buffers before the current one. If set to zero
+ or the current buffer is not found, all buffers are printed.
+*/
+#define gcdDMA_BUFFER_COUNT 0
+
+/*
+ gcdTHREAD_BUFFERS
+
+ When greater then one, will accumulate messages from the specified number
+ of threads in separate output buffers.
+*/
+#define gcdTHREAD_BUFFERS 1
+
+/*
+ gcdENABLE_OVERFLOW
+
+ When set to non-zero, and the output buffer gets full, instead of being
+ printed, it will be allowed to overflow removing the oldest messages.
+*/
+#define gcdENABLE_OVERFLOW 1
+
+/*
+ gcdSHOW_LINE_NUMBER
+
+ When enabledm each print statement will be preceeded with the current
+ line number.
+*/
+#define gcdSHOW_LINE_NUMBER 0
+
+/*
+ gcdSHOW_PROCESS_ID
+
+ When enabledm each print statement will be preceeded with the current
+ process ID.
+*/
+#define gcdSHOW_PROCESS_ID 0
+
+/*
+ gcdSHOW_THREAD_ID
+
+ When enabledm each print statement will be preceeded with the current
+ thread ID.
+*/
+#define gcdSHOW_THREAD_ID 0
+
+/*
+ gcdSHOW_TIME
+
+ When enabled each print statement will be preceeded with the current
+ high-resolution time.
+*/
+#define gcdSHOW_TIME 0
+
+
+/******************************************************************************\
+****************************** Miscellaneous Macros ****************************
+\******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+# define gcmDBGASSERT(Expression, Format, Value) \
+ if (!(Expression)) \
+ { \
+ _DirectPrint( \
+ "*** gcmDBGASSERT ***************************\n" \
+ " function : %s\n" \
+ " line : %d\n" \
+ " expression : " #Expression "\n" \
+ " actual value : " Format "\n", \
+ __FUNCTION__, __LINE__, Value \
+ ); \
+ }
+#else
+# define gcmDBGASSERT(Expression, Format, Value)
+#endif
+
+#define gcmPTRALIGNMENT(Pointer, Alignemnt) \
+( \
+ gcmALIGN(gcmPTR2INT32(Pointer), Alignemnt) - gcmPTR2INT32(Pointer) \
+)
+
+#if gcdALIGNBYSIZE
+# define gcmISALIGNED(Offset, Alignment) \
+ (((Offset) & ((Alignment) - 1)) == 0)
+
+# define gcmkALIGNPTR(Type, Pointer, Alignment) \
+ Pointer = (Type) gcmINT2PTR(gcmALIGN(gcmPTR2INT32(Pointer), Alignment))
+#else
+# define gcmISALIGNED(Offset, Alignment) \
+ gcvTRUE
+
+# define gcmkALIGNPTR(Type, Pointer, Alignment)
+#endif
+
+#define gcmALIGNSIZE(Offset, Size) \
+ ((Size - Offset) + Size)
+
+#define gcdHAVEPREFIX \
+( \
+ gcdSHOW_TIME \
+ || gcdSHOW_LINE_NUMBER \
+ || gcdSHOW_PROCESS_ID \
+ || gcdSHOW_THREAD_ID \
+)
+
+#if gcdHAVEPREFIX
+
+# define gcdOFFSET 0
+
+#if gcdSHOW_TIME
+#if gcmISALIGNED(gcdOFFSET, 8)
+# define gcdTIMESIZE gcmSIZEOF(gctUINT64)
+# elif gcdOFFSET == 4
+# define gcdTIMESIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
+# else
+# error "Unexpected offset value."
+# endif
+# undef gcdOFFSET
+# define gcdOFFSET 8
+#if !defined(gcdPREFIX_LEADER)
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64)
+# define gcdTIMEFORMAT "0x%016llX"
+# else
+# define gcdTIMEFORMAT ", 0x%016llX"
+# endif
+# else
+# define gcdTIMESIZE 0
+# define gcdTIMEFORMAT
+# endif
+
+#if gcdSHOW_LINE_NUMBER
+#if gcmISALIGNED(gcdOFFSET, 8)
+# define gcdNUMSIZE gcmSIZEOF(gctUINT64)
+# elif gcdOFFSET == 4
+# define gcdNUMSIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
+# else
+# error "Unexpected offset value."
+# endif
+# undef gcdOFFSET
+# define gcdOFFSET 8
+#if !defined(gcdPREFIX_LEADER)
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64)
+# define gcdNUMFORMAT "%8llu"
+# else
+# define gcdNUMFORMAT ", %8llu"
+# endif
+# else
+# define gcdNUMSIZE 0
+# define gcdNUMFORMAT
+# endif
+
+#if gcdSHOW_PROCESS_ID
+#if gcmISALIGNED(gcdOFFSET, 4)
+# define gcdPIDSIZE gcmSIZEOF(gctUINT32)
+# else
+# error "Unexpected offset value."
+# endif
+# undef gcdOFFSET
+# define gcdOFFSET 4
+#if !defined(gcdPREFIX_LEADER)
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
+# define gcdPIDFORMAT "pid=%5d"
+# else
+# define gcdPIDFORMAT ", pid=%5d"
+# endif
+# else
+# define gcdPIDSIZE 0
+# define gcdPIDFORMAT
+# endif
+
+#if gcdSHOW_THREAD_ID
+#if gcmISALIGNED(gcdOFFSET, 4)
+# define gcdTIDSIZE gcmSIZEOF(gctUINT32)
+# else
+# error "Unexpected offset value."
+# endif
+# undef gcdOFFSET
+# define gcdOFFSET 4
+#if !defined(gcdPREFIX_LEADER)
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
+# define gcdTIDFORMAT "tid=%5d"
+# else
+# define gcdTIDFORMAT ", tid=%5d"
+# endif
+# else
+# define gcdTIDSIZE 0
+# define gcdTIDFORMAT
+# endif
+
+# define gcdPREFIX_SIZE \
+ ( \
+ gcdTIMESIZE \
+ + gcdNUMSIZE \
+ + gcdPIDSIZE \
+ + gcdTIDSIZE \
+ )
+
+ static const char * _prefixFormat =
+ "["
+ gcdTIMEFORMAT
+ gcdNUMFORMAT
+ gcdPIDFORMAT
+ gcdTIDFORMAT
+ "] ";
+
+#else
+
+# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
+# define gcdPREFIX_SIZE 0
+
+#endif
+
+/* Assumed largest variable argument leader size. */
+#define gcdVARARG_LEADER gcmSIZEOF(gctUINT64)
+
+/* Alignnments. */
+#if gcdALIGNBYSIZE
+# define gcdPREFIX_ALIGNMENT gcdPREFIX_LEADER
+# define gcdVARARG_ALIGNMENT gcdVARARG_LEADER
+#else
+# define gcdPREFIX_ALIGNMENT 0
+# define gcdVARARG_ALIGNMENT 0
+#endif
+
+#if gcdBUFFERED_OUTPUT
+# define gcdOUTPUTPREFIX _AppendPrefix
+# define gcdOUTPUTSTRING _AppendString
+# define gcdOUTPUTCOPY _AppendCopy
+# define gcdOUTPUTBUFFER _AppendBuffer
+#else
+# define gcdOUTPUTPREFIX _PrintPrefix
+# define gcdOUTPUTSTRING _PrintString
+# define gcdOUTPUTCOPY _PrintString
+# define gcdOUTPUTBUFFER _PrintBuffer
+#endif
+
+/******************************************************************************\
+****************************** Private Structures ******************************
+\******************************************************************************/
+
+typedef enum _gceBUFITEM
+{
+ gceBUFITEM_NONE,
+ gcvBUFITEM_PREFIX,
+ gcvBUFITEM_STRING,
+ gcvBUFITEM_COPY,
+ gcvBUFITEM_BUFFER
+}
+gceBUFITEM;
+
+/* Common item head/buffer terminator. */
+typedef struct _gcsBUFITEM_HEAD * gcsBUFITEM_HEAD_PTR;
+typedef struct _gcsBUFITEM_HEAD
+{
+ gceBUFITEM type;
+}
+gcsBUFITEM_HEAD;
+
+/* String prefix (for ex. [ 1,tid=0x019A]) */
+typedef struct _gcsBUFITEM_PREFIX * gcsBUFITEM_PREFIX_PTR;
+typedef struct _gcsBUFITEM_PREFIX
+{
+ gceBUFITEM type;
+#if gcdHAVEPREFIX
+ gctPOINTER prefixData;
+#endif
+}
+gcsBUFITEM_PREFIX;
+
+/* Buffered string. */
+typedef struct _gcsBUFITEM_STRING * gcsBUFITEM_STRING_PTR;
+typedef struct _gcsBUFITEM_STRING
+{
+ gceBUFITEM type;
+ gctINT indent;
+ gctCONST_STRING message;
+ gctPOINTER messageData;
+ gctUINT messageDataSize;
+}
+gcsBUFITEM_STRING;
+
+/* Buffered string (copy of the string is included with the record). */
+typedef struct _gcsBUFITEM_COPY * gcsBUFITEM_COPY_PTR;
+typedef struct _gcsBUFITEM_COPY
+{
+ gceBUFITEM type;
+ gctINT indent;
+ gctPOINTER messageData;
+ gctUINT messageDataSize;
+}
+gcsBUFITEM_COPY;
+
+/* Memory buffer. */
+typedef struct _gcsBUFITEM_BUFFER * gcsBUFITEM_BUFFER_PTR;
+typedef struct _gcsBUFITEM_BUFFER
+{
+ gceBUFITEM type;
+ gctINT indent;
+ gceDUMP_BUFFER bufferType;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ gctUINT32 dmaAddress;
+#endif
+
+ gctUINT dataSize;
+ gctUINT32 address;
+#if gcdHAVEPREFIX
+ gctPOINTER prefixData;
+#endif
+}
+gcsBUFITEM_BUFFER;
+
+typedef struct _gcsBUFFERED_OUTPUT * gcsBUFFERED_OUTPUT_PTR;
+typedef struct _gcsBUFFERED_OUTPUT
+{
+#if gcdTHREAD_BUFFERS > 1
+ gctUINT32 threadID;
+#endif
+
+#if gcdSHOW_LINE_NUMBER
+ gctUINT64 lineNumber;
+#endif
+
+ gctINT indent;
+
+#if gcdBUFFERED_OUTPUT
+ gctINT start;
+ gctINT index;
+ gctINT count;
+ gctUINT8 buffer[gcdBUFFERED_SIZE];
+#endif
+
+ gcsBUFFERED_OUTPUT_PTR prev;
+ gcsBUFFERED_OUTPUT_PTR next;
+}
+gcsBUFFERED_OUTPUT;
+
+typedef gctUINT (* gcfPRINTSTRING) (
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ );
+
+typedef gctINT (* gcfGETITEMSIZE) (
+ IN gcsBUFITEM_HEAD_PTR Item
+ );
+
+/******************************************************************************\
+******************************* Private Variables ******************************
+\******************************************************************************/
+
+static gcsBUFFERED_OUTPUT _outputBuffer[gcdTHREAD_BUFFERS];
+static gcsBUFFERED_OUTPUT_PTR _outputBufferHead = gcvNULL;
+static gcsBUFFERED_OUTPUT_PTR _outputBufferTail = gcvNULL;
+
+/******************************************************************************\
+****************************** Item Size Functions *****************************
+\******************************************************************************/
+
+#if gcdBUFFERED_OUTPUT
+static gctINT
+_GetTerminatorItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ return gcmSIZEOF(gcsBUFITEM_HEAD);
+}
+
+static gctINT
+_GetPrefixItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+#if gcdHAVEPREFIX
+ gcsBUFITEM_PREFIX_PTR item = (gcsBUFITEM_PREFIX_PTR) Item;
+ gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+ return vlen + gcdPREFIX_SIZE;
+#else
+ return gcmSIZEOF(gcsBUFITEM_PREFIX);
+#endif
+}
+
+static gctINT
+_GetStringItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ gcsBUFITEM_STRING_PTR item = (gcsBUFITEM_STRING_PTR) Item;
+ gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+ return vlen + item->messageDataSize;
+}
+
+static gctINT
+_GetCopyItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ gcsBUFITEM_COPY_PTR item = (gcsBUFITEM_COPY_PTR) Item;
+ gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+ return vlen + item->messageDataSize;
+}
+
+static gctINT
+_GetBufferItemSize(
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+#if gcdHAVEPREFIX
+ gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
+ gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+ return vlen + gcdPREFIX_SIZE + item->dataSize;
+#else
+ gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
+ return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
+#endif
+}
+
+static gcfGETITEMSIZE _itemSize[] =
+{
+ _GetTerminatorItemSize,
+ _GetPrefixItemSize,
+ _GetStringItemSize,
+ _GetCopyItemSize,
+ _GetBufferItemSize
+};
+#endif
+
+/******************************************************************************\
+******************************* Printing Functions *****************************
+\******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE) || gcdBUFFERED_OUTPUT
+static void
+_DirectPrint(
+ gctCONST_STRING Message,
+ ...
+ )
+{
+ gctINT len;
+ char buffer[768];
+ gctARGUMENTS arguments;
+
+ gcmkARGUMENTS_START(arguments, Message);
+ len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), Message, &arguments);
+ gcmkARGUMENTS_END(arguments);
+
+ buffer[len] = '\0';
+ gcmkOUTPUT_STRING(buffer);
+}
+#endif
+
+static int
+_AppendIndent(
+ IN gctINT Indent,
+ IN char * Buffer,
+ IN int BufferSize
+ )
+{
+ gctINT i;
+
+ gctINT len = 0;
+ gctINT indent = Indent % 40;
+
+ for (i = 0; i < indent; i += 1)
+ {
+ Buffer[len++] = ' ';
+ }
+
+ if (indent != Indent)
+ {
+ len += gcmkSPRINTF(
+ Buffer + len, BufferSize - len, " <%d> ", Indent
+ );
+
+ Buffer[len] = '\0';
+ }
+
+ return len;
+}
+
+#if gcdHAVEPREFIX
+static void
+_PrintPrefix(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctPOINTER Data
+ )
+{
+ char buffer[768];
+ gctINT len;
+
+ /* Format the string. */
+ len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, Data);
+ buffer[len] = '\0';
+
+ /* Print the string. */
+ gcmkOUTPUT_STRING(buffer);
+}
+#endif
+
+static void
+_PrintString(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctCONST_STRING Message,
+ IN gctUINT ArgumentSize,
+ IN gctPOINTER Data
+ )
+{
+ char buffer[768];
+ gctINT len;
+
+ /* Append the indent string. */
+ len = _AppendIndent(Indent, buffer, gcmSIZEOF(buffer));
+
+ /* Format the string. */
+ len += gcmkVSPRINTF(buffer + len, gcmSIZEOF(buffer) - len, Message, Data);
+ buffer[len] = '\0';
+
+ /* Add end-of-line if missing. */
+ if (buffer[len - 1] != '\n')
+ {
+ buffer[len++] = '\n';
+ buffer[len] = '\0';
+ }
+
+ /* Print the string. */
+ gcmkOUTPUT_STRING(buffer);
+}
+
+static void
+_PrintBuffer(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctPOINTER PrefixData,
+ IN gctPOINTER Data,
+ IN gctUINT Address,
+ IN gctSIZE_T DataSize,
+ IN gceDUMP_BUFFER Type,
+ IN gctUINT32 DmaAddress
+ )
+{
+ static gctCONST_STRING _titleString[] =
+ {
+ "CONTEXT BUFFER",
+ "USER COMMAND BUFFER",
+ "KERNEL COMMAND BUFFER",
+ "LINK BUFFER",
+ "WAIT LINK BUFFER",
+ ""
+ };
+
+ static const gctINT COLUMN_COUNT = 8;
+
+ gctUINT i, column, address;
+ gctSIZE_T count;
+ gctUINT32_PTR data;
+ gctCHAR buffer[768];
+ gctUINT indent, len;
+ gctBOOL command;
+
+ /* Append space for the prefix. */
+#if gcdHAVEPREFIX
+ indent = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, PrefixData);
+ buffer[indent] = '\0';
+#else
+ indent = 0;
+#endif
+
+ /* Append the indent string. */
+ indent += _AppendIndent(
+ Indent, buffer + indent, gcmSIZEOF(buffer) - indent
+ );
+
+ switch (Type)
+ {
+ case gceDUMP_BUFFER_CONTEXT:
+ case gceDUMP_BUFFER_USER:
+ case gceDUMP_BUFFER_KERNEL:
+ case gceDUMP_BUFFER_LINK:
+ case gceDUMP_BUFFER_WAITLINK:
+ /* Form and print the title string. */
+ gcmkSPRINTF2(
+ buffer + indent, gcmSIZEOF(buffer) - indent,
+ "%s%s\n", _titleString[Type],
+ ((DmaAddress >= Address) && (DmaAddress < Address + DataSize))
+ ? " (CURRENT)" : ""
+ );
+
+ gcmkOUTPUT_STRING(buffer);
+
+ /* Terminate the string. */
+ buffer[indent] = '\0';
+
+ /* This is a command buffer. */
+ command = gcvTRUE;
+ break;
+
+ case gceDUMP_BUFFER_FROM_USER:
+ /* This is not a command buffer. */
+ command = gcvFALSE;
+
+ /* No title. */
+ break;
+
+ default:
+ gcmDBGASSERT(gcvFALSE, "%s", "invalid buffer type");
+
+ /* This is not a command buffer. */
+ command = gcvFALSE;
+ }
+
+ /* Overwrite the prefix with spaces. */
+ for (i = 0; i < indent; i += 1)
+ {
+ buffer[i] = ' ';
+ }
+
+ /* Form and print the opening string. */
+ if (command)
+ {
+ gcmkSPRINTF2(
+ buffer + indent, gcmSIZEOF(buffer) - indent,
+ "@[kernel.command %08X %08X\n", Address, (gctUINT32)DataSize
+ );
+
+ gcmkOUTPUT_STRING(buffer);
+
+ /* Terminate the string. */
+ buffer[indent] = '\0';
+ }
+
+ /* Get initial address. */
+ address = Address;
+
+ /* Cast the data pointer. */
+ data = (gctUINT32_PTR) Data;
+
+ /* Compute the number of double words. */
+ count = DataSize / gcmSIZEOF(gctUINT32);
+
+ /* Print the buffer. */
+ for (i = 0, len = indent, column = 0; i < count; i += 1)
+ {
+ /* Append the address. */
+ if (column == 0)
+ {
+ len += gcmkSPRINTF(
+ buffer + len, gcmSIZEOF(buffer) - len, "0x%08X:", address
+ );
+ }
+
+ /* Append the data value. */
+ len += gcmkSPRINTF2(
+ buffer + len, gcmSIZEOF(buffer) - len, "%c%08X",
+ (address == DmaAddress)? '>' : ' ', data[i]
+ );
+
+ buffer[len] = '\0';
+
+ /* Update the address. */
+ address += gcmSIZEOF(gctUINT32);
+
+ /* Advance column count. */
+ column += 1;
+
+ /* End of line? */
+ if ((column % COLUMN_COUNT) == 0)
+ {
+ /* Append EOL. */
+ gcmkSTRCATSAFE(buffer, gcmSIZEOF(buffer), "\n");
+
+ /* Print the string. */
+ gcmkOUTPUT_STRING(buffer);
+
+ /* Reset. */
+ len = indent;
+ column = 0;
+ }
+ }
+
+ /* Print the last partial string. */
+ if (column != 0)
+ {
+ /* Append EOL. */
+ gcmkSTRCATSAFE(buffer, gcmSIZEOF(buffer), "\n");
+
+ /* Print the string. */
+ gcmkOUTPUT_STRING(buffer);
+ }
+
+ /* Form and print the opening string. */
+ if (command)
+ {
+ buffer[indent] = '\0';
+ gcmkSTRCATSAFE(buffer, gcmSIZEOF(buffer), "] -- command\n");
+ gcmkOUTPUT_STRING(buffer);
+ }
+}
+
+#if gcdBUFFERED_OUTPUT
+static gctUINT
+_PrintNone(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ /* Return the size of the node. */
+ return gcmSIZEOF(gcsBUFITEM_HEAD);
+}
+
+static gctUINT
+_PrintPrefixWrapper(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+#if gcdHAVEPREFIX
+ gcsBUFITEM_PREFIX_PTR item;
+ gctUINT vlen;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_PREFIX_PTR) Item;
+
+ /* Print the message. */
+ _PrintPrefix(OutputBuffer, item->prefixData);
+
+ /* Compute the size of the variable portion of the structure. */
+ vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+
+ /* Return the size of the node. */
+ return vlen + gcdPREFIX_SIZE;
+#else
+ return gcmSIZEOF(gcsBUFITEM_PREFIX);
+#endif
+}
+
+static gctUINT
+_PrintStringWrapper(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ gcsBUFITEM_STRING_PTR item;
+ gctUINT vlen;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_STRING_PTR) Item;
+
+ /* Print the message. */
+ _PrintString(
+ OutputBuffer,
+ item->indent, item->message, item->messageDataSize, item->messageData
+ );
+
+ /* Compute the size of the variable portion of the structure. */
+ vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+
+ /* Return the size of the node. */
+ return vlen + item->messageDataSize;
+}
+
+static gctUINT
+_PrintCopyWrapper(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+ gcsBUFITEM_COPY_PTR item;
+ gctCONST_STRING message;
+ gctUINT vlen;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_COPY_PTR) Item;
+
+ /* Determine the string pointer. */
+ message = (gctCONST_STRING) (item + 1);
+
+ /* Print the message. */
+ _PrintString(
+ OutputBuffer,
+ item->indent, message, item->messageDataSize, item->messageData
+ );
+
+ /* Compute the size of the variable portion of the structure. */
+ vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
+
+ /* Return the size of the node. */
+ return vlen + item->messageDataSize;
+}
+
+static gctUINT
+_PrintBufferWrapper(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gcsBUFITEM_HEAD_PTR Item
+ )
+{
+#if gcdHAVEPREFIX
+ gctUINT32 dmaAddress;
+ gcsBUFITEM_BUFFER_PTR item;
+ gctPOINTER data;
+ gctUINT vlen;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_BUFFER_PTR) Item;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ dmaAddress = item->dmaAddress;
+#else
+ dmaAddress = 0xFFFFFFFF;
+#endif
+
+ if (dmaAddress != 0)
+ {
+ /* Compute the data address. */
+ data = ((gctUINT8_PTR) item->prefixData) + gcdPREFIX_SIZE;
+
+ /* Print buffer. */
+ _PrintBuffer(
+ OutputBuffer,
+ item->indent, item->prefixData,
+ data, item->address, item->dataSize,
+ item->bufferType, dmaAddress
+ );
+ }
+
+ /* Compute the size of the variable portion of the structure. */
+ vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
+
+ /* Return the size of the node. */
+ return vlen + gcdPREFIX_SIZE + item->dataSize;
+#else
+ gctUINT32 dmaAddress;
+ gcsBUFITEM_BUFFER_PTR item;
+
+ /* Get access to the data. */
+ item = (gcsBUFITEM_BUFFER_PTR) Item;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ dmaAddress = item->dmaAddress;
+#else
+ dmaAddress = 0xFFFFFFFF;
+#endif
+
+ if (dmaAddress != 0)
+ {
+ /* Print buffer. */
+ _PrintBuffer(
+ OutputBuffer,
+ item->indent, gcvNULL,
+ item + 1, item->address, item->dataSize,
+ item->bufferType, dmaAddress
+ );
+ }
+
+ /* Return the size of the node. */
+ return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
+#endif
+}
+
+static gcfPRINTSTRING _printArray[] =
+{
+ _PrintNone,
+ _PrintPrefixWrapper,
+ _PrintStringWrapper,
+ _PrintCopyWrapper,
+ _PrintBufferWrapper
+};
+#endif
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+#if gcdBUFFERED_OUTPUT
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+static gcsBUFITEM_BUFFER_PTR
+_FindCurrentDMABuffer(
+ gctUINT32 DmaAddress
+ )
+{
+ gctINT i, skip;
+ gcsBUFITEM_HEAD_PTR item;
+ gcsBUFITEM_BUFFER_PTR dmaCurrent;
+
+ /* Reset the current buffer. */
+ dmaCurrent = gcvNULL;
+
+ /* Get the first stored item. */
+ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+ /* Run through all items. */
+ for (i = 0; i < _outputBufferHead->count; i += 1)
+ {
+ /* Buffer item? */
+ if (item->type == gcvBUFITEM_BUFFER)
+ {
+ gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
+
+ if ((DmaAddress >= buffer->address) &&
+ (DmaAddress < buffer->address + buffer->dataSize))
+ {
+ dmaCurrent = buffer;
+ }
+ }
+
+ /* Get the item size and skip it. */
+ skip = (* _itemSize[item->type]) (item);
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ /* End of the buffer? Wrap around. */
+ if (item->type == gceBUFITEM_NONE)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+ }
+ }
+
+ /* Return result. */
+ return dmaCurrent;
+}
+
+static void
+_EnableAllDMABuffers(
+ void
+ )
+{
+ gctINT i, skip;
+ gcsBUFITEM_HEAD_PTR item;
+
+ /* Get the first stored item. */
+ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+ /* Run through all items. */
+ for (i = 0; i < _outputBufferHead->count; i += 1)
+ {
+ /* Buffer item? */
+ if (item->type == gcvBUFITEM_BUFFER)
+ {
+ gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
+
+ /* Enable the buffer. */
+ buffer->dmaAddress = ~0U;
+ }
+
+ /* Get the item size and skip it. */
+ skip = (* _itemSize[item->type]) (item);
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ /* End of the buffer? Wrap around. */
+ if (item->type == gceBUFITEM_NONE)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+ }
+ }
+}
+
+static void
+_EnableDMABuffers(
+ gctUINT32 DmaAddress,
+ gcsBUFITEM_BUFFER_PTR CurrentDMABuffer
+ )
+{
+ gctINT i, skip, index;
+ gcsBUFITEM_HEAD_PTR item;
+ gcsBUFITEM_BUFFER_PTR buffers[gcdDMA_BUFFER_COUNT];
+
+ /* Reset buffer pointers. */
+ gckOS_ZeroMemory(buffers, gcmSIZEOF(buffers));
+
+ /* Set the current buffer index. */
+ index = -1;
+
+ /* Get the first stored item. */
+ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
+
+ /* Run through all items until the current DMA buffer is found. */
+ for (i = 0; i < _outputBufferHead->count; i += 1)
+ {
+ /* Buffer item? */
+ if (item->type == gcvBUFITEM_BUFFER)
+ {
+ /* Advance the index. */
+ index = (index + 1) % gcdDMA_BUFFER_COUNT;
+
+ /* Add to the buffer array. */
+ buffers[index] = (gcsBUFITEM_BUFFER_PTR) item;
+
+ /* Stop if this is the current DMA buffer. */
+ if ((gcsBUFITEM_BUFFER_PTR) item == CurrentDMABuffer)
+ {
+ break;
+ }
+ }
+
+ /* Get the item size and skip it. */
+ skip = (* _itemSize[item->type]) (item);
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ /* End of the buffer? Wrap around. */
+ if (item->type == gceBUFITEM_NONE)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
+ }
+ }
+
+ /* Enable the found buffers. */
+ gcmDBGASSERT(index != -1, "%d", index);
+
+ for (i = 0; i < gcdDMA_BUFFER_COUNT; i += 1)
+ {
+ if (buffers[index] == gcvNULL)
+ {
+ break;
+ }
+
+ buffers[index]->dmaAddress = DmaAddress;
+
+ index -= 1;
+
+ if (index == -1)
+ {
+ index = gcdDMA_BUFFER_COUNT - 1;
+ }
+ }
+}
+#endif
+
+static void
+_Flush(
+ gctUINT32 DmaAddress
+ )
+{
+ gctINT i, skip;
+ gcsBUFITEM_HEAD_PTR item;
+
+ gcsBUFFERED_OUTPUT_PTR outputBuffer = _outputBufferHead;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ if ((outputBuffer != gcvNULL) && (outputBuffer->count != 0))
+ {
+ /* Find the current DMA buffer. */
+ gcsBUFITEM_BUFFER_PTR dmaCurrent = _FindCurrentDMABuffer(DmaAddress);
+
+ /* Was the current buffer found? */
+ if (dmaCurrent == gcvNULL)
+ {
+ /* No, print all buffers. */
+ _EnableAllDMABuffers();
+ }
+ else
+ {
+ /* Yes, enable only specified number of buffers. */
+ _EnableDMABuffers(DmaAddress, dmaCurrent);
+ }
+ }
+#endif
+
+ while (outputBuffer != gcvNULL)
+ {
+ if (outputBuffer->count != 0)
+ {
+ _DirectPrint("********************************************************************************\n");
+ _DirectPrint("FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n", outputBuffer->count);
+ _DirectPrint("********************************************************************************\n");
+
+ item = (gcsBUFITEM_HEAD_PTR) &outputBuffer->buffer[outputBuffer->start];
+
+ for (i = 0; i < outputBuffer->count; i += 1)
+ {
+ skip = (* _printArray[item->type]) (outputBuffer, item);
+
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ if (item->type == gceBUFITEM_NONE)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) outputBuffer->buffer;
+ }
+ }
+
+ outputBuffer->start = 0;
+ outputBuffer->index = 0;
+ outputBuffer->count = 0;
+ }
+
+ outputBuffer = outputBuffer->next;
+ }
+}
+
+static gcsBUFITEM_HEAD_PTR
+_AllocateItem(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Size
+ )
+{
+ gctINT skip;
+ gcsBUFITEM_HEAD_PTR item, next;
+
+#if gcdENABLE_OVERFLOW
+ if (
+ (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+ ||
+ (
+ (OutputBuffer->index < OutputBuffer->start) &&
+ (OutputBuffer->index + Size >= OutputBuffer->start)
+ )
+ )
+ {
+ if (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+ {
+ if (OutputBuffer->index < OutputBuffer->start)
+ {
+ item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
+
+ while (item->type != gceBUFITEM_NONE)
+ {
+ skip = (* _itemSize[item->type]) (item);
+
+ OutputBuffer->start += skip;
+ OutputBuffer->count -= 1;
+
+ item->type = gceBUFITEM_NONE;
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+ }
+
+ OutputBuffer->start = 0;
+ }
+
+ OutputBuffer->index = 0;
+ }
+
+ item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
+
+ while (OutputBuffer->start - OutputBuffer->index <= Size)
+ {
+ skip = (* _itemSize[item->type]) (item);
+
+ OutputBuffer->start += skip;
+ OutputBuffer->count -= 1;
+
+ item->type = gceBUFITEM_NONE;
+ item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
+
+ if (item->type == gceBUFITEM_NONE)
+ {
+ OutputBuffer->start = 0;
+ break;
+ }
+ }
+ }
+#else
+ if (OutputBuffer->index + Size > gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
+ {
+ _DirectPrint("\nMessage buffer full; forcing message flush.\n\n");
+ _Flush(~0U);
+ }
+#endif
+
+ item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->index];
+
+ OutputBuffer->index += Size;
+ OutputBuffer->count += 1;
+
+ next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + Size);
+ next->type = gceBUFITEM_NONE;
+
+ return item;
+}
+
+#if gcdALIGNBYSIZE
+static void
+_FreeExtraSpace(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctPOINTER Item,
+ IN gctINT ItemSize,
+ IN gctINT FreeSize
+ )
+{
+ gcsBUFITEM_HEAD_PTR next;
+
+ OutputBuffer->index -= FreeSize;
+
+ next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) Item + ItemSize);
+ next->type = gceBUFITEM_NONE;
+}
+#endif
+
+#if gcdHAVEPREFIX
+static void
+_AppendPrefix(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctPOINTER Data
+ )
+{
+ gctUINT8_PTR prefixData;
+ gcsBUFITEM_PREFIX_PTR item;
+ gctINT allocSize;
+
+#if gcdALIGNBYSIZE
+ gctUINT alignment;
+ gctINT size, freeSize;
+#endif
+
+ gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+ /* Determine the maximum item size. */
+ allocSize
+ = gcmSIZEOF(gcsBUFITEM_PREFIX)
+ + gcdPREFIX_SIZE
+ + gcdPREFIX_ALIGNMENT;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_PREFIX_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+ /* Compute the initial prefix data pointer. */
+ prefixData = (gctUINT8_PTR) (item + 1);
+
+ /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+ alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
+ prefixData += alignment;
+#endif
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_PREFIX;
+ item->prefixData = prefixData;
+
+ /* Copy argument value. */
+ gcmkMEMCPY(prefixData, Data, gcdPREFIX_SIZE);
+
+#if gcdALIGNBYSIZE
+ /* Compute the actual node size. */
+ size = gcmSIZEOF(gcsBUFITEM_PREFIX) + gcdPREFIX_SIZE + alignment;
+
+ /* Free extra memory if any. */
+ freeSize = allocSize - size;
+ if (freeSize != 0)
+ {
+ _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+ }
+#endif
+}
+#endif
+
+static void
+_AppendString(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctCONST_STRING Message,
+ IN gctUINT ArgumentSize,
+ IN gctPOINTER Data
+ )
+{
+ gctUINT8_PTR messageData;
+ gcsBUFITEM_STRING_PTR item;
+ gctINT allocSize;
+
+#if gcdALIGNBYSIZE
+ gctUINT alignment;
+ gctINT size, freeSize;
+#endif
+
+ /* Determine the maximum item size. */
+ allocSize
+ = gcmSIZEOF(gcsBUFITEM_STRING)
+ + ArgumentSize
+ + gcdVARARG_ALIGNMENT;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_STRING_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+ /* Compute the initial message data pointer. */
+ messageData = (gctUINT8_PTR) (item + 1);
+
+ /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+ alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
+ messageData += alignment;
+#endif
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_STRING;
+ item->indent = Indent;
+ item->message = Message;
+ item->messageData = messageData;
+ item->messageDataSize = ArgumentSize;
+
+ /* Copy argument value. */
+ if (ArgumentSize != 0)
+ {
+ gcmkMEMCPY(messageData, Data, ArgumentSize);
+ }
+
+#if gcdALIGNBYSIZE
+ /* Compute the actual node size. */
+ size = gcmSIZEOF(gcsBUFITEM_STRING) + ArgumentSize + alignment;
+
+ /* Free extra memory if any. */
+ freeSize = allocSize - size;
+ if (freeSize != 0)
+ {
+ _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+ }
+#endif
+}
+
+static void
+_AppendCopy(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctCONST_STRING Message,
+ IN gctUINT ArgumentSize,
+ IN gctPOINTER Data
+ )
+{
+ gctUINT8_PTR messageData;
+ gcsBUFITEM_COPY_PTR item;
+ gctINT allocSize;
+ gctINT messageLength;
+ gctCONST_STRING message;
+
+#if gcdALIGNBYSIZE
+ gctUINT alignment;
+ gctINT size, freeSize;
+#endif
+
+ /* Get the length of the string. */
+ messageLength = strlen(Message) + 1;
+
+ /* Determine the maximum item size. */
+ allocSize
+ = gcmSIZEOF(gcsBUFITEM_COPY)
+ + messageLength
+ + ArgumentSize
+ + gcdVARARG_ALIGNMENT;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_COPY_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+ /* Determine the message placement. */
+ message = (gctCONST_STRING) (item + 1);
+
+ /* Compute the initial message data pointer. */
+ messageData = (gctUINT8_PTR) message + messageLength;
+
+ /* Align the data pointer as necessary. */
+#if gcdALIGNBYSIZE
+ if (ArgumentSize == 0)
+ {
+ alignment = 0;
+ }
+ else
+ {
+ alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
+ messageData += alignment;
+ }
+#endif
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_COPY;
+ item->indent = Indent;
+ item->messageData = messageData;
+ item->messageDataSize = ArgumentSize;
+
+ /* Copy the message. */
+ gcmkMEMCPY((gctPOINTER) message, Message, messageLength);
+
+ /* Copy argument value. */
+ if (ArgumentSize != 0)
+ {
+ gcmkMEMCPY(messageData, Data, ArgumentSize);
+ }
+
+#if gcdALIGNBYSIZE
+ /* Compute the actual node size. */
+ size
+ = gcmSIZEOF(gcsBUFITEM_COPY)
+ + messageLength
+ + ArgumentSize
+ + alignment;
+
+ /* Free extra memory if any. */
+ freeSize = allocSize - size;
+ if (freeSize != 0)
+ {
+ _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+ }
+#endif
+}
+
+static void
+_AppendBuffer(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctPOINTER PrefixData,
+ IN gctPOINTER Data,
+ IN gctUINT Address,
+ IN gctUINT DataSize,
+ IN gceDUMP_BUFFER Type,
+ IN gctUINT32 DmaAddress
+ )
+{
+#if gcdHAVEPREFIX
+ gctUINT8_PTR prefixData;
+ gcsBUFITEM_BUFFER_PTR item;
+ gctINT allocSize;
+ gctPOINTER data;
+
+#if gcdALIGNBYSIZE
+ gctUINT alignment;
+ gctINT size, freeSize;
+#endif
+
+ gcmDBGASSERT(DataSize != 0, "%d", DataSize);
+ gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+ /* Determine the maximum item size. */
+ allocSize
+ = gcmSIZEOF(gcsBUFITEM_BUFFER)
+ + gcdPREFIX_SIZE
+ + gcdPREFIX_ALIGNMENT
+ + DataSize;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, allocSize);
+
+ /* Compute the initial prefix data pointer. */
+ prefixData = (gctUINT8_PTR) (item + 1);
+
+#if gcdALIGNBYSIZE
+ /* Align the data pointer as necessary. */
+ alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
+ prefixData += alignment;
+#endif
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_BUFFER;
+ item->indent = Indent;
+ item->bufferType = Type;
+ item->dataSize = DataSize;
+ item->address = Address;
+ item->prefixData = prefixData;
+
+#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
+ item->dmaAddress = DmaAddress;
+#endif
+
+ /* Copy prefix data. */
+ gcmkMEMCPY(prefixData, PrefixData, gcdPREFIX_SIZE);
+
+ /* Compute the data pointer. */
+ data = prefixData + gcdPREFIX_SIZE;
+
+ /* Copy argument value. */
+ gcmkMEMCPY(data, Data, DataSize);
+
+#if gcdALIGNBYSIZE
+ /* Compute the actual node size. */
+ size
+ = gcmSIZEOF(gcsBUFITEM_BUFFER)
+ + gcdPREFIX_SIZE
+ + alignment
+ + DataSize;
+
+ /* Free extra memory if any. */
+ freeSize = allocSize - size;
+ if (freeSize != 0)
+ {
+ _FreeExtraSpace(OutputBuffer, item, size, freeSize);
+ }
+#endif
+#else
+ gcsBUFITEM_BUFFER_PTR item;
+ gctINT size;
+
+ gcmDBGASSERT(DataSize != 0, "%d", DataSize);
+ gcmDBGASSERT(Data != gcvNULL, "%p", Data);
+
+ /* Determine the maximum item size. */
+ size = gcmSIZEOF(gcsBUFITEM_BUFFER) + DataSize;
+
+ /* Allocate prefix item. */
+ item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, size);
+
+ /* Set item data. */
+ item->type = gcvBUFITEM_BUFFER;
+ item->indent = Indent;
+ item->dataSize = DataSize;
+ item->address = Address;
+
+ /* Copy argument value. */
+ gcmkMEMCPY(item + 1, Data, DataSize);
+#endif
+}
+#endif
+
+static gcmINLINE void
+_InitBuffers(
+ void
+ )
+{
+ int i;
+
+ if (_outputBufferHead == gcvNULL)
+ {
+ for (i = 0; i < gcdTHREAD_BUFFERS; i += 1)
+ {
+ if (_outputBufferTail == gcvNULL)
+ {
+ _outputBufferHead = &_outputBuffer[i];
+ }
+ else
+ {
+ _outputBufferTail->next = &_outputBuffer[i];
+ }
+
+#if gcdTHREAD_BUFFERS > 1
+ _outputBuffer[i].threadID = ~0U;
+#endif
+
+ _outputBuffer[i].prev = _outputBufferTail;
+ _outputBuffer[i].next = gcvNULL;
+
+ _outputBufferTail = &_outputBuffer[i];
+ }
+ }
+}
+
+static gcmINLINE gcsBUFFERED_OUTPUT_PTR
+_GetOutputBuffer(
+ void
+ )
+{
+ gcsBUFFERED_OUTPUT_PTR outputBuffer;
+
+#if gcdTHREAD_BUFFERS > 1
+ /* Get the current thread ID. */
+ gctUINT32 ThreadID = gcmkGETTHREADID();
+
+ /* Locate the output buffer for the thread. */
+ outputBuffer = _outputBufferHead;
+
+ while (outputBuffer != gcvNULL)
+ {
+ if (outputBuffer->threadID == ThreadID)
+ {
+ break;
+ }
+
+ outputBuffer = outputBuffer->next;
+ }
+
+ /* No matching buffer found? */
+ if (outputBuffer == gcvNULL)
+ {
+ /* Get the tail for the buffer. */
+ outputBuffer = _outputBufferTail;
+
+ /* Move it to the head. */
+ _outputBufferTail = _outputBufferTail->prev;
+ _outputBufferTail->next = gcvNULL;
+
+ outputBuffer->prev = gcvNULL;
+ outputBuffer->next = _outputBufferHead;
+
+ _outputBufferHead->prev = outputBuffer;
+ _outputBufferHead = outputBuffer;
+
+ /* Reset the buffer. */
+ outputBuffer->threadID = ThreadID;
+#if gcdBUFFERED_OUTPUT
+ outputBuffer->start = 0;
+ outputBuffer->index = 0;
+ outputBuffer->count = 0;
+#endif
+#if gcdSHOW_LINE_NUMBER
+ outputBuffer->lineNumber = 0;
+#endif
+ }
+#else
+ outputBuffer = _outputBufferHead;
+#endif
+
+ return outputBuffer;
+}
+
+static gcmINLINE int _GetArgumentSize(
+ IN gctCONST_STRING Message
+ )
+{
+ int i, count;
+
+ gcmDBGASSERT(Message != gcvNULL, "%p", Message);
+
+ for (i = 0, count = 0; Message[i]; i += 1)
+ {
+ if (Message[i] == '%')
+ {
+ count += 1;
+ }
+ }
+
+ return count * gcmSIZEOF(gctUINT32);
+}
+
+#if gcdHAVEPREFIX
+static void
+_InitPrefixData(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctPOINTER Data
+ )
+{
+ gctUINT8_PTR data = (gctUINT8_PTR) Data;
+
+#if gcdSHOW_TIME
+ {
+ gctUINT64 time;
+ gckOS_GetProfileTick(&time);
+ gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
+ * ((gctUINT64_PTR) data) = time;
+ data += gcmSIZEOF(gctUINT64);
+ }
+#endif
+
+#if gcdSHOW_LINE_NUMBER
+ {
+ gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
+ * ((gctUINT64_PTR) data) = OutputBuffer->lineNumber;
+ data += gcmSIZEOF(gctUINT64);
+ }
+#endif
+
+#if gcdSHOW_PROCESS_ID
+ {
+ gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
+ * ((gctUINT32_PTR) data) = gcmkGETPROCESSID();
+ data += gcmSIZEOF(gctUINT32);
+ }
+#endif
+
+#if gcdSHOW_THREAD_ID
+ {
+ gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
+ * ((gctUINT32_PTR) data) = gcmkGETTHREADID();
+ }
+#endif
+}
+#endif
+
+static void
+_Print(
+ IN gctUINT ArgumentSize,
+ IN gctBOOL CopyMessage,
+ IN gctCONST_STRING Message,
+ IN gctARGUMENTS * Arguments
+ )
+{
+ gcsBUFFERED_OUTPUT_PTR outputBuffer;
+ gcmkDECLARE_LOCK(lockHandle);
+
+ gcmkLOCKSECTION(lockHandle);
+
+ /* Initialize output buffer list. */
+ _InitBuffers();
+
+ /* Locate the proper output buffer. */
+ outputBuffer = _GetOutputBuffer();
+
+ /* Update the line number. */
+#if gcdSHOW_LINE_NUMBER
+ outputBuffer->lineNumber += 1;
+#endif
+
+ /* Print prefix. */
+#if gcdHAVEPREFIX
+ {
+ gctUINT8_PTR alignedPrefixData;
+ gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
+
+ /* Compute aligned pointer. */
+ alignedPrefixData = prefixData;
+ gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
+
+ /* Initialize the prefix data. */
+ _InitPrefixData(outputBuffer, alignedPrefixData);
+
+ /* Print the prefix. */
+ gcdOUTPUTPREFIX(outputBuffer, alignedPrefixData);
+ }
+#endif
+
+ /* Form the indent string. */
+ if (strncmp(Message, "--", 2) == 0)
+ {
+ outputBuffer->indent -= 2;
+ }
+
+ /* Print the message. */
+ if (CopyMessage)
+ {
+ gcdOUTPUTCOPY(
+ outputBuffer, outputBuffer->indent,
+ Message, ArgumentSize, (gctPOINTER) Arguments
+ );
+ }
+ else
+ {
+ gcdOUTPUTSTRING(
+ outputBuffer, outputBuffer->indent,
+ Message, ArgumentSize, ((gctPOINTER) Arguments)
+ );
+ }
+
+ /* Check increasing indent. */
+ if (strncmp(Message, "++", 2) == 0)
+ {
+ outputBuffer->indent += 2;
+ }
+
+ gcmkUNLOCKSECTION(lockHandle);
+}
+
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#ifdef __QNXNTO__
+
+extern volatile unsigned g_nQnxInIsrs;
+
+#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
+{ \
+ if (atomic_add_value(&g_nQnxInIsrs, 1) == 0) \
+ { \
+ gctARGUMENTS __arguments__; \
+ gcmkARGUMENTS_START(__arguments__, Message); \
+ _Print(ArgumentSize, CopyMessage, Message, &__arguments__); \
+ gcmkARGUMENTS_END(__arguments__); \
+ } \
+ atomic_sub(&g_nQnxInIsrs, 1); \
+}
+
+#else
+
+#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
+{ \
+ gctARGUMENTS __arguments__; \
+ gcmkARGUMENTS_START(__arguments__, Message); \
+ _Print(ArgumentSize, CopyMessage, Message, &__arguments__); \
+ gcmkARGUMENTS_END(__arguments__); \
+}
+
+#endif
+
+/******************************************************************************\
+********************************** Debug Code **********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Print
+**
+** Send a message to the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_PrintN
+**
+** Send a message to the debugger.
+**
+** INPUT:
+**
+** gctUINT ArgumentSize
+** The size of the optional arguments in bytes.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_PrintN(
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_CopyPrint
+**
+** Send a message to the debugger. If in buffered output mode, the entire
+** message will be copied into the buffer instead of using the pointer to
+** the string.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_CopyPrint(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvTRUE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DumpBuffer
+**
+** Print the contents of the specified buffer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctPOINTER Buffer
+** Pointer to the buffer to print.
+**
+** gctUINT Size
+** Size of the buffer.
+**
+** gceDUMP_BUFFER Type
+** Buffer type.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DumpBuffer(
+ IN gckOS Os,
+ IN gctPOINTER Buffer,
+ IN gctSIZE_T Size,
+ IN gceDUMP_BUFFER Type,
+ IN gctBOOL CopyMessage
+ )
+{
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address = 0;
+ gcsBUFFERED_OUTPUT_PTR outputBuffer = gcvNULL;
+ static gctBOOL userLocked;
+ gctCHAR *buffer = (gctCHAR*)Buffer;
+
+ gcmkDECLARE_LOCK(lockHandle);
+
+ /* Request lock when not coming from user,
+ or coming from user and not yet locked
+ and message is starting with @[. */
+ if (Type == gceDUMP_BUFFER_FROM_USER)
+ {
+ if ((Size > 2)
+ && (!strncmp(buffer, "@[", 2) || !strncmp(buffer, "#[", 2))
+ )
+ {
+ /* Beginning of a user dump. */
+ gcmkLOCKSECTION(lockHandle);
+ userLocked = gcvTRUE;
+ }
+ /* Else, let it pass through. */
+
+ /* Some format check. */
+ if ((Size > 2)
+ && (buffer[0] == '@' || buffer[0] == '#')
+ && (buffer[1] != '[')
+ )
+ {
+ /* No error tolerence in parser, so we stop on error to make noise. */
+ for (;;)
+ {
+ gcmkPRINT(
+ "[galcore]: %s(%d): Illegal dump message %s\n",
+ __FUNCTION__, __LINE__,
+ buffer
+ );
+
+ gckOS_Delay(Os, 10 * 1000);
+ }
+ }
+ }
+ else
+ {
+ gcmkLOCKSECTION(lockHandle);
+ userLocked = gcvFALSE;
+ }
+
+ if (Buffer != gcvNULL)
+ {
+ /* Initialize output buffer list. */
+ _InitBuffers();
+
+ /* Locate the proper output buffer. */
+ outputBuffer = _GetOutputBuffer();
+
+ /* Update the line number. */
+#if gcdSHOW_LINE_NUMBER
+ outputBuffer->lineNumber += 1;
+#endif
+
+ /* Get the physical address of the buffer. */
+ if (Type != gceDUMP_BUFFER_FROM_USER)
+ {
+ gcmkVERIFY_OK(gckOS_GetPhysicalAddress(Os, Buffer, &physical));
+ gcmkSAFECASTPHYSADDRT(address, physical);
+ }
+ else
+ {
+ address = 0;
+ }
+
+#if gcdHAVEPREFIX
+ {
+ gctUINT8_PTR alignedPrefixData;
+ gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
+
+ /* Compute aligned pointer. */
+ alignedPrefixData = prefixData;
+ gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
+
+ /* Initialize the prefix data. */
+ _InitPrefixData(outputBuffer, alignedPrefixData);
+
+ /* Print/schedule the buffer. */
+ gcdOUTPUTBUFFER(
+ outputBuffer, outputBuffer->indent,
+ alignedPrefixData, Buffer, address, Size, Type, 0
+ );
+ }
+#else
+ /* Print/schedule the buffer. */
+ if (Type == gceDUMP_BUFFER_FROM_USER)
+ {
+ gckOS_CopyPrint(Buffer);
+ }
+ else
+ {
+ gcdOUTPUTBUFFER(
+ outputBuffer, outputBuffer->indent,
+ gcvNULL, Buffer, address, Size, Type, 0
+ );
+ }
+#endif
+ }
+
+ /* Unlock when not coming from user,
+ or coming from user and not yet locked. */
+ if (userLocked)
+ {
+ gctUINT i = 0;
+
+ while (i < Size && buffer[i])
+ {
+ if (buffer[i] == ']')
+ {
+ /* End of a user dump. */
+ userLocked = gcvFALSE;
+ gcmkUNLOCKSECTION(lockHandle);
+
+ break;
+ }
+
+ i++;
+ }
+ /* Else, let it pass through, don't unlock. */
+ }
+ else
+ {
+ gcmkUNLOCKSECTION(lockHandle);
+ }
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTrace
+**
+** Send a leveled message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level of message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if (Level > _debugLevel)
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceN
+**
+** Send a leveled message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level of message.
+**
+** gctUINT ArgumentSize
+** The size of the optional arguments in bytes.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceN(
+ IN gctUINT32 Level,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if (Level > _debugLevel)
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceZone
+**
+** Send a leveled and zoned message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level for message.
+**
+** gctUINT32 Zone
+** Debug zone for message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if ((Level > _debugLevel) || !(Zone & _debugZones))
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceZoneN
+**
+** Send a leveled and zoned message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level for message.
+**
+** gctUINT32 Zone
+** Debug zone for message.
+**
+** gctUINT ArgumentSize
+** The size of the optional arguments in bytes.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceZoneN(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if ((Level > _debugLevel) || !(Zone & _debugZones))
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugBreak
+**
+** Break into the debugger.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugBreak(
+ void
+ )
+{
+ gckOS_DebugTrace(gcvLEVEL_ERROR, "%s(%d)", __FUNCTION__, __LINE__);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugFatal
+**
+** Send a message to the debugger and break into the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmkPRINT_VERSION();
+ gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
+
+ /* Break into the debugger. */
+ gckOS_DebugBreak();
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevel
+**
+** Set the debug level.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ )
+{
+ _debugLevel = Level;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZone
+**
+** Set the debug zone.
+**
+** INPUT:
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ )
+{
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevelZone
+**
+** Set the debug level and zone.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ )
+{
+ _debugLevel = Level;
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZones
+**
+** Enable or disable debug zones.
+**
+** INPUT:
+**
+** gctUINT32 Zones
+** Debug zones to enable or disable.
+**
+** gctBOOL Enable
+** Set to gcvTRUE to enable the zones (or the Zones with the current
+** zones) or gcvFALSE to disable the specified Zones.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ )
+{
+ if (Enable)
+ {
+ /* Enable the zones. */
+ _debugZones |= Zones;
+ }
+ else
+ {
+ /* Disable the zones. */
+ _debugZones &= ~Zones;
+ }
+}
+
+/*******************************************************************************
+**
+** gckOS_Verify
+**
+** Called to verify the result of a function call.
+**
+** INPUT:
+**
+** gceSTATUS Status
+** Function call result.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Verify(
+ IN gceSTATUS status
+ )
+{
+ _lastError = status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugFlush
+**
+** Force messages to be flushed out.
+**
+** INPUT:
+**
+** gctCONST_STRING CallerName
+** Name of the caller function.
+**
+** gctUINT LineNumber
+** Line number of the caller.
+**
+** gctUINT32 DmaAddress
+** The current DMA address or ~0U to ignore.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugFlush(
+ gctCONST_STRING CallerName,
+ gctUINT LineNumber,
+ gctUINT32 DmaAddress
+ )
+{
+#if gcdBUFFERED_OUTPUT
+ _DirectPrint("\nFlush requested by %s(%d).\n\n", CallerName, LineNumber);
+ _Flush(DmaAddress);
+#endif
+}
+gctCONST_STRING
+gckOS_DebugStatus2Name(
+ gceSTATUS status
+ )
+{
+ switch (status)
+ {
+ case gcvSTATUS_OK:
+ return "gcvSTATUS_OK";
+ case gcvSTATUS_TRUE:
+ return "gcvSTATUS_TRUE";
+ case gcvSTATUS_NO_MORE_DATA:
+ return "gcvSTATUS_NO_MORE_DATA";
+ case gcvSTATUS_CACHED:
+ return "gcvSTATUS_CACHED";
+ case gcvSTATUS_MIPMAP_TOO_LARGE:
+ return "gcvSTATUS_MIPMAP_TOO_LARGE";
+ case gcvSTATUS_NAME_NOT_FOUND:
+ return "gcvSTATUS_NAME_NOT_FOUND";
+ case gcvSTATUS_NOT_OUR_INTERRUPT:
+ return "gcvSTATUS_NOT_OUR_INTERRUPT";
+ case gcvSTATUS_MISMATCH:
+ return "gcvSTATUS_MISMATCH";
+ case gcvSTATUS_MIPMAP_TOO_SMALL:
+ return "gcvSTATUS_MIPMAP_TOO_SMALL";
+ case gcvSTATUS_LARGER:
+ return "gcvSTATUS_LARGER";
+ case gcvSTATUS_SMALLER:
+ return "gcvSTATUS_SMALLER";
+ case gcvSTATUS_CHIP_NOT_READY:
+ return "gcvSTATUS_CHIP_NOT_READY";
+ case gcvSTATUS_NEED_CONVERSION:
+ return "gcvSTATUS_NEED_CONVERSION";
+ case gcvSTATUS_SKIP:
+ return "gcvSTATUS_SKIP";
+ case gcvSTATUS_DATA_TOO_LARGE:
+ return "gcvSTATUS_DATA_TOO_LARGE";
+ case gcvSTATUS_INVALID_CONFIG:
+ return "gcvSTATUS_INVALID_CONFIG";
+ case gcvSTATUS_CHANGED:
+ return "gcvSTATUS_CHANGED";
+ case gcvSTATUS_NOT_SUPPORT_DITHER:
+ return "gcvSTATUS_NOT_SUPPORT_DITHER";
+
+ case gcvSTATUS_INVALID_ARGUMENT:
+ return "gcvSTATUS_INVALID_ARGUMENT";
+ case gcvSTATUS_INVALID_OBJECT:
+ return "gcvSTATUS_INVALID_OBJECT";
+ case gcvSTATUS_OUT_OF_MEMORY:
+ return "gcvSTATUS_OUT_OF_MEMORY";
+ case gcvSTATUS_MEMORY_LOCKED:
+ return "gcvSTATUS_MEMORY_LOCKED";
+ case gcvSTATUS_MEMORY_UNLOCKED:
+ return "gcvSTATUS_MEMORY_UNLOCKED";
+ case gcvSTATUS_HEAP_CORRUPTED:
+ return "gcvSTATUS_HEAP_CORRUPTED";
+ case gcvSTATUS_GENERIC_IO:
+ return "gcvSTATUS_GENERIC_IO";
+ case gcvSTATUS_INVALID_ADDRESS:
+ return "gcvSTATUS_INVALID_ADDRESS";
+ case gcvSTATUS_CONTEXT_LOSSED:
+ return "gcvSTATUS_CONTEXT_LOSSED";
+ case gcvSTATUS_TOO_COMPLEX:
+ return "gcvSTATUS_TOO_COMPLEX";
+ case gcvSTATUS_BUFFER_TOO_SMALL:
+ return "gcvSTATUS_BUFFER_TOO_SMALL";
+ case gcvSTATUS_INTERFACE_ERROR:
+ return "gcvSTATUS_INTERFACE_ERROR";
+ case gcvSTATUS_NOT_SUPPORTED:
+ return "gcvSTATUS_NOT_SUPPORTED";
+ case gcvSTATUS_MORE_DATA:
+ return "gcvSTATUS_MORE_DATA";
+ case gcvSTATUS_TIMEOUT:
+ return "gcvSTATUS_TIMEOUT";
+ case gcvSTATUS_OUT_OF_RESOURCES:
+ return "gcvSTATUS_OUT_OF_RESOURCES";
+ case gcvSTATUS_INVALID_DATA:
+ return "gcvSTATUS_INVALID_DATA";
+ case gcvSTATUS_INVALID_MIPMAP:
+ return "gcvSTATUS_INVALID_MIPMAP";
+ case gcvSTATUS_NOT_FOUND:
+ return "gcvSTATUS_NOT_FOUND";
+ case gcvSTATUS_NOT_ALIGNED:
+ return "gcvSTATUS_NOT_ALIGNED";
+ case gcvSTATUS_INVALID_REQUEST:
+ return "gcvSTATUS_INVALID_REQUEST";
+ case gcvSTATUS_GPU_NOT_RESPONDING:
+ return "gcvSTATUS_GPU_NOT_RESPONDING";
+ case gcvSTATUS_TIMER_OVERFLOW:
+ return "gcvSTATUS_TIMER_OVERFLOW";
+ case gcvSTATUS_VERSION_MISMATCH:
+ return "gcvSTATUS_VERSION_MISMATCH";
+ case gcvSTATUS_LOCKED:
+ return "gcvSTATUS_LOCKED";
+ case gcvSTATUS_INTERRUPTED:
+ return "gcvSTATUS_INTERRUPTED";
+ case gcvSTATUS_DEVICE:
+ return "gcvSTATUS_DEVICE";
+ case gcvSTATUS_NOT_MULTI_PIPE_ALIGNED:
+ return "gcvSTATUS_NOT_MULTI_PIPE_ALIGNED";
+
+ /* Linker errors. */
+ case gcvSTATUS_GLOBAL_TYPE_MISMATCH:
+ return "gcvSTATUS_GLOBAL_TYPE_MISMATCH";
+ case gcvSTATUS_TOO_MANY_ATTRIBUTES:
+ return "gcvSTATUS_TOO_MANY_ATTRIBUTES";
+ case gcvSTATUS_TOO_MANY_UNIFORMS:
+ return "gcvSTATUS_TOO_MANY_UNIFORMS";
+ case gcvSTATUS_TOO_MANY_VARYINGS:
+ return "gcvSTATUS_TOO_MANY_VARYINGS";
+ case gcvSTATUS_UNDECLARED_VARYING:
+ return "gcvSTATUS_UNDECLARED_VARYING";
+ case gcvSTATUS_VARYING_TYPE_MISMATCH:
+ return "gcvSTATUS_VARYING_TYPE_MISMATCH";
+ case gcvSTATUS_MISSING_MAIN:
+ return "gcvSTATUS_MISSING_MAIN";
+ case gcvSTATUS_NAME_MISMATCH:
+ return "gcvSTATUS_NAME_MISMATCH";
+ case gcvSTATUS_INVALID_INDEX:
+ return "gcvSTATUS_INVALID_INDEX";
+ case gcvSTATUS_UNIFORM_MISMATCH:
+ return "gcvSTATUS_UNIFORM_MISMATCH";
+ case gcvSTATUS_UNSAT_LIB_SYMBOL:
+ return "gcvSTATUS_UNSAT_LIB_SYMBOL";
+ case gcvSTATUS_TOO_MANY_SHADERS:
+ return "gcvSTATUS_TOO_MANY_SHADERS";
+ case gcvSTATUS_LINK_INVALID_SHADERS:
+ return "gcvSTATUS_LINK_INVALID_SHADERS";
+ case gcvSTATUS_CS_NO_WORKGROUP_SIZE:
+ return "gcvSTATUS_CS_NO_WORKGROUP_SIZE";
+ case gcvSTATUS_LINK_LIB_ERROR:
+ return "gcvSTATUS_LINK_LIB_ERROR";
+ case gcvSTATUS_SHADER_VERSION_MISMATCH:
+ return "gcvSTATUS_SHADER_VERSION_MISMATCH";
+ case gcvSTATUS_TOO_MANY_INSTRUCTION:
+ return "gcvSTATUS_TOO_MANY_INSTRUCTION";
+ case gcvSTATUS_SSBO_MISMATCH:
+ return "gcvSTATUS_SSBO_MISMATCH";
+ case gcvSTATUS_TOO_MANY_OUTPUT:
+ return "gcvSTATUS_TOO_MANY_OUTPUT";
+ case gcvSTATUS_TOO_MANY_INPUT:
+ return "gcvSTATUS_TOO_MANY_INPUT";
+ case gcvSTATUS_NOT_SUPPORT_CL:
+ return "gcvSTATUS_NOT_SUPPORT_CL";
+ case gcvSTATUS_NOT_SUPPORT_INTEGER:
+ return "gcvSTATUS_NOT_SUPPORT_INTEGER";
+ case gcvSTATUS_UNIFORM_TYPE_MISMATCH:
+ return "gcvSTATUS_UNIFORM_TYPE_MISMATCH";
+ case gcvSTATUS_MISSING_PRIMITIVE_TYPE:
+ return "gcvSTATUS_MISSING_PRIMITIVE_TYPE";
+ case gcvSTATUS_MISSING_OUTPUT_VERTEX_COUNT:
+ return "gcvSTATUS_MISSING_OUTPUT_VERTEX_COUNT";
+ case gcvSTATUS_NON_INVOCATION_ID_AS_INDEX:
+ return "gcvSTATUS_NON_INVOCATION_ID_AS_INDEX";
+ case gcvSTATUS_INPUT_ARRAY_SIZE_MISMATCH:
+ return "gcvSTATUS_INPUT_ARRAY_SIZE_MISMATCH";
+ case gcvSTATUS_OUTPUT_ARRAY_SIZE_MISMATCH:
+ return "gcvSTATUS_OUTPUT_ARRAY_SIZE_MISMATCH";
+
+ /* Compiler errors. */
+ case gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR:
+ return "gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR";
+ case gcvSTATUS_COMPILER_FE_PARSER_ERROR:
+ return "gcvSTATUS_COMPILER_FE_PARSER_ERROR";
+ default:
+ return "nil";
+ }
+}
+
+/*******************************************************************************
+***** Binary Trace *************************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+** _VerifyMessage
+**
+** Verify a binary trace message, decode it to human readable string and print
+** it.
+**
+** ARGUMENTS:
+**
+** gctCONST_STRING Buffer
+** Pointer to buffer to store.
+**
+** gctSIZE_T Bytes
+** Buffer length.
+*/
+void
+_VerifyMessage(
+ IN gctCONST_STRING Buffer,
+ IN gctSIZE_T Bytes
+ )
+{
+ char arguments[150] = {0};
+ char format[100] = {0};
+
+ gctSTRING function;
+ gctPOINTER args;
+ gctUINT32 numArguments;
+ int i = 0;
+ gctUINT32 functionBytes;
+
+ gcsBINARY_TRACE_MESSAGE_PTR message = (gcsBINARY_TRACE_MESSAGE_PTR)Buffer;
+
+ /* Check signature. */
+ if (message->signature != 0x7FFFFFFF)
+ {
+ gcmkPRINT("Signature error");
+ return;
+ }
+
+ /* Get function name. */
+ function = (gctSTRING)&message->payload;
+ functionBytes = (gctUINT32)strlen(function) + 1;
+
+ /* Get arguments number. */
+ numArguments = message->numArguments;
+
+ /* Get arguments . */
+ args = function + functionBytes;
+
+ /* Prepare format string. */
+ while (numArguments--)
+ {
+ format[i++] = '%';
+ format[i++] = 'x';
+ format[i++] = ' ';
+ }
+
+ format[i] = '\0';
+
+ if (numArguments)
+ {
+ gcmkVSPRINTF(arguments, 150, format, (gctARGUMENTS *) &args);
+ }
+
+ gcmkPRINT("[%d](%d): %s(%d) %s",
+ message->pid,
+ message->tid,
+ function,
+ message->line,
+ arguments);
+}
+
+
+/*******************************************************************************
+** gckOS_WriteToRingBuffer
+**
+** Store a buffer to ring buffer.
+**
+** ARGUMENTS:
+**
+** gctCONST_STRING Buffer
+** Pointer to buffer to store.
+**
+** gctSIZE_T Bytes
+** Buffer length.
+*/
+void
+gckOS_WriteToRingBuffer(
+ IN gctCONST_STRING Buffer,
+ IN gctSIZE_T Bytes
+ )
+{
+
+}
+
+/*******************************************************************************
+** gckOS_BinaryTrace
+**
+** Output a binary trace message.
+**
+** ARGUMENTS:
+**
+** gctCONST_STRING Function
+** Pointer to function name.
+**
+** gctINT Line
+** Line number.
+**
+** gctCONST_STRING Text OPTIONAL
+** Optional pointer to a descriptive text.
+**
+** ...
+** Optional arguments to the descriptive text.
+*/
+void
+gckOS_BinaryTrace(
+ IN gctCONST_STRING Function,
+ IN gctINT Line,
+ IN gctCONST_STRING Text OPTIONAL,
+ ...
+ )
+{
+ static gctUINT32 messageSignature = 0x7FFFFFFF;
+ char buffer[gcdBINARY_TRACE_MESSAGE_SIZE];
+ gctUINT32 numArguments = 0;
+ gctUINT32 functionBytes;
+ gctUINT32 i = 0;
+ gctSTRING payload;
+ gcsBINARY_TRACE_MESSAGE_PTR message = (gcsBINARY_TRACE_MESSAGE_PTR)buffer;
+
+ /* Calculate arguments number. */
+ if (Text)
+ {
+ while (Text[i] != '\0')
+ {
+ if (Text[i] == '%')
+ {
+ numArguments++;
+ }
+ i++;
+ }
+ }
+
+ message->signature = messageSignature;
+ message->pid = gcmkGETPROCESSID();
+ message->tid = gcmkGETTHREADID();
+ message->line = Line;
+ message->numArguments = numArguments;
+
+ payload = (gctSTRING)&message->payload;
+
+ /* Function name. */
+ functionBytes = (gctUINT32)gcmkSTRLEN(Function) + 1;
+ gcmkMEMCPY(payload, Function, functionBytes);
+
+ /* Advance to next payload. */
+ payload += functionBytes;
+
+ /* Arguments value. */
+ if (numArguments)
+ {
+ gctARGUMENTS p;
+ gcmkARGUMENTS_START(p, Text);
+
+ for (i = 0; i < numArguments; ++i)
+ {
+ gctPOINTER value = gcmkARGUMENTS_ARG(p, gctPOINTER);
+ gcmkMEMCPY(payload, &value, gcmSIZEOF(gctPOINTER));
+ payload += gcmSIZEOF(gctPOINTER);
+ }
+
+ gcmkARGUMENTS_END(p);
+ }
+
+ gcmkASSERT(payload - buffer <= gcdBINARY_TRACE_MESSAGE_SIZE);
+
+
+ /* Send buffer to ring buffer. */
+ gckOS_WriteToRingBuffer(buffer, (gctUINT32)(payload - buffer));
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
new file mode 100644
index 000000000000..a848eb3743ca
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
@@ -0,0 +1,3224 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_kernel_buffer.h"
+
+#ifdef __QNXNTO__
+#include "gc_hal_kernel_qnx.h"
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_EVENT
+
+#define gcdEVENT_ALLOCATION_COUNT (4096 / gcmSIZEOF(gcsHAL_INTERFACE))
+#define gcdEVENT_MIN_THRESHOLD 4
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+static gcmINLINE gceSTATUS
+gckEVENT_AllocateQueue(
+ IN gckEVENT Event,
+ OUT gcsEVENT_QUEUE_PTR * Queue
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+
+ /* Do we have free queues? */
+ if (Event->freeList == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Move one free queue from the free list. */
+ * Queue = Event->freeList;
+ Event->freeList = Event->freeList->next;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Queue=0x%x", gcmOPT_POINTER(Queue));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckEVENT_FreeQueue(
+ IN gckEVENT Event,
+ OUT gcsEVENT_QUEUE_PTR Queue
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
+
+ /* Move one free queue from the free list. */
+ Queue->next = Event->freeList;
+ Event->freeList = Queue;
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckEVENT_FreeRecord(
+ IN gckEVENT Event,
+ IN gcsEVENT_PTR Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->freeEventMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Push the record on the free list. */
+ Record->next = Event->freeEventList;
+ Event->freeEventList = Record;
+ Event->freeEventCount += 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+gckEVENT_IsEmpty(
+ IN gckEVENT Event,
+ OUT gctBOOL_PTR IsEmpty
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T i;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(IsEmpty != gcvNULL);
+
+ /* Assume the event queue is empty. */
+ *IsEmpty = gcvTRUE;
+
+ /* Walk the event queue. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ /* Check whether this event is in use. */
+ if (Event->queues[i].head != gcvNULL)
+ {
+ /* The event is in use, hence the queue is not empty. */
+ *IsEmpty = gcvFALSE;
+ break;
+ }
+ }
+
+ /* Try acquiring the mutex. */
+ status = gckOS_AcquireMutex(Event->os, Event->eventQueueMutex, 0);
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Timeout - queue is no longer empty. */
+ *IsEmpty = gcvFALSE;
+ }
+ else
+ {
+ /* Bail out on error. */
+ gcmkONERROR(status);
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*IsEmpty=%d", gcmOPT_VALUE(IsEmpty));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_TryToIdleGPU(
+ IN gckEVENT Event
+)
+{
+ gceSTATUS status;
+ gctBOOL empty = gcvFALSE, idle = gcvFALSE;
+ gctBOOL powerLocked = gcvFALSE;
+ gckHARDWARE hardware;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Grab gckHARDWARE object. */
+ hardware = Event->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Check whether the event queue is empty. */
+ gcmkONERROR(gckEVENT_IsEmpty(Event, &empty));
+
+ if (empty)
+ {
+ status = gckOS_AcquireMutex(hardware->os, hardware->powerMutex, 0);
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ powerLocked = gcvTRUE;
+
+ /* Query whether the hardware is idle. */
+ gcmkONERROR(gckHARDWARE_QueryIdle(Event->kernel->hardware, &idle));
+
+ gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
+ powerLocked = gcvFALSE;
+
+ if (idle)
+ {
+ /* Inform the system of idle GPU. */
+ gcmkONERROR(gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_IDLE));
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (powerLocked)
+ {
+ gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+__RemoveRecordFromProcessDB(
+ IN gckEVENT Event,
+ IN gcsEVENT_PTR Record
+ )
+{
+ gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ switch (Record->info.command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_NON_PAGED,
+ gcmUINT64_TO_PTR(Record->info.u.FreeNonPagedMemory.logical)));
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_CONTIGUOUS,
+ gcmUINT64_TO_PTR(Record->info.u.FreeContiguousMemory.logical)));
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_VIDEO_MEMORY_LOCKED,
+ gcmUINT64_TO_PTR(Record->info.u.UnlockVideoMemory.node)));
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_MAP_USER_MEMORY,
+ gcmINT2PTR(Record->info.u.UnmapUserMemory.info)));
+ break;
+
+ case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Event->kernel,
+ Record->processID,
+ gcvDB_COMMAND_BUFFER,
+ gcmUINT64_TO_PTR(Record->info.u.FreeVirtualCommandBuffer.logical)));
+ break;
+
+ default:
+ break;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_ReleaseVideoMemoryHandle(
+ IN gckKERNEL Kernel,
+ IN OUT gcsEVENT_PTR Record,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE nodeObject;
+ gctUINT32 handle;
+
+ switch(Interface->command)
+ {
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ handle = (gctUINT32)Interface->u.UnlockVideoMemory.node;
+
+ gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
+ Kernel, Record->processID, handle, &nodeObject));
+
+ Record->info.u.UnlockVideoMemory.node = gcmPTR_TO_UINT64(nodeObject);
+
+ gckVIDMEM_HANDLE_Dereference(Kernel, Record->processID, handle);
+ break;
+
+ default:
+ break;
+ }
+
+ return gcvSTATUS_OK;
+OnError:
+ return status;
+}
+
+/*******************************************************************************
+**
+** _QueryFlush
+**
+** Check the type of surfaces which will be released by current event and
+** determine the cache needed to flush.
+**
+*/
+static gceSTATUS
+_QueryFlush(
+ IN gckEVENT Event,
+ IN gcsEVENT_PTR Record,
+ OUT gceKERNEL_FLUSH *Flush
+ )
+{
+ gceKERNEL_FLUSH flush = 0;
+ gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ while (Record != gcvNULL)
+ {
+ switch (Record->info.command)
+ {
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ switch(Record->info.u.UnlockVideoMemory.type)
+ {
+ case gcvSURF_TILE_STATUS:
+ flush |= gcvFLUSH_TILE_STATUS;
+ break;
+ case gcvSURF_RENDER_TARGET:
+ flush |= gcvFLUSH_COLOR;
+ break;
+ case gcvSURF_DEPTH:
+ flush |= gcvFLUSH_DEPTH;
+ break;
+ case gcvSURF_TEXTURE:
+ flush |= gcvFLUSH_TEXTURE;
+ break;
+ case gcvSURF_ICACHE:
+ flush |= gcvFLUSH_ICACHE;
+ break;
+ case gcvSURF_TXDESC:
+ flush |= gcvFLUSH_TXDESC;
+ break;
+ case gcvSURF_FENCE:
+ flush |= gcvFLUSH_FENCE;
+ break;
+ case gcvSURF_VERTEX:
+ flush |= gcvFLUSH_VERTEX;
+ break;
+ case gcvSURF_TFBHEADER:
+ flush |= gcvFLUSH_TFBHEADER;
+ break;
+ case gcvSURF_TYPE_UNKNOWN:
+ *Flush = gcvFLUSH_ALL;
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ default:
+ break;
+ }
+ break;
+ case gcvHAL_UNMAP_USER_MEMORY:
+ *Flush = gcvFLUSH_ALL;
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+ default:
+ break;
+ }
+
+ Record = Record->next;
+ }
+
+ *Flush = flush;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+void
+_SubmitTimerFunction(
+ gctPOINTER Data
+ )
+{
+ gckEVENT event = (gckEVENT)Data;
+ gcmkVERIFY_OK(gckEVENT_Submit(event, gcvTRUE, gcvFALSE));
+}
+
+/******************************************************************************\
+******************************* gckEVENT API Code *******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckEVENT_Construct
+**
+** Construct a new gckEVENT object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gckEVENT * Event
+** Pointer to a variable that receives the gckEVENT object pointer.
+*/
+gceSTATUS
+gckEVENT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckEVENT * Event
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gckEVENT eventObj = gcvNULL;
+ int i;
+ gcsEVENT_PTR record;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Event != gcvNULL);
+
+ /* Extract the pointer to the gckOS object. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate the gckEVENT object. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckEVENT), &pointer));
+
+ eventObj = pointer;
+
+ /* Reset the object. */
+ gcmkVERIFY_OK(gckOS_ZeroMemory(eventObj, gcmSIZEOF(struct _gckEVENT)));
+
+ /* Initialize the gckEVENT object. */
+ eventObj->object.type = gcvOBJ_EVENT;
+ eventObj->kernel = Kernel;
+ eventObj->os = os;
+
+ /* Create the mutexes. */
+ gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventQueueMutex));
+ gcmkONERROR(gckOS_CreateMutex(os, &eventObj->freeEventMutex));
+ gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventListMutex));
+
+ /* Create a bunch of event reccords. */
+ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
+ {
+ /* Allocate an event record. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsEVENT), &pointer));
+
+ record = pointer;
+
+ /* Push it on the free list. */
+ record->next = eventObj->freeEventList;
+ eventObj->freeEventList = record;
+ eventObj->freeEventCount += 1;
+ }
+
+ /* Initialize the free list of event queues. */
+ for (i = 0; i < gcdREPO_LIST_COUNT; i += 1)
+ {
+ eventObj->repoList[i].next = eventObj->freeList;
+ eventObj->freeList = &eventObj->repoList[i];
+ }
+
+ eventObj->freeQueueCount = gcmCOUNTOF(eventObj->queues);
+
+ gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->pending));
+
+ gcmkVERIFY_OK(gckOS_CreateTimer(os,
+ _SubmitTimerFunction,
+ (gctPOINTER)eventObj,
+ &eventObj->submitTimer));
+
+#if gcdINTERRUPT_STATISTIC
+ gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->interruptCount));
+ gcmkONERROR(gckOS_AtomSet(os,eventObj->interruptCount, 0));
+#endif
+
+ eventObj->notifyState = -1;
+
+ /* Return pointer to the gckEVENT object. */
+ *Event = eventObj;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Event=0x%x", *Event);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (eventObj != gcvNULL)
+ {
+ if (eventObj->eventQueueMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventQueueMutex));
+ }
+
+ if (eventObj->freeEventMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->freeEventMutex));
+ }
+
+ if (eventObj->eventListMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventListMutex));
+ }
+
+ while (eventObj->freeEventList != gcvNULL)
+ {
+ record = eventObj->freeEventList;
+ eventObj->freeEventList = record->next;
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, record));
+ }
+
+ if (eventObj->pending != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->pending));
+ }
+
+#if gcdINTERRUPT_STATISTIC
+ if (eventObj->interruptCount)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->interruptCount));
+ }
+#endif
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, eventObj));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Destroy
+**
+** Destroy an gckEVENT object.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Destroy(
+ IN gckEVENT Event
+ )
+{
+ gcsEVENT_PTR record;
+ gcsEVENT_QUEUE_PTR queue;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ if (Event->submitTimer != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_StopTimer(Event->os, Event->submitTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Event->os, Event->submitTimer));
+ }
+
+ /* Delete the queue mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventQueueMutex));
+
+ /* Free all free events. */
+ while (Event->freeEventList != gcvNULL)
+ {
+ record = Event->freeEventList;
+ Event->freeEventList = record->next;
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
+ }
+
+ /* Delete the free mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->freeEventMutex));
+
+ /* Free all pending queues. */
+ while (Event->queueHead != gcvNULL)
+ {
+ /* Get the current queue. */
+ queue = Event->queueHead;
+
+ /* Free all pending events. */
+ while (queue->head != gcvNULL)
+ {
+ record = queue->head;
+ queue->head = record->next;
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_WARNING, gcvZONE_EVENT,
+ gcmSIZEOF(record) + gcmSIZEOF(queue->source),
+ "Event record 0x%x is still pending for %d.",
+ record, queue->source
+ );
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
+ }
+
+ /* Remove the top queue from the list. */
+ if (Event->queueHead == Event->queueTail)
+ {
+ Event->queueHead =
+ Event->queueTail = gcvNULL;
+ }
+ else
+ {
+ Event->queueHead = Event->queueHead->next;
+ }
+
+ /* Free the queue. */
+ gcmkVERIFY_OK(gckEVENT_FreeQueue(Event, queue));
+ }
+
+ /* Delete the list mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventListMutex));
+
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->pending));
+
+#if gcdINTERRUPT_STATISTIC
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->interruptCount));
+#endif
+
+ /* Mark the gckEVENT object as unknown. */
+ Event->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckEVENT object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, Event));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_GetEvent
+**
+** Reserve the next available hardware event.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctBOOL Wait
+** Set to gcvTRUE to force the function to wait if no events are
+** immediately available.
+**
+** gceKERNEL_WHERE Source
+** Source of the event.
+**
+** OUTPUT:
+**
+** gctUINT8 * EventID
+** Reserved event ID.
+*/
+#define gcdINVALID_EVENT_PTR ((gcsEVENT_PTR)gcvMAXUINTPTR_T)
+
+gceSTATUS
+gckEVENT_GetEvent(
+ IN gckEVENT Event,
+ IN gctBOOL Wait,
+ OUT gctUINT8 * EventID,
+ IN gceKERNEL_WHERE Source
+ )
+{
+ gctINT i, id;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctINT32 free;
+
+ gcmkHEADER_ARG("Event=0x%x Source=%d", Event, Source);
+
+ while (gcvTRUE)
+ {
+ /* Grab the queue mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->eventQueueMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Walk through all events. */
+ id = Event->lastID;
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ gctINT nextID = id + 1;
+
+ if (nextID == gcmCOUNTOF(Event->queues))
+ {
+ nextID = 0;
+ }
+
+ if (Event->queues[id].head == gcvNULL)
+ {
+ *EventID = (gctUINT8) id;
+
+ Event->lastID = (gctUINT8) nextID;
+
+ /* Save time stamp of event. */
+ Event->queues[id].head = gcdINVALID_EVENT_PTR;
+ Event->queues[id].stamp = ++(Event->stamp);
+ Event->queues[id].source = Source;
+
+ /* Decrease the number of free events. */
+ free = --Event->freeQueueCount;
+
+ /* Make compiler happy. */
+ free = free;
+
+#if gcdDYNAMIC_SPEED
+ if (free <= gcdDYNAMIC_EVENT_THRESHOLD)
+ {
+ gcmkONERROR(gckOS_BroadcastHurry(
+ Event->os,
+ Event->kernel->hardware,
+ gcdDYNAMIC_EVENT_THRESHOLD - free));
+ }
+#endif
+
+ /* Release the queue mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os,
+ Event->eventQueueMutex));
+
+ /* Success. */
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_EVENT,
+ gcmSIZEOF(id),
+ "Using id=%d",
+ id
+ );
+
+ gcmkFOOTER_ARG("*EventID=%u", *EventID);
+ return gcvSTATUS_OK;
+ }
+
+ id = nextID;
+ }
+
+#if gcdDYNAMIC_SPEED
+ /* No free events, speed up the GPU right now! */
+ gcmkONERROR(gckOS_BroadcastHurry(Event->os,
+ Event->kernel->hardware,
+ gcdDYNAMIC_EVENT_THRESHOLD));
+#endif
+
+ /* Release the queue mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ acquired = gcvFALSE;
+
+ /* Fail if wait is not requested. */
+ if (!Wait)
+ {
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Delay a while. */
+ gcmkONERROR(gckOS_Delay(Event->os, 1));
+ }
+
+OnError:
+ if (acquired)
+ {
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_AllocateRecord
+**
+** Allocate a record for the new event.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctBOOL AllocateAllowed
+** State for allocation if out of free events.
+**
+** OUTPUT:
+**
+** gcsEVENT_PTR * Record
+** Allocated event record.
+*/
+static gcmINLINE gceSTATUS
+gckEVENT_AllocateRecord(
+ IN gckEVENT Event,
+ IN gctBOOL AllocateAllowed,
+ OUT gcsEVENT_PTR * Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctINT i;
+ gcsEVENT_PTR record;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Event=0x%x AllocateAllowed=%d", Event, AllocateAllowed);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Test if we are below the allocation threshold. */
+ if ( (AllocateAllowed && (Event->freeEventCount < gcdEVENT_MIN_THRESHOLD)) ||
+ (Event->freeEventCount == 0) )
+ {
+ /* Allocate a bunch of records. */
+ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
+ {
+ /* Allocate an event record. */
+ gcmkONERROR(gckOS_Allocate(Event->os,
+ gcmSIZEOF(gcsEVENT),
+ &pointer));
+
+ record = pointer;
+
+ /* Push it on the free list. */
+ record->next = Event->freeEventList;
+ Event->freeEventList = record;
+ Event->freeEventCount += 1;
+ }
+ }
+
+ *Record = Event->freeEventList;
+ Event->freeEventList = Event->freeEventList->next;
+ Event->freeEventCount -= 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_AddList
+**
+** Add a new event to the list of events.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gcsHAL_INTERFACE_PTR Interface
+** Pointer to the interface for the event to be added.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** gctBOOL AllocateAllowed
+** State for allocation if out of free events.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_AddList(
+ IN gckEVENT Event,
+ IN gcsHAL_INTERFACE_PTR Interface,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctBOOL AllocateAllowed,
+ IN gctBOOL FromKernel
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsEVENT_PTR record = gcvNULL;
+ gcsEVENT_QUEUE_PTR queue;
+ gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
+ gckKERNEL kernel = Event->kernel;
+
+ gcmkHEADER_ARG("Event=0x%x Interface=0x%x",
+ Event, Interface);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, _GC_OBJ_ZONE,
+ "FromWhere=%d AllocateAllowed=%d",
+ FromWhere, AllocateAllowed);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ /* Verify the event command. */
+ gcmkASSERT
+ ( (Interface->command == gcvHAL_FREE_NON_PAGED_MEMORY)
+ || (Interface->command == gcvHAL_FREE_CONTIGUOUS_MEMORY)
+ || (Interface->command == gcvHAL_WRITE_DATA)
+ || (Interface->command == gcvHAL_UNLOCK_VIDEO_MEMORY)
+ || (Interface->command == gcvHAL_SIGNAL)
+ || (Interface->command == gcvHAL_UNMAP_USER_MEMORY)
+ || (Interface->command == gcvHAL_TIMESTAMP)
+ || (Interface->command == gcvHAL_COMMIT_DONE)
+ || (Interface->command == gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER)
+ || (Interface->command == gcvHAL_DESTROY_MMU)
+ );
+
+ /* Validate the source. */
+ if ((FromWhere != gcvKERNEL_COMMAND) && (FromWhere != gcvKERNEL_PIXEL))
+ {
+ /* Invalid argument. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Allocate a free record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, AllocateAllowed, &record));
+
+ /* Termninate the record. */
+ record->next = gcvNULL;
+
+ /* Record the committer. */
+ record->fromKernel = FromKernel;
+
+ /* Copy the event interface into the record. */
+ gckOS_MemCopy(&record->info, Interface, gcmSIZEOF(record->info));
+
+ /* Get process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&record->processID));
+
+ if (FromKernel == gcvFALSE)
+ {
+ gcmkONERROR(__RemoveRecordFromProcessDB(Event, record));
+
+ /* Handle is belonged to current process, it must be released now. */
+ status = _ReleaseVideoMemoryHandle(Event->kernel, record, Interface);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Ingore error because there are other events in the queue. */
+ status = gcvSTATUS_OK;
+ goto OnError;
+ }
+ }
+
+#ifdef __QNXNTO__
+ record->kernel = Event->kernel;
+#endif
+
+ /* Unmap user space logical address.
+ * Linux kernel does not support unmap the memory of other process any more since 3.5.
+ * Let's unmap memory of self process before submit the event to gpu.
+ * */
+ switch(Interface->command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ gcmkONERROR(gckOS_UnmapUserLogical(
+ Event->os,
+ gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical),
+ (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
+ gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
+ break;
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ gcmkONERROR(gckOS_UnmapUserLogical(
+ Event->os,
+ gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical),
+ (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
+ gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
+ break;
+
+ case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+ buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)gcmNAME_TO_PTR(Interface->u.FreeVirtualCommandBuffer.physical);
+ if (buffer != gcvNULL && buffer->virtualBuffer.userLogical)
+ {
+ gcmkONERROR(gckOS_DestroyUserVirtualMapping(
+ Event->os,
+ buffer->virtualBuffer.physical,
+ (gctSIZE_T) Interface->u.FreeVirtualCommandBuffer.bytes,
+ gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->eventListMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Do we need to allocate a new queue? */
+ if ((Event->queueTail == gcvNULL) || (Event->queueTail->source < FromWhere))
+ {
+ /* Allocate a new queue. */
+ gcmkONERROR(gckEVENT_AllocateQueue(Event, &queue));
+
+ /* Initialize the queue. */
+ queue->source = FromWhere;
+ queue->head = gcvNULL;
+ queue->next = gcvNULL;
+
+ /* Attach it to the list of allocated queues. */
+ if (Event->queueTail == gcvNULL)
+ {
+ Event->queueHead =
+ Event->queueTail = queue;
+ }
+ else
+ {
+ Event->queueTail->next = queue;
+ Event->queueTail = queue;
+ }
+ }
+ else
+ {
+ queue = Event->queueTail;
+ }
+
+ /* Attach the record to the queue. */
+ if (queue->head == gcvNULL)
+ {
+ queue->head = record;
+ queue->tail = record;
+ }
+ else
+ {
+ queue->tail->next = record;
+ queue->tail = record;
+ }
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+ }
+
+ if (record != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Unlock
+**
+** Schedule an event to unlock virtual memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union that specifies the virtual memory
+** to unlock.
+**
+** gceSURF_TYPE Type
+** Type of surface to unlock.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Unlock(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctPOINTER Node,
+ IN gceSURF_TYPE Type
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x FromWhere=%d Node=0x%x Type=%d",
+ Event, FromWhere, Node, Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ /* Mark the event as an unlock. */
+ iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
+ iface.u.UnlockVideoMemory.node = gcmPTR_TO_UINT64(Node);
+ iface.u.UnlockVideoMemory.type = Type;
+ iface.u.UnlockVideoMemory.asynchroneous = 0;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_FreeNonPagedMemory
+**
+** Schedule an event to free non-paged memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIZE_T Bytes
+** Number of bytes of non-paged memory to free.
+**
+** gctPHYS_ADDR Physical
+** Physical address of non-paged memory to free.
+**
+** gctPOINTER Logical
+** Logical address of non-paged memory to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+ gckKERNEL kernel = Event->kernel;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_NON_PAGED_MEMORY;
+ iface.u.FreeNonPagedMemory.bytes = Bytes;
+ iface.u.FreeNonPagedMemory.physical = gcmPTR_TO_NAME(Physical);
+ iface.u.FreeNonPagedMemory.logical = gcmPTR_TO_UINT64(Logical);
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckEVENT_DestroyVirtualCommandBuffer(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+ gckKERNEL kernel = Event->kernel;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER;
+ iface.u.FreeVirtualCommandBuffer.bytes = Bytes;
+ iface.u.FreeVirtualCommandBuffer.physical = gcmPTR_TO_NAME(Physical);
+ iface.u.FreeVirtualCommandBuffer.logical = gcmPTR_TO_UINT64(Logical);
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_FreeContigiuousMemory
+**
+** Schedule an event to free contiguous memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIZE_T Bytes
+** Number of bytes of contiguous memory to free.
+**
+** gctPHYS_ADDR Physical
+** Physical address of contiguous memory to free.
+**
+** gctPOINTER Logical
+** Logical address of contiguous memory to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+ gckKERNEL kernel = Event->kernel;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY;
+ iface.u.FreeContiguousMemory.bytes = Bytes;
+ iface.u.FreeContiguousMemory.physical = gcmPTR_TO_NAME(Physical);
+ iface.u.FreeContiguousMemory.logical = gcmPTR_TO_UINT64(Logical);
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Signal
+**
+** Schedule an event to trigger a signal.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIGNAL Signal
+** Pointer to the signal to trigger.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Signal(
+ IN gckEVENT Event,
+ IN gctSIGNAL Signal,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x Signal=0x%x FromWhere=%d",
+ Event, Signal, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ /* Mark the event as a signal. */
+ iface.command = gcvHAL_SIGNAL;
+ iface.u.Signal.signal = gcmPTR_TO_UINT64(Signal);
+ iface.u.Signal.auxSignal = 0;
+ iface.u.Signal.process = 0;
+
+#ifdef __QNXNTO__
+ iface.u.Signal.coid = 0;
+ iface.u.Signal.rcvid = 0;
+
+ gcmkONERROR(gckOS_SignalPending(Event->os, Signal));
+#endif
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_CommitDone
+**
+** Schedule an event to wake up work thread when commit is done by GPU.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_CommitDone(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gckCONTEXT Context
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x FromWhere=%d", Event, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ iface.command = gcvHAL_COMMIT_DONE;
+
+ iface.u.CommitDone.context = gcmPTR_TO_UINT64(Context);
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckEVENT_DestroyMmu(
+ IN gckEVENT Event,
+ IN gckMMU Mmu,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x FromWhere=%d", Event, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ iface.command = gcvHAL_DESTROY_MMU;
+ iface.u.DestroyMmu.mmu = gcmPTR_TO_UINT64(Mmu);
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckEVENT_SubmitAsync(
+ IN gckEVENT Event,
+ IN gctBOOL Wait,
+ IN gctBOOL FromPower
+ )
+{
+ gceSTATUS status;
+ gctUINT8 id = 0xFF;
+ gcsEVENT_QUEUE_PTR queue;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL commitEntered = gcvFALSE;
+ gctUINT32 start, end;
+ gctUINT8_PTR startLogical;
+ gctUINT32 eventBytes;
+
+ gckHARDWARE hardware;
+ gckASYNC_COMMAND asyncCommand;
+
+ gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
+
+ /* Get gckCOMMAND object. */
+ hardware = Event->kernel->hardware;
+ asyncCommand = Event->asyncCommand;
+
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Are there event queues? */
+ if (Event->queueHead != gcvNULL)
+ {
+ /* Acquire the command queue. */
+ gcmkONERROR(gckASYNC_COMMAND_EnterCommit(asyncCommand));
+ commitEntered = gcvTRUE;
+
+ /* Process all queues. */
+ while (Event->queueHead != gcvNULL)
+ {
+ /* Acquire the list mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->eventListMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Get the current queue. */
+ queue = Event->queueHead;
+
+ /* Allocate an event ID. */
+ gcmkONERROR(gckEVENT_GetEvent(Event, Wait, &id, queue->source));
+
+ /* Copy event list to event ID queue. */
+ Event->queues[id].head = queue->head;
+
+ /* Remove the top queue from the list. */
+ if (Event->queueHead == Event->queueTail)
+ {
+ Event->queueHead = gcvNULL;
+ Event->queueTail = gcvNULL;
+ }
+ else
+ {
+ Event->queueHead = Event->queueHead->next;
+ }
+
+ /* Free the queue. */
+ gcmkONERROR(gckEVENT_FreeQueue(Event, queue));
+
+ /* Release the list mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+ acquired = gcvFALSE;
+
+ gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware, gcvNULL, id, gcvKERNEL_BLT, &eventBytes));
+
+ /* Get command sequence. */
+ start = hardware->functions[gcvHARDWARE_FUNCTION_BLT_EVENT].address + id * eventBytes;
+ end = start + 24;
+
+ startLogical = hardware->functions[gcvHARDWARE_FUNCTION_BLT_EVENT].logical + id * eventBytes;
+
+ gcmkDUMPCOMMAND(
+ Event->os,
+ startLogical,
+ end - start,
+ gceDUMP_BUFFER_KERNEL,
+ gcvFALSE
+ );
+
+ gcmkONERROR(gckASYNC_COMMAND_Execute(asyncCommand, start, end));
+ }
+
+ /* Release the command queue. */
+ gcmkONERROR(gckASYNC_COMMAND_ExitCommit(asyncCommand));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Need to unroll the mutex acquire. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+ }
+
+ if (commitEntered)
+ {
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(gckASYNC_COMMAND_ExitCommit(asyncCommand));
+ }
+
+ if (id != 0xFF)
+ {
+ /* Need to unroll the event allocation. */
+ Event->queues[id].head = gcvNULL;
+ }
+
+ if (status == gcvSTATUS_GPU_NOT_RESPONDING)
+ {
+ /* Broadcast GPU stuck. */
+ status = gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_STUCK);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Submit
+**
+** Submit the current event queue to the GPU.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctBOOL Wait
+** Submit requires one vacant event; if Wait is set to not zero,
+** and there are no vacant events at this time, the function will
+** wait until an event becomes vacant so that submission of the
+** queue is successful.
+**
+** gctBOOL FromPower
+** Determines whether the call originates from inside the power
+** management or not.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Submit(
+ IN gckEVENT Event,
+ IN gctBOOL Wait,
+ IN gctBOOL FromPower
+ )
+{
+ gceSTATUS status;
+ gctUINT8 id = 0xFF;
+ gcsEVENT_QUEUE_PTR queue;
+ gctBOOL acquired = gcvFALSE;
+ gckCOMMAND command = gcvNULL;
+ gctBOOL commitEntered = gcvFALSE;
+#if !gcdNULL_DRIVER
+ gctUINT32 bytes;
+ gctPOINTER buffer;
+ gctUINT32 executeBytes;
+ gctUINT32 flushBytes;
+#endif
+
+#if gcdINTERRUPT_STATISTIC
+ gctINT32 oldValue;
+#endif
+
+#if gcdSECURITY
+ gctPOINTER reservedBuffer;
+#endif
+
+ gckHARDWARE hardware;
+
+ gceKERNEL_FLUSH flush = gcvFALSE;
+ gctUINT64 commitStamp;
+
+ gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
+
+ /* Get gckCOMMAND object. */
+ command = Event->kernel->command;
+ hardware = Event->kernel->hardware;
+
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ if (Event->asyncCommand)
+ {
+ /* Call async submit path. */
+ gcmkONERROR(gckEVENT_SubmitAsync(Event, Wait, FromPower));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ gckOS_GetTicks(&Event->lastCommitStamp);
+
+ /* Are there event queues? */
+ if (Event->queueHead != gcvNULL)
+ {
+ /* Acquire the command queue. */
+ gcmkONERROR(gckCOMMAND_EnterCommit(command, FromPower));
+ commitEntered = gcvTRUE;
+
+ /* Get current commit stamp. */
+ commitStamp = Event->kernel->command->commitStamp;
+
+ if (commitStamp)
+ {
+ commitStamp -= 1;
+ }
+
+ /* Process all queues. */
+ while (Event->queueHead != gcvNULL)
+ {
+ /* Acquire the list mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->eventListMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Get the current queue. */
+ queue = Event->queueHead;
+
+ /* Allocate an event ID. */
+ gcmkONERROR(gckEVENT_GetEvent(Event, Wait, &id, queue->source));
+
+ /* Copy event list to event ID queue. */
+ Event->queues[id].head = queue->head;
+
+ /* Update current commit stamp. */
+ Event->queues[id].commitStamp = commitStamp;
+
+ /* Remove the top queue from the list. */
+ if (Event->queueHead == Event->queueTail)
+ {
+ Event->queueHead = gcvNULL;
+ Event->queueTail = gcvNULL;
+ }
+ else
+ {
+ Event->queueHead = Event->queueHead->next;
+ }
+
+ /* Free the queue. */
+ gcmkONERROR(gckEVENT_FreeQueue(Event, queue));
+
+ /* Release the list mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+ acquired = gcvFALSE;
+
+ /* Determine cache needed to flush. */
+ gcmkVERIFY_OK(_QueryFlush(Event, Event->queues[id].head, &flush));
+
+#if gcdNULL_DRIVER
+#if gcdINTERRUPT_STATISTIC
+ gcmkVERIFY_OK(gckOS_AtomIncrement(
+ Event->os,
+ Event->interruptCount,
+ &oldValue
+ ));
+#endif
+
+ /* Notify immediately on infinite hardware. */
+ gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
+
+ gcmkONERROR(gckEVENT_Notify(Event, 0));
+#else
+ /* Get the size of the hardware event. */
+ gcmkONERROR(gckHARDWARE_Event(
+ hardware,
+ gcvNULL,
+ id,
+ Event->queues[id].source,
+ &bytes
+ ));
+
+ /* Get the size of flush command. */
+ gcmkONERROR(gckHARDWARE_Flush(
+ hardware,
+ flush,
+ gcvNULL,
+ &flushBytes
+ ));
+
+ bytes += flushBytes;
+
+ /* Total bytes need to execute. */
+ executeBytes = bytes;
+
+ /* Reserve space in the command queue. */
+ gcmkONERROR(gckCOMMAND_Reserve(command, bytes, &buffer, &bytes));
+#if gcdSECURITY
+ reservedBuffer = buffer;
+#endif
+
+ /* Set the flush in the command queue. */
+ gcmkONERROR(gckHARDWARE_Flush(
+ hardware,
+ flush,
+ buffer,
+ &flushBytes
+ ));
+
+ /* Advance to next command. */
+ buffer = (gctUINT8_PTR)buffer + flushBytes;
+
+ /* Set the hardware event in the command queue. */
+ gcmkONERROR(gckHARDWARE_Event(
+ hardware,
+ buffer,
+ id,
+ Event->queues[id].source,
+ &bytes
+ ));
+
+ /* Advance to next command. */
+ buffer = (gctUINT8_PTR)buffer + bytes;
+
+#if gcdINTERRUPT_STATISTIC
+ gcmkVERIFY_OK(gckOS_AtomIncrement(
+ Event->os,
+ Event->interruptCount,
+ &oldValue
+ ));
+#endif
+
+#if gcdSECURITY
+ gckKERNEL_SecurityExecute(
+ Event->kernel,
+ reservedBuffer,
+ executeBytes
+ );
+#else
+ /* Execute the hardware event. */
+ gcmkONERROR(gckCOMMAND_Execute(command, executeBytes));
+#endif
+#endif
+ }
+
+ /* Release the command queue. */
+ gcmkONERROR(gckCOMMAND_ExitCommit(command, FromPower));
+
+#if !gcdNULL_DRIVER
+ gcmkVERIFY_OK(_TryToIdleGPU(Event));
+#endif
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Need to unroll the mutex acquire. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+ }
+
+ if (commitEntered)
+ {
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, FromPower));
+ }
+
+ if (id != 0xFF)
+ {
+ /* Need to unroll the event allocation. */
+ Event->queues[id].head = gcvNULL;
+ }
+
+ if (status == gcvSTATUS_GPU_NOT_RESPONDING)
+ {
+ /* Broadcast GPU stuck. */
+ status = gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_STUCK);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Commit
+**
+** Commit an event queue from the user.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gcsQUEUE_PTR Queue
+** User event queue.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Commit(
+ IN gckEVENT Event,
+ IN gcsQUEUE_PTR Queue
+ )
+{
+ gceSTATUS status;
+ gcsQUEUE_PTR record = gcvNULL, next;
+ gctUINT32 processID;
+ gctBOOL needCopy = gcvFALSE;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Event=0x%x Queue=0x%x", Event, Queue);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Get the current process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ /* Query if we need to copy the client data. */
+ gcmkONERROR(gckOS_QueryNeedCopy(Event->os, processID, &needCopy));
+
+ /* Loop while there are records in the queue. */
+ while (Queue != gcvNULL)
+ {
+ gcsQUEUE queue;
+
+ if (needCopy)
+ {
+ /* Point to stack record. */
+ record = &queue;
+
+ /* Copy the data from the client. */
+ gcmkONERROR(gckOS_CopyFromUserData(Event->os,
+ record,
+ Queue,
+ gcmSIZEOF(gcsQUEUE)));
+ }
+ else
+ {
+
+ /* Map record into kernel memory. */
+ gcmkONERROR(gckOS_MapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ &pointer));
+
+ record = pointer;
+ }
+
+ /* Append event record to event queue. */
+ gcmkONERROR(
+ gckEVENT_AddList(Event, &record->iface, gcvKERNEL_PIXEL, gcvTRUE, gcvFALSE));
+
+ /* Next record in the queue. */
+ next = gcmUINT64_TO_PTR(record->next);
+
+ if (!needCopy)
+ {
+ /* Unmap record from kernel memory. */
+ gcmkONERROR(
+ gckOS_UnmapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ record = gcvNULL;
+ }
+
+ Queue = next;
+ }
+
+ /* Submit the event list. */
+ gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
+
+ /* Success */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (pointer)
+ {
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER*)pointer));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Compose
+**
+** Schedule a composition event and start a composition.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gcsHAL_COMPOSE_PTR Info
+** Pointer to the composition structure.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Compose(
+ IN gckEVENT Event,
+ IN gcsHAL_COMPOSE_PTR Info
+ )
+{
+ gceSTATUS status;
+ gcsEVENT_PTR headRecord;
+ gcsEVENT_PTR tailRecord;
+ gcsEVENT_PTR tempRecord = gcvNULL;
+ gctUINT8 id = 0xFF;
+ gctUINT32 processID;
+
+ gcmkHEADER_ARG("Event=0x%x Info=0x%x", Event, Info);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+ /* Allocate an event ID. */
+ gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL));
+
+ /* Get process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ /* Allocate a record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+ headRecord = tailRecord = tempRecord;
+
+ /* Initialize the record. */
+ tempRecord->info.command = gcvHAL_SIGNAL;
+ tempRecord->info.u.Signal.process = Info->process;
+#ifdef __QNXNTO__
+ tempRecord->info.u.Signal.coid = Info->coid;
+ tempRecord->info.u.Signal.rcvid = Info->rcvid;
+#endif
+ tempRecord->info.u.Signal.signal = Info->signal;
+ tempRecord->info.u.Signal.auxSignal = 0;
+ tempRecord->next = gcvNULL;
+ tempRecord->processID = processID;
+
+ /* Allocate another record for user signal #1. */
+ if (gcmUINT64_TO_PTR(Info->userSignal1) != gcvNULL)
+ {
+ /* Allocate a record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+ tailRecord->next = tempRecord;
+ tailRecord = tempRecord;
+
+ /* Initialize the record. */
+ tempRecord->info.command = gcvHAL_SIGNAL;
+ tempRecord->info.u.Signal.process = Info->userProcess;
+#ifdef __QNXNTO__
+ tempRecord->info.u.Signal.coid = Info->coid;
+ tempRecord->info.u.Signal.rcvid = Info->rcvid;
+#endif
+ tempRecord->info.u.Signal.signal = Info->userSignal1;
+ tempRecord->info.u.Signal.auxSignal = 0;
+ tempRecord->next = gcvNULL;
+ tempRecord->processID = processID;
+ }
+
+ /* Allocate another record for user signal #2. */
+ if (gcmUINT64_TO_PTR(Info->userSignal2) != gcvNULL)
+ {
+ /* Allocate a record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
+ tailRecord->next = tempRecord;
+
+ /* Initialize the record. */
+ tempRecord->info.command = gcvHAL_SIGNAL;
+ tempRecord->info.u.Signal.process = Info->userProcess;
+#ifdef __QNXNTO__
+ tempRecord->info.u.Signal.coid = Info->coid;
+ tempRecord->info.u.Signal.rcvid = Info->rcvid;
+#endif
+ tempRecord->info.u.Signal.signal = Info->userSignal2;
+ tempRecord->info.u.Signal.auxSignal = 0;
+ tempRecord->next = gcvNULL;
+ tempRecord->processID = processID;
+ }
+
+ /* Set the event list. */
+ Event->queues[id].head = headRecord;
+
+ /* Start composition. */
+ gcmkONERROR(gckHARDWARE_Compose(
+ Event->kernel->hardware, processID,
+ gcmUINT64_TO_PTR(Info->physical), gcmUINT64_TO_PTR(Info->logical), Info->offset, Info->size, id
+ ));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Interrupt
+**
+** Called by the interrupt service routine to store the triggered interrupt
+** mask to be later processed by gckEVENT_Notify.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctUINT32 Data
+** Mask for the 32 interrupts.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Interrupt(
+ IN gckEVENT Event,
+ IN gctUINT32 Data
+ )
+{
+ gcmkHEADER_ARG("Event=0x%x Data=0x%x", Event, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ if (Data & 0x20000000)
+ {
+ gctUINT32 resume;
+ gctUINT32 bytes;
+ gctUINT32 idle;
+ gctUINT32 pageSize = Event->kernel->command->pageSize;
+ Data &= ~0x20000000;
+
+ {
+ /* Make sure FE is idle. */
+ do
+ {
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+ Event->os,
+ Event->kernel->core,
+ 0x4,
+ &idle));
+ }
+ while (idle != 0x7FFFFFFF);
+
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+ Event->os,
+ Event->kernel->core,
+ 0x664,
+ &resume));
+
+ gcmkVERIFY_OK(gckOS_ReadRegisterEx(
+ Event->os,
+ Event->kernel->core,
+ 0x664,
+ &resume));
+
+ gcmkVERIFY_OK(gckHARDWARE_WaitLink(
+ Event->kernel->hardware,
+ gcvNULL,
+ ~0U,
+ resume & (pageSize - 1),
+ &bytes,
+ gcvNULL,
+ gcvNULL
+ ));
+
+ /* Start Command Parser. */
+ gcmkVERIFY_OK(gckHARDWARE_Execute(
+ Event->kernel->hardware,
+ resume,
+ bytes
+ ));
+ }
+ }
+
+ /* Combine current interrupt status with pending flags. */
+ gckOS_AtomSetMask(Event->pending, Data);
+
+#if gcdINTERRUPT_STATISTIC
+ {
+ gctINT j = 0;
+ gctINT32 oldValue;
+
+ for (j = 0; j < gcmCOUNTOF(Event->queues); j++)
+ {
+ if ((Data & (1 << j)))
+ {
+ gcmkVERIFY_OK(gckOS_AtomDecrement(Event->os,
+ Event->interruptCount,
+ &oldValue));
+ }
+ }
+ }
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Notify
+**
+** Process all triggered interrupts.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Notify(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctINT i;
+ gcsEVENT_QUEUE * queue;
+ gctUINT mask = 0;
+ gctBOOL acquired = gcvFALSE;
+ gctSIGNAL signal;
+ gctUINT pending = 0;
+ gckKERNEL kernel = Event->kernel;
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gctINT eventNumber = 0;
+#endif
+#if gcdSECURE_USER
+ gcskSECURE_CACHE_PTR cache;
+ gcuVIDMEM_NODE_PTR node;
+#endif
+ gckVIDMEM_NODE nodeObject;
+
+ gcmkHEADER_ARG("Event=0x%x IDs=0x%x", Event, IDs);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ gcmDEBUG_ONLY(
+ if (IDs != 0)
+ {
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Queue(%d): stamp=%llu source=%d",
+ i,
+ Event->queues[i].stamp,
+ Event->queues[i].source);
+ }
+ }
+ }
+ );
+
+ /* Begin of event handling. */
+ Event->notifyState = 0;
+
+ for (;;)
+ {
+ gcsEVENT_PTR record;
+
+ /* Grab the mutex queue. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->eventQueueMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ gckOS_AtomGet(Event->os, Event->pending, (gctINT32_PTR)&pending);
+
+ if (pending == 0)
+ {
+ /* Release the mutex queue. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ acquired = gcvFALSE;
+
+ /* No more pending interrupts - done. */
+ break;
+ }
+
+ if (pending & 0x80000000)
+ {
+ gcmkPRINT("AXI BUS ERROR");
+ gckHARDWARE_DumpGPUState(Event->kernel->hardware);
+ pending &= 0x7FFFFFFF;
+ }
+
+ if ((pending & 0x40000000) && Event->kernel->hardware->mmuVersion)
+ {
+#if gcdUSE_MMU_EXCEPTION
+#if gcdALLOC_ON_FAULT
+ status = gckHARDWARE_HandleFault(Event->kernel->hardware);
+
+ if (gcmIS_ERROR(status))
+#endif
+ {
+ /* Dump error is fault can't be handle. */
+ gckHARDWARE_DumpMMUException(Event->kernel->hardware);
+
+ gckHARDWARE_DumpGPUState(Event->kernel->hardware);
+ }
+#endif
+
+ pending &= 0xBFFFFFFF;
+ }
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_EVENT,
+ gcmSIZEOF(pending),
+ "Pending interrupts 0x%x",
+ pending
+ );
+
+ queue = gcvNULL;
+
+ gcmDEBUG_ONLY(
+ if (IDs == 0)
+ {
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Queue(%d): stamp=%llu source=%d",
+ i,
+ Event->queues[i].stamp,
+ Event->queues[i].source);
+ }
+ }
+ }
+ );
+
+ /* Find the oldest pending interrupt. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if ((Event->queues[i].head != gcvNULL)
+ && (pending & (1 << i))
+ )
+ {
+ if ((queue == gcvNULL)
+ || (Event->queues[i].stamp < queue->stamp)
+ )
+ {
+ queue = &Event->queues[i];
+ mask = 1 << i;
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ eventNumber = i;
+#endif
+ }
+ }
+ }
+
+ if (queue == gcvNULL)
+ {
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_ERROR, gcvZONE_EVENT,
+ gcmSIZEOF(pending),
+ "Interrupts 0x%x are not pending.",
+ pending
+ );
+
+ gckOS_AtomClearMask(Event->pending, pending);
+
+ /* Release the mutex queue. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ acquired = gcvFALSE;
+ break;
+ }
+
+ /* Check whether there is a missed interrupt. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if ((Event->queues[i].head != gcvNULL)
+ && (Event->queues[i].stamp < queue->stamp)
+ && (Event->queues[i].source <= queue->source)
+ )
+ {
+ gcmkTRACE_N(
+ gcvLEVEL_ERROR,
+ gcmSIZEOF(i) + gcmSIZEOF(Event->queues[i].stamp),
+ "Event %d lost (stamp %llu)",
+ i, Event->queues[i].stamp
+ );
+
+ /* Use this event instead. */
+ queue = &Event->queues[i];
+ mask = 0;
+ }
+ }
+
+ if (mask != 0)
+ {
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_EVENT,
+ gcmSIZEOF(eventNumber),
+ "Processing interrupt %d",
+ eventNumber
+ );
+#endif
+ }
+
+ gckOS_AtomClearMask(Event->pending, mask);
+
+ if (!gckHARDWARE_IsFeatureAvailable(Event->kernel->hardware, gcvFEATURE_FENCE))
+ {
+ /* Write out commit stamp.*/
+ *(gctUINT64 *)(Event->kernel->command->fence->logical) = queue->commitStamp;
+ }
+
+ /* Signal clients waiting for fence. */
+ gcmkVERIFY_OK(gckFENCE_Signal(
+ Event->os,
+ Event->kernel->command->fence
+ ));
+
+ /* Grab the event head. */
+ record = queue->head;
+
+ /* Now quickly clear its event list. */
+ queue->head = gcvNULL;
+
+ /* Increase the number of free events. */
+ Event->freeQueueCount++;
+
+ /* Release the mutex queue. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ acquired = gcvFALSE;
+
+ /* Walk all events for this interrupt. */
+ while (record != gcvNULL)
+ {
+ gcsEVENT_PTR recordNext;
+#ifndef __QNXNTO__
+ gctPOINTER logical;
+#endif
+#if gcdSECURE_USER
+ gctSIZE_T bytes;
+#endif
+
+ /* Grab next record. */
+ recordNext = record->next;
+
+#ifdef __QNXNTO__
+ /*
+ * Assign record->processID as the pid for this galcore thread.
+ * Used in the OS calls which do not take a pid.
+ */
+ drv_thread_specific_key_assign(record->processID, 0);
+#endif
+
+#if gcdSECURE_USER
+ /* Get the cache that belongs to this process. */
+ gcmkONERROR(gckKERNEL_GetProcessDBCache(Event->kernel,
+ record->processID,
+ &cache));
+#endif
+
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_INFO, gcvZONE_EVENT,
+ gcmSIZEOF(record->info.command),
+ "Processing event type: %d",
+ record->info.command
+ );
+
+ switch (record->info.command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_FREE_NON_PAGED_MEMORY: 0x%x",
+ gcmNAME_TO_PTR(record->info.u.FreeNonPagedMemory.physical));
+
+ /* Free non-paged memory. */
+ status = gckOS_FreeNonPagedMemory(
+ Event->os,
+ (gctSIZE_T) record->info.u.FreeNonPagedMemory.bytes,
+ gcmNAME_TO_PTR(record->info.u.FreeNonPagedMemory.physical),
+ gcmUINT64_TO_PTR(record->info.u.FreeNonPagedMemory.logical));
+
+ if (gcmIS_SUCCESS(status))
+ {
+#if gcdSECURE_USER
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Event->kernel,
+ cache,
+ gcmUINT64_TO_PTR(record->record.u.FreeNonPagedMemory.logical),
+ (gctSIZE_T) record->record.u.FreeNonPagedMemory.bytes));
+#endif
+ }
+ gcmRELEASE_NAME(record->info.u.FreeNonPagedMemory.physical);
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_FREE_CONTIGUOUS_MEMORY: 0x%x",
+ gcmNAME_TO_PTR(record->info.u.FreeContiguousMemory.physical));
+
+ /* Unmap the user memory. */
+ status = gckOS_FreeContiguous(
+ Event->os,
+ gcmNAME_TO_PTR(record->info.u.FreeContiguousMemory.physical),
+ gcmUINT64_TO_PTR(record->info.u.FreeContiguousMemory.logical),
+ (gctSIZE_T) record->info.u.FreeContiguousMemory.bytes);
+
+ if (gcmIS_SUCCESS(status))
+ {
+#if gcdSECURE_USER
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Event->kernel,
+ cache,
+ gcmUINT64_TO_PTR(event->event.u.FreeContiguousMemory.logical),
+ (gctSIZE_T) event->event.u.FreeContiguousMemory.bytes));
+#endif
+ }
+ gcmRELEASE_NAME(record->info.u.FreeContiguousMemory.physical);
+ break;
+
+ case gcvHAL_WRITE_DATA:
+#ifndef __QNXNTO__
+ /* Convert physical into logical address. */
+ gcmkERR_BREAK(
+ gckOS_MapPhysical(Event->os,
+ record->info.u.WriteData.address,
+ gcmSIZEOF(gctUINT32),
+ &logical));
+
+ /* Write data. */
+ gcmkERR_BREAK(
+ gckOS_WriteMemory(Event->os,
+ logical,
+ record->info.u.WriteData.data));
+
+ /* Unmap the physical memory. */
+ gcmkERR_BREAK(
+ gckOS_UnmapPhysical(Event->os,
+ logical,
+ gcmSIZEOF(gctUINT32)));
+#else
+ /* Write data. */
+ gcmkERR_BREAK(
+ gckOS_WriteMemory(Event->os,
+ gcmUINT64_TO_PTR(record->info.u.WriteData.address),
+ record->info.u.WriteData.data));
+#endif
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_UNLOCK_VIDEO_MEMORY: 0x%x",
+ record->info.u.UnlockVideoMemory.node);
+
+ nodeObject = gcmUINT64_TO_PTR(record->info.u.UnlockVideoMemory.node);
+
+#if gcdSECURE_USER
+ node = nodeObject->node;
+
+ /* Save node information before it disappears. */
+ node = event->event.u.UnlockVideoMemory.node;
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ logical = gcvNULL;
+ bytes = 0;
+ }
+ else
+ {
+ logical = node->Virtual.logical;
+ bytes = node->Virtual.bytes;
+ }
+#endif
+
+ /* Unlock. */
+ status = gckVIDMEM_Unlock(
+ Event->kernel,
+ nodeObject,
+ record->info.u.UnlockVideoMemory.type,
+ gcvNULL);
+
+#if gcdSECURE_USER
+ if (gcmIS_SUCCESS(status) && (logical != gcvNULL))
+ {
+ gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
+ Event->kernel,
+ cache,
+ logical,
+ bytes));
+ }
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Unlock(
+ Event->kernel,
+ nodeObject,
+ record->processID
+ ));
+#endif
+
+ status = gckVIDMEM_NODE_Dereference(Event->kernel, nodeObject);
+ break;
+
+ case gcvHAL_SIGNAL:
+ signal = gcmUINT64_TO_PTR(record->info.u.Signal.signal);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_SIGNAL: 0x%x",
+ signal);
+
+#ifdef __QNXNTO__
+ if ((record->info.u.Signal.coid == 0)
+ && (record->info.u.Signal.rcvid == 0)
+ )
+ {
+ /* Kernel signal. */
+ gcmkERR_BREAK(
+ gckOS_SignalPulse(Event->os,
+ signal));
+ }
+ else
+ {
+ /* User signal. */
+ gcmkERR_BREAK(
+ gckOS_UserSignal(Event->os,
+ signal,
+ record->info.u.Signal.rcvid,
+ record->info.u.Signal.coid));
+ }
+#else
+ /* Set signal. */
+ if (gcmUINT64_TO_PTR(record->info.u.Signal.process) == gcvNULL)
+ {
+ /* Kernel signal. */
+ gcmkERR_BREAK(
+ gckOS_Signal(Event->os,
+ signal,
+ gcvTRUE));
+ }
+ else
+ {
+ /* User signal. */
+ gcmkERR_BREAK(
+ gckOS_UserSignal(Event->os,
+ signal,
+ gcmUINT64_TO_PTR(record->info.u.Signal.process)));
+ }
+
+ gcmkASSERT(record->info.u.Signal.auxSignal == 0);
+#endif
+ break;
+
+ case gcvHAL_TIMESTAMP:
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "gcvHAL_TIMESTAMP: %d %d",
+ record->info.u.TimeStamp.timer,
+ record->info.u.TimeStamp.request);
+
+ /* Process the timestamp. */
+ switch (record->info.u.TimeStamp.request)
+ {
+ case 0:
+ status = gckOS_GetTime(&Event->kernel->timers[
+ record->info.u.TimeStamp.timer].
+ stopTime);
+ break;
+
+ case 1:
+ status = gckOS_GetTime(&Event->kernel->timers[
+ record->info.u.TimeStamp.timer].
+ startTime);
+ break;
+
+ default:
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_ERROR, gcvZONE_EVENT,
+ gcmSIZEOF(record->info.u.TimeStamp.request),
+ "Invalid timestamp request: %d",
+ record->info.u.TimeStamp.request
+ );
+
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+ break;
+
+ case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+ gcmkVERIFY_OK(
+ gckKERNEL_DestroyVirtualCommandBuffer(Event->kernel,
+ (gctSIZE_T) record->info.u.FreeVirtualCommandBuffer.bytes,
+ gcmNAME_TO_PTR(record->info.u.FreeVirtualCommandBuffer.physical),
+ gcmUINT64_TO_PTR(record->info.u.FreeVirtualCommandBuffer.logical)
+ ));
+ gcmRELEASE_NAME(record->info.u.FreeVirtualCommandBuffer.physical);
+ break;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ case gcvHAL_DESTROY_MMU:
+ status = gckMMU_Destroy(gcmUINT64_TO_PTR(record->info.u.DestroyMmu.mmu));
+ break;
+#endif
+
+ case gcvHAL_COMMIT_DONE:
+ break;
+
+ default:
+ /* Invalid argument. */
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_ERROR, gcvZONE_EVENT,
+ gcmSIZEOF(record->info.command),
+ "Unknown event type: %d",
+ record->info.command
+ );
+
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+
+ /* Make sure there are no errors generated. */
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE_N(
+ gcvLEVEL_WARNING, gcvZONE_EVENT,
+ gcmSIZEOF(status),
+ "Event produced status: %d(%s)",
+ status, gckOS_DebugStatus2Name(status));
+ }
+
+ /* Free the event. */
+ gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+
+ /* Advance to next record. */
+ record = recordNext;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Handled interrupt 0x%x", mask);
+ }
+
+ if (IDs == 0)
+ {
+ gcmkONERROR(_TryToIdleGPU(Event));
+ }
+
+ /* End of event handling. */
+ Event->notifyState = -1;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ }
+
+ /* End of event handling. */
+ Event->notifyState = -1;
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckEVENT_FreeProcess
+**
+** Free all events owned by a particular process ID.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctUINT32 ProcessID
+** Process ID of the process to be freed up.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_FreeProcess(
+ IN gckEVENT Event,
+ IN gctUINT32 ProcessID
+ )
+{
+ gctSIZE_T i;
+ gctBOOL acquired = gcvFALSE;
+ gcsEVENT_PTR record, next;
+ gceSTATUS status;
+ gcsEVENT_PTR deleteHead, deleteTail;
+
+ gcmkHEADER_ARG("Event=0x%x ProcessID=%d", Event, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Walk through all queues. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ /* Grab the event queue mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->eventQueueMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Grab the mutex head. */
+ record = Event->queues[i].head;
+ Event->queues[i].head = gcvNULL;
+ Event->queues[i].tail = gcvNULL;
+ deleteHead = gcvNULL;
+ deleteTail = gcvNULL;
+
+ while (record != gcvNULL)
+ {
+ next = record->next;
+ if (record->processID == ProcessID)
+ {
+ if (deleteHead == gcvNULL)
+ {
+ deleteHead = record;
+ }
+ else
+ {
+ deleteTail->next = record;
+ }
+
+ deleteTail = record;
+ }
+ else
+ {
+ if (Event->queues[i].head == gcvNULL)
+ {
+ Event->queues[i].head = record;
+ }
+ else
+ {
+ Event->queues[i].tail->next = record;
+ }
+
+ Event->queues[i].tail = record;
+ }
+
+ record->next = gcvNULL;
+ record = next;
+ }
+
+ /* Release the mutex queue. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ acquired = gcvFALSE;
+
+ /* Loop through the entire list of events. */
+ for (record = deleteHead; record != gcvNULL; record = next)
+ {
+ /* Get the next event record. */
+ next = record->next;
+
+ /* Free the event record. */
+ gcmkONERROR(gckEVENT_FreeRecord(Event, record));
+ }
+ }
+ }
+
+ gcmkONERROR(_TryToIdleGPU(Event));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Release the event queue mutex. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** gckEVENT_Stop
+**
+** Stop the hardware using the End event mechanism.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctUINT32 ProcessID
+** Process ID Logical belongs.
+**
+** gctPHYS_ADDR Handle
+** Physical address handle. If gcvNULL it is video memory.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIGNAL Signal
+** Pointer to the signal to trigger.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Stop(
+ IN gckEVENT Event,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gctSIGNAL Signal,
+ IN OUT gctUINT32 * waitSize
+ )
+{
+ gceSTATUS status;
+ /* gctSIZE_T waitSize;*/
+ gcsEVENT_PTR record = gcvNULL;
+ gctUINT8 id = 0xFF;
+
+ gcmkHEADER_ARG("Event=0x%x ProcessID=%u Handle=0x%x Logical=0x%x "
+ "Address=0x%x Signal=0x%x",
+ Event, ProcessID, Handle, Logical, Address, Signal);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Submit the current event queue. */
+ gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
+ gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL));
+
+ /* Allocate a record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &record));
+
+ /* Initialize the record. */
+ record->next = gcvNULL;
+ record->processID = ProcessID;
+ record->info.command = gcvHAL_SIGNAL;
+ record->info.u.Signal.signal = gcmPTR_TO_UINT64(Signal);
+#ifdef __QNXNTO__
+ record->info.u.Signal.coid = 0;
+ record->info.u.Signal.rcvid = 0;
+#endif
+ record->info.u.Signal.auxSignal = 0;
+ record->info.u.Signal.process = 0;
+
+ /* Append the record. */
+ Event->queues[id].head = record;
+
+ /* Replace last WAIT with END. */
+ gcmkONERROR(gckHARDWARE_End(
+ Event->kernel->hardware, Logical, Address, waitSize
+ ));
+
+#if USE_KERNEL_VIRTUAL_BUFFERS
+ if (Event->kernel->virtualCommandBuffer)
+ {
+ gcmkONERROR(gckKERNEL_GetGPUAddress(
+ Event->kernel,
+ Logical,
+ gcvFALSE,
+ Event->kernel->command->virtualMemory,
+ &Event->kernel->hardware->lastEnd
+ ));
+ }
+#endif
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Flush the cache for the END. */
+ gcmkONERROR(gckOS_CacheClean(
+ Event->os,
+ ProcessID,
+ gcvNULL,
+ (gctUINT32)Handle,
+ Logical,
+ *waitSize
+ ));
+#endif
+
+ /* Wait for the signal. */
+ gcmkONERROR(gckOS_WaitSignal(Event->os, Signal, gcvFALSE, gcvINFINITE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static void
+_PrintRecord(
+ gcsEVENT_PTR record
+ )
+{
+ switch (record->info.command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ gcmkPRINT(" gcvHAL_FREE_NON_PAGED_MEMORY");
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ gcmkPRINT(" gcvHAL_FREE_CONTIGUOUS_MEMORY");
+ break;
+
+ case gcvHAL_WRITE_DATA:
+ gcmkPRINT(" gcvHAL_WRITE_DATA");
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ gcmkPRINT(" gcvHAL_UNLOCK_VIDEO_MEMORY");
+ break;
+
+ case gcvHAL_SIGNAL:
+ gcmkPRINT(" gcvHAL_SIGNAL process=%d signal=0x%x",
+ record->info.u.Signal.process,
+ record->info.u.Signal.signal);
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ gcmkPRINT(" gcvHAL_UNMAP_USER_MEMORY");
+ break;
+
+ case gcvHAL_TIMESTAMP:
+ gcmkPRINT(" gcvHAL_TIMESTAMP");
+ break;
+
+ case gcvHAL_COMMIT_DONE:
+ gcmkPRINT(" gcvHAL_COMMIT_DONE");
+ break;
+
+ case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
+ gcmkPRINT(" gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER logical=0x%08x",
+ record->info.u.FreeVirtualCommandBuffer.logical);
+ break;
+
+ case gcvHAL_DESTROY_MMU:
+ gcmkPRINT(" gcvHAL_DESTORY_MMU mmu=0x%08x",
+ gcmUINT64_TO_PTR(record->info.u.DestroyMmu.mmu));
+
+ break;
+ default:
+ gcmkPRINT(" Illegal Event %d", record->info.command);
+ break;
+ }
+}
+
+/*******************************************************************************
+** gckEVENT_Dump
+**
+** Dump record in event queue when stuck happens.
+** No protection for the event queue.
+**/
+gceSTATUS
+gckEVENT_Dump(
+ IN gckEVENT Event
+ )
+{
+ gcsEVENT_QUEUE_PTR queueHead = Event->queueHead;
+ gcsEVENT_QUEUE_PTR queue;
+ gcsEVENT_PTR record = gcvNULL;
+ gctINT i;
+#if gcdINTERRUPT_STATISTIC
+ gctINT32 pendingInterrupt;
+ gctUINT32 intrAcknowledge;
+#endif
+ gctINT32 pending;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("*** EVENT STATE DUMP ***\n");
+ gcmkPRINT("**************************\n");
+
+ gcmkPRINT(" Unsumbitted Event:");
+ while(queueHead)
+ {
+ queue = queueHead;
+ record = queueHead->head;
+
+ gcmkPRINT(" [%x]:", queue);
+ while(record)
+ {
+ _PrintRecord(record);
+ record = record->next;
+ }
+
+ if (queueHead == Event->queueTail)
+ {
+ queueHead = gcvNULL;
+ }
+ else
+ {
+ queueHead = queueHead->next;
+ }
+ }
+
+ gcmkPRINT(" Untriggered Event:");
+ for (i = 0; i < gcmCOUNTOF(Event->queues); i++)
+ {
+ queue = &Event->queues[i];
+ record = queue->head;
+
+ gcmkPRINT(" [%d]:", i);
+ while(record)
+ {
+ _PrintRecord(record);
+ record = record->next;
+ }
+ }
+
+#if gcdINTERRUPT_STATISTIC
+ gckOS_AtomGet(Event->os, Event->interruptCount, &pendingInterrupt);
+ gcmkPRINT(" Number of Pending Interrupt: %d", pendingInterrupt);
+
+ if (Event->kernel->recovery == 0)
+ {
+ gckOS_ReadRegisterEx(
+ Event->os,
+ Event->kernel->core,
+ 0x10,
+ &intrAcknowledge
+ );
+
+ gcmkPRINT(" INTR_ACKNOWLEDGE=0x%x", intrAcknowledge);
+ }
+#endif
+
+ gcmkPRINT(" Notify State=%d", Event->notifyState);
+
+ gckOS_AtomGet(Event->os, Event->pending, &pending);
+
+ gcmkPRINT(" Pending=0x%x", pending);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c
new file mode 100644
index 000000000000..1b61b4a3eeda
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_heap.c
@@ -0,0 +1,892 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+/**
+** @file
+** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
+** based memory allocation. An arena-based memory heap allocates data quickly
+** from specified arenas and reduces memory fragmentation.
+**
+*/
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_HEAP
+
+/*******************************************************************************
+***** Structures ***************************************************************
+*******************************************************************************/
+#define gcdIN_USE ((gcskNODE_PTR)gcvMAXUINTPTR_T)
+
+typedef struct _gcskNODE * gcskNODE_PTR;
+typedef struct _gcskNODE
+{
+ /* Number of byets in node. */
+ gctSIZE_T bytes;
+
+ /* Pointer to next free node, or gcvNULL to mark the node as freed, or
+ ** gcdIN_USE to mark the node as used. */
+ gcskNODE_PTR next;
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Time stamp of allocation. */
+ gctUINT64 timeStamp;
+#endif
+}
+gcskNODE;
+
+typedef struct _gcskHEAP * gcskHEAP_PTR;
+typedef struct _gcskHEAP
+{
+ /* Linked list. */
+ gcskHEAP_PTR next;
+ gcskHEAP_PTR prev;
+
+ /* Heap size. */
+ gctSIZE_T size;
+
+ /* Free list. */
+ gcskNODE_PTR freeList;
+}
+gcskHEAP;
+
+struct _gckHEAP
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to a gckOS object. */
+ gckOS os;
+
+ /* Locking mutex. */
+ gctPOINTER mutex;
+
+ /* Allocation parameters. */
+ gctSIZE_T allocationSize;
+
+ /* Heap list. */
+ gcskHEAP_PTR heap;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gctUINT64 timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Profile information. */
+ gctUINT32 allocCount;
+ gctUINT64 allocBytes;
+ gctUINT64 allocBytesMax;
+ gctUINT64 allocBytesTotal;
+ gctUINT32 heapCount;
+ gctUINT32 heapCountMax;
+ gctUINT64 heapMemory;
+ gctUINT64 heapMemoryMax;
+#endif
+};
+
+/*******************************************************************************
+***** Static Support Functions *************************************************
+*******************************************************************************/
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+static gctSIZE_T
+_DumpHeap(
+ IN gcskHEAP_PTR Heap
+ )
+{
+ gctPOINTER p;
+ gctSIZE_T leaked = 0;
+
+ /* Start at first node. */
+ for (p = Heap + 1;;)
+ {
+ /* Convert the pointer. */
+ gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+ /* Check if this is a used node. */
+ if (node->next == gcdIN_USE)
+ {
+ /* Print the leaking node. */
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
+ "Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
+ "(%08X %c%c%c%c)",
+ node, node->bytes, node->timeStamp,
+ ((gctUINT32_PTR) (node + 1))[0],
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
+
+ /* Add leaking byte count. */
+ leaked += node->bytes;
+ }
+
+ /* Test for end of heap. */
+ if (node->bytes == 0)
+ {
+ break;
+ }
+
+ else
+ {
+ /* Move to next node. */
+ p = (gctUINT8_PTR) node + node->bytes;
+ }
+ }
+
+ /* Return the number of leaked bytes. */
+ return leaked;
+}
+#endif
+
+static gceSTATUS
+_CompactKernelHeap(
+ IN gckHEAP Heap
+ )
+{
+ gcskHEAP_PTR heap, next;
+ gctPOINTER p;
+ gcskHEAP_PTR freeList = gcvNULL;
+
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ /* Walk all the heaps. */
+ for (heap = Heap->heap; heap != gcvNULL; heap = next)
+ {
+ gcskNODE_PTR lastFree = gcvNULL;
+
+ /* Zero out the free list. */
+ heap->freeList = gcvNULL;
+
+ /* Start at the first node. */
+ for (p = (gctUINT8_PTR) (heap + 1);;)
+ {
+ /* Convert the pointer. */
+ gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+ gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
+
+ /* Test if this node not used. */
+ if (node->next != gcdIN_USE)
+ {
+ /* Test if this is the end of the heap. */
+ if (node->bytes == 0)
+ {
+ break;
+ }
+
+ /* Test of this is the first free node. */
+ else if (lastFree == gcvNULL)
+ {
+ /* Initialzie the free list. */
+ heap->freeList = node;
+ lastFree = node;
+ }
+
+ else
+ {
+ /* Test if this free node is contiguous with the previous
+ ** free node. */
+ if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
+ {
+ /* Just increase the size of the previous free node. */
+ lastFree->bytes += node->bytes;
+ }
+ else
+ {
+ /* Add to linked list. */
+ lastFree->next = node;
+ lastFree = node;
+ }
+ }
+ }
+
+ /* Move to next node. */
+ p = (gctUINT8_PTR) node + node->bytes;
+ }
+
+ /* Mark the end of the chain. */
+ if (lastFree != gcvNULL)
+ {
+ lastFree->next = gcvNULL;
+ }
+
+ /* Get next heap. */
+ next = heap->next;
+
+ /* Check if the entire heap is free. */
+ if ((heap->freeList != gcvNULL)
+ && (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
+ )
+ {
+ /* Remove the heap from the linked list. */
+ if (heap->prev == gcvNULL)
+ {
+ Heap->heap = next;
+ }
+ else
+ {
+ heap->prev->next = next;
+ }
+
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap->prev;
+ }
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Update profiling. */
+ Heap->heapCount -= 1;
+ Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
+#endif
+
+ /* Add this heap to the list of heaps that need to be freed. */
+ heap->next = freeList;
+ freeList = heap;
+ }
+ }
+
+ if (freeList != gcvNULL)
+ {
+ /* Release the mutex, remove any chance for a dead lock. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Free all heaps in the free list. */
+ for (heap = freeList; heap != gcvNULL; heap = next)
+ {
+ /* Get pointer to the next heap. */
+ next = heap->next;
+
+ /* Free the heap. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+ "Freeing heap 0x%x (%lu bytes)",
+ heap, heap->size + gcmSIZEOF(gcskHEAP));
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
+ }
+
+ /* Acquire the mutex again. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+***** gckHEAP API Code *********************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckHEAP_Construct
+**
+** Construct a new gckHEAP object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctSIZE_T AllocationSize
+** Minimum size per arena.
+**
+** OUTPUT:
+**
+** gckHEAP * Heap
+** Pointer to a variable that will hold the pointer to the gckHEAP
+** object.
+*/
+gceSTATUS
+gckHEAP_Construct(
+ IN gckOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gckHEAP * Heap
+ )
+{
+ gceSTATUS status;
+ gckHEAP heap = gcvNULL;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
+
+ /* Allocate the gckHEAP object. */
+ gcmkONERROR(gckOS_AllocateMemory(Os,
+ gcmSIZEOF(struct _gckHEAP),
+ &pointer));
+
+ heap = pointer;
+
+ /* Initialize the gckHEAP object. */
+ heap->object.type = gcvOBJ_HEAP;
+ heap->os = Os;
+ heap->allocationSize = AllocationSize;
+ heap->heap = gcvNULL;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ heap->timeStamp = 0;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Zero the counters. */
+ heap->allocCount = 0;
+ heap->allocBytes = 0;
+ heap->allocBytesMax = 0;
+ heap->allocBytesTotal = 0;
+ heap->heapCount = 0;
+ heap->heapCountMax = 0;
+ heap->heapMemory = 0;
+ heap->heapMemoryMax = 0;
+#endif
+
+ /* Create the mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
+
+ /* Return the pointer to the gckHEAP object. */
+ *Heap = heap;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Heap=0x%x", *Heap);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (heap != gcvNULL)
+ {
+ /* Free the heap structure. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Destroy
+**
+** Destroy a gckHEAP object.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHEAP_Destroy(
+ IN gckHEAP Heap
+ )
+{
+ gcskHEAP_PTR heap;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gctSIZE_T leaked = 0;
+#endif
+
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
+ {
+ /* Unlink heap from linked list. */
+ Heap->heap = heap->next;
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Check for leaked memory. */
+ leaked += _DumpHeap(heap);
+#endif
+
+ /* Free the heap. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
+ }
+
+ /* Free the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
+
+ /* Free the heap structure. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
+
+ /* Success. */
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gcmkFOOTER_ARG("leaked=%lu", leaked);
+#else
+ gcmkFOOTER_NO();
+#endif
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Allocate
+**
+** Allocate data from the heap.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object.
+**
+** IN gctSIZE_T Bytes
+** Number of byte to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the address of the allocated
+** memory.
+*/
+gceSTATUS
+gckHEAP_Allocate(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctBOOL acquired = gcvFALSE;
+ gcskHEAP_PTR heap;
+ gceSTATUS status;
+ gctSIZE_T bytes;
+ gcskNODE_PTR node, used, prevFree = gcvNULL;
+ gctPOINTER memory = gcvNULL;
+
+ gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Determine number of bytes required for a node. */
+ bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ /* Check if this allocation is bigger than the default allocation size. */
+ if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
+ {
+ /* Adjust allocation size. */
+ Heap->allocationSize = bytes * 2;
+ }
+
+ else if (Heap->heap != gcvNULL)
+ {
+ gctINT i;
+
+ /* 2 retries, since we might need to compact. */
+ for (i = 0; i < 2; ++i)
+ {
+ /* Walk all the heaps. */
+ for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
+ {
+ /* Check if this heap has enough bytes to hold the request. */
+ if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
+ {
+ prevFree = gcvNULL;
+
+ /* Walk the chain of free nodes. */
+ for (node = heap->freeList;
+ node != gcvNULL;
+ node = node->next
+ )
+ {
+ gcmkASSERT(node->next != gcdIN_USE);
+
+ /* Check if this free node has enough bytes. */
+ if (node->bytes >= bytes)
+ {
+ /* Use the node. */
+ goto UseNode;
+ }
+
+ /* Save current free node for linked list management. */
+ prevFree = node;
+ }
+ }
+ }
+
+ if (i == 0)
+ {
+ /* Compact the heap. */
+ gcmkVERIFY_OK(_CompactKernelHeap(Heap));
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "===== KERNEL HEAP =====");
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of allocations : %12u",
+ Heap->allocCount);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of bytes allocated : %12llu",
+ Heap->allocBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum allocation size : %12llu",
+ Heap->allocBytesMax);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Total number of bytes allocated : %12llu",
+ Heap->allocBytesTotal);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of heaps : %12u",
+ Heap->heapCount);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Heap memory in bytes : %12llu",
+ Heap->heapMemory);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum number of heaps : %12u",
+ Heap->heapCountMax);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum heap memory in bytes : %12llu",
+ Heap->heapMemoryMax);
+#endif
+ }
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ acquired = gcvFALSE;
+
+ /* Allocate a new heap. */
+ gcmkONERROR(
+ gckOS_AllocateMemory(Heap->os,
+ Heap->allocationSize,
+ &memory));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+ "Allocated heap 0x%x (%lu bytes)",
+ memory, Heap->allocationSize);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ /* Use the allocated memory as the heap. */
+ heap = (gcskHEAP_PTR) memory;
+
+ /* Insert this heap to the head of the chain. */
+ heap->next = Heap->heap;
+ heap->prev = gcvNULL;
+ heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
+
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap;
+ }
+ Heap->heap = heap;
+
+ /* Mark the end of the heap. */
+ node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
+ + Heap->allocationSize
+ - gcmSIZEOF(gcskNODE)
+ );
+ node->bytes = 0;
+ node->next = gcvNULL;
+
+ /* Create a free list. */
+ node = (gcskNODE_PTR) (heap + 1);
+ heap->freeList = node;
+
+ /* Initialize the free list. */
+ node->bytes = heap->size - gcmSIZEOF(gcskNODE);
+ node->next = gcvNULL;
+
+ /* No previous free. */
+ prevFree = gcvNULL;
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Update profiling. */
+ Heap->heapCount += 1;
+ Heap->heapMemory += Heap->allocationSize;
+
+ if (Heap->heapCount > Heap->heapCountMax)
+ {
+ Heap->heapCountMax = Heap->heapCount;
+ }
+ if (Heap->heapMemory > Heap->heapMemoryMax)
+ {
+ Heap->heapMemoryMax = Heap->heapMemory;
+ }
+#endif
+
+UseNode:
+ /* Verify some stuff. */
+ gcmkASSERT(heap != gcvNULL);
+ gcmkASSERT(node != gcvNULL);
+ gcmkASSERT(node->bytes >= bytes);
+
+ if (heap->prev != gcvNULL)
+ {
+ /* Unlink the heap from the linked list. */
+ heap->prev->next = heap->next;
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap->prev;
+ }
+
+ /* Move the heap to the front of the list. */
+ heap->next = Heap->heap;
+ heap->prev = gcvNULL;
+ Heap->heap = heap;
+ heap->next->prev = heap;
+ }
+
+ /* Check if there is enough free space left after usage for another free
+ ** node. */
+ if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
+ {
+ /* Allocated used space from the back of the free list. */
+ used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
+
+ /* Adjust the number of free bytes. */
+ node->bytes -= bytes;
+ gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
+ }
+ else
+ {
+ /* Remove this free list from the chain. */
+ if (prevFree == gcvNULL)
+ {
+ heap->freeList = node->next;
+ }
+ else
+ {
+ prevFree->next = node->next;
+ }
+
+ /* Consume the entire free node. */
+ used = (gcskNODE_PTR) node;
+ bytes = node->bytes;
+ }
+
+ /* Mark node as used. */
+ used->bytes = bytes;
+ used->next = gcdIN_USE;
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+ used->timeStamp = ++Heap->timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Update profile counters. */
+ Heap->allocCount += 1;
+ Heap->allocBytes += bytes;
+ Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
+ Heap->allocBytesTotal += bytes;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Return pointer to memory. */
+ *Memory = used + 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+ }
+
+ if (memory != gcvNULL)
+ {
+ /* Free the heap memory. */
+ gckOS_FreeMemory(Heap->os, memory);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Free
+**
+** Free allocated memory from the heap.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object.
+**
+** IN gctPOINTER Memory
+** Pointer to memory to free.
+**
+** OUTPUT:
+**
+** NOTHING.
+*/
+gceSTATUS
+gckHEAP_Free(
+ IN gckHEAP Heap,
+ IN gctPOINTER Memory
+ )
+{
+ gcskNODE_PTR node;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ /* Pointer to structure. */
+ node = (gcskNODE_PTR) Memory - 1;
+
+ /* Mark the node as freed. */
+ node->next = gcvNULL;
+
+#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
+ /* Update profile counters. */
+ Heap->allocBytes -= node->bytes;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHEAP_ProfileStart(
+ IN gckHEAP Heap
+ )
+{
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+
+ /* Zero the counters. */
+ Heap->allocCount = 0;
+ Heap->allocBytes = 0;
+ Heap->allocBytesMax = 0;
+ Heap->allocBytesTotal = 0;
+ Heap->heapCount = 0;
+ Heap->heapCountMax = 0;
+ Heap->heapMemory = 0;
+ Heap->heapMemoryMax = 0;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+ IN gckHEAP Heap,
+ IN gctCONST_STRING Title
+ )
+{
+ gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Title != gcvNULL);
+
+ gcmkPRINT("");
+ gcmkPRINT("=====[ HEAP - %s ]=====", Title);
+ gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
+ gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
+ gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
+ gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
+ gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
+ gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
+ gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
+ gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
+ gcmkPRINT("==============================================");
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif /* VIVANTE_PROFILER */
+
+/*******************************************************************************
+***** Test Code ****************************************************************
+*******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c
new file mode 100644
index 000000000000..b4d53a3c3648
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_interrupt_vg.c
@@ -0,0 +1,911 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+/******************************************************************************\
+*********************** Support Functions and Definitions **********************
+\******************************************************************************/
+
+/* Interruot statistics will be accumulated if not zero. */
+#define gcmENABLE_INTERRUPT_STATISTICS 0
+
+#define _GC_OBJ_ZONE gcvZONE_INTERRUPT
+
+/* Object structure. */
+struct _gckVGINTERRUPT
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* gckVGKERNEL pointer. */
+ gckVGKERNEL kernel;
+
+ /* gckOS pointer. */
+ gckOS os;
+
+ /* Interrupt handlers. */
+ gctINTERRUPT_HANDLER handlers[32];
+
+ /* Main interrupt handler thread. */
+ gctTHREAD handler;
+ gctBOOL terminate;
+
+ /* Interrupt FIFO. */
+ gctSEMAPHORE fifoValid;
+ gctUINT32 fifo[256];
+ gctUINT fifoItems;
+ gctUINT8 head;
+ gctUINT8 tail;
+
+ /* Interrupt statistics. */
+#if gcmENABLE_INTERRUPT_STATISTICS
+ gctUINT maxFifoItems;
+ gctUINT fifoOverflow;
+ gctUINT maxSimultaneous;
+ gctUINT multipleCount;
+#endif
+};
+
+
+/*******************************************************************************
+**
+** _ProcessInterrupt
+**
+** The interrupt processor.
+**
+** INPUT:
+**
+** ThreadParameter
+** Pointer to the gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+static void
+_ProcessInterrupt(
+ gckVGINTERRUPT Interrupt,
+ gctUINT_PTR TriggeredCount
+ )
+#else
+static void
+_ProcessInterrupt(
+ gckVGINTERRUPT Interrupt
+ )
+#endif
+{
+ gceSTATUS status;
+ gctUINT32 triggered;
+ gctUINT i;
+
+ /* Advance to the next entry. */
+ Interrupt->tail += 1;
+ Interrupt->fifoItems -= 1;
+
+ /* Get the interrupt value. */
+ triggered = Interrupt->fifo[Interrupt->tail];
+ gcmkASSERT(triggered != 0);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s: triggered=0x%08X\n",
+ __FUNCTION__,
+ triggered
+ );
+
+ /* Walk through all possible interrupts. */
+ for (i = 0; i < gcmSIZEOF(Interrupt->handlers); i += 1)
+ {
+ /* Test if interrupt happened. */
+ if ((triggered & 1) == 1)
+ {
+#if gcmENABLE_INTERRUPT_STATISTICS
+ if (TriggeredCount != gcvNULL)
+ {
+ (* TriggeredCount) += 1;
+ }
+#endif
+
+ /* Make sure we have valid handler. */
+ if (Interrupt->handlers[i] == gcvNULL)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s: Interrupt %d isn't registered.\n",
+ __FUNCTION__, i
+ );
+ }
+ else
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s: interrupt=%d\n",
+ __FUNCTION__,
+ i
+ );
+
+ /* Call the handler. */
+ status = Interrupt->handlers[i] (Interrupt->kernel);
+
+ if (gcmkIS_ERROR(status))
+ {
+ /* Failed to signal the semaphore. */
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s: Error %d incrementing the semaphore #%d.\n",
+ __FUNCTION__, status, i
+ );
+ }
+ }
+ }
+
+ /* Next interrupt. */
+ triggered >>= 1;
+
+ /* No more interrupts to handle? */
+ if (triggered == 0)
+ {
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** _MainInterruptHandler
+**
+** The main interrupt thread serves the interrupt FIFO and calls registered
+** handlers for the interrupts that occured. The handlers are called in the
+** sequence interrupts occured with the exception when multiple interrupts
+** occured at the same time. In that case the handler calls are "sorted" by
+** the interrupt number therefore giving the interrupts with lower numbers
+** higher priority.
+**
+** INPUT:
+**
+** ThreadParameter
+** Pointer to the gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+static gctTHREADFUNCRESULT gctTHREADFUNCTYPE
+_MainInterruptHandler(
+ gctTHREADFUNCPARAMETER ThreadParameter
+ )
+{
+ gceSTATUS status;
+ gckVGINTERRUPT interrupt;
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+ gctUINT count;
+#endif
+
+ /* Cast the object. */
+ interrupt = (gckVGINTERRUPT) ThreadParameter;
+
+ /* Enter the loop. */
+ while (gcvTRUE)
+ {
+ /* Wait for an interrupt. */
+ status = gckOS_DecrementSemaphore(interrupt->os, interrupt->fifoValid);
+
+ /* Error? */
+ if (gcmkIS_ERROR(status))
+ {
+ break;
+ }
+
+ /* System termination request? */
+ if (status == gcvSTATUS_TERMINATE)
+ {
+ break;
+ }
+
+ /* Driver is shutting down? */
+ if (interrupt->terminate)
+ {
+ break;
+ }
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+ /* Reset triggered count. */
+ count = 0;
+
+ /* Process the interrupt. */
+ _ProcessInterrupt(interrupt, &count);
+
+ /* Update conters. */
+ if (count > interrupt->maxSimultaneous)
+ {
+ interrupt->maxSimultaneous = count;
+ }
+
+ if (count > 1)
+ {
+ interrupt->multipleCount += 1;
+ }
+#else
+ /* Process the interrupt. */
+ _ProcessInterrupt(interrupt);
+#endif
+ }
+
+ return 0;
+}
+
+
+/*******************************************************************************
+**
+** _StartInterruptHandler / _StopInterruptHandler
+**
+** Main interrupt handler routine control.
+**
+** INPUT:
+**
+** ThreadParameter
+** Pointer to the gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+static gceSTATUS
+_StartInterruptHandler(
+ gckVGINTERRUPT Interrupt
+ )
+{
+ gceSTATUS status, last;
+
+ do
+ {
+ /* Objects must not be already created. */
+ gcmkASSERT(Interrupt->fifoValid == gcvNULL);
+ gcmkASSERT(Interrupt->handler == gcvNULL);
+
+ /* Reset the termination request. */
+ Interrupt->terminate = gcvFALSE;
+
+#if !gcdENABLE_INFINITE_SPEED_HW
+ /* Construct the fifo semaphore. */
+ gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
+ Interrupt->os, &Interrupt->fifoValid
+ ));
+
+ /* Start the interrupt handler thread. */
+ gcmkERR_BREAK(gckOS_StartThread(
+ Interrupt->os,
+ _MainInterruptHandler,
+ Interrupt,
+ &Interrupt->handler
+ ));
+#endif
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (Interrupt->fifoValid != gcvNULL)
+ {
+ gcmkCHECK_STATUS(gckOS_DestroySemaphore(
+ Interrupt->os, Interrupt->fifoValid
+ ));
+
+ Interrupt->fifoValid = gcvNULL;
+ }
+
+ /* Return the status. */
+ return status;
+}
+
+static gceSTATUS
+_StopInterruptHandler(
+ gckVGINTERRUPT Interrupt
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ /* Does the thread exist? */
+ if (Interrupt->handler == gcvNULL)
+ {
+ /* The semaphore must be NULL as well. */
+ gcmkASSERT(Interrupt->fifoValid == gcvNULL);
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* The semaphore must exist as well. */
+ gcmkASSERT(Interrupt->fifoValid != gcvNULL);
+
+ /* Set the termination request. */
+ Interrupt->terminate = gcvTRUE;
+
+ /* Unlock the thread. */
+ gcmkERR_BREAK(gckOS_IncrementSemaphore(
+ Interrupt->os, Interrupt->fifoValid
+ ));
+
+ /* Wait until the thread quits. */
+ gcmkERR_BREAK(gckOS_StopThread(
+ Interrupt->os,
+ Interrupt->handler
+ ));
+
+ /* Destroy the semaphore. */
+ gcmkERR_BREAK(gckOS_DestroySemaphore(
+ Interrupt->os, Interrupt->fifoValid
+ ));
+
+ /* Reset handles. */
+ Interrupt->handler = gcvNULL;
+ Interrupt->fifoValid = gcvNULL;
+ }
+ while (gcvFALSE);
+
+ /* Return the status. */
+ return status;
+}
+
+
+/******************************************************************************\
+***************************** Interrupt Object API *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Construct
+**
+** Construct an interrupt object.
+**
+** INPUT:
+**
+** Kernel
+** Pointer to the gckVGKERNEL object.
+**
+** OUTPUT:
+**
+** Interrupt
+** Pointer to the new gckVGINTERRUPT object.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Construct(
+ IN gckVGKERNEL Kernel,
+ OUT gckVGINTERRUPT * Interrupt
+ )
+{
+ gceSTATUS status;
+ gckVGINTERRUPT interrupt = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x Interrupt=0x%x", Kernel, Interrupt);
+
+ /* Verify argeuments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interrupt != gcvNULL);
+
+ do
+ {
+ /* Allocate the gckVGINTERRUPT structure. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Kernel->os,
+ gcmSIZEOF(struct _gckVGINTERRUPT),
+ (gctPOINTER *) &interrupt
+ ));
+
+ /* Reset the object data. */
+ gcmkVERIFY_OK(gckOS_ZeroMemory(
+ interrupt, gcmSIZEOF(struct _gckVGINTERRUPT)
+ ));
+
+ /* Initialize the object. */
+ interrupt->object.type = gcvOBJ_INTERRUPT;
+
+ /* Initialize the object pointers. */
+ interrupt->kernel = Kernel;
+ interrupt->os = Kernel->os;
+
+ /* Initialize the current FIFO position. */
+ interrupt->head = (gctUINT8)~0;
+ interrupt->tail = (gctUINT8)~0;
+
+ /* Start the thread. */
+ gcmkERR_BREAK(_StartInterruptHandler(interrupt));
+
+ /* Return interrupt object. */
+ *Interrupt = interrupt;
+
+ gcmkFOOTER_ARG("*Interrup=0x%x", *Interrupt);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (interrupt != gcvNULL)
+ {
+ /* Free the gckVGINTERRUPT structure. */
+ gcmkVERIFY_OK(gckOS_Free(interrupt->os, interrupt));
+ }
+
+ gcmkFOOTER();
+
+ /* Return the status. */
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Destroy
+**
+** Destroy an interrupt object.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to the gckVGINTERRUPT object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Destroy(
+ IN gckVGINTERRUPT Interrupt
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+ do
+ {
+ /* Stop the interrupt thread. */
+ gcmkERR_BREAK(_StopInterruptHandler(Interrupt));
+
+ /* Mark the object as unknown. */
+ Interrupt->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVGINTERRUPT structure. */
+ gcmkERR_BREAK(gckOS_Free(Interrupt->os, Interrupt));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+
+ /* Return the status. */
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_DumpState
+**
+** Print the current state of the interrupt manager.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to a gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+#if gcvDEBUG
+gceSTATUS
+gckVGINTERRUPT_DumpState(
+ IN gckVGINTERRUPT Interrupt
+ )
+{
+ gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+ /* Print the header. */
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ "%s: INTERRUPT OBJECT STATUS\n",
+ __FUNCTION__
+ );
+
+ /* Print statistics. */
+#if gcmENABLE_INTERRUPT_STATISTICS
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " Maximum number of FIFO items accumulated at a single time: %d\n",
+ Interrupt->maxFifoItems
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " Interrupt FIFO overflow happened times: %d\n",
+ Interrupt->fifoOverflow
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " Maximum number of interrupts simultaneously generated: %d\n",
+ Interrupt->maxSimultaneous
+ );
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " Number of times when there were multiple interrupts generated: %d\n",
+ Interrupt->multipleCount
+ );
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " The current number of entries in the FIFO: %d\n",
+ Interrupt->fifoItems
+ );
+
+ /* Print the FIFO contents. */
+ if (Interrupt->fifoItems != 0)
+ {
+ gctUINT8 index;
+ gctUINT8 last;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " FIFO current contents:\n"
+ );
+
+ /* Get the current pointers. */
+ index = Interrupt->tail;
+ last = Interrupt->head;
+
+ while (index != last)
+ {
+ /* Advance to the next entry. */
+ index += 1;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
+ " %d: 0x%08X\n",
+ index, Interrupt->fifo[index]
+ );
+ }
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Enable
+**
+** Enable the specified interrupt.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to a gckVGINTERRUPT object.
+**
+** Id
+** Pointer to the variable that holds the interrupt number to be
+** registered in range 0..31.
+** If the value is less then 0, gckVGINTERRUPT_Enable will attempt
+** to find an unused interrupt. If such interrupt is found, the number
+** will be assigned to the variable if the functuion call succeedes.
+**
+** Handler
+** Pointer to the handler to register for the interrupt.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Enable(
+ IN gckVGINTERRUPT Interrupt,
+ IN OUT gctINT32_PTR Id,
+ IN gctINTERRUPT_HANDLER Handler
+ )
+{
+ gceSTATUS status;
+ gctINT32 i;
+
+ gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x Handler=0x%x", Interrupt, Id, Handler);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+ gcmkVERIFY_ARGUMENT(Id != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Handler != gcvNULL);
+
+ do
+ {
+ /* See if we need to allocate an ID. */
+ if (*Id < 0)
+ {
+ /* Find the first unused interrupt handler. */
+ for (i = 0; i < gcmCOUNTOF(Interrupt->handlers); ++i)
+ {
+ if (Interrupt->handlers[i] == gcvNULL)
+ {
+ break;
+ }
+ }
+
+ /* No unused innterrupts? */
+ if (i == gcmCOUNTOF(Interrupt->handlers))
+ {
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ break;
+ }
+
+ /* Update the interrupt ID. */
+ *Id = i;
+ }
+
+ /* Make sure the ID is in range. */
+ else if (*Id >= gcmCOUNTOF(Interrupt->handlers))
+ {
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+
+ /* Set interrupt handler. */
+ Interrupt->handlers[*Id] = Handler;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Disable
+**
+** Disable the specified interrupt.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to a gckVGINTERRUPT object.
+**
+** Id
+** Interrupt number to be disabled in range 0..31.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+gceSTATUS
+gckVGINTERRUPT_Disable(
+ IN gckVGINTERRUPT Interrupt,
+ IN gctINT32 Id
+ )
+{
+ gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x", Interrupt, Id);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+ gcmkVERIFY_ARGUMENT((Id >= 0) && (Id < gcmCOUNTOF(Interrupt->handlers)));
+
+ /* Reset interrupt handler. */
+ Interrupt->handlers[Id] = gcvNULL;
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckVGINTERRUPT_Enque
+**
+** Read the interrupt status register and put the value in the interrupt FIFO.
+**
+** INPUT:
+**
+** Interrupt
+** Pointer to a gckVGINTERRUPT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+#ifndef __QNXNTO__
+gceSTATUS
+gckVGINTERRUPT_Enque(
+ IN gckVGINTERRUPT Interrupt
+ )
+#else
+gceSTATUS
+gckVGINTERRUPT_Enque(
+ IN gckVGINTERRUPT Interrupt,
+ OUT gckOS *Os,
+ OUT gctSEMAPHORE *Semaphore
+ )
+#endif
+{
+ gceSTATUS status;
+ gctUINT32 triggered;
+
+ gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
+
+#ifdef __QNXNTO__
+ *Os = gcvNULL;
+ *Semaphore = gcvNULL;
+#endif
+
+ do
+ {
+ /* Read interrupt status register. */
+ gcmkERR_BREAK(gckVGHARDWARE_ReadInterrupt(
+ Interrupt->kernel->hardware, &triggered
+ ));
+
+ /* Mask out TS overflow interrupt */
+ triggered &= 0xfffffffe;
+
+ /* No interrupts to process? */
+ if (triggered == 0)
+ {
+ status = gcvSTATUS_NOT_OUR_INTERRUPT;
+ break;
+ }
+
+ /* FIFO overflow? */
+ if (Interrupt->fifoItems == gcmCOUNTOF(Interrupt->fifo))
+ {
+#if gcmENABLE_INTERRUPT_STATISTICS
+ Interrupt->fifoOverflow += 1;
+#endif
+
+ /* OR the interrupt with the last value in the FIFO. */
+ Interrupt->fifo[Interrupt->head] |= triggered;
+
+ /* Success (kind of). */
+ status = gcvSTATUS_OK;
+ }
+ else
+ {
+ /* Advance to the next entry. */
+ Interrupt->head += 1;
+ Interrupt->fifoItems += 1;
+
+#if gcmENABLE_INTERRUPT_STATISTICS
+ if (Interrupt->fifoItems > Interrupt->maxFifoItems)
+ {
+ Interrupt->maxFifoItems = Interrupt->fifoItems;
+ }
+#endif
+
+ /* Set the new value. */
+ Interrupt->fifo[Interrupt->head] = triggered;
+
+#ifndef __QNXNTO__
+ /* Increment the FIFO semaphore. */
+ gcmkERR_BREAK(gckOS_IncrementSemaphore(
+ Interrupt->os, Interrupt->fifoValid
+ ));
+#else
+ *Os = Interrupt->os;
+ *Semaphore = Interrupt->fifoValid;
+#endif
+
+ /* Windows kills our threads prematurely when the application
+ exists. Verify here that the thread is still alive. */
+ status = gckOS_VerifyThread(Interrupt->os, Interrupt->handler);
+
+ /* Has the thread been prematurely terminated? */
+ if (status != gcvSTATUS_OK)
+ {
+ /* Process all accumulated interrupts. */
+ while (Interrupt->head != Interrupt->tail)
+ {
+#if gcmENABLE_INTERRUPT_STATISTICS
+ /* Process the interrupt. */
+ _ProcessInterrupt(Interrupt, gcvNULL);
+#else
+ /* Process the interrupt. */
+ _ProcessInterrupt(Interrupt);
+#endif
+ }
+
+ /* Set success. */
+ status = gcvSTATUS_OK;
+ }
+ }
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
new file mode 100644
index 000000000000..71ef299a8f8a
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
@@ -0,0 +1,2756 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_MMU
+
+typedef enum _gceMMU_TYPE
+{
+ gcvMMU_USED = (0 << 4),
+ gcvMMU_SINGLE = (1 << 4),
+ gcvMMU_FREE = (2 << 4),
+}
+gceMMU_TYPE;
+
+#define gcmENTRY_TYPE(x) (x & 0xF0)
+
+#define gcmENTRY_COUNT(x) ((x & 0xFFFFFF00) >> 8)
+
+#define gcdMMU_TABLE_DUMP 0
+
+#define gcdVERTEX_START (128 << 10)
+
+typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
+
+typedef struct _gcsMMU_STLB
+{
+ gctPHYS_ADDR physical;
+ gctUINT32_PTR logical;
+ gctSIZE_T size;
+ gctPHYS_ADDR_T physBase;
+ gctSIZE_T pageCount;
+ gctUINT32 mtlbIndex;
+ gctUINT32 mtlbEntryNum;
+ gcsMMU_STLB_PTR next;
+} gcsMMU_STLB;
+
+typedef struct _gcsMMU_STLB_ALLOC *gcsMMU_STLB_ALLOC_PTR;
+
+typedef struct _gcsMMU_STLB_ALLOC
+{
+ gctPHYS_ADDR physical;
+ gctUINT32_PTR logical;
+ gctSIZE_T size;
+ gcsMMU_STLB_ALLOC_PTR next;
+} gcsMMU_STLB_ALLOC;
+
+#if gcdSHARED_PAGETABLE
+typedef struct _gcsSharedPageTable * gcsSharedPageTable_PTR;
+typedef struct _gcsSharedPageTable
+{
+ /* Shared gckMMU object. */
+ gckMMU mmu;
+
+ /* Hardwares which use this shared pagetable. */
+ gckHARDWARE hardwares[gcdMAX_GPU_COUNT];
+
+ /* Number of cores use this shared pagetable. */
+ gctUINT32 reference;
+}
+gcsSharedPageTable;
+
+static gcsSharedPageTable_PTR sharedPageTable = gcvNULL;
+#endif
+
+typedef struct _gcsDynamicSpaceNode * gcsDynamicSpaceNode_PTR;
+typedef struct _gcsDynamicSpaceNode
+{
+ gctUINT32 start;
+ gctINT32 entries;
+}
+gcsDynamicSpaceNode;
+
+static void
+_WritePageEntry(
+ IN gctUINT32_PTR PageEntry,
+ IN gctUINT32 EntryValue
+ )
+{
+ static gctUINT16 data = 0xff00;
+
+ if (*(gctUINT8 *)&data == 0xff)
+ {
+ *PageEntry = gcmSWAB32(EntryValue);
+ }
+ else
+ {
+ *PageEntry = EntryValue;
+ }
+}
+
+static gctUINT32
+_ReadPageEntry(
+ IN gctUINT32_PTR PageEntry
+ )
+{
+ static gctUINT16 data = 0xff00;
+ gctUINT32 entryValue;
+
+ if (*(gctUINT8 *)&data == 0xff)
+ {
+ entryValue = *PageEntry;
+ return gcmSWAB32(entryValue);
+ }
+ else
+ {
+ return *PageEntry;
+ }
+}
+
+static gceSTATUS
+_FillPageTable(
+ IN gctUINT32_PTR PageTable,
+ IN gctUINT32 PageCount,
+ IN gctUINT32 EntryValue
+)
+{
+ gctUINT i;
+
+ for (i = 0; i < PageCount; i++)
+ {
+ _WritePageEntry(PageTable + i, EntryValue);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_FillMap(
+ IN gctUINT32_PTR Map,
+ IN gctUINT32 PageCount,
+ IN gctUINT32 EntryValue
+)
+{
+ gctUINT i;
+
+ for (i = 0; i < PageCount; i++)
+ {
+ Map[i] = EntryValue;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_Link(
+ IN gcsADDRESS_AREA_PTR Area,
+ IN gctUINT32 Index,
+ IN gctUINT32 Next
+ )
+{
+ if (Index >= Area->pageTableEntries)
+ {
+ /* Just move heap pointer. */
+ Area->heapList = Next;
+ }
+ else
+ {
+ /* Address page table. */
+ gctUINT32_PTR map = Area->mapLogical;
+
+ /* Dispatch on node type. */
+ switch (gcmENTRY_TYPE(map[Index]))
+ {
+ case gcvMMU_SINGLE:
+ /* Set single index. */
+ map[Index] = (Next << 8) | gcvMMU_SINGLE;
+ break;
+
+ case gcvMMU_FREE:
+ /* Set index. */
+ map[Index + 1] = Next;
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", Index);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_AddFree(
+ IN gcsADDRESS_AREA_PTR Area,
+ IN gctUINT32 Index,
+ IN gctUINT32 Node,
+ IN gctUINT32 Count
+ )
+{
+ gctUINT32_PTR map = Area->mapLogical;
+
+ if (Count == 1)
+ {
+ /* Initialize a single page node. */
+ map[Node] = (~((1U<<8)-1)) | gcvMMU_SINGLE;
+ }
+ else
+ {
+ /* Initialize the node. */
+ map[Node + 0] = (Count << 8) | gcvMMU_FREE;
+ map[Node + 1] = ~0U;
+ }
+
+ /* Append the node. */
+ return _Link(Area, Index, Node);
+}
+
+static gceSTATUS
+_Collect(
+ IN gcsADDRESS_AREA_PTR Area
+ )
+{
+ gctUINT32_PTR map = Area->mapLogical;
+ gceSTATUS status;
+ gctUINT32 i, previous, start = 0, count = 0;
+
+ previous = Area->heapList = ~0U;
+ Area->freeNodes = gcvFALSE;
+
+ /* Walk the entire page table. */
+ for (i = 0; i < Area->pageTableEntries; ++i)
+ {
+ /* Dispatch based on type of page. */
+ switch (gcmENTRY_TYPE(map[i]))
+ {
+ case gcvMMU_USED:
+ /* Used page, so close any open node. */
+ if (count > 0)
+ {
+ /* Add the node. */
+ gcmkONERROR(_AddFree(Area, previous, start, count));
+
+ /* Reset the node. */
+ previous = start;
+ count = 0;
+ }
+ break;
+
+ case gcvMMU_SINGLE:
+ /* Single free node. */
+ if (count++ == 0)
+ {
+ /* Start a new node. */
+ start = i;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* A free node. */
+ if (count == 0)
+ {
+ /* Start a new node. */
+ start = i;
+ }
+
+ /* Advance the count. */
+ count += map[i] >> 8;
+
+ /* Advance the index into the page table. */
+ i += (map[i] >> 8) - 1;
+ break;
+
+ default:
+ gcmkFATAL("MMU page table correcupted at index %u!", i);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* See if we have an open node left. */
+ if (count > 0)
+ {
+ /* Add the node to the list. */
+ gcmkONERROR(_AddFree(Area, previous, start, count));
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
+ "Performed a garbage collection of the MMU heap.");
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the staus. */
+ return status;
+}
+
+static gctUINT32
+_SetPage(gctUINT32 PageAddress, gctUINT32 PageAddressExt, gctBOOL Writable)
+{
+ gctUINT32 entry = PageAddress
+ /* AddressExt */
+ | (PageAddressExt << 4)
+ /* Ignore exception */
+ | (0 << 1)
+ /* Present */
+ | (1 << 0);
+
+ if (Writable)
+ {
+ /* writable */
+ entry |= (1 << 2);
+ }
+#if gcdUSE_MMU_EXCEPTION
+ else
+ {
+ /* If this page is read only, set exception bit to make exception happens
+ ** when writing to it. */
+ entry |= gcdMMU_STLB_EXCEPTION;
+ }
+#endif
+
+ return entry;
+}
+
+static gctUINT32
+_MtlbOffset(
+ gctUINT32 Address
+ )
+{
+ return (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+}
+
+gctUINT32
+_AddressToIndex(
+ IN gcsADDRESS_AREA_PTR Area,
+ IN gctUINT32 Address
+ )
+{
+ gctUINT32 mtlbOffset = (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+ gctUINT32 stlbOffset = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+
+ return (mtlbOffset - Area->dynamicMappingStart) * gcdMMU_STLB_4K_ENTRY_NUM + stlbOffset;
+}
+
+static gctUINT32_PTR
+_StlbEntry(
+ gcsADDRESS_AREA_PTR Area,
+ gctUINT32 Address
+ )
+{
+ gctUINT32 index = _AddressToIndex(Area, Address);
+
+ return &Area->pageTableLogical[index];
+}
+
+static gceSTATUS
+_FillFlatMappingInMap(
+ gcsADDRESS_AREA_PTR Area,
+ gctUINT32 Index,
+ gctUINT32 NumPages
+ )
+{
+ gceSTATUS status;
+ gctUINT32 i;
+ gctBOOL gotIt = gcvFALSE;
+ gctUINT32 index = Index;
+ gctUINT32_PTR map = Area->mapLogical;
+ gctUINT32 previous = ~0U;
+
+ /* Find node which contains index. */
+ for (i = 0; !gotIt && (i < Area->pageTableEntries);)
+ {
+ gctUINT32 numPages;
+
+ switch (gcmENTRY_TYPE(map[i]))
+ {
+ case gcvMMU_SINGLE:
+ if (i == index)
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ previous = i;
+ i = map[i] >> 8;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ numPages = map[i] >> 8;
+ if (index >= i && index + NumPages - 1 < i + numPages)
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ previous = i;
+ i = map[i + 1];
+ }
+ break;
+
+ case gcvMMU_USED:
+ i++;
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ switch (gcmENTRY_TYPE(map[i]))
+ {
+ case gcvMMU_SINGLE:
+ /* Unlink single node from free list. */
+ gcmkONERROR(
+ _Link(Area, previous, map[i] >> 8));
+ break;
+
+ case gcvMMU_FREE:
+ /* Split the node. */
+ {
+ gctUINT32 start;
+ gctUINT32 next = map[i+1];
+ gctUINT32 total = map[i] >> 8;
+ gctUINT32 countLeft = index - i;
+ gctUINT32 countRight = total - countLeft - NumPages;
+
+ if (countLeft)
+ {
+ start = i;
+ _AddFree(Area, previous, start, countLeft);
+ previous = start;
+ }
+
+ if (countRight)
+ {
+ start = index + NumPages;
+ _AddFree(Area, previous, start, countRight);
+ previous = start;
+ }
+
+ _Link(Area, previous, next);
+ }
+ break;
+ }
+
+ _FillMap(&map[index], NumPages, gcvMMU_USED);
+
+ return gcvSTATUS_OK;
+OnError:
+ return status;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+gctUINT32
+_StlbOffset(
+ gctUINT32 Address
+ )
+{
+ return (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+}
+
+static gceSTATUS
+_AllocateStlb(
+ IN gckOS Os,
+ OUT gcsMMU_STLB_PTR *Stlb
+ )
+{
+ gceSTATUS status;
+ gcsMMU_STLB_PTR stlb;
+ gctPOINTER pointer;
+
+ /* Allocate slave TLB record. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsMMU_STLB), &pointer));
+ stlb = pointer;
+
+ stlb->size = gcdMMU_STLB_4K_SIZE;
+
+ /* Allocate slave TLB entries. */
+ gcmkONERROR(gckOS_AllocateContiguous(
+ Os,
+ gcvFALSE,
+ &stlb->size,
+ &stlb->physical,
+ (gctPOINTER)&stlb->logical
+ ));
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(Os, stlb->logical, &stlb->physBase));
+
+#if gcdUSE_MMU_EXCEPTION
+ _FillPageTable(stlb->logical, stlb->size / 4, gcdMMU_STLB_EXCEPTION);
+#else
+ gckOS_ZeroMemory(stlb->logical, stlb->size);
+#endif
+
+ *Stlb = stlb;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+_SetupProcessAddressSpace(
+ IN gckMMU Mmu
+ )
+{
+ gceSTATUS status;
+ gctINT numEntries = 0;
+ gctUINT32_PTR map;
+
+ numEntries = gcdPROCESS_ADDRESS_SPACE_SIZE
+ /* Address space mapped by one MTLB entry. */
+ / (1 << gcdMMU_MTLB_SHIFT);
+
+ area->dynamicMappingStart = 0;
+
+ area->pageTableSize = numEntries * 4096;
+
+ area->pageTableEntries = area->pageTableSize / gcmSIZEOF(gctUINT32);
+
+ gcmkONERROR(gckOS_Allocate(Mmu->os,
+ area->pageTableSize,
+ (void **)&area->mapLogical));
+
+ /* Initialization. */
+ map = area->mapLogical;
+ map[0] = (area->pageTableEntries << 8) | gcvMMU_FREE;
+ map[1] = ~0U;
+ area->heapList = 0;
+ area->freeNodes = gcvFALSE;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+#else
+static gceSTATUS
+_FillFlatMapping(
+ IN gckMMU Mmu,
+ IN gctUINT32 PhysBase,
+ OUT gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gcsMMU_STLB_PTR head = gcvNULL, pre = gcvNULL;
+ gctUINT32 start = PhysBase & ~gcdMMU_PAGE_64K_MASK;
+ gctUINT32 end = (gctUINT32) (PhysBase + Size - 1) & ~gcdMMU_PAGE_64K_MASK;
+ gctUINT32 mStart = start >> gcdMMU_MTLB_SHIFT;
+ gctUINT32 mEnd = end >> gcdMMU_MTLB_SHIFT;
+ gctUINT32 sStart = (start & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+ gctUINT32 sEnd = (end & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+ gctPHYS_ADDR_T physical;
+ gctUINT32 size;
+ gctUINT32 mtlbEntries = 0;
+ gctUINT32 mtlbCountStart = mStart;
+ gctUINT32 stlbCount = 0;
+ gctSIZE_T stlbTotalSize = 0;
+ gctPHYS_ADDR stlbPhysical = gcvNULL;
+ gctUINT32_PTR stlbLogical = gcvNULL;
+ gcsMMU_STLB_ALLOC_PTR stlbAlloc = gcvNULL;
+
+
+ gctUINT32 mtlb = _MtlbOffset(PhysBase);
+ gcsADDRESS_AREA_PTR area = &Mmu->area[0];
+
+ /************************ Setup flat mapping in dynamic range. ****************/
+
+ if (area->dynamicMappingStart != gcvINVALID_ADDRESS && mtlb >= area->dynamicMappingStart &&
+ _MtlbOffset(PhysBase + Size - 1) < area->dynamicMappingEnd)
+ {
+ gctUINT32_PTR stlbEntry;
+ gctUINT i;
+
+ stlbEntry = _StlbEntry(area, PhysBase);
+
+ /* Must be aligned to page. */
+ gcmkASSERT((Size & 0xFFF) == 0);
+
+ for (i = 0; i < (Size / 4096); i++)
+ {
+ /* Flat mapping in page table. */
+ _WritePageEntry(stlbEntry, _SetPage(PhysBase + i * 4096, 0, gcvTRUE));
+ }
+
+ gcmkSAFECASTSIZET(size, Size);
+
+ /* Flat mapping in map. */
+ _FillFlatMappingInMap(area, _AddressToIndex(area, PhysBase), size / 4096);
+
+ return gcvSTATUS_OK;
+ }
+
+ /************************ Setup flat mapping in non dynamic range. **************/
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ /* Calculate How many STLB should we allocate: depending on
+ * number of non-valid mtlb entries for the requested
+ * adress range */
+ while (mtlbCountStart <= mEnd) {
+ gcmkASSERT(mtlbCountStart < gcdMMU_MTLB_ENTRY_NUM);
+
+ /*If the mtlb exists , the stlb already exists and it
+ * will be overwritten anyway: Allocate only when non-valid
+ * mtlb entry */
+ if (*(Mmu->mtlbLogical + mtlbCountStart) == 0)
+ {
+ mtlbEntries++;
+ }
+ ++mtlbCountStart;
+ }
+
+ if(mtlbEntries)
+ {
+ /*First Allocate the staticStlbAlloc stuct to track this allocation*/
+ gctPOINTER stlbAllocPtr = gcvNULL;
+ gcmkONERROR(gckOS_Allocate(Mmu->os, sizeof(struct _gcsMMU_STLB_ALLOC), &stlbAllocPtr));
+ stlbAlloc = stlbAllocPtr;
+ stlbTotalSize = gcdMMU_STLB_64K_SIZE * mtlbEntries;
+
+ /*Allocate all STLBs in one contiguous chunk*/
+ gcmkONERROR(
+ gckOS_AllocateContiguous(Mmu->os,
+ gcvFALSE,
+ &stlbTotalSize,
+ &stlbPhysical,
+ (gctPOINTER)&stlbLogical));
+
+ /*Save the allocation*/
+ stlbAlloc->physical = stlbPhysical;
+ stlbAlloc->logical = stlbLogical;
+ stlbAlloc->size = stlbTotalSize;
+ stlbAlloc->next = gcvNULL;
+ }
+
+ while (mStart <= mEnd)
+ {
+ gcsMMU_STLB_PTR stlb = gcvNULL;
+ gctUINT32 last = (mStart == mEnd) ? sEnd : (gcdMMU_STLB_64K_ENTRY_NUM - 1);
+
+ gcmkASSERT(mStart < gcdMMU_MTLB_ENTRY_NUM);
+ if (*(Mmu->mtlbLogical + mStart) == 0)
+ {
+ gctPOINTER pointer = gcvNULL;
+
+ gctUINT32 mtlbEntry;
+
+ gcmkONERROR(gckOS_Allocate(Mmu->os, sizeof(struct _gcsMMU_STLB), &pointer));
+ stlb = pointer;
+
+ stlb->mtlbEntryNum = 0;
+ stlb->next = gcvNULL;
+ stlb->physical = gcvNULL;
+ stlb->logical = gcvNULL;
+ stlb->size = gcdMMU_STLB_64K_SIZE;
+ stlb->pageCount = 0;
+
+ gcmkASSERT(stlbLogical);
+
+ stlb->logical = (gctUINT32_PTR)(((gctPOINTER)stlbLogical) + stlb->size * stlbCount);
+ stlb->physical = (gctPHYS_ADDR)(((gctPOINTER)stlbPhysical) + stlb->size * stlbCount);
+
+ if (pre == gcvNULL)
+ {
+ pre = head = stlb;
+ }
+ else
+ {
+ gcmkASSERT(pre->next == gcvNULL);
+ pre->next = stlb;
+ pre = stlb;
+ }
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ Mmu->os,
+ stlb->logical,
+ &physical));
+
+ gcmkSAFECASTPHYSADDRT(stlb->physBase, physical);
+
+ if (stlb->physBase & (gcdMMU_STLB_64K_SIZE - 1))
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ physical = stlb->physBase
+ /* 64KB page size */
+ | (1 << 2)
+ /* Ignore exception */
+ | (0 << 1)
+ /* Present */
+ | (1 << 0);
+
+ gcmkSAFECASTPHYSADDRT(mtlbEntry, physical);
+
+ _WritePageEntry(Mmu->mtlbLogical + mStart, mtlbEntry);
+
+#if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
+ __FUNCTION__, __LINE__,
+ mStart,
+ _ReadPageEntry(Mmu->mtlbLogical + mStart));
+#endif
+
+ stlb->mtlbIndex = mStart;
+ stlb->mtlbEntryNum = 1;
+#if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): STLB: logical:%08x -> physical:%08x\n",
+ __FUNCTION__, __LINE__,
+ stlb->logical,
+ stlb->physBase);
+#endif
+
+ /*Increment STLB allocs count*/
+ ++stlbCount;
+ }
+ else
+ {
+ stlb = Mmu->staticSTLB;
+
+ while (stlb)
+ {
+ gctUINT32 mtlbEntry = _ReadPageEntry(Mmu->mtlbLogical + mStart);
+
+ if (stlb->physBase == (mtlbEntry & gcdMMU_MTLB_ENTRY_STLB_MASK))
+ {
+ break;
+ }
+
+ stlb = stlb->next;
+ }
+ }
+
+ /* Fill STLB. */
+ sStart = (start & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+
+ while (sStart <= last)
+ {
+ gcmkASSERT(!(start & gcdMMU_PAGE_64K_MASK));
+ _WritePageEntry(stlb->logical + sStart, _SetPage(start, 0, gcvTRUE));
+#if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): insert STLB[%d]: %08x\n",
+ __FUNCTION__, __LINE__,
+ sStart,
+ _ReadPageEntry(stlb->logical + sStart));
+#endif
+ /* next page. */
+ start += gcdMMU_PAGE_64K_SIZE;
+ sStart++;
+ stlb->pageCount++;
+ }
+
+ ++mStart;
+ }
+
+ if (pre)
+ {
+ /* Insert the stlb into staticSTLB. */
+ if (Mmu->staticSTLB == gcvNULL)
+ {
+ Mmu->staticSTLB = head;
+ }
+ else
+ {
+ gcmkASSERT(pre != gcvNULL);
+ gcmkASSERT(pre->next == gcvNULL);
+ pre->next = Mmu->staticSTLB;
+ Mmu->staticSTLB = head;
+ }
+ }
+
+ if(stlbAlloc)
+ {
+ /*Insert the stlb Allocation*/
+ if (Mmu->staticStlbAllocs == gcvNULL)
+ {
+ Mmu->staticStlbAllocs = stlbAlloc;
+ }
+ else
+ {
+ gcmkASSERT(stlbAlloc->next == gcvNULL);
+ stlbAlloc->next = Mmu->staticStlbAllocs;
+ Mmu->staticStlbAllocs = stlbAlloc;
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+#if gcdENABLE_TRUST_APPLICATION
+ if (Mmu->hardware->secureMode == gcvSECURE_IN_TA)
+ {
+ gckKERNEL_SecurityMapMemory(Mmu->hardware->kernel, gcvNULL, PhysBase, (gctUINT32)Size/4096, &PhysBase);
+ }
+#endif
+
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Roll back. */
+ while (head != gcvNULL)
+ {
+ pre = head;
+ head = head->next;
+
+ if (pre->mtlbEntryNum != 0)
+ {
+ gcmkASSERT(pre->mtlbEntryNum == 1);
+ _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
+ }
+
+ /*Free the STLBs in one shot*/
+ if(stlbAlloc)
+ {
+ if(stlbLogical)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ stlbPhysical,
+ stlbLogical,
+ stlbTotalSize));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, stlbAlloc));
+ }
+
+ if (mutex)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ return status;
+}
+
+static gceSTATUS
+_FindDynamicSpace(
+ IN gckMMU Mmu,
+ OUT gcsDynamicSpaceNode_PTR *Array,
+ OUT gctINT * Size
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctPOINTER pointer = gcvNULL;
+ gcsDynamicSpaceNode_PTR array = gcvNULL;
+ gctINT size = 0;
+ gctINT i = 0, nodeStart = -1, nodeEntries = 0;
+
+ /* Allocate memory for the array. */
+ gcmkONERROR(gckOS_Allocate(Mmu->os,
+ gcmSIZEOF(*array) * (gcdMMU_MTLB_ENTRY_NUM / 2),
+ &pointer));
+
+ array = (gcsDynamicSpaceNode_PTR)pointer;
+
+ /* Loop all the entries. */
+ while (i < gcdMMU_MTLB_ENTRY_NUM)
+ {
+ if (!Mmu->mtlbLogical[i])
+ {
+ if (nodeStart < 0)
+ {
+ /* This is the first entry of the dynamic space. */
+ nodeStart = i;
+ nodeEntries = 1;
+ }
+ else
+ {
+ /* Other entries of the dynamic space. */
+ nodeEntries++;
+ }
+ }
+ else if (nodeStart >= 0)
+ {
+ /* Save the previous node. */
+ array[size].start = nodeStart;
+ array[size].entries = nodeEntries;
+ size++;
+
+ /* Reset the start. */
+ nodeStart = -1;
+ nodeEntries = 0;
+ }
+
+ i++;
+ }
+
+ /* Save the previous node. */
+ if (nodeStart >= 0)
+ {
+ array[size].start = nodeStart;
+ array[size].entries = nodeEntries;
+ size++;
+ }
+
+#if gcdMMU_TABLE_DUMP
+ for (i = 0; i < size; i++)
+ {
+ gckOS_Print("%s(%d): [%d]: start=%d, entries=%d.\n",
+ __FUNCTION__, __LINE__,
+ i,
+ array[i].start,
+ array[i].entries);
+ }
+#endif
+
+ *Array = array;
+ *Size = size;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (pointer != gcvNULL)
+ {
+ gckOS_Free(Mmu->os, pointer);
+ }
+
+ return status;
+}
+
+static gceSTATUS
+_SetupAddressArea(
+ IN gckOS Os,
+ IN gcsADDRESS_AREA_PTR Area,
+ IN gctUINT32 NumMTLBEntries
+ )
+{
+ gceSTATUS status;
+ gctUINT32_PTR map;
+
+ gcmkHEADER();
+ Area->pageTableSize = NumMTLBEntries * 4096;
+
+ gcmkSAFECASTSIZET(Area->pageTableEntries, Area->pageTableSize / gcmSIZEOF(gctUINT32));
+
+ gcmkONERROR(gckOS_Allocate(Os, Area->pageTableSize, (void **)&Area->mapLogical));
+
+ /* Initialization. */
+ map = Area->mapLogical;
+ map[0] = (Area->pageTableEntries << 8) | gcvMMU_FREE;
+ map[1] = ~0U;
+ Area->heapList = 0;
+ Area->freeNodes = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_SetupDynamicSpace(
+ IN gckMMU Mmu
+ )
+{
+ gceSTATUS status;
+ gcsDynamicSpaceNode_PTR nodeArray = gcvNULL;
+ gctINT i, nodeArraySize = 0;
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+ gctINT numEntries = 0;
+ gctBOOL acquired = gcvFALSE;
+ gctUINT32 mtlbEntry;
+ gcsADDRESS_AREA_PTR area = &Mmu->area[0];
+ gcsADDRESS_AREA_PTR areaSecure = &Mmu->area[gcvADDRESS_AREA_SECURE];
+ gctUINT32 secureAreaSize = 0;
+
+ /* Find all the dynamic address space. */
+ gcmkONERROR(_FindDynamicSpace(Mmu, &nodeArray, &nodeArraySize));
+
+ for (i = 0; i < nodeArraySize; i++)
+ {
+ if (nodeArray[i].entries > numEntries)
+ {
+ area->dynamicMappingStart = nodeArray[i].start;
+ numEntries = nodeArray[i].entries;
+ area->dynamicMappingEnd = area->dynamicMappingStart + numEntries;
+ }
+ }
+
+ gckOS_Free(Mmu->os, (gctPOINTER)nodeArray);
+
+#if gcdENABLE_TRUST_APPLICATION
+ if (gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_SECURITY) == gcvSTATUS_TRUE)
+ {
+ secureAreaSize = gcdMMU_SECURE_AREA_SIZE;
+ }
+#endif
+
+ /* Setup secure address area if need. */
+ if (secureAreaSize > 0)
+ {
+ gcmkASSERT(numEntries > (gctINT)secureAreaSize);
+
+ areaSecure->dynamicMappingStart = area->dynamicMappingStart
+ + (numEntries - secureAreaSize);
+
+ gcmkONERROR(_SetupAddressArea(Mmu->os, areaSecure, secureAreaSize));
+
+ numEntries -= secureAreaSize;
+ }
+
+ /* Setup normal address area. */
+ gcmkONERROR(_SetupAddressArea(Mmu->os, area, numEntries));
+
+ /* Construct Slave TLB. */
+ gcmkONERROR(gckOS_AllocateContiguous(Mmu->os,
+ gcvFALSE,
+ &area->pageTableSize,
+ &area->pageTablePhysical,
+ (gctPOINTER)&area->pageTableLogical));
+
+#if gcdUSE_MMU_EXCEPTION
+ gcmkONERROR(_FillPageTable(area->pageTableLogical,
+ area->pageTableEntries,
+ /* Enable exception */
+ 1 << 1));
+#else
+ /* Invalidate all entries. */
+ gcmkONERROR(gckOS_ZeroMemory(area->pageTableLogical,
+ area->pageTableSize));
+#endif
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(Mmu->os,
+ area->pageTableLogical,
+ &physical));
+
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Map to Master TLB. */
+ for (i = (gctINT)area->dynamicMappingStart;
+ i < (gctINT)area->dynamicMappingStart + numEntries;
+ i++)
+ {
+ mtlbEntry = address
+ /* 4KB page size */
+ | (0 << 2)
+ /* Ignore exception */
+ | (0 << 1)
+ /* Present */
+ | (1 << 0);
+
+ _WritePageEntry(Mmu->mtlbLogical + i, mtlbEntry);
+
+#if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
+ __FUNCTION__, __LINE__,
+ i,
+ _ReadPageEntry(Mmu->mtlbLogical + i));
+#endif
+ address += gcdMMU_STLB_4K_SIZE;
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (area->mapLogical)
+ {
+ gcmkVERIFY_OK(
+ gckOS_Free(Mmu->os, (gctPOINTER) area->mapLogical));
+
+
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ area->pageTablePhysical,
+ (gctPOINTER) area->pageTableLogical,
+ area->pageTableSize));
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ return status;
+}
+#endif
+
+gctUINT32
+_GetPageCountOfUsedNode(
+ gctUINT32_PTR Node
+ )
+{
+ gctUINT32 count;
+
+ count = gcmENTRY_COUNT(*Node);
+
+ if ((count << 8) == (~((1U<<8)-1)))
+ {
+ count = 1;
+ }
+
+ return count;
+}
+
+static gcsADDRESS_AREA_PTR
+_GetProcessArea(
+ IN gckMMU Mmu,
+ IN gctBOOL Secure
+ )
+{
+ gceADDRESS_AREA area = gcvADDRESS_AREA_NORMAL;
+
+#if gcdENABLE_TRUST_APPLICATION
+ if (Secure == gcvTRUE)
+ {
+ area = gcvADDRESS_AREA_SECURE;
+ }
+#endif
+
+ return &Mmu->area[area];
+}
+
+/*******************************************************************************
+**
+** _Construct
+**
+** Construct a new gckMMU object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSIZE_T MmuSize
+** Number of bytes for the page table.
+**
+** OUTPUT:
+**
+** gckMMU * Mmu
+** Pointer to a variable that receives the gckMMU object pointer.
+*/
+gceSTATUS
+_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ )
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gckMMU mmu = gcvNULL;
+ gctUINT32_PTR map;
+ gctPOINTER pointer = gcvNULL;
+ gctUINT32 physBase;
+ gctUINT32 physSize;
+ gctUINT32 contiguousBase;
+ gctUINT32 contiguousSize;
+ gctUINT32 gpuAddress;
+ gctPHYS_ADDR_T gpuPhysical;
+ gcsADDRESS_AREA_PTR area = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x MmuSize=%lu", Kernel, MmuSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(MmuSize > 0);
+ gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckHARDWARE object pointer. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Allocate memory for the gckMMU object. */
+ gcmkONERROR(gckOS_Allocate(os, sizeof(struct _gckMMU), &pointer));
+
+ gckOS_ZeroMemory(pointer, sizeof(struct _gckMMU));
+
+ mmu = pointer;
+
+ /* Initialize the gckMMU object. */
+ mmu->object.type = gcvOBJ_MMU;
+ mmu->os = os;
+ mmu->hardware = hardware;
+ mmu->pageTableMutex = gcvNULL;
+ mmu->mtlbLogical = gcvNULL;
+ mmu->staticSTLB = gcvNULL;
+ mmu->staticStlbAllocs = gcvNULL;
+ mmu->enabled = gcvFALSE;
+ gcsLIST_Init(&mmu->hardwareList);
+
+
+ area = &mmu->area[0];
+ area->mapLogical = gcvNULL;
+ area->pageTableLogical = gcvNULL;
+
+ /* Create the page table mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &mmu->pageTableMutex));
+
+
+ if (hardware->mmuVersion == 0)
+ {
+ area->pageTableSize = MmuSize;
+
+ /* Construct address space management table. */
+ gcmkONERROR(gckOS_Allocate(mmu->os,
+ area->pageTableSize,
+ &pointer));
+
+ area->mapLogical = pointer;
+
+ /* Construct page table read by GPU. */
+ gcmkONERROR(gckOS_AllocateContiguous(mmu->os,
+ gcvFALSE,
+ &area->pageTableSize,
+ &area->pageTablePhysical,
+ (gctPOINTER)&area->pageTableLogical));
+
+
+ /* Compute number of entries in page table. */
+ gcmkSAFECASTSIZET(area->pageTableEntries, area->pageTableSize / sizeof(gctUINT32));
+
+ /* Mark all pages as free. */
+ map = area->mapLogical;
+
+ _FillPageTable(area->pageTableLogical, area->pageTableEntries, mmu->safeAddress);
+
+ map[0] = (area->pageTableEntries << 8) | gcvMMU_FREE;
+ map[1] = ~0U;
+ area->heapList = 0;
+ area->freeNodes = gcvFALSE;
+ }
+ else
+ {
+ /* Allocate the 4K mode MTLB table. */
+ mmu->mtlbSize = gcdMMU_MTLB_SIZE;
+
+ gcmkONERROR(
+ gckOS_AllocateContiguous(os,
+ gcvFALSE,
+ &mmu->mtlbSize,
+ &mmu->mtlbPhysical,
+ &pointer));
+
+ mmu->mtlbLogical = pointer;
+
+ area->dynamicMappingStart = gcvINVALID_ADDRESS;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ _FillPageTable(pointer, mmu->mtlbSize / 4, gcdMMU_MTLB_EXCEPTION);
+
+ /* Allocate a array to store stlbs. */
+ gcmkONERROR(gckOS_Allocate(os, mmu->mtlbSize, &mmu->stlbs));
+
+ gckOS_ZeroMemory(mmu->stlbs, mmu->mtlbSize);
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ gcmkONERROR(gckOS_AtomConstruct(os, &mmu->pageTableDirty[i]));
+ }
+
+ _SetupProcessAddressSpace(mmu);
+
+ /* Map kernel command buffer in MMU. */
+ for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+ {
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ mmu->os,
+ Kernel->command->queues[i].logical,
+ &gpuPhysical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(gpuAddress, gpuPhysical);
+
+ gcmkONERROR(gckMMU_FlatMapping(mmu, gpuAddress, 1));
+ }
+#else
+ /* Invalid all the entries. */
+ gcmkONERROR(
+ gckOS_ZeroMemory(pointer, mmu->mtlbSize));
+
+ gcmkONERROR(
+ gckOS_QueryOption(mmu->os, "physBase", &physBase));
+
+ gcmkONERROR(
+ gckOS_QueryOption(mmu->os, "physSize", &physSize));
+
+ gcmkONERROR(
+ gckOS_CPUPhysicalToGPUPhysical(mmu->os, physBase, &gpuPhysical));
+
+ gcmkSAFECASTPHYSADDRT(gpuAddress, gpuPhysical);
+
+ mmu->flatMappingStart = gpuAddress;
+ mmu->flatMappingEnd = gpuAddress + physSize;
+
+ if ( mmu->flatMappingEnd < mmu->flatMappingStart)
+ {
+ mmu->flatMappingEnd = gcvMAXUINT32;
+ }
+
+ if (physSize)
+ {
+ /* Setup user specified flat mapping. */
+ gcmkONERROR(_FillFlatMapping(mmu, gpuAddress, physSize));
+ }
+
+ status = gckOS_QueryOption(mmu->os, "contiguousBase", &contiguousBase);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ status = gckOS_QueryOption(mmu->os, "contiguousSize", &contiguousSize);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ if (contiguousSize && (contiguousBase < mmu->flatMappingStart || contiguousBase + contiguousSize > mmu->flatMappingEnd))
+ {
+ /* Setup flat mapping for reserved memory (VIDMEM). */
+ gcmkONERROR(_FillFlatMapping(mmu, contiguousBase, contiguousSize));
+ }
+ }
+ }
+
+ gcmkONERROR(_SetupDynamicSpace(mmu));
+#endif
+ }
+
+ mmu->safePageSize = 4096;
+
+ gcmkONERROR(gckOS_AllocateContiguous(
+ os,
+ gcvFALSE,
+ &mmu->safePageSize,
+ &mmu->safePagePhysical,
+ &mmu->safePageLogical
+ ));
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(os,
+ mmu->safePageLogical,
+ &gpuPhysical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(mmu->safeAddress, gpuPhysical);
+
+ gckOS_ZeroMemory(mmu->safePageLogical, mmu->safePageSize);
+
+ gcmkONERROR(gckQUEUE_Allocate(os, &mmu->recentFreedAddresses, 16));
+
+ /* Return the gckMMU object pointer. */
+ *Mmu = mmu;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Mmu=0x%x", *Mmu);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (mmu != gcvNULL)
+ {
+ if (area != gcvNULL && area->mapLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_Free(os, (gctPOINTER) area->mapLogical));
+
+
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(os,
+ area->pageTablePhysical,
+ (gctPOINTER) area->pageTableLogical,
+ area->pageTableSize));
+ }
+
+ if (mmu->mtlbLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(os,
+ mmu->mtlbPhysical,
+ (gctPOINTER) mmu->mtlbLogical,
+ mmu->mtlbSize));
+ }
+
+ if (mmu->pageTableMutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, mmu->pageTableMutex));
+ }
+
+ gcmkVERIFY_OK(gckQUEUE_Free(os, &mmu->recentFreedAddresses));
+
+ /* Mark the gckMMU object as unknown. */
+ mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the allocates memory. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, mmu));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** _Destroy
+**
+** Destroy a gckMMU object.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+_Destroy(
+ IN gckMMU Mmu
+ )
+{
+ gctUINT32 i;
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ while (Mmu->staticSTLB != gcvNULL)
+ {
+ gcsMMU_STLB_PTR pre = Mmu->staticSTLB;
+ Mmu->staticSTLB = pre->next;
+
+ if (pre->mtlbEntryNum != 0)
+ {
+ gcmkASSERT(pre->mtlbEntryNum == 1);
+ _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
+#if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): clean MTLB[%d]\n",
+ __FUNCTION__, __LINE__,
+ pre->mtlbIndex);
+#endif
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
+ }
+ /*Walk through all the static STLB allocations and free them*/
+ while (Mmu->staticStlbAllocs != gcvNULL)
+ {
+ gcsMMU_STLB_ALLOC_PTR stlbAlloc = Mmu->staticStlbAllocs;
+ Mmu->staticStlbAllocs = stlbAlloc->next;
+
+ if(stlbAlloc->logical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ stlbAlloc->physical,
+ stlbAlloc->logical,
+ stlbAlloc->size));
+ }
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, stlbAlloc));
+ }
+
+ if (Mmu->hardware->mmuVersion != 0)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ Mmu->mtlbPhysical,
+ (gctPOINTER) Mmu->mtlbLogical,
+ Mmu->mtlbSize));
+ }
+
+ for (i = 0; i < gcvADDRESS_AREA_COUNT; i++)
+ {
+ gcsADDRESS_AREA_PTR area = &Mmu->area[i];
+
+ /* Free address space management table. */
+ if (area->mapLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_Free(Mmu->os, (gctPOINTER) area->mapLogical));
+ }
+
+ if (area->pageTableLogical != gcvNULL)
+ {
+ /* Free page table. */
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ area->pageTablePhysical,
+ (gctPOINTER) area->pageTableLogical,
+ area->pageTableSize));
+ }
+ }
+
+ /* Delete the page table mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->pageTableMutex));
+
+#if gcdPROCESS_ADDRESS_SPACE
+ for (i = 0; i < Mmu->mtlbSize / 4; i++)
+ {
+ struct _gcsMMU_STLB *stlb = ((struct _gcsMMU_STLB **)Mmu->stlbs)[i];
+
+ if (stlb)
+ {
+ gcmkVERIFY_OK(gckOS_FreeContiguous(
+ Mmu->os,
+ stlb->physical,
+ stlb->logical,
+ stlb->size));
+
+ gcmkOS_SAFE_FREE(Mmu->os, stlb);
+ }
+ }
+
+ gcmkOS_SAFE_FREE(Mmu->os, Mmu->stlbs);
+#endif
+
+ if (Mmu->safePageLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_FreeContiguous(
+ Mmu->os,
+ Mmu->safePagePhysical,
+ Mmu->safePageLogical,
+ Mmu->safePageSize
+ ));
+ }
+
+ gcmkVERIFY_OK(gckQUEUE_Free(Mmu->os, &Mmu->recentFreedAddresses));
+
+ /* Mark the gckMMU object as unknown. */
+ Mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckMMU object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, Mmu));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** _AdjstIndex
+**
+** Adjust the index from which we search for a usable node to make sure
+** index allocated is greater than Start.
+*/
+gceSTATUS
+_AdjustIndex(
+ IN gckMMU Mmu,
+ IN gctUINT32 Index,
+ IN gctUINT32 PageCount,
+ IN gctUINT32 Start,
+ OUT gctUINT32 * IndexAdjusted
+ )
+{
+ gceSTATUS status;
+ gctUINT32 index = Index;
+ gcsADDRESS_AREA_PTR area = &Mmu->area[0];
+ gctUINT32_PTR map = area->mapLogical;
+
+ gcmkHEADER();
+
+ for (; index < area->pageTableEntries;)
+ {
+ gctUINT32 result = 0;
+ gctUINT32 nodeSize = 0;
+
+ if (index >= Start)
+ {
+ break;
+ }
+
+ switch (gcmENTRY_TYPE(map[index]))
+ {
+ case gcvMMU_SINGLE:
+ nodeSize = 1;
+ break;
+
+ case gcvMMU_FREE:
+ nodeSize = map[index] >> 8;
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ if (nodeSize > PageCount)
+ {
+ result = index + (nodeSize - PageCount);
+
+ if (result >= Start)
+ {
+ break;
+ }
+ }
+
+ switch (gcmENTRY_TYPE(map[index]))
+ {
+ case gcvMMU_SINGLE:
+ index = map[index] >> 8;
+ break;
+
+ case gcvMMU_FREE:
+ index = map[index + 1];
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ *IndexAdjusted = index;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ )
+{
+#if gcdSHARED_PAGETABLE
+ gceSTATUS status;
+ gctPOINTER pointer;
+
+ gcmkHEADER_ARG("Kernel=0x%08x", Kernel);
+
+ if (sharedPageTable == gcvNULL)
+ {
+ gcmkONERROR(
+ gckOS_Allocate(Kernel->os,
+ sizeof(struct _gcsSharedPageTable),
+ &pointer));
+ sharedPageTable = pointer;
+
+ gcmkONERROR(
+ gckOS_ZeroMemory(sharedPageTable,
+ sizeof(struct _gcsSharedPageTable)));
+
+ gcmkONERROR(_Construct(Kernel, MmuSize, &sharedPageTable->mmu));
+ }
+
+ *Mmu = sharedPageTable->mmu;
+
+ sharedPageTable->hardwares[sharedPageTable->reference] = Kernel->hardware;
+
+ sharedPageTable->reference++;
+
+ gcmkFOOTER_ARG("sharedPageTable->reference=%lu", sharedPageTable->reference);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (sharedPageTable)
+ {
+ if (sharedPageTable->mmu)
+ {
+ gcmkVERIFY_OK(gckMMU_Destroy(sharedPageTable->mmu));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, sharedPageTable));
+ }
+
+ gcmkFOOTER();
+ return status;
+#else
+ return _Construct(Kernel, MmuSize, Mmu);
+#endif
+}
+
+gceSTATUS
+gckMMU_Destroy(
+ IN gckMMU Mmu
+ )
+{
+#if gcdSHARED_PAGETABLE
+ gckOS os = Mmu->os;
+
+ sharedPageTable->reference--;
+
+ if (sharedPageTable->reference == 0)
+ {
+ if (sharedPageTable->mmu)
+ {
+ gcmkVERIFY_OK(_Destroy(Mmu));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, sharedPageTable));
+ }
+
+ return gcvSTATUS_OK;
+#else
+ return _Destroy(Mmu);
+#endif
+}
+
+/*******************************************************************************
+**
+** gckMMU_AllocatePages
+**
+** Allocate pages inside the page table.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** gctSIZE_T PageCount
+** Number of pages to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * PageTable
+** Pointer to a variable that receives the base address of the page
+** table.
+**
+** gctUINT32 * Address
+** Pointer to a variable that receives the hardware specific address.
+*/
+gceSTATUS
+_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ IN gceSURF_TYPE Type,
+ IN gctBOOL Secure,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gctUINT32 index = 0, previous = ~0U, left;
+ gctUINT32_PTR map;
+ gctBOOL gotIt;
+ gctUINT32 address;
+ gctUINT32 pageCount;
+ gcsADDRESS_AREA_PTR area = _GetProcessArea(Mmu, Secure);
+
+ gcmkHEADER_ARG("Mmu=0x%x PageCount=%lu", Mmu, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+ if (PageCount > area->pageTableEntries)
+ {
+ /* Not enough pages avaiable. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ gcmkSAFECASTSIZET(pageCount, PageCount);
+
+#if gcdBOUNDARY_CHECK
+ /* Extra pages as bounary. */
+ pageCount += gcdBOUNDARY_CHECK * 2;
+#endif
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ /* Cast pointer to page table. */
+ for (map = area->mapLogical, gotIt = gcvFALSE; !gotIt;)
+ {
+ index = area->heapList;
+
+ if ((Mmu->hardware->mmuVersion == 0) && (Type == gcvSURF_VERTEX))
+ {
+ gcmkONERROR(_AdjustIndex(
+ Mmu,
+ index,
+ pageCount,
+ gcdVERTEX_START / gcmSIZEOF(gctUINT32),
+ &index
+ ));
+ }
+
+ /* Walk the heap list. */
+ for (; !gotIt && (index < area->pageTableEntries);)
+ {
+ /* Check the node type. */
+ switch (gcmENTRY_TYPE(map[index]))
+ {
+ case gcvMMU_SINGLE:
+ /* Single odes are valid if we only need 1 page. */
+ if (pageCount == 1)
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ /* Move to next node. */
+ previous = index;
+ index = map[index] >> 8;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* Test if the node has enough space. */
+ if (pageCount <= (map[index] >> 8))
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ /* Move to next node. */
+ previous = index;
+ index = map[index + 1];
+ }
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ /* Test if we are out of memory. */
+ if (index >= area->pageTableEntries)
+ {
+ if (area->freeNodes)
+ {
+ /* Time to move out the trash! */
+ gcmkONERROR(_Collect(area));
+
+ /* We are going to search from start, so reset previous to start. */
+ previous = ~0U;
+ }
+ else
+ {
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+ }
+
+ switch (gcmENTRY_TYPE(map[index]))
+ {
+ case gcvMMU_SINGLE:
+ /* Unlink single node from free list. */
+ gcmkONERROR(
+ _Link(area, previous, map[index] >> 8));
+ break;
+
+ case gcvMMU_FREE:
+ /* Check how many pages will be left. */
+ left = (map[index] >> 8) - pageCount;
+ switch (left)
+ {
+ case 0:
+ /* The entire node is consumed, just unlink it. */
+ gcmkONERROR(
+ _Link(area, previous, map[index + 1]));
+ break;
+
+ case 1:
+ /* One page will remain. Convert the node to a single node and
+ ** advance the index. */
+ map[index] = (map[index + 1] << 8) | gcvMMU_SINGLE;
+ index ++;
+ break;
+
+ default:
+ /* Enough pages remain for a new node. However, we will just adjust
+ ** the size of the current node and advance the index. */
+ map[index] = (left << 8) | gcvMMU_FREE;
+ index += left;
+ break;
+ }
+ break;
+ }
+
+ /* Mark node as used. */
+ gcmkONERROR(_FillMap(&map[index], pageCount, gcvMMU_USED));
+
+#if gcdBOUNDARY_CHECK
+ index += gcdBOUNDARY_CHECK;
+#endif
+
+ /* Record pageCount of allocated node at the beginning of node. */
+ if (pageCount == 1)
+ {
+ map[index] = (~((1U<<8)-1)) | gcvMMU_USED;
+ }
+ else
+ {
+ map[index] = (pageCount << 8) | gcvMMU_USED;
+ }
+
+ if (area->pageTableLogical != gcvNULL)
+ {
+ /* Return pointer to page table. */
+ *PageTable = &area->pageTableLogical[index];
+ }
+ else
+ {
+ /* Page table for secure area is handled in trust application. */
+ *PageTable = gcvNULL;
+ }
+
+ /* Build virtual address. */
+ if (Mmu->hardware->mmuVersion == 0)
+ {
+ gcmkONERROR(
+ gckHARDWARE_BuildVirtualAddress(Mmu->hardware, index, 0, &address));
+ }
+ else
+ {
+ gctUINT32 masterOffset = index / gcdMMU_STLB_4K_ENTRY_NUM
+ + area->dynamicMappingStart;
+ gctUINT32 slaveOffset = index % gcdMMU_STLB_4K_ENTRY_NUM;
+
+ address = (masterOffset << gcdMMU_MTLB_SHIFT)
+ | (slaveOffset << gcdMMU_STLB_4K_SHIFT);
+ }
+
+ if (Address != gcvNULL)
+ {
+ *Address = address;
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*PageTable=0x%x *Address=%08x",
+ *PageTable, gcmOPT_VALUE(Address));
+ return gcvSTATUS_OK;
+
+OnError:
+
+ if (mutex)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckMMU_FreePages
+**
+** Free pages inside the page table.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** gctPOINTER PageTable
+** Base address of the page table to free.
+**
+** gctSIZE_T PageCount
+** Number of pages to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+_FreePages(
+ IN gckMMU Mmu,
+ IN gctBOOL Secure,
+ IN gctUINT32 Address,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ )
+{
+ gctUINT32_PTR node;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctUINT32 pageCount;
+ gcuQUEUEDATA data;
+ gcsADDRESS_AREA_PTR area = _GetProcessArea(Mmu, Secure);
+
+ gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=%lu",
+ Mmu, PageTable, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ gcmkSAFECASTSIZET(pageCount, PageCount);
+
+#if gcdBOUNDARY_CHECK
+ pageCount += gcdBOUNDARY_CHECK * 2;
+#endif
+
+ /* Get the node by index. */
+ node = area->mapLogical + ((gctUINT32_PTR)PageTable - area->pageTableLogical);
+
+ if (pageCount != _GetPageCountOfUsedNode(node))
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+
+#if gcdBOUNDARY_CHECK
+ node -= gcdBOUNDARY_CHECK;
+#endif
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (Mmu->hardware->mmuVersion == 0)
+ {
+ _FillPageTable(PageTable, pageCount, Mmu->safeAddress);
+ }
+
+ if (pageCount == 1)
+ {
+ /* Single page node. */
+ node[0] = (~((1U<<8)-1)) | gcvMMU_SINGLE;
+
+ if (PageTable != gcvNULL)
+ {
+#if gcdUSE_MMU_EXCEPTION
+ /* Enable exception */
+ _WritePageEntry(PageTable, (1 << 1));
+#else
+ _WritePageEntry(PageTable, 0);
+#endif
+ }
+ }
+ else
+ {
+ /* Mark the node as free. */
+ node[0] = (pageCount << 8) | gcvMMU_FREE;
+ node[1] = ~0U;
+
+ if (PageTable != gcvNULL)
+ {
+#if gcdUSE_MMU_EXCEPTION
+ /* Enable exception */
+ gcmkVERIFY_OK(_FillPageTable(PageTable, (gctUINT32)PageCount, 1 << 1));
+#else
+ gcmkVERIFY_OK(_FillPageTable(PageTable, (gctUINT32)PageCount, 0));
+#endif
+ }
+ }
+
+ /* We have free nodes. */
+ area->freeNodes = gcvTRUE;
+
+ /* Record freed address range. */
+ data.addressData.start = Address;
+ data.addressData.end = Address + (gctUINT32)PageCount * 4096;
+ gckQUEUE_Enqueue(&Mmu->recentFreedAddresses, &data);
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ acquired = gcvFALSE;
+
+#if gcdENABLE_TRUST_APPLICATION
+ if (Mmu->hardware->secureMode == gcvSECURE_IN_TA)
+ {
+ gckKERNEL_SecurityUnmapMemory(Mmu->hardware->kernel, Address, (gctUINT32)PageCount);
+ }
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+ return gckMMU_AllocatePagesEx(
+ Mmu, PageCount, gcvSURF_TYPE_UNKNOWN, gcvFALSE, PageTable, Address);
+}
+
+gceSTATUS
+gckMMU_AllocatePagesEx(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ IN gceSURF_TYPE Type,
+ IN gctBOOL Secure,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+#if gcdDISABLE_GPU_VIRTUAL_ADDRESS
+ gcmkPRINT("GPU virtual address is disabled.");
+ return gcvSTATUS_NOT_SUPPORTED;
+#else
+ return _AllocatePages(Mmu, PageCount, Type, Secure, PageTable, Address);
+#endif
+}
+
+gceSTATUS
+gckMMU_FreePages(
+ IN gckMMU Mmu,
+ IN gctBOOL Secure,
+ IN gctUINT32 Address,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ )
+{
+ return _FreePages(Mmu, Secure, Address, PageTable, PageCount);
+}
+
+gceSTATUS
+gckMMU_SetPage(
+ IN gckMMU Mmu,
+ IN gctPHYS_ADDR_T PageAddress,
+ IN gctBOOL Writable,
+ IN gctUINT32 *PageEntry
+ )
+{
+ gctUINT32 addressExt;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
+ gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
+
+ /* [31:0]. */
+ address = (gctUINT32)(PageAddress & 0xFFFFFFFF);
+ /* [39:32]. */
+ addressExt = (gctUINT32)((PageAddress >> 32) & 0xFF);
+
+ if (Mmu->hardware->mmuVersion == 0)
+ {
+ _WritePageEntry(PageEntry, address);
+ }
+ else
+ {
+ _WritePageEntry(PageEntry, _SetPage(address, addressExt, gcvTRUE));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckMMU_GetPageEntry(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address,
+ IN gctUINT32_PTR *PageTable
+ )
+{
+ gceSTATUS status;
+ struct _gcsMMU_STLB *stlb;
+ struct _gcsMMU_STLB **stlbs = Mmu->stlbs;
+ gctUINT32 offset = _MtlbOffset(Address);
+ gctUINT32 mtlbEntry;
+ gctBOOL ace = gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_ACE);
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT((Address & 0xFFF) == 0);
+
+ stlb = stlbs[offset];
+
+ if (stlb == gcvNULL)
+ {
+ gcmkONERROR(_AllocateStlb(Mmu->os, &stlb));
+
+ mtlbEntry = stlb->physBase
+ | gcdMMU_MTLB_4K_PAGE
+ | gcdMMU_MTLB_PRESENT
+ ;
+
+ /* Insert Slave TLB address to Master TLB entry.*/
+ _WritePageEntry(Mmu->mtlbLogical + offset, mtlbEntry);
+
+ /* Record stlb. */
+ stlbs[offset] = stlb;
+ }
+
+ *PageTable = &stlb->logical[_StlbOffset(Address)];
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+_CheckMap(
+ IN gckMMU Mmu
+ )
+{
+ gceSTATUS status;
+ gctUINT32_PTR map = area->mapLogical;
+ gctUINT32 index;
+
+ for (index = area->heapList; index < area->pageTableEntries;)
+ {
+ /* Check the node type. */
+ switch (gcmENTRY_TYPE(map[index]))
+ {
+ case gcvMMU_SINGLE:
+ /* Move to next node. */
+ index = map[index] >> 8;
+ break;
+
+ case gcvMMU_FREE:
+ /* Move to next node. */
+ index = map[index + 1];
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index [%u] = %x!", index, map[index]);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckMMU_FlatMapping(
+ IN gckMMU Mmu,
+ IN gctUINT32 Physical,
+ IN gctUINT32 NumPages
+ )
+{
+ gceSTATUS status;
+ gctUINT32 index = _AddressToIndex(Mmu, Physical);
+ gctUINT32 i;
+ gctUINT32_PTR pageTable;
+
+ for (i = 0; i < NumPages; i++)
+ {
+ gckMMU_GetPageEntry(Mmu, Physical + i * 4096, &pageTable);
+
+ _WritePageEntry(pageTable, _SetPage(Physical + i * 4096, 0));
+ }
+
+ gcmkONERROR(_FillFlatMappingInMap(Mmu, index, NumPages));
+
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Roll back. */
+ return status;
+}
+
+gceSTATUS
+gckMMU_FreePagesEx(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address,
+ IN gctSIZE_T PageCount
+ )
+{
+ gctUINT32_PTR node;
+ gceSTATUS status;
+
+#if gcdUSE_MMU_EXCEPTION
+ gctUINT32 i;
+ struct _gcsMMU_STLB *stlb;
+ struct _gcsMMU_STLB **stlbs = Mmu->stlbs;
+#endif
+
+ gcmkHEADER_ARG("Mmu=0x%x Address=0x%x PageCount=%lu",
+ Mmu, Address, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ /* Get the node by index. */
+ node = area->mapLogical + _AddressToIndex(Mmu, Address);
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+
+ if (PageCount == 1)
+ {
+ /* Single page node. */
+ node[0] = (~((1U<<8)-1)) | gcvMMU_SINGLE;
+ }
+ else
+ {
+ /* Mark the node as free. */
+ node[0] = (PageCount << 8) | gcvMMU_FREE;
+ node[1] = ~0U;
+ }
+
+ /* We have free nodes. */
+ area->freeNodes = gcvTRUE;
+
+#if gcdUSE_MMU_EXCEPTION
+ for (i = 0; i < PageCount; i++)
+ {
+ /* Get */
+ stlb = stlbs[_MtlbOffset(Address)];
+
+ /* Enable exception */
+ stlb->logical[_StlbOffset(Address)] = gcdMMU_STLB_EXCEPTION;
+ }
+#endif
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckMMU_Flush(
+ IN gckMMU Mmu,
+ IN gceSURF_TYPE Type
+ )
+{
+#if !gcdPROCESS_ADDRESS_SPACE
+ gckHARDWARE hardware;
+#endif
+ gctUINT32 mask;
+ gctINT i;
+
+ if (Type == gcvSURF_VERTEX || Type == gcvSURF_INDEX)
+ {
+ mask = gcvPAGE_TABLE_DIRTY_BIT_FE;
+ }
+ else
+ {
+ mask = gcvPAGE_TABLE_DIRTY_BIT_OTHER;
+ }
+
+ i = 0;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ gcmkVERIFY_OK(
+ gckOS_AtomSetMask(Mmu->pageTableDirty[i], mask));
+ }
+#else
+#if gcdSHARED_PAGETABLE
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ hardware = sharedPageTable->hardwares[i];
+ if (hardware)
+ {
+ gcmkVERIFY_OK(gckOS_AtomSetMask(hardware->pageTableDirty, mask));
+ }
+ }
+#else
+ hardware = Mmu->hardware;
+ gcmkVERIFY_OK(
+ gckOS_AtomSetMask(hardware->pageTableDirty, mask));
+
+ {
+ gcsLISTHEAD_PTR hardwareHead;
+ gcmkLIST_FOR_EACH(hardwareHead, &Mmu->hardwareList)
+ {
+ hardware = gcmCONTAINEROF(hardwareHead, _gckHARDWARE, mmuHead);
+
+ if (hardware != Mmu->hardware)
+ {
+ gcmkVERIFY_OK(
+ gckOS_AtomSetMask(hardware->pageTableDirty, mask));
+ }
+ }
+ }
+#endif
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckMMU_DumpPageTableEntry(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address
+ )
+{
+#if gcdPROCESS_ADDRESS_SPACE
+ gcsMMU_STLB_PTR *stlbs = Mmu->stlbs;
+ gcsMMU_STLB_PTR stlbDesc = stlbs[_MtlbOffset(Address)];
+#else
+ gctUINT32_PTR pageTable;
+ gctUINT32 index;
+ gctUINT32 mtlb, stlb;
+#endif
+ gcsADDRESS_AREA_PTR area = &Mmu->area[0];
+
+ gcmkHEADER_ARG("Mmu=0x%08X Address=0x%08X", Mmu, Address);
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ gcmkASSERT(Mmu->hardware->mmuVersion > 0);
+
+#if gcdPROCESS_ADDRESS_SPACE
+ if (stlbDesc)
+ {
+ gcmkPRINT(" STLB entry = 0x%08X",
+ _ReadPageEntry(&stlbDesc->logical[_StlbOffset(Address)]));
+ }
+ else
+ {
+ gcmkPRINT(" MTLB entry is empty.");
+ }
+#else
+ mtlb = (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+
+ if (mtlb >= area->dynamicMappingStart)
+ {
+ stlb = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+
+ pageTable = area->pageTableLogical;
+
+ index = (mtlb - area->dynamicMappingStart)
+ * gcdMMU_STLB_4K_ENTRY_NUM
+ + stlb;
+
+ gcmkPRINT(" Page table entry = 0x%08X", _ReadPageEntry(pageTable + index));
+ }
+ else
+ {
+ gcsMMU_STLB_PTR stlbObj = Mmu->staticSTLB;
+ gctUINT32 entry = Mmu->mtlbLogical[mtlb];
+
+ stlb = (Address & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
+
+ entry &= 0xFFFFFFF0;
+
+ while (stlbObj)
+ {
+
+ if (entry == stlbObj->physBase)
+ {
+ gcmkPRINT(" Page table entry = 0x%08X", stlbObj->logical[stlb]);
+ break;
+ }
+
+ stlbObj = stlbObj->next;
+ }
+ }
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+void
+gckMMU_CheckSaftPage(
+ IN gckMMU Mmu
+ )
+{
+ gctUINT8_PTR safeLogical = Mmu->safePageLogical;
+ gctUINT32 offsets[] = {
+ 0,
+ 64,
+ 128,
+ 256,
+ 2560,
+ 4000
+ };
+
+ gctUINT32 i = 0;
+
+ while (i < gcmCOUNTOF(offsets))
+ {
+ if (safeLogical[offsets[i]] != 0)
+ {
+ gcmkPRINT("%s(%d) safe page is over written [%d] = %x",
+ __FUNCTION__, __LINE__, i, safeLogical[offsets[i]]);
+ }
+ }
+}
+
+void
+gckMMU_DumpAddressSpace(
+ IN gckMMU Mmu
+ )
+{
+ gctUINT i;
+ gctUINT next;
+ gcsADDRESS_AREA_PTR area = &Mmu->area[0];
+ gctUINT32_PTR map = area->mapLogical;
+ gctBOOL used = gcvFALSE;
+ gctUINT32 numPages;
+
+ /* Grab the mutex. */
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+
+ /* Find node which contains index. */
+ for (i = 0; i < area->pageTableEntries; i = next)
+ {
+ switch (gcmENTRY_TYPE(map[i]))
+ {
+ case gcvMMU_SINGLE:
+ numPages = 1;
+ next = i + numPages;
+ used = gcvFALSE;
+ break;
+
+ case gcvMMU_FREE:
+ numPages = map[i] >> 8;
+ next = i + numPages;
+ used = gcvFALSE;
+ break;
+
+ case gcvMMU_USED:
+ numPages = 1;
+ next = i + numPages;
+ used = gcvTRUE;
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", i);
+ return;
+ }
+
+ if (!used)
+ {
+ gcmkPRINT("Available Range [%d - %d)", i, i + numPages);
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+}
+
+void
+gckMMU_DumpRecentFreedAddress(
+ IN gckMMU Mmu
+ )
+{
+ gckQUEUE queue = &Mmu->recentFreedAddresses;
+ gctUINT32 i;
+ gcuQUEUEDATA *data;
+
+ if (queue->count)
+ {
+ gcmkPRINT(" Recent %d freed GPU address ranges:", queue->count);
+
+ for (i = 0; i < queue->count; i++)
+ {
+ gckQUEUE_GetData(queue, i, &data);
+
+ gcmkPRINT(" [%08X - %08X]", data->addressData.start, data->addressData.end);
+ }
+ }
+}
+
+gceSTATUS
+gckMMU_FillFlatMapping(
+ IN gckMMU Mmu,
+ IN gctUINT32 PhysBase,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+ gckHARDWARE hardware = Mmu->hardware;
+
+ if (hardware->mmuVersion)
+ {
+ gcmkONERROR(_FillFlatMapping(Mmu, PhysBase, Size));
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckMMU_IsFlatMapped(
+ IN gckMMU Mmu,
+ OUT gctUINT32 Physical,
+ OUT gctBOOL *In
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER();
+
+ gcmkVERIFY_ARGUMENT(In != gcvNULL);
+
+ if (gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_MMU) == gcvFALSE)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ *In = (Physical >= Mmu->flatMappingStart) && (Physical < Mmu->flatMappingEnd)
+ ? gcvTRUE
+ : gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_AttachHardware(
+ IN gckMMU Mmu,
+ IN gckHARDWARE Hardware
+ )
+{
+ gcmkHEADER();
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, _GC_OBJ_ZONE, "Attach core %d", Hardware->core);
+
+ gcsLIST_Add(&Hardware->mmuHead, &Mmu->hardwareList);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+#if !gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckMMU_GetPageEntry(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address,
+ IN gctUINT32_PTR *PageTable
+ )
+{
+ gctUINT32_PTR pageTable;
+ gctUINT32 index;
+ gctUINT32 mtlb, stlb;
+ gcsADDRESS_AREA_PTR area = &Mmu->area[0];
+
+ gcmkHEADER_ARG("Mmu=0x%08X Address=0x%08X", Mmu, Address);
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ gcmkASSERT(Mmu->hardware->mmuVersion > 0);
+
+ mtlb = (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+
+ if (mtlb >= area->dynamicMappingStart)
+ {
+ stlb = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+
+ pageTable = area->pageTableLogical;
+
+ index = (mtlb - area->dynamicMappingStart)
+ * gcdMMU_STLB_4K_ENTRY_NUM
+ + stlb;
+
+ *PageTable = pageTable + index;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
+
+/******************************************************************************
+****************************** T E S T C O D E ******************************
+******************************************************************************/
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c
new file mode 100644
index 000000000000..858e2f4f3730
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu_vg.c
@@ -0,0 +1,556 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+#define _GC_OBJ_ZONE gcvZONE_MMU
+
+/*******************************************************************************
+**
+** gckVGMMU_Construct
+**
+** Construct a new gckVGMMU object.
+**
+** INPUT:
+**
+** gckVGKERNEL Kernel
+** Pointer to an gckVGKERNEL object.
+**
+** gctSIZE_T MmuSize
+** Number of bytes for the page table.
+**
+** OUTPUT:
+**
+** gckVGMMU * Mmu
+** Pointer to a variable that receives the gckVGMMU object pointer.
+*/
+gceSTATUS gckVGMMU_Construct(
+ IN gckVGKERNEL Kernel,
+ IN gctUINT32 MmuSize,
+ OUT gckVGMMU * Mmu
+ )
+{
+ gckOS os;
+ gckVGHARDWARE hardware;
+ gceSTATUS status;
+ gckVGMMU mmu;
+ gctUINT32 * pageTable;
+ gctUINT32 i;
+
+ gcmkHEADER_ARG("Kernel=0x%x MmuSize=0x%x Mmu=0x%x", Kernel, MmuSize, Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(MmuSize > 0);
+ gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckVGHARDWARE object pointer. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Allocate memory for the gckVGMMU object. */
+ status = gckOS_Allocate(os, sizeof(struct _gckVGMMU), (gctPOINTER *) &mmu);
+
+ if (status < 0)
+ {
+ /* Error. */
+ gcmkFATAL(
+ "%s(%d): could not allocate gckVGMMU object.",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER();
+ return status;
+ }
+
+ /* Initialize the gckVGMMU object. */
+ mmu->object.type = gcvOBJ_MMU;
+ mmu->os = os;
+ mmu->hardware = hardware;
+
+ /* Create the mutex. */
+ status = gckOS_CreateMutex(os, &mmu->mutex);
+
+ if (status < 0)
+ {
+ /* Roll back. */
+ mmu->object.type = gcvOBJ_UNKNOWN;
+ gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+ gcmkFOOTER();
+ /* Error. */
+ return status;
+ }
+
+ /* Allocate the page table. */
+ mmu->pageTableSize = (gctUINT32)MmuSize;
+ status = gckOS_AllocateContiguous(os,
+ gcvFALSE,
+ &mmu->pageTableSize,
+ &mmu->pageTablePhysical,
+ &mmu->pageTableLogical);
+
+ if (status < 0)
+ {
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
+
+ mmu->object.type = gcvOBJ_UNKNOWN;
+ gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+ /* Error. */
+ gcmkFATAL(
+ "%s(%d): could not allocate page table.",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER();
+ return status;
+ }
+
+ /* Compute number of entries in page table. */
+ mmu->entryCount = (gctUINT32)mmu->pageTableSize / sizeof(gctUINT32);
+ mmu->entry = 0;
+
+ /* Mark the entire page table as available. */
+ pageTable = (gctUINT32 *) mmu->pageTableLogical;
+ for (i = 0; i < mmu->entryCount; i++)
+ {
+ pageTable[i] = (gctUINT32)~0;
+ }
+
+ /* Set page table address. */
+ status = gckVGHARDWARE_SetMMU(hardware, mmu->pageTableLogical);
+
+ if (status < 0)
+ {
+ /* Free the page table. */
+ gcmkVERIFY_OK(gckOS_FreeContiguous(mmu->os,
+ mmu->pageTablePhysical,
+ mmu->pageTableLogical,
+ mmu->pageTableSize));
+
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
+
+ mmu->object.type = gcvOBJ_UNKNOWN;
+ gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+ /* Error. */
+ gcmkFATAL(
+ "%s(%d): could not program page table.",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER();
+ return status;
+ }
+
+ /* Return the gckVGMMU object pointer. */
+ *Mmu = mmu;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_MMU,
+ "%s(%d): %u entries at %p.(0x%08X)\n",
+ __FUNCTION__, __LINE__,
+ mmu->entryCount,
+ mmu->pageTableLogical,
+ mmu->pageTablePhysical
+ );
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGMMU_Destroy
+**
+** Destroy a nAQMMU object.
+**
+** INPUT:
+**
+** gckVGMMU Mmu
+** Pointer to an gckVGMMU object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGMMU_Destroy(
+ IN gckVGMMU Mmu
+ )
+{
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ /* Free the page table. */
+ gcmkVERIFY_OK(gckOS_FreeContiguous(Mmu->os,
+ Mmu->pageTablePhysical,
+ Mmu->pageTableLogical,
+ Mmu->pageTableSize));
+
+ /* Roll back. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->mutex));
+
+ /* Mark the gckVGMMU object as unknown. */
+ Mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVGMMU object. */
+ gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu));
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVGMMU_AllocatePages
+**
+** Allocate pages inside the page table.
+**
+** INPUT:
+**
+** gckVGMMU Mmu
+** Pointer to an gckVGMMU object.
+**
+** gctSIZE_T PageCount
+** Number of pages to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * PageTable
+** Pointer to a variable that receives the base address of the page
+** table.
+**
+** gctUINT32 * Address
+** Pointer to a variable that receives the hardware specific address.
+*/
+gceSTATUS gckVGMMU_AllocatePages(
+ IN gckVGMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+ gceSTATUS status;
+ gctUINT32 tail, index, i;
+ gctUINT32 * table;
+ gctBOOL allocated = gcvFALSE;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageCount=0x%x PageTable=0x%x Address=0x%x",
+ Mmu, PageCount, PageTable, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_MMU,
+ "%s(%d): %u pages.\n",
+ __FUNCTION__, __LINE__,
+ PageCount
+ );
+
+ if (PageCount > Mmu->entryCount)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_MMU,
+ "%s(%d): page table too small for %u pages.\n",
+ __FUNCTION__, __LINE__,
+ PageCount
+ );
+
+ gcmkFOOTER_NO();
+ /* Not enough pages avaiable. */
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Grab the mutex. */
+ status = gckOS_AcquireMutex(Mmu->os, Mmu->mutex, gcvINFINITE);
+
+ if (status < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_MMU,
+ "%s(%d): could not acquire mutex.\n"
+ ,__FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER();
+ /* Error. */
+ return status;
+ }
+
+ /* Compute the tail for this allocation. */
+ tail = Mmu->entryCount - (gctUINT32)PageCount;
+
+ /* Walk all entries until we find enough slots. */
+ for (index = Mmu->entry; index <= tail;)
+ {
+ /* Access page table. */
+ table = (gctUINT32 *) Mmu->pageTableLogical + index;
+
+ /* See if all slots are available. */
+ for (i = 0; i < PageCount; i++, table++)
+ {
+ if (*table != ~0)
+ {
+ /* Start from next slot. */
+ index += i + 1;
+ break;
+ }
+ }
+
+ if (i == PageCount)
+ {
+ /* Bail out if we have enough page entries. */
+ allocated = gcvTRUE;
+ break;
+ }
+ }
+
+ if (!allocated)
+ {
+ if (status >= 0)
+ {
+ /* Walk all entries until we find enough slots. */
+ for (index = 0; index <= tail;)
+ {
+ /* Access page table. */
+ table = (gctUINT32 *) Mmu->pageTableLogical + index;
+
+ /* See if all slots are available. */
+ for (i = 0; i < PageCount; i++, table++)
+ {
+ if (*table != ~0)
+ {
+ /* Start from next slot. */
+ index += i + 1;
+ break;
+ }
+ }
+
+ if (i == PageCount)
+ {
+ /* Bail out if we have enough page entries. */
+ allocated = gcvTRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!allocated && (status >= 0))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_MMU,
+ "%s(%d): not enough free pages for %u pages.\n",
+ __FUNCTION__, __LINE__,
+ PageCount
+ );
+
+ /* Not enough empty slots available. */
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ if (status >= 0)
+ {
+ /* Build virtual address. */
+ status = gckVGHARDWARE_BuildVirtualAddress(Mmu->hardware,
+ index,
+ 0,
+ Address);
+
+ if (status >= 0)
+ {
+ /* Update current entry into page table. */
+ Mmu->entry = index + (gctUINT32)PageCount;
+
+ /* Return pointer to page table. */
+ *PageTable = (gctUINT32 *) Mmu->pageTableLogical + index;
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_MMU,
+ "%s(%d): allocated %u pages at index %u (0x%08X) @ %p.\n",
+ __FUNCTION__, __LINE__,
+ PageCount,
+ index,
+ *Address,
+ *PageTable
+ );
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->mutex));
+ gcmkFOOTER();
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVGMMU_FreePages
+**
+** Free pages inside the page table.
+**
+** INPUT:
+**
+** gckVGMMU Mmu
+** Pointer to an gckVGMMU object.
+**
+** gctPOINTER PageTable
+** Base address of the page table to free.
+**
+** gctSIZE_T PageCount
+** Number of pages to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGMMU_FreePages(
+ IN gckVGMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ )
+{
+ gctUINT32 * table;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=0x%x",
+ Mmu, PageTable, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_MMU,
+ "%s(%d): freeing %u pages at index %u @ %p.\n",
+ __FUNCTION__, __LINE__,
+ PageCount,
+ ((gctUINT32 *) PageTable - (gctUINT32 *) Mmu->pageTableLogical),
+ PageTable
+ );
+
+ /* Convert pointer. */
+ table = (gctUINT32 *) PageTable;
+
+ /* Mark the page table entries as available. */
+ while (PageCount-- > 0)
+ {
+ *table++ = (gctUINT32)~0;
+ }
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGMMU_SetPage(
+ IN gckVGMMU Mmu,
+ IN gctUINT32 PageAddress,
+ IN gctUINT32 *PageEntry
+ )
+{
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
+ gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
+
+ *PageEntry = PageAddress;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVGMMU_Flush(
+ IN gckVGMMU Mmu
+ )
+{
+ gckVGHARDWARE hardware;
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ hardware = Mmu->hardware;
+ gcmkVERIFY_OK(
+ gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c
new file mode 100644
index 000000000000..5508c10e3f12
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_power.c
@@ -0,0 +1,381 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_POWER
+
+/******************************************************************************\
+************************ Dynamic Voltage Frequency Setting *********************
+\******************************************************************************/
+#if gcdDVFS
+static gctUINT32
+_GetLoadHistory(
+ IN gckDVFS Dvfs,
+ IN gctUINT32 Select,
+ IN gctUINT32 Index
+)
+{
+ return Dvfs->loads[Index];
+}
+
+static void
+_IncreaseScale(
+ IN gckDVFS Dvfs,
+ IN gctUINT32 Load,
+ OUT gctUINT8 *Scale
+ )
+{
+ if (Dvfs->currentScale < 32)
+ {
+ *Scale = Dvfs->currentScale + 8;
+ }
+ else
+ {
+ *Scale = Dvfs->currentScale + 8;
+ *Scale = gcmMIN(64, *Scale);
+ }
+}
+
+static void
+_RecordFrequencyHistory(
+ gckDVFS Dvfs,
+ gctUINT32 Frequency
+ )
+{
+ gctUINT32 i = 0;
+
+ struct _FrequencyHistory *history = Dvfs->frequencyHistory;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (history->frequency == Frequency)
+ {
+ break;
+ }
+
+ if (history->frequency == 0)
+ {
+ history->frequency = Frequency;
+ break;
+ }
+
+ history++;
+ }
+
+ if (i < 16)
+ {
+ history->count++;
+ }
+}
+
+static gctUINT32
+_GetFrequencyHistory(
+ gckDVFS Dvfs,
+ gctUINT32 Frequency
+ )
+{
+ gctUINT32 i = 0;
+
+ struct _FrequencyHistory * history = Dvfs->frequencyHistory;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (history->frequency == Frequency)
+ {
+ break;
+ }
+
+ history++;
+ }
+
+ if (i < 16)
+ {
+ return history->count;
+ }
+
+ return 0;
+}
+
+static void
+_Policy(
+ IN gckDVFS Dvfs,
+ IN gctUINT32 Load,
+ OUT gctUINT8 *Scale
+ )
+{
+ gctUINT8 load[4], nextLoad;
+ gctUINT8 scale;
+
+ /* Last 4 history. */
+ load[0] = (Load & 0xFF);
+ load[1] = (Load & 0xFF00) >> 8;
+ load[2] = (Load & 0xFF0000) >> 16;
+ load[3] = (Load & 0xFF000000) >> 24;
+
+ /* Determine target scale. */
+ if (load[0] > 54)
+ {
+ _IncreaseScale(Dvfs, Load, &scale);
+ }
+ else
+ {
+ nextLoad = (load[0] + load[1] + load[2] + load[3])/4;
+
+ scale = Dvfs->currentScale * (nextLoad) / 54;
+
+ scale = gcmMAX(1, scale);
+ scale = gcmMIN(64, scale);
+ }
+
+ Dvfs->totalConfig++;
+
+ Dvfs->loads[(load[0]-1)/8]++;
+
+ *Scale = scale;
+
+
+ if (Dvfs->totalConfig % 100 == 0)
+ {
+ gcmkPRINT("=======================================================");
+ gcmkPRINT("GPU Load: %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
+ 8, 16, 24, 32, 40, 48, 56, 64);
+ gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
+ _GetLoadHistory(Dvfs,2, 0),
+ _GetLoadHistory(Dvfs,2, 1),
+ _GetLoadHistory(Dvfs,2, 2),
+ _GetLoadHistory(Dvfs,2, 3),
+ _GetLoadHistory(Dvfs,2, 4),
+ _GetLoadHistory(Dvfs,2, 5),
+ _GetLoadHistory(Dvfs,2, 6),
+ _GetLoadHistory(Dvfs,2, 7)
+ );
+
+ gcmkPRINT("Frequency(MHz) %-8d %-8d %-8d %-8d %-8d",
+ 58, 120, 240, 360, 480);
+ gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d",
+ _GetFrequencyHistory(Dvfs, 58),
+ _GetFrequencyHistory(Dvfs,120),
+ _GetFrequencyHistory(Dvfs,240),
+ _GetFrequencyHistory(Dvfs,360),
+ _GetFrequencyHistory(Dvfs,480)
+ );
+ }
+}
+
+static void
+_TimerFunction(
+ gctPOINTER Data
+ )
+{
+ gceSTATUS status;
+ gckDVFS dvfs = (gckDVFS) Data;
+ gckHARDWARE hardware = dvfs->hardware;
+ gctUINT32 value;
+ gctUINT32 frequency;
+ gctUINT8 scale;
+ gctUINT32 t1, t2, consumed;
+
+ gckOS_GetTicks(&t1);
+
+ gcmkONERROR(gckHARDWARE_QueryLoad(hardware, &value));
+
+ /* determine target sacle. */
+ _Policy(dvfs, value, &scale);
+
+ /* Set frequency and voltage. */
+ gcmkONERROR(gckOS_SetGPUFrequency(hardware->os, hardware->core, scale));
+
+ /* Query real frequency. */
+ gcmkONERROR(
+ gckOS_QueryGPUFrequency(hardware->os,
+ hardware->core,
+ &frequency,
+ &dvfs->currentScale));
+
+ _RecordFrequencyHistory(dvfs, frequency);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_POWER,
+ "Current frequency = %d",
+ frequency);
+
+ /* Set period. */
+ gcmkONERROR(gckHARDWARE_SetDVFSPeroid(hardware, frequency));
+
+OnError:
+ /* Determine next querying time. */
+ gckOS_GetTicks(&t2);
+
+ consumed = gcmMIN(((long)t2 - (long)t1), 5);
+
+ if (dvfs->stop == gcvFALSE)
+ {
+ gcmkVERIFY_OK(gckOS_StartTimer(hardware->os,
+ dvfs->timer,
+ dvfs->pollingTime - consumed));
+ }
+
+ return;
+}
+
+gceSTATUS
+gckDVFS_Construct(
+ IN gckHARDWARE Hardware,
+ OUT gckDVFS * Dvfs
+ )
+{
+ gceSTATUS status;
+ gctPOINTER pointer;
+ gckDVFS dvfs = gcvNULL;
+ gckOS os = Hardware->os;
+
+ gcmkHEADER_ARG("Hardware=0x%X", Hardware);
+
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
+
+ /* Allocate a gckDVFS manager. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckDVFS), &pointer));
+
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckDVFS));
+
+ dvfs = pointer;
+
+ /* Initialization. */
+ dvfs->hardware = Hardware;
+ dvfs->pollingTime = gcdDVFS_POLLING_TIME;
+ dvfs->os = Hardware->os;
+ dvfs->currentScale = 64;
+
+ /* Create a polling timer. */
+ gcmkONERROR(gckOS_CreateTimer(os, _TimerFunction, pointer, &dvfs->timer));
+
+ /* Initialize frequency and voltage adjustment helper. */
+ gcmkONERROR(gckOS_PrepareGPUFrequency(os, Hardware->core));
+
+ /* Return result. */
+ *Dvfs = dvfs;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (dvfs)
+ {
+ if (dvfs->timer)
+ {
+ gcmkVERIFY_OK(gckOS_DestroyTimer(os, dvfs->timer));
+ }
+
+ gcmkOS_SAFE_FREE(os, dvfs);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckDVFS_Destroy(
+ IN gckDVFS Dvfs
+ )
+{
+ gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
+ gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
+
+ /* Deinitialize helper fuunction. */
+ gcmkVERIFY_OK(gckOS_FinishGPUFrequency(Dvfs->os, Dvfs->hardware->core));
+
+ /* DestroyTimer. */
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Dvfs->os, Dvfs->timer));
+
+ gcmkOS_SAFE_FREE(Dvfs->os, Dvfs);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDVFS_Start(
+ IN gckDVFS Dvfs
+ )
+{
+ gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
+ gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
+
+ gckHARDWARE_InitDVFS(Dvfs->hardware);
+
+ Dvfs->stop = gcvFALSE;
+
+ gckOS_StartTimer(Dvfs->os, Dvfs->timer, Dvfs->pollingTime);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDVFS_Stop(
+ IN gckDVFS Dvfs
+ )
+{
+ gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
+ gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
+
+ Dvfs->stop = gcvTRUE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h
new file mode 100644
index 000000000000..91f6aeffcd91
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_precomp.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_precomp_h_
+#define __gc_hal_kernel_precomp_h_
+
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+
+#endif /* __gc_hal_kernel_precomp_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c
new file mode 100644
index 000000000000..e783582551ff
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security.c
@@ -0,0 +1,284 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+
+
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+#if gcdSECURITY
+
+/*
+** Open a security service channel.
+*/
+gceSTATUS
+gckKERNEL_SecurityOpen(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPU,
+ OUT gctUINT32 *Channel
+ )
+{
+ gceSTATUS status;
+
+ gcmkONERROR(gckOS_OpenSecurityChannel(Kernel->os, Kernel->core, Channel));
+ gcmkONERROR(gckOS_InitSecurityChannel(*Channel));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+/*
+** Close a security service channel
+*/
+gceSTATUS
+gckKERNEL_SecurityClose(
+ IN gctUINT32 Channel
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*
+** Security service interface.
+*/
+gceSTATUS
+gckKERNEL_SecurityCallService(
+ IN gctUINT32 Channel,
+ IN OUT gcsTA_INTERFACE * Interface
+)
+{
+ gceSTATUS status;
+ gcmkHEADER();
+
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ gckOS_CallSecurityService(Channel, Interface);
+
+ status = Interface->result;
+
+ gcmkONERROR(status);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityStartCommand(
+ IN gckKERNEL Kernel
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_START_COMMAND;
+ iface.u.StartCommand.gpu = Kernel->core;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityAllocateSecurityMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Bytes,
+ OUT gctUINT32 * Handle
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_ALLOCATE_SECRUE_MEMORY;
+ iface.u.AllocateSecurityMemory.bytes = Bytes;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ *Handle = iface.u.AllocateSecurityMemory.memory_handle;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityExecute(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Buffer,
+ IN gctUINT32 Bytes
+ )
+{
+ gceSTATUS status;
+#if defined(LINUX)
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+#endif
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_EXECUTE;
+ iface.u.Execute.command_buffer = (gctUINT32 *)Buffer;
+ iface.u.Execute.gpu = Kernel->core;
+ iface.u.Execute.command_buffer_length = Bytes;
+
+#if defined(LINUX)
+ gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, Buffer, &physical));
+ gcmkSAFECASTPHYSADDRT(address, physical);
+
+ iface.u.Execute.command_buffer = (gctUINT32 *)address;
+#endif
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(gckHARDWARE_UpdateQueueTail(
+ Kernel->hardware, 0, 0
+ ));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityMapMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 *PhysicalArray,
+ IN gctUINT32 PageCount,
+ OUT gctUINT32 * GPUAddress
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+#if defined(LINUX)
+ gctPHYS_ADDR_T physical;
+ gctUINT32 address;
+#endif
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_MAP_MEMORY;
+
+#if defined(LINUX)
+ gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, PhysicalArray, &physical));
+ gcmkSAFECASTPHYSADDRT(address, physical);
+ iface.u.MapMemory.physicals = (gctUINT32 *)address;
+#endif
+
+ iface.u.MapMemory.pageCount = PageCount;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ *GPUAddress = iface.u.MapMemory.gpuAddress;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityUnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPUAddress,
+ IN gctUINT32 PageCount
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_UNMAP_MEMORY;
+
+ iface.u.UnmapMemory.gpuAddress = GPUAddress;
+ iface.u.UnmapMemory.pageCount = PageCount;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security_v1.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security_v1.c
new file mode 100644
index 000000000000..6bb7370d1157
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_security_v1.c
@@ -0,0 +1,320 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+
+
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+#if gcdENABLE_TRUST_APPLICATION
+
+/*
+** Open a security service channel.
+*/
+gceSTATUS
+gckKERNEL_SecurityOpen(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPU,
+ OUT gctUINT32 *Channel
+ )
+{
+ gceSTATUS status;
+
+ gcmkONERROR(gckOS_OpenSecurityChannel(Kernel->os, Kernel->core, Channel));
+ gcmkONERROR(gckOS_InitSecurityChannel(*Channel));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+/*
+** Close a security service channel
+*/
+gceSTATUS
+gckKERNEL_SecurityClose(
+ IN gctUINT32 Channel
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*
+** Security service interface.
+*/
+gceSTATUS
+gckKERNEL_SecurityCallService(
+ IN gctUINT32 Channel,
+ IN OUT gcsTA_INTERFACE * Interface
+)
+{
+ gceSTATUS status;
+ gcmkHEADER();
+
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ gckOS_CallSecurityService(Channel, Interface);
+
+ status = Interface->result;
+
+ gcmkONERROR(status);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityStartCommand(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Address,
+ IN gctUINT32 Bytes
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_START_COMMAND;
+ iface.u.StartCommand.gpu = Kernel->core;
+ iface.u.StartCommand.address = Address;
+ iface.u.StartCommand.bytes = Bytes;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityAllocateSecurityMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Bytes,
+ OUT gctUINT32 * Handle
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_ALLOCATE_SECRUE_MEMORY;
+ iface.u.AllocateSecurityMemory.bytes = Bytes;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ *Handle = iface.u.AllocateSecurityMemory.memory_handle;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityMapMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 *PhysicalArray,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctUINT32 PageCount,
+ OUT gctUINT32 * GPUAddress
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_MAP_MEMORY;
+
+ iface.u.MapMemory.physicals = PhysicalArray;
+ iface.u.MapMemory.physical = Physical;
+ iface.u.MapMemory.pageCount = PageCount;
+ iface.u.MapMemory.gpuAddress = *GPUAddress;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_SecurityDumpMMUException(
+ IN gckKERNEL Kernel
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_DUMP_MMU_EXCEPTION;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+
+
+gceSTATUS
+gckKERNEL_SecurityUnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 GPUAddress,
+ IN gctUINT32 PageCount
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_UNMAP_MEMORY;
+
+ iface.u.UnmapMemory.gpuAddress = GPUAddress;
+ iface.u.UnmapMemory.pageCount = PageCount;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_ReadMMUException(
+ IN gckKERNEL Kernel,
+ IN gctUINT32_PTR MMUStatus,
+ IN gctUINT32_PTR MMUException
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_READ_MMU_EXCEPTION;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ *MMUStatus = iface.u.ReadMMUException.mmuStatus;
+ *MMUException = iface.u.ReadMMUException.mmuException;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_HandleMMUException(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 MMUStatus,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctUINT32 GPUAddress
+ )
+{
+ gceSTATUS status;
+ gcsTA_INTERFACE iface;
+
+ gcmkHEADER();
+
+ iface.command = KERNEL_HANDLE_MMU_EXCEPTION;
+
+ iface.u.HandleMMUException.mmuStatus = MMUStatus;
+ iface.u.HandleMMUException.physical = Physical;
+ iface.u.HandleMMUException.gpuAddress = GPUAddress;
+
+ gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+
+
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
new file mode 100644
index 000000000000..f99923e169cc
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
@@ -0,0 +1,571 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if gcdENABLE_VG
+
+#define _GC_OBJ_ZONE gcvZONE_VG
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_Construct
+**
+** Construct a new gckKERNEL object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN gctPOINTER Context
+** Pointer to a driver defined context.
+**
+** OUTPUT:
+**
+** gckKERNEL * Kernel
+** Pointer to a variable that will hold the pointer to the gckKERNEL
+** object.
+*/
+gceSTATUS gckVGKERNEL_Construct(
+ IN gckOS Os,
+ IN gctPOINTER Context,
+ IN gckKERNEL inKernel,
+ OUT gckVGKERNEL * Kernel
+ )
+{
+ gceSTATUS status;
+ gckVGKERNEL kernel = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+
+ do
+ {
+ /* Allocate the gckKERNEL object. */
+ gcmkERR_BREAK(gckOS_Allocate(
+ Os,
+ sizeof(struct _gckVGKERNEL),
+ (gctPOINTER *) &kernel
+ ));
+
+ /* Initialize the gckKERNEL object. */
+ kernel->object.type = gcvOBJ_KERNEL;
+ kernel->os = Os;
+ kernel->context = Context;
+ kernel->hardware = gcvNULL;
+ kernel->interrupt = gcvNULL;
+ kernel->command = gcvNULL;
+ kernel->mmu = gcvNULL;
+ kernel->kernel = inKernel;
+
+ /* Construct the gckVGHARDWARE object. */
+ gcmkERR_BREAK(gckVGHARDWARE_Construct(
+ Os, &kernel->hardware
+ ));
+
+ /* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
+ kernel->hardware->kernel = kernel;
+
+ /* Construct the gckVGINTERRUPT object. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Construct(
+ kernel, &kernel->interrupt
+ ));
+
+ /* Construct the gckVGCOMMAND object. */
+ gcmkERR_BREAK(gckVGCOMMAND_Construct(
+ kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
+ ));
+
+ /* Construct the gckVGMMU object. */
+ gcmkERR_BREAK(gckVGMMU_Construct(
+ kernel, gcmKB2BYTES(gcdGC355_VGMMU_MEMORY_SIZE_KB), &kernel->mmu
+ ));
+
+ /* Return pointer to the gckKERNEL object. */
+ *Kernel = kernel;
+
+ gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Roll back. */
+ if (kernel != gcvNULL)
+ {
+ if (kernel->mmu != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
+ }
+
+ if (kernel->command != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
+ }
+
+ if (kernel->interrupt != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
+ }
+
+ if (kernel->hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
+ }
+
+ gcmkVERIFY_OK(gckOS_Free(Os, kernel));
+ }
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Destroy
+**
+** Destroy an gckKERNEL object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckVGKERNEL_Destroy(
+ IN gckVGKERNEL Kernel
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ do
+ {
+ /* Destroy the gckVGMMU object. */
+ if (Kernel->mmu != gcvNULL)
+ {
+ gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
+ Kernel->mmu = gcvNULL;
+ }
+
+ /* Destroy the gckVGCOMMAND object. */
+ if (Kernel->command != gcvNULL)
+ {
+ gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
+ Kernel->command = gcvNULL;
+ }
+
+ /* Destroy the gckVGINTERRUPT object. */
+ if (Kernel->interrupt != gcvNULL)
+ {
+ gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
+ Kernel->interrupt = gcvNULL;
+ }
+
+ /* Destroy the gckVGHARDWARE object. */
+ if (Kernel->hardware != gcvNULL)
+ {
+ gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
+ Kernel->hardware = gcvNULL;
+ }
+
+ /* Mark the gckKERNEL object as unknown. */
+ Kernel->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckKERNEL object. */
+ gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Dispatch
+**
+** Dispatch a command received from the user HAL layer.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS gckVGKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE * kernelInterface = Interface;
+ gctUINT32 processID;
+ gckKERNEL kernel = Kernel;
+ gctPHYS_ADDR physical = gcvNULL;
+ gctPOINTER logical = gcvNULL;
+ gctSIZE_T bytes = 0;
+
+ gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ /* Dispatch on command. */
+ switch (Interface->command)
+ {
+ case gcvHAL_QUERY_CHIP_IDENTITY:
+ /* Query chip identity. */
+ gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
+ Kernel->vg->hardware,
+ &kernelInterface->u.QueryChipIdentity.chipModel,
+ &kernelInterface->u.QueryChipIdentity.chipRevision,
+ &kernelInterface->u.QueryChipIdentity.productID,
+ &kernelInterface->u.QueryChipIdentity.ecoID,
+ &kernelInterface->u.QueryChipIdentity.chipFeatures,
+ &kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
+ &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
+ ));
+ break;
+
+ case gcvHAL_QUERY_COMMAND_BUFFER:
+ /* Query command buffer information. */
+ gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
+ Kernel,
+ &kernelInterface->u.QueryCommandBuffer.information
+ ));
+ break;
+
+ case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
+ bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
+ /* Allocate non-paged memory. */
+ gcmkERR_BREAK(gckOS_AllocateNonPagedMemory(
+ Kernel->os,
+ gcvTRUE,
+ &bytes,
+ &physical,
+ &logical
+ ));
+
+ kernelInterface->u.AllocateNonPagedMemory.bytes = bytes;
+ kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
+ kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
+ break;
+
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ physical = gcmNAME_TO_PTR(kernelInterface->u.FreeNonPagedMemory.physical);
+
+ /* Unmap user logical out of physical memory first. */
+ gcmkERR_BREAK(gckOS_UnmapUserLogical(
+ Kernel->os,
+ physical,
+ (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes,
+ gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical)));
+
+
+ /* Free non-paged memory. */
+ gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
+ Kernel->os,
+ (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes,
+ physical,
+ gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical)
+ ));
+
+ gcmRELEASE_NAME(kernelInterface->u.FreeNonPagedMemory.physical);
+ break;
+
+ case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+ bytes = (gctSIZE_T) kernelInterface->u.AllocateContiguousMemory.bytes;
+ /* Allocate contiguous memory. */
+ gcmkERR_BREAK(gckOS_AllocateContiguous(
+ Kernel->os,
+ gcvTRUE,
+ &bytes,
+ &physical,
+ &logical
+ ));
+
+ kernelInterface->u.AllocateContiguousMemory.bytes = bytes;
+ kernelInterface->u.AllocateContiguousMemory.logical = gcmPTR_TO_UINT64(logical);
+ kernelInterface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ physical = gcmNAME_TO_PTR(kernelInterface->u.FreeContiguousMemory.physical);
+ /* Unmap user logical out of physical memory first. */
+ gcmkERR_BREAK(gckOS_UnmapUserLogical(
+ Kernel->os,
+ physical,
+ (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes,
+ gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical)
+ ));
+
+ /* Free contiguous memory. */
+ gcmkERR_BREAK(gckOS_FreeContiguous(
+ Kernel->os,
+ physical,
+ gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical),
+ (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes
+ ));
+
+ gcmRELEASE_NAME(kernelInterface->u.FreeContiguousMemory.physical);
+ break;
+
+ case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+ gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
+ break;
+
+ case gcvHAL_MAP_MEMORY:
+ /* Map memory. */
+ gcmkERR_BREAK(gckKERNEL_MapMemory(
+ Kernel,
+ gcmINT2PTR(kernelInterface->u.MapMemory.physical),
+ (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
+ &logical
+ ));
+ kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
+ break;
+
+ case gcvHAL_UNMAP_MEMORY:
+ /* Unmap memory. */
+ gcmkERR_BREAK(gckKERNEL_UnmapMemory(
+ Kernel,
+ gcmINT2PTR(kernelInterface->u.MapMemory.physical),
+ (gctSIZE_T) kernelInterface->u.MapMemory.bytes,
+ gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical)
+ ));
+ break;
+
+ case gcvHAL_MAP_USER_MEMORY:
+
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+
+ break;
+
+ case gcvHAL_LOCK_VIDEO_MEMORY:
+ gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface));
+ break;
+
+ case gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY:
+ gcmkERR_BREAK(gckKERNEL_BottomHalfUnlockVideoMemory(Kernel, processID,
+ kernelInterface->u.BottomHalfUnlockVideoMemory.node));
+ break;
+
+ case gcvHAL_USER_SIGNAL:
+#if !USE_NEW_LINUX_SIGNAL
+ /* Dispatch depends on the user signal subcommands. */
+ switch(Interface->u.UserSignal.command)
+ {
+ case gcvUSER_SIGNAL_CREATE:
+ /* Create a signal used in the user space. */
+ gcmkERR_BREAK(
+ gckOS_CreateUserSignal(Kernel->os,
+ Interface->u.UserSignal.manualReset,
+ &Interface->u.UserSignal.id));
+
+ gcmkVERIFY_OK(
+ gckKERNEL_AddProcessDB(Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id),
+ gcvNULL,
+ 0));
+ break;
+
+ case gcvUSER_SIGNAL_DESTROY:
+ gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
+ Kernel,
+ processID, gcvDB_SIGNAL,
+ gcmINT2PTR(Interface->u.UserSignal.id)));
+
+ /* Destroy the signal. */
+ gcmkERR_BREAK(
+ gckOS_DestroyUserSignal(Kernel->os,
+ Interface->u.UserSignal.id));
+
+ break;
+
+ case gcvUSER_SIGNAL_SIGNAL:
+ /* Signal the signal. */
+ gcmkERR_BREAK(
+ gckOS_SignalUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.state));
+ break;
+
+ case gcvUSER_SIGNAL_WAIT:
+ /* Wait on the signal. */
+ status = gckOS_WaitUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.wait);
+ break;
+
+ default:
+ /* Invalid user signal command. */
+ gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
+ }
+#endif
+ break;
+
+ case gcvHAL_COMMIT:
+ /* Commit a command and context buffer. */
+ gcmkERR_BREAK(gckVGCOMMAND_Commit(
+ Kernel->vg->command,
+ gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
+ gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
+ kernelInterface->u.VGCommit.entryCount,
+ gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable)
+ ));
+ break;
+
+ case gcvHAL_GET_BASE_ADDRESS:
+ /* Get base address. */
+ gcmkONERROR(
+ gckOS_GetBaseAddress(Kernel->os,
+ &Interface->u.GetBaseAddress.baseAddress));
+ break;
+
+ case gcvHAL_EVENT_COMMIT:
+ gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
+ break;
+
+ default:
+ /* Invalid command, try gckKERNEL_Dispatch */
+ status = gckKERNEL_Dispatch(Kernel, gcvNULL, gcvTRUE, Interface);
+ }
+
+OnError:
+ /* Save status. */
+ kernelInterface->status = status;
+
+ gcmkFOOTER();
+
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_QueryCommandBuffer
+**
+** Query command buffer attributes.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckVGHARDWARE object.
+**
+** OUTPUT:
+**
+** gcsCOMMAND_BUFFER_INFO_PTR Information
+** Pointer to the information structure to receive buffer attributes.
+*/
+gceSTATUS
+gckKERNEL_QueryCommandBuffer(
+ IN gckKERNEL Kernel,
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
+ Kernel, Information);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Get the information. */
+ status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
+
+ gcmkFOOTER();
+ /* Return status. */
+ return status;
+}
+
+#endif /* gcdENABLE_VG */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h
new file mode 100644
index 000000000000..16c8ad2e0ca5
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_vg_h_
+#define __gc_hal_kernel_vg_h_
+
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel_hardware.h"
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+/* gckKERNEL object. */
+struct _gckVGKERNEL
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckVGHARDWARE hardware;
+
+ /* Pointer to gckINTERRUPT object. */
+ gckVGINTERRUPT interrupt;
+
+ /* Pointer to gckCOMMAND object. */
+ gckVGCOMMAND command;
+
+ /* Pointer to context. */
+ gctPOINTER context;
+
+ /* Pointer to gckMMU object. */
+ gckVGMMU mmu;
+
+ gckKERNEL kernel;
+};
+
+/* gckMMU object. */
+struct _gckVGMMU
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckVGHARDWARE hardware;
+
+ /* The page table mutex. */
+ gctPOINTER mutex;
+
+ /* Page table information. */
+ gctSIZE_T pageTableSize;
+ gctPHYS_ADDR pageTablePhysical;
+ gctPOINTER pageTableLogical;
+
+ /* Allocation index. */
+ gctUINT32 entryCount;
+ gctUINT32 entry;
+};
+
+#endif /* __gc_hal_kernel_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
new file mode 100644
index 000000000000..835a0a78b16c
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
@@ -0,0 +1,3138 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#if defined(__QNXNTO__)
+#include <stdlib.h>
+#include <sys/slogcodes.h>
+#include <time.h>
+
+extern unsigned int slogUsageInterval;
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_VIDMEM
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** _Split
+**
+** Split a node on the required byte boundary.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to the node to split.
+**
+** gctSIZE_T Bytes
+** Number of bytes to keep in the node.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gctBOOL
+** gcvTRUE if the node was split successfully, or gcvFALSE if there is an
+** error.
+**
+*/
+static gctBOOL
+_Split(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+ gctPOINTER pointer = gcvNULL;
+
+ /* Make sure the byte boundary makes sense. */
+ if ((Bytes <= 0) || (Bytes > Node->VidMem.bytes))
+ {
+ return gcvFALSE;
+ }
+
+ /* Allocate a new gcuVIDMEM_NODE object. */
+ if (gcmIS_ERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(gcuVIDMEM_NODE),
+ &pointer)))
+ {
+ /* Error. */
+ return gcvFALSE;
+ }
+
+ node = pointer;
+
+ /* Initialize gcuVIDMEM_NODE structure. */
+ node->VidMem.offset = Node->VidMem.offset + Bytes;
+ node->VidMem.bytes = Node->VidMem.bytes - Bytes;
+ node->VidMem.alignment = 0;
+ node->VidMem.locked = 0;
+ node->VidMem.memory = Node->VidMem.memory;
+ node->VidMem.pool = Node->VidMem.pool;
+ node->VidMem.physical = Node->VidMem.physical;
+#ifdef __QNXNTO__
+ node->VidMem.processID = 0;
+ node->VidMem.logical = gcvNULL;
+#endif
+
+ /* Insert node behind specified node. */
+ node->VidMem.next = Node->VidMem.next;
+ node->VidMem.prev = Node;
+ Node->VidMem.next = node->VidMem.next->VidMem.prev = node;
+
+ /* Insert free node behind specified node. */
+ node->VidMem.nextFree = Node->VidMem.nextFree;
+ node->VidMem.prevFree = Node;
+ Node->VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
+
+ /* Adjust size of specified node. */
+ Node->VidMem.bytes = Bytes;
+
+ /* Success. */
+ return gcvTRUE;
+}
+
+/*******************************************************************************
+**
+** _Merge
+**
+** Merge two adjacent nodes together.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to the first of the two nodes to merge.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+*/
+static gceSTATUS
+_Merge(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+ gceSTATUS status;
+
+ /* Save pointer to next node. */
+ node = Node->VidMem.next;
+
+ /* This is a good time to make sure the heap is not corrupted. */
+ if (Node->VidMem.offset + Node->VidMem.bytes != node->VidMem.offset)
+ {
+ /* Corrupted heap. */
+ gcmkASSERT(
+ Node->VidMem.offset + Node->VidMem.bytes == node->VidMem.offset);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+ /* Adjust byte count. */
+ Node->VidMem.bytes += node->VidMem.bytes;
+
+ /* Unlink next node from linked list. */
+ Node->VidMem.next = node->VidMem.next;
+ Node->VidMem.nextFree = node->VidMem.nextFree;
+
+ Node->VidMem.next->VidMem.prev =
+ Node->VidMem.nextFree->VidMem.prevFree = Node;
+
+ /* Free next node. */
+ status = gcmkOS_SAFE_FREE(Os, node);
+ return status;
+}
+
+/******************************************************************************\
+******************************* gckVIDMEM API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVIDMEM_ConstructVirtual
+**
+** Construct a new gcuVIDMEM_NODE union for virtual memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSIZE_T Bytes
+** Number of byte to allocate.
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that receives the gcuVIDMEM_NODE union pointer.
+*/
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Flag,
+ IN gctSIZE_T Bytes,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctPOINTER pointer = gcvNULL;
+ gctINT i;
+
+ gcmkHEADER_ARG("Kernel=0x%x Flag=%x Bytes=%lu", Kernel, Flag, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate an gcuVIDMEM_NODE union. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
+
+ node = pointer;
+
+ /* Initialize gcuVIDMEM_NODE union for virtual memory. */
+ node->Virtual.kernel = Kernel;
+ node->Virtual.contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
+ node->Virtual.logical = gcvNULL;
+#if gcdENABLE_VG
+ node->Virtual.kernelVirtual = gcvNULL;
+#endif
+ node->Virtual.secure = (Flag & gcvALLOC_FLAG_SECURITY) != 0;
+ node->Virtual.onFault = (Flag & gcvALLOC_FLAG_ALLOC_ON_FAULT) != 0;
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ node->Virtual.lockeds[i] = 0;
+ node->Virtual.pageTables[i] = gcvNULL;
+ }
+
+ /* Allocate the virtual memory. */
+ gcmkONERROR(
+ gckOS_AllocatePagedMemoryEx(os,
+ Flag,
+ node->Virtual.bytes = Bytes,
+ &node->Virtual.gid,
+ &node->Virtual.physical));
+
+ if (node->Virtual.onFault == gcvTRUE)
+ {
+ gcsLIST_Add(&node->Virtual.head, &Kernel->db->onFaultVidmemList);
+ }
+
+ /* Return pointer to the gcuVIDMEM_NODE union. */
+ *Node = node;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Created virtual node 0x%x for %u bytes @ 0x%x",
+ node, Bytes, node->Virtual.physical);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (node != gcvNULL)
+ {
+ /* Free the structure. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_DestroyVirtual
+**
+** Destroy an gcuVIDMEM_NODE union for virtual memory.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gckOS os;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+ /* Extact the gckOS object pointer. */
+ os = Node->Virtual.kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ if (Node->Virtual.onFault == gcvTRUE)
+ {
+ gcsLIST_Del(&Node->Virtual.head);
+ }
+
+ /* Delete the gcuVIDMEM_NODE union. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, Node));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Construct
+**
+** Construct a new gckVIDMEM object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 BaseAddress
+** Base address for the video memory heap.
+**
+** gctSIZE_T Bytes
+** Number of bytes in the video memory heap.
+**
+** gctSIZE_T Threshold
+** Minimum number of bytes beyond am allocation before the node is
+** split. Can be used as a minimum alignment requirement.
+**
+** gctSIZE_T BankSize
+** Number of bytes per physical memory bank. Used by bank
+** optimization.
+**
+** OUTPUT:
+**
+** gckVIDMEM * Memory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object.
+*/
+gceSTATUS
+gckVIDMEM_Construct(
+ IN gckOS Os,
+ IN gctUINT32 BaseAddress,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Threshold,
+ IN gctSIZE_T BankSize,
+ OUT gckVIDMEM * Memory
+ )
+{
+ gckVIDMEM memory = gcvNULL;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node;
+ gctINT i, banks = 0;
+ gctPOINTER pointer = gcvNULL;
+ gctUINT32 heapBytes;
+ gctUINT32 bankSize;
+
+ gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
+ "BankSize=%lu",
+ Os, BaseAddress, Bytes, Threshold, BankSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ gcmkSAFECASTSIZET(heapBytes, Bytes);
+ gcmkSAFECASTSIZET(bankSize, BankSize);
+
+ /* Allocate the gckVIDMEM object. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct _gckVIDMEM), &pointer));
+
+ memory = pointer;
+
+ /* Initialize the gckVIDMEM object. */
+ memory->object.type = gcvOBJ_VIDMEM;
+ memory->os = Os;
+
+ /* Set video memory heap information. */
+ memory->baseAddress = BaseAddress;
+ memory->bytes = heapBytes;
+ memory->freeBytes = heapBytes;
+ memory->threshold = Threshold;
+ memory->mutex = gcvNULL;
+
+ BaseAddress = 0;
+
+ /* Walk all possible banks. */
+ for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
+ {
+ gctUINT32 bytes;
+
+ if (BankSize == 0)
+ {
+ /* Use all bytes for the first bank. */
+ bytes = heapBytes;
+ }
+ else
+ {
+ /* Compute number of bytes for this bank. */
+ bytes = gcmALIGN(BaseAddress + 1, bankSize) - BaseAddress;
+
+ if (bytes > heapBytes)
+ {
+ /* Make sure we don't exceed the total number of bytes. */
+ bytes = heapBytes;
+ }
+ }
+
+ if (bytes == 0)
+ {
+ /* Mark heap is not used. */
+ memory->sentinel[i].VidMem.next =
+ memory->sentinel[i].VidMem.prev =
+ memory->sentinel[i].VidMem.nextFree =
+ memory->sentinel[i].VidMem.prevFree = gcvNULL;
+ continue;
+ }
+
+ /* Allocate one gcuVIDMEM_NODE union. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
+
+ node = pointer;
+
+ /* Initialize gcuVIDMEM_NODE union. */
+ node->VidMem.memory = memory;
+
+ node->VidMem.next =
+ node->VidMem.prev =
+ node->VidMem.nextFree =
+ node->VidMem.prevFree = &memory->sentinel[i];
+
+ node->VidMem.offset = BaseAddress;
+ node->VidMem.bytes = bytes;
+ node->VidMem.alignment = 0;
+ node->VidMem.physical = 0;
+ node->VidMem.pool = gcvPOOL_UNKNOWN;
+
+ node->VidMem.locked = 0;
+
+#ifdef __QNXNTO__
+ node->VidMem.processID = 0;
+ node->VidMem.logical = gcvNULL;
+#endif
+
+#if gcdENABLE_VG
+ node->VidMem.kernelVirtual = gcvNULL;
+#endif
+
+ /* Initialize the linked list of nodes. */
+ memory->sentinel[i].VidMem.next =
+ memory->sentinel[i].VidMem.prev =
+ memory->sentinel[i].VidMem.nextFree =
+ memory->sentinel[i].VidMem.prevFree = node;
+
+ /* Mark sentinel. */
+ memory->sentinel[i].VidMem.bytes = 0;
+
+ /* Adjust address for next bank. */
+ BaseAddress += bytes;
+ heapBytes -= bytes;
+ banks ++;
+ }
+
+ /* Assign all the bank mappings. */
+ memory->mapping[gcvSURF_RENDER_TARGET] = banks - 1;
+ memory->mapping[gcvSURF_BITMAP] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_DEPTH] = banks - 1;
+ memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TEXTURE] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_VERTEX] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_INDEX] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TILE_STATUS] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TYPE_UNKNOWN] = 0;
+
+#if gcdENABLE_VG
+ memory->mapping[gcvSURF_IMAGE] = 0;
+ memory->mapping[gcvSURF_MASK] = 0;
+ memory->mapping[gcvSURF_SCISSOR] = 0;
+#endif
+ memory->mapping[gcvSURF_ICACHE] = 0;
+ memory->mapping[gcvSURF_TXDESC] = 0;
+ memory->mapping[gcvSURF_FENCE] = 0;
+ memory->mapping[gcvSURF_TFBHEADER] = 0;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] INDEX: bank %d",
+ memory->mapping[gcvSURF_INDEX]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] VERTEX: bank %d",
+ memory->mapping[gcvSURF_VERTEX]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] TEXTURE: bank %d",
+ memory->mapping[gcvSURF_TEXTURE]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] RENDER_TARGET: bank %d",
+ memory->mapping[gcvSURF_RENDER_TARGET]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] DEPTH: bank %d",
+ memory->mapping[gcvSURF_DEPTH]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] TILE_STATUS: bank %d",
+ memory->mapping[gcvSURF_TILE_STATUS]);
+
+ /* Allocate the mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));
+
+ /* Return pointer to the gckVIDMEM object. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (memory != gcvNULL)
+ {
+ if (memory->mutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
+ }
+
+ for (i = 0; i < banks; ++i)
+ {
+ /* Free the heap. */
+ gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory->sentinel[i].VidMem.next));
+ }
+
+ /* Free the object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Destroy
+**
+** Destroy an gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Destroy(
+ IN gckVIDMEM Memory
+ )
+{
+ gcuVIDMEM_NODE_PTR node, next;
+ gctINT i;
+
+ gcmkHEADER_ARG("Memory=0x%x", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+
+ /* Walk all sentinels. */
+ for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ /* Bail out of the heap is not used. */
+ if (Memory->sentinel[i].VidMem.next == gcvNULL)
+ {
+ break;
+ }
+
+ /* Walk all the nodes until we reach the sentinel. */
+ for (node = Memory->sentinel[i].VidMem.next;
+ node->VidMem.bytes != 0;
+ node = next)
+ {
+ /* Save pointer to the next node. */
+ next = node->VidMem.next;
+
+ /* Free the node. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, node));
+ }
+ }
+
+ /* Free the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Memory->os, Memory->mutex));
+
+ /* Mark the object as unknown. */
+ Memory->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVIDMEM object. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, Memory));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdENABLE_BANK_ALIGNMENT
+
+#if !gcdBANK_BIT_START
+#error gcdBANK_BIT_START not defined.
+#endif
+
+#if !gcdBANK_BIT_END
+#error gcdBANK_BIT_END not defined.
+#endif
+/*******************************************************************************
+** _GetSurfaceBankAlignment
+**
+** Return the required offset alignment required to the make BaseAddress
+** aligned properly.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gcoOS object.
+**
+** gceSURF_TYPE Type
+** Type of allocation.
+**
+** gctUINT32 BaseAddress
+** Base address of current video memory node.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR AlignmentOffset
+** Pointer to a variable that will hold the number of bytes to skip in
+** the current video memory node in order to make the alignment bank
+** aligned.
+*/
+static gceSTATUS
+_GetSurfaceBankAlignment(
+ IN gckKERNEL Kernel,
+ IN gceSURF_TYPE Type,
+ IN gctUINT32 BaseAddress,
+ OUT gctUINT32_PTR AlignmentOffset
+ )
+{
+ gctUINT32 bank;
+ /* To retrieve the bank. */
+ static const gctUINT32 bankMask = (0xFFFFFFFF << gcdBANK_BIT_START)
+ ^ (0xFFFFFFFF << (gcdBANK_BIT_END + 1));
+
+ /* To retrieve the bank and all the lower bytes. */
+ static const gctUINT32 byteMask = ~(0xFFFFFFFF << (gcdBANK_BIT_END + 1));
+
+ gcmkHEADER_ARG("Type=%d BaseAddress=0x%x ", Type, BaseAddress);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(AlignmentOffset != gcvNULL);
+
+ switch (Type)
+ {
+ case gcvSURF_RENDER_TARGET:
+ bank = (BaseAddress & bankMask) >> (gcdBANK_BIT_START);
+
+ /* Align to the first bank. */
+ *AlignmentOffset = (bank == 0) ?
+ 0 :
+ ((1 << (gcdBANK_BIT_END + 1)) + 0) - (BaseAddress & byteMask);
+ break;
+
+ case gcvSURF_DEPTH:
+ bank = (BaseAddress & bankMask) >> (gcdBANK_BIT_START);
+
+ /* Align to the third bank. */
+ *AlignmentOffset = (bank == 2) ?
+ 0 :
+ ((1 << (gcdBANK_BIT_END + 1)) + (2 << gcdBANK_BIT_START)) - (BaseAddress & byteMask);
+
+ /* Minimum 256 byte alignment needed for fast_msaa. */
+ if ((gcdBANK_CHANNEL_BIT > 7) ||
+ ((gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_FAST_MSAA) != gcvSTATUS_TRUE) &&
+ (gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_SMALL_MSAA) != gcvSTATUS_TRUE)))
+ {
+ /* Add a channel offset at the channel bit. */
+ *AlignmentOffset += (1 << gcdBANK_CHANNEL_BIT);
+ }
+ break;
+
+ default:
+ /* no alignment needed. */
+ *AlignmentOffset = 0;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER_ARG("*AlignmentOffset=%u", *AlignmentOffset);
+ return gcvSTATUS_OK;
+}
+#endif
+
+static gcuVIDMEM_NODE_PTR
+_FindNode(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM Memory,
+ IN gctINT Bank,
+ IN gctSIZE_T Bytes,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Alignment
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 alignment;
+
+#if gcdENABLE_BANK_ALIGNMENT
+ gctUINT32 bankAlignment;
+ gceSTATUS status;
+#endif
+
+ if (Memory->sentinel[Bank].VidMem.nextFree == gcvNULL)
+ {
+ /* No free nodes left. */
+ return gcvNULL;
+ }
+
+#if gcdENABLE_BANK_ALIGNMENT
+ /* Walk all free nodes until we have one that is big enough or we have
+ ** reached the sentinel. */
+ for (node = Memory->sentinel[Bank].VidMem.nextFree;
+ node->VidMem.bytes != 0;
+ node = node->VidMem.nextFree)
+ {
+ if (node->VidMem.bytes < Bytes)
+ {
+ continue;
+ }
+
+ gcmkONERROR(_GetSurfaceBankAlignment(
+ Kernel,
+ Type,
+ node->VidMem.memory->baseAddress + node->VidMem.offset,
+ &bankAlignment));
+
+ bankAlignment = gcmALIGN(bankAlignment, *Alignment);
+
+ /* Compute number of bytes to skip for alignment. */
+ alignment = (*Alignment == 0)
+ ? 0
+ : (*Alignment - (node->VidMem.offset % *Alignment));
+
+ if (alignment == *Alignment)
+ {
+ /* Node is already aligned. */
+ alignment = 0;
+ }
+
+ if (node->VidMem.bytes >= Bytes + alignment + bankAlignment)
+ {
+ /* This node is big enough. */
+ *Alignment = alignment + bankAlignment;
+ return node;
+ }
+ }
+#endif
+
+ /* Walk all free nodes until we have one that is big enough or we have
+ reached the sentinel. */
+ for (node = Memory->sentinel[Bank].VidMem.nextFree;
+ node->VidMem.bytes != 0;
+ node = node->VidMem.nextFree)
+ {
+ gctUINT offset;
+
+ gctINT modulo;
+
+ gcmkSAFECASTSIZET(offset, node->VidMem.offset);
+
+ modulo = gckMATH_ModuloInt(offset, *Alignment);
+
+ /* Compute number of bytes to skip for alignment. */
+ alignment = (*Alignment == 0) ? 0 : (*Alignment - modulo);
+
+ if (alignment == *Alignment)
+ {
+ /* Node is already aligned. */
+ alignment = 0;
+ }
+
+ if (node->VidMem.bytes >= Bytes + alignment)
+ {
+ /* This node is big enough. */
+ *Alignment = alignment;
+ return node;
+ }
+ }
+
+#if gcdENABLE_BANK_ALIGNMENT
+OnError:
+#endif
+ /* Not enough memory. */
+ return gcvNULL;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_AllocateLinear
+**
+** Allocate linear memory from the gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** gctUINT32 Alignment
+** Byte alignment for allocation.
+**
+** gceSURF_TYPE Type
+** Type of surface to allocate (use by bank optimization).
+**
+** gctBOOL Specified
+** If user must use this pool, it should set Specified to gcvTRUE,
+** otherwise allocator may reserve some memory for other usage, such
+** as small block size allocation request.
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that will hold the allocated memory node.
+*/
+gceSTATUS
+gckVIDMEM_AllocateLinear(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM Memory,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+ IN gctBOOL Specified,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 alignment;
+ gctINT bank, i;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Memory=0x%x Bytes=%lu Alignment=%u Type=%d",
+ Memory, Bytes, Alignment, Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Type < gcvSURF_NUM_TYPES);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+#if defined(__QNXNTO__)
+ if (slogUsageInterval > 0) {
+ static gctSIZE_T lowwaterFPC = ~0;
+ static time_t last_slog_time;
+ int do_slog_now = 0;
+ time_t this_slog_time = time(NULL);
+
+ if (Memory->freeBytes < lowwaterFPC) {
+ do_slog_now = 1;
+ lowwaterFPC = Memory->freeBytes;
+ }
+
+ if (abs(this_slog_time - last_slog_time) > slogUsageInterval) {
+ do_slog_now = 1;
+ }
+
+ if (do_slog_now) {
+ last_slog_time = this_slog_time;
+ slogf(_SLOGC_GRAPHICS_GL, _SLOG_INFO, "%s: Memory->freeBytes = %u, lowest Memory->freeBytes = %u",
+ __FUNCTION__, (unsigned) Memory->freeBytes, (unsigned) lowwaterFPC);
+ }
+ }
+#endif
+ if (Bytes > Memory->freeBytes)
+ {
+ /* Not enough memory. */
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+#if gcdSMALL_BLOCK_SIZE
+ if ((Memory->freeBytes < (Memory->bytes/gcdRATIO_FOR_SMALL_MEMORY))
+ && (Bytes >= gcdSMALL_BLOCK_SIZE)
+ && (Specified == gcvFALSE)
+ )
+ {
+ /* The left memory is for small memory.*/
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+#endif
+
+ /* Find the default bank for this surface type. */
+ gcmkASSERT((gctINT) Type < gcmCOUNTOF(Memory->mapping));
+ bank = Memory->mapping[Type];
+ alignment = Alignment;
+
+ /* Find a free node in the default bank. */
+ node = _FindNode(Kernel, Memory, bank, Bytes, Type, &alignment);
+
+ /* Out of memory? */
+ if (node == gcvNULL)
+ {
+ /* Walk all lower banks. */
+ for (i = bank - 1; i >= 0; --i)
+ {
+ /* Find a free node inside the current bank. */
+ node = _FindNode(Kernel, Memory, i, Bytes, Type, &alignment);
+ if (node != gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ /* Walk all upper banks. */
+ for (i = bank + 1; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ if (Memory->sentinel[i].VidMem.nextFree == gcvNULL)
+ {
+ /* Abort when we reach unused banks. */
+ break;
+ }
+
+ /* Find a free node inside the current bank. */
+ node = _FindNode(Kernel, Memory, i, Bytes, Type, &alignment);
+ if (node != gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ /* Out of memory. */
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+ /* Do we have an alignment? */
+ if (alignment > 0)
+ {
+ /* Split the node so it is aligned. */
+ if (_Split(Memory->os, node, alignment))
+ {
+ /* Successful split, move to aligned node. */
+ node = node->VidMem.next;
+
+ /* Remove alignment. */
+ alignment = 0;
+ }
+ }
+
+ /* Do we have enough memory after the allocation to split it? */
+ if (node->VidMem.bytes - Bytes > Memory->threshold)
+ {
+ /* Adjust the node size. */
+ _Split(Memory->os, node, Bytes);
+ }
+
+ /* Remove the node from the free list. */
+ node->VidMem.prevFree->VidMem.nextFree = node->VidMem.nextFree;
+ node->VidMem.nextFree->VidMem.prevFree = node->VidMem.prevFree;
+ node->VidMem.nextFree =
+ node->VidMem.prevFree = gcvNULL;
+
+ /* Fill in the information. */
+ node->VidMem.alignment = alignment;
+ node->VidMem.memory = Memory;
+#ifdef __QNXNTO__
+ node->VidMem.logical = gcvNULL;
+ gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
+#endif
+
+ /* Adjust the number of free bytes. */
+ Memory->freeBytes -= node->VidMem.bytes;
+
+#if gcdENABLE_VG
+ node->VidMem.kernelVirtual = gcvNULL;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+
+ /* Return the pointer to the node. */
+ *Node = node;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Allocated %u bytes @ 0x%x [0x%08X]",
+ node->VidMem.bytes, node, node->VidMem.offset);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Free
+**
+** Free an allocated video memory node.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Free(
+ IN gckKERNEL Kernel,
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gceSTATUS status;
+ gckKERNEL kernel = gcvNULL;
+ gckVIDMEM memory = gcvNULL;
+ gcuVIDMEM_NODE_PTR node;
+ gctBOOL mutexAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ if ((Node == gcvNULL)
+ || (Node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /**************************** Video Memory ********************************/
+
+ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ /* Extract pointer to gckVIDMEM object owning the node. */
+ memory = Node->VidMem.memory;
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
+
+ mutexAcquired = gcvTRUE;
+
+#ifdef __QNXNTO__
+ /* Unmap the video memory. */
+ if (Node->VidMem.logical != gcvNULL)
+ {
+ gckKERNEL_UnmapVideoMemory(
+ Kernel,
+ Node->VidMem.logical,
+ Node->VidMem.processID,
+ Node->VidMem.bytes);
+ Node->VidMem.logical = gcvNULL;
+ }
+
+ /* Reset. */
+ Node->VidMem.processID = 0;
+
+ /* Don't try to re-free an already freed node. */
+ if ((Node->VidMem.nextFree == gcvNULL)
+ && (Node->VidMem.prevFree == gcvNULL)
+ )
+#endif
+ {
+#if gcdENABLE_VG
+ if (Node->VidMem.kernelVirtual)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "%s(%d) Unmap %x from kernel space.",
+ __FUNCTION__, __LINE__,
+ Node->VidMem.kernelVirtual);
+
+ gcmkVERIFY_OK(
+ gckOS_UnmapPhysical(memory->os,
+ Node->VidMem.kernelVirtual,
+ Node->VidMem.bytes));
+
+ Node->VidMem.kernelVirtual = gcvNULL;
+ }
+#endif
+
+ /* Check if Node is already freed. */
+ if (Node->VidMem.nextFree)
+ {
+ /* Node is alread freed. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ /* Update the number of free bytes. */
+ memory->freeBytes += Node->VidMem.bytes;
+
+ /* Find the next free node. */
+ for (node = Node->VidMem.next;
+ node != gcvNULL && node->VidMem.nextFree == gcvNULL;
+ node = node->VidMem.next) ;
+
+ /* Insert this node in the free list. */
+ Node->VidMem.nextFree = node;
+ Node->VidMem.prevFree = node->VidMem.prevFree;
+
+ Node->VidMem.prevFree->VidMem.nextFree =
+ node->VidMem.prevFree = Node;
+
+ /* Is the next node a free node and not the sentinel? */
+ if ((Node->VidMem.next == Node->VidMem.nextFree)
+ && (Node->VidMem.next->VidMem.bytes != 0)
+ )
+ {
+ /* Merge this node with the next node. */
+ gcmkONERROR(_Merge(memory->os, node = Node));
+ gcmkASSERT(node->VidMem.nextFree != node);
+ gcmkASSERT(node->VidMem.prevFree != node);
+ }
+
+ /* Is the previous node a free node and not the sentinel? */
+ if ((Node->VidMem.prev == Node->VidMem.prevFree)
+ && (Node->VidMem.prev->VidMem.bytes != 0)
+ )
+ {
+ /* Merge this node with the previous node. */
+ gcmkONERROR(_Merge(memory->os, node = Node->VidMem.prev));
+ gcmkASSERT(node->VidMem.nextFree != node);
+ gcmkASSERT(node->VidMem.prevFree != node);
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Node 0x%x is freed.",
+ Node);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ /* Get gckKERNEL object. */
+ kernel = Node->Virtual.kernel;
+
+ /* Verify the gckKERNEL object pointer. */
+ gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
+
+#if gcdENABLE_VG
+ if (Node->Virtual.kernelVirtual)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "%s(%d) Unmap %x from kernel space.",
+ __FUNCTION__, __LINE__,
+ Node->Virtual.kernelVirtual);
+
+ gcmkVERIFY_OK(
+ gckOS_UnmapPhysical(kernel->os,
+ Node->Virtual.kernelVirtual,
+ Node->Virtual.bytes));
+
+ Node->Virtual.kernelVirtual = gcvNULL;
+ }
+#endif
+
+ /* Free the virtual memory. */
+ gcmkVERIFY_OK(gckOS_FreePagedMemory(kernel->os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes));
+
+ /* Destroy the gcuVIDMEM_NODE union. */
+ gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutexAcquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(
+ memory->os, memory->mutex
+ ));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if !gcdPROCESS_ADDRESS_SPACE
+/*******************************************************************************
+**
+** _NeedVirtualMapping
+**
+** Whether setup GPU page table for video node.
+**
+** INPUT:
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** gceCORE Core
+** Id of current GPU.
+**
+** OUTPUT:
+** gctBOOL * NeedMapping
+** A pointer hold the result whether Node should be mapping.
+*/
+static gceSTATUS
+_NeedVirtualMapping(
+ IN gckKERNEL Kernel,
+ IN gceCORE Core,
+ IN gcuVIDMEM_NODE_PTR Node,
+ OUT gctBOOL * NeedMapping
+)
+{
+ gceSTATUS status;
+ gctPHYS_ADDR_T phys;
+ gctUINT32 address;
+ gctUINT32 end;
+ gcePOOL pool;
+ gctUINT32 offset;
+ gctUINT32 bytes;
+
+ gcmkHEADER_ARG("Node=0x%X", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+ gcmkVERIFY_ARGUMENT(NeedMapping != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Core < gcdMAX_GPU_COUNT);
+
+ if (Node->Virtual.contiguous)
+ {
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ *NeedMapping = gcvFALSE;
+ }
+ else
+#endif
+ if (Node->Virtual.secure)
+ {
+ *NeedMapping = gcvTRUE;
+ }
+ else
+ {
+ /* Convert logical address into a physical address. */
+ gcmkONERROR(gckOS_UserLogicalToPhysical(
+ Kernel->os, Node->Virtual.logical, &phys
+ ));
+
+ if (phys > gcvMAXUINT32)
+ {
+ *NeedMapping = gcvTRUE;
+ }
+ else
+ {
+ gcmkSAFECASTPHYSADDRT(address, phys);
+
+ if (!gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_MMU))
+ {
+ gcmkASSERT(address >= Kernel->hardware->baseAddress);
+
+ /* Subtract baseAddress to get a GPU address used for programming. */
+ address -= Kernel->hardware->baseAddress;
+
+ /* If part of region is belong to gcvPOOL_VIRTUAL,
+ ** whole region has to be mapped. */
+ gcmkSAFECASTSIZET(bytes, Node->Virtual.bytes);
+ end = address + bytes - 1;
+
+ gcmkONERROR(gckHARDWARE_SplitMemory(
+ Kernel->hardware, end, &pool, &offset
+ ));
+
+ *NeedMapping = (pool == gcvPOOL_VIRTUAL);
+ }
+ else
+ {
+ gctBOOL flatMapped;
+
+ gcmkONERROR(gckMMU_IsFlatMapped(Kernel->mmu, address, &flatMapped));
+
+ *NeedMapping = !flatMapped;
+ }
+ }
+ }
+ }
+ else
+ {
+ *NeedMapping = gcvTRUE;
+ }
+
+ gcmkFOOTER_ARG("*NeedMapping=%d", *NeedMapping);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+gcsGPU_MAP_PTR
+_FindGPUMap(
+ IN gcsGPU_MAP_PTR Head,
+ IN gctINT ProcessID
+ )
+{
+ gcsGPU_MAP_PTR map = Head;
+
+ while (map)
+ {
+ if (map->pid == ProcessID)
+ {
+ return map;
+ }
+
+ map = map->next;
+ }
+
+ return gcvNULL;
+}
+
+gcsGPU_MAP_PTR
+_CreateGPUMap(
+ IN gckOS Os,
+ IN gcsGPU_MAP_PTR *Head,
+ IN gcsGPU_MAP_PTR *Tail,
+ IN gctINT ProcessID
+ )
+{
+ gcsGPU_MAP_PTR gpuMap;
+ gctPOINTER pointer = gcvNULL;
+
+ gckOS_Allocate(Os, sizeof(gcsGPU_MAP), &pointer);
+
+ if (pointer == gcvNULL)
+ {
+ return gcvNULL;
+ }
+
+ gpuMap = pointer;
+
+ gckOS_ZeroMemory(pointer, sizeof(gcsGPU_MAP));
+
+ gpuMap->pid = ProcessID;
+
+ if (!*Head)
+ {
+ *Head = *Tail = gpuMap;
+ }
+ else
+ {
+ gpuMap->prev = *Tail;
+ (*Tail)->next = gpuMap;
+ *Tail = gpuMap;
+ }
+
+ return gpuMap;
+}
+
+void
+_DestroyGPUMap(
+ IN gckOS Os,
+ IN gcsGPU_MAP_PTR *Head,
+ IN gcsGPU_MAP_PTR *Tail,
+ IN gcsGPU_MAP_PTR gpuMap
+ )
+{
+
+ if (gpuMap == *Head)
+ {
+ if ((*Head = gpuMap->next) == gcvNULL)
+ {
+ *Tail = gcvNULL;
+ }
+ }
+ else
+ {
+ gpuMap->prev->next = gpuMap->next;
+ if (gpuMap == *Tail)
+ {
+ *Tail = gpuMap->prev;
+ }
+ else
+ {
+ gpuMap->next->prev = gpuMap->prev;
+ }
+ }
+
+ gcmkOS_SAFE_FREE(Os, gpuMap);
+}
+#endif
+
+/*******************************************************************************
+**
+** gckVIDMEM_Lock
+**
+** Lock a video memory node and return its hardware specific address.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable that will hold the hardware specific address.
+**
+** gctUINT32 * PhysicalAddress
+** Pointer to a variable that will hold the bus address of a contiguous
+** video node.
+*/
+gceSTATUS
+gckVIDMEM_Lock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gctBOOL Cacheable,
+ OUT gctUINT32 * Address,
+ OUT gctUINT32 * Gid,
+ OUT gctUINT64 * PhysicalAddress
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL locked = gcvFALSE;
+ gckOS os = gcvNULL;
+#if !gcdPROCESS_ADDRESS_SPACE
+ gctBOOL needMapping = gcvFALSE;
+#endif
+ gctUINT64 physicalAddress;
+ gcuVIDMEM_NODE_PTR node = Node->node;
+ gctPHYS_ADDR_T physical;
+ gctSIZE_T pageSize;
+ gctUINT32 pageMask;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ if ((node == gcvNULL)
+ || (node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Node->mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /**************************** Video Memory ********************************/
+
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ gctUINT32 offset;
+
+ if (Cacheable == gcvTRUE)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+
+ /* Increment the lock count. */
+ node->VidMem.locked ++;
+
+ /* Return the physical address of the node. */
+ gcmkSAFECASTSIZET(offset, node->VidMem.offset);
+
+ *Address = node->VidMem.memory->baseAddress
+ + offset
+ + node->VidMem.alignment;
+
+ physicalAddress = *Address;
+
+ /* Get hardware specific address. */
+#if gcdENABLE_VG
+ if (Kernel->vg == gcvNULL)
+#endif
+ {
+ if (Kernel->hardware->mmuVersion == 0)
+ {
+ /* Convert physical to GPU address for old mmu. */
+ gcmkASSERT(*Address > Kernel->hardware->baseAddress);
+ *Address -= Kernel->hardware->baseAddress;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(
+ Kernel->os,
+ *Address,
+ &physical
+ ));
+
+ gcmkSAFECASTSIZET(*Address, physical);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Locked node 0x%x (%d) @ 0x%08X",
+ node,
+ node->VidMem.locked,
+ *Address);
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ else
+ {
+
+ *Gid = node->Virtual.gid;
+
+#if gcdPAGED_MEMORY_CACHEABLE
+ /* Force video memory cacheable. */
+ Cacheable = gcvTRUE;
+#endif
+
+ gcmkONERROR(
+ gckOS_LockPages(os,
+ node->Virtual.physical,
+ node->Virtual.bytes,
+ Cacheable,
+ &node->Virtual.logical,
+ &node->Virtual.pageCount));
+
+ gcmkONERROR(gckOS_UserLogicalToPhysical(
+ os,
+ node->Virtual.logical,
+ &physicalAddress
+ ));
+
+#if gcdENABLE_VG
+ node->Virtual.physicalAddress = physicalAddress;
+#endif
+
+#if !gcdPROCESS_ADDRESS_SPACE
+ /* Increment the lock count. */
+ if (node->Virtual.lockeds[Kernel->core] ++ == 0)
+ {
+ locked = gcvTRUE;
+
+ gcmkONERROR(_NeedVirtualMapping(Kernel, Kernel->core, node, &needMapping));
+
+ if (needMapping == gcvFALSE)
+ {
+ /* Get hardware specific address. */
+#if gcdENABLE_VG
+ if (Kernel->vg != gcvNULL)
+ {
+ gcmkONERROR(gckVGHARDWARE_ConvertLogical(
+ Kernel->vg->hardware,
+ node->Virtual.logical,
+ gcvTRUE,
+ &node->Virtual.addresses[Kernel->core]));
+ }
+ else
+#endif
+ {
+ gcmkONERROR(gckHARDWARE_ConvertLogical(
+ Kernel->hardware,
+ node->Virtual.logical,
+ gcvTRUE,
+ &node->Virtual.addresses[Kernel->core]));
+ }
+ }
+ else
+ {
+#if gcdSECURITY
+ gctPHYS_ADDR physicalArrayPhysical;
+ gctPOINTER physicalArrayLogical;
+
+ gcmkONERROR(gckOS_AllocatePageArray(
+ os,
+ node->Virtual.physical,
+ node->Virtual.pageCount,
+ &physicalArrayLogical,
+ &physicalArrayPhysical
+ ));
+
+ gcmkONERROR(gckKERNEL_SecurityMapMemory(
+ Kernel,
+ physicalArrayLogical,
+ node->Virtual.pageCount,
+ &node->Virtual.addresses[Kernel->core]
+ ));
+
+ gcmkONERROR(gckOS_FreeNonPagedMemory(
+ os,
+ 1,
+ physicalArrayPhysical,
+ physicalArrayLogical
+ ));
+#else
+#if gcdENABLE_VG
+ if (Kernel->vg != gcvNULL)
+ {
+ /* Allocate pages inside the MMU. */
+ gcmkONERROR(
+ gckVGMMU_AllocatePages(Kernel->vg->mmu,
+ node->Virtual.pageCount,
+ &node->Virtual.pageTables[Kernel->core],
+ &node->Virtual.addresses[Kernel->core]));
+ }
+ else
+#endif
+ {
+ /* Allocate pages inside the MMU. */
+ gcmkONERROR(
+ gckMMU_AllocatePagesEx(Kernel->mmu,
+ node->Virtual.pageCount,
+ node->Virtual.type,
+ node->Virtual.secure,
+ &node->Virtual.pageTables[Kernel->core],
+ &node->Virtual.addresses[Kernel->core]));
+ }
+
+ if (node->Virtual.onFault != gcvTRUE)
+ {
+#if gcdENABLE_TRUST_APPLICATION
+#if gcdENABLE_VG
+ if (Kernel->core != gcvCORE_VG && Kernel->hardware->secureMode == gcvSECURE_IN_TA)
+#else
+ if (Kernel->hardware->secureMode == gcvSECURE_IN_TA)
+#endif
+ {
+ gcmkONERROR(gckKERNEL_MapInTrustApplicaiton(
+ Kernel,
+ node->Virtual.logical,
+ node->Virtual.physical,
+ node->Virtual.addresses[Kernel->core],
+ node->Virtual.pageCount
+ ));
+ }
+ else
+#endif
+ {
+ /* Map the pages. */
+ gcmkONERROR(gckOS_MapPagesEx(os,
+ Kernel->core,
+ node->Virtual.physical,
+ node->Virtual.pageCount,
+ node->Virtual.addresses[Kernel->core],
+ node->Virtual.pageTables[Kernel->core],
+ gcvTRUE,
+ node->Virtual.type));
+ }
+ }
+
+#if gcdENABLE_VG
+ if (Kernel->core == gcvCORE_VG)
+ {
+ gcmkONERROR(gckVGMMU_Flush(Kernel->vg->mmu));
+ }
+ else
+#endif
+ {
+ gcmkONERROR(gckMMU_Flush(Kernel->mmu, node->Virtual.type));
+ }
+#endif
+ }
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Mapped virtual node 0x%x to 0x%08X",
+ node,
+ node->Virtual.addresses[Kernel->core]);
+ }
+
+ /* Return hardware address. */
+ *Address = node->Virtual.addresses[Kernel->core];
+
+ if (needMapping == gcvTRUE)
+ {
+
+#if gcdENABLE_VG
+ if (Kernel->core == gcvCORE_VG)
+ {
+ gcmkVERIFY_OK(gckOS_GetPageSize(os, &pageSize));
+ }
+ else
+#endif
+ {
+ pageSize = Kernel->command->pageSize;
+ }
+
+ pageMask = (gctUINT32)pageSize - 1;
+
+ *Address += (gctUINT32)physicalAddress & pageMask;
+
+ /* Need mark invalid address for virtual memory */
+ if (node->Virtual.contiguous == gcvFALSE)
+ {
+ physicalAddress = gcvINVALID_ADDRESS;
+ }
+ }
+#endif
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+
+ *PhysicalAddress = (gctUINT64)physicalAddress;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (locked)
+ {
+ if (node->Virtual.pageTables[Kernel->core] != gcvNULL)
+ {
+#if gcdENABLE_VG
+ if (Kernel->vg != gcvNULL)
+ {
+ /* Free the pages from the MMU. */
+ gcmkVERIFY_OK(
+ gckVGMMU_FreePages(Kernel->vg->mmu,
+ node->Virtual.pageTables[Kernel->core],
+ node->Virtual.pageCount));
+ }
+ else
+#endif
+ {
+ /* Free the pages from the MMU. */
+ gcmkVERIFY_OK(
+ gckMMU_FreePages(Kernel->mmu,
+ node->Virtual.secure,
+ node->Virtual.addresses[Kernel->core],
+ node->Virtual.pageTables[Kernel->core],
+ node->Virtual.pageCount));
+ }
+ node->Virtual.pageTables[Kernel->core] = gcvNULL;
+ }
+
+ /* Unlock the pages. */
+ gcmkVERIFY_OK(
+ gckOS_UnlockPages(os,
+ node->Virtual.physical,
+ node->Virtual.bytes,
+ node->Virtual.logical
+ ));
+
+ node->Virtual.lockeds[Kernel->core]--;
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Unlock
+**
+** Unlock a video memory node.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a locked gcuVIDMEM_NODE union.
+**
+** gceSURF_TYPE Type
+** Type of surface to unlock.
+**
+** gctBOOL * Asynchroneous
+** Pointer to a variable specifying whether the surface should be
+** unlocked asynchroneously or not.
+**
+** OUTPUT:
+**
+** gctBOOL * Asynchroneous
+** Pointer to a variable receiving the number of bytes used in the
+** command buffer specified by 'Commands'. If gcvNULL, there is no
+** command buffer.
+*/
+gceSTATUS
+gckVIDMEM_Unlock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gceSURF_TYPE Type,
+ IN OUT gctBOOL * Asynchroneous
+ )
+{
+ gceSTATUS status;
+ gckOS os = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+ gcuVIDMEM_NODE_PTR node = Node->node;
+
+ gcmkHEADER_ARG("Node=0x%x Type=%d *Asynchroneous=%d",
+ Node, Type, gcmOPT_VALUE(Asynchroneous));
+
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Get the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Verify the arguments. */
+ if ((node == gcvNULL)
+ || (node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Node->mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /**************************** Video Memory ********************************/
+
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ if (node->VidMem.locked <= 0)
+ {
+ /* The surface was not locked. */
+ status = gcvSTATUS_MEMORY_UNLOCKED;
+ goto OnError;
+ }
+
+ if (Asynchroneous != gcvNULL)
+ {
+ /* Schedule an event to sync with GPU. */
+ *Asynchroneous = gcvTRUE;
+ }
+ else
+ {
+ /* Decrement the lock count. */
+ node->VidMem.locked --;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Unlocked node 0x%x (%d)",
+ node,
+ node->VidMem.locked);
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ else
+ {
+
+
+ if (Asynchroneous == gcvNULL)
+ {
+#if !gcdPROCESS_ADDRESS_SPACE
+ if (node->Virtual.lockeds[Kernel->core] == 0)
+ {
+ status = gcvSTATUS_MEMORY_UNLOCKED;
+ goto OnError;
+ }
+
+ /* Decrement lock count. */
+ -- node->Virtual.lockeds[Kernel->core];
+
+ /* See if we can unlock the resources. */
+ if (node->Virtual.lockeds[Kernel->core] == 0)
+ {
+#if gcdSECURITY
+ if (node->Virtual.addresses[Kernel->core] > 0x80000000)
+ {
+ gcmkONERROR(gckKERNEL_SecurityUnmapMemory(
+ Kernel,
+ node->Virtual.addresses[Kernel->core],
+ node->Virtual.pageCount
+ ));
+ }
+#else
+ /* Free the page table. */
+ if (node->Virtual.pageTables[Kernel->core] != gcvNULL)
+ {
+#if gcdENABLE_VG
+ if (Kernel->vg != gcvNULL)
+ {
+ gcmkONERROR(
+ gckVGMMU_FreePages(Kernel->vg->mmu,
+ node->Virtual.pageTables[Kernel->core],
+ node->Virtual.pageCount));
+ }
+ else
+#endif
+ {
+ gcmkONERROR(
+ gckMMU_FreePages(Kernel->mmu,
+ node->Virtual.secure,
+ node->Virtual.addresses[Kernel->core],
+ node->Virtual.pageTables[Kernel->core],
+ node->Virtual.pageCount));
+ }
+
+ gcmkONERROR(gckOS_UnmapPages(
+ Kernel->os,
+ node->Virtual.pageCount,
+ node->Virtual.addresses[Kernel->core]
+ ));
+
+ /* Mark page table as freed. */
+ node->Virtual.pageTables[Kernel->core] = gcvNULL;
+ }
+#endif
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Unmapped virtual node 0x%x from 0x%08X",
+ node, node->Virtual.addresses[Kernel->core]);
+#endif
+
+ }
+
+ else
+ {
+ gcmkONERROR(
+ gckOS_UnlockPages(os,
+ node->Virtual.physical,
+ node->Virtual.bytes,
+ node->Virtual.logical));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Scheduled unlock for virtual node 0x%x",
+ node);
+
+ /* Schedule the surface to be unlocked. */
+ *Asynchroneous = gcvTRUE;
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdPROCESS_ADDRESS_SPACE
+gceSTATUS
+gckVIDMEM_Node_Lock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ OUT gctUINT32 *Address
+ )
+{
+ gceSTATUS status;
+ gckOS os;
+ gcuVIDMEM_NODE_PTR node = Node->node;
+ gcsGPU_MAP_PTR gpuMap;
+ gctPHYS_ADDR physical = gcvNULL;
+ gctUINT32 phys = gcvINVALID_ADDRESS;
+ gctUINT32 processID;
+ gcsLOCK_INFO_PTR lockInfo;
+ gctUINT32 pageCount;
+ gckMMU mmu;
+ gctUINT32 i;
+ gctUINT32_PTR pageTableEntry;
+ gctUINT32 offset = 0;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Node = %x", Node);
+
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
+
+ gcmkONERROR(gckOS_AcquireMutex(os, Node->mapMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Get map information for current process. */
+ gpuMap = _FindGPUMap(Node->mapHead, processID);
+
+ if (gpuMap == gcvNULL)
+ {
+ gpuMap = _CreateGPUMap(os, &Node->mapHead, &Node->mapTail, processID);
+
+ if (gpuMap == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ }
+
+ lockInfo = &gpuMap->lockInfo;
+
+ if (lockInfo->lockeds[Kernel->core] ++ == 0)
+ {
+ /* Get necessary information. */
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ phys = node->VidMem.memory->baseAddress
+ + node->VidMem.offset
+ + node->VidMem.alignment;
+
+ /* GPU page table use 4K page. */
+ pageCount = ((phys + node->VidMem.bytes + 4096 - 1) >> 12)
+ - (phys >> 12);
+
+ offset = phys & 0xFFF;
+ }
+ else
+ {
+ pageCount = node->Virtual.pageCount;
+ physical = node->Virtual.physical;
+ }
+
+ /* Allocate pages inside the MMU. */
+ gcmkONERROR(gckMMU_AllocatePages(
+ mmu,
+ pageCount,
+ &lockInfo->pageTables[Kernel->core],
+ &lockInfo->GPUAddresses[Kernel->core]));
+
+ /* Record MMU from which pages are allocated. */
+ lockInfo->lockMmus[Kernel->core] = mmu;
+
+ pageTableEntry = lockInfo->pageTables[Kernel->core];
+
+ /* Fill page table entries. */
+ if (phys != gcvINVALID_ADDRESS)
+ {
+ gctUINT32 address = lockInfo->GPUAddresses[Kernel->core];
+ for (i = 0; i < pageCount; i++)
+ {
+ gckMMU_GetPageEntry(mmu, address, &pageTableEntry);
+ gckMMU_SetPage(mmu, phys & 0xFFFFF000, pageTableEntry);
+ phys += 4096;
+ address += 4096;
+ pageTableEntry += 1;
+ }
+ }
+ else
+ {
+ gctUINT32 address = lockInfo->GPUAddresses[Kernel->core];
+ gcmkASSERT(physical != gcvNULL);
+ gcmkONERROR(gckOS_MapPagesEx(os,
+ Kernel->core,
+ physical,
+ pageCount,
+ address,
+ pageTableEntry));
+ }
+
+ gcmkONERROR(gckMMU_Flush(mmu, Node->type));
+ }
+
+ *Address = lockInfo->GPUAddresses[Kernel->core] + offset;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mapMutex));
+ acquired = gcvFALSE;
+
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mapMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_NODE_Unlock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gctUINT32 ProcessID
+ )
+{
+ gceSTATUS status;
+ gcsGPU_MAP_PTR gpuMap;
+ gcsLOCK_INFO_PTR lockInfo;
+ gckMMU mmu;
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 pageCount;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%08X, Node = %x, ProcessID=%d",
+ Kernel, Node, ProcessID);
+
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Node->mapMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Get map information for current process. */
+ gpuMap = _FindGPUMap(Node->mapHead, ProcessID);
+
+ if (gpuMap == gcvNULL)
+ {
+ /* No mapping for this process. */
+ gcmkONERROR(gcvSTATUS_INVALID_DATA);
+ }
+
+ lockInfo = &gpuMap->lockInfo;
+
+ if (--lockInfo->lockeds[Kernel->core] == 0)
+ {
+ node = Node->node;
+
+ /* Get necessary information. */
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ gctUINT32 phys = node->VidMem.memory->baseAddress
+ + node->VidMem.offset
+ + node->VidMem.alignment;
+
+ /* GPU page table use 4K page. */
+ pageCount = ((phys + node->VidMem.bytes + 4096 - 1) >> 12)
+ - (phys >> 12);
+ }
+ else
+ {
+ pageCount = node->Virtual.pageCount;
+ }
+
+ /* Get MMU which allocates pages. */
+ mmu = lockInfo->lockMmus[Kernel->core];
+
+ /* Free virtual spaces in page table. */
+ gcmkVERIFY_OK(gckMMU_FreePagesEx(
+ mmu,
+ lockInfo->GPUAddresses[Kernel->core],
+ pageCount
+ ));
+
+ _DestroyGPUMap(Kernel->os, &Node->mapHead, &Node->mapTail, gpuMap);
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Node->mapMutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Node->mapMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckVIDMEM_HANDLE_Allocate
+**
+** Allocate a handle for a gckVIDMEM_NODE object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gckVIDMEM_NODE Node
+** Pointer to a gckVIDMEM_NODE object.
+**
+** OUTPUT:
+**
+** gctUINT32 * Handle
+** Pointer to a variable receiving a handle represent this
+** gckVIDMEM_NODE in userspace.
+*/
+static gceSTATUS
+gckVIDMEM_HANDLE_Allocate(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ OUT gctUINT32 * Handle
+ )
+{
+ gceSTATUS status;
+ gctUINT32 processID = 0;
+ gctPOINTER pointer = gcvNULL;
+ gctPOINTER handleDatabase = gcvNULL;
+ gctPOINTER mutex = gcvNULL;
+ gctUINT32 handle = 0;
+ gckVIDMEM_HANDLE handleObject = gcvNULL;
+ gckOS os = Kernel->os;
+
+ gcmkHEADER_ARG("Kernel=0x%X, Node=0x%X", Kernel, Node);
+
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate a gckVIDMEM_HANDLE object. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsVIDMEM_HANDLE), &pointer));
+
+ gcmkVERIFY_OK(gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsVIDMEM_HANDLE)));
+
+ handleObject = pointer;
+
+ gcmkONERROR(gckOS_AtomConstruct(os, &handleObject->reference));
+
+ /* Set default reference count to 1. */
+ gckOS_AtomSet(os, handleObject->reference, 1);
+
+ gcmkVERIFY_OK(gckOS_GetProcessID(&processID));
+
+ gcmkONERROR(
+ gckKERNEL_FindHandleDatbase(Kernel,
+ processID,
+ &handleDatabase,
+ &mutex));
+
+ /* Allocate a handle for this object. */
+ gcmkONERROR(
+ gckKERNEL_AllocateIntegerId(handleDatabase, handleObject, &handle));
+
+ handleObject->node = Node;
+ handleObject->handle = handle;
+
+ *Handle = handle;
+
+ gcmkFOOTER_ARG("*Handle=%d", *Handle);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (handleObject != gcvNULL)
+ {
+ if (handleObject->reference != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(os, handleObject->reference));
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, handleObject));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckVIDMEM_NODE_Reference(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node
+ )
+{
+ gctINT32 oldValue;
+ gcmkHEADER_ARG("Kernel=0x%X Node=0x%X", Kernel, Node);
+
+ gckOS_AtomIncrement(Kernel->os, Node->reference, &oldValue);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckVIDMEM_HANDLE_Reference(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_HANDLE handleObject = gcvNULL;
+ gctPOINTER database = gcvNULL;
+ gctPOINTER mutex = gcvNULL;
+ gctINT32 oldValue = 0;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Handle=%d PrcoessID=%d", Handle, ProcessID);
+
+ gcmkONERROR(
+ gckKERNEL_FindHandleDatbase(Kernel, ProcessID, &database, &mutex));
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Translate handle to gckVIDMEM_HANDLE object. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
+
+ /* Increase the reference count. */
+ gckOS_AtomIncrement(Kernel->os, handleObject->reference, &oldValue);
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ acquired = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_HANDLE_Dereference(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle
+ )
+{
+ gceSTATUS status;
+ gctPOINTER handleDatabase = gcvNULL;
+ gctPOINTER mutex = gcvNULL;
+ gctINT32 oldValue = 0;
+ gckVIDMEM_HANDLE handleObject = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Handle=%d PrcoessID=%d", Handle, ProcessID);
+
+ gcmkONERROR(
+ gckKERNEL_FindHandleDatbase(Kernel,
+ ProcessID,
+ &handleDatabase,
+ &mutex));
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Translate handle to gckVIDMEM_HANDLE. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(handleDatabase, Handle, (gctPOINTER *)&handleObject));
+
+ gckOS_AtomDecrement(Kernel->os, handleObject->reference, &oldValue);
+
+ if (oldValue == 1)
+ {
+ /* Remove handle from database if this is the last reference. */
+ gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(handleDatabase, Handle));
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ acquired = gcvFALSE;
+
+ if (oldValue == 1)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, handleObject->reference));
+ gcmkOS_SAFE_FREE(Kernel->os, handleObject);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_HANDLE_LookupAndReference(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Handle,
+ OUT gckVIDMEM_NODE * Node
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_HANDLE handleObject = gcvNULL;
+ gckVIDMEM_NODE node = gcvNULL;
+ gctPOINTER database = gcvNULL;
+ gctPOINTER mutex = gcvNULL;
+ gctUINT32 processID = 0;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
+
+ gckOS_GetProcessID(&processID);
+
+ gcmkONERROR(
+ gckKERNEL_FindHandleDatbase(Kernel, processID, &database, &mutex));
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Translate handle to gckVIDMEM_HANDLE object. */
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
+
+ /* Get gckVIDMEM_NODE object. */
+ node = handleObject->node;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ acquired = gcvFALSE;
+
+ /* Reference this gckVIDMEM_NODE object. */
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Reference(Kernel, node));
+
+ /* Return result. */
+ *Node = node;
+
+ gcmkFOOTER_ARG("*Node=%d", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_HANDLE_Lookup(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle,
+ OUT gckVIDMEM_NODE * Node
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_HANDLE handleObject = gcvNULL;
+ gckVIDMEM_NODE node = gcvNULL;
+ gctPOINTER database = gcvNULL;
+ gctPOINTER mutex = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X ProcessID=%d Handle=%d",
+ Kernel, ProcessID, Handle);
+
+ gcmkONERROR(
+ gckKERNEL_FindHandleDatbase(Kernel, ProcessID, &database, &mutex));
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ gcmkONERROR(
+ gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
+
+ node = handleObject->node;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ acquired = gcvFALSE;
+
+ *Node = node;
+
+ gcmkFOOTER_ARG("*Node=%d", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_NODE_Allocate
+**
+** Allocate a gckVIDMEM_NODE object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** OUTPUT:
+**
+** gctUINT32 * Handle
+** Pointer to a variable receiving a handle represent this
+** gckVIDMEM_NODE in userspace.
+*/
+gceSTATUS
+gckVIDMEM_NODE_Allocate(
+ IN gckKERNEL Kernel,
+ IN gcuVIDMEM_NODE_PTR VideoNode,
+ IN gceSURF_TYPE Type,
+ IN gcePOOL Pool,
+ IN gctUINT32 * Handle
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE node = gcvNULL;
+ gctPOINTER pointer = gcvNULL;
+ gctUINT32 handle = 0;
+ gckOS os = Kernel->os;
+ gctUINT i;
+
+ gcmkHEADER_ARG("Kernel=0x%X VideoNode=0x%X", Kernel, VideoNode);
+
+ /* Construct a node. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsVIDMEM_NODE), &pointer));
+
+ gcmkVERIFY_OK(gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsVIDMEM_NODE)));
+
+ node = pointer;
+
+ node->node = VideoNode;
+ node->type = Type;
+ node->pool = Pool;
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckOS_CreateMutex(os, &node->mapMutex));
+#endif
+
+ gcmkONERROR(gckOS_AtomConstruct(os, &node->reference));
+
+ gcmkONERROR(gckOS_CreateMutex(os, &node->mutex));
+
+ for (i = 0; i < gcvENGINE_COUNT; i++)
+ {
+ gcmkONERROR(gckOS_CreateSignal(os, gcvFALSE, &node->sync[i].signal));
+ }
+
+ /* Reference is 1 by default . */
+ gckVIDMEM_NODE_Reference(Kernel, node);
+
+ /* Create a handle to represent this node. */
+ gcmkONERROR(gckVIDMEM_HANDLE_Allocate(Kernel, node, &handle));
+
+ *Handle = handle;
+
+ gcmkFOOTER_ARG("*Handle=%d", *Handle);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (node != gcvNULL)
+ {
+#if gcdPROCESS_ADDRESS_SPACE
+ if (node->mapMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->mapMutex));
+ }
+#endif
+
+ if (node->mutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->mutex));
+ }
+
+ if (node->reference != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(os, node->reference));
+ }
+
+ for (i = 0; i < gcvENGINE_COUNT; i++)
+ {
+ if (node->sync[i].signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(os, node->sync[i].signal));
+ }
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_NODE_Dereference(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node
+ )
+{
+ gctINT32 oldValue = 0;
+ gctPOINTER database = Kernel->db->nameDatabase;
+ gctPOINTER mutex = Kernel->db->nameDatabaseMutex;
+ gctUINT i;
+
+ gcmkHEADER_ARG("Kernel=0x%X Node=0x%X", Kernel, Node);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+
+ gcmkVERIFY_OK(gckOS_AtomDecrement(Kernel->os, Node->reference, &oldValue));
+
+ if (oldValue == 1 && Node->name)
+ {
+ /* Free name if exists. */
+ gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(database, Node->name));
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+
+ if (oldValue == 1)
+ {
+ /* Free gcuVIDMEM_NODE. */
+ gcmkVERIFY_OK(gckVIDMEM_Free(Kernel, Node->node));
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Node->reference));
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Node->mapMutex));
+#endif
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Node->mutex));
+
+ for (i = 0; i < gcvENGINE_COUNT; i++)
+ {
+ if (Node->sync[i].signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(Kernel->os, Node->sync[i].signal));
+ }
+ }
+
+ gcmkOS_SAFE_FREE(Kernel->os, Node);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_NODE_Name
+**
+** Naming a gckVIDMEM_NODE object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 Handle
+** Handle to a gckVIDMEM_NODE object.
+**
+** OUTPUT:
+**
+** gctUINT32 * Name
+** Pointer to a variable receiving a name which can be pass to another
+** process.
+*/
+gceSTATUS
+gckVIDMEM_NODE_Name(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Handle,
+ IN gctUINT32 * Name
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE node = gcvNULL;
+ gctUINT32 name = 0;
+ gctUINT32 processID = 0;
+ gctPOINTER database = Kernel->db->nameDatabase;
+ gctPOINTER mutex = Kernel->db->nameDatabaseMutex;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL referenced = gcvFALSE;
+ gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
+
+ gcmkVERIFY_ARGUMENT(Name != gcvNULL);
+
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
+ referenced = gcvTRUE;
+
+ if (node->name == 0)
+ {
+ /* Name this node. */
+ gcmkONERROR(gckKERNEL_AllocateIntegerId(database, node, &name));
+ node->name = name;
+ }
+ else
+ {
+ name = node->name;
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ acquired = gcvFALSE;
+
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
+
+ *Name = name;
+
+ gcmkFOOTER_ARG("*Name=%d", *Name);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (referenced)
+ {
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
+ }
+
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_NODE_Import
+**
+** Import a gckVIDMEM_NODE object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 Name
+** Name of a gckVIDMEM_NODE object.
+**
+** OUTPUT:
+**
+** gctUINT32 * Handle
+** Pointer to a variable receiving a handle represent this
+** gckVIDMEM_NODE in userspace.
+*/
+gceSTATUS
+gckVIDMEM_NODE_Import(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Name,
+ IN gctUINT32 * Handle
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE node = gcvNULL;
+ gctPOINTER database = Kernel->db->nameDatabase;
+ gctPOINTER mutex = Kernel->db->nameDatabaseMutex;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL referenced = gcvFALSE;
+
+ gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
+
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Lookup in database to get the node. */
+ gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, (gctPOINTER *)&node));
+
+ /* Reference the node. */
+ gcmkONERROR(gckVIDMEM_NODE_Reference(Kernel, node));
+ referenced = gcvTRUE;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ acquired = gcvFALSE;
+
+ /* Allocate a handle for current process. */
+ gcmkONERROR(gckVIDMEM_HANDLE_Allocate(Kernel, node, Handle));
+
+ gcmkFOOTER_ARG("*Handle=%d", *Handle);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (referenced)
+ {
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
+ }
+
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+
+typedef struct _gcsVIDMEM_NODE_FDPRIVATE
+{
+ gcsFDPRIVATE base;
+ gckKERNEL kernel;
+ gckVIDMEM_NODE node;
+}
+gcsVIDMEM_NODE_FDPRIVATE;
+
+
+static gctINT
+_ReleaseFdPrivate(
+ gcsFDPRIVATE_PTR FdPrivate
+ )
+{
+ /* Cast private info. */
+ gcsVIDMEM_NODE_FDPRIVATE * private = (gcsVIDMEM_NODE_FDPRIVATE *) FdPrivate;
+
+ gckVIDMEM_NODE_Dereference(private->kernel, private->node);
+ gckOS_Free(private->kernel->os, private);
+
+ return 0;
+}
+
+
+/*******************************************************************************
+**
+** gckVIDMEM_NODE_GetFd
+**
+** Attach a gckVIDMEM_NODE object to a native fd.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 Handle
+** Handle to a gckVIDMEM_NODE object.
+**
+** OUTPUT:
+**
+** gctUINT32 * Fd
+** Pointer to a variable receiving a native fd from os.
+*/
+gceSTATUS
+gckVIDMEM_NODE_GetFd(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Handle,
+ OUT gctINT * Fd
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE node = gcvNULL;
+ gctBOOL referenced = gcvFALSE;
+ gcsVIDMEM_NODE_FDPRIVATE * fdPrivate = gcvNULL;
+ gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
+
+ /* Query and reference handle. */
+ gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
+ referenced = gcvTRUE;
+
+ /* Allocated fd owns a reference. */
+ gcmkONERROR(gckOS_Allocate(
+ Kernel->os,
+ gcmSIZEOF(gcsVIDMEM_NODE_FDPRIVATE),
+ (gctPOINTER *)&fdPrivate
+ ));
+
+ fdPrivate->base.release = _ReleaseFdPrivate;
+ fdPrivate->kernel = Kernel;
+ fdPrivate->node = node;
+
+ /* Allocated fd owns a reference. */
+ gcmkONERROR(gckOS_GetFd("vidmem", &fdPrivate->base, Fd));
+
+ gcmkFOOTER_ARG("*Fd=%d", *Fd);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (referenced)
+ {
+ gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
+ }
+
+ if (fdPrivate)
+ {
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, fdPrivate));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_ConstructVirtualFromUserMemory(
+ IN gckKERNEL Kernel,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+ gctPOINTER pointer = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate an gcuVIDMEM_NODE union. */
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
+
+ gckOS_ZeroMemory(pointer, gcmSIZEOF(gcuVIDMEM_NODE));
+
+ node = pointer;
+
+ /* Initialize gcuVIDMEM_NODE union for virtual memory. */
+ node->Virtual.kernel = Kernel;
+
+ /* Wrap Memory. */
+ gcmkONERROR(gckOS_WrapMemory(
+ os, Desc, &node->Virtual.bytes, &node->Virtual.physical, &node->Virtual.contiguous));
+
+ /* Return pointer to the gcuVIDMEM_NODE union. */
+ *Node = node;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (node != gcvNULL)
+ {
+ /* Free the structure. */
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_SetCommitStamp(
+ IN gckKERNEL Kernel,
+ IN gceENGINE Engine,
+ IN gctUINT32 Handle,
+ IN gctUINT64 CommitStamp
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE node;
+ gctUINT32 processID;
+
+ gckOS_GetProcessID(&processID);
+
+ gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
+
+ node->sync[Engine].commitStamp = CommitStamp;
+
+ gckVIDMEM_NODE_Dereference(Kernel, node);
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_GetCommitStamp(
+ IN gckKERNEL Kernel,
+ IN gceENGINE Engine,
+ IN gctUINT32 Handle,
+ OUT gctUINT64_PTR CommitStamp
+ )
+{
+ gceSTATUS status;
+ gckVIDMEM_NODE node;
+ gctUINT32 processID;
+
+ gckOS_GetProcessID(&processID);
+
+ gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
+
+ *CommitStamp = node->sync[Engine].commitStamp;
+
+ gckVIDMEM_NODE_Dereference(Kernel, node);
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gckVIDMEM_FindVIDMEM(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 HardwareAddress,
+ OUT gcuVIDMEM_NODE_PTR * Node,
+ OUT gctUINT32_PTR PageTableEntryValue
+ )
+{
+ gceSTATUS status = gcvSTATUS_NOT_FOUND;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+
+ gcsLISTHEAD_PTR pos;
+
+ gcmkLIST_FOR_EACH(pos, &Kernel->db->onFaultVidmemList)
+ {
+ node = (gcuVIDMEM_NODE_PTR)gcmCONTAINEROF(pos, _gcsVIDMEM_NODE_VIRTUAL, head);
+
+ if (HardwareAddress >= node->Virtual.addresses[Kernel->core]
+ && (HardwareAddress <= node->Virtual.addresses[Kernel->core] - 1 + node->Virtual.bytes)
+ )
+ {
+ *Node = node;
+ status = gcvSTATUS_OK;
+ break;
+ }
+ }
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Setup map for fault address. */
+ gctUINT32 offset = HardwareAddress - node->Virtual.addresses[Kernel->core];
+ gctPHYS_ADDR_T physicalAddress;
+
+ offset &= ~gcdMMU_PAGE_4K_MASK;
+
+ gckOS_PhysicalToPhysicalAddress(Kernel->os, node->Virtual.physical, offset, &physicalAddress);
+
+ gcmkSAFECASTPHYSADDRT(*PageTableEntryValue, physicalAddress);
+ }
+
+ return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_feature_database.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_feature_database.h
new file mode 100644
index 000000000000..29923b0247a2
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_feature_database.h
@@ -0,0 +1,46686 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+/*Auto created on 2017-03-27 17:24*/
+#ifndef _gc_feature_database_h_
+#define _gc_feature_database_h_
+
+typedef struct
+{
+ /* Chip ID. */
+ gctUINT32 chipID;
+ gctUINT32 chipVersion;
+ gctUINT32 productID;
+ gctUINT32 ecoID;
+ gctUINT32 customerID;
+ gctUINT32 patchVersion;
+ gctUINT32 formalRelease;
+ gctUINT32 Streams;
+ gctUINT32 TempRegisters;
+ gctUINT32 ThreadCount;
+ gctUINT32 VertexCacheSize;
+ gctUINT32 NumShaderCores;
+ gctUINT32 NumPixelPipes;
+ gctUINT32 VertexOutputBufferSize;
+ gctUINT32 BufferSize;
+ gctUINT32 InstructionCount;
+ gctUINT32 NumberOfConstants;
+ gctUINT32 CoreCount;
+ gctUINT32 VaryingCount;
+ gctUINT32 LocalStorageSize;
+ gctUINT32 L1CacheSize;
+ gctUINT32 InstructionMemorySize;
+ gctUINT32 ShaderPCLength;
+ gctUINT32 NumResolvePipes;
+ gctUINT32 USC_MAX_PAGES;
+ gctUINT32 RESULT_WINDOW_MAX_SIZE;
+ gctUINT32 NNMadPerCore;
+ gctUINT32 NNCoreCount;
+ gctUINT32 NNInputBufferDepth;
+ gctUINT32 NNAccumBufferDepth;
+ gctUINT32 ClusterAliveMask;
+ gctUINT32 TPEngine_PwlLUTCount;
+ gctUINT32 TPEngine_PwlLUTSize;
+ gctUINT32 REG_FastClear:1;
+ gctUINT32 REG_SpecialAntiAliasing:1;
+ gctUINT32 REG_Pipe3D:1;
+ gctUINT32 REG_DXTTextureCompression:1;
+ gctUINT32 REG_DebugMode:1;
+ gctUINT32 REG_ZCompression:1;
+ gctUINT32 REG_YUV420Filter:1;
+ gctUINT32 REG_MSAA:1;
+ gctUINT32 REG_DC:1;
+ gctUINT32 REG_Pipe2D:1;
+ gctUINT32 REG_ETC1TextureCompression:1;
+ gctUINT32 REG_FastScaler:1;
+ gctUINT32 REG_HighDynamicRange:1;
+ gctUINT32 REG_YUV420Tiler:1;
+ gctUINT32 REG_ModuleCG:1;
+ gctUINT32 REG_MinArea:1;
+ gctUINT32 REG_NoEZ:1;
+ gctUINT32 REG_No422Texture:1;
+ gctUINT32 REG_BufferInterleaving:1;
+ gctUINT32 REG_ByteWrite2D:1;
+ gctUINT32 REG_NoScaler:1;
+ gctUINT32 REG_YUY2Averaging:1;
+ gctUINT32 REG_HalfPECache:1;
+ gctUINT32 REG_HalfTXCache:1;
+ gctUINT32 REG_YUY2RenderTarget:1;
+ gctUINT32 REG_Mem32BitSupport:1;
+ gctUINT32 REG_PipeVG:1;
+ gctUINT32 REG_VGTS:1;
+ gctUINT32 REG_FE20:1;
+ gctUINT32 REG_ByteWrite3D:1;
+ gctUINT32 REG_RsYuvTarget:1;
+ gctUINT32 REG_FE20BitIndex:1;
+ gctUINT32 REG_FlipY:1;
+ gctUINT32 REG_DualReturnBus:1;
+ gctUINT32 REG_EndiannessConfig:1;
+ gctUINT32 REG_Texture8K:1;
+ gctUINT32 REG_CorrectTextureConverter:1;
+ gctUINT32 REG_SpecialMsaaLod:1;
+ gctUINT32 REG_FastClearFlush:1;
+ gctUINT32 REG_2DPE20:1;
+ gctUINT32 REG_CorrectAutoDisable:1;
+ gctUINT32 REG_Render8K:1;
+ gctUINT32 REG_TileStatus2Bits:1;
+ gctUINT32 REG_SeparateTileStatusWhenInterleaved:1;
+ gctUINT32 REG_SuperTiled32x32:1;
+ gctUINT32 REG_VG20:1;
+ gctUINT32 REG_TSExtendedCommands:1;
+ gctUINT32 REG_CompressionFifoFixed:1;
+ gctUINT32 REG_ExtraShaderInstructions0:1;
+ gctUINT32 REG_VGFilter:1;
+ gctUINT32 REG_VG21:1;
+ gctUINT32 REG_ShaderGetsW:1;
+ gctUINT32 REG_ExtraShaderInstructions1:1;
+ gctUINT32 REG_DefaultReg0:1;
+ gctUINT32 REG_MC20:1;
+ gctUINT32 REG_ShaderMSAASideband:1;
+ gctUINT32 REG_BugFixes0:1;
+ gctUINT32 REG_VAA:1;
+ gctUINT32 REG_BypassInMSAA:1;
+ gctUINT32 REG_HierarchicalZ:1;
+ gctUINT32 REG_NewTexture:1;
+ gctUINT32 REG_A8TargetSupport:1;
+ gctUINT32 REG_CorrectStencil:1;
+ gctUINT32 REG_EnhanceVR:1;
+ gctUINT32 REG_RSUVSwizzle:1;
+ gctUINT32 REG_V2Compression:1;
+ gctUINT32 REG_VGDoubleBuffer:1;
+ gctUINT32 REG_BugFixes1:1;
+ gctUINT32 REG_BugFixes2:1;
+ gctUINT32 REG_TextureStride:1;
+ gctUINT32 REG_BugFixes3:1;
+ gctUINT32 REG_CorrectAutoDisable1:1;
+ gctUINT32 REG_AutoRestartTS:1;
+ gctUINT32 REG_BugFixes4:1;
+ gctUINT32 REG_L2Windowing:1;
+ gctUINT32 REG_HalfFloatPipe:1;
+ gctUINT32 REG_PixelDither:1;
+ gctUINT32 REG_TwoStencilReference:1;
+ gctUINT32 REG_ExtendedPixelFormat:1;
+ gctUINT32 REG_CorrectMinMaxDepth:1;
+ gctUINT32 REG_DitherAndFilterPlusAlpha2D:1;
+ gctUINT32 REG_BugFixes5:1;
+ gctUINT32 REG_New2D:1;
+ gctUINT32 REG_NewFloatingPointArithmetic:1;
+ gctUINT32 REG_TextureHorizontalAlignmentSelect:1;
+ gctUINT32 REG_NonPowerOfTwo:1;
+ gctUINT32 REG_LinearTextureSupport:1;
+ gctUINT32 REG_Halti0:1;
+ gctUINT32 REG_CorrectOverflowVG:1;
+ gctUINT32 REG_NegativeLogFix:1;
+ gctUINT32 REG_ResolveOffset:1;
+ gctUINT32 REG_OkToGateAxiClock:1;
+ gctUINT32 REG_MMU:1;
+ gctUINT32 REG_WideLine:1;
+ gctUINT32 REG_BugFixes6:1;
+ gctUINT32 REG_FcFlushStall:1;
+ gctUINT32 REG_LineLoop:1;
+ gctUINT32 REG_LogicOp:1;
+ gctUINT32 REG_SeamlessCubeMap:1;
+ gctUINT32 REG_SuperTiledTexture:1;
+ gctUINT32 REG_LinearPE:1;
+ gctUINT32 REG_RectPrimitive:1;
+ gctUINT32 REG_Composition:1;
+ gctUINT32 REG_CorrectAutoDisableCountWidth:1;
+ gctUINT32 REG_PESwizzle:1;
+ gctUINT32 REG_EndEvent:1;
+ gctUINT32 REG_S1S8:1;
+ gctUINT32 REG_Halti1:1;
+ gctUINT32 REG_RGB888:1;
+ gctUINT32 REG_TX_YUVAssembler:1;
+ gctUINT32 REG_DynamicFrequencyScaling:1;
+ gctUINT32 REG_TXFilter:1;
+ gctUINT32 REG_FullDirectFB:1;
+ gctUINT32 REG_OnePass2DFilter:1;
+ gctUINT32 REG_ThreadWalkerInPS:1;
+ gctUINT32 REG_TileFiller:1;
+ gctUINT32 REG_YUVStandard:1;
+ gctUINT32 REG_MultiSourceBlt:1;
+ gctUINT32 REG_YUVConversion:1;
+ gctUINT32 REG_FlushFixed2D:1;
+ gctUINT32 REG_Interleaver:1;
+ gctUINT32 REG_MixedStreams:1;
+ gctUINT32 REG_L2CacheFor2D420:1;
+ gctUINT32 REG_BugFixes7:1;
+ gctUINT32 REG_NoIndexPattern:1;
+ gctUINT32 REG_TextureTileStatus:1;
+ gctUINT32 REG_DecompressZ16:1;
+ gctUINT32 REG_BugFixes8:1;
+ gctUINT32 REG_DERotationStallFix:1;
+ gctUINT32 REG_OclOnly:1;
+ gctUINT32 REG_NewFeatures0:1;
+ gctUINT32 REG_InstructionCache:1;
+ gctUINT32 REG_GeometryShader:1;
+ gctUINT32 REG_TexCompressionSupertiled:1;
+ gctUINT32 REG_Generics:1;
+ gctUINT32 REG_BugFixes9:1;
+ gctUINT32 REG_FastMSAA:1;
+ gctUINT32 REG_WClip:1;
+ gctUINT32 REG_BugFixes10:1;
+ gctUINT32 REG_UnifiedSamplers:1;
+ gctUINT32 REG_BugFixes11:1;
+ gctUINT32 REG_PerformanceCounters:1;
+ gctUINT32 REG_ExtraShaderInstructions2:1;
+ gctUINT32 REG_BugFixes12:1;
+ gctUINT32 REG_BugFixes13:1;
+ gctUINT32 REG_DEEnhancements1:1;
+ gctUINT32 REG_ACE:1;
+ gctUINT32 REG_TXEnhancements1:1;
+ gctUINT32 REG_SHEnhancements1:1;
+ gctUINT32 REG_SHEnhancements2:1;
+ gctUINT32 REG_PEEnhancements1:1;
+ gctUINT32 REG_DEEnhancements2:1;
+ gctUINT32 REG_BugFixes14:1;
+ gctUINT32 REG_PowerOptimizations0:1;
+ gctUINT32 REG_NewHZ:1;
+ gctUINT32 REG_BugFixes15:1;
+ gctUINT32 REG_DEEnhancements3:1;
+ gctUINT32 REG_SHEnhancements3:1;
+ gctUINT32 REG_SHEnhancements4:1;
+ gctUINT32 REG_TXEnhancements2:1;
+ gctUINT32 REG_FEEnhancements1:1;
+ gctUINT32 REG_PEEnhancements2:1;
+ gctUINT32 REG_PAEnhancements1:1;
+ gctUINT32 REG_DENoGamma:1;
+ gctUINT32 REG_PAEnhancements2:1;
+ gctUINT32 REG_DEEnhancements4:1;
+ gctUINT32 REG_PEEnhancements3:1;
+ gctUINT32 REG_HIEnhancements1:1;
+ gctUINT32 REG_TXEnhancements3:1;
+ gctUINT32 REG_SHEnhancements5:1;
+ gctUINT32 REG_FEEnhancements2:1;
+ gctUINT32 REG_BugFixes16:1;
+ gctUINT32 REG_DEEnhancements5:1;
+ gctUINT32 REG_TXEnhancements4:1;
+ gctUINT32 REG_PEEnhancements4:1;
+ gctUINT32 REG_MCEnhancements1:1;
+ gctUINT32 REG_Halti2:1;
+ gctUINT32 REG_DEMirrorRotate:1;
+ gctUINT32 REG_SmallMSAA:1;
+ gctUINT32 REG_BugFixes17:1;
+ gctUINT32 REG_Rasterizer2:1;
+ gctUINT32 REG_DualPipeOPF:1;
+ gctUINT32 REG_MultiSrcV2:1;
+ gctUINT32 REG_CSCV2:1;
+ gctUINT32 REG_PAEnhancements3:1;
+ gctUINT32 REG_BugFixes18:1;
+ gctUINT32 REG_Compression2D:1;
+ gctUINT32 REG_Probe:1;
+ gctUINT32 REG_MediumPrecision:1;
+ gctUINT32 REG_DESupertile:1;
+ gctUINT32 REG_BugFixes19:1;
+ gctUINT32 REG_SHEnhancements6:1;
+ gctUINT32 REG_SHEnhancements7:1;
+ gctUINT32 REG_BugFixes20:1;
+ gctUINT32 REG_DEAddress40:1;
+ gctUINT32 REG_MiniMMUFix:1;
+ gctUINT32 REG_EEZ:1;
+ gctUINT32 REG_BugFixes21:1;
+ gctUINT32 REG_ExtraVgCaps:1;
+ gctUINT32 REG_MultiSrcV15:1;
+ gctUINT32 REG_BugFixes22:1;
+ gctUINT32 REG_Halti3:1;
+ gctUINT32 REG_TessellationShaders:1;
+ gctUINT32 REG_OPF9Tap:1;
+ gctUINT32 REG_MultiSrcV2StrQuad:1;
+ gctUINT32 REG_SeperateSRCAndDstCache:1;
+ gctUINT32 REG_Halti4:1;
+ gctUINT32 REG_RAWriteDepth:1;
+ gctUINT32 REG_AndroidOnly:1;
+ gctUINT32 REG_HasChipProductReg:1;
+ gctUINT32 REG_TXSupportDEC:1;
+ gctUINT32 REG_S8MSAACompression:1;
+ gctUINT32 REG_BugFixesIn544:1;
+ gctUINT32 REG_L2CacheRemove:1;
+ gctUINT32 REG_FEAllowRndVtxCnt:1;
+ gctUINT32 REG_CubeMapFL28:1;
+ gctUINT32 REG_TX6bitFrac:1;
+ gctUINT32 REG_FEAllowStallPrefetchEng:1;
+ gctUINT32 REG_ThirdPartyCompression:1;
+ gctUINT32 REG_RSS8:1;
+ gctUINT32 REG_MSAACoherencyCheck:1;
+ gctUINT32 REG_Halti5:1;
+ gctUINT32 REG_Evis:1;
+ gctUINT32 REG_BltEngine:1;
+ gctUINT32 REG_BugFixes23:1;
+ gctUINT32 REG_BugFixes24:1;
+ gctUINT32 REG_DEC:1;
+ gctUINT32 REG_VSTileNV12:1;
+ gctUINT32 REG_VSTileNV12_10BIT:1;
+ gctUINT32 RenderTarget8:1;
+ gctUINT32 TxLodFlowCorrection:1;
+ gctUINT32 FaceLod:1;
+ gctUINT32 MultiCoreSemaphoreStallV2:1;
+ gctUINT32 VMSAA:1;
+ gctUINT32 ChipEnableLink:1;
+ gctUINT32 MULTI_SRC_BLT_1_5_ENHANCEMENT:1;
+ gctUINT32 MULTI_SRC_BLT_BILINEAR_FILTER:1;
+ gctUINT32 RA_HZEZ_CLOCK_CONTROL:1;
+ gctUINT32 CACHE128B256BPERLINE:1;
+ gctUINT32 V4Compression:1;
+ gctUINT32 PE2D_MAJOR_SUPER_TILE:1;
+ gctUINT32 PE_32BPC_COLORMASK_FIX:1;
+ gctUINT32 ALPHA_BLENDING_OPT:1;
+ gctUINT32 NEW_GPIPE:1;
+ gctUINT32 PIPELINE_32_ATTRIBUTES:1;
+ gctUINT32 MSAA_SHADING:1;
+ gctUINT32 NO_ANISTRO_FILTER:1;
+ gctUINT32 NO_ASTC:1;
+ gctUINT32 NO_DXT:1;
+ gctUINT32 HWTFB:1;
+ gctUINT32 RA_DEPTH_WRITE_MSAA1X_FIX:1;
+ gctUINT32 EZHZ_CLOCKGATE_FIX:1;
+ gctUINT32 SH_SNAP2PAGE_FIX:1;
+ gctUINT32 SH_HALFDEPENDENCY_FIX:1;
+ gctUINT32 USC_MCFILL_FIX:1;
+ gctUINT32 TPG_TCPERF_FIX:1;
+ gctUINT32 USC_MDFIFO_OVERFLOW_FIX:1;
+ gctUINT32 SH_TEXLD_BARRIER_IN_CS_FIX:1;
+ gctUINT32 RS_NEW_BASEADDR:1;
+ gctUINT32 PE_8bpp_DUALPIPE_FIX:1;
+ gctUINT32 SH_ADVANCED_INSTR:1;
+ gctUINT32 SH_FLAT_INTERPOLATION_DUAL16_FIX:1;
+ gctUINT32 USC_CONTINUOUS_FLUS_FIX:1;
+ gctUINT32 SH_SUPPORT_V4:1;
+ gctUINT32 SH_SUPPORT_ALPHA_KILL:1;
+ gctUINT32 PE_NO_ALPHA_TEST:1;
+ gctUINT32 TX_LOD_NEAREST_SELECT:1;
+ gctUINT32 SH_FIX_LDEXP:1;
+ gctUINT32 SUPPORT_MOVAI:1;
+ gctUINT32 SH_SNAP2PAGE_MAXPAGES_FIX:1;
+ gctUINT32 PE_RGBA16I_FIX:1;
+ gctUINT32 BLT_8bpp_256TILE_FC_FIX:1;
+ gctUINT32 PE_64bit_FENCE_FIX:1;
+ gctUINT32 USC_FULL_CACHE_FIX:1;
+ gctUINT32 TX_YUV_ASSEMBLER_10BIT:1;
+ gctUINT32 FE_32bit_INDEX_FIX:1;
+ gctUINT32 BLT_64bpp_MASKED_CLEAR_FIX:1;
+ gctUINT32 SECURITY:1;
+ gctUINT32 ROBUSTNESS:1;
+ gctUINT32 USC_ATOMIC_FIX:1;
+ gctUINT32 SH_PSO_MSAA1x_FIX:1;
+ gctUINT32 USC_VX_PERF_FIX:1;
+ gctUINT32 EVIS_NO_ABSDIFF:1;
+ gctUINT32 EVIS_NO_BITREPLACE:1;
+ gctUINT32 EVIS_NO_BOXFILTER:1;
+ gctUINT32 EVIS_NO_CORDIAC:1;
+ gctUINT32 EVIS_NO_DP32:1;
+ gctUINT32 EVIS_NO_FILTER:1;
+ gctUINT32 EVIS_NO_IADD:1;
+ gctUINT32 EVIS_NO_SELECTADD:1;
+ gctUINT32 EVIS_LERP_7OUTPUT:1;
+ gctUINT32 EVIS_ACCSQ_8OUTPUT:1;
+ gctUINT32 USC_GOS_ADDR_FIX:1;
+ gctUINT32 TX_8bit_UVFrac:1;
+ gctUINT32 TX_DESC_CACHE_CLOCKGATE_FIX:1;
+ gctUINT32 RSBLT_MSAA_DECOMPRESSION:1;
+ gctUINT32 TX_INTEGER_COORDINATE:1;
+ gctUINT32 DRAWID:1;
+ gctUINT32 PSIO_SAMPLEMASK_IN_R0ZW_FIX:1;
+ gctUINT32 TX_INTEGER_COORDINATE_V2:1;
+ gctUINT32 MULTI_CORE_BLOCK_SET_CONFIG:1;
+ gctUINT32 VG_RESOLVE_ENGINE:1;
+ gctUINT32 VG_PE_COLOR_KEY:1;
+ gctUINT32 VG_IM_INDEX_FORMAT:1;
+ gctUINT32 SNAPPAGE_CMD:1;
+ gctUINT32 SH_NO_INDEX_CONST_ON_A0:1;
+ gctUINT32 SH_NO_ONECONST_LIMIT:1;
+ gctUINT32 SH_IMG_LDST_ON_TEMP:1;
+ gctUINT32 COMPUTE_ONLY:1;
+ gctUINT32 SH_IMG_LDST_CLAMP:1;
+ gctUINT32 SH_ICACHE_ALLOC_COUNT_FIX:1;
+ gctUINT32 SH_ICACHE_PREFETCH:1;
+ gctUINT32 PE2D_SEPARATE_CACHE:1;
+ gctUINT32 VG_AYUV_INPUT_OUTPUT:1;
+ gctUINT32 VG_DOUBLE_IMAGE:1;
+ gctUINT32 VG_RECTANGLE_STRIPE_MODE:1;
+ gctUINT32 VG_MMU:1;
+ gctUINT32 VG_IM_FILTER:1;
+ gctUINT32 VG_IM_YUV_PACKET:1;
+ gctUINT32 VG_IM_YUV_PLANAR:1;
+ gctUINT32 VG_PE_YUV_PACKET:1;
+ gctUINT32 VG_COLOR_PRECISION_8_BIT:1;
+ gctUINT32 PE_MSAA_OQ_FIX:1;
+ gctUINT32 PSIO_MSAA_CL_FIX:1;
+ gctUINT32 USC_DEFER_FILL_FIX:1;
+ gctUINT32 SH_CLOCK_GATE_FIX:1;
+ gctUINT32 FE_NEED_DUMMYDRAW:1;
+ gctUINT32 PE2D_LINEAR_YUV420_OUTPUT:1;
+ gctUINT32 PE2D_LINEAR_YUV420_10BIT:1;
+ gctUINT32 MULTI_CLUSTER:1;
+ gctUINT32 VG_TS_CULLING:1;
+ gctUINT32 VG_FP25:1;
+ gctUINT32 SH_MULTI_WG_PACK:1;
+ gctUINT32 SH_DUAL16_SAMPLEMASK_ZW:1;
+ gctUINT32 TPG_TRIVIAL_MODE_FIX:1;
+ gctUINT32 TX_ASTC_MULTISLICE_FIX:1;
+ gctUINT32 FE_ROBUST_FIX:1;
+ gctUINT32 SH_GPIPE_ACCESS_FULLTEMPS:1;
+ gctUINT32 PSIO_INTERLOCK:1;
+ gctUINT32 PA_WIDELINE_FIX:1;
+ gctUINT32 WIDELINE_HELPER_FIX:1;
+ gctUINT32 G2D_3rd_PARTY_COMPRESSION_1_1:1;
+ gctUINT32 TX_FLUSH_L1CACHE:1;
+ gctUINT32 PE_DITHER_FIX2:1;
+ gctUINT32 G2D_DEC400:1;
+ gctUINT32 SH_TEXLD_U_FIX:1;
+ gctUINT32 MC_FCCACHE_BYTEMASK:1;
+ gctUINT32 SH_MULTI_WG_PACK_FIX:1;
+ gctUINT32 DC_OVERLAY_SCALING:1;
+ gctUINT32 PE_ADVANCE_BLEND_PART0:1;
+ gctUINT32 FE_PATCHLIST_FETCH_FIX:1;
+ gctUINT32 RA_CG_FIX:1;
+ gctUINT32 EVIS_VX2:1;
+ gctUINT32 NN_FLOAT:1;
+ gctUINT32 DEC400:1;
+ gctUINT32 LS_SUPPORT_PERCOMP_DEPENDENCY:1;
+ gctUINT32 TP_ENGINE:1;
+ gctUINT32 MULTI_CORE_BLOCK_SET_CONFIG2:1;
+ gctUINT32 PE_VMSAA_COVERAGE_CACHE_FIX:1;
+ gctUINT32 SECURITY_AHB:1;
+ gctUINT32 MULTICORE_SEMAPHORESTALL_V3:1;
+ gctUINT32 SMALLBATCH:1;
+ gctUINT32 SH_CMPLX:1;
+ gctUINT32 SH_IDIV0_SWZL_EHS:1;
+ gctUINT32 TX_LERP_LESS_BIT:1;
+ gctUINT32 SH_GM_ENDIAN:1;
+ gctUINT32 SH_GM_USC_UNALLOC:1;
+ gctUINT32 SH_END_OF_BB:1;
+ gctUINT32 VIP_V7:1;
+} gcsFEATURE_DATABASE;
+
+static gcsFEATURE_DATABASE gChipInfo[] = {
+ /* dc0000_5550 */
+ {
+ 0x0, /* ChipID */
+ 0x5550, /* ChipRevision */
+ 0x12000000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x300, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc200_4650 */
+ {
+ 0x200, /* ChipID */
+ 0x4650, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc200_4621 */
+ {
+ 0x200, /* ChipID */
+ 0x4621, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x0, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x0, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc300_4650 */
+ {
+ 0x300, /* ChipID */
+ 0x4650, /* ChipRevision */
+ 0x5203, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x5, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc300_4650_guoke */
+ {
+ 0x300, /* ChipID */
+ 0x4650, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x4, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc300_4_6_6_rc0 */
+ {
+ 0x300, /* ChipID */
+ 0x4660, /* ChipRevision */
+ 0x5203, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x1, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc320_5007 */
+ {
+ 0x320, /* ChipID */
+ 0x5007, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x8, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x100, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x0, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x0, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc320_5220 */
+ {
+ 0x320, /* ChipID */
+ 0x5220, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc320_5303 */
+ {
+ 0x320, /* ChipID */
+ 0x5303, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc320_5303_1 */
+ {
+ 0x320, /* ChipID */
+ 0x5303, /* ChipRevision */
+ 0x5202, /* ProductID */
+ 0x1, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x4, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc320_5340 */
+ {
+ 0x320, /* ChipID */
+ 0x5340, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x4, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x1, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc320c_5341 */
+ {
+ 0x320, /* ChipID */
+ 0x5341, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xc, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x1, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x1, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x0, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x1, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x1, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x1, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc320_5341 */
+ {
+ 0x320, /* ChipID */
+ 0x5341, /* ChipRevision */
+ 0x3202, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520l_5_3_5_rc0 */
+ {
+ 0x320, /* ChipID */
+ 0x5350, /* ChipRevision */
+ 0x5202, /* ProductID */
+ 0x0, /* EcoID */
+ 0x206, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc355_v121_rc5 */
+ {
+ 0x355, /* ChipID */
+ 0x1215, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x1, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x1, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x1, /* gcFEATURE_BIT_REG_VGTS */
+ 0x1, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x0, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x1, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x1, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x0, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x1, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x1, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x0, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x0, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc355_v121x */
+ {
+ 0x355, /* ChipID */
+ 0x1217, /* ChipRevision */
+ 0x3003550, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x1, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x1, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x1, /* gcFEATURE_BIT_REG_VGTS */
+ 0x1, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x0, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x1, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x1, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x0, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x1, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x1, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x0, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x1, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x1, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x1, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x1, /* gcFEATURE_BIT_VG_MMU */
+ 0x1, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x1, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x1, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x1, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc400_4633 */
+ {
+ 0x400, /* ChipID */
+ 0x4633, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x20, /* gcFEATURE_VALUE_TempRegisters */
+ 0x40, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x80, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x1, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x0, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc400_4645 */
+ {
+ 0x400, /* ChipID */
+ 0x4645, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x4, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x20, /* gcFEATURE_VALUE_TempRegisters */
+ 0x40, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x80, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x240, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x1, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc400L_0x465x */
+ {
+ 0x400, /* ChipID */
+ 0x4652, /* ChipRevision */
+ 0x70001, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x7, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x20, /* gcFEATURE_VALUE_TempRegisters */
+ 0x40, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x80, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x1, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x1, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000nano_0x4652 */
+ {
+ 0x400, /* ChipID */
+ 0x4652, /* ChipRevision */
+ 0x70001, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x7, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x20, /* gcFEATURE_VALUE_TempRegisters */
+ 0x40, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x80, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x1, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x1, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000nano_0x4652 */
+ {
+ 0x400, /* ChipID */
+ 0x4652, /* ChipRevision */
+ 0x70001, /* ProductID */
+ 0x0, /* EcoID */
+ 0x100, /* CustomerID */
+ 0x9, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x20, /* gcFEATURE_VALUE_TempRegisters */
+ 0x40, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x80, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x1, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x1, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc420_5325 */
+ {
+ 0x420, /* ChipID */
+ 0x5325, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x2, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc420_5336 */
+ {
+ 0x420, /* ChipID */
+ 0x5336, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x3, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x1, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc420cpd_533rc7a */
+ {
+ 0x420, /* ChipID */
+ 0x5337, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x1, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc428_5421 */
+ {
+ 0x428, /* ChipID */
+ 0x5421, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc428c_5_4_2_rc3a */
+ {
+ 0x428, /* ChipID */
+ 0x5423, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x1, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x1, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520_5341 */
+ {
+ 0x520, /* ChipID */
+ 0x5341, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520_5540_rc0 */
+ {
+ 0x520, /* ChipID */
+ 0x5540, /* ChipRevision */
+ 0x5200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x1, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x1, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x1, /* gcFEATURE_BIT_REG_DEC */
+ 0x1, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520l_5_3_4_rc2b */
+ {
+ 0x520, /* ChipID */
+ 0x5342, /* ChipRevision */
+ 0x5202, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x2, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x1, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x1, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x1, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x1, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520c_5_5_0 */
+ {
+ 0x520, /* ChipID */
+ 0x5501, /* ChipRevision */
+ 0x5200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x3, /* CustomerID */
+ 0x2, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x1, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x1, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x1, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x1, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x1, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x1, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520c_5_5_4_rc1 */
+ {
+ 0x520, /* ChipID */
+ 0x5541, /* ChipRevision */
+ 0x5200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x202, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x1, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x1, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x1, /* gcFEATURE_BIT_REG_DEC */
+ 0x1, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520sp_5_5_2_rc0a */
+ {
+ 0x520, /* ChipID */
+ 0x5520, /* ChipRevision */
+ 0x5200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x1, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x1, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x1, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520_v552_rc1 */
+ {
+ 0x520, /* ChipID */
+ 0x5521, /* ChipRevision */
+ 0x5200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x1, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x1, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x1, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc520_5_5_3_rc2a */
+ {
+ 0x520, /* ChipID */
+ 0x5532, /* ChipRevision */
+ 0x5200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x1, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x1, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x1, /* gcFEATURE_BIT_REG_DEC */
+ 0x1, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc600L_0x465x */
+ {
+ 0x600, /* ChipID */
+ 0x4652, /* ChipRevision */
+ 0x70005, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x7, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x1, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x1, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000nanoultra_4_6_5_rc3a */
+ {
+ 0x600, /* ChipID */
+ 0x4653, /* ChipRevision */
+ 0x70005, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x1, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x1, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x1, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000nanoultra_4_6_5_rc3b */
+ {
+ 0x600, /* ChipID */
+ 0x4653, /* ChipRevision */
+ 0x70005, /* ProductID */
+ 0x0, /* EcoID */
+ 0x101, /* CustomerID */
+ 0x2, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x1, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x1, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x0, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x1, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc620_5_5_3_rc0 */
+ {
+ 0x620, /* ChipID */
+ 0x5530, /* ChipRevision */
+ 0x6200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x200, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x1, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x1, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x1, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc620_5_5_5_rc0d */
+ {
+ 0x620, /* ChipID */
+ 0x5550, /* ChipRevision */
+ 0x6200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x201, /* CustomerID */
+ 0x4, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x1, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x1, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x1, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x1, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x1, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc620tpc_5_5_6_rc0a */
+ {
+ 0x620, /* ChipID */
+ 0x5560, /* ChipRevision */
+ 0x6200, /* ProductID */
+ 0x0, /* EcoID */
+ 0x200, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x1, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x0, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x1, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x1, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x0, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x0, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x0, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x0, /* gcFEATURE_BIT_REG_FlipY */
+ 0x0, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x0, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x0, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x0, /* gcFEATURE_BIT_REG_Render8K */
+ 0x0, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x0, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x0, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x0, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x0, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x0, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x1, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x0, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x0, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x0, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x0, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x1, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x1, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x1, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x1, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x1, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x1, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x1, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x1, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x1, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc860L_0x464x */
+ {
+ 0x860, /* ChipID */
+ 0x4647, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x4, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x0, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x1, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc880_5106 */
+ {
+ 0x880, /* ChipID */
+ 0x5106, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x100, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xb, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc880_5122 */
+ {
+ 0x880, /* ChipID */
+ 0x5122, /* ChipRevision */
+ 0x70007, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x240, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xc, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x1, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc880TM_0x512x */
+ {
+ 0x880, /* ChipID */
+ 0x5124, /* ChipRevision */
+ 0x70007, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x2, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x240, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xc, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x0, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x0, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc900_5250 */
+ {
+ 0x900, /* ChipID */
+ 0x5250, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x200, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x1, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x2, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc1000_5036 */
+ {
+ 0x1000, /* ChipID */
+ 0x5036, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x240, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x1, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc1000_5037 */
+ {
+ 0x1000, /* ChipID */
+ 0x5037, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x240, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x1, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc1000_5037_1 */
+ {
+ 0x1000, /* ChipID */
+ 0x5037, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x1, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x240, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x0, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x0, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x1, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc1000_5039 */
+ {
+ 0x1000, /* ChipID */
+ 0x5039, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x11, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x4, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x240, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x1, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x0, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x1, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc1500_5246 */
+ {
+ 0x1500, /* ChipID */
+ 0x5246, /* ChipRevision */
+ 0x70003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x6, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x400, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xf, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x2, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc2000_5108 */
+ {
+ 0x2000, /* ChipID */
+ 0x5108, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0xa8, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xb, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x1, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x0, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x0, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x0, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x0, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x0, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x0, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x0, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x0, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x0, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x0, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc2000_5140 */
+ {
+ 0x2000, /* ChipID */
+ 0x5140, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x5, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x100, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc2000w_5_1_4_rc0e */
+ {
+ 0x2000, /* ChipID */
+ 0x5140, /* ChipRevision */
+ 0x20000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x5, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionCount */
+ 0x100, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x8, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x0, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x1, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x0, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x0, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x0, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x0, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x0, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x0, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x0, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x0, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x0, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x0, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x0, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc2500_5422 */
+ {
+ 0x2500, /* ChipID */
+ 0x5422, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x12, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xf, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x4, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc6400_5422 */
+ {
+ 0x6400, /* ChipID */
+ 0x5422, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x16, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xf, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc3000_5435 */
+ {
+ 0x3000, /* ChipID */
+ 0x5435, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xf, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x4, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x1, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc2000_ffff5450 */
+ {
+ 0x2000, /* ChipID */
+ 0xffff5450, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x8, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x4, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc3000_5450 */
+ {
+ 0x3000, /* ChipID */
+ 0x5450, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x8, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x4, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc3000_5451 */
+ {
+ 0x3000, /* ChipID */
+ 0x5451, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x4, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x4, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x1, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000L_551x */
+ {
+ 0x3000, /* ChipID */
+ 0x5512, /* ChipRevision */
+ 0x70002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x3, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x4, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x1, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000L_5512 */
+ {
+ 0x3000, /* ChipID */
+ 0x5512, /* ChipRevision */
+ 0x70002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x3, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x4, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x1, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000L_5514 */
+ {
+ 0x3000, /* ChipID */
+ 0x5514, /* ChipRevision */
+ 0x70002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x4, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x1, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc4000_5222 */
+ {
+ 0x4000, /* ChipID */
+ 0x5222, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x800, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x800, /* gcFEATURE_VALUE_InstructionCount */
+ 0x200, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xb, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x1, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x0, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x0, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x0, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x0, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc4000_5245 */
+ {
+ 0x4000, /* ChipID */
+ 0x5245, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x400, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xf, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x0, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x0, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x0, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x1, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x0, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x0, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x0, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x0, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc5000_5434 */
+ {
+ 0x5000, /* ChipID */
+ 0x5434, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0xf, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x0, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x0, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x0, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x0, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x0, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x0, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x0, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x0, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x0, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x0, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000_551x */
+ {
+ 0x5000, /* ChipID */
+ 0x5513, /* ChipRevision */
+ 0x70000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x1, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000_5513 */
+ {
+ 0x5000, /* ChipID */
+ 0x5513, /* ChipRevision */
+ 0x70000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x1, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x1, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x0, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x1, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gcXAQ2_CMODEL */
+ {
+ 0x7000, /* ChipID */
+ 0x0, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x200, /* gcFEATURE_VALUE_TempRegisters */
+ 0x100, /* gcFEATURE_VALUE_ThreadCount */
+ 0x8, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x200, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x0, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x100, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x1, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x1, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x1, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x1, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x1, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x0, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x0, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x0, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x0, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x1, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x0, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x0, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x0, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x0, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x0, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x1, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XS_600x */
+ {
+ 0x7000, /* ChipID */
+ 0x6008, /* ChipRevision */
+ 0x70004, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0xb, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XS_6008 */
+ {
+ 0x7000, /* ChipID */
+ 0x6008, /* ChipRevision */
+ 0x70004, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0xb, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XSVX_600x */
+ {
+ 0x7000, /* ChipID */
+ 0x6008, /* ChipRevision */
+ 0x70008, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XSVX_6008 */
+ {
+ 0x7000, /* ChipID */
+ 0x6008, /* ChipRevision */
+ 0x70008, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x7, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XSVX_6009 */
+ {
+ 0x7000, /* ChipID */
+ 0x6009, /* ChipRevision */
+ 0x70008, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x9, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000_6100 */
+ {
+ 0x7000, /* ChipID */
+ 0x6100, /* ChipRevision */
+ 0x70000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x20, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x20, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000L_6100 */
+ {
+ 0x7000, /* ChipID */
+ 0x6100, /* ChipRevision */
+ 0x70002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XS_6100 */
+ {
+ 0x7000, /* ChipID */
+ 0x6100, /* ChipRevision */
+ 0x70004, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x0, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* vip7000UL_6100 */
+ {
+ 0x7000, /* ChipID */
+ 0x6100, /* ChipRevision */
+ 0x5070003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x0, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x70000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x28, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x28, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000UL_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x70003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x10, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x1, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000ULVX_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x7000f, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x10, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x1, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x1, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x1, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* vip7000L_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x5070002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x20, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x20, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* vip7000UL_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x5070003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* vip7000UL_6211 */
+ {
+ 0x7000, /* ChipID */
+ 0x6211, /* ChipRevision */
+ 0x5070003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x21, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x40, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x1, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x6, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0xe0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x1, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* vip8000UL_6211 */
+ {
+ 0x8000, /* ChipID */
+ 0x6211, /* ChipRevision */
+ 0x5080003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x21, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x40, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x1, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x6, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0xe0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x400, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x10, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x1, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x1, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* vip8000ULFN_6211 */
+ {
+ 0x8000, /* ChipID */
+ 0x6211, /* ChipRevision */
+ 0x5080003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x22, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x40, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x1, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x6, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0xe0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x400, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x10, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x1, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x1, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* vip8000UL_6211 */
+ {
+ 0x8000, /* ChipID */
+ 0x6211, /* ChipRevision */
+ 0x5080003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x40, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x1, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x6, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0xe0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x400, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x10, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x1, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x1, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x1, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7400_551x */
+ {
+ 0x7400, /* ChipID */
+ 0x5515, /* ChipRevision */
+ 0x74000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x6, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x0, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x2, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x0, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x0, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x0, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x0, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x0, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x0, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x1, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x1, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x0, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x0, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x0, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x0, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x0, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x0, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x0, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x0, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x0, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x0, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x0, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x0, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x0, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x0, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x0, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x0, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x0, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x0, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x0, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x0, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x0, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x1, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x0, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x0, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x1, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc8000UL_6200 */
+ {
+ 0x8000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x80003, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x8, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x8, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x10, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x1, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* v630 */
+ {
+ 0x7000, /* ChipID */
+ 0x6300, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x1, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XS_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x70004, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000L_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x70002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000LXS_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x7000a, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* vip7000_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x5070000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000ULVX_V11_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x7000f, /* ProductID */
+ 0x0, /* EcoID */
+ 0x1, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x10, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x1, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x1, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x1, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000ULVX_V12_6200 */
+ {
+ 0x7000, /* ChipID */
+ 0x6200, /* ChipRevision */
+ 0x7000f, /* ProductID */
+ 0x0, /* EcoID */
+ 0x2, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x10, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x1, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x0, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000ULVX_6200_pid0x60 */
+ {
+ 0x7000, /* ChipID */
+ 0x6203, /* ChipRevision */
+ 0x7000f, /* ProductID */
+ 0x0, /* EcoID */
+ 0x60, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x200, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x2, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x10, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x0, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x0, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x0, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x1, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x1, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XS_6FFF */
+ {
+ 0x7000, /* ChipID */
+ 0x6fff, /* ChipRevision */
+ 0x70004, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x1, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x0, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x0, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x0, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x70000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x6, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x70000, /* ProductID */
+ 0x0, /* EcoID */
+ 0xa, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XS_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x70004, /* ProductID */
+ 0x0, /* EcoID */
+ 0x8, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x30, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x30, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XS_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x70004, /* ProductID */
+ 0x0, /* EcoID */
+ 0xc, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x30, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x30, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000L_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x70002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x5, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x1, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000L_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x70002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x9, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000LXS_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x7000a, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x30, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x30, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XSVX_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x70008, /* ProductID */
+ 0x0, /* EcoID */
+ 0x7, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000XSVX_6210 */
+ {
+ 0x7000, /* ChipID */
+ 0x6210, /* ChipRevision */
+ 0x70008, /* ProductID */
+ 0x0, /* EcoID */
+ 0xb, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x20, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7000L_DEC400 */
+ {
+ 0x7000, /* ChipID */
+ 0x6214, /* ChipRevision */
+ 0x70002, /* ProductID */
+ 0x0, /* EcoID */
+ 0x30, /* CustomerID */
+ 0x8, /* PatchVersion */
+ 0x1, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x10, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x10, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x1, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x1, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7400_0002 */
+ {
+ 0x8400, /* ChipID */
+ 0x6310, /* ChipRevision */
+ 0x8400a, /* ProductID */
+ 0x0, /* EcoID */
+ 0x44, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x30, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x10, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x30, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x1, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x1, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x1, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x1, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc7400_0003 */
+ {
+ 0x8400, /* ChipID */
+ 0x6310, /* ChipRevision */
+ 0x8400a, /* ProductID */
+ 0x0, /* EcoID */
+ 0x45, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x8, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x400, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x4, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x30, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x8, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x30, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x1, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x0, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x1, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x1, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x1, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc8400_6300 */
+ {
+ 0x8400, /* ChipID */
+ 0x6300, /* ChipRevision */
+ 0x0, /* ProductID */
+ 0x0, /* EcoID */
+ 0x0, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x10, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0xf, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x1, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc8100_6300_pid0x43 */
+ {
+ 0x8100, /* ChipID */
+ 0x6300, /* ChipRevision */
+ 0x81004, /* ProductID */
+ 0x0, /* EcoID */
+ 0x43, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x10, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x1, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x1, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* gc8200_6300_pid0x46 */
+ {
+ 0x8200, /* ChipID */
+ 0x6300, /* ChipRevision */
+ 0x82004, /* ProductID */
+ 0x0, /* EcoID */
+ 0x46, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x10, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x2, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x10, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x3, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x0, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x0, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x1, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x0, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x1, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x1, /* gcFEATURE_BIT_REG_Evis */
+ 0x1, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x1, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x0, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x1, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x1, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x0, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x1, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x1, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x1, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x1, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x1, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x1, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x1, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x1, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x1, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x1, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* cc8000_6220 */
+ {
+ 0x8000, /* ChipID */
+ 0x6220, /* ChipRevision */
+ 0x6080000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x50, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x0, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x0, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x0, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x0, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x0, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+ /* cc8000_6330 */
+ {
+ 0x8000, /* ChipID */
+ 0x6330, /* ChipRevision */
+ 0x6080000, /* ProductID */
+ 0x0, /* EcoID */
+ 0x51, /* CustomerID */
+ 0x0, /* PatchVersion */
+ 0x0, /* FormalRelease */
+ 0x10, /* gcFEATURE_VALUE_Streams */
+ 0x40, /* gcFEATURE_VALUE_TempRegisters */
+ 0x800, /* gcFEATURE_VALUE_ThreadCount */
+ 0x10, /* gcFEATURE_VALUE_VertexCacheSize */
+ 0x8, /* gcFEATURE_VALUE_NumShaderCores */
+ 0x1, /* gcFEATURE_VALUE_NumPixelPipes */
+ 0x400, /* gcFEATURE_VALUE_VertexOutputBufferSize */
+ 0x0, /* gcFEATURE_VALUE_BufferSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionCount */
+ 0x140, /* gcFEATURE_VALUE_NumberOfConstants */
+ 0x1, /* gcFEATURE_VALUE_CoreCount */
+ 0x1f, /* gcFEATURE_VALUE_VaryingCount */
+ 0x40, /* gcFEATURE_VALUE_LocalStorageSize */
+ 0x40, /* gcFEATURE_VALUE_L1CacheSize */
+ 0x200, /* gcFEATURE_VALUE_InstructionMemorySize */
+ 0x14, /* gcFEATURE_VALUE_ShaderPCLength */
+ 0x1, /* gcFEATURE_VALUE_NumResolvePipes */
+ 0x40, /* gcFEATURE_VALUE_USC_MAX_PAGES */
+ 0x100, /* gcFEATURE_VALUE_RESULT_WINDOW_MAX_SIZE */
+ 0x0, /* gcFEATURE_VALUE_NNMadPerCore */
+ 0x0, /* gcFEATURE_VALUE_NNCoreCount */
+ 0x0, /* gcFEATURE_VALUE_NNInputBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_NNAccumBufferDepth */
+ 0x0, /* gcFEATURE_VALUE_ClusterAliveMask */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTCount */
+ 0x0, /* gcFEATURE_VALUE_TPEngine_PwlLUTSize */
+ 0x1, /* gcFEATURE_BIT_REG_FastClear */
+ 0x0, /* gcFEATURE_BIT_REG_SpecialAntiAliasing */
+ 0x1, /* gcFEATURE_BIT_REG_Pipe3D */
+ 0x1, /* gcFEATURE_BIT_REG_DXTTextureCompression */
+ 0x0, /* gcFEATURE_BIT_REG_DebugMode */
+ 0x1, /* gcFEATURE_BIT_REG_ZCompression */
+ 0x0, /* gcFEATURE_BIT_REG_YUV420Filter */
+ 0x1, /* gcFEATURE_BIT_REG_MSAA */
+ 0x0, /* gcFEATURE_BIT_REG_DC */
+ 0x0, /* gcFEATURE_BIT_REG_Pipe2D */
+ 0x1, /* gcFEATURE_BIT_REG_ETC1TextureCompression */
+ 0x1, /* gcFEATURE_BIT_REG_FastScaler */
+ 0x1, /* gcFEATURE_BIT_REG_HighDynamicRange */
+ 0x1, /* gcFEATURE_BIT_REG_YUV420Tiler */
+ 0x1, /* gcFEATURE_BIT_REG_ModuleCG */
+ 0x0, /* gcFEATURE_BIT_REG_MinArea */
+ 0x0, /* gcFEATURE_BIT_REG_NoEZ */
+ 0x0, /* gcFEATURE_BIT_REG_No422Texture */
+ 0x0, /* gcFEATURE_BIT_REG_BufferInterleaving */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite2D */
+ 0x0, /* gcFEATURE_BIT_REG_NoScaler */
+ 0x1, /* gcFEATURE_BIT_REG_YUY2Averaging */
+ 0x0, /* gcFEATURE_BIT_REG_HalfPECache */
+ 0x0, /* gcFEATURE_BIT_REG_HalfTXCache */
+ 0x0, /* gcFEATURE_BIT_REG_YUY2RenderTarget */
+ 0x0, /* gcFEATURE_BIT_REG_Mem32BitSupport */
+ 0x0, /* gcFEATURE_BIT_REG_PipeVG */
+ 0x0, /* gcFEATURE_BIT_REG_VGTS */
+ 0x0, /* gcFEATURE_BIT_REG_FE20 */
+ 0x1, /* gcFEATURE_BIT_REG_ByteWrite3D */
+ 0x1, /* gcFEATURE_BIT_REG_RsYuvTarget */
+ 0x1, /* gcFEATURE_BIT_REG_FE20BitIndex */
+ 0x1, /* gcFEATURE_BIT_REG_FlipY */
+ 0x1, /* gcFEATURE_BIT_REG_DualReturnBus */
+ 0x1, /* gcFEATURE_BIT_REG_EndiannessConfig */
+ 0x1, /* gcFEATURE_BIT_REG_Texture8K */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectTextureConverter */
+ 0x1, /* gcFEATURE_BIT_REG_SpecialMsaaLod */
+ 0x1, /* gcFEATURE_BIT_REG_FastClearFlush */
+ 0x1, /* gcFEATURE_BIT_REG_2DPE20 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectAutoDisable */
+ 0x1, /* gcFEATURE_BIT_REG_Render8K */
+ 0x1, /* gcFEATURE_BIT_REG_TileStatus2Bits */
+ 0x1, /* gcFEATURE_BIT_REG_SeparateTileStatusWhenInterleaved */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiled32x32 */
+ 0x0, /* gcFEATURE_BIT_REG_VG20 */
+ 0x0, /* gcFEATURE_BIT_REG_TSExtendedCommands */
+ 0x1, /* gcFEATURE_BIT_REG_CompressionFifoFixed */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions0 */
+ 0x0, /* gcFEATURE_BIT_REG_VGFilter */
+ 0x0, /* gcFEATURE_BIT_REG_VG21 */
+ 0x1, /* gcFEATURE_BIT_REG_ShaderGetsW */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions1 */
+ 0x1, /* gcFEATURE_BIT_REG_DefaultReg0 */
+ 0x1, /* gcFEATURE_BIT_REG_MC20 */
+ 0x0, /* gcFEATURE_BIT_REG_ShaderMSAASideband */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes0 */
+ 0x0, /* gcFEATURE_BIT_REG_VAA */
+ 0x0, /* gcFEATURE_BIT_REG_BypassInMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_HierarchicalZ */
+ 0x0, /* gcFEATURE_BIT_REG_NewTexture */
+ 0x0, /* gcFEATURE_BIT_REG_A8TargetSupport */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectStencil */
+ 0x1, /* gcFEATURE_BIT_REG_EnhanceVR */
+ 0x1, /* gcFEATURE_BIT_REG_RSUVSwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_V2Compression */
+ 0x0, /* gcFEATURE_BIT_REG_VGDoubleBuffer */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes1 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes2 */
+ 0x0, /* gcFEATURE_BIT_REG_TextureStride */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes3 */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisable1 */
+ 0x0, /* gcFEATURE_BIT_REG_AutoRestartTS */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes4 */
+ 0x0, /* gcFEATURE_BIT_REG_L2Windowing */
+ 0x1, /* gcFEATURE_BIT_REG_HalfFloatPipe */
+ 0x1, /* gcFEATURE_BIT_REG_PixelDither */
+ 0x1, /* gcFEATURE_BIT_REG_TwoStencilReference */
+ 0x1, /* gcFEATURE_BIT_REG_ExtendedPixelFormat */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectMinMaxDepth */
+ 0x1, /* gcFEATURE_BIT_REG_DitherAndFilterPlusAlpha2D */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes5 */
+ 0x0, /* gcFEATURE_BIT_REG_New2D */
+ 0x1, /* gcFEATURE_BIT_REG_NewFloatingPointArithmetic */
+ 0x1, /* gcFEATURE_BIT_REG_TextureHorizontalAlignmentSelect */
+ 0x1, /* gcFEATURE_BIT_REG_NonPowerOfTwo */
+ 0x1, /* gcFEATURE_BIT_REG_LinearTextureSupport */
+ 0x1, /* gcFEATURE_BIT_REG_Halti0 */
+ 0x0, /* gcFEATURE_BIT_REG_CorrectOverflowVG */
+ 0x1, /* gcFEATURE_BIT_REG_NegativeLogFix */
+ 0x1, /* gcFEATURE_BIT_REG_ResolveOffset */
+ 0x1, /* gcFEATURE_BIT_REG_OkToGateAxiClock */
+ 0x1, /* gcFEATURE_BIT_REG_MMU */
+ 0x1, /* gcFEATURE_BIT_REG_WideLine */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes6 */
+ 0x1, /* gcFEATURE_BIT_REG_FcFlushStall */
+ 0x1, /* gcFEATURE_BIT_REG_LineLoop */
+ 0x1, /* gcFEATURE_BIT_REG_LogicOp */
+ 0x1, /* gcFEATURE_BIT_REG_SeamlessCubeMap */
+ 0x1, /* gcFEATURE_BIT_REG_SuperTiledTexture */
+ 0x1, /* gcFEATURE_BIT_REG_LinearPE */
+ 0x1, /* gcFEATURE_BIT_REG_RectPrimitive */
+ 0x0, /* gcFEATURE_BIT_REG_Composition */
+ 0x1, /* gcFEATURE_BIT_REG_CorrectAutoDisableCountWidth */
+ 0x1, /* gcFEATURE_BIT_REG_PESwizzle */
+ 0x1, /* gcFEATURE_BIT_REG_EndEvent */
+ 0x1, /* gcFEATURE_BIT_REG_S1S8 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti1 */
+ 0x0, /* gcFEATURE_BIT_REG_RGB888 */
+ 0x1, /* gcFEATURE_BIT_REG_TX_YUVAssembler */
+ 0x1, /* gcFEATURE_BIT_REG_DynamicFrequencyScaling */
+ 0x0, /* gcFEATURE_BIT_REG_TXFilter */
+ 0x1, /* gcFEATURE_BIT_REG_FullDirectFB */
+ 0x0, /* gcFEATURE_BIT_REG_OnePass2DFilter */
+ 0x1, /* gcFEATURE_BIT_REG_ThreadWalkerInPS */
+ 0x1, /* gcFEATURE_BIT_REG_TileFiller */
+ 0x1, /* gcFEATURE_BIT_REG_YUVStandard */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSourceBlt */
+ 0x0, /* gcFEATURE_BIT_REG_YUVConversion */
+ 0x1, /* gcFEATURE_BIT_REG_FlushFixed2D */
+ 0x1, /* gcFEATURE_BIT_REG_Interleaver */
+ 0x1, /* gcFEATURE_BIT_REG_MixedStreams */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheFor2D420 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes7 */
+ 0x0, /* gcFEATURE_BIT_REG_NoIndexPattern */
+ 0x1, /* gcFEATURE_BIT_REG_TextureTileStatus */
+ 0x1, /* gcFEATURE_BIT_REG_DecompressZ16 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes8 */
+ 0x1, /* gcFEATURE_BIT_REG_DERotationStallFix */
+ 0x0, /* gcFEATURE_BIT_REG_OclOnly */
+ 0x1, /* gcFEATURE_BIT_REG_NewFeatures0 */
+ 0x1, /* gcFEATURE_BIT_REG_InstructionCache */
+ 0x0, /* gcFEATURE_BIT_REG_GeometryShader */
+ 0x1, /* gcFEATURE_BIT_REG_TexCompressionSupertiled */
+ 0x1, /* gcFEATURE_BIT_REG_Generics */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes9 */
+ 0x0, /* gcFEATURE_BIT_REG_FastMSAA */
+ 0x0, /* gcFEATURE_BIT_REG_WClip */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes10 */
+ 0x1, /* gcFEATURE_BIT_REG_UnifiedSamplers */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes11 */
+ 0x1, /* gcFEATURE_BIT_REG_PerformanceCounters */
+ 0x1, /* gcFEATURE_BIT_REG_ExtraShaderInstructions2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes12 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes13 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_ACE */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_DEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes14 */
+ 0x0, /* gcFEATURE_BIT_REG_PowerOptimizations0 */
+ 0x1, /* gcFEATURE_BIT_REG_NewHZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes15 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements1 */
+ 0x0, /* gcFEATURE_BIT_REG_DENoGamma */
+ 0x0, /* gcFEATURE_BIT_REG_PAEnhancements2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_PEEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_HIEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_FEEnhancements2 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes16 */
+ 0x0, /* gcFEATURE_BIT_REG_DEEnhancements5 */
+ 0x1, /* gcFEATURE_BIT_REG_TXEnhancements4 */
+ 0x0, /* gcFEATURE_BIT_REG_PEEnhancements4 */
+ 0x1, /* gcFEATURE_BIT_REG_MCEnhancements1 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti2 */
+ 0x0, /* gcFEATURE_BIT_REG_DEMirrorRotate */
+ 0x1, /* gcFEATURE_BIT_REG_SmallMSAA */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes17 */
+ 0x0, /* gcFEATURE_BIT_REG_Rasterizer2 */
+ 0x0, /* gcFEATURE_BIT_REG_DualPipeOPF */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2 */
+ 0x0, /* gcFEATURE_BIT_REG_CSCV2 */
+ 0x1, /* gcFEATURE_BIT_REG_PAEnhancements3 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes18 */
+ 0x0, /* gcFEATURE_BIT_REG_Compression2D */
+ 0x1, /* gcFEATURE_BIT_REG_Probe */
+ 0x1, /* gcFEATURE_BIT_REG_MediumPrecision */
+ 0x0, /* gcFEATURE_BIT_REG_DESupertile */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes19 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements6 */
+ 0x1, /* gcFEATURE_BIT_REG_SHEnhancements7 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes20 */
+ 0x0, /* gcFEATURE_BIT_REG_DEAddress40 */
+ 0x0, /* gcFEATURE_BIT_REG_MiniMMUFix */
+ 0x1, /* gcFEATURE_BIT_REG_EEZ */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes21 */
+ 0x0, /* gcFEATURE_BIT_REG_ExtraVgCaps */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV15 */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixes22 */
+ 0x1, /* gcFEATURE_BIT_REG_Halti3 */
+ 0x0, /* gcFEATURE_BIT_REG_TessellationShaders */
+ 0x0, /* gcFEATURE_BIT_REG_OPF9Tap */
+ 0x0, /* gcFEATURE_BIT_REG_MultiSrcV2StrQuad */
+ 0x0, /* gcFEATURE_BIT_REG_SeperateSRCAndDstCache */
+ 0x1, /* gcFEATURE_BIT_REG_Halti4 */
+ 0x1, /* gcFEATURE_BIT_REG_RAWriteDepth */
+ 0x0, /* gcFEATURE_BIT_REG_AndroidOnly */
+ 0x1, /* gcFEATURE_BIT_REG_HasChipProductReg */
+ 0x0, /* gcFEATURE_BIT_REG_TXSupportDEC */
+ 0x1, /* gcFEATURE_BIT_REG_S8MSAACompression */
+ 0x1, /* gcFEATURE_BIT_REG_BugFixesIn544 */
+ 0x0, /* gcFEATURE_BIT_REG_L2CacheRemove */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowRndVtxCnt */
+ 0x0, /* gcFEATURE_BIT_REG_CubeMapFL28 */
+ 0x1, /* gcFEATURE_BIT_REG_TX6bitFrac */
+ 0x1, /* gcFEATURE_BIT_REG_FEAllowStallPrefetchEng */
+ 0x0, /* gcFEATURE_BIT_REG_ThirdPartyCompression */
+ 0x1, /* gcFEATURE_BIT_REG_RSS8 */
+ 0x1, /* gcFEATURE_BIT_REG_MSAACoherencyCheck */
+ 0x1, /* gcFEATURE_BIT_REG_Halti5 */
+ 0x0, /* gcFEATURE_BIT_REG_Evis */
+ 0x0, /* gcFEATURE_BIT_REG_BltEngine */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes23 */
+ 0x0, /* gcFEATURE_BIT_REG_BugFixes24 */
+ 0x0, /* gcFEATURE_BIT_REG_DEC */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12 */
+ 0x0, /* gcFEATURE_BIT_REG_VSTileNV12_10BIT */
+ 0x0, /* gcFEATURE_BIT_RenderTarget8 */
+ 0x0, /* gcFEATURE_BIT_TxLodFlowCorrection */
+ 0x0, /* gcFEATURE_BIT_FaceLod */
+ 0x0, /* gcFEATURE_BIT_MultiCoreSemaphoreStallV2 */
+ 0x1, /* gcFEATURE_BIT_VMSAA */
+ 0x0, /* gcFEATURE_BIT_ChipEnableLink */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_1_5_ENHANCEMENT */
+ 0x0, /* gcFEATURE_BIT_MULTI_SRC_BLT_BILINEAR_FILTER */
+ 0x1, /* gcFEATURE_BIT_RA_HZEZ_CLOCK_CONTROL */
+ 0x1, /* gcFEATURE_BIT_CACHE128B256BPERLINE */
+ 0x1, /* gcFEATURE_BIT_V4Compression */
+ 0x0, /* gcFEATURE_BIT_PE2D_MAJOR_SUPER_TILE */
+ 0x1, /* gcFEATURE_BIT_PE_32BPC_COLORMASK_FIX */
+ 0x1, /* gcFEATURE_BIT_ALPHA_BLENDING_OPT */
+ 0x1, /* gcFEATURE_BIT_NEW_GPIPE */
+ 0x0, /* gcFEATURE_BIT_PIPELINE_32_ATTRIBUTES */
+ 0x0, /* gcFEATURE_BIT_MSAA_SHADING */
+ 0x0, /* gcFEATURE_BIT_NO_ANISTRO_FILTER */
+ 0x1, /* gcFEATURE_BIT_NO_ASTC */
+ 0x0, /* gcFEATURE_BIT_NO_DXT */
+ 0x0, /* gcFEATURE_BIT_HWTFB */
+ 0x1, /* gcFEATURE_BIT_RA_DEPTH_WRITE_MSAA1X_FIX */
+ 0x1, /* gcFEATURE_BIT_EZHZ_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_HALFDEPENDENCY_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MCFILL_FIX */
+ 0x1, /* gcFEATURE_BIT_TPG_TCPERF_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_MDFIFO_OVERFLOW_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_TEXLD_BARRIER_IN_CS_FIX */
+ 0x1, /* gcFEATURE_BIT_RS_NEW_BASEADDR */
+ 0x1, /* gcFEATURE_BIT_PE_8bpp_DUALPIPE_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_ADVANCED_INSTR */
+ 0x1, /* gcFEATURE_BIT_SH_FLAT_INTERPOLATION_DUAL16_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_CONTINUOUS_FLUS_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_V4 */
+ 0x0, /* gcFEATURE_BIT_SH_SUPPORT_ALPHA_KILL */
+ 0x1, /* gcFEATURE_BIT_PE_NO_ALPHA_TEST */
+ 0x0, /* gcFEATURE_BIT_TX_LOD_NEAREST_SELECT */
+ 0x1, /* gcFEATURE_BIT_SH_FIX_LDEXP */
+ 0x1, /* gcFEATURE_BIT_SUPPORT_MOVAI */
+ 0x1, /* gcFEATURE_BIT_SH_SNAP2PAGE_MAXPAGES_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_RGBA16I_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_8bpp_256TILE_FC_FIX */
+ 0x1, /* gcFEATURE_BIT_PE_64bit_FENCE_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_FULL_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_YUV_ASSEMBLER_10BIT */
+ 0x1, /* gcFEATURE_BIT_FE_32bit_INDEX_FIX */
+ 0x1, /* gcFEATURE_BIT_BLT_64bpp_MASKED_CLEAR_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY */
+ 0x1, /* gcFEATURE_BIT_ROBUSTNESS */
+ 0x1, /* gcFEATURE_BIT_USC_ATOMIC_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_PSO_MSAA1x_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_VX_PERF_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_ABSDIFF */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BITREPLACE */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_BOXFILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_CORDIAC */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_DP32 */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_FILTER */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_IADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_NO_SELECTADD */
+ 0x0, /* gcFEATURE_BIT_EVIS_LERP_7OUTPUT */
+ 0x0, /* gcFEATURE_BIT_EVIS_ACCSQ_8OUTPUT */
+ 0x1, /* gcFEATURE_BIT_USC_GOS_ADDR_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_8bit_UVFrac */
+ 0x1, /* gcFEATURE_BIT_TX_DESC_CACHE_CLOCKGATE_FIX */
+ 0x1, /* gcFEATURE_BIT_RSBLT_MSAA_DECOMPRESSION */
+ 0x0, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE */
+ 0x1, /* gcFEATURE_BIT_DRAWID */
+ 0x1, /* gcFEATURE_BIT_PSIO_SAMPLEMASK_IN_R0ZW_FIX */
+ 0x1, /* gcFEATURE_BIT_TX_INTEGER_COORDINATE_V2 */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG */
+ 0x0, /* gcFEATURE_BIT_VG_RESOLVE_ENGINE */
+ 0x0, /* gcFEATURE_BIT_VG_PE_COLOR_KEY */
+ 0x0, /* gcFEATURE_BIT_VG_IM_INDEX_FORMAT */
+ 0x0, /* gcFEATURE_BIT_SNAPPAGE_CMD */
+ 0x1, /* gcFEATURE_BIT_SH_NO_INDEX_CONST_ON_A0 */
+ 0x1, /* gcFEATURE_BIT_SH_NO_ONECONST_LIMIT */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_ON_TEMP */
+ 0x1, /* gcFEATURE_BIT_COMPUTE_ONLY */
+ 0x1, /* gcFEATURE_BIT_SH_IMG_LDST_CLAMP */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_ALLOC_COUNT_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_ICACHE_PREFETCH */
+ 0x0, /* gcFEATURE_BIT_PE2D_SEPARATE_CACHE */
+ 0x0, /* gcFEATURE_BIT_VG_AYUV_INPUT_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_VG_DOUBLE_IMAGE */
+ 0x0, /* gcFEATURE_BIT_VG_RECTANGLE_STRIPE_MODE */
+ 0x0, /* gcFEATURE_BIT_VG_MMU */
+ 0x0, /* gcFEATURE_BIT_VG_IM_FILTER */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_IM_YUV_PLANAR */
+ 0x0, /* gcFEATURE_BIT_VG_PE_YUV_PACKET */
+ 0x0, /* gcFEATURE_BIT_VG_COLOR_PRECISION_8_BIT */
+ 0x1, /* gcFEATURE_BIT_PE_MSAA_OQ_FIX */
+ 0x1, /* gcFEATURE_BIT_PSIO_MSAA_CL_FIX */
+ 0x1, /* gcFEATURE_BIT_USC_DEFER_FILL_FIX */
+ 0x1, /* gcFEATURE_BIT_SH_CLOCK_GATE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_NEED_DUMMYDRAW */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_OUTPUT */
+ 0x0, /* gcFEATURE_BIT_PE2D_LINEAR_YUV420_10BIT */
+ 0x0, /* gcFEATURE_BIT_MULTI_CLUSTER */
+ 0x0, /* gcFEATURE_BIT_VG_TS_CULLING */
+ 0x0, /* gcFEATURE_BIT_VG_FP25 */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK */
+ 0x0, /* gcFEATURE_BIT_SH_DUAL16_SAMPLEMASK_ZW */
+ 0x0, /* gcFEATURE_BIT_TPG_TRIVIAL_MODE_FIX */
+ 0x0, /* gcFEATURE_BIT_TX_ASTC_MULTISLICE_FIX */
+ 0x0, /* gcFEATURE_BIT_FE_ROBUST_FIX */
+ 0x0, /* gcFEATURE_BIT_SH_GPIPE_ACCESS_FULLTEMPS */
+ 0x0, /* gcFEATURE_BIT_PSIO_INTERLOCK */
+ 0x1, /* gcFEATURE_BIT_PA_WIDELINE_FIX */
+ 0x0, /* gcFEATURE_BIT_WIDELINE_HELPER_FIX */
+ 0x0, /* gcFEATURE_BIT_G2D_3rd_PARTY_COMPRESSION_1_1 */
+ 0x0, /* gcFEATURE_BIT_TX_FLUSH_L1CACHE */
+ 0x1, /* gcFEATURE_BIT_PE_DITHER_FIX2 */
+ 0x0, /* gcFEATURE_BIT_G2D_DEC400 */
+ 0x0, /* gcFEATURE_BIT_SH_TEXLD_U_FIX */
+ 0x0, /* gcFEATURE_BIT_MC_FCCACHE_BYTEMASK */
+ 0x0, /* gcFEATURE_BIT_SH_MULTI_WG_PACK_FIX */
+ 0x0, /* gcFEATURE_BIT_DC_OVERLAY_SCALING */
+ 0x0, /* gcFEATURE_BIT_PE_ADVANCE_BLEND_PART0 */
+ 0x0, /* gcFEATURE_BIT_FE_PATCHLIST_FETCH_FIX */
+ 0x1, /* gcFEATURE_BIT_RA_CG_FIX */
+ 0x0, /* gcFEATURE_BIT_EVIS_VX2 */
+ 0x0, /* gcFEATURE_BIT_NN_FLOAT */
+ 0x0, /* gcFEATURE_BIT_DEC400 */
+ 0x0, /* gcFEATURE_BIT_LS_SUPPORT_PERCOMP_DEPENDENCY */
+ 0x0, /* gcFEATURE_BIT_TP_ENGINE */
+ 0x0, /* gcFEATURE_BIT_MULTI_CORE_BLOCK_SET_CONFIG2 */
+ 0x0, /* gcFEATURE_BIT_PE_VMSAA_COVERAGE_CACHE_FIX */
+ 0x1, /* gcFEATURE_BIT_SECURITY_AHB */
+ 0x0, /* gcFEATURE_BIT_MULTICORE_SEMAPHORESTALL_V3 */
+ 0x0, /* gcFEATURE_BIT_SMALLBATCH */
+ 0x1, /* gcFEATURE_BIT_SH_CMPLX */
+ 0x1, /* gcFEATURE_BIT_SH_IDIV0_SWZL_EHS */
+ 0x0, /* gcFEATURE_BIT_TX_LERP_LESS_BIT */
+ 0x1, /* gcFEATURE_BIT_SH_GM_ENDIAN */
+ 0x1, /* gcFEATURE_BIT_SH_GM_USC_UNALLOC */
+ 0x1, /* gcFEATURE_BIT_SH_END_OF_BB */
+ 0x0, /* gcFEATURE_BIT_VIP_V7 */
+ },
+};
+
+static gcsFEATURE_DATABASE*
+gcQueryFeatureDB(
+ gctUINT32 ChipID,
+ gctUINT32 ChipVersion,
+ gctUINT32 ProductID,
+ gctUINT32 EcoID,
+ gctUINT32 CustomerID
+ )
+{
+ gctINT entryNum = sizeof(gChipInfo) / sizeof(gChipInfo[0]);
+ gctINT i;
+
+ /* check formal release entries first */
+ for (i = 0; i < entryNum; ++i)
+ {
+
+ if ((gChipInfo[i].chipID == ChipID)
+ && (gChipInfo[i].chipVersion == ChipVersion)
+ && (gChipInfo[i].productID == ProductID)
+ && (gChipInfo[i].ecoID == EcoID)
+ && (gChipInfo[i].customerID == CustomerID)
+ && (gChipInfo[i].formalRelease)
+ )
+ {
+ return &gChipInfo[i];
+ }
+ }
+
+ /* check informal release entries if we dont find in formal entries */
+ for (i = 0; i < entryNum; ++i)
+ {
+
+ if ((gChipInfo[i].chipID == ChipID)
+ && ((gChipInfo[i].chipVersion & 0xFFF0) == (ChipVersion & 0xFFF0))
+ && (gChipInfo[i].productID == ProductID)
+ && (gChipInfo[i].ecoID == EcoID)
+ && (gChipInfo[i].customerID == CustomerID)
+ && (!gChipInfo[i].formalRelease)
+ )
+ {
+ return &gChipInfo[i];
+ }
+ }
+
+ return gcvNULL;
+}
+#endif /* _gc_feature_database_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
new file mode 100644
index 000000000000..bb181768bab5
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
@@ -0,0 +1,2832 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_h_
+#define __gc_hal_h_
+
+#include "gc_hal_rename.h"
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+#include "gc_hal_profiler.h"
+#include "gc_hal_driver.h"
+#if gcdENABLE_3D
+#include "gc_hal_statistics.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* Alignment Macros *******************************
+\******************************************************************************/
+
+/* Alignment with a non-power of two value. */
+#define gcmALIGN_NP2(n, align) \
+( \
+ ((n) + (align) - 1) - (((n) + (align) - 1) % (align)) \
+)
+
+/* Alignment with a power of two value. */
+#define gcmALIGN(n, align) \
+( \
+ ((n) + ((align) - 1)) & ~((align) - 1) \
+)
+
+#define gcmALIGN_BASE(n, align) \
+( \
+ ((n) & ~((align) - 1)) \
+)
+
+/******************************************************************************\
+***************************** Element Count Macro *****************************
+\******************************************************************************/
+
+#define gcmSIZEOF(a) \
+( \
+ (gctSIZE_T) (sizeof(a)) \
+)
+
+#define gcmCOUNTOF(a) \
+( \
+ sizeof(a) / sizeof(a[0]) \
+)
+
+/******************************************************************************\
+********************************* Cast Macro **********************************
+\******************************************************************************/
+#define gcmNAME_TO_PTR(na) \
+ gckKERNEL_QueryPointerFromName(kernel, gcmALL_TO_UINT32(na))
+
+#define gcmPTR_TO_NAME(ptr) \
+ gckKERNEL_AllocateNameFromPointer(kernel, ptr)
+
+#define gcmRELEASE_NAME(na) \
+ gckKERNEL_DeleteName(kernel, gcmALL_TO_UINT32(na))
+
+#define gcmALL_TO_UINT32(t) \
+( \
+ (gctUINT32) (gctUINTPTR_T) (t)\
+)
+
+#define gcmPTR_TO_UINT64(p) \
+( \
+ (gctUINT64) (gctUINTPTR_T) (p)\
+)
+
+#define gcmUINT64_TO_PTR(u) \
+( \
+ (gctPOINTER) (gctUINTPTR_T) (u)\
+)
+
+#define gcmUINT64_TO_TYPE(u, t) \
+( \
+ (t) (gctUINTPTR_T) (u)\
+)
+
+/******************************************************************************\
+******************************** Useful Macro *********************************
+\******************************************************************************/
+
+#define gcvINVALID_ADDRESS ~0U
+#define gcvINVALID_VALUE 0xCCCCCCCC
+
+#define gcmGET_PRE_ROTATION(rotate) \
+ ((rotate) & (~(gcvSURF_POST_FLIP_X | gcvSURF_POST_FLIP_Y)))
+
+#define gcmGET_POST_ROTATION(rotate) \
+ ((rotate) & (gcvSURF_POST_FLIP_X | gcvSURF_POST_FLIP_Y))
+
+/******************************************************************************\
+******************************** gcsOBJECT Object *******************************
+\******************************************************************************/
+
+/* Type of objects. */
+typedef enum _gceOBJECT_TYPE
+{
+ gcvOBJ_UNKNOWN = 0,
+ gcvOBJ_2D = gcmCC('2','D',' ',' '),
+ gcvOBJ_3D = gcmCC('3','D',' ',' '),
+ gcvOBJ_ATTRIBUTE = gcmCC('A','T','T','R'),
+ gcvOBJ_BRUSHCACHE = gcmCC('B','R','U','$'),
+ gcvOBJ_BRUSHNODE = gcmCC('B','R','U','n'),
+ gcvOBJ_BRUSH = gcmCC('B','R','U','o'),
+ gcvOBJ_BUFFER = gcmCC('B','U','F','R'),
+ gcvOBJ_COMMAND = gcmCC('C','M','D',' '),
+ gcvOBJ_COMMANDBUFFER = gcmCC('C','M','D','B'),
+ gcvOBJ_CONTEXT = gcmCC('C','T','X','T'),
+ gcvOBJ_DEVICE = gcmCC('D','E','V',' '),
+ gcvOBJ_DUMP = gcmCC('D','U','M','P'),
+ gcvOBJ_EVENT = gcmCC('E','V','N','T'),
+ gcvOBJ_FUNCTION = gcmCC('F','U','N','C'),
+ gcvOBJ_HAL = gcmCC('H','A','L',' '),
+ gcvOBJ_HARDWARE = gcmCC('H','A','R','D'),
+ gcvOBJ_HEAP = gcmCC('H','E','A','P'),
+ gcvOBJ_INDEX = gcmCC('I','N','D','X'),
+ gcvOBJ_INTERRUPT = gcmCC('I','N','T','R'),
+ gcvOBJ_KERNEL = gcmCC('K','E','R','N'),
+ gcvOBJ_KERNEL_FUNCTION = gcmCC('K','F','C','N'),
+ gcvOBJ_MEMORYBUFFER = gcmCC('M','E','M','B'),
+ gcvOBJ_MMU = gcmCC('M','M','U',' '),
+ gcvOBJ_OS = gcmCC('O','S',' ',' '),
+ gcvOBJ_OUTPUT = gcmCC('O','U','T','P'),
+ gcvOBJ_PAINT = gcmCC('P','N','T',' '),
+ gcvOBJ_PATH = gcmCC('P','A','T','H'),
+ gcvOBJ_QUEUE = gcmCC('Q','U','E',' '),
+ gcvOBJ_SAMPLER = gcmCC('S','A','M','P'),
+ gcvOBJ_SHADER = gcmCC('S','H','D','R'),
+ gcvOBJ_VIR_SHADER = gcmCC('V','S','D','R'),
+ gcvOBJ_STREAM = gcmCC('S','T','R','M'),
+ gcvOBJ_SURF = gcmCC('S','U','R','F'),
+ gcvOBJ_TEXTURE = gcmCC('T','X','T','R'),
+ gcvOBJ_UNIFORM = gcmCC('U','N','I','F'),
+ gcvOBJ_VARIABLE = gcmCC('V','A','R','I'),
+ gcvOBJ_VERTEX = gcmCC('V','R','T','X'),
+ gcvOBJ_VIDMEM = gcmCC('V','M','E','M'),
+ gcvOBJ_VG = gcmCC('V','G',' ',' '),
+ gcvOBJ_BUFOBJ = gcmCC('B','U','F','O'),
+ gcvOBJ_UNIFORM_BLOCK = gcmCC('U','B','L','K'),
+ gcvOBJ_CL = gcmCC('C','L',' ',' '),
+ gcvOBJ_STORAGE_BLOCK = gcmCC('S','B','L','K'),
+ gcvOBJ_IO_BLOCK = gcmCC('I','O','B','K'),
+}
+gceOBJECT_TYPE;
+
+/* gcsOBJECT object defintinon. */
+typedef struct _gcsOBJECT
+{
+ /* Type of an object. */
+ gceOBJECT_TYPE type;
+}
+gcsOBJECT;
+
+typedef struct _gckHARDWARE * gckHARDWARE;
+
+
+#define gcdMAX_GPU_COUNT gcvCORE_COUNT
+
+#define gcdMAX_SURF_LAYERS 4
+
+#define gcdMAX_DRAW_BUFFERS 8
+
+/*******************************************************************************
+**
+** gcmVERIFY_OBJECT
+**
+** Assert if an object is invalid or is not of the specified type. If the
+** object is invalid or not of the specified type, gcvSTATUS_INVALID_OBJECT
+** will be returned from the current function. In retail mode this macro
+** does nothing.
+**
+** ARGUMENTS:
+**
+** obj Object to test.
+** t Expected type of the object.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+#define _gcmVERIFY_OBJECT(prefix, obj, t) \
+ if ((obj) == gcvNULL) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT failed: NULL"); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT((obj) != gcvNULL); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+ return gcvSTATUS_INVALID_OBJECT; \
+ } \
+ else if (((gcsOBJECT*) (obj))->type != t) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT failed: %c%c%c%c", \
+ gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+ return gcvSTATUS_INVALID_OBJECT; \
+ }
+
+# define gcmVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcm, obj, t)
+# define gcmkVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcmk, obj, t)
+#else
+# define gcmVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
+# define gcmkVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
+#endif
+
+/******************************************************************************/
+/*VERIFY_OBJECT if special return expected*/
+/******************************************************************************/
+#ifndef EGL_API_ANDROID
+# define _gcmVERIFY_OBJECT_RETURN(prefix, obj, t, retVal) \
+ do \
+ { \
+ if ((obj) == gcvNULL) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT_RETURN failed: NULL"); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT((obj) != gcvNULL); \
+ prefix##FOOTER_ARG("retVal=%d", retVal); \
+ return retVal; \
+ } \
+ else if (((gcsOBJECT*) (obj))->type != t) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT_RETURN failed: %c%c%c%c", \
+ gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
+ prefix##FOOTER_ARG("retVal=%d", retVal); \
+ return retVal; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_OBJECT_RETURN(obj, t, retVal) \
+ _gcmVERIFY_OBJECT_RETURN(gcm, obj, t, retVal)
+# define gcmkVERIFY_OBJECT_RETURN(obj, t, retVal) \
+ _gcmVERIFY_OBJECT_RETURN(gcmk, obj, t, retVal)
+#else
+# define gcmVERIFY_OBJECT_RETURN(obj, t) do {} while (gcvFALSE)
+# define gcmVERIFY_OBJECT_RETURN(obj, t) do {} while (gcvFALSE)
+#endif
+
+/******************************************************************************\
+********************************** gckOS Object *********************************
+\******************************************************************************/
+
+/* Construct a new gckOS object. */
+gceSTATUS
+gckOS_Construct(
+ IN gctPOINTER Context,
+ OUT gckOS * Os
+ );
+
+/* Destroy an gckOS object. */
+gceSTATUS
+gckOS_Destroy(
+ IN gckOS Os
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gckOS_QueryVideoMemory(
+ IN gckOS Os,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free allocated memory. */
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Wrapper for allocation memory.. */
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Wrapper for freeing memory. */
+gceSTATUS
+gckOS_FreeMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctUINT32 Flag,
+ IN gctSIZE_T Bytes,
+ OUT gctUINT32 * Gid,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/* Lock pages. */
+gceSTATUS
+gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Cacheable,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ );
+
+/* Map pages. */
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ );
+
+/* Map pages. */
+gceSTATUS
+gckOS_MapPagesEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctUINT32 Address,
+ IN gctPOINTER PageTable,
+ IN gctBOOL Writable,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+gckOS_UnmapPages(
+ IN gckOS Os,
+ IN gctSIZE_T PageCount,
+ IN gctUINT32 Address
+ );
+
+/* Unlock pages. */
+gceSTATUS
+gckOS_UnlockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Free paged memory. */
+gceSTATUS
+gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Allocate non-paged memory. */
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free non-paged memory. */
+gceSTATUS
+gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free contiguous memory. */
+gceSTATUS
+gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Get the number fo bytes per page. */
+gceSTATUS
+gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ );
+
+/* Get the physical address of a corresponding logical address. */
+gceSTATUS
+gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Address
+ );
+
+/* Get the physical address of a corresponding user logical address. */
+gceSTATUS
+gckOS_UserLogicalToPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Address
+ );
+
+/* Map physical memory. */
+gceSTATUS
+gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap previously mapped physical memory. */
+gceSTATUS
+gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Get real physical address from descriptor. */
+gceSTATUS
+gckOS_PhysicalToPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Physical,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * PhysicalAddress
+ );
+
+/* Read data from a hardware register. */
+gceSTATUS
+gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+/* Read data from a hardware register. */
+gceSTATUS
+gckOS_ReadRegisterEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegisterEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Write data to a 32-bit memory location. */
+gceSTATUS
+gckOS_WriteMemory(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ );
+
+/* Map physical memory into the process space. */
+gceSTATUS
+gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap physical memory from the specified process space. */
+gceSTATUS
+gckOS_UnmapMemoryEx(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical,
+ IN gctUINT32 PID
+ );
+
+/* Unmap physical memory from the process space. */
+gceSTATUS
+gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Unmap user logical memory out of physical memory.
+ * This function is only supported in Linux currently.
+ */
+gceSTATUS
+gckOS_UnmapUserLogical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Delete a mutex. */
+gceSTATUS
+gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Acquire a mutex. */
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a mutex. */
+gceSTATUS
+gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Atomically exchange a pair of 32-bit values. */
+gceSTATUS
+gckOS_AtomicExchange(
+ IN gckOS Os,
+ IN OUT gctUINT32_PTR Target,
+ IN gctUINT32 NewValue,
+ OUT gctUINT32_PTR OldValue
+ );
+
+/* Atomically exchange a pair of pointers. */
+gceSTATUS
+gckOS_AtomicExchangePtr(
+ IN gckOS Os,
+ IN OUT gctPOINTER * Target,
+ IN gctPOINTER NewValue,
+ OUT gctPOINTER * OldValue
+ );
+
+gceSTATUS
+gckOS_AtomSetMask(
+ IN gctPOINTER Atom,
+ IN gctUINT32 Mask
+ );
+
+gceSTATUS
+gckOS_AtomClearMask(
+ IN gctPOINTER Atom,
+ IN gctUINT32 Mask
+ );
+
+gceSTATUS
+gckOS_DumpCallStack(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_GetProcessNameByPid(
+ IN gctINT Pid,
+ IN gctSIZE_T Length,
+ OUT gctUINT8_PTR String
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomConstruct
+**
+** Create an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Atom
+** Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+ IN gckOS Os,
+ OUT gctPOINTER * Atom
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomDestroy
+**
+** Destroy an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+ IN gckOS Os,
+ OUT gctPOINTER Atom
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomGet
+**
+** Get the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomSet
+**
+** Set the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** gctINT32 Value
+** The value of the atom.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomSet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ IN gctINT32 Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomIncrement
+**
+** Atomically increment the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomDecrement
+**
+** Atomically decrement the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/* Delay a number of milliseconds. */
+gceSTATUS
+gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ );
+
+/* Get time in milliseconds. */
+gceSTATUS
+gckOS_GetTicks(
+ OUT gctUINT32_PTR Time
+ );
+
+/* Compare time value. */
+gceSTATUS
+gckOS_TicksAfter(
+ IN gctUINT32 Time1,
+ IN gctUINT32 Time2,
+ OUT gctBOOL_PTR IsAfter
+ );
+
+/* Get time in microseconds. */
+gceSTATUS
+gckOS_GetTime(
+ OUT gctUINT64_PTR Time
+ );
+
+/* Memory barrier. */
+gceSTATUS
+gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ );
+
+/* Map user pointer. */
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Unmap user pointer. */
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ );
+
+/*******************************************************************************
+**
+** gckOS_QueryNeedCopy
+**
+** Query whether the memory can be accessed or mapped directly or it has to be
+** copied.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID of the current process.
+**
+** OUTPUT:
+**
+** gctBOOL_PTR NeedCopy
+** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
+** gcvFALSE if the memory can be accessed or mapped dircetly.
+*/
+gceSTATUS
+gckOS_QueryNeedCopy(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ OUT gctBOOL_PTR NeedCopy
+ );
+
+/*******************************************************************************
+**
+** gckOS_CopyFromUserData
+**
+** Copy data from user to kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER KernelPointer
+** Pointer to kernel memory.
+**
+** gctPOINTER Pointer
+** Pointer to user memory.
+**
+** gctSIZE_T Size
+** Number of bytes to copy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_CopyFromUserData(
+ IN gckOS Os,
+ IN gctPOINTER KernelPointer,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size
+ );
+
+/*******************************************************************************
+**
+** gckOS_CopyToUserData
+**
+** Copy data from kernel to user memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER KernelPointer
+** Pointer to kernel memory.
+**
+** gctPOINTER Pointer
+** Pointer to user memory.
+**
+** gctSIZE_T Size
+** Number of bytes to copy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_CopyToUserData(
+ IN gckOS Os,
+ IN gctPOINTER KernelPointer,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size
+ );
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_SuspendInterruptEx(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_ResumeInterruptEx(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+/* Perform a memory copy. */
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ );
+
+/* Zero memory. */
+gceSTATUS
+gckOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Device I/O control to the kernel HAL layer. */
+gceSTATUS
+gckOS_DeviceControl(
+ IN gckOS Os,
+ IN gctBOOL FromUser,
+ IN gctUINT32 IoControlCode,
+ IN gctPOINTER InputBuffer,
+ IN gctSIZE_T InputBufferSize,
+ OUT gctPOINTER OutputBuffer,
+ IN gctSIZE_T OutputBufferSize
+ );
+
+/*******************************************************************************
+**
+** gckOS_GetProcessID
+**
+** Get current process ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ProcessID
+** Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+ OUT gctUINT32_PTR ProcessID
+ );
+
+gceSTATUS
+gckOS_GetCurrentProcessID(
+ OUT gctUINT32_PTR ProcessID
+ );
+
+/*******************************************************************************
+**
+** gckOS_GetThreadID
+**
+** Get current thread ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ThreadID
+** Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+ OUT gctUINT32_PTR ThreadID
+ );
+
+/******************************************************************************\
+********************************** Signal Object *********************************
+\******************************************************************************/
+
+/* Create a signal. */
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ );
+
+/* Destroy a signal. */
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Signal a signal. */
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL Interruptable,
+ IN gctUINT32 Wait
+ );
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckOS_SignalPulse(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+gceSTATUS
+gckOS_SignalPending(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+#endif
+
+/* Map a user signal to the kernel space. */
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ );
+
+/* Unmap a user signal */
+gceSTATUS
+gckOS_UnmapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Map user memory. */
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ );
+
+/* Wrap a user memory to gctPHYS_ADDR. */
+gceSTATUS
+gckOS_WrapMemory(
+ IN gckOS Os,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gctSIZE_T *Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctBOOL *Contiguous
+ );
+
+gceSTATUS
+gckOS_GetPolicyID(
+ IN gckOS Os,
+ IN gceSURF_TYPE Type,
+ OUT gctUINT32_PTR PolicyID,
+ OUT gctUINT32_PTR AXIConfig
+ );
+
+/******************************************************************************\
+************************** Android Native Fence Sync ***************************
+\******************************************************************************/
+gceSTATUS
+gckOS_CreateSyncTimeline(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctHANDLE * Timeline
+ );
+
+gceSTATUS
+gckOS_DestroySyncTimeline(
+ IN gckOS Os,
+ IN gctHANDLE Timeline
+ );
+
+gceSTATUS
+gckOS_CreateNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctSIGNAL Signal,
+ OUT gctINT * FenceFD
+ );
+
+gceSTATUS
+gckOS_WaitNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ );
+
+#if !USE_NEW_LINUX_SIGNAL
+/* Create signal to be used in the user space. */
+gceSTATUS
+gckOS_CreateUserSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctINT * SignalID
+ );
+
+/* Destroy signal used in the user space. */
+gceSTATUS
+gckOS_DestroyUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID
+ );
+
+/* Wait for signal used in the user space. */
+gceSTATUS
+gckOS_WaitUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctUINT32 Wait
+ );
+
+/* Signal a signal used in the user space. */
+gceSTATUS
+gckOS_SignalUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctBOOL State
+ );
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+/* Set a signal owned by a process. */
+#if defined(__QNXNTO__)
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctINT Recvid,
+ IN gctINT Coid
+ );
+#else
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ );
+#endif
+
+/******************************************************************************\
+** Cache Support
+*/
+
+gceSTATUS
+gckOS_CacheClean(
+ gckOS Os,
+ gctUINT32 ProcessID,
+ gctPHYS_ADDR Handle,
+ gctPHYS_ADDR_T Physical,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gckOS_CacheFlush(
+ gckOS Os,
+ gctUINT32 ProcessID,
+ gctPHYS_ADDR Handle,
+ gctPHYS_ADDR_T Physical,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gckOS_CacheInvalidate(
+ gckOS Os,
+ gctUINT32 ProcessID,
+ gctPHYS_ADDR Handle,
+ gctPHYS_ADDR_T Physical,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gckOS_CPUPhysicalToGPUPhysical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR_T CPUPhysical,
+ IN gctPHYS_ADDR_T * GPUPhysical
+ );
+
+gceSTATUS
+gckOS_GPUPhysicalToCPUPhysical(
+ IN gckOS Os,
+ IN gctUINT32 GPUPhysical,
+ IN gctPHYS_ADDR_T * CPUPhysical
+ );
+
+gceSTATUS
+gckOS_QueryOption(
+ IN gckOS Os,
+ IN gctCONST_STRING Option,
+ OUT gctUINT32 * Value
+ );
+
+/******************************************************************************\
+** Debug Support
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ );
+
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ );
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ );
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ );
+
+void
+gckOS_SetDebugFile(
+ IN gctCONST_STRING FileName
+ );
+
+/*******************************************************************************
+** Broadcast interface.
+*/
+
+typedef enum _gceBROADCAST
+{
+ /* GPU might be idle. */
+ gcvBROADCAST_GPU_IDLE,
+
+ /* A commit is going to happen. */
+ gcvBROADCAST_GPU_COMMIT,
+
+ /* GPU seems to be stuck. */
+ gcvBROADCAST_GPU_STUCK,
+
+ /* First process gets attached. */
+ gcvBROADCAST_FIRST_PROCESS,
+
+ /* Last process gets detached. */
+ gcvBROADCAST_LAST_PROCESS,
+
+ /* AXI bus error. */
+ gcvBROADCAST_AXI_BUS_ERROR,
+
+ /* Out of memory. */
+ gcvBROADCAST_OUT_OF_MEMORY,
+}
+gceBROADCAST;
+
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ );
+
+gceSTATUS
+gckOS_BroadcastHurry(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT Urgency
+ );
+
+gceSTATUS
+gckOS_BroadcastCalibrateSpeed(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT Idle,
+ IN gctUINT Time
+ );
+
+/*******************************************************************************
+**
+** gckOS_SetGPUPower
+**
+** Set the power of the GPU on or off.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gceCORE Core
+** GPU whose power is set.
+**
+** gctBOOL Clock
+** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+** gctBOOL Power
+** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ );
+
+gceSTATUS
+gckOS_ResetGPU(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+gceSTATUS
+gckOS_PrepareGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+gceSTATUS
+gckOS_FinishGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core
+ );
+
+gceSTATUS
+gckOS_QueryGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctUINT32 * Frequency,
+ OUT gctUINT8 * Scale
+ );
+
+gceSTATUS
+gckOS_SetGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT8 Scale
+ );
+
+/*******************************************************************************
+** Semaphores.
+*/
+
+/* Create a new semaphore. */
+gceSTATUS
+gckOS_CreateSemaphore(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ );
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_CreateSemaphoreVG(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ );
+#endif
+
+/* Delete a semahore. */
+gceSTATUS
+gckOS_DestroySemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Acquire a semahore. */
+gceSTATUS
+gckOS_AcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Try to acquire a semahore. */
+gceSTATUS
+gckOS_TryAcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Release a semahore. */
+gceSTATUS
+gckOS_ReleaseSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/*******************************************************************************
+** Timer API.
+*/
+
+typedef void (*gctTIMERFUNCTION)(gctPOINTER);
+
+/* Create a timer. */
+gceSTATUS
+gckOS_CreateTimer(
+ IN gckOS Os,
+ IN gctTIMERFUNCTION Function,
+ IN gctPOINTER Data,
+ OUT gctPOINTER * Timer
+ );
+
+/* Destory a timer. */
+gceSTATUS
+gckOS_DestroyTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer
+ );
+
+/* Start a timer. */
+gceSTATUS
+gckOS_StartTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer,
+ IN gctUINT32 Delay
+ );
+
+/* Stop a timer. */
+gceSTATUS
+gckOS_StopTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer
+ );
+
+/******************************************************************************\
+********************************* gckHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gckHEAP * gckHEAP;
+
+/* Construct a new gckHEAP object. */
+gceSTATUS
+gckHEAP_Construct(
+ IN gckOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gckHEAP * Heap
+ );
+
+/* Destroy an gckHEAP object. */
+gceSTATUS
+gckHEAP_Destroy(
+ IN gckHEAP Heap
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gckHEAP_Allocate(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gckHEAP_Free(
+ IN gckHEAP Heap,
+ IN gctPOINTER Node
+ );
+
+/* Profile the heap. */
+gceSTATUS
+gckHEAP_ProfileStart(
+ IN gckHEAP Heap
+ );
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+ IN gckHEAP Heap,
+ IN gctCONST_STRING Title
+ );
+
+
+/******************************************************************************\
+******************************** gckVIDMEM Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVIDMEM * gckVIDMEM;
+typedef struct _gckKERNEL * gckKERNEL;
+typedef struct _gckDB * gckDB;
+typedef struct _gckDVFS * gckDVFS;
+typedef struct _gcsASYNC_COMMAND * gckASYNC_COMMAND;
+typedef struct _gckMMU * gckMMU;
+typedef struct _gcsDEVICE * gckDEVICE;
+
+/* Construct a new gckVIDMEM object. */
+gceSTATUS
+gckVIDMEM_Construct(
+ IN gckOS Os,
+ IN gctUINT32 BaseAddress,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Threshold,
+ IN gctSIZE_T Banking,
+ OUT gckVIDMEM * Memory
+ );
+
+/* Destroy an gckVDIMEM object. */
+gceSTATUS
+gckVIDMEM_Destroy(
+ IN gckVIDMEM Memory
+ );
+
+/* Allocate linear memory. */
+gceSTATUS
+gckVIDMEM_AllocateLinear(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM Memory,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+ IN gctBOOL Specified,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gckVIDMEM_Free(
+ IN gckKERNEL Kernel,
+ IN gcuVIDMEM_NODE_PTR Node
+ );
+
+/* Lock memory. */
+gceSTATUS
+gckVIDMEM_Lock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gctBOOL Cacheable,
+ OUT gctUINT32 * Address,
+ OUT gctUINT32 * Gid,
+ OUT gctUINT64 * PhysicalAddress
+ );
+
+/* Unlock memory. */
+gceSTATUS
+gckVIDMEM_Unlock(
+ IN gckKERNEL Kernel,
+ IN gckVIDMEM_NODE Node,
+ IN gceSURF_TYPE Type,
+ IN OUT gctBOOL * Asynchroneous
+ );
+
+/* Construct a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 Flag,
+ IN gctSIZE_T Bytes,
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Destroy a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+ IN gcuVIDMEM_NODE_PTR Node
+ );
+
+gceSTATUS
+gckVIDMEM_SetCommitStamp(
+ IN gckKERNEL Kernel,
+ IN gceENGINE Engine,
+ IN gctUINT32 Handle,
+ IN gctUINT64 CommitStamp
+ );
+
+gceSTATUS
+gckVIDMEM_GetCommitStamp(
+ IN gckKERNEL Kernel,
+ IN gceENGINE Engine,
+ IN gctUINT32 Handle,
+ OUT gctUINT64_PTR CommitStamp
+ );
+
+/******************************************************************************\
+******************************** gckKERNEL Object ******************************
+\******************************************************************************/
+
+struct _gcsHAL_INTERFACE;
+
+/* Notifications. */
+typedef enum _gceNOTIFY
+{
+ gcvNOTIFY_INTERRUPT,
+ gcvNOTIFY_COMMAND_QUEUE,
+}
+gceNOTIFY;
+
+/* Flush flags. */
+typedef enum _gceKERNEL_FLUSH
+{
+ gcvFLUSH_COLOR = 0x01,
+ gcvFLUSH_DEPTH = 0x02,
+ gcvFLUSH_TEXTURE = 0x04,
+ gcvFLUSH_2D = 0x08,
+ gcvFLUSH_L2 = 0x10,
+ gcvFLUSH_TILE_STATUS = 0x20,
+ gcvFLUSH_ICACHE = 0x40,
+ gcvFLUSH_TXDESC = 0x80,
+ gcvFLUSH_FENCE = 0x100,
+ gcvFLUSH_VERTEX = 0x200,
+ gcvFLUSH_TFBHEADER = 0x400,
+ gcvFLUSH_ALL = gcvFLUSH_COLOR
+ | gcvFLUSH_DEPTH
+ | gcvFLUSH_TEXTURE
+ | gcvFLUSH_2D
+ | gcvFLUSH_L2
+ | gcvFLUSH_TILE_STATUS
+ | gcvFLUSH_ICACHE
+ | gcvFLUSH_TXDESC
+ | gcvFLUSH_FENCE
+ | gcvFLUSH_VERTEX
+ | gcvFLUSH_TFBHEADER
+}
+gceKERNEL_FLUSH;
+
+/* Construct a new gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Construct(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT ChipID,
+ IN gctPOINTER Context,
+ IN gckDEVICE Device,
+ IN gckDB SharedDB,
+ OUT gckKERNEL * Kernel
+ );
+
+/* Destroy an gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Destroy(
+ IN gckKERNEL Kernel
+ );
+
+/* Dispatch a user-level command. */
+gceSTATUS
+gckKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gckDEVICE Device,
+ IN gctBOOL FromUser,
+ IN OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Query Database requirements. */
+gceSTATUS
+ gckKERNEL_QueryDatabase(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcsHAL_INTERFACE * Interface
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Lookup the gckVIDMEM object for a pool. */
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ );
+
+gceSTATUS
+gckKERNEL_AllocateLinearMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcePOOL * Pool,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+ IN gctUINT32 Flag,
+ OUT gctUINT32 * Node
+ );
+
+gceSTATUS
+gckKERNEL_ReleaseVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Handle
+ );
+
+gceSTATUS
+gckKERNEL_LockVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gceCORE Core,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL FromUser,
+ IN OUT gcsHAL_INTERFACE * Interface
+ );
+
+gceSTATUS
+gckKERNEL_UnlockVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN OUT gcsHAL_INTERFACE * Interface
+ );
+
+/* Unlock video memory from gpu immediately w/o considering gpu cache flush. */
+gceSTATUS
+gckKERNEL_BottomHalfUnlockVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctUINT32 ProcessID,
+ IN gctUINT32 Node
+ );
+
+/* Map video memory. */
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes,
+#endif
+ OUT gctPOINTER * Logical
+ );
+
+/* Map video memory. */
+gceSTATUS
+gckKERNEL_MapVideoMemoryEx(
+ IN gckKERNEL Kernel,
+ IN gceCORE Core,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes,
+#endif
+ OUT gctPOINTER * Logical
+ );
+
+#ifdef __QNXNTO__
+/* Unmap video memory. */
+gceSTATUS
+gckKERNEL_UnmapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes
+ );
+#endif
+
+/* Map memory. */
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap memory. */
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Notification of events. */
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+ IN gceNOTIFY Notifcation,
+ IN gctBOOL Data
+ );
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ );
+
+/*******************************************************************************
+**
+** gckKERNEL_Recovery
+**
+** Try to recover the GPU from a fatal error.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+ IN gckKERNEL Kernel
+ );
+
+/* Get access to the user data. */
+gceSTATUS
+gckKERNEL_OpenUserData(
+ IN gckKERNEL Kernel,
+ IN gctBOOL NeedCopy,
+ IN gctPOINTER StaticStorage,
+ IN gctPOINTER UserPointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Release resources associated with the user data connection. */
+gceSTATUS
+gckKERNEL_CloseUserData(
+ IN gckKERNEL Kernel,
+ IN gctBOOL NeedCopy,
+ IN gctBOOL FlushData,
+ IN gctPOINTER UserPointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ );
+
+gceSTATUS
+gckDVFS_Construct(
+ IN gckHARDWARE Hardware,
+ OUT gckDVFS * Frequency
+ );
+
+gceSTATUS
+gckDVFS_Destroy(
+ IN gckDVFS Dvfs
+ );
+
+gceSTATUS
+gckDVFS_Start(
+ IN gckDVFS Dvfs
+ );
+
+gceSTATUS
+gckDVFS_Stop(
+ IN gckDVFS Dvfs
+ );
+
+/******************************************************************************\
+******************************* gckHARDWARE Object *****************************
+\******************************************************************************/
+
+/* Construct a new gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Construct(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gckHARDWARE * Hardware
+ );
+
+/* Destroy an gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Destroy(
+ IN gckHARDWARE Hardware
+ );
+
+/* Get hardware type. */
+gceSTATUS
+gckHARDWARE_GetType(
+ IN gckHARDWARE Hardware,
+ OUT gceHARDWARE_TYPE * Type
+ );
+
+/* Query system memory requirements. */
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ );
+
+/* Build virtual address. */
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ );
+
+/* Query command buffer requirements. */
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+ IN gckHARDWARE Hardware,
+ IN gceENGINE Engine,
+ OUT gctUINT32 * Alignment,
+ OUT gctUINT32 * ReservedHead,
+ OUT gctUINT32 * ReservedTail
+ );
+
+/* Add a WAIT/LINK pair in the command queue. */
+gceSTATUS
+gckHARDWARE_WaitLink(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN gctUINT32 Offset,
+ IN OUT gctUINT32 * Bytes,
+ OUT gctUINT32 * WaitOffset,
+ OUT gctUINT32 * WaitBytes
+ );
+
+/* Kickstart the command processor. */
+gceSTATUS
+gckHARDWARE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ IN gctSIZE_T Bytes
+ );
+
+/* Add an END command in the command queue. */
+gceSTATUS
+gckHARDWARE_End(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Address,
+ IN OUT gctUINT32 * Bytes
+ );
+
+gceSTATUS
+gckHARDWARE_ChipEnable(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gceCORE_3D_MASK ChipEnable,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a NOP command in the command queue. */
+gceSTATUS
+gckHARDWARE_Nop(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a PIPESELECT command in the command queue. */
+gceSTATUS
+gckHARDWARE_PipeSelect(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gcePIPE_SELECT Pipe,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Add a LINK command in the command queue. */
+gceSTATUS
+gckHARDWARE_Link(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FetchAddress,
+ IN gctUINT32 FetchSize,
+ IN OUT gctUINT32 * Bytes,
+ OUT gctUINT32 * Low,
+ OUT gctUINT32 * High
+ );
+
+/* Add an EVENT command in the command queue. */
+gceSTATUS
+gckHARDWARE_Event(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT8 Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Query the available memory. */
+gceSTATUS
+gckHARDWARE_QueryMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+ IN gckHARDWARE Hardware,
+ OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
+ );
+
+/* Query the shader uniforms support. */
+gceSTATUS
+gckHARDWARE_QueryShaderCaps(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT * VertexUniforms,
+ OUT gctUINT * FragmentUniforms,
+ OUT gctBOOL * UnifiedUnforms
+ );
+
+/* Split a harwdare specific address into API stuff. */
+gceSTATUS
+gckHARDWARE_SplitMemory(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ );
+
+/* Update command queue tail pointer. */
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset
+ );
+
+/* Convert logical address to hardware specific address. */
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ OUT gctUINT32 * Address
+ );
+
+/* Interrupt manager. */
+gceSTATUS
+gckHARDWARE_Interrupt(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL InterruptValid
+ );
+
+/* Program MMU. */
+gceSTATUS
+gckHARDWARE_SetMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical
+ );
+
+/* Flush the MMU. */
+gceSTATUS
+gckHARDWARE_FlushMMU(
+ IN gckHARDWARE Hardware
+ );
+
+/* Set the page table base address. */
+gceSTATUS
+gckHARDWARE_SetMMUv2(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Enable,
+ IN gctPOINTER MtlbAddress,
+ IN gceMMU_MODE Mode,
+ IN gctPOINTER SafeAddress,
+ IN gctBOOL FromPower
+ );
+
+#if gcdPROCESS_ADDRESS_SPACE
+/* Configure mmu configuration. */
+gceSTATUS
+gckHARDWARE_ConfigMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctPOINTER MtlbLogical,
+ IN gctUINT32 Offset,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctSIZE_T * WaitLinkOffset,
+ OUT gctSIZE_T * WaitLinkBytes
+ );
+#endif
+
+/* Get idle register. */
+gceSTATUS
+gckHARDWARE_GetIdle(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Wait,
+ OUT gctUINT32 * Data
+ );
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+ IN gckHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ );
+
+/* Enable/disable fast clear. */
+gceSTATUS
+gckHARDWARE_SetFastClear(
+ IN gckHARDWARE Hardware,
+ IN gctINT Enable,
+ IN gctINT Compression
+ );
+
+gceSTATUS
+gckHARDWARE_ReadInterrupt(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR IDs
+ );
+
+/* Power management. */
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+ IN gckHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ );
+
+gceSTATUS
+gckHARDWARE_SetPowerManagement(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL PowerManagement
+ );
+
+gceSTATUS
+gckHARDWARE_SetGpuProfiler(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL GpuProfiler
+ );
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+gceSTATUS
+gckHARDWARE_SetFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 FscaleValue
+ );
+
+gceSTATUS
+gckHARDWARE_GetFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT * FscaleValue,
+ IN gctUINT * MinFscaleValue,
+ IN gctUINT * MaxFscaleValue
+ );
+
+gceSTATUS
+gckHARDWARE_SetMinFscaleValue(
+ IN gckHARDWARE Hardware,
+ IN gctUINT MinFscaleValue
+ );
+#endif
+
+#if gcdPOWEROFF_TIMEOUT
+gceSTATUS
+gckHARDWARE_SetPowerOffTimeout(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Timeout
+);
+
+gceSTATUS
+gckHARDWARE_QueryPowerOffTimeout(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32* Timeout
+);
+#endif
+
+/* Profile 2D Engine. */
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+ IN gckHARDWARE Hardware,
+ OUT gcs2D_PROFILE_PTR Profile
+ );
+
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_Reset(
+ IN gckHARDWARE Hardware
+ );
+
+typedef gceSTATUS (*gctISRMANAGERFUNC)(gctPOINTER Context);
+
+gceSTATUS
+gckHARDWARE_SetIsrManager(
+ IN gckHARDWARE Hardware,
+ IN gctISRMANAGERFUNC StartIsr,
+ IN gctISRMANAGERFUNC StopIsr,
+ IN gctPOINTER Context
+ );
+
+/* Start a composition. */
+gceSTATUS
+gckHARDWARE_Compose(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Size,
+ IN gctUINT8 EventID
+ );
+
+/* Check for Hardware features. */
+gceSTATUS
+gckHARDWARE_IsFeatureAvailable(
+ IN gckHARDWARE Hardware,
+ IN gceFEATURE Feature
+ );
+
+gceSTATUS
+gckHARDWARE_DumpMMUException(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_DumpGPUState(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_InitDVFS(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_QueryLoad(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32 * Load
+ );
+
+gceSTATUS
+gckHARDWARE_SetDVFSPeroid(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Frequency
+ );
+
+gceSTATUS
+gckHARDWARE_PrepareFunctions(
+ gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_DestroyFunctions(
+ gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_SetMMUStates(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER MtlbAddress,
+ IN gceMMU_MODE Mode,
+ IN gctPOINTER SafeAddress,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ );
+
+gceSTATUS
+gckHARDWARE_QueryStateTimer(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT64_PTR Start,
+ OUT gctUINT64_PTR End,
+ OUT gctUINT64_PTR On,
+ OUT gctUINT64_PTR Off,
+ OUT gctUINT64_PTR Idle,
+ OUT gctUINT64_PTR Suspend
+ );
+
+gceSTATUS
+gckHARDWARE_Fence(
+ IN gckHARDWARE Hardware,
+ IN gceENGINE Engine,
+ IN gctPOINTER Logical,
+ IN gctUINT32 FenceAddress,
+ IN gctUINT64 FenceData,
+ IN OUT gctUINT32 * Bytes
+ );
+
+#if !gcdENABLE_VG
+/******************************************************************************\
+***************************** gckINTERRUPT Object ******************************
+\******************************************************************************/
+
+typedef struct _gckINTERRUPT * gckINTERRUPT;
+
+typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
+ IN gckKERNEL Kernel
+ );
+
+gceSTATUS
+gckINTERRUPT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckINTERRUPT * Interrupt
+ );
+
+gceSTATUS
+gckINTERRUPT_Destroy(
+ IN gckINTERRUPT Interrupt
+ );
+
+gceSTATUS
+gckINTERRUPT_SetHandler(
+ IN gckINTERRUPT Interrupt,
+ IN OUT gctINT32_PTR Id,
+ IN gctINTERRUPT_HANDLER Handler
+ );
+
+gceSTATUS
+gckINTERRUPT_Notify(
+ IN gckINTERRUPT Interrupt,
+ IN gctBOOL Valid
+ );
+#endif
+/******************************************************************************\
+******************************** gckEVENT Object *******************************
+\******************************************************************************/
+
+typedef struct _gckEVENT * gckEVENT;
+
+/* Construct a new gckEVENT object. */
+gceSTATUS
+gckEVENT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckEVENT * Event
+ );
+
+/* Destroy an gckEVENT object. */
+gceSTATUS
+gckEVENT_Destroy(
+ IN gckEVENT Event
+ );
+
+/* Reserve the next available hardware event. */
+gceSTATUS
+gckEVENT_GetEvent(
+ IN gckEVENT Event,
+ IN gctBOOL Wait,
+ OUT gctUINT8 * EventID,
+ IN gceKERNEL_WHERE Source
+ );
+
+/* Add a new event to the list of events. */
+gceSTATUS
+gckEVENT_AddList(
+ IN gckEVENT Event,
+ IN gcsHAL_INTERFACE_PTR Interface,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctBOOL AllocateAllowed,
+ IN gctBOOL FromKernel
+ );
+
+/* Schedule a FreeNonPagedMemory event. */
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeContiguousMemory event. */
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeVideoMemory event. */
+gceSTATUS
+gckEVENT_FreeVideoMemory(
+ IN gckEVENT Event,
+ IN gcuVIDMEM_NODE_PTR VideoMemory,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a signal event. */
+gceSTATUS
+gckEVENT_Signal(
+ IN gckEVENT Event,
+ IN gctSIGNAL Signal,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule an Unlock event. */
+gceSTATUS
+gckEVENT_Unlock(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctPOINTER Node,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+gckEVENT_CommitDone(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gckCONTEXT Context
+ );
+
+/* Schedule a FreeVirtualCommandBuffer event. */
+gceSTATUS
+gckEVENT_DestroyVirtualCommandBuffer(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+gceSTATUS
+gckEVENT_Submit(
+ IN gckEVENT Event,
+ IN gctBOOL Wait,
+ IN gctBOOL FromPower
+ );
+
+gceSTATUS
+gckEVENT_Commit(
+ IN gckEVENT Event,
+ IN gcsQUEUE_PTR Queue
+ );
+
+/* Schedule a composition event. */
+gceSTATUS
+gckEVENT_Compose(
+ IN gckEVENT Event,
+ IN gcsHAL_COMPOSE_PTR Info
+ );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Notify(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Interrupt(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ );
+
+gceSTATUS
+gckEVENT_Dump(
+ IN gckEVENT Event
+ );
+/******************************************************************************\
+******************************* gckCOMMAND Object ******************************
+\******************************************************************************/
+
+typedef struct _gckCOMMAND * gckCOMMAND;
+
+/* Construct a new gckCOMMAND object. */
+gceSTATUS
+gckCOMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckCOMMAND * Command
+ );
+
+/* Destroy an gckCOMMAND object. */
+gceSTATUS
+gckCOMMAND_Destroy(
+ IN gckCOMMAND Command
+ );
+
+/* Acquire command queue synchronization objects. */
+gceSTATUS
+gckCOMMAND_EnterCommit(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ );
+
+/* Release command queue synchronization objects. */
+gceSTATUS
+gckCOMMAND_ExitCommit(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ );
+
+/* Start the command queue. */
+gceSTATUS
+gckCOMMAND_Start(
+ IN gckCOMMAND Command
+ );
+
+/* Stop the command queue. */
+gceSTATUS
+gckCOMMAND_Stop(
+ IN gckCOMMAND Command
+ );
+
+gceSTATUS
+gckCOMMAND_Commit(
+ IN gckCOMMAND Command,
+ IN gckCONTEXT Context,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcsSTATE_DELTA_PTR StateDelta,
+ IN gcsQUEUE_PTR EventQueue,
+ IN gctUINT32 ProcessID,
+ IN gctBOOL Shared,
+ IN gctUINT32 Index,
+ OUT gctUINT64_PTR CommitStamp,
+ OUT gctBOOL_PTR ContextSwitched
+ );
+
+/* Reserve space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Reserve(
+ IN gckCOMMAND Command,
+ IN gctUINT32 RequestedBytes,
+ OUT gctPOINTER * Buffer,
+ OUT gctUINT32 * BufferSize
+ );
+
+/* Execute reserved space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Execute(
+ IN gckCOMMAND Command,
+ IN gctUINT32 RequstedBytes
+ );
+
+/* Stall the command queue. */
+gceSTATUS
+gckCOMMAND_Stall(
+ IN gckCOMMAND Command,
+ IN gctBOOL FromPower
+ );
+
+/* Attach user process. */
+gceSTATUS
+gckCOMMAND_Attach(
+ IN gckCOMMAND Command,
+ OUT gckCONTEXT * Context,
+ OUT gctSIZE_T * MaxState,
+ OUT gctUINT32 * NumStates,
+ IN gctUINT32 ProcessID
+ );
+
+/* Detach user process. */
+gceSTATUS
+gckCOMMAND_Detach(
+ IN gckCOMMAND Command,
+ IN gckCONTEXT Context
+ );
+
+/* Dump command buffer being executed by GPU. */
+gceSTATUS
+gckCOMMAND_DumpExecutingBuffer(
+ IN gckCOMMAND Command
+ );
+
+/* Whether a kernel command buffer address. */
+gceSTATUS
+gckCOMMAND_AddressInKernelCommandBuffer(
+ IN gckCOMMAND Command,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Pointer
+ );
+
+/******************************************************************************\
+********************************* gckMMU Object ********************************
+\******************************************************************************/
+
+/* Construct a new gckMMU object. */
+gceSTATUS
+gckMMU_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ );
+
+/* Destroy an gckMMU object. */
+gceSTATUS
+gckMMU_Destroy(
+ IN gckMMU Mmu
+ );
+
+/* Allocate pages inside the MMU. */
+gceSTATUS
+gckMMU_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ );
+
+gceSTATUS
+gckMMU_AllocatePagesEx(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ IN gceSURF_TYPE Type,
+ IN gctBOOL Secure,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ );
+
+/* Remove a page table from the MMU. */
+gceSTATUS
+gckMMU_FreePages(
+ IN gckMMU Mmu,
+ IN gctBOOL Secure,
+ IN gctUINT32 Address,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ );
+
+/* Set the MMU page with info. */
+gceSTATUS
+gckMMU_SetPage(
+ IN gckMMU Mmu,
+ IN gctPHYS_ADDR_T PageAddress,
+ IN gctBOOL Writable,
+ IN gctUINT32 *PageEntry
+ );
+
+gceSTATUS
+gckMMU_Flush(
+ IN gckMMU Mmu,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+gckMMU_DumpPageTableEntry(
+ IN gckMMU Mmu,
+ IN gctUINT32 Address
+ );
+
+gceSTATUS
+gckMMU_FillFlatMapping(
+ IN gckMMU Mmu,
+ IN gctUINT32 PhysBase,
+ IN gctSIZE_T Size
+ );
+
+gceSTATUS
+gckMMU_IsFlatMapped(
+ IN gckMMU Mmu,
+ OUT gctUINT32 Physical,
+ OUT gctBOOL *In
+ );
+
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ OUT gcsPROFILER_COUNTERS * Counters
+ );
+#endif
+
+#if VIVANTE_PROFILER_CONTEXT
+gceSTATUS
+gckHARDWARE_QueryContextProfile(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ IN gckCONTEXT Context,
+ OUT gcsPROFILER_COUNTERS * Counters
+ );
+
+gceSTATUS
+gckHARDWARE_UpdateContextProfile(
+ IN gckHARDWARE Hardware,
+ IN gckCONTEXT Context
+ );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryContextNewProfile(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Reset,
+ IN gckCONTEXT Context,
+ OUT gcsPROFILER_NEW_COUNTERS_PART1 * Counters_part1,
+ OUT gcsPROFILER_NEW_COUNTERS_PART2 * Counters_part2
+ );
+
+gceSTATUS
+gckHARDWARE_UpdateContextNewProfile(
+ IN gckHARDWARE Hardware,
+ IN gckCONTEXT Context
+ );
+
+gceSTATUS
+gckHARDWARE_InitProfiler(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckOS_DetectProcessByName(
+ IN gctCONST_POINTER Name
+ );
+
+void
+gckOS_DumpParam(
+ void
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#if gcdENABLE_VG
+#include "gc_hal_vg.h"
+#endif
+
+#endif /* __gc_hal_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
new file mode 100644
index 000000000000..50e8ce500544
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
@@ -0,0 +1,5999 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_base_h_
+#define __gc_hal_base_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+#include "gc_hal_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gckOS * gckOS;
+typedef struct _gcoHAL * gcoHAL;
+typedef struct _gcoOS * gcoOS;
+typedef struct _gco2D * gco2D;
+typedef struct gcsATOM * gcsATOM_PTR;
+
+typedef struct _gco3D * gco3D;
+typedef struct _gcoCL * gcoCL;
+typedef struct _gcsFAST_FLUSH * gcsFAST_FLUSH_PTR;
+
+typedef struct _gcoSURF * gcoSURF;
+typedef struct _gcsSURF_NODE * gcsSURF_NODE_PTR;
+typedef struct _gcsSURF_FORMAT_INFO * gcsSURF_FORMAT_INFO_PTR;
+typedef struct _gcsPOINT * gcsPOINT_PTR;
+typedef struct _gcsSIZE * gcsSIZE_PTR;
+typedef struct _gcsRECT * gcsRECT_PTR;
+typedef struct _gcsBOUNDARY * gcsBOUNDARY_PTR;
+typedef struct _gcoDUMP * gcoDUMP;
+typedef struct _gcoHARDWARE * gcoHARDWARE;
+typedef union _gcuVIDMEM_NODE * gcuVIDMEM_NODE_PTR;
+typedef struct _gcsVIDMEM_NODE * gckVIDMEM_NODE;
+
+#if gcdENABLE_VG
+typedef struct _gcoVG * gcoVG;
+typedef struct _gcsCOMPLETION_SIGNAL * gcsCOMPLETION_SIGNAL_PTR;
+typedef struct _gcsCONTEXT_MAP * gcsCONTEXT_MAP_PTR;
+#else
+typedef void * gcoVG;
+#endif
+
+typedef struct _gcoFENCE * gcoFENCE;
+typedef struct _gcsSYNC_CONTEXT * gcsSYNC_CONTEXT_PTR;
+
+typedef enum {
+ gcvFENCE_TYPE_READ = 0x1,
+ gcvFENCE_TYPE_WRITE = 0x2,
+ gcvFENCE_TYPE_ALL = gcvFENCE_TYPE_READ | gcvFENCE_TYPE_WRITE,
+}
+gceFENCE_TYPE;
+
+typedef struct _gcsUSER_MEMORY_DESC * gcsUSER_MEMORY_DESC_PTR;
+
+
+
+/******************************************************************************\
+********************* Share obj lock/unlock macros. ****************************
+\******************************************************************************/
+#define gcmLOCK_SHARE_OBJ(Obj) \
+{ \
+ if(Obj->sharedLock != gcvNULL)\
+ {\
+ (gcoOS_AcquireMutex( \
+ gcvNULL, Obj->sharedLock, gcvINFINITE));\
+ }\
+}
+
+
+#define gcmUNLOCK_SHARE_OBJ(Obj)\
+{\
+ if(Obj->sharedLock != gcvNULL)\
+ {\
+ (gcoOS_ReleaseMutex(gcvNULL, Obj->sharedLock));\
+ }\
+}
+
+typedef struct _gcsSystemInfo
+{
+ /* memory latency number for SH data fetch, in SH cycle*/
+ gctUINT32 memoryLatencySH;
+}
+gcsSystemInfo;
+
+
+#if gcdENABLE_3D
+#define gcPLS_INITIALIZER \
+{ \
+ gcvNULL, /* gcoOS object. */ \
+ gcvNULL, /* gcoHAL object. */ \
+ 0, /* internalSize */ \
+ gcvNULL, /* internalPhysical */ \
+ gcvNULL, /* internalLogical */ \
+ 0, /* externalSize */ \
+ gcvNULL, /* externalPhysical */ \
+ gcvNULL, /* externalLogical */ \
+ 0, /* contiguousSize */ \
+ gcvNULL, /* contiguousPhysical */ \
+ gcvNULL, /* contiguousLogical */ \
+ gcvNULL, /* eglDisplayInfo */ \
+ gcvNULL, /* eglSurfaceInfo */ \
+ gcvSURF_A8R8G8B8,/* eglConfigFormat */ \
+ gcvNULL, /* reference */ \
+ 0, /* processID */ \
+ 0, /* threadID */ \
+ gcvFALSE, /* exiting */ \
+ gcvFALSE, /* Special flag for NP2 texture. */ \
+ gcvNULL, /* destructor */ \
+ gcvNULL, /* accessLock */ \
+ gcvNULL, /* GL FE compiler lock*/ \
+ gcvPATCH_NOTINIT,/* global patchID */ \
+}
+#else
+#define gcPLS_INITIALIZER \
+{ \
+ gcvNULL, /* gcoOS object. */ \
+ gcvNULL, /* gcoHAL object. */ \
+ 0, /* internalSize */ \
+ gcvNULL, /* internalPhysical */ \
+ gcvNULL, /* internalLogical */ \
+ 0, /* externalSize */ \
+ gcvNULL, /* externalPhysical */ \
+ gcvNULL, /* externalLogical */ \
+ 0, /* contiguousSize */ \
+ gcvNULL, /* contiguousPhysical */ \
+ gcvNULL, /* contiguousLogical */ \
+ gcvNULL, /* eglDisplayInfo */ \
+ gcvNULL, /* eglSurfaceInfo */ \
+ gcvSURF_A8R8G8B8,/* eglConfigFormat */ \
+ gcvNULL, /* reference */ \
+ 0, /* processID */ \
+ 0, /* threadID */ \
+ gcvFALSE, /* exiting */ \
+ gcvFALSE, /* Special flag for NP2 texture. */ \
+ gcvNULL, /* destructor */ \
+ gcvNULL, /* accessLock */ \
+}
+#endif
+
+/******************************************************************************\
+******************************* Thread local storage *************************
+\******************************************************************************/
+
+typedef struct _gcsDRIVER_TLS * gcsDRIVER_TLS_PTR;
+
+typedef struct _gcsDRIVER_TLS
+{
+ void (* destructor)(gcsDRIVER_TLS_PTR Tls);
+}
+gcsDRIVER_TLS;
+
+typedef enum _gceTLS_KEY
+{
+ gcvTLS_KEY_EGL,
+ gcvTLS_KEY_OPENGL_ES,
+ gcvTLS_KEY_OPENVG,
+ gcvTLS_KEY_OPENGL,
+ gcvTLS_KEY_OPENCL,
+ gcvTLS_KEY_OPENVX,
+
+ gcvTLS_KEY_COUNT
+}
+gceTLS_KEY;
+
+typedef struct _gcsTLS * gcsTLS_PTR;
+
+typedef struct _gcsTLS
+{
+ gceHARDWARE_TYPE currentType;
+
+ /* To which core device control is called,
+ * it is index in a hardware type.
+ */
+ gctUINT32 currentCoreIndex;
+
+ /* Current 3D hardwre of this thread */
+ gcoHARDWARE currentHardware;
+
+ /* Default 3D hardware of this thread */
+ gcoHARDWARE defaultHardware;
+
+ /* Only for separated 3D and 2D */
+ gcoHARDWARE hardware2D;
+#if gcdENABLE_VG
+ gcoVGHARDWARE vg;
+ gcoVG engineVG;
+#endif /* gcdENABLE_VG */
+#if gcdENABLE_3D
+ gco3D engine3D;
+#endif
+#if gcdENABLE_2D
+ gco2D engine2D;
+#if gcdDUMP_2D
+ gctUINT32 newDump2DFlag;
+#endif
+#endif
+
+ gctBOOL copied;
+
+ /* libGAL.so handle */
+ gctHANDLE handle;
+
+ /* If true, do not releas 2d engine and hardware in hal layer */
+ gctBOOL release2DUpper;
+
+ /* Driver tls. */
+ gcsDRIVER_TLS_PTR driverTLS[gcvTLS_KEY_COUNT];
+}
+gcsTLS;
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+typedef enum _gcePLS_VALUE
+{
+ gcePLS_VALUE_EGL_DISPLAY_INFO,
+ gcePLS_VALUE_EGL_CONFIG_FORMAT_INFO,
+ gcePLS_VALUE_EGL_DESTRUCTOR_INFO,
+}
+gcePLS_VALUE;
+
+/* Video memory pool type. */
+typedef enum _gcePOOL
+{
+ gcvPOOL_UNKNOWN = 0,
+ gcvPOOL_DEFAULT,
+ gcvPOOL_LOCAL,
+ gcvPOOL_LOCAL_INTERNAL,
+ gcvPOOL_LOCAL_EXTERNAL,
+ gcvPOOL_UNIFIED,
+ gcvPOOL_SYSTEM,
+ gcvPOOL_VIRTUAL,
+ gcvPOOL_USER,
+ gcvPOOL_CONTIGUOUS,
+
+ gcvPOOL_NUMBER_OF_POOLS
+}
+gcePOOL;
+
+#if gcdENABLE_3D
+/* Blending functions. */
+typedef enum _gceBLEND_FUNCTION
+{
+ gcvBLEND_ZERO,
+ gcvBLEND_ONE,
+ gcvBLEND_SOURCE_COLOR,
+ gcvBLEND_INV_SOURCE_COLOR,
+ gcvBLEND_SOURCE_ALPHA,
+ gcvBLEND_INV_SOURCE_ALPHA,
+ gcvBLEND_TARGET_COLOR,
+ gcvBLEND_INV_TARGET_COLOR,
+ gcvBLEND_TARGET_ALPHA,
+ gcvBLEND_INV_TARGET_ALPHA,
+ gcvBLEND_SOURCE_ALPHA_SATURATE,
+ gcvBLEND_CONST_COLOR,
+ gcvBLEND_INV_CONST_COLOR,
+ gcvBLEND_CONST_ALPHA,
+ gcvBLEND_INV_CONST_ALPHA,
+}
+gceBLEND_FUNCTION;
+
+/* Blending modes. */
+typedef enum _gceBLEND_MODE
+{
+ gcvBLEND_ADD = 0,
+ gcvBLEND_SUBTRACT,
+ gcvBLEND_REVERSE_SUBTRACT,
+ gcvBLEND_MIN,
+ gcvBLEND_MAX,
+ gcvBLEND_MULTIPLY,
+ gcvBLEND_SCREEN,
+ gcvBLEND_OVERLAY,
+ gcvBLEND_DARKEN,
+ gcvBLEND_LIGHTEN,
+ gcvBLEND_COLORDODGE,
+ gcvBLEND_COLORBURN,
+ gcvBLEND_HARDLIGHT,
+ gcvBLEND_SOFTLIGHT,
+ gcvBLEND_DIFFERENCE,
+ gcvBLEND_EXCLUSION,
+ gcvBLEND_HSL_HUE,
+ gcvBLEND_HSL_SATURATION,
+ gcvBLEND_HSL_COLOR,
+ gcvBLEND_HSL_LUMINOSITY,
+
+ gcvBLEND_TOTAL
+}
+gceBLEND_MODE;
+
+/* Depth modes. */
+typedef enum _gceDEPTH_MODE
+{
+ gcvDEPTH_NONE,
+ gcvDEPTH_Z,
+ gcvDEPTH_W,
+}
+gceDEPTH_MODE;
+#endif /* gcdENABLE_3D */
+
+
+/* API flags. */
+typedef enum _gceAPI
+{
+ gcvAPI_D3D = 1,
+ gcvAPI_OPENGL_ES11,
+ gcvAPI_OPENGL_ES20,
+ gcvAPI_OPENGL_ES30,
+ gcvAPI_OPENGL_ES31,
+ gcvAPI_OPENGL_ES32,
+ gcvAPI_OPENGL,
+ gcvAPI_OPENVG,
+ gcvAPI_OPENCL,
+ gcvAPI_OPENVK,
+}
+gceAPI;
+
+typedef enum _gceWHERE
+{
+ gcvWHERE_COMMAND_PREFETCH = 0,
+ gcvWHERE_COMMAND,
+ gcvWHERE_RASTER,
+ gcvWHERE_PIXEL,
+ gcvWHERE_BLT,
+}
+gceWHERE;
+
+typedef enum _gceHOW
+{
+ gcvHOW_SEMAPHORE = 0x1,
+ gcvHOW_STALL = 0x2,
+ gcvHOW_SEMAPHORE_STALL = 0x3,
+}
+gceHOW;
+
+typedef enum _gceSignalHandlerType
+{
+ gcvHANDLE_SIGFPE_WHEN_SIGNAL_CODE_IS_0 = 0x1,
+}
+gceSignalHandlerType;
+
+typedef struct _gcsSURF_VIEW
+{
+ gcoSURF surf;
+ gctUINT firstSlice;
+ gctUINT numSlices;
+}gcsSURF_VIEW;
+
+/* gcsHAL_Limits*/
+typedef struct _gcsHAL_LIMITS
+{
+ /* chip info */
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 featureCount;
+ gctUINT32 *chipFeatures;
+
+ /* target caps */
+ gctUINT32 maxWidth;
+ gctUINT32 maxHeight;
+ gctUINT32 multiTargetCount;
+ gctUINT32 maxSamples;
+
+}gcsHAL_LIMITS;
+
+#define gcdEXTERNAL_MEMORY_NAME_MAX 32
+#define gcdEXTERNAL_MEMORY_DATA_MAX 8
+
+typedef struct _gcsEXTERNAL_MEMORY_INFO
+{
+ /* Name of allocator used to attach this memory. */
+ gctCHAR allocatorName[gcdEXTERNAL_MEMORY_NAME_MAX];
+
+ /* User defined data which will be passed to allocator. */
+ gctUINT32 userData[gcdEXTERNAL_MEMORY_DATA_MAX];
+}
+gcsEXTERNAL_MEMORY_INFO;
+
+/******************************************************************************\
+*********** Generic Memory Allocation Optimization Using Containers ************
+\******************************************************************************/
+
+/* Generic container definition. */
+typedef struct _gcsCONTAINER_LINK * gcsCONTAINER_LINK_PTR;
+typedef struct _gcsCONTAINER_LINK
+{
+ /* Points to the next container. */
+ gcsCONTAINER_LINK_PTR next;
+}
+gcsCONTAINER_LINK;
+
+typedef struct _gcsCONTAINER_RECORD * gcsCONTAINER_RECORD_PTR;
+typedef struct _gcsCONTAINER_RECORD
+{
+ gcsCONTAINER_RECORD_PTR prev;
+ gcsCONTAINER_RECORD_PTR next;
+}
+gcsCONTAINER_RECORD;
+
+typedef struct _gcsCONTAINER * gcsCONTAINER_PTR;
+typedef struct _gcsCONTAINER
+{
+ gctUINT containerSize;
+ gctUINT recordSize;
+ gctUINT recordCount;
+ gcsCONTAINER_LINK_PTR containers;
+ gcsCONTAINER_RECORD freeList;
+ gcsCONTAINER_RECORD allocList;
+}
+gcsCONTAINER;
+
+gceSTATUS
+gcsCONTAINER_Construct(
+ IN gcsCONTAINER_PTR Container,
+ gctUINT RecordsPerContainer,
+ gctUINT RecordSize
+ );
+
+gceSTATUS
+gcsCONTAINER_Destroy(
+ IN gcsCONTAINER_PTR Container
+ );
+
+gceSTATUS
+gcsCONTAINER_AllocateRecord(
+ IN gcsCONTAINER_PTR Container,
+ OUT gctPOINTER * Record
+ );
+
+gceSTATUS
+gcsCONTAINER_FreeRecord(
+ IN gcsCONTAINER_PTR Container,
+ IN gctPOINTER Record
+ );
+
+gceSTATUS
+gcsCONTAINER_FreeAll(
+ IN gcsCONTAINER_PTR Container
+ );
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+/* Construct a new gcoHAL object. */
+gceSTATUS
+gcoHAL_ConstructEx(
+ IN gctPOINTER Context,
+ IN gcoOS Os,
+ OUT gcoHAL * Hal
+ );
+
+/* Destroy an gcoHAL object. */
+gceSTATUS
+gcoHAL_DestroyEx(
+ IN gcoHAL Hal
+ );
+
+/* Empty function for compatibility. */
+gceSTATUS
+gcoHAL_Construct(
+ IN gctPOINTER Context,
+ IN gcoOS Os,
+ OUT gcoHAL * Hal
+ );
+
+/* Empty function for compatibility. */
+gceSTATUS
+gcoHAL_Destroy(
+ IN gcoHAL Hal
+ );
+
+/* Get HAL options */
+gceSTATUS
+gcoHAL_GetOption(
+ IN gcoHAL Hal,
+ IN gceOPTION Option
+ );
+
+gceSTATUS
+gcoHAL_FrameInfoOps(
+ IN gcoHAL Hal,
+ IN gceFRAMEINFO FrameInfo,
+ IN gceFRAMEINFO_OP Op,
+ IN OUT gctUINT * Val
+ );
+
+/* Set HAL options */
+gceSTATUS
+gcoHAL_SetOption(
+ IN gcoHAL Hal,
+ IN gceOPTION Option,
+ IN gctBOOL Value
+ );
+
+gceSTATUS
+gcoHAL_GetHardware(
+ IN gcoHAL Hal,
+ OUT gcoHARDWARE* Hw
+ );
+
+#if gcdENABLE_2D
+/* Get pointer to gco2D object. */
+gceSTATUS
+gcoHAL_Get2DEngine(
+ IN gcoHAL Hal,
+ OUT gco2D * Engine
+ );
+#endif
+
+#if gcdENABLE_3D
+gceSTATUS
+gcoHAL_GetSpecialHintData(
+ IN gcoHAL Hal,
+ OUT gctINT * Hint
+ );
+/*
+** Deprecated(Don't use it), keep it here for external library(libgcu.so)
+*/
+gceSTATUS
+gcoHAL_Get3DEngine(
+ IN gcoHAL Hal,
+ OUT gco3D * Engine
+ );
+#endif /* gcdENABLE_3D */
+
+
+gceSTATUS
+gcoHAL_GetProductName(
+ IN gcoHAL Hal,
+ OUT gctSTRING *ProductName
+ );
+
+gceSTATUS
+gcoHAL_SetFscaleValue(
+ IN gctUINT FscaleValue
+ );
+
+gceSTATUS
+gcoHAL_GetFscaleValue(
+ OUT gctUINT * FscaleValue,
+ OUT gctUINT * MinFscaleValue,
+ OUT gctUINT * MaxFscaleValue
+ );
+
+gceSTATUS
+gcoHAL_SetBltNP2Texture(
+ gctBOOL enable
+ );
+
+gceSTATUS
+gcoHAL_NameVideoMemory(
+ IN gctUINT32 Handle,
+ OUT gctUINT32 * Name
+ );
+
+gceSTATUS
+gcoHAL_ImportVideoMemory(
+ IN gctUINT32 Name,
+ OUT gctUINT32 * Handle
+ );
+
+gceSTATUS
+gcoHAL_GetVideoMemoryFd(
+ IN gctUINT32 Handle,
+ OUT gctINT * Fd
+ );
+
+/* Verify whether the specified feature is available in hardware. */
+gceSTATUS
+gcoHAL_IsFeatureAvailable(
+ IN gcoHAL Hal,
+ IN gceFEATURE Feature
+ );
+
+gceSTATUS
+gcoHAL_IsSwwaNeeded(
+ IN gcoHAL Hal,
+ IN gceSWWA Swwa
+ );
+
+gceSTATUS
+gcoHAL_IsFeatureAvailable1(
+ IN gcoHAL Hal,
+ IN gceFEATURE Feature
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gcoHAL_QueryChipIdentity(
+ IN gcoHAL Hal,
+ OUT gceCHIPMODEL* ChipModel,
+ OUT gctUINT32* ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures
+ );
+
+
+gceSTATUS
+gcoHAL_QuerySuperTileMode(
+ OUT gctUINT32_PTR SuperTileMode
+ );
+
+gceSTATUS
+gcoHAL_QueryMultiGPUAffinityConfig(
+ IN gceHARDWARE_TYPE Type,
+ OUT gceMULTI_GPU_MODE *Mode,
+ OUT gctUINT32_PTR CoreIndex
+ );
+
+#ifdef LINUX
+gctINT32
+gcoOS_EndRecordAllocation(void);
+void
+gcoOS_RecordAllocation(void);
+void
+gcoOS_AddRecordAllocation(gctSIZE_T Size);
+#endif
+
+/* Query the amount of video memory. */
+gceSTATUS
+gcoHAL_QueryVideoMemory(
+ IN gcoHAL Hal,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/* Map video memory. */
+gceSTATUS
+gcoHAL_MapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap video memory. */
+gceSTATUS
+gcoHAL_UnmapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ IN gctPOINTER Logical
+ );
+
+/* Schedule an unmap of a buffer mapped through its physical address. */
+gceSTATUS
+gcoHAL_ScheduleUnmapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ IN gctPOINTER Logical
+ );
+
+/* Allocate video memory. */
+gceSTATUS
+gcoOS_AllocateVideoMemory(
+ IN gcoOS Os,
+ IN gctBOOL InUserSpace,
+ IN gctBOOL InCacheable,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctUINT32 * Physical,
+ OUT gctPOINTER * Logical,
+ OUT gctPOINTER * Handle
+ );
+
+/* Free video memory. */
+gceSTATUS
+gcoOS_FreeVideoMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Handle
+ );
+
+/* Lock video memory. */
+gceSTATUS
+gcoOS_LockVideoMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Handle,
+ IN gctBOOL InUserSpace,
+ IN gctBOOL InCacheable,
+ OUT gctUINT32 * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Map user memory. */
+gceSTATUS
+gcoHAL_MapUserMemory(
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR GPUAddress
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gcoHAL_UnmapUserMemory(
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 GPUAddress
+ );
+
+/* Schedule an unmap of a user buffer using event mechanism. */
+gceSTATUS
+gcoHAL_ScheduleUnmapUserMemory(
+ IN gcoHAL Hal,
+ IN gctPOINTER Info,
+ IN gctSIZE_T Size,
+ IN gctUINT32 Address,
+ IN gctPOINTER Memory
+ );
+
+/* Commit the current command buffer. */
+gceSTATUS
+gcoHAL_Commit(
+ IN gcoHAL Hal,
+ IN gctBOOL Stall
+ );
+
+#if gcdENABLE_3D
+/* Sencd fence command. */
+gceSTATUS
+gcoHAL_SendFence(
+ IN gcoHAL Hal
+ );
+#endif /* gcdENABLE_3D */
+
+/* Query the tile capabilities. */
+gceSTATUS
+gcoHAL_QueryTiled(
+ IN gcoHAL Hal,
+ OUT gctINT32 * TileWidth2D,
+ OUT gctINT32 * TileHeight2D,
+ OUT gctINT32 * TileWidth3D,
+ OUT gctINT32 * TileHeight3D
+ );
+
+gceSTATUS
+gcoHAL_Compact(
+ IN gcoHAL Hal
+ );
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gcoHAL_ProfileStart(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_ProfileEnd(
+ IN gcoHAL Hal,
+ IN gctCONST_STRING Title
+ );
+#endif
+
+/* Power Management */
+gceSTATUS
+gcoHAL_SetPowerManagementState(
+ IN gcoHAL Hal,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gcoHAL_QueryPowerManagementState(
+ IN gcoHAL Hal,
+ OUT gceCHIPPOWERSTATE *State
+ );
+
+/* Set the filter type for filter blit. */
+gceSTATUS
+gcoHAL_SetFilterType(
+ IN gcoHAL Hal,
+ IN gceFILTER_TYPE FilterType
+ );
+
+gceSTATUS
+gcoHAL_GetDump(
+ IN gcoHAL Hal,
+ OUT gcoDUMP * Dump
+ );
+
+/* Call the kernel HAL layer. */
+gceSTATUS
+gcoHAL_Call(
+ IN gcoHAL Hal,
+ IN OUT gcsHAL_INTERFACE_PTR Interface
+ );
+
+/* Schedule an event. */
+gceSTATUS
+gcoHAL_ScheduleEvent(
+ IN gcoHAL Hal,
+ IN OUT gcsHAL_INTERFACE_PTR Interface
+ );
+
+/* Request a start/stop timestamp. */
+gceSTATUS
+gcoHAL_SetTimer(
+ IN gcoHAL Hal,
+ IN gctUINT32 Index,
+ IN gctBOOL Start
+ );
+
+/* Get Time delta from a Timer in microseconds. */
+gceSTATUS
+gcoHAL_GetTimerTime(
+ IN gcoHAL Hal,
+ IN gctUINT32 Timer,
+ OUT gctINT32_PTR TimeDelta
+ );
+
+/* set timeout value. */
+gceSTATUS
+gcoHAL_SetTimeOut(
+ IN gcoHAL Hal,
+ IN gctUINT32 timeOut
+ );
+
+gceSTATUS
+gcoHAL_SetHardwareType(
+ IN gcoHAL Hal,
+ IN gceHARDWARE_TYPE HardwardType
+ );
+
+gceSTATUS
+gcoHAL_GetHardwareType(
+ IN gcoHAL Hal,
+ OUT gceHARDWARE_TYPE * HardwardType
+ );
+
+gceSTATUS
+gcoHAL_QueryChipCount(
+ IN gcoHAL Hal,
+ OUT gctINT32 * Count
+ );
+
+gceSTATUS
+gcoHAL_Query3DCoreCount(
+ IN gcoHAL Hal,
+ OUT gctUINT32 *Count
+ );
+
+gceSTATUS
+gcoHAL_QueryCoreCount(
+ IN gcoHAL Hal,
+ IN gceHARDWARE_TYPE Type,
+ OUT gctUINT *Count,
+ OUT gctUINT_PTR ChipIDs
+ );
+
+gceSTATUS
+gcoHAL_QuerySeparated2D(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_QueryHybrid2D(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_Is3DAvailable(
+ IN gcoHAL Hal
+ );
+
+/* Get pointer to gcoVG object. */
+gceSTATUS
+gcoHAL_GetVGEngine(
+ IN gcoHAL Hal,
+ OUT gcoVG * Engine
+ );
+
+gceSTATUS
+gcoHAL_QueryChipLimits(
+ IN gcoHAL Hal,
+ IN gctINT32 Chip,
+ OUT gcsHAL_LIMITS *Limits);
+
+gceSTATUS
+gcoHAL_QueryChipFeature(
+ IN gcoHAL Hal,
+ IN gctINT32 Chip,
+ IN gceFEATURE Feature);
+
+gceSTATUS
+gcoHAL_SetCoreIndex(
+ IN gcoHAL Hal,
+ IN gctUINT32 Core
+ );
+
+gceSTATUS
+gcoHAL_GetCurrentCoreIndex(
+ IN gcoHAL Hal,
+ OUT gctUINT32 *Core
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Shared Buffer --------------------------------------------------------*/
+
+/* Create shared buffer. */
+gceSTATUS
+gcoHAL_CreateShBuffer(
+ IN gctUINT32 Size,
+ OUT gctSHBUF * ShBuf
+ );
+
+/* Destroy shared buffer. */
+gceSTATUS
+gcoHAL_DestroyShBuffer(
+ IN gctSHBUF ShBuf
+ );
+
+/* Map shared buffer to current process. */
+gceSTATUS
+gcoHAL_MapShBuffer(
+ IN gctSHBUF ShBuf
+ );
+
+/* Write user data to shared buffer. */
+gceSTATUS
+gcoHAL_WriteShBuffer(
+ IN gctSHBUF ShBuf,
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 ByteCount
+ );
+
+/* Read user data from shared buffer. */
+gceSTATUS
+gcoHAL_ReadShBuffer(
+ IN gctSHBUF ShBuf,
+ IN gctPOINTER Data,
+ IN gctUINT32 BytesCount,
+ OUT gctUINT32 * BytesRead
+ );
+
+/* Config power management to be enabled or disabled. */
+gceSTATUS
+gcoHAL_ConfigPowerManagement(
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoHAL_AllocateVideoMemory(
+ IN gctUINT Alignment,
+ IN gceSURF_TYPE Type,
+ IN gctUINT32 Flag,
+ IN gcePOOL Pool,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctUINT32_PTR Node
+ );
+
+gceSTATUS
+gcoHAL_LockVideoMemory(
+ IN gctUINT32 Node,
+ IN gctBOOL Cacheable,
+ OUT gctUINT32 * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+gceSTATUS
+gcoHAL_UnlockVideoMemory(
+ IN gctUINT32 Node,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+gcoHAL_ReleaseVideoMemory(
+ IN gctUINT32 Node
+ );
+
+gceSTATUS
+gcoHAL_AllocateContiguous(
+ IN gcoOS Os,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+#if gcdENABLE_3D || gcdENABLE_VG
+/* Query the target capabilities. */
+gceSTATUS
+gcoHAL_QueryTargetCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MultiTargetCount,
+ OUT gctUINT * MaxSamples
+ );
+#endif
+
+gceSTATUS
+gcoHAL_WrapUserMemory(
+ IN gcsUSER_MEMORY_DESC_PTR UserMemoryDesc,
+ OUT gctUINT32_PTR Node
+ );
+
+gceSTATUS
+gcoHAL_QueryResetTimeStamp(
+ OUT gctUINT64_PTR ResetTimeStamp,
+ OUT gctUINT64_PTR ContextID
+ );
+
+gceSTATUS
+gcoHAL_WaitFence(
+ IN gctUINT32 Handle,
+ IN gctUINT32 TimeOut
+ );
+
+#if gcdENABLE_2D
+gceSTATUS
+gcoHAL_AttachExternalMemory(
+ IN gcoHAL Hal,
+ IN gcsEXTERNAL_MEMORY_INFO * External,
+ OUT gctPOINTER * Handle,
+ OUT gctUINT32_PTR GPU2DAddress
+ );
+
+gceSTATUS
+gcoHAL_DetachExternalMemory(
+ IN gcoHAL Hal,
+ IN gctPOINTER * Handle
+ );
+#endif
+
+gceSTATUS
+gcoHAL_ScheduleSignal(
+ IN gctSIGNAL Signal,
+ IN gctSIGNAL AuxSignal,
+ IN gctINT ProcessID,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/******************************************************************************\
+********************************** gcoOS Object *********************************
+\******************************************************************************/
+/* Lock PLS access */
+gceSTATUS
+gcoOS_LockPLS(
+ void
+ );
+
+/* Unlock PLS access */
+gceSTATUS
+gcoOS_UnLockPLS(
+ void
+ );
+
+/* Get PLS value for given key */
+gctPOINTER
+gcoOS_GetPLSValue(
+ IN gcePLS_VALUE key
+ );
+
+/* Set PLS value of a given key */
+void
+gcoOS_SetPLSValue(
+ IN gcePLS_VALUE key,
+ OUT gctPOINTER value
+ );
+
+/* Lock GL FE compiler access */
+gceSTATUS
+gcoOS_LockGLFECompiler(
+ void
+ );
+
+/* Unlock GL FE compiler access */
+gceSTATUS
+gcoOS_UnLockGLFECompiler(
+ void
+ );
+
+gceSTATUS
+gcoOS_GetTLS(
+ OUT gcsTLS_PTR * TLS
+ );
+
+/* Copy the TLS from a source thread. */
+gceSTATUS
+gcoOS_CopyTLS(
+ IN gcsTLS_PTR Source
+ );
+
+/* Query the thread local storage. */
+gceSTATUS
+gcoOS_QueryTLS(
+ OUT gcsTLS_PTR * TLS
+ );
+
+/* Get access to driver tls. */
+gceSTATUS
+gcoOS_GetDriverTLS(
+ IN gceTLS_KEY Key,
+ OUT gcsDRIVER_TLS_PTR * TLS
+ );
+
+/*
+ * Set driver tls.
+ * May cause memory leak if 'destructor' not set.
+ */
+gceSTATUS
+gcoOS_SetDriverTLS(
+ IN gceTLS_KEY Key,
+ IN gcsDRIVER_TLS * TLS
+ );
+
+/* Destroy the objects associated with the current thread. */
+void
+gcoOS_FreeThreadData(
+ void
+ );
+
+/* Empty function for compatibility. */
+gceSTATUS
+gcoOS_Construct(
+ IN gctPOINTER Context,
+ OUT gcoOS * Os
+ );
+
+/* Empty function for compatibility. */
+gceSTATUS
+gcoOS_Destroy(
+ IN gcoOS Os
+ );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gcoOS_GetBaseAddress(
+ IN gcoOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gcoOS_Allocate(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Get allocated memory size. */
+gceSTATUS
+gcoOS_GetMemorySize(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ OUT gctSIZE_T_PTR MemorySize
+ );
+
+/* Free allocated memory. */
+gceSTATUS
+gcoOS_Free(
+ IN gcoOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gcoOS_AllocateSharedMemory(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoOS_FreeSharedMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gcoOS_AllocateMemory(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoOS_FreeMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Free contiguous memory. */
+gceSTATUS
+gcoOS_FreeContiguous(
+ IN gcoOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Map user memory. */
+gceSTATUS
+gcoOS_MapUserMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Map user memory. */
+gceSTATUS
+gcoOS_MapUserMemoryEx(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gcoOS_UnmapUserMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ );
+
+gceSTATUS
+gcoOS_CPUPhysicalToGPUPhysical(
+ IN gctUINT32 CPUPhysical,
+ OUT gctUINT32_PTR GPUPhysical
+ );
+
+/* Device I/O Control call to the kernel HAL layer. */
+gceSTATUS
+gcoOS_DeviceControl(
+ IN gcoOS Os,
+ IN gctUINT32 IoControlCode,
+ IN gctPOINTER InputBuffer,
+ IN gctSIZE_T InputBufferSize,
+ IN gctPOINTER OutputBuffer,
+ IN gctSIZE_T OutputBufferSize
+ );
+
+/* Allocate non paged memory. */
+gceSTATUS
+gcoOS_AllocateNonPagedMemory(
+ IN gcoOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free non paged memory. */
+gceSTATUS
+gcoOS_FreeNonPagedMemory(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+#define gcmOS_SAFE_FREE(os, mem) \
+ gcoOS_Free(os, mem); \
+ mem = gcvNULL
+
+#define gcmOS_SAFE_FREE_SHARED_MEMORY(os, mem) \
+ gcoOS_FreeSharedMemory(os, mem); \
+ mem = gcvNULL
+
+#define gcmkOS_SAFE_FREE(os, mem) \
+ gckOS_Free(os, mem); \
+ mem = gcvNULL
+
+#define gcdMAX_PATH 512
+
+typedef enum _gceFILE_MODE
+{
+ gcvFILE_CREATE = 0,
+ gcvFILE_APPEND,
+ gcvFILE_READ,
+ gcvFILE_CREATETEXT,
+ gcvFILE_APPENDTEXT,
+ gcvFILE_READTEXT,
+}
+gceFILE_MODE;
+
+/* Open a file. */
+gceSTATUS
+gcoOS_Open(
+ IN gcoOS Os,
+ IN gctCONST_STRING FileName,
+ IN gceFILE_MODE Mode,
+ OUT gctFILE * File
+ );
+
+/* Close a file. */
+gceSTATUS
+gcoOS_Close(
+ IN gcoOS Os,
+ IN gctFILE File
+ );
+
+/* Read data from a file. */
+gceSTATUS
+gcoOS_Read(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctSIZE_T ByteCount,
+ IN gctPOINTER Data,
+ OUT gctSIZE_T * ByteRead
+ );
+
+/* Write data to a file. */
+gceSTATUS
+gcoOS_Write(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+/* Flush data to a file. */
+gceSTATUS
+gcoOS_Flush(
+ IN gcoOS Os,
+ IN gctFILE File
+ );
+
+/* Close a file descriptor. */
+gceSTATUS
+gcoOS_CloseFD(
+ IN gcoOS Os,
+ IN gctINT FD
+ );
+
+/* Scan a file. */
+gceSTATUS
+gcoOS_FscanfI(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctCONST_STRING Format,
+ OUT gctUINT *result
+ );
+
+/* Dup file descriptor to another. */
+gceSTATUS
+gcoOS_DupFD(
+ IN gcoOS Os,
+ IN gctINT FD,
+ OUT gctINT * FD2
+ );
+
+/* Create an endpoint for communication. */
+gceSTATUS
+gcoOS_Socket(
+ IN gcoOS Os,
+ IN gctINT Domain,
+ IN gctINT Type,
+ IN gctINT Protocol,
+ OUT gctINT *SockFd
+ );
+
+/* Close a socket. */
+gceSTATUS
+gcoOS_CloseSocket(
+ IN gcoOS Os,
+ IN gctINT SockFd
+ );
+
+/* Initiate a connection on a socket. */
+gceSTATUS
+gcoOS_Connect(
+ IN gcoOS Os,
+ IN gctINT SockFd,
+ IN gctCONST_POINTER HostName,
+ IN gctUINT Port);
+
+/* Shut down part of connection on a socket. */
+gceSTATUS
+gcoOS_Shutdown(
+ IN gcoOS Os,
+ IN gctINT SockFd,
+ IN gctINT How
+ );
+
+/* Send a message on a socket. */
+gceSTATUS
+gcoOS_Send(
+ IN gcoOS Os,
+ IN gctINT SockFd,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data,
+ IN gctINT Flags
+ );
+
+/* Initiate a connection on a socket. */
+gceSTATUS
+gcoOS_WaitForSend(
+ IN gcoOS Os,
+ IN gctINT SockFd,
+ IN gctINT Seconds,
+ IN gctINT MicroSeconds);
+
+/* Get environment variable value. */
+gceSTATUS
+gcoOS_GetEnv(
+ IN gcoOS Os,
+ IN gctCONST_STRING VarName,
+ OUT gctSTRING * Value
+ );
+
+/* Set environment variable value. */
+gceSTATUS
+gcoOS_SetEnv(
+ IN gcoOS Os,
+ IN gctCONST_STRING VarName,
+ IN gctSTRING Value
+ );
+
+/* Get current working directory. */
+gceSTATUS
+gcoOS_GetCwd(
+ IN gcoOS Os,
+ IN gctINT SizeInBytes,
+ OUT gctSTRING Buffer
+ );
+
+/* Get file status info. */
+gceSTATUS
+gcoOS_Stat(
+ IN gcoOS Os,
+ IN gctCONST_STRING FileName,
+ OUT gctPOINTER Buffer
+ );
+
+typedef enum _gceFILE_WHENCE
+{
+ gcvFILE_SEEK_SET,
+ gcvFILE_SEEK_CUR,
+ gcvFILE_SEEK_END
+}
+gceFILE_WHENCE;
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_Seek(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctUINT32 Offset,
+ IN gceFILE_WHENCE Whence
+ );
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_SetPos(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctUINT32 Position
+ );
+
+/* Get the current position of a file. */
+gceSTATUS
+gcoOS_GetPos(
+ IN gcoOS Os,
+ IN gctFILE File,
+ OUT gctUINT32 * Position
+ );
+
+/* Same as strstr. */
+gceSTATUS
+gcoOS_StrStr(
+ IN gctCONST_STRING String,
+ IN gctCONST_STRING SubString,
+ OUT gctSTRING * Output
+ );
+
+/* Find the last occurance of a character inside a string. */
+gceSTATUS
+gcoOS_StrFindReverse(
+ IN gctCONST_STRING String,
+ IN gctINT8 Character,
+ OUT gctSTRING * Output
+ );
+
+gceSTATUS
+gcoOS_StrDup(
+ IN gcoOS Os,
+ IN gctCONST_STRING String,
+ OUT gctSTRING * Target
+ );
+
+/* Copy a string. */
+gceSTATUS
+gcoOS_StrCopySafe(
+ IN gctSTRING Destination,
+ IN gctSIZE_T DestinationSize,
+ IN gctCONST_STRING Source
+ );
+
+/* Append a string. */
+gceSTATUS
+gcoOS_StrCatSafe(
+ IN gctSTRING Destination,
+ IN gctSIZE_T DestinationSize,
+ IN gctCONST_STRING Source
+ );
+
+/* Compare two strings. */
+gceSTATUS
+gcoOS_StrCmp(
+ IN gctCONST_STRING String1,
+ IN gctCONST_STRING String2
+ );
+
+/* Compare characters of two strings. */
+gceSTATUS
+gcoOS_StrNCmp(
+ IN gctCONST_STRING String1,
+ IN gctCONST_STRING String2,
+ IN gctSIZE_T Count
+ );
+
+/* Convert string to float. */
+gceSTATUS
+gcoOS_StrToFloat(
+ IN gctCONST_STRING String,
+ OUT gctFLOAT * Float
+ );
+
+/* Convert hex string to integer. */
+gceSTATUS gcoOS_HexStrToInt(
+ IN gctCONST_STRING String,
+ OUT gctINT * Int
+ );
+
+/* Convert hex string to float. */
+gceSTATUS
+gcoOS_HexStrToFloat(
+ IN gctCONST_STRING String,
+ OUT gctFLOAT * Float
+ );
+
+/* Convert string to integer. */
+gceSTATUS
+gcoOS_StrToInt(
+ IN gctCONST_STRING String,
+ OUT gctINT * Int
+ );
+
+gceSTATUS
+gcoOS_MemCmp(
+ IN gctCONST_POINTER Memory1,
+ IN gctCONST_POINTER Memory2,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_PrintStrSafe(
+ OUT gctSTRING String,
+ IN gctSIZE_T StringSize,
+ IN OUT gctUINT * Offset,
+ IN gctCONST_STRING Format,
+ ...
+ );
+
+gceSTATUS
+gcoOS_LoadLibrary(
+ IN gcoOS Os,
+ IN gctCONST_STRING Library,
+ OUT gctHANDLE * Handle
+ );
+
+gceSTATUS
+gcoOS_FreeLibrary(
+ IN gcoOS Os,
+ IN gctHANDLE Handle
+ );
+
+gceSTATUS
+gcoOS_GetProcAddress(
+ IN gcoOS Os,
+ IN gctHANDLE Handle,
+ IN gctCONST_STRING Name,
+ OUT gctPOINTER * Function
+ );
+
+gceSTATUS
+gcoOS_Compact(
+ IN gcoOS Os
+ );
+
+gceSTATUS
+gcoOS_AddSignalHandler (
+ IN gceSignalHandlerType SignalHandlerType
+ );
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gcoOS_ProfileStart(
+ IN gcoOS Os
+ );
+
+gceSTATUS
+gcoOS_ProfileEnd(
+ IN gcoOS Os,
+ IN gctCONST_STRING Title
+ );
+
+gceSTATUS
+gcoOS_SetProfileSetting(
+ IN gcoOS Os,
+ IN gctBOOL Enable,
+ IN gctCONST_STRING FileName
+ );
+#endif
+
+/* Get the amount of physical system memory */
+gceSTATUS
+gcoOS_GetPhysicalSystemMemorySize(
+ OUT gctSIZE_T * PhysicalSystemMemorySize
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gcoOS_QueryVideoMemory(
+ IN gcoOS Os,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+gceSTATUS
+gcoOS_QueryCurrentProcessName(
+ OUT gctSTRING Name,
+ IN gctSIZE_T Size
+ );
+
+
+/*----------------------------------------------------------------------------*/
+/*----- Atoms ----------------------------------------------------------------*/
+
+/* Construct an atom. */
+gceSTATUS
+gcoOS_AtomConstruct(
+ IN gcoOS Os,
+ OUT gcsATOM_PTR * Atom
+ );
+
+/* Destroy an atom. */
+gceSTATUS
+gcoOS_AtomDestroy(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom
+ );
+
+/* Get the 32-bit value protected by an atom. */
+gceSTATUS
+gcoOS_AtomGet(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/* Set the 32-bit value protected by an atom. */
+gceSTATUS
+gcoOS_AtomSet(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ IN gctINT32 Value
+ );
+
+/* Increment an atom. */
+gceSTATUS
+gcoOS_AtomIncrement(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR OldValue
+ );
+
+/* Decrement an atom. */
+gceSTATUS
+gcoOS_AtomDecrement(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR OldValue
+ );
+
+gctHANDLE
+gcoOS_GetCurrentProcessID(
+ void
+ );
+
+gctHANDLE
+gcoOS_GetCurrentThreadID(
+ void
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Time -----------------------------------------------------------------*/
+
+/* Get the number of milliseconds since the system started. */
+gctUINT32
+gcoOS_GetTicks(
+ void
+ );
+
+/* Get time in microseconds. */
+gceSTATUS
+gcoOS_GetTime(
+ gctUINT64_PTR Time
+ );
+
+/* Get CPU usage in microseconds. */
+gceSTATUS
+gcoOS_GetCPUTime(
+ gctUINT64_PTR CPUTime
+ );
+
+/* Get memory usage. */
+gceSTATUS
+gcoOS_GetMemoryUsage(
+ gctUINT32_PTR MaxRSS,
+ gctUINT32_PTR IxRSS,
+ gctUINT32_PTR IdRSS,
+ gctUINT32_PTR IsRSS
+ );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gcoOS_Delay(
+ IN gcoOS Os,
+ IN gctUINT32 Delay
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Threads --------------------------------------------------------------*/
+
+#ifdef _WIN32
+/* Cannot include windows.h here becuase "near" and "far"
+ * which are used in gcsDEPTH_INFO, are defined to nothing in WinDef.h.
+ * So, use the real value of DWORD and WINAPI, instead.
+ * DWORD is unsigned long, and WINAPI is __stdcall.
+ * If these two are change in WinDef.h, the following two typdefs
+ * need to be changed, too.
+ */
+typedef unsigned long gctTHREAD_RETURN;
+typedef unsigned long (__stdcall * gcTHREAD_ROUTINE)(void * Argument);
+#else
+typedef void * gctTHREAD_RETURN;
+typedef void * (* gcTHREAD_ROUTINE)(void *);
+#endif
+
+/* Create a new thread. */
+gceSTATUS
+gcoOS_CreateThread(
+ IN gcoOS Os,
+ IN gcTHREAD_ROUTINE Worker,
+ IN gctPOINTER Argument,
+ OUT gctPOINTER * Thread
+ );
+
+/* Close a thread. */
+gceSTATUS
+gcoOS_CloseThread(
+ IN gcoOS Os,
+ IN gctPOINTER Thread
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Mutexes --------------------------------------------------------------*/
+
+/* Create a new mutex. */
+gceSTATUS
+gcoOS_CreateMutex(
+ IN gcoOS Os,
+ OUT gctPOINTER * Mutex
+ );
+
+/* Delete a mutex. */
+gceSTATUS
+gcoOS_DeleteMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Acquire a mutex. */
+gceSTATUS
+gcoOS_AcquireMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a mutex. */
+gceSTATUS
+gcoOS_ReleaseMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Signals --------------------------------------------------------------*/
+
+/* Create a signal. */
+gceSTATUS
+gcoOS_CreateSignal(
+ IN gcoOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ );
+
+/* Destroy a signal. */
+gceSTATUS
+gcoOS_DestroySignal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Signal a signal. */
+gceSTATUS
+gcoOS_Signal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gcoOS_WaitSignal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ );
+
+/* Map a signal from another process */
+gceSTATUS
+gcoOS_MapSignal(
+ IN gctSIGNAL RemoteSignal,
+ OUT gctSIGNAL * LocalSignal
+ );
+
+/* Unmap a signal mapped from another process */
+gceSTATUS
+gcoOS_UnmapSignal(
+ IN gctSIGNAL Signal
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Android Native Fence -------------------------------------------------*/
+
+/* Create native fence. */
+gceSTATUS
+gcoOS_CreateNativeFence(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ OUT gctINT * FenceFD
+ );
+
+/* (CPU) Wait on native fence. */
+gceSTATUS
+gcoOS_ClientWaitNativeFence(
+ IN gcoOS Os,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ );
+
+/* (GPU) Wait on native fence. */
+gceSTATUS
+gcoOS_WaitNativeFence(
+ IN gcoOS Os,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Memory Access and Cache ----------------------------------------------*/
+
+/* Write a register. */
+gceSTATUS
+gcoOS_WriteRegister(
+ IN gcoOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Read a register. */
+gceSTATUS
+gcoOS_ReadRegister(
+ IN gcoOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+gceSTATUS
+gcoOS_CacheClean(
+ IN gcoOS Os,
+ IN gctUINT32 Node,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_CacheFlush(
+ IN gcoOS Os,
+ IN gctUINT32 Node,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_CacheInvalidate(
+ IN gcoOS Os,
+ IN gctUINT32 Node,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_MemoryBarrier(
+ IN gcoOS Os,
+ IN gctPOINTER Logical
+ );
+
+gceSTATUS
+gcoOS_CPUPhysicalToGPUPhysical(
+ IN gctUINT32 CPUPhysical,
+ OUT gctUINT32_PTR GPUPhysical
+ );
+
+gceSTATUS
+gcoOS_QuerySystemInfo(
+ IN gcoOS Os,
+ OUT gcsSystemInfo *Info
+ );
+
+
+/*----------------------------------------------------------------------------*/
+/*----- Profile --------------------------------------------------------------*/
+
+gceSTATUS
+gckOS_GetProfileTick(
+ OUT gctUINT64_PTR Tick
+ );
+
+gceSTATUS
+gckOS_QueryProfileTickRate(
+ OUT gctUINT64_PTR TickRate
+ );
+
+gctUINT32
+gckOS_ProfileToMS(
+ IN gctUINT64 Ticks
+ );
+
+gceSTATUS
+gcoOS_GetProfileTick(
+ OUT gctUINT64_PTR Tick
+ );
+
+gceSTATUS
+gcoOS_QueryProfileTickRate(
+ OUT gctUINT64_PTR TickRate
+ );
+
+#define _gcmPROFILE_INIT(prefix, freq, start) \
+ do { \
+ prefix ## OS_QueryProfileTickRate(&(freq)); \
+ prefix ## OS_GetProfileTick(&(start)); \
+ } while (gcvFALSE)
+
+#define _gcmPROFILE_QUERY(prefix, start, ticks) \
+ do { \
+ prefix ## OS_GetProfileTick(&(ticks)); \
+ (ticks) = ((ticks) > (start)) ? ((ticks) - (start)) \
+ : (~0ull - (start) + (ticks) + 1); \
+ } while (gcvFALSE)
+
+#if gcdENABLE_PROFILING
+# define gcmkPROFILE_INIT(freq, start) _gcmPROFILE_INIT(gck, freq, start)
+# define gcmkPROFILE_QUERY(start, ticks) _gcmPROFILE_QUERY(gck, start, ticks)
+# define gcmPROFILE_INIT(freq, start) _gcmPROFILE_INIT(gco, freq, start)
+# define gcmPROFILE_QUERY(start, ticks) _gcmPROFILE_QUERY(gco, start, ticks)
+# define gcmPROFILE_ONLY(x) x
+# define gcmPROFILE_ELSE(x) do { } while (gcvFALSE)
+# define gcmPROFILE_DECLARE_ONLY(x) x
+# define gcmPROFILE_DECLARE_ELSE(x) typedef x
+#else
+# define gcmkPROFILE_INIT(start, freq) do { } while (gcvFALSE)
+# define gcmkPROFILE_QUERY(start, ticks) do { } while (gcvFALSE)
+# define gcmPROFILE_INIT(start, freq) do { } while (gcvFALSE)
+# define gcmPROFILE_QUERY(start, ticks) do { } while (gcvFALSE)
+# define gcmPROFILE_ONLY(x) do { } while (gcvFALSE)
+# define gcmPROFILE_ELSE(x) x
+# define gcmPROFILE_DECLARE_ONLY(x) do { } while (gcvFALSE)
+# define gcmPROFILE_DECLARE_ELSE(x) x
+#endif
+
+/*******************************************************************************
+** gcoMATH object
+*/
+
+#define gcdPI 3.14159265358979323846f
+
+/* Kernel. */
+gctINT
+gckMATH_ModuloInt(
+ IN gctINT X,
+ IN gctINT Y
+ );
+
+/* User. */
+gctUINT32
+gcoMATH_Log2in5dot5(
+ IN gctINT X
+ );
+
+
+gctFLOAT
+gcoMATH_UIntAsFloat(
+ IN gctUINT32 X
+ );
+
+gctUINT32
+gcoMATH_FloatAsUInt(
+ IN gctFLOAT X
+ );
+
+gctBOOL
+gcoMATH_CompareEqualF(
+ IN gctFLOAT X,
+ IN gctFLOAT Y
+ );
+
+gctUINT16
+gcoMATH_UInt8AsFloat16(
+ IN gctUINT8 X
+ );
+
+gctUINT32
+gcoMATH_Float16ToFloat(
+ IN gctUINT16 In
+ );
+
+gctUINT16
+gcoMATH_FloatToFloat16(
+ IN gctUINT32 In
+ );
+
+gctUINT32
+gcoMATH_Float11ToFloat(
+ IN gctUINT32 In
+ );
+
+gctUINT16
+gcoMATH_FloatToFloat11(
+ IN gctUINT32 In
+ );
+
+gctUINT32
+gcoMATH_Float10ToFloat(
+ IN gctUINT32 In
+ );
+
+gctUINT16
+gcoMATH_FloatToFloat10(
+ IN gctUINT32 In
+ );
+
+gctUINT32
+gcoMATH_Float14ToFloat(
+ IN gctUINT16 In
+ );
+
+/******************************************************************************\
+**************************** Coordinate Structures *****************************
+\******************************************************************************/
+
+typedef struct _gcsPOINT
+{
+ gctINT32 x;
+ gctINT32 y;
+}
+gcsPOINT;
+
+typedef struct _gcsSIZE
+{
+ gctINT32 width;
+ gctINT32 height;
+}
+gcsSIZE;
+
+typedef struct _gcsRECT
+{
+ gctINT32 left;
+ gctINT32 top;
+ gctINT32 right;
+ gctINT32 bottom;
+}
+gcsRECT;
+
+typedef struct _gcsPIXEL
+{
+ union
+ {
+ struct
+ {
+ gctFLOAT r, g, b, a;
+ } f;
+ struct
+ {
+ gctINT32 r, g, b, a;
+ } i;
+ struct
+ {
+ gctUINT32 r, g, b, a;
+ } ui;
+ } color;
+
+ gctFLOAT d;
+ gctUINT32 s;
+
+} gcsPIXEL;
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------- gcoSURF Common ------------------------------*/
+
+/* Color format classes. */
+typedef enum _gceFORMAT_CLASS
+{
+ gcvFORMAT_CLASS_RGBA = 4500,
+ gcvFORMAT_CLASS_YUV,
+ gcvFORMAT_CLASS_INDEX,
+ gcvFORMAT_CLASS_LUMINANCE,
+ gcvFORMAT_CLASS_BUMP,
+ gcvFORMAT_CLASS_DEPTH,
+ gcvFORMAT_CLASS_ASTC,
+ gcvFORMAT_CLASS_COMPRESSED,
+ gcvFORMAT_CLASS_OTHER
+}
+gceFORMAT_CLASS;
+
+/* Color format data type */
+typedef enum _gceFORMAT_DATATYPE
+{
+ gcvFORMAT_DATATYPE_UNSIGNED_NORMALIZED,
+ gcvFORMAT_DATATYPE_SIGNED_NORMALIZED,
+ gcvFORMAT_DATATYPE_UNSIGNED_INTEGER,
+ gcvFORMAT_DATATYPE_SIGNED_INTEGER,
+ gcvFORMAT_DATATYPE_FLOAT16,
+ gcvFORMAT_DATATYPE_FLOAT32,
+ gcvFORMAT_DATATYPE_FLOAT_E5B9G9R9,
+ gcvFORMAT_DATATYPE_FLOAT_B10G11R11F,
+ gcvFORMAT_DATATYPE_INDEX,
+ gcvFORMAT_DATATYPE_SRGB,
+ gcvFORMAT_DATATYPE_FLOAT32_UINT,
+}
+gceFORMAT_DATATYPE;
+
+/* Special enums for width field in gcsFORMAT_COMPONENT. */
+typedef enum _gceCOMPONENT_CONTROL
+{
+ gcvCOMPONENT_NOTPRESENT = 0x00,
+ gcvCOMPONENT_DONTCARE = 0x80,
+ gcvCOMPONENT_WIDTHMASK = 0x7F,
+ gcvCOMPONENT_ODD = 0x80
+}
+gceCOMPONENT_CONTROL;
+
+/* Color format component parameters. */
+typedef struct _gcsFORMAT_COMPONENT
+{
+ gctUINT8 start;
+ gctUINT8 width;
+}
+gcsFORMAT_COMPONENT;
+
+/* RGBA color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_RGBA
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT red;
+ gcsFORMAT_COMPONENT green;
+ gcsFORMAT_COMPONENT blue;
+}
+gcsFORMAT_CLASS_TYPE_RGBA;
+
+/* YUV color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_YUV
+{
+ gcsFORMAT_COMPONENT y;
+ gcsFORMAT_COMPONENT u;
+ gcsFORMAT_COMPONENT v;
+}
+gcsFORMAT_CLASS_TYPE_YUV;
+
+/* Index color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_INDEX
+{
+ gcsFORMAT_COMPONENT value;
+}
+gcsFORMAT_CLASS_TYPE_INDEX;
+
+/* Luminance color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_LUMINANCE
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT value;
+}
+gcsFORMAT_CLASS_TYPE_LUMINANCE;
+
+/* Bump map color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_BUMP
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT l;
+ gcsFORMAT_COMPONENT v;
+ gcsFORMAT_COMPONENT u;
+ gcsFORMAT_COMPONENT q;
+ gcsFORMAT_COMPONENT w;
+}
+gcsFORMAT_CLASS_TYPE_BUMP;
+
+/* Depth and stencil format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_DEPTH
+{
+ gcsFORMAT_COMPONENT depth;
+ gcsFORMAT_COMPONENT stencil;
+}
+gcsFORMAT_CLASS_TYPE_DEPTH;
+
+typedef union _gcuPIXEL_FORMAT_CLASS
+{
+ gcsFORMAT_CLASS_TYPE_BUMP bump;
+ gcsFORMAT_CLASS_TYPE_RGBA rgba;
+ gcsFORMAT_CLASS_TYPE_YUV yuv;
+ gcsFORMAT_CLASS_TYPE_LUMINANCE lum;
+ gcsFORMAT_CLASS_TYPE_INDEX index;
+ gcsFORMAT_CLASS_TYPE_DEPTH depth;
+}
+gcuPIXEL_FORMAT_CLASS;
+
+/* Format parameters. */
+typedef struct _gcsSURF_FORMAT_INFO
+{
+ /* Name of the format */
+ gctCONST_STRING formatName;
+
+ /* Format code and class. */
+ gceSURF_FORMAT format;
+ gceFORMAT_CLASS fmtClass;
+
+ /* Format data type */
+ gceFORMAT_DATATYPE fmtDataType;
+
+ /* The size of one pixel in bits. */
+ gctUINT8 bitsPerPixel;
+
+ /* Pixel block dimensions. */
+ gctUINT blockWidth;
+ gctUINT blockHeight;
+
+ /* Pixel block size in bits. */
+ gctUINT blockSize;
+
+ /* Some formats are larger than what the GPU can support. */
+ /* These formats are read in the number of layers specified. */
+ gctUINT8 layers;
+
+ /* The format is faked and software will interpret it differently
+ ** with HW. Most of them can't be blendable(PE) or filterable(TX).
+ */
+ gctBOOL fakedFormat;
+
+ /* Some formats have two neighbour pixels interleaved together. */
+ /* To describe such format, set the flag to 1 and add another */
+ /* like this one describing the odd pixel format. */
+ gctBOOL interleaved;
+
+ /* sRGB format. */
+ gctBOOL sRGB;
+
+ /* Format components. */
+ gcuPIXEL_FORMAT_CLASS u;
+
+ /* Format components. */
+ gcuPIXEL_FORMAT_CLASS uOdd;
+
+ /* Render format. */
+ gceSURF_FORMAT closestRenderFormat;
+ /*gctCLOSEST_FORMAT dynamicClosestRenderFormat;*/
+ gctUINT renderFormat;
+ const gceTEXTURE_SWIZZLE * pixelSwizzle;
+
+ /* Texture format. */
+ gceSURF_FORMAT closestTXFormat;
+ gctUINT txFormat;
+ const gceTEXTURE_SWIZZLE * txSwizzle;
+ gctBOOL txIntFilter;
+}
+gcsSURF_FORMAT_INFO;
+
+/* Frame buffer information. */
+typedef struct _gcsSURF_FRAMEBUFFER
+{
+ gctPOINTER logical;
+ gctUINT width, height;
+ gctINT stride;
+ gceSURF_FORMAT format;
+}
+gcsSURF_FRAMEBUFFER;
+
+/* Generic pixel component descriptors. */
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XXX8;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XX8X;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_X8XX;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_8XXX;
+
+typedef enum _gceORIENTATION
+{
+ gcvORIENTATION_TOP_BOTTOM,
+ gcvORIENTATION_BOTTOM_TOP,
+}
+gceORIENTATION;
+
+
+/* Construct a new gcoSURF object. */
+gceSTATUS
+gcoSURF_Construct(
+ IN gcoHAL Hal,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gcePOOL Pool,
+ OUT gcoSURF * Surface
+ );
+
+/* Destroy an gcoSURF object. */
+gceSTATUS
+gcoSURF_Destroy(
+ IN gcoSURF Surface
+ );
+
+/* Map user-allocated surface. */
+gceSTATUS
+gcoSURF_MapUserSurface(
+ IN gcoSURF Surface,
+ IN gctUINT Alignment,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+/* Wrapp surface with known logical/GPU address */
+gceSTATUS
+gcoSURF_WrapSurface(
+ IN gcoSURF Surface,
+ IN gctUINT Alignment,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+
+/* Query vid mem node info. */
+gceSTATUS
+gcoSURF_QueryVidMemNode(
+ IN gcoSURF Surface,
+ OUT gctUINT32 * Node,
+ OUT gcePOOL * Pool,
+ OUT gctSIZE_T_PTR Bytes
+ );
+
+/* Set the color type of the surface. */
+gceSTATUS
+gcoSURF_SetColorType(
+ IN gcoSURF Surface,
+ IN gceSURF_COLOR_TYPE ColorType
+ );
+
+/* Get the color type of the surface. */
+gceSTATUS
+gcoSURF_GetColorType(
+ IN gcoSURF Surface,
+ OUT gceSURF_COLOR_TYPE *ColorType
+ );
+
+/* Set the color space of the surface. */
+gceSTATUS
+gcoSURF_SetColorSpace(
+ IN gcoSURF Surface,
+ IN gceSURF_COLOR_SPACE ColorSpace
+ );
+
+/* Get the color space of the surface. */
+gceSTATUS
+gcoSURF_GetColorSpace(
+ IN gcoSURF Surface,
+ OUT gceSURF_COLOR_SPACE *ColorSpace
+ );
+
+
+/* Set the surface ration angle. */
+gceSTATUS
+gcoSURF_SetRotation(
+ IN gcoSURF Surface,
+ IN gceSURF_ROTATION Rotation
+ );
+
+gceSTATUS
+gcoSURF_IsValid(
+ IN gcoSURF Surface
+ );
+
+#if gcdENABLE_3D
+/* Verify and return the state of the tile status mechanism. */
+gceSTATUS
+gcoSURF_IsTileStatusSupported(
+ IN gcoSURF Surface
+ );
+
+/* Verify if surface has tile status enabled. */
+gceSTATUS
+gcoSURF_IsTileStatusEnabled(
+ IN gcsSURF_VIEW *SurfView
+ );
+
+/* Verify if surface is compressed. */
+gceSTATUS
+gcoSURF_IsCompressed(
+ IN gcsSURF_VIEW *SurfView
+ );
+
+/* Enable tile status for the specified surface on zero slot. */
+gceSTATUS
+gcoSURF_EnableTileStatus(
+ IN gcsSURF_VIEW *Surface
+ );
+
+/* Enable tile status for the specified surface on specified slot. */
+gceSTATUS
+gcoSURF_EnableTileStatusEx(
+ IN gcsSURF_VIEW *surfView,
+ IN gctUINT RtIndex
+ );
+
+/* Disable tile status for the specified surface. */
+gceSTATUS
+gcoSURF_DisableTileStatus(
+ IN gcsSURF_VIEW *SurfView,
+ IN gctBOOL Decompress
+ );
+
+/* Flush tile status cache for the specified surface. */
+gceSTATUS
+gcoSURF_FlushTileStatus(
+ IN gcsSURF_VIEW *SurfView,
+ IN gctBOOL Decompress
+ );
+#endif /* gcdENABLE_3D */
+
+/* Get surface size. */
+gceSTATUS
+gcoSURF_GetSize(
+ IN gcoSURF Surface,
+ OUT gctUINT * Width,
+ OUT gctUINT * Height,
+ OUT gctUINT * Depth
+ );
+
+/* Get surface information */
+gceSTATUS
+gcoSURF_GetInfo(
+ IN gcoSURF Surface,
+ IN gceSURF_INFO_TYPE InfoType,
+ IN OUT gctINT32 *Value
+ );
+
+/* Get surface aligned sizes. */
+gceSTATUS
+gcoSURF_GetAlignedSize(
+ IN gcoSURF Surface,
+ OUT gctUINT * Width,
+ OUT gctUINT * Height,
+ OUT gctINT * Stride
+ );
+
+/* Get alignments. */
+gceSTATUS
+gcoSURF_GetAlignment(
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT * AddressAlignment,
+ OUT gctUINT * XAlignment,
+ OUT gctUINT * YAlignment
+ );
+
+gceSTATUS
+gcoSURF_AlignResolveRect(
+ IN gcoSURF Surf,
+ IN gcsPOINT_PTR RectOrigin,
+ IN gcsPOINT_PTR RectSize,
+ OUT gcsPOINT_PTR AlignedOrigin,
+ OUT gcsPOINT_PTR AlignedSize
+ );
+
+/* Get surface type and format. */
+gceSTATUS
+gcoSURF_GetFormat(
+ IN gcoSURF Surface,
+ OUT OPTIONAL gceSURF_TYPE * Type,
+ OUT OPTIONAL gceSURF_FORMAT * Format
+ );
+
+/* Get surface information */
+gceSTATUS
+gcoSURF_GetFormatInfo(
+ IN gcoSURF Surface,
+ OUT gcsSURF_FORMAT_INFO_PTR * formatInfo
+ );
+
+/* Get Surface pack format */
+gceSTATUS
+gcoSURF_GetPackedFormat(
+ IN gcoSURF Surface,
+ OUT gceSURF_FORMAT * Format
+ );
+
+/* Get surface tiling. */
+gceSTATUS
+gcoSURF_GetTiling(
+ IN gcoSURF Surface,
+ OUT gceTILING * Tiling
+ );
+
+/* Get bottom buffer offset bytes. */
+gceSTATUS
+gcoSURF_GetBottomBufferOffset(
+ IN gcoSURF Surface,
+ OUT gctUINT_PTR BottomBufferOffset
+ );
+
+/* Lock the surface. */
+gceSTATUS
+gcoSURF_Lock(
+ IN gcoSURF Surface,
+ IN OUT gctUINT32 * Address,
+ IN OUT gctPOINTER * Memory
+ );
+
+/* Unlock the surface. */
+gceSTATUS
+gcoSURF_Unlock(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory
+ );
+
+/*. Query surface flags.*/
+gceSTATUS
+gcoSURF_QueryFlags(
+ IN gcoSURF Surface,
+ IN gceSURF_FLAG Flag
+ );
+
+gceSTATUS
+gcoSURF_QueryHints(
+ IN gcoSURF Surface,
+ IN gceSURF_TYPE Hints
+ );
+
+/* Return pixel format parameters; Info is required to be a pointer to an
+ * array of at least two items because some formats have up to two records
+ * of description. */
+gceSTATUS
+gcoSURF_QueryFormat(
+ IN gceSURF_FORMAT Format,
+ OUT gcsSURF_FORMAT_INFO_PTR * Info
+ );
+
+/* Compute the color pixel mask. */
+gceSTATUS
+gcoSURF_ComputeColorMask(
+ IN gcsSURF_FORMAT_INFO_PTR Format,
+ OUT gctUINT32_PTR ColorMask
+ );
+
+/* Flush the surface. */
+gceSTATUS
+gcoSURF_Flush(
+ IN gcoSURF Surface
+ );
+
+/* Fill surface from it's tile status buffer. */
+gceSTATUS
+gcoSURF_FillFromTile(
+ IN gcsSURF_VIEW *SurView
+ );
+
+/* Fill surface with a value. */
+gceSTATUS
+gcoSURF_Fill(
+ IN gcoSURF Surface,
+ IN gcsPOINT_PTR Origin,
+ IN gcsSIZE_PTR Size,
+ IN gctUINT32 Value,
+ IN gctUINT32 Mask
+ );
+
+/* Alpha blend two surfaces together. */
+gceSTATUS
+gcoSURF_Blend(
+ IN gcoSURF SrcSurf,
+ IN gcoSURF DstSurf,
+ IN gcsPOINT_PTR SrcOrigin,
+ IN gcsPOINT_PTR DstOrigin,
+ IN gcsSIZE_PTR Size,
+ IN gceSURF_BLEND_MODE Mode
+ );
+
+/* Create a new gcoSURF wrapper object. */
+gceSTATUS
+gcoSURF_ConstructWrapper(
+ IN gcoHAL Hal,
+ OUT gcoSURF * Surface
+ );
+
+/* Set surface flags.*/
+gceSTATUS
+gcoSURF_SetFlags(
+ IN gcoSURF Surface,
+ IN gceSURF_FLAG Flag,
+ IN gctBOOL Value
+ );
+
+/* Set the underlying buffer for the surface wrapper. */
+gceSTATUS
+gcoSURF_SetBuffer(
+ IN gcoSURF Surface,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Stride,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+/* Set the size of the surface in pixels and map the underlying buffer. */
+gceSTATUS
+gcoSURF_SetWindow(
+ IN gcoSURF Surface,
+ IN gctUINT X,
+ IN gctUINT Y,
+ IN gctUINT Width,
+ IN gctUINT Height
+ );
+
+/* Set the size of the surface in pixels and map the underlying buffer. */
+gceSTATUS
+gcoSURF_SetImage(
+ IN gcoSURF Surface,
+ IN gctUINT X,
+ IN gctUINT Y,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth
+ );
+
+/* Set width/height alignment of the surface directly and calculate stride/size. This is only for dri backend now. Please be careful before use. */
+gceSTATUS
+gcoSURF_SetAlignment(
+ IN gcoSURF Surface,
+ IN gctUINT Width,
+ IN gctUINT Height
+ );
+
+/* Increase reference count of the surface. */
+gceSTATUS
+gcoSURF_ReferenceSurface(
+ IN gcoSURF Surface
+ );
+
+/* Get surface reference count. */
+gceSTATUS
+gcoSURF_QueryReferenceCount(
+ IN gcoSURF Surface,
+ OUT gctINT32 * ReferenceCount
+ );
+
+/* Set surface orientation. */
+gceSTATUS
+gcoSURF_SetOrientation(
+ IN gcoSURF Surface,
+ IN gceORIENTATION Orientation
+ );
+
+/* Query surface orientation. */
+gceSTATUS
+gcoSURF_QueryOrientation(
+ IN gcoSURF Surface,
+ OUT gceORIENTATION * Orientation
+ );
+
+gceSTATUS
+gcoSURF_NODE_Cache(
+ IN gcsSURF_NODE_PTR Node,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes,
+ IN gceCACHEOPERATION Operation
+ );
+
+gceSTATUS
+gcsSURF_NODE_SetHardwareAddress(
+ IN gcsSURF_NODE_PTR Node,
+ IN gctUINT32 Address
+ );
+
+gceSTATUS
+gcsSURF_NODE_GetHardwareAddress(
+ IN gcsSURF_NODE_PTR Node,
+ OUT gctUINT32_PTR Physical,
+ OUT gctUINT32_PTR Physical2,
+ OUT gctUINT32_PTR Physical3,
+ OUT gctUINT32_PTR PhysicalBottom
+ );
+
+gctUINT32
+gcsSURF_NODE_GetHWAddress(
+ IN gcsSURF_NODE_PTR Node
+ );
+
+/* Lock and unlock surface node */
+gceSTATUS
+gcoSURF_LockNode(
+ IN gcsSURF_NODE_PTR Node,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+gceSTATUS
+gcoSURF_UnLockNode(
+ IN gcsSURF_NODE_PTR Node,
+ IN gceSURF_TYPE Type
+ );
+
+/* Perform CPU cache operation on surface node */
+gceSTATUS
+gcoSURF_NODE_CPUCacheOperation(
+ IN gcsSURF_NODE_PTR Node,
+ IN gceSURF_TYPE Type,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Length,
+ IN gceCACHEOPERATION Operation
+ );
+
+/* Perform CPU cache operation on surface */
+gceSTATUS
+gcoSURF_CPUCacheOperation(
+ IN gcoSURF Surface,
+ IN gceCACHEOPERATION Operation
+ );
+
+
+gceSTATUS
+gcoSURF_Swap(
+ IN gcoSURF Surface1,
+ IN gcoSURF Surface2
+ );
+
+gceSTATUS
+gcoSURF_ResetSurWH(
+ IN gcoSURF Surface,
+ IN gctUINT oriw,
+ IN gctUINT orih,
+ IN gctUINT alignw,
+ IN gctUINT alignh,
+ IN gceSURF_FORMAT fmt
+);
+
+/* Update surface timestamp. */
+gceSTATUS
+gcoSURF_UpdateTimeStamp(
+ IN gcoSURF Surface
+ );
+
+/* Query surface current timestamp. */
+gceSTATUS
+gcoSURF_QueryTimeStamp(
+ IN gcoSURF Surface,
+ OUT gctUINT64 * TimeStamp
+ );
+
+/*
+ * Allocate shared buffer for this surface, so that
+ * surface states can be shared across processes.
+ */
+gceSTATUS
+gcoSURF_AllocShBuffer(
+ IN gcoSURF Surface,
+ OUT gctSHBUF * ShBuf
+ );
+
+/* Bind shared buffer to this surface */
+gceSTATUS
+gcoSURF_BindShBuffer(
+ IN gcoSURF Surface,
+ IN gctSHBUF ShBuf
+ );
+
+/* Push surface shared states to shared buffer. */
+gceSTATUS
+gcoSURF_PushSharedInfo(
+ IN gcoSURF Surface
+ );
+
+/* Pop shared states from shared buffer. */
+gceSTATUS
+gcoSURF_PopSharedInfo(
+ IN gcoSURF Surface
+ );
+
+#if (gcdENABLE_3D || gcdENABLE_VG)
+/* Copy surface. */
+gceSTATUS
+gcoSURF_Copy(
+ IN gcoSURF Surface,
+ IN gcoSURF Source
+ );
+
+/* Set number of samples for a gcoSURF object. */
+gceSTATUS
+gcoSURF_SetSamples(
+ IN gcoSURF Surface,
+ IN gctUINT Samples
+ );
+
+/* Get the number of samples per pixel. */
+gceSTATUS
+gcoSURF_GetSamples(
+ IN gcoSURF Surface,
+ OUT gctUINT_PTR Samples
+ );
+
+/* Append tile status buffer to user pool surface. */
+gceSTATUS
+gcoSURF_AppendTileStatus(
+ IN gcoSURF Surface
+ );
+#endif
+
+gceSTATUS
+gcoSURF_WrapUserMemory(
+ IN gcoHAL Hal,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Stride,
+ IN gctUINT Depth,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT32 Handle,
+ IN gctUINT32 Flag,
+ OUT gcoSURF * Surface
+ );
+
+gceSTATUS
+gcoSURF_WrapUserMultiBuffer(
+ IN gcoHAL Hal,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Stride[3],
+ IN gctUINT32 Handle[3],
+ IN gctUINT BufferOffset[3],
+ IN gctUINT32 Flag,
+ OUT gcoSURF * Surface
+ );
+
+#define MAX_SURF_MIX_SRC_NUM 64
+gceSTATUS
+gcoSURF_MixSurfacesCPU(
+ IN gcoSURF TargetSurface,
+ IN gctUINT TargetSliceIndex,
+ IN gcoSURF *SourceSurface,
+ IN gctUINT *SourceSliceIndices,
+ IN gctFLOAT *Weights,
+ IN gctINT Count
+ );
+
+
+/******************************************************************************\
+********************************* gcoDUMP Object ********************************
+\******************************************************************************/
+
+/* Construct a new gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Construct(
+ IN gcoOS Os,
+ IN gcoHAL Hal,
+ OUT gcoDUMP * Dump
+ );
+
+/* Destroy a gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Destroy(
+ IN gcoDUMP Dump
+ );
+
+/* Enable/disable dumping. */
+gceSTATUS
+gcoDUMP_Control(
+ IN gcoDUMP Dump,
+ IN gctSTRING FileName
+ );
+
+gceSTATUS
+gcoDUMP_IsEnabled(
+ IN gcoDUMP Dump,
+ OUT gctBOOL * Enabled
+ );
+
+/* Add surface. */
+gceSTATUS
+gcoDUMP_AddSurface(
+ IN gcoDUMP Dump,
+ IN gctINT32 Width,
+ IN gctINT32 Height,
+ IN gceSURF_FORMAT PixelFormat,
+ IN gctUINT32 Address,
+ IN gctSIZE_T ByteCount
+ );
+
+/* Mark the beginning of a frame. */
+gceSTATUS
+gcoDUMP_FrameBegin(
+ IN gcoDUMP Dump
+ );
+
+/* Mark the end of a frame. */
+gceSTATUS
+gcoDUMP_FrameEnd(
+ IN gcoDUMP Dump
+ );
+
+/* Dump data. */
+gceSTATUS
+gcoDUMP_DumpData(
+ IN gcoDUMP Dump,
+ IN gceDUMP_TAG Type,
+ IN gctUINT32 Address,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+/* Delete an address. */
+gceSTATUS
+gcoDUMP_Delete(
+ IN gcoDUMP Dump,
+ IN gctUINT32 Address
+ );
+
+/* Enable dump or not. */
+gceSTATUS
+gcoDUMP_SetDumpFlag(
+ IN gctBOOL DumpState
+ );
+
+/******************************************************************************\
+******************************* gcsRECT Structure ******************************
+\******************************************************************************/
+
+/* Initialize rectangle structure. */
+gceSTATUS
+gcsRECT_Set(
+ OUT gcsRECT_PTR Rect,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Return the width of the rectangle. */
+gceSTATUS
+gcsRECT_Width(
+ IN gcsRECT_PTR Rect,
+ OUT gctINT32 * Width
+ );
+
+/* Return the height of the rectangle. */
+gceSTATUS
+gcsRECT_Height(
+ IN gcsRECT_PTR Rect,
+ OUT gctINT32 * Height
+ );
+
+/* Ensure that top left corner is to the left and above the right bottom. */
+gceSTATUS
+gcsRECT_Normalize(
+ IN OUT gcsRECT_PTR Rect
+ );
+
+/* Compare two rectangles. */
+gceSTATUS
+gcsRECT_IsEqual(
+ IN gcsRECT_PTR Rect1,
+ IN gcsRECT_PTR Rect2,
+ OUT gctBOOL * Equal
+ );
+
+/* Compare the sizes of two rectangles. */
+gceSTATUS
+gcsRECT_IsOfEqualSize(
+ IN gcsRECT_PTR Rect1,
+ IN gcsRECT_PTR Rect2,
+ OUT gctBOOL * EqualSize
+ );
+
+gceSTATUS
+gcsRECT_RelativeRotation(
+ IN gceSURF_ROTATION Orientation,
+ IN OUT gceSURF_ROTATION *Relation);
+
+gceSTATUS
+
+gcsRECT_Rotate(
+
+ IN OUT gcsRECT_PTR Rect,
+
+ IN gceSURF_ROTATION Rotation,
+
+ IN gceSURF_ROTATION toRotation,
+
+ IN gctINT32 SurfaceWidth,
+
+ IN gctINT32 SurfaceHeight
+
+ );
+
+/******************************************************************************\
+**************************** gcsBOUNDARY Structure *****************************
+\******************************************************************************/
+
+typedef struct _gcsBOUNDARY
+{
+ gctINT x;
+ gctINT y;
+ gctINT width;
+ gctINT height;
+}
+gcsBOUNDARY;
+
+/******************************************************************************\
+********************************* gcoHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gcoHEAP * gcoHEAP;
+
+/* Construct a new gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Construct(
+ IN gcoOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gcoHEAP * Heap
+ );
+
+/* Destroy an gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Destroy(
+ IN gcoHEAP Heap
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gcoHEAP_Allocate(
+ IN gcoHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcoHEAP_GetMemorySize(
+ IN gcoHEAP Heap,
+ IN gctPOINTER Memory,
+ OUT gctSIZE_T_PTR MemorySize
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoHEAP_Free(
+ IN gcoHEAP Heap,
+ IN gctPOINTER Node
+ );
+
+#if (VIVANTE_PROFILER || gcdDEBUG)
+/* Profile the heap. */
+gceSTATUS
+gcoHEAP_ProfileStart(
+ IN gcoHEAP Heap
+ );
+
+gceSTATUS
+gcoHEAP_ProfileEnd(
+ IN gcoHEAP Heap,
+ IN gctCONST_STRING Title
+ );
+#endif
+
+
+/******************************************************************************\
+******************************* Debugging Macros *******************************
+\******************************************************************************/
+
+void
+gcoOS_SetDebugLevel(
+ IN gctUINT32 Level
+ );
+
+void
+gcoOS_GetDebugLevel(
+ OUT gctUINT32_PTR DebugLevel
+ );
+
+void
+gcoOS_SetDebugZone(
+ IN gctUINT32 Zone
+ );
+
+void
+gcoOS_GetDebugZone(
+ IN gctUINT32 Zone,
+ OUT gctUINT32_PTR DebugZone
+ );
+
+void
+gcoOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ );
+
+void
+gcoOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ );
+
+void
+gcoOS_SetDebugFile(
+ IN gctCONST_STRING FileName
+ );
+
+gctFILE
+gcoOS_ReplaceDebugFile(
+ IN gctFILE fp
+ );
+
+/*******************************************************************************
+**
+** gcmFATAL
+**
+** Print a message to the debugger and execute a break point.
+**
+** ARGUMENTS:
+**
+** message Message.
+** ... Optional arguments.
+*/
+
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_FATAL)
+# define gcmFATAL gcoOS_DebugFatal
+# define gcmkFATAL gckOS_DebugFatal
+#elif gcdHAS_ELLIPSIS
+# define gcmFATAL(...)
+# define gcmkFATAL(...)
+#else
+ gcmINLINE static void
+ __dummy_fatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmFATAL __dummy_fatal
+# define gcmkFATAL __dummy_fatal
+#endif
+
+#define gcmENUM2TEXT(e) case e: return #e
+
+/*******************************************************************************
+**
+** gcmTRACE
+**
+** Print a message to the debugfer if the correct level has been set. In
+** retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** level Level of message.
+** message Message.
+** ... Optional arguments.
+*/
+#define gcvLEVEL_NONE -1
+#define gcvLEVEL_ERROR 0
+#define gcvLEVEL_WARNING 1
+#define gcvLEVEL_INFO 2
+#define gcvLEVEL_VERBOSE 3
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gckOS_DebugTraceN(
+ IN gctUINT32 Level,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+# define gcmTRACE gcoOS_DebugTrace
+# define gcmkTRACE gckOS_DebugTrace
+# define gcmkTRACE_N gckOS_DebugTraceN
+#elif gcdHAS_ELLIPSIS
+# define gcmTRACE(...)
+# define gcmkTRACE(...)
+# define gcmkTRACE_N(...)
+#else
+ gcmINLINE static void
+ __dummy_trace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+
+ gcmINLINE static void
+ __dummy_trace_n(
+ IN gctUINT32 Level,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+
+# define gcmTRACE __dummy_trace
+# define gcmkTRACE __dummy_trace
+# define gcmkTRACE_N __dummy_trace_n
+#endif
+
+/* Zones common for kernel and user. */
+#define gcvZONE_OS (1 << 0)
+#define gcvZONE_HARDWARE (1 << 1)
+#define gcvZONE_HEAP (1 << 2)
+#define gcvZONE_SIGNAL (1 << 3)
+
+/* Kernel zones. */
+#define gcvZONE_KERNEL (1 << 4)
+#define gcvZONE_VIDMEM (1 << 5)
+#define gcvZONE_COMMAND (1 << 6)
+#define gcvZONE_DRIVER (1 << 7)
+#define gcvZONE_CMODEL (1 << 8)
+#define gcvZONE_MMU (1 << 9)
+#define gcvZONE_EVENT (1 << 10)
+#define gcvZONE_DEVICE (1 << 11)
+#define gcvZONE_DATABASE (1 << 12)
+#define gcvZONE_INTERRUPT (1 << 13)
+#define gcvZONE_POWER (1 << 14)
+#define gcvZONE_ASYNC_COMMAND (1 << 15)
+#define gcvZONE_ALLOCATOR (1 << 16)
+
+/* User zones. */
+#define gcvZONE_HAL (1 << 4)
+#define gcvZONE_BUFFER (1 << 5)
+#define gcvZONE_CONTEXT (1 << 6)
+#define gcvZONE_SURFACE (1 << 7)
+#define gcvZONE_INDEX (1 << 8)
+#define gcvZONE_STREAM (1 << 9)
+#define gcvZONE_TEXTURE (1 << 10)
+#define gcvZONE_2D (1 << 11)
+#define gcvZONE_3D (1 << 12)
+#define gcvZONE_COMPILER (1 << 13)
+#define gcvZONE_MEMORY (1 << 14)
+#define gcvZONE_STATE (1 << 15)
+#define gcvZONE_AUX (1 << 16)
+#define gcvZONE_VERTEX (1 << 17)
+#define gcvZONE_CL (1 << 18)
+#define gcvZONE_VG (1 << 19)
+#define gcvZONE_VX (1 << 20)
+#define gcvZONE_IMAGE (1 << 21)
+#define gcvZONE_UTILITY (1 << 22)
+#define gcvZONE_PARAMETERS (1 << 23)
+#define gcvZONE_BUFOBJ (1 << 24)
+#define gcvZONE_SHADER (1 << 25)
+#define gcvZONE_STREAM_OUT (1 << 26)
+
+/* API definitions. */
+#define gcvZONE_API_HAL ((gctUINT32) 1 << 28)
+#define gcvZONE_API_EGL ((gctUINT32) 2 << 28)
+#define gcvZONE_API_ES11 ((gctUINT32) 3 << 28)
+#define gcvZONE_API_ES20 ((gctUINT32) 4 << 28)
+#define gcvZONE_API_ES30 ((gctUINT32) 4 << 28)
+#define gcvZONE_API_VG11 ((gctUINT32) 5 << 28)
+#define gcvZONE_API_GL ((gctUINT32) 6 << 28)
+#define gcvZONE_API_DFB ((gctUINT32) 7 << 28)
+#define gcvZONE_API_GDI ((gctUINT32) 8 << 28)
+#define gcvZONE_API_D3D ((gctUINT32) 9 << 28)
+#define gcvZONE_API_CL ((gctUINT32) 10 << 28)
+#define gcvZONE_API_VX ((gctUINT32) 11 << 28)
+
+
+#define gcmZONE_GET_API(zone) ((zone) >> 28)
+/*Set gcdZONE_MASE like 0x0 | gcvZONE_API_EGL
+will enable print EGL module debug info*/
+#define gcdZONE_MASK 0x0FFFFFFF
+
+/* Handy zones. */
+#define gcvZONE_NONE 0
+#define gcvZONE_ALL 0x0FFFFFFF
+
+/*Dump API depth set 1 for API, 2 for API and API behavior*/
+#define gcvDUMP_API_DEPTH 1
+
+
+/*******************************************************************************
+**
+** gcmTRACE_ZONE
+**
+** Print a message to the debugger if the correct level and zone has been
+** set. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** Level Level of message.
+** Zone Zone of message.
+** Message Message.
+** ... Optional arguments.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gckOS_DebugTraceZoneN(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+# define gcmTRACE_ZONE gcoOS_DebugTraceZone
+# define gcmkTRACE_ZONE gckOS_DebugTraceZone
+# define gcmkTRACE_ZONE_N gckOS_DebugTraceZoneN
+#elif gcdHAS_ELLIPSIS
+# define gcmTRACE_ZONE(...)
+# define gcmkTRACE_ZONE(...)
+# define gcmkTRACE_ZONE_N(...)
+#else
+ gcmINLINE static void
+ __dummy_trace_zone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+
+ gcmINLINE static void
+ __dummy_trace_zone_n(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+
+# define gcmTRACE_ZONE __dummy_trace_zone
+# define gcmkTRACE_ZONE __dummy_trace_zone
+# define gcmkTRACE_ZONE_N __dummy_trace_zone_n
+#endif
+
+
+/*******************************************************************************
+**
+** gcmDEBUG_ONLY
+**
+** Execute a statement or function only in DEBUG mode.
+**
+** ARGUMENTS:
+**
+** f Statement or function to execute.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+# define gcmDEBUG_ONLY(f) f
+#else
+# define gcmDEBUG_ONLY(f)
+#endif
+
+
+/*******************************************************************************
+**
+** gcmSTACK_PUSH
+** gcmSTACK_POP
+** gcmSTACK_DUMP
+** gcmSTACK_REMOVE
+**
+** Push or pop a function with entry arguments on the trace stack.
+**
+** ARGUMENTS:
+**
+** Function Name of function.
+** Line Line number.
+** Text Optional text.
+** ... Optional arguments for text.
+**
+** Thread Thread id.
+*/
+void
+gcoOS_StackPush(
+ IN gctINT8_PTR Identity,
+ IN gctCONST_STRING Function,
+ IN gctINT Line,
+ IN gctCONST_STRING Text,
+ ...
+ );
+
+void
+gcoOS_StackPop(
+ IN gctINT8_PTR Identity,
+ IN gctCONST_STRING Function
+ );
+
+void
+gcoOS_StackDump(
+ void);
+
+void
+gcoOS_StackRemove(
+ IN gctHANDLE Thread
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_STACK)
+# define gcmSTACK_PUSH gcoOS_StackPush
+# define gcmSTACK_POP gcoOS_StackPop
+# define gcmSTACK_DUMP gcoOS_StackDump
+# define gcmSTACK_REMOVE gcoOS_StackRemove
+#elif gcdHAS_ELLIPSIS
+# define gcmSTACK_PUSH(...)
+# define gcmSTACK_POP(...)
+# define gcmSTACK_DUMP()
+# define gcmSTACK_REMOVE(...)
+#else
+ gcmINLINE static void
+ __dummy_stack_push(
+ IN gctCONST_STRING Function,
+ IN gctINT Line,
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+
+ gcmINLINE static void
+ __dummy_stack_pop(
+ IN gctINT8_PTR Identity,
+ IN gctCONST_STRING Function
+ );
+
+ gcmINLINE static void
+ __dummy_stack_remove(
+ IN gctHANDLE Thread
+ );
+
+# define gcmSTACK_PUSH __dummy_stack_push
+# define gcmSTACK_POP(a,b) __dummy_stack_pop
+# define gcmSTACK_DUMP()
+# define gcmSTACK_REMOVE(a) __dummy_stack_remove
+#endif
+
+
+/*******************************************************************************
+**
+** gcmBINARY_TRACE
+**
+** Push or pop a function with entry arguments on the trace stack.
+**
+** ARGUMENTS:
+**
+** Function Name of function
+** Line Line number
+** Text Optional text
+** ... Optional arguments for text.
+*/
+typedef struct _gcsBINARY_TRACE_MESSAGE * gcsBINARY_TRACE_MESSAGE_PTR;
+typedef struct _gcsBINARY_TRACE_MESSAGE
+{
+ gctUINT32 signature;
+ gctUINT32 pid;
+ gctUINT32 tid;
+ gctUINT32 line;
+ gctUINT32 numArguments;
+ gctUINT8 payload;
+}
+gcsBINARY_TRACE_MESSAGE;
+
+void
+gcoOS_BinaryTrace(
+ IN gctCONST_STRING Function,
+ IN gctINT Line,
+ IN gctCONST_STRING Text OPTIONAL,
+ ...
+ );
+
+void
+gckOS_BinaryTrace(
+ IN gctCONST_STRING Function,
+ IN gctINT Line,
+ IN gctCONST_STRING Text OPTIONAL,
+ ...
+ );
+
+#define gcdBINARY_TRACE_MESSAGE_SIZE 240
+
+#if gcdBINARY_TRACE
+# define gcmBINARY_TRACE gcoOS_BinaryTrace
+# define gcmkBINARY_TRACE gckOS_BinaryTrace
+#elif gcdHAS_ELLIPSIS
+# define gcmBINARY_TRACE(Function, Line, Text, ...)
+# define gcmkBINARY_TRACE(Function, Line, Text, ...)
+#else
+ gcmINLINE static void
+ __dummy_binary_trace(
+ IN gctCONST_STRING Function,
+ IN gctINT Line,
+ IN gctCONST_STRING Text,
+ )
+ {
+ }
+
+# define gcmBINARY_TRACE __dummy_binary_trace
+# define gcmkBINARY_TRACE __dummy_binary_trace
+#endif
+
+
+/*******************************************************************************
+**
+** gcmSYSTRACE_BEGIN
+** gcmSYSTRACE_END
+**
+** Systrace is a performance tunning tool on linux.
+**
+** ARGUMENTS:
+**
+** FuncName Function name
+** Zone Systrace zone. Only specified zones are traced.
+*/
+
+void
+gcoOS_SysTraceBegin(
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING FuncName
+ );
+
+void
+gcoOS_SysTraceEnd(
+ IN gctUINT32 Zone
+ );
+
+#if defined(LINUX) && gcdSYSTRACE
+# define gcmSYSTRACE_BEGIN gcoOS_SysTraceBegin
+# define gcmSYSTRACE_END gcoOS_SysTraceEnd
+#elif gcdHAS_ELLIPSIS
+# define gcmSYSTRACE_BEGIN(...)
+# define gcmSYSTRACE_END(...)
+#else
+ gcmINLINE static void
+ __dummy_systrace_begin(
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING FuncName
+ )
+ {
+ }
+
+ gcmINLINE static void
+ __dummy_systrace_end(
+ IN gctUINT32 Zone
+ )
+ {
+ }
+
+# define gcmSYSTRACE_BEGIN __dummy_systrace_begin
+# define gcmSYSTRACE_END __dummy_systrace_end
+#endif
+
+
+/******************************************************************************\
+******************************** Logging Macros ********************************
+\******************************************************************************/
+
+#define gcdHEADER_LEVEL gcvLEVEL_VERBOSE
+
+/* Always enable header/footer when systrace build is on */
+#if defined(LINUX) && gcdSYSTRACE
+#undef gcdEMPTY_HEADER_FOOTER
+#endif
+
+#ifndef gcdEMPTY_HEADER_FOOTER
+#define gcdEMPTY_HEADER_FOOTER 0
+#endif
+
+#if gcdENABLE_PROFILING
+void
+gcoOS_ProfileDB(
+ IN gctCONST_STRING Function,
+ IN OUT gctBOOL_PTR Initialized
+ );
+
+#define gcmHEADER() \
+ gctINT8 __user__ = 1; \
+ static gctBOOL __profile__initialized__ = gcvFALSE; \
+ gcmSTACK_PUSH(&__user__, __FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
+
+#define gcmHEADER_ARG(...) \
+ gctINT8 __user__ = 1; \
+ static gctBOOL __profile__initialized__ = gcvFALSE; \
+ gcmSTACK_PUSH(&__user__, __FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+ gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
+
+#define gcmFOOTER() \
+ gcmSTACK_POP(&__user__, __FUNCTION__); \
+ gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+
+#define gcmFOOTER_NO() \
+ gcmSTACK_POP(&__user__, __FUNCTION__); \
+ gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+
+#define gcmFOOTER_ARG(...) \
+ gcmSTACK_POP(&__user__, __FUNCTION__); \
+ gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
+
+#define gcmFOOTER_KILL() \
+ gcmSTACK_POP(&__user__, __FUNCTION__); \
+ gcoOS_ProfileDB(gcvNULL, gcvNULL)
+
+#else /* !gcdENABLE_PROFILING */
+
+#if gcdEMPTY_HEADER_FOOTER
+# define gcmHEADER()
+#elif gcdHAS_ELLIPSIS
+#define gcmHEADER() \
+ gctINT8 __user__ = 1; \
+ gctINT8_PTR __user_ptr__ = &__user__; \
+ gcmSTACK_PUSH(__user_ptr__, __FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmSYSTRACE_BEGIN(_GC_OBJ_ZONE, __FUNCTION__); \
+ gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d)", __FUNCTION__, __LINE__)
+#else
+ gcmINLINE static void
+ __dummy_header(void)
+ {
+ }
+# define gcmHEADER __dummy_header
+#endif
+
+#if gcdHAS_ELLIPSIS
+#if gcdEMPTY_HEADER_FOOTER
+# define gcmHEADER_ARG(Text, ...)
+#else
+# define gcmHEADER_ARG(Text, ...) \
+ gctINT8 __user__ = 1; \
+ gctINT8_PTR __user_ptr__ = &__user__; \
+ gcmSTACK_PUSH(__user_ptr__, __FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+ gcmSYSTRACE_BEGIN(_GC_OBJ_ZONE, __FUNCTION__); \
+ gcmBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#endif
+#else
+ gcmINLINE static void
+ __dummy_header_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmHEADER_ARG __dummy_header_arg
+#endif
+
+#if gcdEMPTY_HEADER_FOOTER
+# define gcmFOOTER()
+#elif gcdHAS_ELLIPSIS
+# define gcmFOOTER() \
+ gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
+ gcmSYSTRACE_END(_GC_OBJ_ZONE); \
+ gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): status=%d(%s)", \
+ __FUNCTION__, __LINE__, \
+ status, gcmSTATUS2NAME(status)); \
+ *__user_ptr__ -= 1
+#else
+ gcmINLINE static void
+ __dummy_footer(void)
+ {
+ }
+# define gcmFOOTER __dummy_footer
+#endif
+
+#if gcdEMPTY_HEADER_FOOTER
+# define gcmFOOTER_NO()
+#elif gcdHAS_ELLIPSIS
+#define gcmFOOTER_NO() \
+ gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
+ gcmSYSTRACE_END(_GC_OBJ_ZONE); \
+ gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d)", __FUNCTION__, __LINE__); \
+ *__user_ptr__ -= 1
+#else
+ gcmINLINE static void
+ __dummy_footer_no(void)
+ {
+ }
+# define gcmFOOTER_NO __dummy_footer_no
+#endif
+
+#if gcdEMPTY_HEADER_FOOTER
+# define gcmFOOTER_KILL()
+#elif gcdHAS_ELLIPSIS
+#define gcmFOOTER_KILL() \
+ gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
+ gcmSYSTRACE_END(_GC_OBJ_ZONE); \
+ gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d)", __FUNCTION__, __LINE__); \
+ *__user_ptr__ -= 1
+#else
+ gcmINLINE static void
+ __dummy_footer_kill(void)
+ {
+ }
+# define gcmFOOTER_KILL __dummy_footer_kill
+#endif
+
+#if gcdHAS_ELLIPSIS
+#if gcdEMPTY_HEADER_FOOTER
+# define gcmFOOTER_ARG(Text, ...)
+#else
+# define gcmFOOTER_ARG(Text, ...) \
+ gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
+ gcmSYSTRACE_END(_GC_OBJ_ZONE); \
+ gcmBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__); \
+ *__user_ptr__ -= 1
+#endif
+#else
+ gcmINLINE static void
+ __dummy_footer_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmFOOTER_ARG __dummy_footer_arg
+#endif
+
+#endif /* gcdENABLE_PROFILING */
+
+#if gcdHAS_ELLIPSIS
+#define gcmkHEADER() \
+ gctINT8 __kernel__ = 1; \
+ gctINT8_PTR __kernel_ptr__ = &__kernel__; \
+ gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d)", __FUNCTION__, __LINE__)
+#else
+ gcmINLINE static void
+ __dummy_kheader(void)
+ {
+ }
+# define gcmkHEADER __dummy_kheader
+#endif
+
+#if gcdHAS_ELLIPSIS
+# define gcmkHEADER_ARG(Text, ...) \
+ gctINT8 __kernel__ = 1; \
+ gctINT8_PTR __kernel_ptr__ = &__kernel__; \
+ gcmkBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_kheader_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmkHEADER_ARG __dummy_kheader_arg
+#endif
+
+#if gcdHAS_ELLIPSIS
+#define gcmkFOOTER() \
+ gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, status); \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): status=%d(%s)", \
+ __FUNCTION__, __LINE__, status, gcmkSTATUS2NAME(status)); \
+ *__kernel_ptr__ -= 1
+#else
+ gcmINLINE static void
+ __dummy_kfooter(void)
+ {
+ }
+# define gcmkFOOTER __dummy_kfooter
+#endif
+
+#if gcdHAS_ELLIPSIS
+#define gcmkFOOTER_NO() \
+ gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d)", __FUNCTION__, __LINE__); \
+ *__kernel_ptr__ -= 1
+#else
+ gcmINLINE static void
+ __dummy_kfooter_no(void)
+ {
+ }
+# define gcmkFOOTER_NO __dummy_kfooter_no
+#endif
+
+#if gcdHAS_ELLIPSIS
+# define gcmkFOOTER_ARG(Text, ...) \
+ gcmkBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): " Text, \
+ __FUNCTION__, __LINE__, __VA_ARGS__); \
+ *__kernel_ptr__ -= 1
+#else
+ gcmINLINE static void
+ __dummy_kfooter_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmkFOOTER_ARG __dummy_kfooter_arg
+#endif
+
+#define gcmOPT_VALUE(ptr) (((ptr) == gcvNULL) ? 0 : *(ptr))
+#define gcmOPT_VALUE_INDEX(ptr, index) (((ptr) == gcvNULL) ? 0 : ptr[index])
+#define gcmOPT_POINTER(ptr) (((ptr) == gcvNULL) ? gcvNULL : *(ptr))
+#define gcmOPT_STRING(ptr) (((ptr) == gcvNULL) ? "(nil)" : (ptr))
+
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gckOS_PrintN(
+ IN gctUINT ArgumentSize,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gckOS_CopyPrint(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#define gcmPRINT gcoOS_Print
+#define gcmkPRINT gckOS_Print
+#define gcmkPRINT_N gckOS_PrintN
+
+#if gcdPRINT_VERSION
+# define gcmPRINT_VERSION() do { \
+ _gcmPRINT_VERSION(gcm); \
+ gcmSTACK_DUMP(); \
+ } while (0)
+# define gcmkPRINT_VERSION() _gcmPRINT_VERSION(gcmk)
+# define _gcmPRINT_VERSION(prefix) \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ "Vivante HAL version %d.%d.%d build %d", \
+ gcvVERSION_MAJOR, gcvVERSION_MINOR, \
+ gcvVERSION_PATCH, gcvVERSION_BUILD)
+#else
+# define gcmPRINT_VERSION() do { gcmSTACK_DUMP(); } while (gcvFALSE)
+# define gcmkPRINT_VERSION() do { } while (gcvFALSE)
+#endif
+
+typedef enum _gceDUMP_BUFFER
+{
+ gceDUMP_BUFFER_CONTEXT,
+ gceDUMP_BUFFER_USER,
+ gceDUMP_BUFFER_KERNEL,
+ gceDUMP_BUFFER_LINK,
+ gceDUMP_BUFFER_WAITLINK,
+ gceDUMP_BUFFER_FROM_USER,
+}
+gceDUMP_BUFFER;
+
+void
+gckOS_DumpBuffer(
+ IN gckOS Os,
+ IN gctPOINTER Buffer,
+ IN gctSIZE_T Size,
+ IN gceDUMP_BUFFER Type,
+ IN gctBOOL CopyMessage
+ );
+
+#define gcmkDUMPBUFFER gckOS_DumpBuffer
+
+#if gcdDUMP_COMMAND
+# define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage) \
+ gcmkDUMPBUFFER(Os, Buffer, Size, Type, CopyMessage)
+#else
+# define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage)
+#endif
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+
+void
+gckOS_DebugFlush(
+ gctCONST_STRING CallerName,
+ gctUINT LineNumber,
+ gctUINT32 DmaAddress
+ );
+
+# define gcmkDEBUGFLUSH(DmaAddress) \
+ gckOS_DebugFlush(__FUNCTION__, __LINE__, DmaAddress)
+#else
+# define gcmkDEBUGFLUSH(DmaAddress)
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_FRAMERATE
+**
+** Print average frame rate
+**
+*/
+#if gcdDUMP_FRAMERATE
+ gceSTATUS
+ gcfDumpFrameRate(
+ void
+ );
+# define gcmDUMP_FRAMERATE gcfDumpFrameRate
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_FRAMERATE(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_frame_rate(
+ void
+ )
+ {
+ }
+# define gcmDUMP_FRAMERATE __dummy_dump_frame_rate
+#endif
+
+
+/*******************************************************************************
+**
+** gcmDUMP
+**
+** Print a dump message.
+**
+** ARGUMENTS:
+**
+** gctSTRING Message.
+**
+** ... Optional arguments.
+*/
+#if gcdDUMP
+ gceSTATUS
+ gcfDump(
+ IN gcoOS Os,
+ IN gctCONST_STRING String,
+ ...
+ );
+# define gcmDUMP gcfDump
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP(...)
+#else
+ gcmINLINE static void
+ __dummy_dump(
+ IN gcoOS Os,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmDUMP __dummy_dump
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_DATA
+**
+** Add data to the dump.
+**
+** ARGUMENTS:
+**
+** gctSTRING Tag
+** Tag for dump.
+**
+** gctPOINTER Logical
+** Logical address of buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes.
+*/
+
+#if gcdDUMP || gcdDUMP_COMMAND
+ gceSTATUS
+ gcfDumpData(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+# define gcmDUMP_DATA gcfDumpData
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_DATA(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_data(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+ {
+ }
+# define gcmDUMP_DATA __dummy_dump_data
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_BUFFER
+**
+** Print a buffer to the dump.
+**
+** ARGUMENTS:
+**
+** gctSTRING Tag
+** Tag for dump.
+**
+** gctUINT32 Physical
+** Physical address of buffer.
+**
+** gctPOINTER Logical
+** Logical address of buffer.
+**
+** gctUINT32 Offset
+** Offset into buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes.
+*/
+
+#if gcdDUMP || gcdDUMP_COMMAND
+gceSTATUS
+gcfDumpBuffer(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Bytes
+ );
+# define gcmDUMP_BUFFER gcfDumpBuffer
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_BUFFER(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_buffer(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes
+ )
+ {
+ }
+# define gcmDUMP_BUFFER __dummy_dump_buffer
+#endif
+
+#if gcdDUMP
+void
+gcfDumpLock(
+ void
+ );
+# define gcmDUMP_LOCK gcfDumpLock
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_LOCK(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_lock(
+ void
+ )
+ {
+ }
+# define gcmDUMP_LOCK __dummy_dump_lock
+#endif
+
+#if gcdDUMP
+void
+gcfDumpUnlock(
+ void
+ );
+# define gcmDUMP_UNLOCK gcfDumpUnlock
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_UNLOCK(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_unlock(
+ void
+ )
+ {
+ }
+# define gcmDUMP_UNLOCK __dummy_dump_unlock
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API
+**
+** Print a dump message for a high level API prefixed by the function name.
+**
+** ARGUMENTS:
+**
+** gctSTRING Message.
+**
+** ... Optional arguments.
+*/
+gceSTATUS gcfDumpApi(IN gctCONST_STRING String, ...);
+#if gcdDUMP_API
+# define gcmDUMP_API gcfDumpApi
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_API(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api(
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmDUMP_API __dummy_dump_api
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_ARRAY
+**
+** Print an array of data.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to array.
+** gctUINT32 Size.
+*/
+gceSTATUS gcfDumpArray(IN gctCONST_POINTER Data, IN gctUINT32 Size);
+#if gcdDUMP_API
+# define gcmDUMP_API_ARRAY gcfDumpArray
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_API_ARRAY(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_array(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Size
+ )
+ {
+ }
+# define gcmDUMP_API_ARRAY __dummy_dump_api_array
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_ARRAY_TOKEN
+**
+** Print an array of data terminated by a token.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to array.
+** gctUINT32 Termination.
+*/
+gceSTATUS gcfDumpArrayToken(IN gctCONST_POINTER Data, IN gctUINT32 Termination);
+#if gcdDUMP_API
+# define gcmDUMP_API_ARRAY_TOKEN gcfDumpArrayToken
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_API_ARRAY_TOKEN(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_array_token(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Termination
+ )
+ {
+ }
+# define gcmDUMP_API_ARRAY_TOKEN __dummy_dump_api_array_token
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_DATA
+**
+** Print an array of bytes.
+**
+** ARGUMENTS:
+**
+** gctCONST_POINTER Pointer to array.
+** gctSIZE_T Size.
+*/
+gceSTATUS gcfDumpApiData(IN gctCONST_POINTER Data, IN gctSIZE_T Size);
+#if gcdDUMP_API
+# define gcmDUMP_API_DATA gcfDumpApiData
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_API_DATA(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_data(
+ IN gctCONST_POINTER Data,
+ IN gctSIZE_T Size
+ )
+ {
+ }
+# define gcmDUMP_API_DATA __dummy_dump_api_data
+#endif
+
+/*******************************************************************************
+** gcmDUMP_2D_COMMAND
+**
+** Print the 2D command buffer.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to the command buffer.
+** gctUINT32 Command buffer size.
+*/
+gceSTATUS gcfDump2DCommand(IN gctUINT32_PTR Command, IN gctUINT32 Size);
+#if gcdDUMP_2D
+# define gcmDUMP_2D_COMMAND(cmd, size) \
+ if (Hardware->newDump2DLevel > 1) \
+ gcfDump2DCommand(cmd, size)
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_2D_COMMAND(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_2d_command(
+ IN gctUINT32_PTR Command,
+ IN gctUINT32 Size
+ )
+ {
+ }
+# define gcmDUMP_2D_COMMAND __dummy_dump_2d_command
+#endif
+
+/*******************************************************************************
+** gcmDUMP_2D_SURFACE
+**
+** Print the 2D surface memory.
+**
+** ARGUMENTS:
+**
+** gctBOOL Src.
+** gctUINT32 Address.
+*/
+gceSTATUS gcfDump2DSurface(IN gctBOOL Src, IN gctUINT32 Address);
+#if gcdDUMP_2D
+# define gcmDUMP_2D_SURFACE(src, addr) \
+ if (Hardware->newDump2DLevel > 2) \
+ gcfDump2DSurface(src, addr)
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_2D_SURFACE(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_2d_surface(
+ IN gctBOOL Src,
+ IN gctUINT32 Address
+ )
+ {
+ }
+# define gcmDUMP_2D_SURFACE __dummy_dump_2d_surface
+#endif
+
+/*******************************************************************************
+** gcmDUMP_ADD_MEMORY_INFO
+**
+** Record the memory info.
+**
+** ARGUMENTS:
+**
+** gctUINT32 Address.
+** gctSIZE_T Size.
+*/
+gceSTATUS gcfAddMemoryInfo(IN gctUINT32 GPUAddress, IN gctPOINTER Logical, IN gctUINT32 Physical, IN gctUINT32 Size);
+#if gcdDUMP_2D
+# define gcmDUMP_ADD_MEMORY_INFO gcfAddMemoryInfo
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_ADD_MEMORY_INFO(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_add_memory_info(
+ IN gctUINT32 GPUAddress,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Size
+ )
+ {
+ }
+# define gcmDUMP_ADD_MEMORY_INFO __dummy_dump_add_memory_info
+#endif
+
+/*******************************************************************************
+** gcmDUMP_DEL_MEMORY_INFO
+**
+** Record the memory info.
+**
+** ARGUMENTS:
+**
+** gctUINT32 Address.
+*/
+gceSTATUS gcfDelMemoryInfo(IN gctUINT32 Address);
+#if gcdDUMP_2D
+# define gcmDUMP_DEL_MEMORY_INFO gcfDelMemoryInfo
+#elif gcdHAS_ELLIPSIS
+# define gcmDUMP_DEL_MEMORY_INFO(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_del_memory_info(
+ IN gctUINT32 Address
+ )
+ {
+ }
+# define gcmDUMP_DEL_MEMORY_INFO __dummy_dump_del_memory_info
+#endif
+
+/*******************************************************************************
+**
+** gcmTRACE_RELEASE
+**
+** Print a message to the shader debugger.
+**
+** ARGUMENTS:
+**
+** message Message.
+** ... Optional arguments.
+*/
+
+#define gcmTRACE_RELEASE gcoOS_DebugShaderTrace
+
+void
+gcoOS_DebugShaderTrace(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_SetDebugShaderFiles(
+ IN gctCONST_STRING VSFileName,
+ IN gctCONST_STRING FSFileName
+ );
+
+void
+gcoOS_SetDebugShaderFileType(
+ IN gctUINT32 ShaderType
+ );
+
+void
+gcoOS_EnableDebugBuffer(
+ IN gctBOOL Enable
+ );
+
+/*******************************************************************************
+**
+** gcmBREAK
+**
+** Break into the debugger. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** None.
+*/
+
+void
+gcoOS_DebugBreak(
+ void
+ );
+
+void
+gckOS_DebugBreak(
+ void
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_BREAK)
+# define gcmBREAK gcoOS_DebugBreak
+# define gcmkBREAK gckOS_DebugBreak
+#else
+# define gcmBREAK()
+# define gcmkBREAK()
+#endif
+
+/*******************************************************************************
+**
+** gcmASSERT
+**
+** Evaluate an expression and break into the debugger if the expression
+** evaluates to false. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** exp Expression to evaluate.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+# define _gcmASSERT(prefix, exp) \
+ do \
+ { \
+ if (!(exp)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ASSERT at %s(%d)", \
+ __FUNCTION__, __LINE__); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ "(%s)", #exp); \
+ prefix##BREAK(); \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmASSERT(exp) _gcmASSERT(gcm, exp)
+# define gcmkASSERT(exp) _gcmASSERT(gcmk, exp)
+#else
+# define gcmASSERT(exp)
+# define gcmkASSERT(exp)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY
+**
+** Verify if an expression returns true. If the expression does not
+** evaluates to true, an assertion will happen in debug mode.
+**
+** ARGUMENTS:
+**
+** exp Expression to evaluate.
+*/
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+# define gcmVERIFY(exp) gcmASSERT(exp)
+# define gcmkVERIFY(exp) gcmkASSERT(exp)
+#else
+# define gcmVERIFY(exp) exp
+# define gcmkVERIFY(exp) exp
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY_OK
+**
+** Verify a fucntion returns gcvSTATUS_OK. If the function does not return
+** gcvSTATUS_OK, an assertion will happen in debug mode.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+
+void
+gcoOS_Verify(
+ IN gceSTATUS status
+ );
+
+void
+gckOS_Verify(
+ IN gceSTATUS status
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
+# define gcmVERIFY_OK(func) \
+ do \
+ { \
+ gceSTATUS verifyStatus = func; \
+ gcoOS_Verify(verifyStatus); \
+ if (verifyStatus != gcvSTATUS_OK) \
+ { \
+ gcmTRACE( \
+ gcvLEVEL_ERROR, \
+ "gcmVERIFY_OK(%d): function returned %d", \
+ __LINE__, verifyStatus \
+ ); \
+ } \
+ gcmASSERT(verifyStatus == gcvSTATUS_OK); \
+ } \
+ while (gcvFALSE)
+# define gcmkVERIFY_OK(func) \
+ do \
+ { \
+ gceSTATUS verifyStatus = func; \
+ if (verifyStatus != gcvSTATUS_OK) \
+ { \
+ gcmkTRACE( \
+ gcvLEVEL_ERROR, \
+ "gcmkVERIFY_OK(%d): function returned %d", \
+ __LINE__, verifyStatus \
+ ); \
+ } \
+ gckOS_Verify(verifyStatus); \
+ gcmkASSERT(verifyStatus == gcvSTATUS_OK); \
+ } \
+ while (gcvFALSE)
+#else
+# define gcmVERIFY_OK(func) func
+# define gcmkVERIFY_OK(func) func
+#endif
+
+gctCONST_STRING
+gcoOS_DebugStatus2Name(
+ gceSTATUS status
+ );
+
+gctCONST_STRING
+gckOS_DebugStatus2Name(
+ gceSTATUS status
+ );
+
+#if gcmIS_DEBUG(gcdDEBUG)
+# define gcmSTATUS2NAME gcoOS_DebugStatus2Name
+# define gcmkSTATUS2NAME gckOS_DebugStatus2Name
+#else
+# define gcmSTATUS2NAME(status) status
+# define gcmkSTATUS2NAME(status) status
+#endif
+
+/*******************************************************************************
+**
+** gcmERR_BREAK
+**
+** Executes a break statement on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmERR_BREAK(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
+ status, gcmSTATUS2NAME(status), __FUNCTION__, __LINE__); \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+#define _gcmkERR_BREAK(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
+ status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+#define gcmERR_BREAK(func) _gcmERR_BREAK(gcm, func)
+#define gcmkERR_BREAK(func) _gcmkERR_BREAK(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmERR_RETURN
+**
+** Executes a return on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmERR_RETURN(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+ status, gcmSTATUS2NAME(status), __FUNCTION__, __LINE__); \
+ prefix##FOOTER(); \
+ return status; \
+ } \
+ do { } while (gcvFALSE)
+#define _gcmkERR_RETURN(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+ status, gcmkSTATUS2NAME(status), __FUNCTION__, __LINE__); \
+ prefix##FOOTER(); \
+ return status; \
+ } \
+ do { } while (gcvFALSE)
+#define gcmERR_RETURN(func) _gcmERR_RETURN(gcm, func)
+#define gcmkERR_RETURN(func) _gcmkERR_RETURN(gcmk, func)
+
+
+/*******************************************************************************
+**
+** gcmONERROR
+**
+** Jump to the error handler in case there is an error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmONERROR(prefix, func) \
+ do \
+ { \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
+ status, gcmSTATUS2NAME(status), __FUNCTION__, __LINE__); \
+ goto OnError; \
+ } \
+ } \
+ while (gcvFALSE)
+#define _gcmkONERROR(prefix, func) \
+ do \
+ { \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
+ status, gcmkSTATUS2NAME(status), __FUNCTION__, __LINE__); \
+ goto OnError; \
+ } \
+ } \
+ while (gcvFALSE)
+#define gcmONERROR(func) _gcmONERROR(gcm, func)
+#define gcmkONERROR(func) _gcmkONERROR(gcmk, func)
+
+#define gcmGET_INDEX_SIZE(type, size) \
+ switch (type) \
+ { \
+ case gcvINDEX_8: \
+ size = 1; \
+ break; \
+ case gcvINDEX_16: \
+ size = 2; \
+ break; \
+ case gcvINDEX_32: \
+ size = 4; \
+ break; \
+ default: \
+ gcmONERROR(gcvSTATUS_INVALID_ARGUMENT); \
+ } \
+
+/*******************************************************************************
+**
+** gcmkSAFECASTSIZET
+**
+** Check wether value of a gctSIZE_T varible beyond the capability
+** of 32bits GPU hardware.
+**
+** ASSUMPTIONS:
+**
+**
+**
+** ARGUMENTS:
+**
+** x A gctUINT32 variable
+** y A gctSIZE_T variable
+*/
+#define gcmkSAFECASTSIZET(x, y) \
+ do \
+ { \
+ gctUINT32 tmp = (gctUINT32)(y); \
+ if (gcmSIZEOF(gctSIZE_T) > gcmSIZEOF(gctUINT32)) \
+ { \
+ gcmkASSERT(tmp <= gcvMAXUINT32); \
+ } \
+ (x) = tmp; \
+ } \
+ while (gcvFALSE)
+
+#define gcmSAFECASTSIZET(x, y) \
+ do \
+ { \
+ gctUINT32 tmp = (gctUINT32)(y); \
+ if (gcmSIZEOF(gctSIZE_T) > gcmSIZEOF(gctUINT32)) \
+ { \
+ gcmASSERT(tmp <= gcvMAXUINT32); \
+ } \
+ (x) = tmp; \
+ } \
+ while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmkSAFECASTPHYSADDRT
+**
+** Check whether value of a gctPHYS_ADDR_T variable beyond the capability
+** of 32bits GPU hardware.
+**
+** ASSUMPTIONS:
+**
+**
+**
+** ARGUMENTS:
+**
+** x A gctUINT32 variable
+** y A gctPHYS_ADDR_T variable
+*/
+#define gcmkSAFECASTPHYSADDRT(x, y) \
+ do \
+ { \
+ gctUINT32 tmp = (gctUINT32)(y); \
+ if (gcmSIZEOF(gctPHYS_ADDR_T) > gcmSIZEOF(gctUINT32)) \
+ { \
+ gcmkASSERT(tmp <= gcvMAXUINT32); \
+ } \
+ (x) = tmp; \
+ } \
+ while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmSAFECASTPHYSADDRT
+**
+** Check whether value of a gctPHYS_ADDR_T variable beyond the capability
+** of 32bits GPU hardware.
+**
+** ASSUMPTIONS:
+**
+**
+**
+** ARGUMENTS:
+**
+** x A gctUINT32 variable
+** y A gctPHYS_ADDR_T variable
+*/
+#define gcmSAFECASTPHYSADDRT(x, y) \
+ do \
+ { \
+ gctUINT32 tmp = (gctUINT32)(y); \
+ if (gcmSIZEOF(gctPHYS_ADDR_T) > gcmSIZEOF(gctUINT32)) \
+ { \
+ gcmASSERT(tmp <= gcvMAXUINT32); \
+ } \
+ (x) = tmp; \
+ } \
+ while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmVERIFY_LOCK
+**
+** Verifies whether the surface is locked.
+**
+** ARGUMENTS:
+**
+** surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_LOCK(surfaceInfo) \
+ if (!surfaceInfo->node.valid) \
+ { \
+ gcmONERROR(gcvSTATUS_MEMORY_UNLOCKED); \
+ } \
+
+/*******************************************************************************
+**
+** gcmVERIFY_NODE_LOCK
+**
+** Verifies whether the surface node is locked.
+**
+** ARGUMENTS:
+**
+** surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_NODE_LOCK(surfaceNode) \
+ if (!(surfaceNode)->valid) \
+ { \
+ status = gcvSTATUS_MEMORY_UNLOCKED; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmBADOBJECT_BREAK
+**
+** Executes a break statement on bad object.
+**
+** ARGUMENTS:
+**
+** obj Object to test.
+** t Expected type of the object.
+*/
+#define gcmBADOBJECT_BREAK(obj, t) \
+ if ((obj == gcvNULL) \
+ || (((gcsOBJECT *)(obj))->type != t) \
+ ) \
+ { \
+ status = gcvSTATUS_INVALID_OBJECT; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmCHECK_STATUS
+**
+** Executes a break statement on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmCHECK_STATUS(prefix, func) \
+ do \
+ { \
+ last = func; \
+ if (gcmIS_ERROR(last)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
+ last, gcmSTATUS2NAME(last), __FUNCTION__, __LINE__); \
+ status = last; \
+ } \
+ } \
+ while (gcvFALSE)
+#define _gcmkCHECK_STATUS(prefix, func) \
+ do \
+ { \
+ last = func; \
+ if (gcmIS_ERROR(last)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
+ last, gcmkSTATUS2NAME(last), __FUNCTION__, __LINE__); \
+ status = last; \
+ } \
+ } \
+ while (gcvFALSE)
+#define gcmCHECK_STATUS(func) _gcmCHECK_STATUS(gcm, func)
+#define gcmkCHECK_STATUS(func) _gcmkCHECK_STATUS(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmVERIFY_ARGUMENT
+**
+** Assert if an argument does not apply to the specified expression. If
+** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+** returned from the current function. In retail mode this macro does
+** nothing.
+**
+** ARGUMENTS:
+**
+** arg Argument to evaluate.
+*/
+# define _gcmVERIFY_ARGUMENT(prefix, arg) \
+ do \
+ { \
+ if (!(arg)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, #prefix "VERIFY_ARGUMENT failed:"); \
+ prefix##ASSERT(arg); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT); \
+ return gcvSTATUS_INVALID_ARGUMENT; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
+# define gcmkVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcmk, arg)
+
+/*******************************************************************************
+**
+** gcmDEBUG_VERIFY_ARGUMENT
+**
+** Works just like gcmVERIFY_ARGUMENT, but is only valid in debug mode.
+** Use this to verify arguments inside non-public API functions.
+*/
+#if gcdDEBUG
+# define gcmDEBUG_VERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
+# define gcmkDEBUG_VERIFY_ARGUMENT(arg) _gcmkVERIFY_ARGUMENT(gcm, arg)
+#else
+# define gcmDEBUG_VERIFY_ARGUMENT(arg)
+# define gcmkDEBUG_VERIFY_ARGUMENT(arg)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY_ARGUMENT_RETURN
+**
+** Assert if an argument does not apply to the specified expression. If
+** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+** returned from the current function. In retail mode this macro does
+** nothing.
+**
+** ARGUMENTS:
+**
+** arg Argument to evaluate.
+*/
+# define _gcmVERIFY_ARGUMENT_RETURN(prefix, arg, value) \
+ do \
+ { \
+ if (!(arg)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "gcmVERIFY_ARGUMENT_RETURN failed:"); \
+ prefix##ASSERT(arg); \
+ prefix##FOOTER_ARG("value=%d", value); \
+ return value; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_ARGUMENT_RETURN(arg, value) \
+ _gcmVERIFY_ARGUMENT_RETURN(gcm, arg, value)
+# define gcmkVERIFY_ARGUMENT_RETURN(arg, value) \
+ _gcmVERIFY_ARGUMENT_RETURN(gcmk, arg, value)
+
+#define MAX_LOOP_COUNT 0x7FFFFFFF
+
+/******************************************************************************\
+****************************** User Debug Option ******************************
+\******************************************************************************/
+
+/* User option. */
+typedef enum _gceDEBUG_MSG
+{
+ gcvDEBUG_MSG_NONE,
+ gcvDEBUG_MSG_ERROR,
+ gcvDEBUG_MSG_WARNING
+}
+gceDEBUG_MSG;
+
+typedef struct _gcsUSER_DEBUG_OPTION
+{
+ gceDEBUG_MSG debugMsg;
+}
+gcsUSER_DEBUG_OPTION;
+
+gcsUSER_DEBUG_OPTION *
+gcoHAL_GetUserDebugOption(
+ void
+ );
+
+#if gcdHAS_ELLIPSIS
+#define gcmUSER_DEBUG_MSG(level, ...) \
+ do \
+ { \
+ if (level <= gcoHAL_GetUserDebugOption()->debugMsg) \
+ { \
+ gcoOS_Print(__VA_ARGS__); \
+ } \
+ } while (gcvFALSE)
+
+#define gcmUSER_DEBUG_ERROR_MSG(...) gcmUSER_DEBUG_MSG(gcvDEBUG_MSG_ERROR, "Error: " __VA_ARGS__)
+#define gcmUSER_DEBUG_WARNING_MSG(...) gcmUSER_DEBUG_MSG(gcvDEBUG_MSG_WARNING, "Warring: " __VA_ARGS__)
+#else
+#define gcmUSER_DEBUG_MSG
+#define gcmUSER_DEBUG_ERROR_MSG
+#define gcmUSER_DEBUG_WARNING_MSG
+#endif
+
+/*******************************************************************************
+**
+** A set of macros to aid state loading.
+**
+** ARGUMENTS:
+**
+** CommandBuffer Pointer to a gcoCMDBUF object.
+** StateDelta Pointer to a gcsSTATE_DELTA state delta structure.
+** Memory Destination memory pointer of gctUINT32_PTR type.
+** PartOfContext Whether or not the state is a part of the context.
+** FixedPoint Whether or not the state is of the fixed point format.
+** Count Number of consecutive states to be loaded.
+** Address State address.
+** Data Data to be set to the state.
+*/
+
+/*----------------------------------------------------------------------------*/
+
+#if gcmIS_DEBUG(gcdDEBUG_CODE)
+
+# define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count) \
+ CommandBuffer->lastLoadStatePtr = gcmPTR_TO_UINT64(Memory); \
+ CommandBuffer->lastLoadStateAddress = Address; \
+ CommandBuffer->lastLoadStateCount = Count
+
+# define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address) \
+ gcmASSERT( \
+ (gctUINT) (Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastLoadStatePtr, gctUINT32_PTR) - 1) \
+ == \
+ (gctUINT) (Address - CommandBuffer->lastLoadStateAddress) \
+ ); \
+ \
+ gcmASSERT(CommandBuffer->lastLoadStateCount > 0); \
+ \
+ CommandBuffer->lastLoadStateCount -= 1
+
+# define gcmVERIFYLOADSTATEDONE(CommandBuffer) \
+ gcmASSERT(CommandBuffer->lastLoadStateCount == 0);
+
+# define gcmDEFINELOADSTATEBASE() \
+ gctUINT32_PTR LoadStateBase;
+
+# define gcmSETLOADSTATEBASE(CommandBuffer, OutSide) \
+ if (OutSide) \
+ {\
+ LoadStateBase = (gctUINT32_PTR)*OutSide; \
+ }\
+ else\
+ {\
+ LoadStateBase = (gctUINT_PTR)CommandBuffer->buffer;\
+ }
+
+
+# define gcmVERIFYLOADSTATEALIGNED(CommandBuffer, Memory) \
+ gcmASSERT(((Memory - LoadStateBase) & 1) == 0);
+
+# define gcmUNSETLOADSTATEBASE() \
+ LoadStateBase = LoadStateBase;
+
+#else
+
+# define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count)
+# define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address)
+# define gcmVERIFYLOADSTATEDONE(CommandBuffer)
+
+# define gcmDEFINELOADSTATEBASE()
+# define gcmSETLOADSTATEBASE(CommandBuffer, OutSide)
+# define gcmVERIFYLOADSTATEALIGNED(CommandBuffer, Memory)
+# define gcmUNSETLOADSTATEBASE()
+
+#endif
+
+#if gcdSECURE_USER
+
+# define gcmDEFINESECUREUSER() \
+ gctUINT __secure_user_offset__; \
+ gctUINT32_PTR __secure_user_hintArray__;
+
+# define gcmBEGINSECUREUSER() \
+ __secure_user_offset__ = reserve->lastOffset; \
+ \
+ __secure_user_hintArray__ = gcmUINT64_TO_PTR(reserve->hintArrayTail)
+
+# define gcmENDSECUREUSER() \
+ reserve->hintArrayTail = gcmPTR_TO_UINT64(__secure_user_hintArray__)
+
+# define gcmSKIPSECUREUSER() \
+ __secure_user_offset__ += gcmSIZEOF(gctUINT32)
+
+# define gcmUPDATESECUREUSER() \
+ *__secure_user_hintArray__ = __secure_user_offset__; \
+ \
+ __secure_user_offset__ += gcmSIZEOF(gctUINT32); \
+ __secure_user_hintArray__ += 1
+
+#else
+
+# define gcmDEFINESECUREUSER()
+# define gcmBEGINSECUREUSER()
+# define gcmENDSECUREUSER()
+# define gcmSKIPSECUREUSER()
+# define gcmUPDATESECUREUSER()
+
+#endif
+
+/*----------------------------------------------------------------------------*/
+
+#if gcdDUMP
+# define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data) \
+ if (FixedPoint) \
+ { \
+ gcmDUMP(gcvNULL, "#[state.x 0x%04X 0x%08X]", \
+ Address, Data \
+ ); \
+ } \
+ else \
+ { \
+ gcmDUMP(gcvNULL, "#[state 0x%04X 0x%08X]", \
+ Address, Data \
+ ); \
+ }
+#else
+# define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data)
+#endif
+
+#define gcmDEFINESTATEBUFFER(CommandBuffer, StateDelta, Memory, ReserveSize) \
+ gcmDEFINESECUREUSER() \
+ gctSIZE_T ReserveSize; \
+ gcoCMDBUF CommandBuffer; \
+ gctUINT32_PTR Memory; \
+ gcsSTATE_DELTA_PTR StateDelta; \
+ gceENGINE CurrentEngine = gcvENGINE_RENDER
+
+#define gcmBEGINSTATEBUFFER(Hardware, CommandBuffer, StateDelta, Memory, ReserveSize) \
+{ \
+ gcmONERROR(gcoBUFFER_Reserve( \
+ Hardware->engine[CurrentEngine].buffer, ReserveSize, gcvTRUE, gcvCOMMAND_3D, &CommandBuffer \
+ )); \
+ \
+ Memory = (gctUINT32_PTR) gcmUINT64_TO_PTR(CommandBuffer->lastReserve); \
+ \
+ StateDelta = Hardware->delta; \
+ \
+ gcmBEGINSECUREUSER(); \
+}
+
+#define gcmENDSTATEBUFFER(Hardware, CommandBuffer, Memory, ReserveSize) \
+{ \
+ gcmENDSECUREUSER(); \
+ \
+ gcmASSERT( \
+ gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT8_PTR) + ReserveSize \
+ == \
+ (gctUINT8_PTR) Memory \
+ ); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, Count) \
+{ \
+ gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
+ gcmASSERT((gctUINT32)Count <= 1024); \
+ \
+ gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+ \
+ gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count); \
+ \
+ *Memory++ \
+ = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE, LOAD_STATE) \
+ | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT, FixedPoint) \
+ | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT, Count) \
+ | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
+ \
+ gcmSKIPSECUREUSER(); \
+}
+
+#define gcmENDSTATEBATCH(CommandBuffer, Memory) \
+{ \
+ gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+ \
+ gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+ \
+ gcmSAFECASTSIZET(__temp_data32__, Data); \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcoHARDWARE_UpdateDelta( \
+ StateDelta, Address, 0, __temp_data32__ \
+ ); \
+ \
+ gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+ \
+ gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSTATEDATAWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+ \
+ __temp_data32__ = Data; \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcoHARDWARE_UpdateDelta( \
+ StateDelta, Address, Mask, __temp_data32__ \
+ ); \
+ \
+ gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+ \
+ gcmUPDATESECUREUSER(); \
+}
+
+
+#define gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+ \
+ __temp_data32__ = Data; \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
+ \
+ gcmSKIPSECUREUSER(); \
+}
+
+#define gcmSETFILLER(CommandBuffer, Memory) \
+{ \
+ gcmVERIFYLOADSTATEDONE(CommandBuffer); \
+ \
+ Memory += 1; \
+ \
+ gcmSKIPSECUREUSER(); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSINGLESTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data); \
+ gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLESTATEWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data) \
+{ \
+ gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETSTATEDATAWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data); \
+ gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+
+#define gcmSETSINGLECTRLSTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data); \
+ gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+
+
+#define gcmSETSEMASTALLPIPE(StateDelta, CommandBuffer, Memory, Data) \
+{ \
+ gcmSETSINGLECTRLSTATE(StateDelta, CommandBuffer, Memory, gcvFALSE, AQSemaphoreRegAddrs, Data); \
+ \
+ *Memory++ = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
+ \
+ *Memory++ = Data; \
+ \
+ gcmDUMP(gcvNULL, "#[stall 0x%08X 0x%08X]", \
+ gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END), \
+ gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE)); \
+ \
+ gcmSKIPSECUREUSER(); \
+}
+
+/*******************************************************************************
+**
+** gcmSETSTARTDECOMMAND
+**
+** Form a START_DE command.
+**
+** ARGUMENTS:
+**
+** Memory Destination memory pointer of gctUINT32_PTR type.
+** Count Number of the rectangles.
+*/
+
+#define gcmSETSTARTDECOMMAND(Memory, Count) \
+{ \
+ *Memory++ \
+ = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE, START_DE) \
+ | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, COUNT, Count) \
+ | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
+ \
+ *Memory++ = 0xDEADDEED; \
+}
+
+/*****************************************
+** Temp command buffer macro
+*/
+#define gcmDEFINESTATEBUFFER_NEW(CommandBuffer, StateDelta, Memory) \
+ gcmDEFINESECUREUSER() \
+ gcmDEFINELOADSTATEBASE() \
+ gcsTEMPCMDBUF CommandBuffer = gcvNULL; \
+ gctUINT32_PTR Memory; \
+ gcsSTATE_DELTA_PTR StateDelta; \
+ gceENGINE CurrentEngine = gcvENGINE_RENDER
+
+
+#define gcmBEGINSTATEBUFFER_NEW(Hardware, CommandBuffer, StateDelta, Memory, OutSide) \
+{ \
+ if (OutSide) \
+ {\
+ Memory = (gctUINT32_PTR)*OutSide; \
+ }\
+ else \
+ {\
+ gcmONERROR(gcoBUFFER_StartTEMPCMDBUF( \
+ Hardware->engine[CurrentEngine].buffer, &CommandBuffer \
+ ));\
+ \
+ Memory = (gctUINT32_PTR)(CommandBuffer->buffer); \
+ \
+ }\
+ StateDelta = Hardware->delta; \
+ \
+ gcmBEGINSECUREUSER(); \
+ gcmSETLOADSTATEBASE(CommandBuffer,OutSide);\
+}
+
+#define gcmENDSTATEBUFFER_NEW(Hardware, CommandBuffer, Memory, OutSide) \
+{ \
+ gcmENDSECUREUSER(); \
+ \
+ if (OutSide) \
+ {\
+ *OutSide = Memory; \
+ }\
+ else \
+ {\
+ CommandBuffer->currentByteSize = (gctUINT32)((gctUINT8_PTR)Memory - \
+ (gctUINT8_PTR)CommandBuffer->buffer); \
+ \
+ gcmONERROR(gcoBUFFER_EndTEMPCMDBUF(Hardware->engine[CurrentEngine].buffer, gcvFALSE));\
+ }\
+ gcmUNSETLOADSTATEBASE()\
+}
+
+#define gcmDEFINECTRLSTATEBUFFER(CommandBuffer, Memory) \
+ gcmDEFINESECUREUSER() \
+ gcmDEFINELOADSTATEBASE() \
+ gcsTEMPCMDBUF CommandBuffer = gcvNULL; \
+ gctUINT32_PTR Memory; \
+ gceENGINE CurrentEngine = gcvENGINE_RENDER
+
+#define gcmBEGINCTRLSTATEBUFFER(Hardware, CommandBuffer, Memory, OutSide) \
+{ \
+ if (OutSide) \
+ { \
+ Memory = (gctUINT32_PTR)*OutSide; \
+ } \
+ else \
+ { \
+ gcmONERROR(gcoBUFFER_StartTEMPCMDBUF( \
+ Hardware->engine[CurrentEngine].buffer, &CommandBuffer \
+ )); \
+ \
+ Memory = (gctUINT32_PTR)(CommandBuffer->buffer); \
+ } \
+ gcmBEGINSECUREUSER(); \
+ gcmSETLOADSTATEBASE(CommandBuffer,OutSide); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, Count) \
+{ \
+ gcmVERIFYLOADSTATEALIGNED(CommandBuffer,Memory);\
+ gcmASSERT((gctUINT32)Count <= 1024); \
+ \
+ *Memory++ \
+ = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE, LOAD_STATE) \
+ | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT, FixedPoint) \
+ | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT, Count) \
+ | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
+ \
+ gcmSKIPSECUREUSER(); \
+}
+
+#define gcmENDSTATEBATCH_NEW(CommandBuffer, Memory) \
+ gcmVERIFYLOADSTATEALIGNED(CommandBuffer,Memory);
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSTATEDATA_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ gcmSAFECASTSIZET(__temp_data32__, Data); \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcoHARDWARE_UpdateDelta( \
+ StateDelta, Address, 0, __temp_data32__ \
+ ); \
+ \
+ gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+ \
+ gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSTATEDATAWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ __temp_data32__ = Data; \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcoHARDWARE_UpdateDelta( \
+ StateDelta, Address, Mask, __temp_data32__ \
+ ); \
+ \
+ gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+ \
+ gcmUPDATESECUREUSER(); \
+}
+
+
+#define gcmSETCTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, Address, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ __temp_data32__ = Data; \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
+ \
+ gcmSKIPSECUREUSER(); \
+}
+
+#define gcmSETFILLER_NEW(CommandBuffer, Memory) \
+{ \
+ Memory += 1; \
+ \
+ gcmSKIPSECUREUSER(); \
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define gcmSETSINGLESTATE_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETSTATEDATA_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data); \
+ gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLESTATEWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data) \
+{ \
+ gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETSTATEDATAWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data); \
+ gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+
+#define gcmSETSINGLECTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETCTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, Address, Data); \
+ gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+
+
+#define gcmSETSEMASTALLPIPE_NEW(StateDelta, CommandBuffer, Memory, Data) \
+{ \
+ gcmSETSINGLECTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, gcvFALSE, AQSemaphoreRegAddrs, Data); \
+ \
+ *Memory++ = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
+ \
+ *Memory++ = Data; \
+ \
+ gcmDUMP(gcvNULL, "#[stall 0x%08X 0x%08X]", \
+ gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END), \
+ gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE)); \
+ \
+ gcmSKIPSECUREUSER(); \
+}
+
+#define gcmSETSTARTDECOMMAND_NEW(CommandBuffer, Memory, Count) \
+{ \
+ *Memory++ \
+ = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE, START_DE) \
+ | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, COUNT, Count) \
+ | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
+ \
+ *Memory++ = 0xDEADDEED; \
+ \
+}
+
+#define gcmSETSTATEDATA_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ __temp_data32__ = Data; \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+ \
+ gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSTATEDATAWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ __temp_data32__ = Data; \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+ \
+ gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSINGLESTATE_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETSTATEDATA_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data); \
+ gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLESTATEWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data) \
+{ \
+ gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETSTATEDATAWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data); \
+ gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
+}
+
+#define gcmSETSTATEDATA_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+ \
+ gcmSAFECASTSIZET(__temp_data32__, Data); \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+ \
+ gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSTATEDATAWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data) \
+{ \
+ gctUINT32 __temp_data32__; \
+ \
+ gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
+ \
+ __temp_data32__ = Data; \
+ \
+ *Memory++ = __temp_data32__; \
+ \
+ gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
+ \
+ gcmUPDATESECUREUSER(); \
+}
+
+#define gcmSETSINGLESTATE_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data) \
+{ \
+ gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETSTATEDATA_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Data); \
+ gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+#define gcmSETSINGLESTATEWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data) \
+{ \
+ gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
+ gcmSETSTATEDATAWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
+ Address, Mask, Data); \
+ gcmENDSTATEBATCH(CommandBuffer, Memory); \
+}
+
+#define gcmDEFINESTATEBUFFER_NEW_FAST(CommandBuffer, Memory) \
+ gcmDEFINESECUREUSER() \
+ gcmDEFINELOADSTATEBASE() \
+ gcsTEMPCMDBUF CommandBuffer = gcvNULL; \
+ gctUINT32_PTR Memory;
+
+#define gcmDEFINESTATEBUFFER_FAST(CommandBuffer, Memory, ReserveSize) \
+ gcmDEFINESECUREUSER() \
+ gctSIZE_T ReserveSize; \
+ gcoCMDBUF CommandBuffer; \
+ gctUINT32_PTR Memory;
+
+#define gcmBEGINSTATEBUFFER_FAST(Hardware, CommandBuffer, Memory, ReserveSize) \
+{ \
+ gcmONERROR(gcoBUFFER_Reserve( \
+ Hardware->engine[gcvENGINE_RENDER].buffer, ReserveSize, gcvTRUE, &CommandBuffer \
+ )); \
+ \
+ Memory = (gctUINT32_PTR) gcmUINT64_TO_PTR(CommandBuffer->lastReserve); \
+ \
+ gcmBEGINSECUREUSER(); \
+}
+
+#define gcmBEGINSTATEBUFFER_NEW_FAST(Hardware, CommandBuffer, Memory, OutSide) \
+{ \
+ if (OutSide) \
+ {\
+ Memory = (gctUINT32_PTR)*OutSide; \
+ }\
+ else \
+ {\
+ gcmONERROR(gcoBUFFER_StartTEMPCMDBUF( \
+ Hardware->engine[gcvENGINE_RENDER].buffer, &CommandBuffer \
+ ));\
+ \
+ Memory = (gctUINT32_PTR)(CommandBuffer->buffer); \
+ \
+ }\
+ \
+ gcmBEGINSECUREUSER(); \
+ gcmSETLOADSTATEBASE(CommandBuffer,OutSide);\
+}
+
+#define gcmENDSTATEBUFFER_NEW_FAST(Hardware, CommandBuffer, Memory, OutSide) \
+{ \
+ gcmENDSECUREUSER(); \
+ \
+ if (OutSide) \
+ {\
+ *OutSide = Memory; \
+ }\
+ else \
+ {\
+ CommandBuffer->currentByteSize = (gctUINT32)((gctUINT8_PTR)Memory - \
+ (gctUINT8_PTR)CommandBuffer->buffer); \
+ \
+ gcmONERROR(gcoBUFFER_EndTEMPCMDBUF(Hardware->engine[gcvENGINE_RENDER].buffer, gcvFALSE));\
+ }\
+ gcmUNSETLOADSTATEBASE()\
+}
+
+/*******************************************************************************
+**
+** gcmCONFIGUREUNIFORMS
+**
+** Configure uniforms according to chip and numConstants.
+*/
+#if !gcdENABLE_UNIFIED_CONSTANT
+#define gcmCONFIGUREUNIFORMS(ChipModel, ChipRevision, NumConstants, \
+ UnifiedConst, VsConstBase, PsConstBase, VsConstMax, PsConstMax, ConstMax) \
+{ \
+ if (ChipModel == gcv2000 && (ChipRevision == 0x5118 || ChipRevision == 0x5140)) \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 256; \
+ PsConstMax = 64; \
+ ConstMax = 320; \
+ } \
+ else if (NumConstants == 320) \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 256; \
+ PsConstMax = 64; \
+ ConstMax = 320; \
+ } \
+ /* All GC1000 series chips can only support 64 uniforms for ps on non-unified const mode. */ \
+ else if (NumConstants > 256 && ChipModel == gcv1000) \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 256; \
+ PsConstMax = 64; \
+ ConstMax = 320; \
+ } \
+ else if (NumConstants > 256) \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 256; \
+ PsConstMax = 256; \
+ ConstMax = 512; \
+ } \
+ else if (NumConstants == 256) \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 256; \
+ PsConstMax = 256; \
+ ConstMax = 512; \
+ } \
+ else \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 168; \
+ PsConstMax = 64; \
+ ConstMax = 232; \
+ } \
+}
+#else
+#define gcmCONFIGUREUNIFORMS(ChipModel, ChipRevision, Halti5Avail, NumConstants, \
+ UnifiedConst, VsConstBase, PsConstBase, VsConstMax, PsConstMax, ConstMax) \
+{ \
+ if (NumConstants > 256) \
+ { \
+ UnifiedConst = gcvTRUE; \
+ if (Halti5Avail) \
+ { \
+ VsConstBase = gcregGpipeUniformsRegAddrs; \
+ PsConstBase = gcregPixelUniformsRegAddrs; \
+ } \
+ else \
+ {\
+ VsConstBase = gcregSHUniformsRegAddrs; \
+ PsConstBase = gcregSHUniformsRegAddrs; \
+ }\
+ if ((ChipModel == gcv880) && ((ChipRevision & 0xfff0) == 0x5120)) \
+ { \
+ VsConstMax = 512; \
+ PsConstMax = 64; \
+ ConstMax = 576; \
+ } \
+ else \
+ { \
+ VsConstMax = gcmMIN(512, NumConstants - 64); \
+ PsConstMax = gcmMIN(512, NumConstants - 64); \
+ ConstMax = NumConstants; \
+ } \
+ } \
+ else if (NumConstants == 256) \
+ { \
+ if (ChipModel == gcv2000 && (ChipRevision == 0x5118 || ChipRevision == 0x5140)) \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 256; \
+ PsConstMax = 64; \
+ ConstMax = 320; \
+ } \
+ else \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 256; \
+ PsConstMax = 256; \
+ ConstMax = 512; \
+ } \
+ } \
+ else \
+ { \
+ UnifiedConst = gcvFALSE; \
+ VsConstBase = AQVertexShaderConstRegAddrs; \
+ PsConstBase = AQPixelShaderConstRegAddrs; \
+ VsConstMax = 168; \
+ PsConstMax = 64; \
+ ConstMax = 232; \
+ } \
+}
+#endif
+
+#define gcmAnyTileStatusEnableForFullMultiSlice(SurfView, anyTsEnableForMultiSlice)\
+{\
+ gctUINT i = 0; \
+ for (; i < (SurfView->surf->requestD); i++)\
+ {\
+ if ((SurfView->surf->tileStatusNode.pool != gcvPOOL_UNKNOWN) && \
+ (SurfView->surf->tileStatusDisabled[i] == gcvFALSE))\
+ {\
+ *anyTsEnableForMultiSlice = gcvTRUE;\
+ break;\
+ }\
+ }\
+}\
+
+#define gcmAnyTileStatusEnableForMultiSlice(SurfView, anyTsEnableForMultiSlice)\
+{\
+ gctUINT i = SurfView->firstSlice; \
+ for (; i < (SurfView->firstSlice + SurfView->numSlices); i++)\
+ {\
+ if ((SurfView->surf->tileStatusNode.pool != gcvPOOL_UNKNOWN) && \
+ (SurfView->surf->tileStatusDisabled[i] == gcvFALSE))\
+ {\
+ *anyTsEnableForMultiSlice = gcvTRUE;\
+ break;\
+ }\
+ }\
+}\
+
+#define gcmCanTileStatusEnabledForMultiSlice(SurfView, canTsEnabled)\
+{\
+ if (SurfView->numSlices > 1)\
+ {\
+ if (SurfView->surf->tileStatusNode.pool != gcvPOOL_UNKNOWN) \
+ {\
+ gctUINT i = 0;\
+ for (; i < SurfView->numSlices; i++)\
+ {\
+ if (SurfView->surf->tileStatusDisabled[i] == gcvTRUE)\
+ {\
+ *canTsEnabled = gcvFALSE;\
+ break;\
+ }\
+ if (SurfView->surf->fcValue[i] != SurfView->surf->fcValue[0])\
+ {\
+ *canTsEnabled = gcvFALSE;\
+ break;\
+ }\
+ \
+ if (SurfView->surf->fcValueUpper[i] != SurfView->surf->fcValueUpper[0])\
+ {\
+ *canTsEnabled = gcvFALSE;\
+ break;\
+ }\
+ }\
+ }\
+ else\
+ {\
+ *canTsEnabled = gcvFALSE;\
+ }\
+ }\
+ else\
+ {\
+ if ((SurfView->surf->tileStatusNode.pool == gcvPOOL_UNKNOWN) || (SurfView->surf->tileStatusDisabled[SurfView->firstSlice] == gcvTRUE))\
+ {\
+ *canTsEnabled = gcvFALSE;\
+ }\
+ }\
+}\
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_base_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
new file mode 100644
index 000000000000..a4042ca6e38d
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
@@ -0,0 +1,1343 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_driver_h_
+#define __gc_hal_driver_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#if gcdENABLE_VG
+#include "gc_hal_driver_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* I/O Control Codes ******************************
+\******************************************************************************/
+
+#define gcvHAL_CLASS "galcore"
+#define IOCTL_GCHAL_INTERFACE 30000
+#define IOCTL_GCHAL_KERNEL_INTERFACE 30001
+#define IOCTL_GCHAL_TERMINATE 30002
+
+#undef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
+/******************************************************************************\
+********************************* Command Codes ********************************
+\******************************************************************************/
+
+typedef enum _gceHAL_COMMAND_CODES
+{
+ /* Generic query. */
+ gcvHAL_QUERY_VIDEO_MEMORY,
+ gcvHAL_QUERY_CHIP_IDENTITY,
+
+ /* Contiguous memory. */
+ gcvHAL_ALLOCATE_NON_PAGED_MEMORY,
+ gcvHAL_FREE_NON_PAGED_MEMORY,
+ gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY,
+ gcvHAL_FREE_CONTIGUOUS_MEMORY,
+
+ /* Video memory allocation. */
+ gcvHAL_ALLOCATE_VIDEO_MEMORY, /* Enforced alignment. */
+ gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY, /* No alignment. */
+ gcvHAL_RELEASE_VIDEO_MEMORY,
+
+ /* Physical-to-logical mapping. */
+ gcvHAL_MAP_MEMORY,
+ gcvHAL_UNMAP_MEMORY,
+
+ /* Logical-to-physical mapping. */
+ gcvHAL_MAP_USER_MEMORY,
+ gcvHAL_UNMAP_USER_MEMORY,
+
+ /* Surface lock/unlock. */
+ gcvHAL_LOCK_VIDEO_MEMORY,
+ gcvHAL_UNLOCK_VIDEO_MEMORY,
+
+ /* Event queue. */
+ gcvHAL_EVENT_COMMIT,
+
+ gcvHAL_USER_SIGNAL,
+ gcvHAL_SIGNAL,
+ gcvHAL_WRITE_DATA,
+
+ gcvHAL_COMMIT,
+ gcvHAL_STALL,
+
+ gcvHAL_READ_REGISTER,
+ gcvHAL_WRITE_REGISTER,
+
+ gcvHAL_GET_PROFILE_SETTING,
+ gcvHAL_SET_PROFILE_SETTING,
+
+ gcvHAL_READ_ALL_PROFILE_REGISTERS,
+ gcvHAL_PROFILE_REGISTERS_2D,
+#if VIVANTE_PROFILER_PERDRAW
+ gcvHAL_READ_PROFILER_REGISTER_SETTING,
+#endif
+ gcvHAL_READ_ALL_PROFILE_NEW_REGISTERS_PART1,
+ gcvHAL_READ_ALL_PROFILE_NEW_REGISTERS_PART2,
+ gcvHAL_READ_PROFILER_NEW_REGISTER_SETTING,
+
+ /* Power management. */
+ gcvHAL_SET_POWER_MANAGEMENT_STATE,
+ gcvHAL_QUERY_POWER_MANAGEMENT_STATE,
+
+ gcvHAL_GET_BASE_ADDRESS,
+
+ gcvHAL_SET_IDLE, /* reserved */
+
+ /* Queries. */
+ gcvHAL_QUERY_KERNEL_SETTINGS,
+
+ /* Reset. */
+ gcvHAL_RESET,
+
+ /* Map physical address into handle. */
+ gcvHAL_MAP_PHYSICAL,
+
+ /* Debugger stuff. */
+ gcvHAL_DEBUG,
+
+ /* Cache stuff. */
+ gcvHAL_CACHE,
+
+ /* TimeStamp */
+ gcvHAL_TIMESTAMP,
+
+ /* Database. */
+ gcvHAL_DATABASE,
+
+ /* Version. */
+ gcvHAL_VERSION,
+
+ /* Chip info */
+ gcvHAL_CHIP_INFO,
+
+ /* Process attaching/detaching. */
+ gcvHAL_ATTACH,
+ gcvHAL_DETACH,
+
+ /* Composition. */
+ gcvHAL_COMPOSE,
+
+ /* Set timeOut value */
+ gcvHAL_SET_TIMEOUT,
+
+ /* Frame database. */
+ gcvHAL_GET_FRAME_INFO,
+
+ /* GPU profile dump */
+ gcvHAL_DUMP_GPU_PROFILE,
+
+ gcvHAL_QUERY_COMMAND_BUFFER,
+
+ gcvHAL_COMMIT_DONE,
+
+ /* GPU and event dump */
+ gcvHAL_DUMP_GPU_STATE,
+ gcvHAL_DUMP_EVENT,
+
+ /* Virtual command buffer. */
+ gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER,
+ gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER,
+
+ /* FSCALE_VAL. */
+ gcvHAL_SET_FSCALE_VALUE,
+ gcvHAL_GET_FSCALE_VALUE,
+
+ gcvHAL_NAME_VIDEO_MEMORY,
+ gcvHAL_IMPORT_VIDEO_MEMORY,
+
+ /* Reset time stamp. */
+ gcvHAL_QUERY_RESET_TIME_STAMP,
+
+ /* Multi-GPU read/write. */
+ gcvHAL_READ_REGISTER_EX,
+ gcvHAL_WRITE_REGISTER_EX,
+
+ /* Create native fence and return its fd. */
+ gcvHAL_CREATE_NATIVE_FENCE,
+
+ /* Let GPU wait on native fence. */
+ gcvHAL_WAIT_NATIVE_FENCE,
+
+ /* Destory MMU. */
+ gcvHAL_DESTROY_MMU,
+
+ /* Shared buffer. */
+ gcvHAL_SHBUF,
+
+
+ /* Connect a video node to an OS native fd. */
+ gcvHAL_GET_VIDEO_MEMORY_FD,
+
+ /* Config power management. */
+ gcvHAL_CONFIG_POWER_MANAGEMENT,
+
+ /* Wrap a user memory into a video memory node. */
+ gcvHAL_WRAP_USER_MEMORY,
+
+ /* Wait until GPU finishes access to a resource. */
+ gcvHAL_WAIT_FENCE,
+
+#if gcdDEC_ENABLE_AHB
+ gcvHAL_DEC300_READ,
+ gcvHAL_DEC300_WRITE,
+ gcvHAL_DEC300_FLUSH,
+ gcvHAL_DEC300_FLUSH_WAIT,
+#endif
+
+ gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY
+
+}
+gceHAL_COMMAND_CODES;
+
+/******************************************************************************\
+****************************** Interface Structure *****************************
+\******************************************************************************/
+
+#define gcdMAX_PROFILE_FILE_NAME 128
+
+/* Kernel settings. */
+typedef struct _gcsKERNEL_SETTINGS
+{
+ /* Used RealTime signal between kernel and user. */
+ gctINT signal;
+}
+gcsKERNEL_SETTINGS;
+
+typedef struct _gcsUSER_MEMORY_DESC
+{
+ /* Import flag. */
+ gctUINT32 flag;
+
+ /* gcvALLOC_FLAG_DMABUF */
+ gctUINT32 handle;
+
+ /* gcvALLOC_FLAG_USERMEMORY */
+ gctUINT64 logical;
+ gctUINT32 physical;
+ gctUINT32 size;
+
+ /* gcvALLOC_FLAG_EXTERNAL_MEMORY */
+ gcsEXTERNAL_MEMORY_INFO externalMemoryInfo;
+}
+gcsUSER_MEMORY_DESC;
+
+/* gcvHAL_QUERY_CHIP_IDENTITY */
+typedef struct _gcsHAL_QUERY_CHIP_IDENTITY * gcsHAL_QUERY_CHIP_IDENTITY_PTR;
+typedef struct _gcsHAL_QUERY_CHIP_IDENTITY
+{
+
+ /* Chip model. */
+ gceCHIPMODEL chipModel;
+
+ /* Revision value.*/
+ gctUINT32 chipRevision;
+
+ /* Chip date. */
+ gctUINT32 chipDate;
+
+#if gcdENABLE_VG
+ /* Supported feature fields. */
+ gctUINT32 chipFeatures;
+
+ /* Supported minor feature fields. */
+ gctUINT32 chipMinorFeatures;
+
+ /* Supported minor feature 1 fields. */
+ gctUINT32 chipMinorFeatures1;
+
+ /* Supported minor feature 2 fields. */
+ gctUINT32 chipMinorFeatures2;
+
+ /* Supported minor feature 3 fields. */
+ gctUINT32 chipMinorFeatures3;
+
+ /* Supported minor feature 4 fields. */
+ gctUINT32 chipMinorFeatures4;
+
+ /* Supported minor feature 5 fields. */
+ gctUINT32 chipMinorFeatures5;
+
+ /* Supported minor feature 6 fields. */
+ gctUINT32 chipMinorFeatures6;
+#endif
+
+ /* Number of streams supported. */
+ gctUINT32 streamCount;
+
+ /* Number of pixel pipes. */
+ gctUINT32 pixelPipes;
+
+ /* Number of resolve pipes. */
+ gctUINT32 resolvePipes;
+
+ /* Number of instructions. */
+ gctUINT32 instructionCount;
+
+ /* Number of constants. */
+ gctUINT32 numConstants;
+
+ /* Number of varyings */
+ gctUINT32 varyingsCount;
+
+ /* Number of 3D GPUs */
+ gctUINT32 gpuCoreCount;
+
+ /* Product ID */
+ gctUINT32 productID;
+
+ /* Special chip flag bits */
+ gceCHIP_FLAG chipFlags;
+
+ /* ECO ID. */
+ gctUINT32 ecoID;
+
+ /* Customer ID. */
+ gctUINT32 customerID;
+}
+gcsHAL_QUERY_CHIP_IDENTITY;
+
+/* gcvHAL_COMPOSE. */
+typedef struct _gcsHAL_COMPOSE * gcsHAL_COMPOSE_PTR;
+typedef struct _gcsHAL_COMPOSE
+{
+ /* Composition state buffer. */
+ gctUINT64 physical;
+ gctUINT64 logical;
+ gctUINT offset;
+ gctUINT size;
+
+ /* Composition end signal. */
+ gctUINT64 process;
+ gctUINT64 signal;
+
+ /* User signals. */
+ gctUINT64 userProcess;
+ gctUINT64 userSignal1;
+ gctUINT64 userSignal2;
+
+#if defined(__QNXNTO__)
+ /* Client pulse side-channel connection ID. */
+ gctINT32 coid;
+
+ /* Set by server. */
+ gctINT32 rcvid;
+#endif
+}
+gcsHAL_COMPOSE;
+
+
+typedef struct _gcsHAL_INTERFACE
+{
+ /* Command code. */
+ gceHAL_COMMAND_CODES command;
+
+ /* Hardware type. */
+ gceHARDWARE_TYPE hardwareType;
+
+ /* Core index for current hardware type. */
+ gctUINT32 coreIndex;
+
+ /* Status value. */
+ gceSTATUS status;
+
+ /* Handle to this interface channel. */
+ gctUINT64 handle;
+
+ /* Pid of the client. */
+ gctUINT32 pid;
+
+ /* Engine */
+ gceENGINE engine;
+
+ /* Ignore information from TSL when doing IO control */
+ gctBOOL ignoreTLS;
+
+ /* Union of command structures. */
+ union _u
+ {
+ /* gcvHAL_GET_BASE_ADDRESS */
+ struct _gcsHAL_GET_BASE_ADDRESS
+ {
+ /* Physical memory address of internal memory. */
+ OUT gctUINT32 baseAddress;
+
+ /* Start of flat mapping range. */
+ OUT gctUINT32 flatMappingStart;
+
+ /* End of flat mapping range. */
+ OUT gctUINT32 flatMappingEnd;
+ }
+ GetBaseAddress;
+
+ /* gcvHAL_QUERY_VIDEO_MEMORY */
+ struct _gcsHAL_QUERY_VIDEO_MEMORY
+ {
+ /* Physical memory address of internal memory. Just a name. */
+ OUT gctUINT32 internalPhysical;
+
+ /* Size in bytes of internal memory. */
+ OUT gctUINT64 internalSize;
+
+ /* Physical memory address of external memory. Just a name. */
+ OUT gctUINT32 externalPhysical;
+
+ /* Size in bytes of external memory.*/
+ OUT gctUINT64 externalSize;
+
+ /* Physical memory address of contiguous memory. Just a name. */
+ OUT gctUINT32 contiguousPhysical;
+
+ /* Size in bytes of contiguous memory.*/
+ OUT gctUINT64 contiguousSize;
+ }
+ QueryVideoMemory;
+
+ /* gcvHAL_QUERY_CHIP_IDENTITY */
+ gcsHAL_QUERY_CHIP_IDENTITY QueryChipIdentity;
+
+ /* gcvHAL_MAP_MEMORY */
+ struct _gcsHAL_MAP_MEMORY
+ {
+ /* Physical memory address to map. Just a name on Linux/Qnx. */
+ IN gctUINT32 physical;
+
+ /* Number of bytes in physical memory to map. */
+ IN gctUINT64 bytes;
+
+ /* Address of mapped memory. */
+ OUT gctUINT64 logical;
+ }
+ MapMemory;
+
+ /* gcvHAL_UNMAP_MEMORY */
+ struct _gcsHAL_UNMAP_MEMORY
+ {
+ /* Physical memory address to unmap. Just a name on Linux/Qnx. */
+ IN gctUINT32 physical;
+
+ /* Number of bytes in physical memory to unmap. */
+ IN gctUINT64 bytes;
+
+ /* Address of mapped memory to unmap. */
+ IN gctUINT64 logical;
+ }
+ UnmapMemory;
+
+ /* gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY */
+ struct _gcsHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT bytes;
+
+ /* Buffer alignment. */
+ IN gctUINT alignment;
+
+ /* Type of allocation. */
+ IN gceSURF_TYPE type;
+
+ /* Flag of allocation. */
+ IN gctUINT32 flag;
+
+ /* Memory pool to allocate from. */
+ IN OUT gcePOOL pool;
+
+ /* Allocated video memory. */
+ OUT gctUINT32 node;
+ }
+ AllocateLinearVideoMemory;
+
+ /* gcvHAL_ALLOCATE_VIDEO_MEMORY */
+ struct _gcsHAL_ALLOCATE_VIDEO_MEMORY
+ {
+ /* Width of rectangle to allocate. */
+ IN OUT gctUINT width;
+
+ /* Height of rectangle to allocate. */
+ IN OUT gctUINT height;
+
+ /* Depth of rectangle to allocate. */
+ IN gctUINT depth;
+
+ /* Format rectangle to allocate in gceSURF_FORMAT. */
+ IN gceSURF_FORMAT format;
+
+ /* Type of allocation. */
+ IN gceSURF_TYPE type;
+
+ /* Memory pool to allocate from. */
+ IN OUT gcePOOL pool;
+
+ /* Allocated video memory. */
+ OUT gctUINT32 node;
+ }
+ AllocateVideoMemory;
+
+ /* gcvHAL_RELEASE_VIDEO_MEMORY */
+ struct _gcsHAL_RELEASE_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gctUINT32 node;
+
+#ifdef __QNXNTO__
+ /* Mapped logical address to unmap in user space. */
+ OUT gctUINT64 memory;
+
+ /* Number of bytes to allocated. */
+ OUT gctUINT64 bytes;
+#endif
+ }
+ ReleaseVideoMemory;
+
+ /* gcvHAL_LOCK_VIDEO_MEMORY */
+ struct _gcsHAL_LOCK_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gctUINT32 node;
+
+ /* Cache configuration. */
+ /* Only gcvPOOL_CONTIGUOUS and gcvPOOL_VIRUTAL
+ ** can be configured */
+ IN gctBOOL cacheable;
+
+ /* Hardware specific address. */
+ OUT gctUINT32 address;
+
+ /* Mapped logical address. */
+ OUT gctUINT64 memory;
+
+ /* Customer priviate handle*/
+ OUT gctUINT32 gid;
+
+ /* Bus address of a contiguous video node. */
+ OUT gctUINT64 physicalAddress;
+ }
+ LockVideoMemory;
+
+ /* gcvHAL_UNLOCK_VIDEO_MEMORY */
+ struct _gcsHAL_UNLOCK_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gctUINT64 node;
+
+ /* Type of surface. */
+ IN gceSURF_TYPE type;
+
+ /* Flag to unlock surface asynchroneously. */
+ IN OUT gctBOOL asynchroneous;
+ }
+ UnlockVideoMemory;
+
+ /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
+ struct _gcsHAL_ALLOCATE_NON_PAGED_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ OUT gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ OUT gctUINT64 logical;
+ }
+ AllocateNonPagedMemory;
+
+ /* gcvHAL_FREE_NON_PAGED_MEMORY */
+ struct _gcsHAL_FREE_NON_PAGED_MEMORY
+ {
+ /* Number of bytes allocated. */
+ IN gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ IN gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ IN gctUINT64 logical;
+ }
+ FreeNonPagedMemory;
+
+ /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
+ struct _gcsHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ OUT gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ OUT gctUINT64 logical;
+ }
+ AllocateVirtualCommandBuffer;
+
+ /* gcvHAL_FREE_NON_PAGED_MEMORY */
+ struct _gcsHAL_FREE_VIRTUAL_COMMAND_BUFFER
+ {
+ /* Number of bytes allocated. */
+ IN gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ IN gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ IN gctUINT64 logical;
+ }
+ FreeVirtualCommandBuffer;
+
+ /* gcvHAL_EVENT_COMMIT. */
+ struct _gcsHAL_EVENT_COMMIT
+ {
+ /* Event queue in gcsQUEUE. */
+ IN gctUINT64 queue;
+
+ IN gceENGINE engine;
+ }
+ Event;
+
+ /* gcvHAL_COMMIT */
+ struct _gcsHAL_COMMIT
+ {
+ /* Context buffer object gckCONTEXT. */
+ IN gctUINT64 context;
+
+ /* Command buffer gcoCMDBUF. */
+ IN gctUINT64 commandBuffer;
+
+ /* State delta buffer in gcsSTATE_DELTA. */
+ gctUINT64 delta;
+
+ gctUINT64 deltas[gcvCORE_COUNT];
+
+ gctUINT64 contexts[gcvCORE_COUNT];
+
+ gctUINT64 commandBuffers[gcvCORE_COUNT];
+
+
+ /* Event queue in gcsQUEUE. */
+ IN gctUINT64 queue;
+
+ /* Used to distinguish different FE. */
+ IN gceENGINE engine;
+
+ /* The command buffer is linked to multiple command queue. */
+ IN gctBOOL shared;
+
+ /* Index of command queue. */
+ IN gctUINT32 index;
+
+ /* Count of gpu core. */
+ IN gctUINT32 count;
+
+ /* Commit stamp of this commit. */
+ OUT gctUINT64 commitStamp;
+
+ /* If context switch for this commit */
+ OUT gctBOOL contextSwitched;
+ }
+ Commit;
+
+ /* gcvHAL_MAP_USER_MEMORY */
+ struct _gcsHAL_MAP_USER_MEMORY
+ {
+ /* Base address of user memory to map. */
+ IN gctUINT64 memory;
+
+ /* Physical address of user memory to map. */
+ IN gctUINT32 physical;
+
+ /* Size of user memory in bytes to map. */
+ IN gctUINT64 size;
+
+ /* Info record required by gcvHAL_UNMAP_USER_MEMORY. Just a name. */
+ OUT gctUINT32 info;
+
+ /* Physical address of mapped memory. */
+ OUT gctUINT32 address;
+ }
+ MapUserMemory;
+
+ /* gcvHAL_UNMAP_USER_MEMORY */
+ struct _gcsHAL_UNMAP_USER_MEMORY
+ {
+ /* Base address of user memory to unmap. */
+ IN gctUINT64 memory;
+
+ /* Size of user memory in bytes to unmap. */
+ IN gctUINT64 size;
+
+ /* Info record returned by gcvHAL_MAP_USER_MEMORY. Just a name. */
+ IN gctUINT32 info;
+
+ /* Physical address of mapped memory as returned by
+ gcvHAL_MAP_USER_MEMORY. */
+ IN gctUINT32 address;
+ }
+ UnmapUserMemory;
+#if !USE_NEW_LINUX_SIGNAL
+ /* gcsHAL_USER_SIGNAL */
+ struct _gcsHAL_USER_SIGNAL
+ {
+ /* Command. */
+ gceUSER_SIGNAL_COMMAND_CODES command;
+
+ /* Signal ID. */
+ IN OUT gctINT id;
+
+ /* Reset mode. */
+ IN gctBOOL manualReset;
+
+ /* Wait timedout. */
+ IN gctUINT32 wait;
+
+ /* State. */
+ IN gctBOOL state;
+ }
+ UserSignal;
+#endif
+
+ /* gcvHAL_SIGNAL. */
+ struct _gcsHAL_SIGNAL
+ {
+ /* Signal handle to signal gctSIGNAL. */
+ IN gctUINT64 signal;
+
+ /* Reserved gctSIGNAL. */
+ IN gctUINT64 auxSignal;
+
+ /* Process owning the signal gctHANDLE. */
+ IN gctUINT64 process;
+
+#if defined(__QNXNTO__)
+ /* Client pulse side-channel connection ID. Set by client in gcoOS_CreateSignal. */
+ IN gctINT32 coid;
+
+ /* Set by server. */
+ IN gctINT32 rcvid;
+#endif
+ /* Event generated from where of pipeline */
+ IN gceKERNEL_WHERE fromWhere;
+ }
+ Signal;
+
+ /* gcvHAL_WRITE_DATA. */
+ struct _gcsHAL_WRITE_DATA
+ {
+ /* Address to write data to. */
+ IN gctUINT32 address;
+
+ /* Data to write. */
+ IN gctUINT32 data;
+ }
+ WriteData;
+
+ /* gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY */
+ struct _gcsHAL_ALLOCATE_CONTIGUOUS_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT64 bytes;
+
+ /* Hardware address of allocation. */
+ OUT gctUINT32 address;
+
+ /* Physical address of allocation. Just a name. */
+ OUT gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ OUT gctUINT64 logical;
+ }
+ AllocateContiguousMemory;
+
+ /* gcvHAL_FREE_CONTIGUOUS_MEMORY */
+ struct _gcsHAL_FREE_CONTIGUOUS_MEMORY
+ {
+ /* Number of bytes allocated. */
+ IN gctUINT64 bytes;
+
+ /* Physical address of allocation. Just a name. */
+ IN gctUINT32 physical;
+
+ /* Logical address of allocation. */
+ IN gctUINT64 logical;
+ }
+ FreeContiguousMemory;
+
+ /* gcvHAL_READ_REGISTER */
+ struct _gcsHAL_READ_REGISTER
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ /* Data read. */
+ OUT gctUINT32 data;
+ }
+ ReadRegisterData;
+
+ /* gcvHAL_WRITE_REGISTER */
+ struct _gcsHAL_WRITE_REGISTER
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ /* Data read. */
+ IN gctUINT32 data;
+ }
+ WriteRegisterData;
+
+ /* gcvHAL_READ_REGISTER_EX */
+ struct _gcsHAL_READ_REGISTER_EX
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ IN gctUINT32 coreSelect;
+
+ /* Data read. */
+ OUT gctUINT32 data[4];
+ }
+ ReadRegisterDataEx;
+
+ /* gcvHAL_WRITE_REGISTER_EX */
+ struct _gcsHAL_WRITE_REGISTER_EX
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ IN gctUINT32 coreSelect;
+
+ /* Data read. */
+ IN gctUINT32 data[4];
+ }
+ WriteRegisterDataEx;
+
+#if VIVANTE_PROFILER
+ /* gcvHAL_GET_PROFILE_SETTING */
+ struct _gcsHAL_GET_PROFILE_SETTING
+ {
+ /* Enable profiling */
+ OUT gctBOOL enable;
+ OUT gctBOOL syncMode;
+ }
+ GetProfileSetting;
+
+ /* gcvHAL_SET_PROFILE_SETTING */
+ struct _gcsHAL_SET_PROFILE_SETTING
+ {
+ /* Enable profiling */
+ IN gctBOOL enable;
+ IN gctBOOL syncMode;
+ }
+ SetProfileSetting;
+
+#if VIVANTE_PROFILER_PERDRAW
+ /* gcvHAL_READ_PROFILER_REGISTER_SETTING */
+ struct _gcsHAL_READ_PROFILER_REGISTER_SETTING
+ {
+ /*Should Clear Register*/
+ IN gctBOOL bclear;
+ }
+ SetProfilerRegisterClear;
+#endif
+ /* gcvHAL_READ_PROFILER_REGISTER_SETTING */
+ struct _gcsHAL_READ_PROFILER_REGISTER_SETTING
+ {
+ /*Should Clear Register*/
+ IN gctBOOL bclear;
+ }
+ SetProfilerRegisterClear;
+
+ /* gcvHAL_READ_ALL_PROFILE_REGISTERS */
+ struct _gcsHAL_READ_ALL_PROFILE_REGISTERS
+ {
+#if VIVANTE_PROFILER_CONTEXT
+ /* Context buffer object gckCONTEXT. Just a name. */
+ IN gctUINT32 context;
+#endif
+
+ /* Data read. */
+ OUT gcsPROFILER_COUNTERS counters;
+ }
+ RegisterProfileData;
+
+ struct _gcsHAL_READ_ALL_PROFILE_NEW_REGISTERS_PART1
+ {
+#if VIVANTE_PROFILER_CONTEXT
+ /* Context buffer object gckCONTEXT. Just a name. */
+ IN gctUINT32 context;
+#endif
+
+ /* Data read. */
+ OUT gcsPROFILER_NEW_COUNTERS_PART1 newCounters;
+ }
+ RegisterProfileNewData_part1;
+
+ struct _gcsHAL_READ_ALL_PROFILE_NEW_REGISTERS_PART2
+ {
+#if VIVANTE_PROFILER_CONTEXT
+ /* Context buffer object gckCONTEXT. Just a name. */
+ IN gctUINT32 context;
+#endif
+
+ /* Data read. */
+ OUT gcsPROFILER_NEW_COUNTERS_PART2 newCounters;
+ }
+ RegisterProfileNewData_part2;
+
+ /* gcvHAL_PROFILE_REGISTERS_2D */
+ struct _gcsHAL_PROFILE_REGISTERS_2D
+ {
+ /* Data read in gcs2D_PROFILE. */
+ OUT gctUINT64 hwProfile2D;
+ }
+ RegisterProfileData2D;
+#endif
+
+ /* Power management. */
+ /* gcvHAL_SET_POWER_MANAGEMENT_STATE */
+ struct _gcsHAL_SET_POWER_MANAGEMENT
+ {
+ /* Data read. */
+ IN gceCHIPPOWERSTATE state;
+ }
+ SetPowerManagement;
+
+ /* gcvHAL_QUERY_POWER_MANAGEMENT_STATE */
+ struct _gcsHAL_QUERY_POWER_MANAGEMENT
+ {
+ /* Data read. */
+ OUT gceCHIPPOWERSTATE state;
+
+ /* Idle query. */
+ OUT gctBOOL isIdle;
+ }
+ QueryPowerManagement;
+
+ /* gcvHAL_QUERY_KERNEL_SETTINGS */
+ struct _gcsHAL_QUERY_KERNEL_SETTINGS
+ {
+ /* Settings.*/
+ OUT gcsKERNEL_SETTINGS settings;
+ }
+ QueryKernelSettings;
+
+ /* gcvHAL_MAP_PHYSICAL */
+ struct _gcsHAL_MAP_PHYSICAL
+ {
+ /* gcvTRUE to map, gcvFALSE to unmap. */
+ IN gctBOOL map;
+
+ /* Physical address. */
+ IN OUT gctUINT64 physical;
+ }
+ MapPhysical;
+
+ /* gcvHAL_DEBUG */
+ struct _gcsHAL_DEBUG
+ {
+ /* If gcvTRUE, set the debug information. */
+ IN gctBOOL set;
+ IN gctUINT32 level;
+ IN gctUINT32 zones;
+ IN gctBOOL enable;
+
+ IN gceDEBUG_MESSAGE_TYPE type;
+ IN gctUINT32 messageSize;
+
+ /* Message to print if not empty. */
+ IN gctCHAR message[80];
+
+ }
+ Debug;
+
+ /* gcvHAL_CACHE */
+ struct _gcsHAL_CACHE
+ {
+ IN gceCACHEOPERATION operation;
+ IN gctUINT64 process;
+ IN gctUINT64 logical;
+ IN gctUINT64 bytes;
+ IN gctUINT32 node;
+ }
+ Cache;
+
+ /* gcvHAL_TIMESTAMP */
+ struct _gcsHAL_TIMESTAMP
+ {
+ /* Timer select. */
+ IN gctUINT32 timer;
+
+ /* Timer request type (0-stop, 1-start, 2-send delta). */
+ IN gctUINT32 request;
+
+ /* Result of delta time in microseconds. */
+ OUT gctINT32 timeDelta;
+ }
+ TimeStamp;
+
+ /* gcvHAL_DATABASE */
+ struct _gcsHAL_DATABASE
+ {
+ /* Set to gcvTRUE if you want to query a particular process ID.
+ ** Set to gcvFALSE to query the last detached process. */
+ IN gctBOOL validProcessID;
+
+ /* Process ID to query. */
+ IN gctUINT32 processID;
+
+ /* Information. */
+ OUT gcuDATABASE_INFO vidMem;
+ OUT gcuDATABASE_INFO nonPaged;
+ OUT gcuDATABASE_INFO contiguous;
+ OUT gcuDATABASE_INFO gpuIdle;
+
+ /* Detail information about video memory. */
+ OUT gcuDATABASE_INFO vidMemPool[3];
+ }
+ Database;
+
+ /* gcvHAL_VERSION */
+ struct _gcsHAL_VERSION
+ {
+ /* Major version: N.n.n. */
+ OUT gctINT32 major;
+
+ /* Minor version: n.N.n. */
+ OUT gctINT32 minor;
+
+ /* Patch version: n.n.N. */
+ OUT gctINT32 patch;
+
+ /* Build version. */
+ OUT gctUINT32 build;
+ }
+ Version;
+
+ /* gcvHAL_CHIP_INFO */
+ struct _gcsHAL_CHIP_INFO
+ {
+ /* Chip count. */
+ OUT gctINT32 count;
+
+ /* Chip types. */
+ OUT gceHARDWARE_TYPE types[gcdCHIP_COUNT];
+
+ /* Chip IDs. */
+ OUT gctUINT32 ids[gcvCORE_COUNT];
+ }
+ ChipInfo;
+
+ /* gcvHAL_ATTACH */
+ struct _gcsHAL_ATTACH
+ {
+ /* Handle of context buffer object. */
+ OUT gctUINT32 context;
+
+ /* Maximum state in the buffer. */
+ OUT gctUINT64 maxState;
+
+ /* Number of states in the buffer. */
+ OUT gctUINT32 numStates;
+
+ /* Map context buffer to user or not. */
+ IN gctBOOL map;
+
+ /* Physical of context buffer. */
+ OUT gctUINT32 physicals[2];
+
+ /* Physical of context buffer. */
+ OUT gctUINT64 logicals[2];
+
+ /* Bytes of context buffer. */
+ OUT gctUINT32 bytes;
+ }
+ Attach;
+
+ /* gcvHAL_DETACH */
+ struct _gcsHAL_DETACH
+ {
+ /* Context buffer object gckCONTEXT. Just a name. */
+ IN gctUINT32 context;
+ }
+ Detach;
+
+ /* gcvHAL_COMPOSE. */
+ gcsHAL_COMPOSE Compose;
+
+ /* gcvHAL_GET_FRAME_INFO. */
+ struct _gcsHAL_GET_FRAME_INFO
+ {
+ /* gcsHAL_FRAME_INFO* */
+ OUT gctUINT64 frameInfo;
+ }
+ GetFrameInfo;
+
+ /* gcvHAL_SET_TIME_OUT. */
+ struct _gcsHAL_SET_TIMEOUT
+ {
+ gctUINT32 timeOut;
+ }
+ SetTimeOut;
+
+#if gcdENABLE_VG
+ /* gcvHAL_COMMIT */
+ struct _gcsHAL_VGCOMMIT
+ {
+ /* Context buffer. gcsVGCONTEXT_PTR */
+ IN gctUINT64 context;
+
+ /* Command queue. gcsVGCMDQUEUE_PTR */
+ IN gctUINT64 queue;
+
+ /* Number of entries in the queue. */
+ IN gctUINT entryCount;
+
+ /* Task table. gcsTASK_MASTER_TABLE_PTR */
+ IN gctUINT64 taskTable;
+ }
+ VGCommit;
+
+ /* gcvHAL_QUERY_COMMAND_BUFFER */
+ struct _gcsHAL_QUERY_COMMAND_BUFFER
+ {
+ /* Command buffer attributes. */
+ OUT gcsCOMMAND_BUFFER_INFO information;
+ }
+ QueryCommandBuffer;
+
+#endif
+
+ struct _gcsHAL_SET_FSCALE_VALUE
+ {
+ IN gctUINT value;
+ }
+ SetFscaleValue;
+
+ struct _gcsHAL_GET_FSCALE_VALUE
+ {
+ OUT gctUINT value;
+ OUT gctUINT minValue;
+ OUT gctUINT maxValue;
+ }
+ GetFscaleValue;
+
+ struct _gcsHAL_NAME_VIDEO_MEMORY
+ {
+ IN gctUINT32 handle;
+ OUT gctUINT32 name;
+ }
+ NameVideoMemory;
+
+ struct _gcsHAL_IMPORT_VIDEO_MEMORY
+ {
+ IN gctUINT32 name;
+ OUT gctUINT32 handle;
+ }
+ ImportVideoMemory;
+
+ struct _gcsHAL_QUERY_RESET_TIME_STAMP
+ {
+ OUT gctUINT64 timeStamp;
+ OUT gctUINT64 contextID;
+ }
+ QueryResetTimeStamp;
+
+ struct _gcsHAL_CREATE_NATIVE_FENCE
+ {
+ /* Signal id. */
+ IN gctUINT64 signal;
+
+ /* Native fence file descriptor. */
+ OUT gctINT fenceFD;
+
+ }
+ CreateNativeFence;
+
+ struct _gcsHAL_WAIT_NATIVE_FENCE
+ {
+ /* Native fence file descriptor. */
+ IN gctINT fenceFD;
+
+ /* Wait timeout. */
+ IN gctUINT32 timeout;
+ }
+ WaitNativeFence;
+
+ struct _gcsHAL_DESTROY_MMU
+ {
+ /* Mmu object. */
+ IN gctUINT64 mmu;
+ }
+ DestroyMmu;
+
+ struct _gcsHAL_SHBUF
+ {
+ gceSHBUF_COMMAND_CODES command;
+
+ /* Shared buffer. */
+ IN OUT gctUINT64 id;
+
+ /* User data to be shared. */
+ IN gctUINT64 data;
+
+ /* Data size. */
+ IN OUT gctUINT32 bytes;
+ }
+ ShBuf;
+
+
+ struct _gcsHAL_GET_VIDEO_MEMORY_FD
+ {
+ IN gctUINT32 handle;
+ OUT gctINT fd;
+ }
+ GetVideoMemoryFd;
+
+ struct _gcsHAL_CONFIG_POWER_MANAGEMENT
+ {
+ IN gctBOOL enable;
+ }
+ ConfigPowerManagement;
+
+ struct _gcsHAL_WRAP_USER_MEMORY
+ {
+ /* Description of user memory. */
+ IN gcsUSER_MEMORY_DESC desc;
+
+ /* Output video mmory node. */
+ OUT gctUINT32 node;
+
+ }
+ WrapUserMemory;
+
+ struct _gcsHAL_WAIT_FENCE
+ {
+ IN gctUINT32 handle;
+ IN gctUINT32 timeOut;
+ }
+ WaitFence;
+
+ struct _gcsHAL_COMMIT_DONE
+ {
+ IN gctUINT64 context;
+ }
+ CommitDone;
+
+#if gcdDEC_ENABLE_AHB
+ struct _gcsHAL_DEC300_READ
+ {
+ gctUINT32 enable;
+ gctUINT32 readId;
+ gctUINT32 format;
+ gctUINT32 strides[3];
+ gctUINT32 is3D;
+ gctUINT32 isMSAA;
+ gctUINT32 clearValue;
+ gctUINT32 isTPC;
+ gctUINT32 isTPCCompressed;
+ gctUINT32 surfAddrs[3];
+ gctUINT32 tileAddrs[3];
+ }
+ DEC300Read;
+
+ struct _gcsHAL_DEC300_WRITE
+ {
+ gctUINT32 enable;
+ gctUINT32 readId;
+ gctUINT32 writeId;
+ gctUINT32 format;
+ gctUINT32 surfAddr;
+ gctUINT32 tileAddr;
+ }
+ DEC300Write;
+
+ struct _gcsHAL_DEC300_FLUSH
+ {
+ IN gctUINT8 useless;
+ }
+ DEC300Flush;
+
+ struct _gcsHAL_DEC300_FLUSH_WAIT
+ {
+ IN gctUINT32 done;
+ }
+ DEC300FlushWait;
+#endif
+ /* gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY: */
+ struct _gcsHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gctUINT32 node;
+
+ /* Type of surface. */
+ IN gceSURF_TYPE type;
+ }
+ BottomHalfUnlockVideoMemory;
+ }
+ u;
+}
+gcsHAL_INTERFACE;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h
new file mode 100644
index 000000000000..5e41e6506410
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver_vg.h
@@ -0,0 +1,300 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_driver_vg_h_
+#define __gc_hal_driver_vg_h_
+
+
+
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* I/O Control Codes ******************************
+\******************************************************************************/
+
+#define gcvHAL_CLASS "galcore"
+#define IOCTL_GCHAL_INTERFACE 30000
+
+/******************************************************************************\
+********************* Command buffer information structure. ********************
+\******************************************************************************/
+
+typedef struct _gcsCOMMAND_BUFFER_INFO * gcsCOMMAND_BUFFER_INFO_PTR;
+typedef struct _gcsCOMMAND_BUFFER_INFO
+{
+ /* FE command buffer interrupt ID. */
+ gctINT32 feBufferInt;
+
+ /* TS overflow interrupt ID. */
+ gctINT32 tsOverflowInt;
+
+ /* Alignment and mask for the buffer address. */
+ gctUINT addressMask;
+ gctUINT32 addressAlignment;
+
+ /* Alignment for each command. */
+ gctUINT32 commandAlignment;
+
+ /* Number of bytes required by the STATE command. */
+ gctUINT32 stateCommandSize;
+
+ /* Number of bytes required by the RESTART command. */
+ gctUINT32 restartCommandSize;
+
+ /* Number of bytes required by the FETCH command. */
+ gctUINT32 fetchCommandSize;
+
+ /* Number of bytes required by the CALL command. */
+ gctUINT32 callCommandSize;
+
+ /* Number of bytes required by the RETURN command. */
+ gctUINT32 returnCommandSize;
+
+ /* Number of bytes required by the EVENT command. */
+ gctUINT32 eventCommandSize;
+
+ /* Number of bytes required by the END command. */
+ gctUINT32 endCommandSize;
+
+ /* Number of bytes reserved at the tail of a static command buffer. */
+ gctUINT32 staticTailSize;
+
+ /* Number of bytes reserved at the tail of a dynamic command buffer. */
+ gctUINT32 dynamicTailSize;
+}
+gcsCOMMAND_BUFFER_INFO;
+
+/******************************************************************************\
+******************************** Task Structures *******************************
+\******************************************************************************/
+
+typedef enum _gceTASK
+{
+ gcvTASK_LINK,
+ gcvTASK_CLUSTER,
+ gcvTASK_INCREMENT,
+ gcvTASK_DECREMENT,
+ gcvTASK_SIGNAL,
+ gcvTASK_LOCKDOWN,
+ gcvTASK_UNLOCK_VIDEO_MEMORY,
+ gcvTASK_FREE_VIDEO_MEMORY,
+ gcvTASK_FREE_CONTIGUOUS_MEMORY,
+ gcvTASK_UNMAP_USER_MEMORY
+}
+gceTASK;
+
+typedef struct _gcsTASK_HEADER * gcsTASK_HEADER_PTR;
+typedef struct _gcsTASK_HEADER
+{
+ /* Task ID. */
+ IN gceTASK id;
+}
+gcsTASK_HEADER;
+
+typedef struct _gcsTASK_LINK * gcsTASK_LINK_PTR;
+typedef struct _gcsTASK_LINK
+{
+ /* Task ID (gcvTASK_LINK). */
+ IN gceTASK id;
+
+ /* Pointer to the next task container. */
+ IN gctPOINTER cotainer;
+
+ /* Pointer to the next task from the next task container. */
+ IN gcsTASK_HEADER_PTR task;
+}
+gcsTASK_LINK;
+
+typedef struct _gcsTASK_CLUSTER * gcsTASK_CLUSTER_PTR;
+typedef struct _gcsTASK_CLUSTER
+{
+ /* Task ID (gcvTASK_CLUSTER). */
+ IN gceTASK id;
+
+ /* Number of tasks in the cluster. */
+ IN gctUINT taskCount;
+}
+gcsTASK_CLUSTER;
+
+typedef struct _gcsTASK_INCREMENT * gcsTASK_INCREMENT_PTR;
+typedef struct _gcsTASK_INCREMENT
+{
+ /* Task ID (gcvTASK_INCREMENT). */
+ IN gceTASK id;
+
+ /* Address of the variable to increment. */
+ IN gctUINT32 address;
+}
+gcsTASK_INCREMENT;
+
+typedef struct _gcsTASK_DECREMENT * gcsTASK_DECREMENT_PTR;
+typedef struct _gcsTASK_DECREMENT
+{
+ /* Task ID (gcvTASK_DECREMENT). */
+ IN gceTASK id;
+
+ /* Address of the variable to decrement. */
+ IN gctUINT32 address;
+}
+gcsTASK_DECREMENT;
+
+typedef struct _gcsTASK_SIGNAL * gcsTASK_SIGNAL_PTR;
+typedef struct _gcsTASK_SIGNAL
+{
+ /* Task ID (gcvTASK_SIGNAL). */
+ IN gceTASK id;
+
+ /* Process owning the signal. */
+ IN gctHANDLE process;
+
+ /* Signal handle to signal. */
+ IN gctSIGNAL signal;
+
+#if defined(__QNXNTO__)
+ IN gctINT32 coid;
+ IN gctINT32 rcvid;
+#endif
+}
+gcsTASK_SIGNAL;
+
+typedef struct _gcsTASK_LOCKDOWN * gcsTASK_LOCKDOWN_PTR;
+typedef struct _gcsTASK_LOCKDOWN
+{
+ /* Task ID (gcvTASK_LOCKDOWN). */
+ IN gceTASK id;
+
+ /* Address of the user space counter. */
+ IN gctUINT32 userCounter;
+
+ /* Address of the kernel space counter. */
+ IN gctUINT32 kernelCounter;
+
+ /* Process owning the signal. */
+ IN gctHANDLE process;
+
+ /* Signal handle to signal. */
+ IN gctSIGNAL signal;
+}
+gcsTASK_LOCKDOWN;
+
+typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY * gcsTASK_UNLOCK_VIDEO_MEMORY_PTR;
+typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY
+{
+ /* Task ID (gcvTASK_UNLOCK_VIDEO_MEMORY). */
+ IN gceTASK id;
+
+ /* Allocated video memory. */
+ IN gctUINT64 node;
+}
+gcsTASK_UNLOCK_VIDEO_MEMORY;
+
+typedef struct _gcsTASK_FREE_VIDEO_MEMORY * gcsTASK_FREE_VIDEO_MEMORY_PTR;
+typedef struct _gcsTASK_FREE_VIDEO_MEMORY
+{
+ /* Task ID (gcvTASK_FREE_VIDEO_MEMORY). */
+ IN gceTASK id;
+
+ /* Allocated video memory. */
+ IN gctUINT32 node;
+}
+gcsTASK_FREE_VIDEO_MEMORY;
+
+typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY * gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR;
+typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY
+{
+ /* Task ID (gcvTASK_FREE_CONTIGUOUS_MEMORY). */
+ IN gceTASK id;
+
+ /* Number of bytes allocated. */
+ IN gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ IN gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ IN gctPOINTER logical;
+}
+gcsTASK_FREE_CONTIGUOUS_MEMORY;
+
+typedef struct _gcsTASK_UNMAP_USER_MEMORY * gcsTASK_UNMAP_USER_MEMORY_PTR;
+typedef struct _gcsTASK_UNMAP_USER_MEMORY
+{
+ /* Task ID (gcvTASK_UNMAP_USER_MEMORY). */
+ IN gceTASK id;
+
+ /* Base address of user memory to unmap. */
+ IN gctPOINTER memory;
+
+ /* Size of user memory in bytes to unmap. */
+ IN gctSIZE_T size;
+
+ /* Info record returned by gcvHAL_MAP_USER_MEMORY. */
+ IN gctPOINTER info;
+
+ /* Physical address of mapped memory as returned by
+ gcvHAL_MAP_USER_MEMORY. */
+ IN gctUINT32 address;
+}
+gcsTASK_UNMAP_USER_MEMORY;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h
new file mode 100644
index 000000000000..fe0d127a45bf
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_dump.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_dump_h_
+#define __gc_hal_dump_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** FILE LAYOUT:
+**
+** gcsDUMP_FILE structure
+**
+** gcsDUMP_DATA frame
+** gcsDUMP_DATA or gcDUMP_DATA_SIZE records rendingring the frame
+** gctUINT8 data[length]
+*/
+
+#define gcvDUMP_FILE_SIGNATURE gcmCC('g','c','D','B')
+
+typedef struct _gcsDUMP_FILE
+{
+ gctUINT32 signature; /* File signature */
+ gctSIZE_T length; /* Length of file */
+ gctUINT32 frames; /* Number of frames in file */
+}
+gcsDUMP_FILE;
+
+typedef enum _gceDUMP_TAG
+{
+ gcvTAG_SURFACE = gcmCC('s','u','r','f'),
+ gcvTAG_FRAME = gcmCC('f','r','m',' '),
+ gcvTAG_COMMAND = gcmCC('c','m','d',' '),
+ gcvTAG_INDEX = gcmCC('i','n','d','x'),
+ gcvTAG_STREAM = gcmCC('s','t','r','m'),
+ gcvTAG_TEXTURE = gcmCC('t','e','x','t'),
+ gcvTAG_RENDER_TARGET = gcmCC('r','n','d','r'),
+ gcvTAG_DEPTH = gcmCC('z','b','u','f'),
+ gcvTAG_RESOLVE = gcmCC('r','s','l','v'),
+ gcvTAG_DELETE = gcmCC('d','e','l',' '),
+ gcvTAG_BUFOBJ = gcmCC('b','u','f','o'),
+}
+gceDUMP_TAG;
+
+typedef struct _gcsDUMP_SURFACE
+{
+ gceDUMP_TAG type; /* Type of record. */
+ gctUINT32 address; /* Address of the surface. */
+ gctINT16 width; /* Width of surface. */
+ gctINT16 height; /* Height of surface. */
+ gceSURF_FORMAT format; /* Surface pixel format. */
+ gctSIZE_T length; /* Number of bytes inside the surface. */
+}
+gcsDUMP_SURFACE;
+
+typedef struct _gcsDUMP_DATA
+{
+ gceDUMP_TAG type; /* Type of record. */
+ gctSIZE_T length; /* Number of bytes of data. */
+ gctUINT32 address; /* Address for the data. */
+}
+gcsDUMP_DATA;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_dump_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
new file mode 100644
index 000000000000..9d261e9656fd
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
@@ -0,0 +1,587 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_eglplatform_h_
+#define __gc_hal_eglplatform_h_
+
+#include "gc_hal_types.h"
+#include "gc_hal_base.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#ifndef WIN32_LEAN_AND_MEAN
+/* #define WIN32_LEAN_AND_MEAN 1 */
+#endif
+#include <windows.h>
+
+typedef HDC HALNativeDisplayType;
+typedef HWND HALNativeWindowType;
+typedef HBITMAP HALNativePixmapType;
+
+typedef struct __BITFIELDINFO
+{
+ BITMAPINFO bmi;
+ RGBQUAD bmiColors[2];
+}
+BITFIELDINFO;
+
+#elif /* defined(__APPLE__) || */ defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
+
+#elif defined(WL_EGL_PLATFORM) || defined(EGL_API_WL) /* Wayland */
+
+#elif defined(__GBM__) /* GBM */
+
+#elif defined(__ANDROID__) || defined(ANDROID)
+
+#elif defined(MIR_EGL_PLATFORM) /* Mir */
+
+#elif defined(__QNXNTO__)
+
+#elif defined(__unix__) || defined(__APPLE__)
+
+#if defined(EGL_API_DFB)
+
+#elif defined(EGL_API_FB)
+
+#elif defined(EGL_API_NULLWS)
+
+
+#else
+
+/* X11 (tetative). */
+#endif
+
+#else
+#error "Platform not recognized"
+#endif
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+
+#include "gc_hal_eglplatform_type.h"
+
+/*******************************************************************************
+** Display. ********************************************************************
+*/
+
+gceSTATUS
+gcoOS_GetDisplay(
+ OUT HALNativeDisplayType * Display,
+ IN gctPOINTER Context
+ );
+
+gceSTATUS
+gcoOS_GetDisplayByIndex(
+ IN gctINT DisplayIndex,
+ OUT HALNativeDisplayType * Display,
+ IN gctPOINTER Context
+ );
+
+gceSTATUS
+gcoOS_GetDisplayInfo(
+ IN HALNativeDisplayType Display,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctSIZE_T * Physical,
+ OUT gctINT * Stride,
+ OUT gctINT * BitsPerPixel
+ );
+
+
+
+gceSTATUS
+gcoOS_GetDisplayInfoEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctUINT DisplayInfoSize,
+ OUT halDISPLAY_INFO * DisplayInfo
+ );
+
+gceSTATUS
+gcoOS_GetDisplayVirtual(
+ IN HALNativeDisplayType Display,
+ OUT gctINT * Width,
+ OUT gctINT * Height
+ );
+
+gceSTATUS
+gcoOS_GetDisplayBackbuffer(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ OUT gctPOINTER * context,
+ OUT gcoSURF * surface,
+ OUT gctUINT * Offset,
+ OUT gctINT * X,
+ OUT gctINT * Y
+ );
+
+gceSTATUS
+gcoOS_SetDisplayVirtual(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctUINT Offset,
+ IN gctINT X,
+ IN gctINT Y
+ );
+
+gceSTATUS
+gcoOS_SetDisplayVirtualEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctPOINTER Context,
+ IN gcoSURF Surface,
+ IN gctUINT Offset,
+ IN gctINT X,
+ IN gctINT Y
+ );
+
+gceSTATUS
+gcoOS_CancelDisplayBackbuffer(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctPOINTER Context,
+ IN gcoSURF Surface,
+ IN gctUINT Offset,
+ IN gctINT X,
+ IN gctINT Y
+ );
+
+gceSTATUS
+gcoOS_SetSwapInterval(
+ IN HALNativeDisplayType Display,
+ IN gctINT Interval
+);
+
+gceSTATUS
+gcoOS_SetSwapIntervalEx(
+ IN HALNativeDisplayType Display,
+ IN gctINT Interval,
+ IN gctPOINTER localDisplay);
+
+gceSTATUS
+gcoOS_GetSwapInterval(
+ IN HALNativeDisplayType Display,
+ IN gctINT_PTR Min,
+ IN gctINT_PTR Max
+);
+
+gceSTATUS
+gcoOS_DisplayBufferRegions(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctINT NumRects,
+ IN gctINT_PTR Rects
+ );
+
+gceSTATUS
+gcoOS_DestroyDisplay(
+ IN HALNativeDisplayType Display
+ );
+
+gceSTATUS
+gcoOS_InitLocalDisplayInfo(
+ IN HALNativeDisplayType Display,
+ IN OUT gctPOINTER * localDisplay
+ );
+
+gceSTATUS
+gcoOS_DeinitLocalDisplayInfo(
+ IN HALNativeDisplayType Display,
+ IN OUT gctPOINTER * localDisplay
+ );
+
+gceSTATUS
+gcoOS_GetDisplayInfoEx2(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctPOINTER localDisplay,
+ IN gctUINT DisplayInfoSize,
+ OUT halDISPLAY_INFO * DisplayInfo
+ );
+
+gceSTATUS
+gcoOS_GetDisplayBackbufferEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctPOINTER localDisplay,
+ OUT gctPOINTER * context,
+ OUT gcoSURF * surface,
+ OUT gctUINT * Offset,
+ OUT gctINT * X,
+ OUT gctINT * Y
+ );
+
+gceSTATUS
+gcoOS_IsValidDisplay(
+ IN HALNativeDisplayType Display
+ );
+
+gceSTATUS
+gcoOS_GetNativeVisualId(
+ IN HALNativeDisplayType Display,
+ OUT gctINT* nativeVisualId
+ );
+
+gctBOOL
+gcoOS_SynchronousFlip(
+ IN HALNativeDisplayType Display
+ );
+
+/*******************************************************************************
+** Windows. ********************************************************************
+*/
+
+gceSTATUS
+gcoOS_CreateWindow(
+ IN HALNativeDisplayType Display,
+ IN gctINT X,
+ IN gctINT Y,
+ IN gctINT Width,
+ IN gctINT Height,
+ OUT HALNativeWindowType * Window
+ );
+
+gceSTATUS
+gcoOS_GetWindowInfo(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ OUT gctINT * X,
+ OUT gctINT * Y,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * BitsPerPixel,
+ OUT gctUINT * Offset
+ );
+
+gceSTATUS
+gcoOS_DestroyWindow(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window
+ );
+
+gceSTATUS
+gcoOS_DrawImage(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT BitsPerPixel,
+ IN gctPOINTER Bits
+ );
+
+gceSTATUS
+gcoOS_GetImage(
+ IN HALNativeWindowType Window,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ OUT gctINT * BitsPerPixel,
+ OUT gctPOINTER * Bits
+ );
+
+gceSTATUS
+gcoOS_GetWindowInfoEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ OUT gctINT * X,
+ OUT gctINT * Y,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * BitsPerPixel,
+ OUT gctUINT * Offset,
+ OUT gceSURF_FORMAT * Format,
+ OUT gceSURF_TYPE * Type
+ );
+
+gceSTATUS
+gcoOS_DrawImageEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT BitsPerPixel,
+ IN gctPOINTER Bits,
+ IN gceSURF_FORMAT Format
+ );
+
+/*
+ * Possiable types:
+ * gcvSURF_BITMAP
+ * gcvSURF_RENDER_TARGET
+ * gcvSURF_RENDER_TARGET_NO_COMPRESSION
+ * gcvSURF_RENDER_TARGET_NO_TILE_STATUS
+ */
+gceSTATUS
+gcoOS_SetWindowFormat(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format
+ );
+
+
+/*******************************************************************************
+** Pixmaps. ********************************************************************
+*/
+
+gceSTATUS
+gcoOS_CreatePixmap(
+ IN HALNativeDisplayType Display,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT BitsPerPixel,
+ OUT HALNativePixmapType * Pixmap
+ );
+
+gceSTATUS
+gcoOS_GetPixmapInfo(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * BitsPerPixel,
+ OUT gctINT * Stride,
+ OUT gctPOINTER * Bits
+ );
+
+gceSTATUS
+gcoOS_DrawPixmap(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT BitsPerPixel,
+ IN gctPOINTER Bits
+ );
+
+gceSTATUS
+gcoOS_DestroyPixmap(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap
+ );
+
+gceSTATUS
+gcoOS_GetPixmapInfoEx(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * BitsPerPixel,
+ OUT gctINT * Stride,
+ OUT gctPOINTER * Bits,
+ OUT gceSURF_FORMAT * Format
+ );
+
+gceSTATUS
+gcoOS_CopyPixmapBits(
+ IN HALNativeDisplayType Display,
+ IN HALNativePixmapType Pixmap,
+ IN gctUINT DstWidth,
+ IN gctUINT DstHeight,
+ IN gctINT DstStride,
+ IN gceSURF_FORMAT DstFormat,
+ OUT gctPOINTER DstBits
+ );
+
+/*******************************************************************************
+** OS relative. ****************************************************************
+*/
+gceSTATUS
+gcoOS_LoadEGLLibrary(
+ OUT gctHANDLE * Handle
+ );
+
+gceSTATUS
+gcoOS_FreeEGLLibrary(
+ IN gctHANDLE Handle
+ );
+
+gceSTATUS
+gcoOS_ShowWindow(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window
+ );
+
+gceSTATUS
+gcoOS_HideWindow(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window
+ );
+
+gceSTATUS
+gcoOS_SetWindowTitle(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctCONST_STRING Title
+ );
+
+gceSTATUS
+gcoOS_CapturePointer(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window
+ );
+
+gceSTATUS
+gcoOS_GetEvent(
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ OUT halEvent * Event
+ );
+
+gceSTATUS
+gcoOS_CreateClientBuffer(
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT Format,
+ IN gctINT Type,
+ OUT gctPOINTER * ClientBuffer
+ );
+
+gceSTATUS
+gcoOS_GetClientBufferInfo(
+ IN gctPOINTER ClientBuffer,
+ OUT gctINT * Width,
+ OUT gctINT * Height,
+ OUT gctINT * Stride,
+ OUT gctPOINTER * Bits
+ );
+
+gceSTATUS
+gcoOS_DestroyClientBuffer(
+ IN gctPOINTER ClientBuffer
+ );
+
+gceSTATUS
+gcoOS_DestroyContext(
+ IN gctPOINTER Display,
+ IN gctPOINTER Context
+ );
+
+gceSTATUS
+gcoOS_CreateContext(
+ IN gctPOINTER LocalDisplay,
+ IN gctPOINTER Context
+ );
+
+gceSTATUS
+gcoOS_MakeCurrent(
+ IN gctPOINTER LocalDisplay,
+ IN HALNativeWindowType DrawDrawable,
+ IN HALNativeWindowType ReadDrawable,
+ IN gctPOINTER Context,
+ IN gcoSURF ResolveTarget
+ );
+
+gceSTATUS
+gcoOS_CreateDrawable(
+ IN gctPOINTER LocalDisplay,
+ IN HALNativeWindowType Drawable
+ );
+
+gceSTATUS
+gcoOS_DestroyDrawable(
+ IN gctPOINTER LocalDisplay,
+ IN HALNativeWindowType Drawable
+ );
+gceSTATUS
+gcoOS_SwapBuffers(
+ IN gctPOINTER LocalDisplay,
+ IN HALNativeWindowType Drawable,
+ IN gcoSURF RenderTarget,
+ IN gcoSURF ResolveTarget,
+ IN gctPOINTER ResolveBits,
+ OUT gctUINT *Width,
+ OUT gctUINT *Height
+ );
+
+gceSTATUS
+gcoOS_ResizeWindow(
+ IN gctPOINTER localDisplay,
+ IN HALNativeWindowType Drawable,
+ IN gctUINT Width,
+ IN gctUINT Height
+ );
+
+gceSTATUS
+gcoOS_RSForSwap(
+ IN gctPOINTER localDisplay,
+ IN HALNativeWindowType Drawable,
+ IN gctPOINTER resolve
+ );
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_eglplatform_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h
new file mode 100644
index 000000000000..159460d1253a
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform_type.h
@@ -0,0 +1,324 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_eglplatform_type_h_
+#define __gc_hal_eglplatform_type_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+** Events. *********************************************************************
+*/
+
+typedef enum _halEventType
+{
+ /* Keyboard event. */
+ HAL_KEYBOARD,
+
+ /* Mouse move event. */
+ HAL_POINTER,
+
+ /* Mouse button event. */
+ HAL_BUTTON,
+
+ /* Application close event. */
+ HAL_CLOSE,
+
+ /* Application window has been updated. */
+ HAL_WINDOW_UPDATE
+}
+halEventType;
+
+/* Scancodes for keyboard. */
+typedef enum _halKeys
+{
+ HAL_UNKNOWN = -1,
+
+ HAL_BACKSPACE = 0x08,
+ HAL_TAB,
+ HAL_ENTER = 0x0D,
+ HAL_ESCAPE = 0x1B,
+
+ HAL_SPACE = 0x20,
+ HAL_SINGLEQUOTE = 0x27,
+ HAL_PAD_ASTERISK = 0x2A,
+ HAL_COMMA = 0x2C,
+ HAL_HYPHEN,
+ HAL_PERIOD,
+ HAL_SLASH,
+ HAL_0,
+ HAL_1,
+ HAL_2,
+ HAL_3,
+ HAL_4,
+ HAL_5,
+ HAL_6,
+ HAL_7,
+ HAL_8,
+ HAL_9,
+ HAL_SEMICOLON = 0x3B,
+ HAL_EQUAL = 0x3D,
+ HAL_A = 0x41,
+ HAL_B,
+ HAL_C,
+ HAL_D,
+ HAL_E,
+ HAL_F,
+ HAL_G,
+ HAL_H,
+ HAL_I,
+ HAL_J,
+ HAL_K,
+ HAL_L,
+ HAL_M,
+ HAL_N,
+ HAL_O,
+ HAL_P,
+ HAL_Q,
+ HAL_R,
+ HAL_S,
+ HAL_T,
+ HAL_U,
+ HAL_V,
+ HAL_W,
+ HAL_X,
+ HAL_Y,
+ HAL_Z,
+ HAL_LBRACKET,
+ HAL_BACKSLASH,
+ HAL_RBRACKET,
+ HAL_BACKQUOTE = 0x60,
+
+ HAL_F1 = 0x80,
+ HAL_F2,
+ HAL_F3,
+ HAL_F4,
+ HAL_F5,
+ HAL_F6,
+ HAL_F7,
+ HAL_F8,
+ HAL_F9,
+ HAL_F10,
+ HAL_F11,
+ HAL_F12,
+
+ HAL_LCTRL,
+ HAL_RCTRL,
+ HAL_LSHIFT,
+ HAL_RSHIFT,
+ HAL_LALT,
+ HAL_RALT,
+ HAL_CAPSLOCK,
+ HAL_NUMLOCK,
+ HAL_SCROLLLOCK,
+ HAL_PAD_0,
+ HAL_PAD_1,
+ HAL_PAD_2,
+ HAL_PAD_3,
+ HAL_PAD_4,
+ HAL_PAD_5,
+ HAL_PAD_6,
+ HAL_PAD_7,
+ HAL_PAD_8,
+ HAL_PAD_9,
+ HAL_PAD_HYPHEN,
+ HAL_PAD_PLUS,
+ HAL_PAD_SLASH,
+ HAL_PAD_PERIOD,
+ HAL_PAD_ENTER,
+ HAL_SYSRQ,
+ HAL_PRNTSCRN,
+ HAL_BREAK,
+ HAL_UP,
+ HAL_LEFT,
+ HAL_RIGHT,
+ HAL_DOWN,
+ HAL_HOME,
+ HAL_END,
+ HAL_PGUP,
+ HAL_PGDN,
+ HAL_INSERT,
+ HAL_DELETE,
+ HAL_LWINDOW,
+ HAL_RWINDOW,
+ HAL_MENU,
+ HAL_POWER,
+ HAL_SLEEP,
+ HAL_WAKE
+}
+halKeys;
+
+/* Structure that defined keyboard mapping. */
+typedef struct _halKeyMap
+{
+ /* Normal key. */
+ halKeys normal;
+
+ /* Extended key. */
+ halKeys extended;
+}
+halKeyMap;
+
+/* Event structure. */
+typedef struct _halEvent
+{
+ /* Event type. */
+ halEventType type;
+
+ /* Event data union. */
+ union _halEventData
+ {
+ /* Event data for keyboard. */
+ struct _halKeyboard
+ {
+ /* Scancode. */
+ halKeys scancode;
+
+ /* ASCII characte of the key pressed. */
+ char key;
+
+ /* Flag whether the key was pressed (1) or released (0). */
+ char pressed;
+ }
+ keyboard;
+
+ /* Event data for pointer. */
+ struct _halPointer
+ {
+ /* Current pointer coordinate. */
+ int x;
+ int y;
+ }
+ pointer;
+
+ /* Event data for mouse buttons. */
+ struct _halButton
+ {
+ /* Left button state. */
+ int left;
+
+ /* Middle button state. */
+ int middle;
+
+ /* Right button state. */
+ int right;
+
+ /* Current pointer coordinate. */
+ int x;
+ int y;
+ }
+ button;
+ }
+ data;
+}
+halEvent;
+
+/* VFK_DISPLAY_INFO structure defining information returned by
+ vdkGetDisplayInfoEx. */
+typedef struct _halDISPLAY_INFO
+{
+ /* The size of the display in pixels. */
+ int width;
+ int height;
+
+ /* The stride of the dispay. -1 is returned if the stride is not known
+ ** for the specified display.*/
+ int stride;
+
+ /* The color depth of the display in bits per pixel. */
+ int bitsPerPixel;
+
+ /* The logical pointer to the display memory buffer. NULL is returned
+ ** if the pointer is not known for the specified display. */
+ void * logical;
+
+ /* The physical address of the display memory buffer. ~0 is returned
+ ** if the address is not known for the specified display. */
+ unsigned long physical;
+
+ /* Can be wraped as surface. */
+ int wrapFB;
+
+ /* FB_MULTI_BUFFER support */
+ int multiBuffer;
+ int backBufferY;
+
+ /* Tiled buffer / tile status support. */
+ int tiledBuffer;
+ int tileStatus;
+ int compression;
+
+ /* The color info of the display. */
+ unsigned int alphaLength;
+ unsigned int alphaOffset;
+ unsigned int redLength;
+ unsigned int redOffset;
+ unsigned int greenLength;
+ unsigned int greenOffset;
+ unsigned int blueLength;
+ unsigned int blueOffset;
+
+ /* Display flip support. */
+ int flip;
+}
+halDISPLAY_INFO;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_eglplatform_type_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
new file mode 100644
index 000000000000..3ea2d70c300a
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
@@ -0,0 +1,3059 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_engine_h_
+#define __gc_hal_engine_h_
+
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+
+
+#if gcdENABLE_3D && gcdENABLE_VG
+#include "gc_hal_engine_vg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _gcsSURF_RESOLVE_ARGS
+{
+ gceHAL_ARG_VERSION version;
+
+ union _gcsSURF_RESOLVE_ARGS_UNION
+ {
+
+ struct _gcsSURF_RESOLVE_ARG_v2
+ {
+ gctBOOL yInverted;
+ gctBOOL directCopy;
+ gctBOOL resample;
+ gctBOOL bUploadTex; /* used for upload tex.*/
+ gctBOOL visualizeDepth; /* convert depth to visible color */
+ gcsPOINT srcOrigin;
+ gcsPOINT dstOrigin;
+ gcsPOINT rectSize;
+ gctUINT numSlices;
+ gceENGINE engine; /* 3DBlit engine */
+ gctBOOL gpuOnly; /* need only try HW path.*/
+
+ gctBOOL dump; /* need dump for verify */
+ gctBOOL srcSwizzle; /* src surface format swizzle infomation */
+ gctBOOL dstSwizzle; /* dst surface format swizzle infomation */
+ gctBOOL srcCompressed; /* src compressed format*/
+ gctBOOL dstCompressed; /* dst compressed format*/
+ } v2;
+ } uArgs;
+}
+gcsSURF_RESOLVE_ARGS;
+
+typedef struct _gscBUFFER_VIEW
+{
+ gctUINT32 cmd;
+}gcsBUFFER_VIEW, *gcsBUFFER_VIEW_PTR;
+
+typedef struct _gcsIMAGE_VIEW
+{
+ gctUINT32 cmd;
+}gcsIMAGE_VIEW, *gcsIMAGE_VIEW_PTR;
+
+#if gcdENABLE_3D
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoSTREAM * gcoSTREAM;
+typedef struct _gcoVERTEX * gcoVERTEX;
+typedef struct _gcoTEXTURE * gcoTEXTURE;
+typedef struct _gcoINDEX * gcoINDEX;
+typedef struct _gcsVERTEX_ATTRIBUTES * gcsVERTEX_ATTRIBUTES_PTR;
+typedef struct _gcoVERTEXARRAY * gcoVERTEXARRAY;
+typedef struct _gcoBUFOBJ * gcoBUFOBJ;
+
+#define gcdATTRIBUTE_COUNT 32
+
+typedef enum _gcePROGRAM_STAGE
+{
+ gcvPROGRAM_STAGE_VERTEX = 0x0,
+ gcvPROGRAM_STAGE_TCS = 0x1,
+ gcvPROGRAM_STAGE_TES = 0x2,
+ gcvPROGRAM_STAGE_GEOMETRY = 0x3,
+ gcvPROGRAM_STAGE_FRAGMENT = 0x4,
+ gcvPROGRAM_STAGE_COMPUTE = 0x5,
+ gcvPROGRAM_STAGE_OPENCL = 0x6,
+ gcvPROGRAM_STAGE_LAST
+}
+gcePROGRAM_STAGE;
+
+typedef enum _gcePROGRAM_STAGE_BIT
+{
+ gcvPROGRAM_STAGE_VERTEX_BIT = 1 << gcvPROGRAM_STAGE_VERTEX,
+ gcvPROGRAM_STAGE_TCS_BIT = 1 << gcvPROGRAM_STAGE_TCS,
+ gcvPROGRAM_STAGE_TES_BIT = 1 << gcvPROGRAM_STAGE_TES,
+ gcvPROGRAM_STAGE_GEOMETRY_BIT = 1 << gcvPROGRAM_STAGE_GEOMETRY,
+ gcvPROGRAM_STAGE_FRAGMENT_BIT = 1 << gcvPROGRAM_STAGE_FRAGMENT,
+ gcvPROGRAM_STAGE_COMPUTE_BIT = 1 << gcvPROGRAM_STAGE_COMPUTE,
+ gcvPROGRAM_STAGE_OPENCL_BIT = 1 << gcvPROGRAM_STAGE_OPENCL,
+}
+gcePROGRAM_STAGE_BIT;
+
+
+#define gcvPORGRAM_STAGE_GPIPE (gcvPROGRAM_STAGE_VERTEX_BIT | \
+ gcvPROGRAM_STAGE_TCS_BIT | \
+ gcvPROGRAM_STAGE_TES_BIT | \
+ gcvPROGRAM_STAGE_GEOMETRY_BIT)
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+gceSTATUS
+gcoHAL_QueryShaderCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * UnifiedUniforms,
+ OUT gctUINT * VertUniforms,
+ OUT gctUINT * FragUniforms,
+ OUT gctUINT * Varyings,
+ OUT gctUINT * ShaderCoreCount,
+ OUT gctUINT * ThreadCount,
+ OUT gctUINT * VertInstructionCount,
+ OUT gctUINT * FragInstructionCount
+ );
+
+gceSTATUS
+gcoHAL_QuerySamplerBase(
+ IN gcoHAL Hal,
+ OUT gctUINT32 * VertexCount,
+ OUT gctINT_PTR VertexBase,
+ OUT gctUINT32 * FragmentCount,
+ OUT gctINT_PTR FragmentBase
+ );
+
+gceSTATUS
+gcoHAL_QueryUniformBase(
+ IN gcoHAL Hal,
+ OUT gctUINT32 * VertexBase,
+ OUT gctUINT32 * FragmentBase
+ );
+
+gceSTATUS
+gcoHAL_QueryTextureCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MaxDepth,
+ OUT gctBOOL * Cubic,
+ OUT gctBOOL * NonPowerOfTwo,
+ OUT gctUINT * VertexSamplers,
+ OUT gctUINT * PixelSamplers
+ );
+
+gceSTATUS
+gcoHAL_QueryTextureMaxAniso(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxAnisoValue
+ );
+
+gceSTATUS
+gcoHAL_QueryStreamCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT32 * MaxAttributes,
+ OUT gctUINT32 * MaxStreamStride,
+ OUT gctUINT32 * NumberOfStreams,
+ OUT gctUINT32 * Alignment,
+ OUT gctUINT32 * MaxAttribOffset
+ );
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*--------------------------------- gcoSURF 3D --------------------------------*/
+typedef enum _gceBLIT_FLAG
+{
+ gcvBLIT_FLAG_SKIP_DEPTH_WRITE = 1 << 0,
+ gcvBLIT_FLAG_SKIP_STENCIL_WRITE = 1 << 1,
+} gceBLIT_FLAG;
+
+typedef struct _gcsSURF_BLIT_ARGS
+{
+ gcoSURF srcSurface;
+ gctINT srcX, srcY, srcZ;
+ gctINT srcWidth, srcHeight, srcDepth;
+ gcoSURF dstSurface;
+ gctINT dstX, dstY, dstZ;
+ gctINT dstWidth, dstHeight, dstDepth;
+ gctBOOL xReverse;
+ gctBOOL yReverse;
+ gctBOOL scissorTest;
+ gcsRECT scissor;
+ gctUINT flags;
+ gctUINT srcNumSlice, dstNumSlice;
+}
+gcsSURF_BLIT_ARGS;
+
+
+
+
+/* Clear flags. */
+typedef enum _gceCLEAR
+{
+ gcvCLEAR_COLOR = 0x1,
+ gcvCLEAR_DEPTH = 0x2,
+ gcvCLEAR_STENCIL = 0x4,
+ gcvCLEAR_HZ = 0x8,
+ gcvCLEAR_WITH_GPU_ONLY = 0x100,
+ gcvCLEAR_WITH_CPU_ONLY = 0x200,
+ gcvCLEAR_MULTI_SLICES = 0x400,
+}
+gceCLEAR;
+
+typedef struct _gcsSURF_CLEAR_ARGS
+{
+ /*
+ ** Color to fill the color portion of the framebuffer when clear
+ ** is called.
+ */
+ struct {
+ gcuVALUE r;
+ gcuVALUE g;
+ gcuVALUE b;
+ gcuVALUE a;
+ /* Color has multiple value type so we must specify it. */
+ gceVALUE_TYPE valueType;
+ } color;
+
+ gcuVALUE depth;
+ gctUINT stencil;
+
+ gctUINT8 stencilMask; /* stencil bit-wise mask */
+ gctBOOL depthMask; /* Depth Write Mask */
+ gctUINT8 colorMask; /* 4-bit channel Mask: ABGR:MSB->LSB */
+ gcsRECT_PTR clearRect; /* NULL means full clear */
+ gceCLEAR flags; /* clear flags */
+
+ gctUINT32 offset; /* Offset in surface to cube/array/3D, obsolete in v2 version */
+
+} gcsSURF_CLEAR_ARGS, *gcsSURF_CLEAR_ARGS_PTR;
+
+
+typedef struct _gscSURF_BLITDRAW_BLIT
+{
+ gcoSURF srcSurface;
+ gcoSURF dstSurface;
+ gcsRECT srcRect;
+ gcsRECT dstRect;
+ gceTEXTURE_FILTER filterMode;
+ gctBOOL xReverse;
+ gctBOOL yReverse;
+ gctBOOL scissorEnabled;
+ gcsRECT scissor;
+}gscSURF_BLITDRAW_BLIT;
+
+
+typedef enum _gceBLITDRAW_TYPE
+{
+ gcvBLITDRAW_CLEAR = 0,
+ gcvBLITDRAW_BLIT = 1,
+
+ /* last number, not a real type */
+ gcvBLITDRAW_NUM_TYPE
+ }
+gceBLITDRAW_TYPE;
+
+typedef enum _gceSPLIT_DRAW_TYPE
+{
+ gcvSPLIT_DRAW_UNKNOWN = 0x0,
+ gcvSPLIT_DRAW_1,
+ gcvSPLIT_DRAW_2,
+ gcvSPLIT_DRAW_3,
+ gcvSPLIT_DRAW_XFB,
+ gcvSPLIT_DRAW_INDEX_FETCH,
+ gcvSPLIT_DRAW_TCS,
+ gcvSPLIT_DRAW_LAST
+}
+gceSPLIT_DRAW_TYPE;
+
+typedef gceSTATUS (* gctSPLIT_DRAW_FUNC_PTR)(
+ IN gctPOINTER gc,
+ IN gctPOINTER instantDraw,
+ IN gctPOINTER splitDrawInfo
+ );
+
+typedef struct _gcsSPLIT_DRAW_INFO
+{
+ gceSPLIT_DRAW_TYPE splitDrawType;
+ gctSPLIT_DRAW_FUNC_PTR splitDrawFunc;
+
+ union _gcsSPLIT_DRAW_UNION
+ {
+ /* This path will split many draw.*/
+ struct __gcsSPLIT_DRAW_INFO_TCS
+ {
+ gctPOINTER indexPtr;
+ gctUINT indexPerPatch;
+ }info_tcs;
+
+ /* This path split into two draw at most.
+ ** es11 path follow the old code, es30 path
+ ** add more info parameter to record
+ */
+ struct __gcsSPLIT_DRAW_INFO_INDEX_FETCH
+ {
+ gctSIZE_T instanceCount;
+ gctSIZE_T splitCount;
+ gcePRIMITIVE splitPrimMode;
+ gctSIZE_T splitPrimCount;
+ }info_index_fetch;
+ }u;
+} gcsSPLIT_DRAW_INFO,
+*gcsSPLIT_DRAW_INFO_PTR;
+
+typedef struct _gscSURF_BLITDRAW_ARGS
+{
+ /* always the fist member */
+ gceHAL_ARG_VERSION version;
+
+ union _gcsSURF_BLITDRAW_ARGS_UNION
+ {
+ struct _gscSURF_BLITDRAW_ARG_v1
+ {
+ /* Whether it's clear or blit operation, can be extended. */
+ gceBLITDRAW_TYPE type;
+
+ union _gscSURF_BLITDRAW_UNION
+ {
+ gscSURF_BLITDRAW_BLIT blit;
+
+ struct _gscSURF_BLITDRAW_CLEAR
+ {
+ gcsSURF_CLEAR_ARGS clearArgs;
+ gcoSURF rtSurface;
+ gcoSURF dsSurface;
+ } clear;
+ } u;
+ } v1;
+ } uArgs;
+}
+gcsSURF_BLITDRAW_ARGS;
+
+typedef struct _gcsSURF_BLITBLT_ARGS
+{
+ gctCONST_POINTER buf;
+ gceSURF_FORMAT format;
+ gctUINT32 stride;
+ gcoSURF dstSurf;
+ gcsPOINT dstOrigin;
+ gcsPOINT rectSize;
+ gctUINT32 dstOffset;
+}
+gcsSURF_BLITBLT_ARGS;
+
+
+/* CPU Blit with format (including linear <-> tile) conversion*/
+gceSTATUS
+gcoSURF_BlitCPU(
+ gcsSURF_BLIT_ARGS* args
+ );
+
+/* Copy a rectangular area with format conversion. */
+gceSTATUS
+gcoSURF_CopyPixels(
+ IN gcsSURF_VIEW *SrcView,
+ IN gcsSURF_VIEW *DstView,
+ IN gcsSURF_RESOLVE_ARGS *Args
+ );
+
+/* Clear surface function. */
+gceSTATUS
+gcoSURF_Clear(
+ IN gcsSURF_VIEW *SurfView,
+ IN gcsSURF_CLEAR_ARGS_PTR ClearArgs
+ );
+
+/* Preserve pixels from source. */
+gceSTATUS
+gcoSURF_Preserve(
+ IN gcoSURF SrcSurf,
+ IN gcoSURF DstSurf,
+ IN gcsRECT_PTR MaskRect
+ );
+
+/* TO BE REMOVED */
+gceSTATUS
+depr_gcoSURF_Resolve(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 DestAddress,
+ IN gctPOINTER DestBits,
+ IN gctINT DestStride,
+ IN gceSURF_TYPE DestType,
+ IN gceSURF_FORMAT DestFormat,
+ IN gctUINT DestWidth,
+ IN gctUINT DestHeight
+ );
+
+gceSTATUS
+depr_gcoSURF_ResolveRect(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DstSurface,
+ IN gctUINT32 DstAddress,
+ IN gctPOINTER DstBits,
+ IN gctINT DstStride,
+ IN gceSURF_TYPE DstType,
+ IN gceSURF_FORMAT DstFormat,
+ IN gctUINT DstWidth,
+ IN gctUINT DstHeight,
+ IN gcsPOINT_PTR SrcOrigin,
+ IN gcsPOINT_PTR gcoSURF,
+ IN gcsPOINT_PTR RectSize
+ );
+
+/* Resample surface. */
+gceSTATUS
+gcoSURF_Resample(
+ IN gcoSURF SrcSurf,
+ IN gcoSURF DstSurf
+ );
+
+/* Resolve rectangular area of a surface. */
+gceSTATUS
+gcoSURF_ResolveRect(
+ IN gcsSURF_VIEW *SrcView,
+ IN gcsSURF_VIEW *DstView,
+ IN gcsSURF_RESOLVE_ARGS *Args
+ );
+
+gceSTATUS
+gcoSURF_GetResolveAlignment(
+ IN gcoSURF Surface,
+ OUT gctUINT *originX,
+ OUT gctUINT *originY,
+ OUT gctUINT *sizeX,
+ OUT gctUINT *sizeY
+ );
+
+gceSTATUS
+gcoSURF_IsHWResolveable(
+ IN gcoSURF SrcSurf,
+ IN gcoSURF DstSurf,
+ IN gcsPOINT_PTR SrcOrigin,
+ IN gcsPOINT_PTR DstOrigin,
+ IN gcsPOINT_PTR RectSize
+ );
+
+/* Set surface resolvability. */
+gceSTATUS
+gcoSURF_SetResolvability(
+ IN gcoSURF Surface,
+ IN gctBOOL Resolvable
+ );
+
+gceSTATUS
+gcoSURF_IsRenderable(
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoSURF_IsFormatRenderableAsRT(
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoBUFOBJ_GetFence(
+ IN gcoBUFOBJ BufObj,
+ IN gceFENCE_TYPE Type
+ );
+
+gceSTATUS
+gcoBUFOBJ_WaitFence(
+ IN gcoBUFOBJ BufObj,
+ IN gceFENCE_TYPE Type
+ );
+
+gceSTATUS
+gcoBUFOBJ_IsFenceEnabled(
+ IN gcoBUFOBJ BufObj
+ );
+
+gceSTATUS
+gcoSURF_SetSharedLock(
+ IN gcoSURF Surface,
+ IN gctPOINTER SharedLock
+ );
+
+gceSTATUS
+gcoSURF_GetFence(
+ IN gcoSURF Surface,
+ IN gceFENCE_TYPE Type
+ );
+
+gceSTATUS
+gcoSURF_WaitFence(
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoSTREAM_GetFence(
+ IN gcoSTREAM stream
+ );
+
+gceSTATUS
+gcoSTREAM_WaitFence(
+ IN gcoSTREAM stream
+ );
+
+gceSTATUS
+gcoINDEX_GetFence(
+ IN gcoINDEX Index
+ );
+
+gceSTATUS
+gcoINDEX_WaitFence(
+ IN gcoINDEX Index,
+ IN gceFENCE_TYPE Type
+ );
+
+gceSTATUS
+gcoINDEX_SetSharedLock(
+ IN gcoINDEX Index,
+ IN gctPOINTER SharedLock
+ );
+
+gceSTATUS
+gcoSURF_DrawBlit(
+ gcsSURF_VIEW *SrcView,
+ gcsSURF_VIEW *DstView,
+ gscSURF_BLITDRAW_BLIT *Args
+ );
+
+
+/******************************************************************************\
+******************************** gcoINDEX Object *******************************
+\******************************************************************************/
+
+/* Construct a new gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Construct(
+ IN gcoHAL Hal,
+ OUT gcoINDEX * Index
+ );
+
+/* Destroy a gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Destroy(
+ IN gcoINDEX Index
+ );
+
+/* Lock index in memory. */
+gceSTATUS
+gcoINDEX_Lock(
+ IN gcoINDEX Index,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+/* Unlock index that was previously locked with gcoINDEX_Lock. */
+gceSTATUS
+gcoINDEX_Unlock(
+ IN gcoINDEX Index
+ );
+
+/* Upload index data into the memory. */
+gceSTATUS
+gcoINDEX_Load(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE IndexType,
+ IN gctUINT32 IndexCount,
+ IN gctPOINTER IndexBuffer
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_Bind(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_BindOffset(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset
+ );
+
+/* Free existing index buffer. */
+gceSTATUS
+gcoINDEX_Free(
+ IN gcoINDEX Index
+ );
+
+/* Upload data into an index buffer. */
+gceSTATUS
+gcoINDEX_Upload(
+ IN gcoINDEX Index,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Bytes
+ );
+
+/* Upload data into an index buffer starting at an offset. */
+gceSTATUS
+gcoINDEX_UploadOffset(
+ IN gcoINDEX Index,
+ IN gctSIZE_T Offset,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Bytes
+ );
+
+/*Merge index2 to index1 from 0, index2 must subset of inex1*/
+gceSTATUS
+gcoINDEX_Merge(
+ IN gcoINDEX Index1,
+ IN gcoINDEX Index2
+ );
+
+/*check if index buffer is enough for this draw*/
+gctBOOL
+gcoINDEX_CheckRange(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctINT Count,
+ IN gctUINT32 Indices
+ );
+
+/* Query the index capabilities. */
+gceSTATUS
+gcoINDEX_QueryCaps(
+ OUT gctBOOL * Index8,
+ OUT gctBOOL * Index16,
+ OUT gctBOOL * Index32,
+ OUT gctUINT * MaxIndex
+ );
+
+/* Determine the index range in the current index buffer. */
+gceSTATUS
+gcoINDEX_GetIndexRange(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset,
+ IN gctUINT32 Count,
+ OUT gctUINT32 * MinimumIndex,
+ OUT gctUINT32 * MaximumIndex
+ );
+
+/* Dynamic buffer management. */
+gceSTATUS
+gcoINDEX_SetDynamic(
+ IN gcoINDEX Index,
+ IN gctSIZE_T Bytes,
+ IN gctUINT Buffers
+ );
+
+gceSTATUS
+gcoCLHardware_Construct(void);
+/******************************************************************************\
+********************************** gco3D Object *********************************
+\******************************************************************************/
+
+/* Blending targets. */
+typedef enum _gceBLEND_UNIT
+{
+ gcvBLEND_SOURCE,
+ gcvBLEND_TARGET,
+}
+gceBLEND_UNIT;
+
+/* Construct a new gco3D object. */
+gceSTATUS
+gco3D_Construct(
+ IN gcoHAL Hal,
+ IN gctBOOL Robust,
+ OUT gco3D * Engine
+ );
+
+/* Destroy an gco3D object. */
+gceSTATUS
+gco3D_Destroy(
+ IN gco3D Engine
+ );
+
+/* Set 3D API type. */
+gceSTATUS
+gco3D_SetAPI(
+ IN gco3D Engine,
+ IN gceAPI ApiType
+ );
+
+/* Get 3D API type. */
+gceSTATUS
+gco3D_GetAPI(
+ IN gco3D Engine,
+ OUT gceAPI * ApiType
+ );
+
+gceSTATUS
+gco3D_SetTarget(
+ IN gco3D Engine,
+ IN gctUINT32 TargetIndex,
+ IN gcsSURF_VIEW *SurfView,
+ IN gctUINT32 LayerIndex
+ );
+
+gceSTATUS
+gco3D_UnsetTarget(
+ IN gco3D Engine,
+ IN gctUINT32 TargetIndex,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gco3D_SetPSOutputMapping(
+ IN gco3D Engine,
+ IN gctINT32 * psOutputMapping
+ );
+
+gceSTATUS
+gco3D_SetRenderLayered(
+ IN gco3D Engine,
+ IN gctBOOL Enable,
+ IN gctUINT MaxLayers
+ );
+
+gceSTATUS
+gco3D_SetShaderLayered(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco3D_IsProgramSwitched(
+ IN gco3D Engine
+ );
+
+/* Set depth buffer. */
+gceSTATUS
+gco3D_SetDepth(
+ IN gco3D Engine,
+ IN gcsSURF_VIEW *SurfView
+ );
+
+/* Unset depth buffer. */
+gceSTATUS
+gco3D_UnsetDepth(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Set viewport. */
+gceSTATUS
+gco3D_SetViewport(
+ IN gco3D Engine,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Set scissors. */
+gceSTATUS
+gco3D_SetScissors(
+ IN gco3D Engine,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Set clear color. */
+gceSTATUS
+gco3D_SetClearColor(
+ IN gco3D Engine,
+ IN gctUINT8 Red,
+ IN gctUINT8 Green,
+ IN gctUINT8 Blue,
+ IN gctUINT8 Alpha
+ );
+
+/* Set fixed point clear color. */
+gceSTATUS
+gco3D_SetClearColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+/* Set floating point clear color. */
+gceSTATUS
+gco3D_SetClearColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Set fixed point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Depth
+ );
+
+/* Set floating point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthF(
+ IN gco3D Engine,
+ IN gctFLOAT Depth
+ );
+
+/* Set clear stencil. */
+gceSTATUS
+gco3D_SetClearStencil(
+ IN gco3D Engine,
+ IN gctUINT32 Stencil
+ );
+
+/* Set shading mode. */
+gceSTATUS
+gco3D_SetShading(
+ IN gco3D Engine,
+ IN gceSHADING Shading
+ );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_EnableBlending(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set blending function. */
+gceSTATUS
+gco3D_SetBlendFunction(
+ IN gco3D Engine,
+ IN gceBLEND_UNIT Unit,
+ IN gceBLEND_FUNCTION FunctionRGB,
+ IN gceBLEND_FUNCTION FunctionAlpha
+ );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_SetBlendMode(
+ IN gco3D Engine,
+ IN gceBLEND_MODE ModeRGB,
+ IN gceBLEND_MODE ModeAlpha
+ );
+
+/* Set blending mode for separate rt control */
+gceSTATUS
+gco3D_EnableBlendingIndexed(
+ IN gco3D Engine,
+ IN gctUINT Index,
+ IN gctBOOL Enable
+ );
+
+/* Set blending function for separate rt control */
+gceSTATUS
+gco3D_SetBlendFunctionIndexed(
+ IN gco3D Engine,
+ IN gctUINT Index,
+ IN gceBLEND_UNIT Unit,
+ IN gceBLEND_FUNCTION FunctionRGB,
+ IN gceBLEND_FUNCTION FunctionAlpha
+ );
+
+/* Set blending mode for separate rt control*/
+gceSTATUS
+gco3D_SetBlendModeIndexed(
+ IN gco3D Engine,
+ IN gctUINT Index,
+ IN gceBLEND_MODE ModeRGB,
+ IN gceBLEND_MODE ModeAlpha
+ );
+
+/* Set blending color. */
+gceSTATUS
+gco3D_SetBlendColor(
+ IN gco3D Engine,
+ IN gctUINT Red,
+ IN gctUINT Green,
+ IN gctUINT Blue,
+ IN gctUINT Alpha
+ );
+
+/* Set fixed point blending color. */
+gceSTATUS
+gco3D_SetBlendColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+/* Set floating point blending color. */
+gceSTATUS
+gco3D_SetBlendColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Set culling mode. */
+gceSTATUS
+gco3D_SetCulling(
+ IN gco3D Engine,
+ IN gceCULL Mode
+ );
+
+/* Enable point size */
+gceSTATUS
+gco3D_SetPointSizeEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set point sprite */
+gceSTATUS
+gco3D_SetPointSprite(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+
+/* Enable/Disable primitive-id. */
+gceSTATUS
+gco3D_SetPrimitiveIdEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set fill mode. */
+gceSTATUS
+gco3D_SetFill(
+ IN gco3D Engine,
+ IN gceFILL Mode
+ );
+
+/* Set depth compare mode. */
+gceSTATUS
+gco3D_SetDepthCompare(
+ IN gco3D Engine,
+ IN gceCOMPARE Compare
+ );
+
+/* Enable depth writing. */
+gceSTATUS
+gco3D_EnableDepthWrite(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set depth mode. */
+gceSTATUS
+gco3D_SetDepthMode(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode
+ );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeX(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode,
+ IN gctFIXED_POINT Near,
+ IN gctFIXED_POINT Far
+ );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeF(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode,
+ IN gctFLOAT Near,
+ IN gctFLOAT Far
+ );
+
+/* Set last pixel enable */
+gceSTATUS
+gco3D_SetLastPixelEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set depth Bias and Scale */
+gceSTATUS
+gco3D_SetDepthScaleBiasX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT DepthScale,
+ IN gctFIXED_POINT DepthBias
+ );
+
+gceSTATUS
+gco3D_SetDepthScaleBiasF(
+ IN gco3D Engine,
+ IN gctFLOAT DepthScale,
+ IN gctFLOAT DepthBias
+ );
+
+/* Set depth near and far clipping plane. */
+gceSTATUS
+gco3D_SetDepthPlaneF(
+ IN gco3D Engine,
+ IN gctFLOAT Near,
+ IN gctFLOAT Far
+ );
+
+/* Enable or disable dithering. */
+gceSTATUS
+gco3D_EnableDither(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set color write enable bits. */
+gceSTATUS
+gco3D_SetColorWrite(
+ IN gco3D Engine,
+ IN gctUINT8 Enable
+ );
+
+/* Set color write enable bits for separate rt control */
+gceSTATUS
+gco3D_SetColorWriteIndexed(
+ IN gco3D Engine,
+ IN gctUINT Index,
+ IN gctUINT8 Enable
+ );
+
+/* Enable or disable early depth. */
+gceSTATUS
+gco3D_SetEarlyDepth(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Deprecated: Enable or disable all early depth operations. */
+gceSTATUS
+gco3D_SetAllEarlyDepthModes(
+ IN gco3D Engine,
+ IN gctBOOL Disable
+ );
+
+
+gceSTATUS
+gco3D_SetEarlyDepthFromAPP(
+ IN gco3D Engine,
+ IN gctBOOL EarlyDepthFromAPP
+ );
+
+gceSTATUS
+gco3D_SetRADepthWrite(
+ IN gco3D Engine,
+ IN gctBOOL Disable,
+ IN gctBOOL psReadZ,
+ IN gctBOOL psReadW
+ );
+
+gceSTATUS
+gco3D_SetPatchVertices(
+ IN gco3D Engine,
+ IN gctINT PatchVertices
+ );
+
+
+/* Switch dynamic early mode */
+gceSTATUS
+gco3D_SwitchDynamicEarlyDepthMode(
+ IN gco3D Engine
+ );
+
+/* Set dynamic early mode */
+gceSTATUS
+gco3D_DisableDynamicEarlyDepthMode(
+ IN gco3D Engine,
+ IN gctBOOL Disable
+ );
+
+/* Enable or disable depth-only mode. */
+gceSTATUS
+gco3D_SetDepthOnly(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+typedef struct _gcsSTENCIL_INFO * gcsSTENCIL_INFO_PTR;
+typedef struct _gcsSTENCIL_INFO
+{
+ gceSTENCIL_MODE mode;
+
+ gctUINT8 maskFront;
+ gctUINT8 maskBack;
+ gctUINT8 writeMaskFront;
+ gctUINT8 writeMaskBack;
+
+ gctUINT8 referenceFront;
+
+ gceCOMPARE compareFront;
+ gceSTENCIL_OPERATION passFront;
+ gceSTENCIL_OPERATION failFront;
+ gceSTENCIL_OPERATION depthFailFront;
+
+ gctUINT8 referenceBack;
+ gceCOMPARE compareBack;
+ gceSTENCIL_OPERATION passBack;
+ gceSTENCIL_OPERATION failBack;
+ gceSTENCIL_OPERATION depthFailBack;
+}
+gcsSTENCIL_INFO;
+
+/* Set stencil mode. */
+gceSTATUS
+gco3D_SetStencilMode(
+ IN gco3D Engine,
+ IN gceSTENCIL_MODE Mode
+ );
+
+/* Set stencil mask. */
+gceSTATUS
+gco3D_SetStencilMask(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil back mask. */
+gceSTATUS
+gco3D_SetStencilMaskBack(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil write mask. */
+gceSTATUS
+gco3D_SetStencilWriteMask(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil back write mask. */
+gceSTATUS
+gco3D_SetStencilWriteMaskBack(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil reference. */
+gceSTATUS
+gco3D_SetStencilReference(
+ IN gco3D Engine,
+ IN gctUINT8 Reference,
+ IN gctBOOL Front
+ );
+
+/* Set stencil compare. */
+gceSTATUS
+gco3D_SetStencilCompare(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceCOMPARE Compare
+ );
+
+/* Set stencil operation on pass. */
+gceSTATUS
+gco3D_SetStencilPass(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set stencil operation on fail. */
+gceSTATUS
+gco3D_SetStencilFail(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set stencil operation on depth fail. */
+gceSTATUS
+gco3D_SetStencilDepthFail(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set all stencil states in one blow. */
+gceSTATUS
+gco3D_SetStencilAll(
+ IN gco3D Engine,
+ IN gcsSTENCIL_INFO_PTR Info
+ );
+
+typedef struct _gcsALPHA_INFO * gcsALPHA_INFO_PTR;
+typedef struct _gcsALPHA_INFO
+{
+ /* Alpha test states. */
+ gctBOOL test;
+ gceCOMPARE compare;
+ gctUINT8 reference;
+ gctFLOAT floatReference;
+
+ /* Alpha blending states. */
+ gctBOOL blend[gcdMAX_DRAW_BUFFERS];
+
+ gceBLEND_FUNCTION srcFuncColor[gcdMAX_DRAW_BUFFERS];
+ gceBLEND_FUNCTION srcFuncAlpha[gcdMAX_DRAW_BUFFERS];
+ gceBLEND_FUNCTION trgFuncColor[gcdMAX_DRAW_BUFFERS];
+ gceBLEND_FUNCTION trgFuncAlpha[gcdMAX_DRAW_BUFFERS];
+
+ gceBLEND_MODE modeColor[gcdMAX_DRAW_BUFFERS];
+ gceBLEND_MODE modeAlpha[gcdMAX_DRAW_BUFFERS];
+
+ gctUINT32 color;
+
+ gctBOOL anyBlendEnabled;
+}
+gcsALPHA_INFO;
+
+
+/* Enable or disable alpha test. */
+gceSTATUS
+gco3D_SetAlphaTest(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set alpha test compare. */
+gceSTATUS
+gco3D_SetAlphaCompare(
+ IN gco3D Engine,
+ IN gceCOMPARE Compare
+ );
+
+/* Set alpha test reference in unsigned integer. */
+gceSTATUS
+gco3D_SetAlphaReference(
+ IN gco3D Engine,
+ IN gctUINT8 Reference,
+ IN gctFLOAT FloatReference
+ );
+
+/* Set alpha test reference in fixed point. */
+gceSTATUS
+gco3D_SetAlphaReferenceX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Reference
+ );
+
+/* Set alpha test reference in floating point. */
+gceSTATUS
+gco3D_SetAlphaReferenceF(
+ IN gco3D Engine,
+ IN gctFLOAT Reference
+ );
+
+#if gcdALPHA_KILL_IN_SHADER
+gceSTATUS
+gco3D_SetAlphaKill(
+ IN gco3D Engine,
+ IN gctBOOL AlphaKill,
+ IN gctBOOL ColorKill
+ );
+#endif
+
+/* Enable/Disable anti-alias line. */
+gceSTATUS
+gco3D_SetAntiAliasLine(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set texture slot for anti-alias line. */
+gceSTATUS
+gco3D_SetAALineTexSlot(
+ IN gco3D Engine,
+ IN gctUINT TexSlot
+ );
+
+/* Set anti-alias line width scale. */
+gceSTATUS
+gco3D_SetAALineWidth(
+ IN gco3D Engine,
+ IN gctFLOAT Width
+ );
+
+/* Draw a number of primitives. */
+gceSTATUS
+gco3D_DrawPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctSIZE_T StartVertex,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+gceSTATUS
+gco3D_DrawIndirectPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctBOOL DrawIndex,
+ IN gctINT BaseOffset,
+ IN gcoBUFOBJ BufObj
+ );
+
+gceSTATUS
+gco3D_MultiDrawIndirectPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctBOOL DrawIndex,
+ IN gctINT BaseOffset,
+ IN gctINT DrawCount,
+ IN gctINT Stride,
+ IN gcoBUFOBJ BufObj
+ );
+
+gceSTATUS
+gco3D_DrawInstancedPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctBOOL DrawIndex,
+ IN gctINT StartVertex,
+ IN gctSIZE_T StartIndex,
+ IN gctSIZE_T PrimitiveCount,
+ IN gctSIZE_T VertexCount,
+ IN gctSIZE_T InstanceCount
+ );
+
+gceSTATUS
+gco3D_DrawNullPrimitives(
+ IN gco3D Engine
+ );
+
+gceSTATUS
+gco3D_DrawPrimitivesCount(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT* StartVertex,
+ IN gctSIZE_T* VertexCount,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+
+/* Draw a number of primitives using offsets. */
+gceSTATUS
+gco3D_DrawPrimitivesOffset(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT32 StartOffset,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of indexed primitives. */
+gceSTATUS
+gco3D_DrawIndexedPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctSIZE_T BaseVertex,
+ IN gctSIZE_T StartIndex,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of indexed primitives using offsets. */
+gceSTATUS
+gco3D_DrawIndexedPrimitivesOffset(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT32 BaseOffset,
+ IN gctINT32 StartOffset,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a element from pattern */
+gceSTATUS
+gco3D_DrawPattern(
+ IN gco3D Engine,
+ IN gcsFAST_FLUSH_PTR FastFlushInfo
+ );
+
+/* Enable or disable anti-aliasing. */
+gceSTATUS
+gco3D_SetAntiAlias(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set msaa samples */
+gceSTATUS
+gco3D_SetSamples(
+ IN gco3D Engine,
+ IN gctUINT32 Samples
+ );
+
+
+/* Write data into the command buffer. */
+gceSTATUS
+gco3D_WriteBuffer(
+ IN gco3D Engine,
+ IN gctCONST_POINTER Data,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Aligned
+ );
+
+/* Send sempahore and stall until sempahore is signalled. */
+gceSTATUS
+gco3D_Semaphore(
+ IN gco3D Engine,
+ IN gceWHERE From,
+ IN gceWHERE To,
+ IN gceHOW How);
+
+
+/* Explicitly flush shader L1 cache */
+gceSTATUS
+gco3D_FlushSHL1Cache(
+ IN gco3D Engine
+ );
+
+/* Set the subpixels center. */
+gceSTATUS
+gco3D_SetCentroids(
+ IN gco3D Engine,
+ IN gctUINT32 Index,
+ IN gctPOINTER Centroids
+ );
+
+/* query msaa sample coordinates */
+gceSTATUS
+gco3D_GetSampleCoords(
+ IN gco3D Engine,
+ IN gctUINT32 SampleIndex,
+ IN gctBOOL yInverted,
+ OUT gctFLOAT_PTR Coords
+ );
+
+gceSTATUS
+gco3D_SetLogicOp(
+ IN gco3D Engine,
+ IN gctUINT8 Rop
+ );
+
+typedef enum _gceXfbCmd
+{
+ gcvXFBCMD_BEGIN = 0,
+ gcvXFBCMD_PAUSE = 1,
+ gcvXFBCMD_RESUME = 2,
+ gcvXFBCMD_END = 3,
+ gcvXFBCMD_PAUSE_INCOMMIT = 4,
+ gcvXFBCMD_RESUME_INCOMMIT = 5,
+ gcvXFBCMD_INVALID = 6,
+}
+gceXfbCmd;
+
+typedef enum _gceXfbStatus
+{
+ gcvXFB_Disabled = 0,
+ gcvXFB_Paused,
+ gcvXFB_Enabled,
+}
+gceXfbStatus;
+
+typedef enum _gceQueryStatus
+{
+ gcvQUERY_Disabled = 0,
+ gcvQUERY_Paused = 1,
+ gcvQUERY_Enabled = 2,
+}
+gceQueryStatus;
+
+typedef enum _gceQueryCmd
+{
+ gcvQUERYCMD_BEGIN = 0,
+ gcvQUERYCMD_PAUSE = 1,
+ gcvQUERYCMD_RESUME = 2,
+ gcvQUERYCMD_END = 3,
+ gcvQUERYCMD_INVALID = 4,
+}
+gceQueryCmd;
+
+typedef enum _gceQueryType
+{
+ gcvQUERY_OCCLUSION = 0,
+ gcvQUERY_XFB_WRITTEN = 1,
+ gcvQUERY_PRIM_GENERATED = 2,
+ gcvQUERY_MAX_NUM = 3,
+}
+gceQueryType;
+
+gceSTATUS
+gco3D_SetQuery(
+ IN gco3D Engine,
+ IN gctUINT32 QueryHeader,
+ IN gceQueryType Type,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco3D_GetQuery(
+ IN gco3D Engine,
+ IN gceQueryType Type,
+ IN gcsSURF_NODE_PTR Node,
+ IN gctUINT32 Size,
+ IN gctPOINTER Locked,
+ OUT gctINT32 * Index
+ );
+
+gceSTATUS
+gco3D_SetXfbHeader(
+ IN gco3D Engine,
+ IN gctUINT32 Physical
+ );
+
+gceSTATUS
+gco3D_SetXfbBuffer(
+ IN gco3D Engine,
+ IN gctUINT32 Index,
+ IN gctUINT32 BufferAddr,
+ IN gctUINT32 BufferStride,
+ IN gctUINT32 BufferSize
+ );
+
+gceSTATUS
+gco3D_SetXfbCmd(
+ IN gco3D Engine,
+ IN gceXfbCmd Cmd
+ );
+
+gceSTATUS
+gco3D_SetRasterDiscard(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco3D_SetColorOutCount(
+ IN gco3D Engine,
+ IN gctUINT32 ColorOutCount
+ );
+
+gceSTATUS
+gco3D_SetColorCacheMode(
+ IN gco3D Engine
+ );
+
+gceSTATUS
+gco3D_Set3DEngine(
+ IN gco3D Engine
+ );
+
+gceSTATUS
+gco3D_UnSet3DEngine(
+ IN gco3D Engine
+ );
+
+gceSTATUS
+gco3D_Get3DEngine(
+ OUT gco3D * Engine
+ );
+
+gceSTATUS
+gco3D_QueryReset(
+ IN gco3D Engine,
+ OUT gctBOOL_PTR Innocent
+ );
+
+/* OCL thread walker information. */
+typedef struct _gcsTHREAD_WALKER_INFO * gcsTHREAD_WALKER_INFO_PTR;
+typedef struct _gcsTHREAD_WALKER_INFO
+{
+ gctUINT32 dimensions;
+ gctUINT32 traverseOrder;
+ gctUINT32 enableSwathX;
+ gctUINT32 enableSwathY;
+ gctUINT32 enableSwathZ;
+ gctUINT32 swathSizeX;
+ gctUINT32 swathSizeY;
+ gctUINT32 swathSizeZ;
+ gctUINT32 valueOrder;
+
+ gctUINT32 globalSizeX;
+ gctUINT32 globalOffsetX;
+ gctUINT32 globalSizeY;
+ gctUINT32 globalOffsetY;
+ gctUINT32 globalSizeZ;
+ gctUINT32 globalOffsetZ;
+
+ gctUINT32 globalScaleX;
+ gctUINT32 globalScaleY;
+ gctUINT32 globalScaleZ;
+
+ gctUINT32 workGroupSizeX;
+ gctUINT32 workGroupCountX;
+ gctUINT32 workGroupSizeY;
+ gctUINT32 workGroupCountY;
+ gctUINT32 workGroupSizeZ;
+ gctUINT32 workGroupCountZ;
+
+ gctUINT32 threadAllocation;
+ gctBOOL barrierUsed;
+
+ gctBOOL indirect;
+ gctUINT32 groupNumberUniformIdx;
+ gctUINT32 baseAddress;
+}
+gcsTHREAD_WALKER_INFO;
+
+#if gcdENABLE_3D && gcdUSE_VX
+/* VX thread walker parameters. */
+typedef struct _gcsVX_THREAD_WALKER_PARAMETERS * gcsVX_THREAD_WALKER_PARAMETERS_PTR;
+
+typedef struct _gcsVX_THREAD_WALKER_PARAMETERS
+{
+ gctUINT32 valueOrder;
+ gctUINT32 workDim;
+
+ gctUINT32 workGroupSizeX;
+ gctUINT32 workGroupCountX;
+
+ gctUINT32 workGroupSizeY;
+ gctUINT32 workGroupCountY;
+
+ gctUINT32 globalOffsetX;
+ gctUINT32 globalScaleX;
+
+ gctUINT32 globalOffsetY;
+ gctUINT32 globalScaleY;
+}
+gcsVX_THREAD_WALKER_PARAMETERS;
+
+typedef struct _gcsVX_IMAGE_INFO * gcsVX_IMAGE_INFO_PTR;
+
+typedef struct _gcsVX_IMAGE_INFO
+{
+ gctUINT32 format;
+ gctUINT32 rect[4];
+ gctUINT32 width;
+ gctUINT32 height;
+ gctUINT32 bpp;
+ gctUINT32 planes;
+ gctUINT32 componentCount;
+ gctBOOL isFloat;
+
+ gctUINT32 uPixels;
+ gctUINT32 vPixels;
+ gceSURF_FORMAT internalFormat;
+ gctUINT32 border;
+
+ /*vx_imagepatch_addressing_t == (gctUINT32 * 8) */
+ gctUINT32 imagepatch[8 * 3];
+ void *base_addr[3];
+
+ gctUINT32 stride[3];
+
+ gctPOINTER logicals[3];
+ gctUINT32 physicals[3];
+ gctUINT32 bytes;
+
+ gcsSURF_NODE_PTR nodes[3];
+
+#if gcdVX_OPTIMIZER
+ gctUINT32 uniformData[3][4];
+#endif
+}
+gcsVX_IMAGE_INFO;
+typedef struct _gcsVX_DISTRIBUTION_INFO * gcsVX_DISTRIBUTION_INFO_PTR;
+
+typedef struct _gcsVX_DISTRIBUTION_INFO
+{
+
+ gctUINT32 logical;
+ gctUINT32 physical;
+ gctUINT32 bytes;
+
+ gcsSURF_NODE_PTR node;
+}
+gcsVX_DISTRIBUTION_INFO;
+#endif
+
+/* Start OCL thread walker. */
+gceSTATUS
+gco3D_InvokeThreadWalker(
+ IN gco3D Engine,
+ IN gcsTHREAD_WALKER_INFO_PTR Info
+ );
+
+gceSTATUS
+gco3D_GetClosestRenderFormat(
+ IN gco3D Engine,
+ IN gceSURF_FORMAT InFormat,
+ OUT gceSURF_FORMAT* OutFormat
+ );
+
+/* Set w clip and w plane limit value. */
+gceSTATUS
+gco3D_SetWClipEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco3D_GetWClipEnable(
+ IN gco3D Engine,
+ OUT gctBOOL * Enable
+ );
+
+gceSTATUS
+gco3D_SetWPlaneLimitF(
+ IN gco3D Engine,
+ IN gctFLOAT Value
+ );
+
+gceSTATUS
+gco3D_SetWPlaneLimitX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Value
+ );
+
+gceSTATUS
+gco3D_SetWPlaneLimit(
+ IN gco3D Engine,
+ IN gctFLOAT Value
+ );
+
+gceSTATUS
+gco3D_PrimitiveRestart(
+ IN gco3D Engine,
+ IN gctBOOL PrimitiveRestart
+ );
+
+gceSTATUS
+gco3D_LoadProgram(
+ IN gco3D Engine,
+ IN gcePROGRAM_STAGE_BIT StageBits,
+ IN gctPOINTER ProgramState
+ );
+
+gceSTATUS
+gco3D_EnableAlphaToCoverage(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco3D_EnableSampleCoverage(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco3D_SetSampleCoverageValue(
+ IN gco3D Engine,
+ IN gctFLOAT CoverageValue,
+ IN gctBOOL Invert
+ );
+
+gceSTATUS
+gco3D_EnableSampleMask(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco3D_SetSampleMask(
+ IN gco3D Engine,
+ IN gctUINT32 SampleMask
+ );
+
+gceSTATUS
+gco3D_EnableSampleShading(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco3D_SetMinSampleShadingValue(
+ IN gco3D Engine,
+ IN gctFLOAT MinSampleShadingValue
+ );
+
+gceSTATUS
+gco3D_SetSampleShading(
+ IN gco3D Engine,
+ IN gctBOOL Enable,
+ IN gctBOOL IsSampleIn,
+ IN gctFLOAT SampleShadingValue
+ );
+
+gceSTATUS
+gco3D_EnableSampleMaskOut(
+ IN gco3D Engine,
+ IN gctBOOL Enable,
+ IN gctINT SampleMaskLoc
+ );
+
+/*----------------------------------------------------------------------------*/
+/*-------------------------- gco3D Fragment Processor ------------------------*/
+
+/* Set the fragment processor configuration. */
+gceSTATUS
+gco3D_SetFragmentConfiguration(
+ IN gco3D Engine,
+ IN gctBOOL ColorFromStream,
+ IN gctBOOL EnableFog,
+ IN gctBOOL EnableSmoothPoint,
+ IN gctUINT32 ClipPlanes
+ );
+
+/* Enable/disable texture stage operation. */
+gceSTATUS
+gco3D_EnableTextureStage(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL Enable
+ );
+
+/* Program the channel enable masks for the color texture function. */
+gceSTATUS
+gco3D_SetTextureColorMask(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL ColorEnabled,
+ IN gctBOOL AlphaEnabled
+ );
+
+/* Program the channel enable masks for the alpha texture function. */
+gceSTATUS
+gco3D_SetTextureAlphaMask(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL ColorEnabled,
+ IN gctBOOL AlphaEnabled
+ );
+
+/* Program the constant fragment color. */
+gceSTATUS
+gco3D_SetFragmentColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetFragmentColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Program the constant fog color. */
+gceSTATUS
+gco3D_SetFogColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetFogColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Program the constant texture color. */
+gceSTATUS
+gco3D_SetTetxureColorX(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetTetxureColorF(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Configure color texture function. */
+gceSTATUS
+gco3D_SetColorTextureFunction(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gceTEXTURE_FUNCTION Function,
+ IN gceTEXTURE_SOURCE Source0,
+ IN gceTEXTURE_CHANNEL Channel0,
+ IN gceTEXTURE_SOURCE Source1,
+ IN gceTEXTURE_CHANNEL Channel1,
+ IN gceTEXTURE_SOURCE Source2,
+ IN gceTEXTURE_CHANNEL Channel2,
+ IN gctINT Scale
+ );
+
+/* Configure alpha texture function. */
+gceSTATUS
+gco3D_SetAlphaTextureFunction(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gceTEXTURE_FUNCTION Function,
+ IN gceTEXTURE_SOURCE Source0,
+ IN gceTEXTURE_CHANNEL Channel0,
+ IN gceTEXTURE_SOURCE Source1,
+ IN gceTEXTURE_CHANNEL Channel1,
+ IN gceTEXTURE_SOURCE Source2,
+ IN gceTEXTURE_CHANNEL Channel2,
+ IN gctINT Scale
+ );
+
+/******************************************************************************\
+******************************* gcoTEXTURE Object *******************************
+\******************************************************************************/
+
+/* Cube faces. */
+typedef enum _gceTEXTURE_FACE
+{
+ gcvFACE_NONE = 0,
+ gcvFACE_POSITIVE_X,
+ gcvFACE_NEGATIVE_X,
+ gcvFACE_POSITIVE_Y,
+ gcvFACE_NEGATIVE_Y,
+ gcvFACE_POSITIVE_Z,
+ gcvFACE_NEGATIVE_Z,
+}
+gceTEXTURE_FACE;
+
+typedef struct _gcsTEXTURE
+{
+ /* Addressing modes. */
+ gceTEXTURE_ADDRESSING s;
+ gceTEXTURE_ADDRESSING t;
+ gceTEXTURE_ADDRESSING r;
+
+ gceTEXTURE_SWIZZLE swizzle[gcvTEXTURE_COMPONENT_NUM];
+
+ /* Border color. */
+ gctUINT8 border[gcvTEXTURE_COMPONENT_NUM];
+
+ /* Filters. */
+ gceTEXTURE_FILTER minFilter;
+ gceTEXTURE_FILTER magFilter;
+ gceTEXTURE_FILTER mipFilter;
+ gctUINT anisoFilter;
+
+ /* Level of detail. */
+ gctFLOAT lodBias;
+ gctFLOAT lodMin;
+ gctFLOAT lodMax;
+
+ /* base/max level */
+ gctINT32 baseLevel;
+ gctINT32 maxLevel;
+
+ /* depth texture comparison */
+ gceTEXTURE_COMPARE_MODE compareMode;
+ gceCOMPARE compareFunc;
+
+ gceTEXTURE_DS_MODE dsMode;
+
+ /* sRGB decode */
+ gceTEXTURE_SRGBDECODE sRGB;
+
+ gcuVALUE borderColor[4];
+}
+gcsTEXTURE, * gcsTEXTURE_PTR;
+
+typedef struct _gcsTEXTURE_BINDTEXTS_ARGS
+{
+ /* must be the first member */
+ gceHAL_ARG_VERSION version;
+
+}
+gcsTEXTURE_BINDTEXTS_ARGS;
+
+/* Construct a new gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Construct(
+ IN gcoHAL Hal,
+ OUT gcoTEXTURE * Texture
+ );
+
+/* Construct a new gcoTEXTURE object with type information. */
+gceSTATUS
+gcoTEXTURE_ConstructEx(
+ IN gcoHAL Hal,
+ IN gceTEXTURE_TYPE Type,
+ OUT gcoTEXTURE * Texture
+ );
+
+
+/* Construct a new sized gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_ConstructSized(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT Faces,
+ IN gctUINT MipMapCount,
+ IN gcePOOL Pool,
+ OUT gcoTEXTURE * Texture
+ );
+
+/* Destroy an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Destroy(
+ IN gcoTEXTURE Texture
+ );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Upload(
+ IN gcoTEXTURE Texture,
+ IN gctINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctSIZE_T Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_COLOR_SPACE SrcColorSpace
+ );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadSub(
+ IN gcoTEXTURE Texture,
+ IN gctINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctSIZE_T X,
+ IN gctSIZE_T Y,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctSIZE_T Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_COLOR_SPACE SrcColorSpace,
+ IN gctUINT32 PhysicalAddress
+ );
+
+
+/* Upload YUV data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadYUV(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctPOINTER Memory[3],
+ IN gctINT Stride[3],
+ IN gceSURF_FORMAT Format
+ );
+
+/* Upload compressed data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadCompressed(
+ IN gcoTEXTURE Texture,
+ IN gctINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Upload compressed sub data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadCompressedSub(
+ IN gcoTEXTURE Texture,
+ IN gctINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctSIZE_T XOffset,
+ IN gctSIZE_T YOffset,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctSIZE_T Size
+ );
+
+/* Get gcoSURF object for a mipmap level. */
+gceSTATUS
+gcoTEXTURE_GetMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ OUT gcoSURF * Surface
+ );
+
+/* Get gcoSURF object for a mipmap level and face offset. */
+gceSTATUS
+gcoTEXTURE_GetMipMapFace(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ OUT gcoSURF * Surface,
+ OUT gctSIZE_T_PTR Offset
+ );
+
+gceSTATUS
+gcoTEXTURE_GetMipMapSlice(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ IN gctUINT Slice,
+ OUT gcoSURF * Surface,
+ OUT gctSIZE_T_PTR Offset
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gctINT InternalFormat,
+ IN gceSURF_FORMAT Format,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctSIZE_T Depth,
+ IN gctUINT Faces,
+ IN gcePOOL Pool,
+ OUT gcoSURF * Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapEx(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gctINT InternalFormat,
+ IN gceSURF_FORMAT Format,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gctSIZE_T Depth,
+ IN gctUINT Faces,
+ IN gcePOOL Pool,
+ IN gctUINT32 Samples,
+ IN gctBOOL Protected,
+ OUT gcoSURF * Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromClient(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromSurface(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_LockMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ OPTIONAL OUT gctUINT32 * Address,
+ OPTIONAL OUT gctPOINTER * Memory
+ );
+
+gceSTATUS
+gcoTEXTURE_SetEndianHint(
+ IN gcoTEXTURE Texture,
+ IN gceENDIAN_HINT EndianHint
+ );
+
+gceSTATUS
+gcoTEXTURE_Disable(
+ IN gcoHAL Hal,
+ IN gctINT Sampler,
+ IN gctBOOL DefaultInteger
+ );
+
+gceSTATUS
+gcoTEXTURE_Flush(
+ IN gcoTEXTURE Texture
+ );
+
+gceSTATUS
+gcoTEXTURE_FlushVS(
+ IN gcoTEXTURE Texture
+ );
+
+gceSTATUS
+gcoTEXTURE_QueryCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MaxDepth,
+ OUT gctBOOL * Cubic,
+ OUT gctBOOL * NonPowerOfTwo,
+ OUT gctUINT * VertexSamplers,
+ OUT gctUINT * PixelSamplers
+ );
+
+gceSTATUS
+gcoTEXTURE_GetClosestFormat(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT InFormat,
+ OUT gceSURF_FORMAT* OutFormat
+ );
+
+gceSTATUS
+gcoTEXTURE_GetClosestFormatEx(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT InFormat,
+ IN gceTEXTURE_TYPE TextureType,
+ OUT gceSURF_FORMAT* OutFormat
+ );
+
+gceSTATUS
+gcoTEXTURE_GetFormatInfo(
+ IN gcoTEXTURE Texture,
+ IN gctINT preferLevel,
+ OUT gcsSURF_FORMAT_INFO_PTR * TxFormatInfo
+ );
+
+gceSTATUS
+gcoTEXTURE_GetTextureFormatName(
+ IN gcsSURF_FORMAT_INFO_PTR TxFormatInfo,
+ OUT gctCONST_STRING * TxName
+ );
+
+gceSTATUS
+gcoTEXTURE_RenderIntoMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level
+ );
+
+gceSTATUS
+gcoTEXTURE_RenderIntoMipMap2(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gctBOOL Sync
+ );
+
+gceSTATUS
+gcoTEXTURE_IsRenderable(
+ IN gcoTEXTURE Texture,
+ IN gctUINT Level
+ );
+
+gceSTATUS
+gcoTEXTURE_IsComplete(
+ IN gcoTEXTURE Texture,
+ IN gcsTEXTURE_PTR Info,
+ IN gctINT BaseLevel,
+ IN gctINT MaxLevel
+ );
+
+gceSTATUS
+gcoTEXTURE_BindTexture(
+ IN gcoTEXTURE Texture,
+ IN gctINT Target,
+ IN gctINT Sampler,
+ IN gcsTEXTURE_PTR Info
+ );
+
+gceSTATUS
+gcoTEXTURE_BindTextureEx(
+ IN gcoTEXTURE Texture,
+ IN gctINT Target,
+ IN gctINT Sampler,
+ IN gcsTEXTURE_PTR Info,
+ IN gctINT textureLayer
+ );
+
+gceSTATUS
+gcoTEXTURE_BindTextureDesc(
+ IN gcoTEXTURE Texture,
+ IN gctINT Sampler,
+ IN gcsTEXTURE_PTR Info,
+ IN gctINT TextureLayer
+ );
+
+gceSTATUS
+gcoTEXTURE_SetDescDirty(
+ IN gcoTEXTURE Texture
+ );
+
+gceSTATUS
+gcoTEXTURE_InitParams(
+ IN gcoHAL Hal,
+ IN gcsTEXTURE_PTR TexParams
+ );
+
+gceSTATUS
+gcoTEXTURE_SetDepthTextureFlag(
+ IN gcoTEXTURE Texture,
+ IN gctBOOL unsized
+ );
+
+gceSTATUS
+gcoTEXTURE_BindTextureTS(
+ IN gcsTEXTURE_BINDTEXTS_ARGS * args
+ );
+
+gceSTATUS
+gcoTEXTURE_GenerateMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctINT BaseLevel,
+ IN gctINT MaxLevel
+ );
+
+/******************************************************************************\
+******************************* gcoSTREAM Object ******************************
+\******************************************************************************/
+
+typedef enum _gceVERTEX_FORMAT
+{
+ gcvVERTEX_BYTE,
+ gcvVERTEX_UNSIGNED_BYTE,
+ gcvVERTEX_SHORT,
+ gcvVERTEX_UNSIGNED_SHORT,
+ gcvVERTEX_INT,
+ gcvVERTEX_UNSIGNED_INT,
+ gcvVERTEX_FIXED,
+ gcvVERTEX_HALF,
+ gcvVERTEX_FLOAT,
+ gcvVERTEX_UNSIGNED_INT_10_10_10_2,
+ gcvVERTEX_INT_10_10_10_2,
+ gcvVERTEX_UNSIGNED_INT_2_10_10_10_REV,
+ gcvVERTEX_INT_2_10_10_10_REV,
+ /* integer format */
+ gcvVERTEX_INT8,
+ gcvVERTEX_INT16,
+ gcvVERTEX_INT32,
+}
+gceVERTEX_FORMAT;
+
+/* What the SW converting scheme to create temp attrib */
+typedef enum _gceATTRIB_SCHEME
+{
+ gcvATTRIB_SCHEME_KEEP = 0,
+ gcvATTRIB_SCHEME_2_10_10_10_REV_TO_FLOAT,
+ gcvATTRIB_SCHEME_BYTE_TO_IVEC4,
+ gcvATTRIB_SCHEME_SHORT_TO_IVEC4,
+ gcvATTRIB_SCHEME_INT_TO_IVEC4,
+ gcvATTRIB_SCHEME_UBYTE_TO_UVEC4,
+ gcvATTRIB_SCHEME_USHORT_TO_UVEC4,
+ gcvATTRIB_SCHEME_UINT_TO_UVEC4,
+} gceATTRIB_SCHEME;
+
+gceSTATUS
+gcoSTREAM_SetSharedLock(
+ IN gcoSTREAM Stream,
+ IN gctPOINTER sharedLock
+ );
+
+gceSTATUS
+gcoSTREAM_Construct(
+ IN gcoHAL Hal,
+ OUT gcoSTREAM * Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Destroy(
+ IN gcoSTREAM Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Upload(
+ IN gcoSTREAM Stream,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Dynamic
+ );
+
+gceSTATUS
+gcoSTREAM_SetStride(
+ IN gcoSTREAM Stream,
+ IN gctUINT32 Stride
+ );
+
+gceSTATUS
+gcoSTREAM_Size(
+ IN gcoSTREAM Stream,
+ OUT gctSIZE_T *Size
+ );
+
+gceSTATUS
+gcoSTREAM_Node(
+ IN gcoSTREAM Stream,
+ OUT gcsSURF_NODE_PTR * Node
+ );
+
+gceSTATUS
+gcoSTREAM_Lock(
+ IN gcoSTREAM Stream,
+ OUT gctPOINTER * Logical,
+ OUT gctUINT32 * Physical
+ );
+
+gceSTATUS
+gcoSTREAM_Unlock(
+ IN gcoSTREAM Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Reserve(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoSTREAM_Flush(
+ IN gcoSTREAM Stream
+ );
+
+/* Dynamic buffer API. */
+gceSTATUS
+gcoSTREAM_SetDynamic(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Bytes,
+ IN gctUINT Buffers
+ );
+
+typedef struct _gcsSTREAM_INFO
+{
+ gctUINT index;
+ gceVERTEX_FORMAT format;
+ gctBOOL normalized;
+ gctUINT components;
+ gctSIZE_T size;
+ gctCONST_POINTER data;
+ gctUINT stride;
+}
+gcsSTREAM_INFO, * gcsSTREAM_INFO_PTR;
+
+gceSTATUS
+gcoSTREAM_UploadDynamic(
+ IN gcoSTREAM Stream,
+ IN gctUINT VertexCount,
+ IN gctUINT InfoCount,
+ IN gcsSTREAM_INFO_PTR Info,
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoSTREAM_CPUCacheOperation(
+ IN gcoSTREAM Stream,
+ IN gceCACHEOPERATION Operation
+ );
+
+gceSTATUS
+gcoSTREAM_CPUCacheOperation_Range(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Length,
+ IN gceCACHEOPERATION Operation
+ );
+
+/******************************************************************************\
+******************************** gcoVERTEX Object ******************************
+\******************************************************************************/
+
+typedef struct _gcsVERTEX_ATTRIBUTES
+{
+ gceVERTEX_FORMAT format;
+ gctBOOL normalized;
+ gctUINT32 components;
+ gctSIZE_T size;
+ gctUINT32 stream;
+ gctUINT32 offset;
+ gctUINT32 stride;
+}
+gcsVERTEX_ATTRIBUTES;
+
+gceSTATUS
+gcoVERTEX_Construct(
+ IN gcoHAL Hal,
+ OUT gcoVERTEX * Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_Destroy(
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_Reset(
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_EnableAttribute(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 Index,
+ IN gceVERTEX_FORMAT Format,
+ IN gctBOOL Normalized,
+ IN gctUINT32 Components,
+ IN gcoSTREAM Stream,
+ IN gctUINT32 Offset,
+ IN gctUINT32 Stride
+ );
+
+gceSTATUS
+gcoVERTEX_DisableAttribute(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 Index
+ );
+
+gceSTATUS
+gcoVERTEX_Bind(
+ IN gcoVERTEX Vertex
+ );
+
+/*******************************************************************************
+***** gcoVERTEXARRAY Object ***************************************************/
+
+typedef struct _gcsATTRIBUTE
+{
+ /* Enabled. */
+ gctBOOL enable;
+
+ /* Number of components. */
+ gctINT size;
+
+ /* Attribute format. */
+ gceVERTEX_FORMAT format;
+
+ /* Flag whether the attribute is normalized or not. */
+ gctBOOL normalized;
+
+ /* Stride of the component. */
+ gctSIZE_T stride;
+
+ /* Divisor of the attribute */
+ gctUINT divisor;
+
+ /* Pointer to the attribute data. */
+ gctCONST_POINTER pointer;
+
+ /* Stream object owning the attribute data. */
+ gcoBUFOBJ stream;
+
+ /* Generic values for attribute. */
+ gctFLOAT genericValue[4];
+
+ /* Generic size for attribute. */
+ gctINT genericSize;
+
+ /* Vertex shader linkage. */
+ gctUINT linkage;
+
+#if gcdUSE_WCLIP_PATCH
+ /* Does it hold positions? */
+ gctBOOL isPosition;
+#endif
+
+ /* Index to vertex array */
+ gctINT arrayIdx;
+
+ gceATTRIB_SCHEME convertScheme;
+
+ /* Pointer to the temporary buffer to be freed */
+ gcoBUFOBJ tempStream;
+
+ /* Pointer to the temporary memory to be freed */
+ gctCONST_POINTER tempMemory;
+}
+gcsATTRIBUTE,
+* gcsATTRIBUTE_PTR;
+
+typedef struct _gcsVERTEXARRAY
+{
+ /* Enabled. */
+ gctBOOL enable;
+
+ /* Number of components. */
+ gctINT size;
+
+ /* Attribute format. */
+ gceVERTEX_FORMAT format;
+
+ /* Flag whether the attribute is normalized or not. */
+ gctBOOL normalized;
+
+ /* Stride of the component. */
+ gctUINT stride;
+
+ /* Divisor of the attribute */
+ gctUINT divisor;
+
+ /* Pointer to the attribute data. */
+ gctCONST_POINTER pointer;
+
+ /* Stream object owning the attribute data. */
+ gcoSTREAM stream;
+
+ /* Generic values for attribute. */
+ gctFLOAT genericValue[4];
+
+ /* Generic size for attribute. */
+ gctINT genericSize;
+
+ /* Vertex shader linkage. */
+ gctUINT linkage;
+
+ gctBOOL isPosition;
+}
+gcsVERTEXARRAY,
+* gcsVERTEXARRAY_PTR;
+
+gceSTATUS
+gcoVERTEXARRAY_Construct(
+ IN gcoHAL Hal,
+ OUT gcoVERTEXARRAY * Vertex
+ );
+
+gceSTATUS
+gcoVERTEXARRAY_Destroy(
+ IN gcoVERTEXARRAY Vertex
+ );
+
+/* If don't consider isolation, STREAM_INFO / INDEX_INFO could be
+** include in the struct of instantDraw in chip level.*/
+typedef struct _gcsVERTEXARRAY_STREAM_INFO
+{
+ gctUINT attribMask;
+ gctSIZE_T first;
+ gctSIZE_T count;
+ gcePRIMITIVE primMode;
+ gctSIZE_T primCount;
+ gctINT vertexInstIndex;
+ gctBOOL instanced;
+ gctSIZE_T instanceCount;
+
+ union _gcsVERTEXARRAY_STREAM_INFO_UNION
+ {
+ struct _gcsVERTEXARRAY_STREAM_ES11_INFO
+ {
+ gcsVERTEXARRAY_PTR attributes;
+ }es11;
+
+ struct _gcsVERTEXARRAY_STREAM_ES30_INFO
+ {
+ gcsATTRIBUTE_PTR attributes;
+ }es30;
+ }u;
+}gcsVERTEXARRAY_STREAM_INFO,
+*gcsVERTEXARRAY_STREAM_INFO_PTR;
+
+typedef const struct _gcsVERTEXARRAY_STREAM_INFO* gcsVERTEXARRAY_STREAM_INFO_CONST_PTR;
+
+typedef struct _gcsVERTEXARRAY_INDEX_INFO
+{
+ gctSIZE_T count;
+ gceINDEX_TYPE indexType;
+ gctPOINTER indexMemory;
+
+ union _gcsVERTEXARRAY_INDEX_INFO_UNION
+ {
+ struct _gcsVERTEXARRAY_INDEX_ES11_INFO
+ {
+ gcoINDEX indexBuffer;
+ }es11;
+
+ struct _gcsVERTEXARRAY_INDEX_ES30_INFO
+ {
+ gcoBUFOBJ indexBuffer;
+ }es30;
+ }u;
+}gcsVERTEXARRAY_INDEX_INFO,
+*gcsVERTEXARRAY_INDEX_INFO_PTR;
+
+typedef const struct _gcsVERTEXARRAY_INDEX_INFO* gcsVERTEXARRAY_INDEX_INFO_CONST_PTR;
+
+gceSTATUS
+gcoVERTEXARRAY_IndexBind(
+ IN gcoVERTEXARRAY Vertex,
+ IN gcsVERTEXARRAY_INDEX_INFO_PTR IndexInfo
+ );
+
+gceSTATUS
+gcoVERTEXARRAY_StreamBind(
+ IN gcoVERTEXARRAY Vertex,
+#if gcdUSE_WCLIP_PATCH
+ IN OUT gctFLOAT * WLimitRms,
+ IN OUT gctBOOL * WLimitRmsDirty,
+#endif
+ IN gcsVERTEXARRAY_STREAM_INFO_CONST_PTR StreamInfo,
+ IN gcsVERTEXARRAY_INDEX_INFO_CONST_PTR IndexInfo
+ );
+
+gceSTATUS
+gcoVERTEXARRAY_IndexBind_Ex(
+ IN gcoVERTEXARRAY Vertex,
+ IN OUT gcsVERTEXARRAY_STREAM_INFO_PTR StreamInfo,
+ IN gcsVERTEXARRAY_INDEX_INFO_PTR IndexInfo
+ );
+
+gceSTATUS
+gcoVERTEXARRAY_StreamBind_Ex(
+ IN gcoVERTEXARRAY Vertex,
+#if gcdUSE_WCLIP_PATCH
+ IN OUT gctFLOAT * WLimitRms,
+ IN OUT gctBOOL * WLimitRmsDirty,
+#endif
+ IN OUT gcsVERTEXARRAY_STREAM_INFO_PTR StreamInfo,
+ IN gcsVERTEXARRAY_INDEX_INFO_PTR IndexInfo
+ );
+
+gceSTATUS
+gcoVERTEXARRAY_Bind(
+ IN gcoVERTEXARRAY Vertex,
+ IN gctUINT32 EnableBits,
+ IN gcsVERTEXARRAY_PTR VertexArray,
+ IN gctUINT First,
+ IN gctSIZE_T * Count,
+ IN gceINDEX_TYPE IndexType,
+ IN gcoINDEX IndexObject,
+ IN gctPOINTER IndexMemory,
+ IN OUT gcePRIMITIVE * PrimitiveType,
+#if gcdUSE_WCLIP_PATCH
+ IN OUT gctUINT * PrimitiveCount,
+ IN OUT gctFLOAT * wLimitRms,
+ IN OUT gctBOOL * wLimitDirty
+#else
+ IN OUT gctUINT * PrimitiveCount
+#endif
+ );
+
+/*******************************************************************************
+***** Composition *************************************************************/
+
+typedef enum _gceCOMPOSITION
+{
+ gcvCOMPOSE_CLEAR = 1,
+ gcvCOMPOSE_BLUR,
+ gcvCOMPOSE_DIM,
+ gcvCOMPOSE_LAYER
+}
+gceCOMPOSITION;
+
+typedef struct _gcsCOMPOSITION * gcsCOMPOSITION_PTR;
+typedef struct _gcsCOMPOSITION
+{
+ /* Structure size. */
+ gctUINT structSize;
+
+ /* Composition operation. */
+ gceCOMPOSITION operation;
+
+ /* Layer to be composed. */
+ gcoSURF layer;
+
+ /* Source and target coordinates. */
+ gcsRECT srcRect;
+ gcsRECT trgRect;
+
+ /* Target rectangle */
+ gcsPOINT v0;
+ gcsPOINT v1;
+ gcsPOINT v2;
+
+ /* Blending parameters. */
+ gctBOOL enableBlending;
+ gctBOOL premultiplied;
+ gctUINT8 alphaValue;
+
+ /* Clear color. */
+ gctFLOAT r;
+ gctFLOAT g;
+ gctFLOAT b;
+ gctFLOAT a;
+}
+gcsCOMPOSITION;
+
+gceSTATUS
+gco3D_ProbeComposition(
+ IN gcoHARDWARE Hardware,
+ IN gctBOOL ResetIfEmpty
+ );
+
+gceSTATUS
+gco3D_CompositionBegin(
+ IN gcoHARDWARE Hardware
+ );
+
+gceSTATUS
+gco3D_ComposeLayer(
+ IN gcoHARDWARE Hardware,
+ IN gcsCOMPOSITION_PTR Layer
+ );
+
+gceSTATUS
+gco3D_CompositionSignals(
+ IN gcoHARDWARE Hardware,
+ IN gctHANDLE Process,
+ IN gctSIGNAL Signal1,
+ IN gctSIGNAL Signal2
+ );
+
+gceSTATUS
+gco3D_CompositionEnd(
+ IN gcoHARDWARE Hardware,
+ IN gcoSURF Target,
+ IN gctBOOL Synchronous
+ );
+
+/* Frame Database */
+gceSTATUS
+gcoHAL_AddFrameDB(
+ void
+ );
+
+gceSTATUS
+gcoHAL_DumpFrameDB(
+ gctCONST_STRING Filename OPTIONAL
+ );
+
+gceSTATUS
+gcoHAL_InitGPUProfile(
+ void
+ );
+
+gceSTATUS
+gcoHAL_DumpGPUProfile(
+ void
+ );
+
+/******************************************************************************
+**********************gcoBUFOBJ object*****************************************
+*******************************************************************************/
+typedef enum _gceBUFOBJ_TYPE
+{
+ gcvBUFOBJ_TYPE_ARRAY_BUFFER = 1,
+ gcvBUFOBJ_TYPE_ELEMENT_ARRAY_BUFFER = 2,
+ gcvBUFOBJ_TYPE_GENERIC_BUFFER = 100
+
+} gceBUFOBJ_TYPE;
+
+typedef enum _gceBUFOBJ_USAGE
+{
+ gcvBUFOBJ_USAGE_STREAM_DRAW = 1,
+ gcvBUFOBJ_USAGE_STREAM_READ,
+ gcvBUFOBJ_USAGE_STREAM_COPY,
+ gcvBUFOBJ_USAGE_STATIC_DRAW,
+ gcvBUFOBJ_USAGE_STATIC_READ,
+ gcvBUFOBJ_USAGE_STATIC_COPY,
+ gcvBUFOBJ_USAGE_DYNAMIC_DRAW,
+ gcvBUFOBJ_USAGE_DYNAMIC_READ,
+ gcvBUFOBJ_USAGE_DYNAMIC_COPY,
+
+ /* special patch for optimaize performance,
+ ** no fence and duplicate stream to ensure data correct
+ */
+ gcvBUFOBJ_USAGE_DISABLE_FENCE_DYNAMIC_STREAM = 256
+} gceBUFOBJ_USAGE;
+
+/* Construct a new gcoBUFOBJ object. */
+gceSTATUS
+gcoBUFOBJ_Construct(
+ IN gcoHAL Hal,
+ IN gceBUFOBJ_TYPE Type,
+ OUT gcoBUFOBJ * BufObj
+ );
+
+/* Destroy a gcoBUFOBJ object. */
+gceSTATUS
+gcoBUFOBJ_Destroy(
+ IN gcoBUFOBJ BufObj
+ );
+
+/* Lock pbo in memory. */
+gceSTATUS
+gcoBUFOBJ_Lock(
+ IN gcoBUFOBJ BufObj,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+/* Lock pbo in memory. */
+gceSTATUS
+gcoBUFOBJ_FastLock(
+ IN gcoBUFOBJ BufObj,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+/* Unlock pbo that was previously locked with gcoBUFOBJ_Lock. */
+gceSTATUS
+gcoBUFOBJ_Unlock(
+ IN gcoBUFOBJ BufObj
+ );
+
+/* Free existing pbo buffer. */
+gceSTATUS
+gcoBUFOBJ_Free(
+ IN gcoBUFOBJ BufObj
+ );
+
+/* Upload data into an pbo buffer. */
+gceSTATUS
+gcoBUFOBJ_Upload(
+ IN gcoBUFOBJ BufObj,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Bytes,
+ IN gceBUFOBJ_USAGE Usage
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoBUFOBJ_IndexBind (
+ IN gcoBUFOBJ Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Count
+ );
+
+/* Find min and max index for the index buffer */
+gceSTATUS
+gcoBUFOBJ_IndexGetRange(
+ IN gcoBUFOBJ Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset,
+ IN gctUINT32 Count,
+ OUT gctUINT32 * MinimumIndex,
+ OUT gctUINT32 * MaximumIndex
+ );
+
+/* Sets a buffer object as dirty */
+gceSTATUS
+gcoBUFOBJ_SetDirty(
+ IN gcoBUFOBJ BufObj
+ );
+
+/* Creates a new buffer if needed */
+gceSTATUS
+gcoBUFOBJ_AlignIndexBufferWhenNeeded(
+ IN gcoBUFOBJ BufObj,
+ IN gctSIZE_T Offset,
+ OUT gcoBUFOBJ * AlignedBufObj
+ );
+
+/* Cache operations on whole range */
+gceSTATUS
+gcoBUFOBJ_CPUCacheOperation(
+ IN gcoBUFOBJ BufObj,
+ IN gceCACHEOPERATION Operation
+ );
+
+/* Cache operations on a specified range */
+gceSTATUS
+gcoBUFOBJ_CPUCacheOperation_Range(
+ IN gcoBUFOBJ BufObj,
+ IN gctSIZE_T Offset,
+ IN gctSIZE_T Length,
+ IN gceCACHEOPERATION Operation
+ );
+
+/* Return size of the bufobj */
+gceSTATUS
+gcoBUFOBJ_GetSize(
+ IN gcoBUFOBJ BufObj,
+ OUT gctSIZE_T_PTR Size
+ );
+
+/* Return memory node of the bufobj */
+gceSTATUS
+gcoBUFOBJ_GetNode(
+ IN gcoBUFOBJ BufObj,
+ OUT gcsSURF_NODE_PTR * Node
+ );
+
+/* Handle GPU cache operations */
+gceSTATUS
+gcoBUFOBJ_GPUCacheOperation(
+ gcoBUFOBJ BufObj
+ );
+
+/* Dump buffer. */
+void
+gcoBUFOBJ_Dump(
+ IN gcoBUFOBJ BufObj
+ );
+
+#endif /* gcdENABLE_3D */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_engine_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h
new file mode 100644
index 000000000000..9e3dc6c07d43
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine_vg.h
@@ -0,0 +1,1318 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_engine_vg_h_
+#define __gc_hal_engine_vg_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gc_hal_types.h"
+
+/******************************************************************************\
+******************************** VG Enumerations *******************************
+\******************************************************************************/
+
+/**
+** @ingroup gcoVG
+**
+** @brief Tiling mode for painting and imagig.
+**
+** This enumeration defines the tiling modes supported by the HAL. This is
+** in fact a one-to-one mapping of the OpenVG 1.1 tile modes.
+*/
+typedef enum _gceTILE_MODE
+{
+ gcvTILE_FILL,
+ gcvTILE_PAD,
+ gcvTILE_REPEAT,
+ gcvTILE_REFLECT
+}
+gceTILE_MODE;
+
+/******************************************************************************/
+/** @ingroup gcoVG
+**
+** @brief The different paint modes.
+**
+** This enumeration lists the available paint modes.
+*/
+typedef enum _gcePAINT_TYPE
+{
+ /** Solid color. */
+ gcvPAINT_MODE_SOLID,
+
+ /** Linear gradient. */
+ gcvPAINT_MODE_LINEAR,
+
+ /** Radial gradient. */
+ gcvPAINT_MODE_RADIAL,
+
+ /** Pattern. */
+ gcvPAINT_MODE_PATTERN,
+
+ /** Mode count. */
+ gcvPAINT_MODE_COUNT
+}
+gcePAINT_TYPE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Types of path data supported by HAL.
+**
+** This enumeration defines the types of path data supported by the HAL.
+** This is in fact a one-to-one mapping of the OpenVG 1.1 path types.
+*/
+typedef enum _gcePATHTYPE
+{
+ gcePATHTYPE_UNKNOWN = -1,
+ gcePATHTYPE_INT8,
+ gcePATHTYPE_INT16,
+ gcePATHTYPE_INT32,
+ gcePATHTYPE_FLOAT
+}
+gcePATHTYPE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Supported path segment commands.
+**
+** This enumeration defines the path segment commands supported by the HAL.
+*/
+typedef enum _gceVGCMD
+{
+ gcvVGCMD_END, /* 0: GCCMD_TS_OPCODE_END */
+ gcvVGCMD_CLOSE, /* 1: GCCMD_TS_OPCODE_CLOSE */
+ gcvVGCMD_MOVE, /* 2: GCCMD_TS_OPCODE_MOVE */
+ gcvVGCMD_MOVE_REL, /* 3: GCCMD_TS_OPCODE_MOVE_REL */
+ gcvVGCMD_LINE, /* 4: GCCMD_TS_OPCODE_LINE */
+ gcvVGCMD_LINE_REL, /* 5: GCCMD_TS_OPCODE_LINE_REL */
+ gcvVGCMD_QUAD, /* 6: GCCMD_TS_OPCODE_QUADRATIC */
+ gcvVGCMD_QUAD_REL, /* 7: GCCMD_TS_OPCODE_QUADRATIC_REL */
+ gcvVGCMD_CUBIC, /* 8: GCCMD_TS_OPCODE_CUBIC */
+ gcvVGCMD_CUBIC_REL, /* 9: GCCMD_TS_OPCODE_CUBIC_REL */
+ gcvVGCMD_BREAK, /* 10: GCCMD_TS_OPCODE_BREAK */
+ gcvVGCMD_HLINE, /* 11: ******* R E S E R V E D *******/
+ gcvVGCMD_HLINE_REL, /* 12: ******* R E S E R V E D *******/
+ gcvVGCMD_VLINE, /* 13: ******* R E S E R V E D *******/
+ gcvVGCMD_VLINE_REL, /* 14: ******* R E S E R V E D *******/
+ gcvVGCMD_SQUAD, /* 15: ******* R E S E R V E D *******/
+ gcvVGCMD_SQUAD_REL, /* 16: ******* R E S E R V E D *******/
+ gcvVGCMD_SCUBIC, /* 17: ******* R E S E R V E D *******/
+ gcvVGCMD_SCUBIC_REL, /* 18: ******* R E S E R V E D *******/
+ gcvVGCMD_SCCWARC, /* 19: ******* R E S E R V E D *******/
+ gcvVGCMD_SCCWARC_REL, /* 20: ******* R E S E R V E D *******/
+ gcvVGCMD_SCWARC, /* 21: ******* R E S E R V E D *******/
+ gcvVGCMD_SCWARC_REL, /* 22: ******* R E S E R V E D *******/
+ gcvVGCMD_LCCWARC, /* 23: ******* R E S E R V E D *******/
+ gcvVGCMD_LCCWARC_REL, /* 24: ******* R E S E R V E D *******/
+ gcvVGCMD_LCWARC, /* 25: ******* R E S E R V E D *******/
+ gcvVGCMD_LCWARC_REL, /* 26: ******* R E S E R V E D *******/
+
+ /* The width of the command recognized by the hardware on bits. */
+ gcvVGCMD_WIDTH = 5,
+
+ /* Hardware command mask. */
+ gcvVGCMD_MASK = (1 << gcvVGCMD_WIDTH) - 1,
+
+ /* Command modifiers. */
+ gcvVGCMD_H_MOD = 1 << gcvVGCMD_WIDTH, /* = 32 */
+ gcvVGCMD_V_MOD = 2 << gcvVGCMD_WIDTH, /* = 64 */
+ gcvVGCMD_S_MOD = 3 << gcvVGCMD_WIDTH, /* = 96 */
+ gcvVGCMD_ARC_MOD = 4 << gcvVGCMD_WIDTH, /* = 128 */
+
+ /* Emulated LINE commands. */
+ gcvVGCMD_HLINE_EMUL = gcvVGCMD_H_MOD | gcvVGCMD_LINE, /* = 36 */
+ gcvVGCMD_HLINE_EMUL_REL = gcvVGCMD_H_MOD | gcvVGCMD_LINE_REL, /* = 37 */
+ gcvVGCMD_VLINE_EMUL = gcvVGCMD_V_MOD | gcvVGCMD_LINE, /* = 68 */
+ gcvVGCMD_VLINE_EMUL_REL = gcvVGCMD_V_MOD | gcvVGCMD_LINE_REL, /* = 69 */
+
+ /* Emulated SMOOTH commands. */
+ gcvVGCMD_SQUAD_EMUL = gcvVGCMD_S_MOD | gcvVGCMD_QUAD, /* = 102 */
+ gcvVGCMD_SQUAD_EMUL_REL = gcvVGCMD_S_MOD | gcvVGCMD_QUAD_REL, /* = 103 */
+ gcvVGCMD_SCUBIC_EMUL = gcvVGCMD_S_MOD | gcvVGCMD_CUBIC, /* = 104 */
+ gcvVGCMD_SCUBIC_EMUL_REL = gcvVGCMD_S_MOD | gcvVGCMD_CUBIC_REL, /* = 105 */
+
+ /* Emulation ARC commands. */
+ gcvVGCMD_ARC_LINE = gcvVGCMD_ARC_MOD | gcvVGCMD_LINE, /* = 132 */
+ gcvVGCMD_ARC_LINE_REL = gcvVGCMD_ARC_MOD | gcvVGCMD_LINE_REL, /* = 133 */
+ gcvVGCMD_ARC_QUAD = gcvVGCMD_ARC_MOD | gcvVGCMD_QUAD, /* = 134 */
+ gcvVGCMD_ARC_QUAD_REL = gcvVGCMD_ARC_MOD | gcvVGCMD_QUAD_REL /* = 135 */
+}
+gceVGCMD;
+typedef enum _gceVGCMD * gceVGCMD_PTR;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Blending modes supported by the HAL.
+**
+** This enumeration defines the blending modes supported by the HAL. This is
+** in fact a one-to-one mapping of the OpenVG 1.1 blending modes.
+*/
+typedef enum _gceVG_BLEND
+{
+ gcvVG_BLEND_SRC,
+ gcvVG_BLEND_SRC_OVER,
+ gcvVG_BLEND_DST_OVER,
+ gcvVG_BLEND_SRC_IN,
+ gcvVG_BLEND_DST_IN,
+ gcvVG_BLEND_MULTIPLY,
+ gcvVG_BLEND_SCREEN,
+ gcvVG_BLEND_DARKEN,
+ gcvVG_BLEND_LIGHTEN,
+ gcvVG_BLEND_ADDITIVE,
+ gcvVG_BLEND_SUBTRACT,
+ gcvVG_BLEND_FILTER
+}
+gceVG_BLEND;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Image modes supported by the HAL.
+**
+** This enumeration defines the image modes supported by the HAL. This is
+** in fact a one-to-one mapping of the OpenVG 1.1 image modes with the addition
+** of NO IMAGE.
+*/
+typedef enum _gceVG_IMAGE
+{
+ gcvVG_IMAGE_NONE,
+ gcvVG_IMAGE_NORMAL,
+ gcvVG_IMAGE_MULTIPLY,
+ gcvVG_IMAGE_STENCIL,
+ gcvVG_IMAGE_FILTER
+}
+gceVG_IMAGE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Filter mode patterns and imaging.
+**
+** This enumeration defines the filter modes supported by the HAL.
+*/
+typedef enum _gceIMAGE_FILTER
+{
+ gcvFILTER_POINT,
+ gcvFILTER_LINEAR,
+ gcvFILTER_BI_LINEAR
+}
+gceIMAGE_FILTER;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Primitive modes supported by the HAL.
+**
+** This enumeration defines the primitive modes supported by the HAL.
+*/
+typedef enum _gceVG_PRIMITIVE
+{
+ gcvVG_SCANLINE,
+ gcvVG_RECTANGLE,
+ gcvVG_TESSELLATED,
+ gcvVG_TESSELLATED_TILED
+}
+gceVG_PRIMITIVE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Rendering quality modes supported by the HAL.
+**
+** This enumeration defines the rendering quality modes supported by the HAL.
+*/
+typedef enum _gceRENDER_QUALITY
+{
+ gcvVG_NONANTIALIASED,
+ gcvVG_2X2_MSAA,
+ gcvVG_2X4_MSAA,
+ gcvVG_4X4_MSAA
+}
+gceRENDER_QUALITY;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Fill rules supported by the HAL.
+**
+** This enumeration defines the fill rules supported by the HAL.
+*/
+typedef enum _gceFILL_RULE
+{
+ gcvVG_EVEN_ODD,
+ gcvVG_NON_ZERO
+}
+gceFILL_RULE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Cap styles supported by the HAL.
+**
+** This enumeration defines the cap styles supported by the HAL.
+*/
+typedef enum _gceCAP_STYLE
+{
+ gcvCAP_BUTT,
+ gcvCAP_ROUND,
+ gcvCAP_SQUARE
+}
+gceCAP_STYLE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Join styles supported by the HAL.
+**
+** This enumeration defines the join styles supported by the HAL.
+*/
+typedef enum _gceJOIN_STYLE
+{
+ gcvJOIN_MITER,
+ gcvJOIN_ROUND,
+ gcvJOIN_BEVEL
+}
+gceJOIN_STYLE;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Channel mask values.
+**
+** This enumeration defines the values for channel mask used in image
+** filtering.
+*/
+
+/* Base values for channel mask definitions. */
+#define gcvCHANNEL_X (0)
+#define gcvCHANNEL_R (1 << 0)
+#define gcvCHANNEL_G (1 << 1)
+#define gcvCHANNEL_B (1 << 2)
+#define gcvCHANNEL_A (1 << 3)
+
+typedef enum _gceCHANNEL
+{
+ gcvCHANNEL_XXXX = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X),
+ gcvCHANNEL_XXXA = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_A),
+ gcvCHANNEL_XXBX = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_X),
+ gcvCHANNEL_XXBA = (gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_A),
+
+ gcvCHANNEL_XGXX = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_X),
+ gcvCHANNEL_XGXA = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_A),
+ gcvCHANNEL_XGBX = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_X),
+ gcvCHANNEL_XGBA = (gcvCHANNEL_X | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_A),
+
+ gcvCHANNEL_RXXX = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_X),
+ gcvCHANNEL_RXXA = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_X | gcvCHANNEL_A),
+ gcvCHANNEL_RXBX = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_X),
+ gcvCHANNEL_RXBA = (gcvCHANNEL_R | gcvCHANNEL_X | gcvCHANNEL_B | gcvCHANNEL_A),
+
+ gcvCHANNEL_RGXX = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_X),
+ gcvCHANNEL_RGXA = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_X | gcvCHANNEL_A),
+ gcvCHANNEL_RGBX = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_X),
+ gcvCHANNEL_RGBA = (gcvCHANNEL_R | gcvCHANNEL_G | gcvCHANNEL_B | gcvCHANNEL_A),
+}
+gceCHANNEL;
+
+/******************************************************************************\
+******************************** VG Structures *******************************
+\******************************************************************************/
+
+/**
+** @ingroup gcoVG
+**
+** @brief Definition of the color ramp used by the gradient paints.
+**
+** The gcsCOLOR_RAMP structure defines the layout of one single color inside
+** a color ramp which is used by gradient paints.
+*/
+typedef struct _gcsCOLOR_RAMP
+{
+ /** Value for the color stop. */
+ gctFLOAT stop;
+
+ /** Red color channel value for the color stop. */
+ gctFLOAT red;
+
+ /** Green color channel value for the color stop. */
+ gctFLOAT green;
+
+ /** Blue color channel value for the color stop. */
+ gctFLOAT blue;
+
+ /** Alpha color channel value for the color stop. */
+ gctFLOAT alpha;
+}
+gcsCOLOR_RAMP, * gcsCOLOR_RAMP_PTR;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Definition of the color ramp used by the gradient paints in fixed form.
+**
+** The gcsCOLOR_RAMP structure defines the layout of one single color inside
+** a color ramp which is used by gradient paints.
+*/
+typedef struct _gcsFIXED_COLOR_RAMP
+{
+ /** Value for the color stop. */
+ gctFIXED_POINT stop;
+
+ /** Red color channel value for the color stop. */
+ gctFIXED_POINT red;
+
+ /** Green color channel value for the color stop. */
+ gctFIXED_POINT green;
+
+ /** Blue color channel value for the color stop. */
+ gctFIXED_POINT blue;
+
+ /** Alpha color channel value for the color stop. */
+ gctFIXED_POINT alpha;
+}
+gcsFIXED_COLOR_RAMP, * gcsFIXED_COLOR_RAMP_PTR;
+
+
+/**
+** @ingroup gcoVG
+**
+** @brief Rectangle structure used by the gcoVG object.
+**
+** This structure defines the layout of a rectangle. Make sure width and
+** height are larger than 0.
+*/
+typedef struct _gcsVG_RECT * gcsVG_RECT_PTR;
+typedef struct _gcsVG_RECT
+{
+ /** Left location of the rectangle. */
+ gctINT x;
+
+ /** Top location of the rectangle. */
+ gctINT y;
+
+ /** Width of the rectangle. */
+ gctINT width;
+
+ /** Height of the rectangle. */
+ gctINT height;
+}
+gcsVG_RECT;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Path command buffer attribute structure.
+**
+** The gcsPATH_BUFFER_INFO structure contains the specifics about
+** the layout of the path data command buffer.
+*/
+typedef struct _gcsPATH_BUFFER_INFO * gcsPATH_BUFFER_INFO_PTR;
+typedef struct _gcsPATH_BUFFER_INFO
+{
+ gctUINT reservedForHead;
+ gctUINT reservedForTail;
+}
+gcsPATH_BUFFER_INFO;
+
+/**
+** @ingroup gcoVG
+**
+** @brief Definition of the path data container structure.
+**
+** The gcsPATH structure defines the layout of the path data container.
+*/
+typedef struct _gcsPATH_DATA * gcsPATH_DATA_PTR;
+typedef struct _gcsPATH_DATA
+{
+ /* Data container in command buffer format. */
+ gcsCMDBUFFER data;
+
+ /* Path data type. */
+ gcePATHTYPE dataType;
+}
+gcsPATH_DATA;
+
+
+/******************************************************************************\
+********************************* gcoHAL Object ********************************
+\******************************************************************************/
+
+/* Query path data storage attributes. */
+gceSTATUS
+gcoHAL_QueryPathStorage(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ OUT gcsPATH_BUFFER_INFO_PTR Information
+ );
+
+/* Associate a completion signal with the command buffer. */
+gceSTATUS
+gcoHAL_AssociateCompletion(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+/* Release the current command buffer completion signal. */
+gceSTATUS
+gcoHAL_DeassociateCompletion(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+/* Verify whether the command buffer is still in use. */
+gceSTATUS
+gcoHAL_CheckCompletion(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+/* Wait until the command buffer is no longer in use. */
+gceSTATUS
+gcoHAL_WaitCompletion(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+/* Flush the pixel cache. */
+gceSTATUS
+gcoHAL_Flush(
+#if gcdGC355_PROFILER
+ IN gcoHAL Hal,
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth
+#else
+ IN gcoHAL Hal
+#endif
+ );
+
+/* Split a harwdare address into pool and offset. */
+gceSTATUS
+gcoHAL_SplitAddress(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ );
+
+/* Combine pool and offset into a harwdare address. */
+gceSTATUS
+gcoHAL_CombineAddress(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcePOOL Pool,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ );
+
+/* Schedule to free linear video memory allocated. */
+gceSTATUS
+gcoHAL_ScheduleVideoMemory(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT32 Node
+ );
+
+/* Free linear video memory allocated with gcoHAL_AllocateLinearVideoMemory. */
+gceSTATUS
+gcoHAL_FreeVideoMemory(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT32 Node,
+ IN gctBOOL asynchroneous
+ );
+
+/* Query command buffer attributes. */
+gceSTATUS
+gcoHAL_QueryCommandBuffer(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ );
+/* Allocate and lock linear video memory. */
+gceSTATUS
+gcoHAL_AllocateLinearVideoMemory(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT Size,
+ IN gctUINT Alignment,
+ IN gcePOOL Pool,
+ OUT gctUINT32 * Node,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+/* Align the specified size accordingly to the hardware requirements. */
+gceSTATUS
+gcoHAL_GetAlignedSurfaceSize(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Width,
+ IN OUT gctUINT32_PTR Height
+ );
+
+gceSTATUS
+gcoHAL_ReserveTask(
+ IN gcoHAL Hal,
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceBLOCK Block,
+ IN gctUINT TaskCount,
+ IN gctUINT32 Bytes,
+ OUT gctPOINTER * Memory
+ );
+/******************************************************************************\
+********************************** gcoVG Object ********************************
+\******************************************************************************/
+
+/** @defgroup gcoVG gcoVG
+**
+** The gcoVG object abstracts the VG hardware pipe.
+*/
+#if gcdGC355_PROFILER
+void
+gcoVG_ProfilerEnableDisable(
+ IN gcoVG Vg,
+ IN gctUINT enableGetAPITimes,
+ IN gctFILE apiTimeFile
+ );
+
+void
+gcoVG_ProfilerTreeDepth(
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth
+ );
+
+void
+gcoVG_ProfilerSetStates(
+ IN gcoVG Vg,
+ IN gctUINT treeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth
+ );
+#endif
+
+gctBOOL
+gcoVG_IsMaskSupported(
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceSURF_FORMAT Format
+ );
+
+gctBOOL
+gcoVG_IsTargetSupported(
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceSURF_FORMAT Format
+ );
+
+gctBOOL
+gcoVG_IsImageSupported(
+#if gcdGC355_PROFILER
+ IN gcoVG Vg,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceSURF_FORMAT Format
+ );
+
+gctUINT8 gcoVG_PackColorComponent(
+#if gcdGC355_PROFILER
+ gcoVG Vg,
+ gctUINT TreeDepth,
+ gctUINT saveLayerTreeDepth,
+ gctUINT varTreeDepth,
+#endif
+ gctFLOAT Value
+ );
+
+gceSTATUS
+gcoVG_Construct(
+ IN gcoHAL Hal,
+ OUT gcoVG * Vg
+ );
+
+gceSTATUS
+gcoVG_Destroy(
+ IN gcoVG Vg
+#if gcdGC355_PROFILER
+ ,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth
+#endif
+ );
+
+gceSTATUS
+gcoVG_SetTarget(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Target,
+ IN gceORIENTATION orientation
+ );
+
+gceSTATUS
+gcoVG_UnsetTarget(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoVG_SetUserToSurface(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT UserToSurface[9]
+ );
+
+gceSTATUS
+gcoVG_SetSurfaceToImage(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT SurfaceToImage[9]
+ );
+
+gceSTATUS
+gcoVG_EnableMask(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoVG_SetMask(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Mask
+ );
+
+gceSTATUS
+gcoVG_UnsetMask(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoVG_FlushMask(
+ IN gcoVG Vg
+#if gcdGC355_PROFILER
+ ,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth
+#endif
+ );
+
+gceSTATUS
+gcoVG_EnableScissor(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoVG_SetScissor(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctSIZE_T RectangleCount,
+ IN gcsVG_RECT_PTR Rectangles
+ );
+
+gceSTATUS
+gcoVG_EnableColorTransform(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoVG_SetColorTransform(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT ColorTransform[8]
+ );
+
+gceSTATUS
+gcoVG_SetTileFillColor(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+gceSTATUS
+gcoVG_SetSolidPaint(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT8 Red,
+ IN gctUINT8 Green,
+ IN gctUINT8 Blue,
+ IN gctUINT8 Alpha
+ );
+
+gceSTATUS
+gcoVG_SetLinearPaint(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT Constant,
+ IN gctFLOAT StepX,
+ IN gctFLOAT StepY
+ );
+
+gceSTATUS
+gcoVG_SetRadialPaint(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT LinConstant,
+ IN gctFLOAT LinStepX,
+ IN gctFLOAT LinStepY,
+ IN gctFLOAT RadConstant,
+ IN gctFLOAT RadStepX,
+ IN gctFLOAT RadStepY,
+ IN gctFLOAT RadStepXX,
+ IN gctFLOAT RadStepYY,
+ IN gctFLOAT RadStepXY
+ );
+
+gceSTATUS
+gcoVG_SetPatternPaint(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctFLOAT UConstant,
+ IN gctFLOAT UStepX,
+ IN gctFLOAT UStepY,
+ IN gctFLOAT VConstant,
+ IN gctFLOAT VStepX,
+ IN gctFLOAT VStepY,
+ IN gctBOOL Linear
+ );
+
+gceSTATUS
+gcoVG_SetColorRamp(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF ColorRamp,
+ IN gceTILE_MODE ColorRampSpreadMode
+ );
+
+gceSTATUS
+gcoVG_SetPattern(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctINT32 width,
+ IN gctINT32 height,
+ IN gcoSURF Pattern,
+ IN gceTILE_MODE TileMode,
+ IN gceIMAGE_FILTER Filter
+ );
+
+gceSTATUS
+gcoVG_SetImageMode(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceVG_IMAGE Mode
+ );
+
+gceSTATUS
+gcoVG_SetBlendMode(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceVG_BLEND Mode
+ );
+
+gceSTATUS
+gcoVG_SetRenderingQuality(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceRENDER_QUALITY Quality
+ );
+
+gceSTATUS
+gcoVG_SetFillRule(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceFILL_RULE FillRule
+ );
+
+gceSTATUS
+gcoVG_FinalizePath(
+ IN gcoVG Vg,
+ IN gcsPATH_DATA_PTR PathData
+ );
+
+gceSTATUS
+gcoVG_Clear(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctINT X,
+ IN gctINT Y,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+gceSTATUS
+gcoVG_DrawPath(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcsPATH_DATA_PTR PathData,
+ IN gctFLOAT Scale,
+ IN gctFLOAT Bias,
+#if gcdMOVG
+ IN gctUINT32 Width,
+ IN gctUINT32 Height,
+ IN gctFLOAT *Bounds,
+#endif
+ IN gctBOOL SoftwareTesselation
+ );
+
+gceSTATUS
+gcoVG_DrawImage(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gceORIENTATION orientation,
+ IN gcoSURF Source,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsPOINT_PTR TargetOrigin,
+ IN gcsSIZE_PTR SourceSize,
+ IN gctINT SourceX,
+ IN gctINT SourceY,
+ IN gctINT TargetX,
+ IN gctINT TargetY,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctBOOL Mask,
+ IN gctBOOL isDrawImage
+ );
+
+gceSTATUS
+gcoVG_TesselateImage(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Image,
+ IN gcsVG_RECT_PTR Rectangle,
+ IN gceIMAGE_FILTER Filter,
+ IN gctBOOL Mask,
+#if gcdMOVG
+ IN gctBOOL SoftwareTesselation,
+ IN gceVG_BLEND BlendMode,
+ IN gctINT Width,
+ IN gctINT Height
+#else
+ IN gctBOOL SoftwareTesselation
+#endif
+ );
+
+gceSTATUS
+gcoVG_DrawSurfaceToImage(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Image,
+ IN const gcsVG_RECT_PTR SrcRectangle,
+ IN const gcsVG_RECT_PTR DstRectangle,
+ IN const gctFLOAT Matrix[9],
+ IN gceIMAGE_FILTER Filter,
+ IN gctBOOL Mask,
+ IN gctBOOL FirstTime
+ );
+
+gceSTATUS
+gcoVG_Blit(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gcsVG_RECT_PTR SrcRect,
+ IN gcsVG_RECT_PTR TrgRect,
+ IN gceIMAGE_FILTER Filter,
+ IN gceVG_BLEND Mode
+ );
+
+gceSTATUS
+gcoVG_ColorMatrix(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN const gctFLOAT * Matrix,
+ IN gceCHANNEL ColorChannels,
+ IN gctBOOL FilterLinear,
+ IN gctBOOL FilterPremultiplied,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsPOINT_PTR TargetOrigin,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+gceSTATUS
+gcoVG_SeparableConvolve(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gctINT KernelWidth,
+ IN gctINT KernelHeight,
+ IN gctINT ShiftX,
+ IN gctINT ShiftY,
+ IN const gctINT16 * KernelX,
+ IN const gctINT16 * KernelY,
+ IN gctFLOAT Scale,
+ IN gctFLOAT Bias,
+ IN gceTILE_MODE TilingMode,
+ IN gctFLOAT_PTR FillColor,
+ IN gceCHANNEL ColorChannels,
+ IN gctBOOL FilterLinear,
+ IN gctBOOL FilterPremultiplied,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsPOINT_PTR TargetOrigin,
+ IN gcsSIZE_PTR SourceSize,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+gceSTATUS
+gcoVG_GaussianBlur(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gctFLOAT StdDeviationX,
+ IN gctFLOAT StdDeviationY,
+ IN gceTILE_MODE TilingMode,
+ IN gctFLOAT_PTR FillColor,
+ IN gceCHANNEL ColorChannels,
+ IN gctBOOL FilterLinear,
+ IN gctBOOL FilterPremultiplied,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsPOINT_PTR TargetOrigin,
+ IN gcsSIZE_PTR SourceSize,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+gceSTATUS
+gcoVG_EnableDither(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctBOOL Enable
+ );
+
+/* Color Key States. */
+gceSTATUS
+gcoVG_SetColorKey(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT32* Values,
+ IN gctBOOL * Enables
+);
+
+/* Index Color States. */
+gceSTATUS
+gcoVG_SetColorIndexTable(
+ IN gcoVG Vg,
+#if gcdGC355_PROFILER
+ IN gcsPROFILERFUNCNODE *DList,
+ IN gctUINT TreeDepth,
+ IN gctUINT saveLayerTreeDepth,
+ IN gctUINT varTreeDepth,
+#endif
+ IN gctUINT32* Values,
+ IN gctINT32 Count
+);
+
+/* VG RS feature support: YUV format conversion. */
+gceSTATUS
+gcoVG_Resolve(
+ IN gcoVG Vg,
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gctINT SX,
+ IN gctINT SY,
+ IN gctINT DX,
+ IN gctINT DY,
+ IN gctINT Width,
+ IN gctINT Height,
+ IN gctINT Src_uv,
+ IN gctINT Src_standard,
+ IN gctINT Dst_uv,
+ IN gctINT Dst_standard,
+ IN gctINT Dst_alpha
+);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_vg_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
new file mode 100644
index 000000000000..ad9f8e1e8ae1
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
@@ -0,0 +1,2148 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_enum_h_
+#define __gc_hal_enum_h_
+
+#include "gc_hal_options.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Chip models. */
+typedef enum _gceCHIPMODEL
+{
+ gcv200 = 0x0200,
+ gcv300 = 0x0300,
+ gcv320 = 0x0320,
+ gcv328 = 0x0328,
+ gcv350 = 0x0350,
+ gcv355 = 0x0355,
+ gcv400 = 0x0400,
+ gcv410 = 0x0410,
+ gcv420 = 0x0420,
+ gcv428 = 0x0428,
+ gcv450 = 0x0450,
+ gcv500 = 0x0500,
+ gcv520 = 0x0520,
+ gcv530 = 0x0530,
+ gcv600 = 0x0600,
+ gcv620 = 0x0620,
+ gcv700 = 0x0700,
+ gcv800 = 0x0800,
+ gcv860 = 0x0860,
+ gcv880 = 0x0880,
+ gcv900 = 0x0900,
+ gcv1000 = 0x1000,
+ gcv1500 = 0x1500,
+ gcv2000 = 0x2000,
+ gcv2100 = 0x2100,
+ gcv2200 = 0x2200,
+ gcv2500 = 0x2500,
+ gcv3000 = 0x3000,
+ gcv4000 = 0x4000,
+ gcv5000 = 0x5000,
+ gcv5200 = 0x5200,
+ gcv6400 = 0x6400,
+ gcv7000 = 0x7000,
+ gcv7400 = 0x7400,
+}
+gceCHIPMODEL;
+
+/* Chip features. */
+typedef enum _gceFEATURE
+{
+ gcvFEATURE_PIPE_2D = 0,
+ gcvFEATURE_PIPE_3D,
+ gcvFEATURE_PIPE_VG,
+ gcvFEATURE_DC,
+ gcvFEATURE_HIGH_DYNAMIC_RANGE,
+ gcvFEATURE_MODULE_CG,
+ gcvFEATURE_MIN_AREA,
+ gcvFEATURE_BUFFER_INTERLEAVING,
+ gcvFEATURE_BYTE_WRITE_2D,
+ gcvFEATURE_ENDIANNESS_CONFIG,
+ gcvFEATURE_DUAL_RETURN_BUS,
+ gcvFEATURE_DEBUG_MODE,
+ gcvFEATURE_YUY2_RENDER_TARGET,
+ gcvFEATURE_FRAGMENT_PROCESSOR,
+ gcvFEATURE_2DPE20,
+ gcvFEATURE_FAST_CLEAR,
+ gcvFEATURE_YUV420_TILER,
+ gcvFEATURE_YUY2_AVERAGING,
+ gcvFEATURE_FLIP_Y,
+ gcvFEATURE_EARLY_Z,
+ gcvFEATURE_COMPRESSION,
+ gcvFEATURE_MSAA,
+ gcvFEATURE_SPECIAL_ANTI_ALIASING,
+ gcvFEATURE_SPECIAL_MSAA_LOD,
+ gcvFEATURE_422_TEXTURE_COMPRESSION,
+ gcvFEATURE_DXT_TEXTURE_COMPRESSION,
+ gcvFEATURE_ETC1_TEXTURE_COMPRESSION,
+ gcvFEATURE_CORRECT_TEXTURE_CONVERTER,
+ gcvFEATURE_TEXTURE_8K,
+ gcvFEATURE_SCALER,
+ gcvFEATURE_YUV420_SCALER,
+ gcvFEATURE_SHADER_HAS_W,
+ gcvFEATURE_SHADER_HAS_SIGN,
+ gcvFEATURE_SHADER_HAS_FLOOR,
+ gcvFEATURE_SHADER_HAS_CEIL,
+ gcvFEATURE_SHADER_HAS_SQRT,
+ gcvFEATURE_SHADER_HAS_TRIG,
+ gcvFEATURE_HZ,
+ gcvFEATURE_CORRECT_STENCIL,
+ gcvFEATURE_VG20,
+ gcvFEATURE_VG_FILTER,
+ gcvFEATURE_VG21,
+ gcvFEATURE_VG_DOUBLE_BUFFER,
+ gcvFEATURE_MC20,
+ gcvFEATURE_SUPER_TILED,
+ gcvFEATURE_FAST_CLEAR_FLUSH,
+ gcvFEATURE_2D_FILTERBLIT_PLUS_ALPHABLEND,
+ gcvFEATURE_2D_DITHER,
+ gcvFEATURE_2D_A8_TARGET,
+ gcvFEATURE_2D_A8_NO_ALPHA,
+ gcvFEATURE_2D_FILTERBLIT_FULLROTATION,
+ gcvFEATURE_2D_BITBLIT_FULLROTATION,
+ gcvFEATURE_WIDE_LINE,
+ gcvFEATURE_FC_FLUSH_STALL,
+ gcvFEATURE_FULL_DIRECTFB,
+ gcvFEATURE_HALF_FLOAT_PIPE,
+ gcvFEATURE_LINE_LOOP,
+ gcvFEATURE_2D_YUV_BLIT,
+ gcvFEATURE_2D_TILING,
+ gcvFEATURE_NON_POWER_OF_TWO,
+ gcvFEATURE_3D_TEXTURE,
+ gcvFEATURE_TEXTURE_ARRAY,
+ gcvFEATURE_TILE_FILLER,
+ gcvFEATURE_LOGIC_OP,
+ gcvFEATURE_COMPOSITION,
+ gcvFEATURE_MIXED_STREAMS,
+ gcvFEATURE_2D_MULTI_SOURCE_BLT,
+ gcvFEATURE_END_EVENT,
+ gcvFEATURE_VERTEX_10_10_10_2,
+ gcvFEATURE_TEXTURE_10_10_10_2,
+ gcvFEATURE_TEXTURE_ANISOTROPIC_FILTERING,
+ gcvFEATURE_TEXTURE_FLOAT_HALF_FLOAT,
+ gcvFEATURE_2D_ROTATION_STALL_FIX,
+ gcvFEATURE_2D_MULTI_SOURCE_BLT_EX,
+ gcvFEATURE_BUG_FIXES10,
+ gcvFEATURE_2D_MINOR_TILING,
+ gcvFEATURE_TEX_COMPRRESSION_SUPERTILED, /* Supertiled compressed textures are supported. */
+ gcvFEATURE_FAST_MSAA,
+ gcvFEATURE_BUG_FIXED_INDEXED_TRIANGLE_STRIP,
+ gcvFEATURE_TEXTURE_TILE_STATUS_READ,
+ gcvFEATURE_DEPTH_BIAS_FIX,
+ gcvFEATURE_RECT_PRIMITIVE,
+ gcvFEATURE_BUG_FIXES11,
+ gcvFEATURE_SUPERTILED_TEXTURE,
+ gcvFEATURE_2D_NO_COLORBRUSH_INDEX8,
+ gcvFEATURE_RS_YUV_TARGET,
+ gcvFEATURE_2D_FC_SOURCE,
+ gcvFEATURE_2D_CC_NOAA_SOURCE,
+ gcvFEATURE_PE_DITHER_FIX,
+ gcvFEATURE_2D_YUV_SEPARATE_STRIDE,
+ gcvFEATURE_FRUSTUM_CLIP_FIX,
+ gcvFEATURE_TEXTURE_SWIZZLE,
+ gcvFEATURE_PRIMITIVE_RESTART,
+ gcvFEATURE_TEXTURE_LINEAR,
+ gcvFEATURE_TEXTURE_YUV_ASSEMBLER,
+ gcvFEATURE_LINEAR_RENDER_TARGET,
+ gcvFEATURE_SHADER_HAS_ATOMIC,
+ gcvFEATURE_SHADER_HAS_INSTRUCTION_CACHE,
+ gcvFEATURE_SHADER_ENHANCEMENTS2,
+ gcvFEATURE_BUG_FIXES7,
+ gcvFEATURE_SHADER_HAS_RTNE,
+ gcvFEATURE_SHADER_HAS_EXTRA_INSTRUCTIONS2,
+ gcvFEATURE_SHADER_ENHANCEMENTS3,
+ gcvFEATURE_DYNAMIC_FREQUENCY_SCALING,
+ gcvFEATURE_SINGLE_BUFFER,
+ gcvFEATURE_OCCLUSION_QUERY,
+ gcvFEATURE_2D_GAMMA,
+ gcvFEATURE_2D_COLOR_SPACE_CONVERSION,
+ gcvFEATURE_2D_SUPER_TILE_VERSION,
+ gcvFEATURE_HALTI0,
+ gcvFEATURE_HALTI1,
+ gcvFEATURE_HALTI2,
+ gcvFEATURE_SUPPORT_GCREGTX,
+ gcvFEATURE_2D_MIRROR_EXTENSION,
+ gcvFEATURE_TEXTURE_ASTC,
+ gcvFEATURE_TEXTURE_ASTC_DECODE_FIX,
+ gcvFEATURE_TEXTURE_ASTC_BASE_LOD_FIX,
+ gcvFEATURE_2D_SUPER_TILE_V1,
+ gcvFEATURE_2D_SUPER_TILE_V2,
+ gcvFEATURE_2D_SUPER_TILE_V3,
+ gcvFEATURE_2D_MULTI_SOURCE_BLT_EX2,
+ gcvFEATURE_NEW_RA,
+ gcvFEATURE_BUG_FIXED_IMPLICIT_PRIMITIVE_RESTART,
+ gcvFEATURE_PE_MULTI_RT_BLEND_ENABLE_CONTROL,
+ gcvFEATURE_SMALL_MSAA, /* An upgraded version of Fast MSAA */
+ gcvFEATURE_VERTEX_INST_ID_AS_ATTRIBUTE,
+ gcvFEATURE_DUAL_16,
+ gcvFEATURE_BRANCH_ON_IMMEDIATE_REG,
+ gcvFEATURE_2D_COMPRESSION,
+ gcvFEATURE_TPC_COMPRESSION,
+ gcvFEATURE_TPCV11_COMPRESSION,
+ gcvFEATURE_DEC_COMPRESSION,
+ gcvFEATURE_DEC300_COMPRESSION,
+ gcvFEATURE_DEC400_COMPRESSION,
+ gcvFEATURE_DEC_TPC_COMPRESSION,
+ gcvFEATURE_DEC_COMPRESSION_TILE_NV12_8BIT,
+ gcvFEATURE_DEC_COMPRESSION_TILE_NV12_10BIT,
+ gcvFEATURE_2D_OPF_YUV_OUTPUT,
+ gcvFEATURE_2D_FILTERBLIT_A8_ALPHA,
+ gcvFEATURE_2D_MULTI_SRC_BLT_TO_UNIFIED_DST_RECT,
+ gcvFEATURE_2D_MULTI_SRC_BLT_BILINEAR_FILTER,
+ gcvFEATURE_2D_MULTI_SRC_BLT_1_5_ENHANCEMENT,
+ gcvFEATURE_V2_COMPRESSION_Z16_FIX,
+ gcvFEATURE_VERTEX_INST_ID_AS_INTEGER,
+ gcvFEATURE_2D_YUV_MODE,
+ gcvFEATURE_2D_CACHE_128B256BPERLINE,
+ gcvFEATURE_2D_SEPARATE_CACHE,
+ gcvFEATURE_2D_MAJOR_SUPER_TILE,
+ gcvFEATURE_2D_V4COMPRESSION,
+ gcvFEATURE_2D_VMSAA,
+ gcvFEATURE_2D_10BIT_OUTPUT_LINEAR,
+ gcvFEATURE_2D_YUV420_OUTPUT_LINEAR,
+ gcvFEATURE_ACE,
+ gcvFEATURE_COLOR_COMPRESSION,
+ gcvFEATURE_32BPP_COMPONENT_TEXTURE_CHANNEL_SWIZZLE,
+ gcvFEATURE_64BPP_HW_CLEAR_SUPPORT,
+ gcvFEATURE_TX_LERP_PRECISION_FIX,
+ gcvFEATURE_COMPRESSION_V2,
+ gcvFEATURE_MMU,
+ gcvFEATURE_COMPRESSION_V3,
+ gcvFEATURE_TX_DECOMPRESSOR,
+ gcvFEATURE_MRT_TILE_STATUS_BUFFER,
+ gcvFEATURE_COMPRESSION_V1,
+ gcvFEATURE_V1_COMPRESSION_Z16_DECOMPRESS_FIX,
+ gcvFEATURE_RTT,
+ gcvFEATURE_GENERIC_ATTRIB,
+ gcvFEATURE_2D_ONE_PASS_FILTER,
+ gcvFEATURE_2D_ONE_PASS_FILTER_TAP,
+ gcvFEATURE_2D_POST_FLIP,
+ gcvFEATURE_2D_PIXEL_ALIGNMENT,
+ gcvFEATURE_CORRECT_AUTO_DISABLE_COUNT,
+ gcvFEATURE_CORRECT_AUTO_DISABLE_COUNT_WIDTH,
+ gcvFEATURE_8K_RT,
+ gcvFEATURE_HALTI3,
+ gcvFEATURE_EEZ,
+ gcvFEATURE_INTEGER_SIGNEXT_FIX,
+ gcvFEATURE_PSOUTPUT_MAPPING,
+ gcvFEATURE_8K_RT_FIX,
+ gcvFEATURE_TX_TILE_STATUS_MAPPING,
+ gcvFEATURE_SRGB_RT_SUPPORT,
+ gcvFEATURE_TEXTURE_16K,
+ gcvFEATURE_PA_FARZCLIPPING_FIX,
+ gcvFEATURE_PE_DITHER_COLORMASK_FIX,
+ gcvFEATURE_ZSCALE_FIX,
+ gcvFEATURE_MULTI_PIXELPIPES,
+ gcvFEATURE_PIPE_CL,
+ gcvFEATURE_BUG_FIXES18,
+ gcvFEATURE_UNIFIED_SAMPLERS,
+ gcvFEATURE_CL_PS_WALKER,
+ gcvFEATURE_NEW_HZ,
+ gcvFEATURE_TX_FRAC_PRECISION_6BIT,
+ gcvFEATURE_SH_INSTRUCTION_PREFETCH,
+ gcvFEATURE_PROBE,
+ gcvFEATURE_SINGLE_PIPE_HALTI1,
+ gcvFEATURE_BUG_FIXES8, /* This HW feature is wrong, we can't use this to check integer branch!!!*/
+ gcvFEATURE_2D_ALL_QUAD,
+ gcvFEATURE_SEPARATE_SRC_DST,
+ gcvFEATURE_TX_HOR_ALIGN_SEL,
+ gcvFEATURE_HALTI4,
+ gcvFEATURE_MRT_FC_FIX,
+ gcvFEATURE_TESSELLATION,
+ gcvFEATURE_DRAW_INDIRECT,
+ gcvFEATURE_COMPUTE_INDIRECT,
+ gcvFEATURE_MSAA_TEXTURE,
+ gcvFEATURE_STENCIL_TEXTURE,
+ gcvFEATURE_S8_ONLY_RENDERING,
+ gcvFEATURE_D24S8_SAMPLE_STENCIL,
+ gcvFEATURE_ADVANCED_BLEND_MODE_PART0,
+ gcvFEATURE_RA_DEPTH_WRITE,
+ gcvFEATURE_RS_DS_DOWNSAMPLE_NATIVE_SUPPORT,
+ gcvFEATURE_S8_MSAA_COMPRESSION,
+ gcvFEATURE_MSAA_FRAGMENT_OPERATION,
+ gcvFEATURE_FE_START_VERTEX_SUPPORT,
+ gcvFEATURE_DIVISOR_STREAM_ADDR_FIX,
+ gcvFEATURE_ZERO_ATTRIB_SUPPORT,
+ gcvFEATURE_DANGLING_VERTEX_FIX,
+ gcvFEATURE_PE_DISABLE_COLOR_PIPE,
+ gcvFEATURE_FE_12bit_stride,
+ gcvFEATURE_TX_LOD_GUARDBAND,
+ gcvFEATURE_HAS_PRODUCTID,
+ gcvFEATURE_INTEGER32_FIX,
+ gcvFEATURE_TEXTURE_GATHER,
+ gcvFEATURE_IMG_INSTRUCTION,
+ gcvFEATURE_HELPER_INVOCATION,
+ gcvFEATURE_NO_USER_CSC,
+ gcvFEATURE_ANDROID_ONLY,
+ gcvFEATURE_V2_MSAA_COHERENCY_FIX,
+ gcvFEATURE_BLOCK_SIZE_16x16,
+ gcvFEATURE_TX_SUPPORT_DEC,
+ gcvFEATURE_RSBLT_MSAA_DECOMPRESSION,
+ gcvFEATURE_TILEFILLER_32TILE_ALIGNED,
+ gcvFEATURE_GEOMETRY_SHADER,
+ gcvFEATURE_HALTI5,
+ gcvFEATURE_PIPELINE_32_ATTRIBUTES,
+ gcvFEATURE_USC,
+ gcvFEATURE_CUBEMAP_ARRAY,
+ gcvFEATURE_TX_DESCRIPTOR,
+ gcvFEATURE_SEPARATE_RT_CTRL,
+ gcvFEATURE_RENDER_ARRAY,
+ gcvFEATURE_BLT_ENGINE,
+ gcvFEATURE_SMALLDRAW_BATCH,
+ gcvFEATURE_TEXTURE_BUFFER,
+ gcvFEATURE_GS_SUPPORT_EMIT,
+ gcvFEATURE_SAMPLER_BASE_OFFSET,
+ gcvFEATURE_IMAGE_OUT_BOUNDARY_FIX,
+ gcvFEATURE_TX_BORDER_CLAMP,
+ gcvFEATURE_MSAA_SHADING,
+ gcvFEATURE_ADVANCED_SH_INST,
+ gcvFEATURE_LOD_FIX_FOR_BASELEVEL,
+ gcvFEATURE_MULTIDRAW_INDIRECT,
+ gcvFEATURE_DRAW_ELEMENTS_BASE_VERTEX,
+ gcvFEATURE_NEW_STEERING_AND_ICACHE_FLUSH, /* Steering base on register base. Trigger-style Icache flush state. */
+ gcvFEATURE_PE_DITHER_FIX2,
+ gcvFEATURE_INDEX_FETCH_FIX,
+ gcvFEATURE_TEX_BASELOD,
+ gcvFEATURE_TEX_SEAMLESS_CUBE,
+ gcvFEATURE_TEX_ETC2,
+ gcvFEATURE_TEX_CUBE_BORDER_LOD,
+ gcvFEATURE_FE_ALLOW_STALL_PREFETCH_ENG,
+ gcvFEATURE_TX_8BPP_TS_FIX,
+ gcvFEATURE_HW_TFB,
+ gcvFEATURE_COMPRESSION_V4,
+ gcvFEATURE_FENCE,
+ gcvFEATURE_R8_UNORM,
+ gcvFEATURE_TX_DEFAULT_VALUE_FIX,
+ gcvFEATURE_TX_8bit_UVFrac,
+ gcvFEATURE_TX_MIPFILTER_NONE_FIX,
+ gcvFEATURE_MC_STENCIL_CTRL,
+ gcvFEATURE_DEPTH_MATH_FIX,
+ gcvFEATURE_PE_B2B_PIXEL_FIX,
+ gcvFEATURE_TEXTURE_GATHER_OFFSETS,
+ gcvFEATURE_TEX_CACHE_FLUSH_FIX,
+ gcvFEATURE_WIDELINE_HELPER_FIX,
+ gcvFEATURE_LINE_DIAMOND_RULE_FIX,
+ gcvFEATURE_MULTIGPU_SYNC_V2,
+ gcvFEATURE_DRAW_ID,
+ gcvFEATURE_SNAPPAGE_CMD,
+ gcvFEATURE_COMMAND_PREFETCH,
+ gcvFEATURE_SAMPLEPOS_SWIZZLE_FIX,
+ gcvFEATURE_SELECTMAP_SRC0_SWIZZLE_FIX,
+ gcvFEATURE_LOADATTR_OOB_FIX,
+ gcvFEATURE_RA_DEPTH_WRITE_MSAA1X_FIX,
+ gcvFEATURE_MRT_8BIT_DUAL_PIPE_FIX,
+ gcvFEATURE_BUG_FIXES1,
+ gcvFEATURE_MULTI_SOURCE_BLT,
+ gcvFEATURE_ZCOMPRESSION,
+ gcvFEATURE_DITHER_AND_FILTER_PLUS_ALPHA_2D,
+ gcvFEATURE_ONE_PASS_2D_FILTER,
+ gcvFEATURE_TX_FILTER,
+ gcvFEATURE_CHIPENABLE_LINK,
+ gcvFEATURE_TEXTURE_BIAS_LOD_FIX,
+ gcvFEATURE_USE_GL_Z,
+ gcvFEATURE_SUPPORT_INTEGER,
+ /* PARTLY_SUPPORT_INTEGER_BRANCH:
+ ** chips can support all integer types for compare instructions, e.g, CMP, SELECT.
+ ** FULLLY_SUPPORT_INTEGER_BRANCH:
+ ** chips can support all integer types for JMP instruction.
+ ** If PARTLY_SUPPORT_INTEGER_BRANCH is TRUE but FULLLY_SUPPORT_INTEGER_BRANCH is FALSE,
+ ** then this chip can only support INT32/UINT32 JMP instruction.
+ */
+ gcvFEATURE_PARTLY_SUPPORT_INTEGER_BRANCH,
+ gcvFEATURE_FULLLY_SUPPORT_INTEGER_BRANCH,
+ gcvFEATURE_SUPPORT_INTEGER_ATTRIBUTE,
+ gcvFEATURE_SUPPORT_MOVAI,
+ gcvFEATURE_NEED_FIX_FOR_CL_X,
+ gcvFEATURE_NEED_FIX_FOR_CL_XE,
+ gcvFEATURE_HAS_OUTPUT_COUNT_FIX,
+ gcvFEATURE_VARYING_PACKING_LIMITATION,
+ gcvFEATURE_HIGHP_VARYING_SHIFT,
+ gcvFEATURE_BUG_FIXES2,
+ gcvFEATURE_64K_L2_CACHE,
+ gcvFEATURE_128BTILE,
+ gcvFEATURE_ADVANCED_BLEND_OPT,
+ gcvFEATURE_SNAPPAGE_CMD_FIX,
+ gcvFEATURE_L2_CACHE_FOR_2D_420,
+ gcvFEATURE_TILE_STATUS_2BITS,
+ gcvFEATURE_EXTRA_SHADER_INSTRUCTIONS0,
+ gcvFEATURE_EXTRA_SHADER_INSTRUCTIONS1,
+ gcvFEATURE_EXTRA_SHADER_INSTRUCTIONS2,
+ gcvFEATURE_MEDIUM_PRECISION,
+ gcvFEATURE_FE20_BIT_INDEX,
+ gcvFEATURE_BUG_FIXES4,
+ gcvFEATURE_BUG_FIXES12,
+ gcvFEATURE_VMSAA,
+ gcvFEATURE_ROBUST_ATOMIC,
+ gcvFEATURE_32F_COLORMASK_FIX,
+ gcvFEATURE_NEW_GPIPE,
+ gcvFEATURE_RS_NEW_BASEADDR,
+ gcvFEATURE_TX_DXT,
+ gcvFEATURE_SH_FLAT_INTERPOLATION_DUAL16_FIX,
+ gcvFEATURE_EVIS,
+ gcvFEATURE_SH_SUPPORT_V4,
+ gcvFEATURE_SH_SUPPORT_ALPHA_KILL,
+ gcvFEATURE_PE_NO_ALPHA_TEST,
+ gcvFEATURE_SH_SNAP2PAGE_MAXPAGES_FIX,
+ gcvFEATURE_USC_FULLCACHE_FIX,
+ gcvFEATURE_PE_64bit_FENCE_FIX,
+ gcvFEATURE_BLT_8bit_256TILE_FC_FIX,
+ gcvFEATURE_PE_RGBA16I_FIX,
+ gcvFEATURE_BLT_64bpp_MASKED_CLEAR_FIX,
+ gcvFEATURE_SH_PSO_MSAA1x_FIX,
+ gcvFEATURE_USC_ATOMIC_FIX,
+ gcvFEATURE_INDEX_CONST_ON_B0,
+ gcvFEATURE_SH_NO_ONECONST_LIMIT,
+ gcvFEATURE_EVIS_NO_ABSDIFF,
+ gcvFEATURE_EVIS_NO_BITREPLACE,
+ gcvFEATURE_EVIS_NO_BOXFILTER,
+ gcvFEATURE_EVIS_NO_CORDIAC,
+ gcvFEATURE_EVIS_NO_DP32,
+ gcvFEATURE_EVIS_NO_FILTER,
+ gcvFEATURE_EVIS_NO_IADD,
+ gcvFEATURE_EVIS_NO_SELECTADD,
+ gcvFEATURE_EVIS_LERP_7OUTPUT,
+ gcvFEATURE_EVIS_ACCSQ_8OUTPUT,
+ gcvFEATURE_ROBUSTNESS,
+ gcvFEATURE_SECURITY,
+ gcvFEATURE_TX_YUV_ASSEMBLER_10BIT,
+ gcvFEATURE_USC_GOS_ADDR_FIX,
+ gcvFEATURE_SUPPORT_MSAA2X,
+ gcvFEATURE_TX_DESC_CACHE_CLOCKGATE_FIX,
+ gcvFEATURE_TX_INTEGER_COORDINATE,
+ gcvFEATURE_PSIO_SAMPLEMASK_IN_R0ZW_FIX,
+ gcvFEATURE_MULTI_CORE_BLOCK_SET_CONFIG,
+ gcvFEATURE_SH_IMG_LDST_ON_TEMP,
+ gcvFEATURE_TX_INTEGER_COORDINATE_V2,
+ gcvFEATURE_COMPUTE_ONLY,
+ gcvFEATURE_SH_IMG_LDST_CLAMP,
+ gcvFEATURE_SH_ICACHE_ALLOC_COUNT_FIX,
+ gcvFEATURE_MSAA_OQ_FIX,
+ gcvFEATURE_PE_ENHANCEMENTS2,
+ gcvFEATURE_PSIO_MSAA_CL_FIX,
+ gcvFEATURE_FE_NEED_DUMMYDRAW,
+ gcvFEATURE_MULTI_CLUSTER,
+ gcvFEATURE_PSIO_INTERLOCK,
+ gcvFEATURE_BLIT_COMPRESS_DEST,
+ gcvFEATURE_SH_MULTI_WG_PACK,
+ gcvFEATURE_FE_ROBUST_FIX,
+ gcvFEATURE_TX_ASTC_MULTISLICE_FIX,
+ gcvFEATURE_PSIO_DUAL16_32bpc_FIX,
+ gcvFEATURE_LS_SUPPORT_PER_COMP_DEPENDENCY,
+ gcvFEATURE_COMPRESSION_DEC400,
+ gcvFEATURE_SH_TEXLD_U_FIX,
+ gcvFEATURE_TX_FLUSH_L1CACHE,
+ gcvFEATURE_USC_DEFER_FILL_FIX,
+ gcvFEATURE_MC_FCCACHE_BYTEMASK,
+ gcvFEATURE_SH_MULTI_WG_PACK_FIX,
+ gcvFEATURE_FE_PATCHLIST_FETCH_FIX,
+ gcvFEATURE_RA_CG_FIX,
+ gcvFEATURE_EVIS_VX2,
+ gcvFEATURE_SH_HALF_DEPENDENCY_FIX,
+ gcvFEATURE_SH_CLOCK_GATE_FIX,
+ gcvFEATURE_GPIPE_CLOCK_GATE_FIX,
+ gcvFEATURE_TP_ENGINE,
+ gcvFEATURE_TX_BORDER_CLAMP_FIX,
+ gcvFEATURE_SH_IMAGE_LD_LAST_PIXEL_FIX,
+ gcvFEATURE_MULTI_CORE_BLOCK_SET_CONFIG2,
+ gcvFEATURE_MULTIGPU_SYNC_V3,
+ gcvFEATURE_PE_VMSAA_COVERAGE_CACHE_FIX,
+ gcvFEATURE_SECURITY_AHB,
+ gcvFEATURE_TX_LERP_LESS_BIT,
+ /* Insert features above this comment only. */
+ gcvFEATURE_COUNT /* Not a feature. */
+}
+gceFEATURE;
+
+/* dummy draw type.*/
+typedef enum _gceDUMMY_DRAW_TYPE
+{
+ gcvDUMMY_DRAW_INVALID = 0,
+ gcvDUMMY_DRAW_GC400,
+ gcvDUMMY_DRAW_V60,
+}
+gceDUMMY_DRAW_TYPE;
+
+/* Chip SWWA. */
+typedef enum _gceSWWA
+{
+ gcvSWWA_601 = 0,
+ gcvSWWA_706,
+ gcvSWWA_1163,
+ gcvSWWA_1165,
+ /* Insert SWWA above this comment only. */
+ gcvSWWA_COUNT /* Not a SWWA. */
+}
+gceSWWA;
+
+
+/* Option Set*/
+typedef enum _gceOPTION
+{
+ /* HW setting. */
+ gcvOPTION_PREFER_ZCONVERT_BYPASS = 0,
+ gcvOPTION_PREFER_TILED_DISPLAY_BUFFER = 1,
+ gcvOPTION_PREFER_GUARDBAND = 2,
+ gcvOPTION_PREFER_TPG_TRIVIALMODEL = 3,
+ gcvOPTION_PREFER_RA_DEPTH_WRITE = 4,
+ gcvOPTION_PREFER_USC_RECONFIG = 5,
+
+ /* SW options */
+ gcvOPTION_HW_NULL = 50,
+ gcvOPTION_PRINT_OPTION = 51,
+ gcvOPTION_KERNEL_FENCE = 52,
+ gcvOPTION_ASYNC_PIPE = 53,
+ gcvOPTION_FBO_PREFER_MEM = 54,
+ gcvOPTION_GPU_TEX_UPLOAD = 55,
+ gcvOPTION_GPU_BUFOBJ_UPLOAD = 56,
+
+ /* Insert option above this comment only */
+ gcvOPTION_COUNT /* Not a OPTION*/
+}
+gceOPTION;
+
+typedef enum _gceFRAMEINFO
+{
+ /* Total frame count in one run */
+ gcvFRAMEINFO_FRAME_NUM = 0,
+ /* Total draw count in current frame, including draw/compute */
+ gcvFRAMEINFO_DRAW_NUM = 1,
+ /* Total compute count in current frame, subset of drawNum */
+ gcvFRAMEINFO_COMPUTE_NUM = 2,
+ /* Total dual16 draw/compute count in current frame, subset of drawNum */
+ gcvFRAMEINFO_DUAL16_NUM = 3,
+ /* Current programID is being set. only valid for ES20 driver right now */
+ gcvFRAMEINFO_PROGRAM_ID = 4,
+
+ gcvFRAMEINFO_COUNT,
+}
+gceFRAMEINFO;
+
+typedef enum _gceFRAMEINFO_OP
+{
+ gcvFRAMEINFO_OP_INC = 0,
+ gcvFRAMEINFO_OP_DEC = 1,
+ gcvFRAMEINFO_OP_ZERO = 2,
+ gcvFRAMEINFO_OP_GET = 3,
+ gcvFRAMEINFO_OP_SET = 4,
+ gcvFRAMEINFO_OP_COUNT,
+}
+gceFRAMEINFO_OP;
+
+
+/* Chip Power Status. */
+typedef enum _gceCHIPPOWERSTATE
+{
+ gcvPOWER_ON = 0,
+ gcvPOWER_OFF,
+ gcvPOWER_IDLE,
+ gcvPOWER_SUSPEND,
+ gcvPOWER_SUSPEND_ATPOWERON,
+ gcvPOWER_OFF_ATPOWERON,
+ gcvPOWER_IDLE_BROADCAST,
+ gcvPOWER_SUSPEND_BROADCAST,
+ gcvPOWER_OFF_BROADCAST,
+ gcvPOWER_OFF_RECOVERY,
+ gcvPOWER_OFF_TIMEOUT,
+ gcvPOWER_ON_AUTO
+}
+gceCHIPPOWERSTATE;
+
+/* CPU cache operations */
+typedef enum _gceCACHEOPERATION
+{
+ gcvCACHE_CLEAN = 0x01, /* Flush CPU cache to mem */
+ gcvCACHE_INVALIDATE = 0x02, /* Invalidte CPU cache */
+ gcvCACHE_FLUSH = gcvCACHE_CLEAN | gcvCACHE_INVALIDATE, /* Both flush & invalidate */
+ gcvCACHE_MEMORY_BARRIER = 0x04
+}
+gceCACHEOPERATION;
+
+/* Surface types. */
+typedef enum _gceSURF_TYPE
+{
+ gcvSURF_TYPE_UNKNOWN = 0,
+ gcvSURF_INDEX,
+ gcvSURF_VERTEX,
+ gcvSURF_TEXTURE,
+ gcvSURF_RENDER_TARGET,
+ gcvSURF_DEPTH,
+ gcvSURF_BITMAP,
+ gcvSURF_TILE_STATUS,
+ gcvSURF_IMAGE,
+ gcvSURF_MASK,
+ gcvSURF_SCISSOR,
+ gcvSURF_HIERARCHICAL_DEPTH,
+ gcvSURF_ICACHE,
+ gcvSURF_TXDESC,
+ gcvSURF_FENCE,
+ gcvSURF_TFBHEADER,
+ gcvSURF_NUM_TYPES, /* Make sure this is the last one! */
+
+ /* Combinations. */
+ gcvSURF_NO_TILE_STATUS = 0x100,
+ gcvSURF_NO_VIDMEM = 0x200, /* Used to allocate surfaces with no underlying vidmem node.
+ In Android, vidmem node is allocated by another process. */
+ gcvSURF_CACHEABLE = 0x400, /* Used to allocate a cacheable surface */
+
+ gcvSURF_TILE_RLV_FENCE = 0x800, /* create texture fence as tile */
+
+ gcvSURF_TILE_STATUS_DIRTY = 0x1000, /* Init tile status to all dirty */
+
+ gcvSURF_LINEAR = 0x2000,
+
+ gcvSURF_CREATE_AS_TEXTURE = 0x4000, /* create it as a texture */
+
+ gcvSURF_PROTECTED_CONTENT = 0x8000, /* create it as content protected */
+
+ gcvSURF_CREATE_AS_DISPLAYBUFFER = 0x10000, /*create it as a display buffer surface */
+
+ gcvSURF_CONTIGUOUS = 0x20000, /*create it as contiguous */
+
+ /* Create it as no compression, valid on when it has tile status. */
+ gcvSURF_NO_COMPRESSION = 0x40000,
+
+ gcvSURF_DEC = 0x80000, /* Surface is DEC compressed */
+
+ gcvSURF_NO_HZ = 0x100000,
+
+ gcvSURF_3D = 0x200000, /* It's 3d surface */
+
+ gcvSURF_CMA_LIMIT = 0x400000,
+
+ gcvSURF_TEXTURE_LINEAR = gcvSURF_TEXTURE
+ | gcvSURF_LINEAR,
+
+ gcvSURF_RENDER_TARGET_LINEAR = gcvSURF_RENDER_TARGET
+ | gcvSURF_LINEAR,
+
+ gcvSURF_RENDER_TARGET_NO_TILE_STATUS = gcvSURF_RENDER_TARGET
+ | gcvSURF_NO_TILE_STATUS,
+
+ gcvSURF_RENDER_TARGET_NO_COMPRESSION = gcvSURF_RENDER_TARGET
+ | gcvSURF_NO_COMPRESSION,
+
+ gcvSURF_RENDER_TARGET_TS_DIRTY = gcvSURF_RENDER_TARGET
+ | gcvSURF_TILE_STATUS_DIRTY,
+
+ gcvSURF_DEPTH_NO_TILE_STATUS = gcvSURF_DEPTH
+ | gcvSURF_NO_TILE_STATUS,
+
+ gcvSURF_DEPTH_TS_DIRTY = gcvSURF_DEPTH
+ | gcvSURF_TILE_STATUS_DIRTY,
+
+ /* Supported surface types with no vidmem node. */
+ gcvSURF_BITMAP_NO_VIDMEM = gcvSURF_BITMAP
+ | gcvSURF_NO_VIDMEM,
+
+ gcvSURF_TEXTURE_NO_VIDMEM = gcvSURF_TEXTURE
+ | gcvSURF_NO_VIDMEM,
+
+ /* Cacheable surface types with no vidmem node. */
+ gcvSURF_CACHEABLE_BITMAP_NO_VIDMEM = gcvSURF_BITMAP_NO_VIDMEM
+ | gcvSURF_CACHEABLE,
+
+ gcvSURF_CACHEABLE_BITMAP = gcvSURF_BITMAP
+ | gcvSURF_CACHEABLE,
+
+ gcvSURF_TEXTURE_3D = gcvSURF_TEXTURE
+ | gcvSURF_3D
+}
+gceSURF_TYPE;
+
+typedef enum _gceSURF_USAGE
+{
+ gcvSURF_USAGE_UNKNOWN,
+ gcvSURF_USAGE_RESOLVE_AFTER_CPU,
+ gcvSURF_USAGE_RESOLVE_AFTER_3D
+}
+gceSURF_USAGE;
+
+typedef enum _gceSURF_COLOR_SPACE
+{
+ gcvSURF_COLOR_SPACE_UNKNOWN,
+ gcvSURF_COLOR_SPACE_LINEAR,
+ gcvSURF_COLOR_SPACE_NONLINEAR,
+}
+gceSURF_COLOR_SPACE;
+
+typedef enum _gceSURF_COLOR_TYPE
+{
+ gcvSURF_COLOR_UNKNOWN = 0,
+ gcvSURF_COLOR_LINEAR = 0x01,
+ gcvSURF_COLOR_ALPHA_PRE = 0x02,
+}
+gceSURF_COLOR_TYPE;
+
+/* Rotation. */
+typedef enum _gceSURF_ROTATION
+{
+ gcvSURF_0_DEGREE = 0,
+ gcvSURF_90_DEGREE,
+ gcvSURF_180_DEGREE,
+ gcvSURF_270_DEGREE,
+ gcvSURF_FLIP_X,
+ gcvSURF_FLIP_Y,
+
+ gcvSURF_POST_FLIP_X = 0x40000000,
+ gcvSURF_POST_FLIP_Y = 0x80000000,
+}
+gceSURF_ROTATION;
+
+/* Surface flag */
+typedef enum _gceSURF_FLAG
+{
+ /* None flag */
+ gcvSURF_FLAG_NONE = 0x0,
+ /* content is preserved after swap */
+ gcvSURF_FLAG_CONTENT_PRESERVED = 0x1,
+ /* content is updated after swap*/
+ gcvSURF_FLAG_CONTENT_UPDATED = 0x2,
+ /* content is y inverted */
+ gcvSURF_FLAG_CONTENT_YINVERTED = 0x4,
+ /* surface has multiple nodes */
+ gcvSURF_FLAG_MULTI_NODE = 0x8,
+}
+gceSURF_FLAG;
+
+typedef enum _gceMIPMAP_IMAGE_FORMAT
+{
+ gcvUNKNOWN_MIPMAP_IMAGE_FORMAT = -2
+}
+gceMIPMAP_IMAGE_FORMAT;
+
+/* Surface formats.
+** Name rules is from MSB->LSB.
+*/
+typedef enum _gceSURF_FORMAT
+{
+ /* Unknown format. */
+ gcvSURF_UNKNOWN = 0,
+
+ /* Palettized formats. */
+ gcvSURF_INDEX1 = 100,
+ gcvSURF_INDEX4,
+ gcvSURF_INDEX8,
+#if gcdVG_ONLY
+ gcvSURF_INDEX2,
+#endif
+
+ /* RGB formats. */
+ gcvSURF_A2R2G2B2 = 200,
+ gcvSURF_R3G3B2,
+ gcvSURF_A8R3G3B2,
+ gcvSURF_X4R4G4B4,
+ gcvSURF_A4R4G4B4,
+ gcvSURF_R4G4B4A4,
+ gcvSURF_X1R5G5B5,
+ gcvSURF_A1R5G5B5,
+ gcvSURF_R5G5B5A1,
+ gcvSURF_R5G6B5,
+ gcvSURF_R8G8B8,
+ gcvSURF_X8R8G8B8,
+ gcvSURF_A8R8G8B8,
+ gcvSURF_R8G8B8A8,
+ gcvSURF_G8R8G8B8,
+ gcvSURF_R8G8B8G8,
+ gcvSURF_X2R10G10B10,
+ gcvSURF_A2R10G10B10,
+ gcvSURF_R10G10B10A2,
+ gcvSURF_X12R12G12B12,
+ gcvSURF_A12R12G12B12,
+ gcvSURF_X16R16G16B16,
+ gcvSURF_A16R16G16B16,
+ gcvSURF_A32R32G32B32,
+ gcvSURF_R8G8B8X8,
+ gcvSURF_R5G5B5X1,
+ gcvSURF_R4G4B4X4,
+ gcvSURF_X16R16G16B16_2_A8R8G8B8,
+ gcvSURF_A16R16G16B16_2_A8R8G8B8,
+ gcvSURF_A32R32G32B32_2_G32R32F,
+ gcvSURF_A32R32G32B32_4_A8R8G8B8,
+ /* BGR formats. */
+ gcvSURF_A4B4G4R4 = 300,
+ gcvSURF_A1B5G5R5,
+ gcvSURF_B5G6R5,
+ gcvSURF_B8G8R8,
+ gcvSURF_B16G16R16,
+ gcvSURF_X8B8G8R8,
+ gcvSURF_A8B8G8R8,
+ gcvSURF_A2B10G10R10,
+ gcvSURF_X16B16G16R16,
+ gcvSURF_A16B16G16R16,
+ gcvSURF_B32G32R32,
+ gcvSURF_X32B32G32R32,
+ gcvSURF_A32B32G32R32,
+ gcvSURF_B4G4R4A4,
+ gcvSURF_B5G5R5A1,
+ gcvSURF_B8G8R8X8,
+ gcvSURF_B8G8R8A8,
+ gcvSURF_B10G10R10A2,
+ gcvSURF_X4B4G4R4,
+ gcvSURF_X1B5G5R5,
+ gcvSURF_B4G4R4X4,
+ gcvSURF_B5G5R5X1,
+ gcvSURF_X2B10G10R10,
+ gcvSURF_B8G8R8_SNORM,
+ gcvSURF_X8B8G8R8_SNORM,
+ gcvSURF_A8B8G8R8_SNORM,
+ gcvSURF_A8B12G12R12_2_A8R8G8B8,
+
+ /* Compressed formats. */
+ gcvSURF_DXT1 = 400,
+ gcvSURF_DXT2,
+ gcvSURF_DXT3,
+ gcvSURF_DXT4,
+ gcvSURF_DXT5,
+ gcvSURF_CXV8U8,
+ gcvSURF_ETC1,
+ gcvSURF_R11_EAC,
+ gcvSURF_SIGNED_R11_EAC,
+ gcvSURF_RG11_EAC,
+ gcvSURF_SIGNED_RG11_EAC,
+ gcvSURF_RGB8_ETC2,
+ gcvSURF_SRGB8_ETC2,
+ gcvSURF_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ gcvSURF_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ gcvSURF_RGBA8_ETC2_EAC,
+ gcvSURF_SRGB8_ALPHA8_ETC2_EAC,
+
+ /* YUV formats. */
+ gcvSURF_YUY2 = 500,
+ gcvSURF_UYVY,
+ gcvSURF_YV12,
+ gcvSURF_I420,
+ gcvSURF_NV12,
+ gcvSURF_NV21,
+ gcvSURF_NV16,
+ gcvSURF_NV61,
+ gcvSURF_YVYU,
+ gcvSURF_VYUY,
+ gcvSURF_AYUV,
+ gcvSURF_YUV420_10_ST,
+ gcvSURF_YUV420_TILE_ST,
+ gcvSURF_YUV420_TILE_10_ST,
+ gcvSURF_NV12_10BIT,
+ gcvSURF_NV21_10BIT,
+ gcvSURF_NV16_10BIT,
+ gcvSURF_NV61_10BIT,
+ gcvSURF_P010,
+#if gcdVG_ONLY
+ gcvSURF_AYUY2,
+ gcvSURF_ANV12,
+ gcvSURF_ANV16,
+#endif
+
+ /* Depth formats. */
+ gcvSURF_D16 = 600,
+ gcvSURF_D24S8,
+ gcvSURF_D32,
+ gcvSURF_D24X8,
+ gcvSURF_D32F,
+ gcvSURF_S8D32F,
+ gcvSURF_S8D32F_1_G32R32F,
+ gcvSURF_S8D32F_2_A8R8G8B8,
+ gcvSURF_D24S8_1_A8R8G8B8,
+ gcvSURF_S8,
+ gcvSURF_X24S8,
+ gcvSURF_X24S8_1_A8R8G8B8,
+
+ /* Alpha formats. */
+ gcvSURF_A4 = 700,
+ gcvSURF_A8,
+ gcvSURF_A12,
+ gcvSURF_A16,
+ gcvSURF_A32,
+ gcvSURF_A1,
+
+ /* Luminance formats. */
+ gcvSURF_L4 = 800,
+ gcvSURF_L8,
+ gcvSURF_L12,
+ gcvSURF_L16,
+ gcvSURF_L32,
+ gcvSURF_L1,
+
+ /* Alpha/Luminance formats. */
+ gcvSURF_A4L4 = 900,
+ gcvSURF_A2L6,
+ gcvSURF_A8L8,
+ gcvSURF_A4L12,
+ gcvSURF_A12L12,
+ gcvSURF_A16L16,
+
+ /* Bump formats. */
+ gcvSURF_L6V5U5 = 1000,
+ gcvSURF_V8U8,
+ gcvSURF_X8L8V8U8,
+ gcvSURF_Q8W8V8U8,
+ gcvSURF_A2W10V10U10,
+ gcvSURF_V16U16,
+ gcvSURF_Q16W16V16U16,
+
+ /* R/RG/RA formats. */
+ gcvSURF_R8 = 1100,
+ gcvSURF_X8R8,
+ gcvSURF_G8R8,
+ gcvSURF_X8G8R8,
+ gcvSURF_A8R8,
+ gcvSURF_R16,
+ gcvSURF_X16R16,
+ gcvSURF_G16R16,
+ gcvSURF_X16G16R16,
+ gcvSURF_A16R16,
+ gcvSURF_R32,
+ gcvSURF_X32R32,
+ gcvSURF_G32R32,
+ gcvSURF_X32G32R32,
+ gcvSURF_A32R32,
+ gcvSURF_RG16,
+ gcvSURF_R8_SNORM,
+ gcvSURF_G8R8_SNORM,
+
+ gcvSURF_R8_1_X8R8G8B8,
+ gcvSURF_G8R8_1_X8R8G8B8,
+
+ /* Floating point formats. */
+ gcvSURF_R16F = 1200,
+ gcvSURF_X16R16F,
+ gcvSURF_G16R16F,
+ gcvSURF_X16G16R16F,
+ gcvSURF_B16G16R16F,
+ gcvSURF_X16B16G16R16F,
+ gcvSURF_A16B16G16R16F,
+ gcvSURF_R32F,
+ gcvSURF_X32R32F,
+ gcvSURF_G32R32F,
+ gcvSURF_X32G32R32F,
+ gcvSURF_B32G32R32F,
+ gcvSURF_X32B32G32R32F,
+ gcvSURF_A32B32G32R32F,
+ gcvSURF_A16F,
+ gcvSURF_L16F,
+ gcvSURF_A16L16F,
+ gcvSURF_A16R16F,
+ gcvSURF_A32F,
+ gcvSURF_L32F,
+ gcvSURF_A32L32F,
+ gcvSURF_A32R32F,
+ gcvSURF_E5B9G9R9,
+ gcvSURF_B10G11R11F,
+
+ gcvSURF_X16B16G16R16F_2_A8R8G8B8,
+ gcvSURF_A16B16G16R16F_2_A8R8G8B8,
+ gcvSURF_A16B16G16R16F_2_G16R16F,
+ gcvSURF_G32R32F_2_A8R8G8B8,
+ gcvSURF_X32B32G32R32F_2_G32R32F,
+ gcvSURF_A32B32G32R32F_2_G32R32F,
+ gcvSURF_X32B32G32R32F_4_A8R8G8B8,
+ gcvSURF_A32B32G32R32F_4_A8R8G8B8,
+
+ gcvSURF_R16F_1_A4R4G4B4,
+ gcvSURF_G16R16F_1_A8R8G8B8,
+ gcvSURF_B16G16R16F_2_A8R8G8B8,
+
+ gcvSURF_R32F_1_A8R8G8B8,
+ gcvSURF_B32G32R32F_3_A8R8G8B8,
+ gcvSURF_B10G11R11F_1_A8R8G8B8,
+
+ gcvSURF_A32F_1_R32F,
+ gcvSURF_L32F_1_R32F,
+ gcvSURF_A32L32F_1_G32R32F,
+
+
+
+ /* sRGB format. */
+ gcvSURF_SBGR8 = 1400,
+ gcvSURF_A8_SBGR8,
+ gcvSURF_X8_SBGR8,
+ gcvSURF_A8_SRGB8,
+ gcvSURF_X8_SRGB8,
+
+ /* Integer formats. */
+ gcvSURF_R8I = 1500,
+ gcvSURF_R8UI,
+ gcvSURF_R16I,
+ gcvSURF_R16UI,
+ gcvSURF_R32I,
+ gcvSURF_R32UI,
+ gcvSURF_X8R8I,
+ gcvSURF_G8R8I,
+ gcvSURF_X8R8UI,
+ gcvSURF_G8R8UI,
+ gcvSURF_X16R16I,
+ gcvSURF_G16R16I,
+ gcvSURF_X16R16UI,
+ gcvSURF_G16R16UI,
+ gcvSURF_X32R32I,
+ gcvSURF_G32R32I,
+ gcvSURF_X32R32UI,
+ gcvSURF_G32R32UI,
+ gcvSURF_X8G8R8I,
+ gcvSURF_B8G8R8I,
+ gcvSURF_X8G8R8UI,
+ gcvSURF_B8G8R8UI,
+ gcvSURF_X16G16R16I,
+ gcvSURF_B16G16R16I,
+ gcvSURF_X16G16R16UI,
+ gcvSURF_B16G16R16UI,
+ gcvSURF_X32G32R32I,
+ gcvSURF_B32G32R32I,
+ gcvSURF_X32G32R32UI,
+ gcvSURF_B32G32R32UI,
+ gcvSURF_X8B8G8R8I,
+ gcvSURF_A8B8G8R8I,
+ gcvSURF_X8B8G8R8UI,
+ gcvSURF_A8B8G8R8UI,
+ gcvSURF_X16B16G16R16I,
+ gcvSURF_A16B16G16R16I,
+ gcvSURF_X16B16G16R16UI,
+ gcvSURF_A16B16G16R16UI,
+ gcvSURF_X32B32G32R32I,
+ gcvSURF_A32B32G32R32I,
+ gcvSURF_X32B32G32R32UI,
+ gcvSURF_A32B32G32R32UI,
+ gcvSURF_A2B10G10R10UI,
+ gcvSURF_G32R32I_2_A8R8G8B8,
+ gcvSURF_G32R32I_1_G32R32F,
+ gcvSURF_G32R32UI_2_A8R8G8B8,
+ gcvSURF_G32R32UI_1_G32R32F,
+ gcvSURF_X16B16G16R16I_2_A8R8G8B8,
+ gcvSURF_X16B16G16R16I_1_G32R32F,
+ gcvSURF_A16B16G16R16I_2_A8R8G8B8,
+ gcvSURF_A16B16G16R16I_1_G32R32F,
+ gcvSURF_X16B16G16R16UI_2_A8R8G8B8,
+ gcvSURF_X16B16G16R16UI_1_G32R32F,
+ gcvSURF_A16B16G16R16UI_2_A8R8G8B8,
+ gcvSURF_A16B16G16R16UI_1_G32R32F,
+ gcvSURF_X32B32G32R32I_2_G32R32I,
+ gcvSURF_A32B32G32R32I_2_G32R32I,
+ gcvSURF_A32B32G32R32I_2_G32R32F,
+ gcvSURF_X32B32G32R32I_3_A8R8G8B8,
+ gcvSURF_A32B32G32R32I_4_A8R8G8B8,
+ gcvSURF_X32B32G32R32UI_2_G32R32UI,
+ gcvSURF_A32B32G32R32UI_2_G32R32UI,
+ gcvSURF_A32B32G32R32UI_2_G32R32F,
+ gcvSURF_X32B32G32R32UI_3_A8R8G8B8,
+ gcvSURF_A32B32G32R32UI_4_A8R8G8B8,
+ gcvSURF_A2B10G10R10UI_1_A8R8G8B8,
+ gcvSURF_A8B8G8R8I_1_A8R8G8B8,
+ gcvSURF_A8B8G8R8UI_1_A8R8G8B8,
+ gcvSURF_R8I_1_A4R4G4B4,
+ gcvSURF_R8UI_1_A4R4G4B4,
+ gcvSURF_R16I_1_A4R4G4B4,
+ gcvSURF_R16UI_1_A4R4G4B4,
+ gcvSURF_R32I_1_A8R8G8B8,
+ gcvSURF_R32UI_1_A8R8G8B8,
+ gcvSURF_X8R8I_1_A4R4G4B4,
+ gcvSURF_X8R8UI_1_A4R4G4B4,
+ gcvSURF_G8R8I_1_A4R4G4B4,
+ gcvSURF_G8R8UI_1_A4R4G4B4,
+ gcvSURF_X16R16I_1_A4R4G4B4,
+ gcvSURF_X16R16UI_1_A4R4G4B4,
+ gcvSURF_G16R16I_1_A8R8G8B8,
+ gcvSURF_G16R16UI_1_A8R8G8B8,
+ gcvSURF_X32R32I_1_A8R8G8B8,
+ gcvSURF_X32R32UI_1_A8R8G8B8,
+ gcvSURF_X8G8R8I_1_A4R4G4B4,
+ gcvSURF_X8G8R8UI_1_A4R4G4B4,
+ gcvSURF_B8G8R8I_1_A8R8G8B8,
+ gcvSURF_B8G8R8UI_1_A8R8G8B8,
+ gcvSURF_B16G16R16I_2_A8R8G8B8,
+ gcvSURF_B16G16R16I_1_G32R32F,
+ gcvSURF_B16G16R16UI_2_A8R8G8B8,
+ gcvSURF_B16G16R16UI_1_G32R32F,
+ gcvSURF_B32G32R32I_3_A8R8G8B8,
+ gcvSURF_B32G32R32UI_3_A8R8G8B8,
+ gcvSURF_A16B16G16R16_2_A8R8G8B8,
+ gcvSURF_R8G8B8_1_A8R8G8B8,
+ gcvSURF_G16R16_1_A8R8G8B8,
+ gcvSURF_A2B10G10R10_1_A8R8G8B8,
+ gcvSURF_A2R10G10B10_1_A8R8G8B8,
+ gcvSURF_A2W10V10U10_1_A8R8G8B8,
+
+ /* ASTC formats. */
+ gcvSURF_ASTC4x4 = 1600,
+ gcvSURF_ASTC5x4,
+ gcvSURF_ASTC5x5,
+ gcvSURF_ASTC6x5,
+ gcvSURF_ASTC6x6,
+ gcvSURF_ASTC8x5,
+ gcvSURF_ASTC8x6,
+ gcvSURF_ASTC8x8,
+ gcvSURF_ASTC10x5,
+ gcvSURF_ASTC10x6,
+ gcvSURF_ASTC10x8,
+ gcvSURF_ASTC10x10,
+ gcvSURF_ASTC12x10,
+ gcvSURF_ASTC12x12,
+ gcvSURF_ASTC4x4_SRGB,
+ gcvSURF_ASTC5x4_SRGB,
+ gcvSURF_ASTC5x5_SRGB,
+ gcvSURF_ASTC6x5_SRGB,
+ gcvSURF_ASTC6x6_SRGB,
+ gcvSURF_ASTC8x5_SRGB,
+ gcvSURF_ASTC8x6_SRGB,
+ gcvSURF_ASTC8x8_SRGB,
+ gcvSURF_ASTC10x5_SRGB,
+ gcvSURF_ASTC10x6_SRGB,
+ gcvSURF_ASTC10x8_SRGB,
+ gcvSURF_ASTC10x10_SRGB,
+ gcvSURF_ASTC12x10_SRGB,
+ gcvSURF_ASTC12x12_SRGB,
+
+ /* Recompile format*/
+ gcvSURF_L16_1_A4R4G4B4 = 1700,
+ gcvSURF_V16U16_1_A8R8G8B8,
+ gcvSURF_Q8W8V8U8_1_A8R8G8B8,
+ gcvSURF_X8L8V8U8_1_A8R8G8B8,
+ gcvSURF_R3G3B2_1_A8R8G8B8,
+ gcvSURF_A8R3G3B2_1_A8R8G8B8,
+ gcvSURF_W11V11U10_1_A8R8G8B8,
+ gcvSURF_Q16W16V16U16_2_A8R8G8B8,
+ gcvSURF_W11V11U10,
+ gcvSURF_V8U8_1_A4R4G4B4,
+ gcvSURF_A8B8G8R8_1_A8R8G8B8,
+ gcvSURF_A32R32G32B32_1_A8R8G8B8,
+ gcvSURF_X16B16G16R16F_1_A8R8G8B8,
+ gcvSURF_A16B16G16R16F_1_A8R8G8B8,
+ gcvSURF_G32R32F_1_A8R8G8B8,
+ gcvSURF_X32B32G32R32F_1_A8R8G8B8,
+ gcvSURF_A32B32G32R32F_1_A8R8G8B8,
+ gcvSURF_G32R32I_1_A8R8G8B8,
+ gcvSURF_G32R32UI_1_A8R8G8B8,
+ gcvSURF_A32B32G32R32I_1_A8R8G8B8,
+ gcvSURF_A32B32G32R32UI_1_A8R8G8B8,
+ gcvSURF_Q16W16V16U16_1_A8R8G8B8,
+ gcvSURF_A16B16G16R16_1_A8R8G8B8,
+ gcvSURF_FORMAT_COUNT
+}
+gceSURF_FORMAT;
+
+typedef enum _gceSURF_YUV_COLOR_SPACE
+{
+ gcvSURF_ITU_REC601,
+ gcvSURF_ITU_REC709,
+ gcvSURF_ITU_REC2020,
+}
+gceSURF_YUV_COLOR_SPACE;
+
+typedef enum _gceSURF_YUV_SAMPLE_RANGE
+{
+ gcvSURF_YUV_FULL_RANGE,
+ gcvSURF_YUV_NARROW_RANGE,
+}
+gceSURF_YUV_SAMPLE_RANGE;
+
+typedef enum _gceSURF_YUV_CHROMA_SITING
+{
+ gcvSURF_YUV_CHROMA_SITING_0,
+ gcvSURF_YUV_CHROMA_SITING_0_5,
+}
+gceSURF_YUV_CHROMA_SITING;
+
+typedef enum _gceSURF_INFO_TYPE
+{
+ gcvSURF_INFO_UNKNOWN = 0,
+ gcvSURF_INFO_LAYERSIZE = 1,
+ gcvSURF_INFO_SLICESIZE = 2,
+}
+gceSURF_INFO_TYPE;
+
+/* Format modifiers. */
+typedef enum _gceSURF_FORMAT_MODE
+{
+ gcvSURF_FORMAT_OCL = 0x80000000,
+ gcvSURF_FORMAT_PATCH_BORDER = 0x40000000,
+}
+gceSURF_FORMAT_MODE;
+
+/* Pixel swizzle modes. */
+typedef enum _gceSURF_SWIZZLE
+{
+ gcvSURF_NOSWIZZLE = 0,
+ gcvSURF_ARGB,
+ gcvSURF_ABGR,
+ gcvSURF_RGBA,
+ gcvSURF_BGRA
+}
+gceSURF_SWIZZLE;
+
+/* Transparency modes. */
+typedef enum _gceSURF_TRANSPARENCY
+{
+ /* Valid only for PE 1.0 */
+ gcvSURF_OPAQUE = 0,
+ gcvSURF_SOURCE_MATCH,
+ gcvSURF_SOURCE_MASK,
+ gcvSURF_PATTERN_MASK,
+}
+gceSURF_TRANSPARENCY;
+
+/* Surface Alignment. */
+typedef enum _gceSURF_ALIGNMENT
+{
+ gcvSURF_FOUR = 0,
+ gcvSURF_SIXTEEN,
+ gcvSURF_SUPER_TILED,
+ gcvSURF_SPLIT_TILED,
+ gcvSURF_SPLIT_SUPER_TILED
+}
+gceSURF_ALIGNMENT;
+
+/* Surface Addressing. */
+typedef enum _gceSURF_ADDRESSING
+{
+ gcvSURF_NO_STRIDE_TILED = 0,
+ gcvSURF_NO_STRIDE_LINEAR,
+ gcvSURF_STRIDE_TILED,
+ gcvSURF_STRIDE_LINEAR
+}
+gceSURF_ADDRESSING;
+
+/* Transparency modes. */
+typedef enum _gce2D_TRANSPARENCY
+{
+ /* Valid only for PE 2.0 */
+ gcv2D_OPAQUE = 0,
+ gcv2D_KEYED,
+ gcv2D_MASKED
+}
+gce2D_TRANSPARENCY;
+
+/* Mono packing modes. */
+typedef enum _gceSURF_MONOPACK
+{
+ gcvSURF_PACKED8 = 0,
+ gcvSURF_PACKED16,
+ gcvSURF_PACKED32,
+ gcvSURF_UNPACKED,
+}
+gceSURF_MONOPACK;
+
+/* Blending modes. */
+typedef enum _gceSURF_BLEND_MODE
+{
+ /* Porter-Duff blending modes. */
+ /* Fsrc Fdst */
+ gcvBLEND_CLEAR = 0, /* 0 0 */
+ gcvBLEND_SRC, /* 1 0 */
+ gcvBLEND_DST, /* 0 1 */
+ gcvBLEND_SRC_OVER_DST, /* 1 1 - Asrc */
+ gcvBLEND_DST_OVER_SRC, /* 1 - Adst 1 */
+ gcvBLEND_SRC_IN_DST, /* Adst 0 */
+ gcvBLEND_DST_IN_SRC, /* 0 Asrc */
+ gcvBLEND_SRC_OUT_DST, /* 1 - Adst 0 */
+ gcvBLEND_DST_OUT_SRC, /* 0 1 - Asrc */
+ gcvBLEND_SRC_ATOP_DST, /* Adst 1 - Asrc */
+ gcvBLEND_DST_ATOP_SRC, /* 1 - Adst Asrc */
+ gcvBLEND_SRC_XOR_DST, /* 1 - Adst 1 - Asrc */
+
+ /* Special blending modes. */
+ gcvBLEND_SET, /* DST = 1 */
+ gcvBLEND_SUB /* DST = DST * (1 - SRC) */
+}
+gceSURF_BLEND_MODE;
+
+/* Per-pixel alpha modes. */
+typedef enum _gceSURF_PIXEL_ALPHA_MODE
+{
+ gcvSURF_PIXEL_ALPHA_STRAIGHT = 0,
+ gcvSURF_PIXEL_ALPHA_INVERSED
+}
+gceSURF_PIXEL_ALPHA_MODE;
+
+/* Global alpha modes. */
+typedef enum _gceSURF_GLOBAL_ALPHA_MODE
+{
+ gcvSURF_GLOBAL_ALPHA_OFF = 0,
+ gcvSURF_GLOBAL_ALPHA_ON,
+ gcvSURF_GLOBAL_ALPHA_SCALE
+}
+gceSURF_GLOBAL_ALPHA_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gceSURF_PIXEL_COLOR_MODE
+{
+ gcvSURF_COLOR_STRAIGHT = 0,
+ gcvSURF_COLOR_MULTIPLY
+}
+gceSURF_PIXEL_COLOR_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_PIXEL_COLOR_MULTIPLY_MODE
+{
+ gcv2D_COLOR_MULTIPLY_DISABLE = 0,
+ gcv2D_COLOR_MULTIPLY_ENABLE
+}
+gce2D_PIXEL_COLOR_MULTIPLY_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_GLOBAL_COLOR_MULTIPLY_MODE
+{
+ gcv2D_GLOBAL_COLOR_MULTIPLY_DISABLE = 0,
+ gcv2D_GLOBAL_COLOR_MULTIPLY_ALPHA,
+ gcv2D_GLOBAL_COLOR_MULTIPLY_COLOR
+}
+gce2D_GLOBAL_COLOR_MULTIPLY_MODE;
+
+/* Alpha blending factor modes. */
+typedef enum _gceSURF_BLEND_FACTOR_MODE
+{
+ gcvSURF_BLEND_ZERO = 0,
+ gcvSURF_BLEND_ONE,
+ gcvSURF_BLEND_STRAIGHT,
+ gcvSURF_BLEND_INVERSED,
+ gcvSURF_BLEND_COLOR,
+ gcvSURF_BLEND_COLOR_INVERSED,
+ gcvSURF_BLEND_SRC_ALPHA_SATURATED,
+ gcvSURF_BLEND_STRAIGHT_NO_CROSS,
+ gcvSURF_BLEND_INVERSED_NO_CROSS,
+ gcvSURF_BLEND_COLOR_NO_CROSS,
+ gcvSURF_BLEND_COLOR_INVERSED_NO_CROSS,
+ gcvSURF_BLEND_SRC_ALPHA_SATURATED_CROSS
+}
+gceSURF_BLEND_FACTOR_MODE;
+
+/* Alpha blending porter duff rules. */
+typedef enum _gce2D_PORTER_DUFF_RULE
+{
+ gcvPD_CLEAR = 0,
+ gcvPD_SRC,
+ gcvPD_SRC_OVER,
+ gcvPD_DST_OVER,
+ gcvPD_SRC_IN,
+ gcvPD_DST_IN,
+ gcvPD_SRC_OUT,
+ gcvPD_DST_OUT,
+ gcvPD_SRC_ATOP,
+ gcvPD_DST_ATOP,
+ gcvPD_ADD,
+ gcvPD_XOR,
+ gcvPD_DST
+}
+gce2D_PORTER_DUFF_RULE;
+
+/* Alpha blending factor modes. */
+typedef enum _gce2D_YUV_COLOR_MODE
+{
+ gcv2D_YUV_601= 0,
+ gcv2D_YUV_709,
+ gcv2D_YUV_USER_DEFINED,
+ gcv2D_YUV_USER_DEFINED_CLAMP,
+
+ /* Default setting is for src. gcv2D_YUV_DST
+ can be ORed to set dst.
+ */
+ gcv2D_YUV_DST = 0x80000000,
+}
+gce2D_YUV_COLOR_MODE;
+
+/* Nature rotation rules. */
+typedef enum _gce2D_NATURE_ROTATION
+{
+ gcvNR_0_DEGREE = 0,
+ gcvNR_LEFT_90_DEGREE,
+ gcvNR_RIGHT_90_DEGREE,
+ gcvNR_180_DEGREE,
+ gcvNR_FLIP_X,
+ gcvNR_FLIP_Y,
+ gcvNR_TOTAL_RULE,
+}
+gce2D_NATURE_ROTATION;
+
+typedef enum _gce2D_COMMAND
+{
+ gcv2D_CLEAR = 0,
+ gcv2D_LINE,
+ gcv2D_BLT,
+ gcv2D_STRETCH,
+ gcv2D_HOR_FILTER,
+ gcv2D_VER_FILTER,
+ gcv2D_MULTI_SOURCE_BLT,
+ gcv2D_FILTER_BLT,
+}
+gce2D_COMMAND;
+
+typedef enum _gce2D_TILE_STATUS_CONFIG
+{
+ gcv2D_TSC_DISABLE = 0,
+ gcv2D_TSC_ENABLE = 0x00000001,
+ gcv2D_TSC_COMPRESSED = 0x00000002,
+ gcv2D_TSC_DOWN_SAMPLER = 0x00000004,
+ gcv2D_TSC_2D_COMPRESSED = 0x00000008,
+
+ gcv2D_TSC_DEC_COMPRESSED = 0x00000020,
+ gcv2D_TSC_DEC_TPC = 0x00000040,
+ gcv2D_TSC_DEC_TPC_COMPRESSED = 0x00000080,
+
+ gcv2D_TSC_V4_COMPRESSED = 0x00000100,
+ gcv2D_TSC_V4_COMPRESSED_256B = 0x00000200 | gcv2D_TSC_V4_COMPRESSED,
+
+ gcv2D_TSC_DEC_TPC_TILED = gcv2D_TSC_DEC_COMPRESSED | gcv2D_TSC_DEC_TPC,
+ gcv2D_TSC_DEC_TPC_TILED_COMPRESSED = gcv2D_TSC_DEC_TPC_TILED | gcv2D_TSC_DEC_TPC_COMPRESSED,
+
+ gcv2D_TSC_TPC_COMPRESSED = 0x00001000,
+ gcv2D_TSC_TPC_COMPRESSED_V10 = gcv2D_TSC_TPC_COMPRESSED | 0x00000400,
+ gcv2D_TSC_TPC_COMPRESSED_V11 = gcv2D_TSC_TPC_COMPRESSED | 0x00000800,
+}
+gce2D_TILE_STATUS_CONFIG;
+
+typedef enum _gce2D_QUERY
+{
+ gcv2D_QUERY_RGB_ADDRESS_MIN_ALIGN = 0,
+ gcv2D_QUERY_RGB_STRIDE_MIN_ALIGN,
+ gcv2D_QUERY_YUV_ADDRESS_MIN_ALIGN,
+ gcv2D_QUERY_YUV_STRIDE_MIN_ALIGN,
+}
+gce2D_QUERY;
+
+typedef enum _gce2D_SUPER_TILE_VERSION
+{
+ gcv2D_SUPER_TILE_VERSION_V1 = 1,
+ gcv2D_SUPER_TILE_VERSION_V2 = 2,
+ gcv2D_SUPER_TILE_VERSION_V3 = 3,
+}
+gce2D_SUPER_TILE_VERSION;
+
+typedef enum _gce2D_STATE
+{
+ gcv2D_STATE_SPECIAL_FILTER_MIRROR_MODE = 1,
+ gcv2D_STATE_SUPER_TILE_VERSION,
+ gcv2D_STATE_EN_GAMMA,
+ gcv2D_STATE_DE_GAMMA,
+ gcv2D_STATE_MULTI_SRC_BLIT_UNIFIED_DST_RECT,
+ gcv2D_STATE_MULTI_SRC_BLIT_BILINEAR_FILTER,
+ gcv2D_STATE_PROFILE_ENABLE,
+ gcv2D_STATE_XRGB_ENABLE,
+
+ gcv2D_STATE_ARRAY_EN_GAMMA = 0x10001,
+ gcv2D_STATE_ARRAY_DE_GAMMA,
+ gcv2D_STATE_ARRAY_CSC_YUV_TO_RGB,
+ gcv2D_STATE_ARRAY_CSC_RGB_TO_YUV,
+
+ gcv2D_STATE_DEC_TPC_NV12_10BIT = 0x20001,
+ gcv2D_STATE_ARRAY_YUV_SRC_TILE_STATUS_ADDR,
+ gcv2D_STATE_ARRAY_YUV_DST_TILE_STATUS_ADDR,
+}
+gce2D_STATE;
+
+typedef enum _gce2D_STATE_PROFILE
+{
+ gcv2D_STATE_PROFILE_NONE = 0x0,
+ gcv2D_STATE_PROFILE_COMMAND = 0x1,
+ gcv2D_STATE_PROFILE_SURFACE = 0x2,
+ gcv2D_STATE_PROFILE_ALL = 0xFFFF,
+}
+gce2D_STATE_PROFILE;
+
+/* Texture object types */
+typedef enum _gceTEXTURE_TYPE
+{
+ gcvTEXTURE_UNKNOWN = 0,
+ gcvTEXTURE_1D,
+ gcvTEXTURE_2D,
+ gcvTEXTURE_3D,
+ gcvTEXTURE_CUBEMAP,
+ gcvTEXTURE_1D_ARRAY,
+ gcvTEXTURE_2D_ARRAY,
+ gcvTEXTURE_2D_MS,
+ gcvTEXTURE_2D_MS_ARRAY,
+ gcvTEXTURE_CUBEMAP_ARRAY,
+ gcvTEXTURE_EXTERNAL
+}
+gceTEXTURE_TYPE;
+
+#if gcdENABLE_3D
+/* Texture functions. */
+typedef enum _gceTEXTURE_FUNCTION
+{
+ gcvTEXTURE_DUMMY = 0,
+ gcvTEXTURE_REPLACE = 0,
+ gcvTEXTURE_MODULATE,
+ gcvTEXTURE_ADD,
+ gcvTEXTURE_ADD_SIGNED,
+ gcvTEXTURE_INTERPOLATE,
+ gcvTEXTURE_SUBTRACT,
+ gcvTEXTURE_DOT3
+}
+gceTEXTURE_FUNCTION;
+
+/* Texture sources. */
+typedef enum _gceTEXTURE_SOURCE
+{
+ gcvCOLOR_FROM_TEXTURE = 0,
+ gcvCOLOR_FROM_CONSTANT_COLOR,
+ gcvCOLOR_FROM_PRIMARY_COLOR,
+ gcvCOLOR_FROM_PREVIOUS_COLOR
+}
+gceTEXTURE_SOURCE;
+
+/* Texture source channels. */
+typedef enum _gceTEXTURE_CHANNEL
+{
+ gcvFROM_COLOR = 0,
+ gcvFROM_ONE_MINUS_COLOR,
+ gcvFROM_ALPHA,
+ gcvFROM_ONE_MINUS_ALPHA
+}
+gceTEXTURE_CHANNEL;
+#endif /* gcdENABLE_3D */
+
+/* Filter types. */
+typedef enum _gceFILTER_TYPE
+{
+ gcvFILTER_SYNC = 0,
+ gcvFILTER_BLUR,
+ gcvFILTER_USER
+}
+gceFILTER_TYPE;
+
+/* Filter pass types. */
+typedef enum _gceFILTER_PASS_TYPE
+{
+ gcvFILTER_HOR_PASS = 0,
+ gcvFILTER_VER_PASS
+}
+gceFILTER_PASS_TYPE;
+
+/* Endian hints. */
+typedef enum _gceENDIAN_HINT
+{
+ gcvENDIAN_NO_SWAP = 0,
+ gcvENDIAN_SWAP_WORD,
+ gcvENDIAN_SWAP_DWORD
+}
+gceENDIAN_HINT;
+
+/* Tiling modes. */
+typedef enum _gceTILING
+{
+ gcvINVALIDTILED = 0x0, /* Invalid tiling */
+ /* Tiling basic modes enum'ed in power of 2. */
+ gcvLINEAR = 0x1, /* No tiling. */
+ gcvTILED = 0x2, /* 4x4 tiling. */
+ gcvSUPERTILED = 0x4, /* 64x64 tiling. */
+ gcvMINORTILED = 0x8, /* 2x2 tiling. */
+
+ /* Tiling special layouts. */
+ gcvTILING_SPLIT_BUFFER = 0x10,
+ gcvTILING_X_MAJOR = 0x20,
+ gcvTILING_Y_MAJOR = 0x40,
+ gcvTILING_SWAP = 0x80,
+
+ /* Tiling combination layouts. */
+ gcvMULTI_TILED = gcvTILED
+ | gcvTILING_SPLIT_BUFFER,
+
+ gcvMULTI_SUPERTILED = gcvSUPERTILED
+ | gcvTILING_SPLIT_BUFFER,
+
+ gcvYMAJOR_SUPERTILED = gcvSUPERTILED
+ | gcvTILING_Y_MAJOR,
+
+ gcvTILED_8X4 = 0x0100,
+ gcvTILED_4X8 = 0x0100 | gcvTILING_SWAP,
+ gcvTILED_8X8 = 0x0200,
+ gcvTILED_16X4 = 0x0400,
+ gcvTILED_32X4 = 0x0800,
+ gcvTILED_64X4 = 0x1000,
+
+ gcvTILED_8X8_XMAJOR = gcvTILED_8X8 | gcvTILING_X_MAJOR,
+ gcvTILED_8X8_YMAJOR = gcvTILED_8X8 | gcvTILING_Y_MAJOR,
+
+ gcvSUPERTILED_128B = 0x10000 | gcvSUPERTILED,
+ gcvSUPERTILED_256B = 0x20000 | gcvSUPERTILED,
+}
+gceTILING;
+
+typedef enum _gceCACHE_MODE
+{
+ gcvCACHE_NONE,
+ gcvCACHE_128,
+ gcvCACHE_256,
+}
+gceCACHE_MODE;
+
+#define DEFAULT_CACHE_MODE gcvCACHE_256
+
+/* 2D pattern type. */
+typedef enum _gce2D_PATTERN
+{
+ gcv2D_PATTERN_SOLID = 0,
+ gcv2D_PATTERN_MONO,
+ gcv2D_PATTERN_COLOR,
+ gcv2D_PATTERN_INVALID
+}
+gce2D_PATTERN;
+
+/* 2D source type. */
+typedef enum _gce2D_SOURCE
+{
+ gcv2D_SOURCE_MASKED = 0,
+ gcv2D_SOURCE_MONO,
+ gcv2D_SOURCE_COLOR,
+ gcv2D_SOURCE_INVALID
+}
+gce2D_SOURCE;
+
+/* Pipes. */
+typedef enum _gcePIPE_SELECT
+{
+ gcvPIPE_INVALID = ~0,
+ gcvPIPE_3D = 0,
+ gcvPIPE_2D
+}
+gcePIPE_SELECT;
+
+/* Hardware type. */
+typedef enum _gceHARDWARE_TYPE
+{
+ gcvHARDWARE_INVALID,
+ gcvHARDWARE_3D,
+ gcvHARDWARE_2D,
+ gcvHARDWARE_VG,
+ gcvHARDWARE_3D2D,
+ gcvHARDWARE_NUM_TYPES,
+}
+gceHARDWARE_TYPE;
+
+#define gcdCHIP_COUNT gcvCORE_COUNT
+
+typedef enum _gceMMU_MODE
+{
+ gcvMMU_MODE_1K,
+ gcvMMU_MODE_4K,
+} gceMMU_MODE;
+
+/* User signal command codes. */
+typedef enum _gceUSER_SIGNAL_COMMAND_CODES
+{
+ gcvUSER_SIGNAL_CREATE,
+ gcvUSER_SIGNAL_DESTROY,
+ gcvUSER_SIGNAL_SIGNAL,
+ gcvUSER_SIGNAL_WAIT,
+ gcvUSER_SIGNAL_MAP,
+ gcvUSER_SIGNAL_UNMAP,
+}
+gceUSER_SIGNAL_COMMAND_CODES;
+
+/* Shared buffer command codes. */
+typedef enum _gceSHBUF_COMMAND_CODES
+{
+ gcvSHBUF_CREATE,
+ gcvSHBUF_DESTROY,
+ gcvSHBUF_MAP,
+ gcvSHBUF_WRITE,
+ gcvSHBUF_READ,
+}
+gceSHBUF_COMMAND_CODES;
+
+/* Event locations. */
+typedef enum _gceKERNEL_WHERE
+{
+ gcvKERNEL_COMMAND,
+ gcvKERNEL_VERTEX,
+ gcvKERNEL_TRIANGLE,
+ gcvKERNEL_TEXTURE,
+ gcvKERNEL_PIXEL,
+ gcvKERNEL_BLT,
+}
+gceKERNEL_WHERE;
+
+#if gcdENABLE_VG
+/* Hardware blocks. */
+typedef enum _gceBLOCK
+{
+ gcvBLOCK_COMMAND,
+ gcvBLOCK_TESSELLATOR,
+ gcvBLOCK_TESSELLATOR2,
+ gcvBLOCK_TESSELLATOR3,
+ gcvBLOCK_RASTER,
+ gcvBLOCK_VG,
+ gcvBLOCK_VG2,
+ gcvBLOCK_VG3,
+ gcvBLOCK_PIXEL,
+
+ /* Number of defined blocks. */
+ gcvBLOCK_COUNT
+}
+gceBLOCK;
+#endif
+
+/* gcdDUMP message type. */
+typedef enum _gceDEBUG_MESSAGE_TYPE
+{
+ gcvMESSAGE_TEXT,
+ gcvMESSAGE_DUMP
+}
+gceDEBUG_MESSAGE_TYPE;
+
+/* Shading format. */
+typedef enum _gceSHADING
+{
+ gcvSHADING_SMOOTH,
+ gcvSHADING_FLAT_D3D,
+ gcvSHADING_FLAT_OPENGL,
+}
+gceSHADING;
+
+/* Culling modes. */
+typedef enum _gceCULL
+{
+ gcvCULL_NONE,
+ gcvCULL_CCW,
+ gcvCULL_CW,
+}
+gceCULL;
+
+/* Fill modes. */
+typedef enum _gceFILL
+{
+ gcvFILL_POINT,
+ gcvFILL_WIRE_FRAME,
+ gcvFILL_SOLID,
+}
+gceFILL;
+
+/* Compare modes. */
+typedef enum _gceCOMPARE
+{
+ gcvCOMPARE_INVALID = 0,
+ gcvCOMPARE_NEVER,
+ gcvCOMPARE_NOT_EQUAL,
+ gcvCOMPARE_LESS,
+ gcvCOMPARE_LESS_OR_EQUAL,
+ gcvCOMPARE_EQUAL,
+ gcvCOMPARE_GREATER,
+ gcvCOMPARE_GREATER_OR_EQUAL,
+ gcvCOMPARE_ALWAYS,
+}
+gceCOMPARE;
+
+/* Stencil modes. */
+typedef enum _gceSTENCIL_MODE
+{
+ gcvSTENCIL_NONE,
+ gcvSTENCIL_SINGLE_SIDED,
+ gcvSTENCIL_DOUBLE_SIDED,
+}
+gceSTENCIL_MODE;
+
+/* Stencil operations. */
+typedef enum _gceSTENCIL_OPERATION
+{
+ gcvSTENCIL_KEEP,
+ gcvSTENCIL_REPLACE,
+ gcvSTENCIL_ZERO,
+ gcvSTENCIL_INVERT,
+ gcvSTENCIL_INCREMENT,
+ gcvSTENCIL_DECREMENT,
+ gcvSTENCIL_INCREMENT_SATURATE,
+ gcvSTENCIL_DECREMENT_SATURATE,
+ gcvSTENCIL_OPERATION_INVALID = -1
+}
+gceSTENCIL_OPERATION;
+
+/* Stencil selection. */
+typedef enum _gceSTENCIL_WHERE
+{
+ gcvSTENCIL_FRONT,
+ gcvSTENCIL_BACK,
+}
+gceSTENCIL_WHERE;
+
+/* Texture addressing selection. */
+typedef enum _gceTEXTURE_WHICH
+{
+ gcvTEXTURE_S,
+ gcvTEXTURE_T,
+ gcvTEXTURE_R,
+}
+gceTEXTURE_WHICH;
+
+/* Texture addressing modes. */
+typedef enum _gceTEXTURE_ADDRESSING
+{
+ gcvTEXTURE_INVALID = 0,
+ gcvTEXTURE_CLAMP,
+ gcvTEXTURE_WRAP,
+ gcvTEXTURE_MIRROR,
+ gcvTEXTURE_BORDER,
+ gcvTEXTURE_MIRROR_ONCE,
+}
+gceTEXTURE_ADDRESSING;
+
+/* Texture filters. */
+typedef enum _gceTEXTURE_FILTER
+{
+ gcvTEXTURE_NONE,
+ gcvTEXTURE_POINT,
+ gcvTEXTURE_LINEAR,
+ gcvTEXTURE_ANISOTROPIC,
+}
+gceTEXTURE_FILTER;
+
+typedef enum _gceTEXTURE_COMPONENT
+{
+ gcvTEXTURE_COMPONENT_R,
+ gcvTEXTURE_COMPONENT_G,
+ gcvTEXTURE_COMPONENT_B,
+ gcvTEXTURE_COMPONENT_A,
+
+ gcvTEXTURE_COMPONENT_NUM,
+} gceTEXTURE_COMPONENT;
+
+/* Texture swizzle modes. */
+typedef enum _gceTEXTURE_SWIZZLE
+{
+ gcvTEXTURE_SWIZZLE_R = 0,
+ gcvTEXTURE_SWIZZLE_G,
+ gcvTEXTURE_SWIZZLE_B,
+ gcvTEXTURE_SWIZZLE_A,
+ gcvTEXTURE_SWIZZLE_0,
+ gcvTEXTURE_SWIZZLE_1,
+
+ gcvTEXTURE_SWIZZLE_INVALID,
+} gceTEXTURE_SWIZZLE;
+
+typedef enum _gceTEXTURE_SRGBDECODE
+{
+ gcvTEXTURE_SRGB_INVALID = 0,
+ gcvTEXTURE_DECODE,
+ gcvTEXTURE_SKIP_DECODE,
+}gceTEXTURE_SRGBDECODE;
+
+typedef enum _gceTEXTURE_COMPARE_MODE
+{
+ gcvTEXTURE_COMPARE_MODE_INVALID = 0,
+ gcvTEXTURE_COMPARE_MODE_NONE,
+ gcvTEXTURE_COMPARE_MODE_REF,
+} gceTEXTURE_COMPARE_MODE;
+
+typedef enum _gceTEXTURE_DS_MODE
+{
+ gcvTEXTURE_DS_MODE_INVALID = 0,
+ gcvTEXTURE_DS_MODE_DEPTH = 1,
+ gcvTEXTURE_DS_MODE_STENCIL = 2,
+}gceTEXTURE_DS_MODE;
+
+
+/* Pixel output swizzle modes. */
+typedef enum _gcePIXEL_SWIZZLE
+{
+ gcvPIXEL_SWIZZLE_R = gcvTEXTURE_SWIZZLE_R,
+ gcvPIXEL_SWIZZLE_G = gcvTEXTURE_SWIZZLE_G,
+ gcvPIXEL_SWIZZLE_B = gcvTEXTURE_SWIZZLE_B,
+ gcvPIXEL_SWIZZLE_A = gcvTEXTURE_SWIZZLE_A,
+
+ gcvPIXEL_SWIZZLE_INVALID,
+} gcePIXEL_SWIZZLE;
+
+/* Primitive types. */
+typedef enum _gcePRIMITIVE
+{
+ gcvPRIMITIVE_POINT_LIST,
+ gcvPRIMITIVE_LINE_LIST,
+ gcvPRIMITIVE_LINE_STRIP,
+ gcvPRIMITIVE_LINE_LOOP,
+ gcvPRIMITIVE_TRIANGLE_LIST,
+ gcvPRIMITIVE_TRIANGLE_STRIP,
+ gcvPRIMITIVE_TRIANGLE_FAN,
+ gcvPRIMITIVE_RECTANGLE,
+ gcvPRIMITIVE_LINES_ADJACENCY,
+ gcvPRIMITIVE_LINE_STRIP_ADJACENCY,
+ gcvPRIMITIVE_TRIANGLES_ADJACENCY,
+ gcvPRIMITIVE_TRIANGLE_STRIP_ADJACENCY,
+ gcvPRIMITIVE_PATCH_LIST,
+}
+gcePRIMITIVE;
+
+/* Index types. */
+typedef enum _gceINDEX_TYPE
+{
+ gcvINDEX_8,
+ gcvINDEX_16,
+ gcvINDEX_32,
+}
+gceINDEX_TYPE;
+
+/* Multi GPU rendering modes. */
+typedef enum _gceMULTI_GPU_RENDERING_MODE
+{
+ gcvMULTI_GPU_RENDERING_MODE_OFF,
+ gcvMULTI_GPU_RENDERING_MODE_SPLIT_WIDTH,
+ gcvMULTI_GPU_RENDERING_MODE_SPLIT_HEIGHT,
+ gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_64x64,
+ gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_128x64,
+ gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_128x128,
+ gcvMULTI_GPU_RENDERING_MODE_INVALID
+}
+gceMULTI_GPU_RENDERING_MODE;
+
+typedef enum _gceCORE_3D_MASK
+{
+ gcvCORE_3D_0_MASK = (1 << 0),
+ gcvCORE_3D_1_MASK = (1 << 1),
+
+ gcvCORE_3D_ALL_MASK = (0xFFFF)
+}
+gceCORE_3D_MASK;
+
+typedef enum _gceCORE_3D_ID
+{
+ gcvCORE_3D_0_ID = 0,
+ gcvCORE_3D_1_ID = 1,
+
+ gcvCORE_3D_ID_INVALID = ~0UL
+}
+gceCORE_3D_ID;
+
+typedef enum _gceMULTI_GPU_MODE
+{
+ gcvMULTI_GPU_MODE_COMBINED = 0,
+ gcvMULTI_GPU_MODE_INDEPENDENT = 1
+}
+gceMULTI_GPU_MODE;
+
+typedef enum _gceMACHINECODE
+{
+ gcvMACHINECODE_ANTUTU0 = 0x0,
+
+ gcvMACHINECODE_GLB27_RELEASE_0,
+
+ gcvMACHINECODE_GLB25_RELEASE_0,
+ gcvMACHINECODE_GLB25_RELEASE_1,
+
+ /* keep it as the last enum */
+ gcvMACHINECODE_COUNT
+}
+gceMACHINECODE;
+
+typedef enum _gceUNIFORMCVT
+{
+ gcvUNIFORMCVT_NONE = 0,
+ gcvUNIFORMCVT_TO_BOOL,
+ gcvUNIFORMCVT_TO_FLOAT,
+} gceUNIFORMCVT;
+
+typedef enum _gceHAL_ARG_VERSION
+{
+ gcvHAL_ARG_VERSION_V1 = 0x0,
+ gcvHAL_ARG_VERSION_V2,
+}
+gceHAL_ARG_VERSION;
+
+
+typedef enum _gceCMDBUF_TYPE
+{
+ /* Contiguous command buffer. */
+ gcvCMDBUF_CONTIGUOUS,
+ /* Virtual command buffer. */
+ gcvCMDBUF_VIRTUAL,
+ /* Command buffer allocated from reserved memory. */
+ gcvCMDBUF_RESERVED,
+}
+gceCMDBUF_SOURCE;
+
+typedef enum _gceCHIP_FLAG
+{
+ gcvCHIP_FLAG_MSAA_COHERENCEY_ECO_FIX = 1 << 0,
+ gcvCHIP_FLAG_GC2000_R2 = 1 << 1,
+}
+gceCHIP_FLAG;
+
+typedef enum
+{
+ gcvENGINE_RENDER = 0,
+ gcvENGINE_BLT = 1,
+ gcvENGINE_COUNT = 2,
+}
+gceENGINE;
+
+/* CORE enum. */
+typedef enum _gceCORE
+{
+ gcvCORE_MAJOR,
+ gcvCORE_3D1,
+ gcvCORE_3D2,
+ gcvCORE_3D3,
+ gcvCORE_3D4,
+ gcvCORE_3D5,
+ gcvCORE_3D6,
+ gcvCORE_3D7,
+ gcvCORE_3D_MAX = gcvCORE_3D7,
+ gcvCORE_2D,
+ gcvCORE_VG,
+#if gcdDEC_ENABLE_AHB
+ gcvCORE_DEC,
+#endif
+ gcvCORE_COUNT
+}
+gceCORE;
+
+
+typedef enum _gceADDRESS_AREA
+{
+ gcvADDRESS_AREA_NORMAL,
+ gcvADDRESS_AREA_SECURE,
+
+ gcvADDRESS_AREA_COUNT
+}
+gceADDRESS_AREA;
+
+typedef enum _gceSECURE_MODE
+{
+ /* For cores without gcvFEATURE_SECURITY. */
+ gcvSECURE_NONE,
+
+ /* Use registers added in gcvFEATURE_SECURITY in normal driver,
+ ** In this mode, GPU always works under non secure mode and
+ ** should not touch secure buffer. It is used to test basic function.
+ */
+ gcvSECURE_IN_NORMAL,
+
+ /* Make use of gcvFEATURE_SECURITY in trust application. */
+ gcvSECURE_IN_TA
+}
+gceSECURE_MODE;
+
+/*
+* Bit of a requirement is 1 means requirement is a must, 0 means requirement can
+* be ignored.
+*/
+#define gcvALLOC_FLAG_CONTIGUOUS_BIT 0
+#define gcvALLOC_FLAG_CACHEABLE_BIT 1
+#define gcvALLOC_FLAG_SECURITY_BIT 2
+#define gcvALLOC_FLAG_NON_CONTIGUOUS_BIT 3
+#define gcvALLOC_FLAG_MEMLIMIT_BIT 4
+#define gcvALLOC_FLAG_DMABUF_BIT 5
+#define gcvALLOC_FLAG_USERMEMORY_BIT 6
+#define gcvALLOC_FLAG_EXTERNAL_MEMORY_BIT 7
+#define gcvALLOC_FLAG_ALLOC_ON_FAULT_BIT 8
+#define gcvALLOC_FLAG_CMA_LIMIT_BIT 9
+
+/* No special needs. */
+#define gcvALLOC_FLAG_NONE (0)
+/* Physical contiguous. */
+#define gcvALLOC_FLAG_CONTIGUOUS (1 << gcvALLOC_FLAG_CONTIGUOUS_BIT)
+/* Can be remapped as cacheable. */
+#define gcvALLOC_FLAG_CACHEABLE (1 << gcvALLOC_FLAG_CACHEABLE_BIT)
+/* Secure buffer. */
+#define gcvALLOC_FLAG_SECURITY (1 << gcvALLOC_FLAG_SECURITY_BIT)
+/* Physical non contiguous. */
+#define gcvALLOC_FLAG_NON_CONTIGUOUS (1 << gcvALLOC_FLAG_NON_CONTIGUOUS_BIT)
+#define gcvALLOC_FLAG_MEMLIMIT (1 << gcvALLOC_FLAG_MEMLIMIT_BIT)
+
+/* Import DMABUF. */
+#define gcvALLOC_FLAG_DMABUF (1 << gcvALLOC_FLAG_DMABUF_BIT)
+/* Import USERMEMORY. */
+#define gcvALLOC_FLAG_USERMEMORY (1 << gcvALLOC_FLAG_USERMEMORY_BIT)
+/* Import an External Buffer. */
+#define gcvALLOC_FLAG_EXTERNAL_MEMORY (1 << gcvALLOC_FLAG_EXTERNAL_MEMORY_BIT)
+
+/* Real allocation happens when GPU page fault. */
+#define gcvALLOC_FLAG_ALLOC_ON_FAULT (1 << gcvALLOC_FLAG_ALLOC_ON_FAULT_BIT)
+
+/* CMA allocator only */
+#define gcvALLOC_FLAG_CMA_LIMIT (1 << gcvALLOC_FLAG_CMA_LIMIT_BIT)
+
+/* GL_VIV internal usage */
+#ifndef GL_MAP_BUFFER_OBJ_VIV
+#define GL_MAP_BUFFER_OBJ_VIV 0x10000
+#endif
+
+/* Command buffer usage. */
+#define gcvCOMMAND_2D (1 << 0)
+#define gcvCOMMAND_3D (1 << 1)
+
+/* Default chip ID means chip ID same as core index. */
+#define gcvCHIP_ID_DEFAULT (~0U)
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gckCONTEXT * gckCONTEXT;
+typedef struct _gcoCMDBUF * gcoCMDBUF;
+
+typedef struct _gcsSTATE_DELTA * gcsSTATE_DELTA_PTR;
+typedef struct _gcsQUEUE * gcsQUEUE_PTR;
+typedef struct _gcoQUEUE * gcoQUEUE;
+typedef struct _gcsHAL_INTERFACE * gcsHAL_INTERFACE_PTR;
+typedef struct _gcs2D_PROFILE * gcs2D_PROFILE_PTR;
+
+
+#if gcdENABLE_VG
+typedef struct _gcoVGHARDWARE * gcoVGHARDWARE;
+typedef struct _gcoVGBUFFER * gcoVGBUFFER;
+typedef struct _gckVGHARDWARE * gckVGHARDWARE;
+typedef struct _gcsVGCONTEXT * gcsVGCONTEXT_PTR;
+typedef struct _gcsVGCONTEXT_MAP * gcsVGCONTEXT_MAP_PTR;
+typedef struct _gcsVGCMDQUEUE * gcsVGCMDQUEUE_PTR;
+typedef struct _gcsTASK_MASTER_TABLE * gcsTASK_MASTER_TABLE_PTR;
+typedef struct _gckVGKERNEL * gckVGKERNEL;
+typedef void * gctTHREAD;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_enum_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h
new file mode 100644
index 000000000000..1c62781528e9
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_kernel_buffer.h
@@ -0,0 +1,289 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_buffer_h_
+#define __gc_hal_kernel_buffer_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+************************ Command Buffer and Event Objects **********************
+\******************************************************************************/
+
+/* The number of context buffers per user. */
+#define gcdCONTEXT_BUFFER_COUNT 2
+
+#define gcdRENDER_FENCE_LENGTH (6 * gcmSIZEOF(gctUINT32))
+#define gcdBLT_FENCE_LENGTH (10 * gcmSIZEOF(gctUINT32))
+#define gcdRESERVED_FLUSHCACHE_LENGTH (2 * gcmSIZEOF(gctUINT32))
+#define gcdRESERVED_PAUSE_OQ_LENGTH (2 * gcmSIZEOF(gctUINT32))
+#define gcdRESERVED_PAUSE_XFBWRITTEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
+#define gcdRESERVED_PAUSE_PRIMGEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
+#define gcdRESERVED_PAUSE_XFB_LENGTH (2 * gcmSIZEOF(gctUINT32))
+#define gcdRESERVED_HW_FENCE (4 * gcmSIZEOF(gctUINT32))
+#define gcdRESERVED_PAUSE_PROBE_LENGTH (TOTAL_PROBE_NUMBER * 2 * gcmSIZEOF(gctUINT32))
+
+#define gcdRESUME_OQ_LENGTH (2 * gcmSIZEOF(gctUINT32))
+#define gcdRESUME_XFBWRITTEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
+#define gcdRESUME_PRIMGEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
+#define gcdRESUME_XFB_LENGH (2 * gcmSIZEOF(gctUINT32))
+#define gcdRESUME_PROBE_LENGH (TOTAL_PROBE_NUMBER * 2 * gcmSIZEOF(gctUINT32))
+
+
+/* State delta record. */
+typedef struct _gcsSTATE_DELTA_RECORD * gcsSTATE_DELTA_RECORD_PTR;
+typedef struct _gcsSTATE_DELTA_RECORD
+{
+ /* State address. */
+ gctUINT address;
+
+ /* State mask. */
+ gctUINT32 mask;
+
+ /* State data. */
+ gctUINT32 data;
+}
+gcsSTATE_DELTA_RECORD;
+
+/* State delta. */
+typedef struct _gcsSTATE_DELTA
+{
+ /* For debugging: the number of delta in the order of creation. */
+ gctUINT num;
+
+ /* Main state delta ID. Every time state delta structure gets reinitialized,
+ main ID is incremented. If main state ID overflows, all map entry IDs get
+ reinitialized to make sure there is no potential erroneous match after
+ the overflow.*/
+ gctUINT id;
+
+ /* The number of contexts pending modification by the delta. */
+ gctINT refCount;
+
+ /* Vertex element count for the delta buffer. */
+ gctUINT elementCount;
+
+ /* Number of states currently stored in the record array. */
+ gctUINT recordCount;
+
+ /* Record array; holds all modified states in gcsSTATE_DELTA_RECORD. */
+ gctUINT64 recordArray;
+
+ /* Map entry ID is used for map entry validation. If map entry ID does not
+ match the main state delta ID, the entry and the corresponding state are
+ considered not in use. */
+ gctUINT64 mapEntryID;
+ gctUINT mapEntryIDSize;
+
+ /* If the map entry ID matches the main state delta ID, index points to
+ the state record in the record array. */
+ gctUINT64 mapEntryIndex;
+
+ /* Previous and next state deltas in gcsSTATE_DELTA. */
+ gctUINT64 prev;
+ gctUINT64 next;
+}
+gcsSTATE_DELTA;
+
+#define gcdPATCH_LIST_SIZE 1024
+
+/* Command buffer patch record. */
+typedef struct _gcsPATCH
+{
+ /* Handle of a video memory node. */
+ gctUINT32 handle;
+
+ /* Flag */
+ gctUINT32 flag;
+}
+gcsPATCH;
+
+/* List of patches for the command buffer. */
+typedef struct _gcsPATCH_LIST
+{
+ /* Array of patch records. */
+ struct _gcsPATCH patch[gcdPATCH_LIST_SIZE];
+
+ /* Number of patches in the array. */
+ gctUINT count;
+
+ /* Next item in the list. */
+ struct _gcsPATCH_LIST *next;
+}
+gcsPATCH_LIST;
+
+/* Command buffer object. */
+struct _gcoCMDBUF
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Commit count. */
+ gctUINT64 commitCount;
+
+ /* Command buffer entry and exit pipes. */
+ gcePIPE_SELECT entryPipe;
+ gcePIPE_SELECT exitPipe;
+
+ /* Feature usage flags. */
+ gctBOOL using2D;
+ gctBOOL using3D;
+
+ /* Size of reserved tail for each commit. */
+ gctUINT32 reservedTail;
+
+ /* Physical address of command buffer. Just a name. */
+ gctUINT32 physical;
+
+ /* Logical address of command buffer. */
+ gctUINT64 logical;
+
+ /* Number of bytes in command buffer. */
+ gctUINT32 bytes;
+
+ /* Start offset into the command buffer. */
+ gctUINT32 startOffset;
+
+ /* Current offset into the command buffer. */
+ gctUINT32 offset;
+
+ /* Number of free bytes in command buffer. */
+ gctUINT32 free;
+
+ /* Location of the last reserved area. */
+ gctUINT64 lastReserve;
+ gctUINT32 lastOffset;
+
+#if gcdSECURE_USER
+ /* Hint array for the current command buffer. */
+ gctUINT hintArraySize;
+ gctUINT64 hintArray;
+ gctUINT64 hintArrayTail;
+#endif
+
+ /* Last load state command location and hardware address. */
+ gctUINT64 lastLoadStatePtr;
+ gctUINT32 lastLoadStateAddress;
+ gctUINT32 lastLoadStateCount;
+
+ /* List of patches. */
+ gctUINT64 patchHead;
+
+ /* Link to next gcoCMDBUF object in one commit. */
+ gctUINT64 nextCMDBUF;
+
+ /*
+ * Put pointer type member after this line.
+ */
+
+ /* Completion signal. */
+ gctSIGNAL signal;
+
+ /* Link to the siblings. */
+ gcoCMDBUF prev;
+ gcoCMDBUF next;
+
+ /* Mirror command buffer(s). */
+ gcoCMDBUF *mirrors;
+ gctUINT32 mirrorCount;
+};
+
+typedef struct _gcsQUEUE
+{
+ /* Pointer to next gcsQUEUE structure in gcsQUEUE. */
+ gctUINT64 next;
+
+ /* Event information. */
+ gcsHAL_INTERFACE iface;
+}
+gcsQUEUE;
+
+/* Event queue. */
+struct _gcoQUEUE
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to current event queue. */
+ gcsQUEUE_PTR head;
+ gcsQUEUE_PTR tail;
+
+ /* chunks of the records. */
+ gctPOINTER chunks;
+
+ /* List of free records. */
+ gcsQUEUE_PTR freeList;
+
+ #define gcdIN_QUEUE_RECORD_LIMIT 16
+ /* Number of records currently in queue */
+ gctUINT32 recordCount;
+
+ gceENGINE engine;
+};
+
+struct _gcsTEMPCMDBUF
+{
+ gctUINT32 currentByteSize;
+ gctPOINTER buffer;
+ gctBOOL inUse;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_buffer_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h
new file mode 100644
index 000000000000..8b3539730f7b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_mem.h
@@ -0,0 +1,564 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+/*
+** Include file for the local memory management.
+*/
+
+#ifndef __gc_hal_mem_h_
+#define __gc_hal_mem_h_
+#if (gcdENABLE_3D || gcdENABLE_VG)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+** Usage:
+
+ The macros to declare MemPool type and functions are
+ gcmMEM_DeclareFSMemPool (Type, TypeName, Prefix)
+ gcmMEM_DeclareVSMemPool (Type, TypeName, Prefix)
+ gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix)
+
+ The data structures for MemPool are
+ typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
+ typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
+ typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
+
+ The MemPool constructor and destructor functions are
+ gcfMEM_InitFSMemPool(gcsMEM_FS_MEM_POOL *, gcoOS, gctUINT, gctUINT);
+ gcfMEM_FreeFSMemPool(gcsMEM_FS_MEM_POOL *);
+ gcfMEM_InitVSMemPool(gcsMEM_VS_MEM_POOL *, gcoOS, gctUINT, gctBOOL);
+ gcfMEM_FreeVSMemPool(gcsMEM_VS_MEM_POOL *);
+ gcfMEM_InitAFSMemPool(gcsMEM_AFS_MEM_POOL *, gcoOS, gctUINT);
+ gcfMEM_FreeAFSMemPool(gcsMEM_AFS_MEM_POOL *);
+
+ FS: for Fixed-Size data structures
+ VS: for Variable-size data structures
+ AFS: for Array of Fixed-Size data structures
+
+
+ // Example 1: For a fixed-size data structure, struct gcsNode.
+ // It is used locally in a file, so the functions are static without prefix.
+ // At top level, declear allocate and free functions.
+ // The first argument is the data type.
+ // The second armument is the short name used in the fuctions.
+ gcmMEM_DeclareFSMemPool(struct gcsNode, Node, );
+
+ // The previous macro creates two inline functions,
+ // _AllocateNode and _FreeNode.
+
+ // In function or struct
+ gcsMEM_FS_MEM_POOL nodeMemPool;
+
+ // In function,
+ struct gcsNode * node;
+ gceSTATUS status;
+
+ // Before using the memory pool, initialize it.
+ // The second argument is the gcoOS object.
+ // The third argument is the number of data structures to allocate for each chunk.
+ status = gcfMEM_InitFSMemPool(&nodeMemPool, os, 100, sizeof(struct gcsNode));
+ ...
+
+ // Allocate a node.
+ status = _AllocateNode(nodeMemPool, &node);
+ ...
+ // Free a node.
+ _FreeNode(nodeMemPool, node);
+
+ // After using the memory pool, free it.
+ gcfMEM_FreeFSMemPool(&nodeMemPool);
+
+
+ // Example 2: For array of fixed-size data structures, struct gcsNode.
+ // It is used in several files, so the functions are extern with prefix.
+ // At top level, declear allocate and free functions.
+ // The first argument is the data type, and the second one is the short name
+ // used in the fuctions.
+ gcmMEM_DeclareAFSMemPool(struct gcsNode, NodeArray, gcfOpt);
+
+ // The previous macro creates two inline functions,
+ // gcfOpt_AllocateNodeArray and gcfOpt_FreeNodeArray.
+
+ // In function or struct
+ gcsMEM_AFS_MEM_POOL nodeArrayMemPool;
+
+ // In function,
+ struct gcsNode * nodeArray;
+ gceSTATUS status;
+
+ // Before using the array memory pool, initialize it.
+ // The second argument is the gcoOS object, the third is the number of data
+ // structures to allocate for each chunk.
+ status = gcfMEM_InitAFSMemPool(&nodeArrayMemPool, os, sizeof(struct gcsNode));
+ ...
+
+ // Allocate a node array of size 100.
+ status = gcfOpt_AllocateNodeArray(nodeArrayMemPool, &nodeArray, 100);
+ ...
+ // Free a node array.
+ gcfOpt_FreeNodeArray(&nodeArrayMemPool, nodeArray);
+
+ // After using the array memory pool, free it.
+ gcfMEM_FreeAFSMemPool(&nodeArrayMemPool);
+
+*******************************************************************************/
+
+/*******************************************************************************
+** To switch back to use gcoOS_Allocate and gcoOS_Free, add
+** #define USE_LOCAL_MEMORY_POOL 0
+** before including this file.
+*******************************************************************************/
+#ifndef USE_LOCAL_MEMORY_POOL
+/*
+ USE_LOCAL_MEMORY_POOL
+
+ This define enables the local memory management to improve performance.
+*/
+#define USE_LOCAL_MEMORY_POOL 1
+#endif
+
+/*******************************************************************************
+** Memory Pool Data Structures
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+ typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
+ typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
+ typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
+#else
+ typedef gcoOS gcsMEM_FS_MEM_POOL;
+ typedef gcoOS gcsMEM_VS_MEM_POOL;
+ typedef gcoOS gcsMEM_AFS_MEM_POOL;
+#endif
+
+/*******************************************************************************
+** Memory Pool Macros
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName##List( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * FirstPointer, \
+ Type * LastPointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x FirstPointer=0x%x LastPointer=0x%x", MemPool, FirstPointer, LastPointer); \
+ status = gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status;\
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+ status = gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+ Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+ gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pinter); \
+ status = gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+ status = gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+ gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#else
+
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcoOS_Allocate(MemPool, \
+ gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+ status = gcoOS_Allocate(MemPool, \
+ Size, \
+ (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ Size, \
+ (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+ status = gcoOS_Allocate(MemPool, \
+ Count * gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer); \
+ gcmFOOTER(); \
+ return status; \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ Count * gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+ gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
+ gcmFOOTER(); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
+ status = gcmOS_SAFE_FREE(MemPool, Pointer); \
+ gcmFOOTER(); \
+ return status; \
+}
+#endif
+
+/*******************************************************************************
+** Memory Pool Data Functions
+*******************************************************************************/
+gceSTATUS
+gcfMEM_InitFSMemPool(
+ IN gcsMEM_FS_MEM_POOL * MemPool,
+ IN gcoOS OS,
+ IN gctUINT NodeCount,
+ IN gctUINT NodeSize
+ );
+
+gceSTATUS
+gcfMEM_FreeFSMemPool(
+ IN gcsMEM_FS_MEM_POOL * MemPool
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolGetANode(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeANode(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeAList(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ IN gctPOINTER FirstNode,
+ IN gctPOINTER LastNode
+ );
+
+gceSTATUS
+gcfMEM_InitVSMemPool(
+ IN gcsMEM_VS_MEM_POOL * MemPool,
+ IN gcoOS OS,
+ IN gctUINT BlockSize,
+ IN gctBOOL RecycleFreeNode
+ );
+
+gceSTATUS
+gcfMEM_FreeVSMemPool(
+ IN gcsMEM_VS_MEM_POOL * MemPool
+ );
+
+gceSTATUS
+gcfMEM_VSMemPoolGetANode(
+ IN gcsMEM_VS_MEM_POOL MemPool,
+ IN gctUINT Size,
+ IN gctUINT Alignment,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_VSMemPoolFreeANode(
+ IN gcsMEM_VS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+gceSTATUS
+gcfMEM_InitAFSMemPool(
+ IN gcsMEM_AFS_MEM_POOL *MemPool,
+ IN gcoOS OS,
+ IN gctUINT NodeCount,
+ IN gctUINT NodeSize
+ );
+
+gceSTATUS
+gcfMEM_FreeAFSMemPool(
+ IN gcsMEM_AFS_MEM_POOL *MemPool
+ );
+
+gceSTATUS
+gcfMEM_AFSMemPoolGetANode(
+ IN gcsMEM_AFS_MEM_POOL MemPool,
+ IN gctUINT Count,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_AFSMemPoolFreeANode(
+ IN gcsMEM_AFS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (gcdENABLE_3D || gcdENABLE_VG) */
+#endif /* __gc_hal_mem_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
new file mode 100644
index 000000000000..c293202553ef
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
@@ -0,0 +1,1422 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_options_h_
+#define __gc_hal_options_h_
+
+/*
+ gcdSECURITY
+
+*/
+#ifndef gcdSECURITY
+# define gcdSECURITY 0
+#endif
+
+/*
+ gcdPRINT_VERSION
+
+ Print HAL version.
+*/
+#ifndef gcdPRINT_VERSION
+# define gcdPRINT_VERSION 0
+#endif
+
+/*
+USE_KERNEL_VIRTUAL_BUFFERS
+
+This define enables the use of VM for gckCommand and fence buffers.
+*/
+#ifndef USE_KERNEL_VIRTUAL_BUFFERS
+#if defined(UNDER_CE)
+# define USE_KERNEL_VIRTUAL_BUFFERS 1
+#else
+# define USE_KERNEL_VIRTUAL_BUFFERS 0
+#endif
+#endif
+
+/*
+ USE_NEW_LINUX_SIGNAL
+
+ This define enables the Linux kernel signaling between kernel and user.
+*/
+#ifndef USE_NEW_LINUX_SIGNAL
+# define USE_NEW_LINUX_SIGNAL 0
+#endif
+
+/*
+ VIVANTE_PROFILER
+
+ This define enables the profiler.
+*/
+#ifndef VIVANTE_PROFILER
+# define VIVANTE_PROFILER 1
+#endif
+
+/*
+ VIVANTE_PROFILER_CONTEXT
+
+ This define enables the profiler according each context.
+*/
+#ifndef VIVANTE_PROFILER_CONTEXT
+# define VIVANTE_PROFILER_CONTEXT 1
+#endif
+
+#ifndef VIVANTE_PROFILER_PERDRAW
+# define VIVANTE_PROFILER_PERDRAW 0
+#endif
+
+#ifndef VIVANTE_PROFILER_PROBE
+# define VIVANTE_PROFILER_PROBE_PERDRAW 0
+# define VIVANTE_PROFILER_PROBE 0
+#endif
+
+#ifndef VIVANTE_PROFILER_MULTI_GPU
+# define VIVANTE_PROFILER_MULTI_GPU 0
+#endif
+
+#ifndef VIVANTE_PROFILER_ALL_COUNTER
+# define VIVANTE_PROFILER_ALL_COUNTER 0
+#endif
+
+#ifndef VIVANTE_PROFILER_PM
+# define VIVANTE_PROFILER_PM 1
+#endif
+
+/*
+ gcdUSE_VG
+
+ Enable VG HAL layer (only for GC350).
+*/
+#ifndef gcdUSE_VG
+# define gcdUSE_VG 0
+#endif
+
+/*
+ gcdUSE_VX
+
+ Enable VX HAL layer.
+*/
+#ifndef gcdUSE_VX
+# define gcdUSE_VX 1
+#endif
+
+/*
+ PROFILE_HAL_COUNTERS
+
+ This define enables HAL counter profiling support. HW and SHADER
+ counter profiling depends on this.
+*/
+#ifndef PROFILE_HAL_COUNTERS
+# define PROFILE_HAL_COUNTERS 1
+#endif
+
+/*
+ PROFILE_HW_COUNTERS
+
+ This define enables HW counter profiling support.
+*/
+#ifndef PROFILE_HW_COUNTERS
+# define PROFILE_HW_COUNTERS 1
+#endif
+
+/*
+ PROFILE_SHADER_COUNTERS
+
+ This define enables SHADER counter profiling support.
+*/
+#ifndef PROFILE_SHADER_COUNTERS
+# define PROFILE_SHADER_COUNTERS 1
+#endif
+
+/*
+ COMMAND_PROCESSOR_VERSION
+
+ The version of the command buffer and task manager.
+*/
+#define COMMAND_PROCESSOR_VERSION 1
+
+/*
+ gcdDUMP_KEY
+
+ Set this to a string that appears in 'cat /proc/<pid>/cmdline'. E.g. 'camera'.
+ HAL will create dumps for the processes matching this key.
+*/
+#ifndef gcdDUMP_KEY
+# define gcdDUMP_KEY "process"
+#endif
+
+/*
+ gcdDUMP_PATH
+
+ The dump file location. Some processes cannot write to the sdcard.
+ Try apps' data dir, e.g. /data/data/com.android.launcher
+*/
+#ifndef gcdDUMP_PATH
+#if defined(ANDROID)
+# define gcdDUMP_PATH "/mnt/sdcard/"
+#else
+# define gcdDUMP_PATH "./"
+#endif
+#endif
+
+/*
+ gcdDUMP
+
+ When set to 1, a dump of all states and memory uploads, as well as other
+ hardware related execution will be printed to the debug console. This
+ data can be used for playing back applications.
+
+ When set to 2, for vxc, all output memory will be dump.
+
+*/
+#ifndef gcdDUMP
+# define gcdDUMP 0
+#endif
+
+/*
+ gcdDUMP_API
+
+ When set to 1, a high level dump of the EGL and GL/VG APs's are
+ captured.
+*/
+#ifndef gcdDUMP_API
+# define gcdDUMP_API 0
+#endif
+
+/*
+ gcdDUMP_AHB_ACCESS
+
+ When set to 1, a dump of all AHB register access will be printed to kernel
+ message.
+*/
+#ifndef gcdDUMP_AHB_ACCESS
+# define gcdDUMP_AHB_ACCESS 0
+#endif
+
+/*
+ gcdDEBUG_OPTION
+ When set to 1, the debug options are enabled. We must set other MACRO to enable
+ sub case.
+*/
+#ifndef gcdDEBUG_OPTION
+# define gcdDEBUG_OPTION 0
+
+#if gcdDEBUG_OPTION
+/*
+ gcdDEBUG_OPTION_KEY
+ The process name of debug application.
+*/
+#ifndef gcdDEBUG_OPTION_KEY
+# define gcdDEBUG_OPTION_KEY "process"
+# endif
+/*
+ gcdDEBUG_OPTION_NO_GL_DRAWS
+ When set to 1, all glDrawArrays and glDrawElements will be skip.
+*/
+#ifndef gcdDEBUG_OPTION_NO_GL_DRAWS
+# define gcdDEBUG_OPTION_NO_GL_DRAWS 0
+# endif
+/*
+ gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES
+ When set to 1, all DrawPrimitives will be skip.
+*/
+#ifndef gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES
+# define gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES 0
+# endif
+/*
+ gcdDEBUG_OPTION_SKIP_SWAP
+ When set to 1, just one out of gcdDEBUG_OPTION_SKIP_FRAMES(such as 1/10) eglSwapBuffers will be resolve,
+ others skip.
+*/
+#ifndef gcdDEBUG_OPTION_SKIP_SWAP
+# define gcdDEBUG_OPTION_SKIP_SWAP 0
+# define gcdDEBUG_OPTION_SKIP_FRAMES 10
+# endif
+/*
+ gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET
+ When set to 1, the format of render target will force to RGB565.
+*/
+#ifndef gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET
+# define gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET 0
+# endif
+/*
+ gcdDEBUG_OPTION_NONE_TEXTURE
+ When set to 1, the type of texture will be set to AQ_TEXTURE_SAMPLE_MODE_TYPE_NONE.
+*/
+#ifndef gcdDEBUG_OPTION_NONE_TEXTURE
+# define gcdDEBUG_OPTION_NONE_TEXTURE 0
+# endif
+/*
+ gcdDEBUG_OPTION_NONE_DEPTH
+ When set to 1, the depth format of surface will be set to gcvSURF_UNKNOWN.
+*/
+#ifndef gcdDEBUG_OPTION_NONE_DEPTH
+# define gcdDEBUG_OPTION_NONE_DEPTH 0
+# endif
+
+/*
+ gcdDEBUG_FORCE_CONTEXT_UPDATE
+ When set to 1, context will be updated before every commit.
+*/
+#ifndef gcdDEBUG_FORCE_CONTEXT_UPDATE
+# define gcdDEBUG_FORCE_CONTEXT_UPDATE 0
+# endif
+
+
+/*
+ gcdDEBUG_FORCE_CONTEXT_UPDATE
+ When set to 1, pool of each type surface can be specified by
+ changing poolPerType[] in gcsSURF_NODE_Construct.
+*/
+#ifndef gcdDEBUG_OPTION_SPECIFY_POOL
+# define gcdDEBUG_OPTION_SPECIFY_POOL 0
+# endif
+
+# endif
+#endif
+
+/*
+ gcdDUMP_VERIFY_PER_DRAW
+
+ When set to 1, verify RT and images(if used) for every single draw to ease simulation debug.
+ Only valid for ES3 driver for now.
+*/
+#ifndef gcdDUMP_VERIFY_PER_DRAW
+# define gcdDUMP_VERIFY_PER_DRAW 0
+#endif
+
+
+
+/*
+ gcdDUMP_FRAMERATE
+ When set to a value other than zero, averaqe frame rate will be dumped.
+ The value set is the starting frame that the average will be calculated.
+ This is needed because sometimes first few frames are too slow to be included
+ in the average. Frame count starts from 1.
+*/
+#ifndef gcdDUMP_FRAMERATE
+# define gcdDUMP_FRAMERATE 0
+#endif
+
+/*
+ gcdENABLE_FSCALE_VAL_ADJUST
+ When non-zero, FSCALE_VAL when gcvPOWER_ON can be adjusted externally.
+ */
+#ifndef gcdENABLE_FSCALE_VAL_ADJUST
+# define gcdENABLE_FSCALE_VAL_ADJUST 1
+#endif
+
+/*
+ gcdDUMP_IN_KERNEL
+
+ When set to 1, all dumps will happen in the kernel. This is handy if
+ you want the kernel to dump its command buffers as well and the data
+ needs to be in sync.
+*/
+#ifndef gcdDUMP_IN_KERNEL
+# define gcdDUMP_IN_KERNEL 0
+#endif
+
+/*
+ gcdDUMP_COMMAND
+
+ When set to non-zero, the command queue will dump all incoming command
+ and context buffers as well as all other modifications to the command
+ queue.
+*/
+#ifndef gcdDUMP_COMMAND
+# define gcdDUMP_COMMAND 0
+#endif
+
+/*
+ gcdDUMP_2D
+
+ When set to non-zero, it will dump the 2D command and surface.
+*/
+#ifndef gcdDUMP_2D
+# define gcdDUMP_2D 0
+#endif
+
+/*
+ gcdDUMP_FRAME_TGA
+
+ When set to a value other than 0, a dump of the frame specified by the value,
+ will be done into frame.tga. Frame count starts from 1.
+ */
+#ifndef gcdDUMP_FRAME_TGA
+# define gcdDUMP_FRAME_TGA 0
+#endif
+/*
+ gcdNULL_DRIVER
+
+ Set to 1 for infinite speed hardware.
+ Set to 2 for bypassing the HAL.
+ Set to 3 for bypassing the drivers.
+*/
+#ifndef gcdNULL_DRIVER
+# define gcdNULL_DRIVER 0
+#endif
+
+/*
+ gcdENABLE_TIMEOUT_DETECTION
+
+ Enable timeout detection.
+*/
+#ifndef gcdENABLE_TIMEOUT_DETECTION
+# define gcdENABLE_TIMEOUT_DETECTION 0
+#endif
+
+/*
+ gcdCMD_BUFFER_SIZE
+
+ Number of bytes in a command buffer.
+*/
+#ifndef gcdCMD_BUFFER_SIZE
+# define gcdCMD_BUFFER_SIZE (128 << 10)
+#endif
+
+/*
+ gcdCMD_BLT_BUFFER_SIZE
+
+ Number of bytes in a command buffer.
+*/
+#ifndef gcdCMD_BLT_BUFFER_SIZE
+# define gcdCMD_BLT_BUFFER_SIZE (1 << 10)
+#endif
+
+/*
+ gcdCMD_BUFFERS
+
+ Number of command buffers to use per client.
+*/
+#ifndef gcdCMD_BUFFERS
+# define gcdCMD_BUFFERS 2
+#endif
+
+/*
+ gcdMAX_CMD_BUFFERS
+
+ Maximum number of command buffers to use per client.
+*/
+#ifndef gcdMAX_CMD_BUFFERS
+# define gcdMAX_CMD_BUFFERS 8
+#endif
+
+/*
+ gcdCOMMAND_QUEUES
+
+ Number of command queues in the kernel.
+*/
+#ifndef gcdCOMMAND_QUEUES
+# define gcdCOMMAND_QUEUES 2
+#endif
+
+/*
+ gcdPOWER_CONTROL_DELAY
+
+ The delay in milliseconds required to wait until the GPU has woke up
+ from a suspend or power-down state. This is system dependent because
+ the bus clock also needs to stabalize.
+*/
+#ifndef gcdPOWER_CONTROL_DELAY
+# define gcdPOWER_CONTROL_DELAY 0
+#endif
+
+/*
+ gcdMMU_SIZE
+
+ Size of the MMU page table in bytes. Each 4 bytes can hold 4kB worth of
+ virtual data.
+*/
+#ifndef gcdMMU_SIZE
+# define gcdMMU_SIZE (2048 << 10)
+#endif
+
+#ifndef gcdGC355_VGMMU_MEMORY_SIZE_KB
+# define gcdGC355_VGMMU_MEMORY_SIZE_KB 32
+#endif
+/*
+ gcdSECURE_USER
+
+ Use logical addresses instead of physical addresses in user land. In
+ this case a hint table is created for both command buffers and context
+ buffers, and that hint table will be used to patch up those buffers in
+ the kernel when they are ready to submit.
+*/
+#ifndef gcdSECURE_USER
+# define gcdSECURE_USER 0
+#endif
+
+/*
+ gcdSECURE_CACHE_SLOTS
+
+ Number of slots in the logical to DMA address cache table. Each time a
+ logical address needs to be translated into a DMA address for the GPU,
+ this cache will be walked. The replacement scheme is LRU.
+*/
+#ifndef gcdSECURE_CACHE_SLOTS
+# define gcdSECURE_CACHE_SLOTS 1024
+#endif
+
+/*
+ gcdSECURE_CACHE_METHOD
+
+ Replacement scheme used for Secure Cache. The following options are
+ available:
+
+ gcdSECURE_CACHE_LRU
+ A standard LRU cache.
+
+ gcdSECURE_CACHE_LINEAR
+ A linear walker with the idea that an application will always
+ render the scene in a similar way, so the next entry in the
+ cache should be a hit most of the time.
+
+ gcdSECURE_CACHE_HASH
+ A 256-entry hash table.
+
+ gcdSECURE_CACHE_TABLE
+ A simple cache but with potential of a lot of cache replacement.
+*/
+#ifndef gcdSECURE_CACHE_METHOD
+# define gcdSECURE_CACHE_METHOD gcdSECURE_CACHE_HASH
+#endif
+
+/*
+ gcdREGISTER_ACCESS_FROM_USER
+
+ Set to 1 to allow IOCTL calls to get through from user land. This
+ should only be in debug or development drops.
+*/
+#ifndef gcdREGISTER_ACCESS_FROM_USER
+# define gcdREGISTER_ACCESS_FROM_USER 1
+#endif
+
+/*
+ gcdHEAP_SIZE
+
+ Set the allocation size for the internal heaps. Each time a heap is
+ full, a new heap will be allocated with this minmimum amount of bytes.
+ The bigger this size, the fewer heaps there are to allocate, the better
+ the performance. However, heaps won't be freed until they are
+ completely free, so there might be some more memory waste if the size is
+ too big.
+*/
+#ifndef gcdHEAP_SIZE
+# define gcdHEAP_SIZE (64 << 10)
+#endif
+
+/*
+ gcdPOWER_SUSPEND_WHEN_IDLE
+
+ Set to 1 to make GPU enter gcvPOWER_SUSPEND when idle detected,
+ otherwise GPU will enter gcvPOWER_IDLE.
+*/
+#ifndef gcdPOWER_SUSPEND_WHEN_IDLE
+# define gcdPOWER_SUSPEND_WHEN_IDLE 1
+#endif
+
+#ifndef gcdFPGA_BUILD
+# define gcdFPGA_BUILD 0
+#endif
+
+/*
+ gcdGPU_TIMEOUT
+
+ This define specified the number of milliseconds the system will wait
+ before it broadcasts the GPU is stuck. In other words, it will define
+ the timeout of any operation that needs to wait for the GPU.
+
+ If the value is 0, no timeout will be checked for.
+*/
+#ifndef gcdGPU_TIMEOUT
+#if gcdFPGA_BUILD
+# define gcdGPU_TIMEOUT (3600 * 1000)
+# else
+# define gcdGPU_TIMEOUT 20000
+# endif
+#endif
+
+/*
+ gcdGPU_2D_TIMEOUT
+
+ This define specified the number of milliseconds the system will wait
+ before it broadcasts the 2D GPU is stuck. In other words, it will define
+ the timeout of any operation that needs to wait for the GPU.
+
+ If the value is 0, no timeout will be checked for.
+*/
+#ifndef gcdGPU_2D_TIMEOUT
+#if gcdFPGA_BUILD
+# define gcdGPU_2D_TIMEOUT (gcdGPU_TIMEOUT / 5)
+# else
+# define gcdGPU_2D_TIMEOUT 4000
+# endif
+#endif
+
+
+/*
+ gcdGPU_ADVANCETIMER
+
+ it is advance timer.
+*/
+#ifndef gcdGPU_ADVANCETIMER
+# define gcdGPU_ADVANCETIMER 250
+#endif
+
+/*
+ gcdSTATIC_LINK
+
+ This define disalbes static linking;
+*/
+#ifndef gcdSTATIC_LINK
+# define gcdSTATIC_LINK 0
+#endif
+
+/*
+ gcdUSE_NEW_HEAP
+
+ Setting this define to 1 enables new heap.
+*/
+#ifndef gcdUSE_NEW_HEAP
+# define gcdUSE_NEW_HEAP 0
+#endif
+
+/*
+ gcdCMD_NO_2D_CONTEXT
+
+ This define enables no-context 2D command buffer.
+*/
+#ifndef gcdCMD_NO_2D_CONTEXT
+# define gcdCMD_NO_2D_CONTEXT 1
+#endif
+
+/*
+ gcdENABLE_BUFFER_ALIGNMENT
+
+ When enabled, video memory is allocated with atleast 16KB aligment
+ between multiple sub-buffers.
+*/
+#ifndef gcdENABLE_BUFFER_ALIGNMENT
+# define gcdENABLE_BUFFER_ALIGNMENT 1
+#endif
+
+/*
+ gcdENABLE_BANK_ALIGNMENT
+
+ When enabled, video memory is allocated bank aligned. The vendor can modify
+ _GetSurfaceBankAlignment() and _GetBankOffsetBytes() to define how
+ different types of allocations are bank and channel aligned.
+ When disabled (default), no bank alignment is done.
+*/
+#ifndef gcdENABLE_BANK_ALIGNMENT
+# define gcdENABLE_BANK_ALIGNMENT 0
+#endif
+
+/*
+ gcdBANK_BIT_START
+
+ Specifies the start bit of the bank (inclusive).
+*/
+#ifndef gcdBANK_BIT_START
+# define gcdBANK_BIT_START 12
+#endif
+
+/*
+ gcdBANK_BIT_END
+
+ Specifies the end bit of the bank (inclusive).
+*/
+#ifndef gcdBANK_BIT_END
+# define gcdBANK_BIT_END 14
+#endif
+
+/*
+ gcdBANK_CHANNEL_BIT
+
+ When set, video memory when allocated bank aligned is allocated such that
+ render and depth buffer addresses alternate on the channel bit specified.
+ This option has an effect only when gcdENABLE_BANK_ALIGNMENT is enabled.
+ When disabled (default), no alteration is done.
+*/
+#ifndef gcdBANK_CHANNEL_BIT
+# define gcdBANK_CHANNEL_BIT 7
+#endif
+
+/*
+ gcdDYNAMIC_SPEED
+
+ When non-zero, it informs the kernel driver to use the speed throttling
+ broadcasting functions to inform the system the GPU should be spet up or
+ slowed down. It will send a broadcast for slowdown each "interval"
+ specified by this define in milliseconds
+ (gckOS_BroadcastCalibrateSpeed).
+*/
+#ifndef gcdDYNAMIC_SPEED
+# define gcdDYNAMIC_SPEED 2000
+#endif
+
+/*
+ gcdDYNAMIC_EVENT_THRESHOLD
+
+ When non-zero, it specifies the maximum number of available events at
+ which the kernel driver will issue a broadcast to speed up the GPU
+ (gckOS_BroadcastHurry).
+*/
+#ifndef gcdDYNAMIC_EVENT_THRESHOLD
+# define gcdDYNAMIC_EVENT_THRESHOLD 5
+#endif
+
+/*
+ gcdENABLE_PROFILING
+
+ Enable profiling macros.
+*/
+#ifndef gcdENABLE_PROFILING
+# define gcdENABLE_PROFILING 0
+#endif
+
+/*
+ gcdENABLE_128B_MERGE
+
+ Enable 128B merge for the BUS control.
+*/
+#ifndef gcdENABLE_128B_MERGE
+# define gcdENABLE_128B_MERGE 0
+#endif
+
+/*
+ gcdFRAME_DB
+
+ When non-zero, it specified the number of frames inside the frame
+ database. The frame DB will collect per-frame timestamps and hardware
+ counters.
+*/
+#ifndef gcdFRAME_DB
+# define gcdFRAME_DB 0
+# define gcdFRAME_DB_RESET 0
+# define gcdFRAME_DB_NAME "/var/log/frameDB.log"
+#endif
+
+/*
+ gcdPAGED_MEMORY_CACHEABLE
+
+ When non-zero, paged memory will be cacheable.
+
+ Normally, driver will detemines whether a video memory
+ is cacheable or not. When cacheable is not neccessary,
+ it will be writecombine.
+
+ This option is only for those SOC which can't enable
+ writecombine without enabling cacheable.
+*/
+#ifndef gcdPAGED_MEMORY_CACHEABLE
+# define gcdPAGED_MEMORY_CACHEABLE 0
+#endif
+
+/*
+ gcdNONPAGED_MEMORY_CACHEABLE
+
+ When non-zero, non paged memory will be cacheable.
+*/
+#ifndef gcdNONPAGED_MEMORY_CACHEABLE
+# define gcdNONPAGED_MEMORY_CACHEABLE 0
+#endif
+
+/*
+ gcdNONPAGED_MEMORY_BUFFERABLE
+
+ When non-zero, non paged memory will be bufferable.
+ gcdNONPAGED_MEMORY_BUFFERABLE and gcdNONPAGED_MEMORY_CACHEABLE
+ can't be set 1 at same time
+*/
+#ifndef gcdNONPAGED_MEMORY_BUFFERABLE
+# define gcdNONPAGED_MEMORY_BUFFERABLE 1
+#endif
+
+/*
+ gcdENABLE_INFINITE_SPEED_HW
+ enable the Infinte HW , this is for 2D openVG
+*/
+#ifndef gcdENABLE_INFINITE_SPEED_HW
+# define gcdENABLE_INFINITE_SPEED_HW 0
+#endif
+
+/*
+ gcdPOWEROFF_TIMEOUT
+
+ When non-zero, GPU will power off automatically from
+ idle state, and gcdPOWEROFF_TIMEOUT is also the default
+ timeout in milliseconds.
+ */
+#ifndef gcdPOWEROFF_TIMEOUT
+# define gcdPOWEROFF_TIMEOUT 300
+#endif
+
+/*
+ QNX_SINGLE_THREADED_DEBUGGING
+*/
+#ifndef QNX_SINGLE_THREADED_DEBUGGING
+# define QNX_SINGLE_THREADED_DEBUGGING 0
+#endif
+
+/*
+ gcdSHARED_RESOLVE_BUFFER_ENABLED
+
+ Use shared resolve buffer for all app buffers.
+*/
+#ifndef gcdSHARED_RESOLVE_BUFFER_ENABLED
+# define gcdSHARED_RESOLVE_BUFFER_ENABLED 0
+#endif
+
+/*
+ gcdUSE_TRIANGLE_STRIP_PATCH
+ */
+#ifndef gcdUSE_TRIANGLE_STRIP_PATCH
+# define gcdUSE_TRIANGLE_STRIP_PATCH 1
+#endif
+
+/*
+ gcdPROCESS_ADDRESS_SPACE
+
+ When non-zero, every process which attaches to galcore has its own GPU
+ address space, size of which is gcdPROCESS_ADDRESS_SPACE_SIZE.
+*/
+#ifndef gcdPROCESS_ADDRESS_SPACE
+# define gcdPROCESS_ADDRESS_SPACE 0
+# define gcdPROCESS_ADDRESS_SPACE_SIZE 0x80000000
+#endif
+
+/*
+ gcdSHARED_PAGETABLE
+
+ When non-zero, multiple GPUs in one chip with same MMU use
+ one shared pagetable. So that when accessing same surface,
+ they can use same GPU virtual address.
+*/
+#ifndef gcdSHARED_PAGETABLE
+# define gcdSHARED_PAGETABLE 0
+#endif
+
+#ifndef gcdUSE_PVR
+# define gcdUSE_PVR 1
+#endif
+
+/*
+ gcdSMALL_BLOCK_SIZE
+
+ When non-zero, a part of VIDMEM will be reserved for requests
+ whose requesting size is less than gcdSMALL_BLOCK_SIZE.
+
+ For Linux, it's the size of a page. If this requeset fallbacks
+ to gcvPOOL_CONTIGUOUS or gcvPOOL_VIRTUAL, memory will be wasted
+ because they allocate a page at least.
+*/
+#ifndef gcdSMALL_BLOCK_SIZE
+# define gcdSMALL_BLOCK_SIZE 4096
+# define gcdRATIO_FOR_SMALL_MEMORY 32
+#endif
+
+/*
+ gcdCONTIGUOUS_SIZE_LIMIT
+ When non-zero, size of video node from gcvPOOL_CONTIGUOUS is
+ limited by gcdCONTIGUOUS_SIZE_LIMIT.
+*/
+#ifndef gcdCONTIGUOUS_SIZE_LIMIT
+# define gcdCONTIGUOUS_SIZE_LIMIT 0
+#endif
+
+/*
+ gcdLINK_QUEUE_SIZE
+
+ When non-zero, driver maintains a queue to record information of
+ latest lined context buffer and command buffer. Data in this queue
+ is be used to debug.
+*/
+#ifndef gcdLINK_QUEUE_SIZE
+# define gcdLINK_QUEUE_SIZE 64
+#endif
+
+/* gcdALPHA_KILL_IN_SHADER
+
+ Enable alpha kill inside the shader. This will be set automatically by the
+ HAL if certain states match a criteria.
+*/
+#ifndef gcdALPHA_KILL_IN_SHADER
+# define gcdALPHA_KILL_IN_SHADER 1
+#endif
+
+
+
+/*
+ gcdDVFS
+
+ When non-zero, software will make use of dynamic voltage and
+ frequency feature.
+ */
+#ifndef gcdDVFS
+# define gcdDVFS 0
+# define gcdDVFS_ANAYLSE_WINDOW 4
+# define gcdDVFS_POLLING_TIME (gcdDVFS_ANAYLSE_WINDOW * 4)
+#endif
+
+#ifndef gcdSYNC
+# define gcdSYNC 1
+#endif
+
+#ifndef gcdSHADER_SRC_BY_MACHINECODE
+# define gcdSHADER_SRC_BY_MACHINECODE 1
+#endif
+
+#ifndef gcdGLB27_SHADER_REPLACE_OPTIMIZATION
+# define gcdGLB27_SHADER_REPLACE_OPTIMIZATION 1
+#endif
+
+
+/*
+ gcdSUPPORT_SWAP_RECTANGLE
+
+ Support swap with a specific rectangle.
+
+ Set the rectangle with eglSetSwapRectangleVIV api.
+ Android only.
+*/
+#ifndef gcdSUPPORT_SWAP_RECTANGLE
+# define gcdSUPPORT_SWAP_RECTANGLE 1
+#endif
+
+/*
+ gcdGPU_LINEAR_BUFFER_ENABLED
+
+ Use linear buffer for GPU apps so HWC can do 2D composition.
+ Android only.
+*/
+#ifndef gcdGPU_LINEAR_BUFFER_ENABLED
+# define gcdGPU_LINEAR_BUFFER_ENABLED 1
+#endif
+
+/*
+ gcdENABLE_RENDER_INTO_WINDOW
+
+ Enable Render-Into-Window (ie, No-Resolve) feature on android.
+ NOTE that even if enabled, it still depends on hardware feature and
+ android application behavior. When hardware feature or application
+ behavior can not support render into window mode, it will fail back
+ to normal mode.
+ When Render-Into-Window is finally used, window back buffer of android
+ applications will be allocated matching render target tiling format.
+ Otherwise buffer tiling is decided by the above option
+ 'gcdGPU_LINEAR_BUFFER_ENABLED'.
+ Android only for now.
+*/
+#ifndef gcdENABLE_RENDER_INTO_WINDOW
+# define gcdENABLE_RENDER_INTO_WINDOW 1
+#endif
+
+/*
+ gcdENABLE_RENDER_INTO_WINDOW_WITH_FC
+
+ Enable Direct-rendering (ie, No-Resolve) with tile status.
+ This is expremental and in development stage.
+ This will dynamically check if color compression is available.
+*/
+#ifndef gcdENABLE_RENDER_INTO_WINDOW_WITH_FC
+# define gcdENABLE_RENDER_INTO_WINDOW_WITH_FC 0
+#endif
+
+/*
+ gcdENABLE_BLIT_BUFFER_PRESERVE
+
+ Render-Into-Window (ie, No-Resolve) does not include preserved swap
+ behavior. This feature can enable buffer preserve in No-Resolve mode.
+ When enabled, previous buffer (may be part of ) will be resolve-blitted
+ to current buffer.
+*/
+#ifndef gcdENABLE_BLIT_BUFFER_PRESERVE
+# define gcdENABLE_BLIT_BUFFER_PRESERVE 1
+#endif
+
+/*
+ gcdANDROID_NATIVE_FENCE_SYNC
+
+ Enable android native fence sync. It is introduced since jellybean-4.2.
+ Depends on linux kernel option: CONFIG_SYNC.
+
+ 0: Disabled
+ 1: Build framework for native fence sync feature, and EGL extension
+ 2: Enable async swap buffers for client
+ * Native fence sync for client 'queueBuffer' in EGL, which is
+ 'acquireFenceFd' for layer in compositor side.
+ 3. Enable async hwcomposer composition.
+ * 'releaseFenceFd' for layer in compositor side, which is native
+ fence sync when client 'dequeueBuffer'
+ * Native fence sync for compositor 'queueBuffer' in EGL, which is
+ 'acquireFenceFd' for framebuffer target for DC
+ */
+#ifndef gcdANDROID_NATIVE_FENCE_SYNC
+# define gcdANDROID_NATIVE_FENCE_SYNC 0
+#endif
+
+/*
+ gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
+
+ Enable implicit android native buffer sync.
+
+ For non-HW_RENDER buffer, CPU (or other hardware) and GPU can access
+ the buffer at the same time. This is to add implicit synchronization
+ between CPU (or the hardware) and GPU.
+
+ Eventually, please do not use implicit native buffer sync, but use
+ "fence sync" or "android native fence sync" instead in libgui, which
+ can be enabled in frameworks/native/libs/gui/Android.mk. This kind
+ of synchronization should be done by app but not driver itself.
+
+ Please disable this option when either "fence sync" or
+ "android native fence sync" is enabled.
+ */
+#ifndef gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
+# define gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC 1
+#endif
+
+/*
+ * Implicit native buffer sync is not needed when ANDROID_native_fence_sync
+ * is available.
+ */
+#if gcdANDROID_NATIVE_FENCE_SYNC
+# undef gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
+# define gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC 0
+#endif
+
+/*
+ gcdUSE_WCLIP_PATCH
+
+ Enable wclipping patch.
+*/
+#ifndef gcdUSE_WCLIP_PATCH
+# define gcdUSE_WCLIP_PATCH 1
+#endif
+
+#ifndef gcdUSE_NPOT_PATCH
+# define gcdUSE_NPOT_PATCH 1
+#endif
+
+/*
+ gcdINTERNAL_COMMENT
+
+ Wrap internal comment, content wrapped by it and the macor itself
+ will be removed in release driver.
+*/
+#ifndef gcdINTERNAL_COMMENT
+# define gcdINTERNAL_COMMENT 1
+#endif
+
+/*
+ gcdRTT_DISABLE_FC
+
+ Disable RTT FC support. For test only.
+*/
+#ifndef gcdRTT_DISABLE_FC
+# define gcdRTT_DISABLE_FC 0
+#endif
+
+/*
+ gcdFORCE_MIPMAP
+
+ Force generate mipmap for texture.
+*/
+#ifndef gcdFORCE_MIPMAP
+# define gcdFORCE_MIPMAP 0
+#endif
+
+/*
+ gcdFORCE_BILINEAR
+
+ Force bilinear for mipfilter.
+*/
+#ifndef gcdFORCE_BILINEAR
+# define gcdFORCE_BILINEAR 1
+#endif
+
+/*
+ gcdBINARY_TRACE
+
+ When non-zero, binary trace will be generated.
+
+ When gcdBINARY_TRACE_FILE_SIZE is non-zero, binary trace buffer will
+ be written to a file which size is limited to
+ gcdBINARY_TRACE_FILE_SIZE.
+*/
+#ifndef gcdBINARY_TRACE
+# define gcdBINARY_TRACE 0
+# define gcdBINARY_TRACE_FILE_SIZE 0
+#endif
+
+#ifndef gcdMOVG
+# define gcdMOVG 0
+# define gcdENABLE_TS_DOUBLE_BUFFER 1
+#else
+#if gcdMOVG
+# define gcdENABLE_TS_DOUBLE_BUFFER 0
+#else
+# define gcdENABLE_TS_DOUBLE_BUFFER 1
+#endif
+#endif
+
+/* gcdINTERRUPT_STATISTIC
+ *
+ * Monitor the event send to GPU and interrupt issued by GPU.
+ */
+
+#ifndef gcdINTERRUPT_STATISTIC
+#if defined(LINUX) || defined(__QNXNTO__) || defined(UNDER_CE)
+# define gcdINTERRUPT_STATISTIC 1
+#else
+# define gcdINTERRUPT_STATISTIC 0
+#endif
+#endif
+
+/*
+ gcdFENCE_WAIT_LOOP_COUNT
+ Wait fence, loop count.
+*/
+#ifndef gcdFENCE_WAIT_LOOP_COUNT
+# define gcdFENCE_WAIT_LOOP_COUNT 100
+#endif
+
+/*
+ gcdPARTIAL_FAST_CLEAR
+ When it's not zero, partial fast clear is enabled.
+ Depends on gcdHAL_3D_DRAWBLIT, if gcdHAL_3D_DRAWBLIT is not enabled,
+ only available when scissor box is completely aligned.
+ Expremental, under test.
+*/
+#ifndef gcdPARTIAL_FAST_CLEAR
+# define gcdPARTIAL_FAST_CLEAR 1
+#endif
+
+/*
+ gcdREMOVE_SURF_ORIENTATION
+ When it's not zero, we will remove surface orientation function.
+ It wil become to a parameter of resolve function.
+*/
+#ifndef gcdREMOVE_SURF_ORIENTATION
+# define gcdREMOVE_SURF_ORIENTATION 1
+#endif
+
+
+
+/*
+ gcdTEST_DEC200
+ Test part for DEC200. Remove when release.
+*/
+#ifndef gcdTEST_DEC200
+# define gcdTEST_DEC200 0
+#endif
+
+/*
+ gcdPATTERN_FAST_PATH
+ For pattern match
+*/
+#ifndef gcdPATTERN_FAST_PATH
+# define gcdPATTERN_FAST_PATH 1
+#endif
+
+/*
+ gcdUSE_INPUT_DEVICE
+ disable input devices usage under fb mode to support fb+vdk multi-process
+*/
+#ifndef gcdUSE_INPUT_DEVICE
+# define gcdUSE_INPUT_DEVICE 0
+#endif
+
+/*
+ gcdPERFORMANCE_ANALYSIS
+
+ When set to 1, driver will pass information through loadstate
+ to HW. This loadstate does not impact HW execution.
+*/
+#ifndef gcdPERFORMANCE_ANALYSIS
+# define gcdPERFORMANCE_ANALYSIS 0
+#endif
+
+/*
+ gcdFRAMEINFO_STATISTIC
+ When enable, collect frame information.
+*/
+#ifndef gcdFRAMEINFO_STATISTIC
+
+#if (defined(DBG) && DBG) || defined(DEBUG) || \
+ defined(_DEBUG) || gcdDUMP || gcdPERFORMANCE_ANALYSIS || \
+ (defined(WIN32) && !defined(UNDER_CE)) || \
+ gcdFPGA_BUILD
+
+# define gcdFRAMEINFO_STATISTIC 1
+#else
+# define gcdFRAMEINFO_STATISTIC 0
+#endif
+
+#endif
+
+/*
+ gcdDEC_ENABLE_AHB
+ Enable DEC300 compression AHB mode or not.
+*/
+#ifndef gcdDEC_ENABLE_AHB
+# define gcdDEC_ENABLE_AHB 0
+#endif
+
+/*
+ gcdENABLE_UNIFIED_CONSTANT
+ Enable unified constant or not.
+*/
+#ifndef gcdENABLE_UNIFIED_CONSTANT
+# define gcdENABLE_UNIFIED_CONSTANT 1
+#endif
+
+/*
+ Core configurations. By default enable all cores.
+*/
+#ifndef gcdENABLE_3D
+# define gcdENABLE_3D 1
+#endif
+
+#ifndef gcdENABLE_2D
+# define gcdENABLE_2D 1
+#endif
+
+#ifndef gcdENABLE_VG
+# define gcdENABLE_VG 1
+#endif
+
+#ifndef gcdVG_ONLY
+# define gcdVG_ONLY (!gcdENABLE_3D && !gcdENABLE_2D && gcdENABLE_VG)
+#endif
+
+#if defined(WIN32) && !defined(UNDER_CE) && (gcdENABLE_VG == 1)
+
+#ifdef gcdUSE_VX
+#undef gcdUSE_VX
+#endif
+
+#ifdef COMMAND_PROCESSOR_VERSION
+#undef COMMAND_PROCESSOR_VERSION
+#endif
+
+#ifdef gcdENABLE_TRUST_APPLICATION
+#undef gcdENABLE_TRUST_APPLICATION
+#endif
+
+#ifdef gcdENABLE_3D
+#undef gcdENABLE_3D
+#endif
+
+#ifdef gcdENABLE_2D
+#undef gcdENABLE_2D
+#endif
+
+#define gcdENABLE_3D 0
+#define gcdENABLE_2D 0
+#define gcdUSE_VX 0
+#define COMMAND_PROCESSOR_VERSION 2
+#define gcdENABLE_TRUST_APPLICATION 0
+
+#endif /* Only for GC355 Cmodel build. */
+
+#ifndef gcdGC355_PROFILER
+# define gcdGC355_PROFILER 0
+#endif
+
+#ifndef gcdGC355_MEM_PRINT
+# define gcdGC355_MEM_PRINT 0
+#else
+#if (!((gcdENABLE_3D == 0) && (gcdENABLE_2D == 0) && (gcdENABLE_VG == 1)))
+# undef gcdGC355_MEM_PRINT
+# define gcdGC355_MEM_PRINT 0
+# endif
+#endif
+
+
+/*
+ gcdRECORD_COMMAND
+*/
+#ifndef gcdRECORD_COMMAND
+# define gcdRECORD_COMMAND 0
+#endif
+
+/*
+ gcdALLOC_CMD_FROM_RESERVE
+
+ Provide a way by which location of command buffer can be
+ specified. This is a DEBUG option to limit command buffer
+ to some memory range.
+*/
+#ifndef gcdALLOC_CMD_FROM_RESERVE
+# define gcdALLOC_CMD_FROM_RESERVE 0
+#endif
+
+/*
+ gcdBOUNDARY_CHECK
+
+ When enabled, add bounary before and after a range of
+ GPU address. So overflow can be trapped by MMU exception.
+ This is a debug option for new MMU and gcdUSE_MMU_EXCEPTION
+ is enabled.
+*/
+#ifndef gcdBOUNDARY_CHECK
+# define gcdBOUNDARY_CHECK 0
+#endif
+
+/*
+ gcdRENDER_QUALITY_CHECK
+
+ When enabled, we disable performance opt patch
+ to get know rendering quality comparing with other vendor.
+*/
+#ifndef gcdRENDER_QUALITY_CHECK
+# define gcdRENDER_QUALITY_CHECK 0
+#endif
+
+/*
+ gcdSYSTRACE
+
+ When enabled, we embed systrace in function header/footer
+ to gather time information on linux platforms include android.
+ '1' to trace API (EGL, ES11, ES2x, ES3x, etc)
+ '2' to trace HAL (except compiler)
+ '4' to trace HAL compiler
+ See gc_hal_user_debug.c for more detailed trace zones.
+*/
+#ifndef gcdSYSTRACE
+# define gcdSYSTRACE 0
+#endif
+
+#ifndef gcdENABLE_APPCTXT_BLITDRAW
+# define gcdENABLE_APPCTXT_BLITDRAW 0
+#endif
+
+/*
+ gcdENABLE_TRUST_APPLICATION
+
+ When enabled, trust application is used to handle 'security' registers.
+
+ 1) If HW doesn't have robust and security feature, this option is meaningless.
+ 2) If HW have robust and security and this option is not enable,
+ security registers are handled by non secure driver. It is for
+ platform doesn't want/need to use trust zone.
+*/
+#ifndef gcdENABLE_TRUST_APPLICATION
+#if (defined(_WIN32) && !defined(UNDER_CE)) || (defined (LINUX) && !defined(EMULATOR))
+# define gcdENABLE_TRUST_APPLICATION 1
+#else
+# define gcdENABLE_TRUST_APPLICATION 0
+#endif
+#endif
+
+/* Disable gcdENABLE_TRUST_APPLICATION when oboslete gcdSECURITY enabled. */
+#if gcdSECURITY
+#undef gcdENABLE_TRUST_APPLICATION
+#define gcdENABLE_TRUST_APPLICATION 0
+#endif
+
+#ifndef gcdMMU_SECURE_AREA_SIZE
+# define gcdMMU_SECURE_AREA_SIZE 128
+#endif
+
+/*
+VIV:gcdUSE_MMU_EXCEPTION
+
+ When enabled, enable and check exception interrupt raised by MMU.
+*/
+#ifndef gcdUSE_MMU_EXCEPTION
+# define gcdUSE_MMU_EXCEPTION 1
+#endif
+
+#ifndef gcdVX_OPTIMIZER
+# define gcdVX_OPTIMIZER 0
+#endif
+
+#ifndef gcdOCL_READ_IMAGE_OPTIMIZATION
+# define gcdOCL_READ_IMAGE_OPTIMIZATION 0
+#endif
+
+#ifndef gcdALLOC_ON_FAULT
+# define gcdALLOC_ON_FAULT 0
+#endif
+
+/*
+ gcdDISABLE_GPU_VIRTUAL_ADDRESS
+
+ When enabled, disable MMU and all virtual allocated from MMU.
+*/
+#ifndef gcdDISABLE_GPU_VIRTUAL_ADDRESS
+# define gcdDISABLE_GPU_VIRTUAL_ADDRESS 0
+#endif
+
+#ifndef gcdCOMPILER_DEBUGOUTPUT
+# define gcdCOMPILER_DEBUGOUTPUT 0
+#endif
+
+/*
+ gcd2D_COMPRESSION_DEC400_ALIGN_MODE
+
+ Only for DEC400 compression.
+ Set 0 as 16bytes aligned. 1 as 32bytes aligned. 2 as 64bytes aligned.
+ Default is 0 which means 32bytes aligned.
+*/
+#ifndef gcd2D_COMPRESSION_DEC400_ALIGN_MODE
+# define gcd2D_COMPRESSION_DEC400_ALIGN_MODE 1
+#endif
+
+#endif /* __gc_hal_options_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h
new file mode 100644
index 000000000000..031c0c84a767
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_profiler.h
@@ -0,0 +1,1353 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_profiler_h_
+#define __gc_hal_profiler_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GLVERTEX_OBJECT 10
+#define GLVERTEX_OBJECT_BYTES 11
+
+#define GLINDEX_OBJECT 20
+#define GLINDEX_OBJECT_BYTES 21
+
+#define GLTEXTURE_OBJECT 30
+#define GLTEXTURE_OBJECT_BYTES 31
+
+#define GLBUFOBJ_OBJECT 40
+#define GLBUFOBJ_OBJECT_BYTES 41
+
+#if VIVANTE_PROFILER
+#define gcmPROFILE_GC(Enum, Value) gcoPROFILER_Count(gcvNULL, Enum, Value)
+#else
+#define gcmPROFILE_GC(Enum, Value) do { } while (gcvFALSE)
+#endif
+
+#ifndef gcdNEW_PROFILER_FILE
+#define gcdNEW_PROFILER_FILE 1
+#endif
+
+#define ES11_CALLS 151
+#define ES11_DRAWCALLS (ES11_CALLS + 1)
+#define ES11_STATECHANGECALLS (ES11_DRAWCALLS + 1)
+#define ES11_POINTCOUNT (ES11_STATECHANGECALLS + 1)
+#define ES11_LINECOUNT (ES11_POINTCOUNT + 1)
+#define ES11_TRIANGLECOUNT (ES11_LINECOUNT + 1)
+
+#define ES30_CALLS 159
+#define ES30_DRAWCALLS (ES30_CALLS + 1)
+#define ES30_STATECHANGECALLS (ES30_DRAWCALLS + 1)
+#define ES30_POINTCOUNT (ES30_STATECHANGECALLS + 1)
+#define ES30_LINECOUNT (ES30_POINTCOUNT + 1)
+#define ES30_TRIANGLECOUNT (ES30_LINECOUNT + 1)
+
+#define VG11_CALLS 88
+#define VG11_DRAWCALLS (VG11_CALLS + 1)
+#define VG11_STATECHANGECALLS (VG11_DRAWCALLS + 1)
+#define VG11_FILLCOUNT (VG11_STATECHANGECALLS + 1)
+#define VG11_STROKECOUNT (VG11_FILLCOUNT + 1)
+/* End of Driver API ID Definitions. */
+
+/* HAL & MISC IDs. */
+#define HAL_VERTBUFNEWBYTEALLOC 1
+#define HAL_VERTBUFTOTALBYTEALLOC (HAL_VERTBUFNEWBYTEALLOC + 1)
+#define HAL_VERTBUFNEWOBJALLOC (HAL_VERTBUFTOTALBYTEALLOC + 1)
+#define HAL_VERTBUFTOTALOBJALLOC (HAL_VERTBUFNEWOBJALLOC + 1)
+#define HAL_INDBUFNEWBYTEALLOC (HAL_VERTBUFTOTALOBJALLOC + 1)
+#define HAL_INDBUFTOTALBYTEALLOC (HAL_INDBUFNEWBYTEALLOC + 1)
+#define HAL_INDBUFNEWOBJALLOC (HAL_INDBUFTOTALBYTEALLOC + 1)
+#define HAL_INDBUFTOTALOBJALLOC (HAL_INDBUFNEWOBJALLOC + 1)
+#define HAL_TEXBUFNEWBYTEALLOC (HAL_INDBUFTOTALOBJALLOC + 1)
+#define HAL_TEXBUFTOTALBYTEALLOC (HAL_TEXBUFNEWBYTEALLOC + 1)
+#define HAL_TEXBUFNEWOBJALLOC (HAL_TEXBUFTOTALBYTEALLOC + 1)
+#define HAL_TEXBUFTOTALOBJALLOC (HAL_TEXBUFNEWOBJALLOC + 1)
+
+#define GPU_CYCLES 1
+#define GPU_READ64BYTE (GPU_CYCLES + 1)
+#define GPU_WRITE64BYTE (GPU_READ64BYTE + 1)
+#define GPU_TOTALCYCLES (GPU_WRITE64BYTE + 1)
+#define GPU_IDLECYCLES (GPU_TOTALCYCLES + 1)
+
+#define VS_INSTCOUNT 1
+#define VS_BRANCHINSTCOUNT (VS_INSTCOUNT + 1)
+#define VS_TEXLDINSTCOUNT (VS_BRANCHINSTCOUNT + 1)
+#define VS_RENDEREDVERTCOUNT (VS_TEXLDINSTCOUNT + 1)
+#define VS_SOURCE (VS_RENDEREDVERTCOUNT + 1)
+#define VS_NONIDLESTARVECOUNT (VS_SOURCE + 1)
+#define VS_STARVELCOUNT (VS_NONIDLESTARVECOUNT + 1)
+#define VS_STALLCOUNT (VS_STARVELCOUNT + 1)
+#define VS_PROCESSCOUNT (VS_STALLCOUNT + 1)
+
+#define PS_INSTCOUNT 1
+#define PS_BRANCHINSTCOUNT (PS_INSTCOUNT + 1)
+#define PS_TEXLDINSTCOUNT (PS_BRANCHINSTCOUNT + 1)
+#define PS_RENDEREDPIXCOUNT (PS_TEXLDINSTCOUNT + 1)
+#define PS_SOURCE (PS_RENDEREDPIXCOUNT + 1)
+#define PS_NONIDLESTARVECOUNT (PS_SOURCE + 1)
+#define PS_STARVELCOUNT (PS_NONIDLESTARVECOUNT + 1)
+#define PS_STALLCOUNT (PS_STARVELCOUNT + 1)
+#define PS_PROCESSCOUNT (PS_STALLCOUNT + 1)
+#define PS_SHADERCYCLECOUNT (PS_PROCESSCOUNT + 1)
+
+#define PA_INVERTCOUNT 1
+#define PA_INPRIMCOUNT (PA_INVERTCOUNT + 1)
+#define PA_OUTPRIMCOUNT (PA_INPRIMCOUNT + 1)
+#define PA_DEPTHCLIPCOUNT (PA_OUTPRIMCOUNT + 1)
+#define PA_TRIVIALREJCOUNT (PA_DEPTHCLIPCOUNT + 1)
+#define PA_CULLCOUNT (PA_TRIVIALREJCOUNT + 1)
+#define PA_NONIDLESTARVECOUNT (PA_CULLCOUNT + 1)
+#define PA_STARVELCOUNT (PA_NONIDLESTARVECOUNT + 1)
+#define PA_STALLCOUNT (PA_STARVELCOUNT + 1)
+#define PA_PROCESSCOUNT (PA_STALLCOUNT + 1)
+
+#define SE_TRIANGLECOUNT 1
+#define SE_LINECOUNT (SE_TRIANGLECOUNT + 1)
+#define SE_STARVECOUNT (SE_LINECOUNT + 1)
+#define SE_STALLCOUNT (SE_STARVECOUNT + 1)
+#define SE_RECEIVETRIANGLECOUNT (SE_STALLCOUNT + 1)
+#define SE_SENDTRIANGLECOUNT (SE_RECEIVETRIANGLECOUNT + 1)
+#define SE_RECEIVELINESCOUNT (SE_SENDTRIANGLECOUNT + 1)
+#define SE_SENDLINESCOUNT (SE_RECEIVELINESCOUNT + 1)
+#define SE_NONIDLESTARVECOUNT (SE_SENDLINESCOUNT + 1)
+#define SE_PROCESSCOUNT (SE_NONIDLESTARVECOUNT + 1)
+
+#define RA_VALIDPIXCOUNT 1
+#define RA_TOTALQUADCOUNT (RA_VALIDPIXCOUNT + 1)
+#define RA_VALIDQUADCOUNTEZ (RA_TOTALQUADCOUNT + 1)
+#define RA_TOTALPRIMCOUNT (RA_VALIDQUADCOUNTEZ + 1)
+#define RA_PIPECACHEMISSCOUNT (RA_TOTALPRIMCOUNT + 1)
+#define RA_PREFCACHEMISSCOUNT (RA_PIPECACHEMISSCOUNT + 1)
+#define RA_EEZCULLCOUNT (RA_PREFCACHEMISSCOUNT + 1)
+#define RA_NONIDLESTARVECOUNT (RA_EEZCULLCOUNT + 1)
+#define RA_STARVELCOUNT (RA_NONIDLESTARVECOUNT + 1)
+#define RA_STALLCOUNT (RA_STARVELCOUNT + 1)
+#define RA_PROCESSCOUNT (RA_STALLCOUNT + 1)
+
+#define TX_TOTBILINEARREQ 1
+#define TX_TOTTRILINEARREQ (TX_TOTBILINEARREQ + 1)
+#define TX_TOTDISCARDTEXREQ (TX_TOTTRILINEARREQ + 1)
+#define TX_TOTTEXREQ (TX_TOTDISCARDTEXREQ + 1)
+#define TX_MEMREADCOUNT (TX_TOTTEXREQ + 1)
+#define TX_MEMREADIN8BCOUNT (TX_MEMREADCOUNT + 1)
+#define TX_CACHEMISSCOUNT (TX_MEMREADIN8BCOUNT + 1)
+#define TX_CACHEHITTEXELCOUNT (TX_CACHEMISSCOUNT + 1)
+#define TX_CACHEMISSTEXELCOUNT (TX_CACHEHITTEXELCOUNT + 1)
+#define TX_NONIDLESTARVECOUNT (TX_CACHEMISSTEXELCOUNT+ 1)
+#define TX_STARVELCOUNT (TX_NONIDLESTARVECOUNT + 1)
+#define TX_STALLCOUNT (TX_STARVELCOUNT + 1)
+#define TX_PROCESSCOUNT (TX_STALLCOUNT + 1)
+
+#define PE_KILLEDBYCOLOR 1
+#define PE_KILLEDBYDEPTH (PE_KILLEDBYCOLOR + 1)
+#define PE_DRAWNBYCOLOR (PE_KILLEDBYDEPTH + 1)
+#define PE_DRAWNBYDEPTH (PE_DRAWNBYCOLOR + 1)
+
+#define MC_READREQ8BPIPE 1
+#define MC_READREQ8BIP (MC_READREQ8BPIPE + 1)
+#define MC_WRITEREQ8BPIPE (MC_READREQ8BIP + 1)
+#define MC_AXIMINLATENCY (MC_WRITEREQ8BPIPE + 1)
+#define MC_AXIMAXLATENCY (MC_AXIMINLATENCY + 1)
+#define MC_AXITOTALLATENCY (MC_AXIMAXLATENCY + 1)
+#define MC_AXISAMPLECOUNT (MC_AXITOTALLATENCY + 1)
+
+#define AXI_READREQSTALLED 1
+#define AXI_WRITEREQSTALLED (AXI_READREQSTALLED + 1)
+#define AXI_WRITEDATASTALLED (AXI_WRITEREQSTALLED + 1)
+
+#define FE_DRAWCOUNT 1
+#define FE_OUTVERTEXCOUNT (FE_DRAWCOUNT + 1)
+#define FE_STALLCOUNT (FE_OUTVERTEXCOUNT + 1)
+#define FE_STARVECOUNT (FE_STALLCOUNT + 1)
+
+#define PVS_INSTRCOUNT 1
+#define PVS_ALUINSTRCOUNT (PVS_INSTRCOUNT + 1)
+#define PVS_TEXINSTRCOUNT (PVS_ALUINSTRCOUNT + 1)
+#define PVS_ATTRIBCOUNT (PVS_TEXINSTRCOUNT + 1)
+#define PVS_UNIFORMCOUNT (PVS_ATTRIBCOUNT + 1)
+#define PVS_FUNCTIONCOUNT (PVS_UNIFORMCOUNT + 1)
+#define PVS_SOURCE (PVS_FUNCTIONCOUNT + 1)
+
+#define PPS_INSTRCOUNT 1
+#define PPS_ALUINSTRCOUNT (PPS_INSTRCOUNT + 1)
+#define PPS_TEXINSTRCOUNT (PPS_ALUINSTRCOUNT + 1)
+#define PPS_ATTRIBCOUNT (PPS_TEXINSTRCOUNT + 1)
+#define PPS_UNIFORMCOUNT (PPS_ATTRIBCOUNT + 1)
+#define PPS_FUNCTIONCOUNT (PPS_UNIFORMCOUNT + 1)
+#define PPS_SOURCE (PPS_FUNCTIONCOUNT + 1)
+/* End of MISC Counter IDs. */
+
+#ifdef gcdNEW_PROFILER_FILE
+
+/* Category Constants. */
+#define VPHEADER 0x010000
+#define VPG_INFO 0x020000
+#define VPG_TIME 0x030000
+#define VPG_MEM 0x040000
+#define VPG_ES11 0x050000
+#define VPG_ES30 0x060000
+#define VPG_VG11 0x070000
+#define VPG_HAL 0x080000
+#define VPG_HW 0x090000
+#define VPG_GPU 0x0a0000
+#define VPG_VS 0x0b0000
+#define VPG_PS 0x0c0000
+#define VPG_PA 0x0d0000
+#define VPG_SETUP 0x0e0000
+#define VPG_RA 0x0f0000
+#define VPG_TX 0x100000
+#define VPG_PE 0x110000
+#define VPG_MC 0x120000
+#define VPG_AXI 0x130000
+#define VPG_PROG 0x140000
+#define VPG_PVS 0x150000
+#define VPG_PPS 0x160000
+#define VPG_ES11_TIME 0x170000
+#define VPG_ES30_TIME 0x180000
+#define VPG_FRAME 0x190000
+#define VPG_ES11_DRAW 0x200000
+#define VPG_ES30_DRAW 0x210000
+#define VPG_VG11_TIME 0x220000
+#define VPG_FE 0x230000
+#define VPG_MULTI_GPU 0x240000
+#define VPNG_FE 0x250000
+#define VPNG_VS 0x260000
+#define VPNG_PS 0x270000
+#define VPNG_PA 0x280000
+#define VPNG_SETUP 0x290000
+#define VPNG_RA 0x2a0000
+#define VPNG_TX 0x2b0000
+#define VPNG_PE 0x2c0000
+#define VPNG_MCC 0x2d0000
+#define VPNG_MCZ 0x2e0000
+#define VPNG_HI 0x2f0000
+#define VPNG_L2 0x300000
+#define VPG_END 0xff0000
+
+/* Info. */
+#define VPC_INFOCOMPANY (VPG_INFO + 1)
+#define VPC_INFOVERSION (VPC_INFOCOMPANY + 1)
+#define VPC_INFORENDERER (VPC_INFOVERSION + 1)
+#define VPC_INFOREVISION (VPC_INFORENDERER + 1)
+#define VPC_INFODRIVER (VPC_INFOREVISION + 1)
+#define VPC_INFODRIVERMODE (VPC_INFODRIVER + 1)
+#define VPC_INFOSCREENSIZE (VPC_INFODRIVERMODE + 1)
+
+/* Counter Constants. */
+#define VPC_ELAPSETIME (VPG_TIME + 1)
+#define VPC_CPUTIME (VPC_ELAPSETIME + 1)
+
+#define VPC_MEMMAXRES (VPG_MEM + 1)
+#define VPC_MEMSHARED (VPC_MEMMAXRES + 1)
+#define VPC_MEMUNSHAREDDATA (VPC_MEMSHARED + 1)
+#define VPC_MEMUNSHAREDSTACK (VPC_MEMUNSHAREDDATA + 1)
+
+/* OpenGL ES11 Statics Counter IDs. */
+#define VPC_ES11CALLS (VPG_ES11 + ES11_CALLS)
+#define VPC_ES11DRAWCALLS (VPG_ES11 + ES11_DRAWCALLS)
+#define VPC_ES11STATECHANGECALLS (VPG_ES11 + ES11_STATECHANGECALLS)
+#define VPC_ES11POINTCOUNT (VPG_ES11 + ES11_POINTCOUNT)
+#define VPC_ES11LINECOUNT (VPG_ES11 + ES11_LINECOUNT)
+#define VPC_ES11TRIANGLECOUNT (VPG_ES11 + ES11_TRIANGLECOUNT)
+
+/* OpenGL ES30 Statistics Counter IDs. */
+#define VPC_ES30CALLS (VPG_ES30 + ES30_CALLS)
+#define VPC_ES30DRAWCALLS (VPG_ES30 + ES30_DRAWCALLS)
+#define VPC_ES30STATECHANGECALLS (VPG_ES30 + ES30_STATECHANGECALLS)
+#define VPC_ES30POINTCOUNT (VPG_ES30 + ES30_POINTCOUNT)
+#define VPC_ES30LINECOUNT (VPG_ES30 + ES30_LINECOUNT)
+#define VPC_ES30TRIANGLECOUNT (VPG_ES30 + ES30_TRIANGLECOUNT)
+
+/* OpenVG Statistics Counter IDs. */
+#define VPC_VG11CALLS (VPG_VG11 + VG11_CALLS)
+#define VPC_VG11DRAWCALLS (VPG_VG11 + VG11_DRAWCALLS)
+#define VPC_VG11STATECHANGECALLS (VPG_VG11 + VG11_STATECHANGECALLS)
+#define VPC_VG11FILLCOUNT (VPG_VG11 + VG11_FILLCOUNT)
+#define VPC_VG11STROKECOUNT (VPG_VG11 + VG11_STROKECOUNT)
+
+/* HAL Counters. */
+#define VPC_HALVERTBUFNEWBYTEALLOC (VPG_HAL + HAL_VERTBUFNEWBYTEALLOC)
+#define VPC_HALVERTBUFTOTALBYTEALLOC (VPG_HAL + HAL_VERTBUFTOTALBYTEALLOC)
+#define VPC_HALVERTBUFNEWOBJALLOC (VPG_HAL + HAL_VERTBUFNEWOBJALLOC)
+#define VPC_HALVERTBUFTOTALOBJALLOC (VPG_HAL + HAL_VERTBUFTOTALOBJALLOC)
+#define VPC_HALINDBUFNEWBYTEALLOC (VPG_HAL + HAL_INDBUFNEWBYTEALLOC)
+#define VPC_HALINDBUFTOTALBYTEALLOC (VPG_HAL + HAL_INDBUFTOTALBYTEALLOC)
+#define VPC_HALINDBUFNEWOBJALLOC (VPG_HAL + HAL_INDBUFNEWOBJALLOC)
+#define VPC_HALINDBUFTOTALOBJALLOC (VPG_HAL + HAL_INDBUFTOTALOBJALLOC)
+#define VPC_HALTEXBUFNEWBYTEALLOC (VPG_HAL + HAL_TEXBUFNEWBYTEALLOC)
+#define VPC_HALTEXBUFTOTALBYTEALLOC (VPG_HAL + HAL_TEXBUFTOTALBYTEALLOC)
+#define VPC_HALTEXBUFNEWOBJALLOC (VPG_HAL + HAL_TEXBUFNEWOBJALLOC)
+#define VPC_HALTEXBUFTOTALOBJALLOC (VPG_HAL + HAL_TEXBUFTOTALOBJALLOC)
+
+/* HW: GPU Counters. */
+#define VPC_GPUCYCLES (VPG_GPU + GPU_CYCLES)
+#define VPC_GPUREAD64BYTE (VPG_GPU + GPU_READ64BYTE)
+#define VPC_GPUWRITE64BYTE (VPG_GPU + GPU_WRITE64BYTE)
+#define VPC_GPUTOTALCYCLES (VPG_GPU + GPU_TOTALCYCLES)
+#define VPC_GPUIDLECYCLES (VPG_GPU + GPU_IDLECYCLES)
+
+/* HW: Shader Counters. */
+#define VPC_VSINSTCOUNT (VPG_VS + VS_INSTCOUNT)
+#define VPC_VSBRANCHINSTCOUNT (VPG_VS + VS_BRANCHINSTCOUNT)
+#define VPC_VSTEXLDINSTCOUNT (VPG_VS + VS_TEXLDINSTCOUNT)
+#define VPC_VSRENDEREDVERTCOUNT (VPG_VS + VS_RENDEREDVERTCOUNT)
+#define VPC_VSNONIDLESTARVECOUNT (VPG_VS + VS_NONIDLESTARVECOUNT)
+#define VPC_VSSTARVELCOUNT (VPG_VS + VS_STARVELCOUNT)
+#define VPC_VSSTALLCOUNT (VPG_VS + VS_STALLCOUNT)
+#define VPC_VSPROCESSCOUNT (VPG_VS + VS_PROCESSCOUNT)
+/* HW: PS Count. */
+#define VPC_PSINSTCOUNT (VPG_PS + PS_INSTCOUNT)
+#define VPC_PSBRANCHINSTCOUNT (VPG_PS + PS_BRANCHINSTCOUNT)
+#define VPC_PSTEXLDINSTCOUNT (VPG_PS + PS_TEXLDINSTCOUNT)
+#define VPC_PSRENDEREDPIXCOUNT (VPG_PS + PS_RENDEREDPIXCOUNT)
+#define VPC_PSNONIDLESTARVECOUNT (VPG_PS + PS_NONIDLESTARVECOUNT)
+#define VPC_PSSTARVELCOUNT (VPG_PS + PS_STARVELCOUNT)
+#define VPC_PSSTALLCOUNT (VPG_PS + PS_STALLCOUNT)
+#define VPC_PSPROCESSCOUNT (VPG_PS + PS_PROCESSCOUNT)
+#define VPC_PSSHADERCYCLECOUNT (VPG_PS + PS_SHADERCYCLECOUNT)
+
+/* HW: PA Counters. */
+#define VPC_PAINVERTCOUNT (VPG_PA + PA_INVERTCOUNT)
+#define VPC_PAINPRIMCOUNT (VPG_PA + PA_INPRIMCOUNT)
+#define VPC_PAOUTPRIMCOUNT (VPG_PA + PA_OUTPRIMCOUNT)
+#define VPC_PADEPTHCLIPCOUNT (VPG_PA + PA_DEPTHCLIPCOUNT)
+#define VPC_PATRIVIALREJCOUNT (VPG_PA + PA_TRIVIALREJCOUNT)
+#define VPC_PACULLCOUNT (VPG_PA + PA_CULLCOUNT)
+#define VPC_PANONIDLESTARVECOUNT (VPG_PA + PA_NONIDLESTARVECOUNT)
+#define VPC_PASTARVELCOUNT (VPG_PA + PA_STARVELCOUNT)
+#define VPC_PASTALLCOUNT (VPG_PA + PA_STALLCOUNT)
+#define VPC_PAPROCESSCOUNT (VPG_PA + PA_PROCESSCOUNT)
+
+/* HW: Setup Counters. */
+#define VPC_SETRIANGLECOUNT (VPG_SETUP + SE_TRIANGLECOUNT)
+#define VPC_SELINECOUNT (VPG_SETUP + SE_LINECOUNT)
+#define VPC_SESTARVECOUNT (VPG_SETUP + SE_STARVECOUNT)
+#define VPC_SESTALLCOUNT (VPG_SETUP + SE_STALLCOUNT)
+#define VPC_SERECEIVETRIANGLECOUNT (VPG_SETUP + SE_RECEIVETRIANGLECOUNT)
+#define VPC_SESENDTRIANGLECOUNT (VPG_SETUP + SE_SENDTRIANGLECOUNT)
+#define VPC_SERECEIVELINESCOUNT (VPG_SETUP + SE_RECEIVELINESCOUNT)
+#define VPC_SESENDLINESCOUNT (VPG_SETUP + SE_SENDLINESCOUNT)
+#define VPC_SENONIDLESTARVECOUNT (VPG_SETUP + SE_NONIDLESTARVECOUNT)
+#define VPC_SEPROCESSCOUNT (VPG_SETUP + SE_PROCESSCOUNT)
+
+/* HW: RA Counters. */
+#define VPC_RAVALIDPIXCOUNT (VPG_RA + RA_VALIDPIXCOUNT)
+#define VPC_RATOTALQUADCOUNT (VPG_RA + RA_TOTALQUADCOUNT)
+#define VPC_RAVALIDQUADCOUNTEZ (VPG_RA + RA_VALIDQUADCOUNTEZ)
+#define VPC_RATOTALPRIMCOUNT (VPG_RA + RA_TOTALPRIMCOUNT)
+#define VPC_RAPIPECACHEMISSCOUNT (VPG_RA + RA_PIPECACHEMISSCOUNT)
+#define VPC_RAPREFCACHEMISSCOUNT (VPG_RA + RA_PREFCACHEMISSCOUNT)
+#define VPC_RAEEZCULLCOUNT (VPG_RA + RA_EEZCULLCOUNT)
+#define VPC_RANONIDLESTARVECOUNT (VPG_RA + RA_NONIDLESTARVECOUNT)
+#define VPC_RASTARVELCOUNT (VPG_RA + RA_STARVELCOUNT)
+#define VPC_RASTALLCOUNT (VPG_RA + RA_STALLCOUNT)
+#define VPC_RAPROCESSCOUNT (VPG_RA + RA_PROCESSCOUNT)
+
+/* HW: TEX Counters. */
+#define VPC_TXTOTBILINEARREQ (VPG_TX + TX_TOTBILINEARREQ)
+#define VPC_TXTOTTRILINEARREQ (VPG_TX + TX_TOTTRILINEARREQ)
+#define VPC_TXTOTDISCARDTEXREQ (VPG_TX + TX_TOTDISCARDTEXREQ)
+#define VPC_TXTOTTEXREQ (VPG_TX + TX_TOTTEXREQ)
+#define VPC_TXMEMREADCOUNT (VPG_TX + TX_MEMREADCOUNT)
+#define VPC_TXMEMREADIN8BCOUNT (VPG_TX + TX_MEMREADIN8BCOUNT)
+#define VPC_TXCACHEMISSCOUNT (VPG_TX + TX_CACHEMISSCOUNT)
+#define VPC_TXCACHEHITTEXELCOUNT (VPG_TX + TX_CACHEHITTEXELCOUNT)
+#define VPC_TXCACHEMISSTEXELCOUNT (VPG_TX + TX_CACHEMISSTEXELCOUNT)
+#define VPC_TXNONIDLESTARVECOUNT (VPG_TX + TX_NONIDLESTARVECOUNT)
+#define VPC_TXSTARVELCOUNT (VPG_TX + TX_STARVELCOUNT)
+#define VPC_TXSTALLCOUNT (VPG_TX + TX_STALLCOUNT)
+#define VPC_TXPROCESSCOUNT (VPG_TX + TX_PROCESSCOUNT)
+
+/* HW: PE Counters. */
+#define VPC_PEKILLEDBYCOLOR (VPG_PE + PE_KILLEDBYCOLOR)
+#define VPC_PEKILLEDBYDEPTH (VPG_PE + PE_KILLEDBYDEPTH)
+#define VPC_PEDRAWNBYCOLOR (VPG_PE + PE_DRAWNBYCOLOR)
+#define VPC_PEDRAWNBYDEPTH (VPG_PE + PE_DRAWNBYDEPTH)
+
+/* HW: MC Counters. */
+#define VPC_MCREADREQ8BPIPE (VPG_MC + MC_READREQ8BPIPE)
+#define VPC_MCREADREQ8BIP (VPG_MC + MC_READREQ8BIP)
+#define VPC_MCWRITEREQ8BPIPE (VPG_MC + MC_WRITEREQ8BPIPE)
+#define VPC_MCAXIMINLATENCY (VPG_MC + MC_AXIMINLATENCY)
+#define VPC_MCAXIMAXLATENCY (VPG_MC + MC_AXIMAXLATENCY)
+#define VPC_MCAXITOTALLATENCY (VPG_MC + MC_AXITOTALLATENCY)
+#define VPC_MCAXISAMPLECOUNT (VPG_MC + MC_AXISAMPLECOUNT)
+
+/* HW: AXI Counters. */
+#define VPC_AXIREADREQSTALLED (VPG_AXI + AXI_READREQSTALLED)
+#define VPC_AXIWRITEREQSTALLED (VPG_AXI + AXI_WRITEREQSTALLED)
+#define VPC_AXIWRITEDATASTALLED (VPG_AXI + AXI_WRITEDATASTALLED)
+
+/* HW: FE Counters. */
+#define VPC_FEDRAWCOUNT (VPG_FE + FE_DRAWCOUNT)
+#define VPC_FEOUTVERTEXCOUNT (VPG_FE + FE_OUTVERTEXCOUNT)
+#define VPC_FESTALLCOUNT (VPG_FE + FE_STALLCOUNT)
+#define VPC_FESTARVECOUNT (VPG_FE + FE_STARVECOUNT)
+
+/* HW: Shader Counters. */
+#define VPNC_VSINSTCOUNT (VPNG_VS + 1)
+#define VPNC_VSBRANCHINSTCOUNT (VPNG_VS + 2)
+#define VPNC_VSTEXLDINSTCOUNT (VPNG_VS + 3)
+#define VPNC_VSRENDEREDVERTCOUNT (VPNG_VS + 4)
+#define VPNC_VSNONIDLESTARVECOUNT (VPNG_VS + 5)
+#define VPNC_VSSTARVELCOUNT (VPNG_VS + 6)
+#define VPNC_VSSTALLCOUNT (VPNG_VS + 7)
+#define VPNC_VSPROCESSCOUNT (VPNG_VS + 8)
+#define VPNC_VSSHADERCYCLECOUNT (VPNG_VS + 9)
+/* HW: PS Count. */
+#define VPNC_PSINSTCOUNT (VPNG_PS + 1)
+#define VPNC_PSBRANCHINSTCOUNT (VPNG_PS + 2)
+#define VPNC_PSTEXLDINSTCOUNT (VPNG_PS + 3)
+#define VPNC_PSRENDEREDPIXCOUNT (VPNG_PS + 4)
+#define VPNC_PSNONIDLESTARVECOUNT (VPNG_PS + 5)
+#define VPNC_PSSTARVELCOUNT (VPNG_PS + 6)
+#define VPNC_PSSTALLCOUNT (VPNG_PS + 7)
+#define VPNC_PSPROCESSCOUNT (VPNG_PS + 8)
+#define VPNC_PSSHADERCYCLECOUNT (VPNG_PS + 9)
+
+/* HW: PA Counters. */
+#define VPNC_PAINVERTCOUNT (VPNG_PA + 1)
+#define VPNC_PAINPRIMCOUNT (VPNG_PA + 2)
+#define VPNC_PAOUTPRIMCOUNT (VPNG_PA + 3)
+#define VPNC_PADEPTHCLIPCOUNT (VPNG_PA + 4)
+#define VPNC_PATRIVIALREJCOUNT (VPNG_PA + 5)
+#define VPNC_PACULLPRIMCOUNT (VPNG_PA + 6)
+#define VPNC_PADROPPRIMCOUNT (VPNG_PA + 7)
+#define VPNC_PAFRCLIPPRIMCOUNT (VPNG_PA + 8)
+#define VPNC_PAFRCLIPDROPPRIMCOUNT (VPNG_PA + 9)
+#define VPNC_PANONIDLESTARVECOUNT (VPNG_PA + 10)
+#define VPNC_PASTARVELCOUNT (VPNG_PA + 11)
+#define VPNC_PASTALLCOUNT (VPNG_PA + 12)
+#define VPNC_PAPROCESSCOUNT (VPNG_PA + 13)
+
+/* HW: Setup Counters. */
+#define VPNC_SECULLTRIANGLECOUNT (VPNG_SETUP + 1)
+#define VPNC_SECULLLINECOUNT (VPNG_SETUP + 2)
+#define VPNC_SECLIPTRIANGLECOUNT (VPNG_SETUP + 3)
+#define VPNC_SECLIPLINECOUNT (VPNG_SETUP + 4)
+#define VPNC_SESTARVECOUNT (VPNG_SETUP + 5)
+#define VPNC_SESTALLCOUNT (VPNG_SETUP + 6)
+#define VPNC_SERECEIVETRIANGLECOUNT (VPNG_SETUP + 7)
+#define VPNC_SESENDTRIANGLECOUNT (VPNG_SETUP + 8)
+#define VPNC_SERECEIVELINESCOUNT (VPNG_SETUP + 9)
+#define VPNC_SESENDLINESCOUNT (VPNG_SETUP + 10)
+#define VPNC_SENONIDLESTARVECOUNT (VPNG_SETUP + 11)
+#define VPNC_SETRIVIALREJLINECOUNT (VPNG_SETUP + 12)
+#define VPNC_SEPROCESSCOUNT (VPNG_SETUP + 13)
+
+/* HW: RA Counters. */
+#define VPNC_RAVALIDPIXCOUNT (VPNG_RA + 1)
+#define VPNC_RATOTALQUADCOUNT (VPNG_RA + 2)
+#define VPNC_RAVALIDQUADCOUNTEZ (VPNG_RA + 3)
+#define VPNC_RAINPUTPRIMCOUNT (VPNG_RA + 4)
+#define VPNC_RAPIPECACHEMISSCOUNT (VPNG_RA + 5)
+#define VPNC_RAPREFCACHEMISSCOUNT (VPNG_RA + 6)
+#define VPNC_RAPIPEHZCACHEMISSCOUNT (VPNG_RA + 7)
+#define VPNC_RAPREFHZCACHEMISSCOUNT (VPNG_RA + 8)
+#define VPNC_RAOUTPUTQUADCOUNT (VPNG_RA + 9)
+#define VPNC_RAOUTPUTPIXELCOUNT (VPNG_RA + 10)
+#define VPNC_RAEEZCULLCOUNT (VPNG_RA + 11)
+#define VPNC_RANONIDLESTARVECOUNT (VPNG_RA + 12)
+#define VPNC_RASTARVELCOUNT (VPNG_RA + 13)
+#define VPNC_RASTALLCOUNT (VPNG_RA + 14)
+#define VPNC_RAPROCESSCOUNT (VPNG_RA + 15)
+
+/* HW: TEX Counters. */
+#define VPNC_TXTOTBILINEARREQ (VPNG_TX + 1)
+#define VPNC_TXTOTTRILINEARREQ (VPNG_TX + 2)
+#define VPNC_TXTOTDISCARDTEXREQ (VPNG_TX + 3)
+#define VPNC_TXTOTTEXREQ (VPNG_TX + 4)
+#define VPNC_TXMC0MISSCOUNT (VPNG_TX + 5)
+#define VPNC_TXMC0REQCOUNT (VPNG_TX + 6)
+#define VPNC_TXMC1MISSCOUNT (VPNG_TX + 7)
+#define VPNC_TXMC1REQCOUNT (VPNG_TX + 8)
+#define VPNC_TXNONIDLESTARVECOUNT (VPNG_TX + 9)
+#define VPNC_TXSTARVELCOUNT (VPNG_TX + 10)
+#define VPNC_TXSTALLCOUNT (VPNG_TX + 11)
+#define VPNC_TXPROCESSCOUNT (VPNG_TX + 12)
+
+/* HW: PE Counters. */
+#define VPNC_PE0KILLEDBYCOLOR (VPNG_PE + 1)
+#define VPNC_PE0KILLEDBYDEPTH (VPNG_PE + 2)
+#define VPNC_PE0DRAWNBYCOLOR (VPNG_PE + 3)
+#define VPNC_PE0DRAWNBYDEPTH (VPNG_PE + 4)
+#define VPNC_PE1KILLEDBYCOLOR (VPNG_PE + 5)
+#define VPNC_PE1KILLEDBYDEPTH (VPNG_PE + 6)
+#define VPNC_PE1DRAWNBYCOLOR (VPNG_PE + 7)
+#define VPNC_PE1DRAWNBYDEPTH (VPNG_PE + 8)
+
+/* HW: MCC Counters. */
+#define VPNC_MCCREADREQ8BCOLORPIPE (VPNG_MCC + 1)
+#define VPNC_MCCREADREQ8BSOCOLORPIPE (VPNG_MCC + 2)
+#define VPNC_MCCWRITEREQ8BCOLORPIPE (VPNG_MCC + 3)
+#define VPNC_MCCREADREQSOCOLORPIPE (VPNG_MCC + 4)
+#define VPNC_MCCWRITEREQCOLORPIPE (VPNG_MCC + 5)
+#define VPNC_MCCREADREQ8BDEPTHPIPE (VPNG_MCC + 6)
+#define VPNC_MCCREADREQ8BSFDEPTHPIPE (VPNG_MCC + 7)
+#define VPNC_MCCWRITEREQ8BDEPTHPIPE (VPNG_MCC + 8)
+#define VPNC_MCCREADREQSFDEPTHPIPE (VPNG_MCC + 9)
+#define VPNC_MCCWRITEREQDEPTHPIPE (VPNG_MCC + 10)
+#define VPNC_MCCREADREQ8BOTHERPIPE (VPNG_MCC + 11)
+#define VPNC_MCCWRITEREQ8BOTHERPIPE (VPNG_MCC + 12)
+#define VPNC_MCCREADREQOTHERPIPE (VPNG_MCC + 13)
+#define VPNC_MCCWRITEREQOTHERPIPE (VPNG_MCC + 14)
+#define VPNC_MCCAXIMINLATENCY (VPNG_MCC + 15)
+#define VPNC_MCCAXIMAXLATENCY (VPNG_MCC + 16)
+#define VPNC_MCCAXITOTALLATENCY (VPNG_MCC + 17)
+#define VPNC_MCCAXISAMPLECOUNT (VPNG_MCC + 18)
+
+/* HW: MCZ Counters. */
+#define VPNC_MCZREADREQ8BCOLORPIPE (VPNG_MCZ + 1)
+#define VPNC_MCZREADREQ8BSOCOLORPIPE (VPNG_MCZ + 2)
+#define VPNC_MCZWRITEREQ8BCOLORPIPE (VPNG_MCZ + 3)
+#define VPNC_MCZREADREQSOCOLORPIPE (VPNG_MCZ + 4)
+#define VPNC_MCZWRITEREQCOLORPIPE (VPNG_MCZ + 5)
+#define VPNC_MCZREADREQ8BDEPTHPIPE (VPNG_MCZ + 6)
+#define VPNC_MCZREADREQ8BSFDEPTHPIPE (VPNG_MCZ + 7)
+#define VPNC_MCZWRITEREQ8BDEPTHPIPE (VPNG_MCZ + 8)
+#define VPNC_MCZREADREQSFDEPTHPIPE (VPNG_MCZ + 9)
+#define VPNC_MCZWRITEREQDEPTHPIPE (VPNG_MCZ + 10)
+#define VPNC_MCZREADREQ8BOTHERPIPE (VPNG_MCZ + 11)
+#define VPNC_MCZWRITEREQ8BOTHERPIPE (VPNG_MCZ + 12)
+#define VPNC_MCZREADREQOTHERPIPE (VPNG_MCZ + 13)
+#define VPNC_MCZWRITEREQOTHERPIPE (VPNG_MCZ + 14)
+#define VPNC_MCZAXIMINLATENCY (VPNG_MCZ + 15)
+#define VPNC_MCZAXIMAXLATENCY (VPNG_MCZ + 16)
+#define VPNC_MCZAXITOTALLATENCY (VPNG_MCZ + 17)
+#define VPNC_MCZAXISAMPLECOUNT (VPNG_MCZ + 18)
+
+/* HW: HI Counters. */
+#define VPNC_HI0READ8BYTE (VPNG_HI + 1)
+#define VPNC_HI0WRITE8BYTE (VPNG_HI + 2)
+#define VPNC_HI0READREQ (VPNG_HI + 3)
+#define VPNC_HI0WRITEREQ (VPNG_HI + 4)
+#define VPNC_HI0AXIREADREQSTALL (VPNG_HI + 5)
+#define VPNC_HI0AXIWRITEREQSTALL (VPNG_HI + 6)
+#define VPNC_HI0AXIWRITEDATASTALL (VPNG_HI + 7)
+#define VPNC_HI1READ8BYTE (VPNG_HI + 8)
+#define VPNC_HI1WRITE8BYTE (VPNG_HI + 9)
+#define VPNC_HI1READREQ (VPNG_HI + 10)
+#define VPNC_HI1WRITEREQ (VPNG_HI + 11)
+#define VPNC_HI1AXIREADREQSTALL (VPNG_HI + 12)
+#define VPNC_HI1AXIWRITEREQSTALL (VPNG_HI + 13)
+#define VPNC_HI1AXIWRITEDATASTALL (VPNG_HI + 14)
+#define VPNC_HITOTALCYCLES (VPNG_HI + 15)
+#define VPNC_HIIDLECYCLES (VPNG_HI + 16)
+#define VPNC_HIREAD8BYTE (VPNG_HI + 17)
+#define VPNC_HIWRITE8BYTE (VPNG_HI + 18)
+
+/* HW: L2 Counters. */
+#define VPNC_L2AXI0READREQCOUNT (VPNG_L2 + 1)
+#define VPNC_L2AXI1READREQCOUNT (VPNG_L2 + 2)
+#define VPNC_L2AXI0WRITEREQCOUNT (VPNG_L2 + 3)
+#define VPNC_L2AXI1WRITEREQCOUNT (VPNG_L2 + 4)
+#define VPNC_L2READTRANSREQBYAXI0 (VPNG_L2 + 5)
+#define VPNC_L2READTRANSREQBYAXI1 (VPNG_L2 + 6)
+#define VPNC_L2WRITETRANSREQBYAXI0 (VPNG_L2 + 7)
+#define VPNC_L2WRITETRANSREQBYAXI1 (VPNG_L2 + 8)
+#define VPNC_L2AXI0MINLATENCY (VPNG_L2 + 9)
+#define VPNC_L2AXI0MAXLATENCY (VPNG_L2 + 10)
+#define VPNC_L2AXI0TOTLATENCY (VPNG_L2 + 11)
+#define VPNC_L2AXI0TOTREQCOUNT (VPNG_L2 + 12)
+#define VPNC_L2AXI1MINLATENCY (VPNG_L2 + 13)
+#define VPNC_L2AXI1MAXLATENCY (VPNG_L2 + 14)
+#define VPNC_L2AXI1TOTLATENCY (VPNG_L2 + 15)
+#define VPNC_L2AXI1TOTREQCOUNT (VPNG_L2 + 16)
+
+/* HW: FE Counters. */
+#define VPNC_FEDRAWCOUNT (VPNG_FE + 1)
+#define VPNC_FEOUTVERTEXCOUNT (VPNG_FE + 2)
+#define VPNC_FECACHEMISSCOUNT (VPNG_FE + 3)
+#define VPNC_FECACHELKCOUNT (VPNG_FE + 4)
+#define VPNC_FESTALLCOUNT (VPNG_FE + 5)
+#define VPNC_FESTARVECOUNT (VPNG_FE + 6)
+#define VPNC_FEPROCESSCOUNT (VPNG_FE + 7)
+
+/* PROGRAM: Shader program counters. */
+#define VPC_PVSINSTRCOUNT (VPG_PVS + PVS_INSTRCOUNT)
+#define VPC_PVSALUINSTRCOUNT (VPG_PVS + PVS_ALUINSTRCOUNT)
+#define VPC_PVSTEXINSTRCOUNT (VPG_PVS + PVS_TEXINSTRCOUNT)
+#define VPC_PVSATTRIBCOUNT (VPG_PVS + PVS_ATTRIBCOUNT)
+#define VPC_PVSUNIFORMCOUNT (VPG_PVS + PVS_UNIFORMCOUNT)
+#define VPC_PVSFUNCTIONCOUNT (VPG_PVS + PVS_FUNCTIONCOUNT)
+#define VPC_PVSSOURCE (VPG_PVS + PVS_SOURCE)
+
+#define VPC_PPSINSTRCOUNT (VPG_PPS + PPS_INSTRCOUNT)
+#define VPC_PPSALUINSTRCOUNT (VPG_PPS + PPS_ALUINSTRCOUNT)
+#define VPC_PPSTEXINSTRCOUNT (VPG_PPS + PPS_TEXINSTRCOUNT)
+#define VPC_PPSATTRIBCOUNT (VPG_PPS + PPS_ATTRIBCOUNT)
+#define VPC_PPSUNIFORMCOUNT (VPG_PPS + PPS_UNIFORMCOUNT)
+#define VPC_PPSFUNCTIONCOUNT (VPG_PPS + PPS_FUNCTIONCOUNT)
+#define VPC_PPSSOURCE (VPG_PPS + PPS_SOURCE)
+
+#define VPC_PROGRAMHANDLE (VPG_PROG + 1)
+
+#define VPC_ES30_DRAW_NO (VPG_ES30_DRAW + 1)
+#define VPC_ES11_DRAW_NO (VPG_ES11_DRAW + 1)
+#define VPC_ES30_GPU_NO (VPG_MULTI_GPU + 1)
+#endif
+
+#if VIVANTE_PROFILER_ALL_COUNTER
+#define MODULE_FRONT_END_COUNTER_NUM 30
+#define MODULE_SHADER_COUNTER_NUM 30
+#define MODULE_PRIMITIVE_ASSEMBLY_COUNTER_NUM 30
+#define MODULE_SETUP_COUNTER_NUM 30
+#define MODULE_RASTERIZER_COUNTER_NUM 30
+#define MODULE_TEXTURE_COUNTER_NUM 30
+#define MODULE_PIXEL_ENGINE_COUNTER_NUM 30
+#define MODULE_MEMORY_CONTROLLER_COUNTER_NUM 30
+#define MODULE_HOST_INTERFACE_COUNTER_NUM 30
+#endif
+
+#if VIVANTE_PROFILER_PROBE
+#define MODULE_FRONT_END_COUNTER_NUM 0x5
+#define MODULE_VERTEX_SHADER_COUNTER_NUM 0x9
+#define MODULE_PRIMITIVE_ASSEMBLY_COUNTER_NUM 0xC
+#define MODULE_SETUP_COUNTER_NUM 0xD
+#define MODULE_RASTERIZER_COUNTER_NUM 0xE
+#define MODULE_PIXEL_SHADER_COUNTER_NUM 0x9
+#define MODULE_TEXTURE_COUNTER_NUM 0x8
+#define MODULE_PIXEL_ENGINE_COUNTER_NUM 0x8
+#define MODULE_MEMORY_CONTROLLER_COLOR_COUNTER_NUM 0xC
+#define MODULE_MEMORY_CONTROLLER_DEPTH_COUNTER_NUM 0xC
+#define MODULE_HOST_INTERFACE0_COUNTER_NUM 0x9
+#define MODULE_HOST_INTERFACE1_COUNTER_NUM 0x7
+#define MODULE_GPUL2_CACHE_COUNTER_NUM 0xE
+
+typedef enum _gceCOUNTER
+{
+ gcvCOUNTER_FRONT_END,
+ gcvCOUNTER_VERTEX_SHADER,
+ gcvCOUNTER_PRIMITIVE_ASSEMBLY,
+ gcvCOUNTER_SETUP,
+ gcvCOUNTER_RASTERIZER,
+ gcvCOUNTER_PIXEL_SHADER,
+ gcvCOUNTER_TEXTURE,
+ gcvCOUNTER_PIXEL_ENGINE,
+ gcvCOUNTER_MEMORY_CONTROLLER_COLOR,
+ gcvCOUNTER_MEMORY_CONTROLLER_DEPTH,
+ gcvCOUNTER_HOST_INTERFACE0,
+ gcvCOUNTER_HOST_INTERFACE1,
+ gcvCOUNTER_GPUL2_CACHE,
+ gcvCOUNTER_COUNT
+}
+gceCOUNTER;
+#endif
+
+
+#define MODULE_FRONT_END_COUNTER_NUM 0x5
+#define MODULE_VERTEX_SHADER_COUNTER_NUM 0x9
+#define MODULE_PRIMITIVE_ASSEMBLY_COUNTER_NUM 0xC
+#define MODULE_SETUP_COUNTER_NUM 0xD
+#define MODULE_RASTERIZER_COUNTER_NUM 0xE
+#define MODULE_PIXEL_SHADER_COUNTER_NUM 0x9
+#define MODULE_TEXTURE_COUNTER_NUM 0x8
+#define MODULE_PIXEL_ENGINE_COUNTER_NUM 0x8
+#define MODULE_MEMORY_CONTROLLER_COLOR_COUNTER_NUM 0xC
+#define MODULE_MEMORY_CONTROLLER_DEPTH_COUNTER_NUM 0xC
+#define MODULE_HOST_INTERFACE0_COUNTER_NUM 0x9
+#define MODULE_HOST_INTERFACE1_COUNTER_NUM 0x7
+#define MODULE_GPUL2_CACHE_COUNTER_NUM 0xE
+#define TOTAL_PROBE_NUMBER (MODULE_FRONT_END_COUNTER_NUM + MODULE_VERTEX_SHADER_COUNTER_NUM + MODULE_PRIMITIVE_ASSEMBLY_COUNTER_NUM \
+ + MODULE_SETUP_COUNTER_NUM + MODULE_RASTERIZER_COUNTER_NUM + MODULE_PIXEL_SHADER_COUNTER_NUM \
+ + MODULE_TEXTURE_COUNTER_NUM + MODULE_PIXEL_ENGINE_COUNTER_NUM + MODULE_MEMORY_CONTROLLER_COLOR_COUNTER_NUM \
+ + MODULE_MEMORY_CONTROLLER_DEPTH_COUNTER_NUM + MODULE_HOST_INTERFACE0_COUNTER_NUM + MODULE_HOST_INTERFACE1_COUNTER_NUM \
+ + MODULE_GPUL2_CACHE_COUNTER_NUM)
+
+
+typedef enum _gceCOUNTER
+{
+ gcvCOUNTER_FRONT_END,
+ gcvCOUNTER_VERTEX_SHADER,
+ gcvCOUNTER_PRIMITIVE_ASSEMBLY,
+ gcvCOUNTER_SETUP,
+ gcvCOUNTER_RASTERIZER,
+ gcvCOUNTER_PIXEL_SHADER,
+ gcvCOUNTER_TEXTURE,
+ gcvCOUNTER_PIXEL_ENGINE,
+ gcvCOUNTER_MEMORY_CONTROLLER_COLOR,
+ gcvCOUNTER_MEMORY_CONTROLLER_DEPTH,
+ gcvCOUNTER_HOST_INTERFACE0,
+ gcvCOUNTER_HOST_INTERFACE1,
+ gcvCOUNTER_GPUL2_CACHE,
+ gcvCOUNTER_COUNT
+}
+gceCOUNTER;
+
+
+/* HW profile information. */
+typedef struct _gcsPROFILER_NEW_COUNTERS_PART1
+{
+ gctUINT32 gpuTotalRead64BytesPerFrame;
+ gctUINT32 gpuTotalWrite64BytesPerFrame;
+
+ /* FE */
+ gctUINT32 fe_draw_count;
+ gctUINT32 fe_out_vertex_count;
+ gctUINT32 fe_cache_miss_count;
+ gctUINT32 fe_cache_lk_count;
+ gctUINT32 fe_stall_count;
+ gctUINT32 fe_starve_count;
+ gctUINT32 fe_process_count;
+
+ /* PE */
+ gctUINT32 pe0_pixel_count_killed_by_color_pipe;
+ gctUINT32 pe0_pixel_count_killed_by_depth_pipe;
+ gctUINT32 pe0_pixel_count_drawn_by_color_pipe;
+ gctUINT32 pe0_pixel_count_drawn_by_depth_pipe;
+ gctUINT32 pe1_pixel_count_killed_by_color_pipe;
+ gctUINT32 pe1_pixel_count_killed_by_depth_pipe;
+ gctUINT32 pe1_pixel_count_drawn_by_color_pipe;
+ gctUINT32 pe1_pixel_count_drawn_by_depth_pipe;
+
+ /* SH */
+ gctUINT32 shader_cycle_count;
+ gctUINT32 vs_shader_cycle_count;
+ gctUINT32 ps_shader_cycle_count;
+ gctUINT32 ps_inst_counter;
+ gctUINT32 ps_rendered_pixel_counter;
+ gctUINT32 vs_inst_counter;
+ gctUINT32 vs_rendered_vertice_counter;
+ gctUINT32 vs_branch_inst_counter;
+ gctUINT32 vs_texld_inst_counter;
+ gctUINT32 ps_branch_inst_counter;
+ gctUINT32 ps_texld_inst_counter;
+ gctUINT32 vs_non_idle_starve_count;
+ gctUINT32 vs_starve_count;
+ gctUINT32 vs_stall_count;
+ gctUINT32 vs_process_count;
+ gctUINT32 ps_non_idle_starve_count;
+ gctUINT32 ps_starve_count;
+ gctUINT32 ps_stall_count;
+ gctUINT32 ps_process_count;
+
+ /* PA */
+ gctUINT32 pa_input_vtx_counter;
+ gctUINT32 pa_input_prim_counter;
+ gctUINT32 pa_output_prim_counter;
+ gctUINT32 pa_depth_clipped_counter;
+ gctUINT32 pa_trivial_rejected_counter;
+ gctUINT32 pa_culled_prim_counter;
+ gctUINT32 pa_droped_prim_counter;
+ gctUINT32 pa_frustum_clipped_prim_counter;
+ gctUINT32 pa_frustum_clipdroped_prim_counter;
+ gctUINT32 pa_non_idle_starve_count;
+ gctUINT32 pa_starve_count;
+ gctUINT32 pa_stall_count;
+ gctUINT32 pa_process_count;
+
+ /* SE */
+ gctUINT32 se_culled_triangle_count;
+ gctUINT32 se_culled_lines_count;
+ gctUINT32 se_clipped_triangle_count;
+ gctUINT32 se_clipped_line_count;
+ gctUINT32 se_starve_count;
+ gctUINT32 se_stall_count;
+ gctUINT32 se_receive_triangle_count;
+ gctUINT32 se_send_triangle_count;
+ gctUINT32 se_receive_lines_count;
+ gctUINT32 se_send_lines_count;
+ gctUINT32 se_process_count;
+ gctUINT32 se_trivial_rejected_line_count;
+ gctUINT32 se_non_idle_starve_count;
+
+ /* RA */
+ gctUINT32 ra_input_prim_count;
+ gctUINT32 ra_total_quad_count;
+ gctUINT32 ra_valid_quad_count_after_early_z;
+ gctUINT32 ra_valid_pixel_count_to_render;
+ gctUINT32 ra_output_valid_quad_count;
+ gctUINT32 ra_output_valid_pixel_count;
+ gctUINT32 ra_pipe_cache_miss_counter;
+ gctUINT32 ra_pipe_hz_cache_miss_counter;
+ gctUINT32 ra_prefetch_cache_miss_counter;
+ gctUINT32 ra_prefetch_hz_cache_miss_counter;
+ gctUINT32 ra_eez_culled_counter;
+ gctUINT32 ra_non_idle_starve_count;
+ gctUINT32 ra_starve_count;
+ gctUINT32 ra_stall_count;
+ gctUINT32 ra_process_count;
+
+ /* TX */
+ gctUINT32 tx_total_bilinear_requests;
+ gctUINT32 tx_total_trilinear_requests;
+ gctUINT32 tx_total_discarded_texture_requests;
+ gctUINT32 tx_total_texture_requests;
+ gctUINT32 tx_mc0_miss_count;
+ gctUINT32 tx_mc0_request_byte_count;
+ gctUINT32 tx_mc1_miss_count;
+ gctUINT32 tx_mc1_request_byte_count;
+ gctUINT32 tx_non_idle_starve_count;
+ gctUINT32 tx_starve_count;
+ gctUINT32 tx_stall_count;
+ gctUINT32 tx_process_count;
+}
+gcsPROFILER_NEW_COUNTERS_PART1;
+
+typedef struct _gcsPROFILER_NEW_COUNTERS_PART2
+{
+ /* MCC */
+ gctUINT32 mcc_total_read_req_8B_from_colorpipe;
+ gctUINT32 mcc_total_read_req_8B_sentout_from_colorpipe;
+ gctUINT32 mcc_total_write_req_8B_from_colorpipe;
+ gctUINT32 mcc_total_read_req_sentout_from_colorpipe;
+ gctUINT32 mcc_total_write_req_from_colorpipe;
+ gctUINT32 mcc_total_read_req_8B_from_depthpipe;
+ gctUINT32 mcc_total_read_req_8B_sentout_from_depthpipe;
+ gctUINT32 mcc_total_write_req_8B_from_depthpipe;
+ gctUINT32 mcc_total_read_req_sentout_from_depthpipe;
+ gctUINT32 mcc_total_write_req_from_depthpipe;
+ gctUINT32 mcc_total_read_req_8B_from_others;
+ gctUINT32 mcc_total_write_req_8B_from_others;
+ gctUINT32 mcc_total_read_req_from_others;
+ gctUINT32 mcc_total_write_req_from_others;
+ gctUINT32 mcc_axi_total_latency;
+ gctUINT32 mcc_axi_sample_count;
+ gctUINT32 mcc_axi_max_latency;
+ gctUINT32 mcc_axi_min_latency;
+
+ /* MCZ */
+ gctUINT32 mcz_total_read_req_8B_from_colorpipe;
+ gctUINT32 mcz_total_read_req_8B_sentout_from_colorpipe;
+ gctUINT32 mcz_total_write_req_8B_from_colorpipe;
+ gctUINT32 mcz_total_read_req_sentout_from_colorpipe;
+ gctUINT32 mcz_total_write_req_from_colorpipe;
+ gctUINT32 mcz_total_read_req_8B_from_depthpipe;
+ gctUINT32 mcz_total_read_req_8B_sentout_from_depthpipe;
+ gctUINT32 mcz_total_write_req_8B_from_depthpipe;
+ gctUINT32 mcz_total_read_req_sentout_from_depthpipe;
+ gctUINT32 mcz_total_write_req_from_depthpipe;
+ gctUINT32 mcz_total_read_req_8B_from_others;
+ gctUINT32 mcz_total_write_req_8B_from_others;
+ gctUINT32 mcz_total_read_req_from_others;
+ gctUINT32 mcz_total_write_req_from_others;
+ gctUINT32 mcz_axi_total_latency;
+ gctUINT32 mcz_axi_sample_count;
+ gctUINT32 mcz_axi_max_latency;
+ gctUINT32 mcz_axi_min_latency;
+
+ /* HI */
+ gctUINT32 hi0_total_read_8B_count;
+ gctUINT32 hi0_total_write_8B_count;
+ gctUINT32 hi0_total_read_request_count;
+ gctUINT32 hi0_total_write_request_count;
+ gctUINT32 hi0_axi_cycles_read_request_stalled;
+ gctUINT32 hi0_axi_cycles_write_request_stalled;
+ gctUINT32 hi0_axi_cycles_write_data_stalled;
+ gctUINT32 hi1_total_read_8B_count;
+ gctUINT32 hi1_total_write_8B_count;
+ gctUINT32 hi1_total_read_request_count;
+ gctUINT32 hi1_total_write_request_count;
+ gctUINT32 hi1_axi_cycles_read_request_stalled;
+ gctUINT32 hi1_axi_cycles_write_request_stalled;
+ gctUINT32 hi1_axi_cycles_write_data_stalled;
+ gctUINT32 hi_total_cycle_count;
+ gctUINT32 hi_total_idle_cycle_count;
+ gctUINT32 hi_total_read_8B_count;
+ gctUINT32 hi_total_write_8B_count;
+
+ /* L2 */
+ gctUINT32 l2_total_axi0_read_request_count;
+ gctUINT32 l2_total_axi1_read_request_count;
+ gctUINT32 l2_total_axi0_write_request_count;
+ gctUINT32 l2_total_axi1_write_request_count;
+ gctUINT32 l2_total_read_transactions_request_by_axi0;
+ gctUINT32 l2_total_read_transactions_request_by_axi1;
+ gctUINT32 l2_total_write_transactions_request_by_axi0;
+ gctUINT32 l2_total_write_transactions_request_by_axi1;
+ gctUINT32 l2_axi0_minmax_latency;
+ gctUINT32 l2_axi0_min_latency;
+ gctUINT32 l2_axi0_max_latency;
+ gctUINT32 l2_axi0_total_latency;
+ gctUINT32 l2_axi0_total_request_count;
+ gctUINT32 l2_axi1_minmax_latency;
+ gctUINT32 l2_axi1_min_latency;
+ gctUINT32 l2_axi1_max_latency;
+ gctUINT32 l2_axi1_total_latency;
+ gctUINT32 l2_axi1_total_request_count;
+}
+gcsPROFILER_NEW_COUNTERS_PART2;
+
+typedef struct _gcsPROFILER_NEW_COUNTERS
+{
+ gctUINT32 drawID;
+ gcsPROFILER_NEW_COUNTERS_PART1 counters_part1;
+ gcsPROFILER_NEW_COUNTERS_PART2 counters_part2;
+}
+gcsPROFILER_NEW_COUNTERS;
+
+typedef struct _gcsPROFILER_COUNTERS
+{
+ /* HW static counters. */
+ gctUINT32 gpuClock;
+ gctUINT32 axiClock;
+ gctUINT32 shaderClock;
+
+ /* HW vairable counters. */
+ gctUINT32 gpuClockStart;
+ gctUINT32 gpuClockEnd;
+
+ /* HW vairable counters. */
+ gctUINT32 gpuCyclesCounter;
+ gctUINT32 gpuTotalCyclesCounter;
+ gctUINT32 gpuIdleCyclesCounter;
+ gctUINT32 gpuTotalRead64BytesPerFrame;
+ gctUINT32 gpuTotalWrite64BytesPerFrame;
+
+ /* PE */
+ gctUINT32 pe_pixel_count_killed_by_color_pipe;
+ gctUINT32 pe_pixel_count_killed_by_depth_pipe;
+ gctUINT32 pe_pixel_count_drawn_by_color_pipe;
+ gctUINT32 pe_pixel_count_drawn_by_depth_pipe;
+
+ /* SH */
+ gctUINT32 ps_inst_counter;
+ gctUINT32 rendered_pixel_counter;
+ gctUINT32 vs_inst_counter;
+ gctUINT32 rendered_vertice_counter;
+ gctUINT32 vtx_branch_inst_counter;
+ gctUINT32 vtx_texld_inst_counter;
+ gctUINT32 pxl_branch_inst_counter;
+ gctUINT32 pxl_texld_inst_counter;
+ gctUINT32 vs_non_idle_starve_count;
+ gctUINT32 vs_starve_count;
+ gctUINT32 vs_stall_count;
+ gctUINT32 vs_process_count;
+ gctUINT32 ps_non_idle_starve_count;
+ gctUINT32 ps_starve_count;
+ gctUINT32 ps_stall_count;
+ gctUINT32 ps_process_count;
+ gctUINT32 shader_cycle_count;
+
+ /* PA */
+ gctUINT32 pa_input_vtx_counter;
+ gctUINT32 pa_input_prim_counter;
+ gctUINT32 pa_output_prim_counter;
+ gctUINT32 pa_depth_clipped_counter;
+ gctUINT32 pa_trivial_rejected_counter;
+ gctUINT32 pa_culled_counter;
+ gctUINT32 pa_non_idle_starve_count;
+ gctUINT32 pa_starve_count;
+ gctUINT32 pa_stall_count;
+ gctUINT32 pa_process_count;
+
+ /* SE */
+ gctUINT32 se_culled_triangle_count;
+ gctUINT32 se_culled_lines_count;
+ gctUINT32 se_starve_count;
+ gctUINT32 se_stall_count;
+ gctUINT32 se_receive_triangle_count;
+ gctUINT32 se_send_triangle_count;
+ gctUINT32 se_receive_lines_count;
+ gctUINT32 se_send_lines_count;
+ gctUINT32 se_process_count;
+ gctUINT32 se_non_idle_starve_count;
+
+ /* RA */
+ gctUINT32 ra_valid_pixel_count;
+ gctUINT32 ra_total_quad_count;
+ gctUINT32 ra_valid_quad_count_after_early_z;
+ gctUINT32 ra_total_primitive_count;
+ gctUINT32 ra_pipe_cache_miss_counter;
+ gctUINT32 ra_prefetch_cache_miss_counter;
+ gctUINT32 ra_eez_culled_counter;
+ gctUINT32 ra_non_idle_starve_count;
+ gctUINT32 ra_starve_count;
+ gctUINT32 ra_stall_count;
+ gctUINT32 ra_process_count;
+
+ /* TX */
+ gctUINT32 tx_total_bilinear_requests;
+ gctUINT32 tx_total_trilinear_requests;
+ gctUINT32 tx_total_discarded_texture_requests;
+ gctUINT32 tx_total_texture_requests;
+ gctUINT32 tx_mem_read_count;
+ gctUINT32 tx_mem_read_in_8B_count;
+ gctUINT32 tx_cache_miss_count;
+ gctUINT32 tx_cache_hit_texel_count;
+ gctUINT32 tx_cache_miss_texel_count;
+ gctUINT32 tx_non_idle_starve_count;
+ gctUINT32 tx_starve_count;
+ gctUINT32 tx_stall_count;
+ gctUINT32 tx_process_count;
+
+ /* MC */
+ gctUINT32 mc_total_read_req_8B_from_pipeline;
+ gctUINT32 mc_total_read_req_8B_from_IP;
+ gctUINT32 mc_total_write_req_8B_from_pipeline;
+ gctUINT32 mc_axi_total_latency;
+ gctUINT32 mc_axi_sample_count;
+ gctUINT32 mc_axi_max_latency;
+ gctUINT32 mc_axi_min_latency;
+
+ /* HI */
+ gctUINT32 hi_axi_cycles_read_request_stalled;
+ gctUINT32 hi_axi_cycles_write_request_stalled;
+ gctUINT32 hi_axi_cycles_write_data_stalled;
+
+ /* FE */
+ gctUINT32 fe_draw_count;
+ gctUINT32 fe_out_vertex_count;
+ gctUINT32 fe_stall_count;
+ gctUINT32 fe_starve_count;
+
+#if VIVANTE_PROFILER_ALL_COUNTER
+ gctUINT32 feCounters[MODULE_FRONT_END_COUNTER_NUM];
+ gctUINT32 paCounters[MODULE_PRIMITIVE_ASSEMBLY_COUNTER_NUM];
+ gctUINT32 shCounters[MODULE_SHADER_COUNTER_NUM];
+ gctUINT32 seCounters[MODULE_SETUP_COUNTER_NUM];
+ gctUINT32 raCounters[MODULE_RASTERIZER_COUNTER_NUM];
+ gctUINT32 txCounters[MODULE_TEXTURE_COUNTER_NUM];
+ gctUINT32 peCounters[MODULE_PIXEL_ENGINE_COUNTER_NUM];
+ gctUINT32 mcCounters[MODULE_MEMORY_CONTROLLER_COUNTER_NUM];
+ gctUINT32 hiCounters[MODULE_HOST_INTERFACE_COUNTER_NUM];
+
+#endif
+}
+gcsPROFILER_COUNTERS;
+
+#define NumOfDrawBuf 1024
+
+typedef enum _gceCOUNTER_OPTYPE
+{
+ gcvCOUNTER_OP_DRAW = 0,
+ gcvCOUNTER_OP_BLT = 1,
+ gcvCOUNTER_OP_COMPUTE = 2,
+ gcvCOUNTER_OP_RS = 3,
+ gcvCOUNTER_OP_NONE = 4
+}
+gceCOUNTER_OPTYPE;
+
+typedef struct _gcsPROBEBUFFER
+{
+ gctHANDLE newCounterBuf[NumOfDrawBuf];
+ gctUINT32 curBufId;
+ gceCOUNTER_OPTYPE opType[NumOfDrawBuf];
+}
+gcsPROBEBUFFER;
+
+typedef struct _gcsCounterBuffer
+{
+ gcsPROFILER_NEW_COUNTERS counters;
+ gctHANDLE couterBufobj;
+ gctUINT32 probeAddress;
+ gceCOUNTER_OPTYPE opType;
+}
+gcsCounterBuffer;
+
+typedef struct _gcoPROFILER * gcoPROFILER;
+
+struct _gcoPROFILER
+{
+ gctBOOL enable;
+ gctBOOL isSyncMode;
+
+ gctFILE file;
+ gctCHAR* fileName;
+
+ gcsCounterBuffer counterBuf[NumOfDrawBuf];
+ gctINT32 curBufId;
+
+ gctBOOL perDrawMode;
+ gctBOOL needDump;
+ gctBOOL counterEnable;
+};
+
+typedef enum _gceProbeStatus
+{
+ gcvPROBE_Disabled = 0,
+ gcvPROBE_Paused = 1,
+ gcvPROBE_Enabled = 2,
+}
+gceProbeStatus;
+
+typedef enum _gceProbeCmd
+{
+ gcvPROBECMD_BEGIN = 0,
+ gcvPROBECMD_PAUSE = 1,
+ gcvPROBECMD_RESUME = 2,
+ gcvPROBECMD_END = 3,
+}
+gceProbeCmd;
+
+typedef struct _gcsPROBESTATES
+{
+ gceProbeStatus status;
+ gctUINT32 probeAddress;
+}gcsPROBESTATES;
+
+/* HAL profile information. */
+typedef struct _gcsPROFILER
+{
+ gctUINT32 enable;
+ gctBOOL enableHal;
+ gctBOOL enableHW;
+ gctBOOL enableSH;
+ gctBOOL isSyncMode;
+ gctBOOL isCLMode;
+ gctBOOL enablePrint;
+ gctBOOL disableOutputCounter;
+
+ gctBOOL useSocket;
+ gctINT sockFd;
+
+ gctFILE file;
+
+ /* Aggregate Information */
+
+ /* Clock Info */
+ gctUINT64 frameStart;
+ gctUINT64 frameEnd;
+
+ /* Current frame information */
+ gctUINT32 frameNumber;
+ gctUINT64 frameStartTimeusec;
+ gctUINT64 frameEndTimeusec;
+ gctUINT64 frameStartCPUTimeusec;
+ gctUINT64 frameEndCPUTimeusec;
+
+#if PROFILE_HAL_COUNTERS
+ gctUINT32 vertexBufferTotalBytesAlloc;
+ gctUINT32 vertexBufferNewBytesAlloc;
+ int vertexBufferTotalObjectsAlloc;
+ int vertexBufferNewObjectsAlloc;
+
+ gctUINT32 indexBufferTotalBytesAlloc;
+ gctUINT32 indexBufferNewBytesAlloc;
+ int indexBufferTotalObjectsAlloc;
+ int indexBufferNewObjectsAlloc;
+
+ gctUINT32 textureBufferTotalBytesAlloc;
+ gctUINT32 textureBufferNewBytesAlloc;
+ int textureBufferTotalObjectsAlloc;
+ int textureBufferNewObjectsAlloc;
+
+ gctUINT32 numCommits;
+ gctUINT32 drawPointCount;
+ gctUINT32 drawLineCount;
+ gctUINT32 drawTriangleCount;
+ gctUINT32 drawVertexCount;
+ gctUINT32 redundantStateChangeCalls;
+#endif
+
+#if VIVANTE_PROFILER_PROBE
+ gcsPROBEBUFFER probeBuffer;
+ gctFILE probeFile;
+#endif
+
+}
+gcsPROFILER;
+
+/* Memory profile information. */
+struct _gcsMemProfile
+{
+ /* Memory Usage */
+ gctUINT32 videoMemUsed;
+ gctUINT32 systemMemUsed;
+ gctUINT32 commitBufferSize;
+ gctUINT32 contextBufferCopyBytes;
+};
+
+/* Shader profile information. */
+struct _gcsSHADER_PROFILER
+{
+ gctUINT32 shaderLength;
+ gctUINT32 shaderALUCycles;
+ gctUINT32 shaderTexLoadCycles;
+ gctUINT32 shaderTempRegCount;
+ gctUINT32 shaderSamplerRegCount;
+ gctUINT32 shaderInputRegCount;
+ gctUINT32 shaderOutputRegCount;
+};
+
+/* Construct a Profiler object per context. */
+gceSTATUS
+gcoPROFILER_NEW_Construct(
+ OUT gcoPROFILER * Profiler
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_Destroy(
+ IN gcoPROFILER Profiler
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_Enable(
+ IN gcoPROFILER Profiler
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_Disable(
+ void
+);
+
+gceSTATUS
+gcoPROFILER_NEW_Begin(
+ IN gcoPROFILER Profiler,
+ IN gceCOUNTER_OPTYPE operationType
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_End(
+ IN gcoPROFILER Profiler,
+ IN gctUINT32 DrawID
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_EndFrame(
+ IN gcoPROFILER Profiler
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_RecordCounters(
+ IN gctPOINTER Logical,
+ OUT gcsPROFILER_NEW_COUNTERS * Counters
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_WriteCounters(
+ IN gcoPROFILER Profiler,
+ IN gcsPROFILER_NEW_COUNTERS Counters,
+ IN gctBOOL IsFrameEnd
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_Write(
+ IN gcoPROFILER Profiler,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+gceSTATUS
+gcoPROFILER_NEW_Flush(
+ IN gcoPROFILER Profiler
+ );
+
+/* Initialize the gcsProfiler. */
+gceSTATUS
+gcoPROFILER_Initialize(
+ IN gcoHAL Hal,
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Destroy the gcProfiler. */
+gceSTATUS
+gcoPROFILER_Destroy(
+ IN gcoHAL Hal
+ );
+
+/* Write data to profiler. */
+gceSTATUS
+gcoPROFILER_Write(
+ IN gcoHAL Hal,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+/* Flush data out. */
+gceSTATUS
+gcoPROFILER_Flush(
+ IN gcoHAL Hal
+ );
+
+/* Call to signal end of frame. */
+gceSTATUS
+gcoPROFILER_EndFrame(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoPROFILER_Begin(
+ IN gcoHAL Hal,
+ IN gceCOUNTER_OPTYPE operationType
+ );
+
+/* Call to signal end of draw. */
+gceSTATUS
+gcoPROFILER_End(
+ IN gcoHAL Hal,
+ IN gctBOOL FirstDraw
+ );
+
+/* Increase profile counter Enum by Value. */
+gceSTATUS
+gcoPROFILER_Count(
+ IN gcoHAL Hal,
+ IN gctUINT32 Enum,
+ IN gctINT Value
+ );
+
+/* Profile input vertex shader. */
+gceSTATUS
+gcoPROFILER_ShaderVS(
+ IN gcoHAL Hal,
+ IN gctPOINTER Vs
+ );
+
+/* Profile input fragment shader. */
+gceSTATUS
+gcoPROFILER_ShaderFS(
+ IN gcoHAL Hal,
+ IN gctPOINTER Fs
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_profiler_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h
new file mode 100644
index 000000000000..0ade94abcf68
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_raster.h
@@ -0,0 +1,1057 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_raster_h_
+#define __gc_hal_raster_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoBRUSH * gcoBRUSH;
+typedef struct _gcoBRUSH_CACHE * gcoBRUSH_CACHE;
+
+/******************************************************************************\
+******************************** gcoBRUSH Object *******************************
+\******************************************************************************/
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructSingleColor(
+ IN gcoHAL Hal,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructMonochrome(
+ IN gcoHAL Hal,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructColor(
+ IN gcoHAL Hal,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctPOINTER Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Destroy an gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_Destroy(
+ IN gcoBRUSH Brush
+ );
+
+/******************************************************************************\
+******************************** gcoSURF Object *******************************
+\******************************************************************************/
+
+/* Set cipping rectangle. */
+gceSTATUS
+gcoSURF_SetClipping(
+ IN gcoSURF Surface
+ );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gcoSURF_Clear2D(
+ IN gcoSURF DestSurface,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 LoColor,
+ IN gctUINT32 HiColor
+ );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gcoSURF_Line(
+ IN gcoSURF Surface,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop
+ );
+
+/* Generic rectangular blit. */
+gceSTATUS
+gcoSURF_Blit(
+ IN OPTIONAL gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 RectCount,
+ IN OPTIONAL gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN OPTIONAL gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN OPTIONAL gceSURF_TRANSPARENCY Transparency,
+ IN OPTIONAL gctUINT32 TransparencyColor,
+ IN OPTIONAL gctPOINTER Mask,
+ IN OPTIONAL gceSURF_MONOPACK MaskPack
+ );
+
+/* Monochrome blit. */
+gceSTATUS
+gcoSURF_MonoBlit(
+ IN gcoSURF DestSurface,
+ IN gctPOINTER Source,
+ IN gceSURF_MONOPACK SourcePack,
+ IN gcsPOINT_PTR SourceSize,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsRECT_PTR DestRect,
+ IN OPTIONAL gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gctBOOL ColorConvert,
+ IN gctUINT8 MonoTransparency,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor
+ );
+
+/* Filter blit. */
+gceSTATUS
+gcoSURF_FilterBlit(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gcoSURF_EnableAlphaBlend(
+ IN gcoSURF Surface,
+ IN gctUINT8 SrcGlobalAlphaValue,
+ IN gctUINT8 DstGlobalAlphaValue,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+ IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+ IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+ );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gcoSURF_DisableAlphaBlend(
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoSURF_SetDither(
+ IN gcoSURF Surface,
+ IN gctBOOL Dither
+ );
+
+gceSTATUS
+gcoSURF_Set2DSource(
+ gcoSURF Surface,
+ gceSURF_ROTATION Rotation
+ );
+
+gceSTATUS
+gcoSURF_Set2DTarget(
+ gcoSURF Surface,
+ gceSURF_ROTATION Rotation
+ );
+
+/******************************************************************************\
+********************************** gco2D Object *********************************
+\******************************************************************************/
+
+/* Construct a new gco2D object. */
+gceSTATUS
+gco2D_Construct(
+ IN gcoHAL Hal,
+ OUT gco2D * Hardware
+ );
+
+/* Destroy an gco2D object. */
+gceSTATUS
+gco2D_Destroy(
+ IN gco2D Hardware
+ );
+
+/* Sets the maximum number of brushes in the brush cache. */
+gceSTATUS
+gco2D_SetBrushLimit(
+ IN gco2D Hardware,
+ IN gctUINT MaxCount
+ );
+
+/* Flush the brush. */
+gceSTATUS
+gco2D_FlushBrush(
+ IN gco2D Engine,
+ IN gcoBRUSH Brush,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Program the specified solid color brush. */
+gceSTATUS
+gco2D_LoadSolidBrush(
+ IN gco2D Engine,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask
+ );
+
+gceSTATUS
+gco2D_LoadMonochromeBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask
+ );
+
+gceSTATUS
+gco2D_LoadColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask
+ );
+
+/* Configure monochrome source. */
+gceSTATUS
+gco2D_SetMonochromeSource(
+ IN gco2D Engine,
+ IN gctBOOL ColorConvert,
+ IN gctUINT8 MonoTransparency,
+ IN gceSURF_MONOPACK DataPack,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor
+ );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSource(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 TransparencyColor
+ );
+
+/* Configure color source extension for full rotation. */
+gceSTATUS
+gco2D_SetColorSourceEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 TransparencyColor
+ );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSourceAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctBOOL CoordRelative
+ );
+
+gceSTATUS
+gco2D_SetColorSourceN(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctUINT32 SurfaceNumber
+ );
+
+/* Configure masked color source. */
+gceSTATUS
+gco2D_SetMaskedSource(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_MONOPACK MaskPack
+ );
+
+/* Configure masked color source extension for full rotation. */
+gceSTATUS
+gco2D_SetMaskedSourceEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_MONOPACK MaskPack,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+ );
+
+/* Setup the source rectangle. */
+gceSTATUS
+gco2D_SetSource(
+ IN gco2D Engine,
+ IN gcsRECT_PTR SrcRect
+ );
+
+/* Set clipping rectangle. */
+gceSTATUS
+gco2D_SetClipping(
+ IN gco2D Engine,
+ IN gcsRECT_PTR Rect
+ );
+
+/* Configure destination. */
+gceSTATUS
+gco2D_SetTarget(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth
+ );
+
+/* Configure destination extension for full rotation. */
+gceSTATUS
+gco2D_SetTargetEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+ );
+
+/* Calculate and program the stretch factors. */
+gceSTATUS
+gco2D_CalcStretchFactor(
+ IN gco2D Engine,
+ IN gctINT32 SrcSize,
+ IN gctINT32 DestSize,
+ OUT gctUINT32_PTR Factor
+ );
+
+gceSTATUS
+gco2D_SetStretchFactors(
+ IN gco2D Engine,
+ IN gctUINT32 HorFactor,
+ IN gctUINT32 VerFactor
+ );
+
+/* Calculate and program the stretch factors based on the rectangles. */
+gceSTATUS
+gco2D_SetStretchRectFactors(
+ IN gco2D Engine,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect
+ );
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructSingleColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructMonochromeBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctPOINTER Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gco2D_Clear(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gco2D_Line(
+ IN gco2D Engine,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Draw one or more Bresenham lines based on the 32-bit color. */
+gceSTATUS
+gco2D_ColorLine(
+ IN gco2D Engine,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Generic blit. */
+gceSTATUS
+gco2D_Blit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+gceSTATUS
+gco2D_Blend(
+ IN gco2D Engine,
+ IN gctUINT32 SrcCount,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Batch blit. */
+gceSTATUS
+gco2D_BatchBlit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Stretch blit. */
+gceSTATUS
+gco2D_StretchBlit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Monochrome blit. */
+gceSTATUS
+gco2D_MonoBlit(
+ IN gco2D Engine,
+ IN gctPOINTER StreamBits,
+ IN gcsPOINT_PTR StreamSize,
+ IN gcsRECT_PTR StreamRect,
+ IN gceSURF_MONOPACK SrcStreamPack,
+ IN gceSURF_MONOPACK DestStreamPack,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 FgRop,
+ IN gctUINT32 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+gceSTATUS
+gco2D_MonoBlitEx(
+ IN gco2D Engine,
+ IN gctPOINTER StreamBits,
+ IN gctINT32 StreamStride,
+ IN gctINT32 StreamWidth,
+ IN gctINT32 StreamHeight,
+ IN gctINT32 StreamX,
+ IN gctINT32 StreamY,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DstRect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop
+ );
+
+/* Set kernel size. */
+gceSTATUS
+gco2D_SetKernelSize(
+ IN gco2D Engine,
+ IN gctUINT8 HorKernelSize,
+ IN gctUINT8 VerKernelSize
+ );
+
+/* Set filter type. */
+gceSTATUS
+gco2D_SetFilterType(
+ IN gco2D Engine,
+ IN gceFILTER_TYPE FilterType
+ );
+
+/* Set the filter kernel by user. */
+gceSTATUS
+gco2D_SetUserFilterKernel(
+ IN gco2D Engine,
+ IN gceFILTER_PASS_TYPE PassType,
+ IN gctUINT16_PTR KernelArray
+ );
+
+/* Select the pass(es) to be done for user defined filter. */
+gceSTATUS
+gco2D_EnableUserFilterPasses(
+ IN gco2D Engine,
+ IN gctBOOL HorPass,
+ IN gctBOOL VerPass
+ );
+
+/* Frees the temporary buffer allocated by filter blit operation. */
+gceSTATUS
+gco2D_FreeFilterBuffer(
+ IN gco2D Engine
+ );
+
+/* Filter blit. */
+gceSTATUS
+gco2D_FilterBlit(
+ IN gco2D Engine,
+ IN gctUINT32 SrcAddress,
+ IN gctUINT SrcStride,
+ IN gctUINT32 SrcUAddress,
+ IN gctUINT SrcUStride,
+ IN gctUINT32 SrcVAddress,
+ IN gctUINT SrcVStride,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32 DestAddress,
+ IN gctUINT DestStride,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Filter blit extension for full rotation. */
+gceSTATUS
+gco2D_FilterBlitEx(
+ IN gco2D Engine,
+ IN gctUINT32 SrcAddress,
+ IN gctUINT SrcStride,
+ IN gctUINT32 SrcUAddress,
+ IN gctUINT SrcUStride,
+ IN gctUINT32 SrcVAddress,
+ IN gctUINT SrcVStride,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gctUINT32 SrcSurfaceHeight,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32 DestAddress,
+ IN gctUINT DestStride,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gctUINT32 DestSurfaceHeight,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+gceSTATUS
+gco2D_FilterBlitEx2(
+ IN gco2D Engine,
+ IN gctUINT32_PTR SrcAddresses,
+ IN gctUINT32 SrcAddressNum,
+ IN gctUINT32_PTR SrcStrides,
+ IN gctUINT32 SrcStrideNum,
+ IN gceTILING SrcTiling,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gctUINT32 SrcSurfaceHeight,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32_PTR DestAddresses,
+ IN gctUINT32 DestAddressNum,
+ IN gctUINT32_PTR DestStrides,
+ IN gctUINT32 DestStrideNum,
+ IN gceTILING DestTiling,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gctUINT32 DestSurfaceHeight,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gco2D_EnableAlphaBlend(
+ IN gco2D Engine,
+ IN gctUINT8 SrcGlobalAlphaValue,
+ IN gctUINT8 DstGlobalAlphaValue,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+ IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+ IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+ );
+
+/* Enable alpha blending engine in the hardware. */
+gceSTATUS
+gco2D_EnableAlphaBlendAdvanced(
+ IN gco2D Engine,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode
+ );
+
+/* Enable alpha blending engine with Porter Duff rule. */
+gceSTATUS
+gco2D_SetPorterDuffBlending(
+ IN gco2D Engine,
+ IN gce2D_PORTER_DUFF_RULE Rule
+ );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gco2D_DisableAlphaBlend(
+ IN gco2D Engine
+ );
+
+/* Retrieve the maximum number of 32-bit data chunks for a single DE command. */
+gctUINT32
+gco2D_GetMaximumDataCount(
+ void
+ );
+
+/* Retrieve the maximum number of rectangles, that can be passed in a single DE command. */
+gctUINT32
+gco2D_GetMaximumRectCount(
+ void
+ );
+
+/* Returns the pixel alignment of the surface. */
+gceSTATUS
+gco2D_GetPixelAlignment(
+ gceSURF_FORMAT Format,
+ gcsPOINT_PTR Alignment
+ );
+
+/* Retrieve monochrome stream pack size. */
+gceSTATUS
+gco2D_GetPackSize(
+ IN gceSURF_MONOPACK StreamPack,
+ OUT gctUINT32 * PackWidth,
+ OUT gctUINT32 * PackHeight
+ );
+
+/* Flush the 2D pipeline. */
+gceSTATUS
+gco2D_Flush(
+ IN gco2D Engine
+ );
+
+/* Load 256-entry color table for INDEX8 source surfaces. */
+gceSTATUS
+gco2D_LoadPalette(
+ IN gco2D Engine,
+ IN gctUINT FirstIndex,
+ IN gctUINT IndexCount,
+ IN gctPOINTER ColorTable,
+ IN gctBOOL ColorConvert
+ );
+
+/* Enable/disable 2D BitBlt mirrorring. */
+gceSTATUS
+gco2D_SetBitBlitMirror(
+ IN gco2D Engine,
+ IN gctBOOL HorizontalMirror,
+ IN gctBOOL VerticalMirror
+ );
+
+/*
+ * Set the transparency for source, destination and pattern.
+ * It also enable or disable the DFB color key mode.
+ */
+gceSTATUS
+gco2D_SetTransparencyAdvancedEx(
+ IN gco2D Engine,
+ IN gce2D_TRANSPARENCY SrcTransparency,
+ IN gce2D_TRANSPARENCY DstTransparency,
+ IN gce2D_TRANSPARENCY PatTransparency,
+ IN gctBOOL EnableDFBColorKeyMode
+ );
+
+/* Set the transparency for source, destination and pattern. */
+gceSTATUS
+gco2D_SetTransparencyAdvanced(
+ IN gco2D Engine,
+ IN gce2D_TRANSPARENCY SrcTransparency,
+ IN gce2D_TRANSPARENCY DstTransparency,
+ IN gce2D_TRANSPARENCY PatTransparency
+ );
+
+/* Set the source color key. */
+gceSTATUS
+gco2D_SetSourceColorKeyAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKey
+ );
+
+/* Set the source color key range. */
+gceSTATUS
+gco2D_SetSourceColorKeyRangeAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKeyLow,
+ IN gctUINT32 ColorKeyHigh
+ );
+
+/* Set the target color key. */
+gceSTATUS
+gco2D_SetTargetColorKeyAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKey
+ );
+
+/* Set the target color key range. */
+gceSTATUS
+gco2D_SetTargetColorKeyRangeAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKeyLow,
+ IN gctUINT32 ColorKeyHigh
+ );
+
+/* Set the YUV color space mode. */
+gceSTATUS
+gco2D_SetYUVColorMode(
+ IN gco2D Engine,
+ IN gce2D_YUV_COLOR_MODE Mode
+ );
+
+/* Setup the source global color value in ARGB8 format. */
+gceSTATUS gco2D_SetSourceGlobalColorAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Color32
+ );
+
+/* Setup the target global color value in ARGB8 format. */
+gceSTATUS gco2D_SetTargetGlobalColorAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Color32
+ );
+
+/* Setup the source and target pixel multiply modes. */
+gceSTATUS
+gco2D_SetPixelMultiplyModeAdvanced(
+ IN gco2D Engine,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE SrcPremultiplySrcAlpha,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstPremultiplyDstAlpha,
+ IN gce2D_GLOBAL_COLOR_MULTIPLY_MODE SrcPremultiplyGlobalMode,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstDemultiplyDstAlpha
+ );
+
+/* Set the GPU clock cycles after which the idle engine will keep auto-flushing. */
+gceSTATUS
+gco2D_SetAutoFlushCycles(
+ IN gco2D Engine,
+ IN gctUINT32 Cycles
+ );
+
+#if VIVANTE_PROFILER
+/* Read the profile registers available in the 2D engine and sets them in the profile.
+ The function will also reset the pixelsRendered counter every time.
+*/
+gceSTATUS
+gco2D_ProfileEngine(
+ IN gco2D Engine,
+ OPTIONAL gcs2D_PROFILE_PTR Profile
+ );
+#endif
+
+/* Enable or disable 2D dithering. */
+gceSTATUS
+gco2D_EnableDither(
+ IN gco2D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco2D_SetGenericSource(
+ IN gco2D Engine,
+ IN gctUINT32_PTR Addresses,
+ IN gctUINT32 AddressNum,
+ IN gctUINT32_PTR Strides,
+ IN gctUINT32 StrideNum,
+ IN gceTILING Tiling,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+);
+
+gceSTATUS
+gco2D_SetGenericTarget(
+ IN gco2D Engine,
+ IN gctUINT32_PTR Addresses,
+ IN gctUINT32 AddressNum,
+ IN gctUINT32_PTR Strides,
+ IN gctUINT32 StrideNum,
+ IN gceTILING Tiling,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+);
+
+gceSTATUS
+gco2D_SetCurrentSourceIndex(
+ IN gco2D Engine,
+ IN gctUINT32 SrcIndex
+ );
+
+gceSTATUS
+gco2D_MultiSourceBlit(
+ IN gco2D Engine,
+ IN gctUINT32 SourceMask,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 RectCount
+ );
+
+gceSTATUS
+gco2D_SetROP(
+ IN gco2D Engine,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop
+ );
+
+gceSTATUS
+gco2D_SetGdiStretchMode(
+ IN gco2D Engine,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gco2D_SetSourceTileStatus(
+ IN gco2D Engine,
+ IN gce2D_TILE_STATUS_CONFIG TSControl,
+ IN gceSURF_FORMAT CompressedFormat,
+ IN gctUINT32 ClearValue,
+ IN gctUINT32 GpuAddress
+ );
+
+gceSTATUS
+gco2D_SetTargetTileStatus(
+ IN gco2D Engine,
+ IN gce2D_TILE_STATUS_CONFIG TileStatusConfig,
+ IN gceSURF_FORMAT CompressedFormat,
+ IN gctUINT32 ClearValue,
+ IN gctUINT32 GpuAddress
+ );
+
+gceSTATUS
+gco2D_QueryU32(
+ IN gco2D Engine,
+ IN gce2D_QUERY Item,
+ OUT gctUINT32_PTR Value
+ );
+
+gceSTATUS
+gco2D_SetStateU32(
+ IN gco2D Engine,
+ IN gce2D_STATE State,
+ IN gctUINT32 Value
+ );
+
+gceSTATUS
+gco2D_SetStateArrayI32(
+ IN gco2D Engine,
+ IN gce2D_STATE State,
+ IN gctINT32_PTR Array,
+ IN gctINT32 ArraySize
+ );
+
+gceSTATUS
+gco2D_SetStateArrayU32(
+ IN gco2D Engine,
+ IN gce2D_STATE State,
+ IN gctUINT32_PTR Array,
+ IN gctINT32 ArraySize
+ );
+
+gceSTATUS
+gco2D_SetTargetRect(
+ IN gco2D Engine,
+ IN gcsRECT_PTR Rect
+ );
+
+gceSTATUS
+gco2D_Set2DEngine(
+ IN gco2D Engine
+ );
+
+gceSTATUS
+gco2D_UnSet2DEngine(
+ IN gco2D Engine
+ );
+
+gceSTATUS
+gco2D_Get2DEngine(
+ OUT gco2D * Engine
+ );
+
+gceSTATUS
+gco2D_Commit(
+ IN gco2D Engine,
+ IN gctBOOL Stall
+ );
+
+gceSTATUS
+gco2D_NatureRotateTranslation(
+ IN gctBOOL IsSrcRot,
+ IN gce2D_NATURE_ROTATION NatureRotation,
+ IN gctINT32 SrcSurfaceWidth,
+ IN gctINT32 SrcSurfaceHeight,
+ IN gctINT32 DstSurfaceWidth,
+ IN gctINT32 DstSurfaceHeight,
+ IN OUT gcsRECT_PTR SrcRect,
+ IN OUT gcsRECT_PTR DstRect,
+ OUT gceSURF_ROTATION * SrcRotation,
+ OUT gceSURF_ROTATION * DstRotation
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_raster_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h
new file mode 100644
index 000000000000..a7b394d7b293
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_rename.h
@@ -0,0 +1,277 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_rename_h_
+#define __gc_hal_rename_h_
+
+
+#if defined(_HAL2D_APPENDIX)
+
+#define _HAL2D_RENAME_2(api, appendix) api ## appendix
+#define _HAL2D_RENAME_1(api, appendix) _HAL2D_RENAME_2(api, appendix)
+#define gcmHAL2D(api) _HAL2D_RENAME_1(api, _HAL2D_APPENDIX)
+
+
+#define gckOS_Construct gcmHAL2D(gckOS_Construct)
+#define gckOS_Destroy gcmHAL2D(gckOS_Destroy)
+#define gckOS_QueryVideoMemory gcmHAL2D(gckOS_QueryVideoMemory)
+#define gckOS_Allocate gcmHAL2D(gckOS_Allocate)
+#define gckOS_Free gcmHAL2D(gckOS_Free)
+#define gckOS_AllocateMemory gcmHAL2D(gckOS_AllocateMemory)
+#define gckOS_FreeMemory gcmHAL2D(gckOS_FreeMemory)
+#define gckOS_AllocatePagedMemory gcmHAL2D(gckOS_AllocatePagedMemory)
+#define gckOS_AllocatePagedMemoryEx gcmHAL2D(gckOS_AllocatePagedMemoryEx)
+#define gckOS_LockPages gcmHAL2D(gckOS_LockPages)
+#define gckOS_MapPages gcmHAL2D(gckOS_MapPages)
+#define gckOS_UnlockPages gcmHAL2D(gckOS_UnlockPages)
+#define gckOS_FreePagedMemory gcmHAL2D(gckOS_FreePagedMemory)
+#define gckOS_AllocateNonPagedMemory gcmHAL2D(gckOS_AllocateNonPagedMemory)
+#define gckOS_FreeNonPagedMemory gcmHAL2D(gckOS_FreeNonPagedMemory)
+#define gckOS_AllocateContiguous gcmHAL2D(gckOS_AllocateContiguous)
+#define gckOS_FreeContiguous gcmHAL2D(gckOS_FreeContiguous)
+#define gckOS_GetPageSize gcmHAL2D(gckOS_GetPageSize)
+#define gckOS_GetPhysicalAddress gcmHAL2D(gckOS_GetPhysicalAddress)
+#define gckOS_UserLogicalToPhysical gcmHAL2D(gckOS_UserLogicalToPhysical)
+#define gckOS_GetPhysicalAddressProcess gcmHAL2D(gckOS_GetPhysicalAddressProcess)
+#define gckOS_MapPhysical gcmHAL2D(gckOS_MapPhysical)
+#define gckOS_UnmapPhysical gcmHAL2D(gckOS_UnmapPhysical)
+#define gckOS_ReadRegister gcmHAL2D(gckOS_ReadRegister)
+#define gckOS_WriteRegister gcmHAL2D(gckOS_WriteRegister)
+#define gckOS_WriteMemory gcmHAL2D(gckOS_WriteMemory)
+#define gckOS_MapMemory gcmHAL2D(gckOS_MapMemory)
+#define gckOS_UnmapMemory gcmHAL2D(gckOS_UnmapMemory)
+#define gckOS_UnmapMemoryEx gcmHAL2D(gckOS_UnmapMemoryEx)
+#define gckOS_CreateMutex gcmHAL2D(gckOS_CreateMutex)
+#define gckOS_DeleteMutex gcmHAL2D(gckOS_DeleteMutex)
+#define gckOS_AcquireMutex gcmHAL2D(gckOS_AcquireMutex)
+#define gckOS_ReleaseMutex gcmHAL2D(gckOS_ReleaseMutex)
+#define gckOS_AtomicExchange gcmHAL2D(gckOS_AtomicExchange)
+#define gckOS_AtomicExchangePtr gcmHAL2D(gckOS_AtomicExchangePtr)
+#define gckOS_AtomConstruct gcmHAL2D(gckOS_AtomConstruct)
+#define gckOS_AtomDestroy gcmHAL2D(gckOS_AtomDestroy)
+#define gckOS_AtomGet gcmHAL2D(gckOS_AtomGet)
+#define gckOS_AtomIncrement gcmHAL2D(gckOS_AtomIncrement)
+#define gckOS_AtomDecrement gcmHAL2D(gckOS_AtomDecrement)
+#define gckOS_Delay gcmHAL2D(gckOS_Delay)
+#define gckOS_GetTime gcmHAL2D(gckOS_GetTime)
+#define gckOS_MemoryBarrier gcmHAL2D(gckOS_MemoryBarrier)
+#define gckOS_MapUserPointer gcmHAL2D(gckOS_MapUserPointer)
+#define gckOS_UnmapUserPointer gcmHAL2D(gckOS_UnmapUserPointer)
+#define gckOS_QueryNeedCopy gcmHAL2D(gckOS_QueryNeedCopy)
+#define gckOS_CopyFromUserData gcmHAL2D(gckOS_CopyFromUserData)
+#define gckOS_CopyToUserData gcmHAL2D(gckOS_CopyToUserData)
+#define gckOS_SuspendInterrupt gcmHAL2D(gckOS_SuspendInterrupt)
+#define gckOS_ResumeInterrupt gcmHAL2D(gckOS_ResumeInterrupt)
+#define gckOS_GetBaseAddress gcmHAL2D(gckOS_GetBaseAddress)
+#define gckOS_MemCopy gcmHAL2D(gckOS_MemCopy)
+#define gckOS_ZeroMemory gcmHAL2D(gckOS_ZeroMemory)
+#define gckOS_DeviceControl gcmHAL2D(gckOS_DeviceControl)
+#define gckOS_GetProcessID gcmHAL2D(gckOS_GetProcessID)
+#define gckOS_GetThreadID gcmHAL2D(gckOS_GetThreadID)
+#define gckOS_CreateSignal gcmHAL2D(gckOS_CreateSignal)
+#define gckOS_DestroySignal gcmHAL2D(gckOS_DestroySignal)
+#define gckOS_Signal gcmHAL2D(gckOS_Signal)
+#define gckOS_WaitSignal gcmHAL2D(gckOS_WaitSignal)
+#define gckOS_MapSignal gcmHAL2D(gckOS_MapSignal)
+#define gckOS_MapUserMemory gcmHAL2D(gckOS_MapUserMemory)
+#define gckOS_UnmapUserMemory gcmHAL2D(gckOS_UnmapUserMemory)
+#define gckOS_CreateUserSignal gcmHAL2D(gckOS_CreateUserSignal)
+#define gckOS_DestroyUserSignal gcmHAL2D(gckOS_DestroyUserSignal)
+#define gckOS_WaitUserSignal gcmHAL2D(gckOS_WaitUserSignal)
+#define gckOS_SignalUserSignal gcmHAL2D(gckOS_SignalUserSignal)
+#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
+#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
+#define gckOS_CacheClean gcmHAL2D(gckOS_CacheClean)
+#define gckOS_CacheFlush gcmHAL2D(gckOS_CacheFlush)
+#define gckOS_SetDebugLevel gcmHAL2D(gckOS_SetDebugLevel)
+#define gckOS_SetDebugZone gcmHAL2D(gckOS_SetDebugZone)
+#define gckOS_SetDebugLevelZone gcmHAL2D(gckOS_SetDebugLevelZone)
+#define gckOS_SetDebugZones gcmHAL2D(gckOS_SetDebugZones)
+#define gckOS_SetDebugFile gcmHAL2D(gckOS_SetDebugFile)
+#define gckOS_Broadcast gcmHAL2D(gckOS_Broadcast)
+#define gckOS_SetGPUPower gcmHAL2D(gckOS_SetGPUPower)
+#define gckOS_CreateSemaphore gcmHAL2D(gckOS_CreateSemaphore)
+#define gckOS_DestroySemaphore gcmHAL2D(gckOS_DestroySemaphore)
+#define gckOS_AcquireSemaphore gcmHAL2D(gckOS_AcquireSemaphore)
+#define gckOS_ReleaseSemaphore gcmHAL2D(gckOS_ReleaseSemaphore)
+#define gckHEAP_Construct gcmHAL2D(gckHEAP_Construct)
+#define gckHEAP_Destroy gcmHAL2D(gckHEAP_Destroy)
+#define gckHEAP_Allocate gcmHAL2D(gckHEAP_Allocate)
+#define gckHEAP_Free gcmHAL2D(gckHEAP_Free)
+#define gckHEAP_ProfileStart gcmHAL2D(gckHEAP_ProfileStart)
+#define gckHEAP_ProfileEnd gcmHAL2D(gckHEAP_ProfileEnd)
+#define gckHEAP_Test gcmHAL2D(gckHEAP_Test)
+#define gckVIDMEM_Construct gcmHAL2D(gckVIDMEM_Construct)
+#define gckVIDMEM_Destroy gcmHAL2D(gckVIDMEM_Destroy)
+#define gckVIDMEM_Allocate gcmHAL2D(gckVIDMEM_Allocate)
+#define gckVIDMEM_AllocateLinear gcmHAL2D(gckVIDMEM_AllocateLinear)
+#define gckVIDMEM_Free gcmHAL2D(gckVIDMEM_Free)
+#define gckVIDMEM_Lock gcmHAL2D(gckVIDMEM_Lock)
+#define gckVIDMEM_Unlock gcmHAL2D(gckVIDMEM_Unlock)
+#define gckVIDMEM_ConstructVirtual gcmHAL2D(gckVIDMEM_ConstructVirtual)
+#define gckVIDMEM_DestroyVirtual gcmHAL2D(gckVIDMEM_DestroyVirtual)
+#define gckKERNEL_Construct gcmHAL2D(gckKERNEL_Construct)
+#define gckKERNEL_Destroy gcmHAL2D(gckKERNEL_Destroy)
+#define gckKERNEL_Dispatch gcmHAL2D(gckKERNEL_Dispatch)
+#define gckKERNEL_QueryVideoMemory gcmHAL2D(gckKERNEL_QueryVideoMemory)
+#define gckKERNEL_GetVideoMemoryPool gcmHAL2D(gckKERNEL_GetVideoMemoryPool)
+#define gckKERNEL_MapVideoMemory gcmHAL2D(gckKERNEL_MapVideoMemory)
+#define gckKERNEL_UnmapVideoMemory gcmHAL2D(gckKERNEL_UnmapVideoMemory)
+#define gckKERNEL_MapMemory gcmHAL2D(gckKERNEL_MapMemory)
+#define gckKERNEL_UnmapMemory gcmHAL2D(gckKERNEL_UnmapMemory)
+#define gckKERNEL_Notify gcmHAL2D(gckKERNEL_Notify)
+#define gckKERNEL_QuerySettings gcmHAL2D(gckKERNEL_QuerySettings)
+#define gckKERNEL_Recovery gcmHAL2D(gckKERNEL_Recovery)
+#define gckKERNEL_OpenUserData gcmHAL2D(gckKERNEL_OpenUserData)
+#define gckKERNEL_CloseUserData gcmHAL2D(gckKERNEL_CloseUserData)
+#define gckHARDWARE_Construct gcmHAL2D(gckHARDWARE_Construct)
+#define gckHARDWARE_Destroy gcmHAL2D(gckHARDWARE_Destroy)
+#define gckHARDWARE_QuerySystemMemory gcmHAL2D(gckHARDWARE_QuerySystemMemory)
+#define gckHARDWARE_BuildVirtualAddress gcmHAL2D(gckHARDWARE_BuildVirtualAddress)
+#define gckHARDWARE_QueryCommandBuffer gcmHAL2D(gckHARDWARE_QueryCommandBuffer)
+#define gckHARDWARE_WaitLink gcmHAL2D(gckHARDWARE_WaitLink)
+#define gckHARDWARE_Execute gcmHAL2D(gckHARDWARE_Execute)
+#define gckHARDWARE_End gcmHAL2D(gckHARDWARE_End)
+#define gckHARDWARE_Nop gcmHAL2D(gckHARDWARE_Nop)
+#define gckHARDWARE_PipeSelect gcmHAL2D(gckHARDWARE_PipeSelect)
+#define gckHARDWARE_Link gcmHAL2D(gckHARDWARE_Link)
+#define gckHARDWARE_Event gcmHAL2D(gckHARDWARE_Event)
+#define gckHARDWARE_QueryMemory gcmHAL2D(gckHARDWARE_QueryMemory)
+#define gckHARDWARE_QueryChipIdentity gcmHAL2D(gckHARDWARE_QueryChipIdentity)
+#define gckHARDWARE_QueryChipSpecs gcmHAL2D(gckHARDWARE_QueryChipSpecs)
+#define gckHARDWARE_QueryShaderCaps gcmHAL2D(gckHARDWARE_QueryShaderCaps)
+#define gckHARDWARE_ConvertFormat gcmHAL2D(gckHARDWARE_ConvertFormat)
+#define gckHARDWARE_SplitMemory gcmHAL2D(gckHARDWARE_SplitMemory)
+#define gckHARDWARE_AlignToTile gcmHAL2D(gckHARDWARE_AlignToTile)
+#define gckHARDWARE_UpdateQueueTail gcmHAL2D(gckHARDWARE_UpdateQueueTail)
+#define gckHARDWARE_ConvertLogical gcmHAL2D(gckHARDWARE_ConvertLogical)
+#define gckHARDWARE_Interrupt gcmHAL2D(gckHARDWARE_Interrupt)
+#define gckHARDWARE_SetMMU gcmHAL2D(gckHARDWARE_SetMMU)
+#define gckHARDWARE_FlushMMU gcmHAL2D(gckHARDWARE_FlushMMU)
+#define gckHARDWARE_GetIdle gcmHAL2D(gckHARDWARE_GetIdle)
+#define gckHARDWARE_Flush gcmHAL2D(gckHARDWARE_Flush)
+#define gckHARDWARE_SetFastClear gcmHAL2D(gckHARDWARE_SetFastClear)
+#define gckHARDWARE_ReadInterrupt gcmHAL2D(gckHARDWARE_ReadInterrupt)
+#define gckHARDWARE_SetPowerManagementState gcmHAL2D(gckHARDWARE_SetPowerManagementState)
+#define gckHARDWARE_QueryPowerManagementState gcmHAL2D(gckHARDWARE_QueryPowerManagementState)
+#define gckHARDWARE_ProfileEngine2D gcmHAL2D(gckHARDWARE_ProfileEngine2D)
+#define gckHARDWARE_InitializeHardware gcmHAL2D(gckHARDWARE_InitializeHardware)
+#define gckHARDWARE_Reset gcmHAL2D(gckHARDWARE_Reset)
+#define gckINTERRUPT_Construct gcmHAL2D(gckINTERRUPT_Construct)
+#define gckINTERRUPT_Destroy gcmHAL2D(gckINTERRUPT_Destroy)
+#define gckINTERRUPT_SetHandler gcmHAL2D(gckINTERRUPT_SetHandler)
+#define gckINTERRUPT_Notify gcmHAL2D(gckINTERRUPT_Notify)
+#define gckEVENT_Construct gcmHAL2D(gckEVENT_Construct)
+#define gckEVENT_Destroy gcmHAL2D(gckEVENT_Destroy)
+#define gckEVENT_AddList gcmHAL2D(gckEVENT_AddList)
+#define gckEVENT_FreeNonPagedMemory gcmHAL2D(gckEVENT_FreeNonPagedMemory)
+#define gckEVENT_FreeContiguousMemory gcmHAL2D(gckEVENT_FreeContiguousMemory)
+#define gckEVENT_FreeVideoMemory gcmHAL2D(gckEVENT_FreeVideoMemory)
+#define gckEVENT_Signal gcmHAL2D(gckEVENT_Signal)
+#define gckEVENT_Unlock gcmHAL2D(gckEVENT_Unlock)
+#define gckEVENT_Submit gcmHAL2D(gckEVENT_Submit)
+#define gckEVENT_Commit gcmHAL2D(gckEVENT_Commit)
+#define gckEVENT_Notify gcmHAL2D(gckEVENT_Notify)
+#define gckEVENT_Interrupt gcmHAL2D(gckEVENT_Interrupt)
+#define gckCOMMAND_Construct gcmHAL2D(gckCOMMAND_Construct)
+#define gckCOMMAND_Destroy gcmHAL2D(gckCOMMAND_Destroy)
+#define gckCOMMAND_EnterCommit gcmHAL2D(gckCOMMAND_EnterCommit)
+#define gckCOMMAND_ExitCommit gcmHAL2D(gckCOMMAND_ExitCommit)
+#define gckCOMMAND_Start gcmHAL2D(gckCOMMAND_Start)
+#define gckCOMMAND_Stop gcmHAL2D(gckCOMMAND_Stop)
+#define gckCOMMAND_Commit gcmHAL2D(gckCOMMAND_Commit)
+#define gckCOMMAND_Reserve gcmHAL2D(gckCOMMAND_Reserve)
+#define gckCOMMAND_Execute gcmHAL2D(gckCOMMAND_Execute)
+#define gckCOMMAND_Stall gcmHAL2D(gckCOMMAND_Stall)
+#define gckCOMMAND_Attach gcmHAL2D(gckCOMMAND_Attach)
+#define gckCOMMAND_Detach gcmHAL2D(gckCOMMAND_Detach)
+#define gckMMU_Construct gcmHAL2D(gckMMU_Construct)
+#define gckMMU_Destroy gcmHAL2D(gckMMU_Destroy)
+#define gckMMU_AllocatePages gcmHAL2D(gckMMU_AllocatePages)
+#define gckMMU_FreePages gcmHAL2D(gckMMU_FreePages)
+#define gckMMU_Test gcmHAL2D(gckMMU_Test)
+#define gckHARDWARE_QueryProfileRegisters gcmHAL2D(gckHARDWARE_QueryProfileRegisters)
+
+
+#define FindMdlMap gcmHAL2D(FindMdlMap)
+#define OnProcessExit gcmHAL2D(OnProcessExit)
+
+#define gckGALDEVICE_Destroy gcmHAL2D(gckGALDEVICE_Destroy)
+#define gckOS_Print gcmHAL2D(gckOS_Print)
+#define gckGALDEVICE_FreeMemory gcmHAL2D(gckGALDEVICE_FreeMemory)
+#define gckGALDEVICE_AllocateMemory gcmHAL2D(gckGALDEVICE_AllocateMemory)
+#define gckOS_DebugBreak gcmHAL2D(gckOS_DebugBreak)
+#define gckGALDEVICE_Release_ISR gcmHAL2D(gckGALDEVICE_Release_ISR)
+#define gckOS_Verify gcmHAL2D(gckOS_Verify)
+#define gckCOMMAND_Release gcmHAL2D(gckCOMMAND_Release)
+#define gckGALDEVICE_Stop gcmHAL2D(gckGALDEVICE_Stop)
+#define gckGALDEVICE_Construct gcmHAL2D(gckGALDEVICE_Construct)
+#define gckOS_DebugFatal gcmHAL2D(gckOS_DebugFatal)
+#define gckOS_DebugTrace gcmHAL2D(gckOS_DebugTrace)
+#define gckHARDWARE_GetBaseAddress gcmHAL2D(gckHARDWARE_GetBaseAddress)
+#define gckGALDEVICE_Setup_ISR gcmHAL2D(gckGALDEVICE_Setup_ISR)
+#define gckKERNEL_AttachProcess gcmHAL2D(gckKERNEL_AttachProcess)
+#define gckKERNEL_AttachProcessEx gcmHAL2D(gckKERNEL_AttachProcessEx)
+#define gckGALDEVICE_Start_Thread gcmHAL2D(gckGALDEVICE_Start_Thread)
+#define gckHARDWARE_QueryIdle gcmHAL2D(gckHARDWARE_QueryIdle)
+#define gckGALDEVICE_Start gcmHAL2D(gckGALDEVICE_Start)
+#define gckOS_GetKernelLogical gcmHAL2D(gckOS_GetKernelLogical)
+#define gckOS_DebugTraceZone gcmHAL2D(gckOS_DebugTraceZone)
+#define gckGALDEVICE_Stop_Thread gcmHAL2D(gckGALDEVICE_Stop_Thread)
+#define gckHARDWARE_NeedBaseAddress gcmHAL2D(gckHARDWARE_NeedBaseAddress)
+
+#endif
+
+#endif /* __gc_hal_rename_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_resource.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_resource.h
new file mode 100644
index 000000000000..90d82b223b68
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_resource.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_resource_h_
+#define __gc_hal_resource_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_resource_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h
new file mode 100644
index 000000000000..be08c9c2f714
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_security_interface.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef _GC_HAL_SECURITY_INTERFACE_H_
+#define _GC_HAL_SECURITY_INTERFACE_H_
+/*!
+ @brief Command codes between kernel module and TrustZone
+ @discussion
+ Critical services must be done in TrustZone to avoid sensitive content leak. Most of kernel module is kept in non-Secure os to minimize
+ code in TrustZone.
+ */
+typedef enum kernel_packet_command {
+ KERNEL_START_COMMAND,
+ KERNEL_SUBMIT,
+ KERNEL_MAP_MEMORY, /* */
+ KERNEL_UNMAP_MEMORY,
+ KERNEL_ALLOCATE_SECRUE_MEMORY, /*! Security memory management. */
+ KERNEL_FREE_SECURE_MEMORY,
+ KERNEL_EXECUTE, /* Execute a command buffer. */
+ KERNEL_DUMP_MMU_EXCEPTION,
+ KERNEL_HANDLE_MMU_EXCEPTION,
+ KERNEL_READ_MMU_EXCEPTION,
+} kernel_packet_command_t;
+
+struct kernel_start_command {
+ kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
+ gctUINT8 gpu; /*! Which GPU. */
+ gctUINT32 address;
+ gctUINT32 bytes;
+};
+
+/*!
+ @brief gckCOMMAND Object requests TrustZone to submit command buffer.
+ @discussion
+ Code in trustzone will check content of command buffer after copying command buffer to TrustZone.
+ */
+struct kernel_submit {
+ kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
+ gctUINT8 gpu; /*! Which GPU. */
+ gctUINT8 kernel_command; /*! Whether it is a kernel command. */
+ gctUINT32 command_buffer_handle; /*! Handle to command buffer. */
+ gctUINT32 offset; /* Offset in command buffer. */
+ gctUINT32 * command_buffer; /*! Content of command buffer need to be submit. */
+ gctUINT32 command_buffer_length; /*! Length of command buffer. */
+};
+
+
+/*!
+ @brief gckVIDMEM Object requests TrustZone to allocate security memory.
+ @discussion
+ Allocate a buffer from security GPU memory.
+ */
+struct kernel_allocate_security_memory {
+ kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
+ gctUINT32 bytes; /*! Requested bytes. */
+ gctUINT32 memory_handle; /*! Handle of allocated memory. */
+};
+
+/*!
+ @brief gckVIDMEM Object requests TrustZone to allocate security memory.
+ @discussion
+ Free a video memory buffer from security GPU memory.
+ */
+struct kernel_free_security_memory {
+ kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
+ gctUINT32 memory_handle; /*! Handle of allocated memory. */
+};
+
+struct kernel_execute {
+ kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
+ gctUINT8 gpu; /*! Which GPU. */
+ gctUINT8 kernel_command; /*! Whether it is a kernel command. */
+ gctUINT32 * command_buffer; /*! Content of command buffer need to be submit. */
+ gctUINT32 command_buffer_length; /*! Length of command buffer. */
+};
+
+typedef struct kernel_map_scatter_gather {
+ gctUINT32 bytes;
+ gctUINT32 physical;
+ struct kernel_map_scatter_gather *next;
+}
+kernel_map_scatter_gather_t;
+
+struct kernel_map_memory {
+ kernel_packet_command_t command;
+ kernel_map_scatter_gather_t *scatter;
+ gctUINT32 *physicals;
+ gctPHYS_ADDR_T physical; /*! Contiguous physical address range. */
+ gctUINT32 pageCount;
+ gctUINT32 gpuAddress;
+};
+
+struct kernel_unmap_memory {
+ gctUINT32 gpuAddress;
+ gctUINT32 pageCount;
+};
+
+struct kernel_read_mmu_exception {
+ gctUINT32 mmuStatus;
+ gctUINT32 mmuException;
+};
+
+struct kernel_handle_mmu_exception {
+ gctUINT32 mmuStatus;
+ gctPHYS_ADDR_T physical;
+ gctUINT32 gpuAddress;
+};
+
+typedef struct _gcsTA_INTERFACE {
+ kernel_packet_command_t command;
+ union {
+ struct kernel_submit Submit;
+ struct kernel_start_command StartCommand;
+ struct kernel_allocate_security_memory AllocateSecurityMemory;
+ struct kernel_execute Execute;
+ struct kernel_map_memory MapMemory;
+ struct kernel_unmap_memory UnmapMemory;
+ struct kernel_read_mmu_exception ReadMMUException;
+ struct kernel_handle_mmu_exception HandleMMUException;
+ } u;
+ gceSTATUS result;
+} gcsTA_INTERFACE;
+
+enum {
+ gcvTA_COMMAND_INIT,
+ gcvTA_COMMAND_DISPATCH,
+
+ gcvTA_CALLBACK_ALLOC_SECURE_MEM,
+ gcvTA_CALLBACK_FREE_SECURE_MEM,
+};
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h
new file mode 100644
index 000000000000..5a33b01f5d3b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_statistics.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_statistics_h_
+#define __gc_hal_statistics_h_
+
+
+#define VIV_STAT_ENABLE_STATISTICS 0
+
+/* Toal number of frames for which the frame time is accounted. We have storage
+ to keep frame times for last this many frames.
+*/
+#define VIV_STAT_FRAME_BUFFER_SIZE 30
+
+
+/*
+ Total number of frames sampled for a mode. This means
+
+ # of frames for HZ Current : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
+ # of frames for HZ Switched : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
+ +
+ --------------------------------------------------------
+ : (2 * VIV_STAT_EARLY_Z_SAMPLE_FRAMES) frames needed
+
+ IMPORTANT: This total must be smaller than VIV_STAT_FRAME_BUFFER_SIZE
+*/
+#define VIV_STAT_EARLY_Z_SAMPLE_FRAMES 7
+#define VIV_STAT_EARLY_Z_LATENCY_FRAMES 2
+
+/* Multiplication factor for previous Hz off mode. Make it more than 1.0 to advertise HZ on.*/
+#define VIV_STAT_EARLY_Z_FACTOR (1.05f)
+
+/* Defines the statistical data keys monitored by the statistics module */
+typedef enum _gceSTATISTICS
+{
+ gcvFRAME_FPS = 1,
+}
+gceSTATISTICS;
+
+/* HAL statistics information. */
+typedef struct _gcsSTATISTICS_EARLYZ
+{
+ gctUINT switchBackCount;
+ gctUINT nextCheckPoint;
+ gctBOOL disabled;
+}
+gcsSTATISTICS_EARLYZ;
+
+
+/* HAL statistics information. */
+typedef struct _gcsSTATISTICS
+{
+ gctUINT64 frameTime[VIV_STAT_FRAME_BUFFER_SIZE];
+ gctUINT64 previousFrameTime;
+ gctUINT frame;
+ gcsSTATISTICS_EARLYZ earlyZ;
+}
+gcsSTATISTICS;
+
+
+/* Add a frame based data into current statistics. */
+void
+gcfSTATISTICS_AddData(
+ IN gceSTATISTICS Key,
+ IN gctUINT Value
+ );
+
+/* Marks the frame end and triggers statistical calculations and decisions.*/
+void
+gcfSTATISTICS_MarkFrameEnd (
+ void
+ );
+
+/* Sets whether the dynmaic HZ is disabled or not .*/
+void
+gcfSTATISTICS_DisableDynamicEarlyZ (
+ IN gctBOOL Disabled
+ );
+
+#endif /*__gc_hal_statistics_h_ */
+
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h
new file mode 100644
index 000000000000..6677e711d55b
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_types.h
@@ -0,0 +1,1020 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_types_h_
+#define __gc_hal_types_h_
+
+#include "gc_hal_version.h"
+#include "gc_hal_options.h"
+
+#if !defined(VIV_KMD)
+#if defined(__KERNEL__)
+#include "linux/version.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+ typedef unsigned long uintptr_t;
+# endif
+# include "linux/types.h"
+#elif defined(UNDER_CE)
+#include <crtdefs.h>
+#elif defined(_MSC_VER) && (_MSC_VER <= 1500)
+#include <crtdefs.h>
+#include "vadefs.h"
+#elif defined(__QNXNTO__)
+#define _QNX_SOURCE
+#include <stdint.h>
+#include <stddef.h>
+#else
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#endif
+#endif
+
+#ifdef _WIN32
+#pragma warning(disable:4127) /* Conditional expression is constant (do { }
+ ** while(0)). */
+#pragma warning(disable:4100) /* Unreferenced formal parameter. */
+#pragma warning(disable:4204) /* Non-constant aggregate initializer (C99). */
+#pragma warning(disable:4131) /* Uses old-style declarator (for Bison and
+ ** Flex generated files). */
+#pragma warning(disable:4206) /* Translation unit is empty. */
+#pragma warning(disable:4214) /* Nonstandard extension used :
+ ** bit field types other than int. */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+** Platform macros.
+*/
+
+#if defined(__GNUC__)
+# define gcdHAS_ELLIPSIS 1 /* GCC always has it. */
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define gcdHAS_ELLIPSIS 1 /* C99 has it. */
+#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
+# define gcdHAS_ELLIPSIS 1 /* MSVC 2007+ has it. */
+#elif defined(UNDER_CE)
+#if UNDER_CE >= 600
+# define gcdHAS_ELLIPSIS 1
+# else
+# define gcdHAS_ELLIPSIS 0
+# endif
+#else
+# error "gcdHAS_ELLIPSIS: Platform could not be determined"
+#endif
+
+/******************************************************************************\
+************************************ Keyword ***********************************
+\******************************************************************************/
+
+#if defined(ANDROID) && defined(__BIONIC_FORTIFY)
+#if defined(__clang__)
+# define gcmINLINE __inline__ __attribute__ ((always_inline)) __attribute__ ((gnu_inline))
+# else
+# define gcmINLINE __inline__ __attribute__ ((always_inline)) __attribute__ ((gnu_inline)) __attribute__ ((artificial))
+# endif
+#elif ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__APPLE__))
+# define gcmINLINE inline /* C99 keyword. */
+#elif defined(__GNUC__)
+# define gcmINLINE __inline__ /* GNU keyword. */
+#elif defined(_MSC_VER) || defined(UNDER_CE)
+# define gcmINLINE __inline /* Internal keyword. */
+#else
+# error "gcmINLINE: Platform could not be determined"
+#endif
+
+/* Possible debug flags. */
+#define gcdDEBUG_NONE 0
+#define gcdDEBUG_ALL (1 << 0)
+#define gcdDEBUG_FATAL (1 << 1)
+#define gcdDEBUG_TRACE (1 << 2)
+#define gcdDEBUG_BREAK (1 << 3)
+#define gcdDEBUG_ASSERT (1 << 4)
+#define gcdDEBUG_CODE (1 << 5)
+#define gcdDEBUG_STACK (1 << 6)
+
+#define gcmIS_DEBUG(flag) ( gcdDEBUG & (flag | gcdDEBUG_ALL) )
+
+#ifndef gcdDEBUG
+#if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG)
+# define gcdDEBUG gcdDEBUG_ALL
+# else
+# define gcdDEBUG gcdDEBUG_NONE
+# endif
+#endif
+
+#ifdef _USRDLL
+#ifdef _MSC_VER
+#ifdef HAL_EXPORTS
+# define HALAPI __declspec(dllexport)
+# else
+# define HALAPI __declspec(dllimport)
+# endif
+# define HALDECL __cdecl
+# else
+#ifdef HAL_EXPORTS
+# define HALAPI
+# else
+# define HALAPI extern
+# endif
+# endif
+#else
+# define HALAPI
+# define HALDECL
+#endif
+
+/******************************************************************************\
+********************************** Common Types ********************************
+\******************************************************************************/
+
+#define gcvFALSE 0
+#define gcvTRUE 1
+
+#define gcvINFINITE ((gctUINT32) ~0U)
+
+#define gcvINVALID_HANDLE ((gctHANDLE) ~0U)
+
+typedef int gctBOOL;
+typedef gctBOOL * gctBOOL_PTR;
+
+typedef int gctINT;
+typedef signed char gctINT8;
+typedef signed short gctINT16;
+typedef signed int gctINT32;
+typedef signed long long gctINT64;
+
+typedef gctINT * gctINT_PTR;
+typedef gctINT8 * gctINT8_PTR;
+typedef gctINT16 * gctINT16_PTR;
+typedef gctINT32 * gctINT32_PTR;
+typedef gctINT64 * gctINT64_PTR;
+
+typedef unsigned int gctUINT;
+typedef unsigned char gctUINT8;
+typedef unsigned short gctUINT16;
+typedef unsigned int gctUINT32;
+typedef unsigned long long gctUINT64;
+typedef uintptr_t gctUINTPTR_T;
+typedef ptrdiff_t gctPTRDIFF_T;
+
+typedef gctUINT * gctUINT_PTR;
+typedef gctUINT8 * gctUINT8_PTR;
+typedef gctUINT16 * gctUINT16_PTR;
+typedef gctUINT32 * gctUINT32_PTR;
+typedef gctUINT64 * gctUINT64_PTR;
+
+typedef size_t gctSIZE_T;
+typedef gctSIZE_T * gctSIZE_T_PTR;
+typedef gctUINT32 gctTRACE;
+
+#ifdef __cplusplus
+# define gcvNULL 0
+#else
+# define gcvNULL ((void *) 0)
+#endif
+
+#define gcvMAXINT8 0x7f
+#define gcvMININT8 0x80
+#define gcvMAXINT16 0x7fff
+#define gcvMININT16 0x8000
+#define gcvMAXINT32 0x7fffffff
+#define gcvMININT32 0x80000000
+#define gcvMAXINT64 0x7fffffffffffffff
+#define gcvMININT64 0x8000000000000000
+#define gcvMAXUINT8 0xff
+#define gcvMINUINT8 0x0
+#define gcvMAXUINT16 0xffff
+#define gcvMINUINT16 0x0
+#define gcvMAXUINT32 0xffffffff
+#define gcvMINUINT32 0x0
+#define gcvMAXUINT64 0xffffffffffffffff
+#define gcvMINUINT64 0x0
+#define gcvMAXUINTPTR_T (~(gctUINTPTR_T)0)
+
+typedef float gctFLOAT;
+typedef signed int gctFIXED_POINT;
+typedef float * gctFLOAT_PTR;
+
+typedef void * gctPHYS_ADDR;
+typedef void * gctHANDLE;
+typedef void * gctFILE;
+typedef void * gctSIGNAL;
+typedef void * gctWINDOW;
+typedef void * gctIMAGE;
+typedef void * gctSHBUF;
+
+typedef void * gctSEMAPHORE;
+
+typedef void * gctPOINTER;
+typedef const void * gctCONST_POINTER;
+
+typedef char gctCHAR;
+typedef char * gctSTRING;
+typedef const char * gctCONST_STRING;
+
+typedef gctUINT64 gctPHYS_ADDR_T;
+
+typedef struct _gcsCOUNT_STRING
+{
+ gctSIZE_T Length;
+ gctCONST_STRING String;
+}
+gcsCOUNT_STRING;
+
+typedef union _gcuFLOAT_UINT32
+{
+ gctFLOAT f;
+ gctUINT32 u;
+}
+gcuFLOAT_UINT32;
+
+/* Fixed point constants. */
+#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
+#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
+#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
+#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
+#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
+
+
+
+#define gcmFIXEDCLAMP_NEG1_TO_1(_x) \
+ (((_x) < gcvNEGONE_X) \
+ ? gcvNEGONE_X \
+ : (((_x) > gcvONE_X) \
+ ? gcvONE_X \
+ : (_x)))
+
+#define gcmFLOATCLAMP_NEG1_TO_1(_f) \
+ (((_f) < -1.0f) \
+ ? -1.0f \
+ : (((_f) > 1.0f) \
+ ? 1.0f \
+ : (_f)))
+
+
+#define gcmFIXEDCLAMP_0_TO_1(_x) \
+ (((_x) < 0) \
+ ? 0 \
+ : (((_x) > gcvONE_X) \
+ ? gcvONE_X \
+ : (_x)))
+
+#define gcmFLOATCLAMP_0_TO_1(_f) \
+ (((_f) < 0.0f) \
+ ? 0.0f \
+ : (((_f) > 1.0f) \
+ ? 1.0f \
+ : (_f)))
+
+
+/******************************************************************************\
+******************************* Multicast Values *******************************
+\******************************************************************************/
+
+/* Value types. */
+typedef enum _gceVALUE_TYPE
+{
+ gcvVALUE_UINT = 0x0,
+ gcvVALUE_FIXED,
+ gcvVALUE_FLOAT,
+ gcvVALUE_INT,
+
+ /*
+ ** The value need be unsigned denormalized. clamp (0.0-1.0) should be done first.
+ */
+ gcvVALUE_FLAG_UNSIGNED_DENORM = 0x00010000,
+
+ /*
+ ** The value need be signed denormalized. clamp (-1.0-1.0) should be done first.
+ */
+ gcvVALUE_FLAG_SIGNED_DENORM = 0x00020000,
+
+ /*
+ ** The value need to gammar
+ */
+ gcvVALUE_FLAG_GAMMAR = 0x00040000,
+
+ /*
+ ** The value need to convert from float to float16
+ */
+ gcvVALUE_FLAG_FLOAT_TO_FLOAT16 = 0x0080000,
+
+ /*
+ ** Mask for flag field.
+ */
+ gcvVALUE_FLAG_MASK = 0xFFFF0000,
+}
+gceVALUE_TYPE;
+
+/* Value unions. */
+typedef union _gcuVALUE
+{
+ gctUINT uintValue;
+ gctFIXED_POINT fixedValue;
+ gctFLOAT floatValue;
+ gctINT intValue;
+}
+gcuVALUE;
+
+
+
+
+/* Stringizing macro. */
+#define gcmSTRING(Value) #Value
+
+/******************************************************************************\
+******************************* Fixed Point Math *******************************
+\******************************************************************************/
+
+#define gcmXMultiply(x1, x2) gcoMATH_MultiplyFixed(x1, x2)
+#define gcmXDivide(x1, x2) gcoMATH_DivideFixed(x1, x2)
+#define gcmXMultiplyDivide(x1, x2, x3) gcoMATH_MultiplyDivideFixed(x1, x2, x3)
+
+/* 2D Engine profile. */
+typedef struct _gcs2D_PROFILE
+{
+ /* Cycle count.
+ 32bit counter incremented every 2D clock cycle.
+ Wraps back to 0 when the counter overflows.
+ */
+ gctUINT32 cycleCount;
+
+ /* Pixels rendered by the 2D engine.
+ Resets to 0 every time it is read. */
+ gctUINT32 pixelsRendered;
+}
+gcs2D_PROFILE;
+
+/* Macro to combine four characters into a Charcater Code. */
+#define gcmCC(c1, c2, c3, c4) \
+( \
+ (char) (c1) \
+ | \
+ ((char) (c2) << 8) \
+ | \
+ ((char) (c3) << 16) \
+ | \
+ ((char) (c4) << 24) \
+)
+
+#define gcmPRINTABLE(c) ((((c) >= ' ') && ((c) <= '}')) ? ((c) != '%' ? (c) : ' ') : ' ')
+
+#define gcmCC_PRINT(cc) \
+ gcmPRINTABLE((char) ( (cc) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 8) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 16) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 24) & 0xFF))
+
+/******************************************************************************\
+****************************** Function Parameters *****************************
+\******************************************************************************/
+
+#define IN
+#define OUT
+#define INOUT
+#define OPTIONAL
+
+/******************************************************************************\
+********************************* Status Codes *********************************
+\******************************************************************************/
+
+typedef enum _gceSTATUS
+{
+ gcvSTATUS_OK = 0,
+ gcvSTATUS_FALSE = 0,
+ gcvSTATUS_TRUE = 1,
+ gcvSTATUS_NO_MORE_DATA = 2,
+ gcvSTATUS_CACHED = 3,
+ gcvSTATUS_MIPMAP_TOO_LARGE = 4,
+ gcvSTATUS_NAME_NOT_FOUND = 5,
+ gcvSTATUS_NOT_OUR_INTERRUPT = 6,
+ gcvSTATUS_MISMATCH = 7,
+ gcvSTATUS_MIPMAP_TOO_SMALL = 8,
+ gcvSTATUS_LARGER = 9,
+ gcvSTATUS_SMALLER = 10,
+ gcvSTATUS_CHIP_NOT_READY = 11,
+ gcvSTATUS_NEED_CONVERSION = 12,
+ gcvSTATUS_SKIP = 13,
+ gcvSTATUS_DATA_TOO_LARGE = 14,
+ gcvSTATUS_INVALID_CONFIG = 15,
+ gcvSTATUS_CHANGED = 16,
+ gcvSTATUS_NOT_SUPPORT_DITHER = 17,
+ gcvSTATUS_EXECUTED = 18,
+ gcvSTATUS_TERMINATE = 19,
+
+ gcvSTATUS_INVALID_ARGUMENT = -1,
+ gcvSTATUS_INVALID_OBJECT = -2,
+ gcvSTATUS_OUT_OF_MEMORY = -3,
+ gcvSTATUS_MEMORY_LOCKED = -4,
+ gcvSTATUS_MEMORY_UNLOCKED = -5,
+ gcvSTATUS_HEAP_CORRUPTED = -6,
+ gcvSTATUS_GENERIC_IO = -7,
+ gcvSTATUS_INVALID_ADDRESS = -8,
+ gcvSTATUS_CONTEXT_LOSSED = -9,
+ gcvSTATUS_TOO_COMPLEX = -10,
+ gcvSTATUS_BUFFER_TOO_SMALL = -11,
+ gcvSTATUS_INTERFACE_ERROR = -12,
+ gcvSTATUS_NOT_SUPPORTED = -13,
+ gcvSTATUS_MORE_DATA = -14,
+ gcvSTATUS_TIMEOUT = -15,
+ gcvSTATUS_OUT_OF_RESOURCES = -16,
+ gcvSTATUS_INVALID_DATA = -17,
+ gcvSTATUS_INVALID_MIPMAP = -18,
+ gcvSTATUS_NOT_FOUND = -19,
+ gcvSTATUS_NOT_ALIGNED = -20,
+ gcvSTATUS_INVALID_REQUEST = -21,
+ gcvSTATUS_GPU_NOT_RESPONDING = -22,
+ gcvSTATUS_TIMER_OVERFLOW = -23,
+ gcvSTATUS_VERSION_MISMATCH = -24,
+ gcvSTATUS_LOCKED = -25,
+ gcvSTATUS_INTERRUPTED = -26,
+ gcvSTATUS_DEVICE = -27,
+ gcvSTATUS_NOT_MULTI_PIPE_ALIGNED = -28,
+ gcvSTATUS_OUT_OF_SAMPLER = -29,
+
+ /* Linker errors. */
+ gcvSTATUS_GLOBAL_TYPE_MISMATCH = -1000,
+ gcvSTATUS_TOO_MANY_ATTRIBUTES = -1001,
+ gcvSTATUS_TOO_MANY_UNIFORMS = -1002,
+ gcvSTATUS_TOO_MANY_VARYINGS = -1003,
+ gcvSTATUS_UNDECLARED_VARYING = -1004,
+ gcvSTATUS_VARYING_TYPE_MISMATCH = -1005,
+ gcvSTATUS_MISSING_MAIN = -1006,
+ gcvSTATUS_NAME_MISMATCH = -1007,
+ gcvSTATUS_INVALID_INDEX = -1008,
+ gcvSTATUS_UNIFORM_MISMATCH = -1009,
+ gcvSTATUS_UNSAT_LIB_SYMBOL = -1010,
+ gcvSTATUS_TOO_MANY_SHADERS = -1011,
+ gcvSTATUS_LINK_INVALID_SHADERS = -1012,
+ gcvSTATUS_CS_NO_WORKGROUP_SIZE = -1013,
+ gcvSTATUS_LINK_LIB_ERROR = -1014,
+
+ gcvSTATUS_SHADER_VERSION_MISMATCH = -1015,
+ gcvSTATUS_TOO_MANY_INSTRUCTION = -1016,
+ gcvSTATUS_SSBO_MISMATCH = -1017,
+ gcvSTATUS_TOO_MANY_OUTPUT = -1018,
+ gcvSTATUS_TOO_MANY_INPUT = -1019,
+ gcvSTATUS_NOT_SUPPORT_CL = -1020,
+ gcvSTATUS_NOT_SUPPORT_INTEGER = -1021,
+ gcvSTATUS_UNIFORM_TYPE_MISMATCH = -1022,
+
+ gcvSTATUS_MISSING_PRIMITIVE_TYPE = -1023,
+ gcvSTATUS_MISSING_OUTPUT_VERTEX_COUNT = -1024,
+ gcvSTATUS_NON_INVOCATION_ID_AS_INDEX = -1025,
+ gcvSTATUS_INPUT_ARRAY_SIZE_MISMATCH = -1026,
+ gcvSTATUS_OUTPUT_ARRAY_SIZE_MISMATCH = -1027,
+ gcvSTATUS_LOCATION_ALIASED = -1028,
+
+ /* Compiler errors. */
+ gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR = -2000,
+ gcvSTATUS_COMPILER_FE_PARSER_ERROR = -2001,
+
+ /* Recompilation Errors */
+ gcvSTATUS_RECOMPILER_CONVERT_UNIMPLEMENTED = -3000,
+}
+gceSTATUS;
+
+/******************************************************************************\
+********************************* Status Macros ********************************
+\******************************************************************************/
+
+#define gcmIS_ERROR(status) (status < 0)
+#define gcmNO_ERROR(status) (status >= 0)
+#define gcmIS_SUCCESS(status) (status == gcvSTATUS_OK)
+
+/******************************************************************************\
+********************************* Field Macros *********************************
+\******************************************************************************/
+
+#define __gcmSTART(reg_field) \
+ (0 ? reg_field)
+
+#define __gcmEND(reg_field) \
+ (1 ? reg_field)
+
+#define __gcmGETSIZE(reg_field) \
+ (__gcmEND(reg_field) - __gcmSTART(reg_field) + 1)
+
+#define __gcmALIGN(data, reg_field) \
+ (((gctUINT32) (data)) << __gcmSTART(reg_field))
+
+#define __gcmMASK(reg_field) \
+ ((gctUINT32) ((__gcmGETSIZE(reg_field) == 32) \
+ ? ~0U \
+ : (~(~0U << __gcmGETSIZE(reg_field)))))
+
+/*******************************************************************************
+**
+** gcmFIELDMASK
+**
+** Get aligned field mask.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmFIELDMASK(reg, field) \
+( \
+ __gcmALIGN(__gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmGETFIELD
+**
+** Extract the value of a field from specified data.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmGETFIELD(data, reg, field) \
+( \
+ ((((gctUINT32) (data)) >> __gcmSTART(reg##_##field)) \
+ & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+**
+** gcmSETFIELD
+**
+** Set the value of a field within specified data.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETFIELD(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) \
+ & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+ | __gcmALIGN((gctUINT32) (value) \
+ & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmSETFIELDVALUE
+**
+** Set the value of a field within specified data with a
+** predefined value.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Name of the value within the field.
+*/
+#define gcmSETFIELDVALUE(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) \
+ & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+ | __gcmALIGN(reg##_##field##_##value \
+ & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmGETMASKEDFIELDMASK
+**
+** Determine field mask of a masked field.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmGETMASKEDFIELDMASK(reg, field) \
+( \
+ gcmSETFIELD(0, reg, field, ~0U) | \
+ gcmSETFIELD(0, reg, MASK_ ## field, ~0U) \
+)
+
+/*******************************************************************************
+**
+** gcmSETMASKEDFIELD
+**
+** Set the value of a masked field with specified data.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETMASKEDFIELD(reg, field, value) \
+( \
+ gcmSETFIELD (~0U, reg, field, value) & \
+ gcmSETFIELDVALUE(~0U, reg, MASK_ ## field, ENABLED) \
+)
+
+/*******************************************************************************
+**
+** gcmSETMASKEDFIELDVALUE
+**
+** Set the value of a masked field with specified data.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETMASKEDFIELDVALUE(reg, field, value) \
+( \
+ gcmSETFIELDVALUE(~0U, reg, field, value) & \
+ gcmSETFIELDVALUE(~0U, reg, MASK_ ## field, ENABLED) \
+)
+
+/*******************************************************************************
+**
+** gcmVERIFYFIELDVALUE
+**
+** Verify if the value of a field within specified data equals a
+** predefined value.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Name of the value within the field.
+*/
+#define gcmVERIFYFIELDVALUE(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) >> __gcmSTART(reg##_##field) & \
+ __gcmMASK(reg##_##field)) \
+ == \
+ (reg##_##field##_##value & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+** Bit field macros.
+*/
+
+#define __gcmSTARTBIT(Field) \
+ ( 1 ? Field )
+
+#define __gcmBITSIZE(Field) \
+ ( 0 ? Field )
+
+#define __gcmBITMASK(Field) \
+( \
+ (1 << __gcmBITSIZE(Field)) - 1 \
+)
+
+#define gcmGETBITS(Value, Type, Field) \
+( \
+ ( ((Type) (Value)) >> __gcmSTARTBIT(Field) ) \
+ & \
+ __gcmBITMASK(Field) \
+)
+
+#define gcmSETBITS(Value, Type, Field, NewValue) \
+( \
+ ( ((Type) (Value)) \
+ & ~(__gcmBITMASK(Field) << __gcmSTARTBIT(Field)) \
+ ) \
+ | \
+ ( ( ((Type) (NewValue)) \
+ & __gcmBITMASK(Field) \
+ ) << __gcmSTARTBIT(Field) \
+ ) \
+)
+
+/*******************************************************************************
+**
+** gcmISINREGRANGE
+**
+** Verify whether the specified address is in the register range.
+**
+** ARGUMENTS:
+**
+** Address Address to be verified.
+** Name Name of a register.
+*/
+
+#define gcmISINREGRANGE(Address, Name) \
+( \
+ ((Address & (~0U << Name ## _LSB)) == (Name ## _Address >> 2)) \
+)
+
+/******************************************************************************\
+******************************** Ceiling Macro ********************************
+\******************************************************************************/
+#define gcmCEIL(x) (((x) - (gctUINT32)(x)) == 0 ? (gctUINT32)(x) : (gctUINT32)(x) + 1)
+
+/******************************************************************************\
+******************************** Min/Max Macros ********************************
+\******************************************************************************/
+
+#define gcmMIN(x, y) (((x) <= (y)) ? (x) : (y))
+#define gcmMAX(x, y) (((x) >= (y)) ? (x) : (y))
+#define gcmCLAMP(x, min, max) (((x) < (min)) ? (min) : \
+ ((x) > (max)) ? (max) : (x))
+#define gcmABS(x) (((x) < 0) ? -(x) : (x))
+#define gcmNEG(x) (((x) < 0) ? (x) : -(x))
+
+/******************************************************************************\
+******************************** Bit Macro ********************************
+\******************************************************************************/
+#define gcmBITSET(x, y) ((x) & (y))
+/*******************************************************************************
+**
+** gcmPTR2INT
+**
+** Convert a pointer to an integer value.
+**
+** ARGUMENTS:
+**
+** p Pointer value.
+*/
+#define gcmPTR2INT(p) \
+( \
+ (gctUINTPTR_T) (p) \
+)
+
+#define gcmPTR2INT32(p) \
+( \
+ (gctUINT32)(gctUINTPTR_T) (p) \
+)
+
+/*******************************************************************************
+**
+** gcmINT2PTR
+**
+** Convert an integer value into a pointer.
+**
+** ARGUMENTS:
+**
+** v Integer value.
+*/
+
+#define gcmINT2PTR(i) \
+( \
+ (gctPOINTER) (gctUINTPTR_T)(i) \
+)
+
+/*******************************************************************************
+**
+** gcmOFFSETOF
+**
+** Compute the byte offset of a field inside a structure.
+**
+** ARGUMENTS:
+**
+** s Structure name.
+** field Field name.
+*/
+#define gcmOFFSETOF(s, field) \
+( \
+ gcmPTR2INT32(& (((struct s *) 0)->field)) \
+)
+
+/*******************************************************************************
+**
+** gcmCONTAINEROF
+**
+** Get containing structure of a member.
+**
+** ARGUMENTS:
+**
+** Pointer Pointer of member.
+** Type Structure name.
+** Name Field name.
+*/
+#define gcmCONTAINEROF(Pointer, Type, Member) \
+(\
+ (struct Type *)((gctUINTPTR_T)Pointer - gcmOFFSETOF(Type, Member)) \
+)
+
+/*******************************************************************************
+**
+** gcmSWAB32
+**
+** Return a value with all bytes in the 32 bit argument swapped.
+*/
+#define gcmSWAB32(x) ((gctUINT32)( \
+ (((gctUINT32)(x) & (gctUINT32)0x000000FFUL) << 24) | \
+ (((gctUINT32)(x) & (gctUINT32)0x0000FF00UL) << 8) | \
+ (((gctUINT32)(x) & (gctUINT32)0x00FF0000UL) >> 8) | \
+ (((gctUINT32)(x) & (gctUINT32)0xFF000000UL) >> 24)))
+
+/*******************************************************************************
+***** Database ****************************************************************/
+
+typedef struct _gcsDATABASE_COUNTERS
+{
+ /* Number of currently allocated bytes. */
+ gctUINT64 bytes;
+
+ /* Maximum number of bytes allocated (memory footprint). */
+ gctUINT64 maxBytes;
+
+ /* Total number of bytes allocated. */
+ gctUINT64 totalBytes;
+
+ /* The numbers of times video memory was allocated. */
+ gctUINT32 allocCount;
+
+ /* The numbers of times video memory was freed. */
+ gctUINT32 freeCount;
+}
+gcsDATABASE_COUNTERS;
+
+typedef struct _gcuDATABASE_INFO
+{
+ /* Counters. */
+ gcsDATABASE_COUNTERS counters;
+
+ /* Time value. */
+ gctUINT64 time;
+}
+gcuDATABASE_INFO;
+
+/*******************************************************************************
+***** Frame database **********************************************************/
+
+/* gcsHAL_FRAME_INFO */
+typedef struct _gcsHAL_FRAME_INFO
+{
+ /* Current timer tick. */
+ OUT gctUINT64 ticks;
+
+ /* Bandwidth counters. */
+ OUT gctUINT readBytes8[8];
+ OUT gctUINT writeBytes8[8];
+
+ /* Counters. */
+ OUT gctUINT cycles[8];
+ OUT gctUINT idleCycles[8];
+ OUT gctUINT mcCycles[8];
+ OUT gctUINT readRequests[8];
+ OUT gctUINT writeRequests[8];
+
+ /* 3D counters. */
+ OUT gctUINT vertexCount;
+ OUT gctUINT primitiveCount;
+ OUT gctUINT rejectedPrimitives;
+ OUT gctUINT culledPrimitives;
+ OUT gctUINT clippedPrimitives;
+ OUT gctUINT outPrimitives;
+ OUT gctUINT inPrimitives;
+ OUT gctUINT culledQuadCount;
+ OUT gctUINT totalQuadCount;
+ OUT gctUINT quadCount;
+ OUT gctUINT totalPixelCount;
+
+ /* PE counters. */
+ OUT gctUINT colorKilled[8];
+ OUT gctUINT colorDrawn[8];
+ OUT gctUINT depthKilled[8];
+ OUT gctUINT depthDrawn[8];
+
+ /* Shader counters. */
+ OUT gctUINT shaderCycles;
+ OUT gctUINT vsInstructionCount;
+ OUT gctUINT vsTextureCount;
+ OUT gctUINT psInstructionCount;
+ OUT gctUINT psTextureCount;
+
+ /* Texture counters. */
+ OUT gctUINT bilinearRequests;
+ OUT gctUINT trilinearRequests;
+ OUT gctUINT txBytes8;
+ OUT gctUINT txHitCount;
+ OUT gctUINT txMissCount;
+}
+gcsHAL_FRAME_INFO;
+
+typedef struct _gckLINKDATA * gckLINKDATA;
+struct _gckLINKDATA
+{
+ gctUINT32 start;
+ gctUINT32 end;
+ gctUINT32 pid;
+ gctUINT32 linkLow;
+ gctUINT32 linkHigh;
+};
+
+typedef struct _gckADDRESSDATA * gckADDRESSDATA;
+struct _gckADDRESSDATA
+{
+ gctUINT32 start;
+ gctUINT32 end;
+};
+
+typedef union _gcuQUEUEDATA
+{
+ struct _gckLINKDATA linkData;
+
+ struct _gckADDRESSDATA addressData;
+}
+gcuQUEUEDATA;
+
+typedef struct _gckQUEUE * gckQUEUE;
+struct _gckQUEUE
+{
+ gcuQUEUEDATA * datas;
+ gctUINT32 rear;
+ gctUINT32 front;
+ gctUINT32 count;
+ gctUINT32 size;
+};
+
+typedef enum _gceTRACEMODE
+{
+ gcvTRACEMODE_NONE = 0,
+ gcvTRACEMODE_FULL = 1,
+ gcvTRACEMODE_LOGGER = 2,
+ gcvTRACEMODE_PRE = 3,
+ gcvTRACEMODE_POST = 4,
+} gceTRACEMODE;
+
+typedef struct _gcsLISTHEAD * gcsLISTHEAD_PTR;
+typedef struct _gcsLISTHEAD
+{
+ gcsLISTHEAD_PTR prev;
+ gcsLISTHEAD_PTR next;
+}
+gcsLISTHEAD;
+
+/*
+ gcvFEATURE_DATABASE_DATE_MASK
+
+ Mask used to control which bits of chip date will be used to
+ query feature database, ignore release date for fpga and emulator.
+*/
+#if (gcdFPGA_BUILD || defined(EMULATOR))
+# define gcvFEATURE_DATABASE_DATE_MASK (0U)
+#else
+# define gcvFEATURE_DATABASE_DATE_MASK (~0U)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_types_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
new file mode 100644
index 000000000000..e88b675c96f4
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_version_h_
+#define __gc_hal_version_h_
+
+#define gcvVERSION_MAJOR 6
+
+#define gcvVERSION_MINOR 2
+
+#define gcvVERSION_PATCH 2
+
+#define gcvVERSION_BUILD 93313
+
+#define gcvVERSION_STRING "6.2.2.93313"
+
+#endif /* __gc_hal_version_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
new file mode 100644
index 000000000000..1953eae2c5fa
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
@@ -0,0 +1,922 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_vg_h_
+#define __gc_hal_vg_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "gc_hal_rename.h"
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+
+#if gcdENABLE_VG
+
+/* Thread routine type. */
+#if defined(LINUX)
+ typedef gctINT gctTHREADFUNCRESULT;
+ typedef gctPOINTER gctTHREADFUNCPARAMETER;
+# define gctTHREADFUNCTYPE
+#elif defined(WIN32)
+ typedef gctUINT gctTHREADFUNCRESULT;
+ typedef gctPOINTER gctTHREADFUNCPARAMETER;
+# define gctTHREADFUNCTYPE __stdcall
+#elif defined(__QNXNTO__)
+ typedef void * gctTHREADFUNCRESULT;
+ typedef gctPOINTER gctTHREADFUNCPARAMETER;
+# define gctTHREADFUNCTYPE
+#endif
+
+typedef gctTHREADFUNCRESULT (gctTHREADFUNCTYPE * gctTHREADFUNC) (
+ gctTHREADFUNCPARAMETER ThreadParameter
+ );
+
+
+#if defined(gcvDEBUG)
+# undef gcvDEBUG
+#endif
+
+#define gcdFORCE_DEBUG 0
+#define gcdFORCE_MESSAGES 0
+
+
+#if DBG || defined(DEBUG) || defined(_DEBUG) || gcdFORCE_DEBUG
+# define gcvDEBUG 1
+#else
+# define gcvDEBUG 0
+#endif
+
+#define _gcmERROR_RETURN(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##PRINT_VERSION(); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
+ status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
+ return status; \
+ } \
+ do { } while (gcvFALSE)
+
+#define gcmERROR_RETURN(func) _gcmERROR_RETURN(gcm, func)
+
+#define gcmLOG_LOCATION()
+
+#define gcmkIS_ERROR(status) (status < 0)
+
+#define gcmALIGNDOWN(n, align) \
+( \
+ (n) & ~((align) - 1) \
+)
+
+#define gcmIS_VALID_INDEX(Index, Array) \
+ (((gctUINT) (Index)) < gcmCOUNTOF(Array))
+
+
+#define gcmIS_NAN(x) \
+( \
+ ((* (gctUINT32_PTR) &(x)) & 0x7FFFFFFF) == 0x7FFFFFFF \
+)
+
+#define gcmLERP(v1, v2, w) \
+ ((v1) * (w) + (v2) * (1.0f - (w)))
+
+#define gcmINTERSECT(Start1, Start2, Length) \
+ (gcmABS((Start1) - (Start2)) < (Length))
+
+/*******************************************************************************
+**
+** gcmERR_GOTO
+**
+** Prints a message and terminates the current loop on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** Function
+** Function to evaluate.
+*/
+
+#define gcmERR_GOTO(Function) \
+ status = Function; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ gcmTRACE( \
+ gcvLEVEL_ERROR, \
+ "gcmERR_GOTO: status=%d @ line=%d in function %s.\n", \
+ status, __LINE__, __FUNCTION__ \
+ ); \
+ goto ErrorHandler; \
+ }
+
+#if gcvDEBUG || gcdFORCE_MESSAGES
+# define gcmVERIFY_BOOLEAN(Expression) \
+ gcmASSERT( \
+ ( (Expression) == gcvFALSE ) || \
+ ( (Expression) == gcvTRUE ) \
+ )
+#else
+# define gcmVERIFY_BOOLEAN(Expression)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFYFIELDFIT
+**
+** Verify whether the value fits in the field.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmVERIFYFIELDFIT(reg, field, value) \
+ gcmASSERT( \
+ (value) <= gcmFIELDMAX(reg, field) \
+ )
+/*******************************************************************************
+**
+** gcmFIELDMAX
+**
+** Get field maximum value.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmFIELDMAX(reg, field) \
+( \
+ (gctUINT32) \
+ ( \
+ (__gcmGETSIZE(reg##_##field) == 32) \
+ ? ~0U \
+ : (~(~0U << __gcmGETSIZE(reg##_##field))) \
+ ) \
+)
+
+
+/* ANSI C does not have the 'f' functions, define replacements here. */
+#define gcmSINF(x) ((gctFLOAT) sin(x))
+#define gcmCOSF(x) ((gctFLOAT) cos(x))
+#define gcmASINF(x) ((gctFLOAT) asin(x))
+#define gcmACOSF(x) ((gctFLOAT) acos(x))
+#define gcmSQRTF(x) ((gctFLOAT) sqrt(x))
+#define gcmFABSF(x) ((gctFLOAT) fabs(x))
+#define gcmFMODF(x, y) ((gctFLOAT) fmod((x), (y)))
+#define gcmCEILF(x) ((gctFLOAT) ceil(x))
+#define gcmFLOORF(x) ((gctFLOAT) floor(x))
+
+
+
+/* Fixed point constants. */
+#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
+#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
+#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
+#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
+#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
+
+/* Integer constants. */
+#define gcvMAX_POS_INT ((gctINT) 0x7FFFFFFF)
+#define gcvMAX_NEG_INT ((gctINT) 0x80000000)
+
+/* Float constants. */
+#define gcvMAX_POS_FLOAT ((gctFLOAT) 3.4028235e+038)
+#define gcvMAX_NEG_FLOAT ((gctFLOAT) -3.4028235e+038)
+
+/******************************************************************************\
+***************************** Miscellaneous Macro ******************************
+\******************************************************************************/
+
+#define gcmKB2BYTES(Kilobyte) \
+( \
+ (Kilobyte) << 10 \
+)
+
+#define gcmMB2BYTES(Megabyte) \
+( \
+ (Megabyte) << 20 \
+)
+
+#define gcmMAT(Matrix, Row, Column) \
+( \
+ (Matrix) [(Row) * 3 + (Column)] \
+)
+
+#define gcmMAKE2CHAR(Char1, Char2) \
+( \
+ ((gctUINT16) (gctUINT8) (Char1) << 0) | \
+ ((gctUINT16) (gctUINT8) (Char2) << 8) \
+)
+
+#define gcmMAKE4CHAR(Char1, Char2, Char3, Char4) \
+( \
+ ((gctUINT32)(gctUINT8) (Char1) << 0) | \
+ ((gctUINT32)(gctUINT8) (Char2) << 8) | \
+ ((gctUINT32)(gctUINT8) (Char3) << 16) | \
+ ((gctUINT32)(gctUINT8) (Char4) << 24) \
+)
+
+/* some platforms need to fix the physical address for HW to access*/
+#define gcmFIXADDRESS(address) \
+(\
+ (address)\
+)
+
+#define gcmkFIXADDRESS(address) \
+(\
+ (address)\
+)
+
+/******************************************************************************\
+****************************** Kernel Debug Macro ******************************
+\******************************************************************************/
+
+/* Set signal to signaled state for specified process. */
+gceSTATUS
+gckOS_SetSignal(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctSIGNAL Signal
+ );
+
+/* Return the kernel logical pointer for the given physical one. */
+gceSTATUS
+gckOS_GetKernelLogical(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Return the kernel logical pointer for the given physical one. */
+gceSTATUS
+gckOS_GetKernelLogicalEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------- Semaphore Object -----------------------------*/
+
+/* Increment the value of a semaphore. */
+gceSTATUS
+gckOS_IncrementSemaphore(
+ IN gckOS Os,
+ IN gctSEMAPHORE Semaphore
+ );
+
+/* Decrement the value of a semaphore (waiting might occur). */
+gceSTATUS
+gckOS_DecrementSemaphore(
+ IN gckOS Os,
+ IN gctSEMAPHORE Semaphore
+ );
+
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------- Thread Object ------------------------------*/
+
+/* Start a thread. */
+gceSTATUS
+gckOS_StartThread(
+ IN gckOS Os,
+ IN gctTHREADFUNC ThreadFunction,
+ IN gctPOINTER ThreadParameter,
+ OUT gctTHREAD * Thread
+ );
+
+/* Stop a thread. */
+gceSTATUS
+gckOS_StopThread(
+ IN gckOS Os,
+ IN gctTHREAD Thread
+ );
+
+/* Verify whether the thread is still running. */
+gceSTATUS
+gckOS_VerifyThread(
+ IN gckOS Os,
+ IN gctTHREAD Thread
+ );
+
+
+/* Construct a new gckVGKERNEL object. */
+gceSTATUS
+gckVGKERNEL_Construct(
+ IN gckOS Os,
+ IN gctPOINTER Context,
+ IN gckKERNEL inKernel,
+ OUT gckVGKERNEL * Kernel
+ );
+
+/* Destroy an gckVGKERNEL object. */
+gceSTATUS
+gckVGKERNEL_Destroy(
+ IN gckVGKERNEL Kernel
+ );
+
+/* Unmap memory. */
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Dispatch a user-level command. */
+gceSTATUS
+gckVGKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Query command buffer requirements. */
+gceSTATUS
+gckKERNEL_QueryCommandBuffer(
+ IN gckKERNEL Kernel,
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ );
+
+/******************************************************************************\
+******************************* gckVGHARDWARE Object ******************************
+\******************************************************************************/
+
+/* Construct a new gckVGHARDWARE object. */
+gceSTATUS
+gckVGHARDWARE_Construct(
+ IN gckOS Os,
+ OUT gckVGHARDWARE * Hardware
+ );
+
+/* Destroy an gckVGHARDWARE object. */
+gceSTATUS
+gckVGHARDWARE_Destroy(
+ IN gckVGHARDWARE Hardware
+ );
+
+/* Query system memory requirements. */
+gceSTATUS
+gckVGHARDWARE_QuerySystemMemory(
+ IN gckVGHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ );
+
+/* Build virtual address. */
+gceSTATUS
+gckVGHARDWARE_BuildVirtualAddress(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ );
+
+/* Kickstart the command processor. */
+gceSTATUS
+gckVGHARDWARE_Execute(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Address,
+ IN gctUINT32 Count
+ );
+
+/* Query the available memory. */
+gceSTATUS
+gckVGHARDWARE_QueryMemory(
+ IN gckVGHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gckVGHARDWARE_QueryChipIdentity(
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPMODEL* ChipModel,
+ OUT gctUINT32* ChipRevision,
+ OUT gctUINT32* ProductID,
+ OUT gctUINT32* EcoID,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures,
+ OUT gctUINT32* ChipMinorFeatures1
+ );
+
+/* Convert an API format. */
+gceSTATUS
+gckVGHARDWARE_ConvertFormat(
+ IN gckVGHARDWARE Hardware,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT32 * BitsPerPixel,
+ OUT gctUINT32 * BytesPerTile
+ );
+
+/* Split a harwdare specific address into API stuff. */
+gceSTATUS
+gckVGHARDWARE_SplitMemory(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ );
+
+/* Align size to tile boundary. */
+gceSTATUS
+gckVGHARDWARE_AlignToTile(
+ IN gckVGHARDWARE Hardware,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Width,
+ IN OUT gctUINT32_PTR Height
+ );
+
+/* Convert logical address to hardware specific address. */
+gceSTATUS
+gckVGHARDWARE_ConvertLogical(
+ IN gckVGHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctBOOL InUserSpace,
+ OUT gctUINT32 * Address
+ );
+
+/* Program MMU. */
+gceSTATUS
+gckVGHARDWARE_SetMMU(
+ IN gckVGHARDWARE Hardware,
+ IN gctPOINTER Logical
+ );
+
+/* Flush the MMU. */
+gceSTATUS
+gckVGHARDWARE_FlushMMU(
+ IN gckVGHARDWARE Hardware
+ );
+
+/* Get idle register. */
+gceSTATUS
+gckVGHARDWARE_GetIdle(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32 * Data
+ );
+
+/* Flush the caches. */
+gceSTATUS
+gckVGHARDWARE_Flush(
+ IN gckVGHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Enable/disable fast clear. */
+gceSTATUS
+gckVGHARDWARE_SetFastClear(
+ IN gckVGHARDWARE Hardware,
+ IN gctINT Enable
+ );
+
+gceSTATUS
+gckVGHARDWARE_ReadInterrupt(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32_PTR IDs
+ );
+
+/* Power management. */
+gceSTATUS
+gckVGHARDWARE_SetPowerManagementState(
+ IN gckVGHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gckVGHARDWARE_QueryPowerManagementState(
+ IN gckVGHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ );
+
+gceSTATUS
+gckVGHARDWARE_SetPowerManagement(
+ IN gckVGHARDWARE Hardware,
+ IN gctBOOL PowerManagement
+ );
+
+gceSTATUS
+gckVGHARDWARE_SetPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Timeout
+ );
+
+gceSTATUS
+gckVGHARDWARE_QueryPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ OUT gctUINT32* Timeout
+ );
+
+gceSTATUS
+gckVGHARDWARE_QueryIdle(
+ IN gckVGHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ );
+/******************************************************************************\
+*************************** Command Buffer Structures **************************
+\******************************************************************************/
+
+/* Vacant command buffer marker. */
+#define gcvVACANT_BUFFER ((gcsCOMPLETION_SIGNAL_PTR) ((gctSIZE_T)1))
+
+/* Command buffer header. */
+typedef struct _gcsCMDBUFFER * gcsCMDBUFFER_PTR;
+typedef struct _gcsCMDBUFFER
+{
+ /* Pointer to the completion signal. */
+ gcsCOMPLETION_SIGNAL_PTR completion;
+
+ /* The user sets this to the node of the container buffer whitin which
+ this particular command buffer resides. The kernel sets this to the
+ node of the internally allocated buffer. */
+ gcuVIDMEM_NODE_PTR node;
+
+ /* Command buffer hardware address. */
+ gctUINT32 address;
+
+ /* The offset of the buffer from the beginning of the header. */
+ gctUINT32 bufferOffset;
+
+ /* Size of the area allocated for the data portion of this particular
+ command buffer (headers and tail reserves are excluded). */
+ gctUINT32 size;
+
+ /* Offset into the buffer [0..size]; reflects exactly how much data has
+ been put into the command buffer. */
+ gctUINT offset;
+
+ /* The number of command units in the buffer for the hardware to
+ execute. */
+ gctUINT32 dataCount;
+
+ /* MANAGED BY : user HAL (gcoBUFFER object).
+ USED BY : user HAL (gcoBUFFER object).
+ Points to the immediate next allocated command buffer. */
+ gcsCMDBUFFER_PTR nextAllocated;
+
+ /* MANAGED BY : user layers (HAL and drivers).
+ USED BY : kernel HAL (gcoBUFFER object).
+ Points to the next subbuffer if any. A family of subbuffers are chained
+ together and are meant to be executed inseparably as a unit. Meaning
+ that context switching cannot occur while a chain of subbuffers is being
+ executed. */
+ gcsCMDBUFFER_PTR nextSubBuffer;
+}
+gcsCMDBUFFER;
+
+/* Command queue element. */
+typedef struct _gcsVGCMDQUEUE
+{
+ /* Pointer to the command buffer header. */
+ gcsCMDBUFFER_PTR commandBuffer;
+
+ /* Dynamic vs. static command buffer state. */
+ gctBOOL dynamic;
+}
+gcsVGCMDQUEUE;
+
+/* Context map entry. */
+typedef struct _gcsVGCONTEXT_MAP
+{
+ /* State index. */
+ gctUINT32 index;
+
+ /* New state value. */
+ gctUINT32 data;
+
+ /* Points to the next entry in the mod list. */
+ gcsVGCONTEXT_MAP_PTR next;
+}
+gcsVGCONTEXT_MAP;
+
+/* gcsVGCONTEXT structure that holds the current context. */
+typedef struct _gcsVGCONTEXT
+{
+ /* Context ID. */
+ gctUINT64 id;
+
+ /* State caching ebable flag. */
+ gctBOOL stateCachingEnabled;
+
+ /* Current pipe. */
+ gctUINT32 currentPipe;
+
+ /* State map/mod buffer. */
+ gctUINT32 mapFirst;
+ gctUINT32 mapLast;
+ gcsVGCONTEXT_MAP_PTR mapContainer;
+ gcsVGCONTEXT_MAP_PTR mapPrev;
+ gcsVGCONTEXT_MAP_PTR mapCurr;
+ gcsVGCONTEXT_MAP_PTR firstPrevMap;
+ gcsVGCONTEXT_MAP_PTR firstCurrMap;
+
+ /* Main context buffer. */
+ gcsCMDBUFFER_PTR header;
+ gctUINT32_PTR buffer;
+
+ /* Completion signal. */
+ gctHANDLE process;
+ gctSIGNAL signal;
+
+#if defined(__QNXNTO__)
+ gctSIGNAL userSignal;
+ gctINT32 coid;
+ gctINT32 rcvid;
+#endif
+}
+gcsVGCONTEXT;
+
+/* User space task header. */
+typedef struct _gcsTASK * gcsTASK_PTR;
+typedef struct _gcsTASK
+{
+ /* Pointer to the next task for the same interrupt in user space. */
+ gcsTASK_PTR next;
+
+ /* Size of the task data that immediately follows the structure. */
+ gctUINT size;
+
+ /* Task data starts here. */
+ /* ... */
+}
+gcsTASK;
+
+/* User space task master table entry. */
+typedef struct _gcsTASK_MASTER_ENTRY * gcsTASK_MASTER_ENTRY_PTR;
+typedef struct _gcsTASK_MASTER_ENTRY
+{
+ /* Pointers to the head and to the tail of the task chain. */
+ gcsTASK_PTR head;
+ gcsTASK_PTR tail;
+}
+gcsTASK_MASTER_ENTRY;
+
+/* User space task master table entry. */
+typedef struct _gcsTASK_MASTER_TABLE
+{
+ /* Table with one entry per block. */
+ gcsTASK_MASTER_ENTRY table[gcvBLOCK_COUNT];
+
+ /* The total number of tasks sckeduled. */
+ gctUINT count;
+
+ /* The total size of event data in bytes. */
+ gctUINT size;
+
+#if defined(__QNXNTO__)
+ gctINT32 coid;
+ gctINT32 rcvid;
+#endif
+}
+gcsTASK_MASTER_TABLE;
+
+/******************************************************************************\
+***************************** gckVGINTERRUPT Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVGINTERRUPT * gckVGINTERRUPT;
+
+typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
+ IN gckVGKERNEL Kernel
+ );
+
+gceSTATUS
+gckVGINTERRUPT_Construct(
+ IN gckVGKERNEL Kernel,
+ OUT gckVGINTERRUPT * Interrupt
+ );
+
+gceSTATUS
+gckVGINTERRUPT_Destroy(
+ IN gckVGINTERRUPT Interrupt
+ );
+
+gceSTATUS
+gckVGINTERRUPT_Enable(
+ IN gckVGINTERRUPT Interrupt,
+ IN OUT gctINT32_PTR Id,
+ IN gctINTERRUPT_HANDLER Handler
+ );
+
+gceSTATUS
+gckVGINTERRUPT_Disable(
+ IN gckVGINTERRUPT Interrupt,
+ IN gctINT32 Id
+ );
+
+#ifndef __QNXNTO__
+
+gceSTATUS
+gckVGINTERRUPT_Enque(
+ IN gckVGINTERRUPT Interrupt
+ );
+
+#else
+
+gceSTATUS
+gckVGINTERRUPT_Enque(
+ IN gckVGINTERRUPT Interrupt,
+ OUT gckOS *Os,
+ OUT gctSEMAPHORE *Semaphore
+ );
+
+#endif
+
+gceSTATUS
+gckVGINTERRUPT_DumpState(
+ IN gckVGINTERRUPT Interrupt
+ );
+
+
+/******************************************************************************\
+******************************* gckVGCOMMAND Object *******************************
+\******************************************************************************/
+
+typedef struct _gckVGCOMMAND * gckVGCOMMAND;
+
+/* Construct a new gckVGCOMMAND object. */
+gceSTATUS
+gckVGCOMMAND_Construct(
+ IN gckVGKERNEL Kernel,
+ IN gctUINT TaskGranularity,
+ IN gctUINT QueueSize,
+ OUT gckVGCOMMAND * Command
+ );
+
+/* Destroy an gckVGCOMMAND object. */
+gceSTATUS
+gckVGCOMMAND_Destroy(
+ IN gckVGCOMMAND Command
+ );
+
+/* Query command buffer attributes. */
+gceSTATUS
+gckVGCOMMAND_QueryCommandBuffer(
+ IN gckVGCOMMAND Command,
+ OUT gcsCOMMAND_BUFFER_INFO_PTR Information
+ );
+
+/* Allocate a command queue. */
+gceSTATUS
+gckVGCOMMAND_Allocate(
+ IN gckVGCOMMAND Command,
+ IN gctSIZE_T Size,
+ OUT gcsCMDBUFFER_PTR * CommandBuffer,
+ OUT gctPOINTER * Data
+ );
+
+/* Release memory held by the command queue. */
+gceSTATUS
+gckVGCOMMAND_Free(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ );
+
+/* Schedule the command queue for execution. */
+gceSTATUS
+gckVGCOMMAND_Execute(
+ IN gckVGCOMMAND Command,
+ IN gcsCMDBUFFER_PTR CommandBuffer
+ );
+
+/* Commit a buffer to the command queue. */
+gceSTATUS
+gckVGCOMMAND_Commit(
+ IN gckVGCOMMAND Command,
+ IN gcsVGCONTEXT_PTR Context,
+ IN gcsVGCMDQUEUE_PTR Queue,
+ IN gctUINT EntryCount,
+ IN gcsTASK_MASTER_TABLE_PTR TaskTable
+ );
+
+/******************************************************************************\
+********************************* gckVGMMU Object ********************************
+\******************************************************************************/
+
+typedef struct _gckVGMMU * gckVGMMU;
+
+/* Construct a new gckVGMMU object. */
+gceSTATUS
+gckVGMMU_Construct(
+ IN gckVGKERNEL Kernel,
+ IN gctUINT32 MmuSize,
+ OUT gckVGMMU * Mmu
+ );
+
+/* Destroy an gckVGMMU object. */
+gceSTATUS
+gckVGMMU_Destroy(
+ IN gckVGMMU Mmu
+ );
+
+/* Allocate pages inside the MMU. */
+gceSTATUS
+gckVGMMU_AllocatePages(
+ IN gckVGMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ );
+
+/* Remove a page table from the MMU. */
+gceSTATUS
+gckVGMMU_FreePages(
+ IN gckVGMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ );
+
+/* Set the MMU page with info. */
+gceSTATUS
+gckVGMMU_SetPage(
+ IN gckVGMMU Mmu,
+ IN gctUINT32 PageAddress,
+ IN gctUINT32 *PageEntry
+ );
+
+/* Flush MMU */
+gceSTATUS
+gckVGMMU_Flush(
+ IN gckVGMMU Mmu
+ );
+
+#endif /* gcdENABLE_VG */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __gc_hal_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h
new file mode 100644
index 000000000000..efb3d67b4d4e
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_allocator_array_h_
+#define __gc_hal_kernel_allocator_array_h_
+
+extern gceSTATUS
+_DefaultAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+
+extern gceSTATUS
+_UserMemoryAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+extern gceSTATUS
+_DmabufAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+#endif
+
+#ifndef NO_DMA_COHERENT
+extern gceSTATUS
+_DmaAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+#endif
+
+/* Default allocator entry. */
+gcsALLOCATOR_DESC allocatorArray[] =
+{
+ /* Default allocator. */
+ gcmkDEFINE_ALLOCATOR_DESC("default", _DefaultAlloctorInit),
+
+ /* User memory importer. */
+ gcmkDEFINE_ALLOCATOR_DESC("user", _UserMemoryAlloctorInit),
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+ /* Dmabuf allocator. */
+ gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
+#endif
+
+#ifndef NO_DMA_COHERENT
+ gcmkDEFINE_ALLOCATOR_DESC("dma", _DmaAlloctorInit),
+#endif
+};
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dma.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dma.c
new file mode 100644
index 000000000000..034df66d5196
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dma.c
@@ -0,0 +1,496 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_allocator.h"
+
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <asm/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+typedef struct _gcsDMA_PRIV * gcsDMA_PRIV_PTR;
+typedef struct _gcsDMA_PRIV {
+ gctUINT32 size;
+}
+gcsDMA_PRIV;
+
+struct mdl_dma_priv {
+ gctPOINTER kvaddr;
+ dma_addr_t dmaHandle;
+};
+
+/*
+* Debugfs support.
+*/
+int gc_dma_usage_show(struct seq_file* m, void* data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckALLOCATOR Allocator = node->device;
+ gcsDMA_PRIV_PTR priv = Allocator->privateData;
+
+ seq_printf(m, "dma: %u bytes\n", priv->size);
+
+ return 0;
+}
+
+static gcsINFO InfoList[] =
+{
+ {"dmausage", gc_dma_usage_show},
+};
+
+static void
+_DebugfsInit(
+ IN gckALLOCATOR Allocator,
+ IN gckDEBUGFS_DIR Root
+ )
+{
+ gcmkVERIFY_OK(
+ gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "dma"));
+
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
+ &Allocator->debugfsDir,
+ InfoList,
+ gcmCOUNTOF(InfoList),
+ Allocator
+ ));
+}
+
+static void
+_DebugfsCleanup(
+ IN gckALLOCATOR Allocator
+ )
+{
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
+ &Allocator->debugfsDir,
+ InfoList,
+ gcmCOUNTOF(InfoList)
+ ));
+
+ gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
+}
+
+#ifdef CONFIG_ARM64
+static struct device *
+_GetDevice(
+ IN gckOS Os
+ )
+{
+ gcsPLATFORM *platform;
+
+ platform = Os->device->platform;
+
+ if (!platform)
+ {
+ return gcvNULL;
+ }
+
+ return &platform->device->dev;
+}
+#endif
+
+static gceSTATUS
+_DmaAlloc(
+ IN gckALLOCATOR Allocator,
+ INOUT PLINUX_MDL Mdl,
+ IN gctSIZE_T NumPages,
+ IN gctUINT32 Flags
+ )
+{
+ gceSTATUS status;
+ gcsDMA_PRIV_PTR allocatorPriv = (gcsDMA_PRIV_PTR)Allocator->privateData;
+
+ struct mdl_dma_priv *mdlPriv=gcvNULL;
+ gckOS os = Allocator->os;
+
+#if defined CONFIG_ARM64
+ struct device *dev = _GetDevice(os);
+#endif
+
+ gcmkHEADER_ARG("Mdl=%p NumPages=%d", Mdl, NumPages);
+
+#if defined CONFIG_ARM64
+ gcmkVERIFY_ARGUMENT(dev);
+#endif
+
+ gcmkONERROR(gckOS_Allocate(os, sizeof(struct mdl_dma_priv), (gctPOINTER *)&mdlPriv));
+
+ mdlPriv->kvaddr
+#if defined CONFIG_ARM64
+ = dma_alloc_coherent(dev, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, GFP_KERNEL | gcdNOWARN);
+#elif defined CONFIG_MIPS
+ = dma_alloc_coherent(gcvNULL, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, GFP_KERNEL | gcdNOWARN);
+#else
+ = dma_alloc_writecombine(gcvNULL, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, GFP_KERNEL | gcdNOWARN);
+#endif
+
+#ifdef CONFLICT_BETWEEN_BASE_AND_PHYS
+ if ((os->device->baseAddress & 0x80000000) != (mdlPriv->dmaHandle & 0x80000000))
+ {
+ mdlPriv->dmaHandle = (mdlPriv->dmaHandle & ~0x80000000)
+ | (os->device->baseAddress & 0x80000000);
+ }
+#endif
+
+ if (mdlPriv->kvaddr == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ Mdl->priv = mdlPriv;
+
+ Mdl->dmaHandle = mdlPriv->dmaHandle;
+
+ /* Statistic. */
+ allocatorPriv->size += NumPages * PAGE_SIZE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if(mdlPriv)
+ {
+ gckOS_Free(os, mdlPriv);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+static void
+_DmaFree(
+ IN gckALLOCATOR Allocator,
+ IN OUT PLINUX_MDL Mdl
+ )
+{
+ gckOS os = Allocator->os;
+ struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
+ gcsDMA_PRIV_PTR allocatorPriv = (gcsDMA_PRIV_PTR)Allocator->privateData;
+#if defined CONFIG_ARM64
+ dma_free_coherent(_GetDevice(os), Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle);
+#elif defined CONFIG_MIPS
+ dma_free_coherent(gcvNULL, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle);
+#else
+ dma_free_writecombine(gcvNULL, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle);
+#endif
+
+ gckOS_Free(os, mdlPriv);
+
+ /* Statistic. */
+ allocatorPriv->size -= Mdl->numPages * PAGE_SIZE;
+}
+
+gctINT
+_DmaMapUser(
+ gckALLOCATOR Allocator,
+ PLINUX_MDL Mdl,
+ gctBOOL Cacheable,
+ OUT gctPOINTER * UserLogical
+ )
+{
+
+ PLINUX_MDL mdl = Mdl;
+ struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
+ struct vm_area_struct * vma;
+ gctPOINTER userLogical = gcvNULL;
+
+ gcmkHEADER_ARG("Allocator=%p Mdl=%p gctBOOL=%d", Allocator, Mdl, Cacheable);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+ userLogical = (gctSTRING)vm_mmap(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+#else
+ down_write(&current->mm->mmap_sem);
+
+ userLogical = (gctSTRING)do_mmap_pgoff(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ up_write(&current->mm->mmap_sem);
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
+ __FUNCTION__, __LINE__,
+ (gctUINT32)(gctUINTPTR_T)userLogical,
+ (gctUINT32)(gctUINTPTR_T)mdl
+ );
+
+ if (IS_ERR(userLogical))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): do_mmap_pgoff error",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ down_write(&current->mm->mmap_sem);
+
+ vma = find_vma(current->mm, (unsigned long)userLogical);
+
+ if (vma == gcvNULL)
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): find_vma error",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* map kernel memory to user space.. */
+#if defined CONFIG_MIPS
+ if (remap_pfn_range(
+ vma,
+ vma->vm_start,
+ mdlPriv->dmaHandle >> PAGE_SHIFT,
+ mdl->numPages * PAGE_SIZE,
+ gcmkNONPAGED_MEMROY_PROT(vma->vm_page_prot)) < 0)
+#else
+ /* map kernel memory to user space.. */
+ if (dma_mmap_writecombine(gcvNULL,
+ vma,
+ mdlPriv->kvaddr,
+ mdlPriv->dmaHandle,
+ mdl->numPages * PAGE_SIZE) < 0)
+#endif
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): dma_mmap_attrs error",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ up_write(&current->mm->mmap_sem);
+
+ *UserLogical = userLogical;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+void
+_DmaUnmapUser(
+ IN gckALLOCATOR Allocator,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ )
+{
+ if (unlikely(current->mm == gcvNULL))
+ {
+ /* Do nothing if process is exiting. */
+ return;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+ if (vm_munmap((unsigned long)Logical, Size) < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): vm_munmap failed",
+ __FUNCTION__, __LINE__
+ );
+ }
+#else
+ down_write(&current->mm->mmap_sem);
+ if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): do_munmap failed",
+ __FUNCTION__, __LINE__
+ );
+ }
+ up_write(&current->mm->mmap_sem);
+#endif
+}
+
+gceSTATUS
+_DmaMapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ OUT gctPOINTER *Logical
+ )
+{
+ struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
+ *Logical =mdlPriv->kvaddr;
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_DmaUnmapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+extern gceSTATUS
+_DefaultCache(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes,
+ IN gceCACHEOPERATION Operation
+ );
+
+gceSTATUS
+_DmaPhysical(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
+
+ *Physical = mdlPriv->dmaHandle + Offset;
+
+ return gcvSTATUS_OK;
+}
+
+extern void
+_DefaultAllocatorDestructor(
+ IN void* PrivateData
+ );
+
+/* Default allocator operations. */
+gcsALLOCATOR_OPERATIONS DmaAllocatorOperations = {
+ .Alloc = _DmaAlloc,
+ .Free = _DmaFree,
+ .MapUser = _DmaMapUser,
+ .UnmapUser = _DmaUnmapUser,
+ .MapKernel = _DmaMapKernel,
+ .UnmapKernel = _DmaUnmapKernel,
+ .Cache = _DefaultCache,
+ .Physical = _DmaPhysical,
+};
+
+/* Default allocator entry. */
+gceSTATUS
+_DmaAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ )
+{
+ gceSTATUS status;
+ gckALLOCATOR allocator = gcvNULL;
+ gcsDMA_PRIV_PTR priv = gcvNULL;
+
+ gcmkONERROR(gckALLOCATOR_Construct(Os, &DmaAllocatorOperations, &allocator));
+
+ priv = kzalloc(gcmSIZEOF(gcsDMA_PRIV), GFP_KERNEL | gcdNOWARN);
+
+ if (!priv)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Register private data. */
+ allocator->privateData = priv;
+ allocator->privateDataDestructor = _DefaultAllocatorDestructor;
+
+ /* Register debugfs callbacks. */
+ allocator->debugfsInit = _DebugfsInit;
+ allocator->debugfsCleanup = _DebugfsCleanup;
+
+ /*
+ * DMA allocator is only used for NonPaged memory
+ * when NO_DMA_COHERENT is not defined.
+ */
+ allocator->capability = 0;
+
+ *Allocator = allocator;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (allocator)
+ {
+ gcmkOS_SAFE_FREE(Os, allocator);
+ }
+ return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
new file mode 100644
index 000000000000..3463eb990441
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
@@ -0,0 +1,502 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_allocator.h"
+
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <asm/atomic.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/dma-buf.h>
+#include <linux/platform_device.h>
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+/* Descriptor of a dma_buf imported. */
+typedef struct _gcsDMABUF
+{
+ struct dma_buf * dmabuf;
+ struct dma_buf_attachment * attachment;
+ struct sg_table * sgtable;
+ unsigned long * pagearray;
+ int fd;
+
+ int npages;
+ int pid;
+ struct list_head list;
+}
+gcsDMABUF;
+
+struct allocator_priv
+{
+ struct mutex lock;
+ struct list_head buf_list;
+};
+
+/*
+* Debugfs support.
+*/
+int dma_buf_info_show(struct seq_file* m, void* data)
+{
+ int ret;
+ gcsDMABUF *buf_desc;
+ struct dma_buf_attachment *attach_obj;
+ int count = 0;
+ size_t size = 0;
+ int npages = 0;
+ const char *exp_name;
+
+ gcsINFO_NODE *node = m->private;
+ gckALLOCATOR allocator = node->device;
+ struct allocator_priv *priv = allocator->privateData;
+
+ ret = mutex_lock_interruptible(&priv->lock);
+
+ if (ret)
+ return ret;
+
+ seq_puts(m, "Attached dma-buf objects:\n");
+ seq_puts(m, " pid fd pages size exporter attached-devices\n");
+
+ list_for_each_entry(buf_desc, &priv->buf_list, list) {
+ struct dma_buf *buf_obj = buf_desc->dmabuf;
+
+ ret = mutex_lock_interruptible(&buf_obj->lock);
+
+ if (ret) {
+ seq_puts(m,
+ "ERROR locking buffer object: skipping\n");
+ continue;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+ exp_name = buf_obj->exp_name;
+#else
+ exp_name = "unknown";
+#endif
+
+ seq_printf(m, "%6d %6d %8d %8zu %10s",
+ buf_desc->pid,
+ buf_desc->fd,
+ buf_desc->npages,
+ buf_obj->size,
+ exp_name);
+
+ list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
+ seq_printf(m, " %s", dev_name(attach_obj->dev));
+ }
+ seq_puts(m, "\n");
+
+ count++;
+ size += buf_obj->size;
+ npages += buf_desc->npages;
+
+ mutex_unlock(&buf_obj->lock);
+ }
+
+ seq_printf(m, "\nTotal %d objects, %d pages, %zu bytes\n", count, npages, size);
+
+ mutex_unlock(&priv->lock);
+ return 0;
+}
+
+static gcsINFO _InfoList[] =
+{
+ {"bufinfo", dma_buf_info_show},
+};
+
+static void
+_DebugfsInit(
+ IN gckALLOCATOR Allocator,
+ IN gckDEBUGFS_DIR Root
+ )
+{
+ gcmkVERIFY_OK(
+ gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "dma_buf"));
+
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
+ &Allocator->debugfsDir,
+ _InfoList,
+ gcmCOUNTOF(_InfoList),
+ Allocator
+ ));
+}
+
+static void
+_DebugfsCleanup(
+ IN gckALLOCATOR Allocator
+ )
+{
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
+ &Allocator->debugfsDir,
+ _InfoList,
+ gcmCOUNTOF(_InfoList)
+ ));
+
+ gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
+}
+
+static gceSTATUS
+_DmabufAttach(
+ IN gckALLOCATOR Allocator,
+ IN gcsATTACH_DESC_PTR Desc,
+ IN PLINUX_MDL Mdl
+ )
+{
+ gceSTATUS status;
+
+ gckOS os = Allocator->os;
+
+ int fd = (int) Desc->handle;
+
+ struct dma_buf *dmabuf = NULL;
+ struct sg_table *sgt = NULL;
+ struct dma_buf_attachment *attachment = NULL;
+ int npages = 0;
+ unsigned long *pagearray = NULL;
+ int i, j, k = 0;
+ struct scatterlist *s;
+ struct allocator_priv *priv = Allocator->privateData;
+ gcsDMABUF *buf_desc = NULL;
+
+ gcmkHEADER();
+
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Import dma buf handle. */
+ dmabuf = dma_buf_get(fd);
+
+ if (!dmabuf)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ attachment = dma_buf_attach(dmabuf, &os->device->platform->device->dev);
+
+ if (!attachment)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
+
+ if (!sgt)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ /* Prepare page array. */
+ /* Get number of pages. */
+ for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
+ {
+ npages += (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE;
+ }
+
+ /* Allocate page arrary. */
+ gcmkONERROR(gckOS_Allocate(os, npages * gcmSIZEOF(*pagearray), (gctPOINTER *)&pagearray));
+
+ /* Fill page arrary. */
+ for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
+ {
+ for (j = 0; j < (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE; j++)
+ {
+ pagearray[k++] = sg_dma_address(s) + j * PAGE_SIZE;
+ }
+ }
+
+ /* Prepare descriptor. */
+ gcmkONERROR(gckOS_Allocate(os, sizeof(gcsDMABUF), (gctPOINTER *)&buf_desc));
+
+ buf_desc->fd = fd;
+ buf_desc->dmabuf = dmabuf;
+ buf_desc->pagearray = pagearray;
+ buf_desc->attachment = attachment;
+ buf_desc->sgtable = sgt;
+
+ /* Record in buffer list to support debugfs. */
+ buf_desc->npages = npages;
+ buf_desc->pid = _GetProcessID();
+
+ mutex_lock(&priv->lock);
+ list_add(&buf_desc->list, &priv->buf_list);
+ mutex_unlock(&priv->lock);
+
+ /* Record page number. */
+ Mdl->numPages = npages;
+
+ Mdl->priv = buf_desc;
+
+ /* Always treat it as a non-contigous buffer. */
+ Mdl->contiguous = gcvFALSE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (pagearray)
+ {
+ gcmkOS_SAFE_FREE(os, pagearray);
+ }
+ gcmkFOOTER();
+ return status;
+}
+
+
+static void
+_DmabufFree(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl
+ )
+{
+ gcsDMABUF *buf_desc = Mdl->priv;
+ gckOS os = Allocator->os;
+ struct allocator_priv *priv = Allocator->privateData;
+
+ mutex_lock(&priv->lock);
+ list_del(&buf_desc->list);
+ mutex_unlock(&priv->lock);
+
+ dma_buf_unmap_attachment(buf_desc->attachment, buf_desc->sgtable, DMA_BIDIRECTIONAL);
+
+ dma_buf_detach(buf_desc->dmabuf, buf_desc->attachment);
+
+ dma_buf_put(buf_desc->dmabuf);
+
+ gckOS_Free(os, buf_desc->pagearray);
+
+ gckOS_Free(os, buf_desc);
+}
+
+static gctINT
+_DmabufMapUser(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctBOOL Cacheable,
+ OUT gctPOINTER * UserLogical
+ )
+{
+ gcsDMABUF *buf_desc = Mdl->priv;
+ gceSTATUS status;
+ PLINUX_MDL mdl = Mdl;
+ struct file * file = buf_desc->dmabuf->file;
+
+ *UserLogical = (gctSTRING)vm_mmap(file,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ if (IS_ERR(*UserLogical))
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* To make sure the mapping is created. */
+ if (access_ok(VERIFY_READ, *UserLogical, 4))
+ {
+ uint32_t mem;
+ get_user(mem, (uint32_t *) *UserLogical);
+
+ (void) mem;
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+static void
+_DmabufUnmapUser(
+ IN gckALLOCATOR Allocator,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ )
+{
+ if (unlikely(current->mm == gcvNULL))
+ {
+ /* Do nothing if process is exiting. */
+ return;
+ }
+
+ vm_munmap((unsigned long)Logical, Size);
+}
+
+static gceSTATUS
+_DmabufMapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ OUT gctPOINTER *Logical
+ )
+{
+ /* Kernel doesn't acess video memory. */
+ return gcvSTATUS_NOT_SUPPORTED;
+
+}
+
+static gceSTATUS
+_DmabufUnmapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical
+ )
+{
+ /* Kernel doesn't acess video memory. */
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+static gceSTATUS
+_DmabufCache(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes,
+ IN gceCACHEOPERATION Operation
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+
+static gceSTATUS
+_DmabufPhysical(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ gcsDMABUF *buf_desc = Mdl->priv;
+ gctUINT32 offsetInPage = Offset & ~PAGE_MASK;
+ gctUINT32 index = Offset / PAGE_SIZE;
+
+ *Physical = buf_desc->pagearray[index] + offsetInPage;
+
+
+ return gcvSTATUS_OK;
+}
+
+/* Default allocator operations. */
+static gcsALLOCATOR_OPERATIONS DmabufAllocatorOperations =
+{
+ .Attach = _DmabufAttach,
+ .Free = _DmabufFree,
+ .MapUser = _DmabufMapUser,
+ .UnmapUser = _DmabufUnmapUser,
+ .MapKernel = _DmabufMapKernel,
+ .UnmapKernel = _DmabufUnmapKernel,
+ .Cache = _DmabufCache,
+ .Physical = _DmabufPhysical,
+};
+
+extern void
+_DefaultAllocatorDestructor(
+ IN void* PrivateData
+ );
+
+/* Default allocator entry. */
+gceSTATUS
+_DmabufAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ )
+{
+ gceSTATUS status;
+ gckALLOCATOR allocator;
+ struct allocator_priv *priv = NULL;
+
+ priv = kmalloc(sizeof (struct allocator_priv), GFP_KERNEL | gcdNOWARN);
+
+ if (!priv)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ mutex_init(&priv->lock);
+ INIT_LIST_HEAD(&priv->buf_list);
+
+ gcmkONERROR(
+ gckALLOCATOR_Construct(Os, &DmabufAllocatorOperations, &allocator));
+
+ allocator->capability = gcvALLOC_FLAG_DMABUF;
+
+ /* Register private data. */
+ allocator->privateData = priv;
+ allocator->privateDataDestructor = _DefaultAllocatorDestructor;
+
+ /* Register debugfs callbacks. */
+ allocator->debugfsInit = _DebugfsInit;
+ allocator->debugfsCleanup = _DebugfsCleanup;
+
+ *Allocator = allocator;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (priv)
+ {
+ kfree(priv);
+ }
+
+ return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c
new file mode 100644
index 000000000000..966d25545221
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c
@@ -0,0 +1,646 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_allocator.h"
+
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+
+#define _GC_OBJ_ZONE gcvZONE_ALLOCATOR
+
+/* Descriptor of a user memory imported. */
+typedef struct _gcsUserMemory
+{
+ gctPHYS_ADDR_T physical;
+ struct page ** pages;
+ gctUINT32 extraPage;
+ gctPOINTER logical;
+ gctSIZE_T pageCount;
+ gctUINT32 offset;
+ gctBOOL contiguous;
+ gctBOOL userPages;
+ gctBOOL *ref;
+}
+gcsUserMemory;
+
+static gceSTATUS
+_Import(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ IN gcsUserMemory * UserMemory
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gctUINTPTR_T start, end, memory;
+ gctINT result = 0;
+
+ struct page **pages = gcvNULL;
+ gctSIZE_T extraPage;
+ gctSIZE_T pageCount, i;
+ gctBOOL *ref = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x Memory=0x%x Physical=0x%x Size=%lu", Os, Memory, Physical, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+
+ memory = (gctUINTPTR_T) Memory;
+
+ /* Get the number of required pages. */
+ end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ start = memory >> PAGE_SHIFT;
+ pageCount = end - start;
+
+ /* Allocate extra page to avoid cache overflow */
+#if gcdENABLE_2D
+ extraPage = 2;
+#else
+ extraPage = (((memory + gcmALIGN(Size + 64, 64) + PAGE_SIZE - 1) >> PAGE_SHIFT) > end) ? 1 : 0;
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, _GC_OBJ_ZONE,
+ "%s(%d): pageCount: %d. extraPage: %d",
+ __FUNCTION__, __LINE__,
+ pageCount, extraPage
+ );
+
+ /* Overflow. */
+ if ((memory + Size) < memory)
+ {
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Allocate the array of page addresses. */
+ pages = (struct page **)kmalloc((pageCount + extraPage) * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
+
+ if (pages == gcvNULL)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+ ref = (gctBOOL *)kzalloc((pageCount + extraPage) * sizeof(gctBOOL), GFP_KERNEL | gcdNOWARN);
+
+ if (ref == gcvNULL)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+ if (Physical != ~0U)
+ {
+ unsigned long pfn = Physical >> PAGE_SHIFT;
+
+ UserMemory->contiguous = gcvTRUE;
+
+ if (pfn_valid(pfn))
+ {
+ for (i = 0; i < pageCount; i++)
+ {
+ pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
+ }
+ }
+ else
+ {
+ /* Free pages array since there is no struct page for this memory. */
+ kfree(pages);
+ pages = gcvNULL;
+ }
+ }
+ else
+ {
+ UserMemory->contiguous = gcvFALSE;
+ UserMemory->userPages = gcvTRUE;
+
+ /* Get the user pages. */
+ down_read(&current->mm->mmap_sem);
+
+ result = get_user_pages(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
+ current,
+ current->mm,
+#endif
+ memory & PAGE_MASK,
+ pageCount,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+ FOLL_WRITE,
+#else
+ 1,
+ 0,
+#endif
+ pages,
+ gcvNULL
+ );
+
+ up_read(&current->mm->mmap_sem);
+
+ if (result <=0 || result < pageCount)
+ {
+ struct vm_area_struct *vma;
+
+ /* Release the pages if any. */
+ if (result > 0)
+ {
+ for (i = 0; i < result; i++)
+ {
+ if (pages[i] == gcvNULL)
+ {
+ break;
+ }
+
+ put_page(pages[i]);
+ pages[i] = gcvNULL;
+ }
+
+ result = 0;
+ }
+
+ vma = find_vma(current->mm, memory);
+
+ if (vma && (vma->vm_flags & VM_PFNMAP))
+ {
+ pte_t * pte;
+ spinlock_t * ptl;
+ gctUINTPTR_T logical = memory;
+
+ for (i = 0; i < pageCount; i++)
+ {
+ pgd_t * pgd = pgd_offset(current->mm, logical);
+ pud_t * pud = pud_offset(pgd, logical);
+
+ if (pud)
+ {
+ pmd_t * pmd = pmd_offset(pud, logical);
+ pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl);
+ if (!pte)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+ else
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ pages[i] = pte_page(*pte);
+ pte_unmap_unlock(pte, ptl);
+
+ /* Advance to next. */
+ logical += PAGE_SIZE;
+ }
+ }
+ else
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Check whether pages are contigous. */
+ for (i = 1; i < pageCount; i++)
+ {
+ if (pages[i] != nth_page(pages[0], i))
+ {
+ /* Non-contiguous. */
+ break;
+ }
+ }
+
+ if (i == pageCount)
+ {
+ UserMemory->contiguous = gcvTRUE;
+ }
+
+ /* Reference pages. */
+ for (i = 0; i < pageCount; i++)
+ {
+ if (pfn_valid(page_to_pfn(pages[i])))
+ {
+ ref[i] = get_page_unless_zero(pages[i]);
+ }
+ }
+ }
+ else
+ {
+ /* Mark feference when pages from get_user_pages. */
+ for (i = 0; i < pageCount; i++)
+ {
+ ref[i] = gcvTRUE;
+ }
+ }
+ }
+
+ if (UserMemory->userPages)
+ {
+ for (i = 0; i < pageCount; i++)
+ {
+ gctUINT32 phys;
+
+ #ifdef CONFIG_ARM
+ gctUINT32 data;
+
+ if (memory)
+ {
+ get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE));
+ }
+ #endif
+
+ if (pages)
+ {
+ phys = page_to_phys(pages[i]);
+ }
+ else
+ {
+ phys = Physical + i * PAGE_SIZE;
+ }
+
+ if (memory)
+ {
+ /* Flush(clean) the data cache. */
+ gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
+ phys,
+ (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
+ PAGE_SIZE));
+ }
+ }
+ }
+
+ if (extraPage)
+ {
+ if (pages)
+ {
+ for (i = 0; i < extraPage; i++)
+ {
+ pages[pageCount++] = Os->paddingPage;
+ }
+ }
+
+ /* Adjust pageCount to include padding page. */
+ UserMemory->extraPage = extraPage;
+ }
+
+ UserMemory->physical = Physical;
+ UserMemory->pages = pages;
+ UserMemory->pageCount = pageCount;
+ UserMemory->logical = Memory;
+ UserMemory->ref = ref;
+
+ UserMemory->offset = (Physical != ~0U)
+ ? (Physical & ~PAGE_MASK)
+ : (memory & ~PAGE_MASK);
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Release page array. */
+ if (result > 0 && pages != gcvNULL)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): error: page table is freed.",
+ __FUNCTION__, __LINE__
+ );
+
+ for (i = 0; i < result; i++)
+ {
+ if (pages[i] == gcvNULL)
+ {
+ break;
+ }
+
+ put_page(pages[i]);
+ }
+ }
+
+ if (pages != gcvNULL)
+ {
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): error: pages is freed.",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Free the page table. */
+ kfree(pages);
+ }
+
+ if (ref != gcvNULL)
+ {
+ /* Free the ref table. */
+ kfree(ref);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_Free(
+ IN gckOS Os,
+ IN gcsUserMemory * UserMemory
+ )
+{
+ gctSIZE_T pageCount, i;
+ struct page **pages;
+ gctBOOL *ref;
+
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ pages = UserMemory->pages;
+
+ /* Invalid page array. */
+ if (pages == gcvNULL)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ pageCount = UserMemory->pageCount;
+
+ if (UserMemory->extraPage)
+ {
+ pageCount -= UserMemory->extraPage;
+ }
+
+ ref = UserMemory->ref;
+
+ if (UserMemory->userPages)
+ {
+ /* Release the page cache. */
+ if (pages)
+ {
+ for (i = 0; i < pageCount; i++)
+ {
+ if (!PageReserved(pages[i]))
+ {
+ SetPageDirty(pages[i]);
+ }
+
+ if (pfn_valid(page_to_pfn(pages[i])) && ref[i])
+ {
+ put_page(pages[i]);
+ }
+ }
+ }
+ }
+
+ kfree(ref);
+ kfree(pages);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_UserMemoryAttach(
+ IN gckALLOCATOR Allocator,
+ IN gcsATTACH_DESC_PTR Desc,
+ IN PLINUX_MDL Mdl
+ )
+{
+ gceSTATUS status;
+ gcsUserMemory * userMemory = gcvNULL;
+
+ gckOS os = Allocator->os;
+
+ gcmkHEADER();
+
+ /* Handle is meangless for this importer. */
+ gcmkVERIFY_ARGUMENT(Desc != gcvNULL);
+
+ gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsUserMemory), (gctPOINTER *)&userMemory));
+
+ gckOS_ZeroMemory(userMemory, gcmSIZEOF(gcsUserMemory));
+
+ gcmkONERROR(_Import(os, Desc->memory, Desc->physical, Desc->size, userMemory));
+
+ Mdl->priv = userMemory;
+ Mdl->numPages = userMemory->pageCount;
+ Mdl->contiguous = userMemory->contiguous;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if(userMemory != gcvNULL)
+ gckOS_Free(os,(gctPOINTER)userMemory);
+ gcmkFOOTER();
+ return status;
+}
+
+static void
+_UserMemoryFree(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl
+ )
+{
+ gckOS os = Allocator->os;
+ gcsUserMemory *userMemory = Mdl->priv;
+
+ gcmkHEADER();
+
+ if (userMemory)
+ {
+ gcmkVERIFY_OK(_Free(os, userMemory));
+
+ gcmkOS_SAFE_FREE(os, userMemory);
+ }
+
+ gcmkFOOTER_NO();
+}
+
+static gctINT
+_UserMemoryMapUser(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctBOOL Cacheable,
+ OUT gctPOINTER * UserLogical
+ )
+{
+ gcsUserMemory *userMemory = Mdl->priv;
+
+ *UserLogical = userMemory->logical;
+
+ return 0;
+}
+
+static void
+_UserMemoryUnmapUser(
+ IN gckALLOCATOR Allocator,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ )
+{
+ return;
+}
+
+static gceSTATUS
+_UserMemoryMapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ OUT gctPOINTER *Logical
+ )
+{
+ /* Kernel doesn't acess video memory. */
+ return gcvSTATUS_NOT_SUPPORTED;
+
+}
+
+static gceSTATUS
+_UserMemoryUnmapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical
+ )
+{
+ /* Kernel doesn't acess video memory. */
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+static gceSTATUS
+_UserMemoryCache(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes,
+ IN gceCACHEOPERATION Operation
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_UserMemoryPhysical(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ gckOS os = Allocator->os;
+ gcsUserMemory *userMemory = Mdl->priv;
+ gctUINT32 offsetInPage = Offset & ~PAGE_MASK;
+ gctUINT32 index = Offset / PAGE_SIZE;
+
+ if (userMemory->pages)
+ {
+ if (index == userMemory->pageCount - 1 && userMemory->extraPage)
+ {
+ *Physical = page_to_phys(os->paddingPage);
+ }
+ else
+ {
+ *Physical = page_to_phys(userMemory->pages[index]);
+ }
+ }
+ else
+ {
+ *Physical = userMemory->physical + index * PAGE_SIZE;
+ }
+
+ *Physical += offsetInPage;
+
+ return gcvSTATUS_OK;
+}
+
+/* User memory allocator (importer) operations. */
+static gcsALLOCATOR_OPERATIONS UserMemoryAllocatorOperations =
+{
+ .Attach = _UserMemoryAttach,
+ .Free = _UserMemoryFree,
+ .MapUser = _UserMemoryMapUser,
+ .UnmapUser = _UserMemoryUnmapUser,
+ .MapKernel = _UserMemoryMapKernel,
+ .UnmapKernel = _UserMemoryUnmapKernel,
+ .Cache = _UserMemoryCache,
+ .Physical = _UserMemoryPhysical,
+};
+
+/* Default allocator entry. */
+gceSTATUS
+_UserMemoryAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ )
+{
+ gceSTATUS status;
+ gckALLOCATOR allocator;
+
+ gcmkONERROR(
+ gckALLOCATOR_Construct(Os, &UserMemoryAllocatorOperations, &allocator));
+
+ allocator->capability = gcvALLOC_FLAG_USERMEMORY;
+
+ *Allocator = allocator;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h
new file mode 100644
index 000000000000..2a1c3c478cdd
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_array.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_allocator_array_h_
+#define __gc_hal_kernel_allocator_array_h_
+
+extern gceSTATUS
+_DefaultAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+
+extern gceSTATUS
+_UserMemoryAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+
+#if LINUX_CMA_FSL
+extern gceSTATUS
+_CMAFSLAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+#endif
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+extern gceSTATUS
+_DmabufAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+#endif
+
+#ifndef NO_DMA_COHERENT
+extern gceSTATUS
+_DmaAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ );
+#endif
+
+gcsALLOCATOR_DESC allocatorArray[] =
+{
+#if LINUX_CMA_FSL
+ gcmkDEFINE_ALLOCATOR_DESC("cmafsl", _CMAFSLAlloctorInit),
+#endif
+ /* Default allocator. */
+ gcmkDEFINE_ALLOCATOR_DESC("default", _DefaultAlloctorInit),
+
+ /* User memory importer. */
+ gcmkDEFINE_ALLOCATOR_DESC("user", _UserMemoryAlloctorInit),
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+ /* Dmabuf allocator. */
+ gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
+#endif
+
+#ifndef NO_DMA_COHERENT
+ gcmkDEFINE_ALLOCATOR_DESC("dma", _DmaAlloctorInit),
+#endif
+};
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c
new file mode 100644
index 000000000000..fb25e2a7d698
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c
@@ -0,0 +1,473 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_allocator.h"
+
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <asm/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+typedef struct _gcsCMA_PRIV * gcsCMA_PRIV_PTR;
+typedef struct _gcsCMA_PRIV {
+ gctUINT32 cmasize;
+ gctBOOL cmaLimitRequest;
+}
+gcsCMA_PRIV;
+
+struct mdl_cma_priv {
+ gctPOINTER kvaddr;
+ dma_addr_t physical;
+};
+
+int gc_cma_usage_show(struct seq_file* m, void* data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckALLOCATOR Allocator = node->device;
+ gcsCMA_PRIV_PTR priv = Allocator->privateData;
+
+ seq_printf(m, "cma: %u bytes\n", priv->cmasize);
+
+ return 0;
+}
+
+static gcsINFO InfoList[] =
+{
+ {"cmausage", gc_cma_usage_show},
+};
+
+static void
+_DefaultAllocatorDebugfsInit(
+ IN gckALLOCATOR Allocator,
+ IN gckDEBUGFS_DIR Root
+ )
+{
+ gcmkVERIFY_OK(
+ gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "cma"));
+
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
+ &Allocator->debugfsDir,
+ InfoList,
+ gcmCOUNTOF(InfoList),
+ Allocator
+ ));
+}
+
+static void
+_DefaultAllocatorDebugfsCleanup(
+ IN gckALLOCATOR Allocator
+ )
+{
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
+ &Allocator->debugfsDir,
+ InfoList,
+ gcmCOUNTOF(InfoList)
+ ));
+
+ gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
+}
+
+static gceSTATUS
+_CMAFSLAlloc(
+ IN gckALLOCATOR Allocator,
+ INOUT PLINUX_MDL Mdl,
+ IN gctSIZE_T NumPages,
+ IN gctUINT32 Flags
+ )
+{
+ gceSTATUS status;
+ gcsCMA_PRIV_PTR priv = (gcsCMA_PRIV_PTR)Allocator->privateData;
+
+ struct mdl_cma_priv *mdl_priv=gcvNULL;
+ gckOS os = Allocator->os;
+
+ gcmkHEADER_ARG("Mdl=%p NumPages=%d", Mdl, NumPages);
+
+ if (os->allocatorLimitMarker)
+ {
+ if (Flags & gcvALLOC_FLAG_CMA_LIMIT)
+ {
+ priv->cmaLimitRequest = gcvTRUE;
+ }
+ else if (priv->cmaLimitRequest == gcvTRUE)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+ }
+
+ gcmkONERROR(gckOS_Allocate(os, sizeof(struct mdl_cma_priv), (gctPOINTER *)&mdl_priv));
+ mdl_priv->kvaddr = gcvNULL;
+
+ mdl_priv->kvaddr = dma_alloc_writecombine(&os->device->platform->device->dev,
+ NumPages * PAGE_SIZE,
+ &mdl_priv->physical,
+ GFP_KERNEL | gcdNOWARN);
+
+ if (mdl_priv->kvaddr == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ Mdl->priv = mdl_priv;
+ Mdl->dmaHandle = mdl_priv->physical;
+ priv->cmasize += NumPages * PAGE_SIZE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if(mdl_priv)
+ gckOS_Free(os, mdl_priv);
+ gcmkFOOTER();
+ return status;
+}
+
+static void
+_CMAFSLFree(
+ IN gckALLOCATOR Allocator,
+ IN OUT PLINUX_MDL Mdl
+ )
+{
+ gckOS os = Allocator->os;
+ struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
+ gcsCMA_PRIV_PTR priv = (gcsCMA_PRIV_PTR)Allocator->privateData;
+ dma_free_writecombine(&os->device->platform->device->dev,
+ Mdl->numPages * PAGE_SIZE,
+ mdl_priv->kvaddr,
+ mdl_priv->physical);
+ gckOS_Free(os, mdl_priv);
+ priv->cmasize -= Mdl->numPages * PAGE_SIZE;
+}
+
+static gctINT
+_CMAFSLMapUser(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctBOOL Cacheable,
+ OUT gctPOINTER * UserLogical
+ )
+{
+
+ PLINUX_MDL mdl = Mdl;
+ struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
+ gckOS os = Allocator->os;
+ struct vm_area_struct * vma;
+ gctPOINTER userLogical = gcvNULL;
+
+ gcmkHEADER_ARG("Allocator=%p Mdl=%p gctBOOL=%d", Allocator, Mdl, Cacheable);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+ userLogical = (gctSTRING)vm_mmap(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_NORESERVE,
+ 0);
+#else
+ down_write(&current->mm->mmap_sem);
+
+ userLogical = (gctSTRING)do_mmap_pgoff(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ up_write(&current->mm->mmap_sem);
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
+ __FUNCTION__, __LINE__,
+ (gctUINT32)(gctUINTPTR_T)userLogical,
+ (gctUINT32)(gctUINTPTR_T)mdl
+ );
+
+ if (IS_ERR(userLogical))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): do_mmap_pgoff error",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ down_write(&current->mm->mmap_sem);
+
+ vma = find_vma(current->mm, (unsigned long)userLogical);
+
+ if (vma == gcvNULL)
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): find_vma error",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Now map all the vmalloc pages to this user address. */
+ if (mdl->contiguous)
+ {
+ /* map kernel memory to user space.. */
+ if (dma_mmap_writecombine(&os->device->platform->device->dev,
+ vma,
+ mdl_priv->kvaddr,
+ mdl_priv->physical,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): dma_mmap_attrs error",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ gckOS_Print("incorrect mdl:conti%d\n",mdl->contiguous);
+ }
+
+ up_write(&current->mm->mmap_sem);
+
+ gcmkVERIFY_OK(gckOS_CacheFlush(
+ os,
+ _GetProcessID(),
+ mdl,
+ gcvINVALID_ADDRESS,
+ (gctPOINTER)userLogical,
+ mdl->numPages * PAGE_SIZE
+ ));
+
+ *UserLogical = userLogical;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+void
+_CMAUnmapUser(
+ IN gckALLOCATOR Allocator,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ )
+{
+ if (unlikely(current->mm == gcvNULL))
+ {
+ /* Do nothing if process is exiting. */
+ return;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+ if (vm_munmap((unsigned long)Logical, Size) < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): vm_munmap failed",
+ __FUNCTION__, __LINE__
+ );
+ }
+#else
+ down_write(&current->mm->mmap_sem);
+ if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): do_munmap failed",
+ __FUNCTION__, __LINE__
+ );
+ }
+ up_write(&current->mm->mmap_sem);
+#endif
+}
+
+gceSTATUS
+_CMAMapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ OUT gctPOINTER *Logical
+ )
+{
+ struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
+ *Logical =mdl_priv->kvaddr;
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_CMAUnmapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+extern gceSTATUS
+_DefaultCache(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes,
+ IN gceCACHEOPERATION Operation
+ );
+
+gceSTATUS
+_CMAPhysical(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
+
+ *Physical = mdl_priv->physical + Offset;
+
+ return gcvSTATUS_OK;
+}
+
+extern void
+_DefaultAllocatorDestructor(
+ IN void* PrivateData
+ );
+
+/* Default allocator operations. */
+gcsALLOCATOR_OPERATIONS CMAFSLAllocatorOperations = {
+ .Alloc = _CMAFSLAlloc,
+ .Free = _CMAFSLFree,
+ .MapUser = _CMAFSLMapUser,
+ .UnmapUser = _CMAUnmapUser,
+ .MapKernel = _CMAMapKernel,
+ .UnmapKernel = _CMAUnmapKernel,
+ .Cache = _DefaultCache,
+ .Physical = _CMAPhysical,
+};
+
+/* Default allocator entry. */
+gceSTATUS
+_CMAFSLAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ )
+{
+ gceSTATUS status;
+ gckALLOCATOR allocator = gcvNULL;
+ gcsCMA_PRIV_PTR priv = gcvNULL;
+
+ gcmkONERROR(
+ gckALLOCATOR_Construct(Os, &CMAFSLAllocatorOperations, &allocator));
+
+ priv = kzalloc(gcmSIZEOF(gcsCMA_PRIV), GFP_KERNEL | gcdNOWARN);
+
+ if (!priv)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Register private data. */
+ allocator->privateData = priv;
+ allocator->privateDataDestructor = _DefaultAllocatorDestructor;
+
+ allocator->debugfsInit = _DefaultAllocatorDebugfsInit;
+ allocator->debugfsCleanup = _DefaultAllocatorDebugfsCleanup;
+
+ allocator->capability = gcvALLOC_FLAG_CONTIGUOUS;
+
+#if defined(CONFIG_ARM64)
+ Os->allocatorLimitMarker = (Os->device->baseAddress + totalram_pages * PAGE_SIZE) > 0x100000000;
+#else
+ Os->allocatorLimitMarker = gcvFALSE;
+#endif
+ priv->cmaLimitRequest = gcvFALSE;
+
+ if (Os->allocatorLimitMarker)
+ {
+ allocator->capability |= gcvALLOC_FLAG_CMA_LIMIT;
+ }
+
+ *Allocator = allocator;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (allocator)
+ {
+ gcmkOS_SAFE_FREE(Os, allocator);
+ }
+ return status;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
new file mode 100644
index 000000000000..1e62d8742079
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
@@ -0,0 +1,1150 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_allocator.h"
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <asm/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+#include <linux/anon_inodes.h>
+#endif
+#include <linux/file.h>
+
+#include "gc_hal_kernel_allocator_array.h"
+#include "gc_hal_kernel_platform.h"
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#define gcdDISCRETE_PAGES 0
+
+typedef struct _gcsDEFAULT_PRIV * gcsDEFAULT_PRIV_PTR;
+typedef struct _gcsDEFAULT_PRIV
+{
+ gctUINT32 low;
+ gctUINT32 high;
+}
+gcsDEFAULT_PRIV;
+
+typedef struct _gcsDEFAULT_MDL_PRIV *gcsDEFAULT_MDL_PRIV_PTR;
+typedef struct _gcsDEFAULT_MDL_PRIV
+{
+ union _pages
+ {
+ /* Pointer to a array of pages. */
+ struct page * contiguousPages;
+ /* Pointer to a array of pointers to page. */
+ struct page ** nonContiguousPages;
+ }
+ u;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ gctBOOL exact;
+#endif
+
+ struct file * file;
+
+ gctBOOL cacheable;
+
+ gcsPLATFORM * platform;
+
+ gctBOOL contiguous;
+}
+gcsDEFAULT_MDL_PRIV;
+
+/******************************************************************************\
+************************** Default Allocator Debugfs ***************************
+\******************************************************************************/
+
+int gc_usage_show(struct seq_file* m, void* data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckALLOCATOR Allocator = node->device;
+ gcsDEFAULT_PRIV_PTR priv = Allocator->privateData;
+
+ seq_printf(m, "lowMem: %u bytes\n", priv->low);
+ seq_printf(m, "highMem: %u bytes\n", priv->high);
+
+ return 0;
+}
+
+static gcsINFO InfoList[] =
+{
+ {"lowHighUsage", gc_usage_show},
+};
+
+static void
+_DefaultAllocatorDebugfsInit(
+ IN gckALLOCATOR Allocator,
+ IN gckDEBUGFS_DIR Root
+ )
+{
+ gcmkVERIFY_OK(
+ gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "default"));
+
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
+ &Allocator->debugfsDir,
+ InfoList,
+ gcmCOUNTOF(InfoList),
+ Allocator
+ ));
+}
+
+static void
+_DefaultAllocatorDebugfsCleanup(
+ IN gckALLOCATOR Allocator
+ )
+{
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
+ &Allocator->debugfsDir,
+ InfoList,
+ gcmCOUNTOF(InfoList)
+ ));
+
+ gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
+}
+
+static inline struct page *
+_NonContiguousToPage(
+ IN struct page ** Pages,
+ IN gctUINT32 Index
+ )
+{
+ gcmkASSERT(Pages != gcvNULL);
+ return Pages[Index];
+}
+
+static inline unsigned long
+_NonContiguousToPfn(
+ IN struct page ** Pages,
+ IN gctUINT32 Index
+ )
+{
+ gcmkASSERT(Pages != gcvNULL);
+ return page_to_pfn(_NonContiguousToPage(Pages, Index));
+}
+
+static inline unsigned long
+_NonContiguousToPhys(
+ IN struct page ** Pages,
+ IN gctUINT32 Index
+ )
+{
+ gcmkASSERT(Pages != gcvNULL);
+ return page_to_phys(_NonContiguousToPage(Pages, Index));
+}
+
+static void
+_NonContiguousFree(
+ IN struct page ** Pages,
+ IN gctUINT32 NumPages
+ )
+{
+ gctINT i;
+
+ gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
+
+ gcmkASSERT(Pages != gcvNULL);
+
+ for (i = 0; i < NumPages; i++)
+ {
+ __free_page(Pages[i]);
+ }
+
+ if (is_vmalloc_addr(Pages))
+ {
+ vfree(Pages);
+ }
+ else
+ {
+ kfree(Pages);
+ }
+
+ gcmkFOOTER_NO();
+}
+
+static struct page **
+_NonContiguousAlloc(
+ IN gctUINT32 NumPages
+ )
+{
+ struct page ** pages;
+ struct page *p;
+#if gcdDISCRETE_PAGES
+ struct page *l;
+#endif
+ gctINT i, size;
+
+ gcmkHEADER_ARG("NumPages=%lu", NumPages);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+ if (NumPages > totalram_pages)
+#else
+ if (NumPages > num_physpages)
+#endif
+ {
+ gcmkFOOTER_NO();
+ return gcvNULL;
+ }
+
+ size = NumPages * sizeof(struct page *);
+
+ pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
+
+ if (!pages)
+ {
+ pages = vmalloc(size);
+
+ if (!pages)
+ {
+ gcmkFOOTER_NO();
+ return gcvNULL;
+ }
+ }
+
+ for (i = 0; i < NumPages; i++)
+ {
+ p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
+
+ if (!p)
+ {
+ _NonContiguousFree(pages, i);
+ gcmkFOOTER_NO();
+ return gcvNULL;
+ }
+
+#if gcdDISCRETE_PAGES
+ if (i != 0)
+ {
+ if (page_to_pfn(pages[i-1]) == page_to_pfn(p)-1)
+ {
+ /* Replaced page. */
+ l = p;
+
+ /* Allocate a page which is not contiguous to previous one. */
+ p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN);
+
+ /* Give replaced page back. */
+ __free_page(l);
+
+ if (!p)
+ {
+ _NonContiguousFree(pages, i);
+ gcmkFOOTER_NO();
+ return gcvNULL;
+ }
+ }
+ }
+#endif
+
+ pages[i] = p;
+ }
+
+ gcmkFOOTER_ARG("pages=0x%X", pages);
+ return pages;
+}
+
+static gctSTRING
+_CreateKernelVirtualMapping(
+ IN PLINUX_MDL Mdl
+ )
+{
+ gctSTRING addr = 0;
+ gctINT numPages = Mdl->numPages;
+ gcsDEFAULT_MDL_PRIV_PTR mdlPriv = Mdl->priv;
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ if (Mdl->contiguous)
+ {
+ addr = page_address(mdlPriv->u.contiguousPages);
+ }
+ else
+ {
+ addr = vmap(mdlPriv->u.nonContiguousPages,
+ numPages,
+ 0,
+ PAGE_KERNEL);
+
+ /* Trigger a page fault. */
+ memset(addr, 0, numPages * PAGE_SIZE);
+ }
+#else
+ struct page ** pages;
+ gctBOOL free = gcvFALSE;
+ gctINT i;
+
+ if (Mdl->contiguous)
+ {
+ pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
+
+ if (!pages)
+ {
+ return gcvNULL;
+ }
+
+ for (i = 0; i < numPages; i++)
+ {
+ pages[i] = nth_page(mdlPriv->u.contiguousPages, i);
+ }
+
+ free = gcvTRUE;
+ }
+ else
+ {
+ pages = mdlPriv->u.nonContiguousPages;
+ }
+
+ /* ioremap() can't work on system memory since 2.6.38. */
+ addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
+
+ if (free)
+ {
+ kfree(pages);
+ }
+
+#endif
+
+ return addr;
+}
+
+static void
+_DestoryKernelVirtualMapping(
+ IN gctSTRING Addr
+ )
+{
+#if !gcdNONPAGED_MEMORY_CACHEABLE
+ vunmap(Addr);
+#endif
+}
+
+void
+_UnmapUserLogical(
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+)
+{
+ if (unlikely(current->mm == gcvNULL))
+ {
+ /* Do nothing if process is exiting. */
+ return;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ if (vm_munmap((unsigned long)Logical, Size) < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): vm_munmap failed",
+ __FUNCTION__, __LINE__
+ );
+ }
+#else
+ down_write(&current->mm->mmap_sem);
+ if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d): do_munmap failed",
+ __FUNCTION__, __LINE__
+ );
+ }
+ up_write(&current->mm->mmap_sem);
+#endif
+}
+
+static gceSTATUS
+default_mmap_internal(
+ IN gcsDEFAULT_MDL_PRIV_PTR MdlPriv,
+ IN struct vm_area_struct *vma
+ )
+{
+ gcsPLATFORM * platform = MdlPriv->platform;
+ gctUINT32 numPages;
+ unsigned long start;
+ unsigned long pfn;
+ gctINT i;
+
+ gcmkHEADER();
+
+ vma->vm_flags |= gcdVM_FLAGS;
+
+ if (MdlPriv->cacheable == gcvFALSE)
+ {
+ /* Make this mapping non-cached. */
+ vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(vma->vm_page_prot);
+ }
+
+ if (platform && platform->ops->adjustProt)
+ {
+ platform->ops->adjustProt(vma);
+ }
+
+ /* Now map all the vmalloc pages to this user address. */
+ if (MdlPriv->contiguous)
+ {
+ /* map kernel memory to user space.. */
+ if (remap_pfn_range(vma,
+ vma->vm_start,
+ page_to_pfn(MdlPriv->u.contiguousPages),
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot) < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): unable to mmap ret",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ numPages = (vma->vm_end - vma->vm_start) / PAGE_SIZE;
+ start = vma->vm_start;
+
+ for (i = 0; i < numPages; i++)
+ {
+ pfn = _NonContiguousToPfn(MdlPriv->u.nonContiguousPages, i);
+
+ if (remap_pfn_range(vma,
+ start,
+ pfn,
+ PAGE_SIZE,
+ vma->vm_page_prot) < 0)
+ {
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ start += PAGE_SIZE;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+static int default_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ gcsDEFAULT_MDL_PRIV_PTR mdlPriv = file->private_data;
+
+ if (gcmIS_ERROR(default_mmap_internal(mdlPriv, vma)))
+ {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct file_operations default_fops = {
+ .mmap = default_mmap,
+};
+#endif
+
+/***************************************************************************\
+************************ Default Allocator **********************************
+\***************************************************************************/
+static gceSTATUS
+_DefaultAlloc(
+ IN gckALLOCATOR Allocator,
+ INOUT PLINUX_MDL Mdl,
+ IN gctSIZE_T NumPages,
+ IN gctUINT32 Flags
+ )
+{
+ gceSTATUS status;
+ gctUINT i;
+ gctBOOL contiguous = Flags & gcvALLOC_FLAG_CONTIGUOUS;
+#ifdef gcdSYS_FREE_MEMORY_LIMIT
+ struct sysinfo temsysinfo;
+#endif
+
+ gcsDEFAULT_PRIV_PTR priv = (gcsDEFAULT_PRIV_PTR)Allocator->privateData;
+ gcsDEFAULT_MDL_PRIV_PTR mdlPriv = gcvNULL;
+
+ gcmkHEADER_ARG("Mdl=%p NumPages=%zu Flags=0x%x", Mdl, NumPages, Flags);
+
+#ifdef gcdSYS_FREE_MEMORY_LIMIT
+ si_meminfo(&temsysinfo);
+
+ if (Flags & gcvALLOC_FLAG_MEMLIMIT)
+ {
+ if ( (temsysinfo.freeram < NumPages) || ((temsysinfo.freeram-NumPages) < gcdSYS_FREE_MEMORY_LIMIT) )
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ }
+#endif
+
+ gcmkONERROR(gckOS_Allocate(Allocator->os, gcmSIZEOF(gcsDEFAULT_MDL_PRIV), (gctPOINTER *)&mdlPriv));
+
+ gckOS_ZeroMemory(mdlPriv, gcmSIZEOF(gcsDEFAULT_MDL_PRIV));
+
+ if (contiguous)
+ {
+ size_t bytes = NumPages << PAGE_SHIFT;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ void *addr = NULL;
+
+ addr = alloc_pages_exact(bytes, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
+
+ mdlPriv->u.contiguousPages = addr ? virt_to_page(addr) : gcvNULL;
+
+ mdlPriv->exact = gcvTRUE;
+#endif
+
+ if (mdlPriv->u.contiguousPages == gcvNULL)
+ {
+ int order = get_order(bytes);
+
+ if (order >= MAX_ORDER)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+ mdlPriv->u.contiguousPages =
+ alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ mdlPriv->exact = gcvFALSE;
+#endif
+ }
+
+ if (mdlPriv->u.contiguousPages == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ }
+ else
+ {
+ mdlPriv->u.nonContiguousPages = _NonContiguousAlloc(NumPages);
+
+ if (mdlPriv->u.nonContiguousPages == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ }
+
+ for (i = 0; i < NumPages; i++)
+ {
+ struct page *page;
+ gctPHYS_ADDR_T phys = 0U;
+
+ if (contiguous)
+ {
+ page = nth_page(mdlPriv->u.contiguousPages, i);
+ }
+ else
+ {
+ page = _NonContiguousToPage(mdlPriv->u.nonContiguousPages, i);
+ }
+
+ SetPageReserved(page);
+
+ phys = page_to_phys(page);
+
+ BUG_ON(!phys);
+
+ if (PageHighMem(page))
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+ void *vaddr = kmap_atomic(page);
+#else
+ void *vaddr = kmap_atomic(page, KM_USER0);
+#endif
+
+ gcmkVERIFY_OK(gckOS_CacheFlush(
+ Allocator->os, _GetProcessID(), gcvNULL, phys, vaddr, PAGE_SIZE
+ ));
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+ kunmap_atomic(vaddr);
+#else
+ kunmap_atomic(vaddr, KM_USER0);
+#endif
+
+ priv->high += PAGE_SIZE;
+ }
+ else
+ {
+ gcmkVERIFY_OK(gckOS_CacheFlush(
+ Allocator->os, _GetProcessID(), gcvNULL, phys, page_address(page), PAGE_SIZE
+ ));
+
+ priv->low += PAGE_SIZE;
+ }
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+ mdlPriv->file = anon_inode_getfile("default", &default_fops, mdlPriv, O_RDWR);
+
+ if (IS_ERR(mdlPriv->file))
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+#endif
+
+ mdlPriv->platform = Allocator->os->device->platform;
+ mdlPriv->contiguous = contiguous;
+
+ Mdl->priv = mdlPriv;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mdlPriv)
+ {
+ gcmkOS_SAFE_FREE(Allocator->os, mdlPriv);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+static void
+_DefaultFree(
+ IN gckALLOCATOR Allocator,
+ IN OUT PLINUX_MDL Mdl
+ )
+{
+ gctINT i;
+ struct page * page;
+ gcsDEFAULT_PRIV_PTR priv = (gcsDEFAULT_PRIV_PTR)Allocator->privateData;
+ gcsDEFAULT_MDL_PRIV_PTR mdlPriv = Mdl->priv;
+
+ for (i = 0; i < Mdl->numPages; i++)
+ {
+ if (Mdl->contiguous)
+ {
+ page = nth_page(mdlPriv->u.contiguousPages, i);
+ }
+ else
+ {
+ page = _NonContiguousToPage(mdlPriv->u.nonContiguousPages, i);
+ }
+
+ ClearPageReserved(page);
+
+ if (PageHighMem(page))
+ {
+ priv->high -= PAGE_SIZE;
+ }
+ else
+ {
+ priv->low -= PAGE_SIZE;
+ }
+ }
+
+ if (Mdl->contiguous)
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ if (mdlPriv->exact == gcvTRUE)
+ {
+ free_pages_exact(page_address(mdlPriv->u.contiguousPages), Mdl->numPages * PAGE_SIZE);
+ }
+ else
+#endif
+ {
+ __free_pages(mdlPriv->u.contiguousPages, get_order(Mdl->numPages * PAGE_SIZE));
+ }
+ }
+ else
+ {
+ _NonContiguousFree(mdlPriv->u.nonContiguousPages, Mdl->numPages);
+ }
+
+ if (mdlPriv->file != gcvNULL)
+ {
+ fput(mdlPriv->file);
+ }
+
+ gcmkOS_SAFE_FREE(Allocator->os, Mdl->priv);
+}
+
+gctINT
+_DefaultMapUser(
+ gckALLOCATOR Allocator,
+ PLINUX_MDL Mdl,
+ gctBOOL Cacheable,
+ OUT gctPOINTER * UserLogical
+ )
+{
+ gckOS os = Allocator->os;
+
+ PLINUX_MDL mdl = Mdl;
+ gctPOINTER userLogical = gcvNULL;
+ struct vm_area_struct * vma;
+ gcsDEFAULT_MDL_PRIV_PTR mdlPriv = Mdl->priv;
+
+ gcmkHEADER_ARG("Allocator=%p Mdl=%p gctBOOL=%d", Allocator, Mdl, Cacheable);
+
+ /* mdlPriv->cacheable must be used under protection of mdl->mapMutex. */
+ mdlPriv->cacheable = Cacheable;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+ userLogical = (gctSTRING)vm_mmap(mdlPriv->file,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+#else
+ down_write(&current->mm->mmap_sem);
+
+ userLogical = (gctSTRING)do_mmap_pgoff(mdlPriv->file,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ up_write(&current->mm->mmap_sem);
+#endif
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
+ __FUNCTION__, __LINE__,
+ (gctUINT32)(gctUINTPTR_T)userLogical,
+ (gctUINT32)(gctUINTPTR_T)mdl
+ );
+
+ if (IS_ERR(userLogical))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): do_mmap_pgoff error",
+ __FUNCTION__, __LINE__
+ );
+
+ userLogical = gcvNULL;
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ if (mdlPriv->file == gcvNULL)
+ {
+ /* Remap here since there is no file and ops->mmap(). */
+ down_write(&current->mm->mmap_sem);
+
+ vma = find_vma(current->mm, (unsigned long)userLogical);
+
+ if (vma == gcvNULL)
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): find_vma error",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ if (gcmIS_ERROR(default_mmap_internal(mdlPriv, vma)))
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ up_write(&current->mm->mmap_sem);
+ }
+
+ gcmkVERIFY_OK(gckOS_CacheFlush(
+ os,
+ _GetProcessID(),
+ mdl,
+ gcvINVALID_ADDRESS,
+ userLogical,
+ mdl->numPages * PAGE_SIZE
+ ));
+
+ *UserLogical = userLogical;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+void
+_DefaultUnmapUser(
+ IN gckALLOCATOR Allocator,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ )
+{
+ _UnmapUserLogical(Logical, Size);
+}
+
+gceSTATUS
+_DefaultMapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ OUT gctPOINTER *Logical
+ )
+{
+ *Logical = _CreateKernelVirtualMapping(Mdl);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_DefaultUnmapKernel(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical
+ )
+{
+ _DestoryKernelVirtualMapping(Logical);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_DefaultCache(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes,
+ IN gceCACHEOPERATION Operation
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_DefaultPhysical(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ gcsDEFAULT_MDL_PRIV_PTR mdlPriv = Mdl->priv;
+ gctUINT32 offsetInPage = Offset & ~PAGE_MASK;
+ gctUINT32 index = Offset / PAGE_SIZE;
+
+ if (Mdl->contiguous)
+ {
+ *Physical = page_to_phys(nth_page(mdlPriv->u.contiguousPages, index));
+ }
+ else
+ {
+ *Physical = _NonContiguousToPhys(mdlPriv->u.nonContiguousPages, index);
+ }
+
+ *Physical += offsetInPage;
+
+ return gcvSTATUS_OK;
+}
+
+void
+_DefaultAllocatorDestructor(
+ IN void* PrivateData
+ )
+{
+ kfree(PrivateData);
+}
+
+/* Default allocator operations. */
+gcsALLOCATOR_OPERATIONS DefaultAllocatorOperations = {
+ .Alloc = _DefaultAlloc,
+ .Free = _DefaultFree,
+ .MapUser = _DefaultMapUser,
+ .UnmapUser = _DefaultUnmapUser,
+ .MapKernel = _DefaultMapKernel,
+ .UnmapKernel = _DefaultUnmapKernel,
+ .Cache = _DefaultCache,
+ .Physical = _DefaultPhysical,
+};
+
+/* Default allocator entry. */
+gceSTATUS
+_DefaultAlloctorInit(
+ IN gckOS Os,
+ OUT gckALLOCATOR * Allocator
+ )
+{
+ gceSTATUS status;
+ gckALLOCATOR allocator = gcvNULL;
+ gcsDEFAULT_PRIV_PTR priv = gcvNULL;
+
+ gcmkONERROR(
+ gckALLOCATOR_Construct(Os, &DefaultAllocatorOperations, &allocator));
+
+ priv = kzalloc(gcmSIZEOF(gcsDEFAULT_PRIV), GFP_KERNEL | gcdNOWARN);
+
+ if (!priv)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Register private data. */
+ allocator->privateData = priv;
+ allocator->privateDataDestructor = _DefaultAllocatorDestructor;
+
+ allocator->debugfsInit = _DefaultAllocatorDebugfsInit;
+ allocator->debugfsCleanup = _DefaultAllocatorDebugfsCleanup;
+
+ allocator->capability = gcvALLOC_FLAG_CONTIGUOUS
+ | gcvALLOC_FLAG_NON_CONTIGUOUS
+ | gcvALLOC_FLAG_CACHEABLE
+ | gcvALLOC_FLAG_MEMLIMIT
+ | gcvALLOC_FLAG_ALLOC_ON_FAULT
+ ;
+
+#if defined(gcdEMULATE_SECURE_ALLOCATOR)
+ allocator->capability |= gcvALLOC_FLAG_SECURITY;
+#endif
+
+ *Allocator = allocator;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (allocator)
+ {
+ gcmkOS_SAFE_FREE(Os, allocator);
+ }
+ return status;
+}
+
+/***************************************************************************\
+************************ Allocator helper ***********************************
+\***************************************************************************/
+
+gceSTATUS
+gckALLOCATOR_Construct(
+ IN gckOS Os,
+ IN gcsALLOCATOR_OPERATIONS * Operations,
+ OUT gckALLOCATOR * Allocator
+ )
+{
+ gceSTATUS status;
+ gckALLOCATOR allocator;
+
+ gcmkHEADER_ARG("Os=%p, Operations=%p, Allocator=%p",
+ Os, Operations, Allocator);
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Allocator != gcvNULL);
+ gcmkVERIFY_ARGUMENT
+ ( Operations
+ && (Operations->Alloc || Operations->Attach)
+ && (Operations->Free)
+ && Operations->MapUser
+ && Operations->UnmapUser
+ && Operations->MapKernel
+ && Operations->UnmapKernel
+ && Operations->Cache
+ && Operations->Physical
+ );
+
+ gcmkONERROR(
+ gckOS_Allocate(Os, gcmSIZEOF(gcsALLOCATOR), (gctPOINTER *)&allocator));
+
+ gckOS_ZeroMemory(allocator, gcmSIZEOF(gcsALLOCATOR));
+
+ /* Record os. */
+ allocator->os = Os;
+
+ /* Set operations. */
+ allocator->ops = Operations;
+
+ *Allocator = allocator;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/******************************************************************************\
+******************************** Debugfs Support *******************************
+\******************************************************************************/
+
+static gceSTATUS
+_AllocatorDebugfsInit(
+ IN gckOS Os
+ )
+{
+ gceSTATUS status;
+ gckGALDEVICE device = Os->device;
+
+ gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
+
+ gcmkONERROR(gckDEBUGFS_DIR_Init(dir, device->debugfsDir.root, "allocators"));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+static void
+_AllocatorDebugfsCleanup(
+ IN gckOS Os
+ )
+{
+ gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
+
+ gckDEBUGFS_DIR_Deinit(dir);
+}
+
+/***************************************************************************\
+************************ Allocator management *******************************
+\***************************************************************************/
+
+gceSTATUS
+gckOS_ImportAllocators(
+ gckOS Os
+ )
+{
+ gceSTATUS status;
+ gctUINT i;
+ gckALLOCATOR allocator;
+
+ _AllocatorDebugfsInit(Os);
+
+ INIT_LIST_HEAD(&Os->allocatorList);
+
+ for (i = 0; i < gcmCOUNTOF(allocatorArray); i++)
+ {
+ if (allocatorArray[i].construct)
+ {
+ /* Construct allocator. */
+ status = allocatorArray[i].construct(Os, &allocator);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkPRINT("["DEVICE_NAME"]: Can't construct allocator(%s)",
+ allocatorArray[i].name);
+
+ continue;
+ }
+
+ allocator->name = allocatorArray[i].name;
+
+ if (allocator->debugfsInit)
+ {
+ /* Init allocator's debugfs. */
+ allocator->debugfsInit(allocator, &Os->allocatorDebugfsDir);
+ }
+
+ list_add_tail(&allocator->head, &Os->allocatorList);
+ }
+ }
+
+#if gcdDEBUG
+ list_for_each_entry(allocator, &Os->allocatorList, head)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_WARNING, gcvZONE_OS,
+ "%s(%d) Allocator: %s",
+ __FUNCTION__, __LINE__,
+ allocator->name
+ );
+ }
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_FreeAllocators(
+ gckOS Os
+ )
+{
+ gckALLOCATOR allocator;
+ gckALLOCATOR temp;
+
+ list_for_each_entry_safe(allocator, temp, &Os->allocatorList, head)
+ {
+ list_del(&allocator->head);
+
+ if (allocator->debugfsCleanup)
+ {
+ /* Clean up allocator's debugfs. */
+ allocator->debugfsCleanup(allocator);
+ }
+
+ /* Free private data. */
+ if (allocator->privateDataDestructor && allocator->privateData)
+ {
+ allocator->privateDataDestructor(allocator->privateData);
+ }
+
+ gckOS_Free(Os, allocator);
+ }
+
+ _AllocatorDebugfsCleanup(Os);
+
+ return gcvSTATUS_OK;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h
new file mode 100644
index 000000000000..f1dc7c772bac
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h
@@ -0,0 +1,436 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_allocator_h_
+#define __gc_hal_kernel_allocator_h_
+
+#include "gc_hal_kernel_linux.h"
+
+typedef struct _gcsALLOCATOR * gckALLOCATOR;
+typedef struct _gcsATTACH_DESC * gcsATTACH_DESC_PTR;
+
+typedef struct _gcsALLOCATOR_OPERATIONS
+{
+ /**************************************************************************
+ **
+ ** Alloc
+ **
+ ** Allocte memory, request size is page aligned.
+ **
+ ** INPUT:
+ **
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** PLINUX_Mdl
+ ** Pointer to Mdl whichs stores information
+ ** about allocated memory.
+ **
+ ** gctSIZE_T NumPages
+ ** Number of pages need to allocate.
+ **
+ ** gctUINT32 Flag
+ ** Allocation option.
+ **
+ ** OUTPUT:
+ **
+ ** Nothing.
+ **
+ */
+ gceSTATUS
+ (*Alloc)(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctSIZE_T NumPages,
+ IN gctUINT32 Flag
+ );
+
+ /**************************************************************************
+ **
+ ** Free
+ **
+ ** Free memory.
+ **
+ ** INPUT:
+ **
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** PLINUX_MDL Mdl
+ ** Mdl which stores information.
+ **
+ ** OUTPUT:
+ **
+ ** Nothing.
+ **
+ */
+ void
+ (*Free)(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl
+ );
+
+ /**************************************************************************
+ **
+ ** MapUser
+ **
+ ** Map memory to user space.
+ **
+ ** INPUT:
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** PLINUX_MDL Mdl
+ ** Pointer to a Mdl.
+ **
+ ** gctBOOL Cacheable
+ ** Whether this mapping is cacheable.
+ **
+ ** OUTPUT:
+ **
+ ** gctPOINTER * UserLogical
+ ** Pointer to user logical address.
+ **
+ ** Nothing.
+ **
+ */
+ gctINT
+ (*MapUser)(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctBOOL Cacheable,
+ OUT gctPOINTER * UserLogical
+ );
+
+ /**************************************************************************
+ **
+ ** UnmapUser
+ **
+ ** Unmap address from user address space.
+ **
+ ** INPUT:
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** gctPOINTER Logical
+ ** Address to be unmap
+ **
+ ** gctUINT32 Size
+ ** Size of address space
+ **
+ ** OUTPUT:
+ **
+ ** Nothing.
+ **
+ */
+ void
+ (*UnmapUser)(
+ IN gckALLOCATOR Allocator,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ );
+
+ /**************************************************************************
+ **
+ ** MapKernel
+ **
+ ** Map memory to kernel space.
+ **
+ ** INPUT:
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** PLINUX_MDL Mdl
+ ** Pointer to a Mdl object.
+ **
+ ** OUTPUT:
+ ** gctPOINTER * Logical
+ ** Mapped kernel address.
+ */
+ gceSTATUS
+ (*MapKernel)(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ OUT gctPOINTER *Logical
+ );
+
+ /**************************************************************************
+ **
+ ** UnmapKernel
+ **
+ ** Unmap memory from kernel space.
+ **
+ ** INPUT:
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** PLINUX_MDL Mdl
+ ** Pointer to a Mdl object.
+ **
+ ** gctPOINTER Logical
+ ** Mapped kernel address.
+ **
+ ** OUTPUT:
+ **
+ ** Nothing.
+ **
+ */
+ gceSTATUS
+ (*UnmapKernel)(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical
+ );
+
+ /**************************************************************************
+ **
+ ** Cache
+ **
+ ** Maintain cache coherency.
+ **
+ ** INPUT:
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** PLINUX_MDL Mdl
+ ** Pointer to a Mdl object.
+ **
+ ** gctPOINTER Logical
+ ** Logical address, could be user address or kernel address
+ **
+ ** gctUINT32_PTR Physical
+ ** Physical address.
+ **
+ ** gctUINT32 Bytes
+ ** Size of memory region.
+ **
+ ** gceCACHEOPERATION Opertaion
+ ** Cache operation.
+ **
+ ** OUTPUT:
+ **
+ ** Nothing.
+ **
+ */
+ gceSTATUS (*Cache)(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes,
+ IN gceCACHEOPERATION Operation
+ );
+
+ /**************************************************************************
+ **
+ ** Physical
+ **
+ ** Get physical address from a offset in memory region.
+ **
+ ** INPUT:
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** PLINUX_MDL Mdl
+ ** Pointer to a Mdl object.
+ **
+ ** gctUINT32 Offset
+ ** Offset in this memory region.
+ **
+ ** OUTPUT:
+ ** gctUINT32_PTR Physical
+ ** Physical address.
+ **
+ */
+ gceSTATUS (*Physical)(
+ IN gckALLOCATOR Allocator,
+ IN PLINUX_MDL Mdl,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * Physical
+ );
+
+ /**************************************************************************
+ **
+ ** Attach
+ **
+ ** Import memory allocated by an external allocator.
+ **
+ ** INPUT:
+ ** gckALLOCATOR Allocator
+ ** Pointer to an gckALLOCATOER object.
+ **
+ ** gctUINT32 Handle
+ ** Handle of the memory.
+ **
+ ** OUTPUT:
+ ** None.
+ **
+ */
+ gceSTATUS (*Attach)(
+ IN gckALLOCATOR Allocator,
+ IN gcsATTACH_DESC_PTR Desc,
+ OUT PLINUX_MDL Mdl
+ );
+}
+gcsALLOCATOR_OPERATIONS;
+
+typedef struct _gcsALLOCATOR
+{
+ /* Pointer to gckOS Object. */
+ gckOS os;
+
+ /* Name. */
+ gctSTRING name;
+
+ /* Operations. */
+ gcsALLOCATOR_OPERATIONS* ops;
+
+ /* Capability of this allocator. */
+ gctUINT32 capability;
+
+ struct list_head head;
+
+ /* Debugfs entry of this allocator. */
+ gcsDEBUGFS_DIR debugfsDir;
+
+ /* Init allocator debugfs. */
+ void (*debugfsInit)(gckALLOCATOR, gckDEBUGFS_DIR);
+
+ /* Cleanup allocator debugfs. */
+ void (*debugfsCleanup)(gckALLOCATOR);
+
+ /* Private data used by customer allocator. */
+ void * privateData;
+
+ /* Private data destructor. */
+ void (*privateDataDestructor)(void *);
+}
+gcsALLOCATOR;
+
+typedef struct _gcsALLOCATOR_DESC
+{
+ /* Name of a allocator. */
+ char * name;
+
+ /* Entry function to construct a allocator. */
+ gceSTATUS (*construct)(gckOS, gckALLOCATOR *);
+}
+gcsALLOCATOR_DESC;
+
+typedef struct _gcsATTACH_DESC
+{
+ /* gcvALLOC_FLAG_DMABUF */
+ gctUINT32 handle;
+
+ /* gcvALLOC_FLAG_USERMEMORY */
+ gctPOINTER memory;
+ gctUINT32 physical;
+ gctSIZE_T size;
+
+ gcsEXTERNAL_MEMORY_INFO info;
+}
+gcsATTACH_DESC;
+
+/*
+* Helpers
+*/
+
+/* Fill a gcsALLOCATOR_DESC structure. */
+#define gcmkDEFINE_ALLOCATOR_DESC(Name, Construct) \
+ { \
+ .name = Name, \
+ .construct = Construct, \
+ }
+
+/* Construct a allocator. */
+gceSTATUS
+gckALLOCATOR_Construct(
+ IN gckOS Os,
+ IN gcsALLOCATOR_OPERATIONS * Operations,
+ OUT gckALLOCATOR * Allocator
+ );
+
+/*
+ How to implement customer allocator
+
+ Build in customer alloctor
+
+ It is recommanded that customer allocator is implmented in independent
+ source file(s) which is specified by CUSOMTER_ALLOCATOR_OBJS in Kbuld.
+
+ Register gcsALLOCATOR
+
+ For each customer specified allocator, a desciption entry must be added
+ to allocatorArray defined in gc_hal_kernel_allocator_array.h.
+
+ An entry in allocatorArray is a gcsALLOCATOR_DESC structure which describes
+ name and constructor of a gckALLOCATOR object.
+
+
+ Implement gcsALLOCATOR_DESC.init()
+
+ In gcsALLOCATOR_DESC.init(), gckALLOCATOR_Construct should be called
+ to create a gckALLOCATOR object, customer specified private data can
+ be put in gcsALLOCATOR.privateData.
+
+
+ Implement gcsALLOCATOR_OPERATIONS
+
+ When call gckALLOCATOR_Construct to create a gckALLOCATOR object, a
+ gcsALLOCATOR_OPERATIONS structure must be provided whose all members
+ implemented.
+
+*/
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h
new file mode 100644
index 000000000000..afbd7b49f209
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_debug_h_
+#define __gc_hal_kernel_debug_h_
+
+#include <gc_hal_kernel_linux.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** OS-dependent Macros *****************************
+\******************************************************************************/
+
+typedef va_list gctARGUMENTS;
+
+#define gcmkARGUMENTS_START(Arguments, Pointer) \
+ va_start(Arguments, Pointer)
+
+#define gcmkARGUMENTS_END(Arguments) \
+ va_end(Arguments)
+
+#define gcmkARGUMENTS_ARG(Arguments, Type) \
+ va_arg(Arguments, Type)
+
+#if gcdDUMP_COMMAND || gcdDUMP_IN_KERNEL
+/* VIV: gckOS_DumpBuffer holds spinlock and return to userspace which causes
+ schedule in atomic. Because there isn't dump information from interrupt,
+ mutex can be used in this situation. Need to solve this by avoid
+ return userspace while lock still being hold which is very dangerous.
+*/
+#define gcmkDECLARE_LOCK(__mutex__) \
+ static DEFINE_MUTEX(__mutex__); \
+
+#define gcmkLOCKSECTION(__mutex__) \
+ mutex_lock(&__mutex__);
+
+#define gcmkUNLOCKSECTION(__mutex__) \
+ mutex_unlock(&__mutex__);
+#else
+#define gcmkDECLARE_LOCK(__spinLock__) \
+ static DEFINE_SPINLOCK(__spinLock__); \
+ unsigned long __spinLock__##flags = 0;
+
+#define gcmkLOCKSECTION(__spinLock__) \
+ spin_lock_irqsave(&__spinLock__, __spinLock__##flags)
+
+#define gcmkUNLOCKSECTION(__spinLock__) \
+ spin_unlock_irqrestore(&__spinLock__, __spinLock__##flags)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+# define gcmkGETPROCESSID() \
+ task_tgid_vnr(current)
+#else
+# define gcmkGETPROCESSID() \
+ current->tgid
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+# define gcmkGETTHREADID() \
+ task_pid_vnr(current)
+#else
+# define gcmkGETTHREADID() \
+ current->pid
+#endif
+
+#define gcmkOUTPUT_STRING(String) \
+ if(gckDEBUGFS_IsEnabled()) {\
+ while(-ERESTARTSYS == gckDEBUGFS_Print(String));\
+ }else{\
+ printk(String); \
+ }\
+ touch_softlockup_watchdog()
+
+
+#define gcmkSPRINTF(Destination, Size, Message, Value) \
+ snprintf(Destination, Size, Message, Value)
+
+#define gcmkSPRINTF2(Destination, Size, Message, Value1, Value2) \
+ snprintf(Destination, Size, Message, Value1, Value2)
+
+#define gcmkSPRINTF3(Destination, Size, Message, Value1, Value2, Value3) \
+ snprintf(Destination, Size, Message, Value1, Value2, Value3)
+
+#define gcmkVSPRINTF(Destination, Size, Message, Arguments) \
+ vsnprintf(Destination, Size, Message, *((va_list*)Arguments))
+
+#define gcmkSTRCATSAFE(Destination, Size, String) \
+ strncat(Destination, String, (Size) - 1)
+
+#define gcmkMEMCPY(Destination, Source, Size) \
+ memcpy(Destination, Source, Size)
+
+#define gcmkSTRLEN(String) \
+ strlen(String)
+
+/* If not zero, forces data alignment in the variable argument list
+ by its individual size. */
+#define gcdALIGNBYSIZE 1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_debug_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c
new file mode 100644
index 000000000000..3ad0f5ebc689
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.c
@@ -0,0 +1,963 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <asm/uaccess.h>
+#include <linux/completion.h>
+#include <linux/seq_file.h>
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_debug.h"
+
+/*
+ Prequsite:
+
+ 1) Debugfs feature must be enabled in the kernel.
+ 1.a) You can enable this, in the compilation of the uImage, all you have to do is, In the "make menuconfig" part,
+ you have to enable the debugfs in the kernel hacking part of the menu.
+
+ HOW TO USE:
+ 1) insert the driver with the following option logFileSize, Ex: insmod galcore.ko ...... logFileSize=10240
+ This gives a circular buffer of 10 MB
+
+ 2)Usually after inserting the driver, the debug file system is mounted under /sys/kernel/debug/
+
+ 2.a)If the debugfs is not mounted, you must do "mount -t debugfs none /sys/kernel/debug"
+
+ 3) To read what is being printed in the debugfs file system:
+ Ex : cat /sys/kernel/debug/gc/galcore_trace
+
+ 4)To write into the debug file system from user side :
+ Ex: echo "hello" > cat /sys/kernel/debug/gc/galcore_trace
+
+ 5)To write into debugfs from kernel side, Use the function called gckDEBUGFS_Print
+
+ How to Get Video Memory Usage:
+ 1) Select a process whose video memory usage can be dump, no need to reset it until <pid> is needed to be change.
+ echo <pid> > /sys/kernel/debug/gc/vidmem
+
+ 2) Get video memory usage.
+ cat /sys/kernel/debug/gc/vidmem
+
+ USECASE Kernel Dump:
+
+ 1) Go to /hal/inc/gc_hal_options.h, and enable the following flags:
+ - # define gcdDUMP 1
+ - # define gcdDUMP_IN_KERNEL 1
+ - # define gcdDUMP_COMMAND 1
+
+ 2) Go to /hal/kernel/gc_hal_kernel_command.c and disable the following flag
+ -#define gcdSIMPLE_COMMAND_DUMP 0
+
+ 3) Compile the driver
+ 4) insmod it with the logFileSize option
+ 5) Run an application
+ 6) You can get the dump by cat /sys/kernel/debug/gpu/galcore_trace
+
+ */
+
+/**/
+typedef va_list gctDBGARGS ;
+#define gcmkARGS_START(argument, pointer) va_start(argument, pointer)
+#define gcmkARGS_END(argument) va_end(argument)
+
+#define gcmkDEBUGFS_PRINT(ArgumentSize, Message) \
+ { \
+ gctDBGARGS __arguments__; \
+ gcmkARGS_START(__arguments__, Message); \
+ _debugfs_res = _DebugFSPrint(ArgumentSize, Message, &__arguments__);\
+ gcmkARGS_END(__arguments__); \
+ }
+
+
+gcmkDECLARE_LOCK(traceLock);
+
+/* Debug File System Node Struct. */
+struct _gcsDEBUGFS_Node
+{
+ /*wait queues for read and write operations*/
+#if defined(DECLARE_WAIT_QUEUE_HEAD)
+ wait_queue_head_t read_q , write_q ;
+#else
+ struct wait_queue *read_q , *write_q ;
+#endif
+ struct dentry *parent ; /*parent directory*/
+ struct dentry *filen ; /*filename*/
+ struct semaphore sem ; /* mutual exclusion semaphore */
+ char *data ; /* The circular buffer data */
+ int size ; /* Size of the buffer pointed to by 'data' */
+ int refcount ; /* Files that have this buffer open */
+ int read_point ; /* Offset in circ. buffer of oldest data */
+ int write_point ; /* Offset in circ. buffer of newest data */
+ int offset ; /* Byte number of read_point in the stream */
+ struct _gcsDEBUGFS_Node *next ;
+
+ caddr_t temp;
+ int tempSize;
+};
+
+/* amount of data in the queue */
+#define gcmkNODE_QLEN(node) ( (node)->write_point >= (node)->read_point ? \
+ (node)->write_point - (node)->read_point : \
+ (node)->size - (node)->read_point + (node)->write_point)
+
+/* byte number of the last byte in the queue */
+#define gcmkNODE_FIRST_EMPTY_BYTE(node) ((node)->offset + gcmkNODE_QLEN(node))
+
+/*Synchronization primitives*/
+#define gcmkNODE_READQ(node) (&((node)->read_q))
+#define gcmkNODE_WRITEQ(node) (&((node)->write_q))
+#define gcmkNODE_SEM(node) (&((node)->sem))
+
+/*Utilities*/
+#define gcmkMIN(x, y) ((x) < (y) ? (x) : y)
+
+/*Debug File System Struct*/
+typedef struct _gcsDEBUGFS_
+{
+ gcsDEBUGFS_Node* linkedlist ;
+ gcsDEBUGFS_Node* currentNode ;
+ int isInited ;
+} gcsDEBUGFS_ ;
+
+/*debug file system*/
+static gcsDEBUGFS_ gc_dbgfs ;
+
+static int gc_debugfs_open(struct inode *inode, struct file *file)
+{
+ gcsINFO_NODE *node = inode->i_private;
+
+ return single_open(file, node->info->show, node);
+}
+
+static ssize_t
+gc_debugfs_write(
+ struct file *file,
+ const char __user *buf,
+ size_t count,
+ loff_t *pos
+ )
+{
+ struct seq_file *s = file->private_data;
+ gcsINFO_NODE *node = s->private;
+ gcsINFO *info = node->info;
+
+ if (info->write)
+ {
+ char tmpbuf[256] = {0};
+
+ if (count >= sizeof(tmpbuf) || copy_from_user(tmpbuf, buf, count) > 0)
+ {
+ return 0;
+ }
+
+ info->write(tmpbuf, count, node);
+ }
+
+ return count;
+}
+
+static const struct file_operations gc_debugfs_operations = {
+ .owner = THIS_MODULE,
+ .open = gc_debugfs_open,
+ .write = gc_debugfs_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+gceSTATUS
+gckDEBUGFS_DIR_Init(
+ IN gckDEBUGFS_DIR Dir,
+ IN struct dentry *root,
+ IN gctCONST_STRING Name
+ )
+{
+ Dir->root = debugfs_create_dir(Name, root);
+
+ if (!Dir->root)
+ {
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ INIT_LIST_HEAD(&Dir->nodeList);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckDEBUGFS_DIR_CreateFiles(
+ IN gckDEBUGFS_DIR Dir,
+ IN gcsINFO * List,
+ IN int count,
+ IN gctPOINTER Data
+ )
+{
+ int i;
+ gcsINFO_NODE * node;
+ gceSTATUS status;
+
+ for (i = 0; i < count; i++)
+ {
+ /* Create a node. */
+ node = (gcsINFO_NODE *)kzalloc(sizeof(gcsINFO_NODE), GFP_KERNEL);
+
+ node->info = &List[i];
+ node->device = Data;
+
+ node->entry = debugfs_create_file(
+ List[i].name, S_IRUGO|S_IWUSR, Dir->root, node, &gc_debugfs_operations);
+
+ if (!node->entry)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ list_add(&(node->head), &(Dir->nodeList));
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(Dir, List, count));
+ return status;
+}
+
+gceSTATUS
+gckDEBUGFS_DIR_RemoveFiles(
+ IN gckDEBUGFS_DIR Dir,
+ IN gcsINFO * List,
+ IN int count
+ )
+{
+ int i;
+ gcsINFO_NODE * node;
+ gcsINFO_NODE * temp;
+
+ for (i = 0; i < count; i++)
+ {
+ list_for_each_entry_safe(node, temp, &Dir->nodeList, head)
+ {
+ if (node->info == &List[i])
+ {
+ debugfs_remove(node->entry);
+ list_del(&node->head);
+ kfree(node);
+ }
+ }
+ }
+
+ return gcvSTATUS_OK;
+}
+
+void
+gckDEBUGFS_DIR_Deinit(
+ IN gckDEBUGFS_DIR Dir
+ )
+{
+ if (Dir->root != NULL)
+ {
+ debugfs_remove(Dir->root);
+ Dir->root = NULL;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** READ & WRITE FUNCTIONS (START)
+ **
+ *******************************************************************************/
+
+/*******************************************************************************
+ **
+ ** _ReadFromNode
+ **
+ ** 1) reading bytes out of a circular buffer with wraparound.
+ ** 2)returns caddr_t, pointer to data read, which the caller must free.
+ ** 3) length is (a pointer to) the number of bytes to be read, which will be set by this function to
+ ** be the number of bytes actually returned
+ **
+ *******************************************************************************/
+static caddr_t
+_ReadFromNode (
+ gcsDEBUGFS_Node* Node ,
+ size_t *Length ,
+ loff_t *Offset
+ )
+{
+ caddr_t retval ;
+ int bytes_copied = 0 , n , start_point , remaining ;
+
+ /* find the smaller of the total bytes we have available and what
+ * the user is asking for */
+ *Length = gcmkMIN ( *Length , gcmkNODE_QLEN(Node) ) ;
+
+ remaining = * Length ;
+
+ /* Get start point. */
+ start_point = Node->read_point;
+
+ /* allocate memory to return */
+ if (remaining > Node->tempSize)
+ {
+ kfree(Node->temp);
+
+ if ( ( retval = kmalloc ( sizeof (char ) * remaining , GFP_KERNEL ) ) == NULL )
+ return NULL;
+
+ Node->temp = retval;
+ Node->tempSize = remaining;
+ }
+ else
+ {
+ retval = Node->temp;
+ }
+
+ /* copy the (possibly noncontiguous) data to our buffer */
+ while ( remaining )
+ {
+ n = gcmkMIN ( remaining , Node->size - start_point ) ;
+ memcpy ( retval + bytes_copied , Node->data + start_point , n ) ;
+ bytes_copied += n ;
+ remaining -= n ;
+ start_point = ( start_point + n ) % Node->size ;
+ }
+
+ /* advance user's file pointer */
+ Node->read_point = (Node->read_point + * Length) % Node->size ;
+
+ return retval ;
+}
+
+/*******************************************************************************
+ **
+ ** _WriteToNode
+ **
+ ** 1) writes to a circular buffer with wraparound.
+ ** 2)in case of an overflow, it overwrites the oldest unread data.
+ **
+ *********************************************************************************/
+static void
+_WriteToNode (
+ gcsDEBUGFS_Node* Node ,
+ caddr_t Buf ,
+ int Length
+ )
+{
+ int bytes_copied = 0 ;
+ int overflow = 0 ;
+ int n ;
+
+ if ( Length + gcmkNODE_QLEN ( Node ) >= ( Node->size - 1 ) )
+ {
+ overflow = 1 ;
+ }
+
+ while ( Length )
+ {
+ /* how many contiguous bytes are available from the write point to
+ * the end of the circular buffer? */
+ n = gcmkMIN ( Length , Node->size - Node->write_point ) ;
+ memcpy ( Node->data + Node->write_point , Buf + bytes_copied , n ) ;
+ bytes_copied += n ;
+ Length -= n ;
+ Node->write_point = ( Node->write_point + n ) % Node->size ;
+ }
+
+ /* if there is an overflow, reset the read point to read whatever is
+ * the oldest data that we have, that has not yet been
+ * overwritten. */
+ if ( overflow )
+ {
+ Node->read_point = ( Node->write_point + 1 ) % Node->size ;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** PRINTING UTILITY (START)
+ **
+ *******************************************************************************/
+
+/*******************************************************************************
+ **
+ ** _GetArgumentSize
+ **
+ **
+ *******************************************************************************/
+static gctINT
+_GetArgumentSize (
+ IN gctCONST_STRING Message
+ )
+{
+ gctINT i , count ;
+
+ for ( i = 0 , count = 0 ; Message[i] ; i += 1 )
+ {
+ if ( Message[i] == '%' )
+ {
+ count += 1 ;
+ }
+ }
+ return count * sizeof (unsigned int ) ;
+}
+
+/*******************************************************************************
+ **
+ ** _AppendString
+ **
+ **
+ *******************************************************************************/
+static ssize_t
+_AppendString (
+ IN gcsDEBUGFS_Node* Node ,
+ IN gctCONST_STRING String ,
+ IN int Length
+ )
+{
+ int n ;
+
+ /* if the message is longer than the buffer, just take the beginning
+ * of it, in hopes that the reader (if any) will have time to read
+ * before we wrap around and obliterate it */
+ n = gcmkMIN ( Length , Node->size - 1 ) ;
+
+ gcmkLOCKSECTION(traceLock);
+
+ /* now copy it into the circular buffer and free our temp copy */
+ _WriteToNode ( Node , (caddr_t)String , n ) ;
+
+ gcmkUNLOCKSECTION(traceLock);
+
+ return n ;
+}
+
+/*******************************************************************************
+ **
+ ** _DebugFSPrint
+ **
+ **
+ *******************************************************************************/
+static ssize_t
+_DebugFSPrint (
+ IN unsigned int ArgumentSize ,
+ IN const char* Message ,
+ IN gctDBGARGS * Arguments
+
+ )
+{
+ char buffer[MAX_LINE_SIZE] ;
+ int len ;
+ ssize_t res=0;
+
+ len = vsnprintf ( buffer , sizeof (buffer ) , Message , *( va_list * ) Arguments ) ;
+
+ buffer[len] = '\0' ;
+
+ /* Add end-of-line if missing. */
+ if ( buffer[len - 1] != '\n' )
+ {
+ buffer[len ++] = '\n' ;
+ buffer[len] = '\0' ;
+ }
+
+ res = _AppendString ( gc_dbgfs.currentNode , buffer , len ) ;
+
+ wake_up_interruptible ( gcmkNODE_READQ ( gc_dbgfs.currentNode ) ) ; /* blocked in read*/
+
+ return res;
+}
+
+/*******************************************************************************
+ **
+ ** LINUX SYSTEM FUNCTIONS (START)
+ **
+ *******************************************************************************/
+static int
+_DebugFSOpen (
+ struct inode* inode,
+ struct file* filp
+ )
+{
+ filp->private_data = inode->i_private;
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** _DebugFSRead
+ **
+ *******************************************************************************/
+static ssize_t
+_DebugFSRead (
+ struct file *file ,
+ char __user * buffer ,
+ size_t length ,
+ loff_t * offset
+ )
+{
+ int retval ;
+ caddr_t data_to_return ;
+ gcsDEBUGFS_Node* node = file->private_data;
+
+ if (node == NULL)
+ {
+ printk ( "debugfs_read: record not found\n" ) ;
+ return - EIO ;
+ }
+
+ gcmkLOCKSECTION(traceLock);
+
+ /* wait until there's data available (unless we do nonblocking reads) */
+ while (!gcmkNODE_QLEN(node))
+ {
+ gcmkUNLOCKSECTION(traceLock);
+
+ if ( file->f_flags & O_NONBLOCK )
+ {
+ return - EAGAIN ;
+ }
+
+ if ( wait_event_interruptible ( ( *( gcmkNODE_READQ ( node ) ) ) , ( *offset < gcmkNODE_FIRST_EMPTY_BYTE ( node ) ) ) )
+ {
+ return - ERESTARTSYS ; /* signal: tell the fs layer to handle it */
+ }
+
+ gcmkLOCKSECTION(traceLock);
+ }
+
+ data_to_return = _ReadFromNode ( node , &length , offset ) ;
+
+ gcmkUNLOCKSECTION(traceLock);
+
+ if ( data_to_return == NULL )
+ {
+ retval = 0 ;
+ goto unlock ;
+ }
+ if ( copy_to_user ( buffer , data_to_return , length ) > 0 )
+ {
+ retval = - EFAULT ;
+ }
+ else
+ {
+ retval = length ;
+ }
+unlock:
+
+ wake_up_interruptible ( gcmkNODE_WRITEQ ( node ) ) ;
+ return retval ;
+}
+
+/*******************************************************************************
+ **
+ **_DebugFSWrite
+ **
+ *******************************************************************************/
+static ssize_t
+_DebugFSWrite (
+ struct file *file ,
+ const char __user * buffer ,
+ size_t length ,
+ loff_t * offset
+ )
+{
+ caddr_t message = NULL ;
+ int n ;
+ gcsDEBUGFS_Node* node = file->private_data;
+
+ /* get the metadata about this log */
+ if (node == NULL)
+ {
+ return - EIO ;
+ }
+
+ if ( down_interruptible ( gcmkNODE_SEM ( node ) ) )
+ {
+ return - ERESTARTSYS ;
+ }
+
+ /* if the message is longer than the buffer, just take the beginning
+ * of it, in hopes that the reader (if any) will have time to read
+ * before we wrap around and obliterate it */
+ n = gcmkMIN ( length , node->size - 1 ) ;
+
+ /* make sure we have the memory for it */
+ if ( ( message = kmalloc ( n , GFP_KERNEL ) ) == NULL )
+ {
+ up ( gcmkNODE_SEM ( node ) ) ;
+ return - ENOMEM ;
+ }
+
+
+ /* copy into our temp buffer */
+ if ( copy_from_user ( message , buffer , n ) > 0 )
+ {
+ up ( gcmkNODE_SEM ( node ) ) ;
+ kfree ( message ) ;
+ return - EFAULT ;
+ }
+
+ /* now copy it into the circular buffer and free our temp copy */
+ _WriteToNode ( node , message , n ) ;
+
+ kfree ( message ) ;
+ up ( gcmkNODE_SEM ( node ) ) ;
+
+ /* wake up any readers that might be waiting for the data. we call
+ * schedule in the vague hope that a reader will run before the
+ * writer's next write, to avoid losing data. */
+ wake_up_interruptible ( gcmkNODE_READQ ( node ) ) ;
+
+ return n ;
+}
+
+/*******************************************************************************
+ **
+ ** File Operations Table
+ **
+ *******************************************************************************/
+static const struct file_operations debugfs_operations = {
+ .owner = THIS_MODULE ,
+ .open = _DebugFSOpen ,
+ .read = _DebugFSRead ,
+ .write = _DebugFSWrite ,
+} ;
+
+/*******************************************************************************
+ **
+ ** INTERFACE FUNCTIONS (START)
+ **
+ *******************************************************************************/
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_IsEnabled
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+
+
+gctINT
+gckDEBUGFS_IsEnabled ( void )
+{
+ return gc_dbgfs.isInited ;
+}
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_Initialize
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+
+gctINT
+gckDEBUGFS_Initialize ( void )
+{
+ if ( ! gc_dbgfs.isInited )
+ {
+ gc_dbgfs.linkedlist = gcvNULL ;
+ gc_dbgfs.currentNode = gcvNULL ;
+ gc_dbgfs.isInited = 1 ;
+ }
+ return gc_dbgfs.isInited ;
+}
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_Terminate
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+
+gctINT
+gckDEBUGFS_Terminate ( void )
+{
+ gcsDEBUGFS_Node * next = gcvNULL ;
+ gcsDEBUGFS_Node * temp = gcvNULL ;
+ if ( gc_dbgfs.isInited )
+ {
+ temp = gc_dbgfs.linkedlist ;
+ while ( temp != gcvNULL )
+ {
+ next = temp->next ;
+ gckDEBUGFS_FreeNode ( temp ) ;
+ kfree ( temp ) ;
+ temp = next ;
+ }
+ gc_dbgfs.isInited = 0 ;
+ }
+ return 0 ;
+}
+
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_CreateNode
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ ** gckDEBUGFS_FreeNode * Device
+ ** Pointer to a variable receiving the gcsDEBUGFS_Node object pointer on
+ ** success.
+ *********************************************************************************/
+
+gctINT
+gckDEBUGFS_CreateNode (
+ IN gctPOINTER Device,
+ IN gctINT SizeInKB ,
+ IN struct dentry * Root ,
+ IN gctCONST_STRING NodeName ,
+ OUT gcsDEBUGFS_Node **Node
+ )
+{
+ gcsDEBUGFS_Node*node ;
+ /* allocate space for our metadata and initialize it */
+ if ( ( node = kmalloc ( sizeof (gcsDEBUGFS_Node ) , GFP_KERNEL ) ) == NULL )
+ goto struct_malloc_failed ;
+
+ /*Zero it out*/
+ memset ( node , 0 , sizeof (gcsDEBUGFS_Node ) ) ;
+
+ /*Init the sync primitives*/
+#if defined(DECLARE_WAIT_QUEUE_HEAD)
+ init_waitqueue_head ( gcmkNODE_READQ ( node ) ) ;
+#else
+ init_waitqueue ( gcmkNODE_READQ ( node ) ) ;
+#endif
+
+#if defined(DECLARE_WAIT_QUEUE_HEAD)
+ init_waitqueue_head ( gcmkNODE_WRITEQ ( node ) ) ;
+#else
+ init_waitqueue ( gcmkNODE_WRITEQ ( node ) ) ;
+#endif
+ sema_init ( gcmkNODE_SEM ( node ) , 1 ) ;
+ /*End the sync primitives*/
+
+ /*creating the debug file system*/
+ node->parent = Root;
+
+ if (SizeInKB)
+ {
+ /* figure out how much of a buffer this should be and allocate the buffer */
+ node->size = 1024 * SizeInKB ;
+ if ( ( node->data = ( char * ) vmalloc ( sizeof (char ) * node->size ) ) == NULL )
+ goto data_malloc_failed ;
+
+ node->tempSize = 0;
+ node->temp = NULL;
+
+ /*creating the file*/
+ node->filen = debugfs_create_file(NodeName, S_IRUGO|S_IWUSR, node->parent, node,
+ &debugfs_operations);
+ }
+
+ /* add it to our linked list */
+ node->next = gc_dbgfs.linkedlist ;
+ gc_dbgfs.linkedlist = node ;
+
+
+ /* pass the struct back */
+ *Node = node ;
+ return 0 ;
+
+
+data_malloc_failed:
+ kfree ( node ) ;
+struct_malloc_failed:
+ return - ENOMEM ;
+}
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_FreeNode
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+void
+gckDEBUGFS_FreeNode (
+ IN gcsDEBUGFS_Node * Node
+ )
+{
+
+ gcsDEBUGFS_Node **ptr ;
+
+ if ( Node == NULL )
+ {
+ printk ( "null passed to free_vinfo\n" ) ;
+ return ;
+ }
+
+ down ( gcmkNODE_SEM ( Node ) ) ;
+ /*free data*/
+ vfree ( Node->data ) ;
+
+ kfree(Node->temp);
+
+ /*Close Debug fs*/
+ if ( Node->filen )
+ {
+ debugfs_remove ( Node->filen ) ;
+ }
+
+ /* now delete the node from the linked list */
+ ptr = & ( gc_dbgfs.linkedlist ) ;
+ while ( *ptr != Node )
+ {
+ if ( ! *ptr )
+ {
+ printk ( "corrupt info list!\n" ) ;
+ break ;
+ }
+ else
+ ptr = & ( ( **ptr ).next ) ;
+ }
+ *ptr = Node->next ;
+ up ( gcmkNODE_SEM ( Node ) ) ;
+}
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_SetCurrentNode
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+void
+gckDEBUGFS_SetCurrentNode (
+ IN gcsDEBUGFS_Node * Node
+ )
+{
+ gc_dbgfs.currentNode = Node ;
+}
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_GetCurrentNode
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+void
+gckDEBUGFS_GetCurrentNode (
+ OUT gcsDEBUGFS_Node ** Node
+ )
+{
+ *Node = gc_dbgfs.currentNode ;
+}
+
+/*******************************************************************************
+ **
+ ** gckDEBUGFS_Print
+ **
+ **
+ ** INPUT:
+ **
+ ** OUTPUT:
+ **
+ *******************************************************************************/
+ssize_t
+gckDEBUGFS_Print (
+ IN gctCONST_STRING Message ,
+ ...
+ )
+{
+ ssize_t _debugfs_res;
+ gcmkDEBUGFS_PRINT ( _GetArgumentSize ( Message ) , Message ) ;
+ return _debugfs_res;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h
new file mode 100644
index 000000000000..1165b3163495
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debugfs.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include <stdarg.h>
+
+#ifndef __gc_hal_kernel_debugfs_h_
+#define __gc_hal_kernel_debugfs_h_
+
+ #define MAX_LINE_SIZE 768 /* Max bytes for a line of debug info */
+
+
+ typedef struct _gcsDEBUGFS_Node gcsDEBUGFS_Node;
+
+typedef struct _gcsDEBUGFS_DIR *gckDEBUGFS_DIR;
+typedef struct _gcsDEBUGFS_DIR
+{
+ struct dentry * root;
+ struct list_head nodeList;
+}
+gcsDEBUGFS_DIR;
+
+typedef struct _gcsINFO
+{
+ const char * name;
+ int (*show)(struct seq_file*, void*);
+ int (*write)(const char __user *buf, size_t count, void*);
+}
+gcsINFO;
+
+typedef struct _gcsINFO_NODE
+{
+ gcsINFO * info;
+ gctPOINTER device;
+ struct dentry * entry;
+ struct list_head head;
+}
+gcsINFO_NODE;
+
+gceSTATUS
+gckDEBUGFS_DIR_Init(
+ IN gckDEBUGFS_DIR Dir,
+ IN struct dentry *root,
+ IN gctCONST_STRING Name
+ );
+
+gceSTATUS
+gckDEBUGFS_DIR_CreateFiles(
+ IN gckDEBUGFS_DIR Dir,
+ IN gcsINFO * List,
+ IN int count,
+ IN gctPOINTER Data
+ );
+
+gceSTATUS
+gckDEBUGFS_DIR_RemoveFiles(
+ IN gckDEBUGFS_DIR Dir,
+ IN gcsINFO * List,
+ IN int count
+ );
+
+void
+gckDEBUGFS_DIR_Deinit(
+ IN gckDEBUGFS_DIR Dir
+ );
+
+/*******************************************************************************
+ **
+ ** System Related
+ **
+ *******************************************************************************/
+
+gctINT gckDEBUGFS_IsEnabled(void);
+
+gctINT gckDEBUGFS_Initialize(void);
+
+gctINT gckDEBUGFS_Terminate(void);
+
+
+/*******************************************************************************
+ **
+ ** Node Related
+ **
+ *******************************************************************************/
+
+gctINT
+gckDEBUGFS_CreateNode(
+ IN gctPOINTER Device,
+ IN gctINT SizeInKB,
+ IN struct dentry * Root,
+ IN gctCONST_STRING NodeName,
+ OUT gcsDEBUGFS_Node **Node
+ );
+
+void gckDEBUGFS_FreeNode(
+ IN gcsDEBUGFS_Node * Node
+ );
+
+
+
+void gckDEBUGFS_SetCurrentNode(
+ IN gcsDEBUGFS_Node * Node
+ );
+
+
+
+void gckDEBUGFS_GetCurrentNode(
+ OUT gcsDEBUGFS_Node ** Node
+ );
+
+
+ssize_t gckDEBUGFS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#endif
+
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
new file mode 100644
index 000000000000..6ab753f29f71
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
@@ -0,0 +1,2305 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <linux/slab.h>
+
+#define _GC_OBJ_ZONE gcvZONE_DEVICE
+
+#define DEBUG_FILE "galcore_trace"
+#define PARENT_FILE "gpu"
+
+#define gcdDEBUG_FS_WARN "Experimental debug entry, may be removed in future release, do NOT rely on it!\n"
+
+#ifdef FLAREON
+ static struct dove_gpio_irq_handler gc500_handle;
+#endif
+
+static gckGALDEVICE galDevice;
+
+extern gcTA globalTA[16];
+
+/******************************************************************************\
+******************************** Debugfs Support *******************************
+\******************************************************************************/
+
+/******************************************************************************\
+***************************** DEBUG SHOW FUNCTIONS *****************************
+\******************************************************************************/
+
+int gc_info_show(struct seq_file* m, void* data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ int i = 0;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 productID = 0;
+ gctUINT32 ecoID = 0;
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->irqLines[i] != -1)
+ {
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ chipModel = device->kernels[i]->vg->hardware->chipModel;
+ chipRevision = device->kernels[i]->vg->hardware->chipRevision;
+ }
+ else
+#endif
+ {
+ chipModel = device->kernels[i]->hardware->identity.chipModel;
+ chipRevision = device->kernels[i]->hardware->identity.chipRevision;
+ productID = device->kernels[i]->hardware->identity.productID;
+ ecoID = device->kernels[i]->hardware->identity.ecoID;
+ }
+
+ seq_printf(m, "gpu : %d\n", i);
+ seq_printf(m, "model : %4x\n", chipModel);
+ seq_printf(m, "revision : %4x\n", chipRevision);
+ seq_printf(m, "product : %4x\n", productID);
+ seq_printf(m, "eco : %4x\n", ecoID);
+ seq_printf(m, "\n");
+ }
+ }
+
+ return 0;
+}
+
+int gc_clients_show(struct seq_file* m, void* data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+
+ gckKERNEL kernel = _GetValidKernel(device);
+
+ gcsDATABASE_PTR database;
+ gctINT i, pid;
+ char name[24];
+
+ seq_printf(m, "%-8s%s\n", "PID", "NAME");
+ seq_printf(m, "------------------------\n");
+
+ /* Acquire the database mutex. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(kernel->os, kernel->db->dbMutex, gcvINFINITE));
+
+ /* Walk the databases. */
+ for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
+ {
+ for (database = kernel->db->db[i];
+ database != gcvNULL;
+ database = database->next)
+ {
+ pid = database->processID;
+
+ gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
+
+ seq_printf(m, "%-8d%s\n", pid, name);
+ }
+ }
+
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(kernel->os, kernel->db->dbMutex));
+
+ /* Success. */
+ return 0;
+}
+
+static void
+_CounterAdd(
+ gcsDATABASE_COUNTERS * Dest,
+ gcsDATABASE_COUNTERS * Src
+ )
+{
+ Dest->bytes += Src->bytes;
+ Dest->maxBytes += Src->maxBytes;
+ Dest->totalBytes += Src->totalBytes;
+}
+
+static void
+_CounterPrint(
+ gcsDATABASE_COUNTERS * Counter,
+ gctCONST_STRING Name,
+ struct seq_file* m
+ )
+{
+ seq_printf(m, " %s:\n", Name);
+ seq_printf(m, " Used : %10llu B\n", Counter->bytes);
+}
+
+int gc_meminfo_show(struct seq_file* m, void* data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ gckKERNEL kernel = _GetValidKernel(device);
+ gckVIDMEM memory;
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gctUINT32 i;
+
+ gctUINT32 free = 0, used = 0, total = 0;
+
+ gcsDATABASE_COUNTERS contiguousCounter = {0, 0, 0};
+ gcsDATABASE_COUNTERS virtualCounter = {0, 0, 0};
+ gcsDATABASE_COUNTERS nonPagedCounter = {0, 0, 0};
+
+ status = gckKERNEL_GetVideoMemoryPool(kernel, gcvPOOL_SYSTEM, &memory);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
+
+ free = memory->freeBytes;
+ used = memory->bytes - memory->freeBytes;
+ total = memory->bytes;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+ }
+
+ seq_printf(m, "VIDEO MEMORY:\n");
+ seq_printf(m, " gcvPOOL_SYSTEM:\n");
+ seq_printf(m, " Free : %10u B\n", free);
+ seq_printf(m, " Used : %10u B\n", used);
+ seq_printf(m, " Total : %10u B\n", total);
+
+ /* Acquire the database mutex. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(kernel->os, kernel->db->dbMutex, gcvINFINITE));
+
+ /* Walk the databases. */
+ for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
+ {
+ for (database = kernel->db->db[i];
+ database != gcvNULL;
+ database = database->next)
+ {
+ gcsDATABASE_COUNTERS * counter = &database->vidMemPool[gcvPOOL_CONTIGUOUS];
+ _CounterAdd(&contiguousCounter, counter);
+
+ counter = &database->vidMemPool[gcvPOOL_VIRTUAL];
+ _CounterAdd(&virtualCounter, counter);
+
+
+ counter = &database->nonPaged;
+ _CounterAdd(&nonPagedCounter, counter);
+ }
+ }
+
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(kernel->os, kernel->db->dbMutex));
+
+ _CounterPrint(&contiguousCounter, "gcvPOOL_CONTIGUOUS", m);
+ _CounterPrint(&virtualCounter, "gcvPOOL_VIRTUAL", m);
+
+ seq_printf(m, "\n");
+
+ seq_printf(m, "NON PAGED MEMORY:\n");
+ seq_printf(m, " Used : %10llu B\n", nonPagedCounter.bytes);
+
+ return 0;
+}
+
+static int
+_ShowRecord(
+ IN struct seq_file *File,
+ IN gcsDATABASE_RECORD_PTR Record
+ )
+{
+ static const char * recordTypes[gcvDB_NUM_TYPES] = {
+ "Unknown",
+ "VideoMemory",
+ "CommandBuffer",
+ "NonPaged",
+ "Contiguous",
+ "Signal",
+ "VidMemLock",
+ "Context",
+ "Idel",
+ "MapMemory",
+ "MapUserMemory",
+ "ShBuf",
+ };
+
+ seq_printf(File, "%-14s %3d %16p %16zu %16zu\n",
+ recordTypes[Record->type],
+ Record->kernel->core,
+ Record->data,
+ (size_t) Record->physical,
+ Record->bytes
+ );
+
+ return 0;
+}
+
+static int
+_ShowRecords(
+ IN struct seq_file *File,
+ IN gcsDATABASE_PTR Database
+ )
+{
+ gctUINT i;
+
+ seq_printf(File, "Records:\n");
+
+ seq_printf(File, "%14s %3s %16s %16s %16s\n",
+ "Type", "GPU", "Data/Node", "Physical/Node", "Bytes");
+
+ for (i = 0; i < gcmCOUNTOF(Database->list); i++)
+ {
+ gcsDATABASE_RECORD_PTR record = Database->list[i];
+
+ while (record != NULL)
+ {
+ _ShowRecord(File, record);
+ record = record->next;
+ }
+ }
+
+ return 0;
+}
+
+static void
+_ShowCounters(
+ struct seq_file *File,
+ gcsDATABASE_PTR Database
+ )
+{
+ gctUINT i = 0;
+
+ static const char * surfaceTypes[gcvSURF_NUM_TYPES] = {
+ "Unknown",
+ "Index",
+ "Vertex",
+ "Texture",
+ "RenderTarget",
+ "Depth",
+ "Bitmap",
+ "TileStatus",
+ "Image",
+ "Mask",
+ "Scissor",
+ "HZ",
+ "ICache",
+ "TxDesc",
+ "Fence",
+ "TFBHeader",
+ };
+
+ static const char * poolTypes[gcvPOOL_NUMBER_OF_POOLS] = {
+ "Unknown",
+ "Default",
+ "Local",
+ "Internal",
+ "External",
+ "Unified",
+ "System",
+ "Virtual",
+ "User",
+ "Contiguous",
+ };
+
+ static const char * otherCounterNames[] = {
+ "AllocNonPaged",
+ "AllocContiguous",
+ "MapUserMemory",
+ "MapMemory",
+ };
+
+ gcsDATABASE_COUNTERS * otherCounters[] = {
+ &Database->nonPaged,
+ &Database->contiguous,
+ &Database->mapUserMemory,
+ &Database->mapMemory,
+ };
+
+ seq_printf(File, "%-16s %16s %16s %16s\n", "", "Current", "Maximum", "Total");
+
+ /* Print surface type counters. */
+ seq_printf(File, "%-16s %16lld %16lld %16lld\n",
+ "All-Types",
+ Database->vidMem.bytes,
+ Database->vidMem.maxBytes,
+ Database->vidMem.totalBytes);
+
+ for (i = 1; i < gcvSURF_NUM_TYPES; i++)
+ {
+ seq_printf(File, "%-16s %16lld %16lld %16lld\n",
+ surfaceTypes[i],
+ Database->vidMemType[i].bytes,
+ Database->vidMemType[i].maxBytes,
+ Database->vidMemType[i].totalBytes);
+ }
+ seq_puts(File, "\n");
+
+ /* Print surface pool counters. */
+ seq_printf(File, "%-16s %16lld %16lld %16lld\n",
+ "All-Pools",
+ Database->vidMem.bytes,
+ Database->vidMem.maxBytes,
+ Database->vidMem.totalBytes);
+
+ for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
+ {
+ seq_printf(File, "%-16s %16lld %16lld %16lld\n",
+ poolTypes[i],
+ Database->vidMemPool[i].bytes,
+ Database->vidMemPool[i].maxBytes,
+ Database->vidMemPool[i].totalBytes);
+ }
+ seq_puts(File, "\n");
+
+ /* Print other counters. */
+ for (i = 0; i < gcmCOUNTOF(otherCounterNames); i++)
+ {
+ seq_printf(File, "%-16s %16lld %16lld %16lld\n",
+ otherCounterNames[i],
+ otherCounters[i]->bytes,
+ otherCounters[i]->maxBytes,
+ otherCounters[i]->totalBytes);
+ }
+ seq_puts(File, "\n");
+}
+
+static void
+_ShowProcess(
+ IN struct seq_file *File,
+ IN gcsDATABASE_PTR Database
+ )
+{
+ gctINT pid;
+ char name[24];
+
+ /* Process ID and name */
+ pid = Database->processID;
+ gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
+
+ seq_printf(File, "--------------------------------------------------------------------------------\n");
+ seq_printf(File, "Process: %-8d %s\n", pid, name);
+
+ /* Detailed records */
+ _ShowRecords(File, Database);
+
+ seq_printf(File, "Counters:\n");
+
+ _ShowCounters(File, Database);
+}
+
+static void
+_ShowProcesses(
+ IN struct seq_file * File,
+ IN gckKERNEL Kernel
+ )
+{
+ gcsDATABASE_PTR database;
+ gctINT i;
+ static gctUINT64 idleTime = 0;
+
+ /* Acquire the database mutex. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+
+ if (Kernel->db->idleTime)
+ {
+ /* Record idle time if DB upated. */
+ idleTime = Kernel->db->idleTime;
+ Kernel->db->idleTime = 0;
+ }
+
+ /* Idle time since last call */
+ seq_printf(File, "GPU Idle: %llu ns\n", idleTime);
+
+ /* Walk the databases. */
+ for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
+ {
+ for (database = Kernel->db->db[i];
+ database != gcvNULL;
+ database = database->next)
+ {
+ _ShowProcess(File, database);
+ }
+ }
+
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+}
+
+static int
+gc_db_show(struct seq_file *m, void *data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ gckKERNEL kernel = _GetValidKernel(device);
+ _ShowProcesses(m, kernel);
+ return 0 ;
+}
+
+static int
+gc_version_show(struct seq_file *m, void *data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ gcsPLATFORM * platform = device->platform;
+ gctCONST_STRING name;
+
+ seq_printf(m, "%s built at %s\n", gcvVERSION_STRING, HOST);
+
+ if (platform->ops->name)
+ {
+ platform->ops->name(platform, &name);
+ seq_printf(m, "Platform path: %s\n", name);
+ }
+ else
+ {
+ seq_printf(m, "Code path: %s\n", __FILE__);
+ }
+
+ return 0 ;
+}
+
+/*******************************************************************************
+**
+** Show PM state timer.
+**
+** Entry is called as 'idle' for compatible reason, it shows more information
+** than idle actually.
+**
+** Start: Start time of this counting period.
+** End: End time of this counting peroid.
+** On: Time GPU stays in gcvPOWER_0N.
+** Off: Time GPU stays in gcvPOWER_0FF.
+** Idle: Time GPU stays in gcvPOWER_IDLE.
+** Suspend: Time GPU stays in gcvPOWER_SUSPEND.
+*/
+static int
+gc_idle_show(struct seq_file *m, void *data)
+{
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ gckKERNEL kernel = _GetValidKernel(device);
+
+ gctUINT64 start;
+ gctUINT64 end;
+ gctUINT64 on;
+ gctUINT64 off;
+ gctUINT64 idle;
+ gctUINT64 suspend;
+
+ gckHARDWARE_QueryStateTimer(kernel->hardware, &start, &end, &on, &off, &idle, &suspend);
+
+ /* Idle time since last call */
+ seq_printf(m, "Start: %llu ns\n", start);
+ seq_printf(m, "End: %llu ns\n", end);
+ seq_printf(m, "On: %llu ns\n", on);
+ seq_printf(m, "Off: %llu ns\n", off);
+ seq_printf(m, "Idle: %llu ns\n", idle);
+ seq_printf(m, "Suspend: %llu ns\n", suspend);
+
+ return 0 ;
+}
+
+extern void
+_DumpState(
+ IN gckKERNEL Kernel
+ );
+
+/*******************************************************************************
+**
+** Show PM state timer.
+**
+** Entry is called as 'idle' for compatible reason, it shows more information
+** than idle actually.
+**
+** Start: Start time of this counting period.
+** End: End time of this counting peroid.
+** On: Time GPU stays in gcvPOWER_0N.
+** Off: Time GPU stays in gcvPOWER_0FF.
+** Idle: Time GPU stays in gcvPOWER_IDLE.
+** Suspend: Time GPU stays in gcvPOWER_SUSPEND.
+*/
+
+static int dumpCore = 0;
+
+static int
+gc_dump_trigger_show(struct seq_file *m, void *data)
+{
+#if gcdENABLE_3D || gcdENABLE_2D
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ gckKERNEL kernel = gcvNULL;
+
+ if (dumpCore >= gcvCORE_MAJOR && dumpCore < gcvCORE_COUNT)
+ {
+ kernel = device->kernels[dumpCore];
+ }
+#endif
+
+ seq_printf(m, gcdDEBUG_FS_WARN);
+
+#if gcdENABLE_3D || gcdENABLE_2D
+ seq_printf(m, "Get dump from /proc/kmsg or /sys/kernel/debug/gc/galcore_trace\n");
+
+ if (kernel && kernel->hardware->powerManagement == gcvFALSE)
+ {
+ _DumpState(kernel);
+ }
+#endif
+
+ return 0;
+}
+
+static int dumpProcess = 0;
+
+
+static int gc_vidmem_show(struct seq_file *m, void *unused)
+{
+ gceSTATUS status;
+ gcsDATABASE_PTR database;
+ gcsINFO_NODE *node = m->private;
+ gckGALDEVICE device = node->device;
+ char name[64];
+ int i;
+
+ gckKERNEL kernel = _GetValidKernel(device);
+
+ if (dumpProcess == 0)
+ {
+ /* Acquire the database mutex. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(kernel->os, kernel->db->dbMutex, gcvINFINITE));
+
+ for (i = 0; i < gcmCOUNTOF(kernel->db->db); i++)
+ {
+ for (database = kernel->db->db[i];
+ database != gcvNULL;
+ database = database->next)
+ {
+ gckOS_GetProcessNameByPid(database->processID, gcmSIZEOF(name), name);
+ seq_printf(m, "VidMem Usage (Process %d: %s):\n", database->processID, name);
+ _ShowCounters(m, database);
+ seq_puts(m, "\n");
+ }
+ }
+
+ /* Release the database mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(kernel->os, kernel->db->dbMutex));
+ }
+ else
+ {
+ /* Find the database. */
+ status = gckKERNEL_FindDatabase(kernel, dumpProcess, gcvFALSE, &database);
+
+ if (gcmIS_ERROR(status))
+ {
+ seq_printf(m, "ERROR: process %d not found\n", dumpProcess);
+ return 0;
+ }
+
+ gckOS_GetProcessNameByPid(dumpProcess, gcmSIZEOF(name), name);
+ seq_printf(m, "VidMem Usage (Process %d: %s):\n", dumpProcess, name);
+ _ShowCounters(m, database);
+ }
+
+ return 0;
+}
+
+static int gc_vidmem_write(const char __user *buf, size_t count, void* data)
+{
+ dumpProcess = simple_strtol(buf, NULL, 0);
+ return count;
+}
+
+static int gc_dump_trigger_write(const char __user *buf, size_t count, void* data)
+{
+ dumpCore = simple_strtol(buf, NULL, 0);
+ return count;
+}
+
+static gcsINFO InfoList[] =
+{
+ {"info", gc_info_show},
+ {"clients", gc_clients_show},
+ {"meminfo", gc_meminfo_show},
+ {"idle", gc_idle_show},
+ {"database", gc_db_show},
+ {"version", gc_version_show},
+ {"vidmem", gc_vidmem_show, gc_vidmem_write},
+ {"dump_trigger", gc_dump_trigger_show, gc_dump_trigger_write},
+};
+
+static gceSTATUS
+_DebugfsInit(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+
+ gckDEBUGFS_DIR dir = &Device->debugfsDir;
+
+ gcmkONERROR(gckDEBUGFS_DIR_Init(dir, gcvNULL, "gc"));
+
+ gcmkONERROR(gckDEBUGFS_DIR_CreateFiles(dir, InfoList, gcmCOUNTOF(InfoList), Device));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+static void
+_DebugfsCleanup(
+ IN gckGALDEVICE Device
+ )
+{
+ gckDEBUGFS_DIR dir = &Device->debugfsDir;
+
+ if (Device->debugfsDir.root)
+ {
+ gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(dir, InfoList, gcmCOUNTOF(InfoList)));
+
+ gckDEBUGFS_DIR_Deinit(dir);
+ }
+}
+
+
+/******************************************************************************\
+*************************** Memory Allocation Wrappers *************************
+\******************************************************************************/
+
+static gceSTATUS
+_AllocateMemory(
+ IN gckGALDEVICE Device,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPHYS_ADDR *Physical,
+ OUT gctUINT32 *PhysAddr
+ )
+{
+ gceSTATUS status;
+ gctPHYS_ADDR_T physAddr;
+
+ gcmkHEADER_ARG("Device=0x%x Bytes=%lu", Device, Bytes);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
+
+ gcmkONERROR(gckOS_AllocateContiguous(
+ Device->os, gcvFALSE, &Bytes, Physical, Logical
+ ));
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(
+ Device->os, *Logical, &physAddr
+ ));
+
+ gcmkSAFECASTPHYSADDRT(*PhysAddr, physAddr);
+
+ /* Success. */
+ gcmkFOOTER_ARG(
+ "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
+ *Logical, *Physical, *PhysAddr
+ );
+
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_FreeMemory(
+ IN gckGALDEVICE Device,
+ IN gctPOINTER Logical,
+ IN gctPHYS_ADDR Physical)
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
+ Device, Logical, Physical);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ status = gckOS_FreeContiguous(
+ Device->os, Physical, Logical,
+ ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
+ );
+
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_SetupVidMem(
+ IN gckGALDEVICE Device,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gcsDEVICE_CONSTRUCT_ARGS * Args
+ )
+{
+ gceSTATUS status;
+ gctUINT32 physAddr = ~0U;
+ gckGALDEVICE device = Device;
+ struct resource* mem_region;
+
+ /* set up the contiguous memory */
+ device->contiguousSize = ContiguousSize;
+
+ if (ContiguousSize > 0)
+ {
+ if (ContiguousBase == 0)
+ {
+ while (device->contiguousSize > 0)
+ {
+ /* Allocate contiguous memory. */
+ status = _AllocateMemory(
+ device,
+ device->contiguousSize,
+ &device->contiguousBase,
+ &device->contiguousPhysical,
+ &physAddr
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ status = gckVIDMEM_Construct(
+ device->os,
+ physAddr | device->systemMemoryBaseAddress,
+ device->contiguousSize,
+ 64,
+ BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ device->contiguousRequested = gcvTRUE;
+ device->requestedContiguousBase = physAddr;
+ break;
+ }
+
+ gcmkONERROR(_FreeMemory(
+ device,
+ device->contiguousBase,
+ device->contiguousPhysical
+ ));
+
+ device->contiguousBase = gcvNULL;
+ device->contiguousPhysical = gcvNULL;
+ }
+
+ if (device->contiguousSize <= (4 << 20))
+ {
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ device->contiguousSize -= (4 << 20);
+ }
+ }
+ }
+ else
+ {
+ /* Create the contiguous memory heap. */
+ status = gckVIDMEM_Construct(
+ device->os,
+ ContiguousBase | device->systemMemoryBaseAddress,
+ ContiguousSize,
+ 64, BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, disable contiguous memory pool. */
+ device->contiguousVidMem = gcvNULL;
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ if (Args->contiguousRequested == gcvFALSE)
+ {
+ mem_region = request_mem_region(
+ ContiguousBase, ContiguousSize, "galcore managed memory"
+ );
+
+ if (mem_region == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
+ __FUNCTION__, __LINE__,
+ ContiguousSize, ContiguousBase
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ device->requestedContiguousBase = ContiguousBase;
+ device->requestedContiguousSize = ContiguousSize;
+ device->contiguousRequested = Args->contiguousRequested;
+
+ device->contiguousPhysical = gcvNULL;
+ device->contiguousPhysicalName = 0;
+ device->contiguousSize = ContiguousSize;
+ device->contiguousMapped = gcvTRUE;
+ }
+ }
+ }
+
+ return gcvSTATUS_OK;
+OnError:
+ return status;
+}
+
+void
+_SetupRegisterPhysical(
+ IN gckGALDEVICE Device,
+ IN gcsDEVICE_CONSTRUCT_ARGS * Args
+ )
+{
+ gctINT *irqs = Args->irqs;
+ gctUINT *registerBases = Args->registerBases;
+ gctUINT *registerSizes = Args->registerSizes;
+
+ gctINT i = 0;
+
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ if (irqs[i] != -1)
+ {
+ Device->requestedRegisterMemBases[i] = registerBases[i];
+ Device->requestedRegisterMemSizes[i] = registerSizes[i];
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, _GC_OBJ_ZONE,
+ "Get register base %llx of core %d",
+ registerBases[i], i);
+ }
+ }
+}
+
+/******************************************************************************\
+******************************* Interrupt Handler ******************************
+\******************************************************************************/
+static irqreturn_t isrRoutine(int irq, void *ctxt)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+ gceCORE Core = (gceCORE) gcmPTR2INT32(ctxt);
+
+ device = galDevice;
+
+ /* Call kernel interrupt notification. */
+ status = gckKERNEL_Notify(device->kernels[Core], gcvNOTIFY_INTERRUPT, gcvTRUE);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ up(&device->semas[Core]);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int threadRoutine(void *ctxt)
+{
+ gckGALDEVICE device = galDevice;
+ gceCORE core = (gceCORE) gcmPTR2INT32(ctxt);
+ gctUINT i;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Starting isr Thread with extension=%p",
+ device);
+
+ if (core != gcvCORE_VG)
+ {
+ /* Make kernel update page table of this thread to include entry related to command buffer.*/
+ for (i = 0; i < gcdCOMMAND_QUEUES; i++)
+ {
+ gctUINT32 data = *(gctUINT32_PTR)device->kernels[core]->command->queues[i].logical;
+
+ data = 0;
+ }
+ }
+
+ for (;;)
+ {
+ static int down;
+
+ down = down_interruptible(&device->semas[core]);
+ if (down); /*To make gcc 4.6 happye*/
+
+ if (device->killThread == gcvTRUE)
+ {
+ /* The daemon exits. */
+ while (!kthread_should_stop())
+ {
+ gckOS_Delay(device->os, 1);
+ }
+
+ return 0;
+ }
+
+ gckKERNEL_Notify(device->kernels[core],
+ gcvNOTIFY_INTERRUPT,
+ gcvFALSE);
+ }
+}
+
+static irqreturn_t isrRoutineVG(int irq, void *ctxt)
+{
+#if gcdENABLE_VG
+ gceSTATUS status;
+ gckGALDEVICE device;
+
+ device = (gckGALDEVICE) ctxt;
+
+ /* Serve the interrupt. */
+ status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
+
+ /* Determine the return value. */
+ return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
+ ? IRQ_RETVAL(0)
+ : IRQ_RETVAL(1);
+#else
+ return IRQ_NONE;
+#endif
+}
+
+/******************************************************************************\
+******************************* gckGALDEVICE Code ******************************
+\******************************************************************************/
+
+static gceSTATUS
+_StartThread(
+ IN int (*ThreadRoutine)(void *data),
+ IN gceCORE Core
+ )
+{
+ gceSTATUS status;
+ gckGALDEVICE device = galDevice;
+ struct task_struct * task;
+
+ if (device->kernels[Core] != gcvNULL)
+ {
+ /* Start the kernel thread. */
+ task = kthread_run(ThreadRoutine, (void *)Core, "galcore deamon thread for core[%d]", Core);
+
+ if (IS_ERR(task))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not start the kernel thread.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ device->threadCtxts[Core] = task;
+ device->threadInitializeds[Core] = gcvTRUE;
+ }
+ else
+ {
+ device->threadInitializeds[Core] = gcvFALSE;
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Construct
+**
+** Constructor.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gckGALDEVICE * Device
+** Pointer to a variable receiving the gckGALDEVICE object pointer on
+** success.
+*/
+gceSTATUS
+gckGALDEVICE_Construct(
+ IN gctINT IrqLine,
+ IN gctUINT32 RegisterMemBase,
+ IN gctSIZE_T RegisterMemSize,
+ IN gctINT IrqLine2D,
+ IN gctUINT32 RegisterMemBase2D,
+ IN gctSIZE_T RegisterMemSize2D,
+ IN gctINT IrqLineVG,
+ IN gctUINT32 RegisterMemBaseVG,
+ IN gctSIZE_T RegisterMemSizeVG,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 PhysBaseAddr,
+ IN gctUINT32 PhysSize,
+ IN gctINT Signal,
+ IN gctUINT LogFileSize,
+ IN gctINT PowerManagement,
+ IN gctINT GpuProfiler,
+ IN gcsDEVICE_CONSTRUCT_ARGS * Args,
+ OUT gckGALDEVICE *Device
+ )
+{
+ gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
+ gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
+ gctUINT32 horizontalTileSize, verticalTileSize;
+ struct resource* mem_region;
+ gctUINT32 physical;
+ gckGALDEVICE device;
+ gceSTATUS status;
+ gctINT32 i;
+ gceHARDWARE_TYPE type;
+ gckKERNEL kernel = gcvNULL;
+
+ gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
+ "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
+ "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
+ "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
+ "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
+ IrqLine, RegisterMemBase, RegisterMemSize,
+ IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
+ IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
+ ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
+ PhysBaseAddr, PhysSize, Signal);
+
+#if !gcdENABLE_3D
+ IrqLine = -1;
+#endif
+
+#if !gcdENABLE_2D
+ IrqLine2D = -1;
+#endif
+ /* Allocate device structure. */
+ device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);
+ if (!device)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ memset(device, 0, sizeof(struct _gckGALDEVICE));
+
+ device->dbgNode = gcvNULL;
+
+ device->platform = Args->platform;
+
+ device->args = *Args;
+
+ /* set up the contiguous memory */
+ device->contiguousSize = ContiguousSize;
+
+ /* Clear irq lines. */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ device->irqLines[i] = -1;
+ }
+
+ gcmkONERROR(_DebugfsInit(device));
+
+ if (gckDEBUGFS_CreateNode(
+ device, LogFileSize, device->debugfsDir.root ,DEBUG_FILE, &(device->dbgNode)))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to create the debug file system %s/%s \n",
+ __FUNCTION__, __LINE__,
+ PARENT_FILE, DEBUG_FILE
+ );
+ }
+ else if (LogFileSize)
+ {
+ gckDEBUGFS_SetCurrentNode(device->dbgNode);
+ }
+
+ _SetupRegisterPhysical(device, Args);
+
+ if (IrqLine != -1)
+ {
+ device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase;
+ device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize;
+ }
+
+ if (IrqLine2D != -1)
+ {
+ device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D;
+ device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D;
+ }
+
+ if (IrqLineVG != -1)
+ {
+ device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG;
+ device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG;
+ }
+#if gcdDEC_ENABLE_AHB
+ {
+ device->requestedRegisterMemBases[gcvCORE_DEC] = Args->registerMemBaseDEC300;
+ device->requestedRegisterMemSizes[gcvCORE_DEC] = Args->registerMemSizeDEC300;
+ }
+#endif
+
+
+ for (i = gcvCORE_MAJOR; i < gcvCORE_COUNT; i++)
+ {
+ if (Args->irqs[i] != -1)
+ {
+ device->requestedRegisterMemBases[i] = Args->registerBases[i];
+ device->requestedRegisterMemSizes[i] = Args->registerSizes[i];
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DEVICE,
+ "%s(%d): Core = %d, RegiseterBase = %x",
+ __FUNCTION__, __LINE__,
+ i, Args->registerBases[i]
+ );
+ }
+ }
+
+ /* Initialize the ISR. */
+ device->irqLines[gcvCORE_MAJOR] = IrqLine;
+ device->irqLines[gcvCORE_2D] = IrqLine2D;
+ device->irqLines[gcvCORE_VG] = IrqLineVG;
+
+ for (i = gcvCORE_MAJOR; i < gcvCORE_COUNT; i++)
+ {
+ if (Args->irqs[i] != -1)
+ {
+ device->irqLines[i] = Args->irqs[i];
+ }
+ }
+
+ device->requestedContiguousBase = 0;
+ device->requestedContiguousSize = 0;
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ physical = device->requestedRegisterMemBases[i];
+
+ /* Set up register memory region. */
+ if ( physical != 0)
+ {
+
+ if ( Args->registerMemMapped )
+ {
+ device->registerBases[i] = Args->registerMemAddress;
+ device->requestedRegisterMemBases[i] = 0;
+
+ } else {
+
+ mem_region = request_mem_region(physical,
+ device->requestedRegisterMemSizes[i],
+ "galcore register region");
+
+ if (mem_region == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
+ __FUNCTION__, __LINE__,
+ physical, device->requestedRegisterMemSizes[i]
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ device->registerBases[i] = (gctPOINTER) ioremap_nocache(
+ physical, device->requestedRegisterMemSizes[i]);
+
+ if (device->registerBases[i] == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
+ __FUNCTION__, __LINE__,
+ physical, device->requestedRegisterMemSizes[i]
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ physical += device->requestedRegisterMemSizes[i];
+ }
+ }
+
+ /* Set the base address */
+ device->baseAddress = device->physBase = PhysBaseAddr;
+ device->physSize = PhysSize;
+
+ /* Construct the gckOS object. */
+ gcmkONERROR(gckOS_Construct(device, &device->os));
+
+ /* Construct the gckDEVICE object for os independent core management. */
+ gcmkONERROR(gckDEVICE_Construct(device->os, &device->device));
+
+ if (device->irqLines[gcvCORE_MAJOR] != -1)
+ {
+ gcmkONERROR(gctaOS_ConstructOS(device->os, &device->taos));
+ }
+
+ gcmkONERROR(_SetupVidMem(device, ContiguousBase, ContiguousSize, BankSize, Args));
+
+ if (device->irqLines[gcvCORE_MAJOR] != -1)
+ {
+ gcmkONERROR(gcTA_Construct(device->taos, gcvCORE_MAJOR, &globalTA[gcvCORE_MAJOR]));
+
+ gcmkONERROR(gckDEVICE_AddCore(device->device, gcvCORE_MAJOR, Args->chipIDs[gcvCORE_MAJOR], device, &device->kernels[gcvCORE_MAJOR]));
+
+ /* Setup the ISR manager. */
+ gcmkONERROR(gckHARDWARE_SetIsrManager(
+ device->kernels[gcvCORE_MAJOR]->hardware,
+ (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
+ (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
+ (gctPOINTER)gcvCORE_MAJOR
+ ));
+
+ gcmkONERROR(gckHARDWARE_SetFastClear(
+ device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
+ ));
+
+ gcmkONERROR(gckHARDWARE_SetPowerManagement(
+ device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
+ ));
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ gcmkONERROR(gckHARDWARE_SetMinFscaleValue(
+ device->kernels[gcvCORE_MAJOR]->hardware, Args->gpu3DMinClock
+ ));
+#endif
+
+ gcmkONERROR(gckHARDWARE_SetGpuProfiler(
+ device->kernels[gcvCORE_MAJOR]->hardware, GpuProfiler
+ ));
+ }
+ else
+ {
+ device->kernels[gcvCORE_MAJOR] = gcvNULL;
+ }
+
+ if (device->irqLines[gcvCORE_2D] != -1)
+ {
+ gcmkONERROR(gckDEVICE_AddCore(device->device, gcvCORE_2D, gcvCHIP_ID_DEFAULT, device, &device->kernels[gcvCORE_2D]));
+
+ /* Verify the hardware type */
+ gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));
+
+ if (type != gcvHARDWARE_2D)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Unexpected hardware type: %d\n",
+ __FUNCTION__, __LINE__,
+ type
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Setup the ISR manager. */
+ gcmkONERROR(gckHARDWARE_SetIsrManager(
+ device->kernels[gcvCORE_2D]->hardware,
+ (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
+ (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
+ (gctPOINTER)gcvCORE_2D
+ ));
+
+ gcmkONERROR(gckHARDWARE_SetPowerManagement(
+ device->kernels[gcvCORE_2D]->hardware, PowerManagement
+ ));
+
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ gcmkONERROR(gckHARDWARE_SetMinFscaleValue(
+ device->kernels[gcvCORE_2D]->hardware, 1
+ ));
+#endif
+ }
+ else
+ {
+ device->kernels[gcvCORE_2D] = gcvNULL;
+ }
+
+ if (device->irqLines[gcvCORE_VG] != -1)
+ {
+#if gcdENABLE_VG
+ gcmkONERROR(gckDEVICE_AddCore(device->device, gcvCORE_VG, gcvCHIP_ID_DEFAULT, device, &device->kernels[gcvCORE_VG]));
+
+ gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
+ device->kernels[gcvCORE_VG]->vg->hardware,
+ PowerManagement
+ ));
+#endif
+ }
+ else
+ {
+ device->kernels[gcvCORE_VG] = gcvNULL;
+ }
+
+ /* Add core for multiple core. */
+ for (i = gcvCORE_3D1; i <= gcvCORE_3D3; i++)
+ {
+ if (Args->irqs[i] != -1)
+ {
+ gcmkONERROR(gcTA_Construct(device->taos, (gceCORE)i, &globalTA[i]));
+ gckDEVICE_AddCore(device->device, i, Args->chipIDs[i], device, &device->kernels[i]);
+
+ gcmkONERROR(
+ gckHARDWARE_SetFastClear(device->kernels[i]->hardware,
+ FastClear,
+ Compression));
+
+ gcmkONERROR(gckHARDWARE_SetPowerManagement(
+ device->kernels[i]->hardware, PowerManagement
+ ));
+
+ gcmkONERROR(gckHARDWARE_SetGpuProfiler(
+ device->kernels[i]->hardware, GpuProfiler
+ ));
+ }
+ }
+
+ /* Initialize the kernel thread semaphores. */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
+ }
+
+ device->signal = Signal;
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->kernels[i] != gcvNULL) break;
+ }
+
+ if (i == gcdMAX_GPU_COUNT)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ /* Query the ceiling of the system memory. */
+ gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
+ device->kernels[i]->vg->hardware,
+ &device->systemMemorySize,
+ &device->systemMemoryBaseAddress
+ ));
+ /* query the amount of video memory */
+ gcmkONERROR(gckVGHARDWARE_QueryMemory(
+ device->kernels[i]->vg->hardware,
+ &device->internalSize, &internalBaseAddress, &internalAlignment,
+ &device->externalSize, &externalBaseAddress, &externalAlignment,
+ &horizontalTileSize, &verticalTileSize
+ ));
+ }
+ else
+#endif
+ {
+ /* Query the ceiling of the system memory. */
+ gcmkONERROR(gckHARDWARE_QuerySystemMemory(
+ device->kernels[i]->hardware,
+ &device->systemMemorySize,
+ &device->systemMemoryBaseAddress
+ ));
+
+ /* query the amount of video memory */
+ gcmkONERROR(gckHARDWARE_QueryMemory(
+ device->kernels[i]->hardware,
+ &device->internalSize, &internalBaseAddress, &internalAlignment,
+ &device->externalSize, &externalBaseAddress, &externalAlignment,
+ &horizontalTileSize, &verticalTileSize
+ ));
+ }
+
+
+ /* Grab the first availiable kernel */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->irqLines[i] != -1)
+ {
+ kernel = device->kernels[i];
+ break;
+ }
+ }
+
+ /* Set up the internal memory region. */
+ if (device->internalSize > 0)
+ {
+ status = gckVIDMEM_Construct(
+ device->os,
+ internalBaseAddress, device->internalSize, internalAlignment,
+ 0, &device->internalVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, disable internal heap. */
+ device->internalSize = 0;
+ }
+ else
+ {
+ /* Map internal memory. */
+ device->internalLogical
+ = (gctPOINTER) ioremap_nocache(physical, device->internalSize);
+
+ if (device->internalLogical == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
+ device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
+ physical += device->internalSize;
+ }
+ }
+
+ if (device->externalSize > 0)
+ {
+ /* create the external memory heap */
+ status = gckVIDMEM_Construct(
+ device->os,
+ externalBaseAddress, device->externalSize, externalAlignment,
+ 0, &device->externalVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, disable internal heap. */
+ device->externalSize = 0;
+ }
+ else
+ {
+ /* Map external memory. */
+ device->externalLogical
+ = (gctPOINTER) ioremap_nocache(physical, device->externalSize);
+
+ if (device->externalLogical == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
+ device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
+ physical += device->externalSize;
+ }
+ }
+
+ if (device->contiguousPhysical)
+ {
+ device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
+ }
+
+ /* Return pointer to the device. */
+ *Device = galDevice = device;
+
+ gcmkFOOTER_ARG("*Device=0x%x", * Device);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Destroy
+**
+** Class destructor.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Destroy(
+ gckGALDEVICE Device)
+{
+ gctINT i;
+ gckKERNEL kernel = gcvNULL;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ if (Device != gcvNULL)
+ {
+ /* Grab the first availiable kernel */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (Device->irqLines[i] != -1)
+ {
+ kernel = Device->kernels[i];
+ break;
+ }
+ }
+
+ if (Device->internalPhysicalName != 0)
+ {
+ gcmRELEASE_NAME(Device->internalPhysicalName);
+ Device->internalPhysicalName = 0;
+ }
+ if (Device->externalPhysicalName != 0)
+ {
+ gcmRELEASE_NAME(Device->externalPhysicalName);
+ Device->externalPhysicalName = 0;
+ }
+ if (Device->contiguousPhysicalName != 0)
+ {
+ gcmRELEASE_NAME(Device->contiguousPhysicalName);
+ Device->contiguousPhysicalName = 0;
+ }
+
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (Device->kernels[i] != gcvNULL)
+ {
+ Device->kernels[i] = gcvNULL;
+ }
+ }
+
+ if (Device->internalLogical != gcvNULL)
+ {
+ /* Unmap the internal memory. */
+ iounmap(Device->internalLogical);
+ Device->internalLogical = gcvNULL;
+ }
+
+ if (Device->internalVidMem != gcvNULL)
+ {
+ /* Destroy the internal heap. */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+ Device->internalVidMem = gcvNULL;
+ }
+
+ if (Device->externalLogical != gcvNULL)
+ {
+ /* Unmap the external memory. */
+ iounmap(Device->externalLogical);
+ Device->externalLogical = gcvNULL;
+ }
+
+ if (Device->externalVidMem != gcvNULL)
+ {
+ /* destroy the external heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+ Device->externalVidMem = gcvNULL;
+ }
+
+ if (Device->contiguousBase != gcvNULL)
+ {
+ if (Device->contiguousMapped == gcvFALSE)
+ {
+ gcmkVERIFY_OK(_FreeMemory(
+ Device,
+ Device->contiguousBase,
+ Device->contiguousPhysical
+ ));
+ }
+
+ Device->contiguousBase = gcvNULL;
+ Device->contiguousPhysical = gcvNULL;
+ }
+
+ if (Device->requestedContiguousBase != 0
+ && Device->contiguousRequested == gcvFALSE
+ )
+ {
+ release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
+ Device->requestedContiguousBase = 0;
+ Device->requestedContiguousSize = 0;
+ }
+
+ if (Device->contiguousVidMem != gcvNULL)
+ {
+ /* Destroy the contiguous heap. */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+ Device->contiguousVidMem = gcvNULL;
+ }
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (Device->registerBases[i] != gcvNULL)
+ {
+ /* Unmap register memory. */
+ if ( Device->requestedRegisterMemBases[i] != 0 )
+ iounmap(Device->registerBases[i]);
+
+ if (Device->requestedRegisterMemBases[i] != 0)
+ {
+ release_mem_region(Device->requestedRegisterMemBases[i],
+ Device->requestedRegisterMemSizes[i]);
+ }
+
+ Device->registerBases[i] = gcvNULL;
+ Device->requestedRegisterMemBases[i] = 0;
+ Device->requestedRegisterMemSizes[i] = 0;
+ }
+ }
+
+ if (Device->device)
+ {
+ gcmkVERIFY_OK(gckDEVICE_Destroy(Device->os, Device->device));
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (globalTA[i])
+ {
+ gcTA_Destroy(globalTA[i]);
+ globalTA[i] = gcvNULL;
+ }
+ }
+
+ Device->device = gcvNULL;
+ }
+
+ if (Device->taos)
+ {
+ gcmkVERIFY_OK(gctaOS_DestroyOS(Device->taos));
+ Device->taos = gcvNULL;
+ }
+
+ /* Destroy the gckOS object. */
+ if (Device->os != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_Destroy(Device->os));
+ Device->os = gcvNULL;
+ }
+
+ if (Device->dbgNode)
+ {
+ gckDEBUGFS_FreeNode(Device->dbgNode);
+
+ if(Device->dbgNode != gcvNULL)
+ {
+ kfree(Device->dbgNode);
+ Device->dbgNode = gcvNULL;
+ }
+ }
+
+ _DebugfsCleanup(Device);
+
+ /* Free the device. */
+ kfree(Device);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Setup_ISR
+**
+** Start the ISR routine.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Setup successfully.
+** gcvSTATUS_GENERIC_IO
+** Setup failed.
+*/
+gceSTATUS
+gckGALDEVICE_Setup_ISR(
+ IN gceCORE Core
+ )
+{
+ gceSTATUS status;
+ gctINT ret = 0;
+ gckGALDEVICE Device = galDevice;
+
+ gcmkHEADER_ARG("Device=0x%x Core=%d", Device, Core);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ if (Device->irqLines[Core] < 0)
+ {
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+ gc500_handle.dev_name = "galcore interrupt service";
+ gc500_handle.dev_id = Device;
+ gc500_handle.handler = isrRoutine;
+ gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
+ gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+
+ ret = dove_gpio_request(
+ DOVE_GPIO0_7, &gc500_handle
+ );
+#else
+ ret = request_irq(
+ Device->irqLines[Core], isrRoutine, gcdIRQF_FLAG,
+ "galcore interrupt service", (gctPOINTER)Core
+ );
+
+ if (ret != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not register irq line %d (error=%d)\n",
+ __FUNCTION__, __LINE__,
+ Device->irqLines[Core], ret
+ );
+
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Mark ISR as initialized. */
+ Device->isrInitializeds[Core] = gcvTRUE;
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckGALDEVICE_Setup_ISR_VG(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+ gctINT ret;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ if (Device->irqLines[gcvCORE_VG] < 0)
+ {
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+ gc500_handle.dev_name = "galcore interrupt service";
+ gc500_handle.dev_id = Device;
+ gc500_handle.handler = isrRoutineVG;
+ gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
+ gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+
+ ret = dove_gpio_request(
+ DOVE_GPIO0_7, &gc500_handle
+ );
+#else
+ ret = request_irq(
+ Device->irqLines[gcvCORE_VG], isrRoutineVG, gcdIRQF_FLAG,
+ "galcore interrupt service for 2D", Device
+ );
+#endif
+
+ if (ret != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not register irq line %d (error=%d)\n",
+ __FUNCTION__, __LINE__,
+ Device->irqLines[gcvCORE_VG], ret
+ );
+
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ /* Mark ISR as initialized. */
+ Device->isrInitializeds[gcvCORE_VG] = gcvTRUE;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Release_ISR
+**
+** Release the irq line.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Release_ISR(
+ IN gceCORE Core
+ )
+{
+ gckGALDEVICE Device = galDevice;
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* release the irq */
+ if (Device->isrInitializeds[Core])
+ {
+#ifdef FLAREON
+ dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
+#else
+ free_irq(Device->irqLines[Core], (gctPOINTER)Core);
+#endif
+ Device->isrInitializeds[Core] = gcvFALSE;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_Release_ISR_VG(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* release the irq */
+ if (Device->isrInitializeds[gcvCORE_VG])
+ {
+#ifdef FLAREON
+ dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
+#else
+ free_irq(Device->irqLines[gcvCORE_VG], Device);
+#endif
+
+ Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start_Threads
+**
+** Start the daemon threads.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+** gcvSTATUS_GENERIC_IO
+** Start failed.
+*/
+gceSTATUS
+gckGALDEVICE_Start_Threads(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ gcmkONERROR(_StartThread(threadRoutine, gcvCORE_MAJOR));
+ gcmkONERROR(_StartThread(threadRoutine, gcvCORE_2D));
+
+ gcmkONERROR(_StartThread(threadRoutine, gcvCORE_VG));
+
+ {
+ gctUINTPTR_T i = gcvCORE_3D1;
+
+ for (; i <= gcvCORE_3D3; i++)
+ {
+ gcmkONERROR(_StartThread(threadRoutine, i));
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop_Threads
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop_Threads(
+ gckGALDEVICE Device
+ )
+{
+ gctINT i;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ /* Stop the kernel threads. */
+ if (Device->threadInitializeds[i])
+ {
+ Device->killThread = gcvTRUE;
+ up(&Device->semas[i]);
+
+ kthread_stop(Device->threadCtxts[i]);
+ Device->threadCtxts[i] = gcvNULL;
+ Device->threadInitializeds[i] = gcvFALSE;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start
+**
+** Start the gal device, including the following actions: setup the isr routine
+** and start the daemoni thread.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+*/
+gceSTATUS
+gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+ gctUINT i;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ /* Start the kernel thread. */
+ gcmkONERROR(gckGALDEVICE_Start_Threads(Device));
+
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ if (i == gcvCORE_VG)
+ {
+ continue;
+ }
+
+ if (Device->kernels[i] != gcvNULL)
+ {
+ /* Setup the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Setup_ISR(i));
+
+ /* Switch to SUSPEND power state. */
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+ Device->kernels[i]->hardware, gcvPOWER_OFF_BROADCAST
+ ));
+ }
+ }
+
+ if (Device->kernels[gcvCORE_VG] != gcvNULL)
+ {
+ /* Setup the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Setup_ISR_VG(Device));
+
+#if gcdENABLE_VG
+ /* Switch to SUSPEND power state. */
+ gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
+ Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF_BROADCAST
+ ));
+#endif
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ )
+{
+ gceSTATUS status;
+ gctUINT i;
+
+ gcmkHEADER_ARG("Device=0x%x", Device);
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ if (i == gcvCORE_VG)
+ {
+ continue;
+ }
+
+ if (Device->kernels[i] != gcvNULL)
+ {
+ /* Switch to OFF power state. */
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+ Device->kernels[i]->hardware, gcvPOWER_OFF
+ ));
+
+ /* Remove the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Release_ISR(i));
+ }
+ }
+
+ if (Device->kernels[gcvCORE_VG] != gcvNULL)
+ {
+ /* Setup the ISR routine. */
+ gcmkONERROR(gckGALDEVICE_Release_ISR_VG(Device));
+
+#if gcdENABLE_VG
+ /* Switch to OFF power state. */
+ gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
+ Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF
+ ));
+#endif
+ }
+
+ /* Stop the kernel thread. */
+ gcmkONERROR(gckGALDEVICE_Stop_Threads(Device));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_AddCore
+**
+** Add a core after gckGALDevice is constructed.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+*/
+gceSTATUS
+gckGALDEVICE_AddCore(
+ IN gckGALDEVICE Device,
+ IN gcsDEVICE_CONSTRUCT_ARGS * Args
+ )
+{
+ gceSTATUS status;
+ gceCORE core = gcvCORE_COUNT;
+ gctUINT i = 0;
+
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+
+ /* Find which core is added. */
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ if (Args->irqs[i] != -1)
+ {
+ core = i;
+ break;
+ }
+ }
+
+ if (i == gcvCORE_COUNT)
+ {
+ gcmkPRINT("[galcore]: No valid core information found");
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+
+ gcmkPRINT("[galcore]: add core[%d]", core);
+
+ /* Record irq, registerBase, registerSize. */
+ Device->irqLines[core] = Args->irqs[core];
+ _SetupRegisterPhysical(Device, Args);
+
+ /* Map register memory.*/
+
+ /* Add a platform indepedent framework. */
+ gcmkONERROR(gckDEVICE_AddCore(
+ Device->device,
+ core,
+ Args->chipIDs[core],
+ Device,
+ &Device->kernels[core]
+ ));
+
+ /* Start thread routine. */
+ _StartThread(threadRoutine, core);
+
+ /* Register ISR. */
+ gckGALDEVICE_Setup_ISR(core);
+
+ /* Set default power management state. */
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(
+ Device->kernels[core]->hardware, gcvPOWER_OFF_BROADCAST
+ ));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
new file mode 100644
index 000000000000..f7b1e0d6010e
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
@@ -0,0 +1,256 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_device_h_
+#define __gc_hal_kernel_device_h_
+
+#include "gc_hal_kernel_debugfs.h"
+#include "gc_hal_ta.h"
+
+typedef struct _gcsDEVICE_CONSTRUCT_ARGS
+{
+ gctBOOL recovery;
+ gctUINT stuckDump;
+ gctUINT gpu3DMinClock;
+
+ gctBOOL contiguousRequested;
+ gcsPLATFORM* platform;
+ gctBOOL mmu;
+ gctBOOL registerMemMapped;
+ gctPOINTER registerMemAddress;
+#if gcdDEC_ENABLE_AHB
+ gctUINT32 registerMemBaseDEC300;
+ gctSIZE_T registerMemSizeDEC300;
+#endif
+ gctINT irqs[gcvCORE_COUNT];
+ gctUINT registerBases[gcvCORE_COUNT];
+ gctUINT registerSizes[gcvCORE_COUNT];
+ gctBOOL powerManagement;
+ gctBOOL gpuProfiler;
+ gctUINT chipIDs[gcvCORE_COUNT];
+}
+gcsDEVICE_CONSTRUCT_ARGS;
+
+/******************************************************************************\
+************************** gckGALDEVICE Structure ******************************
+\******************************************************************************/
+
+typedef struct _gckGALDEVICE
+{
+ /* Objects. */
+ gckOS os;
+ gckKERNEL kernels[gcdMAX_GPU_COUNT];
+
+ gcsPLATFORM* platform;
+
+ /* Attributes. */
+ gctSIZE_T internalSize;
+ gctPHYS_ADDR internalPhysical;
+ gctUINT32 internalPhysicalName;
+ gctPOINTER internalLogical;
+ gckVIDMEM internalVidMem;
+ gctSIZE_T externalSize;
+ gctPHYS_ADDR externalPhysical;
+ gctUINT32 externalPhysicalName;
+ gctPOINTER externalLogical;
+ gckVIDMEM externalVidMem;
+ gckVIDMEM contiguousVidMem;
+ gctPOINTER contiguousBase;
+ gctPHYS_ADDR contiguousPhysical;
+ gctUINT32 contiguousPhysicalName;
+ gctSIZE_T contiguousSize;
+ gctBOOL contiguousMapped;
+ gctPOINTER contiguousMappedUser;
+ gctBOOL contiguousRequested;
+ gctSIZE_T systemMemorySize;
+ gctUINT32 systemMemoryBaseAddress;
+ gctPOINTER registerBases[gcdMAX_GPU_COUNT];
+ gctSIZE_T registerSizes[gcdMAX_GPU_COUNT];
+ gctUINT32 baseAddress;
+ gctUINT32 physBase;
+ gctUINT32 physSize;
+ gctUINT32 requestedRegisterMemBases[gcdMAX_GPU_COUNT];
+ gctSIZE_T requestedRegisterMemSizes[gcdMAX_GPU_COUNT];
+ gctUINT32 requestedContiguousBase;
+ gctSIZE_T requestedContiguousSize;
+
+ /* IRQ management. */
+ gctINT irqLines[gcdMAX_GPU_COUNT];
+ gctBOOL isrInitializeds[gcdMAX_GPU_COUNT];
+
+ /* Thread management. */
+ struct task_struct *threadCtxts[gcdMAX_GPU_COUNT];
+ struct semaphore semas[gcdMAX_GPU_COUNT];
+ gctBOOL threadInitializeds[gcdMAX_GPU_COUNT];
+ gctBOOL killThread;
+
+ /* Signal management. */
+ gctINT signal;
+
+ /* States before suspend. */
+ gceCHIPPOWERSTATE statesStored[gcdMAX_GPU_COUNT];
+
+ /* Device Debug File System Entry in kernel. */
+ struct _gcsDEBUGFS_Node * dbgNode;
+
+ gcsDEBUGFS_DIR debugfsDir;
+
+ gckDEVICE device;
+
+ gcsDEVICE_CONSTRUCT_ARGS args;
+
+ /* gctsOs object for trust application. */
+ gctaOS taos;
+}
+* gckGALDEVICE;
+
+typedef struct _gcsHAL_PRIVATE_DATA
+{
+ gckGALDEVICE device;
+ gctPOINTER mappedMemory;
+ gctPOINTER contiguousLogical;
+ /* The process opening the device may not be the same as the one that closes it. */
+ gctUINT32 pidOpen;
+}
+gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
+
+gceSTATUS gckGALDEVICE_Setup_ISR(
+ IN gceCORE Core
+ );
+
+gceSTATUS gckGALDEVICE_Setup_ISR_VG(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Release_ISR(
+ IN gceCORE Core
+ );
+
+gceSTATUS gckGALDEVICE_Release_ISR_VG(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start_Threads(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop_Threads(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Construct(
+ IN gctINT IrqLine,
+ IN gctUINT32 RegisterMemBase,
+ IN gctSIZE_T RegisterMemSize,
+ IN gctINT IrqLine2D,
+ IN gctUINT32 RegisterMemBase2D,
+ IN gctSIZE_T RegisterMemSize2D,
+ IN gctINT IrqLineVG,
+ IN gctUINT32 RegisterMemBaseVG,
+ IN gctSIZE_T RegisterMemSizeVG,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 PhysBaseAddr,
+ IN gctUINT32 PhysSize,
+ IN gctINT Signal,
+ IN gctUINT LogFileSize,
+ IN gctINT PowerManagement,
+ IN gctINT GpuProfiler,
+ IN gcsDEVICE_CONSTRUCT_ARGS * Args,
+ OUT gckGALDEVICE *Device
+ );
+
+gceSTATUS gckGALDEVICE_Destroy(
+ IN gckGALDEVICE Device
+ );
+
+static gcmINLINE gckKERNEL
+_GetValidKernel(
+ gckGALDEVICE Device
+ )
+{
+ if (Device->kernels[gcvCORE_MAJOR])
+ {
+ return Device->kernels[gcvCORE_MAJOR];
+ }
+ else
+ if (Device->kernels[gcvCORE_2D])
+ {
+ return Device->kernels[gcvCORE_2D];
+ }
+ else
+ if (Device->kernels[gcvCORE_VG])
+ {
+ return Device->kernels[gcvCORE_VG];
+ }
+ else
+ {
+ gcmkASSERT(gcvFALSE);
+ return gcvNULL;
+ }
+}
+
+#endif /* __gc_hal_kernel_device_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
new file mode 100644
index 000000000000..816aae07190f
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
@@ -0,0 +1,1455 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_driver.h"
+
+#include <linux/platform_device.h>
+#include <linux/component.h>
+
+/* Zone used for header/footer. */
+#define _GC_OBJ_ZONE gcvZONE_DRIVER
+
+MODULE_DESCRIPTION("Vivante Graphics Driver");
+MODULE_LICENSE("Dual MIT/GPL");
+
+static struct class* gpuClass;
+
+static gcsPLATFORM platform;
+
+static gckGALDEVICE galDevice;
+
+static uint major = 199;
+module_param(major, uint, 0644);
+MODULE_PARM_DESC(major, "major device number for GC device");
+
+static int irqLine = -1;
+module_param(irqLine, int, 0644);
+MODULE_PARM_DESC(irqLine, "IRQ number of GC core");
+
+static ulong registerMemBase = 0x80000000;
+module_param(registerMemBase, ulong, 0644);
+MODULE_PARM_DESC(registerMemBase, "Base of bus address of GC core AHB register");
+
+static ulong registerMemSize = 2 << 10;
+module_param(registerMemSize, ulong, 0644);
+MODULE_PARM_DESC(registerMemSize, "Size of bus address range of GC core AHB register");
+
+static int irqLine2D = -1;
+module_param(irqLine2D, int, 0644);
+MODULE_PARM_DESC(irqLine2D, "IRQ number of G2D core if irqLine is used for a G3D core");
+
+static ulong registerMemBase2D = 0x00000000;
+module_param(registerMemBase2D, ulong, 0644);
+MODULE_PARM_DESC(registerMemBase2D, "Base of bus address of G2D core if registerMemBase2D is used for a G3D core");
+
+static ulong registerMemSize2D = 2 << 10;
+module_param(registerMemSize2D, ulong, 0644);
+MODULE_PARM_DESC(registerMemSize2D, "Size of bus address range of G2D core if registerMemSize is used for a G3D core");
+
+static int irqLineVG = -1;
+module_param(irqLineVG, int, 0644);
+MODULE_PARM_DESC(irqLineVG, "IRQ number of VG core");
+
+static ulong registerMemBaseVG = 0x00000000;
+module_param(registerMemBaseVG, ulong, 0644);
+MODULE_PARM_DESC(registerMemBaseVG, "Base of bus address of VG core");
+
+static ulong registerMemSizeVG = 2 << 10;
+module_param(registerMemSizeVG, ulong, 0644);
+MODULE_PARM_DESC(registerMemSizeVG, "Size of bus address range of VG core");
+
+#if gcdDEC_ENABLE_AHB
+static ulong registerMemBaseDEC300 = 0x00000000;
+module_param(registerMemBaseDEC300, ulong, 0644);
+
+static ulong registerMemSizeDEC300 = 2 << 10;
+module_param(registerMemSizeDEC300, ulong, 0644);
+#endif
+
+#ifndef gcdDEFAULT_CONTIGUOUS_SIZE
+#define gcdDEFAULT_CONTIGUOUS_SIZE (4 << 20)
+#endif
+static ulong contiguousSize = gcdDEFAULT_CONTIGUOUS_SIZE;
+module_param(contiguousSize, ulong, 0644);
+MODULE_PARM_DESC(contiguousSize, "Size of memory reserved for GC");
+
+static ulong contiguousBase = 0;
+module_param(contiguousBase, ulong, 0644);
+MODULE_PARM_DESC(contiguousBase, "Base address of memory reserved for GC, if it is 0, GC driver will try to allocate a buffer whose size defined by contiguousSize");
+
+static int fastClear = -1;
+module_param(fastClear, int, 0644);
+MODULE_PARM_DESC(fastClear, "Disable fast clear if set it to 0, enabled by default");
+
+static int compression = -1;
+module_param(compression, int, 0644);
+MODULE_PARM_DESC(compression, "Disable compression if set it to 0, enabled by default");
+
+static int powerManagement = 1;
+module_param(powerManagement, int, 0644);
+MODULE_PARM_DESC(powerManagement, "Disable auto power saving if set it to 1, enabled by default");
+
+static int gpuProfiler = 0;
+module_param(gpuProfiler, int, 0644);
+MODULE_PARM_DESC(gpuProfiler, "Enable profiling support, disabled by default");
+
+static ulong baseAddress = 0;
+module_param(baseAddress, ulong, 0644);
+MODULE_PARM_DESC(baseAddress, "Only used for old MMU, set it to 0 if memory which can be accessed by GPU falls into 0 - 2G, otherwise set it to 0x80000000");
+
+static ulong physSize = 0;
+module_param(physSize, ulong, 0644);
+MODULE_PARM_DESC(physSize, "Obsolete");
+
+static uint logFileSize = 0;
+module_param(logFileSize,uint, 0644);
+MODULE_PARM_DESC(logFileSize, "Size of buffer to store GC driver output messsage, if it is not 0, message is read from /sys/kernel/debug/gc/galcore_trace, default value is 0");
+
+static uint recovery = 0;
+module_param(recovery, uint, 0644);
+MODULE_PARM_DESC(recovery, "Recover GPU from stuck (1: Enable, 0: Disable)");
+
+/* Middle needs about 40KB buffer, Maximal may need more than 200KB buffer. */
+static uint stuckDump = 0;
+module_param(stuckDump, uint, 0644);
+MODULE_PARM_DESC(stuckDump, "Level of stuck dump content (1: Minimal, 2: Middle, 3: Maximal)");
+
+static int showArgs = 0;
+module_param(showArgs, int, 0644);
+MODULE_PARM_DESC(showArgs, "Display parameters value when driver loaded");
+
+static int mmu = 1;
+module_param(mmu, int, 0644);
+MODULE_PARM_DESC(mmu, "Disable MMU if set it to 0, enabled by default");
+
+static int irqs[gcvCORE_COUNT] = {[0 ... gcvCORE_COUNT - 1] = -1};
+module_param_array(irqs, int, NULL, 0644);
+MODULE_PARM_DESC(irqs, "Array of IRQ numbers of multi-GPU");
+
+static uint registerBases[gcvCORE_COUNT];
+module_param_array(registerBases, uint, NULL, 0644);
+MODULE_PARM_DESC(registerBases, "Array of bases of bus address of register of multi-GPU");
+
+static uint registerSizes[gcvCORE_COUNT] = {[0 ... gcvCORE_COUNT - 1] = 2 << 10};
+module_param_array(registerSizes, uint, NULL, 0644);
+MODULE_PARM_DESC(registerSizes, "Array of sizes of bus address range of register of multi-GPU");
+
+static uint chipIDs[gcvCORE_COUNT] = {[0 ... gcvCORE_COUNT - 1] = gcvCHIP_ID_DEFAULT};
+module_param_array(chipIDs, uint, NULL, 0644);
+MODULE_PARM_DESC(chipIDs, "Array of chipIDs of multi-GPU");
+
+static uint type = 0;
+module_param(type, uint, 0664);
+MODULE_PARM_DESC(type, "0 - Char Driver (Default), 1 - Misc Driver");
+
+static int gpu3DMinClock = 1;
+
+static int contiguousRequested = 0;
+
+static gctBOOL registerMemMapped = gcvFALSE;
+static gctPOINTER registerMemAddress = gcvNULL;
+static ulong bankSize = 0;
+static int signal = 48;
+
+void
+_UpdateModuleParam(
+ gcsMODULE_PARAMETERS *Param
+ )
+{
+ irqLine = Param->irqLine ;
+ registerMemBase = Param->registerMemBase;
+ registerMemSize = Param->registerMemSize;
+ irqLine2D = Param->irqLine2D ;
+ registerMemBase2D = Param->registerMemBase2D;
+ registerMemSize2D = Param->registerMemSize2D;
+#if gcdENABLE_VG
+ irqLineVG = Param->irqLineVG;
+ registerMemBaseVG = Param->registerMemBaseVG;
+ registerMemSizeVG = Param->registerMemSizeVG;
+#endif
+ contiguousSize = Param->contiguousSize;
+ contiguousBase = Param->contiguousBase;
+ bankSize = Param->bankSize;
+ fastClear = Param->fastClear;
+ compression = Param->compression;
+ powerManagement = Param->powerManagement;
+ gpuProfiler = Param->gpuProfiler;
+ signal = Param->signal;
+ baseAddress = Param->baseAddress;
+ physSize = Param->physSize;
+ logFileSize = Param->logFileSize;
+ recovery = Param->recovery;
+ stuckDump = Param->stuckDump;
+ showArgs = Param->showArgs;
+ contiguousRequested = Param->contiguousRequested;
+ gpu3DMinClock = Param->gpu3DMinClock;
+ registerMemMapped = Param->registerMemMapped;
+ registerMemAddress = Param->registerMemAddress;
+
+ memcpy(irqs, Param->irqs, gcmSIZEOF(gctINT) * gcvCORE_COUNT);
+ memcpy(registerBases, Param->registerBases, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+ memcpy(registerSizes, Param->registerSizes, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+ memcpy(chipIDs, Param->chipIDs, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+}
+
+void
+gckOS_DumpParam(
+ void
+ )
+{
+ gctINT i;
+
+ printk("Galcore options:\n");
+ if (irqLine != -1)
+ {
+ printk(" irqLine = %d\n", irqLine);
+ printk(" registerMemBase = 0x%08lX\n", registerMemBase);
+ printk(" registerMemSize = 0x%08lX\n", registerMemSize);
+ }
+
+ if (irqLine2D != -1)
+ {
+ printk(" irqLine2D = %d\n", irqLine2D);
+ printk(" registerMemBase2D = 0x%08lX\n", registerMemBase2D);
+ printk(" registerMemSize2D = 0x%08lX\n", registerMemSize2D);
+ }
+
+ if (irqLineVG != -1)
+ {
+ printk(" irqLineVG = %d\n", irqLineVG);
+ printk(" registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
+ printk(" registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
+ }
+
+#if gcdDEC_ENABLE_AHB
+ printk(" registerMemBaseDEC300 = 0x%08lX\n", registerMemBaseDEC300);
+ printk(" registerMemSizeDEC300 = 0x%08lX\n", registerMemSizeDEC300);
+#endif
+
+ printk(" contiguousSize = 0x%08lX\n", contiguousSize);
+ printk(" contiguousBase = 0x%08lX\n", contiguousBase);
+ printk(" bankSize = 0x%08lX\n", bankSize);
+ printk(" fastClear = %d\n", fastClear);
+ printk(" compression = %d\n", compression);
+ printk(" signal = %d\n", signal);
+ printk(" powerManagement = %d\n", powerManagement);
+ printk(" baseAddress = 0x%08lX\n", baseAddress);
+ printk(" physSize = 0x%08lX\n", physSize);
+ printk(" logFileSize = %d KB \n", logFileSize);
+ printk(" recovery = %d\n", recovery);
+ printk(" stuckDump = %d\n", stuckDump);
+ printk(" gpuProfiler = %d\n", gpuProfiler);
+
+ printk(" irqs = ");
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ printk("%d, ", irqs[i]);
+ }
+ printk("\n");
+
+ printk(" registerBases = ");
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ printk("0x%08X, ", registerBases[i]);
+ }
+ printk("\n");
+
+ printk(" registerSizes = ");
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ printk("0x%08X, ", registerSizes[i]);
+ }
+ printk("\n");
+
+ printk(" chipIDs = ");
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ printk("0x%08X, ", chipIDs[i]);
+ }
+ printk("\n");
+
+ printk("Build options:\n");
+ printk(" gcdGPU_TIMEOUT = %d\n", gcdGPU_TIMEOUT);
+ printk(" gcdGPU_2D_TIMEOUT = %d\n", gcdGPU_2D_TIMEOUT);
+ printk(" gcdINTERRUPT_STATISTIC = %d\n", gcdINTERRUPT_STATISTIC);
+}
+
+static int drv_open(
+ struct inode* inode,
+ struct file* filp
+ )
+{
+ gceSTATUS status;
+ gctBOOL attached = gcvFALSE;
+ gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
+ gctINT i;
+
+ gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
+
+ if (filp == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): filp is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL | __GFP_NOWARN);
+
+ if (data == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): private_data is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ data->device = galDevice;
+ data->mappedMemory = gcvNULL;
+ data->contiguousLogical = gcvNULL;
+ data->pidOpen = _GetProcessID();
+
+ /* Attached the process. */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (galDevice->kernels[i] != gcvNULL)
+ {
+ gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
+ }
+ }
+ attached = gcvTRUE;
+
+ if (!galDevice->contiguousMapped)
+ {
+ if (galDevice->contiguousPhysical != gcvNULL)
+ {
+ gcmkONERROR(gckOS_MapMemory(
+ galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ &data->contiguousLogical
+ ));
+ }
+ }
+
+ filp->private_data = data;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+
+OnError:
+ if (data != gcvNULL)
+ {
+ if (data->contiguousLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapMemory(
+ galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ data->contiguousLogical
+ ));
+ }
+
+ kfree(data);
+ }
+
+ if (attached)
+ {
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (galDevice->kernels[i] != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
+ }
+ }
+ }
+
+ gcmkFOOTER();
+ return -ENOTTY;
+}
+
+static int drv_release(
+ struct inode* inode,
+ struct file* filp
+ )
+{
+ gceSTATUS status;
+ gcsHAL_PRIVATE_DATA_PTR data;
+ gckGALDEVICE device;
+ gctINT i;
+
+ gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
+
+ if (filp == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): filp is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ data = filp->private_data;
+
+ if (data == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): private_data is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ device = data->device;
+
+ if (device == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): device is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (!device->contiguousMapped)
+ {
+ if (data->contiguousLogical != gcvNULL)
+ {
+ gcmkONERROR(gckOS_UnmapMemoryEx(
+ galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ data->contiguousLogical,
+ data->pidOpen
+ ));
+
+ data->contiguousLogical = gcvNULL;
+ }
+ }
+
+ /* A process gets detached. */
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (galDevice->kernels[i] != gcvNULL)
+ {
+ gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
+ }
+ }
+
+ kfree(data);
+ filp->private_data = NULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+
+OnError:
+ gcmkFOOTER();
+ return -ENOTTY;
+}
+
+static long drv_ioctl(
+ struct file* filp,
+ unsigned int ioctlCode,
+ unsigned long arg
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+ gctUINT32 copyLen;
+ DRIVER_ARGS drvArgs;
+ gckGALDEVICE device;
+ gcsHAL_PRIVATE_DATA_PTR data;
+ gckVIDMEM_NODE nodeObject;
+ gctUINT32 i;
+
+ gcmkHEADER_ARG(
+ "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
+ filp, ioctlCode, arg
+ );
+
+ if (filp == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): filp is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ data = filp->private_data;
+
+ if (data == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): private_data is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ device = data->device;
+
+ if (device == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): device is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
+ && (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
+ )
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): unknown command %d\n",
+ __FUNCTION__, __LINE__,
+ ioctlCode
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Get the drvArgs. */
+ copyLen = copy_from_user(
+ &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
+ );
+
+ if (copyLen != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): error copying of the input arguments.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Now bring in the gcsHAL_INTERFACE structure. */
+ if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
+ || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
+ )
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): input or/and output structures are invalid.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ copyLen = copy_from_user(
+ &iface, gcmUINT64_TO_PTR(drvArgs.InputBuffer), sizeof(gcsHAL_INTERFACE)
+ );
+
+ if (copyLen != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): error copying of input HAL interface.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ status = gckDEVICE_Dispatch(device->device, &iface);
+
+ /* Redo system call after pending signal is handled. */
+ if (status == gcvSTATUS_INTERRUPTED)
+ {
+ gcmkFOOTER();
+ return -ERESTARTSYS;
+ }
+
+ if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
+ {
+ gcuVIDMEM_NODE_PTR node;
+
+ for (i = 0; i < gcvCORE_COUNT; i++)
+ {
+ if (device->kernels[i] != gcvNULL)
+ {
+ break;
+ }
+ }
+
+ if(i == gcvCORE_COUNT)
+ goto OnError;
+
+ gcmkONERROR(gckVIDMEM_HANDLE_Lookup(device->kernels[i],
+ _GetProcessID(),
+ (gctUINT32)iface.u.LockVideoMemory.node,
+ &nodeObject));
+ node = nodeObject->node;
+
+ /* Special case for mapped memory. */
+ if ((data->mappedMemory != gcvNULL)
+ && (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ )
+ {
+ /* Compute offset into mapped memory. */
+ gctUINT32 offset
+ = (gctUINT8 *) gcmUINT64_TO_PTR(iface.u.LockVideoMemory.memory)
+ - (gctUINT8 *) device->contiguousBase;
+
+ /* Compute offset into user-mapped region. */
+ iface.u.LockVideoMemory.memory =
+ gcmPTR_TO_UINT64((gctUINT8 *) data->mappedMemory + offset);
+ }
+ }
+
+ /* Copy data back to the user. */
+ copyLen = copy_to_user(
+ gcmUINT64_TO_PTR(drvArgs.OutputBuffer), &iface, sizeof(gcsHAL_INTERFACE)
+ );
+
+ if (copyLen != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): error copying of output HAL interface.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+
+OnError:
+ gcmkFOOTER();
+ return -ENOTTY;
+}
+
+static int drv_mmap(
+ struct file* filp,
+ struct vm_area_struct* vma
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gcsHAL_PRIVATE_DATA_PTR data;
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
+
+ if (filp == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): filp is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ data = filp->private_data;
+
+ if (data == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): private_data is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ device = data->device;
+
+ if (device == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): device is NULL\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+#if !gcdPAGED_MEMORY_CACHEABLE
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_flags |= gcdVM_FLAGS;
+#endif
+ vma->vm_pgoff = 0;
+
+ if (device->contiguousMapped)
+ {
+ unsigned long size = vma->vm_end - vma->vm_start;
+ int ret = 0;
+
+ if (size > device->contiguousSize)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Invalid mapping size.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ ret = io_remap_pfn_range(
+ vma,
+ vma->vm_start,
+ device->requestedContiguousBase >> PAGE_SHIFT,
+ size,
+ vma->vm_page_prot
+ );
+
+ if (ret != 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): io_remap_pfn_range failed %d\n",
+ __FUNCTION__, __LINE__,
+ ret
+ );
+
+ data->mappedMemory = gcvNULL;
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ data->mappedMemory = (gctPOINTER) vma->vm_start;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+ }
+
+OnError:
+ gcmkFOOTER();
+ return -ENOTTY;
+}
+
+static struct file_operations driver_fops =
+{
+ .owner = THIS_MODULE,
+ .open = drv_open,
+ .release = drv_release,
+ .unlocked_ioctl = drv_ioctl,
+#ifdef HAVE_COMPAT_IOCTL
+ .compat_ioctl = drv_ioctl,
+#endif
+ .mmap = drv_mmap,
+};
+
+static struct miscdevice gal_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE_NAME,
+ .fops = &driver_fops,
+};
+
+static int drv_init(void)
+{
+ int ret;
+ int result = -EINVAL;
+ gceSTATUS status;
+ gckGALDEVICE device = gcvNULL;
+ struct class* device_class = gcvNULL;
+
+ gcsDEVICE_CONSTRUCT_ARGS args = {
+ .recovery = recovery,
+ .stuckDump = stuckDump,
+ .gpu3DMinClock = gpu3DMinClock,
+ .contiguousRequested = contiguousRequested,
+ .platform = &platform,
+ .mmu = mmu,
+ .registerMemMapped = registerMemMapped,
+ .registerMemAddress = registerMemAddress,
+#if gcdDEC_ENABLE_AHB
+ .registerMemBaseDEC300 = registerMemBaseDEC300,
+ .registerMemSizeDEC300 = registerMemSizeDEC300,
+#endif
+ };
+
+ gcmkHEADER();
+
+ memcpy(args.irqs, irqs, gcmSIZEOF(gctINT) * gcvCORE_COUNT);
+ memcpy(args.registerBases, registerBases, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+ memcpy(args.registerSizes, registerSizes, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+ memcpy(args.chipIDs, chipIDs, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+
+ printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
+ gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
+
+#if !VIVANTE_PROFILER_PM
+ /* when enable gpu profiler, we need to turn off gpu powerMangement */
+ if (gpuProfiler)
+ {
+ powerManagement = 0;
+ }
+#endif
+
+ args.powerManagement = powerManagement;
+ args.gpuProfiler = gpuProfiler;
+
+ if (showArgs)
+ {
+ gckOS_DumpParam();
+ }
+
+ if (logFileSize != 0)
+ {
+ gckDEBUGFS_Initialize();
+ }
+
+ /* Create the GAL device. */
+ status = gckGALDEVICE_Construct(
+ irqLine,
+ registerMemBase, registerMemSize,
+ irqLine2D,
+ registerMemBase2D, registerMemSize2D,
+ irqLineVG,
+ registerMemBaseVG, registerMemSizeVG,
+ contiguousBase, contiguousSize,
+ bankSize, fastClear, compression, baseAddress, physSize, signal,
+ logFileSize,
+ powerManagement,
+ gpuProfiler,
+ &args,
+ &device
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to create the GAL device: status=%d\n",
+ __FUNCTION__, __LINE__, status);
+
+ goto OnError;
+ }
+
+ /* Start the GAL device. */
+ gcmkONERROR(gckGALDEVICE_Start(device));
+
+ if ((physSize != 0)
+ && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
+ && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
+ {
+ /* Reset the base address */
+ device->baseAddress = 0;
+ }
+
+ /* Set global galDevice pointer. */
+ galDevice = device;
+
+ if (type == 1)
+ {
+ /* Register as misc driver. */
+ ret = misc_register(&gal_device);
+
+ if (ret < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): misc_register fails.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ }
+ else
+ {
+ /* Register the character device. */
+ ret = register_chrdev(major, DEVICE_NAME, &driver_fops);
+
+ if (ret < 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Could not allocate major number for mmap.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ if (major == 0)
+ {
+ major = ret;
+ }
+
+ /* Create the device class. */
+ device_class = class_create(THIS_MODULE, CLASS_NAME);
+
+ if (IS_ERR(device_class))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to create the class.\n",
+ __FUNCTION__, __LINE__
+ );
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+ device_create(device_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
+#else
+ device_create(device_class, NULL, MKDEV(major, 0), DEVICE_NAME);
+#endif
+
+ gpuClass = device_class;
+ }
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
+ __FUNCTION__, __LINE__,
+ irqLine, contiguousSize, registerMemBase
+ );
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return 0;
+
+OnError:
+ /* Roll back. */
+ if (device_class != gcvNULL)
+ {
+ device_destroy(device_class, MKDEV(major, 0));
+ class_destroy(device_class);
+ }
+
+ if (device != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
+ gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
+ }
+
+ gcmkFOOTER();
+ return result;
+}
+
+static void drv_exit(void)
+{
+ gcmkHEADER();
+
+ if (type == 1)
+ {
+ misc_deregister(&gal_device);
+ }
+ else
+ {
+ gcmkASSERT(gpuClass != gcvNULL);
+ device_destroy(gpuClass, MKDEV(major, 0));
+ class_destroy(gpuClass);
+
+ unregister_chrdev(major, DEVICE_NAME);
+ }
+
+ gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
+ gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
+
+ if(gckDEBUGFS_IsEnabled())
+ {
+ gckDEBUGFS_Terminate();
+ }
+
+ gcmkFOOTER_NO();
+}
+static int gpu_platform_bind(struct device *dev)
+{
+ int ret;
+
+ ret = component_bind_all(dev, 0);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = drv_init();
+ if (!ret) {
+ platform_set_drvdata(to_platform_device(dev), galDevice);
+
+ return ret;
+ }
+ component_unbind_all(dev, 0);
+ return ret;
+}
+
+static void gpu_platform_unbind(struct device *dev)
+{
+ component_unbind_all(dev, 0);
+}
+
+extern struct component_match *match;
+static const struct component_master_ops gpu_platform_master_ops = {
+ .bind = gpu_platform_bind,
+ .unbind = gpu_platform_unbind,
+};
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int gpu_probe(struct platform_device *pdev)
+#else
+static int __devinit gpu_probe(struct platform_device *pdev)
+#endif
+{
+ int ret = -ENODEV;
+ gcsMODULE_PARAMETERS moduleParam = {
+ .irqLine = irqLine,
+ .registerMemBase = registerMemBase,
+ .registerMemSize = registerMemSize,
+ .irqLine2D = irqLine2D,
+ .registerMemBase2D = registerMemBase2D,
+ .registerMemSize2D = registerMemSize2D,
+ .irqLineVG = irqLineVG,
+ .registerMemBaseVG = registerMemBaseVG,
+ .registerMemSizeVG = registerMemSizeVG,
+ .contiguousSize = contiguousSize,
+ .contiguousBase = contiguousBase,
+ .bankSize = bankSize,
+ .fastClear = fastClear,
+ .compression = compression,
+ .powerManagement = powerManagement,
+ .gpuProfiler = gpuProfiler,
+ .signal = signal,
+ .baseAddress = baseAddress,
+ .physSize = physSize,
+ .logFileSize = logFileSize,
+ .recovery = recovery,
+ .stuckDump = stuckDump,
+ .showArgs = showArgs,
+ .gpu3DMinClock = gpu3DMinClock,
+ .registerMemMapped = registerMemMapped,
+ };
+
+
+ gcmkHEADER();
+
+ memcpy(moduleParam.irqs, irqs, gcmSIZEOF(gctINT) * gcvCORE_COUNT);
+ memcpy(moduleParam.registerBases, registerBases, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+ memcpy(moduleParam.registerSizes, registerSizes, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+ memcpy(moduleParam.chipIDs, chipIDs, gcmSIZEOF(gctUINT) * gcvCORE_COUNT);
+
+ platform.device = pdev;
+
+ if (platform.ops->getPower)
+ {
+ if (gcmIS_ERROR(platform.ops->getPower(&platform)))
+ {
+ gcmkFOOTER_NO();
+ return ret;
+ }
+ }
+
+ if (platform.ops->adjustParam)
+ {
+ /* Override default module param. */
+ platform.ops->adjustParam(&platform, &moduleParam);
+
+ /* Update module param because drv_init() uses them directly. */
+ _UpdateModuleParam(&moduleParam);
+ }
+ if (platform.ops->registerDevice) {
+ /*drv_init() will be called during binding*/
+ ret = component_master_add_with_match(&pdev->dev, &gpu_platform_master_ops, match);
+ if(ret !=0)
+ {
+ gcmkFOOTER_NO();
+ return ret;
+ }
+ }
+ else {
+ ret = drv_init();
+ if (!ret) {
+ platform_set_drvdata(pdev, galDevice);
+ gcmkFOOTER_NO();
+ return ret;
+ }
+ }
+
+ gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
+ return ret;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int gpu_remove(struct platform_device *pdev)
+#else
+static int __devexit gpu_remove(struct platform_device *pdev)
+#endif
+{
+ gcmkHEADER();
+
+ drv_exit();
+
+ if (platform.ops->putPower)
+ {
+ platform.ops->putPower(&platform);
+ }
+ if (platform.ops->registerDevice) {
+ component_master_del(&pdev->dev, &gpu_platform_master_ops);
+ }
+ gcmkFOOTER_NO();
+ return 0;
+}
+
+static int gpu_suspend(struct platform_device *dev, pm_message_t state)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+ gctINT i;
+
+ device = platform_get_drvdata(dev);
+
+ if (!device)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->kernels[i] != gcvNULL)
+ {
+ /* Store states. */
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ status = gckVGHARDWARE_QueryPowerManagementState(device->kernels[i]->vg->hardware, &device->statesStored[i]);
+ }
+ else
+#endif
+ {
+ status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
+ }
+ else
+#endif
+ {
+ status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
+ }
+
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_OFF);
+ }
+ else
+#endif
+ {
+ status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+
+ }
+ }
+
+ return 0;
+}
+
+static int gpu_resume(struct platform_device *dev)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+ gctINT i;
+ gceCHIPPOWERSTATE statesStored;
+
+ device = platform_get_drvdata(dev);
+
+ if (!device)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ if (device->kernels[i] != gcvNULL)
+ {
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
+ }
+ else
+#endif
+ {
+ status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+
+ /* Convert global state to crossponding internal state. */
+ switch(device->statesStored[i])
+ {
+ case gcvPOWER_OFF:
+ statesStored = gcvPOWER_OFF_BROADCAST;
+ break;
+ case gcvPOWER_IDLE:
+ statesStored = gcvPOWER_IDLE_BROADCAST;
+ break;
+ case gcvPOWER_SUSPEND:
+ statesStored = gcvPOWER_SUSPEND_BROADCAST;
+ break;
+ case gcvPOWER_ON:
+ statesStored = gcvPOWER_ON_AUTO;
+ break;
+ default:
+ statesStored = device->statesStored[i];
+ break;
+ }
+
+ /* Restore states. */
+#if gcdENABLE_VG
+ if (i == gcvCORE_VG)
+ {
+ status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, statesStored);
+ }
+ else
+#endif
+ {
+ status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+#ifdef CONFIG_PM_SLEEP
+static int gpu_system_suspend(struct device *dev)
+{
+ pm_message_t state={0};
+ return gpu_suspend(to_platform_device(dev), state);
+}
+
+static int gpu_system_resume(struct device *dev)
+{
+ return gpu_resume(to_platform_device(dev));
+}
+#endif
+
+static const struct dev_pm_ops gpu_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
+};
+#endif
+
+static struct platform_driver gpu_driver = {
+ .probe = gpu_probe,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+ .remove = gpu_remove,
+#else
+ .remove = __devexit_p(gpu_remove),
+#endif
+
+ .suspend = gpu_suspend,
+ .resume = gpu_resume,
+
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DEVICE_NAME,
+#if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+ .pm = &gpu_pm_ops,
+#endif
+ }
+};
+
+static int __init gpu_init(void)
+{
+ int ret = 0;
+
+ memset(&platform, 0, sizeof(gcsPLATFORM));
+
+ gckPLATFORM_QueryOperations(&platform.ops);
+
+ if (platform.ops == gcvNULL)
+ {
+ printk(KERN_ERR "galcore: No platform specific operations.\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (platform.ops->allocPriv)
+ {
+ /* Allocate platform private data. */
+ if (gcmIS_ERROR(platform.ops->allocPriv(&platform)))
+ {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (platform.ops->needAddDevice
+ && platform.ops->needAddDevice(&platform))
+ {
+ /* Allocate device */
+ platform.device = platform_device_alloc(DEVICE_NAME, -1);
+ if (!platform.device)
+ {
+ printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Add device */
+ ret = platform_device_add(platform.device);
+ if (ret)
+ {
+ printk(KERN_ERR "galcore: platform_device_add failed.\n");
+ goto put_dev;
+ }
+ }
+
+ platform.driver = &gpu_driver;
+
+ if (platform.ops->adjustDriver)
+ {
+ /* Override default platform_driver struct. */
+ platform.ops->adjustDriver(&platform);
+ }
+
+ if (platform.ops->registerDevice)
+ {
+ ret = platform.ops->registerDevice(&platform);
+ if (ret != 0) {
+ goto out;
+ }
+ }
+
+ ret = platform_driver_register(&gpu_driver);
+ if (!ret)
+ {
+ goto out;
+ }
+
+ platform_device_del(platform.device);
+put_dev:
+ platform_device_put(platform.device);
+
+out:
+ return ret;
+}
+
+static void __exit gpu_exit(void)
+{
+ platform_driver_unregister(&gpu_driver);
+
+ if (platform.ops->unRegisterDevice)
+ {
+ platform.ops->unRegisterDevice(&platform);
+ }
+
+ if (platform.ops->needAddDevice
+ && platform.ops->needAddDevice(&platform))
+ {
+ platform_device_unregister(platform.device);
+ }
+
+ if (platform.priv)
+ {
+ /* Free platform private data. */
+ platform.ops->freePriv(&platform);
+ }
+}
+
+module_init(gpu_init);
+module_exit(gpu_exit);
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c
new file mode 100644
index 000000000000..f2961e7dbd53
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_iommu.c
@@ -0,0 +1,250 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_device.h"
+
+#include <linux/iommu.h>
+#include <linux/platform_device.h>
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+typedef struct _gcsIOMMU
+{
+ struct iommu_domain * domain;
+ struct device * device;
+}
+gcsIOMMU;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+static int
+_IOMMU_Fault_Handler(
+ struct iommu_domain * Domain,
+ struct device * Dev,
+ unsigned long DomainAddress,
+ int flags,
+ void * args
+ )
+#else
+static int
+_IOMMU_Fault_Handler(
+ struct iommu_domain * Domain,
+ struct device * Dev,
+ unsigned long DomainAddress,
+ int flags
+ )
+#endif
+{
+ return 0;
+}
+
+static int
+_FlatMapping(
+ IN gckIOMMU Iommu
+ )
+{
+ gceSTATUS status;
+ gctUINT32 physical;
+
+ for (physical = 0; physical < 0x80000000; physical += PAGE_SIZE)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "Map %x => %x bytes = %d",
+ physical, physical, PAGE_SIZE
+ );
+
+ gcmkONERROR(gckIOMMU_Map(Iommu, physical, physical, PAGE_SIZE));
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+void
+gckIOMMU_Destory(
+ IN gckOS Os,
+ IN gckIOMMU Iommu
+ )
+{
+ gcmkHEADER();
+
+ if (Iommu->domain && Iommu->device)
+ {
+ iommu_attach_device(Iommu->domain, Iommu->device);
+ }
+
+ if (Iommu->domain)
+ {
+ iommu_domain_free(Iommu->domain);
+ }
+
+ if (Iommu)
+ {
+ gcmkOS_SAFE_FREE(Os, Iommu);
+ }
+
+ gcmkFOOTER_NO();
+}
+
+gceSTATUS
+gckIOMMU_Construct(
+ IN gckOS Os,
+ OUT gckIOMMU * Iommu
+ )
+{
+ gceSTATUS status;
+ gckIOMMU iommu = gcvNULL;
+ struct device *dev;
+ int ret;
+
+ gcmkHEADER();
+
+ dev = &Os->device->platform->device->dev;
+
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsIOMMU), (gctPOINTER *)&iommu));
+
+ gckOS_ZeroMemory(iommu, gcmSIZEOF(gcsIOMMU));
+
+ iommu->domain = iommu_domain_alloc(&platform_bus_type);
+
+ if (!iommu->domain)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "iommu_domain_alloc() fail");
+
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler, dev);
+#else
+ iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler);
+#endif
+
+ ret = iommu_attach_device(iommu->domain, dev);
+
+ if (ret)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS, "iommu_attach_device() fail %d", ret);
+
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ iommu->device = dev;
+
+ _FlatMapping(iommu);
+
+ *Iommu = iommu;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ gckIOMMU_Destory(Os, iommu);
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckIOMMU_Map(
+ IN gckIOMMU Iommu,
+ IN gctUINT32 DomainAddress,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes
+ )
+{
+ gceSTATUS status;
+ int ret;
+
+ gcmkHEADER_ARG("DomainAddress=%#X, Physical=%#X, Bytes=%d",
+ DomainAddress, Physical, Bytes);
+
+ ret = iommu_map(Iommu->domain, DomainAddress, Physical, Bytes, 0);
+
+ if (ret)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+
+ gcmkFOOTER();
+ return status;
+
+}
+
+gceSTATUS
+gckIOMMU_Unmap(
+ IN gckIOMMU Iommu,
+ IN gctUINT32 DomainAddress,
+ IN gctUINT32 Bytes
+ )
+{
+ gcmkHEADER();
+
+ iommu_unmap(Iommu->domain, DomainAddress, Bytes);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c
new file mode 100644
index 000000000000..67c9cbfe20f1
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.c
@@ -0,0 +1,527 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_QueryVideoMemory
+**
+** Query the amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
+** the memory information.
+*/
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=%p", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Get internal memory size and physical address. */
+ Interface->u.QueryVideoMemory.internalSize = device->internalSize;
+ Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysicalName;
+
+ /* Get external memory size and physical address. */
+ Interface->u.QueryVideoMemory.externalSize = device->externalSize;
+ Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysicalName;
+
+ /* Get contiguous memory size and physical address. */
+ Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
+ Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysicalName;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_GetVideoMemoryPool
+**
+** Get the gckVIDMEM object belonging to the specified pool.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcePOOL Pool
+** Pool to query gckVIDMEM object for.
+**
+** OUTPUT:
+**
+** gckVIDMEM * VideoMemory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object belonging to the requested pool.
+*/
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ )
+{
+ gckGALDEVICE device;
+ gckVIDMEM videoMemory;
+
+ gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Dispatch on pool. */
+ switch (Pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ videoMemory = device->internalVidMem;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ videoMemory = device->externalVidMem;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ videoMemory = device->contiguousVidMem;
+ break;
+
+ default:
+ /* Unknown pool. */
+ videoMemory = NULL;
+ }
+
+ /* Return pointer to the gckVIDMEM object. */
+ *VideoMemory = videoMemory;
+
+ /* Return status. */
+ gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory);
+ return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapMemory
+**
+** Map video memory into the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the base address of the mapped
+** memory region.
+*/
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ gckKERNEL kernel = Kernel;
+ gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
+
+ return gckOS_MapMemory(Kernel->os, physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_UnmapMemory
+**
+** Unmap video memory from the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** gctPOINTER Logical
+** Base address of the mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ gckKERNEL kernel = Kernel;
+ gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
+
+ return gckOS_UnmapMemory(Kernel->os, physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapVideoMemory
+**
+** Get the logical address for a hardware specific memory address for the
+** current process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE to map the memory into the user space.
+**
+** gctUINT32 Address
+** Hardware specific memory address.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemoryEx(
+ IN gckKERNEL Kernel,
+ IN gceCORE Core,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Logical
+ )
+{
+ gckGALDEVICE device = gcvNULL;
+ gcePOOL pool = gcvPOOL_UNKNOWN;
+ gctUINT32 offset = 0;
+ gctUINT32 base = 0;
+ gceSTATUS status;
+ gctPOINTER logical = gcvNULL;
+ gctUINT32 baseAddress;
+ gctPHYS_ADDR_T physical;
+
+ gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x",
+ Kernel, InUserSpace, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ /* Split the memory address into a pool type and offset. */
+ gcmkONERROR(
+ gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, Address, &pool, &offset));
+ }
+ else
+#endif
+ {
+ /* Split the memory address into a pool type and offset. */
+ gcmkONERROR(
+ gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset));
+ }
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ if (device->contiguousMapped)
+ {
+ logical = device->contiguousBase;
+ }
+ else
+ {
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+
+ mdl = (PLINUX_MDL) device->contiguousPhysical;
+
+ mutex_lock(&mdl->mapsMutex);
+ mdlMap = FindMdlMap(mdl, _GetProcessID());
+ mutex_unlock(&mdl->mapsMutex);
+
+ logical = (gctPOINTER) mdlMap->vmaAddr;
+ }
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ gcmkVERIFY_OK(
+ gckVGHARDWARE_SplitMemory(Kernel->vg->hardware,
+ device->contiguousVidMem->baseAddress,
+ &pool,
+ &base));
+ }
+ else
+#endif
+ {
+ gctUINT32 systemBaseAddress = 0;
+
+ if (Kernel->hardware->mmuVersion == 0)
+ {
+ gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &systemBaseAddress));
+ }
+
+ gcmkVERIFY_OK(
+ gckOS_CPUPhysicalToGPUPhysical(
+ Kernel->os,
+ device->contiguousVidMem->baseAddress - systemBaseAddress,
+ &physical
+ ));
+
+ gcmkSAFECASTPHYSADDRT(baseAddress, physical);
+
+ gcmkVERIFY_OK(
+ gckHARDWARE_SplitMemory(Kernel->hardware,
+ baseAddress,
+ &pool,
+ &base));
+ }
+ offset -= base;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Build logical address of specified address. */
+ *Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Logical=%p", *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Retunn the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapVideoMemory
+**
+** Get the logical address for a hardware specific memory address for the
+** current process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE to map the memory into the user space.
+**
+** gctUINT32 Address
+** Hardware specific memory address.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Logical
+ )
+{
+ return gckKERNEL_MapVideoMemoryEx(Kernel, gcvCORE_MAJOR, InUserSpace, Address, Logical);
+}
+/*******************************************************************************
+**
+** gckKERNEL_Notify
+**
+** This function iscalled by clients to notify the gckKERNRL object of an event.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gceNOTIFY Notification
+** Notification event.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+ IN gceNOTIFY Notification,
+ IN gctBOOL Data
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=%p Notification=%d Data=%d",
+ Kernel, Notification, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Dispatch on notifcation. */
+ switch (Notification)
+ {
+ case gcvNOTIFY_INTERRUPT:
+ /* Process the interrupt. */
+#if COMMAND_PROCESSOR_VERSION > 1
+ status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
+#else
+ status = gckHARDWARE_Interrupt(Kernel->hardware,
+ Data);
+#endif
+ break;
+
+ default:
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=%p", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Settings != gcvNULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Fill in signal. */
+ Settings->signal = device->signal;
+
+ /* Success. */
+ gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
+ return gcvSTATUS_OK;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
new file mode 100644
index 000000000000..32233cc3418e
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
@@ -0,0 +1,368 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_linux_h_
+#define __gc_hal_kernel_linux_h_
+
+/* VIV: Latest kernel version supported: 4.1.0. */
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#ifdef FLAREON
+#error 1
+# include <asm/arch-realview/dove_gpio_irq.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+
+#include <linux/idr.h>
+
+#ifdef MODVERSIONS
+# include <linux/modversions.h>
+#endif
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+#include <linux/clk.h>
+#endif
+
+#define NTSTRSAFE_NO_CCH_FUNCTIONS
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_platform.h"
+#include "gc_hal_kernel_device.h"
+#include "gc_hal_kernel_os.h"
+#include "gc_hal_kernel_debugfs.h"
+#include "gc_hal_ta.h"
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
+#else
+#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
+#endif
+
+#ifndef DEVICE_NAME
+# define DEVICE_NAME "galcore"
+#endif
+
+#ifndef CLASS_NAME
+# define CLASS_NAME "graphics_class"
+#endif
+
+#define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_MASK)) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
+#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
+#else
+#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
+#endif
+
+/* Protection bit when mapping memroy to user sapce */
+#define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
+
+#if gcdNONPAGED_MEMORY_BUFFERABLE
+#define gcmkIOREMAP ioremap_wc
+#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
+#elif !gcdNONPAGED_MEMORY_CACHEABLE
+#define gcmkIOREMAP ioremap_nocache
+#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
+#endif
+
+#define gcdSUPPRESS_OOM_MESSAGE 1
+
+#if gcdSUPPRESS_OOM_MESSAGE
+#define gcdNOWARN __GFP_NOWARN
+#else
+#define gcdNOWARN 0
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 1, 0)
+#ifdef gcdIRQ_SHARED
+# define gcdIRQF_FLAG (IRQF_SHARED)
+# else
+# define gcdIRQF_FLAG (0)
+# endif
+#else
+#ifdef gcdIRQ_SHARED
+# define gcdIRQF_FLAG (IRQF_DISABLED | IRQF_SHARED)
+# else
+# define gcdIRQF_FLAG (IRQF_DISABLED)
+# endif
+#endif
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+typedef struct _gcsIOMMU * gckIOMMU;
+
+typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
+typedef struct _gcsUSER_MAPPING
+{
+ /* Pointer to next mapping structure. */
+ gcsUSER_MAPPING_PTR next;
+
+ /* Physical address of this mapping. */
+ gctUINT32 physical;
+
+ /* Logical address of this mapping. */
+ gctPOINTER logical;
+
+ /* Number of bytes of this mapping. */
+ gctSIZE_T bytes;
+
+ /* Starting address of this mapping. */
+ gctINT8_PTR start;
+
+ /* Ending address of this mapping. */
+ gctINT8_PTR end;
+}
+gcsUSER_MAPPING;
+
+typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
+typedef struct _gcsINTEGER_DB
+{
+ struct idr idr;
+ spinlock_t lock;
+ gctINT curr;
+}
+gcsINTEGER_DB;
+
+struct _gckOS
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to device */
+ gckGALDEVICE device;
+
+ /* Memory management */
+ struct mutex mdlMutex;
+ struct list_head mdlHead;
+
+ /* Kernel process ID. */
+ gctUINT32 kernelProcessID;
+
+ /* Signal management. */
+
+ /* Lock. */
+ struct mutex signalMutex;
+
+ /* signal id database. */
+ gcsINTEGER_DB signalDB;
+
+ gcsUSER_MAPPING_PTR userMap;
+
+ /* workqueue for os timer. */
+ struct workqueue_struct * workqueue;
+
+ /* Allocate extra page to avoid cache overflow */
+ struct page* paddingPage;
+
+ /* Detect unfreed allocation. */
+ atomic_t allocateCount;
+
+ struct list_head allocatorList;
+
+ gcsDEBUGFS_DIR allocatorDebugfsDir;
+
+ gctBOOL allocatorLimitMarker;
+
+ /* Lock for register access check. */
+ struct mutex registerAccessLocks[gcdMAX_GPU_COUNT];
+
+ /* External power states. */
+ gctBOOL powerStates[gcdMAX_GPU_COUNT];
+
+ /* External clock states. */
+ gctBOOL clockStates[gcdMAX_GPU_COUNT];
+
+ /* IOMMU. */
+ gckIOMMU iommu;
+};
+
+typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
+typedef struct _gcsSIGNAL
+{
+ /* Kernel sync primitive. */
+ struct completion obj;
+
+ /* Manual reset flag. */
+ gctBOOL manualReset;
+
+ /* The reference counter. */
+ atomic_t ref;
+
+ /* The owner of the signal. */
+ gctHANDLE process;
+
+ /* ID. */
+ gctUINT32 id;
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+ /* Parent timeline. */
+ struct sync_timeline * timeline;
+# else
+ struct fence *fence;
+# endif
+#endif
+}
+gcsSIGNAL;
+
+typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
+typedef struct _gcsOSTIMER
+{
+ struct delayed_work work;
+ gctTIMERFUNCTION function;
+ gctPOINTER data;
+} gcsOSTIMER;
+
+gceSTATUS
+gckOS_ImportAllocators(
+ gckOS Os
+ );
+
+gceSTATUS
+gckOS_FreeAllocators(
+ gckOS Os
+ );
+
+gceSTATUS
+_ConvertLogical2Physical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctUINT32 ProcessID,
+ IN PLINUX_MDL Mdl,
+ OUT gctPHYS_ADDR_T * Physical
+ );
+
+void
+_UnmapUserLogical(
+ IN gctPOINTER Logical,
+ IN gctUINT32 Size
+ );
+
+gctBOOL
+_QuerySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+static inline gctINT
+_GetProcessID(
+ void
+ )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ return task_tgid_vnr(current);
+#else
+ return current->tgid;
+#endif
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+static inline int
+is_vmalloc_addr(
+ void *Addr
+ )
+{
+ unsigned long addr = (unsigned long)Addr;
+
+ return addr >= VMALLOC_START && addr < VMALLOC_END;
+}
+#endif
+
+#ifdef CONFIG_IOMMU_SUPPORT
+void
+gckIOMMU_Destory(
+ IN gckOS Os,
+ IN gckIOMMU Iommu
+ );
+
+gceSTATUS
+gckIOMMU_Construct(
+ IN gckOS Os,
+ OUT gckIOMMU * Iommu
+ );
+
+gceSTATUS
+gckIOMMU_Map(
+ IN gckIOMMU Iommu,
+ IN gctUINT32 DomainAddress,
+ IN gctUINT32 Physical,
+ IN gctUINT32 Bytes
+ );
+
+gceSTATUS
+gckIOMMU_Unmap(
+ IN gckIOMMU Iommu,
+ IN gctUINT32 DomainAddress,
+ IN gctUINT32 Bytes
+ );
+#endif
+
+#endif /* __gc_hal_kernel_linux_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c
new file mode 100644
index 000000000000..9ac7a3b4959d
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_math.c
@@ -0,0 +1,66 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+
+gctINT
+gckMATH_ModuloInt(
+ IN gctINT X,
+ IN gctINT Y
+ )
+{
+ if(Y ==0) {return 0;}
+ else {return X % Y;}
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_mutex.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_mutex.h
new file mode 100644
index 000000000000..72be2e933059
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_mutex.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef _gc_hal_kernel_mutex_h_
+#define _gc_hal_kernel_mutex_h_
+
+#include "gc_hal.h"
+#include <linux/mutex.h>
+
+/* Create a new mutex. */
+#define gckOS_CreateMutex(Os, Mutex) \
+({ \
+ gceSTATUS _status; \
+ gcmkHEADER_ARG("Os=0x%X", Os); \
+ \
+ /* Validate the arguments. */ \
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); \
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL); \
+ \
+ /* Allocate the mutex structure. */ \
+ _status = gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex); \
+ \
+ if (gcmIS_SUCCESS(_status)) \
+ { \
+ /* Initialize the mutex. */ \
+ mutex_init(*(struct mutex **)Mutex); \
+ } \
+ \
+ /* Return status. */ \
+ gcmkFOOTER_ARG("*Mutex=0x%X", *(struct mutex **)Mutex); \
+ _status; \
+})
+
+#endif
+
+
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
new file mode 100644
index 000000000000..9bf60450f976
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
@@ -0,0 +1,7807 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mman.h>
+#include <asm/atomic.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/irqflags.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
+#include <linux/math64.h>
+#endif
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#include <linux/anon_inodes.h>
+#endif
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+# include <linux/file.h>
+# include "gc_hal_kernel_sync.h"
+#endif
+
+#if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
+#include <dma.h>
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#include "gc_hal_kernel_allocator.h"
+
+#define gcmkBUG_ON(x, func, line) \
+ do { \
+ if (unlikely(x)) \
+ { \
+ int i = 0; \
+ while (1) \
+ { \
+ static int delay = 10 * 1000; \
+ gcmkPRINT("[galcore]: BUG ON @ %s(%d) (%d)", func, line, i++); \
+ dump_stack(); \
+ gckOS_Delay(gcvNULL, delay); \
+ delay *= 2; \
+ } \
+ } \
+ } while (0)
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+static gctINT
+_GetThreadID(
+ void
+ )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ return task_pid_vnr(current);
+#else
+ return current->pid;
+#endif
+}
+
+/* Must hold Mdl->mpasMutex before call this function. */
+static inline PLINUX_MDL_MAP
+_CreateMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT ProcessID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+
+ gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
+
+ mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
+
+ if (mdlMap == gcvNULL)
+ {
+ gcmkFOOTER_NO();
+ return gcvNULL;
+ }
+
+ mdlMap->pid = ProcessID;
+ mdlMap->vmaAddr = gcvNULL;
+ mdlMap->count = 0;
+
+ list_add(&mdlMap->link, &Mdl->mapsHead);
+
+ gcmkFOOTER_ARG("0x%X", mdlMap);
+ return mdlMap;
+}
+
+/* Must hold Mdl->mpasMutex before call this function. */
+static inline gceSTATUS
+_DestroyMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN PLINUX_MDL_MAP MdlMap
+ )
+{
+ gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
+
+ list_del(&MdlMap->link);
+ kfree(MdlMap);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/* Must hold Mdl->mpasMutex before call this function. */
+extern PLINUX_MDL_MAP
+FindMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT ProcessID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+
+ gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
+
+ if (Mdl == gcvNULL)
+ {
+ gcmkFOOTER_NO();
+ return gcvNULL;
+ }
+
+ list_for_each_entry(mdlMap, &Mdl->mapsHead, link)
+ {
+ if (mdlMap->pid == ProcessID)
+ {
+ gcmkFOOTER_ARG("0x%X", mdlMap);
+ return mdlMap;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvNULL;
+}
+
+
+static PLINUX_MDL
+_CreateMdl(
+ void
+ )
+{
+ PLINUX_MDL mdl;
+
+ gcmkHEADER();
+
+ mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
+
+ if (mdl)
+ {
+ mutex_init(&mdl->mapsMutex);
+ INIT_LIST_HEAD(&mdl->mapsHead);
+ }
+
+ gcmkFOOTER_ARG("0x%X", mdl);
+ return mdl;
+}
+
+static gceSTATUS
+_DestroyMdl(
+ IN PLINUX_MDL Mdl
+ )
+{
+ PLINUX_MDL_MAP mdlMap, next;
+
+ gcmkHEADER_ARG("Mdl=0x%X", Mdl);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
+
+ list_for_each_entry_safe(mdlMap, next, &Mdl->mapsHead, link)
+ {
+ gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
+ }
+
+ kfree(Mdl);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** Integer Id Management.
+*/
+gceSTATUS
+_AllocateIntegerId(
+ IN gcsINTEGER_DB_PTR Database,
+ IN gctPOINTER KernelPointer,
+ OUT gctUINT32 *Id
+ )
+{
+ int result;
+ gctINT next;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ idr_preload(GFP_KERNEL | gcdNOWARN);
+
+ spin_lock(&Database->lock);
+
+ next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
+
+ result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC);
+
+ /* ID allocated should not be 0. */
+ gcmkASSERT(result != 0);
+
+ if (result > 0)
+ {
+ Database->curr = *Id = result;
+ }
+
+ spin_unlock(&Database->lock);
+
+ idr_preload_end();
+
+ if (result < 0)
+ {
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#else
+again:
+ if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
+ {
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ spin_lock(&Database->lock);
+
+ next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
+
+ /* Try to get a id greater than 0. */
+ result = idr_get_new_above(&Database->idr, KernelPointer, next, Id);
+
+ if (!result)
+ {
+ Database->curr = *Id;
+ }
+
+ spin_unlock(&Database->lock);
+
+ if (result == -EAGAIN)
+ {
+ goto again;
+ }
+
+ if (result != 0)
+ {
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_QueryIntegerId(
+ IN gcsINTEGER_DB_PTR Database,
+ IN gctUINT32 Id,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gctPOINTER pointer;
+
+ spin_lock(&Database->lock);
+
+ pointer = idr_find(&Database->idr, Id);
+
+ spin_unlock(&Database->lock);
+
+ if (pointer)
+ {
+ *KernelPointer = pointer;
+ return gcvSTATUS_OK;
+ }
+ else
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_ERROR, gcvZONE_OS,
+ "%s(%d) Id = %d is not found",
+ __FUNCTION__, __LINE__, Id);
+
+ return gcvSTATUS_NOT_FOUND;
+ }
+}
+
+gceSTATUS
+_DestroyIntegerId(
+ IN gcsINTEGER_DB_PTR Database,
+ IN gctUINT32 Id
+ )
+{
+ spin_lock(&Database->lock);
+
+ idr_remove(&Database->idr, Id);
+
+ spin_unlock(&Database->lock);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_QueryProcessPageTable(
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Address
+ )
+{
+#ifndef CONFIG_DEBUG_SPINLOCK
+ spinlock_t *lock = NULL;
+#endif
+ gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ gctUINT32 offset = logical & ~PAGE_MASK;
+
+ if (is_vmalloc_addr(Logical))
+ {
+ *Address = page_to_phys(vmalloc_to_page(Logical)) + offset;
+
+ return gcvSTATUS_OK;
+ }
+
+ if (!current->mm)
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ pgd = pgd_offset(current->mm, logical);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ pud = pud_offset(pgd, logical);
+ if (pud_none(*pud) || pud_bad(*pud))
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ pmd = pmd_offset(pud, logical);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ {
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+#ifndef CONFIG_DEBUG_SPINLOCK
+ pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
+#else
+ spin_lock(&current->mm->page_table_lock);
+
+ pte = pte_offset_map(pmd, logical);
+#endif
+
+ if (!pte)
+ {
+#ifndef CONFIG_DEBUG_SPINLOCK
+ if (lock)
+ {
+ spin_unlock(lock);
+ }
+#else
+ spin_unlock(&current->mm->page_table_lock);
+#endif
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ if (!pte_present(*pte))
+ {
+#ifndef CONFIG_DEBUG_SPINLOCK
+ pte_unmap_unlock(pte, lock);
+#else
+ pte_unmap(pte);
+ spin_unlock(&current->mm->page_table_lock);
+#endif
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ *Address = (pte_pfn(*pte) << PAGE_SHIFT) | offset;
+#ifndef CONFIG_DEBUG_SPINLOCK
+ pte_unmap_unlock(pte, lock);
+#else
+ pte_unmap(pte);
+ spin_unlock(&current->mm->page_table_lock);
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
+static inline gceSTATUS
+outer_func(
+ gceCACHEOPERATION Type,
+ unsigned long Start,
+ unsigned long End
+ )
+{
+ switch (Type)
+ {
+ case gcvCACHE_CLEAN:
+ outer_clean_range(Start, End);
+ break;
+ case gcvCACHE_INVALIDATE:
+ outer_inv_range(Start, End);
+ break;
+ case gcvCACHE_FLUSH:
+ outer_flush_range(Start, End);
+ break;
+ default:
+ return gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** _HandleOuterCache
+**
+** Handle the outer cache for the specified addresses.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctPOINTER Physical
+** Physical address to flush.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+**
+** gceOUTERCACHE_OPERATION Type
+** Operation need to be execute.
+*/
+gceSTATUS
+_HandleOuterCache(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes,
+ IN gceCACHEOPERATION Type
+ )
+{
+ gceSTATUS status;
+ gctPHYS_ADDR_T paddr;
+ gctPOINTER vaddr;
+ gctUINT32 offset, bytes, left;
+
+ gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu",
+ Os, Logical, Bytes);
+
+ if (Physical != gcvINVALID_ADDRESS)
+ {
+ /* Non paged memory or gcvPOOL_USER surface */
+ paddr = (unsigned long) Physical;
+ gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
+ }
+ else
+ {
+ /* Non contiguous virtual memory */
+ vaddr = Logical;
+ left = Bytes;
+
+ while (left)
+ {
+ /* Handle (part of) current page. */
+ offset = (gctUINTPTR_T)vaddr & ~PAGE_MASK;
+
+ bytes = gcmMIN(left, PAGE_SIZE - offset);
+
+ gcmkONERROR(_QueryProcessPageTable(vaddr, &paddr));
+ gcmkONERROR(outer_func(Type, paddr, paddr + bytes));
+
+ vaddr = (gctUINT8_PTR)vaddr + bytes;
+ left -= bytes;
+ }
+ }
+
+ mb();
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gctBOOL
+_AllowAccess(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address
+ )
+{
+ gctUINT32 data;
+
+ /* Check external clock state. */
+ if (Os->clockStates[Core] == gcvFALSE)
+ {
+ gcmkPRINT("[galcore]: %s(%d) GPU[%d] External clock off", __FUNCTION__, __LINE__, Core);
+ return gcvFALSE;
+ }
+
+ /* Check internal clock state. */
+ if (Address == 0)
+ {
+ return gcvTRUE;
+ }
+
+ data = readl((gctUINT8 *)Os->device->registerBases[Core] + 0x0);
+
+ if ((data & 0x3) == 0x3)
+ {
+ gcmkPRINT("[galcore]: %s(%d) GPU[%d] Internal clock off", __FUNCTION__, __LINE__, Core);
+ return gcvFALSE;
+ }
+
+ return gcvTRUE;
+}
+
+static gceSTATUS
+_ShrinkMemory(
+ IN gckOS Os
+ )
+{
+ gcsPLATFORM * platform;
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Os=0x%X", Os);
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ platform = Os->device->platform;
+
+ if (platform && platform->ops->shrinkMemory)
+ {
+ status = platform->ops->shrinkMemory(platform);
+ }
+ else
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Construct
+**
+** Construct a new gckOS object.
+**
+** INPUT:
+**
+** gctPOINTER Context
+** Pointer to the gckGALDEVICE class.
+**
+** OUTPUT:
+**
+** gckOS * Os
+** Pointer to a variable that will hold the pointer to the gckOS object.
+*/
+gceSTATUS
+gckOS_Construct(
+ IN gctPOINTER Context,
+ OUT gckOS * Os
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gctINT i;
+
+ gcmkHEADER_ARG("Context=0x%X", Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+ /* Allocate the gckOS object. */
+ os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
+
+ if (os == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Zero the memory. */
+ gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
+
+ /* Initialize the gckOS object. */
+ os->object.type = gcvOBJ_OS;
+
+ /* Set device device. */
+ os->device = Context;
+
+ /* Set allocateCount to 0, gckOS_Allocate has not been used yet. */
+ atomic_set(&os->allocateCount, 0);
+
+ /* Initialize the memory lock. */
+ mutex_init(&os->mdlMutex);
+
+ INIT_LIST_HEAD(&os->mdlHead);
+
+ /* Get the kernel process ID. */
+ os->kernelProcessID = _GetProcessID();
+
+ /*
+ * Initialize the signal manager.
+ */
+
+ /* Initialize mutex. */
+ mutex_init(&os->signalMutex);
+
+ /* Initialize signal id database lock. */
+ spin_lock_init(&os->signalDB.lock);
+
+ /* Initialize signal id database. */
+ idr_init(&os->signalDB.idr);
+
+ /* Create a workqueue for os timer. */
+ os->workqueue = create_singlethread_workqueue("galcore workqueue");
+
+ if (os->workqueue == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ os->paddingPage = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
+ if (os->paddingPage == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ else
+ {
+ SetPageReserved(os->paddingPage);
+ }
+
+ for (i = 0; i < gcdMAX_GPU_COUNT; i++)
+ {
+ mutex_init(&os->registerAccessLocks[i]);
+ }
+
+ gckOS_ImportAllocators(os);
+
+#ifdef CONFIG_IOMMU_SUPPORT
+ if (((gckGALDEVICE)(os->device))->args.mmu == gcvFALSE)
+ {
+ /* Only use IOMMU when internal MMU is not enabled. */
+ status = gckIOMMU_Construct(os, &os->iommu);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): Fail to setup IOMMU",
+ __FUNCTION__, __LINE__
+ );
+ }
+ }
+#endif
+
+ /* Return pointer to the gckOS object. */
+ *Os = os;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Os=0x%X", *Os);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (os->workqueue != gcvNULL)
+ {
+ destroy_workqueue(os->workqueue);
+ }
+
+ kfree(os);
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Destroy
+**
+** Destroy an gckOS object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Destroy(
+ IN gckOS Os
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ if (Os->paddingPage != gcvNULL)
+ {
+ ClearPageReserved(Os->paddingPage);
+ __free_page(Os->paddingPage);
+ Os->paddingPage = gcvNULL;
+ }
+
+ /*
+ * Destroy the signal manager.
+ */
+
+ /* Wait for all works done. */
+ flush_workqueue(Os->workqueue);
+
+ /* Destory work queue. */
+ destroy_workqueue(Os->workqueue);
+
+ gckOS_FreeAllocators(Os);
+
+#ifdef CONFIG_IOMMU_SUPPORT
+ if (Os->iommu)
+ {
+ gckIOMMU_Destory(Os, Os->iommu);
+ }
+#endif
+
+ /* Flush the debug cache. */
+ gcmkDEBUGFLUSH(~0U);
+
+ /* Mark the gckOS object as unknown. */
+ Os->object.type = gcvOBJ_UNKNOWN;
+
+
+ /* Free the gckOS object. */
+ kfree(Os);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CreateKernelVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ gceSTATUS status;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gckALLOCATOR allocator = mdl->allocator;
+
+ gcmkHEADER();
+
+ *PageCount = mdl->numPages;
+
+ gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, Logical));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_DestroyKernelVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gckALLOCATOR allocator = mdl->allocator;
+
+ gcmkHEADER();
+
+ allocator->ops->UnmapKernel(allocator, mdl, Logical);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CreateUserVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ return gckOS_LockPages(Os, Physical, Bytes, gcvFALSE, Logical, PageCount);
+}
+
+gceSTATUS
+gckOS_DestroyUserVirtualMapping(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ return gckOS_UnlockPages(Os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckOS_Allocate
+**
+** Allocate memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Free
+**
+** Free allocated memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ gcmkONERROR(gckOS_FreeMemory(Os, Memory));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateMemory
+**
+** Allocate memory wrapper.
+**
+** INPUT:
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctPOINTER memory;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ if (Bytes > PAGE_SIZE)
+ {
+ memory = (gctPOINTER) vmalloc(Bytes);
+ }
+ else
+ {
+ memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
+ }
+
+ if (memory == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Increase count. */
+ atomic_inc(&Os->allocateCount);
+
+ /* Return pointer to the memory allocation. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeMemory
+**
+** Free allocated memory wrapper.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FreeMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gcmkHEADER_ARG("Memory=0x%X", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Free the memory from the OS pool. */
+ if (is_vmalloc_addr(Memory))
+ {
+ vfree(Memory);
+ }
+ else
+ {
+ kfree(Memory);
+ }
+
+ /* Decrease count. */
+ atomic_dec(&Os->allocateCount);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapMemory
+**
+** Map physical memory into the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the logical address of the
+** mapped memory.
+*/
+gceSTATUS
+gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ gceSTATUS status;
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL) Physical;
+ gckALLOCATOR allocator;
+ gctINT pid = _GetProcessID();
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ mutex_lock(&mdl->mapsMutex);
+
+ mdlMap = FindMdlMap(mdl, pid);
+
+ if (mdlMap == gcvNULL)
+ {
+ mdlMap = _CreateMdlMap(mdl, pid);
+
+ if (mdlMap == gcvNULL)
+ {
+ mutex_unlock(&mdl->mapsMutex);
+
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ allocator = mdl->allocator;
+
+ gcmkONERROR(
+ allocator->ops->MapUser(allocator,
+ mdl, gcvFALSE,
+ &mdlMap->vmaAddr));
+ }
+
+ mutex_unlock(&mdl->mapsMutex);
+
+ *Logical = mdlMap->vmaAddr;
+
+ gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapMemory
+**
+** Unmap physical memory out of the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
+ Os, Physical, Bytes, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_UnmapMemoryEx
+**
+** Unmap physical memory in the specified process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** gctUINT32 PID
+** Pid of the process that opened the device and mapped this memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapMemoryEx(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical,
+ IN gctUINT32 PID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
+ Os, Physical, Bytes, Logical, PID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PID != 0);
+
+ if (Logical)
+ {
+ mutex_lock(&mdl->mapsMutex);
+
+ mdlMap = FindMdlMap(mdl, PID);
+
+ if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
+ {
+ mutex_unlock(&mdl->mapsMutex);
+
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ _UnmapUserLogical(mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
+
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+
+ mutex_unlock(&mdl->mapsMutex);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserLogical
+**
+** Unmap user logical memory out of physical memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserLogical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
+ Os, Physical, Bytes, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateNonPagedMemory
+**
+** Allocate a number of pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that holds the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that hold the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that will hold the physical address of the
+** allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** allocation.
+*/
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctSIZE_T bytes;
+ gctINT numPages;
+ PLINUX_MDL mdl = gcvNULL;
+ PLINUX_MDL_MAP mdlMap = gcvNULL;
+ gctPOINTER addr;
+ gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+ gckALLOCATOR allocator;
+ gctUINT32 flag = gcvALLOC_FLAG_CONTIGUOUS;
+
+ gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+ Os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+ gcmkVERIFY_ARGUMENT(*Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Align number of bytes to page size. */
+ bytes = gcmALIGN(*Bytes, PAGE_SIZE);
+
+ /* Get total number of pages.. */
+ numPages = GetPageCount(bytes, 0);
+
+ /* Allocate mdl structure */
+ mdl = _CreateMdl();
+ if (mdl == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ if (Os->allocatorLimitMarker)
+ {
+ flag |= gcvALLOC_FLAG_CMA_LIMIT;
+ }
+
+ /* Walk all allocators. */
+ list_for_each_entry(allocator, &Os->allocatorList, head)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d) flag = %x allocator->capability = %x",
+ __FUNCTION__, __LINE__, flag, allocator->capability);
+
+#ifndef NO_DMA_COHERENT
+ /* Point to dma coherent allocator. */
+ if (strcmp(allocator->name, "dma"))
+ {
+ /*!VIV:
+ * For historical issue, we force allocate all non-paged memory from
+ * dma coherent pool when it is not disabled.
+ *
+ * The code below changes the scheme a little: force allocate
+ * non-paged memory whose size is larger than 1 pages, can try other
+ * allocators otherwise. This is to save memory usage of dma
+ * coherent pool.
+ */
+ if (((flag & allocator->capability) != flag) ||
+ (numPages > 1))
+ {
+ continue;
+ }
+ }
+#else
+ if ((flag & allocator->capability) != flag)
+ {
+ continue;
+ }
+#endif
+ status = allocator->ops->Alloc(allocator, mdl, numPages, flag);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ mdl->allocator = allocator;
+ break;
+ }
+ }
+
+ /* Check status. */
+ gcmkONERROR(status);
+
+ mdl->numPages = numPages;
+
+ mdl->contiguous = gcvTRUE;
+
+ gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, &addr));
+
+ /* Trigger a page fault. */
+ memset(addr, 0, numPages * PAGE_SIZE);
+
+ mdl->addr = addr;
+
+ if (InUserSpace)
+ {
+ mdlMap = _CreateMdlMap(mdl, _GetProcessID());
+
+ if (mdlMap == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ gcmkONERROR(allocator->ops->MapUser(allocator, mdl, gcvFALSE, &mdlMap->vmaAddr));
+
+ *Logical = mdlMap->vmaAddr;
+ }
+ else
+ {
+ *Logical = addr;
+ }
+
+ mutex_lock(&Os->mdlMutex);
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+ list_add_tail(&mdl->link, &Os->mdlHead);
+
+ mutex_unlock(&Os->mdlMutex);
+
+ /* Return allocated memory. */
+ *Bytes = bytes;
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
+ *Bytes, *Physical, *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mdlMap != gcvNULL)
+ {
+ /* Free LINUX_MDL_MAP. */
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ }
+
+ if (mdl != gcvNULL)
+ {
+ /* Free LINUX_MDL. */
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_FreeNonPagedMemory
+**
+** Free previously allocated and mapped pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes allocated.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocated memory.
+**
+** gctPOINTER Logical
+** Logical address of the allocated memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL mdl;
+
+ gckALLOCATOR allocator;
+
+ gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
+ Os, Bytes, Physical, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Convert physical address into a pointer to a MDL. */
+ mdl = (PLINUX_MDL) Physical;
+
+ allocator = mdl->allocator;
+
+ allocator->ops->UnmapKernel(allocator, mdl, mdl->addr);
+ allocator->ops->Free(allocator, mdl);
+
+ mutex_lock(&Os->mdlMutex);
+
+ /* Remove the node from global list.. */
+ list_del(&mdl->link);
+
+ mutex_unlock(&Os->mdlMutex);
+
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReadRegister
+**
+** Read data from a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** OUTPUT:
+**
+** gctUINT32 * Data
+** Pointer to a variable that receives the data read from the register.
+*/
+gceSTATUS
+gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ )
+{
+ return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
+}
+
+gceSTATUS
+gckOS_ReadRegisterEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
+
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ if (!in_irq())
+ {
+ mutex_lock(&Os->registerAccessLocks[Core]);
+ }
+
+ gcmkBUG_ON(!_AllowAccess(Os, Core, Address), __FUNCTION__, __LINE__);
+
+ *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+
+ if (!in_irq())
+ {
+ mutex_unlock(&Os->registerAccessLocks[Core]);
+ }
+
+#if gcdDUMP_AHB_ACCESS
+ gcmkPRINT("@[RD %d] %08x %08x", Core, Address, *Data);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_WriteRegister
+**
+** Write data to a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ )
+{
+ return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
+}
+
+gceSTATUS
+gckOS_WriteRegisterEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
+
+ gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
+
+ if (!in_interrupt())
+ {
+ mutex_lock(&Os->registerAccessLocks[Core]);
+ }
+
+ gcmkBUG_ON(!_AllowAccess(Os, Core, Address), __FUNCTION__, __LINE__);
+
+ writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+
+ if (!in_interrupt())
+ {
+ mutex_unlock(&Os->registerAccessLocks[Core]);
+ }
+
+#if gcdDUMP_AHB_ACCESS
+ gcmkPRINT("@[WR %d] %08x %08x", Core, Address, Data);
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPageSize
+**
+** Get the system's page size.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * PageSize
+** Pointer to a variable that will receive the system's page size.
+*/
+gceSTATUS gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
+
+ /* Return the page size. */
+ *PageSize = (gctSIZE_T) PAGE_SIZE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*PageSize=%d", *PageSize);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddressProcess
+**
+** Get the physical system address of a corresponding virtual address for a
+** given process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** gctUINT32 ProcessID
+** Process ID.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+_GetPhysicalAddressProcess(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctUINT32 ProcessID,
+ OUT gctPHYS_ADDR_T * Address
+ )
+{
+ PLINUX_MDL mdl;
+ gctINT8_PTR base;
+ gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
+
+ gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ mutex_lock(&Os->mdlMutex);
+
+ /* First try the contiguous memory pool. */
+ if (Os->device->contiguousMapped)
+ {
+ base = (gctINT8_PTR) Os->device->contiguousBase;
+
+ if (((gctINT8_PTR) Logical >= base)
+ && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
+ )
+ {
+ /* Convert logical address into physical. */
+ *Address = Os->device->contiguousVidMem->baseAddress
+ + (gctINT8_PTR) Logical - base;
+ status = gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ /* Try the contiguous memory pool. */
+ mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
+
+ mutex_lock(&mdl->mapsMutex);
+
+ status = _ConvertLogical2Physical(Os, Logical, ProcessID, mdl, Address);
+
+ mutex_unlock(&mdl->mapsMutex);
+ }
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Walk all MDLs. */
+ list_for_each_entry(mdl, &Os->mdlHead, link)
+ {
+ mutex_lock(&mdl->mapsMutex);
+
+ status = _ConvertLogical2Physical(Os, Logical, ProcessID, mdl, Address);
+
+ mutex_unlock(&mdl->mapsMutex);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&Os->mdlMutex);
+
+ gcmkONERROR(status);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%p", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddress
+**
+** Get the physical system address of a corresponding virtual address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Address
+ )
+{
+ gceSTATUS status;
+ gctUINT32 processID;
+
+ gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Query page table of current process first. */
+ status = _QueryProcessPageTable(Logical, Address);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Get current process ID. */
+ processID = _GetProcessID();
+
+ /* Route through other function. */
+ gcmkONERROR(
+ _GetPhysicalAddressProcess(Os, Logical, processID, Address));
+ }
+
+ gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, *Address, Address));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%p", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_UserLogicalToPhysical
+**
+** Get the physical system address of a corresponding user virtual address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable that receives the 32-bit physical address.
+*/
+gceSTATUS gckOS_UserLogicalToPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Address
+ )
+{
+ return gckOS_GetPhysicalAddress(Os, Logical, Address);
+}
+
+#if gcdSECURE_USER
+static gceSTATUS
+gckOS_AddMapping(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+ gcsUSER_MAPPING_PTR map;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
+ Os, Physical, Logical, Bytes);
+
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(gcsUSER_MAPPING),
+ (gctPOINTER *) &map));
+
+ map->next = Os->userMap;
+ map->physical = Physical - Os->device->baseAddress;
+ map->logical = Logical;
+ map->bytes = Bytes;
+ map->start = (gctINT8_PTR) Logical;
+ map->end = map->start + Bytes;
+
+ Os->userMap = map;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckOS_RemoveMapping(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+ gcsUSER_MAPPING_PTR map, prev;
+
+ gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
+
+ for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
+ {
+ if ((map->logical == Logical) && (map->bytes == Bytes))
+ {
+ break;
+ }
+
+ prev = map;
+ }
+
+ if (map == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
+ }
+
+ if (prev == gcvNULL)
+ {
+ Os->userMap = map->next;
+ }
+ else
+ {
+ prev->next = map->next;
+ }
+
+ gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+_ConvertLogical2Physical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctUINT32 ProcessID,
+ IN PLINUX_MDL Mdl,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ gckALLOCATOR allocator = Mdl->allocator;
+ gctUINT32 offset;
+ gceSTATUS status = gcvSTATUS_NOT_FOUND;
+ gctINT8_PTR vBase;
+
+ /* TASK_SIZE is userspace - kernelspace virtual memory split. */
+ if ((gctUINTPTR_T)Logical >= TASK_SIZE)
+ {
+ /* Kernel virtual address. */
+ vBase = Mdl->addr;
+ }
+ else
+ {
+ /* User virtual address. */
+ PLINUX_MDL_MAP map;
+
+ map = FindMdlMap(Mdl, (gctINT) ProcessID);
+ vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
+ }
+
+ /* Is the given address within that range. */
+ if ((vBase != gcvNULL)
+ && ((gctINT8_PTR) Logical >= vBase)
+ && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
+ )
+ {
+ offset = (gctINT8_PTR) Logical - vBase;
+
+ allocator->ops->Physical(allocator, Mdl, offset, Physical);
+
+ status = gcvSTATUS_OK;
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPhysical
+**
+** Map a physical address into kernel space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Physical
+** Physical address of the memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the base address of the mapped
+** memory.
+*/
+gceSTATUS
+gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctPOINTER logical;
+ PLINUX_MDL mdl;
+ gctBOOL found = gcvFALSE;
+ gctUINT32 physical = Physical;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ mutex_lock(&Os->mdlMutex);
+
+ /* Go through our mapping to see if we know this physical address already. */
+ list_for_each_entry(mdl, &Os->mdlHead, link)
+ {
+ if (mdl->dmaHandle != 0)
+ {
+ if ((physical >= mdl->dmaHandle)
+ && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
+ )
+ {
+ *Logical = mdl->addr + (physical - mdl->dmaHandle);
+ found = gcvTRUE;
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&Os->mdlMutex);
+
+ if (!found)
+ {
+ unsigned long pfn = physical >> PAGE_SHIFT;
+
+ if (pfn_valid(pfn))
+ {
+ gctUINT32 offset = physical & ~PAGE_MASK;
+ struct page ** pages;
+ struct page * page;
+ gctUINT numPages;
+ gctINT i;
+
+ numPages = GetPageCount(PAGE_ALIGN(offset + Bytes), 0);
+
+ pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
+
+ if (!pages)
+ {
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ page = pfn_to_page(pfn);
+
+ for (i = 0; i < numPages; i++)
+ {
+ pages[i] = nth_page(page, i);
+ }
+
+ logical = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
+
+ kfree(pages);
+
+ if (logical == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): Failed to vmap",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Out of resources. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ logical += offset;
+ }
+ else
+ {
+ /* Map memory as cached memory. */
+ request_mem_region(physical, Bytes, "MapRegion");
+ logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
+
+ if (logical == gcvNULL)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): Failed to ioremap",
+ __FUNCTION__, __LINE__
+ );
+
+ /* Out of resources. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+ }
+
+ /* Return pointer to mapped memory. */
+ *Logical = logical;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapPhysical
+**
+** Unmap a previously mapped memory region from kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Pointer to the base address of the memory to unmap.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ PLINUX_MDL mdl;
+ gctBOOL found = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ mutex_lock(&Os->mdlMutex);
+
+ list_for_each_entry(mdl, &Os->mdlHead, link)
+ {
+ if (mdl->addr != gcvNULL)
+ {
+ if ((Logical >= (gctPOINTER)mdl->addr) &&
+ (Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE)))
+ {
+ found = gcvTRUE;
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&Os->mdlMutex);
+
+ if (!found)
+ {
+ /* Unmap the memory. */
+ vunmap((void *)((unsigned long)Logical & PAGE_MASK));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DeleteMutex
+**
+** Delete a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mute to be deleted.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
+
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Destroy the mutex. */
+ mutex_destroy((struct mutex *)Mutex);
+
+ /* Free the mutex structure. */
+ gcmkONERROR(gckOS_Free(Os, Mutex));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireMutex
+**
+** Acquire a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be acquired.
+**
+** gctUINT32 Timeout
+** Timeout value specified in milliseconds.
+** Specify the value of gcvINFINITE to keep the thread suspended
+** until the mutex has been acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
+
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ if (Timeout == gcvINFINITE)
+ {
+ /* Lock the mutex. */
+ mutex_lock(Mutex);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ for (;;)
+ {
+ /* Try to acquire the mutex. */
+ if (mutex_trylock(Mutex))
+ {
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ if (Timeout-- == 0)
+ {
+ break;
+ }
+
+ /* Wait for 1 millisecond. */
+ gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+ }
+
+ /* Timeout. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
+ return gcvSTATUS_TIMEOUT;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseMutex
+**
+** Release an acquired mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
+
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Release the mutex. */
+ mutex_unlock(Mutex);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchange
+**
+** Atomically exchange a pair of 32-bit values.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctINT32_PTR Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctINT32 NewValue
+** Specifies a new value for the 32-bit value pointed to by Target.
+**
+** OUT gctINT32_PTR OldValue
+** The old value of the 32-bit value pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchange(
+ IN gckOS Os,
+ IN OUT gctUINT32_PTR Target,
+ IN gctUINT32 NewValue,
+ OUT gctUINT32_PTR OldValue
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
+
+ /* Exchange the pair of 32-bit values. */
+ *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchangePtr
+**
+** Atomically exchange a pair of pointers.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctPOINTER * Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctPOINTER NewValue
+** Specifies a new value for the pointer pointed to by Target.
+**
+** OUT gctPOINTER * OldValue
+** The old value of the pointer pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchangePtr(
+ IN gckOS Os,
+ IN OUT gctPOINTER * Target,
+ IN gctPOINTER NewValue,
+ OUT gctPOINTER * OldValue
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
+
+ /* Exchange the pair of pointers. */
+ *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicSetMask
+**
+** Atomically set mask to Atom
+**
+** INPUT:
+** IN OUT gctPOINTER Atom
+** Pointer to the atom to set.
+**
+** IN gctUINT32 Mask
+** Mask to set.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomSetMask(
+ IN gctPOINTER Atom,
+ IN gctUINT32 Mask
+ )
+{
+ gctUINT32 oval, nval;
+
+ gcmkHEADER_ARG("Atom=0x%0x", Atom);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ do
+ {
+ oval = atomic_read((atomic_t *) Atom);
+ nval = oval | Mask;
+ }
+ while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomClearMask
+**
+** Atomically clear mask from Atom
+**
+** INPUT:
+** IN OUT gctPOINTER Atom
+** Pointer to the atom to clear.
+**
+** IN gctUINT32 Mask
+** Mask to clear.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomClearMask(
+ IN gctPOINTER Atom,
+ IN gctUINT32 Mask
+ )
+{
+ gctUINT32 oval, nval;
+
+ gcmkHEADER_ARG("Atom=0x%0x", Atom);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ do
+ {
+ oval = atomic_read((atomic_t *) Atom);
+ nval = oval & ~Mask;
+ }
+ while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomConstruct
+**
+** Create an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Atom
+** Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+ IN gckOS Os,
+ OUT gctPOINTER * Atom
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Allocate the atom. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
+
+ /* Initialize the atom. */
+ atomic_set((atomic_t *) *Atom, 0);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomDestroy
+**
+** Destroy an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+ IN gckOS Os,
+ OUT gctPOINTER Atom
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Free the atom. */
+ gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomGet
+**
+** Get the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Return the current value of atom. */
+ *Value = atomic_read((atomic_t *) Atom);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomSet
+**
+** Set the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** gctINT32 Value
+** The value of the atom.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomSet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ IN gctINT32 Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Set the current value of atom. */
+ atomic_set((atomic_t *) Atom, Value);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomIncrement
+**
+** Atomically increment the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable that receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Increment the atom. */
+ *Value = atomic_inc_return((atomic_t *) Atom) - 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomDecrement
+**
+** Atomically decrement the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable that receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Decrement the atom. */
+ *Value = atomic_dec_return((atomic_t *) Atom) + 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_Delay
+**
+** Delay execution of the current thread for a number of milliseconds.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Delay
+** Delay to sleep, specified in milliseconds.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
+
+ if (Delay > 0)
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+ ktime_t delay = ktime_set((Delay / MSEC_PER_SEC), (Delay % MSEC_PER_SEC) * NSEC_PER_MSEC);
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
+#else
+ msleep(Delay);
+#endif
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetTicks
+**
+** Get the number of milliseconds since the system started.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gctUINT32_PTR Time
+** Pointer to a variable to get time.
+**
+*/
+gceSTATUS
+gckOS_GetTicks(
+ OUT gctUINT32_PTR Time
+ )
+{
+ gcmkHEADER();
+
+ *Time = jiffies_to_msecs(jiffies);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_TicksAfter
+**
+** Compare time values got from gckOS_GetTicks.
+**
+** INPUT:
+** gctUINT32 Time1
+** First time value to be compared.
+**
+** gctUINT32 Time2
+** Second time value to be compared.
+**
+** OUTPUT:
+**
+** gctBOOL_PTR IsAfter
+** Pointer to a variable to result.
+**
+*/
+gceSTATUS
+gckOS_TicksAfter(
+ IN gctUINT32 Time1,
+ IN gctUINT32 Time2,
+ OUT gctBOOL_PTR IsAfter
+ )
+{
+ gcmkHEADER();
+
+ *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetTime
+**
+** Get the number of microseconds since the system started.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gctUINT64_PTR Time
+** Pointer to a variable to get time.
+**
+*/
+gceSTATUS
+gckOS_GetTime(
+ OUT gctUINT64_PTR Time
+ )
+{
+ struct timeval tv;
+ gcmkHEADER();
+
+ /* Return the time of day in microseconds. */
+ do_gettimeofday(&tv);
+ *Time = (tv.tv_sec * 1000000ULL) + tv.tv_usec;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MemoryBarrier
+**
+** Make sure the CPU has executed everything up to this point and the data got
+** written to the specified pointer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of memory that needs to be barriered.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+#if gcdNONPAGED_MEMORY_BUFFERABLE \
+ && defined (CONFIG_ARM) \
+ && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+ /* drain write buffer */
+ dsb();
+
+ /* drain outer cache's write buffer? */
+#else
+ mb();
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemory
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+ /* Allocate the memory. */
+ gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvALLOC_FLAG_NONE, Bytes, gcvNULL, Physical));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemoryEx
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Flag
+** Allocation attribute.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctUINT32 * Gid
+** Save the global ID for the piece of allocated memory.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctUINT32 Flag,
+ IN gctSIZE_T Bytes,
+ OUT gctUINT32 * Gid,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ gctINT numPages;
+ PLINUX_MDL mdl = gcvNULL;
+ gctSIZE_T bytes;
+ gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+ gckALLOCATOR allocator;
+
+ gcmkHEADER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+ bytes = gcmALIGN(Bytes, PAGE_SIZE);
+
+ numPages = GetPageCount(bytes, 0);
+
+ mdl = _CreateMdl();
+ if (mdl == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ if (Os->allocatorLimitMarker && (Flag & gcvALLOC_FLAG_CMA_LIMIT))
+ {
+ Flag &= ~gcvALLOC_FLAG_CACHEABLE;
+ }
+ else
+ {
+ Flag &= ~gcvALLOC_FLAG_CMA_LIMIT;
+ }
+
+ /* Walk all allocators. */
+ list_for_each_entry(allocator, &Os->allocatorList, head)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d) flag = %x allocator->capability = %x",
+ __FUNCTION__, __LINE__, Flag, allocator->capability);
+
+ if ((Flag & allocator->capability) != Flag)
+ {
+ continue;
+ }
+
+ status = allocator->ops->Alloc(allocator, mdl, numPages, Flag);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ mdl->allocator = allocator;
+ break;
+ }
+ }
+
+ /* Check status. */
+ gcmkONERROR(status);
+
+ mdl->dmaHandle = 0;
+ mdl->addr = 0;
+ mdl->numPages = numPages;
+ mdl->contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
+
+ if (Gid != gcvNULL)
+ {
+ *Gid = mdl->gid;
+ }
+
+ mutex_lock(&Os->mdlMutex);
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+ list_add_tail(&mdl->link, &Os->mdlHead);
+
+ mutex_unlock(&Os->mdlMutex);
+
+ /* Return physical address. */
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mdl != gcvNULL)
+ {
+ /* Free the memory. */
+ _DestroyMdl(mdl);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreePagedMemory
+**
+** Free memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ )
+{
+ PLINUX_MDL mdl = (PLINUX_MDL) Physical;
+ gckALLOCATOR allocator = (gckALLOCATOR)mdl->allocator;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ mutex_lock(&Os->mdlMutex);
+
+ /* Remove the node from global list. */
+ list_del(&mdl->link);
+
+ mutex_unlock(&Os->mdlMutex);
+
+ allocator->ops->Free(allocator, mdl);
+
+ /* Free the structure... */
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_LockPages
+**
+** Lock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** gctBOOL Cacheable
+** Cache mode of mapping.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the address of the mapped
+** memory.
+**
+** gctSIZE_T * PageCount
+** Pointer to a variable that receives the number of pages required for
+** the page table according to the GPU page size.
+*/
+gceSTATUS
+gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Cacheable,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ gceSTATUS status;
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+ gckALLOCATOR allocator;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
+
+ mdl = (PLINUX_MDL) Physical;
+ allocator = mdl->allocator;
+
+ mutex_lock(&mdl->mapsMutex);
+
+ mdlMap = FindMdlMap(mdl, _GetProcessID());
+
+ if (mdlMap == gcvNULL)
+ {
+ mdlMap = _CreateMdlMap(mdl, _GetProcessID());
+
+ if (mdlMap == gcvNULL)
+ {
+ mutex_unlock(&mdl->mapsMutex);
+
+ gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ status = allocator->ops->MapUser(allocator, mdl, Cacheable, &mdlMap->vmaAddr);
+
+ if (gcmIS_ERROR(status))
+ {
+ mutex_unlock(&mdl->mapsMutex);
+
+ gcmkFOOTER_ARG("*status=%d", status);
+ return status;
+ }
+ }
+
+ mdlMap->count++;
+
+ /* Convert pointer to MDL. */
+ *Logical = mdlMap->vmaAddr;
+
+ /* Return the page number according to the GPU page size. */
+ gcmkASSERT((PAGE_SIZE % 4096) == 0);
+ gcmkASSERT((PAGE_SIZE / 4096) >= 1);
+
+ *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
+
+ mutex_unlock(&mdl->mapsMutex);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPages
+**
+** Map paged memory into a page table.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T PageCount
+** Number of pages required for the physical address.
+**
+** gctPOINTER PageTable
+** Pointer to the page table to fill in.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+gceSTATUS
+gckOS_MapPagesEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctUINT32 Address,
+ IN gctPOINTER PageTable,
+ IN gctBOOL Writable,
+ IN gceSURF_TYPE Type
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ PLINUX_MDL mdl;
+ gctUINT32* table;
+ gctUINT32 offset = 0;
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ gckMMU mmu;
+ PLINUX_MDL mmuMdl;
+ gctUINT32 bytes;
+ gctPHYS_ADDR pageTablePhysical;
+#endif
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gckKERNEL kernel = Os->device->kernels[Core];
+ gckMMU mmu;
+#endif
+ gckALLOCATOR allocator;
+
+ gctUINT32 policyID = 0;
+ gctUINT32 axiConfig = 0;
+
+ gcsPLATFORM * platform = Os->device->platform;
+
+ gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
+ Os, Core, Physical, PageCount, PageTable);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+ /* Convert pointer to MDL. */
+ mdl = (PLINUX_MDL)Physical;
+
+ allocator = mdl->allocator;
+
+ gcmkASSERT(allocator != gcvNULL);
+
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): Physical->0x%X PageCount->0x%X",
+ __FUNCTION__, __LINE__,
+ (gctUINT32)(gctUINTPTR_T)Physical,
+ (gctUINT32)(gctUINTPTR_T)PageCount
+ );
+
+#if gcdPROCESS_ADDRESS_SPACE
+ gcmkONERROR(gckKERNEL_GetProcessMMU(kernel, &mmu));
+#endif
+
+ table = (gctUINT32 *)PageTable;
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ mmu = Os->device->kernels[Core]->mmu;
+ bytes = PageCount * sizeof(*table);
+ mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
+#endif
+
+ if (platform && platform->ops->getPolicyID)
+ {
+ platform->ops->getPolicyID(platform, Type, &policyID, &axiConfig);
+
+ gcmkBUG_ON(policyID > 0x1F, __FUNCTION__, __LINE__);
+
+ /* ID[3:0] is used in STLB. */
+ policyID &= 0xF;
+ }
+
+ /* Get all the physical addresses and store them in the page table. */
+
+ PageCount = PageCount / (PAGE_SIZE / 4096);
+
+ /* Try to get the user pages so DMA can happen. */
+ while (PageCount-- > 0)
+ {
+ gctUINT i;
+ gctPHYS_ADDR_T phys = ~0U;
+
+ allocator->ops->Physical(allocator, mdl, offset, &phys);
+
+ gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, phys, &phys));
+
+ if (policyID)
+ {
+ /* AxUSER must not used for address currently. */
+ gcmkBUG_ON((phys >> 32) & 0xF, __FUNCTION__, __LINE__);
+
+ /* Merge policyID to AxUSER[7:4].*/
+ phys |= ((gctPHYS_ADDR_T)policyID << 36);
+ }
+
+#ifdef CONFIG_IOMMU_SUPPORT
+ if (Os->iommu)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d): Setup mapping in IOMMU %x => %x",
+ __FUNCTION__, __LINE__,
+ Address + offset, phys
+ );
+
+ /* When use IOMMU, GPU use system PAGE_SIZE. */
+ gcmkONERROR(gckIOMMU_Map(
+ Os->iommu, Address + offset, phys, PAGE_SIZE));
+ }
+ else
+#endif
+ {
+
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ for (i = 0; i < (PAGE_SIZE / 4096); i++)
+ {
+ gcmkONERROR(
+ gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
+ phys + (i * 4096),
+ table++));
+ }
+ }
+ else
+#endif
+ {
+ for (i = 0; i < (PAGE_SIZE / 4096); i++)
+ {
+#if gcdPROCESS_ADDRESS_SPACE
+ gctUINT32_PTR pageTableEntry;
+ gckMMU_GetPageEntry(mmu, Address + offset + (i * 4096), &pageTableEntry);
+ gcmkONERROR(
+ gckMMU_SetPage(mmu,
+ phys + (i * 4096),
+ Writable,
+ pageTableEntry));
+#else
+ gcmkONERROR(
+ gckMMU_SetPage(Os->device->kernels[Core]->mmu,
+ phys + (i * 4096),
+ Writable,
+ table++));
+#endif
+ }
+ }
+ }
+
+ offset += PAGE_SIZE;
+ }
+
+#if gcdNONPAGED_MEMORY_CACHEABLE
+ /* Get physical address of pageTable */
+ pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
+ ((gctUINT32 *)PageTable - mmu->pageTableLogical));
+
+ /* Flush the mmu page table cache. */
+ gcmkONERROR(gckOS_CacheClean(
+ Os,
+ _GetProcessID(),
+ gcvNULL,
+ pageTablePhysical,
+ PageTable,
+ bytes
+ ));
+#endif
+
+OnError:
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_UnmapPages(
+ IN gckOS Os,
+ IN gctSIZE_T PageCount,
+ IN gctUINT32 Address
+ )
+{
+#ifdef CONFIG_IOMMU_SUPPORT
+ if (Os->iommu)
+ {
+ gcmkVERIFY_OK(gckIOMMU_Unmap(
+ Os->iommu, Address, PageCount * PAGE_SIZE));
+ }
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnlockPages
+**
+** Unlock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** gctPOINTER Logical
+** Address of the mapped memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnlockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gckALLOCATOR allocator = mdl->allocator;
+ gctINT pid = _GetProcessID();
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
+ Os, Physical, Bytes, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ mutex_lock(&mdl->mapsMutex);
+
+ list_for_each_entry(mdlMap, &mdl->mapsHead, link)
+ {
+ if ((mdlMap->vmaAddr != gcvNULL) && (mdlMap->pid == pid))
+ {
+ if (--mdlMap->count == 0)
+ {
+ allocator->ops->UnmapUser(
+ allocator,
+ mdlMap->vmaAddr,
+ mdl->numPages * PAGE_SIZE);
+
+ mdlMap->vmaAddr = gcvNULL;
+ }
+ }
+ }
+
+ mutex_unlock(&mdl->mapsMutex);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_AllocateContiguous
+**
+** Allocate memory from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that receives the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the logical address of the
+** memory allocation.
+*/
+gceSTATUS
+gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
+ Os, InUserSpace, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
+ gcmkVERIFY_ARGUMENT(*Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Same as non-paged memory for now. */
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
+ InUserSpace,
+ Bytes,
+ Physical,
+ Logical));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
+ *Bytes, *Physical, *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeContiguous
+**
+** Free memory allocated from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctPOINTER Logical
+** Logicval address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
+ Os, Physical, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Same of non-paged memory for now. */
+ gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdENABLE_VG
+/******************************************************************************
+**
+** gckOS_GetKernelLogical
+**
+** Return the kernel logical pointer that corresponods to the specified
+** hardware address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Hardware physical address.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the pointer in kernel address space.
+*/
+gceSTATUS
+gckOS_GetKernelLogical(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
+}
+
+gceSTATUS
+gckOS_GetKernelLogicalEx(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
+
+ do
+ {
+ gckGALDEVICE device;
+ gckKERNEL kernel;
+ gcePOOL pool;
+ gctUINT32 offset;
+ gctPOINTER logical;
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Os->device;
+
+ /* Kernel shortcut. */
+ kernel = device->kernels[Core];
+#if gcdENABLE_VG
+ if (Core == gcvCORE_VG)
+ {
+ gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
+ kernel->vg->hardware, Address, &pool, &offset
+ ));
+ }
+ else
+#endif
+ {
+ /* Split the memory address into a pool type and offset. */
+ gcmkERR_BREAK(gckHARDWARE_SplitMemory(
+ kernel->hardware, Address, &pool, &offset
+ ));
+ }
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ logical = device->contiguousBase;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ gcmkFOOTER();
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Build logical address of specified address. */
+ * KernelPointer = ((gctUINT8_PTR) logical) + offset;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckOS_MapUserPointer
+**
+** Map a pointer from the user process into the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be mapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be mapped.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the mapped pointer in kernel address
+** space.
+*/
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+ *KernelPointer = Pointer;
+
+ gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserPointer
+**
+** Unmap a user process pointer from the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be unmapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be unmapped.
+**
+** gctPOINTER KernelPointer
+** Pointer in kernel address space that needs to be unmapped.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
+ Os, Pointer, Size, KernelPointer);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_QueryNeedCopy
+**
+** Query whether the memory can be accessed or mapped directly or it has to be
+** copied.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID of the current process.
+**
+** OUTPUT:
+**
+** gctBOOL_PTR NeedCopy
+** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
+** gcvFALSE if the memory can be accessed or mapped dircetly.
+*/
+gceSTATUS
+gckOS_QueryNeedCopy(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ OUT gctBOOL_PTR NeedCopy
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
+
+ /* We need to copy data. */
+ *NeedCopy = gcvTRUE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CopyFromUserData
+**
+** Copy data from user to kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER KernelPointer
+** Pointer to kernel memory.
+**
+** gctPOINTER Pointer
+** Pointer to user memory.
+**
+** gctSIZE_T Size
+** Number of bytes to copy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_CopyFromUserData(
+ IN gckOS Os,
+ IN gctPOINTER KernelPointer,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
+ Os, KernelPointer, Pointer, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+
+ /* Copy data from user. */
+ if (copy_from_user(KernelPointer, Pointer, Size) != 0)
+ {
+ /* Could not copy all the bytes. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_CopyToUserData
+**
+** Copy data from kernel to user memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER KernelPointer
+** Pointer to kernel memory.
+**
+** gctPOINTER Pointer
+** Pointer to user memory.
+**
+** gctSIZE_T Size
+** Number of bytes to copy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_CopyToUserData(
+ IN gckOS Os,
+ IN gctPOINTER KernelPointer,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
+ Os, KernelPointer, Pointer, Size);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+
+ /* Copy data to user. */
+ if (copy_to_user(Pointer, KernelPointer, Size) != 0)
+ {
+ /* Could not copy all the bytes. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WriteMemory
+**
+** Write data to a memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of the memory to write to.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WriteMemory(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Write memory. */
+ if (access_ok(VERIFY_WRITE, Address, 4))
+ {
+ /* User address. */
+ if (put_user(Data, (gctUINT32*)Address))
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
+ }
+ }
+ else
+ {
+ /* Kernel address. */
+ *(gctUINT32 *)Address = Data;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_ReadMappedPointer(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32_PTR Data
+ )
+{
+ gceSTATUS status;
+ gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Write memory. */
+ if (access_ok(VERIFY_READ, Address, 4))
+ {
+ /* User address. */
+ if (get_user(*Data, (gctUINT32*)Address))
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
+ }
+ }
+ else
+ {
+ /* Kernel address. */
+ *Data = *(gctUINT32_PTR)Address;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapUserMemory
+**
+** Lock down a user buffer and return an DMA'able address to be used by the
+** hardware to access it.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to lock down.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to lock down.
+**
+** OUTPUT:
+**
+** gctPOINTER * Info
+** Pointer to variable receiving the information record required by
+** gckOS_UnmapUserMemory.
+**
+** gctUINT32_PTR Address
+** Pointer to a variable that will receive the address DMA'able by the
+** hardware.
+*/
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserMemory
+**
+** Unlock a user buffer and that was previously locked down by
+** gckOS_MapUserMemory.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to unlock.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to unlock.
+**
+** gctPOINTER Info
+** Information record returned by gckOS_MapUserMemory.
+**
+** gctUINT32_PTR Address
+** The address returned by gckOS_MapUserMemory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetBaseAddress
+**
+** Get the base address for the physical memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR BaseAddress
+** Pointer to a variable that will receive the base address.
+*/
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Return base address. */
+ *BaseAddress = Os->device->baseAddress;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ )
+{
+ return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
+}
+
+gceSTATUS
+gckOS_SuspendInterruptEx(
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ disable_irq(Os->device->irqLines[Core]);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ )
+{
+ return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
+}
+
+gceSTATUS
+gckOS_ResumeInterruptEx(
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ enable_irq(Os->device->irqLines[Core]);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
+ Destination, Source, Bytes);
+
+ gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Source != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memcpy(Destination, Source, Bytes);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
+
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memset(Memory, 0, Bytes);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************* Cache Control ********************************
+*******************************************************************************/
+
+/*******************************************************************************
+** gckOS_CacheClean
+**
+** Clean the cache for the specified addresses. The GPU is going to need the
+** data. If the system is allocating memory as non-cachable, this function can
+** be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID Logical belongs.
+**
+** gctPHYS_ADDR Handle
+** Physical address handle. If gcvNULL it is video memory.
+**
+** gctPOINTER Physical
+** Physical address to flush.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+
+/*
+
+Following patch can be applied to kernel in case cache API is not exported.
+
+diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
+index 054b491..e9e74ec 100644
+--- a/arch/arm/mm/proc-syms.c
++++ b/arch/arm/mm/proc-syms.c
+@@ -30,6 +30,9 @@ EXPORT_SYMBOL(__cpuc_flush_user_all);
+ EXPORT_SYMBOL(__cpuc_flush_user_range);
+ EXPORT_SYMBOL(__cpuc_coherent_kern_range);
+ EXPORT_SYMBOL(__cpuc_flush_dcache_area);
++EXPORT_SYMBOL(__glue(_CACHE,_dma_map_area));
++EXPORT_SYMBOL(__glue(_CACHE,_dma_unmap_area));
++EXPORT_SYMBOL(__glue(_CACHE,_dma_flush_range));
+ #else
+ EXPORT_SYMBOL(cpu_cache);
+ #endif
+
+*/
+gceSTATUS
+gckOS_CacheClean(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Handle,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcsPLATFORM * platform;
+
+ gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=%p Bytes=%lu",
+ Os, ProcessID, Handle, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ platform = Os->device->platform;
+
+ if (platform && platform->ops->cache)
+ {
+ platform->ops->cache(
+ platform,
+ ProcessID,
+ Handle,
+ Physical,
+ Logical,
+ Bytes,
+ gcvCACHE_CLEAN
+ );
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+
+#if defined (CONFIG_ARM)
+ /* Inner cache. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+ dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
+# else
+ dmac_clean_range(Logical, Logical + Bytes);
+# endif
+
+#elif defined(CONFIG_ARM64)
+ __dma_map_area(Logical, Bytes, DMA_TO_DEVICE);
+#endif
+
+#if defined(CONFIG_OUTER_CACHE)
+ /* Outer cache. */
+ _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_CLEAN);
+#endif
+
+#elif defined(CONFIG_MIPS)
+
+ dma_cache_wback((unsigned long) Logical, Bytes);
+
+#elif defined(CONFIG_PPC)
+
+#else
+ dma_sync_single_for_device(
+ gcvNULL,
+ (dma_addr_t)Physical,
+ Bytes,
+ DMA_TO_DEVICE);
+#endif
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** gckOS_CacheInvalidate
+**
+** Invalidate the cache for the specified addresses. The GPU is going to need
+** data. If the system is allocating memory as non-cachable, this function can
+** be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID Logical belongs.
+**
+** gctPHYS_ADDR Handle
+** Physical address handle. If gcvNULL it is video memory.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheInvalidate(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Handle,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcsPLATFORM * platform;
+
+ gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=%p Bytes=%lu",
+ Os, ProcessID, Handle, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ platform = Os->device->platform;
+
+ if (platform && platform->ops->cache)
+ {
+ platform->ops->cache(
+ platform,
+ ProcessID,
+ Handle,
+ Physical,
+ Logical,
+ Bytes,
+ gcvCACHE_INVALIDATE
+ );
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+
+#if defined (CONFIG_ARM)
+ /* Inner cache. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+ dmac_unmap_area(Logical, Bytes, DMA_FROM_DEVICE);
+# else
+ dmac_inv_range(Logical, Logical + Bytes);
+# endif
+#elif defined(CONFIG_ARM64)
+ __dma_unmap_area(Logical, Bytes, DMA_FROM_DEVICE);
+#endif
+
+#if defined(CONFIG_OUTER_CACHE)
+ /* Outer cache. */
+ _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
+#endif
+
+#elif defined(CONFIG_MIPS)
+ dma_cache_inv((unsigned long) Logical, Bytes);
+#elif defined(CONFIG_PPC)
+#else
+ dma_sync_single_for_device(
+ gcvNULL,
+ (dma_addr_t)Physical,
+ Bytes,
+ DMA_FROM_DEVICE);
+#endif
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** gckOS_CacheFlush
+**
+** Clean the cache for the specified addresses and invalidate the lines as
+** well. The GPU is going to need and modify the data. If the system is
+** allocating memory as non-cachable, this function can be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctUINT32 ProcessID
+** Process ID Logical belongs.
+**
+** gctPHYS_ADDR Handle
+** Physical address handle. If gcvNULL it is video memory.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheFlush(
+ IN gckOS Os,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Handle,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcsPLATFORM * platform;
+
+ gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=%p Bytes=%lu",
+ Os, ProcessID, Handle, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ platform = Os->device->platform;
+
+ if (platform && platform->ops->cache)
+ {
+ platform->ops->cache(
+ platform,
+ ProcessID,
+ Handle,
+ Physical,
+ Logical,
+ Bytes,
+ gcvCACHE_FLUSH
+ );
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#if defined (CONFIG_ARM)
+ /* Inner cache. */
+ dmac_flush_range(Logical, Logical + Bytes);
+#elif defined (CONFIG_ARM64)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+ __dma_flush_area(Logical, Bytes);
+#else
+ __dma_flush_range(Logical, Logical + Bytes);
+#endif
+#endif
+
+#if defined(CONFIG_OUTER_CACHE)
+ /* Outer cache. */
+ _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_FLUSH);
+#endif
+
+#elif defined(CONFIG_MIPS)
+ dma_cache_wback_inv((unsigned long) Logical, Bytes);
+#elif defined(CONFIG_PPC)
+#else
+ dma_sync_single_for_device(
+ gcvNULL,
+ (dma_addr_t)Physical,
+ Bytes,
+ DMA_BIDIRECTIONAL);
+#endif
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************* Broadcasting *********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Broadcast
+**
+** System hook for broadcast events from the kernel driver.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gceBROADCAST Reason
+** Reason for the broadcast. Can be one of the following values:
+**
+** gcvBROADCAST_GPU_IDLE
+** Broadcasted when the kernel driver thinks the GPU might be
+** idle. This can be used to handle power management.
+**
+** gcvBROADCAST_GPU_COMMIT
+** Broadcasted when any client process commits a command
+** buffer. This can be used to handle power management.
+**
+** gcvBROADCAST_GPU_STUCK
+** Broadcasted when the kernel driver hits the timeout waiting
+** for the GPU.
+**
+** gcvBROADCAST_FIRST_PROCESS
+** First process is trying to connect to the kernel.
+**
+** gcvBROADCAST_LAST_PROCESS
+** Last process has detached from the kernel.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ switch (Reason)
+ {
+ case gcvBROADCAST_FIRST_PROCESS:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
+ break;
+
+ case gcvBROADCAST_LAST_PROCESS:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
+
+ /* Put GPU OFF. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware,
+ gcvPOWER_OFF_BROADCAST));
+ break;
+
+ case gcvBROADCAST_GPU_IDLE:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
+
+ /* Put GPU IDLE. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware,
+#if gcdPOWER_SUSPEND_WHEN_IDLE
+ gcvPOWER_SUSPEND_BROADCAST));
+#else
+ gcvPOWER_IDLE_BROADCAST));
+#endif
+
+ /* Add idle process DB. */
+ gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
+ 1,
+ gcvDB_IDLE,
+ gcvNULL, gcvNULL, 0));
+ break;
+
+ case gcvBROADCAST_GPU_COMMIT:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
+
+ /* Add busy process DB. */
+ gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
+ 0,
+ gcvDB_IDLE,
+ gcvNULL, gcvNULL, 0));
+
+ /* Put GPU ON. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
+ break;
+
+ case gcvBROADCAST_GPU_STUCK:
+ gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
+ gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+ break;
+
+ case gcvBROADCAST_AXI_BUS_ERROR:
+ gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
+ gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
+ gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+ break;
+
+ case gcvBROADCAST_OUT_OF_MEMORY:
+ gcmkTRACE_N(gcvLEVEL_INFO, 0, "gcvBROADCAST_OUT_OF_MEMORY\n");
+
+ status = _ShrinkMemory(Os);
+
+ if (status == gcvSTATUS_NOT_SUPPORTED)
+ {
+ goto OnError;
+ }
+
+ gcmkONERROR(status);
+
+ break;
+
+ default:
+ /* Skip unimplemented broadcast. */
+ break;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_BroadcastHurry
+**
+** The GPU is running too slow.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT Urgency
+** The higher the number, the higher the urgency to speed up the GPU.
+** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_BroadcastHurry(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT Urgency
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
+
+ /* Do whatever you need to do to speed up the GPU now. */
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_BroadcastCalibrateSpeed
+**
+** Calibrate the speed of the GPU.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT Idle, Time
+** Idle/Time will give the percentage the GPU is idle, so you can use
+** this to calibrate the working point of the GPU.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_BroadcastCalibrateSpeed(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gctUINT Idle,
+ IN gctUINT Time
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
+ Os, Hardware, Idle, Time);
+
+ /* Do whatever you need to do to callibrate the GPU speed. */
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************** Semaphores **********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_CreateSemaphore
+**
+** Create a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Semaphore
+** Pointer to the variable that will receive the created semaphore.
+*/
+gceSTATUS
+gckOS_CreateSemaphore(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ )
+{
+ gceSTATUS status;
+ struct semaphore *sem = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Allocate the semaphore structure. */
+ sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
+ if (sem == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Initialize the semaphore. */
+ sema_init(sem, 1);
+
+ /* Return to caller. */
+ *Semaphore = (gctPOINTER) sem;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireSemaphore
+**
+** Acquire a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Acquire the semaphore. */
+ down((struct semaphore *) Semaphore);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_TryAcquireSemaphore
+**
+** Try to acquire a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_TryAcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Acquire the semaphore. */
+ if (down_trylock((struct semaphore *) Semaphore))
+ {
+ /* Timeout. */
+ status = gcvSTATUS_TIMEOUT;
+ gcmkFOOTER();
+ return status;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseSemaphore
+**
+** Release a previously acquired semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ReleaseSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Release the semaphore. */
+ up((struct semaphore *) Semaphore);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySemaphore
+**
+** Destroy a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Free the sempahore structure. */
+ kfree(Semaphore);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetProcessID
+**
+** Get current process ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ProcessID
+** Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+ OUT gctUINT32_PTR ProcessID
+ )
+{
+ /* Get process ID. */
+ *ProcessID = _GetProcessID();
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetThreadID
+**
+** Get current thread ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ThreadID
+** Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+ OUT gctUINT32_PTR ThreadID
+ )
+{
+ /* Get thread ID. */
+ if (ThreadID != gcvNULL)
+ {
+ *ThreadID = _GetThreadID();
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetGPUPower
+**
+** Set the power of the GPU on or off.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gceCORE Core
+** GPU whose power is set.
+**
+** gctBOOL Clock
+** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+** gctBOOL Power
+** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ )
+{
+ gcsPLATFORM * platform;
+
+ gctBOOL powerChange = gcvFALSE;
+ gctBOOL clockChange = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ platform = Os->device->platform;
+
+ powerChange = (Power != Os->powerStates[Core]);
+
+ clockChange = (Clock != Os->clockStates[Core]);
+
+ if (powerChange && (Power == gcvTRUE))
+ {
+ if (platform && platform->ops->setPower)
+ {
+ gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
+ }
+
+ Os->powerStates[Core] = Power;
+ }
+
+ if (clockChange)
+ {
+ mutex_lock(&Os->registerAccessLocks[Core]);
+
+ if (platform && platform->ops->setClock)
+ {
+ gcmkVERIFY_OK(platform->ops->setClock(platform, Core, Clock));
+ }
+
+ Os->clockStates[Core] = Clock;
+
+ mutex_unlock(&Os->registerAccessLocks[Core]);
+ }
+
+ if (powerChange && (Power == gcvFALSE))
+ {
+ if (platform && platform->ops->setPower)
+ {
+ gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
+ }
+
+ Os->powerStates[Core] = Power;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ResetGPU
+**
+** Reset the GPU.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose power is set.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ResetGPU(
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
+ gcsPLATFORM * platform;
+
+ gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ platform = Os->device->platform;
+
+ if (platform && platform->ops->reset)
+ {
+ status = platform->ops->reset(platform, Core);
+ }
+
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_PrepareGPUFrequency
+**
+** Prepare to set GPU frequency and voltage.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose frequency and voltage will be set.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_PrepareGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_FinishGPUFrequency
+**
+** Finish GPU frequency setting.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose frequency and voltage is set.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FinishGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_QueryGPUFrequency
+**
+** Query the current frequency of the GPU.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose power is set.
+**
+** gctUINT32 * Frequency
+** Pointer to a gctUINT32 to obtain current frequency, in MHz.
+**
+** gctUINT8 * Scale
+** Pointer to a gctUINT8 to obtain current scale(1 - 64).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_QueryGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctUINT32 * Frequency,
+ OUT gctUINT8 * Scale
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetGPUFrequency
+**
+** Set frequency and voltage of the GPU.
+**
+** 1. DVFS manager gives the target scale of full frequency, BSP must find
+** a real frequency according to this scale and board's configure.
+**
+** 2. BSP should find a suitable voltage for this frequency.
+**
+** 3. BSP must make sure setting take effect before this function returns.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gckCORE Core
+** GPU whose power is set.
+**
+** gctUINT8 Scale
+** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
+** full frequency and 64 means 64/64 of full frequency.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUFrequency(
+ IN gckOS Os,
+ IN gceCORE Core,
+ IN gctUINT8 Scale
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*----------------------------------------------------------------------------*/
+/*----- Profile --------------------------------------------------------------*/
+
+gceSTATUS
+gckOS_GetProfileTick(
+ OUT gctUINT64_PTR Tick
+ )
+{
+ struct timespec time;
+
+ ktime_get_ts(&time);
+
+ *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_QueryProfileTickRate(
+ OUT gctUINT64_PTR TickRate
+ )
+{
+ struct timespec res;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+ res.tv_sec = 0;
+ res.tv_nsec = hrtimer_resolution;
+#else
+ hrtimer_get_res(CLOCK_MONOTONIC, &res);
+#endif
+
+ *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
+
+ return gcvSTATUS_OK;
+}
+
+gctUINT32
+gckOS_ProfileToMS(
+ IN gctUINT64 Ticks
+ )
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
+ return div_u64(Ticks, 1000000);
+#else
+ gctUINT64 rem = Ticks;
+ gctUINT64 b = 1000000;
+ gctUINT64 res, d = 1;
+ gctUINT32 high = rem >> 32;
+
+ /* Reduce the thing a bit first */
+ res = 0;
+ if (high >= 1000000)
+ {
+ high /= 1000000;
+ res = (gctUINT64) high << 32;
+ rem -= (gctUINT64) (high * 1000000) << 32;
+ }
+
+ while (((gctINT64) b > 0) && (b < rem))
+ {
+ b <<= 1;
+ d <<= 1;
+ }
+
+ do
+ {
+ if (rem >= b)
+ {
+ rem -= b;
+ res += d;
+ }
+
+ b >>= 1;
+ d >>= 1;
+ }
+ while (d);
+
+ return (gctUINT32) res;
+#endif
+}
+
+/******************************************************************************\
+******************************* Signal Management ******************************
+\******************************************************************************/
+
+#undef _GC_OBJ_ZONE
+#define _GC_OBJ_ZONE gcvZONE_SIGNAL
+
+/*******************************************************************************
+**
+** gckOS_CreateSignal
+**
+** Create a new signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+**
+** OUTPUT:
+**
+** gctSIGNAL * Signal
+** Pointer to a variable receiving the created gctSIGNAL.
+*/
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ /* Create an event structure. */
+ signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
+
+ if (signal == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Save the process ID. */
+ signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
+ signal->manualReset = ManualReset;
+ init_completion(&signal->obj);
+ atomic_set(&signal->ref, 1);
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+ signal->timeline = gcvNULL;
+# else
+ signal->fence = gcvNULL;
+# endif
+#endif
+
+ gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
+
+ *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
+
+ gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (signal != gcvNULL)
+ {
+ kfree(signal);
+ }
+
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySignal
+**
+** Destroy a signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ mutex_lock(&Os->signalMutex);
+ acquired = gcvTRUE;
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
+
+ if (atomic_dec_and_test(&signal->ref))
+ {
+ gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
+
+ /* Free the sgianl. */
+ kfree(signal);
+ }
+
+ mutex_unlock(&Os->signalMutex);
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ mutex_unlock(&Os->signalMutex);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Signal
+**
+** Set a state of the specified signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+#if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+ struct sync_timeline * timeline = gcvNULL;
+# else
+ struct fence * fence = gcvNULL;
+# endif
+#endif
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ mutex_lock(&Os->signalMutex);
+ acquired = gcvTRUE;
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
+
+ if (State)
+ {
+ /* Set the event to a signaled state. */
+ complete(&signal->obj);
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+ timeline = signal->timeline;
+# else
+ fence = signal->fence;
+ signal->fence = NULL;
+# endif
+#endif
+ }
+ else
+ {
+ /* Set the event to an unsignaled state. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
+ reinit_completion(&signal->obj);
+#else
+ INIT_COMPLETION(signal->obj);
+#endif
+ }
+
+ mutex_unlock(&Os->signalMutex);
+ acquired = gcvFALSE;
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+ /* Signal timeline. */
+ if (timeline)
+ {
+ sync_timeline_signal(timeline);
+ }
+# else
+ if (fence)
+ {
+ fence_signal(fence);
+ fence_put(fence);
+ }
+# endif
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ mutex_unlock(&Os->signalMutex);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_SetSignalVG(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctSIGNAL Signal
+ )
+{
+ gceSTATUS status;
+ gctINT result;
+ struct task_struct * userTask;
+ struct siginfo info;
+
+ userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
+
+ if (userTask != gcvNULL)
+ {
+ info.si_signo = 48;
+ info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
+ info.si_pid = 0;
+ info.si_uid = 0;
+ info.si_ptr = (gctPOINTER) Signal;
+
+ /* Signals with numbers between 32 and 63 are real-time,
+ send a real-time signal to the user process. */
+ result = send_sig_info(48, &info, userTask);
+
+ printk("gckOS_SetSignalVG:0x%x\n", result);
+ /* Error? */
+ if (result < 0)
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): an error has occurred.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+ else
+ {
+ status = gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): an error has occurred.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+
+ /* Return status. */
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckOS_UserSignal
+**
+** Set the specified signal which is owned by a process to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
+ Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
+
+ /* Signal. */
+ status = gckOS_Signal(Os, Signal, gcvTRUE);
+
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitSignal
+**
+** Wait for a signal to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL Interruptable,
+ IN gctUINT32 Wait
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gcsSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
+
+ might_sleep();
+
+#ifdef gcdRT_KERNEL
+ raw_spin_lock_irq(&signal->obj.wait.lock);
+#else
+ spin_lock_irq(&signal->obj.wait.lock);
+#endif
+ if (signal->obj.done)
+ {
+ if (!signal->manualReset)
+ {
+ signal->obj.done = 0;
+ }
+
+ status = gcvSTATUS_OK;
+ }
+ else if (Wait == 0)
+ {
+ status = gcvSTATUS_TIMEOUT;
+ }
+ else
+ {
+ /* Convert wait to milliseconds. */
+ long timeout = (Wait == gcvINFINITE)
+ ? MAX_SCHEDULE_TIMEOUT
+ : msecs_to_jiffies(Wait);
+
+#ifdef gcdRT_KERNEL
+ DEFINE_SWAITER(wait);
+#else
+ DECLARE_WAITQUEUE(wait, current);
+ wait.flags |= WQ_FLAG_EXCLUSIVE;
+#endif
+
+#ifdef gcdRT_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
+ __prepare_to_swait(&signal->obj.wait, &wait);
+#else
+ swait_prepare_locked(&signal->obj.wait, &wait);
+#endif
+#else
+ __add_wait_queue_tail(&signal->obj.wait, &wait);
+#endif
+ while (gcvTRUE)
+ {
+ if (Interruptable && signal_pending(current))
+ {
+ /* Interrupt received. */
+ status = gcvSTATUS_INTERRUPTED;
+ break;
+ }
+
+ __set_current_state(TASK_INTERRUPTIBLE);
+#ifdef gcdRT_KERNEL
+ raw_spin_unlock_irq(&signal->obj.wait.lock);
+#else
+ spin_unlock_irq(&signal->obj.wait.lock);
+#endif
+ timeout = schedule_timeout(timeout);
+#ifdef gcdRT_KERNEL
+ raw_spin_lock_irq(&signal->obj.wait.lock);
+#else
+ spin_lock_irq(&signal->obj.wait.lock);
+#endif
+ if (signal->obj.done)
+ {
+ if (!signal->manualReset)
+ {
+ signal->obj.done = 0;
+ }
+
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ if (timeout == 0)
+ {
+
+ status = gcvSTATUS_TIMEOUT;
+ break;
+ }
+ }
+
+#ifdef gcdRT_KERNEL
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4,4,0)
+ __finish_swait(&signal->obj.wait, &wait);
+#else
+ swait_finish_locked(&signal->obj.wait, &wait);
+#endif
+#else
+ __remove_wait_queue(&signal->obj.wait, &wait);
+#endif
+ }
+
+#ifdef gcdRT_KERNEL
+ raw_spin_unlock_irq(&signal->obj.wait.lock);
+#else
+ spin_unlock_irq(&signal->obj.wait.lock);
+#endif
+OnError:
+ /* Return status. */
+ gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
+ return status;
+}
+
+gceSTATUS
+_QuerySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ )
+{
+ /*
+ * This function is called by 'has_signaled' callback of sync_timeline.
+ * By design, 'has_signaled' could be called in interrupt context, but
+ * in current driver, it can be called only when 'gckOS_Signal' and
+ * 'gckOS_CreateNativeFence'. Thus its safe to use normal version of
+ * spinlock for 'Os->signalDB.lock' and 'signal->obj.wait.lock'.
+ */
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+
+ status = _QueryIntegerId(&Os->signalDB,
+ (gctUINT32)(gctUINTPTR_T)Signal,
+ (gctPOINTER)&signal);
+
+ if (gcmIS_SUCCESS(status))
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
+ status = completion_done(&signal->obj)
+ ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
+#else
+ spin_lock(&signal->obj.wait.lock);
+ status = signal->obj.done ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
+ spin_unlock(&signal->obj.wait.lock);
+#endif
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapSignal
+**
+** Map a signal in to the current process space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to tha gctSIGNAL to map.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** gctSIGNAL * MappedSignal
+** Pointer to a variable receiving the mapped gctSIGNAL.
+*/
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
+
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+ gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
+
+ mutex_lock(&Os->signalMutex);
+
+ gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+
+ if (atomic_inc_return(&signal->ref) <= 1)
+ {
+ /* The previous value is 0, it has been deleted. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ *MappedSignal = (gctSIGNAL) Signal;
+
+ mutex_unlock(&Os->signalMutex);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
+ return gcvSTATUS_OK;
+
+OnError:
+ mutex_unlock(&Os->signalMutex);
+
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapSignal
+**
+** Unmap a signal .
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to that gctSIGNAL mapped.
+*/
+gceSTATUS
+gckOS_UnmapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ )
+{
+ return gckOS_DestroySignal(Os, Signal);
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateUserSignal
+**
+** Create a new signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+**
+** OUTPUT:
+**
+** gctINT * SignalID
+** Pointer to a variable receiving the created signal's ID.
+*/
+gceSTATUS
+gckOS_CreateUserSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctINT * SignalID
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T signal;
+
+ /* Create a new signal. */
+ gcmkONERROR(gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
+ *SignalID = (gctINT) signal;
+
+OnError:
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroyUserSignal
+**
+** Destroy a signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** The signal's ID.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroyUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID
+ )
+{
+ return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitUserSignal
+**
+** Wait for a signal used in the user mode to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** Signal ID.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctUINT32 Wait
+ )
+{
+ return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, gcvTRUE, Wait);
+}
+
+/*******************************************************************************
+**
+** gckOS_SignalUserSignal
+**
+** Set a state of the specified signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** SignalID.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SignalUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctBOOL State
+ )
+{
+ return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
+}
+
+#if gcdENABLE_VG
+gceSTATUS
+gckOS_CreateSemaphoreVG(
+ IN gckOS Os,
+ OUT gctSEMAPHORE * Semaphore
+ )
+{
+ gceSTATUS status;
+ struct semaphore * newSemaphore;
+
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ do
+ {
+ /* Allocate the semaphore structure. */
+ newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
+ if (newSemaphore == gcvNULL)
+ {
+ gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Initialize the semaphore. */
+ sema_init(newSemaphore, 0);
+
+ /* Set the handle. */
+ * Semaphore = (gctSEMAPHORE) newSemaphore;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+
+gceSTATUS
+gckOS_IncrementSemaphore(
+ IN gckOS Os,
+ IN gctSEMAPHORE Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Increment the semaphore's count. */
+ up((struct semaphore *) Semaphore);
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_DecrementSemaphore(
+ IN gckOS Os,
+ IN gctSEMAPHORE Semaphore
+ )
+{
+ gceSTATUS status;
+ gctINT result;
+
+ gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ do
+ {
+ /* Decrement the semaphore's count. If the count is zero, wait
+ until it gets incremented. */
+ result = down_interruptible((struct semaphore *) Semaphore);
+
+ /* Signal received? */
+ if (result != 0)
+ {
+ status = gcvSTATUS_TERMINATE;
+ break;
+ }
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetSignal
+**
+** Set the specified signal to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetSignal(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctSIGNAL Signal
+ )
+{
+ gceSTATUS status;
+ gctINT result;
+ struct task_struct * userTask;
+ struct siginfo info;
+
+ userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
+
+ if (userTask != gcvNULL)
+ {
+ info.si_signo = 48;
+ info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
+ info.si_pid = 0;
+ info.si_uid = 0;
+ info.si_ptr = (gctPOINTER) Signal;
+
+ /* Signals with numbers between 32 and 63 are real-time,
+ send a real-time signal to the user process. */
+ result = send_sig_info(48, &info, userTask);
+
+ /* Error? */
+ if (result < 0)
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): an error has occurred.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+ else
+ {
+ status = gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(
+ gcvLEVEL_ERROR,
+ "%s(%d): an error has occurred.\n",
+ __FUNCTION__, __LINE__
+ );
+ }
+
+ /* Return status. */
+ return status;
+}
+
+/******************************************************************************\
+******************************** Thread Object *********************************
+\******************************************************************************/
+
+gceSTATUS
+gckOS_StartThread(
+ IN gckOS Os,
+ IN gctTHREADFUNC ThreadFunction,
+ IN gctPOINTER ThreadParameter,
+ OUT gctTHREAD * Thread
+ )
+{
+ gceSTATUS status;
+ struct task_struct * thread;
+
+ gcmkHEADER_ARG("Os=0x%X ", Os);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+ do
+ {
+ /* Create the thread. */
+ thread = kthread_create(
+ ThreadFunction,
+ ThreadParameter,
+ "Vivante Kernel Thread"
+ );
+
+ /* Failed? */
+ if (IS_ERR(thread))
+ {
+ status = gcvSTATUS_GENERIC_IO;
+ break;
+ }
+
+ /* Start the thread. */
+ wake_up_process(thread);
+
+ /* Set the thread handle. */
+ * Thread = (gctTHREAD) thread;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+}
+
+gceSTATUS
+gckOS_StopThread(
+ IN gckOS Os,
+ IN gctTHREAD Thread
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+ /* Thread should have already been enabled to terminate. */
+ kthread_stop((struct task_struct *) Thread);
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_VerifyThread(
+ IN gckOS Os,
+ IN gctTHREAD Thread
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
+
+ gcmkFOOTER_NO();
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+#endif
+
+/******************************************************************************\
+******************************** Software Timer ********************************
+\******************************************************************************/
+
+void
+_TimerFunction(
+ struct work_struct * work
+ )
+{
+ gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
+
+ gctTIMERFUNCTION function = timer->function;
+
+ function(timer->data);
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateTimer
+**
+** Create a software timer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctTIMERFUNCTION Function.
+** Pointer to a call back function which will be called when timer is
+** expired.
+**
+** gctPOINTER Data.
+** Private data which will be passed to call back function.
+**
+** OUTPUT:
+**
+** gctPOINTER * Timer
+** Pointer to a variable receiving the created timer.
+*/
+gceSTATUS
+gckOS_CreateTimer(
+ IN gckOS Os,
+ IN gctTIMERFUNCTION Function,
+ IN gctPOINTER Data,
+ OUT gctPOINTER * Timer
+ )
+{
+ gceSTATUS status;
+ gcsOSTIMER_PTR pointer;
+ gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
+
+ gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
+
+ pointer->function = Function;
+ pointer->data = Data;
+
+ INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
+
+ *Timer = pointer;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroyTimer
+**
+** Destory a software timer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Timer
+** Pointer to the timer to be destoryed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroyTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer
+ )
+{
+ gcsOSTIMER_PTR timer;
+ gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
+
+ timer = (gcsOSTIMER_PTR)Timer;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+ cancel_delayed_work_sync(&timer->work);
+#else
+ cancel_delayed_work(&timer->work);
+ flush_workqueue(Os->workqueue);
+#endif
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_StartTimer
+**
+** Schedule a software timer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Timer
+** Pointer to the timer to be scheduled.
+**
+** gctUINT32 Delay
+** Delay in milliseconds.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_StartTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer,
+ IN gctUINT32 Delay
+ )
+{
+ gcsOSTIMER_PTR timer;
+
+ gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Delay != 0);
+
+ timer = (gcsOSTIMER_PTR)Timer;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+ mod_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
+#else
+ if (unlikely(delayed_work_pending(&timer->work)))
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+ cancel_delayed_work_sync(&timer->work);
+#else
+ cancel_delayed_work(&timer->work);
+ flush_workqueue(Os->workqueue);
+#endif
+ }
+
+ queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
+#endif
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_StopTimer
+**
+** Cancel a unscheduled timer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Timer
+** Pointer to the timer to be cancel.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_StopTimer(
+ IN gckOS Os,
+ IN gctPOINTER Timer
+ )
+{
+ gcsOSTIMER_PTR timer;
+ gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
+
+ timer = (gcsOSTIMER_PTR)Timer;
+
+ cancel_delayed_work(&timer->work);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_GetProcessNameByPid(
+ IN gctINT Pid,
+ IN gctSIZE_T Length,
+ OUT gctUINT8_PTR String
+ )
+{
+ struct task_struct *task;
+
+ /* Get the task_struct of the task with pid. */
+ rcu_read_lock();
+
+ task = FIND_TASK_BY_PID(Pid);
+
+ if (task == gcvNULL)
+ {
+ rcu_read_unlock();
+ return gcvSTATUS_NOT_FOUND;
+ }
+
+ /* Get name of process. */
+ strncpy(String, task->comm, Length);
+
+ rcu_read_unlock();
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_DumpCallStack(
+ IN gckOS Os
+ )
+{
+ gcmkHEADER_ARG("Os=0x%X", Os);
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ dump_stack();
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DetectProcessByName
+**
+** task->comm maybe part of process name, so this function
+** can only be used for debugging.
+**
+** INPUT:
+**
+** gctCONST_POINTER Name
+** Pointer to a string to hold name to be check. If the length
+** of name is longer than TASK_COMM_LEN (16), use part of name
+** to detect.
+**
+** OUTPUT:
+**
+** gcvSTATUS_TRUE if name of current process matches Name.
+**
+*/
+gceSTATUS
+gckOS_DetectProcessByName(
+ IN gctCONST_POINTER Name
+ )
+{
+ char comm[sizeof(current->comm)];
+
+ memset(comm, 0, sizeof(comm));
+
+ gcmkVERIFY_OK(
+ gckOS_GetProcessNameByPid(_GetProcessID(), sizeof(current->comm), comm));
+
+ return strstr(comm, Name) ? gcvSTATUS_TRUE
+ : gcvSTATUS_FALSE;
+}
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+gceSTATUS
+gckOS_CreateSyncTimeline(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctHANDLE * Timeline
+ )
+{
+ struct viv_sync_timeline * timeline;
+ char name[32];
+
+ snprintf(name, 32, "gccore-%u", (unsigned int) Core);
+
+ /* Create viv sync timeline. */
+ timeline = viv_sync_timeline_create(name, Os);
+
+ if (timeline == gcvNULL)
+ {
+ /* Out of memory. */
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ *Timeline = (gctHANDLE) timeline;
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_DestroySyncTimeline(
+ IN gckOS Os,
+ IN gctHANDLE Timeline
+ )
+{
+ struct viv_sync_timeline * timeline;
+ gcmkASSERT(Timeline != gcvNULL);
+
+ /* Destroy timeline. */
+ timeline = (struct viv_sync_timeline *) Timeline;
+ sync_timeline_destroy(&timeline->obj);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CreateNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctSIGNAL Signal,
+ OUT gctINT * FenceFD
+ )
+{
+ int fd = -1;
+ struct viv_sync_timeline *timeline;
+ struct sync_pt * pt = gcvNULL;
+ struct sync_fence * fence;
+ char name[32];
+ gcsSIGNAL_PTR signal;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%X Timeline=0x%X Signal=%d",
+ Os, Timeline, (gctUINT)(gctUINTPTR_T)Signal);
+
+ gcmkONERROR(
+ _QueryIntegerId(&Os->signalDB,
+ (gctUINT32)(gctUINTPTR_T)Signal,
+ (gctPOINTER)&signal));
+
+ /* Cast timeline. */
+ timeline = (struct viv_sync_timeline *) Timeline;
+
+ fd = get_unused_fd_flags(O_CLOEXEC);
+
+ if (fd < 0)
+ {
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Create viv_sync_pt. */
+ pt = viv_sync_pt_create(timeline, Signal);
+
+ if (pt == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Reference sync_timeline. */
+ signal->timeline = &timeline->obj;
+
+ /* Build fence name. */
+ snprintf(name, 32, "%.16s-signal_%lu",
+ current->comm,
+ (unsigned long)Signal);
+
+ /* Create sync_fence. */
+ fence = sync_fence_create(name, pt);
+
+ if (fence == NULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Install fence to fd. */
+ sync_fence_install(fence, fd);
+
+ *FenceFD = fd;
+ gcmkFOOTER_ARG("*FenceFD=%d", fd);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Error roll back. */
+ if (pt)
+ {
+ sync_pt_free(pt);
+ }
+
+ if (fd > 0)
+ {
+ put_unused_fd(fd);
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+static void
+_NativeFenceSignaled(
+ struct sync_fence *fence,
+ struct sync_fence_waiter *waiter
+ )
+{
+ kfree(waiter);
+ sync_fence_put(fence);
+}
+
+gceSTATUS
+gckOS_WaitNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ )
+{
+ struct sync_timeline * timeline;
+ struct sync_fence * fence;
+ gctBOOL wait;
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Os=0x%X Timeline=0x%X FenceFD=%d Timeout=%u",
+ Os, Timeline, FenceFD, Timeout);
+
+ /* Get shortcut. */
+ timeline = (struct sync_timeline *) Timeline;
+
+ /* Get sync fence. */
+ fence = sync_fence_fdget(FenceFD);
+
+ if (!fence)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (sync_fence_wait(fence, 0) == 0)
+ {
+ /* Already signaled. */
+ sync_fence_put(fence);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ wait = gcvFALSE;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
+ {
+ int i;
+
+ for (i = 0; i < fence->num_fences; i++)
+ {
+ struct fence *f = fence->cbs[i].sync_pt;
+ struct sync_pt *pt = container_of(f, struct sync_pt, base);
+
+ /* Do not need to wait on same timeline. */
+ if ((sync_pt_parent(pt) != timeline) && !fence_is_signaled(f))
+ {
+ wait = gcvTRUE;
+ break;
+ }
+ }
+ }
+#else
+ {
+ struct list_head *pos;
+ list_for_each(pos, &fence->pt_list_head)
+ {
+ struct sync_pt * pt =
+ container_of(pos, struct sync_pt, pt_list);
+
+ /* Do not need to wait on same timeline. */
+ if (pt->parent != timeline)
+ {
+ wait = gcvTRUE;
+ break;
+ }
+ }
+ }
+#endif
+
+ if (wait)
+ {
+ int err;
+ long timeout = (Timeout == gcvINFINITE) ? - 1 : (long) Timeout;
+ err = sync_fence_wait(fence, timeout);
+
+ /* Put the fence. */
+ sync_fence_put(fence);
+
+ switch (err)
+ {
+ case 0:
+ break;
+ case -ETIME:
+ status = gcvSTATUS_TIMEOUT;
+ break;
+ default:
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ break;
+ }
+ }
+ else
+ {
+ int err;
+ struct sync_fence_waiter *waiter;
+ waiter = (struct sync_fence_waiter *)kmalloc(
+ sizeof (struct sync_fence_waiter), gcdNOWARN | GFP_KERNEL);
+
+ /*
+ * schedule a callback to put the sync_fence. Otherwise after this function
+ * is returned, the caller may free it since it's signaled. Then there's
+ * be a real signal on a free'ed sync fence.
+ */
+ if (!waiter)
+ {
+ sync_fence_put(fence);
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Schedule a waiter callback. */
+ sync_fence_waiter_init(waiter, _NativeFenceSignaled);
+ err = sync_fence_wait_async(fence, waiter);
+
+ switch (err)
+ {
+ case 0:
+ /* Put fence in callback function. */
+ break;
+ case 1:
+ /* already signaled. */
+ sync_fence_put(fence);
+ break;
+ default:
+ sync_fence_put(fence);
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ break;
+ }
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+# else /* v4.9.0 */
+
+gceSTATUS
+gckOS_CreateSyncTimeline(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctHANDLE * Timeline
+ )
+{
+ struct viv_sync_timeline *timeline;
+
+ char name[32];
+
+ snprintf(name, 32, "gccore-%u", (unsigned int) Core);
+ timeline = viv_sync_timeline_create(name, Os);
+
+ if (timeline == gcvNULL)
+ {
+ /* Out of memory. */
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ *Timeline = (gctHANDLE) timeline;
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_DestroySyncTimeline(
+ IN gckOS Os,
+ IN gctHANDLE Timeline
+ )
+{
+ struct viv_sync_timeline * timeline;
+
+ /* Destroy timeline. */
+ timeline = (struct viv_sync_timeline *) Timeline;
+ viv_sync_timeline_destroy(timeline);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CreateNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctSIGNAL Signal,
+ OUT gctINT * FenceFD
+ )
+{
+ struct fence *fence = NULL;
+ struct sync_file *sync = NULL;
+ int fd;
+ struct viv_sync_timeline *timeline;
+ gcsSIGNAL_PTR signal;
+ gceSTATUS status = gcvSTATUS_OK;
+
+ /* Create fence. */
+ timeline = (struct viv_sync_timeline *) Timeline;
+
+ gcmkONERROR(
+ _QueryIntegerId(&Os->signalDB,
+ (gctUINT32)(gctUINTPTR_T)Signal,
+ (gctPOINTER)&signal));
+
+ fence = viv_fence_create(timeline, signal);
+
+ if (!fence)
+ {
+ gcmONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Create sync_file. */
+ sync = sync_file_create(fence);
+
+ if (!sync)
+ {
+ gcmONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Get a unused fd. */
+ fd = get_unused_fd_flags(O_CLOEXEC);
+
+ if (fd < 0)
+ {
+ gcmONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ fd_install(fd, sync->file);
+
+ *FenceFD = fd;
+ return gcvSTATUS_OK;
+
+OnError:
+ if (sync)
+ {
+ fput(sync->file);
+ }
+
+ if (fence)
+ {
+ fence_put(fence);
+ }
+
+ if (fd > 0)
+ {
+ put_unused_fd(fd);
+ }
+
+ *FenceFD = -1;
+ return status;
+}
+
+gceSTATUS
+gckOS_WaitNativeFence(
+ IN gckOS Os,
+ IN gctHANDLE Timeline,
+ IN gctINT FenceFD,
+ IN gctUINT32 Timeout
+ )
+{
+ struct fence *fence;
+ struct viv_sync_timeline *timeline;
+ gceSTATUS status = gcvSTATUS_OK;
+ unsigned int i;
+ unsigned int numFences;
+ struct fence **fences;
+ unsigned long timeout;
+
+ timeline = (struct viv_sync_timeline *) Timeline;
+
+ fence = sync_file_get_fence(FenceFD);
+
+ if (!fence)
+ {
+ gcmONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ if (fence_is_array(fence))
+ {
+ struct fence_array *array = to_fence_array(fence);
+ fences = array->fences;
+ numFences = array->num_fences;
+ }
+ else
+ {
+ fences = &fence;
+ numFences = 1;
+ }
+
+ timeout = msecs_to_jiffies(Timeout);
+
+ for (i = 0; i < numFences; i++)
+ {
+ struct fence *f = fences[i];
+
+ if (f->context != timeline->context &&
+ !fence_is_signaled(f))
+ {
+ signed long ret;
+ ret = fence_wait_timeout(fence, 1, timeout);
+
+ if (ret == -ERESTARTSYS)
+ {
+ status = gcvSTATUS_INTERRUPTED;
+ break;
+ }
+ else if (ret <= 0)
+ {
+ status = gcvSTATUS_TIMEOUT;
+ break;
+ }
+ else
+ {
+ /* wait success. */
+ timeout -= ret;
+ }
+ }
+ }
+
+ fence_put(fence);
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+# endif /* v4.9.0 */
+#endif
+
+#if gcdSECURITY
+gceSTATUS
+gckOS_AllocatePageArray(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageArrayLogical,
+ OUT gctPHYS_ADDR * PageArrayPhysical
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ PLINUX_MDL mdl;
+ gctUINT32* table;
+ gctUINT32 offset;
+ gctSIZE_T bytes;
+ gckALLOCATOR allocator;
+
+ gcmkHEADER_ARG("Os=0x%X Physical=0x%X PageCount=%u",
+ Os, Physical, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ bytes = PageCount * gcmSIZEOF(gctUINT32);
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(
+ Os,
+ gcvFALSE,
+ &bytes,
+ PageArrayPhysical,
+ PageArrayLogical
+ ));
+
+ table = *PageArrayLogical;
+
+ /* Convert pointer to MDL. */
+ mdl = (PLINUX_MDL)Physical;
+
+ allocator = mdl->allocator;
+
+ /* Get all the physical addresses and store them in the page table. */
+
+ offset = 0;
+ PageCount = PageCount / (PAGE_SIZE / 4096);
+
+ /* Try to get the user pages so DMA can happen. */
+ while (PageCount-- > 0)
+ {
+ unsigned long phys = ~0;
+
+ gctPHYS_ADDR_T phys_addr;
+
+ allocator->ops->Physical(allocator, mdl, offset * PAGE_SIZE, &phys_addr);
+
+ phys = (unsigned long)phys_addr;
+
+ table[offset] = phys;
+
+ offset += 1;
+ }
+
+OnError:
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckOS_CPUPhysicalToGPUPhysical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR_T CPUPhysical,
+ IN gctPHYS_ADDR_T * GPUPhysical
+ )
+{
+ gcsPLATFORM * platform;
+ gcmkHEADER_ARG("CPUPhysical=%p", CPUPhysical);
+
+ platform = Os->device->platform;
+
+ if (platform && platform->ops->getGPUPhysical)
+ {
+ gcmkVERIFY_OK(
+ platform->ops->getGPUPhysical(platform, CPUPhysical, GPUPhysical));
+ }
+ else
+ {
+ *GPUPhysical = CPUPhysical;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_GPUPhysicalToCPUPhysical(
+ IN gckOS Os,
+ IN gctUINT32 GPUPhysical,
+ IN gctPHYS_ADDR_T * CPUPhysical
+ )
+{
+ gcsPLATFORM * platform;
+ gcmkHEADER_ARG("GPUPhysical=0x%X", GPUPhysical);
+
+ platform = Os->device->platform;
+
+ if (platform && platform->ops->getCPUPhysical)
+ {
+ gcmkVERIFY_OK(
+ platform->ops->getCPUPhysical(platform, GPUPhysical, CPUPhysical));
+ }
+ else
+ {
+ *CPUPhysical = GPUPhysical;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_PhysicalToPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Physical,
+ IN gctUINT32 Offset,
+ OUT gctPHYS_ADDR_T * PhysicalAddress
+ )
+{
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gckALLOCATOR allocator = mdl->allocator;
+
+ if (allocator)
+ {
+ return allocator->ops->Physical(allocator, mdl, Offset, PhysicalAddress);
+ }
+
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+static int fd_release(struct inode *inode, struct file *file)
+{
+ gcsFDPRIVATE_PTR private = (gcsFDPRIVATE_PTR)file->private_data;
+
+ if (private && private->release)
+ {
+ return private->release(private);
+ }
+
+ return 0;
+}
+
+static const struct file_operations fd_fops =
+{
+ .release = fd_release,
+};
+
+gceSTATUS
+gckOS_GetFd(
+ IN gctSTRING Name,
+ IN gcsFDPRIVATE_PTR Private,
+ OUT gctINT * Fd
+ )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+ *Fd = anon_inode_getfd(Name, &fd_fops, Private, O_RDWR);
+
+ if (*Fd < 0)
+ {
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ return gcvSTATUS_OK;
+#else
+ return gcvSTATUS_NOT_SUPPORTED;
+#endif
+}
+
+gceSTATUS
+gckOS_QueryOption(
+ IN gckOS Os,
+ IN gctCONST_STRING Option,
+ OUT gctUINT32 * Value
+ )
+{
+ gckGALDEVICE device = Os->device;
+
+ if (!strcmp(Option, "physBase"))
+ {
+ *Value = device->physBase;
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "physSize"))
+ {
+ *Value = device->physSize;
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "mmu"))
+ {
+#if gcdSECURITY
+ *Value = 0;
+#else
+ *Value = device->args.mmu;
+#endif
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "contiguousSize"))
+ {
+ *Value = device->contiguousSize;
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "contiguousBase"))
+ {
+ *Value = device->requestedContiguousBase;
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "recovery"))
+ {
+ *Value = device->args.recovery;
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "stuckDump"))
+ {
+ *Value = device->args.stuckDump;
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "powerManagement"))
+ {
+ *Value = device->args.powerManagement;
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "TA"))
+ {
+ *Value = 1;
+ return gcvSTATUS_OK;
+ }
+ else if (!strcmp(Option, "gpuProfiler"))
+ {
+ *Value = device->args.gpuProfiler;
+ return gcvSTATUS_OK;
+ }
+
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+** gckOS_WrapMemory
+**
+** Import a number of pages allocated by other allocator.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Flag
+** Memory type.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that hold the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that will hold the physical address of the
+** allocation.
+*/
+gceSTATUS
+gckOS_WrapMemory(
+ IN gckOS Os,
+ IN gcsUSER_MEMORY_DESC_PTR Desc,
+ OUT gctSIZE_T *Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctBOOL *Contiguous
+ )
+{
+ PLINUX_MDL mdl = gcvNULL;
+ gceSTATUS status = gcvSTATUS_OUT_OF_MEMORY;
+ gckALLOCATOR allocator;
+ gcsATTACH_DESC desc;
+ gctUINT32 flag;
+
+ gcmkHEADER_ARG("Os=0x%X ", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+ mdl = _CreateMdl();
+ if (mdl == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ desc.handle = Desc->handle;
+ desc.memory = gcmUINT64_TO_PTR(Desc->logical);
+ desc.physical = Desc->physical;
+ desc.size = Desc->size;
+ flag = Desc->flag;
+
+ desc.info = Desc->externalMemoryInfo;
+
+ /* Walk all allocators. */
+ list_for_each_entry(allocator, &Os->allocatorList, head)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "%s(%d) Flag = %x allocator->capability = %x",
+ __FUNCTION__, __LINE__, flag, allocator->capability);
+
+ if ((flag & allocator->capability) != flag)
+ {
+ status = gcvSTATUS_NOT_SUPPORTED;
+ continue;
+ }
+
+ if (flag == gcvALLOC_FLAG_EXTERNAL_MEMORY)
+ {
+ /* Use name to match suitable allocator for external memory. */
+ if (!strncmp(Desc->externalMemoryInfo.allocatorName, allocator->name, gcdEXTERNAL_MEMORY_NAME_MAX))
+ {
+ status = gcvSTATUS_NOT_SUPPORTED;
+ continue;
+ }
+ }
+
+ status = allocator->ops->Attach(allocator, &desc, mdl);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ mdl->allocator = allocator;
+ break;
+ }
+ }
+
+ /* Check status. */
+ gcmkONERROR(status);
+
+ mdl->dmaHandle = 0;
+ mdl->addr = 0;
+
+ *Bytes = mdl->numPages * PAGE_SIZE;
+
+ /* Return physical address. */
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ *Contiguous = mdl->contiguous;
+
+ mutex_lock(&Os->mdlMutex);
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+ list_add_tail(&mdl->link, &Os->mdlHead);
+
+ mutex_unlock(&Os->mdlMutex);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mdl != gcvNULL)
+ {
+ /* Free the memory. */
+ _DestroyMdl(mdl);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_GetPolicyID(
+ IN gckOS Os,
+ IN gceSURF_TYPE Type,
+ OUT gctUINT32_PTR PolicyID,
+ OUT gctUINT32_PTR AXIConfig
+ )
+{
+ gcsPLATFORM * platform = Os->device->platform;
+
+ if (platform && platform->ops->getPolicyID)
+ {
+ return platform->ops->getPolicyID(platform, Type, PolicyID, AXIConfig);
+ }
+
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
new file mode 100644
index 000000000000..c17a8f5c56d7
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_os_h_
+#define __gc_hal_kernel_os_h_
+
+typedef struct _LINUX_MDL LINUX_MDL, *PLINUX_MDL;
+typedef struct _LINUX_MDL_MAP LINUX_MDL_MAP, *PLINUX_MDL_MAP;
+
+struct _LINUX_MDL_MAP
+{
+ gctINT pid;
+ gctPOINTER vmaAddr;
+ gctUINT32 count;
+
+ struct list_head link;
+};
+
+struct _LINUX_MDL
+{
+ char * addr;
+
+ gctINT numPages;
+ gctBOOL contiguous;
+ dma_addr_t dmaHandle;
+
+ struct mutex mapsMutex;
+ struct list_head mapsHead;
+
+ /* Pointer to allocator which allocates memory for this mdl. */
+ void * allocator;
+
+ /* Private data used by allocator. */
+ void * priv;
+
+ uint gid;
+
+ struct list_head link;
+};
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT PID
+ );
+
+typedef struct _DRIVER_ARGS
+{
+ gctUINT64 InputBuffer;
+ gctUINT64 InputBufferSize;
+ gctUINT64 OutputBuffer;
+ gctUINT64 OutputBufferSize;
+}
+DRIVER_ARGS;
+
+#endif /* __gc_hal_kernel_os_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h
new file mode 100644
index 000000000000..f8a1e31bbb65
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h
@@ -0,0 +1,386 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef _gc_hal_kernel_platform_h_
+#define _gc_hal_kernel_platform_h_
+#include <linux/mm.h>
+
+typedef struct _gcsMODULE_PARAMETERS
+{
+ gctINT irqLine;
+ gctUINT registerMemBase;
+ gctUINT registerMemSize;
+ gctINT irqLine2D;
+ gctUINT registerMemBase2D;
+ gctUINT registerMemSize2D;
+ gctINT irqLineVG;
+ gctUINT registerMemBaseVG;
+ gctUINT registerMemSizeVG;
+ gctUINT contiguousSize;
+ gctUINT contiguousBase;
+ gctUINT contiguousRequested;
+ gctUINT bankSize;
+ gctINT fastClear;
+ gctINT compression;
+ gctINT powerManagement;
+ gctINT gpuProfiler;
+ gctINT signal;
+ gctUINT baseAddress;
+ gctUINT physSize;
+ gctUINT logFileSize;
+ gctUINT recovery;
+ gctUINT stuckDump;
+ gctUINT showArgs;
+ gctUINT gpu3DMinClock;
+ gctBOOL registerMemMapped;
+ gctPOINTER registerMemAddress;
+ gctINT irqs[gcvCORE_COUNT];
+ gctUINT registerBases[gcvCORE_COUNT];
+ gctUINT registerSizes[gcvCORE_COUNT];
+ gctUINT chipIDs[gcvCORE_COUNT];
+}
+gcsMODULE_PARAMETERS;
+
+typedef struct _gcsPLATFORM * gckPLATFORM;
+
+typedef struct _gcsPLATFORM_OPERATIONS
+{
+ /*******************************************************************************
+ **
+ ** needAddDevice
+ **
+ ** Determine whether platform_device is created by initialization code.
+ ** If platform_device is created by BSP, return gcvFLASE here.
+ */
+ gctBOOL
+ (*needAddDevice)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** registerDevice
+ **
+ ** Determine whether platform device need to be registered
+ */
+ gceSTATUS
+ (*registerDevice)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** runRegisterDevice
+ **
+ ** Unregister platform device
+ */
+ gceSTATUS
+ (*unRegisterDevice)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** adjustParam
+ **
+ ** Override content of arguments, if a argument is not changed here, it will
+ ** keep as default value or value set by insmod command line.
+ */
+ gceSTATUS
+ (*adjustParam)(
+ IN gckPLATFORM Platform,
+ OUT gcsMODULE_PARAMETERS *Args
+ );
+
+ /*******************************************************************************
+ **
+ ** adjustDriver
+ **
+ ** Override content of platform_driver which will be registered.
+ */
+ gceSTATUS
+ (*adjustDriver)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** getPower
+ **
+ ** Prepare power and clock operation.
+ */
+ gceSTATUS
+ (*getPower)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** putPower
+ **
+ ** Finish power and clock operation.
+ */
+ gceSTATUS
+ (*putPower)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** allocPriv
+ **
+ ** Construct platform private data.
+ */
+ gceSTATUS
+ (*allocPriv)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** freePriv
+ **
+ ** free platform private data.
+ */
+ gceSTATUS
+ (*freePriv)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** setPower
+ **
+ ** Set power state of specified GPU.
+ **
+ ** INPUT:
+ **
+ ** gceCORE GPU
+ ** GPU neeed to config.
+ **
+ ** gceBOOL Enable
+ ** Enable or disable power.
+ */
+ gceSTATUS
+ (*setPower)(
+ IN gckPLATFORM Platform,
+ IN gceCORE GPU,
+ IN gctBOOL Enable
+ );
+
+ /*******************************************************************************
+ **
+ ** setClock
+ **
+ ** Set clock state of specified GPU.
+ **
+ ** INPUT:
+ **
+ ** gceCORE GPU
+ ** GPU neeed to config.
+ **
+ ** gceBOOL Enable
+ ** Enable or disable clock.
+ */
+ gceSTATUS
+ (*setClock)(
+ IN gckPLATFORM Platform,
+ IN gceCORE GPU,
+ IN gctBOOL Enable
+ );
+
+ /*******************************************************************************
+ **
+ ** reset
+ **
+ ** Reset GPU outside.
+ **
+ ** INPUT:
+ **
+ ** gceCORE GPU
+ ** GPU neeed to reset.
+ */
+ gceSTATUS
+ (*reset)(
+ IN gckPLATFORM Platform,
+ IN gceCORE GPU
+ );
+
+ /*******************************************************************************
+ **
+ ** getGPUPhysical
+ **
+ ** Convert CPU physical address to GPU physical address if they are
+ ** different.
+ */
+ gceSTATUS
+ (*getGPUPhysical)(
+ IN gckPLATFORM Platform,
+ IN gctPHYS_ADDR_T CPUPhysical,
+ OUT gctPHYS_ADDR_T * GPUPhysical
+ );
+
+ /*******************************************************************************
+ **
+ ** getGPUPhysical
+ **
+ ** Convert GPU physical address to CPU physical address if they are
+ ** different.
+ */
+ gceSTATUS
+ (*getCPUPhysical)(
+ IN gckPLATFORM Platform,
+ IN gctUINT32 GPUPhysical,
+ OUT gctPHYS_ADDR_T * CPUPhysical
+ );
+
+ /*******************************************************************************
+ **
+ ** adjustProt
+ **
+ ** Override Prot flag when mapping paged memory to userspace.
+ */
+ gceSTATUS
+ (*adjustProt)(
+ IN struct vm_area_struct * vma
+ );
+
+ /*******************************************************************************
+ **
+ ** shrinkMemory
+ **
+ ** Do something to collect memory, eg, act as oom killer.
+ */
+ gceSTATUS
+ (*shrinkMemory)(
+ IN gckPLATFORM Platform
+ );
+
+ /*******************************************************************************
+ **
+ ** cache
+ **
+ ** Cache operation.
+ */
+ gceSTATUS
+ (*cache)(
+ IN gckPLATFORM Platform,
+ IN gctUINT32 ProcessID,
+ IN gctPHYS_ADDR Handle,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes,
+ IN gceCACHEOPERATION Operation
+ );
+
+ /*******************************************************************************
+ **
+ ** name
+ **
+ ** Get name of platform code.
+ **
+ ** There is a helper macro gcmkPLATFORM_Name which defines a default callback
+ ** function _Name() which uses code path as name.
+ */
+ gceSTATUS
+ (*name)(
+ IN gckPLATFORM Platform,
+ IN gctCONST_STRING * Name
+ );
+
+ /*******************************************************************************
+ **
+ ** getPolicyID
+ **
+ ** Get policyID for a specified surface type.
+ */
+ gceSTATUS
+ (*getPolicyID)(
+ IN gckPLATFORM Platform,
+ IN gceSURF_TYPE Type,
+ OUT gctUINT32_PTR PolicyID,
+ OUT gctUINT32_PTR AXIConfig
+ );
+}
+gcsPLATFORM_OPERATIONS;
+
+typedef struct _gcsPLATFORM
+{
+ struct platform_device* device;
+ struct platform_driver* driver;
+
+ gcsPLATFORM_OPERATIONS* ops;
+
+ void* priv;
+}
+gcsPLATFORM;
+
+void
+gckPLATFORM_QueryOperations(
+ IN gcsPLATFORM_OPERATIONS ** Operations
+ );
+
+#define gcmkPLATFROM_Name \
+static gceSTATUS \
+_Name( \
+ IN gckPLATFORM Platform, \
+ IN gctCONST_STRING * Name \
+ ) \
+{ \
+ * Name = __FILE__; \
+ return gcvSTATUS_OK; \
+} \
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c
new file mode 100644
index 000000000000..64b278fce09c
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel.c
@@ -0,0 +1,426 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include <linux/slab.h>
+
+#include "tee_client_api.h"
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#define GPU3D_UUID { 0xcc9f80ea, 0xa836, 0x11e3, { 0x9b, 0x07, 0x78, 0x2b, 0xcb, 0x5c, 0xf3, 0xe3 } }
+
+static const TEEC_UUID gpu3d_uuid = GPU3D_UUID;
+TEEC_Context teecContext;
+
+typedef struct _gcsSecurityChannel
+{
+ gckOS os;
+ TEEC_Session session;
+ int * virtual;
+ TEEC_SharedMemory inputBuffer;
+ gctUINT32 bytes;
+ gctPOINTER mutex;
+}
+gcsSecurityChannel;
+
+TEEC_SharedMemory *
+gpu3d_allocate_secure_mem(
+ gckOS Os,
+ unsigned int size
+ )
+{
+ TEEC_Result result;
+ TEEC_Context *context = &teecContext;
+ TEEC_SharedMemory *shm = NULL;
+ void *handle = NULL;
+ gctPHYS_ADDR_T phyAddr;
+ gceSTATUS status;
+ gctSIZE_T bytes = size;
+
+ shm = kmalloc(sizeof(TEEC_SharedMemory), GFP_KERNEL);
+
+ if (NULL == shm)
+ {
+ return NULL;
+ }
+
+ memset(shm, 0, sizeof(TEEC_SharedMemory));
+
+ status = gckOS_AllocatePagedMemoryEx(
+ Os,
+ gcvALLOC_FLAG_SECURITY,
+ bytes,
+ gcvNULL,
+ (gctPHYS_ADDR *)&handle);
+
+ if (gcmIS_ERROR(status))
+ {
+ kfree(shm);
+ return NULL;
+ }
+
+ status = gckOS_PhysicalToPhysicalAddress(
+ Os,
+ handle,
+ 0,
+ &phyAddr);
+
+ if (gcmIS_ERROR(status))
+ {
+ kfree(shm);
+ return NULL;
+ }
+
+ /* record the handle into shm->user_data */
+ shm->userdata = handle;
+
+ /* [b] Bulk input buffer. */
+ shm->size = size;
+ shm->flags = TEEC_MEM_INPUT;
+
+ /* Use TEE Client API to register the underlying memory buffer. */
+ shm->phyAddr = (void *)(gctUINT32)phyAddr;
+
+ result = TEEC_RegisterSharedMemory(
+ context,
+ shm);
+
+ if (result != TEEC_SUCCESS)
+ {
+ gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
+ kfree(shm);
+ return NULL;
+ }
+
+ return shm;
+}
+
+void gpu3d_release_secure_mem(
+ gckOS Os,
+ void *shm_handle
+ )
+{
+ TEEC_SharedMemory *shm = shm_handle;
+ void * handle;
+
+ if (!shm)
+ {
+ return;
+ }
+
+ handle = shm->userdata;
+
+ TEEC_ReleaseSharedMemory(shm);
+ gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
+
+ kfree(shm);
+
+ return;
+}
+
+static TEEC_Result gpu3d_session_callback(
+ TEEC_Session* session,
+ uint32_t commandID,
+ TEEC_Operation* operation,
+ void* userdata
+ )
+{
+ gcsSecurityChannel *channel = userdata;
+
+ if (channel == gcvNULL)
+ {
+ return TEEC_ERROR_BAD_PARAMETERS;
+ }
+
+ switch (commandID)
+ {
+ case gcvTA_CALLBACK_ALLOC_SECURE_MEM:
+ {
+ uint32_t size = operation->params[0].value.a;
+ TEEC_SharedMemory *shm = NULL;
+
+ shm = gpu3d_allocate_secure_mem(channel->os, size);
+ if (shm == NULL)
+ {
+ return TEEC_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* use the value to save the pointer in client side */
+ operation->params[0].value.a = (uint32_t)shm;
+ operation->params[0].value.b = (uint32_t)shm->phyAddr;
+
+ break;
+ }
+ case gcvTA_CALLBACK_FREE_SECURE_MEM:
+ {
+ TEEC_SharedMemory *shm = (TEEC_SharedMemory *)operation->params[0].value.a;
+
+ gpu3d_release_secure_mem(channel->os, shm);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TEEC_SUCCESS;
+}
+
+gceSTATUS
+gckOS_OpenSecurityChannel(
+ IN gckOS Os,
+ IN gceCORE GPU,
+ OUT gctUINT32 *Channel
+ )
+{
+ gceSTATUS status;
+ TEEC_Result result;
+ static bool initialized = gcvFALSE;
+ gcsSecurityChannel *channel = gcvNULL;
+
+ TEEC_Operation operation = {0};
+
+ /* Connect to TEE. */
+ if (initialized == gcvFALSE)
+ {
+ result = TEEC_InitializeContext(NULL, &teecContext);
+
+ if (result != TEEC_SUCCESS)
+ {
+ gcmkONERROR(gcvSTATUS_CHIP_NOT_READY);
+ }
+
+ initialized = gcvTRUE;
+ }
+
+ /* Construct channel. */
+ gcmkONERROR(
+ gckOS_Allocate(Os, gcmSIZEOF(*channel), (gctPOINTER *)&channel));
+
+ gckOS_ZeroMemory(channel, gcmSIZEOF(gcsSecurityChannel));
+
+ channel->os = Os;
+
+ gcmkONERROR(gckOS_CreateMutex(Os, &channel->mutex));
+
+ /* Allocate shared memory for passing gcTA_INTERFACE. */
+ channel->bytes = gcmSIZEOF(gcsTA_INTERFACE);
+ channel->virtual = kmalloc(channel->bytes, GFP_KERNEL | __GFP_NOWARN);
+
+ if (!channel->virtual)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ channel->inputBuffer.size = channel->bytes;
+ channel->inputBuffer.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
+ channel->inputBuffer.phyAddr = (void *)virt_to_phys(channel->virtual);
+
+ result = TEEC_RegisterSharedMemory(&teecContext, &channel->inputBuffer);
+
+ if (result != TEEC_SUCCESS)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ operation.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_VALUE_INPUT,
+ TEEC_NONE,
+ TEEC_NONE,
+ TEEC_NONE);
+
+ operation.params[0].value.a = GPU;
+
+ /* Open session with TEE application. */
+ result = TEEC_OpenSession(
+ &teecContext,
+ &channel->session,
+ &gpu3d_uuid,
+ TEEC_LOGIN_USER,
+ NULL,
+ &operation,
+ NULL);
+
+ /* Prepare callback. */
+ TEEC_RegisterCallback(&channel->session, gpu3d_session_callback, channel);
+
+ *Channel = (gctUINT32)channel;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (channel)
+ {
+ if (channel->virtual)
+ {
+ }
+
+ if (channel->mutex)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, channel->mutex));
+ }
+
+ gcmkVERIFY_OK(gckOS_Free(Os, channel));
+ }
+
+ return status;
+}
+
+gceSTATUS
+gckOS_CloseSecurityChannel(
+ IN gctUINT32 Channel
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CallSecurityService(
+ IN gctUINT32 Channel,
+ IN gcsTA_INTERFACE *Interface
+ )
+{
+ gceSTATUS status;
+ TEEC_Result result;
+ gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
+ TEEC_Operation operation = {0};
+
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(Channel != 0);
+
+ gckOS_AcquireMutex(channel->os, channel->mutex, gcvINFINITE);
+
+ gckOS_MemCopy(channel->virtual, Interface, channel->bytes);
+
+ operation.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_MEMREF_PARTIAL_INPUT,
+ TEEC_NONE,
+ TEEC_NONE,
+ TEEC_NONE);
+
+ /* Note: we use the updated size in the MemRef output by the encryption. */
+ operation.params[0].memref.parent = &channel->inputBuffer;
+ operation.params[0].memref.offset = 0;
+ operation.params[0].memref.size = sizeof(gcsTA_INTERFACE);
+ operation.started = true;
+
+ /* Start the commit command within the TEE application. */
+ result = TEEC_InvokeCommand(
+ &channel->session,
+ gcvTA_COMMAND_DISPATCH,
+ &operation,
+ NULL);
+
+ gckOS_MemCopy(Interface, channel->virtual, channel->bytes);
+
+ gckOS_ReleaseMutex(channel->os, channel->mutex);
+
+ if (result != TEEC_SUCCESS)
+ {
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_InitSecurityChannel(
+ IN gctUINT32 Channel
+ )
+{
+ gceSTATUS status;
+ TEEC_Result result;
+ gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
+ TEEC_Operation operation = {0};
+
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(Channel != 0);
+
+ operation.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_MEMREF_PARTIAL_INPUT,
+ TEEC_NONE,
+ TEEC_NONE,
+ TEEC_NONE);
+
+ /* Note: we use the updated size in the MemRef output by the encryption. */
+ operation.params[0].memref.parent = &channel->inputBuffer;
+ operation.params[0].memref.offset = 0;
+ operation.params[0].memref.size = gcmSIZEOF(gcsTA_INTERFACE);
+ operation.started = true;
+
+ /* Start the commit command within the TEE application. */
+ result = TEEC_InvokeCommand(
+ &channel->session,
+ gcvTA_COMMAND_INIT,
+ &operation,
+ NULL);
+
+ if (result != TEEC_SUCCESS)
+ {
+ gcmkONERROR(gcvSTATUS_GENERIC_IO);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel_emulator.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel_emulator.c
new file mode 100644
index 000000000000..533125fa7728
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_security_channel_emulator.c
@@ -0,0 +1,116 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#if gcdENABLE_TRUST_APPLICATION
+
+gceSTATUS
+gckOS_OpenSecurityChannel(
+ IN gckOS Os,
+ IN gceCORE Core,
+ OUT gctUINT32 *Channel
+ )
+{
+ *Channel = Core + 1;
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_InitSecurityChannel(
+ OUT gctUINT32 Channel
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CloseSecurityChannel(
+ IN gctUINT32 Channel
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+extern gceSTATUS
+TAEmulator (
+ gceCORE,
+ void *
+ );
+
+gceSTATUS
+gckOS_CallSecurityService(
+ IN gctUINT32 Channel,
+ IN gcsTA_INTERFACE *Interface
+ )
+{
+ gceCORE core;
+ gceSTATUS status;
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(Channel != 0);
+
+ core = (gceCORE)(Channel - 1);
+
+ TAEmulator(core, Interface);
+
+ status = Interface->result;
+
+ gcmkFOOTER();
+ return status;
+}
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c
new file mode 100644
index 000000000000..975021903ff7
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c
@@ -0,0 +1,381 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include <gc_hal.h>
+#include <gc_hal_base.h>
+
+#if gcdANDROID_NATIVE_FENCE_SYNC
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+#include "gc_hal_kernel_sync.h"
+#include "gc_hal_kernel_linux.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+
+static struct sync_pt * viv_sync_pt_dup(struct sync_pt *sync_pt)
+{
+ gceSTATUS status;
+ struct viv_sync_pt *pt;
+ struct viv_sync_pt *src;
+ struct viv_sync_timeline *obj;
+
+ src = (struct viv_sync_pt *)sync_pt;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
+ obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
+#else
+ obj = (struct viv_sync_timeline *)sync_pt->parent;
+#endif
+
+ /* Create the new sync_pt. */
+ pt = (struct viv_sync_pt *)
+ sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
+
+ pt->stamp = src->stamp;
+
+ /* Reference signal. */
+ status = gckOS_MapSignal(obj->os,
+ src->signal,
+ gcvNULL /* (gctHANDLE) _GetProcessID() */,
+ &pt->signal);
+
+ if (gcmIS_ERROR(status)) {
+ sync_pt_free((struct sync_pt *)pt);
+ return NULL;
+ }
+
+ return (struct sync_pt *)pt;
+}
+
+static int viv_sync_pt_has_signaled(struct sync_pt *sync_pt)
+{
+ gceSTATUS status;
+ struct viv_sync_pt *pt;
+ struct viv_sync_timeline *obj;
+
+ pt = (struct viv_sync_pt *)sync_pt;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
+ obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
+#else
+ obj = (struct viv_sync_timeline *)sync_pt->parent;
+#endif
+
+ status = _QuerySignal(obj->os, pt->signal);
+
+ if (gcmIS_ERROR(status)) {
+ /* Error. */
+ return -1;
+ }
+
+ return (int) status;
+}
+
+static int viv_sync_pt_compare(struct sync_pt *a, struct sync_pt *b)
+{
+ int ret;
+ struct viv_sync_pt *pt1 = (struct viv_sync_pt *)a;
+ struct viv_sync_pt *pt2 = (struct viv_sync_pt *)b;
+
+ ret = (pt1->stamp < pt2->stamp) ? -1
+ : (pt1->stamp == pt2->stamp) ? 0
+ : 1;
+
+ return ret;
+}
+
+static void viv_sync_pt_free(struct sync_pt *sync_pt)
+{
+ struct viv_sync_pt *pt;
+ struct viv_sync_timeline *obj;
+
+ pt = (struct viv_sync_pt *)sync_pt;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
+ obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
+#else
+ obj = (struct viv_sync_timeline *)sync_pt->parent;
+#endif
+
+ gckOS_DestroySignal(obj->os, pt->signal);
+}
+
+static void viv_timeline_value_str(struct sync_timeline *timeline,
+ char *str, int size)
+{
+ struct viv_sync_timeline *obj;
+
+ obj = (struct viv_sync_timeline *)timeline;
+ snprintf(str, size, "stamp_%llu", obj->stamp);
+}
+
+static void viv_pt_value_str(struct sync_pt *sync_pt, char *str, int size)
+{
+ struct viv_sync_pt *pt;
+
+ pt = (struct viv_sync_pt *)sync_pt;
+ snprintf(str, size, "signal_%lu@stamp_%llu",
+ (unsigned long)pt->signal, pt->stamp);
+}
+
+static struct sync_timeline_ops viv_timeline_ops =
+{
+ .driver_name = "viv_gpu_sync",
+ .dup = viv_sync_pt_dup,
+ .has_signaled = viv_sync_pt_has_signaled,
+ .compare = viv_sync_pt_compare,
+ .free_pt = viv_sync_pt_free,
+ .timeline_value_str = viv_timeline_value_str,
+ .pt_value_str = viv_pt_value_str,
+};
+
+struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS os)
+{
+ struct viv_sync_timeline * obj;
+
+ obj = (struct viv_sync_timeline *)
+ sync_timeline_create(&viv_timeline_ops, sizeof(struct viv_sync_timeline), name);
+
+ obj->os = os;
+ obj->stamp = 0;
+
+ return obj;
+}
+
+struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj,
+ gctSIGNAL Signal)
+{
+ gceSTATUS status;
+ struct viv_sync_pt *pt;
+
+ pt = (struct viv_sync_pt *)
+ sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
+
+ pt->stamp = obj->stamp++;
+
+ /* Dup signal. */
+ status = gckOS_MapSignal(obj->os,
+ Signal,
+ gcvNULL /* (gctHANDLE) _GetProcessID() */,
+ &pt->signal);
+
+ if (gcmIS_ERROR(status)) {
+ sync_pt_free((struct sync_pt *)pt);
+ return NULL;
+ }
+
+ return (struct sync_pt *)pt;
+}
+
+#else /* v4.9.0 */
+
+struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os)
+{
+ struct viv_sync_timeline *timeline;
+
+ timeline = kmalloc(sizeof(struct viv_sync_timeline),
+ gcdNOWARN | GFP_KERNEL);
+
+ if (!timeline)
+ return NULL;
+
+ strncpy(timeline->name, name, sizeof(timeline->name));
+ timeline->context = fence_context_alloc(1);
+ atomic64_set(&timeline->seqno, 0);
+ timeline->os = Os;
+
+ return timeline;
+}
+
+void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline)
+{
+ kfree(timeline);
+}
+
+static const char * viv_fence_get_driver_name(struct fence *fence)
+{
+ return "viv_gpu_sync";
+}
+
+static const char * viv_fence_get_timeline_name(struct fence *fence)
+{
+ struct viv_fence *f = (struct viv_fence *)fence;
+ return f->parent->name;
+}
+
+/* Same as fence_signaled. */
+static inline bool __viv_fence_signaled(struct fence *fence)
+{
+ struct viv_fence *f = (struct viv_fence *)fence;
+ struct viv_sync_timeline *timeline = f->parent;
+ gceSTATUS status;
+
+ status = _QuerySignal(timeline->os, f->signal);
+
+ return (status == gcvSTATUS_TRUE) ? true : false;
+}
+
+static bool viv_fence_enable_signaling(struct fence *fence)
+{
+ /* fence is locked already. */
+ return !__viv_fence_signaled(fence);
+}
+
+static bool viv_fence_signaled(struct fence *fence)
+{
+ /* fence could be locked, could be not. */
+ return __viv_fence_signaled(fence);
+}
+
+static void viv_fence_release(struct fence *fence)
+{
+ struct viv_fence *f = (struct viv_fence *)fence;
+ struct viv_sync_timeline *timeline = f->parent;
+
+ if (f->signal)
+ gckOS_DestroySignal(timeline->os, f->signal);
+
+ kfree(fence);
+}
+
+static struct fence_ops viv_fence_ops =
+{
+ .get_driver_name = viv_fence_get_driver_name,
+ .get_timeline_name = viv_fence_get_timeline_name,
+ .enable_signaling = viv_fence_enable_signaling,
+ .signaled = viv_fence_signaled,
+ .wait = fence_default_wait,
+ .release = viv_fence_release,
+};
+
+struct fence * viv_fence_create(struct viv_sync_timeline *timeline,
+ gcsSIGNAL *signal)
+{
+ gceSTATUS status;
+ struct viv_fence *fence;
+ struct fence *old_fence = NULL;
+ unsigned seqno;
+
+ fence = kmalloc(sizeof(struct viv_fence), gcdNOWARN | GFP_KERNEL);
+
+ if (!fence)
+ return NULL;
+
+ /* Reference signal in fence. */
+ status = gckOS_MapSignal(timeline->os, (gctSIGNAL)(uintptr_t)signal->id,
+ NULL, &fence->signal);
+
+ if (gcmIS_ERROR(status)) {
+ kfree(fence);
+ return NULL;
+ }
+
+ spin_lock_init(&fence->lock);
+
+ fence->parent = timeline;
+
+ seqno = (unsigned)atomic64_inc_return(&timeline->seqno);
+
+ fence_init((struct fence *)fence, &viv_fence_ops,
+ &fence->lock, timeline->context, seqno);
+
+ /*
+ * Reference fence in signal.
+ * Be aware of recursive reference!!
+ */
+#ifdef gcdRT_KERNEL
+ raw_spin_lock_irq(&signal->obj.wait.lock);
+#else
+ spin_lock_irq(&signal->obj.wait.lock);
+#endif
+
+ if (signal->fence) {
+ old_fence = signal->fence;
+ signal->fence = NULL;
+ }
+
+#ifdef gcdRT_KERNEL
+ raw_spin_unlock_irq(&signal->obj.wait.lock);
+#else
+ spin_unlock_irq(&signal->obj.wait.lock);
+#endif
+
+ if (!completion_done(&signal->obj)) {
+ signal->fence = (struct fence*)fence;
+ fence_get((struct fence*)fence);
+ }
+
+ if (old_fence)
+ fence_put(old_fence);
+
+ if (!signal->fence) {
+ /* Fence already signaled. */
+ gckOS_DestroySignal(timeline->os, fence->signal);
+ fence->signal = NULL;
+
+ fence_signal_locked((struct fence*)fence);
+ }
+
+ return (struct fence*)fence;
+}
+
+#endif /* v4.9.0 */
+
+#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h
new file mode 100644
index 000000000000..72c6423f7306
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_kernel_sync_h_
+#define __gc_hal_kernel_sync_h_
+
+#include <linux/types.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+
+/* sync.h is in drivers/staging/android/ for now. */
+#include <sync.h>
+
+#include <gc_hal.h>
+#include <gc_hal_base.h>
+
+struct viv_sync_timeline
+{
+ /* Parent object. */
+ struct sync_timeline obj;
+
+ /* Timestamp when sync_pt is created. */
+ gctUINT64 stamp;
+
+ /* Pointer to os struct. */
+ gckOS os;
+};
+
+
+struct viv_sync_pt
+{
+ /* Parent object. */
+ struct sync_pt pt;
+
+ /* Reference signal. */
+ gctSIGNAL signal;
+
+ /* Timestamp when sync_pt is created. */
+ gctUINT64 stamp;
+};
+
+/* Create viv_sync_timeline object. */
+struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os);
+
+/* Create viv_sync_pt object. */
+struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj,
+ gctSIGNAL signal);
+
+#else /* v4.9.0 */
+
+#include <linux/sync_file.h>
+#include <linux/fence.h>
+#include <linux/fence-array.h>
+
+#include <gc_hal.h>
+#include <gc_hal_base.h>
+#include "gc_hal_kernel_linux.h"
+
+struct viv_sync_timeline
+{
+ char name[64];
+
+ /* Parent object. */
+ u64 context;
+
+ /* Timestamp when sync_pt is created. */
+ atomic64_t seqno;
+
+ /* Pointer to os struct. */
+ gckOS os;
+};
+
+struct viv_fence
+{
+ /* must be the first. */
+ struct fence base;
+ spinlock_t lock;
+
+ struct viv_sync_timeline *parent;
+
+ /* link with signal. */
+ gctSIGNAL signal;
+};
+
+struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os);
+
+void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline);
+
+struct fence * viv_fence_create(struct viv_sync_timeline *timeline,
+ gcsSIGNAL *signal);
+
+#endif /* v4.9.0 */
+
+#endif /* __gc_hal_kernel_sync_h_ */
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/default/gc_hal_kernel_platform_default.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/default/gc_hal_kernel_platform_default.c
new file mode 100644
index 000000000000..8d1a85447a72
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/default/gc_hal_kernel_platform_default.c
@@ -0,0 +1,81 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_platform.h"
+
+gctBOOL
+_NeedAddDevice(
+ IN gckPLATFORM Platform
+ )
+{
+ return gcvTRUE;
+}
+
+gcmkPLATFROM_Name
+
+gcsPLATFORM_OPERATIONS platformOperations =
+{
+ .needAddDevice = _NeedAddDevice,
+ .name = _Name,
+};
+
+void
+gckPLATFORM_QueryOperations(
+ IN gcsPLATFORM_OPERATIONS ** Operations
+ )
+{
+ *Operations = &platformOperations;
+}
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.c
new file mode 100644
index 000000000000..89706ec57dbb
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.c
@@ -0,0 +1,1186 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_kernel_platform.h"
+#include "gc_hal_kernel_device.h"
+#include "gc_hal_driver.h"
+#include <linux/slab.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#endif
+
+#if USE_PLATFORM_DRIVER
+# include <linux/platform_device.h>
+#endif
+#include <linux/component.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)) || defined(IMX8_SCU_CONTROL)
+#define IMX_GPU_SUBSYSTEM 1
+#else
+#define IMX_GPU_SUBSYSTEM 0
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+#include <mach/viv_gpu.h>
+#else
+#include <linux/pm_runtime.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+#include <mach/busfreq.h>
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 29)
+#include <linux/busfreq-imx6.h>
+#include <linux/reset.h>
+#else
+#if !defined(IMX8_SCU_CONTROL)
+#include <linux/busfreq-imx.h>
+#endif
+#include <linux/reset.h>
+#endif
+#endif
+
+#include <linux/clk.h>
+
+#if defined(IMX8_SCU_CONTROL)
+#include <soc/imx8/sc/sci.h>
+static sc_ipc_t gpu_ipcHandle;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+#include <mach/hardware.h>
+#endif
+#include <linux/pm_runtime.h>
+
+#include <linux/regulator/consumer.h>
+
+#ifdef CONFIG_DEVICE_THERMAL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#include <linux/device_cooling.h>
+#define REG_THERMAL_NOTIFIER(a) register_devfreq_cooling_notifier(a);
+#define UNREG_THERMAL_NOTIFIER(a) unregister_devfreq_cooling_notifier(a);
+#else
+extern int register_thermal_notifier(struct notifier_block *nb);
+extern int unregister_thermal_notifier(struct notifier_block *nb);
+#define REG_THERMAL_NOTIFIER(a) register_thermal_notifier(a);
+#define UNREG_THERMAL_NOTIFIER(a) unregister_thermal_notifier(a);
+#endif
+#endif
+
+#ifndef gcdFSL_CONTIGUOUS_SIZE
+#define gcdFSL_CONTIGUOUS_SIZE (4 << 20)
+#endif
+
+static int initgpu3DMinClock = 1;
+module_param(initgpu3DMinClock, int, 0644);
+
+struct platform_device *pdevice;
+
+#ifdef CONFIG_GPU_LOW_MEMORY_KILLER
+# include <linux/kernel.h>
+# include <linux/mm.h>
+# include <linux/oom.h>
+# include <linux/sched.h>
+# include <linux/profile.h>
+
+struct task_struct *lowmem_deathpending;
+
+static int
+task_notify_func(struct notifier_block *self, unsigned long val, void *data);
+
+static struct notifier_block task_nb = {
+ .notifier_call = task_notify_func,
+};
+
+static int
+task_notify_func(struct notifier_block *self, unsigned long val, void *data)
+{
+ struct task_struct *task = data;
+
+ if (task == lowmem_deathpending)
+ lowmem_deathpending = NULL;
+
+ return NOTIFY_DONE;
+}
+
+extern struct task_struct *lowmem_deathpending;
+static unsigned long lowmem_deathpending_timeout;
+
+static int force_contiguous_lowmem_shrink(IN gckKERNEL Kernel)
+{
+ struct task_struct *p;
+ struct task_struct *selected = NULL;
+ int tasksize;
+ int ret = -1;
+ int min_adj = 0;
+ int selected_tasksize = 0;
+ int selected_oom_adj;
+ /*
+ * If we already have a death outstanding, then
+ * bail out right away; indicating to vmscan
+ * that we have nothing further to offer on
+ * this pass.
+ *
+ */
+ if (lowmem_deathpending &&
+ time_before_eq(jiffies, lowmem_deathpending_timeout))
+ return 0;
+ selected_oom_adj = min_adj;
+
+ rcu_read_lock();
+ for_each_process(p) {
+ struct mm_struct *mm;
+ struct signal_struct *sig;
+ gcuDATABASE_INFO info;
+ int oom_adj;
+
+ task_lock(p);
+ mm = p->mm;
+ sig = p->signal;
+ if (!mm || !sig) {
+ task_unlock(p);
+ continue;
+ }
+ oom_adj = sig->oom_score_adj;
+ if (oom_adj < min_adj) {
+ task_unlock(p);
+ continue;
+ }
+
+ tasksize = 0;
+ task_unlock(p);
+ rcu_read_unlock();
+
+ if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_VIDEO_MEMORY, &info) == gcvSTATUS_OK){
+ tasksize += info.counters.bytes / PAGE_SIZE;
+ }
+ if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_CONTIGUOUS, &info) == gcvSTATUS_OK){
+ tasksize += info.counters.bytes / PAGE_SIZE;
+ }
+
+ rcu_read_lock();
+
+ if (tasksize <= 0)
+ continue;
+
+ gckOS_Print("<gpu> pid %d (%s), adj %d, size %d \n", p->pid, p->comm, oom_adj, tasksize);
+
+ if (selected) {
+ if (oom_adj < selected_oom_adj)
+ continue;
+ if (oom_adj == selected_oom_adj &&
+ tasksize <= selected_tasksize)
+ continue;
+ }
+ selected = p;
+ selected_tasksize = tasksize;
+ selected_oom_adj = oom_adj;
+ }
+ if (selected && selected_oom_adj > 0) {
+ gckOS_Print("<gpu> send sigkill to %d (%s), adj %d, size %d\n",
+ selected->pid, selected->comm,
+ selected_oom_adj, selected_tasksize);
+ lowmem_deathpending = selected;
+ lowmem_deathpending_timeout = jiffies + HZ;
+ force_sig(SIGKILL, selected);
+ ret = 0;
+ }
+ rcu_read_unlock();
+ return ret;
+}
+
+extern gckKERNEL
+_GetValidKernel(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS
+_ShrinkMemory(
+ IN gckPLATFORM Platform
+ )
+{
+ struct platform_device *pdev;
+ gckGALDEVICE galDevice;
+ gckKERNEL kernel;
+ gceSTATUS status = gcvSTATUS_OK;
+
+ pdev = Platform->device;
+
+ galDevice = platform_get_drvdata(pdev);
+
+ kernel = _GetValidKernel(galDevice);
+
+ if (kernel != gcvNULL)
+ {
+ if (force_contiguous_lowmem_shrink(kernel) != 0)
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ }
+ else
+ {
+ gcmkPRINT("%s(%d) can't find kernel! ", __FUNCTION__, __LINE__);
+ }
+
+ return status;
+}
+#endif
+
+#if gcdENABLE_FSCALE_VAL_ADJUST && (defined(CONFIG_DEVICE_THERMAL) || defined(CONFIG_DEVICE_THERMAL_MODULE))
+static int thermal_hot_pm_notify(struct notifier_block *nb, unsigned long event,
+ void *dummy)
+{
+ static gctUINT orgFscale, minFscale, maxFscale;
+ static gctBOOL bAlreadyTooHot = gcvFALSE;
+ gckHARDWARE hardware;
+ gckGALDEVICE galDevice;
+
+ galDevice = platform_get_drvdata(pdevice);
+ if (!galDevice)
+ {
+ /* GPU is not ready, so it is meaningless to change GPU freq. */
+ return NOTIFY_OK;
+ }
+
+ if (!galDevice->kernels[gcvCORE_MAJOR])
+ {
+ return NOTIFY_OK;
+ }
+
+ hardware = galDevice->kernels[gcvCORE_MAJOR]->hardware;
+
+ if (!hardware)
+ {
+ return NOTIFY_OK;
+ }
+
+ if (event && !bAlreadyTooHot) {
+ gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale);
+ gckHARDWARE_SetFscaleValue(hardware, minFscale);
+ bAlreadyTooHot = gcvTRUE;
+ gckOS_Print("System is too hot. GPU3D will work at %d/64 clock.\n", minFscale);
+ } else if (!event && bAlreadyTooHot) {
+ gckHARDWARE_SetFscaleValue(hardware, orgFscale);
+ gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale);
+ bAlreadyTooHot = gcvFALSE;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block thermal_hot_pm_notifier = {
+ .notifier_call = thermal_hot_pm_notify,
+ };
+
+static ssize_t show_gpu3DMinClock(struct device_driver *dev, char *buf)
+{
+ gctUINT currentf,minf,maxf;
+ gckGALDEVICE galDevice;
+
+ galDevice = platform_get_drvdata(pdevice);
+ if(galDevice->kernels[gcvCORE_MAJOR])
+ {
+ gckHARDWARE_GetFscaleValue(galDevice->kernels[gcvCORE_MAJOR]->hardware,
+ &currentf, &minf, &maxf);
+ }
+ snprintf(buf, PAGE_SIZE, "%d\n", minf);
+ return strlen(buf);
+}
+
+static ssize_t update_gpu3DMinClock(struct device_driver *dev, const char *buf, size_t count)
+{
+
+ gctINT fields;
+ gctUINT MinFscaleValue;
+ gckGALDEVICE galDevice;
+
+ galDevice = platform_get_drvdata(pdevice);
+ if(galDevice->kernels[gcvCORE_MAJOR])
+ {
+ fields = sscanf(buf, "%d", &MinFscaleValue);
+ if (fields < 1)
+ return -EINVAL;
+
+ gckHARDWARE_SetMinFscaleValue(galDevice->kernels[gcvCORE_MAJOR]->hardware,MinFscaleValue);
+ }
+
+ return count;
+}
+
+static DRIVER_ATTR(gpu3DMinClock, S_IRUGO | S_IWUSR, show_gpu3DMinClock, update_gpu3DMinClock);
+#endif
+
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+static const struct of_device_id mxs_gpu_dt_ids[] = {
+#if IMX_GPU_SUBSYSTEM
+ { .compatible = "fsl,imx8-gpu-ss", },
+#endif
+ { .compatible = "fsl,imx6q-gpu", }, /*Backward Compatiblity */
+ {/* sentinel */}
+};
+MODULE_DEVICE_TABLE(of, mxs_gpu_dt_ids);
+#endif
+
+struct gpu_clk {
+ struct clk *clk_core;
+ struct clk *clk_shader;
+ struct clk *clk_axi;
+ struct clk *clk_ahb;
+};
+
+struct imx_priv {
+
+ struct gpu_clk imx_gpu_clks[gcdMAX_GPU_COUNT];
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ /*Power management.*/
+ struct regulator *gpu_regulator;
+#endif
+#endif
+ /*Run time pm*/
+ struct device *pmdev[gcdMAX_GPU_COUNT];
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ struct reset_control *rstc[gcdMAX_GPU_COUNT];
+#endif
+ int gpu3dCount;
+};
+
+static struct imx_priv imxPriv;
+
+#if IMX_GPU_SUBSYSTEM
+static int gpu_device_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ return 0;
+}
+
+static void gpu_device_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+}
+
+static const struct component_ops gpu_ops = {
+ .bind = gpu_device_bind,
+ .unbind = gpu_device_unbind,
+};
+
+static const struct of_device_id gpu_match[] = {
+ { .compatible = "fsl,imx8-gpu"},
+ { /* sentinel */ }
+};
+
+static int gpu_device_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &gpu_ops);
+}
+
+static int gpu_device_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &gpu_ops);
+ return 0;
+}
+struct platform_driver mxc_gpu_driver = {
+ .driver = {
+ .name = "mxc-gpu",
+ .owner = THIS_MODULE,
+ .of_match_table = gpu_match,
+ },
+ .probe = gpu_device_probe,
+ .remove = gpu_device_remove,
+};
+gceSTATUS
+gckPLATFORM_RegisterDevice(
+ IN gckPLATFORM Platform
+ )
+{
+ return platform_driver_register(&mxc_gpu_driver);
+}
+
+gceSTATUS
+gckPLATFORM_UnRegisterDevice(
+ IN gckPLATFORM Platform
+ )
+{
+ platform_driver_unregister(&mxc_gpu_driver);
+ return gcvSTATUS_OK;
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+ struct device_node *np = data;
+
+ return dev->of_node == np;
+}
+#endif
+/*TODO: Fix */
+struct component_match *match = NULL;
+
+gceSTATUS
+gckPLATFORM_AdjustParam(
+ IN gckPLATFORM Platform,
+ OUT gcsMODULE_PARAMETERS *Args
+ )
+{
+ struct resource* res;
+ struct platform_device* pdev = Platform->device;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ struct device_node *dn =pdev->dev.of_node;
+ const u32 *prop;
+#else
+ struct viv_gpu_platform_data *pdata;
+#endif
+#if IMX_GPU_SUBSYSTEM
+ struct device_node *node =pdev->dev.of_node;
+ if (node && Platform->ops->registerDevice) {
+ int i=0;
+ struct device_node *core_node;
+ gctINT core = gcvCORE_MAJOR;
+ while ((core_node = of_parse_phandle(node, "cores", i++)) != NULL) {
+ struct platform_device *pdev_gpu;
+ gctINT irqLine = -1;
+
+ if(!of_device_is_available(core_node)){
+ of_node_put(core_node);
+ continue;
+ }
+ component_match_add(&pdev->dev, &match, compare_of, core_node);
+
+ pdev_gpu = of_find_device_by_node(core_node);
+ if (!pdev_gpu) {
+ break;
+ }
+ irqLine = platform_get_irq(pdev_gpu, 0);
+ if (irqLine < 0) {
+ break;
+ }
+ res = platform_get_resource(pdev_gpu, IORESOURCE_MEM, 0);
+ if (!res) {
+ break;
+ }
+
+ Args->irqs[core] = irqLine;
+ Args->registerBases[core] = res->start;
+ Args->registerSizes[core] = res->end - res->start + 1;
+
+ of_node_put(core_node);
+ ++core;
+ }
+ if(core_node) {
+ of_node_put(core_node);
+ }
+ }
+ else
+#endif
+ {
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d");
+ if (res)
+ Args->irqLine = res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d");
+ if (res)
+ {
+ Args->registerMemBase = res->start;
+ Args->registerMemSize = res->end - res->start + 1;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d");
+ if (res)
+ Args->irqLine2D = res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d");
+ if (res)
+ {
+ Args->registerMemBase2D = res->start;
+ Args->registerMemSize2D = res->end - res->start + 1;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg");
+ if (res)
+ Args->irqLineVG = res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg");
+ if (res)
+ {
+ Args->registerMemBaseVG = res->start;
+ Args->registerMemSizeVG = res->end - res->start + 1;
+ }
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phys_baseaddr");
+ if (res && !Args->baseAddress && !Args->physSize)
+ {
+ Args->baseAddress = res->start;
+ Args->physSize = res->end - res->start + 1;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "contiguous_mem");
+ if (res)
+ {
+ if( Args->contiguousBase == 0 )
+ Args->contiguousBase = res->start;
+ if( Args->contiguousSize == ~0U )
+ Args->contiguousSize = res->end - res->start + 1;
+ }
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ Args->contiguousBase = 0;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ prop = of_get_property(dn, "contiguousbase", NULL);
+ if(prop)
+ Args->contiguousBase = *prop;
+ of_property_read_u32(dn,"contiguoussize", (u32 *)&contiguousSize);
+#else
+ pdata = pdev->dev.platform_data;
+ if (pdata) {
+ Args->contiguousBase = pdata->reserved_mem_base;
+ Args->contiguousSize = pdata->reserved_mem_size;
+ }
+#endif
+ if (Args->contiguousSize == ~0U)
+ {
+ gckOS_Print("Warning: No contiguous memory is reserverd for gpu.!\n ");
+ gckOS_Print("Warning: Will use default value(%d) for the reserved memory!\n ",gcdFSL_CONTIGUOUS_SIZE);
+ Args->contiguousSize = gcdFSL_CONTIGUOUS_SIZE;
+ }
+
+ Args->gpu3DMinClock = initgpu3DMinClock;
+
+ if(Args->physSize == 0)
+ {
+#if defined(IMX8_PHYS_BASE)
+ Args->baseAddress = IMX8_PHYS_BASE;
+#endif
+
+#if defined(IMX8_PHYS_SIZE)
+ Args->physSize = IMX8_PHYS_SIZE;
+#else
+ Args->physSize = 0x80000000;
+#endif
+ }
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_AllocPriv(
+ IN gckPLATFORM Platform
+ )
+{
+ Platform->priv = &imxPriv;
+
+ gckOS_ZeroMemory(Platform->priv, sizeof(imxPriv));
+
+#ifdef CONFIG_GPU_LOW_MEMORY_KILLER
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ task_free_register(&task_nb);
+#else
+ task_handoff_register(&task_nb);
+#endif
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_FreePriv(
+ IN gckPLATFORM Platform
+ )
+{
+#ifdef CONFIG_GPU_LOW_MEMORY_KILLER
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+ task_free_unregister(&task_nb);
+#else
+ task_handoff_unregister(&task_nb);
+#endif
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_SetClock(
+ IN gckPLATFORM Platform,
+ IN gceCORE GPU,
+ IN gctBOOL Enable
+ );
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+static void imx6sx_optimize_qosc_for_GPU(IN gckPLATFORM Platform)
+{
+ struct device_node *np;
+ void __iomem *src_base;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-qosc");
+ if (!np)
+ return;
+
+ src_base = of_iomap(np, 0);
+ WARN_ON(!src_base);
+ _SetClock(Platform, gcvCORE_MAJOR, gcvTRUE);
+ writel_relaxed(0, src_base); /* Disable clkgate & soft_rst */
+ writel_relaxed(0, src_base+0x60); /* Enable all masters */
+ writel_relaxed(0, src_base+0x1400); /* Disable clkgate & soft_rst for gpu */
+ writel_relaxed(0x0f000222, src_base+0x1400+0xd0); /* Set Write QoS 2 for gpu */
+ writel_relaxed(0x0f000822, src_base+0x1400+0xe0); /* Set Read QoS 8 for gpu */
+ _SetClock(Platform, gcvCORE_MAJOR, gcvFALSE);
+ return;
+}
+#endif
+
+gceSTATUS
+_GetPower(
+ IN gckPLATFORM Platform
+ )
+{
+ struct device* pdev = &Platform->device->dev;
+ struct imx_priv *priv = Platform->priv;
+#if IMX_GPU_SUBSYSTEM
+ struct device_node *node = pdev->of_node;
+#endif
+ struct clk *clk_core = NULL;
+ struct clk *clk_shader = NULL;
+ struct clk *clk_axi = NULL;
+
+ /*Initialize the clock structure*/
+#if IMX_GPU_SUBSYSTEM
+ if (node && Platform->ops->registerDevice) {
+ int i=0;
+ struct device_node *core_node;
+ gctINT core = gcvCORE_MAJOR;
+#if defined(IMX8_SCU_CONTROL)
+ sc_err_t sciErr;
+ uint32_t mu_id;
+ sc_rsrc_t sc_gpu_pid[gcdMAX_GPU_COUNT];
+
+ sciErr = sc_ipc_getMuID(&mu_id);
+ if (sciErr != SC_ERR_NONE) {
+ gckOS_Print("galcore; cannot obtain mu id\n");
+ return gcvSTATUS_FALSE;
+ }
+
+ sciErr = sc_ipc_open(&gpu_ipcHandle, mu_id);
+ if (sciErr != SC_ERR_NONE) {
+ gckOS_Print("galcore: cannot open MU channel to SCU\n");
+ return gcvSTATUS_FALSE;
+ };
+#endif
+ while ((core_node = of_parse_phandle(node, "cores", i++)) != NULL) {
+ struct platform_device *pdev_gpu = NULL;
+ clk_shader = NULL;
+ clk_core = NULL;
+ clk_axi = NULL;
+
+ if(!of_device_is_available(core_node)){
+ of_node_put(core_node);
+ continue;
+ }
+
+ pdev_gpu = of_find_device_by_node(core_node);
+ if (!pdev_gpu) {
+ break;
+ }
+ clk_core = clk_get(&pdev_gpu->dev, "core");
+ if (IS_ERR(clk_core)) {
+ gckOS_Print("galcore: clk_get clk_core failed\n");
+ break;
+ }
+ clk_axi = clk_get(&pdev_gpu->dev, "bus");
+ if (IS_ERR(clk_axi)) {
+ clk_axi = NULL;
+ }
+
+ clk_shader = clk_get(&pdev_gpu->dev, "shader");
+ if (IS_ERR(clk_shader)) {
+ gckOS_Print("galcore: clk_get clk_3d_shader failed\n");
+ continue;
+ }
+
+ priv->imx_gpu_clks[core].clk_shader = clk_shader;
+ priv->imx_gpu_clks[core].clk_core = clk_core;
+ priv->imx_gpu_clks[core].clk_axi = clk_axi;
+
+#if defined(IMX8_SCU_CONTROL)
+ if(!of_property_read_u32(core_node, "fsl,sc_gpu_pid", &sc_gpu_pid[core]))
+ {
+ sciErr = sc_misc_set_control(gpu_ipcHandle, sc_gpu_pid[core], SC_C_ID, core);
+ if (sciErr != SC_ERR_NONE)
+ gckOS_Print("galcore: failed to set gpu id for 3d_%d\n", core);
+
+ /* set single mode by default to avoid the potential impact by inter-signals */
+ sciErr = sc_misc_set_control(gpu_ipcHandle, sc_gpu_pid[core], SC_C_SINGLE_MODE, 1);
+ if (sciErr != SC_ERR_NONE)
+ gckOS_Print("galcore: failed to set gpu single mode for 3d_%d\n", core);
+ }
+#endif
+
+#ifdef CONFIG_PM
+ pm_runtime_enable(&pdev_gpu->dev);
+ priv->pmdev[core] = &pdev_gpu->dev;
+#endif
+ of_node_put(core_node);
+ core++;
+ }
+ priv->gpu3dCount = core;
+
+ if(core_node) {
+ of_node_put(core_node);
+ }
+#if defined(IMX8_SCU_CONTROL)
+ if(priv->gpu3dCount > 1) {
+ for (core=gcvCORE_MAJOR; core <priv->gpu3dCount; core++)
+ {
+ if (sc_gpu_pid[core])
+ {
+ sciErr = sc_misc_set_control(gpu_ipcHandle, sc_gpu_pid[core], SC_C_SINGLE_MODE, 0);
+ if (sciErr != SC_ERR_NONE)
+ gckOS_Print("galcore: failed to set gpu dual mode for 3d_%d\n", core);
+ }
+ }
+ }
+#endif
+ }
+ else
+#endif
+ {
+#ifdef CONFIG_RESET_CONTROLLER
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ struct reset_control *rstc;
+ rstc = devm_reset_control_get(pdev, "gpu3d");
+ priv->rstc[gcvCORE_MAJOR] = IS_ERR(rstc) ? NULL : rstc;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)
+ rstc = devm_reset_control_get_shared(pdev, "gpu2d");
+ priv->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc;
+ rstc = devm_reset_control_get_shared(pdev, "gpuvg");
+#else
+ rstc = devm_reset_control_get(pdev, "gpu2d");
+ priv->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc;
+ rstc = devm_reset_control_get(pdev, "gpuvg");
+#endif
+ priv->rstc[gcvCORE_VG] = IS_ERR(rstc) ? NULL : rstc;
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+ /*get gpu regulator*/
+ priv->gpu_regulator = regulator_get(pdev, "cpu_vddgpu");
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ priv->gpu_regulator = devm_regulator_get(pdev, "pu");
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ if (IS_ERR(priv->gpu_regulator)) {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to get gpu regulator \n",
+ __FUNCTION__, __LINE__);
+ return gcvSTATUS_NOT_FOUND;
+ }
+#endif
+#endif
+ clk_core = clk_get(pdev, "gpu3d_clk");
+ if (!IS_ERR(clk_core)) {
+ clk_axi = clk_get(pdev, "gpu3d_axi_clk");
+ clk_shader = clk_get(pdev, "gpu3d_shader_clk");
+ if (IS_ERR(clk_shader)) {
+ clk_put(clk_core);
+ clk_core = NULL;
+ clk_shader = NULL;
+ gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
+ }
+ } else {
+ clk_core = NULL;
+ gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
+ }
+
+ priv->imx_gpu_clks[gcvCORE_MAJOR].clk_core = clk_core;
+ priv->imx_gpu_clks[gcvCORE_MAJOR].clk_shader = clk_shader;
+ priv->imx_gpu_clks[gcvCORE_MAJOR].clk_axi = clk_axi;
+
+ clk_core = clk_get(pdev, "gpu2d_clk");
+ if (IS_ERR(clk_core)) {
+ clk_core = NULL;
+ gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n");
+ } else {
+ clk_axi = clk_get(pdev, "gpu2d_axi_clk");
+ if (IS_ERR(clk_axi)) {
+ clk_axi = NULL;
+ gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n");
+ }
+
+ priv->imx_gpu_clks[gcvCORE_2D].clk_core = clk_core;
+ priv->imx_gpu_clks[gcvCORE_2D].clk_axi = clk_axi;
+
+ clk_axi = clk_get(pdev, "openvg_axi_clk");
+ if (IS_ERR(clk_axi)) {
+ clk_axi = NULL;
+ gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n");
+ }
+
+ priv->imx_gpu_clks[gcvCORE_VG].clk_core = clk_core;
+ priv->imx_gpu_clks[gcvCORE_VG].clk_axi = clk_axi;
+ }
+
+#ifdef CONFIG_PM
+ pm_runtime_enable(pdev);
+ priv->pmdev[gcvCORE_MAJOR] = pdev;
+ priv->pmdev[gcvCORE_2D] = pdev;
+ priv->pmdev[gcvCORE_VG] = pdev;
+#endif
+ }
+
+#if gcdENABLE_FSCALE_VAL_ADJUST && (defined(CONFIG_DEVICE_THERMAL) || defined(CONFIG_DEVICE_THERMAL_MODULE))
+ pdevice = Platform->device;
+ REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
+ {
+ int ret = 0;
+ ret = driver_create_file(pdevice->dev.driver, &driver_attr_gpu3DMinClock);
+ if(ret)
+ dev_err(&pdevice->dev, "create gpu3DMinClock attr failed (%d)\n", ret);
+ }
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ imx6sx_optimize_qosc_for_GPU(Platform);
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_PutPower(
+ IN gckPLATFORM Platform
+ )
+{
+ int core=0;
+ struct gpu_clk *imx_clk = NULL;
+ struct imx_priv *priv = Platform->priv;
+ struct device *pmdev_last = NULL;/*legacy gpu device entry for imx6*/
+ struct clk *clk_core_last = NULL;/*vg has same core clk as 2d */
+
+ for (core =0; core < gcdMAX_GPU_COUNT; core++)
+ {
+ imx_clk = &priv->imx_gpu_clks[core];
+
+ if(imx_clk->clk_core && imx_clk->clk_core != clk_core_last) {
+ clk_put(imx_clk->clk_core);
+ clk_core_last = imx_clk->clk_core;
+ imx_clk->clk_core = NULL;
+ }
+
+ if(imx_clk->clk_shader) {
+ clk_put(imx_clk->clk_shader);
+ imx_clk->clk_shader = NULL;
+ }
+
+ if(imx_clk->clk_axi) {
+ clk_put(imx_clk->clk_axi);
+ imx_clk->clk_axi = NULL;
+ }
+
+#ifdef CONFIG_PM
+ if(priv->pmdev[core] && priv->pmdev[core] != pmdev_last){
+ pm_runtime_disable(priv->pmdev[core]);
+ pmdev_last = priv->pmdev[core];
+ }
+#endif
+ }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+ if (priv->gpu_regulator) {
+ regulator_put(priv->gpu_regulator);
+ priv->gpu_regulator = NULL;
+ }
+#endif
+
+#if gcdENABLE_FSCALE_VAL_ADJUST && (defined(CONFIG_DEVICE_THERMAL) || defined(CONFIG_DEVICE_THERMAL_MODULE))
+ UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
+
+ driver_remove_file(pdevice->dev.driver, &driver_attr_gpu3DMinClock);
+#endif
+
+#if defined(IMX8_SCU_CONTROL)
+ if (gpu_ipcHandle)
+ sc_ipc_close(gpu_ipcHandle);
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_SetPower(
+ IN gckPLATFORM Platform,
+ IN gceCORE GPU,
+ IN gctBOOL Enable
+ )
+{
+#ifdef CONFIG_PM
+ struct imx_priv* priv = Platform->priv;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ int ret;
+#endif
+#endif
+
+ if (Enable)
+ {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ if(!IS_ERR(priv->gpu_regulator)) {
+ ret = regulator_enable(priv->gpu_regulator);
+ if (ret != 0)
+ gckOS_Print("%s(%d): fail to enable pu regulator %d!\n",
+ __FUNCTION__, __LINE__, ret);
+ }
+#else
+ imx_gpc_power_up_pu(true);
+#endif
+#endif
+
+#ifdef CONFIG_PM
+ pm_runtime_get_sync(priv->pmdev[GPU]);
+#endif
+ }
+ else
+ {
+#ifdef CONFIG_PM
+ pm_runtime_put_sync(priv->pmdev[GPU]);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ if(!IS_ERR(priv->gpu_regulator))
+ regulator_disable(priv->gpu_regulator);
+#else
+ imx_gpc_power_up_pu(false);
+#endif
+#endif
+
+ }
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_SetClock(
+ IN gckPLATFORM Platform,
+ IN gceCORE GPU,
+ IN gctBOOL Enable
+ )
+{
+ struct imx_priv* priv = Platform->priv;
+ struct clk *clk_core = priv->imx_gpu_clks[GPU].clk_core;
+ struct clk *clk_shader = priv->imx_gpu_clks[GPU].clk_shader;
+ struct clk *clk_axi = priv->imx_gpu_clks[GPU].clk_axi;
+
+ if (Enable) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ if(clk_core) clk_prepare(clk_core);
+ if(clk_shader) clk_prepare(clk_shader);
+ if(clk_axi) clk_prepare(clk_axi);
+#endif
+ if(clk_core) clk_enable(clk_core);
+ if(clk_shader) clk_enable(clk_shader);
+ if(clk_axi) clk_enable(clk_axi);
+ } else {
+ if(clk_core) clk_disable(clk_core);
+ if(clk_shader) clk_disable(clk_shader);
+ if(clk_axi) clk_disable(clk_axi);
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ if(clk_core) clk_unprepare(clk_core);
+ if(clk_shader) clk_unprepare(clk_shader);
+ if(clk_axi) clk_unprepare(clk_axi);
+#endif
+ }
+
+ return gcvSTATUS_OK;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int gpu_runtime_suspend(struct device *dev)
+{
+ release_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+
+static int gpu_runtime_resume(struct device *dev)
+{
+ request_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops gpu_pm_ops;
+#endif
+#endif
+
+gceSTATUS
+_AdjustDriver(
+ IN gckPLATFORM Platform
+ )
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ struct platform_driver * driver = Platform->driver;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ driver->driver.of_match_table = mxs_gpu_dt_ids;
+#endif
+
+#ifdef CONFIG_PM
+ /* Override PM callbacks to add runtime PM callbacks. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+ /* Fill local structure with original value. */
+ memcpy(&gpu_pm_ops, driver->driver.pm, sizeof(struct dev_pm_ops));
+
+ /* Add runtime PM callback. */
+#ifdef CONFIG_PM_RUNTIME
+ gpu_pm_ops.runtime_suspend = gpu_runtime_suspend;
+ gpu_pm_ops.runtime_resume = gpu_runtime_resume;
+ gpu_pm_ops.runtime_idle = NULL;
+#endif
+
+ /* Replace callbacks. */
+ driver->driver.pm = &gpu_pm_ops;
+#endif
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+_Reset(
+ IN gckPLATFORM Platform,
+ gceCORE GPU
+ )
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+#define SRC_SCR_OFFSET 0
+#define BP_SRC_SCR_GPU3D_RST 1
+#define BP_SRC_SCR_GPU2D_RST 4
+ void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
+ gctUINT32 bit_offset,val;
+
+ if(GPU == gcvCORE_MAJOR) {
+ bit_offset = BP_SRC_SCR_GPU3D_RST;
+ } else if((GPU == gcvCORE_VG)
+ ||(GPU == gcvCORE_2D)) {
+ bit_offset = BP_SRC_SCR_GPU2D_RST;
+ } else {
+ return gcvSTATUS_INVALID_CONFIG;
+ }
+ val = __raw_readl(src_base + SRC_SCR_OFFSET);
+ val &= ~(1 << (bit_offset));
+ val |= (1 << (bit_offset));
+ __raw_writel(val, src_base + SRC_SCR_OFFSET);
+
+ while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
+ (1 << (bit_offset))) != 0) {
+ }
+
+ return gcvSTATUS_NOT_SUPPORTED;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ struct imx_priv* priv = Platform->priv;
+ struct reset_control *rstc = priv->rstc[GPU];
+ if (rstc)
+ reset_control_reset(rstc);
+#else
+ imx_src_reset_gpu((int)GPU);
+#endif
+ return gcvSTATUS_OK;
+}
+
+gcmkPLATFROM_Name
+
+gcsPLATFORM_OPERATIONS platformOperations = {
+ .adjustParam = gckPLATFORM_AdjustParam,
+ .allocPriv = _AllocPriv,
+ .freePriv = _FreePriv,
+ .getPower = _GetPower,
+ .putPower = _PutPower,
+ .setPower = _SetPower,
+ .setClock = _SetClock,
+ .reset = _Reset,
+ .adjustDriver = _AdjustDriver,
+#ifdef CONFIG_GPU_LOW_MEMORY_KILLER
+ .shrinkMemory = _ShrinkMemory,
+#endif
+#if IMX_GPU_SUBSYSTEM
+ .registerDevice = gckPLATFORM_RegisterDevice,
+ .unRegisterDevice = gckPLATFORM_UnRegisterDevice,
+#endif
+ .name = _Name,
+};
+
+void
+gckPLATFORM_QueryOperations(
+ IN gcsPLATFORM_OPERATIONS ** Operations
+ )
+{
+#if IMX_GPU_SUBSYSTEM
+ if (!of_find_compatible_node(NULL, NULL, "fsl,imx8-gpu-ss")) {
+ platformOperations.registerDevice = NULL;
+ platformOperations.unRegisterDevice = NULL;
+ }
+#endif
+
+ *Operations = &platformOperations;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.config b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.config
new file mode 100644
index 000000000000..edbabab4dfe3
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.config
@@ -0,0 +1,27 @@
+EXTRA_CFLAGS += -DgcdDEFAULT_CONTIGUOUS_SIZE=~0U
+EXTRA_CFLAGS += -DgcdFSL_CONTIGUOUS_SIZE=134217728
+
+ifneq ($(CONFIG_ANDROID),)
+# build for android
+EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=2
+EXTRA_CFLAGS += -DgcdANDROID
+ifeq ($(CONFIG_SYNC)$(CONFIG_SYNC_FILE),)
+$(warn CONFIG_SYNC or CONFIG_SYNC_FILE is not set in kernel config)
+$(warn Android native fence sync requires CONFIG_SYNC or CONFIG_SYNC_FILE)
+endif
+endif
+
+ifneq ($(CONFIG_ARCH_FSL_IMX8QM),)
+EXTRA_CFLAGS += -DIMX8_SCU_CONTROL=1 -DIMX8_PHYS_BASE=0x80000000 -DIMX8_PHYS_SIZE=0x80000000
+endif
+
+EXTRA_CFLAGS += -DLINUX_CMA_FSL=1
+ALLOCATOR_ARRAY_H_LOCATION := $(OS_KERNEL_DIR)/allocator/freescale
+CUSTOMER_ALLOCATOR_OBJS := $(ALLOCATOR_ARRAY_H_LOCATION)/gc_hal_kernel_allocator_cma.o
+
+EXTRA_CFLAGS += -DCLASS_NAME=\"gpu_class\"
+
+EXTRA_CFLAGS += -DgcdGPU_2D_TIMEOUT=20000
+EXTRA_CFLAGS += -DgcdSYS_FREE_MEMORY_LIMIT=51200
+
+EXTRA_CFLAGS += -DNO_DMA_COHERENT=1
diff --git a/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c
new file mode 100644
index 000000000000..ac4958bb2678
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.c
@@ -0,0 +1,348 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_types.h"
+#include "gc_hal_base.h"
+#include "gc_hal_security_interface.h"
+#include "gc_hal_ta.h"
+#include "gc_hal.h"
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/*
+* Responsibility of TA (trust application).
+* 1) Start FE.
+* When non secure driver asks for start FE. TA enable MMU and start FE.
+* TA always execute MMU enable processes because it has no idea whether
+* GPU has been power off.
+*
+* 2) Setup page table
+* When non secure driver asks for set up GPU address to physical address
+* mapping, TA check the attribute of physical address and attribute of
+* GPU address to make sure they are match. Then it change page table.
+*
+*/
+
+gcTA_MMU SharedMmu = gcvNULL;
+
+/*******************************************************************************
+**
+** gcTA_Construct
+**
+** Construct a new gcTA object.
+*/
+int
+gcTA_Construct(
+ IN gctaOS Os,
+ IN gceCORE Core,
+ OUT gcTA *TA
+ )
+{
+ gceSTATUS status;
+ gctPOINTER pointer;
+ gcTA ta = gcvNULL;
+
+ gcmkHEADER();
+ gcmkVERIFY_ARGUMENT(TA != gcvNULL);
+
+ /* Construct a gcTA object. */
+ gcmkONERROR(gctaOS_Allocate(sizeof(struct _gcTA), &pointer));
+
+ gctaOS_ZeroMemory(pointer, sizeof(struct _gcTA));
+
+ ta = (gcTA)pointer;
+
+ ta->os = Os;
+ ta->core = Core;
+
+ gcmkONERROR(gctaHARDWARE_Construct(ta, &ta->hardware));
+
+ if (gctaHARDWARE_IsFeatureAvailable(ta->hardware, gcvFEATURE_SECURITY))
+ {
+ if (SharedMmu == gcvNULL)
+ {
+ gcmkONERROR(gctaMMU_Construct(ta, &ta->mmu));
+
+ /* Record shared MMU. */
+ SharedMmu = ta->mmu;
+ ta->destoryMmu = gcvTRUE;
+ }
+ else
+ {
+ ta->mmu = SharedMmu;
+ ta->destoryMmu = gcvFALSE;
+ }
+
+ gcmkONERROR(gctaHARDWARE_PrepareFunctions(ta->hardware));
+ }
+
+ *TA = ta;
+
+ gcmkFOOTER_NO();
+ return 0;
+
+OnError:
+ if (ta)
+ {
+ if (ta->mmu && ta->destoryMmu)
+ {
+ gcmkVERIFY_OK(gctaMMU_Destory(ta->mmu));
+ }
+
+ if (ta->hardware)
+ {
+ gcmkVERIFY_OK(gctaHARDWARE_Destroy(ta->hardware));
+ }
+
+ gcmkVERIFY_OK(gctaOS_Free(ta));
+ }
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gcTA_Construct
+**
+** Destroy a gcTA object.
+*/
+int
+gcTA_Destroy(
+ IN gcTA TA
+ )
+{
+ if (TA->mmu && TA->destoryMmu)
+ {
+ gcmkVERIFY_OK(gctaMMU_Destory(TA->mmu));
+ }
+
+ if (TA->hardware)
+ {
+ gcmkVERIFY_OK(gctaHARDWARE_Destroy(TA->hardware));
+ }
+
+ gcmkVERIFY_OK(gctaOS_Free(TA));
+
+ /* Destroy. */
+ return 0;
+}
+
+
+/*
+* Map a scatter gather list into gpu address space.
+*
+*/
+gceSTATUS
+gcTA_MapMemory(
+ IN gcTA TA,
+ IN gctUINT32 *PhysicalArray,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctUINT32 PageCount,
+ OUT gctUINT32 *GPUAddress
+ )
+{
+ gceSTATUS status;
+ gcTA_MMU mmu;
+ gctUINT32 pageCount = PageCount;
+ gctUINT32 i;
+ gctUINT32 gpuAddress = *GPUAddress;
+ gctBOOL mtlbSecure = gcvFALSE;
+ gctBOOL physicalSecure = gcvFALSE;
+
+ mmu = TA->mmu;
+
+ /* Fill in page table. */
+ for (i = 0; i < pageCount; i++)
+ {
+ gctUINT32 physical;
+ gctUINT32_PTR entry;
+
+ if (PhysicalArray)
+ {
+ physical = PhysicalArray[i];
+ }
+ else
+ {
+ physical = (gctUINT32)Physical + 4096 * i;
+ }
+
+ gcmkONERROR(gctaMMU_GetPageEntry(mmu, gpuAddress, gcvNULL, &entry, &mtlbSecure));
+
+ status = gctaOS_IsPhysicalSecure(TA->os, physical, &physicalSecure);
+
+ if (gcmIS_SUCCESS(status) && physicalSecure != mtlbSecure)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ gctaMMU_SetPage(mmu, physical, entry);
+
+ gpuAddress += 4096;
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gcTA_UnmapMemory(
+ IN gcTA TA,
+ IN gctUINT32 GPUAddress,
+ IN gctUINT32 PageCount
+ )
+{
+ gceSTATUS status;
+
+ gcmkONERROR(gctaMMU_FreePages(TA->mmu, GPUAddress, PageCount));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gcTA_StartCommand(
+ IN gcTA TA,
+ IN gctUINT32 Address,
+ IN gctUINT32 Bytes
+ )
+{
+ gctaHARDWARE_Execute(TA, Address, Bytes);
+ return gcvSTATUS_OK;
+}
+
+int
+gcTA_Dispatch(
+ IN gcTA TA,
+ IN gcsTA_INTERFACE * Interface
+ )
+{
+ int command = Interface->command;
+
+ gceSTATUS status = gcvSTATUS_OK;
+
+ switch (command)
+ {
+ case KERNEL_START_COMMAND:
+ /* Enable MMU every time FE starts.
+ ** Because if normal world stop GPU and power off GPU, MMU states is reset.
+ */
+ gcmkONERROR(gctaHARDWARE_SetMMU(TA->hardware, TA->mmu->mtlbLogical));
+
+ gcmkONERROR(gcTA_StartCommand(
+ TA,
+ Interface->u.StartCommand.address,
+ Interface->u.StartCommand.bytes
+ ));
+ break;
+
+ case KERNEL_MAP_MEMORY:
+ gcmkONERROR(gcTA_MapMemory(
+ TA,
+ Interface->u.MapMemory.physicals,
+ Interface->u.MapMemory.physical,
+ Interface->u.MapMemory.pageCount,
+ &Interface->u.MapMemory.gpuAddress
+ ));
+
+ break;
+
+ case KERNEL_UNMAP_MEMORY:
+ status = gcTA_UnmapMemory(
+ TA,
+ Interface->u.UnmapMemory.gpuAddress,
+ Interface->u.UnmapMemory.pageCount
+ );
+ break;
+
+ case KERNEL_DUMP_MMU_EXCEPTION:
+ status = gctaHARDWARE_DumpMMUException(TA->hardware);
+ break;
+
+ case KERNEL_HANDLE_MMU_EXCEPTION:
+ status = gctaHARDWARE_HandleMMUException(
+ TA->hardware,
+ Interface->u.HandleMMUException.mmuStatus,
+ Interface->u.HandleMMUException.physical,
+ Interface->u.HandleMMUException.gpuAddress
+ );
+ break;
+
+ case KERNEL_READ_MMU_EXCEPTION:
+ status = gctaHARDWARE_ReadMMUException(
+ TA->hardware,
+ &Interface->u.ReadMMUException.mmuStatus,
+ &Interface->u.ReadMMUException.mmuException
+ );
+ break;
+
+ default:
+ gcmkASSERT(0);
+
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+
+OnError:
+ Interface->result = status;
+
+ return 0;
+}
+
+
+
diff --git a/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.h b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.h
new file mode 100644
index 000000000000..340e58d94fe5
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta.h
@@ -0,0 +1,373 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef _GC_HAL_TA_H_
+#define _GC_HAL_TA_H_
+#include "gc_hal_types.h"
+#include "gc_hal_security_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct _gctaOS * gctaOS;
+typedef struct _gcTA * gcTA;
+
+typedef struct _gcTA_HARDWARE * gcTA_HARDWARE;
+typedef struct _gcTA_MMU * gcTA_MMU;
+
+/*
+ Trust Application is a object needed to be created as a context in trust zone.
+ One client for a core.
+*/
+typedef struct _gcTA {
+ /* gctaOS object */
+ gctaOS os;
+
+ gceCORE core;
+
+ gcTA_MMU mmu;
+
+ gcTA_HARDWARE hardware;
+
+ gctBOOL destoryMmu;
+} gcsTA;
+
+typedef struct _gcTA_MMU
+{
+ gctaOS os;
+
+ gctSIZE_T mtlbBytes;
+ gctPOINTER mtlbLogical;
+ gctPHYS_ADDR mtlbPhysical;
+
+ gctPOINTER stlbs;
+
+ gctPOINTER safePageLogical;
+ gctPHYS_ADDR safePagePhysical;
+
+ gctPOINTER nonSecureSafePageLogical;
+ gctPHYS_ADDR nonSecureSafePagePhysical;
+
+ gctPOINTER mutex;
+}
+gcsTA_MMU;
+
+gceSTATUS HALDECL
+TAEmulator(
+ gceCORE Core,
+ void * Interface
+ );
+
+int
+gcTA_Construct(
+ IN gctaOS Os,
+ IN gceCORE Core,
+ OUT gcTA *TA
+);
+
+int
+gcTA_Destroy(
+ IN gcTA TA
+);
+
+int
+gcTA_Dispatch(
+ IN gcTA TA,
+ IN OUT gcsTA_INTERFACE * Interface
+);
+
+/*************************************
+* Porting layer
+*/
+
+gceSTATUS
+gctaOS_ConstructOS(
+ IN gckOS Os,
+ OUT gctaOS *TAos
+ );
+
+gceSTATUS
+gctaOS_DestroyOS(
+ IN gctaOS Os
+ );
+
+gceSTATUS
+gctaOS_Allocate(
+ IN gctUINT32 Bytes,
+ OUT gctPOINTER *Pointer
+ );
+
+gceSTATUS
+gctaOS_Free(
+ IN gctPOINTER Pointer
+ );
+
+gceSTATUS
+gctaOS_AllocateSecurityMemory(
+ IN gctaOS Os,
+ IN gctSIZE_T *Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPOINTER *Physical
+ );
+
+gceSTATUS
+gctaOS_FreeSecurityMemory(
+ IN gctaOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical,
+ OUT gctPOINTER Physical
+ );
+
+gceSTATUS
+gctaOS_AllocateNonSecurityMemory(
+ IN gctaOS Os,
+ IN gctSIZE_T *Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPOINTER *Physical
+ );
+
+gceSTATUS
+gctaOS_FreeNonSecurityMemory(
+ IN gctaOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical,
+ OUT gctPOINTER Physical
+ );
+
+
+
+gceSTATUS
+gctaOS_GetPhysicalAddress(
+ IN gctaOS Os,
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Physical
+ );
+
+gceSTATUS gctaOS_WriteRegister(
+ IN gctaOS Os, IN gceCORE Core,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+gceSTATUS gctaOS_ReadRegister(
+ IN gctaOS Os, IN gceCORE Core,
+ IN gctUINT32 Address,
+ IN gctUINT32 *Data
+ );
+
+gceSTATUS
+gctaOS_MemCopy(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT8_PTR Src,
+ IN gctUINT32 Bytes
+ );
+
+gceSTATUS
+gctaOS_ZeroMemory(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT32 Bytes
+ );
+
+void
+gctaOS_CacheFlush(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT32 Bytes
+ );
+
+void
+gctaOS_CacheClean(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT32 Bytes
+ );
+
+void
+gctaOS_CacheInvalidate(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT32 Bytes
+ );
+
+gceSTATUS
+gctaOS_IsPhysicalSecure(
+ IN gctaOS Os,
+ IN gctUINT32 Physical,
+ OUT gctBOOL *Secure
+ );
+
+gceSTATUS
+gctaOS_Delay(
+ IN gctaOS Os,
+ IN gctUINT32 Delay
+ );
+
+gceSTATUS
+gctaOS_SetGPUPower(
+ IN gctaOS Os,
+ IN gctUINT32 Core,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ );
+
+/*
+** gctaHARDWARE
+*/
+gceSTATUS
+gctaHARDWARE_Construct(
+ IN gcTA TA,
+ OUT gcTA_HARDWARE * Hardware
+ );
+
+gceSTATUS
+gctaHARDWARE_Destroy(
+ IN gcTA_HARDWARE Hardware
+ );
+
+gceSTATUS
+gctaHARDWARE_Execute(
+ IN gcTA TA,
+ IN gctUINT32 Address,
+ IN gctUINT32 Bytes
+ );
+
+gceSTATUS
+gctaHARDWARE_End(
+ IN gcTA_HARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ );
+
+gceSTATUS
+gctaHARDWARE_SetMMU(
+ IN gcTA_HARDWARE Hardware,
+ IN gctPOINTER Logical
+ );
+
+gceSTATUS
+gctaHARDWARE_IsFeatureAvailable(
+ IN gcTA_HARDWARE Hardware,
+ IN gceFEATURE Feature
+ );
+
+gceSTATUS
+gctaHARDWARE_PrepareFunctions(
+ IN gcTA_HARDWARE Hardware
+ );
+
+gceSTATUS
+gctaHARDWARE_DumpMMUException(
+ IN gcTA_HARDWARE Hardware
+ );
+
+gceSTATUS
+gctaHARDWARE_HandleMMUException(
+ IN gcTA_HARDWARE Hardware,
+ IN gctUINT32 MMUStatus,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctUINT32 GPUAddress
+ );
+
+gceSTATUS
+gctaHARDWARE_ReadMMUException(
+ IN gcTA_HARDWARE Hardware,
+ OUT gctUINT32_PTR MMUStatus,
+ OUT gctUINT32_PTR MMUException
+ );
+
+gceSTATUS
+gctaMMU_Construct(
+ IN gcTA TA,
+ OUT gcTA_MMU *Mmu
+ );
+
+gceSTATUS
+gctaMMU_Destory(
+ IN gcTA_MMU Mmu
+ );
+
+gceSTATUS
+gctaMMU_SetPage(
+ IN gcTA_MMU Mmu,
+ IN gctUINT32 PageAddress,
+ IN gctUINT32 *PageEntry
+ );
+
+gceSTATUS
+gctaMMU_GetPageEntry(
+ IN gcTA_MMU Mmu,
+ IN gctUINT32 Address,
+ OUT gctUINT32_PTR MtlbEntry,
+ OUT gctUINT32_PTR *PageTable,
+ OUT gctBOOL * Secure
+ );
+
+void
+gctaMMU_DumpPagetableEntry(
+ IN gcTA_MMU Mmu,
+ IN gctUINT32 Address
+ );
+
+gceSTATUS
+gctaMMU_FreePages(
+ IN gcTA_MMU Mmu,
+ IN gctUINT32 Address,
+ IN gctUINT32 PageCount
+ );
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_hardware.c b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_hardware.c
new file mode 100644
index 000000000000..a8e1a0ec4ba5
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_hardware.c
@@ -0,0 +1,964 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_types.h"
+#include "gc_hal_base.h"
+#include "gc_hal_security_interface.h"
+#include "gc_hal_ta.h"
+#include "gc_hal_ta_hardware.h"
+#include "gc_hal.h"
+#include "gc_feature_database.h"
+
+
+#define _GC_OBJ_ZONE 1
+#define SRC_MAX 8
+#define RECT_ADDR_OFFSET 3
+
+#define INVALID_ADDRESS ~0U
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+static gceSTATUS
+_IdentifyHardwareByDatabase(
+ IN gcTA_HARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 chipIdentity;
+ gcsFEATURE_DATABASE *database;
+ gctaOS os = Hardware->os;
+
+ gcmkHEADER();
+
+ /***************************************************************************
+ ** Get chip ID and revision.
+ */
+
+ /* Read chip identity register. */
+ gcmkONERROR(gctaOS_ReadRegister(os, Hardware->ta->core, 0x00018, &chipIdentity));
+
+ /* Special case for older graphic cores. */
+ if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ?
+ 31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
+ 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+ {
+ Hardware->chipModel = gcv500;
+ Hardware->chipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+ }
+
+ else
+ {
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gctaOS_ReadRegister(os, Hardware->ta->core,
+ 0x00020,
+ (gctUINT32_PTR) &Hardware->chipModel));
+
+ if (((Hardware->chipModel & 0xFF00) == 0x0400)
+ && (Hardware->chipModel != 0x0420)
+ && (Hardware->chipModel != 0x0428))
+ {
+ Hardware->chipModel = (gceCHIPMODEL) (Hardware->chipModel & 0x0400);
+ }
+
+ /* Read CHIP_REV register. */
+ gcmkONERROR(
+ gctaOS_ReadRegister(os, Hardware->ta->core,
+ 0x00024,
+ &Hardware->chipRevision));
+
+ if ((Hardware->chipModel == gcv300)
+ && (Hardware->chipRevision == 0x2201)
+ )
+ {
+ gctUINT32 chipDate;
+ gctUINT32 chipTime;
+
+ /* Read date and time registers. */
+ gcmkONERROR(
+ gctaOS_ReadRegister(os, Hardware->ta->core,
+ 0x00028,
+ &chipDate));
+
+ gcmkONERROR(
+ gctaOS_ReadRegister(os, Hardware->ta->core,
+ 0x0002C,
+ &chipTime));
+
+ if ((chipDate == 0x20080814) && (chipTime == 0x12051100))
+ {
+ /* This IP has an ECO; put the correct revision in it. */
+ Hardware->chipRevision = 0x1051;
+ }
+ }
+
+ gcmkONERROR(
+ gctaOS_ReadRegister(os, Hardware->ta->core,
+ 0x000A8,
+ &Hardware->productID));
+ }
+
+ gcmkVERIFY_OK(gctaOS_ReadRegister(
+ os, Hardware->ta->core,
+ 0x000E8
+,
+ &Hardware->ecoID
+ ));
+
+ gcmkVERIFY_OK(gctaOS_ReadRegister(
+ os, Hardware->ta->core,
+ 0x00030
+,
+ &Hardware->customerID
+ ));
+
+ /***************************************************************************
+ ** Get chip features.
+ */
+
+ database =
+ Hardware->featureDatabase =
+ gcQueryFeatureDB(
+ Hardware->chipModel,
+ Hardware->chipRevision,
+ Hardware->productID,
+ Hardware->ecoID,
+ Hardware->customerID
+ );
+
+ if (database == gcvNULL)
+ {
+ gcmkPRINT("[galcore]: Feature database is not found,"
+ "chipModel=0x%0x, chipRevision=0x%x, productID=0x%x, ecoID=0x%x, customerID=0x%x",
+ Hardware->chipModel,
+ Hardware->chipRevision,
+ Hardware->productID,
+ Hardware->ecoID,
+ Hardware->customerID);
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+gceSTATUS
+gctaHARDWARE_SetMMUStates(
+ IN gcTA_HARDWARE Hardware,
+ IN gctPOINTER MtlbAddress,
+ IN gceMMU_MODE Mode,
+ IN gctPOINTER SafeAddress,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gceSTATUS status;
+ gctUINT32 config, address;
+ gctUINT32 extMtlb, extSafeAddrss;
+ gctPHYS_ADDR_T physical;
+ gctUINT32_PTR buffer;
+ gctUINT32 reserveBytes = 2 * 4;
+ gcsMMU_TABLE_ARRAY_ENTRY * entry;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ entry = (gcsMMU_TABLE_ARRAY_ENTRY *) Hardware->pagetableArray.logical;
+
+ /* Convert logical address into physical address. */
+ gcmkONERROR(
+ gctaOS_GetPhysicalAddress(Hardware->os, MtlbAddress, &physical));
+
+ config = (gctUINT32)(physical & 0xFFFFFFFF);
+ extMtlb = (gctUINT32)(physical >> 32);
+
+ gcmkONERROR(
+ gctaOS_GetPhysicalAddress(Hardware->os, SafeAddress, &physical));
+
+ address = (gctUINT32)(physical & 0xFFFFFFFF);
+ extSafeAddrss = (gctUINT32)(physical >> 32);
+
+ if (address & 0x3F)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ switch (Mode)
+ {
+ case gcvMMU_MODE_1K:
+ if (config & 0x3FF)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ break;
+
+ case gcvMMU_MODE_4K:
+ if (config & 0xFFF)
+ {
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+ config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (Logical != gcvNULL)
+ {
+ buffer = Logical;
+
+ /* Setup page table array entry. */
+ entry->low = config;
+ entry->high = physical >> 32;
+
+ /* Setup command buffer to load index 0 of page table array. */
+ *buffer++
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
+ 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
+ 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0x006B) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
+ 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
+ 25:16) + 1))))))) << (0 ? 25:16)));
+
+ *buffer++
+ = (((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) &((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ?
+ 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ?
+ 16:16))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ *Bytes = reserveBytes;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER_NO();
+ return status;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gctaHARDWARE_End(
+ IN gcTA_HARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctUINT32 * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append END. */
+ logical[0] =
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ?
+ 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ?
+ 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ /* Record the count of execution which is finised by this END. */
+ logical[1] =
+ 0;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+gceSTATUS
+gctaHARDWARE_Construct(
+ IN gcTA TA,
+ OUT gcTA_HARDWARE * Hardware
+ )
+{
+ gceSTATUS status;
+ gcTA_HARDWARE hardware;
+
+ gctaOS os = TA->os;
+
+ gcmkONERROR(gctaOS_Allocate(
+ gcmSIZEOF(gcsTA_HARDWARE),
+ (gctPOINTER *)&hardware
+ ));
+
+ gctaOS_ZeroMemory((gctUINT8_PTR)hardware, gcmSIZEOF(gcsTA_HARDWARE));
+
+ hardware->ta = TA;
+ hardware->os = os;
+
+ hardware->pagetableArray.size = 4096;
+
+ hardware->functionBytes = 4096;
+
+ /* Power on GPU. */
+ gctaOS_SetGPUPower(os, TA->core, gcvTRUE, gcvTRUE);
+
+ /*************************************/
+ /******** Get chip information ******/
+ /*************************************/
+ gctaOS_WriteRegister(
+ hardware->ta->os, hardware->ta->core,
+ 0x00000,
+ 0x00000900
+ );
+
+ _IdentifyHardwareByDatabase(hardware);
+
+ *Hardware = hardware;
+
+ return gcvSTATUS_OK;
+OnError:
+ return status;
+}
+
+gceSTATUS
+gctaHARDWARE_Destroy(
+ IN gcTA_HARDWARE Hardware
+ )
+{
+ if (Hardware->pagetableArray.logical)
+ {
+ gctaOS_FreeSecurityMemory(
+ Hardware->ta->os,
+ Hardware->pagetableArray.size,
+ Hardware->pagetableArray.logical,
+ (gctUINT32_PTR)Hardware->pagetableArray.physical
+ );
+ }
+
+ if (Hardware->functionLogical)
+ {
+ gctaOS_FreeSecurityMemory(
+ Hardware->ta->os,
+ Hardware->functionBytes,
+ Hardware->functionLogical,
+ (gctUINT32_PTR)Hardware->functionPhysical
+ );
+ }
+
+ gctaOS_Free(Hardware);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaHARDWARE_Execute(
+ IN gcTA TA,
+ IN gctUINT32 Address,
+ IN gctUINT32 Bytes
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = Address, control;
+
+ gcmkHEADER_ARG("Address=0x%x Bytes=%lu",
+ Address, Bytes);
+
+ /* Enable all events. */
+ gcmkONERROR(
+ gctaOS_WriteRegister(TA->os, TA->core, 0x00014, ~0U));
+
+ /* Write address register. */
+ gcmkONERROR(
+ gctaOS_WriteRegister(TA->os, TA->core, 0x00654, address));
+
+ /* Build control register. */
+ control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
+ 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
+ 16:16) + 1))))))) << (0 ? 16:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ?
+ 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0))) | (((gctUINT32) ((gctUINT32) ((Bytes + 7) >> 3) & ((gctUINT32) ((((1 ?
+ 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
+ 15:0)));
+
+ /* Write control register. */
+ gcmkONERROR(
+ gctaOS_WriteRegister(TA->os, TA->core, 0x003A4, control));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Started command buffer @ 0x%08x",
+ address);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gctaHARDWARE_MmuEnable(
+ IN gcTA_HARDWARE Hardware
+ )
+{
+ gctaOS_WriteRegister(
+ Hardware->ta->os, Hardware->ta->core,
+ 0x0018C,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) ((gctUINT32) (1 ) & ((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))));
+
+ return gcvSTATUS_OK;
+}
+
+/*
+* In trust zone, we prepare page table array table and configure base address of
+* it to hardware.
+*/
+gceSTATUS
+gctaHARDWARE_SetMMU(
+ IN gcTA_HARDWARE Hardware,
+ IN gctPOINTER Logical
+ )
+{
+ gcsMMU_TABLE_ARRAY_ENTRY *entry;
+ gcsHARDWARE_FUNCTION *function = &Hardware->functions[0];
+ gctUINT32 delay = 1;
+ gctUINT32 timer = 0;
+ gctUINT32 idle;
+ gctPHYS_ADDR_T mtlbPhysical;
+ gctPHYS_ADDR_T secureSafeAddress;
+ gctPHYS_ADDR_T nonSecureSafeAddress;
+
+ gctaOS_GetPhysicalAddress(Hardware->ta->os, Logical, &mtlbPhysical);
+
+ gctaOS_GetPhysicalAddress(Hardware->ta->os, Hardware->ta->mmu->safePageLogical, &secureSafeAddress);
+
+ gctaOS_GetPhysicalAddress(Hardware->ta->os, Hardware->ta->mmu->nonSecureSafePageLogical, &nonSecureSafeAddress);
+
+ /* Fill entry 0 of page table array. */
+ entry = (gcsMMU_TABLE_ARRAY_ENTRY *)Hardware->pagetableArray.logical;
+
+ entry->low = (gctUINT32)(mtlbPhysical & 0xFFFFFFFF);
+
+ entry->high = (gctUINT32)(mtlbPhysical >> 32)
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 8:8) - (0 ? 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ?
+ 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ?
+ 8:8)))
+ ;
+
+ /* Set page table base. */
+ gctaOS_WriteRegister(
+ Hardware->ta->os, Hardware->ta->core,
+ 0x0038C
+,
+ (gctUINT32)(Hardware->pagetableArray.address & 0xFFFFFFFF)
+ );
+
+ gctaOS_WriteRegister(
+ Hardware->ta->os, Hardware->ta->core,
+ 0x00390
+,
+ (gctUINT32)((Hardware->pagetableArray.address >> 32) & 0xFFFFFFFF)
+ );
+
+ gctaOS_WriteRegister(
+ Hardware->ta->os, Hardware->ta->core,
+ 0x00394
+,
+ 1
+ );
+
+ gctaOS_WriteRegister(
+ Hardware->ta->os, Hardware->ta->core,
+ 0x0039C
+,
+ (gctUINT32)(secureSafeAddress & 0xFFFFFFFF)
+ );
+
+ gctaOS_WriteRegister(
+ Hardware->ta->os, Hardware->ta->core,
+ 0x00398
+,
+ (gctUINT32)(nonSecureSafeAddress & 0xFFFFFFFF)
+ );
+
+ gctaOS_WriteRegister(
+ Hardware->ta->os, Hardware->ta->core,
+ 0x003A0
+,
+ (((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ?
+ 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ?
+ 23:16))) | (((gctUINT32) ((gctUINT32) ((gctUINT32)((secureSafeAddress >> 32) & 0xFFFFFFFF)) & ((gctUINT32) ((((1 ?
+ 23:16) - (0 ? 23:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 23:16) - (0 ?
+ 23:16) + 1))))))) << (0 ? 23:16))) &((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
+ 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ?
+ 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
+ 31:31) - (0 ? 31:31) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:31) - (0 ?
+ 31:31) + 1))))))) << (0 ? 31:31))))
+ | (((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ?
+ 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) | (((gctUINT32) ((gctUINT32) ((gctUINT32)((nonSecureSafeAddress >> 32) & 0xFFFFFFFF)) & ((gctUINT32) ((((1 ?
+ 7:0) - (0 ? 7:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ?
+ 7:0))) &((((gctUINT32) (~0U)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:15) - (0 ?
+ 15:15) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ?
+ 15:15))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15))))
+ );
+
+ /* Execute prepared command sequence. */
+ gctaHARDWARE_Execute(
+ Hardware->ta,
+ function->address,
+ function->bytes
+ );
+
+ /* Wait until MMU configure finishes. */
+ do
+ {
+ gctaOS_Delay(Hardware->os, delay);
+
+ gctaOS_ReadRegister(
+ Hardware->ta->os, Hardware->ta->core,
+ 0x00004,
+ &idle);
+
+ timer += delay;
+ delay *= 2;
+ }
+ while (!(((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ));
+
+ /* Enable MMU. */
+ gctaOS_WriteRegister(
+ Hardware->os, Hardware->ta->core,
+ 0x00388
+,
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ?
+ 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
+ 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
+ ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
+ );
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaHARDWARE_PrepareFunctions(
+ IN gcTA_HARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gcsHARDWARE_FUNCTION * function;
+ gctUINT32 mmuBytes;
+ gctUINT32 endBytes = 8;
+ gctUINT8_PTR logical;
+
+ gcmkHEADER();
+
+ /* Allocate page table array. */
+ gcmkONERROR(gctaOS_AllocateSecurityMemory(
+ Hardware->ta->os,
+ &Hardware->pagetableArray.size,
+ &Hardware->pagetableArray.logical,
+ &Hardware->pagetableArray.physical
+ ));
+
+ gcmkONERROR(gctaOS_GetPhysicalAddress(
+ Hardware->ta->os,
+ Hardware->pagetableArray.logical,
+ &Hardware->pagetableArray.address
+ ));
+
+ /* Allocate GPU functions. */
+ gcmkONERROR(gctaOS_AllocateSecurityMemory(
+ Hardware->ta->os,
+ &Hardware->functionBytes,
+ &Hardware->functionLogical,
+ &Hardware->functionPhysical
+ ));
+
+ gcmkONERROR(gctaOS_GetPhysicalAddress(
+ Hardware->ta->os,
+ Hardware->functionLogical,
+ (gctPHYS_ADDR_T *)&Hardware->functionAddress
+ ));
+
+ function = &Hardware->functions[0];
+
+ function->logical = Hardware->functionLogical;
+
+ function->address = Hardware->functionAddress;
+
+ logical = function->logical;
+
+ gcmkONERROR(gctaHARDWARE_SetMMUStates(
+ Hardware,
+ Hardware->ta->mmu->mtlbLogical,
+ gcvMMU_MODE_4K,
+ Hardware->ta->mmu->safePageLogical,
+ logical,
+ &mmuBytes
+ ));
+
+ logical += 8;
+
+ gcmkONERROR(gctaHARDWARE_End(
+ Hardware,
+ logical,
+ &endBytes
+ ));
+
+ function->bytes = mmuBytes + endBytes;
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gctaHARDWARE_IsFeatureAvailable(
+ IN gcTA_HARDWARE Hardware,
+ IN gceFEATURE Feature
+ )
+{
+ gctBOOL available;
+ gcsFEATURE_DATABASE *database = Hardware->featureDatabase;
+
+ switch (Feature)
+ {
+ case gcvFEATURE_SECURITY:
+ available = database->SECURITY;
+ break;
+ default:
+ gcmkFATAL("Invalid feature has been requested.");
+ available = gcvFALSE;
+ }
+
+ return available;
+}
+
+gceSTATUS
+gctaHARDWARE_DumpMMUException(
+ IN gcTA_HARDWARE Hardware
+ )
+{
+ gctUINT32 mmu = 0;
+ gctUINT32 mmuStatus = 0;
+ gctUINT32 address = 0;
+ gctUINT32 i = 0;
+
+ gctUINT32 mmuStatusRegAddress;
+ gctUINT32 mmuExceptionAddress;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ mmuStatusRegAddress = 0x00384;
+ mmuExceptionAddress = 0x00380;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ gcmkPRINT("ChipModel=0x%x ChipRevision=0x%x:\n",
+ Hardware->chipModel,
+ Hardware->chipRevision);
+
+ gcmkPRINT("**************************\n");
+ gcmkPRINT("*** MMU ERROR DUMP ***\n");
+ gcmkPRINT("**************************\n");
+
+ gcmkVERIFY_OK(gctaOS_ReadRegister(
+ Hardware->os, Hardware->ta->core,
+ mmuStatusRegAddress
+,
+ &mmuStatus
+ ));
+
+ gcmkPRINT(" MMU status = 0x%08X\n", mmuStatus);
+
+ for (i = 0; i < 4; i += 1)
+ {
+ mmu = mmuStatus & 0xF;
+ mmuStatus >>= 4;
+
+ if (mmu == 0)
+ {
+ continue;
+ }
+
+ switch (mmu)
+ {
+ case 1:
+ gcmkPRINT(" MMU%d: slave not present\n", i);
+ break;
+
+ case 2:
+ gcmkPRINT(" MMU%d: page not present\n", i);
+ break;
+
+ case 3:
+ gcmkPRINT(" MMU%d: write violation\n", i);
+ break;
+
+ case 4:
+ gcmkPRINT(" MMU%d: out of bound", i);
+ break;
+
+ case 5:
+ gcmkPRINT(" MMU%d: read security violation", i);
+ break;
+
+ case 6:
+ gcmkPRINT(" MMU%d: write security violation", i);
+ break;
+
+ default:
+ gcmkPRINT(" MMU%d: unknown state\n", i);
+ }
+
+ gcmkVERIFY_OK(gctaOS_ReadRegister(
+ Hardware->os, Hardware->ta->core,
+ mmuExceptionAddress + i * 4
+,
+ &address
+ ));
+
+ gcmkPRINT(" MMU%d: exception address = 0x%08X\n", i, address);
+
+ gctaMMU_DumpPagetableEntry(Hardware->ta->mmu, address);
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaHARDWARE_ReadMMUException(
+ IN gcTA_HARDWARE Hardware,
+ OUT gctUINT32_PTR MMUStatus,
+ OUT gctUINT32_PTR MMUException
+ )
+{
+ gctUINT32 mmuStatusRegAddress;
+ gctUINT32 mmuExceptionAddress;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ mmuStatusRegAddress = 0x00384;
+ mmuExceptionAddress = 0x00380;
+
+ gcmkVERIFY_OK(gctaOS_ReadRegister(
+ Hardware->os, Hardware->ta->core,
+ mmuStatusRegAddress
+,
+ MMUStatus
+ ));
+
+ gcmkVERIFY_OK(gctaOS_ReadRegister(
+ Hardware->os, Hardware->ta->core,
+ mmuExceptionAddress
+,
+ MMUException
+ ));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaHARDWARE_HandleMMUException(
+ IN gcTA_HARDWARE Hardware,
+ IN gctUINT32 MMUStatus,
+ IN gctPHYS_ADDR_T Physical,
+ IN gctUINT32 GPUAddress
+ )
+{
+ gctUINT32 mmu = 0;
+ gctUINT32 mmuStatus = 0;
+ gctUINT32 mtlbEntry = 0;
+ gctUINT32_PTR stlbEntry;
+ gctBOOL secure;
+
+ gctUINT32 mmuStatusRegAddress;
+ gctUINT32 mmuExceptionAddress;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ mmuStatusRegAddress = 0x00384;
+ mmuExceptionAddress = 0x00380;
+
+ gcmkVERIFY_OK(gctaOS_ReadRegister(
+ Hardware->os, Hardware->ta->core,
+ mmuStatusRegAddress
+,
+ &mmuStatus
+ ));
+
+ mmu = mmuStatus & 0xF;
+
+ /* Setup page table. */
+
+ gctaMMU_GetPageEntry(
+ Hardware->ta->mmu,
+ GPUAddress,
+ &mtlbEntry,
+ &stlbEntry,
+ &secure
+ );
+
+ gctaMMU_SetPage(
+ Hardware->ta->mmu,
+ (gctUINT32)Physical,
+ stlbEntry
+ );
+
+ switch (mmu)
+ {
+ case 1:
+ gcmkASSERT(mtlbEntry != 0);
+ gctaOS_WriteRegister(
+ Hardware->os, Hardware->ta->core,
+ mmuExceptionAddress
+,
+ mtlbEntry
+ );
+
+ break;
+
+ case 2:
+ gctaOS_WriteRegister(
+ Hardware->os, Hardware->ta->core,
+ mmuExceptionAddress
+,
+ *stlbEntry
+ );
+ break;
+
+ default:
+ gcmkASSERT(0);
+ }
+
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
diff --git a/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_hardware.h b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_hardware.h
new file mode 100644
index 000000000000..d9c610b13447
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_hardware.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#ifndef _GC_HAL_TA_HARDWARE_H_
+#define _GC_HAL_TA_HARDWARE_H_
+#include "gc_hal_types.h"
+#include "gc_hal_security_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _gcsMMU_TABLE_ARRAY_ENTRY
+{
+ gctUINT32 low;
+ gctUINT32 high;
+}
+gcsMMU_TABLE_ARRAY_ENTRY;
+
+typedef struct _gcsHARDWARE_PAGETABLE_ARRAY
+{
+ /* Number of entries in page table array. */
+ gctUINT num;
+
+ /* Size in bytes of array. */
+ gctSIZE_T size;
+
+ /* Physical address of array. */
+ gctPHYS_ADDR_T address;
+
+ /* Memory descriptor. */
+ gctPOINTER physical;
+
+ /* Logical address of array. */
+ gctPOINTER logical;
+}
+gcsHARDWARE_PAGETABLE_ARRAY;
+
+typedef struct _gcsHARWARE_FUNCTION
+{
+ /* Entry of the function. */
+ gctUINT32 address;
+
+ /* CPU address of the function. */
+ gctUINT8_PTR logical;
+
+ /* Bytes of the function. */
+ gctUINT32 bytes;
+
+ /* Hardware address of END in this function. */
+ gctUINT32 endAddress;
+
+ /* Logical of END in this function. */
+ gctUINT8_PTR endLogical;
+}
+gcsHARDWARE_FUNCTION;
+
+typedef struct _gcTA_HARDWARE
+{
+ gctaOS os;
+ gcTA ta;
+
+ gctUINT32 chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 productID;
+ gctUINT32 ecoID;
+ gctUINT32 customerID;
+
+ gctPOINTER featureDatabase;
+
+ gcsHARDWARE_PAGETABLE_ARRAY pagetableArray;
+
+ /* Function used by gctaHARDWARE. */
+ gctPHYS_ADDR functionPhysical;
+ gctPOINTER functionLogical;
+ gctUINT32 functionAddress;
+ gctSIZE_T functionBytes;
+
+ gcsHARDWARE_FUNCTION functions[1];
+}
+gcsTA_HARDWARE;
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_mmu.c b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_mmu.c
new file mode 100644
index 000000000000..a3ea11e93bb3
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/security_v1/gc_hal_ta_mmu.c
@@ -0,0 +1,586 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_types.h"
+#include "gc_hal_base.h"
+#include "gc_hal_security_interface.h"
+#include "gc_hal_ta.h"
+#include "gc_hal.h"
+
+#define _GC_OBJ_ZONE 2
+/*******************************************************************************
+************************************ Define ************************************
+********************************************************************************/
+
+#define gcdMMU_MTLB_SHIFT 22
+#define gcdMMU_STLB_4K_SHIFT 12
+#define gcdMMU_STLB_64K_SHIFT 16
+
+#define gcdMMU_MTLB_BITS (32 - gcdMMU_MTLB_SHIFT)
+#define gcdMMU_PAGE_4K_BITS gcdMMU_STLB_4K_SHIFT
+#define gcdMMU_STLB_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_4K_BITS)
+#define gcdMMU_PAGE_64K_BITS gcdMMU_STLB_64K_SHIFT
+#define gcdMMU_STLB_64K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_64K_BITS)
+
+#define gcdMMU_MTLB_ENTRY_NUM (1 << gcdMMU_MTLB_BITS)
+#define gcdMMU_MTLB_SIZE (gcdMMU_MTLB_ENTRY_NUM << 2)
+#define gcdMMU_STLB_4K_ENTRY_NUM (1 << gcdMMU_STLB_4K_BITS)
+#define gcdMMU_STLB_4K_SIZE (gcdMMU_STLB_4K_ENTRY_NUM << 2)
+#define gcdMMU_PAGE_4K_SIZE (1 << gcdMMU_STLB_4K_SHIFT)
+#define gcdMMU_STLB_64K_ENTRY_NUM (1 << gcdMMU_STLB_64K_BITS)
+#define gcdMMU_STLB_64K_SIZE (gcdMMU_STLB_64K_ENTRY_NUM << 2)
+#define gcdMMU_PAGE_64K_SIZE (1 << gcdMMU_STLB_64K_SHIFT)
+
+#define gcdMMU_MTLB_MASK (~((1U << gcdMMU_MTLB_SHIFT)-1))
+#define gcdMMU_STLB_4K_MASK ((~0U << gcdMMU_STLB_4K_SHIFT) ^ gcdMMU_MTLB_MASK)
+#define gcdMMU_PAGE_4K_MASK (gcdMMU_PAGE_4K_SIZE - 1)
+#define gcdMMU_STLB_64K_MASK ((~((1U << gcdMMU_STLB_64K_SHIFT)-1)) ^ gcdMMU_MTLB_MASK)
+#define gcdMMU_PAGE_64K_MASK (gcdMMU_PAGE_64K_SIZE - 1)
+
+/* Page offset definitions. */
+#define gcdMMU_OFFSET_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_4K_BITS)
+#define gcdMMU_OFFSET_4K_MASK ((1U << gcdMMU_OFFSET_4K_BITS) - 1)
+#define gcdMMU_OFFSET_16K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_16K_BITS)
+#define gcdMMU_OFFSET_16K_MASK ((1U << gcdMMU_OFFSET_16K_BITS) - 1)
+
+#define gcdMMU_MTLB_PRESENT 0x00000001
+#define gcdMMU_MTLB_EXCEPTION 0x00000002
+#define gcdMMU_MTLB_4K_PAGE 0x00000000
+
+#define gcdMMU_STLB_PRESENT 0x00000001
+#define gcdMMU_STLB_EXCEPTION 0x00000002
+#define gcdMMU_STLB_SECURITY (1 << 4)
+#define gcdMMU_STLB_4K_PAGE 0x00000000
+
+#define gcdUSE_MMU_EXCEPTION 1
+
+#define gcdMMU_SECURE_AREA_START ((gcdMMU_MTLB_ENTRY_NUM - gcdMMU_SECURE_AREA_SIZE) << gcdMMU_MTLB_SHIFT)
+
+typedef enum _gceMMU_TYPE
+{
+ gcvMMU_USED = (0 << 4),
+ gcvMMU_SINGLE = (1 << 4),
+ gcvMMU_FREE = (2 << 4),
+}
+gceMMU_TYPE;
+
+typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
+typedef struct _gcsMMU_STLB
+{
+ gctPHYS_ADDR physical;
+ gctUINT32_PTR logical;
+ gctSIZE_T size;
+ gctPHYS_ADDR_T physBase;
+ gctSIZE_T pageCount;
+ gctUINT32 mtlbIndex;
+ gctUINT32 mtlbEntryNum;
+ gcsMMU_STLB_PTR next;
+} gcsMMU_STLB;
+
+
+#define gcmENTRY_TYPE(x) (x & 0xF0)
+/*
+* We need flat mapping ta command buffer.
+
+*/
+
+/*
+* Helper
+*/
+gctUINT32
+_MtlbOffset(
+ gctUINT32 Address
+ )
+{
+ return (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
+}
+
+gctUINT32
+_StlbOffset(
+ gctUINT32 Address
+ )
+{
+ return (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+}
+
+static gctUINT32
+_SetPage(gctUINT32 PageAddress)
+{
+ return PageAddress
+ /* writable */
+ | (1 << 2)
+ /* Ignore exception */
+ | (0 << 1)
+ /* Present */
+ | (1 << 0);
+}
+
+static void
+_WritePageEntry(
+ IN gctUINT32_PTR PageEntry,
+ IN gctUINT32 EntryValue
+ )
+{
+ *PageEntry = EntryValue;
+
+ gctaOS_CacheClean((gctUINT8_PTR)PageEntry, gcmSIZEOF(gctUINT32));
+}
+
+static gceSTATUS
+_FillPageTable(
+ IN gctUINT32_PTR PageTable,
+ IN gctUINT32 PageCount,
+ IN gctUINT32 EntryValue
+)
+{
+ gctUINT i;
+
+ for (i = 0; i < PageCount; i++)
+ {
+ _WritePageEntry(PageTable + i, EntryValue);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+
+static gceSTATUS
+_AllocateStlb(
+ IN gctaOS Os,
+ OUT gcsMMU_STLB_PTR *Stlb
+ )
+{
+ gceSTATUS status;
+ gcsMMU_STLB_PTR stlb;
+ gctPOINTER pointer = gcvNULL;
+
+ /* Allocate slave TLB record. */
+ gcmkONERROR(gctaOS_Allocate(gcmSIZEOF(gcsMMU_STLB), &pointer));
+ stlb = pointer;
+
+ stlb->size = gcdMMU_STLB_4K_SIZE;
+
+ /* Allocate slave TLB entries. */
+ gcmkONERROR(gctaOS_AllocateSecurityMemory(
+ Os,
+ &stlb->size,
+ (gctPOINTER *)&stlb->logical,
+ &stlb->physical
+ ));
+
+ gcmkONERROR(gctaOS_GetPhysicalAddress(Os, stlb->logical, &stlb->physBase));
+
+#if gcdUSE_MMU_EXCEPTION
+ _FillPageTable(stlb->logical, stlb->size / 4, gcdMMU_STLB_EXCEPTION);
+#else
+ gctaOS_ZeroMemory(stlb->logical, stlb->size);
+#endif
+
+ *Stlb = stlb;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if(pointer != gcvNULL)
+ gcmkVERIFY_OK(gctaOS_Free(pointer));
+ return status;
+}
+
+gceSTATUS
+gctaMMU_Construct(
+ IN gcTA TA,
+ OUT gcTA_MMU *Mmu
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T bytes = 4096;
+
+ gcTA_MMU mmu = gcvNULL;
+
+ gcmkONERROR(gctaOS_Allocate(
+ gcmSIZEOF(gcsTA_MMU),
+ (gctPOINTER *)&mmu
+ ));
+
+ mmu->mtlbLogical = gcvNULL;
+ mmu->stlbs = gcvNULL;
+ mmu->safePageLogical = gcvNULL;
+ mmu->nonSecureSafePageLogical = gcvNULL;
+
+ mmu->os = TA->os;
+
+ /* MTLB bytes. */
+ mmu->mtlbBytes = gcdMMU_MTLB_SIZE;
+
+ /* Allocate MTLB. */
+ gcmkONERROR(gctaOS_AllocateSecurityMemory(
+ TA->os,
+ &mmu->mtlbBytes,
+ &mmu->mtlbLogical,
+ &mmu->mtlbPhysical
+ ));
+
+#if gcdUSE_MMU_EXCEPTION
+ _FillPageTable(mmu->mtlbLogical, mmu->mtlbBytes / 4, gcdMMU_STLB_EXCEPTION);
+#else
+ gctaOS_ZeroMemory(mmu->mtlbLogical, mmu->mtlbBytes);
+#endif
+
+ /* Allocate a array to store stlbs. */
+ gcmkONERROR(gctaOS_Allocate(mmu->mtlbBytes, &mmu->stlbs));
+
+ gctaOS_ZeroMemory((gctUINT8_PTR)mmu->stlbs, mmu->mtlbBytes);
+
+ /* Allocate security safe page. */
+ gcmkONERROR(gctaOS_AllocateSecurityMemory(
+ TA->os,
+ &bytes,
+ &mmu->safePageLogical,
+ &mmu->safePagePhysical
+ ));
+
+ gctaOS_ZeroMemory((gctUINT8_PTR)mmu->safePageLogical, bytes);
+
+ /* Allocate non security safe page. */
+ gcmkONERROR(gctaOS_AllocateSecurityMemory(
+ TA->os,
+ &bytes,
+ &mmu->nonSecureSafePageLogical,
+ &mmu->nonSecureSafePagePhysical
+ ));
+
+ gctaOS_ZeroMemory((gctUINT8_PTR)mmu->nonSecureSafePageLogical, bytes);
+
+ /* gcmkONERROR(gctaOS_CreateMutex(TA->os, &mmu->mutex)); */
+
+ *Mmu = mmu;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mmu)
+ {
+ if (mmu->safePageLogical)
+ {
+ gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
+ TA->os,
+ 4096,
+ mmu->safePageLogical,
+ mmu->safePagePhysical
+ ));
+ }
+
+ if (mmu->nonSecureSafePageLogical)
+ {
+ gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
+ TA->os,
+ 4096,
+ mmu->nonSecureSafePageLogical,
+ mmu->nonSecureSafePagePhysical
+ ));
+ }
+
+ if (mmu->mtlbLogical)
+ {
+ gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
+ TA->os,
+ 4096,
+ mmu->mtlbLogical,
+ mmu->mtlbPhysical
+ ));
+ }
+
+ if (mmu->stlbs)
+ {
+ gcmkVERIFY_OK(gctaOS_Free((gctPOINTER)mmu->stlbs));
+ }
+
+ gcmkVERIFY_OK(gctaOS_Free((gctPOINTER)mmu));
+ }
+ return status;
+}
+
+gceSTATUS
+gctaMMU_Destory(
+ IN gcTA_MMU Mmu
+ )
+{
+ gctaOS os = Mmu->os;
+
+ if (Mmu->safePageLogical)
+ {
+ gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
+ os,
+ 4096,
+ Mmu->safePageLogical,
+ Mmu->safePagePhysical
+ ));
+ }
+
+ if (Mmu->nonSecureSafePageLogical)
+ {
+ gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
+ os,
+ 4096,
+ Mmu->nonSecureSafePageLogical,
+ Mmu->nonSecureSafePagePhysical
+ ));
+ }
+
+ if (Mmu->mtlbLogical)
+ {
+ gcmkVERIFY_OK(gctaOS_FreeSecurityMemory(
+ os,
+ 4096,
+ Mmu->mtlbLogical,
+ Mmu->mtlbPhysical
+ ));
+ }
+
+ if (Mmu->stlbs)
+ {
+ gcmkVERIFY_OK(gctaOS_Free((gctPOINTER)Mmu->stlbs));
+ }
+
+ gcmkVERIFY_OK(gctaOS_Free(Mmu));
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaMMU_GetPageEntry(
+ IN gcTA_MMU Mmu,
+ IN gctUINT32 Address,
+ OUT gctUINT32_PTR MtlbEntry,
+ OUT gctUINT32_PTR *PageTable,
+ OUT gctBOOL * Secure
+ )
+{
+ gceSTATUS status;
+ struct _gcsMMU_STLB *stlb;
+ struct _gcsMMU_STLB **stlbs = (struct _gcsMMU_STLB **)Mmu->stlbs;
+ gctUINT32 offset = _MtlbOffset(Address);
+ gctUINT32 mtlbEntry;
+ gctBOOL secure = Address > gcdMMU_SECURE_AREA_START;
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT((Address & 0xFFF) == 0);
+
+ stlb = stlbs[offset];
+
+ if (stlb == gcvNULL)
+ {
+ gcmkONERROR(_AllocateStlb(Mmu->os, &stlb));
+
+ mtlbEntry = (gctUINT32)(stlb->physBase & 0xFFFFFFFF)
+ | gcdMMU_MTLB_4K_PAGE
+ | gcdMMU_MTLB_PRESENT
+ ;
+
+ if (secure)
+ {
+ /* Secure MTLB. */
+ mtlbEntry |= (1 << 4);
+ }
+
+ /* Insert Slave TLB address to Master TLB entry.*/
+ _WritePageEntry((gctUINT32_PTR)Mmu->mtlbLogical + offset, mtlbEntry);
+
+ /* Record stlb. */
+ stlbs[offset] = stlb;
+
+ if (MtlbEntry)
+ {
+ /* Return entry value of new mtlb entry. */
+ *MtlbEntry = mtlbEntry;
+ }
+ }
+
+ *PageTable = &stlb->logical[_StlbOffset(Address)];
+
+ if (Secure)
+ {
+ *Secure = secure;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gctaMMU_SetPage(
+ IN gcTA_MMU Mmu,
+ IN gctUINT32 PageAddress,
+ IN gctUINT32 *PageEntry
+ )
+{
+ /* gctBOOL secure; */
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
+ gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
+
+ _WritePageEntry(PageEntry, _SetPage(PageAddress));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaMMU_FreePages(
+ IN gcTA_MMU Mmu,
+ IN gctUINT32 Address,
+ IN gctUINT32 PageCount
+ )
+{
+ gceSTATUS status;
+ gctUINT32 i;
+ gctUINT32_PTR entry;
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Fill in page table. */
+ for (i = 0; i < PageCount; i++)
+ {
+ gcmkONERROR(gctaMMU_GetPageEntry(Mmu, Address, gcvNULL, &entry, gcvNULL));
+
+#if gcdUSE_MMU_EXCEPTION
+ *entry = gcdMMU_STLB_EXCEPTION;
+#else
+ *entry = 0;
+#endif
+
+ Address += 4096;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gctaMMU_Enable(
+ IN gcTA_MMU Mmu,
+ IN gcTA TA
+ )
+{
+ gceSTATUS status;
+ gctPHYS_ADDR_T address;
+ gctPHYS_ADDR_T safeAddress;
+
+ gcmkONERROR(gctaOS_GetPhysicalAddress(Mmu->os, Mmu->mtlbLogical, &address));
+
+ gctaOS_GetPhysicalAddress(Mmu->os, Mmu->safePageLogical, &safeAddress);
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+void
+gctaMMU_DumpPagetableEntry(
+ IN gcTA_MMU Mmu,
+ IN gctUINT32 Address
+ )
+{
+ gctUINT32 entry;
+ gctUINT32 mtlb = _MtlbOffset(Address);
+ gctUINT32_PTR mtlbLogical = Mmu->mtlbLogical;
+ gctUINT32_PTR stlbLogical;
+ gcsMMU_STLB_PTR stlb;
+ struct _gcsMMU_STLB **stlbs = (struct _gcsMMU_STLB **)Mmu->stlbs;
+
+ gctUINT32 stlbOffset = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
+ gctUINT32 offsetInPage = Address & gcdMMU_OFFSET_4K_MASK;
+
+ stlb = stlbs[mtlb];
+
+ gcmkPRINT(" MTLB entry = %d\n", mtlb);
+
+ gcmkPRINT(" STLB entry = %d\n", stlbOffset);
+
+ gcmkPRINT(" Offset = 0x%08X (%d)\n", offsetInPage, offsetInPage);
+
+
+ if (stlb == gcvNULL)
+ {
+ /* Dmp mtlb entry. */
+ entry = mtlbLogical[mtlb];
+
+ gcmkPRINT(" mtlb entry [%d] = %x", mtlb, entry);
+ }
+ else
+ {
+ stlbLogical = stlb->logical;
+
+ gcmkPRINT(" stlb entry = 0x%08X", stlbLogical[stlbOffset]);
+ }
+}
+
+
diff --git a/drivers/mxc/gpu-viv/hal/security_v1/os/emulator/gc_hal_ta_emulator.c b/drivers/mxc/gpu-viv/hal/security_v1/os/emulator/gc_hal_ta_emulator.c
new file mode 100644
index 000000000000..f933ddfa3f5d
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/security_v1/os/emulator/gc_hal_ta_emulator.c
@@ -0,0 +1,322 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2017 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2017 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; 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.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_base.h"
+#include "gc_hal.h"
+#include "gc_hal_ta.h"
+#include "gc_hal_kernel_mutex.h"
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+gcTA globalTA[16] = { gcvNULL, gcvNULL, gcvNULL, gcvNULL,gcvNULL, gcvNULL, gcvNULL, gcvNULL };
+gctaOS globalTAos;
+
+struct _gctaOS {
+ void *os;
+
+ gctPOINTER dispatchMutex;
+};
+
+gceSTATUS HALDECL
+TAEmulator(
+ gceCORE Core,
+ void * Interface
+ )
+{
+ gckOS_AcquireMutex(globalTAos->os, globalTAos->dispatchMutex, gcvINFINITE);
+
+ gcTA_Dispatch(globalTA[Core], Interface);
+
+ gckOS_ReleaseMutex(globalTAos->os, globalTAos->dispatchMutex);
+ return gcvSTATUS_OK;
+}
+
+
+gceSTATUS
+gctaOS_ConstructOS(
+ IN gckOS Os,
+ OUT gctaOS *TAos
+ )
+{
+ gctaOS os;
+ gctPOINTER pointer = gcvNULL;
+ gceSTATUS status;
+
+ gcmkONERROR(gckOS_AllocateMemory(Os, gcmSIZEOF(struct _gctaOS), &pointer));
+
+ os = (gctaOS)pointer;
+ os->os = Os;
+
+ gcmkONERROR(gckOS_CreateMutex(Os, &os->dispatchMutex));
+
+ *TAos = globalTAos = os;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ if (pointer != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_FreeMemory(Os, pointer));
+ }
+ return status;
+}
+
+gceSTATUS
+gctaOS_DestroyOS(
+ IN gctaOS Os
+ )
+{
+ gckOS os = Os->os;
+
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, Os->dispatchMutex));
+ gcmkVERIFY_OK(gckOS_FreeMemory(os, Os));
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaOS_AllocateSecurityMemory(
+ IN gctaOS Os,
+ IN gctSIZE_T *Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPOINTER *Physical
+ )
+{
+ gceSTATUS status;
+
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(Os->os, gcvFALSE, Bytes, (gctPHYS_ADDR *)Physical, Logical));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gctaOS_FreeSecurityMemory(
+ IN gctaOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical,
+ OUT gctPOINTER Physical
+ )
+{
+ gckOS_FreeNonPagedMemory(Os->os, Bytes, (gctPHYS_ADDR)Physical, Logical);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaOS_AllocateNonSecurityMemory(
+ IN gctaOS Os,
+ IN gctSIZE_T *Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPOINTER *Physical
+ )
+{
+ gceSTATUS status;
+
+ gcmkONERROR(gckOS_AllocateNonPagedMemory(Os->os, gcvFALSE, Bytes, (gctPHYS_ADDR *)Physical, Logical));
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS
+gctaOS_FreeNonSecurityMemory(
+ IN gctaOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical,
+ OUT gctPOINTER Physical
+ )
+{
+ gckOS_FreeNonPagedMemory(Os->os, Bytes, (gctPHYS_ADDR)Physical, Logical);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaOS_Allocate(
+ IN gctUINT32 Bytes,
+ OUT gctPOINTER *Pointer
+ )
+{
+ return gckOS_AllocateMemory(globalTAos->os, Bytes, Pointer);
+}
+
+gceSTATUS
+gctaOS_Free(
+ IN gctPOINTER Pointer
+ )
+{
+ return gckOS_FreeMemory(globalTAos->os, Pointer);
+}
+
+gceSTATUS
+gctaOS_GetPhysicalAddress(
+ IN gctaOS Os,
+ IN gctPOINTER Logical,
+ OUT gctPHYS_ADDR_T * Physical
+ )
+{
+ gctPHYS_ADDR_T physical;
+ gceSTATUS status;
+
+ gcmkONERROR(gckOS_GetPhysicalAddress(Os->os, Logical, &physical));
+
+ *Physical = (gctUINT32)physical;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ return status;
+}
+
+gceSTATUS gctaOS_WriteRegister(
+ IN gctaOS Os, IN gceCORE Core,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ )
+{
+ return gckOS_WriteRegisterEx(Os->os, Core, Address, Data);
+}
+
+gceSTATUS gctaOS_ReadRegister(
+ IN gctaOS Os, IN gceCORE Core,
+ IN gctUINT32 Address,
+ IN gctUINT32 *Data
+ )
+{
+ return gckOS_ReadRegisterEx(Os->os, Core, Address, Data);
+}
+
+gceSTATUS
+gctaOS_MemCopy(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT8_PTR Src,
+ IN gctUINT32 Bytes
+ )
+{
+ gckOS_MemCopy(Dest, Src, Bytes);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gctaOS_ZeroMemory(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT32 Bytes
+ )
+{
+ gckOS_ZeroMemory(Dest, Bytes);
+ return gcvSTATUS_OK;
+}
+
+void
+gctaOS_CacheFlush(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT32 Bytes
+ )
+{
+
+}
+
+void
+gctaOS_CacheClean(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT32 Bytes
+ )
+{
+
+}
+
+void
+gctaOS_CacheInvalidate(
+ IN gctUINT8_PTR Dest,
+ IN gctUINT32 Bytes
+ )
+{
+
+}
+
+gceSTATUS
+gctaOS_IsPhysicalSecure(
+ IN gctaOS Os,
+ IN gctUINT32 Physical,
+ OUT gctBOOL *Secure
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+gceSTATUS
+gctaOS_Delay(
+ IN gctaOS Os,
+ IN gctUINT32 Delay
+ )
+{
+ return gckOS_Delay(Os->os, Delay);
+}
+
+gceSTATUS
+gctaOS_SetGPUPower(
+ IN gctaOS Os,
+ IN gctUINT32 Core,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ )
+{
+ return gckOS_SetGPUPower(Os->os, Core, Power, Clock);
+}
+
+
diff --git a/drivers/mxc/hdmi-cec/Kconfig b/drivers/mxc/hdmi-cec/Kconfig
new file mode 100644
index 000000000000..c0be06854e27
--- /dev/null
+++ b/drivers/mxc/hdmi-cec/Kconfig
@@ -0,0 +1,11 @@
+
+menu "MXC HDMI CEC (Consumer Electronics Control) support"
+
+config MXC_HDMI_CEC
+ tristate "Support for MXC HDMI CEC (Consumer Electronics Control)"
+ depends on MFD_MXC_HDMI
+ depends on FB_MXC_HDMI
+ help
+ The HDMI CEC device implement low level protocol on i.MX6x platforms.
+
+endmenu
diff --git a/drivers/mxc/hdmi-cec/Makefile b/drivers/mxc/hdmi-cec/Makefile
new file mode 100644
index 000000000000..07248b25b033
--- /dev/null
+++ b/drivers/mxc/hdmi-cec/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MXC_HDMI_CEC) += mxc_hdmi-cec.o
diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c
new file mode 100644
index 000000000000..75c01972e584
--- /dev/null
+++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (C) 2012-2015 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 mxc_hdmi-cec.c
+ *
+ * @brief HDMI CEC system initialization and file operation implementation
+ *
+ * @ingroup HDMI
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/fsl_devices.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <linux/sizes.h>
+
+#include <linux/console.h>
+#include <linux/types.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+#include <linux/pinctrl/consumer.h>
+
+#include <video/mxc_hdmi.h>
+
+#include "mxc_hdmi-cec.h"
+
+
+#define MAX_MESSAGE_LEN 17
+
+#define MESSAGE_TYPE_RECEIVE_SUCCESS 1
+#define MESSAGE_TYPE_NOACK 2
+#define MESSAGE_TYPE_DISCONNECTED 3
+#define MESSAGE_TYPE_CONNECTED 4
+#define MESSAGE_TYPE_SEND_SUCCESS 5
+
+
+struct hdmi_cec_priv {
+ int receive_error;
+ int send_error;
+ u8 Logical_address;
+ bool cec_state;
+ u8 last_msg[MAX_MESSAGE_LEN];
+ u8 msg_len;
+ u8 latest_cec_stat;
+ spinlock_t irq_lock;
+ struct delayed_work hdmi_cec_work;
+ struct mutex lock;
+};
+
+struct hdmi_cec_event {
+ int event_type;
+ int msg_len;
+ u8 msg[MAX_MESSAGE_LEN];
+ struct list_head list;
+};
+
+static LIST_HEAD(head);
+
+static int hdmi_cec_major;
+static struct class *hdmi_cec_class;
+static struct hdmi_cec_priv hdmi_cec_data;
+static u8 open_count;
+
+static wait_queue_head_t hdmi_cec_queue;
+static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data)
+{
+ struct hdmi_cec_priv *hdmi_cec = data;
+ u8 cec_stat = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hdmi_cec->irq_lock, flags);
+
+ hdmi_writeb(0x7f, HDMI_IH_MUTE_CEC_STAT0);
+
+ cec_stat = hdmi_readb(HDMI_IH_CEC_STAT0);
+ hdmi_writeb(cec_stat, HDMI_IH_CEC_STAT0);
+
+ if ((cec_stat & (HDMI_IH_CEC_STAT0_ERROR_INIT | \
+ HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | \
+ HDMI_IH_CEC_STAT0_DONE)) == 0) {
+ spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags);
+ return IRQ_HANDLED;
+ }
+
+ pr_debug("HDMI CEC interrupt received\n");
+ hdmi_cec->latest_cec_stat = cec_stat;
+
+ schedule_delayed_work(&(hdmi_cec->hdmi_cec_work), msecs_to_jiffies(20));
+
+ spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+void mxc_hdmi_cec_handle(u16 cec_stat)
+{
+ u8 val = 0, i = 0;
+ struct hdmi_cec_event *event = NULL;
+
+ /* The current transmission is successful (for initiator only). */
+ if (!open_count)
+ return;
+
+ if (cec_stat & HDMI_IH_CEC_STAT0_DONE) {
+
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s: Not enough memory!\n", __func__);
+ return;
+ }
+
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->event_type = MESSAGE_TYPE_SEND_SUCCESS;
+
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ wake_up(&hdmi_cec_queue);
+ }
+
+ /* EOM is detected so that the received data is ready
+ * in the receiver data buffer
+ */
+ if (cec_stat & HDMI_IH_CEC_STAT0_EOM) {
+
+ hdmi_writeb(0x02, HDMI_IH_CEC_STAT0);
+
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s: Not enough memory!\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+
+ event->msg_len = hdmi_readb(HDMI_CEC_RX_CNT);
+ if (!event->msg_len) {
+ pr_err("%s: Invalid CEC message length!\n", __func__);
+ vfree(event);
+ return;
+ }
+ event->event_type = MESSAGE_TYPE_RECEIVE_SUCCESS;
+
+ for (i = 0; i < event->msg_len; i++)
+ event->msg[i] = hdmi_readb(HDMI_CEC_RX_DATA0+i);
+ hdmi_writeb(0x0, HDMI_CEC_LOCK);
+
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ wake_up(&hdmi_cec_queue);
+ }
+
+ /* An error is detected on cec line (for initiator only). */
+ if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) {
+
+ mutex_lock(&hdmi_cec_data.lock);
+ hdmi_cec_data.send_error++;
+ if (hdmi_cec_data.send_error > 5) {
+ pr_err("%s:Re-transmission is attempted more than 5 times!\n",
+ __func__);
+ hdmi_cec_data.send_error = 0;
+ mutex_unlock(&hdmi_cec_data.lock);
+ return;
+ }
+
+ for (i = 0; i < hdmi_cec_data.msg_len; i++) {
+ hdmi_writeb(hdmi_cec_data.last_msg[i],
+ HDMI_CEC_TX_DATA0 + i);
+ }
+ hdmi_writeb(hdmi_cec_data.msg_len, HDMI_CEC_TX_CNT);
+
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ val |= 0x01;
+ hdmi_writeb(val, HDMI_CEC_CTRL);
+ mutex_unlock(&hdmi_cec_data.lock);
+ }
+
+ /* A frame is not acknowledged in a directly addressed message.
+ * Or a frame is negatively acknowledged in
+ * a broadcast message (for initiator only).
+ */
+ if (cec_stat & HDMI_IH_CEC_STAT0_NACK) {
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s: Not enough memory\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->event_type = MESSAGE_TYPE_NOACK;
+
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ wake_up(&hdmi_cec_queue);
+ }
+
+ /* An error is notified by a follower.
+ * Abnormal logic data bit error (for follower).
+ */
+ if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_FOLL) {
+ hdmi_cec_data.receive_error++;
+ }
+
+ /* HDMI cable connected */
+ if (cec_stat & 0x80) {
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s: Not enough memory\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->event_type = MESSAGE_TYPE_CONNECTED;
+
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ wake_up(&hdmi_cec_queue);
+ }
+
+ /* HDMI cable disconnected */
+ if (cec_stat & 0x100) {
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s: Not enough memory!\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->event_type = MESSAGE_TYPE_DISCONNECTED;
+
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ wake_up(&hdmi_cec_queue);
+ }
+
+ return;
+}
+EXPORT_SYMBOL(mxc_hdmi_cec_handle);
+
+static void mxc_hdmi_cec_worker(struct work_struct *work)
+{
+ u8 val;
+
+ mxc_hdmi_cec_handle(hdmi_cec_data.latest_cec_stat);
+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL |
+ HDMI_IH_CEC_STAT0_ARB_LOST;
+ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
+}
+
+/*!
+ * @brief open function for vpu file operation
+ *
+ * @return 0 on success or negative error code on error
+ */
+static int hdmi_cec_open(struct inode *inode, struct file *filp)
+{
+ mutex_lock(&hdmi_cec_data.lock);
+ if (open_count) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EBUSY;
+ }
+
+ open_count = 1;
+ filp->private_data = (void *)(&hdmi_cec_data);
+ hdmi_cec_data.Logical_address = 15;
+ hdmi_cec_data.cec_state = false;
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ return 0;
+}
+
+static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct hdmi_cec_event *event = NULL;
+
+ pr_debug("function : %s\n", __func__);
+ if (!open_count)
+ return -ENODEV;
+
+ mutex_lock(&hdmi_cec_data.lock);
+ if (false == hdmi_cec_data.cec_state) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EACCES;
+ }
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ /* delete from list */
+ mutex_lock(&hdmi_cec_data.lock);
+ if (list_empty(&head)) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EACCES;
+ }
+ event = list_first_entry(&head, struct hdmi_cec_event, list);
+ list_del(&event->list);
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ if (copy_to_user(buf, event,
+ sizeof(struct hdmi_cec_event) - sizeof(struct list_head))) {
+ vfree(event);
+ return -EFAULT;
+ }
+ vfree(event);
+
+ return sizeof(struct hdmi_cec_event);
+}
+
+static ssize_t hdmi_cec_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int ret = 0 , i = 0;
+ u8 msg[MAX_MESSAGE_LEN];
+ u8 msg_len = 0, val = 0;
+
+ pr_debug("function : %s\n", __func__);
+ if (!open_count)
+ return -ENODEV;
+
+ mutex_lock(&hdmi_cec_data.lock);
+ if (false == hdmi_cec_data.cec_state) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EACCES;
+ }
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ if (count > MAX_MESSAGE_LEN)
+ return -EINVAL;
+
+ mutex_lock(&hdmi_cec_data.lock);
+ hdmi_cec_data.send_error = 0;
+ memset(&msg, 0, MAX_MESSAGE_LEN);
+ ret = copy_from_user(&msg, buf, count);
+ if (ret) {
+ ret = -EACCES;
+ goto end;
+ }
+
+ msg_len = count;
+ hdmi_writeb(msg_len, HDMI_CEC_TX_CNT);
+ for (i = 0; i < msg_len; i++) {
+ hdmi_writeb(msg[i], HDMI_CEC_TX_DATA0+i);
+ }
+
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ val |= 0x01;
+ hdmi_writeb(val, HDMI_CEC_CTRL);
+ memcpy(hdmi_cec_data.last_msg, msg, msg_len);
+ hdmi_cec_data.msg_len = msg_len;
+
+ i = 0;
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ while ((val & 0x01) == 0x1) {
+ msleep(50);
+ i++;
+ if (i > 3) {
+ ret = -EIO;
+ goto end;
+ }
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ }
+
+end:
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ return ret;
+}
+
+/*!
+ * @brief IO ctrl function for vpu file operation
+ * @param cmd IO ctrl command
+ * @return 0 on success or negative error code on error
+ */
+static long hdmi_cec_ioctl(struct file *filp, u_int cmd,
+ u_long arg)
+{
+ int ret = 0, status = 0;
+ u8 val = 0, msg = 0;
+ struct mxc_edid_cfg hdmi_edid_cfg;
+
+ pr_debug("function : %s\n", __func__);
+ if (!open_count)
+ return -ENODEV;
+
+ switch (cmd) {
+ case HDMICEC_IOC_SETLOGICALADDRESS:
+ mutex_lock(&hdmi_cec_data.lock);
+ if (false == hdmi_cec_data.cec_state) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EACCES;
+ }
+
+ hdmi_cec_data.Logical_address = (u8)arg;
+
+ if (hdmi_cec_data.Logical_address <= 7) {
+ val = 1 << hdmi_cec_data.Logical_address;
+ hdmi_writeb(val, HDMI_CEC_ADDR_L);
+ hdmi_writeb(0, HDMI_CEC_ADDR_H);
+ } else if (hdmi_cec_data.Logical_address > 7 &&
+ hdmi_cec_data.Logical_address <= 15) {
+ val = 1 << (hdmi_cec_data.Logical_address - 8);
+ hdmi_writeb(val, HDMI_CEC_ADDR_H);
+ hdmi_writeb(0, HDMI_CEC_ADDR_L);
+ } else {
+ ret = -EINVAL;
+ }
+
+ /* Send Polling message with same source
+ * and destination address
+ */
+ if (0 == ret && 15 != hdmi_cec_data.Logical_address) {
+ msg = (hdmi_cec_data.Logical_address << 4) |
+ hdmi_cec_data.Logical_address;
+ hdmi_writeb(1, HDMI_CEC_TX_CNT);
+ hdmi_writeb(msg, HDMI_CEC_TX_DATA0);
+
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ val |= 0x01;
+ hdmi_writeb(val, HDMI_CEC_CTRL);
+ }
+
+ mutex_unlock(&hdmi_cec_data.lock);
+ break;
+
+ case HDMICEC_IOC_STARTDEVICE:
+ val = hdmi_readb(HDMI_MC_CLKDIS);
+ val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
+ hdmi_writeb(val, HDMI_MC_CLKDIS);
+
+ hdmi_writeb(0x02, HDMI_CEC_CTRL);
+
+ val = HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK |
+ HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE;
+ hdmi_writeb(val, HDMI_CEC_POLARITY);
+
+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL |
+ HDMI_IH_CEC_STAT0_ARB_LOST;
+ hdmi_writeb(val, HDMI_CEC_MASK);
+ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
+
+ mutex_lock(&hdmi_cec_data.lock);
+ hdmi_cec_data.cec_state = true;
+ mutex_unlock(&hdmi_cec_data.lock);
+ break;
+
+ case HDMICEC_IOC_STOPDEVICE:
+ hdmi_writeb(0x10, HDMI_CEC_CTRL);
+
+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL |
+ HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_ARB_LOST |
+ HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM |
+ HDMI_IH_CEC_STAT0_DONE;
+ hdmi_writeb(val, HDMI_CEC_MASK);
+ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
+
+ hdmi_writeb(0x0, HDMI_CEC_POLARITY);
+
+ val = hdmi_readb(HDMI_MC_CLKDIS);
+ val |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
+ hdmi_writeb(val, HDMI_MC_CLKDIS);
+
+ mutex_lock(&hdmi_cec_data.lock);
+ hdmi_cec_data.cec_state = false;
+ mutex_unlock(&hdmi_cec_data.lock);
+ break;
+
+ case HDMICEC_IOC_GETPHYADDRESS:
+ hdmi_get_edid_cfg(&hdmi_edid_cfg);
+ status = copy_to_user((void __user *)arg,
+ &hdmi_edid_cfg.physical_address,
+ 4*sizeof(u8));
+ if (status)
+ ret = -EFAULT;
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+* @brief Release function for vpu file operation
+* @return 0 on success or negative error code on error
+*/
+static int hdmi_cec_release(struct inode *inode, struct file *filp)
+{
+ mutex_lock(&hdmi_cec_data.lock);
+
+ if (open_count) {
+ open_count = 0;
+ hdmi_cec_data.cec_state = false;
+ hdmi_cec_data.Logical_address = 15;
+ }
+
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ return 0;
+}
+
+static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+
+ pr_debug("function : %s\n", __func__);
+
+ if (!open_count)
+ return -ENODEV;
+
+ if (false == hdmi_cec_data.cec_state)
+ return -EACCES;
+
+ poll_wait(file, &hdmi_cec_queue, wait);
+
+ if (!list_empty(&head))
+ mask |= (POLLIN | POLLRDNORM);
+
+ return mask;
+}
+
+const struct file_operations hdmi_cec_fops = {
+ .owner = THIS_MODULE,
+ .read = hdmi_cec_read,
+ .write = hdmi_cec_write,
+ .open = hdmi_cec_open,
+ .unlocked_ioctl = hdmi_cec_ioctl,
+ .release = hdmi_cec_release,
+ .poll = hdmi_cec_poll,
+};
+
+static int hdmi_cec_dev_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ struct device *temp_class;
+ struct resource *res;
+ struct pinctrl *pinctrl;
+ int irq = platform_get_irq(pdev, 0);
+
+ hdmi_cec_major = register_chrdev(hdmi_cec_major,
+ "mxc_hdmi_cec", &hdmi_cec_fops);
+ if (hdmi_cec_major < 0) {
+ dev_err(&pdev->dev, "hdmi_cec: unable to get a major for HDMI CEC\n");
+ err = -EBUSY;
+ goto out;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (unlikely(res == NULL)) {
+ dev_err(&pdev->dev, "hdmi_cec:No HDMI irq line provided\n");
+ goto err_out_chrdev;
+ }
+
+ spin_lock_init(&hdmi_cec_data.irq_lock);
+
+ err = devm_request_irq(&pdev->dev, irq, mxc_hdmi_cec_isr, IRQF_SHARED,
+ dev_name(&pdev->dev), &hdmi_cec_data);
+ if (err < 0) {
+ dev_err(&pdev->dev, "hdmi_cec:Unable to request irq: %d\n", err);
+ goto err_out_chrdev;
+ }
+
+ hdmi_cec_class = class_create(THIS_MODULE, "mxc_hdmi_cec");
+ if (IS_ERR(hdmi_cec_class)) {
+ err = PTR_ERR(hdmi_cec_class);
+ goto err_out_chrdev;
+ }
+
+ temp_class = device_create(hdmi_cec_class, NULL,
+ MKDEV(hdmi_cec_major, 0), NULL, "mxc_hdmi_cec");
+ if (IS_ERR(temp_class)) {
+ err = PTR_ERR(temp_class);
+ goto err_out_class;
+ }
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(&pdev->dev, "can't get/select CEC pinctrl\n");
+ goto err_out_class;
+ }
+
+ init_waitqueue_head(&hdmi_cec_queue);
+
+ INIT_LIST_HEAD(&head);
+
+ mutex_init(&hdmi_cec_data.lock);
+
+ hdmi_cec_data.Logical_address = 15;
+
+ platform_set_drvdata(pdev, &hdmi_cec_data);
+
+ INIT_DELAYED_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker);
+
+ dev_info(&pdev->dev, "HDMI CEC initialized\n");
+ goto out;
+
+err_out_class:
+ device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0));
+ class_destroy(hdmi_cec_class);
+err_out_chrdev:
+ unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec");
+out:
+ return err;
+}
+
+static int hdmi_cec_dev_remove(struct platform_device *pdev)
+{
+ if (hdmi_cec_major > 0) {
+ device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0));
+ class_destroy(hdmi_cec_class);
+ unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec");
+ hdmi_cec_major = 0;
+ }
+ return 0;
+}
+
+static const struct of_device_id imx_hdmi_cec_match[] = {
+ { .compatible = "fsl,imx6q-hdmi-cec", },
+ { .compatible = "fsl,imx6dl-hdmi-cec", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver mxc_hdmi_cec_driver = {
+ .probe = hdmi_cec_dev_probe,
+ .remove = hdmi_cec_dev_remove,
+ .driver = {
+ .name = "mxc_hdmi_cec",
+ .of_match_table = imx_hdmi_cec_match,
+ },
+};
+
+module_platform_driver(mxc_hdmi_cec_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Linux HDMI CEC driver for Freescale i.MX/MXC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxc_hdmi_cec");
+
diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h
new file mode 100644
index 000000000000..5c402af4d0c3
--- /dev/null
+++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2005-2015 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
+ */
+#ifndef _HDMICEC_H_
+#define _HDMICEC_H_
+#include <linux/ioctl.h>
+
+/*
+ * Ioctl definitions
+ */
+
+/* Use 'k' as magic number */
+#define HDMICEC_IOC_MAGIC 'H'
+/*
+ * S means "Set" through a ptr,
+ * T means "Tell" directly with the argument value
+ * G means "Get": reply by setting through a pointer
+ * Q means "Query": response is on the return value
+ * X means "eXchange": G and S atomically
+ * H means "sHift": T and Q atomically
+ */
+#define HDMICEC_IOC_SETLOGICALADDRESS \
+ _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char)
+#define HDMICEC_IOC_STARTDEVICE _IO(HDMICEC_IOC_MAGIC, 2)
+#define HDMICEC_IOC_STOPDEVICE _IO(HDMICEC_IOC_MAGIC, 3)
+#define HDMICEC_IOC_GETPHYADDRESS \
+ _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4])
+
+#endif /* !_HDMICEC_H_ */
diff --git a/drivers/mxc/ipu3/Kconfig b/drivers/mxc/ipu3/Kconfig
new file mode 100644
index 000000000000..c702efed2b55
--- /dev/null
+++ b/drivers/mxc/ipu3/Kconfig
@@ -0,0 +1,21 @@
+config MXC_IPU_V3
+ bool
+
+config MXC_IPU_V3_PRG
+ tristate "i.MX IPUv3 prefetch gasket engine"
+ depends on MXC_IPU_V3 && MXC_IPU_V3_PRE
+ help
+ This enables support for the IPUv3 prefetch gasket engine to
+ support double buffer handshake control bewteen IPUv3 and
+ prefetch engine(PRE), snoop the AXI interface for display
+ refresh requests to memory and modify the request address to
+ fetch the double buffered row of blocks in OCRAM.
+
+config MXC_IPU_V3_PRE
+ tristate "i.MX IPUv3 prefetch engine"
+ depends on MXC_IPU_V3
+ select MXC_IPU_V3_PRG
+ help
+ This enables support for the IPUv3 prefetch engine to improve
+ the system memory performance. The engine has the capability
+ to resolve framebuffers in tile pixel format to linear.
diff --git a/drivers/mxc/ipu3/Makefile b/drivers/mxc/ipu3/Makefile
new file mode 100644
index 000000000000..d48f11244073
--- /dev/null
+++ b/drivers/mxc/ipu3/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_MXC_IPU_V3) = mxc_ipu.o
+
+obj-$(CONFIG_MXC_IPU_V3_PRG) += prg.o
+obj-$(CONFIG_MXC_IPU_V3_PRE) += pre.o
+
+mxc_ipu-objs := ipu_common.o ipu_ic.o ipu_disp.o ipu_capture.o ipu_device.o \
+ ipu_calc_stripes_sizes.o vdoa.o ipu_pixel_clk.o
diff --git a/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c b/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c
new file mode 100644
index 000000000000..512404d4101c
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c
@@ -0,0 +1,495 @@
+/*
+ * Copyright 2009-2015 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 ipu_calc_stripes_sizes.c
+ *
+ * @brief IPU IC functions
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/ipu-v3.h>
+#include <linux/module.h>
+#include <linux/math64.h>
+
+#define BPP_32 0
+#define BPP_16 3
+#define BPP_8 5
+#define BPP_24 1
+#define BPP_12 4
+#define BPP_18 2
+
+static u32 truncate(u32 up, /* 0: down; else: up */
+ u64 a, /* must be non-negative */
+ u32 b)
+{
+ u32 d;
+ u64 div;
+ div = div_u64(a, b);
+ d = b * (div >> 32);
+ if (up && (a > (((u64)d) << 32)))
+ return d+b;
+ else
+ return d;
+}
+
+static unsigned int f_calc(unsigned int pfs, unsigned int bpp, unsigned int *write)
+{/* return input_f */
+ unsigned int f_calculated = 0;
+ switch (pfs) {
+ case IPU_PIX_FMT_YVU422P:
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_YUV444P:
+ f_calculated = 16;
+ break;
+
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_UYVY:
+ f_calculated = 8;
+ break;
+
+ case IPU_PIX_FMT_NV12:
+ f_calculated = 8;
+ break;
+
+ default:
+ f_calculated = 0;
+ break;
+
+ }
+ if (!f_calculated) {
+ switch (bpp) {
+ case BPP_32:
+ f_calculated = 2;
+ break;
+
+ case BPP_16:
+ f_calculated = 4;
+ break;
+
+ case BPP_8:
+ case BPP_24:
+ f_calculated = 8;
+ break;
+
+ case BPP_12:
+ f_calculated = 16;
+ break;
+
+ case BPP_18:
+ f_calculated = 32;
+ break;
+
+ default:
+ f_calculated = 0;
+ break;
+ }
+ }
+ return f_calculated;
+}
+
+
+static unsigned int m_calc(unsigned int pfs)
+{
+ unsigned int m_calculated = 0;
+ switch (pfs) {
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YVU422P:
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_YUV444P:
+ m_calculated = 16;
+ break;
+
+ case IPU_PIX_FMT_NV12:
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_UYVY:
+ m_calculated = 8;
+ break;
+
+ default:
+ m_calculated = 8;
+ break;
+
+ }
+ return m_calculated;
+}
+
+static int calc_split_resize_coeffs(unsigned int inSize, unsigned int outSize,
+ unsigned int *resizeCoeff,
+ unsigned int *downsizeCoeff)
+{
+ uint32_t tempSize;
+ uint32_t tempDownsize;
+
+ if (inSize > 4096) {
+ pr_debug("IC input size(%d) cannot exceed 4096\n",
+ inSize);
+ return -EINVAL;
+ }
+
+ if (outSize > 1024) {
+ pr_debug("IC output size(%d) cannot exceed 1024\n",
+ outSize);
+ return -EINVAL;
+ }
+
+ if ((outSize << 3) < inSize) {
+ pr_debug("IC cannot downsize more than 8:1\n");
+ return -EINVAL;
+ }
+
+ /* Compute downsizing coefficient */
+ /* Output of downsizing unit cannot be more than 1024 */
+ tempDownsize = 0;
+ tempSize = inSize;
+ while (((tempSize > 1024) || (tempSize >= outSize * 2)) &&
+ (tempDownsize < 2)) {
+ tempSize >>= 1;
+ tempDownsize++;
+ }
+ *downsizeCoeff = tempDownsize;
+
+ /* compute resizing coefficient using the following equation:
+ resizeCoeff = M*(SI -1)/(SO - 1)
+ where M = 2^13, SI - input size, SO - output size */
+ *resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
+ if (*resizeCoeff >= 16384L) {
+ pr_debug("Overflow on IC resize coefficient.\n");
+ return -EINVAL;
+ }
+
+ pr_debug("resizing from %u -> %u pixels, "
+ "downsize=%u, resize=%u.%lu (reg=%u)\n", inSize, outSize,
+ *downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
+ ((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
+
+ return 0;
+}
+
+/* Stripe parameters calculator */
+/**************************************************************************
+Notes:
+MSW = the maximal width allowed for a stripe
+ i.MX31: 720, i.MX35: 800, i.MX37/51/53: 1024
+cirr = the maximal inverse resizing ratio for which overlap in the input
+ is requested; typically cirr~2
+flags
+ bit 0 - equal_stripes
+ 0 each stripe is allowed to have independent parameters
+ for maximal image quality
+ 1 the stripes are requested to have identical parameters
+ (except the base address), for maximal performance
+ bit 1 - vertical/horizontal
+ 0 horizontal
+ 1 vertical
+
+If performance is the top priority (above image quality)
+ Avoid overlap, by setting CIRR = 0
+ This will also force effectively identical_stripes = 1
+ Choose IF & OF that corresponds to the same IOX/SX for both stripes
+ Choose IFW & OFW such that
+ IFW/IM, IFW/IF, OFW/OM, OFW/OF are even integers
+ The function returns an error status:
+ 0: no error
+ 1: invalid input parameters -> aborted without result
+ Valid parameters should satisfy the following conditions
+ IFW <= OFW, otherwise downsizing is required
+ - which is not supported yet
+ 4 <= IFW,OFW, so some interpolation may be needed even without overlap
+ IM, OM, IF, OF should not vanish
+ 2*IF <= IFW
+ so the frame can be split to two equal stripes, even without overlap
+ 2*(OF+IF/irr_opt) <= OFW
+ so a valid positive INW exists even for equal stripes
+ OF <= MSW, otherwise, the left stripe cannot be sufficiently large
+ MSW < OFW, so splitting to stripes is required
+ OFW <= 2*MSW, so two stripes are sufficient
+ (this also implies that 2<=MSW)
+ 2: OF is not a multiple of OM - not fully-supported yet
+ Output is produced but OW is not guaranited to be a multiple of OM
+ 4: OFW reduced to be a multiple of OM
+ 8: CIRR > 1: truncated to 1
+ Overlap is not supported (and not needed) y for upsizing)
+**************************************************************************/
+int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
+ /* input frame width;>1 */
+ unsigned int output_frame_width, /* output frame width; >1 */
+ const unsigned int maximal_stripe_width,
+ /* the maximal width allowed for a stripe */
+ const unsigned long long cirr, /* see above */
+ const unsigned int flags, /* see above */
+ u32 input_pixelformat,/* pixel format after of read channel*/
+ u32 output_pixelformat,/* pixel format after of write channel*/
+ struct stripe_param *left,
+ struct stripe_param *right)
+{
+ const unsigned int irr_frac_bits = 13;
+ const unsigned long irr_steps = 1 << irr_frac_bits;
+ const u64 dirr = ((u64)1) << (32 - 2);
+ /* The maximum relative difference allowed between the irrs */
+ const u64 cr = ((u64)4) << 32;
+ /* The importance ratio between the two terms in the cost function below */
+
+ unsigned int status;
+ unsigned int temp;
+ unsigned int onw_min;
+ unsigned int inw = 0, onw = 0, inw_best = 0;
+ /* number of pixels in the left stripe NOT hidden by the right stripe */
+ u64 irr_opt; /* the optimal inverse resizing ratio */
+ u64 rr_opt; /* the optimal resizing ratio = 1/irr_opt*/
+ u64 dinw; /* the misalignment between the stripes */
+ /* (measured in units of input columns) */
+ u64 difwl, difwr = 0;
+ /* The number of input columns not reflected in the output */
+ /* the resizing ratio used for the right stripe is */
+ /* left->irr and right->irr respectively */
+ u64 cost, cost_min;
+ u64 div; /* result of division */
+ bool equal_stripes = (flags & 0x1) != 0;
+ bool vertical = (flags & 0x2) != 0;
+
+ unsigned int input_m, input_f, output_m, output_f; /* parameters for upsizing by stripes */
+ unsigned int resize_coeff;
+ unsigned int downsize_coeff;
+
+ status = 0;
+
+ if (vertical) {
+ input_f = 2;
+ input_m = 8;
+ output_f = 8;
+ output_m = 2;
+ } else {
+ input_f = f_calc(input_pixelformat, 0, NULL);
+ input_m = m_calc(input_pixelformat);
+ output_f = input_m;
+ output_m = m_calc(output_pixelformat);
+ }
+ if ((input_frame_width < 4) || (output_frame_width < 4))
+ return 1;
+
+ irr_opt = div_u64((((u64)(input_frame_width - 1)) << 32),
+ (output_frame_width - 1));
+ rr_opt = div_u64((((u64)(output_frame_width - 1)) << 32),
+ (input_frame_width - 1));
+
+ if ((input_m == 0) || (output_m == 0) || (input_f == 0) || (output_f == 0)
+ || (input_frame_width < (2 * input_f))
+ || ((((u64)output_frame_width) << 32) <
+ (2 * ((((u64)output_f) << 32) + (input_f * rr_opt))))
+ || (maximal_stripe_width < output_f)
+ || ((output_frame_width <= maximal_stripe_width)
+ && (equal_stripes == 0))
+ || ((2 * maximal_stripe_width) < output_frame_width))
+ return 1;
+
+ if (output_f % output_m)
+ status += 2;
+
+ temp = truncate(0, (((u64)output_frame_width) << 32), output_m);
+ if (temp < output_frame_width) {
+ output_frame_width = temp;
+ status += 4;
+ }
+
+ pr_debug("---------------->\n"
+ "if = %d\n"
+ "im = %d\n"
+ "of = %d\n"
+ "om = %d\n"
+ "irr_opt = %llu\n"
+ "rr_opt = %llu\n"
+ "cirr = %llu\n"
+ "pixel in = %08x\n"
+ "pixel out = %08x\n"
+ "ifw = %d\n"
+ "ofwidth = %d\n",
+ input_f,
+ input_m,
+ output_f,
+ output_m,
+ irr_opt,
+ rr_opt,
+ cirr,
+ input_pixelformat,
+ output_pixelformat,
+ input_frame_width,
+ output_frame_width
+ );
+
+ if (equal_stripes) {
+ if ((irr_opt > cirr) /* overlap in the input is not requested */
+ && ((input_frame_width % (input_m << 1)) == 0)
+ && ((input_frame_width % (input_f << 1)) == 0)
+ && ((output_frame_width % (output_m << 1)) == 0)
+ && ((output_frame_width % (output_f << 1)) == 0)) {
+ /* without overlap */
+ left->input_width = right->input_width = right->input_column =
+ input_frame_width >> 1;
+ left->output_width = right->output_width = right->output_column =
+ output_frame_width >> 1;
+ left->input_column = 0;
+ left->output_column = 0;
+ div = div_u64(((((u64)irr_steps) << 32) *
+ (right->input_width - 1)), (right->output_width - 1));
+ left->irr = right->irr = truncate(0, div, 1);
+ } else { /* with overlap */
+ onw = truncate(0, (((u64)output_frame_width - 1) << 32) >> 1,
+ output_f);
+ inw = truncate(0, onw * irr_opt, input_f);
+ /* this is the maximal inw which allows the same resizing ratio */
+ /* in both stripes */
+ onw = truncate(1, (inw * rr_opt), output_f);
+ div = div_u64((((u64)(irr_steps * inw)) <<
+ 32), onw);
+ left->irr = right->irr = truncate(0, div, 1);
+ left->output_width = right->output_width =
+ output_frame_width - onw;
+ /* These are valid assignments for output_width, */
+ /* assuming output_f is a multiple of output_m */
+ div = (((u64)(left->output_width-1) * (left->irr)) << 32);
+ div = (((u64)1) << 32) + div_u64(div, irr_steps);
+
+ left->input_width = right->input_width = truncate(1, div, input_m);
+
+ div = div_u64((((u64)((right->output_width - 1) * right->irr)) <<
+ 32), irr_steps);
+ difwr = (((u64)(input_frame_width - 1 - inw)) << 32) - div;
+ div = div_u64((difwr + (((u64)input_f) << 32)), 2);
+ left->input_column = truncate(0, div, input_f);
+
+
+ /* This splits the truncated input columns evenly */
+ /* between the left and right margins */
+ right->input_column = left->input_column + inw;
+ left->output_column = 0;
+ right->output_column = onw;
+ }
+ if (left->input_width > left->output_width) {
+ if (calc_split_resize_coeffs(left->input_width,
+ left->output_width,
+ &resize_coeff,
+ &downsize_coeff) < 0)
+ return -EINVAL;
+
+ if (downsize_coeff > 0) {
+ left->irr = right->irr =
+ (downsize_coeff << 14) | resize_coeff;
+ }
+ }
+ pr_debug("inw %d, onw %d, ilw %d, ilc %d, olw %d,"
+ " irw %d, irc %d, orw %d, orc %d, "
+ "difwr %llu, lirr %u\n",
+ inw, onw, left->input_width,
+ left->input_column, left->output_width,
+ right->input_width, right->input_column,
+ right->output_width,
+ right->output_column, difwr, left->irr);
+ } else { /* independent stripes */
+ onw_min = output_frame_width - maximal_stripe_width;
+ /* onw is a multiple of output_f, in the range */
+ /* [max(output_f,output_frame_width-maximal_stripe_width),*/
+ /*min(output_frame_width-2,maximal_stripe_width)] */
+ /* definitely beyond the cost of any valid setting */
+ cost_min = (((u64)input_frame_width) << 32) + cr;
+ onw = truncate(0, ((u64)maximal_stripe_width), output_f);
+ if (output_frame_width - onw == 1)
+ onw -= output_f; /* => onw and output_frame_width-1-onw are positive */
+ inw = truncate(0, onw * irr_opt, input_f);
+ /* this is the maximal inw which allows the same resizing ratio */
+ /* in both stripes */
+ onw = truncate(1, inw * rr_opt, output_f);
+ do {
+ div = div_u64((((u64)(irr_steps * inw)) << 32), onw);
+ left->irr = truncate(0, div, 1);
+ div = div_u64((((u64)(onw * left->irr)) << 32),
+ irr_steps);
+ dinw = (((u64)inw) << 32) - div;
+
+ div = div_u64((((u64)((output_frame_width - 1 - onw) * left->irr)) <<
+ 32), irr_steps);
+
+ difwl = (((u64)(input_frame_width - 1 - inw)) << 32) - div;
+
+ cost = difwl + (((u64)(cr * dinw)) >> 32);
+
+ if (cost < cost_min) {
+ inw_best = inw;
+ cost_min = cost;
+ }
+
+ inw -= input_f;
+ onw = truncate(1, inw * rr_opt, output_f);
+ /* This is the minimal onw which allows the same resizing ratio */
+ /* in both stripes */
+ } while (onw >= onw_min);
+
+ inw = inw_best;
+ onw = truncate(1, inw * rr_opt, output_f);
+ div = div_u64((((u64)(irr_steps * inw)) << 32), onw);
+ left->irr = truncate(0, div, 1);
+
+ left->output_width = onw;
+ right->output_width = output_frame_width - onw;
+ /* These are valid assignments for output_width, */
+ /* assuming output_f is a multiple of output_m */
+ left->input_width = truncate(1, ((u64)(inw + 1)) << 32, input_m);
+ right->input_width = truncate(1, ((u64)(input_frame_width - inw)) <<
+ 32, input_m);
+
+ div = div_u64((((u64)(irr_steps * (input_frame_width - 1 - inw))) <<
+ 32), (right->output_width - 1));
+ right->irr = truncate(0, div, 1);
+ temp = truncate(0, ((u64)left->irr) * ((((u64)1) << 32) + dirr), 1);
+ if (temp < right->irr)
+ right->irr = temp;
+ div = div_u64(((u64)((right->output_width - 1) * right->irr) <<
+ 32), irr_steps);
+ difwr = (u64)(input_frame_width - 1 - inw) - div;
+
+
+ div = div_u64((difwr + (((u64)input_f) << 32)), 2);
+ left->input_column = truncate(0, div, input_f);
+
+ /* This splits the truncated input columns evenly */
+ /* between the left and right margins */
+ right->input_column = left->input_column + inw;
+ left->output_column = 0;
+ right->output_column = onw;
+ if (left->input_width > left->output_width) {
+ if (calc_split_resize_coeffs(left->input_width,
+ left->output_width,
+ &resize_coeff,
+ &downsize_coeff) < 0)
+ return -EINVAL;
+ left->irr = (downsize_coeff << 14) | resize_coeff;
+ }
+ if (right->input_width > right->output_width) {
+ if (calc_split_resize_coeffs(right->input_width,
+ right->output_width,
+ &resize_coeff,
+ &downsize_coeff) < 0)
+ return -EINVAL;
+ right->irr = (downsize_coeff << 14) | resize_coeff;
+ }
+ }
+ return status;
+}
+EXPORT_SYMBOL(ipu_calc_stripes_sizes);
diff --git a/drivers/mxc/ipu3/ipu_capture.c b/drivers/mxc/ipu3/ipu_capture.c
new file mode 100644
index 000000000000..f304c8140be4
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_capture.c
@@ -0,0 +1,816 @@
+/*
+ * Copyright 2008-2015 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 ipu_capture.c
+ *
+ * @brief IPU capture dase functions
+ *
+ * @ingroup IPU
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ipu-v3.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include "ipu_prv.h"
+#include "ipu_regs.h"
+
+/*!
+ * _ipu_csi_mclk_set
+ *
+ * @param ipu ipu handler
+ * @param pixel_clk desired pixel clock frequency in Hz
+ * @param csi csi 0 or csi 1
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int _ipu_csi_mclk_set(struct ipu_soc *ipu, uint32_t pixel_clk, uint32_t csi)
+{
+ uint32_t temp;
+ int32_t div_ratio;
+
+ div_ratio = (clk_get_rate(ipu->ipu_clk) / pixel_clk) - 1;
+
+ if (div_ratio > 0xFF || div_ratio < 0) {
+ dev_dbg(ipu->dev, "value of pixel_clk extends normal range\n");
+ return -EINVAL;
+ }
+
+ temp = ipu_csi_read(ipu, csi, CSI_SENS_CONF);
+ temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
+ ipu_csi_write(ipu, csi, temp |
+ (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
+ CSI_SENS_CONF);
+
+ return 0;
+}
+
+/*!
+ * ipu_csi_init_interface
+ * Sets initial values for the CSI registers.
+ * The width and height of the sensor and the actual frame size will be
+ * set to the same values.
+ * @param ipu ipu handler
+ * @param width Sensor width
+ * @param height Sensor height
+ * @param pixel_fmt pixel format
+ * @param cfg_param ipu_csi_signal_cfg_t structure
+ * @param csi csi 0 or csi 1
+ *
+ * @return 0 for success, -EINVAL for error
+ */
+int32_t
+ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
+ uint32_t pixel_fmt, ipu_csi_signal_cfg_t cfg_param)
+{
+ uint32_t data = 0;
+ uint32_t csi = cfg_param.csi;
+
+ /* Set SENS_DATA_FORMAT bits (8, 9 and 10)
+ RGB or YUV444 is 0 which is current value in data so not set
+ explicitly
+ This is also the default value if attempts are made to set it to
+ something invalid. */
+ switch (pixel_fmt) {
+ case IPU_PIX_FMT_YUYV:
+ cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
+ break;
+ case IPU_PIX_FMT_UYVY:
+ cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
+ break;
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_BGR24:
+ cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
+ break;
+ case IPU_PIX_FMT_GENERIC:
+ case IPU_PIX_FMT_GENERIC_16:
+ cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
+ break;
+ case IPU_PIX_FMT_RGB565:
+ cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
+ break;
+ case IPU_PIX_FMT_RGB555:
+ cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Set the CSI_SENS_CONF register remaining fields */
+ data |= cfg_param.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
+ cfg_param.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
+ cfg_param.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
+ cfg_param.Vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
+ cfg_param.Hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
+ cfg_param.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
+ cfg_param.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
+ cfg_param.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
+ cfg_param.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
+ cfg_param.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
+ cfg_param.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
+
+ _ipu_get(ipu);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ ipu_csi_write(ipu, csi, data, CSI_SENS_CONF);
+
+ /* Setup sensor frame size */
+ ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_SENS_FRM_SIZE);
+
+ /* Set CCIR registers */
+ if (cfg_param.clk_mode == IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE) {
+ ipu_csi_write(ipu, csi, 0x40030, CSI_CCIR_CODE_1);
+ ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
+ } else if (cfg_param.clk_mode == IPU_CSI_CLK_MODE_CCIR656_INTERLACED) {
+ if (width == 720 && height == 625) {
+ /* PAL case */
+ /*
+ * Field0BlankEnd = 0x6, Field0BlankStart = 0x2,
+ * Field0ActiveEnd = 0x4, Field0ActiveStart = 0
+ */
+ ipu_csi_write(ipu, csi, 0x40596, CSI_CCIR_CODE_1);
+ /*
+ * Field1BlankEnd = 0x7, Field1BlankStart = 0x3,
+ * Field1ActiveEnd = 0x5, Field1ActiveStart = 0x1
+ */
+ ipu_csi_write(ipu, csi, 0xD07DF, CSI_CCIR_CODE_2);
+
+ ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
+
+ } else if (width == 720 && height == 525) {
+ /* NTSC case */
+ /*
+ * Field0BlankEnd = 0x7, Field0BlankStart = 0x3,
+ * Field0ActiveEnd = 0x5, Field0ActiveStart = 0x1
+ */
+ ipu_csi_write(ipu, csi, 0xD07DF, CSI_CCIR_CODE_1);
+ /*
+ * Field1BlankEnd = 0x6, Field1BlankStart = 0x2,
+ * Field1ActiveEnd = 0x4, Field1ActiveStart = 0
+ */
+ ipu_csi_write(ipu, csi, 0x40596, CSI_CCIR_CODE_2);
+ ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
+ } else {
+ dev_err(ipu->dev, "Unsupported CCIR656 interlaced "
+ "video mode\n");
+ mutex_unlock(&ipu->mutex_lock);
+ _ipu_put(ipu);
+ return -EINVAL;
+ }
+ _ipu_csi_ccir_err_detection_enable(ipu, csi);
+ } else if ((cfg_param.clk_mode ==
+ IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR) ||
+ (cfg_param.clk_mode ==
+ IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR) ||
+ (cfg_param.clk_mode ==
+ IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR) ||
+ (cfg_param.clk_mode ==
+ IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR)) {
+ ipu_csi_write(ipu, csi, 0x40030, CSI_CCIR_CODE_1);
+ ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
+ _ipu_csi_ccir_err_detection_enable(ipu, csi);
+ } else if ((cfg_param.clk_mode == IPU_CSI_CLK_MODE_GATED_CLK) ||
+ (cfg_param.clk_mode == IPU_CSI_CLK_MODE_NONGATED_CLK)) {
+ _ipu_csi_ccir_err_detection_disable(ipu, csi);
+ }
+
+ dev_dbg(ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
+ ipu_csi_read(ipu, csi, CSI_SENS_CONF));
+ dev_dbg(ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
+ ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE));
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ _ipu_put(ipu);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_csi_init_interface);
+
+/*!
+ * ipu_csi_get_sensor_protocol
+ *
+ * @param ipu ipu handler
+ * @param csi csi 0 or csi 1
+ *
+ * @return Returns sensor protocol
+ */
+int32_t ipu_csi_get_sensor_protocol(struct ipu_soc *ipu, uint32_t csi)
+{
+ int ret;
+ _ipu_get(ipu);
+ ret = (ipu_csi_read(ipu, csi, CSI_SENS_CONF) &
+ CSI_SENS_CONF_SENS_PRTCL_MASK) >>
+ CSI_SENS_CONF_SENS_PRTCL_SHIFT;
+ _ipu_put(ipu);
+ return ret;
+}
+EXPORT_SYMBOL(ipu_csi_get_sensor_protocol);
+
+/*!
+ * ipu_csi_enable_mclk
+ *
+ * @param ipu ipu handler
+ * @param csi csi 0 or csi 1
+ * @param flag true to enable mclk, false to disable mclk
+ * @param wait true to wait 100ms make clock stable, false not wait
+ *
+ * @return Returns 0 on success
+ */
+int ipu_csi_enable_mclk(struct ipu_soc *ipu, int csi, bool flag, bool wait)
+{
+ /* Return immediately if there is no csi_clk to manage */
+ if (ipu->csi_clk[csi] == NULL)
+ return 0;
+
+ if (flag) {
+ clk_enable(ipu->csi_clk[csi]);
+ if (wait == true)
+ msleep(10);
+ } else {
+ clk_disable(ipu->csi_clk[csi]);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_csi_enable_mclk);
+
+/*!
+ * ipu_csi_get_window_size
+ *
+ * @param ipu ipu handler
+ * @param width pointer to window width
+ * @param height pointer to window height
+ * @param csi csi 0 or csi 1
+ */
+void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi)
+{
+ uint32_t reg;
+
+ _ipu_get(ipu);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ reg = ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE);
+ *width = (reg & 0xFFFF) + 1;
+ *height = (reg >> 16 & 0xFFFF) + 1;
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ _ipu_put(ipu);
+}
+EXPORT_SYMBOL(ipu_csi_get_window_size);
+
+/*!
+ * ipu_csi_set_window_size
+ *
+ * @param ipu ipu handler
+ * @param width window width
+ * @param height window height
+ * @param csi csi 0 or csi 1
+ */
+void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi)
+{
+ _ipu_get(ipu);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE);
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ _ipu_put(ipu);
+}
+EXPORT_SYMBOL(ipu_csi_set_window_size);
+
+/*!
+ * ipu_csi_set_window_pos
+ *
+ * @param ipu ipu handler
+ * @param left uint32 window x start
+ * @param top uint32 window y start
+ * @param csi csi 0 or csi 1
+ */
+void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi)
+{
+ uint32_t temp;
+
+ _ipu_get(ipu);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
+ temp &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
+ temp |= ((top << CSI_VSC_SHIFT) | (left << CSI_HSC_SHIFT));
+ ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ _ipu_put(ipu);
+}
+EXPORT_SYMBOL(ipu_csi_set_window_pos);
+
+/*!
+ * _ipu_csi_horizontal_downsize_enable
+ * Enable horizontal downsizing(decimation) by 2.
+ *
+ * @param ipu ipu handler
+ * @param csi csi 0 or csi 1
+ */
+void _ipu_csi_horizontal_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
+{
+ uint32_t temp;
+
+ temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
+ temp |= CSI_HORI_DOWNSIZE_EN;
+ ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+}
+
+/*!
+ * _ipu_csi_horizontal_downsize_disable
+ * Disable horizontal downsizing(decimation) by 2.
+ *
+ * @param ipu ipu handler
+ * @param csi csi 0 or csi 1
+ */
+void _ipu_csi_horizontal_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
+{
+ uint32_t temp;
+
+ temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
+ temp &= ~CSI_HORI_DOWNSIZE_EN;
+ ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+}
+
+/*!
+ * _ipu_csi_vertical_downsize_enable
+ * Enable vertical downsizing(decimation) by 2.
+ *
+ * @param ipu ipu handler
+ * @param csi csi 0 or csi 1
+ */
+void _ipu_csi_vertical_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
+{
+ uint32_t temp;
+
+ temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
+ temp |= CSI_VERT_DOWNSIZE_EN;
+ ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+}
+
+/*!
+ * _ipu_csi_vertical_downsize_disable
+ * Disable vertical downsizing(decimation) by 2.
+ *
+ * @param ipu ipu handler
+ * @param csi csi 0 or csi 1
+ */
+void _ipu_csi_vertical_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
+{
+ uint32_t temp;
+
+ temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
+ temp &= ~CSI_VERT_DOWNSIZE_EN;
+ ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+}
+
+/*!
+ * _ipu_csi_set_test_generator
+ *
+ * @param ipu ipu handler
+ * @param active 1 for active and 0 for inactive
+ * @param r_value red value for the generated pattern of even pixel
+ * @param g_value green value for the generated pattern of even
+ * pixel
+ * @param b_value blue value for the generated pattern of even pixel
+ * @param pixel_clk desired pixel clock frequency in Hz
+ * @param csi csi 0 or csi 1
+ */
+void _ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
+ uint32_t g_value, uint32_t b_value, uint32_t pix_clk, uint32_t csi)
+{
+ uint32_t temp;
+
+ temp = ipu_csi_read(ipu, csi, CSI_TST_CTRL);
+
+ if (active == false) {
+ temp &= ~CSI_TEST_GEN_MODE_EN;
+ ipu_csi_write(ipu, csi, temp, CSI_TST_CTRL);
+ } else {
+ /* Set sensb_mclk div_ratio*/
+ _ipu_csi_mclk_set(ipu, pix_clk, csi);
+
+ temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
+ CSI_TEST_GEN_B_MASK);
+ temp |= CSI_TEST_GEN_MODE_EN;
+ temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
+ (g_value << CSI_TEST_GEN_G_SHIFT) |
+ (b_value << CSI_TEST_GEN_B_SHIFT);
+ ipu_csi_write(ipu, csi, temp, CSI_TST_CTRL);
+ }
+}
+
+/*!
+ * _ipu_csi_ccir_err_detection_en
+ * Enable error detection and correction for
+ * CCIR interlaced mode with protection bit.
+ *
+ * @param ipu ipu handler
+ * @param csi csi 0 or csi 1
+ */
+void _ipu_csi_ccir_err_detection_enable(struct ipu_soc *ipu, uint32_t csi)
+{
+ uint32_t temp;
+
+ temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
+ temp |= CSI_CCIR_ERR_DET_EN;
+ ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
+
+}
+
+/*!
+ * _ipu_csi_ccir_err_detection_disable
+ * Disable error detection and correction for
+ * CCIR interlaced mode with protection bit.
+ *
+ * @param ipu ipu handler
+ * @param csi csi 0 or csi 1
+ */
+void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi)
+{
+ uint32_t temp;
+
+ temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
+ temp &= ~CSI_CCIR_ERR_DET_EN;
+ ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
+
+}
+
+/*!
+ * _ipu_csi_set_mipi_di
+ *
+ * @param ipu ipu handler
+ * @param num MIPI data identifier 0-3 handled by CSI
+ * @param di_val data identifier value
+ * @param csi csi 0 or csi 1
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uint32_t csi)
+{
+ uint32_t temp;
+ int retval = 0;
+
+ if (di_val > 0xFFL) {
+ retval = -EINVAL;
+ goto err;
+ }
+
+ temp = ipu_csi_read(ipu, csi, CSI_MIPI_DI);
+
+ switch (num) {
+ case IPU_CSI_MIPI_DI0:
+ temp &= ~CSI_MIPI_DI0_MASK;
+ temp |= (di_val << CSI_MIPI_DI0_SHIFT);
+ ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
+ break;
+ case IPU_CSI_MIPI_DI1:
+ temp &= ~CSI_MIPI_DI1_MASK;
+ temp |= (di_val << CSI_MIPI_DI1_SHIFT);
+ ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
+ break;
+ case IPU_CSI_MIPI_DI2:
+ temp &= ~CSI_MIPI_DI2_MASK;
+ temp |= (di_val << CSI_MIPI_DI2_SHIFT);
+ ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
+ break;
+ case IPU_CSI_MIPI_DI3:
+ temp &= ~CSI_MIPI_DI3_MASK;
+ temp |= (di_val << CSI_MIPI_DI3_SHIFT);
+ ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
+ break;
+ default:
+ retval = -EINVAL;
+ }
+
+err:
+ return retval;
+}
+
+/*!
+ * _ipu_csi_set_skip_isp
+ *
+ * @param ipu ipu handler
+ * @param skip select frames to be skipped and set the
+ * correspond bits to 1
+ * @param max_ratio number of frames in a skipping set and the
+ * maximum value of max_ratio is 5
+ * @param csi csi 0 or csi 1
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int _ipu_csi_set_skip_isp(struct ipu_soc *ipu, uint32_t skip, uint32_t max_ratio, uint32_t csi)
+{
+ uint32_t temp;
+ int retval = 0;
+
+ if (max_ratio > 5) {
+ retval = -EINVAL;
+ goto err;
+ }
+
+ temp = ipu_csi_read(ipu, csi, CSI_SKIP);
+ temp &= ~(CSI_MAX_RATIO_SKIP_ISP_MASK | CSI_SKIP_ISP_MASK);
+ temp |= (max_ratio << CSI_MAX_RATIO_SKIP_ISP_SHIFT) |
+ (skip << CSI_SKIP_ISP_SHIFT);
+ ipu_csi_write(ipu, csi, temp, CSI_SKIP);
+
+err:
+ return retval;
+}
+
+/*!
+ * _ipu_csi_set_skip_smfc
+ *
+ * @param ipu ipu handler
+ * @param skip select frames to be skipped and set the
+ * correspond bits to 1
+ * @param max_ratio number of frames in a skipping set and the
+ * maximum value of max_ratio is 5
+ * @param id csi to smfc skipping id
+ * @param csi csi 0 or csi 1
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int _ipu_csi_set_skip_smfc(struct ipu_soc *ipu, uint32_t skip,
+ uint32_t max_ratio, uint32_t id, uint32_t csi)
+{
+ uint32_t temp;
+ int retval = 0;
+
+ if (max_ratio > 5 || id > 3) {
+ retval = -EINVAL;
+ goto err;
+ }
+
+ temp = ipu_csi_read(ipu, csi, CSI_SKIP);
+ temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
+ CSI_SKIP_SMFC_MASK);
+ temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
+ (id << CSI_ID_2_SKIP_SHIFT) |
+ (skip << CSI_SKIP_SMFC_SHIFT);
+ ipu_csi_write(ipu, csi, temp, CSI_SKIP);
+
+err:
+ return retval;
+}
+
+/*!
+ * _ipu_smfc_init
+ * Map CSI frames to IDMAC channels.
+ *
+ * @param ipu ipu handler
+ * @param channel IDMAC channel 0-3
+ * @param mipi_id mipi id number 0-3
+ * @param csi csi0 or csi1
+ */
+void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id, uint32_t csi)
+{
+ uint32_t temp;
+
+ temp = ipu_smfc_read(ipu, SMFC_MAP);
+
+ switch (channel) {
+ case CSI_MEM0:
+ temp &= ~SMFC_MAP_CH0_MASK;
+ temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH0_SHIFT;
+ break;
+ case CSI_MEM1:
+ temp &= ~SMFC_MAP_CH1_MASK;
+ temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH1_SHIFT;
+ break;
+ case CSI_MEM2:
+ temp &= ~SMFC_MAP_CH2_MASK;
+ temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH2_SHIFT;
+ break;
+ case CSI_MEM3:
+ temp &= ~SMFC_MAP_CH3_MASK;
+ temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH3_SHIFT;
+ break;
+ default:
+ return;
+ }
+
+ ipu_smfc_write(ipu, temp, SMFC_MAP);
+}
+
+/*!
+ * _ipu_smfc_set_wmc
+ * Caution: The number of required channels, the enabled channels
+ * and the FIFO size per channel are configured restrictedly.
+ *
+ * @param ipu ipu handler
+ * @param channel IDMAC channel 0-3
+ * @param set set 1 or clear 0
+ * @param level water mark level when FIFO is on the
+ * relative size
+ */
+void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uint32_t level)
+{
+ uint32_t temp;
+
+ temp = ipu_smfc_read(ipu, SMFC_WMC);
+
+ switch (channel) {
+ case CSI_MEM0:
+ if (set == true) {
+ temp &= ~SMFC_WM0_SET_MASK;
+ temp |= level << SMFC_WM0_SET_SHIFT;
+ } else {
+ temp &= ~SMFC_WM0_CLR_MASK;
+ temp |= level << SMFC_WM0_CLR_SHIFT;
+ }
+ break;
+ case CSI_MEM1:
+ if (set == true) {
+ temp &= ~SMFC_WM1_SET_MASK;
+ temp |= level << SMFC_WM1_SET_SHIFT;
+ } else {
+ temp &= ~SMFC_WM1_CLR_MASK;
+ temp |= level << SMFC_WM1_CLR_SHIFT;
+ }
+ break;
+ case CSI_MEM2:
+ if (set == true) {
+ temp &= ~SMFC_WM2_SET_MASK;
+ temp |= level << SMFC_WM2_SET_SHIFT;
+ } else {
+ temp &= ~SMFC_WM2_CLR_MASK;
+ temp |= level << SMFC_WM2_CLR_SHIFT;
+ }
+ break;
+ case CSI_MEM3:
+ if (set == true) {
+ temp &= ~SMFC_WM3_SET_MASK;
+ temp |= level << SMFC_WM3_SET_SHIFT;
+ } else {
+ temp &= ~SMFC_WM3_CLR_MASK;
+ temp |= level << SMFC_WM3_CLR_SHIFT;
+ }
+ break;
+ default:
+ return;
+ }
+
+ ipu_smfc_write(ipu, temp, SMFC_WMC);
+}
+
+/*!
+ * _ipu_smfc_set_burst_size
+ *
+ * @param ipu ipu handler
+ * @param channel IDMAC channel 0-3
+ * @param bs burst size of IDMAC channel,
+ * the value programmed here shoud be BURST_SIZE-1
+ */
+void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs)
+{
+ uint32_t temp;
+
+ temp = ipu_smfc_read(ipu, SMFC_BS);
+
+ switch (channel) {
+ case CSI_MEM0:
+ temp &= ~SMFC_BS0_MASK;
+ temp |= bs << SMFC_BS0_SHIFT;
+ break;
+ case CSI_MEM1:
+ temp &= ~SMFC_BS1_MASK;
+ temp |= bs << SMFC_BS1_SHIFT;
+ break;
+ case CSI_MEM2:
+ temp &= ~SMFC_BS2_MASK;
+ temp |= bs << SMFC_BS2_SHIFT;
+ break;
+ case CSI_MEM3:
+ temp &= ~SMFC_BS3_MASK;
+ temp |= bs << SMFC_BS3_SHIFT;
+ break;
+ default:
+ return;
+ }
+
+ ipu_smfc_write(ipu, temp, SMFC_BS);
+}
+
+/*!
+ * _ipu_csi_init
+ *
+ * @param ipu ipu handler
+ * @param channel IDMAC channel
+ * @param csi csi 0 or csi 1
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int _ipu_csi_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t csi)
+{
+ uint32_t csi_sens_conf, csi_dest;
+ int retval = 0;
+
+ switch (channel) {
+ case CSI_MEM0:
+ case CSI_MEM1:
+ case CSI_MEM2:
+ case CSI_MEM3:
+ csi_dest = CSI_DATA_DEST_IDMAC;
+ break;
+ case CSI_PRP_ENC_MEM:
+ case CSI_PRP_VF_MEM:
+ csi_dest = CSI_DATA_DEST_IC;
+ break;
+ default:
+ retval = -EINVAL;
+ goto err;
+ }
+
+ csi_sens_conf = ipu_csi_read(ipu, csi, CSI_SENS_CONF);
+ csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
+ ipu_csi_write(ipu, csi, csi_sens_conf | (csi_dest <<
+ CSI_SENS_CONF_DATA_DEST_SHIFT), CSI_SENS_CONF);
+err:
+ return retval;
+}
+
+/*!
+ * csi_irq_handler
+ *
+ * @param irq interrupt id
+ * @param dev_id pointer to ipu handler
+ *
+ * @return Returns if irq is handled
+ */
+static irqreturn_t csi_irq_handler(int irq, void *dev_id)
+{
+ struct ipu_soc *ipu = dev_id;
+ struct completion *comp = &ipu->csi_comp;
+
+ complete(comp);
+ return IRQ_HANDLED;
+}
+
+/*!
+ * _ipu_csi_wait4eof
+ *
+ * @param ipu ipu handler
+ * @param channel IDMAC channel
+ *
+ */
+void _ipu_csi_wait4eof(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ int ret;
+ int irq = 0;
+
+ if (channel == CSI_MEM0)
+ irq = IPU_IRQ_CSI0_OUT_EOF;
+ else if (channel == CSI_MEM1)
+ irq = IPU_IRQ_CSI1_OUT_EOF;
+ else if (channel == CSI_MEM2)
+ irq = IPU_IRQ_CSI2_OUT_EOF;
+ else if (channel == CSI_MEM3)
+ irq = IPU_IRQ_CSI3_OUT_EOF;
+ else if (channel == CSI_PRP_ENC_MEM)
+ irq = IPU_IRQ_PRP_ENC_OUT_EOF;
+ else if (channel == CSI_PRP_VF_MEM)
+ irq = IPU_IRQ_PRP_VF_OUT_EOF;
+ else{
+ dev_err(ipu->dev, "Not a CSI channel\n");
+ return;
+ }
+
+ init_completion(&ipu->csi_comp);
+ ret = ipu_request_irq(ipu, irq, csi_irq_handler, 0, NULL, ipu);
+ if (ret < 0) {
+ dev_err(ipu->dev, "CSI irq %d in use\n", irq);
+ return;
+ }
+ ret = wait_for_completion_timeout(&ipu->csi_comp, msecs_to_jiffies(500));
+ ipu_free_irq(ipu, irq, ipu);
+ dev_dbg(ipu->dev, "CSI stop timeout - %d * 10ms\n", 5 - ret);
+}
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
new file mode 100644
index 000000000000..c5b82f78421f
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -0,0 +1,3494 @@
+/*
+ * Copyright 2005-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 ipu_common.c
+ *
+ * @brief This file contains the IPU driver common API functions.
+ *
+ * @ingroup IPU
+ */
+#include <linux/busfreq-imx.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ipu-v3.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/cacheflush.h>
+
+#include "ipu_param_mem.h"
+#include "ipu_regs.h"
+
+static struct ipu_soc ipu_array[MXC_IPU_MAX_NUM];
+
+/* Static functions */
+static irqreturn_t ipu_sync_irq_handler(int irq, void *desc);
+static irqreturn_t ipu_err_irq_handler(int irq, void *desc);
+
+static inline uint32_t channel_2_dma(ipu_channel_t ch, ipu_buffer_t type)
+{
+ return ((uint32_t) ch >> (6 * type)) & 0x3F;
+};
+
+static inline int _ipu_is_ic_chan(uint32_t dma_chan)
+{
+ return (((dma_chan >= 11) && (dma_chan <= 22) && (dma_chan != 17) &&
+ (dma_chan != 18)));
+}
+
+static inline int _ipu_is_vdi_out_chan(uint32_t dma_chan)
+{
+ return (dma_chan == 5);
+}
+
+static inline int _ipu_is_ic_graphic_chan(uint32_t dma_chan)
+{
+ return (dma_chan == 14 || dma_chan == 15);
+}
+
+/* Either DP BG or DP FG can be graphic window */
+static inline int _ipu_is_dp_graphic_chan(uint32_t dma_chan)
+{
+ return (dma_chan == 23 || dma_chan == 27);
+}
+
+static inline int _ipu_is_irt_chan(uint32_t dma_chan)
+{
+ return ((dma_chan >= 45) && (dma_chan <= 50));
+}
+
+static inline int _ipu_is_dmfc_chan(uint32_t dma_chan)
+{
+ return ((dma_chan >= 23) && (dma_chan <= 29));
+}
+
+static inline int _ipu_is_trb_chan(struct ipu_soc *ipu, uint32_t dma_chan)
+{
+ return (((dma_chan == 8) || (dma_chan == 9) ||
+ (dma_chan == 10) || (dma_chan == 13) ||
+ (dma_chan == 21) || (dma_chan == 23) ||
+ (dma_chan == 27) || (dma_chan == 28)) &&
+ (ipu->devtype >= IPUv3EX));
+}
+
+/*
+ * We usually use IDMAC 23 as full plane and IDMAC 27 as partial
+ * plane.
+ * IDMAC 23/24/28/41 can drive a display respectively - primary
+ * IDMAC 27 depends on IDMAC 23 - nonprimary
+ */
+static inline int _ipu_is_primary_disp_chan(uint32_t dma_chan)
+{
+ return ((dma_chan == 23) || (dma_chan == 24) ||
+ (dma_chan == 28) || (dma_chan == 41));
+}
+
+static inline int _ipu_is_sync_irq(uint32_t irq)
+{
+ /* sync interrupt register number */
+ int reg_num = irq / 32 + 1;
+
+ return ((reg_num == 1) || (reg_num == 2) || (reg_num == 3) ||
+ (reg_num == 4) || (reg_num == 7) || (reg_num == 8) ||
+ (reg_num == 11) || (reg_num == 12) || (reg_num == 13) ||
+ (reg_num == 14) || (reg_num == 15));
+}
+
+static inline uint32_t tri_cur_buf_mask(uint32_t dma_chan)
+{
+ uint32_t mask = 1UL << ((dma_chan * 2) & 0x1F);
+
+ return mask * 3;
+}
+
+static inline uint32_t tri_cur_buf_shift(uint32_t dma_chan)
+{
+ uint32_t mask = 1UL << ((dma_chan * 2) & 0x1F);
+
+ return ffs(mask) - 1;
+}
+
+#define idma_is_valid(ch) ((ch) != NO_DMA)
+#define idma_mask(ch) (idma_is_valid(ch) ? (1UL << ((ch) & 0x1F)) : 0)
+
+static inline bool idma_is_set(struct ipu_soc *ipu, uint32_t reg, uint32_t dma)
+{
+ return !!(ipu_idmac_read(ipu, reg) & idma_mask(dma));
+}
+
+static int ipu_clk_setup_enable(struct ipu_soc *ipu)
+{
+ char pixel_clk[11];
+ char pixel_clk_sel[15];
+ char pixel_clk_div[15];
+ char pixel_clk_parent0[5];
+ char pixel_clk_parent1[9];
+ char *pixel_clk_parents[2];
+ char di_clk[4];
+ char di_clk_sel[8];
+ struct clk *clk;
+ unsigned int di;
+ unsigned int ipu_id; /* for clk naming */
+ int ret;
+
+ dev_dbg(ipu->dev, "ipu_clk = %lu\n", clk_get_rate(ipu->ipu_clk));
+
+ ipu_id = ipu->id + 1;
+
+ pixel_clk_parents[0] = pixel_clk_parent0;
+ pixel_clk_parents[1] = pixel_clk_parent1;
+
+ for (di = 0; di < 2; di++) {
+ snprintf(pixel_clk_sel, sizeof(pixel_clk_sel),
+ "ipu%u_pclk%u_sel", ipu_id, di);
+ snprintf(pixel_clk_parent0, sizeof(pixel_clk_parent0),
+ "ipu%u", ipu_id);
+ snprintf(pixel_clk_parent1, sizeof(pixel_clk_parent1),
+ "ipu%u_di%u", ipu_id, di);
+ clk = clk_register_mux_pix_clk(ipu->dev, pixel_clk_sel,
+ (const char **)pixel_clk_parents,
+ ARRAY_SIZE(pixel_clk_parents),
+ 0, ipu->id, di, 0);
+ if (IS_ERR(clk)) {
+ dev_err(ipu->dev, "di%u mux clk register failed\n", di);
+ return PTR_ERR(clk);
+ }
+ ipu->pixel_clk_sel[di] = clk;
+
+ snprintf(pixel_clk_div, sizeof(pixel_clk_div),
+ "ipu%u_pclk%u_div", ipu_id, di);
+ clk = clk_register_div_pix_clk(ipu->dev, pixel_clk_div,
+ pixel_clk_sel, 0, ipu->id, di, 0);
+ if (IS_ERR(clk)) {
+ dev_err(ipu->dev, "di%u div clk register failed\n", di);
+ return PTR_ERR(clk);
+ }
+
+ snprintf(pixel_clk, sizeof(pixel_clk),
+ "ipu%u_pclk%u", ipu_id, di);
+ ipu->pixel_clk[di] = clk_register_gate_pix_clk(ipu->dev,
+ pixel_clk, pixel_clk_div,
+ CLK_SET_RATE_PARENT, ipu->id, di, 0);
+ if (IS_ERR(ipu->pixel_clk[di])) {
+ dev_err(ipu->dev,
+ "di%u gate clk register failed\n", di);
+ return PTR_ERR(ipu->pixel_clk[di]);
+ }
+
+ ret = clk_set_parent(ipu->pixel_clk_sel[di], ipu->ipu_clk);
+ if (ret) {
+ dev_err(ipu->dev, "pixel clk set parent failed\n");
+ return ret;
+ }
+
+ snprintf(di_clk, sizeof(di_clk), "di%u", di);
+ ipu->di_clk[di] = devm_clk_get(ipu->dev, di_clk);
+ if (IS_ERR(ipu->di_clk[di])) {
+ dev_err(ipu->dev, "di%u clk get failed\n", di);
+ return PTR_ERR(ipu->di_clk[di]);
+ }
+
+ snprintf(di_clk_sel, sizeof(di_clk_sel), "di%u_sel", di);
+ ipu->di_clk_sel[di] = devm_clk_get(ipu->dev, di_clk_sel);
+ if (IS_ERR(ipu->di_clk_sel[di])) {
+ dev_err(ipu->dev, "di%u sel clk get failed\n", di);
+ return PTR_ERR(ipu->di_clk_sel[di]);
+ }
+ }
+
+ return 0;
+}
+
+static int ipu_mem_reset(struct ipu_soc *ipu)
+{
+ int timeout = 1000;
+
+ ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
+
+ while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
+ if (!timeout--)
+ return -ETIME;
+ msleep(1);
+ }
+
+ return 0;
+}
+
+struct ipu_soc *ipu_get_soc(int id)
+{
+ if (id >= MXC_IPU_MAX_NUM)
+ return ERR_PTR(-ENODEV);
+ else if (!ipu_array[id].online)
+ return ERR_PTR(-ENODEV);
+ else
+ return &(ipu_array[id]);
+}
+EXPORT_SYMBOL_GPL(ipu_get_soc);
+
+void _ipu_get(struct ipu_soc *ipu)
+{
+ int ret;
+
+ ret = clk_enable(ipu->ipu_clk);
+ if (ret < 0)
+ BUG();
+}
+
+void _ipu_put(struct ipu_soc *ipu)
+{
+ clk_disable(ipu->ipu_clk);
+}
+
+void ipu_disable_hsp_clk(struct ipu_soc *ipu)
+{
+ _ipu_put(ipu);
+}
+EXPORT_SYMBOL(ipu_disable_hsp_clk);
+
+struct ipu_devtype {
+ const char *name;
+ unsigned long cm_ofs;
+ unsigned long idmac_ofs;
+ unsigned long ic_ofs;
+ unsigned long csi0_ofs;
+ unsigned long csi1_ofs;
+ unsigned long di0_ofs;
+ unsigned long di1_ofs;
+ unsigned long smfc_ofs;
+ unsigned long dc_ofs;
+ unsigned long dmfc_ofs;
+ unsigned long vdi_ofs;
+ unsigned long cpmem_ofs;
+ unsigned long srm_ofs;
+ unsigned long tpm_ofs;
+ unsigned long dc_tmpl_ofs;
+ enum ipuv3_type type;
+ bool idmac_used_bufs_present;
+};
+
+struct ipu_platform_type {
+ struct ipu_devtype devtype;
+ unsigned int ch0123_axi;
+ unsigned int ch23_axi;
+ unsigned int ch27_axi;
+ unsigned int ch28_axi;
+ unsigned int normal_axi;
+ bool smfc_idmac_12bit_3planar_bs_fixup; /* workaround little stripes */
+ bool idmac_used_bufs_en_r;
+ bool idmac_used_bufs_en_w;
+ unsigned int idmac_used_bufs_max_r;
+ unsigned int idmac_used_bufs_max_w;
+};
+
+static struct ipu_platform_type ipu_type_imx51 = {
+ .devtype = {
+ .name = "IPUv3EX",
+ .cm_ofs = 0x1E000000,
+ .idmac_ofs = 0x1E008000,
+ .ic_ofs = 0x1E020000,
+ .csi0_ofs = 0x1E030000,
+ .csi1_ofs = 0x1E038000,
+ .di0_ofs = 0x1E040000,
+ .di1_ofs = 0x1E048000,
+ .smfc_ofs = 0x1E050000,
+ .dc_ofs = 0x1E058000,
+ .dmfc_ofs = 0x1E060000,
+ .vdi_ofs = 0x1E068000,
+ .cpmem_ofs = 0x1F000000,
+ .srm_ofs = 0x1F040000,
+ .tpm_ofs = 0x1F060000,
+ .dc_tmpl_ofs = 0x1F080000,
+ .type = IPUv3EX,
+ .idmac_used_bufs_present = false,
+ },
+ .ch0123_axi = 1,
+ .ch23_axi = 1,
+ .ch23_axi = 1,
+ .ch27_axi = 1,
+ .ch28_axi = 1,
+ .normal_axi = 0,
+ .smfc_idmac_12bit_3planar_bs_fixup = false,
+};
+
+static struct ipu_platform_type ipu_type_imx53 = {
+ .devtype = {
+ .name = "IPUv3M",
+ .cm_ofs = 0x06000000,
+ .idmac_ofs = 0x06008000,
+ .ic_ofs = 0x06020000,
+ .csi0_ofs = 0x06030000,
+ .csi1_ofs = 0x06038000,
+ .di0_ofs = 0x06040000,
+ .di1_ofs = 0x06048000,
+ .smfc_ofs = 0x06050000,
+ .dc_ofs = 0x06058000,
+ .dmfc_ofs = 0x06060000,
+ .vdi_ofs = 0x06068000,
+ .cpmem_ofs = 0x07000000,
+ .srm_ofs = 0x07040000,
+ .tpm_ofs = 0x07060000,
+ .dc_tmpl_ofs = 0x07080000,
+ .type = IPUv3M,
+ .idmac_used_bufs_present = true,
+ },
+ .ch0123_axi = 1,
+ .ch23_axi = 1,
+ .ch27_axi = 1,
+ .ch28_axi = 1,
+ .normal_axi = 0,
+ .idmac_used_bufs_en_r = false,
+ .idmac_used_bufs_en_w = false,
+ .smfc_idmac_12bit_3planar_bs_fixup = false,
+};
+
+static struct ipu_platform_type ipu_type_imx6q = {
+ .devtype = {
+ .name = "IPUv3H",
+ .cm_ofs = 0x00200000,
+ .idmac_ofs = 0x00208000,
+ .ic_ofs = 0x00220000,
+ .csi0_ofs = 0x00230000,
+ .csi1_ofs = 0x00238000,
+ .di0_ofs = 0x00240000,
+ .di1_ofs = 0x00248000,
+ .smfc_ofs = 0x00250000,
+ .dc_ofs = 0x00258000,
+ .dmfc_ofs = 0x00260000,
+ .vdi_ofs = 0x00268000,
+ .cpmem_ofs = 0x00300000,
+ .srm_ofs = 0x00340000,
+ .tpm_ofs = 0x00360000,
+ .dc_tmpl_ofs = 0x00380000,
+ .type = IPUv3H,
+ .idmac_used_bufs_present = true,
+ },
+ .ch0123_axi = 0,
+ .ch23_axi = 0,
+ .ch27_axi = 0,
+ .ch28_axi = 0,
+ .normal_axi = 1,
+ .idmac_used_bufs_en_r = false,
+ .idmac_used_bufs_en_w = false,
+ .smfc_idmac_12bit_3planar_bs_fixup = false,
+};
+
+static struct ipu_platform_type ipu_type_imx6qp = {
+ .devtype = {
+ .name = "IPUv3H",
+ .cm_ofs = 0x00200000,
+ .idmac_ofs = 0x00208000,
+ .ic_ofs = 0x00220000,
+ .csi0_ofs = 0x00230000,
+ .csi1_ofs = 0x00238000,
+ .di0_ofs = 0x00240000,
+ .di1_ofs = 0x00248000,
+ .smfc_ofs = 0x00250000,
+ .dc_ofs = 0x00258000,
+ .dmfc_ofs = 0x00260000,
+ .vdi_ofs = 0x00268000,
+ .cpmem_ofs = 0x00300000,
+ .srm_ofs = 0x00340000,
+ .tpm_ofs = 0x00360000,
+ .dc_tmpl_ofs = 0x00380000,
+ .type = IPUv3H,
+ .idmac_used_bufs_present = true,
+ },
+ .ch0123_axi = 0,
+ .ch23_axi = 0,
+ .ch27_axi = 2,
+ .ch28_axi = 3,
+ .normal_axi = 1,
+ .idmac_used_bufs_en_r = true,
+ .idmac_used_bufs_en_w = true,
+ .idmac_used_bufs_max_r = 0x3,
+ .idmac_used_bufs_max_w = 0x3,
+ .smfc_idmac_12bit_3planar_bs_fixup = true,
+ };
+
+static const struct of_device_id imx_ipuv3_dt_ids[] = {
+ { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
+ { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
+ { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
+ { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6qp, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_ipuv3_dt_ids);
+
+/*!
+ * This function is called by the driver framework to initialize the IPU
+ * hardware.
+ *
+ * @param dev The device structure for the IPU passed in by the
+ * driver framework.
+ *
+ * @return Returns 0 on success or negative error code on error
+ */
+static int ipu_probe(struct platform_device *pdev)
+{
+ struct ipu_soc *ipu;
+ struct resource *res;
+ unsigned long ipu_base;
+ const struct of_device_id *of_id =
+ of_match_device(imx_ipuv3_dt_ids, &pdev->dev);
+ const struct ipu_platform_type *iputype = of_id->data;
+ const struct ipu_devtype *devtype = &iputype->devtype;
+ int ret = 0, id;
+ u32 bypass_reset, reg;
+
+ dev_dbg(&pdev->dev, "<%s>\n", __func__);
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "bypass_reset", &bypass_reset);
+ if (ret < 0) {
+ dev_dbg(&pdev->dev, "can not get bypass_reset\n");
+ return ret;
+ }
+
+ id = of_alias_get_id(pdev->dev.of_node, "ipu");
+ if (id < 0) {
+ dev_dbg(&pdev->dev, "can not get alias id\n");
+ return id;
+ }
+
+ ipu = &ipu_array[id];
+ memset(ipu, 0, sizeof(struct ipu_soc));
+ ipu->bypass_reset = (bool)bypass_reset;
+ ipu->dev = &pdev->dev;
+ ipu->id = id;
+ ipu->devtype = devtype->type;
+ ipu->ch0123_axi = iputype->ch0123_axi;
+ ipu->ch23_axi = iputype->ch23_axi;
+ ipu->ch27_axi = iputype->ch27_axi;
+ ipu->ch28_axi = iputype->ch28_axi;
+ ipu->normal_axi = iputype->normal_axi;
+ ipu->smfc_idmac_12bit_3planar_bs_fixup =
+ iputype->smfc_idmac_12bit_3planar_bs_fixup;
+ spin_lock_init(&ipu->int_reg_spin_lock);
+ spin_lock_init(&ipu->rdy_reg_spin_lock);
+ mutex_init(&ipu->mutex_lock);
+
+ dev_dbg(&pdev->dev, "revision is %s\n", devtype->name);
+
+ ipu->irq_sync = platform_get_irq(pdev, 0);
+ ipu->irq_err = platform_get_irq(pdev, 1);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res || ipu->irq_sync < 0 || ipu->irq_err < 0) {
+ dev_err(&pdev->dev, "can't get device resources\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
+
+ ret = devm_request_irq(&pdev->dev, ipu->irq_sync,
+ ipu_sync_irq_handler, 0, pdev->name, ipu);
+ if (ret) {
+ dev_err(ipu->dev, "request SYNC interrupt failed\n");
+ return ret;
+ }
+ ret = devm_request_irq(&pdev->dev, ipu->irq_err,
+ ipu_err_irq_handler, 0, pdev->name, ipu);
+ if (ret) {
+ dev_err(ipu->dev, "request ERR interrupt failed\n");
+ return ret;
+ }
+
+ ipu_base = res->start;
+
+ ipu->cm_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->cm_ofs, PAGE_SIZE);
+ ipu->ic_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->ic_ofs, PAGE_SIZE);
+ ipu->idmac_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->idmac_ofs, PAGE_SIZE);
+ /* DP Registers are accessed thru the SRM */
+ ipu->dp_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->srm_ofs, PAGE_SIZE);
+ ipu->dc_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->dc_ofs, PAGE_SIZE);
+ ipu->dmfc_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->dmfc_ofs, PAGE_SIZE);
+ ipu->di_reg[0] = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->di0_ofs, PAGE_SIZE);
+ ipu->di_reg[1] = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->di1_ofs, PAGE_SIZE);
+ ipu->smfc_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->smfc_ofs, PAGE_SIZE);
+ ipu->csi_reg[0] = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->csi0_ofs, PAGE_SIZE);
+ ipu->csi_reg[1] = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->csi1_ofs, PAGE_SIZE);
+ ipu->cpmem_base = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->cpmem_ofs, SZ_128K);
+ ipu->tpmem_base = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->tpm_ofs, SZ_64K);
+ ipu->dc_tmpl_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->dc_tmpl_ofs, SZ_128K);
+ ipu->vdi_reg = devm_ioremap(&pdev->dev,
+ ipu_base + devtype->vdi_ofs, PAGE_SIZE);
+ if (!ipu->cm_reg || !ipu->ic_reg || !ipu->idmac_reg ||
+ !ipu->dp_reg || !ipu->dc_reg || !ipu->dmfc_reg ||
+ !ipu->di_reg[0] || !ipu->di_reg[1] || !ipu->smfc_reg ||
+ !ipu->csi_reg[0] || !ipu->csi_reg[1] || !ipu->cpmem_base ||
+ !ipu->tpmem_base || !ipu->dc_tmpl_reg || !ipu->vdi_reg)
+ return -ENOMEM;
+
+ dev_dbg(ipu->dev, "IPU CM Regs = %p\n", ipu->cm_reg);
+ dev_dbg(ipu->dev, "IPU IC Regs = %p\n", ipu->ic_reg);
+ dev_dbg(ipu->dev, "IPU IDMAC Regs = %p\n", ipu->idmac_reg);
+ dev_dbg(ipu->dev, "IPU DP Regs = %p\n", ipu->dp_reg);
+ dev_dbg(ipu->dev, "IPU DC Regs = %p\n", ipu->dc_reg);
+ dev_dbg(ipu->dev, "IPU DMFC Regs = %p\n", ipu->dmfc_reg);
+ dev_dbg(ipu->dev, "IPU DI0 Regs = %p\n", ipu->di_reg[0]);
+ dev_dbg(ipu->dev, "IPU DI1 Regs = %p\n", ipu->di_reg[1]);
+ dev_dbg(ipu->dev, "IPU SMFC Regs = %p\n", ipu->smfc_reg);
+ dev_dbg(ipu->dev, "IPU CSI0 Regs = %p\n", ipu->csi_reg[0]);
+ dev_dbg(ipu->dev, "IPU CSI1 Regs = %p\n", ipu->csi_reg[1]);
+ dev_dbg(ipu->dev, "IPU CPMem = %p\n", ipu->cpmem_base);
+ dev_dbg(ipu->dev, "IPU TPMem = %p\n", ipu->tpmem_base);
+ dev_dbg(ipu->dev, "IPU DC Template Mem = %p\n", ipu->dc_tmpl_reg);
+ dev_dbg(ipu->dev, "IPU VDI Regs = %p\n", ipu->vdi_reg);
+
+ ipu->ipu_clk = devm_clk_get(ipu->dev, "bus");
+ if (IS_ERR(ipu->ipu_clk)) {
+ dev_err(ipu->dev, "clk_get ipu failed");
+ return PTR_ERR(ipu->ipu_clk);
+ }
+
+ /* ipu_clk is always prepared */
+ ret = clk_prepare_enable(ipu->ipu_clk);
+ if (ret < 0) {
+ dev_err(ipu->dev, "ipu clk enable failed\n");
+ return ret;
+ }
+
+ ipu->prg_clk = devm_clk_get(ipu->dev, "prg");
+ if (IS_ERR(ipu->prg_clk))
+ ipu->prg_clk = NULL;
+
+ ipu->online = true;
+
+ platform_set_drvdata(pdev, ipu);
+
+ if (!bypass_reset) {
+ ret = device_reset(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to reset: %d\n", ret);
+ return ret;
+ }
+
+ ipu_mem_reset(ipu);
+
+ ipu_disp_init(ipu);
+
+ /* Set MCU_T to divide MCU access window into 2 */
+ ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
+ IPU_DISP_GEN);
+ }
+
+ /* setup ipu clk tree after ipu reset */
+ ret = ipu_clk_setup_enable(ipu);
+ if (ret < 0) {
+ dev_err(ipu->dev, "ipu clk setup failed\n");
+ ipu->online = false;
+ return ret;
+ }
+
+ if (devtype->idmac_used_bufs_present) {
+ reg = ipu_idmac_read(ipu, IDMAC_CONF);
+ if (iputype->idmac_used_bufs_en_r)
+ reg |= IDMAC_CONF_USED_BUFS_EN_R;
+ else
+ reg &= ~IDMAC_CONF_USED_BUFS_EN_R;
+ if (iputype->idmac_used_bufs_en_w)
+ reg |= IDMAC_CONF_USED_BUFS_EN_W;
+ else
+ reg &= ~IDMAC_CONF_USED_BUFS_EN_W;
+
+ reg &= ~IDMAC_CONF_USED_BUFS_MAX_R_MASK;
+ reg |= (iputype->idmac_used_bufs_max_r <<
+ IDMAC_CONF_USED_BUFS_MAX_R_OFFSET);
+ reg &= ~IDMAC_CONF_USED_BUFS_MAX_W_MASK;
+ reg |= (iputype->idmac_used_bufs_max_w <<
+ IDMAC_CONF_USED_BUFS_MAX_W_OFFSET);
+ ipu_idmac_write(ipu, reg, IDMAC_CONF);
+ }
+
+ /* Set sync refresh channels and CSI->mem channel as high priority */
+ ipu_idmac_write(ipu, 0x18800003L, IDMAC_CHA_PRI(0));
+
+ /* Enable error interrupts by default */
+ ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(5));
+ ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(6));
+ ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(9));
+ ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(10));
+
+ if (!bypass_reset)
+ clk_disable(ipu->ipu_clk);
+
+ register_ipu_device(ipu, id);
+
+ pm_runtime_enable(&pdev->dev);
+
+ return ret;
+}
+
+int ipu_remove(struct platform_device *pdev)
+{
+ struct ipu_soc *ipu = platform_get_drvdata(pdev);
+
+ unregister_ipu_device(ipu, ipu->id);
+
+ clk_put(ipu->ipu_clk);
+
+ return 0;
+}
+
+void ipu_dump_registers(struct ipu_soc *ipu)
+{
+ dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n", ipu_cm_read(ipu, IPU_CONF));
+ dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n", ipu_idmac_read(ipu, IDMAC_CONF));
+ dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
+ ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
+ dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
+ ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
+ dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
+ ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
+ dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
+ ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
+ dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
+ ipu_idmac_read(ipu, IDMAC_BAND_EN(ipu->devtype, 0)));
+ dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
+ ipu_idmac_read(ipu, IDMAC_BAND_EN(ipu->devtype, 32)));
+ dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
+ ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
+ dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
+ ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
+ if (ipu->devtype >= IPUv3EX) {
+ dev_dbg(ipu->dev, "IPU_CHA_TRB_MODE_SEL0 = \t0x%08X\n",
+ ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(ipu->devtype, 0)));
+ dev_dbg(ipu->dev, "IPU_CHA_TRB_MODE_SEL1 = \t0x%08X\n",
+ ipu_cm_read(ipu,
+ IPU_CHA_TRB_MODE_SEL(ipu->devtype, 32)));
+ }
+ dev_dbg(ipu->dev, "DMFC_WR_CHAN = \t0x%08X\n",
+ ipu_dmfc_read(ipu, DMFC_WR_CHAN));
+ dev_dbg(ipu->dev, "DMFC_WR_CHAN_DEF = \t0x%08X\n",
+ ipu_dmfc_read(ipu, DMFC_WR_CHAN_DEF));
+ dev_dbg(ipu->dev, "DMFC_DP_CHAN = \t0x%08X\n",
+ ipu_dmfc_read(ipu, DMFC_DP_CHAN));
+ dev_dbg(ipu->dev, "DMFC_DP_CHAN_DEF = \t0x%08X\n",
+ ipu_dmfc_read(ipu, DMFC_DP_CHAN_DEF));
+ dev_dbg(ipu->dev, "DMFC_IC_CTRL = \t0x%08X\n",
+ ipu_dmfc_read(ipu, DMFC_IC_CTRL));
+ dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
+ ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
+ dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
+ ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
+ dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
+ ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
+ dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
+ ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
+ dev_dbg(ipu->dev, "IPU_VDIC_VDI_FSIZE = \t0x%08X\n",
+ ipu_vdi_read(ipu, VDI_FSIZE));
+ dev_dbg(ipu->dev, "IPU_VDIC_VDI_C = \t0x%08X\n",
+ ipu_vdi_read(ipu, VDI_C));
+ dev_dbg(ipu->dev, "IPU_IC_CONF = \t0x%08X\n",
+ ipu_ic_read(ipu, IC_CONF));
+}
+
+/*!
+ * This function is called to initialize a logical IPU channel.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID to init.
+ *
+ * @param params Input parameter containing union of channel
+ * initialization parameters.
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params)
+{
+ int ret = 0;
+ bool bad_pixfmt;
+ uint32_t ipu_conf, reg, in_g_pixel_fmt, sec_dma;
+
+ dev_dbg(ipu->dev, "init channel = %d\n", IPU_CHAN_ID(channel));
+
+ ret = pm_runtime_get_sync(ipu->dev);
+ if (ret < 0) {
+ dev_err(ipu->dev, "ch = %d, pm_runtime_get failed:%d!\n",
+ IPU_CHAN_ID(channel), ret);
+ dump_stack();
+ return ret;
+ }
+ /*
+ * Here, ret could be 1 if the device's runtime PM status was
+ * already 'active', so clear it to be 0.
+ */
+ ret = 0;
+
+ _ipu_get(ipu);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ /* Re-enable error interrupts every time a channel is initialized */
+ ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(5));
+ ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(6));
+ ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(9));
+ ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(10));
+
+ if (ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) {
+ dev_warn(ipu->dev, "Warning: channel already initialized %d\n",
+ IPU_CHAN_ID(channel));
+ }
+
+ ipu_conf = ipu_cm_read(ipu, IPU_CONF);
+
+ switch (channel) {
+ case CSI_MEM0:
+ case CSI_MEM1:
+ case CSI_MEM2:
+ case CSI_MEM3:
+ if (params->csi_mem.csi > 1) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (params->csi_mem.interlaced)
+ ipu->chan_is_interlaced[channel_2_dma(channel,
+ IPU_OUTPUT_BUFFER)] = true;
+ else
+ ipu->chan_is_interlaced[channel_2_dma(channel,
+ IPU_OUTPUT_BUFFER)] = false;
+
+ ipu->smfc_use_count++;
+ ipu->csi_channel[params->csi_mem.csi] = channel;
+
+ /*SMFC setting*/
+ if (params->csi_mem.mipi_en) {
+ ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_mem.csi));
+ _ipu_smfc_init(ipu, channel, params->csi_mem.mipi_vc,
+ params->csi_mem.csi);
+ _ipu_csi_set_mipi_di(ipu, params->csi_mem.mipi_vc,
+ params->csi_mem.mipi_id, params->csi_mem.csi);
+ } else {
+ ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_mem.csi));
+ _ipu_smfc_init(ipu, channel, 0, params->csi_mem.csi);
+ }
+
+ /*CSI data (include compander) dest*/
+ _ipu_csi_init(ipu, channel, params->csi_mem.csi);
+ break;
+ case CSI_PRP_ENC_MEM:
+ if (params->csi_prp_enc_mem.csi > 1) {
+ ret = -EINVAL;
+ goto err;
+ }
+ if ((ipu->using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM) ||
+ (ipu->using_ic_dirct_ch == MEM_VDI_MEM)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ ipu->using_ic_dirct_ch = CSI_PRP_ENC_MEM;
+
+ ipu->ic_use_count++;
+ ipu->csi_channel[params->csi_prp_enc_mem.csi] = channel;
+
+ if (params->csi_prp_enc_mem.mipi_en) {
+ ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_prp_enc_mem.csi));
+ _ipu_csi_set_mipi_di(ipu,
+ params->csi_prp_enc_mem.mipi_vc,
+ params->csi_prp_enc_mem.mipi_id,
+ params->csi_prp_enc_mem.csi);
+ } else
+ ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_prp_enc_mem.csi));
+
+ /*CSI0/1 feed into IC*/
+ ipu_conf &= ~IPU_CONF_IC_INPUT;
+ if (params->csi_prp_enc_mem.csi)
+ ipu_conf |= IPU_CONF_CSI_SEL;
+ else
+ ipu_conf &= ~IPU_CONF_CSI_SEL;
+
+ /*PRP skip buffer in memory, only valid when RWS_EN is true*/
+ reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, reg & ~FS_ENC_IN_VALID, IPU_FS_PROC_FLOW1);
+
+ /*CSI data (include compander) dest*/
+ _ipu_csi_init(ipu, channel, params->csi_prp_enc_mem.csi);
+ _ipu_ic_init_prpenc(ipu, params, true);
+ break;
+ case CSI_PRP_VF_MEM:
+ if (params->csi_prp_vf_mem.csi > 1) {
+ ret = -EINVAL;
+ goto err;
+ }
+ if ((ipu->using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM) ||
+ (ipu->using_ic_dirct_ch == MEM_VDI_MEM)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ ipu->using_ic_dirct_ch = CSI_PRP_VF_MEM;
+
+ ipu->ic_use_count++;
+ ipu->csi_channel[params->csi_prp_vf_mem.csi] = channel;
+
+ if (params->csi_prp_vf_mem.mipi_en) {
+ ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_prp_vf_mem.csi));
+ _ipu_csi_set_mipi_di(ipu,
+ params->csi_prp_vf_mem.mipi_vc,
+ params->csi_prp_vf_mem.mipi_id,
+ params->csi_prp_vf_mem.csi);
+ } else
+ ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_prp_vf_mem.csi));
+
+ /*CSI0/1 feed into IC*/
+ ipu_conf &= ~IPU_CONF_IC_INPUT;
+ if (params->csi_prp_vf_mem.csi)
+ ipu_conf |= IPU_CONF_CSI_SEL;
+ else
+ ipu_conf &= ~IPU_CONF_CSI_SEL;
+
+ /*PRP skip buffer in memory, only valid when RWS_EN is true*/
+ reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, reg & ~FS_VF_IN_VALID, IPU_FS_PROC_FLOW1);
+
+ /*CSI data (include compander) dest*/
+ _ipu_csi_init(ipu, channel, params->csi_prp_vf_mem.csi);
+ _ipu_ic_init_prpvf(ipu, params, true);
+ break;
+ case MEM_PRP_VF_MEM:
+ if (params->mem_prp_vf_mem.graphics_combine_en) {
+ sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
+ in_g_pixel_fmt = params->mem_prp_vf_mem.in_g_pixel_fmt;
+ bad_pixfmt =
+ _ipu_ch_param_bad_alpha_pos(in_g_pixel_fmt);
+
+ if (params->mem_prp_vf_mem.alpha_chan_en) {
+ if (bad_pixfmt) {
+ dev_err(ipu->dev, "bad pixel format "
+ "for graphics plane from "
+ "ch%d\n", sec_dma);
+ ret = -EINVAL;
+ goto err;
+ }
+ ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = true;
+ }
+ ipu->sec_chan_en[IPU_CHAN_ID(channel)] = true;
+ }
+
+ reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, reg | FS_VF_IN_VALID, IPU_FS_PROC_FLOW1);
+
+ _ipu_ic_init_prpvf(ipu, params, false);
+ ipu->ic_use_count++;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ if ((ipu->using_ic_dirct_ch == CSI_PRP_VF_MEM) ||
+ (ipu->using_ic_dirct_ch == MEM_VDI_MEM) ||
+ (ipu->using_ic_dirct_ch == CSI_PRP_ENC_MEM)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ ipu->using_ic_dirct_ch = MEM_VDI_PRP_VF_MEM;
+ ipu->ic_use_count++;
+ ipu->vdi_use_count++;
+ reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ reg &= ~FS_VDI_SRC_SEL_MASK;
+ ipu_cm_write(ipu, reg , IPU_FS_PROC_FLOW1);
+
+ if (params->mem_prp_vf_mem.graphics_combine_en)
+ ipu->sec_chan_en[IPU_CHAN_ID(channel)] = true;
+ _ipu_ic_init_prpvf(ipu, params, false);
+ _ipu_vdi_init(ipu, channel, params);
+ break;
+ case MEM_VDI_PRP_VF_MEM_P:
+ case MEM_VDI_PRP_VF_MEM_N:
+ case MEM_VDI_MEM_P:
+ case MEM_VDI_MEM_N:
+ _ipu_vdi_init(ipu, channel, params);
+ break;
+ case MEM_VDI_MEM:
+ if ((ipu->using_ic_dirct_ch == CSI_PRP_VF_MEM) ||
+ (ipu->using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM) ||
+ (ipu->using_ic_dirct_ch == CSI_PRP_ENC_MEM)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ ipu->using_ic_dirct_ch = MEM_VDI_MEM;
+ ipu->ic_use_count++;
+ ipu->vdi_use_count++;
+ _ipu_vdi_init(ipu, channel, params);
+ break;
+ case MEM_ROT_VF_MEM:
+ ipu->ic_use_count++;
+ ipu->rot_use_count++;
+ _ipu_ic_init_rotate_vf(ipu, params);
+ break;
+ case MEM_PRP_ENC_MEM:
+ ipu->ic_use_count++;
+ reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, reg | FS_ENC_IN_VALID, IPU_FS_PROC_FLOW1);
+ _ipu_ic_init_prpenc(ipu, params, false);
+ break;
+ case MEM_ROT_ENC_MEM:
+ ipu->ic_use_count++;
+ ipu->rot_use_count++;
+ _ipu_ic_init_rotate_enc(ipu, params);
+ break;
+ case MEM_PP_MEM:
+ if (params->mem_pp_mem.graphics_combine_en) {
+ sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
+ in_g_pixel_fmt = params->mem_pp_mem.in_g_pixel_fmt;
+ bad_pixfmt =
+ _ipu_ch_param_bad_alpha_pos(in_g_pixel_fmt);
+
+ if (params->mem_pp_mem.alpha_chan_en) {
+ if (bad_pixfmt) {
+ dev_err(ipu->dev, "bad pixel format "
+ "for graphics plane from "
+ "ch%d\n", sec_dma);
+ ret = -EINVAL;
+ goto err;
+ }
+ ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = true;
+ }
+
+ ipu->sec_chan_en[IPU_CHAN_ID(channel)] = true;
+ }
+
+ _ipu_ic_init_pp(ipu, params);
+ ipu->ic_use_count++;
+ break;
+ case MEM_ROT_PP_MEM:
+ _ipu_ic_init_rotate_pp(ipu, params);
+ ipu->ic_use_count++;
+ ipu->rot_use_count++;
+ break;
+ case MEM_DC_SYNC:
+ if (params->mem_dc_sync.di > 1) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ipu->dc_di_assignment[1] = params->mem_dc_sync.di;
+ _ipu_dc_init(ipu, 1, params->mem_dc_sync.di,
+ params->mem_dc_sync.interlaced,
+ params->mem_dc_sync.out_pixel_fmt);
+ ipu->di_use_count[params->mem_dc_sync.di]++;
+ ipu->dc_use_count++;
+ ipu->dmfc_use_count++;
+ break;
+ case MEM_BG_SYNC:
+ if (params->mem_dp_bg_sync.di > 1) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (params->mem_dp_bg_sync.alpha_chan_en)
+ ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = true;
+
+ ipu->dc_di_assignment[5] = params->mem_dp_bg_sync.di;
+ _ipu_dp_init(ipu, channel, params->mem_dp_bg_sync.in_pixel_fmt,
+ params->mem_dp_bg_sync.out_pixel_fmt);
+ _ipu_dc_init(ipu, 5, params->mem_dp_bg_sync.di,
+ params->mem_dp_bg_sync.interlaced,
+ params->mem_dp_bg_sync.out_pixel_fmt);
+ ipu->di_use_count[params->mem_dp_bg_sync.di]++;
+ ipu->dc_use_count++;
+ ipu->dp_use_count++;
+ ipu->dmfc_use_count++;
+ break;
+ case MEM_FG_SYNC:
+ _ipu_dp_init(ipu, channel, params->mem_dp_fg_sync.in_pixel_fmt,
+ params->mem_dp_fg_sync.out_pixel_fmt);
+
+ if (params->mem_dp_fg_sync.alpha_chan_en)
+ ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = true;
+
+ ipu->dc_use_count++;
+ ipu->dp_use_count++;
+ ipu->dmfc_use_count++;
+ break;
+ case DIRECT_ASYNC0:
+ if (params->direct_async.di > 1) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ipu->dc_di_assignment[8] = params->direct_async.di;
+ _ipu_dc_init(ipu, 8, params->direct_async.di, false, IPU_PIX_FMT_GENERIC);
+ ipu->di_use_count[params->direct_async.di]++;
+ ipu->dc_use_count++;
+ break;
+ case DIRECT_ASYNC1:
+ if (params->direct_async.di > 1) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ipu->dc_di_assignment[9] = params->direct_async.di;
+ _ipu_dc_init(ipu, 9, params->direct_async.di, false, IPU_PIX_FMT_GENERIC);
+ ipu->di_use_count[params->direct_async.di]++;
+ ipu->dc_use_count++;
+ break;
+ default:
+ dev_err(ipu->dev, "Missing channel initialization\n");
+ break;
+ }
+
+ ipu->channel_init_mask |= 1L << IPU_CHAN_ID(channel);
+
+ ipu_cm_write(ipu, ipu_conf, IPU_CONF);
+
+err:
+ mutex_unlock(&ipu->mutex_lock);
+ return ret;
+}
+EXPORT_SYMBOL(ipu_init_channel);
+
+/*!
+ * This function is called to uninitialize a logical IPU channel.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID to uninit.
+ */
+void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ uint32_t reg;
+ uint32_t in_dma, out_dma = 0;
+ uint32_t ipu_conf;
+ uint32_t dc_chan = 0;
+ int ret;
+
+ mutex_lock(&ipu->mutex_lock);
+
+ if ((ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
+ dev_dbg(ipu->dev, "Channel already uninitialized %d\n",
+ IPU_CHAN_ID(channel));
+ mutex_unlock(&ipu->mutex_lock);
+ return;
+ }
+
+ /* Make sure channel is disabled */
+ /* Get input and output dma channels */
+ in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
+ out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
+
+ if (idma_is_set(ipu, IDMAC_CHA_EN(in_dma), in_dma) ||
+ idma_is_set(ipu, IDMAC_CHA_EN(out_dma), out_dma)) {
+ dev_err(ipu->dev,
+ "Channel %d is not disabled, disable first\n",
+ IPU_CHAN_ID(channel));
+ mutex_unlock(&ipu->mutex_lock);
+ return;
+ }
+
+ ipu_conf = ipu_cm_read(ipu, IPU_CONF);
+
+ /* Reset the double buffer */
+ reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(in_dma));
+ ipu_cm_write(ipu, reg & ~idma_mask(in_dma), IPU_CHA_DB_MODE_SEL(in_dma));
+ reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(out_dma));
+ ipu_cm_write(ipu, reg & ~idma_mask(out_dma), IPU_CHA_DB_MODE_SEL(out_dma));
+
+ /* Reset the triple buffer */
+ reg = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(ipu->devtype, in_dma));
+ ipu_cm_write(ipu, reg & ~idma_mask(in_dma),
+ IPU_CHA_TRB_MODE_SEL(ipu->devtype, in_dma));
+ reg = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(ipu->devtype, out_dma));
+ ipu_cm_write(ipu, reg & ~idma_mask(out_dma),
+ IPU_CHA_TRB_MODE_SEL(ipu->devtype, out_dma));
+
+ if (_ipu_is_ic_chan(in_dma) || _ipu_is_dp_graphic_chan(in_dma)) {
+ ipu->sec_chan_en[IPU_CHAN_ID(channel)] = false;
+ ipu->thrd_chan_en[IPU_CHAN_ID(channel)] = false;
+ }
+
+ switch (channel) {
+ case CSI_MEM0:
+ case CSI_MEM1:
+ case CSI_MEM2:
+ case CSI_MEM3:
+ ipu->smfc_use_count--;
+ if (ipu->csi_channel[0] == channel) {
+ ipu->csi_channel[0] = CHAN_NONE;
+ } else if (ipu->csi_channel[1] == channel) {
+ ipu->csi_channel[1] = CHAN_NONE;
+ }
+ break;
+ case CSI_PRP_ENC_MEM:
+ ipu->ic_use_count--;
+ if (ipu->using_ic_dirct_ch == CSI_PRP_ENC_MEM)
+ ipu->using_ic_dirct_ch = 0;
+ _ipu_ic_uninit_prpenc(ipu);
+ if (ipu->csi_channel[0] == channel) {
+ ipu->csi_channel[0] = CHAN_NONE;
+ } else if (ipu->csi_channel[1] == channel) {
+ ipu->csi_channel[1] = CHAN_NONE;
+ }
+ break;
+ case CSI_PRP_VF_MEM:
+ ipu->ic_use_count--;
+ if (ipu->using_ic_dirct_ch == CSI_PRP_VF_MEM)
+ ipu->using_ic_dirct_ch = 0;
+ _ipu_ic_uninit_prpvf(ipu);
+ if (ipu->csi_channel[0] == channel) {
+ ipu->csi_channel[0] = CHAN_NONE;
+ } else if (ipu->csi_channel[1] == channel) {
+ ipu->csi_channel[1] = CHAN_NONE;
+ }
+ break;
+ case MEM_PRP_VF_MEM:
+ ipu->ic_use_count--;
+ _ipu_ic_uninit_prpvf(ipu);
+ reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, reg & ~FS_VF_IN_VALID, IPU_FS_PROC_FLOW1);
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ ipu->ic_use_count--;
+ ipu->vdi_use_count--;
+ if (ipu->using_ic_dirct_ch == MEM_VDI_PRP_VF_MEM)
+ ipu->using_ic_dirct_ch = 0;
+ _ipu_ic_uninit_prpvf(ipu);
+ _ipu_vdi_uninit(ipu);
+ reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, reg & ~FS_VF_IN_VALID, IPU_FS_PROC_FLOW1);
+ break;
+ case MEM_VDI_MEM:
+ ipu->ic_use_count--;
+ ipu->vdi_use_count--;
+ if (ipu->using_ic_dirct_ch == MEM_VDI_MEM)
+ ipu->using_ic_dirct_ch = 0;
+ _ipu_vdi_uninit(ipu);
+ break;
+ case MEM_VDI_PRP_VF_MEM_P:
+ case MEM_VDI_PRP_VF_MEM_N:
+ case MEM_VDI_MEM_P:
+ case MEM_VDI_MEM_N:
+ break;
+ case MEM_ROT_VF_MEM:
+ ipu->rot_use_count--;
+ ipu->ic_use_count--;
+ _ipu_ic_uninit_rotate_vf(ipu);
+ break;
+ case MEM_PRP_ENC_MEM:
+ ipu->ic_use_count--;
+ _ipu_ic_uninit_prpenc(ipu);
+ reg = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, reg & ~FS_ENC_IN_VALID, IPU_FS_PROC_FLOW1);
+ break;
+ case MEM_ROT_ENC_MEM:
+ ipu->rot_use_count--;
+ ipu->ic_use_count--;
+ _ipu_ic_uninit_rotate_enc(ipu);
+ break;
+ case MEM_PP_MEM:
+ ipu->ic_use_count--;
+ _ipu_ic_uninit_pp(ipu);
+ break;
+ case MEM_ROT_PP_MEM:
+ ipu->rot_use_count--;
+ ipu->ic_use_count--;
+ _ipu_ic_uninit_rotate_pp(ipu);
+ break;
+ case MEM_DC_SYNC:
+ dc_chan = 1;
+ _ipu_dc_uninit(ipu, 1);
+ ipu->di_use_count[ipu->dc_di_assignment[1]]--;
+ ipu->dc_use_count--;
+ ipu->dmfc_use_count--;
+ break;
+ case MEM_BG_SYNC:
+ dc_chan = 5;
+ _ipu_dp_uninit(ipu, channel);
+ _ipu_dc_uninit(ipu, 5);
+ ipu->di_use_count[ipu->dc_di_assignment[5]]--;
+ ipu->dc_use_count--;
+ ipu->dp_use_count--;
+ ipu->dmfc_use_count--;
+ break;
+ case MEM_FG_SYNC:
+ _ipu_dp_uninit(ipu, channel);
+ ipu->dc_use_count--;
+ ipu->dp_use_count--;
+ ipu->dmfc_use_count--;
+ break;
+ case DIRECT_ASYNC0:
+ dc_chan = 8;
+ _ipu_dc_uninit(ipu, 8);
+ ipu->di_use_count[ipu->dc_di_assignment[8]]--;
+ ipu->dc_use_count--;
+ break;
+ case DIRECT_ASYNC1:
+ dc_chan = 9;
+ _ipu_dc_uninit(ipu, 9);
+ ipu->di_use_count[ipu->dc_di_assignment[9]]--;
+ ipu->dc_use_count--;
+ break;
+ default:
+ break;
+ }
+
+ if (ipu->ic_use_count == 0)
+ ipu_conf &= ~IPU_CONF_IC_EN;
+ if (ipu->vdi_use_count == 0) {
+ ipu_conf &= ~IPU_CONF_ISP_EN;
+ ipu_conf &= ~IPU_CONF_VDI_EN;
+ ipu_conf &= ~IPU_CONF_IC_INPUT;
+ }
+ if (ipu->rot_use_count == 0)
+ ipu_conf &= ~IPU_CONF_ROT_EN;
+ if (ipu->dc_use_count == 0)
+ ipu_conf &= ~IPU_CONF_DC_EN;
+ if (ipu->dp_use_count == 0)
+ ipu_conf &= ~IPU_CONF_DP_EN;
+ if (ipu->dmfc_use_count == 0)
+ ipu_conf &= ~IPU_CONF_DMFC_EN;
+ if (ipu->di_use_count[0] == 0) {
+ ipu_conf &= ~IPU_CONF_DI0_EN;
+ }
+ if (ipu->di_use_count[1] == 0) {
+ ipu_conf &= ~IPU_CONF_DI1_EN;
+ }
+ if (ipu->smfc_use_count == 0)
+ ipu_conf &= ~IPU_CONF_SMFC_EN;
+
+ ipu_cm_write(ipu, ipu_conf, IPU_CONF);
+
+ ipu->channel_init_mask &= ~(1L << IPU_CHAN_ID(channel));
+
+ /*
+ * Disable pixel clk and its parent clock(if the parent clock
+ * usecount is 1) after clearing DC/DP/DI bits in IPU_CONF
+ * register to prevent LVDS display channel starvation.
+ */
+ if (_ipu_is_primary_disp_chan(in_dma) &&
+ ipu->pixel_clk_en[ipu->dc_di_assignment[dc_chan]]) {
+ clk_disable_unprepare(ipu->pixel_clk[ipu->dc_di_assignment[dc_chan]]);
+ ipu->pixel_clk_en[ipu->dc_di_assignment[dc_chan]] = false;
+ }
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ _ipu_put(ipu);
+
+ ret = pm_runtime_put_sync_suspend(ipu->dev);
+ if (ret < 0) {
+ dev_err(ipu->dev, "ch = %d, pm_runtime_put failed:%d!\n",
+ IPU_CHAN_ID(channel), ret);
+ dump_stack();
+ }
+
+ WARN_ON(ipu->ic_use_count < 0);
+ WARN_ON(ipu->vdi_use_count < 0);
+ WARN_ON(ipu->rot_use_count < 0);
+ WARN_ON(ipu->dc_use_count < 0);
+ WARN_ON(ipu->dp_use_count < 0);
+ WARN_ON(ipu->dmfc_use_count < 0);
+ WARN_ON(ipu->smfc_use_count < 0);
+}
+EXPORT_SYMBOL(ipu_uninit_channel);
+
+/*!
+ * This function is called to initialize buffer(s) for logical IPU channel.
+ *
+ * @param ipu ipu handler
+ *
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param type Input parameter which buffer to initialize.
+ *
+ * @param pixel_fmt Input parameter for pixel format of buffer.
+ * Pixel format is a FOURCC ASCII code.
+ *
+ * @param width Input parameter for width of buffer in pixels.
+ *
+ * @param height Input parameter for height of buffer in pixels.
+ *
+ * @param stride Input parameter for stride length of buffer
+ * in pixels.
+ *
+ * @param rot_mode Input parameter for rotation setting of buffer.
+ * A rotation setting other than
+ * IPU_ROTATE_VERT_FLIP
+ * should only be used for input buffers of
+ * rotation channels.
+ *
+ * @param phyaddr_0 Input parameter buffer 0 physical address.
+ *
+ * @param phyaddr_1 Input parameter buffer 1 physical address.
+ * Setting this to a value other than NULL enables
+ * double buffering mode.
+ *
+ * @param phyaddr_2 Input parameter buffer 2 physical address.
+ * Setting this to a value other than NULL enables
+ * triple buffering mode, phyaddr_1 should not be
+ * NULL then.
+ *
+ * @param u private u offset for additional cropping,
+ * zero if not used.
+ *
+ * @param v private v offset for additional cropping,
+ * zero if not used.
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
+ ipu_buffer_t type,
+ uint32_t pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ ipu_rotate_mode_t rot_mode,
+ dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
+ dma_addr_t phyaddr_2,
+ uint32_t u, uint32_t v)
+{
+ uint32_t reg;
+ uint32_t dma_chan;
+ uint32_t burst_size;
+
+ dma_chan = channel_2_dma(channel, type);
+ if (!idma_is_valid(dma_chan))
+ return -EINVAL;
+
+ if (stride < width * bytes_per_pixel(pixel_fmt))
+ stride = width * bytes_per_pixel(pixel_fmt);
+
+ if (stride % 4) {
+ dev_err(ipu->dev,
+ "Stride not 32-bit aligned, stride = %d\n", stride);
+ return -EINVAL;
+ }
+ /* IC & IRT channels' width must be multiple of 8 pixels */
+ if ((_ipu_is_ic_chan(dma_chan) || _ipu_is_irt_chan(dma_chan))
+ && (width % 8)) {
+ dev_err(ipu->dev, "Width must be 8 pixel multiple\n");
+ return -EINVAL;
+ }
+
+ if (_ipu_is_vdi_out_chan(dma_chan) &&
+ ((width < 16) || (height < 16) || (width % 2) || (height % 4))) {
+ dev_err(ipu->dev, "vdi width/height limited err\n");
+ return -EINVAL;
+ }
+
+ /* IPUv3EX and IPUv3M support triple buffer */
+ if ((!_ipu_is_trb_chan(ipu, dma_chan)) && phyaddr_2) {
+ dev_err(ipu->dev, "Chan%d doesn't support triple buffer "
+ "mode\n", dma_chan);
+ return -EINVAL;
+ }
+ if (!phyaddr_1 && phyaddr_2) {
+ dev_err(ipu->dev, "Chan%d's buf1 physical addr is NULL for "
+ "triple buffer mode\n", dma_chan);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ipu->mutex_lock);
+
+ /* Build parameter memory data for DMA channel */
+ _ipu_ch_param_init(ipu, dma_chan, pixel_fmt, width, height, stride, u, v, 0,
+ phyaddr_0, phyaddr_1, phyaddr_2);
+
+ /* Set correlative channel parameter of local alpha channel */
+ if ((_ipu_is_ic_graphic_chan(dma_chan) ||
+ _ipu_is_dp_graphic_chan(dma_chan)) &&
+ (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] == true)) {
+ _ipu_ch_param_set_alpha_use_separate_channel(ipu, dma_chan, true);
+ _ipu_ch_param_set_alpha_buffer_memory(ipu, dma_chan);
+ _ipu_ch_param_set_alpha_condition_read(ipu, dma_chan);
+ /* fix alpha width as 8 and burst size as 16*/
+ _ipu_ch_params_set_alpha_width(ipu, dma_chan, 8);
+ _ipu_ch_param_set_burst_size(ipu, dma_chan, 16);
+ } else if (_ipu_is_ic_graphic_chan(dma_chan) &&
+ ipu_pixel_format_has_alpha(pixel_fmt))
+ _ipu_ch_param_set_alpha_use_separate_channel(ipu, dma_chan, false);
+
+ if (rot_mode)
+ _ipu_ch_param_set_rotation(ipu, dma_chan, rot_mode);
+
+ /* IC and ROT channels have restriction of 8 or 16 pix burst length */
+ if (_ipu_is_ic_chan(dma_chan) || _ipu_is_vdi_out_chan(dma_chan)) {
+ if ((width % 16) == 0)
+ _ipu_ch_param_set_burst_size(ipu, dma_chan, 16);
+ else
+ _ipu_ch_param_set_burst_size(ipu, dma_chan, 8);
+ } else if (_ipu_is_irt_chan(dma_chan)) {
+ _ipu_ch_param_set_burst_size(ipu, dma_chan, 8);
+ _ipu_ch_param_set_block_mode(ipu, dma_chan);
+ } else if (_ipu_is_dmfc_chan(dma_chan)) {
+ burst_size = _ipu_ch_param_get_burst_size(ipu, dma_chan);
+ _ipu_dmfc_set_wait4eot(ipu, dma_chan, width);
+ _ipu_dmfc_set_burst_size(ipu, dma_chan, burst_size);
+ }
+
+ if (_ipu_disp_chan_is_interlaced(ipu, channel) ||
+ ipu->chan_is_interlaced[dma_chan])
+ _ipu_ch_param_set_interlaced_scan(ipu, dma_chan);
+
+ if (_ipu_is_ic_chan(dma_chan) || _ipu_is_irt_chan(dma_chan) ||
+ _ipu_is_vdi_out_chan(dma_chan)) {
+ burst_size = _ipu_ch_param_get_burst_size(ipu, dma_chan);
+ _ipu_ic_idma_init(ipu, dma_chan, width, height, burst_size,
+ rot_mode);
+ } else if (_ipu_is_smfc_chan(dma_chan)) {
+ burst_size = _ipu_ch_param_get_burst_size(ipu, dma_chan);
+ /*
+ * This is different from IPUv3 spec, but it is confirmed
+ * in IPUforum that SMFC burst size should be NPB[6:3]
+ * when IDMAC works in 16-bit generic data mode.
+ */
+ if (pixel_fmt == IPU_PIX_FMT_GENERIC)
+ /* 8 bits per pixel */
+ burst_size = burst_size >> 4;
+ else if (pixel_fmt == IPU_PIX_FMT_GENERIC_16)
+ /* 16 bits per pixel */
+ burst_size = burst_size >> 3;
+ else
+ burst_size = burst_size >> 2;
+ _ipu_smfc_set_burst_size(ipu, channel, burst_size-1);
+ }
+
+ switch (dma_chan) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ _ipu_ch_param_set_axi_id(ipu, dma_chan, ipu->ch0123_axi);
+ break;
+ case 23:
+ _ipu_ch_param_set_axi_id(ipu, dma_chan, ipu->ch23_axi);
+ break;
+ case 27:
+ _ipu_ch_param_set_axi_id(ipu, dma_chan, ipu->ch27_axi);
+ break;
+ case 28:
+ _ipu_ch_param_set_axi_id(ipu, dma_chan, ipu->ch28_axi);
+ break;
+ default:
+ _ipu_ch_param_set_axi_id(ipu, dma_chan, ipu->normal_axi);
+ break;
+ }
+
+ if (idma_is_set(ipu, IDMAC_CHA_PRI(dma_chan), dma_chan) &&
+ ipu->devtype == IPUv3H) {
+ uint32_t reg = IDMAC_CH_LOCK_EN_1(ipu->devtype);
+ uint32_t value = 0;
+
+ switch (dma_chan) {
+ case 5:
+ value = 0x3;
+ break;
+ case 11:
+ value = 0x3 << 2;
+ break;
+ case 12:
+ value = 0x3 << 4;
+ break;
+ case 14:
+ value = 0x3 << 6;
+ break;
+ case 15:
+ value = 0x3 << 8;
+ break;
+ case 20:
+ value = 0x3 << 10;
+ break;
+ case 21:
+ value = 0x3 << 12;
+ break;
+ case 22:
+ value = 0x3 << 14;
+ break;
+ case 23:
+ value = 0x3 << 16;
+ break;
+ case 27:
+ value = 0x3 << 18;
+ break;
+ case 28:
+ value = 0x3 << 20;
+ break;
+ case 45:
+ reg = IDMAC_CH_LOCK_EN_2(ipu->devtype);
+ value = 0x3 << 0;
+ break;
+ case 46:
+ reg = IDMAC_CH_LOCK_EN_2(ipu->devtype);
+ value = 0x3 << 2;
+ break;
+ case 47:
+ reg = IDMAC_CH_LOCK_EN_2(ipu->devtype);
+ value = 0x3 << 4;
+ break;
+ case 48:
+ reg = IDMAC_CH_LOCK_EN_2(ipu->devtype);
+ value = 0x3 << 6;
+ break;
+ case 49:
+ reg = IDMAC_CH_LOCK_EN_2(ipu->devtype);
+ value = 0x3 << 8;
+ break;
+ case 50:
+ reg = IDMAC_CH_LOCK_EN_2(ipu->devtype);
+ value = 0x3 << 10;
+ break;
+ default:
+ break;
+ }
+ value |= ipu_idmac_read(ipu, reg);
+ ipu_idmac_write(ipu, value, reg);
+ }
+
+ _ipu_ch_param_dump(ipu, dma_chan);
+
+ if (phyaddr_2 && ipu->devtype >= IPUv3EX) {
+ reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(dma_chan));
+ reg &= ~idma_mask(dma_chan);
+ ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(dma_chan));
+
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_TRB_MODE_SEL(ipu->devtype, dma_chan));
+ reg |= idma_mask(dma_chan);
+ ipu_cm_write(ipu, reg,
+ IPU_CHA_TRB_MODE_SEL(ipu->devtype, dma_chan));
+
+ /* Set IDMAC third buffer's cpmem number */
+ /* See __ipu_ch_get_third_buf_cpmem_num() for mapping */
+ ipu_idmac_write(ipu, 0x00444047L,
+ IDMAC_SUB_ADDR_4(ipu->devtype));
+ ipu_idmac_write(ipu, 0x46004241L,
+ IDMAC_SUB_ADDR_3(ipu->devtype));
+ ipu_idmac_write(ipu, 0x00000045L,
+ IDMAC_SUB_ADDR_1(ipu->devtype));
+
+ /* Reset to buffer 0 */
+ ipu_cm_write(ipu, tri_cur_buf_mask(dma_chan),
+ IPU_CHA_TRIPLE_CUR_BUF(ipu->devtype, dma_chan));
+ } else {
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_TRB_MODE_SEL(ipu->devtype, dma_chan));
+ reg &= ~idma_mask(dma_chan);
+ ipu_cm_write(ipu, reg,
+ IPU_CHA_TRB_MODE_SEL(ipu->devtype, dma_chan));
+
+ reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(dma_chan));
+ if (phyaddr_1)
+ reg |= idma_mask(dma_chan);
+ else
+ reg &= ~idma_mask(dma_chan);
+ ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(dma_chan));
+
+ /* Reset to buffer 0 */
+ ipu_cm_write(ipu, idma_mask(dma_chan),
+ IPU_CHA_CUR_BUF(ipu->devtype, dma_chan));
+
+ }
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_init_channel_buffer);
+
+/*!
+ * This function is called to update the physical address of a buffer for
+ * a logical IPU channel.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param type Input parameter which buffer to initialize.
+ *
+ * @param bufNum Input parameter for buffer number to update.
+ * 0 or 1 are the only valid values.
+ *
+ * @param phyaddr Input parameter buffer physical address.
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail. This function will fail if the buffer is set to ready.
+ */
+int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
+ ipu_buffer_t type, uint32_t bufNum, dma_addr_t phyaddr)
+{
+ uint32_t reg;
+ int ret = 0;
+ uint32_t dma_chan = channel_2_dma(channel, type);
+ unsigned long lock_flags;
+
+ if (dma_chan == IDMA_CHAN_INVALID)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
+ if (bufNum == 0)
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_BUF0_RDY(ipu->devtype, dma_chan));
+ else if (bufNum == 1)
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_BUF1_RDY(ipu->devtype, dma_chan));
+ else
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_BUF2_RDY(ipu->devtype, dma_chan));
+
+ if ((reg & idma_mask(dma_chan)) == 0)
+ _ipu_ch_param_set_buffer(ipu, dma_chan, bufNum, phyaddr);
+ else
+ ret = -EACCES;
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_update_channel_buffer);
+
+/*!
+ * This function is called to update the band mode setting for
+ * a logical IPU channel.
+ *
+ * @param ipu ipu handler
+ *
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param type Input parameter which buffer to initialize.
+ *
+ * @param band_height Input parameter for band lines:
+ * shoule be log2(4/8/16/32/64/128/256).
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int32_t ipu_set_channel_bandmode(struct ipu_soc *ipu, ipu_channel_t channel,
+ ipu_buffer_t type, uint32_t band_height)
+{
+ uint32_t reg;
+ int ret = 0;
+ uint32_t dma_chan = channel_2_dma(channel, type);
+
+ if ((2 > band_height) || (8 < band_height))
+ return -EINVAL;
+
+ mutex_lock(&ipu->mutex_lock);
+
+ reg = ipu_idmac_read(ipu, IDMAC_BAND_EN(ipu->devtype, dma_chan));
+ reg |= 1 << (dma_chan % 32);
+ ipu_idmac_write(ipu, reg, IDMAC_BAND_EN(ipu->devtype, dma_chan));
+
+ _ipu_ch_param_set_bandmode(ipu, dma_chan, band_height);
+ dev_dbg(ipu->dev, "dma_chan:%d, band_height:%d.\n\n",
+ dma_chan, 1 << band_height);
+ mutex_unlock(&ipu->mutex_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_set_channel_bandmode);
+
+/*!
+ * This function is called to initialize a buffer for logical IPU channel.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param type Input parameter which buffer to initialize.
+ *
+ * @param pixel_fmt Input parameter for pixel format of buffer.
+ * Pixel format is a FOURCC ASCII code.
+ *
+ * @param width Input parameter for width of buffer in pixels.
+ *
+ * @param height Input parameter for height of buffer in pixels.
+ *
+ * @param stride Input parameter for stride length of buffer
+ * in pixels.
+ *
+ * @param u predefined private u offset for additional cropping,
+ * zero if not used.
+ *
+ * @param v predefined private v offset for additional cropping,
+ * zero if not used.
+ *
+ * @param vertical_offset vertical offset for Y coordinate
+ * in the existed frame
+ *
+ *
+ * @param horizontal_offset horizontal offset for X coordinate
+ * in the existed frame
+ *
+ *
+ * @return Returns 0 on success or negative error code on fail
+ * This function will fail if any buffer is set to ready.
+ */
+
+int32_t ipu_update_channel_offset(struct ipu_soc *ipu,
+ ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ uint32_t u, uint32_t v,
+ uint32_t vertical_offset, uint32_t horizontal_offset)
+{
+ int ret = 0;
+ uint32_t dma_chan = channel_2_dma(channel, type);
+ unsigned long lock_flags;
+
+ if (dma_chan == IDMA_CHAN_INVALID)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
+ if ((ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(ipu->devtype, dma_chan)) &
+ idma_mask(dma_chan)) ||
+ (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(ipu->devtype, dma_chan)) &
+ idma_mask(dma_chan)) ||
+ ((ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(ipu->devtype, dma_chan)) &
+ idma_mask(dma_chan)) &&
+ (ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(ipu->devtype, dma_chan)) &
+ idma_mask(dma_chan)) && _ipu_is_trb_chan(ipu, dma_chan)))
+ ret = -EACCES;
+ else
+ _ipu_ch_offset_update(ipu, dma_chan, pixel_fmt, width, height, stride,
+ u, v, 0, vertical_offset, horizontal_offset);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_update_channel_offset);
+
+int32_t ipu_get_channel_offset(uint32_t pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ uint32_t u, uint32_t v,
+ uint32_t vertical_offset, uint32_t horizontal_offset,
+ uint32_t *u_offset, uint32_t *v_offset)
+{
+ return __ipu_ch_offset_calc(pixel_fmt, width, height, stride,
+ u, v, 0,
+ vertical_offset, horizontal_offset,
+ u_offset, v_offset);
+}
+EXPORT_SYMBOL(ipu_get_channel_offset);
+
+/*!
+ * This function is called to set a channel's buffer as ready.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param type Input parameter which buffer to initialize.
+ *
+ * @param bufNum Input parameter for which buffer number set to
+ * ready state.
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
+ ipu_buffer_t type, uint32_t bufNum)
+{
+ uint32_t dma_chan = channel_2_dma(channel, type);
+ unsigned long lock_flags;
+
+ if (dma_chan == IDMA_CHAN_INVALID)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
+ /* Mark buffer to be ready. */
+ if (bufNum == 0)
+ ipu_cm_write(ipu, idma_mask(dma_chan),
+ IPU_CHA_BUF0_RDY(ipu->devtype, dma_chan));
+ else if (bufNum == 1)
+ ipu_cm_write(ipu, idma_mask(dma_chan),
+ IPU_CHA_BUF1_RDY(ipu->devtype, dma_chan));
+ else
+ ipu_cm_write(ipu, idma_mask(dma_chan),
+ IPU_CHA_BUF2_RDY(ipu->devtype, dma_chan));
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_select_buffer);
+
+/*!
+ * This function is called to set a channel's buffer as ready.
+ *
+ * @param ipu ipu handler
+ * @param bufNum Input parameter for which buffer number set to
+ * ready state.
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum)
+{
+
+ uint32_t dma_chan = channel_2_dma(MEM_VDI_PRP_VF_MEM, IPU_INPUT_BUFFER);
+ uint32_t mask_bit =
+ idma_mask(channel_2_dma(MEM_VDI_PRP_VF_MEM_P, IPU_INPUT_BUFFER))|
+ idma_mask(dma_chan)|
+ idma_mask(channel_2_dma(MEM_VDI_PRP_VF_MEM_N, IPU_INPUT_BUFFER));
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
+ /* Mark buffers to be ready. */
+ if (bufNum == 0)
+ ipu_cm_write(ipu, mask_bit,
+ IPU_CHA_BUF0_RDY(ipu->devtype, dma_chan));
+ else
+ ipu_cm_write(ipu, mask_bit,
+ IPU_CHA_BUF1_RDY(ipu->devtype, dma_chan));
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_select_multi_vdi_buffer);
+
+#define NA -1
+static int proc_dest_sel[] = {
+ 0, 1, 1, 3, 5, 5, 4, 7, 8, 9, 10, 11, 12, 14, 15, 16,
+ 0, 1, 1, 5, 5, 5, 5, 5, 7, 8, 9, 10, 11, 12, 14, 31 };
+static int proc_src_sel[] = { 0, 6, 7, 6, 7, 8, 5, NA, NA, NA,
+ NA, NA, NA, NA, NA, 1, 2, 3, 4, 7, 8, NA, 8, NA };
+static int disp_src_sel[] = { 0, 6, 7, 8, 3, 4, 5, NA, NA, NA,
+ NA, NA, NA, NA, NA, 1, NA, 2, NA, 3, 4, 4, 4, 4 };
+
+
+/*!
+ * This function links 2 channels together for automatic frame
+ * synchronization. The output of the source channel is linked to the input of
+ * the destination channel.
+ *
+ * @param ipu ipu handler
+ * @param src_ch Input parameter for the logical channel ID of
+ * the source channel.
+ *
+ * @param dest_ch Input parameter for the logical channel ID of
+ * the destination channel.
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch)
+{
+ int retval = 0;
+ uint32_t fs_proc_flow1;
+ uint32_t fs_proc_flow2;
+ uint32_t fs_proc_flow3;
+ uint32_t fs_disp_flow1;
+
+ mutex_lock(&ipu->mutex_lock);
+
+ fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
+ fs_proc_flow3 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW3);
+ fs_disp_flow1 = ipu_cm_read(ipu, IPU_FS_DISP_FLOW1);
+
+ switch (src_ch) {
+ case CSI_MEM0:
+ fs_proc_flow3 &= ~FS_SMFC0_DEST_SEL_MASK;
+ fs_proc_flow3 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_SMFC0_DEST_SEL_OFFSET;
+ break;
+ case CSI_MEM1:
+ fs_proc_flow3 &= ~FS_SMFC1_DEST_SEL_MASK;
+ fs_proc_flow3 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_SMFC1_DEST_SEL_OFFSET;
+ break;
+ case CSI_MEM2:
+ fs_proc_flow3 &= ~FS_SMFC2_DEST_SEL_MASK;
+ fs_proc_flow3 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_SMFC2_DEST_SEL_OFFSET;
+ break;
+ case CSI_MEM3:
+ fs_proc_flow3 &= ~FS_SMFC3_DEST_SEL_MASK;
+ fs_proc_flow3 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_SMFC3_DEST_SEL_OFFSET;
+ break;
+ case CSI_PRP_ENC_MEM:
+ fs_proc_flow2 &= ~FS_PRPENC_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PRPENC_DEST_SEL_OFFSET;
+ break;
+ case CSI_PRP_VF_MEM:
+ fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PRPVF_DEST_SEL_OFFSET;
+ break;
+ case MEM_PP_MEM:
+ fs_proc_flow2 &= ~FS_PP_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PP_DEST_SEL_OFFSET;
+ break;
+ case MEM_ROT_PP_MEM:
+ fs_proc_flow2 &= ~FS_PP_ROT_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PP_ROT_DEST_SEL_OFFSET;
+ break;
+ case MEM_PRP_ENC_MEM:
+ fs_proc_flow2 &= ~FS_PRPENC_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PRPENC_DEST_SEL_OFFSET;
+ break;
+ case MEM_ROT_ENC_MEM:
+ fs_proc_flow2 &= ~FS_PRPENC_ROT_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PRPENC_ROT_DEST_SEL_OFFSET;
+ break;
+ case MEM_PRP_VF_MEM:
+ fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PRPVF_DEST_SEL_OFFSET;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PRPVF_DEST_SEL_OFFSET;
+ break;
+ case MEM_ROT_VF_MEM:
+ fs_proc_flow2 &= ~FS_PRPVF_ROT_DEST_SEL_MASK;
+ fs_proc_flow2 |=
+ proc_dest_sel[IPU_CHAN_ID(dest_ch)] <<
+ FS_PRPVF_ROT_DEST_SEL_OFFSET;
+ break;
+ case MEM_VDOA_MEM:
+ fs_proc_flow3 &= ~FS_VDOA_DEST_SEL_MASK;
+ if (MEM_VDI_MEM == dest_ch)
+ fs_proc_flow3 |= FS_VDOA_DEST_SEL_VDI;
+ else if (MEM_PP_MEM == dest_ch)
+ fs_proc_flow3 |= FS_VDOA_DEST_SEL_IC;
+ else {
+ retval = -EINVAL;
+ goto err;
+ }
+ break;
+ default:
+ retval = -EINVAL;
+ goto err;
+ }
+
+ switch (dest_ch) {
+ case MEM_PP_MEM:
+ fs_proc_flow1 &= ~FS_PP_SRC_SEL_MASK;
+ if (MEM_VDOA_MEM == src_ch)
+ fs_proc_flow1 |= FS_PP_SRC_SEL_VDOA;
+ else
+ fs_proc_flow1 |= proc_src_sel[IPU_CHAN_ID(src_ch)] <<
+ FS_PP_SRC_SEL_OFFSET;
+ break;
+ case MEM_ROT_PP_MEM:
+ fs_proc_flow1 &= ~FS_PP_ROT_SRC_SEL_MASK;
+ fs_proc_flow1 |=
+ proc_src_sel[IPU_CHAN_ID(src_ch)] <<
+ FS_PP_ROT_SRC_SEL_OFFSET;
+ break;
+ case MEM_PRP_ENC_MEM:
+ fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
+ fs_proc_flow1 |=
+ proc_src_sel[IPU_CHAN_ID(src_ch)] << FS_PRP_SRC_SEL_OFFSET;
+ break;
+ case MEM_ROT_ENC_MEM:
+ fs_proc_flow1 &= ~FS_PRPENC_ROT_SRC_SEL_MASK;
+ fs_proc_flow1 |=
+ proc_src_sel[IPU_CHAN_ID(src_ch)] <<
+ FS_PRPENC_ROT_SRC_SEL_OFFSET;
+ break;
+ case MEM_PRP_VF_MEM:
+ fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
+ fs_proc_flow1 |=
+ proc_src_sel[IPU_CHAN_ID(src_ch)] << FS_PRP_SRC_SEL_OFFSET;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
+ fs_proc_flow1 |=
+ proc_src_sel[IPU_CHAN_ID(src_ch)] << FS_PRP_SRC_SEL_OFFSET;
+ break;
+ case MEM_ROT_VF_MEM:
+ fs_proc_flow1 &= ~FS_PRPVF_ROT_SRC_SEL_MASK;
+ fs_proc_flow1 |=
+ proc_src_sel[IPU_CHAN_ID(src_ch)] <<
+ FS_PRPVF_ROT_SRC_SEL_OFFSET;
+ break;
+ case MEM_DC_SYNC:
+ fs_disp_flow1 &= ~FS_DC1_SRC_SEL_MASK;
+ fs_disp_flow1 |=
+ disp_src_sel[IPU_CHAN_ID(src_ch)] << FS_DC1_SRC_SEL_OFFSET;
+ break;
+ case MEM_BG_SYNC:
+ fs_disp_flow1 &= ~FS_DP_SYNC0_SRC_SEL_MASK;
+ fs_disp_flow1 |=
+ disp_src_sel[IPU_CHAN_ID(src_ch)] <<
+ FS_DP_SYNC0_SRC_SEL_OFFSET;
+ break;
+ case MEM_FG_SYNC:
+ fs_disp_flow1 &= ~FS_DP_SYNC1_SRC_SEL_MASK;
+ fs_disp_flow1 |=
+ disp_src_sel[IPU_CHAN_ID(src_ch)] <<
+ FS_DP_SYNC1_SRC_SEL_OFFSET;
+ break;
+ case MEM_DC_ASYNC:
+ fs_disp_flow1 &= ~FS_DC2_SRC_SEL_MASK;
+ fs_disp_flow1 |=
+ disp_src_sel[IPU_CHAN_ID(src_ch)] << FS_DC2_SRC_SEL_OFFSET;
+ break;
+ case MEM_BG_ASYNC0:
+ fs_disp_flow1 &= ~FS_DP_ASYNC0_SRC_SEL_MASK;
+ fs_disp_flow1 |=
+ disp_src_sel[IPU_CHAN_ID(src_ch)] <<
+ FS_DP_ASYNC0_SRC_SEL_OFFSET;
+ break;
+ case MEM_FG_ASYNC0:
+ fs_disp_flow1 &= ~FS_DP_ASYNC1_SRC_SEL_MASK;
+ fs_disp_flow1 |=
+ disp_src_sel[IPU_CHAN_ID(src_ch)] <<
+ FS_DP_ASYNC1_SRC_SEL_OFFSET;
+ break;
+ case MEM_VDI_MEM:
+ fs_proc_flow1 &= ~FS_VDI_SRC_SEL_MASK;
+ if (MEM_VDOA_MEM == src_ch)
+ fs_proc_flow1 |= FS_VDI_SRC_SEL_VDOA;
+ else {
+ retval = -EINVAL;
+ goto err;
+ }
+ break;
+ default:
+ retval = -EINVAL;
+ goto err;
+ }
+
+ ipu_cm_write(ipu, fs_proc_flow1, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, fs_proc_flow2, IPU_FS_PROC_FLOW2);
+ ipu_cm_write(ipu, fs_proc_flow3, IPU_FS_PROC_FLOW3);
+ ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
+
+err:
+ mutex_unlock(&ipu->mutex_lock);
+ return retval;
+}
+EXPORT_SYMBOL(ipu_link_channels);
+
+/*!
+ * This function unlinks 2 channels and disables automatic frame
+ * synchronization.
+ *
+ * @param ipu ipu handler
+ * @param src_ch Input parameter for the logical channel ID of
+ * the source channel.
+ *
+ * @param dest_ch Input parameter for the logical channel ID of
+ * the destination channel.
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch)
+{
+ int retval = 0;
+ uint32_t fs_proc_flow1;
+ uint32_t fs_proc_flow2;
+ uint32_t fs_proc_flow3;
+ uint32_t fs_disp_flow1;
+
+ mutex_lock(&ipu->mutex_lock);
+
+ fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
+ fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
+ fs_proc_flow3 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW3);
+ fs_disp_flow1 = ipu_cm_read(ipu, IPU_FS_DISP_FLOW1);
+
+ switch (src_ch) {
+ case CSI_MEM0:
+ fs_proc_flow3 &= ~FS_SMFC0_DEST_SEL_MASK;
+ break;
+ case CSI_MEM1:
+ fs_proc_flow3 &= ~FS_SMFC1_DEST_SEL_MASK;
+ break;
+ case CSI_MEM2:
+ fs_proc_flow3 &= ~FS_SMFC2_DEST_SEL_MASK;
+ break;
+ case CSI_MEM3:
+ fs_proc_flow3 &= ~FS_SMFC3_DEST_SEL_MASK;
+ break;
+ case CSI_PRP_ENC_MEM:
+ fs_proc_flow2 &= ~FS_PRPENC_DEST_SEL_MASK;
+ break;
+ case CSI_PRP_VF_MEM:
+ fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
+ break;
+ case MEM_PP_MEM:
+ fs_proc_flow2 &= ~FS_PP_DEST_SEL_MASK;
+ break;
+ case MEM_ROT_PP_MEM:
+ fs_proc_flow2 &= ~FS_PP_ROT_DEST_SEL_MASK;
+ break;
+ case MEM_PRP_ENC_MEM:
+ fs_proc_flow2 &= ~FS_PRPENC_DEST_SEL_MASK;
+ break;
+ case MEM_ROT_ENC_MEM:
+ fs_proc_flow2 &= ~FS_PRPENC_ROT_DEST_SEL_MASK;
+ break;
+ case MEM_PRP_VF_MEM:
+ fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ fs_proc_flow2 &= ~FS_PRPVF_DEST_SEL_MASK;
+ break;
+ case MEM_ROT_VF_MEM:
+ fs_proc_flow2 &= ~FS_PRPVF_ROT_DEST_SEL_MASK;
+ break;
+ case MEM_VDOA_MEM:
+ fs_proc_flow3 &= ~FS_VDOA_DEST_SEL_MASK;
+ break;
+ default:
+ retval = -EINVAL;
+ goto err;
+ }
+
+ switch (dest_ch) {
+ case MEM_PP_MEM:
+ fs_proc_flow1 &= ~FS_PP_SRC_SEL_MASK;
+ break;
+ case MEM_ROT_PP_MEM:
+ fs_proc_flow1 &= ~FS_PP_ROT_SRC_SEL_MASK;
+ break;
+ case MEM_PRP_ENC_MEM:
+ fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
+ break;
+ case MEM_ROT_ENC_MEM:
+ fs_proc_flow1 &= ~FS_PRPENC_ROT_SRC_SEL_MASK;
+ break;
+ case MEM_PRP_VF_MEM:
+ fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ fs_proc_flow1 &= ~FS_PRP_SRC_SEL_MASK;
+ break;
+ case MEM_ROT_VF_MEM:
+ fs_proc_flow1 &= ~FS_PRPVF_ROT_SRC_SEL_MASK;
+ break;
+ case MEM_DC_SYNC:
+ fs_disp_flow1 &= ~FS_DC1_SRC_SEL_MASK;
+ break;
+ case MEM_BG_SYNC:
+ fs_disp_flow1 &= ~FS_DP_SYNC0_SRC_SEL_MASK;
+ break;
+ case MEM_FG_SYNC:
+ fs_disp_flow1 &= ~FS_DP_SYNC1_SRC_SEL_MASK;
+ break;
+ case MEM_DC_ASYNC:
+ fs_disp_flow1 &= ~FS_DC2_SRC_SEL_MASK;
+ break;
+ case MEM_BG_ASYNC0:
+ fs_disp_flow1 &= ~FS_DP_ASYNC0_SRC_SEL_MASK;
+ break;
+ case MEM_FG_ASYNC0:
+ fs_disp_flow1 &= ~FS_DP_ASYNC1_SRC_SEL_MASK;
+ break;
+ case MEM_VDI_MEM:
+ fs_proc_flow1 &= ~FS_VDI_SRC_SEL_MASK;
+ break;
+ default:
+ retval = -EINVAL;
+ goto err;
+ }
+
+ ipu_cm_write(ipu, fs_proc_flow1, IPU_FS_PROC_FLOW1);
+ ipu_cm_write(ipu, fs_proc_flow2, IPU_FS_PROC_FLOW2);
+ ipu_cm_write(ipu, fs_proc_flow3, IPU_FS_PROC_FLOW3);
+ ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
+
+err:
+ mutex_unlock(&ipu->mutex_lock);
+ return retval;
+}
+EXPORT_SYMBOL(ipu_unlink_channels);
+
+/*!
+ * This function check whether a logical channel was enabled.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @return This function returns 1 while request channel is enabled or
+ * 0 for not enabled.
+ */
+int32_t ipu_is_channel_busy(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ uint32_t reg;
+ uint32_t in_dma;
+ uint32_t out_dma;
+
+ out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
+ in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
+
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(in_dma));
+ if (reg & idma_mask(in_dma))
+ return 1;
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(out_dma));
+ if (reg & idma_mask(out_dma))
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(ipu_is_channel_busy);
+
+/*!
+ * This function enables a logical channel.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ uint32_t reg;
+ uint32_t ipu_conf;
+ uint32_t in_dma;
+ uint32_t out_dma;
+ uint32_t sec_dma;
+ uint32_t thrd_dma;
+ uint32_t di = 0;
+
+ mutex_lock(&ipu->mutex_lock);
+
+ if (ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
+ dev_err(ipu->dev, "Warning: channel already enabled %d\n",
+ IPU_CHAN_ID(channel));
+ mutex_unlock(&ipu->mutex_lock);
+ return -EACCES;
+ }
+
+ /* Get input and output dma channels */
+ out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
+ in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
+
+ ipu_conf = ipu_cm_read(ipu, IPU_CONF);
+ switch (channel) {
+ case MEM_BG_SYNC:
+ di = ipu->dc_di_assignment[5];
+ if (ipu->di_use_count[di] > 0)
+ ipu_conf |= di ? IPU_CONF_DI1_EN : IPU_CONF_DI0_EN;
+ if (ipu->dp_use_count > 0)
+ ipu_conf |= IPU_CONF_DP_EN;
+ if (ipu->dc_use_count > 0)
+ ipu_conf |= IPU_CONF_DC_EN;
+ if (ipu->dmfc_use_count > 0)
+ ipu_conf |= IPU_CONF_DMFC_EN;
+ break;
+ case MEM_DC_SYNC:
+ di = ipu->dc_di_assignment[1];
+ if (ipu->di_use_count[di] > 0)
+ ipu_conf |= di ? IPU_CONF_DI1_EN : IPU_CONF_DI0_EN;
+ if (ipu->dc_use_count > 0)
+ ipu_conf |= IPU_CONF_DC_EN;
+ if (ipu->dmfc_use_count > 0)
+ ipu_conf |= IPU_CONF_DMFC_EN;
+ break;
+ case MEM_FG_SYNC:
+ if (ipu->dp_use_count > 0)
+ ipu_conf |= IPU_CONF_DP_EN;
+ if (ipu->dc_use_count > 0)
+ ipu_conf |= IPU_CONF_DC_EN;
+ if (ipu->dmfc_use_count > 0)
+ ipu_conf |= IPU_CONF_DMFC_EN;
+ break;
+ case DIRECT_ASYNC0:
+ di = ipu->dc_di_assignment[8];
+ /* fall through */
+ case DIRECT_ASYNC1:
+ di = ipu->dc_di_assignment[9];
+ if (ipu->di_use_count[di] > 0)
+ ipu_conf |= di ? IPU_CONF_DI1_EN : IPU_CONF_DI0_EN;
+ if (ipu->dc_use_count > 0)
+ ipu_conf |= IPU_CONF_DC_EN;
+ break;
+ case MEM_ROT_PP_MEM:
+ case MEM_ROT_ENC_MEM:
+ case MEM_ROT_VF_MEM:
+ if (ipu->rot_use_count > 0)
+ ipu_conf |= IPU_CONF_ROT_EN;
+ /* fall through */
+ case MEM_PP_MEM:
+ case MEM_PRP_ENC_MEM:
+ case MEM_PRP_VF_MEM:
+ case CSI_PRP_ENC_MEM:
+ case CSI_PRP_VF_MEM:
+ if (ipu->ic_use_count > 0)
+ ipu_conf |= IPU_CONF_IC_EN;
+ break;
+ case CSI_MEM0:
+ case CSI_MEM1:
+ case CSI_MEM2:
+ case CSI_MEM3:
+ if (ipu->smfc_use_count > 0)
+ ipu_conf |= IPU_CONF_SMFC_EN;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ case MEM_VDI_MEM:
+ if (ipu->vdi_use_count > 0) {
+ ipu_conf |= IPU_CONF_ISP_EN;
+ ipu_conf |= IPU_CONF_VDI_EN;
+ ipu_conf |= IPU_CONF_IC_INPUT;
+ }
+ if (ipu->ic_use_count > 0)
+ ipu_conf |= IPU_CONF_IC_EN;
+ break;
+ default:
+ break;
+ }
+ ipu_cm_write(ipu, ipu_conf, IPU_CONF);
+
+ if (idma_is_valid(in_dma)) {
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(in_dma));
+ ipu_idmac_write(ipu, reg | idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
+ }
+ if (idma_is_valid(out_dma)) {
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(out_dma));
+ ipu_idmac_write(ipu, reg | idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
+ }
+
+ if ((ipu->sec_chan_en[IPU_CHAN_ID(channel)]) &&
+ ((channel == MEM_PP_MEM) || (channel == MEM_PRP_VF_MEM) ||
+ (channel == MEM_VDI_PRP_VF_MEM))) {
+ sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(sec_dma));
+ ipu_idmac_write(ipu, reg | idma_mask(sec_dma), IDMAC_CHA_EN(sec_dma));
+ }
+ if ((ipu->thrd_chan_en[IPU_CHAN_ID(channel)]) &&
+ ((channel == MEM_PP_MEM) || (channel == MEM_PRP_VF_MEM))) {
+ thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(thrd_dma));
+ ipu_idmac_write(ipu, reg | idma_mask(thrd_dma), IDMAC_CHA_EN(thrd_dma));
+
+ sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
+ reg = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
+ ipu_idmac_write(ipu, reg | idma_mask(sec_dma), IDMAC_SEP_ALPHA);
+ } else if ((ipu->thrd_chan_en[IPU_CHAN_ID(channel)]) &&
+ ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC))) {
+ thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(thrd_dma));
+ ipu_idmac_write(ipu, reg | idma_mask(thrd_dma), IDMAC_CHA_EN(thrd_dma));
+ reg = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
+ ipu_idmac_write(ipu, reg | idma_mask(in_dma), IDMAC_SEP_ALPHA);
+ }
+
+ if ((channel == MEM_DC_SYNC) || (channel == MEM_BG_SYNC) ||
+ (channel == MEM_FG_SYNC)) {
+ reg = ipu_idmac_read(ipu, IDMAC_WM_EN(in_dma));
+ ipu_idmac_write(ipu, reg | idma_mask(in_dma), IDMAC_WM_EN(in_dma));
+
+ _ipu_dp_dc_enable(ipu, channel);
+ }
+
+ if (_ipu_is_ic_chan(in_dma) || _ipu_is_ic_chan(out_dma) ||
+ _ipu_is_irt_chan(in_dma) || _ipu_is_irt_chan(out_dma) ||
+ _ipu_is_vdi_out_chan(out_dma))
+ _ipu_ic_enable_task(ipu, channel);
+
+ ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(channel);
+
+ if (ipu->prg_clk)
+ clk_prepare_enable(ipu->prg_clk);
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_enable_channel);
+
+/*!
+ * This function check buffer ready for a logical channel.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param type Input parameter which buffer to clear.
+ *
+ * @param bufNum Input parameter for which buffer number clear
+ * ready state.
+ *
+ */
+int32_t ipu_check_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum)
+{
+ uint32_t dma_chan = channel_2_dma(channel, type);
+ uint32_t reg;
+ unsigned long lock_flags;
+
+ if (dma_chan == IDMA_CHAN_INVALID)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
+ if (bufNum == 0)
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_BUF0_RDY(ipu->devtype, dma_chan));
+ else if (bufNum == 1)
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_BUF1_RDY(ipu->devtype, dma_chan));
+ else
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_BUF2_RDY(ipu->devtype, dma_chan));
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
+ if (reg & idma_mask(dma_chan))
+ return 1;
+ else
+ return 0;
+}
+EXPORT_SYMBOL(ipu_check_buffer_ready);
+
+/*!
+ * This function clear buffer ready for a logical channel.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param type Input parameter which buffer to clear.
+ *
+ * @param bufNum Input parameter for which buffer number clear
+ * ready state.
+ *
+ */
+void _ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum)
+{
+ uint32_t dma_ch = channel_2_dma(channel, type);
+
+ if (!idma_is_valid(dma_ch))
+ return;
+
+ ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
+ if (bufNum == 0)
+ ipu_cm_write(ipu, idma_mask(dma_ch),
+ IPU_CHA_BUF0_RDY(ipu->devtype, dma_ch));
+ else if (bufNum == 1)
+ ipu_cm_write(ipu, idma_mask(dma_ch),
+ IPU_CHA_BUF1_RDY(ipu->devtype, dma_ch));
+ else
+ ipu_cm_write(ipu, idma_mask(dma_ch),
+ IPU_CHA_BUF2_RDY(ipu->devtype, dma_ch));
+ ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
+}
+
+void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum)
+{
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
+ _ipu_clear_buffer_ready(ipu, channel, type, bufNum);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+}
+EXPORT_SYMBOL(ipu_clear_buffer_ready);
+
+/*!
+ * This function disables a logical channel.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param wait_for_stop Flag to set whether to wait for channel end
+ * of frame or return immediately.
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop)
+{
+ uint32_t reg;
+ uint32_t in_dma;
+ uint32_t out_dma;
+ uint32_t sec_dma = NO_DMA;
+ uint32_t thrd_dma = NO_DMA;
+ uint16_t fg_pos_x, fg_pos_y;
+ unsigned long lock_flags;
+
+ mutex_lock(&ipu->mutex_lock);
+
+ if ((ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
+ dev_dbg(ipu->dev, "Channel already disabled %d\n",
+ IPU_CHAN_ID(channel));
+ mutex_unlock(&ipu->mutex_lock);
+ return -EACCES;
+ }
+
+ /* Get input and output dma channels */
+ out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
+ in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
+
+ if ((idma_is_valid(in_dma) &&
+ !idma_is_set(ipu, IDMAC_CHA_EN(in_dma), in_dma))
+ && (idma_is_valid(out_dma) &&
+ !idma_is_set(ipu, IDMAC_CHA_EN(out_dma), out_dma))) {
+ mutex_unlock(&ipu->mutex_lock);
+ return -EINVAL;
+ }
+
+ if (ipu->sec_chan_en[IPU_CHAN_ID(channel)])
+ sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
+ if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)]) {
+ sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
+ thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
+ }
+
+ if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
+ (channel == MEM_DC_SYNC)) {
+ if (channel == MEM_FG_SYNC) {
+ _ipu_disp_get_window_pos(ipu, channel, &fg_pos_x, &fg_pos_y);
+ _ipu_disp_set_window_pos(ipu, channel, 0, 0);
+ }
+
+ _ipu_dp_dc_disable(ipu, channel, false);
+
+ /*
+ * wait for BG channel EOF then disable FG-IDMAC,
+ * it avoid FG NFB4EOF error.
+ */
+ if ((channel == MEM_FG_SYNC) && (ipu_is_channel_busy(ipu, MEM_BG_SYNC))) {
+ int timeout = 50;
+
+ ipu_cm_write(ipu, IPUIRQ_2_MASK(IPU_IRQ_BG_SYNC_EOF),
+ IPUIRQ_2_STATREG(ipu->devtype,
+ IPU_IRQ_BG_SYNC_EOF));
+ while ((ipu_cm_read(ipu,
+ IPUIRQ_2_STATREG(ipu->devtype,
+ IPU_IRQ_BG_SYNC_EOF)) &
+ IPUIRQ_2_MASK(IPU_IRQ_BG_SYNC_EOF)) == 0) {
+ msleep(10);
+ timeout -= 10;
+ if (timeout <= 0) {
+ dev_err(ipu->dev, "warning: wait for bg sync eof timeout\n");
+ break;
+ }
+ }
+ }
+ } else if (wait_for_stop && !_ipu_is_smfc_chan(out_dma) &&
+ channel != CSI_PRP_VF_MEM && channel != CSI_PRP_ENC_MEM) {
+ while (idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype, in_dma),
+ in_dma) ||
+ idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype, out_dma),
+ out_dma) ||
+ (ipu->sec_chan_en[IPU_CHAN_ID(channel)] &&
+ idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype, sec_dma),
+ sec_dma)) ||
+ (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] &&
+ idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype, thrd_dma),
+ thrd_dma))) {
+ uint32_t irq = 0xffffffff;
+ int timeout = 50000;
+
+ if (idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype,
+ out_dma), out_dma))
+ irq = out_dma;
+ if (ipu->sec_chan_en[IPU_CHAN_ID(channel)] &&
+ idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype,
+ sec_dma), sec_dma))
+ irq = sec_dma;
+ if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] &&
+ idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype,
+ thrd_dma), thrd_dma))
+ irq = thrd_dma;
+ if (idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype,
+ in_dma), in_dma))
+ irq = in_dma;
+
+ if (irq == 0xffffffff) {
+ dev_dbg(ipu->dev, "warning: no channel busy, break\n");
+ break;
+ }
+
+ ipu_cm_write(ipu, IPUIRQ_2_MASK(irq),
+ IPUIRQ_2_STATREG(ipu->devtype, irq));
+
+ dev_dbg(ipu->dev, "warning: channel %d busy, need wait\n", irq);
+
+ while (((ipu_cm_read(ipu,
+ IPUIRQ_2_STATREG(ipu->devtype, irq))
+ & IPUIRQ_2_MASK(irq)) == 0) &&
+ (idma_is_set(ipu, IDMAC_CHA_BUSY(ipu->devtype,
+ irq), irq))) {
+ udelay(10);
+ timeout -= 10;
+ if (timeout <= 0) {
+ ipu_dump_registers(ipu);
+ dev_err(ipu->dev, "warning: disable ipu dma channel %d during its busy state\n", irq);
+ break;
+ }
+ }
+ dev_dbg(ipu->dev, "wait_time:%d\n", 50000 - timeout);
+
+ }
+ }
+
+ if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
+ (channel == MEM_DC_SYNC)) {
+ reg = ipu_idmac_read(ipu, IDMAC_WM_EN(in_dma));
+ ipu_idmac_write(ipu, reg & ~idma_mask(in_dma), IDMAC_WM_EN(in_dma));
+ }
+
+ /* Disable IC task */
+ if (_ipu_is_ic_chan(in_dma) || _ipu_is_ic_chan(out_dma) ||
+ _ipu_is_irt_chan(in_dma) || _ipu_is_irt_chan(out_dma) ||
+ _ipu_is_vdi_out_chan(out_dma))
+ _ipu_ic_disable_task(ipu, channel);
+
+ /* Disable DMA channel(s) */
+ if (idma_is_valid(in_dma)) {
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(in_dma));
+ ipu_idmac_write(ipu, reg & ~idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
+ ipu_cm_write(ipu, idma_mask(in_dma),
+ IPU_CHA_CUR_BUF(ipu->devtype, in_dma));
+ ipu_cm_write(ipu, tri_cur_buf_mask(in_dma),
+ IPU_CHA_TRIPLE_CUR_BUF(ipu->devtype, in_dma));
+ }
+ if (idma_is_valid(out_dma)) {
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(out_dma));
+ ipu_idmac_write(ipu, reg & ~idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
+ ipu_cm_write(ipu, idma_mask(out_dma),
+ IPU_CHA_CUR_BUF(ipu->devtype, out_dma));
+ ipu_cm_write(ipu, tri_cur_buf_mask(out_dma),
+ IPU_CHA_TRIPLE_CUR_BUF(ipu->devtype, out_dma));
+ }
+ if (ipu->sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(sec_dma));
+ ipu_idmac_write(ipu, reg & ~idma_mask(sec_dma), IDMAC_CHA_EN(sec_dma));
+ ipu_cm_write(ipu, idma_mask(sec_dma),
+ IPU_CHA_CUR_BUF(ipu->devtype, sec_dma));
+ }
+ if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(thrd_dma));
+ ipu_idmac_write(ipu, reg & ~idma_mask(thrd_dma), IDMAC_CHA_EN(thrd_dma));
+ if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC) {
+ reg = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
+ ipu_idmac_write(ipu, reg & ~idma_mask(in_dma), IDMAC_SEP_ALPHA);
+ } else {
+ reg = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
+ ipu_idmac_write(ipu, reg & ~idma_mask(sec_dma), IDMAC_SEP_ALPHA);
+ }
+ ipu_cm_write(ipu, idma_mask(thrd_dma),
+ IPU_CHA_CUR_BUF(ipu->devtype, thrd_dma));
+ }
+
+ if (channel == MEM_FG_SYNC)
+ _ipu_disp_set_window_pos(ipu, channel, fg_pos_x, fg_pos_y);
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
+ /* Set channel buffers NOT to be ready */
+ if (idma_is_valid(in_dma)) {
+ _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 0);
+ _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 1);
+ _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 2);
+ }
+ if (idma_is_valid(out_dma)) {
+ _ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 0);
+ _ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 1);
+ }
+ if (ipu->sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
+ _ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 0);
+ _ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 1);
+ }
+ if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
+ _ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 0);
+ _ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 1);
+ }
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
+ ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
+
+ if (ipu->prg_clk)
+ clk_disable_unprepare(ipu->prg_clk);
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_disable_channel);
+
+/*!
+ * This function enables CSI.
+ *
+ * @param ipu ipu handler
+ * @param csi csi num 0 or 1
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi)
+{
+ uint32_t reg;
+
+ if (csi > 1) {
+ dev_err(ipu->dev, "Wrong csi num_%d\n", csi);
+ return -EINVAL;
+ }
+
+ _ipu_get(ipu);
+ mutex_lock(&ipu->mutex_lock);
+ ipu->csi_use_count[csi]++;
+
+ if (ipu->csi_use_count[csi] == 1) {
+ reg = ipu_cm_read(ipu, IPU_CONF);
+ if (csi == 0)
+ ipu_cm_write(ipu, reg | IPU_CONF_CSI0_EN, IPU_CONF);
+ else
+ ipu_cm_write(ipu, reg | IPU_CONF_CSI1_EN, IPU_CONF);
+ }
+ mutex_unlock(&ipu->mutex_lock);
+ _ipu_put(ipu);
+ return 0;
+}
+EXPORT_SYMBOL(ipu_enable_csi);
+
+/*!
+ * This function disables CSI.
+ *
+ * @param ipu ipu handler
+ * @param csi csi num 0 or 1
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi)
+{
+ uint32_t reg;
+
+ if (csi > 1) {
+ dev_err(ipu->dev, "Wrong csi num_%d\n", csi);
+ return -EINVAL;
+ }
+ _ipu_get(ipu);
+ mutex_lock(&ipu->mutex_lock);
+ ipu->csi_use_count[csi]--;
+ if (ipu->csi_use_count[csi] == 0) {
+ _ipu_csi_wait4eof(ipu, ipu->csi_channel[csi]);
+ reg = ipu_cm_read(ipu, IPU_CONF);
+ if (csi == 0)
+ ipu_cm_write(ipu, reg & ~IPU_CONF_CSI0_EN, IPU_CONF);
+ else
+ ipu_cm_write(ipu, reg & ~IPU_CONF_CSI1_EN, IPU_CONF);
+ }
+ mutex_unlock(&ipu->mutex_lock);
+ _ipu_put(ipu);
+ return 0;
+}
+EXPORT_SYMBOL(ipu_disable_csi);
+
+static irqreturn_t ipu_sync_irq_handler(int irq, void *desc)
+{
+ struct ipu_soc *ipu = desc;
+ int i;
+ uint32_t line, bit, int_stat, int_ctrl;
+ irqreturn_t result = IRQ_NONE;
+ const int int_reg[] = { 1, 2, 3, 4, 11, 12, 13, 14, 15, 0 };
+
+ spin_lock(&ipu->int_reg_spin_lock);
+
+ for (i = 0; int_reg[i] != 0; i++) {
+ int_stat = ipu_cm_read(ipu,
+ IPU_INT_STAT(ipu->devtype, int_reg[i]));
+ int_ctrl = ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i]));
+ int_stat &= int_ctrl;
+ ipu_cm_write(ipu, int_stat,
+ IPU_INT_STAT(ipu->devtype, int_reg[i]));
+ while ((line = ffs(int_stat)) != 0) {
+ bit = --line;
+ int_stat &= ~(1UL << line);
+ line += (int_reg[i] - 1) * 32;
+ result |=
+ ipu->irq_list[line].handler(line,
+ ipu->irq_list[line].
+ dev_id);
+ if (ipu->irq_list[line].flags & IPU_IRQF_ONESHOT) {
+ int_ctrl &= ~(1UL << bit);
+ ipu_cm_write(ipu, int_ctrl,
+ IPU_INT_CTRL(int_reg[i]));
+ }
+ }
+ }
+
+ spin_unlock(&ipu->int_reg_spin_lock);
+
+ return result;
+}
+
+static irqreturn_t ipu_err_irq_handler(int irq, void *desc)
+{
+ struct ipu_soc *ipu = desc;
+ int i;
+ uint32_t int_stat;
+ const int err_reg[] = { 5, 6, 9, 10, 0 };
+
+ spin_lock(&ipu->int_reg_spin_lock);
+
+ for (i = 0; err_reg[i] != 0; i++) {
+ int_stat = ipu_cm_read(ipu,
+ IPU_INT_STAT(ipu->devtype, err_reg[i]));
+ int_stat &= ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i]));
+ if (int_stat) {
+ ipu_cm_write(ipu, int_stat,
+ IPU_INT_STAT(ipu->devtype, err_reg[i]));
+ dev_warn(ipu->dev,
+ "IPU Warning - IPU_INT_STAT_%d = 0x%08X\n",
+ err_reg[i], int_stat);
+ /* Disable interrupts so we only get error once */
+ int_stat = ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i])) &
+ ~int_stat;
+ ipu_cm_write(ipu, int_stat, IPU_INT_CTRL(err_reg[i]));
+ }
+ }
+
+ spin_unlock(&ipu->int_reg_spin_lock);
+
+ return IRQ_HANDLED;
+}
+
+/*!
+ * This function enables the interrupt for the specified interrupt line.
+ * The interrupt lines are defined in \b ipu_irq_line enum.
+ *
+ * @param ipu ipu handler
+ * @param irq Interrupt line to enable interrupt for.
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq)
+{
+ uint32_t reg;
+ unsigned long lock_flags;
+ int ret = 0;
+
+ _ipu_get(ipu);
+
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
+
+ /*
+ * Check sync interrupt handler only, since we do nothing for
+ * error interrupts but than print out register values in the
+ * error interrupt source handler.
+ */
+ if (_ipu_is_sync_irq(irq) && (ipu->irq_list[irq].handler == NULL)) {
+ dev_err(ipu->dev, "handler hasn't been registered on sync "
+ "irq %d\n", irq);
+ ret = -EACCES;
+ goto out;
+ }
+
+ reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
+ reg |= IPUIRQ_2_MASK(irq);
+ ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
+out:
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
+
+ _ipu_put(ipu);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_enable_irq);
+
+/*!
+ * This function disables the interrupt for the specified interrupt line.
+ * The interrupt lines are defined in \b ipu_irq_line enum.
+ *
+ * @param ipu ipu handler
+ * @param irq Interrupt line to disable interrupt for.
+ *
+ */
+void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq)
+{
+ uint32_t reg;
+ unsigned long lock_flags;
+
+ _ipu_get(ipu);
+
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
+
+ reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
+ reg &= ~IPUIRQ_2_MASK(irq);
+ ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
+
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
+
+ _ipu_put(ipu);
+}
+EXPORT_SYMBOL(ipu_disable_irq);
+
+/*!
+ * This function clears the interrupt for the specified interrupt line.
+ * The interrupt lines are defined in \b ipu_irq_line enum.
+ *
+ * @param ipu ipu handler
+ * @param irq Interrupt line to clear interrupt for.
+ *
+ */
+void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq)
+{
+ unsigned long lock_flags;
+
+ _ipu_get(ipu);
+
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
+
+ ipu_cm_write(ipu, IPUIRQ_2_MASK(irq),
+ IPUIRQ_2_STATREG(ipu->devtype, irq));
+
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
+
+ _ipu_put(ipu);
+}
+EXPORT_SYMBOL(ipu_clear_irq);
+
+/*!
+ * This function returns the current interrupt status for the specified
+ * interrupt line. The interrupt lines are defined in \b ipu_irq_line enum.
+ *
+ * @param ipu ipu handler
+ * @param irq Interrupt line to get status for.
+ *
+ * @return Returns true if the interrupt is pending/asserted or false if
+ * the interrupt is not pending.
+ */
+bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq)
+{
+ uint32_t reg;
+ unsigned long lock_flags;
+
+ _ipu_get(ipu);
+
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
+ reg = ipu_cm_read(ipu, IPUIRQ_2_STATREG(ipu->devtype, irq));
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
+
+ _ipu_put(ipu);
+
+ if (reg & IPUIRQ_2_MASK(irq))
+ return true;
+ else
+ return false;
+}
+EXPORT_SYMBOL(ipu_get_irq_status);
+
+/*!
+ * This function registers an interrupt handler function for the specified
+ * interrupt line. The interrupt lines are defined in \b ipu_irq_line enum.
+ *
+ * @param ipu ipu handler
+ * @param irq Interrupt line to get status for.
+ *
+ * @param handler Input parameter for address of the handler
+ * function.
+ *
+ * @param irq_flags Flags for interrupt mode. Currently not used.
+ *
+ * @param devname Input parameter for string name of driver
+ * registering the handler.
+ *
+ * @param dev_id Input parameter for pointer of data to be
+ * passed to the handler.
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
+ irqreturn_t(*handler) (int, void *),
+ uint32_t irq_flags, const char *devname, void *dev_id)
+{
+ uint32_t reg;
+ unsigned long lock_flags;
+ int ret = 0;
+
+ BUG_ON(irq >= IPU_IRQ_COUNT);
+
+ _ipu_get(ipu);
+
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
+
+ if (ipu->irq_list[irq].handler != NULL) {
+ dev_err(ipu->dev,
+ "handler already installed on irq %d\n", irq);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Check sync interrupt handler only, since we do nothing for
+ * error interrupts but than print out register values in the
+ * error interrupt source handler.
+ */
+ if (_ipu_is_sync_irq(irq) && (handler == NULL)) {
+ dev_err(ipu->dev, "handler is NULL for sync irq %d\n", irq);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ipu->irq_list[irq].handler = handler;
+ ipu->irq_list[irq].flags = irq_flags;
+ ipu->irq_list[irq].dev_id = dev_id;
+ ipu->irq_list[irq].name = devname;
+
+ /* clear irq stat for previous use */
+ ipu_cm_write(ipu, IPUIRQ_2_MASK(irq),
+ IPUIRQ_2_STATREG(ipu->devtype, irq));
+ /* enable the interrupt */
+ reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
+ reg |= IPUIRQ_2_MASK(irq);
+ ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
+out:
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
+
+ _ipu_put(ipu);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_request_irq);
+
+/*!
+ * This function unregisters an interrupt handler for the specified interrupt
+ * line. The interrupt lines are defined in \b ipu_irq_line enum.
+ *
+ * @param ipu ipu handler
+ * @param irq Interrupt line to get status for.
+ *
+ * @param dev_id Input parameter for pointer of data to be passed
+ * to the handler. This must match value passed to
+ * ipu_request_irq().
+ *
+ */
+void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id)
+{
+ uint32_t reg;
+ unsigned long lock_flags;
+
+ _ipu_get(ipu);
+
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
+
+ /* disable the interrupt */
+ reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
+ reg &= ~IPUIRQ_2_MASK(irq);
+ ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
+ if (ipu->irq_list[irq].dev_id == dev_id)
+ memset(&ipu->irq_list[irq], 0, sizeof(ipu->irq_list[irq]));
+
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
+
+ _ipu_put(ipu);
+}
+EXPORT_SYMBOL(ipu_free_irq);
+
+uint32_t ipu_get_cur_buffer_idx(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type)
+{
+ uint32_t reg, dma_chan;
+
+ dma_chan = channel_2_dma(channel, type);
+ if (!idma_is_valid(dma_chan))
+ return -EINVAL;
+
+ reg = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(ipu->devtype, dma_chan));
+ if ((reg & idma_mask(dma_chan)) && _ipu_is_trb_chan(ipu, dma_chan)) {
+ reg = ipu_cm_read(ipu,
+ IPU_CHA_TRIPLE_CUR_BUF(ipu->devtype, dma_chan));
+ return (reg & tri_cur_buf_mask(dma_chan)) >>
+ tri_cur_buf_shift(dma_chan);
+ } else {
+ reg = ipu_cm_read(ipu, IPU_CHA_CUR_BUF(ipu->devtype, dma_chan));
+ if (reg & idma_mask(dma_chan))
+ return 1;
+ else
+ return 0;
+ }
+}
+EXPORT_SYMBOL(ipu_get_cur_buffer_idx);
+
+uint32_t _ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ uint32_t stat = 0;
+ uint32_t task_stat_reg = ipu_cm_read(ipu,
+ IPU_PROC_TASK_STAT(ipu->devtype));
+
+ switch (channel) {
+ case MEM_PRP_VF_MEM:
+ stat = (task_stat_reg & TSTAT_VF_MASK) >> TSTAT_VF_OFFSET;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ stat = (task_stat_reg & TSTAT_VF_MASK) >> TSTAT_VF_OFFSET;
+ break;
+ case MEM_ROT_VF_MEM:
+ stat =
+ (task_stat_reg & TSTAT_VF_ROT_MASK) >> TSTAT_VF_ROT_OFFSET;
+ break;
+ case MEM_PRP_ENC_MEM:
+ stat = (task_stat_reg & TSTAT_ENC_MASK) >> TSTAT_ENC_OFFSET;
+ break;
+ case MEM_ROT_ENC_MEM:
+ stat =
+ (task_stat_reg & TSTAT_ENC_ROT_MASK) >>
+ TSTAT_ENC_ROT_OFFSET;
+ break;
+ case MEM_PP_MEM:
+ stat = (task_stat_reg & TSTAT_PP_MASK) >> TSTAT_PP_OFFSET;
+ break;
+ case MEM_ROT_PP_MEM:
+ stat =
+ (task_stat_reg & TSTAT_PP_ROT_MASK) >> TSTAT_PP_ROT_OFFSET;
+ break;
+
+ default:
+ stat = TASK_STAT_IDLE;
+ break;
+ }
+ return stat;
+}
+
+/*!
+ * This function check for a logical channel status
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @return This function returns 0 on idle and 1 on busy.
+ *
+ */
+uint32_t ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ uint32_t dma_status;
+
+ _ipu_get(ipu);
+ mutex_lock(&ipu->mutex_lock);
+ dma_status = ipu_is_channel_busy(ipu, channel);
+ mutex_unlock(&ipu->mutex_lock);
+ _ipu_put(ipu);
+
+ dev_dbg(ipu->dev, "%s, dma_status:%d.\n", __func__, dma_status);
+
+ return dma_status;
+}
+EXPORT_SYMBOL(ipu_channel_status);
+
+int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch)
+{
+ uint32_t reg;
+ unsigned long lock_flags;
+ int from_dma = channel_2_dma(from_ch, IPU_INPUT_BUFFER);
+ int to_dma = channel_2_dma(to_ch, IPU_INPUT_BUFFER);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ /* enable target channel */
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(to_dma));
+ ipu_idmac_write(ipu, reg | idma_mask(to_dma), IDMAC_CHA_EN(to_dma));
+
+ ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(to_ch);
+
+ /* switch dp dc */
+ _ipu_dp_dc_disable(ipu, from_ch, true);
+
+ /* disable source channel */
+ reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(from_dma));
+ ipu_idmac_write(ipu, reg & ~idma_mask(from_dma), IDMAC_CHA_EN(from_dma));
+ ipu_cm_write(ipu, idma_mask(from_dma),
+ IPU_CHA_CUR_BUF(ipu->devtype, from_dma));
+ ipu_cm_write(ipu, tri_cur_buf_mask(from_dma),
+ IPU_CHA_TRIPLE_CUR_BUF(ipu->devtype, from_dma));
+
+ ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(from_ch));
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
+ _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 0);
+ _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 1);
+ _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 2);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_swap_channel);
+
+uint32_t bytes_per_pixel(uint32_t fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_GENERIC: /*generic data */
+ case IPU_PIX_FMT_RGB332:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YUV444P:
+ case IPU_PIX_FMT_NV12:
+ case PRE_PIX_FMT_NV21:
+ case IPU_PIX_FMT_NV16:
+ case PRE_PIX_FMT_NV61:
+ return 1;
+ break;
+ case IPU_PIX_FMT_GENERIC_16: /* generic data */
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_BGRA4444:
+ case IPU_PIX_FMT_BGRA5551:
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_UYVY:
+ case IPU_PIX_FMT_GPU16_SB_ST:
+ case IPU_PIX_FMT_GPU16_SB_SRT:
+ case IPU_PIX_FMT_GPU16_ST:
+ case IPU_PIX_FMT_GPU16_SRT:
+ return 2;
+ break;
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_YUV444:
+ return 3;
+ break;
+ case IPU_PIX_FMT_GENERIC_32: /*generic data */
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_RGB32:
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_ABGR32:
+ case IPU_PIX_FMT_GPU32_SB_ST:
+ case IPU_PIX_FMT_GPU32_SB_SRT:
+ case IPU_PIX_FMT_GPU32_ST:
+ case IPU_PIX_FMT_GPU32_SRT:
+ case IPU_PIX_FMT_AYUV:
+ return 4;
+ break;
+ default:
+ return 1;
+ break;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(bytes_per_pixel);
+
+ipu_color_space_t format_to_colorspace(uint32_t fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_RGB666:
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_BGRA4444:
+ case IPU_PIX_FMT_BGRA5551:
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_GBR24:
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_RGB32:
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_ABGR32:
+ case IPU_PIX_FMT_LVDS666:
+ case IPU_PIX_FMT_LVDS888:
+ case IPU_PIX_FMT_GPU32_SB_ST:
+ case IPU_PIX_FMT_GPU32_SB_SRT:
+ case IPU_PIX_FMT_GPU32_ST:
+ case IPU_PIX_FMT_GPU32_SRT:
+ case IPU_PIX_FMT_GPU16_SB_ST:
+ case IPU_PIX_FMT_GPU16_SB_SRT:
+ case IPU_PIX_FMT_GPU16_ST:
+ case IPU_PIX_FMT_GPU16_SRT:
+ return RGB;
+ break;
+
+ default:
+ return YCbCr;
+ break;
+ }
+ return RGB;
+}
+EXPORT_SYMBOL(format_to_colorspace);
+
+bool ipu_pixel_format_has_alpha(uint32_t fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_ABGR32:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+ return false;
+}
+
+bool ipu_ch_param_bad_alpha_pos(uint32_t pixel_fmt)
+{
+ return _ipu_ch_param_bad_alpha_pos(pixel_fmt);
+}
+EXPORT_SYMBOL(ipu_ch_param_bad_alpha_pos);
+
+bool ipu_pixel_format_is_gpu_tile(uint32_t fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_GPU32_SB_ST:
+ case IPU_PIX_FMT_GPU32_SB_SRT:
+ case IPU_PIX_FMT_GPU32_ST:
+ case IPU_PIX_FMT_GPU32_SRT:
+ case IPU_PIX_FMT_GPU16_SB_ST:
+ case IPU_PIX_FMT_GPU16_SB_SRT:
+ case IPU_PIX_FMT_GPU16_ST:
+ case IPU_PIX_FMT_GPU16_SRT:
+ return true;
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL(ipu_pixel_format_is_gpu_tile);
+
+bool ipu_pixel_format_is_split_gpu_tile(uint32_t fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_GPU32_SB_ST:
+ case IPU_PIX_FMT_GPU32_SB_SRT:
+ case IPU_PIX_FMT_GPU16_SB_ST:
+ case IPU_PIX_FMT_GPU16_SB_SRT:
+ return true;
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL(ipu_pixel_format_is_split_gpu_tile);
+
+bool ipu_pixel_format_is_pre_yuv(uint32_t fmt)
+{
+ switch (fmt) {
+ case PRE_PIX_FMT_NV21:
+ case PRE_PIX_FMT_NV61:
+ return true;
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL(ipu_pixel_format_is_pre_yuv);
+
+bool ipu_pixel_format_is_multiplanar_yuv(uint32_t fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_YVU410P:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YVU422P:
+ case IPU_PIX_FMT_YUV444P:
+ case IPU_PIX_FMT_NV12:
+ case PRE_PIX_FMT_NV21:
+ case IPU_PIX_FMT_NV16:
+ case PRE_PIX_FMT_NV61:
+ return true;
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL(ipu_pixel_format_is_multiplanar_yuv);
+
+int ipu_ch_param_get_axi_id(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type)
+{
+ uint32_t dma_chan = channel_2_dma(channel, type);
+ int axi_id;
+
+ if (!idma_is_valid(dma_chan))
+ return -EINVAL;
+
+ _ipu_get(ipu);
+ mutex_lock(&ipu->mutex_lock);
+ axi_id = _ipu_ch_param_get_axi_id(ipu, dma_chan);
+ mutex_unlock(&ipu->mutex_lock);
+ _ipu_put(ipu);
+
+ return axi_id;
+}
+EXPORT_SYMBOL(ipu_ch_param_get_axi_id);
+
+#ifdef CONFIG_PM
+int ipu_runtime_suspend(struct device *dev)
+{
+ release_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "ipu busfreq high release.\n");
+
+ return 0;
+}
+
+int ipu_runtime_resume(struct device *dev)
+{
+ request_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "ipu busfreq high requst.\n");
+
+ return 0;
+}
+
+static const struct dev_pm_ops ipu_pm_ops = {
+ SET_RUNTIME_PM_OPS(ipu_runtime_suspend, ipu_runtime_resume, NULL)
+};
+#endif
+
+/*!
+ * This structure contains pointers to the power management callback functions.
+ */
+static struct platform_driver mxcipu_driver = {
+ .driver = {
+ .name = "imx-ipuv3",
+ .of_match_table = imx_ipuv3_dt_ids,
+ #ifdef CONFIG_PM
+ .pm = &ipu_pm_ops,
+ #endif
+ },
+ .probe = ipu_probe,
+ .remove = ipu_remove,
+};
+
+int32_t __init ipu_gen_init(void)
+{
+ int32_t ret;
+
+ ret = platform_driver_register(&mxcipu_driver);
+ return 0;
+}
+
+subsys_initcall(ipu_gen_init);
+
+static void __exit ipu_gen_uninit(void)
+{
+ platform_driver_unregister(&mxcipu_driver);
+}
+
+module_exit(ipu_gen_uninit);
diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c
new file mode 100644
index 000000000000..c6cfc97a0923
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_device.c
@@ -0,0 +1,3750 @@
+/*
+ * Copyright 2005-2015 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 ipu_device.c
+ *
+ * @brief This file contains the IPUv3 driver device interface and fops functions.
+ *
+ * @ingroup IPU
+ */
+#include <linux/clk.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ipu-v3.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/sched/rt.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+
+#include <asm/cacheflush.h>
+#include <asm/outercache.h>
+
+#include "ipu_param_mem.h"
+#include "ipu_regs.h"
+#include "vdoa.h"
+
+#define CHECK_RETCODE(cont, str, err, label, ret) \
+do { \
+ if (cont) { \
+ dev_err(t->dev, "ERR:[0x%p]-no:0x%x "#str" ret:%d," \
+ "line:%d\n", t, t->task_no, ret, __LINE__);\
+ if (ret != -EACCES) { \
+ t->state = err; \
+ goto label; \
+ } \
+ } \
+} while (0)
+
+#define CHECK_RETCODE_CONT(cont, str, err, ret) \
+do { \
+ if (cont) { \
+ dev_err(t->dev, "ERR:[0x%p]-no:0x%x"#str" ret:%d," \
+ "line:%d\n", t, t->task_no, ret, __LINE__);\
+ if (ret != -EACCES) { \
+ if (t->state == STATE_OK) \
+ t->state = err; \
+ } \
+ } \
+} while (0)
+
+#undef DBG_IPU_PERF
+#ifdef DBG_IPU_PERF
+#define CHECK_PERF(ts) \
+do { \
+ getnstimeofday(ts); \
+} while (0)
+
+#define DECLARE_PERF_VAR \
+ struct timespec ts_queue; \
+ struct timespec ts_dotask; \
+ struct timespec ts_waitirq; \
+ struct timespec ts_sche; \
+ struct timespec ts_rel; \
+ struct timespec ts_frame
+
+#define PRINT_TASK_STATISTICS \
+do { \
+ ts_queue = timespec_sub(tsk->ts_dotask, tsk->ts_queue); \
+ ts_dotask = timespec_sub(tsk->ts_waitirq, tsk->ts_dotask); \
+ ts_waitirq = timespec_sub(tsk->ts_inirq, tsk->ts_waitirq); \
+ ts_sche = timespec_sub(tsk->ts_wakeup, tsk->ts_inirq); \
+ ts_rel = timespec_sub(tsk->ts_rel, tsk->ts_wakeup); \
+ ts_frame = timespec_sub(tsk->ts_rel, tsk->ts_queue); \
+ dev_dbg(tsk->dev, "[0x%p] no-0x%x, ts_q:%ldus, ts_do:%ldus," \
+ "ts_waitirq:%ldus,ts_sche:%ldus, ts_rel:%ldus," \
+ "ts_frame: %ldus\n", tsk, tsk->task_no, \
+ ts_queue.tv_nsec / NSEC_PER_USEC + ts_queue.tv_sec * USEC_PER_SEC,\
+ ts_dotask.tv_nsec / NSEC_PER_USEC + ts_dotask.tv_sec * USEC_PER_SEC,\
+ ts_waitirq.tv_nsec / NSEC_PER_USEC + ts_waitirq.tv_sec * USEC_PER_SEC,\
+ ts_sche.tv_nsec / NSEC_PER_USEC + ts_sche.tv_sec * USEC_PER_SEC,\
+ ts_rel.tv_nsec / NSEC_PER_USEC + ts_rel.tv_sec * USEC_PER_SEC,\
+ ts_frame.tv_nsec / NSEC_PER_USEC + ts_frame.tv_sec * USEC_PER_SEC); \
+ if ((ts_frame.tv_nsec/NSEC_PER_USEC + ts_frame.tv_sec*USEC_PER_SEC) > \
+ 80000) \
+ dev_dbg(tsk->dev, "ts_frame larger than 80ms [0x%p] no-0x%x.\n"\
+ , tsk, tsk->task_no); \
+} while (0)
+#else
+#define CHECK_PERF(ts)
+#define DECLARE_PERF_VAR
+#define PRINT_TASK_STATISTICS
+#endif
+
+#define IPU_PP_CH_VF (IPU_TASK_ID_VF - 1)
+#define IPU_PP_CH_PP (IPU_TASK_ID_PP - 1)
+#define MAX_PP_CH (IPU_TASK_ID_MAX - 1)
+#define VDOA_DEF_TIMEOUT_MS (HZ/2)
+
+/* Strucutures and variables for exporting MXC IPU as device*/
+typedef enum {
+ STATE_OK = 0,
+ STATE_QUEUE,
+ STATE_IN_PROGRESS,
+ STATE_ERR,
+ STATE_TIMEOUT,
+ STATE_RES_TIMEOUT,
+ STATE_NO_IPU,
+ STATE_NO_IRQ,
+ STATE_IPU_BUSY,
+ STATE_IRQ_FAIL,
+ STATE_IRQ_TIMEOUT,
+ STATE_ENABLE_CHAN_FAIL,
+ STATE_DISABLE_CHAN_FAIL,
+ STATE_SEL_BUF_FAIL,
+ STATE_INIT_CHAN_FAIL,
+ STATE_LINK_CHAN_FAIL,
+ STATE_UNLINK_CHAN_FAIL,
+ STATE_INIT_CHAN_BUF_FAIL,
+ STATE_INIT_CHAN_BAND_FAIL,
+ STATE_SYS_NO_MEM,
+ STATE_VDOA_IRQ_TIMEOUT,
+ STATE_VDOA_IRQ_FAIL,
+ STATE_VDOA_TASK_FAIL,
+} ipu_state_t;
+
+enum {
+ INPUT_CHAN_VDI_P = 1,
+ INPUT_CHAN,
+ INPUT_CHAN_VDI_N,
+};
+
+struct ipu_state_msg {
+ int state;
+ char *msg;
+} state_msg[] = {
+ {STATE_OK, "ok"},
+ {STATE_QUEUE, "split queue"},
+ {STATE_IN_PROGRESS, "split in progress"},
+ {STATE_ERR, "error"},
+ {STATE_TIMEOUT, "split task timeout"},
+ {STATE_RES_TIMEOUT, "wait resource timeout"},
+ {STATE_NO_IPU, "no ipu found"},
+ {STATE_NO_IRQ, "no irq found for task"},
+ {STATE_IPU_BUSY, "ipu busy"},
+ {STATE_IRQ_FAIL, "request irq failed"},
+ {STATE_IRQ_TIMEOUT, "wait for irq timeout"},
+ {STATE_ENABLE_CHAN_FAIL, "ipu enable channel fail"},
+ {STATE_DISABLE_CHAN_FAIL, "ipu disable channel fail"},
+ {STATE_SEL_BUF_FAIL, "ipu select buf fail"},
+ {STATE_INIT_CHAN_FAIL, "ipu init channel fail"},
+ {STATE_LINK_CHAN_FAIL, "ipu link channel fail"},
+ {STATE_UNLINK_CHAN_FAIL, "ipu unlink channel fail"},
+ {STATE_INIT_CHAN_BUF_FAIL, "ipu init channel buffer fail"},
+ {STATE_INIT_CHAN_BAND_FAIL, "ipu init channel band mode fail"},
+ {STATE_SYS_NO_MEM, "sys no mem: -ENOMEM"},
+ {STATE_VDOA_IRQ_TIMEOUT, "wait for vdoa irq timeout"},
+ {STATE_VDOA_IRQ_FAIL, "vdoa irq fail"},
+ {STATE_VDOA_TASK_FAIL, "vdoa task fail"},
+};
+
+struct stripe_setting {
+ u32 iw;
+ u32 ih;
+ u32 ow;
+ u32 oh;
+ u32 outh_resize_ratio;
+ u32 outv_resize_ratio;
+ u32 i_left_pos;
+ u32 i_right_pos;
+ u32 i_top_pos;
+ u32 i_bottom_pos;
+ u32 o_left_pos;
+ u32 o_right_pos;
+ u32 o_top_pos;
+ u32 o_bottom_pos;
+ u32 rl_split_line;
+ u32 ud_split_line;
+};
+
+struct task_set {
+#define NULL_MODE 0x0
+#define IC_MODE 0x1
+#define ROT_MODE 0x2
+#define VDI_MODE 0x4
+#define IPU_PREPROCESS_MODE_MASK (IC_MODE | ROT_MODE | VDI_MODE)
+/* VDOA_MODE means this task use vdoa, and VDOA has two modes:
+ * BAND MODE and non-BAND MODE. Non-band mode will do transfer data
+ * to memory. BAND mode needs hareware sync with IPU, it is used default
+ * if connected to VDIC.
+ */
+#define VDOA_MODE 0x8
+#define VDOA_BAND_MODE 0x10
+ u8 mode;
+#define IC_VF 0x1
+#define IC_PP 0x2
+#define ROT_VF 0x4
+#define ROT_PP 0x8
+#define VDI_VF 0x10
+#define VDOA_ONLY 0x20
+ u8 task;
+#define NO_SPLIT 0x0
+#define RL_SPLIT 0x1
+#define UD_SPLIT 0x2
+#define LEFT_STRIPE 0x1
+#define RIGHT_STRIPE 0x2
+#define UP_STRIPE 0x4
+#define DOWN_STRIPE 0x8
+#define SPLIT_MASK 0xF
+ u8 split_mode;
+ u8 band_lines;
+ ipu_channel_t ic_chan;
+ ipu_channel_t rot_chan;
+ ipu_channel_t vdi_ic_p_chan;
+ ipu_channel_t vdi_ic_n_chan;
+
+ u32 i_off;
+ u32 i_uoff;
+ u32 i_voff;
+ u32 istride;
+
+ u32 ov_off;
+ u32 ov_uoff;
+ u32 ov_voff;
+ u32 ovstride;
+
+ u32 ov_alpha_off;
+ u32 ov_alpha_stride;
+
+ u32 o_off;
+ u32 o_uoff;
+ u32 o_voff;
+ u32 ostride;
+
+ u32 r_fmt;
+ u32 r_width;
+ u32 r_height;
+ u32 r_stride;
+ dma_addr_t r_paddr;
+
+ struct stripe_setting sp_setting;
+};
+
+struct ipu_split_task {
+ struct ipu_task task;
+ struct ipu_task_entry *parent_task;
+ struct ipu_task_entry *child_task;
+ u32 task_no;
+};
+
+struct ipu_task_entry {
+ struct ipu_input input;
+ struct ipu_output output;
+
+ bool overlay_en;
+ struct ipu_overlay overlay;
+#define DEF_TIMEOUT_MS 1000
+#define DEF_DELAY_MS 20
+ int timeout;
+ int irq;
+
+ u8 task_id;
+ u8 ipu_id;
+ u8 task_in_list;
+ u8 split_done;
+ struct mutex split_lock;
+ struct mutex vdic_lock;
+ wait_queue_head_t split_waitq;
+
+ struct list_head node;
+ struct list_head split_list;
+ struct ipu_soc *ipu;
+ struct device *dev;
+ struct task_set set;
+ wait_queue_head_t task_waitq;
+ struct completion irq_comp;
+ struct kref refcount;
+ ipu_state_t state;
+ u32 task_no;
+ atomic_t done;
+ atomic_t res_free;
+ atomic_t res_get;
+
+ struct ipu_task_entry *parent;
+ char *vditmpbuf[2];
+ u32 old_save_lines;
+ u32 old_size;
+ bool buf1filled;
+ bool buf0filled;
+
+ vdoa_handle_t vdoa_handle;
+ struct vdoa_output_mem {
+ void *vaddr;
+ dma_addr_t paddr;
+ int size;
+ } vdoa_dma;
+
+#ifdef DBG_IPU_PERF
+ struct timespec ts_queue;
+ struct timespec ts_dotask;
+ struct timespec ts_waitirq;
+ struct timespec ts_inirq;
+ struct timespec ts_wakeup;
+ struct timespec ts_rel;
+#endif
+};
+
+struct ipu_channel_tabel {
+ struct mutex lock;
+ u8 used[MXC_IPU_MAX_NUM][MAX_PP_CH];
+ u8 vdoa_used;
+};
+
+struct ipu_thread_data {
+ struct ipu_soc *ipu;
+ u32 id;
+ u32 is_vdoa;
+};
+
+struct ipu_alloc_list {
+ struct list_head list;
+ dma_addr_t phy_addr;
+ void *cpu_addr;
+ u32 size;
+ void *file_index;
+};
+
+static LIST_HEAD(ipu_alloc_list);
+static DEFINE_MUTEX(ipu_alloc_lock);
+static struct ipu_channel_tabel ipu_ch_tbl;
+static LIST_HEAD(ipu_task_list);
+static DEFINE_SPINLOCK(ipu_task_list_lock);
+static DECLARE_WAIT_QUEUE_HEAD(thread_waitq);
+static DECLARE_WAIT_QUEUE_HEAD(res_waitq);
+static atomic_t req_cnt;
+static atomic_t file_index = ATOMIC_INIT(1);
+static int major;
+static int max_ipu_no;
+static int thread_id;
+static atomic_t frame_no;
+static struct class *ipu_class;
+static struct device *ipu_dev;
+static int debug;
+module_param(debug, int, 0600);
+#ifdef DBG_IPU_PERF
+static struct timespec ts_frame_max;
+static u32 ts_frame_avg;
+static atomic_t frame_cnt;
+#endif
+
+static bool deinterlace_3_field(struct ipu_task_entry *t)
+{
+ return ((t->set.mode & VDI_MODE) &&
+ (t->input.deinterlace.motion != HIGH_MOTION));
+}
+
+static u32 tiled_filed_size(struct ipu_task_entry *t)
+{
+ u32 field_size;
+
+ /* note: page_align is required by VPU hw ouput buffer */
+ field_size = TILED_NV12_FRAME_SIZE(t->input.width, t->input.height/2);
+ return field_size;
+}
+
+static bool only_ic(u8 mode)
+{
+ mode = mode & IPU_PREPROCESS_MODE_MASK;
+ return ((mode == IC_MODE) || (mode == VDI_MODE));
+}
+
+static bool only_rot(u8 mode)
+{
+ mode = mode & IPU_PREPROCESS_MODE_MASK;
+ return (mode == ROT_MODE);
+}
+
+static bool ic_and_rot(u8 mode)
+{
+ mode = mode & IPU_PREPROCESS_MODE_MASK;
+ return ((mode == (IC_MODE | ROT_MODE)) ||
+ (mode == (VDI_MODE | ROT_MODE)));
+}
+
+static bool need_split(struct ipu_task_entry *t)
+{
+ return ((t->set.split_mode != NO_SPLIT) || (t->task_no & SPLIT_MASK));
+}
+
+unsigned int fmt_to_bpp(unsigned int pixelformat)
+{
+ u32 bpp;
+
+ switch (pixelformat) {
+ case IPU_PIX_FMT_RGB565:
+ /*interleaved 422*/
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_UYVY:
+ /*non-interleaved 422*/
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YVU422P:
+ bpp = 16;
+ break;
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_YUV444:
+ case IPU_PIX_FMT_YUV444P:
+ bpp = 24;
+ break;
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_RGB32:
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_ABGR32:
+ bpp = 32;
+ break;
+ /*non-interleaved 420*/
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_NV12:
+ bpp = 12;
+ break;
+ default:
+ bpp = 8;
+ break;
+ }
+ return bpp;
+}
+EXPORT_SYMBOL_GPL(fmt_to_bpp);
+
+cs_t colorspaceofpixel(int fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_RGB666:
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_RGB32:
+ case IPU_PIX_FMT_ABGR32:
+ return RGB_CS;
+ break;
+ case IPU_PIX_FMT_UYVY:
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_YVU422P:
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YUV444:
+ case IPU_PIX_FMT_YUV444P:
+ case IPU_PIX_FMT_NV12:
+ case IPU_PIX_FMT_TILED_NV12:
+ case IPU_PIX_FMT_TILED_NV12F:
+ return YUV_CS;
+ break;
+ default:
+ return NULL_CS;
+ }
+}
+EXPORT_SYMBOL_GPL(colorspaceofpixel);
+
+int need_csc(int ifmt, int ofmt)
+{
+ cs_t ics, ocs;
+
+ ics = colorspaceofpixel(ifmt);
+ ocs = colorspaceofpixel(ofmt);
+
+ if ((ics == NULL_CS) || (ocs == NULL_CS))
+ return -1;
+ else if (ics != ocs)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(need_csc);
+
+static int soc_max_in_width(u32 is_vdoa)
+{
+ return is_vdoa ? 8192 : 4096;
+}
+
+static int soc_max_vdi_in_width(struct ipu_soc *ipu)
+{
+ int i;
+
+ if (!ipu) {
+ for (i = 0; i < max_ipu_no; i++) {
+ ipu = ipu_get_soc(i);
+ if (!IS_ERR_OR_NULL(ipu))
+ break;
+ }
+
+ if (i == max_ipu_no)
+ return 720;
+ }
+ return IPU_MAX_VDI_IN_WIDTH(ipu->devtype);
+}
+static int soc_max_in_height(void)
+{
+ return 4096;
+}
+
+static int soc_max_out_width(void)
+{
+ /* mx51/mx53/mx6q is 1024*/
+ return 1024;
+}
+
+static int soc_max_out_height(void)
+{
+ /* mx51/mx53/mx6q is 1024*/
+ return 1024;
+}
+
+static void dump_task_info(struct ipu_task_entry *t)
+{
+ if (!debug)
+ return;
+ dev_dbg(t->dev, "[0x%p]input:\n", (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->input.format);
+ dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->input.width);
+ dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->input.height);
+ dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n", (void *)t, t->input.crop.w);
+ dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n", (void *)t, t->input.crop.h);
+ dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
+ (void *)t, t->input.crop.pos.x);
+ dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
+ (void *)t, t->input.crop.pos.y);
+ dev_dbg(t->dev, "[0x%p]input buffer:\n", (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->input.paddr);
+ dev_dbg(t->dev, "[0x%p]\ti_off = 0x%x\n", (void *)t, t->set.i_off);
+ dev_dbg(t->dev, "[0x%p]\ti_uoff = 0x%x\n", (void *)t, t->set.i_uoff);
+ dev_dbg(t->dev, "[0x%p]\ti_voff = 0x%x\n", (void *)t, t->set.i_voff);
+ dev_dbg(t->dev, "[0x%p]\tistride = %d\n", (void *)t, t->set.istride);
+ if (t->input.deinterlace.enable) {
+ dev_dbg(t->dev, "[0x%p]deinterlace enabled with:\n", (void *)t);
+ if (t->input.deinterlace.motion != HIGH_MOTION) {
+ dev_dbg(t->dev, "[0x%p]\tlow/medium motion\n", (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tpaddr_n = 0x%x\n",
+ (void *)t, t->input.paddr_n);
+ } else
+ dev_dbg(t->dev, "[0x%p]\thigh motion\n", (void *)t);
+ }
+
+ dev_dbg(t->dev, "[0x%p]output:\n", (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->output.format);
+ dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->output.width);
+ dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->output.height);
+ dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n", (void *)t, t->output.crop.w);
+ dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n", (void *)t, t->output.crop.h);
+ dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
+ (void *)t, t->output.crop.pos.x);
+ dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
+ (void *)t, t->output.crop.pos.y);
+ dev_dbg(t->dev, "[0x%p]\trotate = %d\n", (void *)t, t->output.rotate);
+ dev_dbg(t->dev, "[0x%p]output buffer:\n", (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->output.paddr);
+ dev_dbg(t->dev, "[0x%p]\to_off = 0x%x\n", (void *)t, t->set.o_off);
+ dev_dbg(t->dev, "[0x%p]\to_uoff = 0x%x\n", (void *)t, t->set.o_uoff);
+ dev_dbg(t->dev, "[0x%p]\to_voff = 0x%x\n", (void *)t, t->set.o_voff);
+ dev_dbg(t->dev, "[0x%p]\tostride = %d\n", (void *)t, t->set.ostride);
+
+ if (t->overlay_en) {
+ dev_dbg(t->dev, "[0x%p]overlay:\n", (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n",
+ (void *)t, t->overlay.format);
+ dev_dbg(t->dev, "[0x%p]\twidth = %d\n",
+ (void *)t, t->overlay.width);
+ dev_dbg(t->dev, "[0x%p]\theight = %d\n",
+ (void *)t, t->overlay.height);
+ dev_dbg(t->dev, "[0x%p]\tcrop.w = %d\n",
+ (void *)t, t->overlay.crop.w);
+ dev_dbg(t->dev, "[0x%p]\tcrop.h = %d\n",
+ (void *)t, t->overlay.crop.h);
+ dev_dbg(t->dev, "[0x%p]\tcrop.pos.x = %d\n",
+ (void *)t, t->overlay.crop.pos.x);
+ dev_dbg(t->dev, "[0x%p]\tcrop.pos.y = %d\n",
+ (void *)t, t->overlay.crop.pos.y);
+ dev_dbg(t->dev, "[0x%p]overlay buffer:\n", (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n",
+ (void *)t, t->overlay.paddr);
+ dev_dbg(t->dev, "[0x%p]\tov_off = 0x%x\n",
+ (void *)t, t->set.ov_off);
+ dev_dbg(t->dev, "[0x%p]\tov_uoff = 0x%x\n",
+ (void *)t, t->set.ov_uoff);
+ dev_dbg(t->dev, "[0x%p]\tov_voff = 0x%x\n",
+ (void *)t, t->set.ov_voff);
+ dev_dbg(t->dev, "[0x%p]\tovstride = %d\n",
+ (void *)t, t->set.ovstride);
+ if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
+ dev_dbg(t->dev, "[0x%p]local alpha enabled with:\n",
+ (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n",
+ (void *)t, t->overlay.alpha.loc_alp_paddr);
+ dev_dbg(t->dev, "[0x%p]\tov_alpha_off = 0x%x\n",
+ (void *)t, t->set.ov_alpha_off);
+ dev_dbg(t->dev, "[0x%p]\tov_alpha_stride = %d\n",
+ (void *)t, t->set.ov_alpha_stride);
+ } else
+ dev_dbg(t->dev, "[0x%p]globle alpha enabled with value 0x%x\n",
+ (void *)t, t->overlay.alpha.gvalue);
+ if (t->overlay.colorkey.enable)
+ dev_dbg(t->dev, "[0x%p]colorkey enabled with value 0x%x\n",
+ (void *)t, t->overlay.colorkey.value);
+ }
+
+ dev_dbg(t->dev, "[0x%p]want task_id = %d\n", (void *)t, t->task_id);
+ dev_dbg(t->dev, "[0x%p]want task mode is 0x%x\n",
+ (void *)t, t->set.mode);
+ dev_dbg(t->dev, "[0x%p]\tIC_MODE = 0x%x\n", (void *)t, IC_MODE);
+ dev_dbg(t->dev, "[0x%p]\tROT_MODE = 0x%x\n", (void *)t, ROT_MODE);
+ dev_dbg(t->dev, "[0x%p]\tVDI_MODE = 0x%x\n", (void *)t, VDI_MODE);
+ dev_dbg(t->dev, "[0x%p]\tTask_no = 0x%x\n\n\n", (void *)t, t->task_no);
+}
+
+static void dump_check_err(struct device *dev, int err)
+{
+ switch (err) {
+ case IPU_CHECK_ERR_INPUT_CROP:
+ dev_err(dev, "input crop setting error\n");
+ break;
+ case IPU_CHECK_ERR_OUTPUT_CROP:
+ dev_err(dev, "output crop setting error\n");
+ break;
+ case IPU_CHECK_ERR_OVERLAY_CROP:
+ dev_err(dev, "overlay crop setting error\n");
+ break;
+ case IPU_CHECK_ERR_INPUT_OVER_LIMIT:
+ dev_err(dev, "input over limitation\n");
+ break;
+ case IPU_CHECK_ERR_OVERLAY_WITH_VDI:
+ dev_err(dev, "do not support overlay with deinterlace\n");
+ break;
+ case IPU_CHECK_ERR_OV_OUT_NO_FIT:
+ dev_err(dev,
+ "width/height of overlay and ic output should be same\n");
+ break;
+ case IPU_CHECK_ERR_PROC_NO_NEED:
+ dev_err(dev, "no ipu processing need\n");
+ break;
+ case IPU_CHECK_ERR_SPLIT_INPUTW_OVER:
+ dev_err(dev, "split mode input width overflow\n");
+ break;
+ case IPU_CHECK_ERR_SPLIT_INPUTH_OVER:
+ dev_err(dev, "split mode input height overflow\n");
+ break;
+ case IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER:
+ dev_err(dev, "split mode output width overflow\n");
+ break;
+ case IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER:
+ dev_err(dev, "split mode output height overflow\n");
+ break;
+ case IPU_CHECK_ERR_SPLIT_WITH_ROT:
+ dev_err(dev, "not support split mode with rotation\n");
+ break;
+ case IPU_CHECK_ERR_W_DOWNSIZE_OVER:
+ dev_err(dev, "horizontal downsizing ratio overflow\n");
+ break;
+ case IPU_CHECK_ERR_H_DOWNSIZE_OVER:
+ dev_err(dev, "vertical downsizing ratio overflow\n");
+ break;
+ default:
+ break;
+ }
+}
+
+static void dump_check_warn(struct device *dev, int warn)
+{
+ if (warn & IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN)
+ dev_warn(dev, "input u/v offset not 8 align\n");
+ if (warn & IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN)
+ dev_warn(dev, "output u/v offset not 8 align\n");
+ if (warn & IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN)
+ dev_warn(dev, "overlay u/v offset not 8 align\n");
+}
+
+static int set_crop(struct ipu_crop *crop, int width, int height, int fmt)
+{
+ if ((width == 0) || (height == 0)) {
+ pr_err("Invalid param: width=%d, height=%d\n", width, height);
+ return -EINVAL;
+ }
+
+ if ((IPU_PIX_FMT_TILED_NV12 == fmt) ||
+ (IPU_PIX_FMT_TILED_NV12F == fmt)) {
+ if (crop->w || crop->h) {
+ if (((crop->w + crop->pos.x) > width)
+ || ((crop->h + crop->pos.y) > height)
+ || (0 != (crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN))
+ || (0 != (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))
+ || (0 != (crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN))
+ || (0 != (crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN))
+ ) {
+ pr_err("set_crop error MB align.\n");
+ return -EINVAL;
+ }
+ } else {
+ crop->pos.x = 0;
+ crop->pos.y = 0;
+ crop->w = width;
+ crop->h = height;
+ if ((0 != (crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN))
+ || (0 != (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))) {
+ pr_err("set_crop error w/h MB align.\n");
+ return -EINVAL;
+ }
+ }
+ } else {
+ if (crop->w || crop->h) {
+ if (((crop->w + crop->pos.x) > (width + 16))
+ || ((crop->h + crop->pos.y) > height + 16)) {
+ pr_err("set_crop error exceeds width/height.\n");
+ return -EINVAL;
+ }
+ } else {
+ crop->pos.x = 0;
+ crop->pos.y = 0;
+ crop->w = width;
+ crop->h = height;
+ }
+ crop->w -= crop->w%8;
+ crop->h -= crop->h%8;
+ }
+
+ if ((crop->w == 0) || (crop->h == 0)) {
+ pr_err("Invalid crop param: crop.w=%d, crop.h=%d\n",
+ crop->w, crop->h);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void update_offset(unsigned int fmt,
+ unsigned int width, unsigned int height,
+ unsigned int pos_x, unsigned int pos_y,
+ int *off, int *uoff, int *voff, int *stride)
+{
+ /* NOTE: u v offset should based on start point of off*/
+ switch (fmt) {
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YUV420P:
+ *off = pos_y * width + pos_x;
+ *uoff = (width * (height - pos_y) - pos_x)
+ + (width/2) * (pos_y/2) + pos_x/2;
+ /* In case height is odd, round up to even */
+ *voff = *uoff + (width/2) * ((height+1)/2);
+ break;
+ case IPU_PIX_FMT_YVU420P:
+ *off = pos_y * width + pos_x;
+ *voff = (width * (height - pos_y) - pos_x)
+ + (width/2) * (pos_y/2) + pos_x/2;
+ /* In case height is odd, round up to even */
+ *uoff = *voff + (width/2) * ((height+1)/2);
+ break;
+ case IPU_PIX_FMT_YVU422P:
+ *off = pos_y * width + pos_x;
+ *voff = (width * (height - pos_y) - pos_x)
+ + (width/2) * pos_y + pos_x/2;
+ *uoff = *voff + (width/2) * height;
+ break;
+ case IPU_PIX_FMT_YUV422P:
+ *off = pos_y * width + pos_x;
+ *uoff = (width * (height - pos_y) - pos_x)
+ + (width/2) * pos_y + pos_x/2;
+ *voff = *uoff + (width/2) * height;
+ break;
+ case IPU_PIX_FMT_YUV444P:
+ *off = pos_y * width + pos_x;
+ *uoff = width * height;
+ *voff = width * height * 2;
+ break;
+ case IPU_PIX_FMT_NV12:
+ *off = pos_y * width + pos_x;
+ *uoff = (width * (height - pos_y) - pos_x)
+ + width * (pos_y/2) + pos_x;
+ break;
+ case IPU_PIX_FMT_TILED_NV12:
+ /*
+ * tiled format, progressive:
+ * assuming that line is aligned with MB height (aligned to 16)
+ * offset = line * stride + (pixel / MB_width) * pixels_in_MB
+ * = line * stride + (pixel / 16) * 256
+ * = line * stride + pixel * 16
+ */
+ *off = pos_y * width + (pos_x << 4);
+ *uoff = ALIGN(width * height, SZ_4K) + (*off >> 1) - *off;
+ break;
+ case IPU_PIX_FMT_TILED_NV12F:
+ /*
+ * tiled format, interlaced:
+ * same as above, only number of pixels in MB is 128,
+ * instead of 256
+ */
+ *off = (pos_y >> 1) * width + (pos_x << 3);
+ *uoff = ALIGN(width * height/2, SZ_4K) + (*off >> 1) - *off;
+ break;
+ default:
+ *off = (pos_y * width + pos_x) * fmt_to_bpp(fmt)/8;
+ break;
+ }
+ *stride = width * bytes_per_pixel(fmt);
+}
+
+static int update_split_setting(struct ipu_task_entry *t, bool vdi_split)
+{
+ struct stripe_param left_stripe;
+ struct stripe_param right_stripe;
+ struct stripe_param up_stripe;
+ struct stripe_param down_stripe;
+ u32 iw, ih, ow, oh;
+ u32 max_width;
+ int ret;
+
+ if (t->output.rotate >= IPU_ROTATE_90_RIGHT)
+ return IPU_CHECK_ERR_SPLIT_WITH_ROT;
+
+ iw = t->input.crop.w;
+ ih = t->input.crop.h;
+
+ ow = t->output.crop.w;
+ oh = t->output.crop.h;
+
+ memset(&left_stripe, 0, sizeof(left_stripe));
+ memset(&right_stripe, 0, sizeof(right_stripe));
+ memset(&up_stripe, 0, sizeof(up_stripe));
+ memset(&down_stripe, 0, sizeof(down_stripe));
+
+ if (t->set.split_mode & RL_SPLIT) {
+ /*
+ * We do want equal strips: initialize stripes in case
+ * calc_stripes returns before actually doing the calculation
+ */
+ left_stripe.input_width = iw / 2;
+ left_stripe.output_width = ow / 2;
+ right_stripe.input_column = iw / 2;
+ right_stripe.output_column = ow / 2;
+
+ if (vdi_split)
+ max_width = soc_max_vdi_in_width(t->ipu);
+ else
+ max_width = soc_max_out_width();
+ ret = ipu_calc_stripes_sizes(iw,
+ ow,
+ max_width,
+ (((unsigned long long)1) << 32), /* 32bit for fractional*/
+ 1, /* equal stripes */
+ t->input.format,
+ t->output.format,
+ &left_stripe,
+ &right_stripe);
+ if (ret < 0)
+ return IPU_CHECK_ERR_W_DOWNSIZE_OVER;
+ else if (ret)
+ dev_dbg(t->dev, "Warn: no:0x%x,calc_stripes ret:%d\n",
+ t->task_no, ret);
+ t->set.sp_setting.iw = left_stripe.input_width;
+ t->set.sp_setting.ow = left_stripe.output_width;
+ t->set.sp_setting.outh_resize_ratio = left_stripe.irr;
+ t->set.sp_setting.i_left_pos = left_stripe.input_column;
+ t->set.sp_setting.o_left_pos = left_stripe.output_column;
+ t->set.sp_setting.i_right_pos = right_stripe.input_column;
+ t->set.sp_setting.o_right_pos = right_stripe.output_column;
+ } else {
+ t->set.sp_setting.iw = iw;
+ t->set.sp_setting.ow = ow;
+ t->set.sp_setting.outh_resize_ratio = 0;
+ t->set.sp_setting.i_left_pos = 0;
+ t->set.sp_setting.o_left_pos = 0;
+ t->set.sp_setting.i_right_pos = 0;
+ t->set.sp_setting.o_right_pos = 0;
+ }
+ if ((t->set.sp_setting.iw + t->set.sp_setting.i_right_pos) > (iw+16))
+ return IPU_CHECK_ERR_SPLIT_INPUTW_OVER;
+ if (((t->set.sp_setting.ow + t->set.sp_setting.o_right_pos) > ow)
+ || (t->set.sp_setting.ow > soc_max_out_width()))
+ return IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER;
+ if (rounddown(t->set.sp_setting.ow, 8) * 8 <=
+ rounddown(t->set.sp_setting.iw, 8))
+ return IPU_CHECK_ERR_W_DOWNSIZE_OVER;
+
+ if (t->set.split_mode & UD_SPLIT) {
+ /*
+ * We do want equal strips: initialize stripes in case
+ * calc_stripes returns before actually doing the calculation
+ */
+ up_stripe.input_width = ih / 2;
+ up_stripe.output_width = oh / 2;
+ down_stripe.input_column = ih / 2;
+ down_stripe.output_column = oh / 2;
+ ret = ipu_calc_stripes_sizes(ih,
+ oh,
+ soc_max_out_height(),
+ (((unsigned long long)1) << 32), /* 32bit for fractional*/
+ 0x1 | 0x2, /* equal stripes and vertical */
+ t->input.format,
+ t->output.format,
+ &up_stripe,
+ &down_stripe);
+ if (ret < 0)
+ return IPU_CHECK_ERR_H_DOWNSIZE_OVER;
+ else if (ret)
+ dev_err(t->dev, "Warn: no:0x%x,calc_stripes ret:%d\n",
+ t->task_no, ret);
+ t->set.sp_setting.ih = up_stripe.input_width;
+ t->set.sp_setting.oh = up_stripe.output_width;
+ t->set.sp_setting.outv_resize_ratio = up_stripe.irr;
+ t->set.sp_setting.i_top_pos = up_stripe.input_column;
+ t->set.sp_setting.o_top_pos = up_stripe.output_column;
+ t->set.sp_setting.i_bottom_pos = down_stripe.input_column;
+ t->set.sp_setting.o_bottom_pos = down_stripe.output_column;
+ } else {
+ t->set.sp_setting.ih = ih;
+ t->set.sp_setting.oh = oh;
+ t->set.sp_setting.outv_resize_ratio = 0;
+ t->set.sp_setting.i_top_pos = 0;
+ t->set.sp_setting.o_top_pos = 0;
+ t->set.sp_setting.i_bottom_pos = 0;
+ t->set.sp_setting.o_bottom_pos = 0;
+ }
+
+ /* downscale case: enforce limits */
+ if (((t->set.sp_setting.ih + t->set.sp_setting.i_bottom_pos) > (ih))
+ && (t->set.sp_setting.ih >= t->set.sp_setting.oh))
+ return IPU_CHECK_ERR_SPLIT_INPUTH_OVER;
+ /* upscale case: relax limits because ipu_calc_stripes_sizes() may
+ create input stripe that falls just outside of the input window */
+ else if ((t->set.sp_setting.ih + t->set.sp_setting.i_bottom_pos)
+ > (ih+16))
+ return IPU_CHECK_ERR_SPLIT_INPUTH_OVER;
+ if (((t->set.sp_setting.oh + t->set.sp_setting.o_bottom_pos) > oh)
+ || (t->set.sp_setting.oh > soc_max_out_height()))
+ return IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER;
+ if (rounddown(t->set.sp_setting.oh, 8) * 8 <=
+ rounddown(t->set.sp_setting.ih, 8))
+ return IPU_CHECK_ERR_H_DOWNSIZE_OVER;
+
+ return IPU_CHECK_OK;
+}
+
+static int check_task(struct ipu_task_entry *t)
+{
+ int tmp;
+ int ret = IPU_CHECK_OK;
+ int timeout;
+ bool vdi_split = false;
+ int ocw, och;
+
+ if ((IPU_PIX_FMT_TILED_NV12 == t->overlay.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == t->overlay.format) ||
+ (IPU_PIX_FMT_TILED_NV12 == t->output.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == t->output.format) ||
+ ((IPU_PIX_FMT_TILED_NV12F == t->input.format) &&
+ !t->input.deinterlace.enable)) {
+ ret = IPU_CHECK_ERR_NOT_SUPPORT;
+ goto done;
+ }
+
+ /* check input */
+ ret = set_crop(&t->input.crop, t->input.width, t->input.height,
+ t->input.format);
+ if (ret < 0) {
+ ret = IPU_CHECK_ERR_INPUT_CROP;
+ goto done;
+ } else
+ update_offset(t->input.format, t->input.width, t->input.height,
+ t->input.crop.pos.x, t->input.crop.pos.y,
+ &t->set.i_off, &t->set.i_uoff,
+ &t->set.i_voff, &t->set.istride);
+
+ /* check output */
+ ret = set_crop(&t->output.crop, t->output.width, t->output.height,
+ t->output.format);
+ if (ret < 0) {
+ ret = IPU_CHECK_ERR_OUTPUT_CROP;
+ goto done;
+ } else
+ update_offset(t->output.format,
+ t->output.width, t->output.height,
+ t->output.crop.pos.x, t->output.crop.pos.y,
+ &t->set.o_off, &t->set.o_uoff,
+ &t->set.o_voff, &t->set.ostride);
+
+ if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
+ /*
+ * Cache output width and height and
+ * swap them so that we may check
+ * downsize overflow correctly.
+ */
+ ocw = t->output.crop.h;
+ och = t->output.crop.w;
+ } else {
+ ocw = t->output.crop.w;
+ och = t->output.crop.h;
+ }
+
+ if (ocw * 8 <= t->input.crop.w) {
+ ret = IPU_CHECK_ERR_W_DOWNSIZE_OVER;
+ goto done;
+ }
+
+ if (och * 8 <= t->input.crop.h) {
+ ret = IPU_CHECK_ERR_H_DOWNSIZE_OVER;
+ goto done;
+ }
+
+ if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
+ if ((t->input.crop.w > soc_max_in_width(1)) ||
+ (t->input.crop.h > soc_max_in_height())) {
+ ret = IPU_CHECK_ERR_INPUT_OVER_LIMIT;
+ goto done;
+ }
+ /* output fmt: NV12 and YUYV, now don't support resize */
+ if (((IPU_PIX_FMT_NV12 != t->output.format) &&
+ (IPU_PIX_FMT_YUYV != t->output.format)) ||
+ (t->input.crop.w != t->output.crop.w) ||
+ (t->input.crop.h != t->output.crop.h)) {
+ ret = IPU_CHECK_ERR_NOT_SUPPORT;
+ goto done;
+ }
+ }
+
+ /* check overlay if there is */
+ if (t->overlay_en) {
+ if (t->input.deinterlace.enable) {
+ ret = IPU_CHECK_ERR_OVERLAY_WITH_VDI;
+ goto done;
+ }
+
+ ret = set_crop(&t->overlay.crop, t->overlay.width,
+ t->overlay.height, t->overlay.format);
+ if (ret < 0) {
+ ret = IPU_CHECK_ERR_OVERLAY_CROP;
+ goto done;
+ } else {
+ ocw = t->output.crop.w;
+ och = t->output.crop.h;
+
+ if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
+ ocw = t->output.crop.h;
+ och = t->output.crop.w;
+ }
+ if ((t->overlay.crop.w != ocw) ||
+ (t->overlay.crop.h != och)) {
+ ret = IPU_CHECK_ERR_OV_OUT_NO_FIT;
+ goto done;
+ }
+
+ update_offset(t->overlay.format,
+ t->overlay.width, t->overlay.height,
+ t->overlay.crop.pos.x, t->overlay.crop.pos.y,
+ &t->set.ov_off, &t->set.ov_uoff,
+ &t->set.ov_voff, &t->set.ovstride);
+ if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
+ t->set.ov_alpha_stride = t->overlay.width;
+ t->set.ov_alpha_off = t->overlay.crop.pos.y *
+ t->overlay.width + t->overlay.crop.pos.x;
+ }
+ }
+ }
+
+ /* input overflow? */
+ if (!((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == t->input.format))) {
+ if ((t->input.crop.w > soc_max_in_width(0)) ||
+ (t->input.crop.h > soc_max_in_height())) {
+ ret = IPU_CHECK_ERR_INPUT_OVER_LIMIT;
+ goto done;
+ }
+ }
+
+ /* check task mode */
+ t->set.mode = NULL_MODE;
+ t->set.split_mode = NO_SPLIT;
+
+ if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
+ /*output swap*/
+ tmp = t->output.crop.w;
+ t->output.crop.w = t->output.crop.h;
+ t->output.crop.h = tmp;
+ }
+
+ if (t->output.rotate >= IPU_ROTATE_90_RIGHT)
+ t->set.mode |= ROT_MODE;
+
+ /*need resize or CSC?*/
+ if ((t->input.crop.w != t->output.crop.w) ||
+ (t->input.crop.h != t->output.crop.h) ||
+ need_csc(t->input.format, t->output.format))
+ t->set.mode |= IC_MODE;
+
+ /*need cropping?*/
+ if ((t->input.crop.w != t->input.width) ||
+ (t->input.crop.h != t->input.height) ||
+ (t->output.crop.w != t->output.width) ||
+ (t->output.crop.h != t->output.height))
+ t->set.mode |= IC_MODE;
+
+ /*need flip?*/
+ if ((t->set.mode == NULL_MODE) && (t->output.rotate > IPU_ROTATE_NONE))
+ t->set.mode |= IC_MODE;
+
+ /*need IDMAC do format(same color space)?*/
+ if ((t->set.mode == NULL_MODE) && (t->input.format != t->output.format))
+ t->set.mode |= IC_MODE;
+
+ /*overlay support*/
+ if (t->overlay_en)
+ t->set.mode |= IC_MODE;
+
+ /*deinterlace*/
+ if (t->input.deinterlace.enable) {
+ t->set.mode &= ~IC_MODE;
+ t->set.mode |= VDI_MODE;
+ }
+ if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
+ if (t->set.mode & ROT_MODE) {
+ ret = IPU_CHECK_ERR_NOT_SUPPORT;
+ goto done;
+ }
+ t->set.mode |= VDOA_MODE;
+ if (IPU_PIX_FMT_TILED_NV12F == t->input.format)
+ t->set.mode |= VDOA_BAND_MODE;
+ t->set.mode &= ~IC_MODE;
+ }
+
+ if ((t->set.mode & (IC_MODE | VDI_MODE)) &&
+ (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
+ if (t->output.crop.w > soc_max_out_width())
+ t->set.split_mode |= RL_SPLIT;
+ if (t->output.crop.h > soc_max_out_height())
+ t->set.split_mode |= UD_SPLIT;
+ if (!t->set.split_mode && (t->set.mode & VDI_MODE) &&
+ (t->input.crop.w >
+ soc_max_vdi_in_width(t->ipu))) {
+ t->set.split_mode |= RL_SPLIT;
+ vdi_split = true;
+ }
+ if (t->set.split_mode) {
+ if ((t->set.split_mode == RL_SPLIT) ||
+ (t->set.split_mode == UD_SPLIT))
+ timeout = DEF_TIMEOUT_MS * 2 + DEF_DELAY_MS;
+ else
+ timeout = DEF_TIMEOUT_MS * 4 + DEF_DELAY_MS;
+ if (t->timeout < timeout)
+ t->timeout = timeout;
+
+ ret = update_split_setting(t, vdi_split);
+ if (ret > IPU_CHECK_ERR_MIN)
+ goto done;
+ }
+ }
+
+ if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
+ /*output swap*/
+ tmp = t->output.crop.w;
+ t->output.crop.w = t->output.crop.h;
+ t->output.crop.h = tmp;
+ }
+
+ if (t->set.mode == NULL_MODE) {
+ ret = IPU_CHECK_ERR_PROC_NO_NEED;
+ goto done;
+ }
+
+ if ((t->set.i_uoff % 8) || (t->set.i_voff % 8))
+ ret |= IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN;
+ if ((t->set.o_uoff % 8) || (t->set.o_voff % 8))
+ ret |= IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN;
+ if (t->overlay_en && ((t->set.ov_uoff % 8) || (t->set.ov_voff % 8)))
+ ret |= IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN;
+
+done:
+ /* dump msg */
+ if (debug) {
+ if (ret > IPU_CHECK_ERR_MIN)
+ dump_check_err(t->dev, ret);
+ else if (ret != IPU_CHECK_OK)
+ dump_check_warn(t->dev, ret);
+ }
+
+ return ret;
+}
+
+static int prepare_task(struct ipu_task_entry *t)
+{
+ int ret = 0;
+
+ ret = check_task(t);
+ if (ret > IPU_CHECK_ERR_MIN)
+ return -EINVAL;
+
+ if (t->set.mode & VDI_MODE) {
+ t->task_id = IPU_TASK_ID_VF;
+ t->set.task = VDI_VF;
+ if (t->set.mode & ROT_MODE)
+ t->set.task |= ROT_VF;
+ }
+
+ if (VDOA_MODE == t->set.mode) {
+ if (t->set.task != 0) {
+ dev_err(t->dev, "ERR: vdoa only task:0x%x, [0x%p].\n",
+ t->set.task, t);
+ return -EINVAL;
+ }
+ t->set.task |= VDOA_ONLY;
+ }
+
+ if (VDOA_BAND_MODE & t->set.mode) {
+ /* to save band size: 1<<3 = 8 lines */
+ t->set.band_lines = 3;
+ }
+
+ dump_task_info(t);
+
+ return ret;
+}
+
+static uint32_t ic_vf_pp_is_busy(struct ipu_soc *ipu, bool is_vf)
+{
+ uint32_t status;
+ uint32_t status_vf;
+ uint32_t status_rot;
+
+ if (is_vf) {
+ status = ipu_channel_status(ipu, MEM_VDI_PRP_VF_MEM);
+ status_vf = ipu_channel_status(ipu, MEM_PRP_VF_MEM);
+ status_rot = ipu_channel_status(ipu, MEM_ROT_VF_MEM);
+ return status || status_vf || status_rot;
+ } else {
+ status = ipu_channel_status(ipu, MEM_PP_MEM);
+ status_rot = ipu_channel_status(ipu, MEM_ROT_PP_MEM);
+ return status || status_rot;
+ }
+}
+
+static int _get_vdoa_ipu_res(struct ipu_task_entry *t)
+{
+ int i;
+ struct ipu_soc *ipu;
+ u8 *used;
+ uint32_t found_ipu = 0;
+ uint32_t found_vdoa = 0;
+ struct ipu_channel_tabel *tbl = &ipu_ch_tbl;
+
+ mutex_lock(&tbl->lock);
+ if (t->set.mode & VDOA_MODE) {
+ if (NULL != t->vdoa_handle)
+ found_vdoa = 1;
+ else {
+ found_vdoa = tbl->vdoa_used ? 0 : 1;
+ if (found_vdoa) {
+ tbl->vdoa_used = 1;
+ vdoa_get_handle(&t->vdoa_handle);
+ } else
+ /* first get vdoa->ipu resource sequence */
+ goto out;
+ if (t->set.task & VDOA_ONLY)
+ goto out;
+ }
+ }
+
+ for (i = 0; i < max_ipu_no; i++) {
+ ipu = ipu_get_soc(i);
+ if (IS_ERR(ipu))
+ dev_err(t->dev, "no:0x%x,found_vdoa:%d, ipu:%d\n",
+ t->task_no, found_vdoa, i);
+
+ used = &tbl->used[i][IPU_PP_CH_VF];
+ if (t->set.mode & VDI_MODE) {
+ if (0 == *used) {
+ *used = 1;
+ found_ipu = 1;
+ break;
+ }
+ } else if ((t->set.mode & IC_MODE) || only_rot(t->set.mode)) {
+ if (0 == *used) {
+ t->task_id = IPU_TASK_ID_VF;
+ if (t->set.mode & IC_MODE)
+ t->set.task |= IC_VF;
+ if (t->set.mode & ROT_MODE)
+ t->set.task |= ROT_VF;
+ *used = 1;
+ found_ipu = 1;
+ break;
+ }
+ } else
+ dev_err(t->dev, "no:0x%x,found_vdoa:%d, mode:0x%x\n",
+ t->task_no, found_vdoa, t->set.mode);
+ }
+ if (found_ipu)
+ goto next;
+
+ for (i = 0; i < max_ipu_no; i++) {
+ ipu = ipu_get_soc(i);
+ if (IS_ERR(ipu))
+ dev_err(t->dev, "no:0x%x,found_vdoa:%d, ipu:%d\n",
+ t->task_no, found_vdoa, i);
+
+ if ((t->set.mode & IC_MODE) || only_rot(t->set.mode)) {
+ used = &tbl->used[i][IPU_PP_CH_PP];
+ if (0 == *used) {
+ t->task_id = IPU_TASK_ID_PP;
+ if (t->set.mode & IC_MODE)
+ t->set.task |= IC_PP;
+ if (t->set.mode & ROT_MODE)
+ t->set.task |= ROT_PP;
+ *used = 1;
+ found_ipu = 1;
+ break;
+ }
+ }
+ }
+
+next:
+ if (found_ipu) {
+ t->ipu = ipu;
+ t->ipu_id = i;
+ t->dev = ipu->dev;
+ if (atomic_inc_return(&t->res_get) == 2)
+ dev_err(t->dev,
+ "ERR no:0x%x,found_vdoa:%d,get ipu twice\n",
+ t->task_no, found_vdoa);
+ }
+out:
+ dev_dbg(t->dev,
+ "%s:no:0x%x,found_vdoa:%d, found_ipu:%d\n",
+ __func__, t->task_no, found_vdoa, found_ipu);
+ mutex_unlock(&tbl->lock);
+ if (t->set.task & VDOA_ONLY)
+ return found_vdoa;
+ else if (t->set.mode & VDOA_MODE)
+ return found_vdoa && found_ipu;
+ else
+ return found_ipu;
+}
+
+static void put_vdoa_ipu_res(struct ipu_task_entry *tsk, int vdoa_only)
+{
+ int ret;
+ int rel_vdoa = 0, rel_ipu = 0;
+ struct ipu_channel_tabel *tbl = &ipu_ch_tbl;
+
+ mutex_lock(&tbl->lock);
+ if (tsk->set.mode & VDOA_MODE) {
+ if (!tbl->vdoa_used && tsk->vdoa_handle)
+ dev_err(tsk->dev,
+ "ERR no:0x%x,vdoa not used,mode:0x%x\n",
+ tsk->task_no, tsk->set.mode);
+ if (tbl->vdoa_used && tsk->vdoa_handle) {
+ tbl->vdoa_used = 0;
+ vdoa_put_handle(&tsk->vdoa_handle);
+ if (tsk->ipu)
+ tsk->ipu->vdoa_en = 0;
+ rel_vdoa = 1;
+ if (vdoa_only || (tsk->set.task & VDOA_ONLY))
+ goto out;
+ }
+ }
+
+ tbl->used[tsk->ipu_id][tsk->task_id - 1] = 0;
+ rel_ipu = 1;
+ ret = atomic_inc_return(&tsk->res_free);
+ if (ret == 2)
+ dev_err(tsk->dev,
+ "ERR no:0x%x,rel_vdoa:%d,put ipu twice\n",
+ tsk->task_no, rel_vdoa);
+out:
+ dev_dbg(tsk->dev,
+ "%s:no:0x%x,rel_vdoa:%d, rel_ipu:%d\n",
+ __func__, tsk->task_no, rel_vdoa, rel_ipu);
+ mutex_unlock(&tbl->lock);
+}
+
+static int get_vdoa_ipu_res(struct ipu_task_entry *t)
+{
+ int ret;
+ uint32_t found = 0;
+
+ found = _get_vdoa_ipu_res(t);
+ if (!found) {
+ t->ipu_id = -1;
+ t->ipu = NULL;
+ /* blocking to get resource */
+ ret = atomic_inc_return(&req_cnt);
+ dev_dbg(t->dev,
+ "wait_res:no:0x%x,req_cnt:%d\n", t->task_no, ret);
+ ret = wait_event_timeout(res_waitq, _get_vdoa_ipu_res(t),
+ msecs_to_jiffies(t->timeout - DEF_DELAY_MS));
+ if (ret == 0) {
+ dev_err(t->dev, "ERR[0x%p,no-0x%x] wait_res timeout:%dms!\n",
+ t, t->task_no, t->timeout - DEF_DELAY_MS);
+ ret = -ETIMEDOUT;
+ t->state = STATE_RES_TIMEOUT;
+ goto out;
+ } else {
+ if (!(t->set.task & VDOA_ONLY) && (!t->ipu))
+ dev_err(t->dev,
+ "ERR[no-0x%x] can not get ipu!\n",
+ t->task_no);
+ ret = atomic_read(&req_cnt);
+ if (ret > 0)
+ ret = atomic_dec_return(&req_cnt);
+ else
+ dev_err(t->dev,
+ "ERR[no-0x%x] req_cnt:%d mismatch!\n",
+ t->task_no, ret);
+ dev_dbg(t->dev, "no-0x%x,[0x%p],req_cnt:%d, got_res!\n",
+ t->task_no, t, ret);
+ found = 1;
+ }
+ }
+
+out:
+ return found;
+}
+
+static struct ipu_task_entry *create_task_entry(struct ipu_task *task)
+{
+ struct ipu_task_entry *tsk;
+
+ tsk = kzalloc(sizeof(struct ipu_task_entry), GFP_KERNEL);
+ if (!tsk)
+ return ERR_PTR(-ENOMEM);
+ kref_init(&tsk->refcount);
+ tsk->state = -EINVAL;
+ tsk->ipu_id = -1;
+ tsk->dev = ipu_dev;
+ tsk->input = task->input;
+ tsk->output = task->output;
+ tsk->overlay_en = task->overlay_en;
+ if (tsk->overlay_en)
+ tsk->overlay = task->overlay;
+ if (task->timeout > DEF_TIMEOUT_MS)
+ tsk->timeout = task->timeout;
+ else
+ tsk->timeout = DEF_TIMEOUT_MS;
+
+ return tsk;
+}
+
+static void task_mem_free(struct kref *ref)
+{
+ struct ipu_task_entry *tsk =
+ container_of(ref, struct ipu_task_entry, refcount);
+ kfree(tsk);
+}
+
+int create_split_child_task(struct ipu_split_task *sp_task)
+{
+ int ret = 0;
+ struct ipu_task_entry *tsk;
+
+ tsk = create_task_entry(&sp_task->task);
+ if (IS_ERR(tsk))
+ return PTR_ERR(tsk);
+
+ sp_task->child_task = tsk;
+ tsk->task_no = sp_task->task_no;
+
+ ret = prepare_task(tsk);
+ if (ret < 0)
+ goto err;
+
+ tsk->parent = sp_task->parent_task;
+ tsk->set.sp_setting = sp_task->parent_task->set.sp_setting;
+
+ list_add(&tsk->node, &tsk->parent->split_list);
+ dev_dbg(tsk->dev, "[0x%p] sp_tsk Q list,no-0x%x\n", tsk, tsk->task_no);
+ tsk->state = STATE_QUEUE;
+ CHECK_PERF(&tsk->ts_queue);
+err:
+ return ret;
+}
+
+static inline int sp_task_check_done(struct ipu_split_task *sp_task,
+ struct ipu_task_entry *parent, int num, int *idx)
+{
+ int i;
+ int ret = 0;
+ struct ipu_task_entry *tsk;
+ struct mutex *lock = &parent->split_lock;
+
+ *idx = -EINVAL;
+ mutex_lock(lock);
+ for (i = 0; i < num; i++) {
+ tsk = sp_task[i].child_task;
+ if (tsk && tsk->split_done) {
+ *idx = i;
+ ret = 1;
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(lock);
+ return ret;
+}
+
+static int create_split_task(
+ int stripe,
+ struct ipu_split_task *sp_task)
+{
+ struct ipu_task *task = &(sp_task->task);
+ struct ipu_task_entry *t = sp_task->parent_task;
+ int ret;
+
+ sp_task->task_no |= stripe;
+
+ task->input = t->input;
+ task->output = t->output;
+ task->overlay_en = t->overlay_en;
+ if (task->overlay_en)
+ task->overlay = t->overlay;
+ task->task_id = t->task_id;
+ if ((t->set.split_mode == RL_SPLIT) ||
+ (t->set.split_mode == UD_SPLIT))
+ task->timeout = t->timeout / 2;
+ else
+ task->timeout = t->timeout / 4;
+
+ task->input.crop.w = t->set.sp_setting.iw;
+ task->input.crop.h = t->set.sp_setting.ih;
+ if (task->overlay_en) {
+ task->overlay.crop.w = t->set.sp_setting.ow;
+ task->overlay.crop.h = t->set.sp_setting.oh;
+ }
+ if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
+ task->output.crop.w = t->set.sp_setting.oh;
+ task->output.crop.h = t->set.sp_setting.ow;
+ t->set.sp_setting.rl_split_line = t->set.sp_setting.o_bottom_pos;
+ t->set.sp_setting.ud_split_line = t->set.sp_setting.o_right_pos;
+
+ } else {
+ task->output.crop.w = t->set.sp_setting.ow;
+ task->output.crop.h = t->set.sp_setting.oh;
+ t->set.sp_setting.rl_split_line = t->set.sp_setting.o_right_pos;
+ t->set.sp_setting.ud_split_line = t->set.sp_setting.o_bottom_pos;
+ }
+
+ if (stripe & LEFT_STRIPE)
+ task->input.crop.pos.x += t->set.sp_setting.i_left_pos;
+ else if (stripe & RIGHT_STRIPE)
+ task->input.crop.pos.x += t->set.sp_setting.i_right_pos;
+ if (stripe & UP_STRIPE)
+ task->input.crop.pos.y += t->set.sp_setting.i_top_pos;
+ else if (stripe & DOWN_STRIPE)
+ task->input.crop.pos.y += t->set.sp_setting.i_bottom_pos;
+
+ if (task->overlay_en) {
+ if (stripe & LEFT_STRIPE)
+ task->overlay.crop.pos.x += t->set.sp_setting.o_left_pos;
+ else if (stripe & RIGHT_STRIPE)
+ task->overlay.crop.pos.x += t->set.sp_setting.o_right_pos;
+ if (stripe & UP_STRIPE)
+ task->overlay.crop.pos.y += t->set.sp_setting.o_top_pos;
+ else if (stripe & DOWN_STRIPE)
+ task->overlay.crop.pos.y += t->set.sp_setting.o_bottom_pos;
+ }
+
+ switch (t->output.rotate) {
+ case IPU_ROTATE_NONE:
+ if (stripe & LEFT_STRIPE)
+ task->output.crop.pos.x += t->set.sp_setting.o_left_pos;
+ else if (stripe & RIGHT_STRIPE)
+ task->output.crop.pos.x += t->set.sp_setting.o_right_pos;
+ if (stripe & UP_STRIPE)
+ task->output.crop.pos.y += t->set.sp_setting.o_top_pos;
+ else if (stripe & DOWN_STRIPE)
+ task->output.crop.pos.y += t->set.sp_setting.o_bottom_pos;
+ break;
+ case IPU_ROTATE_VERT_FLIP:
+ if (stripe & LEFT_STRIPE)
+ task->output.crop.pos.x += t->set.sp_setting.o_left_pos;
+ else if (stripe & RIGHT_STRIPE)
+ task->output.crop.pos.x += t->set.sp_setting.o_right_pos;
+ if (stripe & UP_STRIPE)
+ task->output.crop.pos.y =
+ t->output.crop.pos.y + t->output.crop.h
+ - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
+ else if (stripe & DOWN_STRIPE)
+ task->output.crop.pos.y =
+ t->output.crop.pos.y + t->output.crop.h
+ - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
+ break;
+ case IPU_ROTATE_HORIZ_FLIP:
+ if (stripe & LEFT_STRIPE)
+ task->output.crop.pos.x =
+ t->output.crop.pos.x + t->output.crop.w
+ - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
+ else if (stripe & RIGHT_STRIPE)
+ task->output.crop.pos.x =
+ t->output.crop.pos.x + t->output.crop.w
+ - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
+ if (stripe & UP_STRIPE)
+ task->output.crop.pos.y += t->set.sp_setting.o_top_pos;
+ else if (stripe & DOWN_STRIPE)
+ task->output.crop.pos.y += t->set.sp_setting.o_bottom_pos;
+ break;
+ case IPU_ROTATE_180:
+ if (stripe & LEFT_STRIPE)
+ task->output.crop.pos.x =
+ t->output.crop.pos.x + t->output.crop.w
+ - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
+ else if (stripe & RIGHT_STRIPE)
+ task->output.crop.pos.x =
+ t->output.crop.pos.x + t->output.crop.w
+ - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
+ if (stripe & UP_STRIPE)
+ task->output.crop.pos.y =
+ t->output.crop.pos.y + t->output.crop.h
+ - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
+ else if (stripe & DOWN_STRIPE)
+ task->output.crop.pos.y =
+ t->output.crop.pos.y + t->output.crop.h
+ - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
+ break;
+ case IPU_ROTATE_90_RIGHT:
+ if (stripe & UP_STRIPE)
+ task->output.crop.pos.x =
+ t->output.crop.pos.x + t->output.crop.w
+ - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
+ else if (stripe & DOWN_STRIPE)
+ task->output.crop.pos.x =
+ t->output.crop.pos.x + t->output.crop.w
+ - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
+ if (stripe & LEFT_STRIPE)
+ task->output.crop.pos.y += t->set.sp_setting.o_left_pos;
+ else if (stripe & RIGHT_STRIPE)
+ task->output.crop.pos.y += t->set.sp_setting.o_right_pos;
+ break;
+ case IPU_ROTATE_90_RIGHT_HFLIP:
+ if (stripe & UP_STRIPE)
+ task->output.crop.pos.x += t->set.sp_setting.o_top_pos;
+ else if (stripe & DOWN_STRIPE)
+ task->output.crop.pos.x += t->set.sp_setting.o_bottom_pos;
+ if (stripe & LEFT_STRIPE)
+ task->output.crop.pos.y += t->set.sp_setting.o_left_pos;
+ else if (stripe & RIGHT_STRIPE)
+ task->output.crop.pos.y += t->set.sp_setting.o_right_pos;
+ break;
+ case IPU_ROTATE_90_RIGHT_VFLIP:
+ if (stripe & UP_STRIPE)
+ task->output.crop.pos.x =
+ t->output.crop.pos.x + t->output.crop.w
+ - t->set.sp_setting.o_top_pos - t->set.sp_setting.oh;
+ else if (stripe & DOWN_STRIPE)
+ task->output.crop.pos.x =
+ t->output.crop.pos.x + t->output.crop.w
+ - t->set.sp_setting.o_bottom_pos - t->set.sp_setting.oh;
+ if (stripe & LEFT_STRIPE)
+ task->output.crop.pos.y =
+ t->output.crop.pos.y + t->output.crop.h
+ - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
+ else if (stripe & RIGHT_STRIPE)
+ task->output.crop.pos.y =
+ t->output.crop.pos.y + t->output.crop.h
+ - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
+ break;
+ case IPU_ROTATE_90_LEFT:
+ if (stripe & UP_STRIPE)
+ task->output.crop.pos.x += t->set.sp_setting.o_top_pos;
+ else if (stripe & DOWN_STRIPE)
+ task->output.crop.pos.x += t->set.sp_setting.o_bottom_pos;
+ if (stripe & LEFT_STRIPE)
+ task->output.crop.pos.y =
+ t->output.crop.pos.y + t->output.crop.h
+ - t->set.sp_setting.o_left_pos - t->set.sp_setting.ow;
+ else if (stripe & RIGHT_STRIPE)
+ task->output.crop.pos.y =
+ t->output.crop.pos.y + t->output.crop.h
+ - t->set.sp_setting.o_right_pos - t->set.sp_setting.ow;
+ break;
+ default:
+ dev_err(t->dev, "ERR:should not be here\n");
+ break;
+ }
+
+ ret = create_split_child_task(sp_task);
+ if (ret < 0)
+ dev_err(t->dev, "ERR:create_split_child_task() ret:%d\n", ret);
+ return ret;
+}
+
+static int queue_split_task(struct ipu_task_entry *t,
+ struct ipu_split_task *sp_task, uint32_t size)
+{
+ int err[4];
+ int ret = 0;
+ int i, j;
+ struct ipu_task_entry *tsk = NULL;
+ struct mutex *lock = &t->split_lock;
+ struct mutex *vdic_lock = &t->vdic_lock;
+
+ dev_dbg(t->dev, "Split task 0x%p, no-0x%x, size:%d\n",
+ t, t->task_no, size);
+ mutex_init(lock);
+ mutex_init(vdic_lock);
+ init_waitqueue_head(&t->split_waitq);
+ INIT_LIST_HEAD(&t->split_list);
+ for (j = 0; j < size; j++) {
+ memset(&sp_task[j], 0, sizeof(*sp_task));
+ sp_task[j].parent_task = t;
+ sp_task[j].task_no = t->task_no;
+ }
+
+ if (t->set.split_mode == RL_SPLIT) {
+ i = 0;
+ err[i] = create_split_task(RIGHT_STRIPE, &sp_task[i]);
+ if (err[i] < 0)
+ goto err_start;
+ i = 1;
+ err[i] = create_split_task(LEFT_STRIPE, &sp_task[i]);
+ } else if (t->set.split_mode == UD_SPLIT) {
+ i = 0;
+ err[i] = create_split_task(DOWN_STRIPE, &sp_task[i]);
+ if (err[i] < 0)
+ goto err_start;
+ i = 1;
+ err[i] = create_split_task(UP_STRIPE, &sp_task[i]);
+ } else {
+ i = 0;
+ err[i] = create_split_task(RIGHT_STRIPE | DOWN_STRIPE, &sp_task[i]);
+ if (err[i] < 0)
+ goto err_start;
+ i = 1;
+ err[i] = create_split_task(LEFT_STRIPE | DOWN_STRIPE, &sp_task[i]);
+ if (err[i] < 0)
+ goto err_start;
+ i = 2;
+ err[i] = create_split_task(RIGHT_STRIPE | UP_STRIPE, &sp_task[i]);
+ if (err[i] < 0)
+ goto err_start;
+ i = 3;
+ err[i] = create_split_task(LEFT_STRIPE | UP_STRIPE, &sp_task[i]);
+ }
+
+err_start:
+ for (j = 0; j < (i + 1); j++) {
+ if (err[j] < 0) {
+ if (sp_task[j].child_task)
+ dev_err(t->dev,
+ "sp_task[%d],no-0x%x fail state:%d, queue err:%d.\n",
+ j, sp_task[j].child_task->task_no,
+ sp_task[j].child_task->state, err[j]);
+ goto err_exit;
+ }
+ dev_dbg(t->dev, "[0x%p] sp_task[%d], no-0x%x state:%s, queue ret:%d.\n",
+ sp_task[j].child_task, j, sp_task[j].child_task->task_no,
+ state_msg[sp_task[j].child_task->state].msg, err[j]);
+ }
+
+ return ret;
+
+err_exit:
+ for (j = 0; j < (i + 1); j++) {
+ if (err[j] < 0 && !ret)
+ ret = err[j];
+ tsk = sp_task[j].child_task;
+ if (!tsk)
+ continue;
+ kfree(tsk);
+ }
+ t->state = STATE_ERR;
+ return ret;
+
+}
+
+static int init_tiled_buf(struct ipu_soc *ipu, struct ipu_task_entry *t,
+ ipu_channel_t channel, uint32_t ch_type)
+{
+ int ret = 0;
+ int i;
+ uint32_t ipu_fmt;
+ dma_addr_t inbuf_base = 0;
+ u32 field_size;
+ struct vdoa_params param;
+ struct vdoa_ipu_buf buf;
+ struct ipu_soc *ipu_idx;
+ u32 ipu_stride, obuf_size;
+ u32 height, width;
+ ipu_buffer_t type;
+
+ if ((IPU_PIX_FMT_YUYV != t->output.format) &&
+ (IPU_PIX_FMT_NV12 != t->output.format)) {
+ dev_err(t->dev, "ERR:[0x%d] output format\n", t->task_no);
+ return -EINVAL;
+ }
+
+ memset(&param, 0, sizeof(param));
+ /* init channel tiled bufs */
+ if (deinterlace_3_field(t) &&
+ (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
+ field_size = tiled_filed_size(t);
+ if (INPUT_CHAN_VDI_P == ch_type) {
+ inbuf_base = t->input.paddr + field_size;
+ param.vfield_buf.prev_veba = inbuf_base + t->set.i_off;
+ } else if (INPUT_CHAN == ch_type) {
+ inbuf_base = t->input.paddr_n;
+ param.vfield_buf.cur_veba = inbuf_base + t->set.i_off;
+ } else if (INPUT_CHAN_VDI_N == ch_type) {
+ inbuf_base = t->input.paddr_n + field_size;
+ param.vfield_buf.next_veba = inbuf_base + t->set.i_off;
+ } else
+ return -EINVAL;
+ height = t->input.crop.h >> 1; /* field format for vdoa */
+ width = t->input.crop.w;
+ param.vfield_buf.vubo = t->set.i_uoff;
+ param.interlaced = 1;
+ param.scan_order = 1;
+ type = IPU_INPUT_BUFFER;
+ } else if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) &&
+ (INPUT_CHAN == ch_type)) {
+ height = t->input.crop.h;
+ width = t->input.crop.w;
+ param.vframe_buf.veba = t->input.paddr + t->set.i_off;
+ param.vframe_buf.vubo = t->set.i_uoff;
+ type = IPU_INPUT_BUFFER;
+ } else
+ return -EINVAL;
+
+ param.band_mode = (t->set.mode & VDOA_BAND_MODE) ? 1 : 0;
+ if (param.band_mode && (t->set.band_lines != 3) &&
+ (t->set.band_lines != 4) && (t->set.band_lines != 5))
+ return -EINVAL;
+ else if (param.band_mode)
+ param.band_lines = (1 << t->set.band_lines);
+ for (i = 0; i < max_ipu_no; i++) {
+ ipu_idx = ipu_get_soc(i);
+ if (!IS_ERR(ipu_idx) && ipu_idx == ipu)
+ break;
+ }
+ if (t->set.task & VDOA_ONLY)
+ /* dummy, didn't need ipu res */
+ i = 0;
+ if (max_ipu_no == i) {
+ dev_err(t->dev, "ERR:[0x%p] get ipu num\n", t);
+ return -EINVAL;
+ }
+
+ param.ipu_num = i;
+ param.vpu_stride = t->input.width;
+ param.height = height;
+ param.width = width;
+ if (IPU_PIX_FMT_NV12 == t->output.format)
+ param.pfs = VDOA_PFS_NV12;
+ else
+ param.pfs = VDOA_PFS_YUYV;
+ ipu_fmt = (param.pfs == VDOA_PFS_YUYV) ? IPU_PIX_FMT_YUYV :
+ IPU_PIX_FMT_NV12;
+ ipu_stride = param.width * bytes_per_pixel(ipu_fmt);
+ obuf_size = PAGE_ALIGN(param.width * param.height *
+ fmt_to_bpp(ipu_fmt)/8);
+ dev_dbg(t->dev, "band_mode:%d, band_lines:%d\n",
+ param.band_mode, param.band_lines);
+ if (!param.band_mode) {
+ /* note: if only for tiled -> raster convert and
+ no other post-processing, we don't need alloc buf
+ and use output buffer directly.
+ */
+ if (t->set.task & VDOA_ONLY)
+ param.ieba0 = t->output.paddr;
+ else {
+ dev_err(t->dev, "ERR:[0x%d] vdoa task\n", t->task_no);
+ return -EINVAL;
+ }
+ } else {
+ if (IPU_PIX_FMT_TILED_NV12F != t->input.format) {
+ dev_err(t->dev, "ERR [0x%d] vdoa task\n", t->task_no);
+ return -EINVAL;
+ }
+ }
+ ret = vdoa_setup(t->vdoa_handle, &param);
+ if (ret)
+ goto done;
+ vdoa_get_output_buf(t->vdoa_handle, &buf);
+ if (t->set.task & VDOA_ONLY)
+ goto done;
+
+ ret = ipu_init_channel_buffer(ipu,
+ channel,
+ type,
+ ipu_fmt,
+ width,
+ height,
+ ipu_stride,
+ IPU_ROTATE_NONE,
+ buf.ieba0,
+ buf.ieba1,
+ 0,
+ buf.iubo,
+ 0);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+
+ if (param.band_mode) {
+ ret = ipu_set_channel_bandmode(ipu, channel,
+ type, t->set.band_lines);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BAND_FAIL;
+ goto done;
+ }
+ }
+done:
+ return ret;
+}
+
+static int init_tiled_ch_bufs(struct ipu_soc *ipu, struct ipu_task_entry *t)
+{
+ int ret = 0;
+
+ if (IPU_PIX_FMT_TILED_NV12 == t->input.format) {
+ ret = init_tiled_buf(ipu, t, t->set.ic_chan, INPUT_CHAN);
+ CHECK_RETCODE(ret < 0, "init tiled_ch", t->state, done, ret);
+ } else if (IPU_PIX_FMT_TILED_NV12F == t->input.format) {
+ ret = init_tiled_buf(ipu, t, t->set.ic_chan, INPUT_CHAN);
+ CHECK_RETCODE(ret < 0, "init tiled_ch-c", t->state, done, ret);
+ ret = init_tiled_buf(ipu, t, t->set.vdi_ic_p_chan,
+ INPUT_CHAN_VDI_P);
+ CHECK_RETCODE(ret < 0, "init tiled_ch-p", t->state, done, ret);
+ ret = init_tiled_buf(ipu, t, t->set.vdi_ic_n_chan,
+ INPUT_CHAN_VDI_N);
+ CHECK_RETCODE(ret < 0, "init tiled_ch-n", t->state, done, ret);
+ } else {
+ ret = -EINVAL;
+ dev_err(t->dev, "ERR[no-0x%x] invalid fmt:0x%x!\n",
+ t->task_no, t->input.format);
+ }
+
+done:
+ return ret;
+}
+
+static int init_ic(struct ipu_soc *ipu, struct ipu_task_entry *t)
+{
+ int ret = 0;
+ ipu_channel_params_t params;
+ dma_addr_t inbuf = 0, ovbuf = 0, ov_alp_buf = 0;
+ dma_addr_t inbuf_p = 0, inbuf_n = 0;
+ dma_addr_t outbuf = 0;
+ int out_uoff = 0, out_voff = 0, out_rot;
+ int out_w = 0, out_h = 0, out_stride;
+ int out_fmt;
+ u32 vdi_frame_idx = 0;
+
+ memset(&params, 0, sizeof(params));
+
+ /* is it need link a rot channel */
+ if (ic_and_rot(t->set.mode)) {
+ outbuf = t->set.r_paddr;
+ out_w = t->set.r_width;
+ out_h = t->set.r_height;
+ out_stride = t->set.r_stride;
+ out_fmt = t->set.r_fmt;
+ out_uoff = 0;
+ out_voff = 0;
+ out_rot = IPU_ROTATE_NONE;
+ } else {
+ outbuf = t->output.paddr + t->set.o_off;
+ out_w = t->output.crop.w;
+ out_h = t->output.crop.h;
+ out_stride = t->set.ostride;
+ out_fmt = t->output.format;
+ out_uoff = t->set.o_uoff;
+ out_voff = t->set.o_voff;
+ out_rot = t->output.rotate;
+ }
+
+ /* settings */
+ params.mem_prp_vf_mem.in_width = t->input.crop.w;
+ params.mem_prp_vf_mem.out_width = out_w;
+ params.mem_prp_vf_mem.in_height = t->input.crop.h;
+ params.mem_prp_vf_mem.out_height = out_h;
+ params.mem_prp_vf_mem.in_pixel_fmt = t->input.format;
+ params.mem_prp_vf_mem.out_pixel_fmt = out_fmt;
+ params.mem_prp_vf_mem.motion_sel = t->input.deinterlace.motion;
+
+ params.mem_prp_vf_mem.outh_resize_ratio =
+ t->set.sp_setting.outh_resize_ratio;
+ params.mem_prp_vf_mem.outv_resize_ratio =
+ t->set.sp_setting.outv_resize_ratio;
+
+ if (t->overlay_en) {
+ params.mem_prp_vf_mem.in_g_pixel_fmt = t->overlay.format;
+ params.mem_prp_vf_mem.graphics_combine_en = 1;
+ if (t->overlay.alpha.mode == IPU_ALPHA_MODE_GLOBAL)
+ params.mem_prp_vf_mem.global_alpha_en = 1;
+ else if (t->overlay.alpha.loc_alp_paddr)
+ params.mem_prp_vf_mem.alpha_chan_en = 1;
+ /* otherwise, alpha bending per pixel is used. */
+ params.mem_prp_vf_mem.alpha = t->overlay.alpha.gvalue;
+ if (t->overlay.colorkey.enable) {
+ params.mem_prp_vf_mem.key_color_en = 1;
+ params.mem_prp_vf_mem.key_color = t->overlay.colorkey.value;
+ }
+ }
+
+ if (t->input.deinterlace.enable) {
+ if (t->input.deinterlace.field_fmt & IPU_DEINTERLACE_FIELD_MASK)
+ params.mem_prp_vf_mem.field_fmt =
+ IPU_DEINTERLACE_FIELD_BOTTOM;
+ else
+ params.mem_prp_vf_mem.field_fmt =
+ IPU_DEINTERLACE_FIELD_TOP;
+
+ if (t->input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN)
+ vdi_frame_idx = t->input.deinterlace.field_fmt &
+ IPU_DEINTERLACE_RATE_FRAME1;
+ }
+
+ if (t->set.mode & VDOA_MODE)
+ ipu->vdoa_en = 1;
+
+ /* init channels */
+ if (!(t->set.task & VDOA_ONLY)) {
+ ret = ipu_init_channel(ipu, t->set.ic_chan, &params);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_FAIL;
+ goto done;
+ }
+ }
+
+ if (deinterlace_3_field(t)) {
+ ret = ipu_init_channel(ipu, t->set.vdi_ic_p_chan, &params);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_FAIL;
+ goto done;
+ }
+ ret = ipu_init_channel(ipu, t->set.vdi_ic_n_chan, &params);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_FAIL;
+ goto done;
+ }
+ }
+
+ /* init channel bufs */
+ if ((IPU_PIX_FMT_TILED_NV12 == t->input.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == t->input.format)) {
+ ret = init_tiled_ch_bufs(ipu, t);
+ if (ret < 0)
+ goto done;
+ } else {
+ if ((deinterlace_3_field(t)) &&
+ (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
+ if (params.mem_prp_vf_mem.field_fmt ==
+ IPU_DEINTERLACE_FIELD_TOP) {
+ if (vdi_frame_idx) {
+ inbuf_p = t->input.paddr + t->set.istride +
+ t->set.i_off;
+ inbuf = t->input.paddr_n + t->set.i_off;
+ inbuf_n = t->input.paddr_n + t->set.istride +
+ t->set.i_off;
+ params.mem_prp_vf_mem.field_fmt =
+ IPU_DEINTERLACE_FIELD_BOTTOM;
+ } else {
+ inbuf_p = t->input.paddr + t->set.i_off;
+ inbuf = t->input.paddr + t->set.istride + t->set.i_off;
+ inbuf_n = t->input.paddr_n + t->set.i_off;
+ }
+ } else {
+ if (vdi_frame_idx) {
+ inbuf_p = t->input.paddr + t->set.i_off;
+ inbuf = t->input.paddr_n + t->set.istride + t->set.i_off;
+ inbuf_n = t->input.paddr_n + t->set.i_off;
+ params.mem_prp_vf_mem.field_fmt =
+ IPU_DEINTERLACE_FIELD_TOP;
+ } else {
+ inbuf_p = t->input.paddr + t->set.istride +
+ t->set.i_off;
+ inbuf = t->input.paddr + t->set.i_off;
+ inbuf_n = t->input.paddr_n + t->set.istride +
+ t->set.i_off;
+ }
+ }
+ } else {
+ if (t->input.deinterlace.enable) {
+ if (params.mem_prp_vf_mem.field_fmt ==
+ IPU_DEINTERLACE_FIELD_TOP) {
+ if (vdi_frame_idx) {
+ inbuf = t->input.paddr + t->set.istride + t->set.i_off;
+ params.mem_prp_vf_mem.field_fmt =
+ IPU_DEINTERLACE_FIELD_BOTTOM;
+ } else
+ inbuf = t->input.paddr + t->set.i_off;
+ } else {
+ if (vdi_frame_idx) {
+ inbuf = t->input.paddr + t->set.i_off;
+ params.mem_prp_vf_mem.field_fmt =
+ IPU_DEINTERLACE_FIELD_TOP;
+ } else
+ inbuf = t->input.paddr + t->set.istride + t->set.i_off;
+ }
+ } else
+ inbuf = t->input.paddr + t->set.i_off;
+ }
+
+ if (t->overlay_en)
+ ovbuf = t->overlay.paddr + t->set.ov_off;
+ }
+ if (t->overlay_en && (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL))
+ ov_alp_buf = t->overlay.alpha.loc_alp_paddr
+ + t->set.ov_alpha_off;
+
+ if ((IPU_PIX_FMT_TILED_NV12 != t->input.format) &&
+ (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
+ ret = ipu_init_channel_buffer(ipu,
+ t->set.ic_chan,
+ IPU_INPUT_BUFFER,
+ t->input.format,
+ t->input.crop.w,
+ t->input.crop.h,
+ t->set.istride,
+ IPU_ROTATE_NONE,
+ inbuf,
+ 0,
+ 0,
+ t->set.i_uoff,
+ t->set.i_voff);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+ }
+ if (deinterlace_3_field(t) &&
+ (IPU_PIX_FMT_TILED_NV12F != t->input.format)) {
+ ret = ipu_init_channel_buffer(ipu,
+ t->set.vdi_ic_p_chan,
+ IPU_INPUT_BUFFER,
+ t->input.format,
+ t->input.crop.w,
+ t->input.crop.h,
+ t->set.istride,
+ IPU_ROTATE_NONE,
+ inbuf_p,
+ 0,
+ 0,
+ t->set.i_uoff,
+ t->set.i_voff);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+
+ ret = ipu_init_channel_buffer(ipu,
+ t->set.vdi_ic_n_chan,
+ IPU_INPUT_BUFFER,
+ t->input.format,
+ t->input.crop.w,
+ t->input.crop.h,
+ t->set.istride,
+ IPU_ROTATE_NONE,
+ inbuf_n,
+ 0,
+ 0,
+ t->set.i_uoff,
+ t->set.i_voff);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+ }
+
+ if (t->overlay_en) {
+ ret = ipu_init_channel_buffer(ipu,
+ t->set.ic_chan,
+ IPU_GRAPH_IN_BUFFER,
+ t->overlay.format,
+ t->overlay.crop.w,
+ t->overlay.crop.h,
+ t->set.ovstride,
+ IPU_ROTATE_NONE,
+ ovbuf,
+ 0,
+ 0,
+ t->set.ov_uoff,
+ t->set.ov_voff);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+ }
+
+ if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
+ ret = ipu_init_channel_buffer(ipu,
+ t->set.ic_chan,
+ IPU_ALPHA_IN_BUFFER,
+ IPU_PIX_FMT_GENERIC,
+ t->overlay.crop.w,
+ t->overlay.crop.h,
+ t->set.ov_alpha_stride,
+ IPU_ROTATE_NONE,
+ ov_alp_buf,
+ 0,
+ 0,
+ 0, 0);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+ }
+
+ if (!(t->set.task & VDOA_ONLY)) {
+ ret = ipu_init_channel_buffer(ipu,
+ t->set.ic_chan,
+ IPU_OUTPUT_BUFFER,
+ out_fmt,
+ out_w,
+ out_h,
+ out_stride,
+ out_rot,
+ outbuf,
+ 0,
+ 0,
+ out_uoff,
+ out_voff);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+ }
+
+ if ((t->set.mode & VDOA_BAND_MODE) && (t->set.task & VDI_VF)) {
+ ret = ipu_link_channels(ipu, MEM_VDOA_MEM, t->set.ic_chan);
+ CHECK_RETCODE(ret < 0, "ipu_link_ch vdoa_ic",
+ STATE_LINK_CHAN_FAIL, done, ret);
+ }
+
+done:
+ return ret;
+}
+
+static void uninit_ic(struct ipu_soc *ipu, struct ipu_task_entry *t)
+{
+ int ret;
+
+ if ((t->set.mode & VDOA_BAND_MODE) && (t->set.task & VDI_VF)) {
+ ret = ipu_unlink_channels(ipu, MEM_VDOA_MEM, t->set.ic_chan);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_unlink_ch vdoa_ic",
+ STATE_UNLINK_CHAN_FAIL, ret);
+ }
+ ipu_uninit_channel(ipu, t->set.ic_chan);
+ if (deinterlace_3_field(t)) {
+ ipu_uninit_channel(ipu, t->set.vdi_ic_p_chan);
+ ipu_uninit_channel(ipu, t->set.vdi_ic_n_chan);
+ }
+}
+
+static int init_rot(struct ipu_soc *ipu, struct ipu_task_entry *t)
+{
+ int ret = 0;
+ dma_addr_t inbuf = 0, outbuf = 0;
+ int in_uoff = 0, in_voff = 0;
+ int in_fmt, in_width, in_height, in_stride;
+
+ /* init channel */
+ ret = ipu_init_channel(ipu, t->set.rot_chan, NULL);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_FAIL;
+ goto done;
+ }
+
+ /* init channel buf */
+ /* is it need link to a ic channel */
+ if (ic_and_rot(t->set.mode)) {
+ in_fmt = t->set.r_fmt;
+ in_width = t->set.r_width;
+ in_height = t->set.r_height;
+ in_stride = t->set.r_stride;
+ inbuf = t->set.r_paddr;
+ in_uoff = 0;
+ in_voff = 0;
+ } else {
+ in_fmt = t->input.format;
+ in_width = t->input.crop.w;
+ in_height = t->input.crop.h;
+ in_stride = t->set.istride;
+ inbuf = t->input.paddr + t->set.i_off;
+ in_uoff = t->set.i_uoff;
+ in_voff = t->set.i_voff;
+ }
+ outbuf = t->output.paddr + t->set.o_off;
+
+ ret = ipu_init_channel_buffer(ipu,
+ t->set.rot_chan,
+ IPU_INPUT_BUFFER,
+ in_fmt,
+ in_width,
+ in_height,
+ in_stride,
+ t->output.rotate,
+ inbuf,
+ 0,
+ 0,
+ in_uoff,
+ in_voff);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+
+ ret = ipu_init_channel_buffer(ipu,
+ t->set.rot_chan,
+ IPU_OUTPUT_BUFFER,
+ t->output.format,
+ t->output.crop.w,
+ t->output.crop.h,
+ t->set.ostride,
+ IPU_ROTATE_NONE,
+ outbuf,
+ 0,
+ 0,
+ t->set.o_uoff,
+ t->set.o_voff);
+ if (ret < 0) {
+ t->state = STATE_INIT_CHAN_BUF_FAIL;
+ goto done;
+ }
+
+done:
+ return ret;
+}
+
+static void uninit_rot(struct ipu_soc *ipu, struct ipu_task_entry *t)
+{
+ ipu_uninit_channel(ipu, t->set.rot_chan);
+}
+
+static int get_irq(struct ipu_task_entry *t)
+{
+ int irq;
+ ipu_channel_t chan;
+
+ if (only_ic(t->set.mode))
+ chan = t->set.ic_chan;
+ else
+ chan = t->set.rot_chan;
+
+ switch (chan) {
+ case MEM_ROT_VF_MEM:
+ irq = IPU_IRQ_PRP_VF_ROT_OUT_EOF;
+ break;
+ case MEM_ROT_PP_MEM:
+ irq = IPU_IRQ_PP_ROT_OUT_EOF;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ case MEM_PRP_VF_MEM:
+ irq = IPU_IRQ_PRP_VF_OUT_EOF;
+ break;
+ case MEM_PP_MEM:
+ irq = IPU_IRQ_PP_OUT_EOF;
+ break;
+ case MEM_VDI_MEM:
+ irq = IPU_IRQ_VDIC_OUT_EOF;
+ break;
+ default:
+ irq = -EINVAL;
+ }
+
+ return irq;
+}
+
+static irqreturn_t task_irq_handler(int irq, void *dev_id)
+{
+ struct ipu_task_entry *prev_tsk = dev_id;
+
+ CHECK_PERF(&prev_tsk->ts_inirq);
+ complete(&prev_tsk->irq_comp);
+ dev_dbg(prev_tsk->dev, "[0x%p] no-0x%x in-irq!",
+ prev_tsk, prev_tsk->task_no);
+
+ return IRQ_HANDLED;
+}
+
+/* Fix deinterlace up&down split mode medium line */
+static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
+{
+ u32 vdi_size;
+ u32 vdi_save_lines;
+ u32 stripe_mode;
+ u32 task_no;
+ u32 i, offset_addr;
+ u32 line_size;
+ unsigned char *base_off;
+ struct ipu_task_entry *parent = t->parent;
+ struct mutex *lock = &parent->vdic_lock;
+
+ if (!parent) {
+ dev_err(t->dev, "ERR[0x%x]invalid parent\n", t->task_no);
+ return;
+ }
+ mutex_lock(lock);
+ stripe_mode = t->task_no & 0xf;
+ task_no = t->task_no >> 4;
+
+ /* Save both luma and chroma part for interleaved YUV(e.g. YUYV).
+ * Save luma part for non-interleaved and partial-interleaved
+ * YUV format (e.g NV12 and YV12). */
+ if (t->output.format == IPU_PIX_FMT_YUYV ||
+ t->output.format == IPU_PIX_FMT_UYVY)
+ line_size = t->output.crop.w * fmt_to_bpp(t->output.format)/8;
+ else
+ line_size = t->output.crop.w;
+
+ vdi_save_lines = (t->output.crop.h - t->set.sp_setting.ud_split_line)/2;
+ vdi_size = vdi_save_lines * line_size;
+ if (vdi_save_lines <= 0) {
+ dev_err(t->dev, "[0x%p] vdi_save_line error\n", (void *)t);
+ mutex_unlock(lock);
+ return;
+ }
+
+ /*check vditmpbuf buffer have alloced or buffer size is changed */
+ if ((vdi_save_lines != parent->old_save_lines) ||
+ (vdi_size != parent->old_size)) {
+ if (parent->vditmpbuf[0] != NULL)
+ kfree(parent->vditmpbuf[0]);
+ if (parent->vditmpbuf[1] != NULL)
+ kfree(parent->vditmpbuf[1]);
+
+ parent->vditmpbuf[0] = kmalloc(vdi_size, GFP_KERNEL);
+ if (parent->vditmpbuf[0] == NULL) {
+ dev_err(t->dev,
+ "[0x%p]Falied Alloc vditmpbuf[0]\n", (void *)t);
+ mutex_unlock(lock);
+ return;
+ }
+ memset(parent->vditmpbuf[0], 0, vdi_size);
+
+ parent->vditmpbuf[1] = kmalloc(vdi_size, GFP_KERNEL);
+ if (parent->vditmpbuf[1] == NULL) {
+ dev_err(t->dev,
+ "[0x%p]Falied Alloc vditmpbuf[1]\n", (void *)t);
+ mutex_unlock(lock);
+ return;
+ }
+ memset(parent->vditmpbuf[1], 0, vdi_size);
+
+ parent->old_save_lines = vdi_save_lines;
+ parent->old_size = vdi_size;
+ }
+
+ if (pfn_valid(t->output.paddr >> PAGE_SHIFT)) {
+ base_off = page_address(pfn_to_page(t->output.paddr >> PAGE_SHIFT));
+ base_off += t->output.paddr & ((1 << PAGE_SHIFT) - 1);
+ } else {
+ base_off = (char *)ioremap_nocache(t->output.paddr,
+ t->output.width * t->output.height *
+ fmt_to_bpp(t->output.format)/8);
+ }
+ if (base_off == NULL) {
+ dev_err(t->dev, "ERR[0x%p]Failed get virtual address\n", t);
+ mutex_unlock(lock);
+ return;
+ }
+
+ /* UP stripe or UP&LEFT stripe */
+ if ((stripe_mode == UP_STRIPE) ||
+ (stripe_mode == (UP_STRIPE | LEFT_STRIPE))) {
+ if (!parent->buf0filled) {
+ offset_addr = t->set.o_off +
+ t->set.sp_setting.ud_split_line*t->set.ostride;
+ dmac_flush_range(base_off + offset_addr,
+ base_off + offset_addr + vdi_size);
+ outer_flush_range(t->output.paddr + offset_addr,
+ t->output.paddr + offset_addr + vdi_size);
+
+ for (i = 0; i < vdi_save_lines; i++)
+ memcpy(parent->vditmpbuf[0] + i*line_size,
+ base_off + offset_addr +
+ i*t->set.ostride, line_size);
+ parent->buf0filled = true;
+ } else {
+ offset_addr = t->set.o_off + (t->output.crop.h -
+ vdi_save_lines) * t->set.ostride;
+ for (i = 0; i < vdi_save_lines; i++)
+ memcpy(base_off + offset_addr + i*t->set.ostride,
+ parent->vditmpbuf[0] + i*line_size, line_size);
+
+ dmac_flush_range(base_off + offset_addr,
+ base_off + offset_addr + i*t->set.ostride);
+ outer_flush_range(t->output.paddr + offset_addr,
+ t->output.paddr + offset_addr + i*t->set.ostride);
+ parent->buf0filled = false;
+ }
+ }
+ /*Down stripe or Down&Left stripe*/
+ else if ((stripe_mode == DOWN_STRIPE) ||
+ (stripe_mode == (DOWN_STRIPE | LEFT_STRIPE))) {
+ if (!parent->buf0filled) {
+ offset_addr = t->set.o_off + vdi_save_lines*t->set.ostride;
+ dmac_flush_range(base_off + offset_addr,
+ base_off + offset_addr + vdi_size);
+ outer_flush_range(t->output.paddr + offset_addr,
+ t->output.paddr + offset_addr + vdi_size);
+
+ for (i = 0; i < vdi_save_lines; i++)
+ memcpy(parent->vditmpbuf[0] + i*line_size,
+ base_off + offset_addr + i*t->set.ostride,
+ line_size);
+ parent->buf0filled = true;
+ } else {
+ offset_addr = t->set.o_off;
+ for (i = 0; i < vdi_save_lines; i++)
+ memcpy(base_off + offset_addr + i*t->set.ostride,
+ parent->vditmpbuf[0] + i*line_size,
+ line_size);
+
+ dmac_flush_range(base_off + offset_addr,
+ base_off + offset_addr + i*t->set.ostride);
+ outer_flush_range(t->output.paddr + offset_addr,
+ t->output.paddr + offset_addr + i*t->set.ostride);
+ parent->buf0filled = false;
+ }
+ }
+ /*Up&Right stripe*/
+ else if (stripe_mode == (UP_STRIPE | RIGHT_STRIPE)) {
+ if (!parent->buf1filled) {
+ offset_addr = t->set.o_off +
+ t->set.sp_setting.ud_split_line*t->set.ostride;
+ dmac_flush_range(base_off + offset_addr,
+ base_off + offset_addr + vdi_size);
+ outer_flush_range(t->output.paddr + offset_addr,
+ t->output.paddr + offset_addr + vdi_size);
+
+ for (i = 0; i < vdi_save_lines; i++)
+ memcpy(parent->vditmpbuf[1] + i*line_size,
+ base_off + offset_addr + i*t->set.ostride,
+ line_size);
+ parent->buf1filled = true;
+ } else {
+ offset_addr = t->set.o_off +
+ (t->output.crop.h - vdi_save_lines)*t->set.ostride;
+ for (i = 0; i < vdi_save_lines; i++)
+ memcpy(base_off + offset_addr + i*t->set.ostride,
+ parent->vditmpbuf[1] + i*line_size,
+ line_size);
+
+ dmac_flush_range(base_off + offset_addr,
+ base_off + offset_addr + i*t->set.ostride);
+ outer_flush_range(t->output.paddr + offset_addr,
+ t->output.paddr + offset_addr + i*t->set.ostride);
+ parent->buf1filled = false;
+ }
+ }
+ /*Down stripe or Down&Right stript*/
+ else if (stripe_mode == (DOWN_STRIPE | RIGHT_STRIPE)) {
+ if (!parent->buf1filled) {
+ offset_addr = t->set.o_off + vdi_save_lines*t->set.ostride;
+ dmac_flush_range(base_off + offset_addr,
+ base_off + offset_addr + vdi_save_lines*t->set.ostride);
+ outer_flush_range(t->output.paddr + offset_addr,
+ t->output.paddr + offset_addr + vdi_save_lines*t->set.ostride);
+
+ for (i = 0; i < vdi_save_lines; i++)
+ memcpy(parent->vditmpbuf[1] + i*line_size,
+ base_off + offset_addr + i*t->set.ostride,
+ line_size);
+ parent->buf1filled = true;
+ } else {
+ offset_addr = t->set.o_off;
+ for (i = 0; i < vdi_save_lines; i++)
+ memcpy(base_off + offset_addr + i*t->set.ostride,
+ parent->vditmpbuf[1] + i*line_size,
+ line_size);
+
+ dmac_flush_range(base_off + offset_addr,
+ base_off + offset_addr + vdi_save_lines*t->set.ostride);
+ outer_flush_range(t->output.paddr + offset_addr,
+ t->output.paddr + offset_addr + vdi_save_lines*t->set.ostride);
+ parent->buf1filled = false;
+ }
+ }
+ if (!pfn_valid(t->output.paddr >> PAGE_SHIFT))
+ iounmap(base_off);
+ mutex_unlock(lock);
+}
+
+static void do_task_release(struct ipu_task_entry *t, int fail)
+{
+ int ret;
+ struct ipu_soc *ipu = t->ipu;
+
+ if (t->input.deinterlace.enable && !fail &&
+ (t->task_no & (UP_STRIPE | DOWN_STRIPE)))
+ vdi_split_process(ipu, t);
+
+ ipu_free_irq(ipu, t->irq, t);
+
+ if (t->vdoa_dma.vaddr)
+ dma_free_coherent(t->dev,
+ t->vdoa_dma.size,
+ t->vdoa_dma.vaddr,
+ t->vdoa_dma.paddr);
+
+ if (only_ic(t->set.mode)) {
+ ret = ipu_disable_channel(ipu, t->set.ic_chan, true);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic",
+ STATE_DISABLE_CHAN_FAIL, ret);
+ if (deinterlace_3_field(t)) {
+ ret = ipu_disable_channel(ipu, t->set.vdi_ic_p_chan,
+ true);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic_p",
+ STATE_DISABLE_CHAN_FAIL, ret);
+ ret = ipu_disable_channel(ipu, t->set.vdi_ic_n_chan,
+ true);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_ic_n",
+ STATE_DISABLE_CHAN_FAIL, ret);
+ }
+ } else if (only_rot(t->set.mode)) {
+ ret = ipu_disable_channel(ipu, t->set.rot_chan, true);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch only_rot",
+ STATE_DISABLE_CHAN_FAIL, ret);
+ } else if (ic_and_rot(t->set.mode)) {
+ ret = ipu_unlink_channels(ipu, t->set.ic_chan, t->set.rot_chan);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_unlink_ch",
+ STATE_UNLINK_CHAN_FAIL, ret);
+ ret = ipu_disable_channel(ipu, t->set.rot_chan, true);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch ic_and_rot-rot",
+ STATE_DISABLE_CHAN_FAIL, ret);
+ ret = ipu_disable_channel(ipu, t->set.ic_chan, true);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch ic_and_rot-ic",
+ STATE_DISABLE_CHAN_FAIL, ret);
+ if (deinterlace_3_field(t)) {
+ ret = ipu_disable_channel(ipu, t->set.vdi_ic_p_chan,
+ true);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch icrot-ic-p",
+ STATE_DISABLE_CHAN_FAIL, ret);
+ ret = ipu_disable_channel(ipu, t->set.vdi_ic_n_chan,
+ true);
+ CHECK_RETCODE_CONT(ret < 0, "ipu_disable_ch icrot-ic-n",
+ STATE_DISABLE_CHAN_FAIL, ret);
+ }
+ }
+
+ if (only_ic(t->set.mode))
+ uninit_ic(ipu, t);
+ else if (only_rot(t->set.mode))
+ uninit_rot(ipu, t);
+ else if (ic_and_rot(t->set.mode)) {
+ uninit_ic(ipu, t);
+ uninit_rot(ipu, t);
+ }
+
+ t->state = STATE_OK;
+ CHECK_PERF(&t->ts_rel);
+ return;
+}
+
+static void do_task_vdoa_only(struct ipu_task_entry *t)
+{
+ int ret;
+
+ ret = init_tiled_ch_bufs(NULL, t);
+ CHECK_RETCODE(ret < 0, "do_vdoa_only", STATE_ERR, out, ret);
+ ret = vdoa_start(t->vdoa_handle, VDOA_DEF_TIMEOUT_MS);
+ vdoa_stop(t->vdoa_handle);
+ CHECK_RETCODE(ret < 0, "vdoa_wait4complete, do_vdoa_only",
+ STATE_VDOA_IRQ_TIMEOUT, out, ret);
+
+ t->state = STATE_OK;
+out:
+ return;
+}
+
+static void do_task(struct ipu_task_entry *t)
+{
+ int r_size;
+ int irq;
+ int ret;
+ uint32_t busy;
+ struct ipu_soc *ipu = t->ipu;
+
+ CHECK_PERF(&t->ts_dotask);
+
+ if (!ipu) {
+ t->state = STATE_NO_IPU;
+ return;
+ }
+
+ init_completion(&t->irq_comp);
+ dev_dbg(ipu->dev, "[0x%p]Do task no:0x%x: id %d\n", (void *)t,
+ t->task_no, t->task_id);
+ dump_task_info(t);
+
+ if (t->set.task & IC_PP) {
+ t->set.ic_chan = MEM_PP_MEM;
+ dev_dbg(ipu->dev, "[0x%p]ic channel MEM_PP_MEM\n", (void *)t);
+ } else if (t->set.task & IC_VF) {
+ t->set.ic_chan = MEM_PRP_VF_MEM;
+ dev_dbg(ipu->dev, "[0x%p]ic channel MEM_PRP_VF_MEM\n", (void *)t);
+ } else if (t->set.task & VDI_VF) {
+ if (t->set.mode & VDOA_BAND_MODE) {
+ t->set.ic_chan = MEM_VDI_MEM;
+ if (deinterlace_3_field(t)) {
+ t->set.vdi_ic_p_chan = MEM_VDI_MEM_P;
+ t->set.vdi_ic_n_chan = MEM_VDI_MEM_N;
+ }
+ dev_dbg(ipu->dev, "[0x%p]ic ch MEM_VDI_MEM\n",
+ (void *)t);
+ } else {
+ t->set.ic_chan = MEM_VDI_PRP_VF_MEM;
+ if (deinterlace_3_field(t)) {
+ t->set.vdi_ic_p_chan = MEM_VDI_PRP_VF_MEM_P;
+ t->set.vdi_ic_n_chan = MEM_VDI_PRP_VF_MEM_N;
+ }
+ dev_dbg(ipu->dev,
+ "[0x%p]ic ch MEM_VDI_PRP_VF_MEM\n", t);
+ }
+ }
+
+ if (t->set.task & ROT_PP) {
+ t->set.rot_chan = MEM_ROT_PP_MEM;
+ dev_dbg(ipu->dev, "[0x%p]rot channel MEM_ROT_PP_MEM\n", (void *)t);
+ } else if (t->set.task & ROT_VF) {
+ t->set.rot_chan = MEM_ROT_VF_MEM;
+ dev_dbg(ipu->dev, "[0x%p]rot channel MEM_ROT_VF_MEM\n", (void *)t);
+ }
+
+ if (t->task_id == IPU_TASK_ID_VF)
+ busy = ic_vf_pp_is_busy(ipu, true);
+ else if (t->task_id == IPU_TASK_ID_PP)
+ busy = ic_vf_pp_is_busy(ipu, false);
+ else {
+ dev_err(ipu->dev, "ERR[no:0x%x]ipu task_id:%d invalid!\n",
+ t->task_no, t->task_id);
+ return;
+ }
+ if (busy) {
+ dev_err(ipu->dev, "ERR[0x%p-no:0x%x]ipu task_id:%d busy!\n",
+ (void *)t, t->task_no, t->task_id);
+ t->state = STATE_IPU_BUSY;
+ return;
+ }
+
+ irq = get_irq(t);
+ if (irq < 0) {
+ t->state = STATE_NO_IRQ;
+ return;
+ }
+ t->irq = irq;
+
+ /* channel setup */
+ if (only_ic(t->set.mode)) {
+ dev_dbg(t->dev, "[0x%p]only ic mode\n", (void *)t);
+ ret = init_ic(ipu, t);
+ CHECK_RETCODE(ret < 0, "init_ic only_ic",
+ t->state, chan_setup, ret);
+ } else if (only_rot(t->set.mode)) {
+ dev_dbg(t->dev, "[0x%p]only rot mode\n", (void *)t);
+ ret = init_rot(ipu, t);
+ CHECK_RETCODE(ret < 0, "init_rot only_rot",
+ t->state, chan_setup, ret);
+ } else if (ic_and_rot(t->set.mode)) {
+ int rot_idx = (t->task_id == IPU_TASK_ID_VF) ? 0 : 1;
+
+ dev_dbg(t->dev, "[0x%p]ic + rot mode\n", (void *)t);
+ t->set.r_fmt = t->output.format;
+ if (t->output.rotate >= IPU_ROTATE_90_RIGHT) {
+ t->set.r_width = t->output.crop.h;
+ t->set.r_height = t->output.crop.w;
+ } else {
+ t->set.r_width = t->output.crop.w;
+ t->set.r_height = t->output.crop.h;
+ }
+ t->set.r_stride = t->set.r_width *
+ bytes_per_pixel(t->set.r_fmt);
+ r_size = PAGE_ALIGN(t->set.r_width * t->set.r_height
+ * fmt_to_bpp(t->set.r_fmt)/8);
+
+ if (r_size > ipu->rot_dma[rot_idx].size) {
+ dev_dbg(t->dev, "[0x%p]realloc rot buffer\n", (void *)t);
+
+ if (ipu->rot_dma[rot_idx].vaddr)
+ dma_free_coherent(t->dev,
+ ipu->rot_dma[rot_idx].size,
+ ipu->rot_dma[rot_idx].vaddr,
+ ipu->rot_dma[rot_idx].paddr);
+
+ ipu->rot_dma[rot_idx].size = r_size;
+ ipu->rot_dma[rot_idx].vaddr = dma_alloc_coherent(t->dev,
+ r_size,
+ &ipu->rot_dma[rot_idx].paddr,
+ GFP_DMA | GFP_KERNEL);
+ CHECK_RETCODE(ipu->rot_dma[rot_idx].vaddr == NULL,
+ "ic_and_rot", STATE_SYS_NO_MEM,
+ chan_setup, -ENOMEM);
+ }
+ t->set.r_paddr = ipu->rot_dma[rot_idx].paddr;
+
+ dev_dbg(t->dev, "[0x%p]rotation:\n", (void *)t);
+ dev_dbg(t->dev, "[0x%p]\tformat = 0x%x\n", (void *)t, t->set.r_fmt);
+ dev_dbg(t->dev, "[0x%p]\twidth = %d\n", (void *)t, t->set.r_width);
+ dev_dbg(t->dev, "[0x%p]\theight = %d\n", (void *)t, t->set.r_height);
+ dev_dbg(t->dev, "[0x%p]\tpaddr = 0x%x\n", (void *)t, t->set.r_paddr);
+ dev_dbg(t->dev, "[0x%p]\trstride = %d\n", (void *)t, t->set.r_stride);
+
+ ret = init_ic(ipu, t);
+ CHECK_RETCODE(ret < 0, "init_ic ic_and_rot",
+ t->state, chan_setup, ret);
+ ret = init_rot(ipu, t);
+ CHECK_RETCODE(ret < 0, "init_rot ic_and_rot",
+ t->state, chan_setup, ret);
+ ret = ipu_link_channels(ipu, t->set.ic_chan,
+ t->set.rot_chan);
+ CHECK_RETCODE(ret < 0, "ipu_link_ch ic_and_rot",
+ STATE_LINK_CHAN_FAIL, chan_setup, ret);
+ } else {
+ dev_err(t->dev, "ERR [0x%p]do task: should not be here\n", t);
+ t->state = STATE_ERR;
+ return;
+ }
+
+ ret = ipu_request_irq(ipu, irq, task_irq_handler, 0, NULL, t);
+ CHECK_RETCODE(ret < 0, "ipu_req_irq",
+ STATE_IRQ_FAIL, chan_setup, ret);
+
+ /* enable/start channel */
+ if (only_ic(t->set.mode)) {
+ ret = ipu_enable_channel(ipu, t->set.ic_chan);
+ CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic",
+ STATE_ENABLE_CHAN_FAIL, chan_en, ret);
+ if (deinterlace_3_field(t)) {
+ ret = ipu_enable_channel(ipu, t->set.vdi_ic_p_chan);
+ CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic_p",
+ STATE_ENABLE_CHAN_FAIL, chan_en, ret);
+ ret = ipu_enable_channel(ipu, t->set.vdi_ic_n_chan);
+ CHECK_RETCODE(ret < 0, "ipu_enable_ch only_ic_n",
+ STATE_ENABLE_CHAN_FAIL, chan_en, ret);
+ }
+
+ ret = ipu_select_buffer(ipu, t->set.ic_chan, IPU_OUTPUT_BUFFER,
+ 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ if (t->overlay_en) {
+ ret = ipu_select_buffer(ipu, t->set.ic_chan,
+ IPU_GRAPH_IN_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_g",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
+ ret = ipu_select_buffer(ipu, t->set.ic_chan,
+ IPU_ALPHA_IN_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_a",
+ STATE_SEL_BUF_FAIL, chan_buf,
+ ret);
+ }
+ }
+ if (!(t->set.mode & VDOA_BAND_MODE)) {
+ if (deinterlace_3_field(t))
+ ipu_select_multi_vdi_buffer(ipu, 0);
+ else {
+ ret = ipu_select_buffer(ipu, t->set.ic_chan,
+ IPU_INPUT_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf only_ic_i",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ }
+ }
+ } else if (only_rot(t->set.mode)) {
+ ret = ipu_enable_channel(ipu, t->set.rot_chan);
+ CHECK_RETCODE(ret < 0, "ipu_enable_ch only_rot",
+ STATE_ENABLE_CHAN_FAIL, chan_en, ret);
+ ret = ipu_select_buffer(ipu, t->set.rot_chan,
+ IPU_OUTPUT_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf only_rot_o",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ ret = ipu_select_buffer(ipu, t->set.rot_chan,
+ IPU_INPUT_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf only_rot_i",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ } else if (ic_and_rot(t->set.mode)) {
+ ret = ipu_enable_channel(ipu, t->set.rot_chan);
+ CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-rot",
+ STATE_ENABLE_CHAN_FAIL, chan_en, ret);
+ ret = ipu_enable_channel(ipu, t->set.ic_chan);
+ CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-ic",
+ STATE_ENABLE_CHAN_FAIL, chan_en, ret);
+ if (deinterlace_3_field(t)) {
+ ret = ipu_enable_channel(ipu, t->set.vdi_ic_p_chan);
+ CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-p",
+ STATE_ENABLE_CHAN_FAIL, chan_en, ret);
+ ret = ipu_enable_channel(ipu, t->set.vdi_ic_n_chan);
+ CHECK_RETCODE(ret < 0, "ipu_enable_ch ic_and_rot-n",
+ STATE_ENABLE_CHAN_FAIL, chan_en, ret);
+ }
+
+ ret = ipu_select_buffer(ipu, t->set.rot_chan,
+ IPU_OUTPUT_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-rot-o",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ if (t->overlay_en) {
+ ret = ipu_select_buffer(ipu, t->set.ic_chan,
+ IPU_GRAPH_IN_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-g",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ if (t->overlay.alpha.mode == IPU_ALPHA_MODE_LOCAL) {
+ ret = ipu_select_buffer(ipu, t->set.ic_chan,
+ IPU_ALPHA_IN_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf icrot-ic-a",
+ STATE_SEL_BUF_FAIL,
+ chan_buf, ret);
+ }
+ }
+ ret = ipu_select_buffer(ipu, t->set.ic_chan,
+ IPU_OUTPUT_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-o",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ if (deinterlace_3_field(t))
+ ipu_select_multi_vdi_buffer(ipu, 0);
+ else {
+ ret = ipu_select_buffer(ipu, t->set.ic_chan,
+ IPU_INPUT_BUFFER, 0);
+ CHECK_RETCODE(ret < 0, "ipu_sel_buf ic_and_rot-ic-i",
+ STATE_SEL_BUF_FAIL, chan_buf, ret);
+ }
+ }
+
+ if (need_split(t))
+ t->state = STATE_IN_PROGRESS;
+
+ if (t->set.mode & VDOA_BAND_MODE) {
+ ret = vdoa_start(t->vdoa_handle, VDOA_DEF_TIMEOUT_MS);
+ CHECK_RETCODE(ret < 0, "vdoa_wait4complete, do_vdoa_band",
+ STATE_VDOA_IRQ_TIMEOUT, chan_rel, ret);
+ }
+
+ CHECK_PERF(&t->ts_waitirq);
+ ret = wait_for_completion_timeout(&t->irq_comp,
+ msecs_to_jiffies(t->timeout - DEF_DELAY_MS));
+ CHECK_PERF(&t->ts_wakeup);
+ CHECK_RETCODE(ret == 0, "wait_for_comp_timeout",
+ STATE_IRQ_TIMEOUT, chan_rel, ret);
+ dev_dbg(t->dev, "[0x%p] no-0x%x ipu irq done!", t, t->task_no);
+
+chan_rel:
+chan_buf:
+chan_en:
+chan_setup:
+ if (t->set.mode & VDOA_BAND_MODE)
+ vdoa_stop(t->vdoa_handle);
+ do_task_release(t, t->state >= STATE_ERR);
+ return;
+}
+
+static void do_task_vdoa_vdi(struct ipu_task_entry *t)
+{
+ int i;
+ int ret;
+ u32 stripe_width;
+
+ /* FIXME: crop mode not support now */
+ stripe_width = t->input.width >> 1;
+ t->input.crop.pos.x = 0;
+ t->input.crop.pos.y = 0;
+ t->input.crop.w = stripe_width;
+ t->input.crop.h = t->input.height;
+ t->output.crop.w = stripe_width;
+ t->output.crop.h = t->input.height;
+
+ for (i = 0; i < 2; i++) {
+ t->input.crop.pos.x = t->input.crop.pos.x + i * stripe_width;
+ t->output.crop.pos.x = t->output.crop.pos.x + i * stripe_width;
+ /* check input */
+ ret = set_crop(&t->input.crop, t->input.width, t->input.height,
+ t->input.format);
+ if (ret < 0) {
+ ret = STATE_ERR;
+ goto done;
+ } else
+ update_offset(t->input.format,
+ t->input.width, t->input.height,
+ t->input.crop.pos.x,
+ t->input.crop.pos.y,
+ &t->set.i_off, &t->set.i_uoff,
+ &t->set.i_voff, &t->set.istride);
+ dev_dbg(t->dev, "i_off:0x%x, i_uoff:0x%x, istride:%d.\n",
+ t->set.i_off, t->set.i_uoff, t->set.istride);
+ /* check output */
+ ret = set_crop(&t->output.crop, t->input.width,
+ t->output.height, t->output.format);
+ if (ret < 0) {
+ ret = STATE_ERR;
+ goto done;
+ } else
+ update_offset(t->output.format,
+ t->output.width, t->output.height,
+ t->output.crop.pos.x,
+ t->output.crop.pos.y,
+ &t->set.o_off, &t->set.o_uoff,
+ &t->set.o_voff, &t->set.ostride);
+
+ dev_dbg(t->dev, "o_off:0x%x, o_uoff:0x%x, ostride:%d.\n",
+ t->set.o_off, t->set.o_uoff, t->set.ostride);
+
+ do_task(t);
+ }
+
+ return;
+done:
+ dev_err(t->dev, "ERR %s set_crop.\n", __func__);
+ t->state = ret;
+ return;
+}
+
+static void get_res_do_task(struct ipu_task_entry *t)
+{
+ uint32_t found;
+ uint32_t split_child;
+ struct mutex *lock;
+
+ found = get_vdoa_ipu_res(t);
+ if (!found) {
+ dev_err(t->dev, "ERR:[0x%p] no-0x%x can not get res\n",
+ t, t->task_no);
+ return;
+ } else {
+ if (t->set.task & VDOA_ONLY)
+ do_task_vdoa_only(t);
+ else if ((IPU_PIX_FMT_TILED_NV12F == t->input.format) &&
+ (t->set.mode & VDOA_BAND_MODE) &&
+ (t->input.crop.w >
+ soc_max_vdi_in_width(t->ipu)))
+ do_task_vdoa_vdi(t);
+ else
+ do_task(t);
+ put_vdoa_ipu_res(t, 0);
+ }
+ if (t->state != STATE_OK) {
+ dev_err(t->dev, "ERR:[0x%p] no-0x%x state: %s\n",
+ t, t->task_no, state_msg[t->state].msg);
+ }
+
+ split_child = need_split(t) && t->parent;
+ if (split_child) {
+ lock = &t->parent->split_lock;
+ mutex_lock(lock);
+ t->split_done = 1;
+ mutex_unlock(lock);
+ wake_up(&t->parent->split_waitq);
+ }
+
+ return;
+}
+
+static void wait_split_task_complete(struct ipu_task_entry *parent,
+ struct ipu_split_task *sp_task, uint32_t size)
+{
+ struct ipu_task_entry *tsk = NULL;
+ int ret = 0, rc;
+ int j, idx = -1;
+ unsigned long flags;
+ struct mutex *lock = &parent->split_lock;
+ int k, busy_vf, busy_pp;
+ struct ipu_soc *ipu;
+ DECLARE_PERF_VAR;
+
+ for (j = 0; j < size; j++) {
+ rc = wait_event_timeout(
+ parent->split_waitq,
+ sp_task_check_done(sp_task, parent, size, &idx),
+ msecs_to_jiffies(parent->timeout - DEF_DELAY_MS));
+ if (!rc) {
+ dev_err(parent->dev,
+ "ERR:[0x%p] no-0x%x, split_task timeout,j:%d,"
+ "size:%d.\n",
+ parent, parent->task_no, j, size);
+ ret = -ETIMEDOUT;
+ goto out;
+ } else {
+ if (idx < 0) {
+ dev_err(parent->dev,
+ "ERR:[0x%p] no-0x%x, invalid task idx:%d\n",
+ parent, parent->task_no, idx);
+ continue;
+ }
+ tsk = sp_task[idx].child_task;
+ mutex_lock(lock);
+ if (!tsk->split_done || !tsk->ipu)
+ dev_err(tsk->dev,
+ "ERR:no-0x%x,split not done:%d/null ipu:0x%p\n",
+ tsk->task_no, tsk->split_done, tsk->ipu);
+ tsk->split_done = 0;
+ mutex_unlock(lock);
+
+ dev_dbg(tsk->dev,
+ "[0x%p] no-0x%x sp_tsk[%d] done,state:%d.\n",
+ tsk, tsk->task_no, idx, tsk->state);
+ #ifdef DBG_IPU_PERF
+ CHECK_PERF(&tsk->ts_rel);
+ PRINT_TASK_STATISTICS;
+ #endif
+ }
+ }
+
+out:
+ if (ret == -ETIMEDOUT) {
+ /* debug */
+ for (k = 0; k < max_ipu_no; k++) {
+ ipu = ipu_get_soc(k);
+ if (IS_ERR(ipu)) {
+ dev_err(parent->dev, "no:0x%x, null ipu:%d\n",
+ parent->task_no, k);
+ } else {
+ busy_vf = ic_vf_pp_is_busy(ipu, true);
+ busy_pp = ic_vf_pp_is_busy(ipu, false);
+ dev_err(parent->dev,
+ "ERR:ipu[%d] busy_vf:%d, busy_pp:%d.\n",
+ k, busy_vf, busy_pp);
+ }
+ }
+ for (k = 0; k < size; k++) {
+ tsk = sp_task[k].child_task;
+ if (!tsk)
+ continue;
+ dev_err(parent->dev,
+ "ERR: sp_task[%d][0x%p] no-0x%x done:%d,"
+ "state:%s,on_list:%d, ipu:0x%p,timeout!\n",
+ k, tsk, tsk->task_no, tsk->split_done,
+ state_msg[tsk->state].msg, tsk->task_in_list,
+ tsk->ipu);
+ }
+ }
+
+ for (j = 0; j < size; j++) {
+ tsk = sp_task[j].child_task;
+ if (!tsk)
+ continue;
+ spin_lock_irqsave(&ipu_task_list_lock, flags);
+ if (tsk->task_in_list) {
+ list_del(&tsk->node);
+ tsk->task_in_list = 0;
+ dev_dbg(tsk->dev,
+ "[0x%p] no-0x%x,id:%d sp_tsk timeout list_del.\n",
+ tsk, tsk->task_no, tsk->task_id);
+ }
+ spin_unlock_irqrestore(&ipu_task_list_lock, flags);
+ if (!tsk->ipu)
+ continue;
+ if (tsk->state != STATE_OK) {
+ dev_err(tsk->dev,
+ "ERR:[0x%p] no-0x%x,id:%d, sp_tsk state: %s\n",
+ tsk, tsk->task_no, tsk->task_id,
+ state_msg[tsk->state].msg);
+ }
+ kref_put(&tsk->refcount, task_mem_free);
+ }
+
+ kfree(parent->vditmpbuf[0]);
+ kfree(parent->vditmpbuf[1]);
+
+ if (ret < 0)
+ parent->state = STATE_TIMEOUT;
+ else
+ parent->state = STATE_OK;
+ return;
+}
+
+static inline int find_task(struct ipu_task_entry **t, int thread_id)
+{
+ int found;
+ unsigned long flags;
+ struct ipu_task_entry *tsk;
+ struct list_head *task_list = &ipu_task_list;
+
+ *t = NULL;
+ spin_lock_irqsave(&ipu_task_list_lock, flags);
+ found = !list_empty(task_list);
+ if (found) {
+ tsk = list_first_entry(task_list, struct ipu_task_entry, node);
+ if (tsk->task_in_list) {
+ list_del(&tsk->node);
+ tsk->task_in_list = 0;
+ *t = tsk;
+ kref_get(&tsk->refcount);
+ dev_dbg(tsk->dev,
+ "thread_id:%d,[0x%p] task_no:0x%x,mode:0x%x list_del\n",
+ thread_id, tsk, tsk->task_no, tsk->set.mode);
+ } else
+ dev_err(tsk->dev,
+ "thread_id:%d,task_no:0x%x,mode:0x%x not on list_del\n",
+ thread_id, tsk->task_no, tsk->set.mode);
+ }
+ spin_unlock_irqrestore(&ipu_task_list_lock, flags);
+
+ return found;
+}
+
+static int ipu_task_thread(void *argv)
+{
+ struct ipu_task_entry *tsk;
+ struct ipu_task_entry *sp_tsk0;
+ struct ipu_split_task sp_task[4];
+ /* priority lower than irq_thread */
+ const struct sched_param param = {
+ .sched_priority = MAX_USER_RT_PRIO/2 - 1,
+ };
+ int ret;
+ int curr_thread_id;
+ uint32_t size;
+ unsigned long flags;
+ unsigned int cpu;
+ struct cpumask cpu_mask;
+ struct ipu_thread_data *data = (struct ipu_thread_data *)argv;
+
+ thread_id++;
+ curr_thread_id = thread_id;
+ sched_setscheduler(current, SCHED_FIFO, &param);
+
+ if (!data->is_vdoa) {
+ cpu = cpumask_first(cpu_online_mask);
+ cpumask_set_cpu(cpu, &cpu_mask);
+ ret = sched_setaffinity(data->ipu->thread[data->id]->pid,
+ &cpu_mask);
+ if (ret < 0) {
+ pr_err("%s: sched_setaffinity fail:%d.\n", __func__, ret);
+ }
+ pr_debug("%s: sched_setaffinity cpu:%d.\n", __func__, cpu);
+ }
+
+ while (!kthread_should_stop()) {
+ int split_fail = 0;
+ int split_parent;
+ int split_child;
+
+ wait_event_interruptible(thread_waitq, find_task(&tsk, curr_thread_id));
+
+ if (!tsk) {
+ pr_err("thread:%d can not find task.\n",
+ curr_thread_id);
+ continue;
+ }
+
+ /* note: other threads run split child task */
+ split_parent = need_split(tsk) && !tsk->parent;
+ split_child = need_split(tsk) && tsk->parent;
+ if (split_parent) {
+ if ((tsk->set.split_mode == RL_SPLIT) ||
+ (tsk->set.split_mode == UD_SPLIT))
+ size = 2;
+ else
+ size = 4;
+ ret = queue_split_task(tsk, sp_task, size);
+ if (ret < 0) {
+ split_fail = 1;
+ } else {
+ struct list_head *pos;
+
+ spin_lock_irqsave(&ipu_task_list_lock, flags);
+
+ sp_tsk0 = list_first_entry(&tsk->split_list,
+ struct ipu_task_entry, node);
+ list_del(&sp_tsk0->node);
+
+ list_for_each(pos, &tsk->split_list) {
+ struct ipu_task_entry *tmp;
+
+ tmp = list_entry(pos,
+ struct ipu_task_entry, node);
+ tmp->task_in_list = 1;
+ dev_dbg(tmp->dev,
+ "[0x%p] no-0x%x,id:%d sp_tsk "
+ "add_to_list.\n", tmp,
+ tmp->task_no, tmp->task_id);
+ }
+ /* add to global list */
+ list_splice(&tsk->split_list, &ipu_task_list);
+
+ spin_unlock_irqrestore(&ipu_task_list_lock,
+ flags);
+ /* let the parent thread do the first sp_task */
+ /* FIXME: ensure the correct sequence for split
+ 4size: 5/6->9/a*/
+ if (!sp_tsk0)
+ dev_err(tsk->dev,
+ "ERR: no-0x%x,can not get split_tsk0\n",
+ tsk->task_no);
+ wake_up_interruptible(&thread_waitq);
+ get_res_do_task(sp_tsk0);
+ dev_dbg(sp_tsk0->dev,
+ "thread:%d complete tsk no:0x%x.\n",
+ curr_thread_id, sp_tsk0->task_no);
+ ret = atomic_read(&req_cnt);
+ if (ret > 0) {
+ wake_up(&res_waitq);
+ dev_dbg(sp_tsk0->dev,
+ "sp_tsk0 sche thread:%d no:0x%x,"
+ "req_cnt:%d\n", curr_thread_id,
+ sp_tsk0->task_no, ret);
+ /* For other threads to get_res */
+ schedule();
+ }
+ }
+ } else
+ get_res_do_task(tsk);
+
+ /* wait for all 4 sp_task finished here or timeout
+ and then release all resources */
+ if (split_parent && !split_fail)
+ wait_split_task_complete(tsk, sp_task, size);
+
+ if (!split_child) {
+ atomic_inc(&tsk->done);
+ wake_up(&tsk->task_waitq);
+ }
+
+ dev_dbg(tsk->dev, "thread:%d complete tsk no:0x%x-[0x%p].\n",
+ curr_thread_id, tsk->task_no, tsk);
+ ret = atomic_read(&req_cnt);
+ if (ret > 0) {
+ wake_up(&res_waitq);
+ dev_dbg(tsk->dev, "sche thread:%d no:0x%x,req_cnt:%d\n",
+ curr_thread_id, tsk->task_no, ret);
+ /* note: give cpu to other threads to get_res */
+ schedule();
+ }
+
+ kref_put(&tsk->refcount, task_mem_free);
+ }
+
+ pr_info("ERR %s exit.\n", __func__);
+ return 0;
+}
+
+int ipu_check_task(struct ipu_task *task)
+{
+ struct ipu_task_entry *tsk;
+ int ret = 0;
+
+ tsk = create_task_entry(task);
+ if (IS_ERR(tsk))
+ return PTR_ERR(tsk);
+
+ ret = check_task(tsk);
+
+ task->input = tsk->input;
+ task->output = tsk->output;
+ task->overlay = tsk->overlay;
+ dump_task_info(tsk);
+
+ kref_put(&tsk->refcount, task_mem_free);
+ if (ret != 0)
+ pr_debug("%s ret:%d.\n", __func__, ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ipu_check_task);
+
+int ipu_queue_task(struct ipu_task *task)
+{
+ struct ipu_task_entry *tsk;
+ unsigned long flags;
+ int ret;
+ u32 tmp_task_no;
+ DECLARE_PERF_VAR;
+
+ tsk = create_task_entry(task);
+ if (IS_ERR(tsk))
+ return PTR_ERR(tsk);
+
+ CHECK_PERF(&tsk->ts_queue);
+ ret = prepare_task(tsk);
+ if (ret < 0)
+ goto done;
+
+ if (need_split(tsk)) {
+ CHECK_PERF(&tsk->ts_dotask);
+ CHECK_PERF(&tsk->ts_waitirq);
+ CHECK_PERF(&tsk->ts_inirq);
+ CHECK_PERF(&tsk->ts_wakeup);
+ }
+
+ /* task_no last four bits for split task type*/
+ tmp_task_no = atomic_inc_return(&frame_no);
+ tsk->task_no = tmp_task_no << 4;
+ init_waitqueue_head(&tsk->task_waitq);
+
+ spin_lock_irqsave(&ipu_task_list_lock, flags);
+ list_add_tail(&tsk->node, &ipu_task_list);
+ tsk->task_in_list = 1;
+ dev_dbg(tsk->dev, "[0x%p,no-0x%x] list_add_tail\n", tsk, tsk->task_no);
+ spin_unlock_irqrestore(&ipu_task_list_lock, flags);
+ wake_up_interruptible(&thread_waitq);
+
+ ret = wait_event_timeout(tsk->task_waitq, atomic_read(&tsk->done),
+ msecs_to_jiffies(tsk->timeout));
+ if (0 == ret) {
+ /* note: the timeout should larger than the internal timeout!*/
+ ret = -ETIMEDOUT;
+ dev_err(tsk->dev, "ERR: [0x%p] no-0x%x, timeout:%dms!\n",
+ tsk, tsk->task_no, tsk->timeout);
+ } else {
+ if (STATE_OK != tsk->state) {
+ dev_err(tsk->dev, "ERR: [0x%p] no-0x%x,state %d: %s\n",
+ tsk, tsk->task_no, tsk->state,
+ state_msg[tsk->state].msg);
+ ret = -ECANCELED;
+ } else
+ ret = 0;
+ }
+
+ spin_lock_irqsave(&ipu_task_list_lock, flags);
+ if (tsk->task_in_list) {
+ list_del(&tsk->node);
+ tsk->task_in_list = 0;
+ dev_dbg(tsk->dev, "[0x%p] no:0x%x list_del\n",
+ tsk, tsk->task_no);
+ }
+ spin_unlock_irqrestore(&ipu_task_list_lock, flags);
+
+#ifdef DBG_IPU_PERF
+ CHECK_PERF(&tsk->ts_rel);
+ PRINT_TASK_STATISTICS;
+ if (ts_frame_avg == 0)
+ ts_frame_avg = ts_frame.tv_nsec / NSEC_PER_USEC +
+ ts_frame.tv_sec * USEC_PER_SEC;
+ else
+ ts_frame_avg = (ts_frame_avg + ts_frame.tv_nsec / NSEC_PER_USEC
+ + ts_frame.tv_sec * USEC_PER_SEC)/2;
+ if (timespec_compare(&ts_frame, &ts_frame_max) > 0)
+ ts_frame_max = ts_frame;
+
+ atomic_inc(&frame_cnt);
+
+ if ((atomic_read(&frame_cnt) % 1000) == 0)
+ pr_debug("ipu_dev: max frame time:%ldus, avg frame time:%dus,"
+ "frame_cnt:%d\n", ts_frame_max.tv_nsec / NSEC_PER_USEC
+ + ts_frame_max.tv_sec * USEC_PER_SEC,
+ ts_frame_avg, atomic_read(&frame_cnt));
+#endif
+done:
+ if (ret < 0)
+ dev_err(tsk->dev, "ERR: no-0x%x,ipu_queue_task err:%d\n",
+ tsk->task_no, ret);
+
+ kref_put(&tsk->refcount, task_mem_free);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ipu_queue_task);
+
+static int mxc_ipu_open(struct inode *inode, struct file *file)
+{
+ file->private_data = (void *)atomic_inc_return(&file_index);
+ return 0;
+}
+
+static long mxc_ipu_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int __user *argp = (void __user *)arg;
+ int ret = 0;
+
+ switch (cmd) {
+ case IPU_CHECK_TASK:
+ {
+ struct ipu_task task;
+
+ if (copy_from_user
+ (&task, (struct ipu_task *) arg,
+ sizeof(struct ipu_task)))
+ return -EFAULT;
+ ret = ipu_check_task(&task);
+ if (copy_to_user((struct ipu_task *) arg,
+ &task, sizeof(struct ipu_task)))
+ return -EFAULT;
+ break;
+ }
+ case IPU_QUEUE_TASK:
+ {
+ struct ipu_task task;
+
+ if (copy_from_user
+ (&task, (struct ipu_task *) arg,
+ sizeof(struct ipu_task)))
+ return -EFAULT;
+ ret = ipu_queue_task(&task);
+ break;
+ }
+ case IPU_ALLOC:
+ {
+ int size;
+ struct ipu_alloc_list *mem;
+
+ mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+ if (mem == NULL)
+ return -ENOMEM;
+
+ if (get_user(size, argp)) {
+ kfree(mem);
+ return -EFAULT;
+ }
+
+ mem->size = PAGE_ALIGN(size);
+
+ mem->cpu_addr = dma_alloc_coherent(ipu_dev, size,
+ &mem->phy_addr,
+ GFP_DMA | GFP_KERNEL);
+ if (mem->cpu_addr == NULL) {
+ kfree(mem);
+ return -ENOMEM;
+ }
+ mem->file_index = file->private_data;
+ mutex_lock(&ipu_alloc_lock);
+ list_add(&mem->list, &ipu_alloc_list);
+ mutex_unlock(&ipu_alloc_lock);
+
+ if (put_user(mem->phy_addr, argp)) {
+ mutex_lock(&ipu_alloc_lock);
+ list_del(&mem->list);
+ mutex_unlock(&ipu_alloc_lock);
+ dma_free_coherent(ipu_dev,
+ mem->size,
+ mem->cpu_addr,
+ mem->phy_addr);
+ kfree(mem);
+ return -EFAULT;
+ }
+
+ dev_dbg(ipu_dev, "allocated %d bytes @ 0x%08X\n",
+ mem->size, mem->phy_addr);
+
+ break;
+ }
+ case IPU_FREE:
+ {
+ unsigned long offset;
+ struct ipu_alloc_list *mem;
+
+ if (get_user(offset, argp))
+ return -EFAULT;
+
+ ret = -EINVAL;
+ mutex_lock(&ipu_alloc_lock);
+ list_for_each_entry(mem, &ipu_alloc_list, list) {
+ if (mem->phy_addr == offset) {
+ list_del(&mem->list);
+ dma_free_coherent(ipu_dev,
+ mem->size,
+ mem->cpu_addr,
+ mem->phy_addr);
+ kfree(mem);
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&ipu_alloc_lock);
+ if (0 == ret)
+ dev_dbg(ipu_dev, "free %d bytes @ 0x%08X\n",
+ mem->size, mem->phy_addr);
+
+ break;
+ }
+ default:
+ break;
+ }
+ return ret;
+}
+
+static int mxc_ipu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ bool found = false;
+ u32 len;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ struct ipu_alloc_list *mem;
+
+ mutex_lock(&ipu_alloc_lock);
+ list_for_each_entry(mem, &ipu_alloc_list, list) {
+ if (offset == mem->phy_addr) {
+ found = true;
+ len = mem->size;
+ break;
+ }
+ }
+ mutex_unlock(&ipu_alloc_lock);
+ if (!found)
+ return -EINVAL;
+
+ if (vma->vm_end - vma->vm_start > len)
+ return -EINVAL;
+
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot)) {
+ printk(KERN_ERR
+ "mmap failed!\n");
+ return -ENOBUFS;
+ }
+ return 0;
+}
+
+static int mxc_ipu_release(struct inode *inode, struct file *file)
+{
+ struct ipu_alloc_list *mem;
+ struct ipu_alloc_list *n;
+
+ mutex_lock(&ipu_alloc_lock);
+ list_for_each_entry_safe(mem, n, &ipu_alloc_list, list) {
+ if ((mem->cpu_addr != 0) &&
+ (file->private_data == mem->file_index)) {
+ list_del(&mem->list);
+ dma_free_coherent(ipu_dev,
+ mem->size,
+ mem->cpu_addr,
+ mem->phy_addr);
+ dev_dbg(ipu_dev, "rel-free %d bytes @ 0x%08X\n",
+ mem->size, mem->phy_addr);
+ kfree(mem);
+ }
+ }
+ mutex_unlock(&ipu_alloc_lock);
+ atomic_dec(&file_index);
+
+ return 0;
+}
+
+static struct file_operations mxc_ipu_fops = {
+ .owner = THIS_MODULE,
+ .open = mxc_ipu_open,
+ .mmap = mxc_ipu_mmap,
+ .release = mxc_ipu_release,
+ .unlocked_ioctl = mxc_ipu_ioctl,
+};
+
+int register_ipu_device(struct ipu_soc *ipu, int id)
+{
+ int ret = 0;
+ static int idx;
+ static struct ipu_thread_data thread_data[5];
+
+ if (!major) {
+ major = register_chrdev(0, "mxc_ipu", &mxc_ipu_fops);
+ if (major < 0) {
+ printk(KERN_ERR "Unable to register mxc_ipu as a char device\n");
+ ret = major;
+ goto register_cdev_fail;
+ }
+
+ ipu_class = class_create(THIS_MODULE, "mxc_ipu");
+ if (IS_ERR(ipu_class)) {
+ ret = PTR_ERR(ipu_class);
+ goto ipu_class_fail;
+ }
+
+ ipu_dev = device_create(ipu_class, NULL, MKDEV(major, 0),
+ NULL, "mxc_ipu");
+ if (IS_ERR(ipu_dev)) {
+ ret = PTR_ERR(ipu_dev);
+ goto dev_create_fail;
+ }
+ ipu_dev->dma_mask = kmalloc(sizeof(*ipu_dev->dma_mask), GFP_KERNEL);
+ *ipu_dev->dma_mask = DMA_BIT_MASK(32);
+ ipu_dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ mutex_init(&ipu_ch_tbl.lock);
+ }
+ max_ipu_no = ++id;
+ ipu->rot_dma[0].size = 0;
+ ipu->rot_dma[1].size = 0;
+
+ thread_data[idx].ipu = ipu;
+ thread_data[idx].id = 0;
+ thread_data[idx].is_vdoa = 0;
+ ipu->thread[0] = kthread_run(ipu_task_thread, &thread_data[idx++],
+ "ipu%d_task", id);
+ if (IS_ERR(ipu->thread[0])) {
+ ret = PTR_ERR(ipu->thread[0]);
+ goto kthread0_fail;
+ }
+
+ thread_data[idx].ipu = ipu;
+ thread_data[idx].id = 1;
+ thread_data[idx].is_vdoa = 0;
+ ipu->thread[1] = kthread_run(ipu_task_thread, &thread_data[idx++],
+ "ipu%d_task", id);
+ if (IS_ERR(ipu->thread[1])) {
+ ret = PTR_ERR(ipu->thread[1]);
+ goto kthread1_fail;
+ }
+
+
+ return ret;
+
+kthread1_fail:
+ kthread_stop(ipu->thread[0]);
+kthread0_fail:
+ if (id == 0)
+ device_destroy(ipu_class, MKDEV(major, 0));
+dev_create_fail:
+ if (id == 0) {
+ class_destroy(ipu_class);
+ }
+ipu_class_fail:
+ if (id == 0)
+ unregister_chrdev(major, "mxc_ipu");
+register_cdev_fail:
+ return ret;
+}
+
+void unregister_ipu_device(struct ipu_soc *ipu, int id)
+{
+ int i;
+
+ kthread_stop(ipu->thread[0]);
+ kthread_stop(ipu->thread[1]);
+ for (i = 0; i < 2; i++) {
+ if (ipu->rot_dma[i].vaddr)
+ dma_free_coherent(ipu_dev,
+ ipu->rot_dma[i].size,
+ ipu->rot_dma[i].vaddr,
+ ipu->rot_dma[i].paddr);
+ }
+
+ if (major) {
+ device_destroy(ipu_class, MKDEV(major, 0));
+ class_destroy(ipu_class);
+ unregister_chrdev(major, "mxc_ipu");
+ major = 0;
+ }
+}
diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c
new file mode 100644
index 000000000000..f2ccb1e3a137
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_disp.c
@@ -0,0 +1,1981 @@
+/*
+ * Copyright 2005-2015 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 ipu_disp.c
+ *
+ * @brief IPU display submodule API functions
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/ipu-v3.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/atomic.h>
+
+#include "ipu_param_mem.h"
+#include "ipu_regs.h"
+
+struct dp_csc_param_t {
+ int mode;
+ void *coeff;
+};
+
+#define SYNC_WAVE 0
+#define NULL_WAVE (-1)
+#define ASYNC_SER_WAVE 6
+
+/* DC display ID assignments */
+#define DC_DISP_ID_SYNC(di) (di)
+#define DC_DISP_ID_SERIAL 2
+#define DC_DISP_ID_ASYNC 3
+
+int dmfc_type_setup;
+
+void _ipu_dmfc_init(struct ipu_soc *ipu, int dmfc_type, int first)
+{
+ u32 dmfc_wr_chan, dmfc_dp_chan;
+
+ if (first) {
+ if (dmfc_type_setup > dmfc_type)
+ dmfc_type = dmfc_type_setup;
+ else
+ dmfc_type_setup = dmfc_type;
+
+ /* disable DMFC-IC channel*/
+ ipu_dmfc_write(ipu, 0x2, DMFC_IC_CTRL);
+ } else if (dmfc_type_setup >= DMFC_HIGH_RESOLUTION_DC) {
+ dev_dbg(ipu->dev, "DMFC high resolution has set, will not change\n");
+ return;
+ } else
+ dmfc_type_setup = dmfc_type;
+
+ if (dmfc_type == DMFC_HIGH_RESOLUTION_DC) {
+ /* 1 - segment 0~3;
+ * 5B - segement 4, 5;
+ * 5F - segement 6, 7;
+ * 1C, 2C and 6B, 6F unused;
+ */
+ dev_info(ipu->dev, "IPU DMFC DC HIGH RESOLUTION: 1(0~3), 5B(4,5), 5F(6,7)\n");
+ dmfc_wr_chan = 0x00000088;
+ dmfc_dp_chan = 0x00009694;
+ ipu->dmfc_size_28 = 256*4;
+ ipu->dmfc_size_29 = 0;
+ ipu->dmfc_size_24 = 0;
+ ipu->dmfc_size_27 = 128*4;
+ ipu->dmfc_size_23 = 128*4;
+ } else if (dmfc_type == DMFC_HIGH_RESOLUTION_DP) {
+ /* 1 - segment 0, 1;
+ * 5B - segement 2~5;
+ * 5F - segement 6,7;
+ * 1C, 2C and 6B, 6F unused;
+ */
+ dev_info(ipu->dev, "IPU DMFC DP HIGH RESOLUTION: 1(0,1), 5B(2~5), 5F(6,7)\n");
+ dmfc_wr_chan = 0x00000090;
+ dmfc_dp_chan = 0x0000968a;
+ ipu->dmfc_size_28 = 128*4;
+ ipu->dmfc_size_29 = 0;
+ ipu->dmfc_size_24 = 0;
+ ipu->dmfc_size_27 = 128*4;
+ ipu->dmfc_size_23 = 256*4;
+ } else if (dmfc_type == DMFC_HIGH_RESOLUTION_ONLY_DP) {
+ /* 5B - segement 0~3;
+ * 5F - segement 4~7;
+ * 1, 1C, 2C and 6B, 6F unused;
+ */
+ dev_info(ipu->dev, "IPU DMFC ONLY-DP HIGH RESOLUTION: 5B(0~3), 5F(4~7)\n");
+ dmfc_wr_chan = 0x00000000;
+ dmfc_dp_chan = 0x00008c88;
+ ipu->dmfc_size_28 = 0;
+ ipu->dmfc_size_29 = 0;
+ ipu->dmfc_size_24 = 0;
+ ipu->dmfc_size_27 = 256*4;
+ ipu->dmfc_size_23 = 256*4;
+ } else {
+ /* 1 - segment 0, 1;
+ * 5B - segement 4, 5;
+ * 5F - segement 6, 7;
+ * 1C, 2C and 6B, 6F unused;
+ */
+ dev_info(ipu->dev, "IPU DMFC NORMAL mode: 1(0~1), 5B(4,5), 5F(6,7)\n");
+ dmfc_wr_chan = 0x00000090;
+ dmfc_dp_chan = 0x00009694;
+ ipu->dmfc_size_28 = 128*4;
+ ipu->dmfc_size_29 = 0;
+ ipu->dmfc_size_24 = 0;
+ ipu->dmfc_size_27 = 128*4;
+ ipu->dmfc_size_23 = 128*4;
+ }
+ ipu_dmfc_write(ipu, dmfc_wr_chan, DMFC_WR_CHAN);
+ ipu_dmfc_write(ipu, 0x202020F6, DMFC_WR_CHAN_DEF);
+ ipu_dmfc_write(ipu, dmfc_dp_chan, DMFC_DP_CHAN);
+ /* Enable chan 5 watermark set at 5 bursts and clear at 7 bursts */
+ ipu_dmfc_write(ipu, 0x2020F6F6, DMFC_DP_CHAN_DEF);
+}
+
+static int __init dmfc_setup(char *options)
+{
+ get_option(&options, &dmfc_type_setup);
+ if (dmfc_type_setup > DMFC_HIGH_RESOLUTION_ONLY_DP)
+ dmfc_type_setup = DMFC_HIGH_RESOLUTION_ONLY_DP;
+ return 1;
+}
+__setup("dmfc=", dmfc_setup);
+
+void _ipu_dmfc_set_wait4eot(struct ipu_soc *ipu, int dma_chan, int width)
+{
+ u32 dmfc_gen1 = ipu_dmfc_read(ipu, DMFC_GENERAL1);
+
+ if (width >= HIGH_RESOLUTION_WIDTH) {
+ if (dma_chan == 23)
+ _ipu_dmfc_init(ipu, DMFC_HIGH_RESOLUTION_DP, 0);
+ else if (dma_chan == 28)
+ _ipu_dmfc_init(ipu, DMFC_HIGH_RESOLUTION_DC, 0);
+ }
+
+ if (dma_chan == 23) { /*5B*/
+ if (ipu->dmfc_size_23/width > 3)
+ dmfc_gen1 |= 1UL << 20;
+ else
+ dmfc_gen1 &= ~(1UL << 20);
+ } else if (dma_chan == 24) { /*6B*/
+ if (ipu->dmfc_size_24/width > 1)
+ dmfc_gen1 |= 1UL << 22;
+ else
+ dmfc_gen1 &= ~(1UL << 22);
+ } else if (dma_chan == 27) { /*5F*/
+ if (ipu->dmfc_size_27/width > 2)
+ dmfc_gen1 |= 1UL << 21;
+ else
+ dmfc_gen1 &= ~(1UL << 21);
+ } else if (dma_chan == 28) { /*1*/
+ if (ipu->dmfc_size_28/width > 2)
+ dmfc_gen1 |= 1UL << 16;
+ else
+ dmfc_gen1 &= ~(1UL << 16);
+ } else if (dma_chan == 29) { /*6F*/
+ if (ipu->dmfc_size_29/width > 1)
+ dmfc_gen1 |= 1UL << 23;
+ else
+ dmfc_gen1 &= ~(1UL << 23);
+ }
+
+ ipu_dmfc_write(ipu, dmfc_gen1, DMFC_GENERAL1);
+}
+
+void _ipu_dmfc_set_burst_size(struct ipu_soc *ipu, int dma_chan, int burst_size)
+{
+ u32 dmfc_wr_chan = ipu_dmfc_read(ipu, DMFC_WR_CHAN);
+ u32 dmfc_dp_chan = ipu_dmfc_read(ipu, DMFC_DP_CHAN);
+ int dmfc_bs = 0;
+
+ switch (burst_size) {
+ case 64:
+ dmfc_bs = 0x40;
+ break;
+ case 32:
+ case 20:
+ dmfc_bs = 0x80;
+ break;
+ case 16:
+ dmfc_bs = 0xc0;
+ break;
+ default:
+ dev_err(ipu->dev, "Unsupported burst size %d\n",
+ burst_size);
+ return;
+ }
+
+ if (dma_chan == 23) { /*5B*/
+ dmfc_dp_chan &= ~(0xc0);
+ dmfc_dp_chan |= dmfc_bs;
+ } else if (dma_chan == 27) { /*5F*/
+ dmfc_dp_chan &= ~(0xc000);
+ dmfc_dp_chan |= (dmfc_bs << 8);
+ } else if (dma_chan == 28) { /*1*/
+ dmfc_wr_chan &= ~(0xc0);
+ dmfc_wr_chan |= dmfc_bs;
+ }
+
+ ipu_dmfc_write(ipu, dmfc_wr_chan, DMFC_WR_CHAN);
+ ipu_dmfc_write(ipu, dmfc_dp_chan, DMFC_DP_CHAN);
+}
+
+static void _ipu_di_data_wave_config(struct ipu_soc *ipu,
+ int di, int wave_gen,
+ int access_size, int component_size)
+{
+ u32 reg;
+ reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
+ (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
+ ipu_di_write(ipu, di, reg, DI_DW_GEN(wave_gen));
+}
+
+static void _ipu_di_data_pin_config(struct ipu_soc *ipu,
+ int di, int wave_gen, int di_pin, int set,
+ int up, int down)
+{
+ u32 reg;
+
+ reg = ipu_di_read(ipu, di, DI_DW_GEN(wave_gen));
+ reg &= ~(0x3 << (di_pin * 2));
+ reg |= set << (di_pin * 2);
+ ipu_di_write(ipu, di, reg, DI_DW_GEN(wave_gen));
+
+ ipu_di_write(ipu, di, (down << 16) | up, DI_DW_SET(wave_gen, set));
+}
+
+static void _ipu_di_sync_config(struct ipu_soc *ipu,
+ int di, int wave_gen,
+ int run_count, int run_src,
+ int offset_count, int offset_src,
+ int repeat_count, int cnt_clr_src,
+ int cnt_polarity_gen_en,
+ int cnt_polarity_clr_src,
+ int cnt_polarity_trigger_src,
+ int cnt_up, int cnt_down)
+{
+ u32 reg;
+
+ if ((run_count >= 0x1000) || (offset_count >= 0x1000) || (repeat_count >= 0x1000) ||
+ (cnt_up >= 0x400) || (cnt_down >= 0x400)) {
+ dev_err(ipu->dev, "DI%d counters out of range.\n", di);
+ return;
+ }
+
+ reg = (run_count << 19) | (++run_src << 16) |
+ (offset_count << 3) | ++offset_src;
+ ipu_di_write(ipu, di, reg, DI_SW_GEN0(wave_gen));
+ reg = (cnt_polarity_gen_en << 29) | (++cnt_clr_src << 25) |
+ (++cnt_polarity_trigger_src << 12) | (++cnt_polarity_clr_src << 9);
+ reg |= (cnt_down << 16) | cnt_up;
+ if (repeat_count == 0) {
+ /* Enable auto reload */
+ reg |= 0x10000000;
+ }
+ ipu_di_write(ipu, di, reg, DI_SW_GEN1(wave_gen));
+ reg = ipu_di_read(ipu, di, DI_STP_REP(wave_gen));
+ reg &= ~(0xFFFF << (16 * ((wave_gen - 1) & 0x1)));
+ reg |= repeat_count << (16 * ((wave_gen - 1) & 0x1));
+ ipu_di_write(ipu, di, reg, DI_STP_REP(wave_gen));
+}
+
+static void _ipu_dc_map_link(struct ipu_soc *ipu,
+ int current_map,
+ int base_map_0, int buf_num_0,
+ int base_map_1, int buf_num_1,
+ int base_map_2, int buf_num_2)
+{
+ int ptr_0 = base_map_0 * 3 + buf_num_0;
+ int ptr_1 = base_map_1 * 3 + buf_num_1;
+ int ptr_2 = base_map_2 * 3 + buf_num_2;
+ int ptr;
+ u32 reg;
+ ptr = (ptr_2 << 10) + (ptr_1 << 5) + ptr_0;
+
+ reg = ipu_dc_read(ipu, DC_MAP_CONF_PTR(current_map));
+ reg &= ~(0x1F << ((16 * (current_map & 0x1))));
+ reg |= ptr << ((16 * (current_map & 0x1)));
+ ipu_dc_write(ipu, reg, DC_MAP_CONF_PTR(current_map));
+}
+
+static void _ipu_dc_map_config(struct ipu_soc *ipu,
+ int map, int byte_num, int offset, int mask)
+{
+ int ptr = map * 3 + byte_num;
+ u32 reg;
+
+ reg = ipu_dc_read(ipu, DC_MAP_CONF_VAL(ptr));
+ reg &= ~(0xFFFF << (16 * (ptr & 0x1)));
+ reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
+ ipu_dc_write(ipu, reg, DC_MAP_CONF_VAL(ptr));
+
+ reg = ipu_dc_read(ipu, DC_MAP_CONF_PTR(map));
+ reg &= ~(0x1F << ((16 * (map & 0x1)) + (5 * byte_num)));
+ reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
+ ipu_dc_write(ipu, reg, DC_MAP_CONF_PTR(map));
+}
+
+static void _ipu_dc_map_clear(struct ipu_soc *ipu, int map)
+{
+ u32 reg = ipu_dc_read(ipu, DC_MAP_CONF_PTR(map));
+ ipu_dc_write(ipu, reg & ~(0xFFFF << (16 * (map & 0x1))),
+ DC_MAP_CONF_PTR(map));
+}
+
+static void _ipu_dc_write_tmpl(struct ipu_soc *ipu,
+ int word, u32 opcode, u32 operand, int map,
+ int wave, int glue, int sync, int stop)
+{
+ u32 reg;
+
+ if (opcode == WRG) {
+ reg = sync;
+ reg |= (glue << 4);
+ reg |= (++wave << 11);
+ reg |= ((operand & 0x1FFFF) << 15);
+ ipu_dc_tmpl_write(ipu, reg, word * 8);
+
+ reg = (operand >> 17);
+ reg |= opcode << 7;
+ reg |= (stop << 9);
+ ipu_dc_tmpl_write(ipu, reg, word * 8 + 4);
+ } else {
+ reg = sync;
+ reg |= (glue << 4);
+ reg |= (++wave << 11);
+ reg |= (++map << 15);
+ reg |= (operand << 20) & 0xFFF00000;
+ ipu_dc_tmpl_write(ipu, reg, word * 8);
+
+ reg = (operand >> 12);
+ reg |= opcode << 4;
+ reg |= (stop << 9);
+ ipu_dc_tmpl_write(ipu, reg, word * 8 + 4);
+ }
+}
+
+static void _ipu_dc_link_event(struct ipu_soc *ipu,
+ int chan, int event, int addr, int priority)
+{
+ u32 reg;
+ u32 address_shift;
+ if (event < DC_EVEN_UGDE0) {
+ reg = ipu_dc_read(ipu, DC_RL_CH(chan, event));
+ reg &= ~(0xFFFF << (16 * (event & 0x1)));
+ reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
+ ipu_dc_write(ipu, reg, DC_RL_CH(chan, event));
+ } else {
+ reg = ipu_dc_read(ipu, DC_UGDE_0((event - DC_EVEN_UGDE0) / 2));
+ if ((event - DC_EVEN_UGDE0) & 0x1) {
+ reg &= ~(0x2FF << 16);
+ reg |= (addr << 16);
+ reg |= priority ? (2 << 24) : 0x0;
+ } else {
+ reg &= ~0xFC00FFFF;
+ if (priority)
+ chan = (chan >> 1) +
+ ((((chan & 0x1) + ((chan & 0x2) >> 1))) | (chan >> 3));
+ else
+ chan = 0x7;
+ address_shift = ((event - DC_EVEN_UGDE0) >> 1) ? 7 : 8;
+ reg |= (addr << address_shift) | (priority << 3) | chan;
+ }
+ ipu_dc_write(ipu, reg, DC_UGDE_0((event - DC_EVEN_UGDE0) / 2));
+ }
+}
+
+/* Y = R * 1.200 + G * 2.343 + B * .453 + 0.250;
+ U = R * -.672 + G * -1.328 + B * 2.000 + 512.250.;
+ V = R * 2.000 + G * -1.672 + B * -.328 + 512.250.;*/
+static const int rgb2ycbcr_coeff[5][3] = {
+ {0x4D, 0x96, 0x1D},
+ {-0x2B, -0x55, 0x80},
+ {0x80, -0x6B, -0x15},
+ {0x0000, 0x0200, 0x0200}, /* B0, B1, B2 */
+ {0x2, 0x2, 0x2}, /* S0, S1, S2 */
+};
+
+/* R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
+ G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
+ B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128); */
+static const int ycbcr2rgb_coeff[5][3] = {
+ {0x095, 0x000, 0x0CC},
+ {0x095, 0x3CE, 0x398},
+ {0x095, 0x0FF, 0x000},
+ {0x3E42, 0x010A, 0x3DD6}, /*B0,B1,B2 */
+ {0x1, 0x1, 0x1}, /*S0,S1,S2 */
+};
+
+#define mask_a(a) ((u32)(a) & 0x3FF)
+#define mask_b(b) ((u32)(b) & 0x3FFF)
+
+/* Pls keep S0, S1 and S2 as 0x2 by using this convertion */
+static int _rgb_to_yuv(int n, int red, int green, int blue)
+{
+ int c;
+ c = red * rgb2ycbcr_coeff[n][0];
+ c += green * rgb2ycbcr_coeff[n][1];
+ c += blue * rgb2ycbcr_coeff[n][2];
+ c /= 16;
+ c += rgb2ycbcr_coeff[3][n] * 4;
+ c += 8;
+ c /= 16;
+ if (c < 0)
+ c = 0;
+ if (c > 255)
+ c = 255;
+ return c;
+}
+
+/*
+ * Row is for BG: RGB2YUV YUV2RGB RGB2RGB YUV2YUV CSC_NONE
+ * Column is for FG: RGB2YUV YUV2RGB RGB2RGB YUV2YUV CSC_NONE
+ */
+static struct dp_csc_param_t dp_csc_array[CSC_NUM][CSC_NUM] = {
+{
+ {DP_COM_CONF_CSC_DEF_BOTH, (void *)&rgb2ycbcr_coeff},
+ {0, 0}, {0, 0},
+ {DP_COM_CONF_CSC_DEF_BG, (void *)&rgb2ycbcr_coeff},
+ {DP_COM_CONF_CSC_DEF_BG, (void *)&rgb2ycbcr_coeff}
+},
+{
+ {0, 0},
+ {DP_COM_CONF_CSC_DEF_BOTH, (void *)&ycbcr2rgb_coeff},
+ {DP_COM_CONF_CSC_DEF_BG, (void *)&ycbcr2rgb_coeff},
+ {0, 0},
+ {DP_COM_CONF_CSC_DEF_BG, (void *)&ycbcr2rgb_coeff}
+},
+{
+ {0, 0},
+ {DP_COM_CONF_CSC_DEF_FG, (void *)&ycbcr2rgb_coeff},
+ {0, 0}, {0, 0}, {0, 0}
+},
+{
+ {DP_COM_CONF_CSC_DEF_FG, (void *)&rgb2ycbcr_coeff},
+ {0, 0}, {0, 0}, {0, 0}, {0, 0}
+},
+{
+ {DP_COM_CONF_CSC_DEF_FG, (void *)&rgb2ycbcr_coeff},
+ {DP_COM_CONF_CSC_DEF_FG, (void *)&ycbcr2rgb_coeff},
+ {0, 0}, {0, 0}, {0, 0}
+}
+};
+
+void __ipu_dp_csc_setup(struct ipu_soc *ipu,
+ int dp, struct dp_csc_param_t dp_csc_param,
+ bool srm_mode_update)
+{
+ u32 reg;
+ const int (*coeff)[5][3];
+
+ if (dp_csc_param.mode >= 0) {
+ reg = ipu_dp_read(ipu, DP_COM_CONF(dp));
+ reg &= ~DP_COM_CONF_CSC_DEF_MASK;
+ reg |= dp_csc_param.mode;
+ ipu_dp_write(ipu, reg, DP_COM_CONF(dp));
+ }
+
+ coeff = dp_csc_param.coeff;
+
+ if (coeff) {
+ ipu_dp_write(ipu, mask_a((*coeff)[0][0]) |
+ (mask_a((*coeff)[0][1]) << 16), DP_CSC_A_0(dp));
+ ipu_dp_write(ipu, mask_a((*coeff)[0][2]) |
+ (mask_a((*coeff)[1][0]) << 16), DP_CSC_A_1(dp));
+ ipu_dp_write(ipu, mask_a((*coeff)[1][1]) |
+ (mask_a((*coeff)[1][2]) << 16), DP_CSC_A_2(dp));
+ ipu_dp_write(ipu, mask_a((*coeff)[2][0]) |
+ (mask_a((*coeff)[2][1]) << 16), DP_CSC_A_3(dp));
+ ipu_dp_write(ipu, mask_a((*coeff)[2][2]) |
+ (mask_b((*coeff)[3][0]) << 16) |
+ ((*coeff)[4][0] << 30), DP_CSC_0(dp));
+ ipu_dp_write(ipu, mask_b((*coeff)[3][1]) | ((*coeff)[4][1] << 14) |
+ (mask_b((*coeff)[3][2]) << 16) |
+ ((*coeff)[4][2] << 30), DP_CSC_1(dp));
+ }
+
+ if (srm_mode_update) {
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+ }
+}
+
+int _ipu_dp_init(struct ipu_soc *ipu,
+ ipu_channel_t channel, uint32_t in_pixel_fmt,
+ uint32_t out_pixel_fmt)
+{
+ int in_fmt, out_fmt;
+ int dp;
+ int partial = false;
+ uint32_t reg;
+
+ if (channel == MEM_FG_SYNC) {
+ dp = DP_SYNC;
+ partial = true;
+ } else if (channel == MEM_BG_SYNC) {
+ dp = DP_SYNC;
+ partial = false;
+ } else if (channel == MEM_BG_ASYNC0) {
+ dp = DP_ASYNC0;
+ partial = false;
+ } else {
+ return -EINVAL;
+ }
+
+ in_fmt = format_to_colorspace(in_pixel_fmt);
+ out_fmt = format_to_colorspace(out_pixel_fmt);
+
+ if (partial) {
+ if (in_fmt == RGB) {
+ if (out_fmt == RGB)
+ ipu->fg_csc_type = RGB2RGB;
+ else
+ ipu->fg_csc_type = RGB2YUV;
+ } else {
+ if (out_fmt == RGB)
+ ipu->fg_csc_type = YUV2RGB;
+ else
+ ipu->fg_csc_type = YUV2YUV;
+ }
+ } else {
+ if (in_fmt == RGB) {
+ if (out_fmt == RGB)
+ ipu->bg_csc_type = RGB2RGB;
+ else
+ ipu->bg_csc_type = RGB2YUV;
+ } else {
+ if (out_fmt == RGB)
+ ipu->bg_csc_type = YUV2RGB;
+ else
+ ipu->bg_csc_type = YUV2YUV;
+ }
+ }
+
+ /* Transform color key from rgb to yuv if CSC is enabled */
+ reg = ipu_dp_read(ipu, DP_COM_CONF(dp));
+ if (ipu->color_key_4rgb && (reg & DP_COM_CONF_GWCKE) &&
+ (((ipu->fg_csc_type == RGB2YUV) && (ipu->bg_csc_type == YUV2YUV)) ||
+ ((ipu->fg_csc_type == YUV2YUV) && (ipu->bg_csc_type == RGB2YUV)) ||
+ ((ipu->fg_csc_type == YUV2YUV) && (ipu->bg_csc_type == YUV2YUV)) ||
+ ((ipu->fg_csc_type == YUV2RGB) && (ipu->bg_csc_type == YUV2RGB)))) {
+ int red, green, blue;
+ int y, u, v;
+ uint32_t color_key = ipu_dp_read(ipu, DP_GRAPH_WIND_CTRL(dp)) & 0xFFFFFFL;
+
+ dev_dbg(ipu->dev, "_ipu_dp_init color key 0x%x need change to yuv fmt!\n", color_key);
+
+ red = (color_key >> 16) & 0xFF;
+ green = (color_key >> 8) & 0xFF;
+ blue = color_key & 0xFF;
+
+ y = _rgb_to_yuv(0, red, green, blue);
+ u = _rgb_to_yuv(1, red, green, blue);
+ v = _rgb_to_yuv(2, red, green, blue);
+ color_key = (y << 16) | (u << 8) | v;
+
+ reg = ipu_dp_read(ipu, DP_GRAPH_WIND_CTRL(dp)) & 0xFF000000L;
+ ipu_dp_write(ipu, reg | color_key, DP_GRAPH_WIND_CTRL(dp));
+ ipu->color_key_4rgb = false;
+
+ dev_dbg(ipu->dev, "_ipu_dp_init color key change to yuv fmt 0x%x!\n", color_key);
+ }
+
+ __ipu_dp_csc_setup(ipu, dp,
+ dp_csc_array[ipu->bg_csc_type][ipu->fg_csc_type],
+ false);
+
+ return 0;
+}
+
+void _ipu_dp_uninit(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ int dp;
+ int partial = false;
+
+ if (channel == MEM_FG_SYNC) {
+ dp = DP_SYNC;
+ partial = true;
+ } else if (channel == MEM_BG_SYNC) {
+ dp = DP_SYNC;
+ partial = false;
+ } else if (channel == MEM_BG_ASYNC0) {
+ dp = DP_ASYNC0;
+ partial = false;
+ } else {
+ return;
+ }
+
+ if (partial)
+ ipu->fg_csc_type = CSC_NONE;
+ else
+ ipu->bg_csc_type = CSC_NONE;
+
+ __ipu_dp_csc_setup(ipu, dp, dp_csc_array[ipu->bg_csc_type][ipu->fg_csc_type], false);
+}
+
+void _ipu_dc_init(struct ipu_soc *ipu, int dc_chan, int di, bool interlaced, uint32_t pixel_fmt)
+{
+ u32 reg = 0;
+
+ if ((dc_chan == 1) || (dc_chan == 5)) {
+ if (interlaced) {
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NL, 0, 3);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOL, 0, 2);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA, 0, 1);
+ } else {
+ if (di) {
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NL, 2, 3);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOL, 3, 2);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA, 1, 1);
+ if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
+ (pixel_fmt == IPU_PIX_FMT_UYVY) ||
+ (pixel_fmt == IPU_PIX_FMT_YVYU) ||
+ (pixel_fmt == IPU_PIX_FMT_VYUY)) {
+ _ipu_dc_link_event(ipu, dc_chan, DC_ODD_UGDE1, 9, 5);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVEN_UGDE1, 8, 5);
+ }
+ } else {
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NL, 5, 3);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOL, 6, 2);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA, 12, 1);
+ if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
+ (pixel_fmt == IPU_PIX_FMT_UYVY) ||
+ (pixel_fmt == IPU_PIX_FMT_YVYU) ||
+ (pixel_fmt == IPU_PIX_FMT_VYUY)) {
+ _ipu_dc_link_event(ipu, dc_chan, DC_ODD_UGDE0, 10, 5);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVEN_UGDE0, 11, 5);
+ }
+ }
+ }
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NF, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NFIELD, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOF, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOFIELD, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR, 0, 0);
+
+ reg = 0x2;
+ reg |= DC_DISP_ID_SYNC(di) << DC_WR_CH_CONF_PROG_DISP_ID_OFFSET;
+ reg |= di << 2;
+ if (interlaced)
+ reg |= DC_WR_CH_CONF_FIELD_MODE;
+ } else if ((dc_chan == 8) || (dc_chan == 9)) {
+ /* async channels */
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_W_0, 0x64, 1);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_W_1, 0x64, 1);
+
+ reg = 0x3;
+ reg |= DC_DISP_ID_SERIAL << DC_WR_CH_CONF_PROG_DISP_ID_OFFSET;
+ }
+ ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
+
+ ipu_dc_write(ipu, 0x00000000, DC_WR_CH_ADDR(dc_chan));
+
+ ipu_dc_write(ipu, 0x00000084, DC_GEN);
+}
+
+void _ipu_dc_uninit(struct ipu_soc *ipu, int dc_chan)
+{
+ if ((dc_chan == 1) || (dc_chan == 5)) {
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NL, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOL, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NF, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NFIELD, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOF, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_EOFIELD, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_ODD_UGDE0, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVEN_UGDE0, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_ODD_UGDE1, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVEN_UGDE1, 0, 0);
+ } else if ((dc_chan == 8) || (dc_chan == 9)) {
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR_W_0, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR_W_1, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN_W_0, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN_W_1, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_W_0, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_W_1, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR_R_0, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_ADDR_R_1, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN_R_0, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_CHAN_R_1, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_R_0, 0, 0);
+ _ipu_dc_link_event(ipu, dc_chan, DC_EVT_NEW_DATA_R_1, 0, 0);
+ }
+}
+
+int _ipu_disp_chan_is_interlaced(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ if (channel == MEM_DC_SYNC)
+ return !!(ipu_dc_read(ipu, DC_WR_CH_CONF_1) &
+ DC_WR_CH_CONF_FIELD_MODE);
+ else if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC))
+ return !!(ipu_dc_read(ipu, DC_WR_CH_CONF_5) &
+ DC_WR_CH_CONF_FIELD_MODE);
+ return 0;
+}
+
+void _ipu_dp_dc_enable(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ int di;
+ uint32_t reg;
+ uint32_t dc_chan;
+ int irq = 0;
+
+ if (channel == MEM_FG_SYNC)
+ irq = IPU_IRQ_DP_SF_END;
+ else if (channel == MEM_DC_SYNC)
+ dc_chan = 1;
+ else if (channel == MEM_BG_SYNC)
+ dc_chan = 5;
+ else
+ return;
+
+ if (channel == MEM_FG_SYNC) {
+ /* Enable FG channel */
+ reg = ipu_dp_read(ipu, DP_COM_CONF(DP_SYNC));
+ ipu_dp_write(ipu, reg | DP_COM_CONF_FG_EN, DP_COM_CONF(DP_SYNC));
+
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+ return;
+ } else if (channel == MEM_BG_SYNC) {
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+ }
+
+ di = ipu->dc_di_assignment[dc_chan];
+
+ /* Make sure other DC sync channel is not assigned same DI */
+ reg = ipu_dc_read(ipu, DC_WR_CH_CONF(6 - dc_chan));
+ if ((di << 2) == (reg & DC_WR_CH_CONF_PROG_DI_ID)) {
+ reg &= ~DC_WR_CH_CONF_PROG_DI_ID;
+ reg |= di ? 0 : DC_WR_CH_CONF_PROG_DI_ID;
+ ipu_dc_write(ipu, reg, DC_WR_CH_CONF(6 - dc_chan));
+ }
+
+ reg = ipu_dc_read(ipu, DC_WR_CH_CONF(dc_chan));
+ reg |= 4 << DC_WR_CH_CONF_PROG_TYPE_OFFSET;
+ ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
+
+ clk_prepare_enable(ipu->pixel_clk[di]);
+ ipu->pixel_clk_en[ipu->dc_di_assignment[dc_chan]] = true;
+}
+
+static irqreturn_t dc_irq_handler(int irq, void *dev_id)
+{
+ struct ipu_soc *ipu = dev_id;
+ struct completion *comp = &ipu->dc_comp;
+ uint32_t reg;
+ uint32_t dc_chan;
+
+ if (irq == IPU_IRQ_DC_FC_1)
+ dc_chan = 1;
+ else
+ dc_chan = 5;
+
+ if (!ipu->dc_swap) {
+ reg = ipu_dc_read(ipu, DC_WR_CH_CONF(dc_chan));
+ reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
+ ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
+
+ reg = ipu_cm_read(ipu, IPU_DISP_GEN);
+ if (ipu->dc_di_assignment[dc_chan])
+ reg &= ~DI1_COUNTER_RELEASE;
+ else
+ reg &= ~DI0_COUNTER_RELEASE;
+ ipu_cm_write(ipu, reg, IPU_DISP_GEN);
+ }
+
+ complete(comp);
+ return IRQ_HANDLED;
+}
+
+void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
+{
+ int ret;
+ uint32_t reg;
+ uint32_t csc;
+ uint32_t dc_chan;
+ int irq = 0;
+ int timeout = 50;
+
+ ipu->dc_swap = swap;
+
+ if (channel == MEM_DC_SYNC) {
+ dc_chan = 1;
+ irq = IPU_IRQ_DC_FC_1;
+ } else if (channel == MEM_BG_SYNC) {
+ dc_chan = 5;
+ irq = IPU_IRQ_DP_SF_END;
+ } else if (channel == MEM_FG_SYNC) {
+ /* Disable FG channel */
+ dc_chan = 5;
+
+ reg = ipu_dp_read(ipu, DP_COM_CONF(DP_SYNC));
+ csc = reg & DP_COM_CONF_CSC_DEF_MASK;
+ if (csc == DP_COM_CONF_CSC_DEF_FG)
+ reg &= ~DP_COM_CONF_CSC_DEF_MASK;
+
+ reg &= ~DP_COM_CONF_FG_EN;
+ ipu_dp_write(ipu, reg, DP_COM_CONF(DP_SYNC));
+
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+
+ if (ipu_is_channel_busy(ipu, MEM_BG_SYNC)) {
+ ipu_cm_write(ipu, IPUIRQ_2_MASK(IPU_IRQ_DP_SF_END),
+ IPUIRQ_2_STATREG(ipu->devtype,
+ IPU_IRQ_DP_SF_END));
+ while ((ipu_cm_read(ipu,
+ IPUIRQ_2_STATREG(ipu->devtype,
+ IPU_IRQ_DP_SF_END)) &
+ IPUIRQ_2_MASK(IPU_IRQ_DP_SF_END)) == 0) {
+ msleep(2);
+ timeout -= 2;
+ if (timeout <= 0)
+ break;
+ }
+ }
+ return;
+ } else {
+ return;
+ }
+
+ init_completion(&ipu->dc_comp);
+ ret = ipu_request_irq(ipu, irq, dc_irq_handler, 0, NULL, ipu);
+ if (ret < 0) {
+ dev_err(ipu->dev, "DC irq %d in use\n", irq);
+ return;
+ }
+ ret = wait_for_completion_timeout(&ipu->dc_comp, msecs_to_jiffies(50));
+ ipu_free_irq(ipu, irq, ipu);
+ dev_dbg(ipu->dev, "DC stop timeout - %d * 10ms\n", 5 - ret);
+
+ if (ipu->dc_swap) {
+ /* Swap DC channel 1 and 5 settings, and disable old dc chan */
+ reg = ipu_dc_read(ipu, DC_WR_CH_CONF(dc_chan));
+ ipu_dc_write(ipu, reg, DC_WR_CH_CONF(6 - dc_chan));
+ reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
+ reg ^= DC_WR_CH_CONF_PROG_DI_ID;
+ ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
+ }
+}
+
+void _ipu_init_dc_mappings(struct ipu_soc *ipu)
+{
+ /* IPU_PIX_FMT_RGB24 */
+ _ipu_dc_map_clear(ipu, 0);
+ _ipu_dc_map_config(ipu, 0, 0, 7, 0xFF);
+ _ipu_dc_map_config(ipu, 0, 1, 15, 0xFF);
+ _ipu_dc_map_config(ipu, 0, 2, 23, 0xFF);
+
+ /* IPU_PIX_FMT_RGB666 */
+ _ipu_dc_map_clear(ipu, 1);
+ _ipu_dc_map_config(ipu, 1, 0, 5, 0xFC);
+ _ipu_dc_map_config(ipu, 1, 1, 11, 0xFC);
+ _ipu_dc_map_config(ipu, 1, 2, 17, 0xFC);
+
+ /* IPU_PIX_FMT_YUV444 */
+ _ipu_dc_map_clear(ipu, 2);
+ _ipu_dc_map_config(ipu, 2, 0, 15, 0xFF);
+ _ipu_dc_map_config(ipu, 2, 1, 23, 0xFF);
+ _ipu_dc_map_config(ipu, 2, 2, 7, 0xFF);
+
+ /* IPU_PIX_FMT_RGB565 */
+ _ipu_dc_map_clear(ipu, 3);
+ _ipu_dc_map_config(ipu, 3, 0, 4, 0xF8);
+ _ipu_dc_map_config(ipu, 3, 1, 10, 0xFC);
+ _ipu_dc_map_config(ipu, 3, 2, 15, 0xF8);
+
+ /* IPU_PIX_FMT_LVDS666 */
+ _ipu_dc_map_clear(ipu, 4);
+ _ipu_dc_map_config(ipu, 4, 0, 5, 0xFC);
+ _ipu_dc_map_config(ipu, 4, 1, 13, 0xFC);
+ _ipu_dc_map_config(ipu, 4, 2, 21, 0xFC);
+
+ /* IPU_PIX_FMT_VYUY 16bit width */
+ _ipu_dc_map_clear(ipu, 5);
+ _ipu_dc_map_config(ipu, 5, 0, 7, 0xFF);
+ _ipu_dc_map_config(ipu, 5, 1, 0, 0x0);
+ _ipu_dc_map_config(ipu, 5, 2, 15, 0xFF);
+ _ipu_dc_map_clear(ipu, 6);
+ _ipu_dc_map_config(ipu, 6, 0, 0, 0x0);
+ _ipu_dc_map_config(ipu, 6, 1, 7, 0xFF);
+ _ipu_dc_map_config(ipu, 6, 2, 15, 0xFF);
+
+ /* IPU_PIX_FMT_UYUV 16bit width */
+ _ipu_dc_map_clear(ipu, 7);
+ _ipu_dc_map_link(ipu, 7, 6, 0, 6, 1, 6, 2);
+ _ipu_dc_map_clear(ipu, 8);
+ _ipu_dc_map_link(ipu, 8, 5, 0, 5, 1, 5, 2);
+
+ /* IPU_PIX_FMT_YUYV 16bit width */
+ _ipu_dc_map_clear(ipu, 9);
+ _ipu_dc_map_link(ipu, 9, 5, 2, 5, 1, 5, 0);
+ _ipu_dc_map_clear(ipu, 10);
+ _ipu_dc_map_link(ipu, 10, 5, 1, 5, 2, 5, 0);
+
+ /* IPU_PIX_FMT_YVYU 16bit width */
+ _ipu_dc_map_clear(ipu, 11);
+ _ipu_dc_map_link(ipu, 11, 5, 1, 5, 2, 5, 0);
+ _ipu_dc_map_clear(ipu, 12);
+ _ipu_dc_map_link(ipu, 12, 5, 2, 5, 1, 5, 0);
+
+ /* IPU_PIX_FMT_GBR24 */
+ /* IPU_PIX_FMT_VYU444 */
+ _ipu_dc_map_clear(ipu, 13);
+ _ipu_dc_map_link(ipu, 13, 0, 2, 0, 0, 0, 1);
+
+ /* IPU_PIX_FMT_BGR24 */
+ _ipu_dc_map_clear(ipu, 14);
+ _ipu_dc_map_link(ipu, 14, 0, 2, 0, 1, 0, 0);
+}
+
+int _ipu_pixfmt_to_map(uint32_t fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_GENERIC:
+ case IPU_PIX_FMT_RGB24:
+ return 0;
+ case IPU_PIX_FMT_RGB666:
+ return 1;
+ case IPU_PIX_FMT_YUV444:
+ return 2;
+ case IPU_PIX_FMT_RGB565:
+ return 3;
+ case IPU_PIX_FMT_LVDS666:
+ return 4;
+ case IPU_PIX_FMT_VYUY:
+ return 6;
+ case IPU_PIX_FMT_UYVY:
+ return 8;
+ case IPU_PIX_FMT_YUYV:
+ return 10;
+ case IPU_PIX_FMT_YVYU:
+ return 12;
+ case IPU_PIX_FMT_GBR24:
+ case IPU_PIX_FMT_VYU444:
+ return 13;
+ case IPU_PIX_FMT_BGR24:
+ return 14;
+ }
+
+ return -1;
+}
+
+/*!
+ * This function sets the colorspace for of dp.
+ * modes.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param param If it's not NULL, update the csc table
+ * with this parameter.
+ *
+ * @return N/A
+ */
+void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3])
+{
+ int dp;
+ struct dp_csc_param_t dp_csc_param;
+
+ if (channel == MEM_FG_SYNC)
+ dp = DP_SYNC;
+ else if (channel == MEM_BG_SYNC)
+ dp = DP_SYNC;
+ else if (channel == MEM_BG_ASYNC0)
+ dp = DP_ASYNC0;
+ else
+ return;
+
+ dp_csc_param.mode = -1;
+ dp_csc_param.coeff = param;
+ __ipu_dp_csc_setup(ipu, dp, dp_csc_param, true);
+}
+
+void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3])
+{
+ _ipu_dp_set_csc_coefficients(ipu, channel, param);
+}
+EXPORT_SYMBOL(ipu_set_csc_coefficients);
+
+/*!
+ * This function is called to adapt synchronous LCD panel to IPU restriction.
+ *
+ */
+void adapt_panel_to_ipu_restricitions(struct ipu_soc *ipu, uint16_t *v_start_width,
+ uint16_t *v_sync_width,
+ uint16_t *v_end_width)
+{
+ if (*v_end_width < 2) {
+ uint16_t diff = 2 - *v_end_width;
+ if (*v_start_width >= diff) {
+ *v_end_width = 2;
+ *v_start_width = *v_start_width - diff;
+ } else if (*v_sync_width > diff) {
+ *v_end_width = 2;
+ *v_sync_width = *v_sync_width - diff;
+ } else
+ dev_err(ipu->dev, "WARNING: try to adapt timming, but failed\n");
+ dev_err(ipu->dev, "WARNING: adapt panel end blank lines\n");
+ }
+}
+
+/*!
+ * This function is called to initialize a synchronous LCD panel.
+ *
+ * @param ipu ipu handler
+ * @param disp The DI the panel is attached to.
+ *
+ * @param pixel_clk Desired pixel clock frequency in Hz.
+ *
+ * @param pixel_fmt Input parameter for pixel format of buffer.
+ * Pixel format is a FOURCC ASCII code.
+ *
+ * @param width The width of panel in pixels.
+ *
+ * @param height The height of panel in pixels.
+ *
+ * @param hStartWidth The number of pixel clocks between the HSYNC
+ * signal pulse and the start of valid data.
+ *
+ * @param hSyncWidth The width of the HSYNC signal in units of pixel
+ * clocks.
+ *
+ * @param hEndWidth The number of pixel clocks between the end of
+ * valid data and the HSYNC signal for next line.
+ *
+ * @param vStartWidth The number of lines between the VSYNC
+ * signal pulse and the start of valid data.
+ *
+ * @param vSyncWidth The width of the VSYNC signal in units of lines
+ *
+ * @param vEndWidth The number of lines between the end of valid
+ * data and the VSYNC signal for next frame.
+ *
+ * @param sig Bitfield of signal polarities for LCD interface.
+ *
+ * @return This function returns 0 on success or negative error code on
+ * fail.
+ */
+int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
+ uint16_t width, uint16_t height,
+ uint32_t pixel_fmt,
+ uint16_t h_start_width, uint16_t h_sync_width,
+ uint16_t h_end_width, uint16_t v_start_width,
+ uint16_t v_sync_width, uint16_t v_end_width,
+ uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig)
+{
+ uint32_t field0_offset = 0;
+ uint32_t field1_offset;
+ uint32_t reg;
+ uint32_t di_gen, vsync_cnt;
+ uint32_t div, rounded_pixel_clk;
+ uint32_t h_total, v_total;
+ int map;
+ int ret;
+ struct clk *ldb_di0_clk, *ldb_di1_clk;
+ struct clk *di_parent;
+
+ dev_dbg(ipu->dev, "panel size = %d x %d\n", width, height);
+
+ if ((v_sync_width == 0) || (h_sync_width == 0))
+ return -EINVAL;
+
+ adapt_panel_to_ipu_restricitions(ipu, &v_start_width, &v_sync_width, &v_end_width);
+ h_total = width + h_sync_width + h_start_width + h_end_width;
+ v_total = height + v_sync_width + v_start_width + v_end_width;
+
+ /* Init clocking */
+ dev_dbg(ipu->dev, "pixel clk = %d\n", pixel_clk);
+
+ di_parent = clk_get_parent(ipu->di_clk_sel[disp]);
+ if (!di_parent) {
+ dev_err(ipu->dev, "get di clk parent fail\n");
+ return -EINVAL;
+ }
+ ldb_di0_clk = clk_get(ipu->dev, "ldb_di0");
+ if (IS_ERR(ldb_di0_clk)) {
+ dev_err(ipu->dev, "clk_get di0 failed");
+ return PTR_ERR(ldb_di0_clk);
+ }
+ ldb_di1_clk = clk_get(ipu->dev, "ldb_di1");
+ if (IS_ERR(ldb_di1_clk)) {
+ dev_err(ipu->dev, "clk_get di1 failed");
+ return PTR_ERR(ldb_di1_clk);
+ }
+ if (!strcmp(__clk_get_name(di_parent), __clk_get_name(ldb_di0_clk)) ||
+ !strcmp(__clk_get_name(di_parent), __clk_get_name(ldb_di1_clk))) {
+ /* if di clk parent is tve/ldb, then keep it;*/
+ dev_dbg(ipu->dev, "use special clk parent\n");
+ ret = clk_set_parent(ipu->pixel_clk_sel[disp], ipu->di_clk[disp]);
+ if (ret) {
+ dev_err(ipu->dev, "set pixel clk error:%d\n", ret);
+ return ret;
+ }
+ clk_put(ldb_di0_clk);
+ clk_put(ldb_di1_clk);
+ } else {
+ /* try ipu clk first*/
+ dev_dbg(ipu->dev, "try ipu internal clk\n");
+ ret = clk_set_parent(ipu->pixel_clk_sel[disp], ipu->ipu_clk);
+ if (ret) {
+ dev_err(ipu->dev, "set pixel clk error:%d\n", ret);
+ return ret;
+ }
+ rounded_pixel_clk = clk_round_rate(ipu->pixel_clk[disp], pixel_clk);
+ dev_dbg(ipu->dev, "rounded pix clk:%d\n", rounded_pixel_clk);
+ /*
+ * we will only use 1/2 fraction for ipu clk,
+ * so if the clk rate is not fit, try ext clk.
+ */
+ if (!sig.int_clk &&
+ ((rounded_pixel_clk >= pixel_clk + pixel_clk/200) ||
+ (rounded_pixel_clk <= pixel_clk - pixel_clk/200))) {
+ dev_dbg(ipu->dev, "try ipu ext di clk\n");
+
+ rounded_pixel_clk =
+ clk_round_rate(ipu->di_clk[disp], pixel_clk);
+ ret = clk_set_rate(ipu->di_clk[disp],
+ rounded_pixel_clk);
+ if (ret) {
+ dev_err(ipu->dev,
+ "set di clk rate error:%d\n", ret);
+ return ret;
+ }
+ dev_dbg(ipu->dev, "di clk:%d\n", rounded_pixel_clk);
+ ret = clk_set_parent(ipu->pixel_clk_sel[disp],
+ ipu->di_clk[disp]);
+ if (ret) {
+ dev_err(ipu->dev,
+ "set pixel clk parent error:%d\n", ret);
+ return ret;
+ }
+ }
+ }
+ rounded_pixel_clk = clk_round_rate(ipu->pixel_clk[disp], pixel_clk);
+ dev_dbg(ipu->dev, "round pixel clk:%d\n", rounded_pixel_clk);
+ ret = clk_set_rate(ipu->pixel_clk[disp], rounded_pixel_clk);
+ if (ret) {
+ dev_err(ipu->dev, "set pixel clk rate error:%d\n", ret);
+ return ret;
+ }
+ msleep(5);
+ /* Get integer portion of divider */
+ div = clk_get_rate(clk_get_parent(ipu->pixel_clk_sel[disp])) / rounded_pixel_clk;
+ dev_dbg(ipu->dev, "div:%d\n", div);
+ if (!div) {
+ dev_err(ipu->dev, "invalid pixel clk div = 0\n");
+ return -EINVAL;
+ }
+
+
+ mutex_lock(&ipu->mutex_lock);
+
+ _ipu_di_data_wave_config(ipu, disp, SYNC_WAVE, div - 1, div - 1);
+ _ipu_di_data_pin_config(ipu, disp, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
+
+ map = _ipu_pixfmt_to_map(pixel_fmt);
+ if (map < 0) {
+ dev_dbg(ipu->dev, "IPU_DISP: No MAP\n");
+ mutex_unlock(&ipu->mutex_lock);
+ return -EINVAL;
+ }
+
+ /*clear DI*/
+ di_gen = ipu_di_read(ipu, disp, DI_GENERAL);
+ di_gen &= (0x3 << 20);
+ ipu_di_write(ipu, disp, di_gen, DI_GENERAL);
+
+ if (sig.interlaced) {
+ if (ipu->devtype >= IPUv3EX) {
+ /* Setup internal HSYNC waveform */
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 1, /* counter */
+ h_total/2 - 1, /* run count */
+ DI_SYNC_CLK, /* run_resolution */
+ 0, /* offset */
+ DI_SYNC_NONE, /* offset resolution */
+ 0, /* repeat count */
+ DI_SYNC_NONE, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 0 /* COUNT DOWN */
+ );
+
+ /* Field 1 VSYNC waveform */
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 2, /* counter */
+ h_total - 1, /* run count */
+ DI_SYNC_CLK, /* run_resolution */
+ 0, /* offset */
+ DI_SYNC_NONE, /* offset resolution */
+ 0, /* repeat count */
+ DI_SYNC_NONE, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 2*div /* COUNT DOWN */
+ );
+
+ /* Setup internal HSYNC waveform */
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 3, /* counter */
+ v_total*2 - 1, /* run count */
+ DI_SYNC_INT_HSYNC, /* run_resolution */
+ 1, /* offset */
+ DI_SYNC_INT_HSYNC, /* offset resolution */
+ 0, /* repeat count */
+ DI_SYNC_NONE, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 2*div /* COUNT DOWN */
+ );
+
+ /* Active Field ? */
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 4, /* counter */
+ v_total/2 - 1, /* run count */
+ DI_SYNC_HSYNC, /* run_resolution */
+ v_start_width, /* offset */
+ DI_SYNC_HSYNC, /* offset resolution */
+ 2, /* repeat count */
+ DI_SYNC_VSYNC, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 0 /* COUNT DOWN */
+ );
+
+ /* Active Line */
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 5, /* counter */
+ 0, /* run count */
+ DI_SYNC_HSYNC, /* run_resolution */
+ 0, /* offset */
+ DI_SYNC_NONE, /* offset resolution */
+ height/2, /* repeat count */
+ 4, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 0 /* COUNT DOWN */
+ );
+
+ /* Field 0 VSYNC waveform */
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 6, /* counter */
+ v_total - 1, /* run count */
+ DI_SYNC_HSYNC, /* run_resolution */
+ 0, /* offset */
+ DI_SYNC_NONE, /* offset resolution */
+ 0, /* repeat count */
+ DI_SYNC_NONE, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 0 /* COUNT DOWN */
+ );
+
+ /* DC VSYNC waveform */
+ vsync_cnt = 7;
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 7, /* counter */
+ v_total/2 - 1, /* run count */
+ DI_SYNC_HSYNC, /* run_resolution */
+ 9, /* offset */
+ DI_SYNC_HSYNC, /* offset resolution */
+ 2, /* repeat count */
+ DI_SYNC_VSYNC, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 0 /* COUNT DOWN */
+ );
+
+ /* active pixel waveform */
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 8, /* counter */
+ 0, /* run count */
+ DI_SYNC_CLK, /* run_resolution */
+ h_start_width, /* offset */
+ DI_SYNC_CLK, /* offset resolution */
+ width, /* repeat count */
+ 5, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 0 /* COUNT DOWN */
+ );
+
+ /* Second VSYNC */
+ _ipu_di_sync_config(ipu,
+ disp, /* display */
+ 9, /* counter */
+ v_total - 1, /* run count */
+ DI_SYNC_INT_HSYNC, /* run_resolution */
+ v_total/2, /* offset */
+ DI_SYNC_INT_HSYNC, /* offset resolution */
+ 0, /* repeat count */
+ DI_SYNC_HSYNC, /* CNT_CLR_SEL */
+ 0, /* CNT_POLARITY_GEN_EN */
+ DI_SYNC_NONE, /* CNT_POLARITY_CLR_SEL */
+ DI_SYNC_NONE, /* CNT_POLARITY_TRIGGER_SEL */
+ 0, /* COUNT UP */
+ 2*div /* COUNT DOWN */
+ );
+
+ /* set gentime select and tag sel */
+ reg = ipu_di_read(ipu, disp, DI_SW_GEN1(9));
+ reg &= 0x1FFFFFFF;
+ reg |= (3-1)<<29 | 0x00008000;
+ ipu_di_write(ipu, disp, reg, DI_SW_GEN1(9));
+
+ ipu_di_write(ipu, disp, v_total / 2 - 1, DI_SCR_CONF);
+
+ /* set y_sel = 1 */
+ di_gen |= 0x10000000;
+ di_gen |= DI_GEN_POLARITY_5;
+ di_gen |= DI_GEN_POLARITY_8;
+ } else {
+ /* Setup internal HSYNC waveform */
+ _ipu_di_sync_config(ipu, disp, 1, h_total - 1, DI_SYNC_CLK,
+ 0, DI_SYNC_NONE, 0, DI_SYNC_NONE, 0, DI_SYNC_NONE,
+ DI_SYNC_NONE, 0, 0);
+
+ field1_offset = v_sync_width + v_start_width + height / 2 +
+ v_end_width;
+ if (sig.odd_field_first) {
+ field0_offset = field1_offset - 1;
+ field1_offset = 0;
+ }
+ v_total += v_start_width + v_end_width;
+
+ /* Field 1 VSYNC waveform */
+ _ipu_di_sync_config(ipu, disp, 2, v_total - 1, 1,
+ field0_offset,
+ field0_offset ? 1 : DI_SYNC_NONE,
+ 0, DI_SYNC_NONE, 0,
+ DI_SYNC_NONE, DI_SYNC_NONE, 0, 4);
+
+ /* Setup internal HSYNC waveform */
+ _ipu_di_sync_config(ipu, disp, 3, h_total - 1, DI_SYNC_CLK,
+ 0, DI_SYNC_NONE, 0, DI_SYNC_NONE, 0,
+ DI_SYNC_NONE, DI_SYNC_NONE, 0, 4);
+
+ /* Active Field ? */
+ _ipu_di_sync_config(ipu, disp, 4,
+ field0_offset ?
+ field0_offset : field1_offset - 2,
+ 1, v_start_width + v_sync_width, 1, 2, 2,
+ 0, DI_SYNC_NONE, DI_SYNC_NONE, 0, 0);
+
+ /* Active Line */
+ _ipu_di_sync_config(ipu, disp, 5, 0, 1,
+ 0, DI_SYNC_NONE,
+ height / 2, 4, 0, DI_SYNC_NONE,
+ DI_SYNC_NONE, 0, 0);
+
+ /* Field 0 VSYNC waveform */
+ _ipu_di_sync_config(ipu, disp, 6, v_total - 1, 1,
+ 0, DI_SYNC_NONE,
+ 0, DI_SYNC_NONE, 0, DI_SYNC_NONE,
+ DI_SYNC_NONE, 0, 0);
+
+ /* DC VSYNC waveform */
+ vsync_cnt = 7;
+ _ipu_di_sync_config(ipu, disp, 7, 0, 1,
+ field1_offset,
+ field1_offset ? 1 : DI_SYNC_NONE,
+ 1, 2, 0, DI_SYNC_NONE, DI_SYNC_NONE, 0, 0);
+
+ /* active pixel waveform */
+ _ipu_di_sync_config(ipu, disp, 8, 0, DI_SYNC_CLK,
+ h_sync_width + h_start_width, DI_SYNC_CLK,
+ width, 5, 0, DI_SYNC_NONE, DI_SYNC_NONE,
+ 0, 0);
+
+ /* ??? */
+ _ipu_di_sync_config(ipu, disp, 9, v_total - 1, 2,
+ 0, DI_SYNC_NONE,
+ 0, DI_SYNC_NONE, 6, DI_SYNC_NONE,
+ DI_SYNC_NONE, 0, 0);
+
+ reg = ipu_di_read(ipu, disp, DI_SW_GEN1(9));
+ reg |= 0x8000;
+ ipu_di_write(ipu, disp, reg, DI_SW_GEN1(9));
+
+ ipu_di_write(ipu, disp, v_sync_width + v_start_width +
+ v_end_width + height / 2 - 1, DI_SCR_CONF);
+ }
+
+ /* Init template microcode */
+ _ipu_dc_write_tmpl(ipu, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1);
+
+ if (sig.Hsync_pol)
+ di_gen |= DI_GEN_POLARITY_3;
+ if (sig.Vsync_pol)
+ di_gen |= DI_GEN_POLARITY_2;
+ } else {
+ /* Setup internal HSYNC waveform */
+ _ipu_di_sync_config(ipu, disp, 1, h_total - 1, DI_SYNC_CLK,
+ 0, DI_SYNC_NONE, 0, DI_SYNC_NONE, 0, DI_SYNC_NONE,
+ DI_SYNC_NONE, 0, 0);
+
+ /* Setup external (delayed) HSYNC waveform */
+ _ipu_di_sync_config(ipu, disp, DI_SYNC_HSYNC, h_total - 1,
+ DI_SYNC_CLK, div * v_to_h_sync, DI_SYNC_CLK,
+ 0, DI_SYNC_NONE, 1, DI_SYNC_NONE,
+ DI_SYNC_CLK, 0, h_sync_width * 2);
+ /* Setup VSYNC waveform */
+ vsync_cnt = DI_SYNC_VSYNC;
+ _ipu_di_sync_config(ipu, disp, DI_SYNC_VSYNC, v_total - 1,
+ DI_SYNC_INT_HSYNC, 0, DI_SYNC_NONE, 0,
+ DI_SYNC_NONE, 1, DI_SYNC_NONE,
+ DI_SYNC_INT_HSYNC, 0, v_sync_width * 2);
+ ipu_di_write(ipu, disp, v_total - 1, DI_SCR_CONF);
+
+ /* Setup active data waveform to sync with DC */
+ _ipu_di_sync_config(ipu, disp, 4, 0, DI_SYNC_HSYNC,
+ v_sync_width + v_start_width, DI_SYNC_HSYNC, height,
+ DI_SYNC_VSYNC, 0, DI_SYNC_NONE,
+ DI_SYNC_NONE, 0, 0);
+ _ipu_di_sync_config(ipu, disp, 5, 0, DI_SYNC_CLK,
+ h_sync_width + h_start_width, DI_SYNC_CLK,
+ width, 4, 0, DI_SYNC_NONE, DI_SYNC_NONE, 0,
+ 0);
+
+ /* set VGA delayed hsync/vsync no matter VGA enabled */
+ if (disp) {
+ /* couter 7 for VGA delay HSYNC */
+ _ipu_di_sync_config(ipu, disp, 7,
+ h_total - 1, DI_SYNC_CLK,
+ 18, DI_SYNC_CLK,
+ 0, DI_SYNC_NONE,
+ 1, DI_SYNC_NONE, DI_SYNC_CLK,
+ 0, h_sync_width * 2);
+
+ /* couter 8 for VGA delay VSYNC */
+ _ipu_di_sync_config(ipu, disp, 8,
+ v_total - 1, DI_SYNC_INT_HSYNC,
+ 1, DI_SYNC_INT_HSYNC,
+ 0, DI_SYNC_NONE,
+ 1, DI_SYNC_NONE, DI_SYNC_INT_HSYNC,
+ 0, v_sync_width * 2);
+ }
+
+ /* reset all unused counters */
+ ipu_di_write(ipu, disp, 0, DI_SW_GEN0(6));
+ ipu_di_write(ipu, disp, 0, DI_SW_GEN1(6));
+ if (!disp) {
+ ipu_di_write(ipu, disp, 0, DI_SW_GEN0(7));
+ ipu_di_write(ipu, disp, 0, DI_SW_GEN1(7));
+ ipu_di_write(ipu, disp, 0, DI_STP_REP(7));
+ ipu_di_write(ipu, disp, 0, DI_SW_GEN0(8));
+ ipu_di_write(ipu, disp, 0, DI_SW_GEN1(8));
+ ipu_di_write(ipu, disp, 0, DI_STP_REP(8));
+ }
+ ipu_di_write(ipu, disp, 0, DI_SW_GEN0(9));
+ ipu_di_write(ipu, disp, 0, DI_SW_GEN1(9));
+ ipu_di_write(ipu, disp, 0, DI_STP_REP(9));
+
+ reg = ipu_di_read(ipu, disp, DI_STP_REP(6));
+ reg &= 0x0000FFFF;
+ ipu_di_write(ipu, disp, reg, DI_STP_REP(6));
+
+ /* Init template microcode */
+ if (disp) {
+ if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
+ (pixel_fmt == IPU_PIX_FMT_UYVY) ||
+ (pixel_fmt == IPU_PIX_FMT_YVYU) ||
+ (pixel_fmt == IPU_PIX_FMT_VYUY)) {
+ _ipu_dc_write_tmpl(ipu, 8, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5, 1);
+ _ipu_dc_write_tmpl(ipu, 9, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ /* configure user events according to DISP NUM */
+ ipu_dc_write(ipu, (width - 1), DC_UGDE_3(disp));
+ }
+ _ipu_dc_write_tmpl(ipu, 2, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
+ _ipu_dc_write_tmpl(ipu, 3, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
+ _ipu_dc_write_tmpl(ipu, 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
+ _ipu_dc_write_tmpl(ipu, 1, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+
+ } else {
+ if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
+ (pixel_fmt == IPU_PIX_FMT_UYVY) ||
+ (pixel_fmt == IPU_PIX_FMT_YVYU) ||
+ (pixel_fmt == IPU_PIX_FMT_VYUY)) {
+ _ipu_dc_write_tmpl(ipu, 10, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5, 1);
+ _ipu_dc_write_tmpl(ipu, 11, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ /* configure user events according to DISP NUM */
+ ipu_dc_write(ipu, width - 1, DC_UGDE_3(disp));
+ }
+ _ipu_dc_write_tmpl(ipu, 5, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
+ _ipu_dc_write_tmpl(ipu, 6, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
+ _ipu_dc_write_tmpl(ipu, 7, WRG, 0, map, NULL_WAVE, 0, 0, 1);
+ _ipu_dc_write_tmpl(ipu, 12, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ }
+
+ if (sig.Hsync_pol) {
+ di_gen |= DI_GEN_POLARITY_2;
+ if (disp)
+ di_gen |= DI_GEN_POLARITY_7;
+ }
+ if (sig.Vsync_pol) {
+ di_gen |= DI_GEN_POLARITY_3;
+ if (disp)
+ di_gen |= DI_GEN_POLARITY_8;
+ }
+ }
+ /* changinc DISP_CLK polarity: it can be wrong for some applications */
+ if ((pixel_fmt == IPU_PIX_FMT_YUYV) ||
+ (pixel_fmt == IPU_PIX_FMT_UYVY) ||
+ (pixel_fmt == IPU_PIX_FMT_YVYU) ||
+ (pixel_fmt == IPU_PIX_FMT_VYUY))
+ di_gen |= 0x00020000;
+
+ if (!sig.clk_pol)
+ di_gen |= DI_GEN_POLARITY_DISP_CLK;
+
+ ipu_di_write(ipu, disp, di_gen, DI_GENERAL);
+
+ ipu_di_write(ipu, disp, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) |
+ 0x00000002, DI_SYNC_AS_GEN);
+ reg = ipu_di_read(ipu, disp, DI_POL);
+ reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
+ if (sig.enable_pol)
+ reg |= DI_POL_DRDY_POLARITY_15;
+ if (sig.data_pol)
+ reg |= DI_POL_DRDY_DATA_POLARITY;
+ ipu_di_write(ipu, disp, reg, DI_POL);
+
+ ipu_dc_write(ipu, width, DC_DISP_CONF2(DC_DISP_ID_SYNC(disp)));
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_init_sync_panel);
+
+void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp)
+{
+ uint32_t reg;
+ uint32_t di_gen;
+
+ if (disp != 0 && disp != 1)
+ return;
+
+ mutex_lock(&ipu->mutex_lock);
+
+ di_gen = ipu_di_read(ipu, disp, DI_GENERAL);
+ di_gen |= 0x3ff | DI_GEN_POLARITY_DISP_CLK;
+ ipu_di_write(ipu, disp, di_gen, DI_GENERAL);
+
+ reg = ipu_di_read(ipu, disp, DI_POL);
+ reg |= 0x3ffffff;
+ ipu_di_write(ipu, disp, reg, DI_POL);
+
+ mutex_unlock(&ipu->mutex_lock);
+}
+EXPORT_SYMBOL(ipu_uninit_sync_panel);
+
+int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
+ uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig)
+{
+ int map;
+ u32 ser_conf = 0;
+ u32 div;
+ u32 di_clk = clk_get_rate(ipu->ipu_clk);
+
+ /* round up cycle_time, then calcalate the divider using scaled math */
+ cycle_time += (1000000000UL / di_clk) - 1;
+ div = (cycle_time * (di_clk / 256UL)) / (1000000000UL / 256UL);
+
+ map = _ipu_pixfmt_to_map(pixel_fmt);
+ if (map < 0)
+ return -EINVAL;
+
+ mutex_lock(&ipu->mutex_lock);
+
+ if (type == IPU_PANEL_SERIAL) {
+ ipu_di_write(ipu, disp, (div << 24) | ((sig.ifc_width - 1) << 4),
+ DI_DW_GEN(ASYNC_SER_WAVE));
+
+ _ipu_di_data_pin_config(ipu, disp, ASYNC_SER_WAVE, DI_PIN_CS,
+ 0, 0, (div * 2) + 1);
+ _ipu_di_data_pin_config(ipu, disp, ASYNC_SER_WAVE, DI_PIN_SER_CLK,
+ 1, div, div * 2);
+ _ipu_di_data_pin_config(ipu, disp, ASYNC_SER_WAVE, DI_PIN_SER_RS,
+ 2, 0, 0);
+
+ _ipu_dc_write_tmpl(ipu, 0x64, WROD(0), 0, map, ASYNC_SER_WAVE, 0, 0, 1);
+
+ /* Configure DC for serial panel */
+ ipu_dc_write(ipu, 0x14, DC_DISP_CONF1(DC_DISP_ID_SERIAL));
+
+ if (sig.clk_pol)
+ ser_conf |= DI_SER_CONF_SERIAL_CLK_POL;
+ if (sig.data_pol)
+ ser_conf |= DI_SER_CONF_SERIAL_DATA_POL;
+ if (sig.rs_pol)
+ ser_conf |= DI_SER_CONF_SERIAL_RS_POL;
+ if (sig.cs_pol)
+ ser_conf |= DI_SER_CONF_SERIAL_CS_POL;
+ ipu_di_write(ipu, disp, ser_conf, DI_SER_CONF);
+ }
+
+ mutex_unlock(&ipu->mutex_lock);
+ return 0;
+}
+EXPORT_SYMBOL(ipu_init_async_panel);
+
+/*!
+ * This function sets the foreground and background plane global alpha blending
+ * modes. This function also sets the DP graphic plane according to the
+ * parameter of IPUv3 DP channel.
+ *
+ * @param ipu ipu handler
+ * @param channel IPUv3 DP channel
+ *
+ * @param enable Boolean to enable or disable global alpha
+ * blending. If disabled, local blending is used.
+ *
+ * @param alpha Global alpha value.
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
+ bool enable, uint8_t alpha)
+{
+ uint32_t reg;
+ uint32_t flow;
+ bool bg_chan;
+
+ if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
+ flow = DP_SYNC;
+ else if (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0)
+ flow = DP_ASYNC0;
+ else if (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)
+ flow = DP_ASYNC1;
+ else
+ return -EINVAL;
+
+ if (channel == MEM_BG_SYNC || channel == MEM_BG_ASYNC0 ||
+ channel == MEM_BG_ASYNC1)
+ bg_chan = true;
+ else
+ bg_chan = false;
+
+ _ipu_get(ipu);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ if (bg_chan) {
+ reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
+ ipu_dp_write(ipu, reg & ~DP_COM_CONF_GWSEL, DP_COM_CONF(flow));
+ } else {
+ reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
+ ipu_dp_write(ipu, reg | DP_COM_CONF_GWSEL, DP_COM_CONF(flow));
+ }
+
+ if (enable) {
+ reg = ipu_dp_read(ipu, DP_GRAPH_WIND_CTRL(flow)) & 0x00FFFFFFL;
+ ipu_dp_write(ipu, reg | ((uint32_t) alpha << 24),
+ DP_GRAPH_WIND_CTRL(flow));
+
+ reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
+ ipu_dp_write(ipu, reg | DP_COM_CONF_GWAM, DP_COM_CONF(flow));
+ } else {
+ reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
+ ipu_dp_write(ipu, reg & ~DP_COM_CONF_GWAM, DP_COM_CONF(flow));
+ }
+
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ _ipu_put(ipu);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_disp_set_global_alpha);
+
+/*!
+ * This function sets the transparent color key for SDC graphic plane.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param enable Boolean to enable or disable color key
+ *
+ * @param colorKey 24-bit RGB color for transparent color key.
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
+ bool enable, uint32_t color_key)
+{
+ uint32_t reg, flow;
+ int y, u, v;
+ int red, green, blue;
+
+ if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
+ flow = DP_SYNC;
+ else if (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0)
+ flow = DP_ASYNC0;
+ else if (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)
+ flow = DP_ASYNC1;
+ else
+ return -EINVAL;
+
+ _ipu_get(ipu);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ ipu->color_key_4rgb = true;
+ /* Transform color key from rgb to yuv if CSC is enabled */
+ if (((ipu->fg_csc_type == RGB2YUV) && (ipu->bg_csc_type == YUV2YUV)) ||
+ ((ipu->fg_csc_type == YUV2YUV) && (ipu->bg_csc_type == RGB2YUV)) ||
+ ((ipu->fg_csc_type == YUV2YUV) && (ipu->bg_csc_type == YUV2YUV)) ||
+ ((ipu->fg_csc_type == YUV2RGB) && (ipu->bg_csc_type == YUV2RGB))) {
+
+ dev_dbg(ipu->dev, "color key 0x%x need change to yuv fmt\n", color_key);
+
+ red = (color_key >> 16) & 0xFF;
+ green = (color_key >> 8) & 0xFF;
+ blue = color_key & 0xFF;
+
+ y = _rgb_to_yuv(0, red, green, blue);
+ u = _rgb_to_yuv(1, red, green, blue);
+ v = _rgb_to_yuv(2, red, green, blue);
+ color_key = (y << 16) | (u << 8) | v;
+
+ ipu->color_key_4rgb = false;
+
+ dev_dbg(ipu->dev, "color key change to yuv fmt 0x%x\n", color_key);
+ }
+
+ if (enable) {
+ reg = ipu_dp_read(ipu, DP_GRAPH_WIND_CTRL(flow)) & 0xFF000000L;
+ ipu_dp_write(ipu, reg | color_key, DP_GRAPH_WIND_CTRL(flow));
+
+ reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
+ ipu_dp_write(ipu, reg | DP_COM_CONF_GWCKE, DP_COM_CONF(flow));
+ } else {
+ reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
+ ipu_dp_write(ipu, reg & ~DP_COM_CONF_GWCKE, DP_COM_CONF(flow));
+ }
+
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ _ipu_put(ipu);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_disp_set_color_key);
+
+/*!
+ * This function sets the gamma correction for DP output.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param enable Boolean to enable or disable gamma correction.
+ *
+ * @param constk Gamma piecewise linear approximation constk coeff.
+ *
+ * @param slopek Gamma piecewise linear approximation slopek coeff.
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel, bool enable, int constk[], int slopek[])
+{
+ uint32_t reg, flow, i;
+
+ if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
+ flow = DP_SYNC;
+ else if (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0)
+ flow = DP_ASYNC0;
+ else if (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)
+ flow = DP_ASYNC1;
+ else
+ return -EINVAL;
+
+ _ipu_get(ipu);
+
+ mutex_lock(&ipu->mutex_lock);
+
+ for (i = 0; i < 8; i++)
+ ipu_dp_write(ipu, (constk[2*i] & 0x1ff) | ((constk[2*i+1] & 0x1ff) << 16), DP_GAMMA_C(flow, i));
+ for (i = 0; i < 4; i++)
+ ipu_dp_write(ipu, (slopek[4*i] & 0xff) | ((slopek[4*i+1] & 0xff) << 8) |
+ ((slopek[4*i+2] & 0xff) << 16) | ((slopek[4*i+3] & 0xff) << 24), DP_GAMMA_S(flow, i));
+
+ reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
+ if (enable) {
+ if ((ipu->bg_csc_type == RGB2YUV) || (ipu->bg_csc_type == YUV2YUV))
+ reg |= DP_COM_CONF_GAMMA_YUV_EN;
+ else
+ reg &= ~DP_COM_CONF_GAMMA_YUV_EN;
+ ipu_dp_write(ipu, reg | DP_COM_CONF_GAMMA_EN, DP_COM_CONF(flow));
+ } else
+ ipu_dp_write(ipu, reg & ~DP_COM_CONF_GAMMA_EN, DP_COM_CONF(flow));
+
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+
+ mutex_unlock(&ipu->mutex_lock);
+
+ _ipu_put(ipu);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_disp_set_gamma_correction);
+
+/*!
+ * This function sets the window position of the foreground or background plane.
+ * modes.
+ *
+ * @param ipu ipu handler
+ * @param channel Input parameter for the logical channel ID.
+ *
+ * @param x_pos The X coordinate position to place window at.
+ * The position is relative to the top left corner.
+ *
+ * @param y_pos The Y coordinate position to place window at.
+ * The position is relative to the top left corner.
+ *
+ * @return Returns 0 on success or negative error code on fail
+ */
+int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+ int16_t x_pos, int16_t y_pos)
+{
+ u32 reg;
+ uint32_t flow = 0;
+ uint32_t dp_srm_shift;
+
+ if ((channel == MEM_FG_SYNC) || (channel == MEM_BG_SYNC)) {
+ flow = DP_SYNC;
+ dp_srm_shift = 3;
+ } else if (channel == MEM_FG_ASYNC0) {
+ flow = DP_ASYNC0;
+ dp_srm_shift = 5;
+ } else if (channel == MEM_FG_ASYNC1) {
+ flow = DP_ASYNC1;
+ dp_srm_shift = 7;
+ } else
+ return -EINVAL;
+
+ ipu_dp_write(ipu, (x_pos << 16) | y_pos, DP_FG_POS(flow));
+
+ if (ipu_is_channel_busy(ipu, channel)) {
+ /* controled by FSU if channel enabled */
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) & (~(0x3 << dp_srm_shift));
+ reg |= (0x1 << dp_srm_shift);
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+ } else {
+ /* disable auto swap, controled by MCU if channel disabled */
+ reg = ipu_cm_read(ipu, IPU_SRM_PRI2) & (~(0x3 << dp_srm_shift));
+ ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+ }
+
+ return 0;
+}
+
+int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+ int16_t x_pos, int16_t y_pos)
+{
+ int ret;
+
+ _ipu_get(ipu);
+ mutex_lock(&ipu->mutex_lock);
+ ret = _ipu_disp_set_window_pos(ipu, channel, x_pos, y_pos);
+ mutex_unlock(&ipu->mutex_lock);
+ _ipu_put(ipu);
+ return ret;
+}
+EXPORT_SYMBOL(ipu_disp_set_window_pos);
+
+int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+ int16_t *x_pos, int16_t *y_pos)
+{
+ u32 reg;
+ uint32_t flow = 0;
+
+ if (channel == MEM_FG_SYNC)
+ flow = DP_SYNC;
+ else if (channel == MEM_FG_ASYNC0)
+ flow = DP_ASYNC0;
+ else if (channel == MEM_FG_ASYNC1)
+ flow = DP_ASYNC1;
+ else
+ return -EINVAL;
+
+ reg = ipu_dp_read(ipu, DP_FG_POS(flow));
+
+ *x_pos = (reg >> 16) & 0x7FF;
+ *y_pos = reg & 0x7FF;
+
+ return 0;
+}
+int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+ int16_t *x_pos, int16_t *y_pos)
+{
+ int ret;
+
+ _ipu_get(ipu);
+ mutex_lock(&ipu->mutex_lock);
+ ret = _ipu_disp_get_window_pos(ipu, channel, x_pos, y_pos);
+ mutex_unlock(&ipu->mutex_lock);
+ _ipu_put(ipu);
+ return ret;
+}
+EXPORT_SYMBOL(ipu_disp_get_window_pos);
+
+void ipu_reset_disp_panel(struct ipu_soc *ipu)
+{
+ uint32_t tmp;
+
+ tmp = ipu_di_read(ipu, 1, DI_GENERAL);
+ ipu_di_write(ipu, 1, tmp | 0x08, DI_GENERAL);
+ msleep(10); /* tRES >= 100us */
+ tmp = ipu_di_read(ipu, 1, DI_GENERAL);
+ ipu_di_write(ipu, 1, tmp & ~0x08, DI_GENERAL);
+ msleep(60);
+
+ return;
+}
+EXPORT_SYMBOL(ipu_reset_disp_panel);
+
+void ipu_disp_init(struct ipu_soc *ipu)
+{
+ ipu->fg_csc_type = ipu->bg_csc_type = CSC_NONE;
+ ipu->color_key_4rgb = true;
+ _ipu_init_dc_mappings(ipu);
+ _ipu_dmfc_init(ipu, DMFC_NORMAL, 1);
+}
diff --git a/drivers/mxc/ipu3/ipu_ic.c b/drivers/mxc/ipu3/ipu_ic.c
new file mode 100644
index 000000000000..29519bd00d12
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_ic.c
@@ -0,0 +1,924 @@
+/*
+ * Copyright 2005-2015 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 ipu_ic.c
+ *
+ * @brief IPU IC functions
+ *
+ * @ingroup IPU
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ipu-v3.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include "ipu_param_mem.h"
+#include "ipu_regs.h"
+
+enum {
+ IC_TASK_VIEWFINDER,
+ IC_TASK_ENCODER,
+ IC_TASK_POST_PROCESSOR
+};
+
+static void _init_csc(struct ipu_soc *ipu, uint8_t ic_task, ipu_color_space_t in_format,
+ ipu_color_space_t out_format, int csc_index);
+
+static int _calc_resize_coeffs(struct ipu_soc *ipu,
+ uint32_t inSize, uint32_t outSize,
+ uint32_t *resizeCoeff,
+ uint32_t *downsizeCoeff);
+
+void _ipu_vdi_set_top_field_man(struct ipu_soc *ipu, bool top_field_0)
+{
+ uint32_t reg;
+
+ reg = ipu_vdi_read(ipu, VDI_C);
+ if (top_field_0)
+ reg &= ~VDI_C_TOP_FIELD_MAN_1;
+ else
+ reg |= VDI_C_TOP_FIELD_MAN_1;
+ ipu_vdi_write(ipu, reg, VDI_C);
+}
+
+void _ipu_vdi_set_motion(struct ipu_soc *ipu, ipu_motion_sel motion_sel)
+{
+ uint32_t reg;
+
+ reg = ipu_vdi_read(ipu, VDI_C);
+ reg &= ~(VDI_C_MOT_SEL_FULL | VDI_C_MOT_SEL_MED | VDI_C_MOT_SEL_LOW);
+ if (motion_sel == HIGH_MOTION)
+ reg |= VDI_C_MOT_SEL_FULL;
+ else if (motion_sel == MED_MOTION)
+ reg |= VDI_C_MOT_SEL_MED;
+ else
+ reg |= VDI_C_MOT_SEL_LOW;
+
+ ipu_vdi_write(ipu, reg, VDI_C);
+ dev_dbg(ipu->dev, "VDI_C = \t0x%08X\n", reg);
+}
+
+void ic_dump_register(struct ipu_soc *ipu)
+{
+ printk(KERN_DEBUG "IC_CONF = \t0x%08X\n", ipu_ic_read(ipu, IC_CONF));
+ printk(KERN_DEBUG "IC_PRP_ENC_RSC = \t0x%08X\n",
+ ipu_ic_read(ipu, IC_PRP_ENC_RSC));
+ printk(KERN_DEBUG "IC_PRP_VF_RSC = \t0x%08X\n",
+ ipu_ic_read(ipu, IC_PRP_VF_RSC));
+ printk(KERN_DEBUG "IC_PP_RSC = \t0x%08X\n", ipu_ic_read(ipu, IC_PP_RSC));
+ printk(KERN_DEBUG "IC_IDMAC_1 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_1));
+ printk(KERN_DEBUG "IC_IDMAC_2 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_2));
+ printk(KERN_DEBUG "IC_IDMAC_3 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_3));
+}
+
+void _ipu_ic_enable_task(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ uint32_t ic_conf;
+
+ ic_conf = ipu_ic_read(ipu, IC_CONF);
+ switch (channel) {
+ case CSI_PRP_VF_MEM:
+ case MEM_PRP_VF_MEM:
+ ic_conf |= IC_CONF_PRPVF_EN;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ ic_conf |= IC_CONF_PRPVF_EN;
+ break;
+ case MEM_VDI_MEM:
+ ic_conf |= IC_CONF_PRPVF_EN | IC_CONF_RWS_EN ;
+ break;
+ case MEM_ROT_VF_MEM:
+ ic_conf |= IC_CONF_PRPVF_ROT_EN;
+ break;
+ case CSI_PRP_ENC_MEM:
+ case MEM_PRP_ENC_MEM:
+ ic_conf |= IC_CONF_PRPENC_EN;
+ break;
+ case MEM_ROT_ENC_MEM:
+ ic_conf |= IC_CONF_PRPENC_ROT_EN;
+ break;
+ case MEM_PP_MEM:
+ ic_conf |= IC_CONF_PP_EN;
+ break;
+ case MEM_ROT_PP_MEM:
+ ic_conf |= IC_CONF_PP_ROT_EN;
+ break;
+ default:
+ break;
+ }
+ ipu_ic_write(ipu, ic_conf, IC_CONF);
+}
+
+void _ipu_ic_disable_task(struct ipu_soc *ipu, ipu_channel_t channel)
+{
+ uint32_t ic_conf;
+
+ ic_conf = ipu_ic_read(ipu, IC_CONF);
+ switch (channel) {
+ case CSI_PRP_VF_MEM:
+ case MEM_PRP_VF_MEM:
+ ic_conf &= ~IC_CONF_PRPVF_EN;
+ break;
+ case MEM_VDI_PRP_VF_MEM:
+ ic_conf &= ~IC_CONF_PRPVF_EN;
+ break;
+ case MEM_VDI_MEM:
+ ic_conf &= ~(IC_CONF_PRPVF_EN | IC_CONF_RWS_EN);
+ break;
+ case MEM_ROT_VF_MEM:
+ ic_conf &= ~IC_CONF_PRPVF_ROT_EN;
+ break;
+ case CSI_PRP_ENC_MEM:
+ case MEM_PRP_ENC_MEM:
+ ic_conf &= ~IC_CONF_PRPENC_EN;
+ break;
+ case MEM_ROT_ENC_MEM:
+ ic_conf &= ~IC_CONF_PRPENC_ROT_EN;
+ break;
+ case MEM_PP_MEM:
+ ic_conf &= ~IC_CONF_PP_EN;
+ break;
+ case MEM_ROT_PP_MEM:
+ ic_conf &= ~IC_CONF_PP_ROT_EN;
+ break;
+ default:
+ break;
+ }
+ ipu_ic_write(ipu, ic_conf, IC_CONF);
+}
+
+void _ipu_vdi_init(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params)
+{
+ uint32_t reg;
+ uint32_t pixel_fmt;
+ uint32_t pix_per_burst;
+
+ reg = ((params->mem_prp_vf_mem.in_height-1) << 16) |
+ (params->mem_prp_vf_mem.in_width-1);
+ ipu_vdi_write(ipu, reg, VDI_FSIZE);
+
+ /* Full motion, only vertical filter is used
+ Burst size is 4 accesses */
+ if (params->mem_prp_vf_mem.in_pixel_fmt ==
+ IPU_PIX_FMT_UYVY ||
+ params->mem_prp_vf_mem.in_pixel_fmt ==
+ IPU_PIX_FMT_YUYV) {
+ pixel_fmt = VDI_C_CH_422;
+ pix_per_burst = 32;
+ } else {
+ pixel_fmt = VDI_C_CH_420;
+ pix_per_burst = 64;
+ }
+
+ reg = ipu_vdi_read(ipu, VDI_C);
+ reg |= pixel_fmt;
+ switch (channel) {
+ case MEM_VDI_PRP_VF_MEM:
+ reg |= VDI_C_BURST_SIZE2_4;
+ break;
+ case MEM_VDI_PRP_VF_MEM_P:
+ reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_SET_1 | VDI_C_VWM1_CLR_2;
+ break;
+ case MEM_VDI_PRP_VF_MEM_N:
+ reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_SET_1 | VDI_C_VWM3_CLR_2;
+ break;
+
+ case MEM_VDI_MEM:
+ reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
+ << VDI_C_BURST_SIZE2_OFFSET;
+ break;
+ case MEM_VDI_MEM_P:
+ reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
+ << VDI_C_BURST_SIZE1_OFFSET;
+ reg |= VDI_C_VWM1_SET_2 | VDI_C_VWM1_CLR_2;
+ break;
+ case MEM_VDI_MEM_N:
+ reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
+ << VDI_C_BURST_SIZE3_OFFSET;
+ reg |= VDI_C_VWM3_SET_2 | VDI_C_VWM3_CLR_2;
+ break;
+ default:
+ break;
+ }
+ ipu_vdi_write(ipu, reg, VDI_C);
+
+ if (params->mem_prp_vf_mem.field_fmt == IPU_DEINTERLACE_FIELD_TOP)
+ _ipu_vdi_set_top_field_man(ipu, true);
+ else if (params->mem_prp_vf_mem.field_fmt == IPU_DEINTERLACE_FIELD_BOTTOM)
+ _ipu_vdi_set_top_field_man(ipu, false);
+
+ _ipu_vdi_set_motion(ipu, params->mem_prp_vf_mem.motion_sel);
+
+ reg = ipu_ic_read(ipu, IC_CONF);
+ reg &= ~IC_CONF_RWS_EN;
+ ipu_ic_write(ipu, reg, IC_CONF);
+}
+
+void _ipu_vdi_uninit(struct ipu_soc *ipu)
+{
+ ipu_vdi_write(ipu, 0, VDI_FSIZE);
+ ipu_vdi_write(ipu, 0, VDI_C);
+}
+
+int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
+ bool src_is_csi)
+{
+ uint32_t reg, ic_conf;
+ uint32_t downsizeCoeff, resizeCoeff;
+ ipu_color_space_t in_fmt, out_fmt;
+ int ret = 0;
+
+ /* Setup vertical resizing */
+ if (!params->mem_prp_vf_mem.outv_resize_ratio) {
+ ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_height,
+ params->mem_prp_vf_mem.out_height,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate prpvf height "
+ "scaling coefficients\n");
+ return ret;
+ }
+
+ reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
+ } else
+ reg = (params->mem_prp_vf_mem.outv_resize_ratio) << 16;
+
+ /* Setup horizontal resizing */
+ if (!params->mem_prp_vf_mem.outh_resize_ratio) {
+ ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_width,
+ params->mem_prp_vf_mem.out_width,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate prpvf width "
+ "scaling coefficients\n");
+ return ret;
+ }
+
+ reg |= (downsizeCoeff << 14) | resizeCoeff;
+ } else
+ reg |= params->mem_prp_vf_mem.outh_resize_ratio;
+
+ ipu_ic_write(ipu, reg, IC_PRP_VF_RSC);
+
+ ic_conf = ipu_ic_read(ipu, IC_CONF);
+
+ /* Setup color space conversion */
+ in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_pixel_fmt);
+ out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
+ if (in_fmt == RGB) {
+ if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
+ /* Enable RGB->YCBCR CSC1 */
+ _init_csc(ipu, IC_TASK_VIEWFINDER, RGB, out_fmt, 1);
+ ic_conf |= IC_CONF_PRPVF_CSC1;
+ }
+ }
+ if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
+ if (out_fmt == RGB) {
+ /* Enable YCBCR->RGB CSC1 */
+ _init_csc(ipu, IC_TASK_VIEWFINDER, YCbCr, RGB, 1);
+ ic_conf |= IC_CONF_PRPVF_CSC1;
+ } else {
+ /* TODO: Support YUV<->YCbCr conversion? */
+ }
+ }
+
+ if (params->mem_prp_vf_mem.graphics_combine_en) {
+ ic_conf |= IC_CONF_PRPVF_CMB;
+
+ if (!(ic_conf & IC_CONF_PRPVF_CSC1)) {
+ /* need transparent CSC1 conversion */
+ _init_csc(ipu, IC_TASK_VIEWFINDER, RGB, RGB, 1);
+ ic_conf |= IC_CONF_PRPVF_CSC1; /* Enable RGB->RGB CSC */
+ }
+ in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_g_pixel_fmt);
+ out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
+ if (in_fmt == RGB) {
+ if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
+ /* Enable RGB->YCBCR CSC2 */
+ _init_csc(ipu, IC_TASK_VIEWFINDER, RGB, out_fmt, 2);
+ ic_conf |= IC_CONF_PRPVF_CSC2;
+ }
+ }
+ if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
+ if (out_fmt == RGB) {
+ /* Enable YCBCR->RGB CSC2 */
+ _init_csc(ipu, IC_TASK_VIEWFINDER, YCbCr, RGB, 2);
+ ic_conf |= IC_CONF_PRPVF_CSC2;
+ } else {
+ /* TODO: Support YUV<->YCbCr conversion? */
+ }
+ }
+
+ if (params->mem_prp_vf_mem.global_alpha_en) {
+ ic_conf |= IC_CONF_IC_GLB_LOC_A;
+ reg = ipu_ic_read(ipu, IC_CMBP_1);
+ reg &= ~(0xff);
+ reg |= params->mem_prp_vf_mem.alpha;
+ ipu_ic_write(ipu, reg, IC_CMBP_1);
+ } else
+ ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
+
+ if (params->mem_prp_vf_mem.key_color_en) {
+ ic_conf |= IC_CONF_KEY_COLOR_EN;
+ ipu_ic_write(ipu, params->mem_prp_vf_mem.key_color,
+ IC_CMBP_2);
+ } else
+ ic_conf &= ~IC_CONF_KEY_COLOR_EN;
+ } else {
+ ic_conf &= ~IC_CONF_PRPVF_CMB;
+ }
+
+ if (src_is_csi)
+ ic_conf &= ~IC_CONF_RWS_EN;
+ else
+ ic_conf |= IC_CONF_RWS_EN;
+
+ ipu_ic_write(ipu, ic_conf, IC_CONF);
+
+ return ret;
+}
+
+void _ipu_ic_uninit_prpvf(struct ipu_soc *ipu)
+{
+ uint32_t reg;
+
+ reg = ipu_ic_read(ipu, IC_CONF);
+ reg &= ~(IC_CONF_PRPVF_EN | IC_CONF_PRPVF_CMB |
+ IC_CONF_PRPVF_CSC2 | IC_CONF_PRPVF_CSC1);
+ ipu_ic_write(ipu, reg, IC_CONF);
+}
+
+void _ipu_ic_init_rotate_vf(struct ipu_soc *ipu, ipu_channel_params_t *params)
+{
+}
+
+void _ipu_ic_uninit_rotate_vf(struct ipu_soc *ipu)
+{
+ uint32_t reg;
+ reg = ipu_ic_read(ipu, IC_CONF);
+ reg &= ~IC_CONF_PRPVF_ROT_EN;
+ ipu_ic_write(ipu, reg, IC_CONF);
+}
+
+int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
+ bool src_is_csi)
+{
+ uint32_t reg, ic_conf;
+ uint32_t downsizeCoeff, resizeCoeff;
+ ipu_color_space_t in_fmt, out_fmt;
+ int ret = 0;
+
+ /* Setup vertical resizing */
+ if (!params->mem_prp_enc_mem.outv_resize_ratio) {
+ ret = _calc_resize_coeffs(ipu,
+ params->mem_prp_enc_mem.in_height,
+ params->mem_prp_enc_mem.out_height,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate prpenc height "
+ "scaling coefficients\n");
+ return ret;
+ }
+
+ reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
+ } else
+ reg = (params->mem_prp_enc_mem.outv_resize_ratio) << 16;
+
+ /* Setup horizontal resizing */
+ if (!params->mem_prp_enc_mem.outh_resize_ratio) {
+ ret = _calc_resize_coeffs(ipu, params->mem_prp_enc_mem.in_width,
+ params->mem_prp_enc_mem.out_width,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate prpenc width "
+ "scaling coefficients\n");
+ return ret;
+ }
+
+ reg |= (downsizeCoeff << 14) | resizeCoeff;
+ } else
+ reg |= params->mem_prp_enc_mem.outh_resize_ratio;
+
+ ipu_ic_write(ipu, reg, IC_PRP_ENC_RSC);
+
+ ic_conf = ipu_ic_read(ipu, IC_CONF);
+
+ /* Setup color space conversion */
+ in_fmt = format_to_colorspace(params->mem_prp_enc_mem.in_pixel_fmt);
+ out_fmt = format_to_colorspace(params->mem_prp_enc_mem.out_pixel_fmt);
+ if (in_fmt == RGB) {
+ if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
+ /* Enable RGB->YCBCR CSC1 */
+ _init_csc(ipu, IC_TASK_ENCODER, RGB, out_fmt, 1);
+ ic_conf |= IC_CONF_PRPENC_CSC1;
+ }
+ }
+ if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
+ if (out_fmt == RGB) {
+ /* Enable YCBCR->RGB CSC1 */
+ _init_csc(ipu, IC_TASK_ENCODER, YCbCr, RGB, 1);
+ ic_conf |= IC_CONF_PRPENC_CSC1;
+ } else {
+ /* TODO: Support YUV<->YCbCr conversion? */
+ }
+ }
+
+ if (src_is_csi)
+ ic_conf &= ~IC_CONF_RWS_EN;
+ else
+ ic_conf |= IC_CONF_RWS_EN;
+
+ ipu_ic_write(ipu, ic_conf, IC_CONF);
+
+ return ret;
+}
+
+void _ipu_ic_uninit_prpenc(struct ipu_soc *ipu)
+{
+ uint32_t reg;
+
+ reg = ipu_ic_read(ipu, IC_CONF);
+ reg &= ~(IC_CONF_PRPENC_EN | IC_CONF_PRPENC_CSC1);
+ ipu_ic_write(ipu, reg, IC_CONF);
+}
+
+void _ipu_ic_init_rotate_enc(struct ipu_soc *ipu, ipu_channel_params_t *params)
+{
+}
+
+void _ipu_ic_uninit_rotate_enc(struct ipu_soc *ipu)
+{
+ uint32_t reg;
+
+ reg = ipu_ic_read(ipu, IC_CONF);
+ reg &= ~(IC_CONF_PRPENC_ROT_EN);
+ ipu_ic_write(ipu, reg, IC_CONF);
+}
+
+int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
+{
+ uint32_t reg, ic_conf;
+ uint32_t downsizeCoeff, resizeCoeff;
+ ipu_color_space_t in_fmt, out_fmt;
+ int ret = 0;
+
+ /* Setup vertical resizing */
+ if (!params->mem_pp_mem.outv_resize_ratio) {
+ ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_height,
+ params->mem_pp_mem.out_height,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate pp height "
+ "scaling coefficients\n");
+ return ret;
+ }
+
+ reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
+ } else {
+ reg = (params->mem_pp_mem.outv_resize_ratio) << 16;
+ }
+
+ /* Setup horizontal resizing */
+ if (!params->mem_pp_mem.outh_resize_ratio) {
+ ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_width,
+ params->mem_pp_mem.out_width,
+ &resizeCoeff, &downsizeCoeff);
+ if (ret < 0) {
+ dev_err(ipu->dev, "failed to calculate pp width "
+ "scaling coefficients\n");
+ return ret;
+ }
+
+ reg |= (downsizeCoeff << 14) | resizeCoeff;
+ } else {
+ reg |= params->mem_pp_mem.outh_resize_ratio;
+ }
+
+ ipu_ic_write(ipu, reg, IC_PP_RSC);
+
+ ic_conf = ipu_ic_read(ipu, IC_CONF);
+
+ /* Setup color space conversion */
+ in_fmt = format_to_colorspace(params->mem_pp_mem.in_pixel_fmt);
+ out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
+ if (in_fmt == RGB) {
+ if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
+ /* Enable RGB->YCBCR CSC1 */
+ _init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, out_fmt, 1);
+ ic_conf |= IC_CONF_PP_CSC1;
+ }
+ }
+ if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
+ if (out_fmt == RGB) {
+ /* Enable YCBCR->RGB CSC1 */
+ _init_csc(ipu, IC_TASK_POST_PROCESSOR, YCbCr, RGB, 1);
+ ic_conf |= IC_CONF_PP_CSC1;
+ } else {
+ /* TODO: Support YUV<->YCbCr conversion? */
+ }
+ }
+
+ if (params->mem_pp_mem.graphics_combine_en) {
+ ic_conf |= IC_CONF_PP_CMB;
+
+ if (!(ic_conf & IC_CONF_PP_CSC1)) {
+ /* need transparent CSC1 conversion */
+ _init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, RGB, 1);
+ ic_conf |= IC_CONF_PP_CSC1; /* Enable RGB->RGB CSC */
+ }
+
+ in_fmt = format_to_colorspace(params->mem_pp_mem.in_g_pixel_fmt);
+ out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
+ if (in_fmt == RGB) {
+ if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
+ /* Enable RGB->YCBCR CSC2 */
+ _init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, out_fmt, 2);
+ ic_conf |= IC_CONF_PP_CSC2;
+ }
+ }
+ if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
+ if (out_fmt == RGB) {
+ /* Enable YCBCR->RGB CSC2 */
+ _init_csc(ipu, IC_TASK_POST_PROCESSOR, YCbCr, RGB, 2);
+ ic_conf |= IC_CONF_PP_CSC2;
+ } else {
+ /* TODO: Support YUV<->YCbCr conversion? */
+ }
+ }
+
+ if (params->mem_pp_mem.global_alpha_en) {
+ ic_conf |= IC_CONF_IC_GLB_LOC_A;
+ reg = ipu_ic_read(ipu, IC_CMBP_1);
+ reg &= ~(0xff00);
+ reg |= (params->mem_pp_mem.alpha << 8);
+ ipu_ic_write(ipu, reg, IC_CMBP_1);
+ } else
+ ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
+
+ if (params->mem_pp_mem.key_color_en) {
+ ic_conf |= IC_CONF_KEY_COLOR_EN;
+ ipu_ic_write(ipu, params->mem_pp_mem.key_color,
+ IC_CMBP_2);
+ } else
+ ic_conf &= ~IC_CONF_KEY_COLOR_EN;
+ } else {
+ ic_conf &= ~IC_CONF_PP_CMB;
+ }
+
+ ipu_ic_write(ipu, ic_conf, IC_CONF);
+
+ return ret;
+}
+
+void _ipu_ic_uninit_pp(struct ipu_soc *ipu)
+{
+ uint32_t reg;
+
+ reg = ipu_ic_read(ipu, IC_CONF);
+ reg &= ~(IC_CONF_PP_EN | IC_CONF_PP_CSC1 | IC_CONF_PP_CSC2 |
+ IC_CONF_PP_CMB);
+ ipu_ic_write(ipu, reg, IC_CONF);
+}
+
+void _ipu_ic_init_rotate_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
+{
+}
+
+void _ipu_ic_uninit_rotate_pp(struct ipu_soc *ipu)
+{
+ uint32_t reg;
+ reg = ipu_ic_read(ipu, IC_CONF);
+ reg &= ~IC_CONF_PP_ROT_EN;
+ ipu_ic_write(ipu, reg, IC_CONF);
+}
+
+int _ipu_ic_idma_init(struct ipu_soc *ipu, int dma_chan,
+ uint16_t width, uint16_t height,
+ int burst_size, ipu_rotate_mode_t rot)
+{
+ u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
+ u32 temp_rot = bitrev8(rot) >> 5;
+ bool need_hor_flip = false;
+
+ if ((burst_size != 8) && (burst_size != 16)) {
+ dev_dbg(ipu->dev, "Illegal burst length for IC\n");
+ return -EINVAL;
+ }
+
+ width--;
+ height--;
+
+ if (temp_rot & 0x2) /* Need horizontal flip */
+ need_hor_flip = true;
+
+ ic_idmac_1 = ipu_ic_read(ipu, IC_IDMAC_1);
+ ic_idmac_2 = ipu_ic_read(ipu, IC_IDMAC_2);
+ ic_idmac_3 = ipu_ic_read(ipu, IC_IDMAC_3);
+ if (dma_chan == 22) { /* PP output - CB2 */
+ if (burst_size == 16)
+ ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
+
+ if (need_hor_flip)
+ ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
+
+ ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
+ ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
+
+ ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
+ ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
+ } else if (dma_chan == 11) { /* PP Input - CB5 */
+ if (burst_size == 16)
+ ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
+ } else if (dma_chan == 47) { /* PP Rot input */
+ ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
+ ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
+ }
+
+ if (dma_chan == 12) { /* PRP Input - CB6 */
+ if (burst_size == 16)
+ ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
+ }
+
+ if (dma_chan == 20) { /* PRP ENC output - CB0 */
+ if (burst_size == 16)
+ ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
+
+ if (need_hor_flip)
+ ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
+
+ ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
+ ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
+
+ ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
+ ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
+
+ } else if (dma_chan == 45) { /* PRP ENC Rot input */
+ ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
+ ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
+ }
+
+ if (dma_chan == 21) { /* PRP VF output - CB1 */
+ if (burst_size == 16)
+ ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
+
+ if (need_hor_flip)
+ ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
+
+ ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
+ ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
+
+ ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
+ ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
+
+ } else if (dma_chan == 46) { /* PRP VF Rot input */
+ ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
+ ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
+ }
+
+ if (dma_chan == 14) { /* PRP VF graphics combining input - CB3 */
+ if (burst_size == 16)
+ ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
+ } else if (dma_chan == 15) { /* PP graphics combining input - CB4 */
+ if (burst_size == 16)
+ ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
+ } else if (dma_chan == 5) { /* VDIC OUTPUT - CB7 */
+ if (burst_size == 16)
+ ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
+ else
+ ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
+ }
+
+ ipu_ic_write(ipu, ic_idmac_1, IC_IDMAC_1);
+ ipu_ic_write(ipu, ic_idmac_2, IC_IDMAC_2);
+ ipu_ic_write(ipu, ic_idmac_3, IC_IDMAC_3);
+ return 0;
+}
+
+static void _init_csc(struct ipu_soc *ipu, uint8_t ic_task, ipu_color_space_t in_format,
+ ipu_color_space_t out_format, int csc_index)
+{
+ /*
+ * Y = 0.257 * R + 0.504 * G + 0.098 * B + 16;
+ * U = -0.148 * R - 0.291 * G + 0.439 * B + 128;
+ * V = 0.439 * R - 0.368 * G - 0.071 * B + 128;
+ */
+ static const uint32_t rgb2ycbcr_coeff[4][3] = {
+ {0x0042, 0x0081, 0x0019},
+ {0x01DA, 0x01B6, 0x0070},
+ {0x0070, 0x01A2, 0x01EE},
+ {0x0040, 0x0200, 0x0200}, /* A0, A1, A2 */
+ };
+
+ /* transparent RGB->RGB matrix for combining
+ */
+ static const uint32_t rgb2rgb_coeff[4][3] = {
+ {0x0080, 0x0000, 0x0000},
+ {0x0000, 0x0080, 0x0000},
+ {0x0000, 0x0000, 0x0080},
+ {0x0000, 0x0000, 0x0000}, /* A0, A1, A2 */
+ };
+
+/* R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
+ G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
+ B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128); */
+ static const uint32_t ycbcr2rgb_coeff[4][3] = {
+ {149, 0, 204},
+ {149, 462, 408},
+ {149, 255, 0},
+ {8192 - 446, 266, 8192 - 554}, /* A0, A1, A2 */
+ };
+
+ uint32_t param;
+ uint32_t *base = NULL;
+
+ if (ic_task == IC_TASK_ENCODER) {
+ base = (uint32_t *)ipu->tpmem_base + 0x2008 / 4;
+ } else if (ic_task == IC_TASK_VIEWFINDER) {
+ if (csc_index == 1)
+ base = (uint32_t *)ipu->tpmem_base + 0x4028 / 4;
+ else
+ base = (uint32_t *)ipu->tpmem_base + 0x4040 / 4;
+ } else if (ic_task == IC_TASK_POST_PROCESSOR) {
+ if (csc_index == 1)
+ base = (uint32_t *)ipu->tpmem_base + 0x6060 / 4;
+ else
+ base = (uint32_t *)ipu->tpmem_base + 0x6078 / 4;
+ } else {
+ BUG();
+ }
+
+ if ((in_format == YCbCr) && (out_format == RGB)) {
+ /* Init CSC (YCbCr->RGB) */
+ param = (ycbcr2rgb_coeff[3][0] << 27) |
+ (ycbcr2rgb_coeff[0][0] << 18) |
+ (ycbcr2rgb_coeff[1][1] << 9) | ycbcr2rgb_coeff[2][2];
+ writel(param, base++);
+ /* scale = 2, sat = 0 */
+ param = (ycbcr2rgb_coeff[3][0] >> 5) | (2L << (40 - 32));
+ writel(param, base++);
+
+ param = (ycbcr2rgb_coeff[3][1] << 27) |
+ (ycbcr2rgb_coeff[0][1] << 18) |
+ (ycbcr2rgb_coeff[1][0] << 9) | ycbcr2rgb_coeff[2][0];
+ writel(param, base++);
+ param = (ycbcr2rgb_coeff[3][1] >> 5);
+ writel(param, base++);
+
+ param = (ycbcr2rgb_coeff[3][2] << 27) |
+ (ycbcr2rgb_coeff[0][2] << 18) |
+ (ycbcr2rgb_coeff[1][2] << 9) | ycbcr2rgb_coeff[2][1];
+ writel(param, base++);
+ param = (ycbcr2rgb_coeff[3][2] >> 5);
+ writel(param, base++);
+ } else if ((in_format == RGB) && (out_format == YCbCr)) {
+ /* Init CSC (RGB->YCbCr) */
+ param = (rgb2ycbcr_coeff[3][0] << 27) |
+ (rgb2ycbcr_coeff[0][0] << 18) |
+ (rgb2ycbcr_coeff[1][1] << 9) | rgb2ycbcr_coeff[2][2];
+ writel(param, base++);
+ /* scale = 1, sat = 0 */
+ param = (rgb2ycbcr_coeff[3][0] >> 5) | (1UL << 8);
+ writel(param, base++);
+
+ param = (rgb2ycbcr_coeff[3][1] << 27) |
+ (rgb2ycbcr_coeff[0][1] << 18) |
+ (rgb2ycbcr_coeff[1][0] << 9) | rgb2ycbcr_coeff[2][0];
+ writel(param, base++);
+ param = (rgb2ycbcr_coeff[3][1] >> 5);
+ writel(param, base++);
+
+ param = (rgb2ycbcr_coeff[3][2] << 27) |
+ (rgb2ycbcr_coeff[0][2] << 18) |
+ (rgb2ycbcr_coeff[1][2] << 9) | rgb2ycbcr_coeff[2][1];
+ writel(param, base++);
+ param = (rgb2ycbcr_coeff[3][2] >> 5);
+ writel(param, base++);
+ } else if ((in_format == RGB) && (out_format == RGB)) {
+ /* Init CSC */
+ param =
+ (rgb2rgb_coeff[3][0] << 27) | (rgb2rgb_coeff[0][0] << 18) |
+ (rgb2rgb_coeff[1][1] << 9) | rgb2rgb_coeff[2][2];
+ writel(param, base++);
+ /* scale = 2, sat = 0 */
+ param = (rgb2rgb_coeff[3][0] >> 5) | (2UL << 8);
+ writel(param, base++);
+
+ param =
+ (rgb2rgb_coeff[3][1] << 27) | (rgb2rgb_coeff[0][1] << 18) |
+ (rgb2rgb_coeff[1][0] << 9) | rgb2rgb_coeff[2][0];
+ writel(param, base++);
+ param = (rgb2rgb_coeff[3][1] >> 5);
+ writel(param, base++);
+
+ param =
+ (rgb2rgb_coeff[3][2] << 27) | (rgb2rgb_coeff[0][2] << 18) |
+ (rgb2rgb_coeff[1][2] << 9) | rgb2rgb_coeff[2][1];
+ writel(param, base++);
+ param = (rgb2rgb_coeff[3][2] >> 5);
+ writel(param, base++);
+ } else {
+ dev_err(ipu->dev, "Unsupported color space conversion\n");
+ }
+}
+
+static int _calc_resize_coeffs(struct ipu_soc *ipu,
+ uint32_t inSize, uint32_t outSize,
+ uint32_t *resizeCoeff,
+ uint32_t *downsizeCoeff)
+{
+ uint32_t tempSize;
+ uint32_t tempDownsize;
+
+ if (inSize > 4096) {
+ dev_err(ipu->dev, "IC input size(%d) cannot exceed 4096\n",
+ inSize);
+ return -EINVAL;
+ }
+
+ if (outSize > 1024) {
+ dev_err(ipu->dev, "IC output size(%d) cannot exceed 1024\n",
+ outSize);
+ return -EINVAL;
+ }
+
+ if ((outSize << 3) < inSize) {
+ dev_err(ipu->dev, "IC cannot downsize more than 8:1\n");
+ return -EINVAL;
+ }
+
+ /* Compute downsizing coefficient */
+ /* Output of downsizing unit cannot be more than 1024 */
+ tempDownsize = 0;
+ tempSize = inSize;
+ while (((tempSize > 1024) || (tempSize >= outSize * 2)) &&
+ (tempDownsize < 2)) {
+ tempSize >>= 1;
+ tempDownsize++;
+ }
+ *downsizeCoeff = tempDownsize;
+
+ /* compute resizing coefficient using the following equation:
+ resizeCoeff = M*(SI -1)/(SO - 1)
+ where M = 2^13, SI - input size, SO - output size */
+ *resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
+ if (*resizeCoeff >= 16384L) {
+ dev_err(ipu->dev, "Overflow on IC resize coefficient.\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(ipu->dev, "resizing from %u -> %u pixels, "
+ "downsize=%u, resize=%u.%lu (reg=%u)\n", inSize, outSize,
+ *downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
+ ((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
+
+ return 0;
+}
+
+void _ipu_vdi_toggle_top_field_man(struct ipu_soc *ipu)
+{
+ uint32_t reg;
+ uint32_t mask_reg;
+
+ reg = ipu_vdi_read(ipu, VDI_C);
+ mask_reg = reg & VDI_C_TOP_FIELD_MAN_1;
+ if (mask_reg == VDI_C_TOP_FIELD_MAN_1)
+ reg &= ~VDI_C_TOP_FIELD_MAN_1;
+ else
+ reg |= VDI_C_TOP_FIELD_MAN_1;
+
+ ipu_vdi_write(ipu, reg, VDI_C);
+}
diff --git a/drivers/mxc/ipu3/ipu_param_mem.h b/drivers/mxc/ipu3/ipu_param_mem.h
new file mode 100644
index 000000000000..a22839a98ac8
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_param_mem.h
@@ -0,0 +1,998 @@
+/*
+ * Copyright 2005-2015 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
+ */
+#ifndef __INCLUDE_IPU_PARAM_MEM_H__
+#define __INCLUDE_IPU_PARAM_MEM_H__
+
+#include <linux/bitrev.h>
+#include <linux/types.h>
+
+#include "ipu_prv.h"
+
+extern u32 *ipu_cpmem_base;
+
+struct ipu_ch_param_word {
+ uint32_t data[5];
+ uint32_t res[3];
+};
+
+struct ipu_ch_param {
+ struct ipu_ch_param_word word[2];
+};
+
+#define ipu_ch_param_addr(ipu, ch) \
+ (((struct ipu_ch_param *)(ipu)->cpmem_base) + (ch))
+
+#define _param_word(base, w) \
+ (((struct ipu_ch_param *)(base))->word[(w)].data)
+
+#define ipu_ch_param_set_field(base, w, bit, size, v) { \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ _param_word((base), (w))[i] |= (v) << off; \
+ if (((bit)+(size)-1)/32 > i) { \
+ _param_word((base), (w))[i + 1] |= \
+ (v) >> (off ? (32 - off) : 0); \
+ } \
+}
+
+#define ipu_ch_param_set_field_io(base, w, bit, size, v) { \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ unsigned reg_offset; \
+ u32 temp; \
+ reg_offset = sizeof(struct ipu_ch_param_word) * (w) / 4; \
+ reg_offset += i; \
+ temp = readl((u32 *)(base) + reg_offset); \
+ temp |= (v) << off; \
+ writel(temp, (u32 *)(base) + reg_offset); \
+ if (((bit)+(size)-1)/32 > i) { \
+ reg_offset++; \
+ temp = readl((u32 *)(base) + reg_offset); \
+ temp |= (v) >> (off ? (32 - off) : 0); \
+ writel(temp, (u32 *)(base) + reg_offset); \
+ } \
+}
+
+#define ipu_ch_param_mod_field(base, w, bit, size, v) { \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ u32 mask = (1UL << (size)) - 1; \
+ u32 temp = _param_word((base), (w))[i]; \
+ temp &= ~(mask << off); \
+ _param_word((base), (w))[i] = temp | (v) << off; \
+ if (((bit)+(size)-1)/32 > i) { \
+ temp = _param_word((base), (w))[i + 1]; \
+ temp &= ~(mask >> (32 - off)); \
+ _param_word((base), (w))[i + 1] = \
+ temp | ((v) >> (off ? (32 - off) : 0)); \
+ } \
+}
+
+#define ipu_ch_param_mod_field_io(base, w, bit, size, v) { \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ u32 mask = (1UL << (size)) - 1; \
+ unsigned reg_offset; \
+ u32 temp; \
+ reg_offset = sizeof(struct ipu_ch_param_word) * (w) / 4; \
+ reg_offset += i; \
+ temp = readl((u32 *)(base) + reg_offset); \
+ temp &= ~(mask << off); \
+ temp |= (v) << off; \
+ writel(temp, (u32 *)(base) + reg_offset); \
+ if (((bit)+(size)-1)/32 > i) { \
+ reg_offset++; \
+ temp = readl((u32 *)(base) + reg_offset); \
+ temp &= ~(mask >> (32 - off)); \
+ temp |= ((v) >> (off ? (32 - off) : 0)); \
+ writel(temp, (u32 *)(base) + reg_offset); \
+ } \
+}
+
+#define ipu_ch_param_read_field(base, w, bit, size) ({ \
+ u32 temp2; \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ u32 mask = (1UL << (size)) - 1; \
+ u32 temp1 = _param_word((base), (w))[i]; \
+ temp1 = mask & (temp1 >> off); \
+ if (((bit)+(size)-1)/32 > i) { \
+ temp2 = _param_word((base), (w))[i + 1]; \
+ temp2 &= mask >> (off ? (32 - off) : 0); \
+ temp1 |= temp2 << (off ? (32 - off) : 0); \
+ } \
+ temp1; \
+})
+
+#define ipu_ch_param_read_field_io(base, w, bit, size) ({ \
+ u32 temp1, temp2; \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ u32 mask = (1UL << (size)) - 1; \
+ unsigned reg_offset; \
+ reg_offset = sizeof(struct ipu_ch_param_word) * (w) / 4; \
+ reg_offset += i; \
+ temp1 = readl((u32 *)(base) + reg_offset); \
+ temp1 = mask & (temp1 >> off); \
+ if (((bit)+(size)-1)/32 > i) { \
+ reg_offset++; \
+ temp2 = readl((u32 *)(base) + reg_offset); \
+ temp2 &= mask >> (off ? (32 - off) : 0); \
+ temp1 |= temp2 << (off ? (32 - off) : 0); \
+ } \
+ temp1; \
+})
+
+static inline int __ipu_ch_get_third_buf_cpmem_num(int ch)
+{
+ switch (ch) {
+ case 8:
+ return 64;
+ case 9:
+ return 65;
+ case 10:
+ return 66;
+ case 13:
+ return 67;
+ case 21:
+ return 68;
+ case 23:
+ return 69;
+ case 27:
+ return 70;
+ case 28:
+ return 71;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static inline void _ipu_ch_params_set_packing(struct ipu_ch_param *p,
+ int red_width, int red_offset,
+ int green_width, int green_offset,
+ int blue_width, int blue_offset,
+ int alpha_width, int alpha_offset)
+{
+ /* Setup red width and offset */
+ ipu_ch_param_set_field(p, 1, 116, 3, red_width - 1);
+ ipu_ch_param_set_field(p, 1, 128, 5, red_offset);
+ /* Setup green width and offset */
+ ipu_ch_param_set_field(p, 1, 119, 3, green_width - 1);
+ ipu_ch_param_set_field(p, 1, 133, 5, green_offset);
+ /* Setup blue width and offset */
+ ipu_ch_param_set_field(p, 1, 122, 3, blue_width - 1);
+ ipu_ch_param_set_field(p, 1, 138, 5, blue_offset);
+ /* Setup alpha width and offset */
+ ipu_ch_param_set_field(p, 1, 125, 3, alpha_width - 1);
+ ipu_ch_param_set_field(p, 1, 143, 5, alpha_offset);
+}
+
+static inline void _ipu_ch_param_dump(struct ipu_soc *ipu, int ch)
+{
+ struct ipu_ch_param *p = ipu_ch_param_addr(ipu, ch);
+ dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", ch,
+ p->word[0].data[0], p->word[0].data[1], p->word[0].data[2],
+ p->word[0].data[3], p->word[0].data[4]);
+ dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", ch,
+ p->word[1].data[0], p->word[1].data[1], p->word[1].data[2],
+ p->word[1].data[3], p->word[1].data[4]);
+ dev_dbg(ipu->dev, "PFS 0x%x, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 85, 4));
+ dev_dbg(ipu->dev, "BPP 0x%x, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3));
+ dev_dbg(ipu->dev, "NPB 0x%x\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7));
+
+ dev_dbg(ipu->dev, "FW %d, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 125, 13));
+ dev_dbg(ipu->dev, "FH %d, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 138, 12));
+ dev_dbg(ipu->dev, "EBA0 0x%x\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 0, 29) << 3);
+ dev_dbg(ipu->dev, "EBA1 0x%x\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 29, 29) << 3);
+ dev_dbg(ipu->dev, "Stride %d\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14));
+ dev_dbg(ipu->dev, "scan_order %d\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1));
+ dev_dbg(ipu->dev, "uv_stride %d\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 14));
+ dev_dbg(ipu->dev, "u_offset 0x%x\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22) << 3);
+ dev_dbg(ipu->dev, "v_offset 0x%x\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22) << 3);
+
+ dev_dbg(ipu->dev, "Width0 %d+1, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 116, 3));
+ dev_dbg(ipu->dev, "Width1 %d+1, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 119, 3));
+ dev_dbg(ipu->dev, "Width2 %d+1, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 122, 3));
+ dev_dbg(ipu->dev, "Width3 %d+1, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3));
+ dev_dbg(ipu->dev, "Offset0 %d, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 5));
+ dev_dbg(ipu->dev, "Offset1 %d, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 133, 5));
+ dev_dbg(ipu->dev, "Offset2 %d, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 138, 5));
+ dev_dbg(ipu->dev, "Offset3 %d\n",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 143, 5));
+}
+
+static inline void fill_cpmem(struct ipu_soc *ipu, int ch, struct ipu_ch_param *params)
+{
+ int i, w;
+ void *addr = ipu_ch_param_addr(ipu, ch);
+
+ /* 2 words, 5 valid data */
+ for (w = 0; w < 2; w++) {
+ for (i = 0; i < 5; i++) {
+ writel(params->word[w].data[i], addr);
+ addr += 4;
+ }
+ addr += 12;
+ }
+}
+
+static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch,
+ uint32_t pixel_fmt, uint32_t width,
+ uint32_t height, uint32_t stride,
+ uint32_t u, uint32_t v,
+ uint32_t uv_stride, dma_addr_t addr0,
+ dma_addr_t addr1, dma_addr_t addr2)
+{
+ uint32_t u_offset = 0;
+ uint32_t v_offset = 0;
+ uint32_t bs = 0;
+ int32_t sub_ch = 0;
+ struct ipu_ch_param params;
+
+ memset(&params, 0, sizeof(params));
+
+ ipu_ch_param_set_field(&params, 0, 125, 13, width - 1);
+
+ if (((ch == 8) || (ch == 9) || (ch == 10)) && !ipu->vdoa_en) {
+ ipu_ch_param_set_field(&params, 0, 138, 12, (height / 2) - 1);
+ ipu_ch_param_set_field(&params, 1, 102, 14, (stride * 2) - 1);
+ } else {
+ /* note: for vdoa+vdi- ch8/9/10, always use band mode */
+ ipu_ch_param_set_field(&params, 0, 138, 12, height - 1);
+ ipu_ch_param_set_field(&params, 1, 102, 14, stride - 1);
+ }
+
+ /* EBA is 8-byte aligned */
+ ipu_ch_param_set_field(&params, 1, 0, 29, addr0 >> 3);
+ ipu_ch_param_set_field(&params, 1, 29, 29, addr1 >> 3);
+ if (addr0%8)
+ dev_warn(ipu->dev,
+ "IDMAC%d's EBA0 is not 8-byte aligned\n", ch);
+ if (addr1%8)
+ dev_warn(ipu->dev,
+ "IDMAC%d's EBA1 is not 8-byte aligned\n", ch);
+
+ switch (pixel_fmt) {
+ case IPU_PIX_FMT_GENERIC:
+ /*Represents 8-bit Generic data */
+ ipu_ch_param_set_field(&params, 0, 107, 3, 5); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 6); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 63); /* burst size */
+
+ break;
+ case IPU_PIX_FMT_GENERIC_16:
+ /* Represents 16-bit generic data */
+ ipu_ch_param_set_field(&params, 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 6); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+
+ break;
+ case IPU_PIX_FMT_GENERIC_32:
+ /*Represents 32-bit Generic data */
+ break;
+ case IPU_PIX_FMT_RGB565:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 5, 0, 6, 5, 5, 11, 8, 16);
+ break;
+ case IPU_PIX_FMT_BGRA4444:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 4, 4, 4, 8, 4, 12, 4, 0);
+ break;
+ case IPU_PIX_FMT_BGRA5551:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 5, 1, 5, 6, 5, 11, 1, 0);
+ break;
+ case IPU_PIX_FMT_BGR24:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 1); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 19); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 8, 0, 8, 8, 8, 16, 8, 24);
+ break;
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_YUV444:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 1); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 19); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 8, 16, 8, 8, 8, 0, 8, 24);
+ break;
+ case IPU_PIX_FMT_VYU444:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 1); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 19); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 8, 8, 8, 0, 8, 16, 8, 24);
+ break;
+ case IPU_PIX_FMT_AYUV:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 0); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 8, 8, 8, 16, 8, 24, 8, 0);
+ break;
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_BGR32:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 0); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 8, 8, 8, 16, 8, 24, 8, 0);
+ break;
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_RGB32:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 0); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 8, 24, 8, 16, 8, 8, 8, 0);
+ break;
+ case IPU_PIX_FMT_ABGR32:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 0); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15); /* burst size */
+
+ _ipu_ch_params_set_packing(&params, 8, 0, 8, 8, 8, 16, 8, 24);
+ break;
+ case IPU_PIX_FMT_UYVY:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 0xA); /* pix format */
+ if ((ch == 8) || (ch == 9) || (ch == 10)) {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15); /* burst size */
+ } else {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+ }
+ break;
+ case IPU_PIX_FMT_YUYV:
+ ipu_ch_param_set_field(&params, 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 0x8); /* pix format */
+ if ((ch == 8) || (ch == 9) || (ch == 10)) {
+ if (ipu->vdoa_en) {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31);
+ } else {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15);
+ }
+ } else {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+ }
+ break;
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YUV420P:
+ ipu_ch_param_set_field(&params, 1, 85, 4, 2); /* pix format */
+
+ if (uv_stride < stride / 2)
+ uv_stride = stride / 2;
+
+ u_offset = stride * height;
+ v_offset = u_offset + (uv_stride * height / 2);
+ if ((ch == 8) || (ch == 9) || (ch == 10)) {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15); /* burst size */
+ uv_stride = uv_stride*2;
+ } else {
+ if (_ipu_is_smfc_chan(ch) &&
+ ipu->smfc_idmac_12bit_3planar_bs_fixup)
+ bs = 15;
+ else
+ bs = 31;
+ ipu_ch_param_set_field(&params, 1, 78, 7, bs); /* burst size */
+ }
+ break;
+ case IPU_PIX_FMT_YVU420P:
+ ipu_ch_param_set_field(&params, 1, 85, 4, 2); /* pix format */
+
+ if (uv_stride < stride / 2)
+ uv_stride = stride / 2;
+
+ v_offset = stride * height;
+ u_offset = v_offset + (uv_stride * height / 2);
+ if ((ch == 8) || (ch == 9) || (ch == 10)) {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15); /* burst size */
+ uv_stride = uv_stride*2;
+ } else {
+ if (_ipu_is_smfc_chan(ch) &&
+ ipu->smfc_idmac_12bit_3planar_bs_fixup)
+ bs = 15;
+ else
+ bs = 31;
+ ipu_ch_param_set_field(&params, 1, 78, 7, bs); /* burst size */
+ }
+ break;
+ case IPU_PIX_FMT_YVU422P:
+ /* BPP & pixel format */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 1); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+
+ if (uv_stride < stride / 2)
+ uv_stride = stride / 2;
+
+ v_offset = (v == 0) ? stride * height : v;
+ u_offset = (u == 0) ? v_offset + v_offset / 2 : u;
+ break;
+ case IPU_PIX_FMT_YUV422P:
+ /* BPP & pixel format */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 1); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+
+ if (uv_stride < stride / 2)
+ uv_stride = stride / 2;
+
+ u_offset = (u == 0) ? stride * height : u;
+ v_offset = (v == 0) ? u_offset + u_offset / 2 : v;
+ break;
+ case IPU_PIX_FMT_YUV444P:
+ /* BPP & pixel format */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 0); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+ uv_stride = stride;
+ u_offset = (u == 0) ? stride * height : u;
+ v_offset = (v == 0) ? u_offset * 2 : v;
+ break;
+ case IPU_PIX_FMT_NV16:
+ ipu_ch_param_set_field(&params, 1, 85, 4, 1); /* pix format */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+ uv_stride = stride;
+ u_offset = (u == 0) ? stride * height : u;
+ break;
+ case IPU_PIX_FMT_NV12:
+ /* BPP & pixel format */
+ ipu_ch_param_set_field(&params, 1, 85, 4, 4); /* pix format */
+ uv_stride = stride;
+ u_offset = (u == 0) ? stride * height : u;
+ if ((ch == 8) || (ch == 9) || (ch == 10)) {
+ if (ipu->vdoa_en) {
+ /* one field buffer, memory width 64bits */
+ ipu_ch_param_set_field(&params, 1, 78, 7, 63);
+ } else {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 15);
+ /* top/bottom field in one buffer*/
+ uv_stride = uv_stride*2;
+ }
+ } else {
+ ipu_ch_param_set_field(&params, 1, 78, 7, 31); /* burst size */
+ }
+ break;
+ default:
+ dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
+ break;
+ }
+ /*set burst size to 16*/
+
+
+ if (uv_stride)
+ ipu_ch_param_set_field(&params, 1, 128, 14, uv_stride - 1);
+
+ /* Get the uv offset from user when need cropping */
+ if (u || v) {
+ u_offset = u;
+ v_offset = v;
+ }
+
+ /* UBO and VBO are 22-bit and 8-byte aligned */
+ if (u_offset/8 > 0x3fffff)
+ dev_warn(ipu->dev,
+ "IDMAC%d's U offset exceeds IPU limitation\n", ch);
+ if (v_offset/8 > 0x3fffff)
+ dev_warn(ipu->dev,
+ "IDMAC%d's V offset exceeds IPU limitation\n", ch);
+ if (u_offset%8)
+ dev_warn(ipu->dev,
+ "IDMAC%d's U offset is not 8-byte aligned\n", ch);
+ if (v_offset%8)
+ dev_warn(ipu->dev,
+ "IDMAC%d's V offset is not 8-byte aligned\n", ch);
+
+ ipu_ch_param_set_field(&params, 0, 46, 22, u_offset / 8);
+ ipu_ch_param_set_field(&params, 0, 68, 22, v_offset / 8);
+
+ dev_dbg(ipu->dev, "initializing idma ch %d @ %p\n", ch, ipu_ch_param_addr(ipu, ch));
+ fill_cpmem(ipu, ch, &params);
+ if (addr2) {
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+
+ ipu_ch_param_set_field(&params, 1, 0, 29, addr2 >> 3);
+ ipu_ch_param_set_field(&params, 1, 29, 29, 0);
+ if (addr2%8)
+ dev_warn(ipu->dev,
+ "IDMAC%d's sub-CPMEM entry%d EBA0 is not "
+ "8-byte aligned\n", ch, sub_ch);
+
+ dev_dbg(ipu->dev, "initializing idma ch %d @ %p sub cpmem\n", ch,
+ ipu_ch_param_addr(ipu, sub_ch));
+ fill_cpmem(ipu, sub_ch, &params);
+ }
+};
+
+static inline void _ipu_ch_param_set_burst_size(struct ipu_soc *ipu,
+ uint32_t ch,
+ uint16_t burst_pixels)
+{
+ int32_t sub_ch = 0;
+
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
+ burst_pixels - 1);
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
+ burst_pixels - 1);
+};
+
+static inline int _ipu_ch_param_get_burst_size(struct ipu_soc *ipu, uint32_t ch)
+{
+ return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
+};
+
+static inline int _ipu_ch_param_get_bpp(struct ipu_soc *ipu, uint32_t ch)
+{
+ return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
+};
+
+static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
+ int bufNum, dma_addr_t phyaddr)
+{
+ if (bufNum == 2) {
+ ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (ch <= 0)
+ return;
+ bufNum = 0;
+ }
+
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
+ phyaddr / 8);
+};
+
+static inline void _ipu_ch_param_set_rotation(struct ipu_soc *ipu, uint32_t ch,
+ ipu_rotate_mode_t rot)
+{
+ u32 temp_rot = bitrev8(rot) >> 5;
+ int32_t sub_ch = 0;
+
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
+};
+
+static inline void _ipu_ch_param_set_block_mode(struct ipu_soc *ipu, uint32_t ch)
+{
+ int32_t sub_ch = 0;
+
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
+};
+
+static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *ipu,
+ uint32_t ch,
+ bool option)
+{
+ int32_t sub_ch = 0;
+
+ if (option) {
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
+ } else {
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
+ }
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+
+ if (option) {
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
+ } else {
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
+ }
+};
+
+static inline void _ipu_ch_param_set_alpha_condition_read(struct ipu_soc *ipu, uint32_t ch)
+{
+ int32_t sub_ch = 0;
+
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
+};
+
+static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, uint32_t ch)
+{
+ int alp_mem_idx;
+ int32_t sub_ch = 0;
+
+ switch (ch) {
+ case 14: /* PRP graphic */
+ alp_mem_idx = 0;
+ break;
+ case 15: /* PP graphic */
+ alp_mem_idx = 1;
+ break;
+ case 23: /* DP BG SYNC graphic */
+ alp_mem_idx = 4;
+ break;
+ case 27: /* DP FG SYNC graphic */
+ alp_mem_idx = 2;
+ break;
+ default:
+ dev_err(ipu->dev, "unsupported correlative channel of local "
+ "alpha channel\n");
+ return;
+ }
+
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
+};
+
+static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32_t ch)
+{
+ u32 stride;
+ int32_t sub_ch = 0;
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+
+ ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
+ if (sub_ch > 0)
+ ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 113, 1, 1);
+ stride = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14) + 1;
+ /* ILO is 20-bit and 8-byte aligned */
+ if (stride/8 > 0xfffff)
+ dev_warn(ipu->dev,
+ "IDMAC%d's ILO exceeds IPU limitation\n", ch);
+ if (stride%8)
+ dev_warn(ipu->dev,
+ "IDMAC%d's ILO is not 8-byte aligned\n", ch);
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 58, 20, stride / 8);
+ if (sub_ch > 0)
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
+ stride / 8);
+ stride *= 2;
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
+ if (sub_ch > 0)
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
+ stride - 1);
+};
+
+static inline void _ipu_ch_param_set_axi_id(struct ipu_soc *ipu, uint32_t ch, uint32_t id)
+{
+ int32_t sub_ch = 0;
+
+ id %= 4;
+
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2, id);
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, id);
+};
+
+static inline int _ipu_ch_param_get_axi_id(struct ipu_soc *ipu, uint32_t ch)
+{
+ return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2);
+}
+
+static inline int __ipu_ch_offset_calc(uint32_t pixel_fmt,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride,
+ uint32_t u,
+ uint32_t v,
+ uint32_t uv_stride,
+ uint32_t vertical_offset,
+ uint32_t horizontal_offset,
+ uint32_t *u_offset,
+ uint32_t *v_offset)
+{
+ uint32_t u_fix = 0;
+ uint32_t v_fix = 0;
+
+ switch (pixel_fmt) {
+ case IPU_PIX_FMT_GENERIC:
+ case IPU_PIX_FMT_GENERIC_16:
+ case IPU_PIX_FMT_GENERIC_32:
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_YUV444:
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_RGB32:
+ case IPU_PIX_FMT_ABGR32:
+ case IPU_PIX_FMT_UYVY:
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_GPU32_SB_ST:
+ case IPU_PIX_FMT_GPU32_SB_SRT:
+ case IPU_PIX_FMT_GPU32_ST:
+ case IPU_PIX_FMT_GPU32_SRT:
+ case IPU_PIX_FMT_GPU16_SB_ST:
+ case IPU_PIX_FMT_GPU16_SB_SRT:
+ case IPU_PIX_FMT_GPU16_ST:
+ case IPU_PIX_FMT_GPU16_SRT:
+ *u_offset = 0;
+ *v_offset = 0;
+ break;
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YUV420P:
+ if (uv_stride < stride / 2)
+ uv_stride = stride / 2;
+
+ *u_offset = stride * (height - vertical_offset - 1) +
+ (stride - horizontal_offset) +
+ (uv_stride * vertical_offset / 2) +
+ horizontal_offset / 2;
+ *v_offset = *u_offset + (uv_stride * height / 2);
+ u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
+ (horizontal_offset / 2) -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *u_offset;
+ v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
+ (horizontal_offset / 2) -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *v_offset;
+ break;
+ case IPU_PIX_FMT_YVU420P:
+ if (uv_stride < stride / 2)
+ uv_stride = stride / 2;
+
+ *v_offset = stride * (height - vertical_offset - 1) +
+ (stride - horizontal_offset) +
+ (uv_stride * vertical_offset / 2) +
+ horizontal_offset / 2;
+ *u_offset = *v_offset + (uv_stride * height / 2);
+ u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
+ (horizontal_offset / 2) -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *u_offset;
+ v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
+ (horizontal_offset / 2) -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *v_offset;
+ break;
+ case IPU_PIX_FMT_YVU422P:
+ if (uv_stride < stride / 2)
+ uv_stride = stride / 2;
+
+ *v_offset = stride * (height - vertical_offset - 1) +
+ (stride - horizontal_offset) +
+ (uv_stride * vertical_offset) +
+ horizontal_offset / 2;
+ *u_offset = *v_offset + uv_stride * height;
+ u_fix = u ? (u + (uv_stride * vertical_offset) +
+ horizontal_offset / 2 -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *u_offset;
+ v_fix = v ? (v + (uv_stride * vertical_offset) +
+ horizontal_offset / 2 -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *v_offset;
+ break;
+ case IPU_PIX_FMT_YUV422P:
+ if (uv_stride < stride / 2)
+ uv_stride = stride / 2;
+
+ *u_offset = stride * (height - vertical_offset - 1) +
+ (stride - horizontal_offset) +
+ (uv_stride * vertical_offset) +
+ horizontal_offset / 2;
+ *v_offset = *u_offset + uv_stride * height;
+ u_fix = u ? (u + (uv_stride * vertical_offset) +
+ horizontal_offset / 2 -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *u_offset;
+ v_fix = v ? (v + (uv_stride * vertical_offset) +
+ horizontal_offset / 2 -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *v_offset;
+ break;
+ case IPU_PIX_FMT_YUV444P:
+ uv_stride = stride;
+ *u_offset = stride * (height - vertical_offset - 1) +
+ (stride - horizontal_offset) +
+ (uv_stride * vertical_offset) +
+ horizontal_offset;
+ *v_offset = *u_offset + uv_stride * height;
+ u_fix = u ? (u + (uv_stride * vertical_offset) +
+ horizontal_offset -
+ (stride * vertical_offset) -
+ (horizontal_offset)) :
+ *u_offset;
+ v_fix = v ? (v + (uv_stride * vertical_offset) +
+ horizontal_offset -
+ (stride * vertical_offset) -
+ (horizontal_offset)) :
+ *v_offset;
+ break;
+ case IPU_PIX_FMT_NV12:
+ case IPU_PIX_FMT_NV16:
+ case PRE_PIX_FMT_NV21:
+ case PRE_PIX_FMT_NV61:
+ uv_stride = stride;
+ *u_offset = stride * (height - vertical_offset - 1) +
+ (stride - horizontal_offset) +
+ (uv_stride * vertical_offset / 2) +
+ horizontal_offset;
+ *v_offset = 0;
+ u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
+ horizontal_offset -
+ (stride * vertical_offset) - (horizontal_offset)) :
+ *u_offset;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (u_fix > *u_offset)
+ *u_offset = u_fix;
+
+ if (v_fix > *v_offset)
+ *v_offset = v_fix;
+
+ return 0;
+}
+
+/* IDMAC U/V offset changing support */
+/* U and V input is not affected, */
+/* the update is done by new calculation according to */
+/* vertical_offset and horizontal_offset */
+static inline void _ipu_ch_offset_update(struct ipu_soc *ipu,
+ int ch,
+ uint32_t pixel_fmt,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride,
+ uint32_t u,
+ uint32_t v,
+ uint32_t uv_stride,
+ uint32_t vertical_offset,
+ uint32_t horizontal_offset)
+{
+ uint32_t u_offset = 0;
+ uint32_t v_offset = 0;
+ uint32_t old_offset = 0;
+ int32_t sub_ch = 0;
+ int ret;
+
+ ret = __ipu_ch_offset_calc(pixel_fmt, width, height, stride,
+ u, v, uv_stride,
+ vertical_offset, horizontal_offset,
+ &u_offset, &v_offset);
+ if (ret) {
+ dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
+ return;
+ }
+
+ /* UBO and VBO are 22-bit and 8-byte aligned */
+ if (u_offset/8 > 0x3fffff)
+ dev_warn(ipu->dev,
+ "IDMAC%d's U offset exceeds IPU limitation\n", ch);
+ if (v_offset/8 > 0x3fffff)
+ dev_warn(ipu->dev,
+ "IDMAC%d's V offset exceeds IPU limitation\n", ch);
+ if (u_offset%8)
+ dev_warn(ipu->dev,
+ "IDMAC%d's U offset is not 8-byte aligned\n", ch);
+ if (v_offset%8)
+ dev_warn(ipu->dev,
+ "IDMAC%d's V offset is not 8-byte aligned\n", ch);
+
+ old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22);
+ if (old_offset != u_offset / 8)
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22, u_offset / 8);
+ old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22);
+ if (old_offset != v_offset / 8)
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22, v_offset / 8);
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22);
+ if (old_offset != u_offset / 8)
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22, u_offset / 8);
+ old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22);
+ if (old_offset != v_offset / 8)
+ ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22, v_offset / 8);
+};
+
+static inline void _ipu_ch_params_set_alpha_width(struct ipu_soc *ipu, uint32_t ch, int alpha_width)
+{
+ int32_t sub_ch = 0;
+
+ ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
+
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
+};
+
+static inline void _ipu_ch_param_set_bandmode(struct ipu_soc *ipu,
+ uint32_t ch, uint32_t band_height)
+{
+ int32_t sub_ch = 0;
+
+ ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch),
+ 0, 114, 3, band_height - 1);
+ sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
+ if (sub_ch <= 0)
+ return;
+ ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch),
+ 0, 114, 3, band_height - 1);
+
+ dev_dbg(ipu->dev, "BNDM 0x%x, ",
+ ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 114, 3));
+}
+
+/*
+ * The IPUv3 IDMAC has a bug to read 32bpp pixels from a graphics plane
+ * whose alpha component is at the most significant 8 bits. The bug only
+ * impacts on cases in which the relevant separate alpha channel is enabled.
+ *
+ * Return true on bad alpha component position, otherwise, return false.
+ */
+static inline bool _ipu_ch_param_bad_alpha_pos(uint32_t pixel_fmt)
+{
+ switch (pixel_fmt) {
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_RGB32:
+ return true;
+ }
+
+ return false;
+}
+#endif
diff --git a/drivers/mxc/ipu3/ipu_pixel_clk.c b/drivers/mxc/ipu3/ipu_pixel_clk.c
new file mode 100644
index 000000000000..66e73dd6284f
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_pixel_clk.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2013-2015 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 ipu_pixel_clk.c
+ *
+ * @brief IPU pixel clock implementation
+ *
+ * @ingroup IPU
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ipu-v3.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "ipu_prv.h"
+#include "ipu_regs.h"
+
+ /*
+ * muxd clock implementation
+ */
+struct clk_di_mux {
+ struct clk_hw hw;
+ u8 ipu_id;
+ u8 di_id;
+ u8 flags;
+ u8 index;
+};
+#define to_clk_di_mux(_hw) container_of(_hw, struct clk_di_mux, hw)
+
+static int _ipu_pixel_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_di_mux *mux = to_clk_di_mux(hw);
+ struct ipu_soc *ipu = ipu_get_soc(mux->ipu_id);
+ u32 di_gen;
+
+ di_gen = ipu_di_read(ipu, mux->di_id, DI_GENERAL);
+ if (index == 0)
+ /* ipu1_clk or ipu2_clk internal clk */
+ di_gen &= ~DI_GEN_DI_CLK_EXT;
+ else
+ di_gen |= DI_GEN_DI_CLK_EXT;
+
+ ipu_di_write(ipu, mux->di_id, di_gen, DI_GENERAL);
+ mux->index = index;
+ pr_debug("ipu_pixel_clk: di_clk_ext:0x%x, di_gen reg:0x%x.\n",
+ !(di_gen & DI_GEN_DI_CLK_EXT), di_gen);
+ return 0;
+}
+
+static u8 _ipu_pixel_clk_get_parent(struct clk_hw *hw)
+{
+ struct clk_di_mux *mux = to_clk_di_mux(hw);
+
+ return mux->index;
+}
+
+const struct clk_ops clk_mux_di_ops = {
+ .get_parent = _ipu_pixel_clk_get_parent,
+ .set_parent = _ipu_pixel_clk_set_parent,
+};
+
+struct clk *clk_register_mux_pix_clk(struct device *dev, const char *name,
+ const char **parent_names, u8 num_parents, unsigned long flags,
+ u8 ipu_id, u8 di_id, u8 clk_mux_flags)
+{
+ struct clk_di_mux *mux;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ mux = kzalloc(sizeof(struct clk_di_mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &clk_mux_di_ops;
+ init.flags = flags;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+
+ mux->ipu_id = ipu_id;
+ mux->di_id = di_id;
+ mux->flags = clk_mux_flags | CLK_SET_RATE_PARENT;
+ mux->hw.init = &init;
+
+ clk = clk_register(dev, &mux->hw);
+ if (IS_ERR(clk))
+ kfree(mux);
+
+ return clk;
+}
+
+/*
+ * Gated clock implementation
+ */
+struct clk_di_div {
+ struct clk_hw hw;
+ u8 ipu_id;
+ u8 di_id;
+ u8 flags;
+};
+#define to_clk_di_div(_hw) container_of(_hw, struct clk_di_div, hw)
+
+static unsigned long _ipu_pixel_clk_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_di_div *di_div = to_clk_di_div(hw);
+ struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
+ u32 div;
+ u64 final_rate = (unsigned long long)parent_rate * 16;
+
+ _ipu_get(ipu);
+ div = ipu_di_read(ipu, di_div->di_id, DI_BS_CLKGEN0);
+ _ipu_put(ipu);
+ pr_debug("ipu_di%d read BS_CLKGEN0 div:%d, final_rate:%lld, prate:%ld\n",
+ di_div->di_id, div, final_rate, parent_rate);
+
+ if (div == 0)
+ return 0;
+ do_div(final_rate, div);
+
+ return (unsigned long)final_rate;
+}
+
+static long _ipu_pixel_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_clk_rate)
+{
+ u64 div, final_rate;
+ u32 remainder;
+ u64 parent_rate = (unsigned long long)(*parent_clk_rate) * 16;
+
+ /*
+ * Calculate divider
+ * Fractional part is 4 bits,
+ * so simply multiply by 2^4 to get fractional part.
+ */
+ div = parent_rate;
+ remainder = do_div(div, rate);
+ /* Round the divider value */
+ if (remainder > (rate/2))
+ div++;
+ if (div < 0x10) /* Min DI disp clock divider is 1 */
+ div = 0x10;
+ if (div & ~0xFEF)
+ div &= 0xFF8;
+ else {
+ /* Round up divider if it gets us closer to desired pix clk */
+ if ((div & 0xC) == 0xC) {
+ div += 0x10;
+ div &= ~0xF;
+ }
+ }
+ final_rate = parent_rate;
+ do_div(final_rate, div);
+
+ return final_rate;
+}
+
+static int _ipu_pixel_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_clk_rate)
+{
+ struct clk_di_div *di_div = to_clk_di_div(hw);
+ struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
+ u64 div, parent_rate;
+ u32 remainder;
+
+ parent_rate = (unsigned long long)parent_clk_rate * 16;
+ div = parent_rate;
+ remainder = do_div(div, rate);
+ /* Round the divider value */
+ if (remainder > (rate/2))
+ div++;
+
+ /* Round up divider if it gets us closer to desired pix clk */
+ if ((div & 0xC) == 0xC) {
+ div += 0x10;
+ div &= ~0xF;
+ }
+ if (div > 0x1000)
+ pr_err("Overflow, di:%d, DI_BS_CLKGEN0 div:0x%x\n",
+ di_div->di_id, (u32)div);
+ _ipu_get(ipu);
+ ipu_di_write(ipu, di_div->di_id, (u32)div, DI_BS_CLKGEN0);
+
+ /* Setup pixel clock timing */
+ /* FIXME: needs to be more flexible */
+ /* Down time is half of period */
+ ipu_di_write(ipu, di_div->di_id, ((u32)div / 16) << 16, DI_BS_CLKGEN1);
+ _ipu_put(ipu);
+
+ return 0;
+}
+
+static struct clk_ops clk_div_ops = {
+ .recalc_rate = _ipu_pixel_clk_div_recalc_rate,
+ .round_rate = _ipu_pixel_clk_div_round_rate,
+ .set_rate = _ipu_pixel_clk_div_set_rate,
+};
+
+struct clk *clk_register_div_pix_clk(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ u8 ipu_id, u8 di_id, u8 clk_div_flags)
+{
+ struct clk_di_div *di_div;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ di_div = kzalloc(sizeof(struct clk_di_div), GFP_KERNEL);
+ if (!di_div)
+ return ERR_PTR(-ENOMEM);
+
+ /* struct clk_di_div assignments */
+ di_div->ipu_id = ipu_id;
+ di_div->di_id = di_id;
+ di_div->flags = clk_div_flags;
+
+ init.name = name;
+ init.ops = &clk_div_ops;
+ init.flags = flags | CLK_SET_RATE_PARENT;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ di_div->hw.init = &init;
+
+ clk = clk_register(dev, &di_div->hw);
+ if (IS_ERR(clk))
+ kfree(di_div);
+
+ return clk;
+}
+
+/*
+ * Gated clock implementation
+ */
+struct clk_di_gate {
+ struct clk_hw hw;
+ u8 ipu_id;
+ u8 di_id;
+ u8 flags;
+};
+#define to_clk_di_gate(_hw) container_of(_hw, struct clk_di_gate, hw)
+
+static int _ipu_pixel_clk_enable(struct clk_hw *hw)
+{
+ struct clk_di_gate *gate = to_clk_di_gate(hw);
+ struct ipu_soc *ipu = ipu_get_soc(gate->ipu_id);
+ u32 disp_gen;
+
+ disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
+ disp_gen |= gate->di_id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
+ ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
+
+ return 0;
+}
+
+static void _ipu_pixel_clk_disable(struct clk_hw *hw)
+{
+ struct clk_di_gate *gate = to_clk_di_gate(hw);
+ struct ipu_soc *ipu = ipu_get_soc(gate->ipu_id);
+ u32 disp_gen;
+
+ disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
+ disp_gen &= gate->di_id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
+ ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
+
+}
+
+
+static struct clk_ops clk_gate_di_ops = {
+ .enable = _ipu_pixel_clk_enable,
+ .disable = _ipu_pixel_clk_disable,
+};
+
+struct clk *clk_register_gate_pix_clk(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ u8 ipu_id, u8 di_id, u8 clk_gate_flags)
+{
+ struct clk_di_gate *gate;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ gate = kzalloc(sizeof(struct clk_di_gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ gate->ipu_id = ipu_id;
+ gate->di_id = di_id;
+ gate->flags = clk_gate_flags;
+
+ init.name = name;
+ init.ops = &clk_gate_di_ops;
+ init.flags = flags | CLK_SET_RATE_PARENT;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ gate->hw.init = &init;
+
+ clk = clk_register(dev, &gate->hw);
+ if (IS_ERR(clk))
+ kfree(gate);
+
+ return clk;
+}
diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h
new file mode 100644
index 000000000000..0a21d922c127
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_prv.h
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2005-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
+ */
+#ifndef __INCLUDE_IPU_PRV_H__
+#define __INCLUDE_IPU_PRV_H__
+
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
+#include <linux/ipu-v3.h>
+#include <linux/types.h>
+
+#define MXC_IPU_MAX_NUM 2
+#define MXC_DI_NUM_PER_IPU 2
+
+/* Globals */
+extern int dmfc_type_setup;
+
+#define IDMA_CHAN_INVALID 0xFF
+#define HIGH_RESOLUTION_WIDTH 1024
+
+enum ipuv3_type {
+ IPUv3D, /* i.MX37 */
+ IPUv3EX, /* i.MX51 */
+ IPUv3M, /* i.MX53 */
+ IPUv3H, /* i.MX6Q/SDL */
+};
+
+#define IPU_MAX_VDI_IN_WIDTH(type) ({ (type) >= IPUv3M ? 968 : 720; })
+
+struct ipu_irq_node {
+ irqreturn_t(*handler) (int, void *); /*!< the ISR */
+ const char *name; /*!< device associated with the interrupt */
+ void *dev_id; /*!< some unique information for the ISR */
+ __u32 flags; /*!< not used */
+};
+
+enum csc_type_t {
+ RGB2YUV = 0,
+ YUV2RGB,
+ RGB2RGB,
+ YUV2YUV,
+ CSC_NONE,
+ CSC_NUM
+};
+
+struct ipu_soc {
+ unsigned int id;
+ unsigned int devtype;
+ bool online;
+
+ /*clk*/
+ struct clk *ipu_clk;
+ struct clk *di_clk[2];
+ struct clk *di_clk_sel[2];
+ struct clk *pixel_clk[2];
+ bool pixel_clk_en[2];
+ struct clk *pixel_clk_sel[2];
+ struct clk *csi_clk[2];
+ struct clk *prg_clk;
+
+ /*irq*/
+ int irq_sync;
+ int irq_err;
+ struct ipu_irq_node irq_list[IPU_IRQ_COUNT];
+
+ /*reg*/
+ void __iomem *cm_reg;
+ void __iomem *idmac_reg;
+ void __iomem *dp_reg;
+ void __iomem *ic_reg;
+ void __iomem *dc_reg;
+ void __iomem *dc_tmpl_reg;
+ void __iomem *dmfc_reg;
+ void __iomem *di_reg[2];
+ void __iomem *smfc_reg;
+ void __iomem *csi_reg[2];
+ void __iomem *cpmem_base;
+ void __iomem *tpmem_base;
+ void __iomem *vdi_reg;
+
+ struct device *dev;
+
+ ipu_channel_t csi_channel[2];
+ ipu_channel_t using_ic_dirct_ch;
+ unsigned char dc_di_assignment[10];
+ bool sec_chan_en[IPU_MAX_CH];
+ bool thrd_chan_en[IPU_MAX_CH];
+ bool chan_is_interlaced[52];
+ uint32_t channel_init_mask;
+ uint32_t channel_enable_mask;
+
+ /*use count*/
+ int dc_use_count;
+ int dp_use_count;
+ int dmfc_use_count;
+ int smfc_use_count;
+ int ic_use_count;
+ int rot_use_count;
+ int vdi_use_count;
+ int di_use_count[2];
+ int csi_use_count[2];
+
+ struct mutex mutex_lock;
+ spinlock_t int_reg_spin_lock;
+ spinlock_t rdy_reg_spin_lock;
+
+ int dmfc_size_28;
+ int dmfc_size_29;
+ int dmfc_size_24;
+ int dmfc_size_27;
+ int dmfc_size_23;
+
+ enum csc_type_t fg_csc_type;
+ enum csc_type_t bg_csc_type;
+ bool color_key_4rgb;
+ bool dc_swap;
+ struct completion dc_comp;
+ struct completion csi_comp;
+
+ struct rot_mem {
+ void *vaddr;
+ dma_addr_t paddr;
+ int size;
+ } rot_dma[2];
+
+ int vdoa_en;
+ struct task_struct *thread[2];
+
+ /*
+ * Bypass reset to avoid display channel being
+ * stopped by probe since it may starts to work
+ * in bootloader.
+ */
+ bool bypass_reset;
+
+ unsigned int ch0123_axi;
+ unsigned int ch23_axi;
+ unsigned int ch27_axi;
+ unsigned int ch28_axi;
+ unsigned int normal_axi;
+
+ bool smfc_idmac_12bit_3planar_bs_fixup; /* workaround little stripes */
+};
+
+struct ipu_channel {
+ u8 video_in_dma;
+ u8 alpha_in_dma;
+ u8 graph_in_dma;
+ u8 out_dma;
+};
+
+enum ipu_dmfc_type {
+ DMFC_NORMAL = 0,
+ DMFC_HIGH_RESOLUTION_DC,
+ DMFC_HIGH_RESOLUTION_DP,
+ DMFC_HIGH_RESOLUTION_ONLY_DP,
+};
+
+static inline int _ipu_is_smfc_chan(uint32_t dma_chan)
+{
+ return dma_chan <= 3;
+}
+
+static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->cm_reg + offset);
+}
+
+static inline void ipu_cm_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->cm_reg + offset);
+}
+
+static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->idmac_reg + offset);
+}
+
+static inline void ipu_idmac_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->idmac_reg + offset);
+}
+
+static inline u32 ipu_dc_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->dc_reg + offset);
+}
+
+static inline void ipu_dc_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->dc_reg + offset);
+}
+
+static inline u32 ipu_dc_tmpl_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->dc_tmpl_reg + offset);
+}
+
+static inline void ipu_dc_tmpl_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->dc_tmpl_reg + offset);
+}
+
+static inline u32 ipu_dmfc_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->dmfc_reg + offset);
+}
+
+static inline void ipu_dmfc_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->dmfc_reg + offset);
+}
+
+static inline u32 ipu_dp_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->dp_reg + offset);
+}
+
+static inline void ipu_dp_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->dp_reg + offset);
+}
+
+static inline u32 ipu_di_read(struct ipu_soc *ipu, int di, unsigned offset)
+{
+ return readl(ipu->di_reg[di] + offset);
+}
+
+static inline void ipu_di_write(struct ipu_soc *ipu, int di,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->di_reg[di] + offset);
+}
+
+static inline u32 ipu_csi_read(struct ipu_soc *ipu, int csi, unsigned offset)
+{
+ return readl(ipu->csi_reg[csi] + offset);
+}
+
+static inline void ipu_csi_write(struct ipu_soc *ipu, int csi,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->csi_reg[csi] + offset);
+}
+
+static inline u32 ipu_smfc_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->smfc_reg + offset);
+}
+
+static inline void ipu_smfc_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->smfc_reg + offset);
+}
+
+static inline u32 ipu_vdi_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->vdi_reg + offset);
+}
+
+static inline void ipu_vdi_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->vdi_reg + offset);
+}
+
+static inline u32 ipu_ic_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return readl(ipu->ic_reg + offset);
+}
+
+static inline void ipu_ic_write(struct ipu_soc *ipu,
+ u32 value, unsigned offset)
+{
+ writel(value, ipu->ic_reg + offset);
+}
+
+int register_ipu_device(struct ipu_soc *ipu, int id);
+void unregister_ipu_device(struct ipu_soc *ipu, int id);
+ipu_color_space_t format_to_colorspace(uint32_t fmt);
+bool ipu_pixel_format_has_alpha(uint32_t fmt);
+
+void ipu_dump_registers(struct ipu_soc *ipu);
+
+uint32_t _ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel);
+
+void ipu_disp_init(struct ipu_soc *ipu);
+void _ipu_init_dc_mappings(struct ipu_soc *ipu);
+int _ipu_dp_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t in_pixel_fmt,
+ uint32_t out_pixel_fmt);
+void _ipu_dp_uninit(struct ipu_soc *ipu, ipu_channel_t channel);
+void _ipu_dc_init(struct ipu_soc *ipu, int dc_chan, int di, bool interlaced, uint32_t pixel_fmt);
+void _ipu_dc_uninit(struct ipu_soc *ipu, int dc_chan);
+void _ipu_dp_dc_enable(struct ipu_soc *ipu, ipu_channel_t channel);
+void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap);
+void _ipu_dmfc_init(struct ipu_soc *ipu, int dmfc_type, int first);
+void _ipu_dmfc_set_wait4eot(struct ipu_soc *ipu, int dma_chan, int width);
+void _ipu_dmfc_set_burst_size(struct ipu_soc *ipu, int dma_chan, int burst_size);
+int _ipu_disp_chan_is_interlaced(struct ipu_soc *ipu, ipu_channel_t channel);
+
+void _ipu_ic_enable_task(struct ipu_soc *ipu, ipu_channel_t channel);
+void _ipu_ic_disable_task(struct ipu_soc *ipu, ipu_channel_t channel);
+int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
+ bool src_is_csi);
+void _ipu_vdi_init(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
+void _ipu_vdi_uninit(struct ipu_soc *ipu);
+void _ipu_ic_uninit_prpvf(struct ipu_soc *ipu);
+void _ipu_ic_init_rotate_vf(struct ipu_soc *ipu, ipu_channel_params_t *params);
+void _ipu_ic_uninit_rotate_vf(struct ipu_soc *ipu);
+void _ipu_ic_init_csi(struct ipu_soc *ipu, ipu_channel_params_t *params);
+void _ipu_ic_uninit_csi(struct ipu_soc *ipu);
+int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
+ bool src_is_csi);
+void _ipu_ic_uninit_prpenc(struct ipu_soc *ipu);
+void _ipu_ic_init_rotate_enc(struct ipu_soc *ipu, ipu_channel_params_t *params);
+void _ipu_ic_uninit_rotate_enc(struct ipu_soc *ipu);
+int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
+void _ipu_ic_uninit_pp(struct ipu_soc *ipu);
+void _ipu_ic_init_rotate_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
+void _ipu_ic_uninit_rotate_pp(struct ipu_soc *ipu);
+int _ipu_ic_idma_init(struct ipu_soc *ipu, int dma_chan, uint16_t width, uint16_t height,
+ int burst_size, ipu_rotate_mode_t rot);
+void _ipu_vdi_toggle_top_field_man(struct ipu_soc *ipu);
+int _ipu_csi_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t csi);
+int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uint32_t csi);
+void ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
+ uint32_t g_value, uint32_t b_value,
+ uint32_t pix_clk, uint32_t csi);
+void _ipu_csi_ccir_err_detection_enable(struct ipu_soc *ipu, uint32_t csi);
+void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi);
+void _ipu_csi_wait4eof(struct ipu_soc *ipu, ipu_channel_t channel);
+void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id, uint32_t csi);
+void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs);
+void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
+int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+ int16_t x_pos, int16_t y_pos);
+int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+ int16_t *x_pos, int16_t *y_pos);
+void _ipu_get(struct ipu_soc *ipu);
+void _ipu_put(struct ipu_soc *ipu);
+
+struct clk *clk_register_mux_pix_clk(struct device *dev, const char *name,
+ const char **parent_names, u8 num_parents, unsigned long flags,
+ u8 ipu_id, u8 di_id, u8 clk_mux_flags);
+struct clk *clk_register_div_pix_clk(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ u8 ipu_id, u8 di_id, u8 clk_div_flags);
+struct clk *clk_register_gate_pix_clk(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ u8 ipu_id, u8 di_id, u8 clk_gate_flags);
+#endif /* __INCLUDE_IPU_PRV_H__ */
diff --git a/drivers/mxc/ipu3/ipu_regs.h b/drivers/mxc/ipu3/ipu_regs.h
new file mode 100644
index 000000000000..099346da3e1b
--- /dev/null
+++ b/drivers/mxc/ipu3/ipu_regs.h
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2005-2015 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 ipu_regs.h
+ *
+ * @brief IPU Register definitions
+ *
+ * @ingroup IPU
+ */
+#ifndef __IPU_REGS_INCLUDED__
+#define __IPU_REGS_INCLUDED__
+
+#include "ipu_prv.h"
+
+#define IPU_MCU_T_DEFAULT 8
+
+/* Register addresses */
+/* IPU Common registers */
+#define IPU_CM_REG(offset) (offset)
+
+#define IPU_CONF IPU_CM_REG(0)
+#define IPU_SRM_PRI1 IPU_CM_REG(0x00A0)
+#define IPU_SRM_PRI2 IPU_CM_REG(0x00A4)
+#define IPU_FS_PROC_FLOW1 IPU_CM_REG(0x00A8)
+#define IPU_FS_PROC_FLOW2 IPU_CM_REG(0x00AC)
+#define IPU_FS_PROC_FLOW3 IPU_CM_REG(0x00B0)
+#define IPU_FS_DISP_FLOW1 IPU_CM_REG(0x00B4)
+#define IPU_FS_DISP_FLOW2 IPU_CM_REG(0x00B8)
+#define IPU_SKIP IPU_CM_REG(0x00BC)
+#define IPU_DISP_ALT_CONF IPU_CM_REG(0x00C0)
+#define IPU_DISP_GEN IPU_CM_REG(0x00C4)
+#define IPU_DISP_ALT1 IPU_CM_REG(0x00C8)
+#define IPU_DISP_ALT2 IPU_CM_REG(0x00CC)
+#define IPU_DISP_ALT3 IPU_CM_REG(0x00D0)
+#define IPU_DISP_ALT4 IPU_CM_REG(0x00D4)
+#define IPU_SNOOP IPU_CM_REG(0x00D8)
+#define IPU_MEM_RST IPU_CM_REG(0x00DC)
+#define IPU_PM IPU_CM_REG(0x00E0)
+#define IPU_GPR IPU_CM_REG(0x00E4)
+#define IPU_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
+#define IPU_ALT_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
+/*
+ * IPUv3D doesn't support triple buffer, so point
+ * IPU_CHA_TRB_MODE_SEL, IPU_CHA_TRIPLE_CUR_BUF and
+ * IPU_CHA_BUF2_RDY to readonly
+ * IPU_ALT_CUR_BUF0 for IPUv3D.
+ */
+#define IPU_CHA_TRB_MODE_SEL(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0178 + 4 * ((ch) / 32)) : \
+ (0x012C); })
+#define IPU_CHA_TRIPLE_CUR_BUF(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0258 + \
+ 4 * (((ch) * 2) / 32)) : \
+ (0x012C); })
+#define IPU_CHA_BUF2_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0288 + 4 * ((ch) / 32)) : \
+ (0x012C); })
+#define IPU_CHA_CUR_BUF(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x023C + 4 * ((ch) / 32)) : \
+ (0x0124 + 4 * ((ch) / 32)); })
+#define IPU_ALT_CUR_BUF0(type) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0244) : \
+ (0x012C); })
+#define IPU_ALT_CUR_BUF1(type) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0248) : \
+ (0x0130); })
+#define IPU_SRM_STAT(type) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x024C) : \
+ (0x0134); })
+#define IPU_PROC_TASK_STAT(type) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0250) : \
+ (0x0138); })
+#define IPU_DISP_TASK_STAT(type) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0254) : \
+ (0x013C); })
+#define IPU_CHA_BUF0_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0268 + 4 * ((ch) / 32)) : \
+ (0x0140 + 4 * ((ch) / 32)); })
+#define IPU_CHA_BUF1_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0270 + 4 * ((ch) / 32)) : \
+ (0x0148 + 4 * ((ch) / 32)); })
+#define IPU_ALT_CHA_BUF0_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0278 + 4 * ((ch) / 32)) : \
+ (0x0158 + 4 * ((ch) / 32)); })
+#define IPU_ALT_CHA_BUF1_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0280 + 4 * ((ch) / 32)) : \
+ (0x0160 + 4 * ((ch) / 32)); })
+
+#define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * ((n) - 1))
+#define IPU_INT_STAT(type, n) IPU_CM_REG({(type) >= IPUv3EX ? \
+ (0x0200 + 4 * ((n) - 1)) : \
+ (0x00E8 + 4 * ((n) - 1)); })
+
+#define IPUIRQ_2_STATREG(type, irq) IPU_CM_REG(IPU_INT_STAT((type), 1) + 4 \
+ * ((irq) / 32))
+#define IPUIRQ_2_CTRLREG(irq) IPU_CM_REG(IPU_INT_CTRL(1) + 4 * ((irq) / 32))
+#define IPUIRQ_2_MASK(irq) (1UL << ((irq) & 0x1F))
+
+/* IPU VDI registers */
+#define IPU_VDI_REG(offset) (offset)
+
+#define VDI_FSIZE IPU_VDI_REG(0)
+#define VDI_C IPU_VDI_REG(0x0004)
+
+/* IPU CSI Registers */
+#define IPU_CSI_REG(offset) (offset)
+
+#define CSI_SENS_CONF IPU_CSI_REG(0)
+#define CSI_SENS_FRM_SIZE IPU_CSI_REG(0x0004)
+#define CSI_ACT_FRM_SIZE IPU_CSI_REG(0x0008)
+#define CSI_OUT_FRM_CTRL IPU_CSI_REG(0x000C)
+#define CSI_TST_CTRL IPU_CSI_REG(0x0010)
+#define CSI_CCIR_CODE_1 IPU_CSI_REG(0x0014)
+#define CSI_CCIR_CODE_2 IPU_CSI_REG(0x0018)
+#define CSI_CCIR_CODE_3 IPU_CSI_REG(0x001C)
+#define CSI_MIPI_DI IPU_CSI_REG(0x0020)
+#define CSI_SKIP IPU_CSI_REG(0x0024)
+#define CSI_CPD_CTRL IPU_CSI_REG(0x0028)
+#define CSI_CPD_RC(n) IPU_CSI_REG(0x002C + 4 * (n))
+#define CSI_CPD_RS(n) IPU_CSI_REG(0x004C + 4 * (n))
+#define CSI_CPD_GRC(n) IPU_CSI_REG(0x005C + 4 * (n))
+#define CSI_CPD_GRS(n) IPU_CSI_REG(0x007C + 4 * (n))
+#define CSI_CPD_GBC(n) IPU_CSI_REG(0x008C + 4 * (n))
+#define CSI_CPD_GBS(n) IPU_CSI_REG(0x00AC + 4 * (n))
+#define CSI_CPD_BC(n) IPU_CSI_REG(0x00BC + 4 * (n))
+#define CSI_CPD_BS(n) IPU_CSI_REG(0x00DC + 4 * (n))
+#define CSI_CPD_OFFSET1 IPU_CSI_REG(0x00EC)
+#define CSI_CPD_OFFSET2 IPU_CSI_REG(0x00F0)
+
+/* IPU SMFC Registers */
+#define IPU_SMFC_REG(offset) (offset)
+
+#define SMFC_MAP IPU_SMFC_REG(0)
+#define SMFC_WMC IPU_SMFC_REG(0x0004)
+#define SMFC_BS IPU_SMFC_REG(0x0008)
+
+/* IPU IC Registers */
+#define IPU_IC_REG(offset) (offset)
+
+#define IC_CONF IPU_IC_REG(0)
+#define IC_PRP_ENC_RSC IPU_IC_REG(0x0004)
+#define IC_PRP_VF_RSC IPU_IC_REG(0x0008)
+#define IC_PP_RSC IPU_IC_REG(0x000C)
+#define IC_CMBP_1 IPU_IC_REG(0x0010)
+#define IC_CMBP_2 IPU_IC_REG(0x0014)
+#define IC_IDMAC_1 IPU_IC_REG(0x0018)
+#define IC_IDMAC_2 IPU_IC_REG(0x001C)
+#define IC_IDMAC_3 IPU_IC_REG(0x0020)
+#define IC_IDMAC_4 IPU_IC_REG(0x0024)
+
+/* IPU IDMAC Registers */
+#define IPU_IDMAC_REG(offset) (offset)
+
+#define IDMAC_CONF IPU_IDMAC_REG(0x0000)
+#define IDMAC_CHA_EN(ch) IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
+#define IDMAC_SEP_ALPHA IPU_IDMAC_REG(0x000C)
+#define IDMAC_ALT_SEP_ALPHA IPU_IDMAC_REG(0x0010)
+#define IDMAC_CHA_PRI(ch) IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
+#define IDMAC_WM_EN(ch) IPU_IDMAC_REG(0x001C + 4 * ((ch) / 32))
+#define IDMAC_CH_LOCK_EN_1(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x0024) : 0; })
+#define IDMAC_CH_LOCK_EN_2(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x0028) : \
+ (0x0024); })
+#define IDMAC_SUB_ADDR_0(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x002C) : \
+ (0x0028); })
+#define IDMAC_SUB_ADDR_1(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x0030) : \
+ (0x002C); })
+#define IDMAC_SUB_ADDR_2(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x0034) : \
+ (0x0030); })
+/*
+ * IPUv3D doesn't support IDMAC_SUB_ADDR_3 and IDMAC_SUB_ADDR_4,
+ * so point them to readonly IDMAC_CHA_BUSY1 for IPUv3D.
+ */
+#define IDMAC_SUB_ADDR_3(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x0038) : \
+ (0x0040); })
+#define IDMAC_SUB_ADDR_4(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x003C) : \
+ (0x0040); })
+#define IDMAC_BAND_EN(type, ch) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x0040 + 4 * ((ch) / 32)) : \
+ (0x0034 + 4 * ((ch) / 32)); })
+#define IDMAC_CHA_BUSY(type, ch) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
+ (0x0100 + 4 * ((ch) / 32)) : \
+ (0x0040 + 4 * ((ch) / 32)); })
+
+/* IPU DI Registers */
+#define IPU_DI_REG(offset) (offset)
+
+#define DI_GENERAL IPU_DI_REG(0)
+#define DI_BS_CLKGEN0 IPU_DI_REG(0x0004)
+#define DI_BS_CLKGEN1 IPU_DI_REG(0x0008)
+#define DI_SW_GEN0(gen) IPU_DI_REG(0x000C + 4 * ((gen) - 1))
+#define DI_SW_GEN1(gen) IPU_DI_REG(0x0030 + 4 * ((gen) - 1))
+#define DI_STP_REP(gen) IPU_DI_REG(0x0148 + 4 * (((gen) - 1) / 2))
+#define DI_SYNC_AS_GEN IPU_DI_REG(0x0054)
+#define DI_DW_GEN(gen) IPU_DI_REG(0x0058 + 4 * (gen))
+#define DI_DW_SET(gen, set) IPU_DI_REG(0x0088 + 4 * ((gen) + 0xC * (set)))
+#define DI_SER_CONF IPU_DI_REG(0x015C)
+#define DI_SSC IPU_DI_REG(0x0160)
+#define DI_POL IPU_DI_REG(0x0164)
+#define DI_AW0 IPU_DI_REG(0x0168)
+#define DI_AW1 IPU_DI_REG(0x016C)
+#define DI_SCR_CONF IPU_DI_REG(0x0170)
+#define DI_STAT IPU_DI_REG(0x0174)
+
+/* IPU DMFC Registers */
+#define IPU_DMFC_REG(offset) (offset)
+
+#define DMFC_RD_CHAN IPU_DMFC_REG(0)
+#define DMFC_WR_CHAN IPU_DMFC_REG(0x0004)
+#define DMFC_WR_CHAN_DEF IPU_DMFC_REG(0x0008)
+#define DMFC_DP_CHAN IPU_DMFC_REG(0x000C)
+#define DMFC_DP_CHAN_DEF IPU_DMFC_REG(0x0010)
+#define DMFC_GENERAL1 IPU_DMFC_REG(0x0014)
+#define DMFC_GENERAL2 IPU_DMFC_REG(0x0018)
+#define DMFC_IC_CTRL IPU_DMFC_REG(0x001C)
+#define DMFC_STAT IPU_DMFC_REG(0x0020)
+
+/* IPU DC Registers */
+#define IPU_DC_REG(offset) (offset)
+
+#define DC_MAP_CONF_PTR(n) IPU_DC_REG(0x0108 + ((n) & ~0x1) * 2)
+#define DC_MAP_CONF_VAL(n) IPU_DC_REG(0x0144 + ((n) & ~0x1) * 2)
+
+#define _RL_CH_2_OFFSET(ch) (((ch) == 0) ? 8 : ( \
+ ((ch) == 1) ? 0x24 : ( \
+ ((ch) == 2) ? 0x40 : ( \
+ ((ch) == 5) ? 0x64 : ( \
+ ((ch) == 6) ? 0x80 : ( \
+ ((ch) == 8) ? 0x9C : ( \
+ ((ch) == 9) ? 0xBC : (-1))))))))
+#define DC_RL_CH(ch, evt) IPU_DC_REG(_RL_CH_2_OFFSET(ch) + \
+ ((evt) & ~0x1) * 2)
+
+#define DC_EVT_NF 0
+#define DC_EVT_NL 1
+#define DC_EVT_EOF 2
+#define DC_EVT_NFIELD 3
+#define DC_EVT_EOL 4
+#define DC_EVT_EOFIELD 5
+#define DC_EVT_NEW_ADDR 6
+#define DC_EVT_NEW_CHAN 7
+#define DC_EVT_NEW_DATA 8
+
+#define DC_EVT_NEW_ADDR_W_0 0
+#define DC_EVT_NEW_ADDR_W_1 1
+#define DC_EVT_NEW_CHAN_W_0 2
+#define DC_EVT_NEW_CHAN_W_1 3
+#define DC_EVT_NEW_DATA_W_0 4
+#define DC_EVT_NEW_DATA_W_1 5
+#define DC_EVT_NEW_ADDR_R_0 6
+#define DC_EVT_NEW_ADDR_R_1 7
+#define DC_EVT_NEW_CHAN_R_0 8
+#define DC_EVT_NEW_CHAN_R_1 9
+#define DC_EVT_NEW_DATA_R_0 10
+#define DC_EVT_NEW_DATA_R_1 11
+#define DC_EVEN_UGDE0 12
+#define DC_ODD_UGDE0 13
+#define DC_EVEN_UGDE1 14
+#define DC_ODD_UGDE1 15
+#define DC_EVEN_UGDE2 16
+#define DC_ODD_UGDE2 17
+#define DC_EVEN_UGDE3 18
+#define DC_ODD_UGDE3 19
+
+#define dc_ch_offset(ch) \
+({ \
+ const u8 _offset[] = { \
+ 0, 0x1C, 0x38, 0x54, 0x58, 0x5C, 0x78, 0, 0x94, 0xB4}; \
+ _offset[ch]; \
+})
+#define DC_WR_CH_CONF(ch) IPU_DC_REG(dc_ch_offset(ch))
+#define DC_WR_CH_ADDR(ch) IPU_DC_REG(dc_ch_offset(ch) + 4)
+
+#define DC_WR_CH_CONF_1 IPU_DC_REG(0x001C)
+#define DC_WR_CH_ADDR_1 IPU_DC_REG(0x0020)
+#define DC_WR_CH_CONF_5 IPU_DC_REG(0x005C)
+#define DC_WR_CH_ADDR_5 IPU_DC_REG(0x0060)
+#define DC_GEN IPU_DC_REG(0x00D4)
+#define DC_DISP_CONF1(disp) IPU_DC_REG(0x00D8 + 4 * (disp))
+#define DC_DISP_CONF2(disp) IPU_DC_REG(0x00E8 + 4 * (disp))
+#define DC_STAT IPU_DC_REG(0x01C8)
+#define DC_UGDE_0(evt) IPU_DC_REG(0x0174 + 16 * (evt))
+#define DC_UGDE_1(evt) IPU_DC_REG(0x0178 + 16 * (evt))
+#define DC_UGDE_2(evt) IPU_DC_REG(0x017C + 16 * (evt))
+#define DC_UGDE_3(evt) IPU_DC_REG(0x0180 + 16 * (evt))
+
+/* IPU DP Registers */
+#define IPU_DP_REG(offset) (offset)
+
+#define DP_SYNC 0
+#define DP_ASYNC0 0x60
+#define DP_ASYNC1 0xBC
+#define DP_COM_CONF(flow) IPU_DP_REG(flow)
+#define DP_GRAPH_WIND_CTRL(flow) IPU_DP_REG(0x0004 + (flow))
+#define DP_FG_POS(flow) IPU_DP_REG(0x0008 + (flow))
+#define DP_GAMMA_C(flow, i) IPU_DP_REG(0x0014 + (flow) + 4 * (i))
+#define DP_GAMMA_S(flow, i) IPU_DP_REG(0x0034 + (flow) + 4 * (i))
+#define DP_CSC_A_0(flow) IPU_DP_REG(0x0044 + (flow))
+#define DP_CSC_A_1(flow) IPU_DP_REG(0x0048 + (flow))
+#define DP_CSC_A_2(flow) IPU_DP_REG(0x004C + (flow))
+#define DP_CSC_A_3(flow) IPU_DP_REG(0x0050 + (flow))
+#define DP_CSC_0(flow) IPU_DP_REG(0x0054 + (flow))
+#define DP_CSC_1(flow) IPU_DP_REG(0x0058 + (flow))
+
+enum {
+ IPU_CONF_CSI0_EN = 0x00000001,
+ IPU_CONF_CSI1_EN = 0x00000002,
+ IPU_CONF_IC_EN = 0x00000004,
+ IPU_CONF_ROT_EN = 0x00000008,
+ IPU_CONF_ISP_EN = 0x00000010,
+ IPU_CONF_DP_EN = 0x00000020,
+ IPU_CONF_DI0_EN = 0x00000040,
+ IPU_CONF_DI1_EN = 0x00000080,
+ IPU_CONF_DMFC_EN = 0x00000400,
+ IPU_CONF_SMFC_EN = 0x00000100,
+ IPU_CONF_DC_EN = 0x00000200,
+ IPU_CONF_VDI_EN = 0x00001000,
+ IPU_CONF_IDMAC_DIS = 0x00400000,
+ IPU_CONF_IC_DMFC_SEL = 0x02000000,
+ IPU_CONF_IC_DMFC_SYNC = 0x04000000,
+ IPU_CONF_VDI_DMFC_SYNC = 0x08000000,
+ IPU_CONF_CSI0_DATA_SOURCE = 0x10000000,
+ IPU_CONF_CSI0_DATA_SOURCE_OFFSET = 28,
+ IPU_CONF_CSI1_DATA_SOURCE = 0x20000000,
+ IPU_CONF_IC_INPUT = 0x40000000,
+ IPU_CONF_CSI_SEL = 0x80000000,
+
+ DI0_COUNTER_RELEASE = 0x01000000,
+ DI1_COUNTER_RELEASE = 0x02000000,
+
+ FS_PRPVF_ROT_SRC_SEL_MASK = 0x00000F00,
+ FS_PRPVF_ROT_SRC_SEL_OFFSET = 8,
+ FS_PRPENC_ROT_SRC_SEL_MASK = 0x0000000F,
+ FS_PRPENC_ROT_SRC_SEL_OFFSET = 0,
+ FS_PP_ROT_SRC_SEL_MASK = 0x000F0000,
+ FS_PP_ROT_SRC_SEL_OFFSET = 16,
+ FS_PP_SRC_SEL_MASK = 0x0000F000,
+ FS_PP_SRC_SEL_VDOA = 0x00008000,
+ FS_PP_SRC_SEL_OFFSET = 12,
+ FS_PRP_SRC_SEL_MASK = 0x0F000000,
+ FS_PRP_SRC_SEL_OFFSET = 24,
+ FS_VF_IN_VALID = 0x80000000,
+ FS_ENC_IN_VALID = 0x40000000,
+ FS_VDI_SRC_SEL_MASK = 0x30000000,
+ FS_VDI_SRC_SEL_VDOA = 0x20000000,
+ FS_VDOA_DEST_SEL_MASK = 0x00030000,
+ FS_VDOA_DEST_SEL_VDI = 0x00020000,
+ FS_VDOA_DEST_SEL_IC = 0x00010000,
+ FS_VDI_SRC_SEL_OFFSET = 28,
+
+
+ FS_PRPENC_DEST_SEL_MASK = 0x0000000F,
+ FS_PRPENC_DEST_SEL_OFFSET = 0,
+ FS_PRPVF_DEST_SEL_MASK = 0x000000F0,
+ FS_PRPVF_DEST_SEL_OFFSET = 4,
+ FS_PRPVF_ROT_DEST_SEL_MASK = 0x00000F00,
+ FS_PRPVF_ROT_DEST_SEL_OFFSET = 8,
+ FS_PP_DEST_SEL_MASK = 0x0000F000,
+ FS_PP_DEST_SEL_OFFSET = 12,
+ FS_PP_ROT_DEST_SEL_MASK = 0x000F0000,
+ FS_PP_ROT_DEST_SEL_OFFSET = 16,
+ FS_PRPENC_ROT_DEST_SEL_MASK = 0x00F00000,
+ FS_PRPENC_ROT_DEST_SEL_OFFSET = 20,
+
+ FS_SMFC0_DEST_SEL_MASK = 0x0000000F,
+ FS_SMFC0_DEST_SEL_OFFSET = 0,
+ FS_SMFC1_DEST_SEL_MASK = 0x00000070,
+ FS_SMFC1_DEST_SEL_OFFSET = 4,
+ FS_SMFC2_DEST_SEL_MASK = 0x00000780,
+ FS_SMFC2_DEST_SEL_OFFSET = 7,
+ FS_SMFC3_DEST_SEL_MASK = 0x00003800,
+ FS_SMFC3_DEST_SEL_OFFSET = 11,
+
+ FS_DC1_SRC_SEL_MASK = 0x00F00000,
+ FS_DC1_SRC_SEL_OFFSET = 20,
+ FS_DC2_SRC_SEL_MASK = 0x000F0000,
+ FS_DC2_SRC_SEL_OFFSET = 16,
+ FS_DP_SYNC0_SRC_SEL_MASK = 0x0000000F,
+ FS_DP_SYNC0_SRC_SEL_OFFSET = 0,
+ FS_DP_SYNC1_SRC_SEL_MASK = 0x000000F0,
+ FS_DP_SYNC1_SRC_SEL_OFFSET = 4,
+ FS_DP_ASYNC0_SRC_SEL_MASK = 0x00000F00,
+ FS_DP_ASYNC0_SRC_SEL_OFFSET = 8,
+ FS_DP_ASYNC1_SRC_SEL_MASK = 0x0000F000,
+ FS_DP_ASYNC1_SRC_SEL_OFFSET = 12,
+
+ FS_AUTO_REF_PER_MASK = 0,
+ FS_AUTO_REF_PER_OFFSET = 16,
+
+ TSTAT_VF_MASK = 0x0000000C,
+ TSTAT_VF_OFFSET = 2,
+ TSTAT_VF_ROT_MASK = 0x00000300,
+ TSTAT_VF_ROT_OFFSET = 8,
+ TSTAT_ENC_MASK = 0x00000003,
+ TSTAT_ENC_OFFSET = 0,
+ TSTAT_ENC_ROT_MASK = 0x000000C0,
+ TSTAT_ENC_ROT_OFFSET = 6,
+ TSTAT_PP_MASK = 0x00000030,
+ TSTAT_PP_OFFSET = 4,
+ TSTAT_PP_ROT_MASK = 0x00000C00,
+ TSTAT_PP_ROT_OFFSET = 10,
+
+ TASK_STAT_IDLE = 0,
+ TASK_STAT_ACTIVE = 1,
+ TASK_STAT_WAIT4READY = 2,
+
+ /* IDMAC register bits */
+ IDMAC_CONF_USED_BUFS_EN_R = 0x02000000,
+ IDMAC_CONF_USED_BUFS_MAX_R_MASK = 0x01E00000,
+ IDMAC_CONF_USED_BUFS_MAX_R_OFFSET = 21,
+ IDMAC_CONF_USED_BUFS_EN_W = 0x00100000,
+ IDMAC_CONF_USED_BUFS_MAX_W_MASK = 0x000E0000,
+ IDMAC_CONF_USED_BUFS_MAX_W_OFFSET = 17,
+
+ /* Image Converter Register bits */
+ IC_CONF_PRPENC_EN = 0x00000001,
+ IC_CONF_PRPENC_CSC1 = 0x00000002,
+ IC_CONF_PRPENC_ROT_EN = 0x00000004,
+ IC_CONF_PRPVF_EN = 0x00000100,
+ IC_CONF_PRPVF_CSC1 = 0x00000200,
+ IC_CONF_PRPVF_CSC2 = 0x00000400,
+ IC_CONF_PRPVF_CMB = 0x00000800,
+ IC_CONF_PRPVF_ROT_EN = 0x00001000,
+ IC_CONF_PP_EN = 0x00010000,
+ IC_CONF_PP_CSC1 = 0x00020000,
+ IC_CONF_PP_CSC2 = 0x00040000,
+ IC_CONF_PP_CMB = 0x00080000,
+ IC_CONF_PP_ROT_EN = 0x00100000,
+ IC_CONF_IC_GLB_LOC_A = 0x10000000,
+ IC_CONF_KEY_COLOR_EN = 0x20000000,
+ IC_CONF_RWS_EN = 0x40000000,
+ IC_CONF_CSI_MEM_WR_EN = 0x80000000,
+
+ IC_RSZ_MAX_RESIZE_RATIO = 0x00004000,
+
+ IC_IDMAC_1_CB0_BURST_16 = 0x00000001,
+ IC_IDMAC_1_CB1_BURST_16 = 0x00000002,
+ IC_IDMAC_1_CB2_BURST_16 = 0x00000004,
+ IC_IDMAC_1_CB3_BURST_16 = 0x00000008,
+ IC_IDMAC_1_CB4_BURST_16 = 0x00000010,
+ IC_IDMAC_1_CB5_BURST_16 = 0x00000020,
+ IC_IDMAC_1_CB6_BURST_16 = 0x00000040,
+ IC_IDMAC_1_CB7_BURST_16 = 0x00000080,
+ IC_IDMAC_1_PRPENC_ROT_MASK = 0x00003800,
+ IC_IDMAC_1_PRPENC_ROT_OFFSET = 11,
+ IC_IDMAC_1_PRPVF_ROT_MASK = 0x0001C000,
+ IC_IDMAC_1_PRPVF_ROT_OFFSET = 14,
+ IC_IDMAC_1_PP_ROT_MASK = 0x000E0000,
+ IC_IDMAC_1_PP_ROT_OFFSET = 17,
+ IC_IDMAC_1_PP_FLIP_RS = 0x00400000,
+ IC_IDMAC_1_PRPVF_FLIP_RS = 0x00200000,
+ IC_IDMAC_1_PRPENC_FLIP_RS = 0x00100000,
+
+ IC_IDMAC_2_PRPENC_HEIGHT_MASK = 0x000003FF,
+ IC_IDMAC_2_PRPENC_HEIGHT_OFFSET = 0,
+ IC_IDMAC_2_PRPVF_HEIGHT_MASK = 0x000FFC00,
+ IC_IDMAC_2_PRPVF_HEIGHT_OFFSET = 10,
+ IC_IDMAC_2_PP_HEIGHT_MASK = 0x3FF00000,
+ IC_IDMAC_2_PP_HEIGHT_OFFSET = 20,
+
+ IC_IDMAC_3_PRPENC_WIDTH_MASK = 0x000003FF,
+ IC_IDMAC_3_PRPENC_WIDTH_OFFSET = 0,
+ IC_IDMAC_3_PRPVF_WIDTH_MASK = 0x000FFC00,
+ IC_IDMAC_3_PRPVF_WIDTH_OFFSET = 10,
+ IC_IDMAC_3_PP_WIDTH_MASK = 0x3FF00000,
+ IC_IDMAC_3_PP_WIDTH_OFFSET = 20,
+
+ CSI_SENS_CONF_DATA_FMT_SHIFT = 8,
+ CSI_SENS_CONF_DATA_FMT_MASK = 0x00000700,
+ CSI_SENS_CONF_DATA_FMT_RGB_YUV444 = 0L,
+ CSI_SENS_CONF_DATA_FMT_YUV422_YUYV = 1L,
+ CSI_SENS_CONF_DATA_FMT_YUV422_UYVY = 2L,
+ CSI_SENS_CONF_DATA_FMT_BAYER = 3L,
+ CSI_SENS_CONF_DATA_FMT_RGB565 = 4L,
+ CSI_SENS_CONF_DATA_FMT_RGB555 = 5L,
+ CSI_SENS_CONF_DATA_FMT_RGB444 = 6L,
+ CSI_SENS_CONF_DATA_FMT_JPEG = 7L,
+
+ CSI_SENS_CONF_VSYNC_POL_SHIFT = 0,
+ CSI_SENS_CONF_HSYNC_POL_SHIFT = 1,
+ CSI_SENS_CONF_DATA_POL_SHIFT = 2,
+ CSI_SENS_CONF_PIX_CLK_POL_SHIFT = 3,
+ CSI_SENS_CONF_SENS_PRTCL_MASK = 0x00000070L,
+ CSI_SENS_CONF_SENS_PRTCL_SHIFT = 4,
+ CSI_SENS_CONF_PACK_TIGHT_SHIFT = 7,
+ CSI_SENS_CONF_DATA_WIDTH_SHIFT = 11,
+ CSI_SENS_CONF_EXT_VSYNC_SHIFT = 15,
+ CSI_SENS_CONF_DIVRATIO_SHIFT = 16,
+
+ CSI_SENS_CONF_DIVRATIO_MASK = 0x00FF0000L,
+ CSI_SENS_CONF_DATA_DEST_SHIFT = 24,
+ CSI_SENS_CONF_DATA_DEST_MASK = 0x07000000L,
+ CSI_SENS_CONF_JPEG8_EN_SHIFT = 27,
+ CSI_SENS_CONF_JPEG_EN_SHIFT = 28,
+ CSI_SENS_CONF_FORCE_EOF_SHIFT = 29,
+ CSI_SENS_CONF_DATA_EN_POL_SHIFT = 31,
+
+ CSI_DATA_DEST_ISP = 1L,
+ CSI_DATA_DEST_IC = 2L,
+ CSI_DATA_DEST_IDMAC = 4L,
+
+ CSI_CCIR_ERR_DET_EN = 0x01000000L,
+ CSI_HORI_DOWNSIZE_EN = 0x80000000L,
+ CSI_VERT_DOWNSIZE_EN = 0x40000000L,
+ CSI_TEST_GEN_MODE_EN = 0x01000000L,
+
+ CSI_HSC_MASK = 0x1FFF0000,
+ CSI_HSC_SHIFT = 16,
+ CSI_VSC_MASK = 0x00000FFF,
+ CSI_VSC_SHIFT = 0,
+
+ CSI_TEST_GEN_R_MASK = 0x000000FFL,
+ CSI_TEST_GEN_R_SHIFT = 0,
+ CSI_TEST_GEN_G_MASK = 0x0000FF00L,
+ CSI_TEST_GEN_G_SHIFT = 8,
+ CSI_TEST_GEN_B_MASK = 0x00FF0000L,
+ CSI_TEST_GEN_B_SHIFT = 16,
+
+ CSI_MIPI_DI0_MASK = 0x000000FFL,
+ CSI_MIPI_DI0_SHIFT = 0,
+ CSI_MIPI_DI1_MASK = 0x0000FF00L,
+ CSI_MIPI_DI1_SHIFT = 8,
+ CSI_MIPI_DI2_MASK = 0x00FF0000L,
+ CSI_MIPI_DI2_SHIFT = 16,
+ CSI_MIPI_DI3_MASK = 0xFF000000L,
+ CSI_MIPI_DI3_SHIFT = 24,
+
+ CSI_MAX_RATIO_SKIP_ISP_MASK = 0x00070000L,
+ CSI_MAX_RATIO_SKIP_ISP_SHIFT = 16,
+ CSI_SKIP_ISP_MASK = 0x00F80000L,
+ CSI_SKIP_ISP_SHIFT = 19,
+ CSI_MAX_RATIO_SKIP_SMFC_MASK = 0x00000007L,
+ CSI_MAX_RATIO_SKIP_SMFC_SHIFT = 0,
+ CSI_SKIP_SMFC_MASK = 0x000000F8L,
+ CSI_SKIP_SMFC_SHIFT = 3,
+ CSI_ID_2_SKIP_MASK = 0x00000300L,
+ CSI_ID_2_SKIP_SHIFT = 8,
+
+ CSI_COLOR_FIRST_ROW_MASK = 0x00000002L,
+ CSI_COLOR_FIRST_COMP_MASK = 0x00000001L,
+
+ SMFC_MAP_CH0_MASK = 0x00000007L,
+ SMFC_MAP_CH0_SHIFT = 0,
+ SMFC_MAP_CH1_MASK = 0x00000038L,
+ SMFC_MAP_CH1_SHIFT = 3,
+ SMFC_MAP_CH2_MASK = 0x000001C0L,
+ SMFC_MAP_CH2_SHIFT = 6,
+ SMFC_MAP_CH3_MASK = 0x00000E00L,
+ SMFC_MAP_CH3_SHIFT = 9,
+
+ SMFC_WM0_SET_MASK = 0x00000007L,
+ SMFC_WM0_SET_SHIFT = 0,
+ SMFC_WM1_SET_MASK = 0x000001C0L,
+ SMFC_WM1_SET_SHIFT = 6,
+ SMFC_WM2_SET_MASK = 0x00070000L,
+ SMFC_WM2_SET_SHIFT = 16,
+ SMFC_WM3_SET_MASK = 0x01C00000L,
+ SMFC_WM3_SET_SHIFT = 22,
+
+ SMFC_WM0_CLR_MASK = 0x00000038L,
+ SMFC_WM0_CLR_SHIFT = 3,
+ SMFC_WM1_CLR_MASK = 0x00000E00L,
+ SMFC_WM1_CLR_SHIFT = 9,
+ SMFC_WM2_CLR_MASK = 0x00380000L,
+ SMFC_WM2_CLR_SHIFT = 19,
+ SMFC_WM3_CLR_MASK = 0x0E000000L,
+ SMFC_WM3_CLR_SHIFT = 25,
+
+ SMFC_BS0_MASK = 0x0000000FL,
+ SMFC_BS0_SHIFT = 0,
+ SMFC_BS1_MASK = 0x000000F0L,
+ SMFC_BS1_SHIFT = 4,
+ SMFC_BS2_MASK = 0x00000F00L,
+ SMFC_BS2_SHIFT = 8,
+ SMFC_BS3_MASK = 0x0000F000L,
+ SMFC_BS3_SHIFT = 12,
+
+ PF_CONF_TYPE_MASK = 0x00000007,
+ PF_CONF_TYPE_SHIFT = 0,
+ PF_CONF_PAUSE_EN = 0x00000010,
+ PF_CONF_RESET = 0x00008000,
+ PF_CONF_PAUSE_ROW_MASK = 0x00FF0000,
+ PF_CONF_PAUSE_ROW_SHIFT = 16,
+
+ DI_DW_GEN_ACCESS_SIZE_OFFSET = 24,
+ DI_DW_GEN_COMPONENT_SIZE_OFFSET = 16,
+
+ DI_GEN_DI_CLK_EXT = 0x100000,
+ DI_GEN_POLARITY_DISP_CLK = 0x00020000,
+ DI_GEN_POLARITY_1 = 0x00000001,
+ DI_GEN_POLARITY_2 = 0x00000002,
+ DI_GEN_POLARITY_3 = 0x00000004,
+ DI_GEN_POLARITY_4 = 0x00000008,
+ DI_GEN_POLARITY_5 = 0x00000010,
+ DI_GEN_POLARITY_6 = 0x00000020,
+ DI_GEN_POLARITY_7 = 0x00000040,
+ DI_GEN_POLARITY_8 = 0x00000080,
+
+ DI_POL_DRDY_DATA_POLARITY = 0x00000080,
+ DI_POL_DRDY_POLARITY_15 = 0x00000010,
+
+ DI_VSYNC_SEL_OFFSET = 13,
+
+ DC_WR_CH_CONF_FIELD_MODE = 0x00000200,
+ DC_WR_CH_CONF_PROG_TYPE_OFFSET = 5,
+ DC_WR_CH_CONF_PROG_TYPE_MASK = 0x000000E0,
+ DC_WR_CH_CONF_PROG_DI_ID = 0x00000004,
+ DC_WR_CH_CONF_PROG_DISP_ID_OFFSET = 3,
+ DC_WR_CH_CONF_PROG_DISP_ID_MASK = 0x00000018,
+
+ DC_UGDE_0_ODD_EN = 0x02000000,
+ DC_UGDE_0_ID_CODED_MASK = 0x00000007,
+ DC_UGDE_0_ID_CODED_OFFSET = 0,
+ DC_UGDE_0_EV_PRIORITY_MASK = 0x00000078,
+ DC_UGDE_0_EV_PRIORITY_OFFSET = 3,
+
+ DP_COM_CONF_FG_EN = 0x00000001,
+ DP_COM_CONF_GWSEL = 0x00000002,
+ DP_COM_CONF_GWAM = 0x00000004,
+ DP_COM_CONF_GWCKE = 0x00000008,
+ DP_COM_CONF_CSC_DEF_MASK = 0x00000300,
+ DP_COM_CONF_CSC_DEF_OFFSET = 8,
+ DP_COM_CONF_CSC_DEF_FG = 0x00000300,
+ DP_COM_CONF_CSC_DEF_BG = 0x00000200,
+ DP_COM_CONF_CSC_DEF_BOTH = 0x00000100,
+ DP_COM_CONF_GAMMA_EN = 0x00001000,
+ DP_COM_CONF_GAMMA_YUV_EN = 0x00002000,
+
+ DI_SER_CONF_LLA_SER_ACCESS = 0x00000020,
+ DI_SER_CONF_SERIAL_CLK_POL = 0x00000010,
+ DI_SER_CONF_SERIAL_DATA_POL = 0x00000008,
+ DI_SER_CONF_SERIAL_RS_POL = 0x00000004,
+ DI_SER_CONF_SERIAL_CS_POL = 0x00000002,
+ DI_SER_CONF_WAIT4SERIAL = 0x00000001,
+
+ VDI_C_CH_420 = 0x00000000,
+ VDI_C_CH_422 = 0x00000002,
+ VDI_C_MOT_SEL_FULL = 0x00000008,
+ VDI_C_MOT_SEL_LOW = 0x00000004,
+ VDI_C_MOT_SEL_MED = 0x00000000,
+ VDI_C_BURST_SIZE1_4 = 0x00000030,
+ VDI_C_BURST_SIZE2_4 = 0x00000300,
+ VDI_C_BURST_SIZE3_4 = 0x00003000,
+ VDI_C_BURST_SIZE_MASK = 0xF,
+ VDI_C_BURST_SIZE1_OFFSET = 4,
+ VDI_C_BURST_SIZE2_OFFSET = 8,
+ VDI_C_BURST_SIZE3_OFFSET = 12,
+ VDI_C_VWM1_SET_1 = 0x00000000,
+ VDI_C_VWM1_SET_2 = 0x00010000,
+ VDI_C_VWM1_CLR_2 = 0x00080000,
+ VDI_C_VWM3_SET_1 = 0x00000000,
+ VDI_C_VWM3_SET_2 = 0x00400000,
+ VDI_C_VWM3_CLR_2 = 0x02000000,
+ VDI_C_TOP_FIELD_MAN_1 = 0x40000000,
+ VDI_C_TOP_FIELD_AUTO_1 = 0x80000000,
+};
+
+enum di_pins {
+ DI_PIN11 = 0,
+ DI_PIN12 = 1,
+ DI_PIN13 = 2,
+ DI_PIN14 = 3,
+ DI_PIN15 = 4,
+ DI_PIN16 = 5,
+ DI_PIN17 = 6,
+ DI_PIN_CS = 7,
+
+ DI_PIN_SER_CLK = 0,
+ DI_PIN_SER_RS = 1,
+};
+
+enum di_sync_wave {
+ DI_SYNC_NONE = -1,
+ DI_SYNC_CLK = 0,
+ DI_SYNC_INT_HSYNC = 1,
+ DI_SYNC_HSYNC = 2,
+ DI_SYNC_VSYNC = 3,
+ DI_SYNC_DE = 5,
+};
+
+/* DC template opcodes */
+#define WROD(lf) (0x18 | ((lf) << 1))
+#define WRG (0x01)
+
+#endif
diff --git a/drivers/mxc/ipu3/pre-regs.h b/drivers/mxc/ipu3/pre-regs.h
new file mode 100644
index 000000000000..06a9b029ce3e
--- /dev/null
+++ b/drivers/mxc/ipu3/pre-regs.h
@@ -0,0 +1,480 @@
+/*
+ * Freescale PRE Register Definitions
+ *
+ * Copyright 2014-2015 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
+ */
+
+#ifndef __ARCH_ARM___PRE_H
+#define __ARCH_ARM___PRE_H
+
+
+#define HW_PRE_CTRL (0x00000000)
+#define HW_PRE_CTRL_SET (0x00000004)
+#define HW_PRE_CTRL_CLR (0x00000008)
+#define HW_PRE_CTRL_TOG (0x0000000c)
+
+#define BM_PRE_CTRL_SFTRST 0x80000000
+#define BF_PRE_CTRL_SFTRST(v) \
+ (((v) << 31) & BM_PRE_CTRL_SFTRST)
+#define BM_PRE_CTRL_CLKGATE 0x40000000
+#define BF_PRE_CTRL_CLKGATE(v) \
+ (((v) << 30) & BM_PRE_CTRL_CLKGATE)
+#define BM_PRE_CTRL_TPR_RESET_SEL 0x20000000
+#define BF_PRE_CTRL_TPR_RESET_SEL(v) \
+ (((v) << 29) & BM_PRE_CTRL_TPR_RESET_SEL)
+#define BM_PRE_CTRL_EN_REPEAT 0x10000000
+#define BF_PRE_CTRL_EN_REPEAT(v) \
+ (((v) << 28) & BM_PRE_CTRL_EN_REPEAT)
+#define BP_PRE_CTRL_RSVD2 16
+#define BM_PRE_CTRL_RSVD2 0x0FFF0000
+#define BF_PRE_CTRL_RSVD2(v) \
+ (((v) << 16) & BM_PRE_CTRL_RSVD2)
+#define BP_PRE_CTRL_RSVD1 12
+#define BM_PRE_CTRL_RSVD1 0x0000F000
+#define BF_PRE_CTRL_RSVD1(v) \
+ (((v) << 12) & BM_PRE_CTRL_RSVD1)
+#define BM_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN 0x00000800
+#define BF_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN(v) \
+ (((v) << 11) & BM_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN)
+#define BV_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN__0 0x0
+#define BV_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN__1 0x1
+#define BP_PRE_CTRL_HANDSHAKE_LINE_NUM 9
+#define BM_PRE_CTRL_HANDSHAKE_LINE_NUM 0x00000600
+#define BF_PRE_CTRL_HANDSHAKE_LINE_NUM(v) \
+ (((v) << 9) & BM_PRE_CTRL_HANDSHAKE_LINE_NUM)
+#define BV_PRE_CTRL_HANDSHAKE_LINE_NUM__0 0x0
+#define BV_PRE_CTRL_HANDSHAKE_LINE_NUM__1 0x1
+#define BV_PRE_CTRL_HANDSHAKE_LINE_NUM__2 0x2
+#define BM_PRE_CTRL_HANDSHAKE_EN 0x00000100
+#define BF_PRE_CTRL_HANDSHAKE_EN(v) \
+ (((v) << 8) & BM_PRE_CTRL_HANDSHAKE_EN)
+#define BV_PRE_CTRL_HANDSHAKE_EN__0 0x0
+#define BV_PRE_CTRL_HANDSHAKE_EN__1 0x1
+#define BM_PRE_CTRL_INTERLACED_FIELD 0x00000080
+#define BF_PRE_CTRL_INTERLACED_FIELD(v) \
+ (((v) << 7) & BM_PRE_CTRL_INTERLACED_FIELD)
+#define BM_PRE_CTRL_SO 0x00000040
+#define BF_PRE_CTRL_SO(v) \
+ (((v) << 6) & BM_PRE_CTRL_SO)
+#define BM_PRE_CTRL_VFLIP 0x00000020
+#define BF_PRE_CTRL_VFLIP(v) \
+ (((v) << 5) & BM_PRE_CTRL_VFLIP)
+#define BM_PRE_CTRL_SDW_UPDATE 0x00000010
+#define BF_PRE_CTRL_SDW_UPDATE(v) \
+ (((v) << 4) & BM_PRE_CTRL_SDW_UPDATE)
+#define BM_PRE_CTRL_RSVD0 0x00000008
+#define BF_PRE_CTRL_RSVD0(v) \
+ (((v) << 3) & BM_PRE_CTRL_RSVD0)
+#define BM_PRE_CTRL_BLOCK_16 0x00000004
+#define BF_PRE_CTRL_BLOCK_16(v) \
+ (((v) << 2) & BM_PRE_CTRL_BLOCK_16)
+#define BV_PRE_CTRL_BLOCK_16__32x4 0x0
+#define BV_PRE_CTRL_BLOCK_16__16x4 0x1
+#define BM_PRE_CTRL_BLOCK_EN 0x00000002
+#define BF_PRE_CTRL_BLOCK_EN(v) \
+ (((v) << 1) & BM_PRE_CTRL_BLOCK_EN)
+#define BV_PRE_CTRL_BLOCK_EN__0 0x0
+#define BV_PRE_CTRL_BLOCK_EN__1 0x1
+#define BM_PRE_CTRL_ENABLE 0x00000001
+#define BF_PRE_CTRL_ENABLE(v) \
+ (((v) << 0) & BM_PRE_CTRL_ENABLE)
+
+#define HW_PRE_IRQ_MASK (0x00000010)
+#define HW_PRE_IRQ_MASK_SET (0x00000014)
+#define HW_PRE_IRQ_MASK_CLR (0x00000018)
+#define HW_PRE_IRQ_MASK_TOG (0x0000001c)
+
+#define BP_PRE_IRQ_MASK_RSVD1 4
+#define BM_PRE_IRQ_MASK_RSVD1 0xFFFFFFF0
+#define BF_PRE_IRQ_MASK_RSVD1(v) \
+ (((v) << 4) & BM_PRE_IRQ_MASK_RSVD1)
+#define BM_PRE_IRQ_MASK_TPR_RD_NUM_BYTES_OVFL_IRQ_EN 0x00000008
+#define BF_PRE_IRQ_MASK_TPR_RD_NUM_BYTES_OVFL_IRQ_EN(v) \
+ (((v) << 3) & BM_PRE_IRQ_MASK_TPR_RD_NUM_BYTES_OVFL_IRQ_EN)
+#define BM_PRE_IRQ_MASK_HANDSHAKE_ABORT_IRQ_EN 0x00000004
+#define BF_PRE_IRQ_MASK_HANDSHAKE_ABORT_IRQ_EN(v) \
+ (((v) << 2) & BM_PRE_IRQ_MASK_HANDSHAKE_ABORT_IRQ_EN)
+#define BM_PRE_IRQ_MASK_STORE_IRQ_EN 0x00000002
+#define BF_PRE_IRQ_MASK_STORE_IRQ_EN(v) \
+ (((v) << 1) & BM_PRE_IRQ_MASK_STORE_IRQ_EN)
+#define BM_PRE_IRQ_MASK_PREFETCH_IRQ_EN 0x00000001
+#define BF_PRE_IRQ_MASK_PREFETCH_IRQ_EN(v) \
+ (((v) << 0) & BM_PRE_IRQ_MASK_PREFETCH_IRQ_EN)
+
+#define HW_PRE_IRQ (0x00000020)
+#define HW_PRE_IRQ_SET (0x00000024)
+#define HW_PRE_IRQ_CLR (0x00000028)
+#define HW_PRE_IRQ_TOG (0x0000002c)
+
+#define BP_PRE_IRQ_RSVD1 14
+#define BM_PRE_IRQ_RSVD1 0xFFFFC000
+#define BF_PRE_IRQ_RSVD1(v) \
+ (((v) << 14) & BM_PRE_IRQ_RSVD1)
+#define BP_PRE_IRQ_AXI_ERROR_ID 10
+#define BM_PRE_IRQ_AXI_ERROR_ID 0x00003C00
+#define BF_PRE_IRQ_AXI_ERROR_ID(v) \
+ (((v) << 10) & BM_PRE_IRQ_AXI_ERROR_ID)
+#define BM_PRE_IRQ_AXI_READ_ERROR 0x00000200
+#define BF_PRE_IRQ_AXI_READ_ERROR(v) \
+ (((v) << 9) & BM_PRE_IRQ_AXI_READ_ERROR)
+#define BM_PRE_IRQ_AXI_WRITE_ERROR 0x00000100
+#define BF_PRE_IRQ_AXI_WRITE_ERROR(v) \
+ (((v) << 8) & BM_PRE_IRQ_AXI_WRITE_ERROR)
+#define BP_PRE_IRQ_RSVD0 5
+#define BM_PRE_IRQ_RSVD0 0x000000E0
+#define BF_PRE_IRQ_RSVD0(v) \
+ (((v) << 5) & BM_PRE_IRQ_RSVD0)
+#define BM_PRE_IRQ_HANDSHAKE_ERROR_IRQ 0x00000010
+#define BF_PRE_IRQ_HANDSHAKE_ERROR_IRQ(v) \
+ (((v) << 4) & BM_PRE_IRQ_HANDSHAKE_ERROR_IRQ)
+#define BM_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ 0x00000008
+#define BF_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ(v) \
+ (((v) << 3) & BM_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ)
+#define BM_PRE_IRQ_HANDSHAKE_ABORT_IRQ 0x00000004
+#define BF_PRE_IRQ_HANDSHAKE_ABORT_IRQ(v) \
+ (((v) << 2) & BM_PRE_IRQ_HANDSHAKE_ABORT_IRQ)
+#define BM_PRE_IRQ_STORE_IRQ 0x00000002
+#define BF_PRE_IRQ_STORE_IRQ(v) \
+ (((v) << 1) & BM_PRE_IRQ_STORE_IRQ)
+#define BM_PRE_IRQ_PREFETCH_IRQ 0x00000001
+#define BF_PRE_IRQ_PREFETCH_IRQ(v) \
+ (((v) << 0) & BM_PRE_IRQ_PREFETCH_IRQ)
+
+#define HW_PRE_CUR_BUF (0x00000030)
+
+#define BP_PRE_CUR_BUF_ADDR 0
+#define BM_PRE_CUR_BUF_ADDR 0xFFFFFFFF
+#define BF_PRE_CUR_BUF_ADDR(v) (v)
+
+#define HW_PRE_NEXT_BUF (0x00000040)
+
+#define BP_PRE_NEXT_BUF_ADDR 0
+#define BM_PRE_NEXT_BUF_ADDR 0xFFFFFFFF
+#define BF_PRE_NEXT_BUF_ADDR(v) (v)
+
+#define HW_PRE_U_BUF_OFFSET (0x00000050)
+
+#define BP_PRE_U_BUF_OFFSET_RSVD0 25
+#define BM_PRE_U_BUF_OFFSET_RSVD0 0xFE000000
+#define BF_PRE_U_BUF_OFFSET_RSVD0(v) \
+ (((v) << 25) & BM_PRE_U_BUF_OFFSET_RSVD0)
+#define BP_PRE_U_BUF_OFFSET_UBO 0
+#define BM_PRE_U_BUF_OFFSET_UBO 0x01FFFFFF
+#define BF_PRE_U_BUF_OFFSET_UBO(v) \
+ (((v) << 0) & BM_PRE_U_BUF_OFFSET_UBO)
+
+#define HW_PRE_V_BUF_OFFSET (0x00000060)
+
+#define BP_PRE_V_BUF_OFFSET_RSVD0 25
+#define BM_PRE_V_BUF_OFFSET_RSVD0 0xFE000000
+#define BF_PRE_V_BUF_OFFSET_RSVD0(v) \
+ (((v) << 25) & BM_PRE_V_BUF_OFFSET_RSVD0)
+#define BP_PRE_V_BUF_OFFSET_VBO 0
+#define BM_PRE_V_BUF_OFFSET_VBO 0x01FFFFFF
+#define BF_PRE_V_BUF_OFFSET_VBO(v) \
+ (((v) << 0) & BM_PRE_V_BUF_OFFSET_VBO)
+
+#define HW_PRE_TPR_CTRL (0x00000070)
+#define HW_PRE_TPR_CTRL_SET (0x00000074)
+#define HW_PRE_TPR_CTRL_CLR (0x00000078)
+#define HW_PRE_TPR_CTRL_TOG (0x0000007c)
+
+#define BP_PRE_TPR_CTRL_RSVD 8
+#define BM_PRE_TPR_CTRL_RSVD 0xFFFFFF00
+#define BF_PRE_TPR_CTRL_RSVD(v) \
+ (((v) << 8) & BM_PRE_TPR_CTRL_RSVD)
+#define BP_PRE_TPR_CTRL_TILE_FORMAT 0
+#define BM_PRE_TPR_CTRL_TILE_FORMAT 0x000000FF
+#define BF_PRE_TPR_CTRL_TILE_FORMAT(v) \
+ (((v) << 0) & BM_PRE_TPR_CTRL_TILE_FORMAT)
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__BYPASS 0x00
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_SB_ST 0x10
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_SB_SRT 0x50
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_ST 0x20
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_SRT 0x60
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_MST 0xA0
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_MSRT 0xE0
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_SB_ST 0x11
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_SB_SRT 0x51
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_ST 0x21
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_SRT 0x61
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_MST 0xA1
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_MSRT 0xE1
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__VPU8_PRO 0x22
+#define BV_PRE_TPR_CTRL_TILE_FORMAT__VPU8_SB_INT 0x13
+
+#define HW_PRE_PREFETCH_ENGINE_CTRL (0x00000080)
+#define HW_PRE_PREFETCH_ENGINE_CTRL_SET (0x00000084)
+#define HW_PRE_PREFETCH_ENGINE_CTRL_CLR (0x00000088)
+#define HW_PRE_PREFETCH_ENGINE_CTRL_TOG (0x0000008c)
+
+#define BP_PRE_PREFETCH_ENGINE_CTRL_RSVD1 16
+#define BM_PRE_PREFETCH_ENGINE_CTRL_RSVD1 0xFFFF0000
+#define BF_PRE_PREFETCH_ENGINE_CTRL_RSVD1(v) \
+ (((v) << 16) & BM_PRE_PREFETCH_ENGINE_CTRL_RSVD1)
+#define BM_PRE_PREFETCH_ENGINE_CTRL_TPR_COOR_OFFSET_EN 0x00008000
+#define BF_PRE_PREFETCH_ENGINE_CTRL_TPR_COOR_OFFSET_EN(v) \
+ (((v) << 15) & BM_PRE_PREFETCH_ENGINE_CTRL_TPR_COOR_OFFSET_EN)
+#define BM_PRE_PREFETCH_ENGINE_CTRL_PARTIAL_UV_SWAP 0x00004000
+#define BF_PRE_PREFETCH_ENGINE_CTRL_PARTIAL_UV_SWAP(v) \
+ (((v) << 14) & BM_PRE_PREFETCH_ENGINE_CTRL_PARTIAL_UV_SWAP)
+#define BM_PRE_PREFETCH_ENGINE_CTRL_CROP_EN 0x00002000
+#define BF_PRE_PREFETCH_ENGINE_CTRL_CROP_EN(v) \
+ (((v) << 13) & BM_PRE_PREFETCH_ENGINE_CTRL_CROP_EN)
+#define BV_PRE_PREFETCH_ENGINE_CTRL_CROP_EN__0 0x0
+#define BV_PRE_PREFETCH_ENGINE_CTRL_CROP_EN__1 0x1
+#define BM_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE 0x00001000
+#define BF_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE(v) \
+ (((v) << 12) & BM_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE)
+#define BV_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE__0 0x0
+#define BV_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE__1 0x1
+#define BM_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS 0x00000800
+#define BF_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS(v) \
+ (((v) << 11) & BM_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS)
+#define BV_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS__0 0x0
+#define BV_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS__1 0x1
+#define BP_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT 8
+#define BM_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT 0x00000700
+#define BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT(v) \
+ (((v) << 8) & BM_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT)
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__0 0x0
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__1 0x1
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__2 0x2
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__3 0x3
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__4 0x4
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__5 0x5
+#define BP_PRE_PREFETCH_ENGINE_CTRL_RSVD0 6
+#define BM_PRE_PREFETCH_ENGINE_CTRL_RSVD0 0x000000C0
+#define BF_PRE_PREFETCH_ENGINE_CTRL_RSVD0(v) \
+ (((v) << 6) & BM_PRE_PREFETCH_ENGINE_CTRL_RSVD0)
+#define BP_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP 4
+#define BM_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP 0x00000030
+#define BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP(v) \
+ (((v) << 4) & BM_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP)
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP__0 0x0
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP__1 0x1
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP__2 0x2
+#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP__3 0x3
+#define BP_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES 1
+#define BM_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES 0x0000000E
+#define BF_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES(v) \
+ (((v) << 1) & BM_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES)
+#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__8_bytes 0x0
+#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__16_bytes 0x1
+#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__32_bytes 0x2
+#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__64_bytes 0x3
+#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__128_bytes 0x4
+#define BM_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN 0x00000001
+#define BF_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN)
+#define BV_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN__0 0x0
+#define BV_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN__1 0x1
+
+#define HW_PRE_PREFETCH_ENGINE_STATUS (0x00000090)
+
+#define BP_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_Y 16
+#define BM_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_Y 0x3FFF0000
+#define BF_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_Y(v) \
+ (((v) << 16) & BM_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_Y)
+#define BP_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_X 0
+#define BM_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_X 0x0000FFFF
+#define BF_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_X(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_X)
+
+#define HW_PRE_PREFETCH_ENGINE_INPUT_SIZE (0x000000a0)
+
+#define BP_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT 16
+#define BM_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT 0xFFFF0000
+#define BF_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT(v) \
+ (((v) << 16) & BM_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT)
+#define BP_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH 0
+#define BM_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH 0x0000FFFF
+#define BF_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH)
+
+#define HW_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC (0x000000b0)
+
+#define BP_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y 16
+#define BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y 0xFFFF0000
+#define BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y(v) \
+ (((v) << 16) & BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y)
+#define BP_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X 0
+#define BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X 0x0000FFFF
+#define BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X)
+
+#define HW_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC (0x000000c0)
+
+#define BP_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_Y 16
+#define BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_Y 0xFFFF0000
+#define BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_Y(v) \
+ (((v) << 16) & BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_Y)
+#define BP_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_X 0
+#define BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_X 0x0000FFFF
+#define BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_X(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_X)
+
+#define HW_PRE_PREFETCH_ENGINE_PITCH (0x000000d0)
+
+#define BP_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH 16
+#define BM_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH 0xFFFF0000
+#define BF_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH(v) \
+ (((v) << 16) & BM_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH)
+#define BP_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH 0
+#define BM_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH 0x0000FFFF
+#define BF_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH)
+
+#define HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET (0x000000e0)
+#define HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_SET (0x000000e4)
+#define HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_CLR (0x000000e8)
+#define HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_TOG (0x000000ec)
+
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD0 29
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD0 0xE0000000
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD0(v) \
+ (((v) << 29) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD0)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET3 24
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET3 0x1F000000
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET3(v) \
+ (((v) << 24) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET3)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD1 21
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD1 0x00E00000
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD1(v) \
+ (((v) << 21) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD1)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET2 16
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET2 0x001F0000
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET2(v) \
+ (((v) << 16) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET2)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD2 13
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD2 0x0000E000
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD2(v) \
+ (((v) << 13) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD2)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET1 8
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET1 0x00001F00
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET1(v) \
+ (((v) << 8) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET1)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD3 5
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD3 0x000000E0
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD3(v) \
+ (((v) << 5) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD3)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET0 0
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET0 0x0000001F
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET0(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET0)
+
+#define HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH (0x000000f0)
+#define HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_SET (0x000000f4)
+#define HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_CLR (0x000000f8)
+#define HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_TOG (0x000000fc)
+
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_RSVD0 16
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_RSVD0 0xFFFF0000
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_RSVD0(v) \
+ (((v) << 16) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_RSVD0)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH3 12
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH3 0x0000F000
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH3(v) \
+ (((v) << 12) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH3)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH2 8
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH2 0x00000F00
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH2(v) \
+ (((v) << 8) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH2)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH1 4
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH1 0x000000F0
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH1(v) \
+ (((v) << 4) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH1)
+#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH0 0
+#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH0 0x0000000F
+#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH0(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH0)
+
+#define HW_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET (0x00000100)
+
+#define BP_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_RSVD0 23
+#define BM_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_RSVD0 0xFF800000
+#define BF_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_RSVD0(v) \
+ (((v) << 23) & BM_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_RSVD0)
+#define BP_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET 0
+#define BM_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET 0xFFFFFFFF
+#define BF_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET(v) \
+ (((v) << 0) & BM_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET)
+
+#define HW_PRE_STORE_ENGINE_CTRL (0x00000110)
+#define HW_PRE_STORE_ENGINE_CTRL_SET (0x00000114)
+#define HW_PRE_STORE_ENGINE_CTRL_CLR (0x00000118)
+#define HW_PRE_STORE_ENGINE_CTRL_TOG (0x0000011c)
+
+#define BP_PRE_STORE_ENGINE_CTRL_RSVD0 6
+#define BM_PRE_STORE_ENGINE_CTRL_RSVD0 0xFFFFFFC0
+#define BF_PRE_STORE_ENGINE_CTRL_RSVD0(v) \
+ (((v) << 6) & BM_PRE_STORE_ENGINE_CTRL_RSVD0)
+#define BP_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP 4
+#define BM_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP 0x00000030
+#define BF_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP(v) \
+ (((v) << 4) & BM_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP)
+#define BV_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP__8_bits 0x0
+#define BV_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP__16_bits 0x1
+#define BV_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP__32_bits 0x2
+#define BV_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP__64_bits 0x3
+#define BP_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES 1
+#define BM_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES 0x0000000E
+#define BF_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES(v) \
+ (((v) << 1) & BM_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES)
+#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__8_bytes 0x0
+#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__16_bytes 0x1
+#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__32_bytes 0x2
+#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__64_bytes 0x3
+#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__128_bytes 0x4
+#define BM_PRE_STORE_ENGINE_CTRL_STORE_EN 0x00000001
+#define BF_PRE_STORE_ENGINE_CTRL_STORE_EN(v) \
+ (((v) << 0) & BM_PRE_STORE_ENGINE_CTRL_STORE_EN)
+#define BV_PRE_STORE_ENGINE_CTRL_STORE_EN__0 0x0
+#define BV_PRE_STORE_ENGINE_CTRL_STORE_EN__1 0x1
+
+#define HW_PRE_STORE_ENGINE_STATUS (0x00000120)
+
+#define BP_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y 16
+#define BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y 0x3FFF0000
+#define BF_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y(v) \
+ (((v) << 16) & BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y)
+#define BP_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_X 0
+#define BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_X 0x0000FFFF
+#define BF_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_X(v) \
+ (((v) << 0) & BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_X)
+
+#define HW_PRE_STORE_ENGINE_SIZE (0x00000130)
+
+#define BP_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT 16
+#define BM_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT 0xFFFF0000
+#define BF_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT(v) \
+ (((v) << 16) & BM_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT)
+#define BP_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH 0
+#define BM_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH 0x0000FFFF
+#define BF_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH(v) \
+ (((v) << 0) & BM_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH)
+
+#define HW_PRE_STORE_ENGINE_PITCH (0x00000140)
+
+#define BP_PRE_STORE_ENGINE_PITCH_RSVD0 16
+#define BM_PRE_STORE_ENGINE_PITCH_RSVD0 0xFFFF0000
+#define BF_PRE_STORE_ENGINE_PITCH_RSVD0(v) \
+ (((v) << 16) & BM_PRE_STORE_ENGINE_PITCH_RSVD0)
+#define BP_PRE_STORE_ENGINE_PITCH_OUT_PITCH 0
+#define BM_PRE_STORE_ENGINE_PITCH_OUT_PITCH 0x0000FFFF
+#define BF_PRE_STORE_ENGINE_PITCH_OUT_PITCH(v) \
+ (((v) << 0) & BM_PRE_STORE_ENGINE_PITCH_OUT_PITCH)
+
+#define HW_PRE_STORE_ENGINE_ADDR (0x00000150)
+
+#define BP_PRE_STORE_ENGINE_ADDR_OUT_BASE_ADDR 0
+#define BM_PRE_STORE_ENGINE_ADDR_OUT_BASE_ADDR 0xFFFFFFFF
+#define BF_PRE_STORE_ENGINE_ADDR_OUT_BASE_ADDR(v) (v)
+#endif /* __ARCH_ARM___PRE_H */
diff --git a/drivers/mxc/ipu3/pre.c b/drivers/mxc/ipu3/pre.c
new file mode 100644
index 000000000000..f1ce02b3fe90
--- /dev/null
+++ b/drivers/mxc/ipu3/pre.c
@@ -0,0 +1,999 @@
+/*
+ * Copyright (C) 2014-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/genalloc.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ipu-v3.h>
+#include <linux/ipu-v3-pre.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pre-regs.h"
+
+struct ipu_pre_data {
+ unsigned int id;
+ struct device *dev;
+ void __iomem *base;
+ struct clk *clk;
+
+ struct mutex mutex; /* for in_use */
+ spinlock_t lock; /* for register access */
+
+ struct list_head list;
+
+ struct gen_pool *iram_pool;
+ unsigned long double_buffer_size;
+ unsigned long double_buffer_base;
+ unsigned long double_buffer_paddr;
+
+ bool in_use;
+ bool enabled;
+};
+
+static LIST_HEAD(pre_list);
+static DEFINE_SPINLOCK(pre_list_lock);
+
+static inline void pre_write(struct ipu_pre_data *pre,
+ u32 value, unsigned int offset)
+{
+ writel(value, pre->base + offset);
+}
+
+static inline u32 pre_read(struct ipu_pre_data *pre, unsigned offset)
+{
+ return readl(pre->base + offset);
+}
+
+static struct ipu_pre_data *get_pre(unsigned int id)
+{
+ struct ipu_pre_data *pre;
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&pre_list_lock, lock_flags);
+ list_for_each_entry(pre, &pre_list, list) {
+ if (pre->id == id) {
+ spin_unlock_irqrestore(&pre_list_lock, lock_flags);
+ return pre;
+ }
+ }
+ spin_unlock_irqrestore(&pre_list_lock, lock_flags);
+
+ return NULL;
+}
+
+int ipu_pre_alloc(int ipu_id, ipu_channel_t channel)
+{
+ struct ipu_pre_data *pre;
+ int i, fixed;
+
+ if (channel == MEM_BG_SYNC) {
+ fixed = ipu_id ? 3 : 0;
+ pre = get_pre(fixed);
+ if (pre) {
+ mutex_lock(&pre->mutex);
+ if (!pre->in_use) {
+ pre->in_use = true;
+ mutex_unlock(&pre->mutex);
+ return pre->id;
+ }
+ mutex_unlock(&pre->mutex);
+ }
+ return pre ? -EBUSY : -ENOENT;
+ }
+
+ for (i = 1; i < 3; i++) {
+ pre = get_pre(i);
+ if (!pre)
+ continue;
+ mutex_lock(&pre->mutex);
+ if (!pre->in_use) {
+ pre->in_use = true;
+ mutex_unlock(&pre->mutex);
+ return pre->id;
+ }
+ mutex_unlock(&pre->mutex);
+ }
+
+ return pre ? -EBUSY : -ENOENT;
+}
+EXPORT_SYMBOL(ipu_pre_alloc);
+
+void ipu_pre_free(unsigned int *id)
+{
+ struct ipu_pre_data *pre;
+
+ pre = get_pre(*id);
+ if (!pre)
+ return;
+
+ mutex_lock(&pre->mutex);
+ pre->in_use = false;
+ mutex_unlock(&pre->mutex);
+
+ *id = -1;
+}
+EXPORT_SYMBOL(ipu_pre_free);
+
+unsigned long ipu_pre_alloc_double_buffer(unsigned int id, unsigned int size)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+
+ if (!pre)
+ return -ENOENT;
+
+ if (!size)
+ return -EINVAL;
+
+ pre->double_buffer_base = gen_pool_alloc(pre->iram_pool, size);
+ if (!pre->double_buffer_base) {
+ dev_err(pre->dev, "double buffer allocate failed\n");
+ return -ENOMEM;
+ }
+ pre->double_buffer_size = size;
+
+ pre->double_buffer_paddr = gen_pool_virt_to_phys(pre->iram_pool,
+ pre->double_buffer_base);
+
+ return pre->double_buffer_paddr;
+}
+EXPORT_SYMBOL(ipu_pre_alloc_double_buffer);
+
+void ipu_pre_free_double_buffer(unsigned int id)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+
+ if (!pre)
+ return;
+
+ if (pre->double_buffer_base) {
+ gen_pool_free(pre->iram_pool,
+ pre->double_buffer_base,
+ pre->double_buffer_size);
+ pre->double_buffer_base = 0;
+ pre->double_buffer_size = 0;
+ pre->double_buffer_paddr = 0;
+ }
+}
+EXPORT_SYMBOL(ipu_pre_free_double_buffer);
+
+/* PRE register configurations */
+int ipu_pre_set_ctrl(unsigned int id, struct ipu_pre_context *config)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+ int ret = 0;
+
+ if (!pre)
+ return -EINVAL;
+
+ if (!pre->enabled)
+ clk_prepare_enable(pre->clk);
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, BF_PRE_CTRL_TPR_RESET_SEL(1), HW_PRE_CTRL_SET);
+
+ if (config->repeat)
+ pre_write(pre, BF_PRE_CTRL_EN_REPEAT(1), HW_PRE_CTRL_SET);
+ else
+ pre_write(pre, BM_PRE_CTRL_EN_REPEAT, HW_PRE_CTRL_CLR);
+
+ if (config->vflip)
+ pre_write(pre, BF_PRE_CTRL_VFLIP(1), HW_PRE_CTRL_SET);
+ else
+ pre_write(pre, BM_PRE_CTRL_VFLIP, HW_PRE_CTRL_CLR);
+
+ if (config->handshake_en) {
+ pre_write(pre, BF_PRE_CTRL_HANDSHAKE_EN(1), HW_PRE_CTRL_SET);
+ if (config->hsk_abort_en)
+ pre_write(pre, BF_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN(1),
+ HW_PRE_CTRL_SET);
+ else
+ pre_write(pre, BM_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN,
+ HW_PRE_CTRL_CLR);
+
+ switch (config->hsk_line_num) {
+ case 0 /* 4 lines */:
+ pre_write(pre, BM_PRE_CTRL_HANDSHAKE_LINE_NUM,
+ HW_PRE_CTRL_CLR);
+ break;
+ case 1 /* 8 lines */:
+ pre_write(pre, BM_PRE_CTRL_HANDSHAKE_LINE_NUM,
+ HW_PRE_CTRL_CLR);
+ pre_write(pre, BF_PRE_CTRL_HANDSHAKE_LINE_NUM(1),
+ HW_PRE_CTRL_SET);
+ break;
+ case 2 /* 16 lines */:
+ pre_write(pre, BM_PRE_CTRL_HANDSHAKE_LINE_NUM,
+ HW_PRE_CTRL_CLR);
+ pre_write(pre, BF_PRE_CTRL_HANDSHAKE_LINE_NUM(2),
+ HW_PRE_CTRL_SET);
+ break;
+ default:
+ dev_err(pre->dev, "invalid hanshake line number\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ } else
+ pre_write(pre, BM_PRE_CTRL_HANDSHAKE_EN, HW_PRE_CTRL_CLR);
+
+
+ switch (config->prefetch_mode) {
+ case 0:
+ pre_write(pre, BM_PRE_CTRL_BLOCK_EN, HW_PRE_CTRL_CLR);
+ break;
+ case 1:
+ pre_write(pre, BF_PRE_CTRL_BLOCK_EN(1), HW_PRE_CTRL_SET);
+ switch (config->block_size) {
+ case 0:
+ pre_write(pre, BM_PRE_CTRL_BLOCK_16, HW_PRE_CTRL_CLR);
+ break;
+ case 1:
+ pre_write(pre, BF_PRE_CTRL_BLOCK_16(1), HW_PRE_CTRL_SET);
+ break;
+ default:
+ dev_err(pre->dev, "invalid block size for pre\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ break;
+ default:
+ dev_err(pre->dev, "invalid prefech mode for pre\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ switch (config->interlaced) {
+ case 0: /* progressive mode */
+ pre_write(pre, BM_PRE_CTRL_SO, HW_PRE_CTRL_CLR);
+ break;
+ case 2: /* interlaced mode: Pal */
+ pre_write(pre, BF_PRE_CTRL_SO(1), HW_PRE_CTRL_SET);
+ pre_write(pre, BM_PRE_CTRL_INTERLACED_FIELD, HW_PRE_CTRL_CLR);
+ break;
+ case 3: /* interlaced mode: NTSC */
+ pre_write(pre, BF_PRE_CTRL_SO(1), HW_PRE_CTRL_SET);
+ pre_write(pre, BF_PRE_CTRL_INTERLACED_FIELD(1), HW_PRE_CTRL_SET);
+ break;
+ default:
+ dev_err(pre->dev, "invalid interlaced or progressive mode\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (config->sdw_update)
+ pre_write(pre, BF_PRE_CTRL_SDW_UPDATE(1), HW_PRE_CTRL_SET);
+ else
+ pre_write(pre, BM_PRE_CTRL_SDW_UPDATE, HW_PRE_CTRL_CLR);
+
+err:
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ if (!pre->enabled)
+ clk_disable_unprepare(pre->clk);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_pre_set_ctrl);
+
+static void ipu_pre_irq_mask(struct ipu_pre_data *pre,
+ unsigned long mask, bool clear)
+{
+ if (clear) {
+ pre_write(pre, mask & 0x1f, HW_PRE_IRQ_MASK_CLR);
+ return;
+ }
+ pre_write(pre, mask & 0x1f, HW_PRE_IRQ_MASK_SET);
+}
+
+static int ipu_pre_buf_set(unsigned int id, unsigned long cur_buf,
+ unsigned long next_buf)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+
+ if (!pre)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, cur_buf, HW_PRE_CUR_BUF);
+ pre_write(pre, next_buf, HW_PRE_NEXT_BUF);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ return 0;
+}
+
+static int ipu_pre_plane_buf_off_set(unsigned int id,
+ unsigned long sec_buf_off,
+ unsigned long trd_buf_off)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+
+ if (!pre || sec_buf_off & BM_PRE_U_BUF_OFFSET_RSVD0 ||
+ trd_buf_off & BM_PRE_V_BUF_OFFSET_RSVD0)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, sec_buf_off, HW_PRE_U_BUF_OFFSET);
+ pre_write(pre, trd_buf_off, HW_PRE_V_BUF_OFFSET);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ return 0;
+}
+
+static int ipu_pre_tpr_set(unsigned int id, unsigned int tile_fmt)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+ unsigned int tpr_ctrl, fmt;
+
+ if (!pre)
+ return -EINVAL;
+
+ switch (tile_fmt) {
+ case 0x0: /* Bypass */
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x0);
+ break;
+ case IPU_PIX_FMT_GPU32_SB_ST:
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x10);
+ break;
+ case IPU_PIX_FMT_GPU16_SB_ST:
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x11);
+ break;
+ case IPU_PIX_FMT_GPU32_ST:
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x20);
+ break;
+ case IPU_PIX_FMT_GPU16_ST:
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x21);
+ break;
+ case IPU_PIX_FMT_GPU32_SB_SRT:
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x50);
+ break;
+ case IPU_PIX_FMT_GPU16_SB_SRT:
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x51);
+ break;
+ case IPU_PIX_FMT_GPU32_SRT:
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x60);
+ break;
+ case IPU_PIX_FMT_GPU16_SRT:
+ fmt = BF_PRE_TPR_CTRL_TILE_FORMAT(0x61);
+ break;
+ default:
+ dev_err(pre->dev, "invalid tile fmt for pre\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ tpr_ctrl = pre_read(pre, HW_PRE_TPR_CTRL);
+ tpr_ctrl &= ~BM_PRE_TPR_CTRL_TILE_FORMAT;
+ tpr_ctrl |= fmt;
+ pre_write(pre, tpr_ctrl, HW_PRE_TPR_CTRL);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ return 0;
+}
+
+static int ipu_pre_set_shift(int id, unsigned int offset, unsigned int width)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+
+ if (!pre)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, offset, HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET);
+ pre_write(pre, width, HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ return 0;
+}
+
+static int ipu_pre_prefetch(unsigned int id,
+ unsigned int read_burst,
+ unsigned int input_bpp,
+ unsigned int input_pixel_fmt,
+ bool shift_bypass,
+ bool field_inverse,
+ bool tpr_coor_offset_en,
+ struct ipu_rect output_size,
+ unsigned int input_width,
+ unsigned int input_height,
+ unsigned int input_active_width,
+ unsigned int interlaced,
+ int interlace_offset)
+{
+ unsigned int prefetch_ctrl = 0;
+ unsigned int input_y_pitch = 0, input_uv_pitch = 0;
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+
+ if (!pre)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN(1);
+ switch (read_burst) {
+ case 0x0:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES(0x0);
+ break;
+ case 0x1:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES(0x1);
+ break;
+ case 0x2:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES(0x2);
+ break;
+ case 0x3:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES(0x3);
+ break;
+ case 0x4:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES(0x4);
+ break;
+ default:
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+ dev_err(pre->dev, "invalid read burst for prefetch engine\n");
+ return -EINVAL;
+ }
+
+ switch (input_bpp) {
+ case 8:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP(0x0);
+ break;
+ case 16:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP(0x1);
+ break;
+ case 32:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP(0x2);
+ break;
+ case 64:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP(0x3);
+ break;
+ default:
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+ dev_err(pre->dev, "invalid input bpp for prefetch engine\n");
+ return -EINVAL;
+ }
+
+ switch (input_pixel_fmt) {
+ case 0x1: /* tile */
+ case 0x0: /* generic data */
+ case IPU_PIX_FMT_RGB666:
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_BGRA4444:
+ case IPU_PIX_FMT_BGRA5551:
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_GBR24:
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_RGB32:
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_ABGR32:
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_UYVY:
+ case IPU_PIX_FMT_YUV444:
+ case IPU_PIX_FMT_AYUV:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT(0x0);
+ input_y_pitch = input_width * (input_bpp >> 3);
+ if (interlaced && input_pixel_fmt != 0x1)
+ input_y_pitch *= 2;
+ break;
+ case IPU_PIX_FMT_YUV444P:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT(0x1);
+ input_y_pitch = input_width;
+ input_uv_pitch = input_width;
+ break;
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YVU422P:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT(0x2);
+ input_y_pitch = input_width;
+ input_uv_pitch = input_width >> 1;
+ break;
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YUV420P:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT(0x3);
+ input_y_pitch = input_width;
+ input_uv_pitch = input_width >> 1;
+ break;
+ case PRE_PIX_FMT_NV61:
+ prefetch_ctrl |= BM_PRE_PREFETCH_ENGINE_CTRL_PARTIAL_UV_SWAP;
+ case IPU_PIX_FMT_NV16:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT(0x4);
+ input_y_pitch = input_width;
+ input_uv_pitch = input_width;
+ break;
+ case PRE_PIX_FMT_NV21:
+ prefetch_ctrl |= BM_PRE_PREFETCH_ENGINE_CTRL_PARTIAL_UV_SWAP;
+ case IPU_PIX_FMT_NV12:
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT(0x5);
+ input_y_pitch = input_width;
+ input_uv_pitch = input_width;
+ break;
+ default:
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+ dev_err(pre->dev, "invalid input pixel format for prefetch engine\n");
+ return -EINVAL;
+ }
+
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS(shift_bypass ? 1 : 0);
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE(field_inverse ? 1 : 0);
+ prefetch_ctrl |= BF_PRE_PREFETCH_ENGINE_CTRL_TPR_COOR_OFFSET_EN(tpr_coor_offset_en ? 1 : 0);
+
+ pre_write(pre, BF_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH(input_active_width) |
+ BF_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT(input_height),
+ HW_PRE_PREFETCH_ENGINE_INPUT_SIZE);
+
+ if (tpr_coor_offset_en)
+ pre_write(pre, BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X(output_size.left) |
+ BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y(output_size.top),
+ HW_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC);
+
+ pre_write(pre, BF_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH(input_y_pitch) |
+ BF_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH(input_uv_pitch),
+ HW_PRE_PREFETCH_ENGINE_PITCH);
+
+ pre_write(pre, BF_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET(interlace_offset), HW_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET);
+
+ pre_write(pre, prefetch_ctrl, HW_PRE_PREFETCH_ENGINE_CTRL);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ return 0;
+}
+
+static int ipu_pre_store(unsigned int id,
+ bool store_en,
+ unsigned int write_burst,
+ unsigned int output_bpp,
+ /* this means the output
+ * width by prefetch
+ */
+ unsigned int input_width,
+ unsigned int input_height,
+ unsigned int out_pitch,
+ unsigned int output_addr)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned int store_ctrl = 0;
+ unsigned long lock_flags;
+
+ if (!pre)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_STORE_EN(store_en ? 1 : 0);
+
+ if (store_en) {
+ switch (write_burst) {
+ case 0x0:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES(0x0);
+ break;
+ case 0x1:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES(0x1);
+ break;
+ case 0x2:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES(0x2);
+ break;
+ case 0x3:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES(0x3);
+ break;
+ case 0x4:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES(0x4);
+ break;
+ default:
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+ dev_err(pre->dev, "invalid write burst value for store engine\n");
+ return -EINVAL;
+ }
+
+ switch (output_bpp) {
+ case 8:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP(0x0);
+ break;
+ case 16:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP(0x1);
+ break;
+ case 32:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP(0x2);
+ break;
+ case 64:
+ store_ctrl |= BF_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP(0x3);
+ break;
+ default:
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+ dev_err(pre->dev, "invalid ouput bpp for store engine\n");
+ return -EINVAL;
+ }
+
+ pre_write(pre, BF_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH(input_width) |
+ BF_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT(input_height),
+ HW_PRE_STORE_ENGINE_SIZE);
+
+ pre_write(pre, BF_PRE_STORE_ENGINE_PITCH_OUT_PITCH(out_pitch),
+ HW_PRE_STORE_ENGINE_PITCH);
+
+ pre_write(pre, BF_PRE_STORE_ENGINE_ADDR_OUT_BASE_ADDR(output_addr),
+ HW_PRE_STORE_ENGINE_ADDR);
+ }
+
+ pre_write(pre, store_ctrl, HW_PRE_STORE_ENGINE_CTRL);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ return 0;
+}
+/* End */
+
+static irqreturn_t ipu_pre_irq_handle(int irq, void *dev_id)
+{
+ struct ipu_pre_data *pre = dev_id;
+ unsigned int irq_stat, axi_id = 0;
+
+ spin_lock(&pre->lock);
+ irq_stat = pre_read(pre, HW_PRE_IRQ);
+
+ if (irq_stat & BM_PRE_IRQ_HANDSHAKE_ABORT_IRQ) {
+ dev_warn(pre->dev, "handshake abort\n");
+ pre_write(pre, BM_PRE_IRQ_HANDSHAKE_ABORT_IRQ, HW_PRE_IRQ_CLR);
+ }
+
+ if (irq_stat & BM_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ) {
+ dev_warn(pre->dev, "tpr read num bytes overflow\n");
+ pre_write(pre, BM_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ,
+ HW_PRE_IRQ_CLR);
+ }
+
+ if (irq_stat & BM_PRE_IRQ_HANDSHAKE_ERROR_IRQ) {
+ dev_warn(pre->dev, "handshake error\n");
+ pre_write(pre, BM_PRE_IRQ_HANDSHAKE_ERROR_IRQ, HW_PRE_IRQ_CLR);
+ }
+
+ axi_id = (irq_stat & BM_PRE_IRQ_AXI_ERROR_ID) >>
+ BP_PRE_IRQ_AXI_ERROR_ID;
+ if (irq_stat & BM_PRE_IRQ_AXI_WRITE_ERROR) {
+ dev_warn(pre->dev, "AXI%d write error\n", axi_id);
+ pre_write(pre, BM_PRE_IRQ_AXI_WRITE_ERROR, HW_PRE_IRQ_CLR);
+ }
+
+ if (irq_stat & BM_PRE_IRQ_AXI_READ_ERROR) {
+ dev_warn(pre->dev, "AXI%d read error\n", axi_id);
+ pre_write(pre, BM_PRE_IRQ_AXI_READ_ERROR, HW_PRE_IRQ_CLR);
+ }
+ spin_unlock(&pre->lock);
+
+ return IRQ_HANDLED;
+}
+
+static void ipu_pre_out_of_reset(unsigned int id)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+
+ if (!pre)
+ return;
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, BF_PRE_CTRL_SFTRST(1) | BF_PRE_CTRL_CLKGATE(1),
+ HW_PRE_CTRL_CLR);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+}
+
+int ipu_pre_config(int id, struct ipu_pre_context *config)
+{
+ int ret = 0;
+ struct ipu_pre_data *pre = get_pre(id);
+
+ if (!config || !pre)
+ return -EINVAL;
+
+ config->store_addr = pre->double_buffer_paddr;
+
+ if (!pre->enabled)
+ clk_prepare_enable(pre->clk);
+
+ ipu_pre_out_of_reset(id);
+
+ ret = ipu_pre_plane_buf_off_set(id, config->sec_buf_off,
+ config->trd_buf_off);
+ if (ret < 0)
+ goto out;
+
+ ret = ipu_pre_tpr_set(id, config->tile_fmt);
+ if (ret < 0)
+ goto out;
+
+ ret = ipu_pre_buf_set(id, config->cur_buf, config->next_buf);
+ if (ret < 0)
+ goto out;
+
+ ret = ipu_pre_set_shift(id, config->prefetch_shift_offset,
+ config->prefetch_shift_width);
+ if (ret < 0)
+ goto out;
+
+ ret = ipu_pre_prefetch(id, config->read_burst, config->prefetch_input_bpp,
+ config->prefetch_input_pixel_fmt, config->shift_bypass,
+ config->field_inverse, config->tpr_coor_offset_en,
+ config->prefetch_output_size, config->prefetch_input_width,
+ config->prefetch_input_height,
+ config->prefetch_input_active_width,
+ config->interlaced,
+ config->interlace_offset);
+ if (ret < 0)
+ goto out;
+
+ ret = ipu_pre_store(id, config->store_en,
+ config->write_burst, config->store_output_bpp,
+ config->prefetch_output_size.width, config->prefetch_output_size.height,
+ config->store_pitch,
+ config->store_addr);
+ if (ret < 0)
+ goto out;
+
+ ipu_pre_irq_mask(pre, BM_PRE_IRQ_HANDSHAKE_ABORT_IRQ |
+ BM_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ |
+ BM_PRE_IRQ_HANDSHAKE_ERROR_IRQ, false);
+out:
+ if (!pre->enabled)
+ clk_disable_unprepare(pre->clk);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_pre_config);
+
+int ipu_pre_enable(int id)
+{
+ int ret = 0;
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+
+ if (!pre)
+ return -EINVAL;
+
+ if (pre->enabled)
+ return 0;
+
+ clk_prepare_enable(pre->clk);
+
+ /* start the pre engine */
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, BF_PRE_CTRL_ENABLE(1), HW_PRE_CTRL_SET);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ pre->enabled = true;
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_pre_enable);
+
+int ipu_pre_sdw_update(int id)
+{
+ int ret = 0;
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+
+ if (!pre)
+ return -EINVAL;
+
+ if (!pre->enabled)
+ clk_prepare_enable(pre->clk);
+
+ /* start the pre engine */
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, BF_PRE_CTRL_SDW_UPDATE(1), HW_PRE_CTRL_SET);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ if (!pre->enabled)
+ clk_disable_unprepare(pre->clk);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipu_pre_sdw_update);
+
+void ipu_pre_disable(int id)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned long lock_flags;
+
+ if (!pre)
+ return;
+
+ if (!pre->enabled)
+ return;
+
+ /* stop the pre engine */
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, BF_PRE_CTRL_ENABLE(1), HW_PRE_CTRL_CLR);
+ pre_write(pre, BF_PRE_CTRL_SDW_UPDATE(1), HW_PRE_CTRL_SET);
+ pre_write(pre, BF_PRE_CTRL_SFTRST(1), HW_PRE_CTRL_SET);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ clk_disable_unprepare(pre->clk);
+
+ pre->enabled = false;
+}
+EXPORT_SYMBOL(ipu_pre_disable);
+
+int ipu_pre_set_fb_buffer(int id, bool resolve,
+ unsigned long fb_paddr,
+ unsigned int y_res,
+ unsigned int x_crop,
+ unsigned int y_crop,
+ unsigned int sec_buf_off,
+ unsigned int trd_buf_off)
+{
+ struct ipu_pre_data *pre = get_pre(id);
+ unsigned int store_stat, store_block_y;
+ unsigned long lock_flags;
+ bool update = true;
+
+ if (!pre)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pre->lock, lock_flags);
+ pre_write(pre, fb_paddr, HW_PRE_NEXT_BUF);
+ pre_write(pre, sec_buf_off, HW_PRE_U_BUF_OFFSET);
+ pre_write(pre, trd_buf_off, HW_PRE_V_BUF_OFFSET);
+ pre_write(pre, BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X(x_crop) |
+ BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y(y_crop),
+ HW_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC);
+
+ /*
+ * Update shadow only when store engine runs out of the problematic
+ * window to workaround the SoC design bug recorded by errata ERR009624.
+ */
+ if (y_res > IPU_PRE_SMALL_LINE) {
+ unsigned long timeout = jiffies + msecs_to_jiffies(20);
+
+ do {
+ if (time_after(jiffies, timeout)) {
+ update = false;
+ dev_warn(pre->dev, "timeout waiting for PRE "
+ "to run out of problematic window for "
+ "shadow update\n");
+ break;
+ }
+
+ store_stat = pre_read(pre, HW_PRE_STORE_ENGINE_STATUS);
+ store_block_y = (store_stat &
+ BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y) >>
+ BP_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y;
+ } while (store_block_y >=
+ (resolve ? DIV_ROUND_UP(y_res, 4) - 1 : y_res - 2) ||
+ store_block_y == 0);
+ }
+
+ if (update)
+ pre_write(pre, BF_PRE_CTRL_SDW_UPDATE(1), HW_PRE_CTRL_SET);
+ spin_unlock_irqrestore(&pre->lock, lock_flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_pre_set_fb_buffer);
+
+static int ipu_pre_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct ipu_pre_data *pre;
+ struct resource *res;
+ unsigned long lock_flags;
+ int id, irq, err;
+
+ pre = devm_kzalloc(&pdev->dev, sizeof(*pre), GFP_KERNEL);
+ if (!pre)
+ return -ENOMEM;
+ pre->dev = &pdev->dev;
+
+ id = of_alias_get_id(np, "pre");
+ if (id < 0) {
+ dev_err(&pdev->dev, "failed to get PRE id\n");
+ return id;
+ }
+ pre->id = id;
+
+ mutex_init(&pre->mutex);
+ spin_lock_init(&pre->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pre->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pre->base))
+ return PTR_ERR(pre->base);
+
+ pre->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pre->clk)) {
+ dev_err(&pdev->dev, "failed to get the pre clk\n");
+ return PTR_ERR(pre->clk);
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ err = devm_request_irq(&pdev->dev, irq, ipu_pre_irq_handle,
+ IRQF_TRIGGER_RISING, pdev->name, pre);
+ if (err) {
+ dev_err(&pdev->dev, "failed to request pre irq\n");
+ return err;
+ }
+
+ pre->iram_pool = of_gen_pool_get(pdev->dev.of_node, "ocram", 0);
+ if (!pre->iram_pool) {
+ dev_err(&pdev->dev, "no iram exist for pre\n");
+ return -ENOMEM;
+ }
+
+ spin_lock_irqsave(&pre_list_lock, lock_flags);
+ list_add_tail(&pre->list, &pre_list);
+ spin_unlock_irqrestore(&pre_list_lock, lock_flags);
+
+ ipu_pre_alloc_double_buffer(pre->id, IPU_PRE_MAX_WIDTH * 8 * IPU_PRE_MAX_BPP);
+
+ /* PRE GATE ON */
+ clk_prepare_enable(pre->clk);
+ pre_write(pre, BF_PRE_CTRL_SFTRST(1) | BF_PRE_CTRL_CLKGATE(1),
+ HW_PRE_CTRL_CLR);
+ pre_write(pre, 0xf, HW_PRE_IRQ_MASK);
+ clk_disable_unprepare(pre->clk);
+
+ platform_set_drvdata(pdev, pre);
+
+ dev_info(&pdev->dev, "driver probed\n");
+
+ return 0;
+}
+
+static int ipu_pre_remove(struct platform_device *pdev)
+{
+ struct ipu_pre_data *pre = platform_get_drvdata(pdev);
+ unsigned long lock_flags;
+
+ if (pre->iram_pool && pre->double_buffer_base) {
+ gen_pool_free(pre->iram_pool,
+ pre->double_buffer_base,
+ pre->double_buffer_size);
+ }
+
+ spin_lock_irqsave(&pre_list_lock, lock_flags);
+ list_del(&pre->list);
+ spin_unlock_irqrestore(&pre_list_lock, lock_flags);
+
+ return 0;
+}
+
+static const struct of_device_id imx_ipu_pre_dt_ids[] = {
+ { .compatible = "fsl,imx6q-pre", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_ipu_pre_dt_ids);
+
+static struct platform_driver ipu_pre_driver = {
+ .driver = {
+ .name = "imx-pre",
+ .of_match_table = of_match_ptr(imx_ipu_pre_dt_ids),
+ },
+ .probe = ipu_pre_probe,
+ .remove = ipu_pre_remove,
+};
+
+static int __init ipu_pre_init(void)
+{
+ return platform_driver_register(&ipu_pre_driver);
+}
+subsys_initcall(ipu_pre_init);
+
+static void __exit ipu_pre_exit(void)
+{
+ platform_driver_unregister(&ipu_pre_driver);
+}
+module_exit(ipu_pre_exit);
+
+MODULE_DESCRIPTION("i.MX PRE driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mxc/ipu3/prg-regs.h b/drivers/mxc/ipu3/prg-regs.h
new file mode 100644
index 000000000000..bca0e560a6f9
--- /dev/null
+++ b/drivers/mxc/ipu3/prg-regs.h
@@ -0,0 +1,70 @@
+/*
+ * Freescale IPU PRG Register Definitions
+ *
+ * Copyright 2014-2015 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
+ */
+#include <linux/bitops.h>
+
+#ifndef __IPU_PRG_H__
+#define __IPU_PRG_H__
+
+#define IPU_PR_CTRL 0x00
+#define IPU_PR_STATUS 0x04
+#define IPU_PR_QOS 0x08
+#define IPU_PR_REG_UPDATE 0x0c
+#define IPU_PR_STRIDE(ch) (0x10 + (ch) * 4)
+#define IPU_PR_CROP_LINE 0x1c
+#define IPU_PR_ADDR_THD 0x20
+#define IPU_PR_CH_BADDR(ch) (0x24 + (ch) * 4)
+#define IPU_PR_CH_OFFSET(ch) (0x30 + (ch) * 4)
+#define IPU_PR_CH_ILO(ch) (0x3c + (ch) * 4)
+#define IPU_PR_CH_HEIGHT(ch) (0x48 + (ch) * 4)
+
+#define IPU_PR_CTRL_CH_BYPASS(ch) (0x1 << (ch))
+#define IPU_PR_CTRL_SOFT_CH_ARID(ch, n) ((n) << ((ch) * 2 + 8))
+#define IPU_PR_CTRL_SOFT_CH_ARID_MASK(ch) (0x3 << ((ch) * 2 + 8))
+#define IPU_PR_CTRL_CH_SO(ch, interlace) ((interlace) << ((ch) + 16))
+#define IPU_PR_CTRL_CH_SO_MASK(ch) (0x1 << ((ch) + 16))
+#define IPU_PR_CTRL_CH_VFLIP(ch, vflip) ((vflip) << ((ch) + 19))
+#define IPU_PR_CTRL_CH_VFLIP_MASK(ch) (0x1 << ((ch) + 19))
+#define IPU_PR_CTRL_CH_BLOCK_MODE(ch, mode) ((mode) << ((ch) + 22))
+#define IPU_PR_CTRL_CH_BLOCK_MODE_MASK(ch) (0x1 << ((ch) + 22))
+#define IPU_PR_CTRL_CH_CNT_LOAD_EN(ch) (0x1 << ((ch) + 25))
+#define IPU_PR_CTRL_CH_CNT_LOAD_EN_MASK (0x7 << 25)
+#define IPU_PR_CTRL_SOFTRST BIT(30)
+#define IPU_PR_CTRL_SHADOW_EN BIT(31)
+
+#define IPU_PR_STATUS_BUF_RDY(ch, buf) (1 << ((ch) * 2 + (buf)))
+
+#define IPU_PR_QOS_PRI(id, qos) ((qos) << ((id) * 4))
+#define IPU_PR_QOS_MASK(id) (0xf << ((id) * 4))
+
+#define IPU_PR_REG_UPDATE_EN BIT(0)
+
+#define IPU_PR_STRIDE_MASK 0x3fff
+
+#define IPU_PR_CROP_LINE_NUM(ch, n) ((n) << ((ch) * 4))
+#define IPU_PR_CROP_LINE_MASK(ch) (0xf << ((ch) * 4))
+
+#define IPU_PR_ADDR_THD_MASK 0xffffffff
+
+#define IPU_PR_CH_BADDR_MASK 0xffffffff
+
+#define IPU_PR_CH_OFFSET_MASK 0xffffffff
+
+#define IPU_PR_CH_ILO_MASK 0x007fffff
+#define IPU_PR_CH_ILO_NUM(ilo) ((ilo) & IPU_PR_CH_ILO_MASK)
+
+#define IPU_PR_CH_HEIGHT_MASK 0x00000fff
+#define IPU_PR_CH_HEIGHT_NUM(fh) (((fh) - 1) & IPU_PR_CH_HEIGHT_MASK)
+#define IPU_PR_CH_IPU_HEIGHT_MASK 0x0fff0000
+#define IPU_PR_CH_IPU_HEIGHT_NUM(fh) ((((fh) - 1) << 16) & IPU_PR_CH_IPU_HEIGHT_MASK)
+
+#endif /* __IPU_PRG_H__ */
diff --git a/drivers/mxc/ipu3/prg.c b/drivers/mxc/ipu3/prg.c
new file mode 100644
index 000000000000..45363a843392
--- /dev/null
+++ b/drivers/mxc/ipu3/prg.c
@@ -0,0 +1,506 @@
+/*
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ipu-v3-prg.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "prg-regs.h"
+
+#define PRG_CHAN_NUM 3
+
+struct prg_chan {
+ unsigned int pre_num;
+ struct mutex mutex; /* for in_use */
+ bool in_use;
+};
+
+struct ipu_prg_data {
+ unsigned int id;
+ void __iomem *base;
+ unsigned long memory;
+ struct clk *axi_clk;
+ struct clk *apb_clk;
+ struct list_head list;
+ struct device *dev;
+ struct prg_chan chan[PRG_CHAN_NUM];
+ struct regmap *regmap;
+ struct regmap_field *pre_prg_sel[2];
+ spinlock_t lock;
+};
+
+static LIST_HEAD(prg_list);
+static DEFINE_MUTEX(prg_lock);
+
+static inline void prg_write(struct ipu_prg_data *prg,
+ u32 value, unsigned int offset)
+{
+ writel(value, prg->base + offset);
+}
+
+static inline u32 prg_read(struct ipu_prg_data *prg, unsigned offset)
+{
+ return readl(prg->base + offset);
+}
+
+static struct ipu_prg_data *get_prg(unsigned int ipu_id)
+{
+ struct ipu_prg_data *prg;
+
+ mutex_lock(&prg_lock);
+ list_for_each_entry(prg, &prg_list, list) {
+ if (prg->id == ipu_id) {
+ mutex_unlock(&prg_lock);
+ return prg;
+ }
+ }
+ mutex_unlock(&prg_lock);
+
+ return NULL;
+}
+
+static int assign_prg_chan(struct ipu_prg_data *prg, unsigned int pre_num,
+ ipu_channel_t ipu_ch)
+{
+ int prg_ch;
+
+ if (!prg)
+ return -EINVAL;
+
+ switch (ipu_ch) {
+ case MEM_BG_SYNC:
+ prg_ch = 0;
+ break;
+ case MEM_FG_SYNC:
+ prg_ch = 1;
+ break;
+ case MEM_DC_SYNC:
+ prg_ch = 2;
+ break;
+ default:
+ dev_err(prg->dev, "wrong ipu channel type\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&prg->chan[prg_ch].mutex);
+ if (!prg->chan[prg_ch].in_use) {
+ prg->chan[prg_ch].in_use = true;
+ prg->chan[prg_ch].pre_num = pre_num;
+
+ if (prg_ch != 0) {
+ unsigned int pmux, psel; /* primary */
+ unsigned int smux, ssel; /* secondary */
+ struct regmap_field *pfield, *sfield;
+
+ psel = pre_num - 1;
+ ssel = psel ? 0 : 1;
+
+ pfield = prg->pre_prg_sel[psel];
+ sfield = prg->pre_prg_sel[ssel];
+ pmux = (prg_ch - 1) + (prg->id << 1);
+
+ mutex_lock(&prg_lock);
+ regmap_field_write(pfield, pmux);
+
+ /*
+ * PRE1 and PRE2 cannot bind with a same channel of
+ * one PRG even if one of the two PREs is disabled.
+ */
+ regmap_field_read(sfield, &smux);
+ if (smux == pmux) {
+ smux = pmux ^ 0x1;
+ regmap_field_write(sfield, smux);
+ }
+ mutex_unlock(&prg_lock);
+ }
+ mutex_unlock(&prg->chan[prg_ch].mutex);
+ dev_dbg(prg->dev, "bind prg%u ch%d with pre%u\n",
+ prg->id, prg_ch, pre_num);
+ return prg_ch;
+ }
+ mutex_unlock(&prg->chan[prg_ch].mutex);
+ return -EBUSY;
+}
+
+static inline int get_prg_chan(struct ipu_prg_data *prg, unsigned int pre_num)
+{
+ int i;
+
+ if (!prg)
+ return -EINVAL;
+
+ for (i = 0; i < PRG_CHAN_NUM; i++) {
+ mutex_lock(&prg->chan[i].mutex);
+ if (prg->chan[i].in_use &&
+ prg->chan[i].pre_num == pre_num) {
+ mutex_unlock(&prg->chan[i].mutex);
+ return i;
+ }
+ mutex_unlock(&prg->chan[i].mutex);
+ }
+ return -ENOENT;
+}
+
+int ipu_prg_config(struct ipu_prg_config *config)
+{
+ struct ipu_prg_data *prg = get_prg(config->id);
+ struct ipu_soc *ipu = ipu_get_soc(config->id);
+ int prg_ch, axi_id;
+ u32 reg;
+
+ if (!prg || config->crop_line > 3 || !ipu)
+ return -EINVAL;
+
+ if (config->height & ~IPU_PR_CH_HEIGHT_MASK)
+ return -EINVAL;
+
+ prg_ch = assign_prg_chan(prg, config->pre_num, config->ipu_ch);
+ if (prg_ch < 0)
+ return prg_ch;
+
+ axi_id = ipu_ch_param_get_axi_id(ipu, config->ipu_ch, IPU_INPUT_BUFFER);
+
+ clk_prepare_enable(prg->axi_clk);
+ clk_prepare_enable(prg->apb_clk);
+
+ spin_lock(&prg->lock);
+ /* clear all load enable to impact other channels */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg &= ~IPU_PR_CTRL_CH_CNT_LOAD_EN_MASK;
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* counter load enable */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg |= IPU_PR_CTRL_CH_CNT_LOAD_EN(prg_ch);
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* AXI ID */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg &= ~IPU_PR_CTRL_SOFT_CH_ARID_MASK(prg_ch);
+ reg |= IPU_PR_CTRL_SOFT_CH_ARID(prg_ch, axi_id);
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* so */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg &= ~IPU_PR_CTRL_CH_SO_MASK(prg_ch);
+ reg |= IPU_PR_CTRL_CH_SO(prg_ch, config->so);
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* vflip */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg &= ~IPU_PR_CTRL_CH_VFLIP_MASK(prg_ch);
+ reg |= IPU_PR_CTRL_CH_VFLIP(prg_ch, config->vflip);
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* block mode */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg &= ~IPU_PR_CTRL_CH_BLOCK_MODE_MASK(prg_ch);
+ reg |= IPU_PR_CTRL_CH_BLOCK_MODE(prg_ch, config->block_mode);
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* disable bypass */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg &= ~IPU_PR_CTRL_CH_BYPASS(prg_ch);
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* stride */
+ reg = prg_read(prg, IPU_PR_STRIDE(prg_ch));
+ reg &= ~IPU_PR_STRIDE_MASK;
+ reg |= config->stride - 1;
+ prg_write(prg, reg, IPU_PR_STRIDE(prg_ch));
+
+ /* ilo */
+ reg = prg_read(prg, IPU_PR_CH_ILO(prg_ch));
+ reg &= ~IPU_PR_CH_ILO_MASK;
+ reg |= IPU_PR_CH_ILO_NUM(config->ilo);
+ prg_write(prg, reg, IPU_PR_CH_ILO(prg_ch));
+
+ /* height */
+ reg = prg_read(prg, IPU_PR_CH_HEIGHT(prg_ch));
+ reg &= ~IPU_PR_CH_HEIGHT_MASK;
+ reg |= IPU_PR_CH_HEIGHT_NUM(config->height);
+ prg_write(prg, reg, IPU_PR_CH_HEIGHT(prg_ch));
+
+ /* ipu height */
+ reg = prg_read(prg, IPU_PR_CH_HEIGHT(prg_ch));
+ reg &= ~IPU_PR_CH_IPU_HEIGHT_MASK;
+ reg |= IPU_PR_CH_IPU_HEIGHT_NUM(config->ipu_height);
+ prg_write(prg, reg, IPU_PR_CH_HEIGHT(prg_ch));
+
+ /* crop */
+ reg = prg_read(prg, IPU_PR_CROP_LINE);
+ reg &= ~IPU_PR_CROP_LINE_MASK(prg_ch);
+ reg |= IPU_PR_CROP_LINE_NUM(prg_ch, config->crop_line);
+ prg_write(prg, reg, IPU_PR_CROP_LINE);
+
+ /* buffer address */
+ reg = prg_read(prg, IPU_PR_CH_BADDR(prg_ch));
+ reg &= ~IPU_PR_CH_BADDR_MASK;
+ reg |= config->baddr;
+ prg_write(prg, reg, IPU_PR_CH_BADDR(prg_ch));
+
+ /* offset */
+ reg = prg_read(prg, IPU_PR_CH_OFFSET(prg_ch));
+ reg &= ~IPU_PR_CH_OFFSET_MASK;
+ reg |= config->offset;
+ prg_write(prg, reg, IPU_PR_CH_OFFSET(prg_ch));
+
+ /* threshold */
+ reg = prg_read(prg, IPU_PR_ADDR_THD);
+ reg &= ~IPU_PR_ADDR_THD_MASK;
+ reg |= prg->memory;
+ prg_write(prg, reg, IPU_PR_ADDR_THD);
+
+ /* shadow enable */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg |= IPU_PR_CTRL_SHADOW_EN;
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* register update */
+ reg = prg_read(prg, IPU_PR_REG_UPDATE);
+ reg |= IPU_PR_REG_UPDATE_EN;
+ prg_write(prg, reg, IPU_PR_REG_UPDATE);
+ spin_unlock(&prg->lock);
+
+ clk_disable_unprepare(prg->apb_clk);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_prg_config);
+
+int ipu_prg_disable(unsigned int ipu_id, unsigned int pre_num)
+{
+ struct ipu_prg_data *prg = get_prg(ipu_id);
+ int prg_ch;
+ u32 reg;
+
+ if (!prg)
+ return -EINVAL;
+
+ prg_ch = get_prg_chan(prg, pre_num);
+ if (prg_ch < 0)
+ return prg_ch;
+
+ clk_prepare_enable(prg->apb_clk);
+
+ spin_lock(&prg->lock);
+ /* clear all load enable to impact other channels */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg &= ~IPU_PR_CTRL_CH_CNT_LOAD_EN_MASK;
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* counter load enable */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg |= IPU_PR_CTRL_CH_CNT_LOAD_EN(prg_ch);
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* enable bypass */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg |= IPU_PR_CTRL_CH_BYPASS(prg_ch);
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* shadow enable */
+ reg = prg_read(prg, IPU_PR_CTRL);
+ reg |= IPU_PR_CTRL_SHADOW_EN;
+ prg_write(prg, reg, IPU_PR_CTRL);
+
+ /* register update */
+ reg = prg_read(prg, IPU_PR_REG_UPDATE);
+ reg |= IPU_PR_REG_UPDATE_EN;
+ prg_write(prg, reg, IPU_PR_REG_UPDATE);
+ spin_unlock(&prg->lock);
+
+ clk_disable_unprepare(prg->apb_clk);
+ clk_disable_unprepare(prg->axi_clk);
+
+ mutex_lock(&prg->chan[prg_ch].mutex);
+ prg->chan[prg_ch].in_use = false;
+ mutex_unlock(&prg->chan[prg_ch].mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_prg_disable);
+
+int ipu_prg_wait_buf_ready(unsigned int ipu_id, unsigned int pre_num,
+ unsigned int hsk_line_num,
+ int pre_store_out_height)
+{
+ struct ipu_prg_data *prg = get_prg(ipu_id);
+ int prg_ch, timeout = 1000;
+ u32 reg;
+
+ if (!prg)
+ return -EINVAL;
+
+ prg_ch = get_prg_chan(prg, pre_num);
+ if (prg_ch < 0)
+ return prg_ch;
+
+ clk_prepare_enable(prg->apb_clk);
+
+ spin_lock(&prg->lock);
+ if (pre_store_out_height <= (4 << hsk_line_num)) {
+ do {
+ reg = prg_read(prg, IPU_PR_STATUS);
+ udelay(1000);
+ timeout--;
+ } while (!(reg & IPU_PR_STATUS_BUF_RDY(prg_ch, 0)) && timeout);
+ } else {
+ do {
+ reg = prg_read(prg, IPU_PR_STATUS);
+ udelay(1000);
+ timeout--;
+ } while ((!(reg & IPU_PR_STATUS_BUF_RDY(prg_ch, 0)) ||
+ !(reg & IPU_PR_STATUS_BUF_RDY(prg_ch, 1))) && timeout);
+ }
+ spin_unlock(&prg->lock);
+
+ clk_disable_unprepare(prg->apb_clk);
+
+ if (!timeout)
+ dev_err(prg->dev, "wait for buffer ready timeout\n");
+
+ return 0;
+}
+EXPORT_SYMBOL(ipu_prg_wait_buf_ready);
+
+static int ipu_prg_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node, *memory;
+ struct ipu_prg_data *prg;
+ struct resource *res;
+ struct reg_field reg_field0 = REG_FIELD(IOMUXC_GPR5,
+ IMX6Q_GPR5_PRE_PRG_SEL0_LSB,
+ IMX6Q_GPR5_PRE_PRG_SEL0_MSB);
+ struct reg_field reg_field1 = REG_FIELD(IOMUXC_GPR5,
+ IMX6Q_GPR5_PRE_PRG_SEL1_LSB,
+ IMX6Q_GPR5_PRE_PRG_SEL1_MSB);
+ int id, i;
+
+ prg = devm_kzalloc(&pdev->dev, sizeof(*prg), GFP_KERNEL);
+ if (!prg)
+ return -ENOMEM;
+ prg->dev = &pdev->dev;
+
+ for (i = 0; i < PRG_CHAN_NUM; i++)
+ mutex_init(&prg->chan[i].mutex);
+
+ spin_lock_init(&prg->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ prg->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(prg->base))
+ return PTR_ERR(prg->base);
+
+ prg->axi_clk = devm_clk_get(&pdev->dev, "axi");
+ if (IS_ERR(prg->axi_clk)) {
+ dev_err(&pdev->dev, "failed to get the axi clk\n");
+ return PTR_ERR(prg->axi_clk);
+ }
+
+ prg->apb_clk = devm_clk_get(&pdev->dev, "apb");
+ if (IS_ERR(prg->apb_clk)) {
+ dev_err(&pdev->dev, "failed to get the apb clk\n");
+ return PTR_ERR(prg->apb_clk);
+ }
+
+ prg->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
+ if (IS_ERR(prg->regmap)) {
+ dev_err(&pdev->dev, "failed to get regmap\n");
+ return PTR_ERR(prg->regmap);
+ }
+
+ prg->pre_prg_sel[0] = devm_regmap_field_alloc(&pdev->dev, prg->regmap,
+ reg_field0);
+ if (IS_ERR(prg->pre_prg_sel[0]))
+ return PTR_ERR(prg->pre_prg_sel[0]);
+
+ prg->pre_prg_sel[1] = devm_regmap_field_alloc(&pdev->dev, prg->regmap,
+ reg_field1);
+ if (IS_ERR(prg->pre_prg_sel[1]))
+ return PTR_ERR(prg->pre_prg_sel[1]);
+
+ memory = of_parse_phandle(np, "memory-region", 0);
+ if (!memory)
+ return -ENODEV;
+
+ prg->memory = of_translate_address(memory,
+ of_get_address(memory, 0, NULL, NULL));
+
+ id = of_alias_get_id(np, "prg");
+ if (id < 0) {
+ dev_err(&pdev->dev, "failed to get PRG id\n");
+ return id;
+ }
+ prg->id = id;
+
+ mutex_lock(&prg_lock);
+ list_add_tail(&prg->list, &prg_list);
+ mutex_unlock(&prg_lock);
+
+ platform_set_drvdata(pdev, prg);
+
+ dev_info(&pdev->dev, "driver probed\n");
+
+ return 0;
+}
+
+static int ipu_prg_remove(struct platform_device *pdev)
+{
+ struct ipu_prg_data *prg = platform_get_drvdata(pdev);
+
+ mutex_lock(&prg_lock);
+ list_del(&prg->list);
+ mutex_unlock(&prg_lock);
+
+ return 0;
+}
+
+static const struct of_device_id imx_ipu_prg_dt_ids[] = {
+ { .compatible = "fsl,imx6q-prg", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_ipu_prg_dt_ids);
+
+static struct platform_driver ipu_prg_driver = {
+ .driver = {
+ .name = "imx-prg",
+ .of_match_table = of_match_ptr(imx_ipu_prg_dt_ids),
+ },
+ .probe = ipu_prg_probe,
+ .remove = ipu_prg_remove,
+};
+
+static int __init ipu_prg_init(void)
+{
+ return platform_driver_register(&ipu_prg_driver);
+}
+subsys_initcall(ipu_prg_init);
+
+static void __exit ipu_prg_exit(void)
+{
+ platform_driver_unregister(&ipu_prg_driver);
+}
+module_exit(ipu_prg_exit);
+
+MODULE_DESCRIPTION("i.MX PRG driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mxc/ipu3/vdoa.c b/drivers/mxc/ipu3/vdoa.c
new file mode 100644
index 000000000000..68194c9158f1
--- /dev/null
+++ b/drivers/mxc/ipu3/vdoa.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2012-2015 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
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ipu.h>
+#include <linux/genalloc.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "vdoa.h"
+/* 6band(3field* double buffer) * (width*2) * bandline(8)
+ = 6x1024x2x8 = 96k or 72k(1.5byte) */
+#define MAX_VDOA_IRAM_SIZE (1024*96)
+#define VDOA_IRAM_SIZE (1024*72)
+
+#define VDOAC_BAND_HEIGHT_32LINES (32)
+#define VDOAC_BAND_HEIGHT_16LINES (16)
+#define VDOAC_BAND_HEIGHT_8LINES (8)
+#define VDOAC_THREE_FRAMES (0x1 << 2)
+#define VDOAC_SYNC_BAND_MODE (0x1 << 3)
+#define VDOAC_SCAN_ORDER_INTERLACED (0x1 << 4)
+#define VDOAC_PFS_YUYV (0x1 << 5)
+#define VDOAC_IPU_SEL_1 (0x1 << 6)
+#define VDOAFP_FH_MASK (0x1FFF)
+#define VDOAFP_FH_SHIFT (16)
+#define VDOAFP_FW_MASK (0x3FFF)
+#define VDOAFP_FW_SHIFT (0)
+#define VDOASL_VSLY_MASK (0x3FFF)
+#define VDOASL_VSLY_SHIFT (16)
+#define VDOASL_ISLY_MASK (0x7FFF)
+#define VDOASL_ISLY_SHIFT (0)
+#define VDOASRR_START_XFER (0x2)
+#define VDOASRR_SWRST (0x1)
+#define VDOAIEIST_TRANSFER_ERR (0x2)
+#define VDOAIEIST_TRANSFER_END (0x1)
+
+#define VDOAC (0x0) /* Control Register */
+#define VDOASRR (0x4) /* Start and Reset Register */
+#define VDOAIE (0x8) /* Interrupt Enable Register */
+#define VDOAIST (0xc) /* Interrupt Status Register */
+#define VDOAFP (0x10) /* Frame Parameters Register */
+#define VDOAIEBA00 (0x14) /* External Buffer n Frame m Address Register */
+#define VDOAIEBA01 (0x18) /* External Buffer n Frame m Address Register */
+#define VDOAIEBA02 (0x1c) /* External Buffer n Frame m Address Register */
+#define VDOAIEBA10 (0x20) /* External Buffer n Frame m Address Register */
+#define VDOAIEBA11 (0x24) /* External Buffer n Frame m Address Register */
+#define VDOAIEBA12 (0x28) /* External Buffer n Frame m Address Register */
+#define VDOASL (0x2c) /* IPU Stride Line Register */
+#define VDOAIUBO (0x30) /* IPU Chroma Buffer Offset Register */
+#define VDOAVEBA0 (0x34) /* External Buffer m Address Register */
+#define VDOAVEBA1 (0x38) /* External Buffer m Address Register */
+#define VDOAVEBA2 (0x3c) /* External Buffer m Address Register */
+#define VDOAVUBO (0x40) /* VPU Chroma Buffer Offset */
+#define VDOASR (0x44) /* Status Register */
+#define VDOATD (0x48) /* Test Debug Register */
+
+
+enum {
+ VDOA_INIT = 0x1,
+ VDOA_GET = 0x2,
+ VDOA_SETUP = 0x4,
+ VDOA_GET_OBUF = 0x8,
+ VDOA_START = 0x10,
+ VDOA_INIRQ = 0x20,
+ VDOA_STOP = 0x40,
+ VDOA_PUT = VDOA_INIT,
+};
+
+enum {
+ VDOA_NULL = 0,
+ VDOA_FRAME = 1,
+ VDOA_PREV_FIELD = 2,
+ VDOA_CURR_FIELD = 3,
+ VDOA_NEXT_FIELD = 4,
+};
+
+#define CHECK_STATE(expect, retcode) \
+do { \
+ if (!((expect) & vdoa->state)) { \
+ dev_err(vdoa->dev, "ERR: %s state:0x%x, expect:0x%x.\n",\
+ __func__, vdoa->state, (expect)); \
+ retcode; \
+ } \
+} while (0)
+
+#define CHECK_NULL_PTR(ptr) \
+do { \
+ pr_debug("vdoa_ptr:0x%p in %s state:0x%x.\n", \
+ vdoa, __func__, vdoa->state); \
+ if (NULL == (ptr)) { \
+ pr_err("ERR vdoa: %s state:0x%x null ptr.\n", \
+ __func__, vdoa->state); \
+ } \
+} while (0)
+
+struct vdoa_info {
+ int state;
+ struct device *dev;
+ struct clk *vdoa_clk;
+ void __iomem *reg_base;
+ struct gen_pool *iram_pool;
+ unsigned long iram_base;
+ unsigned long iram_paddr;
+ int irq;
+ int field;
+ struct completion comp;
+};
+
+static struct vdoa_info *g_vdoa;
+static unsigned long iram_size;
+static DEFINE_MUTEX(vdoa_lock);
+
+static inline void vdoa_read_register(struct vdoa_info *vdoa,
+ u32 reg, u32 *val)
+{
+ *val = ioread32(vdoa->reg_base + reg);
+ dev_dbg(vdoa->dev, "read_reg:0x%02x, val:0x%08x.\n", reg, *val);
+}
+
+static inline void vdoa_write_register(struct vdoa_info *vdoa,
+ u32 reg, u32 val)
+{
+ iowrite32(val, vdoa->reg_base + reg);
+ dev_dbg(vdoa->dev, "\t\twrite_reg:0x%02x, val:0x%08x.\n", reg, val);
+}
+
+static void dump_registers(struct vdoa_info *vdoa)
+{
+ int i;
+ u32 data;
+
+ for (i = VDOAC; i < VDOATD; i += 4)
+ vdoa_read_register(vdoa, i, &data);
+}
+
+int vdoa_setup(vdoa_handle_t handle, struct vdoa_params *params)
+{
+ int band_size;
+ int total_band_size = 0;
+ int ipu_stride;
+ u32 data;
+ struct vdoa_info *vdoa = (struct vdoa_info *)handle;
+
+ CHECK_NULL_PTR(vdoa);
+ CHECK_STATE(VDOA_GET | VDOA_GET_OBUF | VDOA_STOP, return -EINVAL);
+ if (VDOA_GET == vdoa->state) {
+ dev_dbg(vdoa->dev, "w:%d, h:%d.\n",
+ params->width, params->height);
+ data = (params->band_lines == VDOAC_BAND_HEIGHT_32LINES) ? 2 :
+ ((params->band_lines == VDOAC_BAND_HEIGHT_16LINES) ?
+ 1 : 0);
+ data |= params->scan_order ? VDOAC_SCAN_ORDER_INTERLACED : 0;
+ data |= params->band_mode ? VDOAC_SYNC_BAND_MODE : 0;
+ data |= params->pfs ? VDOAC_PFS_YUYV : 0;
+ data |= params->ipu_num ? VDOAC_IPU_SEL_1 : 0;
+ vdoa_write_register(vdoa, VDOAC, data);
+
+ data = ((params->width & VDOAFP_FW_MASK) << VDOAFP_FW_SHIFT) |
+ ((params->height & VDOAFP_FH_MASK) << VDOAFP_FH_SHIFT);
+ vdoa_write_register(vdoa, VDOAFP, data);
+
+ ipu_stride = params->pfs ? params->width << 1 : params->width;
+ data = ((params->vpu_stride & VDOASL_VSLY_MASK) <<
+ VDOASL_VSLY_SHIFT) |
+ ((ipu_stride & VDOASL_ISLY_MASK) << VDOASL_ISLY_SHIFT);
+ vdoa_write_register(vdoa, VDOASL, data);
+
+ dev_dbg(vdoa->dev, "band_mode:%d, band_line:%d, base:0x%lx.\n",
+ params->band_mode, params->band_lines, vdoa->iram_paddr);
+ }
+ /*
+ * band size = (luma_per_line + chroma_per_line) * bandLines
+ * = width * (3/2 or 2) * bandLines
+ * double buffer mode used.
+ */
+ if (params->pfs)
+ band_size = (params->width << 1) * params->band_lines;
+ else
+ band_size = ((params->width * 3) >> 1) *
+ params->band_lines;
+ if (params->interlaced) {
+ total_band_size = 6 * band_size; /* 3 frames*double buffer */
+ if (iram_size < total_band_size) {
+ dev_err(vdoa->dev, "iram_size:0x%lx is smaller than "
+ "request:0x%x!\n", iram_size, total_band_size);
+ return -EINVAL;
+ }
+ if (params->vfield_buf.prev_veba) {
+ if (params->band_mode) {
+ vdoa_write_register(vdoa, VDOAIEBA00,
+ vdoa->iram_paddr);
+ vdoa_write_register(vdoa, VDOAIEBA10,
+ vdoa->iram_paddr + band_size);
+ } else
+ vdoa_write_register(vdoa, VDOAIEBA00,
+ params->ieba0);
+ vdoa_write_register(vdoa, VDOAVEBA0,
+ params->vfield_buf.prev_veba);
+ vdoa->field = VDOA_PREV_FIELD;
+ }
+ if (params->vfield_buf.cur_veba) {
+ if (params->band_mode) {
+ vdoa_write_register(vdoa, VDOAIEBA01,
+ vdoa->iram_paddr + band_size * 2);
+ vdoa_write_register(vdoa, VDOAIEBA11,
+ vdoa->iram_paddr + band_size * 3);
+ } else
+ vdoa_write_register(vdoa, VDOAIEBA01,
+ params->ieba1);
+ vdoa_write_register(vdoa, VDOAVEBA1,
+ params->vfield_buf.cur_veba);
+ vdoa->field = VDOA_CURR_FIELD;
+ }
+ if (params->vfield_buf.next_veba) {
+ if (params->band_mode) {
+ vdoa_write_register(vdoa, VDOAIEBA02,
+ vdoa->iram_paddr + band_size * 4);
+ vdoa_write_register(vdoa, VDOAIEBA12,
+ vdoa->iram_paddr + band_size * 5);
+ } else
+ vdoa_write_register(vdoa, VDOAIEBA02,
+ params->ieba2);
+ vdoa_write_register(vdoa, VDOAVEBA2,
+ params->vfield_buf.next_veba);
+ vdoa->field = VDOA_NEXT_FIELD;
+ vdoa_read_register(vdoa, VDOAC, &data);
+ data |= VDOAC_THREE_FRAMES;
+ vdoa_write_register(vdoa, VDOAC, data);
+ }
+
+ if (!params->pfs)
+ vdoa_write_register(vdoa, VDOAIUBO,
+ params->width * params->band_lines);
+ vdoa_write_register(vdoa, VDOAVUBO,
+ params->vfield_buf.vubo);
+ dev_dbg(vdoa->dev, "total band_size:0x%x.\n", band_size*6);
+ } else if (params->band_mode) {
+ /* used for progressive frame resize on PrP channel */
+ BUG(); /* currently not support */
+ /* progressvie frame: band mode */
+ vdoa_write_register(vdoa, VDOAIEBA00, vdoa->iram_paddr);
+ vdoa_write_register(vdoa, VDOAIEBA10,
+ vdoa->iram_paddr + band_size);
+ if (!params->pfs)
+ vdoa_write_register(vdoa, VDOAIUBO,
+ params->width * params->band_lines);
+ dev_dbg(vdoa->dev, "total band_size:0x%x\n", band_size*2);
+ } else {
+ /* progressive frame: mem->mem, non-band mode */
+ vdoa->field = VDOA_FRAME;
+ vdoa_write_register(vdoa, VDOAVEBA0, params->vframe_buf.veba);
+ vdoa_write_register(vdoa, VDOAVUBO, params->vframe_buf.vubo);
+ vdoa_write_register(vdoa, VDOAIEBA00, params->ieba0);
+ if (!params->pfs)
+ /* note: iubo is relative value, based on ieba0 */
+ vdoa_write_register(vdoa, VDOAIUBO,
+ params->width * params->height);
+ }
+ vdoa->state = VDOA_SETUP;
+ return 0;
+}
+
+void vdoa_get_output_buf(vdoa_handle_t handle, struct vdoa_ipu_buf *buf)
+{
+ u32 data;
+ struct vdoa_info *vdoa = (struct vdoa_info *)handle;
+
+ CHECK_NULL_PTR(vdoa);
+ CHECK_STATE(VDOA_SETUP, return);
+ vdoa->state = VDOA_GET_OBUF;
+ memset(buf, 0, sizeof(*buf));
+
+ vdoa_read_register(vdoa, VDOAC, &data);
+ switch (vdoa->field) {
+ case VDOA_FRAME:
+ case VDOA_PREV_FIELD:
+ vdoa_read_register(vdoa, VDOAIEBA00, &buf->ieba0);
+ if (data & VDOAC_SYNC_BAND_MODE)
+ vdoa_read_register(vdoa, VDOAIEBA10, &buf->ieba1);
+ break;
+ case VDOA_CURR_FIELD:
+ vdoa_read_register(vdoa, VDOAIEBA01, &buf->ieba0);
+ vdoa_read_register(vdoa, VDOAIEBA11, &buf->ieba1);
+ break;
+ case VDOA_NEXT_FIELD:
+ vdoa_read_register(vdoa, VDOAIEBA02, &buf->ieba0);
+ vdoa_read_register(vdoa, VDOAIEBA12, &buf->ieba1);
+ break;
+ default:
+ BUG();
+ break;
+ }
+ if (!(data & VDOAC_PFS_YUYV))
+ vdoa_read_register(vdoa, VDOAIUBO, &buf->iubo);
+}
+
+int vdoa_start(vdoa_handle_t handle, int timeout_ms)
+{
+ int ret;
+ struct vdoa_info *vdoa = (struct vdoa_info *)handle;
+
+ CHECK_NULL_PTR(vdoa);
+ CHECK_STATE(VDOA_GET_OBUF, return -EINVAL);
+ vdoa->state = VDOA_START;
+ init_completion(&vdoa->comp);
+ vdoa_write_register(vdoa, VDOAIST,
+ VDOAIEIST_TRANSFER_ERR | VDOAIEIST_TRANSFER_END);
+ vdoa_write_register(vdoa, VDOAIE,
+ VDOAIEIST_TRANSFER_ERR | VDOAIEIST_TRANSFER_END);
+
+ enable_irq(vdoa->irq);
+ vdoa_write_register(vdoa, VDOASRR, VDOASRR_START_XFER);
+ dump_registers(vdoa);
+
+ ret = wait_for_completion_timeout(&vdoa->comp,
+ msecs_to_jiffies(timeout_ms));
+
+ return ret > 0 ? 0 : -ETIMEDOUT;
+}
+
+void vdoa_stop(vdoa_handle_t handle)
+{
+ struct vdoa_info *vdoa = (struct vdoa_info *)handle;
+
+ CHECK_NULL_PTR(vdoa);
+ CHECK_STATE(VDOA_GET | VDOA_START | VDOA_INIRQ, return);
+ vdoa->state = VDOA_STOP;
+
+ disable_irq(vdoa->irq);
+
+ vdoa_write_register(vdoa, VDOASRR, VDOASRR_SWRST);
+}
+
+void vdoa_get_handle(vdoa_handle_t *handle)
+{
+ struct vdoa_info *vdoa = g_vdoa;
+
+ CHECK_NULL_PTR(handle);
+ *handle = (vdoa_handle_t *)NULL;
+ CHECK_STATE(VDOA_INIT, return);
+ mutex_lock(&vdoa_lock);
+ clk_prepare_enable(vdoa->vdoa_clk);
+ vdoa->state = VDOA_GET;
+ vdoa->field = VDOA_NULL;
+ vdoa_write_register(vdoa, VDOASRR, VDOASRR_SWRST);
+
+ *handle = (vdoa_handle_t *)vdoa;
+}
+
+void vdoa_put_handle(vdoa_handle_t *handle)
+{
+ struct vdoa_info *vdoa = (struct vdoa_info *)(*handle);
+
+ CHECK_NULL_PTR(vdoa);
+ CHECK_STATE(VDOA_STOP, return);
+ if (vdoa != g_vdoa)
+ BUG();
+
+ clk_disable_unprepare(vdoa->vdoa_clk);
+ vdoa->state = VDOA_PUT;
+ *handle = (vdoa_handle_t *)NULL;
+ mutex_unlock(&vdoa_lock);
+}
+
+static irqreturn_t vdoa_irq_handler(int irq, void *data)
+{
+ u32 status, mask, val;
+ struct vdoa_info *vdoa = data;
+
+ CHECK_NULL_PTR(vdoa);
+ CHECK_STATE(VDOA_START, return IRQ_HANDLED);
+ vdoa->state = VDOA_INIRQ;
+ vdoa_read_register(vdoa, VDOAIST, &status);
+ vdoa_read_register(vdoa, VDOAIE, &mask);
+ val = status & mask;
+ vdoa_write_register(vdoa, VDOAIST, val);
+ if (VDOAIEIST_TRANSFER_ERR & val)
+ dev_err(vdoa->dev, "vdoa Transfer err irq!\n");
+ if (VDOAIEIST_TRANSFER_END & val)
+ dev_dbg(vdoa->dev, "vdoa Transfer end irq!\n");
+ if (0 == val) {
+ dev_err(vdoa->dev, "vdoa unknown irq!\n");
+ BUG();
+ }
+
+ complete(&vdoa->comp);
+ return IRQ_HANDLED;
+}
+
+/* IRAM Size in Kbytes, example:vdoa_iram_size=64, 64KBytes */
+static int __init vdoa_iram_size_setup(char *options)
+{
+ int ret;
+
+ ret = kstrtoul(options, 0, &iram_size);
+ if (ret)
+ iram_size = 0;
+ else
+ iram_size *= SZ_1K;
+
+ return 1;
+}
+__setup("vdoa_iram_size=", vdoa_iram_size_setup);
+
+static const struct of_device_id imx_vdoa_dt_ids[] = {
+ { .compatible = "fsl,imx6q-vdoa", },
+ { /* sentinel */ }
+};
+
+static int vdoa_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct vdoa_info *vdoa;
+ struct resource *res;
+ struct resource *res_irq;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "can't get device resources\n");
+ return -ENOENT;
+ }
+
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_irq) {
+ dev_err(dev, "failed to get irq resource\n");
+ return -ENOENT;
+ }
+
+ vdoa = devm_kzalloc(dev, sizeof(struct vdoa_info), GFP_KERNEL);
+ if (!vdoa)
+ return -ENOMEM;
+ vdoa->dev = dev;
+
+ vdoa->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (!vdoa->reg_base)
+ return -EBUSY;
+
+ vdoa->irq = res_irq->start;
+ ret = devm_request_irq(dev, vdoa->irq, vdoa_irq_handler, 0,
+ "vdoa", vdoa);
+ if (ret) {
+ dev_err(dev, "can't claim irq %d\n", vdoa->irq);
+ return ret;
+ }
+ disable_irq(vdoa->irq);
+
+ vdoa->vdoa_clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(vdoa->vdoa_clk)) {
+ dev_err(dev, "failed to get vdoa_clk\n");
+ return PTR_ERR(vdoa->vdoa_clk);
+ }
+
+ vdoa->iram_pool = of_gen_pool_get(np, "iram", 0);
+ if (!vdoa->iram_pool) {
+ dev_err(&pdev->dev, "iram pool not available\n");
+ return -ENOMEM;
+ }
+
+ if ((iram_size == 0) || (iram_size > MAX_VDOA_IRAM_SIZE))
+ iram_size = VDOA_IRAM_SIZE;
+
+ vdoa->iram_base = gen_pool_alloc(vdoa->iram_pool, iram_size);
+ if (!vdoa->iram_base) {
+ dev_err(&pdev->dev, "unable to alloc iram\n");
+ return -ENOMEM;
+ }
+
+ vdoa->iram_paddr = gen_pool_virt_to_phys(vdoa->iram_pool,
+ vdoa->iram_base);
+
+ dev_dbg(dev, "iram_base:0x%lx,iram_paddr:0x%lx,size:0x%lx\n",
+ vdoa->iram_base, vdoa->iram_paddr, iram_size);
+
+ vdoa->state = VDOA_INIT;
+ dev_set_drvdata(dev, vdoa);
+ g_vdoa = vdoa;
+ dev_info(dev, "i.MX Video Data Order Adapter(VDOA) driver probed\n");
+ return 0;
+}
+
+static int vdoa_remove(struct platform_device *pdev)
+{
+ struct vdoa_info *vdoa = dev_get_drvdata(&pdev->dev);
+
+ gen_pool_free(vdoa->iram_pool, vdoa->iram_base, iram_size);
+ kfree(vdoa);
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver vdoa_driver = {
+ .driver = {
+ .name = "mxc_vdoa",
+ .of_match_table = imx_vdoa_dt_ids,
+ },
+ .probe = vdoa_probe,
+ .remove = vdoa_remove,
+};
+
+static int __init vdoa_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&vdoa_driver);
+ if (err) {
+ pr_err("vdoa_driver register failed\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void __exit vdoa_cleanup(void)
+{
+ platform_driver_unregister(&vdoa_driver);
+}
+
+module_init(vdoa_init);
+module_exit(vdoa_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX Video Data Order Adapter(VDOA) driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mxc/ipu3/vdoa.h b/drivers/mxc/ipu3/vdoa.h
new file mode 100644
index 000000000000..3e4c7356cb26
--- /dev/null
+++ b/drivers/mxc/ipu3/vdoa.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012-2015 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
+ */
+
+#ifndef __VDOA_H__
+#define __VDOA_H__
+
+#define VDOA_PFS_YUYV (1)
+#define VDOA_PFS_NV12 (0)
+
+
+struct vfield_buf {
+ u32 prev_veba;
+ u32 cur_veba;
+ u32 next_veba;
+ u32 vubo;
+};
+
+struct vframe_buf {
+ u32 veba;
+ u32 vubo;
+};
+
+struct vdoa_params {
+ u32 width;
+ u32 height;
+ int vpu_stride;
+ int interlaced;
+ int scan_order;
+ int ipu_num;
+ int band_lines;
+ int band_mode;
+ int pfs;
+ u32 ieba0;
+ u32 ieba1;
+ u32 ieba2;
+ struct vframe_buf vframe_buf;
+ struct vfield_buf vfield_buf;
+};
+struct vdoa_ipu_buf {
+ u32 ieba0;
+ u32 ieba1;
+ u32 iubo;
+};
+
+struct vdoa_info;
+typedef void *vdoa_handle_t;
+
+int vdoa_setup(vdoa_handle_t handle, struct vdoa_params *params);
+void vdoa_get_output_buf(vdoa_handle_t handle, struct vdoa_ipu_buf *buf);
+int vdoa_start(vdoa_handle_t handle, int timeout_ms);
+void vdoa_stop(vdoa_handle_t handle);
+void vdoa_get_handle(vdoa_handle_t *handle);
+void vdoa_put_handle(vdoa_handle_t *handle);
+#endif
diff --git a/drivers/mxc/mipi/Kconfig b/drivers/mxc/mipi/Kconfig
new file mode 100644
index 000000000000..4c85da374ed2
--- /dev/null
+++ b/drivers/mxc/mipi/Kconfig
@@ -0,0 +1,14 @@
+#
+# MIPI configuration
+#
+
+menu "MXC MIPI Support"
+
+config MXC_MIPI_CSI2
+ tristate "MIPI CSI2 support"
+ depends on (SOC_IMX6 || SOC_IMX7)
+ default n
+ ---help---
+ Say Y to get the MIPI CSI2 support.
+
+endmenu
diff --git a/drivers/mxc/mipi/Makefile b/drivers/mxc/mipi/Makefile
new file mode 100644
index 000000000000..98cda773bd28
--- /dev/null
+++ b/drivers/mxc/mipi/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the mipi interface driver
+#
+obj-$(CONFIG_MXC_MIPI_CSI2) += mxc_mipi_csi2.o
diff --git a/drivers/mxc/mipi/mxc_mipi_csi2.c b/drivers/mxc/mipi/mxc_mipi_csi2.c
new file mode 100644
index 000000000000..df45c364f144
--- /dev/null
+++ b/drivers/mxc/mipi/mxc_mipi_csi2.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2011-2014 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/module.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/fsl_devices.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include <linux/mipi_csi2.h>
+
+#include "mxc_mipi_csi2.h"
+
+static struct mipi_csi2_info *gmipi_csi2;
+
+void _mipi_csi2_lock(struct mipi_csi2_info *info)
+{
+ if (!in_irq() && !in_softirq())
+ mutex_lock(&info->mutex_lock);
+}
+
+void _mipi_csi2_unlock(struct mipi_csi2_info *info)
+{
+ if (!in_irq() && !in_softirq())
+ mutex_unlock(&info->mutex_lock);
+}
+
+static inline void mipi_csi2_write(struct mipi_csi2_info *info,
+ unsigned value, unsigned offset)
+{
+ writel(value, info->mipi_csi2_base + offset);
+}
+
+static inline unsigned int mipi_csi2_read(struct mipi_csi2_info *info,
+ unsigned offset)
+{
+ return readl(info->mipi_csi2_base + offset);
+}
+
+/*!
+ * This function is called to enable the mipi csi2 interface.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns setted value
+ */
+bool mipi_csi2_enable(struct mipi_csi2_info *info)
+{
+ bool status;
+
+ _mipi_csi2_lock(info);
+
+ if (!info->mipi_en) {
+ info->mipi_en = true;
+ clk_prepare_enable(info->cfg_clk);
+ clk_prepare_enable(info->dphy_clk);
+ } else
+ mipi_dbg("mipi csi2 already enabled!\n");
+
+ status = info->mipi_en;
+
+ _mipi_csi2_unlock(info);
+
+ return status;
+}
+EXPORT_SYMBOL(mipi_csi2_enable);
+
+/*!
+ * This function is called to disable the mipi csi2 interface.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns setted value
+ */
+bool mipi_csi2_disable(struct mipi_csi2_info *info)
+{
+ bool status;
+
+ _mipi_csi2_lock(info);
+
+ if (info->mipi_en) {
+ info->mipi_en = false;
+ clk_disable_unprepare(info->dphy_clk);
+ clk_disable_unprepare(info->cfg_clk);
+ } else
+ mipi_dbg("mipi csi2 already disabled!\n");
+
+ status = info->mipi_en;
+
+ _mipi_csi2_unlock(info);
+
+ return status;
+}
+EXPORT_SYMBOL(mipi_csi2_disable);
+
+/*!
+ * This function is called to get mipi csi2 disable/enable status.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns mipi csi2 status
+ */
+bool mipi_csi2_get_status(struct mipi_csi2_info *info)
+{
+ bool status;
+
+ _mipi_csi2_lock(info);
+ status = info->mipi_en;
+ _mipi_csi2_unlock(info);
+
+ return status;
+}
+EXPORT_SYMBOL(mipi_csi2_get_status);
+
+/*!
+ * This function is called to set mipi lanes.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns setted value
+ */
+unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info)
+{
+ unsigned int lanes;
+
+ _mipi_csi2_lock(info);
+ mipi_csi2_write(info, info->lanes - 1, MIPI_CSI2_N_LANES);
+ lanes = mipi_csi2_read(info, MIPI_CSI2_N_LANES);
+ _mipi_csi2_unlock(info);
+
+ return lanes;
+}
+EXPORT_SYMBOL(mipi_csi2_set_lanes);
+
+/*!
+ * This function is called to set mipi data type.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns setted value
+ */
+unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info,
+ unsigned int datatype)
+{
+ unsigned int dtype;
+
+ _mipi_csi2_lock(info);
+ info->datatype = datatype;
+ dtype = info->datatype;
+ _mipi_csi2_unlock(info);
+
+ return dtype;
+}
+EXPORT_SYMBOL(mipi_csi2_set_datatype);
+
+/*!
+ * This function is called to get mipi data type.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns mipi data type
+ */
+unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info)
+{
+ unsigned int dtype;
+
+ _mipi_csi2_lock(info);
+ dtype = info->datatype;
+ _mipi_csi2_unlock(info);
+
+ return dtype;
+}
+EXPORT_SYMBOL(mipi_csi2_get_datatype);
+
+/*!
+ * This function is called to get mipi csi2 dphy status.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns dphy status
+ */
+unsigned int mipi_csi2_dphy_status(struct mipi_csi2_info *info)
+{
+ unsigned int status;
+
+ _mipi_csi2_lock(info);
+ status = mipi_csi2_read(info, MIPI_CSI2_PHY_STATE);
+ _mipi_csi2_unlock(info);
+
+ return status;
+}
+EXPORT_SYMBOL(mipi_csi2_dphy_status);
+
+/*!
+ * This function is called to get mipi csi2 error1 status.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns error1 value
+ */
+unsigned int mipi_csi2_get_error1(struct mipi_csi2_info *info)
+{
+ unsigned int err1;
+
+ _mipi_csi2_lock(info);
+ err1 = mipi_csi2_read(info, MIPI_CSI2_ERR1);
+ _mipi_csi2_unlock(info);
+
+ return err1;
+}
+EXPORT_SYMBOL(mipi_csi2_get_error1);
+
+/*!
+ * This function is called to get mipi csi2 error1 status.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns error1 value
+ */
+unsigned int mipi_csi2_get_error2(struct mipi_csi2_info *info)
+{
+ unsigned int err2;
+
+ _mipi_csi2_lock(info);
+ err2 = mipi_csi2_read(info, MIPI_CSI2_ERR2);
+ _mipi_csi2_unlock(info);
+
+ return err2;
+}
+EXPORT_SYMBOL(mipi_csi2_get_error2);
+
+/*!
+ * This function is called to enable mipi to ipu pixel clock.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns 0 on success or negative error code on fail
+ */
+int mipi_csi2_pixelclk_enable(struct mipi_csi2_info *info)
+{
+ return clk_prepare_enable(info->pixel_clk);
+}
+EXPORT_SYMBOL(mipi_csi2_pixelclk_enable);
+
+/*!
+ * This function is called to disable mipi to ipu pixel clock.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns 0 on success or negative error code on fail
+ */
+void mipi_csi2_pixelclk_disable(struct mipi_csi2_info *info)
+{
+ clk_disable_unprepare(info->pixel_clk);
+}
+EXPORT_SYMBOL(mipi_csi2_pixelclk_disable);
+
+/*!
+ * This function is called to power on mipi csi2.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns 0 on success or negative error code on fail
+ */
+int mipi_csi2_reset(struct mipi_csi2_info *info)
+{
+ _mipi_csi2_lock(info);
+
+ mipi_csi2_write(info, 0x0, MIPI_CSI2_PHY_SHUTDOWNZ);
+ mipi_csi2_write(info, 0x0, MIPI_CSI2_DPHY_RSTZ);
+ mipi_csi2_write(info, 0x0, MIPI_CSI2_CSI2_RESETN);
+
+ mipi_csi2_write(info, 0x00000001, MIPI_CSI2_PHY_TST_CTRL0);
+ mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL1);
+ mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
+ mipi_csi2_write(info, 0x00000002, MIPI_CSI2_PHY_TST_CTRL0);
+ mipi_csi2_write(info, 0x00010044, MIPI_CSI2_PHY_TST_CTRL1);
+ mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
+ mipi_csi2_write(info, 0x00000014, MIPI_CSI2_PHY_TST_CTRL1);
+ mipi_csi2_write(info, 0x00000002, MIPI_CSI2_PHY_TST_CTRL0);
+ mipi_csi2_write(info, 0x00000000, MIPI_CSI2_PHY_TST_CTRL0);
+
+ mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_PHY_SHUTDOWNZ);
+ mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_DPHY_RSTZ);
+ mipi_csi2_write(info, 0xffffffff, MIPI_CSI2_CSI2_RESETN);
+
+ _mipi_csi2_unlock(info);
+
+ return 0;
+}
+EXPORT_SYMBOL(mipi_csi2_reset);
+
+/*!
+ * This function is called to get mipi csi2 info.
+ *
+ * @return Returns mipi csi2 info struct pointor
+ */
+struct mipi_csi2_info *mipi_csi2_get_info(void)
+{
+ return gmipi_csi2;
+}
+EXPORT_SYMBOL(mipi_csi2_get_info);
+
+/*!
+ * This function is called to get mipi csi2 bind ipu num.
+ *
+ * @return Returns mipi csi2 bind ipu num
+ */
+int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info)
+{
+ int ipu_id;
+
+ _mipi_csi2_lock(info);
+ ipu_id = info->ipu_id;
+ _mipi_csi2_unlock(info);
+
+ return ipu_id;
+}
+EXPORT_SYMBOL(mipi_csi2_get_bind_ipu);
+
+/*!
+ * This function is called to get mipi csi2 bind csi num.
+ *
+ * @return Returns mipi csi2 bind csi num
+ */
+unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info)
+{
+ unsigned int csi_id;
+
+ _mipi_csi2_lock(info);
+ csi_id = info->csi_id;
+ _mipi_csi2_unlock(info);
+
+ return csi_id;
+}
+EXPORT_SYMBOL(mipi_csi2_get_bind_csi);
+
+/*!
+ * This function is called to get mipi csi2 virtual channel.
+ *
+ * @return Returns mipi csi2 virtual channel num
+ */
+unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info)
+{
+ unsigned int v_channel;
+
+ _mipi_csi2_lock(info);
+ v_channel = info->v_channel;
+ _mipi_csi2_unlock(info);
+
+ return v_channel;
+}
+EXPORT_SYMBOL(mipi_csi2_get_virtual_channel);
+
+/**
+ * This function is called by the driver framework to initialize the MIPI CSI2
+ * device.
+ *
+ * @param pdev The device structure for the MIPI CSI2 passed in by the
+ * driver framework.
+ *
+ * @return Returns 0 on success or negative error code on error
+ */
+static int mipi_csi2_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+ u32 mipi_csi2_dphy_ver;
+ int ret;
+
+ gmipi_csi2 = kmalloc(sizeof(struct mipi_csi2_info), GFP_KERNEL);
+ if (!gmipi_csi2) {
+ ret = -ENOMEM;
+ goto alloc_failed;
+ }
+
+ ret = of_property_read_u32(np, "ipu_id", &(gmipi_csi2->ipu_id));
+ if (ret) {
+ dev_err(&pdev->dev, "ipu_id missing or invalid\n");
+ goto err;
+ }
+
+ ret = of_property_read_u32(np, "csi_id", &(gmipi_csi2->csi_id));
+ if (ret) {
+ dev_err(&pdev->dev, "csi_id missing or invalid\n");
+ goto err;
+ }
+
+ ret = of_property_read_u32(np, "v_channel", &(gmipi_csi2->v_channel));
+ if (ret) {
+ dev_err(&pdev->dev, "v_channel missing or invalid\n");
+ goto err;
+ }
+
+ ret = of_property_read_u32(np, "lanes", &(gmipi_csi2->lanes));
+ if (ret) {
+ dev_err(&pdev->dev, "lanes missing or invalid\n");
+ goto err;
+ }
+
+ if ((gmipi_csi2->ipu_id < 0) || (gmipi_csi2->ipu_id > 1) ||
+ (gmipi_csi2->csi_id > 1) || (gmipi_csi2->v_channel > 3) ||
+ (gmipi_csi2->lanes > 4)) {
+ dev_err(&pdev->dev, "invalid param for mipi csi2!\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* initialize mutex */
+ mutex_init(&gmipi_csi2->mutex_lock);
+
+ /* get mipi csi2 informaiton */
+ gmipi_csi2->pdev = pdev;
+ gmipi_csi2->mipi_en = false;
+
+ gmipi_csi2->cfg_clk = devm_clk_get(dev, "cfg_clk");
+ if (IS_ERR(gmipi_csi2->cfg_clk)) {
+ dev_err(&pdev->dev, "failed to get cfg_clk\n");
+ ret = PTR_ERR(gmipi_csi2->cfg_clk);
+ goto err;
+ }
+
+ /* get mipi dphy clk */
+ gmipi_csi2->dphy_clk = devm_clk_get(dev, "dphy_clk");
+ if (IS_ERR(gmipi_csi2->dphy_clk)) {
+ dev_err(&pdev->dev, "failed to get dphy pll_ref_clk\n");
+ ret = PTR_ERR(gmipi_csi2->dphy_clk);
+ goto err;
+ }
+
+ /* get mipi to ipu pixel clk */
+ gmipi_csi2->pixel_clk = devm_clk_get(dev, "pixel_clk");
+ if (IS_ERR(gmipi_csi2->pixel_clk)) {
+ dev_err(&pdev->dev, "failed to get mipi pixel clk\n");
+ ret = PTR_ERR(gmipi_csi2->pixel_clk);
+ goto err;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ /* mipi register mapping */
+ gmipi_csi2->mipi_csi2_base = ioremap(res->start, PAGE_SIZE);
+ if (!gmipi_csi2->mipi_csi2_base) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* mipi dphy clk enable for register access */
+ clk_prepare_enable(gmipi_csi2->dphy_clk);
+ /* get mipi csi2 dphy version */
+ mipi_csi2_dphy_ver = mipi_csi2_read(gmipi_csi2, MIPI_CSI2_VERSION);
+
+ clk_disable_unprepare(gmipi_csi2->dphy_clk);
+
+ platform_set_drvdata(pdev, gmipi_csi2);
+
+ dev_info(&pdev->dev, "i.MX MIPI CSI2 driver probed\n");
+ dev_info(&pdev->dev, "i.MX MIPI CSI2 dphy version is 0x%x\n",
+ mipi_csi2_dphy_ver);
+
+ return 0;
+
+err:
+ kfree(gmipi_csi2);
+alloc_failed:
+ dev_err(&pdev->dev, "i.MX MIPI CSI2 driver probed - error\n");
+ return ret;
+}
+
+static int mipi_csi2_remove(struct platform_device *pdev)
+{
+ /* unmapping mipi register */
+ iounmap(gmipi_csi2->mipi_csi2_base);
+
+ kfree(gmipi_csi2);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id imx_mipi_csi2_dt_ids[] = {
+ { .compatible = "fsl,imx6q-mipi-csi2", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver mipi_csi2_driver = {
+ .driver = {
+ .name = "mxc_mipi_csi2",
+ .of_match_table = imx_mipi_csi2_dt_ids,
+ },
+ .probe = mipi_csi2_probe,
+ .remove = mipi_csi2_remove,
+};
+
+static int __init mipi_csi2_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&mipi_csi2_driver);
+ if (err) {
+ pr_err("mipi_csi2_driver register failed\n");
+ return -ENODEV;
+ }
+
+ pr_info("MIPI CSI2 driver module loaded\n");
+
+ return 0;
+}
+
+static void __exit mipi_csi2_cleanup(void)
+{
+ platform_driver_unregister(&mipi_csi2_driver);
+}
+
+subsys_initcall(mipi_csi2_init);
+module_exit(mipi_csi2_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX MIPI CSI2 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mxc/mipi/mxc_mipi_csi2.h b/drivers/mxc/mipi/mxc_mipi_csi2.h
new file mode 100644
index 000000000000..291d7e891e09
--- /dev/null
+++ b/drivers/mxc/mipi/mxc_mipi_csi2.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+#ifndef __MXC_MIPI_CSI2_H__
+#define __MXC_MIPI_CSI2_H__
+
+#ifdef DEBUG
+#define mipi_dbg(fmt, ...) \
+ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define mipi_dbg(fmt, ...)
+#endif
+
+/* driver private data */
+struct mipi_csi2_info {
+ bool mipi_en;
+ int ipu_id;
+ unsigned int csi_id;
+ unsigned int v_channel;
+ unsigned int lanes;
+ unsigned int datatype;
+ struct clk *cfg_clk;
+ struct clk *dphy_clk;
+ struct clk *pixel_clk;
+ void __iomem *mipi_csi2_base;
+ struct platform_device *pdev;
+
+ struct mutex mutex_lock;
+};
+
+#endif
diff --git a/drivers/mxc/mlb/Kconfig b/drivers/mxc/mlb/Kconfig
new file mode 100644
index 000000000000..a988c5a61731
--- /dev/null
+++ b/drivers/mxc/mlb/Kconfig
@@ -0,0 +1,17 @@
+#
+# MLB150 configuration
+#
+
+menu "MXC Media Local Bus Driver"
+
+config MXC_MLB
+ boolean
+
+config MXC_MLB150
+ tristate "MLB150 support"
+ depends on (SOC_IMX6Q || SOC_IMX6SX)
+ select MXC_MLB
+ ---help---
+ Say Y to get the MLB150 support.
+
+endmenu
diff --git a/drivers/mxc/mlb/Makefile b/drivers/mxc/mlb/Makefile
new file mode 100644
index 000000000000..e71005a3788f
--- /dev/null
+++ b/drivers/mxc/mlb/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the i.MX6Q/DL MLB150 driver
+#
+
+obj-$(CONFIG_MXC_MLB150) += mxc_mlb.o
diff --git a/drivers/mxc/mlb/mxc_mlb.c b/drivers/mxc/mlb/mxc_mlb.c
new file mode 100755
index 000000000000..f935ab8cb848
--- /dev/null
+++ b/drivers/mxc/mlb/mxc_mlb.c
@@ -0,0 +1,2809 @@
+/*
+ * Copyright (C) 2011-2014 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/cdev.h>
+#include <linux/circ_buf.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/genalloc.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mxc_mlb.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/regulator/consumer.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+
+#define DRIVER_NAME "mxc_mlb150"
+
+/*
+ * MLB module memory map registers define
+ */
+#define REG_MLBC0 0x0
+#define MLBC0_MLBEN (0x1)
+#define MLBC0_MLBCLK_MASK (0x7 << 2)
+#define MLBC0_MLBCLK_SHIFT (2)
+#define MLBC0_MLBPEN (0x1 << 5)
+#define MLBC0_MLBLK (0x1 << 7)
+#define MLBC0_ASYRETRY (0x1 << 12)
+#define MLBC0_CTLRETRY (0x1 << 12)
+#define MLBC0_FCNT_MASK (0x7 << 15)
+#define MLBC0_FCNT_SHIFT (15)
+
+#define REG_MLBPC0 0x8
+#define MLBPC0_MCLKHYS (0x1 << 11)
+
+#define REG_MS0 0xC
+#define REG_MS1 0x14
+
+#define REG_MSS 0x20
+#define MSS_RSTSYSCMD (0x1)
+#define MSS_LKSYSCMD (0x1 << 1)
+#define MSS_ULKSYSCMD (0x1 << 2)
+#define MSS_CSSYSCMD (0x1 << 3)
+#define MSS_SWSYSCMD (0x1 << 4)
+#define MSS_SERVREQ (0x1 << 5)
+
+#define REG_MSD 0x24
+
+#define REG_MIEN 0x2C
+#define MIEN_ISOC_PE (0x1)
+#define MIEN_ISOC_BUFO (0x1 << 1)
+#define MIEN_SYNC_PE (0x1 << 16)
+#define MIEN_ARX_DONE (0x1 << 17)
+#define MIEN_ARX_PE (0x1 << 18)
+#define MIEN_ARX_BREAK (0x1 << 19)
+#define MIEN_ATX_DONE (0x1 << 20)
+#define MIEN_ATX_PE (0x1 << 21)
+#define MIEN_ATX_BREAK (0x1 << 22)
+#define MIEN_CRX_DONE (0x1 << 24)
+#define MIEN_CRX_PE (0x1 << 25)
+#define MIEN_CRX_BREAK (0x1 << 26)
+#define MIEN_CTX_DONE (0x1 << 27)
+#define MIEN_CTX_PE (0x1 << 28)
+#define MIEN_CTX_BREAK (0x1 << 29)
+
+#define REG_MLBPC2 0x34
+#define REG_MLBPC1 0x38
+#define MLBPC1_VAL (0x00000888)
+
+#define REG_MLBC1 0x3C
+#define MLBC1_LOCK (0x1 << 6)
+#define MLBC1_CLKM (0x1 << 7)
+#define MLBC1_NDA_MASK (0xFF << 8)
+#define MLBC1_NDA_SHIFT (8)
+
+#define REG_HCTL 0x80
+#define HCTL_RST0 (0x1)
+#define HCTL_RST1 (0x1 << 1)
+#define HCTL_EN (0x1 << 15)
+
+#define REG_HCMR0 0x88
+#define REG_HCMR1 0x8C
+#define REG_HCER0 0x90
+#define REG_HCER1 0x94
+#define REG_HCBR0 0x98
+#define REG_HCBR1 0x9C
+
+#define REG_MDAT0 0xC0
+#define REG_MDAT1 0xC4
+#define REG_MDAT2 0xC8
+#define REG_MDAT3 0xCC
+
+#define REG_MDWE0 0xD0
+#define REG_MDWE1 0xD4
+#define REG_MDWE2 0xD8
+#define REG_MDWE3 0xDC
+
+#define REG_MCTL 0xE0
+#define MCTL_XCMP (0x1)
+
+#define REG_MADR 0xE4
+#define MADR_WNR (0x1 << 31)
+#define MADR_TB (0x1 << 30)
+#define MADR_ADDR_MASK (0x7f << 8)
+#define MADR_ADDR_SHIFT (0)
+
+#define REG_ACTL 0x3C0
+#define ACTL_MPB (0x1 << 4)
+#define ACTL_DMAMODE (0x1 << 2)
+#define ACTL_SMX (0x1 << 1)
+#define ACTL_SCE (0x1)
+
+#define REG_ACSR0 0x3D0
+#define REG_ACSR1 0x3D4
+#define REG_ACMR0 0x3D8
+#define REG_ACMR1 0x3DC
+
+#define REG_CAT_MDATn(ch) (REG_MDAT0 + ((ch % 8) >> 1) * 4)
+#define REG_CAT_MDWEn(ch) (REG_MDWE0 + ((ch % 8) >> 1) * 4)
+
+#define INT_AHB0_CH_START (0)
+#define INT_AHB1_CH_START (32)
+
+#define LOGIC_CH_NUM (64)
+#define BUF_CDT_OFFSET (0x0)
+#define BUF_ADT_OFFSET (0x40)
+#define BUF_CAT_MLB_OFFSET (0x80)
+#define BUF_CAT_HBI_OFFSET (0x88)
+#define BUF_CTR_END_OFFSET (0x8F)
+
+#define CAT_MODE_RX (0x1 << 0)
+#define CAT_MODE_TX (0x1 << 1)
+#define CAT_MODE_INBOUND_DMA (0x1 << 8)
+#define CAT_MODE_OUTBOUND_DMA (0x1 << 9)
+
+#define CH_SYNC_DEFAULT_QUAD (1)
+#define CH_SYNC_MAX_QUAD (15)
+#define CH_SYNC_CDT_BUF_DEP (CH_SYNC_DEFAULT_QUAD * 4 * 4)
+#define CH_SYNC_ADT_BUF_MULTI (4)
+#define CH_SYNC_ADT_BUF_DEP (CH_SYNC_CDT_BUF_DEP * CH_SYNC_ADT_BUF_MULTI)
+#define CH_SYNC_BUF_SZ (CH_SYNC_MAX_QUAD * 4 * 4 * \
+ CH_SYNC_ADT_BUF_MULTI)
+#define CH_CTRL_CDT_BUF_DEP (64)
+#define CH_CTRL_ADT_BUF_DEP (CH_CTRL_CDT_BUF_DEP)
+#define CH_CTRL_BUF_SZ (CH_CTRL_ADT_BUF_DEP)
+#define CH_ASYNC_MDP_PACKET_LEN (1024)
+#define CH_ASYNC_MEP_PACKET_LEN (1536)
+#define CH_ASYNC_CDT_BUF_DEP (CH_ASYNC_MEP_PACKET_LEN)
+#define CH_ASYNC_ADT_BUF_DEP (CH_ASYNC_CDT_BUF_DEP)
+#define CH_ASYNC_BUF_SZ (CH_ASYNC_ADT_BUF_DEP)
+#define CH_ISOC_BLK_SIZE_188 (188)
+#define CH_ISOC_BLK_SIZE_196 (196)
+#define CH_ISOC_BLK_SIZE (CH_ISOC_BLK_SIZE_188)
+#define CH_ISOC_BLK_NUM (1)
+#define CH_ISOC_CDT_BUF_DEP (CH_ISOC_BLK_SIZE * CH_ISOC_BLK_NUM)
+#define CH_ISOC_ADT_BUF_DEP (CH_ISOC_CDT_BUF_DEP)
+#define CH_ISOC_BUF_SZ (1024)
+
+#define CH_SYNC_DBR_BUF_OFFSET (0x0)
+#define CH_CTRL_DBR_BUF_OFFSET (CH_SYNC_DBR_BUF_OFFSET + \
+ 2 * (CH_SYNC_MAX_QUAD * 4 * 4))
+#define CH_ASYNC_DBR_BUF_OFFSET (CH_CTRL_DBR_BUF_OFFSET + \
+ 2 * CH_CTRL_CDT_BUF_DEP)
+#define CH_ISOC_DBR_BUF_OFFSET (CH_ASYNC_DBR_BUF_OFFSET + \
+ 2 * CH_ASYNC_CDT_BUF_DEP)
+
+#define DBR_BUF_START 0x00000
+
+#define CDT_LEN (16)
+#define ADT_LEN (16)
+#define CAT_LEN (2)
+
+#define CDT_SZ (CDT_LEN * LOGIC_CH_NUM)
+#define ADT_SZ (ADT_LEN * LOGIC_CH_NUM)
+#define CAT_SZ (CAT_LEN * LOGIC_CH_NUM * 2)
+
+#define CDT_BASE(base) (base + BUF_CDT_OFFSET)
+#define ADT_BASE(base) (base + BUF_ADT_OFFSET)
+#define CAT_MLB_BASE(base) (base + BUF_CAT_MLB_OFFSET)
+#define CAT_HBI_BASE(base) (base + BUF_CAT_HBI_OFFSET)
+
+#define CDTn_ADDR(base, n) (base + BUF_CDT_OFFSET + n * CDT_LEN)
+#define ADTn_ADDR(base, n) (base + BUF_ADT_OFFSET + n * ADT_LEN)
+#define CATn_MLB_ADDR(base, n) (base + BUF_CAT_MLB_OFFSET + n * CAT_LEN)
+#define CATn_HBI_ADDR(base, n) (base + BUF_CAT_HBI_OFFSET + n * CAT_LEN)
+
+#define CAT_CL_SHIFT (0x0)
+#define CAT_CT_SHIFT (8)
+#define CAT_CE (0x1 << 11)
+#define CAT_RNW (0x1 << 12)
+#define CAT_MT (0x1 << 13)
+#define CAT_FCE (0x1 << 14)
+#define CAT_MFE (0x1 << 14)
+
+#define CDT_WSBC_SHIFT (14)
+#define CDT_WPC_SHIFT (11)
+#define CDT_RSBC_SHIFT (30)
+#define CDT_RPC_SHIFT (27)
+#define CDT_WPC_1_SHIFT (12)
+#define CDT_RPC_1_SHIFT (28)
+#define CDT_WPTR_SHIFT (0)
+#define CDT_SYNC_WSTS_MASK (0x0000f000)
+#define CDT_SYNC_WSTS_SHIFT (12)
+#define CDT_CTRL_ASYNC_WSTS_MASK (0x0000f000)
+#define CDT_CTRL_ASYNC_WSTS_SHIFT (12)
+#define CDT_ISOC_WSTS_MASK (0x0000e000)
+#define CDT_ISOC_WSTS_SHIFT (13)
+#define CDT_RPTR_SHIFT (16)
+#define CDT_SYNC_RSTS_MASK (0xf0000000)
+#define CDT_SYNC_RSTS_SHIFT (28)
+#define CDT_CTRL_ASYNC_RSTS_MASK (0xf0000000)
+#define CDT_CTRL_ASYNC_RSTS_SHIFT (28)
+#define CDT_ISOC_RSTS_MASK (0xe0000000)
+#define CDT_ISOC_RSTS_SHIFT (29)
+#define CDT_CTRL_ASYNC_WSTS_1 (0x1 << 14)
+#define CDT_CTRL_ASYNC_RSTS_1 (0x1 << 15)
+#define CDT_BD_SHIFT (0)
+#define CDT_BA_SHIFT (16)
+#define CDT_BS_SHIFT (0)
+#define CDT_BF_SHIFT (31)
+
+#define ADT_PG (0x1 << 13)
+#define ADT_LE (0x1 << 14)
+#define ADT_CE (0x1 << 15)
+#define ADT_BD1_SHIFT (0)
+#define ADT_ERR1 (0x1 << 13)
+#define ADT_DNE1 (0x1 << 14)
+#define ADT_RDY1 (0x1 << 15)
+#define ADT_BD2_SHIFT (16)
+#define ADT_ERR2 (0x1 << 29)
+#define ADT_DNE2 (0x1 << 30)
+#define ADT_RDY2 (0x1 << 31)
+#define ADT_BA1_SHIFT (0x0)
+#define ADT_BA2_SHIFT (0x0)
+#define ADT_PS1 (0x1 << 12)
+#define ADT_PS2 (0x1 << 28)
+#define ADT_MEP1 (0x1 << 11)
+#define ADT_MEP2 (0x1 << 27)
+
+#define MLB_MINOR_DEVICES 4
+#define MLB_CONTROL_DEV_NAME "ctrl"
+#define MLB_ASYNC_DEV_NAME "async"
+#define MLB_SYNC_DEV_NAME "sync"
+#define MLB_ISOC_DEV_NAME "isoc"
+
+#define TX_CHANNEL 0
+#define RX_CHANNEL 1
+
+#define TRANS_RING_NODES (1 << 3)
+#define MLB_QUIRK_MLB150 (1 << 0)
+
+enum MLB_CTYPE {
+ MLB_CTYPE_SYNC,
+ MLB_CTYPE_CTRL,
+ MLB_CTYPE_ASYNC,
+ MLB_CTYPE_ISOC,
+};
+
+enum CLK_SPEED {
+ CLK_256FS,
+ CLK_512FS,
+ CLK_1024FS,
+ CLK_2048FS,
+ CLK_3072FS,
+ CLK_4096FS,
+ CLK_6144FS,
+ CLK_8192FS,
+};
+
+enum MLB_INDEX {
+ IMX6Q_MLB = 0,
+ IMX6SX_MLB,
+};
+
+struct mlb_ringbuf {
+ s8 *virt_bufs[TRANS_RING_NODES];
+ u32 phy_addrs[TRANS_RING_NODES];
+ s32 head;
+ s32 tail;
+ s32 unit_size;
+ s32 total_size;
+ rwlock_t rb_lock ____cacheline_aligned; /* ring index lock */
+};
+
+struct mlb_channel_info {
+ /* Input MLB channel address */
+ u32 address;
+ /* Internal AHB channel label */
+ u32 cl;
+ /* DBR buf head */
+ u32 dbr_buf_head;
+};
+
+struct mlb_dev_info {
+ /* device node name */
+ const char dev_name[20];
+ /* channel type */
+ const unsigned int channel_type;
+ /* ch fps */
+ enum CLK_SPEED fps;
+ /* channel info for tx/rx */
+ struct mlb_channel_info channels[2];
+ /* ring buffer */
+ u8 *rbuf_base_virt;
+ u32 rbuf_base_phy;
+ struct mlb_ringbuf rx_rbuf;
+ struct mlb_ringbuf tx_rbuf;
+ /* exception event */
+ unsigned long ex_event;
+ /* tx busy indicator */
+ unsigned long tx_busy;
+ /* channel started up or not */
+ atomic_t on;
+ /* device open count */
+ atomic_t opencnt;
+ /* wait queue head for channel */
+ wait_queue_head_t rx_wq;
+ wait_queue_head_t tx_wq;
+ /* TX OK */
+ s32 tx_ok;
+ /* spinlock for event access */
+ spinlock_t event_lock;
+ /*
+ * Block size for isoc mode
+ * This variable can be configured in ioctl
+ */
+ u32 isoc_blksz;
+ /*
+ * Quads number for sync mode
+ * This variable can be confifured in ioctl
+ */
+ u32 sync_quad;
+ /* Buffer depth in cdt */
+ u32 cdt_buf_dep;
+ /* Buffer depth in adt */
+ u32 adt_buf_dep;
+ /* Buffer size to hold data */
+ u32 buf_size;
+};
+
+struct mlb_data {
+ struct mlb_dev_info *devinfo;
+ struct clk *clk_mlb3p;
+ struct clk *clk_mlb6p;
+ struct cdev cdev;
+ struct class *class; /* device class */
+ dev_t firstdev;
+#ifdef CONFIG_REGULATOR
+ struct regulator *nvcc;
+#endif
+ void __iomem *membase; /* mlb module base address */
+ struct gen_pool *iram_pool;
+ u32 iram_size;
+ int irq_ahb0;
+ int irq_ahb1;
+ int irq_mlb;
+ u32 quirk_flag;
+};
+
+/*
+ * For optimization, we use fixed channel label for
+ * input channels of each mode
+ * SYNC: CL = 0 for RX, CL = 64 for TX
+ * CTRL: CL = 1 for RX, CL = 65 for TX
+ * ASYNC: CL = 2 for RX, CL = 66 for TX
+ * ISOC: CL = 3 for RX, CL = 67 for TX
+ */
+#define SYNC_RX_CL_AHB0 0
+#define CTRL_RX_CL_AHB0 1
+#define ASYNC_RX_CL_AHB0 2
+#define ISOC_RX_CL_AHB0 3
+#define SYNC_TX_CL_AHB0 4
+#define CTRL_TX_CL_AHB0 5
+#define ASYNC_TX_CL_AHB0 6
+#define ISOC_TX_CL_AHB0 7
+
+#define SYNC_RX_CL_AHB1 32
+#define CTRL_RX_CL_AHB1 33
+#define ASYNC_RX_CL_AHB1 34
+#define ISOC_RX_CL_AHB1 35
+#define SYNC_TX_CL_AHB1 36
+#define CTRL_TX_CL_AHB1 37
+#define ASYNC_TX_CL_AHB1 38
+#define ISOC_TX_CL_AHB1 39
+
+#define SYNC_RX_CL SYNC_RX_CL_AHB0
+#define CTRL_RX_CL CTRL_RX_CL_AHB0
+#define ASYNC_RX_CL ASYNC_RX_CL_AHB0
+#define ISOC_RX_CL ISOC_RX_CL_AHB0
+
+#define SYNC_TX_CL SYNC_TX_CL_AHB0
+#define CTRL_TX_CL CTRL_TX_CL_AHB0
+#define ASYNC_TX_CL ASYNC_TX_CL_AHB0
+#define ISOC_TX_CL ISOC_TX_CL_AHB0
+
+static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = {
+ {
+ .dev_name = MLB_SYNC_DEV_NAME,
+ .channel_type = MLB_CTYPE_SYNC,
+ .channels = {
+ [0] = {
+ .cl = SYNC_TX_CL,
+ .dbr_buf_head = CH_SYNC_DBR_BUF_OFFSET,
+ },
+ [1] = {
+ .cl = SYNC_RX_CL,
+ .dbr_buf_head = CH_SYNC_DBR_BUF_OFFSET
+ + CH_SYNC_BUF_SZ,
+ },
+ },
+ .rx_rbuf = {
+ .unit_size = CH_SYNC_BUF_SZ,
+ .rb_lock =
+ __RW_LOCK_UNLOCKED(mlb_devinfo[0].rx_rbuf.rb_lock),
+ },
+ .tx_rbuf = {
+ .unit_size = CH_SYNC_BUF_SZ,
+ .rb_lock =
+ __RW_LOCK_UNLOCKED(mlb_devinfo[0].tx_rbuf.rb_lock),
+ },
+ .cdt_buf_dep = CH_SYNC_CDT_BUF_DEP,
+ .adt_buf_dep = CH_SYNC_ADT_BUF_DEP,
+ .buf_size = CH_SYNC_BUF_SZ,
+ .on = ATOMIC_INIT(0),
+ .opencnt = ATOMIC_INIT(0),
+ .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[0].event_lock),
+ },
+ {
+ .dev_name = MLB_CONTROL_DEV_NAME,
+ .channel_type = MLB_CTYPE_CTRL,
+ .channels = {
+ [0] = {
+ .cl = CTRL_TX_CL,
+ .dbr_buf_head = CH_CTRL_DBR_BUF_OFFSET,
+ },
+ [1] = {
+ .cl = CTRL_RX_CL,
+ .dbr_buf_head = CH_CTRL_DBR_BUF_OFFSET
+ + CH_CTRL_BUF_SZ,
+ },
+ },
+ .rx_rbuf = {
+ .unit_size = CH_CTRL_BUF_SZ,
+ .rb_lock =
+ __RW_LOCK_UNLOCKED(mlb_devinfo[1].rx_rbuf.rb_lock),
+ },
+ .tx_rbuf = {
+ .unit_size = CH_CTRL_BUF_SZ,
+ .rb_lock =
+ __RW_LOCK_UNLOCKED(mlb_devinfo[1].tx_rbuf.rb_lock),
+ },
+ .cdt_buf_dep = CH_CTRL_CDT_BUF_DEP,
+ .adt_buf_dep = CH_CTRL_ADT_BUF_DEP,
+ .buf_size = CH_CTRL_BUF_SZ,
+ .on = ATOMIC_INIT(0),
+ .opencnt = ATOMIC_INIT(0),
+ .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[1].event_lock),
+ },
+ {
+ .dev_name = MLB_ASYNC_DEV_NAME,
+ .channel_type = MLB_CTYPE_ASYNC,
+ .channels = {
+ [0] = {
+ .cl = ASYNC_TX_CL,
+ .dbr_buf_head = CH_ASYNC_DBR_BUF_OFFSET,
+ },
+ [1] = {
+ .cl = ASYNC_RX_CL,
+ .dbr_buf_head = CH_ASYNC_DBR_BUF_OFFSET
+ + CH_ASYNC_BUF_SZ,
+ },
+ },
+ .rx_rbuf = {
+ .unit_size = CH_ASYNC_BUF_SZ,
+ .rb_lock =
+ __RW_LOCK_UNLOCKED(mlb_devinfo[2].rx_rbuf.rb_lock),
+ },
+ .tx_rbuf = {
+ .unit_size = CH_ASYNC_BUF_SZ,
+ .rb_lock =
+ __RW_LOCK_UNLOCKED(mlb_devinfo[2].tx_rbuf.rb_lock),
+ },
+ .cdt_buf_dep = CH_ASYNC_CDT_BUF_DEP,
+ .adt_buf_dep = CH_ASYNC_ADT_BUF_DEP,
+ .buf_size = CH_ASYNC_BUF_SZ,
+ .on = ATOMIC_INIT(0),
+ .opencnt = ATOMIC_INIT(0),
+ .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[2].event_lock),
+ },
+ {
+ .dev_name = MLB_ISOC_DEV_NAME,
+ .channel_type = MLB_CTYPE_ISOC,
+ .channels = {
+ [0] = {
+ .cl = ISOC_TX_CL,
+ .dbr_buf_head = CH_ISOC_DBR_BUF_OFFSET,
+ },
+ [1] = {
+ .cl = ISOC_RX_CL,
+ .dbr_buf_head = CH_ISOC_DBR_BUF_OFFSET
+ + CH_ISOC_BUF_SZ,
+ },
+ },
+ .rx_rbuf = {
+ .unit_size = CH_ISOC_BUF_SZ,
+ .rb_lock =
+ __RW_LOCK_UNLOCKED(mlb_devinfo[3].rx_rbuf.rb_lock),
+ },
+ .tx_rbuf = {
+ .unit_size = CH_ISOC_BUF_SZ,
+ .rb_lock =
+ __RW_LOCK_UNLOCKED(mlb_devinfo[3].tx_rbuf.rb_lock),
+ },
+ .cdt_buf_dep = CH_ISOC_CDT_BUF_DEP,
+ .adt_buf_dep = CH_ISOC_ADT_BUF_DEP,
+ .buf_size = CH_ISOC_BUF_SZ,
+ .on = ATOMIC_INIT(0),
+ .opencnt = ATOMIC_INIT(0),
+ .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[3].event_lock),
+ .isoc_blksz = CH_ISOC_BLK_SIZE_188,
+ },
+};
+
+static void __iomem *mlb_base;
+
+DEFINE_SPINLOCK(ctr_lock);
+
+#ifdef DEBUG
+#define DUMP_REG(reg) pr_debug(#reg": 0x%08x\n", __raw_readl(mlb_base + reg))
+
+static void mlb150_dev_dump_reg(void)
+{
+ pr_debug("mxc_mlb150: Dump registers:\n");
+ DUMP_REG(REG_MLBC0);
+ DUMP_REG(REG_MLBPC0);
+ DUMP_REG(REG_MS0);
+ DUMP_REG(REG_MS1);
+ DUMP_REG(REG_MSS);
+ DUMP_REG(REG_MSD);
+ DUMP_REG(REG_MIEN);
+ DUMP_REG(REG_MLBPC2);
+ DUMP_REG(REG_MLBPC1);
+ DUMP_REG(REG_MLBC1);
+ DUMP_REG(REG_HCTL);
+ DUMP_REG(REG_HCMR0);
+ DUMP_REG(REG_HCMR1);
+ DUMP_REG(REG_HCER0);
+ DUMP_REG(REG_HCER1);
+ DUMP_REG(REG_HCBR0);
+ DUMP_REG(REG_HCBR1);
+ DUMP_REG(REG_MDAT0);
+ DUMP_REG(REG_MDAT1);
+ DUMP_REG(REG_MDAT2);
+ DUMP_REG(REG_MDAT3);
+ DUMP_REG(REG_MDWE0);
+ DUMP_REG(REG_MDWE1);
+ DUMP_REG(REG_MDWE2);
+ DUMP_REG(REG_MDWE3);
+ DUMP_REG(REG_MCTL);
+ DUMP_REG(REG_MADR);
+ DUMP_REG(REG_ACTL);
+ DUMP_REG(REG_ACSR0);
+ DUMP_REG(REG_ACSR1);
+ DUMP_REG(REG_ACMR0);
+ DUMP_REG(REG_ACMR1);
+}
+
+static void mlb150_dev_dump_hex(const u8 *buf, u32 len)
+{
+ print_hex_dump(KERN_DEBUG, "CTR DUMP:",
+ DUMP_PREFIX_OFFSET, 8, 1, buf, len, 0);
+}
+#endif
+
+static inline void mlb150_dev_enable_ctr_write(u32 mdat0_bits_en,
+ u32 mdat1_bits_en, u32 mdat2_bits_en, u32 mdat3_bits_en)
+{
+ __raw_writel(mdat0_bits_en, mlb_base + REG_MDWE0);
+ __raw_writel(mdat1_bits_en, mlb_base + REG_MDWE1);
+ __raw_writel(mdat2_bits_en, mlb_base + REG_MDWE2);
+ __raw_writel(mdat3_bits_en, mlb_base + REG_MDWE3);
+}
+
+#ifdef DEBUG
+static inline u8 mlb150_dev_dbr_read(u32 dbr_addr)
+{
+ s32 timeout = 1000;
+ u8 dbr_val = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctr_lock, flags);
+ __raw_writel(MADR_TB | dbr_addr,
+ mlb_base + REG_MADR);
+
+ while ((!(__raw_readl(mlb_base + REG_MCTL)
+ & MCTL_XCMP)) &&
+ timeout--)
+ ;
+
+ if (0 == timeout) {
+ spin_unlock_irqrestore(&ctr_lock, flags);
+ return -ETIME;
+ }
+
+ dbr_val = __raw_readl(mlb_base + REG_MDAT0) & 0x000000ff;
+
+ __raw_writel(0, mlb_base + REG_MCTL);
+ spin_unlock_irqrestore(&ctr_lock, flags);
+
+ return dbr_val;
+}
+
+static inline s32 mlb150_dev_dbr_write(u32 dbr_addr, u8 dbr_val)
+{
+ s32 timeout = 1000;
+ u32 mdat0 = dbr_val & 0x000000ff;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctr_lock, flags);
+ __raw_writel(mdat0, mlb_base + REG_MDAT0);
+
+ __raw_writel(MADR_WNR | MADR_TB | dbr_addr,
+ mlb_base + REG_MADR);
+
+ while ((!(__raw_readl(mlb_base + REG_MCTL)
+ & MCTL_XCMP)) &&
+ timeout--)
+ ;
+
+ if (timeout <= 0) {
+ spin_unlock_irqrestore(&ctr_lock, flags);
+ return -ETIME;
+ }
+
+ __raw_writel(0, mlb_base + REG_MCTL);
+ spin_unlock_irqrestore(&ctr_lock, flags);
+
+ return 0;
+}
+
+static inline s32 mlb150_dev_dbr_dump(u32 addr, u32 size)
+{
+ u8 *dump_buf = NULL;
+ u8 *buf_ptr = NULL;
+ s32 i;
+
+ dump_buf = kzalloc(size, GFP_KERNEL);
+ if (!dump_buf) {
+ pr_err("can't allocate enough memory\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0, buf_ptr = dump_buf;
+ i < size; ++i, ++buf_ptr)
+ *buf_ptr = mlb150_dev_dbr_read(addr + i);
+
+ mlb150_dev_dump_hex(dump_buf, size);
+
+ kfree(dump_buf);
+
+ return 0;
+}
+#endif
+
+static s32 mlb150_dev_ctr_read(u32 ctr_offset, u32 *ctr_val)
+{
+ s32 timeout = 1000;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctr_lock, flags);
+ __raw_writel(ctr_offset, mlb_base + REG_MADR);
+
+ while ((!(__raw_readl(mlb_base + REG_MCTL)
+ & MCTL_XCMP)) &&
+ timeout--)
+ ;
+
+ if (timeout <= 0) {
+ spin_unlock_irqrestore(&ctr_lock, flags);
+ pr_debug("mxc_mlb150: Read CTR timeout\n");
+ return -ETIME;
+ }
+
+ ctr_val[0] = __raw_readl(mlb_base + REG_MDAT0);
+ ctr_val[1] = __raw_readl(mlb_base + REG_MDAT1);
+ ctr_val[2] = __raw_readl(mlb_base + REG_MDAT2);
+ ctr_val[3] = __raw_readl(mlb_base + REG_MDAT3);
+
+ __raw_writel(0, mlb_base + REG_MCTL);
+
+ spin_unlock_irqrestore(&ctr_lock, flags);
+
+ return 0;
+}
+
+static s32 mlb150_dev_ctr_write(u32 ctr_offset, const u32 *ctr_val)
+{
+ s32 timeout = 1000;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctr_lock, flags);
+
+ __raw_writel(ctr_val[0], mlb_base + REG_MDAT0);
+ __raw_writel(ctr_val[1], mlb_base + REG_MDAT1);
+ __raw_writel(ctr_val[2], mlb_base + REG_MDAT2);
+ __raw_writel(ctr_val[3], mlb_base + REG_MDAT3);
+
+ __raw_writel(MADR_WNR | ctr_offset,
+ mlb_base + REG_MADR);
+
+ while ((!(__raw_readl(mlb_base + REG_MCTL)
+ & MCTL_XCMP)) &&
+ timeout--)
+ ;
+
+ if (timeout <= 0) {
+ spin_unlock_irqrestore(&ctr_lock, flags);
+ pr_debug("mxc_mlb150: Write CTR timeout\n");
+ return -ETIME;
+ }
+
+ __raw_writel(0, mlb_base + REG_MCTL);
+
+ spin_unlock_irqrestore(&ctr_lock, flags);
+
+#ifdef DEBUG_CTR
+ {
+ u32 ctr_rd[4] = { 0 };
+
+ if (!mlb150_dev_ctr_read(ctr_offset, ctr_rd)) {
+ if (ctr_val[0] == ctr_rd[0] &&
+ ctr_val[1] == ctr_rd[1] &&
+ ctr_val[2] == ctr_rd[2] &&
+ ctr_val[3] == ctr_rd[3])
+ return 0;
+ else {
+ pr_debug("mxc_mlb150: ctr write failed\n");
+ pr_debug("offset: 0x%x\n", ctr_offset);
+ pr_debug("Write: 0x%x 0x%x 0x%x 0x%x\n",
+ ctr_val[3], ctr_val[2],
+ ctr_val[1], ctr_val[0]);
+ pr_debug("Read: 0x%x 0x%x 0x%x 0x%x\n",
+ ctr_rd[3], ctr_rd[2],
+ ctr_rd[1], ctr_rd[0]);
+ return -EBADE;
+ }
+ } else {
+ pr_debug("mxc_mlb150: ctr read failed\n");
+ return -EBADE;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+#ifdef DEBUG
+static s32 mlb150_dev_cat_read(u32 ctr_offset, u32 ch, u16 *cat_val)
+{
+ u16 ctr_val[8] = { 0 };
+
+ if (mlb150_dev_ctr_read(ctr_offset, (u32 *)ctr_val))
+ return -ETIME;
+
+ /*
+ * Use u16 array to get u32 array value,
+ * need to convert
+ */
+ cat_val = ctr_val[ch % 8];
+
+ return 0;
+}
+#endif
+
+static s32 mlb150_dev_cat_write(u32 ctr_offset, u32 ch, const u16 cat_val)
+{
+ u16 ctr_val[8] = { 0 };
+
+ if (mlb150_dev_ctr_read(ctr_offset, (u32 *)ctr_val))
+ return -ETIME;
+
+ ctr_val[ch % 8] = cat_val;
+ if (mlb150_dev_ctr_write(ctr_offset, (u32 *)ctr_val))
+ return -ETIME;
+
+ return 0;
+}
+
+#define mlb150_dev_cat_mlb_read(ch, cat_val) \
+ mlb150_dev_cat_read(BUF_CAT_MLB_OFFSET + (ch >> 3), ch, cat_val)
+#define mlb150_dev_cat_mlb_write(ch, cat_val) \
+ mlb150_dev_cat_write(BUF_CAT_MLB_OFFSET + (ch >> 3), ch, cat_val)
+#define mlb150_dev_cat_hbi_read(ch, cat_val) \
+ mlb150_dev_cat_read(BUF_CAT_HBI_OFFSET + (ch >> 3), ch, cat_val)
+#define mlb150_dev_cat_hbi_write(ch, cat_val) \
+ mlb150_dev_cat_write(BUF_CAT_HBI_OFFSET + (ch >> 3), ch, cat_val)
+
+#define mlb150_dev_cdt_read(ch, cdt_val) \
+ mlb150_dev_ctr_read(BUF_CDT_OFFSET + ch, cdt_val)
+#define mlb150_dev_cdt_write(ch, cdt_val) \
+ mlb150_dev_ctr_write(BUF_CDT_OFFSET + ch, cdt_val)
+#define mlb150_dev_adt_read(ch, adt_val) \
+ mlb150_dev_ctr_read(BUF_ADT_OFFSET + ch, adt_val)
+#define mlb150_dev_adt_write(ch, adt_val) \
+ mlb150_dev_ctr_write(BUF_ADT_OFFSET + ch, adt_val)
+
+static s32 mlb150_dev_get_adt_sts(u32 ch)
+{
+ s32 timeout = 1000;
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&ctr_lock, flags);
+ __raw_writel(BUF_ADT_OFFSET + ch,
+ mlb_base + REG_MADR);
+
+ while ((!(__raw_readl(mlb_base + REG_MCTL)
+ & MCTL_XCMP)) &&
+ timeout--)
+ ;
+
+ if (timeout <= 0) {
+ spin_unlock_irqrestore(&ctr_lock, flags);
+ pr_debug("mxc_mlb150: Read CTR timeout\n");
+ return -ETIME;
+ }
+
+ reg = __raw_readl(mlb_base + REG_MDAT1);
+
+ __raw_writel(0, mlb_base + REG_MCTL);
+ spin_unlock_irqrestore(&ctr_lock, flags);
+
+#ifdef DEBUG_ADT
+ pr_debug("mxc_mlb150: Get ch %d adt sts: 0x%08x\n", ch, reg);
+#endif
+
+ return reg;
+}
+
+#ifdef DEBUG
+static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end)
+{
+ u32 i = 0;
+ u32 ctr_val[4] = { 0 };
+
+ pr_debug("mxc_mlb150: CDT Table");
+ for (i = BUF_CDT_OFFSET + ch_start;
+ i < BUF_CDT_OFFSET + ch_end;
+ ++i) {
+ mlb150_dev_ctr_read(i, ctr_val);
+ pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+ i, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]);
+ }
+
+ pr_debug("mxc_mlb150: ADT Table");
+ for (i = BUF_ADT_OFFSET + ch_start;
+ i < BUF_ADT_OFFSET + ch_end;
+ ++i) {
+ mlb150_dev_ctr_read(i, ctr_val);
+ pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+ i, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]);
+ }
+
+ pr_debug("mxc_mlb150: CAT MLB Table");
+ for (i = BUF_CAT_MLB_OFFSET + (ch_start >> 3);
+ i <= BUF_CAT_MLB_OFFSET + ((ch_end + 8) >> 3);
+ ++i) {
+ mlb150_dev_ctr_read(i, ctr_val);
+ pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+ i, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]);
+ }
+
+ pr_debug("mxc_mlb150: CAT HBI Table");
+ for (i = BUF_CAT_HBI_OFFSET + (ch_start >> 3);
+ i <= BUF_CAT_HBI_OFFSET + ((ch_end + 8) >> 3);
+ ++i) {
+ mlb150_dev_ctr_read(i, ctr_val);
+ pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+ i, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]);
+ }
+}
+#endif
+
+/*
+ * Initial the MLB module device
+ */
+static inline void mlb150_dev_enable_dma_irq(u32 enable)
+{
+ u32 ch_rx_mask = (1 << SYNC_RX_CL_AHB0) | (1 << CTRL_RX_CL_AHB0)
+ | (1 << ASYNC_RX_CL_AHB0) | (1 << ISOC_RX_CL_AHB0)
+ | (1 << SYNC_TX_CL_AHB0) | (1 << CTRL_TX_CL_AHB0)
+ | (1 << ASYNC_TX_CL_AHB0) | (1 << ISOC_TX_CL_AHB0);
+ u32 ch_tx_mask = (1 << (SYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (CTRL_RX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (ASYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (ISOC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (SYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (CTRL_TX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (ASYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (ISOC_TX_CL_AHB1 - INT_AHB1_CH_START));
+
+ if (enable) {
+ __raw_writel(ch_rx_mask, mlb_base + REG_ACMR0);
+ __raw_writel(ch_tx_mask, mlb_base + REG_ACMR1);
+ } else {
+ __raw_writel(0x0, mlb_base + REG_ACMR0);
+ __raw_writel(0x0, mlb_base + REG_ACMR1);
+ }
+}
+
+
+static void mlb150_dev_init_ir_amba_ahb(void)
+{
+ u32 reg = 0;
+
+ /*
+ * Step 1. Program the ACMRn registers to enable interrupts from all
+ * active DMA channels
+ */
+ mlb150_dev_enable_dma_irq(1);
+
+ /*
+ * Step 2. Select the status clear method:
+ * ACTL.SCE = 0, hardware clears on read
+ * ACTL.SCE = 1, software writes a '1' to clear
+ * We only support DMA MODE 1
+ */
+ reg = __raw_readl(mlb_base + REG_ACTL);
+ reg |= ACTL_DMAMODE;
+#ifdef MULTIPLE_PACKAGE_MODE
+ reg |= REG_ACTL_MPB;
+#endif
+
+ /*
+ * Step 3. Select 1 or 2 interrupt signals:
+ * ACTL.SMX = 0: one interrupt for channels 0 - 31 on ahb_init[0]
+ * and another interrupt for channels 32 - 63 on ahb_init[1]
+ * ACTL.SMX = 1: singel interrupt all channels on ahb_init[0]
+ */
+ reg &= ~ACTL_SMX;
+
+ __raw_writel(reg, mlb_base + REG_ACTL);
+}
+
+static inline void mlb150_dev_enable_ir_mlb(u32 enable)
+{
+ /*
+ * Step 1, Select the MSn to be cleared by software,
+ * writing a '0' to the appropriate bits
+ */
+ __raw_writel(0, mlb_base + REG_MS0);
+ __raw_writel(0, mlb_base + REG_MS1);
+
+ /*
+ * Step 1, Program MIEN to enable protocol error
+ * interrupts for all active MLB channels
+ */
+ if (enable)
+ __raw_writel(MIEN_CTX_PE |
+ MIEN_CRX_PE | MIEN_ATX_PE |
+ MIEN_ARX_PE | MIEN_SYNC_PE |
+ MIEN_ISOC_PE,
+ mlb_base + REG_MIEN);
+ else
+ __raw_writel(0, mlb_base + REG_MIEN);
+}
+
+static inline void mlb150_enable_pll(struct mlb_data *drvdata)
+{
+ u32 c0_val;
+
+ __raw_writel(MLBPC1_VAL,
+ drvdata->membase + REG_MLBPC1);
+
+ c0_val = __raw_readl(drvdata->membase + REG_MLBC0);
+ if (c0_val & MLBC0_MLBPEN) {
+ c0_val &= ~MLBC0_MLBPEN;
+ __raw_writel(c0_val,
+ drvdata->membase + REG_MLBC0);
+ }
+
+ clk_prepare_enable(drvdata->clk_mlb6p);
+
+ c0_val |= (MLBC0_MLBPEN);
+ __raw_writel(c0_val, drvdata->membase + REG_MLBC0);
+}
+
+static inline void mlb150_disable_pll(struct mlb_data *drvdata)
+{
+ u32 c0_val;
+
+ clk_disable_unprepare(drvdata->clk_mlb6p);
+
+ c0_val = __raw_readl(drvdata->membase + REG_MLBC0);
+
+ __raw_writel(0x0, drvdata->membase + REG_MLBPC1);
+
+ c0_val &= ~MLBC0_MLBPEN;
+ __raw_writel(c0_val, drvdata->membase + REG_MLBC0);
+}
+
+static void mlb150_dev_reset_cdt(void)
+{
+ int i = 0;
+ u32 ctr_val[4] = { 0 };
+
+ mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff);
+
+ for (i = 0; i < (LOGIC_CH_NUM); ++i)
+ mlb150_dev_ctr_write(BUF_CDT_OFFSET + i, ctr_val);
+}
+
+static s32 mlb150_dev_init_ch_cdt(struct mlb_dev_info *pdevinfo, u32 ch,
+ enum MLB_CTYPE ctype, u32 ch_func)
+{
+ u32 cdt_val[4] = { 0 };
+
+ /* a. Set the 14-bit base address (BA) */
+ pr_debug("mxc_mlb150: ctype: %d, ch: %d, dbr_buf_head: 0x%08x",
+ ctype, ch, pdevinfo->channels[ch_func].dbr_buf_head);
+ cdt_val[3] = (pdevinfo->channels[ch_func].dbr_buf_head)
+ << CDT_BA_SHIFT;
+ /*
+ * b. Set the 12-bit or 13-bit buffer depth (BD)
+ * BD = buffer depth in bytes - 1
+ * For synchronous channels: (BD + 1) = 4 * m * bpf
+ * For control channels: (BD + 1) >= max packet length (64)
+ * For asynchronous channels: (BD + 1) >= max packet length
+ * 1024 for a MOST Data packet (MDP);
+ * 1536 for a MOST Ethernet Packet (MEP)
+ * For isochronous channels: (BD + 1) mod (BS + 1) = 0
+ * BS
+ */
+ if (MLB_CTYPE_ISOC == ctype)
+ cdt_val[1] |= (pdevinfo->isoc_blksz - 1);
+ /* BD */
+ cdt_val[3] |= (pdevinfo->cdt_buf_dep - 1) << CDT_BD_SHIFT;
+
+ pr_debug("mxc_mlb150: Set CDT val of channel %d, type: %d: "
+ "0x%08x 0x%08x 0x%08x 0x%08x\n",
+ ch, ctype, cdt_val[3], cdt_val[2], cdt_val[1], cdt_val[0]);
+
+ if (mlb150_dev_cdt_write(ch, cdt_val))
+ return -ETIME;
+
+#ifdef DEBUG_CTR
+ {
+ u32 cdt_rd[4] = { 0 };
+ if (!mlb150_dev_cdt_read(ch, cdt_rd)) {
+ pr_debug("mxc_mlb150: CDT val of channel %d: "
+ "0x%08x 0x%08x 0x%08x 0x%08x\n",
+ ch, cdt_rd[3], cdt_rd[2], cdt_rd[1], cdt_rd[0]);
+ if (cdt_rd[3] == cdt_val[3] &&
+ cdt_rd[2] == cdt_val[2] &&
+ cdt_rd[1] == cdt_val[1] &&
+ cdt_rd[0] == cdt_val[0]) {
+ pr_debug("mxc_mlb150: set cdt succeed!\n");
+ return 0;
+ } else {
+ pr_debug("mxc_mlb150: set cdt failed!\n");
+ return -EBADE;
+ }
+ } else {
+ pr_debug("mxc_mlb150: Read CDT val of channel %d failed\n",
+ ch);
+ return -EBADE;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cl,
+ u32 cat_mode, enum MLB_CTYPE ctype)
+{
+ u16 cat_val = 0;
+#ifdef DEBUG_CTR
+ u16 cat_rd = 0;
+#endif
+
+ cat_val = CAT_CE | (ctype << CAT_CT_SHIFT) | cl;
+
+ if (cat_mode & CAT_MODE_OUTBOUND_DMA)
+ cat_val |= CAT_RNW;
+
+ if (MLB_CTYPE_SYNC == ctype)
+ cat_val |= CAT_MT;
+
+ switch (cat_mode) {
+ case CAT_MODE_RX | CAT_MODE_INBOUND_DMA:
+ case CAT_MODE_TX | CAT_MODE_OUTBOUND_DMA:
+ pr_debug("mxc_mlb150: set CAT val of channel %d, type: %d: 0x%04x\n",
+ ch, ctype, cat_val);
+
+ if (mlb150_dev_cat_mlb_write(ch, cat_val))
+ return -ETIME;
+#ifdef DEBUG_CTR
+ if (!mlb150_dev_cat_mlb_read(ch, &cat_rd))
+ pr_debug("mxc_mlb150: CAT val of mlb channel %d: 0x%04x",
+ ch, cat_rd);
+ else {
+ pr_debug("mxc_mlb150: Read CAT of mlb channel %d failed\n",
+ ch);
+ return -EBADE;
+ }
+#endif
+ break;
+ case CAT_MODE_TX | CAT_MODE_INBOUND_DMA:
+ case CAT_MODE_RX | CAT_MODE_OUTBOUND_DMA:
+ pr_debug("mxc_mlb150: set CAT val of channel %d, type: %d: 0x%04x\n",
+ cl, ctype, cat_val);
+
+ if (mlb150_dev_cat_hbi_write(cl, cat_val))
+ return -ETIME;
+#ifdef DEBUG_CTR
+ if (!mlb150_dev_cat_hbi_read(cl, &cat_rd))
+ pr_debug("mxc_mlb150: CAT val of hbi channel %d: 0x%04x",
+ cl, cat_rd);
+ else {
+ pr_debug("mxc_mlb150: Read CAT of hbi channel %d failed\n",
+ cl);
+ return -EBADE;
+ }
+#endif
+ break;
+ default:
+ return EBADRQC;
+ }
+
+#ifdef DEBUG_CTR
+ {
+ if (cat_val == cat_rd) {
+ pr_debug("mxc_mlb150: set cat succeed!\n");
+ return 0;
+ } else {
+ pr_debug("mxc_mlb150: set cat failed!\n");
+ return -EBADE;
+ }
+ }
+#endif
+ return 0;
+}
+
+static void mlb150_dev_reset_cat(void)
+{
+ int i = 0;
+ u32 ctr_val[4] = { 0 };
+
+ mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff);
+
+ for (i = 0; i < (LOGIC_CH_NUM >> 3); ++i) {
+ mlb150_dev_ctr_write(BUF_CAT_MLB_OFFSET + i, ctr_val);
+ mlb150_dev_ctr_write(BUF_CAT_HBI_OFFSET + i, ctr_val);
+ }
+}
+
+static void mlb150_dev_init_rfb(struct mlb_dev_info *pdevinfo, u32 rx_ch,
+ u32 tx_ch, enum MLB_CTYPE ctype)
+{
+ u32 rx_cl = pdevinfo->channels[RX_CHANNEL].cl;
+ u32 tx_cl = pdevinfo->channels[TX_CHANNEL].cl;
+ /* Step 1, Initialize all bits of CAT to '0' */
+ mlb150_dev_reset_cat();
+ mlb150_dev_reset_cdt();
+ /*
+ * Step 2, Initialize logical channel
+ * Step 3, Program the CDT for channel N
+ */
+ mlb150_dev_init_ch_cdt(pdevinfo, rx_cl, ctype, RX_CHANNEL);
+ mlb150_dev_init_ch_cdt(pdevinfo, tx_cl, ctype, TX_CHANNEL);
+
+ /* Step 4&5, Program the CAT for the inbound and outbound DMA */
+ mlb150_dev_init_ch_cat(rx_ch, rx_cl,
+ CAT_MODE_RX | CAT_MODE_INBOUND_DMA,
+ ctype);
+ mlb150_dev_init_ch_cat(rx_ch, rx_cl,
+ CAT_MODE_RX | CAT_MODE_OUTBOUND_DMA,
+ ctype);
+ mlb150_dev_init_ch_cat(tx_ch, tx_cl,
+ CAT_MODE_TX | CAT_MODE_INBOUND_DMA,
+ ctype);
+ mlb150_dev_init_ch_cat(tx_ch, tx_cl,
+ CAT_MODE_TX | CAT_MODE_OUTBOUND_DMA,
+ ctype);
+}
+
+static void mlb150_dev_reset_adt(void)
+{
+ int i = 0;
+ u32 ctr_val[4] = { 0 };
+
+ mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff);
+
+ for (i = 0; i < (LOGIC_CH_NUM); ++i)
+ mlb150_dev_ctr_write(BUF_ADT_OFFSET + i, ctr_val);
+}
+
+static void mlb150_dev_reset_whole_ctr(void)
+{
+ mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff);
+ mlb150_dev_reset_cdt();
+ mlb150_dev_reset_adt();
+ mlb150_dev_reset_cat();
+}
+
+#define CLR_REG(reg) __raw_writel(0x0, mlb_base + reg)
+
+static void mlb150_dev_reset_all_regs(void)
+{
+ CLR_REG(REG_MLBC0);
+ CLR_REG(REG_MLBPC0);
+ CLR_REG(REG_MS0);
+ CLR_REG(REG_MS1);
+ CLR_REG(REG_MSS);
+ CLR_REG(REG_MSD);
+ CLR_REG(REG_MIEN);
+ CLR_REG(REG_MLBPC2);
+ CLR_REG(REG_MLBPC1);
+ CLR_REG(REG_MLBC1);
+ CLR_REG(REG_HCTL);
+ CLR_REG(REG_HCMR0);
+ CLR_REG(REG_HCMR1);
+ CLR_REG(REG_HCER0);
+ CLR_REG(REG_HCER1);
+ CLR_REG(REG_HCBR0);
+ CLR_REG(REG_HCBR1);
+ CLR_REG(REG_MDAT0);
+ CLR_REG(REG_MDAT1);
+ CLR_REG(REG_MDAT2);
+ CLR_REG(REG_MDAT3);
+ CLR_REG(REG_MDWE0);
+ CLR_REG(REG_MDWE1);
+ CLR_REG(REG_MDWE2);
+ CLR_REG(REG_MDWE3);
+ CLR_REG(REG_MCTL);
+ CLR_REG(REG_MADR);
+ CLR_REG(REG_ACTL);
+ CLR_REG(REG_ACSR0);
+ CLR_REG(REG_ACSR1);
+ CLR_REG(REG_ACMR0);
+ CLR_REG(REG_ACMR1);
+}
+
+static inline s32 mlb150_dev_pipo_start(struct mlb_ringbuf *rbuf,
+ u32 ahb_ch, u32 buf_addr)
+{
+ u32 ctr_val[4] = { 0 };
+
+ ctr_val[1] |= ADT_RDY1;
+ ctr_val[2] = buf_addr;
+
+ if (mlb150_dev_adt_write(ahb_ch, ctr_val))
+ return -ETIME;
+
+ return 0;
+}
+
+static inline s32 mlb150_dev_pipo_next(u32 ahb_ch, enum MLB_CTYPE ctype,
+ u32 dne_sts, u32 buf_addr)
+{
+ u32 ctr_val[4] = { 0 };
+
+ if (MLB_CTYPE_ASYNC == ctype ||
+ MLB_CTYPE_CTRL == ctype) {
+ ctr_val[1] |= ADT_PS1;
+ ctr_val[1] |= ADT_PS2;
+ }
+
+ /*
+ * Clear DNE1 and ERR1
+ * Set the page ready bit (RDY1)
+ */
+ if (dne_sts & ADT_DNE1) {
+ ctr_val[1] |= ADT_RDY2;
+ ctr_val[3] = buf_addr;
+ } else {
+ ctr_val[1] |= ADT_RDY1;
+ ctr_val[2] = buf_addr;
+ }
+
+ if (mlb150_dev_adt_write(ahb_ch, ctr_val))
+ return -ETIME;
+
+ return 0;
+}
+
+static inline s32 mlb150_dev_pipo_stop(struct mlb_ringbuf *rbuf, u32 ahb_ch)
+{
+ u32 ctr_val[4] = { 0 };
+ unsigned long flags;
+
+ write_lock_irqsave(&rbuf->rb_lock, flags);
+ rbuf->head = rbuf->tail = 0;
+ write_unlock_irqrestore(&rbuf->rb_lock, flags);
+
+ if (mlb150_dev_adt_write(ahb_ch, ctr_val))
+ return -ETIME;
+
+ return 0;
+}
+
+static s32 mlb150_dev_init_ch_amba_ahb(struct mlb_dev_info *pdevinfo,
+ struct mlb_channel_info *chinfo,
+ enum MLB_CTYPE ctype)
+{
+ u32 ctr_val[4] = { 0 };
+
+ /* a. Set the 32-bit base address (BA1) */
+ ctr_val[3] = 0;
+ ctr_val[2] = 0;
+ ctr_val[1] = (pdevinfo->adt_buf_dep - 1) << ADT_BD1_SHIFT;
+ ctr_val[1] |= (pdevinfo->adt_buf_dep - 1) << ADT_BD2_SHIFT;
+ if (MLB_CTYPE_ASYNC == ctype ||
+ MLB_CTYPE_CTRL == ctype) {
+ ctr_val[1] |= ADT_PS1;
+ ctr_val[1] |= ADT_PS2;
+ }
+
+ ctr_val[0] |= (ADT_LE | ADT_CE);
+
+ pr_debug("mxc_mlb150: Set ADT val of channel %d, ctype: %d: "
+ "0x%08x 0x%08x 0x%08x 0x%08x\n",
+ chinfo->cl, ctype, ctr_val[3], ctr_val[2],
+ ctr_val[1], ctr_val[0]);
+
+ if (mlb150_dev_adt_write(chinfo->cl, ctr_val))
+ return -ETIME;
+
+#ifdef DEBUG_CTR
+ {
+ u32 ctr_rd[4] = { 0 };
+ if (!mlb150_dev_adt_read(chinfo->cl, ctr_rd)) {
+ pr_debug("mxc_mlb150: ADT val of channel %d: "
+ "0x%08x 0x%08x 0x%08x 0x%08x\n",
+ chinfo->cl, ctr_rd[3], ctr_rd[2],
+ ctr_rd[1], ctr_rd[0]);
+ if (ctr_rd[3] == ctr_val[3] &&
+ ctr_rd[2] == ctr_val[2] &&
+ ctr_rd[1] == ctr_val[1] &&
+ ctr_rd[0] == ctr_val[0]) {
+ pr_debug("mxc_mlb150: set adt succeed!\n");
+ return 0;
+ } else {
+ pr_debug("mxc_mlb150: set adt failed!\n");
+ return -EBADE;
+ }
+ } else {
+ pr_debug("mxc_mlb150: Read ADT val of channel %d failed\n",
+ chinfo->cl);
+ return -EBADE;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+static void mlb150_dev_init_amba_ahb(struct mlb_dev_info *pdevinfo,
+ enum MLB_CTYPE ctype)
+{
+ struct mlb_channel_info *tx_chinfo = &pdevinfo->channels[TX_CHANNEL];
+ struct mlb_channel_info *rx_chinfo = &pdevinfo->channels[RX_CHANNEL];
+
+ /* Step 1, Initialize all bits of the ADT to '0' */
+ mlb150_dev_reset_adt();
+
+ /*
+ * Step 2, Select a logic channel
+ * Step 3, Program the AMBA AHB block ping page for channel N
+ * Step 4, Program the AMBA AHB block pong page for channel N
+ */
+ mlb150_dev_init_ch_amba_ahb(pdevinfo, rx_chinfo, ctype);
+ mlb150_dev_init_ch_amba_ahb(pdevinfo, tx_chinfo, ctype);
+}
+
+static void mlb150_dev_exit(void)
+{
+ u32 c0_val, hctl_val;
+
+ /* Disable EN bits */
+ c0_val = __raw_readl(mlb_base + REG_MLBC0);
+ c0_val &= ~(MLBC0_MLBEN | MLBC0_MLBPEN);
+ __raw_writel(c0_val, mlb_base + REG_MLBC0);
+
+ hctl_val = __raw_readl(mlb_base + REG_HCTL);
+ hctl_val &= ~HCTL_EN;
+ __raw_writel(hctl_val, mlb_base + REG_HCTL);
+
+ __raw_writel(0x0, mlb_base + REG_HCMR0);
+ __raw_writel(0x0, mlb_base + REG_HCMR1);
+
+ mlb150_dev_enable_dma_irq(0);
+ mlb150_dev_enable_ir_mlb(0);
+}
+
+static void mlb150_dev_init(void)
+{
+ u32 c0_val;
+ u32 ch_rx_mask = (1 << SYNC_RX_CL_AHB0) | (1 << CTRL_RX_CL_AHB0)
+ | (1 << ASYNC_RX_CL_AHB0) | (1 << ISOC_RX_CL_AHB0)
+ | (1 << SYNC_TX_CL_AHB0) | (1 << CTRL_TX_CL_AHB0)
+ | (1 << ASYNC_TX_CL_AHB0) | (1 << ISOC_TX_CL_AHB0);
+ u32 ch_tx_mask = (1 << (SYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (CTRL_RX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (ASYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (ISOC_RX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (SYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (CTRL_TX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (ASYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) |
+ (1 << (ISOC_TX_CL_AHB1 - INT_AHB1_CH_START));
+
+ /* Disable EN bits */
+ mlb150_dev_exit();
+
+ /*
+ * Step 1. Initialize CTR and registers
+ * a. Set all bit of the CTR (CAT, CDT, and ADT) to 0.
+ */
+ mlb150_dev_reset_whole_ctr();
+
+ /* a. Set all bit of the CTR (CAT, CDT, and ADT) to 0. */
+ mlb150_dev_reset_all_regs();
+
+ /*
+ * Step 2, Configure the MediaLB interface
+ * Select pin mode and clock, 3-pin and 256fs
+ */
+ c0_val = __raw_readl(mlb_base + REG_MLBC0);
+ c0_val &= ~(MLBC0_MLBPEN | MLBC0_MLBCLK_MASK);
+ __raw_writel(c0_val, mlb_base + REG_MLBC0);
+
+ c0_val |= MLBC0_MLBEN;
+ __raw_writel(c0_val, mlb_base + REG_MLBC0);
+
+ /* Step 3, Configure the HBI interface */
+ __raw_writel(ch_rx_mask, mlb_base + REG_HCMR0);
+ __raw_writel(ch_tx_mask, mlb_base + REG_HCMR1);
+ __raw_writel(HCTL_EN, mlb_base + REG_HCTL);
+
+ mlb150_dev_init_ir_amba_ahb();
+
+ mlb150_dev_enable_ir_mlb(1);
+}
+
+static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 rx_cl, u32 tx_ch, u32 tx_cl)
+{
+ u32 timeout = 10000;
+
+ /*
+ * Check that MediaLB clock is running (MLBC1.CLKM = 0)
+ * If MLBC1.CLKM = 1, clear the register bit, wait one
+ * APB or I/O clock cycle and repeat the check
+ */
+ while ((__raw_readl(mlb_base + REG_MLBC1) & MLBC1_CLKM)
+ && --timeout)
+ __raw_writel(~MLBC1_CLKM, mlb_base + REG_MLBC1);
+
+ if (0 == timeout)
+ return -ETIME;
+
+ timeout = 10000;
+ /* Poll for MLB lock (MLBC0.MLBLK = 1) */
+ while (!(__raw_readl(mlb_base + REG_MLBC0) & MLBC0_MLBLK)
+ && --timeout)
+ ;
+
+ if (0 == timeout)
+ return -ETIME;
+
+ /* Unmute synchronous channel(s) */
+ mlb150_dev_cat_mlb_write(rx_ch, CAT_CE | rx_cl);
+ mlb150_dev_cat_mlb_write(tx_ch,
+ CAT_CE | tx_cl | CAT_RNW);
+ mlb150_dev_cat_hbi_write(rx_cl,
+ CAT_CE | rx_cl | CAT_RNW);
+ mlb150_dev_cat_hbi_write(tx_cl, CAT_CE | tx_cl);
+
+ return 0;
+}
+
+/* In case the user calls channel shutdown, but rx or tx is not completed yet */
+static s32 mlb150_trans_complete_check(struct mlb_dev_info *pdevinfo)
+{
+ struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
+ struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
+ s32 timeout = 1024;
+
+ while (timeout--) {
+ read_lock(&tx_rbuf->rb_lock);
+ if (!CIRC_CNT(tx_rbuf->head, tx_rbuf->tail, TRANS_RING_NODES)) {
+ read_unlock(&tx_rbuf->rb_lock);
+ break;
+ } else
+ read_unlock(&tx_rbuf->rb_lock);
+ }
+
+ if (timeout <= 0) {
+ pr_debug("TX complete check timeout!\n");
+ return -ETIME;
+ }
+
+ timeout = 1024;
+ while (timeout--) {
+ read_lock(&rx_rbuf->rb_lock);
+ if (!CIRC_CNT(rx_rbuf->head, rx_rbuf->tail, TRANS_RING_NODES)) {
+ read_unlock(&rx_rbuf->rb_lock);
+ break;
+ } else
+ read_unlock(&rx_rbuf->rb_lock);
+ }
+
+ if (timeout <= 0) {
+ pr_debug("RX complete check timeout!\n");
+ return -ETIME;
+ }
+
+ /*
+ * Interrupt from TX can only inform that the data is sent
+ * to AHB bus, not mean that it is sent to MITB. Thus we add
+ * a delay here for data to be completed sent.
+ */
+ udelay(1000);
+
+ return 0;
+}
+
+/*
+ * Enable/Disable the MLB IRQ
+ */
+static void mxc_mlb150_irq_enable(struct mlb_data *drvdata, u8 enable)
+{
+ if (enable) {
+ enable_irq(drvdata->irq_ahb0);
+ enable_irq(drvdata->irq_ahb1);
+ enable_irq(drvdata->irq_mlb);
+ } else {
+ disable_irq(drvdata->irq_ahb0);
+ disable_irq(drvdata->irq_ahb1);
+ disable_irq(drvdata->irq_mlb);
+ }
+}
+
+/*
+ * Enable the MLB channel
+ */
+static s32 mlb_channel_enable(struct mlb_data *drvdata,
+ int chan_dev_id, int on)
+{
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+ struct mlb_channel_info *tx_chinfo = &pdevinfo->channels[TX_CHANNEL];
+ struct mlb_channel_info *rx_chinfo = &pdevinfo->channels[RX_CHANNEL];
+ u32 tx_ch = tx_chinfo->address;
+ u32 rx_ch = rx_chinfo->address;
+ u32 tx_cl = tx_chinfo->cl;
+ u32 rx_cl = rx_chinfo->cl;
+ s32 ret = 0;
+
+ /*
+ * setup the direction, enable, channel type,
+ * mode select, channel address and mask buf start
+ */
+ if (on) {
+ u32 ctype = pdevinfo->channel_type;
+
+ mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff);
+ mlb150_dev_init_rfb(pdevinfo, rx_ch, tx_ch, ctype);
+
+ mlb150_dev_init_amba_ahb(pdevinfo, ctype);
+
+#ifdef DEBUG
+ mlb150_dev_dump_ctr_tbl(0, tx_chinfo->cl + 1);
+#endif
+ /* Synchronize and unmute synchrouous channel */
+ if (MLB_CTYPE_SYNC == ctype) {
+ ret = mlb150_dev_unmute_syn_ch(rx_ch, rx_cl,
+ tx_ch, tx_cl);
+ if (ret)
+ return ret;
+ }
+
+ mlb150_dev_enable_ctr_write(0x0, ADT_RDY1 | ADT_DNE1 |
+ ADT_ERR1 | ADT_PS1 |
+ ADT_RDY2 | ADT_DNE2 | ADT_ERR2 | ADT_PS2,
+ 0xffffffff, 0xffffffff);
+
+ if (pdevinfo->fps >= CLK_2048FS)
+ mlb150_enable_pll(drvdata);
+
+ atomic_set(&pdevinfo->on, 1);
+
+#ifdef DEBUG
+ mlb150_dev_dump_reg();
+ mlb150_dev_dump_ctr_tbl(0, tx_chinfo->cl + 1);
+#endif
+ /* Init RX ADT */
+ mlb150_dev_pipo_start(&pdevinfo->rx_rbuf, rx_cl,
+ pdevinfo->rx_rbuf.phy_addrs[0]);
+ } else {
+ mlb150_dev_pipo_stop(&pdevinfo->rx_rbuf, rx_cl);
+
+ mlb150_dev_enable_dma_irq(0);
+ mlb150_dev_enable_ir_mlb(0);
+
+ mlb150_dev_reset_cat();
+
+ atomic_set(&pdevinfo->on, 0);
+
+ if (pdevinfo->fps >= CLK_2048FS)
+ mlb150_disable_pll(drvdata);
+ }
+
+ return 0;
+}
+
+/*
+ * MLB interrupt handler
+ */
+static void mlb_rx_isr(s32 ctype, u32 ahb_ch, struct mlb_dev_info *pdevinfo)
+{
+ struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
+ s32 head, tail, adt_sts;
+ u32 rx_buf_ptr;
+
+#ifdef DEBUG_RX
+ pr_debug("mxc_mlb150: mlb_rx_isr\n");
+#endif
+
+ read_lock(&rx_rbuf->rb_lock);
+
+ head = (rx_rbuf->head + 1) & (TRANS_RING_NODES - 1);
+ tail = ACCESS_ONCE(rx_rbuf->tail);
+ read_unlock(&rx_rbuf->rb_lock);
+
+ if (CIRC_SPACE(head, tail, TRANS_RING_NODES) >= 1) {
+ rx_buf_ptr = rx_rbuf->phy_addrs[head];
+
+ /* commit the item before incrementing the head */
+ smp_wmb();
+
+ write_lock(&rx_rbuf->rb_lock);
+ rx_rbuf->head = head;
+ write_unlock(&rx_rbuf->rb_lock);
+
+ /* wake up the reader */
+ wake_up_interruptible(&pdevinfo->rx_wq);
+ } else {
+ rx_buf_ptr = rx_rbuf->phy_addrs[head];
+ pr_debug("drop RX package, due to no space, (%d,%d)\n",
+ head, tail);
+ }
+
+ adt_sts = mlb150_dev_get_adt_sts(ahb_ch);
+ /* Set ADT for RX */
+ mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, rx_buf_ptr);
+}
+
+static void mlb_tx_isr(s32 ctype, u32 ahb_ch, struct mlb_dev_info *pdevinfo)
+{
+ struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
+ s32 head, tail, adt_sts;
+ u32 tx_buf_ptr;
+
+ read_lock(&tx_rbuf->rb_lock);
+
+ head = ACCESS_ONCE(tx_rbuf->head);
+ tail = (tx_rbuf->tail + 1) & (TRANS_RING_NODES - 1);
+ read_unlock(&tx_rbuf->rb_lock);
+
+ smp_mb();
+ write_lock(&tx_rbuf->rb_lock);
+ tx_rbuf->tail = tail;
+ write_unlock(&tx_rbuf->rb_lock);
+
+ /* check the current tx buffer is available or not */
+ if (CIRC_CNT(head, tail, TRANS_RING_NODES) >= 1) {
+ /* read index before reading contents at that index */
+ smp_read_barrier_depends();
+
+ tx_buf_ptr = tx_rbuf->phy_addrs[tail];
+
+ wake_up_interruptible(&pdevinfo->tx_wq);
+
+ adt_sts = mlb150_dev_get_adt_sts(ahb_ch);
+ /* Set ADT for TX */
+ mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, tx_buf_ptr);
+ }
+}
+
+static irqreturn_t mlb_ahb_isr(int irq, void *dev_id)
+{
+ u32 acsr0, hcer0;
+ u32 ch_mask = (1 << SYNC_RX_CL) | (1 << CTRL_RX_CL)
+ | (1 << ASYNC_RX_CL) | (1 << ISOC_RX_CL)
+ | (1 << SYNC_TX_CL) | (1 << CTRL_TX_CL)
+ | (1 << ASYNC_TX_CL) | (1 << ISOC_TX_CL);
+
+ /*
+ * Step 5, Read the ACSRn registers to determine which channel or
+ * channels are causing the interrupt
+ */
+ acsr0 = __raw_readl(mlb_base + REG_ACSR0);
+
+ hcer0 = __raw_readl(mlb_base + REG_HCER0);
+
+ /*
+ * Step 6, If ACTL.SCE = 1, write the result of step 5 back to ACSR0
+ * and ACSR1 to clear the interrupt
+ * We'll not set ACTL_SCE
+ */
+
+ if (ch_mask & hcer0)
+ pr_err("CH encounters an AHB error: 0x%x\n", hcer0);
+
+ if ((1 << SYNC_RX_CL) & acsr0)
+ mlb_rx_isr(MLB_CTYPE_SYNC, SYNC_RX_CL,
+ &mlb_devinfo[MLB_CTYPE_SYNC]);
+
+ if ((1 << CTRL_RX_CL) & acsr0)
+ mlb_rx_isr(MLB_CTYPE_CTRL, CTRL_RX_CL,
+ &mlb_devinfo[MLB_CTYPE_CTRL]);
+
+ if ((1 << ASYNC_RX_CL) & acsr0)
+ mlb_rx_isr(MLB_CTYPE_ASYNC, ASYNC_RX_CL,
+ &mlb_devinfo[MLB_CTYPE_ASYNC]);
+
+ if ((1 << ISOC_RX_CL) & acsr0)
+ mlb_rx_isr(MLB_CTYPE_ISOC, ISOC_RX_CL,
+ &mlb_devinfo[MLB_CTYPE_ISOC]);
+
+ if ((1 << SYNC_TX_CL) & acsr0)
+ mlb_tx_isr(MLB_CTYPE_SYNC, SYNC_TX_CL,
+ &mlb_devinfo[MLB_CTYPE_SYNC]);
+
+ if ((1 << CTRL_TX_CL) & acsr0)
+ mlb_tx_isr(MLB_CTYPE_CTRL, CTRL_TX_CL,
+ &mlb_devinfo[MLB_CTYPE_CTRL]);
+
+ if ((1 << ASYNC_TX_CL) & acsr0)
+ mlb_tx_isr(MLB_CTYPE_ASYNC, ASYNC_TX_CL,
+ &mlb_devinfo[MLB_CTYPE_ASYNC]);
+
+ if ((1 << ISOC_TX_CL) & acsr0)
+ mlb_tx_isr(MLB_CTYPE_ASYNC, ISOC_TX_CL,
+ &mlb_devinfo[MLB_CTYPE_ISOC]);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mlb_isr(int irq, void *dev_id)
+{
+ u32 rx_int_sts, tx_int_sts, ms0,
+ ms1, tx_cis, rx_cis, ctype;
+ int minor;
+ u32 cdt_val[4] = { 0 };
+
+ /*
+ * Step 4, Read the MSn register to determine which channel(s)
+ * are causing the interrupt
+ */
+ ms0 = __raw_readl(mlb_base + REG_MS0);
+ ms1 = __raw_readl(mlb_base + REG_MS1);
+
+ /*
+ * The MLB150_MS0, MLB150_MS1 registers need to be cleared. In
+ * the spec description, the registers should be cleared when
+ * enabling interrupt. In fact, we also should clear it in ISR.
+ */
+ __raw_writel(0, mlb_base + REG_MS0);
+ __raw_writel(0, mlb_base + REG_MS1);
+
+ pr_debug("mxc_mlb150: mlb interrupt:0x%08x 0x%08x\n",
+ (u32)ms0, (u32)ms1);
+
+ for (minor = 0; minor < MLB_MINOR_DEVICES; minor++) {
+ struct mlb_dev_info *pdevinfo = &mlb_devinfo[minor];
+ u32 rx_mlb_ch = pdevinfo->channels[RX_CHANNEL].address;
+ u32 tx_mlb_ch = pdevinfo->channels[TX_CHANNEL].address;
+ u32 rx_mlb_cl = pdevinfo->channels[RX_CHANNEL].cl;
+ u32 tx_mlb_cl = pdevinfo->channels[TX_CHANNEL].cl;
+
+ tx_cis = rx_cis = 0;
+
+ ctype = pdevinfo->channel_type;
+ rx_int_sts = (rx_mlb_ch < 31) ? ms0 : ms1;
+ tx_int_sts = (tx_mlb_ch < 31) ? ms0 : ms1;
+
+ pr_debug("mxc_mlb150: channel interrupt: "
+ "tx %d: 0x%08x, rx %d: 0x%08x\n",
+ tx_mlb_ch, (u32)tx_int_sts, rx_mlb_ch, (u32)rx_int_sts);
+
+ /* Get tx channel interrupt status */
+ if (tx_int_sts & (1 << (tx_mlb_ch % 32))) {
+ mlb150_dev_cdt_read(tx_mlb_cl, cdt_val);
+ pr_debug("mxc_mlb150: TX_CH: %d, cdt_val[3]: 0x%08x, "
+ "cdt_val[2]: 0x%08x, "
+ "cdt_val[1]: 0x%08x, "
+ "cdt_val[0]: 0x%08x\n",
+ tx_mlb_ch, cdt_val[3], cdt_val[2],
+ cdt_val[1], cdt_val[0]);
+ switch (ctype) {
+ case MLB_CTYPE_SYNC:
+ tx_cis = (cdt_val[2] & CDT_SYNC_WSTS_MASK)
+ >> CDT_SYNC_WSTS_SHIFT;
+ /*
+ * Clear RSTS/WSTS errors to resume
+ * channel operation
+ * a. For synchronous channels: WSTS[3] = 0
+ */
+ cdt_val[2] &= ~(0x8 << CDT_SYNC_WSTS_SHIFT);
+ break;
+ case MLB_CTYPE_CTRL:
+ case MLB_CTYPE_ASYNC:
+ tx_cis = (cdt_val[2] &
+ CDT_CTRL_ASYNC_WSTS_MASK)
+ >> CDT_CTRL_ASYNC_WSTS_SHIFT;
+ tx_cis = (cdt_val[3] & CDT_CTRL_ASYNC_WSTS_1) ?
+ (tx_cis | (0x1 << 4)) : tx_cis;
+ /*
+ * b. For async and ctrl channels:
+ * RSTS[4]/WSTS[4] = 0
+ * and RSTS[2]/WSTS[2] = 0
+ */
+ cdt_val[3] &= ~CDT_CTRL_ASYNC_WSTS_1;
+ cdt_val[2] &=
+ ~(0x4 << CDT_CTRL_ASYNC_WSTS_SHIFT);
+ break;
+ case MLB_CTYPE_ISOC:
+ tx_cis = (cdt_val[2] & CDT_ISOC_WSTS_MASK)
+ >> CDT_ISOC_WSTS_SHIFT;
+ /* c. For isoc channels: WSTS[2:1] = 0x00 */
+ cdt_val[2] &= ~(0x6 << CDT_ISOC_WSTS_SHIFT);
+ break;
+ default:
+ break;
+ }
+ mlb150_dev_cdt_write(tx_mlb_ch, cdt_val);
+ }
+
+ /* Get rx channel interrupt status */
+ if (rx_int_sts & (1 << (rx_mlb_ch % 32))) {
+ mlb150_dev_cdt_read(rx_mlb_cl, cdt_val);
+ pr_debug("mxc_mlb150: RX_CH: %d, cdt_val[3]: 0x%08x, "
+ "cdt_val[2]: 0x%08x, "
+ "cdt_val[1]: 0x%08x, "
+ "cdt_val[0]: 0x%08x\n",
+ rx_mlb_ch, cdt_val[3], cdt_val[2],
+ cdt_val[1], cdt_val[0]);
+ switch (ctype) {
+ case MLB_CTYPE_SYNC:
+ rx_cis = (cdt_val[2] & CDT_SYNC_RSTS_MASK)
+ >> CDT_SYNC_RSTS_SHIFT;
+ cdt_val[2] &= ~(0x8 << CDT_SYNC_WSTS_SHIFT);
+ break;
+ case MLB_CTYPE_CTRL:
+ case MLB_CTYPE_ASYNC:
+ rx_cis =
+ (cdt_val[2] & CDT_CTRL_ASYNC_RSTS_MASK)
+ >> CDT_CTRL_ASYNC_RSTS_SHIFT;
+ rx_cis = (cdt_val[3] & CDT_CTRL_ASYNC_RSTS_1) ?
+ (rx_cis | (0x1 << 4)) : rx_cis;
+ cdt_val[3] &= ~CDT_CTRL_ASYNC_RSTS_1;
+ cdt_val[2] &=
+ ~(0x4 << CDT_CTRL_ASYNC_RSTS_SHIFT);
+ break;
+ case MLB_CTYPE_ISOC:
+ rx_cis = (cdt_val[2] & CDT_ISOC_RSTS_MASK)
+ >> CDT_ISOC_RSTS_SHIFT;
+ cdt_val[2] &= ~(0x6 << CDT_ISOC_WSTS_SHIFT);
+ break;
+ default:
+ break;
+ }
+ mlb150_dev_cdt_write(rx_mlb_ch, cdt_val);
+ }
+
+ if (!tx_cis && !rx_cis)
+ continue;
+
+ /* fill exception event */
+ spin_lock(&pdevinfo->event_lock);
+ pdevinfo->ex_event |= (rx_cis << 16) | tx_cis;
+ spin_unlock(&pdevinfo->event_lock);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int mxc_mlb150_open(struct inode *inode, struct file *filp)
+{
+ int minor, ring_buf_size, buf_size, j, ret;
+ void __iomem *buf_addr;
+ ulong phy_addr;
+ struct mlb_dev_info *pdevinfo = NULL;
+ struct mlb_channel_info *pchinfo = NULL;
+ struct mlb_data *drvdata;
+
+ minor = MINOR(inode->i_rdev);
+ drvdata = container_of(inode->i_cdev, struct mlb_data, cdev);
+
+ if (minor < 0 || minor >= MLB_MINOR_DEVICES) {
+ pr_err("no device\n");
+ return -ENODEV;
+ }
+
+ /* open for each channel device */
+ if (atomic_cmpxchg(&mlb_devinfo[minor].opencnt, 0, 1) != 0) {
+ pr_err("busy\n");
+ return -EBUSY;
+ }
+
+ clk_prepare_enable(drvdata->clk_mlb3p);
+
+ /* initial MLB module */
+ mlb150_dev_init();
+
+ pdevinfo = &mlb_devinfo[minor];
+ pchinfo = &pdevinfo->channels[TX_CHANNEL];
+
+ ring_buf_size = pdevinfo->buf_size;
+ buf_size = ring_buf_size * (TRANS_RING_NODES * 2);
+ buf_addr = (void __iomem *)gen_pool_alloc(drvdata->iram_pool, buf_size);
+ if (buf_addr == NULL) {
+ ret = -ENOMEM;
+ pr_err("can not alloc rx/tx buffers: %d\n", buf_size);
+ return ret;
+ }
+ phy_addr = gen_pool_virt_to_phys(drvdata->iram_pool, (ulong)buf_addr);
+ pr_debug("IRAM Range: Virt 0x%p - 0x%p, Phys 0x%x - 0x%x, size: 0x%x\n",
+ buf_addr, (buf_addr + buf_size - 1), (u32)phy_addr,
+ (u32)(phy_addr + buf_size - 1), buf_size);
+ pdevinfo->rbuf_base_virt = buf_addr;
+ pdevinfo->rbuf_base_phy = phy_addr;
+ drvdata->iram_size = buf_size;
+
+ memset(buf_addr, 0, buf_size);
+
+ for (j = 0; j < (TRANS_RING_NODES);
+ ++j, buf_addr += ring_buf_size, phy_addr += ring_buf_size) {
+ pdevinfo->rx_rbuf.virt_bufs[j] = buf_addr;
+ pdevinfo->rx_rbuf.phy_addrs[j] = phy_addr;
+ pr_debug("RX Ringbuf[%d]: 0x%p 0x%x\n",
+ j, buf_addr, (u32)phy_addr);
+ }
+ pdevinfo->rx_rbuf.unit_size = ring_buf_size;
+ pdevinfo->rx_rbuf.total_size = buf_size;
+ for (j = 0; j < (TRANS_RING_NODES);
+ ++j, buf_addr += ring_buf_size, phy_addr += ring_buf_size) {
+ pdevinfo->tx_rbuf.virt_bufs[j] = buf_addr;
+ pdevinfo->tx_rbuf.phy_addrs[j] = phy_addr;
+ pr_debug("TX Ringbuf[%d]: 0x%p 0x%x\n",
+ j, buf_addr, (u32)phy_addr);
+ }
+
+ pdevinfo->tx_rbuf.unit_size = ring_buf_size;
+ pdevinfo->tx_rbuf.total_size = buf_size;
+
+ /* reset the buffer read/write ptr */
+ pdevinfo->rx_rbuf.head = pdevinfo->rx_rbuf.tail = 0;
+ pdevinfo->tx_rbuf.head = pdevinfo->tx_rbuf.tail = 0;
+ pdevinfo->ex_event = 0;
+ pdevinfo->tx_ok = 0;
+
+ init_waitqueue_head(&pdevinfo->rx_wq);
+ init_waitqueue_head(&pdevinfo->tx_wq);
+
+ drvdata = container_of(inode->i_cdev, struct mlb_data, cdev);
+ drvdata->devinfo = pdevinfo;
+ mxc_mlb150_irq_enable(drvdata, 1);
+ filp->private_data = drvdata;
+
+ return 0;
+}
+
+static int mxc_mlb150_release(struct inode *inode, struct file *filp)
+{
+ int minor;
+ struct mlb_data *drvdata = filp->private_data;
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+
+ minor = MINOR(inode->i_rdev);
+ mxc_mlb150_irq_enable(drvdata, 0);
+
+#ifdef DEBUG
+ mlb150_dev_dump_reg();
+ mlb150_dev_dump_ctr_tbl(0, pdevinfo->channels[TX_CHANNEL].cl + 1);
+#endif
+
+ gen_pool_free(drvdata->iram_pool,
+ (ulong)pdevinfo->rbuf_base_virt, drvdata->iram_size);
+
+ mlb150_dev_exit();
+
+ if (pdevinfo && atomic_read(&pdevinfo->on)
+ && (pdevinfo->fps >= CLK_2048FS))
+ clk_disable_unprepare(drvdata->clk_mlb6p);
+
+ atomic_set(&pdevinfo->on, 0);
+
+ clk_disable_unprepare(drvdata->clk_mlb3p);
+ /* decrease the open count */
+ atomic_set(&pdevinfo->opencnt, 0);
+
+ drvdata->devinfo = NULL;
+
+ return 0;
+}
+
+static long mxc_mlb150_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ //struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = file_inode(filp);
+ struct mlb_data *drvdata = filp->private_data;
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+ void __user *argp = (void __user *)arg;
+ unsigned long flags, event;
+ int minor;
+
+ minor = MINOR(inode->i_rdev);
+
+ switch (cmd) {
+ case MLB_CHAN_SETADDR:
+ {
+ unsigned int caddr;
+ /* get channel address from user space */
+ if (copy_from_user(&caddr, argp, sizeof(caddr))) {
+ pr_err("mxc_mlb150: copy from user failed\n");
+ return -EFAULT;
+ }
+ pdevinfo->channels[TX_CHANNEL].address =
+ (caddr >> 16) & 0xFFFF;
+ pdevinfo->channels[RX_CHANNEL].address = caddr & 0xFFFF;
+ pr_debug("mxc_mlb150: set ch addr, tx: %d, rx: %d\n",
+ pdevinfo->channels[TX_CHANNEL].address,
+ pdevinfo->channels[RX_CHANNEL].address);
+ break;
+ }
+
+ case MLB_CHAN_STARTUP:
+ if (atomic_read(&pdevinfo->on)) {
+ pr_debug("mxc_mlb150: channel alreadly startup\n");
+ break;
+ }
+ if (mlb_channel_enable(drvdata, minor, 1))
+ return -EFAULT;
+ break;
+ case MLB_CHAN_SHUTDOWN:
+ if (atomic_read(&pdevinfo->on) == 0) {
+ pr_debug("mxc_mlb150: channel areadly shutdown\n");
+ break;
+ }
+ mlb150_trans_complete_check(pdevinfo);
+ mlb_channel_enable(drvdata, minor, 0);
+ break;
+ case MLB_CHAN_GETEVENT:
+ /* get and clear the ex_event */
+ spin_lock_irqsave(&pdevinfo->event_lock, flags);
+ event = pdevinfo->ex_event;
+ pdevinfo->ex_event = 0;
+ spin_unlock_irqrestore(&pdevinfo->event_lock, flags);
+
+ if (event) {
+ if (copy_to_user(argp, &event, sizeof(event))) {
+ pr_err("mxc_mlb150: copy to user failed\n");
+ return -EFAULT;
+ }
+ } else
+ return -EAGAIN;
+ break;
+ case MLB_SET_ISOC_BLKSIZE_188:
+ pdevinfo->isoc_blksz = 188;
+ pdevinfo->cdt_buf_dep = pdevinfo->adt_buf_dep =
+ pdevinfo->isoc_blksz * CH_ISOC_BLK_NUM;
+ break;
+ case MLB_SET_ISOC_BLKSIZE_196:
+ pdevinfo->isoc_blksz = 196;
+ pdevinfo->cdt_buf_dep = pdevinfo->adt_buf_dep =
+ pdevinfo->isoc_blksz * CH_ISOC_BLK_NUM;
+ break;
+ case MLB_SET_SYNC_QUAD:
+ {
+ u32 quad;
+
+ if (copy_from_user(&quad, argp, sizeof(quad))) {
+ pr_err("mxc_mlb150: get quad number "
+ "from user failed\n");
+ return -EFAULT;
+ }
+ if (quad <= 0 || quad > 3) {
+ pr_err("mxc_mlb150: Invalid Quadlets!"
+ "Quadlets in Sync mode can "
+ "only be 1, 2, 3\n");
+ return -EINVAL;
+ }
+ pdevinfo->sync_quad = quad;
+ /* Each quadlets is 4 bytes */
+ pdevinfo->cdt_buf_dep = quad * 4 * 4;
+ pdevinfo->adt_buf_dep =
+ pdevinfo->cdt_buf_dep * CH_SYNC_ADT_BUF_MULTI;
+ }
+ break;
+ case MLB_SET_FPS:
+ {
+ u32 fps, c0_val;
+
+ /* get fps from user space */
+ if (copy_from_user(&fps, argp, sizeof(fps))) {
+ pr_err("mxc_mlb150: copy from user failed\n");
+ return -EFAULT;
+ }
+
+ if ((fps > 1024) &&
+ !(drvdata->quirk_flag & MLB_QUIRK_MLB150)) {
+ pr_err("mxc_mlb150: not support fps %d\n", fps);
+ return -EINVAL;
+ }
+
+ c0_val = __raw_readl(mlb_base + REG_MLBC0);
+ c0_val &= ~MLBC0_MLBCLK_MASK;
+
+ /* check fps value */
+ switch (fps) {
+ case 256:
+ case 512:
+ case 1024:
+ pdevinfo->fps = fps >> 9;
+ c0_val &= ~MLBC0_MLBPEN;
+ c0_val |= (fps >> 9)
+ << MLBC0_MLBCLK_SHIFT;
+
+ if (1024 == fps) {
+ /*
+ * Invert output clock phase
+ * in 1024 fps
+ */
+ __raw_writel(0x1,
+ mlb_base + REG_MLBPC2);
+ }
+ break;
+ case 2048:
+ case 3072:
+ case 4096:
+ pdevinfo->fps = (fps >> 10) + 1;
+ c0_val |= ((fps >> 10) + 1)
+ << MLBC0_MLBCLK_SHIFT;
+ break;
+ case 6144:
+ pdevinfo->fps = fps >> 10;
+ c0_val |= ((fps >> 10) + 1)
+ << MLBC0_MLBCLK_SHIFT;
+ break;
+ case 8192:
+ pdevinfo->fps = (fps >> 10) - 1;
+ c0_val |= ((fps >> 10) - 1)
+ << MLBC0_MLBCLK_SHIFT;
+ break;
+ default:
+ pr_debug("mxc_mlb150: invalid fps argument: %d\n",
+ fps);
+ return -EINVAL;
+ }
+
+ __raw_writel(c0_val, mlb_base + REG_MLBC0);
+
+ pr_debug("mxc_mlb150: set fps to %d, MLBC0: 0x%08x\n",
+ fps,
+ (u32)__raw_readl(mlb_base + REG_MLBC0));
+
+ break;
+ }
+
+ case MLB_GET_VER:
+ {
+ u32 version;
+
+ /* get MLB device module version */
+ version = 0x03030003;
+
+ pr_debug("mxc_mlb150: get version: 0x%08x\n",
+ version);
+
+ if (copy_to_user(argp, &version, sizeof(version))) {
+ pr_err("mxc_mlb150: copy to user failed\n");
+ return -EFAULT;
+ }
+ break;
+ }
+
+ case MLB_SET_DEVADDR:
+ {
+ u32 c1_val;
+ u8 devaddr;
+
+ /* get MLB device address from user space */
+ if (copy_from_user
+ (&devaddr, argp, sizeof(unsigned char))) {
+ pr_err("mxc_mlb150: copy from user failed\n");
+ return -EFAULT;
+ }
+
+ c1_val = __raw_readl(mlb_base + REG_MLBC1);
+ c1_val &= ~MLBC1_NDA_MASK;
+ c1_val |= devaddr << MLBC1_NDA_SHIFT;
+ __raw_writel(c1_val, mlb_base + REG_MLBC1);
+ pr_debug("mxc_mlb150: set dev addr, dev addr: %d, "
+ "MLBC1: 0x%08x\n", devaddr,
+ (u32)__raw_readl(mlb_base + REG_MLBC1));
+
+ break;
+ }
+
+ case MLB_IRQ_DISABLE:
+ {
+ disable_irq(drvdata->irq_mlb);
+ break;
+ }
+
+ case MLB_IRQ_ENABLE:
+ {
+ enable_irq(drvdata->irq_mlb);
+ break;
+ }
+ default:
+ pr_info("mxc_mlb150: Invalid ioctl command\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * MLB read routine
+ * Read the current received data from queued buffer,
+ * and free this buffer for hw to fill ingress data.
+ */
+static ssize_t mxc_mlb150_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ int size;
+ struct mlb_data *drvdata = filp->private_data;
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+ struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
+ int head, tail;
+ unsigned long flags;
+
+ read_lock_irqsave(&rx_rbuf->rb_lock, flags);
+
+ head = ACCESS_ONCE(rx_rbuf->head);
+ tail = rx_rbuf->tail;
+
+ read_unlock_irqrestore(&rx_rbuf->rb_lock, flags);
+
+ /* check the current rx buffer is available or not */
+ if (0 == CIRC_CNT(head, tail, TRANS_RING_NODES)) {
+
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ do {
+ DEFINE_WAIT(__wait);
+
+ for (;;) {
+ prepare_to_wait(&pdevinfo->rx_wq,
+ &__wait, TASK_INTERRUPTIBLE);
+
+ read_lock_irqsave(&rx_rbuf->rb_lock, flags);
+ if (CIRC_CNT(rx_rbuf->head, rx_rbuf->tail,
+ TRANS_RING_NODES) > 0) {
+ read_unlock_irqrestore(&rx_rbuf->rb_lock,
+ flags);
+ break;
+ }
+ read_unlock_irqrestore(&rx_rbuf->rb_lock,
+ flags);
+
+ if (!signal_pending(current)) {
+ schedule();
+ continue;
+ }
+ return -ERESTARTSYS;
+ }
+ finish_wait(&pdevinfo->rx_wq, &__wait);
+ } while (0);
+ }
+
+ /* read index before reading contents at that index */
+ smp_read_barrier_depends();
+
+ size = pdevinfo->adt_buf_dep;
+ if (size > count) {
+ /* the user buffer is too small */
+ pr_warning
+ ("mxc_mlb150: received data size is bigger than "
+ "size: %d, count: %d\n", size, count);
+ return -EINVAL;
+ }
+
+ /* extract one item from the buffer */
+ if (copy_to_user(buf, rx_rbuf->virt_bufs[tail], size)) {
+ pr_err("mxc_mlb150: copy from user failed\n");
+ return -EFAULT;
+ }
+
+ /* finish reading descriptor before incrementing tail */
+ smp_mb();
+
+ write_lock_irqsave(&rx_rbuf->rb_lock, flags);
+ rx_rbuf->tail = (tail + 1) & (TRANS_RING_NODES - 1);
+ write_unlock_irqrestore(&rx_rbuf->rb_lock, flags);
+
+ *f_pos = 0;
+
+ return size;
+}
+
+/*
+ * MLB write routine
+ * Copy the user data to tx channel buffer,
+ * and prepare the channel current/next buffer ptr.
+ */
+static ssize_t mxc_mlb150_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ s32 ret = 0;
+ struct mlb_channel_info *pchinfo = NULL;
+ struct mlb_data *drvdata = filp->private_data;
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+ struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
+ int head, tail;
+ unsigned long flags;
+
+ /*
+ * minor = MINOR(filp->f_dentry->d_inode->i_rdev);
+ */
+ pchinfo = &pdevinfo->channels[TX_CHANNEL];
+
+ if (count > pdevinfo->buf_size) {
+ /* too many data to write */
+ pr_warning("mxc_mlb150: overflow write data\n");
+ return -EFBIG;
+ }
+
+ *f_pos = 0;
+
+ read_lock_irqsave(&tx_rbuf->rb_lock, flags);
+
+ head = tx_rbuf->head;
+ tail = ACCESS_ONCE(tx_rbuf->tail);
+ read_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
+
+ if (0 == CIRC_SPACE(head, tail, TRANS_RING_NODES)) {
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ do {
+ DEFINE_WAIT(__wait);
+
+ for (;;) {
+ prepare_to_wait(&pdevinfo->tx_wq,
+ &__wait, TASK_INTERRUPTIBLE);
+
+ read_lock_irqsave(&tx_rbuf->rb_lock, flags);
+ if (CIRC_SPACE(tx_rbuf->head, tx_rbuf->tail,
+ TRANS_RING_NODES) > 0) {
+ read_unlock_irqrestore(&tx_rbuf->rb_lock,
+ flags);
+ break;
+ }
+ read_unlock_irqrestore(&tx_rbuf->rb_lock,
+ flags);
+
+ if (!signal_pending(current)) {
+ schedule();
+ continue;
+ }
+ return -ERESTARTSYS;
+ }
+ finish_wait(&pdevinfo->tx_wq, &__wait);
+ } while (0);
+ }
+
+ if (copy_from_user((void *)tx_rbuf->virt_bufs[head], buf, count)) {
+ read_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
+ pr_err("mxc_mlb: copy from user failed\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ write_lock_irqsave(&tx_rbuf->rb_lock, flags);
+ smp_wmb();
+ tx_rbuf->head = (head + 1) & (TRANS_RING_NODES - 1);
+ write_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
+
+ if (0 == CIRC_CNT(head, tail, TRANS_RING_NODES)) {
+ u32 tx_buf_ptr, ahb_ch;
+ s32 adt_sts;
+ u32 ctype = pdevinfo->channel_type;
+
+ /* read index before reading contents at that index */
+ smp_read_barrier_depends();
+
+ tx_buf_ptr = tx_rbuf->phy_addrs[tail];
+
+ ahb_ch = pdevinfo->channels[TX_CHANNEL].cl;
+ adt_sts = mlb150_dev_get_adt_sts(ahb_ch);
+
+ /* Set ADT for TX */
+ mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, tx_buf_ptr);
+ }
+
+ ret = count;
+out:
+ return ret;
+}
+
+static unsigned int mxc_mlb150_poll(struct file *filp,
+ struct poll_table_struct *wait)
+{
+ int minor;
+ unsigned int ret = 0;
+ struct mlb_data *drvdata = filp->private_data;
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+ struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
+ struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
+ int head, tail;
+ unsigned long flags;
+
+
+ minor = MINOR(file_inode(filp)->i_rdev);
+
+ poll_wait(filp, &pdevinfo->rx_wq, wait);
+ poll_wait(filp, &pdevinfo->tx_wq, wait);
+
+ read_lock_irqsave(&tx_rbuf->rb_lock, flags);
+ head = tx_rbuf->head;
+ tail = tx_rbuf->tail;
+ read_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
+
+ /* check the tx buffer is avaiable or not */
+ if (CIRC_SPACE(head, tail, TRANS_RING_NODES) >= 1)
+ ret |= POLLOUT | POLLWRNORM;
+
+ read_lock_irqsave(&rx_rbuf->rb_lock, flags);
+ head = rx_rbuf->head;
+ tail = rx_rbuf->tail;
+ read_unlock_irqrestore(&rx_rbuf->rb_lock, flags);
+
+ /* check the rx buffer filled or not */
+ if (CIRC_CNT(head, tail, TRANS_RING_NODES) >= 1)
+ ret |= POLLIN | POLLRDNORM;
+
+
+ /* check the exception event */
+ if (pdevinfo->ex_event)
+ ret |= POLLIN | POLLRDNORM;
+
+ return ret;
+}
+
+/*
+ * char dev file operations structure
+ */
+static const struct file_operations mxc_mlb150_fops = {
+
+ .owner = THIS_MODULE,
+ .open = mxc_mlb150_open,
+ .release = mxc_mlb150_release,
+ .unlocked_ioctl = mxc_mlb150_ioctl,
+ .poll = mxc_mlb150_poll,
+ .read = mxc_mlb150_read,
+ .write = mxc_mlb150_write,
+};
+
+static struct platform_device_id imx_mlb150_devtype[] = {
+ {
+ .name = "imx6q-mlb150",
+ .driver_data = MLB_QUIRK_MLB150,
+ }, {
+ .name = "imx6sx-mlb50",
+ .driver_data = 0,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imx_mlb150_devtype);
+
+static const struct of_device_id mlb150_imx_dt_ids[] = {
+ { .compatible = "fsl,imx6q-mlb150",
+ .data = &imx_mlb150_devtype[IMX6Q_MLB], },
+ { .compatible = "fsl,imx6sx-mlb50",
+ .data = &imx_mlb150_devtype[IMX6SX_MLB], },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mlb150_imx_dt_ids);
+
+/*
+ * This function is called whenever the MLB device is detected.
+ */
+static int mxc_mlb150_probe(struct platform_device *pdev)
+{
+ int ret, mlb_major, i;
+ struct mlb_data *drvdata;
+ struct resource *res;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id;
+
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(struct mlb_data),
+ GFP_KERNEL);
+ if (!drvdata) {
+ dev_err(&pdev->dev, "can't allocate enough memory\n");
+ return -ENOMEM;
+ }
+
+ of_id = of_match_device(mlb150_imx_dt_ids, &pdev->dev);
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ else
+ return -EINVAL;
+ /*
+ * Register MLB lld as four character devices
+ */
+ ret = alloc_chrdev_region(&drvdata->firstdev, 0,
+ MLB_MINOR_DEVICES, "mxc_mlb150");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "alloc region error\n");
+ goto err_reg;
+ }
+ mlb_major = MAJOR(drvdata->firstdev);
+ dev_dbg(&pdev->dev, "MLB device major: %d\n", mlb_major);
+
+ cdev_init(&drvdata->cdev, &mxc_mlb150_fops);
+ drvdata->cdev.owner = THIS_MODULE;
+
+ ret = cdev_add(&drvdata->cdev, drvdata->firstdev, MLB_MINOR_DEVICES);
+ if (ret) {
+ dev_err(&pdev->dev, "can't add cdev\n");
+ goto err_reg;
+ }
+
+ /* create class and device for udev information */
+ drvdata->class = class_create(THIS_MODULE, "mlb150");
+ if (IS_ERR(drvdata->class)) {
+ dev_err(&pdev->dev, "failed to create device class\n");
+ ret = -ENOMEM;
+ goto err_class;
+ }
+
+ for (i = 0; i < MLB_MINOR_DEVICES; i++) {
+ struct device *class_dev;
+
+ class_dev = device_create(drvdata->class, NULL,
+ MKDEV(mlb_major, i),
+ NULL, mlb_devinfo[i].dev_name);
+ if (IS_ERR(class_dev)) {
+ dev_err(&pdev->dev, "failed to create mlb150 %s"
+ " class device\n", mlb_devinfo[i].dev_name);
+ ret = -ENOMEM;
+ goto err_dev;
+ }
+ }
+
+ drvdata->quirk_flag = pdev->id_entry->driver_data;
+
+ /* ahb0 irq */
+ drvdata->irq_ahb0 = platform_get_irq(pdev, 1);
+ if (drvdata->irq_ahb0 < 0) {
+ dev_err(&pdev->dev, "No ahb0 irq line provided\n");
+ goto err_dev;
+ }
+ dev_dbg(&pdev->dev, "ahb0_irq: %d\n", drvdata->irq_ahb0);
+ if (devm_request_irq(&pdev->dev, drvdata->irq_ahb0, mlb_ahb_isr,
+ 0, "mlb_ahb0", NULL)) {
+ dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_ahb0);
+ goto err_dev;
+ }
+
+ /* ahb1 irq */
+ drvdata->irq_ahb1 = platform_get_irq(pdev, 2);
+ if (drvdata->irq_ahb1 < 0) {
+ dev_err(&pdev->dev, "No ahb1 irq line provided\n");
+ goto err_dev;
+ }
+ dev_dbg(&pdev->dev, "ahb1_irq: %d\n", drvdata->irq_ahb1);
+ if (devm_request_irq(&pdev->dev, drvdata->irq_ahb1, mlb_ahb_isr,
+ 0, "mlb_ahb1", NULL)) {
+ dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_ahb1);
+ goto err_dev;
+ }
+
+ /* mlb irq */
+ drvdata->irq_mlb = platform_get_irq(pdev, 0);
+ if (drvdata->irq_mlb < 0) {
+ dev_err(&pdev->dev, "No mlb irq line provided\n");
+ goto err_dev;
+ }
+ dev_dbg(&pdev->dev, "mlb_irq: %d\n", drvdata->irq_mlb);
+ if (devm_request_irq(&pdev->dev, drvdata->irq_mlb, mlb_isr,
+ 0, "mlb", NULL)) {
+ dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_mlb);
+ goto err_dev;
+ }
+
+ /* ioremap from phy mlb to kernel space */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't get device resources\n");
+ ret = -ENOENT;
+ goto err_dev;
+ }
+ mlb_base = devm_ioremap_resource(&pdev->dev, res);
+ dev_dbg(&pdev->dev, "mapped base address: 0x%08x\n", (u32)mlb_base);
+ if (IS_ERR(mlb_base)) {
+ dev_err(&pdev->dev,
+ "failed to get ioremap base\n");
+ ret = PTR_ERR(mlb_base);
+ goto err_dev;
+ }
+ drvdata->membase = mlb_base;
+
+#ifdef CONFIG_REGULATOR
+ drvdata->nvcc = devm_regulator_get(&pdev->dev, "reg_nvcc");
+ if (!IS_ERR(drvdata->nvcc)) {
+ regulator_set_voltage(drvdata->nvcc, 2500000, 2500000);
+ dev_err(&pdev->dev, "enalbe regulator\n");
+ ret = regulator_enable(drvdata->nvcc);
+ if (ret) {
+ dev_err(&pdev->dev, "vdd set voltage error\n");
+ goto err_dev;
+ }
+ }
+#endif
+
+ /* enable clock */
+ drvdata->clk_mlb3p = devm_clk_get(&pdev->dev, "mlb");
+ if (IS_ERR(drvdata->clk_mlb3p)) {
+ dev_err(&pdev->dev, "unable to get mlb clock\n");
+ ret = PTR_ERR(drvdata->clk_mlb3p);
+ goto err_dev;
+ }
+
+ if (drvdata->quirk_flag & MLB_QUIRK_MLB150) {
+ drvdata->clk_mlb6p = devm_clk_get(&pdev->dev, "pll8_mlb");
+ if (IS_ERR(drvdata->clk_mlb6p)) {
+ dev_err(&pdev->dev, "unable to get mlb pll clock\n");
+ ret = PTR_ERR(drvdata->clk_mlb6p);
+ goto err_dev;
+ }
+ }
+
+ drvdata->iram_pool = of_gen_pool_get(np, "iram", 0);
+ if (!drvdata->iram_pool) {
+ dev_err(&pdev->dev, "iram pool not available\n");
+ ret = -ENOMEM;
+ goto err_dev;
+ }
+
+ drvdata->devinfo = NULL;
+ mxc_mlb150_irq_enable(drvdata, 0);
+ platform_set_drvdata(pdev, drvdata);
+ return 0;
+
+err_dev:
+ for (--i; i >= 0; i--)
+ device_destroy(drvdata->class, MKDEV(mlb_major, i));
+
+ class_destroy(drvdata->class);
+err_class:
+ cdev_del(&drvdata->cdev);
+err_reg:
+ unregister_chrdev_region(drvdata->firstdev, MLB_MINOR_DEVICES);
+
+ return ret;
+}
+
+static int mxc_mlb150_remove(struct platform_device *pdev)
+{
+ int i;
+ struct mlb_data *drvdata = platform_get_drvdata(pdev);
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+
+ if (pdevinfo && atomic_read(&pdevinfo->on)
+ && (pdevinfo->fps >= CLK_2048FS))
+ clk_disable_unprepare(drvdata->clk_mlb6p);
+
+ if (pdevinfo && atomic_read(&pdevinfo->opencnt))
+ clk_disable_unprepare(drvdata->clk_mlb3p);
+
+ /* disable mlb power */
+#ifdef CONFIG_REGULATOR
+ if (!IS_ERR(drvdata->nvcc))
+ regulator_disable(drvdata->nvcc);
+#endif
+
+ /* destroy mlb device class */
+ for (i = MLB_MINOR_DEVICES - 1; i >= 0; i--)
+ device_destroy(drvdata->class,
+ MKDEV(MAJOR(drvdata->firstdev), i));
+ class_destroy(drvdata->class);
+
+ cdev_del(&drvdata->cdev);
+
+ /* Unregister the two MLB devices */
+ unregister_chrdev_region(drvdata->firstdev, MLB_MINOR_DEVICES);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxc_mlb150_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct mlb_data *drvdata = platform_get_drvdata(pdev);
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+
+ if (pdevinfo && atomic_read(&pdevinfo->on)
+ && (pdevinfo->fps >= CLK_2048FS))
+ clk_disable_unprepare(drvdata->clk_mlb6p);
+
+ if (pdevinfo && atomic_read(&pdevinfo->opencnt)) {
+ mlb150_dev_exit();
+ clk_disable_unprepare(drvdata->clk_mlb3p);
+ }
+
+ return 0;
+}
+
+static int mxc_mlb150_resume(struct platform_device *pdev)
+{
+ struct mlb_data *drvdata = platform_get_drvdata(pdev);
+ struct mlb_dev_info *pdevinfo = drvdata->devinfo;
+
+ if (pdevinfo && atomic_read(&pdevinfo->opencnt)) {
+ clk_prepare_enable(drvdata->clk_mlb3p);
+ mlb150_dev_init();
+ }
+
+ if (pdevinfo && atomic_read(&pdevinfo->on) &&
+ (pdevinfo->fps >= CLK_2048FS))
+ clk_prepare_enable(drvdata->clk_mlb6p);
+
+ return 0;
+}
+#else
+#define mxc_mlb150_suspend NULL
+#define mxc_mlb150_resume NULL
+#endif
+
+/*
+ * platform driver structure for MLB
+ */
+static struct platform_driver mxc_mlb150_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = mlb150_imx_dt_ids,
+ },
+ .probe = mxc_mlb150_probe,
+ .remove = mxc_mlb150_remove,
+ .suspend = mxc_mlb150_suspend,
+ .resume = mxc_mlb150_resume,
+ .id_table = imx_mlb150_devtype,
+};
+
+static int __init mxc_mlb150_init(void)
+{
+ return platform_driver_register(&mxc_mlb150_driver);
+}
+
+static void __exit mxc_mlb150_exit(void)
+{
+ platform_driver_unregister(&mxc_mlb150_driver);
+}
+
+module_init(mxc_mlb150_init);
+module_exit(mxc_mlb150_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MLB150 low level driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mxc/sim/Kconfig b/drivers/mxc/sim/Kconfig
new file mode 100644
index 000000000000..c8ccc47e8643
--- /dev/null
+++ b/drivers/mxc/sim/Kconfig
@@ -0,0 +1,13 @@
+#
+# SIM configuration
+#
+
+menu "MXC SIM Support"
+
+config MXC_SIM
+ tristate "MXC SIM support"
+ default n
+ ---help---
+ Say Y to get MXC SIM support.
+
+endmenu
diff --git a/drivers/mxc/sim/Makefile b/drivers/mxc/sim/Makefile
new file mode 100644
index 000000000000..11796e95a956
--- /dev/null
+++ b/drivers/mxc/sim/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the i.MX SIM driver
+#
+
+obj-$(CONFIG_MXC_SIM) += imx_sim.o
diff --git a/drivers/mxc/sim/imx_sim.c b/drivers/mxc/sim/imx_sim.c
new file mode 100755
index 000000000000..d33c11a9ecbb
--- /dev/null
+++ b/drivers/mxc/sim/imx_sim.c
@@ -0,0 +1,1865 @@
+/*
+ * 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/module.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mxc_sim_interface.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+
+#include <linux/io.h>
+
+#define DRIVER_NAME "mxc_sim"
+#define SIM_INTERNAL_CLK (0)
+#define SIM_RFU (-1)
+
+/* Transmit and receive buffer sizes */
+#define SIM_XMT_BUFFER_SIZE (300)
+#define SIM_RCV_BUFFER_SIZE (400)
+
+#define SIM_TX_FIFO_DEPTH (16)
+#define SIM_RX_FIFO_DEPTH (285)
+
+#define TX_FIFO_THRESHOLD (0x04)
+#define RX_FIFO_THRESHOLD (250)
+
+/* Interface character references */
+#define SIM_IFC_TXI(letter, number) (letter + number * 4)
+#define SIM_IFC_TA1 SIM_IFC_TXI(0, 0)
+#define SIM_IFC_TB1 SIM_IFC_TXI(0, 1)
+#define SIM_IFC_TC1 SIM_IFC_TXI(0, 2)
+#define SIM_IFC_TD1 SIM_IFC_TXI(0, 3)
+#define SIM_IFC_TA2 SIM_IFC_TXI(1, 0)
+#define SIM_IFC_TB2 SIM_IFC_TXI(1, 1)
+#define SIM_IFC_TC2 SIM_IFC_TXI(1, 2)
+#define SIM_IFC_TD2 SIM_IFC_TXI(1, 3)
+#define SIM_IFC_TA3 SIM_IFC_TXI(2, 0)
+#define SIM_IFC_TB3 SIM_IFC_TXI(2, 1)
+#define SIM_IFC_TC3 SIM_IFC_TXI(2, 2)
+#define SIM_IFC_TD3 SIM_IFC_TXI(2, 3)
+#define SIM_IFC_TA4 SIM_IFC_TXI(3, 0)
+#define SIM_IFC_TB4 SIM_IFC_TXI(3, 1)
+#define SIM_IFC_TC4 SIM_IFC_TXI(3, 2)
+#define SIM_IFC_TD4 SIM_IFC_TXI(3, 3)
+
+/* ATR and OPS states */
+#define SIM_STATE_REMOVED (0)
+#define SIM_STATE_DETECTED (1)
+#define SIM_STATE_ATR_RECEIVING (2)
+#define SIM_STATE_ATR_RECEIVED (3)
+#define SIM_STATE_XMTING (4)
+#define SIM_STATE_XMT_DONE (5)
+#define SIM_STATE_XMT_ERROR (6)
+#define SIM_STATE_RECEIVING (7)
+#define SIM_STATE_RECEIVE_DONE (8)
+#define SIM_STATE_RECEIVE_ERROR (9)
+#define SIM_STATE_RESET_SEQUENCY (10)
+
+/* Definitions of the offset of the SIM hardware registers */
+#define PORT1_CNTL (0x00)
+#define SETUP (0x04)
+#define PORT1_DETECT (0x08)
+#define PORT1_XMT_BUF (0x0C)
+#define PORT1_RCV_BUF (0x10)
+#define PORT0_CNTL (0x14)
+#define CNTL (0x18)
+#define CLK_PRESCALER (0x1C)
+#define RCV_THRESHOLD (0x20)
+#define ENABLE (0x24)
+#define XMT_STATUS (0x28)
+#define RCV_STATUS (0x2C)
+#define INT_MASK (0x30)
+#define PORTO_XMT_BUF (0x34)
+#define PORT0_RCV_BUF (0x38)
+#define PORT0_DETECT (0x3C)
+#define DATA_FORMAT (0x40)
+#define XMT_THRESHOLD (0x44)
+#define GUARD_CNTL (0x48)
+#define OD_CONFIG (0x4C)
+#define RESET_CNTL (0x50)
+#define CHAR_WAIT (0x54)
+#define GPCNT (0x58)
+#define DIVISOR (0x5C)
+#define BWT (0x60)
+#define BGT (0x64)
+#define BWT_H (0x68)
+#define XMT_FIFO_STAT (0x6C)
+#define RCV_FIFO_CNT (0x70)
+#define RCV_FIFO_WPTR (0x74)
+#define RCV_FIFO_RPTR (0x78)
+
+/* SIM SETUP register bits */
+#define SIM_SETUP_SPS_PORT0 (0 << 1)
+#define SIM_SETUP_SPS_PORT1 (1 << 1)
+
+/* SIM port[0|1]_cntl register bits */
+#define SIM_PORT_CNTL_SFPD (1 << 7)
+#define SIM_PORT_CNTL_3VOLT (1 << 6)
+#define SIM_PORT_CNTL_SCSP (1 << 5)
+#define SIM_PORT_CNTL_SCEN (1 << 4)
+#define SIM_PORT_CNTL_SRST (1 << 3)
+#define SIM_PORT_CNTL_STEN (1 << 2)
+#define SIM_PORT_CNTL_SVEN (1 << 1)
+#define SIM_PORT_CNTL_SAPD (1 << 0)
+
+/* SIM od_config register bits */
+#define SIM_OD_CONFIG_OD_P1 (1 << 1)
+#define SIM_OD_CONFIG_OD_P0 (1 << 0)
+
+/* SIM enable register bits */
+#define SIM_ENABLE_XMTEN (1 << 1)
+#define SIM_ENABLE_RCVEN (1 << 0)
+#define SIM_ESTOP_EN (1 << 5)
+#define SIM_ESTOP_EXE (1 << 6)
+
+/* SIM int_mask register bits */
+#define SIM_INT_MASK_RFEM (1 << 13)
+#define SIM_INT_MASK_BGTM (1 << 12)
+#define SIM_INT_MASK_BWTM (1 << 11)
+#define SIM_INT_MASK_RTM (1 << 10)
+#define SIM_INT_MASK_CWTM (1 << 9)
+#define SIM_INT_MASK_GPCM (1 << 8)
+#define SIM_INT_MASK_TDTFM (1 << 7)
+#define SIM_INT_MASK_TFOM (1 << 6)
+#define SIM_INT_MASK_XTM (1 << 5)
+#define SIM_INT_MASK_TFEIM (1 << 4)
+#define SIM_INT_MASK_ETCIM (1 << 3)
+#define SIM_INT_MASK_OIM (1 << 2)
+#define SIM_INT_MASK_TCIM (1 << 1)
+#define SIM_INT_MASK_RIM (1 << 0)
+
+/* SIM xmt_status register bits */
+#define SIM_XMT_STATUS_GPCNT (1 << 8)
+#define SIM_XMT_STATUS_TDTF (1 << 7)
+#define SIM_XMT_STATUS_TFO (1 << 6)
+#define SIM_XMT_STATUS_TC (1 << 5)
+#define SIM_XMT_STATUS_ETC (1 << 4)
+#define SIM_XMT_STATUS_TFE (1 << 3)
+#define SIM_XMT_STATUS_XTE (1 << 0)
+
+/* SIM rcv_status register bits */
+#define SIM_RCV_STATUS_BGT (1 << 11)
+#define SIM_RCV_STATUS_BWT (1 << 10)
+#define SIM_RCV_STATUS_RTE (1 << 9)
+#define SIM_RCV_STATUS_CWT (1 << 8)
+#define SIM_RCV_STATUS_CRCOK (1 << 7)
+#define SIM_RCV_STATUS_LRCOK (1 << 6)
+#define SIM_RCV_STATUS_RDRF (1 << 5)
+#define SIM_RCV_STATUS_RFD (1 << 4)
+#define SIM_RCV_STATUS_RFE (1 << 1)
+#define SIM_RCV_STATUS_OEF (1 << 0)
+
+/* SIM cntl register bits */
+#define SIM_CNTL_BWTEN (1 << 15)
+#define SIM_CNTL_XMT_CRC_LRC (1 << 14)
+#define SIM_CNTL_CRCEN (1 << 13)
+#define SIM_CNTL_LRCEN (1 << 12)
+#define SIM_CNTL_CWTEN (1 << 11)
+#define SIM_CNTL_SAMPLE12 (1 << 4)
+#define SIM_CNTL_ONACK (1 << 3)
+#define SIM_CNTL_ANACK (1 << 2)
+#define SIM_CNTL_ICM (1 << 1)
+#define SIM_CNTL_GPCNT_CLK_SEL(x) ((x&0x03) << 9)
+#define SIM_CNTL_GPCNT_CLK_SEL_MASK (0x03 << 9)
+#define SIM_CNTL_BAUD_SEL(x) ((x&0x07) << 6)
+#define SIM_CNTL_BAUD_SEL_MASK (0x07 << 6)
+#define SIM_CNTL_GPCNT_CARD_CLK 1
+#define SIM_CNTL_GPCNT_RCV_CLK 2
+#define SIM_CNTL_GPCNT_ETU_CLK 3
+
+/* SIM rcv_threshold register bits */
+#define SIM_RCV_THRESHOLD_RTH(x) ((x&0x0f) << 9)
+#define SIM_RCV_THRESHOLD_RTH_MASK (0x0f << 9)
+#define SIM_RCV_THRESHOLD_RDT(x) ((x&0x1ff) << 0)
+#define SIM_RCV_THRESHOLD_RDT_MASK (0x1ff << 0)
+
+/* SIM xmt_threshold register bits */
+#define SIM_XMT_THRESHOLD_XTH(x) ((x&0x0f) << 4)
+#define SIM_XMT_THRESHOLD_XTH_MASK (0x0f << 4)
+#define SIM_XMT_THRESHOLD_TDT(x) ((x&0x0f) << 0)
+#define SIM_XMT_THRESHOLD_TDT_MASK (0x0f << 0)
+
+/* SIM guard_cntl register bits */
+#define SIM_GUARD_CNTL_RCVR11 (1 << 8)
+#define SIM_GIARD_CNTL_GETU(x) (x&0xff)
+#define SIM_GIARD_CNTL_GETU_MASK (0xff)
+
+/* SIM port[0|]_detect register bits */
+#define SIM_PORT_DETECT_SPDS (1 << 3)
+#define SIM_PORT_DETECT_SPDP (1 << 2)
+#define SIM_PORT_DETECT_SDI (1 << 1)
+#define SIM_PORT_DETECT_SDIM (1 << 0)
+
+/* SIM RESET_CNTL register bits*/
+#define SIM_RESET_CNTL_FLUSH_RCV (1 << 0)
+#define SIM_RESET_CNTL_FLUSH_XMT (1 << 1)
+#define SIM_RESET_CNTL_SOFT_RESET (1 << 2)
+#define SIM_RESET_CNTL_KILL_CLOCK (1 << 3)
+#define SIM_RESET_CNTL_DOZE (1 << 4)
+#define SIM_RESET_CNTL_STOP (1 << 5)
+#define SIM_RESET_CNTL_DEBUG (1 << 6)
+
+
+/*SIM receive buffer register error status*/
+#define SIM_REC_CWT_ERROR (1 << 10)
+#define SIM_REC_FRAME_ERROR (1 << 9)
+#define SIM_REC_PARITY_ERROR (1 << 8)
+
+#define SIM_EMV_NACK_THRESHOLD (5)
+#define EMV_T0_BGT (16)
+#define EMV_T1_BGT (22)
+#define ATR_THRESHOLD_MAX (100)
+#define ATR_MAX_CWT (10080)
+#define ATR_MAX_DURATION (20160)
+#define FCLK_FREQ (4000000)
+
+#define ATR_TIMEOUT (5)
+#define TX_TIMEOUT (10)
+#define RX_TIMEOUT (100)
+#define RESET_RETRY_TIMES (5)
+#define SIM_QUIRK_TKT259347 (1 << 0)
+#define EMV_RESET_LOW_CYCLES 40000
+#define ATR_MAX_DELAY_CLK 46400
+
+/* Main SIM driver structure */
+struct sim_t{
+ s32 present;
+ u8 open_cnt;
+ int state;
+ struct clk *clk;
+ struct resource *res;
+ void __iomem *ioaddr;
+ int ipb_irq;
+ int dat_irq;
+
+ /* error code occured during transfer */
+ int errval;
+ int protocol_type;
+ sim_timing_t timing_data;
+ sim_baud_t baud_rate;
+ int timeout;
+ u8 nack_threshold;
+ u8 nack_enable;
+ u32 expected_rcv_cnt;
+ u8 is_fixed_len_rec;
+
+ /* remaining bytes to transmit for the current transfer */
+ u32 xmt_remaining;
+ /* transmit position */
+ u32 xmt_pos;
+ /* receive position / number of bytes received */
+ u32 rcv_count;
+ u8 rcv_buffer[SIM_RCV_BUFFER_SIZE];
+ u8 xmt_buffer[SIM_XMT_BUFFER_SIZE];
+ /* transfer completion notifier */
+ struct completion xfer_done;
+ /* async notifier for card and ATR detection */
+ struct fasync_struct *fasync;
+ /* Platform specific data */
+ struct mxc_sim_platform_data *plat_data;
+ bool last_is_tx;
+ u16 rcv_head;
+ spinlock_t lock;
+ bool sven_low_active;
+ u32 port_index;
+ u32 port_detect_reg;
+ u32 port_ctrl_reg;
+ u32 clk_rate;
+ u32 quirks;
+ u8 checking_ts_timing;
+};
+
+static struct miscdevice sim_dev;
+
+static void sim_data_reset(struct sim_t *sim)
+{
+ sim->errval = SIM_OK;
+ sim->protocol_type = 0;
+ sim->timeout = 0;
+ sim->nack_threshold = SIM_EMV_NACK_THRESHOLD;
+ sim->nack_enable = 0;
+ memset(&sim->timing_data, 0, sizeof(sim->timing_data));
+ memset(&sim->baud_rate, 0, sizeof(sim->baud_rate));
+
+ sim->xmt_remaining = 0;
+ sim->xmt_pos = 0;
+ sim->rcv_count = 0;
+ sim->rcv_head = 0;
+ sim->last_is_tx = false;
+ memset(sim->rcv_buffer, 0, SIM_RCV_BUFFER_SIZE);
+ memset(sim->xmt_buffer, 0, SIM_XMT_BUFFER_SIZE);
+
+ init_completion(&sim->xfer_done);
+};
+
+static void sim_set_nack(struct sim_t *sim, u8 enable)
+{
+ u32 reg_val;
+
+ reg_val = __raw_readl(sim->ioaddr + CNTL);
+ /*Disable overrun NACK setting for now*/
+ reg_val &= ~(SIM_CNTL_ONACK);
+
+ if (enable) {
+ reg_val |= SIM_CNTL_ANACK;
+ __raw_writel(reg_val, sim->ioaddr + CNTL);
+ reg_val = __raw_readl(sim->ioaddr + XMT_THRESHOLD);
+ reg_val &= ~(SIM_XMT_THRESHOLD_XTH_MASK);
+ reg_val |= SIM_XMT_THRESHOLD_XTH(sim->nack_threshold);
+ __raw_writel(reg_val, sim->ioaddr + XMT_THRESHOLD);
+ } else {
+ reg_val &= ~SIM_CNTL_ANACK;
+ __raw_writel(reg_val, sim->ioaddr + CNTL);
+ }
+
+ sim->nack_enable = enable;
+}
+
+static void sim_set_tx(struct sim_t *sim, u8 enable)
+{
+ u32 reg_data;
+
+ reg_data = __raw_readl(sim->ioaddr + ENABLE);
+ if (enable) {
+ reg_data |= SIM_ENABLE_XMTEN | SIM_ENABLE_RCVEN;
+ if (sim->quirks & SIM_QUIRK_TKT259347)
+ reg_data &= ~(SIM_ESTOP_EN | SIM_ESTOP_EXE);
+ } else
+ reg_data &= ~SIM_ENABLE_XMTEN;
+
+ __raw_writel(reg_data, sim->ioaddr + ENABLE);
+}
+
+static void sim_set_rx(struct sim_t *sim, u8 enable)
+{
+ u32 reg_data;
+ reg_data = __raw_readl(sim->ioaddr + ENABLE);
+ if (enable) {
+ reg_data |= SIM_ENABLE_RCVEN;
+ reg_data &= ~SIM_ENABLE_XMTEN;
+ if (sim->quirks & SIM_QUIRK_TKT259347)
+ reg_data |= (SIM_ESTOP_EN | SIM_ESTOP_EXE);
+ } else {
+ reg_data &= ~SIM_ENABLE_RCVEN;
+ if (sim->quirks & SIM_QUIRK_TKT259347)
+ reg_data &= ~(SIM_ESTOP_EN | SIM_ESTOP_EXE);
+ }
+
+ __raw_writel(reg_data, sim->ioaddr + ENABLE);
+}
+
+static void sim_reset_timer(struct sim_t *sim)
+{
+ u32 reg_data;
+
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~SIM_CNTL_GPCNT_CLK_SEL_MASK;
+ __raw_writel(reg_data, sim->ioaddr + CNTL);
+}
+
+static void sim_start_timer(struct sim_t *sim, u8 clk_source)
+{
+ u32 reg_data;
+
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~SIM_CNTL_GPCNT_CLK_SEL_MASK;
+ reg_data |= SIM_CNTL_GPCNT_CLK_SEL(clk_source);
+ writel(reg_data, sim->ioaddr + CNTL);
+}
+
+static void sim_set_gpc_timer(struct sim_t *sim, u32 val)
+{
+ uint32_t reg_data;
+
+ /*Clear the interrupt status*/
+ reg_data = __raw_readl(sim->ioaddr + XMT_STATUS);
+ reg_data |= SIM_XMT_STATUS_GPCNT;
+ __raw_writel(reg_data, sim->ioaddr + XMT_STATUS);
+
+ /*Set the timer counter*/
+ __raw_writel(val, sim->ioaddr + GPCNT);
+
+ /*First reset the counter*/
+ sim_reset_timer(sim);
+
+ /*Enable GPC timer interrupt*/
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data &= ~SIM_INT_MASK_GPCM;
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+
+ /*Set the GPCNT clock source to be Fclk*/
+ sim_start_timer(sim, SIM_CNTL_GPCNT_CARD_CLK);
+}
+
+static int sim_reset_low_timing(struct sim_t *sim, u32 clock_cycle)
+{
+ int errval = 0;
+ int timeout = 0;
+ u32 fclk_in_khz, delay_in_us, reg_data;
+
+ fclk_in_khz = sim->clk_rate / MSEC_PER_SEC;
+ delay_in_us = EMV_RESET_LOW_CYCLES * USEC_PER_MSEC / fclk_in_khz;
+
+ sim_set_gpc_timer(sim, clock_cycle);
+
+ timeout = wait_for_completion_timeout(&sim->xfer_done,
+ msecs_to_jiffies(delay_in_us / 1000 * 2));
+ if (timeout == 0) {
+ pr_err("Reset low GPC timout\n");
+ errval = -SIM_E_TIMEOUT;
+ }
+
+ sim_reset_timer(sim);
+ /*Disable GPC timer interrupt*/
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data |= SIM_INT_MASK_GPCM;
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+
+ return errval;
+}
+
+static void sim_set_cwt(struct sim_t *sim, u8 enable)
+{
+ u32 reg_val;
+ reg_val = __raw_readl(sim->ioaddr + CNTL);
+ if (enable && sim->timing_data.cwt)
+ reg_val |= SIM_CNTL_CWTEN;
+ else
+ reg_val &= ~SIM_CNTL_CWTEN;
+ __raw_writel(reg_val, sim->ioaddr + CNTL);
+}
+
+static void sim_set_bwt(struct sim_t *sim, u8 enable)
+{
+ u32 reg_val;
+ reg_val = __raw_readl(sim->ioaddr + CNTL);
+ if (enable && (sim->timing_data.bwt || sim->timing_data.bgt))
+ reg_val |= SIM_CNTL_BWTEN;
+ else
+ reg_val &= ~SIM_CNTL_BWTEN;
+ __raw_writel(reg_val, sim->ioaddr + CNTL);
+}
+
+static int sim_reset_module(struct sim_t *sim)
+{
+ u32 reg_val;
+ s8 timeout = RESET_RETRY_TIMES;
+
+ reg_val = __raw_readl(sim->ioaddr + RESET_CNTL);
+ reg_val |= (SIM_RESET_CNTL_SOFT_RESET);
+ __raw_writel(reg_val, sim->ioaddr + RESET_CNTL);
+
+ while (__raw_readl(sim->ioaddr + RESET_CNTL) & SIM_RESET_CNTL_SOFT_RESET) {
+ usleep_range(1, 3);
+ if (timeout-- <= 0) {
+ pr_err("SIM module reset timeout\n");
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static void sim_receive_atr_set(struct sim_t *sim)
+{
+ u32 reg_data;
+
+ /*Enable RX*/
+ sim_set_rx(sim, 1);
+
+ /*Receive fifo threshold = 1*/
+ reg_data = SIM_RCV_THRESHOLD_RTH(0) | SIM_RCV_THRESHOLD_RDT(1);
+ __raw_writel(reg_data, sim->ioaddr + RCV_THRESHOLD);
+
+ /* Clear the interrupt status*/
+ reg_data = __raw_readl(sim->ioaddr + RCV_STATUS);
+ reg_data |= (SIM_RCV_STATUS_CWT | SIM_RCV_STATUS_RDRF);
+ __raw_writel(reg_data, sim->ioaddr + RCV_STATUS);
+
+ /*Set the cwt timer.Refer the setting of ATR on EMV4.3 book*/
+ __raw_writel(ATR_MAX_CWT, sim->ioaddr + CHAR_WAIT);
+
+ /*Set the baud rate to be 1/372. Refer the setting of ATR on EMV4.3 book
+ *Enable the CWT timer during receiving ATR process.
+ */
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~SIM_CNTL_BAUD_SEL_MASK;
+ reg_data |= SIM_CNTL_BAUD_SEL(0) | SIM_CNTL_CWTEN;
+
+ /*Enable ICM mode*/
+ reg_data |= SIM_CNTL_ICM;
+
+ /*Enable Sample12*/
+ reg_data |= SIM_CNTL_SAMPLE12;
+ __raw_writel(reg_data, sim->ioaddr + CNTL);
+
+ /*Disable NACK*/
+ sim_set_nack(sim, 0);
+
+ /*Set 12 ETUS*/
+ __raw_writel(0, sim->ioaddr + GUARD_CNTL);
+
+ sim->errval = 0;
+ sim->rcv_count = 0;
+ sim->checking_ts_timing = 1;
+ sim->state = SIM_STATE_ATR_RECEIVING;
+
+ /*Enable the RIM and GPC interrupt, disalbe the CWT interrupt*/
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data |= SIM_INT_MASK_CWTM;
+ reg_data &= ~(SIM_INT_MASK_RIM | SIM_INT_MASK_GPCM);
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+}
+
+static int32_t sim_check_rec_data(u32 *reg_data)
+{
+ s32 err = 0;
+
+ if (*reg_data & SIM_REC_CWT_ERROR)
+ err |= SIM_ERROR_CWT;
+
+ if (*reg_data & SIM_REC_FRAME_ERROR)
+ err |= SIM_ERROR_FRAME;
+
+ if (*reg_data & SIM_REC_PARITY_ERROR)
+ err |= SIM_ERROR_PARITY;
+
+ return err;
+}
+
+static void sim_xmt_fill_fifo(struct sim_t *sim)
+{
+ u32 reg_data;
+ u32 bytesleft, i;
+
+ reg_data = __raw_readl(sim->ioaddr + XMT_FIFO_STAT);
+ bytesleft = SIM_TX_FIFO_DEPTH - ((reg_data >> 8) & 0x0F);
+
+ if (bytesleft > sim->xmt_remaining)
+ bytesleft = sim->xmt_remaining;
+
+ for (i = 0; i < bytesleft; i++) {
+ __raw_writel(sim->xmt_buffer[sim->xmt_pos],
+ sim->ioaddr + PORT1_XMT_BUF);
+ sim->xmt_pos++;
+ };
+ sim->xmt_remaining -= bytesleft;
+};
+
+static void sim_rcv_read_fifo(struct sim_t *sim)
+{
+ u16 i, count;
+ u32 reg_data;
+
+ count = __raw_readl(sim->ioaddr + RCV_FIFO_CNT);
+
+ spin_lock(&sim->lock);
+ for (i = 0; i < count; i++) {
+ reg_data = __raw_readl(sim->ioaddr + PORT1_RCV_BUF);
+ sim->errval |= sim_check_rec_data(&reg_data);
+
+ /* T1 mode and t0 mode no parity error, T1 mode SIM module will not produce NACK be
+ * NACK is disabled. T0 mode to ensure there is no parity error for the current byte
+ */
+ if (!(sim->nack_enable && (reg_data & SIM_REC_PARITY_ERROR))) {
+ sim->rcv_buffer[sim->rcv_head + sim->rcv_count] = (u8)reg_data;
+ sim->rcv_count++;
+ }
+ if (sim->rcv_head + sim->rcv_count >= SIM_RCV_BUFFER_SIZE) {
+ pr_err("The software fifo is full,head %d, cnt%d\n", sim->rcv_head, sim->rcv_count);
+ break;
+ }
+ }
+ spin_unlock(&sim->lock);
+}
+
+static void sim_tx_irq_enable(struct sim_t *sim)
+{
+ u32 reg_val;
+ /*Clear the status and enable the related interrupt*/
+ reg_val = __raw_readl(sim->ioaddr + XMT_STATUS);
+ __raw_writel(reg_val, sim->ioaddr + XMT_STATUS);
+ reg_val = __raw_readl(sim->ioaddr + RCV_STATUS);
+ __raw_writel(reg_val, sim->ioaddr + RCV_STATUS);
+
+ reg_val = __raw_readl(sim->ioaddr + INT_MASK);
+ /*
+ *Disable CWT , BWT interrupt when transmitting, it would
+ *be enabled when rx is enabled just after tx completes
+ *The timer will be enabled.
+ */
+ reg_val |= SIM_INT_MASK_CWTM | SIM_INT_MASK_BWTM;
+ reg_val |= SIM_INT_MASK_RIM | SIM_INT_MASK_RTM;
+
+ if (sim->xmt_remaining != 0)
+ reg_val &= ~SIM_INT_MASK_TDTFM;
+ else{
+ reg_val &= ~SIM_INT_MASK_TCIM;
+ /*Enable transmit early complete interrupt.*/
+ reg_val &= ~SIM_INT_MASK_ETCIM;
+ }
+
+ /*NACK interrupt is enabled only when T0 mode*/
+ if (sim->protocol_type == SIM_PROTOCOL_T0 || sim->nack_enable != 0)
+ reg_val &= ~SIM_INT_MASK_XTM;
+ else
+ reg_val |= SIM_INT_MASK_XTM;
+ __raw_writel(reg_val, sim->ioaddr + INT_MASK);
+}
+
+static void sim_tx_irq_disable(struct sim_t *sim)
+{
+ u32 reg_val;
+ /*Disable the NACK interruptand TX related interrupt*/
+ reg_val = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_val |= (SIM_INT_MASK_TDTFM | SIM_INT_MASK_TCIM | SIM_INT_MASK_XTM | SIM_INT_MASK_ETCIM);
+ __raw_writel(reg_val, sim->ioaddr + INT_MASK);
+}
+
+static void sim_rx_irq_enable(struct sim_t *sim)
+{
+ u32 reg_data;
+ /*
+ * Ensure the CWT timer is enabled.
+ */
+ sim_set_cwt(sim, 1);
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data |= (SIM_INT_MASK_TCIM | SIM_INT_MASK_TDTFM | SIM_INT_MASK_XTM);
+ reg_data &= ~(SIM_INT_MASK_RIM | SIM_INT_MASK_CWTM | SIM_INT_MASK_BWTM);
+
+ if (sim->protocol_type == SIM_PROTOCOL_T0 || sim->nack_enable != 0)
+ reg_data &= ~SIM_INT_MASK_RTM;
+ else
+ reg_data |= SIM_INT_MASK_RTM;
+
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+}
+
+static void sim_rx_irq_disable(struct sim_t *sim)
+{
+ u32 reg_val;
+ reg_val = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_val |= (SIM_INT_MASK_RIM | SIM_INT_MASK_CWTM | SIM_INT_MASK_BWTM | SIM_INT_MASK_RTM);
+ __raw_writel(reg_val, sim->ioaddr + INT_MASK);
+}
+
+static irqreturn_t sim_irq_handler(int irq, void *dev_id)
+{
+ u32 reg_data, tx_status, rx_status;
+
+ struct sim_t *sim = (struct sim_t *) dev_id;
+
+ tx_status = __raw_readl(sim->ioaddr + XMT_STATUS);
+ rx_status = __raw_readl(sim->ioaddr + RCV_STATUS);
+ __raw_writel(tx_status, sim->ioaddr + XMT_STATUS);
+ __raw_writel(rx_status, sim->ioaddr + RCV_STATUS);
+
+ if (sim->state == SIM_STATE_ATR_RECEIVING &&
+ sim->checking_ts_timing == 1) {
+
+ if ((tx_status & SIM_XMT_STATUS_GPCNT) &&
+ !(rx_status & SIM_RCV_STATUS_RDRF)) {
+ /*Disable the GPCNT timer and CWT timer right now*/
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~(SIM_CNTL_GPCNT_CLK_SEL_MASK |
+ SIM_CNTL_CWTEN);
+ __raw_writel(reg_data, sim->ioaddr + CNTL);
+
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data |= (SIM_INT_MASK_GPCM |
+ SIM_INT_MASK_CWTM | SIM_INT_MASK_RIM);
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+ sim->errval = SIM_ERROR_ATR_DELAY;
+ complete(&sim->xfer_done);
+ sim->checking_ts_timing = 0;
+ } else if (rx_status & SIM_RCV_STATUS_RDRF) {
+ /*
+ * Reset/stop the GPCNT timer first.
+ */
+ sim_reset_timer(sim);
+
+ /*Enable GPC, CWT interrupt and
+ *disable the rx full interrupt
+ */
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data &= ~(SIM_INT_MASK_GPCM | SIM_INT_MASK_CWTM);
+ reg_data |= SIM_INT_MASK_RIM;
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+ sim_rcv_read_fifo(sim);
+
+ /*Clear the GPCNT expiring status*/
+ __raw_writel(SIM_XMT_STATUS_GPCNT,
+ sim->ioaddr + XMT_STATUS);
+
+ /*ATR each recieved byte will cost 12 ETU, so get the remaining etus*/
+ reg_data = ATR_MAX_DURATION - sim->rcv_count * 12;
+ __raw_writel(reg_data, sim->ioaddr + GPCNT);
+
+ sim_start_timer(sim, SIM_CNTL_GPCNT_ETU_CLK);
+
+ /*Receive fifo threshold set to max value*/
+ reg_data = SIM_RCV_THRESHOLD_RTH(0) | SIM_RCV_THRESHOLD_RDT(ATR_THRESHOLD_MAX);
+ __raw_writel(reg_data, sim->ioaddr + RCV_THRESHOLD);
+ sim->checking_ts_timing = 0;
+ } else {
+ pr_err("Unexpected irq when delay checking\n");
+ }
+ }
+
+ else if (sim->state == SIM_STATE_ATR_RECEIVING) {
+ if ((rx_status & SIM_RCV_STATUS_CWT) ||
+ ((tx_status & SIM_XMT_STATUS_GPCNT) &&
+ (sim->rcv_count != 0))) {
+
+ /*Disable the GPCNT timer and CWT timer right now*/
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~(SIM_CNTL_GPCNT_CLK_SEL_MASK | SIM_CNTL_CWTEN);
+ __raw_writel(reg_data, sim->ioaddr + CNTL);
+
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data |= (SIM_INT_MASK_GPCM | SIM_INT_MASK_CWTM);
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+
+ if (tx_status & SIM_XMT_STATUS_GPCNT)
+ sim->errval |= SIM_ERROR_ATR_TIMEROUT;
+
+ if (rx_status & SIM_RCV_STATUS_CWT)
+ sim->errval |= SIM_ERROR_CWT;
+
+ sim_rcv_read_fifo(sim);
+ sim->state = SIM_STATE_ATR_RECEIVED;
+
+ complete(&sim->xfer_done);
+ }
+ }
+
+ else if (sim->state == SIM_STATE_XMTING) {
+ /*The CWT BWT expire should not happen when in the transmitting state*/
+ if (tx_status & SIM_XMT_STATUS_ETC) {
+ /*Once the transmit frame is completed, need to enable CWT timer*/
+ sim_set_cwt(sim, 1);
+ }
+ if (tx_status & SIM_XMT_STATUS_XTE) {
+ /*Disable TX*/
+ sim_set_tx(sim, 0);
+ /*Disalbe the timers*/
+ sim_set_cwt(sim, 0);
+ sim_set_bwt(sim, 0);
+ /*Disable the NACK interruptand TX related interrupt*/
+ sim_tx_irq_disable(sim);
+
+ /*Update the state and status*/
+ sim->errval |= SIM_ERROR_NACK_THRESHOLD;
+ sim->state = SIM_STATE_XMT_ERROR;
+
+ complete(&sim->xfer_done);
+ } else if (tx_status & SIM_XMT_STATUS_TDTF && sim->xmt_remaining != 0) {
+ sim_xmt_fill_fifo(sim);
+ if (sim->xmt_remaining == 0) {
+ /*Disable TX threshold interrupt and enable tx complete interrupt*/
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data |= SIM_INT_MASK_TDTFM;
+ /*Enable transmit complete and early transmit complete interrupt*/
+ reg_data &= ~(SIM_INT_MASK_TCIM | SIM_INT_MASK_ETCIM);
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+ }
+ } else if (tx_status & SIM_XMT_STATUS_TC && sim->xmt_remaining == 0) {
+ /*Disable the NACK interruptand TX related interrupt*/
+ sim_tx_irq_disable(sim);
+ sim_set_rx(sim, 1);
+ /*Update the state and status*/
+ sim->state = SIM_STATE_XMT_DONE;
+ complete(&sim->xfer_done);
+ }
+ }
+
+ /*
+ * It takes some time to change from SIM_STATE_XMT_DONE to SIM_STATE_RECEIVING
+ * RX would only be enabled after state becomes SIM_STATE_RECEIVING
+ */
+ else if (sim->state == SIM_STATE_RECEIVING) {
+ if (rx_status & SIM_RCV_STATUS_RTE) {
+ /*Disable RX*/
+ sim_set_rx(sim, 0);
+ /*Disable the BWT timer and CWT timer right now*/
+ sim_set_cwt(sim, 0);
+ sim_set_bwt(sim, 0);
+ /*Disable the interrupt right now*/
+ sim_rx_irq_disable(sim);
+ /*Should we read the fifo or just flush the fifo?*/
+ sim_rcv_read_fifo(sim);
+ sim->errval = SIM_ERROR_NACK_THRESHOLD;
+ sim->state = SIM_STATE_RECEIVE_ERROR;
+ complete(&sim->xfer_done);
+ }
+
+ if (rx_status & SIM_RCV_STATUS_RDRF) {
+ sim_rcv_read_fifo(sim);
+ if (sim->is_fixed_len_rec &&
+ sim->rcv_count >= sim->expected_rcv_cnt) {
+
+ /*Disable the BWT timer and CWT timer right now*/
+ sim_rx_irq_disable(sim);
+ /*Add the state judgement to ensure the maybe complete has been impletment in the above "if" case*/
+ if (sim->state == SIM_STATE_RECEIVING) {
+ sim->state = SIM_STATE_RECEIVE_DONE;
+ complete(&sim->xfer_done);
+ }
+ }
+ }
+
+ if ((rx_status & SIM_RCV_STATUS_CWT) ||
+ (rx_status & SIM_RCV_STATUS_BWT) ||
+ (rx_status & SIM_RCV_STATUS_BGT)) {
+
+ /*Disable the BWT timer and CWT timer right now*/
+ sim_set_cwt(sim, 0);
+ sim_set_bwt(sim, 0);
+ sim_rx_irq_disable(sim);
+
+ if (rx_status & SIM_RCV_STATUS_BWT) {
+ sim->errval |= SIM_ERROR_BWT;
+ }
+ if (rx_status & SIM_RCV_STATUS_CWT)
+ sim->errval |= SIM_ERROR_CWT;
+ if (rx_status & SIM_RCV_STATUS_BGT)
+ sim->errval |= SIM_ERROR_BGT;
+
+ sim_rcv_read_fifo(sim);
+ /*Add the state judgement to ensure the maybe complete has been impletment in the above "if" case*/
+ if (sim->state == SIM_STATE_RECEIVING) {
+ sim->state = SIM_STATE_RECEIVE_DONE;
+ complete(&sim->xfer_done);
+ }
+ }
+ }
+
+ else if ((sim->state == SIM_STATE_RESET_SEQUENCY) &&
+ (tx_status & SIM_XMT_STATUS_GPCNT))
+ complete(&sim->xfer_done);
+ else if (rx_status & SIM_RCV_STATUS_RDRF) {
+ pr_err("unexpected status %d\n", sim->state);
+ sim_rcv_read_fifo(sim);
+ }
+
+ return IRQ_HANDLED;
+};
+
+static void sim_start(struct sim_t *sim)
+{
+ u32 reg_data, clk_rate, clk_div = 0;
+ pr_debug("%s entering.\n", __func__);
+
+ if (sim->port_index == 1)
+ __raw_writel(SIM_SETUP_SPS_PORT1, sim->ioaddr + SETUP);
+ else
+ __raw_writel(SIM_SETUP_SPS_PORT0, sim->ioaddr + SETUP);
+
+ /*1 ~ 5 MHz */
+ clk_rate = clk_get_rate(sim->clk);
+ clk_div = (clk_rate + sim->clk_rate - 1) / sim->clk_rate;
+ __raw_writel(clk_div, sim->ioaddr + CLK_PRESCALER);
+
+ /*Set the port pin to be open drained*/
+ reg_data = __raw_readl(sim->ioaddr + OD_CONFIG);
+ if (sim->port_index == 1)
+ reg_data |= SIM_OD_CONFIG_OD_P1;
+ else
+ reg_data |= SIM_OD_CONFIG_OD_P0;
+
+ __raw_writel(reg_data, sim->ioaddr + OD_CONFIG);
+
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+
+ /*One pin mode*/
+ reg_data |= SIM_PORT_CNTL_3VOLT | SIM_PORT_CNTL_STEN;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
+ /* presense detect */
+ pr_debug("%s p0_det is 0x%x \n", __func__,
+ __raw_readl(sim->ioaddr + sim->port_detect_reg));
+ if (__raw_readl(sim->ioaddr + sim->port_detect_reg)
+ & SIM_PORT_DETECT_SPDP) {
+ reg_data = __raw_readl(sim->ioaddr + sim->port_detect_reg);
+ reg_data &= ~SIM_PORT_DETECT_SPDS;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_detect_reg);
+ sim->present = SIM_PRESENT_REMOVED;
+ sim->state = SIM_STATE_REMOVED;
+ } else {
+ reg_data = __raw_readl(sim->ioaddr + sim->port_detect_reg);
+ reg_data |= SIM_PORT_DETECT_SPDS;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_detect_reg);
+ sim->present = SIM_PRESENT_DETECTED;
+ sim->state = SIM_STATE_DETECTED;
+ };
+
+ /*enable card interrupt. clear interrupt status*/
+ reg_data = __raw_readl(sim->ioaddr + sim->port_detect_reg);
+ reg_data |= SIM_PORT_DETECT_SDI;
+ reg_data |= SIM_PORT_DETECT_SDIM;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_detect_reg);
+};
+
+static void sim_cold_reset_sequency(struct sim_t *sim)
+{
+ u32 reg_data;
+
+ sim->state = SIM_STATE_RESET_SEQUENCY;
+
+ /*set VCC*/
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+ if (sim->sven_low_active)
+ reg_data &= ~SIM_PORT_CNTL_SVEN;
+ else
+ reg_data |= SIM_PORT_CNTL_SVEN;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
+ msleep(9);
+
+ /*enable CLK*/
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+ reg_data |= SIM_PORT_CNTL_SCEN;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
+ /*RST low time*/
+ sim_reset_low_timing(sim, EMV_RESET_LOW_CYCLES);
+
+ /*RST high*/
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+ reg_data |= SIM_PORT_CNTL_SRST;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
+ /*wait for ATR*/
+ sim_set_gpc_timer(sim, ATR_MAX_DELAY_CLK);
+};
+
+static void sim_deactivate(struct sim_t *sim)
+{
+ u32 reg_data;
+
+ pr_debug("%s entering.\n", __func__);
+ /* Auto powdown to implement the deactivate sequence */
+ if (sim->present != SIM_PRESENT_REMOVED) {
+ if (sim->sven_low_active) {
+ /*Set the RESET to be low*/
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+ reg_data &= ~SIM_PORT_CNTL_SRST;
+ writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+ usleep_range(2, 5);
+
+ /*Set the clock to be low*/
+ reg_data &= ~SIM_PORT_CNTL_SCEN;
+ writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+ usleep_range(2, 5);
+
+ /*Set the sven to be high*/
+ reg_data |= SIM_PORT_CNTL_SVEN;
+ writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
+ } else {
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+ reg_data |= SIM_PORT_CNTL_SAPD;
+ __raw_writel(reg_data,
+ sim->ioaddr + sim->port_ctrl_reg);
+ reg_data |= SIM_PORT_CNTL_SFPD;
+ __raw_writel(reg_data,
+ sim->ioaddr + sim->port_ctrl_reg);
+ }
+ } else
+ pr_err(">>>No card%s\n", __func__);
+};
+
+static void sim_cold_reset(struct sim_t *sim)
+{
+ if (sim->present != SIM_PRESENT_REMOVED) {
+ sim->state = SIM_STATE_DETECTED;
+ sim->present = SIM_PRESENT_DETECTED;
+ sim_cold_reset_sequency(sim);
+ sim_receive_atr_set(sim);
+ } else {
+ pr_err("No card%s\n", __func__);
+ }
+};
+
+static void sim_warm_reset_sequency(struct sim_t *sim)
+{
+ u32 reg_data;
+
+ sim->state = SIM_STATE_RESET_SEQUENCY;
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+ reg_data |= (SIM_PORT_CNTL_SRST | SIM_PORT_CNTL_SCEN);
+ if (sim->sven_low_active)
+ reg_data &= ~SIM_PORT_CNTL_SVEN;
+ else
+ reg_data |= SIM_PORT_CNTL_SVEN;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
+ usleep_range(20, 25);
+
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+ reg_data &= ~SIM_PORT_CNTL_SRST;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
+ sim_reset_low_timing(sim, EMV_RESET_LOW_CYCLES);
+
+ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
+ reg_data |= SIM_PORT_CNTL_SRST;
+ __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+ sim_set_gpc_timer(sim, ATR_MAX_DELAY_CLK);
+}
+
+static void sim_warm_reset(struct sim_t *sim)
+{
+ if (sim->present != SIM_PRESENT_REMOVED) {
+ sim_data_reset(sim);
+ sim_warm_reset_sequency(sim);
+ sim_receive_atr_set(sim);
+ } else {
+ pr_err("No card%s\n", __func__);
+ }
+};
+
+
+static int sim_card_lock(struct sim_t *sim)
+{
+ int errval;
+
+ /* place holder for true physcial locking */
+ if (sim->present != SIM_PRESENT_REMOVED)
+ errval = SIM_OK;
+ else
+ errval = -SIM_E_NOCARD;
+ return errval;
+};
+
+static int sim_card_eject(struct sim_t *sim)
+{
+ int errval;
+
+ pr_debug("%s entering.\n", __func__);
+ /* place holder for true physcial locking */
+ if (sim->present != SIM_PRESENT_REMOVED)
+ errval = SIM_OK;
+ else
+ errval = -SIM_E_NOCARD;
+ return errval;
+};
+
+static int sim_check_baud_rate(sim_baud_t *baud_rate)
+{
+ /*
+ * The valid value is decribed in the 8.3.3.1 in EMV 4.3
+ */
+ if (baud_rate->fi == 1 && (baud_rate->di == 1 ||
+ baud_rate->di == 2 || baud_rate->di == 3))
+ return 0;
+
+ return -EINVAL;
+}
+
+static int sim_set_baud_rate(struct sim_t *sim)
+{
+ u32 reg_data;
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~(SIM_CNTL_BAUD_SEL_MASK);
+
+ switch (sim->baud_rate.di) {
+ case 1:
+ reg_data |= SIM_CNTL_BAUD_SEL(0);
+ break;
+ case 2:
+ reg_data |= SIM_CNTL_BAUD_SEL(1);
+ break;
+ case 3:
+ reg_data |= SIM_CNTL_BAUD_SEL(2);
+ break;
+ default:
+ pr_err("Invalid baud Di, Using default 372 / 1\n");
+ reg_data |= SIM_CNTL_BAUD_SEL(0);
+ break;
+ }
+
+ __raw_writel(reg_data, sim->ioaddr + CNTL);
+
+ return 0;
+}
+
+static int sim_check_timing_data(sim_timing_t *timing_data)
+{
+ if (timing_data->wwt > 0xFFFF ||
+ timing_data->cwt > 0xFFFF ||
+ timing_data->bgt > 0xFFFF ||
+ timing_data->cgt > 0xFF) {
+ /*Check whether the counter is out of the scope of SIM IP*/
+ pr_err("The timing value is out of scope of IP\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void sim_set_timer_counter(struct sim_t *sim)
+{
+ if (sim->timing_data.wwt != 0 &&
+ sim->protocol_type == SIM_PROTOCOL_T0) {
+ sim->timing_data.cwt = sim->timing_data.wwt;
+ sim->timing_data.bwt = sim->timing_data.wwt;
+ }
+
+
+ if (sim->timing_data.bgt != 0) {
+ __raw_writel(sim->timing_data.bgt, sim->ioaddr + BGT);
+ }
+
+ if (sim->timing_data.cwt != 0)
+ __raw_writel(sim->timing_data.cwt, sim->ioaddr + CHAR_WAIT);
+
+ if (sim->timing_data.bwt != 0) {
+
+ __raw_writel(sim->timing_data.bwt & 0x0000FFFF, sim->ioaddr + BWT);
+ __raw_writel((sim->timing_data.bwt >> 16) & 0x0000FFFF,
+ sim->ioaddr + BWT_H);
+ }
+
+ if (sim->timing_data.cgt == 0xFF && sim->protocol_type == SIM_PROTOCOL_T0)
+ /* From EMV4.3 , CGT =0xFF in T0 mode means 12 ETU.
+ * Set register to be 12 ETU for transmitting and receiving.
+ */
+ __raw_writel(0 , sim->ioaddr + GUARD_CNTL);
+ else if (sim->timing_data.cgt == 0xFF && sim->protocol_type == SIM_PROTOCOL_T1)
+ /* From EMV4.3 , CGT =0xFF in T1 mode means 11 ETU.
+ * Set register to be 12 ETU for transmitting and receiving.
+ */
+ __raw_writel(0x1FF , sim->ioaddr + GUARD_CNTL);
+
+ /*For the T1 mode, use 11ETU to receive.*/
+ else if (sim->protocol_type == SIM_PROTOCOL_T1)
+ __raw_writel((sim->timing_data.cgt | SIM_GUARD_CNTL_RCVR11), sim->ioaddr + GUARD_CNTL);
+
+ else
+ /*sim->protocol_type == SIM_PROTOCOL_T0*/
+ __raw_writel(sim->timing_data.cgt, sim->ioaddr + GUARD_CNTL);
+}
+
+static void sim_xmt_start(struct sim_t *sim)
+{
+ u32 reg_val;
+
+ /*Set TX threshold if there are remaing data*/
+ if (sim->xmt_remaining != 0) {
+ reg_val = __raw_readl(sim->ioaddr + XMT_THRESHOLD);
+ reg_val &= ~SIM_XMT_THRESHOLD_TDT_MASK;
+ reg_val |= SIM_XMT_THRESHOLD_TDT(TX_FIFO_THRESHOLD);
+ __raw_writel(reg_val, sim->ioaddr + XMT_THRESHOLD);
+ }
+ sim_tx_irq_enable(sim);
+
+ /*Enable BWT and disalbe CWT timers when tx*/
+ sim_set_bwt(sim, 1);
+ sim_set_cwt(sim, 0);
+
+ /*Disalbe RX*/
+ sim_set_rx(sim, 0);
+
+ /*Enable TX*/
+ sim_set_tx(sim, 1);
+}
+
+static void sim_flush_fifo(struct sim_t *sim, u8 flush_tx, u8 flush_rx)
+{
+ u32 reg_val;
+
+ reg_val = __raw_readl(sim->ioaddr + RESET_CNTL);
+
+ if (flush_tx)
+ reg_val |= SIM_RESET_CNTL_FLUSH_XMT;
+ if (flush_rx)
+ reg_val |= SIM_RESET_CNTL_FLUSH_RCV;
+ __raw_writel(reg_val, sim->ioaddr + RESET_CNTL);
+
+ usleep_range(2, 3);
+
+ if (flush_tx)
+ reg_val &= ~(SIM_RESET_CNTL_FLUSH_XMT);
+ if (flush_rx)
+ reg_val &= ~(SIM_RESET_CNTL_FLUSH_RCV);
+ __raw_writel(reg_val, sim->ioaddr + RESET_CNTL);
+}
+
+static void sim_change_rcv_threshold(struct sim_t *sim)
+{
+ u32 rx_threshold = 0;
+ u32 reg_val = 0;
+
+ if (sim->is_fixed_len_rec) {
+ rx_threshold = sim->expected_rcv_cnt - sim->rcv_count;
+ reg_val = __raw_readl(sim->ioaddr + RCV_THRESHOLD);
+ reg_val &= ~(SIM_RCV_THRESHOLD_RDT_MASK);
+ reg_val |= SIM_RCV_THRESHOLD_RDT(rx_threshold);
+ __raw_writel(reg_val, sim->ioaddr + RCV_THRESHOLD);
+ }
+}
+
+static void sim_start_rcv(struct sim_t *sim)
+{
+ sim_set_baud_rate(sim);
+ if (sim->protocol_type == SIM_PROTOCOL_T0)
+ sim_set_nack(sim, 1);
+ else if (sim->protocol_type == SIM_PROTOCOL_T1)
+ sim_set_nack(sim, 0);
+
+ /*Set RX threshold*/
+ if (sim->protocol_type == SIM_PROTOCOL_T0)
+ __raw_writel(SIM_RCV_THRESHOLD_RTH(sim->nack_threshold) |
+ SIM_RCV_THRESHOLD_RDT(RX_FIFO_THRESHOLD), sim->ioaddr + RCV_THRESHOLD);
+ else
+ __raw_writel(SIM_RCV_THRESHOLD_RDT(RX_FIFO_THRESHOLD), sim->ioaddr + RCV_THRESHOLD);
+
+ /*Clear status and enable interrupt*/
+ sim_rx_irq_enable(sim);
+
+ /*Disalbe TX and Enable Rx*/
+ sim_set_rx(sim, 1);
+ sim_set_tx(sim, 0);
+}
+
+static void sim_polling_delay(struct sim_t *sim, u32 delay)
+{
+ u32 reg_data;
+
+ /*Reset the timer*/
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~SIM_CNTL_GPCNT_CLK_SEL_MASK;
+ reg_data |= SIM_CNTL_GPCNT_CLK_SEL(0);
+ __raw_writel(reg_data, sim->ioaddr + CNTL);
+
+ /*Clear the interrupt status*/
+ __raw_writel(SIM_XMT_STATUS_GPCNT, sim->ioaddr + XMT_STATUS);
+
+ /*Disable timer interrupt*/
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data |= SIM_INT_MASK_GPCM;
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+
+ __raw_writel(delay, sim->ioaddr + GPCNT);
+
+ /*Set the ETU as clock source and start timer*/
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~SIM_CNTL_GPCNT_CLK_SEL_MASK;
+ reg_data |= SIM_CNTL_GPCNT_CLK_SEL(3);
+ __raw_writel(reg_data, sim->ioaddr + CNTL);
+
+ /*Loop for timeout*/
+ while (!(__raw_readl(sim->ioaddr + XMT_STATUS) & SIM_XMT_STATUS_GPCNT))
+ usleep_range(10, 20);
+ __raw_writel(SIM_XMT_STATUS_GPCNT, sim->ioaddr + XMT_STATUS);
+}
+
+void sim_clear_rx_buf(struct sim_t *sim)
+{
+ unsigned int i;
+ for (i = 0; i < SIM_RCV_BUFFER_SIZE; i++)
+ sim->rcv_buffer[i] = 0;
+ sim->rcv_count = 0;
+ sim->rcv_head = 0;
+}
+
+static long sim_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret, errval = SIM_OK;
+ unsigned long timeout;
+ u32 reg_data;
+ u32 delay;
+ u32 copy_cnt, val;
+ unsigned long flags;
+ unsigned char __user *atr_buffer;
+ unsigned char __user *xmt_buffer;
+ unsigned char __user *rcv_buffer;
+
+ struct sim_t *sim = (struct sim_t *) file->private_data;
+
+ pr_debug("%s entering.\n", __func__);
+ switch (cmd) {
+
+ case SIM_IOCTL_GET_ATR:
+ if (sim->present != SIM_PRESENT_DETECTED) {
+ pr_err("NO card ...\n");
+ errval = -SIM_E_NOCARD;
+ break;
+ };
+ sim->timeout = ATR_TIMEOUT * HZ;
+ val = 0;
+ ret = copy_to_user(&(((sim_atr_t *)arg)->size), &val,
+ sizeof((((sim_atr_t *)arg)->size)));
+
+ timeout = wait_for_completion_interruptible_timeout(&sim->xfer_done,
+ sim->timeout);
+ /*Disalbe the GPCNT timer and CWT timer right now*/
+ reg_data = __raw_readl(sim->ioaddr + CNTL);
+ reg_data &= ~(SIM_CNTL_GPCNT_CLK_SEL_MASK | SIM_CNTL_CWTEN);
+ __raw_writel(reg_data, sim->ioaddr + CNTL);
+
+ reg_data = __raw_readl(sim->ioaddr + INT_MASK);
+ reg_data |= (SIM_INT_MASK_GPCM | SIM_INT_MASK_CWTM);
+ __raw_writel(reg_data, sim->ioaddr + INT_MASK);
+
+ if (timeout == 0) {
+ pr_err("ATR timeout\n");
+ errval = -SIM_E_TIMEOUT;
+ break;
+ }
+
+ ret = copy_to_user(&(((sim_atr_t *)arg)->size), &sim->rcv_count,
+ sizeof(sim->rcv_count));
+ if (ret) {
+ pr_err("ATR ACCESS rcv_count Error, %d\n", ret);
+ errval = -SIM_E_ACCESS;
+ break;
+ }
+
+ __get_user(atr_buffer, &((sim_atr_t __user *)arg)->atr_buffer);
+ ret = copy_to_user(atr_buffer, sim->rcv_buffer, sim->rcv_count);
+ if (ret) {
+ pr_err("ATR ACCESS buffer Error %d %d\n", sim->rcv_count, ret);
+ errval = -SIM_E_ACCESS;
+ break;
+ }
+
+ ret = copy_to_user(&(((sim_atr_t *)arg)->errval), &sim->errval,
+ sizeof(sim->errval));
+ if (ret) {
+ pr_err("ATR ACCESS Error\n");
+ errval = -SIM_E_ACCESS;
+ break;
+ }
+ sim->rcv_count = 0;
+ sim->rcv_head = 0;
+ sim->errval = 0;
+
+ break;
+
+ case SIM_IOCTL_DEACTIVATE:
+
+ sim_deactivate(sim);
+ break;
+
+ case SIM_IOCTL_COLD_RESET:
+ sim->present = SIM_PRESENT_REMOVED;
+ sim->state = SIM_STATE_REMOVED;
+ sim_reset_module(sim);
+ sim_data_reset(sim);
+ sim_start(sim);
+ sim_cold_reset(sim);
+
+ break;
+
+ case SIM_IOCTL_WARM_RESET:
+ sim_warm_reset(sim);
+ break;
+
+ case SIM_IOCTL_XMT:
+ ret = copy_from_user(&sim->xmt_remaining, &(((sim_xmt_t *)arg)->xmt_length),
+ sizeof(uint32_t));
+ if (ret || sim->xmt_remaining > SIM_XMT_BUFFER_SIZE) {
+ pr_err("copy error or to big buffer\n");
+ errval = -EINVAL;
+ break;
+ }
+
+ __get_user(xmt_buffer, &((sim_xmt_t *)arg)->xmt_buffer);
+ ret = copy_from_user(sim->xmt_buffer, xmt_buffer, sim->xmt_remaining);
+
+ if (ret) {
+ pr_err("Copy Error\n");
+ errval = ret;
+ break;
+ }
+
+ sim_clear_rx_buf(sim);
+ sim_set_cwt(sim, 0);
+ sim_set_bwt(sim, 0);
+ /*Flush the tx rx fifo*/
+ sim_flush_fifo(sim, 1, 1);
+ sim->xmt_pos = 0;
+ sim->errval = 0;
+
+ sim_xmt_fill_fifo(sim);
+ sim_set_baud_rate(sim);
+ if (sim->protocol_type == SIM_PROTOCOL_T0)
+ sim_set_nack(sim, 1);
+ else if (sim->protocol_type == SIM_PROTOCOL_T1)
+ sim_set_nack(sim, 0);
+ else {
+ pr_err("Invalid protocol not T0 or T1\n");
+ errval = -EINVAL;
+ break;
+ }
+
+ sim_set_timer_counter(sim);
+ sim_xmt_start(sim);
+ sim->state = SIM_STATE_XMTING;
+
+ sim->timeout = TX_TIMEOUT * HZ;
+ timeout = wait_for_completion_interruptible_timeout(&sim->xfer_done,
+ sim->timeout);
+ if (timeout == 0) {
+ /*Disable the NACK interruptand TX related interrupt*/
+ sim_tx_irq_disable(sim);
+ pr_err("tx timeout\n");
+ }
+
+ if (timeout == 0 || sim->state == SIM_STATE_XMT_ERROR) {
+ pr_err("TX error\n");
+ /*Disable timers*/
+ sim_set_cwt(sim, 0);
+ sim_set_bwt(sim, 0);
+ /*Disable TX*/
+ sim_set_tx(sim, 0);
+ /*Flush the tx fifos*/
+ sim_flush_fifo(sim, 1, 0);
+ if (timeout == 0)
+ errval = -SIM_E_TIMEOUT;
+ else
+ errval = -SIM_E_NACK;
+
+ ret = copy_to_user(&(((sim_atr_t *)arg)->errval), &sim->errval,
+ sizeof(sim->errval));
+ sim->errval = 0;
+ break;
+ }
+
+ /*Copy the error status to user space*/
+ ret = copy_to_user(&(((sim_atr_t *)arg)->errval), &sim->errval,
+ sizeof(sim->errval));
+ sim->last_is_tx = true;
+ /*Start RX*/
+ sim->errval = 0;
+ sim->state = SIM_STATE_RECEIVING;
+ sim_start_rcv(sim);
+
+ break;
+
+ case SIM_IOCTL_RCV:
+ if (sim->present != SIM_PRESENT_DETECTED) {
+ errval = -SIM_E_NOCARD;
+ break;
+ }
+ sim->is_fixed_len_rec = 0;
+ val = 0;
+ ret = copy_from_user(&sim->expected_rcv_cnt, &(((sim_rcv_t *)arg)->rcv_length),
+ sizeof(sim->expected_rcv_cnt));
+
+ /*Set the length to be 0 at first*/
+ ret = copy_to_user(&(((sim_rcv_t *)arg)->rcv_length), &val,
+ sizeof(val));
+
+ /*Set error value to be 0 at first*/
+ ret = copy_to_user(&(((sim_rcv_t *)arg)->errval), &val,
+ sizeof(val));
+
+ if (sim->expected_rcv_cnt != 0)
+ sim->is_fixed_len_rec = 1;
+
+ if (sim->is_fixed_len_rec && sim->rcv_count >= sim->expected_rcv_cnt)
+ goto copy_data;
+
+ if (sim->state != SIM_STATE_RECEIVING) {
+ sim_set_timer_counter(sim);
+ /*Enable CWT BWT*/
+ sim_set_cwt(sim, 1);
+ sim_set_bwt(sim, 1);
+ sim->state = SIM_STATE_RECEIVING;
+ sim_start_rcv(sim);
+ }
+
+ spin_lock_irqsave(&sim->lock, flags);
+ if (sim->is_fixed_len_rec && sim->rcv_count < sim->expected_rcv_cnt)
+ sim_change_rcv_threshold(sim);
+ spin_unlock_irqrestore(&sim->lock, flags);
+ sim->timeout = RX_TIMEOUT * HZ;
+ timeout = wait_for_completion_interruptible_timeout(&sim->xfer_done,
+ sim->timeout);
+
+ if (timeout == 0) {
+ pr_err("Receiving timeout\n");
+ sim_set_cwt(sim, 0);
+ sim_set_bwt(sim, 0);
+ sim_rx_irq_disable(sim);
+ errval = -SIM_E_TIMEOUT;
+ break;
+ }
+
+copy_data:
+ if (sim->is_fixed_len_rec)
+ copy_cnt = sim->rcv_count >= sim->expected_rcv_cnt ? sim->expected_rcv_cnt : sim->rcv_count;
+ else
+ copy_cnt = sim->rcv_count;
+
+ ret = copy_to_user(&(((sim_rcv_t *)arg)->rcv_length), &copy_cnt,
+ sizeof(copy_cnt));
+ if (ret) {
+ pr_err("ATR ACCESS Error\n");
+ errval = -SIM_E_ACCESS;
+ break;
+ }
+
+ __get_user(rcv_buffer, &((sim_rcv_t *)arg)->rcv_buffer);
+ ret = copy_to_user(rcv_buffer, &sim->rcv_buffer[sim->rcv_head], copy_cnt);
+ if (ret) {
+ pr_err("ATR ACCESS Error\n");
+ errval = -SIM_E_ACCESS;
+ break;
+ }
+
+ ret = copy_to_user(&(((sim_rcv_t *)arg)->errval), &sim->errval,
+ sizeof(sim->errval));
+ if (ret) {
+ pr_err("ATR ACCESS Error\n");
+ errval = -SIM_E_ACCESS;
+ break;
+ }
+ /*Reset the receiving count and errval*/
+ spin_lock_irqsave(&sim->lock, flags);
+ sim->rcv_head += copy_cnt;
+ sim->rcv_count -= copy_cnt;
+ sim->errval = 0;
+ spin_unlock_irqrestore(&sim->lock, flags);
+
+ sim->last_is_tx = false;
+
+ break;
+
+ case SIM_IOCTL_SET_PROTOCOL:
+ ret = copy_from_user(&sim->protocol_type, (int *)arg,
+ sizeof(int));
+ if (ret)
+ errval = -SIM_E_ACCESS;
+ break;
+
+ case SIM_IOCTL_SET_TIMING:
+ ret = copy_from_user(&sim->timing_data, (sim_timing_t *)arg,
+ sizeof(sim_timing_t));
+ if (ret) {
+ pr_err("Copy Error\n");
+ errval = ret;
+ break;
+ }
+
+ ret = sim_check_timing_data(&sim->timing_data);
+
+ if (ret)
+ errval = ret;
+
+ break;
+
+ case SIM_IOCTL_SET_BAUD:
+ ret = copy_from_user(&sim->baud_rate, (sim_baud_t *)arg,
+ sizeof(sim_baud_t));
+
+ if (ret) {
+ pr_err("Copy Error\n");
+ errval = ret;
+ break;
+ }
+
+ sim_check_baud_rate(&sim->baud_rate);
+
+ break;
+ case SIM_IOCTL_WAIT:
+ ret = copy_from_user(&delay, (unsigned int *)arg,
+ sizeof(unsigned int));
+
+ if (ret) {
+ pr_err("\nWait Copy Error\n");
+ errval = ret;
+ break;
+ }
+
+ sim_polling_delay(sim, delay);
+ break;
+
+ case SIM_IOCTL_GET_PRESENSE:
+ if (put_user(sim->present, (int *)arg))
+ errval = -SIM_E_ACCESS;
+ break;
+
+ case SIM_IOCTL_CARD_LOCK:
+ errval = sim_card_lock(sim);
+ break;
+
+ case SIM_IOCTL_CARD_EJECT:
+ errval = sim_card_eject(sim);
+ break;
+
+ };
+
+ return errval;
+};
+
+static int sim_open(struct inode *inode, struct file *file)
+{
+ int errval = SIM_OK;
+ struct sim_t *sim = dev_get_drvdata(sim_dev.parent);
+
+ file->private_data = sim;
+ spin_lock_init(&sim->lock);
+
+ pr_debug("%s entering.\n", __func__);
+ if (!sim->ioaddr) {
+ errval = -ENOMEM;
+ return errval;
+ }
+
+ if (!sim->open_cnt)
+ clk_prepare_enable(sim->clk);
+
+ sim->open_cnt = 1;
+
+ errval = sim_reset_module(sim);
+ sim_data_reset(sim);
+
+ return errval;
+};
+
+static int sim_release(struct inode *inode, struct file *file)
+{
+ u32 reg_data;
+ struct sim_t *sim = (struct sim_t *) file->private_data;
+
+ /* disable presense detection */
+ reg_data = __raw_readl(sim->ioaddr + sim->port_detect_reg);
+ __raw_writel(reg_data | SIM_PORT_DETECT_SDIM,
+ sim->ioaddr + sim->port_detect_reg);
+
+ if (sim->present != SIM_PRESENT_REMOVED)
+ sim_deactivate(sim);
+
+
+ if (sim->open_cnt)
+ clk_disable_unprepare(sim->clk);
+
+ sim->open_cnt = 0;
+
+ return 0;
+};
+
+static const struct file_operations sim_fops = {
+ .owner = THIS_MODULE,
+ .open = sim_open,
+ .release = sim_release,
+ .unlocked_ioctl = sim_ioctl,
+};
+
+static struct miscdevice sim_dev = {
+ MISC_DYNAMIC_MINOR,
+ "mxc_sim",
+ &sim_fops
+};
+
+static struct platform_device_id imx_sim_devtype[] = {
+ {
+ .name = "imx7d-sim",
+ .driver_data = 0,
+ }, {
+ .name = "imx6ul-sim",
+ .driver_data = SIM_QUIRK_TKT259347,
+ }, {
+ /* sentinel */
+ }
+};
+
+enum imx_sim_type {
+ IMX7D_SIM = 0,
+ IMX6UL_SIM,
+};
+
+static const struct of_device_id sim_imx_dt_ids[] = {
+ { .compatible = "fsl,imx7d-sim",
+ .data = &imx_sim_devtype[IMX7D_SIM], },
+ { .compatible = "fsl,imx6ul-sim",
+ .data = &imx_sim_devtype[IMX6UL_SIM], },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, mlb150_imx_dt_ids);
+
+static int sim_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ const struct of_device_id *of_id;
+ struct sim_t *sim = NULL;
+ struct device_node *of_node = pdev->dev.of_node;
+
+ sim = devm_kzalloc(&pdev->dev, sizeof(struct sim_t),
+ GFP_KERNEL);
+ if (!sim) {
+ dev_err(&pdev->dev, "can't allocate enough memory\n");
+ return -ENOMEM;
+ }
+
+
+ of_id = of_match_device(sim_imx_dt_ids, &pdev->dev);
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ else
+ return -EINVAL;
+
+ sim->clk_rate = FCLK_FREQ;
+ sim->open_cnt = 0;
+
+ sim->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!sim->res) {
+ pr_err("Can't get the MEMORY\n");
+ return -ENOMEM;
+ }
+ sim->ioaddr = devm_ioremap_resource(&pdev->dev, sim->res);
+ dev_dbg(&pdev->dev, "mapped base address: 0x%08x\n", (u32)sim->ioaddr);
+ if (IS_ERR(sim->ioaddr)) {
+ dev_err(&pdev->dev,
+ "failed to get ioremap base\n");
+ ret = PTR_ERR(sim->ioaddr);
+ return ret;
+ }
+
+ /* request the sim clk and sim_serial_clk */
+ sim->clk = devm_clk_get(&pdev->dev, "sim");
+ if (IS_ERR(sim->clk)) {
+ ret = PTR_ERR(sim->clk);
+ pr_err("Get CLK ERROR !\n");
+ return ret;
+ }
+ pr_debug("sim clock:%lu\n", clk_get_rate(sim->clk));
+
+ sim->ipb_irq = platform_get_irq(pdev, 0);
+ if (sim->ipb_irq < 0) {
+ dev_err(&pdev->dev, "No ipb irq line provided\n");
+ return -ENOENT;
+ }
+ if (devm_request_irq(&pdev->dev, sim->ipb_irq, sim_irq_handler,
+ 0, "mxc_sim_ipb", sim)) {
+ dev_err(&pdev->dev, "can't claim irq %d\n", sim->ipb_irq);
+ return -ENOENT;
+ }
+
+ sim->sven_low_active = of_property_read_bool(of_node,
+ "sven_low_active");
+
+ ret = of_property_read_u32(of_node, "port", &sim->port_index);
+ if (ret)
+ sim->port_index = 0;
+ sim->port_ctrl_reg = (sim->port_index == 0) ?
+ PORT0_CNTL : PORT1_CNTL;
+ sim->port_detect_reg = (sim->port_index == 0) ?
+ PORT0_DETECT : PORT1_DETECT;
+ sim->quirks = pdev->id_entry->driver_data;
+
+ platform_set_drvdata(pdev, sim);
+
+ /*
+ *@todo: Need to figure a better way if possible.
+ */
+ sim_dev.parent = &(pdev->dev);
+
+ misc_register(&sim_dev);
+
+ return 0;
+}
+
+static int sim_remove(struct platform_device *pdev)
+{
+ struct sim_t *sim = platform_get_drvdata(pdev);
+
+ if (sim->open_cnt)
+ clk_disable_unprepare(sim->clk);
+
+ misc_deregister(&sim_dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int sim_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct sim_t *sim = platform_get_drvdata(pdev);
+
+ if (sim->open_cnt)
+ clk_disable_unprepare(sim->clk);
+
+ pinctrl_pm_select_sleep_state(&pdev->dev);
+
+ return 0;
+}
+
+static int sim_resume(struct platform_device *pdev)
+{
+ struct sim_t *sim = platform_get_drvdata(pdev);
+
+ if (sim->open_cnt)
+ clk_prepare_enable(sim->clk);
+
+ pinctrl_pm_select_default_state(&pdev->dev);
+
+ return 0;
+}
+#else
+#define sim_suspend NULL
+#define sim_resume NULL
+#endif
+
+static struct platform_driver sim_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = sim_imx_dt_ids,
+ },
+ .probe = sim_probe,
+ .remove = sim_remove,
+ .suspend = sim_suspend,
+ .resume = sim_resume,
+ .id_table = imx_sim_devtype,
+};
+
+static int __init sim_drv_init(void)
+{
+ return platform_driver_register(&sim_driver);
+}
+
+static void __exit sim_drv_exit(void)
+{
+ platform_driver_unregister(&sim_driver);
+}
+
+module_init(sim_drv_init);
+module_exit(sim_drv_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC SIM Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/mxc/vpu/Kconfig b/drivers/mxc/vpu/Kconfig
new file mode 100644
index 000000000000..520209601dbe
--- /dev/null
+++ b/drivers/mxc/vpu/Kconfig
@@ -0,0 +1,31 @@
+#
+# Codec configuration
+#
+
+menu "MXC VPU(Video Processing Unit) support"
+
+config MXC_VPU
+ tristate "Support for MXC VPU(Video Processing Unit)"
+ depends on (SOC_IMX27 || SOC_IMX5 || SOC_IMX6Q)
+ default y
+ ---help---
+ The VPU codec device provides codec function for H.264/MPEG4/H.263,
+ as well as MPEG2/VC-1/DivX on some platforms.
+
+config MXC_VPU_DEBUG
+ bool "MXC VPU debugging"
+ depends on MXC_VPU != n
+ help
+ This is an option for the developers; most people should
+ say N here. This enables MXC VPU driver debugging.
+
+config MX6_VPU_352M
+ bool "MX6 VPU 352M"
+ depends on MXC_VPU
+ default n
+ help
+ Increase VPU frequncy to 352M, the config will disable bus frequency
+ adjust dynamic, and CPU lowest setpoint will be 352Mhz.
+ This config is used for special VPU use case.
+
+endmenu
diff --git a/drivers/mxc/vpu/Makefile b/drivers/mxc/vpu/Makefile
new file mode 100644
index 000000000000..1a821f4921cb
--- /dev/null
+++ b/drivers/mxc/vpu/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the VPU drivers.
+#
+
+obj-$(CONFIG_MXC_VPU) += mxc_vpu.o
+
+ifeq ($(CONFIG_MXC_VPU_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c
new file mode 100644
index 000000000000..2c9152d9c80e
--- /dev/null
+++ b/drivers/mxc/vpu/mxc_vpu.c
@@ -0,0 +1,1348 @@
+/*
+ * Copyright 2006-2015 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 mxc_vpu.c
+ *
+ * @brief VPU system initialization and file operation implementation
+ *
+ * @ingroup VPU
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/stat.h>
+#include <linux/platform_device.h>
+#include <linux/kdev_t.h>
+#include <linux/dma-mapping.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/fsl_devices.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/regulator/consumer.h>
+#include <linux/page-flags.h>
+#include <linux/mm_types.h>
+#include <linux/types.h>
+#include <linux/memblock.h>
+#include <linux/memory.h>
+#include <linux/version.h>
+#include <asm/page.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/sizes.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+#include <linux/iram_alloc.h>
+#include <mach/clock.h>
+#include <mach/hardware.h>
+#include <mach/mxc_vpu.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+#include <linux/busfreq-imx.h>
+#include <linux/clk.h>
+#include <linux/genalloc.h>
+#include <linux/mxc_vpu.h>
+#include <linux/of.h>
+#include <linux/reset.h>
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+#include <mach/busfreq.h>
+#include <mach/common.h>
+#else
+#include <asm/sizes.h>
+#endif
+
+/* Define one new pgprot which combined uncached and XN(never executable) */
+#define pgprot_noncachedxn(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
+
+struct vpu_priv {
+ struct fasync_struct *async_queue;
+ struct work_struct work;
+ struct workqueue_struct *workqueue;
+ struct mutex lock;
+};
+
+/* To track the allocated memory buffer */
+struct memalloc_record {
+ struct list_head list;
+ struct vpu_mem_desc mem;
+};
+
+struct iram_setting {
+ u32 start;
+ u32 end;
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+static struct gen_pool *iram_pool;
+static u32 iram_base;
+#endif
+
+static LIST_HEAD(head);
+
+static int vpu_major;
+static int vpu_clk_usercount;
+static struct class *vpu_class;
+static struct vpu_priv vpu_data;
+static u8 open_count;
+static struct clk *vpu_clk;
+static struct vpu_mem_desc bitwork_mem = { 0 };
+static struct vpu_mem_desc pic_para_mem = { 0 };
+static struct vpu_mem_desc user_data_mem = { 0 };
+static struct vpu_mem_desc share_mem = { 0 };
+static struct vpu_mem_desc vshare_mem = { 0 };
+
+static void __iomem *vpu_base;
+static int vpu_ipi_irq;
+static u32 phy_vpu_base_addr;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+static phys_addr_t top_address_DRAM;
+static struct mxc_vpu_platform_data *vpu_plat;
+#endif
+
+static struct device *vpu_dev;
+
+/* IRAM setting */
+static struct iram_setting iram;
+
+/* implement the blocking ioctl */
+static int irq_status;
+static int codec_done;
+static wait_queue_head_t vpu_queue;
+
+#ifdef CONFIG_SOC_IMX6Q
+#define MXC_VPU_HAS_JPU
+#endif
+
+#ifdef MXC_VPU_HAS_JPU
+static int vpu_jpu_irq;
+#endif
+
+#ifdef CONFIG_PM
+static unsigned int regBk[64];
+static unsigned int pc_before_suspend;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+static struct regulator *vpu_regulator;
+#endif
+#endif
+static atomic_t clk_cnt_from_ioc = ATOMIC_INIT(0);
+
+#define READ_REG(x) readl_relaxed(vpu_base + x)
+#define WRITE_REG(val, x) writel_relaxed(val, vpu_base + x)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+/* redirect to static functions */
+static int cpu_is_mx6dl(void)
+{
+ int ret;
+ ret = of_machine_is_compatible("fsl,imx6dl");
+ return ret;
+}
+
+static int cpu_is_mx6q(void)
+{
+ int ret;
+ ret = of_machine_is_compatible("fsl,imx6q");
+ return ret;
+}
+#endif
+
+static void vpu_reset(void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+ int ret;
+
+ ret = device_reset(vpu_dev);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+ imx_src_reset_vpu();
+#else
+ if (vpu_plat->reset)
+ vpu_plat->reset();
+#endif
+}
+
+static long vpu_power_get(bool on)
+{
+ long ret = 0;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
+ if (on) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ vpu_regulator = regulator_get(NULL, "cpu_vddvpu");
+ ret = IS_ERR(vpu_regulator);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+ vpu_regulator = devm_regulator_get(vpu_dev, "pu");
+ ret = IS_ERR(vpu_regulator);
+#endif
+ } else {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ if (!IS_ERR(vpu_regulator))
+ regulator_put(vpu_regulator);
+#endif
+ }
+#endif
+ return ret;
+}
+
+static void vpu_power_up(bool on)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+ if (on)
+ pm_runtime_get_sync(vpu_dev);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+ if (on) {
+ if (!IS_ERR(vpu_regulator)) {
+ if (regulator_enable(vpu_regulator))
+ dev_err(vpu_dev, "failed to power up vpu\n");
+ }
+ } else {
+ if (!IS_ERR(vpu_regulator)) {
+ if (regulator_disable(vpu_regulator))
+ dev_err(vpu_dev, "failed to power down vpu\n");
+ }
+ }
+#else
+ imx_gpc_power_up_pu(on);
+#endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+ if (!on)
+ pm_runtime_put_sync_suspend(vpu_dev);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+static int cpu_is_mx53(void)
+{
+ return 0;
+}
+
+static int cpu_is_mx51(void)
+{
+ return 0;
+}
+
+#define VM_RESERVED 0
+#endif
+
+/*!
+ * Private function to alloc dma buffer
+ * @return status 0 success.
+ */
+static int vpu_alloc_dma_buffer(struct vpu_mem_desc *mem)
+{
+ mem->cpu_addr = (unsigned long)
+ dma_alloc_coherent(NULL, PAGE_ALIGN(mem->size),
+ (dma_addr_t *) (&mem->phy_addr),
+ GFP_DMA | GFP_KERNEL);
+ dev_dbg(vpu_dev, "[ALLOC] mem alloc cpu_addr = 0x%x\n", mem->cpu_addr);
+ if ((void *)(mem->cpu_addr) == NULL) {
+ dev_err(vpu_dev, "Physical memory allocation error!\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*!
+ * Private function to free dma buffer
+ */
+static void vpu_free_dma_buffer(struct vpu_mem_desc *mem)
+{
+ if (mem->cpu_addr != 0) {
+ dma_free_coherent(0, PAGE_ALIGN(mem->size),
+ (void *)mem->cpu_addr, mem->phy_addr);
+ }
+}
+
+/*!
+ * Private function to free buffers
+ * @return status 0 success.
+ */
+static int vpu_free_buffers(void)
+{
+ struct memalloc_record *rec, *n;
+ struct vpu_mem_desc mem;
+
+ list_for_each_entry_safe(rec, n, &head, list) {
+ mem = rec->mem;
+ if (mem.cpu_addr != 0) {
+ vpu_free_dma_buffer(&mem);
+ dev_dbg(vpu_dev, "[FREE] freed paddr=0x%08X\n", mem.phy_addr);
+ /* delete from list */
+ list_del(&rec->list);
+ kfree(rec);
+ }
+ }
+
+ return 0;
+}
+
+static inline void vpu_worker_callback(struct work_struct *w)
+{
+ struct vpu_priv *dev = container_of(w, struct vpu_priv,
+ work);
+
+ if (dev->async_queue)
+ kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
+
+ irq_status = 1;
+ /*
+ * Clock is gated on when dec/enc started, gate it off when
+ * codec is done.
+ */
+ if (codec_done)
+ codec_done = 0;
+
+ wake_up_interruptible(&vpu_queue);
+}
+
+/*!
+ * @brief vpu interrupt handler
+ */
+static irqreturn_t vpu_ipi_irq_handler(int irq, void *dev_id)
+{
+ struct vpu_priv *dev = dev_id;
+ unsigned long reg;
+
+ reg = READ_REG(BIT_INT_REASON);
+ if (reg & 0x8)
+ codec_done = 1;
+ WRITE_REG(0x1, BIT_INT_CLEAR);
+
+ queue_work(dev->workqueue, &dev->work);
+
+ return IRQ_HANDLED;
+}
+
+/*!
+ * @brief vpu jpu interrupt handler
+ */
+#ifdef MXC_VPU_HAS_JPU
+static irqreturn_t vpu_jpu_irq_handler(int irq, void *dev_id)
+{
+ struct vpu_priv *dev = dev_id;
+ unsigned long reg;
+
+ reg = READ_REG(MJPEG_PIC_STATUS_REG);
+ if (reg & 0x3)
+ codec_done = 1;
+
+ queue_work(dev->workqueue, &dev->work);
+
+ return IRQ_HANDLED;
+}
+#endif
+
+/*!
+ * @brief check phy memory prepare to pass to vpu is valid or not, we
+ * already address some issue that if pass a wrong address to vpu
+ * (like virtual address), system will hang.
+ *
+ * @return true return is a valid phy memory address, false return not.
+ */
+bool vpu_is_valid_phy_memory(u32 paddr)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ if (paddr > top_address_DRAM)
+ return false;
+#endif
+
+ return true;
+}
+
+/*!
+ * @brief open function for vpu file operation
+ *
+ * @return 0 on success or negative error code on error
+ */
+static int vpu_open(struct inode *inode, struct file *filp)
+{
+
+ mutex_lock(&vpu_data.lock);
+
+ if (open_count++ == 0) {
+ vpu_power_up(true);
+
+#ifdef CONFIG_SOC_IMX6Q
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+ if (READ_REG(BIT_CUR_PC))
+ dev_dbg(vpu_dev, "Not power off before vpu open!\n");
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+#endif
+ }
+
+ filp->private_data = (void *)(&vpu_data);
+ mutex_unlock(&vpu_data.lock);
+ return 0;
+}
+
+/*!
+ * @brief IO ctrl function for vpu file operation
+ * @param cmd IO ctrl command
+ * @return 0 on success or negative error code on error
+ */
+static long vpu_ioctl(struct file *filp, u_int cmd,
+ u_long arg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case VPU_IOC_PHYMEM_ALLOC:
+ {
+ struct memalloc_record *rec;
+
+ rec = kzalloc(sizeof(*rec), GFP_KERNEL);
+ if (!rec)
+ return -ENOMEM;
+
+ ret = copy_from_user(&(rec->mem),
+ (struct vpu_mem_desc *)arg,
+ sizeof(struct vpu_mem_desc));
+ if (ret) {
+ kfree(rec);
+ return -EFAULT;
+ }
+
+ dev_dbg(vpu_dev, "[ALLOC] mem alloc size = 0x%x\n",
+ rec->mem.size);
+
+ ret = vpu_alloc_dma_buffer(&(rec->mem));
+ if (ret == -1) {
+ kfree(rec);
+ dev_err(vpu_dev,
+ "Physical memory allocation error!\n");
+ break;
+ }
+ ret = copy_to_user((void __user *)arg, &(rec->mem),
+ sizeof(struct vpu_mem_desc));
+ if (ret) {
+ kfree(rec);
+ ret = -EFAULT;
+ break;
+ }
+
+ mutex_lock(&vpu_data.lock);
+ list_add(&rec->list, &head);
+ mutex_unlock(&vpu_data.lock);
+
+ break;
+ }
+ case VPU_IOC_PHYMEM_FREE:
+ {
+ struct memalloc_record *rec, *n;
+ struct vpu_mem_desc vpu_mem;
+
+ ret = copy_from_user(&vpu_mem,
+ (struct vpu_mem_desc *)arg,
+ sizeof(struct vpu_mem_desc));
+ if (ret)
+ return -EACCES;
+
+ dev_dbg(vpu_dev, "[FREE] mem freed cpu_addr = 0x%x\n",
+ vpu_mem.cpu_addr);
+ if ((void *)vpu_mem.cpu_addr != NULL)
+ vpu_free_dma_buffer(&vpu_mem);
+
+ mutex_lock(&vpu_data.lock);
+ list_for_each_entry_safe(rec, n, &head, list) {
+ if (rec->mem.cpu_addr == vpu_mem.cpu_addr) {
+ /* delete from list */
+ list_del(&rec->list);
+ kfree(rec);
+ break;
+ }
+ }
+ mutex_unlock(&vpu_data.lock);
+
+ break;
+ }
+ case VPU_IOC_WAIT4INT:
+ {
+ u_long timeout = (u_long) arg;
+ if (!wait_event_interruptible_timeout
+ (vpu_queue, irq_status != 0,
+ msecs_to_jiffies(timeout))) {
+ dev_warn(vpu_dev, "VPU blocking: timeout.\n");
+ ret = -ETIME;
+ } else if (signal_pending(current)) {
+ dev_warn(vpu_dev, "VPU interrupt received.\n");
+ ret = -ERESTARTSYS;
+ } else
+ irq_status = 0;
+ break;
+ }
+ case VPU_IOC_IRAM_SETTING:
+ {
+ ret = copy_to_user((void __user *)arg, &iram,
+ sizeof(struct iram_setting));
+ if (ret)
+ ret = -EFAULT;
+
+ break;
+ }
+ case VPU_IOC_CLKGATE_SETTING:
+ {
+ u32 clkgate_en;
+
+ if (get_user(clkgate_en, (u32 __user *) arg))
+ return -EFAULT;
+
+ if (clkgate_en) {
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+ atomic_inc(&clk_cnt_from_ioc);
+ } else {
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ atomic_dec(&clk_cnt_from_ioc);
+ }
+
+ break;
+ }
+ case VPU_IOC_GET_SHARE_MEM:
+ {
+ mutex_lock(&vpu_data.lock);
+ if (share_mem.cpu_addr != 0) {
+ ret = copy_to_user((void __user *)arg,
+ &share_mem,
+ sizeof(struct vpu_mem_desc));
+ mutex_unlock(&vpu_data.lock);
+ break;
+ } else {
+ if (copy_from_user(&share_mem,
+ (struct vpu_mem_desc *)arg,
+ sizeof(struct vpu_mem_desc))) {
+ mutex_unlock(&vpu_data.lock);
+ return -EFAULT;
+ }
+ if (vpu_alloc_dma_buffer(&share_mem) == -1)
+ ret = -EFAULT;
+ else {
+ if (copy_to_user((void __user *)arg,
+ &share_mem,
+ sizeof(struct
+ vpu_mem_desc)))
+ ret = -EFAULT;
+ }
+ }
+ mutex_unlock(&vpu_data.lock);
+ break;
+ }
+ case VPU_IOC_REQ_VSHARE_MEM:
+ {
+ mutex_lock(&vpu_data.lock);
+ if (vshare_mem.cpu_addr != 0) {
+ ret = copy_to_user((void __user *)arg,
+ &vshare_mem,
+ sizeof(struct vpu_mem_desc));
+ mutex_unlock(&vpu_data.lock);
+ break;
+ } else {
+ if (copy_from_user(&vshare_mem,
+ (struct vpu_mem_desc *)arg,
+ sizeof(struct
+ vpu_mem_desc))) {
+ mutex_unlock(&vpu_data.lock);
+ return -EFAULT;
+ }
+ /* vmalloc shared memory if not allocated */
+ if (!vshare_mem.cpu_addr)
+ vshare_mem.cpu_addr =
+ (unsigned long)
+ vmalloc_user(vshare_mem.size);
+ if (copy_to_user
+ ((void __user *)arg, &vshare_mem,
+ sizeof(struct vpu_mem_desc)))
+ ret = -EFAULT;
+ }
+ mutex_unlock(&vpu_data.lock);
+ break;
+ }
+ case VPU_IOC_GET_WORK_ADDR:
+ {
+ if (bitwork_mem.cpu_addr != 0) {
+ ret =
+ copy_to_user((void __user *)arg,
+ &bitwork_mem,
+ sizeof(struct vpu_mem_desc));
+ break;
+ } else {
+ if (copy_from_user(&bitwork_mem,
+ (struct vpu_mem_desc *)arg,
+ sizeof(struct vpu_mem_desc)))
+ return -EFAULT;
+
+ if (vpu_alloc_dma_buffer(&bitwork_mem) == -1)
+ ret = -EFAULT;
+ else if (copy_to_user((void __user *)arg,
+ &bitwork_mem,
+ sizeof(struct
+ vpu_mem_desc)))
+ ret = -EFAULT;
+ }
+ break;
+ }
+ /*
+ * The following two ioctl is used when user allocates working buffer
+ * and register it to vpu driver.
+ */
+ case VPU_IOC_QUERY_BITWORK_MEM:
+ {
+ if (copy_to_user((void __user *)arg,
+ &bitwork_mem,
+ sizeof(struct vpu_mem_desc)))
+ ret = -EFAULT;
+ break;
+ }
+ case VPU_IOC_SET_BITWORK_MEM:
+ {
+ if (copy_from_user(&bitwork_mem,
+ (struct vpu_mem_desc *)arg,
+ sizeof(struct vpu_mem_desc)))
+ ret = -EFAULT;
+ break;
+ }
+ case VPU_IOC_SYS_SW_RESET:
+ {
+ vpu_reset();
+ break;
+ }
+ case VPU_IOC_REG_DUMP:
+ break;
+ case VPU_IOC_PHYMEM_DUMP:
+ break;
+ case VPU_IOC_PHYMEM_CHECK:
+ {
+ struct vpu_mem_desc check_memory;
+ ret = copy_from_user(&check_memory,
+ (void __user *)arg,
+ sizeof(struct vpu_mem_desc));
+ if (ret != 0) {
+ dev_err(vpu_dev, "copy from user failure:%d\n", ret);
+ ret = -EFAULT;
+ break;
+ }
+ ret = vpu_is_valid_phy_memory((u32)check_memory.phy_addr);
+
+ dev_dbg(vpu_dev, "vpu: memory phy:0x%x %s phy memory\n",
+ check_memory.phy_addr, (ret ? "is" : "isn't"));
+ /* borrow .size to pass back the result. */
+ check_memory.size = ret;
+ ret = copy_to_user((void __user *)arg, &check_memory,
+ sizeof(struct vpu_mem_desc));
+ if (ret) {
+ ret = -EFAULT;
+ break;
+ }
+ break;
+ }
+ case VPU_IOC_LOCK_DEV:
+ {
+ u32 lock_en;
+
+ if (get_user(lock_en, (u32 __user *) arg))
+ return -EFAULT;
+
+ if (lock_en)
+ mutex_lock(&vpu_data.lock);
+ else
+ mutex_unlock(&vpu_data.lock);
+
+ break;
+ }
+ default:
+ {
+ dev_err(vpu_dev, "No such IOCTL, cmd is %d\n", cmd);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ return ret;
+}
+
+/*!
+ * @brief Release function for vpu file operation
+ * @return 0 on success or negative error code on error
+ */
+static int vpu_release(struct inode *inode, struct file *filp)
+{
+ int i;
+ unsigned long timeout;
+
+ mutex_lock(&vpu_data.lock);
+
+ if (open_count > 0 && !(--open_count)) {
+
+ /* Wait for vpu go to idle state */
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+ if (READ_REG(BIT_CUR_PC)) {
+
+ timeout = jiffies + HZ;
+ while (READ_REG(BIT_BUSY_FLAG)) {
+ msleep(1);
+ if (time_after(jiffies, timeout)) {
+ dev_warn(vpu_dev, "VPU timeout during release\n");
+ break;
+ }
+ }
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+
+ /* Clean up interrupt */
+ cancel_work_sync(&vpu_data.work);
+ flush_workqueue(vpu_data.workqueue);
+ irq_status = 0;
+
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+ if (READ_REG(BIT_BUSY_FLAG)) {
+
+ if (cpu_is_mx51() || cpu_is_mx53()) {
+ dev_err(vpu_dev,
+ "fatal error: can't gate/power off when VPU is busy\n");
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ mutex_unlock(&vpu_data.lock);
+ return -EFAULT;
+ }
+
+#ifdef CONFIG_SOC_IMX6Q
+ if (cpu_is_mx6dl() || cpu_is_mx6q()) {
+ WRITE_REG(0x11, 0x10F0);
+ timeout = jiffies + HZ;
+ while (READ_REG(0x10F4) != 0x77) {
+ msleep(1);
+ if (time_after(jiffies, timeout))
+ break;
+ }
+
+ if (READ_REG(0x10F4) != 0x77) {
+ dev_err(vpu_dev,
+ "fatal error: can't gate/power off when VPU is busy\n");
+ WRITE_REG(0x0, 0x10F0);
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ mutex_unlock(&vpu_data.lock);
+ return -EFAULT;
+ } else
+ vpu_reset();
+ }
+#endif
+ }
+ }
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+
+ vpu_free_buffers();
+
+ /* Free shared memory when vpu device is idle */
+ vpu_free_dma_buffer(&share_mem);
+ share_mem.cpu_addr = 0;
+ vfree((void *)vshare_mem.cpu_addr);
+ vshare_mem.cpu_addr = 0;
+
+ vpu_clk_usercount = atomic_read(&clk_cnt_from_ioc);
+ for (i = 0; i < vpu_clk_usercount; i++) {
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ atomic_dec(&clk_cnt_from_ioc);
+ }
+
+ vpu_power_up(false);
+ }
+ mutex_unlock(&vpu_data.lock);
+
+ return 0;
+}
+
+/*!
+ * @brief fasync function for vpu file operation
+ * @return 0 on success or negative error code on error
+ */
+static int vpu_fasync(int fd, struct file *filp, int mode)
+{
+ struct vpu_priv *dev = (struct vpu_priv *)filp->private_data;
+ return fasync_helper(fd, filp, mode, &dev->async_queue);
+}
+
+/*!
+ * @brief memory map function of harware registers for vpu file operation
+ * @return 0 on success or negative error code on error
+ */
+static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm)
+{
+ unsigned long pfn;
+
+ vm->vm_flags |= VM_IO | VM_RESERVED;
+ /*
+ * Since vpu registers have been mapped with ioremap() at probe
+ * which L_PTE_XN is 1, and the same physical address must be
+ * mapped multiple times with same type, so set L_PTE_XN to 1 here.
+ * Otherwise, there may be unexpected result in video codec.
+ */
+ vm->vm_page_prot = pgprot_noncachedxn(vm->vm_page_prot);
+ pfn = phy_vpu_base_addr >> PAGE_SHIFT;
+ dev_dbg(vpu_dev, "size=0x%x, page no.=0x%x\n",
+ (int)(vm->vm_end - vm->vm_start), (int)pfn);
+ return remap_pfn_range(vm, vm->vm_start, pfn, vm->vm_end - vm->vm_start,
+ vm->vm_page_prot) ? -EAGAIN : 0;
+}
+
+/*!
+ * @brief memory map function of memory for vpu file operation
+ * @return 0 on success or negative error code on error
+ */
+static int vpu_map_dma_mem(struct file *fp, struct vm_area_struct *vm)
+{
+ int request_size;
+ request_size = vm->vm_end - vm->vm_start;
+
+ dev_dbg(vpu_dev, "start=0x%x, pgoff=0x%x, size=0x%x\n",
+ (unsigned int)(vm->vm_start), (unsigned int)(vm->vm_pgoff),
+ request_size);
+
+ vm->vm_flags |= VM_IO | VM_RESERVED;
+ vm->vm_page_prot = pgprot_writecombine(vm->vm_page_prot);
+
+ return remap_pfn_range(vm, vm->vm_start, vm->vm_pgoff,
+ request_size, vm->vm_page_prot) ? -EAGAIN : 0;
+
+}
+
+/* !
+ * @brief memory map function of vmalloced share memory
+ * @return 0 on success or negative error code on error
+ */
+static int vpu_map_vshare_mem(struct file *fp, struct vm_area_struct *vm)
+{
+ int ret = -EINVAL;
+
+ ret = remap_vmalloc_range(vm, (void *)(vm->vm_pgoff << PAGE_SHIFT), 0);
+ vm->vm_flags |= VM_IO;
+
+ return ret;
+}
+/*!
+ * @brief memory map interface for vpu file operation
+ * @return 0 on success or negative error code on error
+ */
+static int vpu_mmap(struct file *fp, struct vm_area_struct *vm)
+{
+ unsigned long offset;
+
+ offset = vshare_mem.cpu_addr >> PAGE_SHIFT;
+
+ if (vm->vm_pgoff && (vm->vm_pgoff == offset))
+ return vpu_map_vshare_mem(fp, vm);
+ else if (vm->vm_pgoff)
+ return vpu_map_dma_mem(fp, vm);
+ else
+ return vpu_map_hwregs(fp, vm);
+}
+
+const struct file_operations vpu_fops = {
+ .owner = THIS_MODULE,
+ .open = vpu_open,
+ .unlocked_ioctl = vpu_ioctl,
+ .release = vpu_release,
+ .fasync = vpu_fasync,
+ .mmap = vpu_mmap,
+};
+
+/*!
+ * This function is called by the driver framework to initialize the vpu device.
+ * @param dev The device structure for the vpu passed in by the framework.
+ * @return 0 on success or negative error code on error
+ */
+static int vpu_dev_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ struct device *temp_class;
+ struct resource *res;
+ unsigned long addr = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+ struct device_node *np = pdev->dev.of_node;
+ u32 iramsize;
+
+ err = of_property_read_u32(np, "iramsize", (u32 *)&iramsize);
+ if (!err && iramsize)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+ {
+ iram_pool = of_gen_pool_get(np, "iram", 0);
+ if (!iram_pool) {
+ dev_err(&pdev->dev, "iram pool not available\n");
+ return -ENOMEM;
+ }
+
+ iram_base = gen_pool_alloc(iram_pool, iramsize);
+ if (!iram_base) {
+ dev_err(&pdev->dev, "unable to alloc iram\n");
+ return -ENOMEM;
+ }
+
+ addr = gen_pool_virt_to_phys(iram_pool, iram_base);
+ }
+#else
+ iram_alloc(iramsize, &addr);
+#endif
+ if (addr == 0)
+ iram.start = iram.end = 0;
+ else {
+ iram.start = addr;
+ iram.end = addr + iramsize - 1;
+ }
+#else
+
+ vpu_plat = pdev->dev.platform_data;
+
+ if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size)
+ iram_alloc(vpu_plat->iram_size, &addr);
+ if (addr == 0)
+ iram.start = iram.end = 0;
+ else {
+ iram.start = addr;
+ iram.end = addr + vpu_plat->iram_size - 1;
+ }
+#endif
+
+ vpu_dev = &pdev->dev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpu_regs");
+ if (!res) {
+ dev_err(vpu_dev, "vpu: unable to get vpu base addr\n");
+ return -ENODEV;
+ }
+ phy_vpu_base_addr = res->start;
+ vpu_base = ioremap(res->start, res->end - res->start);
+
+ vpu_major = register_chrdev(vpu_major, "mxc_vpu", &vpu_fops);
+ if (vpu_major < 0) {
+ dev_err(vpu_dev, "vpu: unable to get a major for VPU\n");
+ err = -EBUSY;
+ goto error;
+ }
+
+ vpu_class = class_create(THIS_MODULE, "mxc_vpu");
+ if (IS_ERR(vpu_class)) {
+ err = PTR_ERR(vpu_class);
+ goto err_out_chrdev;
+ }
+
+ temp_class = device_create(vpu_class, NULL, MKDEV(vpu_major, 0),
+ NULL, "mxc_vpu");
+ if (IS_ERR(temp_class)) {
+ err = PTR_ERR(temp_class);
+ goto err_out_class;
+ }
+
+ vpu_clk = clk_get(&pdev->dev, "vpu_clk");
+ if (IS_ERR(vpu_clk)) {
+ err = -ENOENT;
+ goto err_out_class;
+ }
+
+ vpu_ipi_irq = platform_get_irq_byname(pdev, "vpu_ipi_irq");
+ if (vpu_ipi_irq < 0) {
+ dev_err(vpu_dev, "vpu: unable to get vpu interrupt\n");
+ err = -ENXIO;
+ goto err_out_class;
+ }
+ err = request_irq(vpu_ipi_irq, vpu_ipi_irq_handler, 0, "VPU_CODEC_IRQ",
+ (void *)(&vpu_data));
+ if (err)
+ goto err_out_class;
+ if (vpu_power_get(true)) {
+ if (!(cpu_is_mx51() || cpu_is_mx53())) {
+ dev_err(vpu_dev, "failed to get vpu power\n");
+ goto err_out_class;
+ } else {
+ /* regulator_get will return error on MX5x,
+ * just igore it everywhere*/
+ dev_warn(vpu_dev, "failed to get vpu power\n");
+ }
+ }
+
+#ifdef MXC_VPU_HAS_JPU
+ vpu_jpu_irq = platform_get_irq_byname(pdev, "vpu_jpu_irq");
+ if (vpu_jpu_irq < 0) {
+ dev_err(vpu_dev, "vpu: unable to get vpu jpu interrupt\n");
+ err = -ENXIO;
+ free_irq(vpu_ipi_irq, &vpu_data);
+ goto err_out_class;
+ }
+ err = request_irq(vpu_jpu_irq, vpu_jpu_irq_handler, IRQF_TRIGGER_RISING,
+ "VPU_JPG_IRQ", (void *)(&vpu_data));
+ if (err) {
+ free_irq(vpu_ipi_irq, &vpu_data);
+ goto err_out_class;
+ }
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+ pm_runtime_enable(&pdev->dev);
+#endif
+
+ vpu_data.workqueue = create_workqueue("vpu_wq");
+ INIT_WORK(&vpu_data.work, vpu_worker_callback);
+ mutex_init(&vpu_data.lock);
+ dev_info(vpu_dev, "VPU initialized\n");
+ goto out;
+
+err_out_class:
+ device_destroy(vpu_class, MKDEV(vpu_major, 0));
+ class_destroy(vpu_class);
+err_out_chrdev:
+ unregister_chrdev(vpu_major, "mxc_vpu");
+error:
+ iounmap(vpu_base);
+out:
+ return err;
+}
+
+static int vpu_dev_remove(struct platform_device *pdev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+ pm_runtime_disable(&pdev->dev);
+#endif
+ free_irq(vpu_ipi_irq, &vpu_data);
+#ifdef MXC_VPU_HAS_JPU
+ free_irq(vpu_jpu_irq, &vpu_data);
+#endif
+ cancel_work_sync(&vpu_data.work);
+ flush_workqueue(vpu_data.workqueue);
+ destroy_workqueue(vpu_data.workqueue);
+
+ iounmap(vpu_base);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+ if (iram.start)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+ gen_pool_free(iram_pool, iram_base, iram.end-iram.start+1);
+#else
+ iram_free(iram.start, iram.end-iram.start+1);
+#endif
+#else
+ if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size)
+ iram_free(iram.start, vpu_plat->iram_size);
+#endif
+
+ vpu_power_get(false);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+static int vpu_suspend(struct device *dev)
+#else
+static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
+#endif
+{
+ int i;
+ unsigned long timeout;
+
+ mutex_lock(&vpu_data.lock);
+ if (open_count == 0) {
+ /* VPU is released (all instances are freed),
+ * clock is already off, context is no longer needed,
+ * power is already off on MX6,
+ * gate power on MX51 */
+ if (cpu_is_mx51()) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ if (vpu_plat->pg)
+ vpu_plat->pg(1);
+#endif
+ }
+ } else {
+ /* Wait for vpu go to idle state, suspect vpu cannot be changed
+ to idle state after about 1 sec */
+ timeout = jiffies + HZ;
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+ while (READ_REG(BIT_BUSY_FLAG)) {
+ msleep(1);
+ if (time_after(jiffies, timeout)) {
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ mutex_unlock(&vpu_data.lock);
+ return -EAGAIN;
+ }
+ }
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+
+ /* Make sure clock is disabled before suspend */
+ vpu_clk_usercount = atomic_read(&clk_cnt_from_ioc);
+ for (i = 0; i < vpu_clk_usercount; i++) {
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ }
+
+ if (cpu_is_mx53()) {
+ mutex_unlock(&vpu_data.lock);
+ return 0;
+ }
+
+ if (bitwork_mem.cpu_addr != 0) {
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+ /* Save 64 registers from BIT_CODE_BUF_ADDR */
+ for (i = 0; i < 64; i++)
+ regBk[i] = READ_REG(BIT_CODE_BUF_ADDR + (i * 4));
+ pc_before_suspend = READ_REG(BIT_CUR_PC);
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ if (vpu_plat->pg)
+ vpu_plat->pg(1);
+#endif
+
+ /* If VPU is working before suspend, disable
+ * regulator to make usecount right. */
+ vpu_power_up(false);
+ }
+
+ mutex_unlock(&vpu_data.lock);
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+static int vpu_resume(struct device *dev)
+#else
+static int vpu_resume(struct platform_device *pdev)
+#endif
+{
+ int i;
+
+ mutex_lock(&vpu_data.lock);
+ if (open_count == 0) {
+ /* VPU is released (all instances are freed),
+ * clock should be kept off, context is no longer needed,
+ * power should be kept off on MX6,
+ * disable power gating on MX51 */
+ if (cpu_is_mx51()) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ if (vpu_plat->pg)
+ vpu_plat->pg(0);
+#endif
+ }
+ } else {
+ if (cpu_is_mx53())
+ goto recover_clk;
+
+ /* If VPU is working before suspend, enable
+ * regulator to make usecount right. */
+ vpu_power_up(true);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ if (vpu_plat->pg)
+ vpu_plat->pg(0);
+#endif
+
+ if (bitwork_mem.cpu_addr != 0) {
+ u32 *p = (u32 *) bitwork_mem.cpu_addr;
+ u32 data, pc;
+ u16 data_hi;
+ u16 data_lo;
+
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+
+ pc = READ_REG(BIT_CUR_PC);
+ if (pc) {
+ dev_warn(vpu_dev, "Not power off after suspend (PC=0x%x)\n", pc);
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ goto recover_clk;
+ }
+
+ /* Restore registers */
+ for (i = 0; i < 64; i++)
+ WRITE_REG(regBk[i], BIT_CODE_BUF_ADDR + (i * 4));
+
+ WRITE_REG(0x0, BIT_RESET_CTRL);
+ WRITE_REG(0x0, BIT_CODE_RUN);
+ /* MX6 RTL has a bug not to init MBC_SET_SUBBLK_EN on reset */
+#ifdef CONFIG_SOC_IMX6Q
+ WRITE_REG(0x0, MBC_SET_SUBBLK_EN);
+#endif
+
+ /*
+ * Re-load boot code, from the codebuffer in external RAM.
+ * Thankfully, we only need 4096 bytes, same for all platforms.
+ */
+ for (i = 0; i < 2048; i += 4) {
+ data = p[(i / 2) + 1];
+ data_hi = (data >> 16) & 0xFFFF;
+ data_lo = data & 0xFFFF;
+ WRITE_REG((i << 16) | data_hi, BIT_CODE_DOWN);
+ WRITE_REG(((i + 1) << 16) | data_lo,
+ BIT_CODE_DOWN);
+
+ data = p[i / 2];
+ data_hi = (data >> 16) & 0xFFFF;
+ data_lo = data & 0xFFFF;
+ WRITE_REG(((i + 2) << 16) | data_hi,
+ BIT_CODE_DOWN);
+ WRITE_REG(((i + 3) << 16) | data_lo,
+ BIT_CODE_DOWN);
+ }
+
+ if (pc_before_suspend) {
+ WRITE_REG(0x1, BIT_BUSY_FLAG);
+ WRITE_REG(0x1, BIT_CODE_RUN);
+ while (READ_REG(BIT_BUSY_FLAG))
+ ;
+ } else {
+ dev_warn(vpu_dev, "PC=0 before suspend\n");
+ }
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ }
+
+recover_clk:
+ /* Recover vpu clock */
+ for (i = 0; i < vpu_clk_usercount; i++) {
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+ }
+ }
+
+ mutex_unlock(&vpu_data.lock);
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+static int vpu_runtime_suspend(struct device *dev)
+{
+ release_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+
+static int vpu_runtime_resume(struct device *dev)
+{
+ request_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+
+static const struct dev_pm_ops vpu_pm_ops = {
+ SET_RUNTIME_PM_OPS(vpu_runtime_suspend, vpu_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(vpu_suspend, vpu_resume)
+};
+#endif
+
+#else
+#define vpu_suspend NULL
+#define vpu_resume NULL
+#endif /* !CONFIG_PM */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+static const struct of_device_id vpu_of_match[] = {
+ { .compatible = "fsl,imx6-vpu", },
+ {/* sentinel */}
+};
+MODULE_DEVICE_TABLE(of, vpu_of_match);
+#endif
+
+/*! Driver definition
+ *
+ */
+static struct platform_driver mxcvpu_driver = {
+ .driver = {
+ .name = "mxc_vpu",
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+ .of_match_table = vpu_of_match,
+#ifdef CONFIG_PM
+ .pm = &vpu_pm_ops,
+#endif
+#endif
+ },
+ .probe = vpu_dev_probe,
+ .remove = vpu_dev_remove,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ .suspend = vpu_suspend,
+ .resume = vpu_resume,
+#endif
+};
+
+static int __init vpu_init(void)
+{
+ int ret = platform_driver_register(&mxcvpu_driver);
+
+ init_waitqueue_head(&vpu_queue);
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+ memblock_analyze();
+ top_address_DRAM = memblock_end_of_DRAM_with_reserved();
+#endif
+
+ return ret;
+}
+
+static void __exit vpu_exit(void)
+{
+ if (vpu_major > 0) {
+ device_destroy(vpu_class, MKDEV(vpu_major, 0));
+ class_destroy(vpu_class);
+ unregister_chrdev(vpu_major, "mxc_vpu");
+ vpu_major = 0;
+ }
+
+ vpu_free_dma_buffer(&bitwork_mem);
+ vpu_free_dma_buffer(&pic_para_mem);
+ vpu_free_dma_buffer(&user_data_mem);
+
+ /* reset VPU state */
+ vpu_power_up(true);
+ clk_prepare(vpu_clk);
+ clk_enable(vpu_clk);
+ vpu_reset();
+ clk_disable(vpu_clk);
+ clk_unprepare(vpu_clk);
+ vpu_power_up(false);
+
+ clk_put(vpu_clk);
+
+ platform_driver_unregister(&mxcvpu_driver);
+ return;
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Linux VPU driver for Freescale i.MX/MXC");
+MODULE_LICENSE("GPL");
+
+module_init(vpu_init);
+module_exit(vpu_exit);
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 16f7cadda5c3..08f885441af9 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -24,15 +24,23 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/can/led.h>
+#include <linux/can/platform/flexcan.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <linux/regmap.h>
#define DRV_NAME "flexcan"
@@ -139,7 +147,8 @@
(FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
#define FLEXCAN_ESR_ALL_INT \
(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
- FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
+ FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \
+ FLEXCAN_ESR_WAK_INT)
/* FLEXCAN interrupt flag register (IFLAG) bits */
/* Errata ERR005829 step7: Reserve first valid MB */
@@ -247,6 +256,13 @@ struct flexcan_devtype_data {
u32 quirks; /* quirks needed for different IP cores */
};
+struct flexcan_stop_mode {
+ struct regmap *gpr;
+ u8 req_gpr;
+ u8 req_bit;
+ u8 ack_gpr;
+ u8 ack_bit;
+};
struct flexcan_priv {
struct can_priv can;
struct napi_struct napi;
@@ -260,6 +276,8 @@ struct flexcan_priv {
struct flexcan_platform_data *pdata;
const struct flexcan_devtype_data *devtype_data;
struct regulator *reg_xceiver;
+ int id;
+ struct flexcan_stop_mode stm;
};
static struct flexcan_devtype_data fsl_p1010_devtype_data = {
@@ -315,8 +333,29 @@ static inline void flexcan_write(u32 val, void __iomem *addr)
}
#endif
+static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
+{
+ /* enable stop request */
+ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG)
+ regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
+ 1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
+}
+
+static inline void flexcan_exit_stop_mode(struct flexcan_priv *priv)
+{
+ /* remove stop request */
+ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG)
+ regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
+ 1 << priv->stm.req_bit, 0);
+}
+
static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
{
+ if (priv->pdata && priv->pdata->transceiver_switch) {
+ priv->pdata->transceiver_switch(1);
+ return 0;
+ }
+
if (!priv->reg_xceiver)
return 0;
@@ -325,6 +364,11 @@ static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
{
+ if (priv->pdata && priv->pdata->transceiver_switch) {
+ priv->pdata->transceiver_switch(0);
+ return 0;
+ }
+
if (!priv->reg_xceiver)
return 0;
@@ -406,7 +450,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
flexcan_write(reg, &regs->mcr);
while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
- udelay(10);
+ udelay(20);
if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
return -ETIMEDOUT;
@@ -727,6 +771,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
if (reg_esr & FLEXCAN_ESR_ALL_INT)
flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
+ if (reg_esr & FLEXCAN_ESR_WAK_INT)
+ flexcan_exit_stop_mode(priv);
+
/* schedule NAPI in case of:
* - rx IRQ
* - state change IRQ
@@ -841,12 +888,15 @@ static int flexcan_chip_start(struct net_device *dev)
* disable local echo
* choose format C
* set max mailbox number
+ * enable self wakeup
*/
reg_mcr = flexcan_read(&regs->mcr);
reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
- FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS |
- FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
+ FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
+ FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS |
+ FLEXCAN_MCR_WAK_MSK | FLEXCAN_MCR_SLF_WAK |
+ FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
flexcan_write(reg_mcr, &regs->mcr);
@@ -1132,6 +1182,56 @@ static void unregister_flexcandev(struct net_device *dev)
unregister_candev(dev);
}
+static int flexcan_of_parse_stop_mode(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *node;
+ struct flexcan_priv *priv;
+ phandle phandle;
+ u32 out_val[5];
+ int ret;
+
+ if (!np)
+ return -EINVAL;
+ /*
+ * stop mode property format is:
+ * <&gpr req_gpr req_bit ack_gpr ack_bit>.
+ */
+ ret = of_property_read_u32_array(np, "stop-mode", out_val, 5);
+ if (ret) {
+ dev_dbg(&pdev->dev, "no stop-mode property\n");
+ return ret;
+ }
+ phandle = *out_val;
+
+ node = of_find_node_by_phandle(phandle);
+ if (!node) {
+ dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
+ return PTR_ERR(node);
+ }
+
+ priv = netdev_priv(dev);
+ priv->stm.gpr = syscon_node_to_regmap(node);
+ if (IS_ERR(priv->stm.gpr)) {
+ dev_dbg(&pdev->dev, "could not find gpr regmap\n");
+ return PTR_ERR(priv->stm.gpr);
+ }
+
+ of_node_put(node);
+
+ priv->stm.req_gpr = out_val[1];
+ priv->stm.req_bit = out_val[2];
+ priv->stm.ack_gpr = out_val[3];
+ priv->stm.ack_bit = out_val[4];
+
+ dev_dbg(&pdev->dev, "gpr %s req_gpr 0x%x req_bit %u ack_gpr 0x%x ack_bit %u\n",
+ node->full_name, priv->stm.req_gpr,
+ priv->stm.req_bit, priv->stm.ack_gpr,
+ priv->stm.ack_bit);
+ return 0;
+}
+
static const struct of_device_id flexcan_of_match[] = {
{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
@@ -1159,6 +1259,7 @@ static int flexcan_probe(struct platform_device *pdev)
struct flexcan_regs __iomem *regs;
int err, irq;
u32 clock_freq = 0;
+ int wakeup = 1;
reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER)
@@ -1240,6 +1341,17 @@ static int flexcan_probe(struct platform_device *pdev)
devm_can_led_init(dev);
+ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG) {
+ err = flexcan_of_parse_stop_mode(pdev);
+ if (err) {
+ wakeup = 0;
+ dev_dbg(&pdev->dev, "failed to parse stop-mode\n");
+ }
+
+ }
+
+ device_set_wakeup_capable(&pdev->dev, wakeup);
+
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
priv->regs, dev->irq);
@@ -1266,17 +1378,25 @@ static int __maybe_unused flexcan_suspend(struct device *device)
{
struct net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev);
- int err;
if (netif_running(dev)) {
- err = flexcan_chip_disable(priv);
- if (err)
- return err;
netif_stop_queue(dev);
netif_device_detach(dev);
+ /*
+ * if wakeup is enabled, enter stop mode
+ * else enter disabled mode.
+ */
+ if (device_may_wakeup(device)) {
+ enable_irq_wake(dev->irq);
+ flexcan_enter_stop_mode(priv);
+ } else {
+ flexcan_chip_stop(dev);
+ }
}
priv->can.state = CAN_STATE_SLEEPING;
+ pinctrl_pm_select_sleep_state(device);
+
return 0;
}
@@ -1284,17 +1404,24 @@ static int __maybe_unused flexcan_resume(struct device *device)
{
struct net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev);
- int err;
+ int err = 0;
+
+ pinctrl_pm_select_default_state(device);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
if (netif_running(dev)) {
netif_device_attach(dev);
netif_start_queue(dev);
- err = flexcan_chip_enable(priv);
- if (err)
- return err;
+
+ if (device_may_wakeup(device)) {
+ disable_irq_wake(dev->irq);
+ flexcan_exit_stop_mode(priv);
+ }
+
+ err = flexcan_chip_start(dev);
}
- return 0;
+
+ return err;
}
static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume);
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index d1ca45fbb164..2204c57fcc7d 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -22,8 +22,8 @@ if NET_VENDOR_FREESCALE
config FEC
tristate "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \
- ARCH_MXC || SOC_IMX28)
- default ARCH_MXC || SOC_IMX28 if ARM
+ ARM || ARM64)
+ default y
select PHYLIB
select PTP_1588_CLOCK
---help---
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index cbe21dc7e37e..7f022dd178e6 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -3,7 +3,7 @@
#
obj-$(CONFIG_FEC) += fec.o
-fec-objs :=fec_main.o fec_ptp.o
+fec-objs :=fec_main.o fec_fixup.o fec_ptp.o
CFLAGS_fec_main.o := -D__CHECK_ENDIAN__
CFLAGS_fec_ptp.o := -D__CHECK_ENDIAN__
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 5ea740b4cf14..1d7b3cc115e4 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -15,11 +15,13 @@
#include <linux/clocksource.h>
#include <linux/net_tstamp.h>
+#include <linux/pm_qos.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
+ defined(CONFIG_ARM64)
/*
* Just figures, Motorola would have to change the offsets for
* registers in the same peripheral device on different models
@@ -194,7 +196,7 @@
* Evidently, ARM SoCs have the FEC block generated in a
* little endian mode so adjust endianness accordingly.
*/
-#if defined(CONFIG_ARM)
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
#define fec32_to_cpu le32_to_cpu
#define fec16_to_cpu le16_to_cpu
#define cpu_to_fec32 cpu_to_le32
@@ -292,7 +294,7 @@ struct bufdesc_ex {
/* This device has up to three irqs on some platforms */
-#define FEC_IRQ_NUM 3
+#define FEC_IRQ_NUM 4
/* Maximum number of queues supported
* ENET with AVB IP can support up to 3 independent tx queues and rx queues.
@@ -353,6 +355,8 @@ struct bufdesc_ex {
#define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
#define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
+#define FEC0_MII_BUS_SHARE_TRUE 1
+
/* Interrupt events/masks. */
#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
@@ -378,6 +382,8 @@ struct bufdesc_ex {
#define FEC_NAPI_IMASK (FEC_ENET_MII | FEC_ENET_TS_TIMER)
#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
+#define FEC_ENET_ETHEREN ((uint)0x00000002)
+
/* ENET interrupt coalescing macro define */
#define FEC_ITR_CLK_SEL (0x1 << 30)
#define FEC_ITR_EN (0x1 << 31)
@@ -446,6 +452,15 @@ struct bufdesc_ex {
#define FEC_QUIRK_HAS_COALESCE (1 << 13)
/* Interrupt doesn't wake CPU from deep idle */
#define FEC_QUIRK_ERR006687 (1 << 14)
+/*
+ * i.MX6Q/DL ENET cannot wake up system in wait mode because ENET tx & rx
+ * interrupt signal don't connect to GPC. So use pm qos to avoid cpu enter
+ * to wait mode.
+ */
+#define FEC_QUIRK_BUG_WAITMODE (1 << 15)
+
+/* PHY fixup flag define */
+#define FEC_QUIRK_AR8031_FIXUP (1 << 0)
struct bufdesc_prop {
int qid;
@@ -460,6 +475,12 @@ struct bufdesc_prop {
unsigned char dsize_log2;
};
+struct fec_enet_stop_mode {
+ struct regmap *gpr;
+ u8 req_gpr;
+ u8 req_bit;
+};
+
struct fec_enet_priv_tx_q {
struct bufdesc_prop bd;
unsigned char *tx_bounce[TX_RING_SIZE];
@@ -522,10 +543,13 @@ struct fec_enet_private {
/* Phylib and MDIO interface */
struct mii_bus *mii_bus;
int mii_timeout;
+ int mii_bus_share;
+ bool active_in_suspend;
uint phy_speed;
phy_interface_t phy_interface;
struct device_node *phy_node;
int link;
+ bool fixed_link;
int full_duplex;
int speed;
struct completion mdio_done;
@@ -533,7 +557,9 @@ struct fec_enet_private {
bool bufdesc_ex;
int pause_flag;
int wol_flag;
+ int wake_irq;
u32 quirks;
+ u32 fixups;
struct napi_struct napi;
int csum_flags;
@@ -553,6 +579,7 @@ struct fec_enet_private {
int hwts_tx_en;
struct delayed_work time_keep;
struct regulator *reg_phy;
+ struct pm_qos_request pm_qos_req;
unsigned int tx_align;
unsigned int rx_align;
@@ -576,6 +603,8 @@ struct fec_enet_private {
unsigned int next_counter;
u64 ethtool_stats[0];
+
+ struct fec_enet_stop_mode gpr;
};
void fec_ptp_init(struct platform_device *pdev);
@@ -584,6 +613,8 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev);
int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
uint fec_ptp_check_pps_event(struct fec_enet_private *fep);
+void fec_enet_register_fixup(struct net_device *ndev);
+int of_fec_enet_parse_fixup(struct device_node *np);
/****************************************************************************/
#endif /* FEC_H */
diff --git a/drivers/net/ethernet/freescale/fec_fixup.c b/drivers/net/ethernet/freescale/fec_fixup.c
new file mode 100644
index 000000000000..5a8497c22acd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fec_fixup.c
@@ -0,0 +1,74 @@
+/*
+ * 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
+ * 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/netdevice.h>
+#include <linux/phy.h>
+#include "fec.h"
+
+#define PHY_ID_AR8031 0x004dd074
+
+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);
+
+ /* Introduce tx clock delay */
+ phy_write(dev, 0x1d, 0x5);
+ phy_write(dev, 0x1e, 0x100);
+
+ return 0;
+}
+
+void fec_enet_register_fixup(struct net_device *ndev)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ static int registered = 0;
+ int err;
+
+ if (!IS_BUILTIN(CONFIG_PHYLIB))
+ return;
+
+ if (fep->fixups & FEC_QUIRK_AR8031_FIXUP) {
+ static int ar8031_registered = 0;
+
+ if (ar8031_registered)
+ return;
+ err = phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffef,
+ ar8031_phy_fixup);
+ if (err)
+ netdev_info(ndev, "Cannot register PHY board fixup\n");
+ registered = 1;
+ }
+}
+
+int of_fec_enet_parse_fixup(struct device_node *np)
+{
+ int fixups = 0;
+
+ if (of_get_property(np, "fsl,ar8031-phy-fixup", NULL))
+ fixups |= FEC_QUIRK_AR8031_FIXUP;
+
+ return fixups;
+}
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 917091871259..4b99571e88db 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -18,13 +18,14 @@
* Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
* Copyright (c) 2004-2006 Macq Electronique SA.
*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
+ *
+ * Copyright 2017 NXP
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/pm_runtime.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
@@ -47,6 +48,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/clk.h>
+#include <linux/clk/clk-conf.h>
#include <linux/platform_device.h>
#include <linux/mdio.h>
#include <linux/phy.h>
@@ -59,10 +61,14 @@
#include <linux/regulator/consumer.h>
#include <linux/if_vlan.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/busfreq-imx.h>
#include <linux/prefetch.h>
-#include <soc/imx/cpuidle.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
#include <asm/cacheflush.h>
+#include <soc/imx/cpuidle.h>
#include "fec.h"
@@ -72,6 +78,7 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
#define DRIVER_NAME "fec"
#define FEC_ENET_GET_QUQUE(_x) ((_x == 0) ? 1 : ((_x == 1) ? 2 : 0))
+static const u16 fec_enet_vlan_pri_to_queue[8] = {1, 1, 1, 1, 2, 2, 2, 2};
/* Pause frame feild and FIFO threshold */
#define FEC_ENET_FCE (1 << 5)
@@ -102,7 +109,7 @@ static struct platform_device_id fec_devtype[] = {
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
- FEC_QUIRK_HAS_RACC,
+ FEC_QUIRK_HAS_RACC | FEC_QUIRK_BUG_WAITMODE,
}, {
.name = "mvf600-fec",
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
@@ -120,6 +127,13 @@ static struct platform_device_id fec_devtype[] = {
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_BUG_CAPTURE |
FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
}, {
+ .name = "imx8qm-fec",
+ .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
+ FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
+ FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
+ }, {
/* sentinel */
}
};
@@ -133,6 +147,7 @@ enum imx_fec_type {
MVF600_FEC,
IMX6SX_FEC,
IMX6UL_FEC,
+ IMX8QM_FEC,
};
static const struct of_device_id fec_dt_ids[] = {
@@ -143,6 +158,7 @@ static const struct of_device_id fec_dt_ids[] = {
{ .compatible = "fsl,mvf600-fec", .data = &fec_devtype[MVF600_FEC], },
{ .compatible = "fsl,imx6sx-fec", .data = &fec_devtype[IMX6SX_FEC], },
{ .compatible = "fsl,imx6ul-fec", .data = &fec_devtype[IMX6UL_FEC], },
+ { .compatible = "fsl,imx8qm-fec", .data = &fec_devtype[IMX8QM_FEC], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fec_dt_ids);
@@ -191,7 +207,8 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
* account when setting it.
*/
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
+ defined(CONFIG_ARM64)
#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
#else
#define OPT_FRAME_SIZE 0
@@ -237,14 +254,14 @@ static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
struct bufdesc_prop *bd)
{
return (bdp >= bd->last) ? bd->base
- : (struct bufdesc *)(((unsigned)bdp) + bd->dsize);
+ : (struct bufdesc *)(((void *)bdp) + bd->dsize);
}
static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
struct bufdesc_prop *bd)
{
return (bdp <= bd->base) ? bd->last
- : (struct bufdesc *)(((unsigned)bdp) - bd->dsize);
+ : (struct bufdesc *)(((void *)bdp) - bd->dsize);
}
static int fec_enet_get_bd_index(struct bufdesc *bdp,
@@ -904,7 +921,7 @@ fec_restart(struct net_device *ndev)
u32 val;
u32 temp_mac[2];
u32 rcntl = OPT_FRAME_SIZE | 0x04;
- u32 ecntl = 0x2; /* ETHEREN */
+ u32 ecntl = FEC_ENET_ETHEREN; /* ETHEREN */
/* Whack a reset. We should wait for this.
* For i.MX6SX SOC, enet use AXI bus, we use disable MAC
@@ -963,6 +980,7 @@ fec_restart(struct net_device *ndev)
writel(val, fep->hwp + FEC_RACC);
writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL);
}
+ writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL);
#endif
/*
@@ -1081,11 +1099,37 @@ fec_restart(struct net_device *ndev)
}
+static int fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled)
+{
+ struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
+
+ if (fep->gpr.gpr) {
+ if (enabled)
+ regmap_update_bits(fep->gpr.gpr, fep->gpr.req_gpr,
+ 1 << fep->gpr.req_bit,
+ 1 << fep->gpr.req_bit);
+ else
+ regmap_update_bits(fep->gpr.gpr, fep->gpr.req_gpr,
+ 1 << fep->gpr.req_bit,
+ 0);
+ } else if (pdata && pdata->sleep_mode_enable) {
+ pdata->sleep_mode_enable(enabled);
+ }
+
+ return 0;
+}
+
+static inline void fec_irqs_disable(struct net_device *ndev)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+
+ writel(0, fep->hwp + FEC_IMASK);
+}
+
static void
fec_stop(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
- struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
u32 val;
@@ -1108,15 +1152,14 @@ fec_stop(struct net_device *ndev)
writel(1, fep->hwp + FEC_ECNTRL);
udelay(10);
}
- writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+ writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
} else {
- writel(FEC_DEFAULT_IMASK | FEC_ENET_WAKEUP, fep->hwp + FEC_IMASK);
+ writel(FEC_ENET_MII | FEC_ENET_WAKEUP, fep->hwp + FEC_IMASK);
val = readl(fep->hwp + FEC_ECNTRL);
val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
writel(val, fep->hwp + FEC_ECNTRL);
- if (pdata && pdata->sleep_mode_enable)
- pdata->sleep_mode_enable(true);
+ fec_enet_stop_mode(fep, true);
}
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
@@ -1846,13 +1889,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
int ret;
if (enable) {
- ret = clk_prepare_enable(fep->clk_ahb);
- if (ret)
- return ret;
if (fep->clk_enet_out) {
ret = clk_prepare_enable(fep->clk_enet_out);
if (ret)
- goto failed_clk_enet_out;
+ return ret;
}
if (fep->clk_ptp) {
mutex_lock(&fep->ptp_clk_mutex);
@@ -1871,7 +1911,6 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
goto failed_clk_ref;
}
} else {
- clk_disable_unprepare(fep->clk_ahb);
if (fep->clk_enet_out)
clk_disable_unprepare(fep->clk_enet_out);
if (fep->clk_ptp) {
@@ -1892,12 +1931,29 @@ failed_clk_ref:
failed_clk_ptp:
if (fep->clk_enet_out)
clk_disable_unprepare(fep->clk_enet_out);
-failed_clk_enet_out:
- clk_disable_unprepare(fep->clk_ahb);
return ret;
}
+static int fec_restore_mii_bus(struct net_device *ndev)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ int ret;
+
+ ret = pm_runtime_get_sync(&fep->pdev->dev);
+ if (ret < 0)
+ return ret;
+
+ writel(0xffc00000, fep->hwp + FEC_IEVENT);
+ writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+ writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
+ writel(FEC_ENET_ETHEREN, fep->hwp + FEC_ECNTRL);
+
+ pm_runtime_mark_last_busy(&fep->pdev->dev);
+ pm_runtime_put_autosuspend(&fep->pdev->dev);
+ return 0;
+}
+
static int fec_enet_mii_probe(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1965,6 +2021,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
static int fec_enet_mii_init(struct platform_device *pdev)
{
static struct mii_bus *fec0_mii_bus;
+ static int *fec_mii_bus_share;
struct net_device *ndev = platform_get_drvdata(pdev);
struct fec_enet_private *fep = netdev_priv(ndev);
struct device_node *node;
@@ -1991,6 +2048,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
/* fec1 uses fec0 mii_bus */
if (mii_cnt && fec0_mii_bus) {
fep->mii_bus = fec0_mii_bus;
+ *fec_mii_bus_share = FEC0_MII_BUS_SHARE_TRUE;
mii_cnt++;
return 0;
}
@@ -2054,6 +2112,8 @@ static int fec_enet_mii_init(struct platform_device *pdev)
if (node) {
err = of_mdiobus_register(fep->mii_bus, node);
of_node_put(node);
+ } else if (fep->phy_node && !fep->fixed_link) {
+ err = -EPROBE_DEFER;
} else {
err = mdiobus_register(fep->mii_bus);
}
@@ -2064,8 +2124,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
mii_cnt++;
/* save fec0 mii_bus */
- if (fep->quirks & FEC_QUIRK_SINGLE_MDIO)
+ if (fep->quirks & FEC_QUIRK_SINGLE_MDIO) {
fec0_mii_bus = fep->mii_bus;
+ fec_mii_bus_share = &fep->mii_bus_share;
+ }
return 0;
@@ -2109,7 +2171,8 @@ static int fec_enet_get_regs_len(struct net_device *ndev)
/* List of registers that can be safety be read to dump them with ethtool */
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
+ defined(CONFIG_ARM64)
static u32 fec_enet_register_offset[] = {
FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0,
FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL,
@@ -2565,15 +2628,10 @@ fec_enet_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
return -EINVAL;
device_set_wakeup_enable(&ndev->dev, wol->wolopts & WAKE_MAGIC);
- if (device_may_wakeup(&ndev->dev)) {
+ if (device_may_wakeup(&ndev->dev))
fep->wol_flag |= FEC_WOL_FLAG_ENABLE;
- if (fep->irq[0] > 0)
- enable_irq_wake(fep->irq[0]);
- } else {
+ else
fep->wol_flag &= (~FEC_WOL_FLAG_ENABLE);
- if (fep->irq[0] > 0)
- disable_irq_wake(fep->irq[0]);
- }
return 0;
}
@@ -2672,7 +2730,7 @@ static void fec_enet_free_queue(struct net_device *ndev)
for (i = 0; i < fep->num_tx_queues; i++)
if (fep->tx_queue[i] && fep->tx_queue[i]->tso_hdrs) {
txq = fep->tx_queue[i];
- dma_free_coherent(NULL,
+ dma_free_coherent(&fep->pdev->dev,
txq->bd.ring_size * TSO_HEADER_SIZE,
txq->tso_hdrs,
txq->tso_hdrs_dma);
@@ -2706,7 +2764,7 @@ static int fec_enet_alloc_queue(struct net_device *ndev)
txq->tx_wake_threshold =
(txq->bd.ring_size - txq->tx_stop_threshold) / 2;
- txq->tso_hdrs = dma_alloc_coherent(NULL,
+ txq->tso_hdrs = dma_alloc_coherent(&fep->pdev->dev,
txq->bd.ring_size * TSO_HEADER_SIZE,
&txq->tso_hdrs_dma,
GFP_KERNEL);
@@ -2828,10 +2886,29 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
return 0;
}
+static inline bool fec_enet_irq_workaround(struct fec_enet_private *fep)
+{
+ struct device_node *np = fep->pdev->dev.of_node;
+ struct device_node *intr_node;
+
+ intr_node = of_parse_phandle(np, "interrupts-extended", 0);
+ if (intr_node && !strcmp(intr_node->name, "gpio")) {
+ /*
+ * If the interrupt controller is a GPIO node, it must have
+ * applied the workaround for WAIT mode bug.
+ */
+ return true;
+ }
+
+ return false;
+}
+
static int
fec_enet_open(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(fep->pdev);
int ret;
ret = pm_runtime_get_sync(&fep->pdev->dev);
@@ -2866,6 +2943,16 @@ fec_enet_open(struct net_device *ndev)
phy_start(ndev->phydev);
netif_tx_start_all_queues(ndev);
+ if ((id_entry->driver_data & FEC_QUIRK_BUG_WAITMODE) &&
+ !fec_enet_irq_workaround(fep))
+ pm_qos_add_request(&fep->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ 0);
+ else
+ pm_qos_add_request(&fep->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
+
device_set_wakeup_enable(&ndev->dev, fep->wol_flag &
FEC_WOL_FLAG_ENABLE);
@@ -2878,7 +2965,8 @@ err_enet_alloc:
clk_enable:
pm_runtime_mark_last_busy(&fep->pdev->dev);
pm_runtime_put_autosuspend(&fep->pdev->dev);
- pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+ if (!fep->mii_bus_share)
+ pinctrl_pm_select_sleep_state(&fep->pdev->dev);
return ret;
}
@@ -2896,6 +2984,7 @@ fec_enet_close(struct net_device *ndev)
}
phy_disconnect(ndev->phydev);
+ ndev->phydev = NULL;
if (fep->quirks & FEC_QUIRK_ERR006687)
imx6q_cpuidle_fec_irqs_unused();
@@ -2903,7 +2992,9 @@ fec_enet_close(struct net_device *ndev)
fec_enet_update_ethtool_stats(ndev);
fec_enet_clk_enable(ndev, false);
- pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+ pm_qos_remove_request(&fep->pm_qos_req);
+ if (!fep->mii_bus_share)
+ pinctrl_pm_select_sleep_state(&fep->pdev->dev);
pm_runtime_mark_last_busy(&fep->pdev->dev);
pm_runtime_put_autosuspend(&fep->pdev->dev);
@@ -3073,10 +3164,42 @@ static int fec_set_features(struct net_device *netdev,
return 0;
}
+u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb)
+{
+ struct vlan_ethhdr *vhdr;
+ unsigned short vlan_TCI = 0;
+
+ if (skb->protocol == ntohs(ETH_P_ALL)) {
+ vhdr = (struct vlan_ethhdr *)(skb->data);
+ vlan_TCI = ntohs(vhdr->h_vlan_TCI);
+ }
+
+ return vlan_TCI;
+}
+
+u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(fep->pdev);
+ u16 vlan_tag;
+
+ if (!(id_entry->driver_data & FEC_QUIRK_HAS_AVB))
+ return skb_tx_hash(ndev, skb);
+
+ vlan_tag = fec_enet_get_raw_vlan_tci(skb);
+ if (!vlan_tag)
+ return vlan_tag;
+
+ return fec_enet_vlan_pri_to_queue[vlan_tag >> 13];
+}
+
static const struct net_device_ops fec_netdev_ops = {
.ndo_open = fec_enet_open,
.ndo_stop = fec_enet_close,
.ndo_start_xmit = fec_enet_start_xmit,
+ .ndo_select_queue = fec_enet_select_queue,
.ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
@@ -3113,7 +3236,7 @@ static int fec_enet_init(struct net_device *ndev)
unsigned dsize_log2 = __fls(dsize);
WARN_ON(dsize != (1 << dsize_log2));
-#if defined(CONFIG_ARM)
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
fep->rx_align = 0xf;
fep->tx_align = 0xf;
#else
@@ -3209,7 +3332,7 @@ static int fec_enet_init(struct net_device *ndev)
}
#ifdef CONFIG_OF
-static void fec_reset_phy(struct platform_device *pdev)
+static int fec_reset_phy(struct platform_device *pdev)
{
int err, phy_reset;
bool active_high = false;
@@ -3217,16 +3340,18 @@ static void fec_reset_phy(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
if (!np)
- return;
+ return 0;
- of_property_read_u32(np, "phy-reset-duration", &msec);
+ err = of_property_read_u32(np, "phy-reset-duration", &msec);
/* A sane reset duration should not be longer than 1s */
- if (msec > 1000)
+ if (!err && msec > 1000)
msec = 1;
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
- if (!gpio_is_valid(phy_reset))
- return;
+ if (phy_reset == -EPROBE_DEFER)
+ return phy_reset;
+ else if (!gpio_is_valid(phy_reset))
+ return 0;
active_high = of_property_read_bool(np, "phy-reset-active-high");
@@ -3235,7 +3360,7 @@ static void fec_reset_phy(struct platform_device *pdev)
"phy-reset");
if (err) {
dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
- return;
+ return err;
}
if (msec > 20)
@@ -3244,14 +3369,17 @@ static void fec_reset_phy(struct platform_device *pdev)
usleep_range(msec * 1000, msec * 1000 + 1000);
gpio_set_value_cansleep(phy_reset, !active_high);
+
+ return 0;
}
#else /* CONFIG_OF */
-static void fec_reset_phy(struct platform_device *pdev)
+static int fec_reset_phy(struct platform_device *pdev)
{
/*
* In case of platform probe, the reset has been done
* by machine code.
*/
+ return 0;
}
#endif /* CONFIG_OF */
@@ -3286,6 +3414,41 @@ fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx)
}
+static void fec_enet_of_parse_stop_mode(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct device_node *np = pdev->dev.of_node;
+ struct fec_enet_private *fep = netdev_priv(dev);
+ struct device_node *node;
+ phandle phandle;
+ u32 out_val[3];
+ int ret;
+
+ ret = of_property_read_u32_array(np, "stop-mode", out_val, 3);
+ if (ret) {
+ dev_dbg(&pdev->dev, "no stop-mode property\n");
+ return;
+ }
+
+ phandle = *out_val;
+ node = of_find_node_by_phandle(phandle);
+ if (!node) {
+ dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
+ return;
+ }
+
+ fep->gpr.gpr = syscon_node_to_regmap(node);
+ if (IS_ERR(fep->gpr.gpr)) {
+ dev_dbg(&pdev->dev, "could not find gpr regmap\n");
+ return;
+ }
+
+ of_node_put(node);
+
+ fep->gpr.req_gpr = out_val[1];
+ fep->gpr.req_bit = out_val[2];
+}
+
static int
fec_probe(struct platform_device *pdev)
{
@@ -3300,6 +3463,8 @@ fec_probe(struct platform_device *pdev)
int num_tx_qs;
int num_rx_qs;
+ of_dma_configure(&pdev->dev, np);
+
fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
/* Init network device */
@@ -3348,6 +3513,8 @@ fec_probe(struct platform_device *pdev)
!of_property_read_bool(np, "fsl,err006687-workaround-present"))
fep->quirks |= FEC_QUIRK_ERR006687;
+ fec_enet_of_parse_stop_mode(pdev);
+
if (of_get_property(np, "fsl,magic-packet", NULL))
fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
@@ -3360,6 +3527,7 @@ fec_probe(struct platform_device *pdev)
goto failed_phy;
}
phy_node = of_node_get(np);
+ fep->fixed_link = true;
}
fep->phy_node = phy_node;
@@ -3374,6 +3542,10 @@ fec_probe(struct platform_device *pdev)
fep->phy_interface = ret;
}
+#if !defined(CONFIG_ARM64)
+ request_bus_freq(BUS_FREQ_HIGH);
+#endif
+
fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(fep->clk_ipg)) {
ret = PTR_ERR(fep->clk_ipg);
@@ -3415,6 +3587,9 @@ fec_probe(struct platform_device *pdev)
ret = clk_prepare_enable(fep->clk_ipg);
if (ret)
goto failed_clk_ipg;
+ ret = clk_prepare_enable(fep->clk_ahb);
+ if (ret)
+ goto failed_clk_ahb;
fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
if (!IS_ERR(fep->reg_phy)) {
@@ -3422,6 +3597,7 @@ fec_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev,
"Failed to enable phy regulator: %d\n", ret);
+ clk_disable_unprepare(fep->clk_ipg);
goto failed_regulator;
}
} else {
@@ -3434,7 +3610,9 @@ fec_probe(struct platform_device *pdev)
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
- fec_reset_phy(pdev);
+ ret = fec_reset_phy(pdev);
+ if (ret)
+ goto failed_reset;
if (fep->bufdesc_ex)
fec_ptp_init(pdev);
@@ -3459,10 +3637,22 @@ fec_probe(struct platform_device *pdev)
fep->irq[i] = irq;
}
+ ret = of_property_read_u32(np, "fsl,wakeup_irq", &irq);
+ if (!ret && irq < FEC_IRQ_NUM)
+ fep->wake_irq = fep->irq[irq];
+ else
+ fep->wake_irq = fep->irq[0];
+
init_completion(&fep->mdio_done);
+
+ /* board only enable one mii bus in default */
+ if (!of_get_property(np, "fsl,mii-exclusive", NULL))
+ fep->quirks |= FEC_QUIRK_SINGLE_MDIO;
ret = fec_enet_mii_init(pdev);
- if (ret)
+ if (ret) {
+ dev_id = 0;
goto failed_mii_init;
+ }
/* Carrier starts down, phylib will bring it up */
netif_carrier_off(ndev);
@@ -3473,6 +3663,11 @@ fec_probe(struct platform_device *pdev)
if (ret)
goto failed_register;
+ if (!fep->fixed_link) {
+ fep->fixups = of_fec_enet_parse_fixup(np);
+ fec_enet_register_fixup(ndev);
+ }
+
device_init_wakeup(&ndev->dev, fep->wol_flag &
FEC_WOL_HAS_MAGIC_PACKET);
@@ -3495,7 +3690,11 @@ failed_init:
fec_ptp_stop(pdev);
if (fep->reg_phy)
regulator_disable(fep->reg_phy);
+failed_reset:
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
failed_regulator:
+failed_clk_ahb:
clk_disable_unprepare(fep->clk_ipg);
failed_clk_ipg:
fec_enet_clk_enable(ndev, false);
@@ -3535,6 +3734,7 @@ static int __maybe_unused fec_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep = netdev_priv(ndev);
+ int ret = 0;
rtnl_lock();
if (netif_running(ndev)) {
@@ -3546,9 +3746,21 @@ static int __maybe_unused fec_suspend(struct device *dev)
netif_device_detach(ndev);
netif_tx_unlock_bh(ndev);
fec_stop(ndev);
- fec_enet_clk_enable(ndev, false);
- if (!(fep->wol_flag & FEC_WOL_FLAG_ENABLE))
+ if (!(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) {
+ fec_irqs_disable(ndev);
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+ } else {
+ disable_irq(fep->wake_irq);
+ enable_irq_wake(fep->wake_irq);
+ }
+ fec_enet_clk_enable(ndev, false);
+ fep->active_in_suspend = !pm_runtime_status_suspended(dev);
+ if (fep->active_in_suspend)
+ ret = pm_runtime_force_suspend(dev);
+ if (ret < 0)
+ return ret;
+ } else if (fep->mii_bus_share && !ndev->phydev) {
+ pinctrl_pm_select_sleep_state(&fep->pdev->dev);
}
rtnl_unlock();
@@ -3568,8 +3780,7 @@ static int __maybe_unused fec_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep = netdev_priv(ndev);
- struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
- int ret;
+ int ret = 0;
int val;
if (fep->reg_phy && !(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) {
@@ -3580,14 +3791,18 @@ static int __maybe_unused fec_resume(struct device *dev)
rtnl_lock();
if (netif_running(ndev)) {
+ if (fep->active_in_suspend)
+ pm_runtime_force_resume(dev);
ret = fec_enet_clk_enable(ndev, true);
if (ret) {
rtnl_unlock();
goto failed_clk;
}
+
if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) {
- if (pdata && pdata->sleep_mode_enable)
- pdata->sleep_mode_enable(false);
+ disable_irq_wake(fep->wake_irq);
+ fec_enet_stop_mode(fep, false);
+ enable_irq(fep->wake_irq);
val = readl(fep->hwp + FEC_ECNTRL);
val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
writel(val, fep->hwp + FEC_ECNTRL);
@@ -3601,10 +3816,14 @@ static int __maybe_unused fec_resume(struct device *dev)
netif_tx_unlock_bh(ndev);
napi_enable(&fep->napi);
phy_start(ndev->phydev);
+ } else if (fep->mii_bus_share && !ndev->phydev) {
+ pinctrl_pm_select_default_state(&fep->pdev->dev);
+ /* And then recovery mii bus */
+ ret = fec_restore_mii_bus(ndev);
}
rtnl_unlock();
- return 0;
+ return ret;
failed_clk:
if (fep->reg_phy)
@@ -3617,7 +3836,11 @@ static int __maybe_unused fec_runtime_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep = netdev_priv(ndev);
+ clk_disable_unprepare(fep->clk_ahb);
clk_disable_unprepare(fep->clk_ipg);
+#if !defined(CONFIG_ARM64)
+ release_bus_freq(BUS_FREQ_HIGH);
+#endif
return 0;
}
@@ -3626,8 +3849,23 @@ static int __maybe_unused fec_runtime_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep = netdev_priv(ndev);
+ int ret;
+
+#if !defined(CONFIG_ARM64)
+ request_bus_freq(BUS_FREQ_HIGH);
+#endif
+ ret = clk_prepare_enable(fep->clk_ahb);
+ if (ret)
+ return ret;
+ ret = clk_prepare_enable(fep->clk_ipg);
+ if (ret)
+ goto failed_clk_ipg;
- return clk_prepare_enable(fep->clk_ipg);
+ return 0;
+
+failed_clk_ipg:
+ clk_disable_unprepare(fep->clk_ahb);
+ return ret;
}
static const struct dev_pm_ops fec_pm_ops = {
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 2032a6de026b..52c24ac5d751 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -788,6 +788,22 @@ static int kszphy_probe(struct phy_device *phydev)
return 0;
}
+static int ksz8081_resume(struct phy_device *phydev)
+{
+ int value;
+
+ mutex_lock(&phydev->lock);
+ value = phy_read(phydev, MII_BMCR);
+ phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN);
+
+ value = phy_scan_fixups(phydev);
+ if (value < 0)
+ return value;
+ mutex_unlock(&phydev->lock);
+
+ return 0;
+}
+
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
@@ -936,7 +952,7 @@ static struct phy_driver ksphy_driver[] = {
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
.suspend = kszphy_suspend,
- .resume = kszphy_resume,
+ .resume = ksz8081_resume,
}, {
.phy_id = PHY_ID_KSZ8061,
.name = "Micrel KSZ8061",
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index bf02f8e4648a..f0e3e3fa9dc3 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -89,13 +89,23 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
if (!drv || !phydrv->suspend)
return false;
- /* PHY not attached? May suspend if the PHY has not already been
- * suspended as part of a prior call to phy_disconnect() ->
- * phy_detach() -> phy_suspend() because the parent netdev might be the
- * MDIO bus driver and clock gated at this point.
+ /*
+ * netdev is NULL has three cases:
+ * - phy is not found
+ * - phy is found, match to general phy driver
+ * - phy is found, match to specifical phy driver
+ *
+ * Case 1: phy is not found, cannot communicate by MDIO bus.
+ * Case 2: phy is found:
+ * if phy dev driver probe/bind err, netdev is not __open__ status,
+ * mdio bus is unregistered.
+ * if phy is detached, phy had entered suspended status.
+ * Case 3: phy is found, phy is detached, phy had entered suspended status.
+ *
+ * So, in here, it shouldn't set phy to suspend by calling mdio bus.
*/
if (!netdev)
- return !phydev->suspended;
+ return false;
/* Don't suspend PHY if the attached netdev parent may wakeup.
* The parent may point to a PCI device, as in tg3 driver.
@@ -252,7 +262,7 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
}
/* Runs any matching fixups for this phydev */
-static int phy_scan_fixups(struct phy_device *phydev)
+int phy_scan_fixups(struct phy_device *phydev)
{
struct phy_fixup *fixup;
@@ -272,6 +282,7 @@ static int phy_scan_fixups(struct phy_device *phydev)
return 0;
}
+EXPORT_SYMBOL(phy_scan_fixups);
static int phy_bus_match(struct device *dev, struct device_driver *drv)
{
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 8c8edaf1bba6..f0b4e543b3de 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -21,6 +21,7 @@ source "drivers/net/wireless/admtek/Kconfig"
source "drivers/net/wireless/ath/Kconfig"
source "drivers/net/wireless/atmel/Kconfig"
source "drivers/net/wireless/broadcom/Kconfig"
+source "drivers/net/wireless/bcmdhd/Kconfig"
source "drivers/net/wireless/cisco/Kconfig"
source "drivers/net/wireless/intel/Kconfig"
source "drivers/net/wireless/intersil/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index f00d42953fb8..50a9228fddff 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_WLAN_VENDOR_ADMTEK) += admtek/
obj-$(CONFIG_WLAN_VENDOR_ATH) += ath/
obj-$(CONFIG_WLAN_VENDOR_ATMEL) += atmel/
+obj-$(CONFIG_BCMDHD) += bcmdhd/
obj-$(CONFIG_WLAN_VENDOR_BROADCOM) += broadcom/
obj-$(CONFIG_WLAN_VENDOR_CISCO) += cisco/
obj-$(CONFIG_WLAN_VENDOR_INTEL) += intel/
diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig
new file mode 100644
index 000000000000..7234910ac951
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/Kconfig
@@ -0,0 +1,64 @@
+config BCMDHD
+ tristate "Broadcom FullMAC wireless cards support"
+ ---help---
+ This module adds support for wireless adapters based on
+ Broadcom FullMAC chipset.
+
+ If you choose to build a module, it'll be called dhd. Say M if
+ unsure.
+
+config BCMDHD_SDIO
+ tristate "SDIO bus interface support"
+ depends on BCMDHD && MMC
+
+config BCMDHD_PCIE
+ bool "PCIe bus interface support"
+ depends on BCMDHD && PCI && !BCMDHD_SDIO
+
+config BCM4339
+ tristate "BCM4339 support"
+ depends on BCMDHD
+
+config BCM43340
+ tristate "BCM43340 support"
+ depends on BCMDHD
+
+config BCM4354
+ tristate "BCM4354 support"
+ depends on BCMDHD
+
+config BCMDHD_FW_PATH
+ depends on BCMDHD
+ string "Firmware path"
+ default "/system/vendor/firmware/fw_bcmdhd.bin"
+ ---help---
+ Path to the firmware file.
+
+config BCMDHD_NVRAM_PATH
+ depends on BCMDHD
+ string "NVRAM path"
+ default "/system/etc/wifi/bcmdhd.cal"
+ ---help---
+ Path to the calibration file.
+
+config BCMDHD_WEXT
+ bool "Enable WEXT support"
+ depends on BCMDHD && CFG80211 = n
+ select WIRELESS_EXT
+ select WEXT_PRIV
+ help
+ Enables WEXT support
+
+config DHD_USE_STATIC_BUF
+ bool "Enable memory preallocation"
+ depends on BCMDHD
+ default n
+ ---help---
+ Use memory preallocated in platform
+
+config DHD_USE_SCHED_SCAN
+ bool "Use CFG80211 sched scan"
+ depends on BCMDHD && CFG80211
+ default n
+ ---help---
+ Use CFG80211 sched scan
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
new file mode 100644
index 000000000000..c9542d945948
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -0,0 +1,229 @@
+# bcmdhd
+#####################
+# SDIO Basic feature
+#####################
+
+DHDCFLAGS += -Wall -Wstrict-prototypes -Dlinux -DLINUX -DBCMDRIVER \
+ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \
+ -DDHDTHREAD -DSHOW_EVENTS -DBCMDBG -DWLP2P \
+ -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \
+ -DKEEP_ALIVE -DCSCAN -DPKT_FILTER_SUPPORT \
+ -DEMBEDDED_PLATFORM -DPNO_SUPPORT \
+ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT \
+ -DCUSTOMER_HW2 -DGET_CUSTOM_MAC_ENABLE
+
+#################
+# Common feature
+#################
+DHDCFLAGS += -DWL_CFG80211
+# Print out kernel panic point of file and line info when assertion happened
+DHDCFLAGS += -DBCMASSERT_LOG
+
+# keepalive
+DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000
+
+DHDCFLAGS += -DVSDB
+DHDCFLAGS += -DPROP_TXSTATUS
+
+# For p2p connection issue
+DHDCFLAGS += -DWL_SCB_TIMEOUT=10
+
+# TDLS enable
+DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE
+# For TDLS tear down inactive time 40 sec
+DHDCFLAGS += -DCUSTOM_TDLS_IDLE_MODE_SETTING=40000
+# for TDLS RSSI HIGH for establishing TDLS link
+DHDCFLAGS += -DCUSTOM_TDLS_RSSI_THRESHOLD_HIGH=-60
+# for TDLS RSSI HIGH for tearing down TDLS link
+DHDCFLAGS += -DCUSTOM_TDLS_RSSI_THRESHOLD_LOW=-70
+
+# Roaming
+DHDCFLAGS += -DROAM_AP_ENV_DETECTION
+DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API
+DHDCFLAGS += -DENABLE_FW_ROAM_SUSPEND
+# Roaming trigger
+DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-75
+DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=10
+# Set PM 2 always regardless suspend/resume
+DHDCFLAGS += -DSUPPORT_PM2_ONLY
+
+# For special PNO Event keep wake lock for 10sec
+DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10
+DHDCFLAGS += -DMIRACAST_AMPDU_SIZE=8
+
+# Early suspend
+DHDCFLAGS += -DDHD_USE_EARLYSUSPEND
+
+# For Scan result patch
+DHDCFLAGS += -DESCAN_RESULT_PATCH
+
+# For Static Buffer
+ifeq ($(CONFIG_BROADCOM_WIFI_RESERVED_MEM),y)
+ DHDCFLAGS += -DCONFIG_DHD_USE_STATIC_BUF
+ DHDCFLAGS += -DENHANCED_STATIC_BUF
+ DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT
+endif
+ifneq ($(CONFIG_DHD_USE_SCHED_SCAN),)
+DHDCFLAGS += -DWL_SCHED_SCAN
+endif
+
+# Ioctl timeout 5000ms
+DHDCFLAGS += -DIOCTL_RESP_TIMEOUT=5000
+
+# Prevent rx thread monopolize
+DHDCFLAGS += -DWAIT_DEQUEUE
+
+# Config PM Control
+DHDCFLAGS += -DCONFIG_CONTROL_PM
+
+# idle count
+DHDCFLAGS += -DDHD_USE_IDLECOUNT
+
+# Wi-Fi Direct
+DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+DHDCFLAGS += -DWL_CFG80211_STA_EVENT
+DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
+# DHDCFLAGS += -DWL_ENABLE_P2P_IF
+
+# For APSTA virtual interface
+DHDCFLAGS += -DWL_VIRTUAL_APSTA
+
+##########################
+# platform type
+# imx: NXP iMX platform
+##########################
+DHDPLATFORM ?= imx
+ifeq ($(DHDPLATFORM), imx)
+ DHDCFLAGS += -DCONFIG_DTS -DCUSTOMER_IMX
+else
+ # XXX Disable for NXP-iMX platforms
+ # SKB TAILPAD to avoid out of boundary memory access
+ DHDCFLAGS += -DDHDENABLE_TAILPAD
+endif
+
+##########################
+# driver type
+# m: module type driver
+# y: built-in type driver
+##########################
+#DRIVER_TYPE ?= y
+
+ifeq ($(CONFIG_BCMDHD_SDIO), y)
+ DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD
+else
+ DHDCFLAGS += -DNO_SDIO_RESET
+endif
+
+#########################
+# Chip dependent feature
+#########################
+ifneq ($(CONFIG_BCM4354),)
+ DHDCFLAGS += -DBCM4354_CHIP -DHW_OOB
+
+# tput enhancement
+ DHDTXGLOM ?= y
+ MAX_TXGLOM ?= 40
+ DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128
+ DHDCFLAGS += -DDHDTCPACK_SUPPRESS
+ DHDCFLAGS += -DUSE_WL_TXBF
+ DHDCFLAGS += -DUSE_WL_FRAMEBURST
+ DHDCFLAGS += -DRXFRAME_THREAD
+ DHDCFLAGS += -DREPEAT_READFRAME
+ DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64
+ DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0
+# DHDCFLAGS += -DPROP_TXSTATUS_VSDB
+ DHDCFLAGS += -DMAX_HDR_READ=128
+ DHDCFLAGS += -DDHD_FIRSTREAD=128
+ DHDCFLAGS += -DCUSTOM_AMPDU_MPDU=16
+
+# New Features
+ DHDCFLAGS += -DWL11U -DPMF
+ DHDCFLAGS += -DDHD_ENABLE_LPC
+ DHDCFLAGS += -DSAR_SUPPORT
+ DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30
+endif
+
+ifneq ($(CONFIG_BCM4339),)
+ DHDCFLAGS += -DBCM4339_CHIP -DHW_OOB
+
+ # tput enhancement
+ DHDTXGLOM ?= y
+ DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128
+ DHDCFLAGS += -DDHDTCPACK_SUPPRESS
+ DHDCFLAGS += -DUSE_WL_TXBF
+ DHDCFLAGS += -DUSE_WL_FRAMEBURST
+ DHDCFLAGS += -DRXFRAME_THREAD
+ DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64
+ DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0
+# DHDCFLAGS += -DPROP_TXSTATUS_VSDB
+
+ # New Features
+ DHDCFLAGS += -DWL11U
+ DHDCFLAGS += -DDHD_ENABLE_LPC
+ DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30
+endif
+
+##########################
+# SDIO TX glomming
+# y: enable
+# n: disable
+##########################
+DHDTXGLOM ?= n
+ifeq ($(DHDTXGLOM), y)
+ MAX_TXGLOM ?= 32
+ DHDCFLAGS += -DCUSTOM_GLOM_SETTING=8 -DCUSTOM_RXCHAIN=1
+ DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED
+ DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=$(MAX_TXGLOM)
+endif
+
+# Murata: need the following define to handle BCM43340 edge interrupt (vs level interrupt on other chipsets).
+# Define is in imx_v7_defconfig.
+ifeq ($(CONFIG_BCM43340),)
+ DHDCFLAGS += -DHW_OOB
+endif
+
+ifneq ($(CONFIG_BCMDHD_SDIO),)
+ DHDCFLAGS += -DBDC -DOOB_INTR_ONLY -DDHD_BCMEVENTS -DMMC_SDIO_ABORT -DOOB_PARAM
+ DHDCFLAGS += -DBCMSDIO -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR -DDHD_VERSION_NO_DATE_TIME
+endif
+
+ifneq ($(CONFIG_BCMDHD_PCIE),)
+ DHDCFLAGS += -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1
+endif
+
+#EXTRA_LDFLAGS += --strip-debug
+
+EXTRA_CFLAGS += $(DHDCFLAGS) -DDHD_DEBUG
+EXTRA_CFLAGS += -DSRCBASE=\"$(src)\"
+EXTRA_CFLAGS += -I$(src)/include/ -I$(src)/
+KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(shell pwd)
+
+DHDOFILES := dhd_pno.o dhd_common.o dhd_ip.o dhd_custom_gpio.o \
+ dhd_linux.o dhd_linux_sched.o dhd_cfg80211.o dhd_linux_wq.o aiutils.o bcmevent.o \
+ bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o sbutils.o siutils.o \
+ wl_android.o wl_cfg80211.o wl_cfgp2p.o wl_cfg_btcoex.o wldev_common.o wl_linux_mon.o \
+ dhd_linux_platdev.o dhd_pno.o dhd_linux_wq.o wl_cfg_btcoex.o wl_cfgvendor.o
+
+ifneq ($(CONFIG_BCMDHD_SDIO),)
+ DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o
+ DHDOFILES += dhd_cdc.o dhd_wlfc.o dhd_sdio.o
+endif
+
+ifneq ($(CONFIG_BCMDHD_PCIE),)
+ DHDOFILES += dhd_pcie.o dhd_pcie_linux.o dhd_msgbuf.o dhd_log.o circularbuf.o
+endif
+
+bcmdhd-objs := $(DHDOFILES)
+obj-$(CONFIG_BCMDHD_SDIO) += bcmdhd.o
+
+all:
+ @echo "$(MAKE) --no-print-directory -C $(KDIR) SUBDIRS=$(CURDIR) modules"
+ @$(MAKE) --no-print-directory -C $(KDIR) SUBDIRS=$(CURDIR) modules
+
+clean:
+ rm -rf *.o *.ko *.mod.c *~ .*.cmd *.o.cmd .*.o.cmd \
+ Module.symvers modules.order .tmp_versions modules.builtin
+
+install:
+ @$(MAKE) --no-print-directory -C $(KDIR) \
+ SUBDIRS=$(CURDIR) modules_install
diff --git a/drivers/net/wireless/bcmdhd/aiutils.c b/drivers/net/wireless/bcmdhd/aiutils.c
new file mode 100644
index 000000000000..85c034b56ba8
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/aiutils.c
@@ -0,0 +1,1012 @@
+/*
+ * Misc utility routines for accessing chip-specific features
+ * of the SiliconBackplane-based Broadcom chips.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: aiutils.c 530682 2015-01-30 18:48:21Z $
+ */
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <hndsoc.h>
+#include <sbchipc.h>
+#include <pcicfg.h>
+
+#include "siutils_priv.h"
+
+#define BCM47162_DMP() (0)
+#define BCM5357_DMP() (0)
+#define BCM4707_DMP() (0)
+#define remap_coreid(sih, coreid) (coreid)
+#define remap_corerev(sih, corerev) (corerev)
+
+/* EROM parsing */
+
+static uint32
+get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match)
+{
+ uint32 ent;
+ uint inv = 0, nom = 0;
+ uint32 size = 0;
+
+ while (TRUE) {
+ ent = R_REG(si_osh(sih), *eromptr);
+ (*eromptr)++;
+
+ if (mask == 0)
+ break;
+
+ if ((ent & ER_VALID) == 0) {
+ inv++;
+ continue;
+ }
+
+ if (ent == (ER_END | ER_VALID))
+ break;
+
+ if ((ent & mask) == match)
+ break;
+
+ /* escape condition related EROM size if it has invalid values */
+ size += sizeof(*eromptr);
+ if (size >= ER_SZ_MAX) {
+ SI_ERROR(("Failed to find end of EROM marker\n"));
+ break;
+ }
+
+ nom++;
+ }
+
+ SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent));
+ if (inv + nom) {
+ SI_VMSG((" after %d invalid and %d non-matching entries\n", inv, nom));
+ }
+ return ent;
+}
+
+static uint32
+get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh,
+ uint32 *sizel, uint32 *sizeh)
+{
+ uint32 asd, sz, szd;
+
+ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID);
+ if (((asd & ER_TAG1) != ER_ADD) ||
+ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
+ ((asd & AD_ST_MASK) != st)) {
+ /* This is not what we want, "push" it back */
+ (*eromptr)--;
+ return 0;
+ }
+ *addrl = asd & AD_ADDR_MASK;
+ if (asd & AD_AG32)
+ *addrh = get_erom_ent(sih, eromptr, 0, 0);
+ else
+ *addrh = 0;
+ *sizeh = 0;
+ sz = asd & AD_SZ_MASK;
+ if (sz == AD_SZ_SZD) {
+ szd = get_erom_ent(sih, eromptr, 0, 0);
+ *sizel = szd & SD_SZ_MASK;
+ if (szd & SD_SG32)
+ *sizeh = get_erom_ent(sih, eromptr, 0, 0);
+ } else
+ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
+
+ SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
+ sp, ad, st, *sizeh, *sizel, *addrh, *addrl));
+
+ return asd;
+}
+
+static void
+ai_hwfixup(si_info_t *sii)
+{
+}
+
+
+/* parse the enumeration rom to identify all cores */
+void
+ai_scan(si_t *sih, void *regs, uint devid)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ chipcregs_t *cc = (chipcregs_t *)regs;
+ uint32 erombase, *eromptr, *eromlim;
+
+ erombase = R_REG(sii->osh, &cc->eromptr);
+
+ switch (BUSTYPE(sih->bustype)) {
+ case SI_BUS:
+ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE);
+ break;
+
+ case PCI_BUS:
+ /* Set wrappers address */
+ sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE);
+
+ /* Now point the window at the erom */
+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase);
+ eromptr = regs;
+ break;
+
+ case SPI_BUS:
+ case SDIO_BUS:
+ eromptr = (uint32 *)(uintptr)erombase;
+ break;
+
+ case PCMCIA_BUS:
+ default:
+ SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype));
+ ASSERT(0);
+ return;
+ }
+ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
+
+ SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n",
+ regs, erombase, eromptr, eromlim));
+ while (eromptr < eromlim) {
+ uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp;
+ uint32 mpd, asd, addrl, addrh, sizel, sizeh;
+ uint i, j, idx;
+ bool br;
+
+ br = FALSE;
+
+ /* Grok a component */
+ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
+ if (cia == (ER_END | ER_VALID)) {
+ SI_VMSG(("Found END of erom after %d cores\n", sii->numcores));
+ ai_hwfixup(sii);
+ return;
+ }
+
+ cib = get_erom_ent(sih, &eromptr, 0, 0);
+
+ if ((cib & ER_TAG) != ER_CI) {
+ SI_ERROR(("CIA not followed by CIB\n"));
+ goto error;
+ }
+
+ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT;
+ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
+ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
+ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT;
+ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT;
+ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
+ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
+
+#ifdef BCMDBG_SI
+ SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, "
+ "nsw = %d, nmp = %d & nsp = %d\n",
+ mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp));
+#else
+ BCM_REFERENCE(crev);
+#endif
+
+ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
+ continue;
+ if ((nmw + nsw == 0)) {
+ /* A component which is not a core */
+ if (cid == OOB_ROUTER_CORE_ID) {
+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
+ &addrl, &addrh, &sizel, &sizeh);
+ if (asd != 0) {
+ sii->oob_router = addrl;
+ }
+ }
+ if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID)
+ continue;
+ }
+
+ idx = sii->numcores;
+
+ cores_info->cia[idx] = cia;
+ cores_info->cib[idx] = cib;
+ cores_info->coreid[idx] = remap_coreid(sih, cid);
+
+ for (i = 0; i < nmp; i++) {
+ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
+ if ((mpd & ER_TAG) != ER_MP) {
+ SI_ERROR(("Not enough MP entries for component 0x%x\n", cid));
+ goto error;
+ }
+ SI_VMSG((" Master port %d, mp: %d id: %d\n", i,
+ (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT,
+ (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT));
+ }
+
+ /* First Slave Address Descriptor should be port 0:
+ * the main register space for the core
+ */
+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
+ if (asd == 0) {
+ do {
+ /* Try again to see if it is a bridge */
+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
+ &sizel, &sizeh);
+ if (asd != 0)
+ br = TRUE;
+ else {
+ if (br == TRUE) {
+ break;
+ }
+ else if ((addrh != 0) || (sizeh != 0) ||
+ (sizel != SI_CORE_SIZE)) {
+ SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 ="
+ "0x%x\n", addrh, sizeh, sizel));
+ SI_ERROR(("First Slave ASD for"
+ "core 0x%04x malformed "
+ "(0x%08x)\n", cid, asd));
+ goto error;
+ }
+ }
+ } while (1);
+ }
+ cores_info->coresba[idx] = addrl;
+ cores_info->coresba_size[idx] = sizel;
+ /* Get any more ASDs in port 0 */
+ j = 1;
+ do {
+ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
+ &sizel, &sizeh);
+ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) {
+ cores_info->coresba2[idx] = addrl;
+ cores_info->coresba2_size[idx] = sizel;
+ }
+ j++;
+ } while (asd != 0);
+
+ /* Go through the ASDs for other slave ports */
+ for (i = 1; i < nsp; i++) {
+ j = 0;
+ do {
+ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh,
+ &sizel, &sizeh);
+
+ if (asd == 0)
+ break;
+ j++;
+ } while (1);
+ if (j == 0) {
+ SI_ERROR((" SP %d has no address descriptors\n", i));
+ goto error;
+ }
+ }
+
+ /* Now get master wrappers */
+ for (i = 0; i < nmw; i++) {
+ asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh,
+ &sizel, &sizeh);
+ if (asd == 0) {
+ SI_ERROR(("Missing descriptor for MW %d\n", i));
+ goto error;
+ }
+ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
+ SI_ERROR(("Master wrapper %d is not 4KB\n", i));
+ goto error;
+ }
+ if (i == 0)
+ cores_info->wrapba[idx] = addrl;
+ }
+
+ /* And finally slave wrappers */
+ for (i = 0; i < nsw; i++) {
+ uint fwp = (nsp == 1) ? 0 : 1;
+ asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh,
+ &sizel, &sizeh);
+ if (asd == 0) {
+ SI_ERROR(("Missing descriptor for SW %d\n", i));
+ goto error;
+ }
+ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
+ SI_ERROR(("Slave wrapper %d is not 4KB\n", i));
+ goto error;
+ }
+ if ((nmw == 0) && (i == 0))
+ cores_info->wrapba[idx] = addrl;
+ }
+
+
+ /* Don't record bridges */
+ if (br)
+ continue;
+
+ /* Done with core */
+ sii->numcores++;
+ }
+
+ SI_ERROR(("Reached end of erom without finding END"));
+
+error:
+ sii->numcores = 0;
+ return;
+}
+
+/* This function changes the logical "focus" to the indicated core.
+ * Return the current core's virtual address.
+ */
+void *
+ai_setcoreidx(si_t *sih, uint coreidx)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint32 addr, wrap;
+ void *regs;
+
+ if (coreidx >= MIN(sii->numcores, SI_MAXCORES))
+ return (NULL);
+
+ addr = cores_info->coresba[coreidx];
+ wrap = cores_info->wrapba[coreidx];
+
+ /*
+ * If the user has provided an interrupt mask enabled function,
+ * then assert interrupts are disabled before switching the core.
+ */
+ ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
+
+ switch (BUSTYPE(sih->bustype)) {
+ case SI_BUS:
+ /* map new one */
+ if (!cores_info->regs[coreidx]) {
+ cores_info->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE);
+ ASSERT(GOODREGS(cores_info->regs[coreidx]));
+ }
+ sii->curmap = regs = cores_info->regs[coreidx];
+ if (!cores_info->wrappers[coreidx] && (wrap != 0)) {
+ cores_info->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
+ ASSERT(GOODREGS(cores_info->wrappers[coreidx]));
+ }
+ sii->curwrap = cores_info->wrappers[coreidx];
+ break;
+
+ case PCI_BUS:
+ /* point bar0 window */
+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, addr);
+ regs = sii->curmap;
+ /* point bar0 2nd 4KB window to the primary wrapper */
+ if (PCIE_GEN2(sii))
+ OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 4, wrap);
+ else
+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, wrap);
+ break;
+
+ case SPI_BUS:
+ case SDIO_BUS:
+ sii->curmap = regs = (void *)((uintptr)addr);
+ sii->curwrap = (void *)((uintptr)wrap);
+ break;
+
+ case PCMCIA_BUS:
+ default:
+ ASSERT(0);
+ regs = NULL;
+ break;
+ }
+
+ sii->curmap = regs;
+ sii->curidx = coreidx;
+
+ return regs;
+}
+
+
+void
+ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ chipcregs_t *cc = NULL;
+ uint32 erombase, *eromptr, *eromlim;
+ uint i, j, cidx;
+ uint32 cia, cib, nmp, nsp;
+ uint32 asd, addrl, addrh, sizel, sizeh;
+
+ for (i = 0; i < sii->numcores; i++) {
+ if (cores_info->coreid[i] == CC_CORE_ID) {
+ cc = (chipcregs_t *)cores_info->regs[i];
+ break;
+ }
+ }
+ if (cc == NULL)
+ goto error;
+
+ erombase = R_REG(sii->osh, &cc->eromptr);
+ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE);
+ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
+
+ cidx = sii->curidx;
+ cia = cores_info->cia[cidx];
+ cib = cores_info->cib[cidx];
+
+ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
+ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
+
+ /* scan for cores */
+ while (eromptr < eromlim) {
+ if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) &&
+ (get_erom_ent(sih, &eromptr, 0, 0) == cib)) {
+ break;
+ }
+ }
+
+ /* skip master ports */
+ for (i = 0; i < nmp; i++)
+ get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
+
+ /* Skip ASDs in port 0 */
+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
+ if (asd == 0) {
+ /* Try again to see if it is a bridge */
+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
+ &sizel, &sizeh);
+ }
+
+ j = 1;
+ do {
+ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
+ &sizel, &sizeh);
+ j++;
+ } while (asd != 0);
+
+ /* Go through the ASDs for other slave ports */
+ for (i = 1; i < nsp; i++) {
+ j = 0;
+ do {
+ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh,
+ &sizel, &sizeh);
+ if (asd == 0)
+ break;
+
+ if (!asidx--) {
+ *addr = addrl;
+ *size = sizel;
+ return;
+ }
+ j++;
+ } while (1);
+
+ if (j == 0) {
+ SI_ERROR((" SP %d has no address descriptors\n", i));
+ break;
+ }
+ }
+
+error:
+ *size = 0;
+ return;
+}
+
+/* Return the number of address spaces in current core */
+int
+ai_numaddrspaces(si_t *sih)
+{
+ return 2;
+}
+
+/* Return the address of the nth address space in the current core */
+uint32
+ai_addrspace(si_t *sih, uint asidx)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint cidx;
+
+ cidx = sii->curidx;
+
+ if (asidx == 0)
+ return cores_info->coresba[cidx];
+ else if (asidx == 1)
+ return cores_info->coresba2[cidx];
+ else {
+ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
+ __FUNCTION__, asidx));
+ return 0;
+ }
+}
+
+/* Return the size of the nth address space in the current core */
+uint32
+ai_addrspacesize(si_t *sih, uint asidx)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint cidx;
+
+ cidx = sii->curidx;
+
+ if (asidx == 0)
+ return cores_info->coresba_size[cidx];
+ else if (asidx == 1)
+ return cores_info->coresba2_size[cidx];
+ else {
+ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
+ __FUNCTION__, asidx));
+ return 0;
+ }
+}
+
+uint
+ai_flag(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ aidmp_t *ai;
+
+ if (BCM47162_DMP()) {
+ SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
+ return sii->curidx;
+ }
+ if (BCM5357_DMP()) {
+ SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
+ return sii->curidx;
+ }
+ if (BCM4707_DMP()) {
+ SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
+ __FUNCTION__));
+ return sii->curidx;
+ }
+ ai = sii->curwrap;
+
+ return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f);
+}
+
+uint
+ai_flag_alt(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ aidmp_t *ai;
+
+ if (BCM47162_DMP()) {
+ SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
+ return sii->curidx;
+ }
+ if (BCM5357_DMP()) {
+ SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
+ return sii->curidx;
+ }
+ if (BCM4707_DMP()) {
+ SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
+ __FUNCTION__));
+ return sii->curidx;
+ }
+ ai = sii->curwrap;
+
+ return ((R_REG(sii->osh, &ai->oobselouta30) >> AI_OOBSEL_1_SHIFT) & AI_OOBSEL_MASK);
+}
+
+void
+ai_setint(si_t *sih, int siflag)
+{
+}
+
+uint
+ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
+{
+ si_info_t *sii = SI_INFO(sih);
+ uint32 *map = (uint32 *) sii->curwrap;
+
+ if (mask || val) {
+ uint32 w = R_REG(sii->osh, map+(offset/4));
+ w &= ~mask;
+ w |= val;
+ W_REG(sii->osh, map+(offset/4), w);
+ }
+
+ return (R_REG(sii->osh, map+(offset/4)));
+}
+
+uint
+ai_corevendor(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint32 cia;
+
+ cia = cores_info->cia[sii->curidx];
+ return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT);
+}
+
+uint
+ai_corerev(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint32 cib;
+
+
+ cib = cores_info->cib[sii->curidx];
+ return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT);
+}
+
+bool
+ai_iscoreup(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ aidmp_t *ai;
+
+ ai = sii->curwrap;
+
+ return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) &&
+ ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0));
+}
+
+/*
+ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
+ * switch back to the original core, and return the new value.
+ *
+ * When using the silicon backplane, no fiddling with interrupts or core switches is needed.
+ *
+ * Also, when using pci/pcie, we can optimize away the core switching for pci registers
+ * and (on newer pci cores) chipcommon registers.
+ */
+uint
+ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
+{
+ uint origidx = 0;
+ uint32 *r = NULL;
+ uint w;
+ uint intr_val = 0;
+ bool fast = FALSE;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+
+ ASSERT(GOODIDX(coreidx));
+ ASSERT(regoff < SI_CORE_SIZE);
+ ASSERT((val & ~mask) == 0);
+
+ if (coreidx >= SI_MAXCORES)
+ return 0;
+
+ if (BUSTYPE(sih->bustype) == SI_BUS) {
+ /* If internal bus, we can always get at everything */
+ fast = TRUE;
+ /* map if does not exist */
+ if (!cores_info->regs[coreidx]) {
+ cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
+ SI_CORE_SIZE);
+ ASSERT(GOODREGS(cores_info->regs[coreidx]));
+ }
+ r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
+ } else if (BUSTYPE(sih->bustype) == PCI_BUS) {
+ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
+
+ if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
+ /* Chipc registers are mapped at 12KB */
+
+ fast = TRUE;
+ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
+ } else if (sii->pub.buscoreidx == coreidx) {
+ /* pci registers are at either in the last 2KB of an 8KB window
+ * or, in pcie and pci rev 13 at 8KB
+ */
+ fast = TRUE;
+ if (SI_FAST(sii))
+ r = (uint32 *)((char *)sii->curmap +
+ PCI_16KB0_PCIREGS_OFFSET + regoff);
+ else
+ r = (uint32 *)((char *)sii->curmap +
+ ((regoff >= SBCONFIGOFF) ?
+ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
+ regoff);
+ }
+ }
+
+ if (!fast) {
+ INTR_OFF(sii, intr_val);
+
+ /* save current core index */
+ origidx = si_coreidx(&sii->pub);
+
+ /* switch core */
+ r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff);
+ }
+ ASSERT(r != NULL);
+
+ /* mask and set */
+ if (mask || val) {
+ w = (R_REG(sii->osh, r) & ~mask) | val;
+ W_REG(sii->osh, r, w);
+ }
+
+ /* readback */
+ w = R_REG(sii->osh, r);
+
+ if (!fast) {
+ /* restore core index */
+ if (origidx != coreidx)
+ ai_setcoreidx(&sii->pub, origidx);
+
+ INTR_RESTORE(sii, intr_val);
+ }
+
+ return (w);
+}
+
+/*
+ * If there is no need for fiddling with interrupts or core switches (typically silicon
+ * back plane registers, pci registers and chipcommon registers), this function
+ * returns the register offset on this core to a mapped address. This address can
+ * be used for W_REG/R_REG directly.
+ *
+ * For accessing registers that would need a core switch, this function will return
+ * NULL.
+ */
+uint32 *
+ai_corereg_addr(si_t *sih, uint coreidx, uint regoff)
+{
+ uint32 *r = NULL;
+ bool fast = FALSE;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+
+ ASSERT(GOODIDX(coreidx));
+ ASSERT(regoff < SI_CORE_SIZE);
+
+ if (coreidx >= SI_MAXCORES)
+ return 0;
+
+ if (BUSTYPE(sih->bustype) == SI_BUS) {
+ /* If internal bus, we can always get at everything */
+ fast = TRUE;
+ /* map if does not exist */
+ if (!cores_info->regs[coreidx]) {
+ cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
+ SI_CORE_SIZE);
+ ASSERT(GOODREGS(cores_info->regs[coreidx]));
+ }
+ r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
+ } else if (BUSTYPE(sih->bustype) == PCI_BUS) {
+ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
+
+ if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
+ /* Chipc registers are mapped at 12KB */
+
+ fast = TRUE;
+ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
+ } else if (sii->pub.buscoreidx == coreidx) {
+ /* pci registers are at either in the last 2KB of an 8KB window
+ * or, in pcie and pci rev 13 at 8KB
+ */
+ fast = TRUE;
+ if (SI_FAST(sii))
+ r = (uint32 *)((char *)sii->curmap +
+ PCI_16KB0_PCIREGS_OFFSET + regoff);
+ else
+ r = (uint32 *)((char *)sii->curmap +
+ ((regoff >= SBCONFIGOFF) ?
+ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
+ regoff);
+ }
+ }
+
+ if (!fast)
+ return 0;
+
+ return (r);
+}
+
+void
+ai_core_disable(si_t *sih, uint32 bits)
+{
+ si_info_t *sii = SI_INFO(sih);
+ volatile uint32 dummy;
+ uint32 status;
+ aidmp_t *ai;
+
+
+ ASSERT(GOODREGS(sii->curwrap));
+ ai = sii->curwrap;
+
+ /* if core is already in reset, just return */
+ if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET)
+ return;
+
+ /* ensure there are no pending backplane operations */
+ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
+
+ /* if pending backplane ops still, try waiting longer */
+ if (status != 0) {
+ /* 300usecs was sufficient to allow backplane ops to clear for big hammer */
+ /* during driver load we may need more time */
+ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000);
+ /* if still pending ops, continue on and try disable anyway */
+ /* this is in big hammer path, so don't call wl_reinit in this case... */
+ }
+
+ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
+ dummy = R_REG(sii->osh, &ai->resetctrl);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(1);
+
+ W_REG(sii->osh, &ai->ioctrl, bits);
+ dummy = R_REG(sii->osh, &ai->ioctrl);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(10);
+}
+
+/* reset and re-enable a core
+ * inputs:
+ * bits - core specific bits that are set during and after reset sequence
+ * resetbits - core specific bits that are set only during reset sequence
+ */
+void
+ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
+{
+ si_info_t *sii = SI_INFO(sih);
+ aidmp_t *ai;
+ volatile uint32 dummy;
+ uint loop_counter = 10;
+
+ ASSERT(GOODREGS(sii->curwrap));
+ ai = sii->curwrap;
+
+ /* ensure there are no pending backplane operations */
+ SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
+
+
+ /* put core into reset state */
+ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
+ OSL_DELAY(10);
+
+ /* ensure there are no pending backplane operations */
+ SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300);
+
+ W_REG(sii->osh, &ai->ioctrl, (bits | resetbits | SICF_FGC | SICF_CLOCK_EN));
+ dummy = R_REG(sii->osh, &ai->ioctrl);
+ BCM_REFERENCE(dummy);
+
+ /* ensure there are no pending backplane operations */
+ SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
+
+
+ while (R_REG(sii->osh, &ai->resetctrl) != 0 && --loop_counter != 0) {
+ /* ensure there are no pending backplane operations */
+ SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
+
+
+ /* take core out of reset */
+ W_REG(sii->osh, &ai->resetctrl, 0);
+
+ /* ensure there are no pending backplane operations */
+ SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300);
+ }
+
+
+ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN));
+ dummy = R_REG(sii->osh, &ai->ioctrl);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(1);
+}
+
+void
+ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
+{
+ si_info_t *sii = SI_INFO(sih);
+ aidmp_t *ai;
+ uint32 w;
+
+
+ if (BCM47162_DMP()) {
+ SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
+ __FUNCTION__));
+ return;
+ }
+ if (BCM5357_DMP()) {
+ SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
+ __FUNCTION__));
+ return;
+ }
+ if (BCM4707_DMP()) {
+ SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
+ __FUNCTION__));
+ return;
+ }
+
+ ASSERT(GOODREGS(sii->curwrap));
+ ai = sii->curwrap;
+
+ ASSERT((val & ~mask) == 0);
+
+ if (mask || val) {
+ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
+ W_REG(sii->osh, &ai->ioctrl, w);
+ }
+}
+
+uint32
+ai_core_cflags(si_t *sih, uint32 mask, uint32 val)
+{
+ si_info_t *sii = SI_INFO(sih);
+ aidmp_t *ai;
+ uint32 w;
+
+ if (BCM47162_DMP()) {
+ SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
+ __FUNCTION__));
+ return 0;
+ }
+ if (BCM5357_DMP()) {
+ SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
+ __FUNCTION__));
+ return 0;
+ }
+ if (BCM4707_DMP()) {
+ SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
+ __FUNCTION__));
+ return 0;
+ }
+
+ ASSERT(GOODREGS(sii->curwrap));
+ ai = sii->curwrap;
+
+ ASSERT((val & ~mask) == 0);
+
+ if (mask || val) {
+ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
+ W_REG(sii->osh, &ai->ioctrl, w);
+ }
+
+ return R_REG(sii->osh, &ai->ioctrl);
+}
+
+uint32
+ai_core_sflags(si_t *sih, uint32 mask, uint32 val)
+{
+ si_info_t *sii = SI_INFO(sih);
+ aidmp_t *ai;
+ uint32 w;
+
+ if (BCM47162_DMP()) {
+ SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0",
+ __FUNCTION__));
+ return 0;
+ }
+ if (BCM5357_DMP()) {
+ SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n",
+ __FUNCTION__));
+ return 0;
+ }
+ if (BCM4707_DMP()) {
+ SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
+ __FUNCTION__));
+ return 0;
+ }
+
+ ASSERT(GOODREGS(sii->curwrap));
+ ai = sii->curwrap;
+
+ ASSERT((val & ~mask) == 0);
+ ASSERT((mask & ~SISF_CORE_BITS) == 0);
+
+ if (mask || val) {
+ w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val);
+ W_REG(sii->osh, &ai->iostatus, w);
+ }
+
+ return R_REG(sii->osh, &ai->iostatus);
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c
new file mode 100644
index 000000000000..d1f8abe5ff0e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmevent.c
@@ -0,0 +1,242 @@
+/*
+ * bcmevent read-only data shared by kernel or app layers
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ * $Id: bcmevent.c 662961 2016-11-24 01:22:35Z $
+ */
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+#include <proto/bcmeth.h>
+#include <proto/bcmevent.h>
+#include <proto/802.11.h>
+
+#if WLC_E_LAST != 165
+#error "You need to add an entry to bcmevent_names[] for the new event"
+#endif
+
+/* Use the actual name for event tracing */
+#define BCMEVENT_NAME(_event) {(_event), #_event}
+
+const bcmevent_name_t bcmevent_names[] = {
+ BCMEVENT_NAME(WLC_E_SET_SSID),
+ BCMEVENT_NAME(WLC_E_JOIN),
+ BCMEVENT_NAME(WLC_E_START),
+ BCMEVENT_NAME(WLC_E_AUTH),
+ BCMEVENT_NAME(WLC_E_AUTH_IND),
+ BCMEVENT_NAME(WLC_E_DEAUTH),
+ BCMEVENT_NAME(WLC_E_DEAUTH_IND),
+ BCMEVENT_NAME(WLC_E_ASSOC),
+ BCMEVENT_NAME(WLC_E_ASSOC_IND),
+ BCMEVENT_NAME(WLC_E_REASSOC),
+ BCMEVENT_NAME(WLC_E_REASSOC_IND),
+ BCMEVENT_NAME(WLC_E_DISASSOC),
+ BCMEVENT_NAME(WLC_E_DISASSOC_IND),
+ BCMEVENT_NAME(WLC_E_QUIET_START),
+ BCMEVENT_NAME(WLC_E_QUIET_END),
+ BCMEVENT_NAME(WLC_E_BEACON_RX),
+ BCMEVENT_NAME(WLC_E_LINK),
+ BCMEVENT_NAME(WLC_E_MIC_ERROR),
+ BCMEVENT_NAME(WLC_E_NDIS_LINK),
+ BCMEVENT_NAME(WLC_E_ROAM),
+ BCMEVENT_NAME(WLC_E_TXFAIL),
+ BCMEVENT_NAME(WLC_E_PMKID_CACHE),
+ BCMEVENT_NAME(WLC_E_RETROGRADE_TSF),
+ BCMEVENT_NAME(WLC_E_PRUNE),
+ BCMEVENT_NAME(WLC_E_AUTOAUTH),
+ BCMEVENT_NAME(WLC_E_EAPOL_MSG),
+ BCMEVENT_NAME(WLC_E_SCAN_COMPLETE),
+ BCMEVENT_NAME(WLC_E_ADDTS_IND),
+ BCMEVENT_NAME(WLC_E_DELTS_IND),
+ BCMEVENT_NAME(WLC_E_BCNSENT_IND),
+ BCMEVENT_NAME(WLC_E_BCNRX_MSG),
+ BCMEVENT_NAME(WLC_E_BCNLOST_MSG),
+ BCMEVENT_NAME(WLC_E_ROAM_PREP),
+ BCMEVENT_NAME(WLC_E_PFN_NET_FOUND),
+ BCMEVENT_NAME(WLC_E_PFN_NET_LOST),
+#if defined(IBSS_PEER_DISCOVERY_EVENT)
+ BCMEVENT_NAME(WLC_E_IBSS_ASSOC),
+#endif /* defined(IBSS_PEER_DISCOVERY_EVENT) */
+ BCMEVENT_NAME(WLC_E_RADIO),
+ BCMEVENT_NAME(WLC_E_PSM_WATCHDOG),
+ BCMEVENT_NAME(WLC_E_PROBREQ_MSG),
+ BCMEVENT_NAME(WLC_E_SCAN_CONFIRM_IND),
+ BCMEVENT_NAME(WLC_E_PSK_SUP),
+ BCMEVENT_NAME(WLC_E_COUNTRY_CODE_CHANGED),
+ BCMEVENT_NAME(WLC_E_EXCEEDED_MEDIUM_TIME),
+ BCMEVENT_NAME(WLC_E_ICV_ERROR),
+ BCMEVENT_NAME(WLC_E_UNICAST_DECODE_ERROR),
+ BCMEVENT_NAME(WLC_E_MULTICAST_DECODE_ERROR),
+ BCMEVENT_NAME(WLC_E_TRACE),
+ BCMEVENT_NAME(WLC_E_IF),
+#ifdef WLP2P
+ BCMEVENT_NAME(WLC_E_P2P_DISC_LISTEN_COMPLETE),
+#endif
+ BCMEVENT_NAME(WLC_E_RSSI),
+ BCMEVENT_NAME(WLC_E_PFN_SCAN_COMPLETE),
+ BCMEVENT_NAME(WLC_E_EXTLOG_MSG),
+#ifdef WIFI_ACT_FRAME
+ BCMEVENT_NAME(WLC_E_ACTION_FRAME),
+ BCMEVENT_NAME(WLC_E_ACTION_FRAME_RX),
+ BCMEVENT_NAME(WLC_E_ACTION_FRAME_COMPLETE),
+#endif
+ BCMEVENT_NAME(WLC_E_ESCAN_RESULT),
+ BCMEVENT_NAME(WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE),
+#ifdef WLP2P
+ BCMEVENT_NAME(WLC_E_PROBRESP_MSG),
+ BCMEVENT_NAME(WLC_E_P2P_PROBREQ_MSG),
+#endif
+#ifdef PROP_TXSTATUS
+ BCMEVENT_NAME(WLC_E_FIFO_CREDIT_MAP),
+#endif
+ BCMEVENT_NAME(WLC_E_WAKE_EVENT),
+ BCMEVENT_NAME(WLC_E_DCS_REQUEST),
+ BCMEVENT_NAME(WLC_E_RM_COMPLETE),
+#ifdef WLMEDIA_HTSF
+ BCMEVENT_NAME(WLC_E_HTSFSYNC),
+#endif
+ BCMEVENT_NAME(WLC_E_OVERLAY_REQ),
+ BCMEVENT_NAME(WLC_E_CSA_COMPLETE_IND),
+ BCMEVENT_NAME(WLC_E_EXCESS_PM_WAKE_EVENT),
+ BCMEVENT_NAME(WLC_E_PFN_SCAN_NONE),
+ BCMEVENT_NAME(WLC_E_PFN_SCAN_ALLGONE),
+#ifdef SOFTAP
+ BCMEVENT_NAME(WLC_E_GTK_PLUMBED),
+#endif
+ BCMEVENT_NAME(WLC_E_ASSOC_REQ_IE),
+ BCMEVENT_NAME(WLC_E_ASSOC_RESP_IE),
+ BCMEVENT_NAME(WLC_E_ACTION_FRAME_RX_NDIS),
+ BCMEVENT_NAME(WLC_E_BEACON_FRAME_RX),
+#ifdef WLTDLS
+ BCMEVENT_NAME(WLC_E_TDLS_PEER_EVENT),
+#endif /* WLTDLS */
+ BCMEVENT_NAME(WLC_E_NATIVE),
+#ifdef WLPKTDLYSTAT
+ BCMEVENT_NAME(WLC_E_PKTDELAY_IND),
+#endif /* WLPKTDLYSTAT */
+ BCMEVENT_NAME(WLC_E_SERVICE_FOUND),
+ BCMEVENT_NAME(WLC_E_GAS_FRAGMENT_RX),
+ BCMEVENT_NAME(WLC_E_GAS_COMPLETE),
+ BCMEVENT_NAME(WLC_E_P2PO_ADD_DEVICE),
+ BCMEVENT_NAME(WLC_E_P2PO_DEL_DEVICE),
+#ifdef WLWNM
+ BCMEVENT_NAME(WLC_E_WNM_STA_SLEEP),
+#endif /* WLWNM */
+#if defined(WL_PROXDETECT)
+ BCMEVENT_NAME(WLC_E_PROXD),
+#endif
+ BCMEVENT_NAME(WLC_E_CCA_CHAN_QUAL),
+ BCMEVENT_NAME(WLC_E_BSSID),
+#ifdef PROP_TXSTATUS
+ BCMEVENT_NAME(WLC_E_BCMC_CREDIT_SUPPORT),
+#endif
+ BCMEVENT_NAME(WLC_E_TXFAIL_THRESH),
+ BCMEVENT_NAME(WLC_E_RMC_EVENT),
+ BCMEVENT_NAME(WLC_E_PKT_FILTER),
+};
+
+const int bcmevent_names_size = ARRAYSIZE(bcmevent_names);
+
+/*
+ * Validate if the event is proper and if valid copy event header to event.
+ * If proper event pointer is passed, to just validate, pass NULL to event.
+ *
+ * Return values are
+ * BCME_OK - It is a BRCM event or BRCM dongle event
+ * BCME_NOTFOUND - Not BRCM, not an event, may be okay
+ * BCME_BADLEN - Bad length, should not process, just drop
+ */
+int
+is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
+ wl_event_msg_t *out_event)
+{
+ uint16 len;
+ uint16 subtype;
+ uint16 usr_subtype;
+ bcm_event_t *bcm_event;
+ uint8 *pktend;
+ int err = BCME_OK;
+
+ pktend = (uint8 *)pktdata + pktlen;
+ bcm_event = (bcm_event_t *)pktdata;
+
+ /* only care about 16-bit subtype / length versions */
+ if ((uint8 *)&bcm_event->bcm_hdr < pktend) {
+ uint8 short_subtype = *(uint8 *)&bcm_event->bcm_hdr;
+ if (!(short_subtype & 0x80)) {
+ err = BCME_NOTFOUND;
+ goto done;
+ }
+ }
+
+ /* must have both ether_header and bcmeth_hdr */
+ if (pktlen < OFFSETOF(bcm_event_t, event)) {
+ err = BCME_BADLEN;
+ goto done;
+ }
+
+ /* check length in bcmeth_hdr */
+ len = ntoh16_ua((void *)&bcm_event->bcm_hdr.length);
+
+ /* match on subtype, oui and usr subtype for BRCM events */
+ subtype = ntoh16_ua((void *)&bcm_event->bcm_hdr.subtype);
+ if (subtype != BCMILCP_SUBTYPE_VENDOR_LONG) {
+ err = BCME_NOTFOUND;
+ goto done;
+ }
+
+ if (bcmp(BRCM_OUI, &bcm_event->bcm_hdr.oui[0], DOT11_OUI_LEN)) {
+ err = BCME_NOTFOUND;
+ goto done;
+ }
+
+ /* if it is a bcm_event or bcm_dngl_event_t, validate it */
+ usr_subtype = ntoh16_ua((void *)&bcm_event->bcm_hdr.usr_subtype);
+ if (usr_subtype == BCMILCP_BCM_SUBTYPE_EVENT) {
+ if (pktlen < sizeof(bcm_event_t)) {
+ err = BCME_BADLEN;
+ goto done;
+ }
+ len = (uint16)sizeof(bcm_event_t) +
+ (uint16)ntoh32_ua((void *)&bcm_event->event.datalen);
+ if ((uint8 *)pktdata + len > pktend) {
+ err = BCME_BADLEN;
+ goto done;
+ }
+ if (exp_usr_subtype && (exp_usr_subtype != usr_subtype)) {
+ err = BCME_NOTFOUND;
+ goto done;
+ }
+ if (out_event) {
+ /* ensure BRCM event pkt aligned */
+ memcpy(out_event, &bcm_event->event, sizeof(wl_event_msg_t));
+ }
+ }
+ else {
+ err = BCME_NOTFOUND;
+ goto done;
+ }
+
+done:
+ return err;
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh.c b/drivers/net/wireless/bcmdhd/bcmsdh.c
new file mode 100644
index 000000000000..7f4cbcb2fdd7
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmsdh.c
@@ -0,0 +1,705 @@
+/*
+ * BCMSDH interface glue
+ * implement bcmsdh API for SDIOH driver
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdh.c 455573 2014-02-14 17:49:31Z $
+ */
+
+/**
+ * @file bcmsdh.c
+ */
+
+/* ****************** BCMSDH Interface Functions *************************** */
+
+#include <typedefs.h>
+#include <bcmdevs.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <hndsoc.h>
+#include <siutils.h>
+#include <osl.h>
+
+#include <bcmsdh.h> /* BRCM API for SDIO clients (such as wl, dhd) */
+#include <bcmsdbus.h> /* common SDIO/controller interface */
+#include <sbsdio.h> /* SDIO device core hardware definitions. */
+#include <sdio.h> /* SDIO Device and Protocol Specs */
+
+#define SDIOH_API_ACCESS_RETRY_LIMIT 2
+const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
+
+/* local copy of bcm sd handler */
+bcmsdh_info_t * l_bcmsdh = NULL;
+
+
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+extern int
+sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
+
+void
+bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
+{
+ sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
+}
+#endif
+
+/* Attach BCMSDH layer to SDIO Host Controller Driver
+ *
+ * @param osh OSL Handle.
+ * @param cfghdl Configuration Handle.
+ * @param regsva Virtual address of controller registers.
+ * @param irq Interrupt number of SDIO controller.
+ *
+ * @return bcmsdh_info_t Handle to BCMSDH context.
+ */
+bcmsdh_info_t *
+bcmsdh_attach(osl_t *osh, void *sdioh, ulong *regsva)
+{
+ bcmsdh_info_t *bcmsdh;
+
+ if ((bcmsdh = (bcmsdh_info_t *)MALLOC(osh, sizeof(bcmsdh_info_t))) == NULL) {
+ BCMSDH_ERROR(("bcmsdh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)));
+ return NULL;
+ }
+ bzero((char *)bcmsdh, sizeof(bcmsdh_info_t));
+ bcmsdh->sdioh = sdioh;
+ bcmsdh->osh = osh;
+ bcmsdh->init_success = TRUE;
+ *regsva = SI_ENUM_BASE;
+
+ /* Report the BAR, to fix if needed */
+ bcmsdh->sbwad = SI_ENUM_BASE;
+
+ /* save the handler locally */
+ l_bcmsdh = bcmsdh;
+
+ return bcmsdh;
+}
+
+int
+bcmsdh_detach(osl_t *osh, void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ if (bcmsdh != NULL) {
+ MFREE(osh, bcmsdh, sizeof(bcmsdh_info_t));
+ }
+
+ l_bcmsdh = NULL;
+
+ return 0;
+}
+
+int
+bcmsdh_iovar_op(void *sdh, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set);
+}
+
+bool
+bcmsdh_intr_query(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ bool on;
+
+ ASSERT(bcmsdh);
+ status = sdioh_interrupt_query(bcmsdh->sdioh, &on);
+ if (SDIOH_API_SUCCESS(status))
+ return FALSE;
+ else
+ return on;
+}
+
+int
+bcmsdh_intr_enable(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ ASSERT(bcmsdh);
+
+ status = sdioh_interrupt_set(bcmsdh->sdioh, TRUE);
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+
+int
+bcmsdh_intr_disable(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ ASSERT(bcmsdh);
+
+ status = sdioh_interrupt_set(bcmsdh->sdioh, FALSE);
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+
+int
+bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ ASSERT(bcmsdh);
+
+ status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh);
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+
+int
+bcmsdh_intr_dereg(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ ASSERT(bcmsdh);
+
+ status = sdioh_interrupt_deregister(bcmsdh->sdioh);
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+
+#if defined(DHD_DEBUG)
+bool
+bcmsdh_intr_pending(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ ASSERT(sdh);
+ return sdioh_interrupt_pending(bcmsdh->sdioh);
+}
+#endif
+
+
+int
+bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
+{
+ ASSERT(sdh);
+
+ /* don't support yet */
+ return BCME_UNSUPPORTED;
+}
+
+/**
+ * Read from SDIO Configuration Space
+ * @param sdh SDIO Host context.
+ * @param func_num Function number to read from.
+ * @param addr Address to read from.
+ * @param err Error return.
+ * @return value read from SDIO configuration space.
+ */
+uint8
+bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+ int32 retry = 0;
+#endif
+ uint8 data = 0;
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ ASSERT(bcmsdh->init_success);
+
+#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+ do {
+ if (retry) /* wait for 1 ms till bus get settled down */
+ OSL_DELAY(1000);
+#endif
+ status = sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data);
+#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+ } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
+#endif
+ if (err)
+ *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
+
+ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__,
+ fnc_num, addr, data));
+
+ return data;
+}
+
+void
+bcmsdh_cfg_write(void *sdh, uint fnc_num, uint32 addr, uint8 data, int *err)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+ int32 retry = 0;
+#endif
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ ASSERT(bcmsdh->init_success);
+
+#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+ do {
+ if (retry) /* wait for 1 ms till bus get settled down */
+ OSL_DELAY(1000);
+#endif
+ status = sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data);
+#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+ } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
+#endif
+ if (err)
+ *err = SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR;
+
+ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__,
+ fnc_num, addr, data));
+}
+
+uint32
+bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ uint32 data = 0;
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ ASSERT(bcmsdh->init_success);
+
+ status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ, fnc_num,
+ addr, &data, 4);
+
+ if (err)
+ *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
+
+ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__,
+ fnc_num, addr, data));
+
+ return data;
+}
+
+void
+bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ ASSERT(bcmsdh->init_success);
+
+ status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, fnc_num,
+ addr, &data, 4);
+
+ if (err)
+ *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
+
+ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__, fnc_num,
+ addr, data));
+}
+
+
+int
+bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+
+ uint8 *tmp_buf, *tmp_ptr;
+ uint8 *ptr;
+ bool ascii = func & ~0xf;
+ func &= 0x7;
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ ASSERT(bcmsdh->init_success);
+ ASSERT(cis);
+ ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
+
+ status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length);
+
+ if (ascii) {
+ /* Move binary bits to tmp and format them into the provided buffer. */
+ if ((tmp_buf = (uint8 *)MALLOC(bcmsdh->osh, length)) == NULL) {
+ BCMSDH_ERROR(("%s: out of memory\n", __FUNCTION__));
+ return BCME_NOMEM;
+ }
+ bcopy(cis, tmp_buf, length);
+ for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4); tmp_ptr++) {
+ ptr += snprintf((char*)ptr, (cis + length - ptr - 4),
+ "%.2x ", *tmp_ptr & 0xff);
+ if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
+ ptr += snprintf((char *)ptr, (cis + length - ptr -4), "\n");
+ }
+ MFREE(bcmsdh->osh, tmp_buf, length);
+ }
+
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+
+
+int
+bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set)
+{
+ int err = 0;
+ uint bar0 = address & ~SBSDIO_SB_OFT_ADDR_MASK;
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ if (bar0 != bcmsdh->sbwad || force_set) {
+ bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+ (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
+ if (!err)
+ bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
+ (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
+ if (!err)
+ bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
+ (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
+
+ if (!err)
+ bcmsdh->sbwad = bar0;
+ else
+ /* invalidate cached window var */
+ bcmsdh->sbwad = 0;
+
+ }
+
+ return err;
+}
+
+uint32
+bcmsdh_reg_read(void *sdh, uint32 addr, uint size)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ uint32 word = 0;
+
+ BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __FUNCTION__, addr));
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ ASSERT(bcmsdh->init_success);
+
+ if (bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE))
+ return 0xFFFFFFFF;
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ if (size == 4)
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+ SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
+
+ bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
+
+ BCMSDH_INFO(("uint32data = 0x%x\n", word));
+
+ /* if ok, return appropriately masked word */
+ if (SDIOH_API_SUCCESS(status)) {
+ switch (size) {
+ case sizeof(uint8):
+ return (word & 0xff);
+ case sizeof(uint16):
+ return (word & 0xffff);
+ case sizeof(uint32):
+ return word;
+ default:
+ bcmsdh->regfail = TRUE;
+
+ }
+ }
+
+ /* otherwise, bad sdio access or invalid size */
+ BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __FUNCTION__, addr, size));
+ return 0xFFFFFFFF;
+}
+
+uint32
+bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ int err = 0;
+
+ BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
+ __FUNCTION__, addr, size*8, data));
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ ASSERT(bcmsdh->init_success);
+
+ if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE)))
+ return err;
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ if (size == 4)
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, SDIO_FUNC_1,
+ addr, &data, size);
+ bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
+
+ if (SDIOH_API_SUCCESS(status))
+ return 0;
+
+ BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
+ __FUNCTION__, data, addr, size));
+ return 0xFFFFFFFF;
+}
+
+bool
+bcmsdh_regfail(void *sdh)
+{
+ return ((bcmsdh_info_t *)sdh)->regfail;
+}
+
+int
+bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags,
+ uint8 *buf, uint nbytes, void *pkt,
+ bcmsdh_cmplt_fn_t complete_fn, void *handle)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ uint incr_fix;
+ uint width;
+ int err = 0;
+
+ ASSERT(bcmsdh);
+ ASSERT(bcmsdh->init_success);
+
+ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
+ __FUNCTION__, fn, addr, nbytes));
+
+ /* Async not implemented yet */
+ ASSERT(!(flags & SDIO_REQ_ASYNC));
+ if (flags & SDIO_REQ_ASYNC)
+ return BCME_UNSUPPORTED;
+
+ if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE)))
+ return err;
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+
+ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
+ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
+ if (width == 4)
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
+ SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
+
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
+}
+
+int
+bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags,
+ uint8 *buf, uint nbytes, void *pkt,
+ bcmsdh_cmplt_fn_t complete_fn, void *handle)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ uint incr_fix;
+ uint width;
+ int err = 0;
+
+ ASSERT(bcmsdh);
+ ASSERT(bcmsdh->init_success);
+
+ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
+ __FUNCTION__, fn, addr, nbytes));
+
+ /* Async not implemented yet */
+ ASSERT(!(flags & SDIO_REQ_ASYNC));
+ if (flags & SDIO_REQ_ASYNC)
+ return BCME_UNSUPPORTED;
+
+ if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE)))
+ return err;
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+
+ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
+ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
+ if (width == 4)
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
+ SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
+
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+
+int
+bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+
+ ASSERT(bcmsdh);
+ ASSERT(bcmsdh->init_success);
+ ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC,
+ (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
+ addr, 4, nbytes, buf, NULL);
+
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+
+int
+bcmsdh_abort(void *sdh, uint fn)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ return sdioh_abort(bcmsdh->sdioh, fn);
+}
+
+int
+bcmsdh_start(void *sdh, int stage)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ return sdioh_start(bcmsdh->sdioh, stage);
+}
+
+int
+bcmsdh_stop(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ return sdioh_stop(bcmsdh->sdioh);
+}
+
+int
+bcmsdh_waitlockfree(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ return sdioh_waitlockfree(bcmsdh->sdioh);
+}
+
+
+int
+bcmsdh_query_device(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ bcmsdh->vendevid = (VENDOR_BROADCOM << 16) | 0;
+ return (bcmsdh->vendevid);
+}
+
+uint
+bcmsdh_query_iofnum(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ return (sdioh_query_iofnum(bcmsdh->sdioh));
+}
+
+int
+bcmsdh_reset(bcmsdh_info_t *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ return sdioh_sdio_reset(bcmsdh->sdioh);
+}
+
+void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh)
+{
+ ASSERT(sdh);
+ return sdh->sdioh;
+}
+
+/* Function to pass device-status bits to DHD. */
+uint32
+bcmsdh_get_dstatus(void *sdh)
+{
+ return 0;
+}
+uint32
+bcmsdh_cur_sbwad(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+
+ if (!bcmsdh)
+ bcmsdh = l_bcmsdh;
+
+ return (bcmsdh->sbwad);
+}
+
+void
+bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev)
+{
+ return;
+}
+
+
+int
+bcmsdh_sleep(void *sdh, bool enab)
+{
+#ifdef SDIOH_SLEEP_ENABLED
+ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
+ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
+
+ return sdioh_sleep(sd, enab);
+#else
+ return BCME_UNSUPPORTED;
+#endif
+}
+
+int
+bcmsdh_gpio_init(void *sdh)
+{
+ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
+ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
+
+ return sdioh_gpio_init(sd);
+}
+
+bool
+bcmsdh_gpioin(void *sdh, uint32 gpio)
+{
+ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
+ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
+
+ return sdioh_gpioin(sd, gpio);
+}
+
+int
+bcmsdh_gpioouten(void *sdh, uint32 gpio)
+{
+ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
+ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
+
+ return sdioh_gpioouten(sd, gpio);
+}
+
+int
+bcmsdh_gpioout(void *sdh, uint32 gpio, bool enab)
+{
+ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
+ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
+
+ return sdioh_gpioout(sd, gpio, enab);
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
new file mode 100644
index 000000000000..87c00c2f82be
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
@@ -0,0 +1,473 @@
+/*
+ * SDIO access interface for drivers - linux specific (pci only)
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdh_linux.c 662739 2016-11-08 09:20:31Z $
+ */
+
+/**
+ * @file bcmsdh_linux.c
+ */
+
+#define __UNDEF_NO_VERSION__
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <linux/pci.h>
+#include <linux/completion.h>
+
+#include <osl.h>
+#include <pcicfg.h>
+#include <bcmdefs.h>
+#include <bcmdevs.h>
+#include <linux/irq.h>
+extern void dhdsdio_isr(void * args);
+#include <bcmutils.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#if defined(CONFIG_ARCH_ODIN)
+#include <linux/platform_data/gpio-odin.h>
+#endif /* defined(CONFIG_ARCH_ODIN) */
+
+#include <dhd_linux.h>
+
+/* driver info, initialized when bcmsdh_register is called */
+static bcmsdh_driver_t drvinfo = {NULL, NULL, NULL, NULL};
+
+typedef enum {
+ DHD_INTR_INVALID = 0,
+ DHD_INTR_INBAND,
+ DHD_INTR_HWOOB,
+ DHD_INTR_SWOOB
+} DHD_HOST_INTR_TYPE;
+
+/* the BCMSDH module comprises the generic part (bcmsdh.c) and OS specific layer (e.g.
+ * bcmsdh_linux.c). Put all OS specific variables (e.g. irq number and flags) here rather
+ * than in the common structure bcmsdh_info. bcmsdh_info only keeps a handle (os_ctx) to this
+ * structure.
+ */
+typedef struct bcmsdh_os_info {
+ DHD_HOST_INTR_TYPE intr_type;
+ int oob_irq_num; /* valid when hardware or software oob in use */
+ unsigned long oob_irq_flags; /* valid when hardware or software oob in use */
+ bool oob_irq_registered;
+ bool oob_irq_enabled;
+ bool oob_irq_wake_enabled;
+ spinlock_t oob_irq_spinlock;
+ bcmsdh_cb_fn_t oob_irq_handler;
+ void *oob_irq_handler_context;
+ void *context; /* context returned from upper layer */
+ void *sdioh; /* handle to lower layer (sdioh) */
+ void *dev; /* handle to the underlying device */
+ bool dev_wake_enabled;
+} bcmsdh_os_info_t;
+
+/* debugging macros */
+#define SDLX_MSG(x)
+
+/**
+ * Checks to see if vendor and device IDs match a supported SDIO Host Controller.
+ */
+bool
+bcmsdh_chipmatch(uint16 vendor, uint16 device)
+{
+ /* Add other vendors and devices as required */
+
+#ifdef BCMSDIOH_STD
+ /* Check for Arasan host controller */
+ if (vendor == VENDOR_SI_IMAGE) {
+ return (TRUE);
+ }
+ /* Check for BRCM 27XX Standard host controller */
+ if (device == BCM27XX_SDIOH_ID && vendor == VENDOR_BROADCOM) {
+ return (TRUE);
+ }
+ /* Check for BRCM Standard host controller */
+ if (device == SDIOH_FPGA_ID && vendor == VENDOR_BROADCOM) {
+ return (TRUE);
+ }
+ /* Check for TI PCIxx21 Standard host controller */
+ if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI) {
+ return (TRUE);
+ }
+ if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI) {
+ return (TRUE);
+ }
+ /* Ricoh R5C822 Standard SDIO Host */
+ if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH) {
+ return (TRUE);
+ }
+ /* JMicron Standard SDIO Host */
+ if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON) {
+ return (TRUE);
+ }
+
+#endif /* BCMSDIOH_STD */
+#ifdef BCMSDIOH_SPI
+ /* This is the PciSpiHost. */
+ if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) {
+ printf("Found PCI SPI Host Controller\n");
+ return (TRUE);
+ }
+
+#endif /* BCMSDIOH_SPI */
+
+ return (FALSE);
+}
+
+void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bus_type,
+ uint bus_num, uint slot_num)
+{
+ ulong regs;
+ bcmsdh_info_t *bcmsdh;
+ uint32 vendevid;
+ bcmsdh_os_info_t *bcmsdh_osinfo = NULL;
+#ifdef OOB_PARAM
+ wifi_adapter_info_t *adapter = (wifi_adapter_info_t *)adapter_info;
+#endif /* OOB_PARAM */
+
+ bcmsdh = bcmsdh_attach(osh, sdioh, &regs);
+ if (bcmsdh == NULL) {
+ SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
+ goto err;
+ }
+ bcmsdh_osinfo = MALLOC(osh, sizeof(bcmsdh_os_info_t));
+ if (bcmsdh_osinfo == NULL) {
+ SDLX_MSG(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__));
+ goto err;
+ }
+ bzero((char *)bcmsdh_osinfo, sizeof(bcmsdh_os_info_t));
+ bcmsdh->os_cxt = bcmsdh_osinfo;
+ bcmsdh_osinfo->sdioh = sdioh;
+ bcmsdh_osinfo->dev = dev;
+ osl_set_bus_handle(osh, bcmsdh);
+
+#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ if (dev && device_init_wakeup(dev, true) == 0)
+ bcmsdh_osinfo->dev_wake_enabled = TRUE;
+#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
+
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(adapter->oob_disable)) {
+ spin_lock_init(&bcmsdh_osinfo->oob_irq_spinlock);
+ /* Get customer specific OOB IRQ parametres: IRQ number as IRQ type */
+ bcmsdh_osinfo->oob_irq_num = wifi_platform_get_irq_number(adapter_info,
+ &bcmsdh_osinfo->oob_irq_flags);
+ if (bcmsdh_osinfo->oob_irq_num < 0) {
+ SDLX_MSG(("%s: Host OOB irq is not defined\n", __FUNCTION__));
+ goto err;
+ }
+ }
+#endif /* defined(OOB_INTR_ONLY) */
+
+ /* Read the vendor/device ID from the CIS */
+ vendevid = bcmsdh_query_device(bcmsdh);
+ /* try to attach to the target device */
+ bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num,
+ slot_num, 0, bus_type, (void *)regs, osh, bcmsdh);
+ if (bcmsdh_osinfo->context == NULL) {
+ SDLX_MSG(("%s: device attach failed\n", __FUNCTION__));
+ goto err;
+ }
+
+ return bcmsdh;
+
+ /* error handling */
+err:
+ if (bcmsdh != NULL)
+ bcmsdh_detach(osh, bcmsdh);
+ if (bcmsdh_osinfo != NULL)
+ MFREE(osh, bcmsdh_osinfo, sizeof(bcmsdh_os_info_t));
+ return NULL;
+}
+
+int bcmsdh_remove(bcmsdh_info_t *bcmsdh)
+{
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+
+#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ if (bcmsdh_osinfo->dev)
+ device_init_wakeup(bcmsdh_osinfo->dev, false);
+ bcmsdh_osinfo->dev_wake_enabled = FALSE;
+#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
+
+ drvinfo.remove(bcmsdh_osinfo->context);
+ MFREE(bcmsdh->osh, bcmsdh->os_cxt, sizeof(bcmsdh_os_info_t));
+ bcmsdh_detach(bcmsdh->osh, bcmsdh);
+
+ return 0;
+}
+
+int bcmsdh_suspend(bcmsdh_info_t *bcmsdh)
+{
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+
+ if (drvinfo.suspend && drvinfo.suspend(bcmsdh_osinfo->context))
+ return -EBUSY;
+ return 0;
+}
+
+int bcmsdh_resume(bcmsdh_info_t *bcmsdh)
+{
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+
+ if (drvinfo.resume)
+ return drvinfo.resume(bcmsdh_osinfo->context);
+ return 0;
+}
+
+extern int bcmsdh_register_client_driver(void);
+extern void bcmsdh_unregister_client_driver(void);
+extern int sdio_func_reg_notify(void* semaphore);
+extern void sdio_func_unreg_notify(void);
+
+#if defined(BCMLXSDMMC)
+int bcmsdh_reg_sdio_notify(void* semaphore)
+{
+ return sdio_func_reg_notify(semaphore);
+}
+
+void bcmsdh_unreg_sdio_notify(void)
+{
+ sdio_func_unreg_notify();
+}
+#endif /* defined(BCMLXSDMMC) */
+
+int
+bcmsdh_register(bcmsdh_driver_t *driver)
+{
+ int error = 0;
+
+ drvinfo = *driver;
+ SDLX_MSG(("%s: register client driver\n", __FUNCTION__));
+ error = bcmsdh_register_client_driver();
+ if (error)
+ SDLX_MSG(("%s: failed %d\n", __FUNCTION__, error));
+
+ return error;
+}
+
+void
+bcmsdh_unregister(void)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+ if (bcmsdh_pci_driver.node.next == NULL)
+ return;
+#endif
+
+ bcmsdh_unregister_client_driver();
+}
+
+void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *bcmsdh)
+{
+#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+ pm_stay_awake(bcmsdh_osinfo->dev);
+#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
+}
+
+void bcmsdh_dev_relax(bcmsdh_info_t *bcmsdh)
+{
+#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+ pm_relax(bcmsdh_osinfo->dev);
+#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
+}
+
+bool bcmsdh_dev_pm_enabled(bcmsdh_info_t *bcmsdh)
+{
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+
+ return bcmsdh_osinfo->dev_wake_enabled;
+}
+
+#if defined(OOB_INTR_ONLY)
+void bcmsdh_oob_intr_set(bcmsdh_info_t *bcmsdh, bool enable)
+{
+ unsigned long flags;
+ bcmsdh_os_info_t *bcmsdh_osinfo;
+
+ if (!bcmsdh)
+ return;
+
+ bcmsdh_osinfo = bcmsdh->os_cxt;
+ spin_lock_irqsave(&bcmsdh_osinfo->oob_irq_spinlock, flags);
+ if (bcmsdh_osinfo->oob_irq_enabled != enable) {
+ if (enable)
+ enable_irq(bcmsdh_osinfo->oob_irq_num);
+ else
+ disable_irq_nosync(bcmsdh_osinfo->oob_irq_num);
+ bcmsdh_osinfo->oob_irq_enabled = enable;
+ }
+ spin_unlock_irqrestore(&bcmsdh_osinfo->oob_irq_spinlock, flags);
+}
+
+static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)dev_id;
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+
+ bcmsdh_oob_intr_set(bcmsdh, FALSE);
+ bcmsdh_osinfo->oob_irq_handler(bcmsdh_osinfo->oob_irq_handler_context);
+
+ return IRQ_HANDLED;
+}
+
+int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler,
+ void* oob_irq_handler_context)
+{
+ int err = 0;
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+
+ SDLX_MSG(("%s: Enter\n", __FUNCTION__));
+ if (bcmsdh_osinfo->oob_irq_registered) {
+ SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__));
+ return -EBUSY;
+ }
+ SDLX_MSG(("%s OOB irq=%d flags=%X \n", __FUNCTION__,
+ (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags));
+ bcmsdh_osinfo->oob_irq_handler = oob_irq_handler;
+ bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context;
+ bcmsdh_osinfo->oob_irq_enabled = TRUE;
+ bcmsdh_osinfo->oob_irq_registered = TRUE;
+#if defined(CONFIG_ARCH_ODIN)
+ err = odin_gpio_sms_request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq,
+ bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh);
+#else
+ err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq,
+ bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh);
+#endif /* defined(CONFIG_ARCH_ODIN) */
+ if (err) {
+ SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err));
+ bcmsdh_osinfo->oob_irq_enabled = FALSE;
+ bcmsdh_osinfo->oob_irq_registered = FALSE;
+ return err;
+ }
+
+ err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num);
+ if (!err)
+ bcmsdh_osinfo->oob_irq_wake_enabled = TRUE;
+ return err;
+}
+
+void bcmsdh_oob_intr_unregister(bcmsdh_info_t *bcmsdh)
+{
+ int err = 0;
+ bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+
+ SDLX_MSG(("%s: Enter\n", __FUNCTION__));
+ if (!bcmsdh_osinfo->oob_irq_registered) {
+ SDLX_MSG(("%s: irq is not registered\n", __FUNCTION__));
+ return;
+ }
+ if (bcmsdh_osinfo->oob_irq_wake_enabled) {
+ err = disable_irq_wake(bcmsdh_osinfo->oob_irq_num);
+ if (!err)
+ bcmsdh_osinfo->oob_irq_wake_enabled = FALSE;
+ }
+ if (bcmsdh_osinfo->oob_irq_enabled) {
+ disable_irq(bcmsdh_osinfo->oob_irq_num);
+ bcmsdh_osinfo->oob_irq_enabled = FALSE;
+ }
+ free_irq(bcmsdh_osinfo->oob_irq_num, bcmsdh);
+ bcmsdh_osinfo->oob_irq_registered = FALSE;
+}
+#endif
+
+/* Module parameters specific to each host-controller driver */
+
+extern uint sd_msglevel; /* Debug message level */
+module_param(sd_msglevel, uint, 0);
+
+extern uint sd_power; /* 0 = SD Power OFF, 1 = SD Power ON. */
+module_param(sd_power, uint, 0);
+
+extern uint sd_clock; /* SD Clock Control, 0 = SD Clock OFF, 1 = SD Clock ON */
+module_param(sd_clock, uint, 0);
+
+extern uint sd_divisor; /* Divisor (-1 means external clock) */
+module_param(sd_divisor, uint, 0);
+
+extern uint sd_sdmode; /* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */
+module_param(sd_sdmode, uint, 0);
+
+extern uint sd_hiok; /* Ok to use hi-speed mode */
+module_param(sd_hiok, uint, 0);
+
+extern uint sd_f2_blocksize;
+module_param(sd_f2_blocksize, int, 0);
+
+#ifdef BCMSDIOH_STD
+extern int sd_uhsimode;
+module_param(sd_uhsimode, int, 0);
+extern uint sd_tuning_period;
+module_param(sd_tuning_period, uint, 0);
+extern int sd_delay_value;
+module_param(sd_delay_value, uint, 0);
+
+/* SDIO Drive Strength for UHSI mode specific to SDIO3.0 */
+extern char dhd_sdiod_uhsi_ds_override[2];
+module_param_string(dhd_sdiod_uhsi_ds_override, dhd_sdiod_uhsi_ds_override, 2, 0);
+
+#endif
+
+#ifdef BCMSDH_MODULE
+EXPORT_SYMBOL(bcmsdh_attach);
+EXPORT_SYMBOL(bcmsdh_detach);
+EXPORT_SYMBOL(bcmsdh_intr_query);
+EXPORT_SYMBOL(bcmsdh_intr_enable);
+EXPORT_SYMBOL(bcmsdh_intr_disable);
+EXPORT_SYMBOL(bcmsdh_intr_reg);
+EXPORT_SYMBOL(bcmsdh_intr_dereg);
+
+#if defined(DHD_DEBUG)
+EXPORT_SYMBOL(bcmsdh_intr_pending);
+#endif
+
+EXPORT_SYMBOL(bcmsdh_devremove_reg);
+EXPORT_SYMBOL(bcmsdh_cfg_read);
+EXPORT_SYMBOL(bcmsdh_cfg_write);
+EXPORT_SYMBOL(bcmsdh_cis_read);
+EXPORT_SYMBOL(bcmsdh_reg_read);
+EXPORT_SYMBOL(bcmsdh_reg_write);
+EXPORT_SYMBOL(bcmsdh_regfail);
+EXPORT_SYMBOL(bcmsdh_send_buf);
+EXPORT_SYMBOL(bcmsdh_recv_buf);
+
+EXPORT_SYMBOL(bcmsdh_rwdata);
+EXPORT_SYMBOL(bcmsdh_abort);
+EXPORT_SYMBOL(bcmsdh_query_device);
+EXPORT_SYMBOL(bcmsdh_query_iofnum);
+EXPORT_SYMBOL(bcmsdh_iovar_op);
+EXPORT_SYMBOL(bcmsdh_register);
+EXPORT_SYMBOL(bcmsdh_unregister);
+EXPORT_SYMBOL(bcmsdh_chipmatch);
+EXPORT_SYMBOL(bcmsdh_reset);
+EXPORT_SYMBOL(bcmsdh_waitlockfree);
+
+EXPORT_SYMBOL(bcmsdh_get_dstatus);
+EXPORT_SYMBOL(bcmsdh_cfg_read_word);
+EXPORT_SYMBOL(bcmsdh_cfg_write_word);
+EXPORT_SYMBOL(bcmsdh_cur_sbwad);
+EXPORT_SYMBOL(bcmsdh_chipinfo);
+
+#endif /* BCMSDH_MODULE */
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
new file mode 100644
index 000000000000..bf94aaada44e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
@@ -0,0 +1,1491 @@
+/*
+ * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdh_sdmmc.c 662739 2016-11-08 09:20:31Z $
+ */
+#include <typedefs.h>
+
+#include <bcmdevs.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <osl.h>
+#include <sdio.h> /* SDIO Device and Protocol Specs */
+#include <sdioh.h> /* Standard SDIO Host Controller Specification */
+#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
+#include <sdiovar.h> /* ioctl/iovars */
+
+#include <linux/mmc/core.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+#include <dngl_stats.h>
+#include <dhd.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+#include <linux/suspend.h>
+extern volatile bool dhd_mmc_suspend;
+#endif
+#include "bcmsdh_sdmmc.h"
+
+#ifndef BCMSDH_MODULE
+extern int sdio_function_init(void);
+extern void sdio_function_cleanup(void);
+#endif /* BCMSDH_MODULE */
+
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+static void IRQHandler(struct sdio_func *func);
+static void IRQHandlerF2(struct sdio_func *func);
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
+
+#ifdef OOB_PARAM
+extern int sdioh_get_oob_disable(sdioh_info_t *sd);
+#endif /* OOB_PRARM */
+
+#if defined(NO_SDIO_RESET)
+static int sdio_reset_comm(struct mmc_card *card)
+{
+ return 0;
+}
+#else
+extern int sdio_reset_comm(struct mmc_card *card);
+#endif /* NO_SDIO_RESET */
+
+#define DEFAULT_SDIO_F2_BLKSIZE 512
+#ifndef CUSTOM_SDIO_F2_BLKSIZE
+#define CUSTOM_SDIO_F2_BLKSIZE DEFAULT_SDIO_F2_BLKSIZE
+#endif
+
+#define MAX_IO_RW_EXTENDED_BLK 511
+
+uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */
+uint sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE;
+uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */
+
+uint sd_power = 1; /* Default to SD Slot powered ON */
+uint sd_clock = 1; /* Default to SD Clock turned ON */
+uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */
+uint sd_msglevel = 0x01;
+uint sd_use_dma = TRUE;
+
+#ifndef CUSTOM_RXCHAIN
+#define CUSTOM_RXCHAIN 0
+#endif
+
+DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
+DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
+DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
+DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
+
+#define DMA_ALIGN_MASK 0x03
+#define MMC_SDIO_ABORT_RETRY_LIMIT 5
+
+int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data);
+
+static int
+sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
+{
+ int err_ret;
+ uint32 fbraddr;
+ uint8 func;
+
+ sd_trace(("%s\n", __FUNCTION__));
+
+ /* Get the Card's common CIS address */
+ sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
+ sd->func_cis_ptr[0] = sd->com_cis_ptr;
+ sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
+
+ /* Get the Card's function CIS (for each function) */
+ for (fbraddr = SDIOD_FBR_STARTADDR, func = 1;
+ func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
+ sd->func_cis_ptr[func] = sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
+ sd_info(("%s: Function %d CIS Ptr = 0x%x\n",
+ __FUNCTION__, func, sd->func_cis_ptr[func]));
+ }
+
+ sd->func_cis_ptr[0] = sd->com_cis_ptr;
+ sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
+
+ /* Enable Function 1 */
+ sdio_claim_host(sd->func[1]);
+ err_ret = sdio_enable_func(sd->func[1]);
+ sdio_release_host(sd->func[1]);
+ if (err_ret) {
+ sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret));
+ }
+
+ return FALSE;
+}
+
+/*
+ * Public entry points & extern's
+ */
+extern sdioh_info_t *
+sdioh_attach(osl_t *osh, struct sdio_func *func)
+{
+ sdioh_info_t *sd = NULL;
+ int err_ret;
+
+ sd_trace(("%s\n", __FUNCTION__));
+
+ if (func == NULL) {
+ sd_err(("%s: sdio function device is NULL\n", __FUNCTION__));
+ return NULL;
+ }
+
+ if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
+ sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)));
+ return NULL;
+ }
+ bzero((char *)sd, sizeof(sdioh_info_t));
+ sd->osh = osh;
+ sd->fake_func0.num = 0;
+ sd->fake_func0.card = func->card;
+ sd->func[0] = &sd->fake_func0;
+ sd->func[1] = func->card->sdio_func[0];
+ sd->func[2] = func->card->sdio_func[1];
+ sd->num_funcs = 2;
+ sd->sd_blockmode = TRUE;
+ sd->use_client_ints = TRUE;
+ sd->client_block_size[0] = 64;
+ sd->use_rxchain = CUSTOM_RXCHAIN;
+ if (sd->func[1] == NULL || sd->func[2] == NULL) {
+ sd_err(("%s: func 1 or 2 is null \n", __FUNCTION__));
+ goto fail;
+ }
+ sdio_set_drvdata(sd->func[1], sd);
+
+ sdio_claim_host(sd->func[1]);
+ sd->client_block_size[1] = 64;
+ err_ret = sdio_set_block_size(sd->func[1], 64);
+ sdio_release_host(sd->func[1]);
+ if (err_ret) {
+ sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize(%d)\n", err_ret));
+ goto fail;
+ }
+
+ sdio_claim_host(sd->func[2]);
+ sd->client_block_size[2] = sd_f2_blocksize;
+ err_ret = sdio_set_block_size(sd->func[2], sd_f2_blocksize);
+ sdio_release_host(sd->func[2]);
+ if (err_ret) {
+ sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize to %d(%d)\n",
+ sd_f2_blocksize, err_ret));
+ goto fail;
+ }
+
+ sdioh_sdmmc_card_enablefuncs(sd);
+
+ sd_trace(("%s: Done\n", __FUNCTION__));
+ return sd;
+
+fail:
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ return NULL;
+}
+
+
+extern SDIOH_API_RC
+sdioh_detach(osl_t *osh, sdioh_info_t *sd)
+{
+ sd_trace(("%s\n", __FUNCTION__));
+
+ if (sd) {
+
+ /* Disable Function 2 */
+ if (sd->func[2]) {
+ sdio_claim_host(sd->func[2]);
+ sdio_disable_func(sd->func[2]);
+ sdio_release_host(sd->func[2]);
+ }
+
+ /* Disable Function 1 */
+ if (sd->func[1]) {
+ sdio_claim_host(sd->func[1]);
+ sdio_disable_func(sd->func[1]);
+ sdio_release_host(sd->func[1]);
+ }
+
+ sd->func[1] = NULL;
+ sd->func[2] = NULL;
+
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ }
+ return SDIOH_API_RC_SUCCESS;
+}
+
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+
+extern SDIOH_API_RC
+sdioh_enable_func_intr(sdioh_info_t *sd)
+{
+ uint8 reg;
+ int err;
+
+ if (sd->func[0] == NULL) {
+ sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ sdio_claim_host(sd->func[0]);
+ reg = sdio_readb(sd->func[0], SDIOD_CCCR_INTEN, &err);
+ if (err) {
+ sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
+ sdio_release_host(sd->func[0]);
+ return SDIOH_API_RC_FAIL;
+ }
+ /* Enable F1 and F2 interrupts, clear master enable */
+ reg &= ~INTR_CTL_MASTER_EN;
+ reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
+ sdio_writeb(sd->func[0], reg, SDIOD_CCCR_INTEN, &err);
+ sdio_release_host(sd->func[0]);
+
+ if (err) {
+ sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_disable_func_intr(sdioh_info_t *sd)
+{
+ uint8 reg;
+ int err;
+
+ if (sd->func[0] == NULL) {
+ sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ sdio_claim_host(sd->func[0]);
+ reg = sdio_readb(sd->func[0], SDIOD_CCCR_INTEN, &err);
+ if (err) {
+ sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
+ sdio_release_host(sd->func[0]);
+ return SDIOH_API_RC_FAIL;
+ }
+ reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
+ /* Disable master interrupt with the last function interrupt */
+ if (!(reg & 0xFE))
+ reg = 0;
+ sdio_writeb(sd->func[0], reg, SDIOD_CCCR_INTEN, &err);
+ sdio_release_host(sd->func[0]);
+
+ if (err) {
+ sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ return SDIOH_API_RC_SUCCESS;
+}
+#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
+
+/* Configure callback to client when we recieve client interrupt */
+extern SDIOH_API_RC
+sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
+{
+ sd_trace(("%s: Entering\n", __FUNCTION__));
+ if (fn == NULL) {
+ sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__));
+ return SDIOH_API_RC_FAIL;
+ }
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+ OOB_PARAM_IF(dhd_get_oob_disable(argh)) {
+ sd->intr_handler = fn;
+ sd->intr_handler_arg = argh;
+ sd->intr_handler_valid = TRUE;
+
+ /* register and unmask irq */
+ if (sd->func[2]) {
+ sdio_claim_host(sd->func[2]);
+ sdio_claim_irq(sd->func[2], IRQHandlerF2);
+ sdio_release_host(sd->func[2]);
+ }
+
+ if (sd->func[1]) {
+ sdio_claim_host(sd->func[1]);
+ sdio_claim_irq(sd->func[1], IRQHandler);
+ sdio_release_host(sd->func[1]);
+ }
+ } OOB_PARAM_ELSE()
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+ {
+ sdioh_enable_func_intr(sd);
+ }
+#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
+
+ return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_interrupt_deregister(sdioh_info_t *sd)
+{
+ sd_trace(("%s: Entering\n", __FUNCTION__));
+
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+ OOB_PARAM_IF(sd->intr_handler_valid) {
+ if (sd->func[1]) {
+ /* register and unmask irq */
+ sdio_claim_host(sd->func[1]);
+ sdio_release_irq(sd->func[1]);
+ sdio_release_host(sd->func[1]);
+ }
+
+ if (sd->func[2]) {
+ /* Claim host controller F2 */
+ sdio_claim_host(sd->func[2]);
+ sdio_release_irq(sd->func[2]);
+ /* Release host controller F2 */
+ sdio_release_host(sd->func[2]);
+ }
+
+ sd->intr_handler_valid = FALSE;
+ sd->intr_handler = NULL;
+ sd->intr_handler_arg = NULL;
+ } OOB_PARAM_ELSE()
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+ {
+ sdioh_disable_func_intr(sd);
+ }
+#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
+ return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
+{
+ sd_trace(("%s: Entering\n", __FUNCTION__));
+ *onoff = sd->client_intr_enabled;
+ return SDIOH_API_RC_SUCCESS;
+}
+
+#if defined(DHD_DEBUG)
+extern bool
+sdioh_interrupt_pending(sdioh_info_t *sd)
+{
+ return (0);
+}
+#endif
+
+uint
+sdioh_query_iofnum(sdioh_info_t *sd)
+{
+ return sd->num_funcs;
+}
+
+/* IOVar table */
+enum {
+ IOV_MSGLEVEL = 1,
+ IOV_BLOCKMODE,
+ IOV_BLOCKSIZE,
+ IOV_DMA,
+ IOV_USEINTS,
+ IOV_NUMINTS,
+ IOV_NUMLOCALINTS,
+ IOV_HOSTREG,
+ IOV_DEVREG,
+ IOV_DIVISOR,
+ IOV_SDMODE,
+ IOV_HISPEED,
+ IOV_HCIREGS,
+ IOV_POWER,
+ IOV_CLOCK,
+ IOV_RXCHAIN
+};
+
+const bcm_iovar_t sdioh_iovars[] = {
+ {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
+ {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0 },
+ {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */
+ {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 },
+ {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 },
+ {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 },
+ {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 },
+ {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
+ {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
+ {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 },
+ {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 },
+ {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 },
+ {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100},
+ {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0 },
+ {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0 },
+ {NULL, 0, 0, 0, 0 }
+};
+
+int
+sdioh_iovar_op(sdioh_info_t *si, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
+{
+ const bcm_iovar_t *vi = NULL;
+ int bcmerror = 0;
+ int val_size;
+ int32 int_val = 0;
+ bool bool_val;
+ uint32 actionid;
+
+ ASSERT(name);
+ ASSERT(len >= 0);
+
+ /* Get must have return space; Set does not take qualifiers */
+ ASSERT(set || (arg && len));
+ ASSERT(!set || (!params && !plen));
+
+ sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
+
+ if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
+ bcmerror = BCME_UNSUPPORTED;
+ goto exit;
+ }
+
+ if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
+ goto exit;
+
+ /* Set up params so get and set can share the convenience variables */
+ if (params == NULL) {
+ params = arg;
+ plen = len;
+ }
+
+ if (vi->type == IOVT_VOID)
+ val_size = 0;
+ else if (vi->type == IOVT_BUFFER)
+ val_size = len;
+ else
+ val_size = sizeof(int);
+
+ if (plen >= (int)sizeof(int_val))
+ bcopy(params, &int_val, sizeof(int_val));
+
+ bool_val = (int_val != 0) ? TRUE : FALSE;
+ BCM_REFERENCE(bool_val);
+
+ actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+ switch (actionid) {
+ case IOV_GVAL(IOV_MSGLEVEL):
+ int_val = (int32)sd_msglevel;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_MSGLEVEL):
+ sd_msglevel = int_val;
+ break;
+
+ case IOV_GVAL(IOV_BLOCKMODE):
+ int_val = (int32)si->sd_blockmode;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_BLOCKMODE):
+ si->sd_blockmode = (bool)int_val;
+ /* Haven't figured out how to make non-block mode with DMA */
+ break;
+
+ case IOV_GVAL(IOV_BLOCKSIZE):
+ if ((uint32)int_val > si->num_funcs) {
+ bcmerror = BCME_BADARG;
+ break;
+ }
+ int_val = (int32)si->client_block_size[int_val];
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_BLOCKSIZE):
+ {
+ uint func = ((uint32)int_val >> 16);
+ uint blksize = (uint16)int_val;
+ uint maxsize;
+
+ if (func > si->num_funcs) {
+ bcmerror = BCME_BADARG;
+ break;
+ }
+
+ switch (func) {
+ case 0: maxsize = 32; break;
+ case 1: maxsize = BLOCK_SIZE_4318; break;
+ case 2: maxsize = BLOCK_SIZE_4328; break;
+ default: maxsize = 0;
+ }
+ if (blksize > maxsize) {
+ bcmerror = BCME_BADARG;
+ break;
+ }
+ if (!blksize) {
+ blksize = maxsize;
+ }
+
+ /* Now set it */
+ si->client_block_size[func] = blksize;
+
+ break;
+ }
+
+ case IOV_GVAL(IOV_RXCHAIN):
+ int_val = (int32)si->use_rxchain;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_DMA):
+ int_val = (int32)si->sd_use_dma;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DMA):
+ si->sd_use_dma = (bool)int_val;
+ break;
+
+ case IOV_GVAL(IOV_USEINTS):
+ int_val = (int32)si->use_client_ints;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_USEINTS):
+ si->use_client_ints = (bool)int_val;
+ if (si->use_client_ints)
+ si->intmask |= CLIENT_INTR;
+ else
+ si->intmask &= ~CLIENT_INTR;
+
+ break;
+
+ case IOV_GVAL(IOV_DIVISOR):
+ int_val = (uint32)sd_divisor;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DIVISOR):
+ sd_divisor = int_val;
+ break;
+
+ case IOV_GVAL(IOV_POWER):
+ int_val = (uint32)sd_power;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_POWER):
+ sd_power = int_val;
+ break;
+
+ case IOV_GVAL(IOV_CLOCK):
+ int_val = (uint32)sd_clock;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_CLOCK):
+ sd_clock = int_val;
+ break;
+
+ case IOV_GVAL(IOV_SDMODE):
+ int_val = (uint32)sd_sdmode;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_SDMODE):
+ sd_sdmode = int_val;
+ break;
+
+ case IOV_GVAL(IOV_HISPEED):
+ int_val = (uint32)sd_hiok;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_HISPEED):
+ sd_hiok = int_val;
+ break;
+
+ case IOV_GVAL(IOV_NUMINTS):
+ int_val = (int32)si->intrcount;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_NUMLOCALINTS):
+ int_val = (int32)0;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_HOSTREG):
+ {
+ sdreg_t *sd_ptr = (sdreg_t *)params;
+
+ if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) {
+ sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset));
+ bcmerror = BCME_BADARG;
+ break;
+ }
+
+ sd_trace(("%s: rreg%d at offset %d\n", __FUNCTION__,
+ (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32),
+ sd_ptr->offset));
+ if (sd_ptr->offset & 1)
+ int_val = 8; /* sdioh_sdmmc_rreg8(si, sd_ptr->offset); */
+ else if (sd_ptr->offset & 2)
+ int_val = 16; /* sdioh_sdmmc_rreg16(si, sd_ptr->offset); */
+ else
+ int_val = 32; /* sdioh_sdmmc_rreg(si, sd_ptr->offset); */
+
+ bcopy(&int_val, arg, sizeof(int_val));
+ break;
+ }
+
+ case IOV_SVAL(IOV_HOSTREG):
+ {
+ sdreg_t *sd_ptr = (sdreg_t *)params;
+
+ if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) {
+ sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset));
+ bcmerror = BCME_BADARG;
+ break;
+ }
+
+ sd_trace(("%s: wreg%d value 0x%08x at offset %d\n", __FUNCTION__, sd_ptr->value,
+ (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32),
+ sd_ptr->offset));
+ break;
+ }
+
+ case IOV_GVAL(IOV_DEVREG):
+ {
+ sdreg_t *sd_ptr = (sdreg_t *)params;
+ uint8 data = 0;
+
+ if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) {
+ bcmerror = BCME_SDIO_ERROR;
+ break;
+ }
+
+ int_val = (int)data;
+ bcopy(&int_val, arg, sizeof(int_val));
+ break;
+ }
+
+ case IOV_SVAL(IOV_DEVREG):
+ {
+ sdreg_t *sd_ptr = (sdreg_t *)params;
+ uint8 data = (uint8)sd_ptr->value;
+
+ if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) {
+ bcmerror = BCME_SDIO_ERROR;
+ break;
+ }
+ break;
+ }
+
+ default:
+ bcmerror = BCME_UNSUPPORTED;
+ break;
+ }
+exit:
+
+ return bcmerror;
+}
+
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+
+SDIOH_API_RC
+sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
+{
+ SDIOH_API_RC status;
+ uint8 data;
+
+ if (enable)
+ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI;
+ else
+ data = SDIO_SEPINT_ACT_HI; /* disable hw oob interrupt */
+
+ status = sdioh_request_byte(sd, SDIOH_WRITE, 0, SDIOD_CCCR_BRCM_SEPINT, &data);
+ return status;
+}
+#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
+
+extern SDIOH_API_RC
+sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
+{
+ SDIOH_API_RC status;
+ /* No lock needed since sdioh_request_byte does locking */
+ status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
+ return status;
+}
+
+extern SDIOH_API_RC
+sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
+{
+ /* No lock needed since sdioh_request_byte does locking */
+ SDIOH_API_RC status;
+ status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
+ return status;
+}
+
+static int
+sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr)
+{
+ /* read 24 bits and return valid 17 bit addr */
+ int i;
+ uint32 scratch, regdata;
+ uint8 *ptr = (uint8 *)&scratch;
+ for (i = 0; i < 3; i++) {
+ if ((sdioh_sdmmc_card_regread (sd, 0, regaddr, 1, &regdata)) != SUCCESS)
+ sd_err(("%s: Can't read!\n", __FUNCTION__));
+
+ *ptr++ = (uint8) regdata;
+ regaddr++;
+ }
+
+ /* Only the lower 17-bits are valid */
+ scratch = ltoh32(scratch);
+ scratch &= 0x0001FFFF;
+ return (scratch);
+}
+
+extern SDIOH_API_RC
+sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
+{
+ uint32 count;
+ int offset;
+ uint32 foo;
+ uint8 *cis = cisd;
+
+ sd_trace(("%s: Func = %d\n", __FUNCTION__, func));
+
+ if (!sd->func_cis_ptr[func]) {
+ bzero(cis, length);
+ sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__, func));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__, func, sd->func_cis_ptr[func]));
+
+ for (count = 0; count < length; count++) {
+ offset = sd->func_cis_ptr[func] + count;
+ if (sdioh_sdmmc_card_regread (sd, 0, offset, 1, &foo) < 0) {
+ sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ *cis = (uint8)(foo & 0xff);
+ cis++;
+ }
+
+ return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
+{
+ int err_ret = 0;
+#if defined(MMC_SDIO_ABORT)
+ int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
+#endif
+
+ sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr));
+
+ DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
+ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+ if(rw) { /* CMD52 Write */
+ if (func == 0) {
+ /* Can only directly write to some F0 registers. Handle F2 enable
+ * as a special case.
+ */
+ if (regaddr == SDIOD_CCCR_IOEN) {
+ if (sd->func[2]) {
+ sdio_claim_host(sd->func[2]);
+ if (*byte & SDIO_FUNC_ENABLE_2) {
+ /* Enable Function 2 */
+ err_ret = sdio_enable_func(sd->func[2]);
+ if (err_ret) {
+ sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
+ err_ret));
+ }
+ } else {
+ /* Disable Function 2 */
+ err_ret = sdio_disable_func(sd->func[2]);
+ if (err_ret) {
+ sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
+ err_ret));
+ }
+ }
+ sdio_release_host(sd->func[2]);
+ }
+ }
+#if defined(MMC_SDIO_ABORT)
+ /* to allow abort command through F1 */
+ else if (regaddr == SDIOD_CCCR_IOABORT) {
+ while (sdio_abort_retry--) {
+ if (sd->func[func]) {
+ sdio_claim_host(sd->func[func]);
+ /*
+ * this sdio_f0_writeb() can be replaced with
+ * another api depending upon MMC driver change.
+ * As of this time, this is temporaray one
+ */
+ sdio_writeb(sd->func[func],
+ *byte, regaddr, &err_ret);
+ sdio_release_host(sd->func[func]);
+ }
+ if (!err_ret)
+ break;
+ }
+ }
+#endif /* MMC_SDIO_ABORT */
+ else if (regaddr < 0xF0) {
+ sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
+ } else {
+ /* Claim host controller, perform F0 write, and release */
+ if (sd->func[func]) {
+ sdio_claim_host(sd->func[func]);
+ sdio_f0_writeb(sd->func[func],
+ *byte, regaddr, &err_ret);
+ sdio_release_host(sd->func[func]);
+ }
+ }
+ } else {
+ /* Claim host controller, perform Fn write, and release */
+ if (sd->func[func]) {
+ sdio_claim_host(sd->func[func]);
+ sdio_writeb(sd->func[func], *byte, regaddr, &err_ret);
+ sdio_release_host(sd->func[func]);
+ }
+ }
+ } else { /* CMD52 Read */
+ /* Claim host controller, perform Fn read, and release */
+ if (sd->func[func]) {
+ sdio_claim_host(sd->func[func]);
+ if (func == 0) {
+ *byte = sdio_f0_readb(sd->func[func], regaddr, &err_ret);
+ } else {
+ *byte = sdio_readb(sd->func[func], regaddr, &err_ret);
+ }
+ sdio_release_host(sd->func[func]);
+ }
+ }
+
+ if (err_ret) {
+ if ((regaddr == 0x1001F) && ((err_ret == -ETIMEDOUT) || (err_ret == -EILSEQ))) {
+ } else {
+ sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
+ rw ? "Write" : "Read", func, regaddr, *byte, err_ret));
+ }
+ }
+
+ return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+}
+
+extern SDIOH_API_RC
+sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
+ uint32 *word, uint nbytes)
+{
+ int err_ret = SDIOH_API_RC_FAIL;
+#if defined(MMC_SDIO_ABORT)
+ int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
+#endif
+
+ if (func == 0) {
+ sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
+ __FUNCTION__, cmd_type, rw, func, addr, nbytes));
+
+ DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
+ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+ /* Claim host controller */
+ sdio_claim_host(sd->func[func]);
+
+ if(rw) { /* CMD52 Write */
+ if (nbytes == 4) {
+ sdio_writel(sd->func[func], *word, addr, &err_ret);
+ } else if (nbytes == 2) {
+ sdio_writew(sd->func[func], (*word & 0xFFFF), addr, &err_ret);
+ } else {
+ sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
+ }
+ } else { /* CMD52 Read */
+ if (nbytes == 4) {
+ *word = sdio_readl(sd->func[func], addr, &err_ret);
+ } else if (nbytes == 2) {
+ *word = sdio_readw(sd->func[func], addr, &err_ret) & 0xFFFF;
+ } else {
+ sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
+ }
+ }
+
+ /* Release host controller */
+ sdio_release_host(sd->func[func]);
+
+ if (err_ret) {
+#if defined(MMC_SDIO_ABORT)
+ /* Any error on CMD53 transaction should abort that function using function 0. */
+ while (sdio_abort_retry--) {
+ if (sd->func[0]) {
+ sdio_claim_host(sd->func[0]);
+ /*
+ * this sdio_f0_writeb() can be replaced with another api
+ * depending upon MMC driver change.
+ * As of this time, this is temporaray one
+ */
+ sdio_writeb(sd->func[0],
+ func, SDIOD_CCCR_IOABORT, &err_ret);
+ sdio_release_host(sd->func[0]);
+ }
+ if (!err_ret)
+ break;
+ }
+ if (err_ret)
+#endif /* MMC_SDIO_ABORT */
+ {
+ sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
+ rw ? "Write" : "Read", err_ret));
+ }
+ }
+
+ return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+}
+
+#ifdef BCMSDIOH_TXGLOM
+static SDIOH_API_RC
+sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
+ uint addr, void *pkt)
+{
+ bool fifo = (fix_inc == SDIOH_DATA_FIX);
+ int err_ret = 0;
+ void *pnext;
+ uint ttl_len, pkt_offset;
+ uint blk_num;
+ uint blk_size;
+ uint max_blk_count;
+ uint max_req_size;
+ struct mmc_request mmc_req;
+ struct mmc_command mmc_cmd;
+ struct mmc_data mmc_dat;
+ uint32 sg_count;
+ struct sdio_func *sdio_func = sd->func[func];
+ struct mmc_host *host = sdio_func->card->host;
+
+ sd_trace(("%s: Enter\n", __FUNCTION__));
+ ASSERT(pkt);
+ DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
+ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+
+ blk_size = sd->client_block_size[func];
+ max_blk_count = min(host->max_blk_count, (uint)MAX_IO_RW_EXTENDED_BLK);
+ max_req_size = min(max_blk_count * blk_size, host->max_req_size);
+
+ pkt_offset = 0;
+ pnext = pkt;
+
+ while (pnext != NULL) {
+ ttl_len = 0;
+ sg_count = 0;
+ memset(&mmc_req, 0, sizeof(struct mmc_request));
+ memset(&mmc_cmd, 0, sizeof(struct mmc_command));
+ memset(&mmc_dat, 0, sizeof(struct mmc_data));
+ sg_init_table(sd->sg_list, ARRAYSIZE(sd->sg_list));
+
+ /* Set up scatter-gather DMA descriptors. this loop is to find out the max
+ * data we can transfer with one command 53. blocks per command is limited by
+ * host max_req_size and 9-bit max block number. when the total length of this
+ * packet chain is bigger than max_req_size, use multiple SD_IO_RW_EXTENDED
+ * commands (each transfer is still block aligned)
+ */
+ while (pnext != NULL && ttl_len < max_req_size) {
+ int pkt_len;
+ int sg_data_size;
+ uint8 *pdata = (uint8*)PKTDATA(sd->osh, pnext);
+
+ ASSERT(pdata != NULL);
+ pkt_len = PKTLEN(sd->osh, pnext);
+ sd_trace(("%s[%d] data=%p, len=%d\n", __FUNCTION__, write, pdata, pkt_len));
+ /* sg_count is unlikely larger than the array size, and this is
+ * NOT something we can handle here, but in case it happens, PLEASE put
+ * a restriction on max tx/glom count (based on host->max_segs).
+ */
+ if (sg_count >= ARRAYSIZE(sd->sg_list)) {
+ sd_err(("%s: sg list entries exceed limit\n", __FUNCTION__));
+ return (SDIOH_API_RC_FAIL);
+ }
+ pdata += pkt_offset;
+
+ sg_data_size = pkt_len - pkt_offset;
+ if (sg_data_size > max_req_size - ttl_len)
+ sg_data_size = max_req_size - ttl_len;
+ /* some platforms put a restriction on the data size of each scatter-gather
+ * DMA descriptor, use multiple sg buffers when xfer_size is bigger than
+ * max_seg_size
+ */
+ if (sg_data_size > host->max_seg_size)
+ sg_data_size = host->max_seg_size;
+ sg_set_buf(&sd->sg_list[sg_count++], pdata, sg_data_size);
+
+ ttl_len += sg_data_size;
+ pkt_offset += sg_data_size;
+ if (pkt_offset == pkt_len) {
+ pnext = PKTNEXT(sd->osh, pnext);
+ pkt_offset = 0;
+ }
+ }
+
+ if (ttl_len % blk_size != 0) {
+ sd_err(("%s, data length %d not aligned to block size %d\n",
+ __FUNCTION__, ttl_len, blk_size));
+ return SDIOH_API_RC_FAIL;
+ }
+ blk_num = ttl_len / blk_size;
+ mmc_dat.sg = sd->sg_list;
+ mmc_dat.sg_len = sg_count;
+ mmc_dat.blksz = blk_size;
+ mmc_dat.blocks = blk_num;
+ mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+ mmc_cmd.opcode = 53; /* SD_IO_RW_EXTENDED */
+ mmc_cmd.arg = write ? 1<<31 : 0;
+ mmc_cmd.arg |= (func & 0x7) << 28;
+ mmc_cmd.arg |= 1<<27;
+ mmc_cmd.arg |= fifo ? 0 : 1<<26;
+ mmc_cmd.arg |= (addr & 0x1FFFF) << 9;
+ mmc_cmd.arg |= blk_num & 0x1FF;
+ mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+ mmc_req.cmd = &mmc_cmd;
+ mmc_req.data = &mmc_dat;
+ if (!fifo)
+ addr += ttl_len;
+
+ sdio_claim_host(sdio_func);
+ mmc_set_data_timeout(&mmc_dat, sdio_func->card);
+ mmc_wait_for_req(host, &mmc_req);
+ sdio_release_host(sdio_func);
+
+ err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error;
+ if (0 != err_ret) {
+ sd_err(("%s:CMD53 %s failed with code %d\n",
+ __FUNCTION__, write ? "write" : "read", err_ret));
+ return SDIOH_API_RC_FAIL;
+ }
+ }
+
+ sd_trace(("%s: Exit\n", __FUNCTION__));
+ return SDIOH_API_RC_SUCCESS;
+}
+#endif /* BCMSDIOH_TXGLOM */
+
+static SDIOH_API_RC
+sdioh_buffer_tofrom_bus(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
+ uint addr, uint8 *buf, uint len)
+{
+ bool fifo = (fix_inc == SDIOH_DATA_FIX);
+ int err_ret = 0;
+
+ sd_trace(("%s: Enter\n", __FUNCTION__));
+ ASSERT(buf);
+
+ /* NOTE:
+ * For all writes, each packet length is aligned to 32 (or 4)
+ * bytes in dhdsdio_txpkt_preprocess, and for glom the last packet length
+ * is aligned to block boundary. If you want to align each packet to
+ * a custom size, please do it in dhdsdio_txpkt_preprocess, NOT here
+ *
+ * For reads, the alignment is doen in sdioh_request_buffer.
+ *
+ */
+ sdio_claim_host(sd->func[func]);
+
+ if ((write) && (!fifo))
+ err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, len);
+ else if (write)
+ err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, len);
+ else if (fifo)
+ err_ret = sdio_readsb(sd->func[func], buf, addr, len);
+ else
+ err_ret = sdio_memcpy_fromio(sd->func[func], buf, addr, len);
+
+ sdio_release_host(sd->func[func]);
+
+ if (err_ret)
+ sd_err(("%s: %s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=%d\n", __FUNCTION__,
+ (write) ? "TX" : "RX", buf, addr, len, err_ret));
+ else
+ sd_trace(("%s: %s xfr'd %p, addr=0x%05x, len=%d\n", __FUNCTION__,
+ (write) ? "TX" : "RX", buf, addr, len));
+
+ sd_trace(("%s: Exit\n", __FUNCTION__));
+ return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+}
+
+
+/*
+ * This function takes a buffer or packet, and fixes everything up so that in the
+ * end, a DMA-able packet is created.
+ *
+ * A buffer does not have an associated packet pointer, and may or may not be aligned.
+ * A packet may consist of a single packet, or a packet chain. If it is a packet chain,
+ * then all the packets in the chain must be properly aligned. If the packet data is not
+ * aligned, then there may only be one packet, and in this case, it is copied to a new
+ * aligned packet.
+ *
+ */
+extern SDIOH_API_RC
+sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, uint func,
+ uint addr, uint reg_width, uint buf_len, uint8 *buffer, void *pkt)
+{
+ SDIOH_API_RC status;
+ void *tmppkt;
+
+ sd_trace(("%s: Enter\n", __FUNCTION__));
+ DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
+ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+
+ if (pkt) {
+#ifdef BCMSDIOH_TXGLOM
+ /* packet chain, only used for tx/rx glom, all packets length
+ * are aligned, total length is a block multiple
+ */
+ if (PKTNEXT(sd->osh, pkt))
+ return sdioh_request_packet_chain(sd, fix_inc, write, func, addr, pkt);
+#endif /* BCMSDIOH_TXGLOM */
+ /* non-glom mode, ignore the buffer parameter and use the packet pointer
+ * (this shouldn't happen)
+ */
+ buffer = PKTDATA(sd->osh, pkt);
+ buf_len = PKTLEN(sd->osh, pkt);
+ }
+
+ ASSERT(buffer);
+
+ /* buffer and length are aligned, use it directly so we can avoid memory copy */
+ if (((ulong)buffer & DMA_ALIGN_MASK) == 0 && (buf_len & DMA_ALIGN_MASK) == 0)
+ return sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr, buffer, buf_len);
+
+ sd_err(("%s: [%d] doing memory copy buf=%p, len=%d\n",
+ __FUNCTION__, write, buffer, buf_len));
+
+ /* otherwise, a memory copy is needed as the input buffer is not aligned */
+ tmppkt = PKTGET_STATIC(sd->osh, buf_len + DEFAULT_SDIO_F2_BLKSIZE, write ? TRUE : FALSE);
+ if (tmppkt == NULL) {
+ sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, buf_len));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ if (write)
+ bcopy(buffer, PKTDATA(sd->osh, tmppkt), buf_len);
+
+ status = sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr,
+ PKTDATA(sd->osh, tmppkt), ROUNDUP(buf_len, (DMA_ALIGN_MASK+1)));
+
+ if (!write)
+ bcopy(PKTDATA(sd->osh, tmppkt), buffer, buf_len);
+
+ PKTFREE_STATIC(sd->osh, tmppkt, write ? TRUE : FALSE);
+
+ return status;
+}
+
+/* this function performs "abort" for both of host & device */
+extern int
+sdioh_abort(sdioh_info_t *sd, uint func)
+{
+#if defined(MMC_SDIO_ABORT)
+ char t_func = (char) func;
+#endif /* defined(MMC_SDIO_ABORT) */
+ sd_trace(("%s: Enter\n", __FUNCTION__));
+
+#if defined(MMC_SDIO_ABORT)
+ /* issue abort cmd52 command through F1 */
+ sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, &t_func);
+#endif /* defined(MMC_SDIO_ABORT) */
+
+ sd_trace(("%s: Exit\n", __FUNCTION__));
+ return SDIOH_API_RC_SUCCESS;
+}
+
+/* Reset and re-initialize the device */
+int sdioh_sdio_reset(sdioh_info_t *si)
+{
+ sd_trace(("%s: Enter\n", __FUNCTION__));
+ sd_trace(("%s: Exit\n", __FUNCTION__));
+ return SDIOH_API_RC_SUCCESS;
+}
+
+/* Disable device interrupt */
+void
+sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
+{
+ sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
+ sd->intmask &= ~CLIENT_INTR;
+}
+
+/* Enable device interrupt */
+void
+sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
+{
+ sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
+ sd->intmask |= CLIENT_INTR;
+}
+
+/* Read client card reg */
+int
+sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
+{
+
+ if ((func == 0) || (regsize == 1)) {
+ uint8 temp = 0;
+
+ sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
+ *data = temp;
+ *data &= 0xff;
+ sd_data(("%s: byte read data=0x%02x\n",
+ __FUNCTION__, *data));
+ } else {
+ sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, regsize);
+ if (regsize == 2)
+ *data &= 0xffff;
+
+ sd_data(("%s: word read data=0x%08x\n",
+ __FUNCTION__, *data));
+ }
+
+ return SUCCESS;
+}
+
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+/* bcmsdh_sdmmc interrupt handler */
+static void IRQHandler(struct sdio_func *func)
+{
+ sdioh_info_t *sd;
+
+ sd = sdio_get_drvdata(func);
+
+ ASSERT(sd != NULL);
+ sdio_release_host(sd->func[0]);
+
+ if (sd->use_client_ints) {
+ sd->intrcount++;
+ ASSERT(sd->intr_handler);
+ ASSERT(sd->intr_handler_arg);
+ (sd->intr_handler)(sd->intr_handler_arg);
+ } else {
+ sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
+
+ sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
+ __FUNCTION__, sd->client_intr_enabled, sd->intr_handler));
+ }
+
+ sdio_claim_host(sd->func[0]);
+}
+
+/* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
+static void IRQHandlerF2(struct sdio_func *func)
+{
+ sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
+}
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+
+#ifdef NOTUSED
+/* Write client card reg */
+static int
+sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
+{
+
+ if ((func == 0) || (regsize == 1)) {
+ uint8 temp;
+
+ temp = data & 0xff;
+ sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
+ sd_data(("%s: byte write data=0x%02x\n",
+ __FUNCTION__, data));
+ } else {
+ if (regsize == 2)
+ data &= 0xffff;
+
+ sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data, regsize);
+
+ sd_data(("%s: word write data=0x%08x\n",
+ __FUNCTION__, data));
+ }
+
+ return SUCCESS;
+}
+#endif /* NOTUSED */
+
+int
+sdioh_start(sdioh_info_t *sd, int stage)
+{
+ int ret;
+
+ if (!sd) {
+ sd_err(("%s Failed, sd is NULL\n", __FUNCTION__));
+ return (0);
+ }
+
+ /* Need to do this stages as we can't enable the interrupt till
+ downloading of the firmware is complete, other wise polling
+ sdio access will come in way
+ */
+ if (sd->func[0]) {
+ if (stage == 0) {
+ /* Since the power to the chip is killed, we will have
+ re enumerate the device again. Set the block size
+ and enable the fucntion 1 for in preparation for
+ downloading the code
+ */
+ /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux
+ 2.6.27. The implementation prior to that is buggy, and needs broadcom's
+ patch for it
+ */
+ if ((ret = sdio_reset_comm(sd->func[0]->card))) {
+ sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
+ return ret;
+ }
+ else {
+ sd->num_funcs = 2;
+ sd->sd_blockmode = TRUE;
+ sd->use_client_ints = TRUE;
+ sd->client_block_size[0] = 64;
+
+ if (sd->func[1]) {
+ /* Claim host controller */
+ sdio_claim_host(sd->func[1]);
+
+ sd->client_block_size[1] = 64;
+ ret = sdio_set_block_size(sd->func[1], 64);
+ if (ret) {
+ sd_err(("bcmsdh_sdmmc: Failed to set F1 "
+ "blocksize(%d)\n", ret));
+ }
+
+ /* Release host controller F1 */
+ sdio_release_host(sd->func[1]);
+ }
+
+ if (sd->func[2]) {
+ /* Claim host controller F2 */
+ sdio_claim_host(sd->func[2]);
+
+ sd->client_block_size[2] = sd_f2_blocksize;
+ ret = sdio_set_block_size(sd->func[2], sd_f2_blocksize);
+ if (ret) {
+ sd_err(("bcmsdh_sdmmc: Failed to set F2 "
+ "blocksize to %d(%d)\n", sd_f2_blocksize, ret));
+ }
+
+ /* Release host controller F2 */
+ sdio_release_host(sd->func[2]);
+ }
+
+ sdioh_sdmmc_card_enablefuncs(sd);
+ }
+ } else {
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+ OOB_PARAM_IF(sdioh_get_oob_disable(sd)) {
+ sdio_claim_host(sd->func[0]);
+ if (sd->func[2])
+ sdio_claim_irq(sd->func[2], IRQHandlerF2);
+ if (sd->func[1])
+ sdio_claim_irq(sd->func[1], IRQHandler);
+ sdio_release_host(sd->func[0]);
+ } OOB_PARAM_ELSE()
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+#if defined(OOB_INTR_ONLY)
+ {
+#if defined(HW_OOB)
+ sdioh_enable_func_intr(sd);
+#endif /* defined(HW_OOB) */
+ bcmsdh_oob_intr_set(sd->bcmsdh, TRUE);
+ }
+#endif /* defined(OOB_INTR_ONLY) */
+ }
+ }
+ else
+ sd_err(("%s Failed\n", __FUNCTION__));
+
+ return (0);
+}
+
+int
+sdioh_stop(sdioh_info_t *sd)
+{
+ /* MSM7201A Android sdio stack has bug with interrupt
+ So internaly within SDIO stack they are polling
+ which cause issue when device is turned off. So
+ unregister interrupt with SDIO stack to stop the
+ polling
+ */
+ if (sd->func[0]) {
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+ OOB_PARAM_IF(sdioh_get_oob_disable(sd)) {
+ sdio_claim_host(sd->func[0]);
+ if (sd->func[1])
+ sdio_release_irq(sd->func[1]);
+ if (sd->func[2])
+ sdio_release_irq(sd->func[2]);
+ sdio_release_host(sd->func[0]);
+ } OOB_PARAM_ELSE()
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+#if defined(OOB_INTR_ONLY)
+ {
+#if defined(HW_OOB)
+ sdioh_disable_func_intr(sd);
+#endif
+ bcmsdh_oob_intr_set(sd->bcmsdh, FALSE);
+ }
+#endif /* defined(OOB_INTR_ONLY) */
+ }
+ else
+ sd_err(("%s Failed\n", __FUNCTION__));
+ return (0);
+}
+
+int
+sdioh_waitlockfree(sdioh_info_t *sd)
+{
+ return (1);
+}
+
+
+SDIOH_API_RC
+sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio)
+{
+ return SDIOH_API_RC_FAIL;
+}
+
+SDIOH_API_RC
+sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab)
+{
+ return SDIOH_API_RC_FAIL;
+}
+
+bool
+sdioh_gpioin(sdioh_info_t *sd, uint32 gpio)
+{
+ return FALSE;
+}
+
+SDIOH_API_RC
+sdioh_gpio_init(sdioh_info_t *sd)
+{
+ return SDIOH_API_RC_FAIL;
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
new file mode 100644
index 000000000000..f4af5d7ab860
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
@@ -0,0 +1,405 @@
+/*
+ * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdh_sdmmc_linux.c 662758 2016-11-10 08:03:26Z $
+ */
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <sdio.h> /* SDIO Device and Protocol Specs */
+#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
+#include <sdiovar.h> /* to get msglevel bit values */
+
+#include <linux/sched.h> /* request_irq() */
+
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <dhd_linux.h>
+#include <bcmsdh_sdmmc.h>
+#include <dhd_dbg.h>
+
+#if !defined(SDIO_VENDOR_ID_BROADCOM)
+#define SDIO_VENDOR_ID_BROADCOM 0x02d0
+#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */
+
+#define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000
+
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
+#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
+#define SDIO_DEVICE_ID_BROADCOM_4325 0x0493
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
+#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
+#define SDIO_DEVICE_ID_BROADCOM_4319 0x4319
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4319) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4330)
+#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4330) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4334)
+#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4334) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4324)
+#define SDIO_DEVICE_ID_BROADCOM_4324 0x4324
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4324) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_43239)
+#define SDIO_DEVICE_ID_BROADCOM_43239 43239
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_43239) */
+
+extern void wl_cfg80211_set_parent_dev(void *dev);
+extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
+extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
+extern void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bus_type,
+ uint bus_num, uint slot_num);
+extern int bcmsdh_remove(bcmsdh_info_t *bcmsdh);
+
+int sdio_function_init(void);
+void sdio_function_cleanup(void);
+
+#define DESCRIPTION "bcmsdh_sdmmc Driver"
+#define AUTHOR "Broadcom Corporation"
+
+/* module param defaults */
+static int clockoverride = 0;
+
+module_param(clockoverride, int, 0644);
+MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
+
+/* Maximum number of bcmsdh_sdmmc devices supported by driver */
+#define BCMSDH_SDMMC_MAX_DEVICES 1
+
+extern volatile bool dhd_mmc_suspend;
+
+static int sdioh_probe(struct sdio_func *func)
+{
+ int host_idx = func->card->host->index;
+ uint32 rca = func->card->rca;
+ wifi_adapter_info_t *adapter;
+ osl_t *osh = NULL;
+ sdioh_info_t *sdioh = NULL;
+
+ sd_err(("bus num (host idx)=%d, slot num (rca)=%d\n", host_idx, rca));
+ adapter = dhd_wifi_platform_get_adapter(SDIO_BUS, host_idx, rca);
+ if (adapter != NULL)
+ sd_err(("found adapter info '%s'\n", adapter->name));
+ else
+ sd_err(("can't find adapter info for this chip\n"));
+
+#ifdef WL_CFG80211
+ wl_cfg80211_set_parent_dev(&func->dev);
+#endif
+
+ /* allocate SDIO Host Controller state info */
+ osh = osl_attach(&func->dev, SDIO_BUS, TRUE);
+ if (osh == NULL) {
+ sd_err(("%s: osl_attach failed\n", __FUNCTION__));
+ goto fail;
+ }
+ osl_static_mem_init(osh, adapter);
+ sdioh = sdioh_attach(osh, func);
+ if (sdioh == NULL) {
+ sd_err(("%s: sdioh_attach failed\n", __FUNCTION__));
+ goto fail;
+ }
+ sdioh->bcmsdh = bcmsdh_probe(osh, &func->dev, sdioh, adapter, SDIO_BUS, host_idx, rca);
+ if (sdioh->bcmsdh == NULL) {
+ sd_err(("%s: bcmsdh_probe failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+ sdio_set_drvdata(func, sdioh);
+ return 0;
+
+fail:
+ if (sdioh != NULL)
+ sdioh_detach(osh, sdioh);
+ if (osh != NULL)
+ osl_detach(osh);
+ return -ENOMEM;
+}
+
+static void sdioh_remove(struct sdio_func *func)
+{
+ sdioh_info_t *sdioh;
+ osl_t *osh;
+
+ sdioh = sdio_get_drvdata(func);
+ if (sdioh == NULL) {
+ sd_err(("%s: error, no sdioh handler found\n", __FUNCTION__));
+ return;
+ }
+
+ osh = sdioh->osh;
+ bcmsdh_remove(sdioh->bcmsdh);
+ sdioh_detach(osh, sdioh);
+ osl_detach(osh);
+}
+
+static int bcmsdh_sdmmc_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ int ret = 0;
+
+ if (func == NULL)
+ return -EINVAL;
+
+ sd_err(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
+ sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
+ sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
+ sd_info(("sdio_device: 0x%04x\n", func->device));
+ sd_info(("Function#: 0x%04x\n", func->num));
+
+ /* 4318 doesn't have function 2 */
+ if ((func->num == 2) || (func->num == 1 && func->device == 0x4))
+ ret = sdioh_probe(func);
+
+ return ret;
+}
+
+static void bcmsdh_sdmmc_remove(struct sdio_func *func)
+{
+ if (func == NULL) {
+ sd_err(("%s is called with NULL SDIO function pointer\n", __FUNCTION__));
+ return;
+ }
+
+ sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
+ sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
+ sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
+ sd_info(("sdio_device: 0x%04x\n", func->device));
+ sd_info(("Function#: 0x%04x\n", func->num));
+
+ if ((func->num == 2) || (func->num == 1 && func->device == 0x4))
+ sdioh_remove(func);
+}
+
+/* devices we support, null terminated */
+static const struct sdio_device_id bcmsdh_sdmmc_ids[] = {
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4324) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43239) },
+ { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) },
+ { /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids);
+
+#ifdef OOB_PARAM
+uint
+sdioh_get_oob_disable(sdioh_info_t *sd)
+{
+ int host_idx = sd->func[0]->card->host->index;
+ uint32 rca = sd->func[0]->card->rca;
+ wifi_adapter_info_t *adapter;
+
+ adapter = dhd_wifi_platform_get_adapter(SDIO_BUS, host_idx, rca);
+
+ return adapter->oob_disable;
+}
+#endif /* OOB_PARAM */
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM)
+static int bcmsdh_sdmmc_suspend(struct device *pdev)
+{
+ int err;
+ sdioh_info_t *sdioh;
+ struct sdio_func *func = dev_to_sdio_func(pdev);
+ mmc_pm_flag_t sdio_flags;
+
+ sd_err(("%s Enter\n", __FUNCTION__));
+ if (func->num != 2)
+ return 0;
+
+ dhd_mmc_suspend = TRUE;
+ sdioh = sdio_get_drvdata(func);
+ err = bcmsdh_suspend(sdioh->bcmsdh);
+ if (err) {
+ dhd_mmc_suspend = FALSE;
+ return err;
+ }
+
+ sdio_flags = sdio_get_host_pm_caps(func);
+ if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
+ sd_err(("%s: can't keep power while host is suspended\n", __FUNCTION__));
+ dhd_mmc_suspend = FALSE;
+ return -EINVAL;
+ }
+
+ /* keep power while host suspended */
+ err = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+ if (err) {
+ sd_err(("%s: error while trying to keep power\n", __FUNCTION__));
+ dhd_mmc_suspend = FALSE;
+ return err;
+ }
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(sdioh_get_oob_disable(sdioh))) {
+ bcmsdh_oob_intr_set(sdioh->bcmsdh, FALSE);
+ }
+#endif
+ smp_mb();
+
+ return 0;
+}
+
+static int bcmsdh_sdmmc_resume(struct device *pdev)
+{
+ sdioh_info_t *sdioh;
+ struct sdio_func *func = dev_to_sdio_func(pdev);
+
+ sd_err(("%s Enter\n", __FUNCTION__));
+ if (func->num != 2)
+ return 0;
+
+ sdioh = sdio_get_drvdata(func);
+ dhd_mmc_suspend = FALSE;
+ bcmsdh_resume(sdioh->bcmsdh);
+
+ smp_mb();
+ return 0;
+}
+
+static const struct dev_pm_ops bcmsdh_sdmmc_pm_ops = {
+ .suspend = bcmsdh_sdmmc_suspend,
+ .resume = bcmsdh_sdmmc_resume,
+};
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */
+
+#if defined(BCMLXSDMMC)
+static struct semaphore *notify_semaphore = NULL;
+
+static int dummy_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ if (func && (func->num != 2)) {
+ return 0;
+ }
+
+ if (notify_semaphore)
+ up(notify_semaphore);
+ return 0;
+}
+
+static void dummy_remove(struct sdio_func *func)
+{
+}
+
+static struct sdio_driver dummy_sdmmc_driver = {
+ .probe = dummy_probe,
+ .remove = dummy_remove,
+ .name = "dummy_sdmmc",
+ .id_table = bcmsdh_sdmmc_ids,
+ };
+
+int sdio_func_reg_notify(void* semaphore)
+{
+ notify_semaphore = semaphore;
+ return sdio_register_driver(&dummy_sdmmc_driver);
+}
+
+void sdio_func_unreg_notify(void)
+{
+ OSL_SLEEP(15);
+ sdio_unregister_driver(&dummy_sdmmc_driver);
+}
+
+#endif /* defined(BCMLXSDMMC) */
+
+static struct sdio_driver bcmsdh_sdmmc_driver = {
+ .probe = bcmsdh_sdmmc_probe,
+ .remove = bcmsdh_sdmmc_remove,
+ .name = "bcmsdh_sdmmc",
+ .id_table = bcmsdh_sdmmc_ids,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM)
+ .drv = {
+ .pm = &bcmsdh_sdmmc_pm_ops,
+ },
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */
+ };
+
+struct sdos_info {
+ sdioh_info_t *sd;
+ spinlock_t lock;
+};
+
+/* Interrupt enable/disable */
+SDIOH_API_RC
+sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
+{
+ if (!sd)
+ return BCME_BADARG;
+
+ sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling"));
+ return SDIOH_API_RC_SUCCESS;
+}
+
+#ifdef BCMSDH_MODULE
+static int __init
+bcmsdh_module_init(void)
+{
+ int error = 0;
+ error = sdio_function_init();
+ return error;
+}
+
+static void __exit
+bcmsdh_module_cleanup(void)
+{
+ sdio_function_cleanup();
+}
+
+module_init(bcmsdh_module_init);
+module_exit(bcmsdh_module_cleanup);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(DESCRIPTION);
+MODULE_AUTHOR(AUTHOR);
+
+#endif /* BCMSDH_MODULE */
+/*
+ * module init
+*/
+int bcmsdh_register_client_driver(void)
+{
+ return sdio_register_driver(&bcmsdh_sdmmc_driver);
+}
+
+/*
+ * module cleanup
+*/
+void bcmsdh_unregister_client_driver(void)
+{
+ sdio_unregister_driver(&bcmsdh_sdmmc_driver);
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c
new file mode 100644
index 000000000000..8343d3b9586e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c
@@ -0,0 +1,249 @@
+/*
+ * Broadcom SPI Host Controller Driver - Linux Per-port
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdspi_linux.c 406045 2013-06-05 22:09:52Z $
+ */
+
+#include <typedefs.h>
+#include <bcmutils.h>
+
+#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
+#include <sdiovar.h> /* to get msglevel bit values */
+
+#include <pcicfg.h>
+#include <sdio.h> /* SDIO Device and Protocol Specs */
+#include <linux/sched.h> /* request_irq(), free_irq() */
+#include <bcmsdspi.h>
+#include <bcmspi.h>
+
+extern uint sd_crc;
+module_param(sd_crc, uint, 0);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define KERNEL26
+#endif
+
+struct sdos_info {
+ sdioh_info_t *sd;
+ spinlock_t lock;
+ wait_queue_head_t intr_wait_queue;
+};
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define BLOCKABLE() (!in_atomic())
+#else
+#define BLOCKABLE() (!in_interrupt())
+#endif
+
+/* Interrupt handler */
+static irqreturn_t
+sdspi_isr(int irq, void *dev_id
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+, struct pt_regs *ptregs
+#endif
+)
+{
+ sdioh_info_t *sd;
+ struct sdos_info *sdos;
+ bool ours;
+
+ sd = (sdioh_info_t *)dev_id;
+ sd->local_intrcount++;
+
+ if (!sd->card_init_done) {
+ sd_err(("%s: Hey Bogus intr...not even initted: irq %d\n", __FUNCTION__, irq));
+ return IRQ_RETVAL(FALSE);
+ } else {
+ ours = spi_check_client_intr(sd, NULL);
+
+ /* For local interrupts, wake the waiting process */
+ if (ours && sd->got_hcint) {
+ sdos = (struct sdos_info *)sd->sdos_info;
+ wake_up_interruptible(&sdos->intr_wait_queue);
+ }
+
+ return IRQ_RETVAL(ours);
+ }
+}
+
+
+/* Register with Linux for interrupts */
+int
+spi_register_irq(sdioh_info_t *sd, uint irq)
+{
+ sd_trace(("Entering %s: irq == %d\n", __FUNCTION__, irq));
+ if (request_irq(irq, sdspi_isr, IRQF_SHARED, "bcmsdspi", sd) < 0) {
+ sd_err(("%s: request_irq() failed\n", __FUNCTION__));
+ return ERROR;
+ }
+ return SUCCESS;
+}
+
+/* Free Linux irq */
+void
+spi_free_irq(uint irq, sdioh_info_t *sd)
+{
+ free_irq(irq, sd);
+}
+
+/* Map Host controller registers */
+uint32 *
+spi_reg_map(osl_t *osh, uintptr addr, int size)
+{
+ return (uint32 *)REG_MAP(addr, size);
+}
+
+void
+spi_reg_unmap(osl_t *osh, uintptr addr, int size)
+{
+ REG_UNMAP((void*)(uintptr)addr);
+}
+
+int
+spi_osinit(sdioh_info_t *sd)
+{
+ struct sdos_info *sdos;
+
+ sdos = (struct sdos_info*)MALLOC(sd->osh, sizeof(struct sdos_info));
+ sd->sdos_info = (void*)sdos;
+ if (sdos == NULL)
+ return BCME_NOMEM;
+
+ sdos->sd = sd;
+ spin_lock_init(&sdos->lock);
+ init_waitqueue_head(&sdos->intr_wait_queue);
+ return BCME_OK;
+}
+
+void
+spi_osfree(sdioh_info_t *sd)
+{
+ struct sdos_info *sdos;
+ ASSERT(sd && sd->sdos_info);
+
+ sdos = (struct sdos_info *)sd->sdos_info;
+ MFREE(sd->osh, sdos, sizeof(struct sdos_info));
+}
+
+/* Interrupt enable/disable */
+SDIOH_API_RC
+sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
+{
+ ulong flags;
+ struct sdos_info *sdos;
+
+ sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling"));
+
+ sdos = (struct sdos_info *)sd->sdos_info;
+ ASSERT(sdos);
+
+ if (!(sd->host_init_done && sd->card_init_done)) {
+ sd_err(("%s: Card & Host are not initted - bailing\n", __FUNCTION__));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
+ sd_err(("%s: no handler registered, will not enable\n", __FUNCTION__));
+ return SDIOH_API_RC_FAIL;
+ }
+
+ /* Ensure atomicity for enable/disable calls */
+ spin_lock_irqsave(&sdos->lock, flags);
+
+ sd->client_intr_enabled = enable;
+ if (enable && !sd->lockcount)
+ spi_devintr_on(sd);
+ else
+ spi_devintr_off(sd);
+
+ spin_unlock_irqrestore(&sdos->lock, flags);
+
+ return SDIOH_API_RC_SUCCESS;
+}
+
+/* Protect against reentrancy (disable device interrupts while executing) */
+void
+spi_lock(sdioh_info_t *sd)
+{
+ ulong flags;
+ struct sdos_info *sdos;
+
+ sdos = (struct sdos_info *)sd->sdos_info;
+ ASSERT(sdos);
+
+ sd_trace(("%s: %d\n", __FUNCTION__, sd->lockcount));
+
+ spin_lock_irqsave(&sdos->lock, flags);
+ if (sd->lockcount) {
+ sd_err(("%s: Already locked!\n", __FUNCTION__));
+ ASSERT(sd->lockcount == 0);
+ }
+ spi_devintr_off(sd);
+ sd->lockcount++;
+ spin_unlock_irqrestore(&sdos->lock, flags);
+}
+
+/* Enable client interrupt */
+void
+spi_unlock(sdioh_info_t *sd)
+{
+ ulong flags;
+ struct sdos_info *sdos;
+
+ sd_trace(("%s: %d, %d\n", __FUNCTION__, sd->lockcount, sd->client_intr_enabled));
+ ASSERT(sd->lockcount > 0);
+
+ sdos = (struct sdos_info *)sd->sdos_info;
+ ASSERT(sdos);
+
+ spin_lock_irqsave(&sdos->lock, flags);
+ if (--sd->lockcount == 0 && sd->client_intr_enabled) {
+ spi_devintr_on(sd);
+ }
+ spin_unlock_irqrestore(&sdos->lock, flags);
+}
+
+void spi_waitbits(sdioh_info_t *sd, bool yield)
+{
+#ifndef BCMSDYIELD
+ ASSERT(!yield);
+#endif
+ sd_trace(("%s: yield %d canblock %d\n",
+ __FUNCTION__, yield, BLOCKABLE()));
+
+ /* Clear the "interrupt happened" flag and last intrstatus */
+ sd->got_hcint = FALSE;
+
+#ifdef BCMSDYIELD
+ if (yield && BLOCKABLE()) {
+ struct sdos_info *sdos;
+ sdos = (struct sdos_info *)sd->sdos_info;
+ /* Wait for the indication, the interrupt will be masked when the ISR fires. */
+ wait_event_interruptible(sdos->intr_wait_queue, (sd->got_hcint));
+ } else
+#endif /* BCMSDYIELD */
+ {
+ spi_spinbits(sd);
+ }
+
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmspibrcm.c b/drivers/net/wireless/bcmdhd/bcmspibrcm.c
new file mode 100644
index 000000000000..c3ba9d8eefe7
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmspibrcm.c
@@ -0,0 +1,1814 @@
+/*
+ * Broadcom BCMSDH to gSPI Protocol Conversion Layer
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmspibrcm.c 662541 2016-10-28 03:22:57Z $
+ */
+
+#define HSMODE
+
+#include <typedefs.h>
+
+#include <bcmdevs.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <osl.h>
+#include <hndsoc.h>
+#include <siutils.h>
+#include <sbchipc.h>
+#include <sbsdio.h> /* SDIO device core hardware definitions. */
+#include <spid.h>
+
+#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
+#include <sdiovar.h> /* ioctl/iovars */
+#include <sdio.h> /* SDIO Device and Protocol Specs */
+
+#include <pcicfg.h>
+
+
+#include <bcmspibrcm.h>
+#include <bcmspi.h>
+
+/* these are for the older cores... for newer cores we have control for each of them */
+#define F0_RESPONSE_DELAY 16
+#define F1_RESPONSE_DELAY 16
+#define F2_RESPONSE_DELAY F0_RESPONSE_DELAY
+
+
+#define GSPI_F0_RESP_DELAY 0
+#define GSPI_F1_RESP_DELAY F1_RESPONSE_DELAY
+#define GSPI_F2_RESP_DELAY 0
+#define GSPI_F3_RESP_DELAY 0
+
+#define CMDLEN 4
+
+#define DWORDMODE_ON (sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 2) && (sd->dwordmode == TRUE)
+
+/* Globals */
+#if defined(DHD_DEBUG)
+uint sd_msglevel = SDH_ERROR_VAL;
+#else
+uint sd_msglevel = 0;
+#endif
+
+uint sd_hiok = FALSE; /* Use hi-speed mode if available? */
+uint sd_sdmode = SDIOH_MODE_SPI; /* Use SD4 mode by default */
+uint sd_f2_blocksize = 64; /* Default blocksize */
+
+
+uint sd_divisor = 2;
+uint sd_power = 1; /* Default to SD Slot powered ON */
+uint sd_clock = 1; /* Default to SD Clock turned ON */
+uint sd_crc = 0; /* Default to SPI CRC Check turned OFF */
+uint sd_pci_slot = 0xFFFFffff; /* Used to force selection of a particular PCI slot */
+
+uint8 spi_outbuf[SPI_MAX_PKT_LEN];
+uint8 spi_inbuf[SPI_MAX_PKT_LEN];
+
+/* 128bytes buffer is enough to clear data-not-available and program response-delay F0 bits
+ * assuming we will not exceed F0 response delay > 100 bytes at 48MHz.
+ */
+#define BUF2_PKT_LEN 128
+uint8 spi_outbuf2[BUF2_PKT_LEN];
+uint8 spi_inbuf2[BUF2_PKT_LEN];
+
+#define SPISWAP_WD4(x) bcmswap32(x);
+#define SPISWAP_WD2(x) (bcmswap16(x & 0xffff)) | \
+ (bcmswap16((x & 0xffff0000) >> 16) << 16);
+
+/* Prototypes */
+static bool bcmspi_test_card(sdioh_info_t *sd);
+static bool bcmspi_host_device_init_adapt(sdioh_info_t *sd);
+static int bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode);
+static int bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
+ uint32 *data, uint32 datalen);
+static int bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr,
+ int regsize, uint32 *data);
+static int bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr,
+ int regsize, uint32 data);
+static int bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr,
+ uint8 *data);
+static int bcmspi_driver_init(sdioh_info_t *sd);
+static int bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
+ uint32 addr, int nbytes, uint32 *data);
+static int bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize,
+ uint32 *data);
+static void bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer);
+static int bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg);
+
+/*
+ * Public entry points & extern's
+ */
+extern sdioh_info_t *
+sdioh_attach(osl_t *osh, void *bar0, uint irq)
+{
+ sdioh_info_t *sd;
+
+ sd_trace(("%s\n", __FUNCTION__));
+ if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
+ sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh)));
+ return NULL;
+ }
+ bzero((char *)sd, sizeof(sdioh_info_t));
+ sd->osh = osh;
+ if (spi_osinit(sd) != 0) {
+ sd_err(("%s: spi_osinit() failed\n", __FUNCTION__));
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ return NULL;
+ }
+
+ sd->bar0 = bar0;
+ sd->irq = irq;
+ sd->intr_handler = NULL;
+ sd->intr_handler_arg = NULL;
+ sd->intr_handler_valid = FALSE;
+
+ /* Set defaults */
+ sd->use_client_ints = TRUE;
+ sd->sd_use_dma = FALSE; /* DMA Not supported */
+
+ /* Spi device default is 16bit mode, change to 4 when device is changed to 32bit
+ * mode
+ */
+ sd->wordlen = 2;
+
+
+ if (!spi_hw_attach(sd)) {
+ sd_err(("%s: spi_hw_attach() failed\n", __FUNCTION__));
+ spi_osfree(sd);
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ return (NULL);
+ }
+
+ if (bcmspi_driver_init(sd) != SUCCESS) {
+ sd_err(("%s: bcmspi_driver_init() failed()\n", __FUNCTION__));
+ spi_hw_detach(sd);
+ spi_osfree(sd);
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ return (NULL);
+ }
+
+ if (spi_register_irq(sd, irq) != SUCCESS) {
+ sd_err(("%s: spi_register_irq() failed for irq = %d\n", __FUNCTION__, irq));
+ spi_hw_detach(sd);
+ spi_osfree(sd);
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ return (NULL);
+ }
+
+ sd_trace(("%s: Done\n", __FUNCTION__));
+
+ return sd;
+}
+
+extern SDIOH_API_RC
+sdioh_detach(osl_t *osh, sdioh_info_t *sd)
+{
+ sd_trace(("%s\n", __FUNCTION__));
+ if (sd) {
+ sd_err(("%s: detaching from hardware\n", __FUNCTION__));
+ spi_free_irq(sd->irq, sd);
+ spi_hw_detach(sd);
+ spi_osfree(sd);
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ }
+ return SDIOH_API_RC_SUCCESS;
+}
+
+/* Configure callback to client when we recieve client interrupt */
+extern SDIOH_API_RC
+sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
+{
+ sd_trace(("%s: Entering\n", __FUNCTION__));
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+ OOB_PARAM_IF(dhd_get_oob_disable(argh)) {
+ sd->intr_handler = fn;
+ sd->intr_handler_arg = argh;
+ sd->intr_handler_valid = TRUE;
+ }
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+ return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_interrupt_deregister(sdioh_info_t *sd)
+{
+ sd_trace(("%s: Entering\n", __FUNCTION__));
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+ OOB_PARAM_IF(sd->intr_handler_valid) {
+ sd->intr_handler_valid = FALSE;
+ sd->intr_handler = NULL;
+ sd->intr_handler_arg = NULL;
+ }
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+ return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
+{
+ sd_trace(("%s: Entering\n", __FUNCTION__));
+ *onoff = sd->client_intr_enabled;
+ return SDIOH_API_RC_SUCCESS;
+}
+
+#if defined(DHD_DEBUG)
+extern bool
+sdioh_interrupt_pending(sdioh_info_t *sd)
+{
+ return 0;
+}
+#endif
+
+extern SDIOH_API_RC
+sdioh_query_device(sdioh_info_t *sd)
+{
+ /* Return a BRCM ID appropriate to the dongle class */
+ return (sd->num_funcs > 1) ? BCM4329_D11N_ID : BCM4318_D11G_ID;
+}
+
+/* Provide dstatus bits of spi-transaction for dhd layers. */
+extern uint32
+sdioh_get_dstatus(sdioh_info_t *sd)
+{
+ return sd->card_dstatus;
+}
+
+extern void
+sdioh_chipinfo(sdioh_info_t *sd, uint32 chip, uint32 chiprev)
+{
+ sd->chip = chip;
+ sd->chiprev = chiprev;
+}
+
+extern void
+sdioh_dwordmode(sdioh_info_t *sd, bool set)
+{
+ uint8 reg = 0;
+ int status;
+
+ if ((status = sdioh_request_byte(sd, SDIOH_READ, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
+ SUCCESS) {
+ sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
+ return;
+ }
+
+ if (set) {
+ reg |= DWORD_PKT_LEN_EN;
+ sd->dwordmode = TRUE;
+ sd->client_block_size[SPI_FUNC_2] = 4096; /* h2spi's limit is 4KB, we support 8KB */
+ } else {
+ reg &= ~DWORD_PKT_LEN_EN;
+ sd->dwordmode = FALSE;
+ sd->client_block_size[SPI_FUNC_2] = 2048;
+ }
+
+ if ((status = sdioh_request_byte(sd, SDIOH_WRITE, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
+ SUCCESS) {
+ sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
+ return;
+ }
+}
+
+
+uint
+sdioh_query_iofnum(sdioh_info_t *sd)
+{
+ return sd->num_funcs;
+}
+
+/* IOVar table */
+enum {
+ IOV_MSGLEVEL = 1,
+ IOV_BLOCKMODE,
+ IOV_BLOCKSIZE,
+ IOV_DMA,
+ IOV_USEINTS,
+ IOV_NUMINTS,
+ IOV_NUMLOCALINTS,
+ IOV_HOSTREG,
+ IOV_DEVREG,
+ IOV_DIVISOR,
+ IOV_SDMODE,
+ IOV_HISPEED,
+ IOV_HCIREGS,
+ IOV_POWER,
+ IOV_CLOCK,
+ IOV_SPIERRSTATS,
+ IOV_RESP_DELAY_ALL
+};
+
+const bcm_iovar_t sdioh_iovars[] = {
+ {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
+ {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */
+ {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 },
+ {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 },
+ {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 },
+ {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 },
+ {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
+ {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
+ {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 },
+ {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 },
+ {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 },
+ {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100},
+ {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0},
+ {"spi_errstats", IOV_SPIERRSTATS, 0, IOVT_BUFFER, sizeof(struct spierrstats_t) },
+ {"spi_respdelay", IOV_RESP_DELAY_ALL, 0, IOVT_BOOL, 0 },
+ {NULL, 0, 0, 0, 0 }
+};
+
+int
+sdioh_iovar_op(sdioh_info_t *si, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
+{
+ const bcm_iovar_t *vi = NULL;
+ int bcmerror = 0;
+ int val_size;
+ int32 int_val = 0;
+ bool bool_val;
+ uint32 actionid;
+/*
+ sdioh_regs_t *regs;
+*/
+
+ ASSERT(name);
+ ASSERT(len >= 0);
+
+ /* Get must have return space; Set does not take qualifiers */
+ ASSERT(set || (arg && len));
+ ASSERT(!set || (!params && !plen));
+
+ sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
+
+ if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
+ bcmerror = BCME_UNSUPPORTED;
+ goto exit;
+ }
+
+ if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
+ goto exit;
+
+ /* Set up params so get and set can share the convenience variables */
+ if (params == NULL) {
+ params = arg;
+ plen = len;
+ }
+
+ if (vi->type == IOVT_VOID)
+ val_size = 0;
+ else if (vi->type == IOVT_BUFFER)
+ val_size = len;
+ else
+ val_size = sizeof(int);
+
+ if (plen >= (int)sizeof(int_val))
+ bcopy(params, &int_val, sizeof(int_val));
+
+ bool_val = (int_val != 0) ? TRUE : FALSE;
+
+ actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+ switch (actionid) {
+ case IOV_GVAL(IOV_MSGLEVEL):
+ int_val = (int32)sd_msglevel;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_MSGLEVEL):
+ sd_msglevel = int_val;
+ break;
+
+ case IOV_GVAL(IOV_BLOCKSIZE):
+ if ((uint32)int_val > si->num_funcs) {
+ bcmerror = BCME_BADARG;
+ break;
+ }
+ int_val = (int32)si->client_block_size[int_val];
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_DMA):
+ int_val = (int32)si->sd_use_dma;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DMA):
+ si->sd_use_dma = (bool)int_val;
+ break;
+
+ case IOV_GVAL(IOV_USEINTS):
+ int_val = (int32)si->use_client_ints;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_USEINTS):
+ break;
+
+ case IOV_GVAL(IOV_DIVISOR):
+ int_val = (uint32)sd_divisor;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DIVISOR):
+ sd_divisor = int_val;
+ if (!spi_start_clock(si, (uint16)sd_divisor)) {
+ sd_err(("%s: set clock failed\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ }
+ break;
+
+ case IOV_GVAL(IOV_POWER):
+ int_val = (uint32)sd_power;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_POWER):
+ sd_power = int_val;
+ break;
+
+ case IOV_GVAL(IOV_CLOCK):
+ int_val = (uint32)sd_clock;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_CLOCK):
+ sd_clock = int_val;
+ break;
+
+ case IOV_GVAL(IOV_SDMODE):
+ int_val = (uint32)sd_sdmode;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_SDMODE):
+ sd_sdmode = int_val;
+ break;
+
+ case IOV_GVAL(IOV_HISPEED):
+ int_val = (uint32)sd_hiok;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_HISPEED):
+ sd_hiok = int_val;
+
+ if (!bcmspi_set_highspeed_mode(si, (bool)sd_hiok)) {
+ sd_err(("%s: Failed changing highspeed mode to %d.\n",
+ __FUNCTION__, sd_hiok));
+ bcmerror = BCME_ERROR;
+ return ERROR;
+ }
+ break;
+
+ case IOV_GVAL(IOV_NUMINTS):
+ int_val = (int32)si->intrcount;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_NUMLOCALINTS):
+ int_val = (int32)si->local_intrcount;
+ bcopy(&int_val, arg, val_size);
+ break;
+ case IOV_GVAL(IOV_DEVREG):
+ {
+ sdreg_t *sd_ptr = (sdreg_t *)params;
+ uint8 data;
+
+ if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) {
+ bcmerror = BCME_SDIO_ERROR;
+ break;
+ }
+
+ int_val = (int)data;
+ bcopy(&int_val, arg, sizeof(int_val));
+ break;
+ }
+
+ case IOV_SVAL(IOV_DEVREG):
+ {
+ sdreg_t *sd_ptr = (sdreg_t *)params;
+ uint8 data = (uint8)sd_ptr->value;
+
+ if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) {
+ bcmerror = BCME_SDIO_ERROR;
+ break;
+ }
+ break;
+ }
+
+
+ case IOV_GVAL(IOV_SPIERRSTATS):
+ {
+ bcopy(&si->spierrstats, arg, sizeof(struct spierrstats_t));
+ break;
+ }
+
+ case IOV_SVAL(IOV_SPIERRSTATS):
+ {
+ bzero(&si->spierrstats, sizeof(struct spierrstats_t));
+ break;
+ }
+
+ case IOV_GVAL(IOV_RESP_DELAY_ALL):
+ int_val = (int32)si->resp_delay_all;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_RESP_DELAY_ALL):
+ si->resp_delay_all = (bool)int_val;
+ int_val = STATUS_ENABLE|INTR_WITH_STATUS;
+ if (si->resp_delay_all)
+ int_val |= RESP_DELAY_ALL;
+ else {
+ if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_RESPONSE_DELAY, 1,
+ F1_RESPONSE_DELAY) != SUCCESS) {
+ sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
+ bcmerror = BCME_SDIO_ERROR;
+ break;
+ }
+ }
+
+ if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_STATUS_ENABLE, 1, int_val)
+ != SUCCESS) {
+ sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
+ bcmerror = BCME_SDIO_ERROR;
+ break;
+ }
+ break;
+
+ default:
+ bcmerror = BCME_UNSUPPORTED;
+ break;
+ }
+exit:
+
+ return bcmerror;
+}
+
+extern SDIOH_API_RC
+sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
+{
+ SDIOH_API_RC status;
+ /* No lock needed since sdioh_request_byte does locking */
+ status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
+ return status;
+}
+
+extern SDIOH_API_RC
+sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
+{
+ /* No lock needed since sdioh_request_byte does locking */
+ SDIOH_API_RC status;
+
+ if ((fnc_num == SPI_FUNC_1) && (addr == SBSDIO_FUNC1_FRAMECTRL)) {
+ uint8 dummy_data;
+ status = sdioh_cfg_read(sd, fnc_num, addr, &dummy_data);
+ if (status) {
+ sd_err(("sdioh_cfg_read() failed.\n"));
+ return status;
+ }
+ }
+
+ status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
+ return status;
+}
+
+extern SDIOH_API_RC
+sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
+{
+ uint32 count;
+ int offset;
+ uint32 cis_byte;
+ uint16 *cis = (uint16 *)cisd;
+ uint bar0 = SI_ENUM_BASE;
+ int status;
+ uint8 data;
+
+ sd_trace(("%s: Func %d\n", __FUNCTION__, func));
+
+ spi_lock(sd);
+
+ /* Set sb window address to 0x18000000 */
+ data = (bar0 >> 8) & SBSDIO_SBADDRLOW_MASK;
+ status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, &data);
+ if (status == SUCCESS) {
+ data = (bar0 >> 16) & SBSDIO_SBADDRMID_MASK;
+ status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, &data);
+ } else {
+ sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
+ spi_unlock(sd);
+ return (BCME_ERROR);
+ }
+ if (status == SUCCESS) {
+ data = (bar0 >> 24) & SBSDIO_SBADDRHIGH_MASK;
+ status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, &data);
+ } else {
+ sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
+ spi_unlock(sd);
+ return (BCME_ERROR);
+ }
+
+ offset = CC_SROM_OTP; /* OTP offset in chipcommon. */
+ for (count = 0; count < length/2; count++) {
+ if (bcmspi_card_regread (sd, SDIO_FUNC_1, offset, 2, &cis_byte) < 0) {
+ sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
+ spi_unlock(sd);
+ return (BCME_ERROR);
+ }
+
+ *cis = (uint16)cis_byte;
+ cis++;
+ offset += 2;
+ }
+
+ spi_unlock(sd);
+
+ return (BCME_OK);
+}
+
+extern SDIOH_API_RC
+sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
+{
+ int status;
+ uint32 cmd_arg;
+ uint32 dstatus;
+ uint32 data = (uint32)(*byte);
+
+ spi_lock(sd);
+
+ cmd_arg = 0;
+ cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+ cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
+ cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+ cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, rw == SDIOH_READ ? 0 : 1);
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
+
+ if (rw == SDIOH_READ) {
+ sd_trace(("%s: RD cmd_arg=0x%x func=%d regaddr=0x%x\n",
+ __FUNCTION__, cmd_arg, func, regaddr));
+ } else {
+ sd_trace(("%s: WR cmd_arg=0x%x func=%d regaddr=0x%x data=0x%x\n",
+ __FUNCTION__, cmd_arg, func, regaddr, data));
+ }
+
+ if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, 1)) != SUCCESS) {
+ spi_unlock(sd);
+ return status;
+ }
+
+ if (rw == SDIOH_READ) {
+ *byte = (uint8)data;
+ sd_trace(("%s: RD result=0x%x\n", __FUNCTION__, *byte));
+ }
+
+ bcmspi_cmd_getdstatus(sd, &dstatus);
+ if (dstatus)
+ sd_trace(("dstatus=0x%x\n", dstatus));
+
+ spi_unlock(sd);
+ return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
+ uint32 *word, uint nbytes)
+{
+ int status;
+
+ spi_lock(sd);
+
+ if (rw == SDIOH_READ)
+ status = bcmspi_card_regread(sd, func, addr, nbytes, word);
+ else
+ status = bcmspi_card_regwrite(sd, func, addr, nbytes, *word);
+
+ spi_unlock(sd);
+ return (status == SUCCESS ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+}
+
+extern SDIOH_API_RC
+sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func,
+ uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt)
+{
+ int len;
+ int buflen = (int)buflen_u;
+ bool fifo = (fix_inc == SDIOH_DATA_FIX);
+
+ spi_lock(sd);
+
+ ASSERT(reg_width == 4);
+ ASSERT(buflen_u < (1 << 30));
+ ASSERT(sd->client_block_size[func]);
+
+ sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n",
+ __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W',
+ buflen_u, sd->r_cnt, sd->t_cnt, pkt));
+
+ /* Break buffer down into blocksize chunks. */
+ while (buflen > 0) {
+ len = MIN(sd->client_block_size[func], buflen);
+ if (bcmspi_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) {
+ sd_err(("%s: bcmspi_card_buf %s failed\n",
+ __FUNCTION__, rw == SDIOH_READ ? "Read" : "Write"));
+ spi_unlock(sd);
+ return SDIOH_API_RC_FAIL;
+ }
+ buffer += len;
+ buflen -= len;
+ if (!fifo)
+ addr += len;
+ }
+ spi_unlock(sd);
+ return SDIOH_API_RC_SUCCESS;
+}
+
+/* This function allows write to gspi bus when another rd/wr function is deep down the call stack.
+ * Its main aim is to have simpler spi writes rather than recursive writes.
+ * e.g. When there is a need to program response delay on the fly after detecting the SPI-func
+ * this call will allow to program the response delay.
+ */
+static int
+bcmspi_card_byterewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 byte)
+{
+ uint32 cmd_arg;
+ uint32 datalen = 1;
+ uint32 hostlen;
+
+ cmd_arg = 0;
+
+ cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
+ cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
+ cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+ cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, datalen);
+
+ sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+
+
+ /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
+ * according to the wordlen mode(16/32bit) the device is in.
+ */
+ ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
+ datalen = ROUNDUP(datalen, sd->wordlen);
+
+ /* Start by copying command in the spi-outbuffer */
+ if (sd->wordlen == 4) { /* 32bit spid */
+ *(uint32 *)spi_outbuf2 = SPISWAP_WD4(cmd_arg);
+ if (datalen & 0x3)
+ datalen += (4 - (datalen & 0x3));
+ } else if (sd->wordlen == 2) { /* 16bit spid */
+ *(uint32 *)spi_outbuf2 = SPISWAP_WD2(cmd_arg);
+ if (datalen & 0x1)
+ datalen++;
+ } else {
+ sd_err(("%s: Host is %d bit spid, could not create SPI command.\n",
+ __FUNCTION__, 8 * sd->wordlen));
+ return ERROR;
+ }
+
+ /* for Write, put the data into the output buffer */
+ if (datalen != 0) {
+ if (sd->wordlen == 4) { /* 32bit spid */
+ *(uint32 *)&spi_outbuf2[CMDLEN] = SPISWAP_WD4(byte);
+ } else if (sd->wordlen == 2) { /* 16bit spid */
+ *(uint32 *)&spi_outbuf2[CMDLEN] = SPISWAP_WD2(byte);
+ }
+ }
+
+ /* +4 for cmd, +4 for dstatus */
+ hostlen = datalen + 8;
+ hostlen += (4 - (hostlen & 0x3));
+ spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, hostlen);
+
+ /* Last 4bytes are dstatus. Device is configured to return status bits. */
+ if (sd->wordlen == 4) { /* 32bit spid */
+ sd->card_dstatus = SPISWAP_WD4(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
+ } else if (sd->wordlen == 2) { /* 16bit spid */
+ sd->card_dstatus = SPISWAP_WD2(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
+ } else {
+ sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
+ __FUNCTION__, 8 * sd->wordlen));
+ return ERROR;
+ }
+
+ if (sd->card_dstatus)
+ sd_trace(("dstatus after byte rewrite = 0x%x\n", sd->card_dstatus));
+
+ return (BCME_OK);
+}
+
+/* Program the response delay corresponding to the spi function */
+static int
+bcmspi_prog_resp_delay(sdioh_info_t *sd, int func, uint8 resp_delay)
+{
+ if (sd->resp_delay_all == FALSE)
+ return (BCME_OK);
+
+ if (sd->prev_fun == func)
+ return (BCME_OK);
+
+ if (F0_RESPONSE_DELAY == F1_RESPONSE_DELAY)
+ return (BCME_OK);
+
+ bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_RESPONSE_DELAY, resp_delay);
+
+ /* Remember function for which to avoid reprogramming resp-delay in next iteration */
+ sd->prev_fun = func;
+
+ return (BCME_OK);
+
+}
+
+#define GSPI_RESYNC_PATTERN 0x0
+
+/* A resync pattern is a 32bit MOSI line with all zeros. Its a special command in gSPI.
+ * It resets the spi-bkplane logic so that all F1 related ping-pong buffer logic is
+ * synchronised and all queued resuests are cancelled.
+ */
+static int
+bcmspi_resync_f1(sdioh_info_t *sd)
+{
+ uint32 cmd_arg = GSPI_RESYNC_PATTERN, data = 0, datalen = 0;
+
+
+ /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
+ * according to the wordlen mode(16/32bit) the device is in.
+ */
+ ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
+ datalen = ROUNDUP(datalen, sd->wordlen);
+
+ /* Start by copying command in the spi-outbuffer */
+ *(uint32 *)spi_outbuf2 = cmd_arg;
+
+ /* for Write, put the data into the output buffer */
+ *(uint32 *)&spi_outbuf2[CMDLEN] = data;
+
+ /* +4 for cmd, +4 for dstatus */
+ spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, datalen + 8);
+
+ /* Last 4bytes are dstatus. Device is configured to return status bits. */
+ if (sd->wordlen == 4) { /* 32bit spid */
+ sd->card_dstatus = SPISWAP_WD4(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
+ } else if (sd->wordlen == 2) { /* 16bit spid */
+ sd->card_dstatus = SPISWAP_WD2(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
+ } else {
+ sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
+ __FUNCTION__, 8 * sd->wordlen));
+ return ERROR;
+ }
+
+ if (sd->card_dstatus)
+ sd_trace(("dstatus after resync pattern write = 0x%x\n", sd->card_dstatus));
+
+ return (BCME_OK);
+}
+
+uint32 dstatus_count = 0;
+
+static int
+bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg)
+{
+ uint32 dstatus = sd->card_dstatus;
+ struct spierrstats_t *spierrstats = &sd->spierrstats;
+ int err = SUCCESS;
+
+ sd_trace(("cmd = 0x%x, dstatus = 0x%x\n", cmd_arg, dstatus));
+
+ /* Store dstatus of last few gSPI transactions */
+ spierrstats->dstatus[dstatus_count % NUM_PREV_TRANSACTIONS] = dstatus;
+ spierrstats->spicmd[dstatus_count % NUM_PREV_TRANSACTIONS] = cmd_arg;
+ dstatus_count++;
+
+ if (sd->card_init_done == FALSE)
+ return err;
+
+ if (dstatus & STATUS_DATA_NOT_AVAILABLE) {
+ spierrstats->dna++;
+ sd_trace(("Read data not available on F1 addr = 0x%x\n",
+ GFIELD(cmd_arg, SPI_REG_ADDR)));
+ /* Clear dna bit */
+ bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, DATA_UNAVAILABLE);
+ }
+
+ if (dstatus & STATUS_UNDERFLOW) {
+ spierrstats->rdunderflow++;
+ sd_err(("FIFO underflow happened due to current F2 read command.\n"));
+ }
+
+ if (dstatus & STATUS_OVERFLOW) {
+ spierrstats->wroverflow++;
+ sd_err(("FIFO overflow happened due to current (F1/F2) write command.\n"));
+ bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, F1_OVERFLOW);
+ bcmspi_resync_f1(sd);
+ sd_err(("Recovering from F1 FIFO overflow.\n"));
+ }
+
+ if (dstatus & STATUS_F2_INTR) {
+ spierrstats->f2interrupt++;
+ sd_trace(("Interrupt from F2. SW should clear corresponding IntStatus bits\n"));
+ }
+
+ if (dstatus & STATUS_F3_INTR) {
+ spierrstats->f3interrupt++;
+ sd_err(("Interrupt from F3. SW should clear corresponding IntStatus bits\n"));
+ }
+
+ if (dstatus & STATUS_HOST_CMD_DATA_ERR) {
+ spierrstats->hostcmddataerr++;
+ sd_err(("Error in CMD or Host data, detected by CRC/Checksum (optional)\n"));
+ }
+
+ if (dstatus & STATUS_F2_PKT_AVAILABLE) {
+ spierrstats->f2pktavailable++;
+ sd_trace(("Packet is available/ready in F2 TX FIFO\n"));
+ sd_trace(("Packet length = %d\n", sd->dwordmode ?
+ ((dstatus & STATUS_F2_PKT_LEN_MASK) >> (STATUS_F2_PKT_LEN_SHIFT - 2)) :
+ ((dstatus & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT)));
+ }
+
+ if (dstatus & STATUS_F3_PKT_AVAILABLE) {
+ spierrstats->f3pktavailable++;
+ sd_err(("Packet is available/ready in F3 TX FIFO\n"));
+ sd_err(("Packet length = %d\n",
+ (dstatus & STATUS_F3_PKT_LEN_MASK) >> STATUS_F3_PKT_LEN_SHIFT));
+ }
+
+ return err;
+}
+
+extern int
+sdioh_abort(sdioh_info_t *sd, uint func)
+{
+ return 0;
+}
+
+int
+sdioh_start(sdioh_info_t *sd, int stage)
+{
+ return SUCCESS;
+}
+
+int
+sdioh_stop(sdioh_info_t *sd)
+{
+ return SUCCESS;
+}
+
+int
+sdioh_waitlockfree(sdioh_info_t *sd)
+{
+ return SUCCESS;
+}
+
+
+/*
+ * Private/Static work routines
+ */
+static int
+bcmspi_host_init(sdioh_info_t *sd)
+{
+
+ /* Default power on mode */
+ sd->sd_mode = SDIOH_MODE_SPI;
+ sd->polled_mode = TRUE;
+ sd->host_init_done = TRUE;
+ sd->card_init_done = FALSE;
+ sd->adapter_slot = 1;
+
+ return (SUCCESS);
+}
+
+static int
+get_client_blocksize(sdioh_info_t *sd)
+{
+ uint32 regdata[2];
+ int status;
+
+ /* Find F1/F2/F3 max packet size */
+ if ((status = bcmspi_card_regread(sd, 0, SPID_F1_INFO_REG,
+ 8, regdata)) != SUCCESS) {
+ return status;
+ }
+
+ sd_trace(("pkt_size regdata[0] = 0x%x, regdata[1] = 0x%x\n",
+ regdata[0], regdata[1]));
+
+ sd->client_block_size[1] = (regdata[0] & F1_MAX_PKT_SIZE) >> 2;
+ sd_trace(("Func1 blocksize = %d\n", sd->client_block_size[1]));
+ ASSERT(sd->client_block_size[1] == BLOCK_SIZE_F1);
+
+ sd->client_block_size[2] = ((regdata[0] >> 16) & F2_MAX_PKT_SIZE) >> 2;
+ sd_trace(("Func2 blocksize = %d\n", sd->client_block_size[2]));
+ ASSERT(sd->client_block_size[2] == BLOCK_SIZE_F2);
+
+ sd->client_block_size[3] = (regdata[1] & F3_MAX_PKT_SIZE) >> 2;
+ sd_trace(("Func3 blocksize = %d\n", sd->client_block_size[3]));
+ ASSERT(sd->client_block_size[3] == BLOCK_SIZE_F3);
+
+ return 0;
+}
+
+static int
+bcmspi_client_init(sdioh_info_t *sd)
+{
+ uint32 status_en_reg = 0;
+ sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot));
+
+#ifdef HSMODE
+ if (!spi_start_clock(sd, (uint16)sd_divisor)) {
+ sd_err(("spi_start_clock failed\n"));
+ return ERROR;
+ }
+#else
+ /* Start at ~400KHz clock rate for initialization */
+ if (!spi_start_clock(sd, 128)) {
+ sd_err(("spi_start_clock failed\n"));
+ return ERROR;
+ }
+#endif /* HSMODE */
+
+ if (!bcmspi_host_device_init_adapt(sd)) {
+ sd_err(("bcmspi_host_device_init_adapt failed\n"));
+ return ERROR;
+ }
+
+ if (!bcmspi_test_card(sd)) {
+ sd_err(("bcmspi_test_card failed\n"));
+ return ERROR;
+ }
+
+ sd->num_funcs = SPI_MAX_IOFUNCS;
+
+ get_client_blocksize(sd);
+
+ /* Apply resync pattern cmd with all zeros to reset spi-bkplane F1 logic */
+ bcmspi_resync_f1(sd);
+
+ sd->dwordmode = FALSE;
+
+ bcmspi_card_regread(sd, 0, SPID_STATUS_ENABLE, 1, &status_en_reg);
+
+ sd_trace(("%s: Enabling interrupt with dstatus \n", __FUNCTION__));
+ status_en_reg |= INTR_WITH_STATUS;
+
+ if (bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_STATUS_ENABLE, 1,
+ status_en_reg & 0xff) != SUCCESS) {
+ sd_err(("%s: Unable to set response delay for all fun's.\n", __FUNCTION__));
+ return ERROR;
+ }
+
+#ifndef HSMODE
+ /* After configuring for High-Speed mode, set the desired clock rate. */
+ if (!spi_start_clock(sd, 4)) {
+ sd_err(("spi_start_clock failed\n"));
+ return ERROR;
+ }
+#endif /* HSMODE */
+
+ /* check to see if the response delay needs to be programmed properly */
+ {
+ uint32 f1_respdelay = 0;
+ bcmspi_card_regread(sd, 0, SPID_RESP_DELAY_F1, 1, &f1_respdelay);
+ if ((f1_respdelay == 0) || (f1_respdelay == 0xFF)) {
+ /* older sdiodevice core and has no separte resp delay for each of */
+ sd_err(("older corerev < 4 so use the same resp delay for all funcs\n"));
+ sd->resp_delay_new = FALSE;
+ }
+ else {
+ /* older sdiodevice core and has no separte resp delay for each of */
+ int ret_val;
+ sd->resp_delay_new = TRUE;
+ sd_err(("new corerev >= 4 so set the resp delay for each of the funcs\n"));
+ sd_trace(("resp delay for funcs f0(%d), f1(%d), f2(%d), f3(%d)\n",
+ GSPI_F0_RESP_DELAY, GSPI_F1_RESP_DELAY,
+ GSPI_F2_RESP_DELAY, GSPI_F3_RESP_DELAY));
+ ret_val = bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_RESP_DELAY_F0, 1,
+ GSPI_F0_RESP_DELAY);
+ if (ret_val != SUCCESS) {
+ sd_err(("%s: Unable to set response delay for F0\n", __FUNCTION__));
+ return ERROR;
+ }
+ ret_val = bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_RESP_DELAY_F1, 1,
+ GSPI_F1_RESP_DELAY);
+ if (ret_val != SUCCESS) {
+ sd_err(("%s: Unable to set response delay for F1\n", __FUNCTION__));
+ return ERROR;
+ }
+ ret_val = bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_RESP_DELAY_F2, 1,
+ GSPI_F2_RESP_DELAY);
+ if (ret_val != SUCCESS) {
+ sd_err(("%s: Unable to set response delay for F2\n", __FUNCTION__));
+ return ERROR;
+ }
+ ret_val = bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_RESP_DELAY_F3, 1,
+ GSPI_F3_RESP_DELAY);
+ if (ret_val != SUCCESS) {
+ sd_err(("%s: Unable to set response delay for F2\n", __FUNCTION__));
+ return ERROR;
+ }
+ }
+ }
+
+
+ sd->card_init_done = TRUE;
+
+ /* get the device rev to program the prop respdelays */
+
+ return SUCCESS;
+}
+
+static int
+bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode)
+{
+ uint32 regdata;
+ int status;
+
+ if ((status = bcmspi_card_regread(sd, 0, SPID_CONFIG,
+ 4, &regdata)) != SUCCESS)
+ return status;
+
+ sd_trace(("In %s spih-ctrl = 0x%x \n", __FUNCTION__, regdata));
+
+
+ if (hsmode == TRUE) {
+ sd_trace(("Attempting to enable High-Speed mode.\n"));
+
+ if (regdata & HIGH_SPEED_MODE) {
+ sd_trace(("Device is already in High-Speed mode.\n"));
+ return status;
+ } else {
+ regdata |= HIGH_SPEED_MODE;
+ sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
+ if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
+ 4, regdata)) != SUCCESS) {
+ return status;
+ }
+ }
+ } else {
+ sd_trace(("Attempting to disable High-Speed mode.\n"));
+
+ if (regdata & HIGH_SPEED_MODE) {
+ regdata &= ~HIGH_SPEED_MODE;
+ sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
+ if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
+ 4, regdata)) != SUCCESS)
+ return status;
+ }
+ else {
+ sd_trace(("Device is already in Low-Speed mode.\n"));
+ return status;
+ }
+ }
+ spi_controller_highspeed_mode(sd, hsmode);
+
+ return TRUE;
+}
+
+#define bcmspi_find_curr_mode(sd) { \
+ sd->wordlen = 2; \
+ status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
+ regdata &= 0xff; \
+ if ((regdata == 0xad) || (regdata == 0x5b) || \
+ (regdata == 0x5d) || (regdata == 0x5a)) \
+ break; \
+ sd->wordlen = 4; \
+ status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
+ regdata &= 0xff; \
+ if ((regdata == 0xad) || (regdata == 0x5b) || \
+ (regdata == 0x5d) || (regdata == 0x5a)) \
+ break; \
+ sd_trace(("Silicon testability issue: regdata = 0x%x." \
+ " Expected 0xad, 0x5a, 0x5b or 0x5d.\n", regdata)); \
+ OSL_DELAY(100000); \
+}
+
+#define INIT_ADAPT_LOOP 100
+
+/* Adapt clock-phase-speed-bitwidth between host and device */
+static bool
+bcmspi_host_device_init_adapt(sdioh_info_t *sd)
+{
+ uint32 wrregdata, regdata = 0;
+ int status;
+ int i;
+
+ /* Due to a silicon testability issue, the first command from the Host
+ * to the device will get corrupted (first bit will be lost). So the
+ * Host should poll the device with a safe read request. ie: The Host
+ * should try to read F0 addr 0x14 using the Fixed address mode
+ * (This will prevent a unintended write command to be detected by device)
+ */
+ for (i = 0; i < INIT_ADAPT_LOOP; i++) {
+ /* If device was not power-cycled it will stay in 32bit mode with
+ * response-delay-all bit set. Alternate the iteration so that
+ * read either with or without response-delay for F0 to succeed.
+ */
+ bcmspi_find_curr_mode(sd);
+ sd->resp_delay_all = (i & 0x1) ? TRUE : FALSE;
+
+ bcmspi_find_curr_mode(sd);
+ sd->dwordmode = TRUE;
+
+ bcmspi_find_curr_mode(sd);
+ sd->dwordmode = FALSE;
+ }
+
+ /* Bail out, device not detected */
+ if (i == INIT_ADAPT_LOOP)
+ return FALSE;
+
+ /* Softreset the spid logic */
+ if ((sd->dwordmode) || (sd->wordlen == 4)) {
+ bcmspi_card_regwrite(sd, 0, SPID_RESET_BP, 1, RESET_ON_WLAN_BP_RESET|RESET_SPI);
+ bcmspi_card_regread(sd, 0, SPID_RESET_BP, 1, &regdata);
+ sd_trace(("reset reg read = 0x%x\n", regdata));
+ sd_trace(("dwordmode = %d, wordlen = %d, resp_delay_all = %d\n", sd->dwordmode,
+ sd->wordlen, sd->resp_delay_all));
+ /* Restore default state after softreset */
+ sd->wordlen = 2;
+ sd->dwordmode = FALSE;
+ }
+
+ if (sd->wordlen == 4) {
+ if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) !=
+ SUCCESS)
+ return FALSE;
+ if (regdata == TEST_RO_DATA_32BIT_LE) {
+ sd_trace(("Spid is already in 32bit LE mode. Value read = 0x%x\n",
+ regdata));
+ sd_trace(("Spid power was left on.\n"));
+ } else {
+ sd_err(("Spid power was left on but signature read failed."
+ " Value read = 0x%x\n", regdata));
+ return FALSE;
+ }
+ } else {
+ sd->wordlen = 2;
+
+#define CTRL_REG_DEFAULT 0x00010430 /* according to the host m/c */
+
+ wrregdata = (CTRL_REG_DEFAULT);
+
+ if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
+ return FALSE;
+ sd_trace(("(we are still in 16bit mode) 32bit READ LE regdata = 0x%x\n", regdata));
+
+#ifndef HSMODE
+ wrregdata |= (CLOCK_PHASE | CLOCK_POLARITY);
+ wrregdata &= ~HIGH_SPEED_MODE;
+ bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
+#endif /* HSMODE */
+
+ for (i = 0; i < INIT_ADAPT_LOOP; i++) {
+ if ((regdata == 0xfdda7d5b) || (regdata == 0xfdda7d5a)) {
+ sd_trace(("0xfeedbead was leftshifted by 1-bit.\n"));
+ if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4,
+ &regdata)) != SUCCESS)
+ return FALSE;
+ }
+ OSL_DELAY(1000);
+ }
+
+ /* Change to host controller intr-polarity of active-low */
+ wrregdata &= ~INTR_POLARITY;
+ sd_trace(("(we are still in 16bit mode) 32bit Write LE reg-ctrl-data = 0x%x\n",
+ wrregdata));
+ /* Change to 32bit mode */
+ wrregdata |= WORD_LENGTH_32;
+ bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
+
+ /* Change command/data packaging in 32bit LE mode */
+ sd->wordlen = 4;
+
+ if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
+ return FALSE;
+
+ if (regdata == TEST_RO_DATA_32BIT_LE) {
+ sd_trace(("Read spid passed. Value read = 0x%x\n", regdata));
+ sd_trace(("Spid had power-on cycle OR spi was soft-resetted \n"));
+ } else {
+ sd_err(("Stale spid reg values read as it was kept powered. Value read ="
+ "0x%x\n", regdata));
+ return FALSE;
+ }
+ }
+
+
+ return TRUE;
+}
+
+static bool
+bcmspi_test_card(sdioh_info_t *sd)
+{
+ uint32 regdata;
+ int status;
+
+ if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
+ return FALSE;
+
+ if (regdata == (TEST_RO_DATA_32BIT_LE))
+ sd_trace(("32bit LE regdata = 0x%x\n", regdata));
+ else {
+ sd_trace(("Incorrect 32bit LE regdata = 0x%x\n", regdata));
+ return FALSE;
+ }
+
+
+#define RW_PATTERN1 0xA0A1A2A3
+#define RW_PATTERN2 0x4B5B6B7B
+
+ regdata = RW_PATTERN1;
+ if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
+ return FALSE;
+ regdata = 0;
+ if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
+ return FALSE;
+ if (regdata != RW_PATTERN1) {
+ sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
+ RW_PATTERN1, regdata));
+ return FALSE;
+ } else
+ sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
+
+ regdata = RW_PATTERN2;
+ if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
+ return FALSE;
+ regdata = 0;
+ if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
+ return FALSE;
+ if (regdata != RW_PATTERN2) {
+ sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
+ RW_PATTERN2, regdata));
+ return FALSE;
+ } else
+ sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
+
+ return TRUE;
+}
+
+static int
+bcmspi_driver_init(sdioh_info_t *sd)
+{
+ sd_trace(("%s\n", __FUNCTION__));
+ if ((bcmspi_host_init(sd)) != SUCCESS) {
+ return ERROR;
+ }
+
+ if (bcmspi_client_init(sd) != SUCCESS) {
+ return ERROR;
+ }
+
+ return SUCCESS;
+}
+
+/* Read device reg */
+static int
+bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
+{
+ int status;
+ uint32 cmd_arg, dstatus;
+
+ ASSERT(regsize);
+
+ if (func == 2)
+ sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
+
+ cmd_arg = 0;
+ cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
+ cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
+ cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+ cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
+
+ sd_trace(("%s: RD cmd_arg=0x%x func=%d regaddr=0x%x regsize=%d\n",
+ __FUNCTION__, cmd_arg, func, regaddr, regsize));
+
+ if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize)) != SUCCESS)
+ return status;
+
+ bcmspi_cmd_getdstatus(sd, &dstatus);
+ if (dstatus)
+ sd_trace(("dstatus =0x%x\n", dstatus));
+
+ return SUCCESS;
+}
+
+static int
+bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
+{
+
+ int status;
+ uint32 cmd_arg;
+ uint32 dstatus;
+
+ ASSERT(regsize);
+
+ if (func == 2)
+ sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
+
+ cmd_arg = 0;
+ cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
+ cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0); /* Fixed access */
+ cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+ cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize);
+
+ sd_trace(("%s: RD cmd_arg=0x%x func=%d regaddr=0x%x regsize=%d\n",
+ __FUNCTION__, cmd_arg, func, regaddr, regsize));
+
+ if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize)) != SUCCESS)
+ return status;
+
+ sd_trace(("%s: RD result=0x%x\n", __FUNCTION__, *data));
+
+ bcmspi_cmd_getdstatus(sd, &dstatus);
+ sd_trace(("dstatus =0x%x\n", dstatus));
+ return SUCCESS;
+}
+
+/* write a device register */
+static int
+bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
+{
+ int status;
+ uint32 cmd_arg, dstatus;
+
+ ASSERT(regsize);
+
+ cmd_arg = 0;
+
+ cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
+ cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
+ cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+ cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
+
+ sd_trace(("%s: WR cmd_arg=0x%x func=%d regaddr=0x%x regsize=%d data=0x%x\n",
+ __FUNCTION__, cmd_arg, func, regaddr, regsize, data));
+
+ if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, regsize)) != SUCCESS)
+ return status;
+
+ bcmspi_cmd_getdstatus(sd, &dstatus);
+ if (dstatus)
+ sd_trace(("dstatus=0x%x\n", dstatus));
+
+ return SUCCESS;
+}
+
+/* write a device register - 1 byte */
+static int
+bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 *byte)
+{
+ int status;
+ uint32 cmd_arg;
+ uint32 dstatus;
+ uint32 data = (uint32)(*byte);
+
+ cmd_arg = 0;
+ cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+ cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
+ cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+ cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
+
+ sd_trace(("%s: WR cmd_arg=0x%x func=%d regaddr=0x%x data=0x%x\n",
+ __FUNCTION__, cmd_arg, func, regaddr, data));
+
+ if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, 1)) != SUCCESS)
+ return status;
+
+ bcmspi_cmd_getdstatus(sd, &dstatus);
+ if (dstatus)
+ sd_trace(("dstatus =0x%x\n", dstatus));
+
+ return SUCCESS;
+}
+
+void
+bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer)
+{
+ *dstatus_buffer = sd->card_dstatus;
+}
+
+/* 'data' is of type uint32 whereas other buffers are of type uint8 */
+static int
+bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
+ uint32 *data, uint32 datalen)
+{
+ uint32 i, j;
+ uint8 resp_delay = 0;
+ int err = SUCCESS;
+ uint32 hostlen;
+ uint32 spilen = 0;
+ uint32 dstatus_idx = 0;
+ uint16 templen, buslen, len, *ptr = NULL;
+
+ sd_trace(("spi cmd = 0x%x\n", cmd_arg));
+
+ if (DWORDMODE_ON) {
+ spilen = GFIELD(cmd_arg, SPI_LEN);
+ if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_0) ||
+ (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_1))
+ dstatus_idx = spilen * 3;
+
+ if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
+ (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
+ spilen = spilen << 2;
+ dstatus_idx = (spilen % 16) ? (16 - (spilen % 16)) : 0;
+ /* convert len to mod16 size */
+ spilen = ROUNDUP(spilen, 16);
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
+ }
+ }
+
+ /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
+ * according to the wordlen mode(16/32bit) the device is in.
+ */
+ if (sd->wordlen == 4) { /* 32bit spid */
+ *(uint32 *)spi_outbuf = SPISWAP_WD4(cmd_arg);
+ if (datalen & 0x3)
+ datalen += (4 - (datalen & 0x3));
+ } else if (sd->wordlen == 2) { /* 16bit spid */
+ *(uint32 *)spi_outbuf = SPISWAP_WD2(cmd_arg);
+ if (datalen & 0x1)
+ datalen++;
+ if (datalen < 4)
+ datalen = ROUNDUP(datalen, 4);
+ } else {
+ sd_err(("Host is %d bit spid, could not create SPI command.\n",
+ 8 * sd->wordlen));
+ return ERROR;
+ }
+
+ /* for Write, put the data into the output buffer */
+ if (GFIELD(cmd_arg, SPI_RW_FLAG) == 1) {
+ /* We send len field of hw-header always a mod16 size, both from host and dongle */
+ if (DWORDMODE_ON) {
+ if (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) {
+ ptr = (uint16 *)&data[0];
+ templen = *ptr;
+ /* ASSERT(*ptr == ~*(ptr + 1)); */
+ templen = ROUNDUP(templen, 16);
+ *ptr = templen;
+ sd_trace(("actual tx len = %d\n", (uint16)(~*(ptr+1))));
+ }
+ }
+
+ if (datalen != 0) {
+ for (i = 0; i < datalen/4; i++) {
+ if (sd->wordlen == 4) { /* 32bit spid */
+ *(uint32 *)&spi_outbuf[i * 4 + CMDLEN] =
+ SPISWAP_WD4(data[i]);
+ } else if (sd->wordlen == 2) { /* 16bit spid */
+ *(uint32 *)&spi_outbuf[i * 4 + CMDLEN] =
+ SPISWAP_WD2(data[i]);
+ }
+ }
+ }
+ }
+
+ /* Append resp-delay number of bytes and clock them out for F0/1/2 reads. */
+ if ((GFIELD(cmd_arg, SPI_RW_FLAG) == 0)) {
+ int func = GFIELD(cmd_arg, SPI_FUNCTION);
+ switch (func) {
+ case 0:
+ if (sd->resp_delay_new)
+ resp_delay = GSPI_F0_RESP_DELAY;
+ else
+ resp_delay = sd->resp_delay_all ? F0_RESPONSE_DELAY : 0;
+ break;
+ case 1:
+ if (sd->resp_delay_new)
+ resp_delay = GSPI_F1_RESP_DELAY;
+ else
+ resp_delay = F1_RESPONSE_DELAY;
+ break;
+ case 2:
+ if (sd->resp_delay_new)
+ resp_delay = GSPI_F2_RESP_DELAY;
+ else
+ resp_delay = sd->resp_delay_all ? F2_RESPONSE_DELAY : 0;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ /* Program response delay */
+ if (sd->resp_delay_new == FALSE)
+ bcmspi_prog_resp_delay(sd, func, resp_delay);
+ }
+
+ /* +4 for cmd and +4 for dstatus */
+ hostlen = datalen + 8 + resp_delay;
+ hostlen += dstatus_idx;
+ hostlen += (4 - (hostlen & 0x3));
+ spi_sendrecv(sd, spi_outbuf, spi_inbuf, hostlen);
+
+ /* for Read, get the data into the input buffer */
+ if (datalen != 0) {
+ if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) { /* if read cmd */
+ for (j = 0; j < datalen/4; j++) {
+ if (sd->wordlen == 4) { /* 32bit spid */
+ data[j] = SPISWAP_WD4(*(uint32 *)&spi_inbuf[j * 4 +
+ CMDLEN + resp_delay]);
+ } else if (sd->wordlen == 2) { /* 16bit spid */
+ data[j] = SPISWAP_WD2(*(uint32 *)&spi_inbuf[j * 4 +
+ CMDLEN + resp_delay]);
+ }
+ }
+
+ if ((DWORDMODE_ON) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
+ ptr = (uint16 *)&data[0];
+ templen = *ptr;
+ buslen = len = ~(*(ptr + 1));
+ buslen = ROUNDUP(buslen, 16);
+ /* populate actual len in hw-header */
+ if (templen == buslen)
+ *ptr = len;
+ }
+ }
+ }
+
+ /* Restore back the len field of the hw header */
+ if (DWORDMODE_ON) {
+ if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
+ (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
+ ptr = (uint16 *)&data[0];
+ *ptr = (uint16)(~*(ptr+1));
+ }
+ }
+
+ dstatus_idx += (datalen + CMDLEN + resp_delay);
+ /* Last 4bytes are dstatus. Device is configured to return status bits. */
+ if (sd->wordlen == 4) { /* 32bit spid */
+ sd->card_dstatus = SPISWAP_WD4(*(uint32 *)&spi_inbuf[dstatus_idx]);
+ } else if (sd->wordlen == 2) { /* 16bit spid */
+ sd->card_dstatus = SPISWAP_WD2(*(uint32 *)&spi_inbuf[dstatus_idx]);
+ } else {
+ sd_err(("Host is %d bit machine, could not read SPI dstatus.\n",
+ 8 * sd->wordlen));
+ return ERROR;
+ }
+ if (sd->card_dstatus == 0xffffffff) {
+ sd_err(("looks like not a GSPI device or device is not powered.\n"));
+ }
+
+ err = bcmspi_update_stats(sd, cmd_arg);
+
+ return err;
+
+}
+
+static int
+bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
+ uint32 addr, int nbytes, uint32 *data)
+{
+ int status;
+ uint32 cmd_arg;
+ bool write = rw == SDIOH_READ ? 0 : 1;
+ uint retries = 0;
+
+ bool enable;
+ uint32 spilen;
+
+ cmd_arg = 0;
+
+ ASSERT(nbytes);
+ ASSERT(nbytes <= sd->client_block_size[func]);
+
+ if (write) sd->t_cnt++; else sd->r_cnt++;
+
+ if (func == 2) {
+ /* Frame len check limited by gSPI. */
+ if ((nbytes > 2000) && write) {
+ sd_trace((">2KB write: F2 wr of %d bytes\n", nbytes));
+ }
+ /* ASSERT(nbytes <= 2048); Fix bigger len gspi issue and uncomment. */
+ /* If F2 fifo on device is not ready to receive data, don't do F2 transfer */
+ if (write) {
+ uint32 dstatus;
+ /* check F2 ready with cached one */
+ bcmspi_cmd_getdstatus(sd, &dstatus);
+ if ((dstatus & STATUS_F2_RX_READY) == 0) {
+ retries = WAIT_F2RXFIFORDY;
+ enable = 0;
+ while (retries-- && !enable) {
+ OSL_DELAY(WAIT_F2RXFIFORDY_DELAY * 1000);
+ bcmspi_card_regread(sd, SPI_FUNC_0, SPID_STATUS_REG, 4,
+ &dstatus);
+ if (dstatus & STATUS_F2_RX_READY)
+ enable = TRUE;
+ }
+ if (!enable) {
+ struct spierrstats_t *spierrstats = &sd->spierrstats;
+ spierrstats->f2rxnotready++;
+ sd_err(("F2 FIFO is not ready to receive data.\n"));
+ return ERROR;
+ }
+ sd_trace(("No of retries on F2 ready %d\n",
+ (WAIT_F2RXFIFORDY - retries)));
+ }
+ }
+ }
+
+ /* F2 transfers happen on 0 addr */
+ addr = (func == 2) ? 0 : addr;
+
+ /* In pio mode buffer is read using fixed address fifo in func 1 */
+ if ((func == 1) && (fifo))
+ cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0);
+ else
+ cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);
+
+ cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+ cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, addr);
+ cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, write);
+ spilen = sd->data_xfer_count = MIN(sd->client_block_size[func], nbytes);
+ if ((sd->dwordmode == TRUE) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
+ /* convert len to mod4 size */
+ spilen = spilen + ((spilen & 0x3) ? (4 - (spilen & 0x3)): 0);
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
+ } else
+ cmd_arg = SFIELD(cmd_arg, SPI_LEN, spilen);
+
+ if ((func == 2) && (fifo == 1)) {
+ sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
+ __FUNCTION__, write ? "Wr" : "Rd", func, "INCR",
+ addr, nbytes, sd->r_cnt, sd->t_cnt));
+ }
+
+ sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+ sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
+ __FUNCTION__, write ? "Wd" : "Rd", func, "INCR",
+ addr, nbytes, sd->r_cnt, sd->t_cnt));
+
+
+ if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, nbytes)) != SUCCESS) {
+ sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__,
+ (write ? "write" : "read")));
+ return status;
+ }
+
+ /* gSPI expects that hw-header-len is equal to spi-command-len */
+ if ((func == 2) && (rw == SDIOH_WRITE) && (sd->dwordmode == FALSE)) {
+ ASSERT((uint16)sd->data_xfer_count == (uint16)(*data & 0xffff));
+ ASSERT((uint16)sd->data_xfer_count == (uint16)(~((*data & 0xffff0000) >> 16)));
+ }
+
+ if ((nbytes > 2000) && !write) {
+ sd_trace((">2KB read: F2 rd of %d bytes\n", nbytes));
+ }
+
+ return SUCCESS;
+}
+
+/* Reset and re-initialize the device */
+int
+sdioh_sdio_reset(sdioh_info_t *si)
+{
+ si->card_init_done = FALSE;
+ return bcmspi_client_init(si);
+}
+
+SDIOH_API_RC
+sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio)
+{
+ return SDIOH_API_RC_FAIL;
+}
+
+SDIOH_API_RC
+sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab)
+{
+ return SDIOH_API_RC_FAIL;
+}
+
+bool
+sdioh_gpioin(sdioh_info_t *sd, uint32 gpio)
+{
+ return FALSE;
+}
+
+SDIOH_API_RC
+sdioh_gpio_init(sdioh_info_t *sd)
+{
+ return SDIOH_API_RC_FAIL;
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmutils.c b/drivers/net/wireless/bcmdhd/bcmutils.c
new file mode 100644
index 000000000000..1d5c6a07a00c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmutils.c
@@ -0,0 +1,3084 @@
+/*
+ * Driver O/S-independent utility routines
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ * $Id: bcmutils.c 658506 2016-09-08 06:44:19Z $
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <stdarg.h>
+#ifdef BCMDRIVER
+
+#include <osl.h>
+#include <bcmutils.h>
+#if defined(BCMNVRAM)
+#include <siutils.h>
+#include <bcmnvram.h>
+#endif
+
+#else /* !BCMDRIVER */
+
+#include <stdio.h>
+#include <string.h>
+#include <bcmutils.h>
+
+#if defined(BCMEXTSUP)
+#include <bcm_osl.h>
+#endif
+
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+
+#endif /* !BCMDRIVER */
+
+#include <bcmendian.h>
+#include <bcmdevs.h>
+#include <proto/ethernet.h>
+#include <proto/vlan.h>
+#include <proto/bcmip.h>
+#include <proto/802.1d.h>
+#include <proto/802.11.h>
+
+
+void *_bcmutils_dummy_fn = NULL;
+
+
+
+#ifdef BCMDRIVER
+
+
+
+/* copy a pkt buffer chain into a buffer */
+uint
+pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
+{
+ uint n, ret = 0;
+
+ if (len < 0)
+ len = 4096; /* "infinite" */
+
+ /* skip 'offset' bytes */
+ for (; p && offset; p = PKTNEXT(osh, p)) {
+ if (offset < (uint)PKTLEN(osh, p))
+ break;
+ offset -= PKTLEN(osh, p);
+ }
+
+ if (!p)
+ return 0;
+
+ /* copy the data */
+ for (; p && len; p = PKTNEXT(osh, p)) {
+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
+ bcopy(PKTDATA(osh, p) + offset, buf, n);
+ buf += n;
+ len -= n;
+ ret += n;
+ offset = 0;
+ }
+
+ return ret;
+}
+
+/* copy a buffer into a pkt buffer chain */
+uint
+pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf)
+{
+ uint n, ret = 0;
+
+
+ /* skip 'offset' bytes */
+ for (; p && offset; p = PKTNEXT(osh, p)) {
+ if (offset < (uint)PKTLEN(osh, p))
+ break;
+ offset -= PKTLEN(osh, p);
+ }
+
+ if (!p)
+ return 0;
+
+ /* copy the data */
+ for (; p && len; p = PKTNEXT(osh, p)) {
+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
+ bcopy(buf, PKTDATA(osh, p) + offset, n);
+ buf += n;
+ len -= n;
+ ret += n;
+ offset = 0;
+ }
+
+ return ret;
+}
+
+
+
+/* return total length of buffer chain */
+uint BCMFASTPATH
+pkttotlen(osl_t *osh, void *p)
+{
+ uint total;
+ int len;
+
+ total = 0;
+ for (; p; p = PKTNEXT(osh, p)) {
+ len = PKTLEN(osh, p);
+ total += len;
+#ifdef BCMLFRAG
+ if (BCMLFRAG_ENAB()) {
+ if (PKTISFRAG(osh, p)) {
+ total += PKTFRAGTOTLEN(osh, p);
+ }
+ }
+#endif
+ }
+
+ return (total);
+}
+
+/* return the last buffer of chained pkt */
+void *
+pktlast(osl_t *osh, void *p)
+{
+ for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p))
+ ;
+
+ return (p);
+}
+
+/* count segments of a chained packet */
+uint BCMFASTPATH
+pktsegcnt(osl_t *osh, void *p)
+{
+ uint cnt;
+
+ for (cnt = 0; p; p = PKTNEXT(osh, p)) {
+ cnt++;
+#ifdef BCMLFRAG
+ if (BCMLFRAG_ENAB()) {
+ if (PKTISFRAG(osh, p)) {
+ cnt += PKTFRAGTOTNUM(osh, p);
+ }
+ }
+#endif
+ }
+
+ return cnt;
+}
+
+
+/* count segments of a chained packet */
+uint BCMFASTPATH
+pktsegcnt_war(osl_t *osh, void *p)
+{
+ uint cnt;
+ uint8 *pktdata;
+ uint len, remain, align64;
+
+ for (cnt = 0; p; p = PKTNEXT(osh, p)) {
+ cnt++;
+ len = PKTLEN(osh, p);
+ if (len > 128) {
+ pktdata = (uint8 *)PKTDATA(osh, p); /* starting address of data */
+ /* Check for page boundary straddle (2048B) */
+ if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff))
+ cnt++;
+
+ align64 = (uint)((uintptr)pktdata & 0x3f); /* aligned to 64B */
+ align64 = (64 - align64) & 0x3f;
+ len -= align64; /* bytes from aligned 64B to end */
+ /* if aligned to 128B, check for MOD 128 between 1 to 4B */
+ remain = len % 128;
+ if (remain > 0 && remain <= 4)
+ cnt++; /* add extra seg */
+ }
+ }
+
+ return cnt;
+}
+
+uint8 * BCMFASTPATH
+pktdataoffset(osl_t *osh, void *p, uint offset)
+{
+ uint total = pkttotlen(osh, p);
+ uint pkt_off = 0, len = 0;
+ uint8 *pdata = (uint8 *) PKTDATA(osh, p);
+
+ if (offset > total)
+ return NULL;
+
+ for (; p; p = PKTNEXT(osh, p)) {
+ pdata = (uint8 *) PKTDATA(osh, p);
+ pkt_off = offset - len;
+ len += PKTLEN(osh, p);
+ if (len > offset)
+ break;
+ }
+ return (uint8*) (pdata+pkt_off);
+}
+
+
+/* given a offset in pdata, find the pkt seg hdr */
+void *
+pktoffset(osl_t *osh, void *p, uint offset)
+{
+ uint total = pkttotlen(osh, p);
+ uint len = 0;
+
+ if (offset > total)
+ return NULL;
+
+ for (; p; p = PKTNEXT(osh, p)) {
+ len += PKTLEN(osh, p);
+ if (len > offset)
+ break;
+ }
+ return p;
+}
+
+/*
+ * osl multiple-precedence packet queue
+ * hi_prec is always >= the number of the highest non-empty precedence
+ */
+void * BCMFASTPATH
+pktq_penq(struct pktq *pq, int prec, void *p)
+{
+ struct pktq_prec *q;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
+
+
+ ASSERT(!pktq_full(pq));
+ ASSERT(!pktq_pfull(pq, prec));
+ q = &pq->q[prec];
+
+ if (q->head)
+ PKTSETLINK(q->tail, p);
+ else
+ q->head = p;
+
+ q->tail = p;
+ q->len++;
+
+ pq->len++;
+
+ if (pq->hi_prec < prec)
+ pq->hi_prec = (uint8)prec;
+
+ return p;
+}
+
+void * BCMFASTPATH
+pktq_penq_head(struct pktq *pq, int prec, void *p)
+{
+ struct pktq_prec *q;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
+
+
+ ASSERT(!pktq_full(pq));
+ ASSERT(!pktq_pfull(pq, prec));
+ q = &pq->q[prec];
+
+ if (q->head == NULL)
+ q->tail = p;
+
+ PKTSETLINK(p, q->head);
+ q->head = p;
+ q->len++;
+
+ pq->len++;
+
+ if (pq->hi_prec < prec)
+ pq->hi_prec = (uint8)prec;
+
+ return p;
+}
+
+void * BCMFASTPATH
+pktq_pdeq(struct pktq *pq, int prec)
+{
+ struct pktq_prec *q;
+ void *p;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ if ((q->head = PKTLINK(p)) == NULL)
+ q->tail = NULL;
+
+ q->len--;
+
+ pq->len--;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+void * BCMFASTPATH
+pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p)
+{
+ struct pktq_prec *q;
+ void *p;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ q = &pq->q[prec];
+
+ if (prev_p == NULL)
+ return NULL;
+
+ if ((p = PKTLINK(prev_p)) == NULL)
+ return NULL;
+
+ q->len--;
+
+ pq->len--;
+
+ PKTSETLINK(prev_p, PKTLINK(p));
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+void * BCMFASTPATH
+pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg)
+{
+ struct pktq_prec *q;
+ void *p, *prev = NULL;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ q = &pq->q[prec];
+ p = q->head;
+
+ while (p) {
+ if (fn == NULL || (*fn)(p, arg)) {
+ break;
+ } else {
+ prev = p;
+ p = PKTLINK(p);
+ }
+ }
+ if (p == NULL)
+ return NULL;
+
+ if (prev == NULL) {
+ if ((q->head = PKTLINK(p)) == NULL) {
+ q->tail = NULL;
+ }
+ } else {
+ PKTSETLINK(prev, PKTLINK(p));
+ if (q->tail == p) {
+ q->tail = prev;
+ }
+ }
+
+ q->len--;
+
+ pq->len--;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+void * BCMFASTPATH
+pktq_pdeq_tail(struct pktq *pq, int prec)
+{
+ struct pktq_prec *q;
+ void *p, *prev;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ for (prev = NULL; p != q->tail; p = PKTLINK(p))
+ prev = p;
+
+ if (prev)
+ PKTSETLINK(prev, NULL);
+ else
+ q->head = NULL;
+
+ q->tail = prev;
+ q->len--;
+
+ pq->len--;
+
+ return p;
+}
+
+void
+pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg)
+{
+ struct pktq_prec *q;
+ void *p, *prev = NULL;
+
+ q = &pq->q[prec];
+ p = q->head;
+ while (p) {
+ if (fn == NULL || (*fn)(p, arg)) {
+ bool head = (p == q->head);
+ if (head)
+ q->head = PKTLINK(p);
+ else
+ PKTSETLINK(prev, PKTLINK(p));
+ PKTSETLINK(p, NULL);
+ PKTFREE(osh, p, dir);
+ q->len--;
+ pq->len--;
+ p = (head ? q->head : PKTLINK(prev));
+ } else {
+ prev = p;
+ p = PKTLINK(p);
+ }
+ }
+
+ if (q->head == NULL) {
+ ASSERT(q->len == 0);
+ q->tail = NULL;
+ }
+}
+
+bool BCMFASTPATH
+pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
+{
+ struct pktq_prec *q;
+ void *p;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ if (!pktbuf)
+ return FALSE;
+
+ q = &pq->q[prec];
+
+ if (q->head == pktbuf) {
+ if ((q->head = PKTLINK(pktbuf)) == NULL)
+ q->tail = NULL;
+ } else {
+ for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
+ ;
+ if (p == NULL)
+ return FALSE;
+
+ PKTSETLINK(p, PKTLINK(pktbuf));
+ if (q->tail == pktbuf)
+ q->tail = p;
+ }
+
+ q->len--;
+ pq->len--;
+ PKTSETLINK(pktbuf, NULL);
+ return TRUE;
+}
+
+void
+pktq_init(struct pktq *pq, int num_prec, int max_len)
+{
+ int prec;
+
+ ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
+
+ /* pq is variable size; only zero out what's requested */
+ bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
+
+ pq->num_prec = (uint16)num_prec;
+
+ pq->max = (uint16)max_len;
+
+ for (prec = 0; prec < num_prec; prec++)
+ pq->q[prec].max = pq->max;
+}
+
+void
+pktq_set_max_plen(struct pktq *pq, int prec, int max_len)
+{
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ if (prec < pq->num_prec)
+ pq->q[prec].max = (uint16)max_len;
+}
+
+void * BCMFASTPATH
+pktq_deq(struct pktq *pq, int *prec_out)
+{
+ struct pktq_prec *q;
+ void *p;
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+ pq->hi_prec--;
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ if ((q->head = PKTLINK(p)) == NULL)
+ q->tail = NULL;
+
+ q->len--;
+
+ pq->len--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+void * BCMFASTPATH
+pktq_deq_tail(struct pktq *pq, int *prec_out)
+{
+ struct pktq_prec *q;
+ void *p, *prev;
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ for (prec = 0; prec < pq->hi_prec; prec++)
+ if (pq->q[prec].head)
+ break;
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ for (prev = NULL; p != q->tail; p = PKTLINK(p))
+ prev = p;
+
+ if (prev)
+ PKTSETLINK(prev, NULL);
+ else
+ q->head = NULL;
+
+ q->tail = prev;
+ q->len--;
+
+ pq->len--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+void *
+pktq_peek(struct pktq *pq, int *prec_out)
+{
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+ pq->hi_prec--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ return (pq->q[prec].head);
+}
+
+void *
+pktq_peek_tail(struct pktq *pq, int *prec_out)
+{
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ for (prec = 0; prec < pq->hi_prec; prec++)
+ if (pq->q[prec].head)
+ break;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ return (pq->q[prec].tail);
+}
+
+void
+pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg)
+{
+ int prec;
+
+ /* Optimize flush, if pktq len = 0, just return.
+ * pktq len of 0 means pktq's prec q's are all empty.
+ */
+ if (pq->len == 0) {
+ return;
+ }
+
+ for (prec = 0; prec < pq->num_prec; prec++)
+ pktq_pflush(osh, pq, prec, dir, fn, arg);
+ if (fn == NULL)
+ ASSERT(pq->len == 0);
+}
+
+/* Return sum of lengths of a specific set of precedences */
+int
+pktq_mlen(struct pktq *pq, uint prec_bmp)
+{
+ int prec, len;
+
+ len = 0;
+
+ for (prec = 0; prec <= pq->hi_prec; prec++)
+ if (prec_bmp & (1 << prec))
+ len += pq->q[prec].len;
+
+ return len;
+}
+
+/* Priority peek from a specific set of precedences */
+void * BCMFASTPATH
+pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out)
+{
+ struct pktq_prec *q;
+ void *p;
+ int prec;
+
+ if (pq->len == 0)
+ {
+ return NULL;
+ }
+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+ pq->hi_prec--;
+
+ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
+ if (prec-- == 0)
+ return NULL;
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ return p;
+}
+/* Priority dequeue from a specific set of precedences */
+void * BCMFASTPATH
+pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
+{
+ struct pktq_prec *q;
+ void *p;
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+ pq->hi_prec--;
+
+ while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0))
+ if (prec-- == 0)
+ return NULL;
+
+ q = &pq->q[prec];
+
+ if ((p = q->head) == NULL)
+ return NULL;
+
+ if ((q->head = PKTLINK(p)) == NULL)
+ q->tail = NULL;
+
+ q->len--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ pq->len--;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+#endif /* BCMDRIVER */
+
+#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
+const unsigned char bcm_ctype[] = {
+
+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */
+ _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C,
+ _BCM_C, /* 8-15 */
+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */
+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */
+ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */
+ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */
+ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */
+ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */
+ _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X,
+ _BCM_U|_BCM_X, _BCM_U, /* 64-71 */
+ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */
+ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */
+ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */
+ _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X,
+ _BCM_L|_BCM_X, _BCM_L, /* 96-103 */
+ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
+ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
+ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */
+ _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
+ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */
+ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
+ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */
+ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
+ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */
+ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U,
+ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */
+ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
+ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */
+ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L,
+ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
+};
+
+ulong
+bcm_strtoul(const char *cp, char **endp, uint base)
+{
+ ulong result, last_result = 0, value;
+ bool minus;
+
+ minus = FALSE;
+
+ while (bcm_isspace(*cp))
+ cp++;
+
+ if (cp[0] == '+')
+ cp++;
+ else if (cp[0] == '-') {
+ minus = TRUE;
+ cp++;
+ }
+
+ if (base == 0) {
+ if (cp[0] == '0') {
+ if ((cp[1] == 'x') || (cp[1] == 'X')) {
+ base = 16;
+ cp = &cp[2];
+ } else {
+ base = 8;
+ cp = &cp[1];
+ }
+ } else
+ base = 10;
+ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
+ cp = &cp[2];
+ }
+
+ result = 0;
+
+ while (bcm_isxdigit(*cp) &&
+ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
+ result = result*base + value;
+ /* Detected overflow */
+ if (result < last_result && !minus)
+ return (ulong)-1;
+ last_result = result;
+ cp++;
+ }
+
+ if (minus)
+ result = (ulong)(-(long)result);
+
+ if (endp)
+ *endp = DISCARD_QUAL(cp, char);
+
+ return (result);
+}
+
+int
+bcm_atoi(const char *s)
+{
+ return (int)bcm_strtoul(s, NULL, 10);
+}
+
+/* return pointer to location of substring 'needle' in 'haystack' */
+char *
+bcmstrstr(const char *haystack, const char *needle)
+{
+ int len, nlen;
+ int i;
+
+ if ((haystack == NULL) || (needle == NULL))
+ return DISCARD_QUAL(haystack, char);
+
+ nlen = strlen(needle);
+ len = strlen(haystack) - nlen + 1;
+
+ for (i = 0; i < len; i++)
+ if (memcmp(needle, &haystack[i], nlen) == 0)
+ return DISCARD_QUAL(&haystack[i], char);
+ return (NULL);
+}
+
+char *
+bcmstrcat(char *dest, const char *src)
+{
+ char *p;
+
+ p = dest + strlen(dest);
+
+ while ((*p++ = *src++) != '\0')
+ ;
+
+ return (dest);
+}
+
+char *
+bcmstrncat(char *dest, const char *src, uint size)
+{
+ char *endp;
+ char *p;
+
+ p = dest + strlen(dest);
+ endp = p + size;
+
+ while (p != endp && (*p++ = *src++) != '\0')
+ ;
+
+ return (dest);
+}
+
+
+/****************************************************************************
+* Function: bcmstrtok
+*
+* Purpose:
+* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(),
+* but allows strToken() to be used by different strings or callers at the same
+* time. Each call modifies '*string' by substituting a NULL character for the
+* first delimiter that is encountered, and updates 'string' to point to the char
+* after the delimiter. Leading delimiters are skipped.
+*
+* Parameters:
+* string (mod) Ptr to string ptr, updated by token.
+* delimiters (in) Set of delimiter characters.
+* tokdelim (out) Character that delimits the returned token. (May
+* be set to NULL if token delimiter is not required).
+*
+* Returns: Pointer to the next token found. NULL when no more tokens are found.
+*****************************************************************************
+*/
+char *
+bcmstrtok(char **string, const char *delimiters, char *tokdelim)
+{
+ unsigned char *str;
+ unsigned long map[8];
+ int count;
+ char *nextoken;
+
+ if (tokdelim != NULL) {
+ /* Prime the token delimiter */
+ *tokdelim = '\0';
+ }
+
+ /* Clear control map */
+ for (count = 0; count < 8; count++) {
+ map[count] = 0;
+ }
+
+ /* Set bits in delimiter table */
+ do {
+ map[*delimiters >> 5] |= (1 << (*delimiters & 31));
+ }
+ while (*delimiters++);
+
+ str = (unsigned char*)*string;
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets str to point to the terminal
+ * null (*str == '\0')
+ */
+ while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) {
+ str++;
+ }
+
+ nextoken = (char*)str;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there.
+ */
+ for (; *str; str++) {
+ if (map[*str >> 5] & (1 << (*str & 31))) {
+ if (tokdelim != NULL) {
+ *tokdelim = *str;
+ }
+
+ *str++ = '\0';
+ break;
+ }
+ }
+
+ *string = (char*)str;
+
+ /* Determine if a token has been found. */
+ if (nextoken == (char *) str) {
+ return NULL;
+ }
+ else {
+ return nextoken;
+ }
+}
+
+
+#define xToLower(C) \
+ ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C)
+
+
+/****************************************************************************
+* Function: bcmstricmp
+*
+* Purpose: Compare to strings case insensitively.
+*
+* Parameters: s1 (in) First string to compare.
+* s2 (in) Second string to compare.
+*
+* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
+* t1 > t2, when ignoring case sensitivity.
+*****************************************************************************
+*/
+int
+bcmstricmp(const char *s1, const char *s2)
+{
+ char dc, sc;
+
+ while (*s2 && *s1) {
+ dc = xToLower(*s1);
+ sc = xToLower(*s2);
+ if (dc < sc) return -1;
+ if (dc > sc) return 1;
+ s1++;
+ s2++;
+ }
+
+ if (*s1 && !*s2) return 1;
+ if (!*s1 && *s2) return -1;
+ return 0;
+}
+
+
+/****************************************************************************
+* Function: bcmstrnicmp
+*
+* Purpose: Compare to strings case insensitively, upto a max of 'cnt'
+* characters.
+*
+* Parameters: s1 (in) First string to compare.
+* s2 (in) Second string to compare.
+* cnt (in) Max characters to compare.
+*
+* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
+* t1 > t2, when ignoring case sensitivity.
+*****************************************************************************
+*/
+int
+bcmstrnicmp(const char* s1, const char* s2, int cnt)
+{
+ char dc, sc;
+
+ while (*s2 && *s1 && cnt) {
+ dc = xToLower(*s1);
+ sc = xToLower(*s2);
+ if (dc < sc) return -1;
+ if (dc > sc) return 1;
+ s1++;
+ s2++;
+ cnt--;
+ }
+
+ if (!cnt) return 0;
+ if (*s1 && !*s2) return 1;
+ if (!*s1 && *s2) return -1;
+ return 0;
+}
+
+/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
+int
+bcm_ether_atoe(const char *p, struct ether_addr *ea)
+{
+ int i = 0;
+ char *ep;
+
+ for (;;) {
+ ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16);
+ p = ep;
+ if (!*p++ || i == 6)
+ break;
+ }
+
+ return (i == 6);
+}
+
+int
+bcm_atoipv4(const char *p, struct ipv4_addr *ip)
+{
+
+ int i = 0;
+ char *c;
+ for (;;) {
+ ip->addr[i++] = (uint8)bcm_strtoul(p, &c, 0);
+ if (*c++ != '.' || i == IPV4_ADDR_LEN)
+ break;
+ p = c;
+ }
+ return (i == IPV4_ADDR_LEN);
+}
+#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
+
+
+#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
+/* registry routine buffer preparation utility functions:
+ * parameter order is like strncpy, but returns count
+ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2)
+ */
+ulong
+wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen)
+{
+ ulong copyct = 1;
+ ushort i;
+
+ if (abuflen == 0)
+ return 0;
+
+ /* wbuflen is in bytes */
+ wbuflen /= sizeof(ushort);
+
+ for (i = 0; i < wbuflen; ++i) {
+ if (--abuflen == 0)
+ break;
+ *abuf++ = (char) *wbuf++;
+ ++copyct;
+ }
+ *abuf = '\0';
+
+ return copyct;
+}
+#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */
+
+char *
+bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
+{
+ static const char hex[] =
+ {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+ const uint8 *octet = ea->octet;
+ char *p = buf;
+ int i;
+
+ for (i = 0; i < 6; i++, octet++) {
+ *p++ = hex[(*octet >> 4) & 0xf];
+ *p++ = hex[*octet & 0xf];
+ *p++ = ':';
+ }
+
+ *(p-1) = '\0';
+
+ return (buf);
+}
+
+char *
+bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
+{
+ snprintf(buf, 16, "%d.%d.%d.%d",
+ ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
+ return (buf);
+}
+
+char *
+bcm_ipv6_ntoa(void *ipv6, char *buf)
+{
+ /* Implementing RFC 5952 Sections 4 + 5 */
+ /* Not thoroughly tested */
+ uint16 tmp[8];
+ uint16 *a = &tmp[0];
+ char *p = buf;
+ int i, i_max = -1, cnt = 0, cnt_max = 1;
+ uint8 *a4 = NULL;
+ memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN);
+
+ for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+ if (a[i]) {
+ if (cnt > cnt_max) {
+ cnt_max = cnt;
+ i_max = i - cnt;
+ }
+ cnt = 0;
+ } else
+ cnt++;
+ }
+ if (cnt > cnt_max) {
+ cnt_max = cnt;
+ i_max = i - cnt;
+ }
+ if (i_max == 0 &&
+ /* IPv4-translated: ::ffff:0:a.b.c.d */
+ ((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
+ /* IPv4-mapped: ::ffff:a.b.c.d */
+ (cnt_max == 5 && a[5] == 0xffff)))
+ a4 = (uint8*) (a + 6);
+
+ for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+ if ((uint8*) (a + i) == a4) {
+ snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
+ break;
+ } else if (i == i_max) {
+ *p++ = ':';
+ i += cnt_max - 1;
+ p[0] = ':';
+ p[1] = '\0';
+ } else {
+ if (i)
+ *p++ = ':';
+ p += snprintf(p, 8, "%x", ntoh16(a[i]));
+ }
+ }
+
+ return buf;
+}
+#ifdef BCMDRIVER
+
+void
+bcm_mdelay(uint ms)
+{
+ uint i;
+
+ for (i = 0; i < ms; i++) {
+ OSL_DELAY(1000);
+ }
+}
+
+
+
+
+
+#if defined(DHD_DEBUG)
+/* pretty hex print a pkt buffer chain */
+void
+prpkt(const char *msg, osl_t *osh, void *p0)
+{
+ void *p;
+
+ if (msg && (msg[0] != '\0'))
+ printf("%s:\n", msg);
+
+ for (p = p0; p; p = PKTNEXT(osh, p))
+ prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p));
+}
+#endif
+
+/* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
+ * Also updates the inplace vlan tag if requested.
+ * For debugging, it returns an indication of what it did.
+ */
+uint BCMFASTPATH
+pktsetprio(void *pkt, bool update_vtag)
+{
+ struct ether_header *eh;
+ struct ethervlan_header *evh;
+ uint8 *pktdata;
+ int priority = 0;
+ int rc = 0;
+
+ pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
+ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
+
+ eh = (struct ether_header *) pktdata;
+
+ if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
+ uint16 vlan_tag;
+ int vlan_prio, dscp_prio = 0;
+
+ evh = (struct ethervlan_header *)eh;
+
+ vlan_tag = ntoh16(evh->vlan_tag);
+ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
+
+ if (evh->ether_type == hton16(ETHER_TYPE_IP)) {
+ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
+ uint8 tos_tc = IP_TOS46(ip_body);
+ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+ }
+
+ /* DSCP priority gets precedence over 802.1P (vlan tag) */
+ if (dscp_prio != 0) {
+ priority = dscp_prio;
+ rc |= PKTPRIO_VDSCP;
+ } else {
+ priority = vlan_prio;
+ rc |= PKTPRIO_VLAN;
+ }
+ /*
+ * If the DSCP priority is not the same as the VLAN priority,
+ * then overwrite the priority field in the vlan tag, with the
+ * DSCP priority value. This is required for Linux APs because
+ * the VLAN driver on Linux, overwrites the skb->priority field
+ * with the priority value in the vlan tag
+ */
+ if (update_vtag && (priority != vlan_prio)) {
+ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
+ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
+ evh->vlan_tag = hton16(vlan_tag);
+ rc |= PKTPRIO_UPD;
+ }
+ } else if (eh->ether_type == hton16(ETHER_TYPE_IP)) {
+ uint8 *ip_body = pktdata + sizeof(struct ether_header);
+ uint8 tos_tc = IP_TOS46(ip_body);
+ uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT;
+ switch (dscp) {
+ case DSCP_EF:
+ priority = PRIO_8021D_VO;
+ break;
+ case DSCP_AF31:
+ case DSCP_AF32:
+ case DSCP_AF33:
+ priority = PRIO_8021D_CL;
+ break;
+ case DSCP_AF21:
+ case DSCP_AF22:
+ case DSCP_AF23:
+ case DSCP_AF11:
+ case DSCP_AF12:
+ case DSCP_AF13:
+ priority = PRIO_8021D_EE;
+ break;
+ default:
+ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+ break;
+ }
+
+ rc |= PKTPRIO_DSCP;
+ }
+
+ ASSERT(priority >= 0 && priority <= MAXPRIO);
+ PKTSETPRIO(pkt, priority);
+ return (rc | priority);
+}
+
+
+static char bcm_undeferrstr[32];
+static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
+
+/* Convert the error codes into related error strings */
+const char *
+bcmerrorstr(int bcmerror)
+{
+ /* check if someone added a bcmerror code but forgot to add errorstring */
+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
+
+ if (bcmerror > 0 || bcmerror < BCME_LAST) {
+ snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror);
+ return bcm_undeferrstr;
+ }
+
+ ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
+
+ return bcmerrorstrtable[-bcmerror];
+}
+
+
+
+/* iovar table lookup */
+const bcm_iovar_t*
+bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
+{
+ const bcm_iovar_t *vi;
+ const char *lookup_name;
+
+ /* skip any ':' delimited option prefixes */
+ lookup_name = strrchr(name, ':');
+ if (lookup_name != NULL)
+ lookup_name++;
+ else
+ lookup_name = name;
+
+ ASSERT(table != NULL);
+
+ for (vi = table; vi->name; vi++) {
+ if (!strcmp(vi->name, lookup_name))
+ return vi;
+ }
+ /* ran to end of table */
+
+ return NULL; /* var name not found */
+}
+
+int
+bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
+{
+ int bcmerror = 0;
+
+ /* length check on io buf */
+ switch (vi->type) {
+ case IOVT_BOOL:
+ case IOVT_INT8:
+ case IOVT_INT16:
+ case IOVT_INT32:
+ case IOVT_UINT8:
+ case IOVT_UINT16:
+ case IOVT_UINT32:
+ /* all integers are int32 sized args at the ioctl interface */
+ if (len < (int)sizeof(int)) {
+ bcmerror = BCME_BUFTOOSHORT;
+ }
+ break;
+
+ case IOVT_BUFFER:
+ /* buffer must meet minimum length requirement */
+ if (len < vi->minlen) {
+ bcmerror = BCME_BUFTOOSHORT;
+ }
+ break;
+
+ case IOVT_VOID:
+ if (!set) {
+ /* Cannot return nil... */
+ bcmerror = BCME_UNSUPPORTED;
+ } else if (len) {
+ /* Set is an action w/o parameters */
+ bcmerror = BCME_BUFTOOLONG;
+ }
+ break;
+
+ default:
+ /* unknown type for length check in iovar info */
+ ASSERT(0);
+ bcmerror = BCME_UNSUPPORTED;
+ }
+
+ return bcmerror;
+}
+
+#endif /* BCMDRIVER */
+
+
+uint8 *
+bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst)
+{
+ uint8 *new_dst = dst;
+ bcm_tlv_t *dst_tlv = (bcm_tlv_t *)dst;
+
+ /* dst buffer should always be valid */
+ ASSERT(dst);
+
+ /* data len must be within valid range */
+ ASSERT((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE));
+
+ /* source data buffer pointer should be valid, unless datalen is 0
+ * meaning no data with this TLV
+ */
+ ASSERT((data != NULL) || (datalen == 0));
+
+ /* only do work if the inputs are valid
+ * - must have a dst to write to AND
+ * - datalen must be within range AND
+ * - the source data pointer must be non-NULL if datalen is non-zero
+ * (this last condition detects datalen > 0 with a NULL data pointer)
+ */
+ if ((dst != NULL) &&
+ ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) &&
+ ((data != NULL) || (datalen == 0))) {
+
+ /* write type, len fields */
+ dst_tlv->id = (uint8)type;
+ dst_tlv->len = (uint8)datalen;
+
+ /* if data is present, copy to the output buffer and update
+ * pointer to output buffer
+ */
+ if (datalen > 0) {
+
+ memcpy(dst_tlv->data, data, datalen);
+ }
+
+ /* update the output destination poitner to point past
+ * the TLV written
+ */
+ new_dst = dst + BCM_TLV_HDR_SIZE + datalen;
+ }
+
+ return (new_dst);
+}
+
+uint8 *
+bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, int dst_maxlen)
+{
+ uint8 *new_dst = dst;
+
+ if ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) {
+
+ /* if len + tlv hdr len is more than destlen, don't do anything
+ * just return the buffer untouched
+ */
+ if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) {
+
+ new_dst = bcm_write_tlv(type, data, datalen, dst);
+ }
+ }
+
+ return (new_dst);
+}
+
+uint8 *
+bcm_copy_tlv(const void *src, uint8 *dst)
+{
+ uint8 *new_dst = dst;
+ const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
+ uint totlen;
+
+ ASSERT(dst && src);
+ if (dst && src) {
+
+ totlen = BCM_TLV_HDR_SIZE + src_tlv->len;
+ memcpy(dst, src_tlv, totlen);
+ new_dst = dst + totlen;
+ }
+
+ return (new_dst);
+}
+
+
+uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen)
+{
+ uint8 *new_dst = dst;
+ const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
+
+ ASSERT(src);
+ if (src) {
+ if (bcm_valid_tlv(src_tlv, dst_maxlen)) {
+ new_dst = bcm_copy_tlv(src, dst);
+ }
+ }
+
+ return (new_dst);
+}
+
+
+#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
+/*******************************************************************************
+ * crc8
+ *
+ * Computes a crc8 over the input data using the polynomial:
+ *
+ * x^8 + x^7 +x^6 + x^4 + x^2 + 1
+ *
+ * The caller provides the initial value (either CRC8_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data. When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream. When checking, a final
+ * return value of CRC8_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const uint8 crc8_table[256] = {
+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
+};
+
+#define CRC_INNER_LOOP(n, c, x) \
+ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
+
+uint8
+hndcrc8(
+ uint8 *pdata, /* pointer to array of data to process */
+ uint nbytes, /* number of input data bytes to process */
+ uint8 crc /* either CRC8_INIT_VALUE or previous return value */
+)
+{
+ /* hard code the crc loop instead of using CRC_INNER_LOOP macro
+ * to avoid the undefined and unnecessary (uint8 >> 8) operation.
+ */
+ while (nbytes-- > 0)
+ crc = crc8_table[(crc ^ *pdata++) & 0xff];
+
+ return crc;
+}
+
+/*******************************************************************************
+ * crc16
+ *
+ * Computes a crc16 over the input data using the polynomial:
+ *
+ * x^16 + x^12 +x^5 + 1
+ *
+ * The caller provides the initial value (either CRC16_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data. When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream. When checking, a final
+ * return value of CRC16_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const uint16 crc16_table[256] = {
+ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
+ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
+ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
+ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
+ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
+ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
+ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
+ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
+ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
+ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
+ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
+ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
+ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
+ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
+ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
+ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
+ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
+ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
+ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
+ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
+ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
+ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
+ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
+ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
+ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
+ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
+ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
+ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
+ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
+ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
+ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
+ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
+};
+
+uint16
+hndcrc16(
+ uint8 *pdata, /* pointer to array of data to process */
+ uint nbytes, /* number of input data bytes to process */
+ uint16 crc /* either CRC16_INIT_VALUE or previous return value */
+)
+{
+ while (nbytes-- > 0)
+ CRC_INNER_LOOP(16, crc, *pdata++);
+ return crc;
+}
+
+static const uint32 crc32_table[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+/*
+ * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if
+ * accumulating over multiple pieces.
+ */
+uint32
+hndcrc32(uint8 *pdata, uint nbytes, uint32 crc)
+{
+ uint8 *pend;
+ pend = pdata + nbytes;
+ while (pdata < pend)
+ CRC_INNER_LOOP(32, crc, *pdata++);
+
+ return crc;
+}
+
+#ifdef notdef
+#define CLEN 1499 /* CRC Length */
+#define CBUFSIZ (CLEN+4)
+#define CNBUFS 5 /* # of bufs */
+
+void
+testcrc32(void)
+{
+ uint j, k, l;
+ uint8 *buf;
+ uint len[CNBUFS];
+ uint32 crcr;
+ uint32 crc32tv[CNBUFS] =
+ {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110};
+
+ ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL);
+
+ /* step through all possible alignments */
+ for (l = 0; l <= 4; l++) {
+ for (j = 0; j < CNBUFS; j++) {
+ len[j] = CLEN;
+ for (k = 0; k < len[j]; k++)
+ *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff;
+ }
+
+ for (j = 0; j < CNBUFS; j++) {
+ crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE);
+ ASSERT(crcr == crc32tv[j]);
+ }
+ }
+
+ MFREE(buf, CBUFSIZ*CNBUFS);
+ return;
+}
+#endif /* notdef */
+
+/*
+ * Advance from the current 1-byte tag/1-byte length/variable-length value
+ * triple, to the next, returning a pointer to the next.
+ * If the current or next TLV is invalid (does not fit in given buffer length),
+ * NULL is returned.
+ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented
+ * by the TLV parameter's length if it is valid.
+ */
+bcm_tlv_t *
+bcm_next_tlv(bcm_tlv_t *elt, int *buflen)
+{
+ int len;
+
+ /* validate current elt */
+ if (!bcm_valid_tlv(elt, *buflen)) {
+ return NULL;
+ }
+
+ /* advance to next elt */
+ len = elt->len;
+ elt = (bcm_tlv_t*)(elt->data + len);
+ *buflen -= (TLV_HDR_LEN + len);
+
+ /* validate next elt */
+ if (!bcm_valid_tlv(elt, *buflen)) {
+ return NULL;
+ }
+
+ return elt;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+bcm_tlv_t *
+bcm_parse_tlvs(void *buf, int buflen, uint key)
+{
+ bcm_tlv_t *elt;
+ int totlen;
+
+ if ((elt = (bcm_tlv_t*)buf) == NULL) {
+ return NULL;
+ }
+ totlen = buflen;
+
+ /* find tagged parameter */
+ while (totlen >= TLV_HDR_LEN) {
+ int len = elt->len;
+
+ /* validate remaining totlen */
+ if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
+
+ return (elt);
+ }
+
+ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
+ totlen -= (len + TLV_HDR_LEN);
+ }
+
+ return NULL;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag. Stop parsing when we see an element whose ID is greater
+ * than the target key.
+ */
+bcm_tlv_t *
+bcm_parse_ordered_tlvs(void *buf, int buflen, uint key)
+{
+ bcm_tlv_t *elt;
+ int totlen;
+
+ elt = (bcm_tlv_t*)buf;
+ totlen = buflen;
+
+ /* find tagged parameter */
+ while (totlen >= TLV_HDR_LEN) {
+ uint id = elt->id;
+ int len = elt->len;
+
+ /* Punt if we start seeing IDs > than target key */
+ if (id > key) {
+ return (NULL);
+ }
+
+ /* validate remaining totlen */
+ if ((id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
+ return (elt);
+ }
+
+ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
+ totlen -= (len + TLV_HDR_LEN);
+ }
+ return NULL;
+}
+#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
+
+#if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \
+ defined(DHD_DEBUG)
+int
+bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len)
+{
+ int i, slen = 0;
+ uint32 bit, mask;
+ const char *name;
+ mask = bd->mask;
+ if (len < 2 || !buf)
+ return 0;
+
+ buf[0] = '\0';
+
+ for (i = 0; (name = bd->bitfield[i].name) != NULL; i++) {
+ bit = bd->bitfield[i].bit;
+ if ((flags & mask) == bit) {
+ if (len > (int)strlen(name)) {
+ slen = strlen(name);
+ strncpy(buf, name, slen+1);
+ }
+ break;
+ }
+ }
+ return slen;
+}
+
+int
+bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len)
+{
+ int i;
+ char* p = buf;
+ char hexstr[16];
+ int slen = 0, nlen = 0;
+ uint32 bit;
+ const char* name;
+
+ if (len < 2 || !buf)
+ return 0;
+
+ buf[0] = '\0';
+
+ for (i = 0; flags != 0; i++) {
+ bit = bd[i].bit;
+ name = bd[i].name;
+ if (bit == 0 && flags != 0) {
+ /* print any unnamed bits */
+ snprintf(hexstr, 16, "0x%X", flags);
+ name = hexstr;
+ flags = 0; /* exit loop */
+ } else if ((flags & bit) == 0)
+ continue;
+ flags &= ~bit;
+ nlen = strlen(name);
+ slen += nlen;
+ /* count btwn flag space */
+ if (flags != 0)
+ slen += 1;
+ /* need NULL char as well */
+ if (len <= slen)
+ break;
+ /* copy NULL char but don't count it */
+ strncpy(p, name, nlen + 1);
+ p += nlen;
+ /* copy btwn flag space and NULL char */
+ if (flags != 0)
+ p += snprintf(p, 2, " ");
+ }
+
+ /* indicate the str was too short */
+ if (flags != 0) {
+ p += snprintf(p, 2, ">");
+ }
+
+ return (int)(p - buf);
+}
+#endif
+
+/* print bytes formatted as hex to a string. return the resulting string length */
+int
+bcm_format_hex(char *str, const void *bytes, int len)
+{
+ int i;
+ char *p = str;
+ const uint8 *src = (const uint8*)bytes;
+
+ for (i = 0; i < len; i++) {
+ p += snprintf(p, 3, "%02X", *src);
+ src++;
+ }
+ return (int)(p - str);
+}
+
+/* pretty hex print a contiguous buffer */
+void
+prhex(const char *msg, uchar *buf, uint nbytes)
+{
+ char line[128], *p;
+ int len = sizeof(line);
+ int nchar;
+ uint i;
+
+ if (msg && (msg[0] != '\0'))
+ printf("%s:\n", msg);
+
+ p = line;
+ for (i = 0; i < nbytes; i++) {
+ if (i % 16 == 0) {
+ nchar = snprintf(p, len, " %04d: ", i); /* line prefix */
+ p += nchar;
+ len -= nchar;
+ }
+ if (len > 0) {
+ nchar = snprintf(p, len, "%02x ", buf[i]);
+ p += nchar;
+ len -= nchar;
+ }
+
+ if (i % 16 == 15) {
+ printf("%s\n", line); /* flush line */
+ p = line;
+ len = sizeof(line);
+ }
+ }
+
+ /* flush last partial line */
+ if (p != line)
+ printf("%s\n", line);
+}
+
+static const char *crypto_algo_names[] = {
+ "NONE",
+ "WEP1",
+ "TKIP",
+ "WEP128",
+ "AES_CCM",
+ "AES_OCB_MSDU",
+ "AES_OCB_MPDU",
+ "NALG",
+ "UNDEF",
+ "UNDEF",
+ "UNDEF",
+ "WAPI",
+ "PMK",
+ "BIP",
+ "AES_GCM",
+ "AES_CCM256",
+ "AES_GCM256",
+ "BIP_CMAC256",
+ "BIP_GMAC",
+ "BIP_GMAC256",
+ "UNDEF"
+};
+
+const char *
+bcm_crypto_algo_name(uint algo)
+{
+ return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR";
+}
+
+
+char *
+bcm_chipname(uint chipid, char *buf, uint len)
+{
+ const char *fmt;
+
+ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
+ snprintf(buf, len, fmt, chipid);
+ return buf;
+}
+
+/* Produce a human-readable string for boardrev */
+char *
+bcm_brev_str(uint32 brev, char *buf)
+{
+ if (brev < 0x100)
+ snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
+ else
+ snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff);
+
+ return (buf);
+}
+
+#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */
+
+/* dump large strings to console */
+void
+printbig(char *buf)
+{
+ uint len, max_len;
+ char c;
+
+ len = strlen(buf);
+
+ max_len = BUFSIZE_TODUMP_ATONCE;
+
+ while (len > max_len) {
+ c = buf[max_len];
+ buf[max_len] = '\0';
+ printf("%s", buf);
+ buf[max_len] = c;
+
+ buf += max_len;
+ len -= max_len;
+ }
+ /* print the remaining string */
+ printf("%s\n", buf);
+ return;
+}
+
+/* routine to dump fields in a fileddesc structure */
+uint
+bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array,
+ char *buf, uint32 bufsize)
+{
+ uint filled_len;
+ int len;
+ struct fielddesc *cur_ptr;
+
+ filled_len = 0;
+ cur_ptr = fielddesc_array;
+
+ while (bufsize > 1) {
+ if (cur_ptr->nameandfmt == NULL)
+ break;
+ len = snprintf(buf, bufsize, cur_ptr->nameandfmt,
+ read_rtn(arg0, arg1, cur_ptr->offset));
+ /* check for snprintf overflow or error */
+ if (len < 0 || (uint32)len >= bufsize)
+ len = bufsize - 1;
+ buf += len;
+ bufsize -= len;
+ filled_len += len;
+ cur_ptr++;
+ }
+ return filled_len;
+}
+
+uint
+bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
+{
+ uint len;
+
+ len = strlen(name) + 1;
+
+ if ((len + datalen) > buflen)
+ return 0;
+
+ strncpy(buf, name, buflen);
+
+ /* append data onto the end of the name string */
+ if (data) {
+ memcpy(&buf[len], data, datalen);
+ len += datalen;
+ }
+
+ return len;
+}
+
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a uint16.
+ */
+
+#define QDBM_OFFSET 153 /* Offset for first entry */
+#define QDBM_TABLE_LEN 40 /* Table size */
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
+
+static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
+/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
+/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
+/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
+/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
+/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
+};
+
+uint16
+bcm_qdbm_to_mw(uint8 qdbm)
+{
+ uint factor = 1;
+ int idx = qdbm - QDBM_OFFSET;
+
+ if (idx >= QDBM_TABLE_LEN) {
+ /* clamp to max uint16 mW value */
+ return 0xFFFF;
+ }
+
+ /* scale the qdBm index up to the range of the table 0-40
+ * where an offset of 40 qdBm equals a factor of 10 mW.
+ */
+ while (idx < 0) {
+ idx += 40;
+ factor *= 10;
+ }
+
+ /* return the mW value scaled down to the correct factor of 10,
+ * adding in factor/2 to get proper rounding.
+ */
+ return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
+}
+
+uint8
+bcm_mw_to_qdbm(uint16 mw)
+{
+ uint8 qdbm;
+ int offset;
+ uint mw_uint = mw;
+ uint boundary;
+
+ /* handle boundary case */
+ if (mw_uint <= 1)
+ return 0;
+
+ offset = QDBM_OFFSET;
+
+ /* move mw into the range of the table */
+ while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+ mw_uint *= 10;
+ offset -= 40;
+ }
+
+ for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
+ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] -
+ nqdBm_to_mW_map[qdbm])/2;
+ if (mw_uint < boundary) break;
+ }
+
+ qdbm += (uint8)offset;
+
+ return (qdbm);
+}
+
+
+uint
+bcm_bitcount(uint8 *bitmap, uint length)
+{
+ uint bitcount = 0, i;
+ uint8 tmp;
+ for (i = 0; i < length; i++) {
+ tmp = bitmap[i];
+ while (tmp) {
+ bitcount++;
+ tmp &= (tmp - 1);
+ }
+ }
+ return bitcount;
+}
+
+#ifdef BCMDRIVER
+
+/* Initialization of bcmstrbuf structure */
+void
+bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
+{
+ b->origsize = b->size = size;
+ b->origbuf = b->buf = buf;
+}
+
+/* Buffer sprintf wrapper to guard against buffer overflow */
+int
+bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+
+ r = vsnprintf(b->buf, b->size, fmt, ap);
+
+ /* Non Ansi C99 compliant returns -1,
+ * Ansi compliant return r >= b->size,
+ * bcmstdlib returns 0, handle all
+ */
+ /* r == 0 is also the case when strlen(fmt) is zero.
+ * typically the case when "" is passed as argument.
+ */
+ if ((r == -1) || (r >= (int)b->size)) {
+ b->size = 0;
+ } else {
+ b->size -= r;
+ b->buf += r;
+ }
+
+ va_end(ap);
+
+ return r;
+}
+
+void
+bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len)
+{
+ int i;
+
+ if (msg != NULL && msg[0] != '\0')
+ bcm_bprintf(b, "%s", msg);
+ for (i = 0; i < len; i ++)
+ bcm_bprintf(b, "%02X", buf[i]);
+ if (newline)
+ bcm_bprintf(b, "\n");
+}
+
+void
+bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount)
+{
+ int i;
+
+ for (i = 0; i < num_bytes; i++) {
+ num[i] += amount;
+ if (num[i] >= amount)
+ break;
+ amount = 1;
+ }
+}
+
+int
+bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes)
+{
+ int i;
+
+ for (i = nbytes - 1; i >= 0; i--) {
+ if (arg1[i] != arg2[i])
+ return (arg1[i] - arg2[i]);
+ }
+ return 0;
+}
+
+void
+bcm_print_bytes(const char *name, const uchar *data, int len)
+{
+ int i;
+ int per_line = 0;
+
+ printf("%s: %d \n", name ? name : "", len);
+ for (i = 0; i < len; i++) {
+ printf("%02x ", *data++);
+ per_line++;
+ if (per_line == 16) {
+ per_line = 0;
+ printf("\n");
+ }
+ }
+ printf("\n");
+}
+
+/* Look for vendor-specific IE with specified OUI and optional type */
+bcm_tlv_t *
+bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len)
+{
+ bcm_tlv_t *ie;
+ uint8 ie_len;
+
+ ie = (bcm_tlv_t*)tlvs;
+
+ /* make sure we are looking at a valid IE */
+ if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) {
+ return NULL;
+ }
+
+ /* Walk through the IEs looking for an OUI match */
+ do {
+ ie_len = ie->len;
+ if ((ie->id == DOT11_MNG_PROPR_ID) &&
+ (ie_len >= (DOT11_OUI_LEN + type_len)) &&
+ !bcmp(ie->data, voui, DOT11_OUI_LEN))
+ {
+ /* compare optional type */
+ if (type_len == 0 ||
+ !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
+ return (ie); /* a match */
+ }
+ }
+ } while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
+
+ return NULL;
+}
+
+#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
+ defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
+#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1)
+
+int
+bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len)
+{
+ uint i, c;
+ char *p = buf;
+ char *endp = buf + SSID_FMT_BUF_LEN;
+
+ if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN;
+
+ for (i = 0; i < ssid_len; i++) {
+ c = (uint)ssid[i];
+ if (c == '\\') {
+ *p++ = '\\';
+ *p++ = '\\';
+ } else if (bcm_isprint((uchar)c)) {
+ *p++ = (char)c;
+ } else {
+ p += snprintf(p, (endp - p), "\\x%02X", c);
+ }
+ }
+ *p = '\0';
+ ASSERT(p < endp);
+
+ return (int)(p - buf);
+}
+#endif
+
+#endif /* BCMDRIVER */
+
+/*
+ * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
+ * also accepts nvram files which are already in the format of <var1>=<value>\0\<var2>=<value2>\0
+ * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs.
+ * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs.
+*/
+
+unsigned int
+process_nvram_vars(char *varbuf, unsigned int len)
+{
+ char *dp;
+ bool findNewline;
+ int column;
+ unsigned int buf_len, n;
+ unsigned int pad = 0;
+
+ dp = varbuf;
+
+ findNewline = FALSE;
+ column = 0;
+
+ for (n = 0; n < len; n++) {
+ if (varbuf[n] == '\r')
+ continue;
+ if (findNewline && varbuf[n] != '\n')
+ continue;
+ findNewline = FALSE;
+ if (varbuf[n] == '#') {
+ findNewline = TRUE;
+ continue;
+ }
+ if (varbuf[n] == '\n') {
+ if (column == 0)
+ continue;
+ *dp++ = 0;
+ column = 0;
+ continue;
+ }
+ *dp++ = varbuf[n];
+ column++;
+ }
+ buf_len = (unsigned int)(dp - varbuf);
+ if (buf_len % 4) {
+ pad = 4 - buf_len % 4;
+ if (pad && (buf_len + pad <= len)) {
+ buf_len += pad;
+ }
+ }
+
+ while (dp < varbuf + n)
+ *dp++ = 0;
+
+ return buf_len;
+}
+
+/* calculate a * b + c */
+void
+bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c)
+{
+#define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;}
+ uint32 r1, r0;
+ uint32 a1, a0, b1, b0, t, cc = 0;
+
+ a1 = a >> 16;
+ a0 = a & 0xffff;
+ b1 = b >> 16;
+ b0 = b & 0xffff;
+
+ r0 = a0 * b0;
+ FORMALIZE(r0);
+
+ t = (a1 * b0) << 16;
+ FORMALIZE(t);
+
+ r0 += t;
+ FORMALIZE(r0);
+
+ t = (a0 * b1) << 16;
+ FORMALIZE(t);
+
+ r0 += t;
+ FORMALIZE(r0);
+
+ FORMALIZE(c);
+
+ r0 += c;
+ FORMALIZE(r0);
+
+ r0 |= (cc % 2) ? 0x80000000 : 0;
+ r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2);
+
+ *r_high = r1;
+ *r_low = r0;
+}
+
+/* calculate a / b */
+void
+bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
+{
+ uint32 a1 = a_high, a0 = a_low, r0 = 0;
+
+ if (b < 2)
+ return;
+
+ while (a1 != 0) {
+ r0 += (0xffffffff / b) * a1;
+ bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0);
+ }
+
+ r0 += a0 / b;
+ *r = r0;
+}
+
+#ifndef setbit /* As in the header file */
+#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
+/* Set bit in byte array. */
+void
+setbit(void *array, uint bit)
+{
+ ((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY);
+}
+
+/* Clear bit in byte array. */
+void
+clrbit(void *array, uint bit)
+{
+ ((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY));
+}
+
+/* Test if bit is set in byte array. */
+bool
+isset(const void *array, uint bit)
+{
+ return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY)));
+}
+
+/* Test if bit is clear in byte array. */
+bool
+isclr(const void *array, uint bit)
+{
+ return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0);
+}
+#endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */
+#endif /* setbit */
+
+void
+bcm_bitprint32(const uint32 u32)
+{
+ int i;
+ for (i = NBITS(uint32) - 1; i >= 0; i--) {
+ isbitset(u32, i) ? printf("1") : printf("0");
+ if ((i % NBBY) == 0) printf(" ");
+ }
+ printf("\n");
+}
+
+#ifdef BCMDRIVER
+/*
+ * Hierarchical Multiword bitmap based small id allocator.
+ *
+ * Multilevel hierarchy bitmap. (maximum 2 levels)
+ * First hierarchy uses a multiword bitmap to identify 32bit words in the
+ * second hierarchy that have at least a single bit set. Each bit in a word of
+ * the second hierarchy represents a unique ID that may be allocated.
+ *
+ * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed.
+ * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word
+ * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs.
+ * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non
+ * non-zero bitmap word carrying at least one free ID.
+ * BCM_MWBMAP_SHIFT_OP: Used in MOD, DIV and MUL operations.
+ * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID
+ *
+ * Design Notes:
+ * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many
+ * bits are computed each time on allocation and deallocation, requiring 4
+ * array indexed access and 3 arithmetic operations. When not defined, a runtime
+ * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed.
+ * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation.
+ * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may
+ * be used by defining BCM_MWBMAP_USE_CNTSETBITS.
+ *
+ * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array
+ * size is fixed. No intention to support larger than 4K indice allocation. ID
+ * allocators for ranges smaller than 4K will have a wastage of only 12Bytes
+ * with savings in not having to use an indirect access, had it been dynamically
+ * allocated.
+ */
+#define BCM_MWBMAP_ITEMS_MAX (4 * 1024) /* May increase to 16K */
+
+#define BCM_MWBMAP_BITS_WORD (NBITS(uint32))
+#define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
+#define BCM_MWBMAP_WDMAP_MAX (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD)
+#define BCM_MWBMAP_SHIFT_OP (5)
+#define BCM_MWBMAP_MODOP(ix) ((ix) & (BCM_MWBMAP_BITS_WORD - 1))
+#define BCM_MWBMAP_DIVOP(ix) ((ix) >> BCM_MWBMAP_SHIFT_OP)
+#define BCM_MWBMAP_MULOP(ix) ((ix) << BCM_MWBMAP_SHIFT_OP)
+
+/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */
+#define BCM_MWBMAP_PTR(hdl) ((struct bcm_mwbmap *)(hdl))
+#define BCM_MWBMAP_HDL(ptr) ((void *)(ptr))
+
+#if defined(BCM_MWBMAP_DEBUG)
+#define BCM_MWBMAP_AUDIT(mwb) \
+ do { \
+ ASSERT((mwb != NULL) && \
+ (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \
+ bcm_mwbmap_audit(mwb); \
+ } while (0)
+#define MWBMAP_ASSERT(exp) ASSERT(exp)
+#define MWBMAP_DBG(x) printf x
+#else /* !BCM_MWBMAP_DEBUG */
+#define BCM_MWBMAP_AUDIT(mwb) do {} while (0)
+#define MWBMAP_ASSERT(exp) do {} while (0)
+#define MWBMAP_DBG(x)
+#endif /* !BCM_MWBMAP_DEBUG */
+
+
+typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */
+ uint16 wmaps; /* Total number of words in free wd bitmap */
+ uint16 imaps; /* Total number of words in free id bitmap */
+ int16 ifree; /* Count of free indices. Used only in audits */
+ uint16 total; /* Total indices managed by multiword bitmap */
+
+ void * magic; /* Audit handle parameter from user */
+
+ uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of */
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+ int8 wd_count[BCM_MWBMAP_WORDS_MAX]; /* free id running count, 1st lvl */
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+
+ uint32 id_bitmap[0]; /* Second level bitmap */
+} bcm_mwbmap_t;
+
+/* Incarnate a hierarchical multiword bitmap based small index allocator. */
+struct bcm_mwbmap *
+bcm_mwbmap_init(osl_t *osh, uint32 items_max)
+{
+ struct bcm_mwbmap * mwbmap_p;
+ uint32 wordix, size, words, extra;
+
+ /* Implementation Constraint: Uses 32bit word bitmap */
+ MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U);
+ MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U);
+ MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX));
+ MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U);
+
+ ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX);
+
+ /* Determine the number of words needed in the multiword bitmap */
+ extra = BCM_MWBMAP_MODOP(items_max);
+ words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U);
+
+ /* Allocate runtime state of multiword bitmap */
+ /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */
+ size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words);
+ mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size);
+ if (mwbmap_p == (bcm_mwbmap_t *)NULL) {
+ ASSERT(0);
+ goto error1;
+ }
+ memset(mwbmap_p, 0, size);
+
+ /* Initialize runtime multiword bitmap state */
+ mwbmap_p->imaps = (uint16)words;
+ mwbmap_p->ifree = (int16)items_max;
+ mwbmap_p->total = (uint16)items_max;
+
+ /* Setup magic, for use in audit of handle */
+ mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p);
+
+ /* Setup the second level bitmap of free indices */
+ /* Mark all indices as available */
+ for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) {
+ mwbmap_p->id_bitmap[wordix] = (uint32)(~0U);
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+ mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD;
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ }
+
+ /* Ensure that extra indices are tagged as un-available */
+ if (extra) { /* fixup the free ids in last bitmap and wd_count */
+ uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1];
+ *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+ mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ }
+
+ /* Setup the first level bitmap hierarchy */
+ extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps);
+ words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U);
+
+ mwbmap_p->wmaps = (uint16)words;
+
+ for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++)
+ mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U);
+ if (extra) {
+ uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1];
+ *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
+ }
+
+ return mwbmap_p;
+
+error1:
+ return BCM_MWBMAP_INVALID_HDL;
+}
+
+/* Release resources used by multiword bitmap based small index allocator. */
+void
+bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl)
+{
+ bcm_mwbmap_t * mwbmap_p;
+
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+ MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap)
+ + (sizeof(uint32) * mwbmap_p->imaps));
+ return;
+}
+
+/* Allocate a unique small index using a multiword bitmap index allocator. */
+uint32
+bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl)
+{
+ bcm_mwbmap_t * mwbmap_p;
+ uint32 wordix, bitmap;
+
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+ /* Start with the first hierarchy */
+ for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) {
+
+ bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */
+
+ if (bitmap != 0U) {
+
+ uint32 count, bitix, *bitmap_p;
+
+ bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+ /* clear all except trailing 1 */
+ bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
+ MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
+ bcm_count_leading_zeros(bitmap));
+ bitix = (BCM_MWBMAP_BITS_WORD - 1)
+ - bcm_count_leading_zeros(bitmap); /* use asm clz */
+ wordix = BCM_MWBMAP_MULOP(wordix) + bitix;
+
+ /* Clear bit if wd count is 0, without conditional branch */
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1;
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ mwbmap_p->wd_count[wordix]--;
+ count = mwbmap_p->wd_count[wordix];
+ MWBMAP_ASSERT(count ==
+ (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ MWBMAP_ASSERT(count >= 0);
+
+ /* clear wd_bitmap bit if id_map count is 0 */
+ bitmap = (count == 0) << bitix;
+
+ MWBMAP_DBG((
+ "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count));
+
+ *bitmap_p ^= bitmap;
+
+ /* Use bitix in the second hierarchy */
+ bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+ bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */
+ MWBMAP_ASSERT(bitmap != 0U);
+
+ /* clear all except trailing 1 */
+ bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
+ MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
+ bcm_count_leading_zeros(bitmap));
+ bitix = BCM_MWBMAP_MULOP(wordix)
+ + (BCM_MWBMAP_BITS_WORD - 1)
+ - bcm_count_leading_zeros(bitmap); /* use asm clz */
+
+ mwbmap_p->ifree--; /* decrement system wide free count */
+ MWBMAP_ASSERT(mwbmap_p->ifree >= 0);
+
+ MWBMAP_DBG((
+ "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d",
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
+ mwbmap_p->ifree));
+
+ *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */
+
+ return bitix;
+ }
+ }
+
+ ASSERT(mwbmap_p->ifree == 0);
+
+ return BCM_MWBMAP_INVALID_IDX;
+}
+
+/* Force an index at a specified position to be in use */
+void
+bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+ bcm_mwbmap_t * mwbmap_p;
+ uint32 count, wordix, bitmap, *bitmap_p;
+
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+ ASSERT(bitix < mwbmap_p->total);
+
+ /* Start with second hierarchy */
+ wordix = BCM_MWBMAP_DIVOP(bitix);
+ bitmap = (uint32)(1U << BCM_MWBMAP_MODOP(bitix));
+ bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+ ASSERT((*bitmap_p & bitmap) == bitmap);
+
+ mwbmap_p->ifree--; /* update free count */
+ ASSERT(mwbmap_p->ifree >= 0);
+
+ MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d",
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
+ mwbmap_p->ifree));
+
+ *bitmap_p ^= bitmap; /* mark as in use */
+
+ /* Update first hierarchy */
+ bitix = wordix;
+
+ wordix = BCM_MWBMAP_DIVOP(bitix);
+ bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ mwbmap_p->wd_count[bitix]--;
+ count = mwbmap_p->wd_count[bitix];
+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ MWBMAP_ASSERT(count >= 0);
+
+ bitmap = (count == 0) << BCM_MWBMAP_MODOP(bitix);
+
+ MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
+ BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap,
+ (*bitmap_p) ^ bitmap, count));
+
+ *bitmap_p ^= bitmap; /* mark as in use */
+
+ return;
+}
+
+/* Free a previously allocated index back into the multiword bitmap allocator */
+void
+bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+ bcm_mwbmap_t * mwbmap_p;
+ uint32 wordix, bitmap, *bitmap_p;
+
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+ ASSERT(bitix < mwbmap_p->total);
+
+ /* Start with second level hierarchy */
+ wordix = BCM_MWBMAP_DIVOP(bitix);
+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
+ bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+ ASSERT((*bitmap_p & bitmap) == 0U); /* ASSERT not a double free */
+
+ mwbmap_p->ifree++; /* update free count */
+ ASSERT(mwbmap_p->ifree <= mwbmap_p->total);
+
+ MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d",
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap,
+ mwbmap_p->ifree));
+
+ *bitmap_p |= bitmap; /* mark as available */
+
+ /* Now update first level hierarchy */
+
+ bitix = wordix;
+
+ wordix = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */
+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
+ bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+ mwbmap_p->wd_count[bitix]++;
+#endif
+
+#if defined(BCM_MWBMAP_DEBUG)
+ {
+ uint32 count;
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ count = mwbmap_p->wd_count[bitix];
+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+
+ MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD);
+
+ MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d",
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count));
+ }
+#endif /* BCM_MWBMAP_DEBUG */
+
+ *bitmap_p |= bitmap;
+
+ return;
+}
+
+/* Fetch the toal number of free indices in the multiword bitmap allocator */
+uint32
+bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl)
+{
+ bcm_mwbmap_t * mwbmap_p;
+
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+ ASSERT(mwbmap_p->ifree >= 0);
+
+ return mwbmap_p->ifree;
+}
+
+/* Determine whether an index is inuse or free */
+bool
+bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+ bcm_mwbmap_t * mwbmap_p;
+ uint32 wordix, bitmap;
+
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+ ASSERT(bitix < mwbmap_p->total);
+
+ wordix = BCM_MWBMAP_DIVOP(bitix);
+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
+
+ return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U);
+}
+
+/* Debug dump a multiword bitmap allocator */
+void
+bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl)
+{
+ uint32 ix, count;
+ bcm_mwbmap_t * mwbmap_p;
+
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+ printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", mwbmap_p,
+ mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total);
+ for (ix = 0U; ix < mwbmap_p->wmaps; ix++) {
+ printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]);
+ bcm_bitprint32(mwbmap_p->wd_bitmap[ix]);
+ printf("\n");
+ }
+ for (ix = 0U; ix < mwbmap_p->imaps; ix++) {
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]);
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ count = mwbmap_p->wd_count[ix];
+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count);
+ bcm_bitprint32(mwbmap_p->id_bitmap[ix]);
+ printf("\n");
+ }
+
+ return;
+}
+
+/* Audit a hierarchical multiword bitmap */
+void
+bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl)
+{
+ bcm_mwbmap_t * mwbmap_p;
+ uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p;
+
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+ for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) {
+
+ bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+ for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) {
+ if ((*bitmap_p) & (1 << bitix)) {
+ idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix;
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]);
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ count = mwbmap_p->wd_count[idmap_ix];
+ ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+ ASSERT(count != 0U);
+ free_cnt += count;
+ }
+ }
+ }
+
+ ASSERT(free_cnt == mwbmap_p->ifree);
+}
+/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */
+
+#endif /* BCMDRIVER */
+
+/* calculate a >> b; and returns only lower 32 bits */
+void
+bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
+{
+ uint32 a1 = a_high, a0 = a_low, r0 = 0;
+
+ if (b == 0) {
+ r0 = a_low;
+ *r = r0;
+ return;
+ }
+
+ if (b < 32) {
+ a0 = a0 >> b;
+ a1 = a1 & ((1 << b) - 1);
+ a1 = a1 << (32 - b);
+ r0 = a0 | a1;
+ *r = r0;
+ return;
+ } else {
+ r0 = a1 >> (b - 32);
+ *r = r0;
+ return;
+ }
+
+}
+
+/* calculate a + b where a is a 64 bit number and b is a 32 bit number */
+void
+bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset)
+{
+ uint32 r1_lo = *r_lo;
+ (*r_lo) += offset;
+ if (*r_lo < r1_lo)
+ (*r_hi) ++;
+}
+
+/* calculate a - b where a is a 64 bit number and b is a 32 bit number */
+void
+bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset)
+{
+ uint32 r1_lo = *r_lo;
+ (*r_lo) -= offset;
+ if (*r_lo > r1_lo)
+ (*r_hi) --;
+}
+
+#ifdef DEBUG_COUNTER
+#if (OSL_SYSUPTIME_SUPPORT == TRUE)
+void counter_printlog(counter_tbl_t *ctr_tbl)
+{
+ uint32 now;
+
+ if (!ctr_tbl->enabled)
+ return;
+
+ now = OSL_SYSUPTIME();
+
+ if (now - ctr_tbl->prev_log_print > ctr_tbl->log_print_interval) {
+ uint8 i = 0;
+ printf("counter_print(%s %d):", ctr_tbl->name, now - ctr_tbl->prev_log_print);
+
+ for (i = 0; i < ctr_tbl->needed_cnt; i++) {
+ printf(" %u", ctr_tbl->cnt[i]);
+ }
+ printf("\n");
+
+ ctr_tbl->prev_log_print = now;
+ bzero(ctr_tbl->cnt, CNTR_TBL_MAX * sizeof(uint));
+ }
+}
+#else
+/* OSL_SYSUPTIME is not supported so no way to get time */
+#define counter_printlog(a) do {} while (0)
+#endif /* OSL_SYSUPTIME_SUPPORT == TRUE */
+#endif /* DEBUG_COUNTER */
diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_channels.c b/drivers/net/wireless/bcmdhd/bcmwifi_channels.c
new file mode 100644
index 000000000000..0aba9deaa329
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmwifi_channels.c
@@ -0,0 +1,1206 @@
+/*
+ * Misc utility routines used by kernel or app-level.
+ * Contents are wifi-specific, used by any kernel or app-level
+ * software that might want wifi things as it grows.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ * $Id: bcmwifi_channels.c 309193 2012-01-19 00:03:57Z $
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmutils.h>
+
+#ifdef BCMDRIVER
+#include <osl.h>
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+#endif /* BCMDRIVER */
+
+#include <bcmwifi_channels.h>
+
+#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
+#include <bcmstdlib.h> /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
+#endif
+
+/* Definitions for D11AC capable Chanspec type */
+
+/* Chanspec ASCII representation with 802.11ac capability:
+ * [<band> 'g'] <channel> ['/'<bandwidth> [<ctl-sideband>]['/'<1st80channel>'-'<2nd80channel>]]
+ *
+ * <band>:
+ * (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively.
+ * Default value is 2g if channel <= 14, otherwise 5g.
+ * <channel>:
+ * channel number of the 5MHz, 10MHz, 20MHz channel,
+ * or primary channel of 40MHz, 80MHz, 160MHz, or 80+80MHz channel.
+ * <bandwidth>:
+ * (optional) 5, 10, 20, 40, 80, 160, or 80+80. Default value is 20.
+ * <primary-sideband>:
+ * (only for 2.4GHz band 40MHz) U for upper sideband primary, L for lower.
+ *
+ * For 2.4GHz band 40MHz channels, the same primary channel may be the
+ * upper sideband for one 40MHz channel, and the lower sideband for an
+ * overlapping 40MHz channel. The U/L disambiguates which 40MHz channel
+ * is being specified.
+ *
+ * For 40MHz in the 5GHz band and all channel bandwidths greater than
+ * 40MHz, the U/L specificaion is not allowed since the channels are
+ * non-overlapping and the primary sub-band is derived from its
+ * position in the wide bandwidth channel.
+ *
+ * <1st80Channel>:
+ * <2nd80Channel>:
+ * Required for 80+80, otherwise not allowed.
+ * Specifies the center channel of the first and second 80MHz band.
+ *
+ * In its simplest form, it is a 20MHz channel number, with the implied band
+ * of 2.4GHz if channel number <= 14, and 5GHz otherwise.
+ *
+ * To allow for backward compatibility with scripts, the old form for
+ * 40MHz channels is also allowed: <channel><ctl-sideband>
+ *
+ * <channel>:
+ * primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz
+ * <ctl-sideband>:
+ * "U" for upper, "L" for lower (or lower case "u" "l")
+ *
+ * 5 GHz Examples:
+ * Chanspec BW Center Ch Channel Range Primary Ch
+ * 5g8 20MHz 8 - -
+ * 52 20MHz 52 - -
+ * 52/40 40MHz 54 52-56 52
+ * 56/40 40MHz 54 52-56 56
+ * 52/80 80MHz 58 52-64 52
+ * 56/80 80MHz 58 52-64 56
+ * 60/80 80MHz 58 52-64 60
+ * 64/80 80MHz 58 52-64 64
+ * 52/160 160MHz 50 36-64 52
+ * 36/160 160MGz 50 36-64 36
+ * 36/80+80/42-106 80+80MHz 42,106 36-48,100-112 36
+ *
+ * 2 GHz Examples:
+ * Chanspec BW Center Ch Channel Range Primary Ch
+ * 2g8 20MHz 8 - -
+ * 8 20MHz 8 - -
+ * 6 20MHz 6 - -
+ * 6/40l 40MHz 8 6-10 6
+ * 6l 40MHz 8 6-10 6
+ * 6/40u 40MHz 4 2-6 6
+ * 6u 40MHz 4 2-6 6
+ */
+
+/* bandwidth ASCII string */
+static const char *wf_chspec_bw_str[] =
+{
+ "5",
+ "10",
+ "20",
+ "40",
+ "80",
+ "160",
+ "80+80",
+ "na"
+};
+
+static const uint8 wf_chspec_bw_mhz[] =
+{5, 10, 20, 40, 80, 160, 160};
+
+#define WF_NUM_BW \
+ (sizeof(wf_chspec_bw_mhz)/sizeof(uint8))
+
+/* 40MHz channels in 5GHz band */
+static const uint8 wf_5g_40m_chans[] =
+{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159};
+#define WF_NUM_5G_40M_CHANS \
+ (sizeof(wf_5g_40m_chans)/sizeof(uint8))
+
+/* 80MHz channels in 5GHz band */
+static const uint8 wf_5g_80m_chans[] =
+{42, 58, 106, 122, 138, 155};
+#define WF_NUM_5G_80M_CHANS \
+ (sizeof(wf_5g_80m_chans)/sizeof(uint8))
+
+/* 160MHz channels in 5GHz band */
+static const uint8 wf_5g_160m_chans[] =
+{50, 114};
+#define WF_NUM_5G_160M_CHANS \
+ (sizeof(wf_5g_160m_chans)/sizeof(uint8))
+
+
+/* convert bandwidth from chanspec to MHz */
+static uint
+bw_chspec_to_mhz(chanspec_t chspec)
+{
+ uint bw;
+
+ bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT;
+ return (bw >= WF_NUM_BW ? 0 : wf_chspec_bw_mhz[bw]);
+}
+
+/* bw in MHz, return the channel count from the center channel to the
+ * the channel at the edge of the band
+ */
+static uint8
+center_chan_to_edge(uint bw)
+{
+ /* edge channels separated by BW - 10MHz on each side
+ * delta from cf to edge is half of that,
+ * MHz to channel num conversion is 5MHz/channel
+ */
+ return (uint8)(((bw - 20) / 2) / 5);
+}
+
+/* return channel number of the low edge of the band
+ * given the center channel and BW
+ */
+static uint8
+channel_low_edge(uint center_ch, uint bw)
+{
+ return (uint8)(center_ch - center_chan_to_edge(bw));
+}
+
+/* return side band number given center channel and control channel
+ * return -1 on error
+ */
+static int
+channel_to_sb(uint center_ch, uint ctl_ch, uint bw)
+{
+ uint lowest = channel_low_edge(center_ch, bw);
+ uint sb;
+
+ if ((ctl_ch - lowest) % 4) {
+ /* bad ctl channel, not mult 4 */
+ return -1;
+ }
+
+ sb = ((ctl_ch - lowest) / 4);
+
+ /* sb must be a index to a 20MHz channel in range */
+ if (sb >= (bw / 20)) {
+ /* ctl_ch must have been too high for the center_ch */
+ return -1;
+ }
+
+ return sb;
+}
+
+/* return control channel given center channel and side band */
+static uint8
+channel_to_ctl_chan(uint center_ch, uint bw, uint sb)
+{
+ return (uint8)(channel_low_edge(center_ch, bw) + sb * 4);
+}
+
+/* return index of 80MHz channel from channel number
+ * return -1 on error
+ */
+static int
+channel_80mhz_to_id(uint ch)
+{
+ uint i;
+ for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) {
+ if (ch == wf_5g_80m_chans[i])
+ return i;
+ }
+
+ return -1;
+}
+
+/* given a chanspec and a string buffer, format the chanspec as a
+ * string, and return the original pointer a.
+ * Min buffer length must be CHANSPEC_STR_LEN.
+ * On error return NULL
+ */
+char *
+wf_chspec_ntoa(chanspec_t chspec, char *buf)
+{
+ const char *band;
+ uint ctl_chan;
+
+ if (wf_chspec_malformed(chspec))
+ return NULL;
+
+ band = "";
+
+ /* check for non-default band spec */
+ if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) ||
+ (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL))
+ band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g";
+
+ /* ctl channel */
+ ctl_chan = wf_chspec_ctlchan(chspec);
+
+ /* bandwidth and ctl sideband */
+ if (CHSPEC_IS20(chspec)) {
+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan);
+ } else if (!CHSPEC_IS8080(chspec)) {
+ const char *bw;
+ const char *sb = "";
+
+ bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT];
+
+#ifdef CHANSPEC_NEW_40MHZ_FORMAT
+ /* ctl sideband string if needed for 2g 40MHz */
+ if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) {
+ sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
+ }
+
+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb);
+#else
+ /* ctl sideband string instead of BW for 40MHz */
+ if (CHSPEC_IS40(chspec)) {
+ sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb);
+ } else {
+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw);
+ }
+#endif /* CHANSPEC_NEW_40MHZ_FORMAT */
+
+ } else {
+ /* 80+80 */
+ uint chan1 = (chspec & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT;
+ uint chan2 = (chspec & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT;
+
+ /* convert to channel number */
+ chan1 = (chan1 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan1] : 0;
+ chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0;
+
+ /* Outputs a max of CHANSPEC_STR_LEN chars including '\0' */
+ snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2);
+ }
+
+ return (buf);
+}
+
+static int
+read_uint(const char **p, unsigned int *num)
+{
+ unsigned long val;
+ char *endp = NULL;
+
+ val = strtoul(*p, &endp, 10);
+ /* if endp is the initial pointer value, then a number was not read */
+ if (endp == *p)
+ return 0;
+
+ /* advance the buffer pointer to the end of the integer string */
+ *p = endp;
+ /* return the parsed integer */
+ *num = (unsigned int)val;
+
+ return 1;
+}
+
+/* given a chanspec string, convert to a chanspec.
+ * On error return 0
+ */
+chanspec_t
+wf_chspec_aton(const char *a)
+{
+ chanspec_t chspec;
+ uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb;
+ uint num, ctl_ch;
+ uint ch1, ch2;
+ char c, sb_ul = '\0';
+ int i;
+
+ bw = 20;
+ chspec_sb = 0;
+ chspec_ch = ch1 = ch2 = 0;
+
+ /* parse channel num or band */
+ if (!read_uint(&a, &num))
+ return 0;
+
+ /* if we are looking at a 'g', then the first number was a band */
+ c = tolower((int)a[0]);
+ if (c == 'g') {
+ a ++; /* consume the char */
+
+ /* band must be "2" or "5" */
+ if (num == 2)
+ chspec_band = WL_CHANSPEC_BAND_2G;
+ else if (num == 5)
+ chspec_band = WL_CHANSPEC_BAND_5G;
+ else
+ return 0;
+
+ /* read the channel number */
+ if (!read_uint(&a, &ctl_ch))
+ return 0;
+
+ c = tolower((int)a[0]);
+ }
+ else {
+ /* first number is channel, use default for band */
+ ctl_ch = num;
+ chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ?
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
+ }
+
+ if (c == '\0') {
+ /* default BW of 20MHz */
+ chspec_bw = WL_CHANSPEC_BW_20;
+ goto done_read;
+ }
+
+ a ++; /* consume the 'u','l', or '/' */
+
+ /* check 'u'/'l' */
+ if (c == 'u' || c == 'l') {
+ sb_ul = c;
+ chspec_bw = WL_CHANSPEC_BW_40;
+ goto done_read;
+ }
+
+ /* next letter must be '/' */
+ if (c != '/')
+ return 0;
+
+ /* read bandwidth */
+ if (!read_uint(&a, &bw))
+ return 0;
+
+ /* convert to chspec value */
+ if (bw == 20) {
+ chspec_bw = WL_CHANSPEC_BW_20;
+ } else if (bw == 40) {
+ chspec_bw = WL_CHANSPEC_BW_40;
+ } else if (bw == 80) {
+ chspec_bw = WL_CHANSPEC_BW_80;
+ } else if (bw == 160) {
+ chspec_bw = WL_CHANSPEC_BW_160;
+ } else {
+ return 0;
+ }
+
+ /* So far we have <band>g<chan>/<bw>
+ * Can now be followed by u/l if bw = 40,
+ * or '+80' if bw = 80, to make '80+80' bw.
+ */
+
+ c = tolower((int)a[0]);
+
+ /* if we have a 2g/40 channel, we should have a l/u spec now */
+ if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) {
+ if (c == 'u' || c == 'l') {
+ a ++; /* consume the u/l char */
+ sb_ul = c;
+ goto done_read;
+ }
+ }
+
+ /* check for 80+80 */
+ if (c == '+') {
+ /* 80+80 */
+ static const char *plus80 = "80/";
+
+ /* must be looking at '+80/'
+ * check and consume this string.
+ */
+ chspec_bw = WL_CHANSPEC_BW_8080;
+
+ a ++; /* consume the char '+' */
+
+ /* consume the '80/' string */
+ for (i = 0; i < 3; i++) {
+ if (*a++ != *plus80++) {
+ return 0;
+ }
+ }
+
+ /* read primary 80MHz channel */
+ if (!read_uint(&a, &ch1))
+ return 0;
+
+ /* must followed by '-' */
+ if (a[0] != '-')
+ return 0;
+ a ++; /* consume the char */
+
+ /* read secondary 80MHz channel */
+ if (!read_uint(&a, &ch2))
+ return 0;
+ }
+
+done_read:
+ /* skip trailing white space */
+ while (a[0] == ' ') {
+ a ++;
+ }
+
+ /* must be end of string */
+ if (a[0] != '\0')
+ return 0;
+
+ /* Now have all the chanspec string parts read;
+ * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2.
+ * chspec_band and chspec_bw are chanspec values.
+ * Need to convert ctl_ch, sb_ul, and ch1,ch2 into
+ * a center channel (or two) and sideband.
+ */
+
+ /* if a sb u/l string was given, just use that,
+ * guaranteed to be bw = 40 by sting parse.
+ */
+ if (sb_ul != '\0') {
+ if (sb_ul == 'l') {
+ chspec_ch = UPPER_20_SB(ctl_ch);
+ chspec_sb = WL_CHANSPEC_CTL_SB_LLL;
+ } else if (sb_ul == 'u') {
+ chspec_ch = LOWER_20_SB(ctl_ch);
+ chspec_sb = WL_CHANSPEC_CTL_SB_LLU;
+ }
+ }
+ /* if the bw is 20, center and sideband are trivial */
+ else if (chspec_bw == WL_CHANSPEC_BW_20) {
+ chspec_ch = ctl_ch;
+ chspec_sb = WL_CHANSPEC_CTL_SB_NONE;
+ }
+ /* if the bw is 40/80/160, not 80+80, a single method
+ * can be used to to find the center and sideband
+ */
+ else if (chspec_bw != WL_CHANSPEC_BW_8080) {
+ /* figure out ctl sideband based on ctl channel and bandwidth */
+ const uint8 *center_ch = NULL;
+ int num_ch = 0;
+ int sb = -1;
+
+ if (chspec_bw == WL_CHANSPEC_BW_40) {
+ center_ch = wf_5g_40m_chans;
+ num_ch = WF_NUM_5G_40M_CHANS;
+ } else if (chspec_bw == WL_CHANSPEC_BW_80) {
+ center_ch = wf_5g_80m_chans;
+ num_ch = WF_NUM_5G_80M_CHANS;
+ } else if (chspec_bw == WL_CHANSPEC_BW_160) {
+ center_ch = wf_5g_160m_chans;
+ num_ch = WF_NUM_5G_160M_CHANS;
+ } else {
+ return 0;
+ }
+
+ for (i = 0; i < num_ch; i ++) {
+ sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+ if (sb >= 0) {
+ chspec_ch = center_ch[i];
+ chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+ break;
+ }
+ }
+
+ /* check for no matching sb/center */
+ if (sb < 0) {
+ return 0;
+ }
+ }
+ /* Otherwise, bw is 80+80. Figure out channel pair and sb */
+ else {
+ int ch1_id = 0, ch2_id = 0;
+ int sb;
+
+ ch1_id = channel_80mhz_to_id(ch1);
+ ch2_id = channel_80mhz_to_id(ch2);
+
+ /* validate channels */
+ if (ch1 >= ch2 || ch1_id < 0 || ch2_id < 0)
+ return 0;
+
+ /* combined channel in chspec */
+ chspec_ch = (((uint16)ch1_id << WL_CHANSPEC_CHAN1_SHIFT) |
+ ((uint16)ch2_id << WL_CHANSPEC_CHAN2_SHIFT));
+
+ /* figure out ctl sideband */
+
+ /* does the primary channel fit with the 1st 80MHz channel ? */
+ sb = channel_to_sb(ch1, ctl_ch, bw);
+ if (sb < 0) {
+ /* no, so does the primary channel fit with the 2nd 80MHz channel ? */
+ sb = channel_to_sb(ch2, ctl_ch, bw);
+ if (sb < 0) {
+ /* no match for ctl_ch to either 80MHz center channel */
+ return 0;
+ }
+ /* sb index is 0-3 for the low 80MHz channel, and 4-7 for
+ * the high 80MHz channel. Add 4 to to shift to high set.
+ */
+ sb += 4;
+ }
+
+ chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+ }
+
+ chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb);
+
+ if (wf_chspec_malformed(chspec))
+ return 0;
+
+ return chspec;
+}
+
+/*
+ * Verify the chanspec is using a legal set of parameters, i.e. that the
+ * chanspec specified a band, bw, ctl_sb and channel and that the
+ * combination could be legal given any set of circumstances.
+ * RETURNS: TRUE is the chanspec is malformed, false if it looks good.
+ */
+bool
+wf_chspec_malformed(chanspec_t chanspec)
+{
+ uint chspec_bw = CHSPEC_BW(chanspec);
+ uint chspec_ch = CHSPEC_CHANNEL(chanspec);
+
+ /* must be 2G or 5G band */
+ if (CHSPEC_IS2G(chanspec)) {
+ /* must be valid bandwidth */
+ if (chspec_bw != WL_CHANSPEC_BW_20 &&
+ chspec_bw != WL_CHANSPEC_BW_40) {
+ return TRUE;
+ }
+ } else if (CHSPEC_IS5G(chanspec)) {
+ if (chspec_bw == WL_CHANSPEC_BW_8080) {
+ uint ch1_id, ch2_id;
+
+ /* channel number in 80+80 must be in range */
+ ch1_id = CHSPEC_CHAN1(chanspec);
+ ch2_id = CHSPEC_CHAN2(chanspec);
+ if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS)
+ return TRUE;
+
+ /* ch2 must be above ch1 for the chanspec */
+ if (ch2_id <= ch1_id)
+ return TRUE;
+ } else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 ||
+ chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) {
+
+ if (chspec_ch > MAXCHANNEL) {
+ return TRUE;
+ }
+ } else {
+ /* invalid bandwidth */
+ return TRUE;
+ }
+ } else {
+ /* must be 2G or 5G band */
+ return TRUE;
+ }
+
+ /* side band needs to be consistent with bandwidth */
+ if (chspec_bw == WL_CHANSPEC_BW_20) {
+ if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL)
+ return TRUE;
+ } else if (chspec_bw == WL_CHANSPEC_BW_40) {
+ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LLU)
+ return TRUE;
+ } else if (chspec_bw == WL_CHANSPEC_BW_80) {
+ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Verify the chanspec specifies a valid channel according to 802.11.
+ * RETURNS: TRUE if the chanspec is a valid 802.11 channel
+ */
+bool
+wf_chspec_valid(chanspec_t chanspec)
+{
+ uint chspec_bw = CHSPEC_BW(chanspec);
+ uint chspec_ch = CHSPEC_CHANNEL(chanspec);
+
+ if (wf_chspec_malformed(chanspec))
+ return FALSE;
+
+ if (CHSPEC_IS2G(chanspec)) {
+ /* must be valid bandwidth and channel range */
+ if (chspec_bw == WL_CHANSPEC_BW_20) {
+ if (chspec_ch >= 1 && chspec_ch <= 14)
+ return TRUE;
+ } else if (chspec_bw == WL_CHANSPEC_BW_40) {
+ if (chspec_ch >= 3 && chspec_ch <= 11)
+ return TRUE;
+ }
+ } else if (CHSPEC_IS5G(chanspec)) {
+ if (chspec_bw == WL_CHANSPEC_BW_8080) {
+ uint16 ch1, ch2;
+
+ ch1 = wf_5g_80m_chans[CHSPEC_CHAN1(chanspec)];
+ ch2 = wf_5g_80m_chans[CHSPEC_CHAN2(chanspec)];
+
+ /* the two channels must be separated by more than 80MHz by VHT req,
+ * and ch2 above ch1 for the chanspec
+ */
+ if (ch2 > ch1 + CH_80MHZ_APART)
+ return TRUE;
+ } else {
+ const uint8 *center_ch;
+ uint num_ch, i;
+
+ if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40) {
+ center_ch = wf_5g_40m_chans;
+ num_ch = WF_NUM_5G_40M_CHANS;
+ } else if (chspec_bw == WL_CHANSPEC_BW_80) {
+ center_ch = wf_5g_80m_chans;
+ num_ch = WF_NUM_5G_80M_CHANS;
+ } else if (chspec_bw == WL_CHANSPEC_BW_160) {
+ center_ch = wf_5g_160m_chans;
+ num_ch = WF_NUM_5G_160M_CHANS;
+ } else {
+ /* invalid bandwidth */
+ return FALSE;
+ }
+
+ /* check for a valid center channel */
+ if (chspec_bw == WL_CHANSPEC_BW_20) {
+ /* We don't have an array of legal 20MHz 5G channels, but they are
+ * each side of the legal 40MHz channels. Check the chanspec
+ * channel against either side of the 40MHz channels.
+ */
+ for (i = 0; i < num_ch; i ++) {
+ if (chspec_ch == (uint)LOWER_20_SB(center_ch[i]) ||
+ chspec_ch == (uint)UPPER_20_SB(center_ch[i]))
+ break; /* match found */
+ }
+
+ if (i == num_ch) {
+ /* check for channel 165 which is not the side band
+ * of 40MHz 5G channel
+ */
+ if (chspec_ch == 165)
+ i = 0;
+
+ /* check for legacy JP channels on failure */
+ if (chspec_ch == 34 || chspec_ch == 38 ||
+ chspec_ch == 42 || chspec_ch == 46)
+ i = 0;
+ }
+ } else {
+ /* check the chanspec channel to each legal channel */
+ for (i = 0; i < num_ch; i ++) {
+ if (chspec_ch == center_ch[i])
+ break; /* match found */
+ }
+ }
+
+ if (i < num_ch) {
+ /* match found */
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * This function returns the channel number that control traffic is being sent on, for 20MHz
+ * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ
+ * sideband depending on the chanspec selected
+ */
+uint8
+wf_chspec_ctlchan(chanspec_t chspec)
+{
+ uint center_chan;
+ uint bw_mhz;
+ uint sb;
+
+ ASSERT(!wf_chspec_malformed(chspec));
+
+ /* Is there a sideband ? */
+ if (CHSPEC_IS20(chspec)) {
+ return CHSPEC_CHANNEL(chspec);
+ } else {
+ sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+
+ if (CHSPEC_IS8080(chspec)) {
+ bw_mhz = 80;
+
+ if (sb < 4) {
+ center_chan = CHSPEC_CHAN1(chspec);
+ }
+ else {
+ center_chan = CHSPEC_CHAN2(chspec);
+ sb -= 4;
+ }
+
+ /* convert from channel index to channel number */
+ center_chan = wf_5g_80m_chans[center_chan];
+ }
+ else {
+ bw_mhz = bw_chspec_to_mhz(chspec);
+ center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT;
+ }
+
+ return (channel_to_ctl_chan(center_chan, bw_mhz, sb));
+ }
+}
+
+/* given a chanspec, return the bandwidth string */
+char *
+wf_chspec_to_bw_str(chanspec_t chspec)
+{
+ return (char *)wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)];
+}
+
+/*
+ * This function returns the chanspec of the control channel of a given chanspec
+ */
+chanspec_t
+wf_chspec_ctlchspec(chanspec_t chspec)
+{
+ chanspec_t ctl_chspec = chspec;
+ uint8 ctl_chan;
+
+ ASSERT(!wf_chspec_malformed(chspec));
+
+ /* Is there a sideband ? */
+ if (!CHSPEC_IS20(chspec)) {
+ ctl_chan = wf_chspec_ctlchan(chspec);
+ ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20;
+ ctl_chspec |= CHSPEC_BAND(chspec);
+ }
+ return ctl_chspec;
+}
+
+/* return chanspec given control channel and bandwidth
+ * return 0 on error
+ */
+uint16
+wf_channel2chspec(uint ctl_ch, uint bw)
+{
+ uint16 chspec;
+ const uint8 *center_ch = NULL;
+ int num_ch = 0;
+ int sb = -1;
+ int i = 0;
+
+ chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
+
+ chspec |= bw;
+
+ if (bw == WL_CHANSPEC_BW_40) {
+ center_ch = wf_5g_40m_chans;
+ num_ch = WF_NUM_5G_40M_CHANS;
+ bw = 40;
+ } else if (bw == WL_CHANSPEC_BW_80) {
+ center_ch = wf_5g_80m_chans;
+ num_ch = WF_NUM_5G_80M_CHANS;
+ bw = 80;
+ } else if (bw == WL_CHANSPEC_BW_160) {
+ center_ch = wf_5g_160m_chans;
+ num_ch = WF_NUM_5G_160M_CHANS;
+ bw = 160;
+ } else if (bw == WL_CHANSPEC_BW_20) {
+ chspec |= ctl_ch;
+ return chspec;
+ } else {
+ return 0;
+ }
+
+ for (i = 0; i < num_ch; i ++) {
+ sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+ if (sb >= 0) {
+ chspec |= center_ch[i];
+ chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT);
+ break;
+ }
+ }
+
+ /* check for no matching sb/center */
+ if (sb < 0) {
+ return 0;
+ }
+
+ return chspec;
+}
+
+/*
+ * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
+ * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
+ * as the primary 20MHz channel.
+ */
+extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec)
+{
+ chanspec_t chspec40 = chspec;
+ uint center_chan;
+ uint sb;
+
+ ASSERT(!wf_chspec_malformed(chspec));
+
+ if (CHSPEC_IS80(chspec)) {
+ center_chan = CHSPEC_CHANNEL(chspec);
+ sb = CHSPEC_CTL_SB(chspec);
+
+ if (sb == WL_CHANSPEC_CTL_SB_UL) {
+ /* Primary 40MHz is on upper side */
+ sb = WL_CHANSPEC_CTL_SB_L;
+ center_chan += CH_20MHZ_APART;
+ } else if (sb == WL_CHANSPEC_CTL_SB_UU) {
+ /* Primary 40MHz is on upper side */
+ sb = WL_CHANSPEC_CTL_SB_U;
+ center_chan += CH_20MHZ_APART;
+ } else {
+ /* Primary 40MHz is on lower side */
+ /* sideband bits are the same for LL/LU and L/U */
+ center_chan -= CH_20MHZ_APART;
+ }
+
+ /* Create primary 40MHz chanspec */
+ chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 |
+ sb | center_chan);
+ }
+
+ return chspec40;
+}
+
+/*
+ * Return the channel number for a given frequency and base frequency.
+ * The returned channel number is relative to the given base frequency.
+ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
+ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
+ *
+ * Frequency is specified in MHz.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
+ * 2.4 GHz and 5 GHz bands.
+ *
+ * The returned channel will be in the range [1, 14] in the 2.4 GHz band
+ * and [0, 200] otherwise.
+ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
+ * frequency is not a 2.4 GHz channel, or if the frequency is not and even
+ * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ */
+int
+wf_mhz2channel(uint freq, uint start_factor)
+{
+ int ch = -1;
+ uint base;
+ int offset;
+
+ /* take the default channel start frequency */
+ if (start_factor == 0) {
+ if (freq >= 2400 && freq <= 2500)
+ start_factor = WF_CHAN_FACTOR_2_4_G;
+ else if (freq >= 5000 && freq <= 6000)
+ start_factor = WF_CHAN_FACTOR_5_G;
+ }
+
+ if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
+ return 14;
+
+ base = start_factor / 2;
+
+ /* check that the frequency is in 1GHz range of the base */
+ if ((freq < base) || (freq > base + 1000))
+ return -1;
+
+ offset = freq - base;
+ ch = offset / 5;
+
+ /* check that frequency is a 5MHz multiple from the base */
+ if (offset != (ch * 5))
+ return -1;
+
+ /* restricted channel range check for 2.4G */
+ if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
+ return -1;
+
+ return ch;
+}
+
+/*
+ * Return the center frequency in MHz of the given channel and base frequency.
+ * The channel number is interpreted relative to the given base frequency.
+ *
+ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_4_G, and WF_CHAN_FACTOR_5_G
+ * are defined for 2.4 GHz, 4 GHz, and 5 GHz bands.
+ * The channel range of [1, 14] is only checked for a start_factor of
+ * WF_CHAN_FACTOR_2_4_G (4814 = 2407 * 2).
+ * Odd start_factors produce channels on .5 MHz boundaries, in which case
+ * the answer is rounded down to an integral MHz.
+ * -1 is returned for an out of range channel.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ */
+int
+wf_channel2mhz(uint ch, uint start_factor)
+{
+ int freq;
+
+ if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) ||
+ (ch > 200))
+ freq = -1;
+ else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14))
+ freq = 2484;
+ else
+ freq = ch * 5 + start_factor / 2;
+
+ return freq;
+}
+
+/*
+ * Returns the 80+80 chanspec corresponding to the following input parameters
+ *
+ * primary_20mhz - Primary 20 Mhz channel
+ * chan1 - channel number of first 80 Mhz band
+ * chan2 - channel number of second 80 Mhz band
+ *
+ * parameters chan1 and chan2 are channel numbers in {42, 58, 106, 122, 138, 155}
+ *
+ * returns INVCHANSPEC in case of error
+ */
+
+chanspec_t
+wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan1, uint8 chan2)
+{
+ int sb = 0;
+ uint16 chanspec = 0;
+ int chan1_id = 0, chan2_id = 0;
+
+ /* does the primary channel fit with the 1st 80MHz channel ? */
+ sb = channel_to_sb(chan1, primary_20mhz, 80);
+ if (sb < 0) {
+ /* no, so does the primary channel fit with the 2nd 80MHz channel ? */
+ sb = channel_to_sb(chan2, primary_20mhz, 80);
+ if (sb < 0) {
+ /* no match for ctl_ch to either 80MHz center channel */
+ return INVCHANSPEC;
+ }
+ /* sb index is 0-3 for the low 80MHz channel, and 4-7 for
+ * the high 80MHz channel. Add 4 to to shift to high set.
+ */
+ sb += 4;
+ }
+ chan1_id = channel_80mhz_to_id(chan1);
+ chan2_id = channel_80mhz_to_id(chan2);
+ if (chan1_id == -1 || chan2_id == -1)
+ return INVCHANSPEC;
+
+ chanspec = (chan1_id << WL_CHANSPEC_CHAN1_SHIFT)|
+ (chan2_id << WL_CHANSPEC_CHAN2_SHIFT)|
+ (sb << WL_CHANSPEC_CTL_SB_SHIFT)|
+ (WL_CHANSPEC_BW_8080)|
+ (WL_CHANSPEC_BAND_5G);
+
+ return chanspec;
+
+}
+
+/*
+ * This function returns the 80Mhz channel for the given id.
+ */
+static uint8
+wf_chspec_get80Mhz_ch(uint8 chan_80Mhz_id)
+{
+ if (chan_80Mhz_id < WF_NUM_5G_80M_CHANS)
+ return wf_5g_80m_chans[chan_80Mhz_id];
+
+ return 0;
+}
+
+/*
+ * Returns the primary 80 Mhz channel for the provided chanspec
+ *
+ * chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
+ *
+ * returns -1 in case the provided channel is 20/40 Mhz chanspec
+ */
+
+uint8
+wf_chspec_primary80_channel(chanspec_t chanspec)
+{
+ uint8 chan1 = 0, chan2 = 0, primary_20mhz = 0, primary80_chan = 0;
+ int sb = 0;
+
+ primary_20mhz = wf_chspec_ctlchan(chanspec);
+
+ if (CHSPEC_IS80(chanspec)) {
+ primary80_chan = CHSPEC_CHANNEL(chanspec);
+ }
+ else if (CHSPEC_IS8080(chanspec)) {
+ chan1 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec));
+ chan2 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec));
+
+ /* does the primary channel fit with the 1st 80MHz channel ? */
+ sb = channel_to_sb(chan1, primary_20mhz, 80);
+ if (sb < 0) {
+ /* no, so does the primary channel fit with the 2nd 80MHz channel ? */
+ sb = channel_to_sb(chan2, primary_20mhz, 80);
+ if (!(sb < 0)) {
+ primary80_chan = chan2;
+ }
+ }
+ else {
+ primary80_chan = chan1;
+ }
+ }
+ else if (CHSPEC_IS160(chanspec)) {
+ chan1 = CHSPEC_CHANNEL(chanspec);
+ sb = channel_to_sb(chan1, primary_20mhz, 160);
+ if (!(sb < 0)) {
+ /* based on the sb value primary 80 channel can be retrieved
+ * if sb is in range 0 to 3 the lower band is the 80Mhz primary band
+ */
+ if (sb < 4) {
+ primary80_chan = chan1 - CH_40MHZ_APART;
+ }
+ /* if sb is in range 4 to 7 the lower band is the 80Mhz primary band */
+ else
+ {
+ primary80_chan = chan1 + CH_40MHZ_APART;
+ }
+ }
+ }
+ else {
+ /* for 20 and 40 Mhz */
+ primary80_chan = -1;
+ }
+ return primary80_chan;
+}
+
+/*
+ * Returns the secondary 80 Mhz channel for the provided chanspec
+ *
+ * chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
+ *
+ * returns -1 in case the provided channel is 20/40 Mhz chanspec
+ */
+uint8
+wf_chspec_secondary80_channel(chanspec_t chanspec)
+{
+ uint8 chan1 = 0, chan2 = 0, primary_20mhz = 0, secondary80_chan = 0;
+ int sb = 0;
+
+ primary_20mhz = wf_chspec_ctlchan(chanspec);
+ if (CHSPEC_IS80(chanspec)) {
+ secondary80_chan = -1;
+ }
+ else if (CHSPEC_IS8080(chanspec)) {
+ chan1 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec));
+ chan2 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec));
+
+ /* does the primary channel fit with the 1st 80MHz channel ? */
+ sb = channel_to_sb(chan1, primary_20mhz, 80);
+ if (sb < 0) {
+ /* no, so does the primary channel fit with the 2nd 80MHz channel ? */
+ sb = channel_to_sb(chan2, primary_20mhz, 80);
+ if (!(sb < 0)) {
+ secondary80_chan = chan1;
+ }
+ }
+ else {
+ secondary80_chan = chan2;
+ }
+ }
+ else if (CHSPEC_IS160(chanspec)) {
+ chan1 = CHSPEC_CHANNEL(chanspec);
+ sb = channel_to_sb(chan1, primary_20mhz, 160);
+ if (!(sb < 0)) {
+ /* based on the sb value secondary 80 channel can be retrieved
+ *if sb is in range 0 to 3 upper band is the secondary 80Mhz band
+ */
+ if (sb < 4) {
+ secondary80_chan = chan1 + CH_40MHZ_APART;
+ }
+ /* if sb is in range 4 to 7 the lower band is the secondary 80Mhz band */
+ else
+ {
+ secondary80_chan = chan1 - CH_40MHZ_APART;
+ }
+ }
+ }
+ else {
+ /* for 20 and 40 Mhz */
+ secondary80_chan = -1;
+ }
+ return secondary80_chan;
+}
+
+/*
+ * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
+ *
+ * chanspec - Input chanspec for which the primary 80Mhz chanspec has to be retreived
+ *
+ * returns INVCHANSPEC in case the provided channel is 20/40 Mhz chanspec
+ */
+chanspec_t
+wf_chspec_primary80_chspec(chanspec_t chspec)
+{
+ chanspec_t chspec80;
+ uint center_chan, chan1 = 0, chan2 = 0;
+ uint sb;
+
+ ASSERT(!wf_chspec_malformed(chspec));
+ if (CHSPEC_IS8080(chspec)) {
+ chan1 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
+ chan2 = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec));
+
+ sb = CHSPEC_CTL_SB(chspec);
+
+ if (sb < 4) {
+ /* Primary 80MHz is on lower side */
+ center_chan = chan1;
+ }
+ else
+ {
+ /* Primary 80MHz is on upper side */
+ center_chan = chan2;
+ sb -= 4;
+ }
+ /* Create primary 80MHz chanspec */
+ chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 |sb | center_chan);
+ }
+ else if (CHSPEC_IS160(chspec)) {
+ center_chan = CHSPEC_CHANNEL(chspec);
+ sb = CHSPEC_CTL_SB(chspec);
+
+ if (sb < 4) {
+ /* Primary 80MHz is on upper side */
+ center_chan -= CH_40MHZ_APART;
+ }
+ else
+ {
+ /* Primary 80MHz is on lower side */
+ center_chan += CH_40MHZ_APART;
+ sb -= 4;
+ }
+ /* Create primary 80MHz chanspec */
+ chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
+ }
+ else
+ {
+ chspec80 = INVCHANSPEC;
+ }
+ return chspec80;
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_channels.h b/drivers/net/wireless/bcmdhd/bcmwifi_channels.h
new file mode 100644
index 000000000000..0fbe5052b42a
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmwifi_channels.h
@@ -0,0 +1,495 @@
+/*
+ * Misc utility routines for WL and Apps
+ * This header file housing the define and function prototype use by
+ * both the wl driver, tools & Apps.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmwifi_channels.h 309193 2012-01-19 00:03:57Z $
+ */
+
+#ifndef _bcmwifi_channels_h_
+#define _bcmwifi_channels_h_
+
+
+/* A chanspec holds the channel number, band, bandwidth and control sideband */
+typedef uint16 chanspec_t;
+
+/* channel defines */
+#define CH_UPPER_SB 0x01
+#define CH_LOWER_SB 0x02
+#define CH_EWA_VALID 0x04
+#define CH_80MHZ_APART 16
+#define CH_40MHZ_APART 8
+#define CH_20MHZ_APART 4
+#define CH_10MHZ_APART 2
+#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
+#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
+#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216,
+ * this is that + 1 rounded up to a multiple of NBBY (8).
+ * DO NOT MAKE it > 255: channels are uint8's all over
+ */
+#define CHSPEC_CTLOVLP(sp1, sp2, sep) (ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < \
+ (sep))
+
+/* All builds use the new 11ac ratespec/chanspec */
+#undef D11AC_IOTYPES
+#define D11AC_IOTYPES
+
+#define WL_CHANSPEC_CHAN_MASK 0x00ff
+#define WL_CHANSPEC_CHAN_SHIFT 0
+#define WL_CHANSPEC_CHAN1_MASK 0x000f
+#define WL_CHANSPEC_CHAN1_SHIFT 0
+#define WL_CHANSPEC_CHAN2_MASK 0x00f0
+#define WL_CHANSPEC_CHAN2_SHIFT 4
+
+#define WL_CHANSPEC_CTL_SB_MASK 0x0700
+#define WL_CHANSPEC_CTL_SB_SHIFT 8
+#define WL_CHANSPEC_CTL_SB_LLL 0x0000
+#define WL_CHANSPEC_CTL_SB_LLU 0x0100
+#define WL_CHANSPEC_CTL_SB_LUL 0x0200
+#define WL_CHANSPEC_CTL_SB_LUU 0x0300
+#define WL_CHANSPEC_CTL_SB_ULL 0x0400
+#define WL_CHANSPEC_CTL_SB_ULU 0x0500
+#define WL_CHANSPEC_CTL_SB_UUL 0x0600
+#define WL_CHANSPEC_CTL_SB_UUU 0x0700
+#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL
+#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU
+#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
+
+#define WL_CHANSPEC_BW_MASK 0x3800
+#define WL_CHANSPEC_BW_SHIFT 11
+#define WL_CHANSPEC_BW_5 0x0000
+#define WL_CHANSPEC_BW_10 0x0800
+#define WL_CHANSPEC_BW_20 0x1000
+#define WL_CHANSPEC_BW_40 0x1800
+#define WL_CHANSPEC_BW_80 0x2000
+#define WL_CHANSPEC_BW_160 0x2800
+#define WL_CHANSPEC_BW_8080 0x3000
+
+#define WL_CHANSPEC_BAND_MASK 0xc000
+#define WL_CHANSPEC_BAND_SHIFT 14
+#define WL_CHANSPEC_BAND_2G 0x0000
+#define WL_CHANSPEC_BAND_3G 0x4000
+#define WL_CHANSPEC_BAND_4G 0x8000
+#define WL_CHANSPEC_BAND_5G 0xc000
+#define INVCHANSPEC 255
+
+/* channel defines */
+#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \
+ ((channel) - CH_10MHZ_APART) : 0)
+#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
+ ((channel) + CH_10MHZ_APART) : 0)
+
+#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0)
+#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \
+ ((channel) + 3 * CH_10MHZ_APART) : 0)
+#define LU_20_SB(channel) LOWER_20_SB(channel)
+#define UL_20_SB(channel) UPPER_20_SB(channel)
+
+#define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART)
+#define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART)
+#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
+#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
+ ((channel) + CH_20MHZ_APART) : 0)
+#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
+ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
+ WL_CHANSPEC_BAND_5G))
+#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | \
+ WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G)
+#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | \
+ WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G)
+
+/* simple MACROs to get different fields of chanspec */
+#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
+#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT
+#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT
+#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
+#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
+
+#ifdef WL11N_20MHZONLY
+
+#define CHSPEC_IS10(chspec) 0
+#define CHSPEC_IS20(chspec) 1
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec) 0
+#endif
+#ifndef CHSPEC_IS80
+#define CHSPEC_IS80(chspec) 0
+#endif
+#ifndef CHSPEC_IS160
+#define CHSPEC_IS160(chspec) 0
+#endif
+#ifndef CHSPEC_IS8080
+#define CHSPEC_IS8080(chspec) 0
+#endif
+
+#else /* !WL11N_20MHZONLY */
+
+#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
+#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
+#endif
+#ifndef CHSPEC_IS80
+#define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
+#endif
+#ifndef CHSPEC_IS160
+#define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160)
+#endif
+#ifndef CHSPEC_IS8080
+#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080)
+#endif
+
+#endif /* !WL11N_20MHZONLY */
+
+#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
+#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
+#define CHSPEC_SB_UPPER(chspec) \
+ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
+#define CHSPEC_SB_LOWER(chspec) \
+ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
+#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G)
+
+/**
+ * Number of chars needed for wf_chspec_ntoa() destination character buffer.
+ */
+#define CHANSPEC_STR_LEN 20
+
+
+#define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\
+ CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080)
+
+/* BW inequality comparisons, LE (<=), GE (>=), LT (<), GT (>), comparisons can be made
+* as simple numeric comparisons, with the exception that 160 is the same BW as 80+80,
+* but have different numeric values; (WL_CHANSPEC_BW_160 < WL_CHANSPEC_BW_8080).
+*
+* The LT/LE/GT/GE macros check first checks whether both chspec bandwidth and bw are 160 wide.
+* If both chspec bandwidth and bw is not 160 wide, then the comparison is made.
+*/
+#define CHSPEC_BW_GE(chspec, bw) \
+ ((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ (bw == WL_CHANSPEC_BW_160 || bw == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) >= bw))
+
+#define CHSPEC_BW_LE(chspec, bw) \
+ ((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ (bw == WL_CHANSPEC_BW_160 || bw == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) <= bw))
+
+#define CHSPEC_BW_GT(chspec, bw) \
+ (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ (bw == WL_CHANSPEC_BW_160 || bw == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) > bw))
+
+#define CHSPEC_BW_LT(chspec, bw) \
+ (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ (bw == WL_CHANSPEC_BW_160 || bw == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) < bw))
+
+/* Legacy Chanspec defines
+ * These are the defines for the previous format of the chanspec_t
+ */
+#define WL_LCHANSPEC_CHAN_MASK 0x00ff
+#define WL_LCHANSPEC_CHAN_SHIFT 0
+
+#define WL_LCHANSPEC_CTL_SB_MASK 0x0300
+#define WL_LCHANSPEC_CTL_SB_SHIFT 8
+#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100
+#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200
+#define WL_LCHANSPEC_CTL_SB_NONE 0x0300
+
+#define WL_LCHANSPEC_BW_MASK 0x0C00
+#define WL_LCHANSPEC_BW_SHIFT 10
+#define WL_LCHANSPEC_BW_10 0x0400
+#define WL_LCHANSPEC_BW_20 0x0800
+#define WL_LCHANSPEC_BW_40 0x0C00
+
+#define WL_LCHANSPEC_BAND_MASK 0xf000
+#define WL_LCHANSPEC_BAND_SHIFT 12
+#define WL_LCHANSPEC_BAND_5G 0x1000
+#define WL_LCHANSPEC_BAND_2G 0x2000
+
+#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK))
+#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK)
+#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK)
+#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK)
+#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10)
+#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20)
+#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)
+#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G)
+#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G)
+
+#define LCHSPEC_SB_UPPER(chspec) \
+ ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \
+ (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
+#define LCHSPEC_SB_LOWER(chspec) \
+ ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \
+ (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
+
+#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band)))
+
+#define CH20MHZ_LCHSPEC(channel) \
+ (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \
+ WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G))
+
+/*
+ * WF_CHAN_FACTOR_* constants are used to calculate channel frequency
+ * given a channel number.
+ * chan_freq = chan_factor * 500Mhz + chan_number * 5
+ */
+
+/**
+ * Channel Factor for the starting frequence of 2.4 GHz channels.
+ * The value corresponds to 2407 MHz.
+ */
+#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */
+
+/**
+ * Channel Factor for the starting frequence of 5 GHz channels.
+ * The value corresponds to 5000 MHz.
+ */
+#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */
+
+/**
+ * Channel Factor for the starting frequence of 4.9 GHz channels.
+ * The value corresponds to 4000 MHz.
+ */
+#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */
+
+#define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */
+
+/**
+ * Convert chanspec to ascii string
+ *
+ * @param chspec chanspec format
+ * @param buf ascii string of chanspec
+ *
+ * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes
+ *
+ * @see CHANSPEC_STR_LEN
+ */
+extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf);
+
+/**
+ * Convert ascii string to chanspec
+ *
+ * @param a pointer to input string
+ *
+ * @return >= 0 if successful or 0 otherwise
+ */
+extern chanspec_t wf_chspec_aton(const char *a);
+
+/**
+ * Verify the chanspec fields are valid.
+ *
+ * Verify the chanspec is using a legal set field values, i.e. that the chanspec
+ * specified a band, bw, ctl_sb and channel and that the combination could be
+ * legal given some set of circumstances.
+ *
+ * @param chanspec input chanspec to verify
+ *
+ * @return TRUE if the chanspec is malformed, FALSE if it looks good.
+ */
+extern bool wf_chspec_malformed(chanspec_t chanspec);
+
+/**
+ * Verify the chanspec specifies a valid channel according to 802.11.
+ *
+ * @param chanspec input chanspec to verify
+ *
+ * @return TRUE if the chanspec is a valid 802.11 channel
+ */
+extern bool wf_chspec_valid(chanspec_t chanspec);
+
+/**
+ * Return the primary (control) channel.
+ *
+ * This function returns the channel number of the primary 20MHz channel. For
+ * 20MHz channels this is just the channel number. For 40MHz or wider channels
+ * it is the primary 20MHz channel specified by the chanspec.
+ *
+ * @param chspec input chanspec
+ *
+ * @return Returns the channel number of the primary 20MHz channel
+ */
+extern uint8 wf_chspec_ctlchan(chanspec_t chspec);
+
+/**
+ * Return the bandwidth string.
+ *
+ * This function returns the bandwidth string for the passed chanspec.
+ *
+ * @param chspec input chanspec
+ *
+ * @return Returns the bandwidth string
+ */
+extern char * wf_chspec_to_bw_str(chanspec_t chspec);
+
+/**
+ * Return the primary (control) chanspec.
+ *
+ * This function returns the chanspec of the primary 20MHz channel. For 20MHz
+ * channels this is just the chanspec. For 40MHz or wider channels it is the
+ * chanspec of the primary 20MHZ channel specified by the chanspec.
+ *
+ * @param chspec input chanspec
+ *
+ * @return Returns the chanspec of the primary 20MHz channel
+ */
+extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
+
+/**
+ * Return a channel number corresponding to a frequency.
+ *
+ * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
+ * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
+ * as the primary 20MHz channel.
+ */
+extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec);
+
+/*
+ * Return the channel number for a given frequency and base frequency.
+ * The returned channel number is relative to the given base frequency.
+ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
+ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
+ *
+ * Frequency is specified in MHz.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
+ * 2.4 GHz and 5 GHz bands.
+ *
+ * The returned channel will be in the range [1, 14] in the 2.4 GHz band
+ * and [0, 200] otherwise.
+ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
+ * frequency is not a 2.4 GHz channel, or if the frequency is not and even
+ * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ *
+ * @param freq frequency in MHz
+ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz
+ *
+ * @return Returns a channel number
+ *
+ * @see WF_CHAN_FACTOR_2_4_G
+ * @see WF_CHAN_FACTOR_5_G
+ */
+extern int wf_mhz2channel(uint freq, uint start_factor);
+
+/**
+ * Return the center frequency in MHz of the given channel and base frequency.
+ *
+ * Return the center frequency in MHz of the given channel and base frequency.
+ * The channel number is interpreted relative to the given base frequency.
+ *
+ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
+ * 2.4 GHz and 5 GHz bands.
+ * The channel range of [1, 14] is only checked for a start_factor of
+ * WF_CHAN_FACTOR_2_4_G (4814).
+ * Odd start_factors produce channels on .5 MHz boundaries, in which case
+ * the answer is rounded down to an integral MHz.
+ * -1 is returned for an out of range channel.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ *
+ * @param channel input channel number
+ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz
+ *
+ * @return Returns a frequency in MHz
+ *
+ * @see WF_CHAN_FACTOR_2_4_G
+ * @see WF_CHAN_FACTOR_5_G
+ */
+extern int wf_channel2mhz(uint channel, uint start_factor);
+
+/**
+ * Convert ctl chan and bw to chanspec
+ *
+ * @param ctl_ch channel
+ * @param bw bandwidth
+ *
+ * @return > 0 if successful or 0 otherwise
+ *
+ */
+extern uint16 wf_channel2chspec(uint ctl_ch, uint bw);
+
+extern uint wf_channel2freq(uint channel);
+extern uint wf_freq2channel(uint freq);
+
+/*
+ * Returns the 80+80 chanspec corresponding to the following input parameters
+ *
+ * primary_20mhz - Primary 20 Mhz channel
+ * chan1 - channel number of first 80 Mhz band
+ * chan2 - channel number of second 80 Mhz band
+ *
+ * parameters chan1 and chan2 are channel numbers in {42, 58, 106, 122, 138, 155}
+ *
+ * returns INVCHANSPEC in case of error
+ */
+
+extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz,
+uint8 chan1_80Mhz, uint8 chan2_80Mhz);
+
+/*
+ * Returns the primary 80 Mhz channel for the provided chanspec
+ *
+ * chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
+ *
+ * returns -1 in case the provided channel is 20/40 Mhz chanspec
+ */
+extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec);
+
+/*
+ * Returns the secondary 80 Mhz channel for the provided chanspec
+ *
+ * chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
+ *
+ * returns -1 in case the provided channel is 20/40 Mhz chanspec
+ */
+extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec);
+
+/*
+ * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
+ */
+extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec);
+
+
+#endif /* _bcmwifi_channels_h_ */
diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_rates.h b/drivers/net/wireless/bcmdhd/bcmwifi_rates.h
new file mode 100644
index 000000000000..707cf44a6510
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/bcmwifi_rates.h
@@ -0,0 +1,458 @@
+/*
+ * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmwifi_rates.h 5187 2012-06-29 06:17:50Z $
+ */
+
+#ifndef _bcmwifi_rates_h_
+#define _bcmwifi_rates_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define WL_RATESET_SZ_DSSS 4
+#define WL_RATESET_SZ_OFDM 8
+#define WL_RATESET_SZ_HT_MCS 8
+#define WL_RATESET_SZ_VHT_MCS 10
+
+#define WL_TX_CHAINS_MAX 3
+
+#define WL_RATE_DISABLED (-128) /* Power value corresponding to unsupported rate */
+
+/* Transmit channel bandwidths */
+typedef enum wl_tx_bw {
+ WL_TX_BW_20,
+ WL_TX_BW_40,
+ WL_TX_BW_80,
+ WL_TX_BW_160,
+ WL_TX_BW_20IN40,
+ WL_TX_BW_20IN80,
+ WL_TX_BW_40IN80,
+ WL_TX_BW_20IN160,
+ WL_TX_BW_40IN160,
+ WL_TX_BW_80IN160,
+ WL_TX_BW_ALL
+} wl_tx_bw_t;
+
+
+/*
+ * Transmit modes.
+ * Not all modes are listed here, only those required for disambiguation. e.g. SPEXP is not listed
+ */
+typedef enum wl_tx_mode {
+ WL_TX_MODE_NONE,
+ WL_TX_MODE_STBC,
+ WL_TX_MODE_CDD,
+ WL_TX_MODE_TXBF,
+ WL_NUM_TX_MODES
+} wl_tx_mode_t;
+
+
+/* Number of transmit chains */
+typedef enum wl_tx_chains {
+ WL_TX_CHAINS_1 = 1,
+ WL_TX_CHAINS_2,
+ WL_TX_CHAINS_3
+} wl_tx_chains_t;
+
+
+/* Number of transmit streams */
+typedef enum wl_tx_nss {
+ WL_TX_NSS_1 = 1,
+ WL_TX_NSS_2,
+ WL_TX_NSS_3
+} wl_tx_nss_t;
+
+
+typedef enum clm_rates {
+ /************
+ * 1 chain *
+ ************
+ */
+
+ /* 1 Stream */
+ WL_RATE_1X1_DSSS_1 = 0,
+ WL_RATE_1X1_DSSS_2 = 1,
+ WL_RATE_1X1_DSSS_5_5 = 2,
+ WL_RATE_1X1_DSSS_11 = 3,
+
+ WL_RATE_1X1_OFDM_6 = 4,
+ WL_RATE_1X1_OFDM_9 = 5,
+ WL_RATE_1X1_OFDM_12 = 6,
+ WL_RATE_1X1_OFDM_18 = 7,
+ WL_RATE_1X1_OFDM_24 = 8,
+ WL_RATE_1X1_OFDM_36 = 9,
+ WL_RATE_1X1_OFDM_48 = 10,
+ WL_RATE_1X1_OFDM_54 = 11,
+
+ WL_RATE_1X1_MCS0 = 12,
+ WL_RATE_1X1_MCS1 = 13,
+ WL_RATE_1X1_MCS2 = 14,
+ WL_RATE_1X1_MCS3 = 15,
+ WL_RATE_1X1_MCS4 = 16,
+ WL_RATE_1X1_MCS5 = 17,
+ WL_RATE_1X1_MCS6 = 18,
+ WL_RATE_1X1_MCS7 = 19,
+
+ WL_RATE_1X1_VHT0SS1 = 12,
+ WL_RATE_1X1_VHT1SS1 = 13,
+ WL_RATE_1X1_VHT2SS1 = 14,
+ WL_RATE_1X1_VHT3SS1 = 15,
+ WL_RATE_1X1_VHT4SS1 = 16,
+ WL_RATE_1X1_VHT5SS1 = 17,
+ WL_RATE_1X1_VHT6SS1 = 18,
+ WL_RATE_1X1_VHT7SS1 = 19,
+ WL_RATE_1X1_VHT8SS1 = 20,
+ WL_RATE_1X1_VHT9SS1 = 21,
+
+
+ /************
+ * 2 chains *
+ ************
+ */
+
+ /* 1 Stream expanded + 1 */
+ WL_RATE_1X2_DSSS_1 = 22,
+ WL_RATE_1X2_DSSS_2 = 23,
+ WL_RATE_1X2_DSSS_5_5 = 24,
+ WL_RATE_1X2_DSSS_11 = 25,
+
+ WL_RATE_1X2_CDD_OFDM_6 = 26,
+ WL_RATE_1X2_CDD_OFDM_9 = 27,
+ WL_RATE_1X2_CDD_OFDM_12 = 28,
+ WL_RATE_1X2_CDD_OFDM_18 = 29,
+ WL_RATE_1X2_CDD_OFDM_24 = 30,
+ WL_RATE_1X2_CDD_OFDM_36 = 31,
+ WL_RATE_1X2_CDD_OFDM_48 = 32,
+ WL_RATE_1X2_CDD_OFDM_54 = 33,
+
+ WL_RATE_1X2_CDD_MCS0 = 34,
+ WL_RATE_1X2_CDD_MCS1 = 35,
+ WL_RATE_1X2_CDD_MCS2 = 36,
+ WL_RATE_1X2_CDD_MCS3 = 37,
+ WL_RATE_1X2_CDD_MCS4 = 38,
+ WL_RATE_1X2_CDD_MCS5 = 39,
+ WL_RATE_1X2_CDD_MCS6 = 40,
+ WL_RATE_1X2_CDD_MCS7 = 41,
+
+ WL_RATE_1X2_VHT0SS1 = 34,
+ WL_RATE_1X2_VHT1SS1 = 35,
+ WL_RATE_1X2_VHT2SS1 = 36,
+ WL_RATE_1X2_VHT3SS1 = 37,
+ WL_RATE_1X2_VHT4SS1 = 38,
+ WL_RATE_1X2_VHT5SS1 = 39,
+ WL_RATE_1X2_VHT6SS1 = 40,
+ WL_RATE_1X2_VHT7SS1 = 41,
+ WL_RATE_1X2_VHT8SS1 = 42,
+ WL_RATE_1X2_VHT9SS1 = 43,
+
+ /* 2 Streams */
+ WL_RATE_2X2_STBC_MCS0 = 44,
+ WL_RATE_2X2_STBC_MCS1 = 45,
+ WL_RATE_2X2_STBC_MCS2 = 46,
+ WL_RATE_2X2_STBC_MCS3 = 47,
+ WL_RATE_2X2_STBC_MCS4 = 48,
+ WL_RATE_2X2_STBC_MCS5 = 49,
+ WL_RATE_2X2_STBC_MCS6 = 50,
+ WL_RATE_2X2_STBC_MCS7 = 51,
+
+ WL_RATE_2X2_STBC_VHT0SS1 = 44,
+ WL_RATE_2X2_STBC_VHT1SS1 = 45,
+ WL_RATE_2X2_STBC_VHT2SS1 = 46,
+ WL_RATE_2X2_STBC_VHT3SS1 = 47,
+ WL_RATE_2X2_STBC_VHT4SS1 = 48,
+ WL_RATE_2X2_STBC_VHT5SS1 = 49,
+ WL_RATE_2X2_STBC_VHT6SS1 = 50,
+ WL_RATE_2X2_STBC_VHT7SS1 = 51,
+ WL_RATE_2X2_STBC_VHT8SS1 = 52,
+ WL_RATE_2X2_STBC_VHT9SS1 = 53,
+
+ WL_RATE_2X2_SDM_MCS8 = 54,
+ WL_RATE_2X2_SDM_MCS9 = 55,
+ WL_RATE_2X2_SDM_MCS10 = 56,
+ WL_RATE_2X2_SDM_MCS11 = 57,
+ WL_RATE_2X2_SDM_MCS12 = 58,
+ WL_RATE_2X2_SDM_MCS13 = 59,
+ WL_RATE_2X2_SDM_MCS14 = 60,
+ WL_RATE_2X2_SDM_MCS15 = 61,
+
+ WL_RATE_2X2_VHT0SS2 = 54,
+ WL_RATE_2X2_VHT1SS2 = 55,
+ WL_RATE_2X2_VHT2SS2 = 56,
+ WL_RATE_2X2_VHT3SS2 = 57,
+ WL_RATE_2X2_VHT4SS2 = 58,
+ WL_RATE_2X2_VHT5SS2 = 59,
+ WL_RATE_2X2_VHT6SS2 = 60,
+ WL_RATE_2X2_VHT7SS2 = 61,
+ WL_RATE_2X2_VHT8SS2 = 62,
+ WL_RATE_2X2_VHT9SS2 = 63,
+
+ /************
+ * 3 chains *
+ ************
+ */
+
+ /* 1 Stream expanded + 2 */
+ WL_RATE_1X3_DSSS_1 = 64,
+ WL_RATE_1X3_DSSS_2 = 65,
+ WL_RATE_1X3_DSSS_5_5 = 66,
+ WL_RATE_1X3_DSSS_11 = 67,
+
+ WL_RATE_1X3_CDD_OFDM_6 = 68,
+ WL_RATE_1X3_CDD_OFDM_9 = 69,
+ WL_RATE_1X3_CDD_OFDM_12 = 70,
+ WL_RATE_1X3_CDD_OFDM_18 = 71,
+ WL_RATE_1X3_CDD_OFDM_24 = 72,
+ WL_RATE_1X3_CDD_OFDM_36 = 73,
+ WL_RATE_1X3_CDD_OFDM_48 = 74,
+ WL_RATE_1X3_CDD_OFDM_54 = 75,
+
+ WL_RATE_1X3_CDD_MCS0 = 76,
+ WL_RATE_1X3_CDD_MCS1 = 77,
+ WL_RATE_1X3_CDD_MCS2 = 78,
+ WL_RATE_1X3_CDD_MCS3 = 79,
+ WL_RATE_1X3_CDD_MCS4 = 80,
+ WL_RATE_1X3_CDD_MCS5 = 81,
+ WL_RATE_1X3_CDD_MCS6 = 82,
+ WL_RATE_1X3_CDD_MCS7 = 83,
+
+ WL_RATE_1X3_VHT0SS1 = 76,
+ WL_RATE_1X3_VHT1SS1 = 77,
+ WL_RATE_1X3_VHT2SS1 = 78,
+ WL_RATE_1X3_VHT3SS1 = 79,
+ WL_RATE_1X3_VHT4SS1 = 80,
+ WL_RATE_1X3_VHT5SS1 = 81,
+ WL_RATE_1X3_VHT6SS1 = 82,
+ WL_RATE_1X3_VHT7SS1 = 83,
+ WL_RATE_1X3_VHT8SS1 = 84,
+ WL_RATE_1X3_VHT9SS1 = 85,
+
+ /* 2 Streams expanded + 1 */
+ WL_RATE_2X3_STBC_MCS0 = 86,
+ WL_RATE_2X3_STBC_MCS1 = 87,
+ WL_RATE_2X3_STBC_MCS2 = 88,
+ WL_RATE_2X3_STBC_MCS3 = 89,
+ WL_RATE_2X3_STBC_MCS4 = 90,
+ WL_RATE_2X3_STBC_MCS5 = 91,
+ WL_RATE_2X3_STBC_MCS6 = 92,
+ WL_RATE_2X3_STBC_MCS7 = 93,
+
+ WL_RATE_2X3_STBC_VHT0SS1 = 86,
+ WL_RATE_2X3_STBC_VHT1SS1 = 87,
+ WL_RATE_2X3_STBC_VHT2SS1 = 88,
+ WL_RATE_2X3_STBC_VHT3SS1 = 89,
+ WL_RATE_2X3_STBC_VHT4SS1 = 90,
+ WL_RATE_2X3_STBC_VHT5SS1 = 91,
+ WL_RATE_2X3_STBC_VHT6SS1 = 92,
+ WL_RATE_2X3_STBC_VHT7SS1 = 93,
+ WL_RATE_2X3_STBC_VHT8SS1 = 94,
+ WL_RATE_2X3_STBC_VHT9SS1 = 95,
+
+ WL_RATE_2X3_SDM_MCS8 = 96,
+ WL_RATE_2X3_SDM_MCS9 = 97,
+ WL_RATE_2X3_SDM_MCS10 = 98,
+ WL_RATE_2X3_SDM_MCS11 = 99,
+ WL_RATE_2X3_SDM_MCS12 = 100,
+ WL_RATE_2X3_SDM_MCS13 = 101,
+ WL_RATE_2X3_SDM_MCS14 = 102,
+ WL_RATE_2X3_SDM_MCS15 = 103,
+
+ WL_RATE_2X3_VHT0SS2 = 96,
+ WL_RATE_2X3_VHT1SS2 = 97,
+ WL_RATE_2X3_VHT2SS2 = 98,
+ WL_RATE_2X3_VHT3SS2 = 99,
+ WL_RATE_2X3_VHT4SS2 = 100,
+ WL_RATE_2X3_VHT5SS2 = 101,
+ WL_RATE_2X3_VHT6SS2 = 102,
+ WL_RATE_2X3_VHT7SS2 = 103,
+ WL_RATE_2X3_VHT8SS2 = 104,
+ WL_RATE_2X3_VHT9SS2 = 105,
+
+ /* 3 Streams */
+ WL_RATE_3X3_SDM_MCS16 = 106,
+ WL_RATE_3X3_SDM_MCS17 = 107,
+ WL_RATE_3X3_SDM_MCS18 = 108,
+ WL_RATE_3X3_SDM_MCS19 = 109,
+ WL_RATE_3X3_SDM_MCS20 = 110,
+ WL_RATE_3X3_SDM_MCS21 = 111,
+ WL_RATE_3X3_SDM_MCS22 = 112,
+ WL_RATE_3X3_SDM_MCS23 = 113,
+
+ WL_RATE_3X3_VHT0SS3 = 106,
+ WL_RATE_3X3_VHT1SS3 = 107,
+ WL_RATE_3X3_VHT2SS3 = 108,
+ WL_RATE_3X3_VHT3SS3 = 109,
+ WL_RATE_3X3_VHT4SS3 = 110,
+ WL_RATE_3X3_VHT5SS3 = 111,
+ WL_RATE_3X3_VHT6SS3 = 112,
+ WL_RATE_3X3_VHT7SS3 = 113,
+ WL_RATE_3X3_VHT8SS3 = 114,
+ WL_RATE_3X3_VHT9SS3 = 115,
+
+
+ /****************************
+ * TX Beamforming, 2 chains *
+ ****************************
+ */
+
+ /* 1 Stream expanded + 1 */
+
+ WL_RATE_1X2_TXBF_OFDM_6 = 116,
+ WL_RATE_1X2_TXBF_OFDM_9 = 117,
+ WL_RATE_1X2_TXBF_OFDM_12 = 118,
+ WL_RATE_1X2_TXBF_OFDM_18 = 119,
+ WL_RATE_1X2_TXBF_OFDM_24 = 120,
+ WL_RATE_1X2_TXBF_OFDM_36 = 121,
+ WL_RATE_1X2_TXBF_OFDM_48 = 122,
+ WL_RATE_1X2_TXBF_OFDM_54 = 123,
+
+ WL_RATE_1X2_TXBF_MCS0 = 124,
+ WL_RATE_1X2_TXBF_MCS1 = 125,
+ WL_RATE_1X2_TXBF_MCS2 = 126,
+ WL_RATE_1X2_TXBF_MCS3 = 127,
+ WL_RATE_1X2_TXBF_MCS4 = 128,
+ WL_RATE_1X2_TXBF_MCS5 = 129,
+ WL_RATE_1X2_TXBF_MCS6 = 130,
+ WL_RATE_1X2_TXBF_MCS7 = 131,
+
+ WL_RATE_1X2_TXBF_VHT0SS1 = 124,
+ WL_RATE_1X2_TXBF_VHT1SS1 = 125,
+ WL_RATE_1X2_TXBF_VHT2SS1 = 126,
+ WL_RATE_1X2_TXBF_VHT3SS1 = 127,
+ WL_RATE_1X2_TXBF_VHT4SS1 = 128,
+ WL_RATE_1X2_TXBF_VHT5SS1 = 129,
+ WL_RATE_1X2_TXBF_VHT6SS1 = 130,
+ WL_RATE_1X2_TXBF_VHT7SS1 = 131,
+ WL_RATE_1X2_TXBF_VHT8SS1 = 132,
+ WL_RATE_1X2_TXBF_VHT9SS1 = 133,
+
+ /* 2 Streams */
+
+ WL_RATE_2X2_TXBF_SDM_MCS8 = 134,
+ WL_RATE_2X2_TXBF_SDM_MCS9 = 135,
+ WL_RATE_2X2_TXBF_SDM_MCS10 = 136,
+ WL_RATE_2X2_TXBF_SDM_MCS11 = 137,
+ WL_RATE_2X2_TXBF_SDM_MCS12 = 138,
+ WL_RATE_2X2_TXBF_SDM_MCS13 = 139,
+ WL_RATE_2X2_TXBF_SDM_MCS14 = 140,
+ WL_RATE_2X2_TXBF_SDM_MCS15 = 141,
+
+ WL_RATE_2X2_TXBF_VHT0SS2 = 134,
+ WL_RATE_2X2_TXBF_VHT1SS2 = 135,
+ WL_RATE_2X2_TXBF_VHT2SS2 = 136,
+ WL_RATE_2X2_TXBF_VHT3SS2 = 137,
+ WL_RATE_2X2_TXBF_VHT4SS2 = 138,
+ WL_RATE_2X2_TXBF_VHT5SS2 = 139,
+ WL_RATE_2X2_TXBF_VHT6SS2 = 140,
+ WL_RATE_2X2_TXBF_VHT7SS2 = 141,
+
+
+ /****************************
+ * TX Beamforming, 3 chains *
+ ****************************
+ */
+
+ /* 1 Stream expanded + 2 */
+
+ WL_RATE_1X3_TXBF_OFDM_6 = 142,
+ WL_RATE_1X3_TXBF_OFDM_9 = 143,
+ WL_RATE_1X3_TXBF_OFDM_12 = 144,
+ WL_RATE_1X3_TXBF_OFDM_18 = 145,
+ WL_RATE_1X3_TXBF_OFDM_24 = 146,
+ WL_RATE_1X3_TXBF_OFDM_36 = 147,
+ WL_RATE_1X3_TXBF_OFDM_48 = 148,
+ WL_RATE_1X3_TXBF_OFDM_54 = 149,
+
+ WL_RATE_1X3_TXBF_MCS0 = 150,
+ WL_RATE_1X3_TXBF_MCS1 = 151,
+ WL_RATE_1X3_TXBF_MCS2 = 152,
+ WL_RATE_1X3_TXBF_MCS3 = 153,
+ WL_RATE_1X3_TXBF_MCS4 = 154,
+ WL_RATE_1X3_TXBF_MCS5 = 155,
+ WL_RATE_1X3_TXBF_MCS6 = 156,
+ WL_RATE_1X3_TXBF_MCS7 = 157,
+
+ WL_RATE_1X3_TXBF_VHT0SS1 = 150,
+ WL_RATE_1X3_TXBF_VHT1SS1 = 151,
+ WL_RATE_1X3_TXBF_VHT2SS1 = 152,
+ WL_RATE_1X3_TXBF_VHT3SS1 = 153,
+ WL_RATE_1X3_TXBF_VHT4SS1 = 154,
+ WL_RATE_1X3_TXBF_VHT5SS1 = 155,
+ WL_RATE_1X3_TXBF_VHT6SS1 = 156,
+ WL_RATE_1X3_TXBF_VHT7SS1 = 157,
+ WL_RATE_1X3_TXBF_VHT8SS1 = 158,
+ WL_RATE_1X3_TXBF_VHT9SS1 = 159,
+
+ /* 2 Streams expanded + 1 */
+
+ WL_RATE_2X3_TXBF_SDM_MCS8 = 160,
+ WL_RATE_2X3_TXBF_SDM_MCS9 = 161,
+ WL_RATE_2X3_TXBF_SDM_MCS10 = 162,
+ WL_RATE_2X3_TXBF_SDM_MCS11 = 163,
+ WL_RATE_2X3_TXBF_SDM_MCS12 = 164,
+ WL_RATE_2X3_TXBF_SDM_MCS13 = 165,
+ WL_RATE_2X3_TXBF_SDM_MCS14 = 166,
+ WL_RATE_2X3_TXBF_SDM_MCS15 = 167,
+
+ WL_RATE_2X3_TXBF_VHT0SS2 = 160,
+ WL_RATE_2X3_TXBF_VHT1SS2 = 161,
+ WL_RATE_2X3_TXBF_VHT2SS2 = 162,
+ WL_RATE_2X3_TXBF_VHT3SS2 = 163,
+ WL_RATE_2X3_TXBF_VHT4SS2 = 164,
+ WL_RATE_2X3_TXBF_VHT5SS2 = 165,
+ WL_RATE_2X3_TXBF_VHT6SS2 = 166,
+ WL_RATE_2X3_TXBF_VHT7SS2 = 167,
+ WL_RATE_2X3_TXBF_VHT8SS2 = 168,
+ WL_RATE_2X3_TXBF_VHT9SS2 = 169,
+
+ /* 3 Streams */
+
+ WL_RATE_3X3_TXBF_SDM_MCS16 = 170,
+ WL_RATE_3X3_TXBF_SDM_MCS17 = 171,
+ WL_RATE_3X3_TXBF_SDM_MCS18 = 172,
+ WL_RATE_3X3_TXBF_SDM_MCS19 = 173,
+ WL_RATE_3X3_TXBF_SDM_MCS20 = 174,
+ WL_RATE_3X3_TXBF_SDM_MCS21 = 175,
+ WL_RATE_3X3_TXBF_SDM_MCS22 = 176,
+ WL_RATE_3X3_TXBF_SDM_MCS23 = 177,
+
+ WL_RATE_3X3_TXBF_VHT0SS3 = 170,
+ WL_RATE_3X3_TXBF_VHT1SS3 = 171,
+ WL_RATE_3X3_TXBF_VHT2SS3 = 172,
+ WL_RATE_3X3_TXBF_VHT3SS3 = 173,
+ WL_RATE_3X3_TXBF_VHT4SS3 = 174,
+ WL_RATE_3X3_TXBF_VHT5SS3 = 175,
+ WL_RATE_3X3_TXBF_VHT6SS3 = 176,
+ WL_RATE_3X3_TXBF_VHT7SS3 = 177
+} clm_rates_t;
+
+/* Number of rate codes */
+#define WL_NUMRATES 178
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _bcmwifi_rates_h_ */
diff --git a/drivers/net/wireless/bcmdhd/circularbuf.c b/drivers/net/wireless/bcmdhd/circularbuf.c
new file mode 100644
index 000000000000..30c60db3bf6a
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/circularbuf.c
@@ -0,0 +1,326 @@
+/*
+ * Initialization and support routines for self-booting compressed image.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: circularbuf.c 452261 2014-01-29 19:30:23Z $
+ */
+
+#include <circularbuf.h>
+#include <bcmmsgbuf.h>
+#include <osl.h>
+
+#define CIRCULARBUF_READ_SPACE_AT_END(x) \
+ ((x->w_ptr >= x->rp_ptr) ? (x->w_ptr - x->rp_ptr) : (x->e_ptr - x->rp_ptr))
+
+#define CIRCULARBUF_READ_SPACE_AVAIL(x) \
+ (((CIRCULARBUF_READ_SPACE_AT_END(x) == 0) && (x->w_ptr < x->rp_ptr)) ? \
+ x->w_ptr : CIRCULARBUF_READ_SPACE_AT_END(x))
+
+int cbuf_msg_level = CBUF_ERROR_VAL | CBUF_TRACE_VAL | CBUF_INFORM_VAL;
+
+/* #define CBUF_DEBUG */
+#ifdef CBUF_DEBUG
+#define CBUF_DEBUG_CHECK(x) x
+#else
+#define CBUF_DEBUG_CHECK(x)
+#endif /* CBUF_DEBUG */
+
+/*
+ * -----------------------------------------------------------------------------
+ * Function : circularbuf_init
+ * Description:
+ *
+ *
+ * Input Args :
+ *
+ *
+ * Return Values :
+ *
+ * -----------------------------------------------------------------------------
+ */
+void
+circularbuf_init(circularbuf_t *handle, void *buf_base_addr, uint16 total_buf_len)
+{
+ handle->buf_addr = buf_base_addr;
+
+ handle->depth = handle->e_ptr = HTOL32(total_buf_len);
+
+ /* Initialize Read and Write pointers */
+ handle->w_ptr = handle->r_ptr = handle->wp_ptr = handle->rp_ptr = HTOL32(0);
+ handle->mb_ring_bell = NULL;
+ handle->mb_ctx = NULL;
+
+ return;
+}
+
+void
+circularbuf_register_cb(circularbuf_t *handle, mb_ring_t mb_ring_func, void *ctx)
+{
+ handle->mb_ring_bell = mb_ring_func;
+ handle->mb_ctx = ctx;
+}
+
+#ifdef CBUF_DEBUG
+static void
+circularbuf_check_sanity(circularbuf_t *handle)
+{
+ if ((handle->e_ptr > handle->depth) ||
+ (handle->r_ptr > handle->e_ptr) ||
+ (handle->rp_ptr > handle->e_ptr) ||
+ (handle->w_ptr > handle->e_ptr))
+ {
+ printf("%s:%d: Pointers are corrupted.\n", __FUNCTION__, __LINE__);
+ circularbuf_debug_print(handle);
+ ASSERT(0);
+ }
+ return;
+}
+#endif /* CBUF_DEBUG */
+
+/*
+ * -----------------------------------------------------------------------------
+ * Function : circularbuf_reserve_for_write
+ *
+ * Description:
+ * This function reserves N bytes for write in the circular buffer. The circularbuf
+ * implementation will only reserve space in the ciruclar buffer and return
+ * the pointer to the address where the new data can be written.
+ * The actual write implementation (bcopy/dma) is outside the scope of
+ * circularbuf implementation.
+ *
+ * Input Args :
+ * size - No. of bytes to reserve for write
+ *
+ * Return Values :
+ * void * : Pointer to the reserved location. This is the address
+ * that will be used for write (dma/bcopy)
+ *
+ * -----------------------------------------------------------------------------
+ */
+void * BCMFASTPATH
+circularbuf_reserve_for_write(circularbuf_t *handle, uint16 size)
+{
+ int16 avail_space;
+ void *ret_ptr = NULL;
+
+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
+ ASSERT(size < handle->depth);
+
+ if (handle->wp_ptr >= handle->r_ptr)
+ avail_space = handle->depth - handle->wp_ptr;
+ else
+ avail_space = handle->r_ptr - handle->wp_ptr;
+
+ ASSERT(avail_space <= handle->depth);
+ if (avail_space > size)
+ {
+ /* Great. We have enough space. */
+ ret_ptr = CIRCULARBUF_START(handle) + handle->wp_ptr;
+
+ /*
+ * We need to update the wp_ptr for the next guy to write.
+ *
+ * Please Note : We are not updating the write pointer here. This can be
+ * done only after write is complete (In case of DMA, we can only schedule
+ * the DMA. Actual completion will be known only on DMA complete interrupt).
+ */
+ handle->wp_ptr += size;
+ return ret_ptr;
+ }
+
+ /*
+ * If there is no available space, we should check if there is some space left
+ * in the beginning of the circular buffer. Wrap-around case, where there is
+ * not enough space in the end of the circular buffer. But, there might be
+ * room in the beginning of the buffer.
+ */
+ if (handle->wp_ptr >= handle->r_ptr)
+ {
+ avail_space = handle->r_ptr;
+ if (avail_space > size)
+ {
+ /* OK. There is room in the beginning. Let's go ahead and use that.
+ * But, before that, we have left a hole at the end of the circular
+ * buffer as that was not sufficient to accomodate the requested
+ * size. Let's make sure this is updated in the circularbuf structure
+ * so that consumer does not use the hole.
+ */
+ handle->e_ptr = handle->wp_ptr;
+ handle->wp_ptr = size;
+
+ return CIRCULARBUF_START(handle);
+ }
+ }
+
+ /* We have tried enough to accomodate the new packet. There is no room for now. */
+ return NULL;
+}
+
+/*
+ * -----------------------------------------------------------------------------
+ * Function : circularbuf_write_complete
+ *
+ * Description:
+ * This function has to be called by the producer end of circularbuf to indicate to
+ * the circularbuf layer that data has been written and the write pointer can be
+ * updated. In the process, if there was a doorbell callback registered, that
+ * function would also be invoked.
+ *
+ * Input Args :
+ * dest_addr : Address where the data was written. This would be the
+ * same address that was reserved earlier.
+ * bytes_written : Length of data written
+ *
+ * -----------------------------------------------------------------------------
+ */
+void BCMFASTPATH
+circularbuf_write_complete(circularbuf_t *handle, uint16 bytes_written)
+{
+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
+
+ /* Update the write pointer */
+ if ((handle->w_ptr + bytes_written) >= handle->depth) {
+ OSL_CACHE_FLUSH((void *) CIRCULARBUF_START(handle), bytes_written);
+ handle->w_ptr = bytes_written;
+ } else {
+ OSL_CACHE_FLUSH((void *) (CIRCULARBUF_START(handle) + handle->w_ptr),
+ bytes_written);
+ handle->w_ptr += bytes_written;
+ }
+
+ /* And ring the door bell (mail box interrupt) to indicate to the peer that
+ * message is available for consumption.
+ */
+ if (handle->mb_ring_bell)
+ handle->mb_ring_bell(handle->mb_ctx);
+}
+
+/*
+ * -----------------------------------------------------------------------------
+ * Function : circularbuf_get_read_ptr
+ *
+ * Description:
+ * This function will be called by the consumer of circularbuf for reading data from
+ * the circular buffer. This will typically be invoked when the consumer gets a
+ * doorbell interrupt.
+ * Please note that the function only returns the pointer (and length) from
+ * where the data can be read. Actual read implementation is upto the
+ * consumer. It could be a bcopy or dma.
+ *
+ * Input Args :
+ * void * : Address from where the data can be read.
+ * available_len : Length of data available for read.
+ *
+ * -----------------------------------------------------------------------------
+ */
+void * BCMFASTPATH
+circularbuf_get_read_ptr(circularbuf_t *handle, uint16 *available_len)
+{
+ uint8 *ret_addr;
+
+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
+
+ /* First check if there is any data available in the circular buffer */
+ *available_len = CIRCULARBUF_READ_SPACE_AVAIL(handle);
+ if (*available_len == 0)
+ return NULL;
+
+ /*
+ * Although there might be data in the circular buffer for read, in
+ * cases of write wrap-around and read still in the end of the circular
+ * buffer, we might have to wrap around the read pending pointer also.
+ */
+ if (CIRCULARBUF_READ_SPACE_AT_END(handle) == 0)
+ handle->rp_ptr = 0;
+
+ ret_addr = CIRCULARBUF_START(handle) + handle->rp_ptr;
+
+ /*
+ * Please note that we do not update the read pointer here. Only
+ * read pending pointer is updated, so that next reader knows where
+ * to read data from.
+ * read pointer can only be updated when the read is complete.
+ */
+ handle->rp_ptr = (uint16)(ret_addr - CIRCULARBUF_START(handle) + *available_len);
+
+ ASSERT(*available_len <= handle->depth);
+
+ OSL_CACHE_INV((void *) ret_addr, *available_len);
+
+ return ret_addr;
+}
+
+/*
+ * -----------------------------------------------------------------------------
+ * Function : circularbuf_read_complete
+ * Description:
+ * This function has to be called by the consumer end of circularbuf to indicate
+ * that data has been consumed and the read pointer can be updated.
+ *
+ * Input Args :
+ * bytes_read : No. of bytes consumed by the consumer. This has to match
+ * the length returned by circularbuf_get_read_ptr
+ *
+ * Return Values :
+ * CIRCULARBUF_SUCCESS : Otherwise
+ *
+ * -----------------------------------------------------------------------------
+ */
+circularbuf_ret_t BCMFASTPATH
+circularbuf_read_complete(circularbuf_t *handle, uint16 bytes_read)
+{
+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
+ ASSERT(bytes_read < handle->depth);
+
+ /* Update the read pointer */
+ if ((handle->r_ptr + bytes_read) >= handle->depth)
+ handle->r_ptr = bytes_read;
+ else
+ handle->r_ptr += bytes_read;
+
+ return CIRCULARBUF_SUCCESS;
+}
+/*
+ * -----------------------------------------------------------------------------
+ * Function : circularbuf_revert_rp_ptr
+ *
+ * Description:
+ * The rp_ptr update during circularbuf_get_read_ptr() is done to reflect the amount of data
+ * that is sent out to be read by the consumer. But the consumer may not always read the
+ * entire data. In such a case, the rp_ptr needs to be reverted back by 'left' bytes, where
+ * 'left' is the no. of bytes left unread.
+ *
+ * Input args:
+ * bytes : The no. of bytes left unread by the consumer
+ *
+ * -----------------------------------------------------------------------------
+ */
+circularbuf_ret_t
+circularbuf_revert_rp_ptr(circularbuf_t *handle, uint16 bytes)
+{
+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
+ ASSERT(bytes < handle->depth);
+
+ handle->rp_ptr -= bytes;
+
+ return CIRCULARBUF_SUCCESS;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
new file mode 100644
index 000000000000..cb327a6ba67f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -0,0 +1,931 @@
+/*
+ * Header file describing the internal (inter-module) DHD interfaces.
+ *
+ * Provides type definitions and function prototypes used to link the
+ * DHD OS, bus, and protocol modules.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd.h 662786 2016-11-11 09:06:37Z $
+ */
+
+/****************
+ * Common types *
+ */
+
+#ifndef _dhd_h_
+#define _dhd_h_
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
+#include <linux/wakelock.h>
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
+/* The kernel threading is sdio-specific */
+struct task_struct;
+struct sched_param;
+int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
+int get_scheduler_policy(struct task_struct *p);
+
+#define ALL_INTERFACES 0xff
+
+#include <wlioctl.h>
+#include <wlfc_proto.h>
+
+
+#if defined(KEEP_ALIVE)
+/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
+#define KEEP_ALIVE_PERIOD 55000
+#define NULL_PKT_STR "null_pkt"
+#endif /* KEEP_ALIVE */
+/* Forward decls */
+struct dhd_bus;
+struct dhd_prot;
+struct dhd_info;
+struct dhd_ioctl;
+
+/* The level of bus communication with the dongle */
+enum dhd_bus_state {
+ DHD_BUS_DOWN, /* Not ready for frame transfers */
+ DHD_BUS_LOAD, /* Download access only (CPU reset) */
+ DHD_BUS_DATA /* Ready for frame transfers */
+};
+
+
+enum dhd_op_flags {
+/* Firmware requested operation mode */
+ DHD_FLAG_STA_MODE = (1 << (0)), /* STA only */
+ DHD_FLAG_HOSTAP_MODE = (1 << (1)), /* SOFTAP only */
+ DHD_FLAG_P2P_MODE = (1 << (2)), /* P2P Only */
+ /* STA + P2P */
+ DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE),
+ DHD_FLAG_CONCURR_MULTI_CHAN_MODE = (1 << (4)), /* STA + P2P */
+ /* Current P2P mode for P2P connection */
+ DHD_FLAG_P2P_GC_MODE = (1 << (5)),
+ DHD_FLAG_P2P_GO_MODE = (1 << (6)),
+ DHD_FLAG_MBSS_MODE = (1 << (7)), /* MBSS in future */
+ DHD_FLAG_IBSS_MODE = (1 << (8)),
+ DHD_FLAG_MFG_MODE = (1 << (9))
+};
+
+/* Max sequential TX/RX Control timeouts to set HANG event */
+#ifndef MAX_CNTL_TX_TIMEOUT
+#define MAX_CNTL_TX_TIMEOUT 2
+#endif /* MAX_CNTL_TX_TIMEOUT */
+#ifndef MAX_CNTL_RX_TIMEOUT
+#define MAX_CNTL_RX_TIMEOUT 1
+#endif /* MAX_CNTL_RX_TIMEOUT */
+
+#define DHD_SCAN_ASSOC_ACTIVE_TIME 40 /* ms: Embedded default Active setting from DHD */
+#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */
+#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */
+
+#ifndef POWERUP_MAX_RETRY
+#define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */
+#endif
+#ifndef POWERUP_WAIT_MS
+#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */
+#endif
+
+enum dhd_bus_wake_state {
+ WAKE_LOCK_OFF,
+ WAKE_LOCK_PRIV,
+ WAKE_LOCK_DPC,
+ WAKE_LOCK_IOCTL,
+ WAKE_LOCK_DOWNLOAD,
+ WAKE_LOCK_TMOUT,
+ WAKE_LOCK_WATCHDOG,
+ WAKE_LOCK_LINK_DOWN_TMOUT,
+ WAKE_LOCK_PNO_FIND_TMOUT,
+ WAKE_LOCK_SOFTAP_SET,
+ WAKE_LOCK_SOFTAP_STOP,
+ WAKE_LOCK_SOFTAP_START,
+ WAKE_LOCK_SOFTAP_THREAD
+};
+
+enum dhd_prealloc_index {
+ DHD_PREALLOC_PROT = 0,
+ DHD_PREALLOC_RXBUF,
+ DHD_PREALLOC_DATABUF,
+ DHD_PREALLOC_OSL_BUF,
+ DHD_PREALLOC_WIPHY_ESCAN0 = 5,
+ DHD_PREALLOC_WIPHY_ESCAN1 = 6,
+ DHD_PREALLOC_DHD_INFO = 7,
+ DHD_PREALLOC_DHD_WLFC_INFO = 8,
+ DHD_PREALLOC_SECTION_MAX = DHD_PREALLOC_DHD_WLFC_INFO
+};
+
+#define PREALLOC_MASK_LEN 4
+
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#ifndef DHD_SDALIGN
+#define DHD_SDALIGN 32
+#endif
+
+#ifdef DHD_DEBUG
+#define DHD_JOIN_MAX_TIME_DEFAULT 10000 /* ms: Max time out for joining AP */
+#define DHD_SCAN_DEF_TIMEOUT 10000 /* ms: Max time out for scan in progress */
+#endif
+
+/* host reordering packts logic */
+/* followed the structure to hold the reorder buffers (void **p) */
+typedef struct reorder_info {
+ void **p;
+ uint8 flow_id;
+ uint8 cur_idx;
+ uint8 exp_idx;
+ uint8 max_idx;
+ uint8 pend_pkts;
+} reorder_info_t;
+
+#if defined(OOB_PARAM)
+#if !defined(OOB_INTR_ONLY)
+#error OOB_PARAM must be defined with OOB_INTR_ONLY!!
+#endif /* !defined(OOB_INTR_ONLY) */
+
+#define OOB_PARAM_IF(x) if (x)
+#define OOB_PARAM_ELSE() else
+
+#else /* defined(OOB_PARAM) */
+
+#define OOB_PARAM_IF(x)
+#define OOB_PARAM_ELSE()
+#endif /* defined(OOB_PARAM) */
+
+#ifdef DHDTCPACK_SUPPRESS
+#define TCPACK_SUP_OFF 0 /* TCPACK suppress off */
+/* Replace TCPACK in txq when new coming one has higher ACK number. */
+#define TCPACK_SUP_REPLACE 1
+/* TCPACK_SUP_REPLACE + delayed TCPACK TX unless ACK to PSH DATA.
+ * This will give benefits to Half-Duplex bus interface(e.g. SDIO) that
+ * 1. we are able to read TCP DATA packets first from the bus
+ * 2. TCPACKs that do not need to hurry delivered remains longer in TXQ so can be suppressed.
+ */
+#define TCPACK_SUP_DELAYTX 2
+#endif /* DHDTCPACK_SUPPRESS */
+
+/* Common structure for module and instance linkage */
+typedef struct dhd_pub {
+ /* Linkage ponters */
+ osl_t *osh; /* OSL handle */
+ struct dhd_bus *bus; /* Bus module handle */
+ struct dhd_prot *prot; /* Protocol module handle */
+ struct dhd_info *info; /* Info module handle */
+
+ /* to NDIS developer, the structure dhd_common is redundant,
+ * please do NOT merge it back from other branches !!!
+ */
+
+
+ /* Internal dhd items */
+ bool up; /* Driver up/down (to OS) */
+ bool txoff; /* Transmit flow-controlled */
+ bool dongle_reset; /* TRUE = DEVRESET put dongle into reset */
+ enum dhd_bus_state busstate;
+ uint hdrlen; /* Total DHD header length (proto + bus) */
+ uint maxctl; /* Max size rxctl request from proto to bus */
+ uint rxsz; /* Rx buffer size bus module should use */
+ uint8 wme_dp; /* wme discard priority */
+
+ /* Dongle media info */
+ bool iswl; /* Dongle-resident driver is wl */
+ ulong drv_version; /* Version of dongle-resident driver */
+ struct ether_addr mac; /* MAC address obtained from dongle */
+ dngl_stats_t dstats; /* Stats for dongle-based data */
+
+ /* Additional stats for the bus level */
+ ulong tx_packets; /* Data packets sent to dongle */
+ ulong tx_multicast; /* Multicast data packets sent to dongle */
+ ulong tx_errors; /* Errors in sending data to dongle */
+ ulong tx_ctlpkts; /* Control packets sent to dongle */
+ ulong tx_ctlerrs; /* Errors sending control frames to dongle */
+ ulong rx_packets; /* Packets sent up the network interface */
+ ulong rx_multicast; /* Multicast packets sent up the network interface */
+ ulong rx_errors; /* Errors processing rx data packets */
+ ulong rx_ctlpkts; /* Control frames processed from dongle */
+ ulong rx_ctlerrs; /* Errors in processing rx control frames */
+ ulong rx_dropped; /* Packets dropped locally (no memory) */
+ ulong rx_flushed; /* Packets flushed due to unscheduled sendup thread */
+ ulong wd_dpc_sched; /* Number of times dhd dpc scheduled by watchdog timer */
+
+ ulong rx_readahead_cnt; /* Number of packets where header read-ahead was used. */
+ ulong tx_realloc; /* Number of tx packets we had to realloc for headroom */
+ ulong fc_packets; /* Number of flow control pkts recvd */
+
+ /* Last error return */
+ int bcmerror;
+ uint tickcnt;
+
+ /* Last error from dongle */
+ int dongle_error;
+
+ uint8 country_code[WLC_CNTRY_BUF_SZ];
+
+ /* Suspend disable flag and "in suspend" flag */
+ int suspend_disable_flag; /* "1" to disable all extra powersaving during suspend */
+ int in_suspend; /* flag set to 1 when early suspend called */
+#ifdef PNO_SUPPORT
+ int pno_enable; /* pno status : "1" is pno enable */
+ int pno_suspend; /* pno suspend status : "1" is pno suspended */
+#endif /* PNO_SUPPORT */
+ /* DTIM skip value, default 0(or 1) means wake each DTIM
+ * 3 means skip 2 DTIMs and wake up 3rd DTIM(9th beacon when AP DTIM is 3)
+ */
+ int suspend_bcn_li_dtim; /* bcn_li_dtim value in suspend mode */
+#ifdef PKT_FILTER_SUPPORT
+ int early_suspended; /* Early suspend status */
+ int dhcp_in_progress; /* DHCP period */
+#endif
+
+ /* Pkt filter defination */
+ char * pktfilter[100];
+ int pktfilter_count;
+
+ wl_country_t dhd_cspec; /* Current Locale info */
+ char eventmask[WL_EVENTING_MASK_LEN];
+ char prealloc_malloc_mask[PREALLOC_MASK_LEN];
+ int op_mode; /* STA, HostAPD, WFD, SoftAP */
+
+/* Set this to 1 to use a seperate interface (p2p0) for p2p operations.
+ * For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework
+ * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile
+ */
+/* #define WL_ENABLE_P2P_IF 1 */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */
+ struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */
+#endif
+
+#ifdef PROP_TXSTATUS
+ bool wlfc_enabled;
+ int wlfc_mode;
+ void* wlfc_state;
+ /*
+ Mode in which the dhd flow control shall operate. Must be set before
+ traffic starts to the device.
+ 0 - Do not do any proptxtstatus flow control
+ 1 - Use implied credit from a packet status
+ 2 - Use explicit credit
+ 3 - Only AMPDU hostreorder used. no wlfc.
+ */
+ uint8 proptxstatus_mode;
+ bool proptxstatus_txoff;
+ bool proptxstatus_module_ignore;
+ bool proptxstatus_credit_ignore;
+ bool proptxstatus_txstatus_ignore;
+
+ bool wlfc_rxpkt_chk;
+ /*
+ * implement below functions in each platform if needed.
+ */
+ /* platform specific function whether to skip flow control */
+ bool (*skip_fc)(void);
+ /* platform specific function for wlfc_enable and wlfc_deinit */
+ void (*plat_init)(void *dhd);
+ void (*plat_deinit)(void *dhd);
+#endif /* PROP_TXSTATUS */
+#ifdef PNO_SUPPORT
+ void *pno_state;
+#endif
+#ifdef ROAM_AP_ENV_DETECTION
+ bool roam_env_detection;
+#endif
+ bool dongle_isolation;
+ bool dongle_trap_occured; /* flag for sending HANG event to upper layer */
+ int hang_was_sent;
+ int rxcnt_timeout; /* counter rxcnt timeout to send HANG */
+ int txcnt_timeout; /* counter txcnt timeout to send HANG */
+ bool hang_report; /* enable hang report by default */
+#ifdef WLMEDIA_HTSF
+ uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */
+#endif
+#ifdef WLTDLS
+ bool tdls_enable;
+#endif
+ struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS];
+ char fw_capabilities[WLC_IOCTL_SMLEN];
+ #define MAXSKBPEND 1024
+ void *skbbuf[MAXSKBPEND];
+ uint32 store_idx;
+ uint32 sent_idx;
+#ifdef DHDTCPACK_SUPPRESS
+ uint8 tcpack_sup_mode; /* TCPACK suppress mode */
+ void *tcpack_sup_module; /* TCPACK suppress module */
+#endif /* DHDTCPACK_SUPPRESS */
+#if defined(ARP_OFFLOAD_SUPPORT)
+ uint32 arp_version;
+#endif
+#ifdef CUSTOM_SET_CPUCORE
+ struct task_struct * current_dpc;
+ struct task_struct * current_rxf;
+ int chan_isvht80;
+#endif /* CUSTOM_SET_CPUCORE */
+#ifdef OOB_PARAM
+ uint oob_disable;
+#endif /* OOB_PARAM */
+} dhd_pub_t;
+
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+
+ #define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
+ #define _DHD_PM_RESUME_WAIT(a, b) do {\
+ int retry = 0; \
+ SMP_RD_BARRIER_DEPENDS(); \
+ while (dhd_mmc_suspend && retry++ != b) { \
+ SMP_RD_BARRIER_DEPENDS(); \
+ wait_event_interruptible_timeout(a, !dhd_mmc_suspend, 1); \
+ } \
+ } while (0)
+ #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200)
+ #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0)
+ #ifdef CUSTOMER_HW4
+ #define DHD_PM_RESUME_RETURN_ERROR(a) do { \
+ if (dhd_mmc_suspend) { \
+ printf("%s[%d]: mmc is still in suspend state!!!\n", \
+ __FUNCTION__, __LINE__); \
+ return a; \
+ } \
+ } while (0)
+ #else
+ #define DHD_PM_RESUME_RETURN_ERROR(a) do { \
+ if (dhd_mmc_suspend) return a; } while (0)
+ #endif
+ #define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0)
+
+ #define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
+ #define SPINWAIT_SLEEP(a, exp, us) do { \
+ uint countdown = (us) + 9999; \
+ while ((exp) && (countdown >= 10000)) { \
+ wait_event_interruptible_timeout(a, FALSE, 1); \
+ countdown -= 10000; \
+ } \
+ } while (0)
+
+ #else
+
+ #define DHD_PM_RESUME_WAIT_INIT(a)
+ #define DHD_PM_RESUME_WAIT(a)
+ #define DHD_PM_RESUME_WAIT_FOREVER(a)
+ #define DHD_PM_RESUME_RETURN_ERROR(a)
+ #define DHD_PM_RESUME_RETURN
+
+ #define DHD_SPINWAIT_SLEEP_INIT(a)
+ #define SPINWAIT_SLEEP(a, exp, us) do { \
+ uint countdown = (us) + 9; \
+ while ((exp) && (countdown >= 10)) { \
+ OSL_DELAY(10); \
+ countdown -= 10; \
+ } \
+ } while (0)
+
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+
+#ifndef OSL_SLEEP
+#define OSL_SLEEP(ms) OSL_DELAY(ms*1000)
+#endif /* OSL_SLEEP */
+
+#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */
+
+unsigned long dhd_os_spin_lock(dhd_pub_t *pub);
+void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags);
+#ifdef PNO_SUPPORT
+int dhd_pno_clean(dhd_pub_t *dhd);
+#endif /* PNO_SUPPORT */
+/*
+ * Wake locks are an Android power management concept. They are used by applications and services
+ * to request CPU resources.
+ */
+extern int dhd_os_wake_lock(dhd_pub_t *pub);
+extern int dhd_os_wake_unlock(dhd_pub_t *pub);
+extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub);
+extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val);
+extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val);
+extern int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub);
+extern int dhd_os_wd_wake_lock(dhd_pub_t *pub);
+extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub);
+
+inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ mutex_init(&dhdp->wl_softap_lock);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+}
+
+inline static void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t * dhdp)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ mutex_lock(&dhdp->wl_softap_lock);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+}
+
+inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ mutex_unlock(&dhdp->wl_softap_lock);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+}
+
+#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub)
+#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub)
+#define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub)
+#define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \
+ dhd_os_wake_lock_rx_timeout_enable(pub, val)
+#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \
+ dhd_os_wake_lock_ctrl_timeout_enable(pub, val)
+#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL(pub) \
+ dhd_os_wake_lock_ctrl_timeout_cancel(pub)
+
+#define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub)
+#define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub)
+#define DHD_PACKET_TIMEOUT_MS 500
+#define DHD_EVENT_TIMEOUT_MS 1500
+
+
+/* interface operations (register, remove) should be atomic, use this lock to prevent race
+ * condition among wifi on/off and interface operation functions
+ */
+void dhd_net_if_lock(struct net_device *dev);
+void dhd_net_if_unlock(struct net_device *dev);
+
+
+typedef enum dhd_attach_states
+{
+ DHD_ATTACH_STATE_INIT = 0x0,
+ DHD_ATTACH_STATE_NET_ALLOC = 0x1,
+ DHD_ATTACH_STATE_DHD_ALLOC = 0x2,
+ DHD_ATTACH_STATE_ADD_IF = 0x4,
+ DHD_ATTACH_STATE_PROT_ATTACH = 0x8,
+ DHD_ATTACH_STATE_WL_ATTACH = 0x10,
+ DHD_ATTACH_STATE_THREADS_CREATED = 0x20,
+ DHD_ATTACH_STATE_WAKELOCKS_INIT = 0x40,
+ DHD_ATTACH_STATE_CFG80211 = 0x80,
+ DHD_ATTACH_STATE_EARLYSUSPEND_DONE = 0x100,
+ DHD_ATTACH_STATE_DONE = 0x200
+} dhd_attach_states_t;
+
+/* Value -1 means we are unsuccessful in creating the kthread. */
+#define DHD_PID_KT_INVALID -1
+/* Value -2 means we are unsuccessful in both creating the kthread and tasklet */
+#define DHD_PID_KT_TL_INVALID -2
+
+/*
+ * Exported from dhd OS modules (dhd_linux/dhd_ndis)
+ */
+
+/* Indication from bus module regarding presence/insertion of dongle.
+ * Return dhd_pub_t pointer, used as handle to OS module in later calls.
+ * Returned structure should have bus and prot pointers filled in.
+ * bus_hdrlen specifies required headroom for bus module header.
+ */
+extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen);
+#if defined(WLP2P) && defined(WL_CFG80211)
+/* To allow attach/detach calls corresponding to p2p0 interface */
+extern int dhd_attach_p2p(dhd_pub_t *);
+extern int dhd_detach_p2p(dhd_pub_t *);
+#endif /* WLP2P && WL_CFG80211 */
+extern int dhd_register_if(dhd_pub_t *dhdp, int idx, bool need_rtnl_lock);
+
+/* Indication from bus module regarding removal/absence of dongle */
+extern void dhd_detach(dhd_pub_t *dhdp);
+extern void dhd_free(dhd_pub_t *dhdp);
+
+/* Indication from bus module to change flow-control state */
+extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on);
+
+/* Store the status of a connection attempt for later retrieval by an iovar */
+extern void dhd_store_conn_status(uint32 event, uint32 status, uint32 reason);
+
+extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec);
+
+/* Receive frame for delivery to OS. Callee disposes of rxp. */
+extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *rxp, int numpkt, uint8 chan);
+
+/* Return pointer to interface name */
+extern char *dhd_ifname(dhd_pub_t *dhdp, int idx);
+
+/* Request scheduling of the bus dpc */
+extern void dhd_sched_dpc(dhd_pub_t *dhdp);
+
+/* Notify tx completion */
+extern void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success);
+
+/* OS independent layer functions */
+extern int dhd_os_proto_block(dhd_pub_t * pub);
+extern int dhd_os_proto_unblock(dhd_pub_t * pub);
+extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition, bool * pending);
+extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub);
+extern unsigned int dhd_os_get_ioctl_resp_timeout(void);
+extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
+
+extern int dhd_os_get_image_block(char * buf, int len, void * image);
+extern void * dhd_os_open_image(char * filename);
+extern void dhd_os_close_image(void * image);
+extern void dhd_os_wd_timer(void *bus, uint wdtick);
+extern void dhd_os_sdlock(dhd_pub_t * pub);
+extern void dhd_os_sdunlock(dhd_pub_t * pub);
+extern void dhd_os_sdlock_txq(dhd_pub_t * pub);
+extern void dhd_os_sdunlock_txq(dhd_pub_t * pub);
+extern void dhd_os_sdlock_rxq(dhd_pub_t * pub);
+extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub);
+extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub);
+#ifdef DHDTCPACK_SUPPRESS
+extern void dhd_os_tcpacklock(dhd_pub_t *pub);
+extern void dhd_os_tcpackunlock(dhd_pub_t *pub);
+#endif /* DHDTCPACK_SUPPRESS */
+
+extern int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr);
+extern int dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff);
+extern int dhd_custom_get_mac_address(void *adapter, unsigned char *buf);
+extern void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec);
+extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub);
+extern void dhd_os_sdlock_eventq(dhd_pub_t * pub);
+extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub);
+extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret);
+extern int dhd_os_send_hang_message(dhd_pub_t *dhdp);
+extern void dhd_set_version_info(dhd_pub_t *pub, char *fw);
+extern bool dhd_os_check_if_up(dhd_pub_t *pub);
+extern int dhd_os_check_wakelock(dhd_pub_t *pub);
+
+#ifdef CUSTOM_SET_CPUCORE
+extern void dhd_set_cpucore(dhd_pub_t *dhd, int set);
+#endif /* CUSTOM_SET_CPUCORE */
+
+#if defined(KEEP_ALIVE)
+extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
+#endif /* KEEP_ALIVE */
+
+
+#ifdef PKT_FILTER_SUPPORT
+#define DHD_UNICAST_FILTER_NUM 0
+#define DHD_BROADCAST_FILTER_NUM 1
+#define DHD_MULTICAST4_FILTER_NUM 2
+#define DHD_MULTICAST6_FILTER_NUM 3
+#define DHD_MDNS_FILTER_NUM 4
+#define DHD_ARP_FILTER_NUM 5
+extern int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val);
+extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd);
+extern int net_os_enable_packet_filter(struct net_device *dev, int val);
+extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num);
+#endif /* PKT_FILTER_SUPPORT */
+
+extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd);
+extern bool dhd_support_sta_mode(dhd_pub_t *dhd);
+
+#ifdef DHD_DEBUG
+extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size);
+#endif /* DHD_DEBUG */
+
+extern void dhd_os_sdtxlock(dhd_pub_t * pub);
+extern void dhd_os_sdtxunlock(dhd_pub_t * pub);
+
+typedef struct {
+ uint32 limit; /* Expiration time (usec) */
+ uint32 increment; /* Current expiration increment (usec) */
+ uint32 elapsed; /* Current elapsed time (usec) */
+ uint32 tick; /* O/S tick time (usec) */
+} dhd_timeout_t;
+
+#ifdef SHOW_LOGTRACE
+typedef struct {
+ int num_fmts;
+ char **fmts;
+ char *raw_fmts;
+ char *raw_sstr;
+ uint32 ramstart;
+ uint32 rodata_start;
+ uint32 rodata_end;
+ char *rom_raw_sstr;
+ uint32 rom_ramstart;
+ uint32 rom_rodata_start;
+ uint32 rom_rodata_end;
+} dhd_event_log_t;
+#endif /* SHOW_LOGTRACE */
+
+extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec);
+extern int dhd_timeout_expired(dhd_timeout_t *tmo);
+
+extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
+extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net);
+extern struct net_device * dhd_idx2net(void *pub, int ifidx);
+extern int net_os_send_hang_message(struct net_device *dev);
+extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, uint16 pktlen,
+ wl_event_msg_t *, void **data_ptr, void *raw_event);
+extern void wl_event_to_host_order(wl_event_msg_t * evt);
+extern int wl_host_event_get_data(void *pktdata, uint pktlen, wl_event_msg_t *evt);
+
+extern int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len);
+extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set,
+ int ifindex);
+extern void dhd_common_init(osl_t *osh);
+
+extern int dhd_do_driver_init(struct net_device *net);
+extern int dhd_event_ifadd(struct dhd_info *dhd, struct wl_event_data_if *ifevent,
+ char *name, uint8 *mac);
+extern int dhd_event_ifdel(struct dhd_info *dhd, struct wl_event_data_if *ifevent,
+ char *name, uint8 *mac);
+extern struct net_device* dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, char *name,
+ uint8 *mac, uint8 bssidx, bool need_rtnl_lock, char *dngl_name);
+extern int dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock);
+extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name);
+extern void dhd_vif_del(struct dhd_info *dhd, int ifidx);
+extern void dhd_event(struct dhd_info *dhd, char *evpkt, uint evlen, int ifidx);
+extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len);
+
+/* Send packet to dongle via data channel */
+extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt);
+
+/* send up locally generated event */
+extern void dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data);
+/* Send event to host */
+extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data);
+#ifdef LOG_INTO_TCPDUMP
+extern void dhd_sendup_log(dhd_pub_t *dhdp, void *data, int len);
+#endif /* LOG_INTO_TCPDUMP */
+extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag);
+extern uint dhd_bus_status(dhd_pub_t *dhdp);
+extern int dhd_bus_start(dhd_pub_t *dhdp);
+extern int dhd_bus_suspend(dhd_pub_t *dhdpub);
+extern int dhd_bus_resume(dhd_pub_t *dhdpub, int stage);
+extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size);
+extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
+extern bool dhd_is_associated(dhd_pub_t *dhd, uint8 ifidx, int *retval);
+extern uint dhd_bus_chip_id(dhd_pub_t *dhdp);
+extern uint dhd_bus_chiprev_id(dhd_pub_t *dhdp);
+extern uint dhd_bus_chippkg_id(dhd_pub_t *dhdp);
+
+#if defined(KEEP_ALIVE)
+extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
+#endif /* KEEP_ALIVE */
+
+extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd);
+extern int dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set);
+typedef enum cust_gpio_modes {
+ WLAN_RESET_ON,
+ WLAN_RESET_OFF,
+ WLAN_POWER_ON,
+ WLAN_POWER_OFF
+} cust_gpio_modes_t;
+
+extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
+extern int wl_iw_send_priv_event(struct net_device *dev, char *flag);
+/*
+ * Insmod parameters for debug/test
+ */
+
+/* Watchdog timer interval */
+extern uint dhd_watchdog_ms;
+
+#if defined(DHD_DEBUG)
+/* Console output poll interval */
+extern uint dhd_console_ms;
+extern uint wl_msg_level;
+#endif /* defined(DHD_DEBUG) */
+
+extern uint dhd_slpauto;
+
+/* Use interrupts */
+extern uint dhd_intr;
+
+/* Use polling */
+extern uint dhd_poll;
+
+/* ARP offload agent mode */
+extern uint dhd_arp_mode;
+
+/* ARP offload enable */
+extern uint dhd_arp_enable;
+
+/* Pkt filte enable control */
+extern uint dhd_pkt_filter_enable;
+
+/* Pkt filter init setup */
+extern uint dhd_pkt_filter_init;
+
+/* Pkt filter mode control */
+extern uint dhd_master_mode;
+
+/* Roaming mode control */
+extern uint dhd_roam_disable;
+
+/* Roaming mode control */
+extern uint dhd_radio_up;
+
+/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
+extern int dhd_idletime;
+#ifdef DHD_USE_IDLECOUNT
+#define DHD_IDLETIME_TICKS 5
+#else
+#define DHD_IDLETIME_TICKS 1
+#endif /* DHD_USE_IDLECOUNT */
+
+/* SDIO Drive Strength */
+extern uint dhd_sdiod_drive_strength;
+
+/* Override to force tx queueing all the time */
+extern uint dhd_force_tx_queueing;
+/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
+#define DEFAULT_KEEP_ALIVE_VALUE 55000 /* msec */
+#ifndef CUSTOM_KEEP_ALIVE_SETTING
+#define CUSTOM_KEEP_ALIVE_SETTING DEFAULT_KEEP_ALIVE_VALUE
+#endif /* DEFAULT_KEEP_ALIVE_VALUE */
+
+#define NULL_PKT_STR "null_pkt"
+
+/* hooks for custom glom setting option via Makefile */
+#define DEFAULT_GLOM_VALUE -1
+#ifndef CUSTOM_GLOM_SETTING
+#define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE
+#endif
+#define WL_AUTO_ROAM_TRIGGER -75
+/* hooks for custom Roaming Trigger setting via Makefile */
+#define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */
+#define DEFAULT_ROAM_TRIGGER_SETTING -1
+#ifndef CUSTOM_ROAM_TRIGGER_SETTING
+#define CUSTOM_ROAM_TRIGGER_SETTING DEFAULT_ROAM_TRIGGER_VALUE
+#endif
+
+/* hooks for custom Roaming Romaing setting via Makefile */
+#define DEFAULT_ROAM_DELTA_VALUE 10 /* dBm default roam delta all band */
+#define DEFAULT_ROAM_DELTA_SETTING -1
+#ifndef CUSTOM_ROAM_DELTA_SETTING
+#define CUSTOM_ROAM_DELTA_SETTING DEFAULT_ROAM_DELTA_VALUE
+#endif
+
+/* hooks for custom PNO Event wake lock to guarantee enough time
+ for the Platform to detect Event before system suspended
+*/
+#define DEFAULT_PNO_EVENT_LOCK_xTIME 2 /* multiplay of DHD_PACKET_TIMEOUT_MS */
+#ifndef CUSTOM_PNO_EVENT_LOCK_xTIME
+#define CUSTOM_PNO_EVENT_LOCK_xTIME DEFAULT_PNO_EVENT_LOCK_xTIME
+#endif
+/* hooks for custom dhd_dpc_prio setting option via Makefile */
+#define DEFAULT_DHP_DPC_PRIO 1
+#ifndef CUSTOM_DPC_PRIO_SETTING
+#define CUSTOM_DPC_PRIO_SETTING DEFAULT_DHP_DPC_PRIO
+#endif
+
+#ifndef CUSTOM_LISTEN_INTERVAL
+#define CUSTOM_LISTEN_INTERVAL LISTEN_INTERVAL
+#endif /* CUSTOM_LISTEN_INTERVAL */
+
+#define DEFAULT_SUSPEND_BCN_LI_DTIM 3
+#ifndef CUSTOM_SUSPEND_BCN_LI_DTIM
+#define CUSTOM_SUSPEND_BCN_LI_DTIM DEFAULT_SUSPEND_BCN_LI_DTIM
+#endif
+
+#ifndef CUSTOM_RXF_PRIO_SETTING
+#define CUSTOM_RXF_PRIO_SETTING MAX((CUSTOM_DPC_PRIO_SETTING - 1), 1)
+#endif
+
+#define DEFAULT_WIFI_TURNOFF_DELAY 0
+#define WIFI_TURNOFF_DELAY DEFAULT_WIFI_TURNOFF_DELAY
+
+#define DEFAULT_WIFI_TURNON_DELAY 200
+#ifndef WIFI_TURNON_DELAY
+#define WIFI_TURNON_DELAY DEFAULT_WIFI_TURNON_DELAY
+#endif /* WIFI_TURNON_DELAY */
+
+#ifdef WLTDLS
+#ifndef CUSTOM_TDLS_IDLE_MODE_SETTING
+#define CUSTOM_TDLS_IDLE_MODE_SETTING 60000 /* 60sec to tear down TDLS of not active */
+#endif
+#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_HIGH
+#define CUSTOM_TDLS_RSSI_THRESHOLD_HIGH -70 /* rssi threshold for establishing TDLS link */
+#endif
+#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_LOW
+#define CUSTOM_TDLS_RSSI_THRESHOLD_LOW -80 /* rssi threshold for tearing down TDLS link */
+#endif
+#endif /* WLTDLS */
+
+#ifdef DHD_DEBUG
+extern int dhd_start_join_timer(dhd_pub_t *pub);
+extern int dhd_del_join_timer(dhd_pub_t *pub);
+extern int dhd_set_join_timeout(dhd_pub_t *pub, uint32 timeout);
+extern uint32 dhd_get_join_timeout(dhd_pub_t *pub);
+extern int dhd_add_scan_timer(dhd_pub_t *dhd_pub);
+extern int dhd_del_scan_timer(dhd_pub_t *dhd_pub);
+extern int dhd_set_scan_timeout(dhd_pub_t *pub, uint32 timeout);
+extern uint32 dhd_get_scan_timeout(dhd_pub_t *pub);
+#endif /* DHD_DEBUG */
+
+#define MAX_DTIM_SKIP_BEACON_INTERVAL 100 /* max allowed associated AP beacon for DTIM skip */
+#ifndef MAX_DTIM_ALLOWED_INTERVAL
+#define MAX_DTIM_ALLOWED_INTERVAL 600 /* max allowed total beacon interval for DTIM skip */
+#endif
+#define NO_DTIM_SKIP 1
+#ifdef SDTEST
+/* Echo packet generator (SDIO), pkts/s */
+extern uint dhd_pktgen;
+
+/* Echo packet len (0 => sawtooth, max 1800) */
+extern uint dhd_pktgen_len;
+#define MAX_PKTGEN_LEN 1800
+#endif
+
+
+/* optionally set by a module_param_string() */
+#define MOD_PARAM_PATHLEN 2048
+#define MOD_PARAM_INFOLEN 512
+
+#ifdef SOFTAP
+extern char fw_path2[MOD_PARAM_PATHLEN];
+#endif
+
+/* Flag to indicate if we should download firmware on driver load */
+extern uint dhd_download_fw_on_driverload;
+
+
+/* For supporting multiple interfaces */
+#define DHD_MAX_IFS 16
+#define DHD_DEL_IF -0xe
+#define DHD_BAD_IF -0xf
+
+extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
+extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
+
+#define IFLOCK_INIT(lock) *lock = 0
+#define IFLOCK(lock) while (InterlockedCompareExchange((lock), 1, 0)) \
+ NdisStallExecution(1);
+#define IFUNLOCK(lock) InterlockedExchange((lock), 0)
+#define IFLOCK_FREE(lock)
+#define FW_SUPPORTED(dhd, capa) ((strstr(dhd->fw_capabilities, #capa) != NULL))
+#ifdef ARP_OFFLOAD_SUPPORT
+#define MAX_IPV4_ENTRIES 8
+void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode);
+void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable);
+
+/* dhd_commn arp offload wrapers */
+void dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx);
+void dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx);
+int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx);
+void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx);
+#endif /* ARP_OFFLOAD_SUPPORT */
+#ifdef WLTDLS
+int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac);
+#endif
+/* Neighbor Discovery Offload Support */
+int dhd_ndo_enable(dhd_pub_t * dhd, int ndo_enable);
+int dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipaddr, int idx);
+int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx);
+/* ioctl processing for nl80211 */
+int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc, void *data_buf);
+
+void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path);
+void dhd_set_bus_state(void *bus, uint32 state);
+
+/* Remove proper pkts(either one no-frag pkt or whole fragmented pkts) */
+typedef int (*f_droppkt_t)(dhd_pub_t *dhdp, int prec, void* p, bool bPktInQ);
+extern bool dhd_prec_drop_pkts(dhd_pub_t *dhdp, struct pktq *pq, int prec, f_droppkt_t fn);
+
+#ifdef PROP_TXSTATUS
+int dhd_os_wlfc_block(dhd_pub_t *pub);
+int dhd_os_wlfc_unblock(dhd_pub_t *pub);
+extern const uint8 prio2fifo[];
+#endif /* PROP_TXSTATUS */
+
+uint8* dhd_os_prealloc(dhd_pub_t *dhdpub, int section, uint size, bool kmalloc_if_fail);
+void dhd_os_prefree(dhd_pub_t *dhdpub, int section, void *addr, uint size);
+
+#if defined(CONFIG_DHD_USE_STATIC_BUF)
+#define DHD_OS_PREALLOC(dhdpub, section, size) dhd_os_prealloc(dhdpub, section, size, TRUE)
+#define DHD_OS_PREFREE(dhdpub, section, addr, size) dhd_os_prefree(dhdpub, section, addr, size)
+#else
+#define DHD_OS_PREALLOC(dhdpub, section, size) MALLOC(dhdpub->osh, size)
+#define DHD_OS_PREFREE(dhdpub, section, addr, size) MFREE(dhdpub->osh, addr, size)
+#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */
+
+
+#ifdef OOB_PARAM
+extern uint dhd_get_oob_disable(struct dhd_bus* bus);
+#endif /* OOB_PARAM */
+
+#endif /* _dhd_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_bta.c b/drivers/net/wireless/bcmdhd/dhd_bta.c
new file mode 100644
index 000000000000..878af0eece40
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_bta.c
@@ -0,0 +1,337 @@
+/*
+ * BT-AMP support routines
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_bta.c 434656 2013-11-07 01:11:33Z $
+ */
+#error "WLBTAMP is not defined"
+
+#include <typedefs.h>
+#include <osl.h>
+#include <bcmcdc.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/802.11.h>
+#include <proto/802.11_bta.h>
+#include <proto/bt_amp_hci.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_bus.h>
+#include <dhd_proto.h>
+#include <dhdioctl.h>
+#include <dhd_dbg.h>
+
+#include <dhd_bta.h>
+
+
+#ifdef SEND_HCI_CMD_VIA_IOCTL
+#define BTA_HCI_CMD_MAX_LEN HCI_CMD_PREAMBLE_SIZE + HCI_CMD_DATA_SIZE
+
+/* Send HCI cmd via wl iovar HCI_cmd to the dongle. */
+int
+dhd_bta_docmd(dhd_pub_t *pub, void *cmd_buf, uint cmd_len)
+{
+ amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)cmd_buf;
+ uint8 buf[BTA_HCI_CMD_MAX_LEN + 16];
+ uint len = sizeof(buf);
+ wl_ioctl_t ioc;
+
+ if (cmd_len < HCI_CMD_PREAMBLE_SIZE)
+ return BCME_BADLEN;
+
+ if ((uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE > cmd_len)
+ return BCME_BADLEN;
+
+ len = bcm_mkiovar("HCI_cmd",
+ (char *)cmd, (uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE, (char *)buf, len);
+
+
+ memset(&ioc, 0, sizeof(ioc));
+
+ ioc.cmd = WLC_SET_VAR;
+ ioc.buf = buf;
+ ioc.len = len;
+ ioc.set = TRUE;
+
+ return dhd_wl_ioctl(pub, &ioc, ioc.buf, ioc.len);
+}
+#else /* !SEND_HCI_CMD_VIA_IOCTL */
+
+static void
+dhd_bta_flush_hcidata(dhd_pub_t *pub, uint16 llh)
+{
+ int prec;
+ struct pktq *q;
+ uint count = 0;
+
+ q = dhd_bus_txq(pub->bus);
+ if (q == NULL)
+ return;
+
+ DHD_BTA(("dhd: flushing HCI ACL data for logical link %u...\n", llh));
+
+ dhd_os_sdlock_txq(pub);
+
+ /* Walk through the txq and toss all HCI ACL data packets */
+ PKTQ_PREC_ITER(q, prec) {
+ void *head_pkt = NULL;
+
+ while (pktq_ppeek(q, prec) != head_pkt) {
+ void *pkt = pktq_pdeq(q, prec);
+ int ifidx;
+
+ dhd_prot_hdrpull(pub, &ifidx, pkt, NULL, NULL);
+
+ if (PKTLEN(pub->osh, pkt) >= RFC1042_HDR_LEN) {
+ struct ether_header *eh =
+ (struct ether_header *)PKTDATA(pub->osh, pkt);
+
+ if (ntoh16(eh->ether_type) < ETHER_TYPE_MIN) {
+ struct dot11_llc_snap_header *lsh =
+ (struct dot11_llc_snap_header *)&eh[1];
+
+ if (bcmp(lsh, BT_SIG_SNAP_MPROT,
+ DOT11_LLC_SNAP_HDR_LEN - 2) == 0 &&
+ ntoh16(lsh->type) == BTA_PROT_L2CAP) {
+ amp_hci_ACL_data_t *ACL_data =
+ (amp_hci_ACL_data_t *)&lsh[1];
+ uint16 handle = ltoh16(ACL_data->handle);
+
+ if (HCI_ACL_DATA_HANDLE(handle) == llh) {
+ PKTFREE(pub->osh, pkt, TRUE);
+ count ++;
+ continue;
+ }
+ }
+ }
+ }
+
+ dhd_prot_hdrpush(pub, ifidx, pkt);
+
+ if (head_pkt == NULL)
+ head_pkt = pkt;
+ pktq_penq(q, prec, pkt);
+ }
+ }
+
+ dhd_os_sdunlock_txq(pub);
+
+ DHD_BTA(("dhd: flushed %u packet(s) for logical link %u...\n", count, llh));
+}
+
+/* Handle HCI cmd locally.
+ * Return 0: continue to send the cmd across SDIO
+ * < 0: stop, fail
+ * > 0: stop, succuess
+ */
+static int
+_dhd_bta_docmd(dhd_pub_t *pub, amp_hci_cmd_t *cmd)
+{
+ int status = 0;
+
+ switch (ltoh16_ua((uint8 *)&cmd->opcode)) {
+ case HCI_Enhanced_Flush: {
+ eflush_cmd_parms_t *cmdparms = (eflush_cmd_parms_t *)cmd->parms;
+ dhd_bta_flush_hcidata(pub, ltoh16_ua(cmdparms->llh));
+ break;
+ }
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/* Send HCI cmd encapsulated in BT-SIG frame via data channel to the dongle. */
+int
+dhd_bta_docmd(dhd_pub_t *pub, void *cmd_buf, uint cmd_len)
+{
+ amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)cmd_buf;
+ struct ether_header *eh;
+ struct dot11_llc_snap_header *lsh;
+ osl_t *osh = pub->osh;
+ uint len;
+ void *p;
+ int status;
+
+ if (cmd_len < HCI_CMD_PREAMBLE_SIZE) {
+ DHD_ERROR(("dhd_bta_docmd: short command, cmd_len %u\n", cmd_len));
+ return BCME_BADLEN;
+ }
+
+ if ((len = (uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE) > cmd_len) {
+ DHD_ERROR(("dhd_bta_docmd: malformed command, len %u cmd_len %u\n",
+ len, cmd_len));
+ /* return BCME_BADLEN; */
+ }
+
+ p = PKTGET(osh, pub->hdrlen + RFC1042_HDR_LEN + len, TRUE);
+ if (p == NULL) {
+ DHD_ERROR(("dhd_bta_docmd: out of memory\n"));
+ return BCME_NOMEM;
+ }
+
+
+ /* intercept and handle the HCI cmd locally */
+ if ((status = _dhd_bta_docmd(pub, cmd)) > 0)
+ return 0;
+ else if (status < 0)
+ return status;
+
+ /* copy in HCI cmd */
+ PKTPULL(osh, p, pub->hdrlen + RFC1042_HDR_LEN);
+ bcopy(cmd, PKTDATA(osh, p), len);
+
+ /* copy in partial Ethernet header with BT-SIG LLC/SNAP header */
+ PKTPUSH(osh, p, RFC1042_HDR_LEN);
+ eh = (struct ether_header *)PKTDATA(osh, p);
+ bzero(eh->ether_dhost, ETHER_ADDR_LEN);
+ ETHER_SET_LOCALADDR(eh->ether_dhost);
+ bcopy(&pub->mac, eh->ether_shost, ETHER_ADDR_LEN);
+ eh->ether_type = hton16(len + DOT11_LLC_SNAP_HDR_LEN);
+ lsh = (struct dot11_llc_snap_header *)&eh[1];
+ bcopy(BT_SIG_SNAP_MPROT, lsh, DOT11_LLC_SNAP_HDR_LEN - 2);
+ lsh->type = 0;
+
+ return dhd_sendpkt(pub, 0, p);
+}
+#endif /* !SEND_HCI_CMD_VIA_IOCTL */
+
+/* Send HCI ACL data to dongle via data channel */
+int
+dhd_bta_tx_hcidata(dhd_pub_t *pub, void *data_buf, uint data_len)
+{
+ amp_hci_ACL_data_t *data = (amp_hci_ACL_data_t *)data_buf;
+ struct ether_header *eh;
+ struct dot11_llc_snap_header *lsh;
+ osl_t *osh = pub->osh;
+ uint len;
+ void *p;
+
+ if (data_len < HCI_ACL_DATA_PREAMBLE_SIZE) {
+ DHD_ERROR(("dhd_bta_tx_hcidata: short data_buf, data_len %u\n", data_len));
+ return BCME_BADLEN;
+ }
+
+ if ((len = (uint)ltoh16(data->dlen) + HCI_ACL_DATA_PREAMBLE_SIZE) > data_len) {
+ DHD_ERROR(("dhd_bta_tx_hcidata: malformed hci data, len %u data_len %u\n",
+ len, data_len));
+ /* return BCME_BADLEN; */
+ }
+
+ p = PKTGET(osh, pub->hdrlen + RFC1042_HDR_LEN + len, TRUE);
+ if (p == NULL) {
+ DHD_ERROR(("dhd_bta_tx_hcidata: out of memory\n"));
+ return BCME_NOMEM;
+ }
+
+
+ /* copy in HCI ACL data header and HCI ACL data */
+ PKTPULL(osh, p, pub->hdrlen + RFC1042_HDR_LEN);
+ bcopy(data, PKTDATA(osh, p), len);
+
+ /* copy in partial Ethernet header with BT-SIG LLC/SNAP header */
+ PKTPUSH(osh, p, RFC1042_HDR_LEN);
+ eh = (struct ether_header *)PKTDATA(osh, p);
+ bzero(eh->ether_dhost, ETHER_ADDR_LEN);
+ bcopy(&pub->mac, eh->ether_shost, ETHER_ADDR_LEN);
+ eh->ether_type = hton16(len + DOT11_LLC_SNAP_HDR_LEN);
+ lsh = (struct dot11_llc_snap_header *)&eh[1];
+ bcopy(BT_SIG_SNAP_MPROT, lsh, DOT11_LLC_SNAP_HDR_LEN - 2);
+ lsh->type = HTON16(BTA_PROT_L2CAP);
+
+ return dhd_sendpkt(pub, 0, p);
+}
+
+/* txcomplete callback */
+void
+dhd_bta_tx_hcidata_complete(dhd_pub_t *dhdp, void *txp, bool success)
+{
+ uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, txp);
+ amp_hci_ACL_data_t *ACL_data = (amp_hci_ACL_data_t *)(pktdata + RFC1042_HDR_LEN);
+ uint16 handle = ltoh16(ACL_data->handle);
+ uint16 llh = HCI_ACL_DATA_HANDLE(handle);
+
+ wl_event_msg_t event;
+ uint8 data[HCI_EVT_PREAMBLE_SIZE + sizeof(num_completed_data_blocks_evt_parms_t)];
+ amp_hci_event_t *evt;
+ num_completed_data_blocks_evt_parms_t *parms;
+
+ uint16 len = HCI_EVT_PREAMBLE_SIZE + sizeof(num_completed_data_blocks_evt_parms_t);
+
+ /* update the event struct */
+ memset(&event, 0, sizeof(event));
+ event.version = hton16(BCM_EVENT_MSG_VERSION);
+ event.event_type = hton32(WLC_E_BTA_HCI_EVENT);
+ event.status = 0;
+ event.reason = 0;
+ event.auth_type = 0;
+ event.datalen = hton32(len);
+ event.flags = 0;
+
+ /* generate Number of Completed Blocks event */
+ evt = (amp_hci_event_t *)data;
+ evt->ecode = HCI_Number_of_Completed_Data_Blocks;
+ evt->plen = sizeof(num_completed_data_blocks_evt_parms_t);
+
+ parms = (num_completed_data_blocks_evt_parms_t *)evt->parms;
+ htol16_ua_store(dhdp->maxdatablks, (uint8 *)&parms->num_blocks);
+ parms->num_handles = 1;
+ htol16_ua_store(llh, (uint8 *)&parms->completed[0].handle);
+ parms->completed[0].pkts = 1;
+ parms->completed[0].blocks = 1;
+
+ dhd_sendup_event_common(dhdp, &event, data);
+}
+
+/* event callback */
+void
+dhd_bta_doevt(dhd_pub_t *dhdp, void *data_buf, uint data_len)
+{
+ amp_hci_event_t *evt = (amp_hci_event_t *)data_buf;
+
+ ASSERT(dhdp);
+ ASSERT(evt);
+
+ switch (evt->ecode) {
+ case HCI_Command_Complete: {
+ cmd_complete_parms_t *parms = (cmd_complete_parms_t *)evt->parms;
+ switch (ltoh16_ua((uint8 *)&parms->opcode)) {
+ case HCI_Read_Data_Block_Size: {
+ read_data_block_size_evt_parms_t *parms2 =
+ (read_data_block_size_evt_parms_t *)parms->parms;
+ dhdp->maxdatablks = ltoh16_ua((uint8 *)&parms2->data_block_num);
+ break;
+ }
+ }
+ break;
+ }
+
+ case HCI_Flush_Occurred: {
+ flush_occurred_evt_parms_t *evt_parms = (flush_occurred_evt_parms_t *)evt->parms;
+ dhd_bta_flush_hcidata(dhdp, ltoh16_ua((uint8 *)&evt_parms->handle));
+ break;
+ }
+ default:
+ break;
+ }
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_bta.h b/drivers/net/wireless/bcmdhd/dhd_bta.h
new file mode 100644
index 000000000000..2f93802adb3d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_bta.h
@@ -0,0 +1,39 @@
+/*
+ * BT-AMP support routines
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_bta.h 291086 2011-10-21 01:17:24Z $
+ */
+#ifndef __dhd_bta_h__
+#define __dhd_bta_h__
+
+struct dhd_pub;
+
+extern int dhd_bta_docmd(struct dhd_pub *pub, void *cmd_buf, uint cmd_len);
+
+extern void dhd_bta_doevt(struct dhd_pub *pub, void *data_buf, uint data_len);
+
+extern int dhd_bta_tx_hcidata(struct dhd_pub *pub, void *data_buf, uint data_len);
+extern void dhd_bta_tx_hcidata_complete(struct dhd_pub *dhdp, void *txp, bool success);
+
+
+#endif /* __dhd_bta_h__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_bus.h b/drivers/net/wireless/bcmdhd/dhd_bus.h
new file mode 100644
index 000000000000..f47e916813b6
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_bus.h
@@ -0,0 +1,158 @@
+/*
+ * Header file describing the internal (inter-module) DHD interfaces.
+ *
+ * Provides type definitions and function prototypes used to link the
+ * DHD OS, bus, and protocol modules.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_bus.h 457888 2014-02-25 03:34:39Z $
+ */
+
+#ifndef _dhd_bus_h_
+#define _dhd_bus_h_
+
+/*
+ * Exported from dhd bus module (dhd_usb, dhd_sdio)
+ */
+
+/* Indicate (dis)interest in finding dongles. */
+extern int dhd_bus_register(void);
+extern void dhd_bus_unregister(void);
+
+/* Download firmware image and nvram image */
+extern int dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, char *fw_path, char *nv_path);
+
+/* Stop bus module: clear pending frames, disable data flow */
+extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
+
+/* Initialize bus module: prepare for communication w/dongle */
+extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex);
+
+/* Get the Bus Idle Time */
+extern void dhd_bus_getidletime(dhd_pub_t *dhdp, int *idletime);
+
+/* Set the Bus Idle Time */
+extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time);
+
+/* Send a data frame to the dongle. Callee disposes of txp. */
+#ifdef BCMPCIE
+extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp, uint8 ifidx);
+#else
+extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp);
+#endif
+
+
+/* Send/receive a control message to/from the dongle.
+ * Expects caller to enforce a single outstanding transaction.
+ */
+extern int dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen);
+extern int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen);
+
+/* Watchdog timer function */
+extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
+
+extern int dhd_bus_oob_intr_register(dhd_pub_t *dhdp);
+extern void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp);
+extern void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable);
+extern void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub);
+extern void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub);
+extern bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub);
+
+#if defined(DHD_DEBUG)
+/* Device console input function */
+extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen);
+#endif /* defined(DHD_DEBUG) */
+
+/* Deferred processing for the bus, return TRUE requests reschedule */
+extern bool dhd_bus_dpc(struct dhd_bus *bus);
+extern void dhd_bus_isr(bool * InterruptRecognized, bool * QueueMiniportHandleInterrupt, void *arg);
+
+
+/* Check for and handle local prot-specific iovar commands */
+extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+ void *params, int plen, void *arg, int len, bool set);
+
+/* Add bus dump output to a buffer */
+extern void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+
+/* Clear any bus counters */
+extern void dhd_bus_clearcounts(dhd_pub_t *dhdp);
+
+/* return the dongle chipid */
+extern uint dhd_bus_chip(struct dhd_bus *bus);
+
+/* return the dongle chiprev */
+extern uint dhd_bus_chiprev(struct dhd_bus *bus);
+
+/* Set user-specified nvram parameters. */
+extern void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params);
+
+extern void *dhd_bus_pub(struct dhd_bus *bus);
+extern void *dhd_bus_txq(struct dhd_bus *bus);
+extern void *dhd_bus_sih(struct dhd_bus *bus);
+extern uint dhd_bus_hdrlen(struct dhd_bus *bus);
+extern void dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val);
+
+#define DHD_SET_BUS_STATE_DOWN(_bus) do { \
+ (_bus)->dhd->busstate = DHD_BUS_DOWN; \
+} while (0)
+
+/* Register a dummy SDIO client driver in order to be notified of new SDIO device */
+extern int dhd_bus_reg_sdio_notify(void* semaphore);
+extern void dhd_bus_unreg_sdio_notify(void);
+extern void dhd_txglom_enable(dhd_pub_t *dhdp, bool enable);
+extern int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num,
+ uint32 *slot_num);
+
+#ifdef BCMPCIE
+enum {
+ DNGL_TO_HOST_BUF_IOCT,
+ DNGL_TO_HOST_BUF_ADDR,
+ HOST_TO_DNGL_BUF_ADDR,
+ HOST_TO_DNGL_WPTR,
+ HOST_TO_DNGL_RPTR,
+ DNGL_TO_HOST_WPTR,
+ DNGL_TO_HOST_RPTR,
+ TOTAL_LFRAG_PACKET_CNT,
+ HOST_TO_DNGL_CTRLBUF_ADDR,
+ DNGL_TO_HOST_CTRLBUF_ADDR,
+ HTOD_CTRL_RPTR,
+ HTOD_CTRL_WPTR,
+ DTOH_CTRL_RPTR,
+ DTOH_CTRL_WPTR,
+ HTOD_MB_DATA,
+ DTOH_MB_DATA,
+ MAX_HOST_RXBUFS
+};
+typedef void (*dhd_mb_ring_t) (struct dhd_bus *, uint32);
+extern void dhd_bus_cmn_writeshared(struct dhd_bus *bus, void * data, uint32 len, uint8 type);
+extern void dhd_bus_ringbell(struct dhd_bus *bus, uint32 value);
+extern void dhd_bus_cmn_readshared(struct dhd_bus *bus, void* data, uint8 type);
+extern uint32 dhd_bus_get_sharedflags(struct dhd_bus *bus);
+extern void dhd_bus_rx_frame(struct dhd_bus *bus, void* pkt, int ifidx, uint pkt_count);
+extern void dhd_bus_start_queue(struct dhd_bus *bus);
+extern void dhd_bus_stop_queue(struct dhd_bus *bus);
+extern void dhd_bus_update_retlen(struct dhd_bus *bus, uint32 retlen, uint32 cmd_id, uint32 status,
+ uint32 inline_data);
+extern dhd_mb_ring_t dhd_bus_get_mbintr_fn(struct dhd_bus *bus);
+#endif /* BCMPCIE */
+#endif /* _dhd_bus_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c
new file mode 100644
index 000000000000..c776089b04c6
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c
@@ -0,0 +1,789 @@
+/*
+ * DHD Protocol Module for CDC and BDC.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_cdc.c 657232 2016-08-31 11:02:44Z $
+ *
+ * BDC is like CDC, except it includes a header for data packets to convey
+ * packet priority over the bus, and flags (e.g. to indicate checksum status
+ * for dongle offload.)
+ */
+
+#include <typedefs.h>
+#include <osl.h>
+
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include <bcmendian.h>
+
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_proto.h>
+#include <dhd_bus.h>
+#include <dhd_dbg.h>
+
+
+#ifdef PROP_TXSTATUS
+#include <wlfc_proto.h>
+#include <dhd_wlfc.h>
+#endif
+
+
+#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
+#define BUS_HEADER_LEN (24+DHD_SDALIGN) /* Must be at least SDPCM_RESERVE
+ * defined in dhd_sdio.c (amount of header tha might be added)
+ * plus any space that might be needed for alignment padding.
+ */
+#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for
+ * round off at the end of buffer
+ */
+
+typedef struct dhd_prot {
+ uint16 reqid;
+ uint8 pending;
+ uint32 lastcmd;
+ uint8 bus_header[BUS_HEADER_LEN];
+ cdc_ioctl_t msg;
+ unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
+} dhd_prot_t;
+
+
+static int
+dhdcdc_msg(dhd_pub_t *dhd)
+{
+ int err = 0;
+ dhd_prot_t *prot = dhd->prot;
+ int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t);
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ DHD_OS_WAKE_LOCK(dhd);
+
+ /* NOTE : cdc->msg.len holds the desired length of the buffer to be
+ * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
+ * is actually sent to the dongle
+ */
+ if (len > CDC_MAX_MSG_SIZE)
+ len = CDC_MAX_MSG_SIZE;
+
+ /* Send request */
+ err = dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len);
+
+ DHD_OS_WAKE_UNLOCK(dhd);
+ return err;
+}
+
+static int
+dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len)
+{
+ int ret;
+ int cdc_len = len + sizeof(cdc_ioctl_t);
+ dhd_prot_t *prot = dhd->prot;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+
+ do {
+ ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, cdc_len);
+ if (ret < 0)
+ break;
+ } while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id);
+
+
+ return ret;
+}
+
+static int
+dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
+{
+ dhd_prot_t *prot = dhd->prot;
+ cdc_ioctl_t *msg = &prot->msg;
+ int ret = 0, retries = 0;
+ uint32 id, flags = 0;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
+
+
+ /* Respond "bcmerror" and "bcmerrorstr" with local cache */
+ if (cmd == WLC_GET_VAR && buf)
+ {
+ if (!strcmp((char *)buf, "bcmerrorstr"))
+ {
+ strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN);
+ goto done;
+ }
+ else if (!strcmp((char *)buf, "bcmerror"))
+ {
+ *(int *)buf = dhd->dongle_error;
+ goto done;
+ }
+ }
+
+ memset(msg, 0, sizeof(cdc_ioctl_t));
+
+ msg->cmd = htol32(cmd);
+ msg->len = htol32(len);
+ msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
+ CDC_SET_IF_IDX(msg, ifidx);
+ /* add additional action bits */
+ action &= WL_IOCTL_ACTION_MASK;
+ msg->flags |= (action << CDCF_IOC_ACTION_SHIFT);
+ msg->flags = htol32(msg->flags);
+
+ if (buf)
+ memcpy(prot->buf, buf, len);
+
+ if ((ret = dhdcdc_msg(dhd)) < 0) {
+ if (!dhd->hang_was_sent)
+ DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret));
+ goto done;
+ }
+
+retry:
+ /* wait for interrupt and get first fragment */
+ if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0)
+ goto done;
+
+ flags = ltoh32(msg->flags);
+ id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
+
+ if ((id < prot->reqid) && (++retries < RETRIES))
+ goto retry;
+ if (id != prot->reqid) {
+ DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
+ dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid));
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* Copy info buffer */
+ if (buf)
+ {
+ if (ret < (int)len)
+ len = ret;
+ memcpy(buf, (void*) prot->buf, len);
+ }
+
+ /* Check the ERROR flag */
+ if (flags & CDCF_IOC_ERROR)
+ {
+ ret = ltoh32(msg->status);
+ /* Cache error from dongle */
+ dhd->dongle_error = ret;
+ }
+
+done:
+ return ret;
+}
+
+
+static int
+dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
+{
+ dhd_prot_t *prot = dhd->prot;
+ cdc_ioctl_t *msg = &prot->msg;
+ int ret = 0;
+ uint32 flags, id;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
+
+ if (dhd->busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
+ return -EIO;
+ }
+
+ /* don't talk to the dongle if fw is about to be reloaded */
+ if (dhd->hang_was_sent) {
+ DHD_ERROR(("%s: HANG was sent up earlier. Not talking to the chip\n",
+ __FUNCTION__));
+ return -EIO;
+ }
+
+ memset(msg, 0, sizeof(cdc_ioctl_t));
+
+ msg->cmd = htol32(cmd);
+ msg->len = htol32(len);
+ msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
+ CDC_SET_IF_IDX(msg, ifidx);
+ /* add additional action bits */
+ action &= WL_IOCTL_ACTION_MASK;
+ msg->flags |= (action << CDCF_IOC_ACTION_SHIFT) | CDCF_IOC_SET;
+ msg->flags = htol32(msg->flags);
+
+ if (buf)
+ memcpy(prot->buf, buf, len);
+
+ if ((ret = dhdcdc_msg(dhd)) < 0) {
+ DHD_ERROR(("%s: dhdcdc_msg failed w/status %d\n", __FUNCTION__, ret));
+ goto done;
+ }
+
+ if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0)
+ goto done;
+
+ flags = ltoh32(msg->flags);
+ id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
+
+ if (id != prot->reqid) {
+ DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
+ dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid));
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* Check the ERROR flag */
+ if (flags & CDCF_IOC_ERROR)
+ {
+ ret = ltoh32(msg->status);
+ /* Cache error from dongle */
+ dhd->dongle_error = ret;
+ }
+
+done:
+ return ret;
+}
+
+
+int
+dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
+{
+ dhd_prot_t *prot = dhd->prot;
+ int ret = -1;
+ uint8 action;
+
+ if ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent) {
+ DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
+ goto done;
+ }
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ASSERT(len <= WLC_IOCTL_MAXLEN);
+
+ if (len > WLC_IOCTL_MAXLEN)
+ goto done;
+
+ if (prot->pending == TRUE) {
+ DHD_ERROR(("CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n",
+ ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
+ (unsigned long)prot->lastcmd));
+ if ((ioc->cmd == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR)) {
+ DHD_TRACE(("iovar cmd=%s\n", (char*)buf));
+ }
+ goto done;
+ }
+
+ prot->pending = TRUE;
+ prot->lastcmd = ioc->cmd;
+ action = ioc->set;
+ if (action & WL_IOCTL_ACTION_SET)
+ ret = dhdcdc_set_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
+ else {
+ ret = dhdcdc_query_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
+ if (ret > 0)
+ ioc->used = ret - sizeof(cdc_ioctl_t);
+ }
+
+ /* Too many programs assume ioctl() returns 0 on success */
+ if (ret >= 0)
+ ret = 0;
+ else {
+ cdc_ioctl_t *msg = &prot->msg;
+ ioc->needed = ltoh32(msg->len); /* len == needed when set/query fails from dongle */
+ }
+
+ /* Intercept the wme_dp ioctl here */
+ if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) {
+ int slen, val = 0;
+
+ slen = strlen("wme_dp") + 1;
+ if (len >= (int)(slen + sizeof(int)))
+ bcopy(((char *)buf + slen), &val, sizeof(int));
+ dhd->wme_dp = (uint8) ltoh32(val);
+ }
+
+ prot->pending = FALSE;
+
+done:
+
+ return ret;
+}
+
+int
+dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
+{
+ return BCME_UNSUPPORTED;
+}
+
+void
+dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+{
+ if (!dhdp || !dhdp->prot)
+ return;
+
+ bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid);
+#ifdef PROP_TXSTATUS
+ dhd_wlfc_dump(dhdp, strbuf);
+#endif
+}
+
+/* The FreeBSD PKTPUSH could change the packet buf pinter
+ so we need to make it changable
+*/
+#define PKTBUF pktbuf
+void
+dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *PKTBUF)
+{
+#ifdef BDC
+ struct bdc_header *h;
+#endif /* BDC */
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+#ifdef BDC
+ /* Push BDC header used to convey priority for buses that don't */
+
+ PKTPUSH(dhd->osh, PKTBUF, BDC_HEADER_LEN);
+
+ h = (struct bdc_header *)PKTDATA(dhd->osh, PKTBUF);
+
+ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
+ if (PKTSUMNEEDED(PKTBUF))
+ h->flags |= BDC_FLAG_SUM_NEEDED;
+
+
+ h->priority = (PKTPRIO(PKTBUF) & BDC_PRIORITY_MASK);
+ h->flags2 = 0;
+ h->dataOffset = 0;
+#endif /* BDC */
+ BDC_SET_IF_IDX(h, ifidx);
+}
+#undef PKTBUF /* Only defined in the above routine */
+
+int
+dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_info,
+ uint *reorder_info_len)
+{
+#ifdef BDC
+ struct bdc_header *h;
+#endif
+ uint8 data_offset = 0;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+#ifdef BDC
+ if (reorder_info_len)
+ *reorder_info_len = 0;
+ /* Pop BDC header used to convey priority for buses that don't */
+
+ if (PKTLEN(dhd->osh, pktbuf) < BDC_HEADER_LEN) {
+ DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
+ PKTLEN(dhd->osh, pktbuf), BDC_HEADER_LEN));
+ return BCME_ERROR;
+ }
+
+ h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf);
+
+ if (!ifidx) {
+ /* for tx packet, skip the analysis */
+ data_offset = h->dataOffset;
+ PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN);
+ goto exit;
+ }
+
+ *ifidx = BDC_GET_IF_IDX(h);
+
+ if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != BDC_PROTO_VER) {
+ DHD_ERROR(("%s: non-BDC packet received, flags = 0x%x\n",
+ dhd_ifname(dhd, *ifidx), h->flags));
+ if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) == BDC_PROTO_VER_1)
+ h->dataOffset = 0;
+ else
+ return BCME_ERROR;
+ }
+
+ if (h->flags & BDC_FLAG_SUM_GOOD) {
+ DHD_INFO(("%s: BDC packet received with good rx-csum, flags 0x%x\n",
+ dhd_ifname(dhd, *ifidx), h->flags));
+ PKTSETSUMGOOD(pktbuf, TRUE);
+ }
+
+ PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK));
+ data_offset = h->dataOffset;
+ PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN);
+#endif /* BDC */
+
+
+#ifdef PROP_TXSTATUS
+ if (!DHD_PKTTAG_PKTDIR(PKTTAG(pktbuf))) {
+ /*
+ - parse txstatus only for packets that came from the firmware
+ */
+ dhd_wlfc_parse_header_info(dhd, pktbuf, (data_offset << 2),
+ reorder_buf_info, reorder_info_len);
+
+ }
+#endif /* PROP_TXSTATUS */
+
+exit:
+ PKTPULL(dhd->osh, pktbuf, (data_offset << 2));
+ return 0;
+}
+
+
+int
+dhd_prot_attach(dhd_pub_t *dhd)
+{
+ dhd_prot_t *cdc;
+
+ if (!(cdc = (dhd_prot_t *)DHD_OS_PREALLOC(dhd, DHD_PREALLOC_PROT, sizeof(dhd_prot_t)))) {
+ DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+ goto fail;
+ }
+ memset(cdc, 0, sizeof(dhd_prot_t));
+
+ /* ensure that the msg buf directly follows the cdc msg struct */
+ if ((uintptr)(&cdc->msg + 1) != (uintptr)cdc->buf) {
+ DHD_ERROR(("dhd_prot_t is not correctly defined\n"));
+ goto fail;
+ }
+
+ dhd->prot = cdc;
+#ifdef BDC
+ dhd->hdrlen += BDC_HEADER_LEN;
+#endif
+ dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN;
+ return 0;
+
+fail:
+ if (cdc != NULL) {
+ DHD_OS_PREFREE(dhd, DHD_PREALLOC_PROT, cdc, sizeof(dhd_prot_t));
+ }
+ return BCME_NOMEM;
+}
+
+/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */
+void
+dhd_prot_detach(dhd_pub_t *dhd)
+{
+#ifdef PROP_TXSTATUS
+ dhd_wlfc_deinit(dhd);
+#endif
+ DHD_OS_PREFREE(dhd, DHD_PREALLOC_PROT, dhd->prot, sizeof(dhd_prot_t));
+ dhd->prot = NULL;
+}
+
+void
+dhd_prot_dstats(dhd_pub_t *dhd)
+{
+/* No stats from dongle added yet, copy bus stats */
+ dhd->dstats.tx_packets = dhd->tx_packets;
+ dhd->dstats.tx_errors = dhd->tx_errors;
+ dhd->dstats.rx_packets = dhd->rx_packets;
+ dhd->dstats.rx_errors = dhd->rx_errors;
+ dhd->dstats.rx_dropped = dhd->rx_dropped;
+ dhd->dstats.multicast = dhd->rx_multicast;
+ return;
+}
+
+int
+dhd_prot_init(dhd_pub_t *dhd)
+{
+ int ret = 0;
+ wlc_rev_info_t revinfo;
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+
+ /* Get the device rev info */
+ memset(&revinfo, 0, sizeof(revinfo));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
+ if (ret < 0)
+ goto done;
+
+
+ ret = dhd_preinit_ioctls(dhd);
+
+ /* Always assumes wl for now */
+ dhd->iswl = TRUE;
+
+done:
+ return ret;
+}
+
+void
+dhd_prot_stop(dhd_pub_t *dhd)
+{
+/* Nothing to do for CDC */
+}
+
+
+static void
+dhd_get_hostreorder_pkts(void *osh, struct reorder_info *ptr, void **pkt,
+ uint32 *pkt_count, void **pplast, uint8 start, uint8 end)
+{
+ void *plast = NULL, *p;
+ uint32 pkt_cnt = 0;
+
+ if (ptr->pend_pkts == 0) {
+ DHD_REORDER(("%s: no packets in reorder queue \n", __FUNCTION__));
+ *pplast = NULL;
+ *pkt_count = 0;
+ *pkt = NULL;
+ return;
+ }
+ do {
+ p = (void *)(ptr->p[start]);
+ ptr->p[start] = NULL;
+
+ if (p != NULL) {
+ if (plast == NULL)
+ *pkt = p;
+ else
+ PKTSETNEXT(osh, plast, p);
+
+ plast = p;
+ pkt_cnt++;
+ }
+ start++;
+ if (start > ptr->max_idx)
+ start = 0;
+ } while (start != end);
+ *pplast = plast;
+ *pkt_count = pkt_cnt;
+ ptr->pend_pkts -= (uint8)pkt_cnt;
+}
+
+int
+dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len,
+ void **pkt, uint32 *pkt_count)
+{
+ uint8 flow_id, max_idx, cur_idx, exp_idx;
+ struct reorder_info *ptr;
+ uint8 flags;
+ void *cur_pkt, *plast = NULL;
+ uint32 cnt = 0;
+
+ if (pkt == NULL) {
+ if (pkt_count != NULL)
+ *pkt_count = 0;
+ return 0;
+ }
+
+ flow_id = reorder_info_buf[WLHOST_REORDERDATA_FLOWID_OFFSET];
+ flags = reorder_info_buf[WLHOST_REORDERDATA_FLAGS_OFFSET];
+
+ DHD_REORDER(("flow_id %d, flags 0x%02x, idx(%d, %d, %d)\n", flow_id, flags,
+ reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET],
+ reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET],
+ reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET]));
+
+ /* validate flags and flow id */
+ if (flags == 0xFF) {
+ DHD_ERROR(("%s: invalid flags...so ignore this packet\n", __FUNCTION__));
+ *pkt_count = 1;
+ return 0;
+ }
+
+ cur_pkt = *pkt;
+ *pkt = NULL;
+
+ ptr = dhd->reorder_bufs[flow_id];
+ if (flags & WLHOST_REORDERDATA_DEL_FLOW) {
+ uint32 buf_size = sizeof(struct reorder_info);
+
+ DHD_REORDER(("%s: Flags indicating to delete a flow id %d\n",
+ __FUNCTION__, flow_id));
+
+ if (ptr == NULL) {
+ DHD_REORDER(("%s: received flags to cleanup, but no flow (%d) yet\n",
+ __FUNCTION__, flow_id));
+ *pkt_count = 1;
+ *pkt = cur_pkt;
+ return 0;
+ }
+
+ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
+ ptr->exp_idx, ptr->exp_idx);
+ /* set it to the last packet */
+ if (plast) {
+ PKTSETNEXT(dhd->osh, plast, cur_pkt);
+ cnt++;
+ }
+ else {
+ if (cnt != 0) {
+ DHD_ERROR(("%s: del flow: something fishy, pending packets %d\n",
+ __FUNCTION__, cnt));
+ }
+ *pkt = cur_pkt;
+ cnt = 1;
+ }
+ buf_size += ((ptr->max_idx + 1) * sizeof(void *));
+ MFREE(dhd->osh, ptr, buf_size);
+ dhd->reorder_bufs[flow_id] = NULL;
+ *pkt_count = cnt;
+ return 0;
+ }
+ /* all the other cases depend on the existance of the reorder struct for that flow id */
+ if (ptr == NULL) {
+ uint32 buf_size_alloc = sizeof(reorder_info_t);
+ max_idx = reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET];
+
+ buf_size_alloc += ((max_idx + 1) * sizeof(void*));
+ /* allocate space to hold the buffers, index etc */
+
+ DHD_REORDER(("%s: alloc buffer of size %d size, reorder info id %d, maxidx %d\n",
+ __FUNCTION__, buf_size_alloc, flow_id, max_idx));
+ ptr = (struct reorder_info *)MALLOC(dhd->osh, buf_size_alloc);
+ if (ptr == NULL) {
+ DHD_ERROR(("%s: Malloc failed to alloc buffer\n", __FUNCTION__));
+ *pkt_count = 1;
+ return 0;
+ }
+ bzero(ptr, buf_size_alloc);
+ dhd->reorder_bufs[flow_id] = ptr;
+ ptr->p = (void *)(ptr+1);
+ ptr->max_idx = max_idx;
+ }
+ if (flags & WLHOST_REORDERDATA_NEW_HOLE) {
+ DHD_REORDER(("%s: new hole, so cleanup pending buffers\n", __FUNCTION__));
+ if (ptr->pend_pkts) {
+ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
+ ptr->exp_idx, ptr->exp_idx);
+ ptr->pend_pkts = 0;
+ }
+ ptr->cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET];
+ ptr->exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET];
+ ptr->max_idx = reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET];
+ ptr->p[ptr->cur_idx] = cur_pkt;
+ ptr->pend_pkts++;
+ *pkt_count = cnt;
+ }
+ else if (flags & WLHOST_REORDERDATA_CURIDX_VALID) {
+ cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET];
+ exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET];
+
+
+ if ((exp_idx == ptr->exp_idx) && (cur_idx != ptr->exp_idx)) {
+ /* still in the current hole */
+ /* enqueue the current on the buffer chain */
+ if (ptr->p[cur_idx] != NULL) {
+ DHD_REORDER(("%s: HOLE: ERROR buffer pending..free it\n",
+ __FUNCTION__));
+ PKTFREE(dhd->osh, ptr->p[cur_idx], TRUE);
+ ptr->p[cur_idx] = NULL;
+ }
+ ptr->p[cur_idx] = cur_pkt;
+ ptr->pend_pkts++;
+ ptr->cur_idx = cur_idx;
+ DHD_REORDER(("%s: fill up a hole..pending packets is %d\n",
+ __FUNCTION__, ptr->pend_pkts));
+ *pkt_count = 0;
+ *pkt = NULL;
+ }
+ else if (ptr->exp_idx == cur_idx) {
+ /* got the right one ..flush from cur to exp and update exp */
+ DHD_REORDER(("%s: got the right one now, cur_idx is %d\n",
+ __FUNCTION__, cur_idx));
+ if (ptr->p[cur_idx] != NULL) {
+ DHD_REORDER(("%s: Error buffer pending..free it\n",
+ __FUNCTION__));
+ PKTFREE(dhd->osh, ptr->p[cur_idx], TRUE);
+ ptr->p[cur_idx] = NULL;
+ }
+ ptr->p[cur_idx] = cur_pkt;
+ ptr->pend_pkts++;
+
+ ptr->cur_idx = cur_idx;
+ ptr->exp_idx = exp_idx;
+
+ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
+ cur_idx, exp_idx);
+ *pkt_count = cnt;
+ DHD_REORDER(("%s: freeing up buffers %d, still pending %d\n",
+ __FUNCTION__, cnt, ptr->pend_pkts));
+ }
+ else {
+ uint8 end_idx;
+ bool flush_current = FALSE;
+ /* both cur and exp are moved now .. */
+ DHD_REORDER(("%s:, flow %d, both moved, cur %d(%d), exp %d(%d)\n",
+ __FUNCTION__, flow_id, ptr->cur_idx, cur_idx,
+ ptr->exp_idx, exp_idx));
+ if (flags & WLHOST_REORDERDATA_FLUSH_ALL)
+ end_idx = ptr->exp_idx;
+ else
+ end_idx = exp_idx;
+
+ /* flush pkts first */
+ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
+ ptr->exp_idx, end_idx);
+
+ if (cur_idx == ptr->max_idx) {
+ if (exp_idx == 0)
+ flush_current = TRUE;
+ } else {
+ if (exp_idx == cur_idx + 1)
+ flush_current = TRUE;
+ }
+ if (flush_current) {
+ if (plast)
+ PKTSETNEXT(dhd->osh, plast, cur_pkt);
+ else
+ *pkt = cur_pkt;
+ cnt++;
+ }
+ else {
+ ptr->p[cur_idx] = cur_pkt;
+ ptr->pend_pkts++;
+ }
+ ptr->exp_idx = exp_idx;
+ ptr->cur_idx = cur_idx;
+ *pkt_count = cnt;
+ }
+ }
+ else {
+ uint8 end_idx;
+ /* no real packet but update to exp_seq...that means explicit window move */
+ exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET];
+
+ DHD_REORDER(("%s: move the window, cur_idx is %d, exp is %d, new exp is %d\n",
+ __FUNCTION__, ptr->cur_idx, ptr->exp_idx, exp_idx));
+ if (flags & WLHOST_REORDERDATA_FLUSH_ALL)
+ end_idx = ptr->exp_idx;
+ else
+ end_idx = exp_idx;
+
+ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, ptr->exp_idx, end_idx);
+ if (plast)
+ PKTSETNEXT(dhd->osh, plast, cur_pkt);
+ else
+ *pkt = cur_pkt;
+ cnt++;
+ *pkt_count = cnt;
+ /* set the new expected idx */
+ ptr->exp_idx = exp_idx;
+ }
+ return 0;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
new file mode 100644
index 000000000000..17e68663df6a
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
@@ -0,0 +1,301 @@
+/*
+ * Linux cfg80211 driver - Dongle Host Driver (DHD) related
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $
+ */
+
+#include <linux/vmalloc.h>
+#include <net/rtnetlink.h>
+
+#include <bcmutils.h>
+#include <wldev_common.h>
+#include <wl_cfg80211.h>
+#include <brcm_nl80211.h>
+#include <dhd_cfg80211.h>
+
+#ifdef PKT_FILTER_SUPPORT
+#include <dngl_stats.h>
+#include <dhd.h>
+#endif
+extern struct bcm_cfg80211 *g_bcm_cfg;
+
+#ifdef PKT_FILTER_SUPPORT
+extern uint dhd_pkt_filter_enable;
+extern uint dhd_master_mode;
+extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
+#endif
+
+static int dhd_dongle_up = FALSE;
+
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhdioctl.h>
+#include <wlioctl.h>
+#include <dhd_cfg80211.h>
+
+static s32 wl_dongle_up(struct net_device *ndev, u32 up);
+
+/**
+ * Function implementations
+ */
+
+s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg)
+{
+ dhd_dongle_up = FALSE;
+ return 0;
+}
+
+s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg)
+{
+ dhd_dongle_up = FALSE;
+ return 0;
+}
+
+s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg)
+{
+ dhd_dongle_up = FALSE;
+ return 0;
+}
+
+s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ dhd->op_mode |= val;
+ WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode));
+#ifdef ARP_OFFLOAD_SUPPORT
+ if (dhd->arp_version == 1) {
+ /* IF P2P is enabled, disable arpoe */
+ dhd_arp_offload_set(dhd, 0);
+ dhd_arp_offload_enable(dhd, false);
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+ return 0;
+}
+
+s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE);
+ WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode));
+
+#ifdef ARP_OFFLOAD_SUPPORT
+ if (dhd->arp_version == 1) {
+ /* IF P2P is disabled, enable arpoe back for STA mode. */
+ dhd_arp_offload_set(dhd, dhd_arp_mode);
+ dhd_arp_offload_enable(dhd, true);
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+ return 0;
+}
+
+struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
+ uint8 *mac, uint8 bssidx, char *dngl_name)
+{
+ return dhd_allocate_if(cfg->pub, ifidx, name, mac, bssidx, FALSE, dngl_name);
+}
+
+int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
+{
+ return dhd_register_if(cfg->pub, ifidx, FALSE);
+}
+
+int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
+{
+ return dhd_remove_if(cfg->pub, ifidx, FALSE);
+}
+
+struct net_device * dhd_cfg80211_netdev_free(struct net_device *ndev)
+{
+ if (ndev) {
+ if (ndev->ieee80211_ptr) {
+ kfree(ndev->ieee80211_ptr);
+ ndev->ieee80211_ptr = NULL;
+ }
+ free_netdev(ndev);
+ return NULL;
+ }
+
+ return ndev;
+}
+
+void dhd_netdev_free(struct net_device *ndev)
+{
+#ifdef WL_CFG80211
+ ndev = dhd_cfg80211_netdev_free(ndev);
+#endif
+ if (ndev)
+ free_netdev(ndev);
+}
+
+static s32 wl_dongle_up(struct net_device *ndev, u32 up)
+{
+ s32 err = 0;
+
+ err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_UP error (%d)\n", err));
+ }
+ return err;
+}
+
+s32 dhd_config_dongle(struct bcm_cfg80211 *cfg)
+{
+#ifndef DHD_SDALIGN
+#define DHD_SDALIGN 32
+#endif
+ struct net_device *ndev;
+ s32 err = 0;
+
+ WL_TRACE(("In\n"));
+ if (dhd_dongle_up) {
+ WL_ERR(("Dongle is already up\n"));
+ return err;
+ }
+
+ ndev = bcmcfg_to_prmry_ndev(cfg);
+
+ err = wl_dongle_up(ndev, 0);
+ if (unlikely(err)) {
+ WL_ERR(("wl_dongle_up failed\n"));
+ goto default_conf_out;
+ }
+ dhd_dongle_up = true;
+
+default_conf_out:
+
+ return err;
+
+}
+
+#ifdef CONFIG_NL80211_TESTMODE
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, void *data, int len)
+#else
+int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
+{
+ struct sk_buff *reply;
+ struct bcm_cfg80211 *cfg;
+ dhd_pub_t *dhd;
+ struct bcm_nlmsg_hdr *nlioc = data;
+ dhd_ioctl_t ioc = { 0 };
+ int err = 0;
+ void *buf = NULL, *cur;
+ u16 buflen;
+ u16 maxmsglen = PAGE_SIZE - 0x100;
+ bool newbuf = false;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+ int8 index = 0;
+ struct net_device *ndev = NULL;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
+
+ WL_TRACE(("entry: cmd = %d\n", nlioc->cmd));
+ cfg = wiphy_priv(wiphy);
+ dhd = cfg->pub;
+
+ DHD_OS_WAKE_LOCK(dhd);
+
+ /* send to dongle only if we are not waiting for reload already */
+ if (dhd->hang_was_sent) {
+ WL_ERR(("HANG was sent up earlier\n"));
+ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
+ DHD_OS_WAKE_UNLOCK(dhd);
+ return OSL_ERROR(BCME_DONGLE_DOWN);
+ }
+
+ len -= sizeof(struct bcm_nlmsg_hdr);
+
+ if (nlioc->len > 0) {
+ if (nlioc->len <= len) {
+ buf = (void *)nlioc + nlioc->offset;
+ *(char *)(buf + nlioc->len) = '\0';
+ } else {
+ if (nlioc->len > DHD_IOCTL_MAXLEN)
+ nlioc->len = DHD_IOCTL_MAXLEN;
+ buf = vzalloc(nlioc->len);
+ if (!buf)
+ return -ENOMEM;
+ newbuf = true;
+ memcpy(buf, (void *)nlioc + nlioc->offset, len);
+ *(char *)(buf + len) = '\0';
+ }
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+ ndev = wdev_to_wlc_ndev(wdev, cfg);
+ index = dhd_net2idx(dhd->info, ndev);
+ if (index == DHD_BAD_IF) {
+ WL_ERR(("Bad ifidx from wdev:%p\n", wdev));
+ return BCME_ERROR;
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
+
+ ioc.cmd = nlioc->cmd;
+ ioc.len = nlioc->len;
+ ioc.set = nlioc->set;
+ ioc.driver = nlioc->magic;
+ err = dhd_ioctl_process(dhd, 0, &ioc, buf);
+ if (err) {
+ WL_TRACE(("dhd_ioctl_process return err %d\n", err));
+ err = OSL_ERROR(err);
+ goto done;
+ }
+
+ cur = buf;
+ while (nlioc->len > 0) {
+ buflen = nlioc->len > maxmsglen ? maxmsglen : nlioc->len;
+ nlioc->len -= buflen;
+ reply = cfg80211_testmode_alloc_reply_skb(wiphy, buflen+4);
+ if (!reply) {
+ WL_ERR(("Failed to allocate reply msg\n"));
+ err = -ENOMEM;
+ break;
+ }
+
+ if (nla_put(reply, BCM_NLATTR_DATA, buflen, cur) ||
+ nla_put_u16(reply, BCM_NLATTR_LEN, buflen)) {
+ kfree_skb(reply);
+ err = -ENOBUFS;
+ break;
+ }
+
+ do {
+ err = cfg80211_testmode_reply(reply);
+ } while (err == -EAGAIN);
+ if (err) {
+ WL_ERR(("testmode reply failed:%d\n", err));
+ break;
+ }
+ cur += buflen;
+ }
+
+done:
+ if (newbuf)
+ vfree(buf);
+ DHD_OS_WAKE_UNLOCK(dhd);
+ return err;
+}
+#endif /* CONFIG_NL80211_TESTMODE */
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h
new file mode 100644
index 000000000000..f839700218e2
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h
@@ -0,0 +1,59 @@
+/*
+ * Linux cfg80211 driver - Dongle Host Driver (DHD) related
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $
+ */
+
+
+#ifndef __DHD_CFG80211__
+#define __DHD_CFG80211__
+
+#include <wl_cfg80211.h>
+#include <wl_cfgp2p.h>
+
+s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg);
+s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg);
+s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg);
+s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val);
+s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg);
+s32 dhd_config_dongle(struct bcm_cfg80211 *cfg);
+
+#ifdef CONFIG_NL80211_TESTMODE
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, void *data, int len);
+#else
+int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+static inline int
+dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, void *data, int len)
+#else
+static inline int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
+{
+ return 0;
+}
+#endif /* CONFIG_NL80211_TESTMODE */
+
+#endif /* __DHD_CFG80211__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
new file mode 100644
index 000000000000..c45b1e166375
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -0,0 +1,2640 @@
+/*
+ * Broadcom Dongle Host Driver (DHD), common DHD core.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_common.c 662961 2016-11-24 01:22:35Z $
+ */
+#include <typedefs.h>
+#include <osl.h>
+
+#include <epivers.h>
+#include <bcmutils.h>
+
+#include <bcmendian.h>
+#include <dngl_stats.h>
+#include <wlioctl.h>
+#include <dhd.h>
+#include <dhd_ip.h>
+
+#include <proto/bcmevent.h>
+
+#ifdef SHOW_LOGTRACE
+#include <event_log.h>
+#endif /* SHOW_LOGTRACE */
+
+#include <dhd_bus.h>
+#include <dhd_proto.h>
+#include <dhd_dbg.h>
+#include <msgtrace.h>
+
+#ifdef WL_CFG80211
+#include <wl_cfg80211.h>
+#endif
+#ifdef PNO_SUPPORT
+#include <dhd_pno.h>
+#endif
+#ifdef SET_RANDOM_MAC_SOFTAP
+#include <linux/random.h>
+#include <linux/jiffies.h>
+#endif
+
+#define htod32(i) (i)
+#define htod16(i) (i)
+#define dtoh32(i) (i)
+#define dtoh16(i) (i)
+#define htodchanspec(i) (i)
+#define dtohchanspec(i) (i)
+
+#ifdef PROP_TXSTATUS
+#include <wlfc_proto.h>
+#include <dhd_wlfc.h>
+#endif
+
+#ifdef WLMEDIA_HTSF
+extern void htsf_update(struct dhd_info *dhd, void *data);
+#endif
+int dhd_msg_level = DHD_ERROR_VAL;
+
+
+#include <wl_iw.h>
+
+#ifdef SOFTAP
+char fw_path2[MOD_PARAM_PATHLEN];
+extern bool softap_enabled;
+#endif
+
+/* Last connection success/failure status */
+uint32 dhd_conn_event;
+uint32 dhd_conn_status;
+uint32 dhd_conn_reason;
+
+extern int dhd_iscan_request(void * dhdp, uint16 action);
+extern void dhd_ind_scan_confirm(void *h, bool status);
+extern int dhd_iscan_in_progress(void *h);
+void dhd_iscan_lock(void);
+void dhd_iscan_unlock(void);
+extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx);
+#if !defined(AP) && defined(WLP2P)
+extern int dhd_get_concurrent_capabilites(dhd_pub_t *dhd);
+#endif
+bool ap_cfg_running = FALSE;
+bool ap_fw_loaded = FALSE;
+
+/* Version string to report */
+#ifdef DHD_DEBUG
+#ifndef SRCBASE
+#define SRCBASE "drivers/net/wireless/bcmdhd"
+#endif
+#define DHD_COMPILED "\nCompiled in " SRCBASE
+#endif /* DHD_DEBUG */
+
+#if defined(DHD_VERSION_NO_DATE_TIME)
+const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR DHD_COMPILED;
+#else
+#if defined(DHD_DEBUG)
+const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR
+ DHD_COMPILED " on " __DATE__ " at " __TIME__;
+#else
+const char dhd_version[] = "\nDongle Host Driver, version " EPI_VERSION_STR "\nCompiled from ";
+#endif
+#endif /* DHD_VERSION_NO_DATE_TIME */
+
+void dhd_set_timer(void *bus, uint wdtick);
+
+/* IOVar table */
+enum {
+ IOV_VERSION = 1,
+ IOV_MSGLEVEL,
+ IOV_BCMERRORSTR,
+ IOV_BCMERROR,
+ IOV_WDTICK,
+ IOV_DUMP,
+ IOV_CLEARCOUNTS,
+ IOV_LOGDUMP,
+ IOV_LOGCAL,
+ IOV_LOGSTAMP,
+ IOV_GPIOOB,
+ IOV_IOCTLTIMEOUT,
+#if defined(DHD_DEBUG)
+ IOV_CONS,
+ IOV_DCONSOLE_POLL,
+ IOV_DHD_JOIN_TIMEOUT_DBG,
+ IOV_SCAN_TIMEOUT,
+#endif /* defined(DHD_DEBUG) */
+#ifdef PROP_TXSTATUS
+ IOV_PROPTXSTATUS_ENABLE,
+ IOV_PROPTXSTATUS_MODE,
+ IOV_PROPTXSTATUS_OPT,
+ IOV_PROPTXSTATUS_MODULE_IGNORE,
+ IOV_PROPTXSTATUS_CREDIT_IGNORE,
+ IOV_PROPTXSTATUS_TXSTATUS_IGNORE,
+ IOV_PROPTXSTATUS_RXPKT_CHK,
+#endif /* PROP_TXSTATUS */
+ IOV_BUS_TYPE,
+#ifdef WLMEDIA_HTSF
+ IOV_WLPKTDLYSTAT_SZ,
+#endif
+ IOV_CHANGEMTU,
+ IOV_HOSTREORDER_FLOWS,
+#ifdef DHDTCPACK_SUPPRESS
+ IOV_TCPACK_SUPPRESS,
+#endif /* DHDTCPACK_SUPPRESS */
+ IOV_LAST
+};
+
+const bcm_iovar_t dhd_iovars[] = {
+ {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) },
+#ifdef DHD_DEBUG
+ {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
+#endif /* DHD_DEBUG */
+ {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN },
+ {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0 },
+ {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0 },
+ {"dump", IOV_DUMP, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN },
+#ifdef DHD_DEBUG
+ {"cons", IOV_CONS, 0, IOVT_BUFFER, 0 },
+ {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0 },
+ {"scan_timeout", IOV_SCAN_TIMEOUT, 0, IOVT_UINT32, 0 },
+ {"join_timeout_dbg", IOV_DHD_JOIN_TIMEOUT_DBG, 0, IOVT_UINT32, 0 },
+#endif
+ {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0 },
+ {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0 },
+ {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0 },
+#ifdef PROP_TXSTATUS
+ {"proptx", IOV_PROPTXSTATUS_ENABLE, 0, IOVT_BOOL, 0 },
+ /*
+ set the proptxtstatus operation mode:
+ 0 - Do not do any proptxtstatus flow control
+ 1 - Use implied credit from a packet status
+ 2 - Use explicit credit
+ */
+ {"ptxmode", IOV_PROPTXSTATUS_MODE, 0, IOVT_UINT32, 0 },
+ {"proptx_opt", IOV_PROPTXSTATUS_OPT, 0, IOVT_UINT32, 0 },
+ {"pmodule_ignore", IOV_PROPTXSTATUS_MODULE_IGNORE, 0, IOVT_BOOL, 0 },
+ {"pcredit_ignore", IOV_PROPTXSTATUS_CREDIT_IGNORE, 0, IOVT_BOOL, 0 },
+ {"ptxstatus_ignore", IOV_PROPTXSTATUS_TXSTATUS_IGNORE, 0, IOVT_BOOL, 0 },
+ {"rxpkt_chk", IOV_PROPTXSTATUS_RXPKT_CHK, 0, IOVT_BOOL, 0 },
+#endif /* PROP_TXSTATUS */
+ {"bustype", IOV_BUS_TYPE, 0, IOVT_UINT32, 0},
+#ifdef WLMEDIA_HTSF
+ {"pktdlystatsz", IOV_WLPKTDLYSTAT_SZ, 0, IOVT_UINT8, 0 },
+#endif
+ {"changemtu", IOV_CHANGEMTU, 0, IOVT_UINT32, 0 },
+ {"host_reorder_flows", IOV_HOSTREORDER_FLOWS, 0, IOVT_BUFFER,
+ (WLHOST_REORDERDATA_MAXFLOWS + 1) },
+#ifdef DHDTCPACK_SUPPRESS
+ {"tcpack_suppress", IOV_TCPACK_SUPPRESS, 0, IOVT_UINT8, 0 },
+#endif /* DHDTCPACK_SUPPRESS */
+ {NULL, 0, 0, 0, 0 }
+};
+
+#define DHD_IOVAR_BUF_SIZE 128
+
+/* to NDIS developer, the structure dhd_common is redundant,
+ * please do NOT merge it back from other branches !!!
+ */
+
+static int
+dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen)
+{
+ char eabuf[ETHER_ADDR_STR_LEN];
+
+ struct bcmstrbuf b;
+ struct bcmstrbuf *strbuf = &b;
+ if (!dhdp || !dhdp->prot || !buf)
+ return BCME_ERROR;
+
+ bcm_binit(strbuf, buf, buflen);
+
+ /* Base DHD info */
+ bcm_bprintf(strbuf, "%s\n", dhd_version);
+ bcm_bprintf(strbuf, "\n");
+ bcm_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
+ dhdp->up, dhdp->txoff, dhdp->busstate);
+ bcm_bprintf(strbuf, "pub.hdrlen %u pub.maxctl %u pub.rxsz %u\n",
+ dhdp->hdrlen, dhdp->maxctl, dhdp->rxsz);
+ bcm_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %s\n",
+ dhdp->iswl, dhdp->drv_version, bcm_ether_ntoa(&dhdp->mac, eabuf));
+ bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %u\n", dhdp->bcmerror, dhdp->tickcnt);
+
+ bcm_bprintf(strbuf, "dongle stats:\n");
+ bcm_bprintf(strbuf, "tx_packets %lu tx_bytes %lu tx_errors %lu tx_dropped %lu\n",
+ dhdp->dstats.tx_packets, dhdp->dstats.tx_bytes,
+ dhdp->dstats.tx_errors, dhdp->dstats.tx_dropped);
+ bcm_bprintf(strbuf, "rx_packets %lu rx_bytes %lu rx_errors %lu rx_dropped %lu\n",
+ dhdp->dstats.rx_packets, dhdp->dstats.rx_bytes,
+ dhdp->dstats.rx_errors, dhdp->dstats.rx_dropped);
+ bcm_bprintf(strbuf, "multicast %lu\n", dhdp->dstats.multicast);
+
+ bcm_bprintf(strbuf, "bus stats:\n");
+ bcm_bprintf(strbuf, "tx_packets %lu tx_multicast %lu tx_errors %lu\n",
+ dhdp->tx_packets, dhdp->tx_multicast, dhdp->tx_errors);
+ bcm_bprintf(strbuf, "tx_ctlpkts %lu tx_ctlerrs %lu\n",
+ dhdp->tx_ctlpkts, dhdp->tx_ctlerrs);
+ bcm_bprintf(strbuf, "rx_packets %lu rx_multicast %lu rx_errors %lu \n",
+ dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors);
+ bcm_bprintf(strbuf, "rx_ctlpkts %lu rx_ctlerrs %lu rx_dropped %lu\n",
+ dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped);
+ bcm_bprintf(strbuf, "rx_readahead_cnt %lu tx_realloc %lu\n",
+ dhdp->rx_readahead_cnt, dhdp->tx_realloc);
+ bcm_bprintf(strbuf, "\n");
+
+ /* Add any prot info */
+ dhd_prot_dump(dhdp, strbuf);
+ bcm_bprintf(strbuf, "\n");
+
+ /* Add any bus info */
+ dhd_bus_dump(dhdp, strbuf);
+
+ return (!strbuf->size ? BCME_BUFTOOSHORT : 0);
+}
+
+int
+dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, int ifindex)
+{
+ wl_ioctl_t ioc;
+
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+ ioc.set = set;
+
+ return dhd_wl_ioctl(dhd_pub, ifindex, &ioc, arg, len);
+}
+
+
+int
+dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len)
+{
+ int ret = 0;
+
+ if (dhd_os_proto_block(dhd_pub))
+ {
+
+ ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len);
+ if ((ret) && (dhd_pub->up))
+ /* Send hang event only if dhd_open() was success */
+ dhd_os_check_hang(dhd_pub, ifindex, ret);
+
+ if (ret == -ETIMEDOUT && !dhd_pub->up) {
+ DHD_ERROR(("%s: 'resumed on timeout' error is "
+ "occurred before the interface does not"
+ " bring up\n", __FUNCTION__));
+ dhd_pub->busstate = DHD_BUS_DOWN;
+ }
+
+ dhd_os_proto_unblock(dhd_pub);
+
+
+ }
+
+ return ret;
+}
+
+static int
+dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const char *name,
+ void *params, int plen, void *arg, int len, int val_size)
+{
+ int bcmerror = 0;
+ int32 int_val = 0;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ DHD_TRACE(("%s: actionid = %d; name %s\n", __FUNCTION__, actionid, name));
+
+ if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
+ goto exit;
+
+ if (plen >= (int)sizeof(int_val))
+ bcopy(params, &int_val, sizeof(int_val));
+
+ switch (actionid) {
+ case IOV_GVAL(IOV_VERSION):
+ /* Need to have checked buffer length */
+ bcm_strncpy_s((char*)arg, len, dhd_version, len);
+ break;
+
+ case IOV_GVAL(IOV_MSGLEVEL):
+ int_val = (int32)dhd_msg_level;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_MSGLEVEL):
+#ifdef WL_CFG80211
+ /* Enable DHD and WL logs in oneshot */
+ if (int_val & DHD_WL_VAL2)
+ wl_cfg80211_enable_trace(TRUE, int_val & (~DHD_WL_VAL2));
+ else if (int_val & DHD_WL_VAL)
+ wl_cfg80211_enable_trace(FALSE, WL_DBG_DBG);
+ if (!(int_val & DHD_WL_VAL2))
+#endif /* WL_CFG80211 */
+ dhd_msg_level = int_val;
+ break;
+ case IOV_GVAL(IOV_BCMERRORSTR):
+ bcm_strncpy_s((char *)arg, len, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN);
+ ((char *)arg)[BCME_STRLEN - 1] = 0x00;
+ break;
+
+ case IOV_GVAL(IOV_BCMERROR):
+ int_val = (int32)dhd_pub->bcmerror;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_WDTICK):
+ int_val = (int32)dhd_watchdog_ms;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_WDTICK):
+ if (!dhd_pub->up) {
+ bcmerror = BCME_NOTUP;
+ break;
+ }
+ dhd_os_wd_timer(dhd_pub, (uint)int_val);
+ break;
+
+ case IOV_GVAL(IOV_DUMP):
+ bcmerror = dhd_dump(dhd_pub, arg, len);
+ break;
+
+#ifdef DHD_DEBUG
+ case IOV_GVAL(IOV_SCAN_TIMEOUT):
+ {
+ uint32 scan_timeout = dhd_get_scan_timeout(dhd_pub);
+ bcopy(&scan_timeout, arg, sizeof(scan_timeout));
+ break;
+ }
+ case IOV_SVAL(IOV_SCAN_TIMEOUT):
+ {
+ uint32 scan_timeout;
+ bcopy(((uint8*)params), &scan_timeout, sizeof(scan_timeout));
+ dhd_set_scan_timeout(dhd_pub, scan_timeout);
+ break;
+ }
+ case IOV_GVAL(IOV_DHD_JOIN_TIMEOUT_DBG):
+ {
+ uint32 join_timeout = dhd_get_join_timeout(dhd_pub);
+ bcopy(&join_timeout, arg, sizeof(join_timeout));
+ break;
+ }
+ case IOV_SVAL(IOV_DHD_JOIN_TIMEOUT_DBG):
+ {
+ uint32 join_timeout;
+ bcopy(((uint8*)params), &join_timeout, sizeof(join_timeout));
+ dhd_set_join_timeout(dhd_pub, join_timeout);
+ break;
+ }
+#endif /* DHD_DEBUG */
+
+#ifdef DHD_DEBUG
+ case IOV_GVAL(IOV_DCONSOLE_POLL):
+ int_val = (int32)dhd_console_ms;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DCONSOLE_POLL):
+ dhd_console_ms = (uint)int_val;
+ break;
+
+ case IOV_SVAL(IOV_CONS):
+ if (len > 0)
+ bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+ break;
+#endif /* DHD_DEBUG */
+
+ case IOV_SVAL(IOV_CLEARCOUNTS):
+ dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
+ dhd_pub->tx_errors = dhd_pub->rx_errors = 0;
+ dhd_pub->tx_ctlpkts = dhd_pub->rx_ctlpkts = 0;
+ dhd_pub->tx_ctlerrs = dhd_pub->rx_ctlerrs = 0;
+ dhd_pub->rx_dropped = 0;
+ dhd_pub->rx_readahead_cnt = 0;
+ dhd_pub->tx_realloc = 0;
+ dhd_pub->wd_dpc_sched = 0;
+ memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats));
+ dhd_bus_clearcounts(dhd_pub);
+#ifdef PROP_TXSTATUS
+ /* clear proptxstatus related counters */
+ dhd_wlfc_clear_counts(dhd_pub);
+#endif /* PROP_TXSTATUS */
+ break;
+
+
+ case IOV_GVAL(IOV_IOCTLTIMEOUT): {
+ int_val = (int32)dhd_os_get_ioctl_resp_timeout();
+ bcopy(&int_val, arg, sizeof(int_val));
+ break;
+ }
+
+ case IOV_SVAL(IOV_IOCTLTIMEOUT): {
+ if (int_val <= 0)
+ bcmerror = BCME_BADARG;
+ else
+ dhd_os_set_ioctl_resp_timeout((unsigned int)int_val);
+ break;
+ }
+
+
+#ifdef PROP_TXSTATUS
+ case IOV_GVAL(IOV_PROPTXSTATUS_ENABLE): {
+ bool wlfc_enab = FALSE;
+ bcmerror = dhd_wlfc_get_enable(dhd_pub, &wlfc_enab);
+ if (bcmerror != BCME_OK)
+ goto exit;
+ int_val = wlfc_enab ? 1 : 0;
+ bcopy(&int_val, arg, val_size);
+ break;
+ }
+ case IOV_SVAL(IOV_PROPTXSTATUS_ENABLE): {
+ bool wlfc_enab = FALSE;
+ bcmerror = dhd_wlfc_get_enable(dhd_pub, &wlfc_enab);
+ if (bcmerror != BCME_OK)
+ goto exit;
+
+ /* wlfc is already set as desired */
+ if (wlfc_enab == (int_val == 0 ? FALSE : TRUE))
+ goto exit;
+
+ if (int_val == TRUE)
+ bcmerror = dhd_wlfc_init(dhd_pub);
+ else
+ bcmerror = dhd_wlfc_deinit(dhd_pub);
+
+ break;
+ }
+ case IOV_GVAL(IOV_PROPTXSTATUS_MODE):
+ bcmerror = dhd_wlfc_get_mode(dhd_pub, &int_val);
+ if (bcmerror != BCME_OK)
+ goto exit;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_PROPTXSTATUS_MODE):
+ dhd_wlfc_set_mode(dhd_pub, int_val);
+ break;
+
+ case IOV_GVAL(IOV_PROPTXSTATUS_MODULE_IGNORE):
+ bcmerror = dhd_wlfc_get_module_ignore(dhd_pub, &int_val);
+ if (bcmerror != BCME_OK)
+ goto exit;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_PROPTXSTATUS_MODULE_IGNORE):
+ dhd_wlfc_set_module_ignore(dhd_pub, int_val);
+ break;
+
+ case IOV_GVAL(IOV_PROPTXSTATUS_CREDIT_IGNORE):
+ bcmerror = dhd_wlfc_get_credit_ignore(dhd_pub, &int_val);
+ if (bcmerror != BCME_OK)
+ goto exit;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_PROPTXSTATUS_CREDIT_IGNORE):
+ dhd_wlfc_set_credit_ignore(dhd_pub, int_val);
+ break;
+
+ case IOV_GVAL(IOV_PROPTXSTATUS_TXSTATUS_IGNORE):
+ bcmerror = dhd_wlfc_get_txstatus_ignore(dhd_pub, &int_val);
+ if (bcmerror != BCME_OK)
+ goto exit;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_PROPTXSTATUS_TXSTATUS_IGNORE):
+ dhd_wlfc_set_txstatus_ignore(dhd_pub, int_val);
+ break;
+
+ case IOV_GVAL(IOV_PROPTXSTATUS_RXPKT_CHK):
+ bcmerror = dhd_wlfc_get_rxpkt_chk(dhd_pub, &int_val);
+ if (bcmerror != BCME_OK)
+ goto exit;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_PROPTXSTATUS_RXPKT_CHK):
+ dhd_wlfc_set_rxpkt_chk(dhd_pub, int_val);
+ break;
+
+#endif /* PROP_TXSTATUS */
+
+ case IOV_GVAL(IOV_BUS_TYPE):
+ /* The dhd application queries the driver to check if its usb or sdio. */
+#ifdef BCMDHDUSB
+ int_val = BUS_TYPE_USB;
+#endif
+ int_val = BUS_TYPE_SDIO;
+#ifdef PCIE_FULL_DONGLE
+ int_val = BUS_TYPE_PCIE;
+#endif
+ bcopy(&int_val, arg, val_size);
+ break;
+
+
+#ifdef WLMEDIA_HTSF
+ case IOV_GVAL(IOV_WLPKTDLYSTAT_SZ):
+ int_val = dhd_pub->htsfdlystat_sz;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_WLPKTDLYSTAT_SZ):
+ dhd_pub->htsfdlystat_sz = int_val & 0xff;
+ printf("Setting tsfdlystat_sz:%d\n", dhd_pub->htsfdlystat_sz);
+ break;
+#endif
+ case IOV_SVAL(IOV_CHANGEMTU):
+ int_val &= 0xffff;
+ bcmerror = dhd_change_mtu(dhd_pub, int_val, 0);
+ break;
+
+ case IOV_GVAL(IOV_HOSTREORDER_FLOWS):
+ {
+ uint i = 0;
+ uint8 *ptr = (uint8 *)arg;
+ uint8 count = 0;
+
+ ptr++;
+ for (i = 0; i < WLHOST_REORDERDATA_MAXFLOWS; i++) {
+ if (dhd_pub->reorder_bufs[i] != NULL) {
+ *ptr = dhd_pub->reorder_bufs[i]->flow_id;
+ ptr++;
+ count++;
+ }
+ }
+ ptr = (uint8 *)arg;
+ *ptr = count;
+ break;
+ }
+#ifdef DHDTCPACK_SUPPRESS
+ case IOV_GVAL(IOV_TCPACK_SUPPRESS): {
+ int_val = (uint32)dhd_pub->tcpack_sup_mode;
+ bcopy(&int_val, arg, val_size);
+ break;
+ }
+ case IOV_SVAL(IOV_TCPACK_SUPPRESS): {
+ bcmerror = dhd_tcpack_suppress_set(dhd_pub, (uint8)int_val);
+ break;
+ }
+#endif /* DHDTCPACK_SUPPRESS */
+
+ default:
+ bcmerror = BCME_UNSUPPORTED;
+ break;
+ }
+
+exit:
+ DHD_TRACE(("%s: actionid %d, bcmerror %d\n", __FUNCTION__, actionid, bcmerror));
+ return bcmerror;
+}
+
+/* Store the status of a connection attempt for later retrieval by an iovar */
+void
+dhd_store_conn_status(uint32 event, uint32 status, uint32 reason)
+{
+ /* Do not overwrite a WLC_E_PRUNE with a WLC_E_SET_SSID
+ * because an encryption/rsn mismatch results in both events, and
+ * the important information is in the WLC_E_PRUNE.
+ */
+ if (!(event == WLC_E_SET_SSID && status == WLC_E_STATUS_FAIL &&
+ dhd_conn_event == WLC_E_PRUNE)) {
+ dhd_conn_event = event;
+ dhd_conn_status = status;
+ dhd_conn_reason = reason;
+ }
+}
+
+bool
+dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec)
+{
+ void *p;
+ int eprec = -1; /* precedence to evict from */
+ bool discard_oldest;
+
+ /* Fast case, precedence queue is not full and we are also not
+ * exceeding total queue length
+ */
+ if (!pktq_pfull(q, prec) && !pktq_full(q)) {
+ pktq_penq(q, prec, pkt);
+ return TRUE;
+ }
+
+ /* Determine precedence from which to evict packet, if any */
+ if (pktq_pfull(q, prec))
+ eprec = prec;
+ else if (pktq_full(q)) {
+ p = pktq_peek_tail(q, &eprec);
+ ASSERT(p);
+ if (eprec > prec || eprec < 0)
+ return FALSE;
+ }
+
+ /* Evict if needed */
+ if (eprec >= 0) {
+ /* Detect queueing to unconfigured precedence */
+ ASSERT(!pktq_pempty(q, eprec));
+ discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec);
+ if (eprec == prec && !discard_oldest)
+ return FALSE; /* refuse newer (incoming) packet */
+ /* Evict packet according to discard policy */
+ p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q, eprec);
+ ASSERT(p);
+#ifdef DHDTCPACK_SUPPRESS
+ if (dhd_tcpack_check_xmit(dhdp, p) == BCME_ERROR) {
+ DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
+ __FUNCTION__, __LINE__));
+ dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF);
+ }
+#endif /* DHDTCPACK_SUPPRESS */
+ PKTFREE(dhdp->osh, p, TRUE);
+ }
+
+ /* Enqueue */
+ p = pktq_penq(q, prec, pkt);
+ ASSERT(p);
+
+ return TRUE;
+}
+
+/*
+ * Functions to drop proper pkts from queue:
+ * If one pkt in queue is non-fragmented, drop first non-fragmented pkt only
+ * If all pkts in queue are all fragmented, find and drop one whole set fragmented pkts
+ * If can't find pkts matching upper 2 cases, drop first pkt anyway
+ */
+bool
+dhd_prec_drop_pkts(dhd_pub_t *dhdp, struct pktq *pq, int prec, f_droppkt_t fn)
+{
+ struct pktq_prec *q = NULL;
+ void *p, *prev = NULL, *next = NULL, *first = NULL, *last = NULL, *prev_first = NULL;
+ pkt_frag_t frag_info;
+
+ ASSERT(dhdp && pq);
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ q = &pq->q[prec];
+ p = q->head;
+
+ if (p == NULL)
+ return FALSE;
+
+ while (p) {
+ frag_info = pkt_frag_info(dhdp->osh, p);
+ if (frag_info == DHD_PKT_FRAG_NONE) {
+ break;
+ } else if (frag_info == DHD_PKT_FRAG_FIRST) {
+ if (first) {
+ /* No last frag pkt, use prev as last */
+ last = prev;
+ break;
+ } else {
+ first = p;
+ prev_first = prev;
+ }
+ } else if (frag_info == DHD_PKT_FRAG_LAST) {
+ if (first) {
+ last = p;
+ break;
+ }
+ }
+
+ prev = p;
+ p = PKTLINK(p);
+ }
+
+ if ((p == NULL) || ((frag_info != DHD_PKT_FRAG_NONE) && !(first && last))) {
+ /* Not found matching pkts, use oldest */
+ prev = NULL;
+ p = q->head;
+ frag_info = 0;
+ }
+
+ if (frag_info == DHD_PKT_FRAG_NONE) {
+ first = last = p;
+ prev_first = prev;
+ }
+
+ p = first;
+ while (p) {
+ next = PKTLINK(p);
+ q->len--;
+ pq->len--;
+
+ PKTSETLINK(p, NULL);
+
+ if (fn)
+ fn(dhdp, prec, p, TRUE);
+
+ if (p == last)
+ break;
+
+ p = next;
+ }
+
+ if (prev_first == NULL) {
+ if ((q->head = next) == NULL)
+ q->tail = NULL;
+ } else {
+ PKTSETLINK(prev_first, next);
+ if (!next)
+ q->tail = prev_first;
+ }
+
+ return TRUE;
+}
+
+static int
+dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
+{
+ int bcmerror = 0;
+ int val_size;
+ const bcm_iovar_t *vi = NULL;
+ uint32 actionid;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ASSERT(name);
+ ASSERT(len >= 0);
+
+ /* Get MUST have return space */
+ ASSERT(set || (arg && len));
+
+ /* Set does NOT take qualifiers */
+ ASSERT(!set || (!params && !plen));
+
+ if ((vi = bcm_iovar_lookup(dhd_iovars, name)) == NULL) {
+ bcmerror = BCME_UNSUPPORTED;
+ goto exit;
+ }
+
+ DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
+ name, (set ? "set" : "get"), len, plen));
+
+ /* set up 'params' pointer in case this is a set command so that
+ * the convenience int and bool code can be common to set and get
+ */
+ if (params == NULL) {
+ params = arg;
+ plen = len;
+ }
+
+ if (vi->type == IOVT_VOID)
+ val_size = 0;
+ else if (vi->type == IOVT_BUFFER)
+ val_size = len;
+ else
+ /* all other types are integer sized */
+ val_size = sizeof(int);
+
+ actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+
+ bcmerror = dhd_doiovar(dhd_pub, vi, actionid, name, params, plen, arg, len, val_size);
+
+exit:
+ return bcmerror;
+}
+
+int
+dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen)
+{
+ int bcmerror = 0;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (!buf) {
+ return BCME_BADARG;
+ }
+
+ switch (ioc->cmd) {
+ case DHD_GET_MAGIC:
+ if (buflen < sizeof(int))
+ bcmerror = BCME_BUFTOOSHORT;
+ else
+ *(int*)buf = DHD_IOCTL_MAGIC;
+ break;
+
+ case DHD_GET_VERSION:
+ if (buflen < sizeof(int))
+ bcmerror = BCME_BUFTOOSHORT;
+ else
+ *(int*)buf = DHD_IOCTL_VERSION;
+ break;
+
+ case DHD_GET_VAR:
+ case DHD_SET_VAR: {
+ char *arg;
+ uint arglen;
+
+ /* scan past the name to any arguments */
+ for (arg = buf, arglen = buflen; *arg && arglen; arg++, arglen--)
+ ;
+
+ if (*arg) {
+ bcmerror = BCME_BUFTOOSHORT;
+ break;
+ }
+
+ /* account for the NUL terminator */
+ arg++, arglen--;
+
+ /* call with the appropriate arguments */
+ if (ioc->cmd == DHD_GET_VAR)
+ bcmerror = dhd_iovar_op(dhd_pub, buf, arg, arglen,
+ buf, buflen, IOV_GET);
+ else
+ bcmerror = dhd_iovar_op(dhd_pub, buf, NULL, 0, arg, arglen, IOV_SET);
+ if (bcmerror != BCME_UNSUPPORTED)
+ break;
+
+ /* not in generic table, try protocol module */
+ if (ioc->cmd == DHD_GET_VAR)
+ bcmerror = dhd_prot_iovar_op(dhd_pub, buf, arg,
+ arglen, buf, buflen, IOV_GET);
+ else
+ bcmerror = dhd_prot_iovar_op(dhd_pub, buf,
+ NULL, 0, arg, arglen, IOV_SET);
+ if (bcmerror != BCME_UNSUPPORTED)
+ break;
+
+ /* if still not found, try bus module */
+ if (ioc->cmd == DHD_GET_VAR) {
+ bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
+ arg, arglen, buf, buflen, IOV_GET);
+ } else {
+ bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
+ NULL, 0, arg, arglen, IOV_SET);
+ }
+
+ break;
+ }
+ default:
+ bcmerror = BCME_UNSUPPORTED;
+ }
+
+ return bcmerror;
+}
+
+#ifdef SHOW_EVENTS
+#ifdef SHOW_LOGTRACE
+
+#define MAX_NO_OF_ARG 16
+
+#define FMTSTR_SIZE 100
+#define SIZE_LOC_STR 50
+#define MIN_DLEN 4
+#define TAG_BYTES 12
+#define TAG_WORDS 3
+
+static int
+check_event_log_sequence_number(uint32 seq_no)
+{
+ int32 diff;
+ uint32 ret;
+ static uint32 logtrace_seqnum_prev = 0;
+
+ diff = ntoh32(seq_no)-logtrace_seqnum_prev;
+ switch (diff)
+ {
+ case 0:
+ ret = -1; /* duplicate packet . drop */
+ break;
+
+ case 1:
+ ret =0; /* in order */
+ break;
+
+ default:
+ if ((ntoh32(seq_no) == 0) &&
+ (logtrace_seqnum_prev == 0xFFFFFFFF) ) { /* in-order - Roll over */
+ ret = 0;
+ } else {
+
+ if (diff > 0) {
+ DHD_EVENT(("WLC_E_TRACE:"
+ "Event lost (log) seqnum %d nblost %d\n",
+ ntoh32(seq_no), (diff-1)));
+ } else {
+ DHD_EVENT(("WLC_E_TRACE:"
+ "Event Packets coming out of order!!\n"));
+ }
+ ret = 0;
+ }
+ }
+
+ logtrace_seqnum_prev = ntoh32(seq_no);
+
+ return ret;
+}
+
+static void
+dhd_eventmsg_print(dhd_pub_t *dhd_pub, void *event_data, void *raw_event_ptr,
+ uint datalen, const char *event_name)
+{
+ msgtrace_hdr_t hdr;
+ uint32 nblost;
+ uint8 count;
+ char *s, *p;
+ static uint32 seqnum_prev = 0;
+ uint32 *log_ptr = NULL;
+ uchar *buf;
+ event_log_hdr_t event_hdr;
+ uint32 i;
+ int32 j;
+
+ dhd_event_log_t *raw_event = (dhd_event_log_t *) raw_event_ptr;
+
+ char fmtstr_loc_buf[FMTSTR_SIZE] = {0};
+ char (*str_buf)[SIZE_LOC_STR] = NULL;
+ char * str_tmpptr = NULL;
+ uint32 addr = 0;
+ uint32 **hdr_ptr = NULL;
+ uint32 h_i = 0;
+ uint32 hdr_ptr_len = 0;
+
+ typedef union {
+ uint32 val;
+ char * addr;
+ } u_arg;
+ u_arg arg[MAX_NO_OF_ARG] = {{0}};
+ char *c_ptr = NULL;
+
+ buf = (uchar *) event_data;
+ memcpy(&hdr, buf, MSGTRACE_HDRLEN);
+
+ if (hdr.version != MSGTRACE_VERSION) {
+ DHD_EVENT(("\nMACEVENT: %s [unsupported version --> "
+ "dhd version:%d dongle version:%d]\n",
+ event_name, MSGTRACE_VERSION, hdr.version));
+ /* Reset datalen to avoid display below */
+ datalen = 0;
+ return;
+ }
+
+ if (hdr.trace_type == MSGTRACE_HDR_TYPE_MSG) {
+ /* There are 2 bytes available at the end of data */
+ buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0';
+
+ if (ntoh32(hdr.discarded_bytes) || ntoh32(hdr.discarded_printf)) {
+ DHD_EVENT(("WLC_E_TRACE: [Discarded traces in dongle -->"
+ "discarded_bytes %d discarded_printf %d]\n",
+ ntoh32(hdr.discarded_bytes),
+ ntoh32(hdr.discarded_printf)));
+ }
+
+ nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1;
+ if (nblost > 0) {
+ DHD_EVENT(("WLC_E_TRACE:"
+ "[Event lost (msg) --> seqnum %d nblost %d\n",
+ ntoh32(hdr.seqnum), nblost));
+ }
+ seqnum_prev = ntoh32(hdr.seqnum);
+
+ /* Display the trace buffer. Advance from
+ * \n to \n to avoid display big
+ * printf (issue with Linux printk )
+ */
+ p = (char *)&buf[MSGTRACE_HDRLEN];
+ while (*p != '\0' && (s = strstr(p, "\n")) != NULL) {
+ *s = '\0';
+ DHD_EVENT(("%s\n", p));
+ p = s+1;
+ }
+ if (*p)
+ DHD_EVENT(("%s", p));
+
+ /* Reset datalen to avoid display below */
+ datalen = 0;
+
+ } else if (hdr.trace_type == MSGTRACE_HDR_TYPE_LOG) {
+ /* Let the standard event printing work for now */
+ uint32 timestamp, w;
+
+ if (check_event_log_sequence_number(hdr.seqnum)) {
+ DHD_EVENT(("%s: WLC_E_TRACE:"
+ "[Event duplicate (log) %d] dropping!!\n",
+ __FUNCTION__, hdr.seqnum));
+ return; /* drop duplicate events */
+ }
+
+ p = (char *)&buf[MSGTRACE_HDRLEN];
+ datalen -= MSGTRACE_HDRLEN;
+ w = ntoh32((uint32)*p);
+ p += MIN_DLEN;
+ datalen -= MIN_DLEN;
+ timestamp = ntoh32((uint32)*p);
+ BCM_REFERENCE(timestamp);
+ BCM_REFERENCE(w);
+
+ /*
+ * Allocating max possible number of event TAGs in the received buffer
+ * considering that each event requires minimum of TAG_BYTES.
+ */
+ hdr_ptr_len = ((datalen/TAG_BYTES)+1) * sizeof(uint32*);
+
+ if ((raw_event->fmts)) {
+ if (!(str_buf = MALLOC(dhd_pub->osh, (MAX_NO_OF_ARG * SIZE_LOC_STR)))) {
+ DHD_ERROR(("%s: malloc failed\n", __FUNCTION__));
+ }
+
+ if (!(hdr_ptr = MALLOC(dhd_pub->osh, hdr_ptr_len))) {
+ DHD_ERROR(("%s: malloc failed\n", __FUNCTION__));
+ }
+ }
+
+ DHD_EVENT(("timestamp %x%x\n", timestamp, w));
+ if ((!raw_event->fmts) || (!str_buf) || (!hdr_ptr)) {
+ while (datalen > MIN_DLEN) {
+ p += MIN_DLEN;
+ datalen -= MIN_DLEN;
+ /* Print each word. DO NOT ntoh it. */
+ DHD_EVENT((" %8.8x", *((uint32 *) p)));
+ }
+ DHD_EVENT(("\n"));
+ datalen = 0;
+ if (str_buf) {
+ MFREE(dhd_pub->osh, str_buf, (MAX_NO_OF_ARG * SIZE_LOC_STR));
+ }
+ if (hdr_ptr) {
+ MFREE(dhd_pub->osh, hdr_ptr, hdr_ptr_len);
+ }
+ return;
+ }
+
+ /* (raw_event->fmts) has value */
+
+ log_ptr = (uint32 *) (p + datalen);
+
+ while (datalen > MIN_DLEN) {
+ log_ptr--;
+ datalen -= MIN_DLEN;
+ event_hdr.t = *log_ptr;
+ /*
+ * Check for partially overriten entries
+ */
+ if (log_ptr - (uint32 *) p < event_hdr.count) {
+ break;
+ }
+ /*
+ * Check for end of the Frame.
+ */
+ if (event_hdr.tag == EVENT_LOG_TAG_NULL) {
+ continue;
+ }
+ /*
+ * Check For Special Time Stamp Packet
+ */
+ if (event_hdr.tag == EVENT_LOG_TAG_TS) {
+ datalen -= TAG_BYTES;
+ log_ptr = log_ptr - TAG_WORDS;
+ continue;
+ }
+
+ log_ptr[0] = event_hdr.t;
+ if (h_i < (hdr_ptr_len / sizeof(uint32*))) {
+ hdr_ptr[h_i++] = log_ptr;
+ }
+ if (event_hdr.count > MAX_NO_OF_ARG) {
+ break;
+ }
+
+ /* Now place the header at the front
+ * and copy back.
+ */
+ log_ptr -= event_hdr.count;
+
+ c_ptr = NULL;
+ datalen = datalen - (event_hdr.count * MIN_DLEN);
+ }
+ datalen = 0;
+
+ for (j = (h_i-1); j >= 0; j--) {
+ if (!(hdr_ptr[j])) {
+ break;
+ }
+
+ event_hdr.t = *hdr_ptr[j];
+
+ log_ptr = hdr_ptr[j];
+
+ /* Now place the header at the front
+ * and copy back.
+ */
+ log_ptr -= event_hdr.count;
+
+ /* Copy the format string to parse %s and add "CONSOLE: " ??? */
+ if ((event_hdr.fmt_num >> 2) < raw_event->num_fmts) {
+ snprintf(fmtstr_loc_buf, FMTSTR_SIZE,
+ "CONSOLE: [0x%x] %s", log_ptr[event_hdr.count-1],
+ raw_event->fmts[event_hdr.fmt_num >> 2]);
+ c_ptr = fmtstr_loc_buf;
+ }
+
+ for (count = 0; count < (event_hdr.count-1); count++) {
+ if (c_ptr != NULL) {
+ if ((c_ptr = strstr(c_ptr, "%")) != NULL) {
+ c_ptr++;
+ }
+ }
+
+ if ((c_ptr != NULL) && (*c_ptr == 's')) {
+ if ((raw_event->raw_sstr) &&
+ ((log_ptr[count] > raw_event->rodata_start) &&
+ (log_ptr[count] < raw_event->rodata_end))) {
+ /* ram static string */
+ addr = log_ptr[count] - raw_event->rodata_start;
+ str_tmpptr = raw_event->raw_sstr + addr;
+ memcpy(str_buf[count], str_tmpptr, SIZE_LOC_STR);
+ str_buf[count][SIZE_LOC_STR-1] = '\0';
+ arg[count].addr = str_buf[count];
+ } else if ((raw_event->rom_raw_sstr) &&
+ ((log_ptr[count] >
+ raw_event->rom_rodata_start) &&
+ (log_ptr[count] <
+ raw_event->rom_rodata_end))) {
+ /* rom static string */
+ addr = log_ptr[count] - raw_event->rom_rodata_start;
+ str_tmpptr = raw_event->rom_raw_sstr + addr;
+ memcpy(str_buf[count], str_tmpptr, SIZE_LOC_STR);
+ str_buf[count][SIZE_LOC_STR-1] = '\0';
+ arg[count].addr = str_buf[count];
+ } else {
+ /*
+ * Dynamic string OR
+ * No data for static string.
+ * So store all string's address as string.
+ */
+ snprintf(str_buf[count], SIZE_LOC_STR, "(s)0x%x",
+ log_ptr[count]);
+ arg[count].addr = str_buf[count];
+ }
+ } else {
+ /* Other than string */
+ arg[count].val = log_ptr[count];
+ }
+ }
+
+ DHD_EVENT((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
+ arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
+ arg[11], arg[12], arg[13], arg[14], arg[15]));
+
+ for (i = 0; i < MAX_NO_OF_ARG; i++) {
+ arg[i].addr = 0;
+ }
+ for (i = 0; i < MAX_NO_OF_ARG; i++) {
+ memset(str_buf[i], 0, SIZE_LOC_STR);
+ }
+
+ }
+
+ if (str_buf) {
+ MFREE(dhd_pub->osh, str_buf, (MAX_NO_OF_ARG * SIZE_LOC_STR));
+ }
+
+ if (hdr_ptr) {
+ MFREE(dhd_pub->osh, hdr_ptr, hdr_ptr_len);
+ }
+ }
+}
+
+#endif /* SHOW_LOGTRACE */
+
+static void
+wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data,
+ void *raw_event_ptr)
+{
+ uint i, status, reason;
+ bool group = FALSE, flush_txq = FALSE, link = FALSE;
+ const char *auth_str;
+ const char *event_name;
+ uchar *buf;
+ char err_msg[256], eabuf[ETHER_ADDR_STR_LEN];
+ uint event_type, flags, auth_type, datalen;
+
+ event_type = ntoh32(event->event_type);
+ flags = ntoh16(event->flags);
+ status = ntoh32(event->status);
+ reason = ntoh32(event->reason);
+ BCM_REFERENCE(reason);
+ auth_type = ntoh32(event->auth_type);
+ datalen = ntoh32(event->datalen);
+
+ /* debug dump of event messages */
+ snprintf(eabuf, sizeof(eabuf), "%02x:%02x:%02x:%02x:%02x:%02x",
+ (uchar)event->addr.octet[0]&0xff,
+ (uchar)event->addr.octet[1]&0xff,
+ (uchar)event->addr.octet[2]&0xff,
+ (uchar)event->addr.octet[3]&0xff,
+ (uchar)event->addr.octet[4]&0xff,
+ (uchar)event->addr.octet[5]&0xff);
+
+ event_name = "UNKNOWN";
+ for (i = 0; i < (uint)bcmevent_names_size; i++)
+ if (bcmevent_names[i].event == event_type)
+ event_name = bcmevent_names[i].name;
+
+ if (flags & WLC_EVENT_MSG_LINK)
+ link = TRUE;
+ if (flags & WLC_EVENT_MSG_GROUP)
+ group = TRUE;
+ if (flags & WLC_EVENT_MSG_FLUSHTXQ)
+ flush_txq = TRUE;
+
+ switch (event_type) {
+ case WLC_E_START:
+ case WLC_E_DEAUTH:
+ case WLC_E_DISASSOC:
+ DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ break;
+
+ case WLC_E_ASSOC_IND:
+ case WLC_E_REASSOC_IND:
+
+ DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ break;
+
+ case WLC_E_ASSOC:
+ case WLC_E_REASSOC:
+ if (status == WLC_E_STATUS_SUCCESS) {
+ DHD_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n", event_name, eabuf));
+ } else if (status == WLC_E_STATUS_TIMEOUT) {
+ DHD_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n", event_name, eabuf));
+ } else if (status == WLC_E_STATUS_FAIL) {
+ DHD_EVENT(("MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
+ event_name, eabuf, (int)reason));
+ } else {
+ DHD_EVENT(("MACEVENT: %s, MAC %s, unexpected status %d\n",
+ event_name, eabuf, (int)status));
+ }
+ break;
+
+ case WLC_E_DEAUTH_IND:
+ case WLC_E_DISASSOC_IND:
+ DHD_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name, eabuf, (int)reason));
+ break;
+
+ case WLC_E_AUTH:
+ case WLC_E_AUTH_IND:
+ if (auth_type == DOT11_OPEN_SYSTEM)
+ auth_str = "Open System";
+ else if (auth_type == DOT11_SHARED_KEY)
+ auth_str = "Shared Key";
+ else {
+ snprintf(err_msg, sizeof(err_msg), "AUTH unknown: %d", (int)auth_type);
+ auth_str = err_msg;
+ }
+ if (event_type == WLC_E_AUTH_IND) {
+ DHD_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name, eabuf, auth_str));
+ } else if (status == WLC_E_STATUS_SUCCESS) {
+ DHD_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
+ event_name, eabuf, auth_str));
+ } else if (status == WLC_E_STATUS_TIMEOUT) {
+ DHD_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
+ event_name, eabuf, auth_str));
+ } else if (status == WLC_E_STATUS_FAIL) {
+ DHD_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n",
+ event_name, eabuf, auth_str, (int)reason));
+ }
+ BCM_REFERENCE(auth_str);
+
+ break;
+
+ case WLC_E_JOIN:
+ case WLC_E_ROAM:
+ case WLC_E_SET_SSID:
+ if (status == WLC_E_STATUS_SUCCESS) {
+ DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ } else if (status == WLC_E_STATUS_FAIL) {
+ DHD_EVENT(("MACEVENT: %s, failed\n", event_name));
+ } else if (status == WLC_E_STATUS_NO_NETWORKS) {
+ DHD_EVENT(("MACEVENT: %s, no networks found\n", event_name));
+ } else {
+ DHD_EVENT(("MACEVENT: %s, unexpected status %d\n",
+ event_name, (int)status));
+ }
+ break;
+
+ case WLC_E_BEACON_RX:
+ if (status == WLC_E_STATUS_SUCCESS) {
+ DHD_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
+ } else if (status == WLC_E_STATUS_FAIL) {
+ DHD_EVENT(("MACEVENT: %s, FAIL\n", event_name));
+ } else {
+ DHD_EVENT(("MACEVENT: %s, status %d\n", event_name, status));
+ }
+ break;
+
+ case WLC_E_LINK:
+ DHD_EVENT(("MACEVENT: %s %s\n", event_name, link?"UP":"DOWN"));
+ BCM_REFERENCE(link);
+ break;
+
+ case WLC_E_MIC_ERROR:
+ DHD_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
+ event_name, eabuf, group, flush_txq));
+ BCM_REFERENCE(group);
+ BCM_REFERENCE(flush_txq);
+ break;
+
+ case WLC_E_ICV_ERROR:
+ case WLC_E_UNICAST_DECODE_ERROR:
+ case WLC_E_MULTICAST_DECODE_ERROR:
+ DHD_EVENT(("MACEVENT: %s, MAC %s\n",
+ event_name, eabuf));
+ break;
+
+ case WLC_E_TXFAIL:
+ DHD_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
+ break;
+
+ case WLC_E_SCAN_COMPLETE:
+ case WLC_E_ASSOC_REQ_IE:
+ case WLC_E_ASSOC_RESP_IE:
+ case WLC_E_PMKID_CACHE:
+ DHD_EVENT(("MACEVENT: %s\n", event_name));
+ break;
+
+ case WLC_E_PFN_NET_FOUND:
+ case WLC_E_PFN_NET_LOST:
+ case WLC_E_PFN_SCAN_COMPLETE:
+ case WLC_E_PFN_SCAN_NONE:
+ case WLC_E_PFN_SCAN_ALLGONE:
+ DHD_EVENT(("PNOEVENT: %s\n", event_name));
+ break;
+
+ case WLC_E_PSK_SUP:
+ case WLC_E_PRUNE:
+ DHD_EVENT(("MACEVENT: %s, status %d, reason %d\n",
+ event_name, (int)status, (int)reason));
+ break;
+
+#ifdef WIFI_ACT_FRAME
+ case WLC_E_ACTION_FRAME:
+ DHD_TRACE(("MACEVENT: %s Bssid %s\n", event_name, eabuf));
+ break;
+#endif /* WIFI_ACT_FRAME */
+
+#ifdef SHOW_LOGTRACE
+ case WLC_E_TRACE:
+ {
+ dhd_eventmsg_print(dhd_pub, event_data, raw_event_ptr, datalen, event_name);
+ break;
+ }
+#endif /* SHOW_LOGTRACE */
+
+
+ case WLC_E_RSSI:
+ DHD_EVENT(("MACEVENT: %s %d\n", event_name, ntoh32(*((int *)event_data))));
+ break;
+
+ case WLC_E_SERVICE_FOUND:
+ case WLC_E_P2PO_ADD_DEVICE:
+ case WLC_E_P2PO_DEL_DEVICE:
+ DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+ break;
+
+ case WLC_E_CCA_CHAN_QUAL:
+ if (datalen) {
+ buf = (uchar *) event_data;
+ DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d, "
+ "channel 0x%02x \n", event_name, event_type, eabuf, (int)status,
+ (int)reason, (int)auth_type, *(buf + 4)));
+ }
+ break;
+ case WLC_E_PKT_FILTER:
+ if (status == WLC_E_PKT_FILTER_TIMEOUT)
+ DHD_EVENT(("MACEVENT: %s, Timeout(Pkt Filter Id=%d)\n", event_name, reason));
+ else
+ DHD_EVENT(("MACEVENT: %s, status %d reason %d\n", event_name, status, reason));
+ break;
+
+ default:
+ DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
+ event_name, event_type, eabuf, (int)status, (int)reason,
+ (int)auth_type));
+ break;
+ }
+
+ /* show any appended data */
+ if (DHD_BYTES_ON() && DHD_EVENT_ON() && datalen) {
+ buf = (uchar *) event_data;
+ DHD_EVENT((" data (%d) : ", datalen));
+ for (i = 0; i < datalen; i++)
+ DHD_EVENT((" 0x%02x ", *buf++));
+ DHD_EVENT(("\n"));
+ }
+}
+#endif /* SHOW_EVENTS */
+
+/* Check whether packet is a BRCM event pkt. If it is, record event data. */
+int
+wl_host_event_get_data(void *pktdata, uint pktlen, wl_event_msg_t *evt)
+{
+ int ret;
+
+ ret = is_wlc_event_frame(pktdata, pktlen, 0, evt);
+ if (ret != BCME_OK) {
+ DHD_ERROR(("%s: Invalid event frame, err = %d\n",
+ __FUNCTION__, ret));
+ }
+
+ return ret;
+}
+
+int
+wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint16 pktlen,
+ wl_event_msg_t *event, void **data_ptr, void *raw_event)
+{
+ /* check whether packet is a BRCM event pkt */
+ bcm_event_t *pvt_data = (bcm_event_t *)pktdata;
+ uint8 *event_data;
+ uint32 type, status, datalen;
+ uint16 flags;
+ uint evlen;
+ int ret;
+
+ ret = wl_host_event_get_data(pktdata, pktlen, event);
+ if (ret != BCME_OK) {
+ return ret;
+ }
+
+ *data_ptr = &pvt_data[1];
+ event_data = *data_ptr;
+
+ /* memcpy since BRCM event pkt may be unaligned. */
+ memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
+
+ type = ntoh32_ua((void *)&event->event_type);
+ flags = ntoh16_ua((void *)&event->flags);
+ status = ntoh32_ua((void *)&event->status);
+ datalen = ntoh32_ua((void *)&event->datalen);
+
+ if (datalen > pktlen)
+ return (BCME_ERROR);
+
+ evlen = datalen + sizeof(bcm_event_t);
+
+ if (evlen > pktlen)
+ return (BCME_ERROR);
+
+ switch (type) {
+#ifdef DHD_DEBUG
+ case WLC_E_JOIN_START:
+ case WLC_E_ROAM_START:
+ dhd_start_join_timer(dhd_pub);
+ break;
+ case WLC_E_ASSOC:
+ case WLC_E_REASSOC:
+ if ((status != WLC_E_STATUS_TIMEOUT) && (status != WLC_E_STATUS_FAIL))
+ break;
+ case WLC_E_SET_SSID:
+ if (status != WLC_E_STATUS_SUCCESS)
+ break;
+ case WLC_E_JOIN:
+ case WLC_E_ROAM:
+ dhd_del_join_timer(dhd_pub);
+ break;
+
+ case WLC_E_SCAN_CONFIRM_IND:
+ dhd_add_scan_timer(dhd_pub);
+ break;
+
+ case WLC_E_ESCAN_RESULT:
+ dhd_del_scan_timer(dhd_pub);
+ break;
+#endif /* DHD_DEBUG */
+#ifdef PROP_TXSTATUS
+ case WLC_E_FIFO_CREDIT_MAP:
+ if (dhd_wlfc_enable(dhd_pub) != BCME_OK) {
+ DHD_ERROR(("%s: dhd_wlfc_enable failed\n", __FUNCTION__));
+ return (BCME_ERROR);
+ }
+ dhd_wlfc_FIFOcreditmap_event(dhd_pub, event_data);
+ WLFC_DBGMESG(("WLC_E_FIFO_CREDIT_MAP:(AC0,AC1,AC2,AC3),(BC_MC),(OTHER): "
+ "(%d,%d,%d,%d),(%d),(%d)\n", event_data[0], event_data[1],
+ event_data[2],
+ event_data[3], event_data[4], event_data[5]));
+ break;
+
+ case WLC_E_BCMC_CREDIT_SUPPORT:
+ dhd_wlfc_BCMCCredit_support_event(dhd_pub);
+ break;
+#endif /* PROP_TXSTATUS */
+
+ case WLC_E_IF: {
+ struct wl_event_data_if *ifevent = (struct wl_event_data_if *)event_data;
+
+ /* Ignore the event if NOIF is set */
+ if (ifevent->reserved & WLC_E_IF_FLAGS_BSSCFG_NOIF) {
+ DHD_ERROR(("WLC_E_IF: NO_IF set, event Ignored\r\n"));
+ return (BCME_UNSUPPORTED);
+ }
+
+#ifdef PROP_TXSTATUS
+ {
+ uint8* ea = pvt_data->eth.ether_dhost;
+ WLFC_DBGMESG(("WLC_E_IF: idx:%d, action:%s, iftype:%s, "
+ "[%02x:%02x:%02x:%02x:%02x:%02x]\n",
+ ifevent->ifidx,
+ ((ifevent->opcode == WLC_E_IF_ADD) ? "ADD":"DEL"),
+ ((ifevent->role == 0) ? "STA":"AP "),
+ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]));
+ (void)ea;
+
+ if (ifevent->opcode == WLC_E_IF_CHANGE)
+ dhd_wlfc_interface_event(dhd_pub,
+ eWLFC_MAC_ENTRY_ACTION_UPDATE,
+ ifevent->ifidx, ifevent->role, ea);
+ else
+ dhd_wlfc_interface_event(dhd_pub,
+ ((ifevent->opcode == WLC_E_IF_ADD) ?
+ eWLFC_MAC_ENTRY_ACTION_ADD : eWLFC_MAC_ENTRY_ACTION_DEL),
+ ifevent->ifidx, ifevent->role, ea);
+
+ /* dhd already has created an interface by default, for 0 */
+ if (ifevent->ifidx == 0)
+ break;
+ }
+#endif /* PROP_TXSTATUS */
+
+ if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) {
+ if (ifevent->opcode == WLC_E_IF_ADD) {
+ if (dhd_event_ifadd(dhd_pub->info, ifevent, event->ifname,
+ event->addr.octet)) {
+
+ DHD_ERROR(("%s: dhd_event_ifadd failed ifidx: %d %s\n",
+ __FUNCTION__, ifevent->ifidx, event->ifname));
+ return (BCME_ERROR);
+ }
+ } else if (ifevent->opcode == WLC_E_IF_DEL) {
+ dhd_event_ifdel(dhd_pub->info, ifevent, event->ifname,
+ event->addr.octet);
+ } else if (ifevent->opcode == WLC_E_IF_CHANGE) {
+#ifdef WL_CFG80211
+ wl_cfg80211_notify_ifchange(ifevent->ifidx,
+ event->ifname, event->addr.octet, ifevent->bssidx);
+#endif /* WL_CFG80211 */
+ }
+ } else {
+#ifndef PROP_TXSTATUS
+ DHD_ERROR(("%s: Invalid ifidx %d for %s\n",
+ __FUNCTION__, ifevent->ifidx, event->ifname));
+#endif /* !PROP_TXSTATUS */
+ }
+
+ /* send up the if event: btamp user needs it */
+ *ifidx = dhd_ifname2idx(dhd_pub->info, event->ifname);
+ /* push up to external supp/auth */
+ dhd_event(dhd_pub->info, (char *)pvt_data, evlen, *ifidx);
+ break;
+ }
+#ifdef WLMEDIA_HTSF
+ case WLC_E_HTSFSYNC:
+ htsf_update(dhd_pub->info, event_data);
+ break;
+#endif /* WLMEDIA_HTSF */
+ case WLC_E_NDIS_LINK: {
+ uint32 temp = hton32(WLC_E_LINK);
+
+ memcpy((void *)(&pvt_data->event.event_type), &temp,
+ sizeof(pvt_data->event.event_type));
+ }
+ case WLC_E_PFN_NET_FOUND:
+ case WLC_E_PFN_NET_LOST:
+ break;
+#if defined(PNO_SUPPORT)
+ case WLC_E_PFN_BSSID_NET_FOUND:
+ case WLC_E_PFN_BSSID_NET_LOST:
+ case WLC_E_PFN_BEST_BATCHING:
+ dhd_pno_event_handler(dhd_pub, event, (void *)event_data);
+ break;
+#endif
+ /* These are what external supplicant/authenticator wants */
+ /* fall through */
+ case WLC_E_LINK:
+ case WLC_E_DEAUTH:
+ case WLC_E_DEAUTH_IND:
+ case WLC_E_DISASSOC:
+ case WLC_E_DISASSOC_IND:
+ DHD_EVENT(("%s: Link event %d, flags %x, status %x\n",
+ __FUNCTION__, type, flags, status));
+ /* fall through */
+ default:
+ *ifidx = dhd_ifname2idx(dhd_pub->info, event->ifname);
+ /* push up to external supp/auth */
+ dhd_event(dhd_pub->info, (char *)pvt_data, evlen, *ifidx);
+ DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n",
+ __FUNCTION__, type, flags, status));
+ BCM_REFERENCE(flags);
+ BCM_REFERENCE(status);
+
+ break;
+ }
+
+#ifdef SHOW_EVENTS
+ wl_show_host_event(dhd_pub, event, (void *)event_data, raw_event);
+#endif /* SHOW_EVENTS */
+
+ return (BCME_OK);
+}
+
+void
+wl_event_to_host_order(wl_event_msg_t * evt)
+{
+ /* Event struct members passed from dongle to host are stored in network
+ * byte order. Convert all members to host-order.
+ */
+ evt->event_type = ntoh32(evt->event_type);
+ evt->flags = ntoh16(evt->flags);
+ evt->status = ntoh32(evt->status);
+ evt->reason = ntoh32(evt->reason);
+ evt->auth_type = ntoh32(evt->auth_type);
+ evt->datalen = ntoh32(evt->datalen);
+ evt->version = ntoh16(evt->version);
+}
+
+void
+dhd_print_buf(void *pbuf, int len, int bytes_per_line)
+{
+#ifdef DHD_DEBUG
+ int i, j = 0;
+ unsigned char *buf = pbuf;
+
+ if (bytes_per_line == 0) {
+ bytes_per_line = len;
+ }
+
+ for (i = 0; i < len; i++) {
+ printf("%2.2x", *buf++);
+ j++;
+ if (j == bytes_per_line) {
+ printf("\n");
+ j = 0;
+ } else {
+ printf(":");
+ }
+ }
+ printf("\n");
+#endif /* DHD_DEBUG */
+}
+#ifndef strtoul
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+#endif
+
+#ifdef PKT_FILTER_SUPPORT
+/* Convert user's input in hex pattern to byte-size mask */
+static int
+wl_pattern_atoh(char *src, char *dst)
+{
+ int i;
+ if (strncmp(src, "0x", 2) != 0 &&
+ strncmp(src, "0X", 2) != 0) {
+ DHD_ERROR(("Mask invalid format. Needs to start with 0x\n"));
+ return -1;
+ }
+ src = src + 2; /* Skip past 0x */
+ if (strlen(src) % 2 != 0) {
+ DHD_ERROR(("Mask invalid format. Needs to be of even length\n"));
+ return -1;
+ }
+ for (i = 0; *src != '\0'; i++) {
+ char num[3];
+ bcm_strncpy_s(num, sizeof(num), src, 2);
+ num[2] = '\0';
+ dst[i] = (uint8)strtoul(num, NULL, 16);
+ src += 2;
+ }
+ return i;
+}
+
+void
+dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode)
+{
+ char *argv[8];
+ int i = 0;
+ const char *str;
+ int buf_len;
+ int str_len;
+ char *arg_save = 0, *arg_org = 0;
+ int rc;
+ char buf[128];
+ wl_pkt_filter_enable_t enable_parm;
+ wl_pkt_filter_enable_t * pkt_filterp;
+
+ if (!arg)
+ return;
+
+ if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
+ DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+ goto fail;
+ }
+ arg_org = arg_save;
+ memcpy(arg_save, arg, strlen(arg) + 1);
+
+ argv[i] = bcmstrtok(&arg_save, " ", 0);
+
+ i = 0;
+ if (argv[i] == NULL) {
+ DHD_ERROR(("No args provided\n"));
+ goto fail;
+ }
+
+ str = "pkt_filter_enable";
+ str_len = strlen(str);
+ bcm_strncpy_s(buf, sizeof(buf), str, str_len);
+ buf[str_len] = '\0';
+ buf_len = str_len + 1;
+
+ pkt_filterp = (wl_pkt_filter_enable_t *)(buf + str_len + 1);
+
+ /* Parse packet filter id. */
+ enable_parm.id = htod32(strtoul(argv[i], NULL, 0));
+
+ /* Parse enable/disable value. */
+ enable_parm.enable = htod32(enable);
+
+ buf_len += sizeof(enable_parm);
+ memcpy((char *)pkt_filterp,
+ &enable_parm,
+ sizeof(enable_parm));
+
+ /* Enable/disable the specified filter. */
+ rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
+ rc = rc >= 0 ? 0 : rc;
+ if (rc)
+ DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+ __FUNCTION__, arg, rc));
+ else
+ DHD_TRACE(("%s: successfully added pktfilter %s\n",
+ __FUNCTION__, arg));
+
+ /* Contorl the master mode */
+ bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf, sizeof(buf));
+ rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
+ rc = rc >= 0 ? 0 : rc;
+ if (rc)
+ DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+ __FUNCTION__, arg, rc));
+
+fail:
+ if (arg_org)
+ MFREE(dhd->osh, arg_org, strlen(arg) + 1);
+}
+
+void
+dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
+{
+ const char *str;
+ wl_pkt_filter_t pkt_filter;
+ wl_pkt_filter_t *pkt_filterp;
+ int buf_len;
+ int str_len;
+ int rc;
+ uint32 mask_size;
+ uint32 pattern_size;
+ char *argv[8], * buf = 0;
+ int i = 0;
+ char *arg_save = 0, *arg_org = 0;
+#define BUF_SIZE 2048
+
+ if (!arg)
+ return;
+
+ if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
+ DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+ arg_org = arg_save;
+
+ if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) {
+ DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+ memcpy(arg_save, arg, strlen(arg) + 1);
+
+ if (strlen(arg) > BUF_SIZE) {
+ DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf)));
+ goto fail;
+ }
+
+ argv[i] = bcmstrtok(&arg_save, " ", 0);
+ while (argv[i++])
+ argv[i] = bcmstrtok(&arg_save, " ", 0);
+
+ i = 0;
+ if (argv[i] == NULL) {
+ DHD_ERROR(("No args provided\n"));
+ goto fail;
+ }
+
+ str = "pkt_filter_add";
+ str_len = strlen(str);
+ bcm_strncpy_s(buf, BUF_SIZE, str, str_len);
+ buf[ str_len ] = '\0';
+ buf_len = str_len + 1;
+
+ pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
+
+ /* Parse packet filter id. */
+ pkt_filter.id = htod32(strtoul(argv[i], NULL, 0));
+
+ if (argv[++i] == NULL) {
+ DHD_ERROR(("Polarity not provided\n"));
+ goto fail;
+ }
+
+ /* Parse filter polarity. */
+ pkt_filter.negate_match = htod32(strtoul(argv[i], NULL, 0));
+
+ if (argv[++i] == NULL) {
+ DHD_ERROR(("Filter type not provided\n"));
+ goto fail;
+ }
+
+ /* Parse filter type. */
+ pkt_filter.type = htod32(strtoul(argv[i], NULL, 0));
+
+ if (argv[++i] == NULL) {
+ DHD_ERROR(("Offset not provided\n"));
+ goto fail;
+ }
+
+ /* Parse pattern filter offset. */
+ pkt_filter.u.pattern.offset = htod32(strtoul(argv[i], NULL, 0));
+
+ if (argv[++i] == NULL) {
+ DHD_ERROR(("Bitmask not provided\n"));
+ goto fail;
+ }
+
+ /* Parse pattern filter mask. */
+ mask_size =
+ htod32(wl_pattern_atoh(argv[i], (char *) pkt_filterp->u.pattern.mask_and_pattern));
+
+ if (argv[++i] == NULL) {
+ DHD_ERROR(("Pattern not provided\n"));
+ goto fail;
+ }
+
+ /* Parse pattern filter pattern. */
+ pattern_size =
+ htod32(wl_pattern_atoh(argv[i],
+ (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
+
+ if (mask_size != pattern_size) {
+ DHD_ERROR(("Mask and pattern not the same size\n"));
+ goto fail;
+ }
+
+ pkt_filter.u.pattern.size_bytes = mask_size;
+ buf_len += WL_PKT_FILTER_FIXED_LEN;
+ buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
+
+ /* Keep-alive attributes are set in local variable (keep_alive_pkt), and
+ ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
+ ** guarantee that the buffer is properly aligned.
+ */
+ memcpy((char *)pkt_filterp,
+ &pkt_filter,
+ WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+
+ rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
+ rc = rc >= 0 ? 0 : rc;
+
+ if (rc)
+ DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+ __FUNCTION__, arg, rc));
+ else
+ DHD_TRACE(("%s: successfully added pktfilter %s\n",
+ __FUNCTION__, arg));
+
+fail:
+ if (arg_org)
+ MFREE(dhd->osh, arg_org, strlen(arg) + 1);
+
+ if (buf)
+ MFREE(dhd->osh, buf, BUF_SIZE);
+}
+
+void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id)
+{
+ char iovbuf[32];
+ int ret;
+
+ bcm_mkiovar("pkt_filter_delete", (char *)&id, 4, iovbuf, sizeof(iovbuf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ if (ret < 0) {
+ DHD_ERROR(("%s: Failed to delete filter ID:%d, ret=%d\n",
+ __FUNCTION__, id, ret));
+ }
+}
+#endif /* PKT_FILTER_SUPPORT */
+
+/* ========================== */
+/* ==== ARP OFFLOAD SUPPORT = */
+/* ========================== */
+#ifdef ARP_OFFLOAD_SUPPORT
+void
+dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode)
+{
+ char iovbuf[DHD_IOVAR_BUF_SIZE];
+ int iovar_len;
+ int retcode;
+
+ iovar_len = bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+ if (!iovar_len) {
+ DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
+ __FUNCTION__, sizeof(iovbuf)));
+ return;
+ }
+
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iovar_len, TRUE, 0);
+ retcode = retcode >= 0 ? 0 : retcode;
+ if (retcode)
+ DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, retcode = %d\n",
+ __FUNCTION__, arp_mode, retcode));
+ else
+ DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
+ __FUNCTION__, arp_mode));
+}
+
+void
+dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
+{
+ char iovbuf[DHD_IOVAR_BUF_SIZE];
+ int iovar_len;
+ int retcode;
+
+ iovar_len = bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
+ if (!iovar_len) {
+ DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
+ __FUNCTION__, sizeof(iovbuf)));
+ return;
+ }
+
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iovar_len, TRUE, 0);
+ retcode = retcode >= 0 ? 0 : retcode;
+ if (retcode)
+ DHD_TRACE(("%s: failed to enabe ARP offload to %d, retcode = %d\n",
+ __FUNCTION__, arp_enable, retcode));
+ else
+ DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
+ __FUNCTION__, arp_enable));
+ if (arp_enable) {
+ uint32 version;
+ bcm_mkiovar("arp_version", 0, 0, iovbuf, sizeof(iovbuf));
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
+ if (retcode) {
+ DHD_INFO(("%s: fail to get version (maybe version 1:retcode = %d\n",
+ __FUNCTION__, retcode));
+ dhd->arp_version = 1;
+ }
+ else {
+ memcpy(&version, iovbuf, sizeof(version));
+ DHD_INFO(("%s: ARP Version= %x\n", __FUNCTION__, version));
+ dhd->arp_version = version;
+ }
+ }
+}
+
+void
+dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx)
+{
+ int ret = 0;
+ int iov_len = 0;
+ char iovbuf[DHD_IOVAR_BUF_SIZE];
+
+ if (dhd == NULL) return;
+ if (dhd->arp_version == 1)
+ idx = 0;
+
+ iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf));
+ if (!iov_len) {
+ DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
+ __FUNCTION__, sizeof(iovbuf)));
+ return;
+ }
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx)) < 0)
+ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+}
+
+void
+dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx)
+{
+ int ret = 0;
+ int iov_len = 0;
+ char iovbuf[DHD_IOVAR_BUF_SIZE];
+
+ if (dhd == NULL) return;
+ if (dhd->arp_version == 1)
+ idx = 0;
+
+ iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf));
+ if (!iov_len) {
+ DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
+ __FUNCTION__, sizeof(iovbuf)));
+ return;
+ }
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx)) < 0)
+ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+}
+
+void
+dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx)
+{
+ int iov_len = 0;
+ char iovbuf[DHD_IOVAR_BUF_SIZE];
+ int retcode;
+
+
+ if (dhd == NULL) return;
+ if (dhd->arp_version == 1)
+ idx = 0;
+ iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr,
+ sizeof(ipaddr), iovbuf, sizeof(iovbuf));
+ if (!iov_len) {
+ DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
+ __FUNCTION__, sizeof(iovbuf)));
+ return;
+ }
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx);
+
+ if (retcode)
+ DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n",
+ __FUNCTION__, retcode));
+ else
+ DHD_TRACE(("%s: sARP H ipaddr entry added \n",
+ __FUNCTION__));
+}
+
+int
+dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx)
+{
+ int retcode, i;
+ int iov_len;
+ uint32 *ptr32 = buf;
+ bool clr_bottom = FALSE;
+
+ if (!buf)
+ return -1;
+ if (dhd == NULL) return -1;
+ if (dhd->arp_version == 1)
+ idx = 0;
+
+ iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen);
+ BCM_REFERENCE(iov_len);
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, FALSE, idx);
+
+ if (retcode) {
+ DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n",
+ __FUNCTION__, retcode));
+
+ return -1;
+ }
+
+ /* clean up the buf, ascii reminder */
+ for (i = 0; i < MAX_IPV4_ENTRIES; i++) {
+ if (!clr_bottom) {
+ if (*ptr32 == 0)
+ clr_bottom = TRUE;
+ } else {
+ *ptr32 = 0;
+ }
+ ptr32++;
+ }
+
+ return 0;
+}
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+/*
+ * Neighbor Discovery Offload: enable NDO feature
+ * Called by ipv6 event handler when interface comes up/goes down
+ */
+int
+dhd_ndo_enable(dhd_pub_t * dhd, int ndo_enable)
+{
+ char iovbuf[DHD_IOVAR_BUF_SIZE];
+ int iov_len;
+ int retcode;
+
+ if (dhd == NULL)
+ return -1;
+
+ iov_len = bcm_mkiovar("ndoe", (char *)&ndo_enable, 4, iovbuf, sizeof(iovbuf));
+ if (!iov_len) {
+ DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
+ __FUNCTION__, sizeof(iovbuf)));
+ return -1;
+ }
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0);
+ if (retcode)
+ DHD_ERROR(("%s: failed to enabe ndo to %d, retcode = %d\n",
+ __FUNCTION__, ndo_enable, retcode));
+ else
+ DHD_TRACE(("%s: successfully enabed ndo offload to %d\n",
+ __FUNCTION__, ndo_enable));
+
+ return retcode;
+}
+
+/*
+ * Neighbor Discover Offload: enable NDO feature
+ * Called by ipv6 event handler when interface comes up
+ */
+int
+dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipv6addr, int idx)
+{
+ int iov_len = 0;
+ char iovbuf[DHD_IOVAR_BUF_SIZE];
+ int retcode;
+
+ if (dhd == NULL)
+ return -1;
+
+ iov_len = bcm_mkiovar("nd_hostip", (char *)ipv6addr,
+ IPV6_ADDR_LEN, iovbuf, sizeof(iovbuf));
+ if (!iov_len) {
+ DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
+ __FUNCTION__, sizeof(iovbuf)));
+ return -1;
+ }
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx);
+
+ if (retcode)
+ DHD_ERROR(("%s: ndo ip addr add failed, retcode = %d\n",
+ __FUNCTION__, retcode));
+ else
+ DHD_TRACE(("%s: ndo ipaddr entry added \n",
+ __FUNCTION__));
+
+ return retcode;
+}
+/*
+ * Neighbor Discover Offload: enable NDO feature
+ * Called by ipv6 event handler when interface goes down
+ */
+int
+dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx)
+{
+ int iov_len = 0;
+ char iovbuf[DHD_IOVAR_BUF_SIZE];
+ int retcode;
+
+ if (dhd == NULL)
+ return -1;
+
+ iov_len = bcm_mkiovar("nd_hostip_clear", NULL,
+ 0, iovbuf, sizeof(iovbuf));
+ if (!iov_len) {
+ DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
+ __FUNCTION__, sizeof(iovbuf)));
+ return -1;
+ }
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx);
+
+ if (retcode)
+ DHD_ERROR(("%s: ndo ip addr remove failed, retcode = %d\n",
+ __FUNCTION__, retcode));
+ else
+ DHD_TRACE(("%s: ndo ipaddr entry removed \n",
+ __FUNCTION__));
+
+ return retcode;
+}
+
+/* send up locally generated event */
+void
+dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
+{
+ switch (ntoh32(event->event_type)) {
+ default:
+ break;
+ }
+
+ /* Call per-port handler. */
+ dhd_sendup_event(dhdp, event, data);
+}
+
+
+/*
+ * returns = TRUE if associated, FALSE if not associated
+ */
+bool dhd_is_associated(dhd_pub_t *dhd, uint8 ifidx, int *retval)
+{
+ char bssid[6], zbuf[6];
+ int ret = -1;
+
+ bzero(bssid, 6);
+ bzero(zbuf, 6);
+
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, (char *)&bssid,
+ ETHER_ADDR_LEN, FALSE, ifidx);
+ DHD_TRACE((" %s WLC_GET_BSSID ioctl res = %d\n", __FUNCTION__, ret));
+
+ if (ret == BCME_NOTASSOCIATED) {
+ DHD_TRACE(("%s: not associated! res:%d\n", __FUNCTION__, ret));
+ }
+
+ if (retval)
+ *retval = ret;
+
+ if (ret < 0)
+ return FALSE;
+
+ if ((memcmp(bssid, zbuf, ETHER_ADDR_LEN) == 0)) {
+ DHD_TRACE(("%s: WLC_GET_BSSID ioctl returned zero bssid\n", __FUNCTION__));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* Function to estimate possible DTIM_SKIP value */
+int
+dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd)
+{
+ int bcn_li_dtim = 1; /* deafult no dtim skip setting */
+ int ret = -1;
+ int dtim_period = 0;
+ int ap_beacon = 0;
+ int allowed_skip_dtim_cnt = 0;
+ /* Check if associated */
+ if (dhd_is_associated(dhd, 0, NULL) == FALSE) {
+ DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+
+ /* read associated AP beacon interval */
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BCNPRD,
+ &ap_beacon, sizeof(ap_beacon), FALSE, 0)) < 0) {
+ DHD_ERROR(("%s get beacon failed code %d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+
+ /* read associated ap's dtim setup */
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_DTIMPRD,
+ &dtim_period, sizeof(dtim_period), FALSE, 0)) < 0) {
+ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+
+ /* if not assocated just eixt */
+ if (dtim_period == 0) {
+ goto exit;
+ }
+
+ /* attemp to use platform defined dtim skip interval */
+ bcn_li_dtim = dhd->suspend_bcn_li_dtim;
+
+ /* check if sta listen interval fits into AP dtim */
+ if (dtim_period > CUSTOM_LISTEN_INTERVAL) {
+ /* AP DTIM to big for our Listen Interval : no dtim skiping */
+ bcn_li_dtim = NO_DTIM_SKIP;
+ DHD_ERROR(("%s DTIM=%d > Listen=%d : too big ...\n",
+ __FUNCTION__, dtim_period, CUSTOM_LISTEN_INTERVAL));
+ goto exit;
+ }
+
+ if ((dtim_period * ap_beacon * bcn_li_dtim) > MAX_DTIM_ALLOWED_INTERVAL) {
+ allowed_skip_dtim_cnt = MAX_DTIM_ALLOWED_INTERVAL / (dtim_period * ap_beacon);
+ bcn_li_dtim = (allowed_skip_dtim_cnt != 0) ? allowed_skip_dtim_cnt : NO_DTIM_SKIP;
+ }
+
+ if ((bcn_li_dtim * dtim_period) > CUSTOM_LISTEN_INTERVAL) {
+ /* Round up dtim_skip to fit into STAs Listen Interval */
+ bcn_li_dtim = (int)(CUSTOM_LISTEN_INTERVAL / dtim_period);
+ DHD_TRACE(("%s agjust dtim_skip as %d\n", __FUNCTION__, bcn_li_dtim));
+ }
+
+ DHD_ERROR(("%s beacon=%d bcn_li_dtim=%d DTIM=%d Listen=%d\n",
+ __FUNCTION__, ap_beacon, bcn_li_dtim, dtim_period, CUSTOM_LISTEN_INTERVAL));
+
+exit:
+ return bcn_li_dtim;
+}
+
+/* Check if the mode supports STA MODE */
+bool dhd_support_sta_mode(dhd_pub_t *dhd)
+{
+
+#ifdef WL_CFG80211
+ if (!(dhd->op_mode & DHD_FLAG_STA_MODE))
+ return FALSE;
+ else
+#endif /* WL_CFG80211 */
+ return TRUE;
+}
+
+#if defined(KEEP_ALIVE)
+int dhd_keep_alive_onoff(dhd_pub_t *dhd)
+{
+ char buf[256];
+ const char *str;
+ wl_mkeep_alive_pkt_t mkeep_alive_pkt = {0};
+ wl_mkeep_alive_pkt_t *mkeep_alive_pktp;
+ int buf_len;
+ int str_len;
+ int res = -1;
+
+ if (!dhd_support_sta_mode(dhd))
+ return res;
+
+ DHD_TRACE(("%s execution\n", __FUNCTION__));
+
+ str = "mkeep_alive";
+ str_len = strlen(str);
+ strncpy(buf, str, str_len);
+ buf[ str_len ] = '\0';
+ mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1);
+ mkeep_alive_pkt.period_msec = CUSTOM_KEEP_ALIVE_SETTING;
+ buf_len = str_len + 1;
+ mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
+ mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
+ /* Setup keep alive zero for null packet generation */
+ mkeep_alive_pkt.keep_alive_id = 0;
+ mkeep_alive_pkt.len_bytes = 0;
+ buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
+ bzero(mkeep_alive_pkt.data, sizeof(mkeep_alive_pkt.data));
+ /* Keep-alive attributes are set in local variable (mkeep_alive_pkt), and
+ * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no
+ * guarantee that the buffer is properly aligned.
+ */
+ memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN);
+
+ res = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
+
+ return res;
+}
+#endif /* defined(KEEP_ALIVE) */
+/* Android ComboSCAN support */
+
+/*
+ * data parsing from ComboScan tlv list
+*/
+int
+wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token,
+ int input_size, int *bytes_left)
+{
+ char* str;
+ uint16 short_temp;
+ uint32 int_temp;
+
+ if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) {
+ DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+ return -1;
+ }
+ str = *list_str;
+
+ /* Clean all dest bytes */
+ memset(dst, 0, dst_size);
+ while (*bytes_left > 0) {
+
+ if (str[0] != token) {
+ DHD_TRACE(("%s NOT Type=%d get=%d left_parse=%d \n",
+ __FUNCTION__, token, str[0], *bytes_left));
+ return -1;
+ }
+
+ *bytes_left -= 1;
+ str += 1;
+
+ if (input_size == 1) {
+ memcpy(dst, str, input_size);
+ }
+ else if (input_size == 2) {
+ memcpy(dst, (char *)htod16(memcpy(&short_temp, str, input_size)),
+ input_size);
+ }
+ else if (input_size == 4) {
+ memcpy(dst, (char *)htod32(memcpy(&int_temp, str, input_size)),
+ input_size);
+ }
+
+ *bytes_left -= input_size;
+ str += input_size;
+ *list_str = str;
+ return 1;
+ }
+ return 1;
+}
+
+/*
+ * channel list parsing from cscan tlv list
+*/
+int
+wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list,
+ int channel_num, int *bytes_left)
+{
+ char* str;
+ int idx = 0;
+
+ if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) {
+ DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+ return -1;
+ }
+ str = *list_str;
+
+ while (*bytes_left > 0) {
+
+ if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) {
+ *list_str = str;
+ DHD_TRACE(("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0]));
+ return idx;
+ }
+ /* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */
+ *bytes_left -= 1;
+ str += 1;
+
+ if (str[0] == 0) {
+ /* All channels */
+ channel_list[idx] = 0x0;
+ }
+ else {
+ channel_list[idx] = (uint16)str[0];
+ DHD_TRACE(("%s channel=%d \n", __FUNCTION__, channel_list[idx]));
+ }
+ *bytes_left -= 1;
+ str += 1;
+
+ if (idx++ > 255) {
+ DHD_ERROR(("%s Too many channels \n", __FUNCTION__));
+ return -1;
+ }
+ }
+
+ *list_str = str;
+ return idx;
+}
+
+/*
+ * SSIDs list parsing from cscan tlv list
+ */
+int
+wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left)
+{
+ char* str;
+ int idx = 0;
+
+ if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) {
+ DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+ return -1;
+ }
+ str = *list_str;
+ while (*bytes_left > 0) {
+
+ if (str[0] != CSCAN_TLV_TYPE_SSID_IE) {
+ *list_str = str;
+ DHD_TRACE(("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0]));
+ return idx;
+ }
+
+ /* Get proper CSCAN_TLV_TYPE_SSID_IE */
+ *bytes_left -= 1;
+ str += 1;
+
+ if (str[0] == 0) {
+ /* Broadcast SSID */
+ ssid[idx].SSID_len = 0;
+ memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN);
+ *bytes_left -= 1;
+ str += 1;
+
+ DHD_TRACE(("BROADCAST SCAN left=%d\n", *bytes_left));
+ }
+ else if (str[0] <= DOT11_MAX_SSID_LEN) {
+ /* Get proper SSID size */
+ ssid[idx].SSID_len = str[0];
+ *bytes_left -= 1;
+ str += 1;
+
+ /* Get SSID */
+ if (ssid[idx].SSID_len > *bytes_left) {
+ DHD_ERROR(("%s out of memory range len=%d but left=%d\n",
+ __FUNCTION__, ssid[idx].SSID_len, *bytes_left));
+ return -1;
+ }
+
+ memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len);
+
+ *bytes_left -= ssid[idx].SSID_len;
+ str += ssid[idx].SSID_len;
+
+ DHD_TRACE(("%s :size=%d left=%d\n",
+ (char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left));
+ }
+ else {
+ DHD_ERROR(("### SSID size more that %d\n", str[0]));
+ return -1;
+ }
+
+ if (idx++ > max) {
+ DHD_ERROR(("%s number of SSIDs more that %d\n", __FUNCTION__, idx));
+ return -1;
+ }
+ }
+
+ *list_str = str;
+ return idx;
+}
+
+/* Parse a comma-separated list from list_str into ssid array, starting
+ * at index idx. Max specifies size of the ssid array. Parses ssids
+ * and returns updated idx; if idx >= max not all fit, the excess have
+ * not been copied. Returns -1 on empty string, or on ssid too long.
+ */
+int
+wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max)
+{
+ char* str, *ptr;
+
+ if ((list_str == NULL) || (*list_str == NULL))
+ return -1;
+
+ for (str = *list_str; str != NULL; str = ptr) {
+
+ /* check for next TAG */
+ if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) {
+ *list_str = str + strlen(GET_CHANNEL);
+ return idx;
+ }
+
+ if ((ptr = strchr(str, ',')) != NULL) {
+ *ptr++ = '\0';
+ }
+
+ if (strlen(str) > DOT11_MAX_SSID_LEN) {
+ DHD_ERROR(("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN));
+ return -1;
+ }
+
+ if (strlen(str) == 0)
+ ssid[idx].SSID_len = 0;
+
+ if (idx < max) {
+ bzero(ssid[idx].SSID, sizeof(ssid[idx].SSID));
+ strncpy((char*)ssid[idx].SSID, str, sizeof(ssid[idx].SSID) - 1);
+ ssid[idx].SSID_len = strlen(str);
+ }
+ idx++;
+ }
+ return idx;
+}
+
+/*
+ * Parse channel list from iwpriv CSCAN
+ */
+int
+wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num)
+{
+ int num;
+ int val;
+ char* str;
+ char* endptr = NULL;
+
+ if ((list_str == NULL)||(*list_str == NULL))
+ return -1;
+
+ str = *list_str;
+ num = 0;
+ while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) {
+ val = (int)strtoul(str, &endptr, 0);
+ if (endptr == str) {
+ printf("could not parse channel number starting at"
+ " substring \"%s\" in list:\n%s\n",
+ str, *list_str);
+ return -1;
+ }
+ str = endptr + strspn(endptr, " ,");
+
+ if (num == channel_num) {
+ DHD_ERROR(("too many channels (more than %d) in channel list:\n%s\n",
+ channel_num, *list_str));
+ return -1;
+ }
+
+ channel_list[num++] = (uint16)val;
+ }
+ *list_str = str;
+ return num;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
new file mode 100644
index 000000000000..307d2f1b8b8d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
@@ -0,0 +1,300 @@
+/*
+* Customer code to add GPIO control during WLAN start/stop
+* Copyright (C) 1999-2016, Broadcom Corporation
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2 (the "GPL"),
+* available at http://www.broadcom.com/licenses/GPLv2.php, with the
+* following added to such license:
+*
+* As a special exception, the copyright holders of this software give you
+* permission to link this software with independent modules, and to copy and
+* distribute the resulting executable under terms of your choice, provided that
+* you also meet, for each linked independent module, the terms and conditions of
+* the license of that module. An independent module is a module which is not
+* derived from this software. The special exception does not apply to any
+* modifications of the software.
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a license
+* other than the GPL, without Broadcom's express prior written consent.
+*
+* $Id: dhd_custom_gpio.c 493803 2014-07-29 12:31:48Z $
+*/
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_linux.h>
+
+#include <wlioctl.h>
+#include <wl_iw.h>
+
+#define WL_ERROR(x) printf x
+#define WL_TRACE(x)
+
+#if defined(CUSTOMER_HW2)
+
+
+#endif
+
+#if defined(OOB_INTR_ONLY)
+
+#if defined(BCMLXSDMMC)
+extern int sdioh_mmc_irq(int irq);
+#endif /* (BCMLXSDMMC) */
+
+#if defined(CUSTOMER_HW3)
+#include <mach/gpio.h>
+#endif
+
+/* Customer specific Host GPIO defintion */
+static int dhd_oob_gpio_num = -1;
+
+module_param(dhd_oob_gpio_num, int, 0644);
+MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
+
+/* This function will return:
+ * 1) return : Host gpio interrupt number per customer platform
+ * 2) irq_flags_ptr : Type of Host interrupt as Level or Edge
+ *
+ * NOTE :
+ * Customer should check his platform definitions
+ * and his Host Interrupt spec
+ * to figure out the proper setting for his platform.
+ * Broadcom provides just reference settings as example.
+ *
+ */
+int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr)
+{
+ int host_oob_irq = 0;
+
+#if defined(CUSTOMER_HW2)
+ host_oob_irq = wifi_platform_get_irq_number(adapter, irq_flags_ptr);
+
+#else
+#if defined(CUSTOM_OOB_GPIO_NUM)
+ if (dhd_oob_gpio_num < 0) {
+ dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
+ }
+#endif /* CUSTOMER_OOB_GPIO_NUM */
+
+ if (dhd_oob_gpio_num < 0) {
+ WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
+ __FUNCTION__));
+ return (dhd_oob_gpio_num);
+ }
+
+ WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n",
+ __FUNCTION__, dhd_oob_gpio_num));
+
+#if defined(CUSTOMER_HW3)
+ gpio_request(dhd_oob_gpio_num, "oob irq");
+ host_oob_irq = gpio_to_irq(dhd_oob_gpio_num);
+ gpio_direction_input(dhd_oob_gpio_num);
+#endif /* defined CUSTOMER_HW3 */
+#endif
+
+ return (host_oob_irq);
+}
+#endif
+
+/* Customer function to control hw specific wlan gpios */
+int
+dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff)
+{
+ int err = 0;
+
+ return err;
+}
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+/* Function to get custom MAC address */
+int
+dhd_custom_get_mac_address(void *adapter, unsigned char *buf)
+{
+ int ret = 0;
+
+ WL_TRACE(("%s Enter\n", __FUNCTION__));
+ if (!buf)
+ return -EINVAL;
+
+ /* Customer access to MAC address stored outside of DHD driver */
+#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+ ret = wifi_platform_get_mac_addr(adapter, buf);
+#endif
+
+#ifdef EXAMPLE_GET_MAC
+ /* EXAMPLE code */
+ {
+ struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
+ bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
+ }
+#endif /* EXAMPLE_GET_MAC */
+
+ return ret;
+}
+#endif /* GET_CUSTOM_MAC_ENABLE */
+
+/* Customized Locale table : OPTIONAL feature */
+const struct cntry_locales_custom translate_custom_table[] = {
+/* Table should be filled out based on custom platform regulatory requirement */
+#ifdef EXAMPLE_TABLE
+ {"", "XY", 4}, /* Universal if Country code is unknown or empty */
+ {"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
+ {"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
+ {"EU", "EU", 5}, /* European union countries to : EU regrev 05 */
+ {"AT", "EU", 5},
+ {"BE", "EU", 5},
+ {"BG", "EU", 5},
+ {"CY", "EU", 5},
+ {"CZ", "EU", 5},
+ {"DK", "EU", 5},
+ {"EE", "EU", 5},
+ {"FI", "EU", 5},
+ {"FR", "EU", 5},
+ {"DE", "EU", 5},
+ {"GR", "EU", 5},
+ {"HU", "EU", 5},
+ {"IE", "EU", 5},
+ {"IT", "EU", 5},
+ {"LV", "EU", 5},
+ {"LI", "EU", 5},
+ {"LT", "EU", 5},
+ {"LU", "EU", 5},
+ {"MT", "EU", 5},
+ {"NL", "EU", 5},
+ {"PL", "EU", 5},
+ {"PT", "EU", 5},
+ {"RO", "EU", 5},
+ {"SK", "EU", 5},
+ {"SI", "EU", 5},
+ {"ES", "EU", 5},
+ {"SE", "EU", 5},
+ {"GB", "EU", 5},
+ {"KR", "XY", 3},
+ {"AU", "XY", 3},
+ {"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
+ {"TW", "XY", 3},
+ {"AR", "XY", 3},
+ {"MX", "XY", 3},
+ {"IL", "IL", 0},
+ {"CH", "CH", 0},
+ {"TR", "TR", 0},
+ {"NO", "NO", 0},
+#endif /* EXMAPLE_TABLE */
+#if defined(CUSTOMER_HW2)
+#if defined(BCM4335_CHIP)
+ {"", "XZ", 11}, /* Universal if Country code is unknown or empty */
+#endif
+ {"AE", "AE", 1},
+ {"AR", "AR", 1},
+ {"AT", "AT", 1},
+ {"AU", "AU", 2},
+ {"BE", "BE", 1},
+ {"BG", "BG", 1},
+ {"BN", "BN", 1},
+ {"CA", "CA", 2},
+ {"CH", "CH", 1},
+ {"CY", "CY", 1},
+ {"CZ", "CZ", 1},
+ {"DE", "DE", 3},
+ {"DK", "DK", 1},
+ {"EE", "EE", 1},
+ {"ES", "ES", 1},
+ {"FI", "FI", 1},
+ {"FR", "FR", 1},
+ {"GB", "GB", 1},
+ {"GR", "GR", 1},
+ {"HR", "HR", 1},
+ {"HU", "HU", 1},
+ {"IE", "IE", 1},
+ {"IS", "IS", 1},
+ {"IT", "IT", 1},
+ {"ID", "ID", 1},
+ {"JP", "JP", 8},
+ {"KR", "KR", 24},
+ {"KW", "KW", 1},
+ {"LI", "LI", 1},
+ {"LT", "LT", 1},
+ {"LU", "LU", 1},
+ {"LV", "LV", 1},
+ {"MA", "MA", 1},
+ {"MT", "MT", 1},
+ {"MX", "MX", 1},
+ {"NL", "NL", 1},
+ {"NO", "NO", 1},
+ {"PL", "PL", 1},
+ {"PT", "PT", 1},
+ {"PY", "PY", 1},
+ {"RO", "RO", 1},
+ {"SE", "SE", 1},
+ {"SI", "SI", 1},
+ {"SK", "SK", 1},
+ {"TR", "TR", 7},
+ {"TW", "TW", 1},
+ {"IR", "XZ", 11}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */
+ {"SD", "XZ", 11}, /* Universal if Country code is SUDAN */
+ {"SY", "XZ", 11}, /* Universal if Country code is SYRIAN ARAB REPUBLIC */
+ {"GL", "XZ", 11}, /* Universal if Country code is GREENLAND */
+ {"PS", "XZ", 11}, /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */
+ {"TL", "XZ", 11}, /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */
+ {"MH", "XZ", 11}, /* Universal if Country code is MARSHALL ISLANDS */
+#ifdef BCM4330_CHIP
+ {"RU", "RU", 1},
+ {"US", "US", 5}
+#endif
+#endif
+};
+
+
+/* Customized Locale convertor
+* input : ISO 3166-1 country abbreviation
+* output: customized cspec
+*/
+void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec)
+{
+#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+
+ struct cntry_locales_custom *cloc_ptr;
+
+ if (!cspec)
+ return;
+
+ cloc_ptr = wifi_platform_get_country_code(adapter, country_iso_code);
+ if (cloc_ptr) {
+ strlcpy(cspec->ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ);
+ cspec->rev = cloc_ptr->custom_locale_rev;
+ }
+ return;
+#else
+ int size, i;
+
+ size = ARRAYSIZE(translate_custom_table);
+
+ if (cspec == 0)
+ return;
+
+ if (size == 0)
+ return;
+
+ for (i = 0; i < size; i++) {
+ if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
+ memcpy(cspec->ccode,
+ translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
+ cspec->rev = translate_custom_table[i].custom_locale_rev;
+ return;
+ }
+ }
+#ifdef EXAMPLE_TABLE
+ /* if no country code matched return first universal code from translate_custom_table */
+ memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ);
+ cspec->rev = translate_custom_table[0].custom_locale_rev;
+#endif /* EXMAPLE_TABLE */
+ return;
+#endif /* defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) */
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_dbg.h b/drivers/net/wireless/bcmdhd/dhd_dbg.h
new file mode 100644
index 000000000000..164f8aa8c07e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_dbg.h
@@ -0,0 +1,123 @@
+/*
+ * Debug/trace/assert driver definitions for Dongle Host Driver.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_dbg.h 424863 2013-09-19 20:06:14Z $
+ */
+
+#ifndef _dhd_dbg_
+#define _dhd_dbg_
+
+#define USE_NET_RATELIMIT 1
+
+#if defined(DHD_DEBUG)
+
+#define DHD_ERROR(args) do {if ((dhd_msg_level & DHD_ERROR_VAL) && USE_NET_RATELIMIT) \
+ printf args;} while (0)
+#define DHD_TRACE(args) do {if (dhd_msg_level & DHD_TRACE_VAL) printf args;} while (0)
+#define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0)
+#define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0)
+#define DHD_CTL(args) do {if (dhd_msg_level & DHD_CTL_VAL) printf args;} while (0)
+#define DHD_TIMER(args) do {if (dhd_msg_level & DHD_TIMER_VAL) printf args;} while (0)
+#define DHD_HDRS(args) do {if (dhd_msg_level & DHD_HDRS_VAL) printf args;} while (0)
+#define DHD_BYTES(args) do {if (dhd_msg_level & DHD_BYTES_VAL) printf args;} while (0)
+#define DHD_INTR(args) do {if (dhd_msg_level & DHD_INTR_VAL) printf args;} while (0)
+#define DHD_GLOM(args) do {if (dhd_msg_level & DHD_GLOM_VAL) printf args;} while (0)
+#define DHD_EVENT(args) do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0)
+#define DHD_BTA(args) do {if (dhd_msg_level & DHD_BTA_VAL) printf args;} while (0)
+#define DHD_ISCAN(args) do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0)
+#define DHD_ARPOE(args) do {if (dhd_msg_level & DHD_ARPOE_VAL) printf args;} while (0)
+#define DHD_REORDER(args) do {if (dhd_msg_level & DHD_REORDER_VAL) printf args;} while (0)
+#define DHD_PNO(args) do {if (dhd_msg_level & DHD_PNO_VAL) printf args;} while (0)
+
+#define DHD_TRACE_HW4 DHD_TRACE
+
+#define DHD_ERROR_ON() (dhd_msg_level & DHD_ERROR_VAL)
+#define DHD_TRACE_ON() (dhd_msg_level & DHD_TRACE_VAL)
+#define DHD_INFO_ON() (dhd_msg_level & DHD_INFO_VAL)
+#define DHD_DATA_ON() (dhd_msg_level & DHD_DATA_VAL)
+#define DHD_CTL_ON() (dhd_msg_level & DHD_CTL_VAL)
+#define DHD_TIMER_ON() (dhd_msg_level & DHD_TIMER_VAL)
+#define DHD_HDRS_ON() (dhd_msg_level & DHD_HDRS_VAL)
+#define DHD_BYTES_ON() (dhd_msg_level & DHD_BYTES_VAL)
+#define DHD_INTR_ON() (dhd_msg_level & DHD_INTR_VAL)
+#define DHD_GLOM_ON() (dhd_msg_level & DHD_GLOM_VAL)
+#define DHD_EVENT_ON() (dhd_msg_level & DHD_EVENT_VAL)
+#define DHD_BTA_ON() (dhd_msg_level & DHD_BTA_VAL)
+#define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL)
+#define DHD_ARPOE_ON() (dhd_msg_level & DHD_ARPOE_VAL)
+#define DHD_REORDER_ON() (dhd_msg_level & DHD_REORDER_VAL)
+#define DHD_NOCHECKDIED_ON() (dhd_msg_level & DHD_NOCHECKDIED_VAL)
+#define DHD_PNO_ON() (dhd_msg_level & DHD_PNO_VAL)
+
+#else /* defined(BCMDBG) || defined(DHD_DEBUG) */
+
+#define DHD_ERROR(args) do {if (USE_NET_RATELIMIT) printf args;} while (0)
+#define DHD_TRACE(args)
+#define DHD_INFO(args)
+#define DHD_DATA(args)
+#define DHD_CTL(args)
+#define DHD_TIMER(args)
+#define DHD_HDRS(args)
+#define DHD_BYTES(args)
+#define DHD_INTR(args)
+#define DHD_GLOM(args)
+#define DHD_EVENT(args)
+#define DHD_BTA(args)
+#define DHD_ISCAN(args)
+#define DHD_ARPOE(args)
+#define DHD_REORDER(args)
+#define DHD_PNO(args)
+
+#define DHD_TRACE_HW4 DHD_TRACE
+
+#define DHD_ERROR_ON() 0
+#define DHD_TRACE_ON() 0
+#define DHD_INFO_ON() 0
+#define DHD_DATA_ON() 0
+#define DHD_CTL_ON() 0
+#define DHD_TIMER_ON() 0
+#define DHD_HDRS_ON() 0
+#define DHD_BYTES_ON() 0
+#define DHD_INTR_ON() 0
+#define DHD_GLOM_ON() 0
+#define DHD_EVENT_ON() 0
+#define DHD_BTA_ON() 0
+#define DHD_ISCAN_ON() 0
+#define DHD_ARPOE_ON() 0
+#define DHD_REORDER_ON() 0
+#define DHD_NOCHECKDIED_ON() 0
+#define DHD_PNO_ON() 0
+
+#endif
+
+#define DHD_LOG(args)
+
+#define DHD_BLOG(cp, size)
+
+#define DHD_NONE(args)
+extern int dhd_msg_level;
+
+/* Defines msg bits */
+#include <dhdioctl.h>
+
+#endif /* _dhd_dbg_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_ip.c b/drivers/net/wireless/bcmdhd/dhd_ip.c
new file mode 100644
index 000000000000..45d26c5b40ba
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_ip.c
@@ -0,0 +1,965 @@
+/*
+ * IP Packet Parser Module.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_ip.c 529177 2015-01-26 12:49:53Z $
+ */
+#include <typedefs.h>
+#include <osl.h>
+
+#include <proto/ethernet.h>
+#include <proto/vlan.h>
+#include <proto/802.3.h>
+#include <proto/bcmip.h>
+#include <bcmendian.h>
+
+#include <dhd_dbg.h>
+
+#include <dhd_ip.h>
+
+#ifdef DHDTCPACK_SUPPRESS
+#include <dhd_bus.h>
+#include <proto/bcmtcp.h>
+#endif /* DHDTCPACK_SUPPRESS */
+
+/* special values */
+/* 802.3 llc/snap header */
+static const uint8 llc_snap_hdr[SNAP_HDR_LEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+
+pkt_frag_t pkt_frag_info(osl_t *osh, void *p)
+{
+ uint8 *frame;
+ int length;
+ uint8 *pt; /* Pointer to type field */
+ uint16 ethertype;
+ struct ipv4_hdr *iph; /* IP frame pointer */
+ int ipl; /* IP frame length */
+ uint16 iph_frag;
+
+ ASSERT(osh && p);
+
+ frame = PKTDATA(osh, p);
+ length = PKTLEN(osh, p);
+
+ /* Process Ethernet II or SNAP-encapsulated 802.3 frames */
+ if (length < ETHER_HDR_LEN) {
+ DHD_INFO(("%s: short eth frame (%d)\n", __FUNCTION__, length));
+ return DHD_PKT_FRAG_NONE;
+ } else if (ntoh16(*(uint16 *)(frame + ETHER_TYPE_OFFSET)) >= ETHER_TYPE_MIN) {
+ /* Frame is Ethernet II */
+ pt = frame + ETHER_TYPE_OFFSET;
+ } else if (length >= ETHER_HDR_LEN + SNAP_HDR_LEN + ETHER_TYPE_LEN &&
+ !bcmp(llc_snap_hdr, frame + ETHER_HDR_LEN, SNAP_HDR_LEN)) {
+ pt = frame + ETHER_HDR_LEN + SNAP_HDR_LEN;
+ } else {
+ DHD_INFO(("%s: non-SNAP 802.3 frame\n", __FUNCTION__));
+ return DHD_PKT_FRAG_NONE;
+ }
+
+ ethertype = ntoh16(*(uint16 *)pt);
+
+ /* Skip VLAN tag, if any */
+ if (ethertype == ETHER_TYPE_8021Q) {
+ pt += VLAN_TAG_LEN;
+
+ if (pt + ETHER_TYPE_LEN > frame + length) {
+ DHD_INFO(("%s: short VLAN frame (%d)\n", __FUNCTION__, length));
+ return DHD_PKT_FRAG_NONE;
+ }
+
+ ethertype = ntoh16(*(uint16 *)pt);
+ }
+
+ if (ethertype != ETHER_TYPE_IP) {
+ DHD_INFO(("%s: non-IP frame (ethertype 0x%x, length %d)\n",
+ __FUNCTION__, ethertype, length));
+ return DHD_PKT_FRAG_NONE;
+ }
+
+ iph = (struct ipv4_hdr *)(pt + ETHER_TYPE_LEN);
+ ipl = (uint)(length - (pt + ETHER_TYPE_LEN - frame));
+
+ /* We support IPv4 only */
+ if ((ipl < IPV4_OPTIONS_OFFSET) || (IP_VER(iph) != IP_VER_4)) {
+ DHD_INFO(("%s: short frame (%d) or non-IPv4\n", __FUNCTION__, ipl));
+ return DHD_PKT_FRAG_NONE;
+ }
+
+ iph_frag = ntoh16(iph->frag);
+
+ if (iph_frag & IPV4_FRAG_DONT) {
+ return DHD_PKT_FRAG_NONE;
+ } else if ((iph_frag & IPV4_FRAG_MORE) == 0) {
+ return DHD_PKT_FRAG_LAST;
+ } else {
+ return (iph_frag & IPV4_FRAG_OFFSET_MASK)? DHD_PKT_FRAG_CONT : DHD_PKT_FRAG_FIRST;
+ }
+}
+
+#ifdef DHDTCPACK_SUPPRESS
+
+typedef struct {
+ void *pkt_in_q; /* TCP ACK packet that is already in txq or DelayQ */
+ void *pkt_ether_hdr; /* Ethernet header pointer of pkt_in_q */
+} tcpack_info_t;
+
+typedef struct _tdata_psh_info_t {
+ uint32 end_seq; /* end seq# of a received TCP PSH DATA pkt */
+ struct _tdata_psh_info_t *next; /* next pointer of the link chain */
+} tdata_psh_info_t;
+
+typedef struct {
+ struct {
+ uint8 src[IPV4_ADDR_LEN]; /* SRC ip addrs of this TCP stream */
+ uint8 dst[IPV4_ADDR_LEN]; /* DST ip addrs of this TCP stream */
+ } ip_addr;
+ struct {
+ uint8 src[TCP_PORT_LEN]; /* SRC tcp ports of this TCP stream */
+ uint8 dst[TCP_PORT_LEN]; /* DST tcp ports of this TCP stream */
+ } tcp_port;
+ tdata_psh_info_t *tdata_psh_info_head; /* Head of received TCP PSH DATA chain */
+ tdata_psh_info_t *tdata_psh_info_tail; /* Tail of received TCP PSH DATA chain */
+ uint32 last_used_time; /* The last time this tcpdata_info was used(in ms) */
+} tcpdata_info_t;
+
+/* TCPACK SUPPRESS module */
+typedef struct {
+ int tcpack_info_cnt;
+ tcpack_info_t tcpack_info_tbl[TCPACK_INFO_MAXNUM]; /* Info of TCP ACK to send */
+ int tcpdata_info_cnt;
+ tcpdata_info_t tcpdata_info_tbl[TCPDATA_INFO_MAXNUM]; /* Info of received TCP DATA */
+ tdata_psh_info_t *tdata_psh_info_pool; /* Pointer to tdata_psh_info elements pool */
+ tdata_psh_info_t *tdata_psh_info_free; /* free tdata_psh_info elements chain in pool */
+#ifdef DHDTCPACK_SUP_DBG
+ int psh_info_enq_num; /* Number of free TCP PSH DATA info elements in pool */
+#endif /* DHDTCPACK_SUP_DBG */
+} tcpack_sup_module_t;
+
+#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
+counter_tbl_t tack_tbl = {"tcpACK", 0, 1000, 10, {0, }, 1};
+#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
+
+static void
+_tdata_psh_info_pool_enq(tcpack_sup_module_t *tcpack_sup_mod,
+ tdata_psh_info_t *tdata_psh_info)
+{
+ if ((tcpack_sup_mod == NULL) || (tdata_psh_info == NULL)) {
+ DHD_ERROR(("%s %d: ERROR %p %p\n", __FUNCTION__, __LINE__,
+ tcpack_sup_mod, tdata_psh_info));
+ return;
+ }
+
+ ASSERT(tdata_psh_info->next == NULL);
+ tdata_psh_info->next = tcpack_sup_mod->tdata_psh_info_free;
+ tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info;
+#ifdef DHDTCPACK_SUP_DBG
+ tcpack_sup_mod->psh_info_enq_num++;
+#endif
+}
+
+static tdata_psh_info_t*
+_tdata_psh_info_pool_deq(tcpack_sup_module_t *tcpack_sup_mod)
+{
+ tdata_psh_info_t *tdata_psh_info = NULL;
+
+ if (tcpack_sup_mod == NULL) {
+ DHD_ERROR(("%s %d: ERROR %p\n", __FUNCTION__, __LINE__,
+ tcpack_sup_mod));
+ return NULL;
+ }
+
+ tdata_psh_info = tcpack_sup_mod->tdata_psh_info_free;
+ if (tdata_psh_info == NULL)
+ DHD_ERROR(("%s %d: Out of tdata_disc_grp\n", __FUNCTION__, __LINE__));
+ else {
+ tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info->next;
+ tdata_psh_info->next = NULL;
+#ifdef DHDTCPACK_SUP_DBG
+ tcpack_sup_mod->psh_info_enq_num--;
+#endif /* DHDTCPACK_SUP_DBG */
+ }
+
+ return tdata_psh_info;
+}
+
+static int _tdata_psh_info_pool_init(dhd_pub_t *dhdp,
+ tcpack_sup_module_t *tcpack_sup_mod)
+{
+ tdata_psh_info_t *tdata_psh_info_pool = NULL;
+ uint i;
+
+ DHD_TRACE(("%s %d: Enter\n", __FUNCTION__, __LINE__));
+
+ if (tcpack_sup_mod == NULL)
+ return BCME_ERROR;
+
+ ASSERT(tcpack_sup_mod->tdata_psh_info_pool == NULL);
+ ASSERT(tcpack_sup_mod->tdata_psh_info_free == NULL);
+
+ tdata_psh_info_pool =
+ MALLOC(dhdp->osh, sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
+
+ if (tdata_psh_info_pool == NULL)
+ return BCME_NOMEM;
+ bzero(tdata_psh_info_pool, sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
+#ifdef DHDTCPACK_SUP_DBG
+ tcpack_sup_mod->psh_info_enq_num = 0;
+#endif /* DHDTCPACK_SUP_DBG */
+
+ /* Enqueue newly allocated tcpdata psh info elements to the pool */
+ for (i = 0; i < TCPDATA_PSH_INFO_MAXNUM; i++)
+ _tdata_psh_info_pool_enq(tcpack_sup_mod, &tdata_psh_info_pool[i]);
+
+ ASSERT(tcpack_sup_mod->tdata_psh_info_free != NULL);
+ tcpack_sup_mod->tdata_psh_info_pool = tdata_psh_info_pool;
+
+ return BCME_OK;
+}
+
+static void _tdata_psh_info_pool_deinit(dhd_pub_t *dhdp,
+ tcpack_sup_module_t *tcpack_sup_mod)
+{
+ uint i;
+ tdata_psh_info_t *tdata_psh_info;
+
+ DHD_TRACE(("%s %d: Enter\n", __FUNCTION__, __LINE__));
+
+ if (tcpack_sup_mod == NULL) {
+ DHD_ERROR(("%s %d: ERROR tcpack_sup_mod NULL!\n",
+ __FUNCTION__, __LINE__));
+ return;
+ }
+
+ for (i = 0; i < tcpack_sup_mod->tcpdata_info_cnt; i++) {
+ tcpdata_info_t *tcpdata_info = &tcpack_sup_mod->tcpdata_info_tbl[i];
+ /* Return tdata_psh_info elements allocated to each tcpdata_info to the pool */
+ while ((tdata_psh_info = tcpdata_info->tdata_psh_info_head)) {
+ tcpdata_info->tdata_psh_info_head = tdata_psh_info->next;
+ tdata_psh_info->next = NULL;
+ _tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info);
+ }
+ tcpdata_info->tdata_psh_info_tail = NULL;
+ }
+#ifdef DHDTCPACK_SUP_DBG
+ DHD_ERROR(("%s %d: PSH INFO ENQ %d\n",
+ __FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
+#endif /* DHDTCPACK_SUP_DBG */
+
+ i = 0;
+ /* Be sure we recollected all tdata_psh_info elements */
+ while ((tdata_psh_info = tcpack_sup_mod->tdata_psh_info_free)) {
+ tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info->next;
+ tdata_psh_info->next = NULL;
+ i++;
+ }
+ ASSERT(i == TCPDATA_PSH_INFO_MAXNUM);
+ MFREE(dhdp->osh, tcpack_sup_mod->tdata_psh_info_pool,
+ sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
+ tcpack_sup_mod->tdata_psh_info_pool = NULL;
+
+ return;
+}
+
+int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode)
+{
+ int ret = BCME_OK;
+
+ dhd_os_tcpacklock(dhdp);
+
+ if (dhdp->tcpack_sup_mode == mode) {
+ DHD_ERROR(("%s %d: already set to %d\n", __FUNCTION__, __LINE__, mode));
+ goto exit;
+ }
+
+ if (mode > TCPACK_SUP_DELAYTX) {
+ DHD_ERROR(("%s %d: Invalid mode %d\n", __FUNCTION__, __LINE__, mode));
+ ret = BCME_BADARG;
+ goto exit;
+ }
+
+ DHD_TRACE(("%s: %d -> %d\n",
+ __FUNCTION__, dhdp->tcpack_sup_mode, mode));
+
+ /* Old tcpack_sup_mode is TCPACK_SUP_DELAYTX */
+ if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX) {
+ tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module;
+ /* We won't need tdata_psh_info pool and tcpddata_info_tbl anymore */
+ _tdata_psh_info_pool_deinit(dhdp, tcpack_sup_mod);
+ tcpack_sup_mod->tcpdata_info_cnt = 0;
+ bzero(tcpack_sup_mod->tcpdata_info_tbl,
+ sizeof(tcpdata_info_t) * TCPDATA_INFO_MAXNUM);
+ /* For half duplex bus interface, tx precedes rx by default */
+ if (dhdp->bus)
+ dhd_bus_set_dotxinrx(dhdp->bus, TRUE);
+ }
+
+ dhdp->tcpack_sup_mode = mode;
+
+ if (mode == TCPACK_SUP_OFF) {
+ ASSERT(dhdp->tcpack_sup_module != NULL);
+ MFREE(dhdp->osh, dhdp->tcpack_sup_module, sizeof(tcpack_sup_module_t));
+ dhdp->tcpack_sup_module = NULL;
+ goto exit;
+ }
+
+ if (dhdp->tcpack_sup_module == NULL) {
+ tcpack_sup_module_t *tcpack_sup_mod =
+ MALLOC(dhdp->osh, sizeof(tcpack_sup_module_t));
+ if (tcpack_sup_mod == NULL) {
+ DHD_ERROR(("%s %d: No MEM\n", __FUNCTION__, __LINE__));
+ dhdp->tcpack_sup_mode = TCPACK_SUP_OFF;
+ ret = BCME_NOMEM;
+ goto exit;
+ }
+ bzero(tcpack_sup_mod, sizeof(tcpack_sup_module_t));
+ dhdp->tcpack_sup_module = tcpack_sup_mod;
+ }
+
+ if (mode == TCPACK_SUP_DELAYTX) {
+ ret = _tdata_psh_info_pool_init(dhdp, dhdp->tcpack_sup_module);
+ if (ret != BCME_OK)
+ DHD_ERROR(("%s %d: pool init fail with %d\n", __FUNCTION__, __LINE__, ret));
+ else if (dhdp->bus)
+ dhd_bus_set_dotxinrx(dhdp->bus, FALSE);
+ }
+
+exit:
+ dhd_os_tcpackunlock(dhdp);
+ return ret;
+}
+
+void
+dhd_tcpack_info_tbl_clean(dhd_pub_t *dhdp)
+{
+ tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module;
+
+ if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
+ goto exit;
+
+ dhd_os_tcpacklock(dhdp);
+
+ if (!tcpack_sup_mod) {
+ DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n",
+ __FUNCTION__, __LINE__));
+ dhd_os_tcpackunlock(dhdp);
+ goto exit;
+ }
+
+ tcpack_sup_mod->tcpack_info_cnt = 0;
+ bzero(tcpack_sup_mod->tcpack_info_tbl, sizeof(tcpack_info_t) * TCPACK_INFO_MAXNUM);
+ dhd_os_tcpackunlock(dhdp);
+
+exit:
+ return;
+}
+
+inline int dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt)
+{
+ uint8 i;
+ tcpack_sup_module_t *tcpack_sup_mod;
+ tcpack_info_t *tcpack_info_tbl;
+ int tbl_cnt;
+ uint pushed_len;
+ int ret = BCME_OK;
+ void *pdata;
+ uint32 pktlen;
+
+ if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
+ goto exit;
+
+ pdata = PKTDATA(dhdp->osh, pkt);
+
+ /* Length of BDC(+WLFC) headers pushed */
+ pushed_len = BDC_HEADER_LEN + (((struct bdc_header *)pdata)->dataOffset * 4);
+ pktlen = PKTLEN(dhdp->osh, pkt) - pushed_len;
+
+ if (pktlen < TCPACKSZMIN || pktlen > TCPACKSZMAX) {
+ DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n",
+ __FUNCTION__, __LINE__, pktlen));
+ goto exit;
+ }
+
+ dhd_os_tcpacklock(dhdp);
+ tcpack_sup_mod = dhdp->tcpack_sup_module;
+
+ if (!tcpack_sup_mod) {
+ DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
+ ret = BCME_ERROR;
+ dhd_os_tcpackunlock(dhdp);
+ goto exit;
+ }
+ tbl_cnt = tcpack_sup_mod->tcpack_info_cnt;
+ tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl;
+
+ ASSERT(tbl_cnt <= TCPACK_INFO_MAXNUM);
+
+ for (i = 0; i < tbl_cnt; i++) {
+ if (tcpack_info_tbl[i].pkt_in_q == pkt) {
+ DHD_TRACE(("%s %d: pkt %p sent out. idx %d, tbl_cnt %d\n",
+ __FUNCTION__, __LINE__, pkt, i, tbl_cnt));
+ /* This pkt is being transmitted so remove the tcp_ack_info of it. */
+ if (i < tbl_cnt - 1) {
+ bcopy(&tcpack_info_tbl[tbl_cnt - 1],
+ &tcpack_info_tbl[i], sizeof(tcpack_info_t));
+ }
+ bzero(&tcpack_info_tbl[tbl_cnt - 1], sizeof(tcpack_info_t));
+ if (--tcpack_sup_mod->tcpack_info_cnt < 0) {
+ DHD_ERROR(("%s %d: ERROR!!! tcp_ack_info_cnt %d\n",
+ __FUNCTION__, __LINE__, tcpack_sup_mod->tcpack_info_cnt));
+ ret = BCME_ERROR;
+ }
+ break;
+ }
+ }
+ dhd_os_tcpackunlock(dhdp);
+
+exit:
+ return ret;
+}
+
+static INLINE bool dhd_tcpdata_psh_acked(dhd_pub_t *dhdp, uint8 *ip_hdr,
+ uint8 *tcp_hdr, uint32 tcp_ack_num)
+{
+ tcpack_sup_module_t *tcpack_sup_mod;
+ int i;
+ tcpdata_info_t *tcpdata_info = NULL;
+ tdata_psh_info_t *tdata_psh_info = NULL;
+ bool ret = FALSE;
+
+ if (dhdp->tcpack_sup_mode != TCPACK_SUP_DELAYTX)
+ goto exit;
+
+ tcpack_sup_mod = dhdp->tcpack_sup_module;
+
+ if (!tcpack_sup_mod) {
+ DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
+ goto exit;
+ }
+
+ DHD_TRACE(("%s %d: IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
+ " TCP port %d %d, ack %u\n", __FUNCTION__, __LINE__,
+ IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
+ IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
+ ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
+ ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]),
+ tcp_ack_num));
+
+ for (i = 0; i < tcpack_sup_mod->tcpdata_info_cnt; i++) {
+ tcpdata_info_t *tcpdata_info_tmp = &tcpack_sup_mod->tcpdata_info_tbl[i];
+ DHD_TRACE(("%s %d: data info[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
+ " TCP port %d %d\n", __FUNCTION__, __LINE__, i,
+ IPV4_ADDR_TO_STR(ntoh32_ua(tcpdata_info_tmp->ip_addr.src)),
+ IPV4_ADDR_TO_STR(ntoh32_ua(tcpdata_info_tmp->ip_addr.dst)),
+ ntoh16_ua(tcpdata_info_tmp->tcp_port.src),
+ ntoh16_ua(tcpdata_info_tmp->tcp_port.dst)));
+
+ /* If either IP address or TCP port number does not match, skip. */
+ if (memcmp(&ip_hdr[IPV4_SRC_IP_OFFSET],
+ tcpdata_info_tmp->ip_addr.dst, IPV4_ADDR_LEN) == 0 &&
+ memcmp(&ip_hdr[IPV4_DEST_IP_OFFSET],
+ tcpdata_info_tmp->ip_addr.src, IPV4_ADDR_LEN) == 0 &&
+ memcmp(&tcp_hdr[TCP_SRC_PORT_OFFSET],
+ tcpdata_info_tmp->tcp_port.dst, TCP_PORT_LEN) == 0 &&
+ memcmp(&tcp_hdr[TCP_DEST_PORT_OFFSET],
+ tcpdata_info_tmp->tcp_port.src, TCP_PORT_LEN) == 0) {
+ tcpdata_info = tcpdata_info_tmp;
+ break;
+ }
+ }
+
+ if (tcpdata_info == NULL) {
+ DHD_TRACE(("%s %d: no tcpdata_info!\n", __FUNCTION__, __LINE__));
+ goto exit;
+ }
+
+ if (tcpdata_info->tdata_psh_info_head == NULL) {
+ DHD_TRACE(("%s %d: No PSH DATA to be acked!\n", __FUNCTION__, __LINE__));
+ }
+
+ while ((tdata_psh_info = tcpdata_info->tdata_psh_info_head)) {
+ if (IS_TCPSEQ_GE(tcp_ack_num, tdata_psh_info->end_seq)) {
+ DHD_TRACE(("%s %d: PSH ACKED! %u >= %u\n",
+ __FUNCTION__, __LINE__, tcp_ack_num, tdata_psh_info->end_seq));
+ tcpdata_info->tdata_psh_info_head = tdata_psh_info->next;
+ tdata_psh_info->next = NULL;
+ _tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info);
+ ret = TRUE;
+ } else
+ break;
+ }
+ if (tdata_psh_info == NULL)
+ tcpdata_info->tdata_psh_info_tail = NULL;
+
+#ifdef DHDTCPACK_SUP_DBG
+ DHD_TRACE(("%s %d: PSH INFO ENQ %d\n",
+ __FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
+#endif /* DHDTCPACK_SUP_DBG */
+
+exit:
+ return ret;
+}
+
+bool
+dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt)
+{
+ uint8 *new_ether_hdr; /* Ethernet header of the new packet */
+ uint16 new_ether_type; /* Ethernet type of the new packet */
+ uint8 *new_ip_hdr; /* IP header of the new packet */
+ uint8 *new_tcp_hdr; /* TCP header of the new packet */
+ uint32 new_ip_hdr_len; /* IP header length of the new packet */
+ uint32 cur_framelen;
+ uint32 new_tcp_ack_num; /* TCP acknowledge number of the new packet */
+ uint16 new_ip_total_len; /* Total length of IP packet for the new packet */
+ uint32 new_tcp_hdr_len; /* TCP header length of the new packet */
+ tcpack_sup_module_t *tcpack_sup_mod;
+ tcpack_info_t *tcpack_info_tbl;
+ int i;
+ bool ret = FALSE;
+ bool set_dotxinrx = TRUE;
+
+ if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
+ goto exit;
+
+ new_ether_hdr = PKTDATA(dhdp->osh, pkt);
+ cur_framelen = PKTLEN(dhdp->osh, pkt);
+
+ if (cur_framelen < TCPACKSZMIN || cur_framelen > TCPACKSZMAX) {
+ DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n",
+ __FUNCTION__, __LINE__, cur_framelen));
+ goto exit;
+ }
+
+ new_ether_type = new_ether_hdr[12] << 8 | new_ether_hdr[13];
+
+ if (new_ether_type != ETHER_TYPE_IP) {
+ DHD_TRACE(("%s %d: Not a IP packet 0x%x\n",
+ __FUNCTION__, __LINE__, new_ether_type));
+ goto exit;
+ }
+
+ DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, new_ether_type));
+
+ new_ip_hdr = new_ether_hdr + ETHER_HDR_LEN;
+ cur_framelen -= ETHER_HDR_LEN;
+
+ ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN);
+
+ new_ip_hdr_len = IPV4_HLEN(new_ip_hdr);
+ if (IP_VER(new_ip_hdr) != IP_VER_4 || IPV4_PROT(new_ip_hdr) != IP_PROT_TCP) {
+ DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n",
+ __FUNCTION__, __LINE__, IP_VER(new_ip_hdr), IPV4_PROT(new_ip_hdr)));
+ goto exit;
+ }
+
+ new_tcp_hdr = new_ip_hdr + new_ip_hdr_len;
+ cur_framelen -= new_ip_hdr_len;
+
+ ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN);
+
+ DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__));
+
+ /* is it an ack ? Allow only ACK flag, not to suppress others. */
+ if (new_tcp_hdr[TCP_FLAGS_OFFSET] != TCP_FLAG_ACK) {
+ DHD_TRACE(("%s %d: Do not touch TCP flag 0x%x\n",
+ __FUNCTION__, __LINE__, new_tcp_hdr[TCP_FLAGS_OFFSET]));
+ goto exit;
+ }
+
+ new_ip_total_len = ntoh16_ua(&new_ip_hdr[IPV4_PKTLEN_OFFSET]);
+ new_tcp_hdr_len = 4 * TCP_HDRLEN(new_tcp_hdr[TCP_HLEN_OFFSET]);
+
+ /* This packet has TCP data, so just send */
+ if (new_ip_total_len > new_ip_hdr_len + new_tcp_hdr_len) {
+ DHD_TRACE(("%s %d: Do nothing for TCP DATA\n", __FUNCTION__, __LINE__));
+ goto exit;
+ }
+
+ ASSERT(new_ip_total_len == new_ip_hdr_len + new_tcp_hdr_len);
+
+ new_tcp_ack_num = ntoh32_ua(&new_tcp_hdr[TCP_ACK_NUM_OFFSET]);
+
+ DHD_TRACE(("%s %d: TCP ACK with zero DATA length"
+ " IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n",
+ __FUNCTION__, __LINE__,
+ IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_SRC_IP_OFFSET])),
+ IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_DEST_IP_OFFSET])),
+ ntoh16_ua(&new_tcp_hdr[TCP_SRC_PORT_OFFSET]),
+ ntoh16_ua(&new_tcp_hdr[TCP_DEST_PORT_OFFSET])));
+
+ /* Look for tcp_ack_info that has the same ip src/dst addrs and tcp src/dst ports */
+ dhd_os_tcpacklock(dhdp);
+#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
+ counter_printlog(&tack_tbl);
+ tack_tbl.cnt[0]++;
+#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
+
+ tcpack_sup_mod = dhdp->tcpack_sup_module;
+ tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl;
+
+ if (!tcpack_sup_mod) {
+ DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
+ ret = BCME_ERROR;
+ dhd_os_tcpackunlock(dhdp);
+ goto exit;
+ }
+
+ if (dhd_tcpdata_psh_acked(dhdp, new_ip_hdr, new_tcp_hdr, new_tcp_ack_num)) {
+ /* This TCPACK is ACK to TCPDATA PSH pkt, so keep set_dotxinrx TRUE */
+#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
+ tack_tbl.cnt[5]++;
+#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
+ } else
+ set_dotxinrx = FALSE;
+
+ for (i = 0; i < tcpack_sup_mod->tcpack_info_cnt; i++) {
+ void *oldpkt; /* TCPACK packet that is already in txq or DelayQ */
+ uint8 *old_ether_hdr, *old_ip_hdr, *old_tcp_hdr;
+ uint32 old_ip_hdr_len, old_tcp_hdr_len;
+ uint32 old_tcpack_num; /* TCP ACK number of old TCPACK packet in Q */
+
+ if ((oldpkt = tcpack_info_tbl[i].pkt_in_q) == NULL) {
+ DHD_ERROR(("%s %d: Unexpected error!! cur idx %d, ttl cnt %d\n",
+ __FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpack_info_cnt));
+ break;
+ }
+
+ if (PKTDATA(dhdp->osh, oldpkt) == NULL) {
+ DHD_ERROR(("%s %d: oldpkt data NULL!! cur idx %d, ttl cnt %d\n",
+ __FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpack_info_cnt));
+ break;
+ }
+
+ old_ether_hdr = tcpack_info_tbl[i].pkt_ether_hdr;
+ old_ip_hdr = old_ether_hdr + ETHER_HDR_LEN;
+ old_ip_hdr_len = IPV4_HLEN(old_ip_hdr);
+ old_tcp_hdr = old_ip_hdr + old_ip_hdr_len;
+ old_tcp_hdr_len = 4 * TCP_HDRLEN(old_tcp_hdr[TCP_HLEN_OFFSET]);
+
+ DHD_TRACE(("%s %d: oldpkt %p[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
+ " TCP port %d %d\n", __FUNCTION__, __LINE__, oldpkt, i,
+ IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_SRC_IP_OFFSET])),
+ IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_DEST_IP_OFFSET])),
+ ntoh16_ua(&old_tcp_hdr[TCP_SRC_PORT_OFFSET]),
+ ntoh16_ua(&old_tcp_hdr[TCP_DEST_PORT_OFFSET])));
+
+ /* If either of IP address or TCP port number does not match, skip.
+ * Note that src/dst addr fields in ip header are contiguous being 8 bytes in total.
+ * Also, src/dst port fields in TCP header are contiguous being 4 bytes in total.
+ */
+ if (memcmp(&new_ip_hdr[IPV4_SRC_IP_OFFSET],
+ &old_ip_hdr[IPV4_SRC_IP_OFFSET], IPV4_ADDR_LEN * 2) ||
+ memcmp(&new_tcp_hdr[TCP_SRC_PORT_OFFSET],
+ &old_tcp_hdr[TCP_SRC_PORT_OFFSET], TCP_PORT_LEN * 2))
+ continue;
+
+ old_tcpack_num = ntoh32_ua(&old_tcp_hdr[TCP_ACK_NUM_OFFSET]);
+
+ if (IS_TCPSEQ_GT(new_tcp_ack_num, old_tcpack_num)) {
+ /* New packet has higher TCP ACK number, so it replaces the old packet */
+ if (new_ip_hdr_len == old_ip_hdr_len &&
+ new_tcp_hdr_len == old_tcp_hdr_len) {
+ ASSERT(memcmp(new_ether_hdr, old_ether_hdr, ETHER_HDR_LEN) == 0);
+ bcopy(new_ip_hdr, old_ip_hdr, new_ip_total_len);
+ PKTFREE(dhdp->osh, pkt, FALSE);
+ DHD_TRACE(("%s %d: TCP ACK replace %u -> %u\n",
+ __FUNCTION__, __LINE__, old_tcpack_num, new_tcp_ack_num));
+#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
+ tack_tbl.cnt[2]++;
+#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
+ ret = TRUE;
+ } else
+ DHD_TRACE(("%s %d: lenth mismatch %d != %d || %d != %d\n",
+ __FUNCTION__, __LINE__, new_ip_hdr_len, old_ip_hdr_len,
+ new_tcp_hdr_len, old_tcp_hdr_len));
+ } else if (new_tcp_ack_num == old_tcpack_num) {
+ set_dotxinrx = TRUE;
+ /* TCPACK retransmission */
+#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
+ tack_tbl.cnt[3]++;
+#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
+ } else {
+ DHD_TRACE(("%s %d: ACK number reverse old %u(0x%p) new %u(0x%p)\n",
+ __FUNCTION__, __LINE__, old_tcpack_num, oldpkt,
+ new_tcp_ack_num, pkt));
+ }
+ dhd_os_tcpackunlock(dhdp);
+ goto exit;
+ }
+
+ if (i == tcpack_sup_mod->tcpack_info_cnt && i < TCPACK_INFO_MAXNUM) {
+ /* No TCPACK packet with the same IP addr and TCP port is found
+ * in tcp_ack_info_tbl. So add this packet to the table.
+ */
+ DHD_TRACE(("%s %d: Add pkt 0x%p(ether_hdr 0x%p) to tbl[%d]\n",
+ __FUNCTION__, __LINE__, pkt, new_ether_hdr,
+ tcpack_sup_mod->tcpack_info_cnt));
+
+ tcpack_info_tbl[tcpack_sup_mod->tcpack_info_cnt].pkt_in_q = pkt;
+ tcpack_info_tbl[tcpack_sup_mod->tcpack_info_cnt].pkt_ether_hdr = new_ether_hdr;
+ tcpack_sup_mod->tcpack_info_cnt++;
+#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
+ tack_tbl.cnt[1]++;
+#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
+ } else {
+ ASSERT(i == tcpack_sup_mod->tcpack_info_cnt);
+ DHD_TRACE(("%s %d: No empty tcp ack info tbl\n",
+ __FUNCTION__, __LINE__));
+ }
+ dhd_os_tcpackunlock(dhdp);
+
+exit:
+ /* Unless TCPACK_SUP_DELAYTX, dotxinrx is alwasy TRUE, so no need to set here */
+ if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX && set_dotxinrx)
+ dhd_bus_set_dotxinrx(dhdp->bus, TRUE);
+
+ return ret;
+}
+
+bool
+dhd_tcpdata_info_get(dhd_pub_t *dhdp, void *pkt)
+{
+ uint8 *ether_hdr; /* Ethernet header of the new packet */
+ uint16 ether_type; /* Ethernet type of the new packet */
+ uint8 *ip_hdr; /* IP header of the new packet */
+ uint8 *tcp_hdr; /* TCP header of the new packet */
+ uint32 ip_hdr_len; /* IP header length of the new packet */
+ uint32 cur_framelen;
+ uint16 ip_total_len; /* Total length of IP packet for the new packet */
+ uint32 tcp_hdr_len; /* TCP header length of the new packet */
+ uint32 tcp_seq_num; /* TCP sequence number of the new packet */
+ uint16 tcp_data_len; /* TCP DATA length that excludes IP and TCP headers */
+ uint32 end_tcp_seq_num; /* TCP seq number of the last byte in the new packet */
+ tcpack_sup_module_t *tcpack_sup_mod;
+ tcpdata_info_t *tcpdata_info = NULL;
+ tdata_psh_info_t *tdata_psh_info;
+
+ int i;
+ bool ret = FALSE;
+
+ if (dhdp->tcpack_sup_mode != TCPACK_SUP_DELAYTX)
+ goto exit;
+
+ ether_hdr = PKTDATA(dhdp->osh, pkt);
+ cur_framelen = PKTLEN(dhdp->osh, pkt);
+
+ ether_type = ether_hdr[12] << 8 | ether_hdr[13];
+
+ if (ether_type != ETHER_TYPE_IP) {
+ DHD_TRACE(("%s %d: Not a IP packet 0x%x\n",
+ __FUNCTION__, __LINE__, ether_type));
+ goto exit;
+ }
+
+ DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, ether_type));
+
+ ip_hdr = ether_hdr + ETHER_HDR_LEN;
+ cur_framelen -= ETHER_HDR_LEN;
+
+ ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN);
+
+ ip_hdr_len = IPV4_HLEN(ip_hdr);
+ if (IP_VER(ip_hdr) != IP_VER_4 || IPV4_PROT(ip_hdr) != IP_PROT_TCP) {
+ DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n",
+ __FUNCTION__, __LINE__, IP_VER(ip_hdr), IPV4_PROT(ip_hdr)));
+ goto exit;
+ }
+
+ tcp_hdr = ip_hdr + ip_hdr_len;
+ cur_framelen -= ip_hdr_len;
+
+ ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN);
+
+ DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__));
+
+ ip_total_len = ntoh16_ua(&ip_hdr[IPV4_PKTLEN_OFFSET]);
+ tcp_hdr_len = 4 * TCP_HDRLEN(tcp_hdr[TCP_HLEN_OFFSET]);
+
+ /* This packet is mere TCP ACK, so do nothing */
+ if (ip_total_len == ip_hdr_len + tcp_hdr_len) {
+ DHD_TRACE(("%s %d: Do nothing for no data TCP ACK\n", __FUNCTION__, __LINE__));
+ goto exit;
+ }
+
+ ASSERT(ip_total_len > ip_hdr_len + tcp_hdr_len);
+
+ if ((tcp_hdr[TCP_FLAGS_OFFSET] & TCP_FLAG_PSH) == 0) {
+ DHD_TRACE(("%s %d: Not interested TCP DATA packet\n", __FUNCTION__, __LINE__));
+ goto exit;
+ }
+
+ DHD_TRACE(("%s %d: TCP DATA with nonzero DATA length"
+ " IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d, flag 0x%x\n",
+ __FUNCTION__, __LINE__,
+ IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
+ IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
+ ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
+ ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]),
+ tcp_hdr[TCP_FLAGS_OFFSET]));
+
+ dhd_os_tcpacklock(dhdp);
+ tcpack_sup_mod = dhdp->tcpack_sup_module;
+
+ if (!tcpack_sup_mod) {
+ DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
+ ret = BCME_ERROR;
+ dhd_os_tcpackunlock(dhdp);
+ goto exit;
+ }
+
+ /* Look for tcpdata_info that has the same ip src/dst addrs and tcp src/dst ports */
+ i = 0;
+ while (i < tcpack_sup_mod->tcpdata_info_cnt) {
+ tcpdata_info_t *tdata_info_tmp = &tcpack_sup_mod->tcpdata_info_tbl[i];
+ uint32 now_in_ms = OSL_SYSUPTIME();
+ DHD_TRACE(("%s %d: data info[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
+ " TCP port %d %d\n", __FUNCTION__, __LINE__, i,
+ IPV4_ADDR_TO_STR(ntoh32_ua(tdata_info_tmp->ip_addr.src)),
+ IPV4_ADDR_TO_STR(ntoh32_ua(tdata_info_tmp->ip_addr.dst)),
+ ntoh16_ua(tdata_info_tmp->tcp_port.src),
+ ntoh16_ua(tdata_info_tmp->tcp_port.dst)));
+
+ /* If both IP address and TCP port number match, we found it so break.
+ * Note that src/dst addr fields in ip header are contiguous being 8 bytes in total.
+ * Also, src/dst port fields in TCP header are contiguous being 4 bytes in total.
+ */
+ if (memcmp(&ip_hdr[IPV4_SRC_IP_OFFSET],
+ (void *)&tdata_info_tmp->ip_addr, IPV4_ADDR_LEN * 2) == 0 &&
+ memcmp(&tcp_hdr[TCP_SRC_PORT_OFFSET],
+ (void *)&tdata_info_tmp->tcp_port, TCP_PORT_LEN * 2) == 0) {
+ tcpdata_info = tdata_info_tmp;
+ tcpdata_info->last_used_time = now_in_ms;
+ break;
+ }
+
+ if (now_in_ms - tdata_info_tmp->last_used_time > TCPDATA_INFO_TIMEOUT) {
+ tdata_psh_info_t *tdata_psh_info_tmp;
+ tcpdata_info_t *last_tdata_info;
+
+ while ((tdata_psh_info_tmp = tdata_info_tmp->tdata_psh_info_head)) {
+ tdata_info_tmp->tdata_psh_info_head = tdata_psh_info_tmp->next;
+ tdata_psh_info_tmp->next = NULL;
+ DHD_TRACE(("%s %d: Clean tdata_psh_info(end_seq %u)!\n",
+ __FUNCTION__, __LINE__, tdata_psh_info_tmp->end_seq));
+ _tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info_tmp);
+ }
+#ifdef DHDTCPACK_SUP_DBG
+ DHD_ERROR(("%s %d: PSH INFO ENQ %d\n",
+ __FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
+#endif /* DHDTCPACK_SUP_DBG */
+ tcpack_sup_mod->tcpdata_info_cnt--;
+ ASSERT(tcpack_sup_mod->tcpdata_info_cnt >= 0);
+
+ last_tdata_info =
+ &tcpack_sup_mod->tcpdata_info_tbl[tcpack_sup_mod->tcpdata_info_cnt];
+ if (i < tcpack_sup_mod->tcpdata_info_cnt) {
+ ASSERT(last_tdata_info != tdata_info_tmp);
+ bcopy(last_tdata_info, tdata_info_tmp, sizeof(tcpdata_info_t));
+ }
+ bzero(last_tdata_info, sizeof(tcpdata_info_t));
+ DHD_INFO(("%s %d: tcpdata_info(idx %d) is aged out. ttl cnt is now %d\n",
+ __FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpdata_info_cnt));
+ /* Don't increase "i" here, so that the prev last tcpdata_info is checked */
+ } else
+ i++;
+ }
+
+ tcp_seq_num = ntoh32_ua(&tcp_hdr[TCP_SEQ_NUM_OFFSET]);
+ tcp_data_len = ip_total_len - ip_hdr_len - tcp_hdr_len;
+ end_tcp_seq_num = tcp_seq_num + tcp_data_len;
+
+ if (tcpdata_info == NULL) {
+ ASSERT(i == tcpack_sup_mod->tcpdata_info_cnt);
+ if (i >= TCPDATA_INFO_MAXNUM) {
+ DHD_TRACE(("%s %d: tcp_data_info_tbl FULL! %d %d"
+ " IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n",
+ __FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpdata_info_cnt,
+ IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
+ IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
+ ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
+ ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET])));
+ dhd_os_tcpackunlock(dhdp);
+ goto exit;
+ }
+ tcpdata_info = &tcpack_sup_mod->tcpdata_info_tbl[i];
+
+ /* No TCP flow with the same IP addr and TCP port is found
+ * in tcp_data_info_tbl. So add this flow to the table.
+ */
+ DHD_INFO(("%s %d: Add data info to tbl[%d]: IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
+ " TCP port %d %d\n",
+ __FUNCTION__, __LINE__, tcpack_sup_mod->tcpdata_info_cnt,
+ IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
+ IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
+ ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
+ ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET])));
+ /* Note that src/dst addr fields in ip header are contiguous being 8 bytes in total.
+ * Also, src/dst port fields in TCP header are contiguous being 4 bytes in total.
+ */
+ bcopy(&ip_hdr[IPV4_SRC_IP_OFFSET], (void *)&tcpdata_info->ip_addr,
+ IPV4_ADDR_LEN * 2);
+ bcopy(&tcp_hdr[TCP_SRC_PORT_OFFSET], (void *)&tcpdata_info->tcp_port,
+ TCP_PORT_LEN * 2);
+
+ tcpdata_info->last_used_time = OSL_SYSUPTIME();
+ tcpack_sup_mod->tcpdata_info_cnt++;
+ }
+
+ ASSERT(tcpdata_info != NULL);
+
+ tdata_psh_info = _tdata_psh_info_pool_deq(tcpack_sup_mod);
+#ifdef DHDTCPACK_SUP_DBG
+ DHD_TRACE(("%s %d: PSH INFO ENQ %d\n",
+ __FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
+#endif /* DHDTCPACK_SUP_DBG */
+
+ if (tdata_psh_info == NULL) {
+ DHD_ERROR(("%s %d: No more free tdata_psh_info!!\n", __FUNCTION__, __LINE__));
+ ret = BCME_ERROR;
+ dhd_os_tcpackunlock(dhdp);
+ goto exit;
+ }
+ tdata_psh_info->end_seq = end_tcp_seq_num;
+
+#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
+ tack_tbl.cnt[4]++;
+#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
+
+ DHD_TRACE(("%s %d: TCP PSH DATA recvd! end seq %u\n",
+ __FUNCTION__, __LINE__, tdata_psh_info->end_seq));
+
+ ASSERT(tdata_psh_info->next == NULL);
+
+ if (tcpdata_info->tdata_psh_info_head == NULL)
+ tcpdata_info->tdata_psh_info_head = tdata_psh_info;
+ else {
+ ASSERT(tcpdata_info->tdata_psh_info_tail);
+ tcpdata_info->tdata_psh_info_tail->next = tdata_psh_info;
+ }
+ tcpdata_info->tdata_psh_info_tail = tdata_psh_info;
+
+ dhd_os_tcpackunlock(dhdp);
+
+exit:
+ return ret;
+}
+
+#endif /* DHDTCPACK_SUPPRESS */
diff --git a/drivers/net/wireless/bcmdhd/dhd_ip.h b/drivers/net/wireless/bcmdhd/dhd_ip.h
new file mode 100644
index 000000000000..6ba19ba10849
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_ip.h
@@ -0,0 +1,71 @@
+/*
+ * Header file describing the common ip parser function.
+ *
+ * Provides type definitions and function prototypes used to parse ip packet.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_ip.h 457888 2014-02-25 03:34:39Z $
+ */
+
+#ifndef _dhd_ip_h_
+#define _dhd_ip_h_
+
+#ifdef DHDTCPACK_SUPPRESS
+#include <dngl_stats.h>
+#include <bcmutils.h>
+#include <dhd.h>
+#endif /* DHDTCPACK_SUPPRESS */
+
+typedef enum pkt_frag
+{
+ DHD_PKT_FRAG_NONE = 0,
+ DHD_PKT_FRAG_FIRST,
+ DHD_PKT_FRAG_CONT,
+ DHD_PKT_FRAG_LAST
+} pkt_frag_t;
+
+extern pkt_frag_t pkt_frag_info(osl_t *osh, void *p);
+
+#ifdef DHDTCPACK_SUPPRESS
+#define TCPACKSZMIN (ETHER_HDR_LEN + IPV4_MIN_HEADER_LEN + TCP_MIN_HEADER_LEN)
+/* Size of MAX possible TCP ACK packet. Extra bytes for IP/TCP option fields */
+#define TCPACKSZMAX (TCPACKSZMIN + 100)
+
+/* Max number of TCP streams that have own src/dst IP addrs and TCP ports */
+#define TCPACK_INFO_MAXNUM 4
+#define TCPDATA_INFO_MAXNUM 4
+#define TCPDATA_PSH_INFO_MAXNUM (8 * TCPDATA_INFO_MAXNUM)
+
+#define TCPDATA_INFO_TIMEOUT 5000 /* Remove tcpdata_info if inactive for this time (in ms) */
+
+extern int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 on);
+extern void dhd_tcpack_info_tbl_clean(dhd_pub_t *dhdp);
+extern int dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt);
+extern bool dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt);
+extern bool dhd_tcpdata_info_get(dhd_pub_t *dhdp, void *pkt);
+
+#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
+extern counter_tbl_t tack_tbl;
+#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
+#endif /* DHDTCPACK_SUPPRESS */
+
+#endif /* _dhd_ip_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
new file mode 100644
index 000000000000..caaa5483caa9
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -0,0 +1,8008 @@
+/*
+ * Broadcom Dongle Host Driver (DHD), Linux-specific network interface
+ * Basically selected code segments from usb-cdc.c and usb-rndis.c
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_linux.c 663029 2016-11-30 03:37:26Z $
+ */
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+#ifdef SHOW_LOGTRACE
+#include <linux/syscalls.h>
+#include <event_log.h>
+#endif /* SHOW_LOGTRACE */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/etherdevice.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/ip.h>
+#include <net/addrconf.h>
+#include <linux/cpufreq.h>
+
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+
+#include <epivers.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <bcmdevs.h>
+
+#include <proto/ethernet.h>
+#include <proto/bcmevent.h>
+#include <dngl_stats.h>
+#include <dhd_linux_wq.h>
+#include <dhd.h>
+#include <dhd_linux.h>
+#include <dhd_bus.h>
+#include <dhd_proto.h>
+#include <dhd_dbg.h>
+#ifdef CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#endif
+#ifdef WL_CFG80211
+#include <wl_cfg80211.h>
+#endif
+#ifdef CUSTOM_COUNTRY_CODE
+#include <wl_iw.h>
+#endif
+#ifdef P2PONEINT
+#include <wl_cfgp2p.h>
+#endif
+#ifdef PNO_SUPPORT
+#include <dhd_pno.h>
+#endif
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+
+#ifdef DHDTCPACK_SUPPRESS
+#include <dhd_ip.h>
+#endif /* DHDTCPACK_SUPPRESS */
+
+
+#ifdef WLMEDIA_HTSF
+#include <linux/time.h>
+#include <htsf.h>
+
+#define HTSF_MINLEN 200 /* min. packet length to timestamp */
+#define HTSF_BUS_DELAY 150 /* assume a fix propagation in us */
+#define TSMAX 1000 /* max no. of timing record kept */
+#define NUMBIN 34
+
+static uint32 tsidx = 0;
+static uint32 htsf_seqnum = 0;
+uint32 tsfsync;
+struct timeval tsync;
+static uint32 tsport = 5010;
+
+typedef struct histo_ {
+ uint32 bin[NUMBIN];
+} histo_t;
+
+#if !ISPOWEROF2(DHD_SDALIGN)
+#error DHD_SDALIGN is not a power of 2!
+#endif
+
+static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
+#endif /* WLMEDIA_HTSF */
+
+
+
+#if defined(SOFTAP)
+extern bool ap_cfg_running;
+extern bool ap_fw_loaded;
+#endif
+
+
+#ifdef ENABLE_ADAPTIVE_SCHED
+#define DEFAULT_CPUFREQ_THRESH 1000000 /* threshold frequency : 1000000 = 1GHz */
+#ifndef CUSTOM_CPUFREQ_THRESH
+#define CUSTOM_CPUFREQ_THRESH DEFAULT_CPUFREQ_THRESH
+#endif /* CUSTOM_CPUFREQ_THRESH */
+#endif /* ENABLE_ADAPTIVE_SCHED */
+
+/* enable HOSTIP cache update from the host side when an eth0:N is up */
+#define AOE_IP_ALIAS_SUPPORT 1
+
+#ifdef BCM_FD_AGGR
+#include <bcm_rpc.h>
+#include <bcm_rpc_tp.h>
+#endif
+#ifdef PROP_TXSTATUS
+#include <wlfc_proto.h>
+#include <dhd_wlfc.h>
+#endif
+
+#include <wl_android.h>
+
+
+#ifdef ARP_OFFLOAD_SUPPORT
+void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx);
+static int dhd_inetaddr_notifier_call(struct notifier_block *this,
+ unsigned long event, void *ptr);
+static struct notifier_block dhd_inetaddr_notifier = {
+ .notifier_call = dhd_inetaddr_notifier_call
+};
+/* to make sure we won't register the same notifier twice, otherwise a loop is likely to be
+ * created in kernel notifier link list (with 'next' pointing to itself)
+ */
+static bool dhd_inetaddr_notifier_registered = FALSE;
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+static int dhd_inet6addr_notifier_call(struct notifier_block *this,
+ unsigned long event, void *ptr);
+static struct notifier_block dhd_inet6addr_notifier = {
+ .notifier_call = dhd_inet6addr_notifier_call
+};
+/* to make sure we won't register the same notifier twice, otherwise a loop is likely to be
+ * created in kernel notifier link list (with 'next' pointing to itself)
+ */
+static bool dhd_inet6addr_notifier_registered = FALSE;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+#include <linux/suspend.h>
+volatile bool dhd_mmc_suspend = FALSE;
+DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+
+#if defined(OOB_INTR_ONLY)
+extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable);
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+static void dhd_hang_process(void *dhd_info, void *event_data, u8 event);
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+MODULE_LICENSE("GPL v2");
+#endif /* LinuxVer */
+
+#include <dhd_bus.h>
+
+#ifdef BCM_FD_AGGR
+#define DBUS_RX_BUFFER_SIZE_DHD(net) (BCM_RPC_TP_DNGL_AGG_MAX_BYTE)
+#else
+#ifndef PROP_TXSTATUS
+#define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen)
+#else
+#define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen + 128)
+#endif
+#endif /* BCM_FD_AGGR */
+
+#ifdef PROP_TXSTATUS
+extern bool dhd_wlfc_skip_fc(void);
+extern void dhd_wlfc_plat_init(void *dhd);
+extern void dhd_wlfc_plat_deinit(void *dhd);
+#endif /* PROP_TXSTATUS */
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15)
+const char *
+print_tainted()
+{
+ return "";
+}
+#endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */
+
+/* Linux wireless extension support */
+#if defined(WL_WIRELESS_EXT)
+#include <wl_iw.h>
+extern wl_iw_extra_params_t g_wl_iw_params;
+#endif /* defined(WL_WIRELESS_EXT) */
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+#include <linux/nl80211.h>
+#endif /* OEM_ANDROID && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */
+
+extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd);
+
+#ifdef PKT_FILTER_SUPPORT
+extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg);
+extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
+extern void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id);
+#endif
+
+
+#ifdef READ_MACADDR
+extern int dhd_read_macaddr(struct dhd_info *dhd);
+#else
+static inline int dhd_read_macaddr(struct dhd_info *dhd) { return 0; }
+#endif
+#ifdef WRITE_MACADDR
+extern int dhd_write_macaddr(struct ether_addr *mac);
+#else
+static inline int dhd_write_macaddr(struct ether_addr *mac) { return 0; }
+#endif
+
+#ifdef ENABLE_CONTROL_SCHED
+#ifndef ENABLE_ADAPTIVE_SCHED
+#error ENABLE_ADAPTIVE_SCHED not define.
+#endif /* ENABLE_ADAPTIVE_SCHED */
+static int dhd_sysfs_create_node(struct net_device *net);
+static void dhd_sysfs_destroy_node(struct net_device *net);
+#endif /* ENABLE_CONTROL_SCHED */
+
+
+
+
+typedef struct dhd_if_event {
+ struct list_head list;
+ wl_event_data_if_t event;
+ char name[IFNAMSIZ+1];
+ uint8 mac[ETHER_ADDR_LEN];
+} dhd_if_event_t;
+
+/* Interface control information */
+typedef struct dhd_if {
+ struct dhd_info *info; /* back pointer to dhd_info */
+ /* OS/stack specifics */
+ struct net_device *net;
+ struct net_device_stats stats;
+ int idx; /* iface idx in dongle */
+ uint subunit; /* subunit */
+ uint8 mac_addr[ETHER_ADDR_LEN]; /* assigned MAC address */
+ bool attached; /* Delayed attachment when unset */
+ bool txflowcontrol; /* Per interface flow control indicator */
+ char name[IFNAMSIZ+1]; /* linux interface name */
+ char dngl_name[IFNAMSIZ+1]; /* corresponding dongle interface name */
+ uint8 bssidx; /* bsscfg index for the interface */
+ bool set_macaddress;
+ bool set_multicast;
+} dhd_if_t;
+
+#ifdef WLMEDIA_HTSF
+typedef struct {
+ uint32 low;
+ uint32 high;
+} tsf_t;
+
+typedef struct {
+ uint32 last_cycle;
+ uint32 last_sec;
+ uint32 last_tsf;
+ uint32 coef; /* scaling factor */
+ uint32 coefdec1; /* first decimal */
+ uint32 coefdec2; /* second decimal */
+} htsf_t;
+
+typedef struct {
+ uint32 t1;
+ uint32 t2;
+ uint32 t3;
+ uint32 t4;
+} tstamp_t;
+
+static tstamp_t ts[TSMAX];
+static tstamp_t maxdelayts;
+static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0;
+
+#endif /* WLMEDIA_HTSF */
+
+struct ipv6_work_info_t {
+ uint8 if_idx;
+ char ipv6_addr[16];
+ unsigned long event;
+};
+
+/* Local private structure (extension of pub) */
+typedef struct dhd_info {
+#if defined(WL_WIRELESS_EXT)
+ wl_iw_t iw; /* wireless extensions state (must be first) */
+#endif /* defined(WL_WIRELESS_EXT) */
+
+ dhd_pub_t pub;
+ void *adapter; /* adapter information, interrupt, fw path etc. */
+ char fw_path[PATH_MAX]; /* path to firmware image */
+ char nv_path[PATH_MAX]; /* path to nvram vars file */
+
+ /* For supporting multiple interfaces */
+ dhd_if_t *iflist[DHD_MAX_IFS];
+
+ struct semaphore proto_sem;
+#ifdef PROP_TXSTATUS
+ spinlock_t wlfc_spinlock;
+
+#endif /* PROP_TXSTATUS */
+#ifdef WLMEDIA_HTSF
+ htsf_t htsf;
+#endif
+ wait_queue_head_t ioctl_resp_wait;
+ uint32 default_wd_interval;
+
+ struct timer_list timer;
+ bool wd_timer_valid;
+ struct tasklet_struct tasklet;
+ spinlock_t sdlock;
+ spinlock_t txqlock;
+ spinlock_t dhd_lock;
+
+ struct semaphore sdsem;
+ tsk_ctl_t thr_dpc_ctl;
+ tsk_ctl_t thr_wdt_ctl;
+
+ tsk_ctl_t thr_rxf_ctl;
+ spinlock_t rxf_lock;
+ bool rxthread_enabled;
+
+ /* Wakelocks */
+#if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ struct wake_lock wl_wifi; /* Wifi wakelock */
+ struct wake_lock wl_rxwake; /* Wifi rx wakelock */
+ struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */
+ struct wake_lock wl_wdwake; /* Wifi wd wakelock */
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ /* net_device interface lock, prevent race conditions among net_dev interface
+ * calls and wifi_on or wifi_off
+ */
+ struct mutex dhd_net_if_mutex;
+ struct mutex dhd_suspend_mutex;
+#endif
+ spinlock_t wakelock_spinlock;
+ uint32 wakelock_counter;
+ bool waive_wakelock;
+ uint32 wakelock_before_waive;
+ int wakelock_wd_counter;
+ int wakelock_rx_timeout_enable;
+ int wakelock_ctrl_timeout_enable;
+
+ /* Thread to issue ioctl for multicast */
+ wait_queue_head_t ctrl_wait;
+ atomic_t pend_8021x_cnt;
+ dhd_attach_states_t dhd_state;
+#ifdef SHOW_LOGTRACE
+ dhd_event_log_t event_data;
+#endif /* SHOW_LOGTRACE */
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
+
+#ifdef ARP_OFFLOAD_SUPPORT
+ u32 pend_ipaddr;
+#endif /* ARP_OFFLOAD_SUPPORT */
+#ifdef BCM_FD_AGGR
+ void *rpc_th;
+ void *rpc_osh;
+ struct timer_list rpcth_timer;
+ bool rpcth_timer_active;
+ bool fdaggr;
+#endif
+#ifdef DHDTCPACK_SUPPRESS
+ spinlock_t tcpack_lock;
+#endif /* DHDTCPACK_SUPPRESS */
+ void *dhd_deferred_wq;
+#ifdef DEBUG_CPU_FREQ
+ struct notifier_block freq_trans;
+ int __percpu *new_freq;
+#endif
+ unsigned int unit;
+ struct notifier_block pm_notifier;
+#ifdef SAR_SUPPORT
+ struct notifier_block sar_notifier;
+#endif
+#ifdef DHD_DEBUG
+ struct timer_list join_timer;
+ u32 join_timeout_val;
+ bool join_timer_active;
+ uint scan_time_count;
+ struct timer_list scan_timer;
+ bool scan_timer_active;
+#endif
+
+} dhd_info_t;
+
+/* Flag to indicate if we should download firmware on driver load */
+uint dhd_download_fw_on_driverload = TRUE;
+
+/* Definitions to provide path to the firmware and nvram
+ * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt"
+ */
+char firmware_path[MOD_PARAM_PATHLEN];
+char nvram_path[MOD_PARAM_PATHLEN];
+
+/* information string to keep firmware, chio, cheip version info visiable from log */
+char info_string[MOD_PARAM_INFOLEN];
+module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444);
+int op_mode = 0;
+int disable_proptx = 0;
+module_param(op_mode, int, 0644);
+extern int wl_control_wl_start(struct net_device *dev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(BCMLXSDMMC)
+struct semaphore dhd_registration_sem;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+
+/* deferred handlers */
+static void dhd_ifadd_event_handler(void *handle, void *event_info, u8 event);
+static void dhd_ifdel_event_handler(void *handle, void *event_info, u8 event);
+static void dhd_set_mac_addr_handler(void *handle, void *event_info, u8 event);
+static void dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event);
+static void dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event);
+
+#ifdef WL_CFG80211
+extern void dhd_netdev_free(struct net_device *ndev);
+#endif /* WL_CFG80211 */
+
+/* Error bits */
+module_param(dhd_msg_level, int, 0);
+
+#ifdef ARP_OFFLOAD_SUPPORT
+/* ARP offload enable */
+uint dhd_arp_enable = TRUE;
+module_param(dhd_arp_enable, uint, 0);
+
+/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */
+
+uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY;
+
+module_param(dhd_arp_mode, uint, 0);
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+/* Disable Prop tx */
+module_param(disable_proptx, int, 0644);
+/* load firmware and/or nvram values from the filesystem */
+module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660);
+module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0660);
+
+/* Watchdog interval */
+
+/* extend watchdog expiration to 2 seconds when DPC is running */
+#define WATCHDOG_EXTEND_INTERVAL (2000)
+
+uint dhd_watchdog_ms = 10;
+module_param(dhd_watchdog_ms, uint, 0);
+
+#if defined(DHD_DEBUG)
+/* Console poll interval */
+uint dhd_console_ms = 0;
+module_param(dhd_console_ms, uint, 0644);
+#endif /* defined(DHD_DEBUG) */
+
+
+uint dhd_slpauto = TRUE;
+module_param(dhd_slpauto, uint, 0);
+
+#ifdef PKT_FILTER_SUPPORT
+/* Global Pkt filter enable control */
+uint dhd_pkt_filter_enable = TRUE;
+module_param(dhd_pkt_filter_enable, uint, 0);
+#endif
+
+/* Pkt filter init setup */
+uint dhd_pkt_filter_init = 0;
+module_param(dhd_pkt_filter_init, uint, 0);
+
+/* Pkt filter mode control */
+uint dhd_master_mode = TRUE;
+module_param(dhd_master_mode, uint, 0);
+
+int dhd_watchdog_prio = 0;
+module_param(dhd_watchdog_prio, int, 0);
+
+/* DPC thread priority */
+int dhd_dpc_prio = CUSTOM_DPC_PRIO_SETTING;
+module_param(dhd_dpc_prio, int, 0);
+
+/* RX frame thread priority */
+int dhd_rxf_prio = CUSTOM_RXF_PRIO_SETTING;
+module_param(dhd_rxf_prio, int, 0);
+
+#if !defined(BCMDHDUSB)
+extern int dhd_dongle_ramsize;
+module_param(dhd_dongle_ramsize, int, 0);
+#endif /* BCMDHDUSB */
+
+/* Keep track of number of instances */
+static int dhd_found = 0;
+static int instance_base = 0; /* Starting instance number */
+module_param(instance_base, int, 0644);
+
+/* Control fw roaming */
+uint dhd_roam_disable = 0;
+
+/* Control radio state */
+uint dhd_radio_up = 1;
+
+/* Network inteface name */
+char iface_name[IFNAMSIZ] = {'\0'};
+module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
+
+/* The following are specific to the SDIO dongle */
+
+/* IOCTL response timeout */
+int dhd_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
+
+/* Idle timeout for backplane clock */
+int dhd_idletime = DHD_IDLETIME_TICKS;
+module_param(dhd_idletime, int, 0);
+
+/* Use polling */
+uint dhd_poll = FALSE;
+module_param(dhd_poll, uint, 0);
+
+/* Use interrupts */
+uint dhd_intr = TRUE;
+module_param(dhd_intr, uint, 0);
+
+/* SDIO Drive Strength (in milliamps) */
+uint dhd_sdiod_drive_strength = 6;
+module_param(dhd_sdiod_drive_strength, uint, 0);
+
+/* Tx/Rx bounds */
+extern uint dhd_txbound;
+extern uint dhd_rxbound;
+module_param(dhd_txbound, uint, 0);
+module_param(dhd_rxbound, uint, 0);
+
+/* Deferred transmits */
+extern uint dhd_deferred_tx;
+module_param(dhd_deferred_tx, uint, 0);
+
+#ifdef BCMDBGFS
+extern void dhd_dbg_init(dhd_pub_t *dhdp);
+extern void dhd_dbg_remove(void);
+#endif /* BCMDBGFS */
+
+
+
+#ifdef SDTEST
+/* Echo packet generator (pkts/s) */
+uint dhd_pktgen = 0;
+module_param(dhd_pktgen, uint, 0);
+
+/* Echo packet len (0 => sawtooth, max 2040) */
+uint dhd_pktgen_len = 0;
+module_param(dhd_pktgen_len, uint, 0);
+#endif /* SDTEST */
+
+
+extern char dhd_version[];
+
+int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
+static void dhd_net_if_lock_local(dhd_info_t *dhd);
+static void dhd_net_if_unlock_local(dhd_info_t *dhd);
+static void dhd_suspend_lock(dhd_pub_t *dhdp);
+static void dhd_suspend_unlock(dhd_pub_t *dhdp);
+
+#ifdef WLMEDIA_HTSF
+void htsf_update(dhd_info_t *dhd, void *data);
+tsf_t prev_tsf, cur_tsf;
+
+uint32 dhd_get_htsf(dhd_info_t *dhd, int ifidx);
+static int dhd_ioctl_htsf_get(dhd_info_t *dhd, int ifidx);
+static void dhd_dump_latency(void);
+static void dhd_htsf_addtxts(dhd_pub_t *dhdp, void *pktbuf);
+static void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf);
+static void dhd_dump_htsfhisto(histo_t *his, char *s);
+#endif /* WLMEDIA_HTSF */
+
+/* Monitor interface */
+int dhd_monitor_init(void *dhd_pub);
+int dhd_monitor_uninit(void);
+
+#ifdef DHD_DEBUG
+static void dhd_scan_timeout(ulong data);
+static void dhd_join_timeout(ulong data);
+#endif
+
+
+#if defined(WL_WIRELESS_EXT)
+struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
+#endif /* defined(WL_WIRELESS_EXT) */
+
+static void dhd_dpc(ulong data);
+/* forward decl */
+extern int dhd_wait_pend8021x(struct net_device *dev);
+void dhd_os_wd_timer_extend(void *bus, bool extend);
+
+#ifdef TOE
+#ifndef BDC
+#error TOE requires BDC
+#endif /* !BDC */
+static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol);
+static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol);
+#endif /* TOE */
+
+static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, uint16 pktlen,
+ wl_event_msg_t *event_ptr, void **data_ptr);
+#if defined(SUPPORT_P2P_GO_PS)
+#ifdef PROP_TXSTATUS
+static int dhd_wakelock_waive(dhd_info_t *dhdinfo);
+static int dhd_wakelock_restore(dhd_info_t *dhdinfo);
+#endif
+#endif /* defined(SUPPORT_P2P_GO_PS) */
+
+#if defined(CONFIG_PM_SLEEP)
+static int dhd_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored)
+{
+ int ret = NOTIFY_DONE;
+ bool suspend = FALSE;
+ dhd_info_t *dhdinfo = (dhd_info_t*)container_of(nfb, struct dhd_info, pm_notifier);
+
+ BCM_REFERENCE(dhdinfo);
+ switch (action) {
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ suspend = TRUE;
+ break;
+ case PM_POST_HIBERNATION:
+ case PM_POST_SUSPEND:
+ suspend = FALSE;
+ break;
+ }
+
+#if defined(SUPPORT_P2P_GO_PS)
+#ifdef PROP_TXSTATUS
+ if (suspend) {
+ dhd_wakelock_waive(dhdinfo);
+ dhd_wlfc_suspend(&dhdinfo->pub);
+ dhd_wakelock_restore(dhdinfo);
+ } else {
+ dhd_wlfc_resume(&dhdinfo->pub);
+ }
+
+#endif
+#endif /* defined(SUPPORT_P2P_GO_PS) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
+ KERNEL_VERSION(2, 6, 39))
+ dhd_mmc_suspend = suspend;
+ smp_mb();
+#endif
+ return ret;
+}
+
+/* to make sure we won't register the same notifier twice, otherwise a loop is likely to be
+ * created in kernel notifier link list (with 'next' pointing to itself)
+ */
+static bool dhd_pm_notifier_registered = FALSE;
+
+extern int register_pm_notifier(struct notifier_block *nb);
+extern int unregister_pm_notifier(struct notifier_block *nb);
+#endif /* defined(CONFIG_PM_SLEEP) */
+
+#ifdef SAR_SUPPORT
+static int dhd_sar_callback(struct notifier_block *nfb, unsigned long action, void *ignored)
+{
+ dhd_info_t *dhd = (dhd_info_t*)container_of(nfb, struct dhd_info, sar_notifier);
+ char iovbuf[32];
+ s32 sar_enable;
+ int ret = 0;
+
+ /* '1' means activate sarlimit and '0' means back to normal state (deactivate
+ * sarlimit)
+ */
+ sar_enable = action ? 1 : 0;
+
+ bcm_mkiovar("sar_enable", (char *)&sar_enable, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(&dhd->pub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("%s wl sar_enable %d failed %d\n", __FUNCTION__, sar_enable, ret));
+
+ return NOTIFY_DONE;
+}
+
+static bool dhd_sar_notifier_registered = FALSE;
+
+extern int register_notifier_by_sar(struct notifier_block *nb);
+extern int unregister_notifier_by_sar(struct notifier_block *nb);
+#endif /* defined(SAR_SUPPORT) */
+
+/* Request scheduling of the bus rx frame */
+static void dhd_sched_rxf(dhd_pub_t *dhdp, void *skb);
+static void dhd_os_rxflock(dhd_pub_t *pub);
+static void dhd_os_rxfunlock(dhd_pub_t *pub);
+
+static inline int dhd_rxf_enqueue(dhd_pub_t *dhdp, void* skb)
+{
+ uint32 store_idx;
+ uint32 sent_idx;
+
+ if (!skb) {
+ DHD_ERROR(("dhd_rxf_enqueue: NULL skb!!!\n"));
+ return BCME_ERROR;
+ }
+
+ dhd_os_rxflock(dhdp);
+ store_idx = dhdp->store_idx;
+ sent_idx = dhdp->sent_idx;
+ if (dhdp->skbbuf[store_idx] != NULL) {
+ /* Make sure the previous packets are processed */
+ dhd_os_rxfunlock(dhdp);
+#ifdef RXF_DEQUEUE_ON_BUSY
+ DHD_TRACE(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n",
+ skb, store_idx, sent_idx));
+ return BCME_BUSY;
+#else /* RXF_DEQUEUE_ON_BUSY */
+ DHD_ERROR(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n",
+ skb, store_idx, sent_idx));
+ /* removed msleep here, should use wait_event_timeout if we
+ * want to give rx frame thread a chance to run
+ */
+#if defined(WAIT_DEQUEUE)
+ OSL_SLEEP(1);
+#endif
+ return BCME_ERROR;
+#endif /* RXF_DEQUEUE_ON_BUSY */
+ }
+ DHD_TRACE(("dhd_rxf_enqueue: Store SKB %p. idx %d -> %d\n",
+ skb, store_idx, (store_idx + 1) & (MAXSKBPEND - 1)));
+ dhdp->skbbuf[store_idx] = skb;
+ dhdp->store_idx = (store_idx + 1) & (MAXSKBPEND - 1);
+ dhd_os_rxfunlock(dhdp);
+
+ return BCME_OK;
+}
+
+static inline void* dhd_rxf_dequeue(dhd_pub_t *dhdp)
+{
+ uint32 store_idx;
+ uint32 sent_idx;
+ void *skb;
+
+ dhd_os_rxflock(dhdp);
+
+ store_idx = dhdp->store_idx;
+ sent_idx = dhdp->sent_idx;
+ skb = dhdp->skbbuf[sent_idx];
+
+ if (skb == NULL) {
+ dhd_os_rxfunlock(dhdp);
+ DHD_ERROR(("dhd_rxf_dequeue: Dequeued packet is NULL, store idx %d sent idx %d\n",
+ store_idx, sent_idx));
+ return NULL;
+ }
+
+ dhdp->skbbuf[sent_idx] = NULL;
+ dhdp->sent_idx = (sent_idx + 1) & (MAXSKBPEND - 1);
+
+ DHD_TRACE(("dhd_rxf_dequeue: netif_rx_ni(%p), sent idx %d\n",
+ skb, sent_idx));
+
+ dhd_os_rxfunlock(dhdp);
+
+ return skb;
+}
+
+static int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost)
+{
+ dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+
+ if (prepost) { /* pre process */
+ dhd_read_macaddr(dhd);
+ } else { /* post process */
+ dhd_write_macaddr(&dhd->pub.mac);
+ }
+
+ return 0;
+}
+
+#if defined(PKT_FILTER_SUPPORT) && !defined(GAN_LITE_NAT_KEEPALIVE_FILTER)
+static bool
+_turn_on_arp_filter(dhd_pub_t *dhd, int op_mode)
+{
+ bool _apply = FALSE;
+ /* In case of IBSS mode, apply arp pkt filter */
+ if (op_mode & DHD_FLAG_IBSS_MODE) {
+ _apply = TRUE;
+ goto exit;
+ }
+ /* In case of P2P GO or GC, apply pkt filter to pass arp pkt to host */
+#if defined(ARP_OFFLOAD_SUPPORT)
+ if ((dhd->arp_version == 1) &&
+#else
+ if (
+#endif
+ (op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))) {
+ _apply = TRUE;
+ goto exit;
+ }
+
+exit:
+ return _apply;
+}
+#endif /* PKT_FILTER_SUPPORT && !GAN_LITE_NAT_KEEPALIVE_FILTER */
+
+void dhd_set_packet_filter(dhd_pub_t *dhd)
+{
+#ifdef PKT_FILTER_SUPPORT
+ int i;
+
+ DHD_TRACE(("%s: enter\n", __FUNCTION__));
+ if (dhd_pkt_filter_enable) {
+ for (i = 0; i < dhd->pktfilter_count; i++) {
+ dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
+ }
+ }
+#endif /* PKT_FILTER_SUPPORT */
+}
+
+void dhd_enable_packet_filter(int value, dhd_pub_t *dhd)
+{
+#ifdef PKT_FILTER_SUPPORT
+ int i;
+
+ DHD_TRACE(("%s: enter, value = %d\n", __FUNCTION__, value));
+ /* 1 - Enable packet filter, only allow unicast packet to send up */
+ /* 0 - Disable packet filter */
+ if (dhd_pkt_filter_enable && (!value ||
+ (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress)))
+ {
+ for (i = 0; i < dhd->pktfilter_count; i++) {
+#ifndef GAN_LITE_NAT_KEEPALIVE_FILTER
+ if (value && (i == DHD_ARP_FILTER_NUM) &&
+ !_turn_on_arp_filter(dhd, dhd->op_mode)) {
+ DHD_TRACE(("Do not turn on ARP white list pkt filter:"
+ "val %d, cnt %d, op_mode 0x%x\n",
+ value, i, dhd->op_mode));
+ continue;
+ }
+#endif /* !GAN_LITE_NAT_KEEPALIVE_FILTER */
+ dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
+ value, dhd_master_mode);
+ }
+ }
+#endif /* PKT_FILTER_SUPPORT */
+}
+
+static int dhd_set_suspend(int value, dhd_pub_t *dhd)
+{
+#ifndef SUPPORT_PM2_ONLY
+ int power_mode = PM_MAX;
+#endif /* SUPPORT_PM2_ONLY */
+ /* wl_pkt_filter_enable_t enable_parm; */
+ char iovbuf[32];
+ int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */
+#ifndef ENABLE_FW_ROAM_SUSPEND
+ uint roamvar = 1;
+#endif /* ENABLE_FW_ROAM_SUSPEND */
+ uint nd_ra_filter = 0;
+ int ret = 0;
+
+#ifdef DYNAMIC_SWOOB_DURATION
+#ifndef CUSTOM_INTR_WIDTH
+#define CUSTOM_INTR_WIDTH 100
+#endif /* CUSTOM_INTR_WIDTH */
+ int intr_width = 0;
+#endif /* DYNAMIC_SWOOB_DURATION */
+ if (!dhd)
+ return -ENODEV;
+
+ DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n",
+ __FUNCTION__, value, dhd->in_suspend));
+
+ dhd_suspend_lock(dhd);
+
+#ifdef CUSTOM_SET_CPUCORE
+ DHD_TRACE(("%s set cpucore(suspend%d)\n", __FUNCTION__, value));
+ /* set specific cpucore */
+ dhd_set_cpucore(dhd, TRUE);
+#endif /* CUSTOM_SET_CPUCORE */
+ if (dhd->up) {
+ if (value && dhd->in_suspend) {
+#ifdef PKT_FILTER_SUPPORT
+ dhd->early_suspended = 1;
+#endif
+ /* Kernel suspended */
+ DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__));
+
+#ifndef SUPPORT_PM2_ONLY
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
+ sizeof(power_mode), TRUE, 0);
+#endif /* SUPPORT_PM2_ONLY */
+
+ /* Enable packet filter, only allow unicast packet to send up */
+ dhd_enable_packet_filter(1, dhd);
+
+
+ /* If DTIM skip is set up as default, force it to wake
+ * each third DTIM for better power savings. Note that
+ * one side effect is a chance to miss BC/MC packet.
+ */
+ bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd);
+ bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+ 4, iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf),
+ TRUE, 0) < 0)
+ DHD_ERROR(("%s: set dtim failed\n", __FUNCTION__));
+
+#ifndef ENABLE_FW_ROAM_SUSPEND
+ /* Disable firmware roaming during suspend */
+ bcm_mkiovar("roam_off", (char *)&roamvar, 4,
+ iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif /* ENABLE_FW_ROAM_SUSPEND */
+ if (FW_SUPPORTED(dhd, ndoe)) {
+ /* enable IPv6 RA filter in firmware during suspend */
+ nd_ra_filter = 1;
+ bcm_mkiovar("nd_ra_filter_enable", (char *)&nd_ra_filter, 4,
+ iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("failed to set nd_ra_filter (%d)\n",
+ ret));
+ }
+#ifdef DYNAMIC_SWOOB_DURATION
+ intr_width = CUSTOM_INTR_WIDTH;
+ bcm_mkiovar("bus:intr_width", (char *)&intr_width, 4,
+ iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("failed to set intr_width (%d)\n", ret));
+#endif /* DYNAMIC_SWOOB_DURATION */
+ } else {
+#ifdef PKT_FILTER_SUPPORT
+ dhd->early_suspended = 0;
+#endif
+ /* Kernel resumed */
+ DHD_ERROR(("%s: Remove extra suspend setting \n", __FUNCTION__));
+#ifdef DYNAMIC_SWOOB_DURATION
+ intr_width = 0;
+ bcm_mkiovar("bus:intr_width", (char *)&intr_width, 4,
+ iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("failed to set intr_width (%d)\n", ret));
+#endif /* DYNAMIC_SWOOB_DURATION */
+
+#ifndef SUPPORT_PM2_ONLY
+ power_mode = PM_FAST;
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
+ sizeof(power_mode), TRUE, 0);
+#endif /* SUPPORT_PM2_ONLY */
+#ifdef PKT_FILTER_SUPPORT
+ /* disable pkt filter */
+ dhd_enable_packet_filter(0, dhd);
+#endif /* PKT_FILTER_SUPPORT */
+
+ /* restore pre-suspend setting for dtim_skip */
+ bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+ 4, iovbuf, sizeof(iovbuf));
+
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#ifndef ENABLE_FW_ROAM_SUSPEND
+ roamvar = dhd_roam_disable;
+ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf,
+ sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif /* ENABLE_FW_ROAM_SUSPEND */
+ if (FW_SUPPORTED(dhd, ndoe)) {
+ /* disable IPv6 RA filter in firmware during suspend */
+ nd_ra_filter = 0;
+ bcm_mkiovar("nd_ra_filter_enable", (char *)&nd_ra_filter, 4,
+ iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("failed to set nd_ra_filter (%d)\n",
+ ret));
+ }
+ }
+ }
+ dhd_suspend_unlock(dhd);
+
+ return 0;
+}
+
+static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force)
+{
+ dhd_pub_t *dhdp = &dhd->pub;
+ int ret = 0;
+
+ DHD_OS_WAKE_LOCK(dhdp);
+ /* Set flag when early suspend was called */
+ dhdp->in_suspend = val;
+ if ((force || !dhdp->suspend_disable_flag) &&
+ dhd_support_sta_mode(dhdp))
+ {
+ ret = dhd_set_suspend(val, dhdp);
+ }
+
+ DHD_OS_WAKE_UNLOCK(dhdp);
+ return ret;
+}
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
+static void dhd_early_suspend(struct early_suspend *h)
+{
+ struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
+ DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__));
+
+ if (dhd)
+ dhd_suspend_resume_helper(dhd, 1, 0);
+}
+
+static void dhd_late_resume(struct early_suspend *h)
+{
+ struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
+ DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__));
+
+ if (dhd)
+ dhd_suspend_resume_helper(dhd, 0, 0);
+}
+#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
+
+/*
+ * Generalized timeout mechanism. Uses spin sleep with exponential back-off until
+ * the sleep time reaches one jiffy, then switches over to task delay. Usage:
+ *
+ * dhd_timeout_start(&tmo, usec);
+ * while (!dhd_timeout_expired(&tmo))
+ * if (poll_something())
+ * break;
+ * if (dhd_timeout_expired(&tmo))
+ * fatal();
+ */
+
+void
+dhd_timeout_start(dhd_timeout_t *tmo, uint usec)
+{
+ tmo->limit = usec;
+ tmo->increment = 0;
+ tmo->elapsed = 0;
+ tmo->tick = jiffies_to_usecs(1);
+}
+
+int
+dhd_timeout_expired(dhd_timeout_t *tmo)
+{
+ /* Does nothing the first call */
+ if (tmo->increment == 0) {
+ tmo->increment = 1;
+ return 0;
+ }
+
+ if (tmo->elapsed >= tmo->limit)
+ return 1;
+
+ /* Add the delay that's about to take place */
+ tmo->elapsed += tmo->increment;
+
+ if ((!CAN_SLEEP()) || tmo->increment < tmo->tick) {
+ OSL_DELAY(tmo->increment);
+ tmo->increment *= 2;
+ if (tmo->increment > tmo->tick)
+ tmo->increment = tmo->tick;
+ } else {
+ wait_queue_head_t delay_wait;
+ DECLARE_WAITQUEUE(wait, current);
+ init_waitqueue_head(&delay_wait);
+ add_wait_queue(&delay_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ remove_wait_queue(&delay_wait, &wait);
+ set_current_state(TASK_RUNNING);
+ }
+
+ return 0;
+}
+
+int
+dhd_net2idx(dhd_info_t *dhd, struct net_device *net)
+{
+ int i = 0;
+
+ ASSERT(dhd);
+ while (i < DHD_MAX_IFS) {
+ if (dhd->iflist[i] && dhd->iflist[i]->net && (dhd->iflist[i]->net == net))
+ return i;
+ i++;
+ }
+
+ return DHD_BAD_IF;
+}
+
+struct net_device * dhd_idx2net(void *pub, int ifidx)
+{
+ struct dhd_pub *dhd_pub = (struct dhd_pub *)pub;
+ struct dhd_info *dhd_info;
+
+ if (!dhd_pub || ifidx < 0 || ifidx >= DHD_MAX_IFS)
+ return NULL;
+ dhd_info = dhd_pub->info;
+ if (dhd_info && dhd_info->iflist[ifidx])
+ return dhd_info->iflist[ifidx]->net;
+ return NULL;
+}
+
+int
+dhd_ifname2idx(dhd_info_t *dhd, char *name)
+{
+ int i = DHD_MAX_IFS;
+
+ ASSERT(dhd);
+
+ if (name == NULL || *name == '\0')
+ return 0;
+
+ while (--i > 0)
+ if (dhd->iflist[i] && !strncmp(dhd->iflist[i]->dngl_name, name, IFNAMSIZ))
+ break;
+
+ DHD_TRACE(("%s: return idx %d for \"%s\"\n", __FUNCTION__, i, name));
+
+ return i; /* default - the primary interface */
+}
+
+char *
+dhd_ifname(dhd_pub_t *dhdp, int ifidx)
+{
+ dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+
+ ASSERT(dhd);
+
+ if (ifidx < 0 || ifidx >= DHD_MAX_IFS) {
+ DHD_ERROR(("%s: ifidx %d out of range\n", __FUNCTION__, ifidx));
+ return "<if_bad>";
+ }
+
+ if (dhd->iflist[ifidx] == NULL) {
+ DHD_ERROR(("%s: null i/f %d\n", __FUNCTION__, ifidx));
+ return "<if_null>";
+ }
+
+ if (dhd->iflist[ifidx]->net)
+ return dhd->iflist[ifidx]->net->name;
+
+ return "<if_none>";
+}
+
+uint8 *
+dhd_bssidx2bssid(dhd_pub_t *dhdp, int idx)
+{
+ int i;
+ dhd_info_t *dhd = (dhd_info_t *)dhdp;
+
+ ASSERT(dhd);
+ for (i = 0; i < DHD_MAX_IFS; i++)
+ if (dhd->iflist[i] && dhd->iflist[i]->bssidx == idx)
+ return dhd->iflist[i]->mac_addr;
+
+ return NULL;
+}
+
+
+static void
+_dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
+{
+ struct net_device *dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ struct netdev_hw_addr *ha;
+#else
+ struct dev_mc_list *mclist;
+#endif
+ uint32 allmulti, cnt;
+
+ wl_ioctl_t ioc;
+ char *buf, *bufp;
+ uint buflen;
+ int ret;
+
+ if (!dhd->iflist[ifidx]) {
+ DHD_ERROR(("%s : dhd->iflist[%d] was NULL\n", __FUNCTION__, ifidx));
+ return;
+ }
+ dev = dhd->iflist[ifidx]->net;
+ if (!dev)
+ return;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ netif_addr_lock_bh(dev);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ cnt = netdev_mc_count(dev);
+#else
+ cnt = dev->mc_count;
+#endif /* LINUX_VERSION_CODE */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ netif_addr_unlock_bh(dev);
+#endif
+
+ /* Determine initial value of allmulti flag */
+ allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE;
+
+ /* Send down the multicast list first. */
+
+
+ buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETHER_ADDR_LEN);
+ if (!(bufp = buf = MALLOC(dhd->pub.osh, buflen))) {
+ DHD_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
+ dhd_ifname(&dhd->pub, ifidx), cnt));
+ return;
+ }
+
+ strncpy(bufp, "mcast_list", buflen - 1);
+ bufp[buflen - 1] = '\0';
+ bufp += strlen("mcast_list") + 1;
+
+ cnt = htol32(cnt);
+ memcpy(bufp, &cnt, sizeof(cnt));
+ bufp += sizeof(cnt);
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ netif_addr_lock_bh(dev);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ netdev_for_each_mc_addr(ha, dev) {
+ if (!cnt)
+ break;
+ memcpy(bufp, ha->addr, ETHER_ADDR_LEN);
+ bufp += ETHER_ADDR_LEN;
+ cnt--;
+ }
+#else
+ for (mclist = dev->mc_list; (mclist && (cnt > 0));
+ cnt--, mclist = mclist->next) {
+ memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN);
+ bufp += ETHER_ADDR_LEN;
+ }
+#endif /* LINUX_VERSION_CODE */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ netif_addr_unlock_bh(dev);
+#endif
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = WLC_SET_VAR;
+ ioc.buf = buf;
+ ioc.len = buflen;
+ ioc.set = TRUE;
+
+ ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ if (ret < 0) {
+ DHD_ERROR(("%s: set mcast_list failed, cnt %d\n",
+ dhd_ifname(&dhd->pub, ifidx), cnt));
+ allmulti = cnt ? TRUE : allmulti;
+ }
+
+ MFREE(dhd->pub.osh, buf, buflen);
+
+ /* Now send the allmulti setting. This is based on the setting in the
+ * net_device flags, but might be modified above to be turned on if we
+ * were trying to set some addresses and dongle rejected it...
+ */
+
+ buflen = sizeof("allmulti") + sizeof(allmulti);
+ if (!(buf = MALLOC(dhd->pub.osh, buflen))) {
+ DHD_ERROR(("%s: out of memory for allmulti\n", dhd_ifname(&dhd->pub, ifidx)));
+ return;
+ }
+ allmulti = htol32(allmulti);
+
+ if (!bcm_mkiovar("allmulti", (void*)&allmulti, sizeof(allmulti), buf, buflen)) {
+ DHD_ERROR(("%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
+ dhd_ifname(&dhd->pub, ifidx), (int)sizeof(allmulti), buflen));
+ MFREE(dhd->pub.osh, buf, buflen);
+ return;
+ }
+
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = WLC_SET_VAR;
+ ioc.buf = buf;
+ ioc.len = buflen;
+ ioc.set = TRUE;
+
+ ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ if (ret < 0) {
+ DHD_ERROR(("%s: set allmulti %d failed\n",
+ dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)));
+ }
+
+ MFREE(dhd->pub.osh, buf, buflen);
+
+ /* Finally, pick up the PROMISC flag as well, like the NIC driver does */
+
+ allmulti = (dev->flags & IFF_PROMISC) ? TRUE : FALSE;
+
+ allmulti = htol32(allmulti);
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = WLC_SET_PROMISC;
+ ioc.buf = &allmulti;
+ ioc.len = sizeof(allmulti);
+ ioc.set = TRUE;
+
+ ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ if (ret < 0) {
+ DHD_ERROR(("%s: set promisc %d failed\n",
+ dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)));
+ }
+}
+
+int
+_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, uint8 *addr)
+{
+ char buf[32];
+ wl_ioctl_t ioc;
+ int ret;
+
+ if (!bcm_mkiovar("cur_etheraddr", (char*)addr, ETHER_ADDR_LEN, buf, 32)) {
+ DHD_ERROR(("%s: mkiovar failed for cur_etheraddr\n", dhd_ifname(&dhd->pub, ifidx)));
+ return -1;
+ }
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = WLC_SET_VAR;
+ ioc.buf = buf;
+ ioc.len = 32;
+ ioc.set = TRUE;
+
+ ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ if (ret < 0) {
+ DHD_ERROR(("%s: set cur_etheraddr failed\n", dhd_ifname(&dhd->pub, ifidx)));
+ } else {
+ memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETHER_ADDR_LEN);
+ if (ifidx == 0)
+ memcpy(dhd->pub.mac.octet, addr, ETHER_ADDR_LEN);
+ }
+
+ return ret;
+}
+
+#ifdef SOFTAP
+extern struct net_device *ap_net_dev;
+extern tsk_ctl_t ap_eth_ctl; /* ap netdev heper thread ctl */
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+int32 dhd_role_to_nl80211_iftype(int32 role)
+{
+ switch (role) {
+ case WLC_E_IF_ROLE_STA:
+ return NL80211_IFTYPE_STATION;
+ case WLC_E_IF_ROLE_AP:
+ return NL80211_IFTYPE_AP;
+ case WLC_E_IF_ROLE_WDS:
+ return NL80211_IFTYPE_WDS;
+ case WLC_E_IF_ROLE_P2P_GO:
+ return NL80211_IFTYPE_P2P_GO;
+ case WLC_E_IF_ROLE_P2P_CLIENT:
+ return NL80211_IFTYPE_P2P_CLIENT;
+ case WLC_E_IF_ROLE_IBSS:
+ return NL80211_IFTYPE_ADHOC;
+ default:
+ return NL80211_IFTYPE_UNSPECIFIED;
+ }
+}
+#endif /* OEM_ANDROID && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */
+
+static void
+dhd_ifadd_event_handler(void *handle, void *event_info, u8 event)
+{
+ dhd_info_t *dhd = handle;
+ dhd_if_event_t *if_event = event_info;
+ struct net_device *ndev;
+ int ifidx, bssidx;
+ int ret;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+ struct wireless_dev *vwdev, *primary_wdev;
+ struct net_device *primary_ndev;
+#endif /* OEM_ANDROID && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */
+
+ if (event != DHD_WQ_WORK_IF_ADD) {
+ DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
+ return;
+ }
+
+ if (!dhd) {
+ DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__));
+ return;
+ }
+
+ if (!if_event) {
+ DHD_ERROR(("%s: event data is null \n", __FUNCTION__));
+ return;
+ }
+
+ dhd_net_if_lock_local(dhd);
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+
+ ifidx = if_event->event.ifidx;
+ bssidx = if_event->event.bssidx;
+ DHD_TRACE(("%s: registering if with ifidx %d\n", __FUNCTION__, ifidx));
+
+ ndev = dhd_allocate_if(&dhd->pub, ifidx, if_event->name,
+ if_event->mac, bssidx, TRUE, if_event->name);
+ if (!ndev) {
+ DHD_ERROR(("%s: net device alloc failed \n", __FUNCTION__));
+ goto done;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+ vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
+ if (unlikely(!vwdev)) {
+ DHD_ERROR(("Could not allocate wireless device\n"));
+ goto done;
+ }
+ primary_ndev = dhd->pub.info->iflist[0]->net;
+ primary_wdev = ndev_to_wdev(primary_ndev);
+ vwdev->wiphy = primary_wdev->wiphy;
+ vwdev->iftype = dhd_role_to_nl80211_iftype(if_event->event.role);
+ vwdev->netdev = ndev;
+ ndev->ieee80211_ptr = vwdev;
+ SET_NETDEV_DEV(ndev, wiphy_dev(vwdev->wiphy));
+ DHD_ERROR(("virtual interface(%s) is created\n", if_event->name));
+#endif /* OEM_ANDROID && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */
+
+ ret = dhd_register_if(&dhd->pub, ifidx, TRUE);
+ if (ret != BCME_OK) {
+ DHD_ERROR(("%s: dhd_register_if failed\n", __FUNCTION__));
+ dhd_remove_if(&dhd->pub, ifidx, TRUE);
+ }
+done:
+ MFREE(dhd->pub.osh, if_event, sizeof(dhd_if_event_t));
+
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ dhd_net_if_unlock_local(dhd);
+}
+
+static void
+dhd_ifdel_event_handler(void *handle, void *event_info, u8 event)
+{
+ dhd_info_t *dhd = handle;
+ int ifidx;
+ dhd_if_event_t *if_event = event_info;
+
+
+ if (event != DHD_WQ_WORK_IF_DEL) {
+ DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
+ return;
+ }
+
+ if (!dhd) {
+ DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__));
+ return;
+ }
+
+ if (!if_event) {
+ DHD_ERROR(("%s: event data is null \n", __FUNCTION__));
+ return;
+ }
+
+ dhd_net_if_lock_local(dhd);
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+
+ ifidx = if_event->event.ifidx;
+ DHD_TRACE(("Removing interface with idx %d\n", ifidx));
+
+ dhd_remove_if(&dhd->pub, ifidx, TRUE);
+
+ MFREE(dhd->pub.osh, if_event, sizeof(dhd_if_event_t));
+
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ dhd_net_if_unlock_local(dhd);
+}
+
+static void
+dhd_set_mac_addr_handler(void *handle, void *event_info, u8 event)
+{
+ dhd_info_t *dhd = handle;
+ dhd_if_t *ifp = event_info;
+
+#ifdef SOFTAP
+ unsigned long flags;
+ bool in_ap = FALSE;
+#endif
+
+ if (event != DHD_WQ_WORK_SET_MAC) {
+ DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
+ }
+
+ if (!dhd) {
+ DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__));
+ return;
+ }
+
+#ifdef SOFTAP
+ flags = dhd_os_spin_lock(&dhd->pub);
+ in_ap = (ap_net_dev != NULL);
+ dhd_os_spin_unlock(&dhd->pub, flags);
+
+ if (in_ap) {
+ DHD_ERROR(("attempt to set MAC for %s in AP Mode, blocked. \n",
+ ifp->net->name));
+ return;
+ }
+#endif
+ dhd_net_if_lock_local(dhd);
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+
+ if (ifp == NULL || !dhd->pub.up) {
+ DHD_ERROR(("%s: interface info not available/down \n", __FUNCTION__));
+ goto done;
+ }
+
+ DHD_ERROR(("%s: MACID is overwritten\n", __FUNCTION__));
+ ifp->set_macaddress = FALSE;
+ if (_dhd_set_mac_address(dhd, ifp->idx, ifp->mac_addr) == 0)
+ DHD_INFO(("%s: MACID is overwritten\n", __FUNCTION__));
+ else
+ DHD_ERROR(("%s: _dhd_set_mac_address() failed\n", __FUNCTION__));
+
+done:
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ dhd_net_if_unlock_local(dhd);
+}
+
+static void
+dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event)
+{
+ dhd_info_t *dhd = handle;
+ int ifidx = (int)((long int)event_info);
+ dhd_if_t *ifp = NULL;
+
+#ifdef SOFTAP
+ bool in_ap = FALSE;
+ unsigned long flags;
+#endif
+
+ if (event != DHD_WQ_WORK_SET_MCAST_LIST) {
+ DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
+ return;
+ }
+
+ if (!dhd) {
+ DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__));
+ return;
+ }
+
+#ifdef SOFTAP
+ ifp = dhd->iflist[ifidx];
+ flags = dhd_os_spin_lock(&dhd->pub);
+ in_ap = (ap_net_dev != NULL);
+ dhd_os_spin_unlock(&dhd->pub, flags);
+
+ if (in_ap) {
+ DHD_ERROR(("set MULTICAST list for %s in AP Mode, blocked. \n",
+ ifp->net->name));
+ ifp->set_multicast = FALSE;
+ return;
+ }
+#endif
+
+ dhd_net_if_lock_local(dhd);
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+
+ /* Be sure to make corresponding (dhd_if_t*) pointer after lock() */
+ ifp = dhd->iflist[ifidx];
+
+ if (ifp == NULL || !dhd->pub.up) {
+ DHD_ERROR(("%s: interface info not available/down \n", __FUNCTION__));
+ goto done;
+ }
+
+ ifidx = ifp->idx;
+
+
+ _dhd_set_multicast_list(dhd, ifidx);
+ DHD_INFO(("%s: set multicast list for if %d\n", __FUNCTION__, ifidx));
+
+done:
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ dhd_net_if_unlock_local(dhd);
+}
+
+static int
+dhd_set_mac_address(struct net_device *dev, void *addr)
+{
+ int ret = 0;
+
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)addr;
+ int ifidx;
+ dhd_if_t *dhdif;
+
+ ifidx = dhd_net2idx(dhd, dev);
+ if (ifidx == DHD_BAD_IF)
+ return -1;
+
+ dhdif = dhd->iflist[ifidx];
+
+ dhd_net_if_lock_local(dhd);
+ memcpy(dhdif->mac_addr, sa->sa_data, ETHER_ADDR_LEN);
+ dhdif->set_macaddress = TRUE;
+ dhd_net_if_unlock_local(dhd);
+ dhd_deferred_schedule_work((void *)dhdif, DHD_WQ_WORK_SET_MAC,
+ dhd_set_mac_addr_handler, DHD_WORK_PRIORITY_LOW);
+ return ret;
+}
+
+static void
+dhd_set_multicast_list(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ifidx;
+
+ ifidx = dhd_net2idx(dhd, dev);
+ if (ifidx == DHD_BAD_IF)
+ return;
+
+ dhd->iflist[ifidx]->set_multicast = TRUE;
+ dhd_deferred_schedule_work((void *)((long int)ifidx), DHD_WQ_WORK_SET_MCAST_LIST,
+ dhd_set_mcast_list_handler, DHD_WORK_PRIORITY_LOW);
+}
+
+#ifdef PROP_TXSTATUS
+int
+dhd_os_wlfc_block(dhd_pub_t *pub)
+{
+ dhd_info_t *di = (dhd_info_t *)(pub->info);
+ ASSERT(di != NULL);
+ spin_lock_bh(&di->wlfc_spinlock);
+ return 1;
+}
+
+int
+dhd_os_wlfc_unblock(dhd_pub_t *pub)
+{
+ dhd_info_t *di = (dhd_info_t *)(pub->info);
+
+ ASSERT(di != NULL);
+ spin_unlock_bh(&di->wlfc_spinlock);
+ return 1;
+}
+
+const uint8 wme_fifo2ac[] = { 0, 1, 2, 3, 1, 1 };
+const uint8 prio2fifo[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
+#define WME_PRIO2AC(prio) wme_fifo2ac[prio2fifo[(prio)]]
+
+#endif /* PROP_TXSTATUS */
+int BCMFASTPATH
+dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
+{
+ int ret = BCME_OK;
+ dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
+ struct ether_header *eh = NULL;
+
+ /* Reject if down */
+ if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) {
+ /* free the packet here since the caller won't */
+ PKTFREE(dhdp->osh, pktbuf, TRUE);
+ return -ENODEV;
+ }
+
+ /* Update multicast statistic */
+ if (PKTLEN(dhdp->osh, pktbuf) >= ETHER_HDR_LEN) {
+ uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf);
+ eh = (struct ether_header *)pktdata;
+
+ if (ETHER_ISMULTI(eh->ether_dhost))
+ dhdp->tx_multicast++;
+ if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X)
+ atomic_inc(&dhd->pend_8021x_cnt);
+ } else {
+ PKTFREE(dhd->pub.osh, pktbuf, TRUE);
+ return BCME_ERROR;
+ }
+
+#ifdef DHDTCPACK_SUPPRESS
+ /* If this packet has replaced another packet and got freed, just return */
+ if (dhd_tcpack_suppress(dhdp, pktbuf))
+ return ret;
+#endif /* DHDTCPACK_SUPPRESS */
+
+ /* Look into the packet and update the packet priority */
+#ifndef PKTPRIO_OVERRIDE
+ if (PKTPRIO(pktbuf) == 0)
+#endif
+ pktsetprio(pktbuf, FALSE);
+
+#ifdef PROP_TXSTATUS
+ if (dhd_wlfc_is_supported(dhdp)) {
+ /* store the interface ID */
+ DHD_PKTTAG_SETIF(PKTTAG(pktbuf), ifidx);
+
+ /* store destination MAC in the tag as well */
+ DHD_PKTTAG_SETDSTN(PKTTAG(pktbuf), eh->ether_dhost);
+
+ /* decide which FIFO this packet belongs to */
+ if (ETHER_ISMULTI(eh->ether_dhost))
+ /* one additional queue index (highest AC + 1) is used for bc/mc queue */
+ DHD_PKTTAG_SETFIFO(PKTTAG(pktbuf), AC_COUNT);
+ else
+ DHD_PKTTAG_SETFIFO(PKTTAG(pktbuf), WME_PRIO2AC(PKTPRIO(pktbuf)));
+ } else
+#endif /* PROP_TXSTATUS */
+ /* If the protocol uses a data header, apply it */
+ dhd_prot_hdrpush(dhdp, ifidx, pktbuf);
+
+ /* Use bus module to send data frame */
+#ifdef WLMEDIA_HTSF
+ dhd_htsf_addtxts(dhdp, pktbuf);
+#endif
+#ifdef PROP_TXSTATUS
+ {
+ if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_bus_txdata,
+ dhdp->bus, pktbuf, TRUE) == WLFC_UNSUPPORTED) {
+ /* non-proptxstatus way */
+ ret = dhd_bus_txdata(dhdp->bus, pktbuf);
+ }
+ }
+#else
+#ifdef BCMPCIE
+ ret = dhd_bus_txdata(dhdp->bus, pktbuf, (uint8)ifidx);
+#else
+ ret = dhd_bus_txdata(dhdp->bus, pktbuf);
+#endif /* BCMPCIE */
+#endif /* PROP_TXSTATUS */
+
+ return ret;
+}
+
+int BCMFASTPATH
+dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
+{
+ int ret;
+ uint datalen;
+ void *pktbuf;
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
+ dhd_if_t *ifp = NULL;
+ int ifidx;
+#ifdef WLMEDIA_HTSF
+ uint8 htsfdlystat_sz = dhd->pub.htsfdlystat_sz;
+#else
+ uint8 htsfdlystat_sz = 0;
+#endif
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+
+ /* Reject if down */
+ if (dhd->pub.busstate == DHD_BUS_DOWN || dhd->pub.hang_was_sent) {
+ DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d \n",
+ __FUNCTION__, dhd->pub.up, dhd->pub.busstate));
+ netif_stop_queue(net);
+ /* Send Event when bus down detected during data session */
+ if (dhd->pub.up) {
+ DHD_ERROR(("%s: Event HANG sent up\n", __FUNCTION__));
+ net_os_send_hang_message(net);
+ }
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
+ return -ENODEV;
+#else
+ return NETDEV_TX_BUSY;
+#endif
+ }
+
+ ifidx = dhd_net2idx(dhd, net);
+ if (ifidx == DHD_BAD_IF) {
+ DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx));
+ netif_stop_queue(net);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
+ return -ENODEV;
+#else
+ return NETDEV_TX_BUSY;
+#endif
+ }
+
+ /* re-align socket buffer if "skb->data" is odd adress */
+ if (((unsigned long)(skb->data)) & 0x1) {
+ unsigned char *data = skb->data;
+ uint32 length = skb->len;
+ PKTPUSH(dhd->pub.osh, skb, 1);
+ memmove(skb->data, data, length);
+ PKTSETLEN(dhd->pub.osh, skb, length);
+ }
+
+ ifp = dhd->iflist[ifidx];
+ datalen = PKTLEN(dhd->pub.osh, skb);
+
+ /* Make sure there's enough room for any header */
+
+ if (skb_headroom(skb) < dhd->pub.hdrlen + htsfdlystat_sz) {
+ struct sk_buff *skb2;
+
+ DHD_INFO(("%s: insufficient headroom\n",
+ dhd_ifname(&dhd->pub, ifidx)));
+ dhd->pub.tx_realloc++;
+
+ skb2 = skb_realloc_headroom(skb, dhd->pub.hdrlen + htsfdlystat_sz);
+
+ dev_kfree_skb(skb);
+ if ((skb = skb2) == NULL) {
+ DHD_ERROR(("%s: skb_realloc_headroom failed\n",
+ dhd_ifname(&dhd->pub, ifidx)));
+ ret = -ENOMEM;
+ goto done;
+ }
+ }
+
+ /* Convert to packet */
+ if (!(pktbuf = PKTFRMNATIVE(dhd->pub.osh, skb))) {
+ DHD_ERROR(("%s: PKTFRMNATIVE failed\n",
+ dhd_ifname(&dhd->pub, ifidx)));
+ dev_kfree_skb_any(skb);
+ ret = -ENOMEM;
+ goto done;
+ }
+#ifdef WLMEDIA_HTSF
+ if (htsfdlystat_sz && PKTLEN(dhd->pub.osh, pktbuf) >= ETHER_ADDR_LEN) {
+ uint8 *pktdata = (uint8 *)PKTDATA(dhd->pub.osh, pktbuf);
+ struct ether_header *eh = (struct ether_header *)pktdata;
+
+ if (!ETHER_ISMULTI(eh->ether_dhost) &&
+ (ntoh16(eh->ether_type) == ETHER_TYPE_IP)) {
+ eh->ether_type = hton16(ETHER_TYPE_BRCM_PKTDLYSTATS);
+ }
+ }
+#endif
+
+ ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf);
+
+done:
+ if (ret) {
+ ifp->stats.tx_dropped++;
+ }
+ else {
+
+#ifdef PROP_TXSTATUS
+ /* tx_packets counter can counted only when wlfc is disabled */
+ if (!dhd_wlfc_is_supported(&dhd->pub))
+#endif
+ {
+ dhd->pub.tx_packets++;
+ ifp->stats.tx_packets++;
+ ifp->stats.tx_bytes += datalen;
+ }
+ }
+
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+
+ /* Return ok: we always eat the packet */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
+ return 0;
+#else
+ return NETDEV_TX_OK;
+#endif
+}
+
+void
+dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state)
+{
+ struct net_device *net;
+ dhd_info_t *dhd = dhdp->info;
+ int i;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ASSERT(dhd);
+
+ if (ifidx == ALL_INTERFACES) {
+ /* Flow control on all active interfaces */
+ dhdp->txoff = state;
+ for (i = 0; i < DHD_MAX_IFS; i++) {
+ if (dhd->iflist[i]) {
+ net = dhd->iflist[i]->net;
+ if (state == ON)
+ netif_stop_queue(net);
+ else
+ netif_wake_queue(net);
+ }
+ }
+ }
+ else {
+ if (dhd->iflist[ifidx]) {
+ net = dhd->iflist[ifidx]->net;
+ if (state == ON)
+ netif_stop_queue(net);
+ else
+ netif_wake_queue(net);
+ }
+ }
+}
+
+#ifdef DHD_RX_DUMP
+typedef struct {
+ uint16 type;
+ const char *str;
+} PKTTYPE_INFO;
+
+static const PKTTYPE_INFO packet_type_info[] =
+{
+ { ETHER_TYPE_IP, "IP" },
+ { ETHER_TYPE_ARP, "ARP" },
+ { ETHER_TYPE_BRCM, "BRCM" },
+ { ETHER_TYPE_802_1X, "802.1X" },
+ { ETHER_TYPE_WAI, "WAPI" },
+ { 0, ""}
+};
+
+static const char *_get_packet_type_str(uint16 type)
+{
+ int i;
+ int n = sizeof(packet_type_info)/sizeof(packet_type_info[1]) - 1;
+
+ for (i = 0; i < n; i++) {
+ if (packet_type_info[i].type == type)
+ return packet_type_info[i].str;
+ }
+
+ return packet_type_info[n].str;
+}
+#endif /* DHD_RX_DUMP */
+
+
+void
+dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
+{
+ dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+ struct sk_buff *skb;
+ uchar *eth;
+ uint len;
+ void *data, *pnext = NULL;
+ int i;
+ dhd_if_t *ifp;
+ wl_event_msg_t event;
+ int tout_rx = 0;
+ int tout_ctrl = 0;
+ void *skbhead = NULL;
+ void *skbprev = NULL;
+#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP)
+ char *dump_data;
+ uint16 protocol;
+#endif /* DHD_RX_DUMP || DHD_8021X_DUMP */
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) {
+ struct ether_header *eh;
+
+ pnext = PKTNEXT(dhdp->osh, pktbuf);
+ PKTSETNEXT(dhdp->osh, pktbuf, NULL);
+
+ ifp = dhd->iflist[ifidx];
+ if (ifp == NULL) {
+ DHD_ERROR(("%s: ifp is NULL. drop packet\n",
+ __FUNCTION__));
+ PKTFREE(dhdp->osh, pktbuf, FALSE);
+ continue;
+ }
+ eh = (struct ether_header *)PKTDATA(dhdp->osh, pktbuf);
+ /* Dropping only data packets before registering net device to avoid kernel panic */
+#ifndef PROP_TXSTATUS_VSDB
+ if ((!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) &&
+ (ntoh16(eh->ether_type) != ETHER_TYPE_BRCM)) {
+#else
+ if ((!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || !dhd->pub.up) &&
+ (ntoh16(eh->ether_type) != ETHER_TYPE_BRCM)) {
+#endif /* PROP_TXSTATUS_VSDB */
+ DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n",
+ __FUNCTION__));
+ PKTFREE(dhdp->osh, pktbuf, FALSE);
+ continue;
+ }
+
+
+#ifdef PROP_TXSTATUS
+ if (dhd_wlfc_is_header_only_pkt(dhdp, pktbuf)) {
+ /* WLFC may send header only packet when
+ there is an urgent message but no packet to
+ piggy-back on
+ */
+ PKTFREE(dhdp->osh, pktbuf, FALSE);
+ continue;
+ }
+#endif
+#ifdef DHDTCPACK_SUPPRESS
+ dhd_tcpdata_info_get(dhdp, pktbuf);
+#endif
+ skb = PKTTONATIVE(dhdp->osh, pktbuf);
+
+ ifp = dhd->iflist[ifidx];
+ if (ifp == NULL)
+ ifp = dhd->iflist[0];
+
+ ASSERT(ifp);
+ skb->dev = ifp->net;
+
+
+ /* Get the protocol, maintain skb around eth_type_trans()
+ * The main reason for this hack is for the limitation of
+ * Linux 2.4 where 'eth_type_trans' uses the 'net->hard_header_len'
+ * to perform skb_pull inside vs ETH_HLEN. Since to avoid
+ * coping of the packet coming from the network stack to add
+ * BDC, Hardware header etc, during network interface registration
+ * we set the 'net->hard_header_len' to ETH_HLEN + extra space required
+ * for BDC, Hardware header etc. and not just the ETH_HLEN
+ */
+ eth = skb->data;
+ len = skb->len;
+
+#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP)
+ dump_data = skb->data;
+ protocol = (dump_data[12] << 8) | dump_data[13];
+
+ if (protocol == ETHER_TYPE_802_1X) {
+ DHD_ERROR(("ETHER_TYPE_802_1X: "
+ "ver %d, type %d, replay %d\n",
+ dump_data[14], dump_data[15],
+ dump_data[30]));
+ }
+#endif /* DHD_RX_DUMP || DHD_8021X_DUMP */
+#if defined(DHD_RX_DUMP)
+ DHD_ERROR(("RX DUMP - %s\n", _get_packet_type_str(protocol)));
+ if (protocol != ETHER_TYPE_BRCM) {
+ if (dump_data[0] == 0xFF) {
+ DHD_ERROR(("%s: BROADCAST\n", __FUNCTION__));
+
+ if ((dump_data[12] == 8) &&
+ (dump_data[13] == 6)) {
+ DHD_ERROR(("%s: ARP %d\n",
+ __FUNCTION__, dump_data[0x15]));
+ }
+ } else if (dump_data[0] & 1) {
+ DHD_ERROR(("%s: MULTICAST: " MACDBG "\n",
+ __FUNCTION__, MAC2STRDBG(dump_data)));
+ }
+#ifdef DHD_RX_FULL_DUMP
+ {
+ int k;
+ for (k = 0; k < skb->len; k++) {
+ DHD_ERROR(("%02X ", dump_data[k]));
+ if ((k & 15) == 15)
+ DHD_ERROR(("\n"));
+ }
+ DHD_ERROR(("\n"));
+ }
+#endif /* DHD_RX_FULL_DUMP */
+ }
+#endif /* DHD_RX_DUMP */
+
+ skb->protocol = eth_type_trans(skb, skb->dev);
+
+ if (skb->pkt_type == PACKET_MULTICAST) {
+ dhd->pub.rx_multicast++;
+ ifp->stats.multicast++;
+ }
+
+ skb->data = eth;
+ skb->len = len;
+
+#ifdef WLMEDIA_HTSF
+ dhd_htsf_addrxts(dhdp, pktbuf);
+#endif
+ /* Strip header, count, deliver upward */
+ skb_pull(skb, ETH_HLEN);
+
+ /* Process special event packets and then discard them */
+ memset(&event, 0, sizeof(event));
+ if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) {
+ dhd_wl_host_event(dhd, &ifidx,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+ skb_mac_header(skb),
+#else
+ skb->mac.raw,
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) */
+ len > ETHER_TYPE_LEN ? len - ETHER_TYPE_LEN : 0,
+ &event,
+ &data);
+
+ wl_event_to_host_order(&event);
+ if (!tout_ctrl)
+ tout_ctrl = DHD_PACKET_TIMEOUT_MS;
+
+#if defined(PNO_SUPPORT)
+ if (event.event_type == WLC_E_PFN_NET_FOUND) {
+ /* enforce custom wake lock to garantee that Kernel not suspended */
+ tout_ctrl = CUSTOM_PNO_EVENT_LOCK_xTIME * DHD_PACKET_TIMEOUT_MS;
+ }
+#endif /* PNO_SUPPORT */
+
+#ifdef DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT
+ PKTFREE(dhdp->osh, pktbuf, FALSE);
+ continue;
+#endif /* DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT */
+ } else {
+ tout_rx = DHD_PACKET_TIMEOUT_MS;
+
+#ifdef PROP_TXSTATUS
+ dhd_wlfc_save_rxpath_ac_time(dhdp, (uint8)PKTPRIO(skb));
+#endif /* PROP_TXSTATUS */
+ }
+
+ ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
+ ifp = dhd->iflist[ifidx];
+
+ if (ifp->net)
+ ifp->net->last_rx = jiffies;
+
+ if (ntoh16(skb->protocol) != ETHER_TYPE_BRCM) {
+ dhdp->dstats.rx_bytes += skb->len;
+ dhdp->rx_packets++; /* Local count */
+ ifp->stats.rx_bytes += skb->len;
+ ifp->stats.rx_packets++;
+ }
+
+ if (in_interrupt()) {
+ netif_rx(skb);
+ } else {
+ if (dhd->rxthread_enabled) {
+ if (!skbhead)
+ skbhead = skb;
+ else
+ PKTSETNEXT(dhdp->osh, skbprev, skb);
+ skbprev = skb;
+ } else {
+
+ /* If the receive is not processed inside an ISR,
+ * the softirqd must be woken explicitly to service
+ * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled
+ * by netif_rx_ni(), but in earlier kernels, we need
+ * to do it manually.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+ netif_rx_ni(skb);
+#else
+ ulong flags;
+ netif_rx(skb);
+ local_irq_save(flags);
+ RAISE_RX_SOFTIRQ();
+ local_irq_restore(flags);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
+ }
+ }
+ }
+
+ if (dhd->rxthread_enabled && skbhead)
+ dhd_sched_rxf(dhdp, skbhead);
+
+ DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx);
+ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl);
+}
+
+void
+dhd_event(struct dhd_info *dhd, char *evpkt, uint evlen, int ifidx)
+{
+ /* Linux version has nothing to do */
+ return;
+}
+
+void
+dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
+ struct ether_header *eh;
+ uint16 type;
+
+ dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL);
+
+ eh = (struct ether_header *)PKTDATA(dhdp->osh, txp);
+ type = ntoh16(eh->ether_type);
+
+ if (type == ETHER_TYPE_802_1X)
+ atomic_dec(&dhd->pend_8021x_cnt);
+
+#ifdef PROP_TXSTATUS
+ if (dhdp->wlfc_state && (dhdp->proptxstatus_mode != WLFC_FCMODE_NONE)) {
+ dhd_if_t *ifp = dhd->iflist[DHD_PKTTAG_IF(PKTTAG(txp))];
+ uint datalen = PKTLEN(dhd->pub.osh, txp);
+
+ if (success) {
+ dhd->pub.tx_packets++;
+ ifp->stats.tx_packets++;
+ ifp->stats.tx_bytes += datalen;
+ } else {
+ ifp->stats.tx_dropped++;
+ }
+ }
+#endif
+}
+
+static struct net_device_stats *
+dhd_get_stats(struct net_device *net)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
+ dhd_if_t *ifp;
+ int ifidx;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ifidx = dhd_net2idx(dhd, net);
+ if (ifidx == DHD_BAD_IF) {
+ DHD_ERROR(("%s: BAD_IF\n", __FUNCTION__));
+
+ memset(&net->stats, 0, sizeof(net->stats));
+ return &net->stats;
+ }
+
+ ifp = dhd->iflist[ifidx];
+ ASSERT(dhd && ifp);
+
+ if (dhd->pub.up) {
+ /* Use the protocol to get dongle stats */
+ dhd_prot_dstats(&dhd->pub);
+ }
+ return &ifp->stats;
+}
+
+static int
+dhd_watchdog_thread(void *data)
+{
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;
+ dhd_info_t *dhd = (dhd_info_t *)tsk->parent;
+ /* This thread doesn't need any user-level access,
+ * so get rid of all our resources
+ */
+ if (dhd_watchdog_prio > 0) {
+ struct sched_param param;
+ param.sched_priority = (dhd_watchdog_prio < MAX_RT_PRIO)?
+ dhd_watchdog_prio:(MAX_RT_PRIO-1);
+ setScheduler(current, SCHED_FIFO, &param);
+ }
+
+ while (1)
+ if (down_interruptible (&tsk->sema) == 0) {
+ unsigned long flags;
+ unsigned long jiffies_at_start = jiffies;
+ unsigned long time_lapse;
+
+ SMP_RD_BARRIER_DEPENDS();
+ if (tsk->terminated) {
+ break;
+ }
+
+ dhd_os_sdlock(&dhd->pub);
+ if (dhd->pub.dongle_reset == FALSE) {
+ DHD_TIMER(("%s:\n", __FUNCTION__));
+
+ /* Call the bus module watchdog */
+ dhd_bus_watchdog(&dhd->pub);
+
+ flags = dhd_os_spin_lock(&dhd->pub);
+ /* Count the tick for reference */
+ dhd->pub.tickcnt++;
+ time_lapse = jiffies - jiffies_at_start;
+
+ /* Reschedule the watchdog */
+ if (dhd->wd_timer_valid)
+ mod_timer(&dhd->timer,
+ jiffies +
+ msecs_to_jiffies(dhd_watchdog_ms) -
+ min(msecs_to_jiffies(dhd_watchdog_ms), time_lapse));
+ dhd_os_spin_unlock(&dhd->pub, flags);
+ }
+ dhd_os_sdunlock(&dhd->pub);
+ } else {
+ break;
+ }
+
+ complete_and_exit(&tsk->completed, 0);
+}
+
+static void dhd_watchdog(ulong data)
+{
+ dhd_info_t *dhd = (dhd_info_t *)data;
+ unsigned long flags;
+
+ if (dhd->pub.dongle_reset) {
+ return;
+ }
+
+ if (dhd->thr_wdt_ctl.thr_pid >= 0) {
+ up(&dhd->thr_wdt_ctl.sema);
+ return;
+ }
+
+ dhd_os_sdlock(&dhd->pub);
+ /* Call the bus module watchdog */
+ dhd_bus_watchdog(&dhd->pub);
+
+ flags = dhd_os_spin_lock(&dhd->pub);
+ /* Count the tick for reference */
+ dhd->pub.tickcnt++;
+
+ /* Reschedule the watchdog */
+ if (dhd->wd_timer_valid)
+ mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms));
+ dhd_os_spin_unlock(&dhd->pub, flags);
+ dhd_os_sdunlock(&dhd->pub);
+}
+
+#ifdef ENABLE_ADAPTIVE_SCHED
+/* DPC thread policy */
+static int dhd_dpc_poli = SCHED_FIFO;
+static void
+dhd_sched_policy(int prio)
+{
+ struct sched_param param;
+ if (cpufreq_quick_get(0) <= CUSTOM_CPUFREQ_THRESH) {
+ param.sched_priority = 0;
+ setScheduler(current, SCHED_NORMAL, &param);
+ } else {
+ if (get_scheduler_policy(current) != SCHED_FIFO) {
+ param.sched_priority = (prio < MAX_RT_PRIO)? prio : (MAX_RT_PRIO-1);
+ setScheduler(current, dhd_dpc_poli, &param);
+ }
+ }
+}
+#endif /* ENABLE_ADAPTIVE_SCHED */
+#ifdef DEBUG_CPU_FREQ
+static int dhd_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
+{
+ dhd_info_t *dhd = container_of(nb, struct dhd_info, freq_trans);
+ struct cpufreq_freqs *freq = data;
+ if (dhd) {
+ if (!dhd->new_freq)
+ goto exit;
+ if (val == CPUFREQ_POSTCHANGE) {
+ DHD_ERROR(("cpu freq is changed to %u kHZ on CPU %d\n",
+ freq->new, freq->cpu));
+ *per_cpu_ptr(dhd->new_freq, freq->cpu) = freq->new;
+ }
+ }
+exit:
+ return 0;
+}
+#endif /* DEBUG_CPU_FREQ */
+static int
+dhd_dpc_thread(void *data)
+{
+
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;
+ dhd_info_t *dhd = (dhd_info_t *)tsk->parent;
+
+ /* This thread doesn't need any user-level access,
+ * so get rid of all our resources
+ */
+ if (dhd_dpc_prio > 0)
+ {
+ struct sched_param param;
+ param.sched_priority = (dhd_dpc_prio < MAX_RT_PRIO)?dhd_dpc_prio:(MAX_RT_PRIO-1);
+ setScheduler(current, SCHED_FIFO, &param);
+ }
+
+#ifdef CUSTOM_DPC_CPUCORE
+ set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_DPC_CPUCORE));
+#endif
+#ifdef CUSTOM_SET_CPUCORE
+ dhd->pub.current_dpc = current;
+#endif /* CUSTOM_SET_CPUCORE */
+ /* Run until signal received */
+ while (1) {
+ if (!binary_sema_down(tsk)) {
+#ifdef ENABLE_ADAPTIVE_SCHED
+ dhd_sched_policy(dhd_dpc_prio);
+#endif /* ENABLE_ADAPTIVE_SCHED */
+ SMP_RD_BARRIER_DEPENDS();
+ if (tsk->terminated) {
+ break;
+ }
+
+ /* Call bus dpc unless it indicated down (then clean stop) */
+ if (dhd->pub.busstate != DHD_BUS_DOWN) {
+ dhd_os_wd_timer_extend(&dhd->pub, TRUE);
+ while (dhd_bus_dpc(dhd->pub.bus)) {
+ /* process all data */
+ }
+ dhd_os_wd_timer_extend(&dhd->pub, FALSE);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+
+ } else {
+ if (dhd->pub.up)
+ dhd_bus_stop(dhd->pub.bus, TRUE);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ }
+ }
+ else
+ break;
+ }
+ complete_and_exit(&tsk->completed, 0);
+}
+
+static int
+dhd_rxf_thread(void *data)
+{
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;
+ dhd_info_t *dhd = (dhd_info_t *)tsk->parent;
+ dhd_pub_t *pub = &dhd->pub;
+#if defined(WAIT_DEQUEUE)
+#define RXF_WATCHDOG_TIME 250 /* BARK_TIME(1000) / */
+ ulong watchdogTime = OSL_SYSUPTIME(); /* msec */
+#endif
+
+ /* This thread doesn't need any user-level access,
+ * so get rid of all our resources
+ */
+ if (dhd_rxf_prio > 0)
+ {
+ struct sched_param param;
+ param.sched_priority = (dhd_rxf_prio < MAX_RT_PRIO)?dhd_rxf_prio:(MAX_RT_PRIO-1);
+ setScheduler(current, SCHED_FIFO, &param);
+ }
+
+
+#ifdef CUSTOM_SET_CPUCORE
+ dhd->pub.current_rxf = current;
+#endif /* CUSTOM_SET_CPUCORE */
+ /* Run until signal received */
+ while (1) {
+ if (down_interruptible(&tsk->sema) == 0) {
+ void *skb;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+ ulong flags;
+#endif
+#ifdef ENABLE_ADAPTIVE_SCHED
+ dhd_sched_policy(dhd_rxf_prio);
+#endif /* ENABLE_ADAPTIVE_SCHED */
+
+ SMP_RD_BARRIER_DEPENDS();
+
+ if (tsk->terminated) {
+ break;
+ }
+ skb = dhd_rxf_dequeue(pub);
+
+ if (skb == NULL) {
+ continue;
+ }
+ while (skb) {
+ void *skbnext = PKTNEXT(pub->osh, skb);
+ PKTSETNEXT(pub->osh, skb, NULL);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+ netif_rx_ni(skb);
+#else
+ netif_rx(skb);
+ local_irq_save(flags);
+ RAISE_RX_SOFTIRQ();
+ local_irq_restore(flags);
+
+#endif
+ skb = skbnext;
+ }
+#if defined(WAIT_DEQUEUE)
+ if (OSL_SYSUPTIME() - watchdogTime > RXF_WATCHDOG_TIME) {
+ OSL_SLEEP(1);
+ watchdogTime = OSL_SYSUPTIME();
+ }
+#endif
+
+ DHD_OS_WAKE_UNLOCK(pub);
+ }
+ else
+ break;
+ }
+
+ complete_and_exit(&tsk->completed, 0);
+}
+
+static void
+dhd_dpc(ulong data)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)data;
+
+ /* this (tasklet) can be scheduled in dhd_sched_dpc[dhd_linux.c]
+ * down below , wake lock is set,
+ * the tasklet is initialized in dhd_attach()
+ */
+ /* Call bus dpc unless it indicated down (then clean stop) */
+ if (dhd->pub.busstate != DHD_BUS_DOWN) {
+ if (dhd_bus_dpc(dhd->pub.bus))
+ tasklet_schedule(&dhd->tasklet);
+ else
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ } else {
+ dhd_bus_stop(dhd->pub.bus, TRUE);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ }
+}
+
+void
+dhd_sched_dpc(dhd_pub_t *dhdp)
+{
+ dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+
+ DHD_OS_WAKE_LOCK(dhdp);
+ if (dhd->thr_dpc_ctl.thr_pid >= 0) {
+ /* If the semaphore does not get up,
+ * wake unlock should be done here
+ */
+ if (!binary_sema_up(&dhd->thr_dpc_ctl))
+ DHD_OS_WAKE_UNLOCK(dhdp);
+ return;
+ } else {
+ tasklet_schedule(&dhd->tasklet);
+ }
+}
+
+static void
+dhd_sched_rxf(dhd_pub_t *dhdp, void *skb)
+{
+ dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+#ifdef RXF_DEQUEUE_ON_BUSY
+ int ret = BCME_OK;
+ int retry = 2;
+#endif /* RXF_DEQUEUE_ON_BUSY */
+
+ DHD_OS_WAKE_LOCK(dhdp);
+
+ DHD_TRACE(("dhd_sched_rxf: Enter\n"));
+#ifdef RXF_DEQUEUE_ON_BUSY
+ do {
+ ret = dhd_rxf_enqueue(dhdp, skb);
+ if (ret == BCME_OK || ret == BCME_ERROR)
+ break;
+ else
+ OSL_SLEEP(50); /* waiting for dequeueing */
+ } while (retry-- > 0);
+
+ if (retry <= 0 && ret == BCME_BUSY) {
+ void *skbp = skb;
+
+ while (skbp) {
+ void *skbnext = PKTNEXT(dhdp->osh, skbp);
+ PKTSETNEXT(dhdp->osh, skbp, NULL);
+ netif_rx_ni(skbp);
+ skbp = skbnext;
+ }
+ DHD_ERROR(("send skb to kernel backlog without rxf_thread\n"));
+ }
+ else {
+ if (dhd->thr_rxf_ctl.thr_pid >= 0) {
+ up(&dhd->thr_rxf_ctl.sema);
+ }
+ }
+#else /* RXF_DEQUEUE_ON_BUSY */
+ do {
+ if (dhd_rxf_enqueue(dhdp, skb) == BCME_OK)
+ break;
+ } while (1);
+ if (dhd->thr_rxf_ctl.thr_pid >= 0) {
+ up(&dhd->thr_rxf_ctl.sema);
+ }
+ return;
+#endif /* RXF_DEQUEUE_ON_BUSY */
+}
+
+#ifdef TOE
+/* Retrieve current toe component enables, which are kept as a bitmap in toe_ol iovar */
+static int
+dhd_toe_get(dhd_info_t *dhd, int ifidx, uint32 *toe_ol)
+{
+ wl_ioctl_t ioc;
+ char buf[32];
+ int ret;
+
+ memset(&ioc, 0, sizeof(ioc));
+
+ ioc.cmd = WLC_GET_VAR;
+ ioc.buf = buf;
+ ioc.len = (uint)sizeof(buf);
+ ioc.set = FALSE;
+
+ strncpy(buf, "toe_ol", sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) {
+ /* Check for older dongle image that doesn't support toe_ol */
+ if (ret == -EIO) {
+ DHD_ERROR(("%s: toe not supported by device\n",
+ dhd_ifname(&dhd->pub, ifidx)));
+ return -EOPNOTSUPP;
+ }
+
+ DHD_INFO(("%s: could not get toe_ol: ret=%d\n", dhd_ifname(&dhd->pub, ifidx), ret));
+ return ret;
+ }
+
+ memcpy(toe_ol, buf, sizeof(uint32));
+ return 0;
+}
+
+/* Set current toe component enables in toe_ol iovar, and set toe global enable iovar */
+static int
+dhd_toe_set(dhd_info_t *dhd, int ifidx, uint32 toe_ol)
+{
+ wl_ioctl_t ioc;
+ char buf[32];
+ int toe, ret;
+
+ memset(&ioc, 0, sizeof(ioc));
+
+ ioc.cmd = WLC_SET_VAR;
+ ioc.buf = buf;
+ ioc.len = (uint)sizeof(buf);
+ ioc.set = TRUE;
+
+ /* Set toe_ol as requested */
+
+ strncpy(buf, "toe_ol", sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(uint32));
+
+ if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) {
+ DHD_ERROR(("%s: could not set toe_ol: ret=%d\n",
+ dhd_ifname(&dhd->pub, ifidx), ret));
+ return ret;
+ }
+
+ /* Enable toe globally only if any components are enabled. */
+
+ toe = (toe_ol != 0);
+
+ strcpy(buf, "toe");
+ memcpy(&buf[sizeof("toe")], &toe, sizeof(uint32));
+
+ if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) {
+ DHD_ERROR(("%s: could not set toe: ret=%d\n", dhd_ifname(&dhd->pub, ifidx), ret));
+ return ret;
+ }
+
+ return 0;
+}
+#endif /* TOE */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+static void
+dhd_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
+
+ snprintf(info->driver, sizeof(info->driver), "wl");
+ snprintf(info->version, sizeof(info->version), "%lu", dhd->pub.drv_version);
+}
+
+struct ethtool_ops dhd_ethtool_ops = {
+ .get_drvinfo = dhd_ethtool_get_drvinfo
+};
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
+
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
+static int
+dhd_ethtool(dhd_info_t *dhd, void *uaddr)
+{
+ struct ethtool_drvinfo info;
+ char drvname[sizeof(info.driver)];
+ uint32 cmd;
+#ifdef TOE
+ struct ethtool_value edata;
+ uint32 toe_cmpnt, csum_dir;
+ int ret;
+#endif
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* all ethtool calls start with a cmd word */
+ if (copy_from_user(&cmd, uaddr, sizeof (uint32)))
+ return -EFAULT;
+
+ switch (cmd) {
+ case ETHTOOL_GDRVINFO:
+ /* Copy out any request driver name */
+ if (copy_from_user(&info, uaddr, sizeof(info)))
+ return -EFAULT;
+ strncpy(drvname, info.driver, sizeof(info.driver));
+ drvname[sizeof(info.driver)-1] = '\0';
+
+ /* clear struct for return */
+ memset(&info, 0, sizeof(info));
+ info.cmd = cmd;
+
+ /* if dhd requested, identify ourselves */
+ if (strcmp(drvname, "?dhd") == 0) {
+ snprintf(info.driver, sizeof(info.driver), "dhd");
+ strncpy(info.version, EPI_VERSION_STR, sizeof(info.version) - 1);
+ info.version[sizeof(info.version) - 1] = '\0';
+ }
+
+ /* otherwise, require dongle to be up */
+ else if (!dhd->pub.up) {
+ DHD_ERROR(("%s: dongle is not up\n", __FUNCTION__));
+ return -ENODEV;
+ }
+
+ /* finally, report dongle driver type */
+ else if (dhd->pub.iswl)
+ snprintf(info.driver, sizeof(info.driver), "wl");
+ else
+ snprintf(info.driver, sizeof(info.driver), "xx");
+
+ snprintf(info.version, sizeof(info.version), "%lu", dhd->pub.drv_version);
+ if (copy_to_user(uaddr, &info, sizeof(info)))
+ return -EFAULT;
+ DHD_CTL(("%s: given %*s, returning %s\n", __FUNCTION__,
+ (int)sizeof(drvname), drvname, info.driver));
+ break;
+
+#ifdef TOE
+ /* Get toe offload components from dongle */
+ case ETHTOOL_GRXCSUM:
+ case ETHTOOL_GTXCSUM:
+ if ((ret = dhd_toe_get(dhd, 0, &toe_cmpnt)) < 0)
+ return ret;
+
+ csum_dir = (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+
+ edata.cmd = cmd;
+ edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
+
+ if (copy_to_user(uaddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ break;
+
+ /* Set toe offload components in dongle */
+ case ETHTOOL_SRXCSUM:
+ case ETHTOOL_STXCSUM:
+ if (copy_from_user(&edata, uaddr, sizeof(edata)))
+ return -EFAULT;
+
+ /* Read the current settings, update and write back */
+ if ((ret = dhd_toe_get(dhd, 0, &toe_cmpnt)) < 0)
+ return ret;
+
+ csum_dir = (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+
+ if (edata.data != 0)
+ toe_cmpnt |= csum_dir;
+ else
+ toe_cmpnt &= ~csum_dir;
+
+ if ((ret = dhd_toe_set(dhd, 0, toe_cmpnt)) < 0)
+ return ret;
+
+ /* If setting TX checksum mode, tell Linux the new mode */
+ if (cmd == ETHTOOL_STXCSUM) {
+ if (edata.data)
+ dhd->iflist[0]->net->features |= NETIF_F_IP_CSUM;
+ else
+ dhd->iflist[0]->net->features &= ~NETIF_F_IP_CSUM;
+ }
+
+ break;
+#endif /* TOE */
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
+
+static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
+{
+ dhd_info_t *dhd;
+
+ if (!dhdp) {
+ DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ if (!dhdp->up)
+ return FALSE;
+
+ dhd = (dhd_info_t *)dhdp->info;
+#if !defined(BCMPCIE)
+ if (dhd->thr_dpc_ctl.thr_pid < 0) {
+ DHD_ERROR(("%s : skipped due to negative pid - unloading?\n", __FUNCTION__));
+ return FALSE;
+ }
+#endif
+
+ if ((error == -ETIMEDOUT) || (error == -EREMOTEIO) ||
+ ((dhdp->busstate == DHD_BUS_DOWN) && (!dhdp->dongle_reset))) {
+ DHD_ERROR(("%s: Event HANG send up due to re=%d te=%d e=%d s=%d\n", __FUNCTION__,
+ dhdp->rxcnt_timeout, dhdp->txcnt_timeout, error, dhdp->busstate));
+ net_os_send_hang_message(net);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc, void *data_buf)
+{
+ int bcmerror = BCME_OK;
+ int buflen = 0;
+ struct net_device *net;
+
+ net = dhd_idx2net(pub, ifidx);
+ if (!net) {
+ bcmerror = BCME_BADARG;
+ goto done;
+ }
+
+ if (data_buf)
+ buflen = MIN(ioc->len, DHD_IOCTL_MAXLEN);
+
+ /* check for local dhd ioctl and handle it */
+ if (ioc->driver == DHD_IOCTL_MAGIC) {
+ bcmerror = dhd_ioctl((void *)pub, ioc, data_buf, buflen);
+ if (bcmerror)
+ pub->bcmerror = bcmerror;
+ goto done;
+ }
+
+
+ /* send to dongle (must be up, and wl). */
+ if (pub->busstate != DHD_BUS_DATA) {
+ bcmerror = BCME_DONGLE_DOWN;
+ goto done;
+ }
+
+ if (!pub->iswl) {
+ bcmerror = BCME_DONGLE_DOWN;
+ goto done;
+ }
+
+ /*
+ * Flush the TX queue if required for proper message serialization:
+ * Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to
+ * prevent M4 encryption and
+ * intercept WLC_DISASSOC IOCTL - serialize WPS-DONE and WLC_DISASSOC IOCTL to
+ * prevent disassoc frame being sent before WPS-DONE frame.
+ */
+ if (ioc->cmd == WLC_SET_KEY ||
+ (ioc->cmd == WLC_SET_VAR && data_buf != NULL &&
+ strncmp("wsec_key", data_buf, 9) == 0) ||
+ (ioc->cmd == WLC_SET_VAR && data_buf != NULL &&
+ strncmp("bsscfg:wsec_key", data_buf, 15) == 0) ||
+ ioc->cmd == WLC_DISASSOC)
+ dhd_wait_pend8021x(net);
+
+#ifdef WLMEDIA_HTSF
+ if (data_buf) {
+ /* short cut wl ioctl calls here */
+ if (strcmp("htsf", data_buf) == 0) {
+ dhd_ioctl_htsf_get(dhd, 0);
+ return BCME_OK;
+ }
+
+ if (strcmp("htsflate", data_buf) == 0) {
+ if (ioc->set) {
+ memset(ts, 0, sizeof(tstamp_t)*TSMAX);
+ memset(&maxdelayts, 0, sizeof(tstamp_t));
+ maxdelay = 0;
+ tspktcnt = 0;
+ maxdelaypktno = 0;
+ memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN);
+ memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN);
+ memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN);
+ memset(&vi_d4.bin, 0, sizeof(uint32)*NUMBIN);
+ } else {
+ dhd_dump_latency();
+ }
+ return BCME_OK;
+ }
+ if (strcmp("htsfclear", data_buf) == 0) {
+ memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN);
+ memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN);
+ memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN);
+ memset(&vi_d4.bin, 0, sizeof(uint32)*NUMBIN);
+ htsf_seqnum = 0;
+ return BCME_OK;
+ }
+ if (strcmp("htsfhis", data_buf) == 0) {
+ dhd_dump_htsfhisto(&vi_d1, "H to D");
+ dhd_dump_htsfhisto(&vi_d2, "D to D");
+ dhd_dump_htsfhisto(&vi_d3, "D to H");
+ dhd_dump_htsfhisto(&vi_d4, "H to H");
+ return BCME_OK;
+ }
+ if (strcmp("tsport", data_buf) == 0) {
+ if (ioc->set) {
+ memcpy(&tsport, data_buf + 7, 4);
+ } else {
+ DHD_ERROR(("current timestamp port: %d \n", tsport));
+ }
+ return BCME_OK;
+ }
+ }
+#endif /* WLMEDIA_HTSF */
+
+ if ((ioc->cmd == WLC_SET_VAR || ioc->cmd == WLC_GET_VAR) &&
+ data_buf != NULL && strncmp("rpc_", data_buf, 4) == 0) {
+#ifdef BCM_FD_AGGR
+ bcmerror = dhd_fdaggr_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, data_buf, buflen);
+#else
+ bcmerror = BCME_UNSUPPORTED;
+#endif
+ goto done;
+ }
+ bcmerror = dhd_wl_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, data_buf, buflen);
+
+done:
+ dhd_check_hang(net, pub, bcmerror);
+
+ return bcmerror;
+}
+
+static int
+dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
+ dhd_ioctl_t ioc;
+ int bcmerror = 0;
+ int ifidx;
+ int ret;
+ void *local_buf = NULL;
+ u16 buflen = 0;
+
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+
+ /* send to dongle only if we are not waiting for reload already */
+ if (dhd->pub.hang_was_sent) {
+ DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__));
+ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return OSL_ERROR(BCME_DONGLE_DOWN);
+ }
+
+ ifidx = dhd_net2idx(dhd, net);
+ DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd));
+
+ if (ifidx == DHD_BAD_IF) {
+ DHD_ERROR(("%s: BAD IF\n", __FUNCTION__));
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return -1;
+ }
+
+#if defined(WL_WIRELESS_EXT)
+ /* linux wireless extensions */
+ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
+ /* may recurse, do NOT lock */
+ ret = wl_iw_ioctl(net, ifr, cmd);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return ret;
+ }
+#endif /* defined(WL_WIRELESS_EXT) */
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
+ if (cmd == SIOCETHTOOL) {
+ ret = dhd_ethtool(dhd, (void*)ifr->ifr_data);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return ret;
+ }
+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
+
+ if (cmd == SIOCDEVPRIVATE+1) {
+ ret = wl_android_priv_cmd(net, ifr, cmd);
+ dhd_check_hang(net, &dhd->pub, ret);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return ret;
+ }
+
+ if (cmd != SIOCDEVPRIVATE) {
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return -EOPNOTSUPP;
+ }
+
+ memset(&ioc, 0, sizeof(ioc));
+
+#ifdef CONFIG_COMPAT
+ if (is_compat_task()) {
+ compat_wl_ioctl_t compat_ioc;
+ if (copy_from_user(&compat_ioc, ifr->ifr_data, sizeof(compat_wl_ioctl_t))) {
+ bcmerror = BCME_BADADDR;
+ goto done;
+ }
+ ioc.cmd = compat_ioc.cmd;
+ ioc.buf = compat_ptr(compat_ioc.buf);
+ ioc.len = compat_ioc.len;
+ ioc.set = compat_ioc.set;
+ ioc.used = compat_ioc.used;
+ ioc.needed = compat_ioc.needed;
+ /* To differentiate between wl and dhd read 4 more byes */
+ if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(compat_wl_ioctl_t),
+ sizeof(uint)) != 0)) {
+ bcmerror = BCME_BADADDR;
+ goto done;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ /* Copy the ioc control structure part of ioctl request */
+ if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
+ bcmerror = BCME_BADADDR;
+ goto done;
+ }
+
+ /* To differentiate between wl and dhd read 4 more byes */
+ if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t),
+ sizeof(uint)) != 0)) {
+ bcmerror = BCME_BADADDR;
+ goto done;
+ }
+ }
+
+ if (!capable(CAP_NET_ADMIN)) {
+ bcmerror = BCME_EPERM;
+ goto done;
+ }
+
+ if (ioc.len > 0) {
+ buflen = MIN(ioc.len, DHD_IOCTL_MAXLEN);
+ if (!(local_buf = MALLOC(dhd->pub.osh, buflen+1))) {
+ bcmerror = BCME_NOMEM;
+ goto done;
+ }
+ if (copy_from_user(local_buf, ioc.buf, buflen)) {
+ bcmerror = BCME_BADADDR;
+ goto done;
+ }
+ *(char *)(local_buf + buflen) = '\0';
+ }
+
+ bcmerror = dhd_ioctl_process(&dhd->pub, ifidx, &ioc, local_buf);
+
+ if (!bcmerror && buflen && local_buf && ioc.buf) {
+ if (copy_to_user(ioc.buf, local_buf, buflen))
+ bcmerror = -EFAULT;
+ }
+
+done:
+ if (local_buf)
+ MFREE(dhd->pub.osh, local_buf, buflen+1);
+
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+
+ return OSL_ERROR(bcmerror);
+}
+
+
+
+
+static int
+dhd_stop(struct net_device *net)
+{
+ int ifidx = 0;
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
+
+
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+ DHD_TRACE(("%s: Enter %p\n", __FUNCTION__, net));
+ if (dhd->pub.up == 0) {
+ goto exit;
+ }
+
+
+ ifidx = dhd_net2idx(dhd, net);
+ BCM_REFERENCE(ifidx);
+
+ /* Set state and stop OS transmissions */
+ netif_stop_queue(net);
+ dhd->pub.up = 0;
+
+#ifdef ENABLE_CONTROL_SCHED
+ dhd_sysfs_destroy_node(net);
+ dhd_dpc_prio = CUSTOM_DPC_PRIO_SETTING;
+ dhd_dpc_poli = SCHED_FIFO;
+#endif /* ENABLE_CONTROL_SCHED */
+
+#ifdef WL_CFG80211
+ if (ifidx == 0) {
+ wl_cfg80211_down(NULL);
+
+ /*
+ * For CFG80211: Clean up all the left over virtual interfaces
+ * when the primary Interface is brought down. [ifconfig wlan0 down]
+ */
+ if (!dhd_download_fw_on_driverload) {
+ if ((dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) &&
+ (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
+ int i;
+
+
+ dhd_net_if_lock_local(dhd);
+ for (i = 1; i < DHD_MAX_IFS; i++)
+ dhd_remove_if(&dhd->pub, i, FALSE);
+ dhd_net_if_unlock_local(dhd);
+ }
+ cancel_work_sync(dhd->dhd_deferred_wq);
+ }
+ }
+#endif /* WL_CFG80211 */
+
+#ifdef PROP_TXSTATUS
+ dhd_wlfc_cleanup(&dhd->pub, NULL, 0);
+#endif
+ /* Stop the protocol module */
+ dhd_prot_stop(&dhd->pub);
+
+ OLD_MOD_DEC_USE_COUNT;
+exit:
+#if defined(WL_CFG80211)
+ if (ifidx == 0 && !dhd_download_fw_on_driverload)
+ wl_android_wifi_off(net);
+#endif
+ dhd->pub.rxcnt_timeout = 0;
+ dhd->pub.txcnt_timeout = 0;
+
+ dhd->pub.hang_was_sent = 0;
+
+ /* Clear country spec for for built-in type driver */
+ if (!dhd_download_fw_on_driverload) {
+ dhd->pub.dhd_cspec.country_abbrev[0] = 0x00;
+ dhd->pub.dhd_cspec.rev = 0;
+ dhd->pub.dhd_cspec.ccode[0] = 0x00;
+ }
+
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return 0;
+}
+
+#if defined(WL_CFG80211) && (defined(USE_INITIAL_2G_SCAN) || \
+ defined(USE_INITIAL_SHORT_DWELL_TIME))
+extern bool g_first_broadcast_scan;
+#endif /* OEM_ANDROID && WL_CFG80211 && (USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME) */
+
+#ifdef WL11U
+static int dhd_interworking_enable(dhd_pub_t *dhd)
+{
+ char iovbuf[WLC_IOCTL_SMLEN];
+ uint32 enable = true;
+ int ret = BCME_OK;
+
+ bcm_mkiovar("interworking", (char *)&enable, sizeof(enable), iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s: enableing interworking failed, ret=%d\n", __FUNCTION__, ret));
+ }
+
+ if (ret == BCME_OK) {
+ /* basic capabilities for HS20 REL2 */
+ uint32 cap = WL_WNM_BSSTRANS | WL_WNM_NOTIF;
+ bcm_mkiovar("wnm", (char *)&cap, sizeof(cap), iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
+ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s: failed to set WNM info, ret=%d\n", __FUNCTION__, ret));
+ }
+ }
+
+ return ret;
+}
+#endif /* WL11u */
+
+#ifdef ENABLE_CONTROL_SCHED
+static ssize_t
+read_dpc_prio(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
+{
+ DHD_INFO(("%s: read cur_prio(%d), cur_poli(%d)\n",
+ __FUNCTION__, dhd_dpc_prio, dhd_dpc_poli));
+ memset(buf, 0, sizeof(uint32));
+ count += snprintf(buf, sizeof(uint32), "%d", dhd_dpc_prio + (dhd_dpc_poli * 100));
+ return count;
+}
+
+static ssize_t
+write_dpc_prio(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t size)
+{
+ uint32 new_prio = 0;
+ uint32 cur_prio = dhd_dpc_prio + (dhd_dpc_poli * 100);
+
+ memcpy(&new_prio, buf, sizeof(uint32));
+ new_prio = bcm_atoi((char*)&new_prio);
+
+ if (new_prio < 0 || new_prio > 199) {
+ DHD_ERROR(("%s: ERROR invalid new_prio(%d)\n",
+ __FUNCTION__, new_prio));
+ return -EINVAL;
+ }
+
+ if (cur_prio != new_prio) {
+ dhd_dpc_prio = new_prio % 100;
+ dhd_dpc_poli = new_prio / 100;
+ DHD_INFO(("%s: write new_prio(%d), new_policy(%d)\n",
+ __FUNCTION__, dhd_dpc_prio, dhd_dpc_poli));
+ }
+
+ return sizeof(uint32);
+}
+
+static struct bin_attribute dpc_prio_attr = {
+ .attr = {.name = "dpc_prio", .mode = 0644},
+ .size = sizeof(uint32),
+ .read = read_dpc_prio,
+ .write = write_dpc_prio,
+};
+
+static int
+dhd_sysfs_create_node(struct net_device *net)
+{
+ int ret;
+
+ DHD_INFO(("%s Enter\n", __func__));
+ ret = sysfs_create_bin_file(&net->dev.kobj, &dpc_prio_attr);
+
+ if (ret) {
+ DHD_ERROR(("%s: create dpc_prio sysfs fail, ret(%d)\n", __FUNCTION__, ret));
+ return ret;
+ }
+ return 0;
+}
+
+static void
+dhd_sysfs_destroy_node(struct net_device *net)
+{
+ DHD_INFO(("%s Enter\n", __FUNCTION__));
+ sysfs_remove_bin_file(&net->dev.kobj, &dpc_prio_attr);
+}
+#endif /* ENABLE_CONTROL_SCHED */
+
+
+static int
+dhd_open(struct net_device *net)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
+#ifdef TOE
+ uint32 toe_ol;
+#endif
+ int ifidx;
+ int32 ret = 0;
+
+
+
+
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+ dhd->pub.dongle_trap_occured = 0;
+ dhd->pub.hang_was_sent = 0;
+
+#ifdef ENABLE_CONTROL_SCHED
+ ret = dhd_sysfs_create_node(net);
+ if (ret) {
+ DHD_ERROR(("%s: Failed to setup dpc_prio ret(%d)\n", __FUNCTION__, ret));
+ goto exit;
+ }
+#endif /* ENABLE_CONTROL_SCHED */
+
+#if !defined(WL_CFG80211)
+ /*
+ * Force start if ifconfig_up gets called before START command
+ * We keep WEXT's wl_control_wl_start to provide backward compatibility
+ * This should be removed in the future
+ */
+ ret = wl_control_wl_start(net);
+ if (ret != 0) {
+ DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
+ ret = -1;
+ goto exit;
+ }
+
+#endif
+
+ ifidx = dhd_net2idx(dhd, net);
+ DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
+
+ if (ifidx < 0) {
+ DHD_ERROR(("%s: Error: called with invalid IF\n", __FUNCTION__));
+ ret = -1;
+ goto exit;
+ }
+
+ if (!dhd->iflist[ifidx]) {
+ DHD_ERROR(("%s: Error: called when IF already deleted\n", __FUNCTION__));
+ ret = -1;
+ goto exit;
+ }
+
+ if (ifidx == 0) {
+ atomic_set(&dhd->pend_8021x_cnt, 0);
+#if defined(WL_CFG80211)
+ if (!dhd_download_fw_on_driverload) {
+ DHD_ERROR(("\n%s\n", dhd_version));
+#if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
+ g_first_broadcast_scan = TRUE;
+#endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
+ ret = wl_android_wifi_on(net);
+ if (ret != 0) {
+ DHD_ERROR(("%s : wl_android_wifi_on failed (%d)\n",
+ __FUNCTION__, ret));
+ ret = -1;
+ goto exit;
+ }
+ }
+#endif
+
+ if (dhd->pub.busstate != DHD_BUS_DATA) {
+
+ /* try to bring up bus */
+ if ((ret = dhd_bus_start(&dhd->pub)) != 0) {
+ DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
+ ret = -1;
+ goto exit;
+ }
+
+ }
+
+ /* dhd_prot_init has been called in dhd_bus_start or wl_android_wifi_on */
+ memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN);
+
+#ifdef TOE
+ /* Get current TOE mode from dongle */
+ if (dhd_toe_get(dhd, ifidx, &toe_ol) >= 0 && (toe_ol & TOE_TX_CSUM_OL) != 0)
+ dhd->iflist[ifidx]->net->features |= NETIF_F_IP_CSUM;
+ else
+ dhd->iflist[ifidx]->net->features &= ~NETIF_F_IP_CSUM;
+#endif /* TOE */
+
+#if defined(WL_CFG80211)
+ if (unlikely(wl_cfg80211_up(NULL))) {
+ DHD_ERROR(("%s: failed to bring up cfg80211\n", __FUNCTION__));
+ ret = -1;
+ goto exit;
+ }
+#endif /* WL_CFG80211 */
+ }
+
+ /* Allow transmit calls */
+ netif_start_queue(net);
+ dhd->pub.up = 1;
+
+#ifdef BCMDBGFS
+ dhd_dbg_init(&dhd->pub);
+#endif
+
+ OLD_MOD_INC_USE_COUNT;
+exit:
+ if (ret)
+ dhd_stop(net);
+
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+
+
+ return ret;
+}
+
+int dhd_do_driver_init(struct net_device *net)
+{
+ dhd_info_t *dhd = NULL;
+
+ if (!net) {
+ DHD_ERROR(("Primary Interface not initialized \n"));
+ return -EINVAL;
+ }
+
+
+ /* && defined(OEM_ANDROID) && defined(BCMSDIO) */
+ dhd = *(dhd_info_t **)netdev_priv(net);
+
+ /* If driver is already initialized, do nothing
+ */
+ if (dhd->pub.busstate == DHD_BUS_DATA) {
+ DHD_TRACE(("Driver already Inititalized. Nothing to do"));
+ return 0;
+ }
+
+ if (dhd_open(net) < 0) {
+ DHD_ERROR(("Driver Init Failed \n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+dhd_event_ifadd(dhd_info_t *dhdinfo, wl_event_data_if_t *ifevent, char *name, uint8 *mac)
+{
+
+#ifdef WL_CFG80211
+ if (wl_cfg80211_notify_ifadd(ifevent->ifidx, name, mac, ifevent->bssidx) == BCME_OK)
+ return BCME_OK;
+#endif
+
+ /* handle IF event caused by wl commands, SoftAP, WEXT and
+ * anything else. This has to be done asynchronously otherwise
+ * DPC will be blocked (and iovars will timeout as DPC has no chance
+ * to read the response back)
+ */
+ if (ifevent->ifidx > 0) {
+ dhd_if_event_t *if_event = MALLOC(dhdinfo->pub.osh, sizeof(dhd_if_event_t));
+ if (if_event == NULL) {
+ DHD_ERROR(("dhd_event_ifadd: Failed MALLOC, malloced %d bytes",
+ MALLOCED(dhdinfo->pub.osh)));
+ return BCME_NOMEM;
+ }
+ memcpy(&if_event->event, ifevent, sizeof(if_event->event));
+ memcpy(if_event->mac, mac, ETHER_ADDR_LEN);
+ strncpy(if_event->name, name, IFNAMSIZ);
+ if_event->name[IFNAMSIZ - 1] = '\0';
+ dhd_deferred_schedule_work((void *)if_event, DHD_WQ_WORK_IF_ADD,
+ dhd_ifadd_event_handler, DHD_WORK_PRIORITY_LOW);
+ }
+
+ return BCME_OK;
+}
+
+int
+dhd_event_ifdel(dhd_info_t *dhdinfo, wl_event_data_if_t *ifevent, char *name, uint8 *mac)
+{
+ dhd_if_event_t *if_event;
+
+#if defined(WL_CFG80211) && !defined(P2PONEINT)
+ if (wl_cfg80211_notify_ifdel(ifevent->ifidx, name, mac, ifevent->bssidx) == BCME_OK)
+ return BCME_OK;
+#endif /* WL_CFG80211 */
+
+ /* handle IF event caused by wl commands, SoftAP, WEXT and
+ * anything else
+ */
+ if_event = MALLOC(dhdinfo->pub.osh, sizeof(dhd_if_event_t));
+ if (if_event == NULL) {
+ DHD_ERROR(("dhd_event_ifdel: malloc failed for if_event, malloced %d bytes",
+ MALLOCED(dhdinfo->pub.osh)));
+ return BCME_NOMEM;
+ }
+ memcpy(&if_event->event, ifevent, sizeof(if_event->event));
+ memcpy(if_event->mac, mac, ETHER_ADDR_LEN);
+ strncpy(if_event->name, name, IFNAMSIZ);
+ if_event->name[IFNAMSIZ - 1] = '\0';
+ dhd_deferred_schedule_work((void *)if_event, DHD_WQ_WORK_IF_DEL,
+ dhd_ifdel_event_handler, DHD_WORK_PRIORITY_LOW);
+
+ return BCME_OK;
+}
+
+/* unregister and free the existing net_device interface (if any) in iflist and
+ * allocate a new one. the slot is reused. this function does NOT register the
+ * new interface to linux kernel. dhd_register_if does the job
+ */
+struct net_device*
+dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, char *name,
+ uint8 *mac, uint8 bssidx, bool need_rtnl_lock, char *dngl_name)
+{
+ dhd_info_t *dhdinfo = (dhd_info_t *)dhdpub->info;
+ dhd_if_t *ifp;
+
+ ASSERT(dhdinfo && (ifidx < DHD_MAX_IFS));
+ ifp = dhdinfo->iflist[ifidx];
+
+ if (ifp != NULL) {
+ if (ifp->net != NULL) {
+ DHD_ERROR(("%s: free existing IF %s\n", __FUNCTION__, ifp->net->name));
+
+ /* in unregister_netdev case, the interface gets freed by net->destructor
+ * (which is set to free_netdev)
+ */
+ if (ifp->net->reg_state == NETREG_UNINITIALIZED) {
+ free_netdev(ifp->net);
+ } else {
+ netif_stop_queue(ifp->net);
+ if (need_rtnl_lock)
+ unregister_netdev(ifp->net);
+ else
+ unregister_netdevice(ifp->net);
+ }
+ ifp->net = NULL;
+ }
+ } else {
+ ifp = MALLOC(dhdinfo->pub.osh, sizeof(dhd_if_t));
+ if (ifp == NULL) {
+ DHD_ERROR(("%s: OOM - dhd_if_t(%zu)\n", __FUNCTION__, sizeof(dhd_if_t)));
+ return NULL;
+ }
+ }
+
+ memset(ifp, 0, sizeof(dhd_if_t));
+ ifp->info = dhdinfo;
+ ifp->idx = ifidx;
+ ifp->bssidx = bssidx;
+ if (mac != NULL)
+ memcpy(&ifp->mac_addr, mac, ETHER_ADDR_LEN);
+
+ /* Allocate etherdev, including space for private structure */
+ ifp->net = alloc_etherdev(sizeof(dhdinfo));
+ if (ifp->net == NULL) {
+ DHD_ERROR(("%s: OOM - alloc_etherdev(%zu)\n", __FUNCTION__, sizeof(dhdinfo)));
+ goto fail;
+ }
+ memcpy(netdev_priv(ifp->net), &dhdinfo, sizeof(dhdinfo));
+ if (name && name[0]) {
+ strncpy(ifp->net->name, name, IFNAMSIZ);
+ ifp->net->name[IFNAMSIZ - 1] = '\0';
+ }
+#ifdef WL_CFG80211
+ if (ifidx == 0)
+ ifp->net->destructor = free_netdev;
+ else
+ ifp->net->destructor = dhd_netdev_free;
+#else
+ ifp->net->destructor = free_netdev;
+#endif /* WL_CFG80211 */
+ strncpy(ifp->name, ifp->net->name, IFNAMSIZ);
+ ifp->name[IFNAMSIZ - 1] = '\0';
+ dhdinfo->iflist[ifidx] = ifp;
+
+/* initialize the dongle provided if name */
+ if (dngl_name)
+ strncpy(ifp->dngl_name, dngl_name, IFNAMSIZ);
+ else
+ strncpy(ifp->dngl_name, name, IFNAMSIZ);
+
+ return ifp->net;
+
+fail:
+ if (ifp != NULL) {
+ if (ifp->net != NULL) {
+ free_netdev(ifp->net);
+ ifp->net = NULL;
+ }
+ MFREE(dhdinfo->pub.osh, ifp, sizeof(*ifp));
+ ifp = NULL;
+ }
+ dhdinfo->iflist[ifidx] = NULL;
+ return NULL;
+}
+
+/* unregister and free the the net_device interface associated with the indexed
+ * slot, also free the slot memory and set the slot pointer to NULL
+ */
+int
+dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock)
+{
+ dhd_info_t *dhdinfo = (dhd_info_t *)dhdpub->info;
+ dhd_if_t *ifp;
+
+ ifp = dhdinfo->iflist[ifidx];
+ if (ifp != NULL) {
+ if (ifp->net != NULL) {
+ DHD_ERROR(("deleting interface '%s' idx %d\n", ifp->net->name, ifp->idx));
+
+ /* in unregister_netdev case, the interface gets freed by net->destructor
+ * (which is set to free_netdev)
+ */
+ if (ifp->net->reg_state == NETREG_UNINITIALIZED) {
+ free_netdev(ifp->net);
+ } else {
+ netif_stop_queue(ifp->net);
+
+ if (need_rtnl_lock)
+ unregister_netdev(ifp->net);
+ else
+ unregister_netdevice(ifp->net);
+ }
+ ifp->net = NULL;
+ }
+
+ dhdinfo->iflist[ifidx] = NULL;
+ MFREE(dhdinfo->pub.osh, ifp, sizeof(*ifp));
+
+ }
+
+ return BCME_OK;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+static struct net_device_ops dhd_ops_pri = {
+ .ndo_open = dhd_open,
+ .ndo_stop = dhd_stop,
+ .ndo_get_stats = dhd_get_stats,
+ .ndo_do_ioctl = dhd_ioctl_entry,
+ .ndo_start_xmit = dhd_start_xmit,
+ .ndo_set_mac_address = dhd_set_mac_address,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+ .ndo_set_rx_mode = dhd_set_multicast_list,
+#else
+ .ndo_set_multicast_list = dhd_set_multicast_list,
+#endif
+};
+
+static struct net_device_ops dhd_ops_virt = {
+ .ndo_get_stats = dhd_get_stats,
+ .ndo_do_ioctl = dhd_ioctl_entry,
+ .ndo_start_xmit = dhd_start_xmit,
+ .ndo_set_mac_address = dhd_set_mac_address,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+ .ndo_set_rx_mode = dhd_set_multicast_list,
+#else
+ .ndo_set_multicast_list = dhd_set_multicast_list,
+#endif
+};
+
+#ifdef P2PONEINT
+extern int wl_cfgp2p_if_open(struct net_device *net);
+extern int wl_cfgp2p_if_stop(struct net_device *net);
+
+static struct net_device_ops dhd_cfgp2p_ops_virt = {
+ .ndo_open = wl_cfgp2p_if_open,
+ .ndo_stop = wl_cfgp2p_if_stop,
+ .ndo_get_stats = dhd_get_stats,
+ .ndo_do_ioctl = dhd_ioctl_entry,
+ .ndo_start_xmit = dhd_start_xmit,
+ .ndo_set_mac_address = dhd_set_mac_address,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+ .ndo_set_rx_mode = dhd_set_multicast_list,
+#else
+ .ndo_set_multicast_list = dhd_set_multicast_list,
+#endif
+};
+#endif /* P2PONEINT */
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */
+
+#ifdef DEBUGGER
+extern void debugger_init(void *bus_handle);
+#endif
+
+
+#ifdef SHOW_LOGTRACE
+static char *logstrs_path = "/root/logstrs.bin";
+static char *st_str_file_path = "/root/rtecdc.bin";
+static char *map_file_path = "/root/rtecdc.map";
+static char *rom_st_str_file_path = "/root/roml.bin";
+static char *rom_map_file_path = "/root/roml.map";
+
+#define BYTES_AHEAD_NUM 11 /* address in map file is before these many bytes */
+#define READ_NUM_BYTES 1000 /* read map file each time this No. of bytes */
+#define GO_BACK_FILE_POS_NUM_BYTES 100 /* set file pos back to cur pos */
+static char *ramstart_str = "text_start"; /* string in mapfile has addr ramstart */
+static char *rodata_start_str = "rodata_start"; /* string in mapfile has addr rodata start */
+static char *rodata_end_str = "rodata_end"; /* string in mapfile has addr rodata end */
+static char *ram_file_str = "rtecdc";
+static char *rom_file_str = "roml";
+#define RAMSTART_BIT 0x01
+#define RDSTART_BIT 0x02
+#define RDEND_BIT 0x04
+#define ALL_MAP_VAL (RAMSTART_BIT | RDSTART_BIT | RDEND_BIT)
+
+module_param(logstrs_path, charp, S_IRUGO);
+module_param(st_str_file_path, charp, S_IRUGO);
+module_param(map_file_path, charp, S_IRUGO);
+module_param(rom_st_str_file_path, charp, S_IRUGO);
+module_param(rom_map_file_path, charp, S_IRUGO);
+
+static void
+dhd_init_logstrs_array(dhd_event_log_t *temp)
+{
+ struct file *filep = NULL;
+ struct kstat stat;
+ mm_segment_t fs;
+ char *raw_fmts = NULL;
+ int logstrs_size = 0;
+
+ logstr_header_t *hdr = NULL;
+ uint32 *lognums = NULL;
+ char *logstrs = NULL;
+ int ram_index = 0;
+ char **fmts;
+ int num_fmts = 0;
+ uint32 i = 0;
+ int error = 0;
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ filep = filp_open(logstrs_path, O_RDONLY, 0);
+
+ if (IS_ERR(filep)) {
+ DHD_ERROR(("%s: Failed to open the file %s \n", __FUNCTION__, logstrs_path));
+ goto fail;
+ }
+ error = vfs_stat(logstrs_path, &stat);
+ if (error) {
+ DHD_ERROR(("%s: Failed to stat file %s \n", __FUNCTION__, logstrs_path));
+ goto fail;
+ }
+ logstrs_size = (int) stat.size;
+
+ raw_fmts = kmalloc(logstrs_size, GFP_KERNEL);
+ if (raw_fmts == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory \n", __FUNCTION__));
+ goto fail;
+ }
+ if (vfs_read(filep, raw_fmts, logstrs_size, &filep->f_pos) != logstrs_size) {
+ DHD_ERROR(("%s: Failed to read file %s", __FUNCTION__, logstrs_path));
+ goto fail;
+ }
+
+ /* Remember header from the logstrs.bin file */
+ hdr = (logstr_header_t *) (raw_fmts + logstrs_size -
+ sizeof(logstr_header_t));
+
+ if (hdr->log_magic == LOGSTRS_MAGIC) {
+ /*
+ * logstrs.bin start with header.
+ */
+ num_fmts = hdr->rom_logstrs_offset / sizeof(uint32);
+ ram_index = (hdr->ram_lognums_offset -
+ hdr->rom_lognums_offset) / sizeof(uint32);
+ lognums = (uint32 *) &raw_fmts[hdr->rom_lognums_offset];
+ logstrs = (char *) &raw_fmts[hdr->rom_logstrs_offset];
+ } else {
+ /*
+ * Legacy logstrs.bin format without header.
+ */
+ num_fmts = *((uint32 *) (raw_fmts)) / sizeof(uint32);
+ if (num_fmts == 0) {
+ /* Legacy ROM/RAM logstrs.bin format:
+ * - ROM 'lognums' section
+ * - RAM 'lognums' section
+ * - ROM 'logstrs' section.
+ * - RAM 'logstrs' section.
+ *
+ * 'lognums' is an array of indexes for the strings in the
+ * 'logstrs' section. The first uint32 is 0 (index of first
+ * string in ROM 'logstrs' section).
+ *
+ * The 4324b5 is the only ROM that uses this legacy format. Use the
+ * fixed number of ROM fmtnums to find the start of the RAM
+ * 'lognums' section. Use the fixed first ROM string ("Con\n") to
+ * find the ROM 'logstrs' section.
+ */
+ #define NUM_4324B5_ROM_FMTS 186
+ #define FIRST_4324B5_ROM_LOGSTR "Con\n"
+ ram_index = NUM_4324B5_ROM_FMTS;
+ lognums = (uint32 *) raw_fmts;
+ num_fmts = ram_index;
+ logstrs = (char *) &raw_fmts[num_fmts << 2];
+ while (strncmp(FIRST_4324B5_ROM_LOGSTR, logstrs, 4)) {
+ num_fmts++;
+ logstrs = (char *) &raw_fmts[num_fmts << 2];
+ }
+ } else {
+ /* Legacy RAM-only logstrs.bin format:
+ * - RAM 'lognums' section
+ * - RAM 'logstrs' section.
+ *
+ * 'lognums' is an array of indexes for the strings in the
+ * 'logstrs' section. The first uint32 is an index to the
+ * start of 'logstrs'. Therefore, if this index is divided
+ * by 'sizeof(uint32)' it provides the number of logstr
+ * entries.
+ */
+ ram_index = 0;
+ lognums = (uint32 *) raw_fmts;
+ logstrs = (char *) &raw_fmts[num_fmts << 2];
+ }
+ }
+ fmts = kmalloc(num_fmts * sizeof(char *), GFP_KERNEL);
+ if (fmts == NULL) {
+ DHD_ERROR(("Failed to allocate fmts memory"));
+ goto fail;
+ }
+
+ for (i = 0; i < num_fmts; i++) {
+ /* ROM lognums index into logstrs using 'rom_logstrs_offset' as a base
+ * (they are 0-indexed relative to 'rom_logstrs_offset').
+ *
+ * RAM lognums are already indexed to point to the correct RAM logstrs (they
+ * are 0-indexed relative to the start of the logstrs.bin file).
+ */
+ if (i == ram_index) {
+ logstrs = raw_fmts;
+ }
+ fmts[i] = &logstrs[lognums[i]];
+ }
+ temp->fmts = fmts;
+ temp->raw_fmts = raw_fmts;
+ temp->num_fmts = num_fmts;
+ filp_close(filep, NULL);
+ set_fs(fs);
+ return;
+fail:
+ if (raw_fmts) {
+ kfree(raw_fmts);
+ raw_fmts = NULL;
+ }
+ if (!IS_ERR(filep))
+ filp_close(filep, NULL);
+ set_fs(fs);
+ temp->fmts = NULL;
+ return;
+}
+
+static int
+dhd_read_map(char *fname, uint32 *ramstart, uint32 *rodata_start,
+ uint32 *rodata_end)
+{
+ struct file *filep = NULL;
+ mm_segment_t fs;
+ char *raw_fmts = NULL;
+ uint32 read_size = READ_NUM_BYTES;
+ int error = 0;
+ char * cptr = NULL;
+ char c;
+ uint8 count = 0;
+
+ *ramstart = 0;
+ *rodata_start = 0;
+ *rodata_end = 0;
+
+ if (fname == NULL) {
+ DHD_ERROR(("%s: ERROR fname is NULL \n", __FUNCTION__));
+ return BCME_ERROR;
+ }
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ filep = filp_open(fname, O_RDONLY, 0);
+ if (IS_ERR(filep)) {
+ DHD_ERROR(("%s: Failed to open %s \n", __FUNCTION__, fname));
+ goto fail;
+ }
+
+ raw_fmts = kmalloc(read_size, GFP_KERNEL);
+ if (raw_fmts == NULL) {
+ DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__));
+ goto fail;
+ }
+
+ /* read ram start, rodata_start and rodata_end values from map file */
+
+ while (count != ALL_MAP_VAL)
+ {
+ error = vfs_read(filep, raw_fmts, read_size, (&filep->f_pos));
+ if (error < 0) {
+ DHD_ERROR(("%s: read failed %s err:%d \n", __FUNCTION__,
+ map_file_path, error));
+ goto fail;
+ }
+
+ if (error < read_size) {
+ /*
+ * since we reset file pos back to earlier pos by
+ * GO_BACK_FILE_POS_NUM_BYTES bytes we won't reach EOF.
+ * So if ret value is less than read_size, reached EOF don't read further
+ */
+ break;
+ }
+
+ /* Get ramstart address */
+ if ((cptr = strstr(raw_fmts, ramstart_str))) {
+ cptr = cptr - BYTES_AHEAD_NUM;
+ sscanf(cptr, "%x %c text_start", ramstart, &c);
+ count |= RAMSTART_BIT;
+ }
+
+ /* Get ram rodata start address */
+ if ((cptr = strstr(raw_fmts, rodata_start_str))) {
+ cptr = cptr - BYTES_AHEAD_NUM;
+ sscanf(cptr, "%x %c rodata_start", rodata_start, &c);
+ count |= RDSTART_BIT;
+ }
+
+ /* Get ram rodata end address */
+ if ((cptr = strstr(raw_fmts, rodata_end_str))) {
+ cptr = cptr - BYTES_AHEAD_NUM;
+ sscanf(cptr, "%x %c rodata_end", rodata_end, &c);
+ count |= RDEND_BIT;
+ }
+ memset(raw_fmts, 0, read_size);
+ /*
+ * go back to predefined NUM of bytes so that we won't miss
+ * the string and addr even if it comes as splited in next read.
+ */
+ filep->f_pos = filep->f_pos - GO_BACK_FILE_POS_NUM_BYTES;
+ }
+
+ DHD_ERROR(("---ramstart: 0x%x, rodata_start: 0x%x, rodata_end:0x%x\n",
+ *ramstart, *rodata_start, *rodata_end));
+
+ DHD_ERROR(("readmap over \n"));
+
+fail:
+ if (raw_fmts) {
+ kfree(raw_fmts);
+ raw_fmts = NULL;
+ }
+ if (!IS_ERR(filep))
+ filp_close(filep, NULL);
+
+ set_fs(fs);
+ if (count == ALL_MAP_VAL) {
+ return BCME_OK;
+ }
+ DHD_ERROR(("readmap error 0X%x \n", count));
+ return BCME_ERROR;
+}
+
+static void
+dhd_init_static_strs_array(dhd_event_log_t *temp, char *str_file, char *map_file)
+{
+ struct file *filep = NULL;
+ mm_segment_t fs;
+ char *raw_fmts = NULL;
+ uint32 logstrs_size = 0;
+
+ int error = 0;
+ uint32 ramstart = 0;
+ uint32 rodata_start = 0;
+ uint32 rodata_end = 0;
+ uint32 logfilebase = 0;
+
+ error = dhd_read_map(map_file, &ramstart, &rodata_start, &rodata_end);
+ if (error == BCME_ERROR) {
+ DHD_ERROR(("readmap Error!! \n"));
+ /* don't do event log parsing in actual case */
+ temp->raw_sstr = NULL;
+ return;
+ }
+ DHD_ERROR(("ramstart: 0x%x, rodata_start: 0x%x, rodata_end:0x%x\n",
+ ramstart, rodata_start, rodata_end));
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ filep = filp_open(str_file, O_RDONLY, 0);
+ if (IS_ERR(filep)) {
+ DHD_ERROR(("%s: Failed to open the file %s \n", __FUNCTION__, str_file));
+ goto fail;
+ }
+
+ /* Full file size is huge. Just read required part */
+ logstrs_size = rodata_end - rodata_start;
+
+ raw_fmts = kmalloc(logstrs_size, GFP_KERNEL);
+ if (raw_fmts == NULL) {
+ DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__));
+ goto fail;
+ }
+
+ logfilebase = rodata_start - ramstart;
+
+ error = generic_file_llseek(filep, logfilebase, SEEK_SET);
+ if (error < 0) {
+ DHD_ERROR(("%s: %s llseek failed %d \n", __FUNCTION__, str_file, error));
+ goto fail;
+ }
+
+ error = vfs_read(filep, raw_fmts, logstrs_size, (&filep->f_pos));
+ if (error != logstrs_size) {
+ DHD_ERROR(("%s: %s read failed %d \n", __FUNCTION__, str_file, error));
+ goto fail;
+ }
+
+ if (strstr(str_file, ram_file_str) != NULL) {
+ temp->raw_sstr = raw_fmts;
+ temp->ramstart = ramstart;
+ temp->rodata_start = rodata_start;
+ temp->rodata_end = rodata_end;
+ } else if (strstr(str_file, rom_file_str) != NULL) {
+ temp->rom_raw_sstr = raw_fmts;
+ temp->rom_ramstart = ramstart;
+ temp->rom_rodata_start = rodata_start;
+ temp->rom_rodata_end = rodata_end;
+ }
+
+ filp_close(filep, NULL);
+ set_fs(fs);
+
+ return;
+fail:
+ if (raw_fmts) {
+ kfree(raw_fmts);
+ raw_fmts = NULL;
+ }
+ if (!IS_ERR(filep))
+ filp_close(filep, NULL);
+ set_fs(fs);
+ if (strstr(str_file, ram_file_str) != NULL) {
+ temp->raw_sstr = NULL;
+ } else if (strstr(str_file, rom_file_str) != NULL) {
+ temp->rom_raw_sstr = NULL;
+ }
+ return;
+}
+
+#endif /* SHOW_LOGTRACE */
+
+dhd_pub_t *
+dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
+{
+ dhd_info_t *dhd = NULL;
+ struct net_device *net = NULL;
+ char if_name[IFNAMSIZ] = {'\0'};
+ uint32 bus_type = -1;
+ uint32 bus_num = -1;
+ uint32 slot_num = -1;
+ wifi_adapter_info_t *adapter = NULL;
+#ifdef CUSTOM_COUNTRY_CODE
+ struct cntry_locales_custom *cloc_ptr = NULL;
+#endif /* CUSTOM_COUNTRY_CODE */
+
+ dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT;
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* will implement get_ids for DBUS later */
+ dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num);
+ adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
+
+ /* Allocate primary dhd_info */
+ dhd = wifi_platform_prealloc(adapter, DHD_PREALLOC_DHD_INFO, sizeof(dhd_info_t));
+ if (dhd == NULL) {
+ dhd = MALLOC(osh, sizeof(dhd_info_t));
+ if (dhd == NULL) {
+ DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__));
+ goto fail;
+ }
+ }
+ memset(dhd, 0, sizeof(dhd_info_t));
+ dhd_state |= DHD_ATTACH_STATE_DHD_ALLOC;
+
+ dhd->pub.osh = osh;
+ dhd->adapter = adapter;
+
+#ifdef OOB_PARAM
+ dhd->pub.oob_disable = adapter->oob_disable;
+#endif /* OOB_PARAM */
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+ wifi_platform_get_mac_addr(dhd->adapter, dhd->pub.mac.octet);
+#endif /* GET_CUSTOM_MAC_ENABLE */
+#ifdef CUSTOM_COUNTRY_CODE
+ cloc_ptr = wifi_platform_get_country_code(dhd->adapter, dhd->pub.dhd_cspec.ccode);
+ if (cloc_ptr) {
+ strlcpy(dhd->pub.dhd_cspec.country_abbrev, cloc_ptr->iso_abbrev, WLC_CNTRY_BUF_SZ);
+ strlcpy(dhd->pub.dhd_cspec.ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ);
+ dhd->pub.dhd_cspec.rev = cloc_ptr->custom_locale_rev;
+ get_customized_country_code(dhd->adapter, dhd->pub.dhd_cspec.ccode,
+ &dhd->pub.dhd_cspec);
+ }
+#endif /* CUSTOM_COUNTRY_CODE */
+ dhd->thr_dpc_ctl.thr_pid = DHD_PID_KT_TL_INVALID;
+ dhd->thr_wdt_ctl.thr_pid = DHD_PID_KT_INVALID;
+
+ /* Initialize thread based operation and lock */
+ sema_init(&dhd->sdsem, 1);
+
+ /* Some DHD modules (e.g. cfg80211) configures operation mode based on firmware name.
+ * This is indeed a hack but we have to make it work properly before we have a better
+ * solution
+ */
+ dhd_update_fw_nv_path(dhd);
+
+ /* Link to info module */
+ dhd->pub.info = dhd;
+ /* Link to bus module */
+ dhd->pub.bus = bus;
+ dhd->pub.hdrlen = bus_hdrlen;
+
+ /* Set network interface name if it was provided as module parameter */
+ if (iface_name[0]) {
+ int len;
+ char ch;
+ strncpy(if_name, iface_name, IFNAMSIZ);
+ if_name[IFNAMSIZ - 1] = 0;
+ len = strlen(if_name);
+ ch = if_name[len - 1];
+ if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
+ strcat(if_name, "%d");
+ }
+ net = dhd_allocate_if(&dhd->pub, 0, if_name, NULL, 0, TRUE, NULL);
+ if (net == NULL)
+ goto fail;
+ dhd_state |= DHD_ATTACH_STATE_ADD_IF;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
+ net->open = NULL;
+#else
+ net->netdev_ops = NULL;
+#endif
+
+ sema_init(&dhd->proto_sem, 1);
+
+#ifdef PROP_TXSTATUS
+ spin_lock_init(&dhd->wlfc_spinlock);
+
+ dhd->pub.skip_fc = dhd_wlfc_skip_fc;
+ dhd->pub.plat_init = dhd_wlfc_plat_init;
+ dhd->pub.plat_deinit = dhd_wlfc_plat_deinit;
+#endif /* PROP_TXSTATUS */
+
+ /* Initialize other structure content */
+ init_waitqueue_head(&dhd->ioctl_resp_wait);
+ init_waitqueue_head(&dhd->ctrl_wait);
+
+ /* Initialize the spinlocks */
+ spin_lock_init(&dhd->sdlock);
+ spin_lock_init(&dhd->txqlock);
+ spin_lock_init(&dhd->dhd_lock);
+ spin_lock_init(&dhd->rxf_lock);
+#if defined(RXFRAME_THREAD)
+ dhd->rxthread_enabled = TRUE;
+#endif /* defined(RXFRAME_THREAD) */
+
+#ifdef DHDTCPACK_SUPPRESS
+ spin_lock_init(&dhd->tcpack_lock);
+#endif /* DHDTCPACK_SUPPRESS */
+
+ /* Initialize Wakelock stuff */
+ spin_lock_init(&dhd->wakelock_spinlock);
+ dhd->wakelock_counter = 0;
+ dhd->wakelock_wd_counter = 0;
+ dhd->wakelock_rx_timeout_enable = 0;
+ dhd->wakelock_ctrl_timeout_enable = 0;
+ dhd->waive_wakelock = FALSE;
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
+ wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
+ wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake");
+ wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake");
+#endif /* CONFIG_HAS_WAKELOCK */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ mutex_init(&dhd->dhd_net_if_mutex);
+ mutex_init(&dhd->dhd_suspend_mutex);
+#endif
+ dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT;
+
+ /* Attach and link in the protocol */
+ if (dhd_prot_attach(&dhd->pub) != 0) {
+ DHD_ERROR(("dhd_prot_attach failed\n"));
+ goto fail;
+ }
+ dhd_state |= DHD_ATTACH_STATE_PROT_ATTACH;
+
+#ifdef WL_CFG80211
+ /* Attach and link in the cfg80211 */
+ if (unlikely(wl_cfg80211_attach(net, &dhd->pub))) {
+ DHD_ERROR(("wl_cfg80211_attach failed\n"));
+ goto fail;
+ }
+
+ dhd_monitor_init(&dhd->pub);
+ dhd_state |= DHD_ATTACH_STATE_CFG80211;
+#endif
+#if defined(WL_WIRELESS_EXT)
+ /* Attach and link in the iw */
+ if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) {
+ if (wl_iw_attach(net, (void *)&dhd->pub) != 0) {
+ DHD_ERROR(("wl_iw_attach failed\n"));
+ goto fail;
+ }
+ dhd_state |= DHD_ATTACH_STATE_WL_ATTACH;
+ }
+#endif /* defined(WL_WIRELESS_EXT) */
+
+#ifdef SHOW_LOGTRACE
+ dhd_init_logstrs_array(&dhd->event_data);
+ dhd_init_static_strs_array(&dhd->event_data, st_str_file_path, map_file_path);
+ dhd_init_static_strs_array(&dhd->event_data, rom_st_str_file_path, rom_map_file_path);
+#endif /* SHOW_LOGTRACE */
+
+
+ /* Set up the watchdog timer */
+ init_timer(&dhd->timer);
+ dhd->timer.data = (ulong)dhd;
+ dhd->timer.function = dhd_watchdog;
+ dhd->default_wd_interval = dhd_watchdog_ms;
+
+ if (dhd_watchdog_prio >= 0) {
+ /* Initialize watchdog thread */
+ PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread");
+ if (dhd->thr_wdt_ctl.thr_pid < 0) {
+ goto fail;
+ }
+
+ } else {
+ dhd->thr_wdt_ctl.thr_pid = -1;
+ }
+
+#ifdef DEBUGGER
+ debugger_init((void *) bus);
+#endif
+
+ /* Set up the bottom half handler */
+ if (dhd_dpc_prio >= 0) {
+ /* Initialize DPC thread */
+ PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc");
+ if (dhd->thr_dpc_ctl.thr_pid < 0) {
+ goto fail;
+ }
+ } else {
+ /* use tasklet for dpc */
+ tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd);
+ dhd->thr_dpc_ctl.thr_pid = -1;
+ }
+
+ if (dhd->rxthread_enabled) {
+ bzero(&dhd->pub.skbbuf[0], sizeof(void *) * MAXSKBPEND);
+ /* Initialize RXF thread */
+ PROC_START(dhd_rxf_thread, dhd, &dhd->thr_rxf_ctl, 0, "dhd_rxf");
+ if (dhd->thr_rxf_ctl.thr_pid < 0) {
+ goto fail;
+ }
+ }
+
+ dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED;
+
+ /*
+ * Save the dhd_info into the priv
+ */
+ memcpy(netdev_priv(net), &dhd, sizeof(dhd));
+
+#if defined(CONFIG_PM_SLEEP)
+ dhd->pm_notifier.notifier_call = dhd_pm_callback;
+ dhd->pm_notifier.priority = 10;
+ if (!dhd_pm_notifier_registered) {
+ dhd_pm_notifier_registered = TRUE;
+ register_pm_notifier(&dhd->pm_notifier);
+ }
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef SAR_SUPPORT
+ dhd->sar_notifier.notifier_call = dhd_sar_callback;
+ if (!dhd_sar_notifier_registered) {
+ dhd_sar_notifier_registered = TRUE;
+ register_notifier_by_sar(&dhd->sar_notifier);
+ }
+#endif
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
+ dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
+ dhd->early_suspend.suspend = dhd_early_suspend;
+ dhd->early_suspend.resume = dhd_late_resume;
+ register_early_suspend(&dhd->early_suspend);
+ dhd_state |= DHD_ATTACH_STATE_EARLYSUSPEND_DONE;
+#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
+
+#ifdef ARP_OFFLOAD_SUPPORT
+ dhd->pend_ipaddr = 0;
+ if (!dhd_inetaddr_notifier_registered) {
+ dhd_inetaddr_notifier_registered = TRUE;
+ register_inetaddr_notifier(&dhd_inetaddr_notifier);
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+ if (!dhd_inet6addr_notifier_registered) {
+ dhd_inet6addr_notifier_registered = TRUE;
+ register_inet6addr_notifier(&dhd_inet6addr_notifier);
+ }
+ dhd->dhd_deferred_wq = dhd_deferred_work_init((void *)dhd);
+#ifdef DEBUG_CPU_FREQ
+ dhd->new_freq = alloc_percpu(int);
+ dhd->freq_trans.notifier_call = dhd_cpufreq_notifier;
+ cpufreq_register_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+#ifdef DHDTCPACK_SUPPRESS
+ dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_DELAYTX);
+#endif /* DHDTCPACK_SUPPRESS */
+#ifdef DHD_DEBUG
+ dhd->join_timeout_val = DHD_JOIN_MAX_TIME_DEFAULT;
+ dhd->scan_time_count = DHD_SCAN_DEF_TIMEOUT;
+#endif
+ dhd_state |= DHD_ATTACH_STATE_DONE;
+ dhd->dhd_state = dhd_state;
+
+ dhd->unit = dhd_found + instance_base;
+ dhd_found++;
+ return &dhd->pub;
+
+fail:
+ if (dhd_state >= DHD_ATTACH_STATE_DHD_ALLOC) {
+ DHD_TRACE(("%s: Calling dhd_detach dhd_state 0x%x &dhd->pub %p\n",
+ __FUNCTION__, dhd_state, &dhd->pub));
+ dhd->dhd_state = dhd_state;
+ dhd_detach(&dhd->pub);
+ dhd_free(&dhd->pub);
+ }
+
+ return NULL;
+}
+
+int dhd_get_fw_mode(dhd_info_t *dhdinfo)
+{
+ if (strstr(dhdinfo->fw_path, "_apsta") != NULL)
+ return DHD_FLAG_HOSTAP_MODE;
+ if (strstr(dhdinfo->fw_path, "_p2p") != NULL)
+ return DHD_FLAG_P2P_MODE;
+ if (strstr(dhdinfo->fw_path, "_ibss") != NULL)
+ return DHD_FLAG_IBSS_MODE;
+ if (strstr(dhdinfo->fw_path, "_mfg") != NULL)
+ return DHD_FLAG_MFG_MODE;
+
+ return DHD_FLAG_STA_MODE;
+}
+
+bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
+{
+ int fw_len;
+ int nv_len;
+ const char *fw = NULL;
+ const char *nv = NULL;
+ wifi_adapter_info_t *adapter = dhdinfo->adapter;
+
+
+ /* Update firmware and nvram path. The path may be from adapter info or module parameter
+ * The path from adapter info is used for initialization only (as it won't change).
+ *
+ * The firmware_path/nvram_path module parameter may be changed by the system at run
+ * time. When it changes we need to copy it to dhdinfo->fw_path. Also Android private
+ * command may change dhdinfo->fw_path. As such we need to clear the path info in
+ * module parameter after it is copied. We won't update the path until the module parameter
+ * is changed again (first character is not '\0')
+ */
+
+ /* set default firmware and nvram path for built-in type driver */
+ if (!dhd_download_fw_on_driverload) {
+#ifdef CONFIG_BCMDHD_FW_PATH
+ fw = CONFIG_BCMDHD_FW_PATH;
+#endif /* CONFIG_BCMDHD_FW_PATH */
+#ifdef CONFIG_BCMDHD_NVRAM_PATH
+ nv = CONFIG_BCMDHD_NVRAM_PATH;
+#endif /* CONFIG_BCMDHD_NVRAM_PATH */
+ }
+
+ /* check if we need to initialize the path */
+ if (adapter && adapter->fw_path && adapter->fw_path[0] != '\0')
+ fw = adapter->fw_path;
+
+ if (adapter && adapter->nv_path && adapter->nv_path[0] != '\0')
+ nv = adapter->nv_path;
+
+ /* Use module parameter if it is valid, EVEN IF the path has not been initialized
+ *
+ * TODO: need a solution for multi-chip, can't use the same firmware for all chips
+ */
+ if (firmware_path[0] != '\0')
+ fw = firmware_path;
+ if (nvram_path[0] != '\0')
+ nv = nvram_path;
+
+ if (fw && fw[0] != '\0') {
+ fw_len = strlen(fw);
+ if (fw_len >= sizeof(dhdinfo->fw_path)) {
+ DHD_ERROR(("fw path len exceeds max len of dhdinfo->fw_path\n"));
+ return FALSE;
+ }
+ strncpy(dhdinfo->fw_path, fw, sizeof(dhdinfo->fw_path));
+ if (dhdinfo->fw_path[fw_len-1] == '\n')
+ dhdinfo->fw_path[fw_len-1] = '\0';
+ }
+ if (nv && nv[0] != '\0') {
+ nv_len = strlen(nv);
+ if (nv_len >= sizeof(dhdinfo->nv_path)) {
+ DHD_ERROR(("nvram path len exceeds max len of dhdinfo->nv_path\n"));
+ return FALSE;
+ }
+ strncpy(dhdinfo->nv_path, nv, sizeof(dhdinfo->nv_path));
+ if (dhdinfo->nv_path[nv_len-1] == '\n')
+ dhdinfo->nv_path[nv_len-1] = '\0';
+ }
+
+ /* clear the path in module parameter */
+ firmware_path[0] = '\0';
+ nvram_path[0] = '\0';
+
+ if (dhdinfo->fw_path[0] == '\0') {
+ DHD_ERROR(("firmware path not found\n"));
+ return FALSE;
+ }
+ if (dhdinfo->nv_path[0] == '\0') {
+ DHD_ERROR(("nvram path not found\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+int
+dhd_bus_start(dhd_pub_t *dhdp)
+{
+ int ret = -1;
+ dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
+ unsigned long flags;
+
+ ASSERT(dhd);
+
+ DHD_TRACE(("Enter %s:\n", __FUNCTION__));
+
+ /* try to download image and nvram to the dongle */
+ if (dhd->pub.busstate == DHD_BUS_DOWN && dhd_update_fw_nv_path(dhd)) {
+ DHD_INFO(("%s download fw %s, nv %s\n", __FUNCTION__, dhd->fw_path, dhd->nv_path));
+ ret = dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
+ dhd->fw_path, dhd->nv_path);
+ if (ret < 0) {
+ DHD_ERROR(("%s: failed to download firmware %s\n",
+ __FUNCTION__, dhd->fw_path));
+ return ret;
+ }
+ }
+ if (dhd->pub.busstate != DHD_BUS_LOAD) {
+ return -ENETDOWN;
+ }
+
+ dhd_os_sdlock(dhdp);
+
+ /* Start the watchdog timer */
+ dhd->pub.tickcnt = 0;
+ dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
+
+ /* Bring up the bus */
+ if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) {
+
+ DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret));
+ dhd_os_sdunlock(dhdp);
+ return ret;
+ }
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(dhd->pub.oob_disable)) {
+ /* Host registration for OOB interrupt */
+ if (dhd_bus_oob_intr_register(dhdp)) {
+ /* deactivate timer and wait for the handler to finish */
+
+ flags = dhd_os_spin_lock(&dhd->pub);
+ dhd->wd_timer_valid = FALSE;
+ dhd_os_spin_unlock(&dhd->pub, flags);
+ del_timer_sync(&dhd->timer);
+
+ DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__));
+ dhd_os_sdunlock(dhdp);
+ DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
+ return -ENODEV;
+ }
+
+ /* Enable oob at firmware */
+ dhd_enable_oob_intr(dhd->pub.bus, TRUE);
+ }
+#endif
+
+ /* If bus is not ready, can't come up */
+ if (dhd->pub.busstate != DHD_BUS_DATA) {
+ flags = dhd_os_spin_lock(&dhd->pub);
+ dhd->wd_timer_valid = FALSE;
+ dhd_os_spin_unlock(&dhd->pub, flags);
+ del_timer_sync(&dhd->timer);
+ DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__));
+ dhd_os_sdunlock(dhdp);
+ DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
+ return -ENODEV;
+ }
+
+ dhd_os_sdunlock(dhdp);
+
+ dhd_process_cid_mac(dhdp, TRUE);
+
+ /* Bus is ready, do any protocol initialization */
+ if ((ret = dhd_prot_init(&dhd->pub)) < 0)
+ return ret;
+
+ dhd_process_cid_mac(dhdp, FALSE);
+
+#ifdef ARP_OFFLOAD_SUPPORT
+ if (dhd->pend_ipaddr) {
+#ifdef AOE_IP_ALIAS_SUPPORT
+ aoe_update_host_ipv4_table(&dhd->pub, dhd->pend_ipaddr, TRUE, 0);
+#endif /* AOE_IP_ALIAS_SUPPORT */
+ dhd->pend_ipaddr = 0;
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+ return 0;
+}
+#ifdef WLTDLS
+int _dhd_tdls_enable(dhd_pub_t *dhd, bool tdls_on, bool auto_on, struct ether_addr *mac)
+{
+ char iovbuf[WLC_IOCTL_SMLEN];
+ uint32 tdls = tdls_on;
+ int ret = 0;
+ uint32 tdls_auto_op = 0;
+ uint32 tdls_idle_time = CUSTOM_TDLS_IDLE_MODE_SETTING;
+ int32 tdls_rssi_high = CUSTOM_TDLS_RSSI_THRESHOLD_HIGH;
+ int32 tdls_rssi_low = CUSTOM_TDLS_RSSI_THRESHOLD_LOW;
+ BCM_REFERENCE(mac);
+ if (!FW_SUPPORTED(dhd, tdls))
+ return BCME_ERROR;
+
+ if (dhd->tdls_enable == tdls_on)
+ goto auto_mode;
+ bcm_mkiovar("tdls_enable", (char *)&tdls, sizeof(tdls), iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s: tdls %d failed %d\n", __FUNCTION__, tdls, ret));
+ goto exit;
+ }
+ dhd->tdls_enable = tdls_on;
+auto_mode:
+
+ tdls_auto_op = auto_on;
+ bcm_mkiovar("tdls_auto_op", (char *)&tdls_auto_op, sizeof(tdls_auto_op),
+ iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s: tdls_auto_op failed %d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+
+ if (tdls_auto_op) {
+ bcm_mkiovar("tdls_idle_time", (char *)&tdls_idle_time,
+ sizeof(tdls_idle_time), iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s: tdls_idle_time failed %d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+ bcm_mkiovar("tdls_rssi_high", (char *)&tdls_rssi_high, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s: tdls_rssi_high failed %d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+ bcm_mkiovar("tdls_rssi_low", (char *)&tdls_rssi_low, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s: tdls_rssi_low failed %d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+ }
+
+exit:
+ return ret;
+}
+int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+ if (dhd)
+ ret = _dhd_tdls_enable(&dhd->pub, tdls_on, auto_on, mac);
+ else
+ ret = BCME_ERROR;
+ return ret;
+}
+#endif
+
+bool dhd_is_concurrent_mode(dhd_pub_t *dhd)
+{
+ if (!dhd)
+ return FALSE;
+
+ if (dhd->op_mode & DHD_FLAG_CONCURR_MULTI_CHAN_MODE)
+ return TRUE;
+ else if ((dhd->op_mode & DHD_FLAG_CONCURR_SINGLE_CHAN_MODE) ==
+ DHD_FLAG_CONCURR_SINGLE_CHAN_MODE)
+ return TRUE;
+ else
+ return FALSE;
+}
+#if !defined(AP) && defined(WLP2P)
+/* From Android JerryBean release, the concurrent mode is enabled by default and the firmware
+ * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA
+ * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware
+ * would still be named as fw_bcmdhd_apsta.
+ */
+uint32
+dhd_get_concurrent_capabilites(dhd_pub_t *dhd)
+{
+ int32 ret = 0;
+ char buf[WLC_IOCTL_SMLEN];
+ bool mchan_supported = FALSE;
+ /* if dhd->op_mode is already set for HOSTAP and Manufacturing
+ * test mode, that means we only will use the mode as it is
+ */
+ if (dhd->op_mode & (DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))
+ return 0;
+ if (FW_SUPPORTED(dhd, vsdb)) {
+ mchan_supported = TRUE;
+ }
+ if (!FW_SUPPORTED(dhd, p2p)) {
+ DHD_TRACE(("Chip does not support p2p\n"));
+ return 0;
+ }
+ else {
+ /* Chip supports p2p but ensure that p2p is really implemented in firmware or not */
+ memset(buf, 0, sizeof(buf));
+ bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
+ FALSE, 0)) < 0) {
+ DHD_ERROR(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret));
+ return 0;
+ }
+ else {
+ if (buf[0] == 1) {
+ /* By default, chip supports single chan concurrency,
+ * now lets check for mchan
+ */
+ ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE;
+ if (mchan_supported)
+ ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE;
+#if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
+ /* For customer_hw4, although ICS,
+ * we still support concurrent mode
+ */
+ return ret;
+#else
+ return 0;
+#endif
+ }
+ }
+ }
+ return 0;
+}
+#endif
+
+
+int
+dhd_preinit_ioctls(dhd_pub_t *dhd)
+{
+ int ret = 0;
+ char eventmask[WL_EVENTING_MASK_LEN];
+ char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
+ uint8 msglen;
+ eventmsgs_ext_t *eventmask_msg;
+ char iov_buf[WLC_IOCTL_SMLEN];
+ uint32 buf_key_b4_m4 = 1;
+ int ret2 = 0;
+#if defined(CUSTOM_AMPDU_BA_WSIZE)
+ uint32 ampdu_ba_wsize = 0;
+#endif
+#if defined(CUSTOM_AMPDU_MPDU)
+ uint32 ampdu_mpdu = 0;
+#endif
+
+#ifdef PROP_TXSTATUS
+ int wlfc_enable = TRUE;
+#ifndef DISABLE_11N
+ uint32 hostreorder = 1;
+#endif /* DISABLE_11N */
+#endif /* PROP_TXSTATUS */
+
+#ifdef DHD_ENABLE_LPC
+ uint32 lpc = 1;
+#endif /* DHD_ENABLE_LPC */
+ uint power_mode = PM_FAST;
+ uint32 dongle_align = DHD_SDALIGN;
+ uint32 glom = CUSTOM_GLOM_SETTING;
+#if defined(CUSTOMER_HW2) && defined(USE_WL_CREDALL)
+ uint32 credall = 1;
+#endif
+#if defined(VSDB) || defined(ROAM_ENABLE)
+ uint bcn_timeout = 8;
+#else
+ uint bcn_timeout = 4;
+#endif
+ uint retry_max = 7;
+#if defined(ARP_OFFLOAD_SUPPORT)
+ int arpoe = 1;
+#endif
+ int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME;
+ int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME;
+ int scan_passive_time = DHD_SCAN_PASSIVE_TIME;
+ char buf[WLC_IOCTL_SMLEN];
+ char *ptr;
+ uint32 listen_interval = CUSTOM_LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
+#ifdef ROAM_ENABLE
+ uint roamvar = 0;
+ int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL};
+ int roam_scan_period[2] = {10, WLC_BAND_ALL};
+ int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL};
+#ifdef ROAM_AP_ENV_DETECTION
+ int roam_env_mode = AP_ENV_INDETERMINATE;
+#endif /* ROAM_AP_ENV_DETECTION */
+#ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC
+ int roam_fullscan_period = 60;
+#else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
+ int roam_fullscan_period = 120;
+#endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
+#else
+#ifdef DISABLE_BUILTIN_ROAM
+ uint roamvar = 1;
+#endif /* DISABLE_BUILTIN_ROAM */
+#endif /* ROAM_ENABLE */
+
+#if defined(SOFTAP)
+ uint dtim = 1;
+#endif
+#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211))
+ uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */
+ struct ether_addr p2p_ea;
+#endif
+
+#if defined(AP) || defined(WLP2P)
+ uint32 apsta = 1; /* Enable APSTA mode */
+#endif /* defined(AP) || defined(WLP2P) */
+#ifdef GET_CUSTOM_MAC_ENABLE
+ struct ether_addr ea_addr;
+#endif /* GET_CUSTOM_MAC_ENABLE */
+
+#ifdef DISABLE_11N
+ uint32 nmode = 0;
+#endif /* DISABLE_11N */
+
+#ifdef USE_WL_TXBF
+ uint32 txbf = 1;
+#endif /* USE_WL_TXBF */
+#ifdef USE_WL_FRAMEBURST
+ uint32 frameburst = 1;
+#endif /* USE_WL_FRAMEBURST */
+#ifdef CUSTOM_PSPRETEND_THR
+ uint32 pspretend_thr = CUSTOM_PSPRETEND_THR;
+#endif
+#ifdef DISABLE_AUTOCOUNTRY
+ uint32 autocountry = 0;
+#endif /* DISABLE_AUTOCOUNTRY */
+
+#ifdef PKT_FILTER_SUPPORT
+ dhd_pkt_filter_enable = TRUE;
+#endif /* PKT_FILTER_SUPPORT */
+#ifdef WLTDLS
+ dhd->tdls_enable = FALSE;
+#endif /* WLTDLS */
+ dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM;
+ DHD_TRACE(("Enter %s\n", __FUNCTION__));
+ dhd->op_mode = 0;
+ if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) ||
+ (op_mode == DHD_FLAG_MFG_MODE)) {
+ /* Check and adjust IOCTL response timeout for Manufactring firmware */
+ dhd_os_set_ioctl_resp_timeout(MFG_IOCTL_RESP_TIMEOUT);
+ DHD_ERROR(("%s : Set IOCTL response time for Manufactring Firmware\n",
+ __FUNCTION__));
+ }
+ else {
+ dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT);
+ DHD_INFO(("%s : Set IOCTL response time.\n", __FUNCTION__));
+ }
+#ifdef GET_CUSTOM_MAC_ENABLE
+ ret = wifi_platform_get_mac_addr(dhd->info->adapter, ea_addr.octet);
+ if (!ret) {
+ memset(buf, 0, sizeof(buf));
+ bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
+ if (ret < 0) {
+ DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+ return BCME_NOTUP;
+ }
+ memcpy(dhd->mac.octet, ea_addr.octet, ETHER_ADDR_LEN);
+ } else {
+#endif /* GET_CUSTOM_MAC_ENABLE */
+ /* Get the default device MAC address directly from firmware */
+ memset(buf, 0, sizeof(buf));
+ bcm_mkiovar("cur_etheraddr", 0, 0, buf, sizeof(buf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
+ FALSE, 0)) < 0) {
+ DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
+ return BCME_NOTUP;
+ }
+ /* Update public MAC address after reading from Firmware */
+ memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+ }
+#endif /* GET_CUSTOM_MAC_ENABLE */
+ /* get a capabilities from firmware */
+ memset(dhd->fw_capabilities, 0, sizeof(dhd->fw_capabilities));
+ bcm_mkiovar("cap", 0, 0, dhd->fw_capabilities, sizeof(dhd->fw_capabilities));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, dhd->fw_capabilities,
+ sizeof(dhd->fw_capabilities), FALSE, 0)) < 0) {
+ DHD_ERROR(("%s: Get Capability failed (error=%d)\n",
+ __FUNCTION__, ret));
+ return 0;
+ }
+ if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) ||
+ (op_mode == DHD_FLAG_HOSTAP_MODE)) {
+#ifdef SET_RANDOM_MAC_SOFTAP
+ uint rand_mac;
+#endif
+ dhd->op_mode = DHD_FLAG_HOSTAP_MODE;
+#if defined(ARP_OFFLOAD_SUPPORT)
+ arpoe = 0;
+#endif
+#ifdef PKT_FILTER_SUPPORT
+ dhd_pkt_filter_enable = FALSE;
+#endif
+#ifdef SET_RANDOM_MAC_SOFTAP
+ SRANDOM32((uint)jiffies);
+ rand_mac = RANDOM32();
+ iovbuf[0] = 0x02; /* locally administered bit */
+ iovbuf[1] = 0x1A;
+ iovbuf[2] = 0x11;
+ iovbuf[3] = (unsigned char)(rand_mac & 0x0F) | 0xF0;
+ iovbuf[4] = (unsigned char)(rand_mac >> 8);
+ iovbuf[5] = (unsigned char)(rand_mac >> 16);
+
+ bcm_mkiovar("cur_etheraddr", (void *)iovbuf, ETHER_ADDR_LEN, buf, sizeof(buf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
+ if (ret < 0) {
+ DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+ } else
+ memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
+#endif /* SET_RANDOM_MAC_SOFTAP */
+#if !defined(AP) && defined(WL_CFG80211)
+ /* Turn off MPC in AP mode */
+ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret));
+ }
+#endif
+ } else if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) ||
+ (op_mode == DHD_FLAG_MFG_MODE)) {
+#if defined(ARP_OFFLOAD_SUPPORT)
+ arpoe = 0;
+#endif /* ARP_OFFLOAD_SUPPORT */
+#ifdef PKT_FILTER_SUPPORT
+ dhd_pkt_filter_enable = FALSE;
+#endif /* PKT_FILTER_SUPPORT */
+ dhd->op_mode = DHD_FLAG_MFG_MODE;
+ } else {
+ uint32 concurrent_mode = 0;
+ if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_P2P_MODE) ||
+ (op_mode == DHD_FLAG_P2P_MODE)) {
+#if defined(ARP_OFFLOAD_SUPPORT)
+ arpoe = 0;
+#endif
+#ifdef PKT_FILTER_SUPPORT
+ dhd_pkt_filter_enable = FALSE;
+#endif
+ dhd->op_mode = DHD_FLAG_P2P_MODE;
+ } else if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_IBSS_MODE) ||
+ (op_mode == DHD_FLAG_IBSS_MODE)) {
+ dhd->op_mode = DHD_FLAG_IBSS_MODE;
+ } else
+ dhd->op_mode = DHD_FLAG_STA_MODE;
+#if !defined(AP) && defined(WLP2P)
+ if (dhd->op_mode != DHD_FLAG_IBSS_MODE &&
+ (concurrent_mode = dhd_get_concurrent_capabilites(dhd))) {
+#if defined(ARP_OFFLOAD_SUPPORT)
+ arpoe = 1;
+#endif
+ dhd->op_mode |= concurrent_mode;
+ }
+
+ /* Check if we are enabling p2p */
+ if (dhd->op_mode & DHD_FLAG_P2P_MODE) {
+ bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
+ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s APSTA for P2P failed ret= %d\n", __FUNCTION__, ret));
+ }
+
+ memcpy(&p2p_ea, &dhd->mac, ETHER_ADDR_LEN);
+ ETHER_SET_LOCALADDR(&p2p_ea);
+ bcm_mkiovar("p2p_da_override", (char *)&p2p_ea,
+ ETHER_ADDR_LEN, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
+ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s p2p_da_override ret= %d\n", __FUNCTION__, ret));
+ } else {
+ DHD_INFO(("dhd_preinit_ioctls: p2p_da_override succeeded\n"));
+ }
+ }
+#else
+ (void)concurrent_mode;
+#endif
+ }
+
+ DHD_ERROR(("Firmware up: op_mode=0x%04x, MAC="MACDBG"\n",
+ dhd->op_mode, MAC2STRDBG(dhd->mac.octet)));
+ /* Set Country code */
+ if (dhd->dhd_cspec.ccode[0] != 0) {
+ bcm_mkiovar("country", (char *)&dhd->dhd_cspec,
+ sizeof(wl_country_t), iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
+ }
+
+#if defined(DISABLE_AUTOCOUNTRY)
+ /* disable setting country to AP's country */
+ bcm_mkiovar("autocountry", (char *)&autocountry, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("%s disabling autocountry failed %d\n", __FUNCTION__, ret));
+#endif /* DISABLE_AUTOCOUNTRY */
+
+
+ /* Set Listen Interval */
+ bcm_mkiovar("assoc_listen", (char *)&listen_interval, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("%s assoc_listen failed %d\n", __FUNCTION__, ret));
+
+#if defined(ROAM_ENABLE) || defined(DISABLE_BUILTIN_ROAM)
+ /* Disable built-in roaming to allowed ext supplicant to take care of roaming */
+ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */
+#if defined(ROAM_ENABLE)
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger,
+ sizeof(roam_trigger), TRUE, 0)) < 0)
+ DHD_ERROR(("%s: roam trigger set failed %d\n", __FUNCTION__, ret));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, roam_scan_period,
+ sizeof(roam_scan_period), TRUE, 0)) < 0)
+ DHD_ERROR(("%s: roam scan period set failed %d\n", __FUNCTION__, ret));
+ if ((dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta,
+ sizeof(roam_delta), TRUE, 0)) < 0)
+ DHD_ERROR(("%s: roam delta set failed %d\n", __FUNCTION__, ret));
+ bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("%s: roam fullscan period set failed %d\n", __FUNCTION__, ret));
+#ifdef ROAM_AP_ENV_DETECTION
+ if (roam_trigger[0] == WL_AUTO_ROAM_TRIGGER) {
+ bcm_mkiovar("roam_env_detection", (char *)&roam_env_mode,
+ 4, iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) == BCME_OK)
+ dhd->roam_env_detection = TRUE;
+ else {
+ dhd->roam_env_detection = FALSE;
+ }
+ }
+#endif /* ROAM_AP_ENV_DETECTION */
+#endif /* ROAM_ENABLE */
+
+#ifdef WLTDLS
+ /* by default TDLS on and auto mode off */
+ _dhd_tdls_enable(dhd, true, false, NULL);
+#endif /* WLTDLS */
+
+#ifdef DHD_ENABLE_LPC
+ /* Set lpc 1 */
+ bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set lpc failed %d\n", __FUNCTION__, ret));
+#if defined(CUSTOM_PLATFORM_NV_TEGRA)
+ if (ret == BCME_NOTDOWN) {
+ uint wl_down = 1;
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN,
+ (char *)&wl_down, sizeof(wl_down), TRUE, 0);
+ DHD_ERROR(("%s lpc fail WL_DOWN : %d, lpc = %d\n", __FUNCTION__, ret, lpc));
+
+ bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ DHD_ERROR(("%s Set lpc ret --> %d\n", __FUNCTION__, ret));
+ }
+#endif
+ }
+#endif /* DHD_ENABLE_LPC */
+
+ /* Set PowerSave mode */
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
+
+ /* Match Host and Dongle rx alignment */
+ bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
+#if defined(CUSTOMER_HW2) && defined(USE_WL_CREDALL)
+ /* enable credall to reduce the chance of no bus credit happened. */
+ bcm_mkiovar("bus:credall", (char *)&credall, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif
+
+ if (glom != DEFAULT_GLOM_VALUE) {
+ DHD_INFO(("%s set glom=0x%X\n", __FUNCTION__, glom));
+ bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ }
+
+ /* Setup timeout if Beacons are lost and roam is off to report link down */
+ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ /* Setup assoc_retry_max count to reconnect target AP in dongle */
+ bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#if defined(AP) && !defined(WLP2P)
+ /* Turn off MPC in AP mode */
+ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif /* defined(AP) && !defined(WLP2P) */
+
+
+
+#if defined(SOFTAP)
+ if (ap_fw_loaded == TRUE) {
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_DTIMPRD, (char *)&dtim, sizeof(dtim), TRUE, 0);
+ }
+#endif
+
+#if defined(KEEP_ALIVE)
+ {
+ /* Set Keep Alive : be sure to use FW with -keepalive */
+ int res;
+
+#if defined(SOFTAP)
+ if (ap_fw_loaded == FALSE)
+#endif
+ if (!(dhd->op_mode &
+ (DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))) {
+ if ((res = dhd_keep_alive_onoff(dhd)) < 0)
+ DHD_ERROR(("%s set keeplive failed %d\n",
+ __FUNCTION__, res));
+ }
+ }
+#endif /* defined(KEEP_ALIVE) */
+#ifdef USE_WL_TXBF
+ bcm_mkiovar("txbf", (char *)&txbf, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set txbf failed %d\n", __FUNCTION__, ret));
+ }
+#endif /* USE_WL_TXBF */
+#ifdef USE_WL_FRAMEBURST
+#ifdef DISABLE_WL_FRAMEBURST_SOFTAP
+ /* Disable Framebursting for SofAP */
+ if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
+ frameburst = 0;
+ }
+#endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
+ /* Set frameburst to value */
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_FAKEFRAG, (char *)&frameburst,
+ sizeof(frameburst), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set frameburst failed %d\n", __FUNCTION__, ret));
+ }
+#endif /* USE_WL_FRAMEBURST */
+#if defined(CUSTOM_AMPDU_BA_WSIZE)
+ /* Set ampdu ba wsize to 64 or 16 */
+#ifdef CUSTOM_AMPDU_BA_WSIZE
+ ampdu_ba_wsize = CUSTOM_AMPDU_BA_WSIZE;
+#endif
+ if (ampdu_ba_wsize != 0) {
+ bcm_mkiovar("ampdu_ba_wsize", (char *)&ampdu_ba_wsize, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set ampdu_ba_wsize to %d failed %d\n",
+ __FUNCTION__, ampdu_ba_wsize, ret));
+ }
+ }
+#endif
+
+
+#if defined(CUSTOM_AMPDU_MPDU)
+ ampdu_mpdu = CUSTOM_AMPDU_MPDU;
+ if (ampdu_mpdu != 0 && (ampdu_mpdu <= ampdu_ba_wsize)) {
+ bcm_mkiovar("ampdu_mpdu", (char *)&ampdu_mpdu, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set ampdu_mpdu to %d failed %d\n",
+ __FUNCTION__, CUSTOM_AMPDU_MPDU, ret));
+ }
+ }
+#endif /* CUSTOM_AMPDU_MPDU */
+
+#ifdef CUSTOM_PSPRETEND_THR
+ /* Turn off MPC in AP mode */
+ bcm_mkiovar("pspretend_threshold", (char *)&pspretend_thr, 4,
+ iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s pspretend_threshold for HostAPD failed %d\n",
+ __FUNCTION__, ret));
+ }
+#endif
+
+ bcm_mkiovar("buf_key_b4_m4", (char *)&buf_key_b4_m4, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s buf_key_b4_m4 set failed %d\n", __FUNCTION__, ret));
+ }
+
+ /* Read event_msgs mask */
+ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
+ DHD_ERROR(("%s read Event mask failed %d\n", __FUNCTION__, ret));
+ goto done;
+ }
+ bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
+
+ /* Setup event_msgs */
+ setbit(eventmask, WLC_E_SET_SSID);
+ setbit(eventmask, WLC_E_PRUNE);
+ setbit(eventmask, WLC_E_AUTH);
+ setbit(eventmask, WLC_E_ASSOC);
+ setbit(eventmask, WLC_E_REASSOC);
+ setbit(eventmask, WLC_E_REASSOC_IND);
+ setbit(eventmask, WLC_E_DEAUTH);
+ setbit(eventmask, WLC_E_DEAUTH_IND);
+ setbit(eventmask, WLC_E_DISASSOC_IND);
+ setbit(eventmask, WLC_E_DISASSOC);
+ setbit(eventmask, WLC_E_JOIN);
+ setbit(eventmask, WLC_E_START);
+ setbit(eventmask, WLC_E_ASSOC_IND);
+ setbit(eventmask, WLC_E_PSK_SUP);
+ setbit(eventmask, WLC_E_LINK);
+ setbit(eventmask, WLC_E_NDIS_LINK);
+ setbit(eventmask, WLC_E_MIC_ERROR);
+ setbit(eventmask, WLC_E_ASSOC_REQ_IE);
+ setbit(eventmask, WLC_E_ASSOC_RESP_IE);
+#ifndef WL_CFG80211
+ setbit(eventmask, WLC_E_PMKID_CACHE);
+ setbit(eventmask, WLC_E_TXFAIL);
+#endif
+ setbit(eventmask, WLC_E_JOIN_START);
+ setbit(eventmask, WLC_E_SCAN_COMPLETE);
+#ifdef DHD_DEBUG
+ setbit(eventmask, WLC_E_SCAN_CONFIRM_IND);
+#endif
+#ifdef WLMEDIA_HTSF
+ setbit(eventmask, WLC_E_HTSFSYNC);
+#endif /* WLMEDIA_HTSF */
+#ifdef PNO_SUPPORT
+ setbit(eventmask, WLC_E_PFN_NET_FOUND);
+ setbit(eventmask, WLC_E_PFN_BEST_BATCHING);
+ setbit(eventmask, WLC_E_PFN_BSSID_NET_FOUND);
+ setbit(eventmask, WLC_E_PFN_BSSID_NET_LOST);
+#endif /* PNO_SUPPORT */
+ /* enable dongle roaming event */
+ setbit(eventmask, WLC_E_ROAM);
+ setbit(eventmask, WLC_E_BSSID);
+#ifdef WLTDLS
+ setbit(eventmask, WLC_E_TDLS_PEER_EVENT);
+#endif /* WLTDLS */
+#ifdef WL_CFG80211
+ setbit(eventmask, WLC_E_ESCAN_RESULT);
+ if (dhd->op_mode & DHD_FLAG_P2P_MODE) {
+ setbit(eventmask, WLC_E_ACTION_FRAME_RX);
+ setbit(eventmask, WLC_E_P2P_DISC_LISTEN_COMPLETE);
+ }
+#endif /* WL_CFG80211 */
+ setbit(eventmask, WLC_E_TRACE);
+ setbit(eventmask, WLC_E_CSA_COMPLETE_IND);
+
+ /* Write updated Event mask */
+ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set Event mask failed %d\n", __FUNCTION__, ret));
+ goto done;
+ }
+
+ /* make up event mask ext message iovar for event larger than 128 */
+ msglen = ROUNDUP(WLC_E_LAST, NBBY)/NBBY + EVENTMSGS_EXT_STRUCT_SIZE;
+ eventmask_msg = (eventmsgs_ext_t*)kmalloc(msglen, GFP_KERNEL);
+ if (eventmask_msg == NULL) {
+ DHD_ERROR(("failed to allocate %d bytes for event_msg_ext\n", msglen));
+ return BCME_NOMEM;
+ }
+ bzero(eventmask_msg, msglen);
+ eventmask_msg->ver = EVENTMSGS_VER;
+ eventmask_msg->len = ROUNDUP(WLC_E_LAST, NBBY)/NBBY;
+
+ /* Read event_msgs_ext mask */
+ bcm_mkiovar("event_msgs_ext", (char *)eventmask_msg, msglen, iov_buf, sizeof(iov_buf));
+ ret2 = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iov_buf, sizeof(iov_buf), FALSE, 0);
+ if (ret2 != BCME_UNSUPPORTED)
+ ret = ret2;
+ if (ret2 == 0) { /* event_msgs_ext must be supported */
+ bcopy(iov_buf, eventmask_msg, msglen);
+
+ /* Enable required event mask */
+ setbit(eventmask_msg->mask, WLC_E_PKT_FILTER);
+
+ /* Write updated Event mask */
+ eventmask_msg->ver = EVENTMSGS_VER;
+ eventmask_msg->command = EVENTMSGS_SET_MASK;
+ eventmask_msg->len = ROUNDUP(WLC_E_LAST, NBBY)/NBBY;
+ bcm_mkiovar("event_msgs_ext", (char *)eventmask_msg,
+ msglen, iov_buf, sizeof(iov_buf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
+ iov_buf, sizeof(iov_buf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s write event mask ext failed %d\n", __FUNCTION__, ret));
+ kfree(eventmask_msg);
+ goto done;
+ }
+ } else if (ret2 < 0 && ret2 != BCME_UNSUPPORTED) {
+ DHD_ERROR(("%s read event mask ext failed %d\n", __FUNCTION__, ret2));
+ kfree(eventmask_msg);
+ goto done;
+ } /* unsupported is ok */
+ kfree(eventmask_msg);
+
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
+ sizeof(scan_assoc_time), TRUE, 0);
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
+ sizeof(scan_unassoc_time), TRUE, 0);
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_PASSIVE_TIME, (char *)&scan_passive_time,
+ sizeof(scan_passive_time), TRUE, 0);
+
+#ifdef ARP_OFFLOAD_SUPPORT
+ /* Set and enable ARP offload feature for STA only */
+#if defined(SOFTAP)
+ if (arpoe && !ap_fw_loaded) {
+#else
+ if (arpoe) {
+#endif
+ dhd_arp_offload_enable(dhd, TRUE);
+ dhd_arp_offload_set(dhd, dhd_arp_mode);
+ } else {
+ dhd_arp_offload_enable(dhd, FALSE);
+ dhd_arp_offload_set(dhd, 0);
+ }
+ dhd_arp_enable = arpoe;
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+#ifdef PKT_FILTER_SUPPORT
+ /* Setup default defintions for pktfilter , enable in suspend */
+ dhd->pktfilter_count = 6;
+ /* Setup filter to allow only unicast */
+ dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0x01 0x00";
+ dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = NULL;
+ dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = NULL;
+ dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL;
+ /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */
+ dhd->pktfilter[DHD_MDNS_FILTER_NUM] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB";
+ /* apply APP pktfilter */
+ dhd->pktfilter[DHD_ARP_FILTER_NUM] = "105 0 0 12 0xFFFF 0x0806";
+
+
+#if defined(SOFTAP)
+ if (ap_fw_loaded) {
+ dhd_enable_packet_filter(0, dhd);
+ }
+#endif /* defined(SOFTAP) */
+ dhd_set_packet_filter(dhd);
+#endif /* PKT_FILTER_SUPPORT */
+#ifdef DISABLE_11N
+ bcm_mkiovar("nmode", (char *)&nmode, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("%s wl nmode 0 failed %d\n", __FUNCTION__, ret));
+#endif /* DISABLE_11N */
+
+
+ /* query for 'ver' to get version info from firmware */
+ memset(buf, 0, sizeof(buf));
+ ptr = buf;
+ bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0)
+ DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
+ else {
+ bcmstrtok(&ptr, "\n", 0);
+ /* Print fw version info */
+ DHD_ERROR(("Firmware version = %s\n", buf));
+ dhd_set_version_info(dhd, buf);
+ }
+
+ dhd_txglom_enable(dhd, TRUE);
+
+#ifdef PROP_TXSTATUS
+ if (disable_proptx ||
+#ifdef PROP_TXSTATUS_VSDB
+ /* enable WLFC only if the firmware is VSDB when it is in STA mode */
+ (dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
+ dhd->op_mode != DHD_FLAG_IBSS_MODE) ||
+#endif /* PROP_TXSTATUS_VSDB */
+ FALSE) {
+ wlfc_enable = FALSE;
+ }
+
+#ifndef DISABLE_11N
+ bcm_mkiovar("ampdu_hostreorder", (char *)&hostreorder, 4, iovbuf, sizeof(iovbuf));
+ if ((ret2 = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s wl ampdu_hostreorder failed %d\n", __FUNCTION__, ret2));
+ if (ret2 != BCME_UNSUPPORTED)
+ ret = ret2;
+#if defined(CUSTOM_PLATFORM_NV_TEGRA)
+ if (ret == BCME_NOTDOWN) {
+ uint wl_down = 1;
+ ret2 = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_down,
+ sizeof(wl_down), TRUE, 0);
+ DHD_ERROR(("%s ampdu_hostreorder fail WL_DOWN : %d, hostreorder :%d\n",
+ __FUNCTION__, ret2, hostreorder));
+
+ bcm_mkiovar("ampdu_hostreorder", (char *)&hostreorder, 4,
+ iovbuf, sizeof(iovbuf));
+ ret2 = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ DHD_ERROR(("%s wl ampdu_hostreorder. ret --> %d\n", __FUNCTION__, ret2));
+ if (ret2 != BCME_UNSUPPORTED)
+ ret = ret2;
+ }
+#endif
+ if (ret2 != BCME_OK)
+ hostreorder = 0;
+ }
+#endif /* DISABLE_11N */
+ if (wlfc_enable)
+ dhd_wlfc_init(dhd);
+#ifndef DISABLE_11N
+ else if (hostreorder)
+ dhd_wlfc_hostreorder_init(dhd);
+#endif /* DISABLE_11N */
+
+#endif /* PROP_TXSTATUS */
+#ifdef PNO_SUPPORT
+ if (!dhd->pno_state) {
+ dhd_pno_init(dhd);
+ }
+#endif
+#ifdef WL11U
+ dhd_interworking_enable(dhd);
+#endif /* WL11U */
+
+done:
+ return ret;
+}
+
+
+int
+dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set)
+{
+ char buf[strlen(name) + 1 + cmd_len];
+ int len = sizeof(buf);
+ wl_ioctl_t ioc;
+ int ret;
+
+ len = bcm_mkiovar(name, cmd_buf, cmd_len, buf, len);
+
+ memset(&ioc, 0, sizeof(ioc));
+
+ ioc.cmd = set? WLC_SET_VAR : WLC_GET_VAR;
+ ioc.buf = buf;
+ ioc.len = len;
+ ioc.set = set;
+
+ ret = dhd_wl_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len);
+ if (!set && ret >= 0)
+ memcpy(cmd_buf, buf, cmd_len);
+
+ return ret;
+}
+
+int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx)
+{
+ struct dhd_info *dhd = dhdp->info;
+ struct net_device *dev = NULL;
+
+ ASSERT(dhd && dhd->iflist[ifidx]);
+ dev = dhd->iflist[ifidx]->net;
+ ASSERT(dev);
+
+ if (netif_running(dev)) {
+ DHD_ERROR(("%s: Must be down to change its MTU", dev->name));
+ return BCME_NOTDOWN;
+ }
+
+#define DHD_MIN_MTU 1500
+#define DHD_MAX_MTU 1752
+
+ if ((new_mtu < DHD_MIN_MTU) || (new_mtu > DHD_MAX_MTU)) {
+ DHD_ERROR(("%s: MTU size %d is invalid.\n", __FUNCTION__, new_mtu));
+ return BCME_BADARG;
+ }
+
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+#ifdef ARP_OFFLOAD_SUPPORT
+/* add or remove AOE host ip(s) (up to 8 IPs on the interface) */
+void
+aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx)
+{
+ u32 ipv4_buf[MAX_IPV4_ENTRIES]; /* temp save for AOE host_ip table */
+ int i;
+ int ret;
+
+ bzero(ipv4_buf, sizeof(ipv4_buf));
+
+ /* display what we've got */
+ ret = dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx);
+ DHD_ARPOE(("%s: hostip table read from Dongle:\n", __FUNCTION__));
+#ifdef AOE_DBG
+ dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */
+#endif
+ /* now we saved hoste_ip table, clr it in the dongle AOE */
+ dhd_aoe_hostip_clr(dhd_pub, idx);
+
+ if (ret) {
+ DHD_ERROR(("%s failed\n", __FUNCTION__));
+ return;
+ }
+
+ for (i = 0; i < MAX_IPV4_ENTRIES; i++) {
+ if (add && (ipv4_buf[i] == 0)) {
+ ipv4_buf[i] = ipa;
+ add = FALSE; /* added ipa to local table */
+ DHD_ARPOE(("%s: Saved new IP in temp arp_hostip[%d]\n",
+ __FUNCTION__, i));
+ } else if (ipv4_buf[i] == ipa) {
+ ipv4_buf[i] = 0;
+ DHD_ARPOE(("%s: removed IP:%x from temp table %d\n",
+ __FUNCTION__, ipa, i));
+ }
+
+ if (ipv4_buf[i] != 0) {
+ /* add back host_ip entries from our local cache */
+ dhd_arp_offload_add_ip(dhd_pub, ipv4_buf[i], idx);
+ DHD_ARPOE(("%s: added IP:%x to dongle arp_hostip[%d]\n\n",
+ __FUNCTION__, ipv4_buf[i], i));
+ }
+ }
+#ifdef AOE_DBG
+ /* see the resulting hostip table */
+ dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx);
+ DHD_ARPOE(("%s: read back arp_hostip table:\n", __FUNCTION__));
+ dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */
+#endif
+}
+
+/*
+ * Notification mechanism from kernel to our driver. This function is called by the Linux kernel
+ * whenever there is an event related to an IP address.
+ * ptr : kernel provided pointer to IP address that has changed
+ */
+static int dhd_inetaddr_notifier_call(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+{
+ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+
+ dhd_info_t *dhd;
+ dhd_pub_t *dhd_pub;
+ int idx;
+
+ if (!dhd_arp_enable)
+ return NOTIFY_DONE;
+ if (!ifa || !(ifa->ifa_dev->dev))
+ return NOTIFY_DONE;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+ /* Filter notifications meant for non Broadcom devices */
+ if ((ifa->ifa_dev->dev->netdev_ops != &dhd_ops_pri) &&
+ (ifa->ifa_dev->dev->netdev_ops != &dhd_ops_virt)) {
+#if defined(WL_ENABLE_P2P_IF)
+ if (!wl_cfgp2p_is_ifops(ifa->ifa_dev->dev->netdev_ops))
+#endif /* WL_ENABLE_P2P_IF */
+ return NOTIFY_DONE;
+ }
+#endif /* LINUX_VERSION_CODE */
+
+ dhd = *(dhd_info_t **)netdev_priv(ifa->ifa_dev->dev);
+ if (!dhd)
+ return NOTIFY_DONE;
+
+ dhd_pub = &dhd->pub;
+
+#if defined(ARP_OFFLOAD_SUPPORT)
+ if (dhd_pub->arp_version == 1) {
+ idx = 0;
+ }
+ else {
+#else
+ {
+#endif
+ for (idx = 0; idx < DHD_MAX_IFS; idx++) {
+ if (dhd->iflist[idx] && dhd->iflist[idx]->net == ifa->ifa_dev->dev)
+ break;
+ }
+ if (idx < DHD_MAX_IFS)
+ DHD_TRACE(("ifidx : %p %s %d\n", dhd->iflist[idx]->net,
+ dhd->iflist[idx]->name, dhd->iflist[idx]->idx));
+ else {
+ DHD_ERROR(("Cannot find ifidx for(%s) set to 0\n", ifa->ifa_label));
+ idx = 0;
+ }
+ }
+
+ switch (event) {
+ case NETDEV_UP:
+ DHD_ARPOE(("%s: [%s] Up IP: 0x%x\n",
+ __FUNCTION__, ifa->ifa_label, ifa->ifa_address));
+
+ if (dhd->pub.busstate != DHD_BUS_DATA) {
+ DHD_ERROR(("%s: bus not ready, exit\n", __FUNCTION__));
+ if (dhd->pend_ipaddr) {
+ DHD_ERROR(("%s: overwrite pending ipaddr: 0x%x\n",
+ __FUNCTION__, dhd->pend_ipaddr));
+ }
+ dhd->pend_ipaddr = ifa->ifa_address;
+ break;
+ }
+
+#ifdef AOE_IP_ALIAS_SUPPORT
+ DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n",
+ __FUNCTION__));
+ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE, idx);
+#endif /* AOE_IP_ALIAS_SUPPORT */
+ break;
+
+ case NETDEV_DOWN:
+ DHD_ARPOE(("%s: [%s] Down IP: 0x%x\n",
+ __FUNCTION__, ifa->ifa_label, ifa->ifa_address));
+ dhd->pend_ipaddr = 0;
+#ifdef AOE_IP_ALIAS_SUPPORT
+ DHD_ARPOE(("%s:interface is down, AOE clr all for this if\n",
+ __FUNCTION__));
+ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx);
+#else
+ dhd_aoe_hostip_clr(&dhd->pub, idx);
+ dhd_aoe_arp_clr(&dhd->pub, idx);
+#endif /* AOE_IP_ALIAS_SUPPORT */
+ break;
+
+ default:
+ DHD_ARPOE(("%s: do noting for [%s] Event: %lu\n",
+ __func__, ifa->ifa_label, event));
+ break;
+ }
+ return NOTIFY_DONE;
+}
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+/* Neighbor Discovery Offload: defered handler */
+static void
+dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event)
+{
+ struct ipv6_work_info_t *ndo_work = (struct ipv6_work_info_t *)event_data;
+ dhd_pub_t *pub = &((dhd_info_t *)dhd_info)->pub;
+ int ret;
+
+ if (event != DHD_WQ_WORK_IPV6_NDO) {
+ DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
+ return;
+ }
+
+ if (!ndo_work) {
+ DHD_ERROR(("%s: ipv6 work info is not initialized \n", __FUNCTION__));
+ return;
+ }
+
+ if (!pub) {
+ DHD_ERROR(("%s: dhd pub is not initialized \n", __FUNCTION__));
+ return;
+ }
+
+ if (ndo_work->if_idx) {
+ DHD_ERROR(("%s: idx %d \n", __FUNCTION__, ndo_work->if_idx));
+ return;
+ }
+
+ switch (ndo_work->event) {
+ case NETDEV_UP:
+ DHD_TRACE(("%s: Enable NDO and add ipv6 into table \n ", __FUNCTION__));
+ ret = dhd_ndo_enable(pub, TRUE);
+ if (ret < 0) {
+ DHD_ERROR(("%s: Enabling NDO Failed %d\n", __FUNCTION__, ret));
+ }
+
+ ret = dhd_ndo_add_ip(pub, &ndo_work->ipv6_addr[0], ndo_work->if_idx);
+ if (ret < 0) {
+ DHD_ERROR(("%s: Adding host ip for NDO failed %d\n",
+ __FUNCTION__, ret));
+ }
+ break;
+ case NETDEV_DOWN:
+ DHD_TRACE(("%s: clear ipv6 table \n", __FUNCTION__));
+ ret = dhd_ndo_remove_ip(pub, ndo_work->if_idx);
+ if (ret < 0) {
+ DHD_ERROR(("%s: Removing host ip for NDO failed %d\n",
+ __FUNCTION__, ret));
+ goto done;
+ }
+
+ ret = dhd_ndo_enable(pub, FALSE);
+ if (ret < 0) {
+ DHD_ERROR(("%s: disabling NDO Failed %d\n", __FUNCTION__, ret));
+ goto done;
+ }
+ break;
+ default:
+ DHD_ERROR(("%s: unknown notifier event \n", __FUNCTION__));
+ break;
+ }
+done:
+ /* free ndo_work. alloced while scheduling the work */
+ kfree(ndo_work);
+
+ return;
+}
+
+/*
+ * Neighbor Discovery Offload: Called when an interface
+ * is assigned with ipv6 address.
+ * Handles only primary interface
+ */
+static int dhd_inet6addr_notifier_call(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+{
+ dhd_info_t *dhd;
+ dhd_pub_t *dhd_pub;
+ struct inet6_ifaddr *inet6_ifa = ptr;
+ struct in6_addr *ipv6_addr = &inet6_ifa->addr;
+ struct ipv6_work_info_t *ndo_info;
+ int idx = 0; /* REVISIT */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+ /* Filter notifications meant for non Broadcom devices */
+ if (inet6_ifa->idev->dev->netdev_ops != &dhd_ops_pri) {
+ return NOTIFY_DONE;
+ }
+#endif /* LINUX_VERSION_CODE */
+
+ dhd = *(dhd_info_t **)netdev_priv(inet6_ifa->idev->dev);
+ if (!dhd)
+ return NOTIFY_DONE;
+
+ if (dhd->iflist[idx] && dhd->iflist[idx]->net != inet6_ifa->idev->dev)
+ return NOTIFY_DONE;
+ dhd_pub = &dhd->pub;
+ if (!FW_SUPPORTED(dhd_pub, ndoe))
+ return NOTIFY_DONE;
+
+ ndo_info = (struct ipv6_work_info_t *)kzalloc(sizeof(struct ipv6_work_info_t), GFP_ATOMIC);
+ if (!ndo_info) {
+ DHD_ERROR(("%s: ipv6 work alloc failed\n", __FUNCTION__));
+ return NOTIFY_DONE;
+ }
+
+ ndo_info->event = event;
+ ndo_info->if_idx = idx;
+ memcpy(&ndo_info->ipv6_addr[0], ipv6_addr, IPV6_ADDR_LEN);
+
+ /* defer the work to thread as it may block kernel */
+ dhd_deferred_schedule_work((void *)ndo_info, DHD_WQ_WORK_IPV6_NDO,
+ dhd_inet6_work_handler, DHD_WORK_PRIORITY_LOW);
+ return NOTIFY_DONE;
+}
+
+int
+dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
+{
+ dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+ struct net_device *net = NULL;
+ int err = 0;
+ uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 };
+
+ DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
+
+ ASSERT(dhd && dhd->iflist[ifidx]);
+ net = dhd->iflist[ifidx]->net;
+ ASSERT(net);
+
+#ifndef P2PONEINT
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
+ ASSERT(!net->open);
+ net->get_stats = dhd_get_stats;
+ net->do_ioctl = dhd_ioctl_entry;
+ net->hard_start_xmit = dhd_start_xmit;
+ net->set_mac_address = dhd_set_mac_address;
+ net->set_multicast_list = dhd_set_multicast_list;
+ net->open = net->stop = NULL;
+#else
+ ASSERT(!net->netdev_ops);
+ net->netdev_ops = &dhd_ops_virt;
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
+#else
+ net->netdev_ops = &dhd_cfgp2p_ops_virt;
+#endif /* P2PONEINT */
+
+ /* Ok, link into the network layer... */
+ if (ifidx == 0) {
+ /*
+ * device functions for the primary interface only
+ */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
+ net->open = dhd_open;
+ net->stop = dhd_stop;
+#else
+ net->netdev_ops = &dhd_ops_pri;
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
+ if (!ETHER_ISNULLADDR(dhd->pub.mac.octet))
+ memcpy(temp_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN);
+ } else {
+ /*
+ * We have to use the primary MAC for virtual interfaces
+ */
+ memcpy(temp_addr, dhd->iflist[ifidx]->mac_addr, ETHER_ADDR_LEN);
+ /*
+ * Android sets the locally administered bit to indicate that this is a
+ * portable hotspot. This will not work in simultaneous AP/STA mode,
+ * nor with P2P. Need to set the Donlge's MAC address, and then use that.
+ */
+ if (!memcmp(temp_addr, dhd->iflist[0]->mac_addr,
+ ETHER_ADDR_LEN)) {
+ DHD_ERROR(("%s interface [%s]: set locally administered bit in MAC\n",
+ __func__, net->name));
+ temp_addr[0] |= 0x02;
+ }
+ }
+
+ net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+ net->ethtool_ops = &dhd_ethtool_ops;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
+
+#if defined(WL_WIRELESS_EXT)
+#if WIRELESS_EXT < 19
+ net->get_wireless_stats = dhd_get_wireless_stats;
+#endif /* WIRELESS_EXT < 19 */
+#if WIRELESS_EXT > 12
+ net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def;
+#endif /* WIRELESS_EXT > 12 */
+#endif /* defined(WL_WIRELESS_EXT) */
+
+ dhd->pub.rxsz = DBUS_RX_BUFFER_SIZE_DHD(net);
+
+ memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
+
+ if (ifidx == 0)
+ printf("%s\n", dhd_version);
+
+ if (need_rtnl_lock)
+ err = register_netdev(net);
+ else
+ err = register_netdevice(net);
+
+ if (err != 0) {
+ DHD_ERROR(("couldn't register the net device [%s], err %d\n", net->name, err));
+ goto fail;
+ }
+
+
+ printf("Register interface [%s] MAC: "MACDBG"\n\n", net->name,
+ MAC2STRDBG(net->dev_addr));
+
+#if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211)
+ wl_iw_iscan_set_scan_broadcast_prep(net, 1);
+#endif
+
+#if defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ if (ifidx == 0) {
+#ifdef BCMLXSDMMC
+ up(&dhd_registration_sem);
+#endif
+ if (!dhd_download_fw_on_driverload) {
+#ifdef WL_CFG80211
+ wl_terminate_event_handler();
+#endif /* WL_CFG80211 */
+ dhd_net_bus_devreset(net, TRUE);
+ dhd_net_bus_suspend(net);
+ wifi_platform_set_power(dhdp->info->adapter, FALSE, WIFI_TURNOFF_DELAY);
+ }
+ }
+#endif /* OEM_ANDROID && BCMLXSDMMC && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+ return 0;
+
+fail:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+ net->open = NULL;
+#else
+ net->netdev_ops = NULL;
+#endif
+ return err;
+}
+
+void
+dhd_bus_detach(dhd_pub_t *dhdp)
+{
+ dhd_info_t *dhd;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (dhdp) {
+ dhd = (dhd_info_t *)dhdp->info;
+ if (dhd) {
+
+ /*
+ * In case of Android cfg80211 driver, the bus is down in dhd_stop,
+ * calling stop again will cuase SD read/write errors.
+ */
+ if (dhd->pub.busstate != DHD_BUS_DOWN) {
+ /* Stop the protocol module */
+ dhd_prot_stop(&dhd->pub);
+
+ /* Stop the bus module */
+ dhd_bus_stop(dhd->pub.bus, TRUE);
+ }
+
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(dhdp->oob_disable)) {
+ dhd_bus_oob_intr_unregister(dhdp);
+ }
+#endif
+ }
+ }
+}
+
+
+void dhd_detach(dhd_pub_t *dhdp)
+{
+ dhd_info_t *dhd;
+ unsigned long flags;
+ int timer_valid = FALSE;
+
+ if (!dhdp)
+ return;
+
+ dhd = (dhd_info_t *)dhdp->info;
+ if (!dhd)
+ return;
+
+ DHD_TRACE(("%s: Enter state 0x%x\n", __FUNCTION__, dhd->dhd_state));
+
+ dhd->pub.up = 0;
+ if (!(dhd->dhd_state & DHD_ATTACH_STATE_DONE)) {
+ /* Give sufficient time for threads to start running in case
+ * dhd_attach() has failed
+ */
+ OSL_SLEEP(100);
+ }
+
+#ifdef WL_CFG80211
+ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
+ wl_cfg80211_down(NULL);
+ }
+#endif /* WL_CFG80211 */
+
+ if (dhd->dhd_state & DHD_ATTACH_STATE_PROT_ATTACH) {
+ dhd_bus_detach(dhdp);
+
+ if (dhdp->prot)
+ dhd_prot_detach(dhdp);
+ }
+
+#ifdef ARP_OFFLOAD_SUPPORT
+ if (dhd_inetaddr_notifier_registered) {
+ dhd_inetaddr_notifier_registered = FALSE;
+ unregister_inetaddr_notifier(&dhd_inetaddr_notifier);
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+ if (dhd_inet6addr_notifier_registered) {
+ dhd_inet6addr_notifier_registered = FALSE;
+ unregister_inet6addr_notifier(&dhd_inet6addr_notifier);
+ }
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
+ if (dhd->dhd_state & DHD_ATTACH_STATE_EARLYSUSPEND_DONE) {
+ if (dhd->early_suspend.suspend)
+ unregister_early_suspend(&dhd->early_suspend);
+ }
+#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
+
+#if defined(WL_WIRELESS_EXT)
+ if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) {
+ /* Detatch and unlink in the iw */
+ wl_iw_detach();
+ }
+#endif /* defined(WL_WIRELESS_EXT) */
+
+ /* delete all interfaces, start with virtual */
+ if (dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) {
+ int i = 1;
+ dhd_if_t *ifp;
+
+ /* Cleanup virtual interfaces */
+ dhd_net_if_lock_local(dhd);
+ for (i = 1; i < DHD_MAX_IFS; i++) {
+ if (dhd->iflist[i])
+ dhd_remove_if(&dhd->pub, i, TRUE);
+ }
+ dhd_net_if_unlock_local(dhd);
+
+ /* delete primary interface 0 */
+ ifp = dhd->iflist[0];
+ ASSERT(ifp);
+ ASSERT(ifp->net);
+ if (ifp && ifp->net) {
+ /* in unregister_netdev case, the interface gets freed by net->destructor
+ * (which is set to free_netdev)
+ */
+ if (ifp->net->reg_state == NETREG_UNINITIALIZED)
+ free_netdev(ifp->net);
+ else
+ unregister_netdev(ifp->net);
+ ifp->net = NULL;
+ MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
+ dhd->iflist[0] = NULL;
+ }
+ }
+
+ /* Clear the watchdog timer */
+ flags = dhd_os_spin_lock(&dhd->pub);
+ timer_valid = dhd->wd_timer_valid;
+ dhd->wd_timer_valid = FALSE;
+ dhd_os_spin_unlock(&dhd->pub, flags);
+ if (timer_valid)
+ del_timer_sync(&dhd->timer);
+
+ if (dhd->dhd_state & DHD_ATTACH_STATE_THREADS_CREATED) {
+ if (dhd->thr_wdt_ctl.thr_pid >= 0) {
+ PROC_STOP(&dhd->thr_wdt_ctl);
+ }
+
+ if (dhd->rxthread_enabled && dhd->thr_rxf_ctl.thr_pid >= 0) {
+ PROC_STOP(&dhd->thr_rxf_ctl);
+ }
+
+ if (dhd->thr_dpc_ctl.thr_pid >= 0) {
+ PROC_STOP(&dhd->thr_dpc_ctl);
+ } else
+ tasklet_kill(&dhd->tasklet);
+ }
+#ifdef WL_CFG80211
+ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
+ wl_cfg80211_detach(NULL);
+ dhd_monitor_uninit();
+ }
+#endif
+ /* free deferred work queue */
+ dhd_deferred_work_deinit(dhd->dhd_deferred_wq);
+ dhd->dhd_deferred_wq = NULL;
+
+#ifdef SHOW_LOGTRACE
+ if (dhd->event_data.fmts)
+ kfree(dhd->event_data.fmts);
+ if (dhd->event_data.raw_fmts)
+ kfree(dhd->event_data.raw_fmts);
+ if (dhd->event_data.raw_sstr)
+ kfree(dhd->event_data.raw_sstr);
+#endif /* SHOW_LOGTRACE */
+#ifdef PNO_SUPPORT
+ if (dhdp->pno_state)
+ dhd_pno_deinit(dhdp);
+#endif
+#if defined(CONFIG_PM_SLEEP)
+ if (dhd_pm_notifier_registered) {
+ unregister_pm_notifier(&dhd->pm_notifier);
+ dhd_pm_notifier_registered = FALSE;
+ }
+#endif /* CONFIG_PM_SLEEP */
+#ifdef SAR_SUPPORT
+ if (dhd_sar_notifier_registered) {
+ unregister_notifier_by_sar(&dhd->sar_notifier);
+ dhd_sar_notifier_registered = FALSE;
+ }
+#endif
+#ifdef DEBUG_CPU_FREQ
+ if (dhd->new_freq)
+ free_percpu(dhd->new_freq);
+ dhd->new_freq = NULL;
+ cpufreq_unregister_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+ if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) {
+ DHD_TRACE(("wd wakelock count:%d\n", dhd->wakelock_wd_counter));
+#ifdef CONFIG_HAS_WAKELOCK
+ dhd->wakelock_counter = 0;
+ dhd->wakelock_wd_counter = 0;
+ dhd->wakelock_rx_timeout_enable = 0;
+ dhd->wakelock_ctrl_timeout_enable = 0;
+ wake_lock_destroy(&dhd->wl_wifi);
+ wake_lock_destroy(&dhd->wl_rxwake);
+ wake_lock_destroy(&dhd->wl_ctrlwake);
+ wake_lock_destroy(&dhd->wl_wdwake);
+#endif /* CONFIG_HAS_WAKELOCK */
+ }
+
+
+#ifdef DHDTCPACK_SUPPRESS
+ /* This will free all MEM allocated for TCPACK SUPPRESS */
+ dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF);
+#endif /* DHDTCPACK_SUPPRESS */
+}
+
+
+void
+dhd_free(dhd_pub_t *dhdp)
+{
+ dhd_info_t *dhd;
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (dhdp) {
+ int i;
+ for (i = 0; i < ARRAYSIZE(dhdp->reorder_bufs); i++) {
+ if (dhdp->reorder_bufs[i]) {
+ reorder_info_t *ptr;
+ uint32 buf_size = sizeof(struct reorder_info);
+
+ ptr = dhdp->reorder_bufs[i];
+
+ buf_size += ((ptr->max_idx + 1) * sizeof(void*));
+ DHD_REORDER(("free flow id buf %d, maxidx is %d, buf_size %d\n",
+ i, ptr->max_idx, buf_size));
+
+ MFREE(dhdp->osh, dhdp->reorder_bufs[i], buf_size);
+ dhdp->reorder_bufs[i] = NULL;
+ }
+ }
+ dhd = (dhd_info_t *)dhdp->info;
+ /* If pointer is allocated by dhd_os_prealloc then avoid MFREE */
+ if (dhd &&
+ dhd != (dhd_info_t *)dhd_os_prealloc(dhdp, DHD_PREALLOC_DHD_INFO, 0, FALSE))
+ MFREE(dhd->pub.osh, dhd, sizeof(*dhd));
+ dhd = NULL;
+ }
+}
+
+static void __exit
+dhd_module_cleanup(void)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ dhd_bus_unregister();
+
+ wl_android_exit();
+
+ dhd_wifi_platform_unregister_drv();
+}
+
+static int __init
+dhd_module_init(void)
+{
+ int err;
+
+ DHD_ERROR(("%s in\n", __FUNCTION__));
+ err = dhd_wifi_platform_register_drv();
+
+ return err;
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+#if defined(CONFIG_DEFERRED_INITCALLS)
+deferred_module_init(dhd_module_init);
+#elif defined(USE_LATE_INITCALL_SYNC)
+late_initcall_sync(dhd_module_init);
+#else
+late_initcall(dhd_module_init);
+#endif /* USE_LATE_INITCALL_SYNC */
+#else
+module_init(dhd_module_init);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
+
+module_exit(dhd_module_cleanup);
+
+/*
+ * OS specific functions required to implement DHD driver in OS independent way
+ */
+int
+dhd_os_proto_block(dhd_pub_t *pub)
+{
+ dhd_info_t * dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd) {
+ down(&dhd->proto_sem);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+dhd_os_proto_unblock(dhd_pub_t *pub)
+{
+ dhd_info_t * dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd) {
+ up(&dhd->proto_sem);
+ return 1;
+ }
+
+ return 0;
+}
+
+unsigned int
+dhd_os_get_ioctl_resp_timeout(void)
+{
+ return ((unsigned int)dhd_ioctl_timeout_msec);
+}
+
+void
+dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
+{
+ dhd_ioctl_timeout_msec = (int)timeout_msec;
+}
+
+int
+dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending)
+{
+ dhd_info_t * dhd = (dhd_info_t *)(pub->info);
+ int timeout;
+
+ /* Convert timeout in millsecond to jiffies */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec);
+#else
+ timeout = dhd_ioctl_timeout_msec * HZ / 1000;
+#endif
+
+ timeout = wait_event_timeout(dhd->ioctl_resp_wait, (*condition), timeout);
+ return timeout;
+}
+
+int
+dhd_os_ioctl_resp_wake(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+
+ wake_up(&dhd->ioctl_resp_wait);
+ return 0;
+}
+
+void
+dhd_os_wd_timer_extend(void *bus, bool extend)
+{
+ dhd_pub_t *pub = bus;
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+
+ if (extend)
+ dhd_os_wd_timer(bus, WATCHDOG_EXTEND_INTERVAL);
+ else
+ dhd_os_wd_timer(bus, dhd->default_wd_interval);
+}
+
+
+void
+dhd_os_wd_timer(void *bus, uint wdtick)
+{
+ dhd_pub_t *pub = bus;
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ unsigned long flags;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (!dhd) {
+ DHD_ERROR(("%s: dhd NULL\n", __FUNCTION__));
+ return;
+ }
+
+ flags = dhd_os_spin_lock(pub);
+
+ /* don't start the wd until fw is loaded */
+ if (pub->busstate == DHD_BUS_DOWN) {
+ dhd_os_spin_unlock(pub, flags);
+ if (!wdtick)
+ DHD_OS_WD_WAKE_UNLOCK(pub);
+ return;
+ }
+
+ /* Totally stop the timer */
+ if (!wdtick && dhd->wd_timer_valid == TRUE) {
+ dhd->wd_timer_valid = FALSE;
+ dhd_os_spin_unlock(pub, flags);
+ del_timer_sync(&dhd->timer);
+ DHD_OS_WD_WAKE_UNLOCK(pub);
+ return;
+ }
+
+ if (wdtick) {
+ DHD_OS_WD_WAKE_LOCK(pub);
+ dhd_watchdog_ms = (uint)wdtick;
+ /* Re arm the timer, at last watchdog period */
+ mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms));
+ dhd->wd_timer_valid = TRUE;
+ }
+ dhd_os_spin_unlock(pub, flags);
+}
+
+void *
+dhd_os_open_image(char *filename)
+{
+ struct file *fp;
+
+ fp = filp_open(filename, O_RDONLY, 0);
+ /*
+ * 2.6.11 (FC4) supports filp_open() but later revs don't?
+ * Alternative:
+ * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
+ * ???
+ */
+ if (IS_ERR(fp))
+ fp = NULL;
+
+ return fp;
+}
+
+int
+dhd_os_get_image_block(char *buf, int len, void *image)
+{
+ struct file *fp = (struct file *)image;
+ int rdlen;
+
+ if (!image)
+ return 0;
+
+ rdlen = kernel_read(fp, fp->f_pos, buf, len);
+ if (rdlen > 0)
+ fp->f_pos += rdlen;
+
+ return rdlen;
+}
+
+void
+dhd_os_close_image(void *image)
+{
+ if (image)
+ filp_close((struct file *)image, NULL);
+}
+
+void
+dhd_os_sdlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd_dpc_prio >= 0)
+ down(&dhd->sdsem);
+ else
+ spin_lock_bh(&dhd->sdlock);
+}
+
+void
+dhd_os_sdunlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd_dpc_prio >= 0)
+ up(&dhd->sdsem);
+ else
+ spin_unlock_bh(&dhd->sdlock);
+}
+
+void
+dhd_os_sdlock_txq(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_lock_bh(&dhd->txqlock);
+}
+
+void
+dhd_os_sdunlock_txq(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_unlock_bh(&dhd->txqlock);
+}
+
+void
+dhd_os_sdlock_rxq(dhd_pub_t *pub)
+{
+}
+
+void
+dhd_os_sdunlock_rxq(dhd_pub_t *pub)
+{
+}
+
+void
+dhd_os_sdtxlock(dhd_pub_t *pub)
+{
+ dhd_os_sdlock(pub);
+}
+
+void
+dhd_os_sdtxunlock(dhd_pub_t *pub)
+{
+ dhd_os_sdunlock(pub);
+}
+
+static void
+dhd_os_rxflock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_lock_bh(&dhd->rxf_lock);
+
+}
+
+static void
+dhd_os_rxfunlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_unlock_bh(&dhd->rxf_lock);
+}
+
+#ifdef DHDTCPACK_SUPPRESS
+void
+dhd_os_tcpacklock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_lock_bh(&dhd->tcpack_lock);
+
+}
+
+void
+dhd_os_tcpackunlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_unlock_bh(&dhd->tcpack_lock);
+}
+#endif /* DHDTCPACK_SUPPRESS */
+
+uint8* dhd_os_prealloc(dhd_pub_t *dhdpub, int section, uint size, bool kmalloc_if_fail)
+{
+ uint8* buf;
+ gfp_t flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
+
+ if (section > DHD_PREALLOC_SECTION_MAX) {
+ DHD_ERROR(("%s: Invalid Section ID: %d\n", __FUNCTION__, section));
+ return NULL;
+ }
+
+ buf = (uint8*)wifi_platform_prealloc(dhdpub->info->adapter, section, size);
+ if (buf == NULL && kmalloc_if_fail) {
+ if (isset(dhdpub->prealloc_malloc_mask, section)) {
+ DHD_ERROR(("%s: Section %d(size: %d) is already allocated\n",
+ __FUNCTION__, section, size));
+ return NULL;
+ }
+
+ buf = kmalloc(size, flags);
+ if (buf) {
+ DHD_ERROR(("%s: Preallocated memory section %d(size: %d)"
+ "allocated by kmalloc\n", __FUNCTION__,
+ section, size));
+ setbit(dhdpub->prealloc_malloc_mask, section);
+ }
+ }
+
+ return buf;
+}
+
+void dhd_os_prefree(dhd_pub_t *dhdpub, int section, void *addr, uint size)
+{
+ if (section > DHD_PREALLOC_SECTION_MAX) {
+ DHD_ERROR(("%s: Invalid Section ID: %d\n", __FUNCTION__, section));
+ return;
+ }
+
+ if (addr && isset(dhdpub->prealloc_malloc_mask, section)) {
+ DHD_ERROR(("%s: Preallocated memory section %d(size: %d)"
+ "memory is freed by kfree\n", __FUNCTION__,
+ section, size));
+ clrbit(dhdpub->prealloc_malloc_mask, section);
+ kfree(addr);
+ }
+}
+
+#if defined(WL_WIRELESS_EXT)
+struct iw_statistics *
+dhd_get_wireless_stats(struct net_device *dev)
+{
+ int res = 0;
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ if (!dhd->pub.up) {
+ return NULL;
+ }
+
+ res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats);
+
+ if (res == 0)
+ return &dhd->iw.wstats;
+ else
+ return NULL;
+}
+#endif /* defined(WL_WIRELESS_EXT) */
+
+static int
+dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, uint16 pktlen,
+ wl_event_msg_t *event, void **data)
+{
+ int bcmerror = 0;
+ ASSERT(dhd != NULL);
+
+#ifdef SHOW_LOGTRACE
+ bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, event, data, &dhd->event_data);
+#else
+ bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, event, data, NULL);
+#endif /* SHOW_LOGTRACE */
+
+ if (bcmerror != BCME_OK)
+ return (bcmerror);
+
+#if defined(WL_WIRELESS_EXT)
+ if (event->bsscfgidx == 0) {
+ /*
+ * Wireless ext is on primary interface only
+ */
+
+ ASSERT(dhd->iflist[*ifidx] != NULL);
+ ASSERT(dhd->iflist[*ifidx]->net != NULL);
+
+ if (dhd->iflist[*ifidx]->net) {
+ wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
+ }
+ }
+#endif /* defined(WL_WIRELESS_EXT) */
+
+#ifdef WL_CFG80211
+ ASSERT(dhd->iflist[*ifidx] != NULL);
+ ASSERT(dhd->iflist[*ifidx]->net != NULL);
+ if (dhd->iflist[*ifidx]->net)
+ wl_cfg80211_event(dhd->iflist[*ifidx]->net, event, *data);
+#endif /* defined(WL_CFG80211) */
+
+ return (bcmerror);
+}
+
+/* send up locally generated event */
+void
+dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
+{
+ switch (ntoh32(event->event_type)) {
+
+ default:
+ break;
+ }
+}
+
+#ifdef LOG_INTO_TCPDUMP
+void
+dhd_sendup_log(dhd_pub_t *dhdp, void *data, int data_len)
+{
+ struct sk_buff *p, *skb;
+ uint32 pktlen;
+ int len;
+ dhd_if_t *ifp;
+ dhd_info_t *dhd;
+ uchar *skb_data;
+ int ifidx = 0;
+ struct ether_header eth;
+
+ pktlen = sizeof(eth) + data_len;
+ dhd = dhdp->info;
+
+ if ((p = PKTGET(dhdp->osh, pktlen, FALSE))) {
+ ASSERT(ISALIGNED((uintptr)PKTDATA(dhdp->osh, p), sizeof(uint32)));
+
+ bcopy(&dhdp->mac, &eth.ether_dhost, ETHER_ADDR_LEN);
+ bcopy(&dhdp->mac, &eth.ether_shost, ETHER_ADDR_LEN);
+ ETHER_TOGGLE_LOCALADDR(&eth.ether_shost);
+ eth.ether_type = hton16(ETHER_TYPE_BRCM);
+
+ bcopy((void *)&eth, PKTDATA(dhdp->osh, p), sizeof(eth));
+ bcopy(data, PKTDATA(dhdp->osh, p) + sizeof(eth), data_len);
+ skb = PKTTONATIVE(dhdp->osh, p);
+ skb_data = skb->data;
+ len = skb->len;
+
+ ifidx = dhd_ifname2idx(dhd, "wlan0");
+ ifp = dhd->iflist[ifidx];
+ if (ifp == NULL)
+ ifp = dhd->iflist[0];
+
+ ASSERT(ifp);
+ skb->dev = ifp->net;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ skb->data = skb_data;
+ skb->len = len;
+
+ /* Strip header, count, deliver upward */
+ skb_pull(skb, ETH_HLEN);
+
+ /* Send the packet */
+ if (in_interrupt()) {
+ netif_rx(skb);
+ } else {
+ netif_rx_ni(skb);
+ }
+ }
+ else {
+ /* Could not allocate a sk_buf */
+ DHD_ERROR(("%s: unable to alloc sk_buf", __FUNCTION__));
+ }
+}
+#endif /* LOG_INTO_TCPDUMP */
+
+void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+ struct dhd_info *dhdinfo = dhd->info;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ int timeout = msecs_to_jiffies(IOCTL_RESP_TIMEOUT);
+#else
+ int timeout = (IOCTL_RESP_TIMEOUT / 1000) * HZ;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+
+ dhd_os_sdunlock(dhd);
+ wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout);
+ dhd_os_sdlock(dhd);
+#endif
+ return;
+}
+
+void dhd_wait_event_wakeup(dhd_pub_t *dhd)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+ struct dhd_info *dhdinfo = dhd->info;
+ if (waitqueue_active(&dhdinfo->ctrl_wait))
+ wake_up(&dhdinfo->ctrl_wait);
+#endif
+ return;
+}
+
+int
+dhd_net_bus_devreset(struct net_device *dev, uint8 flag)
+{
+ int ret;
+
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ if (flag == TRUE) {
+ /* Issue wl down command before resetting the chip */
+ if (dhd_wl_ioctl_cmd(&dhd->pub, WLC_DOWN, NULL, 0, TRUE, 0) < 0) {
+ DHD_TRACE(("%s: wl down failed\n", __FUNCTION__));
+ }
+#ifdef PROP_TXSTATUS
+ if (dhd->pub.wlfc_enabled)
+ dhd_wlfc_deinit(&dhd->pub);
+#endif /* PROP_TXSTATUS */
+#ifdef PNO_SUPPORT
+ if (dhd->pub.pno_state)
+ dhd_pno_deinit(&dhd->pub);
+#endif
+ }
+
+ if (!flag) {
+ dhd_update_fw_nv_path(dhd);
+ /* update firmware and nvram path to sdio bus */
+ dhd_bus_update_fw_nv_path(dhd->pub.bus,
+ dhd->fw_path, dhd->nv_path);
+ }
+
+ ret = dhd_bus_devreset(&dhd->pub, flag);
+ if (ret) {
+ DHD_ERROR(("%s: dhd_bus_devreset: %d\n", __FUNCTION__, ret));
+ return ret;
+ }
+
+ return ret;
+}
+
+int
+dhd_net_bus_suspend(struct net_device *dev)
+{
+ dhd_info_t *dhdinfo = *(dhd_info_t **)netdev_priv(dev);
+ return dhd_bus_suspend(&dhdinfo->pub);
+}
+
+int
+dhd_net_bus_resume(struct net_device *dev, uint8 stage)
+{
+ dhd_info_t *dhdinfo = *(dhd_info_t **)netdev_priv(dev);
+ return dhd_bus_resume(&dhdinfo->pub, stage);
+}
+
+int net_os_set_suspend_disable(struct net_device *dev, int val)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd) {
+ ret = dhd->pub.suspend_disable_flag;
+ dhd->pub.suspend_disable_flag = val;
+ }
+ return ret;
+}
+
+int net_os_set_suspend(struct net_device *dev, int val, int force)
+{
+ int ret = 0;
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ if (dhd) {
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
+ ret = dhd_set_suspend(val, &dhd->pub);
+#else
+ ret = dhd_suspend_resume_helper(dhd, val, force);
+#endif
+#ifdef WL_CFG80211
+ wl_cfg80211_update_power_mode(dev);
+#endif
+ }
+ return ret;
+}
+
+int net_os_set_suspend_bcn_li_dtim(struct net_device *dev, int val)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ if (dhd)
+ dhd->pub.suspend_bcn_li_dtim = val;
+
+ return 0;
+}
+
+#ifdef PKT_FILTER_SUPPORT
+int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ char *filterp = NULL;
+ int filter_id = 0;
+ int ret = 0;
+
+ if (!dhd || (num == DHD_UNICAST_FILTER_NUM) ||
+ (num == DHD_MDNS_FILTER_NUM))
+ return ret;
+ if (num >= dhd->pub.pktfilter_count)
+ return -EINVAL;
+ switch (num) {
+ case DHD_BROADCAST_FILTER_NUM:
+ filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF";
+ filter_id = 101;
+ break;
+ case DHD_MULTICAST4_FILTER_NUM:
+ filterp = "102 0 0 0 0xFFFFFF 0x01005E";
+ filter_id = 102;
+ break;
+ case DHD_MULTICAST6_FILTER_NUM:
+ filterp = "103 0 0 0 0xFFFF 0x3333";
+ filter_id = 103;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Add filter */
+ if (add_remove) {
+ dhd->pub.pktfilter[num] = filterp;
+ dhd_pktfilter_offload_set(&dhd->pub, dhd->pub.pktfilter[num]);
+ } else { /* Delete filter */
+ if (dhd->pub.pktfilter[num] != NULL) {
+ dhd_pktfilter_offload_delete(&dhd->pub, filter_id);
+ dhd->pub.pktfilter[num] = NULL;
+ }
+ }
+ return ret;
+}
+
+int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val)
+
+{
+ int ret = 0;
+
+ /* Packet filtering is set only if we still in early-suspend and
+ * we need either to turn it ON or turn it OFF
+ * We can always turn it OFF in case of early-suspend, but we turn it
+ * back ON only if suspend_disable_flag was not set
+ */
+ if (dhdp && dhdp->up) {
+ if (dhdp->in_suspend) {
+ if (!val || (val && !dhdp->suspend_disable_flag))
+ dhd_enable_packet_filter(val, dhdp);
+ }
+ }
+ return ret;
+}
+
+/* function to enable/disable packet for Network device */
+int net_os_enable_packet_filter(struct net_device *dev, int val)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ return dhd_os_enable_packet_filter(&dhd->pub, val);
+}
+#endif /* PKT_FILTER_SUPPORT */
+
+int
+dhd_dev_init_ioctl(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret;
+
+ dhd_process_cid_mac(&dhd->pub, TRUE);
+
+ if ((ret = dhd_prot_init(&dhd->pub)) < 0)
+ goto done;
+
+ dhd_process_cid_mac(&dhd->pub, FALSE);
+
+done:
+ return ret;
+}
+
+#ifdef PNO_SUPPORT
+/* Linux wrapper to call common dhd_pno_stop_for_ssid */
+int
+dhd_dev_pno_stop_for_ssid(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ return (dhd_pno_stop_for_ssid(&dhd->pub));
+}
+/* Linux wrapper to call common dhd_pno_set_for_ssid */
+int
+dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
+ uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ return (dhd_pno_set_for_ssid(&dhd->pub, ssids_local, nssid, scan_fr,
+ pno_repeat, pno_freq_expo_max, channel_list, nchan));
+}
+
+/* Linux wrapper to call common dhd_pno_enable */
+int
+dhd_dev_pno_enable(struct net_device *dev, int enable)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ return (dhd_pno_enable(&dhd->pub, enable));
+}
+
+/* Linux wrapper to call common dhd_pno_set_for_hotlist */
+int
+dhd_dev_pno_set_for_hotlist(struct net_device *dev, wl_pfn_bssid_t *p_pfn_bssid,
+ struct dhd_pno_hotlist_params *hotlist_params)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ return (dhd_pno_set_for_hotlist(&dhd->pub, p_pfn_bssid, hotlist_params));
+}
+/* Linux wrapper to call common dhd_dev_pno_stop_for_batch */
+int
+dhd_dev_pno_stop_for_batch(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ return (dhd_pno_stop_for_batch(&dhd->pub));
+}
+/* Linux wrapper to call common dhd_dev_pno_set_for_batch */
+int
+dhd_dev_pno_set_for_batch(struct net_device *dev, struct dhd_pno_batch_params *batch_params)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ return (dhd_pno_set_for_batch(&dhd->pub, batch_params));
+}
+/* Linux wrapper to call common dhd_dev_pno_get_for_batch */
+int
+dhd_dev_pno_get_for_batch(struct net_device *dev, char *buf, int bufsize)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ return (dhd_pno_get_for_batch(&dhd->pub, buf, bufsize, PNO_STATUS_NORMAL));
+}
+#endif /* PNO_SUPPORT */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+static void dhd_hang_process(void *dhd_info, void *event_info, u8 event)
+{
+ dhd_info_t *dhd;
+ struct net_device *dev;
+
+ dhd = (dhd_info_t *)dhd_info;
+ dev = dhd->iflist[0]->net;
+
+ if (dev) {
+ rtnl_lock();
+ dev_close(dev);
+ rtnl_unlock();
+#if defined(WL_WIRELESS_EXT)
+ wl_iw_send_priv_event(dev, "HANG");
+#endif
+#if defined(WL_CFG80211)
+ wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
+#endif
+ }
+}
+
+int dhd_os_send_hang_message(dhd_pub_t *dhdp)
+{
+ int ret = 0;
+ if (dhdp) {
+ if (!dhdp->hang_was_sent) {
+ dhdp->hang_was_sent = 1;
+ dhd_deferred_schedule_work((void *)dhdp, DHD_WQ_WORK_HANG_MSG,
+ dhd_hang_process, DHD_WORK_PRIORITY_HIGH);
+ }
+ }
+ return ret;
+}
+
+int net_os_send_hang_message(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd) {
+ /* Report FW problem when enabled */
+ if (dhd->pub.hang_report) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ ret = dhd_os_send_hang_message(&dhd->pub);
+#else
+ ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
+#endif
+ } else {
+ DHD_ERROR(("%s: FW HANG ignored (for testing purpose) and not sent up\n",
+ __FUNCTION__));
+ /* Enforce bus down to stop any future traffic */
+ dhd->pub.busstate = DHD_BUS_DOWN;
+ }
+ }
+ return ret;
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */
+
+
+int dhd_net_wifi_platform_set_power(struct net_device *dev, bool on, unsigned long delay_msec)
+{
+ dhd_info_t *dhdinfo = *(dhd_info_t **)netdev_priv(dev);
+ return wifi_platform_set_power(dhdinfo->adapter, on, delay_msec);
+}
+
+void dhd_get_customized_country_code(struct net_device *dev, char *country_iso_code,
+ wl_country_t *cspec)
+{
+ dhd_info_t *dhdinfo = *(dhd_info_t **)netdev_priv(dev);
+ get_customized_country_code(dhdinfo->adapter, country_iso_code, cspec);
+}
+void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ if (dhd && dhd->pub.up) {
+ memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t));
+#ifdef WL_CFG80211
+ wl_update_wiphybands(NULL, notify);
+#endif
+ }
+}
+
+void dhd_bus_band_set(struct net_device *dev, uint band)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ if (dhd && dhd->pub.up) {
+#ifdef WL_CFG80211
+ wl_update_wiphybands(NULL, true);
+#endif
+ }
+}
+
+int dhd_net_set_fw_path(struct net_device *dev, char *fw)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ if (!fw || fw[0] == '\0')
+ return -EINVAL;
+
+ strncpy(dhd->fw_path, fw, sizeof(dhd->fw_path) - 1);
+ dhd->fw_path[sizeof(dhd->fw_path)-1] = '\0';
+
+#if defined(SOFTAP)
+ if (strstr(fw, "apsta") != NULL) {
+ DHD_INFO(("GOT APSTA FIRMWARE\n"));
+ ap_fw_loaded = TRUE;
+ } else {
+ DHD_INFO(("GOT STA FIRMWARE\n"));
+ ap_fw_loaded = FALSE;
+ }
+#endif
+ return 0;
+}
+
+void dhd_net_if_lock(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ dhd_net_if_lock_local(dhd);
+}
+
+void dhd_net_if_unlock(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ dhd_net_if_unlock_local(dhd);
+}
+
+static void dhd_net_if_lock_local(dhd_info_t *dhd)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ if (dhd)
+ mutex_lock(&dhd->dhd_net_if_mutex);
+#endif
+}
+
+static void dhd_net_if_unlock_local(dhd_info_t *dhd)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ if (dhd)
+ mutex_unlock(&dhd->dhd_net_if_mutex);
+#endif
+}
+
+static void dhd_suspend_lock(dhd_pub_t *pub)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ if (dhd)
+ mutex_lock(&dhd->dhd_suspend_mutex);
+#endif
+}
+
+static void dhd_suspend_unlock(dhd_pub_t *pub)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ if (dhd)
+ mutex_unlock(&dhd->dhd_suspend_mutex);
+#endif
+}
+
+unsigned long dhd_os_spin_lock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags = 0;
+
+ if (dhd)
+ spin_lock_irqsave(&dhd->dhd_lock, flags);
+
+ return flags;
+}
+
+void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd)
+ spin_unlock_irqrestore(&dhd->dhd_lock, flags);
+}
+
+static int
+dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
+{
+ return (atomic_read(&dhd->pend_8021x_cnt));
+}
+
+#define MAX_WAIT_FOR_8021X_TX 50
+
+int
+dhd_wait_pend8021x(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int timeout = msecs_to_jiffies(10);
+ int ntimes = MAX_WAIT_FOR_8021X_TX;
+ int pend = dhd_get_pend_8021x_cnt(dhd);
+
+ while (ntimes && pend) {
+ if (pend) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(timeout);
+ set_current_state(TASK_RUNNING);
+ ntimes--;
+ }
+ pend = dhd_get_pend_8021x_cnt(dhd);
+ }
+ if (ntimes == 0)
+ {
+ atomic_set(&dhd->pend_8021x_cnt, 0);
+ DHD_ERROR(("%s: TIMEOUT\n", __FUNCTION__));
+ }
+ return pend;
+}
+
+#ifdef DHD_DEBUG
+int
+write_to_file(dhd_pub_t *dhd, uint8 *buf, int size)
+{
+ int ret = 0;
+ struct file *fp;
+ mm_segment_t old_fs;
+ loff_t pos = 0;
+
+ /* change to KERNEL_DS address limit */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ /* open file to write */
+ fp = filp_open("/tmp/mem_dump", O_WRONLY|O_CREAT, 0640);
+ if (!fp) {
+ printf("%s: open file error\n", __FUNCTION__);
+ ret = -1;
+ goto exit;
+ }
+
+ /* Write buf to file */
+ fp->f_op->write(fp, buf, size, &pos);
+
+exit:
+ /* free buf before return */
+ MFREE(dhd->osh, buf, size);
+ /* close file before return */
+ if (fp)
+ filp_close(fp, current->files);
+ /* restore previous address limit */
+ set_fs(old_fs);
+
+ return ret;
+}
+
+static void dhd_join_timeout(ulong data)
+{
+ dhd_info_t *dhd = (dhd_info_t *)data;
+ if (dhd->join_timer_active)
+ DHD_ERROR(("DHD: %s: JOIN TIMEOUT\n",
+ __FUNCTION__));
+}
+
+int dhd_start_join_timer(dhd_pub_t *pub)
+{
+ int ret;
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ DHD_INFO(("DHD: Join Timer Started:%s:\n", __FUNCTION__));
+ if (!dhd->join_timeout_val)
+ dhd->join_timeout_val = DHD_JOIN_MAX_TIME_DEFAULT;
+ init_timer(&dhd->join_timer);
+ dhd->join_timer.data = (ulong)dhd;
+ dhd->join_timer.function = dhd_join_timeout;
+ dhd->join_timer_active = TRUE;
+ ret = mod_timer(&dhd->join_timer, jiffies + msecs_to_jiffies(dhd->join_timeout_val));
+ return ret;
+}
+int dhd_del_join_timer(dhd_pub_t *pub)
+{
+ int ret = BCME_OK;
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ if (dhd->join_timer_active) {
+ ret = del_timer(&dhd->join_timer);
+ DHD_INFO(("DHD: Join Timer Stopped:%s:\n", __FUNCTION__));
+ }
+ return ret;
+}
+int dhd_set_join_timeout(dhd_pub_t *pub, uint32 timeout)
+{
+ int ret = BCME_OK;
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ if (timeout) {
+ dhd->join_timeout_val = timeout;
+ return ret;
+ }
+ DHD_ERROR(("DHD: Join Timer Can not be zero:%s:\n", __FUNCTION__));
+ return BCME_ERROR;
+}
+uint32 dhd_get_join_timeout(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ return dhd->join_timeout_val;
+}
+
+static void dhd_scan_timeout(ulong data)
+{
+ dhd_info_t *dhd = (dhd_info_t *)data;
+ if (dhd->scan_timer_active) {
+ DHD_ERROR(("DHD: %s: SCAN TIMEOUT\n",
+ __FUNCTION__));
+ }
+}
+int dhd_add_scan_timer(dhd_pub_t *pub)
+{
+ int ret;
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ DHD_ERROR(("DHD: Scan Timer Started:%s:\n", __FUNCTION__));
+ if (!dhd->scan_time_count)
+ dhd->scan_time_count = DHD_SCAN_DEF_TIMEOUT;
+ init_timer(&dhd->scan_timer);
+ dhd->scan_timer.data = (ulong)dhd;
+ dhd->scan_timer.function = dhd_scan_timeout;
+ dhd->scan_timer_active = TRUE;
+ ret = mod_timer(&dhd->scan_timer, jiffies + msecs_to_jiffies(dhd->scan_time_count));
+ return ret;
+}
+int dhd_del_scan_timer(dhd_pub_t *pub)
+{
+ int ret = BCME_OK;
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ if (dhd->scan_timer_active) {
+ ret = del_timer(&dhd->scan_timer);
+ DHD_INFO(("DHD: Scan Timer Stopped:%s:\n", __FUNCTION__));
+ }
+ return ret;
+}
+
+int dhd_set_scan_timeout(dhd_pub_t *pub, uint32 timeout)
+{
+ int ret = BCME_OK;
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ if (timeout) {
+ dhd->scan_time_count = timeout;
+ return ret;
+ }
+ DHD_ERROR(("DHD: Scan Timer Can not be zero:%s:\n", __FUNCTION__));
+ return BCME_ERROR;
+}
+uint32 dhd_get_scan_timeout(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ return dhd->scan_time_count;
+}
+#endif /* DHD_DEBUG */
+
+int dhd_os_wake_lock_timeout(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+ int ret = 0;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ ret = dhd->wakelock_rx_timeout_enable > dhd->wakelock_ctrl_timeout_enable ?
+ dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable;
+#ifdef CONFIG_HAS_WAKELOCK
+ if (dhd->wakelock_rx_timeout_enable)
+ wake_lock_timeout(&dhd->wl_rxwake,
+ msecs_to_jiffies(dhd->wakelock_rx_timeout_enable));
+ if (dhd->wakelock_ctrl_timeout_enable)
+ wake_lock_timeout(&dhd->wl_ctrlwake,
+ msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable));
+#endif
+ dhd->wakelock_rx_timeout_enable = 0;
+ dhd->wakelock_ctrl_timeout_enable = 0;
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return ret;
+}
+
+int net_os_wake_lock_timeout(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_lock_timeout(&dhd->pub);
+ return ret;
+}
+
+int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ if (val > dhd->wakelock_rx_timeout_enable)
+ dhd->wakelock_rx_timeout_enable = val;
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return 0;
+}
+
+int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ if (val > dhd->wakelock_ctrl_timeout_enable)
+ dhd->wakelock_ctrl_timeout_enable = val;
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return 0;
+}
+
+int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ dhd->wakelock_ctrl_timeout_enable = 0;
+#ifdef CONFIG_HAS_WAKELOCK
+ if (wake_lock_active(&dhd->wl_ctrlwake))
+ wake_unlock(&dhd->wl_ctrlwake);
+#endif
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return 0;
+}
+
+int net_os_wake_lock_rx_timeout_enable(struct net_device *dev, int val)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_lock_rx_timeout_enable(&dhd->pub, val);
+ return ret;
+}
+
+int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_lock_ctrl_timeout_enable(&dhd->pub, val);
+ return ret;
+}
+
+int dhd_os_wake_lock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+ int ret = 0;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ if (dhd->wakelock_counter == 0 && !dhd->waive_wakelock) {
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_lock(&dhd->wl_wifi);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ dhd_bus_dev_pm_stay_awake(pub);
+#endif
+ }
+ dhd->wakelock_counter++;
+ ret = dhd->wakelock_counter;
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return ret;
+}
+
+int net_os_wake_lock(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_lock(&dhd->pub);
+ return ret;
+}
+
+int dhd_os_wake_unlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+ int ret = 0;
+
+ dhd_os_wake_lock_timeout(pub);
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ if (dhd->wakelock_counter > 0) {
+ dhd->wakelock_counter--;
+ if (dhd->wakelock_counter == 0 && !dhd->waive_wakelock) {
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_unlock(&dhd->wl_wifi);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ dhd_bus_dev_pm_relax(pub);
+#endif
+ }
+ ret = dhd->wakelock_counter;
+ }
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return ret;
+}
+
+int dhd_os_check_wakelock(dhd_pub_t *pub)
+{
+#if defined(CONFIG_HAS_WAKELOCK) || (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ dhd_info_t *dhd;
+
+ if (!pub)
+ return 0;
+ dhd = (dhd_info_t *)(pub->info);
+#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */
+
+#ifdef CONFIG_HAS_WAKELOCK
+ /* Indicate to the SD Host to avoid going to suspend if internal locks are up */
+ if (dhd && (wake_lock_active(&dhd->wl_wifi) ||
+ (wake_lock_active(&dhd->wl_wdwake))))
+ return 1;
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ if (dhd && (dhd->wakelock_counter > 0) && dhd_bus_dev_pm_enabled(pub))
+ return 1;
+#endif
+ return 0;
+}
+int net_os_wake_unlock(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_unlock(&dhd->pub);
+ return ret;
+}
+
+int dhd_os_wd_wake_lock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+ int ret = 0;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ if (dhd->wakelock_wd_counter == 0 && !dhd->waive_wakelock) {
+#ifdef CONFIG_HAS_WAKELOCK
+ /* if wakelock_wd_counter was never used : lock it at once */
+ wake_lock(&dhd->wl_wdwake);
+#endif
+ }
+ dhd->wakelock_wd_counter++;
+ ret = dhd->wakelock_wd_counter;
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return ret;
+}
+
+int dhd_os_wd_wake_unlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+ int ret = 0;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ if (dhd->wakelock_wd_counter > 0) {
+ dhd->wakelock_wd_counter = 0;
+ if (!dhd->waive_wakelock) {
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_unlock(&dhd->wl_wdwake);
+#endif
+ }
+ }
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return ret;
+}
+
+#ifdef PROP_TXSTATUS
+/* waive wakelocks for operations such as IOVARs in suspend function, must be closed
+ * by a paired function call to dhd_wakelock_restore. returns current wakelock counter
+ */
+int dhd_wakelock_waive(dhd_info_t *dhdinfo)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&dhdinfo->wakelock_spinlock, flags);
+ /* dhd_wakelock_waive/dhd_wakelock_restore must be paired */
+ if (dhdinfo->waive_wakelock)
+ goto exit;
+ /* record current lock status */
+ dhdinfo->wakelock_before_waive = dhdinfo->wakelock_counter;
+ dhdinfo->waive_wakelock = TRUE;
+
+exit:
+ ret = dhdinfo->wakelock_wd_counter;
+ spin_unlock_irqrestore(&dhdinfo->wakelock_spinlock, flags);
+ return ret;
+}
+
+int dhd_wakelock_restore(dhd_info_t *dhdinfo)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&dhdinfo->wakelock_spinlock, flags);
+ /* dhd_wakelock_waive/dhd_wakelock_restore must be paired */
+ if (!dhdinfo->waive_wakelock)
+ goto exit;
+
+ dhdinfo->waive_wakelock = FALSE;
+ /* if somebody else acquires wakelock between dhd_wakelock_waive/dhd_wakelock_restore,
+ * we need to make it up by calling wake_lock or pm_stay_awake. or if somebody releases
+ * the lock in between, do the same by calling wake_unlock or pm_relax
+ */
+ if (dhdinfo->wakelock_before_waive == 0 && dhdinfo->wakelock_counter > 0) {
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_lock(&dhdinfo->wl_wifi);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ dhd_bus_dev_pm_stay_awake(&dhdinfo->pub);
+#endif
+ } else if (dhdinfo->wakelock_before_waive > 0 && dhdinfo->wakelock_counter == 0) {
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_unlock(&dhdinfo->wl_wifi);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ dhd_bus_dev_pm_relax(&dhdinfo->pub);
+#endif
+ }
+ dhdinfo->wakelock_before_waive = 0;
+exit:
+ ret = dhdinfo->wakelock_wd_counter;
+ spin_unlock_irqrestore(&dhdinfo->wakelock_spinlock, flags);
+ return ret;
+}
+#endif /* PROP_TXSTATUS */
+
+bool dhd_os_check_if_up(dhd_pub_t *pub)
+{
+ if (!pub)
+ return FALSE;
+ return pub->up;
+}
+
+/* function to collect firmware, chip id and chip version info */
+void dhd_set_version_info(dhd_pub_t *dhdp, char *fw)
+{
+ int i;
+
+ i = snprintf(info_string, sizeof(info_string),
+ " Driver: %s\n Firmware: %s ", EPI_VERSION_STR, fw);
+
+ if (!dhdp)
+ return;
+
+ i = snprintf(&info_string[i], sizeof(info_string) - i,
+ "\n Chip: %x Rev %x Pkg %x", dhd_bus_chip_id(dhdp),
+ dhd_bus_chiprev_id(dhdp), dhd_bus_chippkg_id(dhdp));
+}
+int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd)
+{
+ int ifidx;
+ int ret = 0;
+ dhd_info_t *dhd = NULL;
+
+ if (!net || !netdev_priv(net)) {
+ DHD_ERROR(("%s invalid parameter\n", __FUNCTION__));
+ return -EINVAL;
+ }
+
+ dhd = *(dhd_info_t **)netdev_priv(net);
+ if (!dhd)
+ return -EINVAL;
+
+ ifidx = dhd_net2idx(dhd, net);
+ if (ifidx == DHD_BAD_IF) {
+ DHD_ERROR(("%s bad ifidx\n", __FUNCTION__));
+ return -ENODEV;
+ }
+
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+ ret = dhd_wl_ioctl(&dhd->pub, ifidx, ioc, ioc->buf, ioc->len);
+ dhd_check_hang(net, &dhd->pub, ret);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+
+ return ret;
+}
+
+bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret)
+{
+ struct net_device *net;
+
+ net = dhd_idx2net(dhdp, ifidx);
+ if (!net) {
+ DHD_ERROR(("%s : Invalid index : %d\n", __FUNCTION__, ifidx));
+ return -EINVAL;
+ }
+
+ return dhd_check_hang(net, dhdp, ret);
+}
+
+
+#ifdef PROP_TXSTATUS
+
+void dhd_wlfc_plat_init(void *dhd)
+{
+ return;
+}
+
+void dhd_wlfc_plat_deinit(void *dhd)
+{
+ return;
+}
+
+bool dhd_wlfc_skip_fc(void)
+{
+ return FALSE;
+}
+#endif /* PROP_TXSTATUS */
+
+#ifdef BCMDBGFS
+
+#include <linux/debugfs.h>
+
+extern uint32 dhd_readregl(void *bp, uint32 addr);
+extern uint32 dhd_writeregl(void *bp, uint32 addr, uint32 data);
+
+typedef struct dhd_dbgfs {
+ struct dentry *debugfs_dir;
+ struct dentry *debugfs_mem;
+ dhd_pub_t *dhdp;
+ uint32 size;
+} dhd_dbgfs_t;
+
+dhd_dbgfs_t g_dbgfs;
+
+static int
+dhd_dbg_state_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t
+dhd_dbg_state_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t rval;
+ uint32 tmp;
+ loff_t pos = *ppos;
+ size_t ret;
+
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= g_dbgfs.size || !count)
+ return 0;
+ if (count > g_dbgfs.size - pos)
+ count = g_dbgfs.size - pos;
+
+ /* Basically enforce aligned 4 byte reads. It's up to the user to work out the details */
+ tmp = dhd_readregl(g_dbgfs.dhdp->bus, file->f_pos & (~3));
+
+ ret = copy_to_user(ubuf, &tmp, 4);
+ if (ret == count)
+ return -EFAULT;
+
+ count -= ret;
+ *ppos = pos + count;
+ rval = count;
+
+ return rval;
+}
+
+
+static ssize_t
+dhd_debugfs_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos)
+{
+ loff_t pos = *ppos;
+ size_t ret;
+ uint32 buf;
+
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= g_dbgfs.size || !count)
+ return 0;
+ if (count > g_dbgfs.size - pos)
+ count = g_dbgfs.size - pos;
+
+ ret = copy_from_user(&buf, ubuf, sizeof(uint32));
+ if (ret == count)
+ return -EFAULT;
+
+ /* Basically enforce aligned 4 byte writes. It's up to the user to work out the details */
+ dhd_writeregl(g_dbgfs.dhdp->bus, file->f_pos & (~3), buf);
+
+ return count;
+}
+
+
+loff_t
+dhd_debugfs_lseek(struct file *file, loff_t off, int whence)
+{
+ loff_t pos = -1;
+
+ switch (whence) {
+ case 0:
+ pos = off;
+ break;
+ case 1:
+ pos = file->f_pos + off;
+ break;
+ case 2:
+ pos = g_dbgfs.size - off;
+ }
+ return (pos < 0 || pos > g_dbgfs.size) ? -EINVAL : (file->f_pos = pos);
+}
+
+static const struct file_operations dhd_dbg_state_ops = {
+ .read = dhd_dbg_state_read,
+ .write = dhd_debugfs_write,
+ .open = dhd_dbg_state_open,
+ .llseek = dhd_debugfs_lseek
+};
+
+static void dhd_dbg_create(void)
+{
+ if (g_dbgfs.debugfs_dir) {
+ g_dbgfs.debugfs_mem = debugfs_create_file("mem", 0644, g_dbgfs.debugfs_dir,
+ NULL, &dhd_dbg_state_ops);
+ }
+}
+
+void dhd_dbg_init(dhd_pub_t *dhdp)
+{
+ int err;
+
+ g_dbgfs.dhdp = dhdp;
+ g_dbgfs.size = 0x20000000; /* Allow access to various cores regs */
+
+ g_dbgfs.debugfs_dir = debugfs_create_dir("dhd", 0);
+ if (IS_ERR(g_dbgfs.debugfs_dir)) {
+ err = PTR_ERR(g_dbgfs.debugfs_dir);
+ g_dbgfs.debugfs_dir = NULL;
+ return;
+ }
+
+ dhd_dbg_create();
+
+ return;
+}
+
+void dhd_dbg_remove(void)
+{
+ debugfs_remove(g_dbgfs.debugfs_mem);
+ debugfs_remove(g_dbgfs.debugfs_dir);
+
+ bzero((unsigned char *) &g_dbgfs, sizeof(g_dbgfs));
+
+}
+#endif /* ifdef BCMDBGFS */
+
+#ifdef WLMEDIA_HTSF
+
+static
+void dhd_htsf_addtxts(dhd_pub_t *dhdp, void *pktbuf)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
+ struct sk_buff *skb;
+ uint32 htsf = 0;
+ uint16 dport = 0, oldmagic = 0xACAC;
+ char *p1;
+ htsfts_t ts;
+
+ /* timestamp packet */
+
+ p1 = (char*) PKTDATA(dhdp->osh, pktbuf);
+
+ if (PKTLEN(dhdp->osh, pktbuf) > HTSF_MINLEN) {
+/* memcpy(&proto, p1+26, 4); */
+ memcpy(&dport, p1+40, 2);
+/* proto = ((ntoh32(proto))>> 16) & 0xFF; */
+ dport = ntoh16(dport);
+ }
+
+ /* timestamp only if icmp or udb iperf with port 5555 */
+/* if (proto == 17 && dport == tsport) { */
+ if (dport >= tsport && dport <= tsport + 20) {
+
+ skb = (struct sk_buff *) pktbuf;
+
+ htsf = dhd_get_htsf(dhd, 0);
+ memset(skb->data + 44, 0, 2); /* clear checksum */
+ memcpy(skb->data+82, &oldmagic, 2);
+ memcpy(skb->data+84, &htsf, 4);
+
+ memset(&ts, 0, sizeof(htsfts_t));
+ ts.magic = HTSFMAGIC;
+ ts.prio = PKTPRIO(pktbuf);
+ ts.seqnum = htsf_seqnum++;
+ ts.c10 = get_cycles();
+ ts.t10 = htsf;
+ ts.endmagic = HTSFENDMAGIC;
+
+ memcpy(skb->data + HTSF_HOSTOFFSET, &ts, sizeof(ts));
+ }
+}
+
+static void dhd_dump_htsfhisto(histo_t *his, char *s)
+{
+ int pktcnt = 0, curval = 0, i;
+ for (i = 0; i < (NUMBIN-2); i++) {
+ curval += 500;
+ printf("%d ", his->bin[i]);
+ pktcnt += his->bin[i];
+ }
+ printf(" max: %d TotPkt: %d neg: %d [%s]\n", his->bin[NUMBIN-2], pktcnt,
+ his->bin[NUMBIN-1], s);
+}
+
+static
+void sorttobin(int value, histo_t *histo)
+{
+ int i, binval = 0;
+
+ if (value < 0) {
+ histo->bin[NUMBIN-1]++;
+ return;
+ }
+ if (value > histo->bin[NUMBIN-2]) /* store the max value */
+ histo->bin[NUMBIN-2] = value;
+
+ for (i = 0; i < (NUMBIN-2); i++) {
+ binval += 500; /* 500m s bins */
+ if (value <= binval) {
+ histo->bin[i]++;
+ return;
+ }
+ }
+ histo->bin[NUMBIN-3]++;
+}
+
+static
+void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf)
+{
+ dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+ struct sk_buff *skb;
+ char *p1;
+ uint16 old_magic;
+ int d1, d2, d3, end2end;
+ htsfts_t *htsf_ts;
+ uint32 htsf;
+
+ skb = PKTTONATIVE(dhdp->osh, pktbuf);
+ p1 = (char*)PKTDATA(dhdp->osh, pktbuf);
+
+ if (PKTLEN(osh, pktbuf) > HTSF_MINLEN) {
+ memcpy(&old_magic, p1+78, 2);
+ htsf_ts = (htsfts_t*) (p1 + HTSF_HOSTOFFSET - 4);
+ }
+ else
+ return;
+
+ if (htsf_ts->magic == HTSFMAGIC) {
+ htsf_ts->tE0 = dhd_get_htsf(dhd, 0);
+ htsf_ts->cE0 = get_cycles();
+ }
+
+ if (old_magic == 0xACAC) {
+
+ tspktcnt++;
+ htsf = dhd_get_htsf(dhd, 0);
+ memcpy(skb->data+92, &htsf, sizeof(uint32));
+
+ memcpy(&ts[tsidx].t1, skb->data+80, 16);
+
+ d1 = ts[tsidx].t2 - ts[tsidx].t1;
+ d2 = ts[tsidx].t3 - ts[tsidx].t2;
+ d3 = ts[tsidx].t4 - ts[tsidx].t3;
+ end2end = ts[tsidx].t4 - ts[tsidx].t1;
+
+ sorttobin(d1, &vi_d1);
+ sorttobin(d2, &vi_d2);
+ sorttobin(d3, &vi_d3);
+ sorttobin(end2end, &vi_d4);
+
+ if (end2end > 0 && end2end > maxdelay) {
+ maxdelay = end2end;
+ maxdelaypktno = tspktcnt;
+ memcpy(&maxdelayts, &ts[tsidx], 16);
+ }
+ if (++tsidx >= TSMAX)
+ tsidx = 0;
+ }
+}
+
+uint32 dhd_get_htsf(dhd_info_t *dhd, int ifidx)
+{
+ uint32 htsf = 0, cur_cycle, delta, delta_us;
+ uint32 factor, baseval, baseval2;
+ cycles_t t;
+
+ t = get_cycles();
+ cur_cycle = t;
+
+ if (cur_cycle > dhd->htsf.last_cycle)
+ delta = cur_cycle - dhd->htsf.last_cycle;
+ else {
+ delta = cur_cycle + (0xFFFFFFFF - dhd->htsf.last_cycle);
+ }
+
+ delta = delta >> 4;
+
+ if (dhd->htsf.coef) {
+ /* times ten to get the first digit */
+ factor = (dhd->htsf.coef*10 + dhd->htsf.coefdec1);
+ baseval = (delta*10)/factor;
+ baseval2 = (delta*10)/(factor+1);
+ delta_us = (baseval - (((baseval - baseval2) * dhd->htsf.coefdec2)) / 10);
+ htsf = (delta_us << 4) + dhd->htsf.last_tsf + HTSF_BUS_DELAY;
+ }
+ else {
+ DHD_ERROR(("-------dhd->htsf.coef = 0 -------\n"));
+ }
+
+ return htsf;
+}
+
+static void dhd_dump_latency(void)
+{
+ int i, max = 0;
+ int d1, d2, d3, d4, d5;
+
+ printf("T1 T2 T3 T4 d1 d2 t4-t1 i \n");
+ for (i = 0; i < TSMAX; i++) {
+ d1 = ts[i].t2 - ts[i].t1;
+ d2 = ts[i].t3 - ts[i].t2;
+ d3 = ts[i].t4 - ts[i].t3;
+ d4 = ts[i].t4 - ts[i].t1;
+ d5 = ts[max].t4-ts[max].t1;
+ if (d4 > d5 && d4 > 0) {
+ max = i;
+ }
+ printf("%08X %08X %08X %08X \t%d %d %d %d i=%d\n",
+ ts[i].t1, ts[i].t2, ts[i].t3, ts[i].t4,
+ d1, d2, d3, d4, i);
+ }
+
+ printf("current idx = %d \n", tsidx);
+
+ printf("Highest latency %d pkt no.%d total=%d\n", maxdelay, maxdelaypktno, tspktcnt);
+ printf("%08X %08X %08X %08X \t%d %d %d %d\n",
+ maxdelayts.t1, maxdelayts.t2, maxdelayts.t3, maxdelayts.t4,
+ maxdelayts.t2 - maxdelayts.t1,
+ maxdelayts.t3 - maxdelayts.t2,
+ maxdelayts.t4 - maxdelayts.t3,
+ maxdelayts.t4 - maxdelayts.t1);
+}
+
+
+static int
+dhd_ioctl_htsf_get(dhd_info_t *dhd, int ifidx)
+{
+ wl_ioctl_t ioc;
+ char buf[32];
+ int ret;
+ uint32 s1, s2;
+
+ struct tsf {
+ uint32 low;
+ uint32 high;
+ } tsf_buf;
+
+ memset(&ioc, 0, sizeof(ioc));
+ memset(&tsf_buf, 0, sizeof(tsf_buf));
+
+ ioc.cmd = WLC_GET_VAR;
+ ioc.buf = buf;
+ ioc.len = (uint)sizeof(buf);
+ ioc.set = FALSE;
+
+ strncpy(buf, "tsf", sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ s1 = dhd_get_htsf(dhd, 0);
+ if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) {
+ if (ret == -EIO) {
+ DHD_ERROR(("%s: tsf is not supported by device\n",
+ dhd_ifname(&dhd->pub, ifidx)));
+ return -EOPNOTSUPP;
+ }
+ return ret;
+ }
+ s2 = dhd_get_htsf(dhd, 0);
+
+ memcpy(&tsf_buf, buf, sizeof(tsf_buf));
+ printf(" TSF_h=%04X lo=%08X Calc:htsf=%08X, coef=%d.%d%d delta=%d ",
+ tsf_buf.high, tsf_buf.low, s2, dhd->htsf.coef, dhd->htsf.coefdec1,
+ dhd->htsf.coefdec2, s2-tsf_buf.low);
+ printf("lasttsf=%08X lastcycle=%08X\n", dhd->htsf.last_tsf, dhd->htsf.last_cycle);
+ return 0;
+}
+
+void htsf_update(dhd_info_t *dhd, void *data)
+{
+ static ulong cur_cycle = 0, prev_cycle = 0;
+ uint32 htsf, tsf_delta = 0;
+ uint32 hfactor = 0, cyc_delta, dec1 = 0, dec2, dec3, tmp;
+ ulong b, a;
+ cycles_t t;
+
+ /* cycles_t in inlcude/mips/timex.h */
+
+ t = get_cycles();
+
+ prev_cycle = cur_cycle;
+ cur_cycle = t;
+
+ if (cur_cycle > prev_cycle)
+ cyc_delta = cur_cycle - prev_cycle;
+ else {
+ b = cur_cycle;
+ a = prev_cycle;
+ cyc_delta = cur_cycle + (0xFFFFFFFF - prev_cycle);
+ }
+
+ if (data == NULL)
+ printf(" tsf update ata point er is null \n");
+
+ memcpy(&prev_tsf, &cur_tsf, sizeof(tsf_t));
+ memcpy(&cur_tsf, data, sizeof(tsf_t));
+
+ if (cur_tsf.low == 0) {
+ DHD_INFO((" ---- 0 TSF, do not update, return\n"));
+ return;
+ }
+
+ if (cur_tsf.low > prev_tsf.low)
+ tsf_delta = (cur_tsf.low - prev_tsf.low);
+ else {
+ DHD_INFO((" ---- tsf low is smaller cur_tsf= %08X, prev_tsf=%08X, \n",
+ cur_tsf.low, prev_tsf.low));
+ if (cur_tsf.high > prev_tsf.high) {
+ tsf_delta = cur_tsf.low + (0xFFFFFFFF - prev_tsf.low);
+ DHD_INFO((" ---- Wrap around tsf coutner adjusted TSF=%08X\n", tsf_delta));
+ }
+ else
+ return; /* do not update */
+ }
+
+ if (tsf_delta) {
+ hfactor = cyc_delta / tsf_delta;
+ tmp = (cyc_delta - (hfactor * tsf_delta))*10;
+ dec1 = tmp/tsf_delta;
+ dec2 = ((tmp - dec1*tsf_delta)*10) / tsf_delta;
+ tmp = (tmp - (dec1*tsf_delta))*10;
+ dec3 = ((tmp - dec2*tsf_delta)*10) / tsf_delta;
+
+ if (dec3 > 4) {
+ if (dec2 == 9) {
+ dec2 = 0;
+ if (dec1 == 9) {
+ dec1 = 0;
+ hfactor++;
+ }
+ else {
+ dec1++;
+ }
+ }
+ else
+ dec2++;
+ }
+ }
+
+ if (hfactor) {
+ htsf = ((cyc_delta * 10) / (hfactor*10+dec1)) + prev_tsf.low;
+ dhd->htsf.coef = hfactor;
+ dhd->htsf.last_cycle = cur_cycle;
+ dhd->htsf.last_tsf = cur_tsf.low;
+ dhd->htsf.coefdec1 = dec1;
+ dhd->htsf.coefdec2 = dec2;
+ }
+ else {
+ htsf = prev_tsf.low;
+ }
+}
+
+#endif /* WLMEDIA_HTSF */
+
+#ifdef CUSTOM_SET_CPUCORE
+void dhd_set_cpucore(dhd_pub_t *dhd, int set)
+{
+ int e_dpc = 0, e_rxf = 0, retry_set = 0;
+
+ if (!(dhd->chan_isvht80)) {
+ DHD_ERROR(("%s: chan_status(%d) cpucore!!!\n", __FUNCTION__, dhd->chan_isvht80));
+ return;
+ }
+
+ if (DPC_CPUCORE) {
+ do {
+ if (set == TRUE) {
+ e_dpc = set_cpus_allowed_ptr(dhd->current_dpc,
+ cpumask_of(DPC_CPUCORE));
+ } else {
+ e_dpc = set_cpus_allowed_ptr(dhd->current_dpc,
+ cpumask_of(PRIMARY_CPUCORE));
+ }
+ if (retry_set++ > MAX_RETRY_SET_CPUCORE) {
+ DHD_ERROR(("%s: dpc(%d) invalid cpu!\n", __FUNCTION__, e_dpc));
+ return;
+ }
+ if (e_dpc < 0)
+ OSL_SLEEP(1);
+ } while (e_dpc < 0);
+ }
+ if (RXF_CPUCORE) {
+ do {
+ if (set == TRUE) {
+ e_rxf = set_cpus_allowed_ptr(dhd->current_rxf,
+ cpumask_of(RXF_CPUCORE));
+ } else {
+ e_rxf = set_cpus_allowed_ptr(dhd->current_rxf,
+ cpumask_of(PRIMARY_CPUCORE));
+ }
+ if (retry_set++ > MAX_RETRY_SET_CPUCORE) {
+ DHD_ERROR(("%s: rxf(%d) invalid cpu!\n", __FUNCTION__, e_rxf));
+ return;
+ }
+ if (e_rxf < 0)
+ OSL_SLEEP(1);
+ } while (e_rxf < 0);
+ }
+#ifdef DHD_OF_SUPPORT
+ interrupt_set_cpucore(set, DPC_CPUCORE, PRIMARY_CPUCORE);
+#endif /* DHD_OF_SUPPORT */
+ DHD_TRACE(("%s: set(%d) cpucore success!\n", __FUNCTION__, set));
+
+ return;
+}
+#endif /* CUSTOM_SET_CPUCORE */
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.h b/drivers/net/wireless/bcmdhd/dhd_linux.h
new file mode 100644
index 000000000000..f5df9cb03346
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.h
@@ -0,0 +1,77 @@
+/*
+ * DHD Linux header file (dhd_linux exports for cfg80211 and other components)
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_linux.h 399301 2013-04-29 21:41:52Z $
+ */
+
+/* wifi platform functions for power, interrupt and pre-alloc, either
+ * from Android-like platform device data, or Broadcom wifi platform
+ * device data.
+ *
+ */
+#ifndef __DHD_LINUX_H__
+#define __DHD_LINUX_H__
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+
+#define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */
+
+typedef struct wifi_adapter_info {
+ const char *name;
+ uint irq_num;
+ uint intr_flags;
+ const char *fw_path;
+ const char *nv_path;
+ void *wifi_plat_data; /* wifi ctrl func, for backward compatibility */
+ uint bus_type;
+ uint bus_num;
+ uint slot_num;
+#ifdef OOB_PARAM
+ uint oob_disable;
+#endif /* OOB_PARAM */
+} wifi_adapter_info_t;
+
+typedef struct bcmdhd_wifi_platdata {
+ uint num_adapters;
+ wifi_adapter_info_t *adapters;
+} bcmdhd_wifi_platdata_t;
+
+int dhd_wifi_platform_register_drv(void);
+void dhd_wifi_platform_unregister_drv(void);
+wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_num,
+ uint32 slot_num);
+int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec);
+int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present);
+int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr);
+int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf);
+void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode);
+void* wifi_platform_prealloc(wifi_adapter_info_t *adapter, int section, unsigned long size);
+void* wifi_platform_get_prealloc_func_ptr(wifi_adapter_info_t *adapter);
+
+int dhd_get_fw_mode(struct dhd_info *dhdinfo);
+bool dhd_update_fw_nv_path(struct dhd_info *dhdinfo);
+
+#endif /* __DHD_LINUX_H__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_platdev.c b/drivers/net/wireless/bcmdhd/dhd_linux_platdev.c
new file mode 100644
index 000000000000..4720083af6a2
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_linux_platdev.c
@@ -0,0 +1,821 @@
+/*
+ * Linux platform device for DHD WLAN adapter
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_linux_platdev.c 401742 2013-05-13 15:03:21Z $
+ */
+#include <typedefs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <bcmutils.h>
+#include <linux_osl.h>
+#include <dhd_dbg.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_bus.h>
+#include <dhd_linux.h>
+#include <wl_android.h>
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
+#include <linux/wlan_plat.h>
+#endif
+#ifdef CONFIG_DTS
+#include<linux/regulator/consumer.h>
+#include<linux/of_gpio.h>
+#endif /* CONFIG_DTS */
+
+#if !defined(CONFIG_WIFI_CONTROL_FUNC)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58))
+#define WLAN_PLAT_NODFS_FLAG 0x01
+#endif
+struct wifi_platform_data {
+ int (*set_power)(int val);
+ int (*set_reset)(int val);
+ int (*set_carddetect)(int val);
+ void *(*mem_prealloc)(int section, unsigned long size);
+ int (*get_mac_addr)(unsigned char *buf);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58))
+ void *(*get_country_code)(char *ccode, u32 flags);
+#else
+ void *(*get_country_code)(char *ccode);
+#endif
+};
+#endif /* CONFIG_WIFI_CONTROL_FUNC */
+
+#define WIFI_PLAT_NAME "bcmdhd_wlan"
+#define WIFI_PLAT_NAME2 "bcm4329_wlan"
+#define WIFI_PLAT_EXT "bcmdhd_wifi_platform"
+
+#ifdef CONFIG_DTS
+struct regulator *wifi_regulator = NULL;
+#endif /* CONFIG_DTS */
+
+bool cfg_multichip = FALSE;
+bcmdhd_wifi_platdata_t *dhd_wifi_platdata = NULL;
+static int wifi_plat_dev_probe_ret = 0;
+static bool is_power_on = FALSE;
+#if !defined(CONFIG_DTS)
+#if defined(DHD_OF_SUPPORT)
+static bool dts_enabled = TRUE;
+extern struct resource dhd_wlan_resources;
+extern struct wifi_platform_data dhd_wlan_control;
+#else
+static bool dts_enabled = FALSE;
+struct resource dhd_wlan_resources = {0};
+struct wifi_platform_data dhd_wlan_control = {0};
+#endif /* CONFIG_OF && !defined(CONFIG_ARCH_MSM) */
+#endif /* !defind(CONFIG_DTS) */
+
+static int dhd_wifi_platform_load(void);
+
+extern void* wl_cfg80211_get_dhdp(void);
+
+#ifdef ENABLE_4335BT_WAR
+extern int bcm_bt_lock(int cookie);
+extern void bcm_bt_unlock(int cookie);
+static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24; /* cookie is "WiFi" */
+#endif /* ENABLE_4335BT_WAR */
+
+wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_num, uint32 slot_num)
+{
+ int i;
+
+ if (dhd_wifi_platdata == NULL)
+ return NULL;
+
+ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+ wifi_adapter_info_t *adapter = &dhd_wifi_platdata->adapters[i];
+ if ((adapter->bus_type == -1 || adapter->bus_type == bus_type) &&
+ (adapter->bus_num == -1 || adapter->bus_num == bus_num) &&
+ (adapter->slot_num == -1 || adapter->slot_num == slot_num)) {
+ DHD_TRACE(("found adapter info '%s'\n", adapter->name));
+ return adapter;
+ }
+ }
+ return NULL;
+}
+
+void* wifi_platform_prealloc(wifi_adapter_info_t *adapter, int section, unsigned long size)
+{
+ void *alloc_ptr = NULL;
+ struct wifi_platform_data *plat_data;
+
+ if (!adapter || !adapter->wifi_plat_data)
+ return NULL;
+ plat_data = adapter->wifi_plat_data;
+ if (plat_data->mem_prealloc) {
+ alloc_ptr = plat_data->mem_prealloc(section, size);
+ if (alloc_ptr) {
+ DHD_INFO(("success alloc section %d\n", section));
+ if (size != 0L)
+ bzero(alloc_ptr, size);
+ return alloc_ptr;
+ }
+ }
+
+ DHD_ERROR(("%s: failed to alloc static mem section %d\n", __FUNCTION__, section));
+ return NULL;
+}
+
+void* wifi_platform_get_prealloc_func_ptr(wifi_adapter_info_t *adapter)
+{
+ struct wifi_platform_data *plat_data;
+
+ if (!adapter || !adapter->wifi_plat_data)
+ return NULL;
+ plat_data = adapter->wifi_plat_data;
+ return plat_data->mem_prealloc;
+}
+
+int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr)
+{
+ if (adapter == NULL)
+ return -1;
+ if (irq_flags_ptr)
+ *irq_flags_ptr = adapter->intr_flags;
+ return adapter->irq_num;
+}
+
+int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec)
+{
+ int err = 0;
+#ifdef CONFIG_DTS
+ if (on) {
+ err = regulator_enable(wifi_regulator);
+ is_power_on = TRUE;
+ }
+ else {
+ err = regulator_disable(wifi_regulator);
+ is_power_on = FALSE;
+ }
+ if (err < 0)
+ DHD_ERROR(("%s: regulator enable/disable failed", __FUNCTION__));
+#else
+ struct wifi_platform_data *plat_data;
+
+ if (!adapter || !adapter->wifi_plat_data)
+ return -EINVAL;
+ plat_data = adapter->wifi_plat_data;
+
+ DHD_ERROR(("%s = %d\n", __FUNCTION__, on));
+ if (plat_data->set_power) {
+#ifdef ENABLE_4335BT_WAR
+ if (on) {
+ printk("WiFi: trying to acquire BT lock\n");
+ if (bcm_bt_lock(lock_cookie_wifi) != 0)
+ printk("** WiFi: timeout in acquiring bt lock**\n");
+ printk("%s: btlock acquired\n", __FUNCTION__);
+ }
+ else {
+ /* For a exceptional case, release btlock */
+ bcm_bt_unlock(lock_cookie_wifi);
+ }
+#endif /* ENABLE_4335BT_WAR */
+
+ err = plat_data->set_power(on);
+ }
+
+ if (msec && !err)
+ OSL_SLEEP(msec);
+
+ if (on && !err)
+ is_power_on = TRUE;
+ else
+ is_power_on = FALSE;
+
+#endif /* CONFIG_DTS */
+
+ return err;
+}
+#if defined(CUSTOMER_IMX)
+
+extern void wifi_card_detect(bool);
+int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present)
+{
+ int err = 0;
+ struct wifi_platform_data *plat_data;
+
+ if (!adapter) {
+ pr_err("!!!! %s: failed! adapter variable is NULL!!!!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ DHD_ERROR(("%s device present %d\n", __FUNCTION__, device_present));
+
+ if (!adapter->wifi_plat_data) {
+ wifi_card_detect(device_present); /* hook for card_detect */
+ } else {
+ plat_data = adapter->wifi_plat_data;
+ if (plat_data->set_carddetect)
+ err = plat_data->set_carddetect(device_present);
+ }
+
+ return 0; /* force success status returned */
+}
+
+#else
+int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present)
+{
+ int err = 0;
+ struct wifi_platform_data *plat_data;
+
+ if (!adapter || !adapter->wifi_plat_data)
+ return -EINVAL;
+ plat_data = adapter->wifi_plat_data;
+
+ DHD_ERROR(("%s device present %d\n", __FUNCTION__, device_present));
+ if (plat_data->set_carddetect) {
+ err = plat_data->set_carddetect(device_present);
+ }
+ return err;
+
+}
+#endif /* CUSTOMER_IMX */
+int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf)
+{
+ struct wifi_platform_data *plat_data;
+
+ DHD_ERROR(("%s\n", __FUNCTION__));
+ if (!buf || !adapter || !adapter->wifi_plat_data)
+ return -EINVAL;
+ plat_data = adapter->wifi_plat_data;
+ if (plat_data->get_mac_addr) {
+ return plat_data->get_mac_addr(buf);
+ }
+ return -EOPNOTSUPP;
+}
+
+void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode)
+{
+ /* get_country_code was added after 2.6.39 */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+ struct wifi_platform_data *plat_data;
+
+ if (!ccode || !adapter || !adapter->wifi_plat_data)
+ return NULL;
+ plat_data = adapter->wifi_plat_data;
+
+ DHD_TRACE(("%s\n", __FUNCTION__));
+ if (plat_data->get_country_code) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58))
+ return plat_data->get_country_code(ccode, WLAN_PLAT_NODFS_FLAG);
+#else
+ return plat_data->get_country_code(ccode);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58)) */
+ }
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
+
+ return NULL;
+}
+
+static int wifi_plat_dev_drv_probe(struct platform_device *pdev)
+{
+ struct resource *resource;
+ wifi_adapter_info_t *adapter;
+#ifdef CONFIG_DTS
+#if defined(OOB_INTR_ONLY)
+ int irq, gpio;
+#endif /* defined(OOB_INTR_ONLY) */
+ int ret = 0;
+#endif /* CONFIG_DTS */
+
+ /* Android style wifi platform data device ("bcmdhd_wlan" or "bcm4329_wlan")
+ * is kept for backward compatibility and supports only 1 adapter
+ */
+ ASSERT(dhd_wifi_platdata != NULL);
+ ASSERT(dhd_wifi_platdata->num_adapters == 1);
+ adapter = &dhd_wifi_platdata->adapters[0];
+ adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data);
+
+ resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
+ if (resource == NULL)
+ resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq");
+ if (resource) {
+ adapter->irq_num = resource->start;
+ adapter->intr_flags = resource->flags;
+ }
+
+#ifdef OOB_PARAM
+ adapter->oob_disable = FALSE;
+#endif /* OOB_PARAM */
+
+#ifdef CONFIG_DTS
+ /* get firmware from dts */
+ ret = of_property_read_string(pdev->dev.of_node, "bcmdhd_fw", &adapter->fw_path);
+ if (!ret)
+ DHD_INFO(("fw path:%s\n", adapter->fw_path));
+ ret = of_property_read_string(pdev->dev.of_node, "bcmdhd_nv", &adapter->nv_path);
+ if (!ret)
+ DHD_INFO(("nv path:%s\n", adapter->nv_path));
+
+ wifi_regulator = regulator_get(&pdev->dev, "wlreg_on");
+ if (wifi_regulator == NULL) {
+ DHD_ERROR(("%s regulator is null\n", __FUNCTION__));
+ return -1;
+ }
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(adapter->oob_disable)) {
+ /* This is to get the irq for the OOB */
+ gpio = of_get_gpio(pdev->dev.of_node, 0);
+
+ if (gpio < 0) {
+ DHD_ERROR(("%s no GPIO for OOB in device tree.\n", __FUNCTION__));
+#if defined(OOB_PARAM)
+ DHD_ERROR(("%s continue with non-OOB mode.\n", __FUNCTION__));
+ adapter->oob_disable = TRUE;
+ goto out;
+#else
+ return -1;
+#endif /* defined(OOB_PARAM) */
+ }
+
+ irq = gpio_to_irq(gpio);
+ if (irq < 0) {
+ DHD_ERROR(("%s irq information is incorrect\n", __FUNCTION__));
+ return -1;
+ }
+
+ adapter->irq_num = irq;
+
+ /* Murata -- HW_OOB define depends on chipset.
+ * HW_OOB makes host interrupt level-sensitive versus edge-sensitive.
+ * ZP (BCM4339), 1DX (BCM4343W), 1FX (BCM43364), ZX/SN8000 (BCM43362)
+ * are level-sensitive (HW_OOB defined).
+ * Type 1BW (BCM43340) is edge-sensitive (HW_OOB NOT defined).
+ */
+#ifdef HW_OOB /* HW_OOB defined means level sensitive interrupts */
+ adapter->intr_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
+ IORESOURCE_IRQ_SHAREABLE;
+#else
+ adapter->intr_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+ IORESOURCE_IRQ_SHAREABLE;
+#endif /* HW_OOB */
+ }
+#if defined(OOB_PARAM)
+out:
+#endif /* defined(OOB_PARAM) */
+#endif /* defined(OOB_INTR_ONLY) */
+#endif /* CONFIG_DTS */
+
+ wifi_plat_dev_probe_ret = dhd_wifi_platform_load();
+ return wifi_plat_dev_probe_ret;
+}
+
+static int wifi_plat_dev_drv_remove(struct platform_device *pdev)
+{
+ wifi_adapter_info_t *adapter;
+
+ /* Android style wifi platform data device ("bcmdhd_wlan" or "bcm4329_wlan")
+ * is kept for backward compatibility and supports only 1 adapter
+ */
+ ASSERT(dhd_wifi_platdata != NULL);
+ ASSERT(dhd_wifi_platdata->num_adapters == 1);
+ adapter = &dhd_wifi_platdata->adapters[0];
+ if (is_power_on) {
+ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+ wifi_platform_bus_enumerate(adapter, FALSE);
+ }
+
+#ifdef CONFIG_DTS
+ regulator_put(wifi_regulator);
+#endif /* CONFIG_DTS */
+ return 0;
+}
+
+static int wifi_plat_dev_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+#ifdef OOB_PARAM
+ wifi_adapter_info_t *adapter;
+ adapter = &dhd_wifi_platdata->adapters[0];
+#endif /* OOB_PARAM */
+
+ DHD_TRACE(("##> %s\n", __FUNCTION__));
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(adapter->oob_disable)) {
+ bcmsdh_oob_intr_set(0);
+ }
+#endif /* (OOB_INTR_ONLY) */
+ return 0;
+}
+
+static int wifi_plat_dev_drv_resume(struct platform_device *pdev)
+{
+#ifdef OOB_PARAM
+ wifi_adapter_info_t *adapter;
+ adapter = &dhd_wifi_platdata->adapters[0];
+#endif /* OOB_PARAM */
+
+ DHD_TRACE(("##> %s\n", __FUNCTION__));
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(adapter->oob_disable)) {
+ if (dhd_os_check_if_up(wl_cfg80211_get_dhdp()))
+ bcmsdh_oob_intr_set(1);
+ }
+#endif /* (OOB_INTR_ONLY) */
+ return 0;
+}
+
+#ifdef CONFIG_DTS
+static const struct of_device_id wifi_device_dt_match[] = {
+ { .compatible = "android,bcmdhd_wlan", },
+ {},
+};
+#endif /* CONFIG_DTS */
+static struct platform_driver wifi_platform_dev_driver = {
+ .probe = wifi_plat_dev_drv_probe,
+ .remove = wifi_plat_dev_drv_remove,
+ .suspend = wifi_plat_dev_drv_suspend,
+ .resume = wifi_plat_dev_drv_resume,
+ .driver = {
+ .name = WIFI_PLAT_NAME,
+#ifdef CONFIG_DTS
+ .of_match_table = wifi_device_dt_match,
+#endif /* CONFIG_DTS */
+ }
+};
+
+static struct platform_driver wifi_platform_dev_driver_legacy = {
+ .probe = wifi_plat_dev_drv_probe,
+ .remove = wifi_plat_dev_drv_remove,
+ .suspend = wifi_plat_dev_drv_suspend,
+ .resume = wifi_plat_dev_drv_resume,
+ .driver = {
+ .name = WIFI_PLAT_NAME2,
+ }
+};
+
+static int wifi_platdev_match(struct device *dev, void *data)
+{
+ char *name = (char*)data;
+ struct platform_device *pdev = to_platform_device(dev);
+
+ if (strcmp(pdev->name, name) == 0) {
+ DHD_ERROR(("found wifi platform device %s\n", name));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int wifi_ctrlfunc_register_drv(void)
+{
+ int err = 0;
+ struct device *dev1, *dev2;
+ wifi_adapter_info_t *adapter;
+
+ dev1 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME, wifi_platdev_match);
+ dev2 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME2, wifi_platdev_match);
+
+#if !defined(CONFIG_DTS)
+ if (!dts_enabled) {
+ if (dev1 == NULL && dev2 == NULL) {
+ DHD_ERROR(("no wifi platform data, skip\n"));
+ return -ENXIO;
+ }
+ }
+#endif /* !defined(CONFIG_DTS) */
+
+ /* multi-chip support not enabled, build one adapter information for
+ * DHD (either SDIO, USB or PCIe)
+ */
+ adapter = kzalloc(sizeof(wifi_adapter_info_t), GFP_KERNEL);
+ adapter->name = "DHD generic adapter";
+ adapter->bus_type = -1;
+ adapter->bus_num = -1;
+ adapter->slot_num = -1;
+ adapter->irq_num = -1;
+ is_power_on = FALSE;
+ wifi_plat_dev_probe_ret = 0;
+ dhd_wifi_platdata = kzalloc(sizeof(bcmdhd_wifi_platdata_t), GFP_KERNEL);
+ dhd_wifi_platdata->num_adapters = 1;
+ dhd_wifi_platdata->adapters = adapter;
+
+ if (dev1) {
+ err = platform_driver_register(&wifi_platform_dev_driver);
+ if (err) {
+ DHD_ERROR(("%s: failed to register wifi ctrl func driver\n",
+ __FUNCTION__));
+ return err;
+ }
+ }
+ if (dev2) {
+ err = platform_driver_register(&wifi_platform_dev_driver_legacy);
+ if (err) {
+ DHD_ERROR(("%s: failed to register wifi ctrl func legacy driver\n",
+ __FUNCTION__));
+ return err;
+ }
+ }
+
+#if !defined(CONFIG_DTS)
+ if (dts_enabled) {
+ struct resource *resource;
+ adapter->wifi_plat_data = (void *)&dhd_wlan_control;
+ resource = &dhd_wlan_resources;
+ adapter->irq_num = resource->start;
+ adapter->intr_flags = resource->flags;
+ wifi_plat_dev_probe_ret = dhd_wifi_platform_load();
+ }
+#endif /* !defined(CONFIG_DTS) */
+
+
+#ifdef CONFIG_DTS
+ wifi_plat_dev_probe_ret = platform_driver_register(&wifi_platform_dev_driver);
+#endif /* CONFIG_DTS */
+
+ /* return probe function's return value if registeration succeeded */
+ return wifi_plat_dev_probe_ret;
+}
+
+void wifi_ctrlfunc_unregister_drv(void)
+{
+
+#ifdef CONFIG_DTS
+ DHD_ERROR(("unregister wifi platform drivers\n"));
+ platform_driver_unregister(&wifi_platform_dev_driver);
+#else
+ struct device *dev1, *dev2;
+ dev1 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME, wifi_platdev_match);
+ dev2 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME2, wifi_platdev_match);
+ if (!dts_enabled)
+ if (dev1 == NULL && dev2 == NULL)
+ return;
+
+ DHD_ERROR(("unregister wifi platform drivers\n"));
+ if (dev1)
+ platform_driver_unregister(&wifi_platform_dev_driver);
+ if (dev2)
+ platform_driver_unregister(&wifi_platform_dev_driver_legacy);
+ if (dts_enabled) {
+ wifi_adapter_info_t *adapter;
+ adapter = &dhd_wifi_platdata->adapters[0];
+ if (is_power_on) {
+ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+ wifi_platform_bus_enumerate(adapter, FALSE);
+ }
+ }
+#endif /* !defined(CONFIG_DTS) */
+
+ kfree(dhd_wifi_platdata->adapters);
+ dhd_wifi_platdata->adapters = NULL;
+ dhd_wifi_platdata->num_adapters = 0;
+ kfree(dhd_wifi_platdata);
+ dhd_wifi_platdata = NULL;
+}
+
+static int bcmdhd_wifi_plat_dev_drv_probe(struct platform_device *pdev)
+{
+ dhd_wifi_platdata = (bcmdhd_wifi_platdata_t *)(pdev->dev.platform_data);
+
+ return dhd_wifi_platform_load();
+}
+
+static int bcmdhd_wifi_plat_dev_drv_remove(struct platform_device *pdev)
+{
+ int i;
+ wifi_adapter_info_t *adapter;
+ ASSERT(dhd_wifi_platdata != NULL);
+
+ /* power down all adapters */
+ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+ adapter = &dhd_wifi_platdata->adapters[i];
+ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+ wifi_platform_bus_enumerate(adapter, FALSE);
+ }
+ return 0;
+}
+
+static struct platform_driver dhd_wifi_platform_dev_driver = {
+ .probe = bcmdhd_wifi_plat_dev_drv_probe,
+ .remove = bcmdhd_wifi_plat_dev_drv_remove,
+ .driver = {
+ .name = WIFI_PLAT_EXT,
+ }
+};
+
+int dhd_wifi_platform_register_drv(void)
+{
+ int err = 0;
+ struct device *dev;
+
+ /* register Broadcom wifi platform data driver if multi-chip is enabled,
+ * otherwise use Android style wifi platform data (aka wifi control function)
+ * if it exists
+ *
+ * to support multi-chip DHD, Broadcom wifi platform data device must
+ * be added in kernel early boot (e.g. board config file).
+ */
+ if (cfg_multichip) {
+ dev = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_EXT, wifi_platdev_match);
+ if (dev == NULL) {
+ DHD_ERROR(("bcmdhd wifi platform data device not found!!\n"));
+ return -ENXIO;
+ }
+ err = platform_driver_register(&dhd_wifi_platform_dev_driver);
+ } else {
+ err = wifi_ctrlfunc_register_drv();
+
+ /* no wifi ctrl func either, load bus directly and ignore this error */
+ if (err) {
+ if (err == -ENXIO) {
+ /* wifi ctrl function does not exist */
+ err = dhd_wifi_platform_load();
+ } else {
+ /* unregister driver due to initialization failure */
+ wifi_ctrlfunc_unregister_drv();
+ }
+ }
+ }
+
+ return err;
+}
+
+#ifdef BCMPCIE
+static int dhd_wifi_platform_load_pcie(void)
+{
+ int err = 0;
+ err = dhd_bus_register();
+ return err;
+}
+#else
+static int dhd_wifi_platform_load_pcie(void)
+{
+ return 0;
+}
+#endif /* BCMPCIE */
+
+
+void dhd_wifi_platform_unregister_drv(void)
+{
+ if (cfg_multichip)
+ platform_driver_unregister(&dhd_wifi_platform_dev_driver);
+ else
+ wifi_ctrlfunc_unregister_drv();
+}
+
+extern int dhd_watchdog_prio;
+extern int dhd_dpc_prio;
+extern uint dhd_deferred_tx;
+#if defined(BCMLXSDMMC)
+extern struct semaphore dhd_registration_sem;
+#endif
+
+static int dhd_wifi_platform_load_sdio(void)
+{
+ int i;
+ int err = 0;
+ wifi_adapter_info_t *adapter;
+
+ BCM_REFERENCE(i);
+ BCM_REFERENCE(adapter);
+ /* Sanity check on the module parameters
+ * - Both watchdog and DPC as tasklets are ok
+ * - If both watchdog and DPC are threads, TX must be deferred
+ */
+ if (!(dhd_watchdog_prio < 0 && dhd_dpc_prio < 0) &&
+ !(dhd_watchdog_prio >= 0 && dhd_dpc_prio >= 0 && dhd_deferred_tx))
+ return -EINVAL;
+
+#if defined(BCMLXSDMMC)
+ if (dhd_wifi_platdata == NULL) {
+ DHD_ERROR(("DHD wifi platform data is required for Android build\n"));
+ return -EINVAL;
+ }
+
+ sema_init(&dhd_registration_sem, 0);
+ /* power up all adapters */
+ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+ bool chip_up = FALSE;
+ int retry = POWERUP_MAX_RETRY;
+ struct semaphore dhd_chipup_sem;
+
+ adapter = &dhd_wifi_platdata->adapters[i];
+
+ DHD_ERROR(("Power-up adapter '%s'\n", adapter->name));
+ DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
+ adapter->irq_num, adapter->intr_flags, adapter->fw_path, adapter->nv_path));
+ DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
+ adapter->bus_type, adapter->bus_num, adapter->slot_num));
+
+ do {
+ sema_init(&dhd_chipup_sem, 0);
+ err = dhd_bus_reg_sdio_notify(&dhd_chipup_sem);
+ if (err) {
+ DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n",
+ __FUNCTION__, err));
+ return err;
+ }
+ err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY);
+ if (err) {
+ /* WL_REG_ON state unknown, Power off forcely */
+ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+ continue;
+ } else {
+ wifi_platform_bus_enumerate(adapter, TRUE);
+ err = 0;
+ }
+
+ if (down_timeout(&dhd_chipup_sem, msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) {
+ dhd_bus_unreg_sdio_notify();
+ chip_up = TRUE;
+ break;
+ }
+
+ DHD_ERROR(("failed to power up %s, %d retry left\n", adapter->name, retry));
+ dhd_bus_unreg_sdio_notify();
+ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+ wifi_platform_bus_enumerate(adapter, FALSE);
+ } while (retry--);
+
+ if (!chip_up) {
+ DHD_ERROR(("failed to power up %s, max retry reached**\n", adapter->name));
+ return -ENODEV;
+ }
+
+ }
+
+ err = dhd_bus_register();
+
+ if (err) {
+ DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+
+ /*
+ * Wait till MMC sdio_register_driver callback called and made driver attach.
+ * It's needed to make sync up exit from dhd insmod and
+ * Kernel MMC sdio device callback registration
+ */
+ err = down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT));
+ if (err) {
+ DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__));
+ dhd_bus_unregister();
+ goto fail;
+ }
+
+ return err;
+
+fail:
+ /* power down all adapters */
+ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+ adapter = &dhd_wifi_platdata->adapters[i];
+ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+ wifi_platform_bus_enumerate(adapter, FALSE);
+ }
+#else
+
+ /* x86 bring-up PC needs no power-up operations */
+ err = dhd_bus_register();
+
+#endif
+
+ return err;
+}
+
+static int dhd_wifi_platform_load_usb(void)
+{
+ return 0;
+}
+
+static int dhd_wifi_platform_load()
+{
+ int err = 0;
+
+ wl_android_init();
+
+ if ((err = dhd_wifi_platform_load_usb()))
+ goto end;
+ else if ((err = dhd_wifi_platform_load_sdio()))
+ goto end;
+ else
+ err = dhd_wifi_platform_load_pcie();
+
+end:
+ if (err)
+ wl_android_exit();
+ else
+ wl_android_post_init();
+
+ return err;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_sched.c b/drivers/net/wireless/bcmdhd/dhd_linux_sched.c
new file mode 100644
index 000000000000..2ff7d6c1af09
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_linux_sched.c
@@ -0,0 +1,48 @@
+/*
+ * Expose some of the kernel scheduler routines
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_linux_sched.c 457596 2014-02-24 02:24:14Z $
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <typedefs.h>
+#include <linuxver.h>
+
+int setScheduler(struct task_struct *p, int policy, struct sched_param *param)
+{
+ int rc = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+ rc = sched_setscheduler(p, policy, param);
+#endif /* LinuxVer */
+ return rc;
+}
+
+int get_scheduler_policy(struct task_struct *p)
+{
+ int rc = SCHED_NORMAL;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+ rc = p->policy;
+#endif /* LinuxVer */
+ return rc;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_wq.c b/drivers/net/wireless/bcmdhd/dhd_linux_wq.c
new file mode 100644
index 000000000000..60018349fac0
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_linux_wq.c
@@ -0,0 +1,316 @@
+/*
+ * Broadcom Dongle Host Driver (DHD), Generic work queue framework
+ * Generic interface to handle dhd deferred work events
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_linux_wq.c 589976 2015-10-01 07:01:27Z $
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/ip.h>
+#include <linux/kfifo.h>
+
+#include <linuxver.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <bcmdevs.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_dbg.h>
+#include <dhd_linux_wq.h>
+
+struct dhd_deferred_event_t {
+ u8 event; /* holds the event */
+ void *event_data; /* Holds event specific data */
+ event_handler_t event_handler;
+};
+#define DEFRD_EVT_SIZE sizeof(struct dhd_deferred_event_t)
+
+struct dhd_deferred_wq {
+ struct work_struct deferred_work; /* should be the first member */
+
+ /*
+ * work events may occur simultaneously.
+ * Can hold upto 64 low priority events and 4 high priority events
+ */
+#define DHD_PRIO_WORK_FIFO_SIZE (4 * sizeof(struct dhd_deferred_event_t))
+#define DHD_WORK_FIFO_SIZE (64 * sizeof(struct dhd_deferred_event_t))
+ struct kfifo *prio_fifo;
+ struct kfifo *work_fifo;
+ u8 *prio_fifo_buf;
+ u8 *work_fifo_buf;
+ spinlock_t work_lock;
+ void *dhd_info; /* review: does it require */
+};
+struct dhd_deferred_wq *deferred_wq = NULL;
+
+static inline struct kfifo*
+dhd_kfifo_init(u8 *buf, int size, spinlock_t *lock)
+{
+ struct kfifo *fifo;
+ gfp_t flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
+ fifo = kfifo_init(buf, size, flags, lock);
+#else
+ fifo = (struct kfifo *)kzalloc(sizeof(struct kfifo), flags);
+ if (!fifo) {
+ return NULL;
+ }
+ kfifo_init(fifo, buf, size);
+#endif
+ return fifo;
+}
+
+static inline void
+dhd_kfifo_free(struct kfifo *fifo)
+{
+ kfifo_free(fifo);
+}
+
+/* deferred work functions */
+static void dhd_deferred_work_handler(struct work_struct *data);
+
+void*
+dhd_deferred_work_init(void *dhd_info)
+{
+ struct dhd_deferred_wq *work = NULL;
+ u8* buf;
+ unsigned long fifo_size = 0;
+ gfp_t flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC;
+
+ if (!dhd_info) {
+ DHD_ERROR(("%s: dhd info not initialized\n", __FUNCTION__));
+ goto return_null;
+ }
+
+ work = (struct dhd_deferred_wq *)kzalloc(sizeof(struct dhd_deferred_wq),
+ flags);
+
+ if (!work) {
+ DHD_ERROR(("%s: work queue creation failed \n", __FUNCTION__));
+ goto return_null;
+ }
+
+ INIT_WORK((struct work_struct *)work, dhd_deferred_work_handler);
+
+ /* initialize event fifo */
+ spin_lock_init(&work->work_lock);
+
+ /* allocate buffer to hold prio events */
+ fifo_size = DHD_PRIO_WORK_FIFO_SIZE;
+ fifo_size = is_power_of_2(fifo_size)? fifo_size : roundup_pow_of_two(fifo_size);
+ buf = (u8*)kzalloc(fifo_size, flags);
+ if (!buf) {
+ DHD_ERROR(("%s: prio work fifo allocation failed \n", __FUNCTION__));
+ goto return_null;
+ }
+
+ /* Initialize prio event fifo */
+ work->prio_fifo = dhd_kfifo_init(buf, fifo_size, &work->work_lock);
+ if (!work->prio_fifo) {
+ kfree(buf);
+ goto return_null;
+ }
+
+ /* allocate buffer to hold work events */
+ fifo_size = DHD_WORK_FIFO_SIZE;
+ fifo_size = is_power_of_2(fifo_size)? fifo_size : roundup_pow_of_two(fifo_size);
+ buf = (u8*)kzalloc(fifo_size, flags);
+ if (!buf) {
+ DHD_ERROR(("%s: work fifo allocation failed \n", __FUNCTION__));
+ goto return_null;
+ }
+
+ /* Initialize event fifo */
+ work->work_fifo = dhd_kfifo_init(buf, fifo_size, &work->work_lock);
+ if (!work->work_fifo) {
+ kfree(buf);
+ goto return_null;
+ }
+
+ work->dhd_info = dhd_info;
+ deferred_wq = work;
+ DHD_ERROR(("%s: work queue initialized \n", __FUNCTION__));
+ return work;
+
+return_null:
+
+ if (work)
+ dhd_deferred_work_deinit(work);
+
+ return NULL;
+}
+
+void
+dhd_deferred_work_deinit(void *work)
+{
+ struct dhd_deferred_wq *deferred_work = work;
+
+
+ if (!deferred_work) {
+ DHD_ERROR(("%s: deferred work has been freed alread \n", __FUNCTION__));
+ return;
+ }
+
+ /* cancel the deferred work handling */
+ cancel_work_sync((struct work_struct *)deferred_work);
+
+ /*
+ * free work event fifo.
+ * kfifo_free frees locally allocated fifo buffer
+ */
+ if (deferred_work->prio_fifo)
+ dhd_kfifo_free(deferred_work->prio_fifo);
+
+ if (deferred_work->work_fifo)
+ dhd_kfifo_free(deferred_work->work_fifo);
+
+ kfree(deferred_work);
+
+ /* deinit internal reference pointer */
+ deferred_wq = NULL;
+}
+
+/*
+ * Prepares event to be queued
+ * Schedules the event
+ */
+int
+dhd_deferred_schedule_work(void *event_data, u8 event, event_handler_t event_handler, u8 priority)
+{
+ struct dhd_deferred_event_t deferred_event;
+ int status;
+
+ if (!deferred_wq) {
+ DHD_ERROR(("%s: work queue not initialized \n", __FUNCTION__));
+ ASSERT(0);
+ return DHD_WQ_STS_UNINITIALIZED;
+ }
+
+ if (!event || (event >= DHD_MAX_WQ_EVENTS)) {
+ DHD_ERROR(("%s: Unknown event \n", __FUNCTION__));
+ return DHD_WQ_STS_UNKNOWN_EVENT;
+ }
+
+ /*
+ * default element size is 1, which can be changed
+ * using kfifo_esize(). Older kernel(FC11) doesn't support
+ * changing element size. For compatibility changing
+ * element size is not prefered
+ */
+ ASSERT(kfifo_esize(deferred_wq->prio_fifo) == 1);
+ ASSERT(kfifo_esize(deferred_wq->work_fifo) == 1);
+
+ deferred_event.event = event;
+ deferred_event.event_data = event_data;
+ deferred_event.event_handler = event_handler;
+
+ if (priority == DHD_WORK_PRIORITY_HIGH) {
+ status = kfifo_in_spinlocked(deferred_wq->prio_fifo, &deferred_event,
+ DEFRD_EVT_SIZE, &deferred_wq->work_lock);
+ } else {
+ status = kfifo_in_spinlocked(deferred_wq->work_fifo, &deferred_event,
+ DEFRD_EVT_SIZE, &deferred_wq->work_lock);
+ }
+
+ if (!status) {
+ return DHD_WQ_STS_SCHED_FAILED;
+ }
+ schedule_work((struct work_struct *)deferred_wq);
+ return DHD_WQ_STS_OK;
+}
+
+static int
+dhd_get_scheduled_work(struct dhd_deferred_event_t *event)
+{
+ int status = 0;
+
+ if (!deferred_wq) {
+ DHD_ERROR(("%s: work queue not initialized \n", __FUNCTION__));
+ return DHD_WQ_STS_UNINITIALIZED;
+ }
+
+ /*
+ * default element size is 1 byte, which can be changed
+ * using kfifo_esize(). Older kernel(FC11) doesn't support
+ * changing element size. For compatibility changing
+ * element size is not prefered
+ */
+ ASSERT(kfifo_esize(deferred_wq->prio_fifo) == 1);
+ ASSERT(kfifo_esize(deferred_wq->work_fifo) == 1);
+
+ /* first read priorit event fifo */
+ status = kfifo_out_spinlocked(deferred_wq->prio_fifo, event,
+ DEFRD_EVT_SIZE, &deferred_wq->work_lock);
+
+ if (!status) {
+ /* priority fifo is empty. Now read low prio work fifo */
+ status = kfifo_out_spinlocked(deferred_wq->work_fifo, event,
+ DEFRD_EVT_SIZE, &deferred_wq->work_lock);
+ }
+
+ return status;
+}
+
+/*
+ * Called when work is scheduled
+ */
+static void
+dhd_deferred_work_handler(struct work_struct *work)
+{
+ struct dhd_deferred_wq *deferred_work = (struct dhd_deferred_wq *)work;
+ struct dhd_deferred_event_t work_event;
+ int status;
+
+ if (!deferred_work) {
+ DHD_ERROR(("%s: work queue not initialized\n", __FUNCTION__));
+ return;
+ }
+
+ do {
+ status = dhd_get_scheduled_work(&work_event);
+ DHD_TRACE(("%s: event to handle %d \n", __FUNCTION__, status));
+ if (!status) {
+ DHD_TRACE(("%s: No event to handle %d \n", __FUNCTION__, status));
+ break;
+ }
+
+ if (work_event.event > DHD_MAX_WQ_EVENTS) {
+ DHD_TRACE(("%s: Unknown event %d \n", __FUNCTION__, work_event.event));
+ break;
+ }
+
+ if (work_event.event_handler) {
+ work_event.event_handler(deferred_work->dhd_info,
+ work_event.event_data, work_event.event);
+ } else {
+ DHD_ERROR(("%s: event not defined %d\n", __FUNCTION__, work_event.event));
+ }
+ } while (1);
+ return;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_wq.h b/drivers/net/wireless/bcmdhd/dhd_linux_wq.h
new file mode 100644
index 000000000000..4396ee129e26
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_linux_wq.h
@@ -0,0 +1,64 @@
+/*
+ * Broadcom Dongle Host Driver (DHD), Generic work queue framework
+ * Generic interface to handle dhd deferred work events
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_linux_wq.h 408802 2013-06-20 19:08:47Z $
+ */
+#ifndef _dhd_linux_wq_h_
+#define _dhd_linux_wq_h_
+/*
+ * Work event definitions
+ */
+enum _wq_event {
+ DHD_WQ_WORK_IF_ADD = 1,
+ DHD_WQ_WORK_IF_DEL,
+ DHD_WQ_WORK_SET_MAC,
+ DHD_WQ_WORK_SET_MCAST_LIST,
+ DHD_WQ_WORK_IPV6_NDO,
+ DHD_WQ_WORK_HANG_MSG,
+
+ DHD_MAX_WQ_EVENTS
+};
+
+/*
+ * Work event priority
+ */
+#define DHD_WORK_PRIORITY_LOW 0
+#define DHD_WORK_PRIORITY_HIGH 1
+
+/*
+ * Error definitions
+ */
+#define DHD_WQ_STS_OK 0
+#define DHD_WQ_STS_FAILED -1 /* General failure */
+#define DHD_WQ_STS_UNINITIALIZED -2
+#define DHD_WQ_STS_SCHED_FAILED -3
+#define DHD_WQ_STS_UNKNOWN_EVENT -4
+
+typedef void (*event_handler_t)(void *handle, void *event_data, u8 event);
+
+void *dhd_deferred_work_init(void *dhd);
+void dhd_deferred_work_deinit(void *work);
+int dhd_deferred_schedule_work(void *event_data, u8 event,
+ event_handler_t evt_handler, u8 priority);
+#endif /* _dhd_linux_wq_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c
new file mode 100644
index 000000000000..76745f9d4a23
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c
@@ -0,0 +1,1755 @@
+/*
+ * Header file describing the internal (inter-module) DHD interfaces.
+ *
+ * Provides type definitions and function prototypes used to link the
+ * DHD OS, bus, and protocol modules.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_msgbuf.c 452261 2014-01-29 19:30:23Z $
+ */
+#include <typedefs.h>
+#include <osl.h>
+
+#include <bcmutils.h>
+#include <circularbuf.h>
+#include <bcmmsgbuf.h>
+#include <bcmendian.h>
+
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_proto.h>
+#include <dhd_bus.h>
+#include <dhd_dbg.h>
+
+
+#ifdef PROP_TXSTATUS
+#include <wlfc_proto.h>
+#include <dhd_wlfc.h>
+#endif
+#include <pcie_core.h>
+#include <bcmpcie.h>
+
+#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
+#define IOCTL_HDR_LEN 12
+
+#define DEFAULT_RX_BUFFERS_TO_POST 255
+#define RXBUFPOST_THRESHOLD 16
+#define RX_BUF_BURST 8
+
+#define DHD_STOP_QUEUE_THRESHOLD 24
+#define DHD_START_QUEUE_THRESHOLD 32
+#define MAX_INLINE_IOCTL_LEN 64 /* anything beyond this len will not be inline reqst */
+
+/* Required for Native to PktId mapping incase of 64bit hosts */
+#define MAX_PKTID_ITEMS (2048)
+
+/* Given packet pointer and physical address, macro should return unique 32 bit pktid */
+/* And given 32bit pktid, macro should return packet pointer and physical address */
+extern void *pktid_map_init(void *osh, uint32 count);
+extern void pktid_map_uninit(void *pktid_map_handle);
+extern uint32 pktid_map_unique(void *pktid_map_handle,
+ void *pkt, dmaaddr_t physaddr, uint32 physlen, uint32 dma);
+extern void *pktid_get_packet(void *pktid_map_handle,
+ uint32 id, dmaaddr_t *physaddr, uint32 *physlen);
+
+#define NATIVE_TO_PKTID_INIT(osh, count) pktid_map_init(osh, count)
+#define NATIVE_TO_PKTID_UNINIT(pktid_map_handle) pktid_map_uninit(pktid_map_handle)
+
+#define NATIVE_TO_PKTID(pktid_map_handle, pkt, pa, pa_len, dma) \
+ pktid_map_unique((pktid_map_handle), (void *)(pkt), (pa), (uint32) (pa_len), (uint32)dma)
+#define PKTID_TO_NATIVE(pktid_map_handle, id, pa, pa_len) \
+ pktid_get_packet((pktid_map_handle), (uint32)(id), (void *)&(pa), (uint32 *) &(pa_len))
+
+#define MODX(x, n) ((x) & ((n) -1))
+#define align(x, n) (MODX(x, n) ? ((x) - MODX(x, n) + (n)) : ((x) - MODX(x, n)))
+#define RX_DMA_OFFSET 8
+#define IOCT_RETBUF_SIZE (RX_DMA_OFFSET + WLC_IOCTL_MAXLEN)
+
+typedef struct dhd_prot {
+ uint32 reqid;
+ uint16 hdr_len;
+ uint32 lastcmd;
+ uint32 pending;
+ uint16 rxbufpost;
+ uint16 max_rxbufpost;
+ uint16 active_tx_count;
+ uint16 max_tx_count;
+ dmaaddr_t htod_physaddr;
+ dmaaddr_t dtoh_physaddr;
+ bool txflow_en;
+ circularbuf_t *dtohbuf;
+ circularbuf_t *htodbuf;
+ uint32 rx_dataoffset;
+ void* retbuf;
+ dmaaddr_t retbuf_phys;
+ void* ioctbuf; /* For holding ioct request buf */
+ dmaaddr_t ioctbuf_phys; /* physical address for ioctbuf */
+ dhd_mb_ring_t mb_ring_fn;
+ void *htod_ring;
+ void *dtoh_ring;
+ /* Flag to check if splitbuf support is enabled. */
+ /* Set to False at dhd_prot_attach. Set to True at dhd_prot_init */
+ bool htodsplit;
+ bool dtohsplit;
+ /* H2D/D2H Ctrl rings */
+ dmaaddr_t htod_ctrl_physaddr; /* DMA mapped physical addr ofr H2D ctrl ring */
+ dmaaddr_t dtoh_ctrl_physaddr; /* DMA mapped phys addr for D2H ctrl ring */
+ circularbuf_t *htod_ctrlbuf; /* Cbuf handle for H2D ctrl ring */
+ circularbuf_t *dtoh_ctrlbuf; /* Cbuf handle for D2H ctrl ring */
+ void *htod_ctrl_ring; /* address for H2D control buf */
+ void *dtoh_ctrl_ring; /* address for D2H control buf */
+
+
+ uint16 ioctl_seq_no;
+ uint16 data_seq_no;
+ void *pktid_map_handle;
+} dhd_prot_t;
+
+static int dhdmsgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd,
+ void *buf, uint len, uint8 action);
+static int dhd_msgbuf_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd,
+ void *buf, uint len, uint8 action);
+static int dhdmsgbuf_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len, void* buf, void* retbuf);
+static int dhd_msgbuf_init_dtoh(dhd_pub_t *dhd);
+
+static int dhd_msgbuf_rxbuf_post(dhd_pub_t *dhd);
+static int dhd_msgbuf_init_htod(dhd_pub_t *dhd);
+static int dhd_msgbuf_init_htod_ctrl(dhd_pub_t *dhd);
+static int dhd_msgbuf_init_dtoh_ctrl(dhd_pub_t *dhd);
+static int dhd_prot_rxbufpost(dhd_pub_t *dhd, uint32 count);
+static void dhd_prot_return_rxbuf(dhd_pub_t *dhd, uint16 rxcnt);
+static void dhd_prot_rxcmplt_process(dhd_pub_t *dhd, void* buf);
+static void dhd_prot_event_process(dhd_pub_t *dhd, uint8* buf, uint16 len);
+static void dhd_prot_process_msgtype(dhd_pub_t *dhd, uint8* buf, uint16 len);
+static void dhd_process_msgtype(dhd_pub_t *dhd, uint8* buf, uint16 len);
+
+static void dhd_prot_txstatus_process(dhd_pub_t *dhd, void * buf);
+static void dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void * buf);
+void* dhd_alloc_circularbuf_space(dhd_pub_t *dhd, circularbuf_t *handle, uint16 msglen, uint path);
+static int dhd_fillup_ioct_reqst(dhd_pub_t *dhd, uint16 len, uint cmd, void* buf, int ifidx);
+static int dhd_fillup_ioct_reqst_ptrbased(dhd_pub_t *dhd, uint16 len, uint cmd, void* buf,
+ int ifidx);
+static INLINE void dhd_prot_packet_free(dhd_pub_t *dhd, uint32 pktid);
+static INLINE void *dhd_prot_packet_get(dhd_pub_t *dhd, uint32 pktid);
+
+/* Linkage, sets prot link and updates hdrlen in pub */
+int dhd_prot_attach(dhd_pub_t *dhd)
+{
+ uint alloced = 0;
+
+ dhd_prot_t *msg_buf;
+ if (!(msg_buf = (dhd_prot_t *)DHD_OS_PREALLOC(dhd, DHD_PREALLOC_PROT,
+ sizeof(dhd_prot_t)))) {
+ DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+ goto fail;
+ }
+ memset(msg_buf, 0, sizeof(dhd_prot_t));
+
+ msg_buf->hdr_len = sizeof(ioctl_req_hdr_t) + sizeof(cmn_msg_hdr_t) + sizeof(ret_buf_t);
+ msg_buf->dtohbuf = MALLOC(dhd->osh, sizeof(circularbuf_t));
+ msg_buf->htodbuf = MALLOC(dhd->osh, sizeof(circularbuf_t));
+
+ memset(msg_buf->dtohbuf, 0, sizeof(circularbuf_t));
+ memset(msg_buf->htodbuf, 0, sizeof(circularbuf_t));
+
+ dhd->prot = msg_buf;
+ dhd->maxctl = WLC_IOCTL_MAXLEN + msg_buf->hdr_len;
+
+ /* ret buf for ioctl */
+ msg_buf->retbuf = DMA_ALLOC_CONSISTENT(dhd->osh, IOCT_RETBUF_SIZE, 4,
+ &alloced, &msg_buf->retbuf_phys, NULL);
+ if (msg_buf->retbuf == NULL) {
+ ASSERT(0);
+ return BCME_NOMEM;
+ }
+
+ ASSERT(MODX((unsigned long)msg_buf->retbuf, 4) == 0);
+
+ msg_buf->ioctbuf = DMA_ALLOC_CONSISTENT(dhd->osh, MSGBUF_MAX_MSG_SIZE, 4,
+ &alloced, &msg_buf->ioctbuf_phys, NULL);
+
+ if (msg_buf->ioctbuf == NULL) {
+ ASSERT(0);
+ return BCME_NOMEM;
+ }
+
+ ASSERT(MODX((unsigned long)msg_buf->ioctbuf, 4) == 0);
+
+ msg_buf->pktid_map_handle = NATIVE_TO_PKTID_INIT(dhd->osh, MAX_PKTID_ITEMS);
+ if (msg_buf->pktid_map_handle == NULL) {
+ ASSERT(0);
+ return BCME_NOMEM;
+ }
+
+ msg_buf->htod_ring = DMA_ALLOC_CONSISTENT(dhd->osh, HOST_TO_DNGL_MSGBUF_SZ, 4,
+ &alloced, &msg_buf->htod_physaddr, NULL);
+ if (msg_buf->htod_ring == NULL) {
+ ASSERT(0);
+ return BCME_NOMEM;
+ }
+
+ ASSERT(MODX((unsigned long)msg_buf->htod_ring, 4) == 0);
+
+ msg_buf->dtoh_ring = DMA_ALLOC_CONSISTENT(dhd->osh, DNGL_TO_HOST_MSGBUF_SZ, 4,
+ &alloced, &msg_buf->dtoh_physaddr, NULL);
+ if (msg_buf->dtoh_ring == NULL) {
+ ASSERT(0);
+ return BCME_NOMEM;
+ }
+
+ ASSERT(MODX((unsigned long)msg_buf->dtoh_ring, 4) == 0);
+
+ /* At this point we assume splitbuf is not supported by dongle */
+ msg_buf->htodsplit = FALSE;
+ msg_buf->dtohsplit = FALSE;
+
+
+ return 0;
+
+fail:
+#ifndef CONFIG_DHD_USE_STATIC_BUF
+ if (msg_buf != NULL)
+ MFREE(dhd->osh, msg_buf, sizeof(dhd_prot_t));
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+ return BCME_NOMEM;
+}
+
+/* Unlink, frees allocated protocol memory (including dhd_prot) */
+void dhd_prot_detach(dhd_pub_t *dhd)
+{
+ /* Stop the protocol module */
+ if (dhd->prot) {
+
+ if (dhd->prot->dtoh_ring) {
+ DMA_FREE_CONSISTENT(dhd->osh, dhd->prot->dtoh_ring,
+ DNGL_TO_HOST_MSGBUF_SZ, dhd->prot->dtoh_physaddr, NULL);
+
+ dhd->prot->dtoh_ring = NULL;
+ PHYSADDRHISET(dhd->prot->dtoh_physaddr, 0);
+ PHYSADDRLOSET(dhd->prot->dtoh_physaddr, 0);
+ }
+
+ if (dhd->prot->htod_ring) {
+ DMA_FREE_CONSISTENT(dhd->osh, dhd->prot->htod_ring,
+ HOST_TO_DNGL_MSGBUF_SZ, dhd->prot->htod_physaddr, NULL);
+
+ dhd->prot->htod_ring = NULL;
+ PHYSADDRHISET(dhd->prot->htod_physaddr, 0);
+ PHYSADDRLOSET(dhd->prot->htod_physaddr, 0);
+ }
+
+ if (dhd->prot->dtohbuf) {
+ MFREE(dhd->osh, dhd->prot->dtohbuf, sizeof(circularbuf_t));
+ dhd->prot->dtohbuf = NULL;
+ }
+
+ if (dhd->prot->htodbuf) {
+ MFREE(dhd->osh, dhd->prot->htodbuf, sizeof(circularbuf_t));
+ dhd->prot->htodbuf = NULL;
+ }
+
+ if (dhd->prot->htod_ctrl_ring) {
+ DMA_FREE_CONSISTENT(dhd->osh, dhd->prot->htod_ctrl_ring,
+ HOST_TO_DNGL_CTRLRING_SZ, dhd->prot->htod_ctrl_physaddr, NULL);
+
+ dhd->prot->htod_ctrl_ring = NULL;
+ dhd->prot->htod_ctrl_physaddr = 0;
+ }
+
+ if (dhd->prot->dtoh_ctrl_ring) {
+ DMA_FREE_CONSISTENT(dhd->osh, dhd->prot->dtoh_ctrl_ring,
+ DNGL_TO_HOST_CTRLRING_SZ, dhd->prot->dtoh_ctrl_physaddr, NULL);
+
+ dhd->prot->dtoh_ctrl_ring = NULL;
+ dhd->prot->dtoh_ctrl_physaddr = 0;
+ }
+
+ if (dhd->prot->htod_ctrlbuf) {
+ MFREE(dhd->osh, dhd->prot->htod_ctrlbuf, sizeof(circularbuf_t));
+ dhd->prot->htod_ctrlbuf = NULL;
+ }
+
+ if (dhd->prot->dtoh_ctrlbuf) {
+ MFREE(dhd->osh, dhd->prot->dtoh_ctrlbuf, sizeof(circularbuf_t));
+ dhd->prot->dtoh_ctrlbuf = NULL;
+ }
+
+ if (dhd->prot->retbuf) {
+ DMA_FREE_CONSISTENT(dhd->osh, dhd->prot->retbuf,
+ IOCT_RETBUF_SIZE, dhd->prot->retbuf_phys, NULL);
+ dhd->prot->retbuf = NULL;
+ }
+
+ if (dhd->prot->ioctbuf) {
+ DMA_FREE_CONSISTENT(dhd->osh, dhd->prot->ioctbuf,
+ MSGBUF_MAX_MSG_SIZE, dhd->prot->ioctbuf_phys, NULL);
+
+ dhd->prot->ioctbuf = NULL;
+ }
+
+ NATIVE_TO_PKTID_UNINIT(dhd->prot->pktid_map_handle);
+
+#ifndef CONFIG_DHD_USE_STATIC_BUF
+ MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t));
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+
+ dhd->prot = NULL;
+ }
+}
+
+void
+dhd_prot_rx_dataoffset(dhd_pub_t *dhd, uint32 rx_offset)
+{
+ dhd_prot_t *prot = dhd->prot;
+ prot->rx_dataoffset = rx_offset;
+}
+
+
+/* Initialize protocol: sync w/dongle state.
+ * Sets dongle media info (iswl, drv_version, mac address).
+ */
+int dhd_prot_init(dhd_pub_t *dhd)
+{
+ int ret = 0;
+ wlc_rev_info_t revinfo;
+ dhd_prot_t *prot = dhd->prot;
+ uint32 shared_flags;
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ dhd_bus_cmn_readshared(dhd->bus, &prot->max_tx_count, TOTAL_LFRAG_PACKET_CNT);
+ if (prot->max_tx_count == 0) {
+ /* This can happen if LFrag pool is not enabled for the LFRAG's */
+ /* on the dongle. Let's use some default value */
+ prot->max_tx_count = 64;
+ }
+ DHD_INFO(("%s:%d: MAX_TX_COUNT = %d\n", __FUNCTION__, __LINE__, prot->max_tx_count));
+
+ dhd_bus_cmn_readshared(dhd->bus, &prot->max_rxbufpost, MAX_HOST_RXBUFS);
+ if (prot->max_rxbufpost == 0) {
+ /* This would happen if the dongle firmware is not */
+ /* using the latest shared structure template */
+ prot->max_rxbufpost = DEFAULT_RX_BUFFERS_TO_POST;
+ }
+ DHD_INFO(("%s:%d: MAX_RXBUFPOST = %d\n", __FUNCTION__, __LINE__, prot->max_rxbufpost));
+
+ prot->active_tx_count = 0;
+ prot->txflow_en = FALSE;
+ prot->mb_ring_fn = dhd_bus_get_mbintr_fn(dhd->bus);
+ prot->data_seq_no = 0;
+ prot->ioctl_seq_no = 0;
+ /* initialise msgbufs */
+ shared_flags = dhd_bus_get_sharedflags(dhd->bus);
+ if (shared_flags & PCIE_SHARED_HTOD_SPLIT) {
+ prot->htodsplit = TRUE;
+ if (dhd_msgbuf_init_htod_ctrl(dhd) == BCME_NOMEM)
+ {
+ prot->htodsplit = FALSE;
+ DHD_ERROR(("%s:%d: HTOD ctrl ring alloc failed!\n",
+ __FUNCTION__, __LINE__));
+ }
+ }
+ if (shared_flags & PCIE_SHARED_DTOH_SPLIT) {
+ prot->dtohsplit = TRUE;
+ if (dhd_msgbuf_init_dtoh_ctrl(dhd) == BCME_NOMEM)
+ {
+ prot->dtohsplit = FALSE;
+ DHD_ERROR(("%s:%d: DTOH ctrl ring alloc failed!\n",
+ __FUNCTION__, __LINE__));
+ }
+ }
+ ret = dhd_msgbuf_init_htod(dhd);
+ ret = dhd_msgbuf_init_dtoh(dhd);
+ ret = dhd_msgbuf_rxbuf_post(dhd);
+
+
+ /* Get the device rev info */
+ memset(&revinfo, 0, sizeof(revinfo));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
+ if (ret < 0)
+ goto done;
+#if defined(WL_CFG80211)
+ if (dhd_download_fw_on_driverload)
+#endif /* defined(WL_CFG80211) */
+ ret = dhd_preinit_ioctls(dhd);
+ /* Always assumes wl for now */
+ dhd->iswl = TRUE;
+done:
+ return ret;
+
+}
+
+static INLINE void BCMFASTPATH
+dhd_prot_packet_free(dhd_pub_t *dhd, uint32 pktid)
+{
+ void *PKTBUF;
+ dmaaddr_t pa;
+ uint32 pa_len;
+ PKTBUF = PKTID_TO_NATIVE(dhd->prot->pktid_map_handle, pktid, pa, pa_len);
+ DMA_UNMAP(dhd->osh, (uint) pa, (uint) pa_len, DMA_TX, 0, 0);
+ PKTFREE(dhd->osh, PKTBUF, TRUE);
+ return;
+}
+
+static INLINE void * BCMFASTPATH
+dhd_prot_packet_get(dhd_pub_t *dhd, uint32 pktid)
+{
+ void *PKTBUF;
+ ulong pa;
+ uint32 pa_len;
+ PKTBUF = PKTID_TO_NATIVE(dhd->prot->pktid_map_handle, pktid, pa, pa_len);
+ DMA_UNMAP(dhd->osh, (uint) pa, (uint) pa_len, DMA_RX, 0, 0);
+ return PKTBUF;
+}
+
+static int BCMFASTPATH
+dhd_msgbuf_rxbuf_post(dhd_pub_t *dhd)
+{
+ dhd_prot_t *prot = dhd->prot;
+ unsigned long flags;
+ uint32 fillbufs;
+ uint32 i;
+ fillbufs = prot->max_rxbufpost - prot->rxbufpost;
+
+ for (i = 0; i < fillbufs; ) {
+ int retcount;
+ uint32 buf_count = (fillbufs - i) > RX_BUF_BURST ? RX_BUF_BURST : (fillbufs - i);
+
+ flags = dhd_os_spin_lock(dhd);
+ retcount = dhd_prot_rxbufpost(dhd, buf_count);
+ if (retcount > 0) {
+ prot->rxbufpost += (uint16)retcount;
+ i += (uint16)retcount;
+ dhd_os_spin_unlock(dhd, flags);
+ } else {
+ dhd_os_spin_unlock(dhd, flags);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int BCMFASTPATH
+dhd_prot_rxbufpost(dhd_pub_t *dhd, uint32 count)
+{
+ void *p;
+ uint16 pktsz = 2048;
+ uint32 i;
+ rxdesc_msghdr_t *rxbuf_post;
+ rx_lenptr_tup_t *rx_tup;
+ dmaaddr_t physaddr;
+ uint32 pktlen;
+ uint32 msglen = sizeof(rxdesc_msghdr_t) + count * sizeof(rx_lenptr_tup_t);
+
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *htod_msgbuf = (circularbuf_t *)prot->htodbuf;
+
+ rxbuf_post = (rxdesc_msghdr_t *)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, (uint16)msglen, HOST_TO_DNGL_DATA);
+ if (rxbuf_post == NULL) {
+ DHD_INFO(("%s:%d: HTOD Msgbuf Not available\n",
+ __FUNCTION__, __LINE__));
+ return -1;
+ }
+
+ /* CMN msg header */
+ rxbuf_post->msg.msglen = htol16((uint16)msglen);
+ rxbuf_post->msg.msgtype = MSG_TYPE_RXBUF_POST;
+ rxbuf_post->msg.ifidx = 0;
+ rxbuf_post->msg.u.seq.seq_no = htol16(++prot->data_seq_no);
+
+ /* RX specific hdr */
+ rxbuf_post->rsvd0 = 0;
+ rxbuf_post->rsvd1 = 0;
+ rxbuf_post->descnt = (uint8)count;
+
+ rx_tup = (rx_lenptr_tup_t *) &(rxbuf_post->rx_tup[0]);
+
+ for (i = 0; i < count; i++) {
+ if ((p = PKTGET(dhd->osh, pktsz, FALSE)) == NULL) {
+ DHD_ERROR(("%s:%d: PKTGET for rxbuf failed\n", __FUNCTION__, __LINE__));
+ printf("%s:%d: PKTGET for rxbuf failed. Need to handle this gracefully\n",
+ __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ pktlen = PKTLEN(dhd->osh, p);
+ physaddr = DMA_MAP(dhd->osh, PKTDATA(dhd->osh, p), pktlen, DMA_RX, 0, 0);
+ if (physaddr == 0) {
+ DHD_ERROR(("Something really bad, unless 0 is a valid phyaddr\n"));
+ ASSERT(0);
+ }
+ /* Each bufid-len-ptr tuple */
+ rx_tup->rxbufid = htol32(NATIVE_TO_PKTID(dhd->prot->pktid_map_handle,
+ p, physaddr, pktlen, DMA_RX));
+ rx_tup->len = htol16((uint16)PKTLEN(dhd->osh, p));
+ rx_tup->rsvd2 = 0;
+ rx_tup->ret_buf.high_addr = htol32(PHYSADDRHI(physaddr));
+ rx_tup->ret_buf.low_addr = htol32(PHYSADDRLO(physaddr));
+
+ rx_tup++;
+ }
+
+ /* Since, we are filling the data directly into the bufptr obtained
+ * from the msgbuf, we can directly call the write_complete
+ */
+ circularbuf_write_complete(htod_msgbuf, (uint16)msglen);
+
+ return count;
+}
+
+void BCMFASTPATH
+dhd_msgbuf_ringbell(void *ctx)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *) ctx;
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *htod_msgbuf = (circularbuf_t *)prot->htodbuf;
+
+ /* Following will take care of writing both the Write and End pointers (32 bits) */
+ dhd_bus_cmn_writeshared(dhd->bus, &(CIRCULARBUF_WRITE_PTR(htod_msgbuf)),
+ sizeof(uint32), HOST_TO_DNGL_WPTR);
+
+ prot->mb_ring_fn(dhd->bus, *(uint32 *) &(CIRCULARBUF_WRITE_PTR(htod_msgbuf)));
+}
+
+void BCMFASTPATH
+dhd_ctrlbuf_ringbell(void *ctx)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *) ctx;
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *htod_ctrlbuf = (circularbuf_t *)prot->htod_ctrlbuf;
+
+ /* Following will take care of writing both the Write and End pointers (32 bits) */
+ dhd_bus_cmn_writeshared(dhd->bus, &(CIRCULARBUF_WRITE_PTR(htod_ctrlbuf)),
+ sizeof(uint32), HTOD_CTRL_WPTR);
+
+ prot->mb_ring_fn(dhd->bus, *(uint32 *) &(CIRCULARBUF_WRITE_PTR(htod_ctrlbuf)));
+}
+
+static int
+dhd_msgbuf_init_htod(dhd_pub_t *dhd)
+{
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *htod_msgbuf = (circularbuf_t *)prot->htodbuf;
+
+ circularbuf_init(htod_msgbuf, prot->htod_ring, HOST_TO_DNGL_MSGBUF_SZ);
+ circularbuf_register_cb(htod_msgbuf, dhd_msgbuf_ringbell, (void *)dhd);
+ dhd_bus_cmn_writeshared(dhd->bus, &prot->htod_physaddr,
+ sizeof(prot->htod_physaddr), HOST_TO_DNGL_BUF_ADDR);
+
+ dhd_bus_cmn_writeshared(dhd->bus, &(CIRCULARBUF_WRITE_PTR(htod_msgbuf)),
+ sizeof(uint32), HOST_TO_DNGL_WPTR);
+
+ return 0;
+
+}
+static int
+dhd_msgbuf_init_dtoh(dhd_pub_t *dhd)
+{
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *dtoh_msgbuf = (circularbuf_t *)prot->dtohbuf;
+
+ prot->rxbufpost = 0;
+ circularbuf_init(dtoh_msgbuf, prot->dtoh_ring, DNGL_TO_HOST_MSGBUF_SZ);
+ dhd_bus_cmn_writeshared(dhd->bus, &prot->dtoh_physaddr,
+ sizeof(prot->dtoh_physaddr), DNGL_TO_HOST_BUF_ADDR);
+
+ dhd_bus_cmn_writeshared(dhd->bus, &CIRCULARBUF_READ_PTR(dtoh_msgbuf),
+ sizeof(uint16), DNGL_TO_HOST_RPTR);
+
+ /* One dummy interrupt to the device. This would trigger */
+ /* the msgbuf initializations at the device side. */
+ /* Send dummy intr to device here, only if support for split data/ctrl rings is disabled */
+ /* Else send the dummy initialization intr at dtoh ctrl buf init */
+
+ dhd_bus_ringbell(dhd->bus, PCIE_INTB);
+ return 0;
+}
+
+/* Allocate space for HTOD ctrl ring on host and initialize handle/doorbell for the same */
+static int dhd_msgbuf_init_htod_ctrl(dhd_pub_t *dhd)
+{
+ uint alloced;
+ dhd_prot_t *prot = dhd->prot;
+ prot->htod_ctrlbuf = MALLOC(dhd->osh, sizeof(circularbuf_t));
+ memset(prot->htod_ctrlbuf, 0, sizeof(circularbuf_t));
+
+ prot->htod_ctrl_ring = DMA_ALLOC_CONSISTENT(dhd->osh, HOST_TO_DNGL_CTRLRING_SZ, 4,
+ &alloced, &prot->htod_ctrl_physaddr, NULL);
+ if (prot->htod_ctrl_ring == NULL) {
+ return BCME_NOMEM;
+ }
+
+ ASSERT(MODX((unsigned long)prot->htod_ctrl_ring, 4) == 0);
+
+ circularbuf_init(prot->htod_ctrlbuf, prot->htod_ctrl_ring, HOST_TO_DNGL_CTRLRING_SZ);
+ circularbuf_register_cb(prot->htod_ctrlbuf, dhd_ctrlbuf_ringbell, (void *)dhd);
+ dhd_bus_cmn_writeshared(dhd->bus, &prot->htod_ctrl_physaddr,
+ sizeof(prot->htod_ctrl_physaddr), HOST_TO_DNGL_CTRLBUF_ADDR);
+
+ dhd_bus_cmn_writeshared(dhd->bus, &(CIRCULARBUF_WRITE_PTR(prot->htod_ctrlbuf)),
+ sizeof(uint32), HTOD_CTRL_WPTR);
+
+ return 0;
+}
+/* Allocate space for DTOH ctrl ring on host and initialize msgbuf handle in dhd_prot_t */
+static int dhd_msgbuf_init_dtoh_ctrl(dhd_pub_t *dhd)
+{
+ uint alloced;
+ dhd_prot_t *prot = dhd->prot;
+ prot->dtoh_ctrlbuf = MALLOC(dhd->osh, sizeof(circularbuf_t));
+ memset(prot->dtoh_ctrlbuf, 0, sizeof(circularbuf_t));
+
+ prot->dtoh_ctrl_ring = DMA_ALLOC_CONSISTENT(dhd->osh, DNGL_TO_HOST_CTRLRING_SZ, 4,
+ &alloced, &prot->dtoh_ctrl_physaddr, NULL);
+ if (prot->dtoh_ctrl_ring == NULL) {
+ return BCME_NOMEM;
+ }
+ ASSERT(MODX((unsigned long)prot->dtoh_ctrl_ring, 4) == 0);
+
+ circularbuf_init(prot->dtoh_ctrlbuf, prot->dtoh_ctrl_ring, DNGL_TO_HOST_CTRLRING_SZ);
+ dhd_bus_cmn_writeshared(dhd->bus, &prot->dtoh_ctrl_physaddr,
+ sizeof(prot->dtoh_ctrl_physaddr), DNGL_TO_HOST_CTRLBUF_ADDR);
+
+ dhd_bus_cmn_writeshared(dhd->bus, &(CIRCULARBUF_READ_PTR(prot->dtoh_ctrlbuf)),
+ sizeof(uint32), DTOH_CTRL_RPTR);
+ return 0;
+}
+
+int BCMFASTPATH
+dhd_prot_process_msgbuf(dhd_pub_t *dhd)
+{
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *dtoh_msgbuf = (circularbuf_t *)prot->dtohbuf;
+
+ dhd_bus_cmn_readshared(dhd->bus, &CIRCULARBUF_WRITE_PTR(dtoh_msgbuf), DNGL_TO_HOST_WPTR);
+
+ /* Process all the messages - DTOH direction */
+ while (TRUE) {
+ uint8 *src_addr;
+ uint16 src_len;
+
+ src_addr = circularbuf_get_read_ptr(dtoh_msgbuf, &src_len);
+ if (src_addr == NULL)
+ break;
+
+ /* Prefetch data to populate the cache */
+ OSL_PREFETCH(src_addr);
+
+ dhd_prot_process_msgtype(dhd, src_addr, src_len);
+ circularbuf_read_complete(dtoh_msgbuf, src_len);
+
+ /* Write to dngl rd ptr */
+ dhd_bus_cmn_writeshared(dhd->bus, &CIRCULARBUF_READ_PTR(dtoh_msgbuf),
+ sizeof(uint16), DNGL_TO_HOST_RPTR);
+ }
+
+ return 0;
+}
+
+int BCMFASTPATH
+dhd_prot_process_ctrlbuf(dhd_pub_t * dhd)
+{
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *dtoh_ctrlbuf = (circularbuf_t *)prot->dtoh_ctrlbuf;
+
+ dhd_bus_cmn_readshared(dhd->bus, &CIRCULARBUF_WRITE_PTR(dtoh_ctrlbuf), DTOH_CTRL_WPTR);
+
+ /* Process all the messages - DTOH direction */
+ while (TRUE) {
+ uint8 *src_addr;
+ uint16 src_len;
+
+ src_addr = circularbuf_get_read_ptr(dtoh_ctrlbuf, &src_len);
+ if (src_addr == NULL) {
+ break;
+ }
+ /* Prefetch data to populate the cache */
+ OSL_PREFETCH(src_addr);
+
+ dhd_prot_process_msgtype(dhd, src_addr, src_len);
+ circularbuf_read_complete(dtoh_ctrlbuf, src_len);
+
+ /* Write to dngl rd ptr */
+ dhd_bus_cmn_writeshared(dhd->bus, &CIRCULARBUF_READ_PTR(dtoh_ctrlbuf),
+ sizeof(uint16), DTOH_CTRL_RPTR);
+ }
+
+ return 0;
+}
+
+static void BCMFASTPATH
+dhd_prot_process_msgtype(dhd_pub_t *dhd, uint8* buf, uint16 len)
+{
+ dhd_prot_t *prot = dhd->prot;
+ uint32 cur_dma_len = 0;
+
+ DHD_TRACE(("%s: process msgbuf of len %d\n", __FUNCTION__, len));
+
+ while (len > 0) {
+ ASSERT(len > (sizeof(cmn_msg_hdr_t) + prot->rx_dataoffset));
+ if (prot->rx_dataoffset) {
+ cur_dma_len = *(uint32 *) buf;
+ ASSERT(cur_dma_len <= len);
+ buf += prot->rx_dataoffset;
+ len -= (uint16)prot->rx_dataoffset;
+ }
+ else {
+ cur_dma_len = len;
+ }
+ dhd_process_msgtype(dhd, buf, (uint16)cur_dma_len);
+ len -= (uint16)cur_dma_len;
+ buf += cur_dma_len;
+ }
+}
+
+
+static void
+dhd_check_sequence_num(cmn_msg_hdr_t *msg)
+{
+ static uint32 ioctl_seq_no_old = 0;
+ static uint32 data_seq_no_old = 0;
+
+ switch (msg->msgtype) {
+ case MSG_TYPE_IOCTL_CMPLT:
+ if (msg->u.seq.seq_no && msg->u.seq.seq_no != (ioctl_seq_no_old + 1))
+ {
+ DHD_ERROR(("Error in IOCTL MsgBuf Sequence number!!"
+ "new seq no %u, old seq number %u\n",
+ msg->u.seq.seq_no, ioctl_seq_no_old));
+ }
+ ioctl_seq_no_old = msg->u.seq.seq_no;
+ break;
+
+ case MSG_TYPE_RX_CMPLT:
+ case MSG_TYPE_WL_EVENT :
+ case MSG_TYPE_TX_STATUS :
+ case MSG_TYPE_LOOPBACK:
+ if (msg->u.seq.seq_no && msg->u.seq.seq_no != (data_seq_no_old + 1))
+ {
+ DHD_ERROR(("Error in DATA MsgBuf Sequence number!!"
+ "new seq no %u old seq number %u\n",
+ msg->u.seq.seq_no, data_seq_no_old));
+ }
+ data_seq_no_old = msg->u.seq.seq_no;
+ break;
+
+ default:
+ printf("Unknown MSGTYPE in %s \n", __FUNCTION__);
+ break;
+
+ }
+}
+
+static void BCMFASTPATH
+dhd_process_msgtype(dhd_pub_t *dhd, uint8* buf, uint16 len)
+{
+ uint16 pktlen = len;
+ uint16 msglen;
+ uint8 msgtype;
+ cmn_msg_hdr_t *msg = NULL;
+ while (pktlen > 0) {
+ msg = (cmn_msg_hdr_t *)buf;
+ msgtype = msg->msgtype;
+ msglen = msg->msglen;
+
+ /* Prefetch data to populate the cache */
+ OSL_PREFETCH(buf+msglen);
+
+ dhd_check_sequence_num(msg);
+
+ DHD_INFO(("msgtype %d, msglen is %d \n", msgtype, msglen));
+ switch (msgtype) {
+ case MSG_TYPE_IOCTL_CMPLT:
+ DHD_INFO((" MSG_TYPE_IOCTL_CMPLT\n"));
+ dhd_prot_ioctcmplt_process(dhd, buf);
+ break;
+ case MSG_TYPE_RX_CMPLT:
+ DHD_INFO((" MSG_TYPE_RX_CMPLT\n"));
+ dhd_prot_rxcmplt_process(dhd, buf);
+ break;
+ case MSG_TYPE_WL_EVENT:
+ DHD_INFO((" MSG_TYPE_WL_EVENT\n"));
+ dhd_prot_event_process(dhd, buf, msglen);
+ break;
+ case MSG_TYPE_TX_STATUS:
+ DHD_INFO((" MSG_TYPE_TX_STATUS\n"));
+ dhd_prot_txstatus_process(dhd, buf);
+ break;
+ case MSG_TYPE_LOOPBACK:
+ bcm_print_bytes("LPBK RESP: ", (uint8 *)msg, msglen);
+ DHD_ERROR((" MSG_TYPE_LOOPBACK, len %d\n", msglen));
+ break;
+ default :
+ DHD_ERROR(("Unknown state in %s,"
+ "rxoffset %d\n", __FUNCTION__, dhd->prot->rx_dataoffset));
+ bcm_print_bytes("UNKNOWN msg", (uchar *)msg, msglen);
+ break;
+
+ }
+
+ DHD_INFO(("pktlen is %d, msglen is %d\n", pktlen, msglen));
+ if (pktlen < msglen) {
+ return;
+ }
+ pktlen = pktlen - msglen;
+ buf = buf + msglen;
+ }
+}
+static void
+dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void * buf)
+{
+ uint32 retlen, status, inline_data = 0;
+ uint32 pkt_id, xt_id;
+
+ ioct_resp_hdr_t * ioct_resp = (ioct_resp_hdr_t *)buf;
+ retlen = ltoh32(ioct_resp->ret_len);
+ pkt_id = ltoh32(ioct_resp->pkt_id);
+ xt_id = ltoh32(ioct_resp->xt_id);
+ status = ioct_resp->status;
+ if (retlen <= 4) {
+ inline_data = ltoh32(ioct_resp->inline_data);
+ } else {
+ OSL_CACHE_INV((void *) dhd->prot->retbuf, retlen);
+ }
+ DHD_CTL(("status from the pkt_id is %d, ioctl is %d, ret_len is %d, xt_id %d\n",
+ pkt_id, status, retlen, xt_id));
+
+ if (retlen == 0)
+ retlen = 1;
+
+ dhd_bus_update_retlen(dhd->bus, retlen, pkt_id, status, inline_data);
+ dhd_os_ioctl_resp_wake(dhd);
+}
+
+static void BCMFASTPATH
+dhd_prot_txstatus_process(dhd_pub_t *dhd, void * buf)
+{
+ dhd_prot_t *prot = dhd->prot;
+ txstatus_hdr_t * txstatus;
+ unsigned long flags;
+ uint32 pktid;
+
+ /* locks required to protect circular buffer accesses */
+ flags = dhd_os_spin_lock(dhd);
+
+ txstatus = (txstatus_hdr_t *)buf;
+ pktid = ltoh32(txstatus->pktid);
+
+ prot->active_tx_count--;
+
+ ASSERT(pktid != 0);
+ dhd_prot_packet_free(dhd, pktid);
+
+ if (prot->txflow_en == TRUE) {
+ /* If the pktpool availability is above the high watermark, */
+ /* let's resume the flow of packets to dongle. */
+ if ((prot->max_tx_count - prot->active_tx_count) > DHD_START_QUEUE_THRESHOLD) {
+ dhd_bus_start_queue(dhd->bus);
+ prot->txflow_en = FALSE;
+ }
+ }
+
+ dhd_os_spin_unlock(dhd, flags);
+ return;
+}
+
+static void
+dhd_prot_event_process(dhd_pub_t *dhd, uint8* buf, uint16 len)
+{
+ wl_event_hdr_t * evnt;
+ uint32 bufid;
+ uint16 buflen;
+ int ifidx = 0;
+ uint pkt_count = 1;
+ void* pkt;
+ unsigned long flags;
+
+ /* Event complete header */
+ evnt = (wl_event_hdr_t *)buf;
+ bufid = ltoh32(evnt->rxbufid);
+ buflen = ltoh16(evnt->retbuf_len);
+
+ /* Post another rxbuf to the device */
+ dhd_prot_return_rxbuf(dhd, 1);
+
+ /* locks required to protect pktid_map */
+ flags = dhd_os_spin_lock(dhd);
+
+ pkt = dhd_prot_packet_get(dhd, ltoh32(bufid));
+
+ dhd_os_spin_unlock(dhd, flags);
+
+ /* DMA RX offset updated through shared area */
+ if (dhd->prot->rx_dataoffset)
+ PKTPULL(dhd->osh, pkt, dhd->prot->rx_dataoffset);
+
+ PKTSETLEN(dhd->osh, pkt, buflen);
+
+ /* remove WL header */
+ PKTPULL(dhd->osh, pkt, 4); /* WL Header */
+
+ dhd_bus_rx_frame(dhd->bus, pkt, ifidx, pkt_count);
+}
+
+static void BCMFASTPATH
+dhd_prot_rxcmplt_process(dhd_pub_t *dhd, void* buf)
+{
+ rxcmplt_hdr_t *rxcmplt_h;
+ rxcmplt_tup_t *rx_tup;
+ uint32 bufid;
+ uint16 buflen, cmpltcnt;
+ uint16 data_offset; /* offset at which data starts */
+ void * pkt;
+ int ifidx = 0;
+ uint pkt_count = 0;
+ uint32 i;
+ void *pkthead = NULL;
+ void *pkttail = NULL;
+
+ /* RXCMPLT HDR */
+ rxcmplt_h = (rxcmplt_hdr_t *)buf;
+ cmpltcnt = ltoh16(rxcmplt_h->rxcmpltcnt);
+
+ /* Post another set of rxbufs to the device */
+ dhd_prot_return_rxbuf(dhd, cmpltcnt);
+ ifidx = rxcmplt_h->msg.ifidx;
+
+ rx_tup = (rxcmplt_tup_t *) &(rxcmplt_h->rx_tup[0]);
+ for (i = 0; i < cmpltcnt; i++) {
+ unsigned long flags;
+
+ bufid = ltoh32(rx_tup->rxbufid);
+ buflen = ltoh16(rx_tup->retbuf_len);
+
+ /* offset from which data starts is populated in rxstatus0 */
+ data_offset = ltoh16(rx_tup->data_offset);
+
+ /* locks required to protect pktid_map */
+ flags = dhd_os_spin_lock(dhd);
+ pkt = dhd_prot_packet_get(dhd, ltoh32(bufid));
+ dhd_os_spin_unlock(dhd, flags);
+
+ /* data_offset from buf start */
+ if (data_offset) {
+ /* data offset given from dongle after split rx */
+ PKTPULL(dhd->osh, pkt, data_offset); /* data offset */
+ } else {
+ /* DMA RX offset updated through shared area */
+ if (dhd->prot->rx_dataoffset)
+ PKTPULL(dhd->osh, pkt, dhd->prot->rx_dataoffset);
+ }
+
+ /* Actual length of the packet */
+ PKTSETLEN(dhd->osh, pkt, buflen);
+
+ /* remove WL header */
+ PKTPULL(dhd->osh, pkt, 4); /* WL Header */
+
+ pkt_count++;
+ rx_tup++;
+
+ /* Chain the packets and release in one shot to dhd_linux. */
+ /* Interface and destination checks are not required here. */
+ PKTSETNEXT(dhd->osh, pkt, NULL);
+ if (pkttail == NULL) {
+ pkthead = pkttail = pkt;
+ } else {
+ PKTSETNEXT(dhd->osh, pkttail, pkt);
+ pkttail = pkt;
+ }
+ }
+
+ if (pkthead) {
+ /* Release the packets to dhd_linux */
+ dhd_bus_rx_frame(dhd->bus, pkthead, ifidx, pkt_count);
+ }
+}
+/* Stop protocol: sync w/dongle state. */
+void dhd_prot_stop(dhd_pub_t *dhd)
+{
+ /* nothing to do for pcie */
+}
+
+/* Add any protocol-specific data header.
+ * Caller must reserve prot_hdrlen prepend space.
+ */
+void dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *PKTBUF)
+{
+ return;
+}
+
+#define PKTBUF pktbuf
+
+int BCMFASTPATH
+dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx)
+{
+ unsigned long flags;
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *htod_msgbuf = (circularbuf_t *)prot->htodbuf;
+ txdescr_msghdr_t *txdesc = NULL;
+ tx_lenptr_tup_t *tx_tup;
+ dmaaddr_t physaddr;
+ uint8 *pktdata;
+ uint8 *etherhdr;
+ uint16 pktlen;
+ uint16 hdrlen;
+ uint32 pktid;
+
+ /* Extract the data pointer and length information */
+ pktdata = PKTDATA(dhd->osh, PKTBUF);
+ pktlen = (uint16)PKTLEN(dhd->osh, PKTBUF);
+
+ /* Extract the ethernet header and adjust the data pointer and length */
+ etherhdr = pktdata;
+ pktdata += ETHER_HDR_LEN;
+ pktlen -= ETHER_HDR_LEN;
+
+
+ flags = dhd_os_spin_lock(dhd);
+
+ /* Map the data pointer to a DMA-able address */
+ physaddr = DMA_MAP(dhd->osh, pktdata, pktlen, DMA_TX, 0, 0);
+ if (physaddr == 0) {
+ DHD_ERROR(("Something really bad, unless 0 is a valid phyaddr\n"));
+ ASSERT(0);
+ }
+
+ /* Create a unique 32-bit packet id */
+ pktid = NATIVE_TO_PKTID(dhd->prot->pktid_map_handle, PKTBUF, physaddr, pktlen, DMA_TX);
+
+ /* Reserve space in the circular buffer */
+ hdrlen = sizeof(txdescr_msghdr_t) + (1 * sizeof(tx_lenptr_tup_t));
+
+ txdesc = (txdescr_msghdr_t *)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, hdrlen, HOST_TO_DNGL_DATA);
+ if (txdesc == NULL) {
+ dhd_prot_packet_free(dhd, pktid);
+ dhd_os_spin_unlock(dhd, flags);
+
+ DHD_INFO(("%s:%d: HTOD Msgbuf Not available TxCount = %d\n",
+ __FUNCTION__, __LINE__, prot->active_tx_count));
+ return BCME_NORESOURCE;
+ }
+
+ /* Form the Tx descriptor message buffer */
+
+ /* Common message hdr */
+ txdesc->txcmn.msg.msglen = htol16(hdrlen);
+ txdesc->txcmn.msg.msgtype = MSG_TYPE_TX_POST;
+ txdesc->txcmn.msg.u.seq.seq_no = htol16(++prot->data_seq_no);
+
+ /* Ethernet header */
+ txdesc->txcmn.hdrlen = htol16(ETHER_HDR_LEN);
+ bcopy(etherhdr, txdesc->txhdr, ETHER_HDR_LEN);
+
+ /* Packet ID */
+ txdesc->txcmn.pktid = htol32(pktid);
+
+ /* Descriptor count - Linux needs only one */
+ txdesc->txcmn.descrcnt = 0x1;
+
+ tx_tup = (tx_lenptr_tup_t *) &(txdesc->tx_tup);
+
+ /* Descriptor - 0 */
+ tx_tup->pktlen = htol16(pktlen);
+ tx_tup->ret_buf.high_addr = htol32(PHYSADDRHI(physaddr));
+ tx_tup->ret_buf.low_addr = htol32(PHYSADDRLO(physaddr));
+ /* Descriptor 1 - should be filled here - if required */
+
+ /* Reserved for future use */
+ txdesc->txcmn.priority = (uint8)PKTPRIO(PKTBUF);
+ txdesc->txcmn.flowid = 0;
+ txdesc->txcmn.msg.ifidx = ifidx;
+
+ /* Since, we are filling the data directly into the bufptr obtained
+ * from the circularbuf, we can directly call the write_complete
+ */
+ circularbuf_write_complete(htod_msgbuf, hdrlen);
+
+ prot->active_tx_count++;
+
+ /* If we have accounted for most of the lfrag packets on the dongle, */
+ /* it's time to stop the packet flow - Assert flow control. */
+ if ((prot->max_tx_count - prot->active_tx_count) < DHD_STOP_QUEUE_THRESHOLD) {
+ dhd_bus_stop_queue(dhd->bus);
+ prot->txflow_en = TRUE;
+ }
+
+ dhd_os_spin_unlock(dhd, flags);
+
+ return BCME_OK;
+}
+
+#undef PKTBUF /* Only defined in the above routine */
+int dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pkt, uchar *buf, uint *len)
+{
+ return 0;
+}
+
+static void BCMFASTPATH
+dhd_prot_return_rxbuf(dhd_pub_t *dhd, uint16 rxcnt)
+{
+ dhd_prot_t *prot = dhd->prot;
+
+ prot->rxbufpost -= rxcnt;
+ if (prot->rxbufpost <= (prot->max_rxbufpost - RXBUFPOST_THRESHOLD))
+ dhd_msgbuf_rxbuf_post(dhd);
+
+ return;
+}
+
+/* Use protocol to issue ioctl to dongle */
+int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
+{
+ dhd_prot_t *prot = dhd->prot;
+ int ret = -1;
+ uint8 action;
+
+ if ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent) {
+ DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
+ goto done;
+ }
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ASSERT(len <= WLC_IOCTL_MAXLEN);
+
+ if (len > WLC_IOCTL_MAXLEN)
+ goto done;
+
+ if (prot->pending == TRUE) {
+ DHD_ERROR(("packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n",
+ ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
+ (unsigned long)prot->lastcmd));
+ if ((ioc->cmd == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR)) {
+ DHD_TRACE(("iovar cmd=%s\n", (char*)buf));
+ }
+ goto done;
+ }
+
+ prot->pending = TRUE;
+ prot->lastcmd = ioc->cmd;
+ action = ioc->set;
+ if (action & WL_IOCTL_ACTION_SET) {
+ ret = dhd_msgbuf_set_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
+ } else {
+ ret = dhdmsgbuf_query_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
+ if (ret > 0)
+ ioc->used = ret;
+ }
+ /* Too many programs assume ioctl() returns 0 on success */
+ if (ret >= 0)
+ ret = 0;
+ else {
+ DHD_INFO(("%s: status ret value is %d \n", __FUNCTION__, ret));
+ dhd->dongle_error = ret;
+ }
+
+ /* Intercept the wme_dp ioctl here */
+ if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) {
+ int slen, val = 0;
+
+ slen = strlen("wme_dp") + 1;
+ if (len >= (int)(slen + sizeof(int)))
+ bcopy(((char *)buf + slen), &val, sizeof(int));
+ dhd->wme_dp = (uint8) ltoh32(val);
+ }
+
+ prot->pending = FALSE;
+
+done:
+ return ret;
+
+}
+
+int
+dhdmsgbuf_lpbk_req(dhd_pub_t *dhd, uint len)
+{
+ unsigned long flags;
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *htod_msgbuf;
+
+ ioct_reqst_hdr_t *ioct_rqst;
+
+ uint16 hdrlen = sizeof(ioct_reqst_hdr_t);
+ uint16 msglen = len + hdrlen;
+
+ if (dhd->prot->htodsplit)
+ htod_msgbuf = (circularbuf_t *) prot->htod_ctrlbuf;
+ else
+ htod_msgbuf = (circularbuf_t *) prot->htodbuf;
+
+ if (msglen > MSGBUF_MAX_MSG_SIZE)
+ msglen = MSGBUF_MAX_MSG_SIZE;
+
+ msglen = align(msglen, 4);
+
+ /* locks required to protect circular buffer accesses */
+ flags = dhd_os_spin_lock(dhd);
+
+ if (dhd->prot->htodsplit) {
+ ioct_rqst = (ioct_reqst_hdr_t *)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, msglen, HOST_TO_DNGL_CTRL);
+ }
+ else {
+ ioct_rqst = (ioct_reqst_hdr_t *)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, msglen, HOST_TO_DNGL_DATA);
+ }
+
+ if (ioct_rqst == NULL) {
+ dhd_os_spin_unlock(dhd, flags);
+ return 0;
+ }
+
+ {
+ uint8 *ptr;
+ uint16 i;
+
+ ptr = (uint8 *)ioct_rqst;
+ for (i = 0; i < msglen; i++) {
+ ptr[i] = i % 256;
+ }
+ }
+
+
+ /* Common msg buf hdr */
+ ioct_rqst->msg.msglen = htol16(msglen);
+ ioct_rqst->msg.msgtype = MSG_TYPE_LOOPBACK;
+ ioct_rqst->msg.ifidx = 0;
+ ioct_rqst->msg.u.seq.seq_no = htol16(++prot->data_seq_no);
+
+ bcm_print_bytes("LPBK REQ: ", (uint8 *)ioct_rqst, msglen);
+
+ circularbuf_write_complete(htod_msgbuf, msglen);
+
+ dhd_os_spin_unlock(dhd, flags);
+
+ return 0;
+}
+
+
+static int
+dhdmsgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
+{
+ dhd_prot_t *prot = dhd->prot;
+
+ int ret = 0;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* Respond "bcmerror" and "bcmerrorstr" with local cache */
+ if (cmd == WLC_GET_VAR && buf)
+ {
+ if (!strcmp((char *)buf, "bcmerrorstr"))
+ {
+ strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN);
+ goto done;
+ }
+ else if (!strcmp((char *)buf, "bcmerror"))
+ {
+ *(int *)buf = dhd->dongle_error;
+ goto done;
+ }
+ }
+
+ /* Fill up msgbuf for ioctl req */
+ if (len < MAX_INLINE_IOCTL_LEN) {
+ /* Inline ioct resuest */
+ ret = dhd_fillup_ioct_reqst(dhd, (uint16)len, cmd, buf, ifidx);
+ } else {
+ /* Non inline ioct resuest */
+ ret = dhd_fillup_ioct_reqst_ptrbased(dhd, (uint16)len, cmd, buf, ifidx);
+ }
+
+ DHD_INFO(("ACTION %d ifdix %d cmd %d len %d \n",
+ action, ifidx, cmd, len));
+
+ /* wait for interrupt and get first fragment */
+ ret = dhdmsgbuf_cmplt(dhd, prot->reqid, len, buf, prot->retbuf);
+
+done:
+ return ret;
+}
+static int
+dhdmsgbuf_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len, void* buf, void* retbuf)
+{
+ dhd_prot_t *prot = dhd->prot;
+ ioct_resp_hdr_t ioct_resp;
+ uint8* data;
+ int retlen;
+ int msgbuf_len = 0;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ retlen = dhd_bus_rxctl(dhd->bus, (uchar*)&ioct_resp, msgbuf_len);
+
+ if (retlen <= 0)
+ return -1;
+
+ /* get ret buf */
+ if (buf != NULL) {
+ if (retlen <= 4) {
+ bcopy((void*)&ioct_resp.inline_data, buf, retlen);
+ DHD_INFO(("%s: data is %d, ret_len is %d\n",
+ __FUNCTION__, ioct_resp.inline_data, retlen));
+ }
+ else {
+ data = (uint8*)retbuf;
+ bcopy((void*)&data[prot->rx_dataoffset], buf, retlen);
+ }
+ }
+ return ioct_resp.status;
+}
+static int
+dhd_msgbuf_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
+{
+ dhd_prot_t *prot = dhd->prot;
+
+ int ret = 0;
+
+ DHD_TRACE(("%s: Enter \n", __FUNCTION__));
+ DHD_TRACE(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
+
+ if (dhd->busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
+ return -EIO;
+ }
+
+ /* don't talk to the dongle if fw is about to be reloaded */
+ if (dhd->hang_was_sent) {
+ DHD_ERROR(("%s: HANG was sent up earlier. Not talking to the chip\n",
+ __FUNCTION__));
+ return -EIO;
+ }
+
+ /* Fill up msgbuf for ioctl req */
+ if (len < MAX_INLINE_IOCTL_LEN) {
+ /* Inline ioct resuest */
+ ret = dhd_fillup_ioct_reqst(dhd, (uint16)len, cmd, buf, ifidx);
+ } else {
+ /* Non inline ioct resuest */
+ ret = dhd_fillup_ioct_reqst_ptrbased(dhd, (uint16)len, cmd, buf, ifidx);
+ }
+
+ DHD_INFO(("ACTIOn %d ifdix %d cmd %d len %d \n",
+ action, ifidx, cmd, len));
+
+ ret = dhdmsgbuf_cmplt(dhd, prot->reqid, len, buf, prot->retbuf);
+
+ return ret;
+}
+/* Handles a protocol control response asynchronously */
+int dhd_prot_ctl_complete(dhd_pub_t *dhd)
+{
+ return 0;
+}
+
+/* Check for and handle local prot-specific iovar commands */
+int dhd_prot_iovar_op(dhd_pub_t *dhd, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
+{
+ return BCME_UNSUPPORTED;
+}
+
+/* Add prot dump output to a buffer */
+void dhd_prot_dump(dhd_pub_t *dhd, struct bcmstrbuf *strbuf)
+{
+
+}
+
+/* Update local copy of dongle statistics */
+void dhd_prot_dstats(dhd_pub_t *dhd)
+{
+ return;
+}
+
+int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf,
+ uint reorder_info_len, void **pkt, uint32 *free_buf_count)
+{
+ return 0;
+}
+/* post a dummy message to interrupt dongle */
+/* used to process cons commands */
+int
+dhd_post_dummy_msg(dhd_pub_t *dhd)
+{
+ unsigned long flags;
+ hostevent_hdr_t *hevent = NULL;
+ uint16 msglen = sizeof(hostevent_hdr_t);
+
+ dhd_prot_t *prot = dhd->prot;
+ circularbuf_t *htod_msgbuf;
+
+ /* locks required to protect circular buffer accesses */
+ flags = dhd_os_spin_lock(dhd);
+ if (dhd->prot->htodsplit) {
+ htod_msgbuf = (circularbuf_t *)prot->htod_ctrlbuf;
+ hevent = (hostevent_hdr_t *)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, msglen, HOST_TO_DNGL_CTRL);
+ }
+ else {
+ htod_msgbuf = (circularbuf_t *)prot->htodbuf;
+ hevent = (hostevent_hdr_t *)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, msglen, HOST_TO_DNGL_DATA);
+ }
+
+ if (hevent == NULL) {
+ dhd_os_spin_unlock(dhd, flags);
+ return -1;
+ }
+
+ /* CMN msg header */
+ hevent->msg.msglen = htol16(msglen);
+ hevent->msg.msgtype = MSG_TYPE_HOST_EVNT;
+ hevent->msg.ifidx = 0;
+ hevent->msg.u.seq.seq_no = htol16(++prot->data_seq_no);
+
+ /* Event payload */
+ hevent->evnt_pyld = htol32(HOST_EVENT_CONS_CMD);
+
+ /* Since, we are filling the data directly into the bufptr obtained
+ * from the msgbuf, we can directly call the write_complete
+ */
+ circularbuf_write_complete(htod_msgbuf, msglen);
+ dhd_os_spin_unlock(dhd, flags);
+
+ return 0;
+}
+void * BCMFASTPATH
+dhd_alloc_circularbuf_space(dhd_pub_t *dhd, circularbuf_t *handle, uint16 msglen, uint path)
+{
+ void * ret_buf;
+
+ ret_buf = circularbuf_reserve_for_write(handle, msglen);
+ if (ret_buf == NULL) {
+ /* Try again after updating the read ptr from dongle */
+ if (path == HOST_TO_DNGL_DATA)
+ dhd_bus_cmn_readshared(dhd->bus, &(CIRCULARBUF_READ_PTR(handle)),
+ HOST_TO_DNGL_RPTR);
+ else if (path == HOST_TO_DNGL_CTRL)
+ dhd_bus_cmn_readshared(dhd->bus, &(CIRCULARBUF_READ_PTR(handle)),
+ HTOD_CTRL_RPTR);
+ else
+ DHD_ERROR(("%s:%d: Unknown path value \n", __FUNCTION__, __LINE__));
+ ret_buf = circularbuf_reserve_for_write(handle, msglen);
+ if (ret_buf == NULL) {
+ DHD_INFO(("%s:%d: HTOD Msgbuf Not available \n", __FUNCTION__, __LINE__));
+ return NULL;
+ }
+ }
+
+ return ret_buf;
+}
+INLINE bool
+dhd_prot_dtohsplit(dhd_pub_t* dhd)
+{
+ return dhd->prot->dtohsplit;
+}
+static int
+dhd_fillup_ioct_reqst(dhd_pub_t *dhd, uint16 len, uint cmd, void* buf, int ifidx)
+{
+ dhd_prot_t *prot = dhd->prot;
+ ioct_reqst_hdr_t *ioct_rqst;
+ uint16 hdrlen = sizeof(ioct_reqst_hdr_t);
+ uint16 msglen = len + hdrlen;
+ circularbuf_t *htod_msgbuf;
+ unsigned long flags;
+ uint16 rqstlen = len;
+
+ /* Limit ioct request to MSGBUF_MAX_MSG_SIZE bytes including hdrs */
+ if (rqstlen + hdrlen > MSGBUF_MAX_MSG_SIZE)
+ rqstlen = MSGBUF_MAX_MSG_SIZE - hdrlen;
+
+ /* Messge = hdr + rqstbuf */
+ msglen = rqstlen + hdrlen;
+
+ /* align it to 4 bytes, so that all start addr form cbuf is 4 byte aligned */
+ msglen = align(msglen, 4);
+
+ /* locks required to protect circular buffer accesses */
+ flags = dhd_os_spin_lock(dhd);
+
+ /* Request for cbuf space */
+ if (dhd->prot->htodsplit) {
+ htod_msgbuf = (circularbuf_t *)prot->htod_ctrlbuf;
+ ioct_rqst = (ioct_reqst_hdr_t *)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, msglen, HOST_TO_DNGL_CTRL);
+ }
+ else {
+ htod_msgbuf = (circularbuf_t *)prot->htodbuf;
+ ioct_rqst = (ioct_reqst_hdr_t *)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, msglen, HOST_TO_DNGL_DATA);
+ }
+
+ if (ioct_rqst == NULL) {
+ dhd_os_spin_unlock(dhd, flags);
+ return -1;
+ }
+
+ /* Common msg buf hdr */
+ ioct_rqst->msg.msglen = htol16(msglen);
+ ioct_rqst->msg.msgtype = MSG_TYPE_IOCTL_REQ;
+ ioct_rqst->msg.ifidx = (uint8)ifidx;
+ ioct_rqst->msg.u.seq.seq_no = htol16(++prot->ioctl_seq_no);
+
+ /* Ioctl specific Message buf header */
+ ioct_rqst->ioct_hdr.cmd = htol32(cmd);
+ ioct_rqst->ioct_hdr.pkt_id = htol32(++prot->reqid);
+ ioct_rqst->ioct_hdr.retbuf_len = htol16(len);
+ ioct_rqst->ioct_hdr.xt_id = (uint16)ioct_rqst->ioct_hdr.pkt_id;
+ DHD_CTL(("sending IOCTL_REQ cmd %d, pkt_id %d xt_id %d\n",
+ ioct_rqst->ioct_hdr.cmd, ioct_rqst->ioct_hdr.pkt_id, ioct_rqst->ioct_hdr.xt_id));
+
+ /* Ret buf ptr */
+ ioct_rqst->ret_buf.high_addr = htol32(PHYSADDRHI(prot->retbuf_phys));
+ ioct_rqst->ret_buf.low_addr = htol32(PHYSADDRLO(prot->retbuf_phys));
+
+ /* copy ioct payload */
+ if (buf)
+ memcpy(&ioct_rqst[1], buf, rqstlen);
+
+ /* upd wrt ptr and raise interrupt */
+ circularbuf_write_complete(htod_msgbuf, msglen);
+ dhd_os_spin_unlock(dhd, flags);
+
+ return 0;
+}
+/* Non inline ioct request */
+/* Form a ioctl request first as per ioctptr_reqst_hdr_t header in the circular buffer */
+/* Form a separate request buffer where a 4 byte cmn header is added in the front */
+/* buf contents from parent function is copied to remaining section of this buffer */
+static int
+dhd_fillup_ioct_reqst_ptrbased(dhd_pub_t *dhd, uint16 len, uint cmd, void* buf, int ifidx)
+{
+ dhd_prot_t *prot = dhd->prot;
+ ioctptr_reqst_hdr_t *ioct_rqst;
+ uint16 msglen = sizeof(ioctptr_reqst_hdr_t);
+ circularbuf_t * htod_msgbuf;
+ cmn_msg_hdr_t * ioct_buf; /* For ioctl payload */
+ uint16 alignlen, rqstlen = len;
+ unsigned long flags;
+
+ /* Limit ioct request to MSGBUF_MAX_MSG_SIZE bytes including hdrs */
+ if ((rqstlen + sizeof(cmn_msg_hdr_t)) > MSGBUF_MAX_MSG_SIZE)
+ rqstlen = MSGBUF_MAX_MSG_SIZE - sizeof(cmn_msg_hdr_t);
+
+ /* align it to 4 bytes, so that all start addr form cbuf is 4 byte aligned */
+ alignlen = align(rqstlen, 4);
+
+ /* locks required to protect circular buffer accesses */
+ flags = dhd_os_spin_lock(dhd);
+ /* Request for cbuf space */
+ if (dhd->prot->htodsplit) {
+ htod_msgbuf = (circularbuf_t *)prot->htod_ctrlbuf;
+ ioct_rqst = (ioctptr_reqst_hdr_t*)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, msglen, HOST_TO_DNGL_CTRL);
+ }
+ else {
+ htod_msgbuf = (circularbuf_t *)prot->htodbuf;
+ ioct_rqst = (ioctptr_reqst_hdr_t*)dhd_alloc_circularbuf_space(dhd,
+ htod_msgbuf, msglen, HOST_TO_DNGL_DATA);
+ }
+ if (ioct_rqst == NULL) {
+ dhd_os_spin_unlock(dhd, flags);
+ return -1;
+ }
+
+ /* Common msg buf hdr */
+ ioct_rqst->msg.msglen = htol16(msglen);
+ ioct_rqst->msg.msgtype = MSG_TYPE_IOCTLPTR_REQ;
+ ioct_rqst->msg.ifidx = (uint8)ifidx;
+ ioct_rqst->msg.u.seq.seq_no = htol16(++prot->ioctl_seq_no);
+
+ /* Ioctl specific Message buf header */
+ ioct_rqst->ioct_hdr.cmd = htol32(cmd);
+ ioct_rqst->ioct_hdr.pkt_id = htol32(++prot->reqid);
+ ioct_rqst->ioct_hdr.retbuf_len = htol16(len);
+ ioct_rqst->ioct_hdr.xt_id = (uint16)ioct_rqst->ioct_hdr.pkt_id;
+
+ DHD_CTL(("sending IOCTL_PTRREQ cmd %d, pkt_id %d xt_id %d\n",
+ ioct_rqst->ioct_hdr.cmd, ioct_rqst->ioct_hdr.pkt_id, ioct_rqst->ioct_hdr.xt_id));
+
+ /* Ret buf ptr */
+ ioct_rqst->ret_buf.high_addr = htol32(PHYSADDRHI(prot->retbuf_phys));
+ ioct_rqst->ret_buf.low_addr = htol32(PHYSADDRLO(prot->retbuf_phys));
+
+ /* copy ioct payload */
+ ioct_buf = (cmn_msg_hdr_t *) prot->ioctbuf;
+ ioct_buf->msglen = htol16(alignlen + sizeof(cmn_msg_hdr_t));
+ ioct_buf->msgtype = MSG_TYPE_IOCT_PYLD;
+
+ if (buf) {
+ memcpy(&ioct_buf[1], buf, rqstlen);
+ OSL_CACHE_FLUSH((void *) prot->ioctbuf, rqstlen+sizeof(cmn_msg_hdr_t));
+ }
+
+ if ((ulong)ioct_buf % 4)
+ printf("host ioct address unaligned !!!!! \n");
+
+ /* populate ioctl buffer info */
+ ioct_rqst->ioct_hdr.buflen = htol16(alignlen + sizeof(cmn_msg_hdr_t));
+ ioct_rqst->ioct_buf.high_addr = htol32(PHYSADDRHI(prot->ioctbuf_phys));
+ ioct_rqst->ioct_buf.low_addr = htol32(PHYSADDRLO(prot->ioctbuf_phys));
+
+ /* upd wrt ptr and raise interrupt */
+ circularbuf_write_complete(htod_msgbuf, msglen);
+
+ dhd_os_spin_unlock(dhd, flags);
+
+ return 0;
+}
+
+/* Packet to PacketID mapper */
+typedef struct {
+ ulong native;
+ dmaaddr_t pa;
+ uint32 pa_len;
+ uchar dma;
+} pktid_t;
+
+typedef struct {
+ void *osh;
+ void *mwbmap_hdl;
+ pktid_t *pktid_list;
+ uint32 count;
+} pktid_map_t;
+
+
+void *pktid_map_init(void *osh, uint32 count)
+{
+ pktid_map_t *handle;
+
+ handle = (pktid_map_t *) MALLOC(osh, sizeof(pktid_map_t));
+ if (handle == NULL) {
+ printf("%s:%d: MALLOC failed for size %d\n",
+ __FUNCTION__, __LINE__, (uint32) sizeof(pktid_map_t));
+ return NULL;
+ }
+ handle->osh = osh;
+ handle->count = count;
+ handle->mwbmap_hdl = bcm_mwbmap_init(osh, count);
+ if (handle->mwbmap_hdl == NULL) {
+ printf("%s:%d: bcm_mwbmap_init failed for count %d\n",
+ __FUNCTION__, __LINE__, count);
+ MFREE(osh, handle, sizeof(pktid_map_t));
+ return NULL;
+ }
+
+ handle->pktid_list = (pktid_t *) MALLOC(osh, sizeof(pktid_t) * (count+1));
+ if (handle->pktid_list == NULL) {
+ printf("%s:%d: MALLOC failed for count %d / total = %d\n",
+ __FUNCTION__, __LINE__, count, (uint32) sizeof(pktid_t) * count);
+ bcm_mwbmap_fini(osh, handle->mwbmap_hdl);
+ MFREE(osh, handle, sizeof(pktid_map_t));
+ return NULL;
+ }
+
+ return handle;
+}
+
+void
+pktid_map_uninit(void *pktid_map_handle)
+{
+ pktid_map_t *handle = (pktid_map_t *) pktid_map_handle;
+ uint32 ix;
+
+ if (handle != NULL) {
+ void *osh = handle->osh;
+ for (ix = 0; ix < MAX_PKTID_ITEMS; ix++)
+ {
+ if (!bcm_mwbmap_isfree(handle->mwbmap_hdl, ix)) {
+ /* Mark the slot as free */
+ bcm_mwbmap_free(handle->mwbmap_hdl, ix);
+ /*
+ Here we can do dma unmapping for 32 bit also.
+ Since this in removal path, it will not affect performance
+ */
+ DMA_UNMAP(osh, (uint) handle->pktid_list[ix+1].pa,
+ (uint) handle->pktid_list[ix+1].pa_len,
+ handle->pktid_list[ix+1].dma, 0, 0);
+ PKTFREE(osh,
+ (unsigned long*)handle->pktid_list[ix+1].native, TRUE);
+ }
+ }
+ bcm_mwbmap_fini(osh, handle->mwbmap_hdl);
+ MFREE(osh, handle->pktid_list, sizeof(pktid_t) * (handle->count+1));
+ MFREE(osh, handle, sizeof(pktid_map_t));
+ }
+ return;
+}
+
+uint32 BCMFASTPATH
+pktid_map_unique(void *pktid_map_handle, void *pkt, dmaaddr_t physaddr, uint32 physlen, uint32 dma)
+{
+ uint32 id;
+ pktid_map_t *handle = (pktid_map_t *) pktid_map_handle;
+
+ if (handle == NULL) {
+ printf("%s:%d: Error !!! pktid_map_unique called without initing pktid_map\n",
+ __FUNCTION__, __LINE__);
+ return 0;
+ }
+ id = bcm_mwbmap_alloc(handle->mwbmap_hdl);
+ if (id == BCM_MWBMAP_INVALID_IDX) {
+ printf("%s:%d: bcm_mwbmap_alloc failed. Free Count = %d\n",
+ __FUNCTION__, __LINE__, bcm_mwbmap_free_cnt(handle->mwbmap_hdl));
+ return 0;
+ }
+
+ /* id=0 is invalid as we use this for error checking in the dongle */
+ id += 1;
+ handle->pktid_list[id].native = (ulong) pkt;
+ handle->pktid_list[id].pa = physaddr;
+ handle->pktid_list[id].pa_len = (uint32) physlen;
+ handle->pktid_list[id].dma = dma;
+
+ return id;
+}
+
+void * BCMFASTPATH
+pktid_get_packet(void *pktid_map_handle, uint32 id, dmaaddr_t *physaddr, uint32 *physlen)
+{
+ void *native = NULL;
+ pktid_map_t *handle = (pktid_map_t *) pktid_map_handle;
+ if (handle == NULL) {
+ printf("%s:%d: Error !!! pktid_get_packet called without initing pktid_map\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ /* Debug check */
+ if (bcm_mwbmap_isfree(handle->mwbmap_hdl, (id-1))) {
+ printf("%s:%d: Error !!!. How can the slot (%d) be free if the app is using it.\n",
+ __FUNCTION__, __LINE__, (id-1));
+ return NULL;
+ }
+
+ native = (void *) handle->pktid_list[id].native;
+ *physaddr = handle->pktid_list[id].pa;
+ *physlen = (uint32) handle->pktid_list[id].pa_len;
+
+ /* Mark the slot as free */
+ bcm_mwbmap_free(handle->mwbmap_hdl, (id-1));
+
+ return native;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie.c b/drivers/net/wireless/bcmdhd/dhd_pcie.c
new file mode 100644
index 000000000000..ca02e4ecd90b
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_pcie.c
@@ -0,0 +1,2566 @@
+/*
+ * DHD Bus Module for PCIE
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_pcie.c 662459 2016-10-24 04:35:43Z $
+ */
+
+
+/* include files */
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <bcmdevs.h>
+#include <siutils.h>
+#include <hndsoc.h>
+#include <hndpmu.h>
+#include <sbchipc.h>
+#if defined(DHD_DEBUG)
+#include <hndrte_armtrap.h>
+#include <hndrte_cons.h>
+#endif /* defined(DHD_DEBUG) */
+#include <dngl_stats.h>
+#include <pcie_core.h>
+#include <dhd.h>
+#include <dhd_bus.h>
+#include <dhd_proto.h>
+#include <dhd_dbg.h>
+#include <dhdioctl.h>
+#include <sdiovar.h>
+#include <bcmmsgbuf.h>
+#include <pcicfg.h>
+#include <circularbuf.h>
+#include <dhd_pcie.h>
+#include <bcmpcie.h>
+
+#define MEMBLOCK 2048 /* Block size used for downloading of dongle image */
+#define MAX_NVRAMBUF_SIZE 4096 /* max nvram buf size */
+
+#define ARMCR4REG_BANKIDX (0x40/sizeof(uint32))
+#define ARMCR4REG_BANKPDA (0x4C/sizeof(uint32))
+
+int dhd_dongle_memsize;
+int dhd_dongle_ramsize;
+#ifdef DHD_DEBUG
+static int dhdpcie_bus_readconsole(dhd_bus_t *bus);
+#endif
+static int dhdpcie_bus_membytes(dhd_bus_t *bus, bool write, ulong address, uint8 *data, uint size);
+static int dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid,
+ const char *name, void *params,
+ int plen, void *arg, int len, int val_size);
+static int dhdpcie_bus_lpback_req(struct dhd_bus *bus, uint32 intval);
+static int dhdpcie_bus_download_state(dhd_bus_t *bus, bool enter);
+static int _dhdpcie_download_firmware(struct dhd_bus *bus);
+static int dhdpcie_download_firmware(dhd_bus_t *bus, osl_t *osh);
+static int dhdpcie_bus_write_vars(dhd_bus_t *bus);
+static void dhdpcie_bus_process_mailbox_intr(dhd_bus_t *bus, uint32 intstatus);
+static void dhdpci_bus_read_frames(dhd_bus_t *bus);
+static int dhdpcie_readshared(dhd_bus_t *bus);
+static void dhdpcie_init_shared_addr(dhd_bus_t *bus);
+static bool dhdpcie_dongle_attach(dhd_bus_t *bus);
+static void dhdpcie_bus_intr_enable(dhd_bus_t *bus);
+static void dhdpcie_bus_dongle_setmemsize(dhd_bus_t *bus, int mem_size);
+static void dhdpcie_bus_release_dongle(dhd_bus_t *bus, osl_t *osh,
+ bool dongle_isolation, bool reset_flag);
+static void dhdpcie_bus_release_malloc(dhd_bus_t *bus, osl_t *osh);
+static int dhdpcie_downloadvars(dhd_bus_t *bus, void *arg, int len);
+static uint8 dhdpcie_bus_rtcm8(dhd_bus_t *bus, ulong offset);
+static void dhdpcie_bus_wtcm8(dhd_bus_t *bus, ulong offset, uint8 data);
+static void dhdpcie_bus_wtcm16(dhd_bus_t *bus, ulong offset, uint16 data);
+static uint16 dhdpcie_bus_rtcm16(dhd_bus_t *bus, ulong offset);
+static void dhdpcie_bus_wtcm32(dhd_bus_t *bus, ulong offset, uint32 data);
+static uint32 dhdpcie_bus_rtcm32(dhd_bus_t *bus, ulong offset);
+static void dhdpcie_bus_wreg32(dhd_bus_t *bus, uint reg, uint32 data);
+static uint32 dhdpcie_bus_rreg32(dhd_bus_t *bus, uint reg);
+static void dhdpcie_bus_cfg_set_bar0_win(dhd_bus_t *bus, uint32 data);
+static void dhdpcie_bus_reg_unmap(osl_t *osh, ulong addr, int size);
+static int dhdpcie_cc_nvmshadow(dhd_bus_t *bus, struct bcmstrbuf *b);
+static void dhdpcie_send_mb_data(dhd_bus_t *bus, uint32 h2d_mb_data);
+
+#define PCI_VENDOR_ID_BROADCOM 0x14e4
+
+/* IOVar table */
+enum {
+ IOV_INTR = 1,
+ IOV_MEMBYTES,
+ IOV_MEMSIZE,
+ IOV_SET_DOWNLOAD_STATE,
+ IOV_DEVRESET,
+ IOV_VARS,
+ IOV_MSI_SIM,
+ IOV_PCIE_LPBK,
+ IOV_CC_NVMSHADOW,
+ IOV_RAMSIZE,
+ IOV_RAMSTART,
+ IOV_SLEEP_ALLOWED,
+ IOV_PCIEREG,
+ IOV_PCIECFGREG,
+ IOV_PCIECOREREG,
+ IOV_SBREG,
+ IOV_DONGLEISOLATION,
+ IOV_LTRSLEEPON_UNLOOAD
+};
+
+
+const bcm_iovar_t dhdpcie_iovars[] = {
+ {"intr", IOV_INTR, 0, IOVT_BOOL, 0 },
+ {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) },
+ {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0 },
+ {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, IOVT_BOOL, 0 },
+ {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 },
+ {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0 },
+ {"pcie_lpbk", IOV_PCIE_LPBK, 0, IOVT_UINT32, 0 },
+ {"cc_nvmshadow", IOV_CC_NVMSHADOW, 0, IOVT_BUFFER, 0 },
+ {"ramsize", IOV_RAMSIZE, 0, IOVT_UINT32, 0 },
+ {"ramstart", IOV_RAMSTART, 0, IOVT_UINT32, 0 },
+ {"pciereg", IOV_PCIEREG, 0, IOVT_BUFFER, 2 * sizeof(int32) },
+ {"pciecfgreg", IOV_PCIECFGREG, 0, IOVT_BUFFER, 2 * sizeof(int32) },
+ {"pciecorereg", IOV_PCIECOREREG, 0, IOVT_BUFFER, 2 * sizeof(int32) },
+ {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
+ {"sleep_allowed", IOV_SLEEP_ALLOWED, 0, IOVT_BOOL, 0 },
+ {"dngl_isolation", IOV_DONGLEISOLATION, 0, IOVT_UINT32, 0 },
+ {"ltrsleep_on_unload", IOV_LTRSLEEPON_UNLOOAD, 0, IOVT_UINT32, 0 },
+ {NULL, 0, 0, 0, 0 }
+};
+
+#define MAX_READ_TIMEOUT 5 * 1000 * 1000
+
+/* Register/Unregister functions are called by the main DHD entry
+ * point (e.g. module insertion) to link with the bus driver, in
+ * order to look for or await the device.
+ */
+
+int
+dhd_bus_register(void)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ return dhdpcie_bus_register();
+}
+
+void
+dhd_bus_unregister(void)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ dhdpcie_bus_unregister();
+ return;
+}
+
+
+/** returns a host virtual address */
+uint32 *
+dhdpcie_bus_reg_map(osl_t *osh, ulong addr, int size)
+{
+ return (uint32 *)REG_MAP(addr, size);
+}
+
+void
+dhdpcie_bus_reg_unmap(osl_t *osh, ulong addr, int size)
+{
+ REG_UNMAP((void*)(uintptr)addr);
+ return;
+}
+
+/** 'tcm' is the *host* virtual address at which tcm is mapped */
+dhd_bus_t* dhdpcie_bus_attach(osl_t *osh, volatile char* regs, volatile char* tcm)
+{
+ dhd_bus_t *bus;
+
+ int ret = 0;
+
+ DHD_TRACE(("%s: ENTER\n", __FUNCTION__));
+
+ do {
+ if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) {
+ DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
+ break;
+ }
+ bzero(bus, sizeof(dhd_bus_t));
+ bus->regs = regs;
+ bus->tcm = tcm;
+ bus->osh = osh;
+
+ /* Attach pcie shared structure */
+ bus->pcie_sh = MALLOC(osh, sizeof(pciedev_shared_t));
+
+ /* dhd_common_init(osh); */
+
+ if (dhdpcie_dongle_attach(bus)) {
+ DHD_ERROR(("%s: dhdpcie_probe_attach failed\n", __FUNCTION__));
+ break;
+ }
+
+ /* software resources */
+ if (!(bus->dhd = dhd_attach(osh, bus, PCMSGBUF_HDRLEN))) {
+ DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
+
+ break;
+ }
+ bus->dhd->busstate = DHD_BUS_DOWN;
+
+ /* Attach to the OS network interface */
+ DHD_TRACE(("%s(): Calling dhd_register_if() \n", __FUNCTION__));
+ ret = dhd_register_if(bus->dhd, 0, TRUE);
+ if (ret) {
+ DHD_ERROR(("%s(): ERROR.. dhd_register_if() failed\n", __FUNCTION__));
+ break;
+ }
+ DHD_TRACE(("%s: EXIT SUCCESS\n",
+ __FUNCTION__));
+
+ return bus;
+ } while (0);
+
+ DHD_TRACE(("%s: EXIT FAILURE\n", __FUNCTION__));
+
+ return NULL;
+}
+
+uint
+dhd_bus_chip(struct dhd_bus *bus)
+{
+ ASSERT(bus->sih != NULL);
+ return bus->sih->chip;
+}
+
+uint
+dhd_bus_chiprev(struct dhd_bus *bus)
+{
+ ASSERT(bus);
+ ASSERT(bus->sih != NULL);
+ return bus->sih->chiprev;
+}
+
+void *
+dhd_bus_pub(struct dhd_bus *bus)
+{
+ return bus->dhd;
+}
+
+void *
+dhd_bus_sih(struct dhd_bus *bus)
+{
+ return (void *)bus->sih;
+}
+
+void *
+dhd_bus_txq(struct dhd_bus *bus)
+{
+ return &bus->txq;
+}
+
+
+/*
+
+Name: dhdpcie_bus_isr
+
+Parametrs:
+
+1: IN int irq -- interrupt vector
+2: IN void *arg -- handle to private data structure
+
+Return value:
+
+Status (TRUE or FALSE)
+
+Description:
+Interrupt Service routine checks for the status register,
+disable interrupt and queue DPC if mail box interrupts are raised.
+*/
+
+
+int32
+dhdpcie_bus_isr(dhd_bus_t *bus)
+{
+
+ do {
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ /* verify argument */
+ if (!bus) {
+ DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
+ break;
+ }
+
+ if (bus->dhd->busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s : bus is down. we have nothing to do\n",
+ __FUNCTION__));
+ break;
+ }
+
+
+#ifdef DHD_ALLIRQ
+ /* Lock here covers SMP */
+ dhd_os_sdisrlock(bus->dhd);
+#endif
+ /* Count the interrupt call */
+ bus->intrcount++;
+
+ /* read interrupt status register!! Status bits will be cleared in DPC !! */
+ bus->ipend = TRUE;
+ dhdpcie_bus_intr_disable(bus); /* Disable interrupt!! */
+ bus->intdis = TRUE;
+
+#if defined(DHD_ALLIRQ) || defined(PCIE_ISR_THREAD)
+
+ DHD_TRACE(("Calling dhd_bus_dpc() from %s\n", __FUNCTION__));
+ DHD_OS_WAKE_LOCK(bus->dhd);
+ while (dhd_bus_dpc(bus));
+ DHD_OS_WAKE_UNLOCK(bus->dhd);
+#else
+ bus->dpc_sched = TRUE;
+ dhd_sched_dpc(bus->dhd); /* queue DPC now!! */
+#endif /* defined(DHD_ALLIRQ) || defined(SDIO_ISR_THREAD) */
+
+#ifdef DHD_ALLIRQ
+ dhd_os_sdisrunlock(bus->dhd);
+#endif
+ DHD_TRACE(("%s: Exit Success DPC Queued\n", __FUNCTION__));
+ return TRUE;
+
+ } while (0);
+
+ DHD_TRACE(("%s: Exit Failure\n", __FUNCTION__));
+ return FALSE;
+}
+
+static bool
+dhdpcie_dongle_attach(dhd_bus_t *bus)
+{
+
+ osl_t *osh = bus->osh;
+ void *regsva = (void*)bus->regs;
+ uint16 devid = bus->cl_devid;
+ uint32 val;
+
+ DHD_TRACE(("%s: ENTER\n",
+ __FUNCTION__));
+
+ bus->alp_only = TRUE;
+ bus->sih = NULL;
+
+ /* Set bar0 window to si_enum_base */
+ dhdpcie_bus_cfg_set_bar0_win(bus, SI_ENUM_BASE);
+
+ /* si_attach() will provide an SI handle and scan the backplane */
+ if (!(bus->sih = si_attach((uint)devid, osh, regsva, PCI_BUS, bus,
+ &bus->vars, &bus->varsz))) {
+ DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
+ goto fail;
+ }
+
+ si_setcore(bus->sih, PCIE2_CORE_ID, 0);
+
+ dhdpcie_bus_wreg32(bus, OFFSETOF(sbpcieregs_t, configaddr), 0x4e0);
+ val = dhdpcie_bus_rreg32(bus, OFFSETOF(sbpcieregs_t, configdata));
+ dhdpcie_bus_wreg32(bus, OFFSETOF(sbpcieregs_t, configdata), val);
+
+ /* Get info on the ARM and SOCRAM cores... */
+ if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
+ (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) ||
+ (si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
+ bus->armrev = si_corerev(bus->sih);
+ } else {
+ DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
+ goto fail;
+ }
+
+ if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
+ DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
+ goto fail;
+ }
+ } else {
+ /* cr4 has a different way to find the RAM size from TCM's */
+ if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) {
+ DHD_ERROR(("%s: failed to find CR4-TCM memory!\n", __FUNCTION__));
+ goto fail;
+ }
+ /* also populate base address */
+ switch ((uint16)bus->sih->chip) {
+ case BCM4335_CHIP_ID:
+ bus->dongle_ram_base = CR4_4335_RAM_BASE;
+ break;
+ case BCM4354_CHIP_ID:
+ case BCM4350_CHIP_ID:
+ bus->dongle_ram_base = CR4_4350_RAM_BASE;
+ break;
+ case BCM4360_CHIP_ID:
+ bus->dongle_ram_base = CR4_4360_RAM_BASE;
+ break;
+ case BCM4345_CHIP_ID:
+ /* RAM base changed from 4345c0 (chiprev=6) onwards */
+ bus->dongle_ram_base = (bus->sih->chiprev < 6)
+ ? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
+ break;
+ case BCM43602_CHIP_ID:
+ bus->dongle_ram_base = CR4_43602_RAM_BASE;
+ break;
+ default:
+ bus->dongle_ram_base = 0;
+ DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
+ __FUNCTION__, bus->dongle_ram_base));
+ }
+ }
+ bus->ramsize = bus->orig_ramsize;
+ if (dhd_dongle_memsize)
+ dhdpcie_bus_dongle_setmemsize(bus, dhd_dongle_memsize);
+
+ DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n",
+ bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base));
+
+ bus->srmemsize = si_socram_srmem_size(bus->sih);
+
+
+ bus->def_intmask = PCIE_MB_D2H_MB_MASK | PCIE_MB_TOPCIE_FN0_0 | PCIE_MB_TOPCIE_FN0_1;
+
+ /* Set the poll and/or interrupt flags */
+ bus->intr = (bool)dhd_intr;
+
+ DHD_TRACE(("%s: EXIT: SUCCESS\n",
+ __FUNCTION__));
+ return 0;
+
+fail:
+ if (bus->sih != NULL)
+ si_detach(bus->sih);
+ DHD_TRACE(("%s: EXIT: FAILURE\n",
+ __FUNCTION__));
+ return -1;
+}
+
+int
+dhpcie_bus_unmask_interrupt(dhd_bus_t *bus)
+{
+ dhdpcie_bus_cfg_write_dword(bus, PCIIntmask, 4, I_MB);
+ return 0;
+}
+int
+dhpcie_bus_mask_interrupt(dhd_bus_t *bus)
+{
+ dhdpcie_bus_cfg_write_dword(bus, PCIIntmask, 4, 0x0);
+ return 0;
+}
+
+void
+dhdpcie_bus_intr_enable(dhd_bus_t *bus)
+{
+ DHD_TRACE(("enable interrupts\n"));
+ if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
+ (bus->sih->buscorerev == 4)) {
+ dhpcie_bus_unmask_interrupt(bus);
+ }
+ else if (bus->sih) {
+ si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask,
+ bus->def_intmask, bus->def_intmask);
+ }
+}
+
+void
+dhdpcie_bus_intr_disable(dhd_bus_t *bus)
+{
+
+ DHD_TRACE(("%s Enter\n", __FUNCTION__));
+
+ if (bus) {
+
+ if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
+ (bus->sih->buscorerev == 4)) {
+ dhpcie_bus_mask_interrupt(bus);
+ }
+ else if (bus->sih) {
+ si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask,
+ bus->def_intmask, 0);
+ }
+ }
+ DHD_TRACE(("%s Exit\n", __FUNCTION__));
+}
+
+
+/* Detach and free everything */
+void
+dhdpcie_bus_release(dhd_bus_t *bus)
+{
+ bool dongle_isolation = FALSE;
+ osl_t *osh = NULL;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus) {
+
+ osh = bus->osh;
+ ASSERT(osh);
+
+ if (bus->dhd) {
+ dongle_isolation = bus->dhd->dongle_isolation;
+ dhd_detach(bus->dhd);
+
+ if (bus->intr) {
+ dhdpcie_bus_intr_disable(bus);
+ dhdpcie_free_irq(bus);
+ }
+ dhdpcie_bus_release_dongle(bus, osh, dongle_isolation, TRUE);
+ dhd_free(bus->dhd);
+ bus->dhd = NULL;
+ }
+
+ /* unmap the regs and tcm here!! */
+ if (bus->regs) {
+ dhdpcie_bus_reg_unmap(osh, (ulong)bus->regs, DONGLE_REG_MAP_SIZE);
+ bus->regs = NULL;
+ }
+ if (bus->tcm) {
+ dhdpcie_bus_reg_unmap(osh, (ulong)bus->tcm, DONGLE_TCM_MAP_SIZE);
+ bus->tcm = NULL;
+ }
+
+ dhdpcie_bus_release_malloc(bus, osh);
+ /* Detach pcie shared structure */
+ if (bus->pcie_sh)
+ MFREE(osh, bus->pcie_sh, sizeof(pciedev_shared_t));
+
+#ifdef DHD_DEBUG
+
+ if (bus->console.buf != NULL)
+ MFREE(osh, bus->console.buf, bus->console.bufsize);
+#endif
+
+
+ /* Finally free bus info */
+ MFREE(osh, bus, sizeof(dhd_bus_t));
+
+ }
+
+ DHD_TRACE(("%s: Exit\n", __FUNCTION__));
+
+}
+
+
+void
+dhdpcie_bus_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
+{
+
+ DHD_TRACE(("%s Enter\n", __FUNCTION__));
+
+ DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
+ bus->dhd, bus->dhd->dongle_reset));
+
+ if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag) {
+ DHD_TRACE(("%s Exit\n", __FUNCTION__));
+ return;
+ }
+
+ if (bus->sih) {
+
+
+ if (!dongle_isolation) {
+ uint32 val, i;
+ uint16 cfg_offset[] = {0x4, 0x4C, 0x58, 0x5C, 0x60, 0x64, 0xDC,
+ 0x228, 0x248, 0x4e0, 0x4f4};
+ si_corereg(bus->sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 4);
+ /* apply the WAR: need to restore the config space snoop bus values */
+ OSL_DELAY(100000);
+
+ for (i = 0; i < ARRAYSIZE(cfg_offset); i++) {
+ dhdpcie_bus_wreg32(bus, OFFSETOF(sbpcieregs_t, configaddr),
+ cfg_offset[i]);
+ val = dhdpcie_bus_rreg32(bus,
+ OFFSETOF(sbpcieregs_t, configdata));
+ DHD_INFO(("SNOOP_BUS_UPDATE: config offset 0x%04x, value 0x%04x\n",
+ cfg_offset[i], val));
+ dhdpcie_bus_wreg32(bus, OFFSETOF(sbpcieregs_t, configdata), val);
+ }
+ }
+ if (bus->ltrsleep_on_unload) {
+ si_corereg(bus->sih, bus->sih->buscoreidx,
+ OFFSETOF(sbpcieregs_t, u.pcie2.ltr_state), ~0, 0);
+ }
+ si_detach(bus->sih);
+ if (bus->vars && bus->varsz)
+ MFREE(osh, bus->vars, bus->varsz);
+ bus->vars = NULL;
+ }
+
+ DHD_TRACE(("%s Exit\n", __FUNCTION__));
+}
+
+uint32
+dhdpcie_bus_cfg_read_dword(dhd_bus_t *bus, uint32 addr, uint32 size)
+{
+ uint32 data = OSL_PCI_READ_CONFIG(bus->osh, addr, size);
+ return data;
+}
+
+/* 32 bit config write */
+void
+dhdpcie_bus_cfg_write_dword(dhd_bus_t *bus, uint32 addr, uint32 size, uint32 data)
+{
+ OSL_PCI_WRITE_CONFIG(bus->osh, addr, size, data);
+}
+
+void
+dhdpcie_bus_cfg_set_bar0_win(dhd_bus_t *bus, uint32 data)
+{
+ OSL_PCI_WRITE_CONFIG(bus->osh, PCI_BAR0_WIN, 4, data);
+}
+
+/* 32 bit pio write to device TCM */
+void
+dhdpcie_bus_wreg32(dhd_bus_t *bus, uint reg, uint32 data)
+{
+ *(volatile uint32 *)(bus->regs + reg) = (uint32)data;
+
+}
+
+uint32
+dhdpcie_bus_rreg32(dhd_bus_t *bus, uint reg)
+{
+ uint32 data;
+
+ data = *(volatile uint32 *)(bus->regs + reg);
+ return data;
+}
+
+
+void
+dhdpcie_bus_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
+{
+ int32 min_size = DONGLE_MIN_MEMSIZE;
+ /* Restrict the memsize to user specified limit */
+ DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
+ dhd_dongle_memsize, min_size));
+ if ((dhd_dongle_memsize > min_size) &&
+ (dhd_dongle_memsize < (int32)bus->orig_ramsize))
+ bus->ramsize = dhd_dongle_memsize;
+}
+
+void
+dhdpcie_bus_release_malloc(dhd_bus_t *bus, osl_t *osh)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd && bus->dhd->dongle_reset)
+ return;
+
+ if (bus->vars && bus->varsz) {
+ MFREE(osh, bus->vars, bus->varsz);
+ bus->vars = NULL;
+ }
+
+ DHD_TRACE(("%s: Exit\n", __FUNCTION__));
+ return;
+
+}
+
+/* Stop bus module: clear pending frames, disable data flow */
+void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
+{
+ uint32 status;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (!bus->dhd)
+ return;
+
+ if (enforce_mutex)
+ dhd_os_sdlock(bus->dhd);
+
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ dhdpcie_bus_intr_disable(bus);
+ status = dhdpcie_bus_cfg_read_dword(bus, PCIIntstatus, 4);
+ dhdpcie_bus_cfg_write_dword(bus, PCIIntstatus, 4, status);
+
+ /* Clear rx control and wake any waiters */
+ bus->rxlen = 0;
+ dhd_os_ioctl_resp_wake(bus->dhd);
+
+ if (enforce_mutex)
+ dhd_os_sdunlock(bus->dhd);
+
+ return;
+}
+
+/* Watchdog timer function */
+bool dhd_bus_watchdog(dhd_pub_t *dhd)
+{
+#ifdef DHD_DEBUG
+ dhd_bus_t *bus;
+ bus = dhd->bus;
+
+
+
+ /* Poll for console output periodically */
+ if (dhd->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
+ bus->console.count += dhd_watchdog_ms;
+ if (bus->console.count >= dhd_console_ms) {
+ bus->console.count -= dhd_console_ms;
+ /* Make sure backplane clock is on */
+ if (dhdpcie_bus_readconsole(bus) < 0)
+ dhd_console_ms = 0; /* On error, stop trying */
+ }
+ }
+#endif /* DHD_DEBUG */
+
+ return FALSE;
+}
+
+/* Download firmware image and nvram image */
+int
+dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
+ char *pfw_path, char *pnv_path)
+{
+ int ret;
+
+ bus->fw_path = pfw_path;
+ bus->nv_path = pnv_path;
+
+ ret = dhdpcie_download_firmware(bus, osh);
+
+ return ret;
+}
+
+static int
+dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh)
+{
+ int ret = 0;
+
+ DHD_OS_WAKE_LOCK(bus->dhd);
+
+ ret = _dhdpcie_download_firmware(bus);
+
+ DHD_OS_WAKE_UNLOCK(bus->dhd);
+ return ret;
+}
+
+static int
+dhdpcie_download_code_file(struct dhd_bus *bus, char *pfw_path)
+{
+ int bcmerror = -1;
+ int offset = 0;
+ int len;
+ void *image = NULL;
+ uint8 *memblock = NULL, *memptr;
+
+ DHD_ERROR(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
+
+ image = dhd_os_open_image(pfw_path);
+ if (image == NULL)
+ goto err;
+
+ memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
+ if (memblock == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
+ goto err;
+ }
+ if ((uint32)(uintptr)memblock % DHD_SDALIGN)
+ memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
+
+ /* Download image */
+ while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, image))) {
+ if (len < 0) {
+ DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
+ bcmerror = BCME_ERROR;
+ goto err;
+ }
+ /* check if CR4 */
+ if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ /* if address is 0, store the reset instruction to be written in 0 */
+
+ if (offset == 0) {
+ bus->resetinstr = *(((uint32*)memptr));
+ /* Add start of RAM address to the address given by user */
+ offset += bus->dongle_ram_base;
+ }
+ }
+
+ bcmerror = dhdpcie_bus_membytes(bus, TRUE, offset, memptr, len);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, MEMBLOCK, offset));
+ goto err;
+ }
+
+ offset += MEMBLOCK;
+ }
+
+err:
+ if (memblock)
+ MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN);
+
+ if (image)
+ dhd_os_close_image(image);
+
+ return bcmerror;
+}
+
+
+static int
+dhdpcie_download_nvram(struct dhd_bus *bus)
+{
+ int bcmerror = -1;
+ uint len;
+ void * image = NULL;
+ char * memblock = NULL;
+ char *bufp;
+ char *pnv_path;
+ bool nvram_file_exists;
+
+ pnv_path = bus->nv_path;
+
+ nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
+ if (!nvram_file_exists && (bus->nvram_params == NULL))
+ return (0);
+
+ if (nvram_file_exists) {
+ image = dhd_os_open_image(pnv_path);
+ if (image == NULL)
+ goto err;
+ }
+
+ memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE);
+ if (memblock == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
+ __FUNCTION__, MAX_NVRAMBUF_SIZE));
+ goto err;
+ }
+
+ /* Download variables */
+ if (nvram_file_exists) {
+ len = dhd_os_get_image_block(memblock, MAX_NVRAMBUF_SIZE, image);
+ }
+ else {
+ len = strlen(bus->nvram_params);
+ ASSERT(len <= MAX_NVRAMBUF_SIZE);
+ memcpy(memblock, bus->nvram_params, len);
+ }
+ if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
+ bufp = (char *)memblock;
+ bufp[len] = 0;
+ len = process_nvram_vars(bufp, len);
+ if (len % 4) {
+ len += 4 - (len % 4);
+ }
+ bufp += len;
+ *bufp++ = 0;
+ if (len)
+ bcmerror = dhdpcie_downloadvars(bus, memblock, len + 1);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error downloading vars: %d\n",
+ __FUNCTION__, bcmerror));
+ }
+ }
+ else {
+ DHD_ERROR(("%s: error reading nvram file: %d\n",
+ __FUNCTION__, len));
+ bcmerror = BCME_ERROR;
+ }
+
+err:
+ if (memblock)
+ MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
+
+ if (image)
+ dhd_os_close_image(image);
+
+ return bcmerror;
+}
+
+
+static int
+_dhdpcie_download_firmware(struct dhd_bus *bus)
+{
+ int bcmerror = -1;
+
+ bool embed = FALSE; /* download embedded firmware */
+ bool dlok = FALSE; /* download firmware succeeded */
+
+ /* Out immediately if no image to download */
+ if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
+#ifdef BCMEMBEDIMAGE
+ embed = TRUE;
+#else
+ DHD_ERROR(("%s: no fimrware file\n", __FUNCTION__));
+ return 0;
+#endif
+ }
+
+ /* Keep arm in reset */
+ if (dhdpcie_bus_download_state(bus, TRUE)) {
+ DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
+ goto err;
+ }
+
+ /* External image takes precedence if specified */
+ if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
+ if (dhdpcie_download_code_file(bus, bus->fw_path)) {
+ DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
+#ifdef BCMEMBEDIMAGE
+ embed = TRUE;
+#else
+ goto err;
+#endif
+ }
+ else {
+ embed = FALSE;
+ dlok = TRUE;
+ }
+ }
+
+#ifdef BCMEMBEDIMAGE
+ if (embed) {
+ if (dhdpcie_download_code_array(bus)) {
+ DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__));
+ goto err;
+ }
+ else {
+ dlok = TRUE;
+ }
+ }
+#else
+ BCM_REFERENCE(embed);
+#endif
+ if (!dlok) {
+ DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
+ goto err;
+ }
+
+ /* EXAMPLE: nvram_array */
+ /* If a valid nvram_arry is specified as above, it can be passed down to dongle */
+ /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
+
+ /* External nvram takes precedence if specified */
+ if (dhdpcie_download_nvram(bus)) {
+ DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
+ goto err;
+ }
+
+ /* Take arm out of reset */
+ if (dhdpcie_bus_download_state(bus, FALSE)) {
+ DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
+ goto err;
+ }
+
+ bcmerror = 0;
+
+err:
+ return bcmerror;
+}
+
+int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
+{
+ int timeleft;
+ uint rxlen = 0;
+ bool pending;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd->dongle_reset)
+ return -EIO;
+
+ /* Wait until control frame is available */
+ timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
+ dhd_os_sdlock(bus->dhd);
+ rxlen = bus->rxlen;
+ bcopy(&bus->ioct_resp, msg, sizeof(ioct_resp_hdr_t));
+ bus->rxlen = 0;
+ dhd_os_sdunlock(bus->dhd);
+
+ if (rxlen) {
+ DHD_CTL(("%s: resumed on rxctl frame, got %d\n", __FUNCTION__, rxlen));
+ } else if (timeleft == 0) {
+ DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
+ bus->ioct_resp.pkt_id = 0;
+ bus->ioct_resp.status = 0xffff;
+ } else if (pending == TRUE) {
+ DHD_CTL(("%s: canceled\n", __FUNCTION__));
+ return -ERESTARTSYS;
+ } else {
+ DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
+ }
+ if (timeleft == 0) {
+ bus->dhd->rxcnt_timeout++;
+ DHD_ERROR(("%s: rxcnt_timeout=%d\n", __FUNCTION__, bus->dhd->rxcnt_timeout));
+ }
+ else
+ bus->dhd->rxcnt_timeout = 0;
+
+ if (rxlen)
+ bus->dhd->rx_ctlpkts++;
+ else
+ bus->dhd->rx_ctlerrs++;
+
+ if (bus->dhd->rxcnt_timeout >= MAX_CNTL_TX_TIMEOUT)
+ return -ETIMEDOUT;
+
+ if (bus->dhd->dongle_trap_occured)
+ return -EREMOTEIO;
+
+ return rxlen ? (int)rxlen : -EIO;
+
+}
+
+#define CONSOLE_LINE_MAX 192
+
+#ifdef DHD_DEBUG
+static int
+dhdpcie_bus_readconsole(dhd_bus_t *bus)
+{
+ dhd_console_t *c = &bus->console;
+ uint8 line[CONSOLE_LINE_MAX], ch;
+ uint32 n, idx, addr;
+ int rv;
+
+ /* Don't do anything until FWREADY updates console address */
+ if (bus->console_addr == 0)
+ return -1;
+
+ /* Read console log struct */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
+
+ if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
+ return rv;
+
+ /* Allocate console buffer (one time only) */
+ if (c->buf == NULL) {
+ c->bufsize = ltoh32(c->log.buf_size);
+ if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
+ return BCME_NOMEM;
+ }
+ idx = ltoh32(c->log.idx);
+
+ /* Protect against corrupt value */
+ if (idx > c->bufsize)
+ return BCME_ERROR;
+
+ /* Skip reading the console buffer if the index pointer has not moved */
+ if (idx == c->last)
+ return BCME_OK;
+
+ /* Read the console buffer */
+ addr = ltoh32(c->log.buf);
+ if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
+ return rv;
+
+ while (c->last != idx) {
+ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+ if (c->last == idx) {
+ /* This would output a partial line. Instead, back up
+ * the buffer pointer and output this line next time around.
+ */
+ if (c->last >= n)
+ c->last -= n;
+ else
+ c->last = c->bufsize - n;
+ goto break2;
+ }
+ ch = c->buf[c->last];
+ c->last = (c->last + 1) % c->bufsize;
+ if (ch == '\n')
+ break;
+ line[n] = ch;
+ }
+
+ if (n > 0) {
+ if (line[n - 1] == '\r')
+ n--;
+ line[n] = 0;
+ printf("CONSOLE: %s\n", line);
+ }
+ }
+break2:
+
+ return BCME_OK;
+}
+#endif /* DHD_DEBUG */
+
+/**
+ * Transfers bytes from host to dongle using pio mode.
+ * Parameter 'address' is a backplane address.
+ */
+static int
+dhdpcie_bus_membytes(dhd_bus_t *bus, bool write, ulong address, uint8 *data, uint size)
+{
+ int bcmerror = 0;
+ uint dsize;
+ uint i = 0;
+ /* In remap mode, adjust address beyond socram and redirect
+ * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize
+ * is not backplane accessible
+ */
+
+
+ /* Determine initial transfer parameters */
+ dsize = sizeof(uint8);
+
+ /* Do the transfer(s) */
+ if (write) {
+ while (size) {
+ dhdpcie_bus_wtcm8(bus, address, *data);
+ /* Adjust for next transfer (if any) */
+ if ((size -= dsize)) {
+ data += dsize;
+ address += dsize;
+ }
+ }
+ } else {
+ while (size) {
+ data[i] = dhdpcie_bus_rtcm8(bus, address);
+ /* Adjust for next transfer (if any) */
+ if ((size -= dsize)) {
+ i++;
+ address += dsize;
+ }
+ }
+ }
+ return bcmerror;
+}
+
+/* Send a data frame to the dongle. Callee disposes of txp. */
+int BCMFASTPATH
+dhd_bus_txdata(struct dhd_bus *bus, void *txp, uint8 ifidx)
+{
+ return dhd_prot_txdata(bus->dhd, txp, ifidx);
+}
+
+void
+dhd_bus_stop_queue(struct dhd_bus *bus)
+{
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
+ bus->bus_flowctrl = TRUE;
+}
+
+void
+dhd_bus_start_queue(struct dhd_bus *bus)
+{
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
+ bus->bus_flowctrl = TRUE;
+}
+
+void
+dhd_bus_update_retlen(dhd_bus_t *bus, uint32 retlen, uint32 pkt_id, uint32 status,
+ uint32 inline_data)
+{
+ bus->rxlen = retlen;
+ bus->ioct_resp.pkt_id = pkt_id;
+ bus->ioct_resp.status = status;
+ bus->ioct_resp.inline_data = inline_data;
+}
+
+#if defined(DHD_DEBUG)
+/* Device console input function */
+int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen)
+{
+ dhd_bus_t *bus = dhd->bus;
+ uint32 addr, val;
+ int rv;
+ /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+ if (bus->console_addr == 0)
+ return BCME_UNSUPPORTED;
+
+ /* Exclusive bus access */
+ dhd_os_sdlock(bus->dhd);
+
+ /* Don't allow input if dongle is in reset */
+ if (bus->dhd->dongle_reset) {
+ dhd_os_sdunlock(bus->dhd);
+ return BCME_NOTREADY;
+ }
+
+ /* Zero cbuf_index */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx);
+ val = htol32(0);
+ if ((rv = dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+ goto done;
+
+ /* Write message into cbuf */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf);
+ if ((rv = dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
+ goto done;
+
+ /* Write length into vcons_in */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in);
+ val = htol32(msglen);
+ if ((rv = dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+ goto done;
+
+ dhd_post_dummy_msg(bus->dhd);
+done:
+
+ dhd_os_sdunlock(bus->dhd);
+
+ return rv;
+}
+#endif /* defined(DHD_DEBUG) */
+
+/* Process rx frame , Send up the layer to netif */
+void
+dhd_bus_rx_frame(struct dhd_bus *bus, void* pkt, int ifidx, uint pkt_count)
+{
+ dhd_os_sdunlock(bus->dhd);
+ dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, 0);
+ dhd_os_sdlock(bus->dhd);
+}
+
+/** 'offset' is a backplane address */
+void
+dhdpcie_bus_wtcm8(dhd_bus_t *bus, ulong offset, uint8 data)
+{
+ *(volatile uint8 *)(bus->tcm + offset) = (uint8)data;
+}
+
+uint8
+dhdpcie_bus_rtcm8(dhd_bus_t *bus, ulong offset)
+{
+ volatile uint8 data = *(volatile uint8 *)(bus->tcm + offset);
+ return data;
+}
+
+void
+dhdpcie_bus_wtcm32(dhd_bus_t *bus, ulong offset, uint32 data)
+{
+ *(volatile uint32 *)(bus->tcm + offset) = (uint32)data;
+}
+void
+dhdpcie_bus_wtcm16(dhd_bus_t *bus, ulong offset, uint16 data)
+{
+ *(volatile uint16 *)(bus->tcm + offset) = (uint16)data;
+}
+
+uint16
+dhdpcie_bus_rtcm16(dhd_bus_t *bus, ulong offset)
+{
+ volatile uint16 data = *(volatile uint16 *)(bus->tcm + offset);
+ return data;
+}
+
+uint32
+dhdpcie_bus_rtcm32(dhd_bus_t *bus, ulong offset)
+{
+ volatile uint32 data = *(volatile uint32 *)(bus->tcm + offset);
+ return data;
+}
+
+void
+dhd_bus_cmn_writeshared(dhd_bus_t *bus, void * data, uint32 len, uint8 type)
+{
+ uint64 long_data;
+ ulong tcm_offset;
+
+ DHD_INFO(("%s: writing to msgbuf type %d, len %d\n", __FUNCTION__, type, len));
+
+ switch (type) {
+ case DNGL_TO_HOST_BUF_ADDR :
+ long_data = HTOL64(*(uint64 *)data);
+ tcm_offset = bus->d2h_data_ring_mem_addr;
+ tcm_offset += OFFSETOF(ring_mem_t, base_addr);
+ dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8*) &long_data, len);
+ prhex(__FUNCTION__, data, len);
+ break;
+ case HOST_TO_DNGL_BUF_ADDR :
+ long_data = HTOL64(*(uint64 *)data);
+ tcm_offset = bus->h2d_data_ring_mem_addr;
+ tcm_offset += OFFSETOF(ring_mem_t, base_addr);
+ dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8*) &long_data, len);
+ prhex(__FUNCTION__, data, len);
+ break;
+ case HOST_TO_DNGL_WPTR :
+ tcm_offset = bus->h2d_data_ring_state_addr;
+ tcm_offset += OFFSETOF(ring_state_t, w_offset);
+ dhdpcie_bus_wtcm32(bus, tcm_offset, (uint32) HTOL32(*(uint32 *)data));
+ break;
+ case DNGL_TO_HOST_RPTR :
+ tcm_offset = bus->d2h_data_ring_state_addr;
+ tcm_offset += OFFSETOF(ring_state_t, r_offset);
+ dhdpcie_bus_wtcm16(bus, tcm_offset, (uint16) HTOL16(*(uint16 *)data));
+ break;
+ case HOST_TO_DNGL_CTRLBUF_ADDR:
+ long_data = HTOL64(*(uint64 *)data);
+ tcm_offset = bus->h2d_ctrl_ring_mem_addr;
+ tcm_offset += OFFSETOF(ring_mem_t, base_addr);
+ dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8 *) &long_data, len);
+ break;
+ case DNGL_TO_HOST_CTRLBUF_ADDR:
+ long_data = HTOL64(*(uint64 *)data);
+ tcm_offset = bus->d2h_ctrl_ring_mem_addr;
+ tcm_offset += OFFSETOF(ring_mem_t, base_addr);
+ dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8 *) &long_data, len);
+ break;
+ case HTOD_CTRL_WPTR:
+ tcm_offset = bus->h2d_ctrl_ring_state_addr;
+ tcm_offset += OFFSETOF(ring_state_t, w_offset);
+ dhdpcie_bus_wtcm32(bus, tcm_offset, (uint32) HTOL32(*(uint32 *)data));
+ break;
+ case DTOH_CTRL_RPTR:
+ tcm_offset = bus->d2h_ctrl_ring_state_addr;
+ tcm_offset += OFFSETOF(ring_state_t, r_offset);
+ dhdpcie_bus_wtcm16(bus, tcm_offset, (uint16) HTOL16(*(uint16 *)data));
+ break;
+ case DTOH_MB_DATA:
+ dhdpcie_bus_wtcm32(bus, bus->d2h_mb_data_ptr_addr,
+ (uint32) HTOL32(*(uint32 *)data));
+ break;
+ case HTOD_MB_DATA:
+ dhdpcie_bus_wtcm32(bus, bus->h2d_mb_data_ptr_addr,
+ (uint32) HTOL32(*(uint32 *)data));
+ break;
+ default:
+ break;
+ }
+}
+
+
+void
+dhd_bus_cmn_readshared(dhd_bus_t *bus, void* data, uint8 type)
+{
+ pciedev_shared_t *sh;
+ ulong tcm_offset;
+
+ sh = (pciedev_shared_t*)bus->shared_addr;
+
+ switch (type) {
+ case HOST_TO_DNGL_RPTR :
+ tcm_offset = bus->h2d_data_ring_state_addr;
+ tcm_offset += OFFSETOF(ring_state_t, r_offset);
+ *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, tcm_offset));
+ break;
+ case DNGL_TO_HOST_WPTR :
+ tcm_offset = bus->d2h_data_ring_state_addr;
+ tcm_offset += OFFSETOF(ring_state_t, w_offset);
+ *(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, tcm_offset));
+ break;
+ case TOTAL_LFRAG_PACKET_CNT :
+ *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus,
+ (ulong) &sh->total_lfrag_pkt_cnt));
+ break;
+ case HTOD_CTRL_RPTR:
+ tcm_offset = bus->h2d_ctrl_ring_state_addr;
+ tcm_offset += OFFSETOF(ring_state_t, r_offset);
+ *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, tcm_offset));
+ break;
+ case DTOH_CTRL_WPTR:
+ tcm_offset = bus->d2h_ctrl_ring_state_addr;
+ tcm_offset += OFFSETOF(ring_state_t, w_offset);
+ *(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, tcm_offset));
+ break;
+ case HTOD_MB_DATA:
+ *(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, bus->h2d_mb_data_ptr_addr));
+ break;
+ case DTOH_MB_DATA:
+ *(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, bus->d2h_mb_data_ptr_addr));
+ break;
+ case MAX_HOST_RXBUFS :
+ *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus,
+ (ulong) &sh->max_host_rxbufs));
+ break;
+ default :
+ break;
+ }
+}
+
+uint32 dhd_bus_get_sharedflags(dhd_bus_t *bus)
+{
+ return ((pciedev_shared_t*)bus->pcie_sh)->flags;
+}
+
+void
+dhd_bus_clearcounts(dhd_pub_t *dhdp)
+{
+}
+
+int
+dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ const bcm_iovar_t *vi = NULL;
+ int bcmerror = 0;
+ int val_size;
+ uint32 actionid;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ASSERT(name);
+ ASSERT(len >= 0);
+
+ /* Get MUST have return space */
+ ASSERT(set || (arg && len));
+
+ /* Set does NOT take qualifiers */
+ ASSERT(!set || (!params && !plen));
+
+ DHD_INFO(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
+ name, (set ? "set" : "get"), len, plen));
+
+ /* Look up var locally; if not found pass to host driver */
+ if ((vi = bcm_iovar_lookup(dhdpcie_iovars, name)) == NULL) {
+ goto exit;
+ }
+
+
+ /* set up 'params' pointer in case this is a set command so that
+ * the convenience int and bool code can be common to set and get
+ */
+ if (params == NULL) {
+ params = arg;
+ plen = len;
+ }
+
+ if (vi->type == IOVT_VOID)
+ val_size = 0;
+ else if (vi->type == IOVT_BUFFER)
+ val_size = len;
+ else
+ /* all other types are integer sized */
+ val_size = sizeof(int);
+
+ actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+ bcmerror = dhdpcie_bus_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
+
+exit:
+ return bcmerror;
+}
+
+
+static int
+dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
+ void *params, int plen, void *arg, int len, int val_size)
+{
+ int bcmerror = 0;
+ int32 int_val = 0;
+ int32 int_val2 = 0;
+ int32 int_val3 = 0;
+ bool bool_val = 0;
+
+ DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
+ __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
+
+ if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
+ goto exit;
+
+ if (plen >= (int)sizeof(int_val))
+ bcopy(params, &int_val, sizeof(int_val));
+
+ if (plen >= (int)sizeof(int_val) * 2)
+ bcopy((void*)((uintptr)params + sizeof(int_val)), &int_val2, sizeof(int_val2));
+
+ if (plen >= (int)sizeof(int_val) * 3)
+ bcopy((void*)((uintptr)params + 2 * sizeof(int_val)), &int_val3, sizeof(int_val3));
+
+ bool_val = (int_val != 0) ? TRUE : FALSE;
+
+ /* Some ioctls use the bus */
+ dhd_os_sdlock(bus->dhd);
+
+ /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
+ if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
+ actionid == IOV_GVAL(IOV_DEVRESET))) {
+ bcmerror = BCME_NOTREADY;
+ goto exit;
+ }
+
+ switch (actionid) {
+
+
+ case IOV_SVAL(IOV_VARS):
+ bcmerror = dhdpcie_downloadvars(bus, arg, len);
+ break;
+
+ case IOV_SVAL(IOV_PCIEREG):
+ si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configaddr), ~0,
+ int_val);
+ si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configdata), ~0,
+ int_val2);
+ break;
+
+ case IOV_GVAL(IOV_PCIEREG):
+ si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configaddr), ~0,
+ int_val);
+ int_val = si_corereg(bus->sih, bus->sih->buscoreidx,
+ OFFSETOF(sbpcieregs_t, configdata), 0, 0);
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_PCIECOREREG):
+ si_corereg(bus->sih, bus->sih->buscoreidx, int_val, ~0, int_val2);
+ break;
+
+ case IOV_GVAL(IOV_SBREG):
+ {
+ sdreg_t sdreg;
+ uint32 addr, coreidx;
+
+ bcopy(params, &sdreg, sizeof(sdreg));
+
+ addr = sdreg.offset;
+ coreidx = (addr & 0xF000) >> 12;
+
+ int_val = si_corereg(bus->sih, coreidx, (addr & 0xFFF), 0, 0);
+ bcopy(&int_val, arg, sizeof(int32));
+ break;
+ }
+
+ case IOV_SVAL(IOV_SBREG):
+ {
+ sdreg_t sdreg;
+ uint32 addr, coreidx;
+
+ bcopy(params, &sdreg, sizeof(sdreg));
+
+ addr = sdreg.offset;
+ coreidx = (addr & 0xF000) >> 12;
+
+ si_corereg(bus->sih, coreidx, (addr & 0xFFF), ~0, sdreg.value);
+
+ break;
+ }
+
+
+ case IOV_GVAL(IOV_PCIECOREREG):
+ int_val = si_corereg(bus->sih, bus->sih->buscoreidx, int_val, 0, 0);
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_PCIECFGREG):
+ OSL_PCI_WRITE_CONFIG(bus->osh, int_val, 4, int_val2);
+ break;
+
+ case IOV_GVAL(IOV_PCIECFGREG):
+ int_val = OSL_PCI_READ_CONFIG(bus->osh, int_val, 4);
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_PCIE_LPBK):
+ bcmerror = dhdpcie_bus_lpback_req(bus, int_val);
+ break;
+
+ case IOV_GVAL(IOV_MEMSIZE):
+ int_val = (int32)bus->ramsize;
+ bcopy(&int_val, arg, val_size);
+ break;
+ case IOV_SVAL(IOV_MEMBYTES):
+ case IOV_GVAL(IOV_MEMBYTES):
+ {
+ uint32 address; /* absolute backplane address */
+ uint size, dsize;
+ uint8 *data;
+
+ bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
+
+ ASSERT(plen >= 2*sizeof(int));
+
+ address = (uint32)int_val;
+ bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
+ size = (uint)int_val;
+
+ /* Do some validation */
+ dsize = set ? plen - (2 * sizeof(int)) : len;
+ if (dsize < size) {
+ DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
+ __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
+ bcmerror = BCME_BADARG;
+ break;
+ }
+
+ DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n dsize %d ", __FUNCTION__,
+ (set ? "write" : "read"), size, address, dsize));
+
+ /* check if CR4 */
+ if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ /* if address is 0, store the reset instruction to be written in 0 */
+ if (set && address == bus->dongle_ram_base) {
+ bus->resetinstr = *(((uint32*)params) + 2);
+ }
+ } else {
+ /* If we know about SOCRAM, check for a fit */
+ if ((bus->orig_ramsize) &&
+ ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize)))
+ {
+ uint8 enable, protect, remap;
+ si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
+ if (!enable || protect) {
+ DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
+ __FUNCTION__, bus->orig_ramsize, size, address));
+ DHD_ERROR(("%s: socram enable %d, protect %d\n",
+ __FUNCTION__, enable, protect));
+ bcmerror = BCME_BADARG;
+ break;
+ }
+
+ if (!REMAP_ENAB(bus) && (address >= SOCDEVRAM_ARM_ADDR)) {
+ uint32 devramsize = si_socdevram_size(bus->sih);
+ if ((address < SOCDEVRAM_ARM_ADDR) ||
+ (address + size > (SOCDEVRAM_ARM_ADDR + devramsize))) {
+ DHD_ERROR(("%s: bad address 0x%08x, size 0x%08x\n",
+ __FUNCTION__, address, size));
+ DHD_ERROR(("%s: socram range 0x%08x,size 0x%08x\n",
+ __FUNCTION__, SOCDEVRAM_ARM_ADDR, devramsize));
+ bcmerror = BCME_BADARG;
+ break;
+ }
+ /* move it such that address is real now */
+ address -= SOCDEVRAM_ARM_ADDR;
+ address += SOCDEVRAM_BP_ADDR;
+ DHD_INFO(("%s: Request to %s %d bytes @ Mapped address 0x%08x\n",
+ __FUNCTION__, (set ? "write" : "read"), size, address));
+ } else if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address) && remap) {
+ /* Can not access remap region while devram remap bit is set
+ * ROM content would be returned in this case
+ */
+ DHD_ERROR(("%s: Need to disable remap for address 0x%08x\n",
+ __FUNCTION__, address));
+ bcmerror = BCME_ERROR;
+ break;
+ }
+ }
+ }
+
+ /* Generate the actual data pointer */
+ data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
+
+ /* Call to do the transfer */
+ bcmerror = dhdpcie_bus_membytes(bus, set, address, data, size);
+
+ break;
+ }
+
+ case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
+ bcmerror = dhdpcie_bus_download_state(bus, bool_val);
+ break;
+
+ case IOV_GVAL(IOV_RAMSIZE):
+ int_val = (int32)bus->ramsize;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_RAMSTART):
+ int_val = (int32)bus->dongle_ram_base;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_CC_NVMSHADOW):
+ {
+ struct bcmstrbuf dump_b;
+
+ bcm_binit(&dump_b, arg, len);
+ bcmerror = dhdpcie_cc_nvmshadow(bus, &dump_b);
+ break;
+ }
+
+ case IOV_GVAL(IOV_SLEEP_ALLOWED):
+ bool_val = bus->sleep_allowed;
+ bcopy(&bool_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_SLEEP_ALLOWED):
+ bus->sleep_allowed = bool_val;
+ break;
+
+ case IOV_GVAL(IOV_DONGLEISOLATION):
+ int_val = bus->dhd->dongle_isolation;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DONGLEISOLATION):
+ bus->dhd->dongle_isolation = bool_val;
+ break;
+
+ case IOV_GVAL(IOV_LTRSLEEPON_UNLOOAD):
+ int_val = bus->ltrsleep_on_unload;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_LTRSLEEPON_UNLOOAD):
+ bus->ltrsleep_on_unload = bool_val;
+ break;
+
+ default:
+ bcmerror = BCME_UNSUPPORTED;
+ break;
+ }
+
+exit:
+
+
+ dhd_os_sdunlock(bus->dhd);
+
+ return bcmerror;
+}
+/* Transfers bytes from host to dongle using pio mode */
+static int
+dhdpcie_bus_lpback_req(struct dhd_bus *bus, uint32 len)
+{
+ if (bus->dhd == NULL) {
+ DHD_ERROR(("bus not inited\n"));
+ return 0;
+ }
+ if (bus->dhd->prot == NULL) {
+ DHD_ERROR(("prot is not inited\n"));
+ return 0;
+ }
+ if (bus->dhd->busstate != DHD_BUS_DATA) {
+ DHD_ERROR(("not in a readystate to LPBK is not inited\n"));
+ return 0;
+ }
+ dhdmsgbuf_lpbk_req(bus->dhd, len);
+ return 0;
+}
+
+
+
+static int
+dhdpcie_bus_download_state(dhd_bus_t *bus, bool enter)
+{
+ int bcmerror = 0;
+ uint32 *cr4_regs;
+
+ if (!bus->sih)
+ return BCME_ERROR;
+ /* To enter download state, disable ARM and reset SOCRAM.
+ * To exit download state, simply reset ARM (default is RAM boot).
+ */
+ if (enter) {
+ bus->alp_only = TRUE;
+
+ /* some chips (e.g. 43602) have two ARM cores, the CR4 is receives the firmware. */
+ cr4_regs = si_setcore(bus->sih, ARMCR4_CORE_ID, 0);
+
+ if (cr4_regs == NULL && !(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
+ !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+ if (cr4_regs == NULL) { /* no CR4 present on chip */
+ si_core_disable(bus->sih, 0);
+
+ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+ si_core_reset(bus->sih, 0, 0);
+
+
+ /* Clear the top bit of memory */
+ if (bus->ramsize) {
+ uint32 zeros = 0;
+ if (dhdpcie_bus_membytes(bus, TRUE, bus->ramsize - 4,
+ (uint8*)&zeros, 4) < 0) {
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+ }
+ } else {
+ /* For CR4,
+ * Halt ARM
+ * Remove ARM reset
+ * Read RAM base address [0x18_0000]
+ * [next] Download firmware
+ * [done at else] Populate the reset vector
+ * [done at else] Remove ARM halt
+ */
+ /* Halt ARM & remove reset */
+ si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
+ if (bus->sih->chip == BCM43602_CHIP_ID) {
+ W_REG(bus->pcie_mb_intr_osh, cr4_regs + ARMCR4REG_BANKIDX, 5);
+ W_REG(bus->pcie_mb_intr_osh, cr4_regs + ARMCR4REG_BANKPDA, 0);
+ W_REG(bus->pcie_mb_intr_osh, cr4_regs + ARMCR4REG_BANKIDX, 7);
+ W_REG(bus->pcie_mb_intr_osh, cr4_regs + ARMCR4REG_BANKPDA, 0);
+ }
+ /* reset last 4 bytes of RAM address. to be used for shared area */
+ dhdpcie_init_shared_addr(bus);
+ }
+ } else {
+ if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+ if (!si_iscoreup(bus->sih)) {
+ DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+
+ /* Enable remap before ARM reset but after vars.
+ * No backplane access in remap mode
+ */
+
+ if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
+ !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
+ DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+
+ if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
+ !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+ } else {
+ if (bus->sih->chip == BCM43602_CHIP_ID) {
+ /* Firmware crashes on SOCSRAM access when core is in reset */
+ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find SOCRAM core!\n",
+ __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+ si_core_reset(bus->sih, 0, 0);
+ si_setcore(bus->sih, ARMCR4_CORE_ID, 0);
+ }
+
+ /* write vars */
+ if ((bcmerror = dhdpcie_bus_write_vars(bus))) {
+ DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
+ goto fail;
+ }
+
+
+ /* switch back to arm core again */
+ if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find ARM CR4 core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+ /* write address 0 with reset instruction */
+ bcmerror = dhdpcie_bus_membytes(bus, TRUE, 0,
+ (uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
+
+ /* now remove reset and halt and continue to run CR4 */
+ }
+
+ si_core_reset(bus->sih, 0, 0);
+
+ /* Allow HT Clock now that the ARM is running. */
+ bus->alp_only = FALSE;
+
+ bus->dhd->busstate = DHD_BUS_LOAD;
+ }
+
+fail:
+ /* Always return to PCIE core */
+ si_setcore(bus->sih, PCIE2_CORE_ID, 0);
+
+ return bcmerror;
+}
+
+static int
+dhdpcie_bus_write_vars(dhd_bus_t *bus)
+{
+ int bcmerror = 0;
+ uint32 varsize, phys_size;
+ uint32 varaddr;
+ uint8 *vbuffer;
+ uint32 varsizew;
+#ifdef DHD_DEBUG
+ uint8 *nvram_ularray;
+#endif /* DHD_DEBUG */
+
+ /* Even if there are no vars are to be written, we still need to set the ramsize. */
+ varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
+ varaddr = (bus->ramsize - 4) - varsize;
+
+ varaddr += bus->dongle_ram_base;
+
+ if (bus->vars) {
+
+ vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
+ if (!vbuffer)
+ return BCME_NOMEM;
+
+ bzero(vbuffer, varsize);
+ bcopy(bus->vars, vbuffer, bus->varsz);
+ /* Write the vars list */
+ bcmerror = dhdpcie_bus_membytes(bus, TRUE, varaddr, vbuffer, varsize);
+ /* Implement read back and verify later */
+#ifdef DHD_DEBUG
+ /* Verify NVRAM bytes */
+ DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
+ nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
+ if (!nvram_ularray)
+ return BCME_NOMEM;
+
+ /* Upload image to verify downloaded contents. */
+ memset(nvram_ularray, 0xaa, varsize);
+
+ /* Read the vars list to temp buffer for comparison */
+ bcmerror = dhdpcie_bus_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, varsize, varaddr));
+ }
+ /* Compare the org NVRAM with the one read from RAM */
+ if (memcmp(vbuffer, nvram_ularray, varsize)) {
+ DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
+ } else
+ DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
+ __FUNCTION__));
+
+ MFREE(bus->dhd->osh, nvram_ularray, varsize);
+#endif /* DHD_DEBUG */
+
+ MFREE(bus->dhd->osh, vbuffer, varsize);
+ }
+
+ phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
+
+ phys_size += bus->dongle_ram_base;
+
+ /* adjust to the user specified RAM */
+ DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
+ phys_size, bus->ramsize));
+ DHD_INFO(("Vars are at %d, orig varsize is %d\n",
+ varaddr, varsize));
+ varsize = ((phys_size - 4) - varaddr);
+
+ /*
+ * Determine the length token:
+ * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
+ */
+ if (bcmerror) {
+ varsizew = 0;
+ bus->nvram_csm = varsizew;
+ } else {
+ varsizew = varsize / 4;
+ varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
+ bus->nvram_csm = varsizew;
+ varsizew = htol32(varsizew);
+ }
+
+ DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
+
+ /* Write the length token to the last word */
+ bcmerror = dhdpcie_bus_membytes(bus, TRUE, (phys_size - 4),
+ (uint8*)&varsizew, 4);
+
+ return bcmerror;
+}
+
+int
+dhdpcie_downloadvars(dhd_bus_t *bus, void *arg, int len)
+{
+ int bcmerror = BCME_OK;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* Basic sanity checks */
+ if (bus->dhd->up) {
+ bcmerror = BCME_NOTDOWN;
+ goto err;
+ }
+ if (!len) {
+ bcmerror = BCME_BUFTOOSHORT;
+ goto err;
+ }
+
+ /* Free the old ones and replace with passed variables */
+ if (bus->vars)
+ MFREE(bus->dhd->osh, bus->vars, bus->varsz);
+
+ bus->vars = MALLOC(bus->dhd->osh, len);
+ bus->varsz = bus->vars ? len : 0;
+ if (bus->vars == NULL) {
+ bcmerror = BCME_NOMEM;
+ goto err;
+ }
+
+ /* Copy the passed variables, which should include the terminating double-null */
+ bcopy(arg, bus->vars, bus->varsz);
+err:
+ return bcmerror;
+}
+
+/* Add bus dump output to a buffer */
+void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+{
+
+}
+
+/* Mailbox ringbell Function */
+static void
+dhd_bus_gen_devmb_intr(struct dhd_bus *bus)
+{
+ if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
+ (bus->sih->buscorerev == 4)) {
+ DHD_ERROR(("mailbox communication not supported\n"));
+ return;
+ }
+ /* this is a pcie core register, not the config regsiter */
+ DHD_INFO(("writing a mail box interrupt to the device, through config space\n"));
+ dhdpcie_bus_cfg_write_dword(bus, PCISBMbx, 4, (1 << 0));
+}
+
+/* doorbell ring Function */
+void
+dhd_bus_ringbell(struct dhd_bus *bus, uint32 value)
+{
+ if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
+ (bus->sih->buscorerev == 4)) {
+ si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, PCIE_INTB, PCIE_INTB);
+ } else {
+ /* this is a pcie core register, not the config regsiter */
+ DHD_INFO(("writing a door bell to the device\n"));
+ si_corereg(bus->sih, bus->sih->buscoreidx, PCIH2D_MailBox, ~0, 0x12345678);
+ }
+}
+
+static void
+dhd_bus_ringbell_fast(struct dhd_bus *bus, uint32 value)
+{
+ W_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_addr, value);
+}
+
+static void
+dhd_bus_ringbell_oldpcie(struct dhd_bus *bus, uint32 value)
+{
+ uint32 w;
+ w = (R_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_addr) & ~PCIE_INTB) | PCIE_INTB;
+ W_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_addr, w);
+}
+
+dhd_mb_ring_t
+dhd_bus_get_mbintr_fn(struct dhd_bus *bus)
+{
+ if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
+ (bus->sih->buscorerev == 4)) {
+ bus->pcie_mb_intr_addr = si_corereg_addr(bus->sih, bus->sih->buscoreidx,
+ PCIMailBoxInt);
+ if (bus->pcie_mb_intr_addr) {
+ bus->pcie_mb_intr_osh = si_osh(bus->sih);
+ return dhd_bus_ringbell_oldpcie;
+ }
+ } else {
+ bus->pcie_mb_intr_addr = si_corereg_addr(bus->sih, bus->sih->buscoreidx,
+ PCIH2D_MailBox);
+ if (bus->pcie_mb_intr_addr) {
+ bus->pcie_mb_intr_osh = si_osh(bus->sih);
+ return dhd_bus_ringbell_fast;
+ }
+ }
+ return dhd_bus_ringbell;
+}
+
+bool BCMFASTPATH
+dhd_bus_dpc(struct dhd_bus *bus)
+{
+ uint32 intstatus = 0;
+ uint32 newstatus = 0;
+ bool resched = FALSE; /* Flag indicating resched wanted */
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd->busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
+ bus->intstatus = 0;
+ return 0;
+ }
+
+#ifndef DHD_ALLIRQ
+ dhd_os_sdlock(bus->dhd);
+#endif /* DHD_ALLIRQ */
+ intstatus = bus->intstatus;
+
+ if ((bus->sih->buscorerev == 6) || (bus->sih->buscorerev == 4) ||
+ (bus->sih->buscorerev == 2)) {
+ newstatus = dhdpcie_bus_cfg_read_dword(bus, PCIIntstatus, 4);
+ dhdpcie_bus_cfg_write_dword(bus, PCIIntstatus, 4, newstatus);
+ /* Merge new bits with previous */
+ intstatus |= newstatus;
+ bus->intstatus = 0;
+ if (intstatus & I_MB) {
+ dhdpcie_bus_process_mailbox_intr(bus, intstatus);
+ }
+ } else {
+ /* this is a PCIE core register..not a config register... */
+ newstatus = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, 0, 0);
+ intstatus |= (newstatus & bus->def_intmask);
+ si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, intstatus, intstatus);
+ if (intstatus & bus->def_intmask) {
+ dhdpcie_bus_process_mailbox_intr(bus, intstatus);
+ intstatus &= ~bus->def_intmask;
+ }
+ }
+
+ dhdpcie_bus_intr_enable(bus);
+#ifndef DHD_ALLIRQ
+ dhd_os_sdunlock(bus->dhd);
+#endif /* DHD_ALLIRQ */
+ return resched;
+
+}
+
+
+static void
+dhdpcie_send_mb_data(dhd_bus_t *bus, uint32 h2d_mb_data)
+{
+ uint32 cur_h2d_mb_data = 0;
+
+ dhd_bus_cmn_readshared(bus, &cur_h2d_mb_data, HTOD_MB_DATA);
+
+ if (cur_h2d_mb_data != 0) {
+ uint32 i = 0;
+ DHD_INFO(("GRRRRRRR: MB transaction is already pending 0x%04x\n", cur_h2d_mb_data));
+ while ((i++ < 100) && cur_h2d_mb_data) {
+ OSL_DELAY(10);
+ dhd_bus_cmn_readshared(bus, &cur_h2d_mb_data, HTOD_MB_DATA);
+ }
+ if (i >= 100)
+ DHD_ERROR(("waited 1ms for the dngl to ack the previous mb transaction\n"));
+ }
+
+ dhd_bus_cmn_writeshared(bus, &h2d_mb_data, sizeof(uint32), HTOD_MB_DATA);
+ dhd_bus_gen_devmb_intr(bus);
+}
+
+static void
+dhdpcie_handle_mb_data(dhd_bus_t *bus)
+{
+ uint32 d2h_mb_data = 0;
+ uint32 zero = 0;
+
+ dhd_bus_cmn_readshared(bus, &d2h_mb_data, DTOH_MB_DATA);
+ if (!d2h_mb_data)
+ return;
+
+ dhd_bus_cmn_writeshared(bus, &zero, sizeof(uint32), DTOH_MB_DATA);
+
+ DHD_INFO(("D2H_MB_DATA: 0x%04x\n", d2h_mb_data));
+ if (d2h_mb_data & D2H_DEV_DS_ENTER_REQ) {
+ /* what should we do */
+ DHD_INFO(("D2H_MB_DATA: DEEP SLEEP REQ\n"));
+ dhdpcie_send_mb_data(bus, H2D_HOST_DS_ACK);
+ DHD_INFO(("D2H_MB_DATA: sent DEEP SLEEP ACK\n"));
+ }
+ if (d2h_mb_data & D2H_DEV_DS_EXIT_NOTE) {
+ /* what should we do */
+ DHD_INFO(("D2H_MB_DATA: DEEP SLEEP EXIT\n"));
+ }
+ if (d2h_mb_data & D2H_DEV_D3_ACK) {
+ /* what should we do */
+ DHD_INFO(("D2H_MB_DATA: D3 ACK\n"));
+ }
+}
+
+static void
+dhdpcie_bus_process_mailbox_intr(dhd_bus_t *bus, uint32 intstatus)
+{
+
+ if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
+ (bus->sih->buscorerev == 4)) {
+ /* Msg stream interrupt */
+ if (intstatus & I_BIT1) {
+ dhdpci_bus_read_frames(bus);
+ } else if (intstatus & I_BIT0) {
+ /* do nothing for Now */
+ }
+ }
+ else {
+ if (intstatus & (PCIE_MB_TOPCIE_FN0_0 | PCIE_MB_TOPCIE_FN0_1))
+ dhdpcie_handle_mb_data(bus);
+ if (intstatus & PCIE_MB_D2H_MB_MASK)
+ dhdpci_bus_read_frames(bus);
+ }
+
+}
+
+/* Decode dongle to host message stream */
+static void
+dhdpci_bus_read_frames(dhd_bus_t *bus)
+{
+ /* There may be frames in both ctrl buf and data buf; check ctrl buf first */
+ if (dhd_prot_dtohsplit(bus->dhd))
+ dhd_prot_process_ctrlbuf(bus->dhd);
+ dhd_prot_process_msgbuf(bus->dhd);
+}
+
+static int
+dhdpcie_readshared(dhd_bus_t *bus)
+{
+ uint32 addr = 0;
+ int rv;
+ uint32 shaddr = 0;
+ pciedev_shared_t *sh = bus->pcie_sh;
+ dhd_timeout_t tmo;
+
+ shaddr = bus->dongle_ram_base + bus->ramsize - 4;
+ /* start a timer for 5 seconds */
+ dhd_timeout_start(&tmo, MAX_READ_TIMEOUT);
+
+ while (((addr == 0) || (addr == bus->nvram_csm)) && !dhd_timeout_expired(&tmo)) {
+ /* Read last word in memory to determine address of sdpcm_shared structure */
+ if ((rv = dhdpcie_bus_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
+ return rv;
+
+ addr = ltoh32(addr);
+ }
+
+ if ((addr == 0) || (addr == bus->nvram_csm)) {
+ DHD_ERROR(("%s: address (0x%08x) of pciedev_shared invalid\n",
+ __FUNCTION__, addr));
+ DHD_ERROR(("Waited %u usec, dongle is not ready\n", tmo.elapsed));
+ return BCME_ERROR;
+ } else {
+ bus->shared_addr = (ulong)addr;
+ DHD_ERROR(("PCIe shared addr read took %u usec "
+ "before dongle is ready\n", tmo.elapsed));
+ }
+
+ /* Read hndrte_shared structure */
+ if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr, (uint8 *)sh,
+ sizeof(pciedev_shared_t))) < 0) {
+ DHD_ERROR(("Failed to read PCIe shared struct,"
+ "size read %d < %d\n", rv, (int)sizeof(pciedev_shared_t)));
+ return rv;
+ }
+
+ /* Endianness */
+ sh->flags = ltoh32(sh->flags);
+ sh->trap_addr = ltoh32(sh->trap_addr);
+ sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
+ sh->assert_file_addr = ltoh32(sh->assert_file_addr);
+ sh->assert_line = ltoh32(sh->assert_line);
+ sh->console_addr = ltoh32(sh->console_addr);
+ sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
+ sh->dma_rxoffset = ltoh32(sh->dma_rxoffset);
+ sh->rings_info_ptr = ltoh32(sh->rings_info_ptr);
+ /* load bus console address */
+
+#ifdef DHD_DEBUG
+ bus->console_addr = sh->console_addr;
+#endif
+
+ /* Read the dma rx offset */
+ bus->dma_rxoffset = bus->pcie_sh->dma_rxoffset;
+ dhd_prot_rx_dataoffset(bus->dhd, bus->dma_rxoffset);
+
+ DHD_ERROR(("DMA RX offset from shared Area %d\n", bus->dma_rxoffset));
+
+ if ((sh->flags & PCIE_SHARED_VERSION_MASK) > PCIE_SHARED_VERSION) {
+ DHD_ERROR(("%s: pcie_shared version %d in dhd "
+ "is older than pciedev_shared version %d in dongle\n",
+ __FUNCTION__, PCIE_SHARED_VERSION,
+ sh->flags & PCIE_SHARED_VERSION_MASK));
+ return BCME_ERROR;
+ }
+ /* get ring_info, ring_state and mb data ptrs and store the addresses in bus structure */
+ {
+ ring_info_t ring_info;
+ uint32 tcm_rmem_loc;
+ uint32 tcm_rstate_loc;
+
+ if ((rv = dhdpcie_bus_membytes(bus, FALSE, sh->rings_info_ptr,
+ (uint8 *)&ring_info, sizeof(ring_info_t))) < 0)
+ return rv;
+ bus->h2d_ring_count = ring_info.h2d_ring_count;
+ bus->d2h_ring_count = ring_info.d2h_ring_count;
+
+ bus->h2d_mb_data_ptr_addr = ltoh32(sh->h2d_mb_data_ptr);
+ bus->d2h_mb_data_ptr_addr = ltoh32(sh->d2h_mb_data_ptr);
+
+ bus->ringmem_ptr = ltoh32(ring_info.ringmem_ptr);
+ bus->ring_state_ptr = ltoh32(ring_info.ring_state_ptr);
+
+ bcm_print_bytes("ring_info_raw", (uchar *)&ring_info, sizeof(ring_info_t));
+ DHD_INFO(("ring_info\n"));
+ DHD_INFO(("h2d_ring_count %d\n", bus->h2d_ring_count));
+ DHD_INFO(("d2h_ring_count %d\n", bus->d2h_ring_count));
+ DHD_INFO(("ringmem_ptr 0x%04x\n", bus->ringmem_ptr));
+ DHD_INFO(("ringstate_ptr 0x%04x\n", bus->ring_state_ptr));
+
+ tcm_rmem_loc = bus->ringmem_ptr;
+ tcm_rstate_loc = bus->ring_state_ptr;
+
+ if (bus->h2d_ring_count > 1) {
+ bus->h2d_ctrl_ring_mem_addr = tcm_rmem_loc;
+ tcm_rmem_loc += sizeof(ring_mem_t);
+ bus->h2d_ctrl_ring_state_addr = tcm_rstate_loc;
+ tcm_rstate_loc += sizeof(ring_state_t);
+ }
+ bus->h2d_data_ring_mem_addr = tcm_rmem_loc;
+ tcm_rmem_loc += sizeof(ring_mem_t);
+ bus->h2d_data_ring_state_addr = tcm_rstate_loc;
+ tcm_rstate_loc += sizeof(ring_state_t);
+
+ if (bus->d2h_ring_count > 1) {
+ bus->d2h_ctrl_ring_mem_addr = tcm_rmem_loc;
+ tcm_rmem_loc += sizeof(ring_mem_t);
+ bus->d2h_ctrl_ring_state_addr = tcm_rstate_loc;
+ tcm_rstate_loc += sizeof(ring_state_t);
+ }
+ bus->d2h_data_ring_mem_addr = tcm_rmem_loc;
+ bus->d2h_data_ring_state_addr = tcm_rstate_loc;
+
+ DHD_INFO(("ring_mem\n"));
+ DHD_INFO(("h2d_data_ring_mem 0x%04x\n", bus->h2d_data_ring_mem_addr));
+ DHD_INFO(("h2d_ctrl_ring_mem 0x%04x\n", bus->h2d_ctrl_ring_mem_addr));
+ DHD_INFO(("d2h_data_ring_mem 0x%04x\n", bus->d2h_data_ring_mem_addr));
+ DHD_INFO(("d2h_ctrl_ring_mem 0x%04x\n", bus->d2h_ctrl_ring_mem_addr));
+
+ DHD_INFO(("ring_state\n"));
+ DHD_INFO(("h2d_data_ring_state 0x%04x\n", bus->h2d_data_ring_state_addr));
+ DHD_INFO(("h2d_ctrl_ring_state 0x%04x\n", bus->h2d_ctrl_ring_state_addr));
+ DHD_INFO(("d2h_data_ring_state 0x%04x\n", bus->d2h_data_ring_state_addr));
+ DHD_INFO(("d2h_ctrl_ring_state 0x%04x\n", bus->d2h_ctrl_ring_state_addr));
+
+ DHD_INFO(("mail box address\n"));
+ DHD_INFO(("h2d_mb_data_ptr_addr 0x%04x\n", bus->h2d_mb_data_ptr_addr));
+ DHD_INFO(("d2h_mb_data_ptr_addr 0x%04x\n", bus->d2h_mb_data_ptr_addr));
+ }
+ return BCME_OK;
+}
+
+
+/* Initialize bus module: prepare for communication w/dongle */
+int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ int ret = 0;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ASSERT(bus->dhd);
+ if (!bus->dhd)
+ return 0;
+
+ if (enforce_mutex)
+ dhd_os_sdlock(bus->dhd);
+
+ /* Make sure we're talking to the core. */
+ bus->reg = si_setcore(bus->sih, PCIE2_CORE_ID, 0);
+ ASSERT(bus->reg != NULL);
+
+ /* before opening up bus for data transfer, check if shared are is intact */
+ ret = dhdpcie_readshared(bus);
+ if (ret < 0) {
+ DHD_ERROR(("%s :Shared area read failed \n", __FUNCTION__));
+ return ret;
+ }
+
+
+ /* Make sure we're talking to the core. */
+ bus->reg = si_setcore(bus->sih, PCIE2_CORE_ID, 0);
+ ASSERT(bus->reg != NULL);
+
+ /* Set bus state according to enable result */
+ dhdp->busstate = DHD_BUS_DATA;
+
+ /* Enable the interrupt after device is up */
+ dhdpcie_bus_intr_enable(bus);
+
+ /* bcmsdh_intr_unmask(bus->sdh); */
+
+ if (enforce_mutex)
+ dhd_os_sdunlock(bus->dhd);
+
+ return ret;
+
+}
+
+
+static void
+dhdpcie_init_shared_addr(dhd_bus_t *bus)
+{
+ uint32 addr = 0;
+ uint32 val = 0;
+ addr = bus->dongle_ram_base + bus->ramsize - 4;
+ dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val));
+}
+
+
+bool
+dhdpcie_chipmatch(uint16 vendor, uint16 device)
+{
+ if (vendor != PCI_VENDOR_ID_BROADCOM) {
+ DHD_ERROR(("%s: Unsupported vendor %x device %x\n", __FUNCTION__,
+ vendor, device));
+ return (-ENODEV);
+ }
+
+ if ((device == BCM4350_D11AC_ID) || (device == BCM4350_D11AC2G_ID) ||
+ (device == BCM4350_D11AC5G_ID) || BCM4350_CHIP(device))
+ return 0;
+
+ if ((device == BCM4354_D11AC_ID) || (device == BCM4354_D11AC2G_ID) ||
+ (device == BCM4354_D11AC5G_ID) || (device == BCM4354_CHIP_ID))
+ return 0;
+
+ if ((device == BCM4345_D11AC_ID) || (device == BCM4345_D11AC2G_ID) ||
+ (device == BCM4345_D11AC5G_ID) || (device == BCM4345_CHIP_ID))
+ return 0;
+
+ if ((device == BCM4335_D11AC_ID) || (device == BCM4335_D11AC2G_ID) ||
+ (device == BCM4335_D11AC5G_ID) || (device == BCM4335_CHIP_ID))
+ return 0;
+
+ if ((device == BCM43602_D11AC_ID) || (device == BCM43602_D11AC2G_ID) ||
+ (device == BCM43602_D11AC5G_ID) || (device == BCM43602_CHIP_ID))
+ return 0;
+
+
+ DHD_ERROR(("%s: Unsupported vendor %x device %x\n", __FUNCTION__, vendor, device));
+ return (-ENODEV);
+}
+
+
+/*
+
+Name: dhdpcie_cc_nvmshadow
+
+Description:
+A shadow of OTP/SPROM exists in ChipCommon Region
+betw. 0x800 and 0xBFF (Backplane Addr. 0x1800_0800 and 0x1800_0BFF).
+Strapping option (SPROM vs. OTP), presence of OTP/SPROM and its size
+can also be read from ChipCommon Registers.
+*/
+
+static int
+dhdpcie_cc_nvmshadow(dhd_bus_t *bus, struct bcmstrbuf *b)
+{
+ uint16 dump_offset = 0;
+ uint32 dump_size = 0, otp_size = 0, sprom_size = 0;
+
+ /* Table for 65nm OTP Size (in bits) */
+ int otp_size_65nm[8] = {0, 2048, 4096, 8192, 4096, 6144, 512, 1024};
+
+ volatile uint16 *nvm_shadow;
+
+ uint cur_coreid;
+ uint chipc_corerev;
+ chipcregs_t *chipcregs;
+
+
+ /* Save the current core */
+ cur_coreid = si_coreid(bus->sih);
+ /* Switch to ChipC */
+ chipcregs = (chipcregs_t *)si_setcore(bus->sih, CC_CORE_ID, 0);
+ chipc_corerev = si_corerev(bus->sih);
+
+ /* Check ChipcommonCore Rev */
+ if (chipc_corerev < 44) {
+ DHD_ERROR(("%s: ChipcommonCore Rev %d < 44\n", __FUNCTION__, chipc_corerev));
+ return BCME_UNSUPPORTED;
+ }
+
+ /* Check ChipID */
+ if (((uint16)bus->sih->chip != BCM4350_CHIP_ID) &&
+ ((uint16)bus->sih->chip != BCM4345_CHIP_ID)) {
+ DHD_ERROR(("%s: cc_nvmdump cmd. supported for 4350/4345 only\n",
+ __FUNCTION__));
+ return BCME_UNSUPPORTED;
+ }
+
+ /* Check if SRC_PRESENT in SpromCtrl(0x190 in ChipCommon Regs) is set */
+ if (chipcregs->sromcontrol & SRC_PRESENT) {
+ /* SPROM Size: 1Kbits (0x0), 4Kbits (0x1), 16Kbits(0x2) */
+ sprom_size = (1 << (2 * ((chipcregs->sromcontrol & SRC_SIZE_MASK)
+ >> SRC_SIZE_SHIFT))) * 1024;
+ bcm_bprintf(b, "\nSPROM Present (Size %d bits)\n", sprom_size);
+ }
+
+ if (chipcregs->sromcontrol & SRC_OTPPRESENT) {
+ bcm_bprintf(b, "\nOTP Present");
+
+ if (((chipcregs->otplayout & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT)
+ == OTPL_WRAP_TYPE_40NM) {
+ /* 40nm OTP: Size = (OtpSize + 1) * 1024 bits */
+ otp_size = (((chipcregs->capabilities & CC_CAP_OTPSIZE)
+ >> CC_CAP_OTPSIZE_SHIFT) + 1) * 1024;
+ bcm_bprintf(b, "(Size %d bits)\n", otp_size);
+ } else {
+ /* This part is untested since newer chips have 40nm OTP */
+ otp_size = otp_size_65nm[(chipcregs->capabilities & CC_CAP_OTPSIZE)
+ >> CC_CAP_OTPSIZE_SHIFT];
+ bcm_bprintf(b, "(Size %d bits)\n", otp_size);
+ DHD_INFO(("%s: 65nm/130nm OTP Size not tested. \n",
+ __FUNCTION__));
+ }
+ }
+
+ if (((chipcregs->sromcontrol & SRC_PRESENT) == 0) &&
+ ((chipcregs->capabilities & CC_CAP_OTPSIZE) == 0)) {
+ DHD_ERROR(("%s: SPROM and OTP could not be found \n",
+ __FUNCTION__));
+ return BCME_NOTFOUND;
+ }
+
+ /* Check the strapping option in SpromCtrl: Set = OTP otherwise SPROM */
+ if ((chipcregs->sromcontrol & SRC_OTPSEL) &&
+ (chipcregs->sromcontrol & SRC_OTPPRESENT)) {
+
+ bcm_bprintf(b, "OTP Strap selected.\n"
+ "\nOTP Shadow in ChipCommon:\n");
+
+ dump_size = otp_size / 16 ; /* 16bit words */
+
+ } else if (((chipcregs->sromcontrol & SRC_OTPSEL) == 0) &&
+ (chipcregs->sromcontrol & SRC_PRESENT)) {
+
+ bcm_bprintf(b, "SPROM Strap selected\n"
+ "\nSPROM Shadow in ChipCommon:\n");
+
+ /* If SPROM > 8K only 8Kbits is mapped to ChipCommon (0x800 - 0xBFF) */
+ /* dump_size in 16bit words */
+ dump_size = sprom_size > 8 ? (8 * 1024) / 16 : sprom_size / 16;
+ }
+ else {
+ DHD_ERROR(("%s: NVM Shadow does not exist in ChipCommon\n",
+ __FUNCTION__));
+ return BCME_NOTFOUND;
+ }
+
+ if (bus->regs == NULL) {
+ DHD_ERROR(("ChipCommon Regs. not initialized\n"));
+ return BCME_NOTREADY;
+ } else {
+ bcm_bprintf(b, "\n OffSet:");
+
+ /* Point to the SPROM/OTP shadow in ChipCommon */
+ nvm_shadow = chipcregs->sromotp;
+
+ /*
+ * Read 16 bits / iteration.
+ * dump_size & dump_offset in 16-bit words
+ */
+ while (dump_offset < dump_size) {
+ if (dump_offset % 2 == 0)
+ /* Print the offset in the shadow space in Bytes */
+ bcm_bprintf(b, "\n 0x%04x", dump_offset * 2);
+
+ bcm_bprintf(b, "\t0x%04x", *(nvm_shadow + dump_offset));
+ dump_offset += 0x1;
+ }
+ }
+
+ /* Switch back to the original core */
+ si_setcore(bus->sih, cur_coreid, 0);
+
+ return BCME_OK;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie.h b/drivers/net/wireless/bcmdhd/dhd_pcie.h
new file mode 100644
index 000000000000..d51a53d38a1a
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_pcie.h
@@ -0,0 +1,169 @@
+/*
+ * Linux DHD Bus Module for PCIE
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_pcie.h 452261 2014-01-29 19:30:23Z $
+ */
+
+
+#ifndef dhd_pcie_h
+#define dhd_pcie_h
+
+#include <bcmpcie.h>
+
+/* defines */
+
+#define PCMSGBUF_HDRLEN 20
+#define DONGLE_REG_MAP_SIZE (32 * 1024)
+#define DONGLE_TCM_MAP_SIZE (4096 * 1024)
+#define DONGLE_MIN_MEMSIZE (128 *1024)
+#ifdef DHD_DEBUG
+#define DHD_PCIE_SUCCESS 0
+#define DHD_PCIE_FAILURE 1
+#endif /* DHD_DEBUG */
+#define REMAP_ENAB(bus) ((bus)->remap)
+#define REMAP_ISADDR(bus, a) (((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
+
+
+/* user defined data structures */
+#ifdef DHD_DEBUG
+/* Device console log buffer state */
+#define CONSOLE_LINE_MAX 192
+#define CONSOLE_BUFFER_MAX 2024
+
+
+typedef struct dhd_console {
+ uint count; /* Poll interval msec counter */
+ uint log_addr; /* Log struct address (fixed) */
+ hndrte_log_t log; /* Log struct (host copy) */
+ uint bufsize; /* Size of log buffer */
+ uint8 *buf; /* Log buffer (host copy) */
+ uint last; /* Last buffer read index */
+} dhd_console_t;
+#endif /* DHD_DEBUG */
+
+typedef struct dhd_bus {
+ dhd_pub_t *dhd;
+ struct pci_dev *dev; /* pci device handle */
+ si_t *sih; /* Handle for SI calls */
+ char *vars; /* Variables (from CIS and/or other) */
+ uint varsz; /* Size of variables buffer */
+ uint32 sbaddr; /* Current SB window pointer (-1, invalid) */
+ sbpcieregs_t *reg; /* Registers for PCIE core */
+
+ uint armrev; /* CPU core revision */
+ uint ramrev; /* SOCRAM core revision */
+ uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */
+ uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
+ uint32 srmemsize; /* Size of SRMEM */
+
+ uint32 bus; /* gSPI or SDIO bus */
+ uint32 intstatus; /* Intstatus bits (events) pending */
+ bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
+ bool fcstate; /* State of dongle flow-control */
+
+ uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */
+ char *fw_path; /* module_param: path to firmware image */
+ char *nv_path; /* module_param: path to nvram vars file */
+ const char *nvram_params; /* user specified nvram params. */
+
+ struct pktq txq; /* Queue length used for flow-control */
+
+ uint rxlen; /* Length of valid data in buffer */
+
+
+ bool intr; /* Use interrupts */
+ bool ipend; /* Device interrupt is pending */
+ bool intdis; /* Interrupts disabled by isr */
+ uint intrcount; /* Count of device interrupt callbacks */
+ uint lastintrs; /* Count as of last watchdog timer */
+
+#ifdef DHD_DEBUG
+ dhd_console_t console; /* Console output polling support */
+ uint console_addr; /* Console address from shared struct */
+#endif /* DHD_DEBUG */
+
+ bool alp_only; /* Don't use HT clock (ALP only) */
+
+ bool remap; /* Contiguous 1MB RAM: 512K socram + 512K devram
+ * Available with socram rev 16
+ * Remap region not DMA-able
+ */
+ uint32 resetinstr;
+ uint32 dongle_ram_base;
+
+ ulong shared_addr;
+ pciedev_shared_t *pcie_sh;
+ bool bus_flowctrl;
+ ioct_resp_hdr_t ioct_resp;
+ uint32 dma_rxoffset;
+ volatile char *regs; /* pci device memory va */
+ volatile char *tcm; /* pci device memory va */
+ osl_t *osh;
+ uint32 nvram_csm; /* Nvram checksum */
+ uint16 pollrate;
+ uint16 polltick;
+
+ uint32 *pcie_mb_intr_addr;
+ void *pcie_mb_intr_osh;
+ bool sleep_allowed;
+
+ /* version 3 shared struct related info start */
+ uint8 h2d_ring_count;
+ uint8 d2h_ring_count;
+ uint32 ringmem_ptr;
+ uint32 ring_state_ptr;
+
+ uint32 h2d_data_ring_mem_addr;
+ uint32 h2d_ctrl_ring_mem_addr;
+ uint32 h2d_data_ring_state_addr;
+ uint32 h2d_ctrl_ring_state_addr;
+
+ uint32 d2h_data_ring_mem_addr;
+ uint32 d2h_ctrl_ring_mem_addr;
+ uint32 d2h_data_ring_state_addr;
+ uint32 d2h_ctrl_ring_state_addr;
+
+ uint32 h2d_mb_data_ptr_addr;
+ uint32 d2h_mb_data_ptr_addr;
+ /* version 3 shared struct related info end */
+
+ uint32 def_intmask;
+ bool ltrsleep_on_unload;
+
+} dhd_bus_t;
+
+/* function declarations */
+
+extern uint32* dhdpcie_bus_reg_map(osl_t *osh, ulong addr, int size);
+extern int dhdpcie_bus_register(void);
+extern void dhdpcie_bus_unregister(void);
+extern bool dhdpcie_chipmatch(uint16 vendor, uint16 device);
+
+extern struct dhd_bus* dhdpcie_bus_attach(osl_t *osh, volatile char* regs, volatile char* tcm);
+extern uint32 dhdpcie_bus_cfg_read_dword(struct dhd_bus *bus, uint32 addr, uint32 size);
+extern void dhdpcie_bus_cfg_write_dword(struct dhd_bus *bus, uint32 addr, uint32 size, uint32 data);
+extern void dhdpcie_bus_intr_disable(struct dhd_bus *bus);
+extern void dhdpcie_bus_release(struct dhd_bus *bus);
+extern int32 dhdpcie_bus_isr(struct dhd_bus *bus);
+extern void dhdpcie_free_irq(dhd_bus_t *bus);
+#endif /* dhd_pcie_h */
diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie_linux.c b/drivers/net/wireless/bcmdhd/dhd_pcie_linux.c
new file mode 100644
index 000000000000..85539ae27218
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_pcie_linux.c
@@ -0,0 +1,503 @@
+/*
+ * Linux DHD Bus Module for PCIE
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_pcie_linux.c 452261 2014-01-29 19:30:23Z $
+ */
+
+
+/* include files */
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <bcmdevs.h>
+#include <siutils.h>
+#include <hndsoc.h>
+#include <hndpmu.h>
+#include <sbchipc.h>
+#if defined(DHD_DEBUG)
+#include <hndrte_armtrap.h>
+#include <hndrte_cons.h>
+#endif /* defined(DHD_DEBUG) */
+#include <dngl_stats.h>
+#include <pcie_core.h>
+#include <dhd.h>
+#include <dhd_bus.h>
+#include <dhd_proto.h>
+#include <dhd_dbg.h>
+#include <dhdioctl.h>
+#include <bcmmsgbuf.h>
+#include <pcicfg.h>
+#include <circularbuf.h>
+#include <dhd_pcie.h>
+
+
+#define PCI_CFG_RETRY 10
+#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */
+#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */
+
+#define OSL_PKTTAG_CLEAR(p) \
+do { \
+ struct sk_buff *s = (struct sk_buff *)(p); \
+ ASSERT(OSL_PKTTAG_SZ == 32); \
+ *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \
+ *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \
+ *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
+ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
+} while (0)
+
+
+/* user defined data structures */
+
+typedef struct dhd_pc_res {
+ uint32 bar0_size;
+ void* bar0_addr;
+ uint32 bar1_size;
+ void* bar1_addr;
+} pci_config_res, *pPci_config_res;
+
+typedef bool (*dhdpcie_cb_fn_t)(void *);
+
+typedef struct dhdpcie_info
+{
+ dhd_bus_t *bus;
+ osl_t *osh;
+ struct pci_dev *dev; /* pci device handle */
+ volatile char *regs; /* pci device memory va */
+ volatile char *tcm; /* pci device memory va */
+ uint32 tcm_size; /* pci device memory size */
+ struct pcos_info *pcos_info;
+ uint16 last_intrstatus; /* to cache intrstatus */
+ int irq;
+
+} dhdpcie_info_t;
+
+
+struct pcos_info {
+ dhdpcie_info_t *pc;
+ spinlock_t lock;
+ wait_queue_head_t intr_wait_queue;
+ struct timer_list tuning_timer;
+ int tuning_timer_exp;
+ atomic_t timer_enab;
+ struct tasklet_struct tuning_tasklet;
+};
+
+
+/* function declarations */
+static int __devinit
+dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void __devexit
+dhdpcie_pci_remove(struct pci_dev *pdev);
+static int dhdpcie_init(struct pci_dev *pdev);
+static irqreturn_t dhdpcie_isr(int irq, void *arg);
+static int dhdpcie_pci_suspend(struct pci_dev *dev);
+static int dhdpcie_pci_resume(struct pci_dev *dev);
+static struct pci_device_id dhdpcie_pci_devid[] __devinitdata = {
+ { vendor: 0x14e4,
+ device: PCI_ANY_ID,
+ subvendor: PCI_ANY_ID,
+ subdevice: PCI_ANY_ID,
+ class: PCI_CLASS_NETWORK_OTHER << 8,
+ class_mask: 0xffff00,
+ driver_data: 0,
+ },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, dhdpcie_pci_devid);
+
+static struct pci_driver dhdpcie_driver = {
+ node: {},
+ name: "pcieh",
+ id_table: dhdpcie_pci_devid,
+ probe: dhdpcie_pci_probe,
+ remove: dhdpcie_pci_remove,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+ save_state: NULL,
+#endif
+ suspend: NULL,
+ resume: NULL,
+};
+
+static int dhdpcie_pci_suspend(struct pci_dev *dev)
+{
+ int ret;
+ pci_save_state(dev);
+ pci_enable_wake(dev, PCI_D0, TRUE);
+ pci_disable_device(dev);
+ ret = pci_set_power_state(dev, PCI_D3hot);
+ return ret;
+}
+
+static int dhdpcie_pci_resume(struct pci_dev *dev)
+{
+ int err = 0;
+ uint32 val;
+ pci_restore_state(dev);
+ err = pci_enable_device(dev);
+ if (err) {
+ printf("%s:pci_enable_device error %d \n", __FUNCTION__, err);
+ return err;
+ }
+ pci_set_master(dev);
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state
+ * Code taken from ipw2100 driver
+ */
+ err = pci_set_power_state(dev, PCI_D0);
+ if (err) {
+ printf("%s:pci_set_power_state error %d \n", __FUNCTION__, err);
+ return err;
+ }
+ pci_read_config_dword(dev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
+ return err;
+}
+
+int dhdpcie_pci_suspend_resume(struct pci_dev *dev, bool state)
+{
+ int rc;
+
+ if (state)
+ rc = dhdpcie_pci_suspend(dev);
+ else
+ rc = dhdpcie_pci_resume(dev);
+ return rc;
+}
+int
+dhdpcie_bus_register(void)
+{
+ int error = 0;
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+ if (!(error = pci_module_init(&dhdpcie_driver)))
+ return 0;
+#else
+ if (!(error = pci_register_driver(&dhdpcie_driver)))
+ return 0;
+#endif
+
+ DHD_ERROR(("%s: pci_module_init failed 0x%x\n", __FUNCTION__, error));
+
+ return error;
+}
+
+
+void
+dhdpcie_bus_unregister(void)
+{
+ pci_unregister_driver(&dhdpcie_driver);
+}
+
+int __devinit
+dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+
+ if (dhdpcie_chipmatch (pdev->vendor, pdev->device)) {
+ DHD_ERROR(("%s: chipmatch failed!!\n", __FUNCTION__));
+ return -ENODEV;
+ }
+ printf("PCI_PROBE: bus %X, slot %X,vendor %X, device %X"
+ "(good PCI location)\n", pdev->bus->number,
+ PCI_SLOT(pdev->devfn), pdev->vendor, pdev->device);
+
+ if (dhdpcie_init (pdev)) {
+ DHD_ERROR(("%s: PCIe Enumeration failed\n", __FUNCTION__));
+ return -ENODEV;
+ }
+
+ DHD_TRACE(("%s: PCIe Enumeration done!!\n", __FUNCTION__));
+ return 0;
+}
+
+int
+dhdpcie_detach(dhdpcie_info_t *pch)
+{
+ osl_t *osh = pch->osh;
+ if (pch) {
+ MFREE(osh, pch, sizeof(dhdpcie_info_t));
+ }
+ return 0;
+}
+
+
+void __devexit
+dhdpcie_pci_remove(struct pci_dev *pdev)
+{
+
+ osl_t *osh = NULL;
+ dhdpcie_info_t *pch = NULL;
+ dhd_bus_t *bus = NULL;
+
+ DHD_TRACE(("%s Enter\n", __FUNCTION__));
+ pch = pci_get_drvdata(pdev);
+ bus = pch->bus;
+
+ dhdpcie_bus_release(bus);
+ pci_disable_device(pdev);
+ /* pcie info detach */
+ dhdpcie_detach(pch);
+ /* osl detach */
+ osl_detach(osh);
+
+
+ DHD_TRACE(("%s Exit\n", __FUNCTION__));
+
+ return;
+}
+
+/* Free Linux irq */
+int
+dhdpcie_request_irq(dhdpcie_info_t *dhdpcie_info)
+{
+ dhd_bus_t *bus = dhdpcie_info->bus;
+ struct pci_dev *pdev = dhdpcie_info->bus->dev;
+
+ if (request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED, "dhdpcie", bus) < 0) {
+ DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
+ return -1;
+ }
+
+ return 0; /* SUCCESS */
+}
+
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+#define PRINTF_RESOURCE "0x%016llx"
+#else
+#define PRINTF_RESOURCE "0x%08x"
+#endif
+
+/*
+
+Name: osl_pci_get_resource
+
+Parametrs:
+
+1: struct pci_dev *pdev -- pci device structure
+2: pci_res -- structure containing pci configuration space values
+
+
+Return value:
+
+int - Status (TRUE or FALSE)
+
+Description:
+Access PCI configuration space, retrieve PCI allocated resources , updates in resource structure.
+
+ */
+int dhdpcie_get_resource(dhdpcie_info_t *dhdpcie_info)
+{
+ phys_addr_t bar0_addr, bar1_addr;
+ ulong bar1_size;
+ struct pci_dev *pdev = NULL;
+ pdev = dhdpcie_info->dev;
+ do {
+ if (pci_enable_device(pdev)) {
+ printf("%s: Cannot enable PCI device\n", __FUNCTION__);
+ break;
+ }
+ pci_set_master(pdev);
+ bar0_addr = pci_resource_start(pdev, 0); /* Bar-0 mapped address */
+ bar1_addr = pci_resource_start(pdev, 2); /* Bar-1 mapped address */
+
+ /* read Bar-1 mapped memory range */
+ bar1_size = pci_resource_len(pdev, 2);
+
+ if ((bar1_size == 0) || (bar1_addr == 0)) {
+ printf("%s: BAR1 Not enabled for this device size(%ld),"
+ " addr(0x"PRINTF_RESOURCE")\n",
+ __FUNCTION__, bar1_size, bar1_addr);
+ goto err;
+ }
+
+ dhdpcie_info->regs = (volatile char *) REG_MAP(bar0_addr, DONGLE_REG_MAP_SIZE);
+ dhdpcie_info->tcm = (volatile char *) REG_MAP(bar1_addr, DONGLE_TCM_MAP_SIZE);
+ dhdpcie_info->tcm_size = DONGLE_TCM_MAP_SIZE;
+
+ if (!dhdpcie_info->regs || !dhdpcie_info->tcm) {
+ DHD_ERROR(("%s:ioremap() failed\n", __FUNCTION__));
+ break;
+ }
+ DHD_TRACE(("%s:Phys addr : reg space = %p base addr 0x"PRINTF_RESOURCE" \n",
+ __FUNCTION__, dhdpcie_info->regs, bar0_addr));
+ DHD_TRACE(("%s:Phys addr : tcm_space = %p base addr 0x"PRINTF_RESOURCE" \n",
+ __FUNCTION__, dhdpcie_info->tcm, bar1_addr));
+
+ return 0; /* SUCCESS */
+ } while (0);
+err:
+ return -1; /* FAILURE */
+}
+
+int dhdpcie_scan_resource(dhdpcie_info_t *dhdpcie_info)
+{
+
+ DHD_TRACE(("%s: ENTER\n", __FUNCTION__));
+
+ do {
+ /* define it here only!! */
+ if (dhdpcie_get_resource (dhdpcie_info)) {
+ DHD_ERROR(("%s: Failed to get PCI resources\n", __FUNCTION__));
+ break;
+ }
+ DHD_TRACE(("%s:Exit - SUCCESS \n",
+ __FUNCTION__));
+
+ return 0; /* SUCCESS */
+
+ } while (0);
+
+ DHD_TRACE(("%s:Exit - FAILURE \n", __FUNCTION__));
+
+ return -1; /* FAILURE */
+
+}
+
+int dhdpcie_init(struct pci_dev *pdev)
+{
+
+ osl_t *osh = NULL;
+ dhd_bus_t *bus = NULL;
+ dhdpcie_info_t *dhdpcie_info = NULL;
+
+ do {
+ /* osl attach */
+ if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
+ DHD_ERROR(("%s: osl_attach failed\n", __FUNCTION__));
+ break;
+ }
+
+ /* allocate linux spcific pcie structure here */
+ if (!(dhdpcie_info = MALLOC(osh, sizeof(dhdpcie_info_t)))) {
+ DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
+ break;
+ }
+ bzero(dhdpcie_info, sizeof(dhdpcie_info_t));
+ dhdpcie_info->osh = osh;
+ dhdpcie_info->dev = pdev;
+
+ /* Find the PCI resources, verify the */
+ /* vendor and device ID, map BAR regions and irq, update in structures */
+ if (dhdpcie_scan_resource(dhdpcie_info)) {
+ DHD_ERROR(("%s: dhd_Scan_PCI_Res failed\n", __FUNCTION__));
+
+ break;
+ }
+
+ /* Bus initialization */
+ bus = dhdpcie_bus_attach(osh, dhdpcie_info->regs, dhdpcie_info->tcm);
+ if (!bus) {
+ DHD_ERROR(("%s:dhdpcie_bus_attach() failed\n", __FUNCTION__));
+ break;
+ }
+
+ dhdpcie_info->bus = bus;
+ dhdpcie_info->bus->dev = pdev;
+
+ if (bus->intr) {
+ /* Register interrupt callback, but mask it (not operational yet). */
+ DHD_INTR(("%s: Registering and masking interrupts\n", __FUNCTION__));
+ dhdpcie_bus_intr_disable(bus);
+
+ if (dhdpcie_request_irq(dhdpcie_info)) {
+ DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
+ break;
+ }
+ } else {
+ bus->pollrate = 1;
+ DHD_INFO(("%s: PCIe interrupt function is NOT registered "
+ "due to polling mode\n", __FUNCTION__));
+ }
+
+ if (dhd_download_fw_on_driverload)
+ if (dhd_bus_start(bus->dhd))
+ break;
+
+ /* set private data for pci_dev */
+ pci_set_drvdata(pdev, dhdpcie_info);
+
+ DHD_TRACE(("%s:Exit - SUCCESS \n", __FUNCTION__));
+ return 0; /* return SUCCESS */
+
+ } while (0);
+ /* reverse the initialization in order in case of error */
+
+ if (bus)
+ dhdpcie_bus_release(bus);
+
+ if (dhdpcie_info)
+ dhdpcie_detach(dhdpcie_info);
+ pci_disable_device(pdev);
+ if (osh)
+ osl_detach(osh);
+
+ DHD_TRACE(("%s:Exit - FAILURE \n", __FUNCTION__));
+
+ return -1; /* return FAILURE */
+}
+
+/* Free Linux irq */
+void
+dhdpcie_free_irq(dhd_bus_t *bus)
+{
+ struct pci_dev *pdev = NULL;
+
+ DHD_TRACE(("%s: freeing up the IRQ\n", __FUNCTION__));
+ if (bus) {
+ pdev = bus->dev;
+ free_irq(pdev->irq, bus);
+ }
+ DHD_TRACE(("%s: Exit\n", __FUNCTION__));
+ return;
+}
+
+/*
+
+Name: dhdpcie_isr
+
+Parametrs:
+
+1: IN int irq -- interrupt vector
+2: IN void *arg -- handle to private data structure
+
+Return value:
+
+Status (TRUE or FALSE)
+
+Description:
+Interrupt Service routine checks for the status register,
+disable interrupt and queue DPC if mail box interrupts are raised.
+*/
+
+
+irqreturn_t
+dhdpcie_isr(int irq, void *arg)
+{
+ dhd_bus_t *bus = (dhd_bus_t*)arg;
+ if (dhdpcie_bus_isr(bus))
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c
new file mode 100644
index 000000000000..e1d56e0a566e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_pno.c
@@ -0,0 +1,1899 @@
+/*
+ * Broadcom Dongle Host Driver (DHD)
+ * Prefered Network Offload and Wi-Fi Location Service(WLS) code.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_pno.c 423669 2013-09-18 13:01:55Z yangj$
+ */
+#ifdef PNO_SUPPORT
+#include <typedefs.h>
+#include <osl.h>
+
+#include <epivers.h>
+#include <bcmutils.h>
+
+#include <bcmendian.h>
+#include <linuxver.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/sort.h>
+#include <dngl_stats.h>
+#include <wlioctl.h>
+
+#include <proto/bcmevent.h>
+#include <dhd.h>
+#include <dhd_pno.h>
+#include <dhd_dbg.h>
+
+#ifdef __BIG_ENDIAN
+#include <bcmendian.h>
+#define htod32(i) (bcmswap32(i))
+#define htod16(i) (bcmswap16(i))
+#define dtoh32(i) (bcmswap32(i))
+#define dtoh16(i) (bcmswap16(i))
+#define htodchanspec(i) htod16(i)
+#define dtohchanspec(i) dtoh16(i)
+#else
+#define htod32(i) (i)
+#define htod16(i) (i)
+#define dtoh32(i) (i)
+#define dtoh16(i) (i)
+#define htodchanspec(i) (i)
+#define dtohchanspec(i) (i)
+#endif /* IL_BIGENDINA */
+
+#define NULL_CHECK(p, s, err) \
+ do { \
+ if (!(p)) { \
+ printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \
+ err = BCME_ERROR; \
+ return err; \
+ } \
+ } while (0)
+#define PNO_GET_PNOSTATE(dhd) ((dhd_pno_status_info_t *)dhd->pno_state)
+#define PNO_BESTNET_LEN 1024
+#define PNO_ON 1
+#define PNO_OFF 0
+#define CHANNEL_2G_MAX 14
+#define MAX_NODE_CNT 5
+#define WLS_SUPPORTED(pno_state) (pno_state->wls_supported == TRUE)
+#define TIME_DIFF(timestamp1, timestamp2) (abs((uint32)(timestamp1/1000) \
+ - (uint32)(timestamp2/1000)))
+
+#define ENTRY_OVERHEAD strlen("bssid=\nssid=\nfreq=\nlevel=\nage=\ndist=\ndistSd=\n====")
+#define TIME_MIN_DIFF 5
+static inline bool
+is_dfs(uint16 channel)
+{
+ if (channel >= 52 && channel <= 64) /* class 2 */
+ return TRUE;
+ else if (channel >= 100 && channel <= 140) /* class 4 */
+ return TRUE;
+ else
+ return FALSE;
+}
+int
+dhd_pno_clean(dhd_pub_t *dhd)
+{
+ int pfn = 0;
+ int err;
+ dhd_pno_status_info_t *_pno_state;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ /* Disable PNO */
+ err = dhd_iovar(dhd, 0, "pfn", (char *)&pfn, sizeof(pfn), 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to execute pfn(error : %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ _pno_state->pno_status = DHD_PNO_DISABLED;
+ err = dhd_iovar(dhd, 0, "pfnclear", NULL, 0, 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to execute pfnclear(error : %d)\n",
+ __FUNCTION__, err));
+ }
+exit:
+ return err;
+}
+
+static int
+_dhd_pno_suspend(dhd_pub_t *dhd)
+{
+ int err;
+ int suspend = 1;
+ dhd_pno_status_info_t *_pno_state;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ err = dhd_iovar(dhd, 0, "pfn_suspend", (char *)&suspend, sizeof(suspend), 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to suspend pfn(error :%d)\n", __FUNCTION__, err));
+ goto exit;
+
+ }
+ _pno_state->pno_status = DHD_PNO_SUSPEND;
+exit:
+ return err;
+}
+static int
+_dhd_pno_enable(dhd_pub_t *dhd, int enable)
+{
+ int err = BCME_OK;
+ dhd_pno_status_info_t *_pno_state;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+
+ if (enable & 0xfffe) {
+ DHD_ERROR(("%s invalid value\n", __FUNCTION__));
+ err = BCME_BADARG;
+ goto exit;
+ }
+ if (!dhd_support_sta_mode(dhd)) {
+ DHD_ERROR(("PNO is not allowed for non-STA mode"));
+ err = BCME_BADOPTION;
+ goto exit;
+ }
+ if (enable) {
+ if ((_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) &&
+ dhd_is_associated(dhd, 0, NULL)) {
+ DHD_ERROR(("%s Legacy PNO mode cannot be enabled "
+ "in assoc mode , ignore it\n", __FUNCTION__));
+ err = BCME_BADOPTION;
+ goto exit;
+ }
+ }
+ /* Enable/Disable PNO */
+ err = dhd_iovar(dhd, 0, "pfn", (char *)&enable, sizeof(enable), 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to execute pfn_set\n", __FUNCTION__));
+ goto exit;
+ }
+ _pno_state->pno_status = (enable)?
+ DHD_PNO_ENABLED : DHD_PNO_DISABLED;
+ if (!enable)
+ _pno_state->pno_mode = DHD_PNO_NONE_MODE;
+
+ DHD_PNO(("%s set pno as %s\n",
+ __FUNCTION__, enable ? "Enable" : "Disable"));
+exit:
+ return err;
+}
+
+static int
+_dhd_pno_set(dhd_pub_t *dhd, const dhd_pno_params_t *pno_params, dhd_pno_mode_t mode)
+{
+ int err = BCME_OK;
+ wl_pfn_param_t pfn_param;
+ dhd_pno_params_t *_params;
+ dhd_pno_status_info_t *_pno_state;
+ bool combined_scan = FALSE;
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+
+ memset(&pfn_param, 0, sizeof(pfn_param));
+
+ /* set pfn parameters */
+ pfn_param.version = htod32(PFN_VERSION);
+ pfn_param.flags = ((PFN_LIST_ORDER << SORT_CRITERIA_BIT) |
+ (ENABLE << IMMEDIATE_SCAN_BIT) | (ENABLE << REPORT_SEPERATELY_BIT));
+ if (mode == DHD_PNO_LEGACY_MODE) {
+ /* check and set extra pno params */
+ if ((pno_params->params_legacy.pno_repeat != 0) ||
+ (pno_params->params_legacy.pno_freq_expo_max != 0)) {
+ pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT);
+ pfn_param.repeat = (uchar) (pno_params->params_legacy.pno_repeat);
+ pfn_param.exp = (uchar) (pno_params->params_legacy.pno_freq_expo_max);
+ }
+ /* set up pno scan fr */
+ if (pno_params->params_legacy.scan_fr != 0)
+ pfn_param.scan_freq = htod32(pno_params->params_legacy.scan_fr);
+ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
+ DHD_PNO(("will enable combined scan with BATCHIG SCAN MODE\n"));
+ mode |= DHD_PNO_BATCH_MODE;
+ combined_scan = TRUE;
+ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
+ DHD_PNO(("will enable combined scan with HOTLIST SCAN MODE\n"));
+ mode |= DHD_PNO_HOTLIST_MODE;
+ combined_scan = TRUE;
+ }
+ }
+ if (mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) {
+ /* Scan frequency of 30 sec */
+ pfn_param.scan_freq = htod32(30);
+ /* slow adapt scan is off by default */
+ pfn_param.slow_freq = htod32(0);
+ /* RSSI margin of 30 dBm */
+ pfn_param.rssi_margin = htod16(30);
+ /* Network timeout 60 sec */
+ pfn_param.lost_network_timeout = htod32(60);
+ /* best n = 2 by default */
+ pfn_param.bestn = DEFAULT_BESTN;
+ /* mscan m=0 by default, so not record best networks by default */
+ pfn_param.mscan = DEFAULT_MSCAN;
+ /* default repeat = 10 */
+ pfn_param.repeat = DEFAULT_REPEAT;
+ /* by default, maximum scan interval = 2^2
+ * scan_freq when adaptive scan is turned on
+ */
+ pfn_param.exp = DEFAULT_EXP;
+ if (mode == DHD_PNO_BATCH_MODE) {
+ /* In case of BATCH SCAN */
+ if (pno_params->params_batch.bestn)
+ pfn_param.bestn = pno_params->params_batch.bestn;
+ if (pno_params->params_batch.scan_fr)
+ pfn_param.scan_freq = htod32(pno_params->params_batch.scan_fr);
+ if (pno_params->params_batch.mscan)
+ pfn_param.mscan = pno_params->params_batch.mscan;
+ /* enable broadcast scan */
+ pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
+ } else if (mode == DHD_PNO_HOTLIST_MODE) {
+ /* In case of HOTLIST SCAN */
+ if (pno_params->params_hotlist.scan_fr)
+ pfn_param.scan_freq = htod32(pno_params->params_hotlist.scan_fr);
+ pfn_param.bestn = 0;
+ pfn_param.repeat = 0;
+ /* enable broadcast scan */
+ pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
+ }
+ if (combined_scan) {
+ /* Disable Adaptive Scan */
+ pfn_param.flags &= ~(htod16(ENABLE << ENABLE_ADAPTSCAN_BIT));
+ pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
+ pfn_param.repeat = 0;
+ pfn_param.exp = 0;
+ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
+ /* In case of Legacy PNO + BATCH SCAN */
+ _params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]);
+ if (_params->params_batch.bestn)
+ pfn_param.bestn = _params->params_batch.bestn;
+ if (_params->params_batch.scan_fr)
+ pfn_param.scan_freq = htod32(_params->params_batch.scan_fr);
+ if (_params->params_batch.mscan)
+ pfn_param.mscan = _params->params_batch.mscan;
+ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
+ /* In case of Legacy PNO + HOTLIST SCAN */
+ _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
+ if (_params->params_hotlist.scan_fr)
+ pfn_param.scan_freq = htod32(_params->params_hotlist.scan_fr);
+ pfn_param.bestn = 0;
+ pfn_param.repeat = 0;
+ }
+ }
+ }
+ if (pfn_param.scan_freq < htod32(PNO_SCAN_MIN_FW_SEC) ||
+ pfn_param.scan_freq > htod32(PNO_SCAN_MAX_FW_SEC)) {
+ DHD_ERROR(("%s pno freq(%d sec) is not valid \n",
+ __FUNCTION__, PNO_SCAN_MIN_FW_SEC));
+ err = BCME_BADARG;
+ goto exit;
+ }
+ if (mode == DHD_PNO_BATCH_MODE) {
+ int _tmp = pfn_param.bestn;
+ /* set bestn to calculate the max mscan which firmware supports */
+ err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to set pfnmem\n", __FUNCTION__));
+ goto exit;
+ }
+ /* get max mscan which the firmware supports */
+ err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 0);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to get pfnmem\n", __FUNCTION__));
+ goto exit;
+ }
+ DHD_PNO((" returned mscan : %d, set bestn : %d\n", _tmp, pfn_param.bestn));
+ pfn_param.mscan = MIN(pfn_param.mscan, _tmp);
+ }
+ err = dhd_iovar(dhd, 0, "pfn_set", (char *)&pfn_param, sizeof(pfn_param), 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to execute pfn_set\n", __FUNCTION__));
+ goto exit;
+ }
+ /* need to return mscan if this is for batch scan instead of err */
+ err = (mode == DHD_PNO_BATCH_MODE)? pfn_param.mscan : err;
+exit:
+ return err;
+}
+static int
+_dhd_pno_add_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssids_list, int nssid)
+{
+ int err = BCME_OK;
+ int i = 0;
+ wl_pfn_t pfn_element;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ if (nssid) {
+ NULL_CHECK(ssids_list, "ssid list is NULL", err);
+ }
+ memset(&pfn_element, 0, sizeof(pfn_element));
+ {
+ int j;
+ for (j = 0; j < nssid; j++) {
+ DHD_PNO(("%d: scan for %s size = %d\n", j,
+ ssids_list[j].SSID, ssids_list[j].SSID_len));
+ }
+ }
+ /* Check for broadcast ssid */
+ for (i = 0; i < nssid; i++) {
+ if (!ssids_list[i].SSID_len) {
+ DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", i));
+ err = BCME_ERROR;
+ goto exit;
+ }
+ }
+ /* set all pfn ssid */
+ for (i = 0; i < nssid; i++) {
+ pfn_element.infra = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
+ pfn_element.auth = (DOT11_OPEN_SYSTEM);
+ pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
+ pfn_element.wsec = htod32(0);
+ pfn_element.infra = htod32(1);
+ pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT);
+ memcpy((char *)pfn_element.ssid.SSID, ssids_list[i].SSID,
+ ssids_list[i].SSID_len);
+ pfn_element.ssid.SSID_len = ssids_list[i].SSID_len;
+ err = dhd_iovar(dhd, 0, "pfn_add", (char *)&pfn_element,
+ sizeof(pfn_element), 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to execute pfn_add\n", __FUNCTION__));
+ goto exit;
+ }
+ }
+exit:
+ return err;
+}
+/* qsort compare function */
+static int
+_dhd_pno_cmpfunc(const void *a, const void *b)
+{
+ return (*(uint16*)a - *(uint16*)b);
+}
+static int
+_dhd_pno_chan_merge(uint16 *d_chan_list, int *nchan,
+ uint16 *chan_list1, int nchan1, uint16 *chan_list2, int nchan2)
+{
+ int err = BCME_OK;
+ int i = 0, j = 0, k = 0;
+ uint16 tmp;
+ NULL_CHECK(d_chan_list, "d_chan_list is NULL", err);
+ NULL_CHECK(nchan, "nchan is NULL", err);
+ NULL_CHECK(chan_list1, "chan_list1 is NULL", err);
+ NULL_CHECK(chan_list2, "chan_list2 is NULL", err);
+ /* chan_list1 and chan_list2 should be sorted at first */
+ while (i < nchan1 && j < nchan2) {
+ tmp = chan_list1[i] < chan_list2[j]?
+ chan_list1[i++] : chan_list2[j++];
+ for (; i < nchan1 && chan_list1[i] == tmp; i++);
+ for (; j < nchan2 && chan_list2[j] == tmp; j++);
+ d_chan_list[k++] = tmp;
+ }
+
+ while (i < nchan1) {
+ tmp = chan_list1[i++];
+ for (; i < nchan1 && chan_list1[i] == tmp; i++);
+ d_chan_list[k++] = tmp;
+ }
+
+ while (j < nchan2) {
+ tmp = chan_list2[j++];
+ for (; j < nchan2 && chan_list2[j] == tmp; j++);
+ d_chan_list[k++] = tmp;
+
+ }
+ *nchan = k;
+ return err;
+}
+static int
+_dhd_pno_get_channels(dhd_pub_t *dhd, uint16 *d_chan_list,
+ int *nchan, uint8 band, bool skip_dfs)
+{
+ int err = BCME_OK;
+ int i, j;
+ uint32 chan_buf[WL_NUMCHANNELS + 1];
+ wl_uint32_list_t *list;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ if (*nchan) {
+ NULL_CHECK(d_chan_list, "d_chan_list is NULL", err);
+ }
+ list = (wl_uint32_list_t *) (void *)chan_buf;
+ list->count = htod32(WL_NUMCHANNELS);
+ err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, chan_buf, sizeof(chan_buf), FALSE, 0);
+ if (err < 0) {
+ DHD_ERROR(("failed to get channel list (err: %d)\n", err));
+ goto exit;
+ }
+ for (i = 0, j = 0; i < dtoh32(list->count) && i < *nchan; i++) {
+ if (band == WLC_BAND_2G) {
+ if (dtoh32(list->element[i]) > CHANNEL_2G_MAX)
+ continue;
+ } else if (band == WLC_BAND_5G) {
+ if (dtoh32(list->element[i]) <= CHANNEL_2G_MAX)
+ continue;
+ if (skip_dfs && is_dfs(dtoh32(list->element[i])))
+ continue;
+
+ } else { /* All channels */
+ if (skip_dfs && is_dfs(dtoh32(list->element[i])))
+ continue;
+ }
+ d_chan_list[j++] = dtoh32(list->element[i]);
+ }
+ *nchan = j;
+exit:
+ return err;
+}
+static int
+_dhd_pno_convert_format(dhd_pub_t *dhd, struct dhd_pno_batch_params *params_batch,
+ char *buf, int nbufsize)
+{
+ int err = BCME_OK;
+ int bytes_written = 0, nreadsize = 0;
+ int t_delta = 0;
+ int nleftsize = nbufsize;
+ uint8 cnt = 0;
+ char *bp = buf;
+ char eabuf[ETHER_ADDR_STR_LEN];
+#ifdef PNO_DEBUG
+ char *_base_bp;
+ char msg[150];
+#endif
+ dhd_pno_bestnet_entry_t *iter, *next;
+ dhd_pno_scan_results_t *siter, *snext;
+ dhd_pno_best_header_t *phead, *pprev;
+ NULL_CHECK(params_batch, "params_batch is NULL", err);
+ if (nbufsize > 0)
+ NULL_CHECK(buf, "buf is NULL", err);
+ /* initialize the buffer */
+ memset(buf, 0, nbufsize);
+ DHD_PNO(("%s enter \n", __FUNCTION__));
+ /* # of scans */
+ if (!params_batch->get_batch.batch_started) {
+ bp += nreadsize = sprintf(bp, "scancount=%d\n",
+ params_batch->get_batch.expired_tot_scan_cnt);
+ nleftsize -= nreadsize;
+ params_batch->get_batch.batch_started = TRUE;
+ }
+ DHD_PNO(("%s scancount %d\n", __FUNCTION__, params_batch->get_batch.expired_tot_scan_cnt));
+ /* preestimate scan count until which scan result this report is going to end */
+ list_for_each_entry_safe(siter, snext,
+ &params_batch->get_batch.expired_scan_results_list, list) {
+ phead = siter->bestnetheader;
+ while (phead != NULL) {
+ /* if left_size is less than bestheader total size , stop this */
+ if (nleftsize <=
+ (phead->tot_size + phead->tot_cnt * ENTRY_OVERHEAD))
+ goto exit;
+ /* increase scan count */
+ cnt++;
+ /* # best of each scan */
+ DHD_PNO(("\n<loop : %d, apcount %d>\n", cnt - 1, phead->tot_cnt));
+ /* attribute of the scan */
+ if (phead->reason & PNO_STATUS_ABORT_MASK) {
+ bp += nreadsize = sprintf(bp, "trunc\n");
+ nleftsize -= nreadsize;
+ }
+ list_for_each_entry_safe(iter, next,
+ &phead->entry_list, list) {
+ t_delta = jiffies_to_msecs(jiffies - iter->recorded_time);
+#ifdef PNO_DEBUG
+ _base_bp = bp;
+ memset(msg, 0, sizeof(msg));
+#endif
+ /* BSSID info */
+ bp += nreadsize = sprintf(bp, "bssid=%s\n",
+ bcm_ether_ntoa((const struct ether_addr *)&iter->BSSID, eabuf));
+ nleftsize -= nreadsize;
+ /* SSID */
+ bp += nreadsize = sprintf(bp, "ssid=%s\n", iter->SSID);
+ nleftsize -= nreadsize;
+ /* channel */
+ bp += nreadsize = sprintf(bp, "freq=%d\n",
+ wf_channel2mhz(iter->channel,
+ iter->channel <= CH_MAX_2G_CHANNEL?
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
+ nleftsize -= nreadsize;
+ /* RSSI */
+ bp += nreadsize = sprintf(bp, "level=%d\n", iter->RSSI);
+ nleftsize -= nreadsize;
+ /* add the time consumed in Driver to the timestamp of firmware */
+ iter->timestamp += t_delta;
+ bp += nreadsize = sprintf(bp, "age=%d\n", iter->timestamp);
+ nleftsize -= nreadsize;
+ /* RTT0 */
+ bp += nreadsize = sprintf(bp, "dist=%d\n",
+ (iter->rtt0 == 0)? -1 : iter->rtt0);
+ nleftsize -= nreadsize;
+ /* RTT1 */
+ bp += nreadsize = sprintf(bp, "distSd=%d\n",
+ (iter->rtt0 == 0)? -1 : iter->rtt1);
+ nleftsize -= nreadsize;
+ bp += nreadsize = sprintf(bp, "%s", AP_END_MARKER);
+ nleftsize -= nreadsize;
+ list_del(&iter->list);
+ MFREE(dhd->osh, iter, BESTNET_ENTRY_SIZE);
+#ifdef PNO_DEBUG
+ memcpy(msg, _base_bp, bp - _base_bp);
+ DHD_PNO(("Entry : \n%s", msg));
+#endif
+ }
+ bp += nreadsize = sprintf(bp, "%s", SCAN_END_MARKER);
+ DHD_PNO(("%s", SCAN_END_MARKER));
+ nleftsize -= nreadsize;
+ pprev = phead;
+ /* reset the header */
+ siter->bestnetheader = phead = phead->next;
+ MFREE(dhd->osh, pprev, BEST_HEADER_SIZE);
+
+ siter->cnt_header--;
+ }
+ if (phead == NULL) {
+ /* we store all entry in this scan , so it is ok to delete */
+ list_del(&siter->list);
+ MFREE(dhd->osh, siter, SCAN_RESULTS_SIZE);
+ }
+ }
+exit:
+ if (cnt < params_batch->get_batch.expired_tot_scan_cnt) {
+ DHD_ERROR(("Buffer size is small to save all batch entry,"
+ " cnt : %d (remained_scan_cnt): %d\n",
+ cnt, params_batch->get_batch.expired_tot_scan_cnt - cnt));
+ }
+ params_batch->get_batch.expired_tot_scan_cnt -= cnt;
+ /* set FALSE only if the link list is empty after returning the data */
+ if (list_empty(&params_batch->get_batch.expired_scan_results_list)) {
+ params_batch->get_batch.batch_started = FALSE;
+ bp += sprintf(bp, "%s", RESULTS_END_MARKER);
+ DHD_PNO(("%s", RESULTS_END_MARKER));
+ DHD_PNO(("%s : Getting the batching data is complete\n", __FUNCTION__));
+ }
+ /* return used memory in buffer */
+ bytes_written = (int32)(bp - buf);
+ return bytes_written;
+}
+static int
+_dhd_pno_clear_all_batch_results(dhd_pub_t *dhd, struct list_head *head, bool only_last)
+{
+ int err = BCME_OK;
+ int removed_scan_cnt = 0;
+ dhd_pno_scan_results_t *siter, *snext;
+ dhd_pno_best_header_t *phead, *pprev;
+ dhd_pno_bestnet_entry_t *iter, *next;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(head, "head is NULL", err);
+ NULL_CHECK(head->next, "head->next is NULL", err);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ list_for_each_entry_safe(siter, snext,
+ head, list) {
+ if (only_last) {
+ /* in case that we need to delete only last one */
+ if (!list_is_last(&siter->list, head)) {
+ /* skip if the one is not last */
+ continue;
+ }
+ }
+ /* delete all data belong if the one is last */
+ phead = siter->bestnetheader;
+ while (phead != NULL) {
+ removed_scan_cnt++;
+ list_for_each_entry_safe(iter, next,
+ &phead->entry_list, list) {
+ list_del(&iter->list);
+ MFREE(dhd->osh, iter, BESTNET_ENTRY_SIZE);
+ }
+ pprev = phead;
+ phead = phead->next;
+ MFREE(dhd->osh, pprev, BEST_HEADER_SIZE);
+ }
+ if (phead == NULL) {
+ /* it is ok to delete top node */
+ list_del(&siter->list);
+ MFREE(dhd->osh, siter, SCAN_RESULTS_SIZE);
+ }
+ }
+ return removed_scan_cnt;
+}
+
+static int
+_dhd_pno_cfg(dhd_pub_t *dhd, uint16 *channel_list, int nchan)
+{
+ int err = BCME_OK;
+ int i = 0;
+ wl_pfn_cfg_t pfncfg_param;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ if (nchan) {
+ NULL_CHECK(channel_list, "nchan is NULL", err);
+ }
+ DHD_PNO(("%s enter : nchan : %d\n", __FUNCTION__, nchan));
+ memset(&pfncfg_param, 0, sizeof(wl_pfn_cfg_t));
+ /* Setup default values */
+ pfncfg_param.reporttype = htod32(WL_PFN_REPORT_ALLNET);
+ pfncfg_param.channel_num = htod32(0);
+
+ for (i = 0; i < nchan && nchan < WL_NUMCHANNELS; i++)
+ pfncfg_param.channel_list[i] = channel_list[i];
+
+ pfncfg_param.channel_num = htod32(nchan);
+ err = dhd_iovar(dhd, 0, "pfn_cfg", (char *)&pfncfg_param, sizeof(pfncfg_param), 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to execute pfn_cfg\n", __FUNCTION__));
+ goto exit;
+ }
+exit:
+ return err;
+}
+static int
+_dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mode_t mode)
+{
+ int err = BCME_OK;
+ dhd_pno_status_info_t *_pno_state;
+ NULL_CHECK(dhd, "dhd is NULL\n", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL\n", err);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ mutex_lock(&_pno_state->pno_mutex);
+ switch (mode) {
+ case DHD_PNO_LEGACY_MODE: {
+ struct dhd_pno_ssid *iter, *next;
+ if (params->params_legacy.nssid > 0) {
+ list_for_each_entry_safe(iter, next,
+ &params->params_legacy.ssid_list, list) {
+ list_del(&iter->list);
+ kfree(iter);
+ }
+ }
+ params->params_legacy.nssid = 0;
+ params->params_legacy.scan_fr = 0;
+ params->params_legacy.pno_freq_expo_max = 0;
+ params->params_legacy.pno_repeat = 0;
+ params->params_legacy.nchan = 0;
+ memset(params->params_legacy.chan_list, 0,
+ sizeof(params->params_legacy.chan_list));
+ break;
+ }
+ case DHD_PNO_BATCH_MODE: {
+ params->params_batch.scan_fr = 0;
+ params->params_batch.mscan = 0;
+ params->params_batch.nchan = 0;
+ params->params_batch.rtt = 0;
+ params->params_batch.bestn = 0;
+ params->params_batch.nchan = 0;
+ params->params_batch.band = WLC_BAND_AUTO;
+ memset(params->params_batch.chan_list, 0,
+ sizeof(params->params_batch.chan_list));
+ params->params_batch.get_batch.batch_started = FALSE;
+ params->params_batch.get_batch.buf = NULL;
+ params->params_batch.get_batch.bufsize = 0;
+ params->params_batch.get_batch.reason = 0;
+ _dhd_pno_clear_all_batch_results(dhd,
+ &params->params_batch.get_batch.scan_results_list, FALSE);
+ _dhd_pno_clear_all_batch_results(dhd,
+ &params->params_batch.get_batch.expired_scan_results_list, FALSE);
+ params->params_batch.get_batch.tot_scan_cnt = 0;
+ params->params_batch.get_batch.expired_tot_scan_cnt = 0;
+ params->params_batch.get_batch.top_node_cnt = 0;
+ INIT_LIST_HEAD(&params->params_batch.get_batch.scan_results_list);
+ INIT_LIST_HEAD(&params->params_batch.get_batch.expired_scan_results_list);
+ break;
+ }
+ case DHD_PNO_HOTLIST_MODE: {
+ struct dhd_pno_bssid *iter, *next;
+ if (params->params_hotlist.nbssid > 0) {
+ list_for_each_entry_safe(iter, next,
+ &params->params_hotlist.bssid_list, list) {
+ list_del(&iter->list);
+ kfree(iter);
+ }
+ }
+ params->params_hotlist.scan_fr = 0;
+ params->params_hotlist.nbssid = 0;
+ params->params_hotlist.nchan = 0;
+ params->params_batch.band = WLC_BAND_AUTO;
+ memset(params->params_hotlist.chan_list, 0,
+ sizeof(params->params_hotlist.chan_list));
+ break;
+ }
+ default:
+ DHD_ERROR(("%s : unknown mode : %d\n", __FUNCTION__, mode));
+ break;
+ }
+ mutex_unlock(&_pno_state->pno_mutex);
+ return err;
+}
+static int
+_dhd_pno_add_bssid(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, int nbssid)
+{
+ int err = BCME_OK;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ if (nbssid) {
+ NULL_CHECK(p_pfn_bssid, "bssid list is NULL", err);
+ }
+ err = dhd_iovar(dhd, 0, "pfn_add_bssid", (char *)&p_pfn_bssid,
+ sizeof(wl_pfn_bssid_t) * nbssid, 1);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to execute pfn_cfg\n", __FUNCTION__));
+ goto exit;
+ }
+exit:
+ return err;
+}
+int
+dhd_pno_stop_for_ssid(dhd_pub_t *dhd)
+{
+ int err = BCME_OK;
+ uint32 mode = 0;
+ dhd_pno_status_info_t *_pno_state;
+ dhd_pno_params_t *_params;
+ wl_pfn_bssid_t *p_pfn_bssid = NULL;
+ NULL_CHECK(dhd, "dev is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ if (!(_pno_state->pno_mode & DHD_PNO_LEGACY_MODE)) {
+ DHD_ERROR(("%s : LEGACY PNO MODE is not enabled\n", __FUNCTION__));
+ goto exit;
+ }
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ /* restart Batch mode if the batch mode is on */
+ if (_pno_state->pno_mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) {
+ /* retrieve the batching data from firmware into host */
+ dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
+ /* save current pno_mode before calling dhd_pno_clean */
+ mode = _pno_state->pno_mode;
+ dhd_pno_clean(dhd);
+ /* restore previous pno_mode */
+ _pno_state->pno_mode = mode;
+ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
+ _params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]);
+ /* restart BATCH SCAN */
+ err = dhd_pno_set_for_batch(dhd, &_params->params_batch);
+ if (err < 0) {
+ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
+ DHD_ERROR(("%s : failed to restart batch scan(err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
+ /* restart HOTLIST SCAN */
+ struct dhd_pno_bssid *iter, *next;
+ _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
+ p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) *
+ _params->params_hotlist.nbssid, GFP_KERNEL);
+ if (p_pfn_bssid == NULL) {
+ DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array"
+ " (count: %d)",
+ __FUNCTION__, _params->params_hotlist.nbssid));
+ err = BCME_ERROR;
+ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
+ goto exit;
+ }
+ /* convert dhd_pno_bssid to wl_pfn_bssid */
+ list_for_each_entry_safe(iter, next,
+ &_params->params_hotlist.bssid_list, list) {
+ memcpy(&p_pfn_bssid->macaddr,
+ &iter->macaddr, ETHER_ADDR_LEN);
+ p_pfn_bssid->flags = iter->flags;
+ p_pfn_bssid++;
+ }
+ err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist);
+ if (err < 0) {
+ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
+ DHD_ERROR(("%s : failed to restart hotlist scan(err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+ } else {
+ err = dhd_pno_clean(dhd);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+exit:
+ if (p_pfn_bssid)
+ kfree(p_pfn_bssid);
+ return err;
+}
+
+int
+dhd_pno_enable(dhd_pub_t *dhd, int enable)
+{
+ int err = BCME_OK;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ return (_dhd_pno_enable(dhd, enable));
+}
+
+int
+dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
+ uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan)
+{
+ struct dhd_pno_ssid *_pno_ssid;
+ dhd_pno_params_t *_params;
+ dhd_pno_params_t *_params2;
+ dhd_pno_status_info_t *_pno_state;
+ uint16 _chan_list[WL_NUMCHANNELS];
+ int32 tot_nchan = 0;
+ int err = BCME_OK;
+ int i;
+ int mode = 0;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+
+ if (!dhd_support_sta_mode(dhd)) {
+ err = BCME_BADOPTION;
+ goto exit;
+ }
+ DHD_PNO(("%s enter : scan_fr :%d, pno_repeat :%d,"
+ "pno_freq_expo_max: %d, nchan :%d\n", __FUNCTION__,
+ scan_fr, pno_repeat, pno_freq_expo_max, nchan));
+
+ _params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
+ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
+ DHD_ERROR(("%s : Legacy PNO mode was already started, "
+ "will disable previous one to start new one\n", __FUNCTION__));
+ err = dhd_pno_stop_for_ssid(dhd);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to stop legacy PNO (err %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+ _pno_state->pno_mode |= DHD_PNO_LEGACY_MODE;
+ err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ memset(_chan_list, 0, sizeof(_chan_list));
+ tot_nchan = nchan;
+ if (tot_nchan > 0 && channel_list) {
+ for (i = 0; i < nchan; i++)
+ _params->params_legacy.chan_list[i] = _chan_list[i] = channel_list[i];
+ }
+ if (_pno_state->pno_mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) {
+ DHD_PNO(("BATCH SCAN is on progress in firmware\n"));
+ /* retrieve the batching data from firmware into host */
+ dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
+ /* store current pno_mode before disabling pno */
+ mode = _pno_state->pno_mode;
+ err = _dhd_pno_enable(dhd, PNO_OFF);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
+ goto exit;
+ }
+ /* restore the previous mode */
+ _pno_state->pno_mode = mode;
+ /* use superset of channel list between two mode */
+ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
+ _params2 = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]);
+ if (_params2->params_batch.nchan > 0 && nchan > 0) {
+ err = _dhd_pno_chan_merge(_chan_list, &tot_nchan,
+ &_params2->params_batch.chan_list[0],
+ _params2->params_batch.nchan,
+ &channel_list[0], nchan);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to merge channel list"
+ " between legacy and batch\n",
+ __FUNCTION__));
+ goto exit;
+ }
+ } else {
+ DHD_PNO(("superset channel will use"
+ " all channels in firmware\n"));
+ }
+ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
+ _params2 = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
+ if (_params2->params_hotlist.nchan > 0 && nchan > 0) {
+ err = _dhd_pno_chan_merge(_chan_list, &tot_nchan,
+ &_params2->params_hotlist.chan_list[0],
+ _params2->params_hotlist.nchan,
+ &channel_list[0], nchan);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to merge channel list"
+ " between legacy and hotlist\n",
+ __FUNCTION__));
+ goto exit;
+ }
+ }
+ }
+ }
+ _params->params_legacy.scan_fr = scan_fr;
+ _params->params_legacy.pno_repeat = pno_repeat;
+ _params->params_legacy.pno_freq_expo_max = pno_freq_expo_max;
+ _params->params_legacy.nchan = nchan;
+ _params->params_legacy.nssid = nssid;
+ INIT_LIST_HEAD(&_params->params_legacy.ssid_list);
+ if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_LEGACY_MODE)) < 0) {
+ DHD_ERROR(("failed to set call pno_set (err %d) in firmware\n", err));
+ goto exit;
+ }
+ if ((err = _dhd_pno_add_ssid(dhd, ssid_list, nssid)) < 0) {
+ DHD_ERROR(("failed to add ssid list(err %d), %d in firmware\n", err, nssid));
+ goto exit;
+ }
+ for (i = 0; i < nssid; i++) {
+ _pno_ssid = kzalloc(sizeof(struct dhd_pno_ssid), GFP_KERNEL);
+ if (_pno_ssid == NULL) {
+ DHD_ERROR(("%s : failed to allocate struct dhd_pno_ssid\n",
+ __FUNCTION__));
+ goto exit;
+ }
+ _pno_ssid->SSID_len = ssid_list[i].SSID_len;
+ memcpy(_pno_ssid->SSID, ssid_list[i].SSID, _pno_ssid->SSID_len);
+ list_add_tail(&_pno_ssid->list, &_params->params_legacy.ssid_list);
+
+ }
+ if (tot_nchan > 0) {
+ if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) {
+ DHD_ERROR(("%s : failed to set call pno_cfg (err %d) in firmware\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+ if (_pno_state->pno_status == DHD_PNO_DISABLED) {
+ if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0)
+ DHD_ERROR(("%s : failed to enable PNO\n", __FUNCTION__));
+ }
+exit:
+ /* clear mode in case of error */
+ if (err < 0)
+ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ return err;
+}
+int
+dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params)
+{
+ int err = BCME_OK;
+ uint16 _chan_list[WL_NUMCHANNELS];
+ int rem_nchan = 0, tot_nchan = 0;
+ int mode = 0, mscan = 0;
+ int i = 0;
+ dhd_pno_params_t *_params;
+ dhd_pno_params_t *_params2;
+ dhd_pno_status_info_t *_pno_state;
+ wlc_ssid_t *p_ssid_list = NULL;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ NULL_CHECK(batch_params, "batch_params is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ if (!dhd_support_sta_mode(dhd)) {
+ err = BCME_BADOPTION;
+ goto exit;
+ }
+ if (!WLS_SUPPORTED(_pno_state)) {
+ DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
+ err = BCME_UNSUPPORTED;
+ goto exit;
+ }
+ _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
+ if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
+ _pno_state->pno_mode |= DHD_PNO_BATCH_MODE;
+ err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to call _dhd_pno_reinitialize_prof\n",
+ __FUNCTION__));
+ goto exit;
+ }
+ } else {
+ /* batch mode is already started */
+ return -EBUSY;
+ }
+ _params->params_batch.scan_fr = batch_params->scan_fr;
+ _params->params_batch.bestn = batch_params->bestn;
+ _params->params_batch.mscan = (batch_params->mscan)?
+ batch_params->mscan : DEFAULT_BATCH_MSCAN;
+ _params->params_batch.nchan = batch_params->nchan;
+ memcpy(_params->params_batch.chan_list, batch_params->chan_list,
+ sizeof(_params->params_batch.chan_list));
+
+ memset(_chan_list, 0, sizeof(_chan_list));
+
+ rem_nchan = ARRAYSIZE(batch_params->chan_list) - batch_params->nchan;
+ if (batch_params->band == WLC_BAND_2G || batch_params->band == WLC_BAND_5G) {
+ /* get a valid channel list based on band B or A */
+ err = _dhd_pno_get_channels(dhd,
+ &_params->params_batch.chan_list[batch_params->nchan],
+ &rem_nchan, batch_params->band, FALSE);
+ if (err < 0) {
+ DHD_ERROR(("%s: failed to get valid channel list(band : %d)\n",
+ __FUNCTION__, batch_params->band));
+ goto exit;
+ }
+ /* now we need to update nchan because rem_chan has valid channel count */
+ _params->params_batch.nchan += rem_nchan;
+ /* need to sort channel list */
+ sort(_params->params_batch.chan_list, _params->params_batch.nchan,
+ sizeof(_params->params_batch.chan_list[0]), _dhd_pno_cmpfunc, NULL);
+ }
+#ifdef PNO_DEBUG
+{
+ DHD_PNO(("Channel list : "));
+ for (i = 0; i < _params->params_batch.nchan; i++) {
+ DHD_PNO(("%d ", _params->params_batch.chan_list[i]));
+ }
+ DHD_PNO(("\n"));
+}
+#endif
+ if (_params->params_batch.nchan) {
+ /* copy the channel list into local array */
+ memcpy(_chan_list, _params->params_batch.chan_list, sizeof(_chan_list));
+ tot_nchan = _params->params_batch.nchan;
+ }
+ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
+ struct dhd_pno_ssid *iter, *next;
+ DHD_PNO(("PNO SSID is on progress in firmware\n"));
+ /* store current pno_mode before disabling pno */
+ mode = _pno_state->pno_mode;
+ err = _dhd_pno_enable(dhd, PNO_OFF);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
+ goto exit;
+ }
+ /* restore the previous mode */
+ _pno_state->pno_mode = mode;
+ /* Use the superset for channelist between two mode */
+ _params2 = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
+ if (_params2->params_legacy.nchan > 0 && _params->params_batch.nchan > 0) {
+ err = _dhd_pno_chan_merge(_chan_list, &tot_nchan,
+ &_params2->params_legacy.chan_list[0],
+ _params2->params_legacy.nchan,
+ &_params->params_batch.chan_list[0], _params->params_batch.nchan);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to merge channel list"
+ " between legacy and batch\n",
+ __FUNCTION__));
+ goto exit;
+ }
+ } else {
+ DHD_PNO(("superset channel will use all channels in firmware\n"));
+ }
+ p_ssid_list = kzalloc(sizeof(wlc_ssid_t) *
+ _params2->params_legacy.nssid, GFP_KERNEL);
+ if (p_ssid_list == NULL) {
+ DHD_ERROR(("%s : failed to allocate wlc_ssid_t array (count: %d)",
+ __FUNCTION__, _params2->params_legacy.nssid));
+ err = BCME_ERROR;
+ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ goto exit;
+ }
+ i = 0;
+ /* convert dhd_pno_ssid to dhd_pno_ssid */
+ list_for_each_entry_safe(iter, next, &_params2->params_legacy.ssid_list, list) {
+ p_ssid_list[i].SSID_len = iter->SSID_len;
+ memcpy(p_ssid_list->SSID, iter->SSID, p_ssid_list[i].SSID_len);
+ i++;
+ }
+ if ((err = _dhd_pno_add_ssid(dhd, p_ssid_list,
+ _params2->params_legacy.nssid)) < 0) {
+ DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
+ goto exit;
+ }
+ }
+ if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_BATCH_MODE)) < 0) {
+ DHD_ERROR(("%s : failed to set call pno_set (err %d) in firmware\n",
+ __FUNCTION__, err));
+ goto exit;
+ } else {
+ /* we need to return mscan */
+ mscan = err;
+ }
+ if (tot_nchan > 0) {
+ if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) {
+ DHD_ERROR(("%s : failed to set call pno_cfg (err %d) in firmware\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+ if (_pno_state->pno_status == DHD_PNO_DISABLED) {
+ if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0)
+ DHD_ERROR(("%s : failed to enable PNO\n", __FUNCTION__));
+ }
+exit:
+ /* clear mode in case of error */
+ if (err < 0)
+ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
+ else {
+ /* return #max scan firmware can do */
+ err = mscan;
+ }
+ if (p_ssid_list)
+ kfree(p_ssid_list);
+ return err;
+}
+
+static int
+_dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
+{
+ int err = BCME_OK;
+ int i, j;
+ uint32 timestamp = 0;
+ dhd_pno_params_t *_params = NULL;
+ dhd_pno_status_info_t *_pno_state = NULL;
+ wl_pfn_lscanresults_t *plbestnet = NULL;
+ wl_pfn_lnet_info_t *plnetinfo;
+ dhd_pno_bestnet_entry_t *pbestnet_entry;
+ dhd_pno_best_header_t *pbestnetheader = NULL;
+ dhd_pno_scan_results_t *pscan_results = NULL, *siter, *snext;
+ bool allocate_header = FALSE;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ if (!dhd_support_sta_mode(dhd)) {
+ err = BCME_BADOPTION;
+ goto exit;
+ }
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+
+ if (!WLS_SUPPORTED(_pno_state)) {
+ DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
+ err = BCME_UNSUPPORTED;
+ goto exit;
+ }
+ if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
+ DHD_ERROR(("%s: Batching SCAN mode is not enabled\n", __FUNCTION__));
+ goto exit;
+ }
+ mutex_lock(&_pno_state->pno_mutex);
+ _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
+ if (buf && bufsize) {
+ if (!list_empty(&_params->params_batch.get_batch.expired_scan_results_list)) {
+ /* need to check whether we have cashed data or not */
+ DHD_PNO(("%s: have cashed batching data in Driver\n",
+ __FUNCTION__));
+ /* convert to results format */
+ goto convert_format;
+ } else {
+ /* this is a first try to get batching results */
+ if (!list_empty(&_params->params_batch.get_batch.scan_results_list)) {
+ /* move the scan_results_list to expired_scan_results_lists */
+ list_for_each_entry_safe(siter, snext,
+ &_params->params_batch.get_batch.scan_results_list, list) {
+ list_move_tail(&siter->list,
+ &_params->params_batch.get_batch.expired_scan_results_list);
+ }
+ _params->params_batch.get_batch.top_node_cnt = 0;
+ _params->params_batch.get_batch.expired_tot_scan_cnt =
+ _params->params_batch.get_batch.tot_scan_cnt;
+ _params->params_batch.get_batch.tot_scan_cnt = 0;
+ goto convert_format;
+ }
+ }
+ }
+ /* create dhd_pno_scan_results_t whenever we got event WLC_E_PFN_BEST_BATCHING */
+ pscan_results = (dhd_pno_scan_results_t *)MALLOC(dhd->osh, SCAN_RESULTS_SIZE);
+ if (pscan_results == NULL) {
+ err = BCME_NOMEM;
+ DHD_ERROR(("failed to allocate dhd_pno_scan_results_t\n"));
+ goto exit;
+ }
+ pscan_results->bestnetheader = NULL;
+ pscan_results->cnt_header = 0;
+ /* add the element into list unless total node cnt is less than MAX_NODE_ CNT */
+ if (_params->params_batch.get_batch.top_node_cnt < MAX_NODE_CNT) {
+ list_add(&pscan_results->list, &_params->params_batch.get_batch.scan_results_list);
+ _params->params_batch.get_batch.top_node_cnt++;
+ } else {
+ int _removed_scan_cnt;
+ /* remove oldest one and add new one */
+ DHD_PNO(("%s : Remove oldest node and add new one\n", __FUNCTION__));
+ _removed_scan_cnt = _dhd_pno_clear_all_batch_results(dhd,
+ &_params->params_batch.get_batch.scan_results_list, TRUE);
+ _params->params_batch.get_batch.tot_scan_cnt -= _removed_scan_cnt;
+ list_add(&pscan_results->list, &_params->params_batch.get_batch.scan_results_list);
+
+ }
+ plbestnet = (wl_pfn_lscanresults_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN);
+ NULL_CHECK(plbestnet, "failed to allocate buffer for bestnet", err);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ memset(plbestnet, 0, PNO_BESTNET_LEN);
+ while (plbestnet->status != PFN_COMPLETE) {
+ memset(plbestnet, 0, PNO_BESTNET_LEN);
+ err = dhd_iovar(dhd, 0, "pfnlbest", (char *)plbestnet, PNO_BESTNET_LEN, 0);
+ if (err < 0) {
+ if (err == BCME_EPERM) {
+ DHD_ERROR(("we cannot get the batching data "
+ "during scanning in firmware, try again\n,"));
+ msleep(500);
+ continue;
+ } else {
+ DHD_ERROR(("%s : failed to execute pfnlbest (err :%d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+ DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version,
+ plbestnet->status, plbestnet->count));
+ if (plbestnet->version != PFN_SCANRESULT_VERSION) {
+ err = BCME_VERSION;
+ DHD_ERROR(("bestnet version(%d) is mismatch with Driver version(%d)\n",
+ plbestnet->version, PFN_SCANRESULT_VERSION));
+ goto exit;
+ }
+ plnetinfo = plbestnet->netinfo;
+ for (i = 0; i < plbestnet->count; i++) {
+ pbestnet_entry = (dhd_pno_bestnet_entry_t *)
+ MALLOC(dhd->osh, BESTNET_ENTRY_SIZE);
+ if (pbestnet_entry == NULL) {
+ err = BCME_NOMEM;
+ DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n"));
+ goto exit;
+ }
+ memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE);
+ pbestnet_entry->recorded_time = jiffies; /* record the current time */
+ /* create header for the first entry */
+ allocate_header = (i == 0)? TRUE : FALSE;
+ /* check whether the new generation is started or not */
+ if (timestamp && (TIME_DIFF(timestamp, plnetinfo->timestamp)
+ > TIME_MIN_DIFF))
+ allocate_header = TRUE;
+ timestamp = plnetinfo->timestamp;
+ if (allocate_header) {
+ pbestnetheader = (dhd_pno_best_header_t *)
+ MALLOC(dhd->osh, BEST_HEADER_SIZE);
+ if (pbestnetheader == NULL) {
+ err = BCME_NOMEM;
+ if (pbestnet_entry)
+ MFREE(dhd->osh, pbestnet_entry,
+ BESTNET_ENTRY_SIZE);
+ DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n"));
+ goto exit;
+ }
+ /* increase total cnt of bestnet header */
+ pscan_results->cnt_header++;
+ /* need to record the reason to call dhd_pno_get_for_bach */
+ if (reason)
+ pbestnetheader->reason = (ENABLE << reason);
+ memset(pbestnetheader, 0, BEST_HEADER_SIZE);
+ /* initialize the head of linked list */
+ INIT_LIST_HEAD(&(pbestnetheader->entry_list));
+ /* link the pbestnet heaer into existed list */
+ if (pscan_results->bestnetheader == NULL)
+ /* In case of header */
+ pscan_results->bestnetheader = pbestnetheader;
+ else {
+ dhd_pno_best_header_t *head = pscan_results->bestnetheader;
+ pscan_results->bestnetheader = pbestnetheader;
+ pbestnetheader->next = head;
+ }
+ }
+ /* fills the best network info */
+ pbestnet_entry->channel = plnetinfo->pfnsubnet.channel;
+ pbestnet_entry->RSSI = plnetinfo->RSSI;
+ if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) {
+ /* if RSSI is positive value, we assume that
+ * this scan is aborted by other scan
+ */
+ DHD_PNO(("This scan is aborted\n"));
+ pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT);
+ }
+ pbestnet_entry->rtt0 = plnetinfo->rtt0;
+ pbestnet_entry->rtt1 = plnetinfo->rtt1;
+ pbestnet_entry->timestamp = plnetinfo->timestamp;
+ pbestnet_entry->SSID_len = plnetinfo->pfnsubnet.SSID_len;
+ memcpy(pbestnet_entry->SSID, plnetinfo->pfnsubnet.SSID,
+ pbestnet_entry->SSID_len);
+ memcpy(&pbestnet_entry->BSSID, &plnetinfo->pfnsubnet.BSSID, ETHER_ADDR_LEN);
+ /* add the element into list */
+ list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list);
+ /* increase best entry count */
+ pbestnetheader->tot_cnt++;
+ pbestnetheader->tot_size += BESTNET_ENTRY_SIZE;
+ DHD_PNO(("Header %d\n", pscan_results->cnt_header - 1));
+ DHD_PNO(("\tSSID : "));
+ for (j = 0; j < plnetinfo->pfnsubnet.SSID_len; j++)
+ DHD_PNO(("%c", plnetinfo->pfnsubnet.SSID[j]));
+ DHD_PNO(("\n"));
+ DHD_PNO(("\tBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ plnetinfo->pfnsubnet.BSSID.octet[0],
+ plnetinfo->pfnsubnet.BSSID.octet[1],
+ plnetinfo->pfnsubnet.BSSID.octet[2],
+ plnetinfo->pfnsubnet.BSSID.octet[3],
+ plnetinfo->pfnsubnet.BSSID.octet[4],
+ plnetinfo->pfnsubnet.BSSID.octet[5]));
+ DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
+ plnetinfo->pfnsubnet.channel,
+ plnetinfo->RSSI, plnetinfo->timestamp));
+ DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", plnetinfo->rtt0, plnetinfo->rtt1));
+ plnetinfo++;
+ }
+ }
+ if (pscan_results->cnt_header == 0) {
+ /* In case that we didn't get any data from the firmware
+ * Remove the current scan_result list from get_bach.scan_results_list.
+ */
+ DHD_PNO(("NO BATCH DATA from Firmware, Delete current SCAN RESULT LIST\n"));
+ list_del(&pscan_results->list);
+ MFREE(dhd->osh, pscan_results, SCAN_RESULTS_SIZE);
+ _params->params_batch.get_batch.top_node_cnt--;
+ }
+ /* increase total scan count using current scan count */
+ _params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header;
+
+ if (buf && bufsize) {
+ /* This is a first try to get batching results */
+ if (!list_empty(&_params->params_batch.get_batch.scan_results_list)) {
+ /* move the scan_results_list to expired_scan_results_lists */
+ list_for_each_entry_safe(siter, snext,
+ &_params->params_batch.get_batch.scan_results_list, list) {
+ list_move_tail(&siter->list,
+ &_params->params_batch.get_batch.expired_scan_results_list);
+ }
+ /* reset gloval values after moving to expired list */
+ _params->params_batch.get_batch.top_node_cnt = 0;
+ _params->params_batch.get_batch.expired_tot_scan_cnt =
+ _params->params_batch.get_batch.tot_scan_cnt;
+ _params->params_batch.get_batch.tot_scan_cnt = 0;
+ }
+convert_format:
+ err = _dhd_pno_convert_format(dhd, &_params->params_batch, buf, bufsize);
+ if (err < 0) {
+ DHD_ERROR(("failed to convert the data into upper layer format\n"));
+ goto exit;
+ }
+ }
+exit:
+ if (plbestnet)
+ MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN);
+ if (_params) {
+ _params->params_batch.get_batch.buf = NULL;
+ _params->params_batch.get_batch.bufsize = 0;
+ _params->params_batch.get_batch.bytes_written = err;
+ }
+ mutex_unlock(&_pno_state->pno_mutex);
+ if (waitqueue_active(&_pno_state->get_batch_done.wait))
+ complete(&_pno_state->get_batch_done);
+ return err;
+}
+static void
+_dhd_pno_get_batch_handler(struct work_struct *work)
+{
+ dhd_pno_status_info_t *_pno_state;
+ dhd_pub_t *dhd;
+ struct dhd_pno_batch_params *params_batch;
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ _pno_state = container_of(work, struct dhd_pno_status_info, work);
+ dhd = _pno_state->dhd;
+ if (dhd == NULL) {
+ DHD_ERROR(("%s : dhd is NULL\n", __FUNCTION__));
+ return;
+ }
+ params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
+ _dhd_pno_get_for_batch(dhd, params_batch->get_batch.buf,
+ params_batch->get_batch.bufsize, params_batch->get_batch.reason);
+
+}
+
+int
+dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
+{
+ int err = BCME_OK;
+ char *pbuf = buf;
+ dhd_pno_status_info_t *_pno_state;
+ struct dhd_pno_batch_params *params_batch;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ if (!dhd_support_sta_mode(dhd)) {
+ err = BCME_BADOPTION;
+ goto exit;
+ }
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+
+ if (!WLS_SUPPORTED(_pno_state)) {
+ DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
+ err = BCME_UNSUPPORTED;
+ goto exit;
+ }
+ params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
+ if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
+ DHD_ERROR(("%s: Batching SCAN mode is not enabled\n", __FUNCTION__));
+ memset(pbuf, 0, bufsize);
+ pbuf += sprintf(pbuf, "scancount=%d\n", 0);
+ sprintf(pbuf, "%s", RESULTS_END_MARKER);
+ err = strlen(buf);
+ goto exit;
+ }
+ params_batch->get_batch.buf = buf;
+ params_batch->get_batch.bufsize = bufsize;
+ params_batch->get_batch.reason = reason;
+ params_batch->get_batch.bytes_written = 0;
+ schedule_work(&_pno_state->work);
+ wait_for_completion(&_pno_state->get_batch_done);
+ err = params_batch->get_batch.bytes_written;
+exit:
+ return err;
+}
+
+int
+dhd_pno_stop_for_batch(dhd_pub_t *dhd)
+{
+ int err = BCME_OK;
+ int mode = 0;
+ int i = 0;
+ dhd_pno_status_info_t *_pno_state;
+ dhd_pno_params_t *_params;
+ wl_pfn_bssid_t *p_pfn_bssid = NULL;
+ wlc_ssid_t *p_ssid_list = NULL;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ if (!dhd_support_sta_mode(dhd)) {
+ err = BCME_BADOPTION;
+ goto exit;
+ }
+ if (!WLS_SUPPORTED(_pno_state)) {
+ DHD_ERROR(("%s : wifi location service is not supported\n",
+ __FUNCTION__));
+ err = BCME_UNSUPPORTED;
+ goto exit;
+ }
+ if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
+ DHD_ERROR(("%s : PNO BATCH MODE is not enabled\n", __FUNCTION__));
+ goto exit;
+ }
+ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
+ if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_HOTLIST_MODE)) {
+ mode = _pno_state->pno_mode;
+ dhd_pno_clean(dhd);
+ _pno_state->pno_mode = mode;
+ /* restart Legacy PNO if the Legacy PNO is on */
+ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
+ struct dhd_pno_legacy_params *_params_legacy;
+ struct dhd_pno_ssid *iter, *next;
+ _params_legacy =
+ &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
+ p_ssid_list = kzalloc(sizeof(wlc_ssid_t) *
+ _params_legacy->nssid, GFP_KERNEL);
+ if (p_ssid_list == NULL) {
+ DHD_ERROR(("%s : failed to allocate wlc_ssid_t array (count: %d)",
+ __FUNCTION__, _params_legacy->nssid));
+ err = BCME_ERROR;
+ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ goto exit;
+ }
+ i = 0;
+ /* convert dhd_pno_ssid to dhd_pno_ssid */
+ list_for_each_entry_safe(iter, next, &_params_legacy->ssid_list, list) {
+ p_ssid_list[i].SSID_len = iter->SSID_len;
+ memcpy(p_ssid_list[i].SSID, iter->SSID, p_ssid_list[i].SSID_len);
+ i++;
+ }
+ err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid,
+ _params_legacy->scan_fr, _params_legacy->pno_repeat,
+ _params_legacy->pno_freq_expo_max, _params_legacy->chan_list,
+ _params_legacy->nchan);
+ if (err < 0) {
+ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
+ struct dhd_pno_bssid *iter, *next;
+ _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
+ p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) *
+ _params->params_hotlist.nbssid, GFP_KERNEL);
+ if (p_pfn_bssid == NULL) {
+ DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array"
+ " (count: %d)",
+ __FUNCTION__, _params->params_hotlist.nbssid));
+ err = BCME_ERROR;
+ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
+ goto exit;
+ }
+ i = 0;
+ /* convert dhd_pno_bssid to wl_pfn_bssid */
+ list_for_each_entry_safe(iter, next,
+ &_params->params_hotlist.bssid_list, list) {
+ memcpy(&p_pfn_bssid[i].macaddr, &iter->macaddr, ETHER_ADDR_LEN);
+ p_pfn_bssid[i].flags = iter->flags;
+ i++;
+ }
+ err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist);
+ if (err < 0) {
+ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
+ DHD_ERROR(("%s : failed to restart hotlist scan(err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+ } else {
+ err = dhd_pno_clean(dhd);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+exit:
+ _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
+ _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
+ if (p_ssid_list)
+ kfree(p_ssid_list);
+ if (p_pfn_bssid)
+ kfree(p_pfn_bssid);
+ return err;
+}
+
+int
+dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid,
+ struct dhd_pno_hotlist_params *hotlist_params)
+{
+ int err = BCME_OK;
+ int i;
+ uint16 _chan_list[WL_NUMCHANNELS];
+ int rem_nchan = 0;
+ int tot_nchan = 0;
+ int mode = 0;
+ dhd_pno_params_t *_params;
+ dhd_pno_params_t *_params2;
+ struct dhd_pno_bssid *_pno_bssid;
+ dhd_pno_status_info_t *_pno_state;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ NULL_CHECK(hotlist_params, "hotlist_params is NULL", err);
+ NULL_CHECK(p_pfn_bssid, "p_pfn_bssid is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+
+ if (!dhd_support_sta_mode(dhd)) {
+ err = BCME_BADOPTION;
+ goto exit;
+ }
+ if (!WLS_SUPPORTED(_pno_state)) {
+ DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
+ err = BCME_UNSUPPORTED;
+ goto exit;
+ }
+ _params = &_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS];
+ if (!(_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE)) {
+ _pno_state->pno_mode |= DHD_PNO_HOTLIST_MODE;
+ err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_HOTLIST_MODE);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to call _dhd_pno_reinitialize_prof\n",
+ __FUNCTION__));
+ goto exit;
+ }
+ }
+ _params->params_batch.nchan = hotlist_params->nchan;
+ _params->params_batch.scan_fr = hotlist_params->scan_fr;
+ if (hotlist_params->nchan)
+ memcpy(_params->params_hotlist.chan_list, hotlist_params->chan_list,
+ sizeof(_params->params_hotlist.chan_list));
+ memset(_chan_list, 0, sizeof(_chan_list));
+
+ rem_nchan = ARRAYSIZE(hotlist_params->chan_list) - hotlist_params->nchan;
+ if (hotlist_params->band == WLC_BAND_2G || hotlist_params->band == WLC_BAND_5G) {
+ /* get a valid channel list based on band B or A */
+ err = _dhd_pno_get_channels(dhd,
+ &_params->params_hotlist.chan_list[hotlist_params->nchan],
+ &rem_nchan, hotlist_params->band, FALSE);
+ if (err < 0) {
+ DHD_ERROR(("%s: failed to get valid channel list(band : %d)\n",
+ __FUNCTION__, hotlist_params->band));
+ goto exit;
+ }
+ /* now we need to update nchan because rem_chan has valid channel count */
+ _params->params_hotlist.nchan += rem_nchan;
+ /* need to sort channel list */
+ sort(_params->params_hotlist.chan_list, _params->params_hotlist.nchan,
+ sizeof(_params->params_hotlist.chan_list[0]), _dhd_pno_cmpfunc, NULL);
+ }
+#ifdef PNO_DEBUG
+{
+ int i;
+ DHD_PNO(("Channel list : "));
+ for (i = 0; i < _params->params_batch.nchan; i++) {
+ DHD_PNO(("%d ", _params->params_batch.chan_list[i]));
+ }
+ DHD_PNO(("\n"));
+}
+#endif
+ if (_params->params_hotlist.nchan) {
+ /* copy the channel list into local array */
+ memcpy(_chan_list, _params->params_hotlist.chan_list,
+ sizeof(_chan_list));
+ tot_nchan = _params->params_hotlist.nchan;
+ }
+ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
+ DHD_PNO(("PNO SSID is on progress in firmware\n"));
+ /* store current pno_mode before disabling pno */
+ mode = _pno_state->pno_mode;
+ err = _dhd_pno_enable(dhd, PNO_OFF);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
+ goto exit;
+ }
+ /* restore the previous mode */
+ _pno_state->pno_mode = mode;
+ /* Use the superset for channelist between two mode */
+ _params2 = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
+ if (_params2->params_legacy.nchan > 0 &&
+ _params->params_hotlist.nchan > 0) {
+ err = _dhd_pno_chan_merge(_chan_list, &tot_nchan,
+ &_params2->params_legacy.chan_list[0],
+ _params2->params_legacy.nchan,
+ &_params->params_hotlist.chan_list[0],
+ _params->params_hotlist.nchan);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to merge channel list"
+ "between legacy and hotlist\n",
+ __FUNCTION__));
+ goto exit;
+ }
+ }
+
+ }
+
+ INIT_LIST_HEAD(&(_params->params_hotlist.bssid_list));
+
+ err = _dhd_pno_add_bssid(dhd, p_pfn_bssid, hotlist_params->nbssid);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to call _dhd_pno_add_bssid(err :%d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_HOTLIST_MODE)) < 0) {
+ DHD_ERROR(("%s : failed to set call pno_set (err %d) in firmware\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ if (tot_nchan > 0) {
+ if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) {
+ DHD_ERROR(("%s : failed to set call pno_cfg (err %d) in firmware\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+ for (i = 0; i < hotlist_params->nbssid; i++) {
+ _pno_bssid = kzalloc(sizeof(struct dhd_pno_bssid), GFP_KERNEL);
+ NULL_CHECK(_pno_bssid, "_pfn_bssid is NULL", err);
+ memcpy(&_pno_bssid->macaddr, &p_pfn_bssid[i].macaddr, ETHER_ADDR_LEN);
+ _pno_bssid->flags = p_pfn_bssid[i].flags;
+ list_add_tail(&_pno_bssid->list, &_params->params_hotlist.bssid_list);
+ }
+ _params->params_hotlist.nbssid = hotlist_params->nbssid;
+ if (_pno_state->pno_status == DHD_PNO_DISABLED) {
+ if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0)
+ DHD_ERROR(("%s : failed to enable PNO\n", __FUNCTION__));
+ }
+exit:
+ /* clear mode in case of error */
+ if (err < 0)
+ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
+ return err;
+}
+
+int
+dhd_pno_stop_for_hotlist(dhd_pub_t *dhd)
+{
+ int err = BCME_OK;
+ uint32 mode = 0;
+ int i = 0;
+ dhd_pno_status_info_t *_pno_state;
+ dhd_pno_params_t *_params;
+ wlc_ssid_t *p_ssid_list = NULL;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+
+ if (!WLS_SUPPORTED(_pno_state)) {
+ DHD_ERROR(("%s : wifi location service is not supported\n",
+ __FUNCTION__));
+ err = BCME_UNSUPPORTED;
+ goto exit;
+ }
+
+ if (!(_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE)) {
+ DHD_ERROR(("%s : Hotlist MODE is not enabled\n",
+ __FUNCTION__));
+ goto exit;
+ }
+ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
+
+ if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_BATCH_MODE)) {
+ /* retrieve the batching data from firmware into host */
+ dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
+ /* save current pno_mode before calling dhd_pno_clean */
+ mode = _pno_state->pno_mode;
+ err = dhd_pno_clean(dhd);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ /* restore previos pno mode */
+ _pno_state->pno_mode = mode;
+ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
+ /* restart Legacy PNO Scan */
+ struct dhd_pno_legacy_params *_params_legacy;
+ struct dhd_pno_ssid *iter, *next;
+ _params_legacy =
+ &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
+ p_ssid_list =
+ kzalloc(sizeof(wlc_ssid_t) * _params_legacy->nssid, GFP_KERNEL);
+ if (p_ssid_list == NULL) {
+ DHD_ERROR(("%s : failed to allocate wlc_ssid_t array (count: %d)",
+ __FUNCTION__, _params_legacy->nssid));
+ err = BCME_ERROR;
+ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ goto exit;
+ }
+ /* convert dhd_pno_ssid to dhd_pno_ssid */
+ list_for_each_entry_safe(iter, next, &_params_legacy->ssid_list, list) {
+ p_ssid_list[i].SSID_len = iter->SSID_len;
+ memcpy(p_ssid_list[i].SSID, iter->SSID, p_ssid_list[i].SSID_len);
+ i++;
+ }
+ err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid,
+ _params_legacy->scan_fr, _params_legacy->pno_repeat,
+ _params_legacy->pno_freq_expo_max, _params_legacy->chan_list,
+ _params_legacy->nchan);
+ if (err < 0) {
+ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ } else if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
+ /* restart Batching Scan */
+ _params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]);
+ /* restart BATCH SCAN */
+ err = dhd_pno_set_for_batch(dhd, &_params->params_batch);
+ if (err < 0) {
+ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
+ DHD_ERROR(("%s : failed to restart batch scan(err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+ } else {
+ err = dhd_pno_clean(dhd);
+ if (err < 0) {
+ DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
+ __FUNCTION__, err));
+ goto exit;
+ }
+ }
+exit:
+ if (p_ssid_list)
+ kfree(p_ssid_list);
+ return err;
+}
+
+int
+dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)
+{
+ int err = BCME_OK;
+ uint status, event_type, flags, datalen;
+ dhd_pno_status_info_t *_pno_state;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ if (!WLS_SUPPORTED(_pno_state)) {
+ DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
+ err = BCME_UNSUPPORTED;
+ goto exit;
+ }
+ event_type = ntoh32(event->event_type);
+ flags = ntoh16(event->flags);
+ status = ntoh32(event->status);
+ datalen = ntoh32(event->datalen);
+ DHD_PNO(("%s enter : event_type :%d\n", __FUNCTION__, event_type));
+ switch (event_type) {
+ case WLC_E_PFN_BSSID_NET_FOUND:
+ case WLC_E_PFN_BSSID_NET_LOST:
+ /* TODO : need to implement event logic using generic netlink */
+ break;
+ case WLC_E_PFN_BEST_BATCHING:
+ {
+ struct dhd_pno_batch_params *params_batch;
+ params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
+ if (!waitqueue_active(&_pno_state->get_batch_done.wait)) {
+ DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING\n", __FUNCTION__));
+ params_batch->get_batch.buf = NULL;
+ params_batch->get_batch.bufsize = 0;
+ params_batch->get_batch.reason = PNO_STATUS_EVENT;
+ schedule_work(&_pno_state->work);
+ } else
+ DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING"
+ "will skip this event\n", __FUNCTION__));
+ break;
+ }
+ default:
+ DHD_ERROR(("unknown event : %d\n", event_type));
+ }
+exit:
+ return err;
+}
+
+int dhd_pno_init(dhd_pub_t *dhd)
+{
+ int err = BCME_OK;
+ dhd_pno_status_info_t *_pno_state;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ UNUSED_PARAMETER(_dhd_pno_suspend);
+ if (dhd->pno_state)
+ goto exit;
+ dhd->pno_state = MALLOC(dhd->osh, sizeof(dhd_pno_status_info_t));
+ NULL_CHECK(dhd->pno_state, "failed to create dhd_pno_state", err);
+ memset(dhd->pno_state, 0, sizeof(dhd_pno_status_info_t));
+ /* need to check whether current firmware support batching and hotlist scan */
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ _pno_state->wls_supported = TRUE;
+ _pno_state->dhd = dhd;
+ mutex_init(&_pno_state->pno_mutex);
+ INIT_WORK(&_pno_state->work, _dhd_pno_get_batch_handler);
+ init_completion(&_pno_state->get_batch_done);
+ err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, 0);
+ if (err == BCME_UNSUPPORTED) {
+ _pno_state->wls_supported = FALSE;
+ DHD_INFO(("Current firmware doesn't support"
+ " Android Location Service\n"));
+ }
+exit:
+ return err;
+}
+int dhd_pno_deinit(dhd_pub_t *dhd)
+{
+ int err = BCME_OK;
+ dhd_pno_status_info_t *_pno_state;
+ dhd_pno_params_t *_params;
+ NULL_CHECK(dhd, "dhd is NULL", err);
+
+ DHD_PNO(("%s enter\n", __FUNCTION__));
+ _pno_state = PNO_GET_PNOSTATE(dhd);
+ NULL_CHECK(_pno_state, "pno_state is NULL", err);
+ /* may need to free legacy ssid_list */
+ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
+ _params = &_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
+ _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
+ }
+
+ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
+ _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
+ /* clear resource if the BATCH MODE is on */
+ _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
+ }
+ cancel_work_sync(&_pno_state->work);
+ MFREE(dhd->osh, _pno_state, sizeof(dhd_pno_status_info_t));
+ dhd->pno_state = NULL;
+ return err;
+}
+#endif /* PNO_SUPPORT */
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h
new file mode 100644
index 000000000000..4c9c49ccdbad
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_pno.h
@@ -0,0 +1,253 @@
+/*
+ * Header file of Broadcom Dongle Host Driver (DHD)
+ * Prefered Network Offload code and Wi-Fi Location Service(WLS) code.
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_pno.h 423669 2013-09-18 13:01:55Z $
+ */
+
+#ifndef __DHD_PNO_H__
+#define __DHD_PNO_H__
+
+#if defined(PNO_SUPPORT)
+#define PNO_TLV_PREFIX 'S'
+#define PNO_TLV_VERSION '1'
+#define PNO_TLV_SUBTYPE_LEGACY_PNO '2'
+#define PNO_TLV_RESERVED '0'
+
+#define PNO_BATCHING_SET "SET"
+#define PNO_BATCHING_GET "GET"
+#define PNO_BATCHING_STOP "STOP"
+
+#define PNO_PARAMS_DELIMETER " "
+#define PNO_PARAM_CHANNEL_DELIMETER ","
+#define PNO_PARAM_VALUE_DELLIMETER '='
+#define PNO_PARAM_SCANFREQ "SCANFREQ"
+#define PNO_PARAM_BESTN "BESTN"
+#define PNO_PARAM_MSCAN "MSCAN"
+#define PNO_PARAM_CHANNEL "CHANNEL"
+#define PNO_PARAM_RTT "RTT"
+
+#define PNO_TLV_TYPE_SSID_IE 'S'
+#define PNO_TLV_TYPE_TIME 'T'
+#define PNO_TLV_FREQ_REPEAT 'R'
+#define PNO_TLV_FREQ_EXPO_MAX 'M'
+
+#define MAXNUM_SSID_PER_ADD 16
+#define MAXNUM_PNO_PARAMS 2
+#define PNO_TLV_COMMON_LENGTH 1
+#define DEFAULT_BATCH_MSCAN 16
+
+#define RESULTS_END_MARKER "----\n"
+#define SCAN_END_MARKER "####\n"
+#define AP_END_MARKER "====\n"
+
+enum scan_status {
+ /* SCAN ABORT by other scan */
+ PNO_STATUS_ABORT,
+ /* RTT is presence or not */
+ PNO_STATUS_RTT_PRESENCE,
+ /* Disable PNO by Driver */
+ PNO_STATUS_DISABLE,
+ /* NORMAL BATCHING GET */
+ PNO_STATUS_NORMAL,
+ /* WLC_E_PFN_BEST_BATCHING */
+ PNO_STATUS_EVENT,
+ PNO_STATUS_MAX
+};
+#define PNO_STATUS_ABORT_MASK 0x0001
+#define PNO_STATUS_RTT_MASK 0x0002
+#define PNO_STATUS_DISABLE_MASK 0x0004
+#define PNO_STATUS_OOM_MASK 0x0010
+
+enum index_mode {
+ INDEX_OF_LEGACY_PARAMS,
+ INDEX_OF_BATCH_PARAMS,
+ INDEX_OF_HOTLIST_PARAMS,
+ INDEX_MODE_MAX
+};
+enum dhd_pno_status {
+ DHD_PNO_DISABLED,
+ DHD_PNO_ENABLED,
+ DHD_PNO_SUSPEND
+};
+typedef struct cmd_tlv {
+ char prefix;
+ char version;
+ char subtype;
+ char reserved;
+} cmd_tlv_t;
+typedef enum dhd_pno_mode {
+ /* Wi-Fi Legacy PNO Mode */
+ DHD_PNO_NONE_MODE = 0,
+ DHD_PNO_LEGACY_MODE = (1 << (0)),
+ /* Wi-Fi Android BATCH SCAN Mode */
+ DHD_PNO_BATCH_MODE = (1 << (1)),
+ /* Wi-Fi Android Hotlist SCAN Mode */
+ DHD_PNO_HOTLIST_MODE = (1 << (2))
+} dhd_pno_mode_t;
+struct dhd_pno_ssid {
+ uint32 SSID_len;
+ uchar SSID[DOT11_MAX_SSID_LEN];
+ struct list_head list;
+};
+struct dhd_pno_bssid {
+ struct ether_addr macaddr;
+ /* Bit4: suppress_lost, Bit3: suppress_found */
+ uint16 flags;
+ struct list_head list;
+};
+typedef struct dhd_pno_bestnet_entry {
+ struct ether_addr BSSID;
+ uint8 SSID_len;
+ uint8 SSID[DOT11_MAX_SSID_LEN];
+ int8 RSSI;
+ uint8 channel;
+ uint32 timestamp;
+ uint16 rtt0; /* distance_cm based on RTT */
+ uint16 rtt1; /* distance_cm based on sample standard deviation */
+ unsigned long recorded_time;
+ struct list_head list;
+} dhd_pno_bestnet_entry_t;
+#define BESTNET_ENTRY_SIZE (sizeof(dhd_pno_bestnet_entry_t))
+
+typedef struct dhd_pno_bestnet_header {
+ struct dhd_pno_bestnet_header *next;
+ uint8 reason;
+ uint32 tot_cnt;
+ uint32 tot_size;
+ struct list_head entry_list;
+} dhd_pno_best_header_t;
+#define BEST_HEADER_SIZE (sizeof(dhd_pno_best_header_t))
+
+typedef struct dhd_pno_scan_results {
+ dhd_pno_best_header_t *bestnetheader;
+ uint8 cnt_header;
+ struct list_head list;
+} dhd_pno_scan_results_t;
+#define SCAN_RESULTS_SIZE (sizeof(dhd_pno_scan_results_t))
+
+struct dhd_pno_get_batch_info {
+ /* info related to get batch */
+ char *buf;
+ bool batch_started;
+ uint32 tot_scan_cnt;
+ uint32 expired_tot_scan_cnt;
+ uint32 top_node_cnt;
+ uint32 bufsize;
+ uint32 bytes_written;
+ int reason;
+ struct list_head scan_results_list;
+ struct list_head expired_scan_results_list;
+};
+struct dhd_pno_legacy_params {
+ uint16 scan_fr;
+ uint16 chan_list[WL_NUMCHANNELS];
+ uint16 nchan;
+ int pno_repeat;
+ int pno_freq_expo_max;
+ int nssid;
+ struct list_head ssid_list;
+};
+struct dhd_pno_batch_params {
+ int32 scan_fr;
+ uint8 bestn;
+ uint8 mscan;
+ uint8 band;
+ uint16 chan_list[WL_NUMCHANNELS];
+ uint16 nchan;
+ uint16 rtt;
+ struct dhd_pno_get_batch_info get_batch;
+};
+struct dhd_pno_hotlist_params {
+ uint8 band;
+ int32 scan_fr;
+ uint16 chan_list[WL_NUMCHANNELS];
+ uint16 nchan;
+ uint16 nbssid;
+ struct list_head bssid_list;
+};
+typedef union dhd_pno_params {
+ struct dhd_pno_legacy_params params_legacy;
+ struct dhd_pno_batch_params params_batch;
+ struct dhd_pno_hotlist_params params_hotlist;
+} dhd_pno_params_t;
+typedef struct dhd_pno_status_info {
+ dhd_pub_t *dhd;
+ struct work_struct work;
+ struct mutex pno_mutex;
+ struct completion get_batch_done;
+ bool wls_supported; /* wifi location service supported or not */
+ enum dhd_pno_status pno_status;
+ enum dhd_pno_mode pno_mode;
+ dhd_pno_params_t pno_params_arr[INDEX_MODE_MAX];
+ struct list_head head_list;
+} dhd_pno_status_info_t;
+
+/* wrapper functions */
+extern int
+dhd_dev_pno_enable(struct net_device *dev, int enable);
+
+extern int
+dhd_dev_pno_stop_for_ssid(struct net_device *dev);
+
+extern int
+dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
+ uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan);
+
+extern int
+dhd_dev_pno_set_for_batch(struct net_device *dev,
+ struct dhd_pno_batch_params *batch_params);
+
+extern int
+dhd_dev_pno_get_for_batch(struct net_device *dev, char *buf, int bufsize);
+
+extern int
+dhd_dev_pno_stop_for_batch(struct net_device *dev);
+
+extern int
+dhd_dev_pno_set_for_hotlist(struct net_device *dev, wl_pfn_bssid_t *p_pfn_bssid,
+ struct dhd_pno_hotlist_params *hotlist_params);
+
+/* dhd pno fuctions */
+extern int dhd_pno_stop_for_ssid(dhd_pub_t *dhd);
+extern int dhd_pno_enable(dhd_pub_t *dhd, int enable);
+extern int dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
+ uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan);
+
+extern int dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params);
+
+extern int dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason);
+
+
+extern int dhd_pno_stop_for_batch(dhd_pub_t *dhd);
+
+extern int dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid,
+ struct dhd_pno_hotlist_params *hotlist_params);
+
+extern int dhd_pno_stop_for_hotlist(dhd_pub_t *dhd);
+
+extern int dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data);
+extern int dhd_pno_init(dhd_pub_t *dhd);
+extern int dhd_pno_deinit(dhd_pub_t *dhd);
+#endif
+
+#endif /* __DHD_PNO_H__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_proto.h b/drivers/net/wireless/bcmdhd/dhd_proto.h
new file mode 100644
index 000000000000..828330079b9e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_proto.h
@@ -0,0 +1,115 @@
+/*
+ * Header file describing the internal (inter-module) DHD interfaces.
+ *
+ * Provides type definitions and function prototypes used to link the
+ * DHD OS, bus, and protocol modules.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_proto.h 455951 2014-02-17 10:52:22Z $
+ */
+
+#ifndef _dhd_proto_h_
+#define _dhd_proto_h_
+
+#include <dhdioctl.h>
+#include <wlioctl.h>
+
+#ifndef IOCTL_RESP_TIMEOUT
+#define IOCTL_RESP_TIMEOUT 2000 /* In milli second default value for Production FW */
+#endif /* IOCTL_RESP_TIMEOUT */
+
+#ifndef MFG_IOCTL_RESP_TIMEOUT
+#define MFG_IOCTL_RESP_TIMEOUT 20000 /* In milli second default value for MFG FW */
+#endif /* MFG_IOCTL_RESP_TIMEOUT */
+
+/*
+ * Exported from the dhd protocol module (dhd_cdc, dhd_rndis)
+ */
+
+/* Linkage, sets prot link and updates hdrlen in pub */
+extern int dhd_prot_attach(dhd_pub_t *dhdp);
+
+/* Unlink, frees allocated protocol memory (including dhd_prot) */
+extern void dhd_prot_detach(dhd_pub_t *dhdp);
+
+/* Initialize protocol: sync w/dongle state.
+ * Sets dongle media info (iswl, drv_version, mac address).
+ */
+extern int dhd_prot_init(dhd_pub_t *dhdp);
+
+/* Stop protocol: sync w/dongle state. */
+extern void dhd_prot_stop(dhd_pub_t *dhdp);
+
+/* Add any protocol-specific data header.
+ * Caller must reserve prot_hdrlen prepend space.
+ */
+extern void dhd_prot_hdrpush(dhd_pub_t *, int ifidx, void *txp);
+
+/* Remove any protocol-specific data header. */
+extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, void *rxp, uchar *buf, uint *len);
+
+/* Use protocol to issue ioctl to dongle */
+extern int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len);
+
+/* Handles a protocol control response asynchronously */
+extern int dhd_prot_ctl_complete(dhd_pub_t *dhd);
+
+/* Check for and handle local prot-specific iovar commands */
+extern int dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
+ void *params, int plen, void *arg, int len, bool set);
+
+/* Add prot dump output to a buffer */
+extern void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+
+/* Update local copy of dongle statistics */
+extern void dhd_prot_dstats(dhd_pub_t *dhdp);
+
+extern int dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen);
+
+extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
+
+extern int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf,
+ uint reorder_info_len, void **pkt, uint32 *free_buf_count);
+
+#ifdef BCMPCIE
+extern int dhd_prot_process_msgbuf(dhd_pub_t *dhd);
+extern int dhd_prot_process_ctrlbuf(dhd_pub_t * dhd);
+extern bool dhd_prot_dtohsplit(dhd_pub_t * dhd);
+extern int dhd_post_dummy_msg(dhd_pub_t *dhd);
+extern int dhdmsgbuf_lpbk_req(dhd_pub_t *dhd, uint len);
+extern void dhd_prot_rx_dataoffset(dhd_pub_t *dhd, uint32 offset);
+extern int dhd_prot_txdata(dhd_pub_t *dhd, void *p, uint8 ifidx);
+extern int dhdmsgbuf_dmaxfer_req(dhd_pub_t *dhd, uint len, uint srcdelay, uint destdelay);
+#endif
+
+/********************************
+ * For version-string expansion *
+ */
+#if defined(BDC)
+#define DHD_PROTOCOL "bdc"
+#elif defined(CDC)
+#define DHD_PROTOCOL "cdc"
+#else
+#define DHD_PROTOCOL "unknown"
+#endif /* proto */
+
+#endif /* _dhd_proto_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
new file mode 100644
index 000000000000..425fbba7810c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -0,0 +1,8343 @@
+/*
+ * DHD Bus Module for SDIO
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_sdio.c 663157 2016-12-08 12:19:27Z $
+ */
+
+#include <typedefs.h>
+#include <osl.h>
+#include <bcmsdh.h>
+
+#ifdef BCMEMBEDIMAGE
+#include BCMEMBEDIMAGE
+#endif /* BCMEMBEDIMAGE */
+
+#include <bcmdefs.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <bcmdevs.h>
+
+#include <siutils.h>
+#include <hndpmu.h>
+#include <hndsoc.h>
+#include <bcmsdpcm.h>
+#if defined(DHD_DEBUG)
+#include <hndrte_armtrap.h>
+#include <hndrte_cons.h>
+#endif /* defined(DHD_DEBUG) */
+#include <sbchipc.h>
+#include <sbhnddma.h>
+
+#include <sdio.h>
+#include <sbsdio.h>
+#include <sbsdpcmdev.h>
+#include <bcmsdpcm.h>
+#include <bcmsdbus.h>
+
+#include <proto/ethernet.h>
+#include <proto/802.1d.h>
+#include <proto/802.11.h>
+
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_bus.h>
+#include <dhd_proto.h>
+#include <dhd_dbg.h>
+#include <dhdioctl.h>
+#include <sdiovar.h>
+
+/* Murata Work-around code for HT Avail failure (due to no external slow clk) */
+#define MURATA_WORKAROUND_FOR_HTAVAIL 1
+
+#ifdef PROP_TXSTATUS
+#include <dhd_wlfc.h>
+#endif
+
+#ifdef DHDTCPACK_SUPPRESS
+#include <dhd_ip.h>
+#endif
+
+bool dhd_mp_halting(dhd_pub_t *dhdp);
+extern void bcmsdh_waitfor_iodrain(void *sdh);
+extern void bcmsdh_reject_ioreqs(void *sdh, bool reject);
+extern bool bcmsdh_fatal_error(void *sdh);
+
+#ifndef DHDSDIO_MEM_DUMP_FNAME
+#define DHDSDIO_MEM_DUMP_FNAME "mem_dump"
+#endif
+
+#define QLEN (1024) /* bulk rx and tx queue lengths */
+#define FCHI (QLEN - 10)
+#define FCLOW (FCHI / 2)
+#define PRIOMASK 7
+
+#define TXRETRIES 2 /* # of retries for tx frames */
+#define READ_FRM_CNT_RETRIES 3
+#ifndef DHD_RXBOUND
+#define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */
+#endif
+
+#ifndef DHD_TXBOUND
+#define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */
+#endif
+
+#define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */
+
+#define MEMBLOCK 2048 /* Block size used for downloading of dongle image */
+#define MAX_NVRAMBUF_SIZE 4096 /* max nvram buf size */
+#define MAX_DATA_BUF (64 * 1024) /* Must be large enough to hold biggest possible glom */
+
+#ifndef DHD_FIRSTREAD
+#define DHD_FIRSTREAD 32
+#endif
+#if !ISPOWEROF2(DHD_FIRSTREAD)
+#error DHD_FIRSTREAD is not a power of 2!
+#endif
+
+/* Total length of frame header for dongle protocol */
+#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
+#define SDPCM_HDRLEN_TXGLOM (SDPCM_HDRLEN + SDPCM_HWEXT_LEN)
+#define MAX_TX_PKTCHAIN_CNT SDPCM_MAXGLOM_SIZE
+
+#ifdef SDTEST
+#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
+#else
+#define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN)
+#endif
+
+/* Space for header read, limit for data packets */
+#ifndef MAX_HDR_READ
+#define MAX_HDR_READ 32
+#endif
+#if !ISPOWEROF2(MAX_HDR_READ)
+#error MAX_HDR_READ is not a power of 2!
+#endif
+
+#define MAX_RX_DATASZ 2048
+
+/* Maximum milliseconds to wait for F2 to come up */
+#define DHD_WAIT_F2RDY 3000
+
+/* Bump up limit on waiting for HT to account for first startup;
+ * if the image is doing a CRC calculation before programming the PMU
+ * for HT availability, it could take a couple hundred ms more, so
+ * max out at a 1 second (1000000us).
+ */
+#if (PMU_MAX_TRANSITION_DLY <= 1000000)
+#undef PMU_MAX_TRANSITION_DLY
+#define PMU_MAX_TRANSITION_DLY 1000000
+#define PMU_TRANSITION_DLY_EXTRA 500000
+#endif
+
+/* hooks for limiting threshold custom tx num in rx processing */
+#define DEFAULT_TXINRX_THRES 0
+#ifndef CUSTOM_TXINRX_THRES
+#define CUSTOM_TXINRX_THRES DEFAULT_TXINRX_THRES
+#endif
+
+/* Value for ChipClockCSR during initial setup */
+#define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
+#define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
+
+/* Flags for SDH calls */
+#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
+
+/* Packet free applicable unconditionally for sdio and sdspi. Conditional if
+ * bufpool was present for gspi bus.
+ */
+#define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \
+ PKTFREE(bus->dhd->osh, pkt, FALSE);
+DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
+
+
+#ifdef DHD_DEBUG
+/* Device console log buffer state */
+#define CONSOLE_LINE_MAX 192
+#define CONSOLE_BUFFER_MAX 2024
+typedef struct dhd_console {
+ uint count; /* Poll interval msec counter */
+ uint log_addr; /* Log struct address (fixed) */
+ hndrte_log_t log; /* Log struct (host copy) */
+ uint bufsize; /* Size of log buffer */
+ uint8 *buf; /* Log buffer (host copy) */
+ uint last; /* Last buffer read index */
+} dhd_console_t;
+#endif /* DHD_DEBUG */
+
+#define REMAP_ENAB(bus) ((bus)->remap)
+#define REMAP_ISADDR(bus, a) (((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
+#define KSO_ENAB(bus) ((bus)->kso)
+#define SR_ENAB(bus) ((bus)->_srenab)
+#define SLPAUTO_ENAB(bus) ((SR_ENAB(bus)) && ((bus)->_slpauto))
+#define MIN_RSRC_ADDR (SI_ENUM_BASE + 0x618)
+#define MIN_RSRC_SR 0x3
+#define CORE_CAPEXT_ADDR (SI_ENUM_BASE + 0x64c)
+#define CORE_CAPEXT_SR_SUPPORTED_MASK (1 << 1)
+#define RCTL_MACPHY_DISABLE_MASK (1 << 26)
+#define RCTL_LOGIC_DISABLE_MASK (1 << 27)
+
+#define OOB_WAKEUP_ENAB(bus) ((bus)->_oobwakeup)
+#define GPIO_DEV_SRSTATE 16 /* Host gpio17 mapped to device gpio0 SR state */
+#define GPIO_DEV_SRSTATE_TIMEOUT 320000 /* 320ms */
+#define GPIO_DEV_WAKEUP 17 /* Host gpio17 mapped to device gpio1 wakeup */
+#define CC_CHIPCTRL2_GPIO1_WAKEUP (1 << 0)
+#define CC_CHIPCTRL3_SR_ENG_ENABLE (1 << 2)
+#define OVERFLOW_BLKSZ512_WM 96
+#define OVERFLOW_BLKSZ512_MES 80
+
+#define CC_PMUCC3 (0x3)
+/* Private data for SDIO bus interaction */
+typedef struct dhd_bus {
+ dhd_pub_t *dhd;
+
+ bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */
+ si_t *sih; /* Handle for SI calls */
+ char *vars; /* Variables (from CIS and/or other) */
+ uint varsz; /* Size of variables buffer */
+ uint32 sbaddr; /* Current SB window pointer (-1, invalid) */
+
+ sdpcmd_regs_t *regs; /* Registers for SDIO core */
+ uint sdpcmrev; /* SDIO core revision */
+ uint armrev; /* CPU core revision */
+ uint ramrev; /* SOCRAM core revision */
+ uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */
+ uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
+ uint32 srmemsize; /* Size of SRMEM */
+
+ uint32 bus; /* gSPI or SDIO bus */
+ uint32 bus_num; /* bus number */
+ uint32 slot_num; /* slot ID */
+ uint32 hostintmask; /* Copy of Host Interrupt Mask */
+ uint32 intstatus; /* Intstatus bits (events) pending */
+ bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
+ bool fcstate; /* State of dongle flow-control */
+
+ uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */
+ char *fw_path; /* module_param: path to firmware image */
+ char *nv_path; /* module_param: path to nvram vars file */
+ const char *nvram_params; /* user specified nvram params. */
+
+ uint blocksize; /* Block size of SDIO transfers */
+ uint roundup; /* Max roundup limit */
+
+ struct pktq txq; /* Queue length used for flow-control */
+ uint8 flowcontrol; /* per prio flow control bitmask */
+ uint8 tx_seq; /* Transmit sequence number (next) */
+ uint8 tx_max; /* Maximum transmit sequence allowed */
+
+ uint8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
+ uint8 *rxhdr; /* Header of current rx frame (in hdrbuf) */
+ uint16 nextlen; /* Next Read Len from last header */
+ uint8 rx_seq; /* Receive sequence number (expected) */
+ bool rxskip; /* Skip receive (awaiting NAK ACK) */
+
+ void *glomd; /* Packet containing glomming descriptor */
+ void *glom; /* Packet chain for glommed superframe */
+ uint glomerr; /* Glom packet read errors */
+
+ uint8 *rxbuf; /* Buffer for receiving control packets */
+ uint rxblen; /* Allocated length of rxbuf */
+ uint8 *rxctl; /* Aligned pointer into rxbuf */
+ uint8 *databuf; /* Buffer for receiving big glom packet */
+ uint8 *dataptr; /* Aligned pointer into databuf */
+ uint rxlen; /* Length of valid data in buffer */
+
+ uint8 sdpcm_ver; /* Bus protocol reported by dongle */
+
+ bool intr; /* Use interrupts */
+ bool poll; /* Use polling */
+ bool ipend; /* Device interrupt is pending */
+ bool intdis; /* Interrupts disabled by isr */
+ uint intrcount; /* Count of device interrupt callbacks */
+ uint lastintrs; /* Count as of last watchdog timer */
+ uint spurious; /* Count of spurious interrupts */
+ uint pollrate; /* Ticks between device polls */
+ uint polltick; /* Tick counter */
+ uint pollcnt; /* Count of active polls */
+
+#ifdef DHD_DEBUG
+ dhd_console_t console; /* Console output polling support */
+ uint console_addr; /* Console address from shared struct */
+#endif /* DHD_DEBUG */
+
+ uint regfails; /* Count of R_REG/W_REG failures */
+
+ uint clkstate; /* State of sd and backplane clock(s) */
+ bool activity; /* Activity flag for clock down */
+ int32 idletime; /* Control for activity timeout */
+ int32 idlecount; /* Activity timeout counter */
+ int32 idleclock; /* How to set bus driver when idle */
+ int32 sd_divisor; /* Speed control to bus driver */
+ int32 sd_mode; /* Mode control to bus driver */
+ int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */
+ bool use_rxchain; /* If dhd should use PKT chains */
+ bool sleeping; /* Is SDIO bus sleeping? */
+#if defined(SUPPORT_P2P_GO_PS)
+ wait_queue_head_t bus_sleep;
+#endif /* LINUX && (SUPPORT_P2P_GO_PS || !OEM_ANDROID) */
+ uint rxflow_mode; /* Rx flow control mode */
+ bool rxflow; /* Is rx flow control on */
+ uint prev_rxlim_hit; /* Is prev rx limit exceeded (per dpc schedule) */
+ bool alp_only; /* Don't use HT clock (ALP only) */
+ /* Field to decide if rx of control frames happen in rxbuf or lb-pool */
+ bool usebufpool;
+ int32 txinrx_thres; /* num of in-queued pkts */
+ int32 dotxinrx; /* tx first in dhdsdio_readframes */
+#ifdef SDTEST
+ /* external loopback */
+ bool ext_loop;
+ uint8 loopid;
+
+ /* pktgen configuration */
+ uint pktgen_freq; /* Ticks between bursts */
+ uint pktgen_count; /* Packets to send each burst */
+ uint pktgen_print; /* Bursts between count displays */
+ uint pktgen_total; /* Stop after this many */
+ uint pktgen_minlen; /* Minimum packet data len */
+ uint pktgen_maxlen; /* Maximum packet data len */
+ uint pktgen_mode; /* Configured mode: tx, rx, or echo */
+ uint pktgen_stop; /* Number of tx failures causing stop */
+
+ /* active pktgen fields */
+ uint pktgen_tick; /* Tick counter for bursts */
+ uint pktgen_ptick; /* Burst counter for printing */
+ uint pktgen_sent; /* Number of test packets generated */
+ uint pktgen_rcvd; /* Number of test packets received */
+ uint pktgen_prev_time; /* Time at which previous stats where printed */
+ uint pktgen_prev_sent; /* Number of test packets generated when
+ * previous stats were printed
+ */
+ uint pktgen_prev_rcvd; /* Number of test packets received when
+ * previous stats were printed
+ */
+ uint pktgen_fail; /* Number of failed send attempts */
+ uint16 pktgen_len; /* Length of next packet to send */
+#define PKTGEN_RCV_IDLE (0)
+#define PKTGEN_RCV_ONGOING (1)
+ uint16 pktgen_rcv_state; /* receive state */
+ uint pktgen_rcvd_rcvsession; /* test pkts rcvd per rcv session. */
+#endif /* SDTEST */
+
+ /* Some additional counters */
+ uint tx_sderrs; /* Count of tx attempts with sd errors */
+ uint fcqueued; /* Tx packets that got queued */
+ uint rxrtx; /* Count of rtx requests (NAK to dongle) */
+ uint rx_toolong; /* Receive frames too long to receive */
+ uint rxc_errors; /* SDIO errors when reading control frames */
+ uint rx_hdrfail; /* SDIO errors on header reads */
+ uint rx_badhdr; /* Bad received headers (roosync?) */
+ uint rx_badseq; /* Mismatched rx sequence number */
+ uint fc_rcvd; /* Number of flow-control events received */
+ uint fc_xoff; /* Number which turned on flow-control */
+ uint fc_xon; /* Number which turned off flow-control */
+ uint rxglomfail; /* Failed deglom attempts */
+ uint rxglomframes; /* Number of glom frames (superframes) */
+ uint rxglompkts; /* Number of packets from glom frames */
+ uint f2rxhdrs; /* Number of header reads */
+ uint f2rxdata; /* Number of frame data reads */
+ uint f2txdata; /* Number of f2 frame writes */
+ uint f1regdata; /* Number of f1 register accesses */
+#ifdef DHDENABLE_TAILPAD
+ uint tx_tailpad_chain; /* Number of tail padding by chaining pad_pkt */
+ uint tx_tailpad_pktget; /* Number of tail padding by new PKTGET */
+#endif
+ uint8 *ctrl_frame_buf;
+ uint32 ctrl_frame_len;
+ bool ctrl_frame_stat;
+ uint32 rxint_mode; /* rx interrupt mode */
+ bool remap; /* Contiguous 1MB RAM: 512K socram + 512K devram
+ * Available with socram rev 16
+ * Remap region not DMA-able
+ */
+ bool kso;
+ bool _slpauto;
+ bool _oobwakeup;
+ bool _srenab;
+ bool readframes;
+ bool reqbussleep;
+ uint32 resetinstr;
+ uint32 dongle_ram_base;
+
+ void *glom_pkt_arr[SDPCM_MAXGLOM_SIZE]; /* Array of pkts for glomming */
+ uint32 txglom_cnt; /* Number of pkts in the glom array */
+ uint32 txglom_total_len; /* Total length of pkts in glom array */
+ bool txglom_enable; /* Flag to indicate whether tx glom is enabled/disabled */
+ uint32 txglomsize; /* Glom size limitation */
+ void *pad_pkt;
+#if defined(CUSTOMER_IMX)
+ int bus_wake_on_resume;
+#endif /* CUSTOMER_IMX */
+} dhd_bus_t;
+
+/* clkstate */
+#define CLK_NONE 0
+#define CLK_SDONLY 1
+#define CLK_PENDING 2 /* Not used yet */
+#define CLK_AVAIL 3
+
+#define DHD_NOPMU(dhd) (FALSE)
+
+#ifdef DHD_DEBUG
+static int qcount[NUMPRIO];
+static int tx_packets[NUMPRIO];
+#endif /* DHD_DEBUG */
+
+/* Deferred transmit */
+const uint dhd_deferred_tx = 1;
+
+extern uint dhd_watchdog_ms;
+
+extern void dhd_os_wd_timer(void *bus, uint wdtick);
+
+/* Tx/Rx bounds */
+uint dhd_txbound;
+uint dhd_rxbound;
+uint dhd_txminmax = DHD_TXMINMAX;
+
+/* override the RAM size if possible */
+#define DONGLE_MIN_RAMSIZE (128 *1024)
+int dhd_dongle_ramsize;
+
+uint dhd_doflow = TRUE;
+uint dhd_dpcpoll = FALSE;
+
+module_param(dhd_doflow, uint, 0644);
+module_param(dhd_dpcpoll, uint, 0644);
+
+static bool dhd_alignctl;
+
+static bool sd1idle;
+
+static bool retrydata;
+#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
+
+static uint watermark = 8;
+static uint mesbusyctrl = 0;
+static const uint firstread = DHD_FIRSTREAD;
+
+/* Retry count for register access failures */
+static const uint retry_limit = 2;
+
+/* Force even SD lengths (some host controllers mess up on odd bytes) */
+static bool forcealign;
+
+#define ALIGNMENT 4
+
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
+#endif
+
+#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
+#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
+#endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
+#define PKTALIGN(osh, p, len, align) \
+ do { \
+ uintptr datalign; \
+ datalign = (uintptr)PKTDATA((osh), (p)); \
+ datalign = ROUNDUP(datalign, (align)) - datalign; \
+ ASSERT(datalign < (align)); \
+ ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign)); \
+ if (datalign) \
+ PKTPULL((osh), (p), (uint)datalign); \
+ PKTSETLEN((osh), (p), (len)); \
+ } while (0)
+
+/* Limit on rounding up frames */
+static const uint max_roundup = 512;
+
+/* Try doing readahead */
+static bool dhd_readahead;
+
+/* To check if there's window offered */
+#define DATAOK(bus) \
+ (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
+ (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
+
+/* To check if there's window offered for ctrl frame */
+#define TXCTLOK(bus) \
+ (((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
+ (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
+
+/* Number of pkts available in dongle for data RX */
+#define DATABUFCNT(bus) \
+ ((uint8)(bus->tx_max - bus->tx_seq) - 1)
+
+/* Macros to get register read/write status */
+/* NOTE: these assume a local dhdsdio_bus_t *bus! */
+#define R_SDREG(regvar, regaddr, retryvar) \
+do { \
+ retryvar = 0; \
+ do { \
+ regvar = R_REG(bus->dhd->osh, regaddr); \
+ } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
+ if (retryvar) { \
+ bus->regfails += (retryvar-1); \
+ if (retryvar > retry_limit) { \
+ DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
+ __FUNCTION__, __LINE__)); \
+ regvar = 0; \
+ } \
+ } \
+} while (0)
+
+#define W_SDREG(regval, regaddr, retryvar) \
+do { \
+ retryvar = 0; \
+ do { \
+ W_REG(bus->dhd->osh, regaddr, regval); \
+ } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
+ if (retryvar) { \
+ bus->regfails += (retryvar-1); \
+ if (retryvar > retry_limit) \
+ DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
+ __FUNCTION__, __LINE__)); \
+ } \
+} while (0)
+
+#define BUS_WAKE(bus) \
+ do { \
+ bus->idlecount = 0; \
+ if ((bus)->sleeping) \
+ dhdsdio_bussleep((bus), FALSE); \
+ } while (0);
+
+/*
+ * pktavail interrupts from dongle to host can be managed in 3 different ways
+ * whenever there is a packet available in dongle to transmit to host.
+ *
+ * Mode 0: Dongle writes the software host mailbox and host is interrupted.
+ * Mode 1: (sdiod core rev >= 4)
+ * Device sets a new bit in the intstatus whenever there is a packet
+ * available in fifo. Host can't clear this specific status bit until all the
+ * packets are read from the FIFO. No need to ack dongle intstatus.
+ * Mode 2: (sdiod core rev >= 4)
+ * Device sets a bit in the intstatus, and host acks this by writing
+ * one to this bit. Dongle won't generate anymore packet interrupts
+ * until host reads all the packets from the dongle and reads a zero to
+ * figure that there are no more packets. No need to disable host ints.
+ * Need to ack the intstatus.
+ */
+
+#define SDIO_DEVICE_HMB_RXINT 0 /* default old way */
+#define SDIO_DEVICE_RXDATAINT_MODE_0 1 /* from sdiod rev 4 */
+#define SDIO_DEVICE_RXDATAINT_MODE_1 2 /* from sdiod rev 4 */
+
+
+#define FRAME_AVAIL_MASK(bus) \
+ ((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL)
+
+#define DHD_BUS SDIO_BUS
+
+#define PKT_AVAILABLE(bus, intstatus) ((intstatus) & (FRAME_AVAIL_MASK(bus)))
+
+#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
+
+#define GSPI_PR55150_BAILOUT
+
+#ifdef SDTEST
+static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
+static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count);
+#endif
+
+#ifdef DHD_DEBUG
+static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size);
+static int dhd_serialconsole(dhd_bus_t *bus, bool get, bool enable, int *bcmerror);
+#endif /* DHD_DEBUG */
+
+static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap);
+static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
+
+static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
+static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
+static void dhdsdio_disconnect(void *ptr);
+static bool dhdsdio_chipmatch(uint16 chipid);
+static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
+ void * regsva, uint16 devid);
+static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
+static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
+static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation,
+ bool reset_flag);
+
+static void dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size);
+static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
+ uint8 *buf, uint nbytes,
+ void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
+static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
+ uint8 *buf, uint nbytes,
+ void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry);
+static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt);
+static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
+ int prev_chain_total_len, bool last_chained_pkt,
+ int *pad_pkt_len, void **new_pkt);
+static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt);
+
+static int dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh);
+static int _dhdsdio_download_firmware(dhd_bus_t *bus);
+
+static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path);
+static int dhdsdio_download_nvram(dhd_bus_t *bus);
+#ifdef BCMEMBEDIMAGE
+static int dhdsdio_download_code_array(dhd_bus_t *bus);
+#endif
+static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep);
+static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok);
+static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus);
+
+#ifdef WLMEDIA_HTSF
+#include <htsf.h>
+extern uint32 dhd_get_htsf(void *dhd, int ifidx);
+#endif /* WLMEDIA_HTSF */
+
+static void
+dhdsdio_tune_fifoparam(struct dhd_bus *bus)
+{
+ int err;
+ uint8 devctl, wm, mes;
+
+ if (bus->sih->buscorerev >= 15) {
+ /* See .ppt in PR for these recommended values */
+ if (bus->blocksize == 512) {
+ wm = OVERFLOW_BLKSZ512_WM;
+ mes = OVERFLOW_BLKSZ512_MES;
+ } else {
+ mes = bus->blocksize/4;
+ wm = bus->blocksize/4;
+ }
+
+ watermark = wm;
+ mesbusyctrl = mes;
+ } else {
+ DHD_INFO(("skip fifotune: SdioRev(%d) is lower than minimal requested ver\n",
+ bus->sih->buscorerev));
+ return;
+ }
+
+ /* Update watermark */
+ if (wm > 0) {
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, wm, &err);
+
+ devctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
+ }
+
+ /* Update MES */
+ if (mes > 0) {
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
+ (mes | SBSDIO_MESBUSYCTRL_ENAB), &err);
+ }
+
+ DHD_INFO(("Apply overflow WAR: 0x%02x 0x%02x 0x%02x\n",
+ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err),
+ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, &err),
+ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, &err)));
+}
+
+static void
+dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size)
+{
+ int32 min_size = DONGLE_MIN_RAMSIZE;
+ /* Restrict the ramsize to user specified limit */
+ DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
+ dhd_dongle_ramsize, min_size));
+ if ((dhd_dongle_ramsize > min_size) &&
+ (dhd_dongle_ramsize < (int32)bus->orig_ramsize))
+ bus->ramsize = dhd_dongle_ramsize;
+}
+
+static int
+dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address)
+{
+ int err = 0;
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+ (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
+ if (!err)
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
+ (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
+ if (!err)
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
+ (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
+ return err;
+}
+
+
+#ifdef USE_OOB_GPIO1
+static int
+dhdsdio_oobwakeup_init(dhd_bus_t *bus)
+{
+ uint32 val, addr, data;
+
+ bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP);
+
+ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
+ data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
+
+ /* Set device for gpio1 wakeup */
+ bcmsdh_reg_write(bus->sdh, addr, 4, 2);
+ val = bcmsdh_reg_read(bus->sdh, data, 4);
+ val |= CC_CHIPCTRL2_GPIO1_WAKEUP;
+ bcmsdh_reg_write(bus->sdh, data, 4, val);
+
+ bus->_oobwakeup = TRUE;
+
+ return 0;
+}
+#endif /* USE_OOB_GPIO1 */
+
+/*
+ * Query if FW is in SR mode
+ */
+static bool
+dhdsdio_sr_cap(dhd_bus_t *bus)
+{
+ bool cap = FALSE;
+ uint32 core_capext, addr, data;
+
+
+ if (bus->sih->chip == BCM43430_CHIP_ID) {
+ /* check if fw initialized sr engine */
+ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, sr_control1);
+ if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0)
+ cap = TRUE;
+
+ return cap;
+ }
+
+ if (bus->sih->chip == BCM4324_CHIP_ID) {
+ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
+ data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
+ bcmsdh_reg_write(bus->sdh, addr, 4, 3);
+ core_capext = bcmsdh_reg_read(bus->sdh, data, 4);
+ } else if (bus->sih->chip == BCM4330_CHIP_ID) {
+ core_capext = FALSE;
+ } else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
+ (bus->sih->chip == BCM4339_CHIP_ID) ||
+ (bus->sih->chip == BCM43349_CHIP_ID) ||
+ (bus->sih->chip == BCM4345_CHIP_ID) ||
+ (bus->sih->chip == BCM4354_CHIP_ID) ||
+ (bus->sih->chip == BCM4356_CHIP_ID) ||
+ (bus->sih->chip == BCM4350_CHIP_ID)) {
+ core_capext = TRUE;
+ } else {
+ core_capext = bcmsdh_reg_read(bus->sdh, CORE_CAPEXT_ADDR, 4);
+ core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
+ }
+ if (!(core_capext))
+ return FALSE;
+
+ if (bus->sih->chip == BCM4324_CHIP_ID) {
+ /* FIX: Should change to query SR control register instead */
+ cap = TRUE;
+ } else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
+ (bus->sih->chip == BCM4339_CHIP_ID) ||
+ (bus->sih->chip == BCM43349_CHIP_ID) ||
+ (bus->sih->chip == BCM4345_CHIP_ID) ||
+ (bus->sih->chip == BCM4354_CHIP_ID) ||
+ (bus->sih->chip == BCM4356_CHIP_ID) ||
+ (bus->sih->chip == BCM4350_CHIP_ID)) {
+ uint32 enabval = 0;
+ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
+ data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
+ bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3);
+ enabval = bcmsdh_reg_read(bus->sdh, data, 4);
+
+ if ((bus->sih->chip == BCM4350_CHIP_ID) ||
+ (bus->sih->chip == BCM4345_CHIP_ID) ||
+ (bus->sih->chip == BCM4356_CHIP_ID) ||
+ (bus->sih->chip == BCM4354_CHIP_ID))
+ enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE;
+
+ if (enabval)
+ cap = TRUE;
+ } else {
+ data = bcmsdh_reg_read(bus->sdh,
+ SI_ENUM_BASE + OFFSETOF(chipcregs_t, retention_ctl), 4);
+ if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0)
+ cap = TRUE;
+ }
+
+ return cap;
+}
+
+static int
+dhdsdio_srwar_init(dhd_bus_t *bus)
+{
+ bcmsdh_gpio_init(bus->sdh);
+
+#ifdef USE_OOB_GPIO1
+ dhdsdio_oobwakeup_init(bus);
+#endif
+
+
+ return 0;
+}
+
+static int
+dhdsdio_sr_init(dhd_bus_t *bus)
+{
+ uint8 val;
+ int err = 0;
+
+ if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2))
+ dhdsdio_srwar_init(bus);
+
+ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
+ val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
+ 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
+ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
+
+#ifdef USE_CMD14
+ /* Add CMD14 Support */
+ dhdsdio_devcap_set(bus,
+ (SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT));
+#endif /* USE_CMD14 */
+
+ dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC);
+
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
+
+ bus->_slpauto = dhd_slpauto ? TRUE : FALSE;
+
+ bus->_srenab = TRUE;
+
+ return 0;
+}
+
+/*
+ * FIX: Be sure KSO bit is enabled
+ * Currently, it's defaulting to 0 which should be 1.
+ */
+static int
+dhdsdio_clk_kso_init(dhd_bus_t *bus)
+{
+ uint8 val;
+ int err = 0;
+
+ /* set flag */
+ bus->kso = TRUE;
+
+ /*
+ * Enable KeepSdioOn (KSO) bit for normal operation
+ * Default is 0 (4334A0) so set it. Fixed in B0.
+ */
+ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, NULL);
+ if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
+ val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, val, &err);
+ if (err)
+ DHD_ERROR(("%s: SBSDIO_FUNC1_SLEEPCSR err: 0x%x\n", __FUNCTION__, err));
+ }
+
+ return 0;
+}
+
+#define KSO_DBG(x)
+#define KSO_WAIT_US 50
+#define KSO_WAIT_MS 1
+#define KSO_SLEEP_RETRY_COUNT 20
+#define ERROR_BCME_NODEVICE_MAX 1
+
+#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
+static int
+dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
+{
+ uint8 wr_val = 0, rd_val, cmp_val, bmask;
+ int err = 0;
+ int try_cnt = 0;
+
+ KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
+
+ wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
+
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
+
+ if (on) {
+ cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
+ bmask = cmp_val;
+
+ OSL_SLEEP(3);
+ } else {
+ /* Put device to sleep, turn off KSO */
+ cmp_val = 0;
+ bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
+ }
+
+ do {
+ rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
+ if (((rd_val & bmask) == cmp_val) && !err)
+ break;
+
+ KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err));
+
+ if (((try_cnt + 1) % KSO_SLEEP_RETRY_COUNT) == 0) {
+ OSL_SLEEP(KSO_WAIT_MS);
+ } else
+ OSL_DELAY(KSO_WAIT_US);
+
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
+ } while (try_cnt++ < MAX_KSO_ATTEMPTS);
+
+
+ if (try_cnt > 2)
+ KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n",
+ __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
+
+ if (try_cnt > MAX_KSO_ATTEMPTS) {
+ DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n",
+ __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
+ }
+ return err;
+}
+
+static int
+dhdsdio_clk_kso_iovar(dhd_bus_t *bus, bool on)
+{
+ int err = 0;
+
+ if (on == FALSE) {
+
+ BUS_WAKE(bus);
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ DHD_ERROR(("%s: KSO disable clk: 0x%x\n", __FUNCTION__,
+ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err)));
+ dhdsdio_clk_kso_enab(bus, FALSE);
+ } else {
+ DHD_ERROR(("%s: KSO enable\n", __FUNCTION__));
+
+ /* Make sure we have SD bus access */
+ if (bus->clkstate == CLK_NONE) {
+ DHD_ERROR(("%s: Request SD clk\n", __FUNCTION__));
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+ }
+
+ dhdsdio_clk_kso_enab(bus, TRUE);
+
+ DHD_ERROR(("%s: sleepcsr: 0x%x\n", __FUNCTION__,
+ dhdsdio_sleepcsr_get(bus)));
+ }
+
+ bus->kso = on;
+ BCM_REFERENCE(err);
+
+ return 0;
+}
+
+static uint8
+dhdsdio_sleepcsr_get(dhd_bus_t *bus)
+{
+ int err = 0;
+ uint8 val = 0;
+
+ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
+ if (err)
+ DHD_TRACE(("Failed to read SLEEPCSR: %d\n", err));
+
+ return val;
+}
+
+uint8
+dhdsdio_devcap_get(dhd_bus_t *bus)
+{
+ return bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL);
+}
+
+static int
+dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap)
+{
+ int err = 0;
+
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, cap, &err);
+ if (err)
+ DHD_ERROR(("%s: devcap set err: 0x%x\n", __FUNCTION__, err));
+
+ return 0;
+}
+
+static int
+dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on)
+{
+ int err = 0, retry;
+ uint8 val;
+
+ retry = 0;
+ if (on == TRUE) {
+ /* Enter Sleep */
+
+ /* Be sure we request clk before going to sleep
+ * so we can wake-up with clk request already set
+ * else device can go back to sleep immediately
+ */
+ if (!SLPAUTO_ENAB(bus))
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ else {
+ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if ((val & SBSDIO_CSR_MASK) == 0) {
+ DHD_ERROR(("%s: No clock before enter sleep:0x%x\n",
+ __FUNCTION__, val));
+
+ /* Reset clock request */
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ SBSDIO_ALP_AVAIL_REQ, &err);
+ DHD_ERROR(("%s: clock before sleep:0x%x\n", __FUNCTION__,
+ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err)));
+ }
+ }
+
+ DHD_TRACE(("%s: clk before sleep: 0x%x\n", __FUNCTION__,
+ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err)));
+#ifdef USE_CMD14
+ err = bcmsdh_sleep(bus->sdh, TRUE);
+#else
+ err = dhdsdio_clk_kso_enab(bus, FALSE);
+ if (OOB_WAKEUP_ENAB(bus))
+ {
+ err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, FALSE); /* GPIO_1 is off */
+ }
+#endif /* USE_CMD14 */
+ } else {
+ /* Exit Sleep */
+ /* Make sure we have SD bus access */
+ if (bus->clkstate == CLK_NONE) {
+ DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__));
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+ }
+
+ if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) {
+ SPINWAIT_SLEEP(sdioh_spinwait_sleep,
+ (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) != TRUE),
+ GPIO_DEV_SRSTATE_TIMEOUT);
+
+ if (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) == FALSE) {
+ DHD_ERROR(("ERROR: GPIO_DEV_SRSTATE still low!\n"));
+ }
+ }
+#ifdef USE_CMD14
+ err = bcmsdh_sleep(bus->sdh, FALSE);
+ if (SLPAUTO_ENAB(bus) && (err != 0)) {
+ OSL_DELAY(10000);
+ DHD_TRACE(("%s: Resync device sleep\n", __FUNCTION__));
+
+ /* Toggle sleep to resync with host and device */
+ err = bcmsdh_sleep(bus->sdh, TRUE);
+ OSL_DELAY(10000);
+ err = bcmsdh_sleep(bus->sdh, FALSE);
+
+ if (err) {
+ OSL_DELAY(10000);
+ DHD_ERROR(("%s: CMD14 exit failed again!\n", __FUNCTION__));
+
+ /* Toggle sleep to resync with host and device */
+ err = bcmsdh_sleep(bus->sdh, TRUE);
+ OSL_DELAY(10000);
+ err = bcmsdh_sleep(bus->sdh, FALSE);
+ if (err) {
+ DHD_ERROR(("%s: CMD14 exit failed twice!\n", __FUNCTION__));
+ DHD_ERROR(("%s: FATAL: Device non-response!\n",
+ __FUNCTION__));
+ err = 0;
+ }
+ }
+ }
+#else
+ if (OOB_WAKEUP_ENAB(bus))
+ {
+ err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, TRUE); /* GPIO_1 is on */
+ }
+ do {
+ err = dhdsdio_clk_kso_enab(bus, TRUE);
+ if (err)
+ OSL_SLEEP(10);
+ } while ((err != 0) && (++retry < 3));
+
+ if (err != 0) {
+ DHD_ERROR(("ERROR: kso set failed retry: %d\n", retry));
+ err = 0; /* continue anyway */
+ }
+#endif /* !USE_CMD14 */
+
+ if (err == 0) {
+ uint8 csr;
+
+ /* Wait for device ready during transition to wake-up */
+ SPINWAIT_SLEEP(sdioh_spinwait_sleep,
+ (((csr = dhdsdio_sleepcsr_get(bus)) &
+ SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK) !=
+ (SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), (20000));
+
+ DHD_TRACE(("%s: ExitSleep sleepcsr: 0x%x\n", __FUNCTION__, csr));
+
+ if (!(csr & SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)) {
+ DHD_ERROR(("%s:ERROR: ExitSleep device NOT Ready! 0x%x\n",
+ __FUNCTION__, csr));
+ err = BCME_NODEVICE;
+ }
+
+ SPINWAIT_SLEEP(sdioh_spinwait_sleep,
+ (((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) !=
+ (SBSDIO_HT_AVAIL)), (10000));
+
+ DHD_TRACE(("%s: SBSDIO_FUNC1_CHIPCLKCSR : 0x%x\n", __FUNCTION__, csr));
+ if (!err && ((csr & SBSDIO_HT_AVAIL) != SBSDIO_HT_AVAIL)) {
+ DHD_ERROR(("%s:ERROR: device NOT Ready! 0x%x\n",
+ __FUNCTION__, csr));
+ err = BCME_NODEVICE;
+ }
+ }
+ }
+
+ /* Update if successful */
+ if (err == 0)
+ bus->kso = on ? FALSE : TRUE;
+ else {
+ DHD_ERROR(("%s: Sleep request failed: kso:%d on:%d err:%d\n",
+ __FUNCTION__, bus->kso, on, err));
+ if (!on && retry > 2)
+ bus->kso = FALSE;
+ }
+
+ return err;
+}
+
+/* Turn backplane clock on or off */
+static int
+dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
+{
+#define HT_AVAIL_ERROR_MAX 10
+ static int ht_avail_error = 0;
+ int err;
+ uint8 clkctl, clkreq, devctl;
+ bcmsdh_info_t *sdh;
+ uint32 delay = PMU_MAX_TRANSITION_DLY;
+
+#ifdef MURATA_WORKAROUND_FOR_HTAVAIL
+ int try_count, try_err;
+#endif /* MURATA_WORKAROUND_FOR_HTAVAIL */
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ clkctl = 0;
+ sdh = bus->sdh;
+
+
+ if (!KSO_ENAB(bus))
+ return BCME_OK;
+
+ if (SLPAUTO_ENAB(bus)) {
+ bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
+ return BCME_OK;
+ }
+
+ if (on) {
+ /* Request HT Avail */
+ clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
+
+
+
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
+ if (err) {
+ ht_avail_error++;
+ if (ht_avail_error < HT_AVAIL_ERROR_MAX) {
+ DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ else if (ht_avail_error == HT_AVAIL_ERROR_MAX) {
+ dhd_os_send_hang_message(bus->dhd);
+ }
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
+ return BCME_ERROR;
+ } else {
+ ht_avail_error = 0;
+ }
+
+
+ /* Check current status */
+ clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (err) {
+ DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+
+#if !defined(OOB_INTR_ONLY) || defined(OOB_PARAM)
+ /* Go to pending and await interrupt if appropriate */
+ if (1 &&
+#if defined(OOB_PARAM)
+ bus->dhd->oob_disable &&
+#endif /* OOB_PARAM */
+ !SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
+ /* Allow only clock-available interrupt */
+ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+ if (err) {
+ DHD_ERROR(("%s: Devctl access error setting CA: %d\n",
+ __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+
+ devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
+ DHD_INFO(("CLKCTL: set PENDING\n"));
+ bus->clkstate = CLK_PENDING;
+ return BCME_OK;
+ } else
+#endif /* !defined(OOB_INTR_ONLY) || defined(OOB_PARAM) */
+ {
+ if (bus->clkstate == CLK_PENDING) {
+ /* Cancel CA-only interrupt filter */
+ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
+ }
+ }
+
+ /* Give the 43362 chip a little bit extra time for HT Avail */
+ if (bus->sih->chip == BCM43362_CHIP_ID) {
+ delay += PMU_TRANSITION_DLY_EXTRA;
+ }
+
+#ifdef MURATA_WORKAROUND_FOR_HTAVAIL
+ /* loop 20 times to test condition */
+ for (try_count = 0; try_count < 20; try_count++) {
+ try_err = 0;
+#endif /* MURATA_WORKAROUND_FOR_HTAVAIL */
+ /* Otherwise, wait here (polling) for HT Avail */
+ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
+ SPINWAIT_SLEEP(sdioh_spinwait_sleep,
+ ((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err)),
+ !SBSDIO_CLKAV(clkctl, bus->alp_only)),
+ delay);
+ }
+ if (err) {
+ DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
+#ifdef MURATA_WORKAROUND_FOR_HTAVAIL
+ try_err = 1;
+#else
+ return BCME_ERROR;
+#endif /* MURATA_WORKAROUND_FOR_HTAVAIL */
+ }
+ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
+ DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
+ __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
+#ifdef MURATA_WORKAROUND_FOR_HTAVAIL
+ try_err = 1;
+#else
+ return BCME_ERROR;
+#endif /* MURATA_WORKAROUND_FOR_HTAVAIL */
+ }
+
+#ifdef MURATA_WORKAROUND_FOR_HTAVAIL
+ if (try_err == 0)
+ break;
+ } /* for (try_count = 0; try_count < 20; try_count++) */
+ if (try_err == 1) {
+ DHD_ERROR(("%s: HT Avail request error: retried %d times. UNRECOVERABLE!\n", __FUNCTION__, try_count));
+ return BCME_ERROR;
+ }
+ if (try_count > 0)
+ DHD_ERROR(("%s: HT Avail request NO ERROR: retried %d times.\n", __FUNCTION__, try_count));
+#endif /* MURATA_WORKAROUND_FOR_HTAVAIL */
+
+ /* Mark clock available */
+ bus->clkstate = CLK_AVAIL;
+ DHD_INFO(("CLKCTL: turned ON\n"));
+
+#if defined(DHD_DEBUG)
+ if (bus->alp_only == TRUE) {
+#if !defined(BCMLXSDMMC)
+ if (!SBSDIO_ALPONLY(clkctl)) {
+ DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__));
+ }
+#endif /* !defined(BCMLXSDMMC) */
+ } else {
+ if (SBSDIO_ALPONLY(clkctl)) {
+ DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__));
+ }
+ }
+#endif /* defined (DHD_DEBUG) */
+
+ bus->activity = TRUE;
+#ifdef DHD_USE_IDLECOUNT
+ bus->idlecount = 0;
+#endif /* DHD_USE_IDLECOUNT */
+ } else {
+ clkreq = 0;
+
+ if (bus->clkstate == CLK_PENDING) {
+ /* Cancel CA-only interrupt filter */
+ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
+ }
+
+ bus->clkstate = CLK_SDONLY;
+ if (!SR_ENAB(bus)) {
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
+ DHD_INFO(("CLKCTL: turned OFF\n"));
+ if (err) {
+ DHD_ERROR(("%s: Failed access turning clock off: %d\n",
+ __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+ }
+ }
+ return BCME_OK;
+}
+
+/* Change idle/active SD state */
+static int
+dhdsdio_sdclk(dhd_bus_t *bus, bool on)
+{
+ int err;
+ int32 iovalue;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (on) {
+ if (bus->idleclock == DHD_IDLE_STOP) {
+ /* Turn on clock and restore mode */
+ iovalue = 1;
+ err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
+ &iovalue, sizeof(iovalue), TRUE);
+ if (err) {
+ DHD_ERROR(("%s: error enabling sd_clock: %d\n",
+ __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+
+ iovalue = bus->sd_mode;
+ err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
+ &iovalue, sizeof(iovalue), TRUE);
+ if (err) {
+ DHD_ERROR(("%s: error changing sd_mode: %d\n",
+ __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+ } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
+ /* Restore clock speed */
+ iovalue = bus->sd_divisor;
+ err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
+ &iovalue, sizeof(iovalue), TRUE);
+ if (err) {
+ DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
+ __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+ }
+ bus->clkstate = CLK_SDONLY;
+ } else {
+ /* Stop or slow the SD clock itself */
+ if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
+ DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
+ __FUNCTION__, bus->sd_divisor, bus->sd_mode));
+ return BCME_ERROR;
+ }
+ if (bus->idleclock == DHD_IDLE_STOP) {
+ if (sd1idle) {
+ /* Change to SD1 mode and turn off clock */
+ iovalue = 1;
+ err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
+ &iovalue, sizeof(iovalue), TRUE);
+ if (err) {
+ DHD_ERROR(("%s: error changing sd_clock: %d\n",
+ __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+ }
+
+ iovalue = 0;
+ err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
+ &iovalue, sizeof(iovalue), TRUE);
+ if (err) {
+ DHD_ERROR(("%s: error disabling sd_clock: %d\n",
+ __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+ } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
+ /* Set divisor to idle value */
+ iovalue = bus->idleclock;
+ err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
+ &iovalue, sizeof(iovalue), TRUE);
+ if (err) {
+ DHD_ERROR(("%s: error changing sd_divisor: %d\n",
+ __FUNCTION__, err));
+ return BCME_ERROR;
+ }
+ }
+ bus->clkstate = CLK_NONE;
+ }
+
+ return BCME_OK;
+}
+
+/* Transition SD and backplane clock readiness */
+static int
+dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
+{
+ int ret = BCME_OK;
+#ifdef DHD_DEBUG
+ uint oldstate = bus->clkstate;
+#endif /* DHD_DEBUG */
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* Early exit if we're already there */
+ if (bus->clkstate == target) {
+ if (target == CLK_AVAIL) {
+ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ bus->activity = TRUE;
+#ifdef DHD_USE_IDLECOUNT
+ bus->idlecount = 0;
+#endif /* DHD_USE_IDLECOUNT */
+ }
+ return ret;
+ }
+
+ switch (target) {
+ case CLK_AVAIL:
+ /* Make sure SD clock is available */
+ if (bus->clkstate == CLK_NONE)
+ dhdsdio_sdclk(bus, TRUE);
+ /* Now request HT Avail on the backplane */
+ ret = dhdsdio_htclk(bus, TRUE, pendok);
+ if (ret == BCME_OK) {
+ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ bus->activity = TRUE;
+#ifdef DHD_USE_IDLECOUNT
+ bus->idlecount = 0;
+#endif /* DHD_USE_IDLECOUNT */
+ }
+ break;
+
+ case CLK_SDONLY:
+ /* Remove HT request, or bring up SD clock */
+ if (bus->clkstate == CLK_NONE)
+ ret = dhdsdio_sdclk(bus, TRUE);
+ else if (bus->clkstate == CLK_AVAIL)
+ ret = dhdsdio_htclk(bus, FALSE, FALSE);
+ else
+ DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
+ bus->clkstate, target));
+ if (ret == BCME_OK) {
+ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ }
+ break;
+
+ case CLK_NONE:
+ /* Make sure to remove HT request */
+ if (bus->clkstate == CLK_AVAIL)
+ ret = dhdsdio_htclk(bus, FALSE, FALSE);
+ /* Now remove the SD clock */
+ ret = dhdsdio_sdclk(bus, FALSE);
+#ifdef DHD_DEBUG
+ if (dhd_console_ms == 0)
+#endif /* DHD_DEBUG */
+ if (bus->poll == 0)
+ dhd_os_wd_timer(bus->dhd, 0);
+ break;
+ }
+#ifdef DHD_DEBUG
+ DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
+#endif /* DHD_DEBUG */
+
+ return ret;
+}
+
+static int
+dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
+{
+ int err = 0;
+ bcmsdh_info_t *sdh = bus->sdh;
+ sdpcmd_regs_t *regs = bus->regs;
+ uint retries = 0;
+
+ DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
+ (sleep ? "SLEEP" : "WAKE"),
+ (bus->sleeping ? "SLEEP" : "WAKE")));
+
+ if (bus->dhd->hang_was_sent)
+ return BCME_ERROR;
+
+ /* Done if we're already in the requested state */
+ if (sleep == bus->sleeping)
+ return BCME_OK;
+
+ /* Going to sleep: set the alarm and turn off the lights... */
+ if (sleep) {
+ /* Don't sleep if something is pending */
+ if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
+ return BCME_BUSY;
+
+
+ if (!SLPAUTO_ENAB(bus)) {
+ /* Disable SDIO interrupts (no longer interested) */
+ bcmsdh_intr_disable(bus->sdh);
+
+ /* Make sure the controller has the bus up */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ /* Tell device to start using OOB wakeup */
+ W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
+ if (retries > retry_limit)
+ DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
+
+ /* Turn off our contribution to the HT clock request */
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
+
+ /* Isolate the bus */
+ if (bus->sih->chip != BCM4329_CHIP_ID &&
+ bus->sih->chip != BCM4319_CHIP_ID) {
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+ SBSDIO_DEVCTL_PADS_ISO, NULL);
+ }
+ } else {
+ /* Leave interrupts enabled since device can exit sleep and
+ * interrupt host
+ */
+ err = dhdsdio_clk_devsleep_iovar(bus, TRUE /* sleep */);
+ }
+
+ /* Change state */
+ bus->sleeping = TRUE;
+#if defined(SUPPORT_P2P_GO_PS)
+ wake_up(&bus->bus_sleep);
+#endif /* LINUX && (SUPPORT_P2P_GO_PS || !OEM_ANDROID) */
+ } else {
+ /* Waking up: bus power up is ok, set local state */
+
+ if (!SLPAUTO_ENAB(bus)) {
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, &err);
+
+ /* Force pad isolation off if possible (in case power never toggled) */
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
+
+
+ /* Make sure the controller has the bus up */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ /* Send misc interrupt to indicate OOB not needed */
+ W_SDREG(0, &regs->tosbmailboxdata, retries);
+ if (retries <= retry_limit)
+ W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
+
+ if (retries > retry_limit)
+ DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
+
+ /* Make sure we have SD bus access */
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+
+ /* Enable interrupts again */
+ if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
+ bus->intdis = FALSE;
+ bcmsdh_intr_enable(bus->sdh);
+ }
+ } else {
+ err = dhdsdio_clk_devsleep_iovar(bus, FALSE /* wake */);
+ }
+
+ if (err == 0) {
+ /* Change state */
+ bus->sleeping = FALSE;
+ }
+ }
+
+ return err;
+}
+
+
+#if defined(OOB_INTR_ONLY)
+void
+dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
+{
+#if defined(HW_OOB)
+ bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
+#else
+ sdpcmd_regs_t *regs = bus->regs;
+ uint retries = 0;
+
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ if (enable == TRUE) {
+
+ /* Tell device to start using OOB wakeup */
+ W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
+ if (retries > retry_limit)
+ DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
+
+ } else {
+ /* Send misc interrupt to indicate OOB not needed */
+ W_SDREG(0, &regs->tosbmailboxdata, retries);
+ if (retries <= retry_limit)
+ W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
+ }
+
+ /* Turn off our contribution to the HT clock request */
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+#endif /* !defined(HW_OOB) */
+}
+#endif
+
+int
+dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
+{
+ int ret = BCME_ERROR;
+ osl_t *osh;
+ uint datalen, prec;
+#if defined(DHD_TX_DUMP) || defined(DHD_8021X_DUMP)
+ uint8 *dump_data;
+ uint16 protocol;
+#endif /* DHD_TX_DUMP || DHD_8021X_DUMP */
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ osh = bus->dhd->osh;
+ datalen = PKTLEN(osh, pkt);
+
+#ifdef SDTEST
+ /* Push the test header if doing loopback */
+ if (bus->ext_loop) {
+ uint8* data;
+ PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN);
+ data = PKTDATA(osh, pkt);
+ *data++ = SDPCM_TEST_ECHOREQ;
+ *data++ = (uint8)bus->loopid++;
+ *data++ = (datalen >> 0);
+ *data++ = (datalen >> 8);
+ datalen += SDPCM_TEST_HDRLEN;
+ }
+#else /* SDTEST */
+ BCM_REFERENCE(datalen);
+#endif /* SDTEST */
+
+#if defined(DHD_TX_DUMP) || defined(DHD_8021X_DUMP)
+ dump_data = PKTDATA(osh, pkt);
+ dump_data += 4; /* skip 4 bytes header */
+ protocol = (dump_data[12] << 8) | dump_data[13];
+
+ if (protocol == ETHER_TYPE_802_1X) {
+ DHD_ERROR(("ETHER_TYPE_802_1X [TX]: ver %d, type %d, replay %d\n",
+ dump_data[14], dump_data[15], dump_data[30]));
+ }
+#endif /* DHD_TX_DUMP || DHD_8021X_DUMP */
+
+#if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP)
+ {
+ int i;
+ DHD_ERROR(("TX DUMP\n"));
+
+ for (i = 0; i < (datalen - 4); i++) {
+ DHD_ERROR(("%02X ", dump_data[i]));
+ if ((i & 15) == 15)
+ printk("\n");
+ }
+ DHD_ERROR(("\n"));
+ }
+#endif /* DHD_TX_DUMP && DHD_TX_FULL_DUMP */
+
+ prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
+
+ /* Check for existing queue, current flow-control, pending event, or pending clock */
+ if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
+ (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
+ (bus->clkstate != CLK_AVAIL)) {
+ bool deq_ret;
+ int pkq_len;
+
+ DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, pktq_len(&bus->txq)));
+ bus->fcqueued++;
+
+ /* Priority based enq */
+ dhd_os_sdlock_txq(bus->dhd);
+ deq_ret = dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec);
+ dhd_os_sdunlock_txq(bus->dhd);
+
+ if (!deq_ret) {
+#ifdef PROP_TXSTATUS
+ if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) == 0)
+#endif /* PROP_TXSTATUS */
+ {
+#ifdef DHDTCPACK_SUPPRESS
+ if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
+ DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using\n",
+ __FUNCTION__, __LINE__));
+ dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
+ }
+#endif /* DHDTCPACK_SUPPRESS */
+ dhd_txcomplete(bus->dhd, pkt, FALSE);
+ PKTFREE(osh, pkt, TRUE);
+ }
+ ret = BCME_NORESOURCE;
+ } else
+ ret = BCME_OK;
+
+ dhd_os_sdlock_txq(bus->dhd);
+ pkq_len = pktq_len(&bus->txq);
+ dhd_os_sdunlock_txq(bus->dhd);
+ if (pkq_len >= FCHI) {
+ bool wlfc_enabled = FALSE;
+#ifdef PROP_TXSTATUS
+ wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) !=
+ WLFC_UNSUPPORTED);
+#endif
+ if (!wlfc_enabled && dhd_doflow) {
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
+ }
+ }
+
+#ifdef DHD_DEBUG
+ dhd_os_sdlock_txq(bus->dhd);
+ if (pktq_plen(&bus->txq, prec) > qcount[prec])
+ qcount[prec] = pktq_plen(&bus->txq, prec);
+ dhd_os_sdunlock_txq(bus->dhd);
+#endif
+
+ /* Schedule DPC if needed to send queued packet(s) */
+ if (dhd_deferred_tx && !bus->dpc_sched) {
+ bus->dpc_sched = TRUE;
+ dhd_sched_dpc(bus->dhd);
+ }
+ } else {
+ int chan = SDPCM_DATA_CHANNEL;
+
+#ifdef SDTEST
+ chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL);
+#endif
+ /* Lock: we're about to use shared data/code (and SDIO) */
+ dhd_os_sdlock(bus->dhd);
+
+ /* Otherwise, send it now */
+ BUS_WAKE(bus);
+ /* Make sure back plane ht clk is on, no pending allowed */
+ dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
+
+ ret = dhdsdio_txpkt(bus, chan, &pkt, 1, TRUE);
+
+ if (ret != BCME_OK)
+ bus->dhd->tx_errors++;
+ else
+ bus->dhd->dstats.tx_bytes += datalen;
+
+ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ bus->activity = FALSE;
+ dhdsdio_clkctl(bus, CLK_NONE, TRUE);
+ }
+
+ dhd_os_sdunlock(bus->dhd);
+ }
+
+ return ret;
+}
+
+/* align packet data pointer and packet length to n-byte boundary, process packet headers,
+ * a new packet may be allocated if there is not enough head and/or tail from for padding.
+ * the caller is responsible for updating the glom size in the head packet (when glom is
+ * used)
+ *
+ * pad_pkt_len: returns the length of extra padding needed from the padding packet, this parameter
+ * is taken in tx glom mode only
+ *
+ * new_pkt: out, pointer of the new packet allocated due to insufficient head room for alignment
+ * padding, NULL if not needed, the caller is responsible for freeing the new packet
+ *
+ * return: positive value - length of the packet, including head and tail padding
+ * negative value - errors
+ */
+static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
+ int prev_chain_total_len, bool last_chained_pkt,
+ int *pad_pkt_len, void **new_pkt)
+{
+ osl_t *osh;
+ uint8 *frame;
+ int pkt_len;
+ int modulo;
+ int head_padding;
+ int tail_padding = 0;
+ uint32 swheader;
+ uint32 swhdr_offset;
+ bool alloc_new_pkt = FALSE;
+ uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
+
+ *new_pkt = NULL;
+ osh = bus->dhd->osh;
+
+#ifdef DHDTCPACK_SUPPRESS
+ if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
+ DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
+ __FUNCTION__, __LINE__));
+ dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
+ }
+#endif /* DHDTCPACK_SUPPRESS */
+
+ /* Add space for the SDPCM hardware/software headers */
+ PKTPUSH(osh, pkt, sdpcm_hdrlen);
+ ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2));
+
+ frame = (uint8*)PKTDATA(osh, pkt);
+ pkt_len = (uint16)PKTLEN(osh, pkt);
+
+#ifdef WLMEDIA_HTSF
+ frame = (uint8*)PKTDATA(osh, pkt);
+ if (PKTLEN(osh, pkt) >= 100) {
+ htsf_ts = (htsfts_t*) (frame + HTSF_HOSTOFFSET + 12);
+ if (htsf_ts->magic == HTSFMAGIC) {
+ htsf_ts->c20 = get_cycles();
+ htsf_ts->t20 = dhd_get_htsf(bus->dhd->info, 0);
+ }
+ }
+#endif /* WLMEDIA_HTSF */
+#ifdef DHD_DEBUG
+ if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets))
+ tx_packets[PKTPRIO(pkt)]++;
+#endif /* DHD_DEBUG */
+
+ /* align the data pointer, allocate a new packet if there is not enough space (new
+ * packet data pointer will be aligned thus no padding will be needed)
+ */
+ head_padding = (ulong)frame % DHD_SDALIGN;
+ if (PKTHEADROOM(osh, pkt) < head_padding) {
+ head_padding = 0;
+ alloc_new_pkt = TRUE;
+ } else {
+ uint cur_chain_total_len;
+ int chain_tail_padding = 0;
+
+ /* All packets need to be aligned by DHD_SDALIGN */
+ modulo = (pkt_len + head_padding) % DHD_SDALIGN;
+ tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
+
+ /* Total pkt chain length needs to be aligned by block size,
+ * unless it is a single pkt chain with total length less than one block size,
+ * which we prefer sending by byte mode.
+ *
+ * Do the chain alignment here if
+ * 1. This is the last pkt of the chain of multiple pkts or a single pkt.
+ * 2-1. This chain is of multiple pkts, or
+ * 2-2. This is a single pkt whose size is longer than one block size.
+ */
+ cur_chain_total_len = prev_chain_total_len +
+ (head_padding + pkt_len + tail_padding);
+ if (last_chained_pkt && bus->blocksize != 0 &&
+ (cur_chain_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
+ modulo = cur_chain_total_len % bus->blocksize;
+ chain_tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
+ }
+
+#ifdef DHDENABLE_TAILPAD
+ if (PKTTAILROOM(osh, pkt) < tail_padding) {
+ /* We don't have tail room to align by DHD_SDALIGN */
+ alloc_new_pkt = TRUE;
+ bus->tx_tailpad_pktget++;
+ } else if (PKTTAILROOM(osh, pkt) < tail_padding + chain_tail_padding) {
+ /* We have tail room for tail_padding of this pkt itself, but not for
+ * total pkt chain alignment by block size.
+ * Use the padding packet to avoid memory copy if applicable,
+ * otherwise, just allocate a new pkt.
+ */
+ if (bus->pad_pkt) {
+ *pad_pkt_len = chain_tail_padding;
+ bus->tx_tailpad_chain++;
+ } else {
+ alloc_new_pkt = TRUE;
+ bus->tx_tailpad_pktget++;
+ }
+ } else
+ /* This last pkt's tailroom is sufficient to hold both tail_padding
+ * of the pkt itself and chain_tail_padding of total pkt chain
+ */
+#endif /* DHDENABLE_TAILPAD */
+ tail_padding += chain_tail_padding;
+ }
+
+ DHD_INFO(("%s sdhdr len + orig_pkt_len %d h_pad %d t_pad %d pad_pkt_len %d\n",
+ __FUNCTION__, pkt_len, head_padding, tail_padding, *pad_pkt_len));
+
+ if (alloc_new_pkt) {
+ void *tmp_pkt;
+ int newpkt_size;
+ int cur_total_len;
+
+ ASSERT(*pad_pkt_len == 0);
+
+ DHD_INFO(("%s allocating new packet for padding\n", __FUNCTION__));
+
+ /* head pointer is aligned now, no padding needed */
+ head_padding = 0;
+
+ /* update the tail padding as it depends on the head padding, since a new packet is
+ * allocated, the head padding is non longer needed and packet length is chagned
+ */
+
+ cur_total_len = prev_chain_total_len + pkt_len;
+ if (last_chained_pkt && bus->blocksize != 0 &&
+ (cur_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
+ modulo = cur_total_len % bus->blocksize;
+ tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
+ }
+ else {
+ modulo = pkt_len % DHD_SDALIGN;
+ tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
+ }
+
+ newpkt_size = PKTLEN(osh, pkt) + bus->blocksize + DHD_SDALIGN;
+ bus->dhd->tx_realloc++;
+ tmp_pkt = PKTGET(osh, newpkt_size, TRUE);
+ if (tmp_pkt == NULL) {
+ DHD_ERROR(("failed to alloc new %d byte packet\n", newpkt_size));
+ return BCME_NOMEM;
+ }
+ PKTALIGN(osh, tmp_pkt, PKTLEN(osh, pkt), DHD_SDALIGN);
+ bcopy(PKTDATA(osh, pkt), PKTDATA(osh, tmp_pkt), PKTLEN(osh, pkt));
+ *new_pkt = tmp_pkt;
+ pkt = tmp_pkt;
+ }
+
+ if (head_padding)
+ PKTPUSH(osh, pkt, head_padding);
+
+ frame = (uint8*)PKTDATA(osh, pkt);
+ bzero(frame, head_padding + sdpcm_hdrlen);
+ pkt_len = (uint16)PKTLEN(osh, pkt);
+
+ /* the header has the followming format
+ * 4-byte HW frame tag: length, ~length (for glom this is the total length)
+ *
+ * 8-byte HW extesion flags (glom mode only) as the following:
+ * 2-byte packet length, excluding HW tag and padding
+ * 2-byte frame channel and frame flags (e.g. next frame following)
+ * 2-byte header length
+ * 2-byte tail padding size
+ *
+ * 8-byte SW frame tags as the following
+ * 4-byte flags: host tx seq, channel, data offset
+ * 4-byte flags: TBD
+ */
+
+ swhdr_offset = SDPCM_FRAMETAG_LEN;
+
+ /* hardware frame tag:
+ *
+ * in tx-glom mode, dongle only checks the hardware frame tag in the first
+ * packet and sees it as the total lenght of the glom (including tail padding),
+ * for each packet in the glom, the packet length needs to be updated, (see
+ * below PKTSETLEN)
+ *
+ * in non tx-glom mode, PKTLEN still need to include tail padding as to be
+ * referred to in sdioh_request_buffer(). The tail length will be excluded in
+ * dhdsdio_txpkt_postprocess().
+ */
+ *(uint16*)frame = (uint16)htol16(pkt_len);
+ *(((uint16*)frame) + 1) = (uint16)htol16(~pkt_len);
+ pkt_len += tail_padding;
+
+ /* hardware extesion flags */
+ if (bus->txglom_enable) {
+ uint32 hwheader1;
+ uint32 hwheader2;
+
+ swhdr_offset += SDPCM_HWEXT_LEN;
+ hwheader1 = (pkt_len - SDPCM_FRAMETAG_LEN - tail_padding) |
+ (last_chained_pkt << 24);
+ hwheader2 = (tail_padding) << 16;
+ htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
+ htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
+ }
+ PKTSETLEN((osh), (pkt), (pkt_len));
+
+ /* software frame tags */
+ swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
+ | (txseq % SDPCM_SEQUENCE_WRAP) |
+ (((head_padding + sdpcm_hdrlen) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
+ htol32_ua_store(swheader, frame + swhdr_offset);
+ htol32_ua_store(0, frame + swhdr_offset + sizeof(swheader));
+
+ return pkt_len;
+}
+
+static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt)
+{
+ osl_t *osh;
+ uint8 *frame;
+ int data_offset;
+ int tail_padding;
+ int swhdr_offset = SDPCM_FRAMETAG_LEN + (bus->txglom_enable ? SDPCM_HWEXT_LEN : 0);
+
+ (void)osh;
+ osh = bus->dhd->osh;
+
+ /* restore pkt buffer pointer, but keeps the header pushed by dhd_prot_hdrpush */
+ frame = (uint8*)PKTDATA(osh, pkt);
+
+ DHD_INFO(("%s PKTLEN before postprocess %d",
+ __FUNCTION__, PKTLEN(osh, pkt)));
+
+ /* PKTLEN still includes tail_padding, so exclude it.
+ * We shall have head_padding + original pkt_len for PKTLEN afterwards.
+ */
+ if (bus->txglom_enable) {
+ /* txglom pkts have tail_padding length in HW ext header */
+ tail_padding = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + 4) >> 16;
+ PKTSETLEN(osh, pkt, PKTLEN(osh, pkt) - tail_padding);
+ DHD_INFO((" txglom pkt: tail_padding %d PKTLEN %d\n",
+ tail_padding, PKTLEN(osh, pkt)));
+ } else {
+ /* non-txglom pkts have head_padding + original pkt length in HW frame tag.
+ * We cannot refer to this field for txglom pkts as the first pkt of the chain will
+ * have the field for the total length of the chain.
+ */
+ PKTSETLEN(osh, pkt, *(uint16*)frame);
+ DHD_INFO((" non-txglom pkt: HW frame tag len %d after PKTLEN %d\n",
+ *(uint16*)frame, PKTLEN(osh, pkt)));
+ }
+
+ data_offset = ltoh32_ua(frame + swhdr_offset);
+ data_offset = (data_offset & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT;
+ /* Get rid of sdpcm header + head_padding */
+ PKTPULL(osh, pkt, data_offset);
+
+ DHD_INFO(("%s data_offset %d, PKTLEN %d\n",
+ __FUNCTION__, data_offset, PKTLEN(osh, pkt)));
+
+ return BCME_OK;
+}
+
+static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt)
+{
+ int i;
+ int ret = 0;
+ osl_t *osh;
+ bcmsdh_info_t *sdh;
+ void *pkt = NULL;
+ void *pkt_chain;
+ int total_len = 0;
+ void *head_pkt = NULL;
+ void *prev_pkt = NULL;
+ int pad_pkt_len = 0;
+ int new_pkt_num = 0;
+ void *new_pkts[MAX_TX_PKTCHAIN_CNT];
+ bool wlfc_enabled = FALSE;
+
+ if (bus->dhd->dongle_reset)
+ return BCME_NOTREADY;
+
+ sdh = bus->sdh;
+ osh = bus->dhd->osh;
+ /* init new_pkts[0] to make some compiler happy, not necessary as we check new_pkt_num */
+ new_pkts[0] = NULL;
+
+ for (i = 0; i < num_pkt; i++) {
+ int pkt_len;
+ bool last_pkt;
+ void *new_pkt = NULL;
+
+ pkt = pkts[i];
+ ASSERT(pkt);
+ last_pkt = (i == num_pkt - 1);
+ pkt_len = dhdsdio_txpkt_preprocess(bus, pkt, chan, bus->tx_seq + i,
+ total_len, last_pkt, &pad_pkt_len, &new_pkt);
+ if (pkt_len <= 0)
+ goto done;
+ if (new_pkt) {
+ pkt = new_pkt;
+ new_pkts[new_pkt_num++] = new_pkt;
+ }
+ total_len += pkt_len;
+
+ PKTSETNEXT(osh, pkt, NULL);
+ /* insert the packet into the list */
+ head_pkt ? PKTSETNEXT(osh, prev_pkt, pkt) : (head_pkt = pkt);
+ prev_pkt = pkt;
+
+ }
+
+ /* Update the HW frame tag (total length) in the first pkt of the glom */
+ if (bus->txglom_enable) {
+ uint8 *frame;
+
+ total_len += pad_pkt_len;
+ frame = (uint8*)PKTDATA(osh, head_pkt);
+ *(uint16*)frame = (uint16)htol16(total_len);
+ *(((uint16*)frame) + 1) = (uint16)htol16(~total_len);
+
+ }
+
+ /* if a padding packet if needed, insert it to the end of the link list */
+ if (pad_pkt_len) {
+ PKTSETLEN(osh, bus->pad_pkt, pad_pkt_len);
+ PKTSETNEXT(osh, pkt, bus->pad_pkt);
+ }
+
+ /* dhd_bcmsdh_send_buf ignores the buffer pointer if he packet
+ * parameter is not NULL, for non packet chian we pass NULL pkt pointer
+ * so it will take the aligned length and buffer pointer.
+ */
+ pkt_chain = PKTNEXT(osh, head_pkt) ? head_pkt : NULL;
+ ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
+ PKTDATA(osh, head_pkt), total_len, pkt_chain, NULL, NULL, TXRETRIES);
+ if (ret == BCME_OK)
+ bus->tx_seq = (bus->tx_seq + num_pkt) % SDPCM_SEQUENCE_WRAP;
+
+ /* if a padding packet was needed, remove it from the link list as it not a data pkt */
+ if (pad_pkt_len && pkt)
+ PKTSETNEXT(osh, pkt, NULL);
+
+done:
+ pkt = head_pkt;
+ while (pkt) {
+ void *pkt_next = PKTNEXT(osh, pkt);
+ PKTSETNEXT(osh, pkt, NULL);
+ dhdsdio_txpkt_postprocess(bus, pkt);
+ pkt = pkt_next;
+ }
+
+ /* new packets might be allocated due to insufficient room for padding, but we
+ * still have to indicate the original packets to upper layer
+ */
+ for (i = 0; i < num_pkt; i++) {
+ pkt = pkts[i];
+ wlfc_enabled = FALSE;
+#ifdef PROP_TXSTATUS
+ if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt))) {
+ wlfc_enabled = (dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0) !=
+ WLFC_UNSUPPORTED);
+ }
+#endif /* PROP_TXSTATUS */
+ if (!wlfc_enabled) {
+ PKTSETNEXT(osh, pkt, NULL);
+ dhd_txcomplete(bus->dhd, pkt, ret != 0);
+ if (free_pkt)
+ PKTFREE(osh, pkt, TRUE);
+ }
+ }
+ for (i = 0; i < new_pkt_num; i++)
+ PKTFREE(osh, new_pkts[i], TRUE);
+
+ return ret;
+}
+
+static uint
+dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
+{
+ uint cnt = 0;
+ uint8 tx_prec_map;
+ uint16 txpktqlen = 0;
+ uint32 intstatus = 0;
+ uint retries = 0;
+ osl_t *osh;
+ uint datalen = 0;
+ dhd_pub_t *dhd = bus->dhd;
+ sdpcmd_regs_t *regs = bus->regs;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (!KSO_ENAB(bus)) {
+ DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
+ return BCME_NODEVICE;
+ }
+
+ osh = dhd->osh;
+ tx_prec_map = ~bus->flowcontrol;
+ for (cnt = 0; (cnt < maxframes) && DATAOK(bus);) {
+ int i;
+ int num_pkt = 1;
+ void *pkts[MAX_TX_PKTCHAIN_CNT];
+ int prec_out;
+
+ dhd_os_sdlock_txq(bus->dhd);
+ if (bus->txglom_enable) {
+ num_pkt = MIN((uint32)DATABUFCNT(bus), (uint32)bus->txglomsize);
+ num_pkt = MIN(num_pkt, ARRAYSIZE(pkts));
+ }
+ num_pkt = MIN(num_pkt, pktq_mlen(&bus->txq, tx_prec_map));
+ for (i = 0; i < num_pkt; i++) {
+ pkts[i] = pktq_mdeq(&bus->txq, ~bus->flowcontrol, &prec_out);
+ if (!pkts[i]) {
+ DHD_ERROR(("%s: pktg_mlen non-zero when no pkt\n",
+ __FUNCTION__));
+ ASSERT(0);
+ break;
+ }
+ PKTORPHAN(pkts[i]);
+ datalen += PKTLEN(osh, pkts[i]);
+ }
+ dhd_os_sdunlock_txq(bus->dhd);
+
+ if (i == 0)
+ break;
+ if (dhdsdio_txpkt(bus, SDPCM_DATA_CHANNEL, pkts, i, TRUE) != BCME_OK)
+ dhd->tx_errors++;
+ else
+ dhd->dstats.tx_bytes += datalen;
+ cnt += i;
+
+ /* In poll mode, need to check for other events */
+ if (!bus->intr && cnt)
+ {
+ /* Check device status, signal pending interrupt */
+ R_SDREG(intstatus, &regs->intstatus, retries);
+ bus->f2txdata++;
+ if (bcmsdh_regfail(bus->sdh))
+ break;
+ if (intstatus & bus->hostintmask)
+ bus->ipend = TRUE;
+ }
+
+ }
+
+ dhd_os_sdlock_txq(bus->dhd);
+ txpktqlen = pktq_len(&bus->txq);
+ dhd_os_sdunlock_txq(bus->dhd);
+
+ /* Do flow-control if needed */
+ if (dhd->up && (dhd->busstate == DHD_BUS_DATA) && (txpktqlen < FCLOW)) {
+ bool wlfc_enabled = FALSE;
+#ifdef PROP_TXSTATUS
+ wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED);
+#endif
+ if (!wlfc_enabled && dhd_doflow && dhd->txoff) {
+ dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
+ }
+ }
+
+ return cnt;
+}
+
+static void
+dhdsdio_sendpendctl(dhd_bus_t *bus)
+{
+ bcmsdh_info_t *sdh = bus->sdh;
+ int ret;
+ uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN;
+
+ if (bus->txglom_enable)
+ frame_seq += SDPCM_HWEXT_LEN;
+
+ if (*frame_seq != bus->tx_seq) {
+ DHD_INFO(("%s IOCTL frame seq lag detected!"
+ " frm_seq:%d != bus->tx_seq:%d, corrected\n",
+ __FUNCTION__, *frame_seq, bus->tx_seq));
+ *frame_seq = bus->tx_seq;
+ }
+
+ ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
+ (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len,
+ NULL, NULL, NULL, 1);
+ if (ret == BCME_OK)
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+
+ bus->ctrl_frame_stat = FALSE;
+ dhd_wait_event_wakeup(bus->dhd);
+}
+
+int
+dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
+{
+ static int err_nodevice = 0;
+ uint8 *frame;
+ uint16 len;
+ uint32 swheader;
+ bcmsdh_info_t *sdh = bus->sdh;
+ uint8 doff = 0;
+ int ret = -1;
+ uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd->dongle_reset)
+ return -EIO;
+
+ /* Back the pointer to make a room for bus header */
+ frame = msg - sdpcm_hdrlen;
+ len = (msglen += sdpcm_hdrlen);
+
+ /* Add alignment padding (optional for ctl frames) */
+ if (dhd_alignctl) {
+ if ((doff = ((uintptr)frame % DHD_SDALIGN))) {
+ frame -= doff;
+ len += doff;
+ msglen += doff;
+ bzero(frame, doff + sdpcm_hdrlen);
+ }
+ ASSERT(doff < DHD_SDALIGN);
+ }
+ doff += sdpcm_hdrlen;
+
+ /* Round send length to next SDIO block */
+ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
+ uint16 pad = bus->blocksize - (len % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize))
+ len += pad;
+ } else if (len % DHD_SDALIGN) {
+ len += DHD_SDALIGN - (len % DHD_SDALIGN);
+ }
+
+ /* Satisfy length-alignment requirements */
+ if (forcealign && (len & (ALIGNMENT - 1)))
+ len = ROUNDUP(len, ALIGNMENT);
+
+ ASSERT(ISALIGNED((uintptr)frame, 2));
+
+
+ /* Need to lock here to protect txseq and SDIO tx calls */
+ dhd_os_sdlock(bus->dhd);
+
+ BUS_WAKE(bus);
+
+ /* Make sure backplane clock is on */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
+ *(uint16*)frame = htol16((uint16)msglen);
+ *(((uint16*)frame) + 1) = htol16(~msglen);
+
+ if (bus->txglom_enable) {
+ uint32 hwheader1, hwheader2;
+ /* Software tag: channel, sequence number, data offset */
+ swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
+ | bus->tx_seq
+ | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
+ htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN);
+ htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN
+ + SDPCM_HWEXT_LEN + sizeof(swheader));
+
+ hwheader1 = (msglen - SDPCM_FRAMETAG_LEN) | (1 << 24);
+ hwheader2 = (len - (msglen)) << 16;
+ htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
+ htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
+
+ *(uint16*)frame = htol16(len);
+ *(((uint16*)frame) + 1) = htol16(~(len));
+ } else {
+ /* Software tag: channel, sequence number, data offset */
+ swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
+ | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
+ htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
+ htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+ }
+ if (!TXCTLOK(bus)) {
+ DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
+ __FUNCTION__, bus->tx_max, bus->tx_seq));
+ bus->ctrl_frame_stat = TRUE;
+ /* Send from dpc */
+ bus->ctrl_frame_buf = frame;
+ bus->ctrl_frame_len = len;
+
+ if (!bus->dpc_sched) {
+ bus->dpc_sched = TRUE;
+ dhd_sched_dpc(bus->dhd);
+ }
+ if (bus->ctrl_frame_stat) {
+ dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
+ }
+
+ if (bus->ctrl_frame_stat == FALSE) {
+ DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
+ ret = 0;
+ } else {
+ bus->dhd->txcnt_timeout++;
+ if (!bus->dhd->hang_was_sent) {
+ DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
+ __FUNCTION__, bus->dhd->txcnt_timeout));
+ }
+ ret = -1;
+ bus->ctrl_frame_stat = FALSE;
+ goto done;
+ }
+ }
+
+ bus->dhd->txcnt_timeout = 0;
+ bus->ctrl_frame_stat = TRUE;
+
+ if (ret == -1) {
+#ifdef DHD_DEBUG
+ if (DHD_BYTES_ON() && DHD_CTL_ON()) {
+ prhex("Tx Frame", frame, len);
+ } else if (DHD_HDRS_ON()) {
+ prhex("TxHdr", frame, MIN(len, 16));
+ }
+#endif
+ ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
+ frame, len, NULL, NULL, NULL, TXRETRIES);
+ if (ret == BCME_OK)
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+ }
+ bus->ctrl_frame_stat = FALSE;
+
+done:
+ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ bus->activity = FALSE;
+ dhdsdio_clkctl(bus, CLK_NONE, TRUE);
+ }
+
+ dhd_os_sdunlock(bus->dhd);
+
+ if (ret)
+ bus->dhd->tx_ctlerrs++;
+ else
+ bus->dhd->tx_ctlpkts++;
+
+ if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT)
+ return -ETIMEDOUT;
+
+ if (ret == BCME_NODEVICE)
+ err_nodevice++;
+ else
+ err_nodevice = 0;
+
+ return ret ? err_nodevice >= ERROR_BCME_NODEVICE_MAX ? -ETIMEDOUT : -EIO : 0;
+}
+
+int
+dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
+{
+ int timeleft;
+ uint rxlen = 0;
+ bool pending;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd->dongle_reset)
+ return -EIO;
+
+ /* Wait until control frame is available */
+ timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
+
+ dhd_os_sdlock(bus->dhd);
+ rxlen = bus->rxlen;
+ bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
+ bus->rxlen = 0;
+ dhd_os_sdunlock(bus->dhd);
+
+ if (rxlen) {
+ DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
+ __FUNCTION__, rxlen, msglen));
+ } else if (timeleft == 0) {
+#ifdef DHD_DEBUG
+ uint32 status, retry = 0;
+ R_SDREG(status, &bus->regs->intstatus, retry);
+ DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n",
+ __FUNCTION__, status));
+#else
+ DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
+#endif /* DHD_DEBUG */
+#ifdef DHD_DEBUG
+ dhd_os_sdlock(bus->dhd);
+ dhdsdio_checkdied(bus, NULL, 0);
+ dhd_os_sdunlock(bus->dhd);
+#endif /* DHD_DEBUG */
+ } else if (pending == TRUE) {
+ /* signal pending */
+ DHD_ERROR(("%s: signal pending\n", __FUNCTION__));
+ return -EINTR;
+
+ } else {
+ DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
+#ifdef DHD_DEBUG
+ dhd_os_sdlock(bus->dhd);
+ dhdsdio_checkdied(bus, NULL, 0);
+ dhd_os_sdunlock(bus->dhd);
+#endif /* DHD_DEBUG */
+ }
+ if (timeleft == 0) {
+ if (rxlen == 0)
+ bus->dhd->rxcnt_timeout++;
+ DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__,
+ bus->dhd->rxcnt_timeout, rxlen));
+ }
+ else
+ bus->dhd->rxcnt_timeout = 0;
+
+ if (rxlen)
+ bus->dhd->rx_ctlpkts++;
+ else
+ bus->dhd->rx_ctlerrs++;
+
+ if (bus->dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT)
+ return -ETIMEDOUT;
+
+ if (bus->dhd->dongle_trap_occured)
+ return -EREMOTEIO;
+
+ return rxlen ? (int)rxlen : -EIO;
+}
+
+/* IOVar table */
+enum {
+ IOV_INTR = 1,
+ IOV_POLLRATE,
+ IOV_SDREG,
+ IOV_SBREG,
+ IOV_SDCIS,
+ IOV_MEMBYTES,
+ IOV_RAMSIZE,
+ IOV_RAMSTART,
+#ifdef DHD_DEBUG
+ IOV_CHECKDIED,
+ IOV_SERIALCONS,
+#endif /* DHD_DEBUG */
+ IOV_SET_DOWNLOAD_STATE,
+ IOV_SOCRAM_STATE,
+ IOV_FORCEEVEN,
+ IOV_SDIOD_DRIVE,
+ IOV_READAHEAD,
+ IOV_SDRXCHAIN,
+ IOV_ALIGNCTL,
+ IOV_SDALIGN,
+ IOV_DEVRESET,
+ IOV_CPU,
+#if defined(USE_SDIOFIFO_IOVAR)
+ IOV_WATERMARK,
+ IOV_MESBUSYCTRL,
+#endif /* USE_SDIOFIFO_IOVAR */
+#ifdef SDTEST
+ IOV_PKTGEN,
+ IOV_EXTLOOP,
+#endif /* SDTEST */
+ IOV_SPROM,
+ IOV_TXBOUND,
+ IOV_RXBOUND,
+ IOV_TXMINMAX,
+ IOV_IDLETIME,
+ IOV_IDLECLOCK,
+ IOV_SD1IDLE,
+ IOV_SLEEP,
+ IOV_DONGLEISOLATION,
+ IOV_KSO,
+ IOV_DEVSLEEP,
+ IOV_DEVCAP,
+ IOV_VARS,
+#ifdef SOFTAP
+ IOV_FWPATH,
+#endif
+ IOV_TXGLOMSIZE,
+ IOV_TXGLOMMODE,
+ IOV_HANGREPORT,
+ IOV_TXINRX_THRES
+};
+
+const bcm_iovar_t dhdsdio_iovars[] = {
+ {"intr", IOV_INTR, 0, IOVT_BOOL, 0 },
+ {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0 },
+ {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0 },
+ {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0 },
+ {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0 },
+ {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0 },
+ {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) },
+ {"ramsize", IOV_RAMSIZE, 0, IOVT_UINT32, 0 },
+ {"ramstart", IOV_RAMSTART, 0, IOVT_UINT32, 0 },
+ {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, IOVT_BOOL, 0 },
+ {"socram_state", IOV_SOCRAM_STATE, 0, IOVT_BOOL, 0 },
+ {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 },
+ {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0 },
+ {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0 },
+ {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0 },
+ {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0 },
+ {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0 },
+ {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0 },
+#ifdef DHD_DEBUG
+ {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
+ {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
+ {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN },
+ {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0 },
+ {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0 },
+ {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0 },
+ {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0 },
+ {"cpu", IOV_CPU, 0, IOVT_BOOL, 0 },
+#ifdef DHD_DEBUG
+ {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0 },
+ {"serial", IOV_SERIALCONS, 0, IOVT_UINT32, 0 },
+#endif /* DHD_DEBUG */
+#endif /* DHD_DEBUG */
+#ifdef SDTEST
+ {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 },
+ {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) },
+#endif /* SDTEST */
+#if defined(USE_SDIOFIFO_IOVAR)
+ {"watermark", IOV_WATERMARK, 0, IOVT_UINT32, 0 },
+ {"mesbusyctrl", IOV_MESBUSYCTRL, 0, IOVT_UINT32, 0 },
+#endif /* USE_SDIOFIFO_IOVAR */
+ {"devcap", IOV_DEVCAP, 0, IOVT_UINT32, 0 },
+ {"dngl_isolation", IOV_DONGLEISOLATION, 0, IOVT_UINT32, 0 },
+ {"kso", IOV_KSO, 0, IOVT_UINT32, 0 },
+ {"devsleep", IOV_DEVSLEEP, 0, IOVT_UINT32, 0 },
+#ifdef SOFTAP
+ {"fwpath", IOV_FWPATH, 0, IOVT_BUFFER, 0 },
+#endif
+ {"txglomsize", IOV_TXGLOMSIZE, 0, IOVT_UINT32, 0 },
+ {"fw_hang_report", IOV_HANGREPORT, 0, IOVT_BOOL, 0 },
+ {"txinrx_thres", IOV_TXINRX_THRES, 0, IOVT_INT32, 0 },
+ {NULL, 0, 0, 0, 0 }
+};
+
+static void
+dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
+{
+ uint q1, q2;
+
+ if (!div) {
+ bcm_bprintf(strbuf, "%s N/A", desc);
+ } else {
+ q1 = num / div;
+ q2 = (100 * (num - (q1 * div))) / div;
+ bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
+ }
+}
+
+void
+dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+{
+ dhd_bus_t *bus = dhdp->bus;
+
+ bcm_bprintf(strbuf, "Bus SDIO structure:\n");
+ bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
+ bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
+ bcm_bprintf(strbuf, "fcstate %d qlen %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n",
+ bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip,
+ bus->rxlen, bus->rx_seq);
+ bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n",
+ bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
+ bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n",
+ bus->pollrate, bus->pollcnt, bus->regfails);
+
+ bcm_bprintf(strbuf, "\nAdditional counters:\n");
+#ifdef DHDENABLE_TAILPAD
+ bcm_bprintf(strbuf, "tx_tailpad_chain %u tx_tailpad_pktget %u\n",
+ bus->tx_tailpad_chain, bus->tx_tailpad_pktget);
+#endif
+ bcm_bprintf(strbuf, "tx_sderrs %u fcqueued %u rxrtx %u rx_toolong %u rxc_errors %u\n",
+ bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
+ bus->rxc_errors);
+ bcm_bprintf(strbuf, "rx_hdrfail %u badhdr %u badseq %u\n",
+ bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
+ bcm_bprintf(strbuf, "fc_rcvd %u, fc_xoff %u, fc_xon %u\n",
+ bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
+ bcm_bprintf(strbuf, "rxglomfail %u, rxglomframes %u, rxglompkts %u\n",
+ bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
+ bcm_bprintf(strbuf, "f2rx (hdrs/data) %u (%u/%u), f2tx %u f1regs %u\n",
+ (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata,
+ bus->f2txdata, bus->f1regdata);
+ {
+ dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
+ (bus->f2rxhdrs + bus->f2rxdata));
+ dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata);
+ dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
+ (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
+ dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount);
+ bcm_bprintf(strbuf, "\n");
+
+ dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
+ bus->dhd->rx_packets);
+ dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes);
+ bcm_bprintf(strbuf, "\n");
+
+ dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata);
+ dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata);
+ dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
+ (bus->f2txdata + bus->f1regdata));
+ dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount);
+ bcm_bprintf(strbuf, "\n");
+
+ dhd_dump_pct(strbuf, "Total: pkts/f2rw",
+ (bus->dhd->tx_packets + bus->dhd->rx_packets),
+ (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
+ dhd_dump_pct(strbuf, ", pkts/f1sd",
+ (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata);
+ dhd_dump_pct(strbuf, ", pkts/sd",
+ (bus->dhd->tx_packets + bus->dhd->rx_packets),
+ (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
+ dhd_dump_pct(strbuf, ", pkts/int",
+ (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount);
+ bcm_bprintf(strbuf, "\n\n");
+ }
+
+#ifdef SDTEST
+ if (bus->pktgen_count) {
+ bcm_bprintf(strbuf, "pktgen config and count:\n");
+ bcm_bprintf(strbuf, "freq %u count %u print %u total %u min %u len %u\n",
+ bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print,
+ bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen);
+ bcm_bprintf(strbuf, "send attempts %u rcvd %u fail %u\n",
+ bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
+ }
+#endif /* SDTEST */
+#ifdef DHD_DEBUG
+ bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
+ bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
+ bcm_bprintf(strbuf, "blocksize %u roundup %u\n", bus->blocksize, bus->roundup);
+#endif /* DHD_DEBUG */
+ bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
+ bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping);
+}
+
+void
+dhd_bus_clearcounts(dhd_pub_t *dhdp)
+{
+ dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
+
+ bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
+ bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
+ bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
+#ifdef DHDENABLE_TAILPAD
+ bus->tx_tailpad_chain = bus->tx_tailpad_pktget = 0;
+#endif
+ bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
+ bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
+ bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
+}
+
+#ifdef SDTEST
+static int
+dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg)
+{
+ dhd_pktgen_t pktgen;
+
+ pktgen.version = DHD_PKTGEN_VERSION;
+ pktgen.freq = bus->pktgen_freq;
+ pktgen.count = bus->pktgen_count;
+ pktgen.print = bus->pktgen_print;
+ pktgen.total = bus->pktgen_total;
+ pktgen.minlen = bus->pktgen_minlen;
+ pktgen.maxlen = bus->pktgen_maxlen;
+ pktgen.numsent = bus->pktgen_sent;
+ pktgen.numrcvd = bus->pktgen_rcvd;
+ pktgen.numfail = bus->pktgen_fail;
+ pktgen.mode = bus->pktgen_mode;
+ pktgen.stop = bus->pktgen_stop;
+
+ bcopy(&pktgen, arg, sizeof(pktgen));
+
+ return 0;
+}
+
+static int
+dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg)
+{
+ dhd_pktgen_t pktgen;
+ uint oldcnt, oldmode;
+
+ bcopy(arg, &pktgen, sizeof(pktgen));
+ if (pktgen.version != DHD_PKTGEN_VERSION)
+ return BCME_BADARG;
+
+ oldcnt = bus->pktgen_count;
+ oldmode = bus->pktgen_mode;
+
+ bus->pktgen_freq = pktgen.freq;
+ bus->pktgen_count = pktgen.count;
+ bus->pktgen_print = pktgen.print;
+ bus->pktgen_total = pktgen.total;
+ bus->pktgen_minlen = pktgen.minlen;
+ bus->pktgen_maxlen = pktgen.maxlen;
+ bus->pktgen_mode = pktgen.mode;
+ bus->pktgen_stop = pktgen.stop;
+
+ bus->pktgen_tick = bus->pktgen_ptick = 0;
+ bus->pktgen_prev_time = jiffies;
+ bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen);
+ bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen);
+
+ /* Clear counts for a new pktgen (mode change, or was stopped) */
+ if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) {
+ bus->pktgen_sent = bus->pktgen_prev_sent = bus->pktgen_rcvd = 0;
+ bus->pktgen_prev_rcvd = bus->pktgen_fail = 0;
+ }
+
+ return 0;
+}
+#endif /* SDTEST */
+
+static void
+dhdsdio_devram_remap(dhd_bus_t *bus, bool val)
+{
+ uint8 enable, protect, remap;
+
+ si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
+ remap = val ? TRUE : FALSE;
+ si_socdevram(bus->sih, TRUE, &enable, &protect, &remap);
+}
+
+static int
+dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size)
+{
+ int bcmerror = 0;
+ uint32 sdaddr;
+ uint dsize;
+
+ /* In remap mode, adjust address beyond socram and redirect
+ * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize
+ * is not backplane accessible
+ */
+ if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address)) {
+ address -= bus->orig_ramsize;
+ address += SOCDEVRAM_BP_ADDR;
+ }
+
+ /* Determine initial transfer parameters */
+ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
+ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
+ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
+ else
+ dsize = size;
+
+ /* Set the backplane window to include the start address */
+ if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
+ DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
+ goto xfer_done;
+ }
+
+ /* Do the transfer(s) */
+ while (size) {
+ DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
+ __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
+ (address & SBSDIO_SBWINDOW_MASK)));
+ if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) {
+ DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
+ break;
+ }
+
+ /* Adjust for next transfer (if any) */
+ if ((size -= dsize)) {
+ data += dsize;
+ address += dsize;
+ if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
+ DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
+ break;
+ }
+ sdaddr = 0;
+ dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size);
+ }
+
+ }
+
+xfer_done:
+ /* Return the window to backplane enumeration space for core access */
+ if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
+ DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__,
+ bcmsdh_cur_sbwad(bus->sdh)));
+ }
+
+ return bcmerror;
+}
+
+#ifdef DHD_DEBUG
+static int
+dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
+{
+ uint32 addr;
+ int rv, i;
+ uint32 shaddr = 0;
+
+ if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID && !dhdsdio_sr_cap(bus))
+ bus->srmemsize = 0;
+
+ shaddr = bus->dongle_ram_base + bus->ramsize - 4;
+ i = 0;
+ do {
+ /* Read last word in memory to determine address of sdpcm_shared structure */
+ if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
+ return rv;
+
+ addr = ltoh32(addr);
+
+ DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
+
+ /*
+ * Check if addr is valid.
+ * NVRAM length at the end of memory should have been overwritten.
+ */
+ if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
+ if ((bus->srmemsize > 0) && (i++ == 0)) {
+ shaddr -= bus->srmemsize;
+ } else {
+ DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
+ __FUNCTION__, addr));
+ return BCME_ERROR;
+ }
+ } else
+ break;
+ } while (i < 2);
+
+ /* Read hndrte_shared structure */
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
+ return rv;
+
+ /* Endianness */
+ sh->flags = ltoh32(sh->flags);
+ sh->trap_addr = ltoh32(sh->trap_addr);
+ sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
+ sh->assert_file_addr = ltoh32(sh->assert_file_addr);
+ sh->assert_line = ltoh32(sh->assert_line);
+ sh->console_addr = ltoh32(sh->console_addr);
+ sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
+
+ if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1)
+ return BCME_OK;
+
+ if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
+ DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
+ "is different than sdpcm_shared version %d in dongle\n",
+ __FUNCTION__, SDPCM_SHARED_VERSION,
+ sh->flags & SDPCM_SHARED_VERSION_MASK));
+ return BCME_ERROR;
+ }
+
+ return BCME_OK;
+}
+
+#define CONSOLE_LINE_MAX 192
+
+static int
+dhdsdio_readconsole(dhd_bus_t *bus)
+{
+ dhd_console_t *c = &bus->console;
+ uint8 line[CONSOLE_LINE_MAX], ch;
+ uint32 n, idx, addr;
+ int rv;
+
+ /* Don't do anything until FWREADY updates console address */
+ if (bus->console_addr == 0)
+ return 0;
+
+ if (!KSO_ENAB(bus))
+ return 0;
+
+ /* Read console log struct */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
+ return rv;
+
+ /* Allocate console buffer (one time only) */
+ if (c->buf == NULL) {
+ c->bufsize = ltoh32(c->log.buf_size);
+ if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
+ return BCME_NOMEM;
+ }
+
+ idx = ltoh32(c->log.idx);
+
+ /* Protect against corrupt value */
+ if (idx > c->bufsize)
+ return BCME_ERROR;
+
+ /* Skip reading the console buffer if the index pointer has not moved */
+ if (idx == c->last)
+ return BCME_OK;
+
+ /* Read the console buffer */
+ addr = ltoh32(c->log.buf);
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
+ return rv;
+
+ while (c->last != idx) {
+ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+ if (c->last == idx) {
+ /* This would output a partial line. Instead, back up
+ * the buffer pointer and output this line next time around.
+ */
+ if (c->last >= n)
+ c->last -= n;
+ else
+ c->last = c->bufsize - n;
+ goto break2;
+ }
+ ch = c->buf[c->last];
+ c->last = (c->last + 1) % c->bufsize;
+ if (ch == '\n')
+ break;
+ line[n] = ch;
+ }
+
+ if (n > 0) {
+ if (line[n - 1] == '\r')
+ n--;
+ line[n] = 0;
+ printf("CONSOLE: %s\n", line);
+#ifdef LOG_INTO_TCPDUMP
+ dhd_sendup_log(bus->dhd, line, n);
+#endif /* LOG_INTO_TCPDUMP */
+ }
+ }
+break2:
+
+ return BCME_OK;
+}
+
+static int
+dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size)
+{
+ int bcmerror = 0;
+ uint msize = 512;
+ char *mbuffer = NULL;
+ char *console_buffer = NULL;
+ uint maxstrlen = 256;
+ char *str = NULL;
+ trap_t tr;
+ sdpcm_shared_t sdpcm_shared;
+ struct bcmstrbuf strbuf;
+ uint32 console_ptr, console_size, console_index;
+ uint8 line[CONSOLE_LINE_MAX], ch;
+ uint32 n, i, addr;
+ int rv;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (DHD_NOCHECKDIED_ON())
+ return 0;
+
+ if (data == NULL) {
+ /*
+ * Called after a rx ctrl timeout. "data" is NULL.
+ * allocate memory to trace the trap or assert.
+ */
+ size = msize;
+ mbuffer = data = MALLOC(bus->dhd->osh, msize);
+ if (mbuffer == NULL) {
+ DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
+ bcmerror = BCME_NOMEM;
+ goto done;
+ }
+ }
+
+ if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
+ DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
+ bcmerror = BCME_NOMEM;
+ goto done;
+ }
+
+ if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0)
+ goto done;
+
+ bcm_binit(&strbuf, data, size);
+
+ bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address : 0x%08X\n",
+ sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
+
+ if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
+ /* NOTE: Misspelled assert is intentional - DO NOT FIX.
+ * (Avoids conflict with real asserts for programmatic parsing of output.)
+ */
+ bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
+ }
+
+ if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) {
+ /* NOTE: Misspelled assert is intentional - DO NOT FIX.
+ * (Avoids conflict with real asserts for programmatic parsing of output.)
+ */
+ bcm_bprintf(&strbuf, "No trap%s in dongle",
+ (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
+ ?"/assrt" :"");
+ } else {
+ if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
+ /* Download assert */
+ bcm_bprintf(&strbuf, "Dongle assert");
+ if (sdpcm_shared.assert_exp_addr != 0) {
+ str[0] = '\0';
+ if ((bcmerror = dhdsdio_membytes(bus, FALSE,
+ sdpcm_shared.assert_exp_addr,
+ (uint8 *)str, maxstrlen)) < 0)
+ goto done;
+
+ str[maxstrlen - 1] = '\0';
+ bcm_bprintf(&strbuf, " expr \"%s\"", str);
+ }
+
+ if (sdpcm_shared.assert_file_addr != 0) {
+ str[0] = '\0';
+ if ((bcmerror = dhdsdio_membytes(bus, FALSE,
+ sdpcm_shared.assert_file_addr,
+ (uint8 *)str, maxstrlen)) < 0)
+ goto done;
+
+ str[maxstrlen - 1] = '\0';
+ bcm_bprintf(&strbuf, " file \"%s\"", str);
+ }
+
+ bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line);
+ }
+
+ if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
+ bus->dhd->dongle_trap_occured = TRUE;
+ if ((bcmerror = dhdsdio_membytes(bus, FALSE,
+ sdpcm_shared.trap_addr,
+ (uint8*)&tr, sizeof(trap_t))) < 0)
+ goto done;
+
+ bcm_bprintf(&strbuf,
+ "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
+ "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
+ "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, "
+ "r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
+ ltoh32(tr.type), ltoh32(tr.epc), ltoh32(tr.cpsr), ltoh32(tr.spsr),
+ ltoh32(tr.r13), ltoh32(tr.r14), ltoh32(tr.pc),
+ ltoh32(sdpcm_shared.trap_addr),
+ ltoh32(tr.r0), ltoh32(tr.r1), ltoh32(tr.r2), ltoh32(tr.r3),
+ ltoh32(tr.r4), ltoh32(tr.r5), ltoh32(tr.r6), ltoh32(tr.r7));
+
+ addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log);
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr,
+ (uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
+ goto printbuf;
+
+ addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.buf_size);
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr,
+ (uint8 *)&console_size, sizeof(console_size))) < 0)
+ goto printbuf;
+
+ addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.idx);
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr,
+ (uint8 *)&console_index, sizeof(console_index))) < 0)
+ goto printbuf;
+
+ console_ptr = ltoh32(console_ptr);
+ console_size = ltoh32(console_size);
+ console_index = ltoh32(console_index);
+
+ if (console_size > CONSOLE_BUFFER_MAX ||
+ !(console_buffer = MALLOC(bus->dhd->osh, console_size)))
+ goto printbuf;
+
+ if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr,
+ (uint8 *)console_buffer, console_size)) < 0)
+ goto printbuf;
+
+ for (i = 0, n = 0; i < console_size; i += n + 1) {
+ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+ ch = console_buffer[(console_index + i + n) % console_size];
+ if (ch == '\n')
+ break;
+ line[n] = ch;
+ }
+
+
+ if (n > 0) {
+ if (line[n - 1] == '\r')
+ n--;
+ line[n] = 0;
+ /* Don't use DHD_ERROR macro since we print
+ * a lot of information quickly. The macro
+ * will truncate a lot of the printfs
+ */
+
+ if (dhd_msg_level & DHD_ERROR_VAL)
+ printf("CONSOLE: %s\n", line);
+ }
+ }
+ }
+ }
+
+printbuf:
+ if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
+ DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
+ }
+
+
+done:
+ if (mbuffer)
+ MFREE(bus->dhd->osh, mbuffer, msize);
+ if (str)
+ MFREE(bus->dhd->osh, str, maxstrlen);
+ if (console_buffer)
+ MFREE(bus->dhd->osh, console_buffer, console_size);
+
+ return bcmerror;
+}
+#endif /* #ifdef DHD_DEBUG */
+
+
+int
+dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
+{
+ int bcmerror = BCME_OK;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* Basic sanity checks */
+ if (bus->dhd->up) {
+ bcmerror = BCME_NOTDOWN;
+ goto err;
+ }
+ if (!len) {
+ bcmerror = BCME_BUFTOOSHORT;
+ goto err;
+ }
+
+ /* Free the old ones and replace with passed variables */
+ if (bus->vars)
+ MFREE(bus->dhd->osh, bus->vars, bus->varsz);
+
+ bus->vars = MALLOC(bus->dhd->osh, len);
+ bus->varsz = bus->vars ? len : 0;
+ if (bus->vars == NULL) {
+ bcmerror = BCME_NOMEM;
+ goto err;
+ }
+
+ /* Copy the passed variables, which should include the terminating double-null */
+ bcopy(arg, bus->vars, bus->varsz);
+err:
+ return bcmerror;
+}
+
+#ifdef DHD_DEBUG
+
+#define CC_PLL_CHIPCTRL_SERIAL_ENAB (1 << 24)
+#define CC_CHIPCTRL_JTAG_SEL (1 << 3)
+#define CC_CHIPCTRL_GPIO_SEL (0x3)
+#define CC_PLL_CHIPCTRL_SERIAL_ENAB_4334 (1 << 28)
+
+static int
+dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror)
+{
+ int int_val;
+ uint32 addr, data, uart_enab = 0;
+ uint32 jtag_sel = CC_CHIPCTRL_JTAG_SEL;
+ uint32 gpio_sel = CC_CHIPCTRL_GPIO_SEL;
+
+ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
+ data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
+ *bcmerror = 0;
+
+ bcmsdh_reg_write(bus->sdh, addr, 4, 1);
+ if (bcmsdh_regfail(bus->sdh)) {
+ *bcmerror = BCME_SDIO_ERROR;
+ return -1;
+ }
+ int_val = bcmsdh_reg_read(bus->sdh, data, 4);
+ if (bcmsdh_regfail(bus->sdh)) {
+ *bcmerror = BCME_SDIO_ERROR;
+ return -1;
+ }
+ if (bus->sih->chip == BCM4330_CHIP_ID) {
+ uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB;
+ }
+ else if (bus->sih->chip == BCM4334_CHIP_ID ||
+ bus->sih->chip == BCM43340_CHIP_ID ||
+ bus->sih->chip == BCM43341_CHIP_ID ||
+ bus->sih->chip == BCM43342_CHIP_ID ||
+ 0) {
+ if (enable) {
+ /* Moved to PMU chipcontrol 1 from 4330 */
+ int_val &= ~gpio_sel;
+ int_val |= jtag_sel;
+ } else {
+ int_val |= gpio_sel;
+ int_val &= ~jtag_sel;
+ }
+ uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB_4334;
+ }
+
+ if (!set)
+ return (int_val & uart_enab);
+ if (enable)
+ int_val |= uart_enab;
+ else
+ int_val &= ~uart_enab;
+ bcmsdh_reg_write(bus->sdh, data, 4, int_val);
+ if (bcmsdh_regfail(bus->sdh)) {
+ *bcmerror = BCME_SDIO_ERROR;
+ return -1;
+ }
+ if (bus->sih->chip == BCM4330_CHIP_ID) {
+ uint32 chipcontrol;
+ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol);
+ chipcontrol = bcmsdh_reg_read(bus->sdh, addr, 4);
+ chipcontrol &= ~jtag_sel;
+ if (enable) {
+ chipcontrol |= jtag_sel;
+ chipcontrol &= ~gpio_sel;
+ }
+ bcmsdh_reg_write(bus->sdh, addr, 4, chipcontrol);
+ }
+
+ return (int_val & uart_enab);
+}
+#endif
+
+static int
+dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
+ void *params, int plen, void *arg, int len, int val_size)
+{
+ int bcmerror = 0;
+ int32 int_val = 0;
+ bool bool_val = 0;
+
+ DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
+ __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
+
+ if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
+ goto exit;
+
+ if (plen >= (int)sizeof(int_val))
+ bcopy(params, &int_val, sizeof(int_val));
+
+ bool_val = (int_val != 0) ? TRUE : FALSE;
+
+
+ /* Some ioctls use the bus */
+ dhd_os_sdlock(bus->dhd);
+
+ /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
+ if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
+ actionid == IOV_GVAL(IOV_DEVRESET))) {
+ bcmerror = BCME_NOTREADY;
+ goto exit;
+ }
+
+ /*
+ * Special handling for keepSdioOn: New SDIO Wake-up Mechanism
+ */
+ if ((vi->varid == IOV_KSO) && (IOV_ISSET(actionid))) {
+ dhdsdio_clk_kso_iovar(bus, bool_val);
+ goto exit;
+ } else if ((vi->varid == IOV_DEVSLEEP) && (IOV_ISSET(actionid))) {
+ {
+ dhdsdio_clk_devsleep_iovar(bus, bool_val);
+ if (!SLPAUTO_ENAB(bus) && (bool_val == FALSE) && (bus->ipend)) {
+ DHD_ERROR(("INT pending in devsleep 1, dpc_sched: %d\n",
+ bus->dpc_sched));
+ if (!bus->dpc_sched) {
+ bus->dpc_sched = TRUE;
+ dhd_sched_dpc(bus->dhd);
+ }
+ }
+ }
+ goto exit;
+ }
+
+ /* Handle sleep stuff before any clock mucking */
+ if (vi->varid == IOV_SLEEP) {
+ if (IOV_ISSET(actionid)) {
+ bcmerror = dhdsdio_bussleep(bus, bool_val);
+ } else {
+ int_val = (int32)bus->sleeping;
+ bcopy(&int_val, arg, val_size);
+ }
+ goto exit;
+ }
+
+ /* Request clock to allow SDIO accesses */
+ if (!bus->dhd->dongle_reset) {
+ BUS_WAKE(bus);
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ }
+
+ switch (actionid) {
+ case IOV_GVAL(IOV_INTR):
+ int_val = (int32)bus->intr;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_INTR):
+ bus->intr = bool_val;
+ bus->intdis = FALSE;
+ if (bus->dhd->up) {
+ if (bus->intr) {
+ DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
+ bcmsdh_intr_enable(bus->sdh);
+ } else {
+ DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
+ bcmsdh_intr_disable(bus->sdh);
+ }
+ }
+ break;
+
+ case IOV_GVAL(IOV_POLLRATE):
+ int_val = (int32)bus->pollrate;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_POLLRATE):
+ bus->pollrate = (uint)int_val;
+ bus->poll = (bus->pollrate != 0);
+ break;
+
+ case IOV_GVAL(IOV_IDLETIME):
+ int_val = bus->idletime;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_IDLETIME):
+ if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) {
+ bcmerror = BCME_BADARG;
+ } else {
+ bus->idletime = int_val;
+ }
+ break;
+
+ case IOV_GVAL(IOV_IDLECLOCK):
+ int_val = (int32)bus->idleclock;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_IDLECLOCK):
+ bus->idleclock = int_val;
+ break;
+
+ case IOV_GVAL(IOV_SD1IDLE):
+ int_val = (int32)sd1idle;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_SD1IDLE):
+ sd1idle = bool_val;
+ break;
+
+
+ case IOV_SVAL(IOV_MEMBYTES):
+ case IOV_GVAL(IOV_MEMBYTES):
+ {
+ uint32 address;
+ uint size, dsize;
+ uint8 *data;
+
+ bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
+
+ ASSERT(plen >= 2*sizeof(int));
+
+ address = (uint32)int_val;
+ bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
+ size = (uint)int_val;
+
+ /* Do some validation */
+ dsize = set ? plen - (2 * sizeof(int)) : len;
+ if (dsize < size) {
+ DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
+ __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
+ bcmerror = BCME_BADARG;
+ break;
+ }
+
+ DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
+ (set ? "write" : "read"), size, address));
+
+ /* check if CR4 */
+ if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ /*
+ * If address is start of RAM (i.e. a downloaded image),
+ * store the reset instruction to be written in 0
+ */
+ if (set && address == bus->dongle_ram_base) {
+ bus->resetinstr = *(((uint32*)params) + 2);
+ }
+ } else {
+ /* If we know about SOCRAM, check for a fit */
+ if ((bus->orig_ramsize) &&
+ ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize)))
+ {
+ uint8 enable, protect, remap;
+ si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
+ if (!enable || protect) {
+ DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
+ __FUNCTION__, bus->orig_ramsize, size, address));
+ DHD_ERROR(("%s: socram enable %d, protect %d\n",
+ __FUNCTION__, enable, protect));
+ bcmerror = BCME_BADARG;
+ break;
+ }
+
+ if (!REMAP_ENAB(bus) && (address >= SOCDEVRAM_ARM_ADDR)) {
+ uint32 devramsize = si_socdevram_size(bus->sih);
+ if ((address < SOCDEVRAM_ARM_ADDR) ||
+ (address + size > (SOCDEVRAM_ARM_ADDR + devramsize))) {
+ DHD_ERROR(("%s: bad address 0x%08x, size 0x%08x\n",
+ __FUNCTION__, address, size));
+ DHD_ERROR(("%s: socram range 0x%08x,size 0x%08x\n",
+ __FUNCTION__, SOCDEVRAM_ARM_ADDR, devramsize));
+ bcmerror = BCME_BADARG;
+ break;
+ }
+ /* move it such that address is real now */
+ address -= SOCDEVRAM_ARM_ADDR;
+ address += SOCDEVRAM_BP_ADDR;
+ DHD_INFO(("%s: Request to %s %d bytes @ Mapped address 0x%08x\n",
+ __FUNCTION__, (set ? "write" : "read"), size, address));
+ } else if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address) && remap) {
+ /* Can not access remap region while devram remap bit is set
+ * ROM content would be returned in this case
+ */
+ DHD_ERROR(("%s: Need to disable remap for address 0x%08x\n",
+ __FUNCTION__, address));
+ bcmerror = BCME_ERROR;
+ break;
+ }
+ }
+ }
+
+ /* Generate the actual data pointer */
+ data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
+
+ /* Call to do the transfer */
+ bcmerror = dhdsdio_membytes(bus, set, address, data, size);
+
+ break;
+ }
+
+ case IOV_GVAL(IOV_RAMSIZE):
+ int_val = (int32)bus->ramsize;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_RAMSTART):
+ int_val = (int32)bus->dongle_ram_base;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_SDIOD_DRIVE):
+ int_val = (int32)dhd_sdiod_drive_strength;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_SDIOD_DRIVE):
+ dhd_sdiod_drive_strength = int_val;
+ si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength);
+ break;
+
+ case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
+ bcmerror = dhdsdio_download_state(bus, bool_val);
+ break;
+
+ case IOV_SVAL(IOV_SOCRAM_STATE):
+ bcmerror = dhdsdio_download_state(bus, bool_val);
+ break;
+
+ case IOV_SVAL(IOV_VARS):
+ bcmerror = dhdsdio_downloadvars(bus, arg, len);
+ break;
+
+ case IOV_GVAL(IOV_READAHEAD):
+ int_val = (int32)dhd_readahead;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_READAHEAD):
+ if (bool_val && !dhd_readahead)
+ bus->nextlen = 0;
+ dhd_readahead = bool_val;
+ break;
+
+ case IOV_GVAL(IOV_SDRXCHAIN):
+ int_val = (int32)bus->use_rxchain;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_SDRXCHAIN):
+ if (bool_val && !bus->sd_rxchain)
+ bcmerror = BCME_UNSUPPORTED;
+ else
+ bus->use_rxchain = bool_val;
+ break;
+ case IOV_GVAL(IOV_ALIGNCTL):
+ int_val = (int32)dhd_alignctl;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_ALIGNCTL):
+ dhd_alignctl = bool_val;
+ break;
+
+ case IOV_GVAL(IOV_SDALIGN):
+ int_val = DHD_SDALIGN;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+#ifdef DHD_DEBUG
+ case IOV_GVAL(IOV_VARS):
+ if (bus->varsz < (uint)len)
+ bcopy(bus->vars, arg, bus->varsz);
+ else
+ bcmerror = BCME_BUFTOOSHORT;
+ break;
+#endif /* DHD_DEBUG */
+
+#ifdef DHD_DEBUG
+ case IOV_GVAL(IOV_SDREG):
+ {
+ sdreg_t *sd_ptr;
+ uint32 addr, size;
+
+ sd_ptr = (sdreg_t *)params;
+
+ addr = (ulong)bus->regs + sd_ptr->offset;
+ size = sd_ptr->func;
+ int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
+ if (bcmsdh_regfail(bus->sdh))
+ bcmerror = BCME_SDIO_ERROR;
+ bcopy(&int_val, arg, sizeof(int32));
+ break;
+ }
+
+ case IOV_SVAL(IOV_SDREG):
+ {
+ sdreg_t *sd_ptr;
+ uint32 addr, size;
+
+ sd_ptr = (sdreg_t *)params;
+
+ addr = (ulong)bus->regs + sd_ptr->offset;
+ size = sd_ptr->func;
+ bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
+ if (bcmsdh_regfail(bus->sdh))
+ bcmerror = BCME_SDIO_ERROR;
+ break;
+ }
+
+ /* Same as above, but offset is not backplane (not SDIO core) */
+ case IOV_GVAL(IOV_SBREG):
+ {
+ sdreg_t sdreg;
+ uint32 addr, size;
+
+ bcopy(params, &sdreg, sizeof(sdreg));
+
+ addr = SI_ENUM_BASE + sdreg.offset;
+ size = sdreg.func;
+ int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
+ if (bcmsdh_regfail(bus->sdh))
+ bcmerror = BCME_SDIO_ERROR;
+ bcopy(&int_val, arg, sizeof(int32));
+ break;
+ }
+
+ case IOV_SVAL(IOV_SBREG):
+ {
+ sdreg_t sdreg;
+ uint32 addr, size;
+
+ bcopy(params, &sdreg, sizeof(sdreg));
+
+ addr = SI_ENUM_BASE + sdreg.offset;
+ size = sdreg.func;
+ bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
+ if (bcmsdh_regfail(bus->sdh))
+ bcmerror = BCME_SDIO_ERROR;
+ break;
+ }
+
+ case IOV_GVAL(IOV_SDCIS):
+ {
+ *(char *)arg = 0;
+
+ bcmstrcat(arg, "\nFunc 0\n");
+ bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
+ bcmstrcat(arg, "\nFunc 1\n");
+ bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
+ bcmstrcat(arg, "\nFunc 2\n");
+ bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
+ break;
+ }
+
+ case IOV_GVAL(IOV_FORCEEVEN):
+ int_val = (int32)forcealign;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_FORCEEVEN):
+ forcealign = bool_val;
+ break;
+
+ case IOV_GVAL(IOV_TXBOUND):
+ int_val = (int32)dhd_txbound;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_TXBOUND):
+ dhd_txbound = (uint)int_val;
+ break;
+
+ case IOV_GVAL(IOV_RXBOUND):
+ int_val = (int32)dhd_rxbound;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_RXBOUND):
+ dhd_rxbound = (uint)int_val;
+ break;
+
+ case IOV_GVAL(IOV_TXMINMAX):
+ int_val = (int32)dhd_txminmax;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_TXMINMAX):
+ dhd_txminmax = (uint)int_val;
+ break;
+
+ case IOV_GVAL(IOV_SERIALCONS):
+ int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror);
+ if (bcmerror != 0)
+ break;
+
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_SERIALCONS):
+ dhd_serialconsole(bus, TRUE, bool_val, &bcmerror);
+ break;
+
+
+#endif /* DHD_DEBUG */
+
+
+#ifdef SDTEST
+ case IOV_GVAL(IOV_EXTLOOP):
+ int_val = (int32)bus->ext_loop;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_EXTLOOP):
+ bus->ext_loop = bool_val;
+ break;
+
+ case IOV_GVAL(IOV_PKTGEN):
+ bcmerror = dhdsdio_pktgen_get(bus, arg);
+ break;
+
+ case IOV_SVAL(IOV_PKTGEN):
+ bcmerror = dhdsdio_pktgen_set(bus, arg);
+ break;
+#endif /* SDTEST */
+
+#if defined(USE_SDIOFIFO_IOVAR)
+ case IOV_GVAL(IOV_WATERMARK):
+ int_val = (int32)watermark;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_WATERMARK):
+ watermark = (uint)int_val;
+ watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark;
+ DHD_ERROR(("Setting watermark as 0x%x.\n", watermark));
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL);
+ break;
+
+ case IOV_GVAL(IOV_MESBUSYCTRL):
+ int_val = (int32)mesbusyctrl;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_MESBUSYCTRL):
+ mesbusyctrl = (uint)int_val;
+ mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK)
+ ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl;
+ DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl));
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
+ ((uint8)mesbusyctrl | 0x80), NULL);
+ break;
+#endif
+
+
+ case IOV_GVAL(IOV_DONGLEISOLATION):
+ int_val = bus->dhd->dongle_isolation;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DONGLEISOLATION):
+ bus->dhd->dongle_isolation = bool_val;
+ break;
+
+ case IOV_SVAL(IOV_DEVRESET):
+ DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
+ __FUNCTION__, bool_val, bus->dhd->dongle_reset,
+ bus->dhd->busstate));
+
+ ASSERT(bus->dhd->osh);
+ /* ASSERT(bus->cl_devid); */
+
+ dhd_bus_devreset(bus->dhd, (uint8)bool_val);
+
+ break;
+ /*
+ * softap firmware is updated through module parameter or android private command
+ */
+
+ case IOV_GVAL(IOV_DEVRESET):
+ DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
+
+ /* Get its status */
+ int_val = (bool) bus->dhd->dongle_reset;
+ bcopy(&int_val, arg, val_size);
+
+ break;
+
+ case IOV_GVAL(IOV_KSO):
+ int_val = dhdsdio_sleepcsr_get(bus);
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_DEVCAP):
+ int_val = dhdsdio_devcap_get(bus);
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DEVCAP):
+ dhdsdio_devcap_set(bus, (uint8) int_val);
+ break;
+ case IOV_GVAL(IOV_TXGLOMSIZE):
+ int_val = (int32)bus->txglomsize;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_TXGLOMSIZE):
+ if (int_val > SDPCM_MAXGLOM_SIZE) {
+ bcmerror = BCME_ERROR;
+ } else {
+ bus->txglomsize = (uint)int_val;
+ }
+ break;
+ case IOV_SVAL(IOV_HANGREPORT):
+ bus->dhd->hang_report = bool_val;
+ DHD_ERROR(("%s: Set hang_report as %d\n", __FUNCTION__, bus->dhd->hang_report));
+ break;
+
+ case IOV_GVAL(IOV_HANGREPORT):
+ int_val = (int32)bus->dhd->hang_report;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_GVAL(IOV_TXINRX_THRES):
+ int_val = bus->txinrx_thres;
+ bcopy(&int_val, arg, val_size);
+ break;
+ case IOV_SVAL(IOV_TXINRX_THRES):
+ if (int_val < 0) {
+ bcmerror = BCME_BADARG;
+ } else {
+ bus->txinrx_thres = int_val;
+ }
+ break;
+
+ default:
+ bcmerror = BCME_UNSUPPORTED;
+ break;
+ }
+
+exit:
+ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ bus->activity = FALSE;
+ dhdsdio_clkctl(bus, CLK_NONE, TRUE);
+ }
+
+ dhd_os_sdunlock(bus->dhd);
+
+ return bcmerror;
+}
+
+static int
+dhdsdio_write_vars(dhd_bus_t *bus)
+{
+ int bcmerror = 0;
+ uint32 varsize, phys_size;
+ uint32 varaddr;
+ uint8 *vbuffer;
+ uint32 varsizew;
+#ifdef DHD_DEBUG
+ uint8 *nvram_ularray;
+#endif /* DHD_DEBUG */
+
+ /* Even if there are no vars are to be written, we still need to set the ramsize. */
+ varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
+ varaddr = (bus->ramsize - 4) - varsize;
+
+ varaddr += bus->dongle_ram_base;
+
+ if (bus->vars) {
+ if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 7)) {
+ if (((varaddr & 0x3C) == 0x3C) && (varsize > 4)) {
+ DHD_ERROR(("PR85623WAR in place\n"));
+ varsize += 4;
+ varaddr -= 4;
+ }
+ }
+
+ vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
+ if (!vbuffer)
+ return BCME_NOMEM;
+
+ bzero(vbuffer, varsize);
+ bcopy(bus->vars, vbuffer, bus->varsz);
+
+ /* Write the vars list */
+ bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize);
+#ifdef DHD_DEBUG
+ /* Verify NVRAM bytes */
+ DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
+ nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
+ if (!nvram_ularray) {
+ MFREE(bus->dhd->osh, vbuffer, varsize);
+ return BCME_NOMEM;
+ }
+
+ /* Upload image to verify downloaded contents. */
+ memset(nvram_ularray, 0xaa, varsize);
+
+ /* Read the vars list to temp buffer for comparison */
+ bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, varsize, varaddr));
+ }
+ /* Compare the org NVRAM with the one read from RAM */
+ if (memcmp(vbuffer, nvram_ularray, varsize)) {
+ DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
+ } else
+ DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
+ __FUNCTION__));
+
+ MFREE(bus->dhd->osh, nvram_ularray, varsize);
+#endif /* DHD_DEBUG */
+
+ MFREE(bus->dhd->osh, vbuffer, varsize);
+ }
+
+ phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
+
+ phys_size += bus->dongle_ram_base;
+
+ /* adjust to the user specified RAM */
+ DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
+ phys_size, bus->ramsize));
+ DHD_INFO(("Vars are at %d, orig varsize is %d\n",
+ varaddr, varsize));
+ varsize = ((phys_size - 4) - varaddr);
+
+ /*
+ * Determine the length token:
+ * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
+ */
+ if (bcmerror) {
+ varsizew = 0;
+ } else {
+ varsizew = varsize / 4;
+ varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
+ varsizew = htol32(varsizew);
+ }
+
+ DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
+
+ /* Write the length token to the last word */
+ bcmerror = dhdsdio_membytes(bus, TRUE, (phys_size - 4),
+ (uint8*)&varsizew, 4);
+
+ return bcmerror;
+}
+
+static int
+dhdsdio_download_state(dhd_bus_t *bus, bool enter)
+{
+ uint retries;
+ int bcmerror = 0;
+ int foundcr4 = 0;
+
+ if (!bus->sih)
+ return BCME_ERROR;
+ /* To enter download state, disable ARM and reset SOCRAM.
+ * To exit download state, simply reset ARM (default is RAM boot).
+ */
+ if (enter) {
+ bus->alp_only = TRUE;
+
+ if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
+ !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
+ if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ foundcr4 = 1;
+ } else {
+ DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+ }
+
+ if (!foundcr4) {
+ si_core_disable(bus->sih, 0);
+ if (bcmsdh_regfail(bus->sdh)) {
+ bcmerror = BCME_SDIO_ERROR;
+ goto fail;
+ }
+
+ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+ si_core_reset(bus->sih, 0, 0);
+ if (bcmsdh_regfail(bus->sdh)) {
+ DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n",
+ __FUNCTION__));
+ bcmerror = BCME_SDIO_ERROR;
+ goto fail;
+ }
+
+ /* Disable remap for download */
+ if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih))
+ dhdsdio_devram_remap(bus, FALSE);
+
+ if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID) {
+ /* Disabling Remap for SRAM_3 */
+ si_socram_set_bankpda(bus->sih, 0x3, 0x0);
+ }
+
+ /* Clear the top bit of memory */
+ if (bus->ramsize) {
+ uint32 zeros = 0;
+ if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4,
+ (uint8*)&zeros, 4) < 0) {
+ bcmerror = BCME_SDIO_ERROR;
+ goto fail;
+ }
+ }
+ } else {
+ /* For CR4,
+ * Halt ARM
+ * Remove ARM reset
+ * Read RAM base address [0x18_0000]
+ * [next] Download firmware
+ * [done at else] Populate the reset vector
+ * [done at else] Remove ARM halt
+ */
+ /* Halt ARM & remove reset */
+ si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
+ }
+ } else {
+ if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+ if (!si_iscoreup(bus->sih)) {
+ DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+
+ if ((bcmerror = dhdsdio_write_vars(bus))) {
+ DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
+ goto fail;
+ }
+
+ /* Enable remap before ARM reset but after vars.
+ * No backplane access in remap mode
+ */
+ if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih))
+ dhdsdio_devram_remap(bus, TRUE);
+
+ if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
+ !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
+ DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+ W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
+
+
+ if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
+ !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+ } else {
+ /* cr4 has no socram, but tcm's */
+ /* write vars */
+ if ((bcmerror = dhdsdio_write_vars(bus))) {
+ DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
+ goto fail;
+ }
+
+ if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
+ !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
+ DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+ W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
+
+ /* switch back to arm core again */
+ if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
+ DHD_ERROR(("%s: Failed to find ARM CR4 core!\n", __FUNCTION__));
+ bcmerror = BCME_ERROR;
+ goto fail;
+ }
+ /* write address 0 with reset instruction */
+ bcmerror = dhdsdio_membytes(bus, TRUE, 0,
+ (uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
+
+ /* now remove reset and halt and continue to run CR4 */
+ }
+
+ si_core_reset(bus->sih, 0, 0);
+ if (bcmsdh_regfail(bus->sdh)) {
+ DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
+ bcmerror = BCME_SDIO_ERROR;
+ goto fail;
+ }
+
+ /* Allow HT Clock now that the ARM is running. */
+ bus->alp_only = FALSE;
+
+ bus->dhd->busstate = DHD_BUS_LOAD;
+ }
+
+fail:
+ /* Always return to SDIOD core */
+ if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
+ si_setcore(bus->sih, SDIOD_CORE_ID, 0);
+
+ return bcmerror;
+}
+
+int
+dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+ void *params, int plen, void *arg, int len, bool set)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ const bcm_iovar_t *vi = NULL;
+ int bcmerror = 0;
+ int val_size;
+ uint32 actionid;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ASSERT(name);
+ ASSERT(len >= 0);
+
+ /* Get MUST have return space */
+ ASSERT(set || (arg && len));
+
+ /* Set does NOT take qualifiers */
+ ASSERT(!set || (!params && !plen));
+
+ /* Look up var locally; if not found pass to host driver */
+ if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) {
+ dhd_os_sdlock(bus->dhd);
+
+ BUS_WAKE(bus);
+
+ /* Turn on clock in case SD command needs backplane */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set);
+
+ /* Check for bus configuration changes of interest */
+
+ /* If it was divisor change, read the new one */
+ if (set && strcmp(name, "sd_divisor") == 0) {
+ if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
+ &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
+ bus->sd_divisor = -1;
+ DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
+ } else {
+ DHD_INFO(("%s: noted %s update, value now %d\n",
+ __FUNCTION__, name, bus->sd_divisor));
+ }
+ }
+ /* If it was a mode change, read the new one */
+ if (set && strcmp(name, "sd_mode") == 0) {
+ if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
+ &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
+ bus->sd_mode = -1;
+ DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
+ } else {
+ DHD_INFO(("%s: noted %s update, value now %d\n",
+ __FUNCTION__, name, bus->sd_mode));
+ }
+ }
+ /* Similar check for blocksize change */
+ if (set && strcmp(name, "sd_blocksize") == 0) {
+ int32 fnum = 2;
+ if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
+ &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
+ bus->blocksize = 0;
+ DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
+ } else {
+ DHD_INFO(("%s: noted %s update, value now %d\n",
+ __FUNCTION__, "sd_blocksize", bus->blocksize));
+
+ dhdsdio_tune_fifoparam(bus);
+ }
+ }
+ bus->roundup = MIN(max_roundup, bus->blocksize);
+
+ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ bus->activity = FALSE;
+ dhdsdio_clkctl(bus, CLK_NONE, TRUE);
+ }
+
+ dhd_os_sdunlock(bus->dhd);
+ goto exit;
+ }
+
+ DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
+ name, (set ? "set" : "get"), len, plen));
+
+ /* set up 'params' pointer in case this is a set command so that
+ * the convenience int and bool code can be common to set and get
+ */
+ if (params == NULL) {
+ params = arg;
+ plen = len;
+ }
+
+ if (vi->type == IOVT_VOID)
+ val_size = 0;
+ else if (vi->type == IOVT_BUFFER)
+ val_size = len;
+ else
+ /* all other types are integer sized */
+ val_size = sizeof(int);
+
+ actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+ bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
+
+exit:
+ return bcmerror;
+}
+
+void
+dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
+{
+ osl_t *osh;
+ uint32 local_hostintmask;
+ uint8 saveclk;
+ uint retries;
+ int err;
+ bool wlfc_enabled = FALSE;
+
+ if (!bus->dhd)
+ return;
+
+ osh = bus->dhd->osh;
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ bcmsdh_waitlockfree(bus->sdh);
+
+ if (enforce_mutex)
+ dhd_os_sdlock(bus->dhd);
+
+ if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) {
+ /* if Firmware already hangs disbale any interrupt */
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ bus->hostintmask = 0;
+ bcmsdh_intr_disable(bus->sdh);
+ } else {
+
+ BUS_WAKE(bus);
+
+ /* Change our idea of bus state */
+ bus->dhd->busstate = DHD_BUS_DOWN;
+
+ if (KSO_ENAB(bus)) {
+
+ /* Enable clock for device interrupts */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ /* Disable and clear interrupts at the chip level also */
+ W_SDREG(0, &bus->regs->hostintmask, retries);
+ local_hostintmask = bus->hostintmask;
+ bus->hostintmask = 0;
+
+ /* Force clocks on backplane to be sure F2 interrupt propagates */
+ saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (!err) {
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
+ }
+ if (err) {
+ DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
+ __FUNCTION__, err));
+ }
+
+ /* Turn off the bus (F2), free any pending packets */
+ DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
+ bcmsdh_intr_disable(bus->sdh);
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
+
+ /* Clear any pending interrupts now that F2 is disabled */
+ W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
+ }
+
+ /* Turn off the backplane clock (only) */
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+ }
+
+#ifdef PROP_TXSTATUS
+ wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED);
+#endif
+ if (!wlfc_enabled) {
+#ifdef DHDTCPACK_SUPPRESS
+ /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
+ * when there is a newly coming packet from network stack.
+ */
+ dhd_tcpack_info_tbl_clean(bus->dhd);
+#endif /* DHDTCPACK_SUPPRESS */
+ /* Clear the data packet queues */
+ pktq_flush(osh, &bus->txq, TRUE, NULL, 0);
+ }
+
+ /* Clear any held glomming stuff */
+ if (bus->glomd)
+ PKTFREE(osh, bus->glomd, FALSE);
+
+ if (bus->glom)
+ PKTFREE(osh, bus->glom, FALSE);
+
+ bus->glom = bus->glomd = NULL;
+
+ /* Clear rx control and wake any waiters */
+ bus->rxlen = 0;
+ dhd_os_ioctl_resp_wake(bus->dhd);
+
+ /* Reset some F2 state stuff */
+ bus->rxskip = FALSE;
+ bus->tx_seq = bus->rx_seq = 0;
+
+ bus->tx_max = 4;
+
+ if (enforce_mutex)
+ dhd_os_sdunlock(bus->dhd);
+}
+
+#if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD)
+extern uint sd_txglom;
+#endif
+void
+dhd_txglom_enable(dhd_pub_t *dhdp, bool enable)
+{
+ /* can't enable host txglom by default, some platforms have no
+ * (or crappy) ADMA support and txglom will cause kernel assertions (e.g.
+ * panda board)
+ */
+ dhd_bus_t *bus = dhdp->bus;
+#ifdef BCMSDIOH_TXGLOM
+ char buf[256];
+ uint32 rxglom;
+ int32 ret;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+#ifdef BCMSDIOH_STD
+ if (enable)
+ enable = sd_txglom;
+#endif /* BCMSDIOH_STD */
+
+ if (enable) {
+ rxglom = 1;
+ memset(buf, 0, sizeof(buf));
+ bcm_mkiovar("bus:rxglom", (void *)&rxglom, 4, buf, sizeof(buf));
+ ret = dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
+ if (ret >= 0)
+ bus->txglom_enable = TRUE;
+ else {
+#ifdef BCMSDIOH_STD
+ sd_txglom = 0;
+#endif /* BCMSDIOH_STD */
+ bus->txglom_enable = FALSE;
+ }
+ } else
+#endif /* BCMSDIOH_TXGLOM */
+ bus->txglom_enable = FALSE;
+}
+
+int
+dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ dhd_timeout_t tmo;
+ uint retries = 0;
+ uint8 ready, enable;
+ int err, ret = 0;
+ uint8 saveclk;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ ASSERT(bus->dhd);
+ if (!bus->dhd)
+ return 0;
+
+ if (enforce_mutex)
+ dhd_os_sdlock(bus->dhd);
+
+ /* Make sure backplane clock is on, needed to generate F2 interrupt */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ if (bus->clkstate != CLK_AVAIL) {
+ DHD_ERROR(("%s: clock state is wrong. state = %d\n", __FUNCTION__, bus->clkstate));
+ ret = -1;
+ goto exit;
+ }
+
+
+ /* Force clocks on backplane to be sure F2 interrupt propagates */
+ saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (!err) {
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
+ }
+ if (err) {
+ DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
+ ret = -1;
+ goto exit;
+ }
+
+ /* Enable function 2 (frame transfers) */
+ W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
+ &bus->regs->tosbmailboxdata, retries);
+ enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
+
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
+
+ /* Give the dongle some time to do its thing and set IOR2 */
+ dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
+
+ ready = 0;
+ while (ready != enable && !dhd_timeout_expired(&tmo))
+ ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
+
+ DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
+ __FUNCTION__, enable, ready, tmo.elapsed));
+
+
+ /* If F2 successfully enabled, set core and enable interrupts */
+ if (ready == enable) {
+ /* Make sure we're talking to the core. */
+ if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
+ bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
+ ASSERT(bus->regs != NULL);
+
+ /* Set up the interrupt mask and enable interrupts */
+ bus->hostintmask = HOSTINTMASK;
+ /* corerev 4 could use the newer interrupt logic to detect the frames */
+ if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) &&
+ (bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) {
+ bus->hostintmask &= ~I_HMB_FRAME_IND;
+ bus->hostintmask |= I_XMTDATA_AVAIL;
+ }
+ W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
+
+ if (bus->sih->buscorerev < 15) {
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
+ (uint8)watermark, &err);
+ }
+
+ /* Set bus state according to enable result */
+ dhdp->busstate = DHD_BUS_DATA;
+
+ /* bcmsdh_intr_unmask(bus->sdh); */
+
+ bus->intdis = FALSE;
+ if (bus->intr) {
+ DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
+ bcmsdh_intr_enable(bus->sdh);
+ } else {
+ DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
+ bcmsdh_intr_disable(bus->sdh);
+ }
+
+ }
+
+
+ else {
+ /* Disable F2 again */
+ enable = SDIO_FUNC_ENABLE_1;
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
+ }
+
+ if (dhdsdio_sr_cap(bus)) {
+ dhdsdio_sr_init(bus);
+ /* Masking the chip active interrupt permanantly */
+ bus->hostintmask &= ~I_CHIPACTIVE;
+ W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
+ DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n",
+ __FUNCTION__, bus->hostintmask));
+ }
+ else
+ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
+
+ /* If we didn't come up, turn off backplane clock */
+ if (dhdp->busstate != DHD_BUS_DATA)
+ dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+
+
+exit:
+ if (enforce_mutex)
+ dhd_os_sdunlock(bus->dhd);
+
+ return ret;
+}
+
+static void
+dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
+{
+ bcmsdh_info_t *sdh = bus->sdh;
+ sdpcmd_regs_t *regs = bus->regs;
+ uint retries = 0;
+ uint16 lastrbc;
+ uint8 hi, lo;
+ int err;
+
+ DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__,
+ (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")));
+
+ if (!KSO_ENAB(bus)) {
+ DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
+ return;
+ }
+
+ if (abort) {
+ bcmsdh_abort(sdh, SDIO_FUNC_2);
+ }
+
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err);
+ if (err) {
+ DHD_ERROR(("%s: SBSDIO_FUNC1_FRAMECTRL cmd err\n", __FUNCTION__));
+ goto fail;
+ }
+ bus->f1regdata++;
+
+ /* Wait until the packet has been flushed (device/FIFO stable) */
+ for (lastrbc = retries = 0xffff; retries > 0; retries--) {
+ hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL);
+ lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, &err);
+ if (err) {
+ DHD_ERROR(("%s: SBSDIO_FUNC1_RFAMEBCLO cmd err\n", __FUNCTION__));
+ goto fail;
+ }
+
+ bus->f1regdata += 2;
+
+ if ((hi == 0) && (lo == 0))
+ break;
+
+ if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
+ DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n",
+ __FUNCTION__, lastrbc, ((hi << 8) + lo)));
+ }
+ lastrbc = (hi << 8) + lo;
+ }
+
+ if (!retries) {
+ DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc));
+ } else {
+ DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)));
+ }
+
+ if (rtx) {
+ bus->rxrtx++;
+ W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
+ bus->f1regdata++;
+ if (retries <= retry_limit) {
+ bus->rxskip = TRUE;
+ }
+ }
+
+ /* Clear partial in any case */
+ bus->nextlen = 0;
+
+fail:
+ /* If we can't reach the device, signal failure */
+ if (err || bcmsdh_regfail(sdh))
+ bus->dhd->busstate = DHD_BUS_DOWN;
+}
+
+static void
+dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff)
+{
+ bcmsdh_info_t *sdh = bus->sdh;
+ uint rdlen, pad;
+
+ int sdret;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* Control data already received in aligned rxctl */
+ if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
+ goto gotpkt;
+
+ ASSERT(bus->rxbuf);
+ /* Set rxctl for frame (w/optional alignment) */
+ bus->rxctl = bus->rxbuf;
+ if (dhd_alignctl) {
+ bus->rxctl += firstread;
+ if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
+ bus->rxctl += (DHD_SDALIGN - pad);
+ bus->rxctl -= firstread;
+ }
+ ASSERT(bus->rxctl >= bus->rxbuf);
+
+ /* Copy the already-read portion over */
+ bcopy(hdr, bus->rxctl, firstread);
+ if (len <= firstread)
+ goto gotpkt;
+
+ /* Copy the full data pkt in gSPI case and process ioctl. */
+ if (bus->bus == SPI_BUS) {
+ bcopy(hdr, bus->rxctl, len);
+ goto gotpkt;
+ }
+
+ /* Raise rdlen to next SDIO block to avoid tail command */
+ rdlen = len - firstread;
+ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
+ pad = bus->blocksize - (rdlen % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+ ((len + pad) < bus->dhd->maxctl))
+ rdlen += pad;
+ } else if (rdlen % DHD_SDALIGN) {
+ rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+ }
+
+ /* Satisfy length-alignment requirements */
+ if (forcealign && (rdlen & (ALIGNMENT - 1)))
+ rdlen = ROUNDUP(rdlen, ALIGNMENT);
+
+ /* Drop if the read is too big or it exceeds our maximum */
+ if ((rdlen + firstread) > bus->dhd->maxctl) {
+ DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
+ __FUNCTION__, rdlen, bus->dhd->maxctl));
+ bus->dhd->rx_errors++;
+ dhdsdio_rxfail(bus, FALSE, FALSE);
+ goto done;
+ }
+
+ if ((len - doff) > bus->dhd->maxctl) {
+ DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
+ __FUNCTION__, len, (len - doff), bus->dhd->maxctl));
+ bus->dhd->rx_errors++; bus->rx_toolong++;
+ dhdsdio_rxfail(bus, FALSE, FALSE);
+ goto done;
+ }
+
+
+ /* Read remainder of frame body into the rxctl buffer */
+ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
+ (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
+ bus->f2rxdata++;
+ ASSERT(sdret != BCME_PENDING);
+
+ /* Control frame failures need retransmission */
+ if (sdret < 0) {
+ DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret));
+ bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
+ dhdsdio_rxfail(bus, TRUE, TRUE);
+ goto done;
+ }
+
+gotpkt:
+
+#ifdef DHD_DEBUG
+ if (DHD_BYTES_ON() && DHD_CTL_ON()) {
+ prhex("RxCtrl", bus->rxctl, len);
+ }
+#endif
+
+ /* Point to valid data and indicate its length */
+ bus->rxctl += doff;
+ bus->rxlen = len - doff;
+
+done:
+ /* Awake any waiters */
+ dhd_os_ioctl_resp_wake(bus->dhd);
+}
+int
+dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len,
+ void **pkt, uint32 *pkt_count);
+
+static uint8
+dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
+{
+ uint16 dlen, totlen;
+ uint8 *dptr, num = 0;
+
+ uint16 sublen, check;
+ void *pfirst, *plast, *pnext;
+ void * list_tail[DHD_MAX_IFS] = { NULL };
+ void * list_head[DHD_MAX_IFS] = { NULL };
+ uint8 idx;
+ osl_t *osh = bus->dhd->osh;
+
+ int errcode;
+ uint8 chan, seq, doff, sfdoff;
+ uint8 txmax;
+ uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
+ uint reorder_info_len;
+
+ int ifidx = 0;
+ bool usechain = bus->use_rxchain;
+
+ /* If packets, issue read(s) and send up packet chain */
+ /* Return sequence numbers consumed? */
+
+ DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom));
+
+ /* If there's a descriptor, generate the packet chain */
+ if (bus->glomd) {
+ dhd_os_sdlock_rxq(bus->dhd);
+
+ pfirst = plast = pnext = NULL;
+ dlen = (uint16)PKTLEN(osh, bus->glomd);
+ dptr = PKTDATA(osh, bus->glomd);
+ if (!dlen || (dlen & 1)) {
+ DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n",
+ __FUNCTION__, dlen));
+ dlen = 0;
+ }
+
+ for (totlen = num = 0; dlen; num++) {
+ /* Get (and move past) next length */
+ sublen = ltoh16_ua(dptr);
+ dlen -= sizeof(uint16);
+ dptr += sizeof(uint16);
+ if ((sublen < SDPCM_HDRLEN) ||
+ ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
+ DHD_ERROR(("%s: descriptor len %d bad: %d\n",
+ __FUNCTION__, num, sublen));
+ pnext = NULL;
+ break;
+ }
+ if (sublen % DHD_SDALIGN) {
+ DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
+ __FUNCTION__, sublen, DHD_SDALIGN));
+ usechain = FALSE;
+ }
+ totlen += sublen;
+
+ /* For last frame, adjust read len so total is a block multiple */
+ if (!dlen) {
+ sublen += (ROUNDUP(totlen, bus->blocksize) - totlen);
+ totlen = ROUNDUP(totlen, bus->blocksize);
+ }
+
+ /* Allocate/chain packet for next subframe */
+ if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) {
+ DHD_ERROR(("%s: PKTGET failed, num %d len %d\n",
+ __FUNCTION__, num, sublen));
+ break;
+ }
+ ASSERT(!PKTLINK(pnext));
+ if (!pfirst) {
+ ASSERT(!plast);
+ pfirst = plast = pnext;
+ } else {
+ ASSERT(plast);
+ PKTSETNEXT(osh, plast, pnext);
+ plast = pnext;
+ }
+
+ /* Adhere to start alignment requirements */
+ PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
+ }
+
+ /* If all allocations succeeded, save packet chain in bus structure */
+ if (pnext) {
+ DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
+ __FUNCTION__, totlen, num));
+ if (DHD_GLOM_ON() && bus->nextlen) {
+ if (totlen != bus->nextlen) {
+ DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
+ "rxseq %d\n", __FUNCTION__, bus->nextlen,
+ totlen, rxseq));
+ }
+ }
+ bus->glom = pfirst;
+ pfirst = pnext = NULL;
+ } else {
+ if (pfirst)
+ PKTFREE(osh, pfirst, FALSE);
+ bus->glom = NULL;
+ num = 0;
+ }
+
+ /* Done with descriptor packet */
+ PKTFREE(osh, bus->glomd, FALSE);
+ bus->glomd = NULL;
+ bus->nextlen = 0;
+
+ dhd_os_sdunlock_rxq(bus->dhd);
+ }
+
+ /* Ok -- either we just generated a packet chain, or had one from before */
+ if (bus->glom) {
+ if (DHD_GLOM_ON()) {
+ DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__));
+ for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) {
+ DHD_GLOM((" %p: %p len 0x%04x (%d)\n",
+ pnext, (uint8*)PKTDATA(osh, pnext),
+ PKTLEN(osh, pnext), PKTLEN(osh, pnext)));
+ }
+ }
+
+ pfirst = bus->glom;
+ dlen = (uint16)pkttotlen(osh, pfirst);
+
+ /* Do an SDIO read for the superframe. Configurable iovar to
+ * read directly into the chained packet, or allocate a large
+ * packet and and copy into the chain.
+ */
+ if (usechain) {
+ errcode = dhd_bcmsdh_recv_buf(bus,
+ bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
+ F2SYNC, (uint8*)PKTDATA(osh, pfirst),
+ dlen, pfirst, NULL, NULL);
+ } else if (bus->dataptr) {
+ errcode = dhd_bcmsdh_recv_buf(bus,
+ bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
+ F2SYNC, bus->dataptr,
+ dlen, NULL, NULL, NULL);
+ sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr);
+ if (sublen != dlen) {
+ DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
+ __FUNCTION__, dlen, sublen));
+ errcode = -1;
+ }
+ pnext = NULL;
+ } else {
+ DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
+ errcode = -1;
+ }
+ bus->f2rxdata++;
+ ASSERT(errcode != BCME_PENDING);
+
+ /* On failure, kill the superframe, allow a couple retries */
+ if (errcode < 0) {
+ DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
+ __FUNCTION__, dlen, errcode));
+ bus->dhd->rx_errors++;
+
+ if (bus->glomerr++ < 3) {
+ dhdsdio_rxfail(bus, TRUE, TRUE);
+ } else {
+ bus->glomerr = 0;
+ dhdsdio_rxfail(bus, TRUE, FALSE);
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE(osh, bus->glom, FALSE);
+ dhd_os_sdunlock_rxq(bus->dhd);
+ bus->rxglomfail++;
+ bus->glom = NULL;
+ }
+ return 0;
+ }
+
+#ifdef DHD_DEBUG
+ if (DHD_GLOM_ON()) {
+ prhex("SUPERFRAME", PKTDATA(osh, pfirst),
+ MIN(PKTLEN(osh, pfirst), 48));
+ }
+#endif
+
+
+ /* Validate the superframe header */
+ dptr = (uint8 *)PKTDATA(osh, pfirst);
+ sublen = ltoh16_ua(dptr);
+ check = ltoh16_ua(dptr + sizeof(uint16));
+
+ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
+ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
+ bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+ DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
+ __FUNCTION__, bus->nextlen, seq));
+ bus->nextlen = 0;
+ }
+ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+ txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+
+ errcode = 0;
+ if ((uint16)~(sublen^check)) {
+ DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
+ __FUNCTION__, sublen, check));
+ errcode = -1;
+ } else if (ROUNDUP(sublen, bus->blocksize) != dlen) {
+ DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
+ __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen));
+ errcode = -1;
+ } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) {
+ DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__,
+ SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])));
+ errcode = -1;
+ } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
+ DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__));
+ errcode = -1;
+ } else if ((doff < SDPCM_HDRLEN) ||
+ (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) {
+ DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
+ __FUNCTION__, doff, sublen, PKTLEN(osh, pfirst),
+ SDPCM_HDRLEN));
+ errcode = -1;
+ }
+
+ /* Check sequence number of superframe SW header */
+ if (rxseq != seq) {
+ DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
+ __FUNCTION__, seq, rxseq));
+ bus->rx_badseq++;
+ rxseq = seq;
+ }
+
+ /* Check window for sanity */
+ if ((uint8)(txmax - bus->tx_seq) > 0x70) {
+ DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
+ __FUNCTION__, txmax, bus->tx_seq));
+ txmax = bus->tx_max;
+ }
+ bus->tx_max = txmax;
+
+ /* Remove superframe header, remember offset */
+ PKTPULL(osh, pfirst, doff);
+ sfdoff = doff;
+
+ /* Validate all the subframe headers */
+ for (num = 0, pnext = pfirst; pnext && !errcode;
+ num++, pnext = PKTNEXT(osh, pnext)) {
+ dptr = (uint8 *)PKTDATA(osh, pnext);
+ dlen = (uint16)PKTLEN(osh, pnext);
+ sublen = ltoh16_ua(dptr);
+ check = ltoh16_ua(dptr + sizeof(uint16));
+ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
+ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+#ifdef DHD_DEBUG
+ if (DHD_GLOM_ON()) {
+ prhex("subframe", dptr, 32);
+ }
+#endif
+
+ if ((uint16)~(sublen^check)) {
+ DHD_ERROR(("%s (subframe %d): HW hdr error: "
+ "len/check 0x%04x/0x%04x\n",
+ __FUNCTION__, num, sublen, check));
+ errcode = -1;
+ } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
+ DHD_ERROR(("%s (subframe %d): length mismatch: "
+ "len 0x%04x, expect 0x%04x\n",
+ __FUNCTION__, num, sublen, dlen));
+ errcode = -1;
+ } else if ((chan != SDPCM_DATA_CHANNEL) &&
+ (chan != SDPCM_EVENT_CHANNEL)) {
+ DHD_ERROR(("%s (subframe %d): bad channel %d\n",
+ __FUNCTION__, num, chan));
+ errcode = -1;
+ } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
+ DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
+ __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN));
+ errcode = -1;
+ }
+ }
+
+ if (errcode) {
+ /* Terminate frame on error, request a couple retries */
+ if (bus->glomerr++ < 3) {
+ /* Restore superframe header space */
+ PKTPUSH(osh, pfirst, sfdoff);
+ dhdsdio_rxfail(bus, TRUE, TRUE);
+ } else {
+ bus->glomerr = 0;
+ dhdsdio_rxfail(bus, TRUE, FALSE);
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE(osh, bus->glom, FALSE);
+ dhd_os_sdunlock_rxq(bus->dhd);
+ bus->rxglomfail++;
+ bus->glom = NULL;
+ }
+ bus->nextlen = 0;
+ return 0;
+ }
+
+ /* Basic SD framing looks ok - process each packet (header) */
+ bus->glom = NULL;
+ plast = NULL;
+
+ dhd_os_sdlock_rxq(bus->dhd);
+ for (num = 0; pfirst; rxseq++, pfirst = pnext) {
+ pnext = PKTNEXT(osh, pfirst);
+ PKTSETNEXT(osh, pfirst, NULL);
+
+ dptr = (uint8 *)PKTDATA(osh, pfirst);
+ sublen = ltoh16_ua(dptr);
+ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
+ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
+ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+
+ DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
+ __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst),
+ PKTLEN(osh, pfirst), sublen, chan, seq));
+
+ ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL));
+
+ if (rxseq != seq) {
+ DHD_GLOM(("%s: rx_seq %d, expected %d\n",
+ __FUNCTION__, seq, rxseq));
+ bus->rx_badseq++;
+ rxseq = seq;
+ }
+
+#ifdef DHD_DEBUG
+ if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+ prhex("Rx Subframe Data", dptr, dlen);
+ }
+#endif
+
+ PKTSETLEN(osh, pfirst, sublen);
+ PKTPULL(osh, pfirst, doff);
+
+ reorder_info_len = sizeof(reorder_info_buf);
+
+ if (PKTLEN(osh, pfirst) == 0) {
+ PKTFREE(bus->dhd->osh, pfirst, FALSE);
+ continue;
+ } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf,
+ &reorder_info_len) != 0) {
+ DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
+ bus->dhd->rx_errors++;
+ PKTFREE(osh, pfirst, FALSE);
+ continue;
+ }
+ if (reorder_info_len) {
+ uint32 free_buf_count;
+ void *ppfirst;
+
+ ppfirst = pfirst;
+ /* Reordering info from the firmware */
+ dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf,
+ reorder_info_len, &ppfirst, &free_buf_count);
+
+ if (free_buf_count == 0) {
+ continue;
+ }
+ else {
+ void *temp;
+
+ /* go to the end of the chain and attach the pnext there */
+ temp = ppfirst;
+ while (PKTNEXT(osh, temp) != NULL) {
+ temp = PKTNEXT(osh, temp);
+ }
+ pfirst = temp;
+ if (list_tail[ifidx] == NULL)
+ list_head[ifidx] = ppfirst;
+ else
+ PKTSETNEXT(osh, list_tail[ifidx], ppfirst);
+ list_tail[ifidx] = pfirst;
+ }
+
+ num += (uint8)free_buf_count;
+ }
+ else {
+ /* this packet will go up, link back into chain and count it */
+
+ if (list_tail[ifidx] == NULL) {
+ list_head[ifidx] = list_tail[ifidx] = pfirst;
+ }
+ else {
+ PKTSETNEXT(osh, list_tail[ifidx], pfirst);
+ list_tail[ifidx] = pfirst;
+ }
+ num++;
+ }
+#ifdef DHD_DEBUG
+ if (DHD_GLOM_ON()) {
+ DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
+ __FUNCTION__, num, pfirst,
+ PKTDATA(osh, pfirst), PKTLEN(osh, pfirst),
+ PKTNEXT(osh, pfirst), PKTLINK(pfirst)));
+ prhex("", (uint8 *)PKTDATA(osh, pfirst),
+ MIN(PKTLEN(osh, pfirst), 32));
+ }
+#endif /* DHD_DEBUG */
+ }
+ dhd_os_sdunlock_rxq(bus->dhd);
+
+ for (idx = 0; idx < DHD_MAX_IFS; idx++) {
+ if (list_head[idx]) {
+ void *temp;
+ uint8 cnt = 0;
+ temp = list_head[idx];
+ do {
+ temp = PKTNEXT(osh, temp);
+ cnt++;
+ } while (temp);
+ if (cnt) {
+ dhd_os_sdunlock(bus->dhd);
+ dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0);
+ dhd_os_sdlock(bus->dhd);
+ }
+ }
+ }
+ bus->rxglomframes++;
+ bus->rxglompkts += num;
+ }
+ return num;
+}
+
+
+#ifdef SDHOST3
+static bool
+dhdsdio_pr94636_WAR(dhd_bus_t *bus)
+{
+ uint cd = 0;
+ uint ld = 0;
+ int bcmerror = 0;
+ uint32 l_data[5];
+ uint32 l_addr = (0x18002200 & SBSDIO_SB_OFT_ADDR_MASK);
+
+ /* Read 20 bytes from 0x18002200
+ * the sdiod Tx DMA registers address on AI Backplane.
+ */
+ if ((bcmerror = bcmsdh_rwdata(bus->sdh, FALSE, l_addr, (uint8 *)&l_data[0], 20))) {
+ DHD_ERROR(("%s: bcmsdh_rwdata failed\n", __FUNCTION__));
+ return FALSE;
+ }
+ ld = l_data[1];
+ ld = ld & 0x00001fff;
+ cd = l_data[4];
+ cd = cd & 0x00001fff;
+ if (cd == ld)
+ return TRUE;
+ else
+ return FALSE;
+}
+#endif /* SDHOST3 */
+/* Return TRUE if there may be more frames to read */
+static uint
+dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
+{
+ osl_t *osh = bus->dhd->osh;
+ bcmsdh_info_t *sdh = bus->sdh;
+
+ uint16 len, check; /* Extracted hardware header fields */
+ uint8 chan, seq, doff; /* Extracted software header fields */
+ uint8 fcbits; /* Extracted fcbits from software header */
+ uint8 delta;
+
+ void *pkt; /* Packet for event or data frames */
+ uint16 pad; /* Number of pad bytes to read */
+ uint16 rdlen; /* Total number of bytes to read */
+ uint8 rxseq; /* Next sequence number to expect */
+ uint rxleft = 0; /* Remaining number of frames allowed */
+ int sdret; /* Return code from bcmsdh calls */
+ uint8 txmax; /* Maximum tx sequence offered */
+ bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
+ uint8 *rxbuf;
+ int ifidx = 0;
+ uint rxcount = 0; /* Total frames read */
+ uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
+ uint reorder_info_len;
+ uint pkt_count;
+
+#if defined(DHD_DEBUG) || defined(SDTEST)
+ bool sdtest = FALSE; /* To limit message spew from test mode */
+#endif
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ bus->readframes = TRUE;
+
+ if (!KSO_ENAB(bus)) {
+ DHD_ERROR(("%s: KSO off\n", __FUNCTION__));
+ bus->readframes = FALSE;
+ return 0;
+ }
+
+ ASSERT(maxframes);
+
+#ifdef SDTEST
+ /* Allow pktgen to override maxframes */
+ if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
+ maxframes = bus->pktgen_count;
+ sdtest = TRUE;
+ }
+#endif
+
+ /* Not finished unless we encounter no more frames indication */
+ *finished = FALSE;
+
+
+ for (rxseq = bus->rx_seq, rxleft = maxframes;
+ !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
+ rxseq++, rxleft--) {
+#ifdef DHDTCPACK_SUP_DBG
+ if (bus->dhd->tcpack_sup_mode != TCPACK_SUP_DELAYTX) {
+ if (bus->dotxinrx == FALSE)
+ DHD_ERROR(("%s %d: dotxinrx FALSE with tcpack_sub_mode %d\n",
+ __FUNCTION__, __LINE__, bus->dhd->tcpack_sup_mode));
+ }
+#ifdef DEBUG_COUNTER
+ else if (pktq_mlen(&bus->txq, ~bus->flowcontrol) > 0) {
+ tack_tbl.cnt[bus->dotxinrx ? 6 : 7]++;
+ }
+#endif /* DEBUG_COUNTER */
+#endif /* DHDTCPACK_SUP_DBG */
+ /* tx more to improve rx performance */
+ if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
+ dhdsdio_sendpendctl(bus);
+ } else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
+ !bus->fcstate && DATAOK(bus) &&
+ (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
+ dhdsdio_sendfromq(bus, dhd_txbound);
+#ifdef DHDTCPACK_SUPPRESS
+ /* In TCPACK_SUP_DELAYTX mode, do txinrx only if
+ * 1. Any DATA packet to TX
+ * 2. TCPACK to TCPDATA PSH packets.
+ * in bus txq.
+ */
+ bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ?
+ FALSE : TRUE;
+#endif
+ }
+
+ /* Handle glomming separately */
+ if (bus->glom || bus->glomd) {
+ uint8 cnt;
+ DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
+ __FUNCTION__, bus->glomd, bus->glom));
+ cnt = dhdsdio_rxglom(bus, rxseq);
+ DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
+ rxseq += cnt - 1;
+ rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
+ continue;
+ }
+
+ /* Try doing single read if we can */
+ if (dhd_readahead && bus->nextlen) {
+ uint16 nextlen = bus->nextlen;
+ bus->nextlen = 0;
+
+ if (bus->bus == SPI_BUS) {
+ rdlen = len = nextlen;
+ }
+ else {
+ rdlen = len = nextlen << 4;
+
+ /* Pad read to blocksize for efficiency */
+ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
+ pad = bus->blocksize - (rdlen % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+ ((rdlen + pad + firstread) < MAX_RX_DATASZ))
+ rdlen += pad;
+ } else if (rdlen % DHD_SDALIGN) {
+ rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+ }
+ }
+
+ /* We use bus->rxctl buffer in WinXP for initial control pkt receives.
+ * Later we use buffer-poll for data as well as control packets.
+ * This is required because dhd receives full frame in gSPI unlike SDIO.
+ * After the frame is received we have to distinguish whether it is data
+ * or non-data frame.
+ */
+ /* Allocate a packet buffer */
+ dhd_os_sdlock_rxq(bus->dhd);
+ if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) {
+ if (bus->bus == SPI_BUS) {
+ bus->usebufpool = FALSE;
+ bus->rxctl = bus->rxbuf;
+ if (dhd_alignctl) {
+ bus->rxctl += firstread;
+ if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
+ bus->rxctl += (DHD_SDALIGN - pad);
+ bus->rxctl -= firstread;
+ }
+ ASSERT(bus->rxctl >= bus->rxbuf);
+ rxbuf = bus->rxctl;
+ /* Read the entire frame */
+ sdret = dhd_bcmsdh_recv_buf(bus,
+ bcmsdh_cur_sbwad(sdh),
+ SDIO_FUNC_2,
+ F2SYNC, rxbuf, rdlen,
+ NULL, NULL, NULL);
+ bus->f2rxdata++;
+ ASSERT(sdret != BCME_PENDING);
+
+
+ /* Control frame failures need retransmission */
+ if (sdret < 0) {
+ DHD_ERROR(("%s: read %d control bytes failed: %d\n",
+ __FUNCTION__, rdlen, sdret));
+ /* dhd.rx_ctlerrs is higher level */
+ bus->rxc_errors++;
+ dhd_os_sdunlock_rxq(bus->dhd);
+ dhdsdio_rxfail(bus, TRUE,
+ (bus->bus == SPI_BUS) ? FALSE : TRUE);
+ continue;
+ }
+ } else {
+ /* Give up on data, request rtx of events */
+ DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d "
+ "expected rxseq %d\n",
+ __FUNCTION__, len, rdlen, rxseq));
+ /* Just go try again w/normal header read */
+ dhd_os_sdunlock_rxq(bus->dhd);
+ continue;
+ }
+ } else {
+ if (bus->bus == SPI_BUS)
+ bus->usebufpool = TRUE;
+
+ ASSERT(!PKTLINK(pkt));
+ PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
+ rxbuf = (uint8 *)PKTDATA(osh, pkt);
+ /* Read the entire frame */
+ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
+ SDIO_FUNC_2,
+ F2SYNC, rxbuf, rdlen,
+ pkt, NULL, NULL);
+ bus->f2rxdata++;
+ ASSERT(sdret != BCME_PENDING);
+
+ if (sdret < 0) {
+ DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
+ __FUNCTION__, rdlen, sdret));
+ PKTFREE(bus->dhd->osh, pkt, FALSE);
+ bus->dhd->rx_errors++;
+ dhd_os_sdunlock_rxq(bus->dhd);
+ /* Force retry w/normal header read. Don't attempt NAK for
+ * gSPI
+ */
+ dhdsdio_rxfail(bus, TRUE,
+ (bus->bus == SPI_BUS) ? FALSE : TRUE);
+ continue;
+ }
+ }
+ dhd_os_sdunlock_rxq(bus->dhd);
+
+ /* Now check the header */
+ bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
+
+ /* Extract hardware header fields */
+ len = ltoh16_ua(bus->rxhdr);
+ check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
+
+ /* All zeros means readahead info was bad */
+ if (!(len|check)) {
+ DHD_INFO(("%s (nextlen): read zeros in HW header???\n",
+ __FUNCTION__));
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE2();
+ dhd_os_sdunlock_rxq(bus->dhd);
+ GSPI_PR55150_BAILOUT;
+ continue;
+ }
+
+ /* Validate check bytes */
+ if ((uint16)~(len^check)) {
+ DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check"
+ " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen,
+ len, check));
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE2();
+ dhd_os_sdunlock_rxq(bus->dhd);
+ bus->rx_badhdr++;
+ dhdsdio_rxfail(bus, FALSE, FALSE);
+ GSPI_PR55150_BAILOUT;
+ continue;
+ }
+
+ /* Validate frame length */
+ if (len < SDPCM_HDRLEN) {
+ DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n",
+ __FUNCTION__, len));
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE2();
+ dhd_os_sdunlock_rxq(bus->dhd);
+ GSPI_PR55150_BAILOUT;
+ continue;
+ }
+
+ /* Check for consistency with readahead info */
+ len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
+ if (len_consistent) {
+ /* Mismatch, force retry w/normal header (may be >4K) */
+ DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
+ "expected rxseq %d\n",
+ __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq));
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE2();
+ dhd_os_sdunlock_rxq(bus->dhd);
+ dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE);
+ GSPI_PR55150_BAILOUT;
+ continue;
+ }
+
+
+ /* Extract software header fields */
+ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+
+ bus->nextlen =
+ bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+ DHD_INFO(("%s (nextlen): got frame w/nextlen too large"
+ " (%d), seq %d\n", __FUNCTION__, bus->nextlen,
+ seq));
+ bus->nextlen = 0;
+ }
+
+ bus->dhd->rx_readahead_cnt ++;
+ /* Handle Flow Control */
+ fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+
+ delta = 0;
+ if (~bus->flowcontrol & fcbits) {
+ bus->fc_xoff++;
+ delta = 1;
+ }
+ if (bus->flowcontrol & ~fcbits) {
+ bus->fc_xon++;
+ delta = 1;
+ }
+
+ if (delta) {
+ bus->fc_rcvd++;
+ bus->flowcontrol = fcbits;
+ }
+
+ /* Check and update sequence number */
+ if (rxseq != seq) {
+ DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n",
+ __FUNCTION__, seq, rxseq));
+ bus->rx_badseq++;
+ rxseq = seq;
+ }
+
+ /* Check window for sanity */
+ if ((uint8)(txmax - bus->tx_seq) > 0x70) {
+ DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
+ __FUNCTION__, txmax, bus->tx_seq));
+ txmax = bus->tx_max;
+ }
+ bus->tx_max = txmax;
+
+#ifdef DHD_DEBUG
+ if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+ prhex("Rx Data", rxbuf, len);
+ } else if (DHD_HDRS_ON()) {
+ prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
+ }
+#endif
+
+ if (chan == SDPCM_CONTROL_CHANNEL) {
+ if (bus->bus == SPI_BUS) {
+ dhdsdio_read_control(bus, rxbuf, len, doff);
+ if (bus->usebufpool) {
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE(bus->dhd->osh, pkt, FALSE);
+ dhd_os_sdunlock_rxq(bus->dhd);
+ }
+ continue;
+ } else {
+ DHD_ERROR(("%s (nextlen): readahead on control"
+ " packet %d?\n", __FUNCTION__, seq));
+ /* Force retry w/normal header read */
+ bus->nextlen = 0;
+ dhdsdio_rxfail(bus, FALSE, TRUE);
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE2();
+ dhd_os_sdunlock_rxq(bus->dhd);
+ continue;
+ }
+ }
+
+ if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
+ DHD_ERROR(("Received %d bytes on %d channel. Running out of "
+ "rx pktbuf's or not yet malloced.\n", len, chan));
+ continue;
+ }
+
+ /* Validate data offset */
+ if ((doff < SDPCM_HDRLEN) || (doff > len)) {
+ DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
+ __FUNCTION__, doff, len, SDPCM_HDRLEN));
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE2();
+ dhd_os_sdunlock_rxq(bus->dhd);
+ ASSERT(0);
+ dhdsdio_rxfail(bus, FALSE, FALSE);
+ continue;
+ }
+
+ /* All done with this one -- now deliver the packet */
+ goto deliver;
+ }
+ /* gSPI frames should not be handled in fractions */
+ if (bus->bus == SPI_BUS) {
+ break;
+ }
+#ifdef SDHOST3
+ if (((((uint16)bus->sih->chip) == BCM4324_CHIP_ID) && (bus->sih->chiprev <= 1)) ||
+ (((uint16)bus->sih->chip) == BCM43340_CHIP_ID) ||
+ (((uint16)bus->sih->chip) == BCM43341_CHIP_ID) ||
+ (((uint16)bus->sih->chip) == BCM4334_CHIP_ID)) {
+ if (dhdsdio_pr94636_WAR(bus) == TRUE) {
+ *finished = TRUE;
+ break;
+ }
+ }
+#endif /* SDHOST3 */
+
+ /* Read frame header (hardware and software) */
+ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
+ bus->rxhdr, firstread, NULL, NULL, NULL);
+ bus->f2rxhdrs++;
+ ASSERT(sdret != BCME_PENDING);
+
+ if (sdret < 0) {
+ DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret));
+ bus->rx_hdrfail++;
+ dhdsdio_rxfail(bus, TRUE, TRUE);
+ continue;
+ }
+
+#ifdef DHD_DEBUG
+ if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
+ prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
+ }
+#endif
+
+ /* Extract hardware header fields */
+ len = ltoh16_ua(bus->rxhdr);
+ check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
+
+ /* All zeros means no more frames */
+ if (!(len|check)) {
+ *finished = TRUE;
+ break;
+ }
+
+ /* Validate check bytes */
+ if ((uint16)~(len^check)) {
+ DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n",
+ __FUNCTION__, len, check));
+ bus->rx_badhdr++;
+ dhdsdio_rxfail(bus, FALSE, FALSE);
+ continue;
+ }
+
+ /* Validate frame length */
+ if (len < SDPCM_HDRLEN) {
+ DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len));
+ continue;
+ }
+
+ /* Extract software header fields */
+ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+
+ /* Validate data offset */
+ if ((doff < SDPCM_HDRLEN) || (doff > len)) {
+ DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n",
+ __FUNCTION__, doff, len, SDPCM_HDRLEN, seq));
+ bus->rx_badhdr++;
+ ASSERT(0);
+ dhdsdio_rxfail(bus, FALSE, FALSE);
+ continue;
+ }
+
+ /* Save the readahead length if there is one */
+ bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+ DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n",
+ __FUNCTION__, bus->nextlen, seq));
+ bus->nextlen = 0;
+ }
+
+ /* Handle Flow Control */
+ fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+
+ delta = 0;
+ if (~bus->flowcontrol & fcbits) {
+ bus->fc_xoff++;
+ delta = 1;
+ }
+ if (bus->flowcontrol & ~fcbits) {
+ bus->fc_xon++;
+ delta = 1;
+ }
+
+ if (delta) {
+ bus->fc_rcvd++;
+ bus->flowcontrol = fcbits;
+ }
+
+ /* Check and update sequence number */
+ if (rxseq != seq) {
+ DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq));
+ bus->rx_badseq++;
+ rxseq = seq;
+ }
+
+ /* Check window for sanity */
+ if ((uint8)(txmax - bus->tx_seq) > 0x70) {
+ DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
+ __FUNCTION__, txmax, bus->tx_seq));
+ txmax = bus->tx_max;
+ }
+ bus->tx_max = txmax;
+
+ /* Call a separate function for control frames */
+ if (chan == SDPCM_CONTROL_CHANNEL) {
+ dhdsdio_read_control(bus, bus->rxhdr, len, doff);
+ continue;
+ }
+
+ ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) ||
+ (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL));
+
+ /* Length to read */
+ rdlen = (len > firstread) ? (len - firstread) : 0;
+
+ /* May pad read to blocksize for efficiency */
+ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
+ pad = bus->blocksize - (rdlen % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+ ((rdlen + pad + firstread) < MAX_RX_DATASZ))
+ rdlen += pad;
+ } else if (rdlen % DHD_SDALIGN) {
+ rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+ }
+
+ /* Satisfy length-alignment requirements */
+ if (forcealign && (rdlen & (ALIGNMENT - 1)))
+ rdlen = ROUNDUP(rdlen, ALIGNMENT);
+
+ if ((rdlen + firstread) > MAX_RX_DATASZ) {
+ /* Too long -- skip this frame */
+ DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen));
+ bus->dhd->rx_errors++; bus->rx_toolong++;
+ dhdsdio_rxfail(bus, FALSE, FALSE);
+ continue;
+ }
+
+ dhd_os_sdlock_rxq(bus->dhd);
+ if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) {
+ /* Give up on data, request rtx of events */
+ DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n",
+ __FUNCTION__, rdlen, chan));
+ bus->dhd->rx_dropped++;
+ dhd_os_sdunlock_rxq(bus->dhd);
+ dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan));
+ continue;
+ }
+ dhd_os_sdunlock_rxq(bus->dhd);
+
+ ASSERT(!PKTLINK(pkt));
+
+ /* Leave room for what we already read, and align remainder */
+ ASSERT(firstread < (PKTLEN(osh, pkt)));
+ PKTPULL(osh, pkt, firstread);
+ PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
+
+ /* Read the remaining frame data */
+ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
+ ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL);
+ bus->f2rxdata++;
+ ASSERT(sdret != BCME_PENDING);
+
+ if (sdret < 0) {
+ DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen,
+ ((chan == SDPCM_EVENT_CHANNEL) ? "event" :
+ ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret));
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE(bus->dhd->osh, pkt, FALSE);
+ dhd_os_sdunlock_rxq(bus->dhd);
+ bus->dhd->rx_errors++;
+ dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan));
+ continue;
+ }
+
+ /* Copy the already-read portion */
+ PKTPUSH(osh, pkt, firstread);
+ bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread);
+
+#ifdef DHD_DEBUG
+ if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+ prhex("Rx Data", PKTDATA(osh, pkt), len);
+ }
+#endif
+
+deliver:
+ /* Save superframe descriptor and allocate packet frame */
+ if (chan == SDPCM_GLOM_CHANNEL) {
+ if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
+ DHD_GLOM(("%s: got glom descriptor, %d bytes:\n",
+ __FUNCTION__, len));
+#ifdef DHD_DEBUG
+ if (DHD_GLOM_ON()) {
+ prhex("Glom Data", PKTDATA(osh, pkt), len);
+ }
+#endif
+ PKTSETLEN(osh, pkt, len);
+ ASSERT(doff == SDPCM_HDRLEN);
+ PKTPULL(osh, pkt, SDPCM_HDRLEN);
+ bus->glomd = pkt;
+ } else {
+ DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__));
+ dhdsdio_rxfail(bus, FALSE, FALSE);
+ }
+ continue;
+ }
+
+ /* Fill in packet len and prio, deliver upward */
+ PKTSETLEN(osh, pkt, len);
+ PKTPULL(osh, pkt, doff);
+
+#ifdef SDTEST
+ /* Test channel packets are processed separately */
+ if (chan == SDPCM_TEST_CHANNEL) {
+ dhdsdio_testrcv(bus, pkt, seq);
+ continue;
+ }
+#endif /* SDTEST */
+
+ if (PKTLEN(osh, pkt) == 0) {
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE(bus->dhd->osh, pkt, FALSE);
+ dhd_os_sdunlock_rxq(bus->dhd);
+ continue;
+ } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt, reorder_info_buf,
+ &reorder_info_len) != 0) {
+ DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
+ dhd_os_sdlock_rxq(bus->dhd);
+ PKTFREE(bus->dhd->osh, pkt, FALSE);
+ dhd_os_sdunlock_rxq(bus->dhd);
+ bus->dhd->rx_errors++;
+ continue;
+ }
+ if (reorder_info_len) {
+ /* Reordering info from the firmware */
+ dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len,
+ &pkt, &pkt_count);
+ if (pkt_count == 0)
+ continue;
+ }
+ else
+ pkt_count = 1;
+
+ /* Unlock during rx call */
+ dhd_os_sdunlock(bus->dhd);
+ dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan);
+ dhd_os_sdlock(bus->dhd);
+ }
+ rxcount = maxframes - rxleft;
+#ifdef DHD_DEBUG
+ /* Message if we hit the limit */
+ if (!rxleft && !sdtest)
+ DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes));
+ else
+#endif /* DHD_DEBUG */
+ DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount));
+ /* Back off rxseq if awaiting rtx, update rx_seq */
+ if (bus->rxskip)
+ rxseq--;
+ bus->rx_seq = rxseq;
+
+ if (bus->reqbussleep)
+ {
+ dhdsdio_bussleep(bus, TRUE);
+ bus->reqbussleep = FALSE;
+ }
+ bus->readframes = FALSE;
+
+ return rxcount;
+}
+
+static uint32
+dhdsdio_hostmail(dhd_bus_t *bus)
+{
+ sdpcmd_regs_t *regs = bus->regs;
+ uint32 intstatus = 0;
+ uint32 hmb_data;
+ uint8 fcbits;
+ uint retries = 0;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* Read mailbox data and ack that we did so */
+ R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
+ if (retries <= retry_limit)
+ W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
+ bus->f1regdata += 2;
+
+ /* Dongle recomposed rx frames, accept them again */
+ if (hmb_data & HMB_DATA_NAKHANDLED) {
+ DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq));
+ if (!bus->rxskip) {
+ DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__));
+ }
+ bus->rxskip = FALSE;
+ intstatus |= FRAME_AVAIL_MASK(bus);
+ }
+
+ /*
+ * DEVREADY does not occur with gSPI.
+ */
+ if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
+ bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT;
+ if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
+ DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n",
+ bus->sdpcm_ver, SDPCM_PROT_VERSION));
+ else
+ DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver));
+ /* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */
+ if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
+ (bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_1)) {
+ uint32 val;
+
+ val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
+ val &= ~CC_XMTDATAAVAIL_MODE;
+ val |= CC_XMTDATAAVAIL_CTRL;
+ W_REG(bus->dhd->osh, &bus->regs->corecontrol, val);
+
+ val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
+ }
+
+#ifdef DHD_DEBUG
+ /* Retrieve console state address now that firmware should have updated it */
+ {
+ sdpcm_shared_t shared;
+ if (dhdsdio_readshared(bus, &shared) == 0)
+ bus->console_addr = shared.console_addr;
+ }
+#endif /* DHD_DEBUG */
+ }
+
+ /*
+ * Flow Control has been moved into the RX headers and this out of band
+ * method isn't used any more. Leave this here for possibly remaining backward
+ * compatible with older dongles
+ */
+ if (hmb_data & HMB_DATA_FC) {
+ fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT;
+
+ if (fcbits & ~bus->flowcontrol)
+ bus->fc_xoff++;
+ if (bus->flowcontrol & ~fcbits)
+ bus->fc_xon++;
+
+ bus->fc_rcvd++;
+ bus->flowcontrol = fcbits;
+ }
+
+#ifdef DHD_DEBUG
+ /* At least print a message if FW halted */
+ if (hmb_data & HMB_DATA_FWHALT) {
+ DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED : set BUS DOWN\n"));
+ dhdsdio_checkdied(bus, NULL, 0);
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ }
+#endif /* DHD_DEBUG */
+
+ /* Shouldn't be any others */
+ if (hmb_data & ~(HMB_DATA_DEVREADY |
+ HMB_DATA_FWHALT |
+ HMB_DATA_NAKHANDLED |
+ HMB_DATA_FC |
+ HMB_DATA_FWREADY |
+ HMB_DATA_FCDATA_MASK |
+ HMB_DATA_VERSION_MASK)) {
+ DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
+ }
+
+ return intstatus;
+}
+
+static bool
+dhdsdio_dpc(dhd_bus_t *bus)
+{
+ bcmsdh_info_t *sdh = bus->sdh;
+ sdpcmd_regs_t *regs = bus->regs;
+ uint32 intstatus, newstatus = 0;
+ uint retries = 0;
+ uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
+ uint txlimit = dhd_txbound; /* Tx frames to send before resched */
+ uint framecnt = 0; /* Temporary counter of tx/rx frames */
+ bool rxdone = TRUE; /* Flag for no more read data */
+ bool resched = FALSE; /* Flag indicating resched wanted */
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ dhd_os_sdlock(bus->dhd);
+
+ if (bus->dhd->busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
+ bus->intstatus = 0;
+ dhd_os_sdunlock(bus->dhd);
+ return 0;
+ }
+
+ /* Start with leftover status bits */
+ intstatus = bus->intstatus;
+
+ if (!SLPAUTO_ENAB(bus) && !KSO_ENAB(bus)) {
+ DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
+ goto exit;
+ }
+
+ /* If waiting for HTAVAIL, check status */
+ if (!SLPAUTO_ENAB(bus) && (bus->clkstate == CLK_PENDING)) {
+ int err;
+ uint8 clkctl, devctl = 0;
+
+#ifdef DHD_DEBUG
+ /* Check for inconsistent device control */
+ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+ if (err) {
+ DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ } else {
+ ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
+ }
+#endif /* DHD_DEBUG */
+
+ /* Read CSR, if clock on switch to AVAIL, else ignore */
+ clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (err) {
+ DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err));
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ }
+
+ DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl));
+
+ if (SBSDIO_HTAV(clkctl)) {
+ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+ if (err) {
+ DHD_ERROR(("%s: error reading DEVCTL: %d\n",
+ __FUNCTION__, err));
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ }
+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
+ if (err) {
+ DHD_ERROR(("%s: error writing DEVCTL: %d\n",
+ __FUNCTION__, err));
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ }
+ bus->clkstate = CLK_AVAIL;
+ } else {
+ goto clkwait;
+ }
+ }
+
+ BUS_WAKE(bus);
+
+ /* Make sure backplane clock is on */
+ dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
+ if (bus->clkstate != CLK_AVAIL)
+ goto clkwait;
+
+ /* Pending interrupt indicates new device status */
+ if (bus->ipend) {
+ bus->ipend = FALSE;
+ R_SDREG(newstatus, &regs->intstatus, retries);
+ bus->f1regdata++;
+ if (bcmsdh_regfail(bus->sdh))
+ newstatus = 0;
+ newstatus &= bus->hostintmask;
+ bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
+ if (newstatus) {
+ bus->f1regdata++;
+ if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) &&
+ (newstatus == I_XMTDATA_AVAIL)) {
+ }
+ else
+ W_SDREG(newstatus, &regs->intstatus, retries);
+ }
+ }
+
+ /* Merge new bits with previous */
+ intstatus |= newstatus;
+ bus->intstatus = 0;
+
+ /* Handle flow-control change: read new state in case our ack
+ * crossed another change interrupt. If change still set, assume
+ * FC ON for safety, let next loop through do the debounce.
+ */
+ if (intstatus & I_HMB_FC_CHANGE) {
+ intstatus &= ~I_HMB_FC_CHANGE;
+ W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
+ R_SDREG(newstatus, &regs->intstatus, retries);
+ bus->f1regdata += 2;
+ bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
+ intstatus |= (newstatus & bus->hostintmask);
+ }
+
+ /* Just being here means nothing more to do for chipactive */
+ if (intstatus & I_CHIPACTIVE) {
+ /* ASSERT(bus->clkstate == CLK_AVAIL); */
+ intstatus &= ~I_CHIPACTIVE;
+ }
+
+ /* Handle host mailbox indication */
+ if (intstatus & I_HMB_HOST_INT) {
+ intstatus &= ~I_HMB_HOST_INT;
+ intstatus |= dhdsdio_hostmail(bus);
+ }
+
+ /* Generally don't ask for these, can get CRC errors... */
+ if (intstatus & I_WR_OOSYNC) {
+ DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
+ intstatus &= ~I_WR_OOSYNC;
+ }
+
+ if (intstatus & I_RD_OOSYNC) {
+ DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
+ intstatus &= ~I_RD_OOSYNC;
+ }
+
+ if (intstatus & I_SBINT) {
+ DHD_ERROR(("Dongle reports SBINT\n"));
+ intstatus &= ~I_SBINT;
+ }
+
+ /* Would be active due to wake-wlan in gSPI */
+ if (intstatus & I_CHIPACTIVE) {
+ DHD_INFO(("Dongle reports CHIPACTIVE\n"));
+ intstatus &= ~I_CHIPACTIVE;
+ }
+
+ if (intstatus & I_HMB_FC_STATE) {
+ DHD_INFO(("Dongle reports HMB_FC_STATE\n"));
+ intstatus &= ~I_HMB_FC_STATE;
+ }
+
+ /* Ignore frame indications if rxskip is set */
+ if (bus->rxskip) {
+ intstatus &= ~FRAME_AVAIL_MASK(bus);
+ }
+
+ /* On frame indication, read available frames */
+ if (PKT_AVAILABLE(bus, intstatus)) {
+ framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
+ if (rxdone || bus->rxskip)
+ intstatus &= ~FRAME_AVAIL_MASK(bus);
+ rxlimit -= MIN(framecnt, rxlimit);
+ }
+
+ /* Keep still-pending events for next scheduling */
+ bus->intstatus = intstatus;
+
+clkwait:
+ /* Re-enable interrupts to detect new device events (mailbox, rx frame)
+ * or clock availability. (Allows tx loop to check ipend if desired.)
+ * (Unless register access seems hosed, as we may not be able to ACK...)
+ */
+ if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
+ DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
+ __FUNCTION__, rxdone, framecnt));
+ bus->intdis = FALSE;
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(bus->dhd->oob_disable)) {
+ bcmsdh_oob_intr_set(bus->sdh, TRUE);
+ }
+#endif /* defined(OOB_INTR_ONLY) */
+ bcmsdh_intr_enable(sdh);
+ }
+
+#if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
+ OOB_PARAM_IF(!(bus->dhd->oob_disable)) {
+ /* In case of SW-OOB(using edge trigger),
+ * Check interrupt status in the dongle again after enable irq on the host.
+ * and rechedule dpc if interrupt is pended in the dongle.
+ * There is a chance to miss OOB interrupt while irq is disabled on the host.
+ * No need to do this with HW-OOB(level trigger)
+ */
+ R_SDREG(newstatus, &regs->intstatus, retries);
+ if (bcmsdh_regfail(bus->sdh))
+ newstatus = 0;
+ if (newstatus & bus->hostintmask) {
+ bus->ipend = TRUE;
+ resched = TRUE;
+ }
+ }
+#endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */
+
+#ifdef PROP_TXSTATUS
+ dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE);
+#endif
+
+ if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
+ dhdsdio_sendpendctl(bus);
+
+ /* Send queued frames (limit 1 if rx may still be pending) */
+ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
+ pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
+ framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax);
+ framecnt = dhdsdio_sendfromq(bus, framecnt);
+ txlimit -= framecnt;
+ }
+ /* Resched the DPC if ctrl cmd is pending on bus credit */
+ if (bus->ctrl_frame_stat)
+ resched = TRUE;
+
+ /* Resched if events or tx frames are pending, else await next interrupt */
+ /* On failed register access, all bets are off: no resched or interrupts */
+ if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
+ if ((bus->sih && bus->sih->buscorerev >= 12) && !(dhdsdio_sleepcsr_get(bus) &
+ SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
+ /* Bus failed because of KSO */
+ DHD_ERROR(("%s: Bus failed due to KSO\n", __FUNCTION__));
+ bus->kso = FALSE;
+ } else {
+ DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n",
+ __FUNCTION__));
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ bus->intstatus = 0;
+ }
+ } else if (bus->clkstate == CLK_PENDING) {
+ /* Awaiting I_CHIPACTIVE; don't resched */
+ } else if (bus->intstatus || bus->ipend ||
+ (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
+ PKT_AVAILABLE(bus, bus->intstatus)) { /* Read multiple frames */
+ resched = TRUE;
+ }
+
+ bus->dpc_sched = resched;
+
+ /* If we're done for now, turn off clock request. */
+ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING)) {
+ bus->activity = FALSE;
+ dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+ }
+
+exit:
+
+ if (!resched && dhd_dpcpoll) {
+ if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) {
+ resched = TRUE;
+ }
+ }
+
+ dhd_os_sdunlock(bus->dhd);
+ return resched;
+}
+
+bool
+dhd_bus_dpc(struct dhd_bus *bus)
+{
+ bool resched;
+
+ /* Call the DPC directly. */
+ DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
+ resched = dhdsdio_dpc(bus);
+
+ return resched;
+}
+
+void
+dhdsdio_isr(void *arg)
+{
+ dhd_bus_t *bus = (dhd_bus_t*)arg;
+ bcmsdh_info_t *sdh;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (!bus) {
+ DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
+ return;
+ }
+ sdh = bus->sdh;
+
+ if (bus->dhd->busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
+ return;
+ }
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ /* Count the interrupt call */
+ bus->intrcount++;
+ bus->ipend = TRUE;
+
+ /* Shouldn't get this interrupt if we're sleeping? */
+ if (!SLPAUTO_ENAB(bus)) {
+ if (bus->sleeping) {
+ DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
+ return;
+ } else if (!KSO_ENAB(bus)) {
+ DHD_ERROR(("ISR in devsleep 1\n"));
+ }
+ }
+
+ /* Disable additional interrupts (is this needed now)? */
+ if (bus->intr) {
+ DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
+ } else {
+ DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
+ }
+
+ bcmsdh_intr_disable(sdh);
+ bus->intdis = TRUE;
+
+#if defined(SDIO_ISR_THREAD) || defined(OOB_PARAM)
+ OOB_PARAM_IF(bus->dhd->oob_disable) {
+ DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
+ DHD_OS_WAKE_LOCK(bus->dhd);
+ dhdsdio_dpc(bus);
+ DHD_OS_WAKE_UNLOCK(bus->dhd);
+ } OOB_PARAM_ELSE()
+#endif /* defined(SDIO_ISR_THREAD) || defined(OOB_PARAM) */
+#if !defined(SDIO_ISR_THREAD) || defined(OOB_PARAM)
+ {
+ bus->dpc_sched = TRUE;
+ dhd_sched_dpc(bus->dhd);
+ }
+#endif /* !defined(SDIO_ISR_THREAD) || defined(OOB_PARAM) */
+
+
+}
+
+#ifdef SDTEST
+static void
+dhdsdio_pktgen_init(dhd_bus_t *bus)
+{
+ /* Default to specified length, or full range */
+ if (dhd_pktgen_len) {
+ bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN);
+ bus->pktgen_minlen = bus->pktgen_maxlen;
+ } else {
+ bus->pktgen_maxlen = MAX_PKTGEN_LEN;
+ bus->pktgen_minlen = 0;
+ }
+ bus->pktgen_len = (uint16)bus->pktgen_minlen;
+
+ /* Default to per-watchdog burst with 10s print time */
+ bus->pktgen_freq = 1;
+ bus->pktgen_print = dhd_watchdog_ms ? (10000 / dhd_watchdog_ms) : 0;
+ bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
+
+ /* Default to echo mode */
+ bus->pktgen_mode = DHD_PKTGEN_ECHO;
+ bus->pktgen_stop = 1;
+}
+
+static void
+dhdsdio_pktgen(dhd_bus_t *bus)
+{
+ void *pkt;
+ uint8 *data;
+ uint pktcount;
+ uint fillbyte;
+ osl_t *osh = bus->dhd->osh;
+ uint16 len;
+ ulong time_lapse;
+ uint sent_pkts;
+ uint rcvd_pkts;
+
+ /* Display current count if appropriate */
+ if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
+ bus->pktgen_ptick = 0;
+ printf("%s: send attempts %d, rcvd %d, errors %d\n",
+ __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
+
+ /* Print throughput stats only for constant length packet runs */
+ if (bus->pktgen_minlen == bus->pktgen_maxlen) {
+ time_lapse = jiffies - bus->pktgen_prev_time;
+ bus->pktgen_prev_time = jiffies;
+ sent_pkts = bus->pktgen_sent - bus->pktgen_prev_sent;
+ bus->pktgen_prev_sent = bus->pktgen_sent;
+ rcvd_pkts = bus->pktgen_rcvd - bus->pktgen_prev_rcvd;
+ bus->pktgen_prev_rcvd = bus->pktgen_rcvd;
+
+ printf("%s: Tx Throughput %d kbps, Rx Throughput %d kbps\n",
+ __FUNCTION__,
+ (sent_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8,
+ (rcvd_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8);
+ }
+ }
+
+ /* For recv mode, just make sure dongle has started sending */
+ if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
+ if (bus->pktgen_rcv_state == PKTGEN_RCV_IDLE) {
+ bus->pktgen_rcv_state = PKTGEN_RCV_ONGOING;
+ dhdsdio_sdtest_set(bus, bus->pktgen_total);
+ }
+ return;
+ }
+
+ /* Otherwise, generate or request the specified number of packets */
+ for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
+ /* Stop if total has been reached */
+ if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) {
+ bus->pktgen_count = 0;
+ break;
+ }
+
+ /* Allocate an appropriate-sized packet */
+ if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
+ len = SDPCM_TEST_PKT_CNT_FLD_LEN;
+ } else {
+ len = bus->pktgen_len;
+ }
+ if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
+ TRUE))) {;
+ DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
+ break;
+ }
+ PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
+ data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
+
+ /* Write test header cmd and extra based on mode */
+ switch (bus->pktgen_mode) {
+ case DHD_PKTGEN_ECHO:
+ *data++ = SDPCM_TEST_ECHOREQ;
+ *data++ = (uint8)bus->pktgen_sent;
+ break;
+
+ case DHD_PKTGEN_SEND:
+ *data++ = SDPCM_TEST_DISCARD;
+ *data++ = (uint8)bus->pktgen_sent;
+ break;
+
+ case DHD_PKTGEN_RXBURST:
+ *data++ = SDPCM_TEST_BURST;
+ *data++ = (uint8)bus->pktgen_count; /* Just for backward compatability */
+ break;
+
+ default:
+ DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode));
+ PKTFREE(osh, pkt, TRUE);
+ bus->pktgen_count = 0;
+ return;
+ }
+
+ /* Write test header length field */
+ *data++ = (bus->pktgen_len >> 0);
+ *data++ = (bus->pktgen_len >> 8);
+
+ /* Write frame count in a 4 byte field adjucent to SDPCM test header for
+ * burst mode
+ */
+ if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
+ *data++ = (uint8)(bus->pktgen_count >> 0);
+ *data++ = (uint8)(bus->pktgen_count >> 8);
+ *data++ = (uint8)(bus->pktgen_count >> 16);
+ *data++ = (uint8)(bus->pktgen_count >> 24);
+ } else {
+
+ /* Then fill in the remainder -- N/A for burst */
+ for (fillbyte = 0; fillbyte < len; fillbyte++)
+ *data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent);
+ }
+
+#ifdef DHD_DEBUG
+ if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+ data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
+ prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN);
+ }
+#endif
+
+ /* Send it */
+ if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) {
+ bus->pktgen_fail++;
+ if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail)
+ bus->pktgen_count = 0;
+ }
+ bus->pktgen_sent++;
+
+ /* Bump length if not fixed, wrap at max */
+ if (++bus->pktgen_len > bus->pktgen_maxlen)
+ bus->pktgen_len = (uint16)bus->pktgen_minlen;
+
+ /* Special case for burst mode: just send one request! */
+ if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
+ break;
+ }
+}
+
+static void
+dhdsdio_sdtest_set(dhd_bus_t *bus, uint count)
+{
+ void *pkt;
+ uint8 *data;
+ osl_t *osh = bus->dhd->osh;
+
+ /* Allocate the packet */
+ if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
+ SDPCM_TEST_PKT_CNT_FLD_LEN + DHD_SDALIGN, TRUE))) {
+ DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
+ return;
+ }
+ PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
+ SDPCM_TEST_PKT_CNT_FLD_LEN), DHD_SDALIGN);
+ data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
+
+ /* Fill in the test header */
+ *data++ = SDPCM_TEST_SEND;
+ *data++ = (count > 0)?TRUE:FALSE;
+ *data++ = (bus->pktgen_maxlen >> 0);
+ *data++ = (bus->pktgen_maxlen >> 8);
+ *data++ = (uint8)(count >> 0);
+ *data++ = (uint8)(count >> 8);
+ *data++ = (uint8)(count >> 16);
+ *data++ = (uint8)(count >> 24);
+
+ /* Send it */
+ if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK)
+ bus->pktgen_fail++;
+}
+
+
+static void
+dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq)
+{
+ osl_t *osh = bus->dhd->osh;
+ uint8 *data;
+ uint pktlen;
+
+ uint8 cmd;
+ uint8 extra;
+ uint16 len;
+ uint16 offset;
+
+ /* Check for min length */
+ if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) {
+ DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen));
+ PKTFREE(osh, pkt, FALSE);
+ return;
+ }
+
+ /* Extract header fields */
+ data = PKTDATA(osh, pkt);
+ cmd = *data++;
+ extra = *data++;
+ len = *data++; len += *data++ << 8;
+ DHD_TRACE(("%s:cmd:%d, xtra:%d,len:%d\n", __FUNCTION__, cmd, extra, len));
+ /* Check length for relevant commands */
+ if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) {
+ if (pktlen != len + SDPCM_TEST_HDRLEN) {
+ DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d"
+ " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
+ PKTFREE(osh, pkt, FALSE);
+ return;
+ }
+ }
+
+ /* Process as per command */
+ switch (cmd) {
+ case SDPCM_TEST_ECHOREQ:
+ /* Rx->Tx turnaround ok (even on NDIS w/current implementation) */
+ *(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP;
+ if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) == BCME_OK) {
+ bus->pktgen_sent++;
+ } else {
+ bus->pktgen_fail++;
+ PKTFREE(osh, pkt, FALSE);
+ }
+ bus->pktgen_rcvd++;
+ break;
+
+ case SDPCM_TEST_ECHORSP:
+ if (bus->ext_loop) {
+ PKTFREE(osh, pkt, FALSE);
+ bus->pktgen_rcvd++;
+ break;
+ }
+
+ for (offset = 0; offset < len; offset++, data++) {
+ if (*data != SDPCM_TEST_FILL(offset, extra)) {
+ DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: "
+ "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
+ offset, len, SDPCM_TEST_FILL(offset, extra), *data));
+ break;
+ }
+ }
+ PKTFREE(osh, pkt, FALSE);
+ bus->pktgen_rcvd++;
+ break;
+
+ case SDPCM_TEST_DISCARD:
+ {
+ int i = 0;
+ uint8 *prn = data;
+ uint8 testval = extra;
+ for (i = 0; i < len; i++) {
+ if (*prn != testval) {
+ DHD_ERROR(("DIErr@Pkt#:%d,Ix:%d, expected:0x%x, got:0x%x\n",
+ i, bus->pktgen_rcvd_rcvsession, testval, *prn));
+ prn++; testval++;
+ }
+ }
+ }
+ PKTFREE(osh, pkt, FALSE);
+ bus->pktgen_rcvd++;
+ break;
+
+ case SDPCM_TEST_BURST:
+ case SDPCM_TEST_SEND:
+ default:
+ DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d"
+ " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
+ PKTFREE(osh, pkt, FALSE);
+ break;
+ }
+
+ /* For recv mode, stop at limit (and tell dongle to stop sending) */
+ if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
+ if (bus->pktgen_rcv_state != PKTGEN_RCV_IDLE) {
+ bus->pktgen_rcvd_rcvsession++;
+
+ if (bus->pktgen_total &&
+ (bus->pktgen_rcvd_rcvsession >= bus->pktgen_total)) {
+ bus->pktgen_count = 0;
+ DHD_ERROR(("Pktgen:rcv test complete!\n"));
+ bus->pktgen_rcv_state = PKTGEN_RCV_IDLE;
+ dhdsdio_sdtest_set(bus, FALSE);
+ bus->pktgen_rcvd_rcvsession = 0;
+ }
+ }
+ }
+}
+#endif /* SDTEST */
+
+int dhd_bus_oob_intr_register(dhd_pub_t *dhdp)
+{
+ int err = 0;
+
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(dhdp->oob_disable)) {
+ err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus);
+ }
+#endif
+ return err;
+}
+
+void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp)
+{
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(dhdp->oob_disable)) {
+ bcmsdh_oob_intr_unregister(dhdp->bus->sdh);
+ }
+#endif
+}
+
+void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable)
+{
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(dhdp->oob_disable)) {
+ bcmsdh_oob_intr_set(dhdp->bus->sdh, enable);
+ }
+#endif
+}
+
+void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub)
+{
+ bcmsdh_dev_pm_stay_awake(dhdpub->bus->sdh);
+}
+
+void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub)
+{
+ bcmsdh_dev_relax(dhdpub->bus->sdh);
+}
+
+bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub)
+{
+ bool enabled = FALSE;
+
+ enabled = bcmsdh_dev_pm_enabled(dhdpub->bus->sdh);
+ return enabled;
+}
+
+extern bool
+dhd_bus_watchdog(dhd_pub_t *dhdp)
+{
+ dhd_bus_t *bus;
+
+ DHD_TIMER(("%s: Enter\n", __FUNCTION__));
+
+ bus = dhdp->bus;
+
+ if (bus->dhd->dongle_reset)
+ return FALSE;
+
+ if (bus->dhd->hang_was_sent) {
+ dhd_os_wd_timer(bus->dhd, 0);
+ return FALSE;
+ }
+
+ /* Ignore the timer if simulating bus down */
+ if (!SLPAUTO_ENAB(bus) && bus->sleeping)
+ return FALSE;
+
+ if (dhdp->busstate == DHD_BUS_DOWN)
+ return FALSE;
+
+
+#if defined(CUSTOMER_IMX)
+ if (bus->bus_wake_on_resume) {
+ BUS_WAKE(bus);
+ bus->bus_wake_on_resume = 0;
+ }
+#endif /* CUSTOMER_IMX */
+
+
+ /* Poll period: check device if appropriate. */
+ if (!SLPAUTO_ENAB(bus) && (bus->poll && (++bus->polltick >= bus->pollrate))) {
+ uint32 intstatus = 0;
+
+ /* Reset poll tick */
+ bus->polltick = 0;
+
+ /* Check device if no interrupts */
+ if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
+
+ if (!bus->dpc_sched) {
+ uint8 devpend;
+ devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
+ SDIOD_CCCR_INTPEND, NULL);
+ intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2);
+ }
+
+ /* If there is something, make like the ISR and schedule the DPC */
+ if (intstatus) {
+ bus->pollcnt++;
+ bus->ipend = TRUE;
+ if (bus->intr) {
+ bcmsdh_intr_disable(bus->sdh);
+ }
+ bus->dpc_sched = TRUE;
+ dhd_sched_dpc(bus->dhd);
+ }
+ }
+
+ /* Update interrupt tracking */
+ bus->lastintrs = bus->intrcount;
+ }
+
+#ifdef DHD_DEBUG
+ /* Poll for console output periodically */
+ if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
+ bus->console.count += dhd_watchdog_ms;
+ if (bus->console.count >= dhd_console_ms) {
+ bus->console.count -= dhd_console_ms;
+ /* Make sure backplane clock is on */
+ if (SLPAUTO_ENAB(bus))
+ dhdsdio_bussleep(bus, FALSE);
+ else
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ if (dhdsdio_readconsole(bus) < 0)
+ dhd_console_ms = 0; /* On error, stop trying */
+ }
+ }
+#endif /* DHD_DEBUG */
+
+#ifdef SDTEST
+ /* Generate packets if configured */
+ if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
+ /* Make sure backplane clock is on */
+ if (SLPAUTO_ENAB(bus))
+ dhdsdio_bussleep(bus, FALSE);
+ else
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ bus->pktgen_tick = 0;
+ dhdsdio_pktgen(bus);
+ }
+#endif
+
+ /* On idle timeout clear activity flag and/or turn off clock */
+#ifdef DHD_USE_IDLECOUNT
+ if (bus->activity)
+ bus->activity = FALSE;
+ else {
+ bus->idlecount++;
+
+ if ((bus->idletime > 0) && (bus->idlecount >= bus->idletime)) {
+ DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__));
+ if (SLPAUTO_ENAB(bus)) {
+ if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY)
+ dhd_os_wd_timer(bus->dhd, 0);
+ } else
+ dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+
+ bus->idlecount = 0;
+ }
+ }
+#else
+ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
+ if (++bus->idlecount >= bus->idletime) {
+ bus->idlecount = 0;
+ if (bus->activity) {
+ bus->activity = FALSE;
+ if (SLPAUTO_ENAB(bus)) {
+ if (!bus->readframes)
+ dhdsdio_bussleep(bus, TRUE);
+ else
+ bus->reqbussleep = TRUE;
+ }
+ else
+ dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+ }
+ }
+ }
+#endif /* DHD_USE_IDLECOUNT */
+
+ return bus->ipend;
+}
+
+#ifdef DHD_DEBUG
+extern int
+dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ uint32 addr, val;
+ int rv;
+ void *pkt;
+
+ /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+ if (bus->console_addr == 0)
+ return BCME_UNSUPPORTED;
+
+ /* Exclusive bus access */
+ dhd_os_sdlock(bus->dhd);
+
+ /* Don't allow input if dongle is in reset */
+ if (bus->dhd->dongle_reset) {
+ dhd_os_sdunlock(bus->dhd);
+ return BCME_NOTREADY;
+ }
+
+ /* Request clock to allow SDIO accesses */
+ BUS_WAKE(bus);
+ /* No pend allowed since txpkt is called later, ht clk has to be on */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ /* Zero cbuf_index */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx);
+ val = htol32(0);
+ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+ goto done;
+
+ /* Write message into cbuf */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf);
+ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
+ goto done;
+
+ /* Write length into vcons_in */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in);
+ val = htol32(msglen);
+ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+ goto done;
+
+ /* Bump dongle by sending an empty packet on the event channel.
+ * sdpcm_sendup (RX) checks for virtual console input.
+ */
+ if ((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL)
+ rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
+
+done:
+ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ bus->activity = FALSE;
+ dhdsdio_clkctl(bus, CLK_NONE, TRUE);
+ }
+
+ dhd_os_sdunlock(bus->dhd);
+
+ return rv;
+}
+#endif /* DHD_DEBUG */
+
+#ifdef DHD_DEBUG
+static void
+dhd_dump_cis(uint fn, uint8 *cis)
+{
+ uint byte, tag, tdata;
+ DHD_INFO(("Function %d CIS:\n", fn));
+
+ for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
+ if ((byte % 16) == 0)
+ DHD_INFO((" "));
+ DHD_INFO(("%02x ", cis[byte]));
+ if ((byte % 16) == 15)
+ DHD_INFO(("\n"));
+ if (!tdata--) {
+ tag = cis[byte];
+ if (tag == 0xff)
+ break;
+ else if (!tag)
+ tdata = 0;
+ else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
+ tdata = cis[byte + 1] + 1;
+ else
+ DHD_INFO(("]"));
+ }
+ }
+ if ((byte % 16) != 15)
+ DHD_INFO(("\n"));
+}
+#endif /* DHD_DEBUG */
+
+static bool
+dhdsdio_chipmatch(uint16 chipid)
+{
+ if (chipid == BCM4325_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4329_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4315_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4319_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4336_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4330_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43237_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43362_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4314_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43242_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43340_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43341_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43143_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43342_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4334_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43239_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4324_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4335_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4339_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43349_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4345_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4350_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4354_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM4356_CHIP_ID)
+ return TRUE;
+ if (chipid == BCM43430_CHIP_ID)
+ return TRUE;
+ return FALSE;
+}
+
+static void *
+dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
+ uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
+{
+ int ret;
+ dhd_bus_t *bus;
+
+
+ /* Init global variables at run-time, not as part of the declaration.
+ * This is required to support init/de-init of the driver. Initialization
+ * of globals as part of the declaration results in non-deterministic
+ * behavior since the value of the globals may be different on the
+ * first time that the driver is initialized vs subsequent initializations.
+ */
+ dhd_txbound = DHD_TXBOUND;
+ dhd_rxbound = DHD_RXBOUND;
+ dhd_alignctl = TRUE;
+ sd1idle = TRUE;
+ dhd_readahead = TRUE;
+ retrydata = FALSE;
+
+ dhd_doflow = FALSE;
+ dhd_dongle_ramsize = 0;
+ dhd_txminmax = DHD_TXMINMAX;
+
+ forcealign = TRUE;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid));
+
+ /* We make assumptions about address window mappings */
+ ASSERT((uintptr)regsva == SI_ENUM_BASE);
+
+ /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
+ * means early parse could fail, so here we should get either an ID
+ * we recognize OR (-1) indicating we must request power first.
+ */
+ /* Check the Vendor ID */
+ switch (venid) {
+ case 0x0000:
+ case VENDOR_BROADCOM:
+ break;
+ default:
+ DHD_ERROR(("%s: unknown vendor: 0x%04x\n",
+ __FUNCTION__, venid));
+ goto forcereturn;
+ }
+
+ /* Check the Device ID and make sure it's one that we support */
+ switch (devid) {
+ case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */
+ case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */
+ case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */
+ DHD_INFO(("%s: found 4325 Dongle\n", __FUNCTION__));
+ break;
+ case BCM4329_D11N_ID: /* 4329 802.11n dualband device */
+ case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */
+ case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */
+ case 0x4329:
+ DHD_INFO(("%s: found 4329 Dongle\n", __FUNCTION__));
+ break;
+ case BCM4315_D11DUAL_ID: /* 4315 802.11a/g id */
+ case BCM4315_D11G_ID: /* 4315 802.11g id */
+ case BCM4315_D11A_ID: /* 4315 802.11a id */
+ DHD_INFO(("%s: found 4315 Dongle\n", __FUNCTION__));
+ break;
+ case BCM4319_D11N_ID: /* 4319 802.11n id */
+ case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */
+ case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */
+ DHD_INFO(("%s: found 4319 Dongle\n", __FUNCTION__));
+ break;
+ case 0:
+ DHD_INFO(("%s: allow device id 0, will check chip internals\n",
+ __FUNCTION__));
+ break;
+
+ default:
+ DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
+ __FUNCTION__, venid, devid));
+ goto forcereturn;
+ }
+
+ if (osh == NULL) {
+ DHD_ERROR(("%s: osh is NULL!\n", __FUNCTION__));
+ goto forcereturn;
+ }
+
+ /* Allocate private bus interface state */
+ if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) {
+ DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
+ goto fail;
+ }
+ bzero(bus, sizeof(dhd_bus_t));
+ bus->sdh = sdh;
+ bus->cl_devid = (uint16)devid;
+ bus->bus = DHD_BUS;
+ bus->bus_num = bus_no;
+ bus->slot_num = slot;
+ bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
+ bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */
+
+#if defined(SUPPORT_P2P_GO_PS)
+ init_waitqueue_head(&bus->bus_sleep);
+#endif /* LINUX && (SUPPORT_P2P_GO_PS || !OEM_ANDROID) */
+
+ /* attempt to attach to the dongle */
+ if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
+ DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+ /* Attach to the dhd/OS/network interface */
+ if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) {
+ DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+ /* Allocate buffers */
+ if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
+ DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+ if (!(dhdsdio_probe_init(bus, osh, sdh))) {
+ DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+ if (bus->intr) {
+ /* Register interrupt callback, but mask it (not operational yet). */
+ DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
+ bcmsdh_intr_disable(sdh);
+ if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
+ DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
+ __FUNCTION__, ret));
+ goto fail;
+ }
+ DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
+ } else {
+ DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n",
+ __FUNCTION__));
+ }
+
+ DHD_INFO(("%s: completed!!\n", __FUNCTION__));
+
+ /* if firmware path present try to download and bring up bus */
+ bus->dhd->hang_report = TRUE;
+ if (dhd_download_fw_on_driverload) {
+ if ((ret = dhd_bus_start(bus->dhd)) != 0) {
+ DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__));
+ goto fail;
+ }
+ }
+ /* Ok, have the per-port tell the stack we're open for business */
+ if (dhd_register_if(bus->dhd, 0, TRUE) != 0) {
+ DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
+ goto fail;
+ }
+
+
+ return bus;
+
+fail:
+ dhdsdio_release(bus, osh);
+
+forcereturn:
+
+ return NULL;
+}
+
+static bool
+dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
+ uint16 devid)
+{
+ int err = 0;
+ uint8 clkctl = 0;
+
+ bus->alp_only = TRUE;
+ bus->sih = NULL;
+
+ /* Return the window to backplane enumeration space for core access */
+ if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) {
+ DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__));
+ }
+
+
+ /* Force PLL off until si_attach() programs PLL control regs */
+
+
+
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err);
+ if (!err)
+ clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+
+ if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
+ DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
+ err, DHD_INIT_CLKCTL1, clkctl));
+ goto fail;
+ }
+
+#ifdef DHD_DEBUG
+ if (DHD_INFO_ON()) {
+ uint fn, numfn;
+ uint8 *cis[SDIOD_MAX_IOFUNCS];
+ int err = 0;
+
+ numfn = bcmsdh_query_iofnum(sdh);
+ ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
+
+ /* Make sure ALP is available before trying to read CIS */
+ SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
+ !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
+
+ /* Now request ALP be put on the bus */
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ DHD_INIT_CLKCTL2, &err);
+ OSL_DELAY(65);
+
+ for (fn = 0; fn <= numfn; fn++) {
+ if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
+ DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn));
+ break;
+ }
+ bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
+
+ if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) {
+ DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err));
+ MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
+ break;
+ }
+ dhd_dump_cis(fn, cis[fn]);
+ }
+
+ while (fn-- > 0) {
+ ASSERT(cis[fn]);
+ MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
+ }
+
+ if (err) {
+ DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n"));
+ goto fail;
+ }
+ }
+#endif /* DHD_DEBUG */
+
+ /* si_attach() will provide an SI handle and scan the backplane */
+ if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh,
+ &bus->vars, &bus->varsz))) {
+ DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
+ goto fail;
+ }
+
+#ifdef DHD_DEBUG
+ DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n",
+ bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg));
+#endif /* DHD_DEBUG */
+
+
+ bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
+
+ if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) {
+ DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
+ __FUNCTION__, bus->sih->chip));
+ goto fail;
+ }
+
+ if (bus->sih->buscorerev >= 12)
+ dhdsdio_clk_kso_init(bus);
+ else
+ bus->kso = TRUE;
+
+ if (CST4330_CHIPMODE_SDIOD(bus->sih->chipst)) {
+ }
+
+ si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
+
+
+ /* Get info on the ARM and SOCRAM cores... */
+ if (!DHD_NOPMU(bus)) {
+ if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
+ (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) ||
+ (si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
+ bus->armrev = si_corerev(bus->sih);
+ } else {
+ DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
+ goto fail;
+ }
+
+ if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
+ DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
+ goto fail;
+ }
+ } else {
+ /* cr4 has a different way to find the RAM size from TCM's */
+ if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) {
+ DHD_ERROR(("%s: failed to find CR4-TCM memory!\n", __FUNCTION__));
+ goto fail;
+ }
+ /* also populate base address */
+ switch ((uint16)bus->sih->chip) {
+ case BCM4335_CHIP_ID:
+ case BCM4339_CHIP_ID:
+ case BCM43349_CHIP_ID:
+ bus->dongle_ram_base = CR4_4335_RAM_BASE;
+ break;
+ case BCM4350_CHIP_ID:
+ case BCM4354_CHIP_ID:
+ case BCM4356_CHIP_ID:
+ bus->dongle_ram_base = CR4_4350_RAM_BASE;
+ break;
+ case BCM4360_CHIP_ID:
+ bus->dongle_ram_base = CR4_4360_RAM_BASE;
+ break;
+ case BCM4345_CHIP_ID:
+ /* RAM base changed from 4345c0 (chiprev=6) onwards */
+ bus->dongle_ram_base = (bus->sih->chiprev < 6)
+ ? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
+ break;
+ default:
+ bus->dongle_ram_base = 0;
+ DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
+ __FUNCTION__, bus->dongle_ram_base));
+ }
+ }
+ bus->ramsize = bus->orig_ramsize;
+ if (dhd_dongle_ramsize)
+ dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
+
+ DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n",
+ bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base));
+
+ bus->srmemsize = si_socram_srmem_size(bus->sih);
+ }
+
+ /* ...but normally deal with the SDPCMDEV core */
+ if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) &&
+ !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) {
+ DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__));
+ goto fail;
+ }
+ bus->sdpcmrev = si_corerev(bus->sih);
+
+ /* Set core control so an SDIO reset does a backplane reset */
+ OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
+ bus->rxint_mode = SDIO_DEVICE_HMB_RXINT;
+
+ if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
+ (bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_1))
+ {
+ uint32 val;
+
+ val = R_REG(osh, &bus->regs->corecontrol);
+ val &= ~CC_XMTDATAAVAIL_MODE;
+ val |= CC_XMTDATAAVAIL_CTRL;
+ W_REG(osh, &bus->regs->corecontrol, val);
+ }
+
+
+ pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
+
+ /* Locate an appropriately-aligned portion of hdrbuf */
+ bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN);
+
+ /* Set the poll and/or interrupt flags */
+ bus->intr = (bool)dhd_intr;
+ if ((bus->poll = (bool)dhd_poll))
+ bus->pollrate = 1;
+
+ /* Setting default Glom size */
+ bus->txglomsize = SDPCM_DEFGLOM_SIZE;
+
+ return TRUE;
+
+fail:
+ if (bus->sih != NULL) {
+ si_detach(bus->sih);
+ bus->sih = NULL;
+ }
+ return FALSE;
+}
+
+static bool
+dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd->maxctl) {
+ bus->rxblen = ROUNDUP((bus->dhd->maxctl+SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
+ if (!(bus->rxbuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_RXBUF, bus->rxblen))) {
+ DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
+ __FUNCTION__, bus->rxblen));
+ goto fail;
+ }
+ }
+ /* Allocate buffer to receive glomed packet */
+ if (!(bus->databuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) {
+ DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
+ __FUNCTION__, MAX_DATA_BUF));
+ /* release rxbuf which was already located as above */
+ if (bus->rxbuf) {
+ DHD_OS_PREFREE(bus->dhd, DHD_PREALLOC_RXBUF, bus->rxbuf, bus->rxblen);
+ bus->rxbuf = NULL;
+ }
+ goto fail;
+ }
+
+ /* Align the buffer */
+ if ((uintptr)bus->databuf % DHD_SDALIGN)
+ bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN));
+ else
+ bus->dataptr = bus->databuf;
+
+ return TRUE;
+
+fail:
+ return FALSE;
+}
+
+static bool
+dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
+{
+ int32 fnum;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ bus->_srenab = FALSE;
+
+#ifdef SDTEST
+ dhdsdio_pktgen_init(bus);
+#endif /* SDTEST */
+
+ /* Disable F2 to clear any intermediate frame state on the dongle */
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
+
+ bus->dhd->busstate = DHD_BUS_DOWN;
+ bus->sleeping = FALSE;
+ bus->rxflow = FALSE;
+ bus->prev_rxlim_hit = 0;
+
+ /* Done with backplane-dependent accesses, can drop clock... */
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+
+ /* ...and initialize clock/power states */
+ bus->clkstate = CLK_SDONLY;
+ bus->idletime = (int32)dhd_idletime;
+ bus->idleclock = DHD_IDLE_ACTIVE;
+
+ /* Query the SD clock speed */
+ if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
+ &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
+ DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor"));
+ bus->sd_divisor = -1;
+ } else {
+ DHD_INFO(("%s: Initial value for %s is %d\n",
+ __FUNCTION__, "sd_divisor", bus->sd_divisor));
+ }
+
+ /* Query the SD bus mode */
+ if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
+ &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
+ DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode"));
+ bus->sd_mode = -1;
+ } else {
+ DHD_INFO(("%s: Initial value for %s is %d\n",
+ __FUNCTION__, "sd_mode", bus->sd_mode));
+ }
+
+ /* Query the F2 block size, set roundup accordingly */
+ fnum = 2;
+ if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32),
+ &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
+ bus->blocksize = 0;
+ DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
+ } else {
+ DHD_INFO(("%s: Initial value for %s is %d\n",
+ __FUNCTION__, "sd_blocksize", bus->blocksize));
+
+ dhdsdio_tune_fifoparam(bus);
+ }
+ bus->roundup = MIN(max_roundup, bus->blocksize);
+
+ if (bus->pad_pkt)
+ PKTFREE(osh, bus->pad_pkt, FALSE);
+ bus->pad_pkt = PKTGET(osh, SDIO_MAX_BLOCK_SIZE, FALSE);
+ if (bus->pad_pkt == NULL)
+ DHD_ERROR(("failed to allocate padding packet\n"));
+ else {
+ int alignment_offset = 0;
+ uintptr pktprt = (uintptr)PKTDATA(osh, bus->pad_pkt);
+ if (!(pktprt&1) && (pktprt = (pktprt % DHD_SDALIGN)))
+ PKTPUSH(osh, bus->pad_pkt, alignment_offset);
+ PKTSETNEXT(osh, bus->pad_pkt, NULL);
+ }
+
+
+ /* Query if bus module supports packet chaining, default to use if supported */
+ if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
+ &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) {
+ bus->sd_rxchain = FALSE;
+ } else {
+ DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
+ __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support")));
+ }
+ bus->use_rxchain = (bool)bus->sd_rxchain;
+ bus->txinrx_thres = CUSTOM_TXINRX_THRES;
+ /* TX first in dhdsdio_readframes() */
+ bus->dotxinrx = TRUE;
+
+ return TRUE;
+}
+
+int
+dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
+ char *pfw_path, char *pnv_path)
+{
+ int ret;
+
+ bus->fw_path = pfw_path;
+ bus->nv_path = pnv_path;
+
+ ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
+
+
+ return ret;
+}
+
+static int
+dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
+{
+ int ret;
+
+
+ DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
+ __FUNCTION__, bus->fw_path, bus->nv_path));
+ DHD_OS_WAKE_LOCK(bus->dhd);
+
+ /* Download the firmware */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ ret = _dhdsdio_download_firmware(bus);
+
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+
+ DHD_OS_WAKE_UNLOCK(bus->dhd);
+ return ret;
+}
+
+/* Detach and free everything */
+static void
+dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
+{
+ bool dongle_isolation = FALSE;
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus) {
+ ASSERT(osh);
+
+ if (bus->dhd) {
+ dongle_isolation = bus->dhd->dongle_isolation;
+ dhd_detach(bus->dhd);
+ }
+
+ /* De-register interrupt handler */
+ bcmsdh_intr_disable(bus->sdh);
+ bcmsdh_intr_dereg(bus->sdh);
+
+ if (bus->dhd) {
+ dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE);
+ dhd_free(bus->dhd);
+ bus->dhd = NULL;
+ }
+
+ dhdsdio_release_malloc(bus, osh);
+
+#ifdef DHD_DEBUG
+ if (bus->console.buf != NULL)
+ MFREE(osh, bus->console.buf, bus->console.bufsize);
+#endif
+
+ if (bus->pad_pkt)
+ PKTFREE(osh, bus->pad_pkt, FALSE);
+
+
+ MFREE(osh, bus, sizeof(dhd_bus_t));
+ }
+
+ DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
+}
+
+static void
+dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd && bus->dhd->dongle_reset)
+ return;
+
+ if (bus->rxbuf) {
+#ifndef CONFIG_DHD_USE_STATIC_BUF
+ MFREE(osh, bus->rxbuf, bus->rxblen);
+#endif
+ bus->rxctl = bus->rxbuf = NULL;
+ bus->rxlen = 0;
+ }
+
+ if (bus->databuf) {
+#ifndef CONFIG_DHD_USE_STATIC_BUF
+ MFREE(osh, bus->databuf, MAX_DATA_BUF);
+#endif
+ bus->databuf = NULL;
+ }
+
+ if (bus->vars && bus->varsz) {
+ MFREE(osh, bus->vars, bus->varsz);
+ bus->vars = NULL;
+ }
+
+}
+
+
+static void
+dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
+{
+ DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
+ bus->dhd, bus->dhd->dongle_reset));
+
+ if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
+ return;
+
+ if (bus->sih) {
+#if !defined(BCMLXSDMMC)
+ if (bus->dhd) {
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ }
+ if (KSO_ENAB(bus) && (dongle_isolation == FALSE))
+ si_watchdog(bus->sih, 4);
+#endif /* !defined(BCMLXSDMMC) */
+ if (bus->dhd) {
+ dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+ }
+ si_detach(bus->sih);
+ bus->sih = NULL;
+ if (bus->vars && bus->varsz)
+ MFREE(osh, bus->vars, bus->varsz);
+ bus->vars = NULL;
+ }
+
+ DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
+}
+
+static void
+dhdsdio_disconnect(void *ptr)
+{
+ dhd_bus_t *bus = (dhd_bus_t *)ptr;
+
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+
+
+ if (bus) {
+ ASSERT(bus->dhd);
+ dhdsdio_release(bus, bus->dhd->osh);
+ }
+
+
+
+ DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
+}
+
+static int
+dhdsdio_suspend(void *context)
+{
+ int ret = 0;
+
+ dhd_bus_t *bus = (dhd_bus_t*)context;
+#if defined(SUPPORT_P2P_GO_PS)
+ int wait_time = 0;
+
+ if (bus->idletime > 0) {
+ wait_time = 2 * (msecs_to_jiffies(bus->idletime * dhd_watchdog_ms));
+ }
+#endif /* SUPPORT_P2P_GO_PS || !OEM_ANDROID */
+ ret = dhd_os_check_wakelock(bus->dhd);
+#if defined(SUPPORT_P2P_GO_PS)
+ /* Sometimes DHD enters into suspend state when bus is still awake due
+ * to absence of wake locks on Non-Android platforms, so perform bus
+ * sleep status check using bus_sleep event to prevent dhd entering
+ * into suspend state when bus is still awake.
+ */
+ if ((!ret) && (bus->dhd->up) && (bus->dhd->op_mode != DHD_FLAG_HOSTAP_MODE)) {
+ if (wait_event_timeout(bus->bus_sleep, bus->sleeping, wait_time) == 0) {
+ if (!bus->sleeping) {
+ DHD_ERROR(("%s: cannot suspend because bus is awake\n",
+ __FUNCTION__));
+ return -EBUSY;
+ }
+ }
+ }
+#endif /* SUPPORT_P2P_GO_PS || !OEM_ANDROID */
+ return ret;
+}
+
+static int
+dhdsdio_resume(void *context)
+{
+
+#if defined(OOB_INTR_ONLY) || defined(CUSTOMER_IMX)
+ dhd_bus_t *bus = (dhd_bus_t*)context;
+#endif /* defined(OOB_INTR_ONLY)||defined(BCMSPI_ANDROID)||
+ * defined(CUSTOMER_IMX) */
+
+#if defined(OOB_INTR_ONLY)
+
+ OOB_PARAM_IF(!(bus->dhd->oob_disable)) {
+ if (dhd_os_check_if_up(bus->dhd))
+ bcmsdh_oob_intr_set(bus->sdh, TRUE);
+ }
+#endif
+
+#if defined(CUSTOMER_IMX)
+ bus->bus_wake_on_resume = 1;
+ dhd_os_wd_timer(bus->dhd, 1000);
+#endif /* CUSTOMER_IMX */
+
+ return 0;
+}
+
+
+/* Register/Unregister functions are called by the main DHD entry
+ * point (e.g. module insertion) to link with the bus driver, in
+ * order to look for or await the device.
+ */
+
+static bcmsdh_driver_t dhd_sdio = {
+ dhdsdio_probe,
+ dhdsdio_disconnect,
+ dhdsdio_suspend,
+ dhdsdio_resume
+};
+
+int
+dhd_bus_register(void)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ return bcmsdh_register(&dhd_sdio);
+}
+
+void
+dhd_bus_unregister(void)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ bcmsdh_unregister();
+}
+
+#if defined(BCMLXSDMMC)
+/* Register a dummy SDIO client driver in order to be notified of new SDIO device */
+int dhd_bus_reg_sdio_notify(void* semaphore)
+{
+ return bcmsdh_reg_sdio_notify(semaphore);
+}
+
+void dhd_bus_unreg_sdio_notify(void)
+{
+ bcmsdh_unreg_sdio_notify();
+}
+#endif /* defined(BCMLXSDMMC) */
+
+#ifdef BCMEMBEDIMAGE
+static int
+dhdsdio_download_code_array(struct dhd_bus *bus)
+{
+ int bcmerror = -1;
+ int offset = 0;
+ unsigned char *ularray = NULL;
+
+ DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__));
+
+ /* Download image */
+ while ((offset + MEMBLOCK) < sizeof(dlarray)) {
+ /* check if CR4 */
+ if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ /* if address is 0, store the reset instruction to be written in 0 */
+
+ if (offset == 0) {
+ bus->resetinstr = *(((uint32*)dlarray));
+ /* Add start of RAM address to the address given by user */
+ offset += bus->dongle_ram_base;
+ }
+ }
+
+ bcmerror = dhdsdio_membytes(bus, TRUE, offset,
+ (uint8 *) (dlarray + offset), MEMBLOCK);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, MEMBLOCK, offset));
+ goto err;
+ }
+
+ offset += MEMBLOCK;
+ }
+
+ if (offset < sizeof(dlarray)) {
+ bcmerror = dhdsdio_membytes(bus, TRUE, offset,
+ (uint8 *) (dlarray + offset), sizeof(dlarray) - offset);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
+ goto err;
+ }
+ }
+
+#ifdef DHD_DEBUG
+ /* Upload and compare the downloaded code */
+ {
+ ularray = MALLOC(bus->dhd->osh, bus->ramsize);
+ /* Upload image to verify downloaded contents. */
+ offset = 0;
+ memset(ularray, 0xaa, bus->ramsize);
+ while ((offset + MEMBLOCK) < sizeof(dlarray)) {
+ bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, MEMBLOCK, offset));
+ goto err;
+ }
+
+ offset += MEMBLOCK;
+ }
+
+ if (offset < sizeof(dlarray)) {
+ bcmerror = dhdsdio_membytes(bus, FALSE, offset,
+ ularray + offset, sizeof(dlarray) - offset);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
+ goto err;
+ }
+ }
+
+ if (memcmp(dlarray, ularray, sizeof(dlarray))) {
+ DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n",
+ __FUNCTION__, dlimagename, dlimagever, dlimagedate));
+ goto err;
+ } else
+ DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n",
+ __FUNCTION__, dlimagename, dlimagever, dlimagedate));
+
+ }
+#endif /* DHD_DEBUG */
+
+err:
+ if (ularray)
+ MFREE(bus->dhd->osh, ularray, bus->ramsize);
+ return bcmerror;
+}
+#endif /* BCMEMBEDIMAGE */
+
+static int
+dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
+{
+ int bcmerror = -1;
+ int offset = 0;
+ int len;
+ void *image = NULL;
+ uint8 *memblock = NULL, *memptr;
+
+ DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
+
+ image = dhd_os_open_image(pfw_path);
+ if (image == NULL)
+ goto err;
+
+ memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
+ if (memblock == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
+ goto err;
+ }
+ if ((uint32)(uintptr)memblock % DHD_SDALIGN)
+ memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
+
+ /* Download image */
+ while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, image))) {
+ if (len < 0) {
+ DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
+ bcmerror = BCME_ERROR;
+ goto err;
+ }
+ /* check if CR4 */
+ if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ /* if address is 0, store the reset instruction to be written in 0 */
+
+ if (offset == 0) {
+ bus->resetinstr = *(((uint32*)memptr));
+ /* Add start of RAM address to the address given by user */
+ offset += bus->dongle_ram_base;
+ }
+ }
+
+ bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, MEMBLOCK, offset));
+ goto err;
+ }
+
+ offset += MEMBLOCK;
+ }
+
+err:
+ if (memblock)
+ MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN);
+
+ if (image)
+ dhd_os_close_image(image);
+
+ return bcmerror;
+}
+
+/*
+ EXAMPLE: nvram_array
+ nvram_arry format:
+ name=value
+ Use carriage return at the end of each assignment, and an empty string with
+ carriage return at the end of array.
+
+ For example:
+ unsigned char nvram_array[] = {"name1=value1\n", "name2=value2\n", "\n"};
+ Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx.
+
+ Search "EXAMPLE: nvram_array" to see how the array is activated.
+*/
+
+void
+dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params)
+{
+ bus->nvram_params = nvram_params;
+}
+
+static int
+dhdsdio_download_nvram(struct dhd_bus *bus)
+{
+ int bcmerror = -1;
+ uint len;
+ void * image = NULL;
+ char * memblock = NULL;
+ char *bufp;
+ char *pnv_path;
+ bool nvram_file_exists;
+
+ pnv_path = bus->nv_path;
+
+ nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
+ if (!nvram_file_exists && (bus->nvram_params == NULL))
+ return (0);
+
+ if (nvram_file_exists) {
+ image = dhd_os_open_image(pnv_path);
+ if (image == NULL)
+ goto err;
+ }
+
+ memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE);
+ if (memblock == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
+ __FUNCTION__, MAX_NVRAMBUF_SIZE));
+ goto err;
+ }
+
+ /* Download variables */
+ if (nvram_file_exists) {
+ len = dhd_os_get_image_block(memblock, MAX_NVRAMBUF_SIZE, image);
+ }
+ else {
+ len = strlen(bus->nvram_params);
+ ASSERT(len <= MAX_NVRAMBUF_SIZE);
+ memcpy(memblock, bus->nvram_params, len);
+ }
+ if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
+ bufp = (char *)memblock;
+ bufp[len] = 0;
+ len = process_nvram_vars(bufp, len);
+ if (len % 4) {
+ len += 4 - (len % 4);
+ }
+ bufp += len;
+ *bufp++ = 0;
+ if (len)
+ bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error downloading vars: %d\n",
+ __FUNCTION__, bcmerror));
+ }
+ }
+ else {
+ DHD_ERROR(("%s: error reading nvram file: %d\n",
+ __FUNCTION__, len));
+ bcmerror = BCME_SDIO_ERROR;
+ }
+
+err:
+ if (memblock)
+ MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
+
+ if (image)
+ dhd_os_close_image(image);
+
+ return bcmerror;
+}
+
+static int
+_dhdsdio_download_firmware(struct dhd_bus *bus)
+{
+ int bcmerror = -1;
+
+ bool embed = FALSE; /* download embedded firmware */
+ bool dlok = FALSE; /* download firmware succeeded */
+
+ /* Out immediately if no image to download */
+ if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
+#ifdef BCMEMBEDIMAGE
+ embed = TRUE;
+#else
+ return 0;
+#endif
+ }
+
+ /* Keep arm in reset */
+ if (dhdsdio_download_state(bus, TRUE)) {
+ DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
+ goto err;
+ }
+
+ /* External image takes precedence if specified */
+ if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
+ if (dhdsdio_download_code_file(bus, bus->fw_path)) {
+ DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
+#ifdef BCMEMBEDIMAGE
+ embed = TRUE;
+#else
+ goto err;
+#endif
+ }
+ else {
+ embed = FALSE;
+ dlok = TRUE;
+ }
+ }
+
+#ifdef BCMEMBEDIMAGE
+ if (embed) {
+ if (dhdsdio_download_code_array(bus)) {
+ DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__));
+ goto err;
+ }
+ else {
+ dlok = TRUE;
+ }
+ }
+#else
+ BCM_REFERENCE(embed);
+#endif
+ if (!dlok) {
+ DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
+ goto err;
+ }
+
+ /* EXAMPLE: nvram_array */
+ /* If a valid nvram_arry is specified as above, it can be passed down to dongle */
+ /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
+
+ /* External nvram takes precedence if specified */
+ if (dhdsdio_download_nvram(bus)) {
+ DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
+ goto err;
+ }
+
+ /* Take arm out of reset */
+ if (dhdsdio_download_state(bus, FALSE)) {
+ DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
+ goto err;
+ }
+
+ bcmerror = 0;
+
+err:
+ return bcmerror;
+}
+
+static int
+dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
+ void *pkt, bcmsdh_cmplt_fn_t complete, void *handle)
+{
+ int status;
+
+ if (!KSO_ENAB(bus)) {
+ DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
+ return BCME_NODEVICE;
+ }
+
+ status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle);
+
+ return status;
+}
+
+static int
+dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
+ void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry)
+{
+ int ret;
+ int i = 0;
+ int retries = 0;
+ bcmsdh_info_t *sdh;
+
+ if (!KSO_ENAB(bus)) {
+ DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
+ return BCME_NODEVICE;
+ }
+
+ sdh = bus->sdh;
+ do {
+ ret = bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes,
+ pkt, complete, handle);
+
+ bus->f2txdata++;
+ ASSERT(ret != BCME_PENDING);
+
+ if (ret == BCME_NODEVICE) {
+ DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__));
+ } else if (ret < 0) {
+ /* On failure, abort the command and terminate the frame */
+ DHD_ERROR(("%s: sdio error %d, abort command and terminate frame.\n",
+ __FUNCTION__, ret));
+ bus->tx_sderrs++;
+ bus->f1regdata++;
+ bus->dhd->tx_errors++;
+ bcmsdh_abort(sdh, SDIO_FUNC_2);
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
+ SFC_WF_TERM, NULL);
+ for (i = 0; i < READ_FRM_CNT_RETRIES; i++) {
+ uint8 hi, lo;
+ hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI,
+ NULL);
+ lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO,
+ NULL);
+ bus->f1regdata += 2;
+ if ((hi == 0) && (lo == 0))
+ break;
+ }
+ }
+ } while ((ret < 0) && retrydata && ++retries < max_retry);
+
+ return ret;
+}
+
+uint
+dhd_bus_chip(struct dhd_bus *bus)
+{
+ ASSERT(bus->sih != NULL);
+ return bus->sih->chip;
+}
+
+uint
+dhd_bus_chiprev(struct dhd_bus *bus)
+{
+ ASSERT(bus);
+ ASSERT(bus->sih != NULL);
+ return bus->sih->chiprev;
+}
+
+void *
+dhd_bus_pub(struct dhd_bus *bus)
+{
+ return bus->dhd;
+}
+
+void *
+dhd_bus_sih(struct dhd_bus *bus)
+{
+ return (void *)bus->sih;
+}
+
+void *
+dhd_bus_txq(struct dhd_bus *bus)
+{
+ return &bus->txq;
+}
+
+void
+dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val)
+{
+ bus->dotxinrx = val;
+}
+
+int
+dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
+{
+ int bcmerror = 0;
+ dhd_bus_t *bus;
+
+ bus = dhdp->bus;
+
+ if (flag == TRUE) {
+ if (!bus->dhd->dongle_reset) {
+ dhd_os_sdlock(dhdp);
+ dhd_os_wd_timer(dhdp, 0);
+#if !defined(IGNORE_ETH0_DOWN)
+ /* Force flow control as protection when stop come before ifconfig_down */
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
+#endif /* !defined(IGNORE_ETH0_DOWN) */
+ /* Expect app to have torn down any connection before calling */
+ /* Stop the bus, disable F2 */
+ dhd_bus_stop(bus, FALSE);
+
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(dhdp->oob_disable)) {
+ /* Clean up any pending IRQ */
+ dhd_enable_oob_intr(bus, FALSE);
+ bcmsdh_oob_intr_set(bus->sdh, FALSE);
+ bcmsdh_oob_intr_unregister(bus->sdh);
+ }
+#endif
+
+ /* Clean tx/rx buffer pointers, detach from the dongle */
+ dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE);
+
+ bus->dhd->dongle_reset = TRUE;
+ bus->dhd->up = FALSE;
+ dhd_txglom_enable(dhdp, FALSE);
+ dhd_os_sdunlock(dhdp);
+
+ DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__));
+ /* App can now remove power from device */
+ } else
+ bcmerror = BCME_SDIO_ERROR;
+ } else {
+ /* App must have restored power to device before calling */
+
+ DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __FUNCTION__));
+
+ if (bus->dhd->dongle_reset) {
+ /* Turn on WLAN */
+ dhd_os_sdlock(dhdp);
+ /* Reset SD client */
+ bcmsdh_reset(bus->sdh);
+
+ /* Attempt to re-attach & download */
+ if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
+ (uint32 *)SI_ENUM_BASE,
+ bus->cl_devid)) {
+ /* Attempt to download binary to the dongle */
+ if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) &&
+ dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh) >= 0) {
+
+ /* Re-init bus, enable F2 transfer */
+ bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
+ if (bcmerror == BCME_OK) {
+#if defined(OOB_INTR_ONLY)
+ OOB_PARAM_IF(!(dhdp->oob_disable)) {
+ dhd_enable_oob_intr(bus, TRUE);
+ bcmsdh_oob_intr_register(bus->sdh,
+ dhdsdio_isr, bus);
+ bcmsdh_oob_intr_set(bus->sdh, TRUE);
+ }
+#endif
+
+ bus->dhd->dongle_reset = FALSE;
+ bus->dhd->up = TRUE;
+
+#if !defined(IGNORE_ETH0_DOWN)
+ /* Restore flow control */
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
+#endif
+ dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
+
+ DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
+ } else {
+ dhd_bus_stop(bus, FALSE);
+ dhdsdio_release_dongle(bus, bus->dhd->osh,
+ TRUE, FALSE);
+ }
+ } else {
+ DHD_ERROR(("%s Failed to download binary to the dongle\n",
+ __FUNCTION__));
+ if (bus->sih != NULL) {
+ si_detach(bus->sih);
+ bus->sih = NULL;
+ }
+ bcmerror = BCME_SDIO_ERROR;
+ }
+ } else
+ bcmerror = BCME_SDIO_ERROR;
+
+ dhd_os_sdunlock(dhdp);
+ } else {
+ bcmerror = BCME_SDIO_ERROR;
+ DHD_INFO(("%s called when dongle is not in reset\n",
+ __FUNCTION__));
+ DHD_INFO(("Will call dhd_bus_start instead\n"));
+ dhd_bus_resume(dhdp, 1);
+ if ((bcmerror = dhd_bus_start(dhdp)) != 0)
+ DHD_ERROR(("%s: dhd_bus_start fail with %d\n",
+ __FUNCTION__, bcmerror));
+ }
+ }
+ return bcmerror;
+}
+
+int dhd_bus_suspend(dhd_pub_t *dhdpub)
+{
+ return bcmsdh_stop(dhdpub->bus->sdh);
+}
+
+int dhd_bus_resume(dhd_pub_t *dhdpub, int stage)
+{
+ return bcmsdh_start(dhdpub->bus->sdh, stage);
+}
+
+/* Get Chip ID version */
+uint dhd_bus_chip_id(dhd_pub_t *dhdp)
+{
+ dhd_bus_t *bus = dhdp->bus;
+
+ return bus->sih->chip;
+}
+
+/* Get Chip Rev ID version */
+uint dhd_bus_chiprev_id(dhd_pub_t *dhdp)
+{
+ dhd_bus_t *bus = dhdp->bus;
+
+ return bus->sih->chiprev;
+}
+
+/* Get Chip Pkg ID version */
+uint dhd_bus_chippkg_id(dhd_pub_t *dhdp)
+{
+ dhd_bus_t *bus = dhdp->bus;
+
+ return bus->sih->chippkg;
+}
+
+int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num, uint32 *slot_num)
+{
+ *bus_type = bus->bus;
+ *bus_num = bus->bus_num;
+ *slot_num = bus->slot_num;
+ return 0;
+}
+
+int
+dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size)
+{
+ dhd_bus_t *bus;
+
+ bus = dhdp->bus;
+ return dhdsdio_membytes(bus, set, address, data, size);
+}
+
+
+void
+dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path)
+{
+ bus->fw_path = pfw_path;
+ bus->nv_path = pnv_path;
+}
+
+int
+dhd_enableOOB(dhd_pub_t *dhd, bool sleep)
+{
+ dhd_bus_t *bus = dhd->bus;
+ sdpcmd_regs_t *regs = bus->regs;
+ uint retries = 0;
+
+ if (sleep) {
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ /* Tell device to start using OOB wakeup */
+ W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
+ if (retries > retry_limit) {
+ DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
+ return BCME_BUSY;
+ }
+ /* Turn off our contribution to the HT clock request */
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+ } else {
+ /* Make sure the controller has the bus up */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ /* Send misc interrupt to indicate OOB not needed */
+ W_SDREG(0, &regs->tosbmailboxdata, retries);
+ if (retries <= retry_limit)
+ W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
+
+ if (retries > retry_limit)
+ DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
+
+ /* Make sure we have SD bus access */
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+ }
+ return BCME_OK;
+}
+
+void
+dhd_bus_pktq_flush(dhd_pub_t *dhdp)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ bool wlfc_enabled = FALSE;
+
+#ifdef PROP_TXSTATUS
+ wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED);
+#endif
+ if (!wlfc_enabled) {
+#ifdef DHDTCPACK_SUPPRESS
+ /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
+ * when there is a newly coming packet from network stack.
+ */
+ dhd_tcpack_info_tbl_clean(bus->dhd);
+#endif /* DHDTCPACK_SUPPRESS */
+ /* Clear the data packet queues */
+ pktq_flush(dhdp->osh, &bus->txq, TRUE, NULL, 0);
+ }
+}
+
+int
+dhd_sr_config(dhd_pub_t *dhd, bool on)
+{
+ dhd_bus_t *bus = dhd->bus;
+
+ if (!bus->_srenab)
+ return -1;
+
+ return dhdsdio_clk_devsleep_iovar(bus, on);
+}
+
+uint16
+dhd_get_chipid(dhd_pub_t *dhd)
+{
+ dhd_bus_t *bus = dhd->bus;
+
+ if (bus && bus->sih)
+ return (uint16)bus->sih->chip;
+ else
+ return 0;
+}
+
+#ifdef DEBUGGER
+uint32 dhd_sdio_reg_read(void *h, uint32 addr)
+{
+ uint32 rval;
+ struct dhd_bus *bus = (struct dhd_bus *) h;
+
+ dhd_os_sdlock(bus->dhd);
+
+ BUS_WAKE(bus);
+
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ rval = bcmsdh_reg_read(bus->sdh, addr, 4);
+
+ dhd_os_sdunlock(bus->dhd);
+
+ return rval;
+}
+
+void dhd_sdio_reg_write(void *h, uint32 addr, uint32 val)
+{
+ struct dhd_bus *bus = (struct dhd_bus *) h;
+
+ dhd_os_sdlock(bus->dhd);
+
+ BUS_WAKE(bus);
+
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ bcmsdh_reg_write(bus->sdh, addr, 4, val);
+
+ dhd_os_sdunlock(bus->dhd);
+}
+#endif /* DEBUGGER */
+
+
+#ifdef OOB_PARAM
+uint
+dhd_get_oob_disable(struct dhd_bus *bus)
+{
+ return bus->dhd->oob_disable;
+}
+#endif /* OOB_PARAM */
diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.c b/drivers/net/wireless/bcmdhd/dhd_wlfc.c
new file mode 100644
index 000000000000..8c1436a3ee3f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.c
@@ -0,0 +1,4049 @@
+/*
+ * DHD PROP_TXSTATUS Module.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_wlfc.c 658506 2016-09-08 06:44:19Z $
+ *
+ */
+
+#include <typedefs.h>
+#include <osl.h>
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+
+#include <dngl_stats.h>
+#include <dhd.h>
+
+#include <dhd_bus.h>
+#include <dhd_dbg.h>
+
+#ifdef PROP_TXSTATUS
+#include <wlfc_proto.h>
+#include <dhd_wlfc.h>
+#endif
+#ifdef DHDTCPACK_SUPPRESS
+#include <dhd_ip.h>
+#endif /* DHDTCPACK_SUPPRESS */
+
+
+/*
+ * wlfc naming and lock rules:
+ *
+ * 1. Private functions name like _dhd_wlfc_XXX, declared as static and avoid wlfc lock operation.
+ * 2. Public functions name like dhd_wlfc_XXX, use wlfc lock if needed.
+ * 3. Non-Proptxstatus module call public functions only and avoid wlfc lock operation.
+ *
+ */
+
+
+#ifdef PROP_TXSTATUS
+
+#define DHD_WLFC_QMON_COMPLETE(entry)
+
+#define LIMIT_BORROW
+
+
+static uint16
+_dhd_wlfc_adjusted_seq(void* p, uint8 current_seq)
+{
+ uint16 seq;
+
+ if (!p) {
+ return 0xffff;
+ }
+
+ seq = WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
+ if (seq < current_seq) {
+ /* wrap around */
+ seq += 256;
+ }
+
+ return seq;
+}
+
+static void
+_dhd_wlfc_prec_enque(struct pktq *pq, int prec, void* p, bool qHead,
+ uint8 current_seq, bool reOrder)
+{
+ struct pktq_prec *q;
+ uint16 seq, seq2;
+ void *p2, *p2_prev;
+
+ if (!p)
+ return;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
+
+ ASSERT(!pktq_full(pq));
+ ASSERT(!pktq_pfull(pq, prec));
+
+ q = &pq->q[prec];
+
+ PKTSETLINK(p, NULL);
+ if (q->head == NULL) {
+ /* empty queue */
+ q->head = p;
+ q->tail = p;
+ } else {
+ if (reOrder && (prec & 1)) {
+ seq = _dhd_wlfc_adjusted_seq(p, current_seq);
+ p2 = qHead ? q->head : q->tail;
+ seq2 = _dhd_wlfc_adjusted_seq(p2, current_seq);
+
+ if ((qHead &&((seq+1) > seq2)) || (!qHead && ((seq2+1) > seq))) {
+ /* need reorder */
+ p2 = q->head;
+ p2_prev = NULL;
+ seq2 = _dhd_wlfc_adjusted_seq(p2, current_seq);
+
+ while (seq > seq2) {
+ p2_prev = p2;
+ p2 = PKTLINK(p2);
+ if (!p2) {
+ break;
+ }
+ seq2 = _dhd_wlfc_adjusted_seq(p2, current_seq);
+ }
+
+ if (p2_prev == NULL) {
+ /* insert head */
+ PKTSETLINK(p, q->head);
+ q->head = p;
+ } else if (p2 == NULL) {
+ /* insert tail */
+ PKTSETLINK(p2_prev, p);
+ q->tail = p;
+ } else {
+ /* insert after p2_prev */
+ PKTSETLINK(p, PKTLINK(p2_prev));
+ PKTSETLINK(p2_prev, p);
+ }
+ goto exit;
+ }
+ }
+
+ if (qHead) {
+ PKTSETLINK(p, q->head);
+ q->head = p;
+ } else {
+ PKTSETLINK(q->tail, p);
+ q->tail = p;
+ }
+ }
+
+exit:
+
+ q->len++;
+ pq->len++;
+
+ if (pq->hi_prec < prec)
+ pq->hi_prec = (uint8)prec;
+}
+
+/* Create a place to store all packet pointers submitted to the firmware until
+ a status comes back, suppress or otherwise.
+
+ hang-er: noun, a contrivance on which things are hung, as a hook.
+*/
+static void*
+_dhd_wlfc_hanger_create(osl_t *osh, int max_items)
+{
+ int i;
+ wlfc_hanger_t* hanger;
+
+ /* allow only up to a specific size for now */
+ ASSERT(max_items == WLFC_HANGER_MAXITEMS);
+
+ if ((hanger = (wlfc_hanger_t*)MALLOC(osh, WLFC_HANGER_SIZE(max_items))) == NULL)
+ return NULL;
+
+ memset(hanger, 0, WLFC_HANGER_SIZE(max_items));
+ hanger->max_items = max_items;
+
+ for (i = 0; i < hanger->max_items; i++) {
+ hanger->items[i].state = WLFC_HANGER_ITEM_STATE_FREE;
+ }
+ return hanger;
+}
+
+static int
+_dhd_wlfc_hanger_delete(osl_t *osh, void* hanger)
+{
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+
+ if (h) {
+ MFREE(osh, h, WLFC_HANGER_SIZE(h->max_items));
+ return BCME_OK;
+ }
+ return BCME_BADARG;
+}
+
+static uint16
+_dhd_wlfc_hanger_get_free_slot(void* hanger)
+{
+ uint32 i;
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+
+ if (h) {
+ i = h->slot_pos + 1;
+ if (i == h->max_items) {
+ i = 0;
+ }
+ while (i != h->slot_pos) {
+ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE) {
+ h->slot_pos = i;
+ return (uint16)i;
+ }
+ i++;
+ if (i == h->max_items)
+ i = 0;
+ }
+ h->failed_slotfind++;
+ }
+ return WLFC_HANGER_MAXITEMS;
+}
+
+static int
+_dhd_wlfc_hanger_get_genbit(void* hanger, void* pkt, uint32 slot_id, int* gen)
+{
+ int rc = BCME_OK;
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+
+ *gen = 0xff;
+
+ /* this packet was not pushed at the time it went to the firmware */
+ if (slot_id == WLFC_HANGER_MAXITEMS)
+ return BCME_NOTFOUND;
+
+ if (h) {
+ if ((h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) ||
+ (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) {
+ *gen = h->items[slot_id].gen;
+ }
+ else {
+ rc = BCME_NOTFOUND;
+ }
+ }
+ else
+ rc = BCME_BADARG;
+ return rc;
+}
+
+static int
+_dhd_wlfc_hanger_pushpkt(void* hanger, void* pkt, uint32 slot_id)
+{
+ int rc = BCME_OK;
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+
+ if (h && (slot_id < WLFC_HANGER_MAXITEMS)) {
+ if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_FREE) {
+ h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE;
+ h->items[slot_id].pkt = pkt;
+ h->pushed++;
+ }
+ else {
+ h->failed_to_push++;
+ rc = BCME_NOTFOUND;
+ }
+ }
+ else
+ rc = BCME_BADARG;
+ return rc;
+}
+
+static int
+_dhd_wlfc_hanger_poppkt(void* hanger, uint32 slot_id, void** pktout, int remove_from_hanger)
+{
+ int rc = BCME_OK;
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+
+ /* this packet was not pushed at the time it went to the firmware */
+ if (slot_id == WLFC_HANGER_MAXITEMS)
+ return BCME_NOTFOUND;
+
+ if (h) {
+ if (h->items[slot_id].state != WLFC_HANGER_ITEM_STATE_FREE) {
+ *pktout = h->items[slot_id].pkt;
+ if (remove_from_hanger) {
+ h->items[slot_id].state =
+ WLFC_HANGER_ITEM_STATE_FREE;
+ h->items[slot_id].pkt = NULL;
+ h->items[slot_id].gen = 0xff;
+ h->items[slot_id].identifier = 0;
+ h->popped++;
+ }
+ }
+ else {
+ h->failed_to_pop++;
+ rc = BCME_NOTFOUND;
+ }
+ }
+ else
+ rc = BCME_BADARG;
+ return rc;
+}
+
+static int
+_dhd_wlfc_hanger_mark_suppressed(void* hanger, uint32 slot_id, uint8 gen)
+{
+ int rc = BCME_OK;
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+
+ /* this packet was not pushed at the time it went to the firmware */
+ if (slot_id == WLFC_HANGER_MAXITEMS)
+ return BCME_NOTFOUND;
+ if (h) {
+ h->items[slot_id].gen = gen;
+ if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) {
+ h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED;
+ }
+ else
+ rc = BCME_BADARG;
+ }
+ else
+ rc = BCME_BADARG;
+
+ return rc;
+}
+
+static void
+_dhd_wlfc_hanger_waitevent_set(void* hanger, uint32 hslot, uint8 waitevent)
+{
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+ ASSERT(h && (hslot < (uint32) h->max_items));
+
+ h->items[hslot].waitevent = waitevent;
+}
+
+static uint8
+_dhd_wlfc_hanger_waitevent_decreturn(void* hanger, uint32 hslot)
+{
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+ ASSERT(h && (hslot < (uint32) h->max_items));
+
+ h->items[hslot].waitevent--;
+ return h->items[hslot].waitevent;
+}
+
+/* return true if the slot is only waiting for clean */
+static bool
+_dhd_wlfc_hanger_wait_clean(void* hanger, uint32 hslot)
+{
+ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
+
+ if ((hslot < (uint32) h->max_items) &&
+ (h->items[hslot].state == WLFC_HANGER_ITEM_STATE_WAIT_CLEAN)) {
+ /* the packet should be already freed by _dhd_wlfc_cleanup */
+ h->items[hslot].state = WLFC_HANGER_ITEM_STATE_FREE;
+ h->items[hslot].pkt = NULL;
+ h->items[hslot].gen = 0xff;
+ h->items[hslot].identifier = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* remove reference of specific packet in hanger */
+static bool
+_dhd_wlfc_hanger_remove_reference(wlfc_hanger_t* h, void* pkt)
+{
+ int i;
+
+ if (!h || !pkt) {
+ return FALSE;
+ }
+
+ for (i = 0; i < h->max_items; i++) {
+ if (pkt == h->items[i].pkt) {
+ if ((h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) ||
+ (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) {
+ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE;
+ h->items[i].pkt = NULL;
+ h->items[i].gen = 0xff;
+ h->items[i].identifier = 0;
+ }
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static int
+_dhd_wlfc_enque_afq(athost_wl_status_info_t* ctx, void *p)
+{
+ wlfc_mac_descriptor_t* entry;
+ uint16 entry_idx = WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
+ uint8 prec = DHD_PKTTAG_FIFO(PKTTAG(p));
+
+ if (entry_idx < WLFC_MAC_DESC_TABLE_SIZE)
+ entry = &ctx->destination_entries.nodes[entry_idx];
+ else if (entry_idx < (WLFC_MAC_DESC_TABLE_SIZE + WLFC_MAX_IFNUM))
+ entry = &ctx->destination_entries.interfaces[entry_idx - WLFC_MAC_DESC_TABLE_SIZE];
+ else
+ entry = &ctx->destination_entries.other;
+
+ pktq_penq(&entry->afq, prec, p);
+
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_deque_afq(athost_wl_status_info_t* ctx, uint16 hslot, uint8 hcnt, uint8 prec,
+ void **pktout)
+{
+ wlfc_mac_descriptor_t *entry;
+ struct pktq *pq;
+ struct pktq_prec *q;
+ void *p, *b;
+
+ if (!ctx) {
+ DHD_ERROR(("%s: ctx(%p), pktout(%p)\n", __FUNCTION__, ctx, pktout));
+ return BCME_BADARG;
+ }
+
+ if (pktout) {
+ *pktout = NULL;
+ }
+
+ ASSERT(hslot < (WLFC_MAC_DESC_TABLE_SIZE + WLFC_MAX_IFNUM + 1));
+
+ if (hslot < WLFC_MAC_DESC_TABLE_SIZE)
+ entry = &ctx->destination_entries.nodes[hslot];
+ else if (hslot < (WLFC_MAC_DESC_TABLE_SIZE + WLFC_MAX_IFNUM))
+ entry = &ctx->destination_entries.interfaces[hslot - WLFC_MAC_DESC_TABLE_SIZE];
+ else
+ entry = &ctx->destination_entries.other;
+
+ pq = &entry->afq;
+
+ ASSERT(prec < pq->num_prec);
+
+ q = &pq->q[prec];
+
+ b = NULL;
+ p = q->head;
+
+ while (p && (hcnt != WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(p)))))
+ {
+ b = p;
+ p = PKTLINK(p);
+ }
+
+ if (p == NULL) {
+ /* none is matched */
+ if (b) {
+ DHD_ERROR(("%s: can't find matching seq(%d)\n", __FUNCTION__, hcnt));
+ } else {
+ DHD_ERROR(("%s: queue is empty\n", __FUNCTION__));
+ }
+
+ return BCME_ERROR;
+ }
+
+ if (!b) {
+ /* head packet is matched */
+ if ((q->head = PKTLINK(p)) == NULL) {
+ q->tail = NULL;
+ }
+ } else {
+ /* middle packet is matched */
+ DHD_INFO(("%s: out of order, seq(%d), head_seq(%d)\n", __FUNCTION__, hcnt,
+ WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(q->head)))));
+ ctx->stats.ooo_pkts[prec]++;
+ PKTSETLINK(b, PKTLINK(p));
+ if (PKTLINK(p) == NULL) {
+ q->tail = b;
+ }
+ }
+
+ q->len--;
+ pq->len--;
+
+ PKTSETLINK(p, NULL);
+
+ if (pktout) {
+ *pktout = p;
+ }
+
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_pushheader(athost_wl_status_info_t* ctx, void* p, bool tim_signal,
+ uint8 tim_bmp, uint8 mac_handle, uint32 htodtag, uint16 htodseq, bool skip_wlfc_hdr)
+{
+ uint32 wl_pktinfo = 0;
+ uint8* wlh;
+ uint8 dataOffset = 0;
+ uint8 fillers;
+ uint8 tim_signal_len = 0;
+ dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
+
+ struct bdc_header *h;
+
+ if (skip_wlfc_hdr)
+ goto push_bdc_hdr;
+
+ if (tim_signal) {
+ tim_signal_len = TLV_HDR_LEN + WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP;
+ }
+
+ /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */
+ dataOffset = WLFC_CTL_VALUE_LEN_PKTTAG + TLV_HDR_LEN + tim_signal_len;
+ if (WLFC_GET_REUSESEQ(dhdp->wlfc_mode)) {
+ dataOffset += WLFC_CTL_VALUE_LEN_SEQ;
+ }
+
+ fillers = ROUNDUP(dataOffset, 4) - dataOffset;
+ dataOffset += fillers;
+
+ PKTPUSH(ctx->osh, p, dataOffset);
+ wlh = (uint8*) PKTDATA(ctx->osh, p);
+
+ wl_pktinfo = htol32(htodtag);
+
+ wlh[TLV_TAG_OFF] = WLFC_CTL_TYPE_PKTTAG;
+ wlh[TLV_LEN_OFF] = WLFC_CTL_VALUE_LEN_PKTTAG;
+ memcpy(&wlh[TLV_HDR_LEN], &wl_pktinfo, sizeof(uint32));
+
+ if (WLFC_GET_REUSESEQ(dhdp->wlfc_mode)) {
+ uint16 wl_seqinfo = htol16(htodseq);
+ wlh[TLV_LEN_OFF] += WLFC_CTL_VALUE_LEN_SEQ;
+ memcpy(&wlh[TLV_HDR_LEN + WLFC_CTL_VALUE_LEN_PKTTAG], &wl_seqinfo,
+ WLFC_CTL_VALUE_LEN_SEQ);
+ }
+
+ if (tim_signal_len) {
+ wlh[dataOffset - fillers - tim_signal_len ] =
+ WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP;
+ wlh[dataOffset - fillers - tim_signal_len + 1] =
+ WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP;
+ wlh[dataOffset - fillers - tim_signal_len + 2] = mac_handle;
+ wlh[dataOffset - fillers - tim_signal_len + 3] = tim_bmp;
+ }
+ if (fillers)
+ memset(&wlh[dataOffset - fillers], WLFC_CTL_TYPE_FILLER, fillers);
+
+push_bdc_hdr:
+
+ PKTPUSH(ctx->osh, p, BDC_HEADER_LEN);
+ h = (struct bdc_header *)PKTDATA(ctx->osh, p);
+ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
+ if (PKTSUMNEEDED(p))
+ h->flags |= BDC_FLAG_SUM_NEEDED;
+
+
+ h->priority = (PKTPRIO(p) & BDC_PRIORITY_MASK);
+ h->flags2 = 0;
+ h->dataOffset = dataOffset >> 2;
+ BDC_SET_IF_IDX(h, DHD_PKTTAG_IF(PKTTAG(p)));
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf)
+{
+ struct bdc_header *h;
+
+ if (PKTLEN(ctx->osh, pktbuf) < BDC_HEADER_LEN) {
+ DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
+ PKTLEN(ctx->osh, pktbuf), BDC_HEADER_LEN));
+ return BCME_ERROR;
+ }
+ h = (struct bdc_header *)PKTDATA(ctx->osh, pktbuf);
+
+ /* pull BDC header */
+ PKTPULL(ctx->osh, pktbuf, BDC_HEADER_LEN);
+
+ if (PKTLEN(ctx->osh, pktbuf) < (uint)(h->dataOffset << 2)) {
+ DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
+ PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2)));
+ return BCME_ERROR;
+ }
+
+ /* pull wl-header */
+ PKTPULL(ctx->osh, pktbuf, (h->dataOffset << 2));
+ return BCME_OK;
+}
+
+static wlfc_mac_descriptor_t*
+_dhd_wlfc_find_table_entry(athost_wl_status_info_t* ctx, void* p)
+{
+ int i;
+ wlfc_mac_descriptor_t* table = ctx->destination_entries.nodes;
+ uint8 ifid = DHD_PKTTAG_IF(PKTTAG(p));
+ uint8* dstn = DHD_PKTTAG_DSTN(PKTTAG(p));
+ wlfc_mac_descriptor_t* entry = DHD_PKTTAG_ENTRY(PKTTAG(p));
+ int iftype = ctx->destination_entries.interfaces[ifid].iftype;
+
+ /* saved one exists, return it */
+ if (entry)
+ return entry;
+
+ /* Multicast destination, STA and P2P clients get the interface entry.
+ * STA/GC gets the Mac Entry for TDLS destinations, TDLS destinations
+ * have their own entry.
+ */
+ if ((iftype == WLC_E_IF_ROLE_STA || ETHER_ISMULTI(dstn) ||
+ iftype == WLC_E_IF_ROLE_P2P_CLIENT) &&
+ (ctx->destination_entries.interfaces[ifid].occupied)) {
+ entry = &ctx->destination_entries.interfaces[ifid];
+ }
+
+ if (entry && ETHER_ISMULTI(dstn)) {
+ DHD_PKTTAG_SET_ENTRY(PKTTAG(p), entry);
+ return entry;
+ }
+
+ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) {
+ if (table[i].occupied) {
+ if (table[i].interface_id == ifid) {
+ if (!memcmp(table[i].ea, dstn, ETHER_ADDR_LEN)) {
+ entry = &table[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if (entry == NULL)
+ entry = &ctx->destination_entries.other;
+
+ DHD_PKTTAG_SET_ENTRY(PKTTAG(p), entry);
+
+ return entry;
+}
+
+static int
+_dhd_wlfc_prec_drop(dhd_pub_t *dhdp, int prec, void* p, bool bPktInQ)
+{
+ athost_wl_status_info_t* ctx;
+ void *pout = NULL;
+
+ ASSERT(dhdp && p);
+ ASSERT(prec >= 0 && prec <= WLFC_PSQ_PREC_COUNT);
+
+ ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
+
+ if (!WLFC_GET_AFQ(dhdp->wlfc_mode) && (prec & 1)) {
+ /* suppressed queue, need pop from hanger */
+ _dhd_wlfc_hanger_poppkt(ctx->hanger, WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG
+ (PKTTAG(p))), &pout, 1);
+ ASSERT(p == pout);
+ }
+
+ if (!(prec & 1)) {
+#ifdef DHDTCPACK_SUPPRESS
+ /* pkt in delayed q, so fake push BDC header for
+ * dhd_tcpack_check_xmit() and dhd_txcomplete().
+ */
+ _dhd_wlfc_pushheader(ctx, p, FALSE, 0, 0, 0, 0, TRUE);
+
+ /* This packet is about to be freed, so remove it from tcp_ack_info_tbl
+ * This must be one of...
+ * 1. A pkt already in delayQ is evicted by another pkt with higher precedence
+ * in _dhd_wlfc_prec_enq_with_drop()
+ * 2. A pkt could not be enqueued to delayQ because it is full,
+ * in _dhd_wlfc_enque_delayq().
+ * 3. A pkt could not be enqueued to delayQ because it is full,
+ * in _dhd_wlfc_rollback_packet_toq().
+ */
+ if (dhd_tcpack_check_xmit(dhdp, p) == BCME_ERROR) {
+ DHD_ERROR(("%s %d: tcpack_suppress ERROR!!!"
+ " Stop using it\n",
+ __FUNCTION__, __LINE__));
+ dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF);
+ }
+#endif /* DHDTCPACK_SUPPRESS */
+ }
+
+ if (bPktInQ) {
+ ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec>>1]--;
+ ctx->pkt_cnt_per_ac[prec>>1]--;
+ }
+
+ dhd_txcomplete(dhdp, p, FALSE);
+ PKTFREE(ctx->osh, p, TRUE);
+ ctx->stats.pktout++;
+ ctx->stats.drop_pkts[prec]++;
+
+ return 0;
+}
+
+static bool
+_dhd_wlfc_prec_enq_with_drop(dhd_pub_t *dhdp, struct pktq *pq, void *pkt, int prec, bool qHead,
+ uint8 current_seq)
+{
+ void *p = NULL;
+ int eprec = -1; /* precedence to evict from */
+ athost_wl_status_info_t* ctx;
+
+ ASSERT(dhdp && pq && pkt);
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
+
+ /* Fast case, precedence queue is not full and we are also not
+ * exceeding total queue length
+ */
+ if (!pktq_pfull(pq, prec) && !pktq_full(pq)) {
+ goto exit;
+ }
+
+ /* Determine precedence from which to evict packet, if any */
+ if (pktq_pfull(pq, prec))
+ eprec = prec;
+ else if (pktq_full(pq)) {
+ p = pktq_peek_tail(pq, &eprec);
+ if (!p) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return FALSE;
+ }
+ if ((eprec > prec) || (eprec < 0)) {
+ if (!pktq_pempty(pq, prec)) {
+ eprec = prec;
+ } else {
+ return FALSE;
+ }
+ }
+ }
+
+ /* Evict if needed */
+ if (eprec >= 0) {
+ /* Detect queueing to unconfigured precedence */
+ ASSERT(!pktq_pempty(pq, eprec));
+ /* Evict all fragmented frames */
+ dhd_prec_drop_pkts(dhdp, pq, eprec, _dhd_wlfc_prec_drop);
+ }
+
+exit:
+ /* Enqueue */
+ _dhd_wlfc_prec_enque(pq, prec, pkt, qHead, current_seq,
+ WLFC_GET_REORDERSUPP(dhdp->wlfc_mode));
+ ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(pkt))][prec>>1]++;
+ ctx->pkt_cnt_per_ac[prec>>1]++;
+
+ return TRUE;
+}
+
+
+static int
+_dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx,
+ void* p, ewlfc_packet_state_t pkt_type, uint32 hslot)
+{
+ /*
+ put the packet back to the head of queue
+
+ - suppressed packet goes back to suppress sub-queue
+ - pull out the header, if new or delayed packet
+
+ Note: hslot is used only when header removal is done.
+ */
+ wlfc_mac_descriptor_t* entry;
+ int rc = BCME_OK;
+ int prec, fifo_id;
+
+ entry = _dhd_wlfc_find_table_entry(ctx, p);
+ prec = DHD_PKTTAG_FIFO(PKTTAG(p));
+ fifo_id = prec << 1;
+ if (pkt_type == eWLFC_PKTTYPE_SUPPRESSED)
+ fifo_id += 1;
+ if (entry != NULL) {
+ /*
+ if this packet did not count against FIFO credit, it must have
+ taken a requested_credit from the firmware (for pspoll etc.)
+ */
+ if ((prec != AC_COUNT) && !DHD_PKTTAG_CREDITCHECK(PKTTAG(p)))
+ entry->requested_credit++;
+
+ if (pkt_type == eWLFC_PKTTYPE_DELAYED) {
+ /* decrement sequence count */
+ WLFC_DECR_SEQCOUNT(entry, prec);
+ /* remove header first */
+ rc = _dhd_wlfc_pullheader(ctx, p);
+ if (rc != BCME_OK) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ goto exit;
+ }
+ }
+
+ if (_dhd_wlfc_prec_enq_with_drop(ctx->dhdp, &entry->psq, p, fifo_id, TRUE,
+ WLFC_SEQCOUNT(entry, fifo_id>>1))
+ == FALSE) {
+ /* enque failed */
+ DHD_ERROR(("Error: %s():%d, fifo_id(%d)\n",
+ __FUNCTION__, __LINE__, fifo_id));
+ rc = BCME_ERROR;
+ }
+ } else {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ rc = BCME_ERROR;
+ }
+exit:
+ if (rc != BCME_OK) {
+ ctx->stats.rollback_failed++;
+ _dhd_wlfc_prec_drop(ctx->dhdp, fifo_id, p, FALSE);
+ }
+ else
+ ctx->stats.rollback++;
+
+ return rc;
+}
+
+static bool
+_dhd_wlfc_allow_fc(athost_wl_status_info_t* ctx, uint8 ifid)
+{
+ int prec, ac_traffic = WLFC_NO_TRAFFIC;
+
+ for (prec = 0; prec < AC_COUNT; prec++) {
+ if (ctx->pkt_cnt_in_q[ifid][prec] > 0) {
+ if (ac_traffic == WLFC_NO_TRAFFIC)
+ ac_traffic = prec + 1;
+ else if (ac_traffic != (prec + 1))
+ ac_traffic = WLFC_MULTI_TRAFFIC;
+ }
+ }
+
+ if (ac_traffic >= 1 && ac_traffic <= AC_COUNT) {
+ /* single AC (BE/BK/VI/VO) in queue */
+ if (ctx->allow_fc) {
+ return TRUE;
+ } else {
+ uint32 delta;
+ uint32 curr_t = OSL_SYSUPTIME();
+
+ if (ctx->fc_defer_timestamp == 0) {
+ /* first signle ac scenario */
+ ctx->fc_defer_timestamp = curr_t;
+ return FALSE;
+ }
+
+ /* single AC duration, this handles wrap around, e.g. 1 - ~0 = 2. */
+ delta = curr_t - ctx->fc_defer_timestamp;
+ if (delta >= WLFC_FC_DEFER_PERIOD_MS) {
+ ctx->allow_fc = TRUE;
+ }
+ }
+ } else {
+ /* multiple ACs or BCMC in queue */
+ ctx->allow_fc = FALSE;
+ ctx->fc_defer_timestamp = 0;
+ }
+
+ return ctx->allow_fc;
+}
+
+static void
+_dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint8 if_id)
+{
+ dhd_pub_t *dhdp;
+
+ ASSERT(ctx);
+
+ dhdp = (dhd_pub_t *)ctx->dhdp;
+ ASSERT(dhdp);
+
+ if (dhdp->skip_fc && dhdp->skip_fc())
+ return;
+
+ if ((ctx->hostif_flow_state[if_id] == OFF) && !_dhd_wlfc_allow_fc(ctx, if_id))
+ return;
+
+ if ((pq->len <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) {
+ /* start traffic */
+ ctx->hostif_flow_state[if_id] = OFF;
+ /*
+ WLFC_DBGMESG(("qlen:%02d, if:%02d, ->OFF, start traffic %s()\n",
+ pq->len, if_id, __FUNCTION__));
+ */
+ WLFC_DBGMESG(("F"));
+
+ dhd_txflowcontrol(dhdp, if_id, OFF);
+
+ ctx->toggle_host_if = 0;
+ }
+
+ if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) {
+ /* stop traffic */
+ ctx->hostif_flow_state[if_id] = ON;
+ /*
+ WLFC_DBGMESG(("qlen:%02d, if:%02d, ->ON, stop traffic %s()\n",
+ pq->len, if_id, __FUNCTION__));
+ */
+ WLFC_DBGMESG(("N"));
+
+ dhd_txflowcontrol(dhdp, if_id, ON);
+
+ ctx->host_ifidx = if_id;
+ ctx->toggle_host_if = 1;
+ }
+
+ return;
+}
+
+static int
+_dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry,
+ uint8 ta_bmp)
+{
+ int rc = BCME_OK;
+ void* p = NULL;
+ int dummylen = ((dhd_pub_t *)ctx->dhdp)->hdrlen+ 16;
+ dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
+
+ if (dhdp->proptxstatus_txoff) {
+ rc = BCME_NORESOURCE;
+ return rc;
+ }
+
+ /* allocate a dummy packet */
+ p = PKTGET(ctx->osh, dummylen, TRUE);
+ if (p) {
+ PKTPULL(ctx->osh, p, dummylen);
+ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), 0);
+ _dhd_wlfc_pushheader(ctx, p, TRUE, ta_bmp, entry->mac_handle, 0, 0, FALSE);
+ DHD_PKTTAG_SETSIGNALONLY(PKTTAG(p), 1);
+ DHD_PKTTAG_WLFCPKT_SET(PKTTAG(p), 1);
+#ifdef PROP_TXSTATUS_DEBUG
+ ctx->stats.signal_only_pkts_sent++;
+#endif
+
+#if defined(BCMPCIE)
+ rc = dhd_bus_txdata(dhdp->bus, p, ctx->host_ifidx);
+#else
+ rc = dhd_bus_txdata(dhdp->bus, p);
+#endif
+ if (rc != BCME_OK) {
+ _dhd_wlfc_pullheader(ctx, p);
+ PKTFREE(ctx->osh, p, TRUE);
+ }
+ }
+ else {
+ DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n",
+ __FUNCTION__, dummylen));
+ rc = BCME_NOMEM;
+ }
+ return rc;
+}
+
+/* Return TRUE if traffic availability changed */
+static bool
+_dhd_wlfc_traffic_pending_check(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry,
+ int prec)
+{
+ bool rc = FALSE;
+
+ if (entry->state == WLFC_STATE_CLOSE) {
+ if ((pktq_plen(&entry->psq, (prec << 1)) == 0) &&
+ (pktq_plen(&entry->psq, ((prec << 1) + 1)) == 0)) {
+
+ if (entry->traffic_pending_bmp & NBITVAL(prec)) {
+ rc = TRUE;
+ entry->traffic_pending_bmp =
+ entry->traffic_pending_bmp & ~ NBITVAL(prec);
+ }
+ }
+ else {
+ if (!(entry->traffic_pending_bmp & NBITVAL(prec))) {
+ rc = TRUE;
+ entry->traffic_pending_bmp =
+ entry->traffic_pending_bmp | NBITVAL(prec);
+ }
+ }
+ }
+ if (rc) {
+ /* request a TIM update to firmware at the next piggyback opportunity */
+ if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) {
+ entry->send_tim_signal = 1;
+ _dhd_wlfc_send_signalonly_packet(ctx, entry, entry->traffic_pending_bmp);
+ entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
+ entry->send_tim_signal = 0;
+ }
+ else {
+ rc = FALSE;
+ }
+ }
+ return rc;
+}
+
+static int
+_dhd_wlfc_enque_suppressed(athost_wl_status_info_t* ctx, int prec, void* p)
+{
+ wlfc_mac_descriptor_t* entry;
+
+ entry = _dhd_wlfc_find_table_entry(ctx, p);
+ if (entry == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_NOTFOUND;
+ }
+ /*
+ - suppressed packets go to sub_queue[2*prec + 1] AND
+ - delayed packets go to sub_queue[2*prec + 0] to ensure
+ order of delivery.
+ */
+ if (_dhd_wlfc_prec_enq_with_drop(ctx->dhdp, &entry->psq, p, ((prec << 1) + 1), FALSE,
+ WLFC_SEQCOUNT(entry, prec))
+ == FALSE) {
+ ctx->stats.delayq_full_error++;
+ /* WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); */
+ WLFC_DBGMESG(("s"));
+ return BCME_ERROR;
+ }
+
+ /* A packet has been pushed, update traffic availability bitmap, if applicable */
+ _dhd_wlfc_traffic_pending_check(ctx, entry, prec);
+ _dhd_wlfc_flow_control_check(ctx, &entry->psq, DHD_PKTTAG_IF(PKTTAG(p)));
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx,
+ wlfc_mac_descriptor_t* entry, void* p, int header_needed, uint32* slot)
+{
+ int rc = BCME_OK;
+ int hslot = WLFC_HANGER_MAXITEMS;
+ bool send_tim_update = FALSE;
+ uint32 htod = 0;
+ uint16 htodseq = 0;
+ uint8 free_ctr;
+ int gen = 0xff;
+ dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
+
+ *slot = hslot;
+
+ if (entry == NULL) {
+ entry = _dhd_wlfc_find_table_entry(ctx, p);
+ }
+
+ if (entry == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_ERROR;
+ }
+
+ if (entry->send_tim_signal) {
+ send_tim_update = TRUE;
+ entry->send_tim_signal = 0;
+ entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
+ }
+
+ if (header_needed) {
+ if (WLFC_GET_AFQ(dhdp->wlfc_mode)) {
+ hslot = (uint)(entry - &ctx->destination_entries.nodes[0]);
+ } else {
+ hslot = _dhd_wlfc_hanger_get_free_slot(ctx->hanger);
+ }
+ gen = entry->generation;
+ free_ctr = WLFC_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p)));
+ } else {
+ if (WLFC_GET_REUSESEQ(dhdp->wlfc_mode)) {
+ htodseq = DHD_PKTTAG_H2DSEQ(PKTTAG(p));
+ }
+
+ hslot = WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
+
+ if (WLFC_GET_REORDERSUPP(dhdp->wlfc_mode)) {
+ gen = entry->generation;
+ } else if (WLFC_GET_AFQ(dhdp->wlfc_mode)) {
+ gen = WL_TXSTATUS_GET_GENERATION(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
+ } else {
+ _dhd_wlfc_hanger_get_genbit(ctx->hanger, p, hslot, &gen);
+ }
+
+ free_ctr = WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
+ /* remove old header */
+ _dhd_wlfc_pullheader(ctx, p);
+ }
+
+ if (hslot >= WLFC_HANGER_MAXITEMS) {
+ DHD_ERROR(("Error: %s():no hanger slot available\n", __FUNCTION__));
+ return BCME_ERROR;
+ }
+
+ WL_TXSTATUS_SET_FREERUNCTR(htod, free_ctr);
+ WL_TXSTATUS_SET_HSLOT(htod, hslot);
+ WL_TXSTATUS_SET_FIFO(htod, DHD_PKTTAG_FIFO(PKTTAG(p)));
+ WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST);
+ WL_TXSTATUS_SET_GENERATION(htod, gen);
+ DHD_PKTTAG_SETPKTDIR(PKTTAG(p), 1);
+
+ if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) {
+ /*
+ Indicate that this packet is being sent in response to an
+ explicit request from the firmware side.
+ */
+ WLFC_PKTFLAG_SET_PKTREQUESTED(htod);
+ } else {
+ WLFC_PKTFLAG_CLR_PKTREQUESTED(htod);
+ }
+
+ rc = _dhd_wlfc_pushheader(ctx, p, send_tim_update,
+ entry->traffic_lastreported_bmp, entry->mac_handle, htod, htodseq, FALSE);
+ if (rc == BCME_OK) {
+ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod);
+
+ if (!WLFC_GET_AFQ(dhdp->wlfc_mode) && header_needed) {
+ /*
+ a new header was created for this packet.
+ push to hanger slot and scrub q. Since bus
+ send succeeded, increment seq number as well.
+ */
+ rc = _dhd_wlfc_hanger_pushpkt(ctx->hanger, p, hslot);
+ if (rc == BCME_OK) {
+#ifdef PROP_TXSTATUS_DEBUG
+ ((wlfc_hanger_t*)(ctx->hanger))->items[hslot].push_time =
+ OSL_SYSUPTIME();
+#endif
+ } else {
+ DHD_ERROR(("%s() hanger_pushpkt() failed, rc: %d\n",
+ __FUNCTION__, rc));
+ }
+ }
+
+ if ((rc == BCME_OK) && header_needed) {
+ /* increment free running sequence count */
+ WLFC_INCR_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p)));
+ }
+ }
+ *slot = hslot;
+ return rc;
+}
+
+static int
+_dhd_wlfc_is_destination_open(athost_wl_status_info_t* ctx,
+ wlfc_mac_descriptor_t* entry, int prec)
+{
+ if (entry->interface_id >= WLFC_MAX_IFNUM) {
+ ASSERT(&ctx->destination_entries.other == entry);
+ return 1;
+ }
+ if (ctx->destination_entries.interfaces[entry->interface_id].iftype ==
+ WLC_E_IF_ROLE_P2P_GO) {
+ /* - destination interface is of type p2p GO.
+ For a p2pGO interface, if the destination is OPEN but the interface is
+ CLOSEd, do not send traffic. But if the dstn is CLOSEd while there is
+ destination-specific-credit left send packets. This is because the
+ firmware storing the destination-specific-requested packet in queue.
+ */
+ if ((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) &&
+ (entry->requested_packet == 0)) {
+ return 0;
+ }
+ }
+ /* AP, p2p_go -> unicast desc entry, STA/p2p_cl -> interface desc. entry */
+ if (((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) &&
+ (entry->requested_packet == 0)) ||
+ (!(entry->ac_bitmap & (1 << prec)))) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void*
+_dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, int prec,
+ uint8* ac_credit_spent, uint8* needs_hdr, wlfc_mac_descriptor_t** entry_out,
+ bool only_no_credit)
+{
+ dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
+ wlfc_mac_descriptor_t* entry;
+ int total_entries;
+ void* p = NULL;
+ int i;
+
+ *entry_out = NULL;
+ /* most cases a packet will count against FIFO credit */
+ *ac_credit_spent = ((prec == AC_COUNT) && !ctx->bcmc_credit_supported) ? 0 : 1;
+
+ /* search all entries, include nodes as well as interfaces */
+ if (only_no_credit) {
+ total_entries = ctx->requested_entry_count;
+ } else {
+ total_entries = ctx->active_entry_count;
+ }
+
+ for (i = 0; i < total_entries; i++) {
+ if (only_no_credit) {
+ entry = ctx->requested_entry[i];
+ } else {
+ entry = ctx->active_entry_head;
+ /* move head to ensure fair round-robin */
+ ctx->active_entry_head = ctx->active_entry_head->next;
+ }
+ ASSERT(entry);
+
+ if (entry->occupied && _dhd_wlfc_is_destination_open(ctx, entry, prec) &&
+ (entry->transit_count < WL_TXSTATUS_FREERUNCTR_MASK) &&
+ !(WLFC_GET_REORDERSUPP(dhdp->wlfc_mode) && entry->suppressed)) {
+ if (entry->state == WLFC_STATE_CLOSE) {
+ *ac_credit_spent = 0;
+ }
+
+ /* higher precedence will be picked up first,
+ * i.e. suppressed packets before delayed ones
+ */
+ p = pktq_pdeq(&entry->psq, PSQ_SUP_IDX(prec));
+ *needs_hdr = 0;
+ if (p == NULL) {
+ if (entry->suppressed == TRUE) {
+ /* skip this entry */
+ continue;
+ }
+ /* De-Q from delay Q */
+ p = pktq_pdeq(&entry->psq, PSQ_DLY_IDX(prec));
+ *needs_hdr = 1;
+ }
+
+ if (p != NULL) {
+ /* did the packet come from suppress sub-queue? */
+ if (entry->requested_credit > 0) {
+ entry->requested_credit--;
+#ifdef PROP_TXSTATUS_DEBUG
+ entry->dstncredit_sent_packets++;
+#endif
+ } else if (entry->requested_packet > 0) {
+ entry->requested_packet--;
+ DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p));
+ }
+
+ *entry_out = entry;
+ ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec]--;
+ ctx->pkt_cnt_per_ac[prec]--;
+ _dhd_wlfc_flow_control_check(ctx, &entry->psq,
+ DHD_PKTTAG_IF(PKTTAG(p)));
+ /*
+ A packet has been picked up, update traffic
+ availability bitmap, if applicable
+ */
+ _dhd_wlfc_traffic_pending_check(ctx, entry, prec);
+ return p;
+ }
+ }
+ }
+ return NULL;
+}
+
+static int
+_dhd_wlfc_enque_delayq(athost_wl_status_info_t* ctx, void* pktbuf, int prec)
+{
+ wlfc_mac_descriptor_t* entry;
+
+ if (pktbuf != NULL) {
+ entry = _dhd_wlfc_find_table_entry(ctx, pktbuf);
+ if (entry == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_ERROR;
+ }
+
+ /*
+ - suppressed packets go to sub_queue[2*prec + 1] AND
+ - delayed packets go to sub_queue[2*prec + 0] to ensure
+ order of delivery.
+ */
+ if (_dhd_wlfc_prec_enq_with_drop(ctx->dhdp, &entry->psq, pktbuf, (prec << 1),
+ FALSE, WLFC_SEQCOUNT(entry, prec))
+ == FALSE) {
+ WLFC_DBGMESG(("D"));
+ ctx->stats.delayq_full_error++;
+ return BCME_ERROR;
+ }
+
+
+ /*
+ A packet has been pushed, update traffic availability bitmap,
+ if applicable
+ */
+ _dhd_wlfc_traffic_pending_check(ctx, entry, prec);
+ }
+
+ return BCME_OK;
+}
+
+static bool _dhd_wlfc_ifpkt_fn(void* p, void *p_ifid)
+{
+ if (!p || !p_ifid)
+ return FALSE;
+
+ return (DHD_PKTTAG_WLFCPKT(PKTTAG(p))&& (*((uint8 *)p_ifid) == DHD_PKTTAG_IF(PKTTAG(p))));
+}
+
+static bool _dhd_wlfc_entrypkt_fn(void* p, void *entry)
+{
+ if (!p || !entry)
+ return FALSE;
+
+ return (DHD_PKTTAG_WLFCPKT(PKTTAG(p))&& (entry == DHD_PKTTAG_ENTRY(PKTTAG(p))));
+}
+
+static void
+_dhd_wlfc_return_implied_credit(athost_wl_status_info_t* wlfc, void* pkt)
+{
+ dhd_pub_t *dhdp;
+
+ if (!wlfc || !pkt) {
+ return;
+ }
+
+ dhdp = (dhd_pub_t *)(wlfc->dhdp);
+ if (dhdp && (dhdp->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) &&
+ DHD_PKTTAG_CREDITCHECK(PKTTAG(pkt))) {
+ int lender, credit_returned = 0;
+ uint8 fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pkt));
+
+ /* Note that borrower is fifo_id */
+ /* Return credits to highest priority lender first */
+ for (lender = AC_COUNT; lender >= 0; lender--) {
+ if (wlfc->credits_borrowed[fifo_id][lender] > 0) {
+ wlfc->FIFO_credit[lender]++;
+ wlfc->credits_borrowed[fifo_id][lender]--;
+ credit_returned = 1;
+ break;
+ }
+ }
+
+ if (!credit_returned) {
+ wlfc->FIFO_credit[fifo_id]++;
+ }
+ }
+}
+
+static void
+_dhd_wlfc_pktq_flush(athost_wl_status_info_t* ctx, struct pktq *pq,
+ bool dir, f_processpkt_t fn, void *arg, q_type_t q_type)
+{
+ int prec;
+ dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
+
+ ASSERT(dhdp);
+
+ /* Optimize flush, if pktq len = 0, just return.
+ * pktq len of 0 means pktq's prec q's are all empty.
+ */
+ if (pq->len == 0) {
+ return;
+ }
+
+
+ for (prec = 0; prec < pq->num_prec; prec++) {
+ struct pktq_prec *q;
+ void *p, *prev = NULL;
+
+ q = &pq->q[prec];
+ p = q->head;
+ while (p) {
+ if (fn == NULL || (*fn)(p, arg)) {
+ bool head = (p == q->head);
+ if (head)
+ q->head = PKTLINK(p);
+ else
+ PKTSETLINK(prev, PKTLINK(p));
+ if (q_type == Q_TYPE_PSQ) {
+ if (!WLFC_GET_AFQ(dhdp->wlfc_mode) && (prec & 1)) {
+ _dhd_wlfc_hanger_remove_reference(ctx->hanger, p);
+ }
+ ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec>>1]--;
+ ctx->pkt_cnt_per_ac[prec>>1]--;
+ ctx->stats.cleanup_psq_cnt++;
+ if (!(prec & 1)) {
+ /* pkt in delayed q, so fake push BDC header for
+ * dhd_tcpack_check_xmit() and dhd_txcomplete().
+ */
+ _dhd_wlfc_pushheader(ctx, p, FALSE, 0, 0,
+ 0, 0, TRUE);
+#ifdef DHDTCPACK_SUPPRESS
+ if (dhd_tcpack_check_xmit(dhdp, p) == BCME_ERROR) {
+ DHD_ERROR(("%s %d: tcpack_suppress ERROR!!!"
+ " Stop using it\n",
+ __FUNCTION__, __LINE__));
+ dhd_tcpack_suppress_set(dhdp,
+ TCPACK_SUP_OFF);
+ }
+#endif /* DHDTCPACK_SUPPRESS */
+ }
+ } else if (q_type == Q_TYPE_AFQ) {
+ wlfc_mac_descriptor_t* entry =
+ _dhd_wlfc_find_table_entry(ctx, p);
+ entry->transit_count--;
+ if (entry->suppressed &&
+ (--entry->suppr_transit_count == 0)) {
+ entry->suppressed = FALSE;
+ }
+ _dhd_wlfc_return_implied_credit(ctx, p);
+ ctx->stats.cleanup_fw_cnt++;
+ }
+ PKTSETLINK(p, NULL);
+ dhd_txcomplete(dhdp, p, FALSE);
+ PKTFREE(ctx->osh, p, dir);
+ if (dir) {
+ ctx->stats.pktout++;
+ }
+ q->len--;
+ pq->len--;
+ p = (head ? q->head : PKTLINK(prev));
+ } else {
+ prev = p;
+ p = PKTLINK(p);
+ }
+ }
+
+ if (q->head == NULL) {
+ ASSERT(q->len == 0);
+ q->tail = NULL;
+ }
+
+ }
+
+ if (fn == NULL)
+ ASSERT(pq->len == 0);
+}
+
+static void*
+_dhd_wlfc_pktq_pdeq_with_fn(struct pktq *pq, int prec, f_processpkt_t fn, void *arg)
+{
+ struct pktq_prec *q;
+ void *p, *prev = NULL;
+
+ ASSERT(prec >= 0 && prec < pq->num_prec);
+
+ q = &pq->q[prec];
+ p = q->head;
+
+ while (p) {
+ if (fn == NULL || (*fn)(p, arg)) {
+ break;
+ } else {
+ prev = p;
+ p = PKTLINK(p);
+ }
+ }
+ if (p == NULL)
+ return NULL;
+
+ if (prev == NULL) {
+ if ((q->head = PKTLINK(p)) == NULL) {
+ q->tail = NULL;
+ }
+ } else {
+ PKTSETLINK(prev, PKTLINK(p));
+ if (q->tail == p) {
+ q->tail = prev;
+ }
+ }
+
+ q->len--;
+
+ pq->len--;
+
+ PKTSETLINK(p, NULL);
+
+ return p;
+}
+
+static void
+_dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
+{
+ int prec;
+ void *pkt = NULL, *head = NULL, *tail = NULL;
+ struct pktq *txq = (struct pktq *)dhd_bus_txq(dhd->bus);
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger;
+ wlfc_mac_descriptor_t* entry;
+
+ dhd_os_sdlock_txq(dhd);
+ for (prec = 0; prec < txq->num_prec; prec++) {
+ while ((pkt = _dhd_wlfc_pktq_pdeq_with_fn(txq, prec, fn, arg))) {
+#ifdef DHDTCPACK_SUPPRESS
+ if (dhd_tcpack_check_xmit(dhd, pkt) == BCME_ERROR) {
+ DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
+ __FUNCTION__, __LINE__));
+ dhd_tcpack_suppress_set(dhd, TCPACK_SUP_OFF);
+ }
+#endif /* DHDTCPACK_SUPPRESS */
+ if (!head) {
+ head = pkt;
+ }
+ if (tail) {
+ PKTSETLINK(tail, pkt);
+ }
+ tail = pkt;
+ }
+ }
+ dhd_os_sdunlock_txq(dhd);
+
+
+ while ((pkt = head)) {
+ head = PKTLINK(pkt);
+ PKTSETLINK(pkt, NULL);
+ entry = _dhd_wlfc_find_table_entry(wlfc, pkt);
+
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode) &&
+ !_dhd_wlfc_hanger_remove_reference(h, pkt)) {
+ DHD_ERROR(("%s: can't find pkt(%p) in hanger, free it anyway\n",
+ __FUNCTION__, pkt));
+ }
+ entry->transit_count--;
+ if (entry->suppressed &&
+ (--entry->suppr_transit_count == 0)) {
+ entry->suppressed = FALSE;
+ }
+ _dhd_wlfc_return_implied_credit(wlfc, pkt);
+ dhd_txcomplete(dhd, pkt, FALSE);
+ PKTFREE(wlfc->osh, pkt, TRUE);
+ wlfc->stats.pktout++;
+ wlfc->stats.cleanup_txq_cnt++;
+
+ }
+}
+
+void
+_dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
+{
+ int i;
+ int total_entries;
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ wlfc_mac_descriptor_t* table;
+ wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger;
+
+ wlfc->stats.cleanup_txq_cnt = 0;
+ wlfc->stats.cleanup_psq_cnt = 0;
+ wlfc->stats.cleanup_fw_cnt = 0;
+ /*
+ * flush sequence shoulde be txq -> psq -> hanger/afq, hanger has to be last one
+ */
+ /* flush bus->txq */
+ _dhd_wlfc_cleanup_txq(dhd, fn, arg);
+
+
+ /* flush psq, search all entries, include nodes as well as interfaces */
+ total_entries = sizeof(wlfc->destination_entries)/sizeof(wlfc_mac_descriptor_t);
+ table = (wlfc_mac_descriptor_t*)&wlfc->destination_entries;
+
+ for (i = 0; i < total_entries; i++) {
+ if (table[i].occupied) {
+ /* release packets held in PSQ (both delayed and suppressed) */
+ if (table[i].psq.len) {
+ WLFC_DBGMESG(("%s(): PSQ[%d].len = %d\n",
+ __FUNCTION__, i, table[i].psq.len));
+ _dhd_wlfc_pktq_flush(wlfc, &table[i].psq, TRUE,
+ fn, arg, Q_TYPE_PSQ);
+ }
+
+ /* free packets held in AFQ */
+ if (WLFC_GET_AFQ(dhd->wlfc_mode) && (table[i].afq.len)) {
+ _dhd_wlfc_pktq_flush(wlfc, &table[i].afq, TRUE,
+ fn, arg, Q_TYPE_AFQ);
+ }
+
+ if ((fn == NULL) && (&table[i] != &wlfc->destination_entries.other)) {
+ table[i].occupied = 0;
+ if (table[i].transit_count || table[i].suppr_transit_count) {
+ DHD_ERROR(("%s: table[%d] transit(%d), suppr_tansit(%d)\n",
+ __FUNCTION__, i,
+ table[i].transit_count,
+ table[i].suppr_transit_count));
+ }
+ }
+ }
+ }
+
+ /*
+ . flush remained pkt in hanger queue, not in bus->txq nor psq.
+ . the remained pkt was successfully downloaded to dongle already.
+ . hanger slot state cannot be set to free until receive txstatus update.
+ */
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ for (i = 0; i < h->max_items; i++) {
+ if ((h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) ||
+ (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) {
+ if (fn == NULL || (*fn)(h->items[i].pkt, arg)) {
+ table = _dhd_wlfc_find_table_entry(wlfc, h->items[i].pkt);
+ table->transit_count--;
+ if (table->suppressed &&
+ (--table->suppr_transit_count == 0)) {
+ table->suppressed = FALSE;
+ }
+ _dhd_wlfc_return_implied_credit(wlfc, h->items[i].pkt);
+ dhd_txcomplete(dhd, h->items[i].pkt, FALSE);
+ PKTFREE(wlfc->osh, h->items[i].pkt, TRUE);
+ wlfc->stats.pktout++;
+ wlfc->stats.cleanup_fw_cnt++;
+ h->items[i].state = WLFC_HANGER_ITEM_STATE_WAIT_CLEAN;
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+static int
+_dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry,
+ uint8 action, uint8 ifid, uint8 iftype, uint8* ea,
+ f_processpkt_t fn, void *arg)
+{
+ int rc = BCME_OK;
+
+
+ if ((action == eWLFC_MAC_ENTRY_ACTION_ADD) || (action == eWLFC_MAC_ENTRY_ACTION_UPDATE)) {
+ entry->occupied = 1;
+ entry->state = WLFC_STATE_OPEN;
+ entry->requested_credit = 0;
+ entry->interface_id = ifid;
+ entry->iftype = iftype;
+ entry->ac_bitmap = 0xff; /* update this when handling APSD */
+ /* for an interface entry we may not care about the MAC address */
+ if (ea != NULL)
+ memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN);
+
+#ifdef P2PONEINT
+ if ((action == eWLFC_MAC_ENTRY_ACTION_ADD) ||
+ ((action == eWLFC_MAC_ENTRY_ACTION_UPDATE) && (entry->psq.num_prec == 0))) {
+#else
+ if (action == eWLFC_MAC_ENTRY_ACTION_ADD) {
+#endif
+ dhd_pub_t *dhdp = (dhd_pub_t *)(ctx->dhdp);
+ pktq_init(&entry->psq, WLFC_PSQ_PREC_COUNT, WLFC_PSQ_LEN);
+ if (WLFC_GET_AFQ(dhdp->wlfc_mode)) {
+ pktq_init(&entry->afq, WLFC_AFQ_PREC_COUNT, WLFC_PSQ_LEN);
+ }
+
+ if (entry->next == NULL) {
+ /* not linked to anywhere, add to tail */
+ if (ctx->active_entry_head) {
+ entry->prev = ctx->active_entry_head->prev;
+ ctx->active_entry_head->prev->next = entry;
+ ctx->active_entry_head->prev = entry;
+ entry->next = ctx->active_entry_head;
+
+ } else {
+ ASSERT(ctx->active_entry_count == 0);
+ entry->prev = entry->next = entry;
+ ctx->active_entry_head = entry;
+ }
+ ctx->active_entry_count++;
+ } else {
+ DHD_ERROR(("%s():%d, entry(%d)\n", __FUNCTION__, __LINE__,
+ (int)(entry - &ctx->destination_entries.nodes[0])));
+ }
+ }
+ } else if (action == eWLFC_MAC_ENTRY_ACTION_DEL) {
+ /* When the entry is deleted, the packets that are queued in the entry must be
+ cleanup. The cleanup action should be before the occupied is set as 0.
+ */
+ _dhd_wlfc_cleanup(ctx->dhdp, fn, arg);
+ _dhd_wlfc_flow_control_check(ctx, &entry->psq, ifid);
+
+ entry->occupied = 0;
+ entry->suppressed = 0;
+ entry->state = WLFC_STATE_CLOSE;
+ entry->requested_credit = 0;
+ entry->transit_count = 0;
+ entry->suppr_transit_count = 0;
+ memset(&entry->ea[0], 0, ETHER_ADDR_LEN);
+
+ if (entry->next) {
+ /* not floating, remove from Q */
+ if (ctx->active_entry_count <= 1) {
+ /* last item */
+ ctx->active_entry_head = NULL;
+ ctx->active_entry_count = 0;
+ } else {
+ entry->prev->next = entry->next;
+ entry->next->prev = entry->prev;
+ if (entry == ctx->active_entry_head) {
+ ctx->active_entry_head = entry->next;
+ }
+ ctx->active_entry_count--;
+ }
+ entry->next = entry->prev = NULL;
+ } else {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ }
+ }
+ return rc;
+}
+
+#ifdef LIMIT_BORROW
+static int
+_dhd_wlfc_borrow_credit(athost_wl_status_info_t* ctx, int highest_lender_ac, int borrower_ac)
+{
+ int lender_ac;
+ int rc = -1;
+
+ if (ctx == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return -1;
+ }
+
+ /* Borrow from lowest priority available AC (including BC/MC credits) */
+ for (lender_ac = 0; lender_ac <= highest_lender_ac; lender_ac++) {
+ if (ctx->FIFO_credit[lender_ac] > 0) {
+ ctx->credits_borrowed[borrower_ac][lender_ac]++;
+ ctx->FIFO_credit[lender_ac]--;
+ rc = lender_ac;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static int _dhd_wlfc_return_credit(athost_wl_status_info_t* ctx, int lender_ac, int borrower_ac)
+{
+ if ((ctx == NULL) || (lender_ac < 0) || (lender_ac > AC_COUNT) ||
+ (borrower_ac < 0) || (borrower_ac > AC_COUNT)) {
+ DHD_ERROR(("Error: %s():%d, ctx(%p), lender_ac(%d), borrower_ac(%d)\n",
+ __FUNCTION__, __LINE__, ctx, lender_ac, borrower_ac));
+
+ return BCME_BADARG;
+ }
+
+ ctx->credits_borrowed[borrower_ac][lender_ac]--;
+ ctx->FIFO_credit[lender_ac]++;
+
+ return BCME_OK;
+}
+#endif /* LIMIT_BORROW */
+
+static int
+_dhd_wlfc_interface_entry_update(void* state,
+ uint8 action, uint8 ifid, uint8 iftype, uint8* ea)
+{
+ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state;
+ wlfc_mac_descriptor_t* entry;
+
+ if (ifid >= WLFC_MAX_IFNUM)
+ return BCME_BADARG;
+
+ entry = &ctx->destination_entries.interfaces[ifid];
+
+ return _dhd_wlfc_mac_entry_update(ctx, entry, action, ifid, iftype, ea,
+ _dhd_wlfc_ifpkt_fn, &ifid);
+}
+
+static int
+_dhd_wlfc_BCMCCredit_support_update(void* state)
+{
+ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state;
+
+ ctx->bcmc_credit_supported = TRUE;
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits)
+{
+ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state;
+ int i;
+
+ for (i = 0; i <= 4; i++) {
+ if (ctx->Init_FIFO_credit[i] != ctx->FIFO_credit[i]) {
+ DHD_ERROR(("%s: credit[i] is not returned, (%d %d)\n",
+ __FUNCTION__, ctx->Init_FIFO_credit[i], ctx->FIFO_credit[i]));
+ }
+ }
+
+ /* update the AC FIFO credit map */
+ ctx->FIFO_credit[0] += (credits[0] - ctx->Init_FIFO_credit[0]);
+ ctx->FIFO_credit[1] += (credits[1] - ctx->Init_FIFO_credit[1]);
+ ctx->FIFO_credit[2] += (credits[2] - ctx->Init_FIFO_credit[2]);
+ ctx->FIFO_credit[3] += (credits[3] - ctx->Init_FIFO_credit[3]);
+ ctx->FIFO_credit[4] += (credits[4] - ctx->Init_FIFO_credit[4]);
+
+ ctx->Init_FIFO_credit[0] = credits[0];
+ ctx->Init_FIFO_credit[1] = credits[1];
+ ctx->Init_FIFO_credit[2] = credits[2];
+ ctx->Init_FIFO_credit[3] = credits[3];
+ ctx->Init_FIFO_credit[4] = credits[4];
+
+ /* credit for ATIM FIFO is not used yet. */
+ ctx->Init_FIFO_credit[5] = ctx->FIFO_credit[5] = 0;
+
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac,
+ dhd_wlfc_commit_info_t *commit_info, f_commitpkt_t fcommit, void* commit_ctx)
+{
+ uint32 hslot;
+ int rc;
+ dhd_pub_t *dhdp = (dhd_pub_t *)(ctx->dhdp);
+
+ /*
+ if ac_fifo_credit_spent = 0
+
+ This packet will not count against the FIFO credit.
+ To ensure the txstatus corresponding to this packet
+ does not provide an implied credit (default behavior)
+ mark the packet accordingly.
+
+ if ac_fifo_credit_spent = 1
+
+ This is a normal packet and it counts against the FIFO
+ credit count.
+ */
+ DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), commit_info->ac_fifo_credit_spent);
+ rc = _dhd_wlfc_pretx_pktprocess(ctx, commit_info->mac_entry, commit_info->p,
+ commit_info->needs_hdr, &hslot);
+
+ if (rc == BCME_OK) {
+ DHD_PKTTAG_WLFCPKT_SET(PKTTAG(commit_info->p), 1);
+ rc = fcommit(commit_ctx, commit_info->p);
+ if (rc == BCME_OK) {
+ uint8 gen = WL_TXSTATUS_GET_GENERATION(
+ DHD_PKTTAG_H2DTAG(PKTTAG(commit_info->p)));
+ if (!WLFC_GET_AFQ(dhdp->wlfc_mode)) {
+ _dhd_wlfc_hanger_waitevent_set(ctx->hanger, hslot,
+ WLFC_HANGER_ITEM_WAIT_EVENT_COUNT);
+ }
+ ctx->stats.pkt2bus++;
+ if (commit_info->ac_fifo_credit_spent || (ac == AC_COUNT)) {
+ ctx->stats.send_pkts[ac]++;
+ WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac);
+ }
+
+ if (gen != commit_info->mac_entry->generation) {
+ /* will be suppressed back by design */
+ if (!commit_info->mac_entry->suppressed) {
+ commit_info->mac_entry->suppressed = TRUE;
+ }
+ commit_info->mac_entry->suppr_transit_count++;
+ }
+ commit_info->mac_entry->transit_count++;
+ } else if (commit_info->needs_hdr) {
+ if (!WLFC_GET_AFQ(dhdp->wlfc_mode)) {
+ void *pout = NULL;
+ /* pop hanger for delayed packet */
+ _dhd_wlfc_hanger_poppkt(ctx->hanger, WL_TXSTATUS_GET_HSLOT(
+ DHD_PKTTAG_H2DTAG(PKTTAG(commit_info->p))), &pout, 1);
+ ASSERT(commit_info->p == pout);
+ }
+ }
+ } else {
+ ctx->stats.generic_error++;
+ }
+
+ if (rc != BCME_OK) {
+ /*
+ pretx pkt process or bus commit has failed, rollback.
+ - remove wl-header for a delayed packet
+ - save wl-header header for suppressed packets
+ - reset credit check flag
+ */
+ _dhd_wlfc_rollback_packet_toq(ctx, commit_info->p, commit_info->pkt_type, hslot);
+ DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), 0);
+ }
+
+ return rc;
+}
+
+static uint8
+_dhd_wlfc_find_mac_desc_id_from_mac(dhd_pub_t *dhdp, uint8* ea)
+{
+ wlfc_mac_descriptor_t* table =
+ ((athost_wl_status_info_t*)dhdp->wlfc_state)->destination_entries.nodes;
+ uint8 table_index;
+
+ if (ea != NULL) {
+ for (table_index = 0; table_index < WLFC_MAC_DESC_TABLE_SIZE; table_index++) {
+ if ((memcmp(ea, &table[table_index].ea[0], ETHER_ADDR_LEN) == 0) &&
+ table[table_index].occupied)
+ return table_index;
+ }
+ }
+ return WLFC_MAC_DESC_ID_INVALID;
+}
+
+static int
+_dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len, void** p_mac)
+{
+ uint8 status_flag;
+ uint32 status;
+ int ret = BCME_OK;
+ int remove_from_hanger = 1;
+ void* pktbuf = NULL;
+ uint8 fifo_id = 0, gen = 0, count = 0, hcnt;
+ uint16 hslot;
+ wlfc_mac_descriptor_t* entry = NULL;
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ uint16 seq = 0, seq_fromfw = 0, seq_num = 0;
+
+ memcpy(&status, pkt_info, sizeof(uint32));
+ status_flag = WL_TXSTATUS_GET_FLAGS(status);
+ hcnt = WL_TXSTATUS_GET_FREERUNCTR(status);
+ hslot = WL_TXSTATUS_GET_HSLOT(status);
+ fifo_id = WL_TXSTATUS_GET_FIFO(status);
+ gen = WL_TXSTATUS_GET_GENERATION(status);
+
+ if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) {
+ memcpy(&seq, pkt_info + WLFC_CTL_VALUE_LEN_TXSTATUS, WLFC_CTL_VALUE_LEN_SEQ);
+ seq_fromfw = WL_SEQ_GET_FROMFW(seq);
+ seq_num = WL_SEQ_GET_NUM(seq);
+ }
+
+ wlfc->stats.txstatus_in += len;
+
+ if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) {
+ wlfc->stats.pkt_freed += len;
+ }
+
+ else if (status_flag == WLFC_CTL_PKTFLAG_DISCARD_NOACK) {
+ wlfc->stats.pkt_freed += len;
+ }
+
+ else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) {
+ wlfc->stats.d11_suppress += len;
+ remove_from_hanger = 0;
+ }
+
+ else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) {
+ wlfc->stats.wl_suppress += len;
+ remove_from_hanger = 0;
+ }
+
+ else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) {
+ wlfc->stats.wlc_tossed_pkts += len;
+ }
+
+ if (dhd->proptxstatus_txstatus_ignore) {
+ if (!remove_from_hanger) {
+ DHD_ERROR(("suppress txstatus: %d\n", status_flag));
+ }
+ return BCME_OK;
+ }
+
+ while (count < len) {
+ if (WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ ret = _dhd_wlfc_deque_afq(wlfc, hslot, hcnt, fifo_id, &pktbuf);
+ } else {
+ if (_dhd_wlfc_hanger_wait_clean(wlfc->hanger, hslot)) {
+ goto cont;
+ }
+
+ ret = _dhd_wlfc_hanger_poppkt(wlfc->hanger, hslot, &pktbuf, 0);
+ }
+
+ if ((ret != BCME_OK) || !pktbuf) {
+ goto cont;
+ }
+
+ /* set fifo_id to correct value because not all FW does that */
+ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf));
+
+ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf);
+
+ if (!remove_from_hanger) {
+ /* this packet was suppressed */
+ if (!entry->suppressed || (entry->generation != gen)) {
+ if (!entry->suppressed) {
+ entry->suppr_transit_count = entry->transit_count;
+ if (p_mac) {
+ *p_mac = entry;
+ }
+ } else {
+ DHD_ERROR(("gen(%d), entry->generation(%d)\n",
+ gen, entry->generation));
+ }
+ entry->suppressed = TRUE;
+
+ }
+ entry->generation = gen;
+ }
+
+#ifdef PROP_TXSTATUS_DEBUG
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode))
+ {
+ uint32 new_t = OSL_SYSUPTIME();
+ uint32 old_t;
+ uint32 delta;
+ old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[hslot].push_time;
+
+
+ wlfc->stats.latency_sample_count++;
+ if (new_t > old_t)
+ delta = new_t - old_t;
+ else
+ delta = 0xffffffff + new_t - old_t;
+ wlfc->stats.total_status_latency += delta;
+ wlfc->stats.latency_most_recent = delta;
+
+ wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta;
+ if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32))
+ wlfc->stats.idx_delta = 0;
+ }
+#endif /* PROP_TXSTATUS_DEBUG */
+
+ /* pick up the implicit credit from this packet */
+ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) {
+ _dhd_wlfc_return_implied_credit(wlfc, pktbuf);
+ } else {
+ /*
+ if this packet did not count against FIFO credit, it must have
+ taken a requested_credit from the destination entry (for pspoll etc.)
+ */
+ if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf)))
+ entry->requested_credit++;
+#ifdef PROP_TXSTATUS_DEBUG
+ entry->dstncredit_acks++;
+#endif
+ }
+
+ if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) ||
+ (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) {
+ /* save generation bit inside packet */
+ WL_TXSTATUS_SET_GENERATION(DHD_PKTTAG_H2DTAG(PKTTAG(pktbuf)), gen);
+
+ if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) {
+ WL_SEQ_SET_FROMDRV(DHD_PKTTAG_H2DSEQ(PKTTAG(pktbuf)), seq_fromfw);
+ WL_SEQ_SET_NUM(DHD_PKTTAG_H2DSEQ(PKTTAG(pktbuf)), seq_num);
+ }
+
+ ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf);
+ if (ret != BCME_OK) {
+ /* delay q is full, drop this packet */
+ DHD_WLFC_QMON_COMPLETE(entry);
+ _dhd_wlfc_prec_drop(dhd, (fifo_id << 1) + 1, pktbuf, FALSE);
+ } else {
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ /* Mark suppressed to avoid a double free
+ during wlfc cleanup
+ */
+ _dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, hslot, gen);
+ }
+ }
+ } else {
+ uint8 waitevent = 0;
+ void *pktbuf_tmp = NULL;
+ dhd_txcomplete(dhd, pktbuf, TRUE);
+
+ DHD_WLFC_QMON_COMPLETE(entry);
+ wlfc->stats.pktout++;
+
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ waitevent = _dhd_wlfc_hanger_waitevent_decreturn(wlfc->hanger,
+ hslot);
+ if (!waitevent) {
+ ret = _dhd_wlfc_hanger_poppkt(wlfc->hanger,
+ hslot, &pktbuf_tmp, 1);
+ ASSERT((ret == BCME_OK) && (pktbuf == pktbuf_tmp));
+ }
+ }
+ if (!waitevent) {
+ /* free the packet */
+ PKTFREE(wlfc->osh, pktbuf, TRUE);
+ }
+ }
+ /* pkt back from firmware side */
+ entry->transit_count--;
+ if (entry->suppressed && (--entry->suppr_transit_count == 0)) {
+ entry->suppressed = FALSE;
+ }
+
+cont:
+ hcnt = (hcnt + 1) & WL_TXSTATUS_FREERUNCTR_MASK;
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ hslot = (hslot + 1) & WL_TXSTATUS_HSLOT_MASK;
+ }
+
+ if (WLFC_GET_REUSESEQ(dhd->wlfc_mode) && seq_fromfw) {
+ seq_num = (seq_num + 1) & WL_SEQ_NUM_MASK;
+ }
+
+ count++;
+ }
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits)
+{
+ int i;
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ for (i = 0; i < WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK; i++) {
+#ifdef PROP_TXSTATUS_DEBUG
+ wlfc->stats.fifo_credits_back[i] += credits[i];
+#endif
+
+ /* update FIFO credits */
+ if (dhd->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT)
+ {
+ int lender; /* Note that borrower is i */
+
+ /* Return credits to highest priority lender first */
+ for (lender = AC_COUNT; (lender >= 0) && (credits[i] > 0); lender--) {
+ if (wlfc->credits_borrowed[i][lender] > 0) {
+ if (credits[i] >= wlfc->credits_borrowed[i][lender]) {
+ credits[i] -=
+ (uint8)wlfc->credits_borrowed[i][lender];
+ wlfc->FIFO_credit[lender] +=
+ wlfc->credits_borrowed[i][lender];
+ wlfc->credits_borrowed[i][lender] = 0;
+ }
+ else {
+ wlfc->credits_borrowed[i][lender] -= credits[i];
+ wlfc->FIFO_credit[lender] += credits[i];
+ credits[i] = 0;
+ }
+ }
+ }
+
+ /* If we have more credits left over, these must belong to the AC */
+ if (credits[i] > 0) {
+ wlfc->FIFO_credit[i] += credits[i];
+ }
+
+ if (wlfc->FIFO_credit[i] > wlfc->Init_FIFO_credit[i]) {
+ wlfc->FIFO_credit[i] = wlfc->Init_FIFO_credit[i];
+ }
+ }
+ }
+
+ return BCME_OK;
+}
+
+static void
+_dhd_wlfc_suppress_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
+{
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ wlfc_mac_descriptor_t* entry;
+ int prec;
+ void *pkt = NULL, *head = NULL, *tail = NULL;
+ struct pktq *txq = (struct pktq *)dhd_bus_txq(dhd->bus);
+ uint8 results[WLFC_CTL_VALUE_LEN_TXSTATUS+WLFC_CTL_VALUE_LEN_SEQ];
+ uint8 credits[WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK] = {0};
+ uint32 htod = 0;
+ uint16 htodseq = 0;
+ bool bCreditUpdate = FALSE;
+
+ dhd_os_sdlock_txq(dhd);
+ for (prec = 0; prec < txq->num_prec; prec++) {
+ while ((pkt = _dhd_wlfc_pktq_pdeq_with_fn(txq, prec, fn, arg))) {
+ if (!head) {
+ head = pkt;
+ }
+ if (tail) {
+ PKTSETLINK(tail, pkt);
+ }
+ tail = pkt;
+ }
+ }
+ dhd_os_sdunlock_txq(dhd);
+
+ while ((pkt = head)) {
+ head = PKTLINK(pkt);
+ PKTSETLINK(pkt, NULL);
+
+ entry = _dhd_wlfc_find_table_entry(wlfc, pkt);
+
+ /* fake a suppression txstatus */
+ htod = DHD_PKTTAG_H2DTAG(PKTTAG(pkt));
+ WL_TXSTATUS_SET_FLAGS(htod, WLFC_CTL_PKTFLAG_WLSUPPRESS);
+ WL_TXSTATUS_SET_GENERATION(htod, entry->generation);
+ memcpy(results, &htod, WLFC_CTL_VALUE_LEN_TXSTATUS);
+ if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) {
+ htodseq = DHD_PKTTAG_H2DSEQ(PKTTAG(pkt));
+ if (WL_SEQ_GET_FROMDRV(htodseq)) {
+ WL_SEQ_SET_FROMFW(htodseq, 1);
+ WL_SEQ_SET_FROMDRV(htodseq, 0);
+ }
+ memcpy(results + WLFC_CTL_VALUE_LEN_TXSTATUS, &htodseq,
+ WLFC_CTL_VALUE_LEN_SEQ);
+ }
+ if (WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ _dhd_wlfc_enque_afq(wlfc, pkt);
+ }
+ _dhd_wlfc_compressed_txstatus_update(dhd, results, 1, NULL);
+
+ /* fake a fifo credit back */
+ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pkt))) {
+ credits[DHD_PKTTAG_FIFO(PKTTAG(pkt))]++;
+ bCreditUpdate = TRUE;
+ }
+ }
+
+ if (bCreditUpdate) {
+ _dhd_wlfc_fifocreditback_indicate(dhd, credits);
+ }
+}
+
+
+static int
+_dhd_wlfc_dbg_senum_check(dhd_pub_t *dhd, uint8 *value)
+{
+ uint32 timestamp;
+
+ (void)dhd;
+
+ bcopy(&value[2], &timestamp, sizeof(uint32));
+ DHD_INFO(("RXPKT: SEQ: %d, timestamp %d\n", value[1], timestamp));
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_rssi_indicate(dhd_pub_t *dhd, uint8* rssi)
+{
+ (void)dhd;
+ (void)rssi;
+ return BCME_OK;
+}
+
+static void
+_dhd_wlfc_add_requested_entry(athost_wl_status_info_t* wlfc, wlfc_mac_descriptor_t* entry)
+{
+ int i;
+
+ if (!wlfc || !entry) {
+ return;
+ }
+
+ for (i = 0; i < wlfc->requested_entry_count; i++) {
+ if (entry == wlfc->requested_entry[i]) {
+ break;
+ }
+ }
+
+ if (i == wlfc->requested_entry_count) {
+ /* no match entry found */
+ ASSERT(wlfc->requested_entry_count <= (WLFC_MAC_DESC_TABLE_SIZE-1));
+ wlfc->requested_entry[wlfc->requested_entry_count++] = entry;
+ }
+}
+
+static void
+_dhd_wlfc_remove_requested_entry(athost_wl_status_info_t* wlfc, wlfc_mac_descriptor_t* entry)
+{
+ int i;
+
+ if (!wlfc || !entry) {
+ return;
+ }
+
+ for (i = 0; i < wlfc->requested_entry_count; i++) {
+ if (entry == wlfc->requested_entry[i]) {
+ break;
+ }
+ }
+
+ if (i < wlfc->requested_entry_count) {
+ /* found */
+ ASSERT(wlfc->requested_entry_count > 0);
+ wlfc->requested_entry_count--;
+ if (i != wlfc->requested_entry_count) {
+ wlfc->requested_entry[i] =
+ wlfc->requested_entry[wlfc->requested_entry_count];
+ }
+ wlfc->requested_entry[wlfc->requested_entry_count] = NULL;
+ }
+}
+
+static int
+_dhd_wlfc_mac_table_update(dhd_pub_t *dhd, uint8* value, uint8 type)
+{
+ int rc;
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ wlfc_mac_descriptor_t* table;
+ uint8 existing_index;
+ uint8 table_index;
+ uint8 ifid;
+ uint8* ea;
+
+ WLFC_DBGMESG(("%s(), mac [%02x:%02x:%02x:%02x:%02x:%02x],%s,idx:%d,id:0x%02x\n",
+ __FUNCTION__, value[2], value[3], value[4], value[5], value[6], value[7],
+ ((type == WLFC_CTL_TYPE_MACDESC_ADD) ? "ADD":"DEL"),
+ WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]), value[0]));
+
+ table = wlfc->destination_entries.nodes;
+ table_index = WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]);
+ ifid = value[1];
+ ea = &value[2];
+
+ _dhd_wlfc_remove_requested_entry(wlfc, &table[table_index]);
+ if (type == WLFC_CTL_TYPE_MACDESC_ADD) {
+ existing_index = _dhd_wlfc_find_mac_desc_id_from_mac(dhd, &value[2]);
+ if ((existing_index != WLFC_MAC_DESC_ID_INVALID) &&
+ (existing_index != table_index) && table[existing_index].occupied) {
+ /*
+ there is an existing different entry, free the old one
+ and move it to new index if necessary.
+ */
+ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[existing_index],
+ eWLFC_MAC_ENTRY_ACTION_DEL, table[existing_index].interface_id,
+ table[existing_index].iftype, NULL, _dhd_wlfc_entrypkt_fn,
+ &table[existing_index]);
+ }
+
+ if (!table[table_index].occupied) {
+ /* this new MAC entry does not exist, create one */
+ table[table_index].mac_handle = value[0];
+ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index],
+ eWLFC_MAC_ENTRY_ACTION_ADD, ifid,
+ wlfc->destination_entries.interfaces[ifid].iftype,
+ ea, NULL, NULL);
+ } else {
+ /* the space should have been empty, but it's not */
+ wlfc->stats.mac_update_failed++;
+ }
+ }
+
+ if (type == WLFC_CTL_TYPE_MACDESC_DEL) {
+ if (table[table_index].occupied) {
+ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index],
+ eWLFC_MAC_ENTRY_ACTION_DEL, ifid,
+ wlfc->destination_entries.interfaces[ifid].iftype,
+ ea, _dhd_wlfc_entrypkt_fn, &table[table_index]);
+ } else {
+ /* the space should have been occupied, but it's not */
+ wlfc->stats.mac_update_failed++;
+ }
+ }
+ BCM_REFERENCE(rc);
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_psmode_update(dhd_pub_t *dhd, uint8* value, uint8 type)
+{
+ /* Handle PS on/off indication */
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ wlfc_mac_descriptor_t* table;
+ wlfc_mac_descriptor_t* desc;
+ uint8 mac_handle = value[0];
+ int i;
+
+ table = wlfc->destination_entries.nodes;
+ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)];
+ if (desc->occupied) {
+ /* a fresh PS mode should wipe old ps credits? */
+ desc->requested_credit = 0;
+ if (type == WLFC_CTL_TYPE_MAC_OPEN) {
+ desc->state = WLFC_STATE_OPEN;
+ desc->ac_bitmap = 0xff;
+ DHD_WLFC_CTRINC_MAC_OPEN(desc);
+ _dhd_wlfc_remove_requested_entry(wlfc, desc);
+ }
+ else {
+ desc->state = WLFC_STATE_CLOSE;
+ DHD_WLFC_CTRINC_MAC_CLOSE(desc);
+ /*
+ Indicate to firmware if there is any traffic pending.
+ */
+ for (i = 0; i < AC_COUNT; i++) {
+ _dhd_wlfc_traffic_pending_check(wlfc, desc, i);
+ }
+ }
+ }
+ else {
+ wlfc->stats.psmode_update_failed++;
+ }
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_interface_update(dhd_pub_t *dhd, uint8* value, uint8 type)
+{
+ /* Handle PS on/off indication */
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ wlfc_mac_descriptor_t* table;
+ uint8 if_id = value[0];
+
+ if (if_id < WLFC_MAX_IFNUM) {
+ table = wlfc->destination_entries.interfaces;
+ if (table[if_id].occupied) {
+ if (type == WLFC_CTL_TYPE_INTERFACE_OPEN) {
+ table[if_id].state = WLFC_STATE_OPEN;
+ /* WLFC_DBGMESG(("INTERFACE[%d] OPEN\n", if_id)); */
+ }
+ else {
+ table[if_id].state = WLFC_STATE_CLOSE;
+ /* WLFC_DBGMESG(("INTERFACE[%d] CLOSE\n", if_id)); */
+ }
+ return BCME_OK;
+ }
+ }
+ wlfc->stats.interface_update_failed++;
+
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_credit_request(dhd_pub_t *dhd, uint8* value)
+{
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ wlfc_mac_descriptor_t* table;
+ wlfc_mac_descriptor_t* desc;
+ uint8 mac_handle;
+ uint8 credit;
+
+ table = wlfc->destination_entries.nodes;
+ mac_handle = value[1];
+ credit = value[0];
+
+ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)];
+ if (desc->occupied) {
+ desc->requested_credit = credit;
+
+ desc->ac_bitmap = value[2] & (~(1<<AC_COUNT));
+ _dhd_wlfc_add_requested_entry(wlfc, desc);
+ }
+ else {
+ wlfc->stats.credit_request_failed++;
+ }
+ return BCME_OK;
+}
+
+static int
+_dhd_wlfc_packet_request(dhd_pub_t *dhd, uint8* value)
+{
+ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ wlfc_mac_descriptor_t* table;
+ wlfc_mac_descriptor_t* desc;
+ uint8 mac_handle;
+ uint8 packet_count;
+
+ table = wlfc->destination_entries.nodes;
+ mac_handle = value[1];
+ packet_count = value[0];
+
+ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)];
+ if (desc->occupied) {
+ desc->requested_packet = packet_count;
+
+ desc->ac_bitmap = value[2] & (~(1<<AC_COUNT));
+ _dhd_wlfc_add_requested_entry(wlfc, desc);
+ }
+ else {
+ wlfc->stats.packet_request_failed++;
+ }
+ return BCME_OK;
+}
+
+static void
+_dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len)
+{
+ if (info_len) {
+ if (info_buf) {
+ bcopy(val, info_buf, len);
+ *info_len = len;
+ }
+ else
+ *info_len = 0;
+ }
+}
+
+/*
+ * public functions
+ */
+
+bool dhd_wlfc_is_supported(dhd_pub_t *dhd)
+{
+ bool rc = TRUE;
+
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return FALSE;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ rc = FALSE;
+ }
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return rc;
+}
+
+int dhd_wlfc_enable(dhd_pub_t *dhd)
+{
+ int i, rc = BCME_OK;
+ athost_wl_status_info_t* wlfc;
+
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_enabled || dhd->wlfc_state) {
+ rc = BCME_OK;
+ goto exit;
+ }
+
+ /* allocate space to track txstatus propagated from firmware */
+ dhd->wlfc_state = DHD_OS_PREALLOC(dhd, DHD_PREALLOC_DHD_WLFC_INFO,
+ sizeof(athost_wl_status_info_t));
+
+ if (dhd->wlfc_state == NULL) {
+ rc = BCME_NOMEM;
+ goto exit;
+ }
+
+ /* initialize state space */
+ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ memset(wlfc, 0, sizeof(athost_wl_status_info_t));
+
+ /* remember osh & dhdp */
+ wlfc->osh = dhd->osh;
+ wlfc->dhdp = dhd;
+
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ wlfc->hanger = _dhd_wlfc_hanger_create(dhd->osh, WLFC_HANGER_MAXITEMS);
+ if (wlfc->hanger == NULL) {
+ DHD_OS_PREFREE(dhd, DHD_PREALLOC_DHD_WLFC_INFO,
+ dhd->wlfc_state, sizeof(athost_wl_status_info_t));
+ dhd->wlfc_state = NULL;
+ rc = BCME_NOMEM;
+ goto exit;
+ }
+ }
+
+ dhd->proptxstatus_mode = WLFC_FCMODE_EXPLICIT_CREDIT;
+ /* default to check rx pkt */
+ if (dhd->op_mode & DHD_FLAG_IBSS_MODE) {
+ dhd->wlfc_rxpkt_chk = FALSE;
+ } else {
+ dhd->wlfc_rxpkt_chk = TRUE;
+ }
+
+
+ /* initialize all interfaces to accept traffic */
+ for (i = 0; i < WLFC_MAX_IFNUM; i++) {
+ wlfc->hostif_flow_state[i] = OFF;
+ }
+
+ _dhd_wlfc_mac_entry_update(wlfc, &wlfc->destination_entries.other,
+ eWLFC_MAC_ENTRY_ACTION_ADD, 0xff, 0, NULL, NULL, NULL);
+
+ wlfc->allow_credit_borrow = 0;
+ wlfc->single_ac = 0;
+ wlfc->single_ac_timestamp = 0;
+
+
+exit:
+ dhd_os_wlfc_unblock(dhd);
+
+ return rc;
+}
+
+int
+dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, uchar *reorder_info_buf,
+ uint *reorder_info_len)
+{
+ uint8 type, len;
+ uint8* value;
+ uint8* tmpbuf;
+ uint16 remainder = (uint16)tlv_hdr_len;
+ uint16 processed = 0;
+ athost_wl_status_info_t* wlfc = NULL;
+ void* entry;
+
+ if ((dhd == NULL) || (pktbuf == NULL)) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (dhd->proptxstatus_mode != WLFC_ONLY_AMPDU_HOSTREORDER) {
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhd);
+ return WLFC_UNSUPPORTED;
+ }
+ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ }
+
+ tmpbuf = (uint8*)PKTDATA(dhd->osh, pktbuf);
+
+ if (remainder) {
+ while ((processed < (WLFC_MAX_PENDING_DATALEN * 2)) && (remainder > 0)) {
+ type = tmpbuf[processed];
+ if (type == WLFC_CTL_TYPE_FILLER) {
+ remainder -= 1;
+ processed += 1;
+ continue;
+ }
+
+ len = tmpbuf[processed + 1];
+ value = &tmpbuf[processed + 2];
+
+ if (remainder < (2 + len))
+ break;
+
+ remainder -= 2 + len;
+ processed += 2 + len;
+ entry = NULL;
+
+ DHD_INFO(("%s():%d type %d remainder %d processed %d\n",
+ __FUNCTION__, __LINE__, type, remainder, processed));
+
+ if (type == WLFC_CTL_TYPE_HOST_REORDER_RXPKTS)
+ _dhd_wlfc_reorderinfo_indicate(value, len, reorder_info_buf,
+ reorder_info_len);
+
+ if (wlfc == NULL) {
+ ASSERT(dhd->proptxstatus_mode == WLFC_ONLY_AMPDU_HOSTREORDER);
+
+ if (type != WLFC_CTL_TYPE_HOST_REORDER_RXPKTS &&
+ type != WLFC_CTL_TYPE_TRANS_ID)
+ DHD_INFO(("%s():%d dhd->wlfc_state is NULL yet!"
+ " type %d remainder %d processed %d\n",
+ __FUNCTION__, __LINE__, type, remainder, processed));
+ continue;
+ }
+
+ if (type == WLFC_CTL_TYPE_TXSTATUS) {
+ _dhd_wlfc_compressed_txstatus_update(dhd, value, 1, &entry);
+ }
+ else if (type == WLFC_CTL_TYPE_COMP_TXSTATUS) {
+ uint8 compcnt_offset = WLFC_CTL_VALUE_LEN_TXSTATUS;
+
+ if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) {
+ compcnt_offset += WLFC_CTL_VALUE_LEN_SEQ;
+ }
+ _dhd_wlfc_compressed_txstatus_update(dhd, value,
+ value[compcnt_offset], &entry);
+ }
+ else if (type == WLFC_CTL_TYPE_FIFO_CREDITBACK)
+ _dhd_wlfc_fifocreditback_indicate(dhd, value);
+
+ else if (type == WLFC_CTL_TYPE_RSSI)
+ _dhd_wlfc_rssi_indicate(dhd, value);
+
+ else if (type == WLFC_CTL_TYPE_MAC_REQUEST_CREDIT)
+ _dhd_wlfc_credit_request(dhd, value);
+
+ else if (type == WLFC_CTL_TYPE_MAC_REQUEST_PACKET)
+ _dhd_wlfc_packet_request(dhd, value);
+
+ else if ((type == WLFC_CTL_TYPE_MAC_OPEN) ||
+ (type == WLFC_CTL_TYPE_MAC_CLOSE))
+ _dhd_wlfc_psmode_update(dhd, value, type);
+
+ else if ((type == WLFC_CTL_TYPE_MACDESC_ADD) ||
+ (type == WLFC_CTL_TYPE_MACDESC_DEL))
+ _dhd_wlfc_mac_table_update(dhd, value, type);
+
+ else if (type == WLFC_CTL_TYPE_TRANS_ID)
+ _dhd_wlfc_dbg_senum_check(dhd, value);
+
+ else if ((type == WLFC_CTL_TYPE_INTERFACE_OPEN) ||
+ (type == WLFC_CTL_TYPE_INTERFACE_CLOSE)) {
+ _dhd_wlfc_interface_update(dhd, value, type);
+ }
+
+ if (entry && WLFC_GET_REORDERSUPP(dhd->wlfc_mode)) {
+ /* suppress all packets for this mac entry from bus->txq */
+ _dhd_wlfc_suppress_txq(dhd, _dhd_wlfc_entrypkt_fn, entry);
+ }
+ }
+ if (remainder != 0 && wlfc) {
+ /* trouble..., something is not right */
+ wlfc->stats.tlv_parse_failed++;
+ }
+ }
+
+ if (wlfc)
+ wlfc->stats.dhd_hdrpulls++;
+
+ dhd_os_wlfc_unblock(dhd);
+ return BCME_OK;
+}
+
+int
+dhd_wlfc_commit_packets(dhd_pub_t *dhdp, f_commitpkt_t fcommit, void* commit_ctx, void *pktbuf,
+ bool need_toggle_host_if)
+{
+ int ac, single_ac = 0, rc = BCME_OK;
+ dhd_wlfc_commit_info_t commit_info;
+ athost_wl_status_info_t* ctx;
+ int bus_retry_count = 0;
+
+ uint8 tx_map = 0; /* packets (send + in queue), Bitmask for 4 ACs + BC/MC */
+ uint8 rx_map = 0; /* received packets, Bitmask for 4 ACs + BC/MC */
+ uint8 packets_map = 0; /* packets in queue, Bitmask for 4 ACs + BC/MC */
+ bool no_credit = FALSE;
+
+#ifdef LIMIT_BORROW
+ int lender;
+#endif
+
+ if ((dhdp == NULL) || (fcommit == NULL)) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhdp);
+
+ if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ if (pktbuf) {
+ DHD_PKTTAG_WLFCPKT_SET(PKTTAG(pktbuf), 0);
+ }
+ rc = WLFC_UNSUPPORTED;
+ goto exit2;
+ }
+
+ ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
+
+
+ if (dhdp->proptxstatus_module_ignore) {
+ if (pktbuf) {
+ uint32 htod = 0;
+ WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST);
+ _dhd_wlfc_pushheader(ctx, pktbuf, FALSE, 0, 0, htod, 0, FALSE);
+ if (fcommit(commit_ctx, pktbuf))
+ PKTFREE(ctx->osh, pktbuf, TRUE);
+ rc = BCME_OK;
+ }
+ goto exit;
+ }
+
+ memset(&commit_info, 0, sizeof(commit_info));
+
+ /*
+ Commit packets for regular AC traffic. Higher priority first.
+ First, use up FIFO credits available to each AC. Based on distribution
+ and credits left, borrow from other ACs as applicable
+
+ -NOTE:
+ If the bus between the host and firmware is overwhelmed by the
+ traffic from host, it is possible that higher priority traffic
+ starves the lower priority queue. If that occurs often, we may
+ have to employ weighted round-robin or ucode scheme to avoid
+ low priority packet starvation.
+ */
+
+ if (pktbuf) {
+ ac = DHD_PKTTAG_FIFO(PKTTAG(pktbuf));
+ /* en-queue the packets to respective queue. */
+ rc = _dhd_wlfc_enque_delayq(ctx, pktbuf, ac);
+ if (rc)
+ _dhd_wlfc_prec_drop(ctx->dhdp, (ac << 1), pktbuf, FALSE);
+ else
+ ctx->stats.pktin++;
+ }
+
+ for (ac = AC_COUNT; ac >= 0; ac--) {
+ if (dhdp->wlfc_rxpkt_chk) {
+ /* check rx packet */
+ uint32 curr_t = OSL_SYSUPTIME(), delta;
+
+ delta = curr_t - ctx->rx_timestamp[ac];
+ if (delta < WLFC_RX_DETECTION_THRESHOLD_MS) {
+ rx_map |= (1 << ac);
+ }
+ }
+
+ if (ctx->pkt_cnt_per_ac[ac] == 0) {
+ continue;
+ }
+ tx_map |= (1 << ac);
+ single_ac = ac + 1;
+ while (FALSE == dhdp->proptxstatus_txoff) {
+ /* packets from delayQ with less priority are fresh and
+ * they'd need header and have no MAC entry
+ */
+ no_credit = (ctx->FIFO_credit[ac] < 1);
+ if (dhdp->proptxstatus_credit_ignore ||
+ ((ac == AC_COUNT) && !ctx->bcmc_credit_supported)) {
+ no_credit = FALSE;
+ }
+ commit_info.needs_hdr = 1;
+ commit_info.mac_entry = NULL;
+ commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac,
+ &(commit_info.ac_fifo_credit_spent),
+ &(commit_info.needs_hdr),
+ &(commit_info.mac_entry),
+ no_credit);
+ commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED :
+ eWLFC_PKTTYPE_SUPPRESSED;
+
+ if (commit_info.p == NULL) {
+ break;
+ }
+
+ if (!dhdp->proptxstatus_credit_ignore) {
+ ASSERT(ctx->FIFO_credit[ac] >= commit_info.ac_fifo_credit_spent);
+ }
+ /* here we can ensure have credit or no credit needed */
+ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, fcommit,
+ commit_ctx);
+
+ /* Bus commits may fail (e.g. flow control); abort after retries */
+ if (rc == BCME_OK) {
+ if (commit_info.ac_fifo_credit_spent)
+ ctx->FIFO_credit[ac]--;
+ } else {
+ bus_retry_count++;
+ if (bus_retry_count >= BUS_RETRIES) {
+ DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc));
+ goto exit;
+ }
+ }
+ }
+
+ if (ctx->pkt_cnt_per_ac[ac]) {
+ packets_map |= (1 << ac);
+ }
+ }
+
+ if ((tx_map == 0) || dhdp->proptxstatus_credit_ignore) {
+ /* nothing send out or remain in queue */
+ rc = BCME_OK;
+ goto exit;
+ }
+
+ if (((tx_map & (tx_map - 1)) == 0) && (tx_map >= rx_map)) {
+ /* only one tx ac exist and no higher rx ac */
+ if ((single_ac == ctx->single_ac) && ctx->allow_credit_borrow) {
+ ac = single_ac - 1;
+ } else {
+ uint32 delta;
+ uint32 curr_t = OSL_SYSUPTIME();
+
+ if (single_ac != ctx->single_ac) {
+ /* new single ac traffic (first single ac or different single ac) */
+ ctx->allow_credit_borrow = 0;
+ ctx->single_ac_timestamp = curr_t;
+ ctx->single_ac = (uint8)single_ac;
+ rc = BCME_OK;
+ goto exit;
+ }
+ /* same ac traffic, check if it lasts enough time */
+ delta = curr_t - ctx->single_ac_timestamp;
+
+ if (delta >= WLFC_BORROW_DEFER_PERIOD_MS) {
+ /* wait enough time, can borrow now */
+ ctx->allow_credit_borrow = 1;
+ ac = single_ac - 1;
+ } else {
+ rc = BCME_OK;
+ goto exit;
+ }
+ }
+ } else {
+ /* If we have multiple AC traffic, turn off borrowing, mark time and bail out */
+ ctx->allow_credit_borrow = 0;
+ ctx->single_ac_timestamp = 0;
+ ctx->single_ac = 0;
+ rc = BCME_OK;
+ goto exit;
+ }
+
+ if (packets_map == 0) {
+ /* nothing to send, skip borrow */
+ rc = BCME_OK;
+ goto exit;
+ }
+
+ /* At this point, borrow all credits only for ac */
+ while (FALSE == dhdp->proptxstatus_txoff) {
+#ifdef LIMIT_BORROW
+ if ((lender = _dhd_wlfc_borrow_credit(ctx, AC_COUNT, ac)) == -1) {
+ break;
+ }
+#endif
+ commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac,
+ &(commit_info.ac_fifo_credit_spent),
+ &(commit_info.needs_hdr),
+ &(commit_info.mac_entry),
+ FALSE);
+ if (commit_info.p == NULL) {
+ /* before borrow only one ac exists and now this only ac is empty */
+#ifdef LIMIT_BORROW
+ _dhd_wlfc_return_credit(ctx, lender, ac);
+#endif
+ break;
+ }
+
+ commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED :
+ eWLFC_PKTTYPE_SUPPRESSED;
+
+ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info,
+ fcommit, commit_ctx);
+
+ /* Bus commits may fail (e.g. flow control); abort after retries */
+ if (rc == BCME_OK) {
+
+ if (commit_info.ac_fifo_credit_spent) {
+#ifndef LIMIT_BORROW
+ ctx->FIFO_credit[ac]--;
+#endif
+ } else {
+#ifdef LIMIT_BORROW
+ _dhd_wlfc_return_credit(ctx, lender, ac);
+#endif
+ }
+ } else {
+#ifdef LIMIT_BORROW
+ _dhd_wlfc_return_credit(ctx, lender, ac);
+#endif
+ bus_retry_count++;
+ if (bus_retry_count >= BUS_RETRIES) {
+ DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc));
+ goto exit;
+ }
+ }
+ }
+
+exit:
+ if (need_toggle_host_if && ctx->toggle_host_if) {
+ ctx->toggle_host_if = 0;
+ }
+
+exit2:
+ dhd_os_wlfc_unblock(dhdp);
+ return rc;
+}
+
+int
+dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success)
+{
+ athost_wl_status_info_t* wlfc;
+ void* pout = NULL;
+ int rtn = BCME_OK;
+ if ((dhd == NULL) || (txp == NULL)) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ rtn = WLFC_UNSUPPORTED;
+ goto EXIT;
+ }
+
+ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+ if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) {
+#ifdef PROP_TXSTATUS_DEBUG
+ wlfc->stats.signal_only_pkts_freed++;
+#endif
+ /* is this a signal-only packet? */
+ _dhd_wlfc_pullheader(wlfc, txp);
+ PKTFREE(wlfc->osh, txp, TRUE);
+ goto EXIT;
+ }
+
+ if (!success || dhd->proptxstatus_txstatus_ignore) {
+ wlfc_mac_descriptor_t *entry = _dhd_wlfc_find_table_entry(wlfc, txp);
+
+ WLFC_DBGMESG(("At: %s():%d, bus_complete() failure for %p, htod_tag:0x%08x\n",
+ __FUNCTION__, __LINE__, txp, DHD_PKTTAG_H2DTAG(PKTTAG(txp))));
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ _dhd_wlfc_hanger_poppkt(wlfc->hanger, WL_TXSTATUS_GET_HSLOT(
+ DHD_PKTTAG_H2DTAG(PKTTAG(txp))), &pout, 1);
+ ASSERT(txp == pout);
+ }
+
+ /* indicate failure and free the packet */
+ dhd_txcomplete(dhd, txp, success);
+
+ /* return the credit, if necessary */
+ _dhd_wlfc_return_implied_credit(wlfc, txp);
+
+ entry->transit_count--;
+ if (entry->suppressed && (--entry->suppr_transit_count == 0)) {
+ entry->suppressed = FALSE;
+ }
+
+ PKTFREE(wlfc->osh, txp, TRUE);
+ wlfc->stats.pktout++;
+ } else {
+ /* bus confirmed pkt went to firmware side */
+ if (WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ _dhd_wlfc_enque_afq(wlfc, txp);
+ } else {
+ int ret;
+ void *pktbuf_tmp = NULL;
+ int hslot = WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG(PKTTAG(txp)));
+ if (_dhd_wlfc_hanger_waitevent_decreturn(wlfc->hanger, hslot) == 0) {
+ ret = _dhd_wlfc_hanger_poppkt(wlfc->hanger, hslot, &pktbuf_tmp, 1);
+ BCM_REFERENCE(ret);
+ ASSERT((ret == BCME_OK) && pktbuf_tmp && (txp == pktbuf_tmp));
+
+ /* free the packet */
+ PKTFREE(wlfc->osh, txp, TRUE);
+ }
+ }
+ }
+
+EXIT:
+ dhd_os_wlfc_unblock(dhd);
+ return rtn;
+}
+
+int
+dhd_wlfc_init(dhd_pub_t *dhd)
+{
+ char iovbuf[14]; /* Room for "tlv" + '\0' + parameter */
+ /* enable all signals & indicate host proptxstatus logic is active */
+ uint32 tlv, mode, fw_caps;
+ int ret = 0;
+
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+ if (dhd->wlfc_enabled) {
+ DHD_ERROR(("%s():%d, Already enabled!\n", __FUNCTION__, __LINE__));
+ dhd_os_wlfc_unblock(dhd);
+ return BCME_OK;
+ }
+ dhd->wlfc_enabled = TRUE;
+ dhd_os_wlfc_unblock(dhd);
+
+ tlv = WLFC_FLAGS_RSSI_SIGNALS |
+ WLFC_FLAGS_XONXOFF_SIGNALS |
+ WLFC_FLAGS_CREDIT_STATUS_SIGNALS |
+ WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE |
+ WLFC_FLAGS_HOST_RXRERODER_ACTIVE;
+
+
+ /*
+ try to enable/disable signaling by sending "tlv" iovar. if that fails,
+ fallback to no flow control? Print a message for now.
+ */
+
+ /* enable proptxtstatus signaling by default */
+ bcm_mkiovar("tlv", (char *)&tlv, 4, iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) {
+ DHD_ERROR(("dhd_wlfc_init(): failed to enable/disable bdcv2 tlv signaling\n"));
+ }
+ else {
+ /*
+ Leaving the message for now, it should be removed after a while; once
+ the tlv situation is stable.
+ */
+ DHD_ERROR(("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n",
+ dhd->wlfc_enabled?"enabled":"disabled", tlv));
+ }
+
+ /* query caps */
+ ret = bcm_mkiovar("wlfc_mode", (char *)&mode, 4, iovbuf, sizeof(iovbuf));
+ if (ret > 0) {
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
+ }
+
+ if (ret >= 0) {
+ fw_caps = *((uint32 *)iovbuf);
+ mode = 0;
+ DHD_ERROR(("%s: query wlfc_mode succeed, fw_caps=0x%x\n", __FUNCTION__, fw_caps));
+
+ if (WLFC_IS_OLD_DEF(fw_caps)) {
+ /* enable proptxtstatus v2 by default */
+ mode = WLFC_MODE_AFQ;
+ } else {
+ WLFC_SET_AFQ(mode, WLFC_GET_AFQ(fw_caps));
+ WLFC_SET_REUSESEQ(mode, WLFC_GET_REUSESEQ(fw_caps));
+ WLFC_SET_REORDERSUPP(mode, WLFC_GET_REORDERSUPP(fw_caps));
+ }
+ ret = bcm_mkiovar("wlfc_mode", (char *)&mode, 4, iovbuf, sizeof(iovbuf));
+ if (ret > 0) {
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ }
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ dhd->wlfc_mode = 0;
+ if (ret >= 0) {
+ if (WLFC_IS_OLD_DEF(mode)) {
+ WLFC_SET_AFQ(dhd->wlfc_mode, (mode == WLFC_MODE_AFQ));
+ } else {
+ dhd->wlfc_mode = mode;
+ }
+ }
+ DHD_ERROR(("dhd_wlfc_init(): wlfc_mode=0x%x, ret=%d\n", dhd->wlfc_mode, ret));
+
+ dhd_os_wlfc_unblock(dhd);
+
+ if (dhd->plat_init)
+ dhd->plat_init((void *)dhd);
+
+ return BCME_OK;
+}
+
+int
+dhd_wlfc_hostreorder_init(dhd_pub_t *dhd)
+{
+ char iovbuf[14]; /* Room for "tlv" + '\0' + parameter */
+ /* enable only ampdu hostreorder here */
+ uint32 tlv;
+
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ DHD_TRACE(("%s():%d Enter\n", __FUNCTION__, __LINE__));
+
+ tlv = WLFC_FLAGS_HOST_RXRERODER_ACTIVE;
+
+ /* enable proptxtstatus signaling by default */
+ bcm_mkiovar("tlv", (char *)&tlv, 4, iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) {
+ DHD_ERROR(("%s(): failed to enable/disable bdcv2 tlv signaling\n",
+ __FUNCTION__));
+ }
+ else {
+ /*
+ Leaving the message for now, it should be removed after a while; once
+ the tlv situation is stable.
+ */
+ DHD_ERROR(("%s(): successful bdcv2 tlv signaling, %d\n",
+ __FUNCTION__, tlv));
+ }
+
+ dhd_os_wlfc_block(dhd);
+ dhd->proptxstatus_mode = WLFC_ONLY_AMPDU_HOSTREORDER;
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+#ifdef SUPPORT_P2P_GO_PS
+int
+dhd_wlfc_suspend(dhd_pub_t *dhd)
+{
+
+ uint32 iovbuf[4]; /* Room for "tlv" + '\0' + parameter */
+ uint32 tlv = 0;
+
+ DHD_TRACE(("%s: masking wlfc events\n", __FUNCTION__));
+ if (!dhd->wlfc_enabled)
+ return -1;
+
+ bcm_mkiovar("tlv", NULL, 0, (char*)iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0) < 0) {
+ DHD_ERROR(("%s: failed to get bdcv2 tlv signaling\n", __FUNCTION__));
+ return -1;
+ }
+ tlv = iovbuf[0];
+ if ((tlv & (WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS)) == 0)
+ return 0;
+ tlv &= ~(WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS);
+ bcm_mkiovar("tlv", (char *)&tlv, 4, (char*)iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) {
+ DHD_ERROR(("%s: failed to set bdcv2 tlv signaling to 0x%x\n",
+ __FUNCTION__, tlv));
+ return -1;
+ }
+
+ return 0;
+}
+
+ int
+dhd_wlfc_resume(dhd_pub_t *dhd)
+{
+ uint32 iovbuf[4]; /* Room for "tlv" + '\0' + parameter */
+ uint32 tlv = 0;
+
+ DHD_TRACE(("%s: unmasking wlfc events\n", __FUNCTION__));
+ if (!dhd->wlfc_enabled)
+ return -1;
+
+ bcm_mkiovar("tlv", NULL, 0, (char*)iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0) < 0) {
+ DHD_ERROR(("%s: failed to get bdcv2 tlv signaling\n", __FUNCTION__));
+ return -1;
+ }
+ tlv = iovbuf[0];
+ if ((tlv & (WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS)) ==
+ (WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS))
+ return 0;
+ tlv |= (WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS);
+ bcm_mkiovar("tlv", (char *)&tlv, 4, (char*)iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, (char*)iovbuf, sizeof(iovbuf), TRUE, 0) < 0) {
+ DHD_ERROR(("%s: failed to set bdcv2 tlv signaling to 0x%x\n",
+ __FUNCTION__, tlv));
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* SUPPORT_P2P_GO_PS */
+
+int
+dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
+{
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhd);
+ return WLFC_UNSUPPORTED;
+ }
+
+ _dhd_wlfc_cleanup_txq(dhd, fn, arg);
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+/* release all packet resources */
+int
+dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
+{
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhd);
+ return WLFC_UNSUPPORTED;
+ }
+
+ _dhd_wlfc_cleanup(dhd, fn, arg);
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int
+dhd_wlfc_deinit(dhd_pub_t *dhd)
+{
+ char iovbuf[32]; /* Room for "ampdu_hostreorder" or "tlv" + '\0' + parameter */
+ /* cleanup all psq related resources */
+ athost_wl_status_info_t* wlfc;
+ uint32 tlv = 0;
+ uint32 hostreorder = 0;
+ int ret = BCME_OK;
+
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+ if (!dhd->wlfc_enabled) {
+ DHD_ERROR(("%s():%d, Already disabled!\n", __FUNCTION__, __LINE__));
+ dhd_os_wlfc_unblock(dhd);
+ return BCME_OK;
+ }
+ dhd->wlfc_enabled = FALSE;
+ dhd_os_wlfc_unblock(dhd);
+
+ /* query ampdu hostreorder */
+ bcm_mkiovar("ampdu_hostreorder", NULL, 0, iovbuf, sizeof(iovbuf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
+ if (ret == BCME_OK)
+ hostreorder = *((uint32 *)iovbuf);
+ else {
+ hostreorder = 0;
+ DHD_ERROR(("%s():%d, ampdu_hostreorder get failed Err = %d\n",
+ __FUNCTION__, __LINE__, ret));
+ }
+
+ if (hostreorder) {
+ tlv = WLFC_FLAGS_HOST_RXRERODER_ACTIVE;
+ DHD_ERROR(("%s():%d, maintain HOST RXRERODER flag in tvl\n",
+ __FUNCTION__, __LINE__));
+ }
+
+ /* Disable proptxtstatus signaling for deinit */
+ bcm_mkiovar("tlv", (char *)&tlv, 4, iovbuf, sizeof(iovbuf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
+ if (ret == BCME_OK) {
+ /*
+ Leaving the message for now, it should be removed after a while; once
+ the tlv situation is stable.
+ */
+ DHD_ERROR(("%s():%d successfully %s bdcv2 tlv signaling, %d\n",
+ __FUNCTION__, __LINE__,
+ dhd->wlfc_enabled?"enabled":"disabled", tlv));
+ } else
+ DHD_ERROR(("%s():%d failed to enable/disable bdcv2 tlv signaling Err = %d\n",
+ __FUNCTION__, __LINE__, ret));
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhd);
+ return WLFC_UNSUPPORTED;
+ }
+
+ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+
+#ifdef PROP_TXSTATUS_DEBUG
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode))
+ {
+ int i;
+ wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger;
+ for (i = 0; i < h->max_items; i++) {
+ if (h->items[i].state != WLFC_HANGER_ITEM_STATE_FREE) {
+ WLFC_DBGMESG(("%s() pkt[%d] = 0x%p, FIFO_credit_used:%d\n",
+ __FUNCTION__, i, h->items[i].pkt,
+ DHD_PKTTAG_CREDITCHECK(PKTTAG(h->items[i].pkt))));
+ }
+ }
+ }
+#endif
+
+ _dhd_wlfc_cleanup(dhd, NULL, NULL);
+
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ /* delete hanger */
+ _dhd_wlfc_hanger_delete(dhd->osh, wlfc->hanger);
+ }
+
+
+ /* free top structure */
+ DHD_OS_PREFREE(dhd, DHD_PREALLOC_DHD_WLFC_INFO,
+ dhd->wlfc_state, sizeof(athost_wl_status_info_t));
+ dhd->wlfc_state = NULL;
+ dhd->proptxstatus_mode = hostreorder ?
+ WLFC_ONLY_AMPDU_HOSTREORDER : WLFC_FCMODE_NONE;
+
+ dhd_os_wlfc_unblock(dhd);
+
+ if (dhd->plat_deinit)
+ dhd->plat_deinit((void *)dhd);
+ return BCME_OK;
+}
+
+int dhd_wlfc_interface_event(dhd_pub_t *dhdp, uint8 action, uint8 ifid, uint8 iftype, uint8* ea)
+{
+ int rc;
+
+ if (dhdp == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhdp);
+
+ if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhdp);
+ return WLFC_UNSUPPORTED;
+ }
+
+ rc = _dhd_wlfc_interface_entry_update(dhdp->wlfc_state, action, ifid, iftype, ea);
+
+ dhd_os_wlfc_unblock(dhdp);
+ return rc;
+}
+
+int dhd_wlfc_FIFOcreditmap_event(dhd_pub_t *dhdp, uint8* event_data)
+{
+ int rc;
+
+ if (dhdp == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhdp);
+
+ if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhdp);
+ return WLFC_UNSUPPORTED;
+ }
+
+ rc = _dhd_wlfc_FIFOcreditmap_update(dhdp->wlfc_state, event_data);
+
+ dhd_os_wlfc_unblock(dhdp);
+
+ return rc;
+}
+
+int dhd_wlfc_BCMCCredit_support_event(dhd_pub_t *dhdp)
+{
+ int rc;
+
+ if (dhdp == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhdp);
+
+ if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhdp);
+ return WLFC_UNSUPPORTED;
+ }
+
+ rc = _dhd_wlfc_BCMCCredit_support_update(dhdp->wlfc_state);
+
+ dhd_os_wlfc_unblock(dhdp);
+ return rc;
+}
+
+int
+dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+{
+ int i;
+ uint8* ea;
+ athost_wl_status_info_t* wlfc;
+ wlfc_hanger_t* h;
+ wlfc_mac_descriptor_t* mac_table;
+ wlfc_mac_descriptor_t* interfaces;
+ char* iftypes[] = {"STA", "AP", "WDS", "p2pGO", "p2pCL"};
+
+ if (!dhdp || !strbuf) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhdp);
+
+ if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhdp);
+ return WLFC_UNSUPPORTED;
+ }
+
+ wlfc = (athost_wl_status_info_t*)dhdp->wlfc_state;
+
+ h = (wlfc_hanger_t*)wlfc->hanger;
+ if (h == NULL) {
+ bcm_bprintf(strbuf, "wlfc-hanger not initialized yet\n");
+ }
+
+ mac_table = wlfc->destination_entries.nodes;
+ interfaces = wlfc->destination_entries.interfaces;
+ bcm_bprintf(strbuf, "---- wlfc stats ----\n");
+
+ if (!WLFC_GET_AFQ(dhdp->wlfc_mode)) {
+ h = (wlfc_hanger_t*)wlfc->hanger;
+ if (h == NULL) {
+ bcm_bprintf(strbuf, "wlfc-hanger not initialized yet\n");
+ } else {
+ bcm_bprintf(strbuf, "wlfc hanger (pushed,popped,f_push,"
+ "f_pop,f_slot, pending) = (%d,%d,%d,%d,%d,%d)\n",
+ h->pushed,
+ h->popped,
+ h->failed_to_push,
+ h->failed_to_pop,
+ h->failed_slotfind,
+ (h->pushed - h->popped));
+ }
+ }
+
+ bcm_bprintf(strbuf, "wlfc fail(tlv,credit_rqst,mac_update,psmode_update), "
+ "(dq_full,rollback_fail) = (%d,%d,%d,%d), (%d,%d)\n",
+ wlfc->stats.tlv_parse_failed,
+ wlfc->stats.credit_request_failed,
+ wlfc->stats.mac_update_failed,
+ wlfc->stats.psmode_update_failed,
+ wlfc->stats.delayq_full_error,
+ wlfc->stats.rollback_failed);
+
+ bcm_bprintf(strbuf, "PKTS (init_credit,credit,sent,drop_d,drop_s,outoforder) "
+ "(AC0[%d,%d,%d,%d,%d,%d],AC1[%d,%d,%d,%d,%d,%d],AC2[%d,%d,%d,%d,%d,%d],"
+ "AC3[%d,%d,%d,%d,%d,%d],BC_MC[%d,%d,%d,%d,%d,%d])\n",
+ wlfc->Init_FIFO_credit[0], wlfc->FIFO_credit[0], wlfc->stats.send_pkts[0],
+ wlfc->stats.drop_pkts[0], wlfc->stats.drop_pkts[1], wlfc->stats.ooo_pkts[0],
+ wlfc->Init_FIFO_credit[1], wlfc->FIFO_credit[1], wlfc->stats.send_pkts[1],
+ wlfc->stats.drop_pkts[2], wlfc->stats.drop_pkts[3], wlfc->stats.ooo_pkts[1],
+ wlfc->Init_FIFO_credit[2], wlfc->FIFO_credit[2], wlfc->stats.send_pkts[2],
+ wlfc->stats.drop_pkts[4], wlfc->stats.drop_pkts[5], wlfc->stats.ooo_pkts[2],
+ wlfc->Init_FIFO_credit[3], wlfc->FIFO_credit[3], wlfc->stats.send_pkts[3],
+ wlfc->stats.drop_pkts[6], wlfc->stats.drop_pkts[7], wlfc->stats.ooo_pkts[3],
+ wlfc->Init_FIFO_credit[4], wlfc->FIFO_credit[4], wlfc->stats.send_pkts[4],
+ wlfc->stats.drop_pkts[8], wlfc->stats.drop_pkts[9], wlfc->stats.ooo_pkts[4]);
+
+ bcm_bprintf(strbuf, "\n");
+ for (i = 0; i < WLFC_MAX_IFNUM; i++) {
+ if (interfaces[i].occupied) {
+ char* iftype_desc;
+
+ if (interfaces[i].iftype > WLC_E_IF_ROLE_P2P_CLIENT)
+ iftype_desc = "<Unknown";
+ else
+ iftype_desc = iftypes[interfaces[i].iftype];
+
+ ea = interfaces[i].ea;
+ bcm_bprintf(strbuf, "INTERFACE[%d].ea = "
+ "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d, type: %s "
+ "netif_flow_control:%s\n", i,
+ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5],
+ interfaces[i].interface_id,
+ iftype_desc, ((wlfc->hostif_flow_state[i] == OFF)
+ ? " OFF":" ON"));
+
+ bcm_bprintf(strbuf, "INTERFACE[%d].PSQ(len,state,credit),(trans,supp_trans)"
+ "= (%d,%s,%d),(%d,%d)\n",
+ i,
+ interfaces[i].psq.len,
+ ((interfaces[i].state ==
+ WLFC_STATE_OPEN) ? "OPEN":"CLOSE"),
+ interfaces[i].requested_credit,
+ interfaces[i].transit_count, interfaces[i].suppr_transit_count);
+
+ bcm_bprintf(strbuf, "INTERFACE[%d].PSQ"
+ "(delay0,sup0,afq0),(delay1,sup1,afq1),(delay2,sup2,afq2),"
+ "(delay3,sup3,afq3),(delay4,sup4,afq4) = (%d,%d,%d),"
+ "(%d,%d,%d),(%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n",
+ i,
+ interfaces[i].psq.q[0].len,
+ interfaces[i].psq.q[1].len,
+ interfaces[i].afq.q[0].len,
+ interfaces[i].psq.q[2].len,
+ interfaces[i].psq.q[3].len,
+ interfaces[i].afq.q[1].len,
+ interfaces[i].psq.q[4].len,
+ interfaces[i].psq.q[5].len,
+ interfaces[i].afq.q[2].len,
+ interfaces[i].psq.q[6].len,
+ interfaces[i].psq.q[7].len,
+ interfaces[i].afq.q[3].len,
+ interfaces[i].psq.q[8].len,
+ interfaces[i].psq.q[9].len,
+ interfaces[i].afq.q[4].len);
+ }
+ }
+
+ bcm_bprintf(strbuf, "\n");
+ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) {
+ if (mac_table[i].occupied) {
+ ea = mac_table[i].ea;
+ bcm_bprintf(strbuf, "MAC_table[%d].ea = "
+ "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d \n", i,
+ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5],
+ mac_table[i].interface_id);
+
+ bcm_bprintf(strbuf, "MAC_table[%d].PSQ(len,state,credit),(trans,supp_trans)"
+ "= (%d,%s,%d),(%d,%d)\n",
+ i,
+ mac_table[i].psq.len,
+ ((mac_table[i].state ==
+ WLFC_STATE_OPEN) ? " OPEN":"CLOSE"),
+ mac_table[i].requested_credit,
+ mac_table[i].transit_count, mac_table[i].suppr_transit_count);
+#ifdef PROP_TXSTATUS_DEBUG
+ bcm_bprintf(strbuf, "MAC_table[%d]: (opened, closed) = (%d, %d)\n",
+ i, mac_table[i].opened_ct, mac_table[i].closed_ct);
+#endif
+ bcm_bprintf(strbuf, "MAC_table[%d].PSQ"
+ "(delay0,sup0,afq0),(delay1,sup1,afq1),(delay2,sup2,afq2),"
+ "(delay3,sup3,afq3),(delay4,sup4,afq4) =(%d,%d,%d),"
+ "(%d,%d,%d),(%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n",
+ i,
+ mac_table[i].psq.q[0].len,
+ mac_table[i].psq.q[1].len,
+ mac_table[i].afq.q[0].len,
+ mac_table[i].psq.q[2].len,
+ mac_table[i].psq.q[3].len,
+ mac_table[i].afq.q[1].len,
+ mac_table[i].psq.q[4].len,
+ mac_table[i].psq.q[5].len,
+ mac_table[i].afq.q[2].len,
+ mac_table[i].psq.q[6].len,
+ mac_table[i].psq.q[7].len,
+ mac_table[i].afq.q[3].len,
+ mac_table[i].psq.q[8].len,
+ mac_table[i].psq.q[9].len,
+ mac_table[i].afq.q[4].len);
+
+ }
+ }
+
+#ifdef PROP_TXSTATUS_DEBUG
+ {
+ int avg;
+ int moving_avg = 0;
+ int moving_samples;
+
+ if (wlfc->stats.latency_sample_count) {
+ moving_samples = sizeof(wlfc->stats.deltas)/sizeof(uint32);
+
+ for (i = 0; i < moving_samples; i++)
+ moving_avg += wlfc->stats.deltas[i];
+ moving_avg /= moving_samples;
+
+ avg = (100 * wlfc->stats.total_status_latency) /
+ wlfc->stats.latency_sample_count;
+ bcm_bprintf(strbuf, "txstatus latency (average, last, moving[%d]) = "
+ "(%d.%d, %03d, %03d)\n",
+ moving_samples, avg/100, (avg - (avg/100)*100),
+ wlfc->stats.latency_most_recent,
+ moving_avg);
+ }
+ }
+
+ bcm_bprintf(strbuf, "wlfc- fifo[0-5] credit stats: sent = (%d,%d,%d,%d,%d,%d), "
+ "back = (%d,%d,%d,%d,%d,%d)\n",
+ wlfc->stats.fifo_credits_sent[0],
+ wlfc->stats.fifo_credits_sent[1],
+ wlfc->stats.fifo_credits_sent[2],
+ wlfc->stats.fifo_credits_sent[3],
+ wlfc->stats.fifo_credits_sent[4],
+ wlfc->stats.fifo_credits_sent[5],
+
+ wlfc->stats.fifo_credits_back[0],
+ wlfc->stats.fifo_credits_back[1],
+ wlfc->stats.fifo_credits_back[2],
+ wlfc->stats.fifo_credits_back[3],
+ wlfc->stats.fifo_credits_back[4],
+ wlfc->stats.fifo_credits_back[5]);
+ {
+ uint32 fifo_cr_sent = 0;
+ uint32 fifo_cr_acked = 0;
+ uint32 request_cr_sent = 0;
+ uint32 request_cr_ack = 0;
+ uint32 bc_mc_cr_ack = 0;
+
+ for (i = 0; i < sizeof(wlfc->stats.fifo_credits_sent)/sizeof(uint32); i++) {
+ fifo_cr_sent += wlfc->stats.fifo_credits_sent[i];
+ }
+
+ for (i = 0; i < sizeof(wlfc->stats.fifo_credits_back)/sizeof(uint32); i++) {
+ fifo_cr_acked += wlfc->stats.fifo_credits_back[i];
+ }
+
+ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) {
+ if (wlfc->destination_entries.nodes[i].occupied) {
+ request_cr_sent +=
+ wlfc->destination_entries.nodes[i].dstncredit_sent_packets;
+ }
+ }
+ for (i = 0; i < WLFC_MAX_IFNUM; i++) {
+ if (wlfc->destination_entries.interfaces[i].occupied) {
+ request_cr_sent +=
+ wlfc->destination_entries.interfaces[i].dstncredit_sent_packets;
+ }
+ }
+ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) {
+ if (wlfc->destination_entries.nodes[i].occupied) {
+ request_cr_ack +=
+ wlfc->destination_entries.nodes[i].dstncredit_acks;
+ }
+ }
+ for (i = 0; i < WLFC_MAX_IFNUM; i++) {
+ if (wlfc->destination_entries.interfaces[i].occupied) {
+ request_cr_ack +=
+ wlfc->destination_entries.interfaces[i].dstncredit_acks;
+ }
+ }
+ bcm_bprintf(strbuf, "wlfc- (sent, status) => pq(%d,%d), vq(%d,%d),"
+ "other:%d, bc_mc:%d, signal-only, (sent,freed): (%d,%d)",
+ fifo_cr_sent, fifo_cr_acked,
+ request_cr_sent, request_cr_ack,
+ wlfc->destination_entries.other.dstncredit_acks,
+ bc_mc_cr_ack,
+ wlfc->stats.signal_only_pkts_sent, wlfc->stats.signal_only_pkts_freed);
+ }
+#endif /* PROP_TXSTATUS_DEBUG */
+ bcm_bprintf(strbuf, "\n");
+ bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull,out),(dropped,hdr_only,wlc_tossed)"
+ "(freed,free_err,rollback)) = "
+ "((%d,%d,%d,%d,%d),(%d,%d,%d),(%d,%d,%d))\n",
+ wlfc->stats.pktin,
+ wlfc->stats.pkt2bus,
+ wlfc->stats.txstatus_in,
+ wlfc->stats.dhd_hdrpulls,
+ wlfc->stats.pktout,
+
+ wlfc->stats.pktdropped,
+ wlfc->stats.wlfc_header_only_pkt,
+ wlfc->stats.wlc_tossed_pkts,
+
+ wlfc->stats.pkt_freed,
+ wlfc->stats.pkt_free_err, wlfc->stats.rollback);
+
+ bcm_bprintf(strbuf, "wlfc- suppress((d11,wlc,err),enq(d11,wl,hq,mac?),retx(d11,wlc,hq)) = "
+ "((%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d))\n",
+ wlfc->stats.d11_suppress,
+ wlfc->stats.wl_suppress,
+ wlfc->stats.bad_suppress,
+
+ wlfc->stats.psq_d11sup_enq,
+ wlfc->stats.psq_wlsup_enq,
+ wlfc->stats.psq_hostq_enq,
+ wlfc->stats.mac_handle_notfound,
+
+ wlfc->stats.psq_d11sup_retx,
+ wlfc->stats.psq_wlsup_retx,
+ wlfc->stats.psq_hostq_retx);
+
+ bcm_bprintf(strbuf, "wlfc- cleanup(txq,psq,fw) = (%d,%d,%d)\n",
+ wlfc->stats.cleanup_txq_cnt,
+ wlfc->stats.cleanup_psq_cnt,
+ wlfc->stats.cleanup_fw_cnt);
+
+ bcm_bprintf(strbuf, "wlfc- generic error: %d\n", wlfc->stats.generic_error);
+
+ for (i = 0; i < WLFC_MAX_IFNUM; i++) {
+ bcm_bprintf(strbuf, "wlfc- if[%d], pkt_cnt_in_q/AC[0-4] = (%d,%d,%d,%d,%d)\n", i,
+ wlfc->pkt_cnt_in_q[i][0],
+ wlfc->pkt_cnt_in_q[i][1],
+ wlfc->pkt_cnt_in_q[i][2],
+ wlfc->pkt_cnt_in_q[i][3],
+ wlfc->pkt_cnt_in_q[i][4]);
+ }
+ bcm_bprintf(strbuf, "\n");
+
+ dhd_os_wlfc_unblock(dhdp);
+ return BCME_OK;
+}
+
+int dhd_wlfc_clear_counts(dhd_pub_t *dhd)
+{
+ athost_wl_status_info_t* wlfc;
+ wlfc_hanger_t* hanger;
+
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhd);
+ return WLFC_UNSUPPORTED;
+ }
+
+ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+
+ memset(&wlfc->stats, 0, sizeof(athost_wl_stat_counters_t));
+
+ if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
+ hanger = (wlfc_hanger_t*)wlfc->hanger;
+
+ hanger->pushed = 0;
+ hanger->popped = 0;
+ hanger->failed_slotfind = 0;
+ hanger->failed_to_pop = 0;
+ hanger->failed_to_push = 0;
+ }
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_get_enable(dhd_pub_t *dhd, bool *val)
+{
+ if (!dhd || !val) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ *val = dhd->wlfc_enabled;
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_get_mode(dhd_pub_t *dhd, int *val)
+{
+ if (!dhd || !val) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ *val = dhd->wlfc_state ? dhd->proptxstatus_mode : 0;
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_set_mode(dhd_pub_t *dhd, int val)
+{
+ if (!dhd) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (dhd->wlfc_state) {
+ dhd->proptxstatus_mode = val & 0xff;
+ }
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+bool dhd_wlfc_is_header_only_pkt(dhd_pub_t * dhd, void *pktbuf)
+{
+ athost_wl_status_info_t* wlfc;
+ bool rc = FALSE;
+
+ if (dhd == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return FALSE;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhd);
+ return FALSE;
+ }
+
+ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+
+ if (PKTLEN(wlfc->osh, pktbuf) == 0) {
+ wlfc->stats.wlfc_header_only_pkt++;
+ rc = TRUE;
+ }
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return rc;
+}
+
+int dhd_wlfc_flowcontrol(dhd_pub_t *dhdp, bool state, bool bAcquireLock)
+{
+ if (dhdp == NULL) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ if (bAcquireLock) {
+ dhd_os_wlfc_block(dhdp);
+ }
+
+ if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE) ||
+ dhdp->proptxstatus_module_ignore) {
+ if (bAcquireLock) {
+ dhd_os_wlfc_unblock(dhdp);
+ }
+ return WLFC_UNSUPPORTED;
+ }
+
+ if (state != dhdp->proptxstatus_txoff) {
+ dhdp->proptxstatus_txoff = state;
+ }
+
+ if (bAcquireLock) {
+ dhd_os_wlfc_unblock(dhdp);
+ }
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_save_rxpath_ac_time(dhd_pub_t * dhd, uint8 prio)
+{
+ athost_wl_status_info_t* wlfc;
+ int rx_path_ac = -1;
+
+ if ((dhd == NULL) || (prio >= NUMPRIO)) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if (!dhd->wlfc_rxpkt_chk) {
+ dhd_os_wlfc_unblock(dhd);
+ return BCME_OK;
+ }
+
+ if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ dhd_os_wlfc_unblock(dhd);
+ return WLFC_UNSUPPORTED;
+ }
+
+ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
+
+ rx_path_ac = prio2fifo[prio];
+ wlfc->rx_timestamp[rx_path_ac] = OSL_SYSUPTIME();
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_get_module_ignore(dhd_pub_t *dhd, int *val)
+{
+ if (!dhd || !val) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ *val = dhd->proptxstatus_module_ignore;
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_set_module_ignore(dhd_pub_t *dhd, int val)
+{
+ char iovbuf[14]; /* Room for "tlv" + '\0' + parameter */
+ uint32 tlv = 0;
+ bool bChanged = FALSE;
+
+ if (!dhd) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ if ((bool)val != dhd->proptxstatus_module_ignore) {
+ dhd->proptxstatus_module_ignore = (val != 0);
+ /* force txstatus_ignore sync with proptxstatus_module_ignore */
+ dhd->proptxstatus_txstatus_ignore = dhd->proptxstatus_module_ignore;
+ if (FALSE == dhd->proptxstatus_module_ignore) {
+ tlv = WLFC_FLAGS_RSSI_SIGNALS |
+ WLFC_FLAGS_XONXOFF_SIGNALS |
+ WLFC_FLAGS_CREDIT_STATUS_SIGNALS |
+ WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE;
+ }
+ /* always enable host reorder */
+ tlv |= WLFC_FLAGS_HOST_RXRERODER_ACTIVE;
+ bChanged = TRUE;
+ }
+
+ dhd_os_wlfc_unblock(dhd);
+
+ if (bChanged) {
+ /* select enable proptxtstatus signaling */
+ bcm_mkiovar("tlv", (char *)&tlv, 4, iovbuf, sizeof(iovbuf));
+ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) {
+ DHD_ERROR(("%s: failed to set bdcv2 tlv signaling to 0x%x\n",
+ __FUNCTION__, tlv));
+ }
+ else {
+ DHD_ERROR(("%s: successfully set bdcv2 tlv signaling to 0x%x\n",
+ __FUNCTION__, tlv));
+ }
+ }
+ return BCME_OK;
+}
+
+int dhd_wlfc_get_credit_ignore(dhd_pub_t *dhd, int *val)
+{
+ if (!dhd || !val) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ *val = dhd->proptxstatus_credit_ignore;
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_set_credit_ignore(dhd_pub_t *dhd, int val)
+{
+ if (!dhd) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ dhd->proptxstatus_credit_ignore = (val != 0);
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_get_txstatus_ignore(dhd_pub_t *dhd, int *val)
+{
+ if (!dhd || !val) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ *val = dhd->proptxstatus_txstatus_ignore;
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_set_txstatus_ignore(dhd_pub_t *dhd, int val)
+{
+ if (!dhd) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ dhd->proptxstatus_txstatus_ignore = (val != 0);
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val)
+{
+ if (!dhd || !val) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ *val = dhd->wlfc_rxpkt_chk;
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+
+int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val)
+{
+ if (!dhd) {
+ DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhd);
+
+ dhd->wlfc_rxpkt_chk = (val != 0);
+
+ dhd_os_wlfc_unblock(dhd);
+
+ return BCME_OK;
+}
+#endif /* PROP_TXSTATUS */
diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.h b/drivers/net/wireless/bcmdhd/dhd_wlfc.h
new file mode 100644
index 000000000000..330ac384997d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.h
@@ -0,0 +1,513 @@
+/*
+* Copyright (C) 1999-2016, Broadcom Corporation
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2 (the "GPL"),
+* available at http://www.broadcom.com/licenses/GPLv2.php, with the
+* following added to such license:
+*
+* As a special exception, the copyright holders of this software give you
+* permission to link this software with independent modules, and to copy and
+* distribute the resulting executable under terms of your choice, provided that
+* you also meet, for each linked independent module, the terms and conditions of
+* the license of that module. An independent module is a module which is not
+* derived from this software. The special exception does not apply to any
+* modifications of the software.
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a license
+* other than the GPL, without Broadcom's express prior written consent.
+* $Id: dhd_wlfc.h 485659 2014-06-16 21:33:12Z $
+*
+*/
+#ifndef __wlfc_host_driver_definitions_h__
+#define __wlfc_host_driver_definitions_h__
+
+
+/* #define OOO_DEBUG */
+
+#define WLFC_UNSUPPORTED -9999
+
+#define WLFC_NO_TRAFFIC -1
+#define WLFC_MULTI_TRAFFIC 0
+
+#define BUS_RETRIES 1 /* # of retries before aborting a bus tx operation */
+
+/* 16 bits will provide an absolute max of 65536 slots */
+#define WLFC_HANGER_MAXITEMS 3072
+
+#define WLFC_HANGER_ITEM_STATE_FREE 1
+#define WLFC_HANGER_ITEM_STATE_INUSE 2
+#define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3
+#define WLFC_HANGER_ITEM_STATE_WAIT_CLEAN 4
+
+#define WLFC_HANGER_ITEM_WAIT_EVENT_COUNT 2
+#define WLFC_HANGER_ITEM_WAIT_EVENT_INVALID 255
+
+typedef enum {
+ Q_TYPE_PSQ,
+ Q_TYPE_AFQ
+} q_type_t;
+
+typedef enum ewlfc_packet_state {
+ eWLFC_PKTTYPE_NEW,
+ eWLFC_PKTTYPE_DELAYED,
+ eWLFC_PKTTYPE_SUPPRESSED,
+ eWLFC_PKTTYPE_MAX
+} ewlfc_packet_state_t;
+
+typedef enum ewlfc_mac_entry_action {
+ eWLFC_MAC_ENTRY_ACTION_ADD,
+ eWLFC_MAC_ENTRY_ACTION_DEL,
+ eWLFC_MAC_ENTRY_ACTION_UPDATE,
+ eWLFC_MAC_ENTRY_ACTION_MAX
+} ewlfc_mac_entry_action_t;
+
+typedef struct wlfc_hanger_item {
+ uint8 state;
+ uint8 gen;
+ uint8 waitevent; /* wait txstatus_update and txcomplete before free a packet */
+ uint8 pad;
+ uint32 identifier;
+ void* pkt;
+#ifdef PROP_TXSTATUS_DEBUG
+ uint32 push_time;
+#endif
+ struct wlfc_hanger_item *next;
+} wlfc_hanger_item_t;
+
+typedef struct wlfc_hanger {
+ int max_items;
+ uint32 pushed;
+ uint32 popped;
+ uint32 failed_to_push;
+ uint32 failed_to_pop;
+ uint32 failed_slotfind;
+ uint32 slot_pos;
+ wlfc_hanger_item_t items[1];
+} wlfc_hanger_t;
+
+#define WLFC_HANGER_SIZE(n) ((sizeof(wlfc_hanger_t) - \
+ sizeof(wlfc_hanger_item_t)) + ((n)*sizeof(wlfc_hanger_item_t)))
+
+#define WLFC_STATE_OPEN 1
+#define WLFC_STATE_CLOSE 2
+
+#define WLFC_PSQ_PREC_COUNT ((AC_COUNT + 1) * 2) /* 2 for each AC traffic and bc/mc */
+#define WLFC_AFQ_PREC_COUNT (AC_COUNT + 1)
+
+#define WLFC_PSQ_LEN 2048
+
+#define WLFC_FLOWCONTROL_HIWATER (2048 - 256)
+#define WLFC_FLOWCONTROL_LOWATER 256
+
+#define WLFC_LOG_BUF_SIZE (1024*1024)
+
+typedef struct wlfc_mac_descriptor {
+ uint8 occupied;
+ uint8 interface_id;
+ uint8 iftype;
+ uint8 state;
+ uint8 ac_bitmap; /* for APSD */
+ uint8 requested_credit;
+ uint8 requested_packet;
+ uint8 ea[ETHER_ADDR_LEN];
+ /*
+ maintain (MAC,AC) based seq count for
+ packets going to the device. As well as bc/mc.
+ */
+ uint8 seq[AC_COUNT + 1];
+ uint8 generation;
+ struct pktq psq;
+ /* packets at firmware */
+ struct pktq afq;
+ /* The AC pending bitmap that was reported to the fw at last change */
+ uint8 traffic_lastreported_bmp;
+ /* The new AC pending bitmap */
+ uint8 traffic_pending_bmp;
+ /* 1= send on next opportunity */
+ uint8 send_tim_signal;
+ uint8 mac_handle;
+ /* Number of packets at dongle for this entry. */
+ uint transit_count;
+ /* Numbe of suppression to wait before evict from delayQ */
+ uint suppr_transit_count;
+ /* flag. TRUE when in suppress state */
+ uint8 suppressed;
+
+
+#ifdef PROP_TXSTATUS_DEBUG
+ uint32 dstncredit_sent_packets;
+ uint32 dstncredit_acks;
+ uint32 opened_ct;
+ uint32 closed_ct;
+#endif
+ struct wlfc_mac_descriptor* prev;
+ struct wlfc_mac_descriptor* next;
+} wlfc_mac_descriptor_t;
+
+typedef struct dhd_wlfc_commit_info {
+ uint8 needs_hdr;
+ uint8 ac_fifo_credit_spent;
+ ewlfc_packet_state_t pkt_type;
+ wlfc_mac_descriptor_t* mac_entry;
+ void* p;
+} dhd_wlfc_commit_info_t;
+
+#define WLFC_DECR_SEQCOUNT(entry, prec) do { if (entry->seq[(prec)] == 0) {\
+ entry->seq[prec] = 0xff; } else entry->seq[prec]--;} while (0)
+
+#define WLFC_INCR_SEQCOUNT(entry, prec) entry->seq[(prec)]++
+#define WLFC_SEQCOUNT(entry, prec) entry->seq[(prec)]
+
+typedef struct athost_wl_stat_counters {
+ uint32 pktin;
+ uint32 pktout;
+ uint32 pkt2bus;
+ uint32 pktdropped;
+ uint32 tlv_parse_failed;
+ uint32 rollback;
+ uint32 rollback_failed;
+ uint32 delayq_full_error;
+ uint32 credit_request_failed;
+ uint32 packet_request_failed;
+ uint32 mac_update_failed;
+ uint32 psmode_update_failed;
+ uint32 interface_update_failed;
+ uint32 wlfc_header_only_pkt;
+ uint32 txstatus_in;
+ uint32 d11_suppress;
+ uint32 wl_suppress;
+ uint32 bad_suppress;
+ uint32 pkt_freed;
+ uint32 pkt_free_err;
+ uint32 psq_wlsup_retx;
+ uint32 psq_wlsup_enq;
+ uint32 psq_d11sup_retx;
+ uint32 psq_d11sup_enq;
+ uint32 psq_hostq_retx;
+ uint32 psq_hostq_enq;
+ uint32 mac_handle_notfound;
+ uint32 wlc_tossed_pkts;
+ uint32 dhd_hdrpulls;
+ uint32 generic_error;
+ /* an extra one for bc/mc traffic */
+ uint32 send_pkts[AC_COUNT + 1];
+ uint32 drop_pkts[WLFC_PSQ_PREC_COUNT];
+ uint32 ooo_pkts[AC_COUNT + 1];
+#ifdef PROP_TXSTATUS_DEBUG
+ /* all pkt2bus -> txstatus latency accumulated */
+ uint32 latency_sample_count;
+ uint32 total_status_latency;
+ uint32 latency_most_recent;
+ int idx_delta;
+ uint32 deltas[10];
+ uint32 fifo_credits_sent[6];
+ uint32 fifo_credits_back[6];
+ uint32 dropped_qfull[6];
+ uint32 signal_only_pkts_sent;
+ uint32 signal_only_pkts_freed;
+#endif
+ uint32 cleanup_txq_cnt;
+ uint32 cleanup_psq_cnt;
+ uint32 cleanup_fw_cnt;
+} athost_wl_stat_counters_t;
+
+#ifdef PROP_TXSTATUS_DEBUG
+#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do { \
+ (ctx)->stats.fifo_credits_sent[(ac)]++;} while (0)
+#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do { \
+ (ctx)->stats.fifo_credits_back[(ac)]++;} while (0)
+#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do { \
+ (ctx)->stats.dropped_qfull[(ac)]++;} while (0)
+#else
+#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do {} while (0)
+#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do {} while (0)
+#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do {} while (0)
+#endif
+
+#define WLFC_FCMODE_NONE 0
+#define WLFC_FCMODE_IMPLIED_CREDIT 1
+#define WLFC_FCMODE_EXPLICIT_CREDIT 2
+#define WLFC_ONLY_AMPDU_HOSTREORDER 3
+
+/* How long to defer borrowing in milliseconds */
+#define WLFC_BORROW_DEFER_PERIOD_MS 100
+
+/* How long to defer flow control in milliseconds */
+#define WLFC_FC_DEFER_PERIOD_MS 200
+
+/* How long to detect occurance per AC in miliseconds */
+#define WLFC_RX_DETECTION_THRESHOLD_MS 100
+
+/* Mask to represent available ACs (note: BC/MC is ignored */
+#define WLFC_AC_MASK 0xF
+
+typedef struct athost_wl_status_info {
+ uint8 last_seqid_to_wlc;
+
+ /* OSL handle */
+ osl_t* osh;
+ /* dhd pub */
+ void* dhdp;
+
+ /* stats */
+ athost_wl_stat_counters_t stats;
+
+ int Init_FIFO_credit[AC_COUNT + 2];
+
+ /* the additional ones are for bc/mc and ATIM FIFO */
+ int FIFO_credit[AC_COUNT + 2];
+
+ /* Credit borrow counts for each FIFO from each of the other FIFOs */
+ int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2];
+
+ /* packet hanger and MAC->handle lookup table */
+ void* hanger;
+ struct {
+ /* table for individual nodes */
+ wlfc_mac_descriptor_t nodes[WLFC_MAC_DESC_TABLE_SIZE];
+ /* table for interfaces */
+ wlfc_mac_descriptor_t interfaces[WLFC_MAX_IFNUM];
+ /* OS may send packets to unknown (unassociated) destinations */
+ /* A place holder for bc/mc and packets to unknown destinations */
+ wlfc_mac_descriptor_t other;
+ } destination_entries;
+
+ wlfc_mac_descriptor_t *active_entry_head;
+ int active_entry_count;
+
+ wlfc_mac_descriptor_t* requested_entry[WLFC_MAC_DESC_TABLE_SIZE];
+ int requested_entry_count;
+
+ /* pkt counts for each interface and ac */
+ int pkt_cnt_in_q[WLFC_MAX_IFNUM][AC_COUNT+1];
+ int pkt_cnt_per_ac[AC_COUNT+1];
+ uint8 allow_fc;
+ uint32 fc_defer_timestamp;
+ uint32 rx_timestamp[AC_COUNT+1];
+ /* ON/OFF state for flow control to the host network interface */
+ uint8 hostif_flow_state[WLFC_MAX_IFNUM];
+ uint8 host_ifidx;
+ /* to flow control an OS interface */
+ uint8 toggle_host_if;
+
+ /* To borrow credits */
+ uint8 allow_credit_borrow;
+
+ /* ac number for the first single ac traffic */
+ uint8 single_ac;
+
+ /* Timestamp for the first single ac traffic */
+ uint32 single_ac_timestamp;
+
+ bool bcmc_credit_supported;
+
+} athost_wl_status_info_t;
+
+/* Please be mindful that total pkttag space is 32 octets only */
+typedef struct dhd_pkttag {
+ /*
+ b[15] - 1 = wlfc packet
+ b[14:13] - encryption exemption
+ b[12 ] - 1 = event channel
+ b[11 ] - 1 = this packet was sent in response to one time packet request,
+ do not increment credit on status for this one. [WLFC_CTL_TYPE_MAC_REQUEST_PACKET].
+ b[10 ] - 1 = signal-only-packet to firmware [i.e. nothing to piggyback on]
+ b[9 ] - 1 = packet is host->firmware (transmit direction)
+ - 0 = packet received from firmware (firmware->host)
+ b[8 ] - 1 = packet was sent due to credit_request (pspoll),
+ packet does not count against FIFO credit.
+ - 0 = normal transaction, packet counts against FIFO credit
+ b[7 ] - 1 = AP, 0 = STA
+ b[6:4] - AC FIFO number
+ b[3:0] - interface index
+ */
+ uint16 if_flags;
+ /* destination MAC address for this packet so that not every
+ module needs to open the packet to find this
+ */
+ uint8 dstn_ether[ETHER_ADDR_LEN];
+ /*
+ This 32-bit goes from host to device for every packet.
+ */
+ uint32 htod_tag;
+
+ /*
+ This 16-bit is original seq number for every suppress packet.
+ */
+ uint16 htod_seq;
+
+ /*
+ This address is mac entry for every packet.
+ */
+ void* entry;
+ /* bus specific stuff */
+ union {
+ struct {
+ void* stuff;
+ uint32 thing1;
+ uint32 thing2;
+ } sd;
+ struct {
+ void* bus;
+ void* urb;
+ } usb;
+ } bus_specific;
+} dhd_pkttag_t;
+
+#define DHD_PKTTAG_WLFCPKT_MASK 0x1
+#define DHD_PKTTAG_WLFCPKT_SHIFT 15
+#define DHD_PKTTAG_WLFCPKT_SET(tag, value) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & \
+ ~(DHD_PKTTAG_WLFCPKT_MASK << DHD_PKTTAG_WLFCPKT_SHIFT)) | \
+ (((value) & DHD_PKTTAG_WLFCPKT_MASK) << DHD_PKTTAG_WLFCPKT_SHIFT)
+#define DHD_PKTTAG_WLFCPKT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_WLFCPKT_SHIFT) & DHD_PKTTAG_WLFCPKT_MASK)
+
+#define DHD_PKTTAG_EXEMPT_MASK 0x3
+#define DHD_PKTTAG_EXEMPT_SHIFT 13
+#define DHD_PKTTAG_EXEMPT_SET(tag, value) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & \
+ ~(DHD_PKTTAG_EXEMPT_MASK << DHD_PKTTAG_EXEMPT_SHIFT)) | \
+ (((value) & DHD_PKTTAG_EXEMPT_MASK) << DHD_PKTTAG_EXEMPT_SHIFT)
+#define DHD_PKTTAG_EXEMPT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_EXEMPT_SHIFT) & DHD_PKTTAG_EXEMPT_MASK)
+
+#define DHD_PKTTAG_EVENT_MASK 0x1
+#define DHD_PKTTAG_EVENT_SHIFT 12
+#define DHD_PKTTAG_SETEVENT(tag, event) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & \
+ ~(DHD_PKTTAG_EVENT_MASK << DHD_PKTTAG_EVENT_SHIFT)) | \
+ (((event) & DHD_PKTTAG_EVENT_MASK) << DHD_PKTTAG_EVENT_SHIFT)
+#define DHD_PKTTAG_EVENT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_EVENT_SHIFT) & DHD_PKTTAG_EVENT_MASK)
+
+#define DHD_PKTTAG_ONETIMEPKTRQST_MASK 0x1
+#define DHD_PKTTAG_ONETIMEPKTRQST_SHIFT 11
+#define DHD_PKTTAG_SETONETIMEPKTRQST(tag) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & \
+ ~(DHD_PKTTAG_ONETIMEPKTRQST_MASK << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)) | \
+ (1 << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)
+#define DHD_PKTTAG_ONETIMEPKTRQST(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) & DHD_PKTTAG_ONETIMEPKTRQST_MASK)
+
+#define DHD_PKTTAG_SIGNALONLY_MASK 0x1
+#define DHD_PKTTAG_SIGNALONLY_SHIFT 10
+#define DHD_PKTTAG_SETSIGNALONLY(tag, signalonly) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & \
+ ~(DHD_PKTTAG_SIGNALONLY_MASK << DHD_PKTTAG_SIGNALONLY_SHIFT)) | \
+ (((signalonly) & DHD_PKTTAG_SIGNALONLY_MASK) << DHD_PKTTAG_SIGNALONLY_SHIFT)
+#define DHD_PKTTAG_SIGNALONLY(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_SIGNALONLY_SHIFT) & DHD_PKTTAG_SIGNALONLY_MASK)
+
+#define DHD_PKTTAG_PKTDIR_MASK 0x1
+#define DHD_PKTTAG_PKTDIR_SHIFT 9
+#define DHD_PKTTAG_SETPKTDIR(tag, dir) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & \
+ ~(DHD_PKTTAG_PKTDIR_MASK << DHD_PKTTAG_PKTDIR_SHIFT)) | \
+ (((dir) & DHD_PKTTAG_PKTDIR_MASK) << DHD_PKTTAG_PKTDIR_SHIFT)
+#define DHD_PKTTAG_PKTDIR(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_PKTDIR_SHIFT) & DHD_PKTTAG_PKTDIR_MASK)
+
+#define DHD_PKTTAG_CREDITCHECK_MASK 0x1
+#define DHD_PKTTAG_CREDITCHECK_SHIFT 8
+#define DHD_PKTTAG_SETCREDITCHECK(tag, check) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & \
+ ~(DHD_PKTTAG_CREDITCHECK_MASK << DHD_PKTTAG_CREDITCHECK_SHIFT)) | \
+ (((check) & DHD_PKTTAG_CREDITCHECK_MASK) << DHD_PKTTAG_CREDITCHECK_SHIFT)
+#define DHD_PKTTAG_CREDITCHECK(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_CREDITCHECK_SHIFT) & DHD_PKTTAG_CREDITCHECK_MASK)
+
+#define DHD_PKTTAG_IFTYPE_MASK 0x1
+#define DHD_PKTTAG_IFTYPE_SHIFT 7
+#define DHD_PKTTAG_SETIFTYPE(tag, isAP) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & \
+ ~(DHD_PKTTAG_IFTYPE_MASK << DHD_PKTTAG_IFTYPE_SHIFT)) | \
+ (((isAP) & DHD_PKTTAG_IFTYPE_MASK) << DHD_PKTTAG_IFTYPE_SHIFT)
+#define DHD_PKTTAG_IFTYPE(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_IFTYPE_SHIFT) & DHD_PKTTAG_IFTYPE_MASK)
+
+#define DHD_PKTTAG_FIFO_MASK 0x7
+#define DHD_PKTTAG_FIFO_SHIFT 4
+#define DHD_PKTTAG_SETFIFO(tag, fifo) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_FIFO_MASK << DHD_PKTTAG_FIFO_SHIFT)) | \
+ (((fifo) & DHD_PKTTAG_FIFO_MASK) << DHD_PKTTAG_FIFO_SHIFT)
+#define DHD_PKTTAG_FIFO(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_FIFO_SHIFT) & DHD_PKTTAG_FIFO_MASK)
+
+#define DHD_PKTTAG_IF_MASK 0xf
+#define DHD_PKTTAG_IF_SHIFT 0
+#define DHD_PKTTAG_SETIF(tag, if) ((dhd_pkttag_t*)(tag))->if_flags = \
+ (((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_IF_MASK << DHD_PKTTAG_IF_SHIFT)) | \
+ (((if) & DHD_PKTTAG_IF_MASK) << DHD_PKTTAG_IF_SHIFT)
+#define DHD_PKTTAG_IF(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
+ DHD_PKTTAG_IF_SHIFT) & DHD_PKTTAG_IF_MASK)
+
+#define DHD_PKTTAG_SETDSTN(tag, dstn_MAC_ea) memcpy(((dhd_pkttag_t*)((tag)))->dstn_ether, \
+ (dstn_MAC_ea), ETHER_ADDR_LEN)
+#define DHD_PKTTAG_DSTN(tag) ((dhd_pkttag_t*)(tag))->dstn_ether
+
+#define DHD_PKTTAG_SET_H2DTAG(tag, h2dvalue) ((dhd_pkttag_t*)(tag))->htod_tag = (h2dvalue)
+#define DHD_PKTTAG_H2DTAG(tag) (((dhd_pkttag_t*)(tag))->htod_tag)
+
+#define DHD_PKTTAG_SET_H2DSEQ(tag, seq) ((dhd_pkttag_t*)(tag))->htod_seq = (seq)
+#define DHD_PKTTAG_H2DSEQ(tag) (((dhd_pkttag_t*)(tag))->htod_seq)
+
+#define DHD_PKTTAG_SET_ENTRY(tag, entry) ((dhd_pkttag_t*)(tag))->entry = (entry)
+#define DHD_PKTTAG_ENTRY(tag) (((dhd_pkttag_t*)(tag))->entry)
+
+#define PSQ_SUP_IDX(x) (x * 2 + 1)
+#define PSQ_DLY_IDX(x) (x * 2)
+
+typedef int (*f_commitpkt_t)(void* ctx, void* p);
+typedef bool (*f_processpkt_t)(void* p, void* arg);
+
+#ifdef PROP_TXSTATUS_DEBUG
+#define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do { (entry)->closed_ct++; } while (0)
+#define DHD_WLFC_CTRINC_MAC_OPEN(entry) do { (entry)->opened_ct++; } while (0)
+#else
+#define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do {} while (0)
+#define DHD_WLFC_CTRINC_MAC_OPEN(entry) do {} while (0)
+#endif
+
+/* public functions */
+int dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len,
+ uchar *reorder_info_buf, uint *reorder_info_len);
+int dhd_wlfc_commit_packets(dhd_pub_t *dhdp, f_commitpkt_t fcommit,
+ void* commit_ctx, void *pktbuf, bool need_toggle_host_if);
+int dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success);
+int dhd_wlfc_init(dhd_pub_t *dhd);
+int dhd_wlfc_hostreorder_init(dhd_pub_t *dhd);
+#ifdef SUPPORT_P2P_GO_PS
+int dhd_wlfc_suspend(dhd_pub_t *dhd);
+int dhd_wlfc_resume(dhd_pub_t *dhd);
+#endif /* SUPPORT_P2P_GO_PS */
+int dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg);
+int dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void* arg);
+int dhd_wlfc_deinit(dhd_pub_t *dhd);
+int dhd_wlfc_interface_event(dhd_pub_t *dhdp, uint8 action, uint8 ifid, uint8 iftype, uint8* ea);
+int dhd_wlfc_FIFOcreditmap_event(dhd_pub_t *dhdp, uint8* event_data);
+int dhd_wlfc_BCMCCredit_support_event(dhd_pub_t *dhdp);
+int dhd_wlfc_enable(dhd_pub_t *dhdp);
+int dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+int dhd_wlfc_clear_counts(dhd_pub_t *dhd);
+int dhd_wlfc_get_enable(dhd_pub_t *dhd, bool *val);
+int dhd_wlfc_get_mode(dhd_pub_t *dhd, int *val);
+int dhd_wlfc_set_mode(dhd_pub_t *dhd, int val);
+bool dhd_wlfc_is_supported(dhd_pub_t *dhd);
+bool dhd_wlfc_is_header_only_pkt(dhd_pub_t * dhd, void *pktbuf);
+int dhd_wlfc_flowcontrol(dhd_pub_t *dhdp, bool state, bool bAcquireLock);
+int dhd_wlfc_save_rxpath_ac_time(dhd_pub_t * dhd, uint8 prio);
+
+int dhd_wlfc_get_module_ignore(dhd_pub_t *dhd, int *val);
+int dhd_wlfc_set_module_ignore(dhd_pub_t *dhd, int val);
+int dhd_wlfc_get_credit_ignore(dhd_pub_t *dhd, int *val);
+int dhd_wlfc_set_credit_ignore(dhd_pub_t *dhd, int val);
+int dhd_wlfc_get_txstatus_ignore(dhd_pub_t *dhd, int *val);
+int dhd_wlfc_set_txstatus_ignore(dhd_pub_t *dhd, int val);
+
+int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val);
+int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val);
+#endif /* __wlfc_host_driver_definitions_h__ */
diff --git a/drivers/net/wireless/bcmdhd/dngl_stats.h b/drivers/net/wireless/bcmdhd/dngl_stats.h
new file mode 100644
index 000000000000..9546e8042d70
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dngl_stats.h
@@ -0,0 +1,43 @@
+/*
+ * Common stats definitions for clients of dongle
+ * ports
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dngl_stats.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _dngl_stats_h_
+#define _dngl_stats_h_
+
+typedef struct {
+ unsigned long rx_packets; /* total packets received */
+ unsigned long tx_packets; /* total packets transmitted */
+ unsigned long rx_bytes; /* total bytes received */
+ unsigned long tx_bytes; /* total bytes transmitted */
+ unsigned long rx_errors; /* bad packets received */
+ unsigned long tx_errors; /* packet transmit problems */
+ unsigned long rx_dropped; /* packets dropped by dongle */
+ unsigned long tx_dropped; /* packets dropped by dongle */
+ unsigned long multicast; /* multicast packets received */
+} dngl_stats_t;
+
+#endif /* _dngl_stats_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dngl_wlhdr.h b/drivers/net/wireless/bcmdhd/dngl_wlhdr.h
new file mode 100644
index 000000000000..8a254f44c9d6
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dngl_wlhdr.h
@@ -0,0 +1,40 @@
+/*
+ * Dongle WL Header definitions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dngl_wlhdr.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _dngl_wlhdr_h_
+#define _dngl_wlhdr_h_
+
+typedef struct wl_header {
+ uint8 type; /* Header type */
+ uint8 version; /* Header version */
+ int8 rssi; /* RSSI */
+ uint8 pad; /* Unused */
+} wl_header_t;
+
+#define WL_HEADER_LEN sizeof(wl_header_t)
+#define WL_HEADER_TYPE 0
+#define WL_HEADER_VER 1
+#endif /* _dngl_wlhdr_h_ */
diff --git a/drivers/net/wireless/bcmdhd/hndpmu.c b/drivers/net/wireless/bcmdhd/hndpmu.c
new file mode 100644
index 000000000000..8268afc90e0b
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/hndpmu.c
@@ -0,0 +1,282 @@
+/*
+ * Misc utility routines for accessing PMU corerev specific features
+ * of the SiliconBackplane-based Broadcom chips.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: hndpmu.c 530682 2015-01-30 18:48:21Z $
+ */
+
+
+/*
+ * Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs.
+ * However, in the context of this file the baseband ('BB') PLL/FLL is referred to.
+ *
+ * Throughout this code, the prefixes 'pmu0_', 'pmu1_' and 'pmu2_' are used.
+ * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012)
+ * pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports
+ * fractional frequency generation. pmu2_ does not support fractional frequency generation.
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <bcmdevs.h>
+#include <hndsoc.h>
+#include <sbchipc.h>
+#include <hndpmu.h>
+
+#define PMU_ERROR(args)
+
+#define PMU_MSG(args)
+
+/* To check in verbose debugging messages not intended
+ * to be on except on private builds.
+ */
+#define PMU_NONE(args)
+
+/** contains resource bit positions for a specific chip */
+struct rsc_per_chip_s {
+ uint8 ht_avail;
+ uint8 macphy_clkavail;
+ uint8 ht_start;
+ uint8 otp_pu;
+};
+
+typedef struct rsc_per_chip_s rsc_per_chip_t;
+
+
+/* SDIO Pad drive strength to select value mappings.
+ * The last strength value in each table must be 0 (the tri-state value).
+ */
+typedef struct {
+ uint8 strength; /* Pad Drive Strength in mA */
+ uint8 sel; /* Chip-specific select value */
+} sdiod_drive_str_t;
+
+/* SDIO Drive Strength to sel value table for PMU Rev 1 */
+static const sdiod_drive_str_t sdiod_drive_strength_tab1[] = {
+ {4, 0x2},
+ {2, 0x3},
+ {1, 0x0},
+ {0, 0x0} };
+
+/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
+static const sdiod_drive_str_t sdiod_drive_strength_tab2[] = {
+ {12, 0x7},
+ {10, 0x6},
+ {8, 0x5},
+ {6, 0x4},
+ {4, 0x2},
+ {2, 0x1},
+ {0, 0x0} };
+
+/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
+static const sdiod_drive_str_t sdiod_drive_strength_tab3[] = {
+ {32, 0x7},
+ {26, 0x6},
+ {22, 0x5},
+ {16, 0x4},
+ {12, 0x3},
+ {8, 0x2},
+ {4, 0x1},
+ {0, 0x0} };
+
+/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8v) */
+static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v8[] = {
+ {32, 0x6},
+ {26, 0x7},
+ {22, 0x4},
+ {16, 0x5},
+ {12, 0x2},
+ {8, 0x3},
+ {4, 0x0},
+ {0, 0x1} };
+
+/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.2v) */
+
+/* SDIO Drive Strength to sel value table for PMU Rev 11 (2.5v) */
+
+/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
+static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = {
+ {6, 0x7},
+ {5, 0x6},
+ {4, 0x5},
+ {3, 0x4},
+ {2, 0x2},
+ {1, 0x1},
+ {0, 0x0} };
+
+/* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */
+
+/** SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
+static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = {
+ {3, 0x3},
+ {2, 0x2},
+ {1, 0x1},
+ {0, 0x0} };
+
+
+/**
+ * SDIO Drive Strength to sel value table for 43143 PMU Rev 17, see Confluence 43143 Toplevel
+ * architecture page, section 'PMU Chip Control 1 Register definition', click link to picture
+ * BCM43143_sel_sdio_signals.jpg. Valid after PMU Chip Control 0 Register, bit31 (override) has
+ * been written '1'.
+ */
+#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33
+
+static const sdiod_drive_str_t sdiod_drive_strength_tab7_3v3[] = {
+ /* note: for 14, 10, 6 and 2mA hw timing is not met according to rtl team */
+ {16, 0x7},
+ {12, 0x5},
+ {8, 0x3},
+ {4, 0x1} }; /* note: 43143 does not support tristate */
+
+#else
+
+static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = {
+ /* note: for 7, 5, 3 and 1mA hw timing is not met according to rtl team */
+ {8, 0x7},
+ {6, 0x5},
+ {4, 0x3},
+ {2, 0x1} }; /* note: 43143 does not support tristate */
+
+#endif /* BCM_SDIO_VDDIO */
+
+#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
+
+/**
+ * Balance between stable SDIO operation and power consumption is achieved using this function.
+ * Note that each drive strength table is for a specific VDDIO of the SDIO pads, ideally this
+ * function should read the VDDIO itself to select the correct table. For now it has been solved
+ * with the 'BCM_SDIO_VDDIO' preprocessor constant.
+ *
+ * 'drivestrength': desired pad drive strength in mA. Drive strength of 0 requests tri-state (if
+ * hardware supports this), if no hw support drive strength is not programmed.
+ */
+void
+si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
+{
+ chipcregs_t *cc;
+ uint origidx, intr_val = 0;
+ sdiod_drive_str_t *str_tab = NULL;
+ uint32 str_mask = 0; /* only alter desired bits in PMU chipcontrol 1 register */
+ uint32 str_shift = 0;
+ uint32 str_ovr_pmuctl = PMU_CHIPCTL0; /* PMU chipcontrol register containing override bit */
+ uint32 str_ovr_pmuval = 0; /* position of bit within this register */
+
+ if (!(sih->cccaps & CC_CAP_PMU)) {
+ return;
+ }
+
+ /* Remember original core before switch to chipc */
+ cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
+
+ switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) {
+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
+ str_mask = 0x30000000;
+ str_shift = 28;
+ break;
+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
+ case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4):
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
+ str_mask = 0x00003800;
+ str_shift = 11;
+ break;
+ case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
+ case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11):
+ if (sih->pmurev == 8) {
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3;
+ }
+ else if (sih->pmurev == 11) {
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8;
+ }
+ str_mask = 0x00003800;
+ str_shift = 11;
+ break;
+ case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8;
+ str_mask = 0x00003800;
+ str_shift = 11;
+ break;
+ case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8;
+ str_mask = 0x00003800;
+ str_shift = 11;
+ break;
+ case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab6_1v8;
+ str_mask = 0x00001800;
+ str_shift = 11;
+ break;
+ case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
+#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33
+ if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_3v3)->strength) {
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_3v3;
+ }
+#else
+ if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_1v8)->strength) {
+ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_1v8;
+ }
+#endif /* BCM_SDIO_VDDIO */
+ str_mask = 0x00000007;
+ str_ovr_pmuval = PMU43143_CC0_SDIO_DRSTR_OVR;
+ break;
+ default:
+ PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
+ bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
+ break;
+ }
+
+ if (str_tab != NULL && cc != NULL) {
+ uint32 cc_data_temp;
+ int i;
+
+ /* Pick the lowest available drive strength equal or greater than the
+ * requested strength. Drive strength of 0 requests tri-state.
+ */
+ for (i = 0; drivestrength < str_tab[i].strength; i++)
+ ;
+
+ if (i > 0 && drivestrength > str_tab[i].strength)
+ i--;
+
+ W_REG(osh, &cc->chipcontrol_addr, PMU_CHIPCTL1);
+ cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
+ cc_data_temp &= ~str_mask;
+ cc_data_temp |= str_tab[i].sel << str_shift;
+ W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
+ if (str_ovr_pmuval) { /* enables the selected drive strength */
+ W_REG(osh, &cc->chipcontrol_addr, str_ovr_pmuctl);
+ OR_REG(osh, &cc->chipcontrol_data, str_ovr_pmuval);
+ }
+ PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n",
+ drivestrength, str_tab[i].strength));
+ }
+
+ /* Return to original core */
+ si_restore_core(sih, origidx, intr_val);
+} /* si_sdiod_drive_strength_init */
diff --git a/drivers/net/wireless/bcmdhd/include/Makefile b/drivers/net/wireless/bcmdhd/include/Makefile
new file mode 100644
index 000000000000..bc90f3cab224
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/Makefile
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# This script serves following purpose:
+#
+# 1. It generates native version information by querying
+# automerger maintained database to see where src/include
+# came from
+# 2. For select components, as listed in compvers.sh
+# it generates component version files
+#
+# Copyright 2005, Broadcom, Inc.
+#
+# $Id: Makefile 347587 2012-07-27 09:13:31Z $
+#
+
+export SRCBASE:=..
+
+TARGETS := epivers.h
+
+ifdef VERBOSE
+export VERBOSE
+endif
+
+all release: epivers compvers
+
+# Generate epivers.h for native branch url
+epivers:
+ bash epivers.sh
+
+# Generate component versions based on component url
+compvers:
+ @if [ -s "compvers.sh" ]; then \
+ echo "Generating component versions, if any"; \
+ bash compvers.sh; \
+ else \
+ echo "Skipping component version generation"; \
+ fi
+
+# Generate epivers.h for native branch version
+clean_compvers:
+ @if [ -s "compvers.sh" ]; then \
+ echo "bash compvers.sh clean"; \
+ bash compvers.sh clean; \
+ else \
+ echo "Skipping component version clean"; \
+ fi
+
+clean:
+ rm -f $(TARGETS) *.prev
+
+clean_all: clean clean_compvers
+
+.PHONY: all release clean epivers compvers clean_compvers
diff --git a/drivers/net/wireless/bcmdhd/include/aidmp.h b/drivers/net/wireless/bcmdhd/include/aidmp.h
new file mode 100644
index 000000000000..95745e5178c5
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/aidmp.h
@@ -0,0 +1,387 @@
+/*
+ * Broadcom AMBA Interconnect definitions.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: aidmp.h 530682 2015-01-30 18:48:21Z $
+ */
+
+#ifndef _AIDMP_H
+#define _AIDMP_H
+
+/* Manufacturer Ids */
+#define MFGID_ARM 0x43b
+#define MFGID_BRCM 0x4bf
+#define MFGID_MIPS 0x4a7
+
+/* Component Classes */
+#define CC_SIM 0
+#define CC_EROM 1
+#define CC_CORESIGHT 9
+#define CC_VERIF 0xb
+#define CC_OPTIMO 0xd
+#define CC_GEN 0xe
+#define CC_PRIMECELL 0xf
+
+/* Enumeration ROM registers */
+#define ER_EROMENTRY 0x000
+#define ER_REMAPCONTROL 0xe00
+#define ER_REMAPSELECT 0xe04
+#define ER_MASTERSELECT 0xe10
+#define ER_ITCR 0xf00
+#define ER_ITIP 0xf04
+
+/* Erom entries */
+#define ER_TAG 0xe
+#define ER_TAG1 0x6
+#define ER_VALID 1
+#define ER_CI 0
+#define ER_MP 2
+#define ER_ADD 4
+#define ER_END 0xe
+#define ER_BAD 0xffffffff
+#define ER_SZ_MAX 4096 /* 4KB */
+
+/* EROM CompIdentA */
+#define CIA_MFG_MASK 0xfff00000
+#define CIA_MFG_SHIFT 20
+#define CIA_CID_MASK 0x000fff00
+#define CIA_CID_SHIFT 8
+#define CIA_CCL_MASK 0x000000f0
+#define CIA_CCL_SHIFT 4
+
+/* EROM CompIdentB */
+#define CIB_REV_MASK 0xff000000
+#define CIB_REV_SHIFT 24
+#define CIB_NSW_MASK 0x00f80000
+#define CIB_NSW_SHIFT 19
+#define CIB_NMW_MASK 0x0007c000
+#define CIB_NMW_SHIFT 14
+#define CIB_NSP_MASK 0x00003e00
+#define CIB_NSP_SHIFT 9
+#define CIB_NMP_MASK 0x000001f0
+#define CIB_NMP_SHIFT 4
+
+/* EROM MasterPortDesc */
+#define MPD_MUI_MASK 0x0000ff00
+#define MPD_MUI_SHIFT 8
+#define MPD_MP_MASK 0x000000f0
+#define MPD_MP_SHIFT 4
+
+/* EROM AddrDesc */
+#define AD_ADDR_MASK 0xfffff000
+#define AD_SP_MASK 0x00000f00
+#define AD_SP_SHIFT 8
+#define AD_ST_MASK 0x000000c0
+#define AD_ST_SHIFT 6
+#define AD_ST_SLAVE 0x00000000
+#define AD_ST_BRIDGE 0x00000040
+#define AD_ST_SWRAP 0x00000080
+#define AD_ST_MWRAP 0x000000c0
+#define AD_SZ_MASK 0x00000030
+#define AD_SZ_SHIFT 4
+#define AD_SZ_4K 0x00000000
+#define AD_SZ_8K 0x00000010
+#define AD_SZ_16K 0x00000020
+#define AD_SZ_SZD 0x00000030
+#define AD_AG32 0x00000008
+#define AD_ADDR_ALIGN 0x00000fff
+#define AD_SZ_BASE 0x00001000 /* 4KB */
+
+/* EROM SizeDesc */
+#define SD_SZ_MASK 0xfffff000
+#define SD_SG32 0x00000008
+#define SD_SZ_ALIGN 0x00000fff
+
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+typedef volatile struct _aidmp {
+ uint32 oobselina30; /* 0x000 */
+ uint32 oobselina74; /* 0x004 */
+ uint32 PAD[6];
+ uint32 oobselinb30; /* 0x020 */
+ uint32 oobselinb74; /* 0x024 */
+ uint32 PAD[6];
+ uint32 oobselinc30; /* 0x040 */
+ uint32 oobselinc74; /* 0x044 */
+ uint32 PAD[6];
+ uint32 oobselind30; /* 0x060 */
+ uint32 oobselind74; /* 0x064 */
+ uint32 PAD[38];
+ uint32 oobselouta30; /* 0x100 */
+ uint32 oobselouta74; /* 0x104 */
+ uint32 PAD[6];
+ uint32 oobseloutb30; /* 0x120 */
+ uint32 oobseloutb74; /* 0x124 */
+ uint32 PAD[6];
+ uint32 oobseloutc30; /* 0x140 */
+ uint32 oobseloutc74; /* 0x144 */
+ uint32 PAD[6];
+ uint32 oobseloutd30; /* 0x160 */
+ uint32 oobseloutd74; /* 0x164 */
+ uint32 PAD[38];
+ uint32 oobsynca; /* 0x200 */
+ uint32 oobseloutaen; /* 0x204 */
+ uint32 PAD[6];
+ uint32 oobsyncb; /* 0x220 */
+ uint32 oobseloutben; /* 0x224 */
+ uint32 PAD[6];
+ uint32 oobsyncc; /* 0x240 */
+ uint32 oobseloutcen; /* 0x244 */
+ uint32 PAD[6];
+ uint32 oobsyncd; /* 0x260 */
+ uint32 oobseloutden; /* 0x264 */
+ uint32 PAD[38];
+ uint32 oobaextwidth; /* 0x300 */
+ uint32 oobainwidth; /* 0x304 */
+ uint32 oobaoutwidth; /* 0x308 */
+ uint32 PAD[5];
+ uint32 oobbextwidth; /* 0x320 */
+ uint32 oobbinwidth; /* 0x324 */
+ uint32 oobboutwidth; /* 0x328 */
+ uint32 PAD[5];
+ uint32 oobcextwidth; /* 0x340 */
+ uint32 oobcinwidth; /* 0x344 */
+ uint32 oobcoutwidth; /* 0x348 */
+ uint32 PAD[5];
+ uint32 oobdextwidth; /* 0x360 */
+ uint32 oobdinwidth; /* 0x364 */
+ uint32 oobdoutwidth; /* 0x368 */
+ uint32 PAD[37];
+ uint32 ioctrlset; /* 0x400 */
+ uint32 ioctrlclear; /* 0x404 */
+ uint32 ioctrl; /* 0x408 */
+ uint32 PAD[61];
+ uint32 iostatus; /* 0x500 */
+ uint32 PAD[127];
+ uint32 ioctrlwidth; /* 0x700 */
+ uint32 iostatuswidth; /* 0x704 */
+ uint32 PAD[62];
+ uint32 resetctrl; /* 0x800 */
+ uint32 resetstatus; /* 0x804 */
+ uint32 resetreadid; /* 0x808 */
+ uint32 resetwriteid; /* 0x80c */
+ uint32 PAD[60];
+ uint32 errlogctrl; /* 0x900 */
+ uint32 errlogdone; /* 0x904 */
+ uint32 errlogstatus; /* 0x908 */
+ uint32 errlogaddrlo; /* 0x90c */
+ uint32 errlogaddrhi; /* 0x910 */
+ uint32 errlogid; /* 0x914 */
+ uint32 errloguser; /* 0x918 */
+ uint32 errlogflags; /* 0x91c */
+ uint32 PAD[56];
+ uint32 intstatus; /* 0xa00 */
+ uint32 PAD[255];
+ uint32 config; /* 0xe00 */
+ uint32 PAD[63];
+ uint32 itcr; /* 0xf00 */
+ uint32 PAD[3];
+ uint32 itipooba; /* 0xf10 */
+ uint32 itipoobb; /* 0xf14 */
+ uint32 itipoobc; /* 0xf18 */
+ uint32 itipoobd; /* 0xf1c */
+ uint32 PAD[4];
+ uint32 itipoobaout; /* 0xf30 */
+ uint32 itipoobbout; /* 0xf34 */
+ uint32 itipoobcout; /* 0xf38 */
+ uint32 itipoobdout; /* 0xf3c */
+ uint32 PAD[4];
+ uint32 itopooba; /* 0xf50 */
+ uint32 itopoobb; /* 0xf54 */
+ uint32 itopoobc; /* 0xf58 */
+ uint32 itopoobd; /* 0xf5c */
+ uint32 PAD[4];
+ uint32 itopoobain; /* 0xf70 */
+ uint32 itopoobbin; /* 0xf74 */
+ uint32 itopoobcin; /* 0xf78 */
+ uint32 itopoobdin; /* 0xf7c */
+ uint32 PAD[4];
+ uint32 itopreset; /* 0xf90 */
+ uint32 PAD[15];
+ uint32 peripherialid4; /* 0xfd0 */
+ uint32 peripherialid5; /* 0xfd4 */
+ uint32 peripherialid6; /* 0xfd8 */
+ uint32 peripherialid7; /* 0xfdc */
+ uint32 peripherialid0; /* 0xfe0 */
+ uint32 peripherialid1; /* 0xfe4 */
+ uint32 peripherialid2; /* 0xfe8 */
+ uint32 peripherialid3; /* 0xfec */
+ uint32 componentid0; /* 0xff0 */
+ uint32 componentid1; /* 0xff4 */
+ uint32 componentid2; /* 0xff8 */
+ uint32 componentid3; /* 0xffc */
+} aidmp_t;
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+/* Out-of-band Router registers */
+#define OOB_BUSCONFIG 0x020
+#define OOB_STATUSA 0x100
+#define OOB_STATUSB 0x104
+#define OOB_STATUSC 0x108
+#define OOB_STATUSD 0x10c
+#define OOB_ENABLEA0 0x200
+#define OOB_ENABLEA1 0x204
+#define OOB_ENABLEA2 0x208
+#define OOB_ENABLEA3 0x20c
+#define OOB_ENABLEB0 0x280
+#define OOB_ENABLEB1 0x284
+#define OOB_ENABLEB2 0x288
+#define OOB_ENABLEB3 0x28c
+#define OOB_ENABLEC0 0x300
+#define OOB_ENABLEC1 0x304
+#define OOB_ENABLEC2 0x308
+#define OOB_ENABLEC3 0x30c
+#define OOB_ENABLED0 0x380
+#define OOB_ENABLED1 0x384
+#define OOB_ENABLED2 0x388
+#define OOB_ENABLED3 0x38c
+#define OOB_ITCR 0xf00
+#define OOB_ITIPOOBA 0xf10
+#define OOB_ITIPOOBB 0xf14
+#define OOB_ITIPOOBC 0xf18
+#define OOB_ITIPOOBD 0xf1c
+#define OOB_ITOPOOBA 0xf30
+#define OOB_ITOPOOBB 0xf34
+#define OOB_ITOPOOBC 0xf38
+#define OOB_ITOPOOBD 0xf3c
+
+/* DMP wrapper registers */
+#define AI_OOBSELINA30 0x000
+#define AI_OOBSELINA74 0x004
+#define AI_OOBSELINB30 0x020
+#define AI_OOBSELINB74 0x024
+#define AI_OOBSELINC30 0x040
+#define AI_OOBSELINC74 0x044
+#define AI_OOBSELIND30 0x060
+#define AI_OOBSELIND74 0x064
+#define AI_OOBSELOUTA30 0x100
+#define AI_OOBSELOUTA74 0x104
+#define AI_OOBSELOUTB30 0x120
+#define AI_OOBSELOUTB74 0x124
+#define AI_OOBSELOUTC30 0x140
+#define AI_OOBSELOUTC74 0x144
+#define AI_OOBSELOUTD30 0x160
+#define AI_OOBSELOUTD74 0x164
+#define AI_OOBSYNCA 0x200
+#define AI_OOBSELOUTAEN 0x204
+#define AI_OOBSYNCB 0x220
+#define AI_OOBSELOUTBEN 0x224
+#define AI_OOBSYNCC 0x240
+#define AI_OOBSELOUTCEN 0x244
+#define AI_OOBSYNCD 0x260
+#define AI_OOBSELOUTDEN 0x264
+#define AI_OOBAEXTWIDTH 0x300
+#define AI_OOBAINWIDTH 0x304
+#define AI_OOBAOUTWIDTH 0x308
+#define AI_OOBBEXTWIDTH 0x320
+#define AI_OOBBINWIDTH 0x324
+#define AI_OOBBOUTWIDTH 0x328
+#define AI_OOBCEXTWIDTH 0x340
+#define AI_OOBCINWIDTH 0x344
+#define AI_OOBCOUTWIDTH 0x348
+#define AI_OOBDEXTWIDTH 0x360
+#define AI_OOBDINWIDTH 0x364
+#define AI_OOBDOUTWIDTH 0x368
+
+
+#define AI_IOCTRLSET 0x400
+#define AI_IOCTRLCLEAR 0x404
+#define AI_IOCTRL 0x408
+#define AI_IOSTATUS 0x500
+#define AI_RESETCTRL 0x800
+#define AI_RESETSTATUS 0x804
+
+#define AI_IOCTRLWIDTH 0x700
+#define AI_IOSTATUSWIDTH 0x704
+
+#define AI_RESETREADID 0x808
+#define AI_RESETWRITEID 0x80c
+#define AI_ERRLOGCTRL 0xa00
+#define AI_ERRLOGDONE 0xa04
+#define AI_ERRLOGSTATUS 0xa08
+#define AI_ERRLOGADDRLO 0xa0c
+#define AI_ERRLOGADDRHI 0xa10
+#define AI_ERRLOGID 0xa14
+#define AI_ERRLOGUSER 0xa18
+#define AI_ERRLOGFLAGS 0xa1c
+#define AI_INTSTATUS 0xa00
+#define AI_CONFIG 0xe00
+#define AI_ITCR 0xf00
+#define AI_ITIPOOBA 0xf10
+#define AI_ITIPOOBB 0xf14
+#define AI_ITIPOOBC 0xf18
+#define AI_ITIPOOBD 0xf1c
+#define AI_ITIPOOBAOUT 0xf30
+#define AI_ITIPOOBBOUT 0xf34
+#define AI_ITIPOOBCOUT 0xf38
+#define AI_ITIPOOBDOUT 0xf3c
+#define AI_ITOPOOBA 0xf50
+#define AI_ITOPOOBB 0xf54
+#define AI_ITOPOOBC 0xf58
+#define AI_ITOPOOBD 0xf5c
+#define AI_ITOPOOBAIN 0xf70
+#define AI_ITOPOOBBIN 0xf74
+#define AI_ITOPOOBCIN 0xf78
+#define AI_ITOPOOBDIN 0xf7c
+#define AI_ITOPRESET 0xf90
+#define AI_PERIPHERIALID4 0xfd0
+#define AI_PERIPHERIALID5 0xfd4
+#define AI_PERIPHERIALID6 0xfd8
+#define AI_PERIPHERIALID7 0xfdc
+#define AI_PERIPHERIALID0 0xfe0
+#define AI_PERIPHERIALID1 0xfe4
+#define AI_PERIPHERIALID2 0xfe8
+#define AI_PERIPHERIALID3 0xfec
+#define AI_COMPONENTID0 0xff0
+#define AI_COMPONENTID1 0xff4
+#define AI_COMPONENTID2 0xff8
+#define AI_COMPONENTID3 0xffc
+
+/* resetctrl */
+#define AIRC_RESET 1
+
+/* config */
+#define AICFG_OOB 0x00000020
+#define AICFG_IOS 0x00000010
+#define AICFG_IOC 0x00000008
+#define AICFG_TO 0x00000004
+#define AICFG_ERRL 0x00000002
+#define AICFG_RST 0x00000001
+
+/* bit defines for AI_OOBSELOUTB74 reg */
+#define OOB_SEL_OUTEN_B_5 15
+#define OOB_SEL_OUTEN_B_6 23
+
+/* AI_OOBSEL for A/B/C/D, 0-7 */
+#define AI_OOBSEL_MASK 0x1F
+#define AI_OOBSEL_0_SHIFT 0
+#define AI_OOBSEL_1_SHIFT 8
+#define AI_OOBSEL_2_SHIFT 16
+#define AI_OOBSEL_3_SHIFT 24
+#define AI_OOBSEL_4_SHIFT 0
+#define AI_OOBSEL_5_SHIFT 8
+#define AI_OOBSEL_6_SHIFT 16
+#define AI_OOBSEL_7_SHIFT 24
+
+#endif /* _AIDMP_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcm_cfg.h b/drivers/net/wireless/bcmdhd/include/bcm_cfg.h
new file mode 100644
index 000000000000..1fe8da885396
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcm_cfg.h
@@ -0,0 +1,29 @@
+/*
+ * BCM common config options
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcm_cfg.h 351867 2012-08-21 18:46:16Z $
+ */
+
+#ifndef _bcm_cfg_h_
+#define _bcm_cfg_h_
+#endif /* _bcm_cfg_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h b/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h
new file mode 100644
index 000000000000..f13d94d8aceb
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h
@@ -0,0 +1,361 @@
+/*
+ * Memory pools library, Public interface
+ *
+ * API Overview
+ *
+ * This package provides a memory allocation subsystem based on pools of
+ * homogenous objects.
+ *
+ * Instrumentation is available for reporting memory utilization both
+ * on a per-data-structure basis and system wide.
+ *
+ * There are two main types defined in this API.
+ *
+ * pool manager: A singleton object that acts as a factory for
+ * pool allocators. It also is used for global
+ * instrumentation, such as reporting all blocks
+ * in use across all data structures. The pool manager
+ * creates and provides individual memory pools
+ * upon request to application code.
+ *
+ * memory pool: An object for allocating homogenous memory blocks.
+ *
+ * Global identifiers in this module use the following prefixes:
+ * bcm_mpm_* Memory pool manager
+ * bcm_mp_* Memory pool
+ *
+ * There are two main types of memory pools:
+ *
+ * prealloc: The contiguous memory block of objects can either be supplied
+ * by the client or malloc'ed by the memory manager. The objects are
+ * allocated out of a block of memory and freed back to the block.
+ *
+ * heap: The memory pool allocator uses the heap (malloc/free) for memory.
+ * In this case, the pool allocator is just providing statistics
+ * and instrumentation on top of the heap, without modifying the heap
+ * allocation implementation.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcm_mpool_pub.h 407097 2013-06-11 18:43:16Z $
+ */
+
+#ifndef _BCM_MPOOL_PUB_H
+#define _BCM_MPOOL_PUB_H 1
+
+#include <typedefs.h> /* needed for uint16 */
+
+
+/*
+**************************************************************************
+*
+* Type definitions, handles
+*
+**************************************************************************
+*/
+
+/* Forward declaration of OSL handle. */
+struct osl_info;
+
+/* Forward declaration of string buffer. */
+struct bcmstrbuf;
+
+/*
+ * Opaque type definition for the pool manager handle. This object is used for global
+ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and
+ * instrumentation/debugging.
+ */
+struct bcm_mpm_mgr;
+typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h;
+
+/*
+ * Opaque type definition for an instance of a pool. This handle is used for allocating
+ * and freeing memory through the pool, as well as management/instrumentation on this
+ * specific pool.
+ */
+struct bcm_mp_pool;
+typedef struct bcm_mp_pool *bcm_mp_pool_h;
+
+
+/*
+ * To make instrumentation more readable, every memory
+ * pool must have a readable name. Pool names are up to
+ * 8 bytes including '\0' termination. (7 printable characters.)
+ */
+#define BCM_MP_NAMELEN 8
+
+
+/*
+ * Type definition for pool statistics.
+ */
+typedef struct bcm_mp_stats {
+ char name[BCM_MP_NAMELEN]; /* Name of this pool. */
+ unsigned int objsz; /* Object size allocated in this pool */
+ uint16 nobj; /* Total number of objects in this pool */
+ uint16 num_alloc; /* Number of objects currently allocated */
+ uint16 high_water; /* Max number of allocated objects. */
+ uint16 failed_alloc; /* Failed allocations. */
+} bcm_mp_stats_t;
+
+
+/*
+**************************************************************************
+*
+* API Routines on the pool manager.
+*
+**************************************************************************
+*/
+
+/*
+ * bcm_mpm_init() - initialize the whole memory pool system.
+ *
+ * Parameters:
+ * osh: INPUT Operating system handle. Needed for heap memory allocation.
+ * max_pools: INPUT Maximum number of mempools supported.
+ * mgr: OUTPUT The handle is written with the new pools manager object/handle.
+ *
+ * Returns:
+ * BCME_OK Object initialized successfully. May be used.
+ * BCME_NOMEM Initialization failed due to no memory. Object must not be used.
+ */
+int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp);
+
+
+/*
+ * bcm_mpm_deinit() - de-initialize the whole memory pool system.
+ *
+ * Parameters:
+ * mgr: INPUT Pointer to pool manager handle.
+ *
+ * Returns:
+ * BCME_OK Memory pool manager successfully de-initialized.
+ * other Indicated error occured during de-initialization.
+ */
+int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp);
+
+/*
+ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The
+ * pool uses a contiguous block of pre-alloced
+ * memory. The memory block may either be provided
+ * by the client or dynamically allocated by the
+ * pool manager.
+ *
+ * Parameters:
+ * mgr: INPUT The handle to the pool manager
+ * obj_sz: INPUT Size of objects that will be allocated by the new pool
+ * Must be >= sizeof(void *).
+ * nobj: INPUT Maximum number of concurrently existing objects to support
+ * memstart INPUT Pointer to the memory to use, or NULL to malloc()
+ * memsize INPUT Number of bytes referenced from memstart (for error checking).
+ * Must be 0 if 'memstart' is NULL.
+ * poolname INPUT For instrumentation, the name of the pool
+ * newp: OUTPUT The handle for the new pool, if creation is successful
+ *
+ * Returns:
+ * BCME_OK Pool created ok.
+ * other Pool not created due to indicated error. newpoolp set to NULL.
+ *
+ *
+ */
+int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr,
+ unsigned int obj_sz,
+ int nobj,
+ void *memstart,
+ unsigned int memsize,
+ const char poolname[BCM_MP_NAMELEN],
+ bcm_mp_pool_h *newp);
+
+
+/*
+ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after
+ * all memory objects have been freed back to the pool.
+ *
+ * Parameters:
+ * mgr: INPUT The handle to the pools manager
+ * pool: INPUT The handle of the pool to delete
+ *
+ * Returns:
+ * BCME_OK Pool deleted ok.
+ * other Pool not deleted due to indicated error.
+ *
+ */
+int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
+
+/*
+ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory
+ * pool allocator uses the heap (malloc/free) for memory.
+ * In this case, the pool allocator is just providing
+ * statistics and instrumentation on top of the heap,
+ * without modifying the heap allocation implementation.
+ *
+ * Parameters:
+ * mgr: INPUT The handle to the pool manager
+ * obj_sz: INPUT Size of objects that will be allocated by the new pool
+ * poolname INPUT For instrumentation, the name of the pool
+ * newp: OUTPUT The handle for the new pool, if creation is successful
+ *
+ * Returns:
+ * BCME_OK Pool created ok.
+ * other Pool not created due to indicated error. newpoolp set to NULL.
+ *
+ *
+ */
+int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz,
+ const char poolname[BCM_MP_NAMELEN],
+ bcm_mp_pool_h *newp);
+
+
+/*
+ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after
+ * all memory objects have been freed back to the pool.
+ *
+ * Parameters:
+ * mgr: INPUT The handle to the pools manager
+ * pool: INPUT The handle of the pool to delete
+ *
+ * Returns:
+ * BCME_OK Pool deleted ok.
+ * other Pool not deleted due to indicated error.
+ *
+ */
+int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
+
+
+/*
+ * bcm_mpm_stats() - Return stats for all pools
+ *
+ * Parameters:
+ * mgr: INPUT The handle to the pools manager
+ * stats: OUTPUT Array of pool statistics.
+ * nentries: MOD Max elements in 'stats' array on INPUT. Actual number
+ * of array elements copied to 'stats' on OUTPUT.
+ *
+ * Returns:
+ * BCME_OK Ok
+ * other Error getting stats.
+ *
+ */
+int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries);
+
+
+/*
+ * bcm_mpm_dump() - Display statistics on all pools
+ *
+ * Parameters:
+ * mgr: INPUT The handle to the pools manager
+ * b: OUTPUT Output buffer.
+ *
+ * Returns:
+ * BCME_OK Ok
+ * other Error during dump.
+ *
+ */
+int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b);
+
+
+/*
+ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to
+ * compensate for alignment requirements of the objects.
+ * This function provides the padded object size. If clients
+ * pre-allocate a memory slab for a memory pool, the
+ * padded object size should be used by the client to allocate
+ * the memory slab (in order to provide sufficent space for
+ * the maximum number of objects).
+ *
+ * Parameters:
+ * mgr: INPUT The handle to the pools manager.
+ * obj_sz: INPUT Input object size.
+ * padded_obj_sz: OUTPUT Padded object size.
+ *
+ * Returns:
+ * BCME_OK Ok
+ * BCME_BADARG Bad arguments.
+ *
+ */
+int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz);
+
+
+/*
+***************************************************************************
+*
+* API Routines on a specific pool.
+*
+***************************************************************************
+*/
+
+
+/*
+ * bcm_mp_alloc() - Allocate a memory pool object.
+ *
+ * Parameters:
+ * pool: INPUT The handle to the pool.
+ *
+ * Returns:
+ * A pointer to the new object. NULL on error.
+ *
+ */
+void* bcm_mp_alloc(bcm_mp_pool_h pool);
+
+/*
+ * bcm_mp_free() - Free a memory pool object.
+ *
+ * Parameters:
+ * pool: INPUT The handle to the pool.
+ * objp: INPUT A pointer to the object to free.
+ *
+ * Returns:
+ * BCME_OK Ok
+ * other Error during free.
+ *
+ */
+int bcm_mp_free(bcm_mp_pool_h pool, void *objp);
+
+/*
+ * bcm_mp_stats() - Return stats for this pool
+ *
+ * Parameters:
+ * pool: INPUT The handle to the pool
+ * stats: OUTPUT Pool statistics
+ *
+ * Returns:
+ * BCME_OK Ok
+ * other Error getting statistics.
+ *
+ */
+int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats);
+
+
+/*
+ * bcm_mp_dump() - Dump a pool
+ *
+ * Parameters:
+ * pool: INPUT The handle to the pool
+ * b OUTPUT Output buffer
+ *
+ * Returns:
+ * BCME_OK Ok
+ * other Error during dump.
+ *
+ */
+int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b);
+
+
+#endif /* _BCM_MPOOL_PUB_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmcdc.h b/drivers/net/wireless/bcmdhd/include/bcmcdc.h
new file mode 100644
index 000000000000..a70ab3f9d044
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmcdc.h
@@ -0,0 +1,132 @@
+/*
+ * CDC network driver ioctl/indication encoding
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmcdc.h 318308 2012-03-02 02:23:42Z $
+ */
+#ifndef _bcmcdc_h_
+#define _bcmcdc_h_
+#include <proto/ethernet.h>
+
+typedef struct cdc_ioctl {
+ uint32 cmd; /* ioctl command value */
+ uint32 len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */
+ uint32 flags; /* flag defns given below */
+ uint32 status; /* status code returned from the device */
+} cdc_ioctl_t;
+
+/* Max valid buffer size that can be sent to the dongle */
+#define CDC_MAX_MSG_SIZE ETHER_MAX_LEN
+
+/* len field is divided into input and output buffer lengths */
+#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected response length, */
+ /* excluding IOCTL header */
+#define CDCL_IOC_OUTLEN_SHIFT 0
+#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length, excluding IOCTL header */
+#define CDCL_IOC_INLEN_SHIFT 16
+
+/* CDC flag definitions */
+#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */
+#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */
+#define CDCF_IOC_OVL_IDX_MASK 0x3c /* overlay region index mask */
+#define CDCF_IOC_OVL_RSV 0x40 /* 1=reserve this overlay region */
+#define CDCF_IOC_OVL 0x80 /* 1=this ioctl corresponds to an overlay */
+#define CDCF_IOC_ACTION_MASK 0xfe /* SET/GET, OVL_IDX, OVL_RSV, OVL mask */
+#define CDCF_IOC_ACTION_SHIFT 1 /* SET/GET, OVL_IDX, OVL_RSV, OVL shift */
+#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */
+#define CDCF_IOC_IF_SHIFT 12
+#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl req/resp pairing */
+#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */
+
+#define CDC_IOC_IF_IDX(flags) (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
+#define CDC_IOC_ID(flags) (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
+
+#define CDC_GET_IF_IDX(hdr) \
+ ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
+#define CDC_SET_IF_IDX(hdr, idx) \
+ ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT)))
+
+/*
+ * BDC header
+ *
+ * The BDC header is used on data packets to convey priority across USB.
+ */
+
+struct bdc_header {
+ uint8 flags; /* Flags */
+ uint8 priority; /* 802.1d Priority 0:2 bits, 4:7 USB flow control info */
+ uint8 flags2;
+ uint8 dataOffset; /* Offset from end of BDC header to packet data, in
+ * 4-byte words. Leaves room for optional headers.
+ */
+};
+
+#define BDC_HEADER_LEN 4
+
+/* flags field bitmap */
+#define BDC_FLAG_80211_PKT 0x01 /* Packet is in 802.11 format (dongle -> host) */
+#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */
+#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums: host->device */
+#define BDC_FLAG_EVENT_MSG 0x08 /* Payload contains an event msg: device->host */
+#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
+#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
+
+/* priority field bitmap */
+#define BDC_PRIORITY_MASK 0x07
+#define BDC_PRIORITY_FC_MASK 0xf0 /* flow control info mask */
+#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */
+
+/* flags2 field bitmap */
+#define BDC_FLAG2_IF_MASK 0x0f /* interface index (host <-> dongle) */
+#define BDC_FLAG2_IF_SHIFT 0
+#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */
+ /* FLOW CONTROL info only */
+
+/* version numbers */
+#define BDC_PROTO_VER_1 1 /* Old Protocol version */
+#define BDC_PROTO_VER 2 /* Protocol version */
+
+/* flags2.if field access macros */
+#define BDC_GET_IF_IDX(hdr) \
+ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
+#define BDC_SET_IF_IDX(hdr, idx) \
+ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT)))
+
+#define BDC_FLAG2_PAD_MASK 0xf0
+#define BDC_FLAG_PAD_MASK 0x03
+#define BDC_FLAG2_PAD_SHIFT 2
+#define BDC_FLAG_PAD_SHIFT 0
+#define BDC_FLAG2_PAD_IDX 0x3c
+#define BDC_FLAG_PAD_IDX 0x03
+#define BDC_GET_PAD_LEN(hdr) \
+ ((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \
+ ((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT)))
+#define BDC_SET_PAD_LEN(hdr, idx) \
+ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \
+ (((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \
+ ((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \
+ (((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT)))
+
+#endif /* _bcmcdc_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmdefs.h b/drivers/net/wireless/bcmdhd/include/bcmdefs.h
new file mode 100644
index 000000000000..a53a793a0d0f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmdefs.h
@@ -0,0 +1,348 @@
+/*
+ * Misc system wide definitions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmdefs.h 433011 2013-10-30 09:19:54Z $
+ */
+
+#ifndef _bcmdefs_h_
+#define _bcmdefs_h_
+
+/*
+ * One doesn't need to include this file explicitly, gets included automatically if
+ * typedefs.h is included.
+ */
+
+/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function
+ * arguments or local variables.
+ */
+#define BCM_REFERENCE(data) ((void)(data))
+
+/* Allow for suppressing unused variable warnings. */
+#ifdef __GNUC__
+#define UNUSED_VAR __attribute__ ((unused))
+#else
+#define UNUSED_VAR
+#endif
+
+/* Compile-time assert can be used in place of ASSERT if the expression evaluates
+ * to a constant at compile time.
+ */
+#define STATIC_ASSERT(expr) { \
+ /* Make sure the expression is constant. */ \
+ typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e UNUSED_VAR; \
+ /* Make sure the expression is true. */ \
+ typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1] UNUSED_VAR; \
+}
+
+/* Reclaiming text and data :
+ * The following macros specify special linker sections that can be reclaimed
+ * after a system is considered 'up'.
+ * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN,
+ * as in most cases, the attach function calls the detach function to clean up on error).
+ */
+
+#define bcmreclaimed 0
+#define _data _data
+#define _fn _fn
+#define BCMPREATTACHDATA(_data) _data
+#define BCMPREATTACHFN(_fn) _fn
+#define _data _data
+#define _fn _fn
+#define _fn _fn
+#define BCMNMIATTACHFN(_fn) _fn
+#define BCMNMIATTACHDATA(_data) _data
+#define CONST const
+
+#undef BCM47XX_CA9
+
+#ifndef BCMFASTPATH
+#if defined(BCM47XX_CA9)
+#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath")))
+#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host")))
+#else
+#define BCMFASTPATH
+#define BCMFASTPATH_HOST
+#endif
+#endif /* BCMFASTPATH */
+
+
+/* Use the BCMRAMFN() macro to tag functions in source that must be included in RAM (excluded from
+ * ROM). This should eliminate the need to manually specify these functions in the ROM config file.
+ * It should only be used in special cases where the function must be in RAM for *all* ROM-based
+ * chips.
+ */
+ #define BCMRAMFN(_fn) _fn
+
+
+
+/* Put some library data/code into ROM to reduce RAM requirements */
+#define _data _data
+#define BCMROMDAT_NAME(_data) _data
+#define _fn _fn
+#define _fn _fn
+#define STATIC static
+#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data)
+#define BCMROMDAT_SIZEOF(data) sizeof(data)
+#define BCMROMDAT_APATCH(data)
+#define BCMROMDAT_SPATCH(data)
+
+/* Bus types */
+#define SI_BUS 0 /* SOC Interconnect */
+#define PCI_BUS 1 /* PCI target */
+#define PCMCIA_BUS 2 /* PCMCIA target */
+#define SDIO_BUS 3 /* SDIO target */
+#define JTAG_BUS 4 /* JTAG */
+#define USB_BUS 5 /* USB (does not support R/W REG) */
+#define SPI_BUS 6 /* gSPI target */
+#define RPC_BUS 7 /* RPC target */
+
+/* Allows size optimization for single-bus image */
+#ifdef BCMBUSTYPE
+#define BUSTYPE(bus) (BCMBUSTYPE)
+#else
+#define BUSTYPE(bus) (bus)
+#endif
+
+/* Allows size optimization for single-backplane image */
+#ifdef BCMCHIPTYPE
+#define CHIPTYPE(bus) (BCMCHIPTYPE)
+#else
+#define CHIPTYPE(bus) (bus)
+#endif
+
+
+/* Allows size optimization for SPROM support */
+#if defined(BCMSPROMBUS)
+#define SPROMBUS (BCMSPROMBUS)
+#elif defined(SI_PCMCIA_SROM)
+#define SPROMBUS (PCMCIA_BUS)
+#else
+#define SPROMBUS (PCI_BUS)
+#endif
+
+/* Allows size optimization for single-chip image */
+#ifdef BCMCHIPID
+#define CHIPID(chip) (BCMCHIPID)
+#else
+#define CHIPID(chip) (chip)
+#endif
+
+#ifdef BCMCHIPREV
+#define CHIPREV(rev) (BCMCHIPREV)
+#else
+#define CHIPREV(rev) (rev)
+#endif
+
+/* Defines for DMA Address Width - Shared between OSL and HNDDMA */
+#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */
+#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */
+#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */
+
+#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */
+#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */
+#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */
+#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */
+
+typedef struct {
+ uint32 loaddr;
+ uint32 hiaddr;
+} dma64addr_t;
+
+#define PHYSADDR64HI(_pa) ((_pa).hiaddr)
+#define PHYSADDR64HISET(_pa, _val) \
+ do { \
+ (_pa).hiaddr = (_val); \
+ } while (0)
+#define PHYSADDR64LO(_pa) ((_pa).loaddr)
+#define PHYSADDR64LOSET(_pa, _val) \
+ do { \
+ (_pa).loaddr = (_val); \
+ } while (0)
+
+#ifdef BCMDMA64OSL
+typedef dma64addr_t dmaaddr_t;
+#define PHYSADDRHI(_pa) PHYSADDR64HI(_pa)
+#define PHYSADDRHISET(_pa, _val) PHYSADDR64HISET(_pa, _val)
+#define PHYSADDRLO(_pa) PHYSADDR64LO(_pa)
+#define PHYSADDRLOSET(_pa, _val) PHYSADDR64LOSET(_pa, _val)
+
+#else
+typedef unsigned long dmaaddr_t;
+#define PHYSADDRHI(_pa) (0)
+#define PHYSADDRHISET(_pa, _val)
+#define PHYSADDRLO(_pa) ((_pa))
+#define PHYSADDRLOSET(_pa, _val) \
+ do { \
+ (_pa) = (_val); \
+ } while (0)
+#endif /* BCMDMA64OSL */
+
+/* One physical DMA segment */
+typedef struct {
+ dmaaddr_t addr;
+ uint32 length;
+} hnddma_seg_t;
+
+#define MAX_DMA_SEGS 8
+
+
+typedef struct {
+ void *oshdmah; /* Opaque handle for OSL to store its information */
+ uint origsize; /* Size of the virtual packet */
+ uint nsegs;
+ hnddma_seg_t segs[MAX_DMA_SEGS];
+} hnddma_seg_map_t;
+
+
+/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF).
+ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL.
+ * There is a compile time check in wlc.c which ensure that this value is at least as big
+ * as TXOFF. This value is used in dma_rxfill (hnddma.c).
+ */
+
+#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY)
+/* add 40 bytes to allow for extra RPC header and info */
+#define BCMEXTRAHDROOM 260
+#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */
+#if defined(BCM47XX_CA9)
+#define BCMEXTRAHDROOM 224
+#else
+#define BCMEXTRAHDROOM 204
+#endif /* linux && BCM47XX_CA9 */
+#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */
+
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#ifndef SDALIGN
+#define SDALIGN 32
+#endif
+
+/* Headroom required for dongle-to-host communication. Packets allocated
+ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should
+ * leave this much room in front for low-level message headers which may
+ * be needed to get across the dongle bus to the host. (These messages
+ * don't go over the network, so room for the full WL header above would
+ * be a waste.).
+*/
+#define BCMDONGLEHDRSZ 12
+#define BCMDONGLEPADSZ 16
+
+#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ)
+
+
+#if defined(NO_BCMDBG_ASSERT)
+# undef BCMDBG_ASSERT
+# undef BCMASSERT_LOG
+#endif
+
+#if defined(BCMASSERT_LOG)
+#define BCMASSERT_SUPPORT
+#endif
+
+/* Macros for doing definition and get/set of bitfields
+ * Usage example, e.g. a three-bit field (bits 4-6):
+ * #define <NAME>_M BITFIELD_MASK(3)
+ * #define <NAME>_S 4
+ * ...
+ * regval = R_REG(osh, &regs->regfoo);
+ * field = GFIELD(regval, <NAME>);
+ * regval = SFIELD(regval, <NAME>, 1);
+ * W_REG(osh, &regs->regfoo, regval);
+ */
+#define BITFIELD_MASK(width) \
+ (((unsigned)1 << (width)) - 1)
+#define GFIELD(val, field) \
+ (((val) >> field ## _S) & field ## _M)
+#define SFIELD(val, field, bits) \
+ (((val) & (~(field ## _M << field ## _S))) | \
+ ((unsigned)(bits) << field ## _S))
+
+/* define BCMSMALL to remove misc features for memory-constrained environments */
+#ifdef BCMSMALL
+#undef BCMSPACE
+#define bcmspace FALSE /* if (bcmspace) code is discarded */
+#else
+#define BCMSPACE
+#define bcmspace TRUE /* if (bcmspace) code is retained */
+#endif
+
+/* Max. nvram variable table size */
+#ifndef MAXSZ_NVRAM_VARS
+#define MAXSZ_NVRAM_VARS 4096
+#endif
+
+
+
+/* WL_ENAB_RUNTIME_CHECK may be set based upon the #define below (for ROM builds). It may also
+ * be defined via makefiles (e.g. ROM auto abandon unoptimized compiles).
+ */
+
+
+#ifdef BCMLFRAG /* BCMLFRAG support enab macros */
+ extern bool _bcmlfrag;
+ #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+ #define BCMLFRAG_ENAB() (_bcmlfrag)
+ #elif defined(BCMLFRAG_DISABLED)
+ #define BCMLFRAG_ENAB() (0)
+ #else
+ #define BCMLFRAG_ENAB() (1)
+ #endif
+#else
+ #define BCMLFRAG_ENAB() (0)
+#endif /* BCMLFRAG_ENAB */
+#ifdef BCMSPLITRX /* BCMLFRAG support enab macros */
+ extern bool _bcmsplitrx;
+ #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+ #define BCMSPLITRX_ENAB() (_bcmsplitrx)
+ #elif defined(BCMSPLITRX_DISABLED)
+ #define BCMSPLITRX_ENAB() (0)
+ #else
+ #define BCMSPLITRX_ENAB() (1)
+ #endif
+#else
+ #define BCMSPLITRX_ENAB() (0)
+#endif /* BCMSPLITRX */
+#ifdef BCM_SPLITBUF
+ extern bool _bcmsplitbuf;
+ #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+ #define BCM_SPLITBUF_ENAB() (_bcmsplitbuf)
+ #elif defined(BCM_SPLITBUF_DISABLED)
+ #define BCM_SPLITBUF_ENAB() (0)
+ #else
+ #define BCM_SPLITBUF_ENAB() (1)
+ #endif
+#else
+ #define BCM_SPLITBUF_ENAB() (0)
+#endif /* BCM_SPLITBUF */
+/* Max size for reclaimable NVRAM array */
+#ifdef DL_NVRAM
+#define NVRAM_ARRAY_MAXSIZE DL_NVRAM
+#else
+#define NVRAM_ARRAY_MAXSIZE MAXSZ_NVRAM_VARS
+#endif /* DL_NVRAM */
+
+#ifdef BCMUSBDEV_ENABLED
+extern uint32 gFWID;
+#endif
+
+
+#endif /* _bcmdefs_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h
new file mode 100644
index 000000000000..99958bf541d4
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmdevs.h
@@ -0,0 +1,688 @@
+/*
+ * Broadcom device-specific manifest constants.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmdevs.h 475454 2014-05-05 20:54:58Z $
+ */
+
+#ifndef _BCMDEVS_H
+#define _BCMDEVS_H
+
+/* PCI vendor IDs */
+#define VENDOR_EPIGRAM 0xfeda
+#define VENDOR_BROADCOM 0x14e4
+#define VENDOR_3COM 0x10b7
+#define VENDOR_NETGEAR 0x1385
+#define VENDOR_DIAMOND 0x1092
+#define VENDOR_INTEL 0x8086
+#define VENDOR_DELL 0x1028
+#define VENDOR_HP 0x103c
+#define VENDOR_HP_COMPAQ 0x0e11
+#define VENDOR_APPLE 0x106b
+#define VENDOR_SI_IMAGE 0x1095 /* Silicon Image, used by Arasan SDIO Host */
+#define VENDOR_BUFFALO 0x1154 /* Buffalo vendor id */
+#define VENDOR_TI 0x104c /* Texas Instruments */
+#define VENDOR_RICOH 0x1180 /* Ricoh */
+#define VENDOR_JMICRON 0x197b
+
+
+/* PCMCIA vendor IDs */
+#define VENDOR_BROADCOM_PCMCIA 0x02d0
+
+/* SDIO vendor IDs */
+#define VENDOR_BROADCOM_SDIO 0x00BF
+
+/* DONGLE VID/PIDs */
+#define BCM_DNGL_VID 0x0a5c
+#define BCM_DNGL_BL_PID_4328 0xbd12
+#define BCM_DNGL_BL_PID_4322 0xbd13
+#define BCM_DNGL_BL_PID_4319 0xbd16
+#define BCM_DNGL_BL_PID_43236 0xbd17
+#define BCM_DNGL_BL_PID_4332 0xbd18
+#define BCM_DNGL_BL_PID_4330 0xbd19
+#define BCM_DNGL_BL_PID_4334 0xbd1a
+#define BCM_DNGL_BL_PID_43239 0xbd1b
+#define BCM_DNGL_BL_PID_4324 0xbd1c
+#define BCM_DNGL_BL_PID_4360 0xbd1d
+#define BCM_DNGL_BL_PID_43143 0xbd1e
+#define BCM_DNGL_BL_PID_43242 0xbd1f
+#define BCM_DNGL_BL_PID_43342 0xbd21
+#define BCM_DNGL_BL_PID_4335 0xbd20
+#define BCM_DNGL_BL_PID_43341 0xbd22
+#define BCM_DNGL_BL_PID_4350 0xbd23
+#define BCM_DNGL_BL_PID_4345 0xbd24
+#define BCM_DNGL_BL_PID_4349 0xbd25
+#define BCM_DNGL_BL_PID_4354 0xbd26
+
+#define BCM_DNGL_BDC_PID 0x0bdc
+#define BCM_DNGL_JTAG_PID 0x4a44
+
+/* HW USB BLOCK [CPULESS USB] PIDs */
+#define BCM_HWUSB_PID_43239 43239
+
+/* PCI Device IDs */
+#define BCM4210_DEVICE_ID 0x1072 /* never used */
+#define BCM4230_DEVICE_ID 0x1086 /* never used */
+#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */
+#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */
+#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */
+#define BCM4211_DEVICE_ID 0x4211
+#define BCM4231_DEVICE_ID 0x4231
+#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */
+#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */
+#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */
+#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */
+#define BCM4328_D11DUAL_ID 0x4314 /* 4328/4312 802.11a/g id */
+#define BCM4328_D11G_ID 0x4315 /* 4328/4312 802.11g id */
+#define BCM4328_D11A_ID 0x4316 /* 4328/4312 802.11a id */
+#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */
+#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */
+#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */
+#define BCM4325_D11DUAL_ID 0x431b /* 4325 802.11a/g id */
+#define BCM4325_D11G_ID 0x431c /* 4325 802.11g id */
+#define BCM4325_D11A_ID 0x431d /* 4325 802.11a id */
+#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */
+#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */
+#define BCM4306_UART_ID 0x4322 /* 4306 uart */
+#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */
+#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */
+#define BCM4306_D11G_ID2 0x4325 /* BCM4306_D11G_ID; INF w/loose binding war */
+#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */
+#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Ghz band id */
+#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */
+#define BCM4322_D11N_ID 0x432b /* 4322 802.11n dualband device */
+#define BCM4322_D11N2G_ID 0x432c /* 4322 802.11n 2.4GHz device */
+#define BCM4322_D11N5G_ID 0x432d /* 4322 802.11n 5GHz device */
+#define BCM4329_D11N_ID 0x432e /* 4329 802.11n dualband device */
+#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */
+#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */
+#define BCM4315_D11DUAL_ID 0x4334 /* 4315 802.11a/g id */
+#define BCM4315_D11G_ID 0x4335 /* 4315 802.11g id */
+#define BCM4315_D11A_ID 0x4336 /* 4315 802.11a id */
+#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */
+#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */
+#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */
+#define BCM43231_D11N2G_ID 0x4340 /* 43231 802.11n 2.4GHz device */
+#define BCM43221_D11N2G_ID 0x4341 /* 43221 802.11n 2.4GHz device */
+#define BCM43222_D11N_ID 0x4350 /* 43222 802.11n dualband device */
+#define BCM43222_D11N2G_ID 0x4351 /* 43222 802.11n 2.4GHz device */
+#define BCM43222_D11N5G_ID 0x4352 /* 43222 802.11n 5GHz device */
+#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */
+#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db device */
+#define BCM43226_D11N_ID 0x4354 /* 43226 802.11n dualband device */
+#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */
+#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */
+#define BCM43236_D11N5G_ID 0x4348 /* 43236 802.11n 5GHz device */
+#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */
+#define BCM43421_D11N_ID 0xA99D /* 43421 802.11n dualband device */
+#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
+#define BCM4330_D11N_ID 0x4360 /* 4330 802.11n dualband device */
+#define BCM4330_D11N2G_ID 0x4361 /* 4330 802.11n 2.4G device */
+#define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */
+#define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */
+#define BCM6362_D11N_ID 0x435f /* 6362 802.11n dualband device */
+#define BCM6362_D11N2G_ID 0x433f /* 6362 802.11n 2.4Ghz band id */
+#define BCM6362_D11N5G_ID 0x434f /* 6362 802.11n 5Ghz band id */
+#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */
+#define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */
+#define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */
+#define BCM43237_D11N_ID 0x4355 /* 43237 802.11n dualband device */
+#define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */
+#define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */
+#define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */
+#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */
+#define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */
+#define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */
+#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */
+#define BCM43217_D11N2G_ID 0x43a9 /* 43217 802.11n 2.4GHz device */
+#define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */
+#define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */
+#define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */
+#define BCM43143_D11N2G_ID 0x4366 /* 43143 802.11n 2.4G device */
+#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */
+#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */
+#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */
+#define BCM43342_D11N_ID 0x4383 /* 43342 802.11n dualband device */
+#define BCM43342_D11N2G_ID 0x4384 /* 43342 802.11n 2.4G device */
+#define BCM43342_D11N5G_ID 0x4385 /* 43342 802.11n 5G device */
+#define BCM43341_D11N_ID 0x4386 /* 43341 802.11n dualband device */
+#define BCM43341_D11N2G_ID 0x4387 /* 43341 802.11n 2.4G device */
+#define BCM43341_D11N5G_ID 0x4388 /* 43341 802.11n 5G device */
+#define BCM4360_D11AC_ID 0x43a0
+#define BCM4360_D11AC2G_ID 0x43a1
+#define BCM4360_D11AC5G_ID 0x43a2
+#define BCM4345_D11AC_ID 0x43ab /* 4345 802.11ac dualband device */
+#define BCM4345_D11AC2G_ID 0x43ac /* 4345 802.11ac 2.4G device */
+#define BCM4345_D11AC5G_ID 0x43ad /* 4345 802.11ac 5G device */
+#define BCM4335_D11AC_ID 0x43ae
+#define BCM4335_D11AC2G_ID 0x43af
+#define BCM4335_D11AC5G_ID 0x43b0
+#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */
+#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */
+#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */
+#define BCM43602_D11AC_ID 0x43ba /* ac dualband PCI devid SPROM programmed */
+#define BCM43602_D11AC2G_ID 0x43bb /* 43602 802.11ac 2.4G device */
+#define BCM43602_D11AC5G_ID 0x43bc /* 43602 802.11ac 5G device */
+
+/* PCI Subsystem ID */
+#define BCM943228HMB_SSID_VEN1 0x0607
+#define BCM94313HMGBL_SSID_VEN1 0x0608
+#define BCM94313HMG_SSID_VEN1 0x0609
+#define BCM943142HM_SSID_VEN1 0x0611
+
+#define BCM43143_D11N2G_ID 0x4366 /* 43143 802.11n 2.4G device */
+
+#define BCM43242_D11N_ID 0x4367 /* 43242 802.11n dualband device */
+#define BCM43242_D11N2G_ID 0x4368 /* 43242 802.11n 2.4G device */
+#define BCM43242_D11N5G_ID 0x4369 /* 43242 802.11n 5G device */
+
+#define BCM4350_D11AC_ID 0x43a3
+#define BCM4350_D11AC2G_ID 0x43a4
+#define BCM4350_D11AC5G_ID 0x43a5
+
+#define BCM43556_D11AC_ID 0x43b7
+#define BCM43556_D11AC2G_ID 0x43b8
+#define BCM43556_D11AC5G_ID 0x43b9
+
+#define BCM43558_D11AC_ID 0x43c0
+#define BCM43558_D11AC2G_ID 0x43c1
+#define BCM43558_D11AC5G_ID 0x43c2
+
+#define BCM43566_D11AC_ID 0x43d3
+#define BCM43566_D11AC2G_ID 0x43d4
+#define BCM43566_D11AC5G_ID 0x43d5
+
+#define BCM43568_D11AC_ID 0x43d6
+#define BCM43568_D11AC2G_ID 0x43d7
+#define BCM43568_D11AC5G_ID 0x43d8
+
+#define BCM43569_D11AC_ID 0x43d9
+#define BCM43569_D11AC2G_ID 0x43da
+#define BCM43569_D11AC5G_ID 0x43db
+
+#define BCM4354_D11AC_ID 0x43df /* 4354 802.11ac dualband device */
+#define BCM4354_D11AC2G_ID 0x43e0 /* 4354 802.11ac 2.4G device */
+#define BCM4354_D11AC5G_ID 0x43e1 /* 4354 802.11ac 5G device */
+#define BCM43430_D11N2G_ID 0x43e2 /* 43430 802.11n 2.4G device */
+
+
+#define BCM43349_D11N_ID 0x43e6 /* 43349 802.11n dualband id */
+#define BCM43349_D11N2G_ID 0x43e7 /* 43349 802.11n 2.4Ghz band id */
+#define BCM43349_D11N5G_ID 0x43e8 /* 43349 802.11n 5Ghz band id */
+
+#define BCM4356_D11AC_ID 0x43ec /* 4356 802.11ac dualband device */
+#define BCM4356_D11AC2G_ID 0x43ed /* 4356 802.11ac 2.4G device */
+#define BCM4356_D11AC5G_ID 0x43ee /* 4356 802.11ac 5G device */
+
+#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */
+#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */
+#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */
+#define BCM_JTAGM_ID 0x43f1 /* BCM jtagm device id */
+#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */
+#define BCM_SDIOH_ID 0x43f3 /* BCM sdio host id */
+#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */
+#define SPIH_FPGA_ID 0x43f5 /* PCI SPI Host Controller FPGA */
+#define BCM_SPIH_ID 0x43f6 /* Synopsis SPI Host Controller */
+#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */
+#define BCM_JTAGM2_ID 0x43f9 /* BCM alternate jtagm device id */
+#define SDHCI_FPGA_ID 0x43fa /* Standard SDIO Host Controller FPGA */
+#define BCM4402_ENET_ID 0x4402 /* 4402 enet */
+#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */
+#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */
+#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */
+#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */
+#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */
+#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */
+#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */
+#define BCM47XX_AUDIO_ID 0x4711 /* 47xx audio codec */
+#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */
+#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */
+#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */
+#define BCM47XX_GMAC_ID 0x4715 /* 47xx Unimac based GbE */
+#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */
+#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */
+#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */
+#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */
+#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */
+#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */
+#define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */
+#define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */
+#define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */
+#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */
+#define BCM4716_DEVICE_ID 0x4722 /* 4716 base devid */
+#define BCM47XX_USB30H_ID 0x472a /* 47xx usb 3.0 host */
+#define BCM47XX_USB30D_ID 0x472b /* 47xx usb 3.0 device */
+#define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */
+#define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */
+#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */
+#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */
+#define JINVANI_SDIOH_ID 0x4743 /* Jinvani SDIO Gold Host */
+#define BCM27XX_SDIOH_ID 0x2702 /* BCM27xx Standard SDIO Host */
+#define PCIXX21_FLASHMEDIA_ID 0x803b /* TI PCI xx21 Standard Host Controller */
+#define PCIXX21_SDIOH_ID 0x803c /* TI PCI xx21 Standard Host Controller */
+#define R5C822_SDIOH_ID 0x0822 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */
+#define JMICRON_SDIOH_ID 0x2381 /* JMicron Standard SDIO Host Controller */
+
+/* Chip IDs */
+#define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */
+#define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */
+#define BCM43111_CHIP_ID 43111 /* 43111 chipcommon chipid (OTP chipid) */
+#define BCM43112_CHIP_ID 43112 /* 43112 chipcommon chipid (OTP chipid) */
+#define BCM4312_CHIP_ID 0x4312 /* 4312 chipcommon chipid */
+#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */
+#define BCM43131_CHIP_ID 43131 /* 43131 chip id (OTP chipid) */
+#define BCM4315_CHIP_ID 0x4315 /* 4315 chip id */
+#define BCM4318_CHIP_ID 0x4318 /* 4318 chipcommon chipid */
+#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */
+#define BCM4320_CHIP_ID 0x4320 /* 4320 chipcommon chipid */
+#define BCM4321_CHIP_ID 0x4321 /* 4321 chipcommon chipid */
+#define BCM43217_CHIP_ID 43217 /* 43217 chip id (OTP chipid) */
+#define BCM4322_CHIP_ID 0x4322 /* 4322 chipcommon chipid */
+#define BCM43221_CHIP_ID 43221 /* 43221 chipcommon chipid (OTP chipid) */
+#define BCM43222_CHIP_ID 43222 /* 43222 chipcommon chipid */
+#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */
+#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */
+#define BCM43227_CHIP_ID 43227 /* 43227 chipcommon chipid */
+#define BCM43228_CHIP_ID 43228 /* 43228 chipcommon chipid */
+#define BCM43226_CHIP_ID 43226 /* 43226 chipcommon chipid */
+#define BCM43231_CHIP_ID 43231 /* 43231 chipcommon chipid (OTP chipid) */
+#define BCM43234_CHIP_ID 43234 /* 43234 chipcommon chipid */
+#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */
+#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */
+#define BCM43237_CHIP_ID 43237 /* 43237 chipcommon chipid */
+#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */
+#define BCM43239_CHIP_ID 43239 /* 43239 chipcommon chipid */
+#define BCM43420_CHIP_ID 43420 /* 43222 chipcommon chipid (OTP, RBBU) */
+#define BCM43421_CHIP_ID 43421 /* 43224 chipcommon chipid (OTP, RBBU) */
+#define BCM43428_CHIP_ID 43428 /* 43228 chipcommon chipid (OTP, RBBU) */
+#define BCM43431_CHIP_ID 43431 /* 4331 chipcommon chipid (OTP, RBBU) */
+#define BCM43460_CHIP_ID 43460 /* 4360 chipcommon chipid (OTP, RBBU) */
+#define BCM4325_CHIP_ID 0x4325 /* 4325 chip id */
+#define BCM4328_CHIP_ID 0x4328 /* 4328 chip id */
+#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */
+#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */
+#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */
+#define BCM43362_CHIP_ID 43362 /* 43362 chipcommon chipid */
+#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */
+#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */
+#define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */
+#define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */
+#define BCM43143_CHIP_ID 43143 /* 43143 chipcommon chipid */
+#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */
+#define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */
+#define BCM43243_CHIP_ID 43243 /* 43243 chipcommon chipid */
+#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */
+#define BCM4335_CHIP_ID 0x4335 /* 4335 chipcommon chipid */
+#define BCM4339_CHIP_ID 0x4339 /* 4339 chipcommon chipid */
+#define BCM43349_CHIP_ID 43349 /* 43349(0xA955) chipcommon chipid */
+#define BCM4360_CHIP_ID 0x4360 /* 4360 chipcommon chipid */
+#define BCM4352_CHIP_ID 0x4352 /* 4352 chipcommon chipid */
+#define BCM43526_CHIP_ID 0xAA06
+#define BCM43340_CHIP_ID 43340 /* 43340 chipcommon chipid */
+#define BCM43341_CHIP_ID 43341 /* 43341 chipcommon chipid */
+#define BCM43342_CHIP_ID 43342 /* 43342 chipcommon chipid */
+#define BCM4350_CHIP_ID 0x4350 /* 4350 chipcommon chipid */
+#define BCM4354_CHIP_ID 0x4354 /* 4354 chipcommon chipid */
+#define BCM4356_CHIP_ID 0x4356 /* 4356 chipcommon chipid */
+#define BCM43556_CHIP_ID 0xAA24 /* 43556 chipcommon chipid */
+#define BCM43558_CHIP_ID 0xAA26 /* 43558 chipcommon chipid */
+#define BCM43566_CHIP_ID 0xAA2E /* 43566 chipcommon chipid */
+#define BCM43568_CHIP_ID 0xAA30 /* 43568 chipcommon chipid */
+#define BCM43569_CHIP_ID 0xAA31 /* 43569 chipcommon chipid */
+#define BCM4350_CHIP(chipid) ((CHIPID(chipid) == BCM4350_CHIP_ID) || \
+ (CHIPID(chipid) == BCM4354_CHIP_ID) || \
+ (CHIPID(chipid) == BCM4356_CHIP_ID) || \
+ (CHIPID(chipid) == BCM43556_CHIP_ID) || \
+ (CHIPID(chipid) == BCM43558_CHIP_ID) || \
+ (CHIPID(chipid) == BCM43566_CHIP_ID) || \
+ (CHIPID(chipid) == BCM43568_CHIP_ID) || \
+ (CHIPID(chipid) == BCM43569_CHIP_ID)) /* 4350 variations */
+#define BCM4345_CHIP_ID 0x4345 /* 4345 chipcommon chipid */
+#define BCM43430_CHIP_ID 43430 /* 43430 chipcommon chipid */
+
+#define BCM43602_CHIP_ID 0xaa52 /* 43602 chipcommon chipid */
+
+#define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */
+#define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */
+#define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */
+#define BCM4706_CHIP_ID 0x5300 /* 4706 chipcommon chipid */
+#define BCM4707_CHIP_ID 53010 /* 4707 chipcommon chipid */
+#define BCM53018_CHIP_ID 53018 /* 53018 chipcommon chipid */
+#define BCM4707_CHIP(chipid) (((chipid) == BCM4707_CHIP_ID) || ((chipid) == BCM53018_CHIP_ID))
+#define BCM4710_CHIP_ID 0x4710 /* 4710 chipid */
+#define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */
+#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */
+#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */
+#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */
+#define BCM4749_CHIP_ID 0x4749 /* 5357 chipcommon chipid (OTP, RBBU) */
+#define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */
+#define BCM5350_CHIP_ID 0x5350 /* 5350 chipcommon chipid */
+#define BCM5352_CHIP_ID 0x5352 /* 5352 chipcommon chipid */
+#define BCM5354_CHIP_ID 0x5354 /* 5354 chipcommon chipid */
+#define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */
+#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */
+#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */
+#define BCM53572_CHIP_ID 53572 /* 53572 chipcommon chipid */
+
+/* Package IDs */
+#define BCM4303_PKG_ID 2 /* 4303 package id */
+#define BCM4309_PKG_ID 1 /* 4309 package id */
+#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */
+#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */
+#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */
+#define BCM4328USBD11G_PKG_ID 2 /* 4328 802.11g USB package id */
+#define BCM4328USBDUAL_PKG_ID 3 /* 4328 802.11a/g USB package id */
+#define BCM4328SDIOD11G_PKG_ID 4 /* 4328 802.11g SDIO package id */
+#define BCM4328SDIODUAL_PKG_ID 5 /* 4328 802.11a/g SDIO package id */
+#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */
+#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */
+#define BCM5354E_PKG_ID 1 /* 5354E package id */
+#define BCM4716_PKG_ID 8 /* 4716 package id */
+#define BCM4717_PKG_ID 9 /* 4717 package id */
+#define BCM4718_PKG_ID 10 /* 4718 package id */
+#define BCM5356_PKG_NONMODE 1 /* 5356 package without nmode suppport */
+#define BCM5358U_PKG_ID 8 /* 5358U package id */
+#define BCM5358_PKG_ID 9 /* 5358 package id */
+#define BCM47186_PKG_ID 10 /* 47186 package id */
+#define BCM5357_PKG_ID 11 /* 5357 package id */
+#define BCM5356U_PKG_ID 12 /* 5356U package id */
+#define BCM53572_PKG_ID 8 /* 53572 package id */
+#define BCM5357C0_PKG_ID 8 /* 5357c0 package id (the same as 53572) */
+#define BCM47188_PKG_ID 9 /* 47188 package id */
+#define BCM5358C0_PKG_ID 0xa /* 5358c0 package id */
+#define BCM5356C0_PKG_ID 0xb /* 5356c0 package id */
+#define BCM4331TT_PKG_ID 8 /* 4331 12x12 package id */
+#define BCM4331TN_PKG_ID 9 /* 4331 12x9 package id */
+#define BCM4331TNA0_PKG_ID 0xb /* 4331 12x9 package id */
+#define BCM4706L_PKG_ID 1 /* 4706L package id */
+
+#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */
+#define HDLSIM_PKG_ID 14 /* HDL simulator package id */
+#define HWSIM_PKG_ID 15 /* Hardware simulator package id */
+#define BCM43224_FAB_CSM 0x8 /* the chip is manufactured by CSM */
+#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */
+#define BCM4336_WLBGA_PKG_ID 0x8
+#define BCM4330_WLBGA_PKG_ID 0x0
+#define BCM4314PCIE_ARM_PKG_ID (8 | 0) /* 4314 QFN PCI package id, bit 3 tie high */
+#define BCM4314SDIO_PKG_ID (8 | 1) /* 4314 QFN SDIO package id */
+#define BCM4314PCIE_PKG_ID (8 | 2) /* 4314 QFN PCI (ARM-less) package id */
+#define BCM4314SDIO_ARM_PKG_ID (8 | 3) /* 4314 QFN SDIO (ARM-less) package id */
+#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) /* 4314 FpBGA SDIO package id */
+#define BCM4314DEV_PKG_ID (8 | 6) /* 4314 Developement package id */
+
+#define BCM4707_PKG_ID 1 /* 4707 package id */
+#define BCM4708_PKG_ID 2 /* 4708 package id */
+#define BCM4709_PKG_ID 0 /* 4709 package id */
+
+#define PCIXX21_FLASHMEDIA0_ID 0x8033 /* TI PCI xx21 Standard Host Controller */
+#define PCIXX21_SDIOH0_ID 0x8034 /* TI PCI xx21 Standard Host Controller */
+
+#define BCM4335_WLCSP_PKG_ID (0x0) /* WLCSP Module/Mobile SDIO/HSIC. */
+#define BCM4335_FCBGA_PKG_ID (0x1) /* FCBGA PC/Embeded/Media PCIE/SDIO */
+#define BCM4335_WLBGA_PKG_ID (0x2) /* WLBGA COB/Mobile SDIO/HSIC. */
+#define BCM4335_FCBGAD_PKG_ID (0x3) /* FCBGA Debug Debug/Dev All if's. */
+#define BCM4335_PKG_MASK (0x3)
+
+/* boardflags */
+#define BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */
+#define BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */
+#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */
+#define BFL_AIRLINEMODE 0x00000004 /* Board implements gpio 13 radio disable indication, UNUSED */
+#define BFL_ADCDIV 0x00000008 /* Board has the rssi ADC divider */
+#define BFL_DIS_256QAM 0x00000008
+#define BFL_ENETROBO 0x00000010 /* Board has robo switch or core */
+#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */
+#define BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */
+#define BFL_ENETADM 0x00000080 /* Board has ADMtek switch */
+#define BFL_ENETVLAN 0x00000100 /* Board has VLAN capability */
+#define BFL_UNUSED 0x00000200
+#define BFL_NOPCI 0x00000400 /* Board leaves PCI floating */
+#define BFL_FEM 0x00000800 /* Board supports the Front End Module */
+#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */
+#define BFL_HGPA 0x00002000 /* Board has a high gain PA */
+#define BFL_BTC2WIRE_ALTGPIO 0x00004000 /* Board's BTC 2wire is in the alternate gpios */
+#define BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */
+#define BFL_NOPA 0x00010000 /* Board has no PA */
+#define BFL_RSSIINV 0x00020000 /* Board's RSSI uses positive slope(not TSSI) */
+#define BFL_PAREF 0x00040000 /* Board uses the PARef LDO */
+#define BFL_3TSWITCH 0x00080000 /* Board uses a triple throw switch shared with BT */
+#define BFL_PHASESHIFT 0x00100000 /* Board can support phase shifter */
+#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */
+#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */
+#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */
+#define BFL_CCKFAVOREVM 0x01000000 /* Favor CCK EVM over spectral mask */
+#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */
+#define BFL_LNLDO2_2P5 0x04000000 /* Select 2.5V as LNLDO2 output voltage */
+#define BFL_FASTPWR 0x08000000
+#define BFL_UCPWRCTL_MININDX 0x08000000 /* Enforce min power index to avoid FEM damage */
+#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */
+#define BFL_TRSW_1by2 0x20000000 /* Board has 2 TRSW's in 1by2 designs */
+#define BFL_GAINBOOSTA01 0x20000000 /* 5g Gainboost for core0 and core1 */
+#define BFL_LO_TRSW_R_5GHz 0x40000000 /* In 5G do not throw TRSW to T for clipLO gain */
+#define BFL_ELNA_GAINDEF 0x80000000 /* Backoff InitGain based on elna_2g/5g field
+ * when this flag is set
+ */
+#define BFL_EXTLNA_TX 0x20000000 /* Temp boardflag to indicate to */
+
+/* boardflags2 */
+#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */
+#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */
+#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */
+#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */
+#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */
+#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */
+#define BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */
+#define BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */
+#define BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace
+ * BFL2_BTC3WIRE
+ */
+#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */
+#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */
+#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */
+#define BFL2_TRISTATE_LED 0x00000800 /* Tri-state the LED */
+#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */
+#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */
+#define BFL2_BPHY_ALL_TXCORES 0x00004000 /* Transmit bphy frames using all tx cores */
+#define BFL2_FCC_BANDEDGE_WAR 0x00008000 /* Activates WAR to improve FCC bandedge performance */
+#define BFL2_DAC_SPUR_IMPROVEMENT 0x00008000 /* Reducing DAC Spurs */
+#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */
+#define BFL2_IPALVLSHIFT_3P3 0x00020000
+#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */
+#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio on */
+ /* Most drivers will turn it off without this flag */
+ /* to save power. */
+
+#define BFL2_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are controlled by analog PA ctrl lines */
+#define BFL2_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are controlled by analog PA ctrl lines */
+#define BFL2_ELNACTRL_TRSW_2G 0x00400000 /* AZW4329: 2G gmode_elna_gain controls TR Switch */
+#define BFL2_BT_SHARE_ANT0 0x00800000 /* share core0 antenna with BT */
+#define BFL2_TEMPSENSE_HIGHER 0x01000000 /* The tempsense threshold can sustain higher value
+ * than programmed. The exact delta is decided by
+ * driver per chip/boardtype. This can be used
+ * when tempsense qualification happens after shipment
+ */
+#define BFL2_BTC3WIREONLY 0x02000000 /* standard 3 wire btc only. 4 wire not supported */
+#define BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */
+#define BFL2_EXTLNA_PWRSAVE 0x08000000 /* boardflag to enable ucode to apply power save */
+ /* ucode control of eLNA during Tx */
+#define BFL2_4313_RADIOREG 0x10000000
+ /* board rework */
+#define BFL2_DYNAMIC_VMID 0x10000000 /* enable dynamic Vmid in idle TSSI CAL for 4331 */
+
+#define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */
+#define BFL2_DYNAMIC_VMID 0x10000000 /* boardflag to enable dynamic Vmid idle TSSI CAL */
+#define BFL2_LNA1BYPFORTR2G 0x40000000 /* acphy, enable lna1 bypass for clip gain, 2g */
+#define BFL2_LNA1BYPFORTR5G 0x80000000 /* acphy, enable lna1 bypass for clip gain, 5g */
+
+/* SROM 11 - 11ac boardflag definitions */
+#define BFL_SROM11_BTCOEX 0x00000001 /* Board supports BTCOEX */
+#define BFL_SROM11_WLAN_BT_SH_XTL 0x00000002 /* bluetooth and wlan share same crystal */
+#define BFL_SROM11_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */
+#define BFL_SROM11_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */
+#define BFL_SROM11_GAINBOOSTA01 0x20000000 /* 5g Gainboost for core0 and core1 */
+#define BFL2_SROM11_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */
+#define BFL2_SROM11_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are ctrl-ed by analog PA ctrl lines */
+#define BFL2_SROM11_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are ctrl-ed by analog PA ctrl lines */
+#define BFL2_SROM11_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */
+
+/* boardflags3 */
+#define BFL3_FEMCTRL_SUB 0x00000007 /* acphy, subrevs of femctrl on top of srom_femctrl */
+#define BFL3_RCAL_WAR 0x00000008 /* acphy, rcal war active on this board (4335a0) */
+#define BFL3_TXGAINTBLID 0x00000070 /* acphy, txgain table id */
+#define BFL3_TXGAINTBLID_SHIFT 0x4 /* acphy, txgain table id shift bit */
+#define BFL3_TSSI_DIV_WAR 0x00000080 /* acphy, Seperate paparam for 20/40/80 */
+#define BFL3_TSSI_DIV_WAR_SHIFT 0x7 /* acphy, Seperate paparam for 20/40/80 shift bit */
+#define BFL3_FEMTBL_FROM_NVRAM 0x00000100 /* acphy, femctrl table is read from nvram */
+#define BFL3_FEMTBL_FROM_NVRAM_SHIFT 0x8 /* acphy, femctrl table is read from nvram */
+#define BFL3_AGC_CFG_2G 0x00000200 /* acphy, gain control configuration for 2G */
+#define BFL3_AGC_CFG_5G 0x00000400 /* acphy, gain control configuration for 5G */
+#define BFL3_PPR_BIT_EXT 0x00000800 /* acphy, bit position for 1bit extension for ppr */
+#define BFL3_PPR_BIT_EXT_SHIFT 11 /* acphy, bit shift for 1bit extension for ppr */
+#define BFL3_BBPLL_SPR_MODE_DIS 0x00001000 /* acphy, disables bbpll spur modes */
+#define BFL3_RCAL_OTP_VAL_EN 0x00002000 /* acphy, to read rcal_trim value from otp */
+#define BFL3_2GTXGAINTBL_BLANK 0x00004000 /* acphy, blank the first X ticks of 2g gaintbl */
+#define BFL3_2GTXGAINTBL_BLANK_SHIFT 14 /* acphy, blank the first X ticks of 2g gaintbl */
+#define BFL3_5GTXGAINTBL_BLANK 0x00008000 /* acphy, blank the first X ticks of 5g gaintbl */
+#define BFL3_5GTXGAINTBL_BLANK_SHIFT 15 /* acphy, blank the first X ticks of 5g gaintbl */
+#define BFL3_PHASETRACK_MAX_ALPHABETA 0x00010000 /* acphy, to max out alpha,beta to 511 */
+#define BFL3_PHASETRACK_MAX_ALPHABETA_SHIFT 16 /* acphy, to max out alpha,beta to 511 */
+/* acphy, to use backed off gaintbl for lte-coex */
+#define BFL3_LTECOEX_GAINTBL_EN 0x00060000
+/* acphy, to use backed off gaintbl for lte-coex */
+#define BFL3_LTECOEX_GAINTBL_EN_SHIFT 17
+#define BFL3_5G_SPUR_WAR 0x00080000 /* acphy, enable spur WAR in 5G band */
+
+/* acphy: lpmode2g and lpmode_5g related boardflags */
+#define BFL3_ACPHY_LPMODE_2G 0x00300000 /* bits 20:21 for lpmode_2g choice */
+#define BFL3_ACPHY_LPMODE_2G_SHIFT 20
+
+#define BFL3_ACPHY_LPMODE_5G 0x00C00000 /* bits 22:23 for lpmode_5g choice */
+#define BFL3_ACPHY_LPMODE_5G_SHIFT 22
+
+#define BFL3_EXT_LPO_ISCLOCK 0x02000000 /* External LPO is clock, not x-tal */
+#define BFL3_FORCE_INT_LPO_SEL 0x04000000 /* Force internal lpo */
+#define BFL3_FORCE_EXT_LPO_SEL 0x08000000 /* Force external lpo */
+
+#define BFL3_EN_BRCM_IMPBF 0x10000000 /* acphy, Allow BRCM Implicit TxBF */
+#define BFL3_AVVMID_FROM_NVRAM 0x40000000 /* Read Av Vmid from NVRAM */
+#define BFL3_VLIN_EN_FROM_NVRAM 0x80000000 /* Read Vlin En from NVRAM */
+
+#define BFL3_AVVMID_FROM_NVRAM_SHIFT 30 /* Read Av Vmid from NVRAM */
+#define BFL3_VLIN_EN_FROM_NVRAM_SHIFT 31 /* Enable Vlin from NVRAM */
+
+
+/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
+#define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */
+#define BOARD_GPIO_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */
+#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistence Input */
+#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistence Out */
+#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistence Input */
+#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistence Out */
+#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */
+#define BOARD_GPIO_12 0x1000 /* gpio 12 */
+#define BOARD_GPIO_13 0x2000 /* gpio 13 */
+#define BOARD_GPIO_BTC4_IN 0x0800 /* gpio 11, coex4, in */
+#define BOARD_GPIO_BTC4_BT 0x2000 /* gpio 12, coex4, bt active */
+#define BOARD_GPIO_BTC4_STAT 0x4000 /* gpio 14, coex4, status */
+#define BOARD_GPIO_BTC4_WLAN 0x8000 /* gpio 15, coex4, wlan active */
+#define BOARD_GPIO_1_WLAN_PWR 0x02 /* throttle WLAN power on X21 board */
+#define BOARD_GPIO_2_WLAN_PWR 0x04 /* throttle WLAN power on X29C board */
+#define BOARD_GPIO_3_WLAN_PWR 0x08 /* throttle WLAN power on X28 board */
+#define BOARD_GPIO_4_WLAN_PWR 0x10 /* throttle WLAN power on X19 board */
+
+#define GPIO_BTC4W_OUT_4312 0x010 /* bit 4 is BT_IODISABLE */
+#define GPIO_BTC4W_OUT_43224 0x020 /* bit 5 is BT_IODISABLE */
+#define GPIO_BTC4W_OUT_43224_SHARED 0x0e0 /* bit 5 is BT_IODISABLE */
+#define GPIO_BTC4W_OUT_43225 0x0e0 /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */
+#define GPIO_BTC4W_OUT_43421 0x020 /* bit 5 is BT_IODISABLE */
+#define GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */
+#define GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */
+
+#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */
+#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */
+#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */
+#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */
+
+/* power control defines */
+#define PLL_DELAY 150 /* us pll on delay */
+#define FREF_DELAY 200 /* us fref change delay */
+#define MIN_SLOW_CLK 32 /* us Slow clock period */
+#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */
+
+
+/* 43341 Boards */
+#define BCM943341WLABGS_SSID 0x062d
+
+/* 43342 Boards */
+#define BCM943342FCAGBI_SSID 0x0641
+
+/* 43602 Boards, unclear yet what boards will be created. */
+#define BCM943602RSVD1_SSID 0x06a5
+#define BCM943602RSVD2_SSID 0x06a6
+
+/* # of GPIO pins */
+#define GPIO_NUMPINS 32
+
+/* These values are used by dhd host driver. */
+#define RDL_RAM_BASE_4319 0x60000000
+#define RDL_RAM_BASE_4329 0x60000000
+#define RDL_RAM_SIZE_4319 0x48000
+#define RDL_RAM_SIZE_4329 0x48000
+#define RDL_RAM_SIZE_43236 0x70000
+#define RDL_RAM_BASE_43236 0x60000000
+#define RDL_RAM_SIZE_4328 0x60000
+#define RDL_RAM_BASE_4328 0x80000000
+#define RDL_RAM_SIZE_4322 0x60000
+#define RDL_RAM_BASE_4322 0x60000000
+#define RDL_RAM_SIZE_4360 0xA0000
+#define RDL_RAM_BASE_4360 0x60000000
+#define RDL_RAM_SIZE_43242 0x90000
+#define RDL_RAM_BASE_43242 0x60000000
+#define RDL_RAM_SIZE_43143 0x70000
+#define RDL_RAM_BASE_43143 0x60000000
+#define RDL_RAM_SIZE_4350 0xC0000
+#define RDL_RAM_BASE_4350 0x180800
+
+/* generic defs for nvram "muxenab" bits
+* Note: these differ for 4335a0. refer bcmchipc.h for specific mux options.
+*/
+#define MUXENAB_UART 0x00000001
+#define MUXENAB_GPIO 0x00000002
+#define MUXENAB_ERCX 0x00000004 /* External Radio BT coex */
+#define MUXENAB_JTAG 0x00000008
+#define MUXENAB_HOST_WAKE 0x00000010 /* configure GPIO for SDIO host_wake */
+#define MUXENAB_I2S_EN 0x00000020
+#define MUXENAB_I2S_MASTER 0x00000040
+#define MUXENAB_I2S_FULL 0x00000080
+#define MUXENAB_SFLASH 0x00000100
+#define MUXENAB_RFSWCTRL0 0x00000200
+#define MUXENAB_RFSWCTRL1 0x00000400
+#define MUXENAB_RFSWCTRL2 0x00000800
+#define MUXENAB_SECI 0x00001000
+#define MUXENAB_BT_LEGACY 0x00002000
+#define MUXENAB_HOST_WAKE1 0x00004000 /* configure alternative GPIO for SDIO host_wake */
+
+/* Boot flags */
+#define FLASH_KERNEL_NFLASH 0x00000001
+#define FLASH_BOOT_NFLASH 0x00000002
+
+#endif /* _BCMDEVS_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmendian.h b/drivers/net/wireless/bcmdhd/include/bcmendian.h
new file mode 100644
index 000000000000..48b6e669949e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmendian.h
@@ -0,0 +1,329 @@
+/*
+ * Byte order utilities
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmendian.h 402715 2013-05-16 18:50:09Z $
+ *
+ * This file by default provides proper behavior on little-endian architectures.
+ * On big-endian architectures, IL_BIGENDIAN should be defined.
+ */
+
+#ifndef _BCMENDIAN_H_
+#define _BCMENDIAN_H_
+
+#include <typedefs.h>
+
+/* Reverse the bytes in a 16-bit value */
+#define BCMSWAP16(val) \
+ ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \
+ (((uint16)(val) & (uint16)0xff00U) >> 8)))
+
+/* Reverse the bytes in a 32-bit value */
+#define BCMSWAP32(val) \
+ ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \
+ (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \
+ (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \
+ (((uint32)(val) & (uint32)0xff000000U) >> 24)))
+
+/* Reverse the two 16-bit halves of a 32-bit value */
+#define BCMSWAP32BY16(val) \
+ ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \
+ (((uint32)(val) & (uint32)0xffff0000U) >> 16)))
+
+/* Reverse the bytes in a 64-bit value */
+#define BCMSWAP64(val) \
+ ((uint64)((((uint64)(val) & 0x00000000000000ffULL) << 56) | \
+ (((uint64)(val) & 0x000000000000ff00ULL) << 40) | \
+ (((uint64)(val) & 0x0000000000ff0000ULL) << 24) | \
+ (((uint64)(val) & 0x00000000ff000000ULL) << 8) | \
+ (((uint64)(val) & 0x000000ff00000000ULL) >> 8) | \
+ (((uint64)(val) & 0x0000ff0000000000ULL) >> 24) | \
+ (((uint64)(val) & 0x00ff000000000000ULL) >> 40) | \
+ (((uint64)(val) & 0xff00000000000000ULL) >> 56)))
+
+/* Reverse the two 32-bit halves of a 64-bit value */
+#define BCMSWAP64BY32(val) \
+ ((uint64)((((uint64)(val) & 0x00000000ffffffffULL) << 32) | \
+ (((uint64)(val) & 0xffffffff00000000ULL) >> 32)))
+
+
+/* Byte swapping macros
+ * Host <=> Network (Big Endian) for 16- and 32-bit values
+ * Host <=> Little-Endian for 16- and 32-bit values
+ */
+#ifndef hton16
+#define HTON16(i) BCMSWAP16(i)
+#define hton16(i) bcmswap16(i)
+#define HTON32(i) BCMSWAP32(i)
+#define hton32(i) bcmswap32(i)
+#define NTOH16(i) BCMSWAP16(i)
+#define ntoh16(i) bcmswap16(i)
+#define NTOH32(i) BCMSWAP32(i)
+#define ntoh32(i) bcmswap32(i)
+#define LTOH16(i) (i)
+#define ltoh16(i) (i)
+#define LTOH32(i) (i)
+#define ltoh32(i) (i)
+#define HTOL16(i) (i)
+#define htol16(i) (i)
+#define HTOL32(i) (i)
+#define htol32(i) (i)
+#define HTOL64(i) (i)
+#define htol64(i) (i)
+#endif /* hton16 */
+
+#define ltoh16_buf(buf, i)
+#define htol16_buf(buf, i)
+
+/* Unaligned loads and stores in host byte order */
+#define load32_ua(a) ltoh32_ua(a)
+#define store32_ua(a, v) htol32_ua_store(v, a)
+#define load16_ua(a) ltoh16_ua(a)
+#define store16_ua(a, v) htol16_ua_store(v, a)
+
+#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8))
+#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24))
+#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1])
+#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3])
+
+#define ltoh_ua(ptr) \
+ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
+ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \
+ sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \
+ *(uint8 *)0)
+
+#define ntoh_ua(ptr) \
+ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
+ sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \
+ sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \
+ *(uint8 *)0)
+
+#ifdef __GNUC__
+
+/* GNU macro versions avoid referencing the argument multiple times, while also
+ * avoiding the -fno-inline used in ROM builds.
+ */
+
+#define bcmswap16(val) ({ \
+ uint16 _val = (val); \
+ BCMSWAP16(_val); \
+})
+
+#define bcmswap32(val) ({ \
+ uint32 _val = (val); \
+ BCMSWAP32(_val); \
+})
+
+#define bcmswap64(val) ({ \
+ uint64 _val = (val); \
+ BCMSWAP64(_val); \
+})
+
+#define bcmswap32by16(val) ({ \
+ uint32 _val = (val); \
+ BCMSWAP32BY16(_val); \
+})
+
+#define bcmswap16_buf(buf, len) ({ \
+ uint16 *_buf = (uint16 *)(buf); \
+ uint _wds = (len) / 2; \
+ while (_wds--) { \
+ *_buf = bcmswap16(*_buf); \
+ _buf++; \
+ } \
+})
+
+#define htol16_ua_store(val, bytes) ({ \
+ uint16 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val & 0xff; \
+ _bytes[1] = _val >> 8; \
+})
+
+#define htol32_ua_store(val, bytes) ({ \
+ uint32 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val & 0xff; \
+ _bytes[1] = (_val >> 8) & 0xff; \
+ _bytes[2] = (_val >> 16) & 0xff; \
+ _bytes[3] = _val >> 24; \
+})
+
+#define hton16_ua_store(val, bytes) ({ \
+ uint16 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val >> 8; \
+ _bytes[1] = _val & 0xff; \
+})
+
+#define hton32_ua_store(val, bytes) ({ \
+ uint32 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val >> 24; \
+ _bytes[1] = (_val >> 16) & 0xff; \
+ _bytes[2] = (_val >> 8) & 0xff; \
+ _bytes[3] = _val & 0xff; \
+})
+
+#define ltoh16_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _LTOH16_UA(_bytes); \
+})
+
+#define ltoh32_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _LTOH32_UA(_bytes); \
+})
+
+#define ntoh16_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _NTOH16_UA(_bytes); \
+})
+
+#define ntoh32_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _NTOH32_UA(_bytes); \
+})
+
+#else /* !__GNUC__ */
+
+/* Inline versions avoid referencing the argument multiple times */
+static INLINE uint16
+bcmswap16(uint16 val)
+{
+ return BCMSWAP16(val);
+}
+
+static INLINE uint32
+bcmswap32(uint32 val)
+{
+ return BCMSWAP32(val);
+}
+
+static INLINE uint64
+bcmswap64(uint64 val)
+{
+ return BCMSWAP64(val);
+}
+
+static INLINE uint32
+bcmswap32by16(uint32 val)
+{
+ return BCMSWAP32BY16(val);
+}
+
+/* Reverse pairs of bytes in a buffer (not for high-performance use) */
+/* buf - start of buffer of shorts to swap */
+/* len - byte length of buffer */
+static INLINE void
+bcmswap16_buf(uint16 *buf, uint len)
+{
+ len = len / 2;
+
+ while (len--) {
+ *buf = bcmswap16(*buf);
+ buf++;
+ }
+}
+
+/*
+ * Store 16-bit value to unaligned little-endian byte array.
+ */
+static INLINE void
+htol16_ua_store(uint16 val, uint8 *bytes)
+{
+ bytes[0] = val & 0xff;
+ bytes[1] = val >> 8;
+}
+
+/*
+ * Store 32-bit value to unaligned little-endian byte array.
+ */
+static INLINE void
+htol32_ua_store(uint32 val, uint8 *bytes)
+{
+ bytes[0] = val & 0xff;
+ bytes[1] = (val >> 8) & 0xff;
+ bytes[2] = (val >> 16) & 0xff;
+ bytes[3] = val >> 24;
+}
+
+/*
+ * Store 16-bit value to unaligned network-(big-)endian byte array.
+ */
+static INLINE void
+hton16_ua_store(uint16 val, uint8 *bytes)
+{
+ bytes[0] = val >> 8;
+ bytes[1] = val & 0xff;
+}
+
+/*
+ * Store 32-bit value to unaligned network-(big-)endian byte array.
+ */
+static INLINE void
+hton32_ua_store(uint32 val, uint8 *bytes)
+{
+ bytes[0] = val >> 24;
+ bytes[1] = (val >> 16) & 0xff;
+ bytes[2] = (val >> 8) & 0xff;
+ bytes[3] = val & 0xff;
+}
+
+/*
+ * Load 16-bit value from unaligned little-endian byte array.
+ */
+static INLINE uint16
+ltoh16_ua(const void *bytes)
+{
+ return _LTOH16_UA((const uint8 *)bytes);
+}
+
+/*
+ * Load 32-bit value from unaligned little-endian byte array.
+ */
+static INLINE uint32
+ltoh32_ua(const void *bytes)
+{
+ return _LTOH32_UA((const uint8 *)bytes);
+}
+
+/*
+ * Load 16-bit value from unaligned big-(network-)endian byte array.
+ */
+static INLINE uint16
+ntoh16_ua(const void *bytes)
+{
+ return _NTOH16_UA((const uint8 *)bytes);
+}
+
+/*
+ * Load 32-bit value from unaligned big-(network-)endian byte array.
+ */
+static INLINE uint32
+ntoh32_ua(const void *bytes)
+{
+ return _NTOH32_UA((const uint8 *)bytes);
+}
+
+#endif /* !__GNUC__ */
+#endif /* !_BCMENDIAN_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmmsgbuf.h b/drivers/net/wireless/bcmdhd/include/bcmmsgbuf.h
new file mode 100644
index 000000000000..23ef576ba66f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmmsgbuf.h
@@ -0,0 +1,261 @@
+/*
+ * MSGBUF network driver ioctl/indication encoding
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmmsgbuf.h 452261 2014-01-29 19:30:23Z $
+ */
+#ifndef _bcmmsgbuf_h_
+#define _bcmmsgbuf_h_
+#include <proto/ethernet.h>
+#include <wlioctl.h>
+#include <bcmpcie.h>
+#define MSGBUF_MAX_MSG_SIZE ETHER_MAX_LEN
+#define DNGL_TO_HOST_MSGBUF_SZ (8 * 1024) /* Host side ring */
+#define HOST_TO_DNGL_MSGBUF_SZ (8 * 1024) /* Host side ring */
+#define DTOH_LOCAL_MSGBUF_SZ (8 * 1024) /* dongle side ring */
+#define HTOD_LOCAL_MSGBUF_SZ (8 * 1024) /* dongle side ring */
+#define HTOD_LOCAL_CTRLRING_SZ (1 * 1024) /* H2D control ring dongle side */
+#define DTOH_LOCAL_CTRLRING_SZ (1 * 1024) /* D2H control ring dongle side */
+#define HOST_TO_DNGL_CTRLRING_SZ (1 * 1024) /* Host to Device ctrl ring on host */
+#define DNGL_TO_HOST_CTRLRING_SZ (1 * 1024) /* Device to host ctrl ring on host */
+
+enum {
+ DNGL_TO_HOST_MSGBUF,
+ HOST_TO_DNGL_MSGBUF
+};
+
+enum {
+ MSG_TYPE_IOCTL_REQ = 0x1,
+ MSG_TYPE_IOCTLPTR_REQ,
+ MSG_TYPE_IOCTL_CMPLT,
+ MSG_TYPE_WL_EVENT,
+ MSG_TYPE_TX_POST,
+ MSG_TYPE_RXBUF_POST,
+ MSG_TYPE_RX_CMPLT,
+ MSG_TYPE_TX_STATUS,
+ MSG_TYPE_EVENT_PYLD,
+ MSG_TYPE_IOCT_PYLD, /* used only internally inside dongle */
+ MSG_TYPE_RX_PYLD, /* used only internally inside dongle */
+ MSG_TYPE_TX_PYLD, /* To be removed once split header is implemented */
+ MSG_TYPE_HOST_EVNT,
+ MSG_TYPE_LOOPBACK = 15, /* dongle loops the message back to host */
+ MSG_TYPE_LPBK_DMAXFER = 16, /* dongle DMA loopback */
+ MSG_TYPE_TX_BATCH_POST = 17
+};
+
+enum {
+ HOST_TO_DNGL_DATA,
+ HOST_TO_DNGL_CTRL,
+ DNGL_TO_HOST_DATA,
+ DNGL_TO_HOST_CTRL
+};
+
+#define MESSAGE_PAYLOAD(a) (((a) == MSG_TYPE_IOCT_PYLD) | ((a) == MSG_TYPE_RX_PYLD) |\
+ ((a) == MSG_TYPE_EVENT_PYLD) | ((a) == MSG_TYPE_TX_PYLD))
+#define MESSAGE_CTRLPATH(a) (((a) == MSG_TYPE_IOCTL_REQ) | ((a) == MSG_TYPE_IOCTLPTR_REQ) |\
+ ((a) == MSG_TYPE_IOCTL_CMPLT) | ((a) == MSG_TYPE_HOST_EVNT) |\
+ ((a) == MSG_TYPE_LOOPBACK) | ((a) == MSG_TYPE_WL_EVENT))
+
+/* IOCTL req Hdr */
+/* cmn Msg Hdr */
+typedef struct cmn_msg_hdr {
+ uint16 msglen;
+ uint8 msgtype;
+ uint8 ifidx;
+ union seqn {
+ uint32 seq_id;
+ struct sequence {
+ uint16 seq_no;
+ uint8 ring_id;
+ uint8 rsvd;
+ } seq;
+ } u;
+} cmn_msg_hdr_t;
+
+typedef struct ioctl_req_hdr {
+ uint32 pkt_id; /* Packet ID */
+ uint32 cmd; /* IOCTL ID */
+ uint16 retbuf_len;
+ uint16 buflen;
+ uint16 xt_id; /* transaction ID */
+ uint16 rsvd[1];
+} ioctl_req_hdr_t;
+
+/* ret buf struct */
+typedef struct ret_buf_ptr {
+ uint32 low_addr;
+ uint32 high_addr;
+} ret_buf_t;
+
+/* Complete msgbuf hdr for ioctl from host to dongle */
+typedef struct ioct_reqst_hdr {
+ cmn_msg_hdr_t msg;
+ ioctl_req_hdr_t ioct_hdr;
+ ret_buf_t ret_buf;
+} ioct_reqst_hdr_t;
+
+typedef struct ioctptr_reqst_hdr {
+ cmn_msg_hdr_t msg;
+ ioctl_req_hdr_t ioct_hdr;
+ ret_buf_t ret_buf;
+ ret_buf_t ioct_buf;
+} ioctptr_reqst_hdr_t;
+
+/* ioctl response header */
+typedef struct ioct_resp_hdr {
+ cmn_msg_hdr_t msg;
+ uint32 pkt_id;
+ uint32 status;
+ uint32 ret_len;
+ uint32 inline_data;
+ uint16 xt_id; /* transaction ID */
+ uint16 rsvd[1];
+} ioct_resp_hdr_t;
+
+/* ioct resp header used in dongle */
+/* ret buf hdr will be stripped off inside dongle itself */
+typedef struct msgbuf_ioctl_resp {
+ ioct_resp_hdr_t ioct_hdr;
+ ret_buf_t ret_buf; /* ret buf pointers */
+} msgbuf_ioct_resp_t;
+
+/* WL evet hdr info */
+typedef struct wl_event_hdr {
+ cmn_msg_hdr_t msg;
+ uint16 event;
+ uint8 flags;
+ uint8 rsvd;
+ uint16 retbuf_len;
+ uint16 rsvd1;
+ uint32 rxbufid;
+} wl_event_hdr_t;
+
+#define TXDESCR_FLOWID_PCIELPBK_1 0xFF
+#define TXDESCR_FLOWID_PCIELPBK_2 0xFE
+
+typedef struct txbatch_lenptr_tup {
+ uint32 pktid;
+ uint16 pktlen;
+ uint16 rsvd;
+ ret_buf_t ret_buf; /* ret buf pointers */
+} txbatch_lenptr_tup_t;
+
+typedef struct txbatch_cmn_msghdr {
+ cmn_msg_hdr_t msg;
+ uint8 priority;
+ uint8 hdrlen;
+ uint8 pktcnt;
+ uint8 flowid;
+ uint8 txhdr[ETHER_HDR_LEN];
+ uint16 rsvd;
+} txbatch_cmn_msghdr_t;
+
+typedef struct txbatch_msghdr {
+ txbatch_cmn_msghdr_t txcmn;
+ txbatch_lenptr_tup_t tx_tup[0]; /* Based on packet count */
+} txbatch_msghdr_t;
+
+/* TX desc posting header */
+typedef struct tx_lenptr_tup {
+ uint16 pktlen;
+ uint16 rsvd;
+ ret_buf_t ret_buf; /* ret buf pointers */
+} tx_lenptr_tup_t;
+
+typedef struct txdescr_cmn_msghdr {
+ cmn_msg_hdr_t msg;
+ uint8 priority;
+ uint8 hdrlen;
+ uint8 descrcnt;
+ uint8 flowid;
+ uint32 pktid;
+} txdescr_cmn_msghdr_t;
+
+typedef struct txdescr_msghdr {
+ txdescr_cmn_msghdr_t txcmn;
+ uint8 txhdr[ETHER_HDR_LEN];
+ uint16 rsvd;
+ tx_lenptr_tup_t tx_tup[0]; /* Based on descriptor count */
+} txdescr_msghdr_t;
+
+/* Tx status header info */
+typedef struct txstatus_hdr {
+ cmn_msg_hdr_t msg;
+ uint32 pktid;
+} txstatus_hdr_t;
+/* RX bufid-len-ptr tuple */
+typedef struct rx_lenptr_tup {
+ uint32 rxbufid;
+ uint16 len;
+ uint16 rsvd2;
+ ret_buf_t ret_buf; /* ret buf pointers */
+} rx_lenptr_tup_t;
+/* Rx descr Post hdr info */
+typedef struct rxdesc_msghdr {
+ cmn_msg_hdr_t msg;
+ uint16 rsvd0;
+ uint8 rsvd1;
+ uint8 descnt;
+ rx_lenptr_tup_t rx_tup[0];
+} rxdesc_msghdr_t;
+
+/* RX complete tuples */
+typedef struct rxcmplt_tup {
+ uint16 retbuf_len;
+ uint16 data_offset;
+ uint32 rxstatus0;
+ uint32 rxstatus1;
+ uint32 rxbufid;
+} rxcmplt_tup_t;
+/* RX complete messge hdr */
+typedef struct rxcmplt_hdr {
+ cmn_msg_hdr_t msg;
+ uint16 rsvd0;
+ uint16 rxcmpltcnt;
+ rxcmplt_tup_t rx_tup[0];
+} rxcmplt_hdr_t;
+typedef struct hostevent_hdr {
+ cmn_msg_hdr_t msg;
+ uint32 evnt_pyld;
+} hostevent_hdr_t;
+
+typedef struct dma_xfer_params {
+ uint32 src_physaddr_hi;
+ uint32 src_physaddr_lo;
+ uint32 dest_physaddr_hi;
+ uint32 dest_physaddr_lo;
+ uint32 len;
+ uint32 srcdelay;
+ uint32 destdelay;
+} dma_xfer_params_t;
+
+enum {
+ HOST_EVENT_CONS_CMD = 1
+};
+
+/* defines for flags */
+#define MSGBUF_IOC_ACTION_MASK 0x1
+
+#endif /* _bcmmsgbuf_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmnvram.h b/drivers/net/wireless/bcmdhd/include/bcmnvram.h
new file mode 100644
index 000000000000..3f145f271881
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmnvram.h
@@ -0,0 +1,272 @@
+/*
+ * NVRAM variable manipulation
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmnvram.h 428512 2013-10-09 02:12:11Z $
+ */
+
+#ifndef _bcmnvram_h_
+#define _bcmnvram_h_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+
+struct nvram_header {
+ uint32 magic;
+ uint32 len;
+ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
+ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
+ uint32 config_ncdl; /* ncdl values for memc */
+};
+
+struct nvram_tuple {
+ char *name;
+ char *value;
+ struct nvram_tuple *next;
+};
+
+/*
+ * Get default value for an NVRAM variable
+ */
+extern char *nvram_default_get(const char *name);
+/*
+ * validate/restore all per-interface related variables
+ */
+extern void nvram_validate_all(char *prefix, bool restore);
+
+/*
+ * restore specific per-interface variable
+ */
+extern void nvram_restore_var(char *prefix, char *name);
+
+/*
+ * Initialize NVRAM access. May be unnecessary or undefined on certain
+ * platforms.
+ */
+extern int nvram_init(void *sih);
+extern int nvram_deinit(void *sih);
+
+
+/*
+ * Append a chunk of nvram variables to the global list
+ */
+extern int nvram_append(void *si, char *vars, uint varsz);
+
+extern void nvram_get_global_vars(char **varlst, uint *varsz);
+
+
+/*
+ * Check for reset button press for restoring factory defaults.
+ */
+extern int nvram_reset(void *sih);
+
+/*
+ * Disable NVRAM access. May be unnecessary or undefined on certain
+ * platforms.
+ */
+extern void nvram_exit(void *sih);
+
+/*
+ * Get the value of an NVRAM variable. The pointer returned may be
+ * invalid after a set.
+ * @param name name of variable to get
+ * @return value of variable or NULL if undefined
+ */
+extern char * nvram_get(const char *name);
+
+/*
+ * Read the reset GPIO value from the nvram and set the GPIO
+ * as input
+ */
+extern int nvram_resetgpio_init(void *sih);
+
+/*
+ * Get the value of an NVRAM variable.
+ * @param name name of variable to get
+ * @return value of variable or NUL if undefined
+ */
+static INLINE char *
+nvram_safe_get(const char *name)
+{
+ char *p = nvram_get(name);
+ return p ? p : "";
+}
+
+/*
+ * Match an NVRAM variable.
+ * @param name name of variable to match
+ * @param match value to compare against value of variable
+ * @return TRUE if variable is defined and its value is string equal
+ * to match or FALSE otherwise
+ */
+static INLINE int
+nvram_match(const char *name, const char *match)
+{
+ const char *value = nvram_get(name);
+ return (value && !strcmp(value, match));
+}
+
+/*
+ * Inversely match an NVRAM variable.
+ * @param name name of variable to match
+ * @param match value to compare against value of variable
+ * @return TRUE if variable is defined and its value is not string
+ * equal to invmatch or FALSE otherwise
+ */
+static INLINE int
+nvram_invmatch(const char *name, const char *invmatch)
+{
+ const char *value = nvram_get(name);
+ return (value && strcmp(value, invmatch));
+}
+
+/*
+ * Set the value of an NVRAM variable. The name and value strings are
+ * copied into private storage. Pointers to previously set values
+ * may become invalid. The new value may be immediately
+ * retrieved but will not be permanently stored until a commit.
+ * @param name name of variable to set
+ * @param value value of variable
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_set(const char *name, const char *value);
+
+/*
+ * Unset an NVRAM variable. Pointers to previously set values
+ * remain valid until a set.
+ * @param name name of variable to unset
+ * @return 0 on success and errno on failure
+ * NOTE: use nvram_commit to commit this change to flash.
+ */
+extern int nvram_unset(const char *name);
+
+/*
+ * Commit NVRAM variables to permanent storage. All pointers to values
+ * may be invalid after a commit.
+ * NVRAM values are undefined after a commit.
+ * @param nvram_corrupt true to corrupt nvram, false otherwise.
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_commit_internal(bool nvram_corrupt);
+
+/*
+ * Commit NVRAM variables to permanent storage. All pointers to values
+ * may be invalid after a commit.
+ * NVRAM values are undefined after a commit.
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_commit(void);
+
+/*
+ * Get all NVRAM variables (format name=value\0 ... \0\0).
+ * @param buf buffer to store variables
+ * @param count size of buffer in bytes
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_getall(char *nvram_buf, int count);
+
+/*
+ * returns the crc value of the nvram
+ * @param nvh nvram header pointer
+ */
+uint8 nvram_calc_crc(struct nvram_header * nvh);
+
+extern int nvram_space;
+#endif /* _LANGUAGE_ASSEMBLY */
+
+/* The NVRAM version number stored as an NVRAM variable */
+#define NVRAM_SOFTWARE_VERSION "1"
+
+#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
+#define NVRAM_CLEAR_MAGIC 0x0
+#define NVRAM_INVALID_MAGIC 0xFFFFFFFF
+#define NVRAM_VERSION 1
+#define NVRAM_HEADER_SIZE 20
+/* This definition is for precommit staging, and will be removed */
+#define NVRAM_SPACE 0x8000
+/* For CFE builds this gets passed in thru the makefile */
+#ifndef MAX_NVRAM_SPACE
+#define MAX_NVRAM_SPACE 0x10000
+#endif
+#define DEF_NVRAM_SPACE 0x8000
+#define ROM_ENVRAM_SPACE 0x1000
+#define NVRAM_LZMA_MAGIC 0x4c5a4d41 /* 'LZMA' */
+
+#define NVRAM_MAX_VALUE_LEN 255
+#define NVRAM_MAX_PARAM_LEN 64
+
+#define NVRAM_CRC_START_POSITION 9 /* magic, len, crc8 to be skipped */
+#define NVRAM_CRC_VER_MASK 0xffffff00 /* for crc_ver_init */
+
+/* Offsets to embedded nvram area */
+#define NVRAM_START_COMPRESSED 0x400
+#define NVRAM_START 0x1000
+
+#define BCM_JUMBO_NVRAM_DELIMIT '\n'
+#define BCM_JUMBO_START "Broadcom Jumbo Nvram file"
+
+
+#if (defined(FAILSAFE_UPGRADE) || defined(CONFIG_FAILSAFE_UPGRADE) || \
+ defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__))
+#define IMAGE_SIZE "image_size"
+#define BOOTPARTITION "bootpartition"
+#define IMAGE_BOOT BOOTPARTITION
+#define PARTIALBOOTS "partialboots"
+#define MAXPARTIALBOOTS "maxpartialboots"
+#define IMAGE_1ST_FLASH_TRX "flash0.trx"
+#define IMAGE_1ST_FLASH_OS "flash0.os"
+#define IMAGE_2ND_FLASH_TRX "flash0.trx2"
+#define IMAGE_2ND_FLASH_OS "flash0.os2"
+#define IMAGE_FIRST_OFFSET "image_first_offset"
+#define IMAGE_SECOND_OFFSET "image_second_offset"
+#define LINUX_FIRST "linux"
+#define LINUX_SECOND "linux2"
+#endif
+
+#if (defined(DUAL_IMAGE) || defined(CONFIG_DUAL_IMAGE) || \
+ defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__))
+/* Shared by all: CFE, Linux Kernel, and Ap */
+#define IMAGE_BOOT "image_boot"
+#define BOOTPARTITION IMAGE_BOOT
+/* CFE variables */
+#define IMAGE_1ST_FLASH_TRX "flash0.trx"
+#define IMAGE_1ST_FLASH_OS "flash0.os"
+#define IMAGE_2ND_FLASH_TRX "flash0.trx2"
+#define IMAGE_2ND_FLASH_OS "flash0.os2"
+#define IMAGE_SIZE "image_size"
+
+/* CFE and Linux Kernel shared variables */
+#define IMAGE_FIRST_OFFSET "image_first_offset"
+#define IMAGE_SECOND_OFFSET "image_second_offset"
+
+/* Linux application variables */
+#define LINUX_FIRST "linux"
+#define LINUX_SECOND "linux2"
+#define POLICY_TOGGLE "toggle"
+#define LINUX_PART_TO_FLASH "linux_to_flash"
+#define LINUX_FLASH_POLICY "linux_flash_policy"
+
+#endif /* defined(DUAL_IMAGE||CONFIG_DUAL_IMAGE)||__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ */
+
+#endif /* _bcmnvram_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmpcie.h b/drivers/net/wireless/bcmdhd/include/bcmpcie.h
new file mode 100644
index 000000000000..f243fc30e7a8
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmpcie.h
@@ -0,0 +1,129 @@
+/*
+ * Broadcom PCIE
+ * Software-specific definitions shared between device and host side
+ * Explains the shared area between host and dongle
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmpcie.h 452261 2014-01-29 19:30:23Z $
+ */
+
+#ifndef _bcmpcie_h_
+#define _bcmpcie_h_
+
+#include <circularbuf.h>
+
+#define ADDR_64(x) (x.addr)
+#define HIGH_ADDR_32(x) ((uint32) (((sh_addr_t) x).high_addr))
+#define LOW_ADDR_32(x) ((uint32) (((sh_addr_t) x).low_addr))
+
+typedef struct {
+ uint32 low_addr;
+ uint32 high_addr;
+} sh_addr_t;
+
+#define PCIE_SHARED_VERSION 0x0003
+#define PCIE_SHARED_VERSION_MASK 0x00FF
+#define PCIE_SHARED_ASSERT_BUILT 0x0100
+#define PCIE_SHARED_ASSERT 0x0200
+#define PCIE_SHARED_TRAP 0x0400
+#define PCIE_SHARED_IN_BRPT 0x0800
+#define PCIE_SHARED_SET_BRPT 0x1000
+#define PCIE_SHARED_PENDING_BRPT 0x2000
+#define PCIE_SHARED_HTOD_SPLIT 0x4000
+#define PCIE_SHARED_DTOH_SPLIT 0x8000
+
+typedef struct ring_mem {
+ uint8 idx;
+ uint8 rsvd;
+ uint16 size;
+ sh_addr_t base_addr;
+} ring_mem_t;
+
+#define RINGSTATE_INITED 1
+
+typedef struct ring_state {
+ uint8 idx;
+ uint8 state;
+ uint16 r_offset;
+ uint16 w_offset;
+ uint16 e_offset;
+} ring_state_t;
+
+
+typedef struct ring_info {
+ uint8 h2d_ring_count;
+ uint8 d2h_ring_count;
+ uint8 rsvd[2];
+ /* locations in the TCM where the ringmem is and ringstate are defined */
+ uint32 ringmem_ptr; /* h2d_ring_count + d2h_ring_count */
+ uint32 ring_state_ptr; /* h2d_ring_count + d2h_ring_count */
+} ring_info_t;
+
+typedef struct {
+ /* shared area version captured at flags 7:0 */
+ uint32 flags;
+
+ uint32 trap_addr;
+ uint32 assert_exp_addr;
+ uint32 assert_file_addr;
+ uint32 assert_line;
+ uint32 console_addr; /* Address of hndrte_cons_t */
+ uint32 msgtrace_addr;
+ uint32 fwid;
+
+ /* Used for debug/flow control */
+ uint16 total_lfrag_pkt_cnt;
+ uint16 max_host_rxbufs;
+ uint32 rsvd1;
+
+ uint32 dma_rxoffset;
+
+ /* these will be used for sleep request/ack, d3 req/ack */
+ uint32 h2d_mb_data_ptr;
+ uint32 d2h_mb_data_ptr;
+
+ /* information pertinent to host IPC/msgbuf channels */
+ /* location in the TCM memory which has the ring_info */
+ uint32 rings_info_ptr;
+
+ /* block of host memory for the dongle to push the status into */
+ sh_addr_t device_rings_stsblk;
+ uint32 device_rings_stsblk_len;
+
+} pciedev_shared_t;
+
+
+/* H2D mail box Data */
+#define H2D_HOST_D3_INFORM 0x00000001
+#define H2D_HOST_DS_ACK 0x00000002
+
+/* D2H mail box Data */
+#define D2H_DEV_D3_ACK 0x00000001
+#define D2H_DEV_DS_ENTER_REQ 0x00000002
+#define D2H_DEV_DS_EXIT_NOTE 0x00000004
+
+
+extern pciedev_shared_t pciedev_shared;
+#define NEXTTXP(i, d) ((((i)+1) >= (d)) ? 0 : ((i)+1))
+#define NTXPACTIVE(r, w, d) (((r) <= (w)) ? ((w)-(r)) : ((d)-(r)+(w)))
+#define NTXPAVAIL(r, w, d) (((d) - NTXPACTIVE((r), (w), (d))) > 1)
+
+#endif /* _bcmpcie_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmpcispi.h b/drivers/net/wireless/bcmdhd/include/bcmpcispi.h
new file mode 100644
index 000000000000..54d0ce0831e2
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmpcispi.h
@@ -0,0 +1,181 @@
+/*
+ * Broadcom PCI-SPI Host Controller Register Definitions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmpcispi.h 241182 2011-02-17 21:50:03Z $
+ */
+#ifndef _BCM_PCI_SPI_H
+#define _BCM_PCI_SPI_H
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define _PADLINE(line) pad ## line
+#define _XSTR(line) _PADLINE(line)
+#define PAD _XSTR(__LINE__)
+#endif /* PAD */
+
+
+typedef volatile struct {
+ uint32 spih_ctrl; /* 0x00 SPI Control Register */
+ uint32 spih_stat; /* 0x04 SPI Status Register */
+ uint32 spih_data; /* 0x08 SPI Data Register, 32-bits wide */
+ uint32 spih_ext; /* 0x0C SPI Extension Register */
+ uint32 PAD[4]; /* 0x10-0x1F PADDING */
+
+ uint32 spih_gpio_ctrl; /* 0x20 SPI GPIO Control Register */
+ uint32 spih_gpio_data; /* 0x24 SPI GPIO Data Register */
+ uint32 PAD[6]; /* 0x28-0x3F PADDING */
+
+ uint32 spih_int_edge; /* 0x40 SPI Interrupt Edge Register (0=Level, 1=Edge) */
+ uint32 spih_int_pol; /* 0x44 SPI Interrupt Polarity Register (0=Active Low, */
+ /* 1=Active High) */
+ uint32 spih_int_mask; /* 0x48 SPI Interrupt Mask */
+ uint32 spih_int_status; /* 0x4C SPI Interrupt Status */
+ uint32 PAD[4]; /* 0x50-0x5F PADDING */
+
+ uint32 spih_hex_disp; /* 0x60 SPI 4-digit hex display value */
+ uint32 spih_current_ma; /* 0x64 SPI SD card current consumption in mA */
+ uint32 PAD[1]; /* 0x68 PADDING */
+ uint32 spih_disp_sel; /* 0x6c SPI 4-digit hex display mode select (1=current) */
+ uint32 PAD[4]; /* 0x70-0x7F PADDING */
+ uint32 PAD[8]; /* 0x80-0x9F PADDING */
+ uint32 PAD[8]; /* 0xA0-0xBF PADDING */
+ uint32 spih_pll_ctrl; /* 0xC0 PLL Control Register */
+ uint32 spih_pll_status; /* 0xC4 PLL Status Register */
+ uint32 spih_xtal_freq; /* 0xC8 External Clock Frequency in units of 10000Hz */
+ uint32 spih_clk_count; /* 0xCC External Clock Count Register */
+
+} spih_regs_t;
+
+typedef volatile struct {
+ uint32 cfg_space[0x40]; /* 0x000-0x0FF PCI Configuration Space (Read Only) */
+ uint32 P_IMG_CTRL0; /* 0x100 PCI Image0 Control Register */
+
+ uint32 P_BA0; /* 0x104 32 R/W PCI Image0 Base Address register */
+ uint32 P_AM0; /* 0x108 32 R/W PCI Image0 Address Mask register */
+ uint32 P_TA0; /* 0x10C 32 R/W PCI Image0 Translation Address register */
+ uint32 P_IMG_CTRL1; /* 0x110 32 R/W PCI Image1 Control register */
+ uint32 P_BA1; /* 0x114 32 R/W PCI Image1 Base Address register */
+ uint32 P_AM1; /* 0x118 32 R/W PCI Image1 Address Mask register */
+ uint32 P_TA1; /* 0x11C 32 R/W PCI Image1 Translation Address register */
+ uint32 P_IMG_CTRL2; /* 0x120 32 R/W PCI Image2 Control register */
+ uint32 P_BA2; /* 0x124 32 R/W PCI Image2 Base Address register */
+ uint32 P_AM2; /* 0x128 32 R/W PCI Image2 Address Mask register */
+ uint32 P_TA2; /* 0x12C 32 R/W PCI Image2 Translation Address register */
+ uint32 P_IMG_CTRL3; /* 0x130 32 R/W PCI Image3 Control register */
+ uint32 P_BA3; /* 0x134 32 R/W PCI Image3 Base Address register */
+ uint32 P_AM3; /* 0x138 32 R/W PCI Image3 Address Mask register */
+ uint32 P_TA3; /* 0x13C 32 R/W PCI Image3 Translation Address register */
+ uint32 P_IMG_CTRL4; /* 0x140 32 R/W PCI Image4 Control register */
+ uint32 P_BA4; /* 0x144 32 R/W PCI Image4 Base Address register */
+ uint32 P_AM4; /* 0x148 32 R/W PCI Image4 Address Mask register */
+ uint32 P_TA4; /* 0x14C 32 R/W PCI Image4 Translation Address register */
+ uint32 P_IMG_CTRL5; /* 0x150 32 R/W PCI Image5 Control register */
+ uint32 P_BA5; /* 0x154 32 R/W PCI Image5 Base Address register */
+ uint32 P_AM5; /* 0x158 32 R/W PCI Image5 Address Mask register */
+ uint32 P_TA5; /* 0x15C 32 R/W PCI Image5 Translation Address register */
+ uint32 P_ERR_CS; /* 0x160 32 R/W PCI Error Control and Status register */
+ uint32 P_ERR_ADDR; /* 0x164 32 R PCI Erroneous Address register */
+ uint32 P_ERR_DATA; /* 0x168 32 R PCI Erroneous Data register */
+
+ uint32 PAD[5]; /* 0x16C-0x17F PADDING */
+
+ uint32 WB_CONF_SPC_BAR; /* 0x180 32 R WISHBONE Configuration Space Base Address */
+ uint32 W_IMG_CTRL1; /* 0x184 32 R/W WISHBONE Image1 Control register */
+ uint32 W_BA1; /* 0x188 32 R/W WISHBONE Image1 Base Address register */
+ uint32 W_AM1; /* 0x18C 32 R/W WISHBONE Image1 Address Mask register */
+ uint32 W_TA1; /* 0x190 32 R/W WISHBONE Image1 Translation Address reg */
+ uint32 W_IMG_CTRL2; /* 0x194 32 R/W WISHBONE Image2 Control register */
+ uint32 W_BA2; /* 0x198 32 R/W WISHBONE Image2 Base Address register */
+ uint32 W_AM2; /* 0x19C 32 R/W WISHBONE Image2 Address Mask register */
+ uint32 W_TA2; /* 0x1A0 32 R/W WISHBONE Image2 Translation Address reg */
+ uint32 W_IMG_CTRL3; /* 0x1A4 32 R/W WISHBONE Image3 Control register */
+ uint32 W_BA3; /* 0x1A8 32 R/W WISHBONE Image3 Base Address register */
+ uint32 W_AM3; /* 0x1AC 32 R/W WISHBONE Image3 Address Mask register */
+ uint32 W_TA3; /* 0x1B0 32 R/W WISHBONE Image3 Translation Address reg */
+ uint32 W_IMG_CTRL4; /* 0x1B4 32 R/W WISHBONE Image4 Control register */
+ uint32 W_BA4; /* 0x1B8 32 R/W WISHBONE Image4 Base Address register */
+ uint32 W_AM4; /* 0x1BC 32 R/W WISHBONE Image4 Address Mask register */
+ uint32 W_TA4; /* 0x1C0 32 R/W WISHBONE Image4 Translation Address reg */
+ uint32 W_IMG_CTRL5; /* 0x1C4 32 R/W WISHBONE Image5 Control register */
+ uint32 W_BA5; /* 0x1C8 32 R/W WISHBONE Image5 Base Address register */
+ uint32 W_AM5; /* 0x1CC 32 R/W WISHBONE Image5 Address Mask register */
+ uint32 W_TA5; /* 0x1D0 32 R/W WISHBONE Image5 Translation Address reg */
+ uint32 W_ERR_CS; /* 0x1D4 32 R/W WISHBONE Error Control and Status reg */
+ uint32 W_ERR_ADDR; /* 0x1D8 32 R WISHBONE Erroneous Address register */
+ uint32 W_ERR_DATA; /* 0x1DC 32 R WISHBONE Erroneous Data register */
+ uint32 CNF_ADDR; /* 0x1E0 32 R/W Configuration Cycle register */
+ uint32 CNF_DATA; /* 0x1E4 32 R/W Configuration Cycle Generation Data reg */
+
+ uint32 INT_ACK; /* 0x1E8 32 R Interrupt Acknowledge register */
+ uint32 ICR; /* 0x1EC 32 R/W Interrupt Control register */
+ uint32 ISR; /* 0x1F0 32 R/W Interrupt Status register */
+} spih_pciregs_t;
+
+/*
+ * PCI Core interrupt enable and status bit definitions.
+ */
+
+/* PCI Core ICR Register bit definitions */
+#define PCI_INT_PROP_EN (1 << 0) /* Interrupt Propagation Enable */
+#define PCI_WB_ERR_INT_EN (1 << 1) /* Wishbone Error Interrupt Enable */
+#define PCI_PCI_ERR_INT_EN (1 << 2) /* PCI Error Interrupt Enable */
+#define PCI_PAR_ERR_INT_EN (1 << 3) /* Parity Error Interrupt Enable */
+#define PCI_SYS_ERR_INT_EN (1 << 4) /* System Error Interrupt Enable */
+#define PCI_SOFTWARE_RESET (1U << 31) /* Software reset of the PCI Core. */
+
+
+/* PCI Core ISR Register bit definitions */
+#define PCI_INT_PROP_ST (1 << 0) /* Interrupt Propagation Status */
+#define PCI_WB_ERR_INT_ST (1 << 1) /* Wishbone Error Interrupt Status */
+#define PCI_PCI_ERR_INT_ST (1 << 2) /* PCI Error Interrupt Status */
+#define PCI_PAR_ERR_INT_ST (1 << 3) /* Parity Error Interrupt Status */
+#define PCI_SYS_ERR_INT_ST (1 << 4) /* System Error Interrupt Status */
+
+
+/* Registers on the Wishbone bus */
+#define SPIH_CTLR_INTR (1 << 0) /* SPI Host Controller Core Interrupt */
+#define SPIH_DEV_INTR (1 << 1) /* SPI Device Interrupt */
+#define SPIH_WFIFO_INTR (1 << 2) /* SPI Tx FIFO Empty Intr (FPGA Rev >= 8) */
+
+/* GPIO Bit definitions */
+#define SPIH_CS (1 << 0) /* SPI Chip Select (active low) */
+#define SPIH_SLOT_POWER (1 << 1) /* SD Card Slot Power Enable */
+#define SPIH_CARD_DETECT (1 << 2) /* SD Card Detect */
+
+/* SPI Status Register Bit definitions */
+#define SPIH_STATE_MASK 0x30 /* SPI Transfer State Machine state mask */
+#define SPIH_STATE_SHIFT 4 /* SPI Transfer State Machine state shift */
+#define SPIH_WFFULL (1 << 3) /* SPI Write FIFO Full */
+#define SPIH_WFEMPTY (1 << 2) /* SPI Write FIFO Empty */
+#define SPIH_RFFULL (1 << 1) /* SPI Read FIFO Full */
+#define SPIH_RFEMPTY (1 << 0) /* SPI Read FIFO Empty */
+
+#define SPIH_EXT_CLK (1U << 31) /* Use External Clock as PLL Clock source. */
+
+#define SPIH_PLL_NO_CLK (1 << 1) /* Set to 1 if the PLL's input clock is lost. */
+#define SPIH_PLL_LOCKED (1 << 3) /* Set to 1 when the PLL is locked. */
+
+/* Spin bit loop bound check */
+#define SPI_SPIN_BOUND 0xf4240 /* 1 million */
+
+#endif /* _BCM_PCI_SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmperf.h b/drivers/net/wireless/bcmdhd/include/bcmperf.h
new file mode 100644
index 000000000000..1911d8a3e27a
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmperf.h
@@ -0,0 +1,36 @@
+/*
+ * Performance counters software interface.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmperf.h 241182 2011-02-17 21:50:03Z $
+ */
+/* essai */
+#ifndef _BCMPERF_H_
+#define _BCMPERF_H_
+/* get cache hits and misses */
+#define BCMPERF_ENABLE_INSTRCOUNT()
+#define BCMPERF_ENABLE_ICACHE_MISS()
+#define BCMPERF_ENABLE_ICACHE_HIT()
+#define BCMPERF_GETICACHE_MISS(x) ((x) = 0)
+#define BCMPERF_GETICACHE_HIT(x) ((x) = 0)
+#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0)
+#endif /* _BCMPERF_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h
new file mode 100644
index 000000000000..28d30c027ef8
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h
@@ -0,0 +1,143 @@
+/*
+ * Definitions for API from sdio common code (bcmsdh) to individual
+ * host controller drivers.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdbus.h 408158 2013-06-17 22:15:35Z $
+ */
+
+#ifndef _sdio_api_h_
+#define _sdio_api_h_
+
+
+#define SDIOH_API_RC_SUCCESS (0x00)
+#define SDIOH_API_RC_FAIL (0x01)
+#define SDIOH_API_SUCCESS(status) (status == 0)
+
+#define SDIOH_READ 0 /* Read request */
+#define SDIOH_WRITE 1 /* Write request */
+
+#define SDIOH_DATA_FIX 0 /* Fixed addressing */
+#define SDIOH_DATA_INC 1 /* Incremental addressing */
+
+#define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */
+#define SDIOH_CMD_TYPE_APPEND 1 /* Append command */
+#define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */
+
+#define SDIOH_DATA_PIO 0 /* PIO mode */
+#define SDIOH_DATA_DMA 1 /* DMA mode */
+
+/* Max number of glommed pkts */
+#ifdef CUSTOM_MAX_TXGLOM_SIZE
+#define SDPCM_MAXGLOM_SIZE CUSTOM_MAX_TXGLOM_SIZE
+#else
+#define SDPCM_MAXGLOM_SIZE 40
+#endif /* CUSTOM_MAX_TXGLOM_SIZE */
+
+#define SDPCM_TXGLOM_CPY 0 /* SDIO 2.0 should use copy mode */
+#define SDPCM_TXGLOM_MDESC 1 /* SDIO 3.0 should use multi-desc mode */
+
+#ifdef CUSTOM_DEF_TXGLOM_SIZE
+#define SDPCM_DEFGLOM_SIZE CUSTOM_DEF_TXGLOM_SIZE
+#else
+#define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE
+#endif /* CUSTOM_DEF_TXGLOM_SIZE */
+
+#if SDPCM_DEFGLOM_SIZE > SDPCM_MAXGLOM_SIZE
+#warning "SDPCM_DEFGLOM_SIZE cannot be higher than SDPCM_MAXGLOM_SIZE!!"
+#undef SDPCM_DEFGLOM_SIZE
+#define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE
+#endif
+
+typedef int SDIOH_API_RC;
+
+/* SDio Host structure */
+typedef struct sdioh_info sdioh_info_t;
+
+/* callback function, taking one arg */
+typedef void (*sdioh_cb_fn_t)(void *);
+
+extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si, sdioh_cb_fn_t fn, void *argh);
+extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
+
+/* query whether SD interrupt is enabled or not */
+extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff);
+
+/* enable or disable SD interrupt */
+extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
+
+#if defined(DHD_DEBUG)
+extern bool sdioh_interrupt_pending(sdioh_info_t *si);
+#endif
+
+/* read or write one byte using cmd52 */
+extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc, uint addr, uint8 *byte);
+
+/* read or write 2/4 bytes using cmd53 */
+extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type, uint rw, uint fnc,
+ uint addr, uint32 *word, uint nbyte);
+
+/* read or write any buffer using cmd53 */
+extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma, uint fix_inc,
+ uint rw, uint fnc_num, uint32 addr, uint regwidth, uint32 buflen, uint8 *buffer,
+ void *pkt);
+
+/* get cis data */
+extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, uint8 *cis, uint32 length);
+
+extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, uint32 addr, uint8 *data);
+extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, uint32 addr, uint8 *data);
+
+/* query number of io functions */
+extern uint sdioh_query_iofnum(sdioh_info_t *si);
+
+/* handle iovars */
+extern int sdioh_iovar_op(sdioh_info_t *si, const char *name,
+ void *params, int plen, void *arg, int len, bool set);
+
+/* Issue abort to the specified function and clear controller as needed */
+extern int sdioh_abort(sdioh_info_t *si, uint fnc);
+
+/* Start and Stop SDIO without re-enumerating the SD card. */
+extern int sdioh_start(sdioh_info_t *si, int stage);
+extern int sdioh_stop(sdioh_info_t *si);
+
+/* Wait system lock free */
+extern int sdioh_waitlockfree(sdioh_info_t *si);
+
+/* Reset and re-initialize the device */
+extern int sdioh_sdio_reset(sdioh_info_t *si);
+
+
+
+#if defined(BCMSDIOH_STD)
+ #define SDIOH_SLEEP_ENABLED
+#endif
+extern SDIOH_API_RC sdioh_sleep(sdioh_info_t *si, bool enab);
+
+/* GPIO support */
+extern SDIOH_API_RC sdioh_gpio_init(sdioh_info_t *sd);
+extern bool sdioh_gpioin(sdioh_info_t *sd, uint32 gpio);
+extern SDIOH_API_RC sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio);
+extern SDIOH_API_RC sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab);
+
+#endif /* _sdio_api_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh.h b/drivers/net/wireless/bcmdhd/include/bcmsdh.h
new file mode 100644
index 000000000000..8062bf735b90
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmsdh.h
@@ -0,0 +1,251 @@
+/*
+ * SDIO host client driver interface of Broadcom HNBU
+ * export functions to client drivers
+ * abstract OS and BUS specific details of SDIO
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdh.h 662739 2016-11-08 09:20:31Z $
+ */
+
+/**
+ * @file bcmsdh.h
+ */
+
+#ifndef _bcmsdh_h_
+#define _bcmsdh_h_
+
+#define BCMSDH_ERROR_VAL 0x0001 /* Error */
+#define BCMSDH_INFO_VAL 0x0002 /* Info */
+extern const uint bcmsdh_msglevel;
+
+#define BCMSDH_ERROR(x)
+#define BCMSDH_INFO(x)
+
+#if (defined(BCMSDIOH_STD) || defined(BCMSDIOH_BCM) || defined(BCMSDIOH_SPI))
+#define BCMSDH_ADAPTER
+#endif /* BCMSDIO && (BCMSDIOH_STD || BCMSDIOH_BCM || BCMSDIOH_SPI) */
+
+/* forward declarations */
+typedef struct bcmsdh_info bcmsdh_info_t;
+typedef void (*bcmsdh_cb_fn_t)(void *);
+
+extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *sdioh, ulong *regsva);
+/**
+ * BCMSDH API context
+ */
+struct bcmsdh_info
+{
+ bool init_success; /* underlying driver successfully attached */
+ void *sdioh; /* handler for sdioh */
+ uint32 vendevid; /* Target Vendor and Device ID on SD bus */
+ osl_t *osh;
+ bool regfail; /* Save status of last reg_read/reg_write call */
+ uint32 sbwad; /* Save backplane window address */
+ void *os_cxt; /* Pointer to per-OS private data */
+};
+
+/* Detach - freeup resources allocated in attach */
+extern int bcmsdh_detach(osl_t *osh, void *sdh);
+
+/* Query if SD device interrupts are enabled */
+extern bool bcmsdh_intr_query(void *sdh);
+
+/* Enable/disable SD interrupt */
+extern int bcmsdh_intr_enable(void *sdh);
+extern int bcmsdh_intr_disable(void *sdh);
+
+/* Register/deregister device interrupt handler. */
+extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh);
+extern int bcmsdh_intr_dereg(void *sdh);
+/* Enable/disable SD card interrupt forward */
+extern void bcmsdh_intr_forward(void *sdh, bool pass);
+
+#if defined(DHD_DEBUG)
+/* Query pending interrupt status from the host controller */
+extern bool bcmsdh_intr_pending(void *sdh);
+#endif
+
+/* Register a callback to be called if and when bcmsdh detects
+ * device removal. No-op in the case of non-removable/hardwired devices.
+ */
+extern int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh);
+
+/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
+ * fn: function number
+ * addr: unmodified SDIO-space address
+ * data: data byte to write
+ * err: pointer to error code (or NULL)
+ */
+extern uint8 bcmsdh_cfg_read(void *sdh, uint func, uint32 addr, int *err);
+extern void bcmsdh_cfg_write(void *sdh, uint func, uint32 addr, uint8 data, int *err);
+
+/* Read/Write 4bytes from/to cfg space */
+extern uint32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err);
+extern void bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err);
+
+/* Read CIS content for specified function.
+ * fn: function whose CIS is being requested (0 is common CIS)
+ * cis: pointer to memory location to place results
+ * length: number of bytes to read
+ * Internally, this routine uses the values from the cis base regs (0x9-0xB)
+ * to form an SDIO-space address to read the data from.
+ */
+extern int bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length);
+
+/* Synchronous access to device (client) core registers via CMD53 to F1.
+ * addr: backplane address (i.e. >= regsva from attach)
+ * size: register width in bytes (2 or 4)
+ * data: data for register write
+ */
+extern uint32 bcmsdh_reg_read(void *sdh, uint32 addr, uint size);
+extern uint32 bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data);
+
+/* set sb address window */
+extern int bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set);
+
+/* Indicate if last reg read/write failed */
+extern bool bcmsdh_regfail(void *sdh);
+
+/* Buffer transfer to/from device (client) core via cmd53.
+ * fn: function number
+ * addr: backplane address (i.e. >= regsva from attach)
+ * flags: backplane width, address increment, sync/async
+ * buf: pointer to memory data buffer
+ * nbytes: number of bytes to transfer to/from buf
+ * pkt: pointer to packet associated with buf (if any)
+ * complete: callback function for command completion (async only)
+ * handle: handle for completion callback (first arg in callback)
+ * Returns 0 or error code.
+ * NOTE: Async operation is not currently supported.
+ */
+typedef void (*bcmsdh_cmplt_fn_t)(void *handle, int status, bool sync_waiting);
+extern int bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags,
+ uint8 *buf, uint nbytes, void *pkt,
+ bcmsdh_cmplt_fn_t complete_fn, void *handle);
+extern int bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags,
+ uint8 *buf, uint nbytes, void *pkt,
+ bcmsdh_cmplt_fn_t complete_fn, void *handle);
+
+extern void bcmsdh_glom_post(void *sdh, uint8 *frame, void *pkt, uint len);
+extern void bcmsdh_glom_clear(void *sdh);
+extern uint bcmsdh_set_mode(void *sdh, uint mode);
+extern bool bcmsdh_glom_enabled(void);
+/* Flags bits */
+#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */
+#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */
+#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */
+#define SDIO_BYTE_MODE 0x8 /* Byte mode request(non-block mode) */
+
+/* Pending (non-error) return code */
+#define BCME_PENDING 1
+
+/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
+ * rw: read or write (0/1)
+ * addr: direct SDIO address
+ * buf: pointer to memory data buffer
+ * nbytes: number of bytes to transfer to/from buf
+ * Returns 0 or error code.
+ */
+extern int bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes);
+
+/* Issue an abort to the specified function */
+extern int bcmsdh_abort(void *sdh, uint fn);
+
+/* Start SDIO Host Controller communication */
+extern int bcmsdh_start(void *sdh, int stage);
+
+/* Stop SDIO Host Controller communication */
+extern int bcmsdh_stop(void *sdh);
+
+/* Wait system lock free */
+extern int bcmsdh_waitlockfree(void *sdh);
+
+/* Returns the "Device ID" of target device on the SDIO bus. */
+extern int bcmsdh_query_device(void *sdh);
+
+/* Returns the number of IO functions reported by the device */
+extern uint bcmsdh_query_iofnum(void *sdh);
+
+/* Miscellaneous knob tweaker. */
+extern int bcmsdh_iovar_op(void *sdh, const char *name,
+ void *params, int plen, void *arg, int len, bool set);
+
+/* Reset and reinitialize the device */
+extern int bcmsdh_reset(bcmsdh_info_t *sdh);
+
+/* helper functions */
+
+/* callback functions */
+typedef struct {
+ /* probe the device */
+ void *(*probe)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot,
+ uint16 func, uint bustype, void * regsva, osl_t * osh,
+ void * param);
+ /* remove the device */
+ void (*remove)(void *context);
+ /* can we suspend now */
+ int (*suspend)(void *context);
+ /* resume from suspend */
+ int (*resume)(void *context);
+} bcmsdh_driver_t;
+
+/* platform specific/high level functions */
+extern int bcmsdh_register(bcmsdh_driver_t *driver);
+extern void bcmsdh_unregister(void);
+extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device);
+extern void bcmsdh_device_remove(void * sdh);
+
+extern int bcmsdh_reg_sdio_notify(void* semaphore);
+extern void bcmsdh_unreg_sdio_notify(void);
+
+#if defined(OOB_INTR_ONLY)
+extern int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler,
+ void* oob_irq_handler_context);
+extern void bcmsdh_oob_intr_unregister(bcmsdh_info_t *sdh);
+extern void bcmsdh_oob_intr_set(bcmsdh_info_t *sdh, bool enable);
+#endif
+extern void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *sdh);
+extern void bcmsdh_dev_relax(bcmsdh_info_t *sdh);
+extern bool bcmsdh_dev_pm_enabled(bcmsdh_info_t *sdh);
+
+int bcmsdh_suspend(bcmsdh_info_t *bcmsdh);
+int bcmsdh_resume(bcmsdh_info_t *bcmsdh);
+
+/* Function to pass device-status bits to DHD. */
+extern uint32 bcmsdh_get_dstatus(void *sdh);
+
+/* Function to return current window addr */
+extern uint32 bcmsdh_cur_sbwad(void *sdh);
+
+/* Function to pass chipid and rev to lower layers for controlling pr's */
+extern void bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev);
+
+
+extern int bcmsdh_sleep(void *sdh, bool enab);
+
+/* GPIO support */
+extern int bcmsdh_gpio_init(void *sd);
+extern bool bcmsdh_gpioin(void *sd, uint32 gpio);
+extern int bcmsdh_gpioouten(void *sd, uint32 gpio);
+extern int bcmsdh_gpioout(void *sd, uint32 gpio, bool enab);
+
+#endif /* _bcmsdh_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h
new file mode 100644
index 000000000000..2891b8521eb4
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h
@@ -0,0 +1,117 @@
+/*
+ * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdh_sdmmc.h 444019 2013-12-18 08:36:54Z $
+ */
+
+#ifndef __BCMSDH_SDMMC_H__
+#define __BCMSDH_SDMMC_H__
+
+#define sd_err(x)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+
+
+#define sd_sync_dma(sd, read, nbytes)
+#define sd_init_dma(sd)
+#define sd_ack_intr(sd)
+#define sd_wakeup(sd);
+
+#define sd_log(x)
+
+#define SDIOH_ASSERT(exp) \
+ do { if (!(exp)) \
+ printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
+ } while (0)
+
+#define BLOCK_SIZE_4318 64
+#define BLOCK_SIZE_4328 512
+
+/* internal return code */
+#define SUCCESS 0
+#define ERROR 1
+
+/* private bus modes */
+#define SDIOH_MODE_SD4 2
+#define CLIENT_INTR 0x100 /* Get rid of this! */
+#define SDIOH_SDMMC_MAX_SG_ENTRIES (SDPCM_MAXGLOM_SIZE+2)
+
+struct sdioh_info {
+ osl_t *osh; /* osh handler */
+ void *bcmsdh; /* upper layer handle */
+ bool client_intr_enabled; /* interrupt connnected flag */
+ bool intr_handler_valid; /* client driver interrupt handler valid */
+ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
+ void *intr_handler_arg; /* argument to call interrupt handler */
+ uint16 intmask; /* Current active interrupts */
+
+ int intrcount; /* Client interrupts */
+ bool sd_use_dma; /* DMA on CMD53 */
+ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
+ /* Must be on for sd_multiblock to be effective */
+ bool use_client_ints; /* If this is false, make sure to restore */
+ int sd_mode; /* SD1/SD4/SPI */
+ int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
+ uint8 num_funcs; /* Supported funcs on client */
+ uint32 com_cis_ptr;
+ uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
+ bool use_rxchain;
+ struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES];
+ struct sdio_func fake_func0;
+ struct sdio_func *func[SDIOD_MAX_IOFUNCS];
+
+};
+
+/************************************************************
+ * Internal interfaces: per-port references into bcmsdh_sdmmc.c
+ */
+
+/* Global message bits */
+extern uint sd_msglevel;
+
+/* OS-independent interrupt handler */
+extern bool check_client_intr(sdioh_info_t *sd);
+
+/* Core interrupt enable/disable of device interrupts */
+extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
+extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
+
+
+/**************************************************************
+ * Internal interfaces: bcmsdh_sdmmc.c references to per-port code
+ */
+
+/* Register mapping routines */
+extern uint32 *sdioh_sdmmc_reg_map(osl_t *osh, int32 addr, int size);
+extern void sdioh_sdmmc_reg_unmap(osl_t *osh, int32 addr, int size);
+
+/* Interrupt (de)registration routines */
+extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
+extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
+
+extern sdioh_info_t *sdioh_attach(osl_t *osh, struct sdio_func *func);
+extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd);
+#endif /* __BCMSDH_SDMMC_H__ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h
new file mode 100644
index 000000000000..26d064fcd9cc
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h
@@ -0,0 +1,281 @@
+/*
+ * Broadcom SDIO/PCMCIA
+ * Software-specific definitions shared between device and host side
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdpcm.h 414378 2013-07-24 15:58:50Z $
+ */
+
+#ifndef _bcmsdpcm_h_
+#define _bcmsdpcm_h_
+
+/*
+ * Software allocation of To SB Mailbox resources
+ */
+
+/* intstatus bits */
+#define I_SMB_NAK I_SMB_SW0 /* To SB Mailbox Frame NAK */
+#define I_SMB_INT_ACK I_SMB_SW1 /* To SB Mailbox Host Interrupt ACK */
+#define I_SMB_USE_OOB I_SMB_SW2 /* To SB Mailbox Use OOB Wakeup */
+#define I_SMB_DEV_INT I_SMB_SW3 /* To SB Mailbox Miscellaneous Interrupt */
+
+#define I_TOSBMAIL (I_SMB_NAK | I_SMB_INT_ACK | I_SMB_USE_OOB | I_SMB_DEV_INT)
+
+/* tosbmailbox bits corresponding to intstatus bits */
+#define SMB_NAK (1 << 0) /* To SB Mailbox Frame NAK */
+#define SMB_INT_ACK (1 << 1) /* To SB Mailbox Host Interrupt ACK */
+#define SMB_USE_OOB (1 << 2) /* To SB Mailbox Use OOB Wakeup */
+#define SMB_DEV_INT (1 << 3) /* To SB Mailbox Miscellaneous Interrupt */
+#define SMB_MASK 0x0000000f /* To SB Mailbox Mask */
+
+/* tosbmailboxdata */
+#define SMB_DATA_VERSION_MASK 0x00ff0000 /* host protocol version (sent with F2 enable) */
+#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version (sent with F2 enable) */
+
+/*
+ * Software allocation of To Host Mailbox resources
+ */
+
+/* intstatus bits */
+#define I_HMB_FC_STATE I_HMB_SW0 /* To Host Mailbox Flow Control State */
+#define I_HMB_FC_CHANGE I_HMB_SW1 /* To Host Mailbox Flow Control State Changed */
+#define I_HMB_FRAME_IND I_HMB_SW2 /* To Host Mailbox Frame Indication */
+#define I_HMB_HOST_INT I_HMB_SW3 /* To Host Mailbox Miscellaneous Interrupt */
+
+#define I_TOHOSTMAIL (I_HMB_FC_CHANGE | I_HMB_FRAME_IND | I_HMB_HOST_INT)
+
+/* tohostmailbox bits corresponding to intstatus bits */
+#define HMB_FC_ON (1 << 0) /* To Host Mailbox Flow Control State */
+#define HMB_FC_CHANGE (1 << 1) /* To Host Mailbox Flow Control State Changed */
+#define HMB_FRAME_IND (1 << 2) /* To Host Mailbox Frame Indication */
+#define HMB_HOST_INT (1 << 3) /* To Host Mailbox Miscellaneous Interrupt */
+#define HMB_MASK 0x0000000f /* To Host Mailbox Mask */
+
+/* tohostmailboxdata */
+#define HMB_DATA_NAKHANDLED 0x01 /* we're ready to retransmit NAK'd frame to host */
+#define HMB_DATA_DEVREADY 0x02 /* we're ready to to talk to host after enable */
+#define HMB_DATA_FC 0x04 /* per prio flowcontrol update flag to host */
+#define HMB_DATA_FWREADY 0x08 /* firmware is ready for protocol activity */
+#define HMB_DATA_FWHALT 0x10 /* firmware has halted operation */
+
+#define HMB_DATA_FCDATA_MASK 0xff000000 /* per prio flowcontrol data */
+#define HMB_DATA_FCDATA_SHIFT 24 /* per prio flowcontrol data */
+
+#define HMB_DATA_VERSION_MASK 0x00ff0000 /* device protocol version (with devready) */
+#define HMB_DATA_VERSION_SHIFT 16 /* device protocol version (with devready) */
+
+/*
+ * Software-defined protocol header
+ */
+
+/* Current protocol version */
+#define SDPCM_PROT_VERSION 4
+
+/* SW frame header */
+#define SDPCM_SEQUENCE_MASK 0x000000ff /* Sequence Number Mask */
+#define SDPCM_PACKET_SEQUENCE(p) (((uint8 *)p)[0] & 0xff) /* p starts w/SW Header */
+
+#define SDPCM_CHANNEL_MASK 0x00000f00 /* Channel Number Mask */
+#define SDPCM_CHANNEL_SHIFT 8 /* Channel Number Shift */
+#define SDPCM_PACKET_CHANNEL(p) (((uint8 *)p)[1] & 0x0f) /* p starts w/SW Header */
+
+#define SDPCM_FLAGS_MASK 0x0000f000 /* Mask of flag bits */
+#define SDPCM_FLAGS_SHIFT 12 /* Flag bits shift */
+#define SDPCM_PACKET_FLAGS(p) ((((uint8 *)p)[1] & 0xf0) >> 4) /* p starts w/SW Header */
+
+/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */
+#define SDPCM_NEXTLEN_MASK 0x00ff0000 /* Next Read Len Mask */
+#define SDPCM_NEXTLEN_SHIFT 16 /* Next Read Len Shift */
+#define SDPCM_NEXTLEN_VALUE(p) ((((uint8 *)p)[2] & 0xff) << 4) /* p starts w/SW Header */
+#define SDPCM_NEXTLEN_OFFSET 2
+
+/* Data Offset from SOF (HW Tag, SW Tag, Pad) */
+#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */
+#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff)
+#define SDPCM_DOFFSET_MASK 0xff000000
+#define SDPCM_DOFFSET_SHIFT 24
+
+#define SDPCM_FCMASK_OFFSET 4 /* Flow control */
+#define SDPCM_FCMASK_VALUE(p) (((uint8 *)p)[SDPCM_FCMASK_OFFSET ] & 0xff)
+#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */
+#define SDPCM_WINDOW_VALUE(p) (((uint8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff)
+#define SDPCM_VERSION_OFFSET 6 /* Version # */
+#define SDPCM_VERSION_VALUE(p) (((uint8 *)p)[SDPCM_VERSION_OFFSET] & 0xff)
+#define SDPCM_UNUSED_OFFSET 7 /* Spare */
+#define SDPCM_UNUSED_VALUE(p) (((uint8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff)
+
+#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */
+
+/* logical channel numbers */
+#define SDPCM_CONTROL_CHANNEL 0 /* Control Request/Response Channel Id */
+#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */
+#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */
+#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets (superframes) */
+#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */
+#define SDPCM_MAX_CHANNEL 15
+
+#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for eight-bit frame seq number */
+
+#define SDPCM_FLAG_RESVD0 0x01
+#define SDPCM_FLAG_RESVD1 0x02
+#define SDPCM_FLAG_GSPI_TXENAB 0x04
+#define SDPCM_FLAG_GLOMDESC 0x08 /* Superframe descriptor mask */
+
+/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */
+#define SDPCM_GLOMDESC_FLAG (SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT)
+
+#define SDPCM_GLOMDESC(p) (((uint8 *)p)[1] & 0x80)
+
+/* For TEST_CHANNEL packets, define another 4-byte header */
+#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2);
+ * Semantics of Ext byte depend on command.
+ * Len is current or requested frame length, not
+ * including test header; sent little-endian.
+ */
+#define SDPCM_TEST_PKT_CNT_FLD_LEN 4 /* Packet count filed legth */
+#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */
+#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */
+#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */
+#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count
+ * (Backward compatabilty) Set frame count in a
+ * 4 byte filed adjacent to the HDR
+ */
+#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off
+ * Set frame count in a 4 byte filed adjacent to
+ * the HDR
+ */
+
+/* Handy macro for filling in datagen packets with a pattern */
+#define SDPCM_TEST_FILL(byteno, id) ((uint8)(id + byteno))
+
+/*
+ * Software counters (first part matches hardware counters)
+ */
+
+typedef volatile struct {
+ uint32 cmd52rd; /* Cmd52RdCount, SDIO: cmd52 reads */
+ uint32 cmd52wr; /* Cmd52WrCount, SDIO: cmd52 writes */
+ uint32 cmd53rd; /* Cmd53RdCount, SDIO: cmd53 reads */
+ uint32 cmd53wr; /* Cmd53WrCount, SDIO: cmd53 writes */
+ uint32 abort; /* AbortCount, SDIO: aborts */
+ uint32 datacrcerror; /* DataCrcErrorCount, SDIO: frames w/CRC error */
+ uint32 rdoutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */
+ uint32 wroutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */
+ uint32 writebusy; /* WriteBusyCount, SDIO: device asserted "busy" */
+ uint32 readwait; /* ReadWaitCount, SDIO: no data ready for a read cmd */
+ uint32 readterm; /* ReadTermCount, SDIO: read frame termination cmds */
+ uint32 writeterm; /* WriteTermCount, SDIO: write frames termination cmds */
+ uint32 rxdescuflo; /* receive descriptor underflows */
+ uint32 rxfifooflo; /* receive fifo overflows */
+ uint32 txfifouflo; /* transmit fifo underflows */
+ uint32 runt; /* runt (too short) frames recv'd from bus */
+ uint32 badlen; /* frame's rxh len does not match its hw tag len */
+ uint32 badcksum; /* frame's hw tag chksum doesn't agree with len value */
+ uint32 seqbreak; /* break in sequence # space from one rx frame to the next */
+ uint32 rxfcrc; /* frame rx header indicates crc error */
+ uint32 rxfwoos; /* frame rx header indicates write out of sync */
+ uint32 rxfwft; /* frame rx header indicates write frame termination */
+ uint32 rxfabort; /* frame rx header indicates frame aborted */
+ uint32 woosint; /* write out of sync interrupt */
+ uint32 roosint; /* read out of sync interrupt */
+ uint32 rftermint; /* read frame terminate interrupt */
+ uint32 wftermint; /* write frame terminate interrupt */
+} sdpcmd_cnt_t;
+
+/*
+ * Register Access Macros
+ */
+
+#define SDIODREV_IS(var, val) ((var) == (val))
+#define SDIODREV_GE(var, val) ((var) >= (val))
+#define SDIODREV_GT(var, val) ((var) > (val))
+#define SDIODREV_LT(var, val) ((var) < (val))
+#define SDIODREV_LE(var, val) ((var) <= (val))
+
+#define SDIODDMAREG32(h, dir, chnl) \
+ ((dir) == DMA_TX ? \
+ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].xmt) : \
+ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].rcv))
+
+#define SDIODDMAREG64(h, dir, chnl) \
+ ((dir) == DMA_TX ? \
+ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].xmt) : \
+ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].rcv))
+
+#define SDIODDMAREG(h, dir, chnl) \
+ (SDIODREV_LT((h)->corerev, 1) ? \
+ SDIODDMAREG32((h), (dir), (chnl)) : \
+ SDIODDMAREG64((h), (dir), (chnl)))
+
+#define PCMDDMAREG(h, dir, chnl) \
+ ((dir) == DMA_TX ? \
+ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.xmt) : \
+ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.rcv))
+
+#define SDPCMDMAREG(h, dir, chnl, coreid) \
+ ((coreid) == SDIOD_CORE_ID ? \
+ SDIODDMAREG(h, dir, chnl) : \
+ PCMDDMAREG(h, dir, chnl))
+
+#define SDIODFIFOREG(h, corerev) \
+ (SDIODREV_LT((corerev), 1) ? \
+ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod32.dmafifo)) : \
+ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod64.dmafifo)))
+
+#define PCMDFIFOREG(h) \
+ ((dma32diag_t *)(uintptr)&((h)->regs->dma.pcm32.dmafifo))
+
+#define SDPCMFIFOREG(h, coreid, corerev) \
+ ((coreid) == SDIOD_CORE_ID ? \
+ SDIODFIFOREG(h, corerev) : \
+ PCMDFIFOREG(h))
+
+/*
+ * Shared structure between dongle and the host.
+ * The structure contains pointers to trap or assert information.
+ */
+#define SDPCM_SHARED_VERSION 0x0001
+#define SDPCM_SHARED_VERSION_MASK 0x00FF
+#define SDPCM_SHARED_ASSERT_BUILT 0x0100
+#define SDPCM_SHARED_ASSERT 0x0200
+#define SDPCM_SHARED_TRAP 0x0400
+#define SDPCM_SHARED_IN_BRPT 0x0800
+#define SDPCM_SHARED_SET_BRPT 0x1000
+#define SDPCM_SHARED_PENDING_BRPT 0x2000
+
+typedef struct {
+ uint32 flags;
+ uint32 trap_addr;
+ uint32 assert_exp_addr;
+ uint32 assert_file_addr;
+ uint32 assert_line;
+ uint32 console_addr; /* Address of hndrte_cons_t */
+ uint32 msgtrace_addr;
+ uint32 fwid;
+} sdpcm_shared_t;
+
+extern sdpcm_shared_t sdpcm_shared;
+
+/* Function can be used to notify host of FW halt */
+extern void sdpcmd_fwhalt(void);
+
+#endif /* _bcmsdpcm_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdspi.h b/drivers/net/wireless/bcmdhd/include/bcmsdspi.h
new file mode 100644
index 000000000000..3c3a16048043
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmsdspi.h
@@ -0,0 +1,135 @@
+/*
+ * SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdspi.h 294363 2011-11-06 23:02:20Z $
+ */
+#ifndef _BCM_SD_SPI_H
+#define _BCM_SD_SPI_H
+
+/* global msglevel for debug messages - bitvals come from sdiovar.h */
+
+#define sd_err(x)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+
+#define sd_log(x)
+
+#define SDIOH_ASSERT(exp) \
+ do { if (!(exp)) \
+ printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
+ } while (0)
+
+#define BLOCK_SIZE_4318 64
+#define BLOCK_SIZE_4328 512
+
+/* internal return code */
+#define SUCCESS 0
+#undef ERROR
+#define ERROR 1
+
+/* private bus modes */
+#define SDIOH_MODE_SPI 0
+
+#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */
+#define USE_MULTIBLOCK 0x4
+
+struct sdioh_info {
+ uint cfg_bar; /* pci cfg address for bar */
+ uint32 caps; /* cached value of capabilities reg */
+ uint bar0; /* BAR0 for PCI Device */
+ osl_t *osh; /* osh handler */
+ void *controller; /* Pointer to SPI Controller's private data struct */
+
+ uint lockcount; /* nest count of sdspi_lock() calls */
+ bool client_intr_enabled; /* interrupt connnected flag */
+ bool intr_handler_valid; /* client driver interrupt handler valid */
+ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
+ void *intr_handler_arg; /* argument to call interrupt handler */
+ bool initialized; /* card initialized */
+ uint32 target_dev; /* Target device ID */
+ uint32 intmask; /* Current active interrupts */
+ void *sdos_info; /* Pointer to per-OS private data */
+
+ uint32 controller_type; /* Host controller type */
+ uint8 version; /* Host Controller Spec Compliance Version */
+ uint irq; /* Client irq */
+ uint32 intrcount; /* Client interrupts */
+ uint32 local_intrcount; /* Controller interrupts */
+ bool host_init_done; /* Controller initted */
+ bool card_init_done; /* Client SDIO interface initted */
+ bool polled_mode; /* polling for command completion */
+
+ bool sd_use_dma; /* DMA on CMD53 */
+ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
+ /* Must be on for sd_multiblock to be effective */
+ bool use_client_ints; /* If this is false, make sure to restore */
+ bool got_hcint; /* Host Controller interrupt. */
+ /* polling hack in wl_linux.c:wl_timer() */
+ int adapter_slot; /* Maybe dealing with multiple slots/controllers */
+ int sd_mode; /* SD1/SD4/SPI */
+ int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
+ uint32 data_xfer_count; /* Current register transfer size */
+ uint32 cmd53_wr_data; /* Used to pass CMD53 write data */
+ uint32 card_response; /* Used to pass back response status byte */
+ uint32 card_rsp_data; /* Used to pass back response data word */
+ uint16 card_rca; /* Current Address */
+ uint8 num_funcs; /* Supported funcs on client */
+ uint32 com_cis_ptr;
+ uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
+ void *dma_buf;
+ ulong dma_phys;
+ int r_cnt; /* rx count */
+ int t_cnt; /* tx_count */
+};
+
+/************************************************************
+ * Internal interfaces: per-port references into bcmsdspi.c
+ */
+
+/* Global message bits */
+extern uint sd_msglevel;
+
+/**************************************************************
+ * Internal interfaces: bcmsdspi.c references to per-port code
+ */
+
+/* Register mapping routines */
+extern uint32 *spi_reg_map(osl_t *osh, uintptr addr, int size);
+extern void spi_reg_unmap(osl_t *osh, uintptr addr, int size);
+
+/* Interrupt (de)registration routines */
+extern int spi_register_irq(sdioh_info_t *sd, uint irq);
+extern void spi_free_irq(uint irq, sdioh_info_t *sd);
+
+/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
+extern void spi_lock(sdioh_info_t *sd);
+extern void spi_unlock(sdioh_info_t *sd);
+
+/* Allocate/init/free per-OS private data */
+extern int spi_osinit(sdioh_info_t *sd);
+extern void spi_osfree(sdioh_info_t *sd);
+
+#endif /* _BCM_SD_SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h
new file mode 100644
index 000000000000..3624aaba5171
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h
@@ -0,0 +1,282 @@
+/*
+ * 'Standard' SDIO HOST CONTROLLER driver
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsdstd.h 623513 2016-03-08 06:22:05Z $
+ */
+#ifndef _BCM_SD_STD_H
+#define _BCM_SD_STD_H
+
+/* global msglevel for debug messages - bitvals come from sdiovar.h */
+#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+#define sd_dma(x)
+
+#define sd_sync_dma(sd, read, nbytes)
+#define sd_init_dma(sd)
+#define sd_ack_intr(sd)
+#define sd_wakeup(sd);
+/* Allocate/init/free per-OS private data */
+extern int sdstd_osinit(sdioh_info_t *sd);
+extern void sdstd_osfree(sdioh_info_t *sd);
+
+#define sd_log(x)
+
+#define SDIOH_ASSERT(exp) \
+ do { if (!(exp)) \
+ printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
+ } while (0)
+
+#define BLOCK_SIZE_4318 64
+#define BLOCK_SIZE_4328 512
+
+/* internal return code */
+#define SUCCESS 0
+#define ERROR 1
+
+/* private bus modes */
+#define SDIOH_MODE_SPI 0
+#define SDIOH_MODE_SD1 1
+#define SDIOH_MODE_SD4 2
+
+#define MAX_SLOTS 6 /* For PCI: Only 6 BAR entries => 6 slots */
+#define SDIOH_REG_WINSZ 0x100 /* Number of registers in Standard Host Controller */
+
+#define SDIOH_TYPE_ARASAN_HDK 1
+#define SDIOH_TYPE_BCM27XX 2
+#define SDIOH_TYPE_TI_PCIXX21 4 /* TI PCIxx21 Standard Host Controller */
+#define SDIOH_TYPE_RICOH_R5C822 5 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter */
+#define SDIOH_TYPE_JMICRON 6 /* JMicron Standard SDIO Host Controller */
+
+/* For linux, allow yielding for dongle */
+#define BCMSDYIELD
+
+/* Expected card status value for CMD7 */
+#define SDIOH_CMD7_EXP_STATUS 0x00001E00
+
+#define RETRIES_LARGE 100000
+#define sdstd_os_yield(sd) do {} while (0)
+#define RETRIES_SMALL 100
+
+
+#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */
+#define USE_MULTIBLOCK 0x4
+
+#define USE_FIFO 0x8 /* Fifo vs non-fifo */
+
+#define CLIENT_INTR 0x100 /* Get rid of this! */
+
+#define HC_INTR_RETUNING 0x1000
+
+
+#ifdef BCMSDIOH_TXGLOM
+/* Total glom pkt can not exceed 64K
+ * need one more slot for glom padding packet
+ */
+#define SDIOH_MAXGLOM_SIZE (40+1)
+
+typedef struct glom_buf {
+ uint32 count; /* Total number of pkts queued */
+ void *dma_buf_arr[SDIOH_MAXGLOM_SIZE]; /* Frame address */
+ ulong dma_phys_arr[SDIOH_MAXGLOM_SIZE]; /* DMA_MAPed address of frames */
+ uint16 nbytes[SDIOH_MAXGLOM_SIZE]; /* Size of each frame */
+} glom_buf_t;
+#endif
+
+struct sdioh_info {
+ uint cfg_bar; /* pci cfg address for bar */
+ uint32 caps; /* cached value of capabilities reg */
+ uint32 curr_caps; /* max current capabilities reg */
+
+ osl_t *osh; /* osh handler */
+ volatile char *mem_space; /* pci device memory va */
+ uint lockcount; /* nest count of sdstd_lock() calls */
+ bool client_intr_enabled; /* interrupt connnected flag */
+ bool intr_handler_valid; /* client driver interrupt handler valid */
+ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
+ void *intr_handler_arg; /* argument to call interrupt handler */
+ bool initialized; /* card initialized */
+ uint target_dev; /* Target device ID */
+ uint16 intmask; /* Current active interrupts */
+ void *sdos_info; /* Pointer to per-OS private data */
+ void *bcmsdh; /* handler to upper layer stack (bcmsdh) */
+
+ uint32 controller_type; /* Host controller type */
+ uint8 version; /* Host Controller Spec Compliance Version */
+ uint irq; /* Client irq */
+ int intrcount; /* Client interrupts */
+ int local_intrcount; /* Controller interrupts */
+ bool host_init_done; /* Controller initted */
+ bool card_init_done; /* Client SDIO interface initted */
+ bool polled_mode; /* polling for command completion */
+
+ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
+ /* Must be on for sd_multiblock to be effective */
+ bool use_client_ints; /* If this is false, make sure to restore */
+ /* polling hack in wl_linux.c:wl_timer() */
+ int adapter_slot; /* Maybe dealing with multiple slots/controllers */
+ int sd_mode; /* SD1/SD4/SPI */
+ int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
+ uint32 data_xfer_count; /* Current transfer */
+ uint16 card_rca; /* Current Address */
+ int8 sd_dma_mode; /* DMA Mode (PIO, SDMA, ... ADMA2) on CMD53 */
+ uint8 num_funcs; /* Supported funcs on client */
+ uint32 com_cis_ptr;
+ uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
+ void *dma_buf; /* DMA Buffer virtual address */
+ ulong dma_phys; /* DMA Buffer physical address */
+ void *adma2_dscr_buf; /* ADMA2 Descriptor Buffer virtual address */
+ ulong adma2_dscr_phys; /* ADMA2 Descriptor Buffer physical address */
+
+ /* adjustments needed to make the dma align properly */
+ void *dma_start_buf;
+ ulong dma_start_phys;
+ uint alloced_dma_size;
+ void *adma2_dscr_start_buf;
+ ulong adma2_dscr_start_phys;
+ uint alloced_adma2_dscr_size;
+
+ int r_cnt; /* rx count */
+ int t_cnt; /* tx_count */
+ bool got_hcint; /* local interrupt flag */
+ uint16 last_intrstatus; /* to cache intrstatus */
+ int host_UHSISupported; /* whether UHSI is supported for HC. */
+ int card_UHSI_voltage_Supported; /* whether UHSI is supported for
+ * Card in terms of Voltage [1.8 or 3.3].
+ */
+ int global_UHSI_Supp; /* type of UHSI support in both host and card.
+ * HOST_SDR_UNSUPP: capabilities not supported/matched
+ * HOST_SDR_12_25: SDR12 and SDR25 supported
+ * HOST_SDR_50_104_DDR: one of SDR50/SDR104 or DDR50 supptd
+ */
+ volatile int sd3_dat_state; /* data transfer state used for retuning check */
+ volatile int sd3_tun_state; /* tuning state used for retuning check */
+ bool sd3_tuning_reqd; /* tuning requirement parameter */
+ uint32 caps3; /* cached value of 32 MSbits capabilities reg (SDIO 3.0) */
+#ifdef BCMSDIOH_TXGLOM
+ glom_buf_t glom_info; /* pkt information used for glomming */
+ uint txglom_mode; /* Txglom mode: 0 - copy, 1 - multi-descriptor */
+#endif
+};
+
+#define DMA_MODE_NONE 0
+#define DMA_MODE_SDMA 1
+#define DMA_MODE_ADMA1 2
+#define DMA_MODE_ADMA2 3
+#define DMA_MODE_ADMA2_64 4
+#define DMA_MODE_AUTO -1
+
+#define USE_DMA(sd) ((bool)((sd->sd_dma_mode > 0) ? TRUE : FALSE))
+
+/* States for Tuning and corr data */
+#define TUNING_IDLE 0
+#define TUNING_START 1
+#define TUNING_START_AFTER_DAT 2
+#define TUNING_ONGOING 3
+
+#define DATA_TRANSFER_IDLE 0
+#define DATA_TRANSFER_ONGOING 1
+
+#define CHECK_TUNING_PRE_DATA 1
+#define CHECK_TUNING_POST_DATA 2
+
+
+#ifdef DHD_DEBUG
+#define SD_DHD_DISABLE_PERIODIC_TUNING 0x01
+#define SD_DHD_ENABLE_PERIODIC_TUNING 0x00
+#endif
+
+
+/************************************************************
+ * Internal interfaces: per-port references into bcmsdstd.c
+ */
+
+/* Global message bits */
+extern uint sd_msglevel;
+
+/* OS-independent interrupt handler */
+extern bool check_client_intr(sdioh_info_t *sd);
+
+/* Core interrupt enable/disable of device interrupts */
+extern void sdstd_devintr_on(sdioh_info_t *sd);
+extern void sdstd_devintr_off(sdioh_info_t *sd);
+
+/* Enable/disable interrupts for local controller events */
+extern void sdstd_intrs_on(sdioh_info_t *sd, uint16 norm, uint16 err);
+extern void sdstd_intrs_off(sdioh_info_t *sd, uint16 norm, uint16 err);
+
+/* Wait for specified interrupt and error bits to be set */
+extern void sdstd_spinbits(sdioh_info_t *sd, uint16 norm, uint16 err);
+
+
+/**************************************************************
+ * Internal interfaces: bcmsdstd.c references to per-port code
+ */
+
+/* Register mapping routines */
+extern uint32 *sdstd_reg_map(osl_t *osh, ulong addr, int size);
+extern void sdstd_reg_unmap(osl_t *osh, ulong addr, int size);
+
+/* Interrupt (de)registration routines */
+extern int sdstd_register_irq(sdioh_info_t *sd, uint irq);
+extern void sdstd_free_irq(uint irq, sdioh_info_t *sd);
+
+/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
+extern void sdstd_lock(sdioh_info_t *sd);
+extern void sdstd_unlock(sdioh_info_t *sd);
+extern void sdstd_waitlockfree(sdioh_info_t *sd);
+
+/* OS-specific wrappers for safe concurrent register access */
+extern void sdstd_os_lock_irqsave(sdioh_info_t *sd, ulong* flags);
+extern void sdstd_os_unlock_irqrestore(sdioh_info_t *sd, ulong* flags);
+
+/* OS-specific wait-for-interrupt-or-status */
+extern int sdstd_waitbits(sdioh_info_t *sd, uint16 norm, uint16 err, bool yield, uint16 *bits);
+
+/* used by bcmsdstd_linux [implemented in sdstd] */
+extern void sdstd_3_enable_retuning_int(sdioh_info_t *sd);
+extern void sdstd_3_disable_retuning_int(sdioh_info_t *sd);
+extern bool sdstd_3_is_retuning_int_set(sdioh_info_t *sd);
+extern void sdstd_3_check_and_do_tuning(sdioh_info_t *sd, int tuning_param);
+extern bool sdstd_3_check_and_set_retuning(sdioh_info_t *sd);
+extern int sdstd_3_get_tune_state(sdioh_info_t *sd);
+extern int sdstd_3_get_data_state(sdioh_info_t *sd);
+extern void sdstd_3_set_tune_state(sdioh_info_t *sd, int state);
+extern void sdstd_3_set_data_state(sdioh_info_t *sd, int state);
+extern uint8 sdstd_3_get_tuning_exp(sdioh_info_t *sd);
+extern uint32 sdstd_3_get_uhsi_clkmode(sdioh_info_t *sd);
+extern int sdstd_3_clk_tuning(sdioh_info_t *sd, uint32 sd3ClkMode);
+
+/* used by sdstd [implemented in bcmsdstd_linux/ndis] */
+extern void sdstd_3_start_tuning(sdioh_info_t *sd);
+extern void sdstd_3_osinit_tuning(sdioh_info_t *sd);
+extern void sdstd_3_osclean_tuning(sdioh_info_t *sd);
+
+extern void sdstd_enable_disable_periodic_timer(sdioh_info_t * sd, uint val);
+
+extern sdioh_info_t *sdioh_attach(osl_t *osh, void *bar0, uint irq);
+extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd);
+#endif /* _BCM_SD_STD_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmspi.h b/drivers/net/wireless/bcmdhd/include/bcmspi.h
new file mode 100644
index 000000000000..3d44d715871f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmspi.h
@@ -0,0 +1,40 @@
+/*
+ * Broadcom SPI Low-Level Hardware Driver API
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmspi.h 241182 2011-02-17 21:50:03Z $
+ */
+#ifndef _BCM_SPI_H
+#define _BCM_SPI_H
+
+extern void spi_devintr_off(sdioh_info_t *sd);
+extern void spi_devintr_on(sdioh_info_t *sd);
+extern bool spi_start_clock(sdioh_info_t *sd, uint16 new_sd_divisor);
+extern bool spi_controller_highspeed_mode(sdioh_info_t *sd, bool hsmode);
+extern bool spi_check_client_intr(sdioh_info_t *sd, int *is_dev_intr);
+extern bool spi_hw_attach(sdioh_info_t *sd);
+extern bool spi_hw_detach(sdioh_info_t *sd);
+extern void spi_sendrecv(sdioh_info_t *sd, uint8 *msg_out, uint8 *msg_in, int msglen);
+extern void spi_spinbits(sdioh_info_t *sd);
+extern void spi_waitbits(sdioh_info_t *sd, bool yield);
+
+#endif /* _BCM_SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h
new file mode 100644
index 000000000000..5483012f09fb
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h
@@ -0,0 +1,162 @@
+/*
+ * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmspibrcm.h 373331 2012-12-07 04:46:22Z $
+ */
+#ifndef _BCM_SPI_BRCM_H
+#define _BCM_SPI_BRCM_H
+
+#ifndef SPI_MAX_IOFUNCS
+/* Maximum number of I/O funcs */
+#define SPI_MAX_IOFUNCS 4
+#endif
+/* global msglevel for debug messages - bitvals come from sdiovar.h */
+
+#if defined(DHD_DEBUG)
+#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
+#define sd_trace(x) do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0)
+#define sd_info(x) do { if (sd_msglevel & SDH_INFO_VAL) printf x; } while (0)
+#define sd_debug(x) do { if (sd_msglevel & SDH_DEBUG_VAL) printf x; } while (0)
+#define sd_data(x) do { if (sd_msglevel & SDH_DATA_VAL) printf x; } while (0)
+#define sd_ctrl(x) do { if (sd_msglevel & SDH_CTRL_VAL) printf x; } while (0)
+#else
+#define sd_err(x)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+#endif
+
+#define sd_log(x)
+
+#define SDIOH_ASSERT(exp) \
+ do { if (!(exp)) \
+ printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
+ } while (0)
+
+#define BLOCK_SIZE_F1 64
+#define BLOCK_SIZE_F2 2048
+#define BLOCK_SIZE_F3 2048
+
+/* internal return code */
+#define SUCCESS 0
+#undef ERROR
+#define ERROR 1
+#define ERROR_UF 2
+#define ERROR_OF 3
+
+/* private bus modes */
+#define SDIOH_MODE_SPI 0
+
+#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */
+#define USE_MULTIBLOCK 0x4
+
+struct sdioh_info {
+ uint cfg_bar; /* pci cfg address for bar */
+ uint32 caps; /* cached value of capabilities reg */
+ void *bar0; /* BAR0 for PCI Device */
+ osl_t *osh; /* osh handler */
+ void *controller; /* Pointer to SPI Controller's private data struct */
+ uint lockcount; /* nest count of spi_lock() calls */
+ bool client_intr_enabled; /* interrupt connnected flag */
+ bool intr_handler_valid; /* client driver interrupt handler valid */
+ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
+ void *intr_handler_arg; /* argument to call interrupt handler */
+ bool initialized; /* card initialized */
+ uint32 target_dev; /* Target device ID */
+ uint32 intmask; /* Current active interrupts */
+ void *sdos_info; /* Pointer to per-OS private data */
+ uint32 controller_type; /* Host controller type */
+ uint8 version; /* Host Controller Spec Compliance Version */
+ uint irq; /* Client irq */
+ uint32 intrcount; /* Client interrupts */
+ uint32 local_intrcount; /* Controller interrupts */
+ bool host_init_done; /* Controller initted */
+ bool card_init_done; /* Client SDIO interface initted */
+ bool polled_mode; /* polling for command completion */
+
+ bool sd_use_dma; /* DMA on CMD53 */
+ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
+ /* Must be on for sd_multiblock to be effective */
+ bool use_client_ints; /* If this is false, make sure to restore */
+ /* polling hack in wl_linux.c:wl_timer() */
+ int adapter_slot; /* Maybe dealing with multiple slots/controllers */
+ int sd_mode; /* SD1/SD4/SPI */
+ int client_block_size[SPI_MAX_IOFUNCS]; /* Blocksize */
+ uint32 data_xfer_count; /* Current transfer */
+ uint16 card_rca; /* Current Address */
+ uint8 num_funcs; /* Supported funcs on client */
+ uint32 card_dstatus; /* 32bit device status */
+ uint32 com_cis_ptr;
+ uint32 func_cis_ptr[SPI_MAX_IOFUNCS];
+ void *dma_buf;
+ ulong dma_phys;
+ int r_cnt; /* rx count */
+ int t_cnt; /* tx_count */
+ uint32 wordlen; /* host processor 16/32bits */
+ uint32 prev_fun;
+ uint32 chip;
+ uint32 chiprev;
+ bool resp_delay_all;
+ bool dwordmode;
+ bool resp_delay_new;
+
+ struct spierrstats_t spierrstats;
+};
+
+/************************************************************
+ * Internal interfaces: per-port references into bcmspibrcm.c
+ */
+
+/* Global message bits */
+extern uint sd_msglevel;
+
+/**************************************************************
+ * Internal interfaces: bcmspibrcm.c references to per-port code
+ */
+
+/* Interrupt (de)registration routines */
+extern int spi_register_irq(sdioh_info_t *sd, uint irq);
+extern void spi_free_irq(uint irq, sdioh_info_t *sd);
+
+/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
+extern void spi_lock(sdioh_info_t *sd);
+extern void spi_unlock(sdioh_info_t *sd);
+
+/* Allocate/init/free per-OS private data */
+extern int spi_osinit(sdioh_info_t *sd);
+extern void spi_osfree(sdioh_info_t *sd);
+
+#define SPI_RW_FLAG_M BITFIELD_MASK(1) /* Bit [31] - R/W Command Bit */
+#define SPI_RW_FLAG_S 31
+#define SPI_ACCESS_M BITFIELD_MASK(1) /* Bit [30] - Fixed/Incr Access */
+#define SPI_ACCESS_S 30
+#define SPI_FUNCTION_M BITFIELD_MASK(2) /* Bit [29:28] - Function Number */
+#define SPI_FUNCTION_S 28
+#define SPI_REG_ADDR_M BITFIELD_MASK(17) /* Bit [27:11] - Address */
+#define SPI_REG_ADDR_S 11
+#define SPI_LEN_M BITFIELD_MASK(11) /* Bit [10:0] - Packet length */
+#define SPI_LEN_S 0
+
+#endif /* _BCM_SPI_BRCM_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h b/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h
new file mode 100644
index 000000000000..98b9a4d0ea4f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h
@@ -0,0 +1,633 @@
+/*
+ * SROM format definition.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsrom_fmt.h 427005 2013-10-02 00:15:10Z $
+ */
+
+#ifndef _bcmsrom_fmt_h_
+#define _bcmsrom_fmt_h_
+
+#define SROM_MAXREV 11 /* max revisiton supported by driver */
+
+/* Maximum srom: 6 Kilobits == 768 bytes */
+#define SROM_MAX 768
+#define SROM_MAXW 384
+#define VARS_MAX 4096
+
+/* PCI fields */
+#define PCI_F0DEVID 48
+
+
+#define SROM_WORDS 64
+
+#define SROM3_SWRGN_OFF 28 /* s/w region offset in words */
+
+#define SROM_SSID 2
+#define SROM_SVID 3
+
+#define SROM_WL1LHMAXP 29
+
+#define SROM_WL1LPAB0 30
+#define SROM_WL1LPAB1 31
+#define SROM_WL1LPAB2 32
+
+#define SROM_WL1HPAB0 33
+#define SROM_WL1HPAB1 34
+#define SROM_WL1HPAB2 35
+
+#define SROM_MACHI_IL0 36
+#define SROM_MACMID_IL0 37
+#define SROM_MACLO_IL0 38
+#define SROM_MACHI_ET0 39
+#define SROM_MACMID_ET0 40
+#define SROM_MACLO_ET0 41
+#define SROM_MACHI_ET1 42
+#define SROM_MACMID_ET1 43
+#define SROM_MACLO_ET1 44
+#define SROM3_MACHI 37
+#define SROM3_MACMID 38
+#define SROM3_MACLO 39
+
+#define SROM_BXARSSI2G 40
+#define SROM_BXARSSI5G 41
+
+#define SROM_TRI52G 42
+#define SROM_TRI5GHL 43
+
+#define SROM_RXPO52G 45
+
+#define SROM2_ENETPHY 45
+
+#define SROM_AABREV 46
+/* Fields in AABREV */
+#define SROM_BR_MASK 0x00ff
+#define SROM_CC_MASK 0x0f00
+#define SROM_CC_SHIFT 8
+#define SROM_AA0_MASK 0x3000
+#define SROM_AA0_SHIFT 12
+#define SROM_AA1_MASK 0xc000
+#define SROM_AA1_SHIFT 14
+
+#define SROM_WL0PAB0 47
+#define SROM_WL0PAB1 48
+#define SROM_WL0PAB2 49
+
+#define SROM_LEDBH10 50
+#define SROM_LEDBH32 51
+
+#define SROM_WL10MAXP 52
+
+#define SROM_WL1PAB0 53
+#define SROM_WL1PAB1 54
+#define SROM_WL1PAB2 55
+
+#define SROM_ITT 56
+
+#define SROM_BFL 57
+#define SROM_BFL2 28
+#define SROM3_BFL2 61
+
+#define SROM_AG10 58
+
+#define SROM_CCODE 59
+
+#define SROM_OPO 60
+
+#define SROM3_LEDDC 62
+
+#define SROM_CRCREV 63
+
+/* SROM Rev 4: Reallocate the software part of the srom to accomodate
+ * MIMO features. It assumes up to two PCIE functions and 440 bytes
+ * of useable srom i.e. the useable storage in chips with OTP that
+ * implements hardware redundancy.
+ */
+
+#define SROM4_WORDS 220
+
+#define SROM4_SIGN 32
+#define SROM4_SIGNATURE 0x5372
+
+#define SROM4_BREV 33
+
+#define SROM4_BFL0 34
+#define SROM4_BFL1 35
+#define SROM4_BFL2 36
+#define SROM4_BFL3 37
+#define SROM5_BFL0 37
+#define SROM5_BFL1 38
+#define SROM5_BFL2 39
+#define SROM5_BFL3 40
+
+#define SROM4_MACHI 38
+#define SROM4_MACMID 39
+#define SROM4_MACLO 40
+#define SROM5_MACHI 41
+#define SROM5_MACMID 42
+#define SROM5_MACLO 43
+
+#define SROM4_CCODE 41
+#define SROM4_REGREV 42
+#define SROM5_CCODE 34
+#define SROM5_REGREV 35
+
+#define SROM4_LEDBH10 43
+#define SROM4_LEDBH32 44
+#define SROM5_LEDBH10 59
+#define SROM5_LEDBH32 60
+
+#define SROM4_LEDDC 45
+#define SROM5_LEDDC 45
+
+#define SROM4_AA 46
+#define SROM4_AA2G_MASK 0x00ff
+#define SROM4_AA2G_SHIFT 0
+#define SROM4_AA5G_MASK 0xff00
+#define SROM4_AA5G_SHIFT 8
+
+#define SROM4_AG10 47
+#define SROM4_AG32 48
+
+#define SROM4_TXPID2G 49
+#define SROM4_TXPID5G 51
+#define SROM4_TXPID5GL 53
+#define SROM4_TXPID5GH 55
+
+#define SROM4_TXRXC 61
+#define SROM4_TXCHAIN_MASK 0x000f
+#define SROM4_TXCHAIN_SHIFT 0
+#define SROM4_RXCHAIN_MASK 0x00f0
+#define SROM4_RXCHAIN_SHIFT 4
+#define SROM4_SWITCH_MASK 0xff00
+#define SROM4_SWITCH_SHIFT 8
+
+
+/* Per-path fields */
+#define MAX_PATH_SROM 4
+#define SROM4_PATH0 64
+#define SROM4_PATH1 87
+#define SROM4_PATH2 110
+#define SROM4_PATH3 133
+
+#define SROM4_2G_ITT_MAXP 0
+#define SROM4_2G_PA 1
+#define SROM4_5G_ITT_MAXP 5
+#define SROM4_5GLH_MAXP 6
+#define SROM4_5G_PA 7
+#define SROM4_5GL_PA 11
+#define SROM4_5GH_PA 15
+
+/* Fields in the ITT_MAXP and 5GLH_MAXP words */
+#define B2G_MAXP_MASK 0xff
+#define B2G_ITT_SHIFT 8
+#define B5G_MAXP_MASK 0xff
+#define B5G_ITT_SHIFT 8
+#define B5GH_MAXP_MASK 0xff
+#define B5GL_MAXP_SHIFT 8
+
+/* All the miriad power offsets */
+#define SROM4_2G_CCKPO 156
+#define SROM4_2G_OFDMPO 157
+#define SROM4_5G_OFDMPO 159
+#define SROM4_5GL_OFDMPO 161
+#define SROM4_5GH_OFDMPO 163
+#define SROM4_2G_MCSPO 165
+#define SROM4_5G_MCSPO 173
+#define SROM4_5GL_MCSPO 181
+#define SROM4_5GH_MCSPO 189
+#define SROM4_CDDPO 197
+#define SROM4_STBCPO 198
+#define SROM4_BW40PO 199
+#define SROM4_BWDUPPO 200
+
+#define SROM4_CRCREV 219
+
+
+/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
+ * This is acombined srom for both MIMO and SISO boards, usable in
+ * the .130 4Kilobit OTP with hardware redundancy.
+ */
+
+#define SROM8_SIGN 64
+
+#define SROM8_BREV 65
+
+#define SROM8_BFL0 66
+#define SROM8_BFL1 67
+#define SROM8_BFL2 68
+#define SROM8_BFL3 69
+
+#define SROM8_MACHI 70
+#define SROM8_MACMID 71
+#define SROM8_MACLO 72
+
+#define SROM8_CCODE 73
+#define SROM8_REGREV 74
+
+#define SROM8_LEDBH10 75
+#define SROM8_LEDBH32 76
+
+#define SROM8_LEDDC 77
+
+#define SROM8_AA 78
+
+#define SROM8_AG10 79
+#define SROM8_AG32 80
+
+#define SROM8_TXRXC 81
+
+#define SROM8_BXARSSI2G 82
+#define SROM8_BXARSSI5G 83
+#define SROM8_TRI52G 84
+#define SROM8_TRI5GHL 85
+#define SROM8_RXPO52G 86
+
+#define SROM8_FEM2G 87
+#define SROM8_FEM5G 88
+#define SROM8_FEM_ANTSWLUT_MASK 0xf800
+#define SROM8_FEM_ANTSWLUT_SHIFT 11
+#define SROM8_FEM_TR_ISO_MASK 0x0700
+#define SROM8_FEM_TR_ISO_SHIFT 8
+#define SROM8_FEM_PDET_RANGE_MASK 0x00f8
+#define SROM8_FEM_PDET_RANGE_SHIFT 3
+#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006
+#define SROM8_FEM_EXTPA_GAIN_SHIFT 1
+#define SROM8_FEM_TSSIPOS_MASK 0x0001
+#define SROM8_FEM_TSSIPOS_SHIFT 0
+
+#define SROM8_THERMAL 89
+
+/* Temp sense related entries */
+#define SROM8_MPWR_RAWTS 90
+#define SROM8_TS_SLP_OPT_CORRX 91
+/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
+#define SROM8_FOC_HWIQ_IQSWP 92
+
+#define SROM8_EXTLNAGAIN 93
+
+/* Temperature delta for PHY calibration */
+#define SROM8_PHYCAL_TEMPDELTA 94
+
+/* Measured power 1 & 2, 0-13 bits at offset 95, MSB 2 bits are unused for now. */
+#define SROM8_MPWR_1_AND_2 95
+
+
+/* Per-path offsets & fields */
+#define SROM8_PATH0 96
+#define SROM8_PATH1 112
+#define SROM8_PATH2 128
+#define SROM8_PATH3 144
+
+#define SROM8_2G_ITT_MAXP 0
+#define SROM8_2G_PA 1
+#define SROM8_5G_ITT_MAXP 4
+#define SROM8_5GLH_MAXP 5
+#define SROM8_5G_PA 6
+#define SROM8_5GL_PA 9
+#define SROM8_5GH_PA 12
+
+/* All the miriad power offsets */
+#define SROM8_2G_CCKPO 160
+
+#define SROM8_2G_OFDMPO 161
+#define SROM8_5G_OFDMPO 163
+#define SROM8_5GL_OFDMPO 165
+#define SROM8_5GH_OFDMPO 167
+
+#define SROM8_2G_MCSPO 169
+#define SROM8_5G_MCSPO 177
+#define SROM8_5GL_MCSPO 185
+#define SROM8_5GH_MCSPO 193
+
+#define SROM8_CDDPO 201
+#define SROM8_STBCPO 202
+#define SROM8_BW40PO 203
+#define SROM8_BWDUPPO 204
+
+/* SISO PA parameters are in the path0 spaces */
+#define SROM8_SISO 96
+
+/* Legacy names for SISO PA paramters */
+#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP)
+#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA)
+#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1)
+#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2)
+#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP)
+#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP)
+#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA)
+#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1)
+#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2)
+#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA)
+#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1)
+#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2)
+#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA)
+#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1)
+#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2)
+
+#define SROM8_CRCREV 219
+
+/* SROM REV 9 */
+#define SROM9_2GPO_CCKBW20 160
+#define SROM9_2GPO_CCKBW20UL 161
+#define SROM9_2GPO_LOFDMBW20 162
+#define SROM9_2GPO_LOFDMBW20UL 164
+
+#define SROM9_5GLPO_LOFDMBW20 166
+#define SROM9_5GLPO_LOFDMBW20UL 168
+#define SROM9_5GMPO_LOFDMBW20 170
+#define SROM9_5GMPO_LOFDMBW20UL 172
+#define SROM9_5GHPO_LOFDMBW20 174
+#define SROM9_5GHPO_LOFDMBW20UL 176
+
+#define SROM9_2GPO_MCSBW20 178
+#define SROM9_2GPO_MCSBW20UL 180
+#define SROM9_2GPO_MCSBW40 182
+
+#define SROM9_5GLPO_MCSBW20 184
+#define SROM9_5GLPO_MCSBW20UL 186
+#define SROM9_5GLPO_MCSBW40 188
+#define SROM9_5GMPO_MCSBW20 190
+#define SROM9_5GMPO_MCSBW20UL 192
+#define SROM9_5GMPO_MCSBW40 194
+#define SROM9_5GHPO_MCSBW20 196
+#define SROM9_5GHPO_MCSBW20UL 198
+#define SROM9_5GHPO_MCSBW40 200
+
+#define SROM9_PO_MCS32 202
+#define SROM9_PO_LOFDM40DUP 203
+#define SROM8_RXGAINERR_2G 205
+#define SROM8_RXGAINERR_5GL 206
+#define SROM8_RXGAINERR_5GM 207
+#define SROM8_RXGAINERR_5GH 208
+#define SROM8_RXGAINERR_5GU 209
+#define SROM8_SUBBAND_PPR 210
+#define SROM8_PCIEINGRESS_WAR 211
+#define SROM9_SAR 212
+
+#define SROM8_NOISELVL_2G 213
+#define SROM8_NOISELVL_5GL 214
+#define SROM8_NOISELVL_5GM 215
+#define SROM8_NOISELVL_5GH 216
+#define SROM8_NOISELVL_5GU 217
+#define SROM8_NOISECALOFFSET 218
+
+#define SROM9_REV_CRC 219
+
+#define SROM10_CCKPWROFFSET 218
+#define SROM10_SIGN 219
+#define SROM10_SWCTRLMAP_2G 220
+#define SROM10_CRCREV 229
+
+#define SROM10_WORDS 230
+#define SROM10_SIGNATURE SROM4_SIGNATURE
+
+
+/* SROM REV 11 */
+#define SROM11_BREV 65
+
+#define SROM11_BFL0 66
+#define SROM11_BFL1 67
+#define SROM11_BFL2 68
+#define SROM11_BFL3 69
+#define SROM11_BFL4 70
+#define SROM11_BFL5 71
+
+#define SROM11_MACHI 72
+#define SROM11_MACMID 73
+#define SROM11_MACLO 74
+
+#define SROM11_CCODE 75
+#define SROM11_REGREV 76
+
+#define SROM11_LEDBH10 77
+#define SROM11_LEDBH32 78
+
+#define SROM11_LEDDC 79
+
+#define SROM11_AA 80
+
+#define SROM11_AGBG10 81
+#define SROM11_AGBG2A0 82
+#define SROM11_AGA21 83
+
+#define SROM11_TXRXC 84
+
+#define SROM11_FEM_CFG1 85
+#define SROM11_FEM_CFG2 86
+
+/* Masks and offsets for FEM_CFG */
+#define SROM11_FEMCTRL_MASK 0xf800
+#define SROM11_FEMCTRL_SHIFT 11
+#define SROM11_PAPDCAP_MASK 0x0400
+#define SROM11_PAPDCAP_SHIFT 10
+#define SROM11_TWORANGETSSI_MASK 0x0200
+#define SROM11_TWORANGETSSI_SHIFT 9
+#define SROM11_PDGAIN_MASK 0x01f0
+#define SROM11_PDGAIN_SHIFT 4
+#define SROM11_EPAGAIN_MASK 0x000e
+#define SROM11_EPAGAIN_SHIFT 1
+#define SROM11_TSSIPOSSLOPE_MASK 0x0001
+#define SROM11_TSSIPOSSLOPE_SHIFT 0
+#define SROM11_GAINCTRLSPH_MASK 0xf800
+#define SROM11_GAINCTRLSPH_SHIFT 11
+
+#define SROM11_THERMAL 87
+#define SROM11_MPWR_RAWTS 88
+#define SROM11_TS_SLP_OPT_CORRX 89
+#define SROM11_XTAL_FREQ 90
+#define SROM11_5GB0_4080_W0_A1 91
+#define SROM11_PHYCAL_TEMPDELTA 92
+#define SROM11_MPWR_1_AND_2 93
+#define SROM11_5GB0_4080_W1_A1 94
+#define SROM11_TSSIFLOOR_2G 95
+#define SROM11_TSSIFLOOR_5GL 96
+#define SROM11_TSSIFLOOR_5GM 97
+#define SROM11_TSSIFLOOR_5GH 98
+#define SROM11_TSSIFLOOR_5GU 99
+
+/* Masks and offsets for Terrmal parameters */
+#define SROM11_TEMPS_PERIOD_MASK 0xf0
+#define SROM11_TEMPS_PERIOD_SHIFT 4
+#define SROM11_TEMPS_HYSTERESIS_MASK 0x0f
+#define SROM11_TEMPS_HYSTERESIS_SHIFT 0
+#define SROM11_TEMPCORRX_MASK 0xfc
+#define SROM11_TEMPCORRX_SHIFT 2
+#define SROM11_TEMPSENSE_OPTION_MASK 0x3
+#define SROM11_TEMPSENSE_OPTION_SHIFT 0
+
+#define SROM11_PDOFF_2G_40M_A0_MASK 0x000f
+#define SROM11_PDOFF_2G_40M_A0_SHIFT 0
+#define SROM11_PDOFF_2G_40M_A1_MASK 0x00f0
+#define SROM11_PDOFF_2G_40M_A1_SHIFT 4
+#define SROM11_PDOFF_2G_40M_A2_MASK 0x0f00
+#define SROM11_PDOFF_2G_40M_A2_SHIFT 8
+#define SROM11_PDOFF_2G_40M_VALID_MASK 0x8000
+#define SROM11_PDOFF_2G_40M_VALID_SHIFT 15
+
+#define SROM11_PDOFF_2G_40M 100
+#define SROM11_PDOFF_40M_A0 101
+#define SROM11_PDOFF_40M_A1 102
+#define SROM11_PDOFF_40M_A2 103
+#define SROM11_5GB0_4080_W2_A1 103
+#define SROM11_PDOFF_80M_A0 104
+#define SROM11_PDOFF_80M_A1 105
+#define SROM11_PDOFF_80M_A2 106
+#define SROM11_5GB1_4080_W0_A1 106
+
+#define SROM11_SUBBAND5GVER 107
+
+/* Per-path fields and offset */
+#define MAX_PATH_SROM_11 3
+#define SROM11_PATH0 108
+#define SROM11_PATH1 128
+#define SROM11_PATH2 148
+
+#define SROM11_2G_MAXP 0
+#define SROM11_5GB1_4080_PA 0
+#define SROM11_2G_PA 1
+#define SROM11_5GB2_4080_PA 2
+#define SROM11_RXGAINS1 4
+#define SROM11_RXGAINS 5
+#define SROM11_5GB3_4080_PA 5
+#define SROM11_5GB1B0_MAXP 6
+#define SROM11_5GB3B2_MAXP 7
+#define SROM11_5GB0_PA 8
+#define SROM11_5GB1_PA 11
+#define SROM11_5GB2_PA 14
+#define SROM11_5GB3_PA 17
+
+/* Masks and offsets for rxgains */
+#define SROM11_RXGAINS5GTRELNABYPA_MASK 0x8000
+#define SROM11_RXGAINS5GTRELNABYPA_SHIFT 15
+#define SROM11_RXGAINS5GTRISOA_MASK 0x7800
+#define SROM11_RXGAINS5GTRISOA_SHIFT 11
+#define SROM11_RXGAINS5GELNAGAINA_MASK 0x0700
+#define SROM11_RXGAINS5GELNAGAINA_SHIFT 8
+#define SROM11_RXGAINS2GTRELNABYPA_MASK 0x0080
+#define SROM11_RXGAINS2GTRELNABYPA_SHIFT 7
+#define SROM11_RXGAINS2GTRISOA_MASK 0x0078
+#define SROM11_RXGAINS2GTRISOA_SHIFT 3
+#define SROM11_RXGAINS2GELNAGAINA_MASK 0x0007
+#define SROM11_RXGAINS2GELNAGAINA_SHIFT 0
+#define SROM11_RXGAINS5GHTRELNABYPA_MASK 0x8000
+#define SROM11_RXGAINS5GHTRELNABYPA_SHIFT 15
+#define SROM11_RXGAINS5GHTRISOA_MASK 0x7800
+#define SROM11_RXGAINS5GHTRISOA_SHIFT 11
+#define SROM11_RXGAINS5GHELNAGAINA_MASK 0x0700
+#define SROM11_RXGAINS5GHELNAGAINA_SHIFT 8
+#define SROM11_RXGAINS5GMTRELNABYPA_MASK 0x0080
+#define SROM11_RXGAINS5GMTRELNABYPA_SHIFT 7
+#define SROM11_RXGAINS5GMTRISOA_MASK 0x0078
+#define SROM11_RXGAINS5GMTRISOA_SHIFT 3
+#define SROM11_RXGAINS5GMELNAGAINA_MASK 0x0007
+#define SROM11_RXGAINS5GMELNAGAINA_SHIFT 0
+
+/* Power per rate */
+#define SROM11_CCKBW202GPO 168
+#define SROM11_CCKBW20UL2GPO 169
+#define SROM11_MCSBW202GPO 170
+#define SROM11_MCSBW202GPO_1 171
+#define SROM11_MCSBW402GPO 172
+#define SROM11_MCSBW402GPO_1 173
+#define SROM11_DOT11AGOFDMHRBW202GPO 174
+#define SROM11_OFDMLRBW202GPO 175
+
+#define SROM11_MCSBW205GLPO 176
+#define SROM11_MCSBW205GLPO_1 177
+#define SROM11_MCSBW405GLPO 178
+#define SROM11_MCSBW405GLPO_1 179
+#define SROM11_MCSBW805GLPO 180
+#define SROM11_MCSBW805GLPO_1 181
+#define SROM11_RPCAL_2G 182
+#define SROM11_RPCAL_5GL 183
+#define SROM11_MCSBW205GMPO 184
+#define SROM11_MCSBW205GMPO_1 185
+#define SROM11_MCSBW405GMPO 186
+#define SROM11_MCSBW405GMPO_1 187
+#define SROM11_MCSBW805GMPO 188
+#define SROM11_MCSBW805GMPO_1 189
+#define SROM11_RPCAL_5GM 190
+#define SROM11_RPCAL_5GH 191
+#define SROM11_MCSBW205GHPO 192
+#define SROM11_MCSBW205GHPO_1 193
+#define SROM11_MCSBW405GHPO 194
+#define SROM11_MCSBW405GHPO_1 195
+#define SROM11_MCSBW805GHPO 196
+#define SROM11_MCSBW805GHPO_1 197
+#define SROM11_RPCAL_5GU 198
+#define SROM11_PDOFF_2G_CCK 199
+#define SROM11_MCSLR5GLPO 200
+#define SROM11_MCSLR5GMPO 201
+#define SROM11_MCSLR5GHPO 202
+
+#define SROM11_SB20IN40HRPO 203
+#define SROM11_SB20IN80AND160HR5GLPO 204
+#define SROM11_SB40AND80HR5GLPO 205
+#define SROM11_SB20IN80AND160HR5GMPO 206
+#define SROM11_SB40AND80HR5GMPO 207
+#define SROM11_SB20IN80AND160HR5GHPO 208
+#define SROM11_SB40AND80HR5GHPO 209
+#define SROM11_SB20IN40LRPO 210
+#define SROM11_SB20IN80AND160LR5GLPO 211
+#define SROM11_SB40AND80LR5GLPO 212
+#define SROM11_TXIDXCAP2G 212
+#define SROM11_SB20IN80AND160LR5GMPO 213
+#define SROM11_SB40AND80LR5GMPO 214
+#define SROM11_TXIDXCAP5G 214
+#define SROM11_SB20IN80AND160LR5GHPO 215
+#define SROM11_SB40AND80LR5GHPO 216
+
+#define SROM11_DOT11AGDUPHRPO 217
+#define SROM11_DOT11AGDUPLRPO 218
+
+/* MISC */
+#define SROM11_PCIEINGRESS_WAR 220
+#define SROM11_SAR 221
+
+#define SROM11_NOISELVL_2G 222
+#define SROM11_NOISELVL_5GL 223
+#define SROM11_NOISELVL_5GM 224
+#define SROM11_NOISELVL_5GH 225
+#define SROM11_NOISELVL_5GU 226
+
+#define SROM11_RXGAINERR_2G 227
+#define SROM11_RXGAINERR_5GL 228
+#define SROM11_RXGAINERR_5GM 229
+#define SROM11_RXGAINERR_5GH 230
+#define SROM11_RXGAINERR_5GU 231
+
+#define SROM11_SIGN 64
+#define SROM11_CRCREV 233
+
+#define SROM11_WORDS 234
+#define SROM11_SIGNATURE 0x0634
+
+typedef struct {
+ uint8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */
+ uint8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
+ uint8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */
+ uint8 triso; /* TR switch isolation */
+ uint8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */
+} srom_fem_t;
+
+#endif /* _bcmsrom_fmt_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h b/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h
new file mode 100644
index 000000000000..12ae7284fd59
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h
@@ -0,0 +1,1014 @@
+/*
+ * Table that encodes the srom formats for PCI/PCIe NICs.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmsrom_tbl.h 427005 2013-10-02 00:15:10Z $
+ */
+
+#ifndef _bcmsrom_tbl_h_
+#define _bcmsrom_tbl_h_
+
+#include "sbpcmcia.h"
+#include "wlioctl.h"
+
+typedef struct {
+ const char *name;
+ uint32 revmask;
+ uint32 flags;
+ uint16 off;
+ uint16 mask;
+} sromvar_t;
+
+#define SRFL_MORE 1 /* value continues as described by the next entry */
+#define SRFL_NOFFS 2 /* value bits can't be all one's */
+#define SRFL_PRHEX 4 /* value is in hexdecimal format */
+#define SRFL_PRSIGN 8 /* value is in signed decimal format */
+#define SRFL_CCODE 0x10 /* value is in country code format */
+#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
+#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
+#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */
+#define SRFL_ARRAY 0x100 /* value is in an array. All elements EXCEPT FOR THE LAST
+ * ONE in the array should have this flag set.
+ */
+
+
+#define SROM_DEVID_PCIE 48
+
+/* Assumptions:
+ * - Ethernet address spans across 3 consective words
+ *
+ * Table rules:
+ * - Add multiple entries next to each other if a value spans across multiple words
+ * (even multiple fields in the same word) with each entry except the last having
+ * it's SRFL_MORE bit set.
+ * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
+ * bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
+ * - The last entry's name field must be NULL to indicate the end of the table. Other
+ * entries must have non-NULL name.
+ */
+
+static const sromvar_t pci_sromvars[] = {
+#if defined(CABLECPE)
+ {"devid", 0xffffff00, SRFL_PRHEX, PCI_F0DEVID, 0xffff},
+#elif defined(BCMPCIEDEV) && defined(BCMPCIEDEV_ENABLED)
+ {"devid", 0xffffff00, SRFL_PRHEX, SROM_DEVID_PCIE, 0xffff},
+#else
+ {"devid", 0xffffff00, SRFL_PRHEX|SRFL_NOVAR, PCI_F0DEVID, 0xffff},
+#endif
+ {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK},
+ {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
+ {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
+ {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
+ {"boardflags", 0x00000004, SRFL_PRHEX|SRFL_MORE, SROM_BFL, 0xffff},
+ {"", 0, 0, SROM_BFL2, 0xffff},
+ {"boardflags", 0x00000008, SRFL_PRHEX|SRFL_MORE, SROM_BFL, 0xffff},
+ {"", 0, 0, SROM3_BFL2, 0xffff},
+ {"boardflags", 0x00000010, SRFL_PRHEX|SRFL_MORE, SROM4_BFL0, 0xffff},
+ {"", 0, 0, SROM4_BFL1, 0xffff},
+ {"boardflags", 0x000000e0, SRFL_PRHEX|SRFL_MORE, SROM5_BFL0, 0xffff},
+ {"", 0, 0, SROM5_BFL1, 0xffff},
+ {"boardflags", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL0, 0xffff},
+ {"", 0, 0, SROM8_BFL1, 0xffff},
+ {"boardflags2", 0x00000010, SRFL_PRHEX|SRFL_MORE, SROM4_BFL2, 0xffff},
+ {"", 0, 0, SROM4_BFL3, 0xffff},
+ {"boardflags2", 0x000000e0, SRFL_PRHEX|SRFL_MORE, SROM5_BFL2, 0xffff},
+ {"", 0, 0, SROM5_BFL3, 0xffff},
+ {"boardflags2", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL2, 0xffff},
+ {"", 0, 0, SROM8_BFL3, 0xffff},
+ {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
+ {"subvid", 0xfffffffc, SRFL_PRHEX, SROM_SVID, 0xffff},
+ {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
+ {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff},
+ {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff},
+ {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff},
+ {"boardnum", 0x00000700, 0, SROM8_MACLO, 0xffff},
+ {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
+ {"regrev", 0x00000008, 0, SROM_OPO, 0xff00},
+ {"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff},
+ {"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff},
+ {"regrev", 0x00000700, 0, SROM8_REGREV, 0x00ff},
+ {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
+ {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
+ {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
+ {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
+ {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
+ {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
+ {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
+ {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
+ {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
+ {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
+ {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
+ {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
+ {"ledbh0", 0x00000700, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
+ {"ledbh1", 0x00000700, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
+ {"ledbh2", 0x00000700, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
+ {"ledbh3", 0x00000700, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
+ {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
+ {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
+ {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
+ {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff},
+ {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
+ {"pa0b0", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
+ {"pa0b1", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
+ {"pa0b2", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
+ {"pa0itssit", 0x00000700, 0, SROM8_W0_ITTMAXP, 0xff00},
+ {"pa0maxpwr", 0x00000700, 0, SROM8_W0_ITTMAXP, 0x00ff},
+ {"opo", 0x0000000c, 0, SROM_OPO, 0x00ff},
+ {"opo", 0x00000700, 0, SROM8_2G_OFDMPO, 0x00ff},
+ {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
+ {"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff},
+ {"aa2g", 0x00000700, 0, SROM8_AA, 0x00ff},
+ {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
+ {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00},
+ {"aa5g", 0x00000700, 0, SROM8_AA, 0xff00},
+ {"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff},
+ {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00},
+ {"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff},
+ {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00},
+ {"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff},
+ {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00},
+ {"ag0", 0x00000700, 0, SROM8_AG10, 0x00ff},
+ {"ag1", 0x00000700, 0, SROM8_AG10, 0xff00},
+ {"ag2", 0x00000700, 0, SROM8_AG32, 0x00ff},
+ {"ag3", 0x00000700, 0, SROM8_AG32, 0xff00},
+ {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
+ {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
+ {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
+ {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
+ {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
+ {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
+ {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
+ {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
+ {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
+ {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00},
+ {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
+ {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
+ {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
+ {"pa1b0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
+ {"pa1b1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
+ {"pa1b2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
+ {"pa1lob0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
+ {"pa1lob1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
+ {"pa1lob2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
+ {"pa1hib0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
+ {"pa1hib1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
+ {"pa1hib2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
+ {"pa1itssit", 0x00000700, 0, SROM8_W1_ITTMAXP, 0xff00},
+ {"pa1maxpwr", 0x00000700, 0, SROM8_W1_ITTMAXP, 0x00ff},
+ {"pa1lomaxpwr", 0x00000700, 0, SROM8_W1_MAXP_LCHC, 0xff00},
+ {"pa1himaxpwr", 0x00000700, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
+ {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
+ {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
+ {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
+ {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
+ {"bxa2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x1800},
+ {"rssisav2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x0700},
+ {"rssismc2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x00f0},
+ {"rssismf2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x000f},
+ {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
+ {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
+ {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
+ {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
+ {"bxa5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x1800},
+ {"rssisav5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x0700},
+ {"rssismc5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x00f0},
+ {"rssismf5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x000f},
+ {"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff},
+ {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00},
+ {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
+ {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00},
+ {"tri2g", 0x00000700, 0, SROM8_TRI52G, 0x00ff},
+ {"tri5g", 0x00000700, 0, SROM8_TRI52G, 0xff00},
+ {"tri5gl", 0x00000700, 0, SROM8_TRI5GHL, 0x00ff},
+ {"tri5gh", 0x00000700, 0, SROM8_TRI5GHL, 0xff00},
+ {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
+ {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
+ {"rxpo2g", 0x00000700, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
+ {"rxpo5g", 0x00000700, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
+ {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK},
+ {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK},
+ {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK},
+ {"txchain", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK},
+ {"rxchain", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK},
+ {"antswitch", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK},
+ {"tssipos2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK},
+ {"extpagain2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK},
+ {"pdetrange2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK},
+ {"triso2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
+ {"antswctl2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK},
+ {"tssipos5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK},
+ {"extpagain5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK},
+ {"pdetrange5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK},
+ {"triso5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
+ {"antswctl5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK},
+ {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
+ {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
+ {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
+ {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
+ {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
+ {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
+ {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
+ {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
+ {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
+ {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
+ {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
+ {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
+ {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
+ {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
+ {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
+ {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
+
+ {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
+ {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
+ {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
+ {"ccode", 0x00000700, SRFL_CCODE, SROM8_CCODE, 0xffff},
+ {"macaddr", 0x00000700, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
+ {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
+ {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
+ {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
+ {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff},
+ {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff},
+ {"leddc", 0x00000700, SRFL_NOFFS|SRFL_LEDDC, SROM8_LEDDC, 0xffff},
+ {"leddc", 0x000000e0, SRFL_NOFFS|SRFL_LEDDC, SROM5_LEDDC, 0xffff},
+ {"leddc", 0x00000010, SRFL_NOFFS|SRFL_LEDDC, SROM4_LEDDC, 0xffff},
+ {"leddc", 0x00000008, SRFL_NOFFS|SRFL_LEDDC, SROM3_LEDDC, 0xffff},
+
+ {"tempthresh", 0x00000700, 0, SROM8_THERMAL, 0xff00},
+ {"tempoffset", 0x00000700, 0, SROM8_THERMAL, 0x00ff},
+ {"rawtempsense", 0x00000700, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff},
+ {"measpower", 0x00000700, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00},
+ {"tempsense_slope", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x00ff},
+ {"tempcorrx", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00},
+ {"tempsense_option", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x0300},
+ {"freqoffset_corr", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x000f},
+ {"iqcal_swp_dis", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010},
+ {"hw_iqcal_en", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020},
+ {"elna2g", 0x00000700, 0, SROM8_EXTLNAGAIN, 0x00ff},
+ {"elna5g", 0x00000700, 0, SROM8_EXTLNAGAIN, 0xff00},
+ {"phycal_tempdelta", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff},
+ {"temps_period", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0x0f00},
+ {"temps_hysteresis", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0xf000},
+ {"measpower1", 0x00000700, SRFL_PRHEX, SROM8_MPWR_1_AND_2, 0x007f},
+ {"measpower2", 0x00000700, SRFL_PRHEX, SROM8_MPWR_1_AND_2, 0x3f80},
+
+ {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
+ {"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
+ {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
+ {"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
+ {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
+ {"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
+ {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
+ {"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
+ {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
+ {"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
+ {"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
+ {"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
+ {"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
+ {"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
+ {"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
+ {"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
+ {"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
+ {"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
+ {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
+ {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
+ {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
+ {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
+ {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
+ {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
+ {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
+ {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
+ {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
+ {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
+ {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
+ {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
+ {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
+ {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
+ {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
+ {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
+ {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
+ {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
+ {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
+ {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
+ {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
+ {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
+ {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
+ {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
+ {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
+ {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
+ {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
+ {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
+ {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
+ {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
+ {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
+ {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
+ {"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
+ {"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
+ {"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
+ {"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
+ {"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
+ {"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
+ {"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
+ {"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
+ {"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
+ {"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
+ {"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
+ {"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
+ {"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
+ {"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
+ {"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
+ {"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
+ {"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
+ {"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
+ {"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
+ {"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
+ {"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
+ {"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
+ {"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
+ {"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
+ {"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
+ {"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
+ {"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
+ {"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
+ {"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
+ {"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
+ {"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
+ {"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
+ {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff},
+ {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff},
+ {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff},
+ {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
+ {"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff},
+ {"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff},
+ {"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff},
+ {"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
+
+ /* power per rate from sromrev 9 */
+ {"cckbw202gpo", 0x00000600, 0, SROM9_2GPO_CCKBW20, 0xffff},
+ {"cckbw20ul2gpo", 0x00000600, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
+ {"legofdmbw202gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_LOFDMBW20, 0xffff},
+ {"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
+ {"legofdmbw20ul2gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL, 0xffff},
+ {"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
+ {"legofdmbw205glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_LOFDMBW20, 0xffff},
+ {"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
+ {"legofdmbw20ul5glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL, 0xffff},
+ {"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
+ {"legofdmbw205gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_LOFDMBW20, 0xffff},
+ {"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
+ {"legofdmbw20ul5gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL, 0xffff},
+ {"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
+ {"legofdmbw205ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_LOFDMBW20, 0xffff},
+ {"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
+ {"legofdmbw20ul5ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL, 0xffff},
+ {"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
+ {"mcsbw202gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff},
+ {"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
+ {"mcsbw20ul2gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff},
+ {"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
+ {"mcsbw402gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff},
+ {"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
+ {"mcsbw205glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff},
+ {"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
+ {"mcsbw20ul5glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW20UL, 0xffff},
+ {"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
+ {"mcsbw405glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff},
+ {"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
+ {"mcsbw205gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff},
+ {"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
+ {"mcsbw20ul5gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW20UL, 0xffff},
+ {"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
+ {"mcsbw405gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff},
+ {"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
+ {"mcsbw205ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff},
+ {"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
+ {"mcsbw20ul5ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW20UL, 0xffff},
+ {"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
+ {"mcsbw405ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff},
+ {"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
+ {"mcs32po", 0x00000600, 0, SROM9_PO_MCS32, 0xffff},
+ {"legofdm40duppo", 0x00000600, 0, SROM9_PO_LOFDM40DUP, 0xffff},
+ {"pcieingress_war", 0x00000700, 0, SROM8_PCIEINGRESS_WAR, 0xf},
+ {"rxgainerr2ga0", 0x00000700, 0, SROM8_RXGAINERR_2G, 0x003f},
+ {"rxgainerr2ga1", 0x00000700, 0, SROM8_RXGAINERR_2G, 0x07c0},
+ {"rxgainerr2ga2", 0x00000700, 0, SROM8_RXGAINERR_2G, 0xf800},
+ {"rxgainerr5gla0", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0x003f},
+ {"rxgainerr5gla1", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0x07c0},
+ {"rxgainerr5gla2", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0xf800},
+ {"rxgainerr5gma0", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0x003f},
+ {"rxgainerr5gma1", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0x07c0},
+ {"rxgainerr5gma2", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0xf800},
+ {"rxgainerr5gha0", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0x003f},
+ {"rxgainerr5gha1", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0x07c0},
+ {"rxgainerr5gha2", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0xf800},
+ {"rxgainerr5gua0", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0x003f},
+ {"rxgainerr5gua1", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0x07c0},
+ {"rxgainerr5gua2", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0xf800},
+ {"sar2g", 0x00000600, 0, SROM9_SAR, 0x00ff},
+ {"sar5g", 0x00000600, 0, SROM9_SAR, 0xff00},
+ {"noiselvl2ga0", 0x00000700, 0, SROM8_NOISELVL_2G, 0x001f},
+ {"noiselvl2ga1", 0x00000700, 0, SROM8_NOISELVL_2G, 0x03e0},
+ {"noiselvl2ga2", 0x00000700, 0, SROM8_NOISELVL_2G, 0x7c00},
+ {"noiselvl5gla0", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x001f},
+ {"noiselvl5gla1", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x03e0},
+ {"noiselvl5gla2", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x7c00},
+ {"noiselvl5gma0", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x001f},
+ {"noiselvl5gma1", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x03e0},
+ {"noiselvl5gma2", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x7c00},
+ {"noiselvl5gha0", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x001f},
+ {"noiselvl5gha1", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x03e0},
+ {"noiselvl5gha2", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x7c00},
+ {"noiselvl5gua0", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x001f},
+ {"noiselvl5gua1", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x03e0},
+ {"noiselvl5gua2", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x7c00},
+ {"noisecaloffset", 0x00000300, 0, SROM8_NOISECALOFFSET, 0x00ff},
+ {"noisecaloffset5g", 0x00000300, 0, SROM8_NOISECALOFFSET, 0xff00},
+ {"subband5gver", 0x00000700, 0, SROM8_SUBBAND_PPR, 0x7},
+
+ {"cckPwrOffset", 0x00000400, 0, SROM10_CCKPWROFFSET, 0xffff},
+ /* swctrlmap_2g array, note that the last element doesn't have SRFL_ARRAY flag set */
+ {"swctrlmap_2g", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G, 0xffff},
+ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 1, 0xffff},
+ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 2, 0xffff},
+ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 3, 0xffff},
+ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 4, 0xffff},
+ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 5, 0xffff},
+ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 6, 0xffff},
+ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 7, 0xffff},
+ {"", 0x00000400, SRFL_PRHEX, SROM10_SWCTRLMAP_2G + 8, 0xffff},
+
+ /* sromrev 11 */
+ {"boardflags3", 0xfffff800, SRFL_PRHEX|SRFL_MORE, SROM11_BFL4, 0xffff},
+ {"", 0, 0, SROM11_BFL5, 0xffff},
+ {"boardnum", 0xfffff800, 0, SROM11_MACLO, 0xffff},
+ {"macaddr", 0xfffff800, SRFL_ETHADDR, SROM11_MACHI, 0xffff},
+ {"ccode", 0xfffff800, SRFL_CCODE, SROM11_CCODE, 0xffff},
+ {"regrev", 0xfffff800, 0, SROM11_REGREV, 0x00ff},
+ {"ledbh0", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH10, 0x00ff},
+ {"ledbh1", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH10, 0xff00},
+ {"ledbh2", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH32, 0x00ff},
+ {"ledbh3", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH32, 0xff00},
+ {"leddc", 0xfffff800, SRFL_NOFFS|SRFL_LEDDC, SROM11_LEDDC, 0xffff},
+ {"aa2g", 0xfffff800, 0, SROM11_AA, 0x00ff},
+ {"aa5g", 0xfffff800, 0, SROM11_AA, 0xff00},
+ {"agbg0", 0xfffff800, 0, SROM11_AGBG10, 0xff00},
+ {"agbg1", 0xfffff800, 0, SROM11_AGBG10, 0x00ff},
+ {"agbg2", 0xfffff800, 0, SROM11_AGBG2A0, 0xff00},
+ {"aga0", 0xfffff800, 0, SROM11_AGBG2A0, 0x00ff},
+ {"aga1", 0xfffff800, 0, SROM11_AGA21, 0xff00},
+ {"aga2", 0xfffff800, 0, SROM11_AGA21, 0x00ff},
+ {"txchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_TXCHAIN_MASK},
+ {"rxchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_RXCHAIN_MASK},
+ {"antswitch", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_SWITCH_MASK},
+
+ {"tssiposslope2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0001},
+ {"epagain2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x000e},
+ {"pdgain2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x01f0},
+ {"tworangetssi2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0200},
+ {"papdcap2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0400},
+ {"femctrl", 0xfffff800, 0, SROM11_FEM_CFG1, 0xf800},
+
+ {"tssiposslope5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0001},
+ {"epagain5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x000e},
+ {"pdgain5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x01f0},
+ {"tworangetssi5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0200},
+ {"papdcap5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0400},
+ {"gainctrlsph", 0xfffff800, 0, SROM11_FEM_CFG2, 0xf800},
+
+ {"tempthresh", 0xfffff800, 0, SROM11_THERMAL, 0xff00},
+ {"tempoffset", 0xfffff800, 0, SROM11_THERMAL, 0x00ff},
+ {"rawtempsense", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_RAWTS, 0x01ff},
+ {"measpower", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_RAWTS, 0xfe00},
+ {"tempsense_slope", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x00ff},
+ {"tempcorrx", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0xfc00},
+ {"tempsense_option", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x0300},
+ {"xtalfreq", 0xfffff800, 0, SROM11_XTAL_FREQ, 0xffff},
+ /* Special PA Params for 4350 5G Band, 40/80 MHz BW Ant #1 */
+ {"pa5gbw4080a1", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W0_A1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W1_A1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W2_A1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_4080_W0_A1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_4080_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_4080_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_4080_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_4080_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX, SROM11_PATH2 + SROM11_5GB3_4080_PA + 2, 0xffff},
+ {"phycal_tempdelta", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x00ff},
+ {"temps_period", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x0f00},
+ {"temps_hysteresis", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0xf000},
+ {"measpower1", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x007f},
+ {"measpower2", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x3f80},
+ {"tssifloor2g", 0xfffff800, SRFL_PRHEX, SROM11_TSSIFLOOR_2G, 0x03ff},
+ {"tssifloor5g", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GL, 0x03ff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GM, 0x03ff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GH, 0x03ff},
+ {"", 0xfffff800, SRFL_PRHEX, SROM11_TSSIFLOOR_5GU, 0x03ff},
+ {"pdoffset2g40ma0", 0xfffff800, 0, SROM11_PDOFF_2G_40M, 0x000f},
+ {"pdoffset2g40ma1", 0xfffff800, 0, SROM11_PDOFF_2G_40M, 0x00f0},
+ {"pdoffset2g40ma2", 0xfffff800, 0, SROM11_PDOFF_2G_40M, 0x0f00},
+ {"pdoffset2g40mvalid", 0xfffff800, 0, SROM11_PDOFF_2G_40M, 0x8000},
+ {"pdoffset40ma0", 0xfffff800, 0, SROM11_PDOFF_40M_A0, 0xffff},
+ {"pdoffset40ma1", 0xfffff800, 0, SROM11_PDOFF_40M_A1, 0xffff},
+ {"pdoffset40ma2", 0xfffff800, 0, SROM11_PDOFF_40M_A2, 0xffff},
+ {"pdoffset80ma0", 0xfffff800, 0, SROM11_PDOFF_80M_A0, 0xffff},
+ {"pdoffset80ma1", 0xfffff800, 0, SROM11_PDOFF_80M_A1, 0xffff},
+ {"pdoffset80ma2", 0xfffff800, 0, SROM11_PDOFF_80M_A2, 0xffff},
+
+ {"subband5gver", 0xfffff800, SRFL_PRHEX, SROM11_SUBBAND5GVER, 0xffff},
+ {"paparambwver", 0xfffff800, 0, SROM11_MCSLR5GLPO, 0xf000},
+ /* Special PA Params for 4350 5G Band, 40/80 MHz BW Ant #0 */
+ {"pa5gbw4080a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 +SROM11_5GB0_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX, SROM11_PATH2 + SROM11_5GB3_PA + 2, 0xffff},
+ /* Special PA Params for 4335 5G Band, 40 MHz BW */
+ {"pa5gbw40a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB3_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB3_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX, SROM11_PATH1 + SROM11_5GB3_PA + 2, 0xffff},
+ /* Special PA Params for 4335 5G Band, 80 MHz BW */
+ {"pa5gbw80a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX, SROM11_PATH2 + SROM11_5GB3_PA + 2, 0xffff},
+ /* Special PA Params for 4335 2G Band, CCK */
+ {"pa2gccka0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_2G_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_2G_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX, SROM11_PATH1 + SROM11_2G_PA + 2, 0xffff},
+
+ /* power per rate */
+ {"cckbw202gpo", 0xfffff800, 0, SROM11_CCKBW202GPO, 0xffff},
+ {"cckbw20ul2gpo", 0xfffff800, 0, SROM11_CCKBW20UL2GPO, 0xffff},
+ {"mcsbw202gpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW202GPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW202GPO_1, 0xffff},
+ {"mcsbw402gpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW402GPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW402GPO_1, 0xffff},
+ {"dot11agofdmhrbw202gpo", 0xfffff800, 0, SROM11_DOT11AGOFDMHRBW202GPO, 0xffff},
+ {"ofdmlrbw202gpo", 0xfffff800, 0, SROM11_OFDMLRBW202GPO, 0xffff},
+ {"mcsbw205glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GLPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW205GLPO_1, 0xffff},
+ {"mcsbw405glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GLPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW405GLPO_1, 0xffff},
+ {"mcsbw805glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GLPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW805GLPO_1, 0xffff},
+ {"mcsbw205gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GMPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW205GMPO_1, 0xffff},
+ {"mcsbw405gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GMPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW405GMPO_1, 0xffff},
+ {"mcsbw805gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GMPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW805GMPO_1, 0xffff},
+ {"mcsbw205ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GHPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW205GHPO_1, 0xffff},
+ {"mcsbw405ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GHPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW405GHPO_1, 0xffff},
+ {"mcsbw805ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GHPO, 0xffff},
+ {"", 0xfffff800, 0, SROM11_MCSBW805GHPO_1, 0xffff},
+ {"mcslr5glpo", 0xfffff800, 0, SROM11_MCSLR5GLPO, 0x0fff},
+ {"mcslr5gmpo", 0xfffff800, 0, SROM11_MCSLR5GMPO, 0xffff},
+ {"mcslr5ghpo", 0xfffff800, 0, SROM11_MCSLR5GHPO, 0xffff},
+ {"sb20in40hrpo", 0xfffff800, 0, SROM11_SB20IN40HRPO, 0xffff},
+ {"sb20in80and160hr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GLPO, 0xffff},
+ {"sb40and80hr5glpo", 0xfffff800, 0, SROM11_SB40AND80HR5GLPO, 0xffff},
+ {"sb20in80and160hr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GMPO, 0xffff},
+ {"sb40and80hr5gmpo", 0xfffff800, 0, SROM11_SB40AND80HR5GMPO, 0xffff},
+ {"sb20in80and160hr5ghpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GHPO, 0xffff},
+ {"sb40and80hr5ghpo", 0xfffff800, 0, SROM11_SB40AND80HR5GHPO, 0xffff},
+ {"sb20in40lrpo", 0xfffff800, 0, SROM11_SB20IN40LRPO, 0xffff},
+ {"sb20in80and160lr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GLPO, 0xffff},
+ {"sb40and80lr5glpo", 0xfffff800, 0, SROM11_SB40AND80LR5GLPO, 0xffff},
+ {"sb20in80and160lr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GMPO, 0xffff},
+ {"sb40and80lr5gmpo", 0xfffff800, 0, SROM11_SB40AND80LR5GMPO, 0xffff},
+ {"sb20in80and160lr5ghpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GHPO, 0xffff},
+ {"sb40and80lr5ghpo", 0xfffff800, 0, SROM11_SB40AND80LR5GHPO, 0xffff},
+ {"dot11agduphrpo", 0xfffff800, 0, SROM11_DOT11AGDUPHRPO, 0xffff},
+ {"dot11agduplrpo", 0xfffff800, 0, SROM11_DOT11AGDUPLRPO, 0xffff},
+
+ /* Misc */
+ {"sar2g", 0xfffff800, 0, SROM11_SAR, 0x00ff},
+ {"sar5g", 0xfffff800, 0, SROM11_SAR, 0xff00},
+
+ {"noiselvl2ga0", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x001f},
+ {"noiselvl2ga1", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x03e0},
+ {"noiselvl2ga2", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x7c00},
+ {"noiselvl5ga0", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GL, 0x001f},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GM, 0x001f},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GH, 0x001f},
+ {"", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x001f},
+ {"noiselvl5ga1", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GL, 0x03e0},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GM, 0x03e0},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GH, 0x03e0},
+ {"", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x03e0},
+ {"noiselvl5ga2", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GL, 0x7c00},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GM, 0x7c00},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_NOISELVL_5GH, 0x7c00},
+ {"", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x7c00},
+
+ {"rxgainerr2ga0", 0xfffff800, 0, SROM11_RXGAINERR_2G, 0x003f},
+ {"rxgainerr2ga1", 0xfffff800, 0, SROM11_RXGAINERR_2G, 0x07c0},
+ {"rxgainerr2ga2", 0xfffff800, 0, SROM11_RXGAINERR_2G, 0xf800},
+ {"rxgainerr5ga0", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GL, 0x003f},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GM, 0x003f},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GH, 0x003f},
+ {"", 0xfffff800, 0, SROM11_RXGAINERR_5GU, 0x003f},
+ {"rxgainerr5ga1", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GL, 0x07c0},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GM, 0x07c0},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GH, 0x07c0},
+ {"", 0xfffff800, 0, SROM11_RXGAINERR_5GU, 0x07c0},
+ {"rxgainerr5ga2", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GL, 0xf800},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GM, 0xf800},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GH, 0xf800},
+ {"", 0xfffff800, 0, SROM11_RXGAINERR_5GU, 0xf800},
+ {"rpcal2g", 0xfffff800, 0, SROM11_RPCAL_2G, 0xffff},
+ {"rpcal5gb0", 0xfffff800, 0, SROM11_RPCAL_5GL, 0xffff},
+ {"rpcal5gb1", 0xfffff800, 0, SROM11_RPCAL_5GM, 0xffff},
+ {"rpcal5gb2", 0xfffff800, 0, SROM11_RPCAL_5GH, 0xffff},
+ {"rpcal5gb3", 0xfffff800, 0, SROM11_RPCAL_5GU, 0xffff},
+ {"txidxcap2g", 0xfffff800, 0, SROM11_TXIDXCAP2G, 0x0ff0},
+ {"txidxcap5g", 0xfffff800, 0, SROM11_TXIDXCAP5G, 0x0ff0},
+ {"pdoffsetcckma0", 0xfffff800, 0, SROM11_PDOFF_2G_CCK, 0x000f},
+ {"pdoffsetcckma1", 0xfffff800, 0, SROM11_PDOFF_2G_CCK, 0x00f0},
+ {"pdoffsetcckma2", 0xfffff800, 0, SROM11_PDOFF_2G_CCK, 0x0f00},
+ {NULL, 0, 0, 0, 0}
+};
+
+static const sromvar_t perpath_pci_sromvars[] = {
+ {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
+ {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
+ {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
+ {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
+ {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
+ {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
+ {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
+ {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
+ {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
+ {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
+ {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
+ {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
+ {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
+ {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
+ {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
+ {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff},
+ {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff},
+ {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff},
+ {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
+ {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff},
+ {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff},
+ {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff},
+ {"maxp2ga", 0x00000700, 0, SROM8_2G_ITT_MAXP, 0x00ff},
+ {"itt2ga", 0x00000700, 0, SROM8_2G_ITT_MAXP, 0xff00},
+ {"itt5ga", 0x00000700, 0, SROM8_5G_ITT_MAXP, 0xff00},
+ {"pa2gw0a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
+ {"pa2gw1a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
+ {"pa2gw2a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
+ {"maxp5ga", 0x00000700, 0, SROM8_5G_ITT_MAXP, 0x00ff},
+ {"maxp5gha", 0x00000700, 0, SROM8_5GLH_MAXP, 0x00ff},
+ {"maxp5gla", 0x00000700, 0, SROM8_5GLH_MAXP, 0xff00},
+ {"pa5gw0a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
+ {"pa5gw1a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
+ {"pa5gw2a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
+ {"pa5glw0a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
+ {"pa5glw1a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff},
+ {"pa5glw2a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff},
+ {"pa5ghw0a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
+ {"pa5ghw1a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff},
+ {"pa5ghw2a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff},
+
+ /* sromrev 11 */
+ {"maxp2ga", 0xfffff800, 0, SROM11_2G_MAXP, 0x00ff},
+ {"pa2ga", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX, SROM11_2G_PA + 2, 0xffff},
+ {"rxgains5gmelnagaina", 0xfffff800, 0, SROM11_RXGAINS1, 0x0007},
+ {"rxgains5gmtrisoa", 0xfffff800, 0, SROM11_RXGAINS1, 0x0078},
+ {"rxgains5gmtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS1, 0x0080},
+ {"rxgains5ghelnagaina", 0xfffff800, 0, SROM11_RXGAINS1, 0x0700},
+ {"rxgains5ghtrisoa", 0xfffff800, 0, SROM11_RXGAINS1, 0x7800},
+ {"rxgains5ghtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS1, 0x8000},
+ {"rxgains2gelnagaina", 0xfffff800, 0, SROM11_RXGAINS, 0x0007},
+ {"rxgains2gtrisoa", 0xfffff800, 0, SROM11_RXGAINS, 0x0078},
+ {"rxgains2gtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS, 0x0080},
+ {"rxgains5gelnagaina", 0xfffff800, 0, SROM11_RXGAINS, 0x0700},
+ {"rxgains5gtrisoa", 0xfffff800, 0, SROM11_RXGAINS, 0x7800},
+ {"rxgains5gtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS, 0x8000},
+ {"maxp5ga", 0xfffff800, SRFL_ARRAY, SROM11_5GB1B0_MAXP, 0x00ff},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_5GB1B0_MAXP, 0xff00},
+ {"", 0xfffff800, SRFL_ARRAY, SROM11_5GB3B2_MAXP, 0x00ff},
+ {"", 0xfffff800, 0, SROM11_5GB3B2_MAXP, 0xff00},
+ {"pa5ga", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 2, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA + 1, 0xffff},
+ {"", 0xfffff800, SRFL_PRHEX, SROM11_5GB3_PA + 2, 0xffff},
+
+ {NULL, 0, 0, 0, 0}
+};
+
+#if !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP))
+#define PHY_TYPE_HT 7 /* HT-Phy value */
+#define PHY_TYPE_N 4 /* N-Phy value */
+#define PHY_TYPE_LP 5 /* LP-Phy value */
+#endif /* !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */
+#if !defined(PHY_TYPE_AC)
+#define PHY_TYPE_AC 11 /* AC-Phy value */
+#endif /* !defined(PHY_TYPE_AC) */
+#if !defined(PHY_TYPE_NULL)
+#define PHY_TYPE_NULL 0xf /* Invalid Phy value */
+#endif /* !defined(PHY_TYPE_NULL) */
+
+typedef struct {
+ uint16 phy_type;
+ uint16 bandrange;
+ uint16 chain;
+ const char *vars;
+} pavars_t;
+
+static const pavars_t pavars[] = {
+ /* HTPHY */
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 2, "pa2gw0a2 pa2gw1a2 pa2gw2a2"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 2, "pa5glw0a2 pa5glw1a2 pa5glw2a2"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 2, "pa5gw0a2 pa5gw1a2 pa5gw2a2"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 0, "pa5gw0a3 pa5gw1a3 pa5gw2a3"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 1, "pa5glw0a3 pa5glw1a3 pa5glw2a3"},
+ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 2, "pa5ghw0a3 pa5ghw1a3 pa5ghw2a3"},
+ /* NPHY */
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND0, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND0, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND1, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND1, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
+ /* LPPHY */
+ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"},
+ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"},
+ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"},
+ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"},
+ /* ACPHY */
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 0, "pa2ga0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 1, "pa2ga1"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 2, "pa2ga2"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 0, "pa5ga0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 1, "pa5ga1"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 2, "pa5ga2"},
+ {PHY_TYPE_NULL, 0, 0, ""}
+};
+
+/* pavars table when paparambwver is 1 */
+static const pavars_t pavars_bwver_1[] = {
+ /* ACPHY */
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 0, "pa2ga0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gccka0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 1, "pa2ga2"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 0, "pa5ga0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 1, "pa5gbw40a0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 2, "pa5gbw80a0"},
+ {PHY_TYPE_NULL, 0, 0, ""}
+};
+
+/* pavars table when paparambwver is 2 */
+static const pavars_t pavars_bwver_2[] = {
+ /* ACPHY */
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 0, "pa2ga0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 1, "pa2ga1"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 0, "pa5ga0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 1, "pa5ga1"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 2, "pa5gbw4080a0"},
+ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 3, "pa5gbw4080a1"},
+ {PHY_TYPE_NULL, 0, 0, ""}
+};
+
+typedef struct {
+ uint16 phy_type;
+ uint16 bandrange;
+ const char *vars;
+} povars_t;
+
+static const povars_t povars[] = {
+ /* NPHY */
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 "
+ "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 "
+ "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 "
+ "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"},
+ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 "
+ "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"},
+ {PHY_TYPE_NULL, 0, ""}
+};
+
+typedef struct {
+ uint8 tag; /* Broadcom subtag name */
+ uint32 revmask; /* Supported cis_sromrev */
+ uint8 len; /* Length field of the tuple, note that it includes the
+ * subtag name (1 byte): 1 + tuple content length
+ */
+ const char *params;
+} cis_tuple_t;
+
+#define OTP_RAW (0xff - 1) /* Reserved tuple number for wrvar Raw input */
+#define OTP_VERS_1 (0xff - 2) /* CISTPL_VERS_1 */
+#define OTP_MANFID (0xff - 3) /* CISTPL_MANFID */
+#define OTP_RAW1 (0xff - 4) /* Like RAW, but comes first */
+
+static const cis_tuple_t cis_hnbuvars[] = {
+ {OTP_RAW1, 0xffffffff, 0, ""}, /* special case */
+ {OTP_VERS_1, 0xffffffff, 0, "smanf sproductname"}, /* special case (non BRCM tuple) */
+ {OTP_MANFID, 0xffffffff, 4, "2manfid 2prodid"}, /* special case (non BRCM tuple) */
+ /* Unified OTP: tupple to embed USB manfid inside SDIO CIS */
+ {HNBU_UMANFID, 0xffffffff, 8, "8usbmanfid"},
+ {HNBU_SROMREV, 0xffffffff, 2, "1sromrev"},
+ /* NOTE: subdevid is also written to boardtype.
+ * Need to write HNBU_BOARDTYPE to change it if it is different.
+ */
+ {HNBU_CHIPID, 0xffffffff, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"},
+ {HNBU_BOARDREV, 0xffffffff, 3, "2boardrev"},
+ {HNBU_PAPARMS, 0xffffffff, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"},
+ {HNBU_AA, 0xffffffff, 3, "1aa2g 1aa5g"},
+ {HNBU_AA, 0xffffffff, 3, "1aa0 1aa1"}, /* backward compatibility */
+ {HNBU_AG, 0xffffffff, 5, "1ag0 1ag1 1ag2 1ag3"},
+ {HNBU_BOARDFLAGS, 0xffffffff, 13, "4boardflags 4boardflags2 4boardflags3"},
+ {HNBU_LEDS, 0xffffffff, 17, "1ledbh0 1ledbh1 1ledbh2 1ledbh3 1ledbh4 1ledbh5 "
+ "1ledbh6 1ledbh7 1ledbh8 1ledbh9 1ledbh10 1ledbh11 1ledbh12 1ledbh13 1ledbh14 1ledbh15"},
+ {HNBU_CCODE, 0xffffffff, 4, "2ccode 1cctl"},
+ {HNBU_CCKPO, 0xffffffff, 3, "2cckpo"},
+ {HNBU_OFDMPO, 0xffffffff, 5, "4ofdmpo"},
+ {HNBU_PAPARMS5G, 0xffffffff, 23, "2pa1b0 2pa1b1 2pa1b2 2pa1lob0 2pa1lob1 2pa1lob2 "
+ "2pa1hib0 2pa1hib1 2pa1hib2 1pa1itssit "
+ "1pa1maxpwr 1pa1lomaxpwr 1pa1himaxpwr"},
+ {HNBU_RDLID, 0xffffffff, 3, "2rdlid"},
+ {HNBU_RSSISMBXA2G, 0xffffffff, 3, "0rssismf2g 0rssismc2g "
+ "0rssisav2g 0bxa2g"}, /* special case */
+ {HNBU_RSSISMBXA5G, 0xffffffff, 3, "0rssismf5g 0rssismc5g "
+ "0rssisav5g 0bxa5g"}, /* special case */
+ {HNBU_XTALFREQ, 0xffffffff, 5, "4xtalfreq"},
+ {HNBU_TRI2G, 0xffffffff, 2, "1tri2g"},
+ {HNBU_TRI5G, 0xffffffff, 4, "1tri5gl 1tri5g 1tri5gh"},
+ {HNBU_RXPO2G, 0xffffffff, 2, "1rxpo2g"},
+ {HNBU_RXPO5G, 0xffffffff, 2, "1rxpo5g"},
+ {HNBU_BOARDNUM, 0xffffffff, 3, "2boardnum"},
+ {HNBU_MACADDR, 0xffffffff, 7, "6macaddr"}, /* special case */
+ {HNBU_RDLSN, 0xffffffff, 3, "2rdlsn"},
+ {HNBU_BOARDTYPE, 0xffffffff, 3, "2boardtype"},
+ {HNBU_LEDDC, 0xffffffff, 3, "2leddc"},
+ {HNBU_RDLRNDIS, 0xffffffff, 2, "1rdlndis"},
+ {HNBU_CHAINSWITCH, 0xffffffff, 5, "1txchain 1rxchain 2antswitch"},
+ {HNBU_REGREV, 0xffffffff, 2, "1regrev"},
+ {HNBU_FEM, 0x000007fe, 5, "0antswctl2g 0triso2g 0pdetrange2g 0extpagain2g "
+ "0tssipos2g 0antswctl5g 0triso5g 0pdetrange5g 0extpagain5g 0tssipos5g"}, /* special case */
+ {HNBU_PAPARMS_C0, 0x000007fe, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 "
+ "2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 2pa5gw1a0 2pa5gw2a0 "
+ "2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 2pa5ghw1a0 2pa5ghw2a0"},
+ {HNBU_PAPARMS_C1, 0x000007fe, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 "
+ "2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 2pa5gw1a1 2pa5gw2a1 "
+ "2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 2pa5ghw1a1 2pa5ghw2a1"},
+ {HNBU_PO_CCKOFDM, 0xffffffff, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo "
+ "4ofdm5ghpo"},
+ {HNBU_PO_MCS2G, 0xffffffff, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 "
+ "2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"},
+ {HNBU_PO_MCS5GM, 0xffffffff, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 "
+ "2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"},
+ {HNBU_PO_MCS5GLH, 0xffffffff, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 "
+ "2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 "
+ "2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 "
+ "2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"},
+ {HNBU_CCKFILTTYPE, 0xffffffff, 2, "1cckdigfilttype"},
+ {HNBU_PO_CDD, 0xffffffff, 3, "2cddpo"},
+ {HNBU_PO_STBC, 0xffffffff, 3, "2stbcpo"},
+ {HNBU_PO_40M, 0xffffffff, 3, "2bw40po"},
+ {HNBU_PO_40MDUP, 0xffffffff, 3, "2bwduppo"},
+ {HNBU_RDLRWU, 0xffffffff, 2, "1rdlrwu"},
+ {HNBU_WPS, 0xffffffff, 3, "1wpsgpio 1wpsled"},
+ {HNBU_USBFS, 0xffffffff, 2, "1usbfs"},
+ {HNBU_ELNA2G, 0xffffffff, 2, "1elna2g"},
+ {HNBU_ELNA5G, 0xffffffff, 2, "1elna5g"},
+ {HNBU_CUSTOM1, 0xffffffff, 5, "4customvar1"},
+ {OTP_RAW, 0xffffffff, 0, ""}, /* special case */
+ {HNBU_OFDMPO5G, 0xffffffff, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"},
+ {HNBU_USBEPNUM, 0xffffffff, 3, "2usbepnum"},
+ {HNBU_CCKBW202GPO, 0xffffffff, 5, "2cckbw202gpo 2cckbw20ul2gpo"},
+ {HNBU_LEGOFDMBW202GPO, 0xffffffff, 9, "4legofdmbw202gpo 4legofdmbw20ul2gpo"},
+ {HNBU_LEGOFDMBW205GPO, 0xffffffff, 25, "4legofdmbw205glpo 4legofdmbw20ul5glpo "
+ "4legofdmbw205gmpo 4legofdmbw20ul5gmpo 4legofdmbw205ghpo 4legofdmbw20ul5ghpo"},
+ {HNBU_MCS2GPO, 0xffffffff, 13, "4mcsbw202gpo 4mcsbw20ul2gpo 4mcsbw402gpo"},
+ {HNBU_MCS5GLPO, 0xffffffff, 13, "4mcsbw205glpo 4mcsbw20ul5glpo 4mcsbw405glpo"},
+ {HNBU_MCS5GMPO, 0xffffffff, 13, "4mcsbw205gmpo 4mcsbw20ul5gmpo 4mcsbw405gmpo"},
+ {HNBU_MCS5GHPO, 0xffffffff, 13, "4mcsbw205ghpo 4mcsbw20ul5ghpo 4mcsbw405ghpo"},
+ {HNBU_MCS32PO, 0xffffffff, 3, "2mcs32po"},
+ {HNBU_LEG40DUPPO, 0xffffffff, 3, "2legofdm40duppo"},
+ {HNBU_TEMPTHRESH, 0xffffffff, 7, "1tempthresh 0temps_period 0temps_hysteresis "
+ "1tempoffset 1tempsense_slope 0tempcorrx 0tempsense_option "
+ "1phycal_tempdelta"}, /* special case */
+ {HNBU_MUXENAB, 0xffffffff, 2, "1muxenab"},
+ {HNBU_FEM_CFG, 0xfffff800, 5, "0femctrl 0papdcap2g 0tworangetssi2g 0pdgain2g "
+ "0epagain2g 0tssiposslope2g 0gainctrlsph 0papdcap5g 0tworangetssi5g 0pdgain5g 0epagain5g "
+ "0tssiposslope5g"}, /* special case */
+ {HNBU_ACPA_C0, 0xfffff800, 39, "2subband5gver 2maxp2ga0 2*3pa2ga0 "
+ "1*4maxp5ga0 2*12pa5ga0"},
+ {HNBU_ACPA_C1, 0xfffff800, 37, "2maxp2ga1 2*3pa2ga1 1*4maxp5ga1 2*12pa5ga1"},
+ {HNBU_ACPA_C2, 0xfffff800, 37, "2maxp2ga2 2*3pa2ga2 1*4maxp5ga2 2*12pa5ga2"},
+ {HNBU_MEAS_PWR, 0xfffff800, 5, "1measpower 1measpower1 1measpower2 2rawtempsense"},
+ {HNBU_PDOFF, 0xfffff800, 13, "2pdoffset40ma0 2pdoffset40ma1 2pdoffset40ma2 "
+ "2pdoffset80ma0 2pdoffset80ma1 2pdoffset80ma2"},
+ {HNBU_ACPPR_2GPO, 0xfffff800, 5, "2dot11agofdmhrbw202gpo 2ofdmlrbw202gpo"},
+ {HNBU_ACPPR_5GPO, 0xfffff800, 31, "4mcsbw805glpo 4mcsbw1605glpo 4mcsbw805gmpo "
+ "4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5glpo 2mcslr5gmpo 2mcslr5ghpo"},
+ {HNBU_ACPPR_SBPO, 0xfffff800, 33, "2sb20in40hrpo 2sb20in80and160hr5glpo "
+ "2sb40and80hr5glpo 2sb20in80and160hr5gmpo 2sb40and80hr5gmpo 2sb20in80and160hr5ghpo "
+ "2sb40and80hr5ghpo 2sb20in40lrpo 2sb20in80and160lr5glpo 2sb40and80lr5glpo "
+ "2sb20in80and160lr5gmpo 2sb40and80lr5gmpo 2sb20in80and160lr5ghpo 2sb40and80lr5ghpo "
+ "2dot11agduphrpo 2dot11agduplrpo"},
+ {HNBU_NOISELVL, 0xfffff800, 16, "1noiselvl2ga0 1noiselvl2ga1 1noiselvl2ga2 "
+ "1*4noiselvl5ga0 1*4noiselvl5ga1 1*4noiselvl5ga2"},
+ {HNBU_RXGAIN_ERR, 0xfffff800, 16, "1rxgainerr2ga0 1rxgainerr2ga1 1rxgainerr2ga2 "
+ "1*4rxgainerr5ga0 1*4rxgainerr5ga1 1*4rxgainerr5ga2"},
+ {HNBU_AGBGA, 0xfffff800, 7, "1agbg0 1agbg1 1agbg2 1aga0 1aga1 1aga2"},
+ {HNBU_UUID, 0xffffffff, 17, "16uuid"},
+ {HNBU_WOWLGPIO, 0xffffffff, 2, "1wowl_gpio"},
+ {HNBU_ACRXGAINS_C0, 0xfffff800, 5, "0rxgains5gtrelnabypa0 0rxgains5gtrisoa0 "
+ "0rxgains5gelnagaina0 0rxgains2gtrelnabypa0 0rxgains2gtrisoa0 0rxgains2gelnagaina0 "
+ "0rxgains5ghtrelnabypa0 0rxgains5ghtrisoa0 0rxgains5ghelnagaina0 0rxgains5gmtrelnabypa0 "
+ "0rxgains5gmtrisoa0 0rxgains5gmelnagaina0"}, /* special case */
+ {HNBU_ACRXGAINS_C1, 0xfffff800, 5, "0rxgains5gtrelnabypa1 0rxgains5gtrisoa1 "
+ "0rxgains5gelnagaina1 0rxgains2gtrelnabypa1 0rxgains2gtrisoa1 0rxgains2gelnagaina1 "
+ "0rxgains5ghtrelnabypa1 0rxgains5ghtrisoa1 0rxgains5ghelnagaina1 0rxgains5gmtrelnabypa1 "
+ "0rxgains5gmtrisoa1 0rxgains5gmelnagaina1"}, /* special case */
+ {HNBU_ACRXGAINS_C2, 0xfffff800, 5, "0rxgains5gtrelnabypa2 0rxgains5gtrisoa2 "
+ "0rxgains5gelnagaina2 0rxgains2gtrelnabypa2 0rxgains2gtrisoa2 0rxgains2gelnagaina2 "
+ "0rxgains5ghtrelnabypa2 0rxgains5ghtrisoa2 0rxgains5ghelnagaina2 0rxgains5gmtrelnabypa2 "
+ "0rxgains5gmtrisoa2 0rxgains5gmelnagaina2"}, /* special case */
+ {HNBU_TXDUTY, 0xfffff800, 9, "2tx_duty_cycle_ofdm_40_5g "
+ "2tx_duty_cycle_thresh_40_5g 2tx_duty_cycle_ofdm_80_5g 2tx_duty_cycle_thresh_80_5g"},
+ {HNBU_PDOFF_2G, 0xfffff800, 3, "0pdoffset2g40ma0 0pdoffset2g40ma1 "
+ "0pdoffset2g40ma2 0pdoffset2g40mvalid"},
+ {HNBU_ACPA_CCK, 0xfffff800, 7, "2*3pa2gccka0"},
+ {HNBU_ACPA_40, 0xfffff800, 25, "2*12pa5gbw40a0"},
+ {HNBU_ACPA_80, 0xfffff800, 25, "2*12pa5gbw80a0"},
+ {HNBU_ACPA_4080, 0xfffff800, 49, "2*12pa5gbw4080a0 2*12pa5gbw4080a1"},
+ {HNBU_SUBBAND5GVER, 0xfffff800, 3, "2subband5gver"},
+ {HNBU_PAPARAMBWVER, 0xfffff800, 2, "1paparambwver"},
+ {0xFF, 0xffffffff, 0, ""}
+};
+
+#endif /* _bcmsrom_tbl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h
new file mode 100644
index 000000000000..add3f252b28e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/bcmutils.h
@@ -0,0 +1,1204 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmutils.h 490613 2014-07-11 05:23:34Z $
+ */
+
+#ifndef _bcmutils_h_
+#define _bcmutils_h_
+
+#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src))
+#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count))
+#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef PKTQ_LOG
+#include <wlioctl.h>
+#endif
+
+/* ctype replacement */
+#define _BCM_U 0x01 /* upper */
+#define _BCM_L 0x02 /* lower */
+#define _BCM_D 0x04 /* digit */
+#define _BCM_C 0x08 /* cntrl */
+#define _BCM_P 0x10 /* punct */
+#define _BCM_S 0x20 /* white space (space/lf/tab) */
+#define _BCM_X 0x40 /* hex digit */
+#define _BCM_SP 0x80 /* hard space (0x20) */
+
+extern const unsigned char bcm_ctype[];
+#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)])
+
+#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0)
+#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0)
+#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0)
+#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0)
+#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0)
+#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0)
+#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0)
+#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0)
+#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0)
+#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
+#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c))
+
+/* Buffer structure for collecting string-formatted data
+* using bcm_bprintf() API.
+* Use bcm_binit() to initialize before use
+*/
+
+struct bcmstrbuf {
+ char *buf; /* pointer to current position in origbuf */
+ unsigned int size; /* current (residual) size in bytes */
+ char *origbuf; /* unmodified pointer to orignal buffer */
+ unsigned int origsize; /* unmodified orignal buffer size in bytes */
+};
+
+/* ** driver-only section ** */
+#ifdef BCMDRIVER
+#include <osl.h>
+
+#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */
+
+/*
+ * Spin at most 'us' microseconds while 'exp' is true.
+ * Caller should explicitly test 'exp' when this completes
+ * and take appropriate error action if 'exp' is still true.
+ */
+#ifndef SPINWAIT_POLL_PERIOD
+#define SPINWAIT_POLL_PERIOD 10
+#endif
+
+#define SPINWAIT(exp, us) { \
+ uint countdown = (us) + (SPINWAIT_POLL_PERIOD - 1); \
+ while ((exp) && (countdown >= SPINWAIT_POLL_PERIOD)) { \
+ OSL_DELAY(SPINWAIT_POLL_PERIOD); \
+ countdown -= SPINWAIT_POLL_PERIOD; \
+ } \
+}
+
+/* osl multi-precedence packet queue */
+#define PKTQ_LEN_MAX 0xFFFF /* Max uint16 65535 packets */
+#ifndef PKTQ_LEN_DEFAULT
+#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */
+#endif
+#ifndef PKTQ_MAX_PREC
+#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */
+#endif
+
+typedef struct pktq_prec {
+ void *head; /* first packet to dequeue */
+ void *tail; /* last packet to dequeue */
+ uint16 len; /* number of queued packets */
+ uint16 max; /* maximum number of queued packets */
+} pktq_prec_t;
+
+#ifdef PKTQ_LOG
+typedef struct {
+ uint32 requested; /* packets requested to be stored */
+ uint32 stored; /* packets stored */
+ uint32 saved; /* packets saved,
+ because a lowest priority queue has given away one packet
+ */
+ uint32 selfsaved; /* packets saved,
+ because an older packet from the same queue has been dropped
+ */
+ uint32 full_dropped; /* packets dropped,
+ because pktq is full with higher precedence packets
+ */
+ uint32 dropped; /* packets dropped because pktq per that precedence is full */
+ uint32 sacrificed; /* packets dropped,
+ in order to save one from a queue of a highest priority
+ */
+ uint32 busy; /* packets droped because of hardware/transmission error */
+ uint32 retry; /* packets re-sent because they were not received */
+ uint32 ps_retry; /* packets retried again prior to moving power save mode */
+ uint32 suppress; /* packets which were suppressed and not transmitted */
+ uint32 retry_drop; /* packets finally dropped after retry limit */
+ uint32 max_avail; /* the high-water mark of the queue capacity for packets -
+ goes to zero as queue fills
+ */
+ uint32 max_used; /* the high-water mark of the queue utilisation for packets -
+ increases with use ('inverse' of max_avail)
+ */
+ uint32 queue_capacity; /* the maximum capacity of the queue */
+ uint32 rtsfail; /* count of rts attempts that failed to receive cts */
+ uint32 acked; /* count of packets sent (acked) successfully */
+ uint32 txrate_succ; /* running total of phy rate of packets sent successfully */
+ uint32 txrate_main; /* running totoal of primary phy rate of all packets */
+ uint32 throughput; /* actual data transferred successfully */
+ uint32 airtime; /* cumulative total medium access delay in useconds */
+ uint32 _logtime; /* timestamp of last counter clear */
+} pktq_counters_t;
+
+typedef struct {
+ uint32 _prec_log;
+ pktq_counters_t* _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */
+} pktq_log_t;
+#endif /* PKTQ_LOG */
+
+
+#define PKTQ_COMMON \
+ uint16 num_prec; /* number of precedences in use */ \
+ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ \
+ uint16 max; /* total max packets */ \
+ uint16 len; /* total number of packets */
+
+/* multi-priority pkt queue */
+struct pktq {
+ PKTQ_COMMON
+ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
+ struct pktq_prec q[PKTQ_MAX_PREC];
+#ifdef PKTQ_LOG
+ pktq_log_t* pktqlog;
+#endif
+};
+
+/* simple, non-priority pkt queue */
+struct spktq {
+ PKTQ_COMMON
+ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
+ struct pktq_prec q[1];
+};
+
+#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
+
+/* fn(pkt, arg). return true if pkt belongs to if */
+typedef bool (*ifpkt_cb_t)(void*, int);
+
+#ifdef BCMPKTPOOL
+#define POOL_ENAB(pool) ((pool) && (pool)->inited)
+#define SHARED_POOL (pktpool_shared)
+#else /* BCMPKTPOOL */
+#define POOL_ENAB(bus) 0
+#define SHARED_POOL ((struct pktpool *)NULL)
+#endif /* BCMPKTPOOL */
+
+#ifdef BCMFRAGPOOL
+#define SHARED_FRAG_POOL (pktpool_shared_lfrag)
+#endif
+#define SHARED_RXFRAG_POOL (pktpool_shared_rxlfrag)
+
+
+#ifndef PKTPOOL_LEN_MAX
+#define PKTPOOL_LEN_MAX 40
+#endif /* PKTPOOL_LEN_MAX */
+#define PKTPOOL_CB_MAX 3
+
+struct pktpool;
+typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg);
+typedef struct {
+ pktpool_cb_t cb;
+ void *arg;
+} pktpool_cbinfo_t;
+/* call back fn extension to populate host address in pool pkt */
+typedef int (*pktpool_cb_extn_t)(struct pktpool *pool, void *arg, void* pkt);
+typedef struct {
+ pktpool_cb_extn_t cb;
+ void *arg;
+} pktpool_cbextn_info_t;
+
+
+#ifdef BCMDBG_POOL
+/* pkt pool debug states */
+#define POOL_IDLE 0
+#define POOL_RXFILL 1
+#define POOL_RXDH 2
+#define POOL_RXD11 3
+#define POOL_TXDH 4
+#define POOL_TXD11 5
+#define POOL_AMPDU 6
+#define POOL_TXENQ 7
+
+typedef struct {
+ void *p;
+ uint32 cycles;
+ uint32 dur;
+} pktpool_dbg_t;
+
+typedef struct {
+ uint8 txdh; /* tx to host */
+ uint8 txd11; /* tx to d11 */
+ uint8 enq; /* waiting in q */
+ uint8 rxdh; /* rx from host */
+ uint8 rxd11; /* rx from d11 */
+ uint8 rxfill; /* dma_rxfill */
+ uint8 idle; /* avail in pool */
+} pktpool_stats_t;
+#endif /* BCMDBG_POOL */
+
+typedef struct pktpool {
+ bool inited; /* pktpool_init was successful */
+ uint8 type; /* type of lbuf: basic, frag, etc */
+ uint8 id; /* pktpool ID: index in registry */
+ bool istx; /* direction: transmit or receive data path */
+
+ void * freelist; /* free list: see PKTNEXTFREE(), PKTSETNEXTFREE() */
+ uint16 avail; /* number of packets in pool's free list */
+ uint16 len; /* number of packets managed by pool */
+ uint16 maxlen; /* maximum size of pool <= PKTPOOL_LEN_MAX */
+ uint16 plen; /* size of pkt buffer, excluding lbuf|lbuf_frag */
+
+ bool empty;
+ uint8 cbtoggle;
+ uint8 cbcnt;
+ uint8 ecbcnt;
+ bool emptycb_disable;
+ pktpool_cbinfo_t *availcb_excl;
+ pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX];
+ pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX];
+ pktpool_cbextn_info_t cbext;
+#ifdef BCMDBG_POOL
+ uint8 dbg_cbcnt;
+ pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX];
+ uint16 dbg_qlen;
+ pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1];
+#endif
+} pktpool_t;
+
+extern pktpool_t *pktpool_shared;
+#ifdef BCMFRAGPOOL
+extern pktpool_t *pktpool_shared_lfrag;
+#endif
+extern pktpool_t *pktpool_shared_rxlfrag;
+
+/* Incarnate a pktpool registry. On success returns total_pools. */
+extern int pktpool_attach(osl_t *osh, uint32 total_pools);
+extern int pktpool_dettach(osl_t *osh); /* Relinquish registry */
+
+extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx, uint8 type);
+extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp);
+extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal);
+extern void* pktpool_get(pktpool_t *pktp);
+extern void pktpool_free(pktpool_t *pktp, void *p);
+extern int pktpool_add(pktpool_t *pktp, void *p);
+extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp);
+extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb);
+extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
+extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
+extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen);
+extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen);
+extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable);
+extern bool pktpool_emptycb_disabled(pktpool_t *pktp);
+int pktpool_hostaddr_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg);
+#define POOLPTR(pp) ((pktpool_t *)(pp))
+#define POOLID(pp) (POOLPTR(pp)->id)
+
+#define POOLSETID(pp, ppid) (POOLPTR(pp)->id = (ppid))
+
+#define pktpool_len(pp) (POOLPTR(pp)->len)
+#define pktpool_avail(pp) (POOLPTR(pp)->avail)
+#define pktpool_plen(pp) (POOLPTR(pp)->plen)
+#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen)
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * A pool ID is assigned with a pkt pool during pool initialization. This is
+ * done by maintaining a registry of all initialized pools, and the registry
+ * index at which the pool is registered is used as the pool's unique ID.
+ * ID 0 is reserved and is used to signify an invalid pool ID.
+ * All packets henceforth allocated from a pool will be tagged with the pool's
+ * unique ID. Packets allocated from the heap will use the reserved ID = 0.
+ * Packets with non-zero pool id signify that they were allocated from a pool.
+ * A maximum of 15 pools are supported, allowing a 4bit pool ID to be used
+ * in place of a 32bit pool pointer in each packet.
+ * ----------------------------------------------------------------------------
+ */
+#define PKTPOOL_INVALID_ID (0)
+#define PKTPOOL_MAXIMUM_ID (15)
+
+/* Registry of pktpool(s) */
+extern pktpool_t *pktpools_registry[PKTPOOL_MAXIMUM_ID + 1];
+
+/* Pool ID to/from Pool Pointer converters */
+#define PKTPOOL_ID2PTR(id) (pktpools_registry[id])
+#define PKTPOOL_PTR2ID(pp) (POOLID(pp))
+
+
+#ifdef BCMDBG_POOL
+extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
+extern int pktpool_start_trigger(pktpool_t *pktp, void *p);
+extern int pktpool_dbg_dump(pktpool_t *pktp);
+extern int pktpool_dbg_notify(pktpool_t *pktp);
+extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats);
+#endif /* BCMDBG_POOL */
+
+/* forward definition of ether_addr structure used by some function prototypes */
+
+struct ether_addr;
+
+extern int ether_isbcast(const void *ea);
+extern int ether_isnulladdr(const void *ea);
+
+/* operations on a specific precedence in packet queue */
+
+#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max))
+#define pktq_pmax(pq, prec) ((pq)->q[prec].max)
+#define pktq_plen(pq, prec) ((pq)->q[prec].len)
+#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len)
+#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max)
+#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0)
+
+#define pktq_ppeek(pq, prec) ((pq)->q[prec].head)
+#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail)
+
+extern void *pktq_penq(struct pktq *pq, int prec, void *p);
+extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
+extern void *pktq_pdeq(struct pktq *pq, int prec);
+extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
+extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg);
+extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
+/* Empty the queue at particular precedence level */
+extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir,
+ ifpkt_cb_t fn, int arg);
+/* Remove a specified packet from its queue */
+extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
+
+/* operations on a set of precedences in packet queue */
+
+extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
+extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
+extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
+
+/* operations on packet queue as a whole */
+
+#define pktq_len(pq) ((int)(pq)->len)
+#define pktq_max(pq) ((int)(pq)->max)
+#define pktq_avail(pq) ((int)((pq)->max - (pq)->len))
+#define pktq_full(pq) ((pq)->len >= (pq)->max)
+#define pktq_empty(pq) ((pq)->len == 0)
+
+/* operations for single precedence queues */
+#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p))
+#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p))
+#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0)
+#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0)
+#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len)
+
+extern void pktq_init(struct pktq *pq, int num_prec, int max_len);
+extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len);
+
+/* prec_out may be NULL if caller is not interested in return value */
+extern void *pktq_deq(struct pktq *pq, int *prec_out);
+extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
+extern void *pktq_peek(struct pktq *pq, int *prec_out);
+extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
+extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg);
+
+/* externs */
+/* packet */
+extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf);
+extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf);
+extern uint pkttotlen(osl_t *osh, void *p);
+extern void *pktlast(osl_t *osh, void *p);
+extern uint pktsegcnt(osl_t *osh, void *p);
+extern uint pktsegcnt_war(osl_t *osh, void *p);
+extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset);
+extern void *pktoffset(osl_t *osh, void *p, uint offset);
+
+/* Get priority from a packet and pass it back in scb (or equiv) */
+#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */
+#define PKTPRIO_VLAN 0x200 /* VLAN prio found */
+#define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */
+#define PKTPRIO_DSCP 0x800 /* DSCP prio found */
+
+/* DSCP type definitions (RFC4594) */
+/* AF1x: High-Throughput Data (RFC2597) */
+#define DSCP_AF11 0x0A
+#define DSCP_AF12 0x0C
+#define DSCP_AF13 0x0E
+/* AF2x: Low-Latency Data (RFC2597) */
+#define DSCP_AF21 0x12
+#define DSCP_AF22 0x14
+#define DSCP_AF23 0x16
+/* AF3x: Multimedia Streaming (RFC2597) */
+#define DSCP_AF31 0x1A
+#define DSCP_AF32 0x1C
+#define DSCP_AF33 0x1E
+/* EF: Telephony (RFC3246) */
+#define DSCP_EF 0x2E
+
+extern uint pktsetprio(void *pkt, bool update_vtag);
+
+/* string */
+extern int bcm_atoi(const char *s);
+extern ulong bcm_strtoul(const char *cp, char **endp, uint base);
+extern char *bcmstrstr(const char *haystack, const char *needle);
+extern char *bcmstrcat(char *dest, const char *src);
+extern char *bcmstrncat(char *dest, const char *src, uint size);
+extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen);
+char* bcmstrtok(char **string, const char *delimiters, char *tokdelim);
+int bcmstricmp(const char *s1, const char *s2);
+int bcmstrnicmp(const char* s1, const char* s2, int cnt);
+
+
+/* ethernet address */
+extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf);
+extern int bcm_ether_atoe(const char *p, struct ether_addr *ea);
+
+/* ip address */
+struct ipv4_addr;
+extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf);
+extern char *bcm_ipv6_ntoa(void *ipv6, char *buf);
+extern int bcm_atoipv4(const char *p, struct ipv4_addr *ip);
+
+/* delay */
+extern void bcm_mdelay(uint ms);
+/* variable access */
+#define NVRAM_RECLAIM_CHECK(name)
+
+extern char *getvar(char *vars, const char *name);
+extern int getintvar(char *vars, const char *name);
+extern int getintvararray(char *vars, const char *name, int index);
+extern int getintvararraysize(char *vars, const char *name);
+extern uint getgpiopin(char *vars, char *pin_name, uint def_pin);
+#define bcm_perf_enable()
+#define bcmstats(fmt)
+#define bcmlog(fmt, a1, a2)
+#define bcmdumplog(buf, size) *buf = '\0'
+#define bcmdumplogent(buf, idx) -1
+
+#define TSF_TICKS_PER_MS 1000
+
+#define bcmtslog(tstamp, fmt, a1, a2)
+#define bcmprinttslogs()
+#define bcmprinttstamp(us)
+#define bcmdumptslog(buf, size)
+
+extern char *bcm_nvram_vars(uint *length);
+extern int bcm_nvram_cache(void *sih);
+
+/* Support for sharing code across in-driver iovar implementations.
+ * The intent is that a driver use this structure to map iovar names
+ * to its (private) iovar identifiers, and the lookup function to
+ * find the entry. Macros are provided to map ids and get/set actions
+ * into a single number space for a switch statement.
+ */
+
+/* iovar structure */
+typedef struct bcm_iovar {
+ const char *name; /* name for lookup and display */
+ uint16 varid; /* id for switch */
+ uint16 flags; /* driver-specific flag bits */
+ uint16 type; /* base type of argument */
+ uint16 minlen; /* min length for buffer vars */
+} bcm_iovar_t;
+
+/* varid definitions are per-driver, may use these get/set bits */
+
+/* IOVar action bits for id mapping */
+#define IOV_GET 0 /* Get an iovar */
+#define IOV_SET 1 /* Set an iovar */
+
+/* Varid to actionid mapping */
+#define IOV_GVAL(id) ((id) * 2)
+#define IOV_SVAL(id) ((id) * 2 + IOV_SET)
+#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET)
+#define IOV_ID(actionid) (actionid >> 1)
+
+/* flags are per-driver based on driver attributes */
+
+extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name);
+extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set);
+#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
+ defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
+extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len);
+#endif
+#endif /* BCMDRIVER */
+
+/* Base type definitions */
+#define IOVT_VOID 0 /* no value (implictly set only) */
+#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */
+#define IOVT_INT8 2 /* integer values are range-checked */
+#define IOVT_UINT8 3 /* unsigned int 8 bits */
+#define IOVT_INT16 4 /* int 16 bits */
+#define IOVT_UINT16 5 /* unsigned int 16 bits */
+#define IOVT_INT32 6 /* int 32 bits */
+#define IOVT_UINT32 7 /* unsigned int 32 bits */
+#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */
+#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER)
+
+/* Initializer for IOV type strings */
+#define BCM_IOV_TYPE_INIT { \
+ "void", \
+ "bool", \
+ "int8", \
+ "uint8", \
+ "int16", \
+ "uint16", \
+ "int32", \
+ "uint32", \
+ "buffer", \
+ "" }
+
+#define BCM_IOVT_IS_INT(type) (\
+ (type == IOVT_BOOL) || \
+ (type == IOVT_INT8) || \
+ (type == IOVT_UINT8) || \
+ (type == IOVT_INT16) || \
+ (type == IOVT_UINT16) || \
+ (type == IOVT_INT32) || \
+ (type == IOVT_UINT32))
+
+/* ** driver/apps-shared section ** */
+
+#define BCME_STRLEN 64 /* Max string length for BCM errors */
+#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST))
+
+
+/*
+ * error codes could be added but the defined ones shouldn't be changed/deleted
+ * these error codes are exposed to the user code
+ * when ever a new error code is added to this list
+ * please update errorstring table with the related error string and
+ * update osl files with os specific errorcode map
+*/
+
+#define BCME_OK 0 /* Success */
+#define BCME_ERROR -1 /* Error generic */
+#define BCME_BADARG -2 /* Bad Argument */
+#define BCME_BADOPTION -3 /* Bad option */
+#define BCME_NOTUP -4 /* Not up */
+#define BCME_NOTDOWN -5 /* Not down */
+#define BCME_NOTAP -6 /* Not AP */
+#define BCME_NOTSTA -7 /* Not STA */
+#define BCME_BADKEYIDX -8 /* BAD Key Index */
+#define BCME_RADIOOFF -9 /* Radio Off */
+#define BCME_NOTBANDLOCKED -10 /* Not band locked */
+#define BCME_NOCLK -11 /* No Clock */
+#define BCME_BADRATESET -12 /* BAD Rate valueset */
+#define BCME_BADBAND -13 /* BAD Band */
+#define BCME_BUFTOOSHORT -14 /* Buffer too short */
+#define BCME_BUFTOOLONG -15 /* Buffer too long */
+#define BCME_BUSY -16 /* Busy */
+#define BCME_NOTASSOCIATED -17 /* Not Associated */
+#define BCME_BADSSIDLEN -18 /* Bad SSID len */
+#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */
+#define BCME_BADCHAN -20 /* Bad Channel */
+#define BCME_BADADDR -21 /* Bad Address */
+#define BCME_NORESOURCE -22 /* Not Enough Resources */
+#define BCME_UNSUPPORTED -23 /* Unsupported */
+#define BCME_BADLEN -24 /* Bad length */
+#define BCME_NOTREADY -25 /* Not Ready */
+#define BCME_EPERM -26 /* Not Permitted */
+#define BCME_NOMEM -27 /* No Memory */
+#define BCME_ASSOCIATED -28 /* Associated */
+#define BCME_RANGE -29 /* Not In Range */
+#define BCME_NOTFOUND -30 /* Not Found */
+#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */
+#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */
+#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */
+#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */
+#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */
+#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */
+#define BCME_VERSION -37 /* Incorrect version */
+#define BCME_TXFAIL -38 /* TX failure */
+#define BCME_RXFAIL -39 /* RX failure */
+#define BCME_NODEVICE -40 /* Device not present */
+#define BCME_NMODE_DISABLED -41 /* NMODE disabled */
+#define BCME_NONRESIDENT -42 /* access to nonresident overlay */
+#define BCME_SCANREJECT -43 /* reject scan request */
+#define BCME_USAGE_ERROR -44 /* WLCMD usage error */
+#define BCME_IOCTL_ERROR -45 /* WLCMD ioctl error */
+#define BCME_SERIAL_PORT_ERR -46 /* RWL serial port error */
+#define BCME_DISABLED -47 /* Disabled in this build */
+#define BCME_DECERR -48 /* Decrypt error */
+#define BCME_ENCERR -49 /* Encrypt error */
+#define BCME_MICERR -50 /* Integrity/MIC error */
+#define BCME_REPLAY -51 /* Replay */
+#define BCME_IE_NOTFOUND -52 /* IE not found */
+#define BCME_LAST BCME_IE_NOTFOUND
+
+#define BCME_NOTENABLED BCME_DISABLED
+
+/* These are collection of BCME Error strings */
+#define BCMERRSTRINGTABLE { \
+ "OK", \
+ "Undefined error", \
+ "Bad Argument", \
+ "Bad Option", \
+ "Not up", \
+ "Not down", \
+ "Not AP", \
+ "Not STA", \
+ "Bad Key Index", \
+ "Radio Off", \
+ "Not band locked", \
+ "No clock", \
+ "Bad Rate valueset", \
+ "Bad Band", \
+ "Buffer too short", \
+ "Buffer too long", \
+ "Busy", \
+ "Not Associated", \
+ "Bad SSID len", \
+ "Out of Range Channel", \
+ "Bad Channel", \
+ "Bad Address", \
+ "Not Enough Resources", \
+ "Unsupported", \
+ "Bad length", \
+ "Not Ready", \
+ "Not Permitted", \
+ "No Memory", \
+ "Associated", \
+ "Not In Range", \
+ "Not Found", \
+ "WME Not Enabled", \
+ "TSPEC Not Found", \
+ "ACM Not Supported", \
+ "Not WME Association", \
+ "SDIO Bus Error", \
+ "Dongle Not Accessible", \
+ "Incorrect version", \
+ "TX Failure", \
+ "RX Failure", \
+ "Device Not Present", \
+ "NMODE Disabled", \
+ "Nonresident overlay access", \
+ "Scan Rejected", \
+ "WLCMD usage error", \
+ "WLCMD ioctl error", \
+ "RWL serial port error", \
+ "Disabled", \
+ "Decrypt error", \
+ "Encrypt error", \
+ "MIC error", \
+ "Replay", \
+ "IE not found", \
+}
+
+#ifndef ABS
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+#endif /* ABS */
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+/* limit to [min, max] */
+#ifndef LIMIT_TO_RANGE
+#define LIMIT_TO_RANGE(x, min, max) \
+ ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
+#endif /* LIMIT_TO_RANGE */
+
+/* limit to max */
+#ifndef LIMIT_TO_MAX
+#define LIMIT_TO_MAX(x, max) \
+ (((x) > (max) ? (max) : (x)))
+#endif /* LIMIT_TO_MAX */
+
+/* limit to min */
+#ifndef LIMIT_TO_MIN
+#define LIMIT_TO_MIN(x, min) \
+ (((x) < (min) ? (min) : (x)))
+#endif /* LIMIT_TO_MIN */
+
+#define DELTA(curr, prev) ((curr) > (prev) ? ((curr) - (prev)) : \
+ (0xffffffff - (prev) + (curr) + 1))
+#define CEIL(x, y) (((x) + ((y) - 1)) / (y))
+#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#define ROUNDDN(p, align) ((p) & ~((align) - 1))
+#define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0)
+#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \
+ & ~((boundary) - 1))
+#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \
+ & ~((boundary) - 1))
+#define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0)
+#define VALID_MASK(mask) !((mask) & ((mask) + 1))
+
+#ifndef OFFSETOF
+#ifdef __ARMCC_VERSION
+/*
+ * The ARM RVCT compiler complains when using OFFSETOF where a constant
+ * expression is expected, such as an initializer for a static object.
+ * offsetof from the runtime library doesn't have that problem.
+ */
+#include <stddef.h>
+#define OFFSETOF(type, member) offsetof(type, member)
+#else
+# if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 8))
+/* GCC 4.8+ complains when using our OFFSETOF macro in array length declarations. */
+# define OFFSETOF(type, member) __builtin_offsetof(type, member)
+# else
+# define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member)
+# endif /* GCC 4.8 or newer */
+#endif /* __ARMCC_VERSION */
+#endif /* OFFSETOF */
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
+#ifndef ARRAYLAST /* returns pointer to last array element */
+#define ARRAYLAST(a) (&a[ARRAYSIZE(a)-1])
+#endif
+
+/* Reference a function; used to prevent a static function from being optimized out */
+extern void *_bcmutils_dummy_fn;
+#define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f))
+
+/* bit map related macros */
+#ifndef setbit
+#ifndef NBBY /* the BSD family defines NBBY */
+#define NBBY 8 /* 8 bits per byte */
+#endif /* #ifndef NBBY */
+#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
+extern void setbit(void *array, uint bit);
+extern void clrbit(void *array, uint bit);
+extern bool isset(const void *array, uint bit);
+extern bool isclr(const void *array, uint bit);
+#else
+#define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY))
+#define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY)))
+#define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY)))
+#define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0)
+#endif
+#endif /* setbit */
+
+#define isbitset(a, i) (((a) & (1 << (i))) != 0)
+
+#define NBITS(type) (sizeof(type) * 8)
+#define NBITVAL(nbits) (1 << (nbits))
+#define MAXBITVAL(nbits) ((1 << (nbits)) - 1)
+#define NBITMASK(nbits) MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8)
+
+extern void bcm_bitprint32(const uint32 u32);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Multiword map of 2bits, nibbles
+ * setbit2 setbit4 (void *ptr, uint32 ix, uint32 val)
+ * getbit2 getbit4 (void *ptr, uint32 ix)
+ * ----------------------------------------------------------------------------
+ */
+
+#define DECLARE_MAP_API(NB, RSH, LSH, OFF, MSK) \
+static INLINE void setbit##NB(void *ptr, uint32 ix, uint32 val) \
+{ \
+ uint32 *addr = (uint32 *)ptr; \
+ uint32 *a = addr + (ix >> RSH); /* (ix / 2^RSH) */ \
+ uint32 pos = (ix & OFF) << LSH; /* (ix % 2^RSH) * 2^LSH */ \
+ uint32 mask = (MSK << pos); \
+ uint32 tmp = *a & ~mask; \
+ *a = tmp | (val << pos); \
+} \
+static INLINE uint32 getbit##NB(void *ptr, uint32 ix) \
+{ \
+ uint32 *addr = (uint32 *)ptr; \
+ uint32 *a = addr + (ix >> RSH); \
+ uint32 pos = (ix & OFF) << LSH; \
+ return ((*a >> pos) & MSK); \
+}
+
+DECLARE_MAP_API(2, 4, 1, 15U, 0x0003) /* setbit2() and getbit2() */
+DECLARE_MAP_API(4, 3, 2, 7U, 0x000F) /* setbit4() and getbit4() */
+
+
+/* basic mux operation - can be optimized on several architectures */
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+/* modulo inc/dec - assumes x E [0, bound - 1] */
+#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+/* modulo inc/dec, bound = 2^k */
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
+
+/* modulo add/sub - assumes x, y E [0, bound - 1] */
+#define MODADD(x, y, bound) \
+ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
+#define MODSUB(x, y, bound) \
+ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
+
+/* module add/sub, bound = 2^k */
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
+/* crc defines */
+#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */
+#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */
+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
+#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */
+#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */
+
+/* use for direct output of MAC address in printf etc */
+#define MACF "%02x:%02x:%02x:%02x:%02x:%02x"
+#define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \
+ ((struct ether_addr *) (ea))->octet[1], \
+ ((struct ether_addr *) (ea))->octet[2], \
+ ((struct ether_addr *) (ea))->octet[3], \
+ ((struct ether_addr *) (ea))->octet[4], \
+ ((struct ether_addr *) (ea))->octet[5]
+
+#define ETHER_TO_MACF(ea) (ea).octet[0], \
+ (ea).octet[1], \
+ (ea).octet[2], \
+ (ea).octet[3], \
+ (ea).octet[4], \
+ (ea).octet[5]
+#if !defined(SIMPLE_MAC_PRINT)
+#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC2STR(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5]
+#else
+#define MACDBG "%02x:%02x:%02x"
+#define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5]
+#define MACSTR "%02x:%02x:%02x"
+#define MAC2STR(ea) (ea)[0], (ea)[4], (ea)[5]
+#endif /* SIMPLE_MAC_PRINT */
+
+/* bcm_format_flags() bit description structure */
+typedef struct bcm_bit_desc {
+ uint32 bit;
+ const char* name;
+} bcm_bit_desc_t;
+
+/* bcm_format_field */
+typedef struct bcm_bit_desc_ex {
+ uint32 mask;
+ const bcm_bit_desc_t *bitfield;
+} bcm_bit_desc_ex_t;
+
+/* buffer length for ethernet address from bcm_ether_ntoa() */
+#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */
+
+/* crypto utility function */
+/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */
+static INLINE void
+xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst)
+{
+ if (
+#ifdef __i386__
+ 1 ||
+#endif
+ (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) {
+ /* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */
+ /* x86 supports unaligned. This version runs 6x-9x faster on x86. */
+ ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0];
+ ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1];
+ ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2];
+ ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3];
+ } else {
+ /* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */
+ int k;
+ for (k = 0; k < 16; k++)
+ dst[k] = src1[k] ^ src2[k];
+ }
+}
+
+/* externs */
+/* crc */
+extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc);
+extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc);
+extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc);
+
+/* format/print */
+#if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \
+ defined(WLMSG_ASSOC)
+/* print out the value a field has: fields may have 1-32 bits and may hold any value */
+extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len);
+/* print out which bits in flags are set */
+extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len);
+#endif
+
+extern int bcm_format_hex(char *str, const void *bytes, int len);
+
+extern const char *bcm_crypto_algo_name(uint algo);
+extern char *bcm_chipname(uint chipid, char *buf, uint len);
+extern char *bcm_brev_str(uint32 brev, char *buf);
+extern void printbig(char *buf);
+extern void prhex(const char *msg, uchar *buf, uint len);
+
+/* IE parsing */
+
+/* tag_ID/length/value_buffer tuple */
+typedef struct bcm_tlv {
+ uint8 id;
+ uint8 len;
+ uint8 data[1];
+} bcm_tlv_t;
+
+/* bcm tlv w/ 16 bit id/len */
+typedef struct bcm_xtlv {
+ uint16 id;
+ uint16 len;
+ uint8 data[1];
+} bcm_xtlv_t;
+
+/* descriptor of xtlv data src or dst */
+typedef struct {
+ uint16 type;
+ uint16 len;
+ void *ptr; /* ptr to memory location */
+} xtlv_desc_t;
+
+/* set a var from xtlv buffer */
+typedef int
+(bcm_set_var_from_tlv_cbfn_t)(void *ctx, void **tlv_buf, uint16 type, uint16 len);
+
+struct bcm_tlvbuf {
+ uint16 size;
+ uint8 *head; /* point to head of buffer */
+ uint8 *buf; /* current position of buffer */
+ /* followed by the allocated buffer */
+};
+
+#define BCM_TLV_MAX_DATA_SIZE (255)
+#define BCM_XTLV_MAX_DATA_SIZE (65535)
+#define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data))
+
+#define BCM_XTLV_HDR_SIZE (OFFSETOF(bcm_xtlv_t, data))
+#define BCM_XTLV_LEN(elt) ltoh16_ua(&(elt->len))
+#define BCM_XTLV_ID(elt) ltoh16_ua(&(elt->id))
+#define BCM_XTLV_SIZE(elt) (BCM_XTLV_HDR_SIZE + BCM_XTLV_LEN(elt))
+
+/* Check that bcm_tlv_t fits into the given buflen */
+#define bcm_valid_tlv(elt, buflen) (\
+ ((int)(buflen) >= (int)BCM_TLV_HDR_SIZE) && \
+ ((int)(buflen) >= (int)(BCM_TLV_HDR_SIZE + (elt)->len)))
+
+#define bcm_valid_xtlv(elt, buflen) (\
+ ((int)(buflen) >= (int)BCM_XTLV_HDR_SIZE) && \
+ ((int)(buflen) >= (int)BCM_XTLV_SIZE(elt)))
+
+extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen);
+extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
+extern bcm_tlv_t *bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen);
+
+extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key);
+
+extern bcm_tlv_t *bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type,
+ int type_len);
+
+extern uint8 *bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst);
+extern uint8 *bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst,
+ int dst_maxlen);
+
+extern uint8 *bcm_copy_tlv(const void *src, uint8 *dst);
+extern uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen);
+
+/* xtlv */
+extern bcm_xtlv_t *bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen);
+extern struct bcm_tlvbuf *bcm_xtlv_buf_alloc(void *osh, uint16 len);
+extern void bcm_xtlv_buf_free(void *osh, struct bcm_tlvbuf *tbuf);
+extern uint16 bcm_xtlv_buf_len(struct bcm_tlvbuf *tbuf);
+extern uint16 bcm_xtlv_buf_rlen(struct bcm_tlvbuf *tbuf);
+extern uint8 *bcm_xtlv_buf(struct bcm_tlvbuf *tbuf);
+extern uint8 *bcm_xtlv_head(struct bcm_tlvbuf *tbuf);
+extern int bcm_xtlv_put_data(struct bcm_tlvbuf *tbuf, uint16 type, const void *data, uint16 dlen);
+extern int bcm_xtlv_put_8(struct bcm_tlvbuf *tbuf, uint16 type, const int8 data);
+extern int bcm_xtlv_put_16(struct bcm_tlvbuf *tbuf, uint16 type, const int16 data);
+extern int bcm_xtlv_put_32(struct bcm_tlvbuf *tbuf, uint16 type, const int32 data);
+extern int bcm_unpack_xtlv_entry(void **tlv_buf, uint16 xpct_type, uint16 xpct_len, void *dst);
+extern int bcm_skip_xtlv(void **tlv_buf);
+extern int bcm_pack_xtlv_entry(void **tlv_buf, uint16 *buflen, uint16 type, uint16 len, void *src);
+extern int bcm_unpack_xtlv_buf(void *ctx,
+ void *tlv_buf, uint16 buflen, bcm_set_var_from_tlv_cbfn_t *cbfn);
+extern int
+bcm_unpack_xtlv_buf_to_mem(void *tlv_buf, int *buflen, xtlv_desc_t *items);
+extern int
+bcm_pack_xtlv_buf_from_mem(void **tlv_buf, uint16 *buflen, xtlv_desc_t *items);
+extern int
+bcm_pack_xtlv_entry_from_hex_string(void **tlv_buf, uint16 *buflen, uint16 type, char *hex);
+
+/* bcmerror */
+extern const char *bcmerrorstr(int bcmerror);
+
+/* multi-bool data type: set of bools, mbool is true if any is set */
+typedef uint32 mbool;
+#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */
+#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */
+#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* TRUE if one bool is set */
+#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val)))
+
+/* generic datastruct to help dump routines */
+struct fielddesc {
+ const char *nameandfmt;
+ uint32 offset;
+ uint32 len;
+};
+
+extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size);
+extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len);
+
+extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount);
+extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes);
+extern void bcm_print_bytes(const char *name, const uchar *cdata, int len);
+
+typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset);
+extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str,
+ char *buf, uint32 bufsize);
+extern uint bcm_bitcount(uint8 *bitmap, uint bytelength);
+
+extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...);
+
+/* power conversion */
+extern uint16 bcm_qdbm_to_mw(uint8 qdbm);
+extern uint8 bcm_mw_to_qdbm(uint16 mw);
+extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len);
+
+unsigned int process_nvram_vars(char *varbuf, unsigned int len);
+
+/* calculate a * b + c */
+extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c);
+/* calculate a / b */
+extern void bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
+
+
+/* Public domain bit twiddling hacks/utilities: Sean Eron Anderson */
+
+/* Table driven count set bits. */
+static const uint8 /* Table only for use by bcm_cntsetbits */
+_CSBTBL[256] =
+{
+# define B2(n) n, n + 1, n + 1, n + 2
+# define B4(n) B2(n), B2(n + 1), B2(n + 1), B2(n + 2)
+# define B6(n) B4(n), B4(n + 1), B4(n + 1), B4(n + 2)
+ B6(0), B6(0 + 1), B6(0 + 1), B6(0 + 2)
+};
+
+static INLINE uint32 /* Uses table _CSBTBL for fast counting of 1's in a u32 */
+bcm_cntsetbits(const uint32 u32)
+{
+ /* function local scope declaration of const _CSBTBL[] */
+ const uint8 * p = (const uint8 *)&u32;
+ return (_CSBTBL[p[0]] + _CSBTBL[p[1]] + _CSBTBL[p[2]] + _CSBTBL[p[3]]);
+}
+
+
+static INLINE int /* C equivalent count of leading 0's in a u32 */
+C_bcm_count_leading_zeros(uint32 u32)
+{
+ int shifts = 0;
+ while (u32) {
+ shifts++; u32 >>= 1;
+ }
+ return (32U - shifts);
+}
+
+#ifdef BCMDRIVER
+/*
+ * Assembly instructions: Count Leading Zeros
+ * "clz" : MIPS, ARM
+ * "cntlzw" : PowerPC
+ * "BSF" : x86
+ * "lzcnt" : AMD, SPARC
+ */
+
+#if defined(__arm__)
+
+#if defined(__ARM_ARCH_7M__) /* Cortex M3 */
+#define __USE_ASM_CLZ__
+#endif /* __ARM_ARCH_7M__ */
+
+#if defined(__ARM_ARCH_7R__) /* Cortex R4 */
+#define __USE_ASM_CLZ__
+#endif /* __ARM_ARCH_7R__ */
+
+#endif /* __arm__ */
+
+static INLINE int
+bcm_count_leading_zeros(uint32 u32)
+{
+#if defined(__USE_ASM_CLZ__)
+ int zeros;
+ __asm__ volatile("clz %0, %1 \n" : "=r" (zeros) : "r" (u32));
+ return zeros;
+#else /* C equivalent */
+ return C_bcm_count_leading_zeros(u32);
+#endif /* C equivalent */
+}
+
+/* INTERFACE: Multiword bitmap based small id allocator. */
+struct bcm_mwbmap; /* forward declaration for use as an opaque mwbmap handle */
+
+#define BCM_MWBMAP_INVALID_HDL ((struct bcm_mwbmap *)NULL)
+#define BCM_MWBMAP_INVALID_IDX ((uint32)(~0U))
+
+/* Incarnate a multiword bitmap based small index allocator */
+extern struct bcm_mwbmap * bcm_mwbmap_init(osl_t * osh, uint32 items_max);
+
+/* Free up the multiword bitmap index allocator */
+extern void bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl);
+
+/* Allocate a unique small index using a multiword bitmap index allocator */
+extern uint32 bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl);
+
+/* Force an index at a specified position to be in use */
+extern void bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+/* Free a previously allocated index back into the multiword bitmap allocator */
+extern void bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+/* Fetch the toal number of free indices in the multiword bitmap allocator */
+extern uint32 bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl);
+
+/* Determine whether an index is inuse or free */
+extern bool bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+/* Debug dump a multiword bitmap allocator */
+extern void bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl);
+
+extern void bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl);
+/* End - Multiword bitmap based small Id allocator. */
+#endif /* BCMDRIVER */
+
+extern void bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
+
+void bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset);
+void bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#ifdef DEBUG_COUNTER
+#define CNTR_TBL_MAX 10
+typedef struct _counter_tbl_t {
+ char name[16]; /* name of this counter table */
+ uint32 prev_log_print; /* Internal use. Timestamp of the previous log print */
+ uint log_print_interval; /* Desired interval to print logs in ms */
+ uint needed_cnt; /* How many counters need to be used */
+ uint32 cnt[CNTR_TBL_MAX]; /* Counting entries to increase at desired places */
+ bool enabled; /* Whether to enable printing log */
+} counter_tbl_t;
+
+
+void counter_printlog(counter_tbl_t *ctr_tbl);
+#endif /* DEBUG_COUNTER */
+
+#endif /* _bcmutils_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/brcm_nl80211.h b/drivers/net/wireless/bcmdhd/include/brcm_nl80211.h
new file mode 100644
index 000000000000..9892b9cc8685
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/brcm_nl80211.h
@@ -0,0 +1,56 @@
+/*
+ * Definitions for nl80211 testmode access to host driver
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: brcm_nl80211.h 454792 2014-02-11 20:40:19Z $
+ *
+ */
+
+#ifndef _brcm_nl80211_h_
+#define _brcm_nl80211_h_
+
+struct bcm_nlmsg_hdr {
+ uint cmd; /* common ioctl definition */
+ uint len; /* attached buffer length */
+ uint offset; /* user buffer offset */
+ uint set; /* get or set request optional */
+ uint magic; /* magic number for verification */
+};
+
+enum bcmnl_attrs {
+ BCM_NLATTR_UNSPEC,
+
+ BCM_NLATTR_LEN,
+ BCM_NLATTR_DATA,
+
+ __BCM_NLATTR_AFTER_LAST,
+ BCM_NLATTR_MAX = __BCM_NLATTR_AFTER_LAST - 1
+};
+
+struct nl_prv_data {
+ int err; /* return result */
+ void *data; /* ioctl return buffer pointer */
+ uint len; /* ioctl return buffer length */
+ struct bcm_nlmsg_hdr *nlioc; /* bcm_nlmsg_hdr header pointer */
+};
+
+#endif /* _brcm_nl80211_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/circularbuf.h b/drivers/net/wireless/bcmdhd/include/circularbuf.h
new file mode 100644
index 000000000000..2d35599342f6
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/circularbuf.h
@@ -0,0 +1,115 @@
+/*
+ * Initialization and support routines for self-booting compressed image.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: circularbuf.h 452261 2014-01-29 19:30:23Z $
+ */
+
+#ifndef __CIRCULARBUF_H_INCLUDED__
+#define __CIRCULARBUF_H_INCLUDED__
+
+#include <osl.h>
+#include <typedefs.h>
+#include <bcmendian.h>
+
+/* Enumerations of return values provided by MsgBuf implementation */
+typedef enum {
+ CIRCULARBUF_FAILURE = -1,
+ CIRCULARBUF_SUCCESS
+} circularbuf_ret_t;
+
+/* Core circularbuf circular buffer structure */
+typedef struct circularbuf_s
+{
+ uint16 depth; /* Depth of circular buffer */
+ uint16 r_ptr; /* Read Ptr */
+ uint16 w_ptr; /* Write Ptr */
+ uint16 e_ptr; /* End Ptr */
+ uint16 wp_ptr; /* wp_ptr/pending - scheduled for DMA. But, not yet complete. */
+ uint16 rp_ptr; /* rp_ptr/pending - scheduled for DMA. But, not yet complete. */
+
+ uint8 *buf_addr;
+ void *mb_ctx;
+ void (*mb_ring_bell)(void *ctx);
+} circularbuf_t;
+
+#define CBUF_ERROR_VAL 0x00000001 /* Error level tracing */
+#define CBUF_TRACE_VAL 0x00000002 /* Function level tracing */
+#define CBUF_INFORM_VAL 0x00000004 /* debug level tracing */
+
+extern int cbuf_msg_level;
+
+#define CBUF_ERROR(args) do {if (cbuf_msg_level & CBUF_ERROR_VAL) printf args;} while (0)
+#define CBUF_TRACE(args) do {if (cbuf_msg_level & CBUF_TRACE_VAL) printf args;} while (0)
+#define CBUF_INFO(args) do {if (cbuf_msg_level & CBUF_INFORM_VAL) printf args;} while (0)
+
+#define CIRCULARBUF_START(x) ((x)->buf_addr)
+#define CIRCULARBUF_WRITE_PTR(x) ((x)->w_ptr)
+#define CIRCULARBUF_READ_PTR(x) ((x)->r_ptr)
+#define CIRCULARBUF_END_PTR(x) ((x)->e_ptr)
+
+#define circularbuf_debug_print(handle) \
+ CBUF_INFO(("%s:%d:\t%p rp=%4d r=%4d wp=%4d w=%4d e=%4d\n", \
+ __FUNCTION__, __LINE__, \
+ (void *) CIRCULARBUF_START(handle), \
+ (int) (handle)->rp_ptr, (int) (handle)->r_ptr, \
+ (int) (handle)->wp_ptr, (int) (handle)->w_ptr, \
+ (int) (handle)->e_ptr));
+
+
+/* Callback registered by application/mail-box with the circularbuf implementation.
+ * This will be invoked by the circularbuf implementation when write is complete and
+ * ready for informing the peer
+ */
+typedef void (*mb_ring_t)(void *ctx);
+
+
+/* Public Functions exposed by circularbuf */
+void
+circularbuf_init(circularbuf_t *handle, void *buf_base_addr, uint16 total_buf_len);
+void
+circularbuf_register_cb(circularbuf_t *handle, mb_ring_t mb_ring_func, void *ctx);
+
+/* Write Functions */
+void *
+circularbuf_reserve_for_write(circularbuf_t *handle, uint16 size);
+void
+circularbuf_write_complete(circularbuf_t *handle, uint16 bytes_written);
+
+/* Read Functions */
+void *
+circularbuf_get_read_ptr(circularbuf_t *handle, uint16 *avail_len);
+circularbuf_ret_t
+circularbuf_read_complete(circularbuf_t *handle, uint16 bytes_read);
+
+/*
+ * circularbuf_get_read_ptr() updates rp_ptr by the amount that the consumer
+ * is supposed to read. The consumer may not read the entire amount.
+ * In such a case, circularbuf_revert_rp_ptr() call follows a corresponding
+ * circularbuf_get_read_ptr() call to revert the rp_ptr back to
+ * the point till which data has actually been processed.
+ * It is not valid if it is preceded by multiple get_read_ptr() calls
+ */
+circularbuf_ret_t
+circularbuf_revert_rp_ptr(circularbuf_t *handle, uint16 bytes);
+
+#endif /* __CIRCULARBUF_H_INCLUDED__ */
diff --git a/drivers/net/wireless/bcmdhd/include/dbus.h b/drivers/net/wireless/bcmdhd/include/dbus.h
new file mode 100644
index 000000000000..841830097945
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/dbus.h
@@ -0,0 +1,582 @@
+/*
+ * Dongle BUS interface Abstraction layer
+ * target serial buses like USB, SDIO, SPI, etc.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dbus.h 423346 2013-09-11 22:38:40Z $
+ */
+
+#ifndef __DBUS_H__
+#define __DBUS_H__
+
+#include "typedefs.h"
+
+#define DBUSTRACE(args)
+#define DBUSERR(args)
+#define DBUSINFO(args)
+#define DBUSDBGLOCK(args)
+
+enum {
+ DBUS_OK = 0,
+ DBUS_ERR = -200,
+ DBUS_ERR_TIMEOUT,
+ DBUS_ERR_DISCONNECT,
+ DBUS_ERR_NODEVICE,
+ DBUS_ERR_UNSUPPORTED,
+ DBUS_ERR_PENDING,
+ DBUS_ERR_NOMEM,
+ DBUS_ERR_TXFAIL,
+ DBUS_ERR_TXTIMEOUT,
+ DBUS_ERR_TXDROP,
+ DBUS_ERR_RXFAIL,
+ DBUS_ERR_RXDROP,
+ DBUS_ERR_TXCTLFAIL,
+ DBUS_ERR_RXCTLFAIL,
+ DBUS_ERR_REG_PARAM,
+ DBUS_STATUS_CANCELLED,
+ DBUS_ERR_NVRAM,
+ DBUS_JUMBO_NOMATCH,
+ DBUS_JUMBO_BAD_FORMAT,
+ DBUS_NVRAM_NONTXT
+};
+
+#define BCM_OTP_SIZE_43236 84 /* number of 16 bit values */
+#define BCM_OTP_SW_RGN_43236 24 /* start offset of SW config region */
+#define BCM_OTP_ADDR_43236 0x18000800 /* address of otp base */
+
+#define ERR_CBMASK_TXFAIL 0x00000001
+#define ERR_CBMASK_RXFAIL 0x00000002
+#define ERR_CBMASK_ALL 0xFFFFFFFF
+
+#define DBUS_CBCTL_WRITE 0
+#define DBUS_CBCTL_READ 1
+#if defined(INTR_EP_ENABLE)
+#define DBUS_CBINTR_POLL 2
+#endif /* defined(INTR_EP_ENABLE) */
+
+#define DBUS_TX_RETRY_LIMIT 3 /* retries for failed txirb */
+#define DBUS_TX_TIMEOUT_INTERVAL 250 /* timeout for txirb complete, in ms */
+
+#define DBUS_BUFFER_SIZE_TX 32000
+#define DBUS_BUFFER_SIZE_RX 24000
+
+#define DBUS_BUFFER_SIZE_TX_NOAGG 2048
+#define DBUS_BUFFER_SIZE_RX_NOAGG 2048
+
+/* DBUS types */
+enum {
+ DBUS_USB,
+ DBUS_SDIO,
+ DBUS_SPI,
+ DBUS_UNKNOWN
+};
+
+enum dbus_state {
+ DBUS_STATE_DL_PENDING,
+ DBUS_STATE_DL_DONE,
+ DBUS_STATE_UP,
+ DBUS_STATE_DOWN,
+ DBUS_STATE_PNP_FWDL,
+ DBUS_STATE_DISCONNECT,
+ DBUS_STATE_SLEEP
+};
+
+enum dbus_pnp_state {
+ DBUS_PNP_DISCONNECT,
+ DBUS_PNP_SLEEP,
+ DBUS_PNP_RESUME
+};
+
+enum dbus_file {
+ DBUS_FIRMWARE,
+ DBUS_NVFILE
+};
+
+typedef enum _DEVICE_SPEED {
+ INVALID_SPEED = -1,
+ LOW_SPEED = 1, /* USB 1.1: 1.5 Mbps */
+ FULL_SPEED, /* USB 1.1: 12 Mbps */
+ HIGH_SPEED, /* USB 2.0: 480 Mbps */
+ SUPER_SPEED, /* USB 3.0: 4.8 Gbps */
+} DEVICE_SPEED;
+
+typedef struct {
+ int bustype;
+ int vid;
+ int pid;
+ int devid;
+ int chiprev; /* chip revsion number */
+ int mtu;
+ int nchan; /* Data Channels */
+ int has_2nd_bulk_in_ep;
+} dbus_attrib_t;
+
+/* FIX: Account for errors related to DBUS;
+ * Let upper layer account for packets/bytes
+ */
+typedef struct {
+ uint32 rx_errors;
+ uint32 tx_errors;
+ uint32 rx_dropped;
+ uint32 tx_dropped;
+} dbus_stats_t;
+
+/*
+ * Configurable BUS parameters
+ */
+enum {
+ DBUS_CONFIG_ID_RXCTL_DEFERRES = 1,
+ DBUS_CONFIG_ID_TXRXQUEUE
+};
+typedef struct {
+ uint32 config_id;
+ union {
+ bool rxctl_deferrespok;
+ struct {
+ int maxrxq;
+ int rxbufsize;
+ int maxtxq;
+ int txbufsize;
+ } txrxqueue;
+ };
+} dbus_config_t;
+
+/*
+ * External Download Info
+ */
+typedef struct dbus_extdl {
+ uint8 *fw;
+ int fwlen;
+ uint8 *vars;
+ int varslen;
+} dbus_extdl_t;
+
+struct dbus_callbacks;
+struct exec_parms;
+
+typedef void *(*probe_cb_t)(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
+typedef void (*disconnect_cb_t)(void *arg);
+typedef void *(*exec_cb_t)(struct exec_parms *args);
+
+/* Client callbacks registered during dbus_attach() */
+typedef struct dbus_callbacks {
+ void (*send_complete)(void *cbarg, void *info, int status);
+ void (*recv_buf)(void *cbarg, uint8 *buf, int len);
+ void (*recv_pkt)(void *cbarg, void *pkt);
+ void (*txflowcontrol)(void *cbarg, bool onoff);
+ void (*errhandler)(void *cbarg, int err);
+ void (*ctl_complete)(void *cbarg, int type, int status);
+ void (*state_change)(void *cbarg, int state);
+ void *(*pktget)(void *cbarg, uint len, bool send);
+ void (*pktfree)(void *cbarg, void *p, bool send);
+} dbus_callbacks_t;
+
+struct dbus_pub;
+struct bcmstrbuf;
+struct dbus_irb;
+struct dbus_irb_rx;
+struct dbus_irb_tx;
+struct dbus_intf_callbacks;
+
+typedef struct {
+ void* (*attach)(struct dbus_pub *pub, void *cbarg, struct dbus_intf_callbacks *cbs);
+ void (*detach)(struct dbus_pub *pub, void *bus);
+
+ int (*up)(void *bus);
+ int (*down)(void *bus);
+ int (*send_irb)(void *bus, struct dbus_irb_tx *txirb);
+ int (*recv_irb)(void *bus, struct dbus_irb_rx *rxirb);
+ int (*cancel_irb)(void *bus, struct dbus_irb_tx *txirb);
+ int (*send_ctl)(void *bus, uint8 *buf, int len);
+ int (*recv_ctl)(void *bus, uint8 *buf, int len);
+ int (*get_stats)(void *bus, dbus_stats_t *stats);
+ int (*get_attrib)(void *bus, dbus_attrib_t *attrib);
+
+ int (*pnp)(void *bus, int evnt);
+ int (*remove)(void *bus);
+ int (*resume)(void *bus);
+ int (*suspend)(void *bus);
+ int (*stop)(void *bus);
+ int (*reset)(void *bus);
+
+ /* Access to bus buffers directly */
+ void *(*pktget)(void *bus, int len);
+ void (*pktfree)(void *bus, void *pkt);
+
+ int (*iovar_op)(void *bus, const char *name, void *params, int plen, void *arg, int len,
+ bool set);
+ void (*dump)(void *bus, struct bcmstrbuf *strbuf);
+ int (*set_config)(void *bus, dbus_config_t *config);
+ int (*get_config)(void *bus, dbus_config_t *config);
+
+ bool (*device_exists)(void *bus);
+ bool (*dlneeded)(void *bus);
+ int (*dlstart)(void *bus, uint8 *fw, int len);
+ int (*dlrun)(void *bus);
+ bool (*recv_needed)(void *bus);
+
+ void *(*exec_rxlock)(void *bus, exec_cb_t func, struct exec_parms *args);
+ void *(*exec_txlock)(void *bus, exec_cb_t func, struct exec_parms *args);
+
+ int (*tx_timer_init)(void *bus);
+ int (*tx_timer_start)(void *bus, uint timeout);
+ int (*tx_timer_stop)(void *bus);
+
+ int (*sched_dpc)(void *bus);
+ int (*lock)(void *bus);
+ int (*unlock)(void *bus);
+ int (*sched_probe_cb)(void *bus);
+
+ int (*shutdown)(void *bus);
+
+ int (*recv_stop)(void *bus);
+ int (*recv_resume)(void *bus);
+
+ int (*recv_irb_from_ep)(void *bus, struct dbus_irb_rx *rxirb, uint ep_idx);
+
+ int (*readreg)(void *bus, uint32 regaddr, int datalen, uint32 *value);
+
+ /* Add from the bottom */
+} dbus_intf_t;
+
+typedef struct dbus_pub {
+ struct osl_info *osh;
+ dbus_stats_t stats;
+ dbus_attrib_t attrib;
+ enum dbus_state busstate;
+ DEVICE_SPEED device_speed;
+ int ntxq, nrxq, rxsize;
+ void *bus;
+ struct shared_info *sh;
+ void *dev_info;
+} dbus_pub_t;
+
+#define BUS_INFO(bus, type) (((type *) bus)->pub->bus)
+
+#define ALIGNED_LOCAL_VARIABLE(var, align) \
+ uint8 buffer[SDALIGN+64]; \
+ uint8 *var = (uint8 *)(((uintptr)&buffer[0]) & ~(align-1)) + align;
+
+/*
+ * Public Bus Function Interface
+ */
+
+/*
+ * FIX: Is there better way to pass OS/Host handles to DBUS but still
+ * maintain common interface for all OS??
+ * Under NDIS, param1 needs to be MiniportHandle
+ * For NDIS60, param2 is WdfDevice
+ * Under Linux, param1 and param2 are NULL;
+ */
+extern int dbus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, void *prarg,
+ void *param1, void *param2);
+extern int dbus_deregister(void);
+
+extern dbus_pub_t *dbus_attach(struct osl_info *osh, int rxsize, int nrxq, int ntxq,
+ void *cbarg, dbus_callbacks_t *cbs, dbus_extdl_t *extdl, struct shared_info *sh);
+extern void dbus_detach(dbus_pub_t *pub);
+
+extern int dbus_up(dbus_pub_t *pub);
+extern int dbus_down(dbus_pub_t *pub);
+extern int dbus_stop(dbus_pub_t *pub);
+extern int dbus_shutdown(dbus_pub_t *pub);
+extern void dbus_flowctrl_rx(dbus_pub_t *pub, bool on);
+
+extern int dbus_send_txdata(dbus_pub_t *dbus, void *pktbuf);
+extern int dbus_send_buf(dbus_pub_t *pub, uint8 *buf, int len, void *info);
+extern int dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info);
+extern int dbus_send_ctl(dbus_pub_t *pub, uint8 *buf, int len);
+extern int dbus_recv_ctl(dbus_pub_t *pub, uint8 *buf, int len);
+extern int dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx);
+extern int dbus_poll_intr(dbus_pub_t *pub);
+extern int dbus_get_stats(dbus_pub_t *pub, dbus_stats_t *stats);
+extern int dbus_get_attrib(dbus_pub_t *pub, dbus_attrib_t *attrib);
+extern int dbus_get_device_speed(dbus_pub_t *pub);
+extern int dbus_set_config(dbus_pub_t *pub, dbus_config_t *config);
+extern int dbus_get_config(dbus_pub_t *pub, dbus_config_t *config);
+extern void * dbus_get_devinfo(dbus_pub_t *pub);
+
+extern void *dbus_pktget(dbus_pub_t *pub, int len);
+extern void dbus_pktfree(dbus_pub_t *pub, void* pkt);
+
+extern int dbus_set_errmask(dbus_pub_t *pub, uint32 mask);
+extern int dbus_pnp_sleep(dbus_pub_t *pub);
+extern int dbus_pnp_resume(dbus_pub_t *pub, int *fw_reload);
+extern int dbus_pnp_disconnect(dbus_pub_t *pub);
+
+extern int dbus_iovar_op(dbus_pub_t *pub, const char *name,
+ void *params, int plen, void *arg, int len, bool set);
+
+extern void *dhd_dbus_txq(const dbus_pub_t *pub);
+extern uint dhd_dbus_hdrlen(const dbus_pub_t *pub);
+
+/*
+ * Private Common Bus Interface
+ */
+
+/* IO Request Block (IRB) */
+typedef struct dbus_irb {
+ struct dbus_irb *next; /* it's casted from dbus_irb_tx or dbus_irb_rx struct */
+} dbus_irb_t;
+
+typedef struct dbus_irb_rx {
+ struct dbus_irb irb; /* Must be first */
+ uint8 *buf;
+ int buf_len;
+ int actual_len;
+ void *pkt;
+ void *info;
+ void *arg;
+} dbus_irb_rx_t;
+
+typedef struct dbus_irb_tx {
+ struct dbus_irb irb; /* Must be first */
+ uint8 *buf;
+ int len;
+ void *pkt;
+ int retry_count;
+ void *info;
+ void *arg;
+ void *send_buf; /* linear bufffer for LINUX when aggreagtion is enabled */
+} dbus_irb_tx_t;
+
+/* DBUS interface callbacks are different from user callbacks
+ * so, internally, different info can be passed to upper layer
+ */
+typedef struct dbus_intf_callbacks {
+ void (*send_irb_timeout)(void *cbarg, dbus_irb_tx_t *txirb);
+ void (*send_irb_complete)(void *cbarg, dbus_irb_tx_t *txirb, int status);
+ void (*recv_irb_complete)(void *cbarg, dbus_irb_rx_t *rxirb, int status);
+ void (*errhandler)(void *cbarg, int err);
+ void (*ctl_complete)(void *cbarg, int type, int status);
+ void (*state_change)(void *cbarg, int state);
+ bool (*isr)(void *cbarg, bool *wantdpc);
+ bool (*dpc)(void *cbarg, bool bounded);
+ void (*watchdog)(void *cbarg);
+ void *(*pktget)(void *cbarg, uint len, bool send);
+ void (*pktfree)(void *cbarg, void *p, bool send);
+ struct dbus_irb* (*getirb)(void *cbarg, bool send);
+ void (*rxerr_indicate)(void *cbarg, bool on);
+} dbus_intf_callbacks_t;
+
+/*
+ * Porting: To support new bus, port these functions below
+ */
+
+/*
+ * Bus specific Interface
+ * Implemented by dbus_usb.c/dbus_sdio.c
+ */
+extern int dbus_bus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, void *prarg,
+ dbus_intf_t **intf, void *param1, void *param2);
+extern int dbus_bus_deregister(void);
+extern void dbus_bus_fw_get(void *bus, uint8 **fw, int *fwlen, int *decomp);
+
+/*
+ * Bus-specific and OS-specific Interface
+ * Implemented by dbus_usb_[linux/ndis].c/dbus_sdio_[linux/ndis].c
+ */
+extern int dbus_bus_osl_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb,
+ void *prarg, dbus_intf_t **intf, void *param1, void *param2);
+extern int dbus_bus_osl_deregister(void);
+
+/*
+ * Bus-specific, OS-specific, HW-specific Interface
+ * Mainly for SDIO Host HW controller
+ */
+extern int dbus_bus_osl_hw_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb,
+ void *prarg, dbus_intf_t **intf);
+extern int dbus_bus_osl_hw_deregister(void);
+
+extern uint usbdev_bulkin_eps(void);
+#if defined(BCM_REQUEST_FW)
+extern void *dbus_get_fw_nvfile(int devid, uint8 **fw, int *fwlen, int type,
+ uint16 boardtype, uint16 boardrev);
+extern void dbus_release_fw_nvfile(void *firmware);
+#endif /* #if defined(BCM_REQUEST_FW) */
+
+
+#if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX)
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+ /* Backward compatibility */
+ typedef unsigned int gfp_t;
+
+ #define dma_pool pci_pool
+ #define dma_pool_create(name, dev, size, align, alloc) \
+ pci_pool_create(name, dev, size, align, alloc, GFP_DMA | GFP_ATOMIC)
+ #define dma_pool_destroy(pool) pci_pool_destroy(pool)
+ #define dma_pool_alloc(pool, flags, handle) pci_pool_alloc(pool, flags, handle)
+ #define dma_pool_free(pool, vaddr, addr) pci_pool_free(pool, vaddr, addr)
+
+ #define dma_map_single(dev, addr, size, dir) pci_map_single(dev, addr, size, dir)
+ #define dma_unmap_single(dev, hnd, size, dir) pci_unmap_single(dev, hnd, size, dir)
+ #define DMA_FROM_DEVICE PCI_DMA_FROMDEVICE
+ #define DMA_TO_DEVICE PCI_DMA_TODEVICE
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */
+
+/* Availability of these functions varies (when present, they have two arguments) */
+#ifndef hc32_to_cpu
+ #define hc32_to_cpu(x) le32_to_cpu(x)
+ #define cpu_to_hc32(x) cpu_to_le32(x)
+ typedef unsigned int __hc32;
+#else
+ #error Two-argument functions needed
+#endif
+
+/* Private USB opcode base */
+#define EHCI_FASTPATH 0x31
+#define EHCI_SET_EP_BYPASS EHCI_FASTPATH
+#define EHCI_SET_BYPASS_CB (EHCI_FASTPATH + 1)
+#define EHCI_SET_BYPASS_DEV (EHCI_FASTPATH + 2)
+#define EHCI_DUMP_STATE (EHCI_FASTPATH + 3)
+#define EHCI_SET_BYPASS_POOL (EHCI_FASTPATH + 4)
+#define EHCI_CLR_EP_BYPASS (EHCI_FASTPATH + 5)
+
+/*
+ * EHCI QTD structure (hardware and extension)
+ * NOTE that is does not need to (and does not) match its kernel counterpart
+ */
+#define EHCI_QTD_NBUFFERS 5
+#define EHCI_QTD_ALIGN 32
+#define EHCI_BULK_PACKET_SIZE 512
+#define EHCI_QTD_XACTERR_MAX 32
+
+struct ehci_qtd {
+ /* Hardware map */
+ volatile uint32_t qtd_next;
+ volatile uint32_t qtd_altnext;
+ volatile uint32_t qtd_status;
+#define EHCI_QTD_GET_BYTES(x) (((x)>>16) & 0x7fff)
+#define EHCI_QTD_IOC 0x00008000
+#define EHCI_QTD_GET_CERR(x) (((x)>>10) & 0x3)
+#define EHCI_QTD_SET_CERR(x) ((x) << 10)
+#define EHCI_QTD_GET_PID(x) (((x)>>8) & 0x3)
+#define EHCI_QTD_SET_PID(x) ((x) << 8)
+#define EHCI_QTD_ACTIVE 0x80
+#define EHCI_QTD_HALTED 0x40
+#define EHCI_QTD_BUFERR 0x20
+#define EHCI_QTD_BABBLE 0x10
+#define EHCI_QTD_XACTERR 0x08
+#define EHCI_QTD_MISSEDMICRO 0x04
+ volatile uint32_t qtd_buffer[EHCI_QTD_NBUFFERS];
+ volatile uint32_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
+
+ /* Implementation extension */
+ dma_addr_t qtd_self; /* own hardware address */
+ struct ehci_qtd *obj_next; /* software link to the next QTD */
+ void *rpc; /* pointer to the rpc buffer */
+ size_t length; /* length of the data in the buffer */
+ void *buff; /* pointer to the reassembly buffer */
+ int xacterrs; /* retry counter for qtd xact error */
+} __attribute__ ((aligned(EHCI_QTD_ALIGN)));
+
+#define EHCI_NULL __constant_cpu_to_le32(1) /* HW null pointer shall be odd */
+
+#define SHORT_READ_Q(token) (EHCI_QTD_GET_BYTES(token) != 0 && EHCI_QTD_GET_PID(token) == 1)
+
+/* Queue Head */
+/* NOTE This structure is slightly different from the one in the kernel; but needs to stay
+ * compatible
+ */
+struct ehci_qh {
+ /* Hardware map */
+ volatile uint32_t qh_link;
+ volatile uint32_t qh_endp;
+ volatile uint32_t qh_endphub;
+ volatile uint32_t qh_curqtd;
+
+ /* QTD overlay */
+ volatile uint32_t ow_next;
+ volatile uint32_t ow_altnext;
+ volatile uint32_t ow_status;
+ volatile uint32_t ow_buffer [EHCI_QTD_NBUFFERS];
+ volatile uint32_t ow_buffer_hi [EHCI_QTD_NBUFFERS];
+
+ /* Extension (should match the kernel layout) */
+ dma_addr_t unused0;
+ void *unused1;
+ struct list_head unused2;
+ struct ehci_qtd *dummy;
+ struct ehci_qh *unused3;
+
+ struct ehci_hcd *unused4;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+ struct kref unused5;
+ unsigned unused6;
+
+ uint8_t unused7;
+
+ /* periodic schedule info */
+ uint8_t unused8;
+ uint8_t unused9;
+ uint8_t unused10;
+ uint16_t unused11;
+ uint16_t unused12;
+ uint16_t unused13;
+ struct usb_device *unused14;
+#else
+ unsigned unused5;
+
+ u8 unused6;
+
+ /* periodic schedule info */
+ u8 unused7;
+ u8 unused8;
+ u8 unused9;
+ unsigned short unused10;
+ unsigned short unused11;
+#define NO_FRAME ((unsigned short)~0)
+#ifdef EHCI_QUIRK_FIX
+ struct usb_device *unused12;
+#endif /* EHCI_QUIRK_FIX */
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */
+ struct ehci_qtd *first_qtd;
+ /* Link to the first QTD; this is an optimized equivalent of the qtd_list field */
+ /* NOTE that ehci_qh in ehci.h shall reserve this word */
+} __attribute__ ((aligned(EHCI_QTD_ALIGN)));
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+/* The corresponding structure in the kernel is used to get the QH */
+struct hcd_dev { /* usb_device.hcpriv points to this */
+ struct list_head unused0;
+ struct list_head unused1;
+
+ /* array of QH pointers */
+ void *ep[32];
+};
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */
+
+int optimize_qtd_fill_with_rpc(const dbus_pub_t *pub, int epn, struct ehci_qtd *qtd, void *rpc,
+ int token, int len);
+int optimize_qtd_fill_with_data(const dbus_pub_t *pub, int epn, struct ehci_qtd *qtd, void *data,
+ int token, int len);
+int optimize_submit_async(struct ehci_qtd *qtd, int epn);
+void inline optimize_ehci_qtd_init(struct ehci_qtd *qtd, dma_addr_t dma);
+struct ehci_qtd *optimize_ehci_qtd_alloc(gfp_t flags);
+void optimize_ehci_qtd_free(struct ehci_qtd *qtd);
+void optimize_submit_rx_request(const dbus_pub_t *pub, int epn, struct ehci_qtd *qtd_in, void *buf);
+#endif /* EHCI_FASTPATH_TX || EHCI_FASTPATH_RX */
+
+void dbus_flowctrl_tx(void *dbi, bool on);
+#endif /* __DBUS_H__ */
diff --git a/drivers/net/wireless/bcmdhd/include/devctrl_if/wlioctl_defs.h b/drivers/net/wireless/bcmdhd/include/devctrl_if/wlioctl_defs.h
new file mode 100644
index 000000000000..d85298b9297c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/devctrl_if/wlioctl_defs.h
@@ -0,0 +1,1987 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wlioctl_defs.h 403826 2013-05-22 16:40:55Z $
+ */
+
+
+#ifndef wlioctl_defs_h
+#define wlioctl_defs_h
+
+
+
+
+
+/* All builds use the new 11ac ratespec/chanspec */
+#undef D11AC_IOTYPES
+#define D11AC_IOTYPES
+
+/* WL_RSPEC defines for rate information */
+#define WL_RSPEC_RATE_MASK 0x000000FF /* rate or HT MCS value */
+#define WL_RSPEC_VHT_MCS_MASK 0x0000000F /* VHT MCS value */
+#define WL_RSPEC_VHT_NSS_MASK 0x000000F0 /* VHT Nss value */
+#define WL_RSPEC_VHT_NSS_SHIFT 4 /* VHT Nss value shift */
+#define WL_RSPEC_TXEXP_MASK 0x00000300
+#define WL_RSPEC_TXEXP_SHIFT 8
+#define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */
+#define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */
+#define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */
+#define WL_RSPEC_TXBF 0x00200000 /* bit indicates TXBF mode */
+#define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */
+#define WL_RSPEC_SGI 0x00800000 /* Short GI mode */
+#define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */
+#define WL_RSPEC_OVERRIDE_RATE 0x40000000 /* bit indicate to override mcs only */
+#define WL_RSPEC_OVERRIDE_MODE 0x80000000 /* bit indicates override both rate & mode */
+
+/* WL_RSPEC_ENCODING field defs */
+#define WL_RSPEC_ENCODE_RATE 0x00000000 /* Legacy rate is stored in RSPEC_RATE_MASK */
+#define WL_RSPEC_ENCODE_HT 0x01000000 /* HT MCS is stored in RSPEC_RATE_MASK */
+#define WL_RSPEC_ENCODE_VHT 0x02000000 /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */
+
+/* WL_RSPEC_BW field defs */
+#define WL_RSPEC_BW_UNSPECIFIED 0
+#define WL_RSPEC_BW_20MHZ 0x00010000
+#define WL_RSPEC_BW_40MHZ 0x00020000
+#define WL_RSPEC_BW_80MHZ 0x00030000
+#define WL_RSPEC_BW_160MHZ 0x00040000
+
+/* Legacy defines for the nrate iovar */
+#define OLD_NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */
+#define OLD_NRATE_RATE_MASK 0x0000007f /* rate/mcs value */
+#define OLD_NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */
+#define OLD_NRATE_STF_SHIFT 8 /* stf mode shift */
+#define OLD_NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */
+#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */
+#define OLD_NRATE_SGI 0x00800000 /* sgi mode */
+#define OLD_NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */
+
+#define OLD_NRATE_STF_SISO 0 /* stf mode SISO */
+#define OLD_NRATE_STF_CDD 1 /* stf mode CDD */
+#define OLD_NRATE_STF_STBC 2 /* stf mode STBC */
+#define OLD_NRATE_STF_SDM 3 /* stf mode SDM */
+
+#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */
+
+#define MAX_CCA_CHANNELS 38 /* Max number of 20 Mhz wide channels */
+#define MAX_CCA_SECS 60 /* CCA keeps this many seconds history */
+
+#define IBSS_MED 15 /* Mediom in-bss congestion percentage */
+#define IBSS_HI 25 /* Hi in-bss congestion percentage */
+#define OBSS_MED 12
+#define OBSS_HI 25
+#define INTERFER_MED 5
+#define INTERFER_HI 10
+
+#define CCA_FLAG_2G_ONLY 0x01 /* Return a channel from 2.4 Ghz band */
+#define CCA_FLAG_5G_ONLY 0x02 /* Return a channel from 2.4 Ghz band */
+#define CCA_FLAG_IGNORE_DURATION 0x04 /* Ignore dwell time for each channel */
+#define CCA_FLAGS_PREFER_1_6_11 0x10
+#define CCA_FLAG_IGNORE_INTERFER 0x20 /* do not exlude channel based on interfer level */
+
+#define CCA_ERRNO_BAND 1 /* After filtering for band pref, no choices left */
+#define CCA_ERRNO_DURATION 2 /* After filtering for duration, no choices left */
+#define CCA_ERRNO_PREF_CHAN 3 /* After filtering for chan pref, no choices left */
+#define CCA_ERRNO_INTERFER 4 /* After filtering for interference, no choices left */
+#define CCA_ERRNO_TOO_FEW 5 /* Only 1 channel was input */
+
+#define WL_STA_AID(a) ((a) &~ 0xc000)
+
+/* Flags for sta_info_t indicating properties of STA */
+#define WL_STA_BRCM 0x00000001 /* Running a Broadcom driver */
+#define WL_STA_WME 0x00000002 /* WMM association */
+#define WL_STA_NONERP 0x00000004 /* No ERP */
+#define WL_STA_AUTHE 0x00000008 /* Authenticated */
+#define WL_STA_ASSOC 0x00000010 /* Associated */
+#define WL_STA_AUTHO 0x00000020 /* Authorized */
+#define WL_STA_WDS 0x00000040 /* Wireless Distribution System */
+#define WL_STA_WDS_LINKUP 0x00000080 /* WDS traffic/probes flowing properly */
+#define WL_STA_PS 0x00000100 /* STA is in power save mode from AP's viewpoint */
+#define WL_STA_APSD_BE 0x00000200 /* APSD delv/trigger for AC_BE is default enabled */
+#define WL_STA_APSD_BK 0x00000400 /* APSD delv/trigger for AC_BK is default enabled */
+#define WL_STA_APSD_VI 0x00000800 /* APSD delv/trigger for AC_VI is default enabled */
+#define WL_STA_APSD_VO 0x00001000 /* APSD delv/trigger for AC_VO is default enabled */
+#define WL_STA_N_CAP 0x00002000 /* STA 802.11n capable */
+#define WL_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
+#define WL_STA_AMPDU_CAP 0x00008000 /* STA AMPDU capable */
+#define WL_STA_AMSDU_CAP 0x00010000 /* STA AMSDU capable */
+#define WL_STA_MIMO_PS 0x00020000 /* mimo ps mode is enabled */
+#define WL_STA_MIMO_RTS 0x00040000 /* send rts in mimo ps mode */
+#define WL_STA_RIFS_CAP 0x00080000 /* rifs enabled */
+#define WL_STA_VHT_CAP 0x00100000 /* STA VHT(11ac) capable */
+#define WL_STA_WPS 0x00200000 /* WPS state */
+
+#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */
+
+/* STA HT cap fields */
+#define WL_STA_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */
+#define WL_STA_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */
+#define WL_STA_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */
+#define WL_STA_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */
+#define WL_STA_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */
+#define WL_STA_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */
+#define WL_STA_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */
+#define WL_STA_CAP_GF 0x0010 /* Greenfield preamble support */
+#define WL_STA_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */
+#define WL_STA_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */
+#define WL_STA_CAP_TX_STBC 0x0080 /* Tx STBC support */
+#define WL_STA_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */
+#define WL_STA_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */
+#define WL_STA_CAP_DELAYED_BA 0x0400 /* delayed BA support */
+#define WL_STA_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */
+#define WL_STA_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */
+#define WL_STA_CAP_PSMP 0x2000 /* Power Save Multi Poll support */
+#define WL_STA_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */
+#define WL_STA_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */
+
+#define WL_STA_CAP_RX_STBC_NO 0x0 /* no rx STBC support */
+#define WL_STA_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */
+#define WL_STA_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */
+#define WL_STA_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */
+
+/* scb vht flags */
+#define WL_STA_VHT_LDPCCAP 0x0001
+#define WL_STA_SGI80 0x0002
+#define WL_STA_SGI160 0x0004
+#define WL_STA_VHT_TX_STBCCAP 0x0008
+#define WL_STA_VHT_RX_STBCCAP 0x0010
+#define WL_STA_SU_BEAMFORMER 0x0020
+#define WL_STA_SU_BEAMFORMEE 0x0040
+#define WL_STA_MU_BEAMFORMER 0x0080
+#define WL_STA_MU_BEAMFORMEE 0x0100
+#define WL_STA_VHT_TXOP_PS 0x0200
+#define WL_STA_HTC_VHT_CAP 0x0400
+
+/* Values for TX Filter override mode */
+#define WLC_TXFILTER_OVERRIDE_DISABLED 0
+#define WLC_TXFILTER_OVERRIDE_ENABLED 1
+
+#define WL_IOCTL_ACTION_GET 0x0
+#define WL_IOCTL_ACTION_SET 0x1
+#define WL_IOCTL_ACTION_OVL_IDX_MASK 0x1e
+#define WL_IOCTL_ACTION_OVL_RSV 0x20
+#define WL_IOCTL_ACTION_OVL 0x40
+#define WL_IOCTL_ACTION_MASK 0x7e
+#define WL_IOCTL_ACTION_OVL_SHIFT 1
+
+#define WL_BSSTYPE_INFRA 1
+#define WL_BSSTYPE_INDEP 0
+#define WL_BSSTYPE_ANY 2
+
+/* Bitmask for scan_type */
+#define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */
+#define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */
+#define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */
+#define WL_SCANFLAGS_OFFCHAN 0x08 /* allow scanning/reporting off-channel APs */
+#define WL_SCANFLAGS_HOTSPOT 0x10 /* automatic ANQP to hotspot APs */
+
+/* wl_iscan_results status values */
+#define WL_SCAN_RESULTS_SUCCESS 0
+#define WL_SCAN_RESULTS_PARTIAL 1
+#define WL_SCAN_RESULTS_PENDING 2
+#define WL_SCAN_RESULTS_ABORTED 3
+#define WL_SCAN_RESULTS_NO_MEM 4
+
+#define SCANOL_ENABLED (1 << 0)
+#define SCANOL_BCAST_SSID (1 << 1)
+#define SCANOL_NOTIFY_BCAST_SSID (1 << 2)
+#define SCANOL_RESULTS_PER_CYCLE (1 << 3)
+
+/* scan times in milliseconds */
+#define SCANOL_HOME_TIME 45 /* for home channel processing */
+#define SCANOL_ASSOC_TIME 20 /* dwell on a channel while associated */
+#define SCANOL_UNASSOC_TIME 40 /* dwell on a channel while unassociated */
+#define SCANOL_PASSIVE_TIME 110 /* listen on a channelfor passive scan */
+#define SCANOL_AWAY_LIMIT 100 /* max time to be away from home channel */
+#define SCANOL_IDLE_REST_TIME 40
+#define SCANOL_IDLE_REST_MULTIPLIER 0
+#define SCANOL_ACTIVE_REST_TIME 20
+#define SCANOL_ACTIVE_REST_MULTIPLIER 0
+#define SCANOL_CYCLE_IDLE_REST_TIME 300000 /* Idle Rest Time between Scan Cycle (msec) */
+#define SCANOL_CYCLE_IDLE_REST_MULTIPLIER 0 /* Idle Rest Time Multiplier */
+#define SCANOL_CYCLE_ACTIVE_REST_TIME 200
+#define SCANOL_CYCLE_ACTIVE_REST_MULTIPLIER 0
+#define SCANOL_MAX_REST_TIME 3600000 /* max rest time between scan cycle (msec) */
+#define SCANOL_CYCLE_DEFAULT 0 /* default for Max Scan Cycle, 0 = forever */
+#define SCANOL_CYCLE_MAX 864000 /* Max Scan Cycle */
+ /* 10 sec/scan cycle => 100 days */
+#define SCANOL_NPROBES 2 /* for Active scan; send n probes on each channel */
+#define SCANOL_NPROBES_MAX 5 /* for Active scan; send n probes on each channel */
+#define SCANOL_SCAN_START_DLY 10 /* delay start of offload scan (sec) */
+#define SCANOL_SCAN_START_DLY_MAX 240 /* delay start of offload scan (sec) */
+#define SCANOL_MULTIPLIER_MAX 10 /* Max Multiplier */
+#define SCANOL_UNASSOC_TIME_MAX 100 /* max dwell on a channel while unassociated */
+#define SCANOL_PASSIVE_TIME_MAX 500 /* max listen on a channel for passive scan */
+#define SCANOL_SSID_MAX 16 /* max supported preferred SSID */
+
+/* masks for channel and ssid count */
+#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff
+#define WL_SCAN_PARAMS_NSSID_SHIFT 16
+
+#define WL_SCAN_ACTION_START 1
+#define WL_SCAN_ACTION_CONTINUE 2
+#define WL_SCAN_ACTION_ABORT 3
+
+
+#define ANTENNA_NUM_1 1 /* total number of antennas to be used */
+#define ANTENNA_NUM_2 2
+#define ANTENNA_NUM_3 3
+#define ANTENNA_NUM_4 4
+
+#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */
+#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */
+#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */
+#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */
+#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */
+#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */
+
+/* interference source detection and identification mode */
+#define ITFR_MODE_DISABLE 0 /* disable feature */
+#define ITFR_MODE_MANUAL_ENABLE 1 /* enable manual detection */
+#define ITFR_MODE_AUTO_ENABLE 2 /* enable auto detection */
+
+/* bit definitions for flags in interference source report */
+#define ITFR_INTERFERENCED 1 /* interference detected */
+#define ITFR_HOME_CHANNEL 2 /* home channel has interference */
+#define ITFR_NOISY_ENVIRONMENT 4 /* noisy environemnt so feature stopped */
+
+#define WL_NUM_RPI_BINS 8
+#define WL_RM_TYPE_BASIC 1
+#define WL_RM_TYPE_CCA 2
+#define WL_RM_TYPE_RPI 3
+
+#define WL_RM_FLAG_PARALLEL (1<<0)
+
+#define WL_RM_FLAG_LATE (1<<1)
+#define WL_RM_FLAG_INCAPABLE (1<<2)
+#define WL_RM_FLAG_REFUSED (1<<3)
+
+/* flags */
+#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */
+
+#define WLC_CIS_DEFAULT 0 /* built-in default */
+#define WLC_CIS_SROM 1 /* source is sprom */
+#define WLC_CIS_OTP 2 /* source is otp */
+
+/* PCL - Power Control Loop */
+/* current gain setting is replaced by user input */
+#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */
+#define WL_ATTEN_PCL_ON 1 /* turn on PCL */
+/* current gain setting is maintained */
+#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */
+
+#define PLC_CMD_FAILOVER 1
+#define PLC_CMD_MAC_COST 2
+#define PLC_CMD_LINK_COST 3
+#define PLC_CMD_NODE_LIST 4
+
+#define NODE_TYPE_UNKNOWN 0 /* Unknown link */
+#define NODE_TYPE_WIFI_ONLY 1 /* Pure Wireless STA node */
+#define NODE_TYPE_PLC_ONLY 2 /* Pure PLC only node */
+#define NODE_TYPE_WIFI_PLC 3 /* WiFi PLC capable node */
+
+/* defines used by poweridx iovar - it controls power in a-band */
+/* current gain setting is maintained */
+#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */
+#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */
+#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */
+#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */
+/* value >= 0 causes
+ * - input to be set to that value
+ * - PCL to be off
+ */
+
+#define BCM_MAC_STATUS_INDICATION (0x40010200L)
+
+/* Values for TX Filter override mode */
+#define WLC_TXFILTER_OVERRIDE_DISABLED 0
+#define WLC_TXFILTER_OVERRIDE_ENABLED 1
+
+/* magic pattern used for mismatch driver and wl */
+#define WL_TXFIFO_SZ_MAGIC 0xa5a5
+
+/* check this magic number */
+#define WLC_IOCTL_MAGIC 0x14e46c77
+
+/* bss_info_cap_t flags */
+#define WL_BSS_FLAGS_FROM_BEACON 0x01 /* bss_info derived from beacon */
+#define WL_BSS_FLAGS_FROM_CACHE 0x02 /* bss_info collected from cache */
+#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04 /* rssi info received on channel (vs offchannel) */
+#define WL_BSS_FLAGS_HS20 0x08 /* hotspot 2.0 capable */
+#define WL_BSS_FLAGS_RSSI_INVALID 0x10 /* BSS contains invalid RSSI */
+#define WL_BSS_FLAGS_RSSI_INACCURATE 0x20 /* BSS contains inaccurate RSSI */
+
+/* bssinfo flag for nbss_cap */
+#define VHT_BI_SGI_80MHZ 0x00000100
+#define VHT_BI_80MHZ 0x00000200
+#define VHT_BI_160MHZ 0x00000400
+#define VHT_BI_8080MHZ 0x00000800
+
+/* reference to wl_ioctl_t struct used by usermode driver */
+#define ioctl_subtype set /* subtype param */
+#define ioctl_pid used /* pid param */
+#define ioctl_status needed /* status param */
+
+
+/* Enumerate crypto algorithms */
+#define CRYPTO_ALGO_OFF 0
+#define CRYPTO_ALGO_WEP1 1
+#define CRYPTO_ALGO_TKIP 2
+#define CRYPTO_ALGO_WEP128 3
+#define CRYPTO_ALGO_AES_CCM 4
+#define CRYPTO_ALGO_AES_OCB_MSDU 5
+#define CRYPTO_ALGO_AES_OCB_MPDU 6
+#if !defined(BCMEXTCCX)
+#define CRYPTO_ALGO_NALG 7
+#else
+#define CRYPTO_ALGO_CKIP 7
+#define CRYPTO_ALGO_CKIP_MMH 8
+#define CRYPTO_ALGO_WEP_MMH 9
+#define CRYPTO_ALGO_NALG 10
+#endif
+
+#define CRYPTO_ALGO_SMS4 11
+#define CRYPTO_ALGO_PMK 12 /* for 802.1x supp to set PMK before 4-way */
+#define CRYPTO_ALGO_BIP 13 /* 802.11w BIP (aes cmac) */
+
+#define CRYPTO_ALGO_AES_GCM 14 /* 128 bit GCM */
+#define CRYPTO_ALGO_AES_CCM256 15 /* 256 bit CCM */
+#define CRYPTO_ALGO_AES_GCM256 16 /* 256 bit GCM */
+#define CRYPTO_ALGO_BIP_CMAC256 17 /* 256 bit BIP CMAC */
+#define CRYPTO_ALGO_BIP_GMAC 18 /* 128 bit BIP GMAC */
+#define CRYPTO_ALGO_BIP_GMAC256 19 /* 256 bit BIP GMAC */
+
+#define CRYPTO_ALGO_NONE CRYPTO_ALGO_OFF
+
+#define WSEC_GEN_MIC_ERROR 0x0001
+#define WSEC_GEN_REPLAY 0x0002
+#define WSEC_GEN_ICV_ERROR 0x0004
+#define WSEC_GEN_MFP_ACT_ERROR 0x0008
+#define WSEC_GEN_MFP_DISASSOC_ERROR 0x0010
+#define WSEC_GEN_MFP_DEAUTH_ERROR 0x0020
+
+#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */
+#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */
+#if defined(BCMEXTCCX)
+#define WL_CKIP_KP (1 << 4) /* CMIC */
+#define WL_CKIP_MMH (1 << 5) /* CKIP */
+#else
+#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */
+#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */
+#endif
+#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */
+
+/* wireless security bitvec */
+#define WEP_ENABLED 0x0001
+#define TKIP_ENABLED 0x0002
+#define AES_ENABLED 0x0004
+#define WSEC_SWFLAG 0x0008
+#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */
+
+/* wsec macros for operating on the above definitions */
+#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED)
+#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED)
+#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED)
+
+#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED)
+
+#define MFP_CAPABLE 0x0200
+#define MFP_REQUIRED 0x0400
+#define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */
+
+/* WPA authentication mode bitvec */
+#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */
+#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */
+#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */
+#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */
+#if defined(BCMEXTCCX)
+#define WPA_AUTH_CCKM 0x0008 /* CCKM */
+#define WPA2_AUTH_CCKM 0x0010 /* CCKM2 */
+#endif
+/* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */
+#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */
+#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */
+#define BRCM_AUTH_PSK 0x0100 /* BRCM specific PSK */
+#define BRCM_AUTH_DPT 0x0200 /* DPT PSK without group keys */
+//#define WPA2_AUTH_MFP 0x1000 /* MFP (11w) in contrast to CCX */
+#define WPA2_AUTH_1X_SHA256 0x1000 /* 1X with SHA256 key derivation */
+#define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */
+#define WPA2_AUTH_FT 0x4000 /* Fast Transition. */
+#define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */
+#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */
+
+/* pmkid */
+#define MAXPMKID 16
+
+#define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
+#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */
+#define WLC_IOCTL_MEDLEN 1536 /* "med" length ioctl buffer required */
+#if defined(LCNCONF) || defined(LCN40CONF)
+#define WLC_SAMPLECOLLECT_MAXLEN 8192 /* Max Sample Collect buffer */
+#else
+#define WLC_SAMPLECOLLECT_MAXLEN 10240 /* Max Sample Collect buffer for two cores */
+#endif
+#define WLC_SAMPLECOLLECT_MAXLEN_LCN40 8192
+
+/* common ioctl definitions */
+#define WLC_GET_MAGIC 0
+#define WLC_GET_VERSION 1
+#define WLC_UP 2
+#define WLC_DOWN 3
+#define WLC_GET_LOOP 4
+#define WLC_SET_LOOP 5
+#define WLC_DUMP 6
+#define WLC_GET_MSGLEVEL 7
+#define WLC_SET_MSGLEVEL 8
+#define WLC_GET_PROMISC 9
+#define WLC_SET_PROMISC 10
+/* #define WLC_OVERLAY_IOCTL 11 */ /* not supported */
+#define WLC_GET_RATE 12
+#define WLC_GET_MAX_RATE 13
+#define WLC_GET_INSTANCE 14
+/* #define WLC_GET_FRAG 15 */ /* no longer supported */
+/* #define WLC_SET_FRAG 16 */ /* no longer supported */
+/* #define WLC_GET_RTS 17 */ /* no longer supported */
+/* #define WLC_SET_RTS 18 */ /* no longer supported */
+#define WLC_GET_INFRA 19
+#define WLC_SET_INFRA 20
+#define WLC_GET_AUTH 21
+#define WLC_SET_AUTH 22
+#define WLC_GET_BSSID 23
+#define WLC_SET_BSSID 24
+#define WLC_GET_SSID 25
+#define WLC_SET_SSID 26
+#define WLC_RESTART 27
+#define WLC_TERMINATED 28
+/* #define WLC_DUMP_SCB 28 */ /* no longer supported */
+#define WLC_GET_CHANNEL 29
+#define WLC_SET_CHANNEL 30
+#define WLC_GET_SRL 31
+#define WLC_SET_SRL 32
+#define WLC_GET_LRL 33
+#define WLC_SET_LRL 34
+#define WLC_GET_PLCPHDR 35
+#define WLC_SET_PLCPHDR 36
+#define WLC_GET_RADIO 37
+#define WLC_SET_RADIO 38
+#define WLC_GET_PHYTYPE 39
+#define WLC_DUMP_RATE 40
+#define WLC_SET_RATE_PARAMS 41
+#define WLC_GET_FIXRATE 42
+#define WLC_SET_FIXRATE 43
+/* #define WLC_GET_WEP 42 */ /* no longer supported */
+/* #define WLC_SET_WEP 43 */ /* no longer supported */
+#define WLC_GET_KEY 44
+#define WLC_SET_KEY 45
+#define WLC_GET_REGULATORY 46
+#define WLC_SET_REGULATORY 47
+#define WLC_GET_PASSIVE_SCAN 48
+#define WLC_SET_PASSIVE_SCAN 49
+#define WLC_SCAN 50
+#define WLC_SCAN_RESULTS 51
+#define WLC_DISASSOC 52
+#define WLC_REASSOC 53
+#define WLC_GET_ROAM_TRIGGER 54
+#define WLC_SET_ROAM_TRIGGER 55
+#define WLC_GET_ROAM_DELTA 56
+#define WLC_SET_ROAM_DELTA 57
+#define WLC_GET_ROAM_SCAN_PERIOD 58
+#define WLC_SET_ROAM_SCAN_PERIOD 59
+#define WLC_EVM 60 /* diag */
+#define WLC_GET_TXANT 61
+#define WLC_SET_TXANT 62
+#define WLC_GET_ANTDIV 63
+#define WLC_SET_ANTDIV 64
+/* #define WLC_GET_TXPWR 65 */ /* no longer supported */
+/* #define WLC_SET_TXPWR 66 */ /* no longer supported */
+#define WLC_GET_CLOSED 67
+#define WLC_SET_CLOSED 68
+#define WLC_GET_MACLIST 69
+#define WLC_SET_MACLIST 70
+#define WLC_GET_RATESET 71
+#define WLC_SET_RATESET 72
+/* #define WLC_GET_LOCALE 73 */ /* no longer supported */
+#define WLC_LONGTRAIN 74
+#define WLC_GET_BCNPRD 75
+#define WLC_SET_BCNPRD 76
+#define WLC_GET_DTIMPRD 77
+#define WLC_SET_DTIMPRD 78
+#define WLC_GET_SROM 79
+#define WLC_SET_SROM 80
+#define WLC_GET_WEP_RESTRICT 81
+#define WLC_SET_WEP_RESTRICT 82
+#define WLC_GET_COUNTRY 83
+#define WLC_SET_COUNTRY 84
+#define WLC_GET_PM 85
+#define WLC_SET_PM 86
+#define WLC_GET_WAKE 87
+#define WLC_SET_WAKE 88
+/* #define WLC_GET_D11CNTS 89 */ /* -> "counters" iovar */
+#define WLC_GET_FORCELINK 90 /* ndis only */
+#define WLC_SET_FORCELINK 91 /* ndis only */
+#define WLC_FREQ_ACCURACY 92 /* diag */
+#define WLC_CARRIER_SUPPRESS 93 /* diag */
+#define WLC_GET_PHYREG 94
+#define WLC_SET_PHYREG 95
+#define WLC_GET_RADIOREG 96
+#define WLC_SET_RADIOREG 97
+#define WLC_GET_REVINFO 98
+#define WLC_GET_UCANTDIV 99
+#define WLC_SET_UCANTDIV 100
+#define WLC_R_REG 101
+#define WLC_W_REG 102
+/* #define WLC_DIAG_LOOPBACK 103 old tray diag */
+/* #define WLC_RESET_D11CNTS 104 */ /* -> "reset_d11cnts" iovar */
+#define WLC_GET_MACMODE 105
+#define WLC_SET_MACMODE 106
+#define WLC_GET_MONITOR 107
+#define WLC_SET_MONITOR 108
+#define WLC_GET_GMODE 109
+#define WLC_SET_GMODE 110
+#define WLC_GET_LEGACY_ERP 111
+#define WLC_SET_LEGACY_ERP 112
+#define WLC_GET_RX_ANT 113
+#define WLC_GET_CURR_RATESET 114 /* current rateset */
+#define WLC_GET_SCANSUPPRESS 115
+#define WLC_SET_SCANSUPPRESS 116
+#define WLC_GET_AP 117
+#define WLC_SET_AP 118
+#define WLC_GET_EAP_RESTRICT 119
+#define WLC_SET_EAP_RESTRICT 120
+#define WLC_SCB_AUTHORIZE 121
+#define WLC_SCB_DEAUTHORIZE 122
+#define WLC_GET_WDSLIST 123
+#define WLC_SET_WDSLIST 124
+#define WLC_GET_ATIM 125
+#define WLC_SET_ATIM 126
+#define WLC_GET_RSSI 127
+#define WLC_GET_PHYANTDIV 128
+#define WLC_SET_PHYANTDIV 129
+#define WLC_AP_RX_ONLY 130
+#define WLC_GET_TX_PATH_PWR 131
+#define WLC_SET_TX_PATH_PWR 132
+#define WLC_GET_WSEC 133
+#define WLC_SET_WSEC 134
+#define WLC_GET_PHY_NOISE 135
+#define WLC_GET_BSS_INFO 136
+#define WLC_GET_PKTCNTS 137
+#define WLC_GET_LAZYWDS 138
+#define WLC_SET_LAZYWDS 139
+#define WLC_GET_BANDLIST 140
+
+#define WLC_GET_BAND 141
+#define WLC_SET_BAND 142
+#define WLC_SCB_DEAUTHENTICATE 143
+#define WLC_GET_SHORTSLOT 144
+#define WLC_GET_SHORTSLOT_OVERRIDE 145
+#define WLC_SET_SHORTSLOT_OVERRIDE 146
+#define WLC_GET_SHORTSLOT_RESTRICT 147
+#define WLC_SET_SHORTSLOT_RESTRICT 148
+#define WLC_GET_GMODE_PROTECTION 149
+#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150
+#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151
+#define WLC_UPGRADE 152
+/* #define WLC_GET_MRATE 153 */ /* no longer supported */
+/* #define WLC_SET_MRATE 154 */ /* no longer supported */
+#define WLC_GET_IGNORE_BCNS 155
+#define WLC_SET_IGNORE_BCNS 156
+#define WLC_GET_SCB_TIMEOUT 157
+#define WLC_SET_SCB_TIMEOUT 158
+#define WLC_GET_ASSOCLIST 159
+#define WLC_GET_CLK 160
+#define WLC_SET_CLK 161
+#define WLC_GET_UP 162
+#define WLC_OUT 163
+#define WLC_GET_WPA_AUTH 164
+#define WLC_SET_WPA_AUTH 165
+#define WLC_GET_UCFLAGS 166
+#define WLC_SET_UCFLAGS 167
+#define WLC_GET_PWRIDX 168
+#define WLC_SET_PWRIDX 169
+#define WLC_GET_TSSI 170
+#define WLC_GET_SUP_RATESET_OVERRIDE 171
+#define WLC_SET_SUP_RATESET_OVERRIDE 172
+/* #define WLC_SET_FAST_TIMER 173 */ /* no longer supported */
+/* #define WLC_GET_FAST_TIMER 174 */ /* no longer supported */
+/* #define WLC_SET_SLOW_TIMER 175 */ /* no longer supported */
+/* #define WLC_GET_SLOW_TIMER 176 */ /* no longer supported */
+/* #define WLC_DUMP_PHYREGS 177 */ /* no longer supported */
+#define WLC_GET_PROTECTION_CONTROL 178
+#define WLC_SET_PROTECTION_CONTROL 179
+#define WLC_GET_PHYLIST 180
+#define WLC_ENCRYPT_STRENGTH 181 /* ndis only */
+#define WLC_DECRYPT_STATUS 182 /* ndis only */
+#define WLC_GET_KEY_SEQ 183
+#define WLC_GET_SCAN_CHANNEL_TIME 184
+#define WLC_SET_SCAN_CHANNEL_TIME 185
+#define WLC_GET_SCAN_UNASSOC_TIME 186
+#define WLC_SET_SCAN_UNASSOC_TIME 187
+#define WLC_GET_SCAN_HOME_TIME 188
+#define WLC_SET_SCAN_HOME_TIME 189
+#define WLC_GET_SCAN_NPROBES 190
+#define WLC_SET_SCAN_NPROBES 191
+#define WLC_GET_PRB_RESP_TIMEOUT 192
+#define WLC_SET_PRB_RESP_TIMEOUT 193
+#define WLC_GET_ATTEN 194
+#define WLC_SET_ATTEN 195
+#define WLC_GET_SHMEM 196 /* diag */
+#define WLC_SET_SHMEM 197 /* diag */
+/* #define WLC_GET_GMODE_PROTECTION_CTS 198 */ /* no longer supported */
+/* #define WLC_SET_GMODE_PROTECTION_CTS 199 */ /* no longer supported */
+#define WLC_SET_WSEC_TEST 200
+#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201
+#define WLC_TKIP_COUNTERMEASURES 202
+#define WLC_GET_PIOMODE 203
+#define WLC_SET_PIOMODE 204
+#define WLC_SET_ASSOC_PREFER 205
+#define WLC_GET_ASSOC_PREFER 206
+#define WLC_SET_ROAM_PREFER 207
+#define WLC_GET_ROAM_PREFER 208
+#define WLC_SET_LED 209
+#define WLC_GET_LED 210
+#define WLC_GET_INTERFERENCE_MODE 211
+#define WLC_SET_INTERFERENCE_MODE 212
+#define WLC_GET_CHANNEL_QA 213
+#define WLC_START_CHANNEL_QA 214
+#define WLC_GET_CHANNEL_SEL 215
+#define WLC_START_CHANNEL_SEL 216
+#define WLC_GET_VALID_CHANNELS 217
+#define WLC_GET_FAKEFRAG 218
+#define WLC_SET_FAKEFRAG 219
+#define WLC_GET_PWROUT_PERCENTAGE 220
+#define WLC_SET_PWROUT_PERCENTAGE 221
+#define WLC_SET_BAD_FRAME_PREEMPT 222
+#define WLC_GET_BAD_FRAME_PREEMPT 223
+#define WLC_SET_LEAP_LIST 224
+#define WLC_GET_LEAP_LIST 225
+#define WLC_GET_CWMIN 226
+#define WLC_SET_CWMIN 227
+#define WLC_GET_CWMAX 228
+#define WLC_SET_CWMAX 229
+#define WLC_GET_WET 230
+#define WLC_SET_WET 231
+#define WLC_GET_PUB 232
+/* #define WLC_SET_GLACIAL_TIMER 233 */ /* no longer supported */
+/* #define WLC_GET_GLACIAL_TIMER 234 */ /* no longer supported */
+#define WLC_GET_KEY_PRIMARY 235
+#define WLC_SET_KEY_PRIMARY 236
+
+
+/* #define WLC_DUMP_RADIOREGS 237 */ /* no longer supported */
+#define WLC_GET_ACI_ARGS 238
+#define WLC_SET_ACI_ARGS 239
+#define WLC_UNSET_CALLBACK 240
+#define WLC_SET_CALLBACK 241
+#define WLC_GET_RADAR 242
+#define WLC_SET_RADAR 243
+#define WLC_SET_SPECT_MANAGMENT 244
+#define WLC_GET_SPECT_MANAGMENT 245
+#define WLC_WDS_GET_REMOTE_HWADDR 246 /* handled in wl_linux.c/wl_vx.c */
+#define WLC_WDS_GET_WPA_SUP 247
+#define WLC_SET_CS_SCAN_TIMER 248
+#define WLC_GET_CS_SCAN_TIMER 249
+#define WLC_MEASURE_REQUEST 250
+#define WLC_INIT 251
+#define WLC_SEND_QUIET 252
+#define WLC_KEEPALIVE 253
+#define WLC_SEND_PWR_CONSTRAINT 254
+#define WLC_UPGRADE_STATUS 255
+#define WLC_CURRENT_PWR 256
+#define WLC_GET_SCAN_PASSIVE_TIME 257
+#define WLC_SET_SCAN_PASSIVE_TIME 258
+#define WLC_LEGACY_LINK_BEHAVIOR 259
+#define WLC_GET_CHANNELS_IN_COUNTRY 260
+#define WLC_GET_COUNTRY_LIST 261
+#define WLC_GET_VAR 262 /* get value of named variable */
+#define WLC_SET_VAR 263 /* set named variable to value */
+#define WLC_NVRAM_GET 264 /* deprecated */
+#define WLC_NVRAM_SET 265
+#define WLC_NVRAM_DUMP 266
+#define WLC_REBOOT 267
+#define WLC_SET_WSEC_PMK 268
+#define WLC_GET_AUTH_MODE 269
+#define WLC_SET_AUTH_MODE 270
+#define WLC_GET_WAKEENTRY 271
+#define WLC_SET_WAKEENTRY 272
+#define WLC_NDCONFIG_ITEM 273 /* currently handled in wl_oid.c */
+#define WLC_NVOTPW 274
+#define WLC_OTPW 275
+#define WLC_IOV_BLOCK_GET 276
+#define WLC_IOV_MODULES_GET 277
+#define WLC_SOFT_RESET 278
+#define WLC_GET_ALLOW_MODE 279
+#define WLC_SET_ALLOW_MODE 280
+#define WLC_GET_DESIRED_BSSID 281
+#define WLC_SET_DESIRED_BSSID 282
+#define WLC_DISASSOC_MYAP 283
+#define WLC_GET_NBANDS 284 /* for Dongle EXT_STA support */
+#define WLC_GET_BANDSTATES 285 /* for Dongle EXT_STA support */
+#define WLC_GET_WLC_BSS_INFO 286 /* for Dongle EXT_STA support */
+#define WLC_GET_ASSOC_INFO 287 /* for Dongle EXT_STA support */
+#define WLC_GET_OID_PHY 288 /* for Dongle EXT_STA support */
+#define WLC_SET_OID_PHY 289 /* for Dongle EXT_STA support */
+#define WLC_SET_ASSOC_TIME 290 /* for Dongle EXT_STA support */
+#define WLC_GET_DESIRED_SSID 291 /* for Dongle EXT_STA support */
+#define WLC_GET_CHANSPEC 292 /* for Dongle EXT_STA support */
+#define WLC_GET_ASSOC_STATE 293 /* for Dongle EXT_STA support */
+#define WLC_SET_PHY_STATE 294 /* for Dongle EXT_STA support */
+#define WLC_GET_SCAN_PENDING 295 /* for Dongle EXT_STA support */
+#define WLC_GET_SCANREQ_PENDING 296 /* for Dongle EXT_STA support */
+#define WLC_GET_PREV_ROAM_REASON 297 /* for Dongle EXT_STA support */
+#define WLC_SET_PREV_ROAM_REASON 298 /* for Dongle EXT_STA support */
+#define WLC_GET_BANDSTATES_PI 299 /* for Dongle EXT_STA support */
+#define WLC_GET_PHY_STATE 300 /* for Dongle EXT_STA support */
+#define WLC_GET_BSS_WPA_RSN 301 /* for Dongle EXT_STA support */
+#define WLC_GET_BSS_WPA2_RSN 302 /* for Dongle EXT_STA support */
+#define WLC_GET_BSS_BCN_TS 303 /* for Dongle EXT_STA support */
+#define WLC_GET_INT_DISASSOC 304 /* for Dongle EXT_STA support */
+#define WLC_SET_NUM_PEERS 305 /* for Dongle EXT_STA support */
+#define WLC_GET_NUM_BSS 306 /* for Dongle EXT_STA support */
+#define WLC_PHY_SAMPLE_COLLECT 307 /* phy sample collect mode */
+/* #define WLC_UM_PRIV 308 */ /* Deprecated: usermode driver */
+#define WLC_GET_CMD 309
+/* #define WLC_LAST 310 */ /* Never used - can be reused */
+#define WLC_SET_INTERFERENCE_OVERRIDE_MODE 311 /* set inter mode override */
+#define WLC_GET_INTERFERENCE_OVERRIDE_MODE 312 /* get inter mode override */
+/* #define WLC_GET_WAI_RESTRICT 313 */ /* for WAPI, deprecated use iovar instead */
+/* #define WLC_SET_WAI_RESTRICT 314 */ /* for WAPI, deprecated use iovar instead */
+/* #define WLC_SET_WAI_REKEY 315 */ /* for WAPI, deprecated use iovar instead */
+#define WLC_SET_NAT_CONFIG 316 /* for configuring NAT filter driver */
+#define WLC_GET_NAT_STATE 317
+#define WLC_GET_TXBF_RATESET 318
+#define WLC_SET_TXBF_RATESET 319
+#define WLC_SCAN_CQ 320
+#define WLC_GET_RSSI_QDB 321 /* qdB portion of the RSSI */
+
+#define WLC_LAST 322
+#ifndef EPICTRL_COOKIE
+#define EPICTRL_COOKIE 0xABADCEDE
+#endif
+
+/* vx wlc ioctl's offset */
+#define CMN_IOCTL_OFF 0x180
+
+/*
+ * custom OID support
+ *
+ * 0xFF - implementation specific OID
+ * 0xE4 - first byte of Broadcom PCI vendor ID
+ * 0x14 - second byte of Broadcom PCI vendor ID
+ * 0xXX - the custom OID number
+ */
+
+/* begin 0x1f values beyond the start of the ET driver range. */
+#define WL_OID_BASE 0xFFE41420
+
+/* NDIS overrides */
+#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE)
+#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK)
+#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK)
+#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH)
+#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS)
+#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR)
+#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM)
+
+/* EXT_STA Dongle suuport */
+#define OID_STA_CHANSPEC (WL_OID_BASE + WLC_GET_CHANSPEC)
+#define OID_STA_NBANDS (WL_OID_BASE + WLC_GET_NBANDS)
+#define OID_STA_GET_PHY (WL_OID_BASE + WLC_GET_OID_PHY)
+#define OID_STA_SET_PHY (WL_OID_BASE + WLC_SET_OID_PHY)
+#define OID_STA_ASSOC_TIME (WL_OID_BASE + WLC_SET_ASSOC_TIME)
+#define OID_STA_DESIRED_SSID (WL_OID_BASE + WLC_GET_DESIRED_SSID)
+#define OID_STA_SET_PHY_STATE (WL_OID_BASE + WLC_SET_PHY_STATE)
+#define OID_STA_SCAN_PENDING (WL_OID_BASE + WLC_GET_SCAN_PENDING)
+#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING)
+#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON)
+#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON)
+#define OID_STA_GET_PHY_STATE (WL_OID_BASE + WLC_GET_PHY_STATE)
+#define OID_STA_INT_DISASSOC (WL_OID_BASE + WLC_GET_INT_DISASSOC)
+#define OID_STA_SET_NUM_PEERS (WL_OID_BASE + WLC_SET_NUM_PEERS)
+#define OID_STA_GET_NUM_BSS (WL_OID_BASE + WLC_GET_NUM_BSS)
+
+/* NAT filter driver support */
+#define OID_NAT_SET_CONFIG (WL_OID_BASE + WLC_SET_NAT_CONFIG)
+#define OID_NAT_GET_STATE (WL_OID_BASE + WLC_GET_NAT_STATE)
+
+#define WL_DECRYPT_STATUS_SUCCESS 1
+#define WL_DECRYPT_STATUS_FAILURE 2
+#define WL_DECRYPT_STATUS_UNKNOWN 3
+
+/* allows user-mode app to poll the status of USB image upgrade */
+#define WLC_UPGRADE_SUCCESS 0
+#define WLC_UPGRADE_PENDING 1
+
+/* WLC_GET_AUTH, WLC_SET_AUTH values */
+#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */
+#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
+#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */
+
+/* a large TX Power as an init value to factor out of MIN() calculations,
+ * keep low enough to fit in an int8, units are .25 dBm
+ */
+#define WLC_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */
+
+/* "diag" iovar argument and error code */
+#define WL_DIAG_INTERRUPT 1 /* d11 loopback interrupt test */
+#define WL_DIAG_LOOPBACK 2 /* d11 loopback data test */
+#define WL_DIAG_MEMORY 3 /* d11 memory test */
+#define WL_DIAG_LED 4 /* LED test */
+#define WL_DIAG_REG 5 /* d11/phy register test */
+#define WL_DIAG_SROM 6 /* srom read/crc test */
+#define WL_DIAG_DMA 7 /* DMA test */
+#define WL_DIAG_LOOPBACK_EXT 8 /* enhenced d11 loopback data test */
+
+#define WL_DIAGERR_SUCCESS 0
+#define WL_DIAGERR_FAIL_TO_RUN 1 /* unable to run requested diag */
+#define WL_DIAGERR_NOT_SUPPORTED 2 /* diag requested is not supported */
+#define WL_DIAGERR_INTERRUPT_FAIL 3 /* loopback interrupt test failed */
+#define WL_DIAGERR_LOOPBACK_FAIL 4 /* loopback data test failed */
+#define WL_DIAGERR_SROM_FAIL 5 /* srom read failed */
+#define WL_DIAGERR_SROM_BADCRC 6 /* srom crc failed */
+#define WL_DIAGERR_REG_FAIL 7 /* d11/phy register test failed */
+#define WL_DIAGERR_MEMORY_FAIL 8 /* d11 memory test failed */
+#define WL_DIAGERR_NOMEM 9 /* diag test failed due to no memory */
+#define WL_DIAGERR_DMA_FAIL 10 /* DMA test failed */
+
+#define WL_DIAGERR_MEMORY_TIMEOUT 11 /* d11 memory test didn't finish in time */
+#define WL_DIAGERR_MEMORY_BADPATTERN 12 /* d11 memory test result in bad pattern */
+
+/* band types */
+#define WLC_BAND_AUTO 0 /* auto-select */
+#define WLC_BAND_5G 1 /* 5 Ghz */
+#define WLC_BAND_2G 2 /* 2.4 Ghz */
+#define WLC_BAND_ALL 3 /* all bands */
+
+/* band range returned by band_range iovar */
+#define WL_CHAN_FREQ_RANGE_2G 0
+#define WL_CHAN_FREQ_RANGE_5GL 1
+#define WL_CHAN_FREQ_RANGE_5GM 2
+#define WL_CHAN_FREQ_RANGE_5GH 3
+
+#define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4
+#define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5
+#define WL_CHAN_FREQ_RANGE_5GML_5BAND 6
+#define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7
+#define WL_CHAN_FREQ_RANGE_5GH_5BAND 8
+
+#define WL_CHAN_FREQ_RANGE_5G_BAND0 1
+#define WL_CHAN_FREQ_RANGE_5G_BAND1 2
+#define WL_CHAN_FREQ_RANGE_5G_BAND2 3
+#define WL_CHAN_FREQ_RANGE_5G_BAND3 4
+
+#define WL_CHAN_FREQ_RANGE_5G_4BAND 5
+
+/* MAC list modes */
+#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */
+#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */
+#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */
+
+/*
+ * 54g modes (basic bits may still be overridden)
+ *
+ * GMODE_LEGACY_B Rateset: 1b, 2b, 5.5, 11
+ * Preamble: Long
+ * Shortslot: Off
+ * GMODE_AUTO Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ * Extended Rateset: 6, 9, 12, 48
+ * Preamble: Long
+ * Shortslot: Auto
+ * GMODE_ONLY Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
+ * Extended Rateset: 6b, 9, 12b, 48
+ * Preamble: Short required
+ * Shortslot: Auto
+ * GMODE_B_DEFERRED Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ * Extended Rateset: 6, 9, 12, 48
+ * Preamble: Long
+ * Shortslot: On
+ * GMODE_PERFORMANCE Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
+ * Preamble: Short required
+ * Shortslot: On and required
+ * GMODE_LRS Rateset: 1b, 2b, 5.5b, 11b
+ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
+ * Preamble: Long
+ * Shortslot: Auto
+ */
+#define GMODE_LEGACY_B 0
+#define GMODE_AUTO 1
+#define GMODE_ONLY 2
+#define GMODE_B_DEFERRED 3
+#define GMODE_PERFORMANCE 4
+#define GMODE_LRS 5
+#define GMODE_MAX 6
+
+/* values for PLCPHdr_override */
+#define WLC_PLCP_AUTO -1
+#define WLC_PLCP_SHORT 0
+#define WLC_PLCP_LONG 1
+
+/* values for g_protection_override and n_protection_override */
+#define WLC_PROTECTION_AUTO -1
+#define WLC_PROTECTION_OFF 0
+#define WLC_PROTECTION_ON 1
+#define WLC_PROTECTION_MMHDR_ONLY 2
+#define WLC_PROTECTION_CTS_ONLY 3
+
+/* values for g_protection_control and n_protection_control */
+#define WLC_PROTECTION_CTL_OFF 0
+#define WLC_PROTECTION_CTL_LOCAL 1
+#define WLC_PROTECTION_CTL_OVERLAP 2
+
+/* values for n_protection */
+#define WLC_N_PROTECTION_OFF 0
+#define WLC_N_PROTECTION_OPTIONAL 1
+#define WLC_N_PROTECTION_20IN40 2
+#define WLC_N_PROTECTION_MIXEDMODE 3
+
+/* values for n_preamble_type */
+#define WLC_N_PREAMBLE_MIXEDMODE 0
+#define WLC_N_PREAMBLE_GF 1
+#define WLC_N_PREAMBLE_GF_BRCM 2
+
+/* values for band specific 40MHz capabilities (deprecated) */
+#define WLC_N_BW_20ALL 0
+#define WLC_N_BW_40ALL 1
+#define WLC_N_BW_20IN2G_40IN5G 2
+
+#define WLC_BW_20MHZ_BIT (1<<0)
+#define WLC_BW_40MHZ_BIT (1<<1)
+#define WLC_BW_80MHZ_BIT (1<<2)
+#define WLC_BW_160MHZ_BIT (1<<3)
+
+/* Bandwidth capabilities */
+#define WLC_BW_CAP_20MHZ (WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_40MHZ (WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_80MHZ (WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_160MHZ (WLC_BW_160MHZ_BIT|WLC_BW_80MHZ_BIT| \
+ WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_UNRESTRICTED 0xFF
+
+#define WL_BW_CAP_20MHZ(bw_cap) (((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_40MHZ(bw_cap) (((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_80MHZ(bw_cap) (((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_160MHZ(bw_cap)(((bw_cap) & WLC_BW_160MHZ_BIT) ? TRUE : FALSE)
+
+/* values to force tx/rx chain */
+#define WLC_N_TXRX_CHAIN0 0
+#define WLC_N_TXRX_CHAIN1 1
+
+/* bitflags for SGI support (sgi_rx iovar) */
+#define WLC_N_SGI_20 0x01
+#define WLC_N_SGI_40 0x02
+#define WLC_VHT_SGI_80 0x04
+
+/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */
+#define WLC_SGI_ALL 0x02
+
+#define LISTEN_INTERVAL 10
+/* interference mitigation options */
+#define INTERFERE_OVRRIDE_OFF -1 /* interference override off */
+#define INTERFERE_NONE 0 /* off */
+#define NON_WLAN 1 /* foreign/non 802.11 interference, no auto detect */
+#define WLAN_MANUAL 2 /* ACI: no auto detection */
+#define WLAN_AUTO 3 /* ACI: auto detect */
+#define WLAN_AUTO_W_NOISE 4 /* ACI: auto - detect and non 802.11 interference */
+#define AUTO_ACTIVE (1 << 7) /* Auto is currently active */
+
+/* interfernece mode bit-masks (ACPHY) */
+#define ACPHY_ACI_GLITCHBASED_DESENSE 1 /* bit 0 */
+#define ACPHY_ACI_HWACI_PKTGAINLMT 2 /* bit 1 */
+#define ACPHY_ACI_W2NB_PKTGAINLMT 4 /* bit 2 */
+#define ACPHY_ACI_PREEMPTION 8 /* bit 3 */
+#define ACPHY_ACI_MAX_MODE 15
+
+/* AP environment */
+#define AP_ENV_DETECT_NOT_USED 0 /* We aren't using AP environment detection */
+#define AP_ENV_DENSE 1 /* "Corporate" or other AP dense environment */
+#define AP_ENV_SPARSE 2 /* "Home" or other sparse environment */
+#define AP_ENV_INDETERMINATE 3 /* AP environment hasn't been identified */
+
+#define TRIGGER_NOW 0
+#define TRIGGER_CRS 0x01
+#define TRIGGER_CRSDEASSERT 0x02
+#define TRIGGER_GOODFCS 0x04
+#define TRIGGER_BADFCS 0x08
+#define TRIGGER_BADPLCP 0x10
+#define TRIGGER_CRSGLITCH 0x20
+
+#define WL_SAMPLEDATA_HEADER_TYPE 1
+#define WL_SAMPLEDATA_HEADER_SIZE 80 /* sample collect header size (bytes) */
+#define WL_SAMPLEDATA_TYPE 2
+#define WL_SAMPLEDATA_SEQ 0xff /* sequence # */
+#define WL_SAMPLEDATA_MORE_DATA 0x100 /* more data mask */
+
+/* WL_OTA START */
+#define WL_OTA_ARG_PARSE_BLK_SIZE 1200
+#define WL_OTA_TEST_MAX_NUM_RATE 30
+#define WL_OTA_TEST_MAX_NUM_SEQ 100
+
+#define WL_THRESHOLD_LO_BAND 70 /* range from 5250MHz - 5350MHz */
+
+/* radar iovar SET defines */
+#define WL_RADAR_DETECTOR_OFF 0 /* radar detector off */
+#define WL_RADAR_DETECTOR_ON 1 /* radar detector on */
+#define WL_RADAR_SIMULATED 2 /* force radar detector to declare
+ * detection once
+ */
+#define WL_RSSI_ANT_VERSION 1 /* current version of wl_rssi_ant_t */
+#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */
+#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */
+#define WL_ANT_IDX_1 0 /* antenna index 1 */
+#define WL_ANT_IDX_2 1 /* antenna index 2 */
+
+#ifndef WL_RSSI_ANT_MAX
+#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */
+#elif WL_RSSI_ANT_MAX != 4
+#error "WL_RSSI_ANT_MAX does not match"
+#endif
+
+/* dfs_status iovar-related defines */
+
+/* cac - channel availability check,
+ * ism - in-service monitoring
+ * csa - channel switching announcement
+ */
+
+/* cac state values */
+#define WL_DFS_CACSTATE_IDLE 0 /* state for operating in non-radar channel */
+#define WL_DFS_CACSTATE_PREISM_CAC 1 /* CAC in progress */
+#define WL_DFS_CACSTATE_ISM 2 /* ISM in progress */
+#define WL_DFS_CACSTATE_CSA 3 /* csa */
+#define WL_DFS_CACSTATE_POSTISM_CAC 4 /* ISM CAC */
+#define WL_DFS_CACSTATE_PREISM_OOC 5 /* PREISM OOC */
+#define WL_DFS_CACSTATE_POSTISM_OOC 6 /* POSTISM OOC */
+#define WL_DFS_CACSTATES 7 /* this many states exist */
+
+/* Defines used with channel_bandwidth for curpower */
+#define WL_BW_20MHZ 0
+#define WL_BW_40MHZ 1
+#define WL_BW_80MHZ 2
+#define WL_BW_160MHZ 3
+
+/* tx_power_t.flags bits */
+#define WL_TX_POWER_F_ENABLED 1
+#define WL_TX_POWER_F_HW 2
+#define WL_TX_POWER_F_MIMO 4
+#define WL_TX_POWER_F_SISO 8
+#define WL_TX_POWER_F_HT 0x10
+#define WL_TX_POWER_F_VHT 0x20
+#define WL_TX_POWER_F_OPENLOOP 0x40
+
+/* Message levels */
+#define WL_ERROR_VAL 0x00000001
+#define WL_TRACE_VAL 0x00000002
+#define WL_PRHDRS_VAL 0x00000004
+#define WL_PRPKT_VAL 0x00000008
+#define WL_INFORM_VAL 0x00000010
+#define WL_TMP_VAL 0x00000020
+#define WL_OID_VAL 0x00000040
+#define WL_RATE_VAL 0x00000080
+#define WL_ASSOC_VAL 0x00000100
+#define WL_PRUSR_VAL 0x00000200
+#define WL_PS_VAL 0x00000400
+#define WL_TXPWR_VAL 0x00000800 /* retired in TOT on 6/10/2009 */
+#define WL_PORT_VAL 0x00001000
+#define WL_DUAL_VAL 0x00002000
+#define WL_WSEC_VAL 0x00004000
+#define WL_WSEC_DUMP_VAL 0x00008000
+#define WL_LOG_VAL 0x00010000
+#define WL_NRSSI_VAL 0x00020000 /* retired in TOT on 6/10/2009 */
+#define WL_LOFT_VAL 0x00040000 /* retired in TOT on 6/10/2009 */
+#define WL_REGULATORY_VAL 0x00080000
+#define WL_PHYCAL_VAL 0x00100000 /* retired in TOT on 6/10/2009 */
+#define WL_RADAR_VAL 0x00200000 /* retired in TOT on 6/10/2009 */
+#define WL_MPC_VAL 0x00400000
+#define WL_APSTA_VAL 0x00800000
+#define WL_DFS_VAL 0x01000000
+#define WL_BA_VAL 0x02000000 /* retired in TOT on 6/14/2010 */
+#define WL_ACI_VAL 0x04000000
+#define WL_MBSS_VAL 0x04000000
+#define WL_CAC_VAL 0x08000000
+#define WL_AMSDU_VAL 0x10000000
+#define WL_AMPDU_VAL 0x20000000
+#define WL_FFPLD_VAL 0x40000000
+
+/* wl_msg_level is full. For new bits take the next one and AND with
+ * wl_msg_level2 in wl_dbg.h
+ */
+#define WL_DPT_VAL 0x00000001
+#define WL_SCAN_VAL 0x00000002
+#define WL_WOWL_VAL 0x00000004
+#define WL_COEX_VAL 0x00000008
+#define WL_RTDC_VAL 0x00000010
+#define WL_PROTO_VAL 0x00000020
+#define WL_BTA_VAL 0x00000040
+#define WL_CHANINT_VAL 0x00000080
+#define WL_WMF_VAL 0x00000100
+#define WL_P2P_VAL 0x00000200
+#define WL_ITFR_VAL 0x00000400
+#define WL_MCHAN_VAL 0x00000800
+#define WL_TDLS_VAL 0x00001000
+#define WL_MCNX_VAL 0x00002000
+#define WL_PROT_VAL 0x00004000
+#define WL_PSTA_VAL 0x00008000
+#define WL_TSO_VAL 0x00010000
+#define WL_TRF_MGMT_VAL 0x00020000
+#define WL_LPC_VAL 0x00040000
+#define WL_L2FILTER_VAL 0x00080000
+#define WL_TXBF_VAL 0x00100000
+#define WL_P2PO_VAL 0x00200000
+#define WL_TBTT_VAL 0x00400000
+#define WL_NIC_VAL 0x00800000
+#define WL_MQ_VAL 0x01000000
+
+/* This level is currently used in Phoenix2 only */
+#define WL_SRSCAN_VAL 0x02000000
+
+#define WL_WNM_VAL 0x04000000
+#define WL_PWRSEL_VAL 0x10000000
+#define WL_NET_DETECT_VAL 0x20000000
+#define WL_PCIE_VAL 0x40000000
+
+/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier
+ * rather than a message-type of its own
+ */
+#define WL_TIMESTAMP_VAL 0x80000000
+
+/* max # of leds supported by GPIO (gpio pin# == led index#) */
+#define WL_LED_NUMGPIO 32 /* gpio 0-31 */
+
+/* led per-pin behaviors */
+#define WL_LED_OFF 0 /* always off */
+#define WL_LED_ON 1 /* always on */
+#define WL_LED_ACTIVITY 2 /* activity */
+#define WL_LED_RADIO 3 /* radio enabled */
+#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */
+#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */
+#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */
+#define WL_LED_WI1 7
+#define WL_LED_WI2 8
+#define WL_LED_WI3 9
+#define WL_LED_ASSOC 10 /* associated state indicator */
+#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */
+#define WL_LED_ASSOCACT 12 /* on when associated; blink fast for activity */
+#define WL_LED_WI4 13
+#define WL_LED_WI5 14
+#define WL_LED_BLINKSLOW 15 /* blink slow */
+#define WL_LED_BLINKMED 16 /* blink med */
+#define WL_LED_BLINKFAST 17 /* blink fast */
+#define WL_LED_BLINKCUSTOM 18 /* blink custom */
+#define WL_LED_BLINKPERIODIC 19 /* blink periodic (custom 1000ms / off 400ms) */
+#define WL_LED_ASSOC_WITH_SEC 20 /* when connected with security */
+ /* keep on for 300 sec */
+#define WL_LED_START_OFF 21 /* off upon boot, could be turned on later */
+#define WL_LED_WI6 22
+#define WL_LED_WI7 23
+#define WL_LED_WI8 24
+#define WL_LED_NUMBEHAVIOR 25
+
+/* led behavior numeric value format */
+#define WL_LED_BEH_MASK 0x7f /* behavior mask */
+#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */
+
+/* number of bytes needed to define a proper bit mask for MAC event reporting */
+#define BCMIO_ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#define BCMIO_NBBY 8
+/* number of bytes needed to define a mask for MAC event reporting */
+#define WL_EVENTING_MASK_LEN (((WLC_E_LAST) / 8) + (((WLC_E_LAST % 8) > 0) ? 1 : 0))
+
+
+/* join preference types */
+#define WL_JOIN_PREF_RSSI 1 /* by RSSI */
+#define WL_JOIN_PREF_WPA 2 /* by akm and ciphers */
+#define WL_JOIN_PREF_BAND 3 /* by 802.11 band */
+#define WL_JOIN_PREF_RSSI_DELTA 4 /* by 802.11 band only if RSSI delta condition matches */
+#define WL_JOIN_PREF_TRANS_PREF 5 /* defined by requesting AP */
+
+/* band preference */
+#define WLJP_BAND_ASSOC_PREF 255 /* use what WLC_SET_ASSOC_PREFER ioctl specifies */
+
+/* any multicast cipher suite */
+#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00"
+
+/* 802.11h measurement types */
+#define WLC_MEASURE_TPC 1
+#define WLC_MEASURE_CHANNEL_BASIC 2
+#define WLC_MEASURE_CHANNEL_CCA 3
+#define WLC_MEASURE_CHANNEL_RPI 4
+
+/* regulatory enforcement levels */
+#define SPECT_MNGMT_OFF 0 /* both 11h and 11d disabled */
+#define SPECT_MNGMT_LOOSE_11H 1 /* allow non-11h APs in scan lists */
+#define SPECT_MNGMT_STRICT_11H 2 /* prune out non-11h APs from scan list */
+#define SPECT_MNGMT_STRICT_11D 3 /* switch to 802.11D mode */
+/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE
+ * adoption is done regardless of capability spectrum_management
+ */
+#define SPECT_MNGMT_LOOSE_11H_D 4 /* operation defined above */
+
+#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */
+#define WL_CHAN_VALID_SW (1 << 1) /* valid with current country setting */
+#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */
+#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */
+#define WL_CHAN_INACTIVE (1 << 4) /* temporarily inactive due to radar */
+#define WL_CHAN_PASSIVE (1 << 5) /* channel is in passive mode */
+#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */
+
+/* BTC mode used by "btc_mode" iovar */
+#define WL_BTC_DISABLE 0 /* disable BT coexistence */
+#define WL_BTC_FULLTDM 1 /* full TDM COEX */
+#define WL_BTC_ENABLE 1 /* full TDM COEX to maintain backward compatiblity */
+#define WL_BTC_PREMPT 2 /* full TDM COEX with preemption */
+#define WL_BTC_LITE 3 /* light weight coex for large isolation platform */
+#define WL_BTC_PARALLEL 4 /* BT and WLAN run in parallel with separate antenna */
+#define WL_BTC_HYBRID 5 /* hybrid coex, only ack is allowed to transmit in BT slot */
+#define WL_BTC_DEFAULT 8 /* set the default mode for the device */
+#define WL_INF_BTC_DISABLE 0
+#define WL_INF_BTC_ENABLE 1
+#define WL_INF_BTC_AUTO 3
+
+/* BTC wire used by "btc_wire" iovar */
+#define WL_BTC_DEFWIRE 0 /* use default wire setting */
+#define WL_BTC_2WIRE 2 /* use 2-wire BTC */
+#define WL_BTC_3WIRE 3 /* use 3-wire BTC */
+#define WL_BTC_4WIRE 4 /* use 4-wire BTC */
+
+/* BTC flags: BTC configuration that can be set by host */
+#define WL_BTC_FLAG_PREMPT (1 << 0)
+#define WL_BTC_FLAG_BT_DEF (1 << 1)
+#define WL_BTC_FLAG_ACTIVE_PROT (1 << 2)
+#define WL_BTC_FLAG_SIM_RSP (1 << 3)
+#define WL_BTC_FLAG_PS_PROTECT (1 << 4)
+#define WL_BTC_FLAG_SIM_TX_LP (1 << 5)
+#define WL_BTC_FLAG_ECI (1 << 6)
+#define WL_BTC_FLAG_LIGHT (1 << 7)
+#define WL_BTC_FLAG_PARALLEL (1 << 8)
+
+/* maximum channels returned by the get valid channels iovar */
+#define WL_NUMCHANNELS 64
+
+/* max number of chanspecs (used by the iovar to calc. buf space) */
+#define WL_NUMCHANSPECS 110
+
+/* WDS link local endpoint WPA role */
+#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */
+#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */
+#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */
+
+/* Base offset values */
+#define WL_PKT_FILTER_BASE_PKT 0
+#define WL_PKT_FILTER_BASE_END 1
+#define WL_PKT_FILTER_BASE_D11_H 2 /* May be removed */
+#define WL_PKT_FILTER_BASE_D11_D 3 /* May be removed */
+#define WL_PKT_FILTER_BASE_ETH_H 4
+#define WL_PKT_FILTER_BASE_ETH_D 5
+#define WL_PKT_FILTER_BASE_ARP_H 6
+#define WL_PKT_FILTER_BASE_ARP_D 7 /* May be removed */
+#define WL_PKT_FILTER_BASE_IP4_H 8
+#define WL_PKT_FILTER_BASE_IP4_D 9
+#define WL_PKT_FILTER_BASE_IP6_H 10
+#define WL_PKT_FILTER_BASE_IP6_D 11
+#define WL_PKT_FILTER_BASE_TCP_H 12
+#define WL_PKT_FILTER_BASE_TCP_D 13 /* May be removed */
+#define WL_PKT_FILTER_BASE_UDP_H 14
+#define WL_PKT_FILTER_BASE_UDP_D 15
+#define WL_PKT_FILTER_BASE_IP6_P 16
+#define WL_PKT_FILTER_BASE_COUNT 17 /* May be removed */
+
+/* String mapping for bases that may be used by applications or debug */
+#define WL_PKT_FILTER_BASE_NAMES \
+ { "START", WL_PKT_FILTER_BASE_PKT }, \
+ { "END", WL_PKT_FILTER_BASE_END }, \
+ { "ETH_H", WL_PKT_FILTER_BASE_ETH_H }, \
+ { "ETH_D", WL_PKT_FILTER_BASE_ETH_D }, \
+ { "D11_H", WL_PKT_FILTER_BASE_D11_H }, \
+ { "D11_D", WL_PKT_FILTER_BASE_D11_D }, \
+ { "ARP_H", WL_PKT_FILTER_BASE_ARP_H }, \
+ { "IP4_H", WL_PKT_FILTER_BASE_IP4_H }, \
+ { "IP4_D", WL_PKT_FILTER_BASE_IP4_D }, \
+ { "IP6_H", WL_PKT_FILTER_BASE_IP6_H }, \
+ { "IP6_D", WL_PKT_FILTER_BASE_IP6_D }, \
+ { "IP6_P", WL_PKT_FILTER_BASE_IP6_P }, \
+ { "TCP_H", WL_PKT_FILTER_BASE_TCP_H }, \
+ { "TCP_D", WL_PKT_FILTER_BASE_TCP_D }, \
+ { "UDP_H", WL_PKT_FILTER_BASE_UDP_H }, \
+ { "UDP_D", WL_PKT_FILTER_BASE_UDP_D }
+
+/* Flags for a pattern list element */
+#define WL_PKT_FILTER_MFLAG_NEG 0x0001
+
+/*
+ * Packet engine interface
+ */
+
+#define WL_PKTENG_PER_TX_START 0x01
+#define WL_PKTENG_PER_TX_STOP 0x02
+#define WL_PKTENG_PER_RX_START 0x04
+#define WL_PKTENG_PER_RX_WITH_ACK_START 0x05
+#define WL_PKTENG_PER_TX_WITH_ACK_START 0x06
+#define WL_PKTENG_PER_RX_STOP 0x08
+#define WL_PKTENG_PER_MASK 0xff
+
+#define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */
+
+#define WL_PKTENG_MAXPKTSZ 16384 /* max pktsz limit for pkteng */
+
+#define NUM_80211b_RATES 4
+#define NUM_80211ag_RATES 8
+#define NUM_80211n_RATES 32
+#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES)
+
+/*
+ * WOWL capability/override settings
+ */
+#define WL_WOWL_MAGIC (1 << 0) /* Wakeup on Magic packet */
+#define WL_WOWL_NET (1 << 1) /* Wakeup on Netpattern */
+#define WL_WOWL_DIS (1 << 2) /* Wakeup on loss-of-link due to Disassoc/Deauth */
+#define WL_WOWL_RETR (1 << 3) /* Wakeup on retrograde TSF */
+#define WL_WOWL_BCN (1 << 4) /* Wakeup on loss of beacon */
+#define WL_WOWL_TST (1 << 5) /* Wakeup after test */
+#define WL_WOWL_M1 (1 << 6) /* Wakeup after PTK refresh */
+#define WL_WOWL_EAPID (1 << 7) /* Wakeup after receipt of EAP-Identity Req */
+#define WL_WOWL_PME_GPIO (1 << 8) /* Wakeind via PME(0) or GPIO(1) */
+#define WL_WOWL_NEEDTKIP1 (1 << 9) /* need tkip phase 1 key to be updated by the driver */
+#define WL_WOWL_GTK_FAILURE (1 << 10) /* enable wakeup if GTK fails */
+#define WL_WOWL_EXTMAGPAT (1 << 11) /* support extended magic packets */
+#define WL_WOWL_ARPOFFLOAD (1 << 12) /* support ARP/NS/keepalive offloading */
+#define WL_WOWL_WPA2 (1 << 13) /* read protocol version for EAPOL frames */
+#define WL_WOWL_KEYROT (1 << 14) /* If the bit is set, use key rotaton */
+#define WL_WOWL_BCAST (1 << 15) /* If the bit is set, frm received was bcast frame */
+#define WL_WOWL_SCANOL (1 << 16) /* If the bit is set, scan offload is enabled */
+#define WL_WOWL_TCPKEEP_TIME (1 << 17) /* Wakeup on tcpkeep alive timeout */
+#define WL_WOWL_MDNS_CONFLICT (1 << 18) /* Wakeup on mDNS Conflict Resolution */
+#define WL_WOWL_MDNS_SERVICE (1 << 19) /* Wakeup on mDNS Service Connect */
+#define WL_WOWL_TCPKEEP_DATA (1 << 20) /* tcp keepalive got data */
+#define WL_WOWL_FW_HALT (1 << 21) /* Firmware died in wowl mode */
+#define WL_WOWL_ENAB_HWRADIO (1 << 22) /* Enable detection of radio button changes */
+#define WL_WOWL_MIC_FAIL (1 << 23) /* Offloads detected MIC failure(s) */
+#define WL_WOWL_LINKDOWN (1 << 31) /* Link Down indication in WoWL mode */
+
+#define WL_WOWL_TCPKEEP (1 << 20) /* temp copy to satisfy automerger */
+#define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */
+
+#define WOWL_PATTEN_TYPE_ARP (1 << 0) /* ARP offload Pattern */
+#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */
+
+#define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */
+#define MAGIC_PKT_NUM_MAC_ADDRS 16
+
+
+/* Overlap BSS Scan parameters default, minimum, maximum */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT 20 /* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN 5 /* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX 1000 /* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT 10 /* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN 10 /* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX 1000 /* unit TU */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT 300 /* unit Sec */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN 10 /* unit Sec */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX 900 /* unit Sec */
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT 5
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN 5
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX 100
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT 200 /* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN 200 /* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT 20 /* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN 20 /* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT 25 /* unit percent */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN 0 /* unit percent */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX 100 /* unit percent */
+
+#define WL_MIN_NUM_OBSS_SCAN_ARG 7 /* minimum number of arguments required for OBSS Scan */
+
+#define WL_COEX_INFO_MASK 0x07
+#define WL_COEX_INFO_REQ 0x01
+#define WL_COEX_40MHZ_INTOLERANT 0x02
+#define WL_COEX_WIDTH20 0x04
+
+#define WLC_RSSI_INVALID 0 /* invalid RSSI value */
+
+#define MAX_RSSI_LEVELS 8
+
+/* **** EXTLOG **** */
+#define EXTLOG_CUR_VER 0x0100
+
+#define MAX_ARGSTR_LEN 18 /* At least big enough for storing ETHER_ADDR_STR_LEN */
+
+/* log modules (bitmap) */
+#define LOG_MODULE_COMMON 0x0001
+#define LOG_MODULE_ASSOC 0x0002
+#define LOG_MODULE_EVENT 0x0004
+#define LOG_MODULE_MAX 3 /* Update when adding module */
+
+/* log levels */
+#define WL_LOG_LEVEL_DISABLE 0
+#define WL_LOG_LEVEL_ERR 1
+#define WL_LOG_LEVEL_WARN 2
+#define WL_LOG_LEVEL_INFO 3
+#define WL_LOG_LEVEL_MAX WL_LOG_LEVEL_INFO /* Update when adding level */
+
+/* flag */
+#define LOG_FLAG_EVENT 1
+
+/* log arg_type */
+#define LOG_ARGTYPE_NULL 0
+#define LOG_ARGTYPE_STR 1 /* %s */
+#define LOG_ARGTYPE_INT 2 /* %d */
+#define LOG_ARGTYPE_INT_STR 3 /* %d...%s */
+#define LOG_ARGTYPE_STR_INT 4 /* %s...%d */
+
+/* 802.11 Mgmt Packet flags */
+#define VNDR_IE_BEACON_FLAG 0x1
+#define VNDR_IE_PRBRSP_FLAG 0x2
+#define VNDR_IE_ASSOCRSP_FLAG 0x4
+#define VNDR_IE_AUTHRSP_FLAG 0x8
+#define VNDR_IE_PRBREQ_FLAG 0x10
+#define VNDR_IE_ASSOCREQ_FLAG 0x20
+#define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */
+#define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */
+
+#if defined(WLP2P)
+/* P2P Action Frames flags (spec ordered) */
+#define VNDR_IE_GONREQ_FLAG 0x001000
+#define VNDR_IE_GONRSP_FLAG 0x002000
+#define VNDR_IE_GONCFM_FLAG 0x004000
+#define VNDR_IE_INVREQ_FLAG 0x008000
+#define VNDR_IE_INVRSP_FLAG 0x010000
+#define VNDR_IE_DISREQ_FLAG 0x020000
+#define VNDR_IE_DISRSP_FLAG 0x040000
+#define VNDR_IE_PRDREQ_FLAG 0x080000
+#define VNDR_IE_PRDRSP_FLAG 0x100000
+
+#define VNDR_IE_P2PAF_SHIFT 12
+#endif /* WLP2P */
+
+/* channel interference measurement (chanim) related defines */
+
+/* chanim mode */
+#define CHANIM_DISABLE 0 /* disabled */
+#define CHANIM_DETECT 1 /* detection only */
+#define CHANIM_EXT 2 /* external state machine */
+#define CHANIM_ACT 3 /* full internal state machine, detect + act */
+#define CHANIM_MODE_MAX 4
+
+/* define for apcs reason code */
+#define APCS_INIT 0
+#define APCS_IOCTL 1
+#define APCS_CHANIM 2
+#define APCS_CSTIMER 3
+#define APCS_BTA 4
+#define APCS_TXDLY 5
+#define APCS_NONACSD 6
+#define APCS_DFS_REENTRY 7
+#define APCS_TXFAIL 8
+#define APCS_MAX 9
+
+/* number of ACS record entries */
+#define CHANIM_ACS_RECORD 10
+
+/* CHANIM */
+#define CCASTATS_TXDUR 0
+#define CCASTATS_INBSS 1
+#define CCASTATS_OBSS 2
+#define CCASTATS_NOCTG 3
+#define CCASTATS_NOPKT 4
+#define CCASTATS_DOZE 5
+#define CCASTATS_TXOP 6
+#define CCASTATS_GDTXDUR 7
+#define CCASTATS_BDTXDUR 8
+#define CCASTATS_MAX 9
+
+#define WL_CHANIM_COUNT_ALL 0xff
+#define WL_CHANIM_COUNT_ONE 0x1
+
+/* ap tpc modes */
+#define AP_TPC_OFF 0
+#define AP_TPC_BSS_PWR 1 /* BSS power control */
+#define AP_TPC_AP_PWR 2 /* AP power control */
+#define AP_TPC_AP_BSS_PWR 3 /* Both AP and BSS power control */
+#define AP_TPC_MAX_LINK_MARGIN 127
+
+/* ap tpc modes */
+#define AP_TPC_OFF 0
+#define AP_TPC_BSS_PWR 1 /* BSS power control */
+#define AP_TPC_AP_PWR 2 /* AP power control */
+#define AP_TPC_AP_BSS_PWR 3 /* Both AP and BSS power control */
+#define AP_TPC_MAX_LINK_MARGIN 127
+
+/* state */
+#define WL_P2P_DISC_ST_SCAN 0
+#define WL_P2P_DISC_ST_LISTEN 1
+#define WL_P2P_DISC_ST_SEARCH 2
+
+/* i/f type */
+#define WL_P2P_IF_CLIENT 0
+#define WL_P2P_IF_GO 1
+#define WL_P2P_IF_DYNBCN_GO 2
+#define WL_P2P_IF_DEV 3
+
+/* count */
+#define WL_P2P_SCHED_RSVD 0
+#define WL_P2P_SCHED_REPEAT 255 /* anything > 255 will be treated as 255 */
+
+#define WL_P2P_SCHED_FIXED_LEN 3
+
+/* schedule type */
+#define WL_P2P_SCHED_TYPE_ABS 0 /* Scheduled Absence */
+#define WL_P2P_SCHED_TYPE_REQ_ABS 1 /* Requested Absence */
+
+/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */
+#define WL_P2P_SCHED_ACTION_NONE 0 /* no action */
+#define WL_P2P_SCHED_ACTION_DOZE 1 /* doze */
+/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */
+#define WL_P2P_SCHED_ACTION_GOOFF 2 /* turn off GO beacon/prbrsp functions */
+/* schedule option - WL_P2P_SCHED_TYPE_XXX */
+#define WL_P2P_SCHED_ACTION_RESET 255 /* reset */
+
+/* schedule option - WL_P2P_SCHED_TYPE_ABS */
+#define WL_P2P_SCHED_OPTION_NORMAL 0 /* normal start/interval/duration/count */
+#define WL_P2P_SCHED_OPTION_BCNPCT 1 /* percentage of beacon interval */
+/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */
+#define WL_P2P_SCHED_OPTION_TSFOFS 2 /* normal start/internal/duration/count with
+ * start being an offset of the 'current' TSF
+ */
+
+/* feature flags */
+#define WL_P2P_FEAT_GO_CSA (1 << 0) /* GO moves with the STA using CSA method */
+#define WL_P2P_FEAT_GO_NOLEGACY (1 << 1) /* GO does not probe respond to non-p2p probe
+ * requests
+ */
+#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2) /* Restrict p2p dev interface from responding */
+
+/* n-mode support capability */
+/* 2x2 includes both 1x1 & 2x2 devices
+ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
+ * control it independently
+ */
+#define WL_11N_2x2 1
+#define WL_11N_3x3 3
+#define WL_11N_4x4 4
+
+/* define 11n feature disable flags */
+#define WLFEATURE_DISABLE_11N 0x00000001
+#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002
+#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004
+#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008
+#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010
+#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020
+#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040
+#define WLFEATURE_DISABLE_11N_GF 0x00000080
+
+/* Proxy STA modes */
+#define PSTA_MODE_DISABLED 0
+#define PSTA_MODE_PROXY 1
+#define PSTA_MODE_REPEATER 2
+
+/* op code in nat_cfg */
+#define NAT_OP_ENABLE 1 /* enable NAT on given interface */
+#define NAT_OP_DISABLE 2 /* disable NAT on given interface */
+#define NAT_OP_DISABLE_ALL 3 /* disable NAT on all interfaces */
+
+/* NAT state */
+#define NAT_STATE_ENABLED 1 /* NAT is enabled */
+#define NAT_STATE_DISABLED 2 /* NAT is disabled */
+
+#define CHANNEL_5G_LOW_START 36 /* 5G low (36..48) CDD enable/disable bit mask */
+#define CHANNEL_5G_MID_START 52 /* 5G mid (52..64) CDD enable/disable bit mask */
+#define CHANNEL_5G_HIGH_START 100 /* 5G high (100..140) CDD enable/disable bit mask */
+#define CHANNEL_5G_UPPER_START 149 /* 5G upper (149..161) CDD enable/disable bit mask */
+
+/* D0 Coalescing */
+#define IPV4_ARP_FILTER 0x0001
+#define IPV4_NETBT_FILTER 0x0002
+#define IPV4_LLMNR_FILTER 0x0004
+#define IPV4_SSDP_FILTER 0x0008
+#define IPV4_WSD_FILTER 0x0010
+#define IPV6_NETBT_FILTER 0x0200
+#define IPV6_LLMNR_FILTER 0x0400
+#define IPV6_SSDP_FILTER 0x0800
+#define IPV6_WSD_FILTER 0x1000
+
+/* Network Offload Engine */
+#define NWOE_OL_ENABLE 0x00000001
+
+/*
+ * Traffic management structures/defines.
+ */
+
+/* Traffic management bandwidth parameters */
+#define TRF_MGMT_MAX_PRIORITIES 3
+
+#define TRF_MGMT_FLAG_ADD_DSCP 0x0001 /* Add DSCP to IP TOS field */
+#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Don't shape traffic */
+#define TRF_MGMT_FLAG_MANAGE_LOCAL_TRAFFIC 0x0008 /* Manage traffic over our local subnet */
+#define TRF_MGMT_FLAG_FILTER_ON_MACADDR 0x0010 /* filter on MAC address */
+#define TRF_MGMT_FLAG_NO_RX 0x0020 /* do not apply fiters to rx packets */
+
+#define TRF_FILTER_MAC_ADDR 0x0001 /* L2 filter use dst mac address for filtering */
+#define TRF_FILTER_IP_ADDR 0x0002 /* L3 filter use ip ddress for filtering */
+#define TRF_FILTER_L4 0x0004 /* L4 filter use tcp/udp for filtering */
+#define TRF_FILTER_DWM 0x0008 /* L3 filter use DSCP for filtering */
+#define TRF_FILTER_FAVORED 0x0010 /* Tag the packet FAVORED */
+
+/* WNM/NPS subfeatures mask */
+#define WL_WNM_BSSTRANS 0x00000001
+#define WL_WNM_PROXYARP 0x00000002
+#define WL_WNM_MAXIDLE 0x00000004
+#define WL_WNM_TIMBC 0x00000008
+#define WL_WNM_TFS 0x00000010
+#define WL_WNM_SLEEP 0x00000020
+#define WL_WNM_DMS 0x00000040
+#define WL_WNM_FMS 0x00000080
+#define WL_WNM_NOTIF 0x00000100
+#define WL_WNM_MAX 0x00000200
+
+#ifndef ETHER_MAX_DATA
+#define ETHER_MAX_DATA 1500
+#endif /* ETHER_MAX_DATA */
+
+/* Different discovery modes for dpt */
+#define DPT_DISCOVERY_MANUAL 0x01 /* manual discovery mode */
+#define DPT_DISCOVERY_AUTO 0x02 /* auto discovery mode */
+#define DPT_DISCOVERY_SCAN 0x04 /* scan-based discovery mode */
+
+/* different path selection values */
+#define DPT_PATHSEL_AUTO 0 /* auto mode for path selection */
+#define DPT_PATHSEL_DIRECT 1 /* always use direct DPT path */
+#define DPT_PATHSEL_APPATH 2 /* always use AP path */
+
+/* different ops for deny list */
+#define DPT_DENY_LIST_ADD 1 /* add to dpt deny list */
+#define DPT_DENY_LIST_REMOVE 2 /* remove from dpt deny list */
+
+/* different ops for manual end point */
+#define DPT_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */
+#define DPT_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */
+#define DPT_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */
+
+/* flags to indicate DPT status */
+#define DPT_STATUS_ACTIVE 0x01 /* link active (though may be suspended) */
+#define DPT_STATUS_AES 0x02 /* link secured through AES encryption */
+#define DPT_STATUS_FAILED 0x04 /* DPT link failed */
+
+#ifdef WLTDLS
+/* different ops for manual end point */
+#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */
+#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */
+#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */
+#define TDLS_MANUAL_EP_PM 4 /* put dpt endpoint in PM mode */
+#define TDLS_MANUAL_EP_WAKE 5 /* wake up dpt endpoint from PM */
+#define TDLS_MANUAL_EP_DISCOVERY 6 /* discover if endpoint is TDLS capable */
+#define TDLS_MANUAL_EP_CHSW 7 /* channel switch */
+#define TDLS_MANUAL_EP_WFD_TPQ 8 /* WiFi-Display Tunneled Probe reQuest */
+
+/* modes */
+#define TDLS_WFD_IE_TX 0
+#define TDLS_WFD_IE_RX 1
+#define TDLS_WFD_PROBE_IE_TX 2
+#define TDLS_WFD_PROBE_IE_RX 3
+#endif /* WLTDLS */
+
+/* define for flag */
+#define TSPEC_PENDING 0 /* TSPEC pending */
+#define TSPEC_ACCEPTED 1 /* TSPEC accepted */
+#define TSPEC_REJECTED 2 /* TSPEC rejected */
+#define TSPEC_UNKNOWN 3 /* TSPEC unknown */
+#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */
+
+
+/* Software feature flag defines used by wlfeatureflag */
+#ifdef WLAFTERBURNER
+#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */
+#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */
+#endif /* WLAFTERBURNER */
+#define WL_SWFL_NOHWRADIO 0x0004
+#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */
+#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */
+
+#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */
+
+#define CSA_BROADCAST_ACTION_FRAME 0 /* csa broadcast action frame */
+#define CSA_UNICAST_ACTION_FRAME 1 /* csa unicast action frame */
+
+/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER.
+ *
+ * (-100 < value < 0) value is used directly as a roaming trigger in dBm
+ * (0 <= value) value specifies a logical roaming trigger level from
+ * the list below
+ *
+ * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never
+ * the logical roam trigger value.
+ */
+#define WLC_ROAM_TRIGGER_DEFAULT 0 /* default roaming trigger */
+#define WLC_ROAM_TRIGGER_BANDWIDTH 1 /* optimize for bandwidth roaming trigger */
+#define WLC_ROAM_TRIGGER_DISTANCE 2 /* optimize for distance roaming trigger */
+#define WLC_ROAM_TRIGGER_AUTO 3 /* auto-detect environment */
+#define WLC_ROAM_TRIGGER_MAX_VALUE 3 /* max. valid value */
+
+#define WLC_ROAM_NEVER_ROAM_TRIGGER (-100) /* Avoid Roaming by setting a large value */
+
+/* Preferred Network Offload (PNO, formerly PFN) defines */
+#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */
+
+#define SORT_CRITERIA_BIT 0
+#define AUTO_NET_SWITCH_BIT 1
+#define ENABLE_BKGRD_SCAN_BIT 2
+#define IMMEDIATE_SCAN_BIT 3
+#define AUTO_CONNECT_BIT 4
+#define ENABLE_BD_SCAN_BIT 5
+#define ENABLE_ADAPTSCAN_BIT 6
+#define IMMEDIATE_EVENT_BIT 8
+#define SUPPRESS_SSID_BIT 9
+#define ENABLE_NET_OFFLOAD_BIT 10
+
+#define SORT_CRITERIA_MASK 0x0001
+#define AUTO_NET_SWITCH_MASK 0x0002
+#define ENABLE_BKGRD_SCAN_MASK 0x0004
+#define IMMEDIATE_SCAN_MASK 0x0008
+#define AUTO_CONNECT_MASK 0x0010
+
+#define ENABLE_BD_SCAN_MASK 0x0020
+#define ENABLE_ADAPTSCAN_MASK 0x00c0
+#define IMMEDIATE_EVENT_MASK 0x0100
+#define SUPPRESS_SSID_MASK 0x0200
+#define ENABLE_NET_OFFLOAD_MASK 0x0400
+
+#define PFN_VERSION 2
+#define PFN_SCANRESULT_VERSION 1
+#define MAX_PFN_LIST_COUNT 16
+
+#define PFN_COMPLETE 1
+#define PFN_INCOMPLETE 0
+
+#define DEFAULT_BESTN 2
+#define DEFAULT_MSCAN 0
+#define DEFAULT_REPEAT 10
+#define DEFAULT_EXP 2
+
+#define WL_PFN_SUPPRESSFOUND_MASK 0x08
+#define WL_PFN_SUPPRESSLOST_MASK 0x10
+#define WL_PFN_RSSI_MASK 0xff00
+#define WL_PFN_RSSI_SHIFT 8
+
+#define WL_PFN_REPORT_ALLNET 0
+#define WL_PFN_REPORT_SSIDNET 1
+#define WL_PFN_REPORT_BSSIDNET 2
+
+#define WL_PFN_CFG_FLAGS_PROHIBITED 0x00000001 /* Accept and use prohibited channels */
+#define WL_PFN_CFG_FLAGS_RESERVED 0xfffffffe /* Remaining reserved for future use */
+
+#define WL_PFN_HIDDEN_BIT 2
+#define PNO_SCAN_MAX_FW 508*1000 /* max time scan time in msec */
+#define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */
+#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */
+#define WL_PFN_HIDDEN_MASK 0x4
+
+/* TCP Checksum Offload error injection for testing */
+#define TOE_ERRTEST_TX_CSUM 0x00000001
+#define TOE_ERRTEST_RX_CSUM 0x00000002
+#define TOE_ERRTEST_RX_CSUM2 0x00000004
+
+/* ARP Offload feature flags for arp_ol iovar */
+#define ARP_OL_AGENT 0x00000001
+#define ARP_OL_SNOOP 0x00000002
+#define ARP_OL_HOST_AUTO_REPLY 0x00000004
+#define ARP_OL_PEER_AUTO_REPLY 0x00000008
+
+/* ARP Offload error injection */
+#define ARP_ERRTEST_REPLY_PEER 0x1
+#define ARP_ERRTEST_REPLY_HOST 0x2
+
+#define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */
+#define ND_MULTIHOMING_MAX 10 /* Maximum local host IP addresses */
+#define ND_REQUEST_MAX 5 /* Max set of offload params */
+
+
+/* AOAC wake event flag */
+#define WAKE_EVENT_NLO_DISCOVERY_BIT 1
+#define WAKE_EVENT_AP_ASSOCIATION_LOST_BIT 2
+#define WAKE_EVENT_GTK_HANDSHAKE_ERROR_BIT 4
+#define WAKE_EVENT_4WAY_HANDSHAKE_REQUEST_BIT 8
+
+#define MAX_NUM_WOL_PATTERN 16 /* LOGO requirements min 16 */
+
+/* Packet filter operation mode */
+/* True: 1; False: 0 */
+#define PKT_FILTER_MODE_FORWARD_ON_MATCH 1
+/* Enable and disable pkt_filter as a whole */
+#define PKT_FILTER_MODE_DISABLE 2
+/* Cache first matched rx pkt(be queried by host later) */
+#define PKT_FILTER_MODE_PKT_CACHE_ON_MATCH 4
+/* If pkt_filter is enabled and no filter is set, don't forward anything */
+#define PKT_FILTER_MODE_PKT_FORWARD_OFF_DEFAULT 8
+
+#ifdef DONGLEOVERLAYS
+#define OVERLAY_IDX_MASK 0x000000ff
+#define OVERLAY_IDX_SHIFT 0
+#define OVERLAY_FLAGS_MASK 0xffffff00
+#define OVERLAY_FLAGS_SHIFT 8
+/* overlay written to device memory immediately after loading the base image */
+#define OVERLAY_FLAG_POSTLOAD 0x100
+/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */
+#define OVERLAY_FLAG_DEFER_DL 0x200
+/* overlay downloaded prior to the host going to sleep */
+#define OVERLAY_FLAG_PRESLEEP 0x400
+#define OVERLAY_DOWNLOAD_CHUNKSIZE 1024
+#endif /* DONGLEOVERLAYS */
+
+/* reuse two number in the sc/rc space */
+#define SMFS_CODE_MALFORMED 0xFFFE
+#define SMFS_CODE_IGNORED 0xFFFD
+
+/* RFAWARE def */
+#define BCM_ACTION_RFAWARE 0x77
+#define BCM_ACTION_RFAWARE_DCS 0x01
+
+/* DCS reason code define */
+#define BCM_DCS_IOVAR 0x1
+#define BCM_DCS_UNKNOWN 0xFF
+
+
+#ifdef PROP_TXSTATUS
+/* Bit definitions for tlv iovar */
+/*
+ * enable RSSI signals:
+ * WLFC_CTL_TYPE_RSSI
+ */
+#define WLFC_FLAGS_RSSI_SIGNALS 0x0001
+
+/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals:
+ *
+ * WLFC_CTL_TYPE_MAC_OPEN
+ * WLFC_CTL_TYPE_MAC_CLOSE
+ *
+ * WLFC_CTL_TYPE_INTERFACE_OPEN
+ * WLFC_CTL_TYPE_INTERFACE_CLOSE
+ *
+ * WLFC_CTL_TYPE_MACDESC_ADD
+ * WLFC_CTL_TYPE_MACDESC_DEL
+ *
+ */
+#define WLFC_FLAGS_XONXOFF_SIGNALS 0x0002
+
+/* enable (status, fifo_credit, mac_credit) signals
+ * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT
+ * WLFC_CTL_TYPE_TXSTATUS
+ * WLFC_CTL_TYPE_FIFO_CREDITBACK
+ */
+#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS 0x0004
+
+#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008
+#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010
+#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020
+#define WLFC_FLAGS_HOST_RXRERODER_ACTIVE 0x0040
+#define WLFC_FLAGS_PKT_STAMP_SIGNALS 0x0080
+
+#endif /* PROP_TXSTATUS */
+
+#define WL_TIMBC_STATUS_AP_UNKNOWN 255 /* AP status for internal use only */
+
+#define WL_DFRTS_LOGIC_OFF 0 /* Feature is disabled */
+#define WL_DFRTS_LOGIC_OR 1 /* OR all non-zero threshold conditions */
+#define WL_DFRTS_LOGIC_AND 2 /* AND all non-zero threshold conditions */
+
+/* Definitions for Reliable Multicast */
+#define WL_RELMCAST_MAX_CLIENT 32
+#define WL_RELMCAST_FLAG_INBLACKLIST 1
+#define WL_RELMCAST_FLAG_ACTIVEACKER 2
+#define WL_RELMCAST_FLAG_RELMCAST 4
+
+/* structures for proximity detection device role */
+#define WL_PROXD_MODE_DISABLE 0
+#define WL_PROXD_MODE_NEUTRAL 1
+#define WL_PROXD_MODE_INITIATOR 2
+#define WL_PROXD_MODE_TARGET 3
+#define WL_PROXD_RANDOM_WAKEUP 0x8000
+
+
+#ifdef NET_DETECT
+#define NET_DETECT_MAX_WAKE_DATA_SIZE 2048
+#define NET_DETECT_MAX_PROFILES 16
+#define NET_DETECT_MAX_CHANNELS 50
+#endif /* NET_DETECT */
+
+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+#define WL_RADIO_SW_DISABLE (1<<0)
+#define WL_RADIO_HW_DISABLE (1<<1)
+#define WL_RADIO_MPC_DISABLE (1<<2)
+#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */
+
+#define WL_SPURAVOID_OFF 0
+#define WL_SPURAVOID_ON1 1
+#define WL_SPURAVOID_ON2 2
+
+
+#define WL_4335_SPURAVOID_ON1 1
+#define WL_4335_SPURAVOID_ON2 2
+#define WL_4335_SPURAVOID_ON3 3
+#define WL_4335_SPURAVOID_ON4 4
+#define WL_4335_SPURAVOID_ON5 5
+#define WL_4335_SPURAVOID_ON6 6
+#define WL_4335_SPURAVOID_ON7 7
+#define WL_4335_SPURAVOID_ON8 8
+#define WL_4335_SPURAVOID_ON9 9
+
+/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */
+#define WL_TXPWR_OVERRIDE (1U<<31)
+#define WL_TXPWR_NEG (1U<<30)
+
+
+/* phy types (returned by WLC_GET_PHYTPE) */
+#define WLC_PHY_TYPE_A 0
+#define WLC_PHY_TYPE_B 1
+#define WLC_PHY_TYPE_G 2
+#define WLC_PHY_TYPE_N 4
+#define WLC_PHY_TYPE_LP 5
+#define WLC_PHY_TYPE_SSN 6
+#define WLC_PHY_TYPE_HT 7
+#define WLC_PHY_TYPE_LCN 8
+#define WLC_PHY_TYPE_LCN40 10
+#define WLC_PHY_TYPE_AC 11
+#define WLC_PHY_TYPE_NULL 0xf
+
+/* Values for PM */
+#define PM_OFF 0
+#define PM_MAX 1
+#define PM_FAST 2
+#define PM_FORCE_OFF 3 /* use this bit to force PM off even bt is active */
+
+#define WL_WME_CNT_VERSION 1 /* current version of wl_wme_cnt_t */
+
+/* fbt_cap: FBT assoc / reassoc modes. */
+#define WLC_FBT_CAP_DRV_4WAY_AND_REASSOC 1 /* Driver 4-way handshake & reassoc (WLFBT). */
+
+/* monitor_promisc_level bits */
+#define WL_MONPROMISC_PROMISC 0x0001
+#define WL_MONPROMISC_CTRL 0x0002
+#define WL_MONPROMISC_FCS 0x0004
+
+/* TCP Checksum Offload defines */
+#define TOE_TX_CSUM_OL 0x00000001
+#define TOE_RX_CSUM_OL 0x00000002
+
+#endif /* wlioctl_defs_h */
diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h
new file mode 100644
index 000000000000..770de78f5a30
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/dhdioctl.h
@@ -0,0 +1,135 @@
+/*
+ * Definitions for ioctls to access DHD iovars.
+ * Based on wlioctl.h (for Broadcom 802.11abg driver).
+ * (Moves towards generic ioctls for BCM drivers/iovars.)
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhdioctl.h 454792 2014-02-11 20:40:19Z $
+ */
+
+#ifndef _dhdioctl_h_
+#define _dhdioctl_h_
+
+#include <typedefs.h>
+
+
+/* require default structure packing */
+#define BWL_DEFAULT_PACKING
+#include <packed_section_start.h>
+
+
+/* Linux network driver ioctl encoding */
+typedef struct dhd_ioctl {
+ uint cmd; /* common ioctl definition */
+ void *buf; /* pointer to user buffer */
+ uint len; /* length of user buffer */
+ bool set; /* get or set request (optional) */
+ uint used; /* bytes read or written (optional) */
+ uint needed; /* bytes needed (optional) */
+ uint driver; /* to identify target driver */
+} dhd_ioctl_t;
+
+/* Underlying BUS definition */
+enum {
+ BUS_TYPE_USB = 0, /* for USB dongles */
+ BUS_TYPE_SDIO, /* for SDIO dongles */
+ BUS_TYPE_PCIE /* for PCIE dongles */
+};
+
+/* per-driver magic numbers */
+#define DHD_IOCTL_MAGIC 0x00444944
+
+/* bump this number if you change the ioctl interface */
+#define DHD_IOCTL_VERSION 1
+
+#define DHD_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
+#define DHD_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */
+
+/* common ioctl definitions */
+#define DHD_GET_MAGIC 0
+#define DHD_GET_VERSION 1
+#define DHD_GET_VAR 2
+#define DHD_SET_VAR 3
+
+/* message levels */
+#define DHD_ERROR_VAL 0x0001
+#define DHD_TRACE_VAL 0x0002
+#define DHD_INFO_VAL 0x0004
+#define DHD_DATA_VAL 0x0008
+#define DHD_CTL_VAL 0x0010
+#define DHD_TIMER_VAL 0x0020
+#define DHD_HDRS_VAL 0x0040
+#define DHD_BYTES_VAL 0x0080
+#define DHD_INTR_VAL 0x0100
+#define DHD_LOG_VAL 0x0200
+#define DHD_GLOM_VAL 0x0400
+#define DHD_EVENT_VAL 0x0800
+#define DHD_BTA_VAL 0x1000
+#define DHD_ISCAN_VAL 0x2000
+#define DHD_ARPOE_VAL 0x4000
+#define DHD_REORDER_VAL 0x8000
+#define DHD_WL_VAL 0x10000
+#define DHD_NOCHECKDIED_VAL 0x20000 /* UTF WAR */
+#define DHD_WL_VAL2 0x40000
+#define DHD_PNO_VAL 0x80000
+
+#ifdef SDTEST
+/* For pktgen iovar */
+typedef struct dhd_pktgen {
+ uint version; /* To allow structure change tracking */
+ uint freq; /* Max ticks between tx/rx attempts */
+ uint count; /* Test packets to send/rcv each attempt */
+ uint print; /* Print counts every <print> attempts */
+ uint total; /* Total packets (or bursts) */
+ uint minlen; /* Minimum length of packets to send */
+ uint maxlen; /* Maximum length of packets to send */
+ uint numsent; /* Count of test packets sent */
+ uint numrcvd; /* Count of test packets received */
+ uint numfail; /* Count of test send failures */
+ uint mode; /* Test mode (type of test packets) */
+ uint stop; /* Stop after this many tx failures */
+} dhd_pktgen_t;
+
+/* Version in case structure changes */
+#define DHD_PKTGEN_VERSION 2
+
+/* Type of test packets to use */
+#define DHD_PKTGEN_ECHO 1 /* Send echo requests */
+#define DHD_PKTGEN_SEND 2 /* Send discard packets */
+#define DHD_PKTGEN_RXBURST 3 /* Request dongle send N packets */
+#define DHD_PKTGEN_RECV 4 /* Continuous rx from continuous tx dongle */
+#endif /* SDTEST */
+
+/* Enter idle immediately (no timeout) */
+#define DHD_IDLE_IMMEDIATE (-1)
+
+/* Values for idleclock iovar: other values are the sd_divisor to use when idle */
+#define DHD_IDLE_ACTIVE 0 /* Do not request any SD clock change when idle */
+#define DHD_IDLE_STOP (-1) /* Request SD clock be stopped (and use SD1 mode) */
+
+
+/* require default structure packing */
+#include <packed_section_end.h>
+
+#endif /* _dhdioctl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
new file mode 100644
index 000000000000..31e5a916b17f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $
+ *
+*/
+
+#ifndef _epivers_h_
+#define _epivers_h_
+
+#define EPI_MAJOR_VERSION 1
+
+#define EPI_MINOR_VERSION 141
+
+#define EPI_RC_NUMBER 100
+
+#define EPI_INCREMENTAL_NUMBER 6
+
+#define EPI_BUILD_NUMBER 0
+
+#define EPI_VERSION 1, 141, 100, 6
+
+#define EPI_VERSION_NUM 0x018d6406
+
+#define EPI_VERSION_DEV 1.141.100
+
+/* Driver Version String, ASCII, 32 chars max */
+#define EPI_VERSION_STR "1.141.100.6 (r)"
+
+#endif /* _epivers_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/hndpmu.h b/drivers/net/wireless/bcmdhd/include/hndpmu.h
new file mode 100644
index 000000000000..c0d83101c750
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/hndpmu.h
@@ -0,0 +1,36 @@
+/*
+ * HND SiliconBackplane PMU support.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: hndpmu.h 431134 2013-10-22 18:25:42Z $
+ */
+
+#ifndef _hndpmu_h_
+#define _hndpmu_h_
+
+
+extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on, uint32* min_res_mask);
+extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength);
+
+extern void si_pmu_minresmask_htavail_set(si_t *sih, osl_t *osh, bool set_clear);
+
+#endif /* _hndpmu_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h b/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h
new file mode 100644
index 000000000000..39fdf0f5895c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h
@@ -0,0 +1,88 @@
+/*
+ * HNDRTE arm trap handling.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: hndrte_armtrap.h 261365 2011-05-24 20:42:23Z $
+ */
+
+#ifndef _hndrte_armtrap_h
+#define _hndrte_armtrap_h
+
+
+/* ARM trap handling */
+
+/* Trap types defined by ARM (see arminc.h) */
+
+/* Trap locations in lo memory */
+#define TRAP_STRIDE 4
+#define FIRST_TRAP TR_RST
+#define LAST_TRAP (TR_FIQ * TRAP_STRIDE)
+
+#if defined(__ARM_ARCH_4T__)
+#define MAX_TRAP_TYPE (TR_FIQ + 1)
+#elif defined(__ARM_ARCH_7M__)
+#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS)
+#endif /* __ARM_ARCH_7M__ */
+
+/* The trap structure is defined here as offsets for assembly */
+#define TR_TYPE 0x00
+#define TR_EPC 0x04
+#define TR_CPSR 0x08
+#define TR_SPSR 0x0c
+#define TR_REGS 0x10
+#define TR_REG(n) (TR_REGS + (n) * 4)
+#define TR_SP TR_REG(13)
+#define TR_LR TR_REG(14)
+#define TR_PC TR_REG(15)
+
+#define TRAP_T_SIZE 80
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include <typedefs.h>
+
+typedef struct _trap_struct {
+ uint32 type;
+ uint32 epc;
+ uint32 cpsr;
+ uint32 spsr;
+ uint32 r0; /* a1 */
+ uint32 r1; /* a2 */
+ uint32 r2; /* a3 */
+ uint32 r3; /* a4 */
+ uint32 r4; /* v1 */
+ uint32 r5; /* v2 */
+ uint32 r6; /* v3 */
+ uint32 r7; /* v4 */
+ uint32 r8; /* v5 */
+ uint32 r9; /* sb/v6 */
+ uint32 r10; /* sl/v7 */
+ uint32 r11; /* fp/v8 */
+ uint32 r12; /* ip */
+ uint32 r13; /* sp */
+ uint32 r14; /* lr */
+ uint32 pc; /* r15 */
+} trap_t;
+
+#endif /* !_LANGUAGE_ASSEMBLY */
+
+#endif /* _hndrte_armtrap_h */
diff --git a/drivers/net/wireless/bcmdhd/include/hndrte_cons.h b/drivers/net/wireless/bcmdhd/include/hndrte_cons.h
new file mode 100644
index 000000000000..5cecea53cff2
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/hndrte_cons.h
@@ -0,0 +1,78 @@
+/*
+ * Console support for hndrte.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: hndrte_cons.h 427140 2013-10-02 18:07:07Z $
+ */
+#ifndef _HNDRTE_CONS_H
+#define _HNDRTE_CONS_H
+
+#include <typedefs.h>
+
+#if defined(RWL_DONGLE) || defined(UART_REFLECTOR)
+/* For Dongle uart tranport max cmd len is 256 bytes + header length (16 bytes)
+ * In case of ASD commands we are not sure about how much is the command size
+ * To be on the safe side, input buf len CBUF_LEN is increased to max (512) bytes.
+ */
+#define RWL_MAX_DATA_LEN (512 + 8) /* allow some extra bytes for '/n' termination */
+#define CBUF_LEN (RWL_MAX_DATA_LEN + 64) /* allow 64 bytes for header ("rwl...") */
+#else
+#define CBUF_LEN (128)
+#endif /* RWL_DONGLE || UART_REFLECTOR */
+
+#define LOG_BUF_LEN 1024
+
+typedef struct {
+ uint32 buf; /* Can't be pointer on (64-bit) hosts */
+ uint buf_size;
+ uint idx;
+ uint out_idx; /* output index */
+} hndrte_log_t;
+
+typedef struct {
+ /* Virtual UART
+ * When there is no UART (e.g. Quickturn), the host should write a complete
+ * input line directly into cbuf and then write the length into vcons_in.
+ * This may also be used when there is a real UART (at risk of conflicting with
+ * the real UART). vcons_out is currently unused.
+ */
+ volatile uint vcons_in;
+ volatile uint vcons_out;
+
+ /* Output (logging) buffer
+ * Console output is written to a ring buffer log_buf at index log_idx.
+ * The host may read the output when it sees log_idx advance.
+ * Output will be lost if the output wraps around faster than the host polls.
+ */
+ hndrte_log_t log;
+
+ /* Console input line buffer
+ * Characters are read one at a time into cbuf until <CR> is received, then
+ * the buffer is processed as a command line. Also used for virtual UART.
+ */
+ uint cbuf_idx;
+ char cbuf[CBUF_LEN];
+} hndrte_cons_t;
+
+hndrte_cons_t *hndrte_get_active_cons_state(void);
+
+#endif /* _HNDRTE_CONS_H */
diff --git a/drivers/net/wireless/bcmdhd/include/hndsoc.h b/drivers/net/wireless/bcmdhd/include/hndsoc.h
new file mode 100644
index 000000000000..7b32f9627b31
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/hndsoc.h
@@ -0,0 +1,282 @@
+/*
+ * Broadcom HND chip & on-chip-interconnect-related definitions.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: hndsoc.h 432420 2013-10-28 14:14:02Z $
+ */
+
+#ifndef _HNDSOC_H
+#define _HNDSOC_H
+
+/* Include the soci specific files */
+#include <sbconfig.h>
+#include <aidmp.h>
+
+/*
+ * SOC Interconnect Address Map.
+ * All regions may not exist on all chips.
+ */
+#define SI_SDRAM_BASE 0x00000000 /* Physical SDRAM */
+#define SI_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */
+#define SI_PCI_MEM_SZ (64 * 1024 * 1024)
+#define SI_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */
+#define SI_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */
+#define SI_SDRAM_R2 0x80000000 /* Region 2 for sdram (512 MB) */
+
+#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
+
+#define SI_WRAP_BASE 0x18100000 /* Wrapper space base */
+#define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */
+
+#ifndef SI_MAXCORES
+#define SI_MAXCORES 32 /* NorthStar has more cores */
+#endif /* SI_MAXCORES */
+
+#define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */
+#define SI_FASTRAM_SWAPPED 0x19800000
+
+#define SI_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */
+#define SI_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */
+#define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */
+#define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */
+#define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */
+#define SI_FLASH_WINDOW 0x01000000 /* Flash XIP Window */
+
+#define SI_NS_NANDFLASH 0x1c000000 /* NorthStar NAND flash base */
+#define SI_NS_NORFLASH 0x1e000000 /* NorthStar NOR flash base */
+#define SI_NS_ROM 0xfffd0000 /* NorthStar ROM */
+#define SI_NS_FLASH_WINDOW 0x02000000 /* Flash XIP Window */
+
+#define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */
+#define SI_ARMCR4_ROM 0x000f0000 /* ARM Cortex-R4 ROM */
+#define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */
+#define SI_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */
+#define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */
+#define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */
+
+#define SI_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */
+#define SI_PCI_DMA2 0x80000000 /* Client Mode sb2pcitranslation2 (1 GB) */
+#define SI_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */
+#define SI_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2
+ * (2 ZettaBytes), low 32 bits
+ */
+#define SI_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2
+ * (2 ZettaBytes), high 32 bits
+ */
+/* core codes */
+#define NODEV_CORE_ID 0x700 /* Invalid coreid */
+#define CC_CORE_ID 0x800 /* chipcommon core */
+#define ILINE20_CORE_ID 0x801 /* iline20 core */
+#define SRAM_CORE_ID 0x802 /* sram core */
+#define SDRAM_CORE_ID 0x803 /* sdram core */
+#define PCI_CORE_ID 0x804 /* pci core */
+#define MIPS_CORE_ID 0x805 /* mips core */
+#define ENET_CORE_ID 0x806 /* enet mac core */
+#define CODEC_CORE_ID 0x807 /* v90 codec core */
+#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */
+#define ADSL_CORE_ID 0x809 /* ADSL core */
+#define ILINE100_CORE_ID 0x80a /* iline100 core */
+#define IPSEC_CORE_ID 0x80b /* ipsec core */
+#define UTOPIA_CORE_ID 0x80c /* utopia core */
+#define PCMCIA_CORE_ID 0x80d /* pcmcia core */
+#define SOCRAM_CORE_ID 0x80e /* internal memory core */
+#define MEMC_CORE_ID 0x80f /* memc sdram core */
+#define OFDM_CORE_ID 0x810 /* OFDM phy core */
+#define EXTIF_CORE_ID 0x811 /* external interface core */
+#define D11_CORE_ID 0x812 /* 802.11 MAC core */
+#define APHY_CORE_ID 0x813 /* 802.11a phy core */
+#define BPHY_CORE_ID 0x814 /* 802.11b phy core */
+#define GPHY_CORE_ID 0x815 /* 802.11g phy core */
+#define MIPS33_CORE_ID 0x816 /* mips3302 core */
+#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */
+#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */
+#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */
+#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */
+#define SDIOH_CORE_ID 0x81b /* sdio host core */
+#define ROBO_CORE_ID 0x81c /* roboswitch core */
+#define ATA100_CORE_ID 0x81d /* parallel ATA core */
+#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */
+#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */
+#define PCIE_CORE_ID 0x820 /* pci express core */
+#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */
+#define SRAMC_CORE_ID 0x822 /* SRAM controller core */
+#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */
+#define ARM11_CORE_ID 0x824 /* ARM 1176 core */
+#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */
+#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */
+#define PMU_CORE_ID 0x827 /* PMU core */
+#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */
+#define SDIOD_CORE_ID 0x829 /* SDIO device core */
+#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */
+#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */
+#define MIPS74K_CORE_ID 0x82c /* mips 74k core */
+#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */
+#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */
+#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */
+#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */
+#define SC_CORE_ID 0x831 /* shared common core */
+#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */
+#define SPIH_CORE_ID 0x833 /* SPI host core */
+#define I2S_CORE_ID 0x834 /* I2S core */
+#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */
+#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */
+
+#define ACPHY_CORE_ID 0x83b /* Dot11 ACPHY */
+#define PCIE2_CORE_ID 0x83c /* pci express Gen2 core */
+#define USB30D_CORE_ID 0x83d /* usb 3.0 device core */
+#define ARMCR4_CORE_ID 0x83e /* ARM CR4 CPU */
+#define GCI_CORE_ID 0x840 /* GCI Core */
+#define APB_BRIDGE_CORE_ID 0x135 /* APB bridge core ID */
+#define AXI_CORE_ID 0x301 /* AXI/GPV core ID */
+#define EROM_CORE_ID 0x366 /* EROM core ID */
+#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */
+#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all
+ * unused address ranges
+ */
+
+#define CC_4706_CORE_ID 0x500 /* chipcommon core */
+#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */
+#define NS_DMA_CORE_ID 0x502 /* DMA core */
+#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */
+#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */
+#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */
+#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */
+#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */
+#define NS_ROM_CORE_ID 0x508 /* ROM core */
+#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */
+#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */
+#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */
+#define SOCRAM_4706_CORE_ID 0x50e /* internal memory core */
+#define NS_SOCRAM_CORE_ID SOCRAM_4706_CORE_ID
+#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */
+#define NS_IHOST_CORE_ID ARMCA9_CORE_ID /* ARM Cortex A9 core (ihost) */
+#define GMAC_COMMON_4706_CORE_ID 0x5dc /* Gigabit MAC core */
+#define GMAC_4706_CORE_ID 0x52d /* Gigabit MAC core */
+#define AMEMC_CORE_ID 0x52e /* DDR1/2 memory controller core */
+#define ALTA_CORE_ID 0x534 /* I2S core */
+#define DDR23_PHY_CORE_ID 0x5dd
+
+#define SI_PCI1_MEM 0x40000000 /* Host Mode sb2pcitranslation0 (64 MB) */
+#define SI_PCI1_CFG 0x44000000 /* Host Mode sb2pcitranslation1 (64 MB) */
+#define SI_PCIE1_DMA_H32 0xc0000000 /* PCIE Client Mode sb2pcitranslation2
+ * (2 ZettaBytes), high 32 bits
+ */
+#define CC_4706B0_CORE_REV 0x8000001f /* chipcommon core */
+#define SOCRAM_4706B0_CORE_REV 0x80000005 /* internal memory core */
+#define GMAC_4706B0_CORE_REV 0x80000000 /* Gigabit MAC core */
+
+/* There are TWO constants on all HND chips: SI_ENUM_BASE above,
+ * and chipcommon being the first core:
+ */
+#define SI_CC_IDX 0
+/* SOC Interconnect types (aka chip types) */
+#define SOCI_SB 0
+#define SOCI_AI 1
+#define SOCI_UBUS 2
+#define SOCI_NAI 3
+
+/* Common core control flags */
+#define SICF_BIST_EN 0x8000
+#define SICF_PME_EN 0x4000
+#define SICF_CORE_BITS 0x3ffc
+#define SICF_FGC 0x0002
+#define SICF_CLOCK_EN 0x0001
+
+/* Common core status flags */
+#define SISF_BIST_DONE 0x8000
+#define SISF_BIST_ERROR 0x4000
+#define SISF_GATED_CLK 0x2000
+#define SISF_DMA64 0x1000
+#define SISF_CORE_BITS 0x0fff
+
+/* Norstar core status flags */
+#define SISF_NS_BOOTDEV_MASK 0x0003 /* ROM core */
+#define SISF_NS_BOOTDEV_NOR 0x0000 /* ROM core */
+#define SISF_NS_BOOTDEV_NAND 0x0001 /* ROM core */
+#define SISF_NS_BOOTDEV_ROM 0x0002 /* ROM core */
+#define SISF_NS_BOOTDEV_OFFLOAD 0x0003 /* ROM core */
+#define SISF_NS_SKUVEC_MASK 0x000c /* ROM core */
+
+/* A register that is common to all cores to
+ * communicate w/PMU regarding clock control.
+ */
+#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */
+#define SI_PWR_CTL_ST 0x1e8 /* For memory clock gating */
+
+/* clk_ctl_st register */
+#define CCS_FORCEALP 0x00000001 /* force ALP request */
+#define CCS_FORCEHT 0x00000002 /* force HT request */
+#define CCS_FORCEILP 0x00000004 /* force ILP request */
+#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */
+#define CCS_HTAREQ 0x00000010 /* HT Avail Request */
+#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */
+#define CCS_HQCLKREQ 0x00000040 /* HQ Clock Required */
+#define CCS_USBCLKREQ 0x00000100 /* USB Clock Req */
+#define CCS_SECICLKREQ 0x00000100 /* SECI Clock Req */
+#define CCS_ARMFASTCLOCKREQ 0x00000100 /* ARM CR4 fast clock request */
+#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */
+#define CCS_ERSRC_REQ_SHIFT 8
+#define CCS_ALPAVAIL 0x00010000 /* ALP is available */
+#define CCS_HTAVAIL 0x00020000 /* HT is available */
+#define CCS_BP_ON_APL 0x00040000 /* RO: Backplane is running on ALP clock */
+#define CCS_BP_ON_HT 0x00080000 /* RO: Backplane is running on HT clock */
+#define CCS_ARMFASTCLOCKSTATUS 0x01000000 /* Fast CPU clock is running */
+#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */
+#define CCS_ERSRC_STS_SHIFT 24
+
+#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */
+#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */
+
+/* Not really related to SOC Interconnect, but a couple of software
+ * conventions for the use the flash space:
+ */
+
+/* Minumum amount of flash we support */
+#define FLASH_MIN 0x00020000 /* Minimum flash size */
+
+/* A boot/binary may have an embedded block that describes its size */
+#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */
+#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */
+#define BISZ_MAGIC_IDX 0 /* Word 0: magic */
+#define BISZ_TXTST_IDX 1 /* 1: text start */
+#define BISZ_TXTEND_IDX 2 /* 2: text end */
+#define BISZ_DATAST_IDX 3 /* 3: data start */
+#define BISZ_DATAEND_IDX 4 /* 4: data end */
+#define BISZ_BSSST_IDX 5 /* 5: bss start */
+#define BISZ_BSSEND_IDX 6 /* 6: bss end */
+#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */
+
+/* Boot/Kernel related defintion and functions */
+#define SOC_BOOTDEV_ROM 0x00000001
+#define SOC_BOOTDEV_PFLASH 0x00000002
+#define SOC_BOOTDEV_SFLASH 0x00000004
+#define SOC_BOOTDEV_NANDFLASH 0x00000008
+
+#define SOC_KNLDEV_NORFLASH 0x00000002
+#define SOC_KNLDEV_NANDFLASH 0x00000004
+
+#ifndef _LANGUAGE_ASSEMBLY
+int soc_boot_dev(void *sih);
+int soc_knl_dev(void *sih);
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#endif /* _HNDSOC_H */
diff --git a/drivers/net/wireless/bcmdhd/include/linux_osl.h b/drivers/net/wireless/bcmdhd/include/linux_osl.h
new file mode 100644
index 000000000000..ba989be9b165
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/linux_osl.h
@@ -0,0 +1,763 @@
+/*
+ * Linux OS Independent Layer
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: linux_osl.h 657415 2016-09-01 05:45:34Z $
+ */
+
+#ifndef _linux_osl_h_
+#define _linux_osl_h_
+
+#include <typedefs.h>
+
+/* Linux Kernel: File Operations: start */
+extern void * osl_os_open_image(char * filename);
+extern int osl_os_get_image_block(char * buf, int len, void * image);
+extern void osl_os_close_image(void * image);
+extern int osl_os_image_size(void *image);
+/* Linux Kernel: File Operations: end */
+
+#ifdef BCMDRIVER
+
+/* OSL initialization */
+#ifdef SHARED_OSL_CMN
+extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag, void **osh_cmn);
+#else
+extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag);
+#endif /* SHARED_OSL_CMN */
+
+extern void osl_detach(osl_t *osh);
+extern int osl_static_mem_init(osl_t *osh, void *adapter);
+extern int osl_static_mem_deinit(osl_t *osh, void *adapter);
+extern void osl_set_bus_handle(osl_t *osh, void *bus_handle);
+extern void* osl_get_bus_handle(osl_t *osh);
+
+/* Global ASSERT type */
+extern uint32 g_assert_type;
+
+/* ASSERT */
+#if defined(BCMASSERT_LOG)
+ #define ASSERT(exp) \
+ do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
+extern void osl_assert(const char *exp, const char *file, int line);
+#else
+ #ifdef __GNUC__
+ #define GCC_VERSION \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+ #if GCC_VERSION > 30100
+ #define ASSERT(exp) do {} while (0)
+ #else
+ /* ASSERT could cause segmentation fault on GCC3.1, use empty instead */
+ #define ASSERT(exp)
+ #endif /* GCC_VERSION > 30100 */
+ #endif /* __GNUC__ */
+#endif
+
+/* microsecond delay */
+#define OSL_DELAY(usec) osl_delay(usec)
+extern void osl_delay(uint usec);
+
+#define OSL_SLEEP(ms) osl_sleep(ms)
+extern void osl_sleep(uint ms);
+
+#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \
+ osl_pcmcia_read_attr((osh), (offset), (buf), (size))
+#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \
+ osl_pcmcia_write_attr((osh), (offset), (buf), (size))
+extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size);
+extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size);
+
+/* PCI configuration space access macros */
+#define OSL_PCI_READ_CONFIG(osh, offset, size) \
+ osl_pci_read_config((osh), (offset), (size))
+#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \
+ osl_pci_write_config((osh), (offset), (size), (val))
+extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size);
+extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val);
+
+/* PCI device bus # and slot # */
+#define OSL_PCI_BUS(osh) osl_pci_bus(osh)
+#define OSL_PCI_SLOT(osh) osl_pci_slot(osh)
+extern uint osl_pci_bus(osl_t *osh);
+extern uint osl_pci_slot(osl_t *osh);
+extern struct pci_dev *osl_pci_device(osl_t *osh);
+
+/* Pkttag flag should be part of public information */
+typedef struct {
+ bool pkttag;
+ bool mmbus; /* Bus supports memory-mapped register accesses */
+ pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */
+ void *tx_ctx; /* Context to the callback function */
+ void *unused[3];
+} osl_pubinfo_t;
+
+#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \
+ do { \
+ ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \
+ ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \
+ } while (0)
+
+
+/* host/bus architecture-specific byte swap */
+#define BUS_SWAP32(v) (v)
+ #define MALLOC(osh, size) osl_malloc((osh), (size))
+ #define MALLOCZ(osh, size) osl_mallocz((osh), (size))
+ #define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size))
+ #define MALLOCED(osh) osl_malloced((osh))
+ #define MEMORY_LEFTOVER(osh) osl_check_memleak(osh)
+ extern void *osl_malloc(osl_t *osh, uint size);
+ extern void *osl_mallocz(osl_t *osh, uint size);
+ extern void osl_mfree(osl_t *osh, void *addr, uint size);
+ extern uint osl_malloced(osl_t *osh);
+ extern uint osl_check_memleak(osl_t *osh);
+
+
+#define MALLOC_FAILED(osh) osl_malloc_failed((osh))
+extern uint osl_malloc_failed(osl_t *osh);
+
+/* allocate/free shared (dma-able) consistent memory */
+#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align()
+#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \
+ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
+#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \
+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
+
+#define DMA_ALLOC_CONSISTENT_FORCE32(osh, size, align, tot, pap, dmah) \
+ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
+#define DMA_FREE_CONSISTENT_FORCE32(osh, va, size, pa, dmah) \
+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
+
+extern uint osl_dma_consistent_align(void);
+extern void *
+osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, dmaaddr_t *pap);
+extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa);
+
+/* map/unmap direction */
+#define DMA_TX 1 /* TX direction for DMA */
+#define DMA_RX 2 /* RX direction for DMA */
+
+/* map/unmap shared (dma-able) memory */
+#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \
+ osl_dma_unmap((osh), (pa), (size), (direction))
+extern dmaaddr_t osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p,
+ hnddma_seg_map_t *txp_dmah);
+extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction);
+
+/* API for DMA addressing capability */
+#define OSL_DMADDRWIDTH(osh, addrwidth) ({BCM_REFERENCE(osh); BCM_REFERENCE(addrwidth);})
+
+#if defined(__ARM_ARCH_7A__)
+ extern void osl_cache_flush(void *va, uint size);
+ extern void osl_cache_inv(void *va, uint size);
+ extern void osl_prefetch(const void *ptr);
+ #define OSL_CACHE_FLUSH(va, len) osl_cache_flush((void *) va, len)
+ #define OSL_CACHE_INV(va, len) osl_cache_inv((void *) va, len)
+ #define OSL_PREFETCH(ptr) osl_prefetch(ptr)
+#else
+ #define OSL_CACHE_FLUSH(va, len) BCM_REFERENCE(va)
+ #define OSL_CACHE_INV(va, len) BCM_REFERENCE(va)
+ #define OSL_PREFETCH(ptr) prefetch(ptr)
+#endif
+
+/* register access macros */
+ #include <bcmsdh.h>
+ #define OSL_WRITE_REG(osh, r, v) (bcmsdh_reg_write(osl_get_bus_handle(osh), \
+ (uintptr)(r), sizeof(*(r)), (v)))
+ #define OSL_READ_REG(osh, r) (bcmsdh_reg_read(osl_get_bus_handle(osh), \
+ (uintptr)(r), sizeof(*(r))))
+
+ #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) if (((osl_pubinfo_t*)(osh))->mmbus) \
+ mmap_op else bus_op
+ #define SELECT_BUS_READ(osh, mmap_op, bus_op) (((osl_pubinfo_t*)(osh))->mmbus) ? \
+ mmap_op : bus_op
+
+#define OSL_ERROR(bcmerror) osl_error(bcmerror)
+extern int osl_error(int bcmerror);
+
+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
+#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */
+
+#define OSH_NULL NULL
+
+/*
+ * BINOSL selects the slightly slower function-call-based binary compatible osl.
+ * Macros expand to calls to functions defined in linux_osl.c .
+ */
+#include <linuxver.h> /* use current 2.4.x calling conventions */
+#include <linux/kernel.h> /* for vsn/printf's */
+#include <linux/string.h> /* for mem*, str* */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29)
+#define OSL_SYSUPTIME() ((uint32)jiffies_to_msecs(jiffies))
+#else
+#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ))
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29) */
+#define printf(fmt, args...) printk(fmt , ## args)
+#include <linux/kernel.h> /* for vsn/printf's */
+#include <linux/string.h> /* for mem*, str* */
+/* bcopy's: Linux kernel doesn't provide these (anymore) */
+#define bcopy(src, dst, len) memcpy((dst), (src), (len))
+#define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
+#define bzero(b, len) memset((b), '\0', (len))
+
+/* register access macros */
+
+#define R_REG(osh, r) (\
+ SELECT_BUS_READ(osh, \
+ ({ \
+ __typeof(*(r)) __osl_v; \
+ switch (sizeof(*(r))) { \
+ case sizeof(uint8): __osl_v = \
+ readb((volatile uint8*)(r)); break; \
+ case sizeof(uint16): __osl_v = \
+ readw((volatile uint16*)(r)); break; \
+ case sizeof(uint32): __osl_v = \
+ readl((volatile uint32*)(r)); break; \
+ } \
+ __osl_v; \
+ }), \
+ OSL_READ_REG(osh, r)) \
+)
+
+#define W_REG(osh, r, v) do { \
+ SELECT_BUS_WRITE(osh, \
+ switch (sizeof(*(r))) { \
+ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \
+ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \
+ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \
+ }, \
+ (OSL_WRITE_REG(osh, r, v))); \
+ } while (0)
+
+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
+
+/* bcopy, bcmp, and bzero functions */
+#define bcopy(src, dst, len) memcpy((dst), (src), (len))
+#define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
+#define bzero(b, len) memset((b), '\0', (len))
+
+/* uncached/cached virtual address */
+#define OSL_UNCACHED(va) ((void *)va)
+#define OSL_CACHED(va) ((void *)va)
+
+#define OSL_PREF_RANGE_LD(va, sz) BCM_REFERENCE(va)
+#define OSL_PREF_RANGE_ST(va, sz) BCM_REFERENCE(va)
+
+/* get processor cycle count */
+#if defined(__i386__)
+#define OSL_GETCYCLES(x) rdtscl((x))
+#else
+#define OSL_GETCYCLES(x) ((x) = 0)
+#endif
+
+/* dereference an address that may cause a bus exception */
+#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; })
+
+/* map/unmap physical to virtual I/O */
+#if !defined(CONFIG_MMC_MSM7X00A)
+#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size))
+#else
+#define REG_MAP(pa, size) (void *)(0)
+#endif /* !defined(CONFIG_MMC_MSM7X00A */
+#define REG_UNMAP(va) iounmap((va))
+
+/* shared (dma-able) memory access macros */
+#define R_SM(r) *(r)
+#define W_SM(r, v) (*(r) = (v))
+#define BZERO_SM(r, len) memset((r), '\0', (len))
+
+/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for
+ * performance reasons), we need the Linux headers.
+ */
+#include <linuxver.h> /* use current 2.4.x calling conventions */
+
+/* packet primitives */
+#ifdef BCMDBG_CTRACE
+#define PKTGET(osh, len, send) osl_pktget((osh), (len), __LINE__, __FILE__)
+#define PKTDUP(osh, skb) osl_pktdup((osh), (skb), __LINE__, __FILE__)
+#else
+#define PKTGET(osh, len, send) osl_pktget((osh), (len))
+#define PKTDUP(osh, skb) osl_pktdup((osh), (skb))
+#endif /* BCMDBG_CTRACE */
+#define PKTLIST_DUMP(osh, buf) BCM_REFERENCE(osh)
+#define PKTDBG_TRACE(osh, pkt, bit) BCM_REFERENCE(osh)
+#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send))
+#ifdef CONFIG_DHD_USE_STATIC_BUF
+#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len))
+#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send))
+#else
+#define PKTGET_STATIC PKTGET
+#define PKTFREE_STATIC PKTFREE
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+#define PKTDATA(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->data);})
+#define PKTLEN(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->len);})
+
+
+#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head))
+#define PKTEXPHEADROOM(osh, skb, b) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ skb_realloc_headroom((struct sk_buff*)(skb), (b)); \
+ })
+#define PKTTAILROOM(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ skb_tailroom((struct sk_buff*)(skb)); \
+ })
+#define PKTPADTAILROOM(osh, skb, padlen) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ skb_pad((struct sk_buff*)(skb), (padlen)); \
+ })
+#define PKTNEXT(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->next);})
+#define PKTSETNEXT(osh, skb, x) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)); \
+ })
+#define PKTSETLEN(osh, skb, len) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ __skb_trim((struct sk_buff*)(skb), (len)); \
+ })
+#define PKTPUSH(osh, skb, bytes) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ skb_push((struct sk_buff*)(skb), (bytes)); \
+ })
+#define PKTPULL(osh, skb, bytes) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ skb_pull((struct sk_buff*)(skb), (bytes)); \
+ })
+#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb))
+#define PKTSETPOOL(osh, skb, x, y) BCM_REFERENCE(osh)
+#define PKTPOOL(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
+#define PKTFREELIST(skb) PKTLINK(skb)
+#define PKTSETFREELIST(skb, x) PKTSETLINK((skb), (x))
+#define PKTPTR(skb) (skb)
+#define PKTID(skb) ({BCM_REFERENCE(skb); 0;})
+#define PKTSETID(skb, id) ({BCM_REFERENCE(skb); BCM_REFERENCE(id);})
+#define PKTSHRINK(osh, m) ({BCM_REFERENCE(osh); m;})
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#define PKTORPHAN(skb) skb_orphan(skb)
+#else
+#define PKTORPHAN(skb) ({BCM_REFERENCE(skb); 0;})
+#endif /* LINUX VERSION >= 3.6 */
+
+#ifdef BCMDBG_CTRACE
+#define DEL_CTRACE(zosh, zskb) { \
+ unsigned long zflags; \
+ spin_lock_irqsave(&(zosh)->ctrace_lock, zflags); \
+ list_del(&(zskb)->ctrace_list); \
+ (zosh)->ctrace_num--; \
+ (zskb)->ctrace_start = 0; \
+ (zskb)->ctrace_count = 0; \
+ spin_unlock_irqrestore(&(zosh)->ctrace_lock, zflags); \
+}
+
+#define UPDATE_CTRACE(zskb, zfile, zline) { \
+ struct sk_buff *_zskb = (struct sk_buff *)(zskb); \
+ if (_zskb->ctrace_count < CTRACE_NUM) { \
+ _zskb->func[_zskb->ctrace_count] = zfile; \
+ _zskb->line[_zskb->ctrace_count] = zline; \
+ _zskb->ctrace_count++; \
+ } \
+ else { \
+ _zskb->func[_zskb->ctrace_start] = zfile; \
+ _zskb->line[_zskb->ctrace_start] = zline; \
+ _zskb->ctrace_start++; \
+ if (_zskb->ctrace_start >= CTRACE_NUM) \
+ _zskb->ctrace_start = 0; \
+ } \
+}
+
+#define ADD_CTRACE(zosh, zskb, zfile, zline) { \
+ unsigned long zflags; \
+ spin_lock_irqsave(&(zosh)->ctrace_lock, zflags); \
+ list_add(&(zskb)->ctrace_list, &(zosh)->ctrace_list); \
+ (zosh)->ctrace_num++; \
+ UPDATE_CTRACE(zskb, zfile, zline); \
+ spin_unlock_irqrestore(&(zosh)->ctrace_lock, zflags); \
+}
+
+#define PKTCALLER(zskb) UPDATE_CTRACE((struct sk_buff *)zskb, (char *)__FUNCTION__, __LINE__)
+#endif /* BCMDBG_CTRACE */
+
+#ifdef CTFPOOL
+#define CTFPOOL_REFILL_THRESH 3
+typedef struct ctfpool {
+ void *head;
+ spinlock_t lock;
+ uint max_obj;
+ uint curr_obj;
+ uint obj_size;
+ uint refills;
+ uint fast_allocs;
+ uint fast_frees;
+ uint slow_allocs;
+} ctfpool_t;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+#define FASTBUF (1 << 0)
+#define PKTSETFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF); \
+ })
+#define PKTCLRFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)); \
+ })
+#define PKTISFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF); \
+ })
+#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->pktc_flags)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+#define FASTBUF (1 << 16)
+#define PKTSETFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF); \
+ })
+#define PKTCLRFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)); \
+ })
+#define PKTISFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->mac_len) & FASTBUF); \
+ })
+#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len)
+#else
+#define FASTBUF (1 << 0)
+#define PKTSETFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->__unused) |= FASTBUF); \
+ })
+#define PKTCLRFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)); \
+ })
+#define PKTISFAST(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ ((((struct sk_buff*)(skb))->__unused) & FASTBUF); \
+ })
+#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused)
+#endif /* 2.6.22 */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool)
+#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head)
+#else
+#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->sk)
+#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->sk)->head)
+#endif
+
+extern void *osl_ctfpool_add(osl_t *osh);
+extern void osl_ctfpool_replenish(osl_t *osh, uint thresh);
+extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size);
+extern void osl_ctfpool_cleanup(osl_t *osh);
+extern void osl_ctfpool_stats(osl_t *osh, void *b);
+#else /* CTFPOOL */
+#define PKTSETFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
+#define PKTCLRFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
+#define PKTISFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
+#endif /* CTFPOOL */
+
+#define PKTSETCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
+#define PKTCLRCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
+#define PKTISCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
+
+#ifdef HNDCTF
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+#define SKIPCT (1 << 2)
+#define CHAINED (1 << 3)
+#define PKTSETSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->pktc_flags |= SKIPCT); \
+ })
+#define PKTCLRSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT)); \
+ })
+#define PKTSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->pktc_flags & SKIPCT); \
+ })
+#define PKTSETCHAINED(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->pktc_flags |= CHAINED); \
+ })
+#define PKTCLRCHAINED(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED)); \
+ })
+#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->pktc_flags & CHAINED)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+#define SKIPCT (1 << 18)
+#define CHAINED (1 << 19)
+#define PKTSETSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->mac_len |= SKIPCT); \
+ })
+#define PKTCLRSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)); \
+ })
+#define PKTSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->mac_len & SKIPCT); \
+ })
+#define PKTSETCHAINED(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->mac_len |= CHAINED); \
+ })
+#define PKTCLRCHAINED(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->mac_len &= (~CHAINED)); \
+ })
+#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->mac_len & CHAINED)
+#else /* 2.6.22 */
+#define SKIPCT (1 << 2)
+#define CHAINED (1 << 3)
+#define PKTSETSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->__unused |= SKIPCT); \
+ })
+#define PKTCLRSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->__unused &= (~SKIPCT)); \
+ })
+#define PKTSKIPCT(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->__unused & SKIPCT); \
+ })
+#define PKTSETCHAINED(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->__unused |= CHAINED); \
+ })
+#define PKTCLRCHAINED(osh, skb) \
+ ({ \
+ BCM_REFERENCE(osh); \
+ (((struct sk_buff*)(skb))->__unused &= (~CHAINED)); \
+ })
+#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->__unused & CHAINED)
+#endif /* 2.6.22 */
+typedef struct ctf_mark {
+ uint32 value;
+} ctf_mark_t;
+#define CTF_MARK(m) (m.value)
+#else /* HNDCTF */
+#define PKTSETSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
+#define PKTCLRSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
+#define PKTSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
+#define CTF_MARK(m) ({BCM_REFERENCE(m); 0;})
+#endif /* HNDCTF */
+
+#ifdef BCMFA
+#ifdef BCMFA_HW_HASH
+#define PKTSETFAHIDX(skb, idx) (((struct sk_buff*)(skb))->napt_idx = idx)
+#else
+#define PKTSETFAHIDX(skb, idx) ({BCM_REFERENCE(skb); BCM_REFERENCE(idx);})
+#endif /* BCMFA_SW_HASH */
+#define PKTGETFAHIDX(skb) (((struct sk_buff*)(skb))->napt_idx)
+#define PKTSETFADEV(skb, imp) (((struct sk_buff*)(skb))->dev = imp)
+#define PKTSETRXDEV(skb) (((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev)
+
+#define AUX_TCP_FIN_RST (1 << 0)
+#define AUX_FREED (1 << 1)
+#define PKTSETFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST)
+#define PKTCLRFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST))
+#define PKTISFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST)
+#define PKTSETFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_FREED)
+#define PKTCLRFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED))
+#define PKTISFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_FREED)
+#define PKTISFABRIDGED(skb) PKTISFAAUX(skb)
+#else
+#define PKTISFAAUX(skb) ({BCM_REFERENCE(skb); FALSE;})
+#define PKTISFABRIDGED(skb) ({BCM_REFERENCE(skb); FALSE;})
+#define PKTISFAFREED(skb) ({BCM_REFERENCE(skb); FALSE;})
+
+#define PKTCLRFAAUX(skb) BCM_REFERENCE(skb)
+#define PKTSETFAFREED(skb) BCM_REFERENCE(skb)
+#define PKTCLRFAFREED(skb) BCM_REFERENCE(skb)
+#endif /* BCMFA */
+
+extern void osl_pktfree(osl_t *osh, void *skb, bool send);
+extern void *osl_pktget_static(osl_t *osh, uint len);
+extern void osl_pktfree_static(osl_t *osh, void *skb, bool send);
+
+#ifdef BCMDBG_CTRACE
+#define PKT_CTRACE_DUMP(osh, b) osl_ctrace_dump((osh), (b))
+extern void *osl_pktget(osl_t *osh, uint len, int line, char *file);
+extern void *osl_pkt_frmnative(osl_t *osh, void *skb, int line, char *file);
+extern int osl_pkt_is_frmnative(osl_t *osh, struct sk_buff *pkt);
+extern void *osl_pktdup(osl_t *osh, void *skb, int line, char *file);
+struct bcmstrbuf;
+extern void osl_ctrace_dump(osl_t *osh, struct bcmstrbuf *b);
+#else
+extern void *osl_pkt_frmnative(osl_t *osh, void *skb);
+extern void *osl_pktget(osl_t *osh, uint len);
+extern void *osl_pktdup(osl_t *osh, void *skb);
+#endif /* BCMDBG_CTRACE */
+extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt);
+#ifdef BCMDBG_CTRACE
+#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), \
+ (struct sk_buff*)(skb), __LINE__, __FILE__)
+#define PKTISFRMNATIVE(osh, skb) osl_pkt_is_frmnative((osl_t *)(osh), (struct sk_buff *)(skb))
+#else
+#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb))
+#endif /* BCMDBG_CTRACE */
+#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt))
+
+#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev)
+#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x))
+#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority)
+#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x))
+#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW)
+#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \
+ ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
+/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */
+#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned)
+
+#ifdef CONFIG_NF_CONNTRACK_MARK
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define PKTMARK(p) (((struct sk_buff *)(p))->mark)
+#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->mark = (m)
+#else /* !2.6.0 */
+#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark)
+#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m)
+#endif /* 2.6.0 */
+#else /* CONFIG_NF_CONNTRACK_MARK */
+#define PKTMARK(p) 0
+#define PKTSETMARK(p, m)
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
+#define PKTALLOCED(osh) osl_pktalloced(osh)
+extern uint osl_pktalloced(osl_t *osh);
+
+#define DMA_MAP(osh, va, size, direction, p, dmah) \
+ osl_dma_map((osh), (va), (size), (direction), (p), (dmah))
+
+#ifdef PKTC
+/* Use 8 bytes of skb tstamp field to store below info */
+struct chain_node {
+ struct sk_buff *link;
+ unsigned int flags:3, pkts:9, bytes:20;
+};
+
+#define CHAIN_NODE(skb) ((struct chain_node*)(((struct sk_buff*)skb)->pktc_cb))
+
+#define PKTCSETATTR(s, f, p, b) ({CHAIN_NODE(s)->flags = (f); CHAIN_NODE(s)->pkts = (p); \
+ CHAIN_NODE(s)->bytes = (b);})
+#define PKTCCLRATTR(s) ({CHAIN_NODE(s)->flags = CHAIN_NODE(s)->pkts = \
+ CHAIN_NODE(s)->bytes = 0;})
+#define PKTCGETATTR(s) (CHAIN_NODE(s)->flags << 29 | CHAIN_NODE(s)->pkts << 20 | \
+ CHAIN_NODE(s)->bytes)
+#define PKTCCNT(skb) (CHAIN_NODE(skb)->pkts)
+#define PKTCLEN(skb) (CHAIN_NODE(skb)->bytes)
+#define PKTCGETFLAGS(skb) (CHAIN_NODE(skb)->flags)
+#define PKTCSETFLAGS(skb, f) (CHAIN_NODE(skb)->flags = (f))
+#define PKTCCLRFLAGS(skb) (CHAIN_NODE(skb)->flags = 0)
+#define PKTCFLAGS(skb) (CHAIN_NODE(skb)->flags)
+#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c))
+#define PKTCINCRCNT(skb) (CHAIN_NODE(skb)->pkts++)
+#define PKTCADDCNT(skb, c) (CHAIN_NODE(skb)->pkts += (c))
+#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l))
+#define PKTCADDLEN(skb, l) (CHAIN_NODE(skb)->bytes += (l))
+#define PKTCSETFLAG(skb, fb) (CHAIN_NODE(skb)->flags |= (fb))
+#define PKTCCLRFLAG(skb, fb) (CHAIN_NODE(skb)->flags &= ~(fb))
+#define PKTCLINK(skb) (CHAIN_NODE(skb)->link)
+#define PKTSETCLINK(skb, x) (CHAIN_NODE(skb)->link = (struct sk_buff*)(x))
+#define FOREACH_CHAINED_PKT(skb, nskb) \
+ for (; (skb) != NULL; (skb) = (nskb)) \
+ if ((nskb) = (PKTISCHAINED(skb) ? PKTCLINK(skb) : NULL), \
+ PKTSETCLINK((skb), NULL), 1)
+#define PKTCFREE(osh, skb, send) \
+do { \
+ void *nskb; \
+ ASSERT((skb) != NULL); \
+ FOREACH_CHAINED_PKT((skb), nskb) { \
+ PKTCLRCHAINED((osh), (skb)); \
+ PKTCCLRFLAGS((skb)); \
+ PKTFREE((osh), (skb), (send)); \
+ } \
+} while (0)
+#define PKTCENQTAIL(h, t, p) \
+do { \
+ if ((t) == NULL) { \
+ (h) = (t) = (p); \
+ } else { \
+ PKTSETCLINK((t), (p)); \
+ (t) = (p); \
+ } \
+} while (0)
+#endif /* PKTC */
+
+#else /* ! BCMDRIVER */
+
+
+/* ASSERT */
+ #define ASSERT(exp) do {} while (0)
+
+/* MALLOC and MFREE */
+#define MALLOC(o, l) malloc(l)
+#define MFREE(o, p, l) free(p)
+#include <stdlib.h>
+
+/* str* and mem* functions */
+#include <string.h>
+
+/* *printf functions */
+#include <stdio.h>
+
+/* bcopy, bcmp, and bzero */
+extern void bcopy(const void *src, void *dst, size_t len);
+extern int bcmp(const void *b1, const void *b2, size_t len);
+extern void bzero(void *b, size_t len);
+#endif /* ! BCMDRIVER */
+
+#endif /* _linux_osl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h
new file mode 100644
index 000000000000..15071c901e6c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/linuxver.h
@@ -0,0 +1,754 @@
+/*
+ * Linux-specific abstractions to gain some independence from linux kernel versions.
+ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: linuxver.h 656961 2016-08-30 13:20:42Z $
+ */
+
+#ifndef _linuxver_h_
+#define _linuxver_h_
+
+#include <typedefs.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+#include <linux/config.h>
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+#include <generated/autoconf.h>
+#else
+#include <linux/autoconf.h>
+#endif
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */
+#include <linux/module.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
+#include <linux/kconfig.h>
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0))
+/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */
+#ifdef __UNDEF_NO_VERSION__
+#undef __NO_VERSION__
+#else
+#define __NO_VERSION__
+#endif
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i")
+#define module_param_string(_name_, _string_, _size_, _perm_) \
+ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_))
+#endif
+
+/* linux/malloc.h is deprecated, use linux/slab.h instead. */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9))
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+#undef IP_TOS
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */
+#include <asm/io.h>
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41))
+#include <linux/workqueue.h>
+#else
+#include <linux/tqueue.h>
+#ifndef work_struct
+#define work_struct tq_struct
+#endif
+#ifndef INIT_WORK
+#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data))
+#endif
+#ifndef schedule_work
+#define schedule_work(_work) schedule_task((_work))
+#endif
+#ifndef flush_scheduled_work
+#define flush_scheduled_work() flush_scheduled_tasks()
+#endif
+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#define DAEMONIZE(a) do { \
+ allow_signal(SIGKILL); \
+ allow_signal(SIGTERM); \
+ } while (0)
+#elif ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)))
+#define DAEMONIZE(a) daemonize(a); \
+ allow_signal(SIGKILL); \
+ allow_signal(SIGTERM);
+#else /* Linux 2.4 (w/o preemption patch) */
+#define RAISE_RX_SOFTIRQ() \
+ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
+#define DAEMONIZE(a) daemonize(); \
+ do { if (a) \
+ strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a)))); \
+ } while (0);
+#endif /* LINUX_VERSION_CODE */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func)
+#else
+#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work)
+#if !(LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18) && defined(RHEL_MAJOR) && \
+ (RHEL_MAJOR == 5))
+/* Exclude RHEL 5 */
+typedef void (*work_func_t)(void *work);
+#endif
+#endif /* >= 2.6.20 */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+/* Some distributions have their own 2.6.x compatibility layers */
+#ifndef IRQ_NONE
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#define IRQ_RETVAL(x)
+#endif
+#else
+typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#define IRQF_SHARED SA_SHIRQ
+#endif /* < 2.6.18 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
+#ifdef CONFIG_NET_RADIO
+#define CONFIG_WIRELESS_EXT
+#endif
+#endif /* < 2.6.17 */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67)
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+#include <linux/sched.h>
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+#include <linux/sched/rt.h>
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+#include <net/lib80211.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+#include <linux/ieee80211.h>
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#include <net/ieee80211.h>
+#endif
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */
+
+
+#ifndef __exit
+#define __exit
+#endif
+#ifndef __devexit
+#define __devexit
+#endif
+#ifndef __devinit
+# if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+# define __devinit __init
+# else
+/* All devices are hotpluggable since linux 3.8.0 */
+# define __devinit
+# endif
+#endif /* !__devinit */
+#ifndef __devinitdata
+#define __devinitdata
+#endif
+#ifndef __devexit_p
+#define __devexit_p(x) x
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0))
+
+#define pci_get_drvdata(dev) (dev)->sysdata
+#define pci_set_drvdata(dev, value) (dev)->sysdata = (value)
+
+/*
+ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration
+ */
+
+struct pci_device_id {
+ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */
+ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
+ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
+ unsigned long driver_data; /* Data private to the driver */
+};
+
+struct pci_driver {
+ struct list_head node;
+ char *name;
+ const struct pci_device_id *id_table; /* NULL if wants all devices */
+ int (*probe)(struct pci_dev *dev,
+ const struct pci_device_id *id); /* New device inserted */
+ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug
+ * capable driver)
+ */
+ void (*suspend)(struct pci_dev *dev); /* Device suspended */
+ void (*resume)(struct pci_dev *dev); /* Device woken up */
+};
+
+#define MODULE_DEVICE_TABLE(type, name)
+#define PCI_ANY_ID (~0)
+
+/* compatpci.c */
+#define pci_module_init pci_register_driver
+extern int pci_register_driver(struct pci_driver *drv);
+extern void pci_unregister_driver(struct pci_driver *drv);
+
+#endif /* PCI registration */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
+#define pci_module_init pci_register_driver
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18))
+#ifdef MODULE
+#define module_init(x) int init_module(void) { return x(); }
+#define module_exit(x) void cleanup_module(void) { x(); }
+#else
+#define module_init(x) __initcall(x);
+#define module_exit(x) __exitcall(x);
+#endif
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+#define WL_USE_NETDEV_OPS
+#else
+#undef WL_USE_NETDEV_OPS
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL)
+#define WL_CONFIG_RFKILL
+#else
+#undef WL_CONFIG_RFKILL
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48))
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13))
+#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)])
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44))
+#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23))
+#define pci_enable_device(dev) do { } while (0)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14))
+#define net_device device
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42))
+
+/*
+ * DMA mapping
+ *
+ * See linux/Documentation/DMA-mapping.txt
+ */
+
+#ifndef PCI_DMA_TODEVICE
+#define PCI_DMA_TODEVICE 1
+#define PCI_DMA_FROMDEVICE 2
+#endif
+
+typedef u32 dma_addr_t;
+
+/* Pure 2^n version of get_order */
+static inline int get_order(unsigned long size)
+{
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+
+static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ void *ret;
+ int gfp = GFP_ATOMIC | GFP_DMA;
+
+ ret = (void *)__get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_bus(ret);
+ }
+ return ret;
+}
+static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
+#define pci_unmap_single(cookie, address, size, dir)
+
+#endif /* DMA mapping */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43))
+
+#define dev_kfree_skb_any(a) dev_kfree_skb(a)
+#define netif_down(dev) do { (dev)->start = 0; } while (0)
+
+/* pcmcia-cs provides its own netdevice compatibility layer */
+#ifndef _COMPAT_NETDEVICE_H
+
+/*
+ * SoftNet
+ *
+ * For pre-softnet kernels we need to tell the upper layer not to
+ * re-enter start_xmit() while we are in there. However softnet
+ * guarantees not to enter while we are in there so there is no need
+ * to do the netif_stop_queue() dance unless the transmit queue really
+ * gets stuck. This should also improve performance according to tests
+ * done by Aman Singla.
+ */
+
+#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
+#define netif_wake_queue(dev) \
+ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0)
+#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy)
+
+static inline void netif_start_queue(struct net_device *dev)
+{
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+}
+
+#define netif_queue_stopped(dev) (dev)->tbusy
+#define netif_running(dev) (dev)->start
+
+#endif /* _COMPAT_NETDEVICE_H */
+
+#define netif_device_attach(dev) netif_start_queue(dev)
+#define netif_device_detach(dev) netif_stop_queue(dev)
+
+/* 2.4.x renamed bottom halves to tasklets */
+#define tasklet_struct tq_struct
+static inline void tasklet_schedule(struct tasklet_struct *tasklet)
+{
+ queue_task(tasklet, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+static inline void tasklet_init(struct tasklet_struct *tasklet,
+ void (*func)(unsigned long),
+ unsigned long data)
+{
+ tasklet->next = NULL;
+ tasklet->sync = 0;
+ tasklet->routine = (void (*)(void *))func;
+ tasklet->data = (void *)data;
+}
+#define tasklet_kill(tasklet) { do {} while (0); }
+
+/* 2.4.x introduced del_timer_sync() */
+#define del_timer_sync(timer) del_timer(timer)
+
+#else
+
+#define netif_down(dev)
+
+#endif /* SoftNet */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3))
+
+/*
+ * Emit code to initialise a tq_struct's routine and data pointers
+ */
+#define PREPARE_TQUEUE(_tq, _routine, _data) \
+ do { \
+ (_tq)->routine = _routine; \
+ (_tq)->data = _data; \
+ } while (0)
+
+/*
+ * Emit code to initialise all of a tq_struct
+ */
+#define INIT_TQUEUE(_tq, _routine, _data) \
+ do { \
+ INIT_LIST_HEAD(&(_tq)->list); \
+ (_tq)->sync = 0; \
+ PREPARE_TQUEUE((_tq), (_routine), (_data)); \
+ } while (0)
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */
+
+/* Power management related macro & routines */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9)
+#define PCI_SAVE_STATE(a, b) pci_save_state(a)
+#define PCI_RESTORE_STATE(a, b) pci_restore_state(a)
+#else
+#define PCI_SAVE_STATE(a, b) pci_save_state(a, b)
+#define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6))
+static inline int
+pci_save_state(struct pci_dev *dev, u32 *buffer)
+{
+ int i;
+ if (buffer) {
+ for (i = 0; i < 16; i++)
+ pci_read_config_dword(dev, i * 4, &buffer[i]);
+ }
+ return 0;
+}
+
+static inline int
+pci_restore_state(struct pci_dev *dev, u32 *buffer)
+{
+ int i;
+
+ if (buffer) {
+ for (i = 0; i < 16; i++)
+ pci_write_config_dword(dev, i * 4, buffer[i]);
+ }
+ /*
+ * otherwise, write the context information we know from bootup.
+ * This works around a problem where warm-booting from Windows
+ * combined with a D3(hot)->D0 transition causes PCI config
+ * header data to be forgotten.
+ */
+ else {
+ for (i = 0; i < 6; i ++)
+ pci_write_config_dword(dev,
+ PCI_BASE_ADDRESS_0 + (i * 4),
+ pci_resource_start(dev, i));
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+ return 0;
+}
+#endif /* PCI power management */
+
+/* Old cp0 access macros deprecated in 2.4.19 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19))
+#define read_c0_count() read_32bit_cp0_register(CP0_COUNT)
+#endif
+
+/* Module refcount handled internally in 2.6.x */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#ifndef SET_MODULE_OWNER
+#define SET_MODULE_OWNER(dev) do {} while (0)
+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#else
+#define OLD_MOD_INC_USE_COUNT do {} while (0)
+#define OLD_MOD_DEC_USE_COUNT do {} while (0)
+#endif
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */
+#ifndef SET_MODULE_OWNER
+#define SET_MODULE_OWNER(dev) do {} while (0)
+#endif
+#ifndef MOD_INC_USE_COUNT
+#define MOD_INC_USE_COUNT do {} while (0)
+#endif
+#ifndef MOD_DEC_USE_COUNT
+#define MOD_DEC_USE_COUNT do {} while (0)
+#endif
+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */
+
+#ifndef SET_NETDEV_DEV
+#define SET_NETDEV_DEV(net, pdev) do {} while (0)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
+#ifndef HAVE_FREE_NETDEV
+#define free_netdev(dev) kfree(dev)
+#endif
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+/* struct packet_type redefined in 2.6.x */
+#define af_packet_priv data
+#endif
+
+/* suspend args */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+#define DRV_SUSPEND_STATE_TYPE pm_message_t
+#else
+#define DRV_SUSPEND_STATE_TYPE uint32
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+#define CHECKSUM_HW CHECKSUM_PARTIAL
+#endif
+
+typedef struct {
+ void *parent; /* some external entity that the thread supposed to work for */
+ char *proc_name;
+ struct task_struct *p_task;
+ long thr_pid;
+ int prio; /* priority */
+ struct semaphore sema;
+ int terminated;
+ struct completion completed;
+ spinlock_t spinlock;
+ int up_cnt;
+} tsk_ctl_t;
+
+
+/* requires tsk_ctl_t tsk argument, the caller's priv data is passed in owner ptr */
+/* note this macro assumes there may be only one context waiting on thread's completion */
+#ifdef DHD_DEBUG
+#define DBG_THR(x) printk x
+#else
+#define DBG_THR(x)
+#endif
+
+static inline bool binary_sema_down(tsk_ctl_t *tsk)
+{
+ if (down_interruptible(&tsk->sema) == 0) {
+ unsigned long flags = 0;
+ spin_lock_irqsave(&tsk->spinlock, flags);
+ if (tsk->up_cnt == 1)
+ tsk->up_cnt--;
+ else {
+ DBG_THR(("dhd_dpc_thread: Unexpected up_cnt %d\n", tsk->up_cnt));
+ }
+ spin_unlock_irqrestore(&tsk->spinlock, flags);
+ return false;
+ } else
+ return true;
+}
+
+static inline bool binary_sema_up(tsk_ctl_t *tsk)
+{
+ bool sem_up = false;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&tsk->spinlock, flags);
+ if (tsk->up_cnt == 0) {
+ tsk->up_cnt++;
+ sem_up = true;
+ } else if (tsk->up_cnt == 1) {
+ /* dhd_sched_dpc: dpc is alread up! */
+ } else
+ DBG_THR(("dhd_sched_dpc: unexpected up cnt %d!\n", tsk->up_cnt));
+
+ spin_unlock_irqrestore(&tsk->spinlock, flags);
+
+ if (sem_up)
+ up(&tsk->sema);
+
+ return sem_up;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x)
+#else
+#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x)
+#endif
+
+#define PROC_START(thread_func, owner, tsk_ctl, flags, name) \
+{ \
+ sema_init(&((tsk_ctl)->sema), 0); \
+ init_completion(&((tsk_ctl)->completed)); \
+ (tsk_ctl)->parent = owner; \
+ (tsk_ctl)->proc_name = name; \
+ (tsk_ctl)->terminated = FALSE; \
+ (tsk_ctl)->p_task = kthread_run(thread_func, tsk_ctl, (char*)name); \
+ if (IS_ERR((tsk_ctl)->p_task)) { \
+ (tsk_ctl)->thr_pid = DHD_PID_KT_INVALID; \
+ DBG_THR(("%s(): thread:%s:%lx failed\n", __FUNCTION__, \
+ (tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \
+ } else { \
+ (tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \
+ spin_lock_init(&((tsk_ctl)->spinlock)); \
+ DBG_THR(("%s(): thread:%s:%lx started\n", __FUNCTION__, \
+ (tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \
+ } \
+}
+
+#define PROC_STOP(tsk_ctl) \
+{ \
+ (tsk_ctl)->terminated = TRUE; \
+ smp_wmb(); \
+ up(&((tsk_ctl)->sema)); \
+ wait_for_completion(&((tsk_ctl)->completed)); \
+ DBG_THR(("%s(): thread:%s:%lx terminated OK\n", __FUNCTION__, \
+ (tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \
+ (tsk_ctl)->thr_pid = -1; \
+}
+
+/* ----------------------- */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+#define KILL_PROC(nr, sig) \
+{ \
+struct task_struct *tsk; \
+struct pid *pid; \
+pid = find_get_pid((pid_t)nr); \
+tsk = pid_task(pid, PIDTYPE_PID); \
+if (tsk) send_sig(sig, tsk, 1); \
+}
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
+ KERNEL_VERSION(2, 6, 30))
+#define KILL_PROC(pid, sig) \
+{ \
+ struct task_struct *tsk; \
+ tsk = find_task_by_vpid(pid); \
+ if (tsk) send_sig(sig, tsk, 1); \
+}
+#else
+#define KILL_PROC(pid, sig) \
+{ \
+ kill_proc(pid, sig, 1); \
+}
+#endif
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#include <linux/time.h>
+#include <linux/wait.h>
+#else
+#include <linux/sched.h>
+
+#define __wait_event_interruptible_timeout(wq, condition, ret) \
+do { \
+ wait_queue_t __wait; \
+ init_waitqueue_entry(&__wait, current); \
+ \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ set_current_state(TASK_INTERRUPTIBLE); \
+ if (condition) \
+ break; \
+ if (!signal_pending(current)) { \
+ ret = schedule_timeout(ret); \
+ if (!ret) \
+ break; \
+ continue; \
+ } \
+ ret = -ERESTARTSYS; \
+ break; \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout) \
+({ \
+ long __ret = timeout; \
+ if (!(condition)) \
+ __wait_event_interruptible_timeout(wq, condition, __ret); \
+ __ret; \
+})
+
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */
+
+/*
+For < 2.6.24, wl creates its own netdev but doesn't
+align the priv area like the genuine alloc_netdev().
+Since netdev_priv() always gives us the aligned address, it will
+not match our unaligned address for < 2.6.24
+*/
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#define DEV_PRIV(dev) (dev->priv)
+#else
+#define DEV_PRIV(dev) netdev_priv(dev)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+#define WL_ISR(i, d, p) wl_isr((i), (d))
+#else
+#define WL_ISR(i, d, p) wl_isr((i), (d), (p))
+#endif /* < 2.6.20 */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+#define netdev_priv(dev) dev->priv
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+#define CAN_SLEEP() ((!in_atomic() && !irqs_disabled()))
+#else
+#define CAN_SLEEP() (FALSE)
+#endif
+
+#define KMALLOC_FLAG (CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC)
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#define RANDOM32 prandom_u32
+#else
+#define RANDOM32 random32
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#define SRANDOM32(entropy) prandom_seed(entropy)
+#else
+#define SRANDOM32(entropy) srandom32(entropy)
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */
+
+/*
+ * Overide latest kfifo functions with
+ * older version to work on older kernels
+ */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
+#define kfifo_in_spinlocked(a, b, c, d) kfifo_put(a, (u8 *)b, c)
+#define kfifo_out_spinlocked(a, b, c, d) kfifo_get(a, (u8 *)b, c)
+#define kfifo_esize(a) 1
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)) && \
+ (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)) && !defined(WL_COMPAT_WIRELESS)
+#define kfifo_in_spinlocked(a, b, c, d) kfifo_in_locked(a, b, c, d)
+#define kfifo_out_spinlocked(a, b, c, d) kfifo_out_locked(a, b, c, d)
+#define kfifo_esize(a) 1
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) */
+
+#endif /* _linuxver_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/miniopt.h b/drivers/net/wireless/bcmdhd/include/miniopt.h
new file mode 100644
index 000000000000..18e181364db3
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/miniopt.h
@@ -0,0 +1,77 @@
+/*
+ * Command line options parser.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ * $Id: miniopt.h 241182 2011-02-17 21:50:03Z $
+ */
+
+
+#ifndef MINI_OPT_H
+#define MINI_OPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---- Include Files ---------------------------------------------------- */
+/* ---- Constants and Types ---------------------------------------------- */
+
+#define MINIOPT_MAXKEY 128 /* Max options */
+typedef struct miniopt {
+
+ /* These are persistent after miniopt_init() */
+ const char* name; /* name for prompt in error strings */
+ const char* flags; /* option chars that take no args */
+ bool longflags; /* long options may be flags */
+ bool opt_end; /* at end of options (passed a "--") */
+
+ /* These are per-call to miniopt() */
+
+ int consumed; /* number of argv entries cosumed in
+ * the most recent call to miniopt()
+ */
+ bool positional;
+ bool good_int; /* 'val' member is the result of a sucessful
+ * strtol conversion of the option value
+ */
+ char opt;
+ char key[MINIOPT_MAXKEY];
+ char* valstr; /* positional param, or value for the option,
+ * or null if the option had
+ * no accompanying value
+ */
+ uint uval; /* strtol translation of valstr */
+ int val; /* strtol translation of valstr */
+} miniopt_t;
+
+void miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags);
+int miniopt(miniopt_t *t, char **argv);
+
+
+/* ---- Variable Externs ------------------------------------------------- */
+/* ---- Function Prototypes ---------------------------------------------- */
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MINI_OPT_H */
diff --git a/drivers/net/wireless/bcmdhd/include/msgtrace.h b/drivers/net/wireless/bcmdhd/include/msgtrace.h
new file mode 100644
index 000000000000..358cc3b3d0ca
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/msgtrace.h
@@ -0,0 +1,77 @@
+/*
+ * Trace messages sent over HBUS
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: msgtrace.h 369735 2012-11-19 22:50:22Z $
+ */
+
+#ifndef _MSGTRACE_H
+#define _MSGTRACE_H
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#define MSGTRACE_VERSION 1
+
+/* Message trace header */
+typedef BWL_PRE_PACKED_STRUCT struct msgtrace_hdr {
+ uint8 version;
+ uint8 trace_type;
+#define MSGTRACE_HDR_TYPE_MSG 0
+#define MSGTRACE_HDR_TYPE_LOG 1
+ uint16 len; /* Len of the trace */
+ uint32 seqnum; /* Sequence number of message. Useful if the messsage has been lost
+ * because of DMA error or a bus reset (ex: SDIO Func2)
+ */
+ /* Msgtrace type only */
+ uint32 discarded_bytes; /* Number of discarded bytes because of trace overflow */
+ uint32 discarded_printf; /* Number of discarded printf because of trace overflow */
+} BWL_POST_PACKED_STRUCT msgtrace_hdr_t;
+
+#define MSGTRACE_HDRLEN sizeof(msgtrace_hdr_t)
+
+/* The hbus driver generates traces when sending a trace message. This causes endless traces.
+ * This flag must be set to TRUE in any hbus traces. The flag is reset in the function msgtrace_put.
+ * This prevents endless traces but generates hasardous lost of traces only in bus device code.
+ * It is recommendat to set this flag in macro SD_TRACE but not in SD_ERROR for avoiding missing
+ * hbus error traces. hbus error trace should not generates endless traces.
+ */
+extern bool msgtrace_hbus_trace;
+
+typedef void (*msgtrace_func_send_t)(void *hdl1, void *hdl2, uint8 *hdr,
+ uint16 hdrlen, uint8 *buf, uint16 buflen);
+extern void msgtrace_start(void);
+extern void msgtrace_stop(void);
+extern int msgtrace_sent(void);
+extern void msgtrace_put(char *buf, int count);
+extern void msgtrace_init(void *hdl1, void *hdl2, msgtrace_func_send_t func_send);
+extern bool msgtrace_event_enabled(void);
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _MSGTRACE_H */
diff --git a/drivers/net/wireless/bcmdhd/include/osl.h b/drivers/net/wireless/bcmdhd/include/osl.h
new file mode 100644
index 000000000000..928cbf98e4fb
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/osl.h
@@ -0,0 +1,142 @@
+/*
+ * OS Abstraction Layer
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: osl.h 424562 2013-09-18 10:57:30Z $
+ */
+
+#ifndef _osl_h_
+#define _osl_h_
+
+/* osl handle type forward declaration */
+typedef struct osl_info osl_t;
+typedef struct osl_dmainfo osldma_t;
+
+#define OSL_PKTTAG_SZ 32 /* Size of PktTag */
+
+/* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */
+typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status);
+
+/* Drivers use REGOPSSET() to register register read/write funcitons */
+typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size);
+typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size);
+
+
+#include <linux_osl.h>
+
+#ifndef PKTDBG_TRACE
+#define PKTDBG_TRACE(osh, pkt, bit) BCM_REFERENCE(osh)
+#endif
+
+#define PKTCTFMAP(osh, p) BCM_REFERENCE(osh)
+
+/* --------------------------------------------------------------------------
+** Register manipulation macros.
+*/
+
+#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val)))
+
+#ifndef AND_REG
+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
+#endif /* !AND_REG */
+
+#ifndef OR_REG
+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
+#endif /* !OR_REG */
+
+#if !defined(OSL_SYSUPTIME)
+#define OSL_SYSUPTIME() (0)
+#define OSL_SYSUPTIME_SUPPORT FALSE
+#else
+#define OSL_SYSUPTIME_SUPPORT TRUE
+#endif /* OSL_SYSUPTIME */
+
+#if !defined(PKTC) && !defined(PKTC_DONGLE)
+#define PKTCGETATTR(skb) (0)
+#define PKTCSETATTR(skb, f, p, b) BCM_REFERENCE(skb)
+#define PKTCCLRATTR(skb) BCM_REFERENCE(skb)
+#define PKTCCNT(skb) (1)
+#define PKTCLEN(skb) PKTLEN(NULL, skb)
+#define PKTCGETFLAGS(skb) (0)
+#define PKTCSETFLAGS(skb, f) BCM_REFERENCE(skb)
+#define PKTCCLRFLAGS(skb) BCM_REFERENCE(skb)
+#define PKTCFLAGS(skb) (0)
+#define PKTCSETCNT(skb, c) BCM_REFERENCE(skb)
+#define PKTCINCRCNT(skb) BCM_REFERENCE(skb)
+#define PKTCADDCNT(skb, c) BCM_REFERENCE(skb)
+#define PKTCSETLEN(skb, l) BCM_REFERENCE(skb)
+#define PKTCADDLEN(skb, l) BCM_REFERENCE(skb)
+#define PKTCSETFLAG(skb, fb) BCM_REFERENCE(skb)
+#define PKTCCLRFLAG(skb, fb) BCM_REFERENCE(skb)
+#define PKTCLINK(skb) NULL
+#define PKTSETCLINK(skb, x) BCM_REFERENCE(skb)
+#define FOREACH_CHAINED_PKT(skb, nskb) \
+ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb))
+#define PKTCFREE PKTFREE
+#define PKTCENQTAIL(h, t, p) \
+do { \
+ if ((t) == NULL) { \
+ (h) = (t) = (p); \
+ } \
+} while (0)
+#endif /* !linux || !PKTC */
+
+#if !defined(HNDCTF) && !defined(PKTC_TX_DONGLE)
+#define PKTSETCHAINED(osh, skb) BCM_REFERENCE(osh)
+#define PKTCLRCHAINED(osh, skb) BCM_REFERENCE(osh)
+#define PKTISCHAINED(skb) FALSE
+#endif
+
+/* Lbuf with fraglist */
+#define PKTFRAGPKTID(osh, lb) (0)
+#define PKTSETFRAGPKTID(osh, lb, id) BCM_REFERENCE(osh)
+#define PKTFRAGTOTNUM(osh, lb) (0)
+#define PKTSETFRAGTOTNUM(osh, lb, tot) BCM_REFERENCE(osh)
+#define PKTFRAGTOTLEN(osh, lb) (0)
+#define PKTSETFRAGTOTLEN(osh, lb, len) BCM_REFERENCE(osh)
+#define PKTFRAGIFINDEX(osh, lb) (0)
+#define PKTSETFRAGIFINDEX(osh, lb, idx) BCM_REFERENCE(osh)
+
+/* in rx path, reuse totlen as used len */
+#define PKTFRAGUSEDLEN(osh, lb) (0)
+#define PKTSETFRAGUSEDLEN(osh, lb, len) BCM_REFERENCE(osh)
+
+#define PKTFRAGLEN(osh, lb, ix) (0)
+#define PKTSETFRAGLEN(osh, lb, ix, len) BCM_REFERENCE(osh)
+#define PKTFRAGDATA_LO(osh, lb, ix) (0)
+#define PKTSETFRAGDATA_LO(osh, lb, ix, addr) BCM_REFERENCE(osh)
+#define PKTFRAGDATA_HI(osh, lb, ix) (0)
+#define PKTSETFRAGDATA_HI(osh, lb, ix, addr) BCM_REFERENCE(osh)
+
+/* RX FRAG */
+#define PKTISRXFRAG(osh, lb) (0)
+#define PKTSETRXFRAG(osh, lb) BCM_REFERENCE(osh)
+#define PKTRESETRXFRAG(osh, lb) BCM_REFERENCE(osh)
+
+/* TX FRAG */
+#define PKTISTXFRAG(osh, lb) (0)
+#define PKTSETTXFRAG(osh, lb) BCM_REFERENCE(osh)
+
+#define PKTISFRAG(osh, lb) (0)
+#define PKTFRAGISCHAINED(osh, i) (0)
+
+#endif /* _osl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/packed_section_end.h b/drivers/net/wireless/bcmdhd/include/packed_section_end.h
new file mode 100644
index 000000000000..3ad2eb68486b
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/packed_section_end.h
@@ -0,0 +1,59 @@
+/*
+ * Declare directives for structure packing. No padding will be provided
+ * between the members of packed structures, and therefore, there is no
+ * guarantee that structure members will be aligned.
+ *
+ * Declaring packed structures is compiler specific. In order to handle all
+ * cases, packed structures should be delared as:
+ *
+ * #include <packed_section_start.h>
+ *
+ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t {
+ * some_struct_members;
+ * } BWL_POST_PACKED_STRUCT foobar_t;
+ *
+ * #include <packed_section_end.h>
+ *
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ * $Id: packed_section_end.h 241182 2011-02-17 21:50:03Z $
+ */
+
+
+/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
+ * and undefined in packed_section_end.h. If it is NOT defined at this
+ * point, then there is a missing include of packed_section_start.h.
+ */
+#ifdef BWL_PACKED_SECTION
+ #undef BWL_PACKED_SECTION
+#else
+ #error "BWL_PACKED_SECTION is NOT defined!"
+#endif
+
+
+
+
+/* Compiler-specific directives for structure packing are declared in
+ * packed_section_start.h. This marks the end of the structure packing section,
+ * so, undef them here.
+ */
+#undef BWL_PRE_PACKED_STRUCT
+#undef BWL_POST_PACKED_STRUCT
diff --git a/drivers/net/wireless/bcmdhd/include/packed_section_start.h b/drivers/net/wireless/bcmdhd/include/packed_section_start.h
new file mode 100644
index 000000000000..a8dd120f750c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/packed_section_start.h
@@ -0,0 +1,63 @@
+/*
+ * Declare directives for structure packing. No padding will be provided
+ * between the members of packed structures, and therefore, there is no
+ * guarantee that structure members will be aligned.
+ *
+ * Declaring packed structures is compiler specific. In order to handle all
+ * cases, packed structures should be delared as:
+ *
+ * #include <packed_section_start.h>
+ *
+ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t {
+ * some_struct_members;
+ * } BWL_POST_PACKED_STRUCT foobar_t;
+ *
+ * #include <packed_section_end.h>
+ *
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ * $Id: packed_section_start.h 286783 2011-09-29 06:18:57Z $
+ */
+
+
+/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
+ * and undefined in packed_section_end.h. If it is already defined at this
+ * point, then there is a missing include of packed_section_end.h.
+ */
+#ifdef BWL_PACKED_SECTION
+ #error "BWL_PACKED_SECTION is already defined!"
+#else
+ #define BWL_PACKED_SECTION
+#endif
+
+
+
+
+/* Declare compiler-specific directives for structure packing. */
+#if defined(__GNUC__) || defined(__lint)
+ #define BWL_PRE_PACKED_STRUCT
+ #define BWL_POST_PACKED_STRUCT __attribute__ ((packed))
+#elif defined(__CC_ARM)
+ #define BWL_PRE_PACKED_STRUCT __packed
+ #define BWL_POST_PACKED_STRUCT
+#else
+ #error "Unknown compiler!"
+#endif
diff --git a/drivers/net/wireless/bcmdhd/include/pcicfg.h b/drivers/net/wireless/bcmdhd/include/pcicfg.h
new file mode 100644
index 000000000000..05849db91b39
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/pcicfg.h
@@ -0,0 +1,101 @@
+/*
+ * pcicfg.h: PCI configuration constants and structures.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: pcicfg.h 413666 2013-07-20 01:16:40Z $
+ */
+
+#ifndef _h_pcicfg_
+#define _h_pcicfg_
+
+/* A structure for the config registers is nice, but in most
+ * systems the config space is not memory mapped, so we need
+ * field offsetts. :-(
+ */
+#define PCI_CFG_VID 0
+#define PCI_CFG_DID 2
+#define PCI_CFG_CMD 4
+#define PCI_CFG_STAT 6
+#define PCI_CFG_REV 8
+#define PCI_CFG_PROGIF 9
+#define PCI_CFG_SUBCL 0xa
+#define PCI_CFG_BASECL 0xb
+#define PCI_CFG_CLSZ 0xc
+#define PCI_CFG_LATTIM 0xd
+#define PCI_CFG_HDR 0xe
+#define PCI_CFG_BIST 0xf
+#define PCI_CFG_BAR0 0x10
+#define PCI_CFG_BAR1 0x14
+#define PCI_CFG_BAR2 0x18
+#define PCI_CFG_BAR3 0x1c
+#define PCI_CFG_BAR4 0x20
+#define PCI_CFG_BAR5 0x24
+#define PCI_CFG_CIS 0x28
+#define PCI_CFG_SVID 0x2c
+#define PCI_CFG_SSID 0x2e
+#define PCI_CFG_ROMBAR 0x30
+#define PCI_CFG_CAPPTR 0x34
+#define PCI_CFG_INT 0x3c
+#define PCI_CFG_PIN 0x3d
+#define PCI_CFG_MINGNT 0x3e
+#define PCI_CFG_MAXLAT 0x3f
+#define PCI_CFG_DEVCTRL 0xd8
+#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */
+#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */
+#define PCI_SPROM_CONTROL 0x88 /* sprom property control */
+#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */
+#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */
+#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */
+#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */
+#define PCI_BACKPLANE_ADDR 0xa0 /* address an arbitrary location on the system backplane */
+#define PCI_BACKPLANE_DATA 0xa4 /* data at the location specified by above address */
+#define PCI_CLK_CTL_ST 0xa8 /* pci config space clock control/status (>=rev14) */
+#define PCI_BAR0_WIN2 0xac /* backplane addres space accessed by second 4KB of BAR0 */
+#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */
+#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */
+#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */
+
+#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */
+#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */
+#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */
+#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the
+ * 8KB window, so their address is the "regular"
+ * address plus 4K
+ */
+/*
+ * PCIE GEN2 changed some of the above locations for
+ * Bar0WrapperBase, SecondaryBAR0Window and SecondaryBAR0WrapperBase
+ * BAR0 maps 32K of register space
+*/
+#define PCIE2_BAR0_WIN2 0x70 /* backplane addres space accessed by second 4KB of BAR0 */
+#define PCIE2_BAR0_CORE2_WIN 0x74 /* backplane addres space accessed by second 4KB of BAR0 */
+#define PCIE2_BAR0_CORE2_WIN2 0x78 /* backplane addres space accessed by second 4KB of BAR0 */
+
+#define PCI_BAR0_WINSZ (16 * 1024) /* bar0 window size Match with corerev 13 */
+/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */
+#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */
+#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */
+#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */
+
+
+#define PCI_CONFIG_SPACE_SIZE 256
+#endif /* _h_pcicfg_ */
diff --git a/drivers/net/wireless/bcmdhd/include/pcie_core.h b/drivers/net/wireless/bcmdhd/include/pcie_core.h
new file mode 100644
index 000000000000..36dc875690e7
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/pcie_core.h
@@ -0,0 +1,581 @@
+/*
+ * BCM43XX PCIE core hardware definitions.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: pcie_core.h 430913 2013-10-21 21:46:10Z $
+ */
+#ifndef _PCIE_CORE_H
+#define _PCIE_CORE_H
+#include <sbhnddma.h>
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define _PADLINE(line) pad ## line
+#define _XSTR(line) _PADLINE(line)
+#define PAD _XSTR(__LINE__)
+#endif
+
+/* PCIE Enumeration space offsets */
+#define PCIE_CORE_CONFIG_OFFSET 0x0
+#define PCIE_FUNC0_CONFIG_OFFSET 0x400
+#define PCIE_FUNC1_CONFIG_OFFSET 0x500
+#define PCIE_FUNC2_CONFIG_OFFSET 0x600
+#define PCIE_FUNC3_CONFIG_OFFSET 0x700
+#define PCIE_SPROM_SHADOW_OFFSET 0x800
+#define PCIE_SBCONFIG_OFFSET 0xE00
+
+
+#define PCIEDEV_MAX_DMAS 4
+
+/* PCIE Bar0 Address Mapping. Each function maps 16KB config space */
+#define PCIE_DEV_BAR0_SIZE 0x4000
+#define PCIE_BAR0_WINMAPCORE_OFFSET 0x0
+#define PCIE_BAR0_EXTSPROM_OFFSET 0x1000
+#define PCIE_BAR0_PCIECORE_OFFSET 0x2000
+#define PCIE_BAR0_CCCOREREG_OFFSET 0x3000
+
+/* different register spaces to access thr'u pcie indirect access */
+#define PCIE_CONFIGREGS 1 /* Access to config space */
+#define PCIE_PCIEREGS 2 /* Access to pcie registers */
+
+/* dma regs to control the flow between host2dev and dev2host */
+typedef struct pcie_devdmaregs {
+ dma64regs_t tx;
+ uint32 PAD[2];
+ dma64regs_t rx;
+ uint32 PAD[2];
+} pcie_devdmaregs_t;
+
+
+/* door bell register sets */
+typedef struct pcie_doorbell {
+ uint32 host2dev_0;
+ uint32 host2dev_1;
+ uint32 dev2host_0;
+ uint32 dev2host_1;
+} pcie_doorbell_t;
+
+/* SB side: PCIE core and host control registers */
+typedef struct sbpcieregs {
+ uint32 control; /* host mode only */
+ uint32 iocstatus; /* PCIE2: iostatus */
+ uint32 PAD[1];
+ uint32 biststatus; /* bist Status: 0x00C */
+ uint32 gpiosel; /* PCIE gpio sel: 0x010 */
+ uint32 gpioouten; /* PCIE gpio outen: 0x14 */
+ uint32 PAD[2];
+ uint32 intstatus; /* Interrupt status: 0x20 */
+ uint32 intmask; /* Interrupt mask: 0x24 */
+ uint32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */
+ uint32 obffcontrol; /* PCIE2: 0x2C */
+ uint32 obffintstatus; /* PCIE2: 0x30 */
+ uint32 obffdatastatus; /* PCIE2: 0x34 */
+ uint32 PAD[2];
+ uint32 errlog; /* PCIE2: 0x40 */
+ uint32 errlogaddr; /* PCIE2: 0x44 */
+ uint32 mailboxint; /* PCIE2: 0x48 */
+ uint32 mailboxintmsk; /* PCIE2: 0x4c */
+ uint32 ltrspacing; /* PCIE2: 0x50 */
+ uint32 ltrhysteresiscnt; /* PCIE2: 0x54 */
+ uint32 PAD[42];
+
+ uint32 sbtopcie0; /* sb to pcie translation 0: 0x100 */
+ uint32 sbtopcie1; /* sb to pcie translation 1: 0x104 */
+ uint32 sbtopcie2; /* sb to pcie translation 2: 0x108 */
+ uint32 PAD[5];
+
+ /* pcie core supports in direct access to config space */
+ uint32 configaddr; /* pcie config space access: Address field: 0x120 */
+ uint32 configdata; /* pcie config space access: Data field: 0x124 */
+ union {
+ struct {
+ /* mdio access to serdes */
+ uint32 mdiocontrol; /* controls the mdio access: 0x128 */
+ uint32 mdiodata; /* Data to the mdio access: 0x12c */
+ /* pcie protocol phy/dllp/tlp register indirect access mechanism */
+ uint32 pcieindaddr; /* indirect access to the internal register: 0x130 */
+ uint32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */
+ uint32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */
+ uint32 PAD[177];
+ } pcie1;
+ struct {
+ /* mdio access to serdes */
+ uint32 mdiocontrol; /* controls the mdio access: 0x128 */
+ uint32 mdiowrdata; /* write data to mdio 0x12C */
+ uint32 mdiorddata; /* read data to mdio 0x130 */
+ uint32 PAD[3]; /* 0x134-0x138-0x13c */
+ /* door bell registers available from gen2 rev5 onwards */
+ pcie_doorbell_t dbls[PCIEDEV_MAX_DMAS]; /* 0x140 - 0x17F */
+ uint32 dataintf; /* 0x180 */
+ uint32 PAD[1]; /* 0x184 */
+ uint32 d2h_intrlazy_0; /* 0x188 */
+ uint32 h2d_intrlazy_0; /* 0x18c */
+ uint32 h2d_intstat_0; /* 0x190 */
+ uint32 h2d_intmask_0; /* 0x194 */
+ uint32 d2h_intstat_0; /* 0x198 */
+ uint32 d2h_intmask_0; /* 0x19c */
+ uint32 ltr_state; /* 0x1A0 */
+ uint32 pwr_int_status; /* 0x1A4 */
+ uint32 pwr_int_mask; /* 0x1A8 */
+ uint32 PAD[21]; /* 0x1AC - 0x200 */
+ pcie_devdmaregs_t h2d0_dmaregs; /* 0x200 - 0x23c */
+ pcie_devdmaregs_t d2h0_dmaregs; /* 0x240 - 0x27c */
+ pcie_devdmaregs_t h2d1_dmaregs; /* 0x280 - 0x2bc */
+ pcie_devdmaregs_t d2h1_dmaregs; /* 0x2c0 - 0x2fc */
+ pcie_devdmaregs_t h2d2_dmaregs; /* 0x300 - 0x33c */
+ pcie_devdmaregs_t d2h2_dmaregs; /* 0x340 - 0x37c */
+ pcie_devdmaregs_t h2d3_dmaregs; /* 0x380 - 0x3bc */
+ pcie_devdmaregs_t d2h3_dmaregs; /* 0x3c0 - 0x3fc */
+ } pcie2;
+ } u;
+ uint32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */
+ uint16 sprom[64]; /* SPROM shadow Area */
+} sbpcieregs_t;
+
+/* PCI control */
+#define PCIE_RST_OE 0x01 /* When set, drives PCI_RESET out to pin */
+#define PCIE_RST 0x02 /* Value driven out to pin */
+#define PCIE_SPERST 0x04 /* SurvivePeRst */
+#define PCIE_DISABLE_L1CLK_GATING 0x10
+#define PCIE_DISSPROMLD 0x200 /* DisableSpromLoadOnPerst */
+
+#define PCIE_CFGADDR 0x120 /* offsetof(configaddr) */
+#define PCIE_CFGDATA 0x124 /* offsetof(configdata) */
+
+/* Interrupt status/mask */
+#define PCIE_INTA 0x01 /* PCIE INTA message is received */
+#define PCIE_INTB 0x02 /* PCIE INTB message is received */
+#define PCIE_INTFATAL 0x04 /* PCIE INTFATAL message is received */
+#define PCIE_INTNFATAL 0x08 /* PCIE INTNONFATAL message is received */
+#define PCIE_INTCORR 0x10 /* PCIE INTCORR message is received */
+#define PCIE_INTPME 0x20 /* PCIE INTPME message is received */
+#define PCIE_PERST 0x40 /* PCIE Reset Interrupt */
+
+#define PCIE_INT_MB_FN0_0 0x0100 /* PCIE to SB Mailbox int Fn0.0 is received */
+#define PCIE_INT_MB_FN0_1 0x0200 /* PCIE to SB Mailbox int Fn0.1 is received */
+#define PCIE_INT_MB_FN1_0 0x0400 /* PCIE to SB Mailbox int Fn1.0 is received */
+#define PCIE_INT_MB_FN1_1 0x0800 /* PCIE to SB Mailbox int Fn1.1 is received */
+#define PCIE_INT_MB_FN2_0 0x1000 /* PCIE to SB Mailbox int Fn2.0 is received */
+#define PCIE_INT_MB_FN2_1 0x2000 /* PCIE to SB Mailbox int Fn2.1 is received */
+#define PCIE_INT_MB_FN3_0 0x4000 /* PCIE to SB Mailbox int Fn3.0 is received */
+#define PCIE_INT_MB_FN3_1 0x8000 /* PCIE to SB Mailbox int Fn3.1 is received */
+
+/* PCIE MailboxInt/MailboxIntMask register */
+#define PCIE_MB_TOSB_FN0_0 0x0001 /* write to assert PCIEtoSB Mailbox interrupt */
+#define PCIE_MB_TOSB_FN0_1 0x0002
+#define PCIE_MB_TOSB_FN1_0 0x0004
+#define PCIE_MB_TOSB_FN1_1 0x0008
+#define PCIE_MB_TOSB_FN2_0 0x0010
+#define PCIE_MB_TOSB_FN2_1 0x0020
+#define PCIE_MB_TOSB_FN3_0 0x0040
+#define PCIE_MB_TOSB_FN3_1 0x0080
+#define PCIE_MB_TOPCIE_FN0_0 0x0100 /* int status/mask for SBtoPCIE Mailbox interrupts */
+#define PCIE_MB_TOPCIE_FN0_1 0x0200
+#define PCIE_MB_TOPCIE_FN1_0 0x0400
+#define PCIE_MB_TOPCIE_FN1_1 0x0800
+#define PCIE_MB_TOPCIE_FN2_0 0x1000
+#define PCIE_MB_TOPCIE_FN2_1 0x2000
+#define PCIE_MB_TOPCIE_FN3_0 0x4000
+#define PCIE_MB_TOPCIE_FN3_1 0x8000
+#define PCIE_MB_TOPCIE_D2H0_DB0 0x10000
+#define PCIE_MB_TOPCIE_D2H0_DB1 0x20000
+#define PCIE_MB_TOPCIE_D2H1_DB0 0x40000
+#define PCIE_MB_TOPCIE_D2H1_DB1 0x80000
+#define PCIE_MB_TOPCIE_D2H2_DB0 0x100000
+#define PCIE_MB_TOPCIE_D2H2_DB1 0x200000
+#define PCIE_MB_TOPCIE_D2H3_DB0 0x400000
+#define PCIE_MB_TOPCIE_D2H3_DB1 0x800000
+
+#define PCIE_MB_D2H_MB_MASK \
+ (PCIE_MB_TOPCIE_D2H0_DB0 | PCIE_MB_TOPCIE_D2H0_DB1 | \
+ PCIE_MB_TOPCIE_D2H1_DB1 | PCIE_MB_TOPCIE_D2H1_DB1 | \
+ PCIE_MB_TOPCIE_D2H2_DB1 | PCIE_MB_TOPCIE_D2H2_DB1 | \
+ PCIE_MB_TOPCIE_D2H3_DB1 | PCIE_MB_TOPCIE_D2H3_DB1)
+
+/* SB to PCIE translation masks */
+#define SBTOPCIE0_MASK 0xfc000000
+#define SBTOPCIE1_MASK 0xfc000000
+#define SBTOPCIE2_MASK 0xc0000000
+
+/* Access type bits (0:1) */
+#define SBTOPCIE_MEM 0
+#define SBTOPCIE_IO 1
+#define SBTOPCIE_CFG0 2
+#define SBTOPCIE_CFG1 3
+
+/* Prefetch enable bit 2 */
+#define SBTOPCIE_PF 4
+
+/* Write Burst enable for memory write bit 3 */
+#define SBTOPCIE_WR_BURST 8
+
+/* config access */
+#define CONFIGADDR_FUNC_MASK 0x7000
+#define CONFIGADDR_FUNC_SHF 12
+#define CONFIGADDR_REG_MASK 0x0FFF
+#define CONFIGADDR_REG_SHF 0
+
+#define PCIE_CONFIG_INDADDR(f, r) ((((f) & CONFIGADDR_FUNC_MASK) << CONFIGADDR_FUNC_SHF) | \
+ (((r) & CONFIGADDR_REG_MASK) << CONFIGADDR_REG_SHF))
+
+/* PCIE protocol regs Indirect Address */
+#define PCIEADDR_PROT_MASK 0x300
+#define PCIEADDR_PROT_SHF 8
+#define PCIEADDR_PL_TLP 0
+#define PCIEADDR_PL_DLLP 1
+#define PCIEADDR_PL_PLP 2
+
+/* PCIE protocol PHY diagnostic registers */
+#define PCIE_PLP_MODEREG 0x200 /* Mode */
+#define PCIE_PLP_STATUSREG 0x204 /* Status */
+#define PCIE_PLP_LTSSMCTRLREG 0x208 /* LTSSM control */
+#define PCIE_PLP_LTLINKNUMREG 0x20c /* Link Training Link number */
+#define PCIE_PLP_LTLANENUMREG 0x210 /* Link Training Lane number */
+#define PCIE_PLP_LTNFTSREG 0x214 /* Link Training N_FTS */
+#define PCIE_PLP_ATTNREG 0x218 /* Attention */
+#define PCIE_PLP_ATTNMASKREG 0x21C /* Attention Mask */
+#define PCIE_PLP_RXERRCTR 0x220 /* Rx Error */
+#define PCIE_PLP_RXFRMERRCTR 0x224 /* Rx Framing Error */
+#define PCIE_PLP_RXERRTHRESHREG 0x228 /* Rx Error threshold */
+#define PCIE_PLP_TESTCTRLREG 0x22C /* Test Control reg */
+#define PCIE_PLP_SERDESCTRLOVRDREG 0x230 /* SERDES Control Override */
+#define PCIE_PLP_TIMINGOVRDREG 0x234 /* Timing param override */
+#define PCIE_PLP_RXTXSMDIAGREG 0x238 /* RXTX State Machine Diag */
+#define PCIE_PLP_LTSSMDIAGREG 0x23C /* LTSSM State Machine Diag */
+
+/* PCIE protocol DLLP diagnostic registers */
+#define PCIE_DLLP_LCREG 0x100 /* Link Control */
+#define PCIE_DLLP_LSREG 0x104 /* Link Status */
+#define PCIE_DLLP_LAREG 0x108 /* Link Attention */
+#define PCIE_DLLP_LAMASKREG 0x10C /* Link Attention Mask */
+#define PCIE_DLLP_NEXTTXSEQNUMREG 0x110 /* Next Tx Seq Num */
+#define PCIE_DLLP_ACKEDTXSEQNUMREG 0x114 /* Acked Tx Seq Num */
+#define PCIE_DLLP_PURGEDTXSEQNUMREG 0x118 /* Purged Tx Seq Num */
+#define PCIE_DLLP_RXSEQNUMREG 0x11C /* Rx Sequence Number */
+#define PCIE_DLLP_LRREG 0x120 /* Link Replay */
+#define PCIE_DLLP_LACKTOREG 0x124 /* Link Ack Timeout */
+#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */
+#define PCIE_DLLP_RTRYWPREG 0x12C /* Retry buffer write ptr */
+#define PCIE_DLLP_RTRYRPREG 0x130 /* Retry buffer Read ptr */
+#define PCIE_DLLP_RTRYPPREG 0x134 /* Retry buffer Purged ptr */
+#define PCIE_DLLP_RTRRWREG 0x138 /* Retry buffer Read/Write */
+#define PCIE_DLLP_ECTHRESHREG 0x13C /* Error Count Threshold */
+#define PCIE_DLLP_TLPERRCTRREG 0x140 /* TLP Error Counter */
+#define PCIE_DLLP_ERRCTRREG 0x144 /* Error Counter */
+#define PCIE_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter */
+#define PCIE_DLLP_TESTREG 0x14C /* Test */
+#define PCIE_DLLP_PKTBIST 0x150 /* Packet BIST */
+#define PCIE_DLLP_PCIE11 0x154 /* DLLP PCIE 1.1 reg */
+
+#define PCIE_DLLP_LSREG_LINKUP (1 << 16)
+
+/* PCIE protocol TLP diagnostic registers */
+#define PCIE_TLP_CONFIGREG 0x000 /* Configuration */
+#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */
+#define PCIE_TLP_WRDMAUPPER 0x010 /* Write DMA Upper Address */
+#define PCIE_TLP_WRDMALOWER 0x014 /* Write DMA Lower Address */
+#define PCIE_TLP_WRDMAREQ_LBEREG 0x018 /* Write DMA Len/ByteEn Req */
+#define PCIE_TLP_RDDMAUPPER 0x01C /* Read DMA Upper Address */
+#define PCIE_TLP_RDDMALOWER 0x020 /* Read DMA Lower Address */
+#define PCIE_TLP_RDDMALENREG 0x024 /* Read DMA Len Req */
+#define PCIE_TLP_MSIDMAUPPER 0x028 /* MSI DMA Upper Address */
+#define PCIE_TLP_MSIDMALOWER 0x02C /* MSI DMA Lower Address */
+#define PCIE_TLP_MSIDMALENREG 0x030 /* MSI DMA Len Req */
+#define PCIE_TLP_SLVREQLENREG 0x034 /* Slave Request Len */
+#define PCIE_TLP_FCINPUTSREQ 0x038 /* Flow Control Inputs */
+#define PCIE_TLP_TXSMGRSREQ 0x03C /* Tx StateMachine and Gated Req */
+#define PCIE_TLP_ADRACKCNTARBLEN 0x040 /* Address Ack XferCnt and ARB Len */
+#define PCIE_TLP_DMACPLHDR0 0x044 /* DMA Completion Hdr 0 */
+#define PCIE_TLP_DMACPLHDR1 0x048 /* DMA Completion Hdr 1 */
+#define PCIE_TLP_DMACPLHDR2 0x04C /* DMA Completion Hdr 2 */
+#define PCIE_TLP_DMACPLMISC0 0x050 /* DMA Completion Misc0 */
+#define PCIE_TLP_DMACPLMISC1 0x054 /* DMA Completion Misc1 */
+#define PCIE_TLP_DMACPLMISC2 0x058 /* DMA Completion Misc2 */
+#define PCIE_TLP_SPTCTRLLEN 0x05C /* Split Controller Req len */
+#define PCIE_TLP_SPTCTRLMSIC0 0x060 /* Split Controller Misc 0 */
+#define PCIE_TLP_SPTCTRLMSIC1 0x064 /* Split Controller Misc 1 */
+#define PCIE_TLP_BUSDEVFUNC 0x068 /* Bus/Device/Func */
+#define PCIE_TLP_RESETCTR 0x06C /* Reset Counter */
+#define PCIE_TLP_RTRYBUF 0x070 /* Retry Buffer value */
+#define PCIE_TLP_TGTDEBUG1 0x074 /* Target Debug Reg1 */
+#define PCIE_TLP_TGTDEBUG2 0x078 /* Target Debug Reg2 */
+#define PCIE_TLP_TGTDEBUG3 0x07C /* Target Debug Reg3 */
+#define PCIE_TLP_TGTDEBUG4 0x080 /* Target Debug Reg4 */
+
+/* MDIO control */
+#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
+#define MDIOCTL_DIVISOR_VAL 0x2
+#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */
+#define MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */
+
+/* MDIO Data */
+#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */
+#define MDIODATA_TA 0x00020000 /* Turnaround */
+#define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift (rev < 10) */
+#define MDIODATA_REGADDR_MASK_OLD 0x003c0000 /* Regaddr Mask (rev < 10) */
+#define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift (rev < 10) */
+#define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */
+#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */
+#define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */
+#define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */
+#define MDIODATA_DEVADDR_MASK 0x0f800000 /* Physmedia devaddr Mask */
+#define MDIODATA_WRITE 0x10000000 /* write Transaction */
+#define MDIODATA_READ 0x20000000 /* Read Transaction */
+#define MDIODATA_START 0x40000000 /* start of Transaction */
+
+#define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */
+#define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */
+
+/* MDIO control/wrData/rdData register defines for PCIE Gen 2 */
+#define MDIOCTL2_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
+#define MDIOCTL2_DIVISOR_VAL 0x2
+#define MDIOCTL2_REGADDR_SHF 8 /* Regaddr shift */
+#define MDIOCTL2_REGADDR_MASK 0x00FFFF00 /* Regaddr Mask */
+#define MDIOCTL2_DEVADDR_SHF 24 /* Physmedia devaddr shift */
+#define MDIOCTL2_DEVADDR_MASK 0x0f000000 /* Physmedia devaddr Mask */
+#define MDIOCTL2_SLAVE_BYPASS 0x10000000 /* IP slave bypass */
+#define MDIOCTL2_READ 0x20000000 /* IP slave bypass */
+
+#define MDIODATA2_DONE 0x80000000 /* rd/wr transaction done */
+#define MDIODATA2_MASK 0x7FFFFFFF /* rd/wr transaction data */
+#define MDIODATA2_DEVADDR_SHF 4 /* Physmedia devaddr shift */
+
+
+/* MDIO devices (SERDES modules)
+ * unlike old pcie cores (rev < 10), rev10 pcie serde organizes registers into a few blocks.
+ * two layers mapping (blockidx, register offset) is required
+ */
+#define MDIO_DEV_IEEE0 0x000
+#define MDIO_DEV_IEEE1 0x001
+#define MDIO_DEV_BLK0 0x800
+#define MDIO_DEV_BLK1 0x801
+#define MDIO_DEV_BLK2 0x802
+#define MDIO_DEV_BLK3 0x803
+#define MDIO_DEV_BLK4 0x804
+#define MDIO_DEV_TXPLL 0x808 /* TXPLL register block idx */
+#define MDIO_DEV_TXCTRL0 0x820
+#define MDIO_DEV_SERDESID 0x831
+#define MDIO_DEV_RXCTRL0 0x840
+
+
+/* XgxsBlk1_A Register Offsets */
+#define BLK1_PWR_MGMT0 0x16
+#define BLK1_PWR_MGMT1 0x17
+#define BLK1_PWR_MGMT2 0x18
+#define BLK1_PWR_MGMT3 0x19
+#define BLK1_PWR_MGMT4 0x1A
+
+/* serdes regs (rev < 10) */
+#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */
+#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */
+#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */
+ /* SERDES RX registers */
+#define SERDES_RX_CTRL 1 /* Rx cntrl */
+#define SERDES_RX_TIMER1 2 /* Rx Timer1 */
+#define SERDES_RX_CDR 6 /* CDR */
+#define SERDES_RX_CDRBW 7 /* CDR BW */
+
+ /* SERDES RX control register */
+#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */
+#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */
+
+ /* SERDES PLL registers */
+#define SERDES_PLL_CTRL 1 /* PLL control reg */
+#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */
+
+/* Power management threshold */
+#define PCIE_L0THRESHOLDTIME_MASK 0xFF00 /* bits 0 - 7 */
+#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */
+#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */
+#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */
+#define PCIE_ASPMTIMER_EXTEND 0x01000000 /* > rev7: enable extend ASPM timer */
+
+/* SPROM offsets */
+#define SRSH_ASPM_OFFSET 4 /* word 4 */
+#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */
+#define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */
+#define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */
+#define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */
+#define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */
+#define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */
+#define SRSH_CLKREQ_OFFSET_REV8 52 /* word 52 for srom rev 8 */
+#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */
+#define SRSH_BD_OFFSET 6 /* word 6 */
+#define SRSH_AUTOINIT_OFFSET 18 /* auto initialization enable */
+
+/* Linkcontrol reg offset in PCIE Cap */
+#define PCIE_CAP_LINKCTRL_OFFSET 16 /* linkctrl offset in pcie cap */
+#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */
+#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */
+#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */
+#define PCIE_LINKSPEED_MASK 0xF0000 /* bits 0 - 3 of high word */
+#define PCIE_LINKSPEED_SHIFT 16 /* PCIE_LINKSPEED_SHIFT */
+
+/* Devcontrol reg offset in PCIE Cap */
+#define PCIE_CAP_DEVCTRL_OFFSET 8 /* devctrl offset in pcie cap */
+#define PCIE_CAP_DEVCTRL_MRRS_MASK 0x7000 /* Max read request size mask */
+#define PCIE_CAP_DEVCTRL_MRRS_SHIFT 12 /* Max read request size shift */
+#define PCIE_CAP_DEVCTRL_MRRS_128B 0 /* 128 Byte */
+#define PCIE_CAP_DEVCTRL_MRRS_256B 1 /* 256 Byte */
+#define PCIE_CAP_DEVCTRL_MRRS_512B 2 /* 512 Byte */
+#define PCIE_CAP_DEVCTRL_MRRS_1024B 3 /* 1024 Byte */
+#define PCIE_CAP_DEVCTRL_MPS_MASK 0x00e0 /* Max payload size mask */
+#define PCIE_CAP_DEVCTRL_MPS_SHIFT 5 /* Max payload size shift */
+#define PCIE_CAP_DEVCTRL_MPS_128B 0 /* 128 Byte */
+#define PCIE_CAP_DEVCTRL_MPS_256B 1 /* 256 Byte */
+#define PCIE_CAP_DEVCTRL_MPS_512B 2 /* 512 Byte */
+#define PCIE_CAP_DEVCTRL_MPS_1024B 3 /* 1024 Byte */
+
+#define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */
+#define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */
+#define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */
+#define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */
+
+#define PCIE_ASPM_L11_ENAB 8 /* ASPM L1.1 in PML1_sub_control2 */
+#define PCIE_ASPM_L12_ENAB 4 /* ASPM L1.2 in PML1_sub_control2 */
+
+/* Devcontrol2 reg offset in PCIE Cap */
+#define PCIE_CAP_DEVCTRL2_OFFSET 0x28 /* devctrl2 offset in pcie cap */
+#define PCIE_CAP_DEVCTRL2_LTR_ENAB_MASK 0x400 /* Latency Tolerance Reporting Enable */
+#define PCIE_CAP_DEVCTRL2_OBFF_ENAB_SHIFT 13 /* Enable OBFF mechanism, select signaling method */
+#define PCIE_CAP_DEVCTRL2_OBFF_ENAB_MASK 0x6000 /* Enable OBFF mechanism, select signaling method */
+
+/* LTR registers in PCIE Cap */
+#define PCIE_CAP_LTR0_REG_OFFSET 0x798 /* ltr0_reg offset in pcie cap */
+#define PCIE_CAP_LTR1_REG_OFFSET 0x79C /* ltr1_reg offset in pcie cap */
+#define PCIE_CAP_LTR2_REG_OFFSET 0x7A0 /* ltr2_reg offset in pcie cap */
+#define PCIE_CAP_LTR0_REG 0 /* ltr0_reg */
+#define PCIE_CAP_LTR1_REG 1 /* ltr1_reg */
+#define PCIE_CAP_LTR2_REG 2 /* ltr2_reg */
+
+/* Status reg PCIE_PLP_STATUSREG */
+#define PCIE_PLP_POLARITYINV_STAT 0x10
+
+
+/* PCIE BRCM Vendor CAP REVID reg bits */
+#define BRCMCAP_PCIEREV_CT_MASK 0xF00
+#define BRCMCAP_PCIEREV_CT_SHIFT 8
+#define BRCMCAP_PCIEREV_REVID_MASK 0xFF
+#define BRCMCAP_PCIEREV_REVID_SHIFT 0
+
+#define PCIE_REVREG_CT_PCIE1 0
+#define PCIE_REVREG_CT_PCIE2 1
+
+/* PCIE GEN2 specific defines */
+/* PCIE BRCM Vendor Cap offsets w.r.t to vendor cap ptr */
+#define PCIE2R0_BRCMCAP_REVID_OFFSET 4
+#define PCIE2R0_BRCMCAP_BAR0_WIN0_WRAP_OFFSET 8
+#define PCIE2R0_BRCMCAP_BAR0_WIN2_OFFSET 12
+#define PCIE2R0_BRCMCAP_BAR0_WIN2_WRAP_OFFSET 16
+#define PCIE2R0_BRCMCAP_BAR0_WIN_OFFSET 20
+#define PCIE2R0_BRCMCAP_BAR1_WIN_OFFSET 24
+#define PCIE2R0_BRCMCAP_SPROM_CTRL_OFFSET 28
+#define PCIE2R0_BRCMCAP_BAR2_WIN_OFFSET 32
+#define PCIE2R0_BRCMCAP_INTSTATUS_OFFSET 36
+#define PCIE2R0_BRCMCAP_INTMASK_OFFSET 40
+#define PCIE2R0_BRCMCAP_PCIE2SB_MB_OFFSET 44
+#define PCIE2R0_BRCMCAP_BPADDR_OFFSET 48
+#define PCIE2R0_BRCMCAP_BPDATA_OFFSET 52
+#define PCIE2R0_BRCMCAP_CLKCTLSTS_OFFSET 56
+
+/* definition of configuration space registers of PCIe gen2
+ * http://hwnbu-twiki.sj.broadcom.com/twiki/pub/Mwgroup/CurrentPcieGen2ProgramGuide/pcie_ep.htm
+ */
+#define PCIECFGREG_PML1_SUB_CTRL1 0x248
+#define PCI_PM_L1_2_ENA_MASK 0x00000001 /* PCI-PM L1.2 Enabled */
+#define PCI_PM_L1_1_ENA_MASK 0x00000002 /* PCI-PM L1.1 Enabled */
+#define ASPM_L1_2_ENA_MASK 0x00000004 /* ASPM L1.2 Enabled */
+#define ASPM_L1_1_ENA_MASK 0x00000008 /* ASPM L1.1 Enabled */
+
+#define PCIECFGREG_PDL_CTRL1 0x1004
+#define PCIECFGREG_REG_PHY_CTL7 0x181c
+/* PCIe gen2 mailbox interrupt masks */
+#define I_MB 0x3
+#define I_BIT0 0x1
+#define I_BIT1 0x2
+
+/* PCIE gen2 config regs */
+#define PCIIntstatus 0x090
+#define PCIIntmask 0x094
+#define PCISBMbx 0x98
+
+/* enumeration Core regs */
+#define PCIH2D_MailBox 0x140
+#define PCID2H_MailBox 0x148
+#define PCIMailBoxInt 0x48
+#define PCIMailBoxMask 0x4C
+
+#define I_F0_B0 (0x1 << 8) /* Mail box interrupt Function 0 interrupt, bit 0 */
+#define I_F0_B1 (0x1 << 9) /* Mail box interrupt Function 0 interrupt, bit 1 */
+
+#define PCIECFGREG_DEVCONTROL 0xB4
+
+/* SROM hardware region */
+#define SROM_OFFSET_BAR1_CTRL 52
+
+#define BAR1_ENC_SIZE_MASK 0x000e
+#define BAR1_ENC_SIZE_SHIFT 1
+
+#define BAR1_ENC_SIZE_1M 0
+#define BAR1_ENC_SIZE_2M 1
+#define BAR1_ENC_SIZE_4M 2
+
+#define PCIEGEN2_CAP_DEVSTSCTRL2_OFFSET 0xD4
+#define PCIEGEN2_CAP_DEVSTSCTRL2_LTRENAB 0x400
+
+/*
+ * Latency Tolerance Reporting (LTR) states
+ * Active has the least tolerant latency requirement
+ * Sleep is most tolerant
+ */
+#define LTR_ACTIVE 2
+#define LTR_ACTIVE_IDLE 1
+#define LTR_SLEEP 0
+
+
+/* pwrinstatus, pwrintmask regs */
+#define PCIEGEN2_PWRINT_D0_STATE_SHIFT 0
+#define PCIEGEN2_PWRINT_D1_STATE_SHIFT 1
+#define PCIEGEN2_PWRINT_D2_STATE_SHIFT 2
+#define PCIEGEN2_PWRINT_D3_STATE_SHIFT 3
+#define PCIEGEN2_PWRINT_L0_LINK_SHIFT 4
+#define PCIEGEN2_PWRINT_L0s_LINK_SHIFT 5
+#define PCIEGEN2_PWRINT_L1_LINK_SHIFT 6
+#define PCIEGEN2_PWRINT_L2_L3_LINK_SHIFT 7
+#define PCIEGEN2_PWRINT_OBFF_CHANGE_SHIFT 8
+
+#define PCIEGEN2_PWRINT_D0_STATE_MASK (1 << PCIEGEN2_PWRINT_D0_STATE_SHIFT)
+#define PCIEGEN2_PWRINT_D1_STATE_MASK (1 << PCIEGEN2_PWRINT_D1_STATE_SHIFT)
+#define PCIEGEN2_PWRINT_D2_STATE_MASK (1 << PCIEGEN2_PWRINT_D2_STATE_SHIFT)
+#define PCIEGEN2_PWRINT_D3_STATE_MASK (1 << PCIEGEN2_PWRINT_D3_STATE_SHIFT)
+#define PCIEGEN2_PWRINT_L0_LINK_MASK (1 << PCIEGEN2_PWRINT_L0_LINK_SHIFT)
+#define PCIEGEN2_PWRINT_L0s_LINK_MASK (1 << PCIEGEN2_PWRINT_L0s_LINK_SHIFT)
+#define PCIEGEN2_PWRINT_L1_LINK_MASK (1 << PCIEGEN2_PWRINT_L1_LINK_SHIFT)
+#define PCIEGEN2_PWRINT_L2_L3_LINK_MASK (1 << PCIEGEN2_PWRINT_L2_L3_LINK_SHIFT)
+#define PCIEGEN2_PWRINT_OBFF_CHANGE_MASK (1 << PCIEGEN2_PWRINT_OBFF_CHANGE_SHIFT)
+
+/* sbtopcie mail box */
+#define SBTOPCIE_MB_FUNC0_SHIFT 8
+#define SBTOPCIE_MB_FUNC1_SHIFT 10
+#define SBTOPCIE_MB_FUNC2_SHIFT 12
+#define SBTOPCIE_MB_FUNC3_SHIFT 14
+
+#endif /* _PCIE_CORE_H */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11.h b/drivers/net/wireless/bcmdhd/include/proto/802.11.h
new file mode 100644
index 000000000000..823ebe06a290
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/802.11.h
@@ -0,0 +1,3803 @@
+/*
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * Fundamental types and constants relating to 802.11
+ *
+ * $Id: 802.11.h 444070 2013-12-18 13:20:12Z $
+ */
+
+#ifndef _802_11_H_
+#define _802_11_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#ifndef _NET_ETHERNET_H_
+#include <proto/ethernet.h>
+#endif
+
+#include <proto/wpa.h>
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */
+
+/* Generic 802.11 frame constants */
+#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */
+#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */
+#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */
+#define DOT11_FCS_LEN 4 /* d11 FCS length */
+#define DOT11_ICV_LEN 4 /* d11 ICV length */
+#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */
+#define DOT11_QOS_LEN 2 /* d11 QoS length */
+#define DOT11_HTC_LEN 4 /* d11 HT Control field length */
+
+#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */
+#define DOT11_IV_LEN 4 /* d11 IV length */
+#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */
+#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */
+#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */
+#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */
+
+/* Includes MIC */
+#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */
+/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */
+#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \
+ DOT11_QOS_LEN + \
+ DOT11_IV_AES_CCM_LEN + \
+ DOT11_MAX_MPDU_BODY_LEN + \
+ DOT11_ICV_LEN + \
+ DOT11_FCS_LEN) /* d11 max MPDU length */
+
+#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */
+
+/* dot11RTSThreshold */
+#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */
+#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */
+
+/* dot11FragmentationThreshold */
+#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */
+#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength
+ * of the attached PHY
+ */
+#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */
+
+/* dot11BeaconPeriod */
+#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */
+#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */
+
+/* dot11DTIMPeriod */
+#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */
+#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */
+
+/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */
+#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */
+#define DOT11_OUI_LEN 3 /* d11 OUI length */
+BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header {
+ uint8 dsap; /* always 0xAA */
+ uint8 ssap; /* always 0xAA */
+ uint8 ctl; /* always 0x03 */
+ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00
+ * Bridge-Tunnel: 0x00 0x00 0xF8
+ */
+ uint16 type; /* ethertype */
+} BWL_POST_PACKED_STRUCT;
+
+/* RFC1042 header used by 802.11 per 802.1H */
+#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */
+
+/* Generic 802.11 MAC header */
+/*
+ * N.B.: This struct reflects the full 4 address 802.11 MAC header.
+ * The fields are defined such that the shorter 1, 2, and 3
+ * address headers just use the first k fields.
+ */
+BWL_PRE_PACKED_STRUCT struct dot11_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr a1; /* address 1 */
+ struct ether_addr a2; /* address 2 */
+ struct ether_addr a3; /* address 3 */
+ uint16 seq; /* sequence control */
+ struct ether_addr a4; /* address 4 */
+} BWL_POST_PACKED_STRUCT;
+
+/* Control frames */
+
+BWL_PRE_PACKED_STRUCT struct dot11_rts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_RTS_LEN 16 /* d11 RTS frame length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_cts_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CTS_LEN 10 /* d11 CTS frame length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_ack_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACK_LEN 10 /* d11 ACK frame length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* AID */
+ struct ether_addr bssid; /* receiver address, STA in AP */
+ struct ether_addr ta; /* transmitter address */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr bssid; /* transmitter address, STA in AP */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */
+
+/* RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling
+* category+OUI+vendor specific content ( this can be variable)
+*/
+BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific {
+ uint8 category;
+ uint8 OUI[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 data[1040];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t;
+
+/* generic vender specific action frame with variable length */
+BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr {
+ uint8 category;
+ uint8 OUI[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t;
+
+#define DOT11_ACTION_VS_HDR_LEN 6
+
+#define BCM_ACTION_OUI_BYTE0 0x00
+#define BCM_ACTION_OUI_BYTE1 0x90
+#define BCM_ACTION_OUI_BYTE2 0x4c
+
+/* BA/BAR Control parameters */
+#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */
+#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */
+#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */
+
+#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */
+#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */
+
+#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */
+#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */
+
+#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */
+#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */
+
+/* control frame header (BA/BAR) */
+BWL_PRE_PACKED_STRUCT struct dot11_ctl_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr ra; /* receiver address */
+ struct ether_addr ta; /* transmitter address */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */
+
+/* BAR frame payload */
+BWL_PRE_PACKED_STRUCT struct dot11_bar {
+ uint16 bar_control; /* BAR Control */
+ uint16 seqnum; /* Starting Sequence control */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BAR_LEN 4 /* BAR frame payload length */
+
+#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */
+#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */
+/* BA frame payload */
+BWL_PRE_PACKED_STRUCT struct dot11_ba {
+ uint16 ba_control; /* BA Control */
+ uint16 seqnum; /* Starting Sequence control */
+ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BA_LEN 4 /* BA frame payload len (wo bitmap) */
+
+/* Management frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_management_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr da; /* receiver address */
+ struct ether_addr sa; /* transmitter address */
+ struct ether_addr bssid; /* BSS ID */
+ uint16 seq; /* sequence control */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */
+
+/* Management frame payloads */
+
+BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb {
+ uint32 timestamp[2];
+ uint16 beacon_interval;
+ uint16 capability;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BCN_PRB_LEN 12 /* 802.11 beacon/probe frame fixed length */
+#define DOT11_BCN_PRB_FIXED_LEN 12 /* 802.11 beacon/probe frame fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_auth {
+ uint16 alg; /* algorithm */
+ uint16 seq; /* sequence control */
+ uint16 status; /* status code */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge IE */
+
+BWL_PRE_PACKED_STRUCT struct dot11_assoc_req {
+ uint16 capability; /* capability information */
+ uint16 listen; /* listen interval */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */
+
+BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req {
+ uint16 capability; /* capability information */
+ uint16 listen; /* listen interval */
+ struct ether_addr ap; /* Current AP address */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */
+
+BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp {
+ uint16 capability; /* capability information */
+ uint16 status; /* status code */
+ uint16 aid; /* association ID */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ASSOC_RESP_FIXED_LEN 6 /* length of assoc resp frame without info elts */
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_measure {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width {
+ uint8 category;
+ uint8 action;
+ uint8 ch_width;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops {
+ uint8 category;
+ uint8 action;
+ uint8 control;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query {
+ uint8 category;
+ uint8 action;
+ uint16 id;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_vht_oper_mode {
+ uint8 category;
+ uint8 action;
+ uint8 mode;
+} BWL_POST_PACKED_STRUCT;
+
+#define SM_PWRSAVE_ENABLE 1
+#define SM_PWRSAVE_MODE 2
+
+/* ************* 802.11h related definitions. ************* */
+BWL_PRE_PACKED_STRUCT struct dot11_power_cnst {
+ uint8 id;
+ uint8 len;
+ uint8 power;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_power_cnst dot11_power_cnst_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_power_cap {
+ uint8 min;
+ uint8 max;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_power_cap dot11_power_cap_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep {
+ uint8 id;
+ uint8 len;
+ uint8 tx_pwr;
+ uint8 margin;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tpc_rep dot11_tpc_rep_t;
+#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */
+
+BWL_PRE_PACKED_STRUCT struct dot11_supp_channels {
+ uint8 id;
+ uint8 len;
+ uint8 first_channel;
+ uint8 num_channels;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_supp_channels dot11_supp_channels_t;
+
+/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband
+ * offset for 40MHz operation. The possible 3 values are:
+ * 1 = above control channel
+ * 3 = below control channel
+ * 0 = no extension channel
+ */
+BWL_PRE_PACKED_STRUCT struct dot11_extch {
+ uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */
+ uint8 len; /* IE length */
+ uint8 extch;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extch dot11_extch_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3];
+ uint8 type; /* type inidicates what follows */
+ uint8 extch;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t;
+
+#define BRCM_EXTCH_IE_LEN 5
+#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */
+#define DOT11_EXTCH_IE_LEN 1
+#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */
+#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */
+#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */
+#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr {
+ uint8 category;
+ uint8 action;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACTION_FRMHDR_LEN 2
+
+/* CSA IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch {
+ uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */
+ uint8 len; /* length of IE */
+ uint8 mode; /* mode 0 or 1 */
+ uint8 channel; /* channel switch to */
+ uint8 count; /* number of beacons before switching */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_channel_switch dot11_chan_switch_ie_t;
+
+#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */
+/* CSA mode - 802.11h-2003 $7.3.2.20 */
+#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */
+#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel {
+ uint8 category;
+ uint8 action;
+ dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */
+ dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_csa_body {
+ uint8 mode; /* mode 0 or 1 */
+ uint8 reg; /* regulatory class */
+ uint8 channel; /* channel switch to */
+ uint8 count; /* number of beacons before switching */
+} BWL_POST_PACKED_STRUCT;
+
+/* 11n Extended Channel Switch IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_ext_csa {
+ uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */
+ uint8 len; /* length of IE */
+ struct dot11_csa_body b; /* body of the ie */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ext_csa dot11_ext_csa_ie_t;
+#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa {
+ uint8 category;
+ uint8 action;
+ dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa {
+ uint8 category;
+ uint8 action;
+ struct dot11_csa_body b; /* body of the ie */
+} BWL_POST_PACKED_STRUCT;
+
+/* Wide Bandwidth Channel Switch IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_wide_bw_channel_switch {
+ uint8 id; /* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
+ uint8 len; /* length of IE */
+ uint8 channel_width; /* new channel width */
+ uint8 center_frequency_segment_0; /* center frequency segment 0 */
+ uint8 center_frequency_segment_1; /* center frequency segment 1 */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wide_bw_channel_switch dot11_wide_bw_chan_switch_ie_t;
+
+#define DOT11_WIDE_BW_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */
+
+/* Channel Switch Wrapper IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch_wrapper {
+ uint8 id; /* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
+ uint8 len; /* length of IE */
+ dot11_wide_bw_chan_switch_ie_t wb_chan_switch_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_channel_switch_wrapper dot11_chan_switch_wrapper_ie_t;
+
+/* VHT Transmit Power Envelope IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_vht_transmit_power_envelope {
+ uint8 id; /* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
+ uint8 len; /* length of IE */
+ uint8 transmit_power_info;
+ uint8 local_max_transmit_power_20;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_vht_transmit_power_envelope dot11_vht_transmit_power_envelope_ie_t;
+
+/* vht transmit power envelope IE length depends on channel width */
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_40MHZ 1
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_80MHZ 2
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_160MHZ 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_coex {
+ uint8 id;
+ uint8 len;
+ uint8 info;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_coex dot11_obss_coex_t;
+#define DOT11_OBSS_COEXINFO_LEN 1 /* length of OBSS Coexistence INFO IE */
+
+#define DOT11_OBSS_COEX_INFO_REQ 0x01
+#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02
+#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist {
+ uint8 id;
+ uint8 len;
+ uint8 regclass;
+ uint8 chanlist[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_chanlist dot11_obss_chanlist_t;
+#define DOT11_OBSS_CHANLIST_FIXED_LEN 1 /* fixed length of regclass */
+
+BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie {
+ uint8 id;
+ uint8 len;
+ uint8 cap[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extcap_ie dot11_extcap_ie_t;
+
+#define DOT11_EXTCAP_LEN_MAX 8
+
+#define DOT11_EXTCAP_LEN_COEX 1
+#define DOT11_EXTCAP_LEN_BT 3
+#define DOT11_EXTCAP_LEN_IW 4
+#define DOT11_EXTCAP_LEN_SI 6
+
+#define DOT11_EXTCAP_LEN_TDLS 5
+#define DOT11_11AC_EXTCAP_LEN_TDLS 8
+
+#define DOT11_EXTCAP_LEN_FMS 2
+#define DOT11_EXTCAP_LEN_PROXY_ARP 2
+#define DOT11_EXTCAP_LEN_TFS 3
+#define DOT11_EXTCAP_LEN_WNM_SLEEP 3
+#define DOT11_EXTCAP_LEN_TIMBC 3
+#define DOT11_EXTCAP_LEN_BSSTRANS 3
+#define DOT11_EXTCAP_LEN_DMS 4
+#define DOT11_EXTCAP_LEN_WNM_NOTIFICATION 6
+#define DOT11_EXTCAP_LEN_TDLS_WBW 8
+#define DOT11_EXTCAP_LEN_OPMODE_NOTIFICATION 8
+
+BWL_PRE_PACKED_STRUCT struct dot11_extcap {
+ uint8 extcap[DOT11_EXTCAP_LEN_MAX];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extcap dot11_extcap_t;
+
+/* TDLS Capabilities */
+#define DOT11_TDLS_CAP_TDLS 37 /* TDLS support */
+#define DOT11_TDLS_CAP_PU_BUFFER_STA 28 /* TDLS Peer U-APSD buffer STA support */
+#define DOT11_TDLS_CAP_PEER_PSM 20 /* TDLS Peer PSM support */
+#define DOT11_TDLS_CAP_CH_SW 30 /* TDLS Channel switch */
+#define DOT11_TDLS_CAP_PROH 38 /* TDLS prohibited */
+#define DOT11_TDLS_CAP_CH_SW_PROH 39 /* TDLS Channel switch prohibited */
+#define DOT11_TDLS_CAP_TDLS_WIDER_BW 61 /* TDLS Wider Band-Width */
+
+#define TDLS_CAP_MAX_BIT 39 /* TDLS max bit defined in ext cap */
+
+/* 802.11h/802.11k Measurement Request/Report IEs */
+/* Measurement Type field */
+#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */
+#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */
+#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement RPI type */
+#define DOT11_MEASURE_TYPE_CHLOAD 3 /* d11 measurement Channel Load type */
+#define DOT11_MEASURE_TYPE_NOISE 4 /* d11 measurement Noise Histogram type */
+#define DOT11_MEASURE_TYPE_BEACON 5 /* d11 measurement Beacon type */
+#define DOT11_MEASURE_TYPE_FRAME 6 /* d11 measurement Frame type */
+#define DOT11_MEASURE_TYPE_STAT 7 /* d11 measurement STA Statistics type */
+#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */
+#define DOT11_MEASURE_TYPE_TXSTREAM 9 /* d11 measurement TX Stream type */
+#define DOT11_MEASURE_TYPE_PAUSE 255 /* d11 measurement pause type */
+
+/* Measurement Request Modes */
+#define DOT11_MEASURE_MODE_PARALLEL (1<<0) /* d11 measurement parallel */
+#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */
+#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */
+#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */
+#define DOT11_MEASURE_MODE_DUR (1<<4) /* d11 measurement dur mandatory */
+/* Measurement Report Modes */
+#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */
+#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */
+#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */
+/* Basic Measurement Map bits */
+#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */
+#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */
+#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */
+#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */
+#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_req {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_req dot11_meas_req_t;
+#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */
+/* length of Measure Request IE data not including variable len */
+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_rep {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ BWL_PRE_PACKED_STRUCT union
+ {
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+ } BWL_POST_PACKED_STRUCT basic;
+ uint8 data[1];
+ } BWL_POST_PACKED_STRUCT rep;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_rep dot11_meas_rep_t;
+
+/* length of Measure Report IE data not including variable len */
+#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t;
+#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_quiet {
+ uint8 id;
+ uint8 len;
+ uint8 count; /* TBTTs until beacon interval in quiet starts */
+ uint8 period; /* Beacon intervals between periodic quiet periods ? */
+ uint16 duration; /* Length of quiet period, in TU's */
+ uint16 offset; /* TU's offset from TBTT in Count field */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_quiet dot11_quiet_t;
+
+BWL_PRE_PACKED_STRUCT struct chan_map_tuple {
+ uint8 channel;
+ uint8 map;
+} BWL_POST_PACKED_STRUCT;
+typedef struct chan_map_tuple chan_map_tuple_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs {
+ uint8 id;
+ uint8 len;
+ uint8 eaddr[ETHER_ADDR_LEN];
+ uint8 interval;
+ chan_map_tuple_t map[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ibss_dfs dot11_ibss_dfs_t;
+
+/* WME Elements */
+#define WME_OUI "\x00\x50\xf2" /* WME OUI */
+#define WME_OUI_LEN 3
+#define WME_OUI_TYPE 2 /* WME type */
+#define WME_TYPE 2 /* WME type, deprecated */
+#define WME_SUBTYPE_IE 0 /* Information Element */
+#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */
+#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */
+#define WME_VER 1 /* WME version */
+
+/* WME Access Category Indices (ACIs) */
+#define AC_BE 0 /* Best Effort */
+#define AC_BK 1 /* Background */
+#define AC_VI 2 /* Video */
+#define AC_VO 3 /* Voice */
+#define AC_COUNT 4 /* number of ACs */
+
+typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */
+
+#define AC_BITMAP_NONE 0x0 /* No ACs */
+#define AC_BITMAP_ALL 0xf /* All ACs */
+#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0)
+#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac))))
+#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac))))
+
+/* WME Information Element (IE) */
+BWL_PRE_PACKED_STRUCT struct wme_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+} BWL_POST_PACKED_STRUCT;
+typedef struct wme_ie wme_ie_t;
+#define WME_IE_LEN 7 /* WME IE length */
+
+BWL_PRE_PACKED_STRUCT struct edcf_acparam {
+ uint8 ACI;
+ uint8 ECW;
+ uint16 TXOP; /* stored in network order (ls octet first) */
+} BWL_POST_PACKED_STRUCT;
+typedef struct edcf_acparam edcf_acparam_t;
+
+/* WME Parameter Element (PE) */
+BWL_PRE_PACKED_STRUCT struct wme_param_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+ uint8 rsvd;
+ edcf_acparam_t acparam[AC_COUNT];
+} BWL_POST_PACKED_STRUCT;
+typedef struct wme_param_ie wme_param_ie_t;
+#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */
+
+/* QoS Info field for IE as sent from AP */
+#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */
+#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */
+#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */
+#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */
+
+/* QoS Info field for IE as sent from STA */
+#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */
+#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */
+#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */
+#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */
+#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */
+#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */
+#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */
+#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */
+#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */
+#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */
+#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */
+#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */
+
+/* ACI */
+#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */
+#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */
+#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */
+#define EDCF_ACM_MASK 0x10 /* ACM mask */
+#define EDCF_ACI_MASK 0x60 /* ACI mask */
+#define EDCF_ACI_SHIFT 5 /* ACI shift */
+#define EDCF_AIFSN_SHIFT 12 /* 4 MSB(0xFFF) in ifs_ctl for AC idx */
+
+/* ECW */
+#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */
+#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */
+#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1)
+#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */
+#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */
+#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */
+
+/* TXOP */
+#define EDCF_TXOP_MIN 0 /* TXOP minimum value */
+#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */
+#define EDCF_TXOP2USEC(txop) ((txop) << 5)
+
+/* Default BE ACI value for non-WME connection STA */
+#define NON_EDCF_AC_BE_ACI_STA 0x02
+
+/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */
+#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */
+#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */
+#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */
+#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */
+#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */
+#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */
+#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */
+#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */
+#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */
+#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */
+#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */
+#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */
+
+/* Default EDCF parameters that AP uses; WMM draft Table 14 */
+#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */
+#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */
+#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */
+#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */
+#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */
+#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */
+#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */
+#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */
+#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */
+#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */
+#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */
+#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */
+
+/* EDCA Parameter IE */
+BWL_PRE_PACKED_STRUCT struct edca_param_ie {
+ uint8 qosinfo;
+ uint8 rsvd;
+ edcf_acparam_t acparam[AC_COUNT];
+} BWL_POST_PACKED_STRUCT;
+typedef struct edca_param_ie edca_param_ie_t;
+#define EDCA_PARAM_IE_LEN 18 /* EDCA Parameter IE length */
+
+/* QoS Capability IE */
+BWL_PRE_PACKED_STRUCT struct qos_cap_ie {
+ uint8 qosinfo;
+} BWL_POST_PACKED_STRUCT;
+typedef struct qos_cap_ie qos_cap_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie {
+ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */
+ uint8 length;
+ uint16 station_count; /* total number of STAs associated */
+ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */
+ uint16 aac; /* available admission capacity */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t;
+#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */
+
+/* nom_msdu_size */
+#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */
+#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */
+
+/* surplus_bandwidth */
+/* Represented as 3 bits of integer, binary point, 13 bits fraction */
+#define INTEGER_SHIFT 13 /* integer shift */
+#define FRACTION_MASK 0x1FFF /* fraction mask */
+
+/* Management Notification Frame */
+BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
+ uint8 category; /* DOT11_ACTION_NOTIFICATION */
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */
+
+/* Timeout Interval IE */
+BWL_PRE_PACKED_STRUCT struct ti_ie {
+ uint8 ti_type;
+ uint32 ti_val;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ti_ie ti_ie_t;
+#define TI_TYPE_REASSOC_DEADLINE 1
+#define TI_TYPE_KEY_LIFETIME 2
+
+/* WME Action Codes */
+#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */
+#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */
+#define WME_DELTS_REQUEST 2 /* WME DELTS request */
+
+/* WME Setup Response Status Codes */
+#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */
+#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */
+#define WME_ADMISSION_REFUSED 3 /* WME admission refused */
+
+/* Macro to take a pointer to a beacon or probe response
+ * body and return the char* pointer to the SSID info element
+ */
+#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN)
+
+/* Authentication frame payload constants */
+#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */
+#define DOT11_SHARED_KEY 1 /* d11 shared authentication */
+#define DOT11_FAST_BSS 2 /* d11 fast bss authentication */
+#define DOT11_CHALLENGE_LEN 128 /* d11 challenge text length */
+
+/* Frame control macros */
+#define FC_PVER_MASK 0x3 /* PVER mask */
+#define FC_PVER_SHIFT 0 /* PVER shift */
+#define FC_TYPE_MASK 0xC /* type mask */
+#define FC_TYPE_SHIFT 2 /* type shift */
+#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */
+#define FC_SUBTYPE_SHIFT 4 /* subtype shift */
+#define FC_TODS 0x100 /* to DS */
+#define FC_TODS_SHIFT 8 /* to DS shift */
+#define FC_FROMDS 0x200 /* from DS */
+#define FC_FROMDS_SHIFT 9 /* from DS shift */
+#define FC_MOREFRAG 0x400 /* more frag. */
+#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */
+#define FC_RETRY 0x800 /* retry */
+#define FC_RETRY_SHIFT 11 /* retry shift */
+#define FC_PM 0x1000 /* PM */
+#define FC_PM_SHIFT 12 /* PM shift */
+#define FC_MOREDATA 0x2000 /* more data */
+#define FC_MOREDATA_SHIFT 13 /* more data shift */
+#define FC_WEP 0x4000 /* WEP */
+#define FC_WEP_SHIFT 14 /* WEP shift */
+#define FC_ORDER 0x8000 /* order */
+#define FC_ORDER_SHIFT 15 /* order shift */
+
+/* sequence control macros */
+#define SEQNUM_SHIFT 4 /* seq. number shift */
+#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */
+#define FRAGNUM_MASK 0xF /* frag. number mask */
+
+/* Frame Control type/subtype defs */
+
+/* FC Types */
+#define FC_TYPE_MNG 0 /* management type */
+#define FC_TYPE_CTL 1 /* control type */
+#define FC_TYPE_DATA 2 /* data type */
+
+/* Management Subtypes */
+#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */
+#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */
+#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */
+#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */
+#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */
+#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */
+#define FC_SUBTYPE_BEACON 8 /* beacon */
+#define FC_SUBTYPE_ATIM 9 /* ATIM */
+#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */
+#define FC_SUBTYPE_AUTH 11 /* authentication */
+#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */
+#define FC_SUBTYPE_ACTION 13 /* action */
+#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */
+
+/* Control Subtypes */
+#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */
+#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */
+#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */
+#define FC_SUBTYPE_PS_POLL 10 /* PS poll */
+#define FC_SUBTYPE_RTS 11 /* RTS */
+#define FC_SUBTYPE_CTS 12 /* CTS */
+#define FC_SUBTYPE_ACK 13 /* ACK */
+#define FC_SUBTYPE_CF_END 14 /* CF-END */
+#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */
+
+/* Data Subtypes */
+#define FC_SUBTYPE_DATA 0 /* Data */
+#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */
+#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */
+#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */
+#define FC_SUBTYPE_NULL 4 /* Null */
+#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */
+#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */
+#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */
+#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */
+#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */
+#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */
+#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */
+#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */
+#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */
+#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */
+
+/* Data Subtype Groups */
+#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0)
+#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0)
+#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0)
+#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0)
+#define FC_SUBTYPE_ANY_PSPOLL(s) (((s) & 10) != 0)
+
+/* Type/Subtype Combos */
+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */
+
+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */
+
+#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */
+#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */
+
+#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */
+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */
+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */
+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */
+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */
+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */
+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */
+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */
+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */
+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */
+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */
+#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */
+
+#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */
+#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */
+#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */
+#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */
+#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */
+#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */
+#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */
+#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */
+#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */
+
+#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */
+#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */
+#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */
+#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */
+#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */
+
+/* QoS Control Field */
+
+/* 802.1D Priority */
+#define QOS_PRIO_SHIFT 0 /* QoS priority shift */
+#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */
+#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */
+
+/* Traffic Identifier */
+#define QOS_TID_SHIFT 0 /* QoS TID shift */
+#define QOS_TID_MASK 0x000f /* QoS TID mask */
+#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */
+
+/* End of Service Period (U-APSD) */
+#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */
+#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */
+#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */
+
+/* Ack Policy */
+#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */
+#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */
+#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */
+#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */
+#define QOS_ACK_SHIFT 5 /* QoS ACK shift */
+#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */
+#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */
+
+/* A-MSDU flag */
+#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */
+#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */
+
+/* Management Frames */
+
+/* Management Frame Constants */
+
+/* Fixed fields */
+#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */
+#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */
+#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */
+#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */
+#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */
+#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */
+#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */
+#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */
+#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */
+#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */
+
+/* DUR/ID field in assoc resp is 0xc000 | AID */
+#define DOT11_AID_MASK 0x3fff /* d11 AID mask */
+
+/* Reason Codes */
+#define DOT11_RC_RESERVED 0 /* d11 RC reserved */
+#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */
+#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */
+#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station
+ * is leaving (or has left) IBSS or ESS
+ */
+#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */
+#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle
+ * all currently associated stations
+ */
+#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from
+ * nonauthenticated station
+ */
+#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from
+ * nonassociated station
+ */
+#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is
+ * leaving (or has left) BSS
+ */
+#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is not
+ * authenticated with responding station
+ */
+#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */
+#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */
+/* 12 is unused */
+
+/* 32-39 are QSTA specific reasons added in 11e */
+#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */
+#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */
+#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */
+#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */
+#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */
+#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */
+#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */
+#define DOT11_RC_TIMEOUT 39 /* timeout */
+
+#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */
+
+#define DOT11_RC_TDLS_PEER_UNREACH 25
+#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26
+
+/* Status Codes */
+#define DOT11_SC_SUCCESS 0 /* Successful */
+#define DOT11_SC_FAILURE 1 /* Unspecified failure */
+#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 /* TDLS wakeup schedule rejected but alternative */
+ /* schedule provided */
+#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 /* TDLS wakeup schedule rejected */
+#define DOT11_SC_TDLS_SEC_DISABLED 5 /* TDLS Security disabled */
+#define DOT11_SC_LIFETIME_REJ 6 /* Unacceptable lifetime */
+#define DOT11_SC_NOT_SAME_BSS 7 /* Not in same BSS */
+#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested
+ * capabilities in the Capability
+ * Information field
+ */
+#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability
+ * to confirm that association exists
+ */
+#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason
+ * outside the scope of this standard
+ */
+#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support
+ * the specified authentication
+ * algorithm
+ */
+#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame
+ * with authentication transaction
+ * sequence number out of expected
+ * sequence
+ */
+#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of
+ * challenge failure
+ */
+#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout
+ * waiting for next frame in sequence
+ */
+#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is
+ * unable to handle additional
+ * associated stations
+ */
+#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting
+ * station not supporting all of the
+ * data rates in the BSSBasicRateSet
+ * parameter
+ */
+#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting
+ * station not supporting the Short
+ * Preamble option
+ */
+#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting
+ * station not supporting the PBCC
+ * Modulation option
+ */
+#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting
+ * station not supporting the Channel
+ * Agility option
+ */
+#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum
+ * Management capability is required.
+ */
+#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info
+ * in the Power Cap element is
+ * unacceptable.
+ */
+#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info
+ * in the Supported Channel element is
+ * unacceptable
+ */
+#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting
+ * station not supporting the Short Slot
+ * Time option
+ */
+#define DOT11_SC_ASSOC_DSSSOFDM_REQUIRED 26 /* Association denied because requesting station
+ * does not support the DSSS-OFDM option
+ */
+#define DOT11_SC_ASSOC_HT_REQUIRED 27 /* Association denied because the requesting
+ * station does not support HT features
+ */
+#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28 /* Association denied due to AP
+ * being unable to reach the R0 Key Holder
+ */
+#define DOT11_SC_ASSOC_TRY_LATER 30 /* Association denied temporarily, try again later
+ */
+#define DOT11_SC_ASSOC_MFP_VIOLATION 31 /* Association denied due to Robust Management
+ * frame policy violation
+ */
+
+#define DOT11_SC_DECLINED 37 /* request declined */
+#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */
+#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 /* invalid pairwise cipher */
+#define DOT11_SC_INVALID_AKMP 43 /* Association denied due to invalid AKMP */
+#define DOT11_SC_INVALID_RSNIE_CAP 45 /* invalid RSN IE capabilities */
+#define DOT11_SC_DLS_NOT_ALLOWED 48 /* DLS is not allowed in the BSS by policy */
+#define DOT11_SC_INVALID_PMKID 53 /* Association denied due to invalid PMKID */
+#define DOT11_SC_INVALID_MDID 54 /* Association denied due to invalid MDID */
+#define DOT11_SC_INVALID_FTIE 55 /* Association denied due to invalid FTIE */
+
+#define DOT11_SC_ADV_PROTO_NOT_SUPPORTED 59 /* ad proto not supported */
+#define DOT11_SC_NO_OUTSTAND_REQ 60 /* no outstanding req */
+#define DOT11_SC_RSP_NOT_RX_FROM_SERVER 61 /* no response from server */
+#define DOT11_SC_TIMEOUT 62 /* timeout */
+#define DOT11_SC_QUERY_RSP_TOO_LARGE 63 /* query rsp too large */
+#define DOT11_SC_SERVER_UNREACHABLE 65 /* server unreachable */
+
+#define DOT11_SC_UNEXP_MSG 70 /* Unexpected message */
+#define DOT11_SC_INVALID_SNONCE 71 /* Invalid SNonce */
+#define DOT11_SC_INVALID_RSNIE 72 /* Invalid contents of RSNIE */
+#define DOT11_SC_ASSOC_VHT_REQUIRED 104 /* Association denied because the requesting
+ * station does not support VHT features.
+ */
+
+#define DOT11_SC_TRANSMIT_FAILURE 79 /* transmission failure */
+
+/* Info Elts, length of INFORMATION portion of Info Elts */
+#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */
+#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */
+
+/* TIM Info element has 3 bytes fixed info in INFORMATION field,
+ * followed by 1 to 251 bytes of Partial Virtual Bitmap
+ */
+#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */
+#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */
+#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */
+#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */
+#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */
+
+/* TLV defines */
+#define TLV_TAG_OFF 0 /* tag offset */
+#define TLV_LEN_OFF 1 /* length offset */
+#define TLV_HDR_LEN 2 /* header length */
+#define TLV_BODY_OFF 2 /* body offset */
+#define TLV_BODY_LEN_MAX 255 /* max body length */
+
+/* Management Frame Information Element IDs */
+#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */
+#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */
+#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */
+#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */
+#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */
+#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */
+#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */
+#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */
+#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */
+#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */
+#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */
+#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */
+#define DOT11_MNG_EDCA_PARAM_ID 12 /* 11E EDCA Parameter id */
+#define DOT11_MNG_TSPEC_ID 13 /* d11 management TSPEC id */
+#define DOT11_MNG_TCLAS_ID 14 /* d11 management TCLAS id */
+#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */
+#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */
+#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */
+#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */
+#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */
+#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */
+#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */
+#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
+#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */
+#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */
+#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */
+#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */
+#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */
+#define DOT11_MNG_TCLAS_PROC_ID 44 /* d11 management TCLAS processing id */
+#define DOT11_MNG_HT_CAP 45 /* d11 mgmt HT cap id */
+#define DOT11_MNG_QOS_CAP_ID 46 /* 11E QoS Capability id */
+#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */
+#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */
+#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */
+#define DOT11_MNG_AP_CHREP_ID 51 /* 11k AP Channel report id */
+#define DOT11_MNG_NEIGHBOR_REP_ID 52 /* 11k & 11v Neighbor report id */
+#define DOT11_MNG_RCPI_ID 53 /* 11k RCPI */
+#define DOT11_MNG_MDIE_ID 54 /* 11r Mobility domain id */
+#define DOT11_MNG_FTIE_ID 55 /* 11r Fast Bss Transition id */
+#define DOT11_MNG_FT_TI_ID 56 /* 11r Timeout Interval id */
+#define DOT11_MNG_RDE_ID 57 /* 11r RIC Data Element id */
+#define DOT11_MNG_REGCLASS_ID 59 /* d11 management regulatory class id */
+#define DOT11_MNG_EXT_CSA_ID 60 /* d11 Extended CSA */
+#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */
+#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */
+#define DOT11_MNG_BSS_AVR_ACCESS_DELAY_ID 63 /* 11k bss average access delay */
+#define DOT11_MNG_ANTENNA_ID 64 /* 11k antenna id */
+#define DOT11_MNG_RSNI_ID 65 /* 11k RSNI id */
+#define DOT11_MNG_MEASUREMENT_PILOT_TX_ID 66 /* 11k measurement pilot tx info id */
+#define DOT11_MNG_BSS_AVAL_ADMISSION_CAP_ID 67 /* 11k bss aval admission cap id */
+#define DOT11_MNG_BSS_AC_ACCESS_DELAY_ID 68 /* 11k bss AC access delay id */
+#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */
+#define DOT11_MNG_TIME_ADVERTISE_ID 69 /* 11p time advertisement */
+#define DOT11_MNG_RRM_CAP_ID 70 /* 11k radio measurement capability */
+#define DOT11_MNG_MULTIPLE_BSSID_ID 71 /* 11k multiple BSSID id */
+#define DOT11_MNG_HT_BSS_COEXINFO_ID 72 /* d11 mgmt OBSS Coexistence INFO */
+#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 /* d11 mgmt OBSS Intolerant Channel list */
+#define DOT11_MNG_HT_OBSS_ID 74 /* d11 mgmt OBSS HT info */
+#define DOT11_MNG_MMIE_ID 76 /* d11 mgmt MIC IE */
+#define DOT11_MNG_FMS_DESCR_ID 86 /* 11v FMS descriptor */
+#define DOT11_MNG_FMS_REQ_ID 87 /* 11v FMS request id */
+#define DOT11_MNG_FMS_RESP_ID 88 /* 11v FMS response id */
+#define DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID 90 /* 11v bss max idle id */
+#define DOT11_MNG_TFS_REQUEST_ID 91 /* 11v tfs request id */
+#define DOT11_MNG_TFS_RESPONSE_ID 92 /* 11v tfs response id */
+#define DOT11_MNG_WNM_SLEEP_MODE_ID 93 /* 11v wnm-sleep mode id */
+#define DOT11_MNG_TIMBC_REQ_ID 94 /* 11v TIM broadcast request id */
+#define DOT11_MNG_TIMBC_RESP_ID 95 /* 11v TIM broadcast response id */
+#define DOT11_MNG_CHANNEL_USAGE 97 /* 11v channel usage */
+#define DOT11_MNG_TIME_ZONE_ID 98 /* 11v time zone */
+#define DOT11_MNG_DMS_REQUEST_ID 99 /* 11v dms request id */
+#define DOT11_MNG_DMS_RESPONSE_ID 100 /* 11v dms response id */
+#define DOT11_MNG_LINK_IDENTIFIER_ID 101 /* 11z TDLS Link Identifier IE */
+#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 /* 11z TDLS Wakeup Schedule IE */
+#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 /* 11z TDLS Channel Switch Timing IE */
+#define DOT11_MNG_PTI_CONTROL_ID 105 /* 11z TDLS PTI Control IE */
+#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 /* 11z TDLS PU Buffer Status IE */
+#define DOT11_MNG_INTERWORKING_ID 107 /* 11u interworking */
+#define DOT11_MNG_ADVERTISEMENT_ID 108 /* 11u advertisement protocol */
+#define DOT11_MNG_EXP_BW_REQ_ID 109 /* 11u expedited bandwith request */
+#define DOT11_MNG_QOS_MAP_ID 110 /* 11u QoS map set */
+#define DOT11_MNG_ROAM_CONSORT_ID 111 /* 11u roaming consortium */
+#define DOT11_MNG_EMERGCY_ALERT_ID 112 /* 11u emergency alert identifier */
+#define DOT11_MNG_EXT_CAP_ID 127 /* d11 mgmt ext capability */
+#define DOT11_MNG_VHT_CAP_ID 191 /* d11 mgmt VHT cap id */
+#define DOT11_MNG_VHT_OPERATION_ID 192 /* d11 mgmt VHT op id */
+#define DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID 194 /* Wide BW Channel Switch IE */
+#define DOT11_MNG_VHT_TRANSMIT_POWER_ENVELOPE_ID 195 /* VHT transmit Power Envelope IE */
+#define DOT11_MNG_CHANNEL_SWITCH_WRAPPER_ID 196 /* Channel Switch Wrapper IE */
+#define DOT11_MNG_AID_ID 197 /* Association ID IE */
+#define DOT11_MNG_OPER_MODE_NOTIF_ID 199 /* d11 mgmt VHT oper mode notif */
+
+
+#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */
+#define DOT11_MNG_PROPR_ID 221
+/* should start using this one instead of above two */
+#define DOT11_MNG_VS_ID 221 /* d11 management Vendor Specific IE */
+
+/* Rate Defines */
+
+/* Valid rates for the Supported Rates and Extended Supported Rates IEs.
+ * Encoding is the rate in 500kbps units, rouding up for fractional values.
+ * 802.11-2012, section 6.5.5.2, DATA_RATE parameter enumerates all the values.
+ * The rate values cover DSSS, HR/DSSS, ERP, and OFDM phy rates.
+ * The defines below do not cover the rates specific to 10MHz, {3, 4.5, 27},
+ * and 5MHz, {1.5, 2.25, 3, 4.5, 13.5}, which are not supported by Broadcom devices.
+ */
+
+#define DOT11_RATE_1M 2 /* 1 Mbps in 500kbps units */
+#define DOT11_RATE_2M 4 /* 2 Mbps in 500kbps units */
+#define DOT11_RATE_5M5 11 /* 5.5 Mbps in 500kbps units */
+#define DOT11_RATE_11M 22 /* 11 Mbps in 500kbps units */
+#define DOT11_RATE_6M 12 /* 6 Mbps in 500kbps units */
+#define DOT11_RATE_9M 18 /* 9 Mbps in 500kbps units */
+#define DOT11_RATE_12M 24 /* 12 Mbps in 500kbps units */
+#define DOT11_RATE_18M 36 /* 18 Mbps in 500kbps units */
+#define DOT11_RATE_24M 48 /* 24 Mbps in 500kbps units */
+#define DOT11_RATE_36M 72 /* 36 Mbps in 500kbps units */
+#define DOT11_RATE_48M 96 /* 48 Mbps in 500kbps units */
+#define DOT11_RATE_54M 108 /* 54 Mbps in 500kbps units */
+#define DOT11_RATE_MAX 108 /* highest rate (54 Mbps) in 500kbps units */
+
+/* Supported Rates and Extended Supported Rates IEs
+ * The supported rates octets are defined a the MSB indicatin a Basic Rate
+ * and bits 0-6 as the rate value
+ */
+#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */
+#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */
+
+/* BSS Membership Selector parameters
+ * 802.11-2012 and 802.11ac_D4.0 sec 8.4.2.3
+ * These selector values are advertised in Supported Rates and Extended Supported Rates IEs
+ * in the supported rates list with the Basic rate bit set.
+ * Constants below include the basic bit.
+ */
+#define DOT11_BSS_MEMBERSHIP_HT 0xFF /* Basic 0x80 + 127, HT Required to join */
+#define DOT11_BSS_MEMBERSHIP_VHT 0xFE /* Basic 0x80 + 126, VHT Required to join */
+
+/* ERP info element bit values */
+#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */
+#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present
+ *in the BSS
+ */
+#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for
+ *ERP-OFDM frames
+ */
+#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed,
+ * 1 == not allowed
+ */
+/* TS Delay element offset & size */
+#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */
+#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */
+
+/* Capability Information Field */
+#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */
+#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */
+#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */
+#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */
+#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */
+#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */
+#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */
+#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */
+#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */
+#define DOT11_CAP_QOS 0x0200 /* d11 cap. qos */
+#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */
+#define DOT11_CAP_APSD 0x0800 /* d11 cap. apsd */
+#define DOT11_CAP_RRM 0x1000 /* d11 cap. 11k radio measurement */
+#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */
+#define DOT11_CAP_DELAY_BA 0x4000 /* d11 cap. delayed block ack */
+#define DOT11_CAP_IMMEDIATE_BA 0x8000 /* d11 cap. immediate block ack */
+
+/* Extended capabilities IE bitfields */
+/* 20/40 BSS Coexistence Management support bit position */
+#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0
+/* Extended Channel Switching support bit position */
+#define DOT11_EXT_CAP_EXT_CHAN_SWITCHING 2
+/* scheduled PSMP support bit position */
+#define DOT11_EXT_CAP_SPSMP 6
+/* Flexible Multicast Service */
+#define DOT11_EXT_CAP_FMS 11
+/* proxy ARP service support bit position */
+#define DOT11_EXT_CAP_PROXY_ARP 12
+/* Traffic Filter Service */
+#define DOT11_EXT_CAP_TFS 16
+/* WNM-Sleep Mode */
+#define DOT11_EXT_CAP_WNM_SLEEP 17
+/* TIM Broadcast service */
+#define DOT11_EXT_CAP_TIMBC 18
+/* BSS Transition Management support bit position */
+#define DOT11_EXT_CAP_BSSTRANS_MGMT 19
+/* Direct Multicast Service */
+#define DOT11_EXT_CAP_DMS 26
+/* Interworking support bit position */
+#define DOT11_EXT_CAP_IW 31
+/* service Interval granularity bit position and mask */
+#define DOT11_EXT_CAP_SI 41
+#define DOT11_EXT_CAP_SI_MASK 0x0E
+/* WNM notification */
+#define DOT11_EXT_CAP_WNM_NOTIF 46
+/* Operating mode notification - VHT (11ac D3.0 - 8.4.2.29) */
+#define DOT11_EXT_CAP_OPER_MODE_NOTIF 62
+
+/* VHT Operating mode bit fields - (11ac D3.0 - 8.4.1.50) */
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT 0
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_MASK 0x3
+#define DOT11_OPER_MODE_RXNSS_SHIFT 4
+#define DOT11_OPER_MODE_RXNSS_MASK 0x70
+#define DOT11_OPER_MODE_RXNSS_TYPE_SHIFT 7
+#define DOT11_OPER_MODE_RXNSS_TYPE_MASK 0x80
+
+#define DOT11_OPER_MODE(type, nss, chanw) (\
+ ((type) << DOT11_OPER_MODE_RXNSS_TYPE_SHIFT &\
+ DOT11_OPER_MODE_RXNSS_TYPE_MASK) |\
+ (((nss) - 1) << DOT11_OPER_MODE_RXNSS_SHIFT & DOT11_OPER_MODE_RXNSS_MASK) |\
+ ((chanw) << DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT &\
+ DOT11_OPER_MODE_CHANNEL_WIDTH_MASK))
+
+#define DOT11_OPER_MODE_CHANNEL_WIDTH(mode) \
+ (((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK)\
+ >> DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT)
+#define DOT11_OPER_MODE_RXNSS(mode) \
+ ((((mode) & DOT11_OPER_MODE_RXNSS_MASK) \
+ >> DOT11_OPER_MODE_RXNSS_SHIFT) + 1)
+#define DOT11_OPER_MODE_RXNSS_TYPE(mode) \
+ (((mode) & DOT11_OPER_MODE_RXNSS_TYPE_MASK)\
+ >> DOT11_OPER_MODE_RXNSS_TYPE_SHIFT)
+
+#define DOT11_OPER_MODE_20MHZ 0
+#define DOT11_OPER_MODE_40MHZ 1
+#define DOT11_OPER_MODE_80MHZ 2
+#define DOT11_OPER_MODE_160MHZ 3
+#define DOT11_OPER_MODE_8080MHZ 3
+
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_20MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_20MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_40MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_40MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_80MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_80MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_160MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_160MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_8080MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_8080MHZ)
+
+/* Operating mode information element 802.11ac D3.0 - 8.4.2.168 */
+BWL_PRE_PACKED_STRUCT struct dot11_oper_mode_notif_ie {
+ uint8 mode;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_oper_mode_notif_ie dot11_oper_mode_notif_ie_t;
+
+#define DOT11_OPER_MODE_NOTIF_IE_LEN 1
+
+/* Extended Capability Information Field */
+#define DOT11_OBSS_COEX_MNG_SUPPORT 0x01 /* 20/40 BSS Coexistence Management support */
+
+/*
+ * Action Frame Constants
+ */
+#define DOT11_ACTION_HDR_LEN 2 /* action frame category + action field */
+#define DOT11_ACTION_CAT_OFF 0 /* category offset */
+#define DOT11_ACTION_ACT_OFF 1 /* action offset */
+
+/* Action Category field (sec 8.4.1.11) */
+#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* category error mask */
+#define DOT11_ACTION_CAT_MASK 0x7F /* category mask */
+#define DOT11_ACTION_CAT_SPECT_MNG 0 /* category spectrum management */
+#define DOT11_ACTION_CAT_QOS 1 /* category QoS */
+#define DOT11_ACTION_CAT_DLS 2 /* category DLS */
+#define DOT11_ACTION_CAT_BLOCKACK 3 /* category block ack */
+#define DOT11_ACTION_CAT_PUBLIC 4 /* category public */
+#define DOT11_ACTION_CAT_RRM 5 /* category radio measurements */
+#define DOT11_ACTION_CAT_FBT 6 /* category fast bss transition */
+#define DOT11_ACTION_CAT_HT 7 /* category for HT */
+#define DOT11_ACTION_CAT_SA_QUERY 8 /* security association query */
+#define DOT11_ACTION_CAT_PDPA 9 /* protected dual of public action */
+#define DOT11_ACTION_CAT_WNM 10 /* category for WNM */
+#define DOT11_ACTION_CAT_UWNM 11 /* category for Unprotected WNM */
+#define DOT11_ACTION_NOTIFICATION 17
+#define DOT11_ACTION_CAT_VHT 21 /* VHT action */
+#define DOT11_ACTION_CAT_VSP 126 /* protected vendor specific */
+#define DOT11_ACTION_CAT_VS 127 /* category Vendor Specific */
+
+/* Spectrum Management Action IDs (sec 7.4.1) */
+#define DOT11_SM_ACTION_M_REQ 0 /* d11 action measurement request */
+#define DOT11_SM_ACTION_M_REP 1 /* d11 action measurement response */
+#define DOT11_SM_ACTION_TPC_REQ 2 /* d11 action TPC request */
+#define DOT11_SM_ACTION_TPC_REP 3 /* d11 action TPC response */
+#define DOT11_SM_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */
+#define DOT11_SM_ACTION_EXT_CSA 5 /* d11 extened CSA for 11n */
+
+/* HT action ids */
+#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */
+#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */
+
+/* Public action ids */
+#define DOT11_PUB_ACTION_BSS_COEX_MNG 0 /* 20/40 Coexistence Management action id */
+#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */
+#define DOT11_PUB_ACTION_GAS_CB_REQ 12 /* GAS Comeback Request */
+
+/* Block Ack action types */
+#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */
+#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */
+#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */
+
+/* ADDBA action parameters */
+#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 /* AMSDU supported under BA */
+#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */
+#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */
+#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */
+#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */
+#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */
+#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */
+
+#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */
+#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */
+
+/* Fast Transition action types */
+#define DOT11_FT_ACTION_FT_RESERVED 0
+#define DOT11_FT_ACTION_FT_REQ 1 /* FBT request - for over-the-DS FBT */
+#define DOT11_FT_ACTION_FT_RES 2 /* FBT response - for over-the-DS FBT */
+#define DOT11_FT_ACTION_FT_CON 3 /* FBT confirm - for OTDS with RRP */
+#define DOT11_FT_ACTION_FT_ACK 4 /* FBT ack */
+
+/* DLS action types */
+#define DOT11_DLS_ACTION_REQ 0 /* DLS Request */
+#define DOT11_DLS_ACTION_RESP 1 /* DLS Response */
+#define DOT11_DLS_ACTION_TD 2 /* DLS Teardown */
+
+/* Wireless Network Management (WNM) action types */
+#define DOT11_WNM_ACTION_EVENT_REQ 0
+#define DOT11_WNM_ACTION_EVENT_REP 1
+#define DOT11_WNM_ACTION_DIAG_REQ 2
+#define DOT11_WNM_ACTION_DIAG_REP 3
+#define DOT11_WNM_ACTION_LOC_CFG_REQ 4
+#define DOT11_WNM_ACTION_LOC_RFG_RESP 5
+#define DOT11_WNM_ACTION_BSSTRANS_QUERY 6
+#define DOT11_WNM_ACTION_BSSTRANS_REQ 7
+#define DOT11_WNM_ACTION_BSSTRANS_RESP 8
+#define DOT11_WNM_ACTION_FMS_REQ 9
+#define DOT11_WNM_ACTION_FMS_RESP 10
+#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11
+#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12
+#define DOT11_WNM_ACTION_TFS_REQ 13
+#define DOT11_WNM_ACTION_TFS_RESP 14
+#define DOT11_WNM_ACTION_TFS_NOTIFY_REQ 15
+#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16
+#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17
+#define DOT11_WNM_ACTION_TIMBC_REQ 18
+#define DOT11_WNM_ACTION_TIMBC_RESP 19
+#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20
+#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21
+#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22
+#define DOT11_WNM_ACTION_DMS_REQ 23
+#define DOT11_WNM_ACTION_DMS_RESP 24
+#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25
+#define DOT11_WNM_ACTION_NOTFCTN_REQ 26
+#define DOT11_WNM_ACTION_NOTFCTN_RESP 27
+#define DOT11_WNM_ACTION_TFS_NOTIFY_RESP 28
+
+/* Unprotected Wireless Network Management (WNM) action types */
+#define DOT11_UWNM_ACTION_TIM 0
+#define DOT11_UWNM_ACTION_TIMING_MEASUREMENT 1
+
+#define DOT11_MNG_COUNTRY_ID_LEN 3
+
+/* VHT category action types - 802.11ac D3.0 - 8.5.23.1 */
+#define DOT11_VHT_ACTION_CBF 0 /* Compressed Beamforming */
+#define DOT11_VHT_ACTION_GID_MGMT 1 /* Group ID Management */
+#define DOT11_VHT_ACTION_OPER_MODE_NOTIF 2 /* Operating mode notif'n */
+
+/* DLS Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_dls_req {
+ uint8 category; /* category of action frame (2) */
+ uint8 action; /* DLS action: req (0) */
+ struct ether_addr da; /* destination address */
+ struct ether_addr sa; /* source address */
+ uint16 cap; /* capability */
+ uint16 timeout; /* timeout value */
+ uint8 data[1]; /* IE:support rate, extend support rate, HT cap */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dls_req dot11_dls_req_t;
+#define DOT11_DLS_REQ_LEN 18 /* Fixed length */
+
+/* DLS response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_dls_resp {
+ uint8 category; /* category of action frame (2) */
+ uint8 action; /* DLS action: req (0) */
+ uint16 status; /* status code field */
+ struct ether_addr da; /* destination address */
+ struct ether_addr sa; /* source address */
+ uint8 data[1]; /* optional: capability, rate ... */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dls_resp dot11_dls_resp_t;
+#define DOT11_DLS_RESP_LEN 16 /* Fixed length */
+
+
+/* ************* 802.11v related definitions. ************* */
+
+/* BSS Management Transition Query frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_query {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: trans_query (6) */
+ uint8 token; /* dialog token */
+ uint8 reason; /* transition query reason */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bsstrans_query dot11_bsstrans_query_t;
+#define DOT11_BSSTRANS_QUERY_LEN 4 /* Fixed length */
+
+/* BSS Management Transition Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_req {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: trans_req (7) */
+ uint8 token; /* dialog token */
+ uint8 reqmode; /* transition request mode */
+ uint16 disassoc_tmr; /* disassociation timer */
+ uint8 validity_intrvl; /* validity interval */
+ uint8 data[1]; /* optional: BSS term duration, ... */
+ /* ...session info URL, candidate list */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bsstrans_req dot11_bsstrans_req_t;
+#define DOT11_BSSTRANS_REQ_LEN 7 /* Fixed length */
+
+/* BSS Mgmt Transition Request Mode Field - 802.11v */
+#define DOT11_BSSTRANS_REQMODE_PREF_LIST_INCL 0x01
+#define DOT11_BSSTRANS_REQMODE_ABRIDGED 0x02
+#define DOT11_BSSTRANS_REQMODE_DISASSOC_IMMINENT 0x04
+#define DOT11_BSSTRANS_REQMODE_BSS_TERM_INCL 0x08
+#define DOT11_BSSTRANS_REQMODE_ESS_DISASSOC_IMNT 0x10
+
+/* BSS Management transition response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_resp {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: trans_resp (8) */
+ uint8 token; /* dialog token */
+ uint8 status; /* transition status */
+ uint8 term_delay; /* validity interval */
+ uint8 data[1]; /* optional: BSSID target, candidate list */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bsstrans_resp dot11_bsstrans_resp_t;
+#define DOT11_BSSTRANS_RESP_LEN 5 /* Fixed length */
+
+/* BSS Mgmt Transition Response Status Field */
+#define DOT11_BSSTRANS_RESP_STATUS_ACCEPT 0
+#define DOT11_BSSTRANS_RESP_STATUS_REJECT 1
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_INSUFF_BCN 2
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_INSUFF_CAP 3
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_TERM_UNDESIRED 4
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_TERM_DELAY_REQ 5
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_BSS_LIST_PROVIDED 6
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_NO_SUITABLE_BSS 7
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_LEAVING_ESS 8
+
+
+/* BSS Max Idle Period element */
+BWL_PRE_PACKED_STRUCT struct dot11_bss_max_idle_period_ie {
+ uint8 id; /* 90, DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID */
+ uint8 len;
+ uint16 max_idle_period; /* in unit of 1000 TUs */
+ uint8 idle_opt;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_max_idle_period_ie dot11_bss_max_idle_period_ie_t;
+#define DOT11_BSS_MAX_IDLE_PERIOD_IE_LEN 3 /* bss max idle period IE size */
+#define DOT11_BSS_MAX_IDLE_PERIOD_OPT_PROTECTED 1 /* BSS max idle option */
+
+/* TIM Broadcast request element */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_req_ie {
+ uint8 id; /* 94, DOT11_MNG_TIMBC_REQ_ID */
+ uint8 len;
+ uint8 interval; /* in unit of beacon interval */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_req_ie dot11_timbc_req_ie_t;
+#define DOT11_TIMBC_REQ_IE_LEN 1 /* Fixed length */
+
+/* TIM Broadcast request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_req {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: DOT11_WNM_ACTION_TIMBC_REQ(18) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* TIM broadcast request element */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_req dot11_timbc_req_t;
+#define DOT11_TIMBC_REQ_LEN 3 /* Fixed length */
+
+/* TIM Broadcast response element */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp_ie {
+ uint8 id; /* 95, DOT11_MNG_TIM_BROADCAST_RESP_ID */
+ uint8 len;
+ uint8 status; /* status of add request */
+ uint8 interval; /* in unit of beacon interval */
+ int32 offset; /* in unit of ms */
+ uint16 high_rate; /* in unit of 0.5 Mb/s */
+ uint16 low_rate; /* in unit of 0.5 Mb/s */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_resp_ie dot11_timbc_resp_ie_t;
+#define DOT11_TIMBC_DENY_RESP_IE_LEN 1 /* Deny. Fixed length */
+#define DOT11_TIMBC_ACCEPT_RESP_IE_LEN 10 /* Accept. Fixed length */
+
+#define DOT11_TIMBC_STATUS_ACCEPT 0
+#define DOT11_TIMBC_STATUS_ACCEPT_TSTAMP 1
+#define DOT11_TIMBC_STATUS_DENY 2
+#define DOT11_TIMBC_STATUS_OVERRIDDEN 3
+#define DOT11_TIMBC_STATUS_RESERVED 4
+
+/* TIM Broadcast request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* action: DOT11_WNM_ACTION_TIMBC_RESP(19) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* TIM broadcast response element */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_resp dot11_timbc_resp_t;
+#define DOT11_TIMBC_RESP_LEN 3 /* Fixed length */
+
+/* TIM element */
+BWL_PRE_PACKED_STRUCT struct dot11_tim_ie {
+ uint8 id; /* 5, DOT11_MNG_TIM_ID */
+ uint8 len; /* 4 - 255 */
+ uint8 dtim_count; /* DTIM decrementing counter */
+ uint8 dtim_period; /* DTIM period */
+ uint8 bitmap_control; /* AID 0 + bitmap offset */
+ uint8 pvb[1]; /* Partial Virtual Bitmap, variable length */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tim_ie dot11_tim_ie_t;
+#define DOT11_TIM_IE_FIXED_LEN 3 /* Fixed length, without id and len */
+#define DOT11_TIM_IE_FIXED_TOTAL_LEN 5 /* Fixed length, with id and len */
+
+/* TIM Broadcast frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc {
+ uint8 category; /* category of action frame (11) */
+ uint8 action; /* action: TIM (0) */
+ uint8 check_beacon; /* need to check-beacon */
+ uint8 tsf[8]; /* Time Synchronization Function */
+ dot11_tim_ie_t tim_ie; /* TIM element */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc dot11_timbc_t;
+#define DOT11_TIMBC_HDR_LEN (sizeof(dot11_timbc_t) - sizeof(dot11_tim_ie_t))
+#define DOT11_TIMBC_FIXED_LEN (sizeof(dot11_timbc_t) - 1) /* Fixed length */
+#define DOT11_TIMBC_LEN 11 /* Fixed length */
+
+/* TCLAS frame classifier type */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_hdr {
+ uint8 type;
+ uint8 mask;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_hdr dot11_tclas_fc_hdr_t;
+#define DOT11_TCLAS_FC_HDR_LEN 2 /* Fixed length */
+
+#define DOT11_TCLAS_MASK_0 0x1
+#define DOT11_TCLAS_MASK_1 0x2
+#define DOT11_TCLAS_MASK_2 0x4
+#define DOT11_TCLAS_MASK_3 0x8
+#define DOT11_TCLAS_MASK_4 0x10
+#define DOT11_TCLAS_MASK_5 0x20
+#define DOT11_TCLAS_MASK_6 0x40
+#define DOT11_TCLAS_MASK_7 0x80
+
+#define DOT11_TCLAS_FC_0_ETH 0
+#define DOT11_TCLAS_FC_1_IP 1
+#define DOT11_TCLAS_FC_2_8021Q 2
+#define DOT11_TCLAS_FC_3_OFFSET 3
+#define DOT11_TCLAS_FC_4_IP_HIGHER 4
+#define DOT11_TCLAS_FC_5_8021D 5
+
+/* TCLAS frame classifier type 0 parameters for Ethernet */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_0_eth {
+ uint8 type;
+ uint8 mask;
+ uint8 sa[ETHER_ADDR_LEN];
+ uint8 da[ETHER_ADDR_LEN];
+ uint16 eth_type;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_0_eth dot11_tclas_fc_0_eth_t;
+#define DOT11_TCLAS_FC_0_ETH_LEN 16
+
+/* TCLAS frame classifier type 1 parameters for IPV4 */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_1_ipv4 {
+ uint8 type;
+ uint8 mask;
+ uint8 version;
+ uint32 src_ip;
+ uint32 dst_ip;
+ uint16 src_port;
+ uint16 dst_port;
+ uint8 dscp;
+ uint8 protocol;
+ uint8 reserved;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_1_ipv4 dot11_tclas_fc_1_ipv4_t;
+#define DOT11_TCLAS_FC_1_IPV4_LEN 18
+
+/* TCLAS frame classifier type 2 parameters for 802.1Q */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_2_8021q {
+ uint8 type;
+ uint8 mask;
+ uint16 tci;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_2_8021q dot11_tclas_fc_2_8021q_t;
+#define DOT11_TCLAS_FC_2_8021Q_LEN 4
+
+/* TCLAS frame classifier type 3 parameters for filter offset */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_3_filter {
+ uint8 type;
+ uint8 mask;
+ uint16 offset;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_3_filter dot11_tclas_fc_3_filter_t;
+#define DOT11_TCLAS_FC_3_FILTER_LEN 4
+
+/* TCLAS frame classifier type 4 parameters for IPV4 is the same as TCLAS type 1 */
+typedef struct dot11_tclas_fc_1_ipv4 dot11_tclas_fc_4_ipv4_t;
+#define DOT11_TCLAS_FC_4_IPV4_LEN DOT11_TCLAS_FC_1_IPV4_LEN
+
+/* TCLAS frame classifier type 4 parameters for IPV6 */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_4_ipv6 {
+ uint8 type;
+ uint8 mask;
+ uint8 version;
+ uint8 saddr[16];
+ uint8 daddr[16];
+ uint16 src_port;
+ uint16 dst_port;
+ uint8 dscp;
+ uint8 nexthdr;
+ uint8 flow_lbl[3];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_4_ipv6 dot11_tclas_fc_4_ipv6_t;
+#define DOT11_TCLAS_FC_4_IPV6_LEN 44
+
+/* TCLAS frame classifier type 5 parameters for 802.1D */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_5_8021d {
+ uint8 type;
+ uint8 mask;
+ uint8 pcp;
+ uint8 cfi;
+ uint16 vid;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_5_8021d dot11_tclas_fc_5_8021d_t;
+#define DOT11_TCLAS_FC_5_8021D_LEN 6
+
+/* TCLAS frame classifier type parameters */
+BWL_PRE_PACKED_STRUCT union dot11_tclas_fc {
+ uint8 data[1];
+ dot11_tclas_fc_hdr_t hdr;
+ dot11_tclas_fc_0_eth_t t0_eth;
+ dot11_tclas_fc_1_ipv4_t t1_ipv4;
+ dot11_tclas_fc_2_8021q_t t2_8021q;
+ dot11_tclas_fc_3_filter_t t3_filter;
+ dot11_tclas_fc_4_ipv4_t t4_ipv4;
+ dot11_tclas_fc_4_ipv6_t t4_ipv6;
+ dot11_tclas_fc_5_8021d_t t5_8021d;
+} BWL_POST_PACKED_STRUCT;
+typedef union dot11_tclas_fc dot11_tclas_fc_t;
+
+#define DOT11_TCLAS_FC_MIN_LEN 4 /* Classifier Type 2 has the min size */
+#define DOT11_TCLAS_FC_MAX_LEN 254
+
+/* TCLAS element */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_ie {
+ uint8 id; /* 14, DOT11_MNG_TCLAS_ID */
+ uint8 len;
+ uint8 user_priority;
+ dot11_tclas_fc_t fc;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_ie dot11_tclas_ie_t;
+#define DOT11_TCLAS_IE_LEN 3 /* Fixed length, include id and len */
+
+/* TCLAS processing element */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_proc_ie {
+ uint8 id; /* 44, DOT11_MNG_TCLAS_PROC_ID */
+ uint8 len;
+ uint8 process;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_proc_ie dot11_tclas_proc_ie_t;
+#define DOT11_TCLAS_PROC_IE_LEN 3 /* Fixed length, include id and len */
+
+#define DOT11_TCLAS_PROC_MATCHALL 0 /* All high level element need to match */
+#define DOT11_TCLAS_PROC_MATCHONE 1 /* One high level element need to match */
+#define DOT11_TCLAS_PROC_NONMATCH 2 /* Non match to any high level element */
+
+
+/* TSPEC element defined in 802.11 std section 8.4.2.32 - Not supported */
+#define DOT11_TSPEC_IE_LEN 57 /* Fixed length */
+
+/* TFS request element */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_req_ie {
+ uint8 id; /* 91, DOT11_MNG_TFS_REQUEST_ID */
+ uint8 len;
+ uint8 tfs_id;
+ uint8 actcode;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_req_ie dot11_tfs_req_ie_t;
+#define DOT11_TFS_REQ_IE_LEN 2 /* Fixed length, without id and len */
+
+/* TFS request action codes (bitfield) */
+#define DOT11_TFS_ACTCODE_DELETE 1
+#define DOT11_TFS_ACTCODE_NOTIFY 2
+
+/* TFS request subelement IDs */
+#define DOT11_TFS_REQ_TFS_SE_ID 1
+#define DOT11_TFS_REQ_VENDOR_SE_ID 221
+
+/* TFS subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_se {
+ uint8 sub_id;
+ uint8 len;
+ uint8 data[1]; /* TCLAS element(s) + optional TCLAS proc */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_se dot11_tfs_se_t;
+
+
+/* TFS response element */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp_ie {
+ uint8 id; /* 92, DOT11_MNG_TFS_RESPONSE_ID */
+ uint8 len;
+ uint8 tfs_id;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp_ie dot11_tfs_resp_ie_t;
+#define DOT11_TFS_RESP_IE_LEN 1 /* Fixed length, without id and len */
+
+/* TFS response subelement IDs (same subelments, but different IDs than in TFS request */
+#define DOT11_TFS_RESP_TFS_STATUS_SE_ID 1
+#define DOT11_TFS_RESP_TFS_SE_ID 2
+#define DOT11_TFS_RESP_VENDOR_SE_ID 221
+
+/* TFS status subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_status_se {
+ uint8 sub_id; /* 92, DOT11_MNG_TFS_RESPONSE_ID */
+ uint8 len;
+ uint8 resp_st;
+ uint8 data[1]; /* Potential dot11_tfs_se_t included */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_status_se dot11_tfs_status_se_t;
+#define DOT11_TFS_STATUS_SE_LEN 1 /* Fixed length, without id and len */
+
+/* Following Definition should be merged to FMS_TFS macro below */
+/* TFS Response status code. Identical to FMS Element status, without N/A */
+#define DOT11_TFS_STATUS_ACCEPT 0
+#define DOT11_TFS_STATUS_DENY_FORMAT 1
+#define DOT11_TFS_STATUS_DENY_RESOURCE 2
+#define DOT11_TFS_STATUS_DENY_POLICY 4
+#define DOT11_TFS_STATUS_DENY_UNSPECIFIED 5
+#define DOT11_TFS_STATUS_ALTPREF_POLICY 7
+#define DOT11_TFS_STATUS_ALTPREF_TCLAS_UNSUPP 14
+
+/* FMS Element Status and TFS Response Status Definition */
+#define DOT11_FMS_TFS_STATUS_ACCEPT 0
+#define DOT11_FMS_TFS_STATUS_DENY_FORMAT 1
+#define DOT11_FMS_TFS_STATUS_DENY_RESOURCE 2
+#define DOT11_FMS_TFS_STATUS_DENY_MULTIPLE_DI 3
+#define DOT11_FMS_TFS_STATUS_DENY_POLICY 4
+#define DOT11_FMS_TFS_STATUS_DENY_UNSPECIFIED 5
+#define DOT11_FMS_TFS_STATUS_ALT_DIFF_DI 6
+#define DOT11_FMS_TFS_STATUS_ALT_POLICY 7
+#define DOT11_FMS_TFS_STATUS_ALT_CHANGE_DI 8
+#define DOT11_FMS_TFS_STATUS_ALT_MCRATE 9
+#define DOT11_FMS_TFS_STATUS_TERM_POLICY 10
+#define DOT11_FMS_TFS_STATUS_TERM_RESOURCE 11
+#define DOT11_FMS_TFS_STATUS_TERM_HIGHER_PRIO 12
+#define DOT11_FMS_TFS_STATUS_ALT_CHANGE_MDI 13
+#define DOT11_FMS_TFS_STATUS_ALT_TCLAS_UNSUPP 14
+
+/* TFS Management Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_req {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: TFS request (13) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_req dot11_tfs_req_t;
+#define DOT11_TFS_REQ_LEN 3 /* Fixed length */
+
+/* TFS Management Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: TFS request (14) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp dot11_tfs_resp_t;
+#define DOT11_TFS_RESP_LEN 3 /* Fixed length */
+
+/* TFS Management Notify frame request header */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify_req {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: TFS notify request (15) */
+ uint8 tfs_id_cnt; /* TFS IDs count */
+ uint8 tfs_id[1]; /* Array of TFS IDs */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_notify_req dot11_tfs_notify_req_t;
+#define DOT11_TFS_NOTIFY_REQ_LEN 3 /* Fixed length */
+
+/* TFS Management Notify frame response header */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify_resp {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: TFS notify response (28) */
+ uint8 tfs_id_cnt; /* TFS IDs count */
+ uint8 tfs_id[1]; /* Array of TFS IDs */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_notify_resp dot11_tfs_notify_resp_t;
+#define DOT11_TFS_NOTIFY_RESP_LEN 3 /* Fixed length */
+
+
+/* WNM-Sleep Management Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_req {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: wnm-sleep request (16) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_req dot11_wnm_sleep_req_t;
+#define DOT11_WNM_SLEEP_REQ_LEN 3 /* Fixed length */
+
+/* WNM-Sleep Management Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_resp {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: wnm-sleep request (17) */
+ uint8 token; /* dialog token */
+ uint16 key_len; /* key data length */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_resp dot11_wnm_sleep_resp_t;
+#define DOT11_WNM_SLEEP_RESP_LEN 5 /* Fixed length */
+
+#define DOT11_WNM_SLEEP_SUBELEM_ID_GTK 0
+#define DOT11_WNM_SLEEP_SUBELEM_ID_IGTK 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_gtk {
+ uint8 sub_id;
+ uint8 len;
+ uint16 key_info;
+ uint8 key_length;
+ uint8 rsc[8];
+ uint8 key[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_subelem_gtk dot11_wnm_sleep_subelem_gtk_t;
+#define DOT11_WNM_SLEEP_SUBELEM_GTK_FIXED_LEN 11 /* without sub_id, len, and key */
+#define DOT11_WNM_SLEEP_SUBELEM_GTK_MAX_LEN 43 /* without sub_id and len */
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_igtk {
+ uint8 sub_id;
+ uint8 len;
+ uint16 key_id;
+ uint8 pn[6];
+ uint8 key[16];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_subelem_igtk dot11_wnm_sleep_subelem_igtk_t;
+#define DOT11_WNM_SLEEP_SUBELEM_IGTK_LEN 24 /* Fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_ie {
+ uint8 id; /* 93, DOT11_MNG_WNM_SLEEP_MODE_ID */
+ uint8 len;
+ uint8 act_type;
+ uint8 resp_status;
+ uint16 interval;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_ie dot11_wnm_sleep_ie_t;
+#define DOT11_WNM_SLEEP_IE_LEN 4 /* Fixed length */
+
+#define DOT11_WNM_SLEEP_ACT_TYPE_ENTER 0
+#define DOT11_WNM_SLEEP_ACT_TYPE_EXIT 1
+
+#define DOT11_WNM_SLEEP_RESP_ACCEPT 0
+#define DOT11_WNM_SLEEP_RESP_UPDATE 1
+#define DOT11_WNM_SLEEP_RESP_DENY 2
+#define DOT11_WNM_SLEEP_RESP_DENY_TEMP 3
+#define DOT11_WNM_SLEEP_RESP_DENY_KEY 4
+#define DOT11_WNM_SLEEP_RESP_DENY_INUSE 5
+#define DOT11_WNM_SLEEP_RESP_LAST 6
+
+/* DMS Management Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: dms request (23) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req dot11_dms_req_t;
+#define DOT11_DMS_REQ_LEN 3 /* Fixed length */
+
+/* DMS Management Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: dms request (24) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp dot11_dms_resp_t;
+#define DOT11_DMS_RESP_LEN 3 /* Fixed length */
+
+/* DMS request element */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req_ie {
+ uint8 id; /* 99, DOT11_MNG_DMS_REQUEST_ID */
+ uint8 len;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req_ie dot11_dms_req_ie_t;
+#define DOT11_DMS_REQ_IE_LEN 2 /* Fixed length */
+
+/* DMS response element */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_ie {
+ uint8 id; /* 100, DOT11_MNG_DMS_RESPONSE_ID */
+ uint8 len;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp_ie dot11_dms_resp_ie_t;
+#define DOT11_DMS_RESP_IE_LEN 2 /* Fixed length */
+
+/* DMS request descriptor */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req_desc {
+ uint8 dms_id;
+ uint8 len;
+ uint8 type;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req_desc dot11_dms_req_desc_t;
+#define DOT11_DMS_REQ_DESC_LEN 3 /* Fixed length */
+
+#define DOT11_DMS_REQ_TYPE_ADD 0
+#define DOT11_DMS_REQ_TYPE_REMOVE 1
+#define DOT11_DMS_REQ_TYPE_CHANGE 2
+
+/* DMS response status */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_st {
+ uint8 dms_id;
+ uint8 len;
+ uint8 type;
+ uint16 lsc;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp_st dot11_dms_resp_st_t;
+#define DOT11_DMS_RESP_STATUS_LEN 5 /* Fixed length */
+
+#define DOT11_DMS_RESP_TYPE_ACCEPT 0
+#define DOT11_DMS_RESP_TYPE_DENY 1
+#define DOT11_DMS_RESP_TYPE_TERM 2
+
+#define DOT11_DMS_RESP_LSC_UNSUPPORTED 0xFFFF
+
+/* FMS Management Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_req {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: fms request (9) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_req dot11_fms_req_t;
+#define DOT11_FMS_REQ_LEN 3 /* Fixed length */
+
+/* FMS Management Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_resp {
+ uint8 category; /* category of action frame (10) */
+ uint8 action; /* WNM action: fms request (10) */
+ uint8 token; /* dialog token */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_resp dot11_fms_resp_t;
+#define DOT11_FMS_RESP_LEN 3 /* Fixed length */
+
+/* FMS Descriptor element */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_desc {
+ uint8 id;
+ uint8 len;
+ uint8 num_fms_cnt;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_desc dot11_fms_desc_t;
+#define DOT11_FMS_DESC_LEN 1 /* Fixed length */
+
+#define DOT11_FMS_CNTR_MAX 0x8
+#define DOT11_FMS_CNTR_ID_MASK 0x7
+#define DOT11_FMS_CNTR_ID_SHIFT 0x0
+#define DOT11_FMS_CNTR_COUNT_MASK 0xf1
+#define DOT11_FMS_CNTR_SHIFT 0x3
+
+/* FMS request element */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_req_ie {
+ uint8 id;
+ uint8 len;
+ uint8 fms_token; /* token used to identify fms stream set */
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_req_ie dot11_fms_req_ie_t;
+#define DOT11_FMS_REQ_IE_FIX_LEN 1 /* Fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_rate_id_field {
+ uint8 mask;
+ uint8 mcs_idx;
+ uint16 rate;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rate_id_field dot11_rate_id_field_t;
+#define DOT11_RATE_ID_FIELD_MCS_SEL_MASK 0x7
+#define DOT11_RATE_ID_FIELD_MCS_SEL_OFFSET 0
+#define DOT11_RATE_ID_FIELD_RATETYPE_MASK 0x18
+#define DOT11_RATE_ID_FIELD_RATETYPE_OFFSET 3
+#define DOT11_RATE_ID_FIELD_LEN sizeof(dot11_rate_id_field_t)
+
+/* FMS request subelements */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_se {
+ uint8 sub_id;
+ uint8 len;
+ uint8 interval;
+ uint8 max_interval;
+ dot11_rate_id_field_t rate;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_se dot11_fms_se_t;
+#define DOT11_FMS_REQ_SE_LEN 6 /* Fixed length */
+
+#define DOT11_FMS_REQ_SE_ID_FMS 1 /* FMS subelement */
+#define DOT11_FMS_REQ_SE_ID_VS 221 /* Vendor Specific subelement */
+
+/* FMS response element */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_resp_ie {
+ uint8 id;
+ uint8 len;
+ uint8 fms_token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_resp_ie dot11_fms_resp_ie_t;
+#define DOT11_FMS_RESP_IE_FIX_LEN 1 /* Fixed length */
+
+/* FMS status subelements */
+#define DOT11_FMS_STATUS_SE_ID_FMS 1 /* FMS Status */
+#define DOT11_FMS_STATUS_SE_ID_TCLAS 2 /* TCLAS Status */
+#define DOT11_FMS_STATUS_SE_ID_VS 221 /* Vendor Specific subelement */
+
+/* FMS status subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_status_se {
+ uint8 sub_id;
+ uint8 len;
+ uint8 status;
+ uint8 interval;
+ uint8 max_interval;
+ uint8 fmsid;
+ uint8 counter;
+ dot11_rate_id_field_t rate;
+ uint8 mcast_addr[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_status_se dot11_fms_status_se_t;
+#define DOT11_FMS_STATUS_SE_LEN 15 /* Fixed length */
+
+/* TCLAS status subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_status_se {
+ uint8 sub_id;
+ uint8 len;
+ uint8 fmsid;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_status_se dot11_tclas_status_se_t;
+#define DOT11_TCLAS_STATUS_SE_LEN 1 /* Fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_addba_req {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba req */
+ uint8 token; /* identifier */
+ uint16 addba_param_set; /* parameter set */
+ uint16 timeout; /* timeout in seconds */
+ uint16 start_seqnum; /* starting sequence number */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_addba_req dot11_addba_req_t;
+#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */
+
+BWL_PRE_PACKED_STRUCT struct dot11_addba_resp {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba resp */
+ uint8 token; /* identifier */
+ uint16 status; /* status of add request */
+ uint16 addba_param_set; /* negotiated parameter set */
+ uint16 timeout; /* negotiated timeout in seconds */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_addba_resp dot11_addba_resp_t;
+#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */
+
+/* DELBA action parameters */
+#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */
+#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */
+#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */
+#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */
+
+BWL_PRE_PACKED_STRUCT struct dot11_delba {
+ uint8 category; /* category of action frame (3) */
+ uint8 action; /* action: addba req */
+ uint16 delba_param_set; /* paarmeter set */
+ uint16 reason; /* reason for dellba */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_delba dot11_delba_t;
+#define DOT11_DELBA_LEN 6 /* length of delba frame */
+
+/* SA Query action field value */
+#define SA_QUERY_REQUEST 0
+#define SA_QUERY_RESPONSE 1
+
+/* ************* 802.11r related definitions. ************* */
+
+/* Over-the-DS Fast Transition Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_ft_req {
+ uint8 category; /* category of action frame (6) */
+ uint8 action; /* action: ft req */
+ uint8 sta_addr[ETHER_ADDR_LEN];
+ uint8 tgt_ap_addr[ETHER_ADDR_LEN];
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_req dot11_ft_req_t;
+#define DOT11_FT_REQ_FIXED_LEN 14
+
+/* Over-the-DS Fast Transition Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_ft_res {
+ uint8 category; /* category of action frame (6) */
+ uint8 action; /* action: ft resp */
+ uint8 sta_addr[ETHER_ADDR_LEN];
+ uint8 tgt_ap_addr[ETHER_ADDR_LEN];
+ uint16 status; /* status code */
+ uint8 data[1]; /* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_res dot11_ft_res_t;
+#define DOT11_FT_RES_FIXED_LEN 16
+
+/* RDE RIC Data Element. */
+BWL_PRE_PACKED_STRUCT struct dot11_rde_ie {
+ uint8 id; /* 11r, DOT11_MNG_RDE_ID */
+ uint8 length;
+ uint8 rde_id; /* RDE identifier. */
+ uint8 rd_count; /* Resource Descriptor Count. */
+ uint16 status; /* Status Code. */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rde_ie dot11_rde_ie_t;
+
+/* 11r - Size of the RDE (RIC Data Element) IE, including TLV header. */
+#define DOT11_MNG_RDE_IE_LEN sizeof(dot11_rde_ie_t)
+
+
+/* ************* 802.11k related definitions. ************* */
+
+/* Radio measurements enabled capability ie */
+#define DOT11_RRM_CAP_LEN 5 /* length of rrm cap bitmap */
+#define RCPI_IE_LEN 1
+#define RSNI_IE_LEN 1
+BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie {
+ uint8 cap[DOT11_RRM_CAP_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t;
+
+/* Bitmap definitions for cap ie */
+#define DOT11_RRM_CAP_LINK 0
+#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1
+#define DOT11_RRM_CAP_PARALLEL 2
+#define DOT11_RRM_CAP_REPEATED 3
+#define DOT11_RRM_CAP_BCN_PASSIVE 4
+#define DOT11_RRM_CAP_BCN_ACTIVE 5
+#define DOT11_RRM_CAP_BCN_TABLE 6
+#define DOT11_RRM_CAP_BCN_REP_COND 7
+#define DOT11_RRM_CAP_FM 8
+#define DOT11_RRM_CAP_CLM 9
+#define DOT11_RRM_CAP_NHM 10
+#define DOT11_RRM_CAP_SM 11
+#define DOT11_RRM_CAP_LCIM 12
+#define DOT11_RRM_CAP_LCIA 13
+#define DOT11_RRM_CAP_TSCM 14
+#define DOT11_RRM_CAP_TTSCM 15
+#define DOT11_RRM_CAP_AP_CHANREP 16
+#define DOT11_RRM_CAP_RMMIB 17
+/* bit18-bit26, not used for RRM_IOVAR */
+#define DOT11_RRM_CAP_MPTI 27
+#define DOT11_RRM_CAP_NBRTSFO 28
+#define DOT11_RRM_CAP_RCPI 29
+#define DOT11_RRM_CAP_RSNI 30
+#define DOT11_RRM_CAP_BSSAAD 31
+#define DOT11_RRM_CAP_BSSAAC 32
+#define DOT11_RRM_CAP_AI 33
+
+/* Operating Class (formerly "Regulatory Class") definitions */
+#define DOT11_OP_CLASS_NONE 255
+
+BWL_PRE_PACKED_STRUCT struct do11_ap_chrep {
+ uint8 id;
+ uint8 len;
+ uint8 reg;
+ uint8 chanlist[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct do11_ap_chrep dot11_ap_chrep_t;
+
+/* Radio Measurements action ids */
+#define DOT11_RM_ACTION_RM_REQ 0 /* Radio measurement request */
+#define DOT11_RM_ACTION_RM_REP 1 /* Radio measurement report */
+#define DOT11_RM_ACTION_LM_REQ 2 /* Link measurement request */
+#define DOT11_RM_ACTION_LM_REP 3 /* Link measurement report */
+#define DOT11_RM_ACTION_NR_REQ 4 /* Neighbor report request */
+#define DOT11_RM_ACTION_NR_REP 5 /* Neighbor report response */
+
+/* Generic radio measurement action frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_rm_action {
+ uint8 category; /* category of action frame (5) */
+ uint8 action; /* radio measurement action */
+ uint8 token; /* dialog token */
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rm_action dot11_rm_action_t;
+#define DOT11_RM_ACTION_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq {
+ uint8 category; /* category of action frame (5) */
+ uint8 action; /* radio measurement action */
+ uint8 token; /* dialog token */
+ uint16 reps; /* no. of repetitions */
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq dot11_rmreq_t;
+#define DOT11_RMREQ_LEN 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_rm_ie {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rm_ie dot11_rm_ie_t;
+#define DOT11_RM_IE_LEN 5
+
+/* Definitions for "mode" bits in rm req */
+#define DOT11_RMREQ_MODE_PARALLEL 1
+#define DOT11_RMREQ_MODE_ENABLE 2
+#define DOT11_RMREQ_MODE_REQUEST 4
+#define DOT11_RMREQ_MODE_REPORT 8
+#define DOT11_RMREQ_MODE_DURMAND 0x10 /* Duration Mandatory */
+
+/* Definitions for "mode" bits in rm rep */
+#define DOT11_RMREP_MODE_LATE 1
+#define DOT11_RMREP_MODE_INCAPABLE 2
+#define DOT11_RMREP_MODE_REFUSED 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+ uint8 bcn_mode;
+ struct ether_addr bssid;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t;
+#define DOT11_RMREQ_BCN_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 frame_info;
+ uint8 rcpi;
+ uint8 rsni;
+ struct ether_addr bssid;
+ uint8 antenna_id;
+ uint32 parent_tsf;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t;
+#define DOT11_RMREP_BCN_LEN 26
+
+/* Beacon request measurement mode */
+#define DOT11_RMREQ_BCN_PASSIVE 0
+#define DOT11_RMREQ_BCN_ACTIVE 1
+#define DOT11_RMREQ_BCN_TABLE 2
+
+/* Sub-element IDs for Beacon Request */
+#define DOT11_RMREQ_BCN_SSID_ID 0
+#define DOT11_RMREQ_BCN_REPINFO_ID 1
+#define DOT11_RMREQ_BCN_REPDET_ID 2
+#define DOT11_RMREQ_BCN_REQUEST_ID 10
+#define DOT11_RMREQ_BCN_APCHREP_ID DOT11_MNG_AP_CHREP_ID
+
+/* Reporting Detail element definition */
+#define DOT11_RMREQ_BCN_REPDET_FIXED 0 /* Fixed length fields only */
+#define DOT11_RMREQ_BCN_REPDET_REQUEST 1 /* + requested information elems */
+#define DOT11_RMREQ_BCN_REPDET_ALL 2 /* All fields */
+
+/* Sub-element IDs for Beacon Report */
+#define DOT11_RMREP_BCN_FRM_BODY 1
+
+/* Sub-element IDs for Frame Report */
+#define DOT11_RMREP_FRAME_COUNT_REPORT 1
+
+/* Channel load request */
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_chanload {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_chanload dot11_rmreq_chanload_t;
+#define DOT11_RMREQ_CHANLOAD_LEN 11
+
+/* Channel load report */
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_chanload {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 channel_load;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_chanload dot11_rmrep_chanload_t;
+#define DOT11_RMREP_CHANLOAD_LEN 13
+
+/* Noise histogram request */
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_noise {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_noise dot11_rmreq_noise_t;
+#define DOT11_RMREQ_NOISE_LEN 11
+
+/* Noise histogram report */
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_noise {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 antid;
+ uint8 anpi;
+ uint8 ipi0_dens;
+ uint8 ipi1_dens;
+ uint8 ipi2_dens;
+ uint8 ipi3_dens;
+ uint8 ipi4_dens;
+ uint8 ipi5_dens;
+ uint8 ipi6_dens;
+ uint8 ipi7_dens;
+ uint8 ipi8_dens;
+ uint8 ipi9_dens;
+ uint8 ipi10_dens;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_noise dot11_rmrep_noise_t;
+#define DOT11_RMREP_NOISE_LEN 25
+
+/* Frame request */
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_frame {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+ uint8 req_type;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_frame dot11_rmreq_frame_t;
+#define DOT11_RMREQ_FRAME_LEN 18
+
+/* Frame report */
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frame {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_frame dot11_rmrep_frame_t;
+#define DOT11_RMREP_FRAME_LEN 12
+
+/* Frame report entry */
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frmentry {
+ struct ether_addr ta;
+ struct ether_addr bssid;
+ uint8 phy_type;
+ uint8 avg_rcpi;
+ uint8 last_rsni;
+ uint8 last_rcpi;
+ uint8 ant_id;
+ uint16 frame_cnt;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_frmentry dot11_rmrep_frmentry_t;
+#define DOT11_RMREP_FRMENTRY_LEN 19
+
+/* STA statistics request */
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_stat {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ struct ether_addr peer;
+ uint16 interval;
+ uint16 duration;
+ uint8 group_id;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_stat dot11_rmreq_stat_t;
+#define DOT11_RMREQ_STAT_LEN 16
+
+/* STA statistics report */
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_stat {
+ uint16 duration;
+ uint8 group_id;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_stat dot11_rmrep_stat_t;
+
+/* Transmit stream/category measurement request */
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_tx_stream {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint16 interval;
+ uint16 duration;
+ struct ether_addr peer;
+ uint8 traffic_id;
+ uint8 bin0_range;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_tx_stream dot11_rmreq_tx_stream_t;
+
+/* Transmit stream/category measurement report */
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_tx_stream {
+ uint32 starttime[2];
+ uint16 duration;
+ struct ether_addr peer;
+ uint8 traffic_id;
+ uint8 reason;
+ uint32 txmsdu_cnt;
+ uint32 msdu_discarded_cnt;
+ uint32 msdufailed_cnt;
+ uint32 msduretry_cnt;
+ uint32 cfpolls_lost_cnt;
+ uint32 avrqueue_delay;
+ uint32 avrtx_delay;
+ uint8 bin0_range;
+ uint32 bin0;
+ uint32 bin1;
+ uint32 bin2;
+ uint32 bin3;
+ uint32 bin4;
+ uint32 bin5;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_tx_stream dot11_rmrep_tx_stream_t;
+
+/* Measurement pause request */
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_pause_time {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint16 pause_time;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_pause_time dot11_rmreq_pause_time_t;
+
+
+/* Neighbor Report subelements ID (11k & 11v) */
+#define DOT11_NGBR_TSF_INFO_SE_ID 1
+#define DOT11_NGBR_CCS_SE_ID 2
+#define DOT11_NGBR_BSSTRANS_PREF_SE_ID 3
+#define DOT11_NGBR_BSS_TERM_DUR_SE_ID 4
+#define DOT11_NGBR_BEARING_SE_ID 5
+
+/* Neighbor Report, BSS Transition Candidate Preference subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_ngbr_bsstrans_pref_se {
+ uint8 sub_id;
+ uint8 len;
+ uint8 preference;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ngbr_bsstrans_pref_se dot11_ngbr_bsstrans_pref_se_t;
+#define DOT11_NGBR_BSSTRANS_PREF_SE_LEN 1
+
+/* Neighbor Report, BSS Termination Duration subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_ngbr_bss_term_dur_se {
+ uint8 sub_id;
+ uint8 len;
+ uint8 tsf[8];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ngbr_bss_term_dur_se dot11_ngbr_bss_term_dur_se_t;
+#define DOT11_NGBR_BSS_TERM_DUR_SE_LEN 10
+
+/* Neighbor Report BSSID Information Field */
+#define DOT11_NGBR_BI_REACHABILTY_UNKN 0x0002
+#define DOT11_NGBR_BI_REACHABILTY 0x0003
+#define DOT11_NGBR_BI_SEC 0x0004
+#define DOT11_NGBR_BI_KEY_SCOPE 0x0008
+#define DOT11_NGBR_BI_CAP 0x03f0
+#define DOT11_NGBR_BI_CAP_SPEC_MGMT 0x0010
+#define DOT11_NGBR_BI_CAP_QOS 0x0020
+#define DOT11_NGBR_BI_CAP_APSD 0x0040
+#define DOT11_NGBR_BI_CAP_RDIO_MSMT 0x0080
+#define DOT11_NGBR_BI_CAP_DEL_BA 0x0100
+#define DOT11_NGBR_BI_CAP_IMM_BA 0x0200
+#define DOT11_NGBR_BI_MOBILITY 0x0400
+#define DOT11_NGBR_BI_HT 0x0800
+
+/* Neighbor Report element (11k & 11v) */
+BWL_PRE_PACKED_STRUCT struct dot11_neighbor_rep_ie {
+ uint8 id;
+ uint8 len;
+ struct ether_addr bssid;
+ uint32 bssid_info;
+ uint8 reg; /* Operating class */
+ uint8 channel;
+ uint8 phytype;
+ uint8 data[1]; /* Variable size subelements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_neighbor_rep_ie dot11_neighbor_rep_ie_t;
+#define DOT11_NEIGHBOR_REP_IE_FIXED_LEN 13
+
+
+/* MLME Enumerations */
+#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */
+#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */
+#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */
+#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */
+#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */
+
+/* Link Measurement */
+BWL_PRE_PACKED_STRUCT struct dot11_lmreq {
+ uint8 category; /* category of action frame (5) */
+ uint8 action; /* radio measurement action */
+ uint8 token; /* dialog token */
+ uint8 txpwr; /* Transmit Power Used */
+ uint8 maxtxpwr; /* Max Transmit Power */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_lmreq dot11_lmreq_t;
+#define DOT11_LMREQ_LEN 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_lmrep {
+ uint8 category; /* category of action frame (5) */
+ uint8 action; /* radio measurement action */
+ uint8 token; /* dialog token */
+ dot11_tpc_rep_t tpc; /* TPC element */
+ uint8 rxant; /* Receive Antenna ID */
+ uint8 txant; /* Transmit Antenna ID */
+ uint8 rcpi; /* RCPI */
+ uint8 rsni; /* RSNI */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_lmrep dot11_lmrep_t;
+#define DOT11_LMREP_LEN 11
+
+/* 802.11 BRCM "Compromise" Pre N constants */
+#define PREN_PREAMBLE 24 /* green field preamble time */
+#define PREN_MM_EXT 12 /* extra mixed mode preamble time */
+#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */
+
+/* 802.11N PHY constants */
+#define RIFS_11N_TIME 2 /* NPHY RIFS time */
+
+/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3
+ * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2
+ */
+/* HT-SIG1 */
+#define HT_SIG1_MCS_MASK 0x00007F
+#define HT_SIG1_CBW 0x000080
+#define HT_SIG1_HT_LENGTH 0xFFFF00
+
+/* HT-SIG2 */
+#define HT_SIG2_SMOOTHING 0x000001
+#define HT_SIG2_NOT_SOUNDING 0x000002
+#define HT_SIG2_RESERVED 0x000004
+#define HT_SIG2_AGGREGATION 0x000008
+#define HT_SIG2_STBC_MASK 0x000030
+#define HT_SIG2_STBC_SHIFT 4
+#define HT_SIG2_FEC_CODING 0x000040
+#define HT_SIG2_SHORT_GI 0x000080
+#define HT_SIG2_ESS_MASK 0x000300
+#define HT_SIG2_ESS_SHIFT 8
+#define HT_SIG2_CRC 0x03FC00
+#define HT_SIG2_TAIL 0x1C0000
+
+/* HT Timing-related parameters (802.11-2012, sec 20.3.6) */
+#define HT_T_LEG_PREAMBLE 16
+#define HT_T_L_SIG 4
+#define HT_T_SIG 8
+#define HT_T_LTF1 4
+#define HT_T_GF_LTF1 8
+#define HT_T_LTFs 4
+#define HT_T_STF 4
+#define HT_T_GF_STF 8
+#define HT_T_SYML 4
+
+#define HT_N_SERVICE 16 /* bits in SERVICE field */
+#define HT_N_TAIL 6 /* tail bits per BCC encoder */
+
+/* 802.11 A PHY constants */
+#define APHY_SLOT_TIME 9 /* APHY slot time */
+#define APHY_SIFS_TIME 16 /* APHY SIFS time */
+#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */
+#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */
+#define APHY_SIGNAL_TIME 4 /* APHY signal time */
+#define APHY_SYMBOL_TIME 4 /* APHY symbol time */
+#define APHY_SERVICE_NBITS 16 /* APHY service nbits */
+#define APHY_TAIL_NBITS 6 /* APHY tail nbits */
+#define APHY_CWMIN 15 /* APHY cwmin */
+
+/* 802.11 B PHY constants */
+#define BPHY_SLOT_TIME 20 /* BPHY slot time */
+#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */
+#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */
+#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */
+#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */
+#define BPHY_CWMIN 31 /* BPHY cwmin */
+
+/* 802.11 G constants */
+#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */
+
+#define PHY_CWMAX 1023 /* PHY cwmax */
+
+#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */
+
+/* 802.11 VHT constants */
+
+typedef int vht_group_id_t;
+
+/* for VHT-A1 */
+/* SIG-A1 reserved bits */
+#define VHT_SIGA1_CONST_MASK 0x800004
+
+#define VHT_SIGA1_BW_MASK 0x000003
+#define VHT_SIGA1_20MHZ_VAL 0x000000
+#define VHT_SIGA1_40MHZ_VAL 0x000001
+#define VHT_SIGA1_80MHZ_VAL 0x000002
+#define VHT_SIGA1_160MHZ_VAL 0x000003
+
+#define VHT_SIGA1_STBC 0x000008
+
+#define VHT_SIGA1_GID_MASK 0x0003f0
+#define VHT_SIGA1_GID_SHIFT 4
+#define VHT_SIGA1_GID_TO_AP 0x00
+#define VHT_SIGA1_GID_NOT_TO_AP 0x3f
+#define VHT_SIGA1_GID_MAX_GID 0x3f
+
+#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00
+#define VHT_SIGA1_NSTS_SHIFT 10
+
+#define VHT_SIGA1_PARTIAL_AID_MASK 0x3fe000
+#define VHT_SIGA1_PARTIAL_AID_SHIFT 13
+
+#define VHT_SIGA1_TXOP_PS_NOT_ALLOWED 0x400000
+
+/* for VHT-A2 */
+#define VHT_SIGA2_GI_NONE 0x000000
+#define VHT_SIGA2_GI_SHORT 0x000001
+#define VHT_SIGA2_GI_W_MOD10 0x000002
+#define VHT_SIGA2_CODING_LDPC 0x000004
+#define VHT_SIGA2_LDPC_EXTRA_OFDM_SYM 0x000008
+#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100
+#define VHT_SIGA2_MCS_SHIFT 4
+
+#define VHT_SIGA2_B9_RESERVED 0x000200
+#define VHT_SIGA2_TAIL_MASK 0xfc0000
+#define VHT_SIGA2_TAIL_VALUE 0x000000
+
+/* VHT Timing-related parameters (802.11ac D4.0, sec 22.3.6) */
+#define VHT_T_LEG_PREAMBLE 16
+#define VHT_T_L_SIG 4
+#define VHT_T_SIG_A 8
+#define VHT_T_LTF 4
+#define VHT_T_STF 4
+#define VHT_T_SIG_B 4
+#define VHT_T_SYML 4
+
+#define VHT_N_SERVICE 16 /* bits in SERVICE field */
+#define VHT_N_TAIL 6 /* tail bits per BCC encoder */
+
+
+/* dot11Counters Table - 802.11 spec., Annex D */
+typedef struct d11cnt {
+ uint32 txfrag; /* dot11TransmittedFragmentCount */
+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */
+ uint32 txfail; /* dot11FailedCount */
+ uint32 txretry; /* dot11RetryCount */
+ uint32 txretrie; /* dot11MultipleRetryCount */
+ uint32 rxdup; /* dot11FrameduplicateCount */
+ uint32 txrts; /* dot11RTSSuccessCount */
+ uint32 txnocts; /* dot11RTSFailureCount */
+ uint32 txnoack; /* dot11ACKFailureCount */
+ uint32 rxfrag; /* dot11ReceivedFragmentCount */
+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */
+ uint32 rxcrc; /* dot11FCSErrorCount */
+ uint32 txfrmsnt; /* dot11TransmittedFrameCount */
+ uint32 rxundec; /* dot11WEPUndecryptableCount */
+} d11cnt_t;
+
+#define BRCM_PROP_OUI "\x00\x90\x4C"
+
+
+/* Action frame type for RWL */
+#define RWL_WIFI_DEFAULT 0
+#define RWL_WIFI_FIND_MY_PEER 9 /* Used while finding server */
+#define RWL_WIFI_FOUND_PEER 10 /* Server response to the client */
+#define RWL_ACTION_WIFI_FRAG_TYPE 85 /* Fragment indicator for receiver */
+
+#define PROXD_AF_TYPE 11 /* Wifi proximity action frame type */
+#define BRCM_RELMACST_AF_TYPE 12 /* RMC action frame type */
+
+
+/* brcm syscap_ie cap */
+#define BRCM_SYSCAP_WET_TUNNEL 0x0100 /* Device with WET_TUNNEL support */
+
+#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */
+
+/* BRCM info element */
+BWL_PRE_PACKED_STRUCT struct brcm_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3];
+ uint8 ver; /* type/ver of this IE */
+ uint8 assoc; /* # of assoc STAs */
+ uint8 flags; /* misc flags */
+ uint8 flags1; /* misc flags */
+ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */
+} BWL_POST_PACKED_STRUCT;
+typedef struct brcm_ie brcm_ie_t;
+#define BRCM_IE_LEN 11 /* BRCM IE length */
+#define BRCM_IE_VER 2 /* BRCM IE version */
+#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */
+
+/* brcm_ie flags */
+#define BRF_LZWDS 0x4 /* lazy wds enabled */
+#define BRF_BLOCKACK 0x8 /* BlockACK capable */
+
+/* brcm_ie flags1 */
+#define BRF1_AMSDU 0x1 /* A-MSDU capable */
+#define BRF1_WMEPS 0x4 /* AP is capable of handling WME + PS w/o APSD */
+#define BRF1_PSOFIX 0x8 /* AP has fixed PS mode out-of-order packets */
+#define BRF1_RX_LARGE_AGG 0x10 /* device can rx large aggregates */
+#define BRF1_RFAWARE_DCS 0x20 /* RFAWARE dynamic channel selection (DCS) */
+#define BRF1_SOFTAP 0x40 /* Configure as Broadcom SOFTAP */
+#define BRF1_DWDS 0x80 /* DWDS capable */
+
+/* Vendor IE structure */
+BWL_PRE_PACKED_STRUCT struct vndr_ie {
+ uchar id;
+ uchar len;
+ uchar oui [3];
+ uchar data [1]; /* Variable size data */
+} BWL_POST_PACKED_STRUCT;
+typedef struct vndr_ie vndr_ie_t;
+
+#define VNDR_IE_HDR_LEN 2 /* id + len field */
+#define VNDR_IE_MIN_LEN 3 /* size of the oui field */
+#define VNDR_IE_FIXED_LEN (VNDR_IE_HDR_LEN + VNDR_IE_MIN_LEN)
+
+#define VNDR_IE_MAX_LEN 255 /* vendor IE max length, without ID and len */
+
+/* BRCM PROP DEVICE PRIMARY MAC ADDRESS IE */
+BWL_PRE_PACKED_STRUCT struct member_of_brcm_prop_ie {
+ uchar id;
+ uchar len;
+ uchar oui[3];
+ uint8 type; /* type inidicates what follows */
+ struct ether_addr ea; /* Device Primary MAC Adrress */
+} BWL_POST_PACKED_STRUCT;
+typedef struct member_of_brcm_prop_ie member_of_brcm_prop_ie_t;
+
+#define MEMBER_OF_BRCM_PROP_IE_LEN 10 /* IE max length */
+#define MEMBER_OF_BRCM_PROP_IE_HDRLEN (sizeof(member_of_brcm_prop_ie_t))
+#define MEMBER_OF_BRCM_PROP_IE_TYPE 54
+
+/* BRCM Reliable Multicast IE */
+BWL_PRE_PACKED_STRUCT struct relmcast_brcm_prop_ie {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 type; /* type inidicates what follows */
+ struct ether_addr ea; /* The ack sender's MAC Adrress */
+ struct ether_addr mcast_ea; /* The multicast MAC address */
+ uint8 updtmo; /* time interval(second) for client to send null packet to report its rssi */
+} BWL_POST_PACKED_STRUCT;
+typedef struct relmcast_brcm_prop_ie relmcast_brcm_prop_ie_t;
+
+/* IE length */
+/* BRCM_PROP_IE_LEN = sizeof(relmcast_brcm_prop_ie_t)-((sizeof (id) + sizeof (len)))? */
+#define RELMCAST_BRCM_PROP_IE_LEN (sizeof(relmcast_brcm_prop_ie_t)-(2*sizeof(uint8)))
+
+#define RELMCAST_BRCM_PROP_IE_TYPE 55
+
+/* ************* HT definitions. ************* */
+#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */
+#define MAX_MCS_NUM (128) /* max mcs number = 128 */
+
+BWL_PRE_PACKED_STRUCT struct ht_cap_ie {
+ uint16 cap;
+ uint8 params;
+ uint8 supp_mcs[MCSSET_LEN];
+ uint16 ext_htcap;
+ uint32 txbf_cap;
+ uint8 as_cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_cap_ie ht_cap_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_ht_cap_ie {
+ uint8 id;
+ uint8 len;
+ ht_cap_ie_t ht_cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ht_cap_ie dot11_ht_cap_ie_t;
+
+/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
+/* the capability IE is primarily used to convey this nodes abilities */
+BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3];
+ uint8 type; /* type inidicates what follows */
+ ht_cap_ie_t cap_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_prop_cap_ie ht_prop_cap_ie_t;
+
+#define HT_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */
+#define HT_CAP_IE_LEN 26 /* HT capability len (based on .11n d2.0) */
+#define HT_CAP_IE_TYPE 51
+
+#define HT_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */
+#define HT_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */
+#define HT_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */
+#define HT_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */
+#define HT_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */
+#define HT_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */
+#define HT_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */
+#define HT_CAP_GF 0x0010 /* Greenfield preamble support */
+#define HT_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */
+#define HT_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */
+#define HT_CAP_TX_STBC 0x0080 /* Tx STBC support */
+#define HT_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */
+#define HT_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */
+#define HT_CAP_DELAYED_BA 0x0400 /* delayed BA support */
+#define HT_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */
+
+#define HT_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */
+#define HT_CAP_PSMP 0x2000 /* Power Save Multi Poll support */
+#define HT_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */
+#define HT_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */
+
+#define HT_CAP_RX_STBC_NO 0x0 /* no rx STBC support */
+#define HT_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */
+#define HT_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */
+#define HT_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */
+
+
+#define HT_CAP_TXBF_CAP_IMPLICIT_TXBF_RX 0x1
+#define HT_CAP_TXBF_CAP_NDP_TX 0x8
+#define HT_CAP_TXBF_CAP_NDP_RX 0x10
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI 0x100
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_STEERING 0x200
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_STEERING 0x400
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI_FB_MASK 0x1800
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI_FB_SHIFT 11
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_FB_MASK 0x6000
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_FB_SHIFT 13
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_FB_MASK 0x18000
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_FB_SHIFT 15
+#define HT_CAP_TXBF_CAP_CSI_BFR_ANT_SHIFT 19
+#define HT_CAP_TXBF_CAP_NC_BFR_ANT_SHIFT 21
+#define HT_CAP_TXBF_CAP_C_BFR_ANT_SHIFT 23
+#define HT_CAP_TXBF_CAP_C_BFR_ANT_MASK 0x1800000
+
+#define HT_CAP_TXBF_CAP_CHAN_ESTIM_SHIFT 27
+#define HT_CAP_TXBF_CAP_CHAN_ESTIM_MASK 0x18000000
+
+#define HT_CAP_TXBF_FB_TYPE_NONE 0
+#define HT_CAP_TXBF_FB_TYPE_DELAYED 1
+#define HT_CAP_TXBF_FB_TYPE_IMMEDIATE 2
+#define HT_CAP_TXBF_FB_TYPE_BOTH 3
+
+#define HT_CAP_TX_BF_CAP_EXPLICIT_CSI_FB_MASK 0x400
+#define HT_CAP_TX_BF_CAP_EXPLICIT_CSI_FB_SHIFT 10
+#define HT_CAP_TX_BF_CAP_EXPLICIT_COMPRESSED_FB_MASK 0x18000
+#define HT_CAP_TX_BF_CAP_EXPLICIT_COMPRESSED_FB_SHIFT 15
+
+#define VHT_MAX_MPDU 11454 /* max mpdu size for now (bytes) */
+#define VHT_MPDU_MSDU_DELTA 56 /* Difference in spec - vht mpdu, amsdu len */
+/* Max AMSDU len - per spec */
+#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA)
+
+#define HT_MAX_AMSDU 7935 /* max amsdu size (bytes) per the HT spec */
+#define HT_MIN_AMSDU 3835 /* min amsdu size (bytes) per the HT spec */
+
+#define HT_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */
+#define HT_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */
+#define HT_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */
+
+/* HT/AMPDU specific define */
+#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/4 usec units */
+#define AMPDU_DENSITY_NONE 0 /* No density requirement */
+#define AMPDU_DENSITY_1over4_US 1 /* 1/4 us density */
+#define AMPDU_DENSITY_1over2_US 2 /* 1/2 us density */
+#define AMPDU_DENSITY_1_US 3 /* 1 us density */
+#define AMPDU_DENSITY_2_US 4 /* 2 us density */
+#define AMPDU_DENSITY_4_US 5 /* 4 us density */
+#define AMPDU_DENSITY_8_US 6 /* 8 us density */
+#define AMPDU_DENSITY_16_US 7 /* 16 us density */
+#define AMPDU_RX_FACTOR_8K 0 /* max rcv ampdu len (8kb) */
+#define AMPDU_RX_FACTOR_16K 1 /* max rcv ampdu len (16kb) */
+#define AMPDU_RX_FACTOR_32K 2 /* max rcv ampdu len (32kb) */
+#define AMPDU_RX_FACTOR_64K 3 /* max rcv ampdu len (64kb) */
+
+/* AMPDU RX factors for VHT rates */
+#define AMPDU_RX_FACTOR_128K 4 /* max rcv ampdu len (128kb) */
+#define AMPDU_RX_FACTOR_256K 5 /* max rcv ampdu len (256kb) */
+#define AMPDU_RX_FACTOR_512K 6 /* max rcv ampdu len (512kb) */
+#define AMPDU_RX_FACTOR_1024K 7 /* max rcv ampdu len (1024kb) */
+
+#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */
+#define AMPDU_RX_FACTOR_BASE_PWR 13 /* ampdu factor base for rx len in power of 2 */
+
+#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */
+#define AMPDU_DELIMITER_LEN_MAX 63 /* max length of ampdu delimiter(enforced in HW) */
+
+#define HT_CAP_EXT_PCO 0x0001
+#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006
+#define HT_CAP_EXT_PCO_TTIME_SHIFT 1
+#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300
+#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8
+#define HT_CAP_EXT_HTC 0x0400
+#define HT_CAP_EXT_RD_RESP 0x0800
+
+BWL_PRE_PACKED_STRUCT struct ht_add_ie {
+ uint8 ctl_ch; /* control channel number */
+ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */
+ uint16 opmode; /* operation mode */
+ uint16 misc_bits; /* misc bits */
+ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_add_ie ht_add_ie_t;
+
+/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
+/* the additional IE is primarily used to convey the current BSS configuration */
+BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie {
+ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */
+ uint8 len; /* IE length */
+ uint8 oui[3];
+ uint8 type; /* indicates what follows */
+ ht_add_ie_t add_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_prop_add_ie ht_prop_add_ie_t;
+
+#define HT_ADD_IE_LEN 22
+#define HT_ADD_IE_TYPE 52
+
+/* byte1 defn's */
+#define HT_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */
+#define HT_RIFS_PERMITTED 0x08 /* RIFS allowed */
+
+/* opmode defn's */
+#define HT_OPMODE_MASK 0x0003 /* protection mode mask */
+#define HT_OPMODE_SHIFT 0 /* protection mode shift */
+#define HT_OPMODE_PURE 0x0000 /* protection mode PURE */
+#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */
+#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */
+#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */
+#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */
+#define DOT11N_TXBURST 0x0008 /* Tx burst limit */
+#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */
+
+/* misc_bites defn's */
+#define HT_BASIC_STBC_MCS 0x007f /* basic STBC MCS */
+#define HT_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */
+#define HT_SECOND_BCN 0x0100 /* Secondary beacon support */
+#define HT_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */
+#define HT_PCO_ACTIVE 0x0400 /* PCO active */
+#define HT_PCO_PHASE 0x0800 /* PCO phase */
+#define HT_DUALCTS_PROTECTION 0x0080 /* DUAL CTS protection needed */
+
+/* Tx Burst Limits */
+#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */
+#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */
+
+/* Macros for opmode */
+#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ >> HT_OPMODE_SHIFT)
+#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_MIXED) /* mixed mode present */
+#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_HT20IN40) /* 20MHz HT present */
+#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_OPTIONAL) /* Optional protection present */
+#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \
+ HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */
+#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \
+ == HT_OPMODE_NONGF) /* non-GF present */
+#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \
+ == DOT11N_TXBURST) /* Tx Burst present */
+#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \
+ == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */
+
+BWL_PRE_PACKED_STRUCT struct obss_params {
+ uint16 passive_dwell;
+ uint16 active_dwell;
+ uint16 bss_widthscan_interval;
+ uint16 passive_total;
+ uint16 active_total;
+ uint16 chanwidth_transition_dly;
+ uint16 activity_threshold;
+} BWL_POST_PACKED_STRUCT;
+typedef struct obss_params obss_params_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_ie {
+ uint8 id;
+ uint8 len;
+ obss_params_t obss_params;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_ie dot11_obss_ie_t;
+#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t) /* HT OBSS len (based on 802.11n d3.0) */
+
+/* HT control field */
+#define HT_CTRL_LA_TRQ 0x00000002 /* sounding request */
+#define HT_CTRL_LA_MAI 0x0000003C /* MCS request or antenna selection indication */
+#define HT_CTRL_LA_MAI_SHIFT 2
+#define HT_CTRL_LA_MAI_MRQ 0x00000004 /* MCS request */
+#define HT_CTRL_LA_MAI_MSI 0x00000038 /* MCS request sequence identifier */
+#define HT_CTRL_LA_MFSI 0x000001C0 /* MFB sequence identifier */
+#define HT_CTRL_LA_MFSI_SHIFT 6
+#define HT_CTRL_LA_MFB_ASELC 0x0000FE00 /* MCS feedback, antenna selection command/data */
+#define HT_CTRL_LA_MFB_ASELC_SH 9
+#define HT_CTRL_LA_ASELC_CMD 0x00000C00 /* ASEL command */
+#define HT_CTRL_LA_ASELC_DATA 0x0000F000 /* ASEL data */
+#define HT_CTRL_CAL_POS 0x00030000 /* Calibration position */
+#define HT_CTRL_CAL_SEQ 0x000C0000 /* Calibration sequence */
+#define HT_CTRL_CSI_STEERING 0x00C00000 /* CSI/Steering */
+#define HT_CTRL_CSI_STEER_SHIFT 22
+#define HT_CTRL_CSI_STEER_NFB 0 /* no fedback required */
+#define HT_CTRL_CSI_STEER_CSI 1 /* CSI, H matrix */
+#define HT_CTRL_CSI_STEER_NCOM 2 /* non-compressed beamforming */
+#define HT_CTRL_CSI_STEER_COM 3 /* compressed beamforming */
+#define HT_CTRL_NDP_ANNOUNCE 0x01000000 /* NDP announcement */
+#define HT_CTRL_AC_CONSTRAINT 0x40000000 /* AC Constraint */
+#define HT_CTRL_RDG_MOREPPDU 0x80000000 /* RDG/More PPDU */
+
+/* ************* VHT definitions. ************* */
+
+/*
+ * VHT Capabilites IE (sec 8.4.2.160)
+ */
+
+BWL_PRE_PACKED_STRUCT struct vht_cap_ie {
+ uint32 vht_cap_info;
+ /* supported MCS set - 64 bit field */
+ uint16 rx_mcs_map;
+ uint16 rx_max_rate;
+ uint16 tx_mcs_map;
+ uint16 tx_max_rate;
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_cap_ie vht_cap_ie_t;
+
+/* 4B cap_info + 8B supp_mcs */
+#define VHT_CAP_IE_LEN 12
+
+/* VHT Capabilities Info field - 32bit - in VHT Cap IE */
+#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003
+#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c
+#define VHT_CAP_INFO_LDPC 0x00000010
+#define VHT_CAP_INFO_SGI_80MHZ 0x00000020
+#define VHT_CAP_INFO_SGI_160MHZ 0x00000040
+#define VHT_CAP_INFO_TX_STBC 0x00000080
+#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700
+#define VHT_CAP_INFO_RX_STBC_SHIFT 8
+#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800
+#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000
+#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000
+#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13
+#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000
+#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16
+#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000
+#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000
+#define VHT_CAP_INFO_TXOPPS 0x00200000
+#define VHT_CAP_INFO_HTCVHT 0x00400000
+#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000
+#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23
+#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000
+#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26
+
+/* VHT Supported MCS Set - 64-bit - in VHT Cap IE */
+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff
+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0
+
+#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff
+#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0
+
+#define VHT_CAP_MCS_MAP_0_7 0
+#define VHT_CAP_MCS_MAP_0_8 1
+#define VHT_CAP_MCS_MAP_0_9 2
+#define VHT_CAP_MCS_MAP_NONE 3
+#define VHT_CAP_MCS_MAP_S 2 /* num bits for 1-stream */
+#define VHT_CAP_MCS_MAP_M 0x3 /* mask for 1-stream */
+/* assumes VHT_CAP_MCS_MAP_NONE is 3 and 2 bits are used for encoding */
+#define VHT_CAP_MCS_MAP_NONE_ALL 0xffff
+/* mcsmap with MCS0-9 for Nss = 3 */
+#define VHT_CAP_MCS_MAP_0_9_NSS3 \
+ ((VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(1)) | \
+ (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(2)) | \
+ (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(3)))
+
+#define VHT_CAP_MCS_MAP_NSS_MAX 8
+
+/* get mcsmap with given mcs for given nss streams */
+#define VHT_CAP_MCS_MAP_CREATE(mcsmap, nss, mcs) \
+ do { \
+ int i; \
+ for (i = 1; i <= nss; i++) { \
+ VHT_MCS_MAP_SET_MCS_PER_SS(i, mcs, mcsmap); \
+ } \
+ } while (0)
+
+/* Map the mcs code to mcs bit map */
+#define VHT_MCS_CODE_TO_MCS_MAP(mcs_code) \
+ ((mcs_code == VHT_CAP_MCS_MAP_0_7) ? 0xff : \
+ (mcs_code == VHT_CAP_MCS_MAP_0_8) ? 0x1ff : \
+ (mcs_code == VHT_CAP_MCS_MAP_0_9) ? 0x3ff : 0)
+
+/* Map the mcs bit map to mcs code */
+#define VHT_MCS_MAP_TO_MCS_CODE(mcs_map) \
+ ((mcs_map == 0xff) ? VHT_CAP_MCS_MAP_0_7 : \
+ (mcs_map == 0x1ff) ? VHT_CAP_MCS_MAP_0_8 : \
+ (mcs_map == 0x3ff) ? VHT_CAP_MCS_MAP_0_9 : VHT_CAP_MCS_MAP_NONE)
+
+/* VHT Capabilities Supported Channel Width */
+typedef enum vht_cap_chan_width {
+ VHT_CAP_CHAN_WIDTH_SUPPORT_MANDATORY = 0x00,
+ VHT_CAP_CHAN_WIDTH_SUPPORT_160 = 0x04,
+ VHT_CAP_CHAN_WIDTH_SUPPORT_160_8080 = 0x08
+} vht_cap_chan_width_t;
+
+/* VHT Capabilities Supported max MPDU LEN (sec 8.4.2.160.2) */
+typedef enum vht_cap_max_mpdu_len {
+ VHT_CAP_MPDU_MAX_4K = 0x00,
+ VHT_CAP_MPDU_MAX_8K = 0x01,
+ VHT_CAP_MPDU_MAX_11K = 0x02
+} vht_cap_max_mpdu_len_t;
+
+/* Maximum MPDU Length byte counts for the VHT Capabilities advertised limits */
+#define VHT_MPDU_LIMIT_4K 3895
+#define VHT_MPDU_LIMIT_8K 7991
+#define VHT_MPDU_LIMIT_11K 11454
+
+
+/*
+ * VHT Operation IE (sec 8.4.2.161)
+ */
+
+BWL_PRE_PACKED_STRUCT struct vht_op_ie {
+ uint8 chan_width;
+ uint8 chan1;
+ uint8 chan2;
+ uint16 supp_mcs; /* same def as above in vht cap */
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_op_ie vht_op_ie_t;
+
+/* 3B VHT Op info + 2B Basic MCS */
+#define VHT_OP_IE_LEN 5
+
+typedef enum vht_op_chan_width {
+ VHT_OP_CHAN_WIDTH_20_40 = 0,
+ VHT_OP_CHAN_WIDTH_80 = 1,
+ VHT_OP_CHAN_WIDTH_160 = 2,
+ VHT_OP_CHAN_WIDTH_80_80 = 3
+} vht_op_chan_width_t;
+
+/* AID length */
+#define AID_IE_LEN 2
+/*
+ * BRCM vht features IE header
+ * The header if the fixed part of the IE
+ * On the 5GHz band this is the entire IE,
+ * on 2.4GHz the VHT IEs as defined in the 802.11ac
+ * specification follows
+ *
+ *
+ * VHT features rates bitmap.
+ * Bit0: 5G MCS 0-9 BW 160MHz
+ * Bit1: 5G MCS 0-9 support BW 80MHz
+ * Bit2: 5G MCS 0-9 support BW 20MHz
+ * Bit3: 2.4G MCS 0-9 support BW 20MHz
+ * Bits:4-7 Reserved for future use
+ *
+ */
+#define VHT_FEATURES_IE_TYPE 0x4
+BWL_PRE_PACKED_STRUCT struct vht_features_ie_hdr {
+ uint8 oui[3];
+ uint8 type; /* type of this IE = 4 */
+ uint8 rate_mask; /* VHT rate mask */
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_features_ie_hdr vht_features_ie_hdr_t;
+
+/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */
+#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1) * VHT_CAP_MCS_MAP_S)
+#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \
+ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & VHT_CAP_MCS_MAP_M)
+#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \
+ do { \
+ (mcsMap) &= (~(VHT_CAP_MCS_MAP_M << VHT_MCS_MAP_GET_SS_IDX(nss))); \
+ (mcsMap) |= (((numMcs) & VHT_CAP_MCS_MAP_M) << VHT_MCS_MAP_GET_SS_IDX(nss)); \
+ } while (0)
+#define VHT_MCS_SS_SUPPORTED(nss, mcsMap) \
+ (VHT_MCS_MAP_GET_MCS_PER_SS((nss), (mcsMap)) != VHT_CAP_MCS_MAP_NONE)
+
+
+/* ************* WPA definitions. ************* */
+#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
+#define WPA_OUI_LEN 3 /* WPA OUI length */
+#define WPA_OUI_TYPE 1
+#define WPA_VERSION 1 /* WPA version */
+#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */
+#define WPA2_OUI_LEN 3 /* WPA2 OUI length */
+#define WPA2_VERSION 1 /* WPA2 version */
+#define WPA2_VERSION_LEN 2 /* WAP2 version length */
+
+/* ************* WPS definitions. ************* */
+#define WPS_OUI "\x00\x50\xF2" /* WPS OUI */
+#define WPS_OUI_LEN 3 /* WPS OUI length */
+#define WPS_OUI_TYPE 4
+
+/* ************* WFA definitions. ************* */
+
+#ifdef P2P_IE_OVRD
+#define WFA_OUI MAC_OUI
+#else
+#define WFA_OUI "\x50\x6F\x9A" /* WFA OUI */
+#endif /* P2P_IE_OVRD */
+#define WFA_OUI_LEN 3 /* WFA OUI length */
+#ifdef P2P_IE_OVRD
+#define WFA_OUI_TYPE_P2P MAC_OUI_TYPE_P2P
+#else
+#define WFA_OUI_TYPE_TPC 8
+#define WFA_OUI_TYPE_P2P 9
+#endif
+
+#define WFA_OUI_TYPE_TPC 8
+#ifdef WLTDLS
+#define WFA_OUI_TYPE_TPQ 4 /* WFD Tunneled Probe ReQuest */
+#define WFA_OUI_TYPE_TPS 5 /* WFD Tunneled Probe ReSponse */
+#define WFA_OUI_TYPE_WFD 10
+#endif /* WTDLS */
+#define WFA_OUI_TYPE_HS20 0x10
+
+/* RSN authenticated key managment suite */
+#define RSN_AKM_NONE 0 /* None (IBSS) */
+#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */
+#define RSN_AKM_PSK 2 /* Pre-shared Key */
+#define RSN_AKM_FBT_1X 3 /* Fast Bss transition using 802.1X */
+#define RSN_AKM_FBT_PSK 4 /* Fast Bss transition using Pre-shared Key */
+#define RSN_AKM_MFP_1X 5 /* SHA256 key derivation, using 802.1X */
+#define RSN_AKM_MFP_PSK 6 /* SHA256 key derivation, using Pre-shared Key */
+#define RSN_AKM_TPK 7 /* TPK(TDLS Peer Key) handshake */
+
+/* Key related defines */
+#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */
+#define DOT11_MAX_IGTK_KEYS 2
+#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */
+#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */
+#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */
+#define DOT11_WPA_KEY_RSC_LEN 8 /* WPA RSC key len */
+
+#define WEP1_KEY_SIZE 5 /* max size of any WEP key */
+#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */
+#define WEP128_KEY_SIZE 13 /* max size of any WEP key */
+#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */
+#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */
+#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */
+#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */
+#define TKIP_KEY_SIZE 32 /* size of any TKIP key, includs MIC keys */
+#define TKIP_TK_SIZE 16
+#define TKIP_MIC_KEY_SIZE 8
+#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */
+#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */
+#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */
+#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */
+#define AES_KEY_SIZE 16 /* size of AES key */
+#define AES_MIC_SIZE 8 /* size of AES MIC */
+#define BIP_KEY_SIZE 16 /* size of BIP key */
+#define BIP_MIC_SIZE 8 /* sizeof BIP MIC */
+
+#define AES_GCM_MIC_SIZE 16 /* size of MIC for 128-bit GCM - .11adD9 */
+
+#define AES256_KEY_SIZE 32 /* size of AES 256 key - .11acD5 */
+#define AES256_MIC_SIZE 16 /* size of MIC for 256 bit keys, incl BIP */
+
+/* WCN */
+#define WCN_OUI "\x00\x50\xf2" /* WCN OUI */
+#define WCN_TYPE 4 /* WCN type */
+
+
+/* 802.11r protocol definitions */
+
+/* Mobility Domain IE */
+BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie {
+ uint8 id;
+ uint8 len;
+ uint16 mdid; /* Mobility Domain Id */
+ uint8 cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_mdid_ie dot11_mdid_ie_t;
+
+#define FBT_MDID_CAP_OVERDS 0x01 /* Fast Bss transition over the DS support */
+#define FBT_MDID_CAP_RRP 0x02 /* Resource request protocol support */
+
+/* Fast Bss Transition IE */
+BWL_PRE_PACKED_STRUCT struct dot11_ft_ie {
+ uint8 id;
+ uint8 len;
+ uint16 mic_control; /* Mic Control */
+ uint8 mic[16];
+ uint8 anonce[32];
+ uint8 snonce[32];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_ie dot11_ft_ie_t;
+
+#define TIE_TYPE_RESERVED 0
+#define TIE_TYPE_REASSOC_DEADLINE 1
+#define TIE_TYPE_KEY_LIEFTIME 2
+#define TIE_TYPE_ASSOC_COMEBACK 3
+BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie {
+ uint8 id;
+ uint8 len;
+ uint8 type; /* timeout interval type */
+ uint32 value; /* timeout interval value */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timeout_ie dot11_timeout_ie_t;
+
+/* GTK ie */
+BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie {
+ uint8 id;
+ uint8 len;
+ uint16 key_info;
+ uint8 key_len;
+ uint8 rsc[8];
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_gtk_ie dot11_gtk_ie_t;
+
+/* Management MIC ie */
+BWL_PRE_PACKED_STRUCT struct mmic_ie {
+ uint8 id; /* IE ID: DOT11_MNG_MMIE_ID */
+ uint8 len; /* IE length */
+ uint16 key_id; /* key id */
+ uint8 ipn[6]; /* ipn */
+ uint8 mic[16]; /* mic */
+} BWL_POST_PACKED_STRUCT;
+typedef struct mmic_ie mmic_ie_t;
+
+#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00"
+#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF"
+
+
+/* ************* WMM Parameter definitions. ************* */
+#define WMM_OUI "\x00\x50\xF2" /* WNN OUI */
+#define WMM_OUI_LEN 3 /* WMM OUI length */
+#define WMM_OUI_TYPE 2 /* WMM OUT type */
+#define WMM_VERSION 1
+#define WMM_VERSION_LEN 1
+
+/* WMM OUI subtype */
+#define WMM_OUI_SUBTYPE_PARAMETER 1
+#define WMM_PARAMETER_IE_LEN 24
+
+/* Link Identifier Element */
+BWL_PRE_PACKED_STRUCT struct link_id_ie {
+ uint8 id;
+ uint8 len;
+ struct ether_addr bssid;
+ struct ether_addr tdls_init_mac;
+ struct ether_addr tdls_resp_mac;
+} BWL_POST_PACKED_STRUCT;
+typedef struct link_id_ie link_id_ie_t;
+#define TDLS_LINK_ID_IE_LEN 18
+
+/* Link Wakeup Schedule Element */
+BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie {
+ uint8 id;
+ uint8 len;
+ uint32 offset; /* in ms between TSF0 and start of 1st Awake Window */
+ uint32 interval; /* in ms bwtween the start of 2 Awake Windows */
+ uint32 awake_win_slots; /* in backof slots, duration of Awake Window */
+ uint32 max_wake_win; /* in ms, max duration of Awake Window */
+ uint16 idle_cnt; /* number of consecutive Awake Windows */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wakeup_sch_ie wakeup_sch_ie_t;
+#define TDLS_WAKEUP_SCH_IE_LEN 18
+
+/* Channel Switch Timing Element */
+BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie {
+ uint8 id;
+ uint8 len;
+ uint16 switch_time; /* in ms, time to switch channels */
+ uint16 switch_timeout; /* in ms */
+} BWL_POST_PACKED_STRUCT;
+typedef struct channel_switch_timing_ie channel_switch_timing_ie_t;
+#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4
+
+/* PTI Control Element */
+BWL_PRE_PACKED_STRUCT struct pti_control_ie {
+ uint8 id;
+ uint8 len;
+ uint8 tid;
+ uint16 seq_control;
+} BWL_POST_PACKED_STRUCT;
+typedef struct pti_control_ie pti_control_ie_t;
+#define TDLS_PTI_CONTROL_IE_LEN 3
+
+/* PU Buffer Status Element */
+BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie {
+ uint8 id;
+ uint8 len;
+ uint8 status;
+} BWL_POST_PACKED_STRUCT;
+typedef struct pu_buffer_status_ie pu_buffer_status_ie_t;
+#define TDLS_PU_BUFFER_STATUS_IE_LEN 1
+#define TDLS_PU_BUFFER_STATUS_AC_BK 1
+#define TDLS_PU_BUFFER_STATUS_AC_BE 2
+#define TDLS_PU_BUFFER_STATUS_AC_VI 4
+#define TDLS_PU_BUFFER_STATUS_AC_VO 8
+
+/* TDLS Action Field Values */
+#define TDLS_SETUP_REQ 0
+#define TDLS_SETUP_RESP 1
+#define TDLS_SETUP_CONFIRM 2
+#define TDLS_TEARDOWN 3
+#define TDLS_PEER_TRAFFIC_IND 4
+#define TDLS_CHANNEL_SWITCH_REQ 5
+#define TDLS_CHANNEL_SWITCH_RESP 6
+#define TDLS_PEER_PSM_REQ 7
+#define TDLS_PEER_PSM_RESP 8
+#define TDLS_PEER_TRAFFIC_RESP 9
+#define TDLS_DISCOVERY_REQ 10
+
+/* 802.11z TDLS Public Action Frame action field */
+#define TDLS_DISCOVERY_RESP 14
+
+/* 802.11u GAS action frames */
+#define GAS_REQUEST_ACTION_FRAME 10
+#define GAS_RESPONSE_ACTION_FRAME 11
+#define GAS_COMEBACK_REQUEST_ACTION_FRAME 12
+#define GAS_COMEBACK_RESPONSE_ACTION_FRAME 13
+
+/* 802.11u interworking access network options */
+#define IW_ANT_MASK 0x0f
+#define IW_INTERNET_MASK 0x10
+#define IW_ASRA_MASK 0x20
+#define IW_ESR_MASK 0x40
+#define IW_UESA_MASK 0x80
+
+/* 802.11u interworking access network type */
+#define IW_ANT_PRIVATE_NETWORK 0
+#define IW_ANT_PRIVATE_NETWORK_WITH_GUEST 1
+#define IW_ANT_CHARGEABLE_PUBLIC_NETWORK 2
+#define IW_ANT_FREE_PUBLIC_NETWORK 3
+#define IW_ANT_PERSONAL_DEVICE_NETWORK 4
+#define IW_ANT_EMERGENCY_SERVICES_NETWORK 5
+#define IW_ANT_TEST_NETWORK 14
+#define IW_ANT_WILDCARD_NETWORK 15
+
+/* 802.11u advertisement protocol */
+#define ADVP_ANQP_PROTOCOL_ID 0
+
+/* 802.11u advertisement protocol masks */
+#define ADVP_QRL_MASK 0x7f
+#define ADVP_PAME_BI_MASK 0x80
+
+/* 802.11u advertisement protocol values */
+#define ADVP_QRL_REQUEST 0x00
+#define ADVP_QRL_RESPONSE 0x7f
+#define ADVP_PAME_BI_DEPENDENT 0x00
+#define ADVP_PAME_BI_INDEPENDENT ADVP_PAME_BI_MASK
+
+/* 802.11u ANQP information ID */
+#define ANQP_ID_QUERY_LIST 256
+#define ANQP_ID_CAPABILITY_LIST 257
+#define ANQP_ID_VENUE_NAME_INFO 258
+#define ANQP_ID_EMERGENCY_CALL_NUMBER_INFO 259
+#define ANQP_ID_NETWORK_AUTHENTICATION_TYPE_INFO 260
+#define ANQP_ID_ROAMING_CONSORTIUM_LIST 261
+#define ANQP_ID_IP_ADDRESS_TYPE_AVAILABILITY_INFO 262
+#define ANQP_ID_NAI_REALM_LIST 263
+#define ANQP_ID_G3PP_CELLULAR_NETWORK_INFO 264
+#define ANQP_ID_AP_GEOSPATIAL_LOCATION 265
+#define ANQP_ID_AP_CIVIC_LOCATION 266
+#define ANQP_ID_AP_LOCATION_PUBLIC_ID_URI 267
+#define ANQP_ID_DOMAIN_NAME_LIST 268
+#define ANQP_ID_EMERGENCY_ALERT_ID_URI 269
+#define ANQP_ID_EMERGENCY_NAI 271
+#define ANQP_ID_VENDOR_SPECIFIC_LIST 56797
+
+/* 802.11u ANQP OUI */
+#define ANQP_OUI_SUBTYPE 9
+
+/* 802.11u venue name */
+#define VENUE_LANGUAGE_CODE_SIZE 3
+#define VENUE_NAME_SIZE 255
+
+/* 802.11u venue groups */
+#define VENUE_UNSPECIFIED 0
+#define VENUE_ASSEMBLY 1
+#define VENUE_BUSINESS 2
+#define VENUE_EDUCATIONAL 3
+#define VENUE_FACTORY 4
+#define VENUE_INSTITUTIONAL 5
+#define VENUE_MERCANTILE 6
+#define VENUE_RESIDENTIAL 7
+#define VENUE_STORAGE 8
+#define VENUE_UTILITY 9
+#define VENUE_VEHICULAR 10
+#define VENUE_OUTDOOR 11
+
+/* 802.11u network authentication type indicator */
+#define NATI_ACCEPTANCE_OF_TERMS_CONDITIONS 0
+#define NATI_ONLINE_ENROLLMENT_SUPPORTED 1
+#define NATI_HTTP_HTTPS_REDIRECTION 2
+#define NATI_DNS_REDIRECTION 3
+
+/* 802.11u IP address type availability - IPv6 */
+#define IPA_IPV6_SHIFT 0
+#define IPA_IPV6_MASK (0x03 << IPA_IPV6_SHIFT)
+#define IPA_IPV6_NOT_AVAILABLE 0x00
+#define IPA_IPV6_AVAILABLE 0x01
+#define IPA_IPV6_UNKNOWN_AVAILABILITY 0x02
+
+/* 802.11u IP address type availability - IPv4 */
+#define IPA_IPV4_SHIFT 2
+#define IPA_IPV4_MASK (0x3f << IPA_IPV4_SHIFT)
+#define IPA_IPV4_NOT_AVAILABLE 0x00
+#define IPA_IPV4_PUBLIC 0x01
+#define IPA_IPV4_PORT_RESTRICT 0x02
+#define IPA_IPV4_SINGLE_NAT 0x03
+#define IPA_IPV4_DOUBLE_NAT 0x04
+#define IPA_IPV4_PORT_RESTRICT_SINGLE_NAT 0x05
+#define IPA_IPV4_PORT_RESTRICT_DOUBLE_NAT 0x06
+#define IPA_IPV4_UNKNOWN_AVAILABILITY 0x07
+
+/* 802.11u NAI realm encoding */
+#define REALM_ENCODING_RFC4282 0
+#define REALM_ENCODING_UTF8 1
+
+/* 802.11u IANA EAP method type numbers */
+#define REALM_EAP_TLS 13
+#define REALM_EAP_SIM 18
+#define REALM_EAP_TTLS 21
+#define REALM_EAP_AKA 23
+#define REALM_EAP_PSK 47
+#define REALM_EAP_AKAP 50
+#define REALM_EAP_EXPANDED 254
+
+/* 802.11u authentication ID */
+#define REALM_EXPANDED_EAP 1
+#define REALM_NON_EAP_INNER_AUTHENTICATION 2
+#define REALM_INNER_AUTHENTICATION_EAP 3
+#define REALM_EXPANDED_INNER_EAP 4
+#define REALM_CREDENTIAL 5
+#define REALM_TUNNELED_EAP_CREDENTIAL 6
+#define REALM_VENDOR_SPECIFIC_EAP 221
+
+/* 802.11u non-EAP inner authentication type */
+#define REALM_PAP 1
+#define REALM_CHAP 2
+#define REALM_MSCHAP 3
+#define REALM_MSCHAPV2 4
+
+/* 802.11u credential type */
+#define REALM_SIM 1
+#define REALM_USIM 2
+#define REALM_NFC 3
+#define REALM_HARDWARE_TOKEN 4
+#define REALM_SOFTOKEN 5
+#define REALM_CERTIFICATE 6
+#define REALM_USERNAME_PASSWORD 7
+#define REALM_SERVER_SIDE 8
+
+/* 802.11u 3GPP PLMN */
+#define G3PP_GUD_VERSION 0
+#define G3PP_PLMN_LIST_IE 0
+
+/* hotspot2.0 indication element (vendor specific) */
+BWL_PRE_PACKED_STRUCT struct hs20_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 config;
+} BWL_POST_PACKED_STRUCT;
+typedef struct hs20_ie hs20_ie_t;
+#define HS20_IE_LEN 5 /* HS20 IE length */
+
+/* IEEE 802.11 Annex E */
+typedef enum {
+ DOT11_2GHZ_20MHZ_CLASS_12 = 81, /* Ch 1-11 */
+ DOT11_5GHZ_20MHZ_CLASS_1 = 115, /* Ch 36-48 */
+ DOT11_5GHZ_20MHZ_CLASS_2_DFS = 118, /* Ch 52-64 */
+ DOT11_5GHZ_20MHZ_CLASS_3 = 124, /* Ch 149-161 */
+ DOT11_5GHZ_20MHZ_CLASS_4_DFS = 121, /* Ch 100-140 */
+ DOT11_5GHZ_20MHZ_CLASS_5 = 125, /* Ch 149-165 */
+ DOT11_5GHZ_40MHZ_CLASS_22 = 116, /* Ch 36-44, lower */
+ DOT11_5GHZ_40MHZ_CLASS_23_DFS = 119, /* Ch 52-60, lower */
+ DOT11_5GHZ_40MHZ_CLASS_24_DFS = 122, /* Ch 100-132, lower */
+ DOT11_5GHZ_40MHZ_CLASS_25 = 126, /* Ch 149-157, lower */
+ DOT11_5GHZ_40MHZ_CLASS_27 = 117, /* Ch 40-48, upper */
+ DOT11_5GHZ_40MHZ_CLASS_28_DFS = 120, /* Ch 56-64, upper */
+ DOT11_5GHZ_40MHZ_CLASS_29_DFS = 123, /* Ch 104-136, upper */
+ DOT11_5GHZ_40MHZ_CLASS_30 = 127, /* Ch 153-161, upper */
+ DOT11_2GHZ_40MHZ_CLASS_32 = 83, /* Ch 1-7, lower */
+ DOT11_2GHZ_40MHZ_CLASS_33 = 84, /* Ch 5-11, upper */
+} dot11_op_class_t;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _802_11_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h b/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h
new file mode 100644
index 000000000000..cb27cf90a22f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h
@@ -0,0 +1,45 @@
+/*
+ * BT-AMP (BlueTooth Alternate Mac and Phy) 802.11 PAL (Protocol Adaptation Layer)
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: 802.11_bta.h 382882 2013-02-04 23:24:31Z $
+*/
+
+#ifndef _802_11_BTA_H_
+#define _802_11_BTA_H_
+
+#define BT_SIG_SNAP_MPROT "\xAA\xAA\x03\x00\x19\x58"
+
+/* BT-AMP 802.11 PAL Protocols */
+#define BTA_PROT_L2CAP 1
+#define BTA_PROT_ACTIVITY_REPORT 2
+#define BTA_PROT_SECURITY 3
+#define BTA_PROT_LINK_SUPERVISION_REQUEST 4
+#define BTA_PROT_LINK_SUPERVISION_REPLY 5
+
+/* BT-AMP 802.11 PAL AMP_ASSOC Type IDs */
+#define BTA_TYPE_ID_MAC_ADDRESS 1
+#define BTA_TYPE_ID_PREFERRED_CHANNELS 2
+#define BTA_TYPE_ID_CONNECTED_CHANNELS 3
+#define BTA_TYPE_ID_CAPABILITIES 4
+#define BTA_TYPE_ID_VERSION 5
+#endif /* _802_11_bta_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11e.h b/drivers/net/wireless/bcmdhd/include/proto/802.11e.h
new file mode 100644
index 000000000000..4caab96752f4
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/802.11e.h
@@ -0,0 +1,132 @@
+/*
+ * 802.11e protocol header file
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: 802.11e.h 382883 2013-02-04 23:26:09Z $
+ */
+
+#ifndef _802_11e_H_
+#define _802_11e_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/* WME Traffic Specification (TSPEC) element */
+#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */
+#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */
+
+#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */
+#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */
+#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */
+#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */
+
+BWL_PRE_PACKED_STRUCT struct tsinfo {
+ uint8 octets[3];
+} BWL_POST_PACKED_STRUCT;
+
+typedef struct tsinfo tsinfo_t;
+
+/* 802.11e TSPEC IE */
+typedef BWL_PRE_PACKED_STRUCT struct tspec {
+ uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */
+ uint8 type; /* WME_TYPE */
+ uint8 subtype; /* WME_SUBTYPE_TSPEC */
+ uint8 version; /* WME_VERSION */
+ tsinfo_t tsinfo; /* TS Info bit field */
+ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */
+ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */
+ uint32 min_srv_interval; /* Minimum Service Interval (us) */
+ uint32 max_srv_interval; /* Maximum Service Interval (us) */
+ uint32 inactivity_interval; /* Inactivity Interval (us) */
+ uint32 suspension_interval; /* Suspension Interval (us) */
+ uint32 srv_start_time; /* Service Start Time (us) */
+ uint32 min_data_rate; /* Minimum Data Rate (bps) */
+ uint32 mean_data_rate; /* Mean Data Rate (bps) */
+ uint32 peak_data_rate; /* Peak Data Rate (bps) */
+ uint32 max_burst_size; /* Maximum Burst Size (bytes) */
+ uint32 delay_bound; /* Delay Bound (us) */
+ uint32 min_phy_rate; /* Minimum PHY Rate (bps) */
+ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0-8.0) */
+ uint16 medium_time; /* Medium Time (32 us/s periods) */
+} BWL_POST_PACKED_STRUCT tspec_t;
+
+#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */
+
+/* ts_info */
+/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */
+#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */
+#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */
+#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */
+#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */
+#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */
+#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */
+#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */
+#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */
+#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */
+#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */
+#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */
+#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */
+/* TS info. user priority mask */
+#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT)
+
+/* Macro to get/set bit(s) field in TSINFO */
+#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT)
+#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \
+ TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT)
+#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT)
+#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \
+ TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT)
+
+#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \
+ ((id) << TS_INFO_TID_SHIFT))
+#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \
+ ((prio) << TS_INFO_USER_PRIO_SHIFT))
+
+/* 802.11e QBSS Load IE */
+#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */
+#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */
+
+#define CAC_ADDTS_RESP_TIMEOUT 1000 /* default ADDTS response timeout in ms */
+ /* DEFVAL dot11ADDTSResponseTimeout = 1s */
+
+/* 802.11e ADDTS status code */
+#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */
+#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */
+#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */
+#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE 47 /* ADDTS refused but could retry later */
+
+/* 802.11e DELTS status code */
+#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */
+#define DOT11E_STATUS_END_TS 37 /* END TS */
+#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */
+#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _802_11e_CAC_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.1d.h b/drivers/net/wireless/bcmdhd/include/proto/802.1d.h
new file mode 100644
index 000000000000..e4e98eb9721f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/802.1d.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * Fundamental types and constants relating to 802.1D
+ *
+ * $Id: 802.1d.h 382882 2013-02-04 23:24:31Z $
+ */
+
+#ifndef _802_1_D_
+#define _802_1_D_
+
+/* 802.1D priority defines */
+#define PRIO_8021D_NONE 2 /* None = - */
+#define PRIO_8021D_BK 1 /* BK - Background */
+#define PRIO_8021D_BE 0 /* BE - Best-effort */
+#define PRIO_8021D_EE 3 /* EE - Excellent-effort */
+#define PRIO_8021D_CL 4 /* CL - Controlled Load */
+#define PRIO_8021D_VI 5 /* Vi - Video */
+#define PRIO_8021D_VO 6 /* Vo - Voice */
+#define PRIO_8021D_NC 7 /* NC - Network Control */
+#define MAXPRIO 7 /* 0-7 */
+#define NUMPRIO (MAXPRIO + 1)
+
+#define ALLPRIO -1 /* All prioirty */
+
+/* Converts prio to precedence since the numerical value of
+ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped.
+ */
+#define PRIO2PREC(prio) \
+ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio))
+
+#endif /* _802_1_D__ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.3.h b/drivers/net/wireless/bcmdhd/include/proto/802.3.h
new file mode 100644
index 000000000000..991b85eb62f6
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/802.3.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * Fundamental constants relating to 802.3
+ *
+ * $Id: 802.3.h 417943 2013-08-13 07:54:04Z $
+ */
+
+#ifndef _802_3_h_
+#define _802_3_h_
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#define SNAP_HDR_LEN 6 /* 802.3 SNAP header length */
+#define DOT3_OUI_LEN 3 /* 802.3 oui length */
+
+BWL_PRE_PACKED_STRUCT struct dot3_mac_llc_snap_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN]; /* dest mac */
+ uint8 ether_shost[ETHER_ADDR_LEN]; /* src mac */
+ uint16 length; /* frame length incl header */
+ uint8 dsap; /* always 0xAA */
+ uint8 ssap; /* always 0xAA */
+ uint8 ctl; /* always 0x03 */
+ uint8 oui[DOT3_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00
+ * Bridge-Tunnel: 0x00 0x00 0xF8
+ */
+ uint16 type; /* ethertype */
+} BWL_POST_PACKED_STRUCT;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* #ifndef _802_3_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
new file mode 100644
index 000000000000..891b44d299fb
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
@@ -0,0 +1,112 @@
+/*
+ * Broadcom Ethernettype protocol definitions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmeth.h 382882 2013-02-04 23:24:31Z $
+ */
+
+/*
+ * Broadcom Ethernet protocol defines
+ */
+
+#ifndef _BCMETH_H_
+#define _BCMETH_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* ETHER_TYPE_BRCM is defined in ethernet.h */
+
+/*
+ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field
+ * in one of two formats: (only subtypes 32768-65535 are in use now)
+ *
+ * subtypes 0-32767:
+ * 8 bit subtype (0-127)
+ * 8 bit length in bytes (0-255)
+ *
+ * subtypes 32768-65535:
+ * 16 bit big-endian subtype
+ * 16 bit big-endian length in bytes (0-65535)
+ *
+ * length is the number of additional bytes beyond the 4 or 6 byte header
+ *
+ * Reserved values:
+ * 0 reserved
+ * 5-15 reserved for iLine protocol assignments
+ * 17-126 reserved, assignable
+ * 127 reserved
+ * 32768 reserved
+ * 32769-65534 reserved, assignable
+ * 65535 reserved
+ */
+
+/*
+ * While adding the subtypes and their specific processing code make sure
+ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition
+ */
+
+#define BCMILCP_SUBTYPE_RATE 1
+#define BCMILCP_SUBTYPE_LINK 2
+#define BCMILCP_SUBTYPE_CSA 3
+#define BCMILCP_SUBTYPE_LARQ 4
+#define BCMILCP_SUBTYPE_VENDOR 5
+#define BCMILCP_SUBTYPE_FLH 17
+
+#define BCMILCP_SUBTYPE_VENDOR_LONG 32769
+#define BCMILCP_SUBTYPE_CERT 32770
+#define BCMILCP_SUBTYPE_SES 32771
+
+
+#define BCMILCP_BCM_SUBTYPE_RESERVED 0
+#define BCMILCP_BCM_SUBTYPE_EVENT 1
+#define BCMILCP_BCM_SUBTYPE_SES 2
+/*
+ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded
+ * within BCMILCP_BCM_SUBTYPE_EVENT type messages
+ */
+/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */
+#define BCMILCP_BCM_SUBTYPE_DPT 4
+
+#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8
+#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0
+
+/* These fields are stored in network order */
+typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr
+{
+ uint16 subtype; /* Vendor specific..32769 */
+ uint16 length;
+ uint8 version; /* Version is 0 */
+ uint8 oui[3]; /* Broadcom OUI */
+ /* user specific Data */
+ uint16 usr_subtype;
+} BWL_POST_PACKED_STRUCT bcmeth_hdr_t;
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _BCMETH_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h
new file mode 100644
index 000000000000..2791636b8ce2
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h
@@ -0,0 +1,517 @@
+/*
+ * Broadcom Event protocol definitions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * Dependencies: proto/bcmeth.h
+ *
+ * $Id: bcmevent.h 662961 2016-11-24 01:22:35Z $
+ *
+ */
+
+/*
+ * Broadcom Ethernet Events protocol defines
+ *
+ */
+
+#ifndef _BCMEVENT_H_
+#define _BCMEVENT_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+/* #include <ethernet.h> -- TODO: req., excluded to overwhelming coupling (break up ethernet.h) */
+#include <proto/bcmeth.h>
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#define BCM_EVENT_MSG_VERSION 2 /* wl_event_msg_t struct version */
+#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */
+
+/* flags */
+#define WLC_EVENT_MSG_LINK 0x01 /* link is up */
+#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */
+#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */
+#define WLC_EVENT_MSG_UNKBSS 0x08 /* unknown source bsscfg */
+#define WLC_EVENT_MSG_UNKIF 0x10 /* unknown source OS i/f */
+
+/* these fields are stored in network order */
+
+/* version 1 */
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint16 version;
+ uint16 flags; /* see flags below */
+ uint32 event_type; /* Message (see below) */
+ uint32 status; /* Status code (see below) */
+ uint32 reason; /* Reason code (if applicable) */
+ uint32 auth_type; /* WLC_E_AUTH */
+ uint32 datalen; /* data buf */
+ struct ether_addr addr; /* Station address (if applicable) */
+ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */
+} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t;
+
+/* the current version */
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint16 version;
+ uint16 flags; /* see flags below */
+ uint32 event_type; /* Message (see below) */
+ uint32 status; /* Status code (see below) */
+ uint32 reason; /* Reason code (if applicable) */
+ uint32 auth_type; /* WLC_E_AUTH */
+ uint32 datalen; /* data buf */
+ struct ether_addr addr; /* Station address (if applicable) */
+ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */
+ uint8 ifidx; /* destination OS i/f index */
+ uint8 bsscfgidx; /* source bsscfg index */
+} BWL_POST_PACKED_STRUCT wl_event_msg_t;
+
+/* used by driver msgs */
+typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
+ struct ether_header eth;
+ bcmeth_hdr_t bcm_hdr;
+ wl_event_msg_t event;
+ /* data portion follows */
+} BWL_POST_PACKED_STRUCT bcm_event_t;
+
+#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header))
+
+/* Event messages */
+#define WLC_E_SET_SSID 0 /* indicates status of set SSID */
+#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */
+#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */
+#define WLC_E_AUTH 3 /* 802.11 AUTH request */
+#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */
+#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */
+#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */
+#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */
+#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */
+#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */
+#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */
+#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */
+#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */
+#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */
+#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */
+#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */
+#define WLC_E_LINK 16 /* generic link indication */
+#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */
+#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */
+#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */
+#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */
+#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */
+#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */
+#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */
+#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */
+#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */
+#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */
+#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */
+#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */
+#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */
+#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */
+#define WLC_E_BCNLOST_MSG 31 /* indicate to host loss of beacon */
+#define WLC_E_ROAM_PREP 32 /* before attempting to roam */
+#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */
+#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */
+#define WLC_E_RESET_COMPLETE 35
+#define WLC_E_JOIN_START 36
+#define WLC_E_ROAM_START 37
+#define WLC_E_ASSOC_START 38
+#define WLC_E_IBSS_ASSOC 39
+#define WLC_E_RADIO 40
+#define WLC_E_PSM_WATCHDOG 41 /* PSM microcode watchdog fired */
+#define WLC_E_PROBREQ_MSG 44 /* probe request received */
+#define WLC_E_SCAN_CONFIRM_IND 45
+#define WLC_E_PSK_SUP 46 /* WPA Handshake fail */
+#define WLC_E_COUNTRY_CODE_CHANGED 47
+#define WLC_E_EXCEEDED_MEDIUM_TIME 48 /* WMMAC excedded medium time */
+#define WLC_E_ICV_ERROR 49 /* WEP ICV error occurred */
+#define WLC_E_UNICAST_DECODE_ERROR 50 /* Unsupported unicast encrypted frame */
+#define WLC_E_MULTICAST_DECODE_ERROR 51 /* Unsupported multicast encrypted frame */
+#define WLC_E_TRACE 52
+#define WLC_E_IF 54 /* I/F change (for dongle host notification) */
+#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55 /* listen state expires */
+#define WLC_E_RSSI 56 /* indicate RSSI change based on configured levels */
+/* PFN best network batching event, conflict/share with WLC_E_PFN_SCAN_COMPLETE */
+#define WLC_E_PFN_BEST_BATCHING 57
+#define WLC_E_PFN_SCAN_COMPLETE 57 /* PFN completed scan of network list */
+/* PFN best network batching event, conflict/share with WLC_E_PFN_SCAN_COMPLETE */
+#define WLC_E_PFN_BEST_BATCHING 57
+#define WLC_E_EXTLOG_MSG 58
+#define WLC_E_ACTION_FRAME 59 /* Action frame Rx */
+#define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */
+#define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */
+#define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */
+#define WLC_E_CHANNEL_ADOPTED 63
+#define WLC_E_AP_STARTED 64 /* AP started */
+#define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */
+#define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */
+#define WLC_E_WAI_STA_EVENT 67 /* WAI stations event */
+#define WLC_E_WAI_MSG 68 /* event encapsulating an WAI message */
+#define WLC_E_ESCAN_RESULT 69 /* escan result event */
+#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 /* action frame off channel complete */
+#define WLC_E_PROBRESP_MSG 71 /* probe response received */
+#define WLC_E_P2P_PROBREQ_MSG 72 /* P2P Probe request received */
+#define WLC_E_DCS_REQUEST 73
+#define WLC_E_FIFO_CREDIT_MAP 74 /* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */
+#define WLC_E_ACTION_FRAME_RX 75 /* Received action frame event WITH
+ * wl_event_rx_frame_data_t header
+ */
+#define WLC_E_WAKE_EVENT 76 /* Wake Event timer fired, used for wake WLAN test mode */
+#define WLC_E_RM_COMPLETE 77 /* Radio measurement complete */
+#define WLC_E_HTSFSYNC 78 /* Synchronize TSF with the host */
+#define WLC_E_OVERLAY_REQ 79 /* request an overlay IOCTL/iovar from the host */
+#define WLC_E_CSA_COMPLETE_IND 80 /* 802.11 CHANNEL SWITCH ACTION completed */
+#define WLC_E_EXCESS_PM_WAKE_EVENT 81 /* excess PM Wake Event to inform host */
+#define WLC_E_PFN_SCAN_NONE 82 /* no PFN networks around */
+/* PFN BSSID network found event, conflict/share with WLC_E_PFN_SCAN_NONE */
+#define WLC_E_PFN_BSSID_NET_FOUND 82
+#define WLC_E_PFN_SCAN_ALLGONE 83 /* last found PFN network gets lost */
+/* PFN BSSID network lost event, conflict/share with WLC_E_PFN_SCAN_ALLGONE */
+#define WLC_E_PFN_BSSID_NET_LOST 83
+#define WLC_E_GTK_PLUMBED 84
+#define WLC_E_ASSOC_IND_NDIS 85 /* 802.11 ASSOC indication for NDIS only */
+#define WLC_E_REASSOC_IND_NDIS 86 /* 802.11 REASSOC indication for NDIS only */
+#define WLC_E_ASSOC_REQ_IE 87
+#define WLC_E_ASSOC_RESP_IE 88
+#define WLC_E_ASSOC_RECREATED 89 /* association recreated on resume */
+#define WLC_E_ACTION_FRAME_RX_NDIS 90 /* rx action frame event for NDIS only */
+#define WLC_E_AUTH_REQ 91 /* authentication request received */
+#define WLC_E_TDLS_PEER_EVENT 92 /* discovered peer, connected/disconnected peer */
+#define WLC_E_SPEEDY_RECREATE_FAIL 93 /* fast assoc recreation failed */
+#define WLC_E_NATIVE 94 /* port-specific event and payload (e.g. NDIS) */
+#define WLC_E_PKTDELAY_IND 95 /* event for tx pkt delay suddently jump */
+#define WLC_E_PSTA_PRIMARY_INTF_IND 99 /* psta primary interface indication */
+#define WLC_E_NAN 100 /* NAN event */
+#define WLC_E_BEACON_FRAME_RX 101
+#define WLC_E_SERVICE_FOUND 102 /* desired service found */
+#define WLC_E_GAS_FRAGMENT_RX 103 /* GAS fragment received */
+#define WLC_E_GAS_COMPLETE 104 /* GAS sessions all complete */
+#define WLC_E_P2PO_ADD_DEVICE 105 /* New device found by p2p offload */
+#define WLC_E_P2PO_DEL_DEVICE 106 /* device has been removed by p2p offload */
+#define WLC_E_WNM_STA_SLEEP 107 /* WNM event to notify STA enter sleep mode */
+#define WLC_E_TXFAIL_THRESH 108 /* Indication of MAC tx failures (exhaustion of
+ * 802.11 retries) exceeding threshold(s)
+ */
+#define WLC_E_PROXD 109 /* Proximity Detection event */
+#define WLC_E_IBSS_COALESCE 110 /* IBSS Coalescing */
+#define WLC_E_AIBSS_TXFAIL 110 /* TXFAIL event for AIBSS, re using event 110 */
+#define WLC_E_CSA_START_IND 121
+#define WLC_E_CSA_DONE_IND 122
+#define WLC_E_CSA_FAILURE_IND 123
+#define WLC_E_CCA_CHAN_QUAL 124 /* CCA based channel quality report */
+#define WLC_E_BSSID 125 /* to report change in BSSID while roaming */
+#define WLC_E_TX_STAT_ERROR 126 /* tx error indication */
+#define WLC_E_BCMC_CREDIT_SUPPORT 127 /* credit check for BCMC supported */
+#define WLC_E_RMC_EVENT 139 /* RMC event */
+#define WLC_E_PKT_FILTER 164 /* Packet filter event */
+#define WLC_E_LAST 165 /* highest val + 1 for range checking */
+
+#if (WLC_E_LAST > 165)
+#error "WLC_E_LAST: Invalid value for last event; must be <= 140."
+#endif /* WLC_E_LAST */
+
+
+/* Table of event name strings for UIs and debugging dumps */
+typedef struct {
+ uint event;
+ const char *name;
+} bcmevent_name_t;
+
+extern const bcmevent_name_t bcmevent_names[];
+extern const int bcmevent_names_size;
+
+/* validate if the event is proper and if valid copy event header to event */
+extern int is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
+ wl_event_msg_t *out_event);
+
+/* Event status codes */
+#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */
+#define WLC_E_STATUS_FAIL 1 /* operation failed */
+#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */
+#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */
+#define WLC_E_STATUS_ABORT 4 /* operation was aborted */
+#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */
+#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */
+#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */
+#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */
+#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */
+#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */
+#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */
+#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */
+#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */
+#define WLC_E_STATUS_CS_ABORT 15 /* abort channel select */
+#define WLC_E_STATUS_ERROR 16 /* request failed due to error */
+
+/* roam reason codes */
+#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */
+#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */
+#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */
+#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */
+#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */
+
+/* Roam codes used primarily by CCX */
+#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */
+#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */
+#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */
+#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */
+#define WLC_E_REASON_MINTXRATE 9 /* roamed because at mintxrate for too long */
+#define WLC_E_REASON_TXFAIL 10 /* We can hear AP, but AP can't hear us */
+#define WLC_E_REASON_REQUESTED_ROAM 11 /* roamed due to BSS Mgmt Transition REQ by AP */
+
+/* prune reason codes */
+#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* encryption mismatch */
+#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */
+#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */
+#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */
+#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */
+#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */
+#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */
+#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */
+#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */
+#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */
+#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */
+#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */
+#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */
+#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */
+#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */
+
+/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */
+#define WLC_E_SUP_OTHER 0 /* Other reason */
+#define WLC_E_SUP_DECRYPT_KEY_DATA 1 /* Decryption of key data failed */
+#define WLC_E_SUP_BAD_UCAST_WEP128 2 /* Illegal use of ucast WEP128 */
+#define WLC_E_SUP_BAD_UCAST_WEP40 3 /* Illegal use of ucast WEP40 */
+#define WLC_E_SUP_UNSUP_KEY_LEN 4 /* Unsupported key length */
+#define WLC_E_SUP_PW_KEY_CIPHER 5 /* Unicast cipher mismatch in pairwise key */
+#define WLC_E_SUP_MSG3_TOO_MANY_IE 6 /* WPA IE contains > 1 RSN IE in key msg 3 */
+#define WLC_E_SUP_MSG3_IE_MISMATCH 7 /* WPA IE mismatch in key message 3 */
+#define WLC_E_SUP_NO_INSTALL_FLAG 8 /* INSTALL flag unset in 4-way msg */
+#define WLC_E_SUP_MSG3_NO_GTK 9 /* encapsulated GTK missing from msg 3 */
+#define WLC_E_SUP_GRP_KEY_CIPHER 10 /* Multicast cipher mismatch in group key */
+#define WLC_E_SUP_GRP_MSG1_NO_GTK 11 /* encapsulated GTK missing from group msg 1 */
+#define WLC_E_SUP_GTK_DECRYPT_FAIL 12 /* GTK decrypt failure */
+#define WLC_E_SUP_SEND_FAIL 13 /* message send failure */
+#define WLC_E_SUP_DEAUTH 14 /* received FC_DEAUTH */
+#define WLC_E_SUP_WPA_PSK_TMO 15 /* WPA PSK 4-way handshake timeout */
+
+/* Event data for events that include frames received over the air */
+/* WLC_E_PROBRESP_MSG
+ * WLC_E_P2P_PROBREQ_MSG
+ * WLC_E_ACTION_FRAME_RX
+ */
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data {
+ uint16 version;
+ uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */
+ int32 rssi;
+ uint32 mactime;
+ uint32 rate;
+} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t;
+
+#define BCM_RX_FRAME_DATA_VERSION 1
+
+/* WLC_E_IF event data */
+typedef struct wl_event_data_if {
+ uint8 ifidx; /* RTE virtual device index (for dongle) */
+ uint8 opcode; /* see I/F opcode */
+ uint8 reserved; /* bit mask (WLC_E_IF_FLAGS_XXX ) */
+ uint8 bssidx; /* bsscfg index */
+ uint8 role; /* see I/F role */
+} wl_event_data_if_t;
+
+/* opcode in WLC_E_IF event */
+#define WLC_E_IF_ADD 1 /* bsscfg add */
+#define WLC_E_IF_DEL 2 /* bsscfg delete */
+#define WLC_E_IF_CHANGE 3 /* bsscfg role change */
+
+/* I/F role code in WLC_E_IF event */
+#define WLC_E_IF_ROLE_STA 0 /* Infra STA */
+#define WLC_E_IF_ROLE_AP 1 /* Access Point */
+#define WLC_E_IF_ROLE_WDS 2 /* WDS link */
+#define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */
+#define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */
+#define WLC_E_IF_ROLE_IBSS 8 /* IBSS */
+
+/* WLC_E_RSSI event data */
+typedef struct wl_event_data_rssi {
+ int32 rssi;
+ int32 snr;
+ int32 noise;
+} wl_event_data_rssi_t;
+
+/* WLC_E_IF flag */
+#define WLC_E_IF_FLAGS_BSSCFG_NOIF 0x1 /* no host I/F creation needed */
+
+/* Reason codes for LINK */
+#define WLC_E_LINK_BCN_LOSS 1 /* Link down because of beacon loss */
+#define WLC_E_LINK_DISASSOC 2 /* Link down because of disassoc */
+#define WLC_E_LINK_ASSOC_REC 3 /* Link down because assoc recreate failed */
+#define WLC_E_LINK_BSSCFG_DIS 4 /* Link down due to bsscfg down */
+
+/* reason codes for WLC_E_OVERLAY_REQ event */
+#define WLC_E_OVL_DOWNLOAD 0 /* overlay download request */
+#define WLC_E_OVL_UPDATE_IND 1 /* device indication of host overlay update */
+
+/* reason codes for WLC_E_TDLS_PEER_EVENT event */
+#define WLC_E_TDLS_PEER_DISCOVERED 0 /* peer is ready to establish TDLS */
+#define WLC_E_TDLS_PEER_CONNECTED 1
+#define WLC_E_TDLS_PEER_DISCONNECTED 2
+
+#ifdef WLTDLS
+/* TDLS Action Category code */
+#define TDLS_AF_CATEGORY 12
+/* Wi-Fi Display (WFD) Vendor Specific Category */
+/* used for WFD Tunneled Probe Request and Response */
+#define TDLS_VENDOR_SPECIFIC 127
+/* TDLS Action Field Values */
+#define TDLS_ACTION_SETUP_REQ 0
+#define TDLS_ACTION_SETUP_RESP 1
+#define TDLS_ACTION_SETUP_CONFIRM 2
+#define TDLS_ACTION_TEARDOWN 3
+#define WLAN_TDLS_SET_PROBE_WFD_IE 11
+#define WLAN_TDLS_SET_SETUP_WFD_IE 12
+#endif
+
+
+/* reason codes for WLC_E_RMC_EVENT event */
+#define WLC_E_REASON_RMC_NONE 0
+#define WLC_E_REASON_RMC_AR_LOST 1
+#define WLC_E_REASON_RMC_AR_NO_ACK 2
+
+
+/* WLC_E_PKT_FILTER event codes */
+#define WLC_E_PKT_FILTER_TIMEOUT 1 /* Matching packet not received in last timeout seconds */
+
+/* GAS event data */
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas {
+ uint16 channel; /* channel of GAS protocol */
+ uint8 dialog_token; /* GAS dialog token */
+ uint8 fragment_id; /* fragment id */
+ uint16 status_code; /* status code on GAS completion */
+ uint16 data_len; /* length of data to follow */
+ uint8 data[1]; /* variable length specified by data_len */
+} BWL_POST_PACKED_STRUCT wl_event_gas_t;
+
+/* service discovery TLV */
+typedef BWL_PRE_PACKED_STRUCT struct wl_sd_tlv {
+ uint16 length; /* length of response_data */
+ uint8 protocol; /* service protocol type */
+ uint8 transaction_id; /* service transaction id */
+ uint8 status_code; /* status code */
+ uint8 data[1]; /* response data */
+} BWL_POST_PACKED_STRUCT wl_sd_tlv_t;
+
+/* service discovery event data */
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_sd {
+ uint16 channel; /* channel */
+ uint8 count; /* number of tlvs */
+ wl_sd_tlv_t tlv[1]; /* service discovery TLV */
+} BWL_POST_PACKED_STRUCT wl_event_sd_t;
+
+/* Reason codes for WLC_E_PROXD */
+#define WLC_E_PROXD_FOUND 1 /* Found a proximity device */
+#define WLC_E_PROXD_GONE 2 /* Lost a proximity device */
+#define WLC_E_PROXD_START 3 /* used by: target */
+#define WLC_E_PROXD_STOP 4 /* used by: target */
+#define WLC_E_PROXD_COMPLETED 5 /* used by: initiator completed */
+#define WLC_E_PROXD_ERROR 6 /* used by both initiator and target */
+#define WLC_E_PROXD_COLLECT_START 7 /* used by: target & initiator */
+#define WLC_E_PROXD_COLLECT_STOP 8 /* used by: target */
+#define WLC_E_PROXD_COLLECT_COMPLETED 9 /* used by: initiator completed */
+#define WLC_E_PROXD_COLLECT_ERROR 10 /* used by both initiator and target */
+#define WLC_E_PROXD_NAN_EVENT 11 /* used by both initiator and target */
+
+/* proxd_event data */
+typedef struct ftm_sample {
+ uint32 value; /* RTT in ns */
+ int8 rssi; /* RSSI */
+} ftm_sample_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct proxd_event_data {
+ uint16 ver; /* version */
+ uint16 mode; /* mode: target/initiator */
+ uint16 method; /* method: rssi/TOF/AOA */
+ uint8 err_code; /* error classification */
+ uint8 TOF_type; /* one way or two way TOF */
+ uint8 OFDM_frame_type; /* legacy or VHT */
+ uint8 bandwidth; /* Bandwidth is 20, 40,80, MHZ */
+ struct ether_addr peer_mac; /* (e.g for tgt:initiator's */
+ uint32 distance; /* dst to tgt, units meter */
+ uint32 meanrtt; /* mean delta */
+ uint32 modertt; /* Mode delta */
+ uint32 medianrtt; /* median RTT */
+ uint32 sdrtt; /* Standard deviation of RTT */
+ int gdcalcresult; /* Software or Hardware Kind of redundant, but if */
+ /* frame type is VHT, then we should do it by hardware */
+ int16 avg_rssi; /* avg rssi accroos the ftm frames */
+ int16 validfrmcnt; /* Firmware's valid frame counts */
+ char *peer_router_info; /* Peer router information if available in TLV, */
+ /* We will add this field later */
+ int32 var1; /* average of group delay */
+ int32 var2; /* average of threshold crossing */
+ int32 var3; /* difference between group delay and threshold crossing */
+ /* raw Fine Time Measurements (ftm) data */
+ uint16 ftm_unit; /* ftm cnt resolution in picoseconds , 6250ps - default */
+ uint16 ftm_cnt; /* num of rtd measurments/length in the ftm buffer */
+ ftm_sample_t ftm_buff[1]; /* 1 ... ftm_cnt */
+} BWL_POST_PACKED_STRUCT wl_proxd_event_data_t;
+
+
+/* Video Traffic Interference Monitor Event */
+#define INTFER_EVENT_VERSION 1
+#define INTFER_STREAM_TYPE_NONTCP 1
+#define INTFER_STREAM_TYPE_TCP 2
+#define WLINTFER_STATS_NSMPLS 4
+typedef struct wl_intfer_event {
+ uint16 version; /* version */
+ uint16 status; /* status */
+ uint8 txfail_histo[WLINTFER_STATS_NSMPLS]; /* txfail histo */
+} wl_intfer_event_t;
+
+/* WLC_E_PSTA_PRIMARY_INTF_IND event data */
+typedef struct wl_psta_primary_intf_event {
+ struct ether_addr prim_ea; /* primary intf ether addr */
+} wl_psta_primary_intf_event_t;
+
+/* ********** NAN protocol events/subevents ********** */
+#define NAN_EVENT_BUFFER_SIZE 512 /* max size */
+/* nan application events to the host driver */
+enum nan_app_events {
+ WL_NAN_EVENT_START = 1, /* NAN cluster started */
+ WL_NAN_EVENT_JOIN = 2, /* Joined to a NAN cluster */
+ WL_NAN_EVENT_ROLE = 3, /* Role or State changed */
+ WL_NAN_EVENT_SCAN_COMPLETE = 4,
+ WL_NAN_EVENT_DISCOVERY_RESULT = 5,
+ WL_NAN_EVENT_REPLIED = 6,
+ WL_NAN_EVENT_TERMINATED = 7, /* the instance ID will be present in the ev data */
+ WL_NAN_EVENT_RECEIVE = 8,
+ WL_NAN_EVENT_STATUS_CHG = 9, /* generated on any change in nan_mac status */
+ WL_NAN_EVENT_MERGE = 10, /* Merged to a NAN cluster */
+ WL_NAN_EVENT_STOP = 11, /* NAN stopped */
+ WL_NAN_EVENT_INVALID = 12, /* delimiter for max value */
+};
+#define IS_NAN_EVT_ON(var, evt) ((var & (1 << (evt-1))) != 0)
+/* ******************* end of NAN section *************** */
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _BCMEVENT_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h
new file mode 100644
index 000000000000..8d54b8bfe21d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * Fundamental constants relating to IP Protocol
+ *
+ * $Id: bcmip.h 457888 2014-02-25 03:34:39Z $
+ */
+
+#ifndef _bcmip_h_
+#define _bcmip_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/* IPV4 and IPV6 common */
+#define IP_VER_OFFSET 0x0 /* offset to version field */
+#define IP_VER_MASK 0xf0 /* version mask */
+#define IP_VER_SHIFT 4 /* version shift */
+#define IP_VER_4 4 /* version number for IPV4 */
+#define IP_VER_6 6 /* version number for IPV6 */
+
+#define IP_VER(ip_body) \
+ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT)
+
+#define IP_PROT_ICMP 0x1 /* ICMP protocol */
+#define IP_PROT_IGMP 0x2 /* IGMP protocol */
+#define IP_PROT_TCP 0x6 /* TCP protocol */
+#define IP_PROT_UDP 0x11 /* UDP protocol type */
+#define IP_PROT_ICMP6 0x3a /* ICMPv6 protocol type */
+
+/* IPV4 field offsets */
+#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */
+#define IPV4_TOS_OFFSET 1 /* type of service offset */
+#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */
+#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */
+#define IPV4_PROT_OFFSET 9 /* protocol type offset */
+#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */
+#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */
+#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */
+#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */
+#define IPV4_MIN_HEADER_LEN 20 /* Minimum size for an IP header (no options) */
+
+/* IPV4 field decodes */
+#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */
+#define IPV4_VER_SHIFT 4 /* IPV4 version shift */
+
+#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */
+#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK))
+
+#define IPV4_ADDR_LEN 4 /* IPV4 address length */
+
+#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \
+ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0)
+
+#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \
+ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff)
+
+#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */
+#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */
+
+#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET])
+
+#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */
+#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */
+
+#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */
+#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */
+#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */
+
+#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET])
+
+#define IPV4_FRAG_RESV 0x8000 /* Reserved */
+#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */
+#define IPV4_FRAG_MORE 0x2000 /* More fragments */
+#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */
+
+#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */
+
+/* IPV4 packet formats */
+BWL_PRE_PACKED_STRUCT struct ipv4_addr {
+ uint8 addr[IPV4_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct ipv4_hdr {
+ uint8 version_ihl; /* Version and Internet Header Length */
+ uint8 tos; /* Type Of Service */
+ uint16 tot_len; /* Number of bytes in packet (max 65535) */
+ uint16 id;
+ uint16 frag; /* 3 flag bits and fragment offset */
+ uint8 ttl; /* Time To Live */
+ uint8 prot; /* Protocol */
+ uint16 hdr_chksum; /* IP header checksum */
+ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */
+ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */
+} BWL_POST_PACKED_STRUCT;
+
+/* IPV6 field offsets */
+#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */
+#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */
+#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */
+#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */
+#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */
+
+/* IPV6 field decodes */
+#define IPV6_TRAFFIC_CLASS(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \
+ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4))
+
+#define IPV6_FLOW_LABEL(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \
+ (((uint8 *)(ipv6_body))[2] << 8) | \
+ (((uint8 *)(ipv6_body))[3]))
+
+#define IPV6_PAYLOAD_LEN(ipv6_body) \
+ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \
+ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1])
+
+#define IPV6_NEXT_HDR(ipv6_body) \
+ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET])
+
+#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body)
+
+#define IPV6_ADDR_LEN 16 /* IPV6 address length */
+
+/* IPV4 TOS or IPV6 Traffic Classifier or 0 */
+#define IP_TOS46(ip_body) \
+ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \
+ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0)
+
+#define IP_DSCP46(ip_body) (IP_TOS46(ip_body) >> IPV4_TOS_DSCP_SHIFT);
+
+/* IPV6 extension headers (options) */
+#define IPV6_EXTHDR_HOP 0
+#define IPV6_EXTHDR_ROUTING 43
+#define IPV6_EXTHDR_FRAGMENT 44
+#define IPV6_EXTHDR_AUTH 51
+#define IPV6_EXTHDR_NONE 59
+#define IPV6_EXTHDR_DEST 60
+
+#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \
+ ((prot) == IPV6_EXTHDR_ROUTING) || \
+ ((prot) == IPV6_EXTHDR_FRAGMENT) || \
+ ((prot) == IPV6_EXTHDR_AUTH) || \
+ ((prot) == IPV6_EXTHDR_NONE) || \
+ ((prot) == IPV6_EXTHDR_DEST))
+
+#define IPV6_MIN_HLEN 40
+
+#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3)
+
+BWL_PRE_PACKED_STRUCT struct ipv6_exthdr {
+ uint8 nexthdr;
+ uint8 hdrlen;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag {
+ uint8 nexthdr;
+ uint8 rsvd;
+ uint16 frag_off;
+ uint32 ident;
+} BWL_POST_PACKED_STRUCT;
+
+static INLINE int32
+ipv6_exthdr_len(uint8 *h, uint8 *proto)
+{
+ uint16 len = 0, hlen;
+ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h;
+
+ while (IPV6_EXTHDR(eh->nexthdr)) {
+ if (eh->nexthdr == IPV6_EXTHDR_NONE)
+ return -1;
+ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT)
+ hlen = 8;
+ else if (eh->nexthdr == IPV6_EXTHDR_AUTH)
+ hlen = (eh->hdrlen + 2) << 2;
+ else
+ hlen = IPV6_EXTHDR_LEN(eh);
+
+ len += hlen;
+ eh = (struct ipv6_exthdr *)(h + len);
+ }
+
+ *proto = eh->nexthdr;
+ return len;
+}
+
+#define IPV4_ISMULTI(a) (((a) & 0xf0000000) == 0xe0000000)
+
+#define IPV4_MCAST_TO_ETHER_MCAST(ipv4, ether) \
+{ \
+ ether[0] = 0x01; \
+ ether[1] = 0x00; \
+ ether[2] = 0x5E; \
+ ether[3] = (ipv4 & 0x7f0000) >> 16; \
+ ether[4] = (ipv4 & 0xff00) >> 8; \
+ ether[5] = (ipv4 & 0xff); \
+}
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#define IPV4_ADDR_STR "%d.%d.%d.%d"
+#define IPV4_ADDR_TO_STR(addr) ((uint32)addr & 0xff000000) >> 24, \
+ ((uint32)addr & 0x00ff0000) >> 16, \
+ ((uint32)addr & 0x0000ff00) >> 8, \
+ ((uint32)addr & 0x000000ff)
+
+#endif /* _bcmip_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmipv6.h b/drivers/net/wireless/bcmdhd/include/proto/bcmipv6.h
new file mode 100644
index 000000000000..7701ea2fe6b3
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/bcmipv6.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * Fundamental constants relating to Neighbor Discovery Protocol
+ *
+ * $Id: bcmipv6.h 399482 2013-04-30 09:24:37Z $
+ */
+
+#ifndef _bcmipv6_h_
+#define _bcmipv6_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* Extension headers */
+#define IPV6_EXT_HOP 0
+#define IPV6_EXT_ROUTE 43
+#define IPV6_EXT_FRAG 44
+#define IPV6_EXT_DEST 60
+#define IPV6_EXT_ESEC 50
+#define IPV6_EXT_AUTH 51
+
+/* Minimum size (extension header "word" length) */
+#define IPV6_EXT_WORD 8
+
+/* Offsets for most extension headers */
+#define IPV6_EXT_NEXTHDR 0
+#define IPV6_EXT_HDRLEN 1
+
+/* Constants specific to fragmentation header */
+#define IPV6_FRAG_MORE_MASK 0x0001
+#define IPV6_FRAG_MORE_SHIFT 0
+#define IPV6_FRAG_OFFS_MASK 0xfff8
+#define IPV6_FRAG_OFFS_SHIFT 3
+
+/* For icmpv6 */
+#define ICMPV6_HEADER_TYPE 0x3A
+#define ICMPV6_PKT_TYPE_NS 135
+#define ICMPV6_PKT_TYPE_NA 136
+
+#define ICMPV6_ND_OPT_TYPE_TARGET_MAC 2
+#define ICMPV6_ND_OPT_TYPE_SRC_MAC 1
+
+#define ICMPV6_ND_OPT_LEN_LINKADDR 1
+
+#define ICMPV6_ND_OPT_LEN_LINKADDR 1
+
+#define IPV6_VERSION 6
+#define IPV6_HOP_LIMIT 255
+
+#define IPV6_ADDR_NULL(a) ((a[0] | a[1] | a[2] | a[3] | a[4] | \
+ a[5] | a[6] | a[7] | a[8] | a[9] | \
+ a[10] | a[11] | a[12] | a[13] | \
+ a[14] | a[15]) == 0)
+
+#define IPV6_ADDR_LOCAL(a) (((a[0] == 0xfe) && (a[1] & 0x80))? TRUE: FALSE)
+
+/* IPV6 address */
+BWL_PRE_PACKED_STRUCT struct ipv6_addr {
+ uint8 addr[16];
+} BWL_POST_PACKED_STRUCT;
+
+
+/* ICMPV6 Header */
+BWL_PRE_PACKED_STRUCT struct icmp6_hdr {
+ uint8 icmp6_type;
+ uint8 icmp6_code;
+ uint16 icmp6_cksum;
+ BWL_PRE_PACKED_STRUCT union {
+ uint32 reserved;
+ BWL_PRE_PACKED_STRUCT struct nd_advt {
+ uint32 reserved1:5,
+ override:1,
+ solicited:1,
+ router:1,
+ reserved2:24;
+ } BWL_POST_PACKED_STRUCT nd_advt;
+ } BWL_POST_PACKED_STRUCT opt;
+} BWL_POST_PACKED_STRUCT;
+
+/* Ipv6 Header Format */
+BWL_PRE_PACKED_STRUCT struct ipv6_hdr {
+ uint8 priority:4,
+ version:4;
+ uint8 flow_lbl[3];
+ uint16 payload_len;
+ uint8 nexthdr;
+ uint8 hop_limit;
+ struct ipv6_addr saddr;
+ struct ipv6_addr daddr;
+} BWL_POST_PACKED_STRUCT;
+
+/* Neighbor Advertisement/Solicitation Packet Structure */
+BWL_PRE_PACKED_STRUCT struct nd_msg {
+ struct icmp6_hdr icmph;
+ struct ipv6_addr target;
+} BWL_POST_PACKED_STRUCT;
+
+
+/* Neighibor Solicitation/Advertisement Optional Structure */
+BWL_PRE_PACKED_STRUCT struct nd_msg_opt {
+ uint8 type;
+ uint8 len;
+ uint8 mac_addr[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+/* Ipv6 Fragmentation Header */
+BWL_PRE_PACKED_STRUCT struct ipv6_frag {
+ uint8 nexthdr;
+ uint8 reserved;
+ uint16 frag_offset;
+ uint32 ident;
+} BWL_POST_PACKED_STRUCT;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+static const struct ipv6_addr all_node_ipv6_maddr = {
+ { 0xff, 0x2, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 1
+ }};
+
+#define IPV6_ISMULTI(a) (a[0] == 0xff)
+
+#define IPV6_MCAST_TO_ETHER_MCAST(ipv6, ether) \
+{ \
+ ether[0] = 0x33; \
+ ether[1] = 0x33; \
+ ether[2] = ipv6[12]; \
+ ether[3] = ipv6[13]; \
+ ether[4] = ipv6[14]; \
+ ether[5] = ipv6[15]; \
+}
+
+#endif /* !defined(_bcmipv6_h_) */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmtcp.h b/drivers/net/wireless/bcmdhd/include/proto/bcmtcp.h
new file mode 100644
index 000000000000..20e7531ff0a8
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/bcmtcp.h
@@ -0,0 +1,90 @@
+/*
+ * Fundamental constants relating to TCP Protocol
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmtcp.h 457888 2014-02-25 03:34:39Z $
+ */
+
+#ifndef _bcmtcp_h_
+#define _bcmtcp_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+#define TCP_SRC_PORT_OFFSET 0 /* TCP source port offset */
+#define TCP_DEST_PORT_OFFSET 2 /* TCP dest port offset */
+#define TCP_SEQ_NUM_OFFSET 4 /* TCP sequence number offset */
+#define TCP_ACK_NUM_OFFSET 8 /* TCP acknowledgement number offset */
+#define TCP_HLEN_OFFSET 12 /* HLEN and reserved bits offset */
+#define TCP_FLAGS_OFFSET 13 /* FLAGS and reserved bits offset */
+#define TCP_CHKSUM_OFFSET 16 /* TCP body checksum offset */
+
+#define TCP_PORT_LEN 2 /* TCP port field length */
+
+/* 8bit TCP flag field */
+#define TCP_FLAG_URG 0x20
+#define TCP_FLAG_ACK 0x10
+#define TCP_FLAG_PSH 0x08
+#define TCP_FLAG_RST 0x04
+#define TCP_FLAG_SYN 0x02
+#define TCP_FLAG_FIN 0x01
+
+#define TCP_HLEN_MASK 0xf000
+#define TCP_HLEN_SHIFT 12
+
+/* These fields are stored in network order */
+BWL_PRE_PACKED_STRUCT struct bcmtcp_hdr
+{
+ uint16 src_port; /* Source Port Address */
+ uint16 dst_port; /* Destination Port Address */
+ uint32 seq_num; /* TCP Sequence Number */
+ uint32 ack_num; /* TCP Sequence Number */
+ uint16 hdrlen_rsvd_flags; /* Header length, reserved bits and flags */
+ uint16 tcpwin; /* TCP window */
+ uint16 chksum; /* Segment checksum with pseudoheader */
+ uint16 urg_ptr; /* Points to seq-num of byte following urg data */
+} BWL_POST_PACKED_STRUCT;
+
+#define TCP_MIN_HEADER_LEN 20
+
+#define TCP_HDRLEN_MASK 0xf0
+#define TCP_HDRLEN_SHIFT 4
+#define TCP_HDRLEN(hdrlen) (((hdrlen) & TCP_HDRLEN_MASK) >> TCP_HDRLEN_SHIFT)
+
+#define TCP_FLAGS_MASK 0x1f
+#define TCP_FLAGS(hdrlen) ((hdrlen) & TCP_FLAGS_MASK)
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+/* To address round up by 32bit. */
+#define IS_TCPSEQ_GE(a, b) ((a - b) < NBITVAL(31)) /* a >= b */
+#define IS_TCPSEQ_LE(a, b) ((b - a) < NBITVAL(31)) /* a =< b */
+#define IS_TCPSEQ_GT(a, b) !IS_TCPSEQ_LE(a, b) /* a > b */
+#define IS_TCPSEQ_LT(a, b) !IS_TCPSEQ_GE(a, b) /* a < b */
+
+#endif /* #ifndef _bcmtcp_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h b/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h
new file mode 100644
index 000000000000..3fdabec0d770
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h
@@ -0,0 +1,441 @@
+/*
+ * BT-AMP (BlueTooth Alternate Mac and Phy) HCI (Host/Controller Interface)
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bt_amp_hci.h 382882 2013-02-04 23:24:31Z $
+*/
+
+#ifndef _bt_amp_hci_h
+#define _bt_amp_hci_h
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/* AMP HCI CMD packet format */
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_cmd {
+ uint16 opcode;
+ uint8 plen;
+ uint8 parms[1];
+} BWL_POST_PACKED_STRUCT amp_hci_cmd_t;
+
+#define HCI_CMD_PREAMBLE_SIZE OFFSETOF(amp_hci_cmd_t, parms)
+#define HCI_CMD_DATA_SIZE 255
+
+/* AMP HCI CMD opcode layout */
+#define HCI_CMD_OPCODE(ogf, ocf) ((((ogf) & 0x3F) << 10) | ((ocf) & 0x03FF))
+#define HCI_CMD_OGF(opcode) ((uint8)(((opcode) >> 10) & 0x3F))
+#define HCI_CMD_OCF(opcode) ((opcode) & 0x03FF)
+
+/* AMP HCI command opcodes */
+#define HCI_Read_Failed_Contact_Counter HCI_CMD_OPCODE(0x05, 0x0001)
+#define HCI_Reset_Failed_Contact_Counter HCI_CMD_OPCODE(0x05, 0x0002)
+#define HCI_Read_Link_Quality HCI_CMD_OPCODE(0x05, 0x0003)
+#define HCI_Read_Local_AMP_Info HCI_CMD_OPCODE(0x05, 0x0009)
+#define HCI_Read_Local_AMP_ASSOC HCI_CMD_OPCODE(0x05, 0x000A)
+#define HCI_Write_Remote_AMP_ASSOC HCI_CMD_OPCODE(0x05, 0x000B)
+#define HCI_Create_Physical_Link HCI_CMD_OPCODE(0x01, 0x0035)
+#define HCI_Accept_Physical_Link_Request HCI_CMD_OPCODE(0x01, 0x0036)
+#define HCI_Disconnect_Physical_Link HCI_CMD_OPCODE(0x01, 0x0037)
+#define HCI_Create_Logical_Link HCI_CMD_OPCODE(0x01, 0x0038)
+#define HCI_Accept_Logical_Link HCI_CMD_OPCODE(0x01, 0x0039)
+#define HCI_Disconnect_Logical_Link HCI_CMD_OPCODE(0x01, 0x003A)
+#define HCI_Logical_Link_Cancel HCI_CMD_OPCODE(0x01, 0x003B)
+#define HCI_Flow_Spec_Modify HCI_CMD_OPCODE(0x01, 0x003C)
+#define HCI_Write_Flow_Control_Mode HCI_CMD_OPCODE(0x01, 0x0067)
+#define HCI_Read_Best_Effort_Flush_Timeout HCI_CMD_OPCODE(0x01, 0x0069)
+#define HCI_Write_Best_Effort_Flush_Timeout HCI_CMD_OPCODE(0x01, 0x006A)
+#define HCI_Short_Range_Mode HCI_CMD_OPCODE(0x01, 0x006B)
+#define HCI_Reset HCI_CMD_OPCODE(0x03, 0x0003)
+#define HCI_Read_Connection_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0015)
+#define HCI_Write_Connection_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0016)
+#define HCI_Read_Link_Supervision_Timeout HCI_CMD_OPCODE(0x03, 0x0036)
+#define HCI_Write_Link_Supervision_Timeout HCI_CMD_OPCODE(0x03, 0x0037)
+#define HCI_Enhanced_Flush HCI_CMD_OPCODE(0x03, 0x005F)
+#define HCI_Read_Logical_Link_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0061)
+#define HCI_Write_Logical_Link_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0062)
+#define HCI_Set_Event_Mask_Page_2 HCI_CMD_OPCODE(0x03, 0x0063)
+#define HCI_Read_Location_Data_Command HCI_CMD_OPCODE(0x03, 0x0064)
+#define HCI_Write_Location_Data_Command HCI_CMD_OPCODE(0x03, 0x0065)
+#define HCI_Read_Local_Version_Info HCI_CMD_OPCODE(0x04, 0x0001)
+#define HCI_Read_Local_Supported_Commands HCI_CMD_OPCODE(0x04, 0x0002)
+#define HCI_Read_Buffer_Size HCI_CMD_OPCODE(0x04, 0x0005)
+#define HCI_Read_Data_Block_Size HCI_CMD_OPCODE(0x04, 0x000A)
+
+/* AMP HCI command parameters */
+typedef BWL_PRE_PACKED_STRUCT struct read_local_cmd_parms {
+ uint8 plh;
+ uint8 offset[2]; /* length so far */
+ uint8 max_remote[2];
+} BWL_POST_PACKED_STRUCT read_local_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct write_remote_cmd_parms {
+ uint8 plh;
+ uint8 offset[2];
+ uint8 len[2];
+ uint8 frag[1];
+} BWL_POST_PACKED_STRUCT write_remote_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct phy_link_cmd_parms {
+ uint8 plh;
+ uint8 key_length;
+ uint8 key_type;
+ uint8 key[1];
+} BWL_POST_PACKED_STRUCT phy_link_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_cmd_parms {
+ uint8 plh;
+ uint8 reason;
+} BWL_POST_PACKED_STRUCT dis_phy_link_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct log_link_cmd_parms {
+ uint8 plh;
+ uint8 txflow[16];
+ uint8 rxflow[16];
+} BWL_POST_PACKED_STRUCT log_link_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ext_flow_spec {
+ uint8 id;
+ uint8 service_type;
+ uint8 max_sdu[2];
+ uint8 sdu_ia_time[4];
+ uint8 access_latency[4];
+ uint8 flush_timeout[4];
+} BWL_POST_PACKED_STRUCT ext_flow_spec_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_cmd_parms {
+ uint8 plh;
+ uint8 tx_fs_ID;
+} BWL_POST_PACKED_STRUCT log_link_cancel_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_cmd_parms {
+ uint8 llh[2];
+ uint8 txflow[16];
+ uint8 rxflow[16];
+} BWL_POST_PACKED_STRUCT flow_spec_mod_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct plh_pad {
+ uint8 plh;
+ uint8 pad;
+} BWL_POST_PACKED_STRUCT plh_pad_t;
+
+typedef BWL_PRE_PACKED_STRUCT union hci_handle {
+ uint16 bredr;
+ plh_pad_t amp;
+} BWL_POST_PACKED_STRUCT hci_handle_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ls_to_cmd_parms {
+ hci_handle_t handle;
+ uint8 timeout[2];
+} BWL_POST_PACKED_STRUCT ls_to_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct befto_cmd_parms {
+ uint8 llh[2];
+ uint8 befto[4];
+} BWL_POST_PACKED_STRUCT befto_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct srm_cmd_parms {
+ uint8 plh;
+ uint8 srm;
+} BWL_POST_PACKED_STRUCT srm_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ld_cmd_parms {
+ uint8 ld_aware;
+ uint8 ld[2];
+ uint8 ld_opts;
+ uint8 l_opts;
+} BWL_POST_PACKED_STRUCT ld_cmd_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct eflush_cmd_parms {
+ uint8 llh[2];
+ uint8 packet_type;
+} BWL_POST_PACKED_STRUCT eflush_cmd_parms_t;
+
+/* Generic AMP extended flow spec service types */
+#define EFS_SVCTYPE_NO_TRAFFIC 0
+#define EFS_SVCTYPE_BEST_EFFORT 1
+#define EFS_SVCTYPE_GUARANTEED 2
+
+/* AMP HCI event packet format */
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_event {
+ uint8 ecode;
+ uint8 plen;
+ uint8 parms[1];
+} BWL_POST_PACKED_STRUCT amp_hci_event_t;
+
+#define HCI_EVT_PREAMBLE_SIZE OFFSETOF(amp_hci_event_t, parms)
+
+/* AMP HCI event codes */
+#define HCI_Command_Complete 0x0E
+#define HCI_Command_Status 0x0F
+#define HCI_Flush_Occurred 0x11
+#define HCI_Enhanced_Flush_Complete 0x39
+#define HCI_Physical_Link_Complete 0x40
+#define HCI_Channel_Select 0x41
+#define HCI_Disconnect_Physical_Link_Complete 0x42
+#define HCI_Logical_Link_Complete 0x45
+#define HCI_Disconnect_Logical_Link_Complete 0x46
+#define HCI_Flow_Spec_Modify_Complete 0x47
+#define HCI_Number_of_Completed_Data_Blocks 0x48
+#define HCI_Short_Range_Mode_Change_Complete 0x4C
+#define HCI_Status_Change_Event 0x4D
+#define HCI_Vendor_Specific 0xFF
+
+/* AMP HCI event mask bit positions */
+#define HCI_Physical_Link_Complete_Event_Mask 0x0001
+#define HCI_Channel_Select_Event_Mask 0x0002
+#define HCI_Disconnect_Physical_Link_Complete_Event_Mask 0x0004
+#define HCI_Logical_Link_Complete_Event_Mask 0x0020
+#define HCI_Disconnect_Logical_Link_Complete_Event_Mask 0x0040
+#define HCI_Flow_Spec_Modify_Complete_Event_Mask 0x0080
+#define HCI_Number_of_Completed_Data_Blocks_Event_Mask 0x0100
+#define HCI_Short_Range_Mode_Change_Complete_Event_Mask 0x1000
+#define HCI_Status_Change_Event_Mask 0x2000
+#define HCI_All_Event_Mask 0x31e7
+/* AMP HCI event parameters */
+typedef BWL_PRE_PACKED_STRUCT struct cmd_status_parms {
+ uint8 status;
+ uint8 cmdpkts;
+ uint16 opcode;
+} BWL_POST_PACKED_STRUCT cmd_status_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct cmd_complete_parms {
+ uint8 cmdpkts;
+ uint16 opcode;
+ uint8 parms[1];
+} BWL_POST_PACKED_STRUCT cmd_complete_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct flush_occurred_evt_parms {
+ uint16 handle;
+} BWL_POST_PACKED_STRUCT flush_occurred_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct write_remote_evt_parms {
+ uint8 status;
+ uint8 plh;
+} BWL_POST_PACKED_STRUCT write_remote_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_local_evt_parms {
+ uint8 status;
+ uint8 plh;
+ uint16 len;
+ uint8 frag[1];
+} BWL_POST_PACKED_STRUCT read_local_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_local_info_evt_parms {
+ uint8 status;
+ uint8 AMP_status;
+ uint32 bandwidth;
+ uint32 gbandwidth;
+ uint32 latency;
+ uint32 PDU_size;
+ uint8 ctrl_type;
+ uint16 PAL_cap;
+ uint16 AMP_ASSOC_len;
+ uint32 max_flush_timeout;
+ uint32 be_flush_timeout;
+} BWL_POST_PACKED_STRUCT read_local_info_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct log_link_evt_parms {
+ uint8 status;
+ uint16 llh;
+ uint8 plh;
+ uint8 tx_fs_ID;
+} BWL_POST_PACKED_STRUCT log_link_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct disc_log_link_evt_parms {
+ uint8 status;
+ uint16 llh;
+ uint8 reason;
+} BWL_POST_PACKED_STRUCT disc_log_link_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_evt_parms {
+ uint8 status;
+ uint8 plh;
+ uint8 tx_fs_ID;
+} BWL_POST_PACKED_STRUCT log_link_cancel_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_evt_parms {
+ uint8 status;
+ uint16 llh;
+} BWL_POST_PACKED_STRUCT flow_spec_mod_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct phy_link_evt_parms {
+ uint8 status;
+ uint8 plh;
+} BWL_POST_PACKED_STRUCT phy_link_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_evt_parms {
+ uint8 status;
+ uint8 plh;
+ uint8 reason;
+} BWL_POST_PACKED_STRUCT dis_phy_link_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_ls_to_evt_parms {
+ uint8 status;
+ hci_handle_t handle;
+ uint16 timeout;
+} BWL_POST_PACKED_STRUCT read_ls_to_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_lla_ca_to_evt_parms {
+ uint8 status;
+ uint16 timeout;
+} BWL_POST_PACKED_STRUCT read_lla_ca_to_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_data_block_size_evt_parms {
+ uint8 status;
+ uint16 ACL_pkt_len;
+ uint16 data_block_len;
+ uint16 data_block_num;
+} BWL_POST_PACKED_STRUCT read_data_block_size_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct data_blocks {
+ uint16 handle;
+ uint16 pkts;
+ uint16 blocks;
+} BWL_POST_PACKED_STRUCT data_blocks_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct num_completed_data_blocks_evt_parms {
+ uint16 num_blocks;
+ uint8 num_handles;
+ data_blocks_t completed[1];
+} BWL_POST_PACKED_STRUCT num_completed_data_blocks_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct befto_evt_parms {
+ uint8 status;
+ uint32 befto;
+} BWL_POST_PACKED_STRUCT befto_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct srm_evt_parms {
+ uint8 status;
+ uint8 plh;
+ uint8 srm;
+} BWL_POST_PACKED_STRUCT srm_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct contact_counter_evt_parms {
+ uint8 status;
+ uint8 llh[2];
+ uint16 counter;
+} BWL_POST_PACKED_STRUCT contact_counter_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct contact_counter_reset_evt_parms {
+ uint8 status;
+ uint8 llh[2];
+} BWL_POST_PACKED_STRUCT contact_counter_reset_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct read_linkq_evt_parms {
+ uint8 status;
+ hci_handle_t handle;
+ uint8 link_quality;
+} BWL_POST_PACKED_STRUCT read_linkq_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ld_evt_parms {
+ uint8 status;
+ uint8 ld_aware;
+ uint8 ld[2];
+ uint8 ld_opts;
+ uint8 l_opts;
+} BWL_POST_PACKED_STRUCT ld_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct eflush_complete_evt_parms {
+ uint16 handle;
+} BWL_POST_PACKED_STRUCT eflush_complete_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct vendor_specific_evt_parms {
+ uint8 len;
+ uint8 parms[1];
+} BWL_POST_PACKED_STRUCT vendor_specific_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct local_version_info_evt_parms {
+ uint8 status;
+ uint8 hci_version;
+ uint16 hci_revision;
+ uint8 pal_version;
+ uint16 mfg_name;
+ uint16 pal_subversion;
+} BWL_POST_PACKED_STRUCT local_version_info_evt_parms_t;
+
+#define MAX_SUPPORTED_CMD_BYTE 64
+typedef BWL_PRE_PACKED_STRUCT struct local_supported_cmd_evt_parms {
+ uint8 status;
+ uint8 cmd[MAX_SUPPORTED_CMD_BYTE];
+} BWL_POST_PACKED_STRUCT local_supported_cmd_evt_parms_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct status_change_evt_parms {
+ uint8 status;
+ uint8 amp_status;
+} BWL_POST_PACKED_STRUCT status_change_evt_parms_t;
+
+/* AMP HCI error codes */
+#define HCI_SUCCESS 0x00
+#define HCI_ERR_ILLEGAL_COMMAND 0x01
+#define HCI_ERR_NO_CONNECTION 0x02
+#define HCI_ERR_MEMORY_FULL 0x07
+#define HCI_ERR_CONNECTION_TIMEOUT 0x08
+#define HCI_ERR_MAX_NUM_OF_CONNECTIONS 0x09
+#define HCI_ERR_CONNECTION_EXISTS 0x0B
+#define HCI_ERR_CONNECTION_DISALLOWED 0x0C
+#define HCI_ERR_CONNECTION_ACCEPT_TIMEOUT 0x10
+#define HCI_ERR_UNSUPPORTED_VALUE 0x11
+#define HCI_ERR_ILLEGAL_PARAMETER_FMT 0x12
+#define HCI_ERR_CONN_TERM_BY_LOCAL_HOST 0x16
+#define HCI_ERR_UNSPECIFIED 0x1F
+#define HCI_ERR_UNIT_KEY_USED 0x26
+#define HCI_ERR_QOS_REJECTED 0x2D
+#define HCI_ERR_PARAM_OUT_OF_RANGE 0x30
+#define HCI_ERR_NO_SUITABLE_CHANNEL 0x39
+#define HCI_ERR_CHANNEL_MOVE 0xFF
+
+/* AMP HCI ACL Data packet format */
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_ACL_data {
+ uint16 handle; /* 12-bit connection handle + 2-bit PB and 2-bit BC flags */
+ uint16 dlen; /* data total length */
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT amp_hci_ACL_data_t;
+
+#define HCI_ACL_DATA_PREAMBLE_SIZE OFFSETOF(amp_hci_ACL_data_t, data)
+
+#define HCI_ACL_DATA_BC_FLAGS (0x0 << 14)
+#define HCI_ACL_DATA_PB_FLAGS (0x3 << 12)
+
+#define HCI_ACL_DATA_HANDLE(handle) ((handle) & 0x0fff)
+#define HCI_ACL_DATA_FLAGS(handle) ((handle) >> 12)
+
+/* AMP Activity Report packet formats */
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report {
+ uint8 ScheduleKnown;
+ uint8 NumReports;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT amp_hci_activity_report_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report_triple {
+ uint32 StartTime;
+ uint32 Duration;
+ uint32 Periodicity;
+} BWL_POST_PACKED_STRUCT amp_hci_activity_report_triple_t;
+
+#define HCI_AR_SCHEDULE_KNOWN 0x01
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _bt_amp_hci_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/eapol.h b/drivers/net/wireless/bcmdhd/include/proto/eapol.h
new file mode 100644
index 000000000000..0cdde4891921
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/eapol.h
@@ -0,0 +1,211 @@
+/*
+ * 802.1x EAPOL definitions
+ *
+ * See
+ * IEEE Std 802.1X-2001
+ * IEEE 802.1X RADIUS Usage Guidelines
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: eapol.h 526865 2015-01-15 07:44:19Z $
+ */
+
+#ifndef _eapol_h_
+#define _eapol_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#include <bcmcrypto/aeskeywrap.h>
+
+/* EAPOL for 802.3/Ethernet */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ struct ether_header eth; /* 802.3/Ethernet header */
+ unsigned char version; /* EAPOL protocol version */
+ unsigned char type; /* EAPOL type */
+ unsigned short length; /* Length of body */
+ unsigned char body[1]; /* Body (optional) */
+} BWL_POST_PACKED_STRUCT eapol_header_t;
+
+#define EAPOL_HEADER_LEN 18
+
+typedef struct {
+ unsigned char version; /* EAPOL protocol version */
+ unsigned char type; /* EAPOL type */
+ unsigned short length; /* Length of body */
+} eapol_hdr_t;
+
+#define EAPOL_HDR_LEN 4
+
+/* EAPOL version */
+#define WPA2_EAPOL_VERSION 2
+#define WPA_EAPOL_VERSION 1
+#define LEAP_EAPOL_VERSION 1
+#define SES_EAPOL_VERSION 1
+
+/* EAPOL types */
+#define EAP_PACKET 0
+#define EAPOL_START 1
+#define EAPOL_LOGOFF 2
+#define EAPOL_KEY 3
+#define EAPOL_ASF 4
+
+/* EAPOL-Key types */
+#define EAPOL_RC4_KEY 1
+#define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */
+#define EAPOL_WPA_KEY 254 /* WPA */
+
+/* RC4 EAPOL-Key header field sizes */
+#define EAPOL_KEY_REPLAY_LEN 8
+#define EAPOL_KEY_IV_LEN 16
+#define EAPOL_KEY_SIG_LEN 16
+
+/* RC4 EAPOL-Key */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ unsigned char type; /* Key Descriptor Type */
+ unsigned short length; /* Key Length (unaligned) */
+ unsigned char replay[EAPOL_KEY_REPLAY_LEN]; /* Replay Counter */
+ unsigned char iv[EAPOL_KEY_IV_LEN]; /* Key IV */
+ unsigned char index; /* Key Flags & Index */
+ unsigned char signature[EAPOL_KEY_SIG_LEN]; /* Key Signature */
+ unsigned char key[1]; /* Key (optional) */
+} BWL_POST_PACKED_STRUCT eapol_key_header_t;
+
+#define EAPOL_KEY_HEADER_LEN 44
+
+/* RC4 EAPOL-Key flags */
+#define EAPOL_KEY_FLAGS_MASK 0x80
+#define EAPOL_KEY_BROADCAST 0
+#define EAPOL_KEY_UNICAST 0x80
+
+/* RC4 EAPOL-Key index */
+#define EAPOL_KEY_INDEX_MASK 0x7f
+
+/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */
+#define EAPOL_WPA_KEY_REPLAY_LEN 8
+#define EAPOL_WPA_KEY_NONCE_LEN 32
+#define EAPOL_WPA_KEY_IV_LEN 16
+#define EAPOL_WPA_KEY_RSC_LEN 8
+#define EAPOL_WPA_KEY_ID_LEN 8
+#define EAPOL_WPA_KEY_MIC_LEN 16
+#define EAPOL_WPA_KEY_DATA_LEN (EAPOL_WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN)
+#define EAPOL_WPA_MAX_KEY_SIZE 32
+
+/* WPA EAPOL-Key */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ unsigned char type; /* Key Descriptor Type */
+ unsigned short key_info; /* Key Information (unaligned) */
+ unsigned short key_len; /* Key Length (unaligned) */
+ unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */
+ unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */
+ unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */
+ unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */
+ unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */
+ unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */
+ unsigned short data_len; /* Key Data Length */
+ unsigned char data[EAPOL_WPA_KEY_DATA_LEN]; /* Key data */
+} BWL_POST_PACKED_STRUCT eapol_wpa_key_header_t;
+
+#define EAPOL_WPA_KEY_LEN 95
+
+/* WPA/802.11i/WPA2 KEY KEY_INFO bits */
+#define WPA_KEY_DESC_V1 0x01
+#define WPA_KEY_DESC_V2 0x02
+#define WPA_KEY_DESC_V3 0x03
+#define WPA_KEY_PAIRWISE 0x08
+#define WPA_KEY_INSTALL 0x40
+#define WPA_KEY_ACK 0x80
+#define WPA_KEY_MIC 0x100
+#define WPA_KEY_SECURE 0x200
+#define WPA_KEY_ERROR 0x400
+#define WPA_KEY_REQ 0x800
+
+#define WPA_KEY_DESC_V2_OR_V3 WPA_KEY_DESC_V2
+
+/* WPA-only KEY KEY_INFO bits */
+#define WPA_KEY_INDEX_0 0x00
+#define WPA_KEY_INDEX_1 0x10
+#define WPA_KEY_INDEX_2 0x20
+#define WPA_KEY_INDEX_3 0x30
+#define WPA_KEY_INDEX_MASK 0x30
+#define WPA_KEY_INDEX_SHIFT 0x04
+
+/* 802.11i/WPA2-only KEY KEY_INFO bits */
+#define WPA_KEY_ENCRYPTED_DATA 0x1000
+
+/* Key Data encapsulation */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint8 type;
+ uint8 length;
+ uint8 oui[3];
+ uint8 subtype;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT eapol_wpa2_encap_data_t;
+
+#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 6
+
+#define WPA2_KEY_DATA_SUBTYPE_GTK 1
+#define WPA2_KEY_DATA_SUBTYPE_STAKEY 2
+#define WPA2_KEY_DATA_SUBTYPE_MAC 3
+#define WPA2_KEY_DATA_SUBTYPE_PMKID 4
+#define WPA2_KEY_DATA_SUBTYPE_IGTK 9
+
+/* GTK encapsulation */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint8 flags;
+ uint8 reserved;
+ uint8 gtk[EAPOL_WPA_MAX_KEY_SIZE];
+} BWL_POST_PACKED_STRUCT eapol_wpa2_key_gtk_encap_t;
+
+#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 2
+
+#define WPA2_GTK_INDEX_MASK 0x03
+#define WPA2_GTK_INDEX_SHIFT 0x00
+
+#define WPA2_GTK_TRANSMIT 0x04
+
+/* IGTK encapsulation */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint16 key_id;
+ uint8 ipn[6];
+ uint8 key[EAPOL_WPA_MAX_KEY_SIZE];
+} BWL_POST_PACKED_STRUCT eapol_wpa2_key_igtk_encap_t;
+
+#define EAPOL_WPA2_KEY_IGTK_ENCAP_HDR_LEN 8
+
+/* STAKey encapsulation */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint8 reserved[2];
+ uint8 mac[ETHER_ADDR_LEN];
+ uint8 stakey[EAPOL_WPA_MAX_KEY_SIZE];
+} BWL_POST_PACKED_STRUCT eapol_wpa2_key_stakey_encap_t;
+
+#define WPA2_KEY_DATA_PAD 0xdd
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _eapol_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/ethernet.h b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h
new file mode 100644
index 000000000000..2d025502e291
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h
@@ -0,0 +1,220 @@
+/*
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: ethernet.h 403353 2013-05-20 14:05:33Z $
+ */
+
+#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */
+#define _NET_ETHERNET_H_
+
+#ifndef _TYPEDEFS_H_
+#include "typedefs.h"
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#define ETHER_ADDR_LEN 6
+
+/*
+ * The number of bytes in the type field.
+ */
+#define ETHER_TYPE_LEN 2
+
+/*
+ * The number of bytes in the trailing CRC field.
+ */
+#define ETHER_CRC_LEN 4
+
+/*
+ * The length of the combined header.
+ */
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
+
+/*
+ * The minimum packet length.
+ */
+#define ETHER_MIN_LEN 64
+
+/*
+ * The minimum packet user data length.
+ */
+#define ETHER_MIN_DATA 46
+
+/*
+ * The maximum packet length.
+ */
+#define ETHER_MAX_LEN 1518
+
+/*
+ * The maximum packet user data length.
+ */
+#define ETHER_MAX_DATA 1500
+
+/* ether types */
+#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */
+#define ETHER_TYPE_IP 0x0800 /* IP */
+#define ETHER_TYPE_ARP 0x0806 /* ARP */
+#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */
+#define ETHER_TYPE_IPV6 0x86dd /* IPv6 */
+#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */
+#define ETHER_TYPE_802_1X 0x888e /* 802.1x */
+#ifdef PLC
+#define ETHER_TYPE_88E1 0x88e1 /* GIGLE */
+#define ETHER_TYPE_8912 0x8912 /* GIGLE */
+#define ETHER_TYPE_GIGLED 0xffff /* GIGLE */
+#endif /* PLC */
+#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */
+#define ETHER_TYPE_WAI 0x88b4 /* WAI */
+#define ETHER_TYPE_89_0D 0x890d /* 89-0d frame for TDLS */
+
+#define ETHER_TYPE_PPP_SES 0x8864 /* PPPoE Session */
+
+#define ETHER_TYPE_IAPP_L2_UPDATE 0x6 /* IAPP L2 update frame */
+
+/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */
+#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */
+
+/* ether header */
+#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */
+#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */
+#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */
+
+/*
+ * A macro to validate a length with
+ */
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \
+ ((uint8 *)ea)[0] = 0x01; \
+ ((uint8 *)ea)[1] = 0x00; \
+ ((uint8 *)ea)[2] = 0x5e; \
+ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \
+ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \
+ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \
+}
+
+#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+BWL_PRE_PACKED_STRUCT struct ether_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 ether_type;
+} BWL_POST_PACKED_STRUCT;
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+BWL_PRE_PACKED_STRUCT struct ether_addr {
+ uint8 octet[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */
+
+/*
+ * Takes a pointer, set, test, clear, toggle locally admininistered
+ * address bit in the 48-bit Ethernet address.
+ */
+#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2))
+#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2)
+#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd))
+#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2))
+
+/* Takes a pointer, marks unicast address bit in the MAC address */
+#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1))
+
+/*
+ * Takes a pointer, returns true if a 48-bit multicast address
+ * (including broadcast, since it is all ones)
+ */
+#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1)
+
+
+/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */
+#define eacmp(a, b) ((((const uint16 *)(a))[0] ^ ((const uint16 *)(b))[0]) | \
+ (((const uint16 *)(a))[1] ^ ((const uint16 *)(b))[1]) | \
+ (((const uint16 *)(a))[2] ^ ((const uint16 *)(b))[2]))
+
+#define ether_cmp(a, b) eacmp(a, b)
+
+/* copy an ethernet address - assumes the pointers can be referenced as shorts */
+#define eacopy(s, d) \
+do { \
+ ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \
+ ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \
+ ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \
+} while (0)
+
+#define ether_copy(s, d) eacopy(s, d)
+
+/* Copy an ethernet address in reverse order */
+#define ether_rcopy(s, d) \
+do { \
+ ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \
+ ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \
+ ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \
+} while (0)
+
+
+
+static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
+static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}};
+static const struct ether_addr ether_ipv6_mcast = {{0x33, 0x33, 0x00, 0x00, 0x00, 0x01}};
+
+#define ETHER_ISBCAST(ea) ((((const uint8 *)(ea))[0] & \
+ ((const uint8 *)(ea))[1] & \
+ ((const uint8 *)(ea))[2] & \
+ ((const uint8 *)(ea))[3] & \
+ ((const uint8 *)(ea))[4] & \
+ ((const uint8 *)(ea))[5]) == 0xff)
+#define ETHER_ISNULLADDR(ea) ((((const uint8 *)(ea))[0] | \
+ ((const uint8 *)(ea))[1] | \
+ ((const uint8 *)(ea))[2] | \
+ ((const uint8 *)(ea))[3] | \
+ ((const uint8 *)(ea))[4] | \
+ ((const uint8 *)(ea))[5]) == 0)
+
+#define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \
+ ((const uint16 *)(da))[1] | \
+ ((const uint16 *)(da))[2]) == 0)
+#define ETHER_ISNULLSRC(sa) ETHER_ISNULLDEST(sa)
+
+#define ETHER_MOVE_HDR(d, s) \
+do { \
+ struct ether_header t; \
+ t = *(struct ether_header *)(s); \
+ *(struct ether_header *)(d) = t; \
+} while (0)
+
+#define ETHER_ISUCAST(ea) ((((uint8 *)(ea))[0] & 0x01) == 0)
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _NET_ETHERNET_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/p2p.h b/drivers/net/wireless/bcmdhd/include/proto/p2p.h
new file mode 100644
index 000000000000..678a36a85bd8
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/p2p.h
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * Fundamental types and constants relating to WFA P2P (aka WiFi Direct)
+ *
+ * $Id: p2p.h 444066 2013-12-18 12:49:24Z $
+ */
+
+#ifndef _P2P_H_
+#define _P2P_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+#include <wlioctl.h>
+#include <proto/802.11.h>
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/* WiFi P2P OUI values */
+#define P2P_OUI WFA_OUI /* WiFi P2P OUI */
+#define P2P_VER WFA_OUI_TYPE_P2P /* P2P version: 9=WiFi P2P v1.0 */
+
+#define P2P_IE_ID 0xdd /* P2P IE element ID */
+
+/* WiFi P2P IE */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_ie {
+ uint8 id; /* IE ID: 0xDD */
+ uint8 len; /* IE length */
+ uint8 OUI[3]; /* WiFi P2P specific OUI: P2P_OUI */
+ uint8 oui_type; /* Identifies P2P version: P2P_VER */
+ uint8 subelts[1]; /* variable length subelements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_ie wifi_p2p_ie_t;
+
+#define P2P_IE_FIXED_LEN 6
+
+#define P2P_ATTR_ID_OFF 0
+#define P2P_ATTR_LEN_OFF 1
+#define P2P_ATTR_DATA_OFF 3
+
+#define P2P_ATTR_ID_LEN 1 /* ID filed length */
+#define P2P_ATTR_LEN_LEN 2 /* length field length */
+#define P2P_ATTR_HDR_LEN 3 /* ID + 2-byte length field spec 1.02 */
+
+/* P2P IE Subelement IDs from WiFi P2P Technical Spec 1.00 */
+#define P2P_SEID_STATUS 0 /* Status */
+#define P2P_SEID_MINOR_RC 1 /* Minor Reason Code */
+#define P2P_SEID_P2P_INFO 2 /* P2P Capability (capabilities info) */
+#define P2P_SEID_DEV_ID 3 /* P2P Device ID */
+#define P2P_SEID_INTENT 4 /* Group Owner Intent */
+#define P2P_SEID_CFG_TIMEOUT 5 /* Configuration Timeout */
+#define P2P_SEID_CHANNEL 6 /* Listen channel */
+#define P2P_SEID_GRP_BSSID 7 /* P2P Group BSSID */
+#define P2P_SEID_XT_TIMING 8 /* Extended Listen Timing */
+#define P2P_SEID_INTINTADDR 9 /* Intended P2P Interface Address */
+#define P2P_SEID_P2P_MGBTY 10 /* P2P Manageability */
+#define P2P_SEID_CHAN_LIST 11 /* Channel List */
+#define P2P_SEID_ABSENCE 12 /* Notice of Absence */
+#define P2P_SEID_DEV_INFO 13 /* Device Info */
+#define P2P_SEID_GROUP_INFO 14 /* Group Info */
+#define P2P_SEID_GROUP_ID 15 /* Group ID */
+#define P2P_SEID_P2P_IF 16 /* P2P Interface */
+#define P2P_SEID_OP_CHANNEL 17 /* Operating Channel */
+#define P2P_SEID_INVITE_FLAGS 18 /* Invitation Flags */
+#define P2P_SEID_VNDR 221 /* Vendor-specific subelement */
+
+#define P2P_SE_VS_ID_SERVICES 0x1b
+
+
+/* WiFi P2P IE subelement: P2P Capability (capabilities info) */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_info_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_P2P_INFO */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 dev; /* Device Capability Bitmap */
+ uint8 group; /* Group Capability Bitmap */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_info_se_s wifi_p2p_info_se_t;
+
+/* P2P Capability subelement's Device Capability Bitmap bit values */
+#define P2P_CAPSE_DEV_SERVICE_DIS 0x1 /* Service Discovery */
+#define P2P_CAPSE_DEV_CLIENT_DIS 0x2 /* Client Discoverability */
+#define P2P_CAPSE_DEV_CONCURRENT 0x4 /* Concurrent Operation */
+#define P2P_CAPSE_DEV_INFRA_MAN 0x8 /* P2P Infrastructure Managed */
+#define P2P_CAPSE_DEV_LIMIT 0x10 /* P2P Device Limit */
+#define P2P_CAPSE_INVITE_PROC 0x20 /* P2P Invitation Procedure */
+
+/* P2P Capability subelement's Group Capability Bitmap bit values */
+#define P2P_CAPSE_GRP_OWNER 0x1 /* P2P Group Owner */
+#define P2P_CAPSE_PERSIST_GRP 0x2 /* Persistent P2P Group */
+#define P2P_CAPSE_GRP_LIMIT 0x4 /* P2P Group Limit */
+#define P2P_CAPSE_GRP_INTRA_BSS 0x8 /* Intra-BSS Distribution */
+#define P2P_CAPSE_GRP_X_CONNECT 0x10 /* Cross Connection */
+#define P2P_CAPSE_GRP_PERSISTENT 0x20 /* Persistent Reconnect */
+#define P2P_CAPSE_GRP_FORMATION 0x40 /* Group Formation */
+
+
+/* WiFi P2P IE subelement: Group Owner Intent */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_intent_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_INTENT */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 intent; /* Intent Value 0...15 (0=legacy 15=master only) */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_intent_se_s wifi_p2p_intent_se_t;
+
+/* WiFi P2P IE subelement: Configuration Timeout */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_cfg_tmo_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_CFG_TIMEOUT */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 go_tmo; /* GO config timeout in units of 10 ms */
+ uint8 client_tmo; /* Client config timeout in units of 10 ms */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_cfg_tmo_se_s wifi_p2p_cfg_tmo_se_t;
+
+/* WiFi P2P IE subelement: Listen Channel */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_listen_channel_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_CHANNEL */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 country[3]; /* Country String */
+ uint8 op_class; /* Operating Class */
+ uint8 channel; /* Channel */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_listen_channel_se_s wifi_p2p_listen_channel_se_t;
+
+/* WiFi P2P IE subelement: P2P Group BSSID */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_bssid_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_GRP_BSSID */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 mac[6]; /* P2P group bssid */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_grp_bssid_se_s wifi_p2p_grp_bssid_se_t;
+
+/* WiFi P2P IE subelement: P2P Group ID */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_id_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_GROUP_ID */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 mac[6]; /* P2P device address */
+ uint8 ssid[1]; /* ssid. device id. variable length */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_grp_id_se_s wifi_p2p_grp_id_se_t;
+
+/* WiFi P2P IE subelement: P2P Interface */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_intf_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_P2P_IF */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 mac[6]; /* P2P device address */
+ uint8 ifaddrs; /* P2P Interface Address count */
+ uint8 ifaddr[1][6]; /* P2P Interface Address list */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_intf_se_s wifi_p2p_intf_se_t;
+
+/* WiFi P2P IE subelement: Status */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_status_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_STATUS */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 status; /* Status Code: P2P_STATSE_* */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_status_se_s wifi_p2p_status_se_t;
+
+/* Status subelement Status Code definitions */
+#define P2P_STATSE_SUCCESS 0
+ /* Success */
+#define P2P_STATSE_FAIL_INFO_CURR_UNAVAIL 1
+ /* Failed, information currently unavailable */
+#define P2P_STATSE_PASSED_UP P2P_STATSE_FAIL_INFO_CURR_UNAVAIL
+ /* Old name for above in P2P spec 1.08 and older */
+#define P2P_STATSE_FAIL_INCOMPAT_PARAMS 2
+ /* Failed, incompatible parameters */
+#define P2P_STATSE_FAIL_LIMIT_REACHED 3
+ /* Failed, limit reached */
+#define P2P_STATSE_FAIL_INVALID_PARAMS 4
+ /* Failed, invalid parameters */
+#define P2P_STATSE_FAIL_UNABLE_TO_ACCOM 5
+ /* Failed, unable to accomodate request */
+#define P2P_STATSE_FAIL_PROTO_ERROR 6
+ /* Failed, previous protocol error or disruptive behaviour */
+#define P2P_STATSE_FAIL_NO_COMMON_CHAN 7
+ /* Failed, no common channels */
+#define P2P_STATSE_FAIL_UNKNOWN_GROUP 8
+ /* Failed, unknown P2P Group */
+#define P2P_STATSE_FAIL_INTENT 9
+ /* Failed, both peers indicated Intent 15 in GO Negotiation */
+#define P2P_STATSE_FAIL_INCOMPAT_PROVIS 10
+ /* Failed, incompatible provisioning method */
+#define P2P_STATSE_FAIL_USER_REJECT 11
+ /* Failed, rejected by user */
+
+/* WiFi P2P IE attribute: Extended Listen Timing */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_ext_se_s {
+ uint8 eltId; /* ID: P2P_SEID_EXT_TIMING */
+ uint8 len[2]; /* length not including eltId, len fields */
+ uint8 avail[2]; /* availibility period */
+ uint8 interval[2]; /* availibility interval */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_ext_se_s wifi_p2p_ext_se_t;
+
+#define P2P_EXT_MIN 10 /* minimum 10ms */
+
+/* WiFi P2P IE subelement: Intended P2P Interface Address */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_intintad_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_INTINTADDR */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 mac[6]; /* intended P2P interface MAC address */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_intintad_se_s wifi_p2p_intintad_se_t;
+
+/* WiFi P2P IE subelement: Channel */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_channel_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_STATUS */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 band; /* Regulatory Class (band) */
+ uint8 channel; /* Channel */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_channel_se_s wifi_p2p_channel_se_t;
+
+
+/* Channel Entry structure within the Channel List SE */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_entry_s {
+ uint8 band; /* Regulatory Class (band) */
+ uint8 num_channels; /* # of channels in the channel list */
+ uint8 channels[WL_NUMCHANNELS]; /* Channel List */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_chanlist_entry_s wifi_p2p_chanlist_entry_t;
+#define WIFI_P2P_CHANLIST_SE_MAX_ENTRIES 2
+
+/* WiFi P2P IE subelement: Channel List */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_CHAN_LIST */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 country[3]; /* Country String */
+ uint8 num_entries; /* # of channel entries */
+ wifi_p2p_chanlist_entry_t entries[WIFI_P2P_CHANLIST_SE_MAX_ENTRIES];
+ /* Channel Entry List */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_chanlist_se_s wifi_p2p_chanlist_se_t;
+
+/* WiFi Primary Device Type structure */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_pri_devtype_s {
+ uint16 cat_id; /* Category ID */
+ uint8 OUI[3]; /* WFA OUI: 0x0050F2 */
+ uint8 oui_type; /* WPS_OUI_TYPE */
+ uint16 sub_cat_id; /* Sub Category ID */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_pri_devtype_s wifi_p2p_pri_devtype_t;
+
+/* WiFi P2P Device Info Sub Element Primary Device Type Sub Category
+ * maximum values for each category
+ */
+#define P2P_DISE_SUBCATEGORY_MINVAL 1
+#define P2P_DISE_CATEGORY_COMPUTER 1
+#define P2P_DISE_SUBCATEGORY_COMPUTER_MAXVAL 8
+#define P2P_DISE_CATEGORY_INPUT_DEVICE 2
+#define P2P_DISE_SUBCATEGORY_INPUT_DEVICE_MAXVAL 9
+#define P2P_DISE_CATEGORY_PRINTER 3
+#define P2P_DISE_SUBCATEGORY_PRINTER_MAXVAL 5
+#define P2P_DISE_CATEGORY_CAMERA 4
+#define P2P_DISE_SUBCATEGORY_CAMERA_MAXVAL 4
+#define P2P_DISE_CATEGORY_STORAGE 5
+#define P2P_DISE_SUBCATEGORY_STORAGE_MAXVAL 1
+#define P2P_DISE_CATEGORY_NETWORK_INFRA 6
+#define P2P_DISE_SUBCATEGORY_NETWORK_INFRA_MAXVAL 4
+#define P2P_DISE_CATEGORY_DISPLAY 7
+#define P2P_DISE_SUBCATEGORY_DISPLAY_MAXVAL 4
+#define P2P_DISE_CATEGORY_MULTIMEDIA 8
+#define P2P_DISE_SUBCATEGORY_MULTIMEDIA_MAXVAL 6
+#define P2P_DISE_CATEGORY_GAMING 9
+#define P2P_DISE_SUBCATEGORY_GAMING_MAXVAL 5
+#define P2P_DISE_CATEGORY_TELEPHONE 10
+#define P2P_DISE_SUBCATEGORY_TELEPHONE_MAXVAL 5
+#define P2P_DISE_CATEGORY_AUDIO 11
+#define P2P_DISE_SUBCATEGORY_AUDIO_MAXVAL 6
+
+/* WiFi P2P IE's Device Info subelement */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_devinfo_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_DEVINFO */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 mac[6]; /* P2P Device MAC address */
+ uint16 wps_cfg_meths; /* Config Methods: reg_prototlv.h WPS_CONFMET_* */
+ uint8 pri_devtype[8]; /* Primary Device Type */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_devinfo_se_s wifi_p2p_devinfo_se_t;
+
+#define P2P_DEV_TYPE_LEN 8
+
+/* WiFi P2P IE's Group Info subelement Client Info Descriptor */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_cid_fixed_s {
+ uint8 len;
+ uint8 devaddr[ETHER_ADDR_LEN]; /* P2P Device Address */
+ uint8 ifaddr[ETHER_ADDR_LEN]; /* P2P Interface Address */
+ uint8 devcap; /* Device Capability */
+ uint8 cfg_meths[2]; /* Config Methods: reg_prototlv.h WPS_CONFMET_* */
+ uint8 pridt[P2P_DEV_TYPE_LEN]; /* Primary Device Type */
+ uint8 secdts; /* Number of Secondary Device Types */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_cid_fixed_s wifi_p2p_cid_fixed_t;
+
+/* WiFi P2P IE's Device ID subelement */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_devid_se_s {
+ uint8 eltId;
+ uint8 len[2];
+ struct ether_addr addr; /* P2P Device MAC address */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_devid_se_s wifi_p2p_devid_se_t;
+
+/* WiFi P2P IE subelement: P2P Manageability */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_mgbt_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_P2P_MGBTY */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 mg_bitmap; /* manageability bitmap */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_mgbt_se_s wifi_p2p_mgbt_se_t;
+/* mg_bitmap field bit values */
+#define P2P_MGBTSE_P2PDEVMGMT_FLAG 0x1 /* AP supports Managed P2P Device */
+
+/* WiFi P2P IE subelement: Group Info */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_grpinfo_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_GROUP_INFO */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_grpinfo_se_s wifi_p2p_grpinfo_se_t;
+
+/* WiFi IE subelement: Operating Channel */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_op_channel_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_OP_CHANNEL */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 country[3]; /* Country String */
+ uint8 op_class; /* Operating Class */
+ uint8 channel; /* Channel */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_op_channel_se_s wifi_p2p_op_channel_se_t;
+
+/* WiFi IE subelement: INVITATION FLAGS */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_invite_flags_se_s {
+ uint8 eltId; /* SE ID: P2P_SEID_INVITE_FLAGS */
+ uint8 len[2]; /* SE length not including eltId, len fields */
+ uint8 flags; /* Flags */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_invite_flags_se_s wifi_p2p_invite_flags_se_t;
+
+/* WiFi P2P Action Frame */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_action_frame {
+ uint8 category; /* P2P_AF_CATEGORY */
+ uint8 OUI[3]; /* OUI - P2P_OUI */
+ uint8 type; /* OUI Type - P2P_VER */
+ uint8 subtype; /* OUI Subtype - P2P_AF_* */
+ uint8 dialog_token; /* nonzero, identifies req/resp tranaction */
+ uint8 elts[1]; /* Variable length information elements. Max size =
+ * ACTION_FRAME_SIZE - sizeof(this structure) - 1
+ */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_action_frame wifi_p2p_action_frame_t;
+#define P2P_AF_CATEGORY 0x7f
+
+#define P2P_AF_FIXED_LEN 7
+
+/* WiFi P2P Action Frame OUI Subtypes */
+#define P2P_AF_NOTICE_OF_ABSENCE 0 /* Notice of Absence */
+#define P2P_AF_PRESENCE_REQ 1 /* P2P Presence Request */
+#define P2P_AF_PRESENCE_RSP 2 /* P2P Presence Response */
+#define P2P_AF_GO_DISC_REQ 3 /* GO Discoverability Request */
+
+
+/* WiFi P2P Public Action Frame */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_pub_act_frame {
+ uint8 category; /* P2P_PUB_AF_CATEGORY */
+ uint8 action; /* P2P_PUB_AF_ACTION */
+ uint8 oui[3]; /* P2P_OUI */
+ uint8 oui_type; /* OUI type - P2P_VER */
+ uint8 subtype; /* OUI subtype - P2P_TYPE_* */
+ uint8 dialog_token; /* nonzero, identifies req/rsp transaction */
+ uint8 elts[1]; /* Variable length information elements. Max size =
+ * ACTION_FRAME_SIZE - sizeof(this structure) - 1
+ */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_pub_act_frame wifi_p2p_pub_act_frame_t;
+#define P2P_PUB_AF_FIXED_LEN 8
+#define P2P_PUB_AF_CATEGORY 0x04
+#define P2P_PUB_AF_ACTION 0x09
+
+/* WiFi P2P Public Action Frame OUI Subtypes */
+#define P2P_PAF_GON_REQ 0 /* Group Owner Negotiation Req */
+#define P2P_PAF_GON_RSP 1 /* Group Owner Negotiation Rsp */
+#define P2P_PAF_GON_CONF 2 /* Group Owner Negotiation Confirm */
+#define P2P_PAF_INVITE_REQ 3 /* P2P Invitation Request */
+#define P2P_PAF_INVITE_RSP 4 /* P2P Invitation Response */
+#define P2P_PAF_DEVDIS_REQ 5 /* Device Discoverability Request */
+#define P2P_PAF_DEVDIS_RSP 6 /* Device Discoverability Response */
+#define P2P_PAF_PROVDIS_REQ 7 /* Provision Discovery Request */
+#define P2P_PAF_PROVDIS_RSP 8 /* Provision Discovery Response */
+#define P2P_PAF_SUBTYPE_INVALID 255 /* Invalid Subtype */
+
+/* TODO: Stop using these obsolete aliases for P2P_PAF_GON_* */
+#define P2P_TYPE_MNREQ P2P_PAF_GON_REQ
+#define P2P_TYPE_MNRSP P2P_PAF_GON_RSP
+#define P2P_TYPE_MNCONF P2P_PAF_GON_CONF
+
+/* WiFi P2P IE subelement: Notice of Absence */
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_desc {
+ uint8 cnt_type; /* Count/Type */
+ uint32 duration; /* Duration */
+ uint32 interval; /* Interval */
+ uint32 start; /* Start Time */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_noa_desc wifi_p2p_noa_desc_t;
+
+BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_se {
+ uint8 eltId; /* Subelement ID */
+ uint8 len[2]; /* Length */
+ uint8 index; /* Index */
+ uint8 ops_ctw_parms; /* CTWindow and OppPS Parameters */
+ wifi_p2p_noa_desc_t desc[1]; /* Notice of Absence Descriptor(s) */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2p_noa_se wifi_p2p_noa_se_t;
+
+#define P2P_NOA_SE_FIXED_LEN 5
+
+#define P2P_NOA_SE_MAX_DESC 2 /* max NoA descriptors in presence request */
+
+/* cnt_type field values */
+#define P2P_NOA_DESC_CNT_RESERVED 0 /* reserved and should not be used */
+#define P2P_NOA_DESC_CNT_REPEAT 255 /* continuous schedule */
+#define P2P_NOA_DESC_TYPE_PREFERRED 1 /* preferred values */
+#define P2P_NOA_DESC_TYPE_ACCEPTABLE 2 /* acceptable limits */
+
+/* ctw_ops_parms field values */
+#define P2P_NOA_CTW_MASK 0x7f
+#define P2P_NOA_OPS_MASK 0x80
+#define P2P_NOA_OPS_SHIFT 7
+
+#define P2P_CTW_MIN 10 /* minimum 10TU */
+
+/*
+ * P2P Service Discovery related
+ */
+#define P2PSD_ACTION_CATEGORY 0x04
+ /* Public action frame */
+#define P2PSD_ACTION_ID_GAS_IREQ 0x0a
+ /* Action value for GAS Initial Request AF */
+#define P2PSD_ACTION_ID_GAS_IRESP 0x0b
+ /* Action value for GAS Initial Response AF */
+#define P2PSD_ACTION_ID_GAS_CREQ 0x0c
+ /* Action value for GAS Comback Request AF */
+#define P2PSD_ACTION_ID_GAS_CRESP 0x0d
+ /* Action value for GAS Comback Response AF */
+#define P2PSD_AD_EID 0x6c
+ /* Advertisement Protocol IE ID */
+#define P2PSD_ADP_TUPLE_QLMT_PAMEBI 0x00
+ /* Query Response Length Limit 7 bits plus PAME-BI 1 bit */
+#define P2PSD_ADP_PROTO_ID 0x00
+ /* Advertisement Protocol ID. Always 0 for P2P SD */
+#define P2PSD_GAS_OUI P2P_OUI
+ /* WFA OUI */
+#define P2PSD_GAS_OUI_SUBTYPE P2P_VER
+ /* OUI Subtype for GAS IE */
+#define P2PSD_GAS_NQP_INFOID 0xDDDD
+ /* NQP Query Info ID: 56797 */
+#define P2PSD_GAS_COMEBACKDEALY 0x00
+ /* Not used in the Native GAS protocol */
+
+/* Service Protocol Type */
+typedef enum p2psd_svc_protype {
+ SVC_RPOTYPE_ALL = 0,
+ SVC_RPOTYPE_BONJOUR = 1,
+ SVC_RPOTYPE_UPNP = 2,
+ SVC_RPOTYPE_WSD = 3,
+ SVC_RPOTYPE_VENDOR = 255
+} p2psd_svc_protype_t;
+
+/* Service Discovery response status code */
+typedef enum {
+ P2PSD_RESP_STATUS_SUCCESS = 0,
+ P2PSD_RESP_STATUS_PROTYPE_NA = 1,
+ P2PSD_RESP_STATUS_DATA_NA = 2,
+ P2PSD_RESP_STATUS_BAD_REQUEST = 3
+} p2psd_resp_status_t;
+
+/* Advertisement Protocol IE tuple field */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_tpl {
+ uint8 llm_pamebi; /* Query Response Length Limit bit 0-6, set to 0 plus
+ * Pre-Associated Message Exchange BSSID Independent bit 7, set to 0
+ */
+ uint8 adp_id; /* Advertisement Protocol ID: 0 for NQP Native Query Protocol */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_adp_tpl wifi_p2psd_adp_tpl_t;
+
+/* Advertisement Protocol IE */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_ie {
+ uint8 id; /* IE ID: 0x6c - 108 */
+ uint8 len; /* IE length */
+ wifi_p2psd_adp_tpl_t adp_tpl; /* Advertisement Protocol Tuple field. Only one
+ * tuple is defined for P2P Service Discovery
+ */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_adp_ie wifi_p2psd_adp_ie_t;
+
+/* NQP Vendor-specific Content */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_nqp_query_vsc {
+ uint8 oui_subtype; /* OUI Subtype: 0x09 */
+ uint16 svc_updi; /* Service Update Indicator */
+ uint8 svc_tlvs[1]; /* wifi_p2psd_qreq_tlv_t type for service request,
+ * wifi_p2psd_qresp_tlv_t type for service response
+ */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_nqp_query_vsc wifi_p2psd_nqp_query_vsc_t;
+
+/* Service Request TLV */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_tlv {
+ uint16 len; /* Length: 5 plus size of Query Data */
+ uint8 svc_prot; /* Service Protocol Type */
+ uint8 svc_tscid; /* Service Transaction ID */
+ uint8 query_data[1]; /* Query Data, passed in from above Layer 2 */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_qreq_tlv wifi_p2psd_qreq_tlv_t;
+
+/* Query Request Frame, defined in generic format, instead of NQP specific */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_frame {
+ uint16 info_id; /* Info ID: 0xDDDD */
+ uint16 len; /* Length of service request TLV, 5 plus the size of request data */
+ uint8 oui[3]; /* WFA OUI: 0x0050F2 */
+ uint8 qreq_vsc[1]; /* Vendor-specific Content: wifi_p2psd_nqp_query_vsc_t type for NQP */
+
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_qreq_frame wifi_p2psd_qreq_frame_t;
+
+/* GAS Initial Request AF body, "elts" in wifi_p2p_pub_act_frame */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_ireq_frame {
+ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */
+ uint16 qreq_len; /* Query Request Length */
+ uint8 qreq_frm[1]; /* Query Request Frame wifi_p2psd_qreq_frame_t */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_gas_ireq_frame wifi_p2psd_gas_ireq_frame_t;
+
+/* Service Response TLV */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_tlv {
+ uint16 len; /* Length: 5 plus size of Query Data */
+ uint8 svc_prot; /* Service Protocol Type */
+ uint8 svc_tscid; /* Service Transaction ID */
+ uint8 status; /* Value defined in Table 57 of P2P spec. */
+ uint8 query_data[1]; /* Response Data, passed in from above Layer 2 */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_qresp_tlv wifi_p2psd_qresp_tlv_t;
+
+/* Query Response Frame, defined in generic format, instead of NQP specific */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_frame {
+ uint16 info_id; /* Info ID: 0xDDDD */
+ uint16 len; /* Lenth of service response TLV, 6 plus the size of resp data */
+ uint8 oui[3]; /* WFA OUI: 0x0050F2 */
+ uint8 qresp_vsc[1]; /* Vendor-specific Content: wifi_p2psd_qresp_tlv_t type for NQP */
+
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_qresp_frame wifi_p2psd_qresp_frame_t;
+
+/* GAS Initial Response AF body, "elts" in wifi_p2p_pub_act_frame */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_iresp_frame {
+ uint16 status; /* Value defined in Table 7-23 of IEEE P802.11u */
+ uint16 cb_delay; /* GAS Comeback Delay */
+ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */
+ uint16 qresp_len; /* Query Response Length */
+ uint8 qresp_frm[1]; /* Query Response Frame wifi_p2psd_qresp_frame_t */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_gas_iresp_frame wifi_p2psd_gas_iresp_frame_t;
+
+/* GAS Comeback Response AF body, "elts" in wifi_p2p_pub_act_frame */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_cresp_frame {
+ uint16 status; /* Value defined in Table 7-23 of IEEE P802.11u */
+ uint8 fragment_id; /* Fragmentation ID */
+ uint16 cb_delay; /* GAS Comeback Delay */
+ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */
+ uint16 qresp_len; /* Query Response Length */
+ uint8 qresp_frm[1]; /* Query Response Frame wifi_p2psd_qresp_frame_t */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_gas_cresp_frame wifi_p2psd_gas_cresp_frame_t;
+
+/* Wi-Fi GAS Public Action Frame */
+BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_pub_act_frame {
+ uint8 category; /* 0x04 Public Action Frame */
+ uint8 action; /* 0x6c Advertisement Protocol */
+ uint8 dialog_token; /* nonzero, identifies req/rsp transaction */
+ uint8 query_data[1]; /* Query Data. wifi_p2psd_gas_ireq_frame_t
+ * or wifi_p2psd_gas_iresp_frame_t format
+ */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wifi_p2psd_gas_pub_act_frame wifi_p2psd_gas_pub_act_frame_t;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _P2P_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/sdspi.h b/drivers/net/wireless/bcmdhd/include/proto/sdspi.h
new file mode 100644
index 000000000000..cb761b8eaa3c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/sdspi.h
@@ -0,0 +1,75 @@
+/*
+ * SD-SPI Protocol Standard
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sdspi.h 382882 2013-02-04 23:24:31Z $
+ */
+#ifndef _SD_SPI_H
+#define _SD_SPI_H
+
+#define SPI_START_M BITFIELD_MASK(1) /* Bit [31] - Start Bit */
+#define SPI_START_S 31
+#define SPI_DIR_M BITFIELD_MASK(1) /* Bit [30] - Direction */
+#define SPI_DIR_S 30
+#define SPI_CMD_INDEX_M BITFIELD_MASK(6) /* Bits [29:24] - Command number */
+#define SPI_CMD_INDEX_S 24
+#define SPI_RW_M BITFIELD_MASK(1) /* Bit [23] - Read=0, Write=1 */
+#define SPI_RW_S 23
+#define SPI_FUNC_M BITFIELD_MASK(3) /* Bits [22:20] - Function Number */
+#define SPI_FUNC_S 20
+#define SPI_RAW_M BITFIELD_MASK(1) /* Bit [19] - Read After Wr */
+#define SPI_RAW_S 19
+#define SPI_STUFF_M BITFIELD_MASK(1) /* Bit [18] - Stuff bit */
+#define SPI_STUFF_S 18
+#define SPI_BLKMODE_M BITFIELD_MASK(1) /* Bit [19] - Blockmode 1=blk */
+#define SPI_BLKMODE_S 19
+#define SPI_OPCODE_M BITFIELD_MASK(1) /* Bit [18] - OP Code */
+#define SPI_OPCODE_S 18
+#define SPI_ADDR_M BITFIELD_MASK(17) /* Bits [17:1] - Address */
+#define SPI_ADDR_S 1
+#define SPI_STUFF0_M BITFIELD_MASK(1) /* Bit [0] - Stuff bit */
+#define SPI_STUFF0_S 0
+
+#define SPI_RSP_START_M BITFIELD_MASK(1) /* Bit [7] - Start Bit (always 0) */
+#define SPI_RSP_START_S 7
+#define SPI_RSP_PARAM_ERR_M BITFIELD_MASK(1) /* Bit [6] - Parameter Error */
+#define SPI_RSP_PARAM_ERR_S 6
+#define SPI_RSP_RFU5_M BITFIELD_MASK(1) /* Bit [5] - RFU (Always 0) */
+#define SPI_RSP_RFU5_S 5
+#define SPI_RSP_FUNC_ERR_M BITFIELD_MASK(1) /* Bit [4] - Function number error */
+#define SPI_RSP_FUNC_ERR_S 4
+#define SPI_RSP_CRC_ERR_M BITFIELD_MASK(1) /* Bit [3] - COM CRC Error */
+#define SPI_RSP_CRC_ERR_S 3
+#define SPI_RSP_ILL_CMD_M BITFIELD_MASK(1) /* Bit [2] - Illegal Command error */
+#define SPI_RSP_ILL_CMD_S 2
+#define SPI_RSP_RFU1_M BITFIELD_MASK(1) /* Bit [1] - RFU (Always 0) */
+#define SPI_RSP_RFU1_S 1
+#define SPI_RSP_IDLE_M BITFIELD_MASK(1) /* Bit [0] - In idle state */
+#define SPI_RSP_IDLE_S 0
+
+/* SD-SPI Protocol Definitions */
+#define SDSPI_COMMAND_LEN 6 /* Number of bytes in an SD command */
+#define SDSPI_START_BLOCK 0xFE /* SD Start Block Token */
+#define SDSPI_IDLE_PAD 0xFF /* SD-SPI idle value for MOSI */
+#define SDSPI_START_BIT_MASK 0x80
+
+#endif /* _SD_SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/vlan.h b/drivers/net/wireless/bcmdhd/include/proto/vlan.h
new file mode 100644
index 000000000000..ba6b0f52cdb3
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/vlan.h
@@ -0,0 +1,95 @@
+/*
+ * 802.1Q VLAN protocol definitions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: vlan.h 382883 2013-02-04 23:26:09Z $
+ */
+
+#ifndef _vlan_h_
+#define _vlan_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#ifndef VLAN_VID_MASK
+#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */
+#endif
+
+#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */
+#define VLAN_PRI_SHIFT 13 /* user priority */
+
+#define VLAN_PRI_MASK 7 /* 3 bits of priority */
+
+#define VLAN_TPID_OFFSET 12 /* offset of tag protocol id field */
+#define VLAN_TCI_OFFSET 14 /* offset of tag ctrl info field */
+
+#define VLAN_TAG_LEN 4
+#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */
+
+#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */
+
+struct vlan_header {
+ uint16 vlan_type; /* 0x8100 */
+ uint16 vlan_tag; /* priority, cfi and vid */
+};
+
+struct ethervlan_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 vlan_type; /* 0x8100 */
+ uint16 vlan_tag; /* priority, cfi and vid */
+ uint16 ether_type;
+};
+
+struct dot3_mac_llc_snapvlan_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN]; /* dest mac */
+ uint8 ether_shost[ETHER_ADDR_LEN]; /* src mac */
+ uint16 length; /* frame length incl header */
+ uint8 dsap; /* always 0xAA */
+ uint8 ssap; /* always 0xAA */
+ uint8 ctl; /* always 0x03 */
+ uint8 oui[3]; /* RFC1042: 0x00 0x00 0x00
+ * Bridge-Tunnel: 0x00 0x00 0xF8
+ */
+ uint16 vlan_type; /* 0x8100 */
+ uint16 vlan_tag; /* priority, cfi and vid */
+ uint16 ether_type; /* ethertype */
+};
+
+#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN)
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#define ETHERVLAN_MOVE_HDR(d, s) \
+do { \
+ struct ethervlan_header t; \
+ t = *(struct ethervlan_header *)(s); \
+ *(struct ethervlan_header *)(d) = t; \
+} while (0)
+
+#endif /* _vlan_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/wpa.h b/drivers/net/wireless/bcmdhd/include/proto/wpa.h
new file mode 100644
index 000000000000..0e0db0af0b5f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/wpa.h
@@ -0,0 +1,175 @@
+/*
+ * Fundamental types and constants relating to WPA
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wpa.h 384536 2013-02-12 04:13:09Z $
+ */
+
+#ifndef _proto_wpa_h_
+#define _proto_wpa_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* Reason Codes */
+
+/* 13 through 23 taken from IEEE Std 802.11i-2004 */
+#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */
+#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */
+#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */
+#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */
+#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from
+ * (re-)assoc. request/probe response
+ */
+#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */
+#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */
+#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */
+#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */
+#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */
+#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */
+
+#define WPA2_PMKID_LEN 16
+
+/* WPA IE fixed portion */
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint8 tag; /* TAG */
+ uint8 length; /* TAG length */
+ uint8 oui[3]; /* IE OUI */
+ uint8 oui_type; /* OUI type */
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT version; /* IE version */
+} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t;
+#define WPA_IE_OUITYPE_LEN 4
+#define WPA_IE_FIXED_LEN 8
+#define WPA_IE_TAG_FIXED_LEN 6
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint8 tag; /* TAG */
+ uint8 length; /* TAG length */
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT version; /* IE version */
+} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t;
+#define WPA_RSN_IE_FIXED_LEN 4
+#define WPA_RSN_IE_TAG_FIXED_LEN 2
+typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN];
+
+/* WPA suite/multicast suite */
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint8 oui[3];
+ uint8 type;
+} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t;
+#define WPA_SUITE_LEN 4
+
+/* WPA unicast suite list/key management suite list */
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT count;
+ wpa_suite_t list[1];
+} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+#define WPA_IE_SUITE_COUNT_LEN 2
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT count;
+ wpa_pmkid_t list[1];
+} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t;
+
+/* WPA cipher suites */
+#define WPA_CIPHER_NONE 0 /* None */
+#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */
+#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */
+#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */
+#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */
+#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */
+#define WPA_CIPHER_BIP 6 /* WEP (104-bit) */
+#define WPA_CIPHER_TPK 7 /* Group addressed traffic not allowed */
+
+
+#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \
+ (cipher) == WPA_CIPHER_WEP_40 || \
+ (cipher) == WPA_CIPHER_WEP_104 || \
+ (cipher) == WPA_CIPHER_TKIP || \
+ (cipher) == WPA_CIPHER_AES_OCB || \
+ (cipher) == WPA_CIPHER_AES_CCM || \
+ (cipher) == WPA_CIPHER_TPK)
+
+
+/* WPA TKIP countermeasures parameters */
+#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */
+#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */
+
+/* RSN IE defines */
+#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */
+
+/* RSN Capabilities defined in 802.11i */
+#define RSN_CAP_PREAUTH 0x0001
+#define RSN_CAP_NOPAIRWISE 0x0002
+#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C
+#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2
+#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030
+#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4
+#define RSN_CAP_1_REPLAY_CNTR 0
+#define RSN_CAP_2_REPLAY_CNTRS 1
+#define RSN_CAP_4_REPLAY_CNTRS 2
+#define RSN_CAP_16_REPLAY_CNTRS 3
+#define RSN_CAP_MFPR 0x0040
+#define RSN_CAP_MFPC 0x0080
+#define RSN_CAP_SPPC 0x0400
+#define RSN_CAP_SPPR 0x0800
+
+/* WPA capabilities defined in 802.11i */
+#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS
+#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS
+#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT
+#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK
+
+/* WPA capabilities defined in 802.11zD9.0 */
+#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) /* bit 9 */
+
+/* WPA Specific defines */
+#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */
+#define WPA_PMKID_CNT_LEN 2 /* Length of RSN PMKID count (2 octests) */
+
+#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH
+
+#define WPA2_PMKID_COUNT_LEN 2
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _proto_wpa_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/wps.h b/drivers/net/wireless/bcmdhd/include/proto/wps.h
new file mode 100644
index 000000000000..ac36ede91157
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/proto/wps.h
@@ -0,0 +1,379 @@
+/*
+ * WPS IE definitions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id$
+ */
+
+#ifndef _WPS_
+#define _WPS_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Data Element Definitions */
+#define WPS_ID_AP_CHANNEL 0x1001
+#define WPS_ID_ASSOC_STATE 0x1002
+#define WPS_ID_AUTH_TYPE 0x1003
+#define WPS_ID_AUTH_TYPE_FLAGS 0x1004
+#define WPS_ID_AUTHENTICATOR 0x1005
+#define WPS_ID_CONFIG_METHODS 0x1008
+#define WPS_ID_CONFIG_ERROR 0x1009
+#define WPS_ID_CONF_URL4 0x100A
+#define WPS_ID_CONF_URL6 0x100B
+#define WPS_ID_CONN_TYPE 0x100C
+#define WPS_ID_CONN_TYPE_FLAGS 0x100D
+#define WPS_ID_CREDENTIAL 0x100E
+#define WPS_ID_DEVICE_NAME 0x1011
+#define WPS_ID_DEVICE_PWD_ID 0x1012
+#define WPS_ID_E_HASH1 0x1014
+#define WPS_ID_E_HASH2 0x1015
+#define WPS_ID_E_SNONCE1 0x1016
+#define WPS_ID_E_SNONCE2 0x1017
+#define WPS_ID_ENCR_SETTINGS 0x1018
+#define WPS_ID_ENCR_TYPE 0x100F
+#define WPS_ID_ENCR_TYPE_FLAGS 0x1010
+#define WPS_ID_ENROLLEE_NONCE 0x101A
+#define WPS_ID_FEATURE_ID 0x101B
+#define WPS_ID_IDENTITY 0x101C
+#define WPS_ID_IDENTITY_PROOF 0x101D
+#define WPS_ID_KEY_WRAP_AUTH 0x101E
+#define WPS_ID_KEY_IDENTIFIER 0x101F
+#define WPS_ID_MAC_ADDR 0x1020
+#define WPS_ID_MANUFACTURER 0x1021
+#define WPS_ID_MSG_TYPE 0x1022
+#define WPS_ID_MODEL_NAME 0x1023
+#define WPS_ID_MODEL_NUMBER 0x1024
+#define WPS_ID_NW_INDEX 0x1026
+#define WPS_ID_NW_KEY 0x1027
+#define WPS_ID_NW_KEY_INDEX 0x1028
+#define WPS_ID_NEW_DEVICE_NAME 0x1029
+#define WPS_ID_NEW_PWD 0x102A
+#define WPS_ID_OOB_DEV_PWD 0x102C
+#define WPS_ID_OS_VERSION 0x102D
+#define WPS_ID_POWER_LEVEL 0x102F
+#define WPS_ID_PSK_CURRENT 0x1030
+#define WPS_ID_PSK_MAX 0x1031
+#define WPS_ID_PUBLIC_KEY 0x1032
+#define WPS_ID_RADIO_ENABLED 0x1033
+#define WPS_ID_REBOOT 0x1034
+#define WPS_ID_REGISTRAR_CURRENT 0x1035
+#define WPS_ID_REGISTRAR_ESTBLSHD 0x1036
+#define WPS_ID_REGISTRAR_LIST 0x1037
+#define WPS_ID_REGISTRAR_MAX 0x1038
+#define WPS_ID_REGISTRAR_NONCE 0x1039
+#define WPS_ID_REQ_TYPE 0x103A
+#define WPS_ID_RESP_TYPE 0x103B
+#define WPS_ID_RF_BAND 0x103C
+#define WPS_ID_R_HASH1 0x103D
+#define WPS_ID_R_HASH2 0x103E
+#define WPS_ID_R_SNONCE1 0x103F
+#define WPS_ID_R_SNONCE2 0x1040
+#define WPS_ID_SEL_REGISTRAR 0x1041
+#define WPS_ID_SERIAL_NUM 0x1042
+#define WPS_ID_SC_STATE 0x1044
+#define WPS_ID_SSID 0x1045
+#define WPS_ID_TOT_NETWORKS 0x1046
+#define WPS_ID_UUID_E 0x1047
+#define WPS_ID_UUID_R 0x1048
+#define WPS_ID_VENDOR_EXT 0x1049
+#define WPS_ID_VERSION 0x104A
+#define WPS_ID_X509_CERT_REQ 0x104B
+#define WPS_ID_X509_CERT 0x104C
+#define WPS_ID_EAP_IDENTITY 0x104D
+#define WPS_ID_MSG_COUNTER 0x104E
+#define WPS_ID_PUBKEY_HASH 0x104F
+#define WPS_ID_REKEY_KEY 0x1050
+#define WPS_ID_KEY_LIFETIME 0x1051
+#define WPS_ID_PERM_CFG_METHODS 0x1052
+#define WPS_ID_SEL_REG_CFG_METHODS 0x1053
+#define WPS_ID_PRIM_DEV_TYPE 0x1054
+#define WPS_ID_SEC_DEV_TYPE_LIST 0x1055
+#define WPS_ID_PORTABLE_DEVICE 0x1056
+#define WPS_ID_AP_SETUP_LOCKED 0x1057
+#define WPS_ID_APP_LIST 0x1058
+#define WPS_ID_EAP_TYPE 0x1059
+#define WPS_ID_INIT_VECTOR 0x1060
+#define WPS_ID_KEY_PROVIDED_AUTO 0x1061
+#define WPS_ID_8021X_ENABLED 0x1062
+#define WPS_ID_WEP_TRANSMIT_KEY 0x1064
+#define WPS_ID_REQ_DEV_TYPE 0x106A
+
+/* WSC 2.0, WFA Vendor Extension Subelements */
+#define WFA_VENDOR_EXT_ID "\x00\x37\x2A"
+#define WPS_WFA_SUBID_VERSION2 0x00
+#define WPS_WFA_SUBID_AUTHORIZED_MACS 0x01
+#define WPS_WFA_SUBID_NW_KEY_SHAREABLE 0x02
+#define WPS_WFA_SUBID_REQ_TO_ENROLL 0x03
+#define WPS_WFA_SUBID_SETTINGS_DELAY_TIME 0x04
+
+
+/* WCN-NET Windows Rally Vertical Pairing Vendor Extensions */
+#define MS_VENDOR_EXT_ID "\x00\x01\x37"
+#define WPS_MS_ID_VPI 0x1001 /* Vertical Pairing Identifier TLV */
+#define WPS_MS_ID_TRANSPORT_UUID 0x1002 /* Transport UUID TLV */
+
+/* Vertical Pairing Identifier TLV Definitions */
+#define WPS_MS_VPI_TRANSPORT_NONE 0x00 /* None */
+#define WPS_MS_VPI_TRANSPORT_DPWS 0x01 /* Devices Profile for Web Services */
+#define WPS_MS_VPI_TRANSPORT_UPNP 0x02 /* uPnP */
+#define WPS_MS_VPI_TRANSPORT_SDNWS 0x03 /* Secure Devices Profile for Web Services */
+#define WPS_MS_VPI_NO_PROFILE_REQ 0x00 /* Wi-Fi profile not requested.
+ * Not supported in Windows 7
+ */
+#define WPS_MS_VPI_PROFILE_REQ 0x01 /* Wi-Fi profile requested. */
+
+/* sizes of the fixed size elements */
+#define WPS_ID_AP_CHANNEL_S 2
+#define WPS_ID_ASSOC_STATE_S 2
+#define WPS_ID_AUTH_TYPE_S 2
+#define WPS_ID_AUTH_TYPE_FLAGS_S 2
+#define WPS_ID_AUTHENTICATOR_S 8
+#define WPS_ID_CONFIG_METHODS_S 2
+#define WPS_ID_CONFIG_ERROR_S 2
+#define WPS_ID_CONN_TYPE_S 1
+#define WPS_ID_CONN_TYPE_FLAGS_S 1
+#define WPS_ID_DEVICE_PWD_ID_S 2
+#define WPS_ID_ENCR_TYPE_S 2
+#define WPS_ID_ENCR_TYPE_FLAGS_S 2
+#define WPS_ID_FEATURE_ID_S 4
+#define WPS_ID_MAC_ADDR_S 6
+#define WPS_ID_MSG_TYPE_S 1
+#define WPS_ID_SC_STATE_S 1
+#define WPS_ID_RF_BAND_S 1
+#define WPS_ID_OS_VERSION_S 4
+#define WPS_ID_VERSION_S 1
+#define WPS_ID_SEL_REGISTRAR_S 1
+#define WPS_ID_SEL_REG_CFG_METHODS_S 2
+#define WPS_ID_REQ_TYPE_S 1
+#define WPS_ID_RESP_TYPE_S 1
+#define WPS_ID_AP_SETUP_LOCKED_S 1
+
+/* WSC 2.0, WFA Vendor Extension Subelements */
+#define WPS_WFA_SUBID_VERSION2_S 1
+#define WPS_WFA_SUBID_NW_KEY_SHAREABLE_S 1
+#define WPS_WFA_SUBID_REQ_TO_ENROLL_S 1
+#define WPS_WFA_SUBID_SETTINGS_DELAY_TIME_S 1
+
+/* Association states */
+#define WPS_ASSOC_NOT_ASSOCIATED 0
+#define WPS_ASSOC_CONN_SUCCESS 1
+#define WPS_ASSOC_CONFIG_FAIL 2
+#define WPS_ASSOC_ASSOC_FAIL 3
+#define WPS_ASSOC_IP_FAIL 4
+
+/* Authentication types */
+#define WPS_AUTHTYPE_OPEN 0x0001
+#define WPS_AUTHTYPE_WPAPSK 0x0002 /* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_SHARED 0x0004 /* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_WPA 0x0008 /* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_WPA2 0x0010
+#define WPS_AUTHTYPE_WPA2PSK 0x0020
+
+/* Config methods */
+#define WPS_CONFMET_USBA 0x0001 /* Deprecated in WSC 2.0 */
+#define WPS_CONFMET_ETHERNET 0x0002 /* Deprecated in WSC 2.0 */
+#define WPS_CONFMET_LABEL 0x0004
+#define WPS_CONFMET_DISPLAY 0x0008
+#define WPS_CONFMET_EXT_NFC_TOK 0x0010
+#define WPS_CONFMET_INT_NFC_TOK 0x0020
+#define WPS_CONFMET_NFC_INTF 0x0040
+#define WPS_CONFMET_PBC 0x0080
+#define WPS_CONFMET_KEYPAD 0x0100
+/* WSC 2.0 */
+#define WPS_CONFMET_VIRT_PBC 0x0280
+#define WPS_CONFMET_PHY_PBC 0x0480
+#define WPS_CONFMET_VIRT_DISPLAY 0x2008
+#define WPS_CONFMET_PHY_DISPLAY 0x4008
+
+/* WPS error messages */
+#define WPS_ERROR_NO_ERROR 0
+#define WPS_ERROR_OOB_INT_READ_ERR 1
+#define WPS_ERROR_DECRYPT_CRC_FAIL 2
+#define WPS_ERROR_CHAN24_NOT_SUPP 3
+#define WPS_ERROR_CHAN50_NOT_SUPP 4
+#define WPS_ERROR_SIGNAL_WEAK 5 /* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NW_AUTH_FAIL 6 /* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NW_ASSOC_FAIL 7 /* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NO_DHCP_RESP 8 /* Deprecated in WSC 2.0 */
+#define WPS_ERROR_FAILED_DHCP_CONF 9 /* Deprecated in WSC 2.0 */
+#define WPS_ERROR_IP_ADDR_CONFLICT 10 /* Deprecated in WSC 2.0 */
+#define WPS_ERROR_FAIL_CONN_REGISTRAR 11
+#define WPS_ERROR_MULTI_PBC_DETECTED 12
+#define WPS_ERROR_ROGUE_SUSPECTED 13
+#define WPS_ERROR_DEVICE_BUSY 14
+#define WPS_ERROR_SETUP_LOCKED 15
+#define WPS_ERROR_MSG_TIMEOUT 16 /* Deprecated in WSC 2.0 */
+#define WPS_ERROR_REG_SESSION_TIMEOUT 17 /* Deprecated in WSC 2.0 */
+#define WPS_ERROR_DEV_PWD_AUTH_FAIL 18
+
+/* Connection types */
+#define WPS_CONNTYPE_ESS 0x01
+#define WPS_CONNTYPE_IBSS 0x02
+
+/* Device password ID */
+#define WPS_DEVICEPWDID_DEFAULT 0x0000
+#define WPS_DEVICEPWDID_USER_SPEC 0x0001
+#define WPS_DEVICEPWDID_MACHINE_SPEC 0x0002
+#define WPS_DEVICEPWDID_REKEY 0x0003
+#define WPS_DEVICEPWDID_PUSH_BTN 0x0004
+#define WPS_DEVICEPWDID_REG_SPEC 0x0005
+
+/* Encryption type */
+#define WPS_ENCRTYPE_NONE 0x0001
+#define WPS_ENCRTYPE_WEP 0x0002 /* Deprecated in WSC 2.0 */
+#define WPS_ENCRTYPE_TKIP 0x0004 /* Deprecated in version 2.0. TKIP can only
+ * be advertised on the AP when Mixed Mode
+ * is enabled (Encryption Type is 0x000c).
+ */
+#define WPS_ENCRTYPE_AES 0x0008
+
+
+/* WPS Message Types */
+#define WPS_ID_BEACON 0x01
+#define WPS_ID_PROBE_REQ 0x02
+#define WPS_ID_PROBE_RESP 0x03
+#define WPS_ID_MESSAGE_M1 0x04
+#define WPS_ID_MESSAGE_M2 0x05
+#define WPS_ID_MESSAGE_M2D 0x06
+#define WPS_ID_MESSAGE_M3 0x07
+#define WPS_ID_MESSAGE_M4 0x08
+#define WPS_ID_MESSAGE_M5 0x09
+#define WPS_ID_MESSAGE_M6 0x0A
+#define WPS_ID_MESSAGE_M7 0x0B
+#define WPS_ID_MESSAGE_M8 0x0C
+#define WPS_ID_MESSAGE_ACK 0x0D
+#define WPS_ID_MESSAGE_NACK 0x0E
+#define WPS_ID_MESSAGE_DONE 0x0F
+
+/* WSP private ID for local use */
+#define WPS_PRIVATE_ID_IDENTITY (WPS_ID_MESSAGE_DONE + 1)
+#define WPS_PRIVATE_ID_WPS_START (WPS_ID_MESSAGE_DONE + 2)
+#define WPS_PRIVATE_ID_FAILURE (WPS_ID_MESSAGE_DONE + 3)
+#define WPS_PRIVATE_ID_FRAG (WPS_ID_MESSAGE_DONE + 4)
+#define WPS_PRIVATE_ID_FRAG_ACK (WPS_ID_MESSAGE_DONE + 5)
+#define WPS_PRIVATE_ID_EAPOL_START (WPS_ID_MESSAGE_DONE + 6)
+
+
+/* Device Type categories for primary and secondary device types */
+#define WPS_DEVICE_TYPE_CAT_COMPUTER 1
+#define WPS_DEVICE_TYPE_CAT_INPUT_DEVICE 2
+#define WPS_DEVICE_TYPE_CAT_PRINTER 3
+#define WPS_DEVICE_TYPE_CAT_CAMERA 4
+#define WPS_DEVICE_TYPE_CAT_STORAGE 5
+#define WPS_DEVICE_TYPE_CAT_NW_INFRA 6
+#define WPS_DEVICE_TYPE_CAT_DISPLAYS 7
+#define WPS_DEVICE_TYPE_CAT_MM_DEVICES 8
+#define WPS_DEVICE_TYPE_CAT_GAME_DEVICES 9
+#define WPS_DEVICE_TYPE_CAT_TELEPHONE 10
+#define WPS_DEVICE_TYPE_CAT_AUDIO_DEVICES 11 /* WSC 2.0 */
+
+/* Device Type sub categories for primary and secondary device types */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_PC 1
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_SERVER 2
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MEDIA_CTR 3
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_UM_PC 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_NOTEBOOK 5 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_DESKTOP 6 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MID 7 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_NETBOOK 8 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_Keyboard 1 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_MOUSE 2 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_JOYSTICK 3 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_TRACKBALL 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_GAM_CTRL 5 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_REMOTE 6 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_TOUCHSCREEN 7 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_BIO_READER 8 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_BAR_READER 9 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_PRINTER 1
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_SCANNER 2
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_FAX 3 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_COPIER 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_ALLINONE 5 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_DGTL_STILL 1
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_VIDEO_CAM 2 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_WEB_CAM 3 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_SECU_CAM 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_STOR_NAS 1
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_AP 1
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_ROUTER 2
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_SWITCH 3
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_GATEWAY 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_BRIDGE 5 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_TV 1
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PIC_FRAME 2
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PROJECTOR 3
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_MONITOR 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_DAR 1
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVR 2
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_MCX 3
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_STB 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_MS_ME 5 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVP 6 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX 1
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX_360 2
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PS 3
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_GC 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PGD 5 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_WM 1
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_PSM 2 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_PDM 3 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_SSM 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_SDM 5 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_TUNER 1 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_SPEAKERS 2 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_PMP 3 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HEADSET 4 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HPHONE 5 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_MPHONE 6 /* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HTS 7 /* WSC 2.0 */
+
+
+/* Device request/response type */
+#define WPS_MSGTYPE_ENROLLEE_INFO_ONLY 0x00
+#define WPS_MSGTYPE_ENROLLEE_OPEN_8021X 0x01
+#define WPS_MSGTYPE_REGISTRAR 0x02
+#define WPS_MSGTYPE_AP_WLAN_MGR 0x03
+
+/* RF Band */
+#define WPS_RFBAND_24GHZ 0x01
+#define WPS_RFBAND_50GHZ 0x02
+
+/* Simple Config state */
+#define WPS_SCSTATE_UNCONFIGURED 0x01
+#define WPS_SCSTATE_CONFIGURED 0x02
+#define WPS_SCSTATE_OFF 11
+
+/* WPS Vendor extension key */
+#define WPS_OUI_HEADER_LEN 2
+#define WPS_OUI_HEADER_SIZE 4
+#define WPS_OUI_FIXED_HEADER_OFF 16
+#define WPS_WFA_SUBID_V2_OFF 3
+#define WPS_WFA_V2_OFF 5
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WPS_ */
diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h
new file mode 100644
index 000000000000..f1549b6466ae
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h
@@ -0,0 +1,3304 @@
+/*
+ * SiliconBackplane Chipcommon core hardware definitions.
+ *
+ * The chipcommon core provides chip identification, SB control,
+ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer,
+ * GPIO interface, extbus, and support for serial and parallel flashes.
+ *
+ * $Id: sbchipc.h 662459 2016-10-24 04:35:43Z $
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ */
+
+#ifndef _SBCHIPC_H
+#define _SBCHIPC_H
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define _PADLINE(line) pad ## line
+#define _XSTR(line) _PADLINE(line)
+#define PAD _XSTR(__LINE__)
+#endif /* PAD */
+
+typedef struct eci_prerev35 {
+ uint32 eci_output;
+ uint32 eci_control;
+ uint32 eci_inputlo;
+ uint32 eci_inputmi;
+ uint32 eci_inputhi;
+ uint32 eci_inputintpolaritylo;
+ uint32 eci_inputintpolaritymi;
+ uint32 eci_inputintpolarityhi;
+ uint32 eci_intmasklo;
+ uint32 eci_intmaskmi;
+ uint32 eci_intmaskhi;
+ uint32 eci_eventlo;
+ uint32 eci_eventmi;
+ uint32 eci_eventhi;
+ uint32 eci_eventmasklo;
+ uint32 eci_eventmaskmi;
+ uint32 eci_eventmaskhi;
+ uint32 PAD[3];
+} eci_prerev35_t;
+
+typedef struct eci_rev35 {
+ uint32 eci_outputlo;
+ uint32 eci_outputhi;
+ uint32 eci_controllo;
+ uint32 eci_controlhi;
+ uint32 eci_inputlo;
+ uint32 eci_inputhi;
+ uint32 eci_inputintpolaritylo;
+ uint32 eci_inputintpolarityhi;
+ uint32 eci_intmasklo;
+ uint32 eci_intmaskhi;
+ uint32 eci_eventlo;
+ uint32 eci_eventhi;
+ uint32 eci_eventmasklo;
+ uint32 eci_eventmaskhi;
+ uint32 eci_auxtx;
+ uint32 eci_auxrx;
+ uint32 eci_datatag;
+ uint32 eci_uartescvalue;
+ uint32 eci_autobaudctr;
+ uint32 eci_uartfifolevel;
+} eci_rev35_t;
+
+typedef struct flash_config {
+ uint32 PAD[19];
+ /* Flash struct configuration registers (0x18c) for BCM4706 (corerev = 31) */
+ uint32 flashstrconfig;
+} flash_config_t;
+
+typedef volatile struct {
+ uint32 chipid; /* 0x0 */
+ uint32 capabilities;
+ uint32 corecontrol; /* corerev >= 1 */
+ uint32 bist;
+
+ /* OTP */
+ uint32 otpstatus; /* 0x10, corerev >= 10 */
+ uint32 otpcontrol;
+ uint32 otpprog;
+ uint32 otplayout; /* corerev >= 23 */
+
+ /* Interrupt control */
+ uint32 intstatus; /* 0x20 */
+ uint32 intmask;
+
+ /* Chip specific regs */
+ uint32 chipcontrol; /* 0x28, rev >= 11 */
+ uint32 chipstatus; /* 0x2c, rev >= 11 */
+
+ /* Jtag Master */
+ uint32 jtagcmd; /* 0x30, rev >= 10 */
+ uint32 jtagir;
+ uint32 jtagdr;
+ uint32 jtagctrl;
+
+ /* serial flash interface registers */
+ uint32 flashcontrol; /* 0x40 */
+ uint32 flashaddress;
+ uint32 flashdata;
+ uint32 otplayoutextension; /* rev >= 35 */
+
+ /* Silicon backplane configuration broadcast control */
+ uint32 broadcastaddress; /* 0x50 */
+ uint32 broadcastdata;
+
+ /* gpio - cleared only by power-on-reset */
+ uint32 gpiopullup; /* 0x58, corerev >= 20 */
+ uint32 gpiopulldown; /* 0x5c, corerev >= 20 */
+ uint32 gpioin; /* 0x60 */
+ uint32 gpioout; /* 0x64 */
+ uint32 gpioouten; /* 0x68 */
+ uint32 gpiocontrol; /* 0x6C */
+ uint32 gpiointpolarity; /* 0x70 */
+ uint32 gpiointmask; /* 0x74 */
+
+ /* GPIO events corerev >= 11 */
+ uint32 gpioevent;
+ uint32 gpioeventintmask;
+
+ /* Watchdog timer */
+ uint32 watchdog; /* 0x80 */
+
+ /* GPIO events corerev >= 11 */
+ uint32 gpioeventintpolarity;
+
+ /* GPIO based LED powersave registers corerev >= 16 */
+ uint32 gpiotimerval; /* 0x88 */
+ uint32 gpiotimeroutmask;
+
+ /* clock control */
+ uint32 clockcontrol_n; /* 0x90 */
+ uint32 clockcontrol_sb; /* aka m0 */
+ uint32 clockcontrol_pci; /* aka m1 */
+ uint32 clockcontrol_m2; /* mii/uart/mipsref */
+ uint32 clockcontrol_m3; /* cpu */
+ uint32 clkdiv; /* corerev >= 3 */
+ uint32 gpiodebugsel; /* corerev >= 28 */
+ uint32 capabilities_ext; /* 0xac */
+
+ /* pll delay registers (corerev >= 4) */
+ uint32 pll_on_delay; /* 0xb0 */
+ uint32 fref_sel_delay;
+ uint32 slow_clk_ctl; /* 5 < corerev < 10 */
+ uint32 PAD;
+
+ /* Instaclock registers (corerev >= 10) */
+ uint32 system_clk_ctl; /* 0xc0 */
+ uint32 clkstatestretch;
+ uint32 PAD[2];
+
+ /* Indirect backplane access (corerev >= 22) */
+ uint32 bp_addrlow; /* 0xd0 */
+ uint32 bp_addrhigh;
+ uint32 bp_data;
+ uint32 PAD;
+ uint32 bp_indaccess;
+ /* SPI registers, corerev >= 37 */
+ uint32 gsioctrl;
+ uint32 gsioaddress;
+ uint32 gsiodata;
+
+ /* More clock dividers (corerev >= 32) */
+ uint32 clkdiv2;
+ /* FAB ID (corerev >= 40) */
+ uint32 otpcontrol1;
+ uint32 fabid; /* 0xf8 */
+
+ /* In AI chips, pointer to erom */
+ uint32 eromptr; /* 0xfc */
+
+ /* ExtBus control registers (corerev >= 3) */
+ uint32 pcmcia_config; /* 0x100 */
+ uint32 pcmcia_memwait;
+ uint32 pcmcia_attrwait;
+ uint32 pcmcia_iowait;
+ uint32 ide_config;
+ uint32 ide_memwait;
+ uint32 ide_attrwait;
+ uint32 ide_iowait;
+ uint32 prog_config;
+ uint32 prog_waitcount;
+ uint32 flash_config;
+ uint32 flash_waitcount;
+ uint32 SECI_config; /* 0x130 SECI configuration */
+ uint32 SECI_status;
+ uint32 SECI_statusmask;
+ uint32 SECI_rxnibchanged;
+
+ uint32 PAD[20];
+
+ /* SROM interface (corerev >= 32) */
+ uint32 sromcontrol; /* 0x190 */
+ uint32 sromaddress;
+ uint32 sromdata;
+ uint32 PAD[1]; /* 0x19C */
+ /* NAND flash registers for BCM4706 (corerev = 31) */
+ uint32 nflashctrl; /* 0x1a0 */
+ uint32 nflashconf;
+ uint32 nflashcoladdr;
+ uint32 nflashrowaddr;
+ uint32 nflashdata;
+ uint32 nflashwaitcnt0; /* 0x1b4 */
+ uint32 PAD[2];
+
+ uint32 seci_uart_data; /* 0x1C0 */
+ uint32 seci_uart_bauddiv;
+ uint32 seci_uart_fcr;
+ uint32 seci_uart_lcr;
+ uint32 seci_uart_mcr;
+ uint32 seci_uart_lsr;
+ uint32 seci_uart_msr;
+ uint32 seci_uart_baudadj;
+ /* Clock control and hardware workarounds (corerev >= 20) */
+ uint32 clk_ctl_st; /* 0x1e0 */
+ uint32 hw_war;
+ uint32 PAD[70];
+
+ /* UARTs */
+ uint8 uart0data; /* 0x300 */
+ uint8 uart0imr;
+ uint8 uart0fcr;
+ uint8 uart0lcr;
+ uint8 uart0mcr;
+ uint8 uart0lsr;
+ uint8 uart0msr;
+ uint8 uart0scratch;
+ uint8 PAD[248]; /* corerev >= 1 */
+
+ uint8 uart1data; /* 0x400 */
+ uint8 uart1imr;
+ uint8 uart1fcr;
+ uint8 uart1lcr;
+ uint8 uart1mcr;
+ uint8 uart1lsr;
+ uint8 uart1msr;
+ uint8 uart1scratch; /* 0x407 */
+ uint32 PAD[62];
+
+ /* save/restore, corerev >= 48 */
+ uint32 sr_capability; /* 0x500 */
+ uint32 sr_control0; /* 0x504 */
+ uint32 sr_control1; /* 0x508 */
+ uint32 gpio_control; /* 0x50C */
+ uint32 PAD[60];
+
+ /* PMU registers (corerev >= 20) */
+ /* Note: all timers driven by ILP clock are updated asynchronously to HT/ALP.
+ * The CPU must read them twice, compare, and retry if different.
+ */
+ uint32 pmucontrol; /* 0x600 */
+ uint32 pmucapabilities;
+ uint32 pmustatus;
+ uint32 res_state;
+ uint32 res_pending;
+ uint32 pmutimer;
+ uint32 min_res_mask;
+ uint32 max_res_mask;
+ uint32 res_table_sel;
+ uint32 res_dep_mask;
+ uint32 res_updn_timer;
+ uint32 res_timer;
+ uint32 clkstretch;
+ uint32 pmuwatchdog;
+ uint32 gpiosel; /* 0x638, rev >= 1 */
+ uint32 gpioenable; /* 0x63c, rev >= 1 */
+ uint32 res_req_timer_sel;
+ uint32 res_req_timer;
+ uint32 res_req_mask;
+ uint32 PAD;
+ uint32 chipcontrol_addr; /* 0x650 */
+ uint32 chipcontrol_data; /* 0x654 */
+ uint32 regcontrol_addr;
+ uint32 regcontrol_data;
+ uint32 pllcontrol_addr;
+ uint32 pllcontrol_data;
+ uint32 pmustrapopt; /* 0x668, corerev >= 28 */
+ uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */
+ uint32 retention_ctl; /* 0x670 */
+ uint32 PAD[3];
+ uint32 retention_grpidx; /* 0x680 */
+ uint32 retention_grpctl; /* 0x684 */
+ uint32 PAD[94];
+ uint16 sromotp[512]; /* 0x800 */
+#ifdef NFLASH_SUPPORT
+ /* Nand flash MLC controller registers (corerev >= 38) */
+ uint32 nand_revision; /* 0xC00 */
+ uint32 nand_cmd_start;
+ uint32 nand_cmd_addr_x;
+ uint32 nand_cmd_addr;
+ uint32 nand_cmd_end_addr;
+ uint32 nand_cs_nand_select;
+ uint32 nand_cs_nand_xor;
+ uint32 PAD;
+ uint32 nand_spare_rd0;
+ uint32 nand_spare_rd4;
+ uint32 nand_spare_rd8;
+ uint32 nand_spare_rd12;
+ uint32 nand_spare_wr0;
+ uint32 nand_spare_wr4;
+ uint32 nand_spare_wr8;
+ uint32 nand_spare_wr12;
+ uint32 nand_acc_control;
+ uint32 PAD;
+ uint32 nand_config;
+ uint32 PAD;
+ uint32 nand_timing_1;
+ uint32 nand_timing_2;
+ uint32 nand_semaphore;
+ uint32 PAD;
+ uint32 nand_devid;
+ uint32 nand_devid_x;
+ uint32 nand_block_lock_status;
+ uint32 nand_intfc_status;
+ uint32 nand_ecc_corr_addr_x;
+ uint32 nand_ecc_corr_addr;
+ uint32 nand_ecc_unc_addr_x;
+ uint32 nand_ecc_unc_addr;
+ uint32 nand_read_error_count;
+ uint32 nand_corr_stat_threshold;
+ uint32 PAD[2];
+ uint32 nand_read_addr_x;
+ uint32 nand_read_addr;
+ uint32 nand_page_program_addr_x;
+ uint32 nand_page_program_addr;
+ uint32 nand_copy_back_addr_x;
+ uint32 nand_copy_back_addr;
+ uint32 nand_block_erase_addr_x;
+ uint32 nand_block_erase_addr;
+ uint32 nand_inv_read_addr_x;
+ uint32 nand_inv_read_addr;
+ uint32 PAD[2];
+ uint32 nand_blk_wr_protect;
+ uint32 PAD[3];
+ uint32 nand_acc_control_cs1;
+ uint32 nand_config_cs1;
+ uint32 nand_timing_1_cs1;
+ uint32 nand_timing_2_cs1;
+ uint32 PAD[20];
+ uint32 nand_spare_rd16;
+ uint32 nand_spare_rd20;
+ uint32 nand_spare_rd24;
+ uint32 nand_spare_rd28;
+ uint32 nand_cache_addr;
+ uint32 nand_cache_data;
+ uint32 nand_ctrl_config;
+ uint32 nand_ctrl_status;
+#endif /* NFLASH_SUPPORT */
+ uint32 gci_corecaps0; /* GCI starting at 0xC00 */
+ uint32 gci_corecaps1;
+ uint32 gci_corecaps2;
+ uint32 gci_corectrl;
+ uint32 gci_corestat; /* 0xC10 */
+ uint32 gci_intstat; /* 0xC14 */
+ uint32 gci_intmask; /* 0xC18 */
+ uint32 gci_wakemask; /* 0xC1C */
+ uint32 gci_levelintstat; /* 0xC20 */
+ uint32 gci_eventintstat; /* 0xC24 */
+ uint32 PAD[6];
+ uint32 gci_indirect_addr; /* 0xC40 */
+ uint32 gci_gpioctl; /* 0xC44 */
+ uint32 gci_gpiostatus;
+ uint32 gci_gpiomask; /* 0xC4C */
+ uint32 PAD;
+ uint32 gci_miscctl; /* 0xC54 */
+ uint32 gci_gpiointmask;
+ uint32 gci_gpiowakemask;
+ uint32 gci_input[32]; /* C60 */
+ uint32 gci_event[32]; /* CE0 */
+ uint32 gci_output[4]; /* D60 */
+ uint32 gci_control_0; /* 0xD70 */
+ uint32 gci_control_1; /* 0xD74 */
+ uint32 gci_level_polreg; /* 0xD78 */
+ uint32 gci_levelintmask; /* 0xD7C */
+ uint32 gci_eventintmask; /* 0xD80 */
+ uint32 PAD[3];
+ uint32 gci_inbandlevelintmask; /* 0xD90 */
+ uint32 gci_inbandeventintmask; /* 0xD94 */
+ uint32 PAD[2];
+ uint32 gci_seciauxtx; /* 0xDA0 */
+ uint32 gci_seciauxrx; /* 0xDA4 */
+ uint32 gci_secitx_datatag; /* 0xDA8 */
+ uint32 gci_secirx_datatag; /* 0xDAC */
+ uint32 gci_secitx_datamask; /* 0xDB0 */
+ uint32 gci_seciusef0tx_reg; /* 0xDB4 */
+ uint32 gci_secif0tx_offset; /* 0xDB8 */
+ uint32 gci_secif0rx_offset; /* 0xDBC */
+ uint32 gci_secif1tx_offset; /* 0xDC0 */
+ uint32 PAD[3];
+ uint32 gci_uartescval; /* DD0 */
+ uint32 PAD[3];
+ uint32 gci_secibauddiv; /* DE0 */
+ uint32 gci_secifcr; /* DE4 */
+ uint32 gci_secilcr; /* DE8 */
+ uint32 gci_secimcr; /* DEC */
+ uint32 PAD[2];
+ uint32 gci_baudadj; /* DF8 */
+ uint32 PAD;
+ uint32 gci_chipctrl; /* 0xE00 */
+ uint32 gci_chipsts; /* 0xE04 */
+} chipcregs_t;
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+
+#define CC_CHIPID 0
+#define CC_CAPABILITIES 4
+#define CC_CHIPST 0x2c
+#define CC_EROMPTR 0xfc
+
+#define CC_OTPST 0x10
+#define CC_JTAGCMD 0x30
+#define CC_JTAGIR 0x34
+#define CC_JTAGDR 0x38
+#define CC_JTAGCTRL 0x3c
+#define CC_GPIOPU 0x58
+#define CC_GPIOPD 0x5c
+#define CC_GPIOIN 0x60
+#define CC_GPIOOUT 0x64
+#define CC_GPIOOUTEN 0x68
+#define CC_GPIOCTRL 0x6c
+#define CC_GPIOPOL 0x70
+#define CC_GPIOINTM 0x74
+#define CC_WATCHDOG 0x80
+#define CC_CLKC_N 0x90
+#define CC_CLKC_M0 0x94
+#define CC_CLKC_M1 0x98
+#define CC_CLKC_M2 0x9c
+#define CC_CLKC_M3 0xa0
+#define CC_CLKDIV 0xa4
+#define CC_SYS_CLK_CTL 0xc0
+#define CC_CLK_CTL_ST SI_CLK_CTL_ST
+#define PMU_CTL 0x600
+#define PMU_CAP 0x604
+#define PMU_ST 0x608
+#define PMU_RES_STATE 0x60c
+#define PMU_TIMER 0x614
+#define PMU_MIN_RES_MASK 0x618
+#define PMU_MAX_RES_MASK 0x61c
+#define CC_CHIPCTL_ADDR 0x650
+#define CC_CHIPCTL_DATA 0x654
+#define PMU_REG_CONTROL_ADDR 0x658
+#define PMU_REG_CONTROL_DATA 0x65C
+#define PMU_PLL_CONTROL_ADDR 0x660
+#define PMU_PLL_CONTROL_DATA 0x664
+#define CC_SROM_CTRL 0x190
+#define CC_SROM_OTP 0x800 /* SROM/OTP address space */
+#define CC_GCI_INDIRECT_ADDR_REG 0xC40
+#define CC_GCI_CHIP_CTRL_REG 0xE00
+#define CC_GCI_CC_OFFSET_2 2
+#define CC_GCI_CC_OFFSET_5 5
+
+#define CHIPCTRLREG0 0x0
+#define CHIPCTRLREG1 0x1
+#define CHIPCTRLREG2 0x2
+#define CHIPCTRLREG3 0x3
+#define CHIPCTRLREG4 0x4
+#define CHIPCTRLREG5 0x5
+#define CHIPCTRLREG6 0x6
+#define REGCTRLREG4 0x4
+#define REGCTRLREG5 0x5
+#define REGCTRLREG6 0x6
+#define PMU_RES_STATE 0x60c
+#define PMU_RES_PENDING 0x610
+#define PMU_TIMER 0x614
+#define MINRESMASKREG 0x618
+#define MAXRESMASKREG 0x61c
+#define CHIPCTRLADDR 0x650
+#define CHIPCTRLDATA 0x654
+#define RSRCTABLEADDR 0x620
+#define PMU_RES_DEP_MASK 0x624
+#define RSRCUPDWNTIME 0x628
+#define PMUREG_RESREQ_MASK 0x68c
+#define EXT_LPO_AVAIL 0x100
+#define LPO_SEL (1 << 0)
+#define CC_EXT_LPO_PU 0x200000
+#define GC_EXT_LPO_PU 0x2
+#define CC_INT_LPO_PU 0x100000
+#define GC_INT_LPO_PU 0x1
+#define EXT_LPO_SEL 0x8
+#define INT_LPO_SEL 0x4
+#define ENABLE_FINE_CBUCK_CTRL (1 << 30)
+#define REGCTRL5_PWM_AUTO_CTRL_MASK 0x007e0000
+#define REGCTRL5_PWM_AUTO_CTRL_SHIFT 17
+#define REGCTRL6_PWM_AUTO_CTRL_MASK 0x3fff0000
+#define REGCTRL6_PWM_AUTO_CTRL_SHIFT 16
+
+#ifdef NFLASH_SUPPORT
+/* NAND flash support */
+#define CC_NAND_REVISION 0xC00
+#define CC_NAND_CMD_START 0xC04
+#define CC_NAND_CMD_ADDR 0xC0C
+#define CC_NAND_SPARE_RD_0 0xC20
+#define CC_NAND_SPARE_RD_4 0xC24
+#define CC_NAND_SPARE_RD_8 0xC28
+#define CC_NAND_SPARE_RD_C 0xC2C
+#define CC_NAND_CONFIG 0xC48
+#define CC_NAND_DEVID 0xC60
+#define CC_NAND_DEVID_EXT 0xC64
+#define CC_NAND_INTFC_STATUS 0xC6C
+#endif /* NFLASH_SUPPORT */
+
+/* chipid */
+#define CID_ID_MASK 0x0000ffff /* Chip Id mask */
+#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */
+#define CID_REV_SHIFT 16 /* Chip Revision shift */
+#define CID_PKG_MASK 0x00f00000 /* Package Option mask */
+#define CID_PKG_SHIFT 20 /* Package Option shift */
+#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */
+#define CID_CC_SHIFT 24
+#define CID_TYPE_MASK 0xf0000000 /* Chip Type */
+#define CID_TYPE_SHIFT 28
+
+/* capabilities */
+#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */
+#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */
+#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */
+#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */
+#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */
+#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */
+#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */
+#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */
+#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */
+#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */
+#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */
+#define CC_CAP_PWR_CTL 0x00040000 /* Power control */
+#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */
+#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */
+#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */
+#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */
+#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */
+#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */
+#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */
+#define CC_CAP_ECI 0x20000000 /* ECI Present, rev >= 21 */
+#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */
+#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */
+
+#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */
+#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */
+
+/* capabilities extension */
+#define CC_CAP_EXT_SECI_PRESENT 0x00000001 /* SECI present */
+#define CC_CAP_EXT_GCI_PRESENT 0x00000004 /* GCI present */
+
+/* WL Channel Info to BT via GCI - bits 40 - 47 */
+#define GCI_WL_CHN_INFO_MASK (0xFF00)
+/* PLL type */
+#define PLL_NONE 0x00000000
+#define PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */
+#define PLL_TYPE2 0x00020000 /* 48MHz, 4 dividers */
+#define PLL_TYPE3 0x00030000 /* 25MHz, 2 dividers */
+#define PLL_TYPE4 0x00008000 /* 48MHz, 4 dividers */
+#define PLL_TYPE5 0x00018000 /* 25MHz, 4 dividers */
+#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */
+#define PLL_TYPE7 0x00038000 /* 25MHz, 4 dividers */
+
+/* ILP clock */
+#define ILP_CLOCK 32000
+
+/* ALP clock on pre-PMU chips */
+#define ALP_CLOCK 20000000
+
+#ifdef CFG_SIM
+#define NS_ALP_CLOCK 84922
+#define NS_SLOW_ALP_CLOCK 84922
+#define NS_CPU_CLOCK 534500
+#define NS_SLOW_CPU_CLOCK 534500
+#define NS_SI_CLOCK 271750
+#define NS_SLOW_SI_CLOCK 271750
+#define NS_FAST_MEM_CLOCK 271750
+#define NS_MEM_CLOCK 271750
+#define NS_SLOW_MEM_CLOCK 271750
+#else
+#define NS_ALP_CLOCK 125000000
+#define NS_SLOW_ALP_CLOCK 100000000
+#define NS_CPU_CLOCK 1000000000
+#define NS_SLOW_CPU_CLOCK 800000000
+#define NS_SI_CLOCK 250000000
+#define NS_SLOW_SI_CLOCK 200000000
+#define NS_FAST_MEM_CLOCK 800000000
+#define NS_MEM_CLOCK 533000000
+#define NS_SLOW_MEM_CLOCK 400000000
+#endif /* CFG_SIM */
+
+/* HT clock */
+#define HT_CLOCK 80000000
+
+/* corecontrol */
+#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */
+#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */
+#define CC_ASYNCGPIO 0x00000004 /* 1=generate GPIO interrupt without backplane clock */
+#define CC_UARTCLKEN 0x00000008 /* enable UART Clock (corerev > = 21 */
+
+/* 4321 chipcontrol */
+#define CHIPCTRL_4321A0_DEFAULT 0x3a4
+#define CHIPCTRL_4321A1_DEFAULT 0x0a4
+#define CHIPCTRL_4321_PLL_DOWN 0x800000 /* serdes PLL down override */
+
+/* Fields in the otpstatus register in rev >= 21 */
+#define OTPS_OL_MASK 0x000000ff
+#define OTPS_OL_MFG 0x00000001 /* manuf row is locked */
+#define OTPS_OL_OR1 0x00000002 /* otp redundancy row 1 is locked */
+#define OTPS_OL_OR2 0x00000004 /* otp redundancy row 2 is locked */
+#define OTPS_OL_GU 0x00000008 /* general use region is locked */
+#define OTPS_GUP_MASK 0x00000f00
+#define OTPS_GUP_SHIFT 8
+#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */
+#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */
+#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */
+#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */
+#define OTPS_READY 0x00001000
+#define OTPS_RV(x) (1 << (16 + (x))) /* redundancy entry valid */
+#define OTPS_RV_MASK 0x0fff0000
+#define OTPS_PROGOK 0x40000000
+
+/* Fields in the otpcontrol register in rev >= 21 */
+#define OTPC_PROGSEL 0x00000001
+#define OTPC_PCOUNT_MASK 0x0000000e
+#define OTPC_PCOUNT_SHIFT 1
+#define OTPC_VSEL_MASK 0x000000f0
+#define OTPC_VSEL_SHIFT 4
+#define OTPC_TMM_MASK 0x00000700
+#define OTPC_TMM_SHIFT 8
+#define OTPC_ODM 0x00000800
+#define OTPC_PROGEN 0x80000000
+
+/* Fields in the 40nm otpcontrol register in rev >= 40 */
+#define OTPC_40NM_PROGSEL_SHIFT 0
+#define OTPC_40NM_PCOUNT_SHIFT 1
+#define OTPC_40NM_PCOUNT_WR 0xA
+#define OTPC_40NM_PCOUNT_V1X 0xB
+#define OTPC_40NM_REGCSEL_SHIFT 5
+#define OTPC_40NM_REGCSEL_DEF 0x4
+#define OTPC_40NM_PROGIN_SHIFT 8
+#define OTPC_40NM_R2X_SHIFT 10
+#define OTPC_40NM_ODM_SHIFT 11
+#define OTPC_40NM_DF_SHIFT 15
+#define OTPC_40NM_VSEL_SHIFT 16
+#define OTPC_40NM_VSEL_WR 0xA
+#define OTPC_40NM_VSEL_V1X 0xA
+#define OTPC_40NM_VSEL_R1X 0x5
+#define OTPC_40NM_COFAIL_SHIFT 30
+
+#define OTPC1_CPCSEL_SHIFT 0
+#define OTPC1_CPCSEL_DEF 6
+#define OTPC1_TM_SHIFT 8
+#define OTPC1_TM_WR 0x84
+#define OTPC1_TM_V1X 0x84
+#define OTPC1_TM_R1X 0x4
+
+/* Fields in otpprog in rev >= 21 and HND OTP */
+#define OTPP_COL_MASK 0x000000ff
+#define OTPP_COL_SHIFT 0
+#define OTPP_ROW_MASK 0x0000ff00
+#define OTPP_ROW_SHIFT 8
+#define OTPP_OC_MASK 0x0f000000
+#define OTPP_OC_SHIFT 24
+#define OTPP_READERR 0x10000000
+#define OTPP_VALUE_MASK 0x20000000
+#define OTPP_VALUE_SHIFT 29
+#define OTPP_START_BUSY 0x80000000
+#define OTPP_READ 0x40000000 /* HND OTP */
+
+/* Fields in otplayout register */
+#define OTPL_HWRGN_OFF_MASK 0x00000FFF
+#define OTPL_HWRGN_OFF_SHIFT 0
+#define OTPL_WRAP_REVID_MASK 0x00F80000
+#define OTPL_WRAP_REVID_SHIFT 19
+#define OTPL_WRAP_TYPE_MASK 0x00070000
+#define OTPL_WRAP_TYPE_SHIFT 16
+#define OTPL_WRAP_TYPE_65NM 0
+#define OTPL_WRAP_TYPE_40NM 1
+#define OTPL_ROW_SIZE_MASK 0x0000F000
+#define OTPL_ROW_SIZE_SHIFT 12
+
+/* otplayout reg corerev >= 36 */
+#define OTP_CISFORMAT_NEW 0x80000000
+
+/* Opcodes for OTPP_OC field */
+#define OTPPOC_READ 0
+#define OTPPOC_BIT_PROG 1
+#define OTPPOC_VERIFY 3
+#define OTPPOC_INIT 4
+#define OTPPOC_SET 5
+#define OTPPOC_RESET 6
+#define OTPPOC_OCST 7
+#define OTPPOC_ROW_LOCK 8
+#define OTPPOC_PRESCN_TEST 9
+
+/* Opcodes for OTPP_OC field (40NM) */
+#define OTPPOC_READ_40NM 0
+#define OTPPOC_PROG_ENABLE_40NM 1
+#define OTPPOC_PROG_DISABLE_40NM 2
+#define OTPPOC_VERIFY_40NM 3
+#define OTPPOC_WORD_VERIFY_1_40NM 4
+#define OTPPOC_ROW_LOCK_40NM 5
+#define OTPPOC_STBY_40NM 6
+#define OTPPOC_WAKEUP_40NM 7
+#define OTPPOC_WORD_VERIFY_0_40NM 8
+#define OTPPOC_PRESCN_TEST_40NM 9
+#define OTPPOC_BIT_PROG_40NM 10
+#define OTPPOC_WORDPROG_40NM 11
+#define OTPPOC_BURNIN_40NM 12
+#define OTPPOC_AUTORELOAD_40NM 13
+#define OTPPOC_OVST_READ_40NM 14
+#define OTPPOC_OVST_PROG_40NM 15
+
+/* Fields in otplayoutextension */
+#define OTPLAYOUTEXT_FUSE_MASK 0x3FF
+
+
+/* Jtagm characteristics that appeared at a given corerev */
+#define JTAGM_CREV_OLD 10 /* Old command set, 16bit max IR */
+#define JTAGM_CREV_IRP 22 /* Able to do pause-ir */
+#define JTAGM_CREV_RTI 28 /* Able to do return-to-idle */
+
+/* jtagcmd */
+#define JCMD_START 0x80000000
+#define JCMD_BUSY 0x80000000
+#define JCMD_STATE_MASK 0x60000000
+#define JCMD_STATE_TLR 0x00000000 /* Test-logic-reset */
+#define JCMD_STATE_PIR 0x20000000 /* Pause IR */
+#define JCMD_STATE_PDR 0x40000000 /* Pause DR */
+#define JCMD_STATE_RTI 0x60000000 /* Run-test-idle */
+#define JCMD0_ACC_MASK 0x0000f000
+#define JCMD0_ACC_IRDR 0x00000000
+#define JCMD0_ACC_DR 0x00001000
+#define JCMD0_ACC_IR 0x00002000
+#define JCMD0_ACC_RESET 0x00003000
+#define JCMD0_ACC_IRPDR 0x00004000
+#define JCMD0_ACC_PDR 0x00005000
+#define JCMD0_IRW_MASK 0x00000f00
+#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */
+#define JCMD_ACC_IRDR 0x00000000
+#define JCMD_ACC_DR 0x00010000
+#define JCMD_ACC_IR 0x00020000
+#define JCMD_ACC_RESET 0x00030000
+#define JCMD_ACC_IRPDR 0x00040000
+#define JCMD_ACC_PDR 0x00050000
+#define JCMD_ACC_PIR 0x00060000
+#define JCMD_ACC_IRDR_I 0x00070000 /* rev 28: return to run-test-idle */
+#define JCMD_ACC_DR_I 0x00080000 /* rev 28: return to run-test-idle */
+#define JCMD_IRW_MASK 0x00001f00
+#define JCMD_IRW_SHIFT 8
+#define JCMD_DRW_MASK 0x0000003f
+
+/* jtagctrl */
+#define JCTRL_FORCE_CLK 4 /* Force clock */
+#define JCTRL_EXT_EN 2 /* Enable external targets */
+#define JCTRL_EN 1 /* Enable Jtag master */
+
+/* Fields in clkdiv */
+#define CLKD_SFLASH 0x0f000000
+#define CLKD_SFLASH_SHIFT 24
+#define CLKD_OTP 0x000f0000
+#define CLKD_OTP_SHIFT 16
+#define CLKD_JTAG 0x00000f00
+#define CLKD_JTAG_SHIFT 8
+#define CLKD_UART 0x000000ff
+
+#define CLKD2_SROM 0x00000003
+
+/* intstatus/intmask */
+#define CI_GPIO 0x00000001 /* gpio intr */
+#define CI_EI 0x00000002 /* extif intr (corerev >= 3) */
+#define CI_TEMP 0x00000004 /* temp. ctrl intr (corerev >= 15) */
+#define CI_SIRQ 0x00000008 /* serial IRQ intr (corerev >= 15) */
+#define CI_ECI 0x00000010 /* eci intr (corerev >= 21) */
+#define CI_PMU 0x00000020 /* pmu intr (corerev >= 21) */
+#define CI_UART 0x00000040 /* uart intr (corerev >= 21) */
+#define CI_WDRESET 0x80000000 /* watchdog reset occurred */
+
+/* slow_clk_ctl */
+#define SCC_SS_MASK 0x00000007 /* slow clock source mask */
+#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */
+#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */
+#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */
+#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
+#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled,
+ * 0: LPO is enabled
+ */
+#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock,
+ * 0: power logic control
+ */
+#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors
+ * PLL clock disable requests from core
+ */
+#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't
+ * disable crystal when appropriate
+ */
+#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */
+#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */
+#define SCC_CD_SHIFT 16
+
+/* system_clk_ctl */
+#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */
+#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */
+#define SYCC_FP 0x00000004 /* ForcePLLOn */
+#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */
+#define SYCC_HR 0x00000010 /* Force HT */
+#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */
+#define SYCC_CD_SHIFT 16
+
+/* Indirect backplane access */
+#define BPIA_BYTEEN 0x0000000f
+#define BPIA_SZ1 0x00000001
+#define BPIA_SZ2 0x00000003
+#define BPIA_SZ4 0x00000007
+#define BPIA_SZ8 0x0000000f
+#define BPIA_WRITE 0x00000100
+#define BPIA_START 0x00000200
+#define BPIA_BUSY 0x00000200
+#define BPIA_ERROR 0x00000400
+
+/* pcmcia/prog/flash_config */
+#define CF_EN 0x00000001 /* enable */
+#define CF_EM_MASK 0x0000000e /* mode */
+#define CF_EM_SHIFT 1
+#define CF_EM_FLASH 0 /* flash/asynchronous mode */
+#define CF_EM_SYNC 2 /* synchronous mode */
+#define CF_EM_PCMCIA 4 /* pcmcia mode */
+#define CF_DS 0x00000010 /* destsize: 0=8bit, 1=16bit */
+#define CF_BS 0x00000020 /* byteswap */
+#define CF_CD_MASK 0x000000c0 /* clock divider */
+#define CF_CD_SHIFT 6
+#define CF_CD_DIV2 0x00000000 /* backplane/2 */
+#define CF_CD_DIV3 0x00000040 /* backplane/3 */
+#define CF_CD_DIV4 0x00000080 /* backplane/4 */
+#define CF_CE 0x00000100 /* clock enable */
+#define CF_SB 0x00000200 /* size/bytestrobe (synch only) */
+
+/* pcmcia_memwait */
+#define PM_W0_MASK 0x0000003f /* waitcount0 */
+#define PM_W1_MASK 0x00001f00 /* waitcount1 */
+#define PM_W1_SHIFT 8
+#define PM_W2_MASK 0x001f0000 /* waitcount2 */
+#define PM_W2_SHIFT 16
+#define PM_W3_MASK 0x1f000000 /* waitcount3 */
+#define PM_W3_SHIFT 24
+
+/* pcmcia_attrwait */
+#define PA_W0_MASK 0x0000003f /* waitcount0 */
+#define PA_W1_MASK 0x00001f00 /* waitcount1 */
+#define PA_W1_SHIFT 8
+#define PA_W2_MASK 0x001f0000 /* waitcount2 */
+#define PA_W2_SHIFT 16
+#define PA_W3_MASK 0x1f000000 /* waitcount3 */
+#define PA_W3_SHIFT 24
+
+/* pcmcia_iowait */
+#define PI_W0_MASK 0x0000003f /* waitcount0 */
+#define PI_W1_MASK 0x00001f00 /* waitcount1 */
+#define PI_W1_SHIFT 8
+#define PI_W2_MASK 0x001f0000 /* waitcount2 */
+#define PI_W2_SHIFT 16
+#define PI_W3_MASK 0x1f000000 /* waitcount3 */
+#define PI_W3_SHIFT 24
+
+/* prog_waitcount */
+#define PW_W0_MASK 0x0000001f /* waitcount0 */
+#define PW_W1_MASK 0x00001f00 /* waitcount1 */
+#define PW_W1_SHIFT 8
+#define PW_W2_MASK 0x001f0000 /* waitcount2 */
+#define PW_W2_SHIFT 16
+#define PW_W3_MASK 0x1f000000 /* waitcount3 */
+#define PW_W3_SHIFT 24
+
+#define PW_W0 0x0000000c
+#define PW_W1 0x00000a00
+#define PW_W2 0x00020000
+#define PW_W3 0x01000000
+
+/* flash_waitcount */
+#define FW_W0_MASK 0x0000003f /* waitcount0 */
+#define FW_W1_MASK 0x00001f00 /* waitcount1 */
+#define FW_W1_SHIFT 8
+#define FW_W2_MASK 0x001f0000 /* waitcount2 */
+#define FW_W2_SHIFT 16
+#define FW_W3_MASK 0x1f000000 /* waitcount3 */
+#define FW_W3_SHIFT 24
+
+/* When Srom support present, fields in sromcontrol */
+#define SRC_START 0x80000000
+#define SRC_BUSY 0x80000000
+#define SRC_OPCODE 0x60000000
+#define SRC_OP_READ 0x00000000
+#define SRC_OP_WRITE 0x20000000
+#define SRC_OP_WRDIS 0x40000000
+#define SRC_OP_WREN 0x60000000
+#define SRC_OTPSEL 0x00000010
+#define SRC_OTPPRESENT 0x00000020
+#define SRC_LOCK 0x00000008
+#define SRC_SIZE_MASK 0x00000006
+#define SRC_SIZE_1K 0x00000000
+#define SRC_SIZE_4K 0x00000002
+#define SRC_SIZE_16K 0x00000004
+#define SRC_SIZE_SHIFT 1
+#define SRC_PRESENT 0x00000001
+
+/* Fields in pmucontrol */
+#define PCTL_ILP_DIV_MASK 0xffff0000
+#define PCTL_ILP_DIV_SHIFT 16
+#define PCTL_LQ_REQ_EN 0x00008000
+#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */
+#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */
+#define PCTL_HT_REQ_EN 0x00000100
+#define PCTL_ALP_REQ_EN 0x00000080
+#define PCTL_XTALFREQ_MASK 0x0000007c
+#define PCTL_XTALFREQ_SHIFT 2
+#define PCTL_ILP_DIV_EN 0x00000002
+#define PCTL_LPO_SEL 0x00000001
+
+/* Retention Control */
+#define PMU_RCTL_CLK_DIV_SHIFT 0
+#define PMU_RCTL_CHAIN_LEN_SHIFT 12
+#define PMU_RCTL_MACPHY_DISABLE_SHIFT 26
+#define PMU_RCTL_MACPHY_DISABLE_MASK (1 << 26)
+#define PMU_RCTL_LOGIC_DISABLE_SHIFT 27
+#define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27)
+#define PMU_RCTL_MEMSLP_LOG_SHIFT 28
+#define PMU_RCTL_MEMSLP_LOG_MASK (1 << 28)
+#define PMU_RCTL_MEMRETSLP_LOG_SHIFT 29
+#define PMU_RCTL_MEMRETSLP_LOG_MASK (1 << 29)
+
+/* Retention Group Control */
+#define PMU_RCTLGRP_CHAIN_LEN_SHIFT 0
+#define PMU_RCTLGRP_RMODE_ENABLE_SHIFT 14
+#define PMU_RCTLGRP_RMODE_ENABLE_MASK (1 << 14)
+#define PMU_RCTLGRP_DFT_ENABLE_SHIFT 15
+#define PMU_RCTLGRP_DFT_ENABLE_MASK (1 << 15)
+#define PMU_RCTLGRP_NSRST_DISABLE_SHIFT 16
+#define PMU_RCTLGRP_NSRST_DISABLE_MASK (1 << 16)
+/* Retention Group Control special for 4334 */
+#define PMU4334_RCTLGRP_CHAIN_LEN_GRP0 338
+#define PMU4334_RCTLGRP_CHAIN_LEN_GRP1 315
+/* Retention Group Control special for 43341 */
+#define PMU43341_RCTLGRP_CHAIN_LEN_GRP0 366
+#define PMU43341_RCTLGRP_CHAIN_LEN_GRP1 330
+
+/* Fields in clkstretch */
+#define CSTRETCH_HT 0xffff0000
+#define CSTRETCH_ALP 0x0000ffff
+
+/* gpiotimerval */
+#define GPIO_ONTIME_SHIFT 16
+
+/* clockcontrol_n */
+#define CN_N1_MASK 0x3f /* n1 control */
+#define CN_N2_MASK 0x3f00 /* n2 control */
+#define CN_N2_SHIFT 8
+#define CN_PLLC_MASK 0xf0000 /* pll control */
+#define CN_PLLC_SHIFT 16
+
+/* clockcontrol_sb/pci/uart */
+#define CC_M1_MASK 0x3f /* m1 control */
+#define CC_M2_MASK 0x3f00 /* m2 control */
+#define CC_M2_SHIFT 8
+#define CC_M3_MASK 0x3f0000 /* m3 control */
+#define CC_M3_SHIFT 16
+#define CC_MC_MASK 0x1f000000 /* mux control */
+#define CC_MC_SHIFT 24
+
+/* N3M Clock control magic field values */
+#define CC_F6_2 0x02 /* A factor of 2 in */
+#define CC_F6_3 0x03 /* 6-bit fields like */
+#define CC_F6_4 0x05 /* N1, M1 or M3 */
+#define CC_F6_5 0x09
+#define CC_F6_6 0x11
+#define CC_F6_7 0x21
+
+#define CC_F5_BIAS 5 /* 5-bit fields get this added */
+
+#define CC_MC_BYPASS 0x08
+#define CC_MC_M1 0x04
+#define CC_MC_M1M2 0x02
+#define CC_MC_M1M2M3 0x01
+#define CC_MC_M1M3 0x11
+
+/* Type 2 Clock control magic field values */
+#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */
+#define CC_T2M2_BIAS 3 /* m2 bias */
+
+#define CC_T2MC_M1BYP 1
+#define CC_T2MC_M2BYP 2
+#define CC_T2MC_M3BYP 4
+
+/* Type 6 Clock control magic field values */
+#define CC_T6_MMASK 1 /* bits of interest in m */
+#define CC_T6_M0 120000000 /* sb clock for m = 0 */
+#define CC_T6_M1 100000000 /* sb clock for m = 1 */
+#define SB2MIPS_T6(sb) (2 * (sb))
+
+/* Common clock base */
+#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */
+#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLLs */
+
+/* Clock control values for 200MHz in 5350 */
+#define CLKC_5350_N 0x0311
+#define CLKC_5350_M 0x04020009
+
+/* Flash types in the chipcommon capabilities register */
+#define FLASH_NONE 0x000 /* No flash */
+#define SFLASH_ST 0x100 /* ST serial flash */
+#define SFLASH_AT 0x200 /* Atmel serial flash */
+#define NFLASH 0x300
+#define PFLASH 0x700 /* Parallel flash */
+#define QSPIFLASH_ST 0x800
+#define QSPIFLASH_AT 0x900
+
+/* Bits in the ExtBus config registers */
+#define CC_CFG_EN 0x0001 /* Enable */
+#define CC_CFG_EM_MASK 0x000e /* Extif Mode */
+#define CC_CFG_EM_ASYNC 0x0000 /* Async/Parallel flash */
+#define CC_CFG_EM_SYNC 0x0002 /* Synchronous */
+#define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */
+#define CC_CFG_EM_IDE 0x0006 /* IDE */
+#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */
+#define CC_CFG_CD_MASK 0x00e0 /* Sync: Clock divisor, rev >= 20 */
+#define CC_CFG_CE 0x0100 /* Sync: Clock enable, rev >= 20 */
+#define CC_CFG_SB 0x0200 /* Sync: Size/Bytestrobe, rev >= 20 */
+#define CC_CFG_IS 0x0400 /* Extif Sync Clk Select, rev >= 20 */
+
+/* ExtBus address space */
+#define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */
+#define CC_EB_PCMCIA_MEM 0x1a000000 /* PCMCIA 0 memory base address */
+#define CC_EB_PCMCIA_IO 0x1a200000 /* PCMCIA 0 I/O base address */
+#define CC_EB_PCMCIA_CFG 0x1a400000 /* PCMCIA 0 config base address */
+#define CC_EB_IDE 0x1a800000 /* IDE memory base */
+#define CC_EB_PCMCIA1_MEM 0x1a800000 /* PCMCIA 1 memory base address */
+#define CC_EB_PCMCIA1_IO 0x1aa00000 /* PCMCIA 1 I/O base address */
+#define CC_EB_PCMCIA1_CFG 0x1ac00000 /* PCMCIA 1 config base address */
+#define CC_EB_PROGIF 0x1b000000 /* ProgIF Async/Sync base address */
+
+
+/* Start/busy bit in flashcontrol */
+#define SFLASH_OPCODE 0x000000ff
+#define SFLASH_ACTION 0x00000700
+#define SFLASH_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */
+#define SFLASH_START 0x80000000
+#define SFLASH_BUSY SFLASH_START
+
+/* flashcontrol action codes */
+#define SFLASH_ACT_OPONLY 0x0000 /* Issue opcode only */
+#define SFLASH_ACT_OP1D 0x0100 /* opcode + 1 data byte */
+#define SFLASH_ACT_OP3A 0x0200 /* opcode + 3 addr bytes */
+#define SFLASH_ACT_OP3A1D 0x0300 /* opcode + 3 addr & 1 data bytes */
+#define SFLASH_ACT_OP3A4D 0x0400 /* opcode + 3 addr & 4 data bytes */
+#define SFLASH_ACT_OP3A4X4D 0x0500 /* opcode + 3 addr, 4 don't care & 4 data bytes */
+#define SFLASH_ACT_OP3A1X4D 0x0700 /* opcode + 3 addr, 1 don't care & 4 data bytes */
+
+/* flashcontrol action+opcodes for ST flashes */
+#define SFLASH_ST_WREN 0x0006 /* Write Enable */
+#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */
+#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */
+#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */
+#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */
+#define SFLASH_ST_PP 0x0302 /* Page Program */
+#define SFLASH_ST_SE 0x02d8 /* Sector Erase */
+#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */
+#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */
+#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */
+#define SFLASH_ST_CSA 0x1000 /* Keep chip select asserted */
+#define SFLASH_ST_SSE 0x0220 /* Sub-sector Erase */
+
+#define SFLASH_MXIC_RDID 0x0390 /* Read Manufacture ID */
+#define SFLASH_MXIC_MFID 0xc2 /* MXIC Manufacture ID */
+
+/* Status register bits for ST flashes */
+#define SFLASH_ST_WIP 0x01 /* Write In Progress */
+#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */
+#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */
+#define SFLASH_ST_BP_SHIFT 2
+#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */
+
+/* flashcontrol action+opcodes for Atmel flashes */
+#define SFLASH_AT_READ 0x07e8
+#define SFLASH_AT_PAGE_READ 0x07d2
+#define SFLASH_AT_BUF1_READ
+#define SFLASH_AT_BUF2_READ
+#define SFLASH_AT_STATUS 0x01d7
+#define SFLASH_AT_BUF1_WRITE 0x0384
+#define SFLASH_AT_BUF2_WRITE 0x0387
+#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283
+#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286
+#define SFLASH_AT_BUF1_PROGRAM 0x0288
+#define SFLASH_AT_BUF2_PROGRAM 0x0289
+#define SFLASH_AT_PAGE_ERASE 0x0281
+#define SFLASH_AT_BLOCK_ERASE 0x0250
+#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382
+#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385
+#define SFLASH_AT_BUF1_LOAD 0x0253
+#define SFLASH_AT_BUF2_LOAD 0x0255
+#define SFLASH_AT_BUF1_COMPARE 0x0260
+#define SFLASH_AT_BUF2_COMPARE 0x0261
+#define SFLASH_AT_BUF1_REPROGRAM 0x0258
+#define SFLASH_AT_BUF2_REPROGRAM 0x0259
+
+/* Status register bits for Atmel flashes */
+#define SFLASH_AT_READY 0x80
+#define SFLASH_AT_MISMATCH 0x40
+#define SFLASH_AT_ID_MASK 0x38
+#define SFLASH_AT_ID_SHIFT 3
+
+/* SPI register bits, corerev >= 37 */
+#define GSIO_START 0x80000000
+#define GSIO_BUSY GSIO_START
+
+/*
+ * These are the UART port assignments, expressed as offsets from the base
+ * register. These assignments should hold for any serial port based on
+ * a 8250, 16450, or 16550(A).
+ */
+
+#define UART_RX 0 /* In: Receive buffer (DLAB=0) */
+#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */
+#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
+#define UART_IER 1 /* In/Out: Interrupt Enable Register (DLAB=0) */
+#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */
+#define UART_IIR 2 /* In: Interrupt Identity Register */
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
+#define UART_LCR_WLEN8 0x03 /* Word length: 8 bits */
+#define UART_MCR_OUT2 0x08 /* MCR GPIO out 2 */
+#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
+#define UART_LSR_RX_FIFO 0x80 /* Receive FIFO error */
+#define UART_LSR_TDHR 0x40 /* Data-hold-register empty */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_BREAK 0x10 /* Break interrupt */
+#define UART_LSR_FRAMING 0x08 /* Framing error */
+#define UART_LSR_PARITY 0x04 /* Parity error */
+#define UART_LSR_OVERRUN 0x02 /* Overrun error */
+#define UART_LSR_RXRDY 0x01 /* Receiver ready */
+#define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */
+
+/* Interrupt Identity Register (IIR) bits */
+#define UART_IIR_FIFO_MASK 0xc0 /* IIR FIFO disable/enabled mask */
+#define UART_IIR_INT_MASK 0xf /* IIR interrupt ID source */
+#define UART_IIR_MDM_CHG 0x0 /* Modem status changed */
+#define UART_IIR_NOINT 0x1 /* No interrupt pending */
+#define UART_IIR_THRE 0x2 /* THR empty */
+#define UART_IIR_RCVD_DATA 0x4 /* Received data available */
+#define UART_IIR_RCVR_STATUS 0x6 /* Receiver status */
+#define UART_IIR_CHAR_TIME 0xc /* Character time */
+
+/* Interrupt Enable Register (IER) bits */
+#define UART_IER_PTIME 128 /* Programmable THRE Interrupt Mode Enable */
+#define UART_IER_EDSSI 8 /* enable modem status interrupt */
+#define UART_IER_ELSI 4 /* enable receiver line status interrupt */
+#define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */
+#define UART_IER_ERBFI 1 /* enable data available interrupt */
+
+/* pmustatus */
+#define PST_EXTLPOAVAIL 0x0100
+#define PST_WDRESET 0x0080
+#define PST_INTPEND 0x0040
+#define PST_SBCLKST 0x0030
+#define PST_SBCLKST_ILP 0x0010
+#define PST_SBCLKST_ALP 0x0020
+#define PST_SBCLKST_HT 0x0030
+#define PST_ALPAVAIL 0x0008
+#define PST_HTAVAIL 0x0004
+#define PST_RESINIT 0x0003
+
+/* pmucapabilities */
+#define PCAP_REV_MASK 0x000000ff
+#define PCAP_RC_MASK 0x00001f00
+#define PCAP_RC_SHIFT 8
+#define PCAP_TC_MASK 0x0001e000
+#define PCAP_TC_SHIFT 13
+#define PCAP_PC_MASK 0x001e0000
+#define PCAP_PC_SHIFT 17
+#define PCAP_VC_MASK 0x01e00000
+#define PCAP_VC_SHIFT 21
+#define PCAP_CC_MASK 0x1e000000
+#define PCAP_CC_SHIFT 25
+#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */
+#define PCAP5_PC_SHIFT 17
+#define PCAP5_VC_MASK 0x07c00000
+#define PCAP5_VC_SHIFT 22
+#define PCAP5_CC_MASK 0xf8000000
+#define PCAP5_CC_SHIFT 27
+
+/* PMU Resource Request Timer registers */
+/* This is based on PmuRev0 */
+#define PRRT_TIME_MASK 0x03ff
+#define PRRT_INTEN 0x0400
+#define PRRT_REQ_ACTIVE 0x0800
+#define PRRT_ALP_REQ 0x1000
+#define PRRT_HT_REQ 0x2000
+#define PRRT_HQ_REQ 0x4000
+
+/* PMU resource bit position */
+#define PMURES_BIT(bit) (1 << (bit))
+
+/* PMU resource number limit */
+#define PMURES_MAX_RESNUM 30
+
+/* PMU chip control0 register */
+#define PMU_CHIPCTL0 0
+#define PMU43143_CC0_SDIO_DRSTR_OVR (1 << 31) /* sdio drive strength override enable */
+
+/* clock req types */
+#define PMU_CC1_CLKREQ_TYPE_SHIFT 19
+#define PMU_CC1_CLKREQ_TYPE_MASK (1 << PMU_CC1_CLKREQ_TYPE_SHIFT)
+
+#define CLKREQ_TYPE_CONFIG_OPENDRAIN 0
+#define CLKREQ_TYPE_CONFIG_PUSHPULL 1
+
+/* PMU chip control1 register */
+#define PMU_CHIPCTL1 1
+#define PMU_CC1_RXC_DLL_BYPASS 0x00010000
+#define PMU_CC1_ENABLE_BBPLL_PWR_DOWN 0x00000010
+
+#define PMU_CC1_IF_TYPE_MASK 0x00000030
+#define PMU_CC1_IF_TYPE_RMII 0x00000000
+#define PMU_CC1_IF_TYPE_MII 0x00000010
+#define PMU_CC1_IF_TYPE_RGMII 0x00000020
+
+#define PMU_CC1_SW_TYPE_MASK 0x000000c0
+#define PMU_CC1_SW_TYPE_EPHY 0x00000000
+#define PMU_CC1_SW_TYPE_EPHYMII 0x00000040
+#define PMU_CC1_SW_TYPE_EPHYRMII 0x00000080
+#define PMU_CC1_SW_TYPE_RGMII 0x000000c0
+
+/* PMU chip control2 register */
+#define PMU_CHIPCTL2 2
+#define PMU_CC2_FORCE_SUBCORE_PWR_SWITCH_ON (1 << 18)
+#define PMU_CC2_FORCE_PHY_PWR_SWITCH_ON (1 << 19)
+#define PMU_CC2_FORCE_VDDM_PWR_SWITCH_ON (1 << 20)
+#define PMU_CC2_FORCE_MEMLPLDO_PWR_SWITCH_ON (1 << 21)
+
+/* PMU chip control3 register */
+#define PMU_CHIPCTL3 3
+
+/* PMU chip control6 register */
+#define PMU_CHIPCTL6 6
+#define PMU_CC6_ENABLE_CLKREQ_WAKEUP (1 << 4)
+#define PMU_CC6_ENABLE_PMU_WAKEUP_ALP (1 << 6)
+
+#define PMU_CC3_ENABLE_SDIO_WAKEUP_SHIFT 19
+#define PMU_CC3_ENABLE_RF_SHIFT 22
+#define PMU_CC3_RF_DISABLE_IVALUE_SHIFT 23
+
+/* PMU chip control5 register */
+#define PMU_CHIPCTL5 5
+
+/* PMU chip control6 register */
+#define PMU_CHIPCTL6 6
+#define PMU_CC6_ENABLE_CLKREQ_WAKEUP (1 << 4)
+#define PMU_CC6_ENABLE_PMU_WAKEUP_ALP (1 << 6)
+
+/* PMU corerev and chip specific PLL controls.
+ * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
+ * to differentiate different PLLs controlled by the same PMU rev.
+ */
+/* pllcontrol registers */
+/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */
+#define PMU0_PLL0_PLLCTL0 0
+#define PMU0_PLL0_PC0_PDIV_MASK 1
+#define PMU0_PLL0_PC0_PDIV_FREQ 25000
+#define PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038
+#define PMU0_PLL0_PC0_DIV_ARM_SHIFT 3
+#define PMU0_PLL0_PC0_DIV_ARM_BASE 8
+
+/* PC0_DIV_ARM for PLLOUT_ARM */
+#define PMU0_PLL0_PC0_DIV_ARM_110MHZ 0
+#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1
+#define PMU0_PLL0_PC0_DIV_ARM_88MHZ 2
+#define PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */
+#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4
+#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5
+#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6
+#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7
+
+/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */
+#define PMU0_PLL0_PLLCTL1 1
+#define PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000
+#define PMU0_PLL0_PC1_WILD_INT_SHIFT 28
+#define PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00
+#define PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8
+#define PMU0_PLL0_PC1_STOP_MOD 0x00000040
+
+/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */
+#define PMU0_PLL0_PLLCTL2 2
+#define PMU0_PLL0_PC2_WILD_INT_MASK 0xf
+#define PMU0_PLL0_PC2_WILD_INT_SHIFT 4
+
+/* pllcontrol registers */
+/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
+#define PMU1_PLL0_PLLCTL0 0
+#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000
+#define PMU1_PLL0_PC0_P1DIV_SHIFT 20
+#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000
+#define PMU1_PLL0_PC0_P2DIV_SHIFT 24
+
+/* m<x>div */
+#define PMU1_PLL0_PLLCTL1 1
+#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff
+#define PMU1_PLL0_PC1_M1DIV_SHIFT 0
+#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00
+#define PMU1_PLL0_PC1_M2DIV_SHIFT 8
+#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000
+#define PMU1_PLL0_PC1_M3DIV_SHIFT 16
+#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000
+#define PMU1_PLL0_PC1_M4DIV_SHIFT 24
+#define PMU1_PLL0_PC1_M4DIV_BY_9 9
+#define PMU1_PLL0_PC1_M4DIV_BY_18 0x12
+#define PMU1_PLL0_PC1_M4DIV_BY_36 0x24
+
+#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8
+#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
+#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
+
+/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
+#define PMU1_PLL0_PLLCTL2 2
+#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff
+#define PMU1_PLL0_PC2_M5DIV_SHIFT 0
+#define PMU1_PLL0_PC2_M5DIV_BY_12 0xc
+#define PMU1_PLL0_PC2_M5DIV_BY_18 0x12
+#define PMU1_PLL0_PC2_M5DIV_BY_36 0x24
+#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00
+#define PMU1_PLL0_PC2_M6DIV_SHIFT 8
+#define PMU1_PLL0_PC2_M6DIV_BY_18 0x12
+#define PMU1_PLL0_PC2_M6DIV_BY_36 0x24
+#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000
+#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17
+#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1
+#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */
+#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000
+#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20
+
+/* ndiv_frac */
+#define PMU1_PLL0_PLLCTL3 3
+#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff
+#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0
+
+/* pll_ctrl */
+#define PMU1_PLL0_PLLCTL4 4
+
+/* pll_ctrl, vco_rng, clkdrive_ch<x> */
+#define PMU1_PLL0_PLLCTL5 5
+#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00
+#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8
+
+#define PMU1_PLL0_PLLCTL6 6
+#define PMU1_PLL0_PLLCTL7 7
+
+/* PMU rev 2 control words */
+#define PMU2_PHY_PLL_PLLCTL 4
+#define PMU2_SI_PLL_PLLCTL 10
+
+/* PMU rev 2 */
+/* pllcontrol registers */
+/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
+#define PMU2_PLL_PLLCTL0 0
+#define PMU2_PLL_PC0_P1DIV_MASK 0x00f00000
+#define PMU2_PLL_PC0_P1DIV_SHIFT 20
+#define PMU2_PLL_PC0_P2DIV_MASK 0x0f000000
+#define PMU2_PLL_PC0_P2DIV_SHIFT 24
+
+/* m<x>div */
+#define PMU2_PLL_PLLCTL1 1
+#define PMU2_PLL_PC1_M1DIV_MASK 0x000000ff
+#define PMU2_PLL_PC1_M1DIV_SHIFT 0
+#define PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00
+#define PMU2_PLL_PC1_M2DIV_SHIFT 8
+#define PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000
+#define PMU2_PLL_PC1_M3DIV_SHIFT 16
+#define PMU2_PLL_PC1_M4DIV_MASK 0xff000000
+#define PMU2_PLL_PC1_M4DIV_SHIFT 24
+
+/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
+#define PMU2_PLL_PLLCTL2 2
+#define PMU2_PLL_PC2_M5DIV_MASK 0x000000ff
+#define PMU2_PLL_PC2_M5DIV_SHIFT 0
+#define PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00
+#define PMU2_PLL_PC2_M6DIV_SHIFT 8
+#define PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000
+#define PMU2_PLL_PC2_NDIV_MODE_SHIFT 17
+#define PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000
+#define PMU2_PLL_PC2_NDIV_INT_SHIFT 20
+
+/* ndiv_frac */
+#define PMU2_PLL_PLLCTL3 3
+#define PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff
+#define PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0
+
+/* pll_ctrl */
+#define PMU2_PLL_PLLCTL4 4
+
+/* pll_ctrl, vco_rng, clkdrive_ch<x> */
+#define PMU2_PLL_PLLCTL5 5
+#define PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00
+#define PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8
+#define PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000
+#define PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12
+#define PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000
+#define PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16
+#define PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000
+#define PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20
+#define PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000
+#define PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24
+#define PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000
+#define PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28
+
+/* PMU rev 5 (& 6) */
+#define PMU5_PLL_P1P2_OFF 0
+#define PMU5_PLL_P1_MASK 0x0f000000
+#define PMU5_PLL_P1_SHIFT 24
+#define PMU5_PLL_P2_MASK 0x00f00000
+#define PMU5_PLL_P2_SHIFT 20
+#define PMU5_PLL_M14_OFF 1
+#define PMU5_PLL_MDIV_MASK 0x000000ff
+#define PMU5_PLL_MDIV_WIDTH 8
+#define PMU5_PLL_NM5_OFF 2
+#define PMU5_PLL_NDIV_MASK 0xfff00000
+#define PMU5_PLL_NDIV_SHIFT 20
+#define PMU5_PLL_NDIV_MODE_MASK 0x000e0000
+#define PMU5_PLL_NDIV_MODE_SHIFT 17
+#define PMU5_PLL_FMAB_OFF 3
+#define PMU5_PLL_MRAT_MASK 0xf0000000
+#define PMU5_PLL_MRAT_SHIFT 28
+#define PMU5_PLL_ABRAT_MASK 0x08000000
+#define PMU5_PLL_ABRAT_SHIFT 27
+#define PMU5_PLL_FDIV_MASK 0x07ffffff
+#define PMU5_PLL_PLLCTL_OFF 4
+#define PMU5_PLL_PCHI_OFF 5
+#define PMU5_PLL_PCHI_MASK 0x0000003f
+
+/* pmu XtalFreqRatio */
+#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
+#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
+#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31
+
+/* Divider allocation in 4716/47162/5356/5357 */
+#define PMU5_MAINPLL_CPU 1
+#define PMU5_MAINPLL_MEM 2
+#define PMU5_MAINPLL_SI 3
+
+/* 4706 PMU */
+#define PMU4706_MAINPLL_PLL0 0
+#define PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */
+#define PMU6_4706_PROC_P2DIV_MASK 0x000f0000
+#define PMU6_4706_PROC_P2DIV_SHIFT 16
+#define PMU6_4706_PROC_P1DIV_MASK 0x0000f000
+#define PMU6_4706_PROC_P1DIV_SHIFT 12
+#define PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8
+#define PMU6_4706_PROC_NDIV_INT_SHIFT 3
+#define PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007
+#define PMU6_4706_PROC_NDIV_MODE_SHIFT 0
+
+#define PMU7_PLL_PLLCTL7 7
+#define PMU7_PLL_CTL7_M4DIV_MASK 0xff000000
+#define PMU7_PLL_CTL7_M4DIV_SHIFT 24
+#define PMU7_PLL_CTL7_M4DIV_BY_6 6
+#define PMU7_PLL_CTL7_M4DIV_BY_12 0xc
+#define PMU7_PLL_CTL7_M4DIV_BY_24 0x18
+#define PMU7_PLL_PLLCTL8 8
+#define PMU7_PLL_CTL8_M5DIV_MASK 0x000000ff
+#define PMU7_PLL_CTL8_M5DIV_SHIFT 0
+#define PMU7_PLL_CTL8_M5DIV_BY_8 8
+#define PMU7_PLL_CTL8_M5DIV_BY_12 0xc
+#define PMU7_PLL_CTL8_M5DIV_BY_24 0x18
+#define PMU7_PLL_CTL8_M6DIV_MASK 0x0000ff00
+#define PMU7_PLL_CTL8_M6DIV_SHIFT 8
+#define PMU7_PLL_CTL8_M6DIV_BY_12 0xc
+#define PMU7_PLL_CTL8_M6DIV_BY_24 0x18
+#define PMU7_PLL_PLLCTL11 11
+#define PMU7_PLL_PLLCTL11_MASK 0xffffff00
+#define PMU7_PLL_PLLCTL11_VAL 0x22222200
+
+/* PMU rev 15 */
+#define PMU15_PLL_PLLCTL0 0
+#define PMU15_PLL_PC0_CLKSEL_MASK 0x00000003
+#define PMU15_PLL_PC0_CLKSEL_SHIFT 0
+#define PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC
+#define PMU15_PLL_PC0_FREQTGT_SHIFT 2
+#define PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000
+#define PMU15_PLL_PC0_PRESCALE_SHIFT 22
+#define PMU15_PLL_PC0_KPCTRL_MASK 0x07000000
+#define PMU15_PLL_PC0_KPCTRL_SHIFT 24
+#define PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000
+#define PMU15_PLL_PC0_FCNTCTRL_SHIFT 27
+#define PMU15_PLL_PC0_FDCMODE_MASK 0x40000000
+#define PMU15_PLL_PC0_FDCMODE_SHIFT 30
+#define PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000
+#define PMU15_PLL_PC0_CTRLBIAS_SHIFT 31
+
+#define PMU15_PLL_PLLCTL1 1
+#define PMU15_PLL_PC1_BIAS_CTLM_MASK 0x00000060
+#define PMU15_PLL_PC1_BIAS_CTLM_SHIFT 5
+#define PMU15_PLL_PC1_BIAS_CTLM_RST_MASK 0x00000040
+#define PMU15_PLL_PC1_BIAS_CTLM_RST_SHIFT 6
+#define PMU15_PLL_PC1_BIAS_SS_DIVR_MASK 0x0001FF80
+#define PMU15_PLL_PC1_BIAS_SS_DIVR_SHIFT 7
+#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_MASK 0x03FE0000
+#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_SHIFT 17
+#define PMU15_PLL_PC1_BIAS_INTG_BW_MASK 0x0C000000
+#define PMU15_PLL_PC1_BIAS_INTG_BW_SHIFT 26
+#define PMU15_PLL_PC1_BIAS_INTG_BYP_MASK 0x10000000
+#define PMU15_PLL_PC1_BIAS_INTG_BYP_SHIFT 28
+#define PMU15_PLL_PC1_OPENLP_EN_MASK 0x40000000
+#define PMU15_PLL_PC1_OPENLP_EN_SHIFT 30
+
+#define PMU15_PLL_PLLCTL2 2
+#define PMU15_PLL_PC2_CTEN_MASK 0x00000001
+#define PMU15_PLL_PC2_CTEN_SHIFT 0
+
+#define PMU15_PLL_PLLCTL3 3
+#define PMU15_PLL_PC3_DITHER_EN_MASK 0x00000001
+#define PMU15_PLL_PC3_DITHER_EN_SHIFT 0
+#define PMU15_PLL_PC3_DCOCTLSP_MASK 0xFE000000
+#define PMU15_PLL_PC3_DCOCTLSP_SHIFT 25
+#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_MASK 0x01
+#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_SHIFT 0
+#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_MASK 0x02
+#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_SHIFT 1
+#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_MASK 0x04
+#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_SHIFT 2
+#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_MASK 0x18
+#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_SHIFT 3
+#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_MASK 0x60
+#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_SHIFT 5
+#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV1 0
+#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV2 1
+#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV3 2
+#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV5 3
+
+#define PMU15_PLL_PLLCTL4 4
+#define PMU15_PLL_PC4_FLLCLK1_DIV_MASK 0x00000007
+#define PMU15_PLL_PC4_FLLCLK1_DIV_SHIFT 0
+#define PMU15_PLL_PC4_FLLCLK2_DIV_MASK 0x00000038
+#define PMU15_PLL_PC4_FLLCLK2_DIV_SHIFT 3
+#define PMU15_PLL_PC4_FLLCLK3_DIV_MASK 0x000001C0
+#define PMU15_PLL_PC4_FLLCLK3_DIV_SHIFT 6
+#define PMU15_PLL_PC4_DBGMODE_MASK 0x00000E00
+#define PMU15_PLL_PC4_DBGMODE_SHIFT 9
+#define PMU15_PLL_PC4_FLL480_CTLSP_LK_MASK 0x00001000
+#define PMU15_PLL_PC4_FLL480_CTLSP_LK_SHIFT 12
+#define PMU15_PLL_PC4_FLL480_CTLSP_MASK 0x000FE000
+#define PMU15_PLL_PC4_FLL480_CTLSP_SHIFT 13
+#define PMU15_PLL_PC4_DINPOL_MASK 0x00100000
+#define PMU15_PLL_PC4_DINPOL_SHIFT 20
+#define PMU15_PLL_PC4_CLKOUT_PD_MASK 0x00200000
+#define PMU15_PLL_PC4_CLKOUT_PD_SHIFT 21
+#define PMU15_PLL_PC4_CLKDIV2_PD_MASK 0x00400000
+#define PMU15_PLL_PC4_CLKDIV2_PD_SHIFT 22
+#define PMU15_PLL_PC4_CLKDIV4_PD_MASK 0x00800000
+#define PMU15_PLL_PC4_CLKDIV4_PD_SHIFT 23
+#define PMU15_PLL_PC4_CLKDIV8_PD_MASK 0x01000000
+#define PMU15_PLL_PC4_CLKDIV8_PD_SHIFT 24
+#define PMU15_PLL_PC4_CLKDIV16_PD_MASK 0x02000000
+#define PMU15_PLL_PC4_CLKDIV16_PD_SHIFT 25
+#define PMU15_PLL_PC4_TEST_EN_MASK 0x04000000
+#define PMU15_PLL_PC4_TEST_EN_SHIFT 26
+
+#define PMU15_PLL_PLLCTL5 5
+#define PMU15_PLL_PC5_FREQTGT_MASK 0x000FFFFF
+#define PMU15_PLL_PC5_FREQTGT_SHIFT 0
+#define PMU15_PLL_PC5_DCOCTLSP_MASK 0x07F00000
+#define PMU15_PLL_PC5_DCOCTLSP_SHIFT 20
+#define PMU15_PLL_PC5_PRESCALE_MASK 0x18000000
+#define PMU15_PLL_PC5_PRESCALE_SHIFT 27
+
+#define PMU15_PLL_PLLCTL6 6
+#define PMU15_PLL_PC6_FREQTGT_MASK 0x000FFFFF
+#define PMU15_PLL_PC6_FREQTGT_SHIFT 0
+#define PMU15_PLL_PC6_DCOCTLSP_MASK 0x07F00000
+#define PMU15_PLL_PC6_DCOCTLSP_SHIFT 20
+#define PMU15_PLL_PC6_PRESCALE_MASK 0x18000000
+#define PMU15_PLL_PC6_PRESCALE_SHIFT 27
+
+#define PMU15_FREQTGT_480_DEFAULT 0x19AB1
+#define PMU15_FREQTGT_492_DEFAULT 0x1A4F5
+#define PMU15_ARM_96MHZ 96000000 /* 96 Mhz */
+#define PMU15_ARM_98MHZ 98400000 /* 98.4 Mhz */
+#define PMU15_ARM_97MHZ 97000000 /* 97 Mhz */
+
+
+#define PMU17_PLLCTL2_NDIVTYPE_MASK 0x00000070
+#define PMU17_PLLCTL2_NDIVTYPE_SHIFT 4
+
+#define PMU17_PLLCTL2_NDIV_MODE_INT 0
+#define PMU17_PLLCTL2_NDIV_MODE_INT1B8 1
+#define PMU17_PLLCTL2_NDIV_MODE_MASH111 2
+#define PMU17_PLLCTL2_NDIV_MODE_MASH111B8 3
+
+#define PMU17_PLLCTL0_BBPLL_PWRDWN 0
+#define PMU17_PLLCTL0_BBPLL_DRST 3
+#define PMU17_PLLCTL0_BBPLL_DISBL_CLK 8
+
+/* PLL usage in 4716/47162 */
+#define PMU4716_MAINPLL_PLL0 12
+
+/* PLL usage in 4335 */
+#define PMU4335_PLL0_PC2_P1DIV_MASK 0x000f0000
+#define PMU4335_PLL0_PC2_P1DIV_SHIFT 16
+#define PMU4335_PLL0_PC2_NDIV_INT_MASK 0xff800000
+#define PMU4335_PLL0_PC2_NDIV_INT_SHIFT 23
+#define PMU4335_PLL0_PC1_MDIV2_MASK 0x0000ff00
+#define PMU4335_PLL0_PC1_MDIV2_SHIFT 8
+
+
+/* PLL usage in 5356/5357 */
+#define PMU5356_MAINPLL_PLL0 0
+#define PMU5357_MAINPLL_PLL0 0
+
+/* 4716/47162 resources */
+#define RES4716_PROC_PLL_ON 0x00000040
+#define RES4716_PROC_HT_AVAIL 0x00000080
+
+/* 4716/4717/4718 Chip specific ChipControl register bits */
+#define CCTRL_471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared w/ pflash */
+
+/* 5357 Chip specific ChipControl register bits */
+/* 2nd - 32-bit reg */
+#define CCTRL_5357_I2S_PINS_ENABLE 0x00040000 /* I2S pins enable */
+#define CCTRL_5357_I2CSPI_PINS_ENABLE 0x00080000 /* I2C/SPI pins enable */
+
+/* 5354 resources */
+#define RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */
+#define RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */
+#define RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */
+#define RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */
+#define RES5354_ILP_REQUEST 4 /* 0x00010 */
+#define RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */
+#define RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */
+#define RES5354_ROM_SWITCH 7 /* 0x00080 */
+#define RES5354_PA_REF_LDO 8 /* 0x00100 */
+#define RES5354_RADIO_LDO 9 /* 0x00200 */
+#define RES5354_AFE_LDO 10 /* 0x00400 */
+#define RES5354_PLL_LDO 11 /* 0x00800 */
+#define RES5354_BG_FILTBYP 12 /* 0x01000 */
+#define RES5354_TX_FILTBYP 13 /* 0x02000 */
+#define RES5354_RX_FILTBYP 14 /* 0x04000 */
+#define RES5354_XTAL_PU 15 /* 0x08000 */
+#define RES5354_XTAL_EN 16 /* 0x10000 */
+#define RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */
+#define RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */
+#define RES5354_BB_PLL_PU 19 /* 0x80000 */
+
+/* 5357 Chip specific ChipControl register bits */
+#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */
+#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */
+#define CCTRL5357_NFLASH (1<<16) /* Nandflash in ChipControl 1, bit 16 */
+
+/* 43217 Chip specific ChipControl register bits */
+#define CCTRL43217_EXTPA_C0 (1<<13) /* core0 extPA in ChipControl 1, bit 13 */
+#define CCTRL43217_EXTPA_C1 (1<<8) /* core1 extPA in ChipControl 1, bit 8 */
+
+/* 43228 Chip specific ChipControl register bits */
+#define CCTRL43228_EXTPA_C0 (1<<14) /* core1 extPA in ChipControl 1, bit 14 */
+#define CCTRL43228_EXTPA_C1 (1<<9) /* core0 extPA in ChipControl 1, bit 1 */
+
+/* 4328 resources */
+#define RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */
+#define RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */
+#define RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */
+#define RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */
+#define RES4328_ILP_REQUEST 4 /* 0x00010 */
+#define RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */
+#define RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */
+#define RES4328_ROM_SWITCH 7 /* 0x00080 */
+#define RES4328_PA_REF_LDO 8 /* 0x00100 */
+#define RES4328_RADIO_LDO 9 /* 0x00200 */
+#define RES4328_AFE_LDO 10 /* 0x00400 */
+#define RES4328_PLL_LDO 11 /* 0x00800 */
+#define RES4328_BG_FILTBYP 12 /* 0x01000 */
+#define RES4328_TX_FILTBYP 13 /* 0x02000 */
+#define RES4328_RX_FILTBYP 14 /* 0x04000 */
+#define RES4328_XTAL_PU 15 /* 0x08000 */
+#define RES4328_XTAL_EN 16 /* 0x10000 */
+#define RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */
+#define RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */
+#define RES4328_BB_PLL_PU 19 /* 0x80000 */
+
+/* 4325 A0/A1 resources */
+#define RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */
+#define RES4325_CBUCK_BURST 1 /* 0x00000002 */
+#define RES4325_CBUCK_PWM 2 /* 0x00000004 */
+#define RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */
+#define RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */
+#define RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */
+#define RES4325_ILP_REQUEST 6 /* 0x00000040 */
+#define RES4325_ABUCK_BURST 7 /* 0x00000080 */
+#define RES4325_ABUCK_PWM 8 /* 0x00000100 */
+#define RES4325_LNLDO1_PU 9 /* 0x00000200 */
+#define RES4325_OTP_PU 10 /* 0x00000400 */
+#define RES4325_LNLDO3_PU 11 /* 0x00000800 */
+#define RES4325_LNLDO4_PU 12 /* 0x00001000 */
+#define RES4325_XTAL_PU 13 /* 0x00002000 */
+#define RES4325_ALP_AVAIL 14 /* 0x00004000 */
+#define RES4325_RX_PWRSW_PU 15 /* 0x00008000 */
+#define RES4325_TX_PWRSW_PU 16 /* 0x00010000 */
+#define RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */
+#define RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */
+#define RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */
+#define RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */
+#define RES4325_HT_AVAIL 21 /* 0x00200000 */
+
+/* 4325 B0/C0 resources */
+#define RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */
+#define RES4325B0_CBUCK_BURST 2 /* 0x00000004 */
+#define RES4325B0_CBUCK_PWM 3 /* 0x00000008 */
+#define RES4325B0_CLDO_PU 4 /* 0x00000010 */
+
+/* 4325 C1 resources */
+#define RES4325C1_LNLDO2_PU 12 /* 0x00001000 */
+
+/* 4325 chip-specific ChipStatus register bits */
+#define CST4325_SPROM_OTP_SEL_MASK 0x00000003
+#define CST4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */
+#define CST4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */
+#define CST4325_OTP_SEL 2 /* OTP is powered up, no SPROM */
+#define CST4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */
+#define CST4325_SDIO_USB_MODE_MASK 0x00000004
+#define CST4325_SDIO_USB_MODE_SHIFT 2
+#define CST4325_RCAL_VALID_MASK 0x00000008
+#define CST4325_RCAL_VALID_SHIFT 3
+#define CST4325_RCAL_VALUE_MASK 0x000001f0
+#define CST4325_RCAL_VALUE_SHIFT 4
+#define CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */
+#define CST4325_PMUTOP_2B_SHIFT 9
+
+#define RES4329_RESERVED0 0 /* 0x00000001 */
+#define RES4329_CBUCK_LPOM 1 /* 0x00000002 */
+#define RES4329_CBUCK_BURST 2 /* 0x00000004 */
+#define RES4329_CBUCK_PWM 3 /* 0x00000008 */
+#define RES4329_CLDO_PU 4 /* 0x00000010 */
+#define RES4329_PALDO_PU 5 /* 0x00000020 */
+#define RES4329_ILP_REQUEST 6 /* 0x00000040 */
+#define RES4329_RESERVED7 7 /* 0x00000080 */
+#define RES4329_RESERVED8 8 /* 0x00000100 */
+#define RES4329_LNLDO1_PU 9 /* 0x00000200 */
+#define RES4329_OTP_PU 10 /* 0x00000400 */
+#define RES4329_RESERVED11 11 /* 0x00000800 */
+#define RES4329_LNLDO2_PU 12 /* 0x00001000 */
+#define RES4329_XTAL_PU 13 /* 0x00002000 */
+#define RES4329_ALP_AVAIL 14 /* 0x00004000 */
+#define RES4329_RX_PWRSW_PU 15 /* 0x00008000 */
+#define RES4329_TX_PWRSW_PU 16 /* 0x00010000 */
+#define RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */
+#define RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */
+#define RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */
+#define RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */
+#define RES4329_HT_AVAIL 21 /* 0x00200000 */
+
+#define CST4329_SPROM_OTP_SEL_MASK 0x00000003
+#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */
+#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */
+#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */
+#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */
+#define CST4329_SPI_SDIO_MODE_MASK 0x00000004
+#define CST4329_SPI_SDIO_MODE_SHIFT 2
+
+/* 4312 chip-specific ChipStatus register bits */
+#define CST4312_SPROM_OTP_SEL_MASK 0x00000003
+#define CST4312_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */
+#define CST4312_SPROM_SEL 1 /* OTP is powered up, SPROM is present */
+#define CST4312_OTP_SEL 2 /* OTP is powered up, no SPROM */
+#define CST4312_OTP_BAD 3 /* OTP is broken, SPROM is present */
+
+/* 4312 resources (all PMU chips with little memory constraint) */
+#define RES4312_SWITCHER_BURST 0 /* 0x00000001 */
+#define RES4312_SWITCHER_PWM 1 /* 0x00000002 */
+#define RES4312_PA_REF_LDO 2 /* 0x00000004 */
+#define RES4312_CORE_LDO_BURST 3 /* 0x00000008 */
+#define RES4312_CORE_LDO_PWM 4 /* 0x00000010 */
+#define RES4312_RADIO_LDO 5 /* 0x00000020 */
+#define RES4312_ILP_REQUEST 6 /* 0x00000040 */
+#define RES4312_BG_FILTBYP 7 /* 0x00000080 */
+#define RES4312_TX_FILTBYP 8 /* 0x00000100 */
+#define RES4312_RX_FILTBYP 9 /* 0x00000200 */
+#define RES4312_XTAL_PU 10 /* 0x00000400 */
+#define RES4312_ALP_AVAIL 11 /* 0x00000800 */
+#define RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */
+#define RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */
+#define RES4312_HT_AVAIL 14 /* 0x00004000 */
+
+/* 4322 resources */
+#define RES4322_RF_LDO 0
+#define RES4322_ILP_REQUEST 1
+#define RES4322_XTAL_PU 2
+#define RES4322_ALP_AVAIL 3
+#define RES4322_SI_PLL_ON 4
+#define RES4322_HT_SI_AVAIL 5
+#define RES4322_PHY_PLL_ON 6
+#define RES4322_HT_PHY_AVAIL 7
+#define RES4322_OTP_PU 8
+
+/* 4322 chip-specific ChipStatus register bits */
+#define CST4322_XTAL_FREQ_20_40MHZ 0x00000020
+#define CST4322_SPROM_OTP_SEL_MASK 0x000000c0
+#define CST4322_SPROM_OTP_SEL_SHIFT 6
+#define CST4322_NO_SPROM_OTP 0 /* no OTP, no SPROM */
+#define CST4322_SPROM_PRESENT 1 /* SPROM is present */
+#define CST4322_OTP_PRESENT 2 /* OTP is present */
+#define CST4322_PCI_OR_USB 0x00000100
+#define CST4322_BOOT_MASK 0x00000600
+#define CST4322_BOOT_SHIFT 9
+#define CST4322_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */
+#define CST4322_BOOT_FROM_ROM 1 /* boot from ROM */
+#define CST4322_BOOT_FROM_FLASH 2 /* boot from FLASH */
+#define CST4322_BOOT_FROM_INVALID 3
+#define CST4322_ILP_DIV_EN 0x00000800
+#define CST4322_FLASH_TYPE_MASK 0x00001000
+#define CST4322_FLASH_TYPE_SHIFT 12
+#define CST4322_FLASH_TYPE_SHIFT_ST 0 /* ST serial FLASH */
+#define CST4322_FLASH_TYPE_SHIFT_ATMEL 1 /* ATMEL flash */
+#define CST4322_ARM_TAP_SEL 0x00002000
+#define CST4322_RES_INIT_MODE_MASK 0x0000c000
+#define CST4322_RES_INIT_MODE_SHIFT 14
+#define CST4322_RES_INIT_MODE_ILPAVAIL 0 /* resinitmode: ILP available */
+#define CST4322_RES_INIT_MODE_ILPREQ 1 /* resinitmode: ILP request */
+#define CST4322_RES_INIT_MODE_ALPAVAIL 2 /* resinitmode: ALP available */
+#define CST4322_RES_INIT_MODE_HTAVAIL 3 /* resinitmode: HT available */
+#define CST4322_PCIPLLCLK_GATING 0x00010000
+#define CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000
+#define CST4322_PCI_CARDBUS_MODE 0x00040000
+
+/* 43224 chip-specific ChipControl register bits */
+#define CCTRL43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */
+#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
+#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
+
+/* 43236 resources */
+#define RES43236_REGULATOR 0
+#define RES43236_ILP_REQUEST 1
+#define RES43236_XTAL_PU 2
+#define RES43236_ALP_AVAIL 3
+#define RES43236_SI_PLL_ON 4
+#define RES43236_HT_SI_AVAIL 5
+
+/* 43236 chip-specific ChipControl register bits */
+#define CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */
+#define CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
+#define CCTRL43236_EXT_LNA (1<<2) /* 0 disable */
+#define CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */
+#define CCTRL43236_GSIO (1<<4) /* 0 disable */
+
+/* 43236 Chip specific ChipStatus register bits */
+#define CST43236_SFLASH_MASK 0x00000040
+#define CST43236_OTP_SEL_MASK 0x00000080
+#define CST43236_OTP_SEL_SHIFT 7
+#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */
+#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */
+#define CST43236_BOOT_MASK 0x00001800
+#define CST43236_BOOT_SHIFT 11
+#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */
+#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */
+#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */
+#define CST43236_BOOT_FROM_INVALID 3
+
+/* 43237 resources */
+#define RES43237_REGULATOR 0
+#define RES43237_ILP_REQUEST 1
+#define RES43237_XTAL_PU 2
+#define RES43237_ALP_AVAIL 3
+#define RES43237_SI_PLL_ON 4
+#define RES43237_HT_SI_AVAIL 5
+
+/* 43237 chip-specific ChipControl register bits */
+#define CCTRL43237_BT_COEXIST (1<<0) /* 0 disable */
+#define CCTRL43237_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
+#define CCTRL43237_EXT_LNA (1<<2) /* 0 disable */
+#define CCTRL43237_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */
+#define CCTRL43237_GSIO (1<<4) /* 0 disable */
+
+/* 43237 Chip specific ChipStatus register bits */
+#define CST43237_SFLASH_MASK 0x00000040
+#define CST43237_OTP_SEL_MASK 0x00000080
+#define CST43237_OTP_SEL_SHIFT 7
+#define CST43237_HSIC_MASK 0x00000100 /* USB/HSIC */
+#define CST43237_BP_CLK 0x00000200 /* 120/96Mbps */
+#define CST43237_BOOT_MASK 0x00001800
+#define CST43237_BOOT_SHIFT 11
+#define CST43237_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */
+#define CST43237_BOOT_FROM_ROM 1 /* boot from ROM */
+#define CST43237_BOOT_FROM_FLASH 2 /* boot from FLASH */
+#define CST43237_BOOT_FROM_INVALID 3
+
+/* 43239 resources */
+#define RES43239_OTP_PU 9
+#define RES43239_MACPHY_CLKAVAIL 23
+#define RES43239_HT_AVAIL 24
+
+/* 43239 Chip specific ChipStatus register bits */
+#define CST43239_SPROM_MASK 0x00000002
+#define CST43239_SFLASH_MASK 0x00000004
+#define CST43239_RES_INIT_MODE_SHIFT 7
+#define CST43239_RES_INIT_MODE_MASK 0x000001f0
+#define CST43239_CHIPMODE_SDIOD(cs) ((cs) & (1 << 15)) /* SDIO || gSPI */
+#define CST43239_CHIPMODE_USB20D(cs) (~(cs) & (1 << 15)) /* USB || USBDA */
+#define CST43239_CHIPMODE_SDIO(cs) (((cs) & (1 << 0)) == 0) /* SDIO */
+#define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) /* gSPI */
+
+/* 4324 resources */
+/* 43242 use same PMU as 4324 */
+#define RES4324_LPLDO_PU 0
+#define RES4324_RESET_PULLDN_DIS 1
+#define RES4324_PMU_BG_PU 2
+#define RES4324_HSIC_LDO_PU 3
+#define RES4324_CBUCK_LPOM_PU 4
+#define RES4324_CBUCK_PFM_PU 5
+#define RES4324_CLDO_PU 6
+#define RES4324_LPLDO2_LVM 7
+#define RES4324_LNLDO1_PU 8
+#define RES4324_LNLDO2_PU 9
+#define RES4324_LDO3P3_PU 10
+#define RES4324_OTP_PU 11
+#define RES4324_XTAL_PU 12
+#define RES4324_BBPLL_PU 13
+#define RES4324_LQ_AVAIL 14
+#define RES4324_WL_CORE_READY 17
+#define RES4324_ILP_REQ 18
+#define RES4324_ALP_AVAIL 19
+#define RES4324_PALDO_PU 20
+#define RES4324_RADIO_PU 21
+#define RES4324_SR_CLK_STABLE 22
+#define RES4324_SR_SAVE_RESTORE 23
+#define RES4324_SR_PHY_PWRSW 24
+#define RES4324_SR_PHY_PIC 25
+#define RES4324_SR_SUBCORE_PWRSW 26
+#define RES4324_SR_SUBCORE_PIC 27
+#define RES4324_SR_MEM_PM0 28
+#define RES4324_HT_AVAIL 29
+#define RES4324_MACPHY_CLKAVAIL 30
+
+/* 4324 Chip specific ChipStatus register bits */
+#define CST4324_SPROM_MASK 0x00000080
+#define CST4324_SFLASH_MASK 0x00400000
+#define CST4324_RES_INIT_MODE_SHIFT 10
+#define CST4324_RES_INIT_MODE_MASK 0x00000c00
+#define CST4324_CHIPMODE_MASK 0x7
+#define CST4324_CHIPMODE_SDIOD(cs) ((~(cs)) & (1 << 2)) /* SDIO || gSPI */
+#define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) /* USB || USBDA */
+
+/* 43242 Chip specific ChipStatus register bits */
+#define CST43242_SFLASH_MASK 0x00000008
+#define CST43242_SR_HALT (1<<25)
+#define CST43242_SR_CHIP_STATUS_2 27 /* bit 27 */
+
+/* 4331 resources */
+#define RES4331_REGULATOR 0
+#define RES4331_ILP_REQUEST 1
+#define RES4331_XTAL_PU 2
+#define RES4331_ALP_AVAIL 3
+#define RES4331_SI_PLL_ON 4
+#define RES4331_HT_SI_AVAIL 5
+
+/* 4331 chip-specific ChipControl register bits */
+#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */
+#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
+#define CCTRL4331_EXT_LNA_G (1<<2) /* 0 disable */
+#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */
+#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */
+#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */
+#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */
+#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */
+#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */
+#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */
+#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */
+#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */
+#define CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa disable, 1 ext pa enabled */
+#define CCTRL4331_EXT_LNA_A (1<<13) /* 0 disable */
+#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */
+#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */
+#define CCTRL4331_EXTPA_ANA_EN (1<<24) /* 0 ext pa disable, 1 ext pa enabled */
+
+/* 4331 Chip specific ChipStatus register bits */
+#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */
+#define CST4331_SPROM_OTP_SEL_MASK 0x00000006
+#define CST4331_SPROM_OTP_SEL_SHIFT 1
+#define CST4331_SPROM_PRESENT 0x00000002
+#define CST4331_OTP_PRESENT 0x00000004
+#define CST4331_LDO_RF 0x00000008
+#define CST4331_LDO_PAR 0x00000010
+
+/* 4315 resource */
+#define RES4315_CBUCK_LPOM 1 /* 0x00000002 */
+#define RES4315_CBUCK_BURST 2 /* 0x00000004 */
+#define RES4315_CBUCK_PWM 3 /* 0x00000008 */
+#define RES4315_CLDO_PU 4 /* 0x00000010 */
+#define RES4315_PALDO_PU 5 /* 0x00000020 */
+#define RES4315_ILP_REQUEST 6 /* 0x00000040 */
+#define RES4315_LNLDO1_PU 9 /* 0x00000200 */
+#define RES4315_OTP_PU 10 /* 0x00000400 */
+#define RES4315_LNLDO2_PU 12 /* 0x00001000 */
+#define RES4315_XTAL_PU 13 /* 0x00002000 */
+#define RES4315_ALP_AVAIL 14 /* 0x00004000 */
+#define RES4315_RX_PWRSW_PU 15 /* 0x00008000 */
+#define RES4315_TX_PWRSW_PU 16 /* 0x00010000 */
+#define RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */
+#define RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */
+#define RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */
+#define RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */
+#define RES4315_HT_AVAIL 21 /* 0x00200000 */
+
+/* 4315 chip-specific ChipStatus register bits */
+#define CST4315_SPROM_OTP_SEL_MASK 0x00000003 /* gpio [7:6], SDIO CIS selection */
+#define CST4315_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */
+#define CST4315_SPROM_SEL 0x00000001 /* use SPROM, OTP is powered up */
+#define CST4315_OTP_SEL 0x00000002 /* use OTP, OTP is powered up */
+#define CST4315_OTP_PWRDN 0x00000003 /* use SPROM, OTP is powered down */
+#define CST4315_SDIO_MODE 0x00000004 /* gpio [8], sdio/usb mode */
+#define CST4315_RCAL_VALID 0x00000008
+#define CST4315_RCAL_VALUE_MASK 0x000001f0
+#define CST4315_RCAL_VALUE_SHIFT 4
+#define CST4315_PALDO_EXTPNP 0x00000200 /* PALDO is configured with external PNP */
+#define CST4315_CBUCK_MODE_MASK 0x00000c00
+#define CST4315_CBUCK_MODE_BURST 0x00000400
+#define CST4315_CBUCK_MODE_LPBURST 0x00000c00
+
+/* 4319 resources */
+#define RES4319_CBUCK_LPOM 1 /* 0x00000002 */
+#define RES4319_CBUCK_BURST 2 /* 0x00000004 */
+#define RES4319_CBUCK_PWM 3 /* 0x00000008 */
+#define RES4319_CLDO_PU 4 /* 0x00000010 */
+#define RES4319_PALDO_PU 5 /* 0x00000020 */
+#define RES4319_ILP_REQUEST 6 /* 0x00000040 */
+#define RES4319_LNLDO1_PU 9 /* 0x00000200 */
+#define RES4319_OTP_PU 10 /* 0x00000400 */
+#define RES4319_LNLDO2_PU 12 /* 0x00001000 */
+#define RES4319_XTAL_PU 13 /* 0x00002000 */
+#define RES4319_ALP_AVAIL 14 /* 0x00004000 */
+#define RES4319_RX_PWRSW_PU 15 /* 0x00008000 */
+#define RES4319_TX_PWRSW_PU 16 /* 0x00010000 */
+#define RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */
+#define RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */
+#define RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */
+#define RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */
+#define RES4319_HT_AVAIL 21 /* 0x00200000 */
+
+/* 4319 chip-specific ChipStatus register bits */
+#define CST4319_SPI_CPULESSUSB 0x00000001
+#define CST4319_SPI_CLK_POL 0x00000002
+#define CST4319_SPI_CLK_PH 0x00000008
+#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */
+#define CST4319_SPROM_OTP_SEL_SHIFT 6
+#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */
+#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */
+#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */
+#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */
+#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */
+#define CST4319_REMAP_SEL_MASK 0x00000600
+#define CST4319_ILPDIV_EN 0x00000800
+#define CST4319_XTAL_PD_POL 0x00001000
+#define CST4319_LPO_SEL 0x00002000
+#define CST4319_RES_INIT_MODE 0x0000c000
+#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */
+#define CST4319_CBUCK_MODE_MASK 0x00060000
+#define CST4319_CBUCK_MODE_BURST 0x00020000
+#define CST4319_CBUCK_MODE_LPBURST 0x00060000
+#define CST4319_RCAL_VALID 0x01000000
+#define CST4319_RCAL_VALUE_MASK 0x3e000000
+#define CST4319_RCAL_VALUE_SHIFT 25
+
+#define PMU1_PLL0_CHIPCTL0 0
+#define PMU1_PLL0_CHIPCTL1 1
+#define PMU1_PLL0_CHIPCTL2 2
+#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000
+#define CCTL_4319USB_XTAL_SEL_SHIFT 19
+#define CCTL_4319USB_48MHZ_PLL_SEL 1
+#define CCTL_4319USB_24MHZ_PLL_SEL 2
+
+/* PMU resources for 4336 */
+#define RES4336_CBUCK_LPOM 0
+#define RES4336_CBUCK_BURST 1
+#define RES4336_CBUCK_LP_PWM 2
+#define RES4336_CBUCK_PWM 3
+#define RES4336_CLDO_PU 4
+#define RES4336_DIS_INT_RESET_PD 5
+#define RES4336_ILP_REQUEST 6
+#define RES4336_LNLDO_PU 7
+#define RES4336_LDO3P3_PU 8
+#define RES4336_OTP_PU 9
+#define RES4336_XTAL_PU 10
+#define RES4336_ALP_AVAIL 11
+#define RES4336_RADIO_PU 12
+#define RES4336_BG_PU 13
+#define RES4336_VREG1p4_PU_PU 14
+#define RES4336_AFE_PWRSW_PU 15
+#define RES4336_RX_PWRSW_PU 16
+#define RES4336_TX_PWRSW_PU 17
+#define RES4336_BB_PWRSW_PU 18
+#define RES4336_SYNTH_PWRSW_PU 19
+#define RES4336_MISC_PWRSW_PU 20
+#define RES4336_LOGEN_PWRSW_PU 21
+#define RES4336_BBPLL_PWRSW_PU 22
+#define RES4336_MACPHY_CLKAVAIL 23
+#define RES4336_HT_AVAIL 24
+#define RES4336_RSVD 25
+
+/* 4336 chip-specific ChipStatus register bits */
+#define CST4336_SPI_MODE_MASK 0x00000001
+#define CST4336_SPROM_PRESENT 0x00000002
+#define CST4336_OTP_PRESENT 0x00000004
+#define CST4336_ARMREMAP_0 0x00000008
+#define CST4336_ILPDIV_EN_MASK 0x00000010
+#define CST4336_ILPDIV_EN_SHIFT 4
+#define CST4336_XTAL_PD_POL_MASK 0x00000020
+#define CST4336_XTAL_PD_POL_SHIFT 5
+#define CST4336_LPO_SEL_MASK 0x00000040
+#define CST4336_LPO_SEL_SHIFT 6
+#define CST4336_RES_INIT_MODE_MASK 0x00000180
+#define CST4336_RES_INIT_MODE_SHIFT 7
+#define CST4336_CBUCK_MODE_MASK 0x00000600
+#define CST4336_CBUCK_MODE_SHIFT 9
+
+/* 4336 Chip specific PMU ChipControl register bits */
+#define PCTL_4336_SERIAL_ENAB (1 << 24)
+
+/* 4330 resources */
+#define RES4330_CBUCK_LPOM 0
+#define RES4330_CBUCK_BURST 1
+#define RES4330_CBUCK_LP_PWM 2
+#define RES4330_CBUCK_PWM 3
+#define RES4330_CLDO_PU 4
+#define RES4330_DIS_INT_RESET_PD 5
+#define RES4330_ILP_REQUEST 6
+#define RES4330_LNLDO_PU 7
+#define RES4330_LDO3P3_PU 8
+#define RES4330_OTP_PU 9
+#define RES4330_XTAL_PU 10
+#define RES4330_ALP_AVAIL 11
+#define RES4330_RADIO_PU 12
+#define RES4330_BG_PU 13
+#define RES4330_VREG1p4_PU_PU 14
+#define RES4330_AFE_PWRSW_PU 15
+#define RES4330_RX_PWRSW_PU 16
+#define RES4330_TX_PWRSW_PU 17
+#define RES4330_BB_PWRSW_PU 18
+#define RES4330_SYNTH_PWRSW_PU 19
+#define RES4330_MISC_PWRSW_PU 20
+#define RES4330_LOGEN_PWRSW_PU 21
+#define RES4330_BBPLL_PWRSW_PU 22
+#define RES4330_MACPHY_CLKAVAIL 23
+#define RES4330_HT_AVAIL 24
+#define RES4330_5gRX_PWRSW_PU 25
+#define RES4330_5gTX_PWRSW_PU 26
+#define RES4330_5g_LOGEN_PWRSW_PU 27
+
+/* 4330 chip-specific ChipStatus register bits */
+#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */
+#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */
+#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */
+#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */
+#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */
+#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */
+#define CST4330_OTP_PRESENT 0x00000010
+#define CST4330_LPO_AUTODET_EN 0x00000020
+#define CST4330_ARMREMAP_0 0x00000040
+#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */
+#define CST4330_ILPDIV_EN 0x00000100
+#define CST4330_LPO_SEL 0x00000200
+#define CST4330_RES_INIT_MODE_SHIFT 10
+#define CST4330_RES_INIT_MODE_MASK 0x00000c00
+#define CST4330_CBUCK_MODE_SHIFT 12
+#define CST4330_CBUCK_MODE_MASK 0x00003000
+#define CST4330_CBUCK_POWER_OK 0x00004000
+#define CST4330_BB_PLL_LOCKED 0x00008000
+#define SOCDEVRAM_BP_ADDR 0x1E000000
+#define SOCDEVRAM_ARM_ADDR 0x00800000
+
+/* 4330 Chip specific PMU ChipControl register bits */
+#define PCTL_4330_SERIAL_ENAB (1 << 24)
+
+/* 4330 Chip specific ChipControl register bits */
+#define CCTRL_4330_GPIO_SEL 0x00000001 /* 1=select GPIOs to be muxed out */
+#define CCTRL_4330_ERCX_SEL 0x00000002 /* 1=select ERCX BT coex to be muxed out */
+#define CCTRL_4330_SDIO_HOST_WAKE 0x00000004 /* SDIO: 1=configure GPIO0 for host wake */
+#define CCTRL_4330_JTAG_DISABLE 0x00000008 /* 1=disable JTAG interface on mux'd pins */
+
+#define PMU_VREG0_ADDR 0
+#define PMU_VREG0_DISABLE_PULLD_BT_SHIFT 2
+#define PMU_VREG0_DISABLE_PULLD_WL_SHIFT 3
+
+#define PMU_VREG4_ADDR 4
+
+#define PMU_VREG4_CLDO_PWM_SHIFT 4
+#define PMU_VREG4_CLDO_PWM_MASK 0x7
+
+#define PMU_VREG4_LPLDO1_SHIFT 15
+#define PMU_VREG4_LPLDO1_MASK 0x7
+#define PMU_VREG4_LPLDO1_1p20V 0
+#define PMU_VREG4_LPLDO1_1p15V 1
+#define PMU_VREG4_LPLDO1_1p10V 2
+#define PMU_VREG4_LPLDO1_1p25V 3
+#define PMU_VREG4_LPLDO1_1p05V 4
+#define PMU_VREG4_LPLDO1_1p00V 5
+#define PMU_VREG4_LPLDO1_0p95V 6
+#define PMU_VREG4_LPLDO1_0p90V 7
+
+#define PMU_VREG4_LPLDO2_LVM_SHIFT 18
+#define PMU_VREG4_LPLDO2_LVM_MASK 0x7
+#define PMU_VREG4_LPLDO2_HVM_SHIFT 21
+#define PMU_VREG4_LPLDO2_HVM_MASK 0x7
+#define PMU_VREG4_LPLDO2_LVM_HVM_MASK 0x3f
+#define PMU_VREG4_LPLDO2_1p00V 0
+#define PMU_VREG4_LPLDO2_1p15V 1
+#define PMU_VREG4_LPLDO2_1p20V 2
+#define PMU_VREG4_LPLDO2_1p10V 3
+#define PMU_VREG4_LPLDO2_0p90V 4 /* 4 - 7 is 0.90V */
+
+#define PMU_VREG4_HSICLDO_BYPASS_SHIFT 27
+#define PMU_VREG4_HSICLDO_BYPASS_MASK 0x1
+
+#define PMU_VREG5_ADDR 5
+#define PMU_VREG5_HSICAVDD_PD_SHIFT 6
+#define PMU_VREG5_HSICAVDD_PD_MASK 0x1
+#define PMU_VREG5_HSICDVDD_PD_SHIFT 11
+#define PMU_VREG5_HSICDVDD_PD_MASK 0x1
+
+/* 4334 resources */
+#define RES4334_LPLDO_PU 0
+#define RES4334_RESET_PULLDN_DIS 1
+#define RES4334_PMU_BG_PU 2
+#define RES4334_HSIC_LDO_PU 3
+#define RES4334_CBUCK_LPOM_PU 4
+#define RES4334_CBUCK_PFM_PU 5
+#define RES4334_CLDO_PU 6
+#define RES4334_LPLDO2_LVM 7
+#define RES4334_LNLDO_PU 8
+#define RES4334_LDO3P3_PU 9
+#define RES4334_OTP_PU 10
+#define RES4334_XTAL_PU 11
+#define RES4334_WL_PWRSW_PU 12
+#define RES4334_LQ_AVAIL 13
+#define RES4334_LOGIC_RET 14
+#define RES4334_MEM_SLEEP 15
+#define RES4334_MACPHY_RET 16
+#define RES4334_WL_CORE_READY 17
+#define RES4334_ILP_REQ 18
+#define RES4334_ALP_AVAIL 19
+#define RES4334_MISC_PWRSW_PU 20
+#define RES4334_SYNTH_PWRSW_PU 21
+#define RES4334_RX_PWRSW_PU 22
+#define RES4334_RADIO_PU 23
+#define RES4334_WL_PMU_PU 24
+#define RES4334_VCO_LDO_PU 25
+#define RES4334_AFE_LDO_PU 26
+#define RES4334_RX_LDO_PU 27
+#define RES4334_TX_LDO_PU 28
+#define RES4334_HT_AVAIL 29
+#define RES4334_MACPHY_CLK_AVAIL 30
+
+/* 4334 chip-specific ChipStatus register bits */
+#define CST4334_CHIPMODE_MASK 7
+#define CST4334_SDIO_MODE 0x00000000
+#define CST4334_SPI_MODE 0x00000004
+#define CST4334_HSIC_MODE 0x00000006
+#define CST4334_BLUSB_MODE 0x00000007
+#define CST4334_CHIPMODE_HSIC(cs) (((cs) & CST4334_CHIPMODE_MASK) == CST4334_HSIC_MODE)
+#define CST4334_OTP_PRESENT 0x00000010
+#define CST4334_LPO_AUTODET_EN 0x00000020
+#define CST4334_ARMREMAP_0 0x00000040
+#define CST4334_SPROM_PRESENT 0x00000080
+#define CST4334_ILPDIV_EN_MASK 0x00000100
+#define CST4334_ILPDIV_EN_SHIFT 8
+#define CST4334_LPO_SEL_MASK 0x00000200
+#define CST4334_LPO_SEL_SHIFT 9
+#define CST4334_RES_INIT_MODE_MASK 0x00000C00
+#define CST4334_RES_INIT_MODE_SHIFT 10
+
+/* 4334 Chip specific PMU ChipControl register bits */
+#define PCTL_4334_GPIO3_ENAB (1 << 3)
+
+/* 4334 Chip control */
+#define CCTRL4334_PMU_WAKEUP_GPIO1 (1 << 0)
+#define CCTRL4334_PMU_WAKEUP_HSIC (1 << 1)
+#define CCTRL4334_PMU_WAKEUP_AOS (1 << 2)
+#define CCTRL4334_HSIC_WAKE_MODE (1 << 3)
+#define CCTRL4334_HSIC_INBAND_GPIO1 (1 << 4)
+#define CCTRL4334_HSIC_LDO_PU (1 << 23)
+
+/* 4334 Chip control 3 */
+#define CCTRL4334_BLOCK_EXTRNL_WAKE (1 << 4)
+#define CCTRL4334_SAVERESTORE_FIX (1 << 5)
+
+/* 43341 Chip control 3 */
+#define CCTRL43341_BLOCK_EXTRNL_WAKE (1 << 13)
+#define CCTRL43341_SAVERESTORE_FIX (1 << 14)
+#define CCTRL43341_BT_ISO_SEL (1 << 16)
+
+/* 4334 Chip specific ChipControl1 register bits */
+#define CCTRL1_4334_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */
+#define CCTRL1_4334_ERCX_SEL (1 << 1) /* 1=select ERCX BT coex to be muxed out */
+#define CCTRL1_4334_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */
+#define CCTRL1_4334_JTAG_DISABLE (1 << 3) /* 1=disable JTAG interface on mux'd pins */
+#define CCTRL1_4334_UART_ON_4_5 (1 << 28) /* 1=UART_TX/UART_RX muxed on GPIO_4/5 (4334B0/1) */
+
+/* 4324 Chip specific ChipControl1 register bits */
+#define CCTRL1_4324_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */
+#define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */
+
+/* 43143 chip-specific ChipStatus register bits based on Confluence documentation */
+/* register contains strap values sampled during POR */
+#define CST43143_REMAP_TO_ROM (3 << 0) /* 00=Boot SRAM, 01=Boot ROM, 10=Boot SFLASH */
+#define CST43143_SDIO_EN (1 << 2) /* 0 = USB Enab, SDIO pins are GPIO or I2S */
+#define CST43143_SDIO_ISO (1 << 3) /* 1 = SDIO isolated */
+#define CST43143_USB_CPU_LESS (1 << 4) /* 1 = CPULess mode Enabled */
+#define CST43143_CBUCK_MODE (3 << 6) /* Indicates what controller mode CBUCK is in */
+#define CST43143_POK_CBUCK (1 << 8) /* 1 = 1.2V CBUCK voltage ready */
+#define CST43143_PMU_OVRSPIKE (1 << 9)
+#define CST43143_PMU_OVRTEMP (0xF << 10)
+#define CST43143_SR_FLL_CAL_DONE (1 << 14)
+#define CST43143_USB_PLL_LOCKDET (1 << 15)
+#define CST43143_PMU_PLL_LOCKDET (1 << 16)
+#define CST43143_CHIPMODE_SDIOD(cs) (((cs) & CST43143_SDIO_EN) != 0) /* SDIO */
+
+/* 43143 Chip specific ChipControl register bits */
+/* 00: SECI is disabled (JATG functional), 01: 2 wire, 10: 4 wire */
+#define CCTRL_43143_SECI (1<<0)
+#define CCTRL_43143_BT_LEGACY (1<<1)
+#define CCTRL_43143_I2S_MODE (1<<2) /* 0: SDIO enabled */
+#define CCTRL_43143_I2S_MASTER (1<<3) /* 0: I2S MCLK input disabled */
+#define CCTRL_43143_I2S_FULL (1<<4) /* 0: I2S SDIN and SPDIF_TX inputs disabled */
+#define CCTRL_43143_GSIO (1<<5) /* 0: sFlash enabled */
+#define CCTRL_43143_RF_SWCTRL_MASK (7<<6) /* 0: disabled */
+#define CCTRL_43143_RF_SWCTRL_0 (1<<6)
+#define CCTRL_43143_RF_SWCTRL_1 (2<<6)
+#define CCTRL_43143_RF_SWCTRL_2 (4<<6)
+#define CCTRL_43143_RF_XSWCTRL (1<<9) /* 0: UART enabled */
+#define CCTRL_43143_HOST_WAKE0 (1<<11) /* 1: SDIO separate interrupt output from GPIO4 */
+#define CCTRL_43143_HOST_WAKE1 (1<<12) /* 1: SDIO separate interrupt output from GPIO16 */
+
+/* 43143 resources, based on pmu_params.xls V1.19 */
+#define RES43143_EXT_SWITCHER_PWM 0 /* 0x00001 */
+#define RES43143_XTAL_PU 1 /* 0x00002 */
+#define RES43143_ILP_REQUEST 2 /* 0x00004 */
+#define RES43143_ALP_AVAIL 3 /* 0x00008 */
+#define RES43143_WL_CORE_READY 4 /* 0x00010 */
+#define RES43143_BBPLL_PWRSW_PU 5 /* 0x00020 */
+#define RES43143_HT_AVAIL 6 /* 0x00040 */
+#define RES43143_RADIO_PU 7 /* 0x00080 */
+#define RES43143_MACPHY_CLK_AVAIL 8 /* 0x00100 */
+#define RES43143_OTP_PU 9 /* 0x00200 */
+#define RES43143_LQ_AVAIL 10 /* 0x00400 */
+
+#define PMU43143_XTAL_CORE_SIZE_MASK 0x3F
+
+/* 4313 resources */
+#define RES4313_BB_PU_RSRC 0
+#define RES4313_ILP_REQ_RSRC 1
+#define RES4313_XTAL_PU_RSRC 2
+#define RES4313_ALP_AVAIL_RSRC 3
+#define RES4313_RADIO_PU_RSRC 4
+#define RES4313_BG_PU_RSRC 5
+#define RES4313_VREG1P4_PU_RSRC 6
+#define RES4313_AFE_PWRSW_RSRC 7
+#define RES4313_RX_PWRSW_RSRC 8
+#define RES4313_TX_PWRSW_RSRC 9
+#define RES4313_BB_PWRSW_RSRC 10
+#define RES4313_SYNTH_PWRSW_RSRC 11
+#define RES4313_MISC_PWRSW_RSRC 12
+#define RES4313_BB_PLL_PWRSW_RSRC 13
+#define RES4313_HT_AVAIL_RSRC 14
+#define RES4313_MACPHY_CLK_AVAIL_RSRC 15
+
+/* 4313 chip-specific ChipStatus register bits */
+#define CST4313_SPROM_PRESENT 1
+#define CST4313_OTP_PRESENT 2
+#define CST4313_SPROM_OTP_SEL_MASK 0x00000002
+#define CST4313_SPROM_OTP_SEL_SHIFT 0
+
+/* 4313 Chip specific ChipControl register bits */
+#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
+
+/* PMU respources for 4314 */
+#define RES4314_LPLDO_PU 0
+#define RES4314_PMU_SLEEP_DIS 1
+#define RES4314_PMU_BG_PU 2
+#define RES4314_CBUCK_LPOM_PU 3
+#define RES4314_CBUCK_PFM_PU 4
+#define RES4314_CLDO_PU 5
+#define RES4314_LPLDO2_LVM 6
+#define RES4314_WL_PMU_PU 7
+#define RES4314_LNLDO_PU 8
+#define RES4314_LDO3P3_PU 9
+#define RES4314_OTP_PU 10
+#define RES4314_XTAL_PU 11
+#define RES4314_WL_PWRSW_PU 12
+#define RES4314_LQ_AVAIL 13
+#define RES4314_LOGIC_RET 14
+#define RES4314_MEM_SLEEP 15
+#define RES4314_MACPHY_RET 16
+#define RES4314_WL_CORE_READY 17
+#define RES4314_ILP_REQ 18
+#define RES4314_ALP_AVAIL 19
+#define RES4314_MISC_PWRSW_PU 20
+#define RES4314_SYNTH_PWRSW_PU 21
+#define RES4314_RX_PWRSW_PU 22
+#define RES4314_RADIO_PU 23
+#define RES4314_VCO_LDO_PU 24
+#define RES4314_AFE_LDO_PU 25
+#define RES4314_RX_LDO_PU 26
+#define RES4314_TX_LDO_PU 27
+#define RES4314_HT_AVAIL 28
+#define RES4314_MACPHY_CLK_AVAIL 29
+
+/* 4314 chip-specific ChipStatus register bits */
+#define CST4314_OTP_ENABLED 0x00200000
+
+/* 43228 resources */
+#define RES43228_NOT_USED 0
+#define RES43228_ILP_REQUEST 1
+#define RES43228_XTAL_PU 2
+#define RES43228_ALP_AVAIL 3
+#define RES43228_PLL_EN 4
+#define RES43228_HT_PHY_AVAIL 5
+
+/* 43228 chipstatus reg bits */
+#define CST43228_ILP_DIV_EN 0x1
+#define CST43228_OTP_PRESENT 0x2
+#define CST43228_SERDES_REFCLK_PADSEL 0x4
+#define CST43228_SDIO_MODE 0x8
+#define CST43228_SDIO_OTP_PRESENT 0x10
+#define CST43228_SDIO_RESET 0x20
+
+/* 4706 chipstatus reg bits */
+#define CST4706_PKG_OPTION (1<<0) /* 0: full-featured package 1: low-cost package */
+#define CST4706_SFLASH_PRESENT (1<<1) /* 0: parallel, 1: serial flash is present */
+#define CST4706_SFLASH_TYPE (1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */
+#define CST4706_MIPS_BENDIAN (1<<3) /* 0: little, 1: big endian */
+#define CST4706_PCIE1_DISABLE (1<<5) /* PCIE1 enable strap pin */
+
+/* 4706 flashstrconfig reg bits */
+#define FLSTRCF4706_MASK 0x000000ff
+#define FLSTRCF4706_SF1 0x00000001 /* 2nd serial flash present */
+#define FLSTRCF4706_PF1 0x00000002 /* 2nd parallel flash present */
+#define FLSTRCF4706_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */
+#define FLSTRCF4706_NF1 0x00000008 /* 2nd NAND flash present */
+#define FLSTRCF4706_1ST_MADDR_SEG_MASK 0x000000f0 /* Valid value mask */
+#define FLSTRCF4706_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */
+#define FLSTRCF4706_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */
+#define FLSTRCF4706_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */
+#define FLSTRCF4706_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */
+#define FLSTRCF4706_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */
+#define FLSTRCF4706_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */
+#define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */
+
+/* 4360 Chip specific ChipControl register bits */
+#define CCTRL4360_I2C_MODE (1 << 0)
+#define CCTRL4360_UART_MODE (1 << 1)
+#define CCTRL4360_SECI_MODE (1 << 2)
+#define CCTRL4360_BTSWCTRL_MODE (1 << 3)
+#define CCTRL4360_DISCRETE_FEMCTRL_MODE (1 << 4)
+#define CCTRL4360_DIGITAL_PACTRL_MODE (1 << 5)
+#define CCTRL4360_BTSWCTRL_AND_DIGPA_PRESENT (1 << 6)
+#define CCTRL4360_EXTRA_GPIO_MODE (1 << 7)
+#define CCTRL4360_EXTRA_FEMCTRL_MODE (1 << 8)
+#define CCTRL4360_BT_LGCY_MODE (1 << 9)
+#define CCTRL4360_CORE2FEMCTRL4_ON (1 << 21)
+#define CCTRL4360_SECI_ON_GPIO01 (1 << 24)
+
+/* 4360 Chip specific Regulator Control register bits */
+#define RCTRL4360_RFLDO_PWR_DOWN (1 << 1)
+
+/* 4360 PMU resources and chip status bits */
+#define RES4360_REGULATOR 0
+#define RES4360_ILP_AVAIL 1
+#define RES4360_ILP_REQ 2
+#define RES4360_XTAL_LDO_PU 3
+#define RES4360_XTAL_PU 4
+#define RES4360_ALP_AVAIL 5
+#define RES4360_BBPLLPWRSW_PU 6
+#define RES4360_HT_AVAIL 7
+#define RES4360_OTP_PU 8
+
+#define CST4360_XTAL_40MZ 0x00000001
+#define CST4360_SFLASH 0x00000002
+#define CST4360_SPROM_PRESENT 0x00000004
+#define CST4360_SFLASH_TYPE 0x00000004
+#define CST4360_OTP_ENABLED 0x00000008
+#define CST4360_REMAP_ROM 0x00000010
+#define CST4360_RSRC_INIT_MODE_MASK 0x00000060
+#define CST4360_RSRC_INIT_MODE_SHIFT 5
+#define CST4360_ILP_DIVEN 0x00000080
+#define CST4360_MODE_USB 0x00000100
+#define CST4360_SPROM_SIZE_MASK 0x00000600
+#define CST4360_SPROM_SIZE_SHIFT 9
+#define CST4360_BBPLL_LOCK 0x00000800
+#define CST4360_AVBBPLL_LOCK 0x00001000
+#define CST4360_USBBBPLL_LOCK 0x00002000
+#define CST4360_RSRC_INIT_MODE(cs) ((cs & CST4360_RSRC_INIT_MODE_MASK) >> \
+ CST4360_RSRC_INIT_MODE_SHIFT)
+
+#define CCTRL_4360_UART_SEL 0x2
+
+
+/* 43602 PMU resources based on pmu_params.xls version v0.95 */
+#define RES43602_LPLDO_PU 0
+#define RES43602_REGULATOR 1
+#define RES43602_PMU_SLEEP 2
+#define RES43602_RSVD_3 3
+#define RES43602_XTALLDO_PU 4
+#define RES43602_SERDES_PU 5
+#define RES43602_BBPLL_PWRSW_PU 6
+#define RES43602_SR_CLK_START 7
+#define RES43602_SR_PHY_PWRSW 8
+#define RES43602_SR_SUBCORE_PWRSW 9
+#define RES43602_XTAL_PU 10
+#define RES43602_PERST_OVR 11
+#define RES43602_SR_CLK_STABLE 12
+#define RES43602_SR_SAVE_RESTORE 13
+#define RES43602_SR_SLEEP 14
+#define RES43602_LQ_START 15
+#define RES43602_LQ_AVAIL 16
+#define RES43602_WL_CORE_RDY 17
+#define RES43602_ILP_REQ 18
+#define RES43602_ALP_AVAIL 19
+#define RES43602_RADIO_PU 20
+#define RES43602_RFLDO_PU 21
+#define RES43602_HT_START 22
+#define RES43602_HT_AVAIL 23
+#define RES43602_MACPHY_CLKAVAIL 24
+#define RES43602_PARLDO_PU 25
+#define RES43602_RSVD_26 26
+
+/* 43602 chip status bits */
+#define CST43602_SPROM_PRESENT (1<<1)
+#define CST43602_SPROM_SIZE (1<<10) /* 0 = 16K, 1 = 4K */
+#define CST43602_BBPLL_LOCK (1<<11)
+#define CST43602_RF_LDO_OUT_OK (1<<15) /* RF LDO output OK */
+
+#define PMU43602_CC2_FORCE_EXT_LPO (1 << 19) /* 1=ext LPO clock is the final LPO clock */
+#define PMU43602_CC2_XTAL32_SEL (1 << 30) /* 0=ext_clock, 1=xtal */
+
+#define CC_SR1_43602_SR_ASM_ADDR (0x0)
+
+/* PLL CTL register values for open loop, used during S/R operation */
+#define PMU43602_PLL_CTL6_VAL 0x68000528
+#define PMU43602_PLL_CTL7_VAL 0x6
+
+#define PMU43602_CC3_ARMCR4_DBG_CLK (1 << 29)
+
+
+/* 43430 PMU resources based on pmu_params.xls */
+#define RES43430_LPLDO_PU 0
+#define RES43430_BG_PU 1
+#define RES43430_PMU_SLEEP 2
+#define RES43430_RSVD_3 3
+#define RES43430_CBUCK_LPOM_PU 4
+#define RES43430_CBUCK_PFM_PU 5
+#define RES43430_COLD_START_WAIT 6
+#define RES43430_RSVD_7 7
+#define RES43430_LNLDO_PU 8
+#define RES43430_RSVD_9 9
+#define RES43430_LDO3P3_PU 10
+#define RES43430_OTP_PU 11
+#define RES43430_XTAL_PU 12
+#define RES43430_SR_CLK_START 13
+#define RES43430_LQ_AVAIL 14
+#define RES43430_LQ_START 15
+#define RES43430_RSVD_16 16
+#define RES43430_WL_CORE_RDY 17
+#define RES43430_ILP_REQ 18
+#define RES43430_ALP_AVAIL 19
+#define RES43430_MINI_PMU 20
+#define RES43430_RADIO_PU 21
+#define RES43430_SR_CLK_STABLE 22
+#define RES43430_SR_SAVE_RESTORE 23
+#define RES43430_SR_PHY_PWRSW 24
+#define RES43430_SR_VDDM_PWRSW 25
+#define RES43430_SR_SUBCORE_PWRSW 26
+#define RES43430_SR_SLEEP 27
+#define RES43430_HT_START 28
+#define RES43430_HT_AVAIL 29
+#define RES43430_MACPHY_CLK_AVAIL 30
+
+/* 43430 chip status bits */
+#define CST43430_SDIO_MODE 0x00000001
+#define CST43430_GSPI_MODE 0x00000002
+#define CST43430_RSRC_INIT_MODE_0 0x00000080
+#define CST43430_RSRC_INIT_MODE_1 0x00000100
+#define CST43430_SEL0_SDIO 0x00000200
+#define CST43430_SEL1_SDIO 0x00000400
+#define CST43430_SEL2_SDIO 0x00000800
+#define CST43430_BBPLL_LOCKED 0x00001000
+#define CST43430_DBG_INST_DETECT 0x00004000
+#define CST43430_CLB2WL_BT_READY 0x00020000
+#define CST43430_JTAG_MODE 0x00100000
+#define CST43430_HOST_IFACE 0x00400000
+#define CST43430_TRIM_EN 0x00800000
+#define CST43430_DIN_PACKAGE_OPTION 0x10000000
+
+/* defines to detect active host interface in use */
+#define CHIP_HOSTIF_PCIEMODE 0x1
+#define CHIP_HOSTIF_USBMODE 0x2
+#define CHIP_HOSTIF_SDIOMODE 0x4
+#define CHIP_HOSTIF_PCIE(sih) (si_chip_hostif(sih) == CHIP_HOSTIF_PCIEMODE)
+#define CHIP_HOSTIF_USB(sih) (si_chip_hostif(sih) == CHIP_HOSTIF_USBMODE)
+#define CHIP_HOSTIF_SDIO(sih) (si_chip_hostif(sih) == CHIP_HOSTIF_SDIOMODE)
+
+/* 4335 resources */
+#define RES4335_LPLDO_PO 0
+#define RES4335_PMU_BG_PU 1
+#define RES4335_PMU_SLEEP 2
+#define RES4335_RSVD_3 3
+#define RES4335_CBUCK_LPOM_PU 4
+#define RES4335_CBUCK_PFM_PU 5
+#define RES4335_RSVD_6 6
+#define RES4335_RSVD_7 7
+#define RES4335_LNLDO_PU 8
+#define RES4335_XTALLDO_PU 9
+#define RES4335_LDO3P3_PU 10
+#define RES4335_OTP_PU 11
+#define RES4335_XTAL_PU 12
+#define RES4335_SR_CLK_START 13
+#define RES4335_LQ_AVAIL 14
+#define RES4335_LQ_START 15
+#define RES4335_RSVD_16 16
+#define RES4335_WL_CORE_RDY 17
+#define RES4335_ILP_REQ 18
+#define RES4335_ALP_AVAIL 19
+#define RES4335_MINI_PMU 20
+#define RES4335_RADIO_PU 21
+#define RES4335_SR_CLK_STABLE 22
+#define RES4335_SR_SAVE_RESTORE 23
+#define RES4335_SR_PHY_PWRSW 24
+#define RES4335_SR_VDDM_PWRSW 25
+#define RES4335_SR_SUBCORE_PWRSW 26
+#define RES4335_SR_SLEEP 27
+#define RES4335_HT_START 28
+#define RES4335_HT_AVAIL 29
+#define RES4335_MACPHY_CLKAVAIL 30
+
+/* 4335 Chip specific ChipStatus register bits */
+#define CST4335_SPROM_MASK 0x00000020
+#define CST4335_SFLASH_MASK 0x00000040
+#define CST4335_RES_INIT_MODE_SHIFT 7
+#define CST4335_RES_INIT_MODE_MASK 0x00000180
+#define CST4335_CHIPMODE_MASK 0xF
+#define CST4335_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) /* SDIO */
+#define CST4335_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) /* gSPI */
+#define CST4335_CHIPMODE_USB20D(cs) (((cs) & (1 << 2)) != 0) /* HSIC || USBDA */
+#define CST4335_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) /* PCIE */
+
+/* 4335 Chip specific ChipControl1 register bits */
+#define CCTRL1_4335_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */
+#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */
+
+#define PATCHTBL_SIZE (0x800)
+#define CR4_4335_RAM_BASE (0x180000)
+#define CR4_4345_LT_C0_RAM_BASE (0x1b0000)
+#define CR4_4345_GE_C0_RAM_BASE (0x198000)
+#define CR4_4349_RAM_BASE (0x180000)
+#define CR4_4350_RAM_BASE (0x180000)
+#define CR4_4360_RAM_BASE (0x0)
+#define CR4_43602_RAM_BASE (0x180000)
+
+/* 4335 chip OTP present & OTP select bits. */
+#define SPROM4335_OTP_SELECT 0x00000010
+#define SPROM4335_OTP_PRESENT 0x00000020
+
+/* 4335 GCI specific bits. */
+#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_PRESENT (1 << 24)
+#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_TYPE 25
+#define CC4335_GCI_FUNC_SEL_PAD_SDIO 0x00707770
+
+/* SFLASH clkdev specific bits. */
+#define CC4335_SFLASH_CLKDIV_MASK 0x1F000000
+#define CC4335_SFLASH_CLKDIV_SHIFT 25
+
+/* 4335 OTP bits for SFLASH. */
+#define CC4335_SROM_OTP_SFLASH 40
+#define CC4335_SROM_OTP_SFLASH_PRESENT 0x1
+#define CC4335_SROM_OTP_SFLASH_TYPE 0x2
+#define CC4335_SROM_OTP_SFLASH_CLKDIV_MASK 0x003C
+#define CC4335_SROM_OTP_SFLASH_CLKDIV_SHIFT 2
+
+
+/* 4335 chip OTP present & OTP select bits. */
+#define SPROM4335_OTP_SELECT 0x00000010
+#define SPROM4335_OTP_PRESENT 0x00000020
+
+/* 4335 GCI specific bits. */
+#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_PRESENT (1 << 24)
+#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_TYPE 25
+#define CC4335_GCI_FUNC_SEL_PAD_SDIO 0x00707770
+
+/* SFLASH clkdev specific bits. */
+#define CC4335_SFLASH_CLKDIV_MASK 0x1F000000
+#define CC4335_SFLASH_CLKDIV_SHIFT 25
+
+/* 4335 OTP bits for SFLASH. */
+#define CC4335_SROM_OTP_SFLASH 40
+#define CC4335_SROM_OTP_SFLASH_PRESENT 0x1
+#define CC4335_SROM_OTP_SFLASH_TYPE 0x2
+#define CC4335_SROM_OTP_SFLASH_CLKDIV_MASK 0x003C
+#define CC4335_SROM_OTP_SFLASH_CLKDIV_SHIFT 2
+
+/* 4335 resources--END */
+
+/* 4345 Chip specific ChipStatus register bits */
+#define CST4345_SPROM_MASK 0x00000020
+#define CST4345_SFLASH_MASK 0x00000040
+#define CST4345_RES_INIT_MODE_SHIFT 7
+#define CST4345_RES_INIT_MODE_MASK 0x00000180
+#define CST4345_CHIPMODE_MASK 0x4000F
+#define CST4345_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) /* SDIO */
+#define CST4345_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) /* gSPI */
+#define CST4345_CHIPMODE_HSIC(cs) (((cs) & (1 << 2)) != 0) /* HSIC */
+#define CST4345_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) /* PCIE */
+#define CST4345_CHIPMODE_USB20D(cs) (((cs) & (1 << 18)) != 0) /* USBDA */
+
+/* 4350 Chipcommon ChipStatus bits */
+#define CST4350_SDIO_MODE 0x00000001
+#define CST4350_HSIC20D_MODE 0x00000002
+#define CST4350_BP_ON_HSIC_CLK 0x00000004
+#define CST4350_PCIE_MODE 0x00000008
+#define CST4350_USB20D_MODE 0x00000010
+#define CST4350_USB30D_MODE 0x00000020
+#define CST4350_SPROM_PRESENT 0x00000040
+#define CST4350_RSRC_INIT_MODE_0 0x00000080
+#define CST4350_RSRC_INIT_MODE_1 0x00000100
+#define CST4350_SEL0_SDIO 0x00000200
+#define CST4350_SEL1_SDIO 0x00000400
+#define CST4350_SDIO_PAD_MODE 0x00000800
+#define CST4350_BBPLL_LOCKED 0x00001000
+#define CST4350_USBPLL_LOCKED 0x00002000
+#define CST4350_LINE_STATE 0x0000C000
+#define CST4350_SERDES_PIPE_PLLLOCK 0x00010000
+#define CST4350_BT_READY 0x00020000
+#define CST4350_SFLASH_PRESENT 0x00040000
+#define CST4350_CPULESS_ENABLE 0x00080000
+#define CST4350_STRAP_HOST_IFC_1 0x00100000
+#define CST4350_STRAP_HOST_IFC_2 0x00200000
+#define CST4350_STRAP_HOST_IFC_3 0x00400000
+#define CST4350_RAW_SPROM_PRESENT 0x00800000
+#define CST4350_APP_CLK_SWITCH_SEL_RDBACK 0x01000000
+#define CST4350_RAW_RSRC_INIT_MODE_0 0x02000000
+#define CST4350_SDIO_PAD_VDDIO 0x04000000
+#define CST4350_GSPI_MODE 0x08000000
+#define CST4350_PACKAGE_OPTION 0xF0000000
+#define CST4350_PACKAGE_SHIFT 28
+
+/* package option for 4350 */
+#define CST4350_PACKAGE_WLCSP 0x0
+#define CST4350_PACKAGE_PCIE 0x1
+#define CST4350_PACKAGE_WLBGA 0x2
+#define CST4350_PACKAGE_DBG 0x3
+#define CST4350_PACKAGE_USB 0x4
+#define CST4350_PACKAGE_USB_HSIC 0x4
+
+#define CST4350_PKG_MODE(cs) ((cs & CST4350_PACKAGE_OPTION) >> CST4350_PACKAGE_SHIFT)
+
+#define CST4350_PKG_WLCSP(cs) (CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_WLCSP))
+#define CST4350_PKG_PCIE(cs) (CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_PCIE))
+#define CST4350_PKG_WLBGA(cs) (CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_WLBGA))
+#define CST4350_PKG_USB(cs) (CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_USB))
+#define CST4350_PKG_USB_HSIC(cs) (CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_USB_HSIC))
+
+/* 4350C0 USB PACKAGE using raw_sprom_present to indicate 40mHz xtal */
+#define CST4350_PKG_USB_40M(cs) (cs & CST4350_RAW_SPROM_PRESENT)
+
+#define CST4350_CHIPMODE_SDIOD(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_SDIOD))
+#define CST4350_CHIPMODE_USB20D(cs) ((CST4350_IFC_MODE(cs)) == (CST4350_IFC_MODE_USB20D))
+#define CST4350_CHIPMODE_HSIC20D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC20D))
+#define CST4350_CHIPMODE_HSIC30D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC30D))
+#define CST4350_CHIPMODE_USB30D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D))
+#define CST4350_CHIPMODE_USB30D_WL(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D_WL))
+#define CST4350_CHIPMODE_PCIE(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_PCIE))
+
+/* strap_host_ifc strap value */
+#define CST4350_HOST_IFC_MASK 0x00700000
+#define CST4350_HOST_IFC_SHIFT 20
+
+/* host_ifc raw mode */
+#define CST4350_IFC_MODE_SDIOD 0x0
+#define CST4350_IFC_MODE_HSIC20D 0x1
+#define CST4350_IFC_MODE_HSIC30D 0x2
+#define CST4350_IFC_MODE_PCIE 0x3
+#define CST4350_IFC_MODE_USB20D 0x4
+#define CST4350_IFC_MODE_USB30D 0x5
+#define CST4350_IFC_MODE_USB30D_WL 0x6
+#define CST4350_IFC_MODE_USB30D_BT 0x7
+
+#define CST4350_IFC_MODE(cs) ((cs & CST4350_HOST_IFC_MASK) >> CST4350_HOST_IFC_SHIFT)
+
+#define CST4350_CHIPMODE_SDIOD(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_SDIOD))
+#define CST4350_CHIPMODE_USB20D(cs) ((CST4350_IFC_MODE(cs)) == (CST4350_IFC_MODE_USB20D))
+#define CST4350_CHIPMODE_HSIC20D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC20D))
+#define CST4350_CHIPMODE_HSIC30D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC30D))
+#define CST4350_CHIPMODE_USB30D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D))
+#define CST4350_CHIPMODE_USB30D_WL(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D_WL))
+#define CST4350_CHIPMODE_PCIE(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_PCIE))
+
+/* 4350 PMU resources */
+#define RES4350_LPLDO_PU 0
+#define RES4350_PMU_BG_PU 1
+#define RES4350_PMU_SLEEP 2
+#define RES4350_RSVD_3 3
+#define RES4350_CBUCK_LPOM_PU 4
+#define RES4350_CBUCK_PFM_PU 5
+#define RES4350_COLD_START_WAIT 6
+#define RES4350_RSVD_7 7
+#define RES4350_LNLDO_PU 8
+#define RES4350_XTALLDO_PU 9
+#define RES4350_LDO3P3_PU 10
+#define RES4350_OTP_PU 11
+#define RES4350_XTAL_PU 12
+#define RES4350_SR_CLK_START 13
+#define RES4350_LQ_AVAIL 14
+#define RES4350_LQ_START 15
+#define RES4350_RSVD_16 16
+#define RES4350_WL_CORE_RDY 17
+#define RES4350_ILP_REQ 18
+#define RES4350_ALP_AVAIL 19
+#define RES4350_MINI_PMU 20
+#define RES4350_RADIO_PU 21
+#define RES4350_SR_CLK_STABLE 22
+#define RES4350_SR_SAVE_RESTORE 23
+#define RES4350_SR_PHY_PWRSW 24
+#define RES4350_SR_VDDM_PWRSW 25
+#define RES4350_SR_SUBCORE_PWRSW 26
+#define RES4350_SR_SLEEP 27
+#define RES4350_HT_START 28
+#define RES4350_HT_AVAIL 29
+#define RES4350_MACPHY_CLKAVAIL 30
+
+#define MUXENAB4350_UART_MASK (0x0000000f)
+#define MUXENAB4350_UART_SHIFT 0
+#define MUXENAB4350_HOSTWAKE_MASK (0x000000f0) /* configure GPIO for SDIO host_wake */
+#define MUXENAB4350_HOSTWAKE_SHIFT 4
+
+
+/* 4350 GCI function sel values */
+#define CC4350_FNSEL_HWDEF (0)
+#define CC4350_FNSEL_SAMEASPIN (1)
+#define CC4350_FNSEL_UART (2)
+#define CC4350_FNSEL_SFLASH (3)
+#define CC4350_FNSEL_SPROM (4)
+#define CC4350_FNSEL_I2C (5)
+#define CC4350_FNSEL_MISC0 (6)
+#define CC4350_FNSEL_GCI (7)
+#define CC4350_FNSEL_MISC1 (8)
+#define CC4350_FNSEL_MISC2 (9)
+#define CC4350_FNSEL_PWDOG (10)
+#define CC4350_FNSEL_IND (12)
+#define CC4350_FNSEL_PDN (13)
+#define CC4350_FNSEL_PUP (14)
+#define CC4350_FNSEL_TRISTATE (15)
+#define CC4350C_FNSEL_UART (3)
+
+
+/* 4350 GPIO */
+#define CC4350_PIN_GPIO_00 (0)
+#define CC4350_PIN_GPIO_01 (1)
+#define CC4350_PIN_GPIO_02 (2)
+#define CC4350_PIN_GPIO_03 (3)
+#define CC4350_PIN_GPIO_04 (4)
+#define CC4350_PIN_GPIO_05 (5)
+#define CC4350_PIN_GPIO_06 (6)
+#define CC4350_PIN_GPIO_07 (7)
+#define CC4350_PIN_GPIO_08 (8)
+#define CC4350_PIN_GPIO_09 (9)
+#define CC4350_PIN_GPIO_10 (10)
+#define CC4350_PIN_GPIO_11 (11)
+#define CC4350_PIN_GPIO_12 (12)
+#define CC4350_PIN_GPIO_13 (13)
+#define CC4350_PIN_GPIO_14 (14)
+#define CC4350_PIN_GPIO_15 (15)
+
+#define CC2_4350_PHY_PWRSW_UPTIME_MASK (0xf << 0)
+#define CC2_4350_PHY_PWRSW_UPTIME_SHIFT (0)
+#define CC2_4350_VDDM_PWRSW_UPDELAY_MASK (0xf << 4)
+#define CC2_4350_VDDM_PWRSW_UPDELAY_SHIFT (4)
+#define CC2_4350_VDDM_PWRSW_UPTIME_MASK (0xf << 8)
+#define CC2_4350_VDDM_PWRSW_UPTIME_SHIFT (8)
+#define CC2_4350_SBC_PWRSW_DNDELAY_MASK (0x3 << 12)
+#define CC2_4350_SBC_PWRSW_DNDELAY_SHIFT (12)
+#define CC2_4350_PHY_PWRSW_DNDELAY_MASK (0x3 << 14)
+#define CC2_4350_PHY_PWRSW_DNDELAY_SHIFT (14)
+#define CC2_4350_VDDM_PWRSW_DNDELAY_MASK (0x3 << 16)
+#define CC2_4350_VDDM_PWRSW_DNDELAY_SHIFT (16)
+#define CC2_4350_VDDM_PWRSW_EN_MASK (1 << 20)
+#define CC2_4350_VDDM_PWRSW_EN_SHIFT (20)
+#define CC2_4350_MEMLPLDO_PWRSW_EN_MASK (1 << 21)
+#define CC2_4350_MEMLPLDO_PWRSW_EN_SHIFT (21)
+#define CC2_4350_SDIO_AOS_WAKEUP_MASK (1 << 24)
+#define CC2_4350_SDIO_AOS_WAKEUP_SHIFT (24)
+
+/* Applies to 4335/4350/4345 */
+#define CC3_SR_CLK_SR_MEM_MASK (1 << 0)
+#define CC3_SR_CLK_SR_MEM_SHIFT (0)
+#define CC3_SR_BIT1_TBD_MASK (1 << 1)
+#define CC3_SR_BIT1_TBD_SHIFT (1)
+#define CC3_SR_ENGINE_ENABLE_MASK (1 << 2)
+#define CC3_SR_ENGINE_ENABLE_SHIFT (2)
+#define CC3_SR_BIT3_TBD_MASK (1 << 3)
+#define CC3_SR_BIT3_TBD_SHIFT (3)
+#define CC3_SR_MINDIV_FAST_CLK_MASK (0xF << 4)
+#define CC3_SR_MINDIV_FAST_CLK_SHIFT (4)
+#define CC3_SR_R23_SR2_RISE_EDGE_TRIG_MASK (1 << 8)
+#define CC3_SR_R23_SR2_RISE_EDGE_TRIG_SHIFT (8)
+#define CC3_SR_R23_SR2_FALL_EDGE_TRIG_MASK (1 << 9)
+#define CC3_SR_R23_SR2_FALL_EDGE_TRIG_SHIFT (9)
+#define CC3_SR_R23_SR_RISE_EDGE_TRIG_MASK (1 << 10)
+#define CC3_SR_R23_SR_RISE_EDGE_TRIG_SHIFT (10)
+#define CC3_SR_R23_SR_FALL_EDGE_TRIG_MASK (1 << 11)
+#define CC3_SR_R23_SR_FALL_EDGE_TRIG_SHIFT (11)
+#define CC3_SR_NUM_CLK_HIGH_MASK (0x7 << 12)
+#define CC3_SR_NUM_CLK_HIGH_SHIFT (12)
+#define CC3_SR_BIT15_TBD_MASK (1 << 15)
+#define CC3_SR_BIT15_TBD_SHIFT (15)
+#define CC3_SR_PHY_FUNC_PIC_MASK (1 << 16)
+#define CC3_SR_PHY_FUNC_PIC_SHIFT (16)
+#define CC3_SR_BIT17_19_TBD_MASK (0x7 << 17)
+#define CC3_SR_BIT17_19_TBD_SHIFT (17)
+#define CC3_SR_CHIP_TRIGGER_1_MASK (1 << 20)
+#define CC3_SR_CHIP_TRIGGER_1_SHIFT (20)
+#define CC3_SR_CHIP_TRIGGER_2_MASK (1 << 21)
+#define CC3_SR_CHIP_TRIGGER_2_SHIFT (21)
+#define CC3_SR_CHIP_TRIGGER_3_MASK (1 << 22)
+#define CC3_SR_CHIP_TRIGGER_3_SHIFT (22)
+#define CC3_SR_CHIP_TRIGGER_4_MASK (1 << 23)
+#define CC3_SR_CHIP_TRIGGER_4_SHIFT (23)
+#define CC3_SR_ALLOW_SBC_FUNC_PIC_MASK (1 << 24)
+#define CC3_SR_ALLOW_SBC_FUNC_PIC_SHIFT (24)
+#define CC3_SR_BIT25_26_TBD_MASK (0x3 << 25)
+#define CC3_SR_BIT25_26_TBD_SHIFT (25)
+#define CC3_SR_ALLOW_SBC_STBY_MASK (1 << 27)
+#define CC3_SR_ALLOW_SBC_STBY_SHIFT (27)
+#define CC3_SR_GPIO_MUX_MASK (0xF << 28)
+#define CC3_SR_GPIO_MUX_SHIFT (28)
+
+/* Applies to 4335/4350/4345 */
+#define CC4_SR_INIT_ADDR_MASK (0x3FF0000)
+#define CC4_4350_SR_ASM_ADDR (0x30)
+#define CC4_4335_SR_ASM_ADDR (0x48)
+#define CC4_4345_SR_ASM_ADDR (0x48)
+#define CC4_SR_INIT_ADDR_SHIFT (16)
+
+#define CC4_4350_EN_SR_CLK_ALP_MASK (1 << 30)
+#define CC4_4350_EN_SR_CLK_ALP_SHIFT (30)
+#define CC4_4350_EN_SR_CLK_HT_MASK (1 << 31)
+#define CC4_4350_EN_SR_CLK_HT_SHIFT (31)
+
+#define VREG4_4350_MEMLPDO_PU_MASK (1 << 31)
+#define VREG4_4350_MEMLPDO_PU_SHIFT 31
+
+#define CC6_4350_PCIE_CLKREQ_WAKEUP_MASK (1 << 4)
+#define CC6_4350_PCIE_CLKREQ_WAKEUP_SHIFT (4)
+#define CC6_4350_PMU_WAKEUP_ALPAVAIL_MASK (1 << 6)
+#define CC6_4350_PMU_WAKEUP_ALPAVAIL_SHIFT (6)
+
+/* GCI chipcontrol register indices */
+#define CC_GCI_CHIPCTRL_00 (0)
+#define CC_GCI_CHIPCTRL_01 (1)
+#define CC_GCI_CHIPCTRL_02 (2)
+#define CC_GCI_CHIPCTRL_03 (3)
+#define CC_GCI_CHIPCTRL_04 (4)
+#define CC_GCI_CHIPCTRL_05 (5)
+#define CC_GCI_CHIPCTRL_06 (6)
+#define CC_GCI_CHIPCTRL_07 (7)
+#define CC_GCI_CHIPCTRL_08 (8)
+#define CC_GCI_XTAL_BUFSTRG_NFC (0xff << 12)
+
+#define CC_GCI_06_JTAG_SEL_SHIFT 4
+#define CC_GCI_06_JTAG_SEL_MASK (1 << 4)
+
+#define CC_GCI_NUMCHIPCTRLREGS(cap1) ((cap1 & 0xF00) >> 8)
+
+/* 4345 PMU resources */
+#define RES4345_LPLDO_PU 0
+#define RES4345_PMU_BG_PU 1
+#define RES4345_PMU_SLEEP 2
+#define RES4345_HSICLDO_PU 3
+#define RES4345_CBUCK_LPOM_PU 4
+#define RES4345_CBUCK_PFM_PU 5
+#define RES4345_COLD_START_WAIT 6
+#define RES4345_RSVD_7 7
+#define RES4345_LNLDO_PU 8
+#define RES4345_XTALLDO_PU 9
+#define RES4345_LDO3P3_PU 10
+#define RES4345_OTP_PU 11
+#define RES4345_XTAL_PU 12
+#define RES4345_SR_CLK_START 13
+#define RES4345_LQ_AVAIL 14
+#define RES4345_LQ_START 15
+#define RES4345_PERST_OVR 16
+#define RES4345_WL_CORE_RDY 17
+#define RES4345_ILP_REQ 18
+#define RES4345_ALP_AVAIL 19
+#define RES4345_MINI_PMU 20
+#define RES4345_RADIO_PU 21
+#define RES4345_SR_CLK_STABLE 22
+#define RES4345_SR_SAVE_RESTORE 23
+#define RES4345_SR_PHY_PWRSW 24
+#define RES4345_SR_VDDM_PWRSW 25
+#define RES4345_SR_SUBCORE_PWRSW 26
+#define RES4345_SR_SLEEP 27
+#define RES4345_HT_START 28
+#define RES4345_HT_AVAIL 29
+#define RES4345_MACPHY_CLK_AVAIL 30
+
+/* 4335 pins
+* note: only the values set as default/used are added here.
+*/
+#define CC4335_PIN_GPIO_00 (0)
+#define CC4335_PIN_GPIO_01 (1)
+#define CC4335_PIN_GPIO_02 (2)
+#define CC4335_PIN_GPIO_03 (3)
+#define CC4335_PIN_GPIO_04 (4)
+#define CC4335_PIN_GPIO_05 (5)
+#define CC4335_PIN_GPIO_06 (6)
+#define CC4335_PIN_GPIO_07 (7)
+#define CC4335_PIN_GPIO_08 (8)
+#define CC4335_PIN_GPIO_09 (9)
+#define CC4335_PIN_GPIO_10 (10)
+#define CC4335_PIN_GPIO_11 (11)
+#define CC4335_PIN_GPIO_12 (12)
+#define CC4335_PIN_GPIO_13 (13)
+#define CC4335_PIN_GPIO_14 (14)
+#define CC4335_PIN_GPIO_15 (15)
+#define CC4335_PIN_SDIO_CLK (16)
+#define CC4335_PIN_SDIO_CMD (17)
+#define CC4335_PIN_SDIO_DATA0 (18)
+#define CC4335_PIN_SDIO_DATA1 (19)
+#define CC4335_PIN_SDIO_DATA2 (20)
+#define CC4335_PIN_SDIO_DATA3 (21)
+#define CC4335_PIN_RF_SW_CTRL_6 (22)
+#define CC4335_PIN_RF_SW_CTRL_7 (23)
+#define CC4335_PIN_RF_SW_CTRL_8 (24)
+#define CC4335_PIN_RF_SW_CTRL_9 (25)
+
+/* 4335 GCI function sel values
+*/
+#define CC4335_FNSEL_HWDEF (0)
+#define CC4335_FNSEL_SAMEASPIN (1)
+#define CC4335_FNSEL_GPIO0 (2)
+#define CC4335_FNSEL_GPIO1 (3)
+#define CC4335_FNSEL_GCI0 (4)
+#define CC4335_FNSEL_GCI1 (5)
+#define CC4335_FNSEL_UART (6)
+#define CC4335_FNSEL_SFLASH (7)
+#define CC4335_FNSEL_SPROM (8)
+#define CC4335_FNSEL_MISC0 (9)
+#define CC4335_FNSEL_MISC1 (10)
+#define CC4335_FNSEL_MISC2 (11)
+#define CC4335_FNSEL_IND (12)
+#define CC4335_FNSEL_PDN (13)
+#define CC4335_FNSEL_PUP (14)
+#define CC4335_FNSEL_TRI (15)
+
+/* 4345 pins
+* note: only the values set as default/used are added here.
+*/
+#define CC4345_PIN_GPIO_00 (0)
+#define CC4345_PIN_GPIO_01 (1)
+#define CC4345_PIN_GPIO_02 (2)
+#define CC4345_PIN_GPIO_03 (3)
+#define CC4345_PIN_GPIO_04 (4)
+#define CC4345_PIN_GPIO_05 (5)
+#define CC4345_PIN_GPIO_06 (6)
+#define CC4345_PIN_GPIO_07 (7)
+#define CC4345_PIN_GPIO_08 (8)
+#define CC4345_PIN_GPIO_09 (9)
+#define CC4345_PIN_GPIO_10 (10)
+#define CC4345_PIN_GPIO_11 (11)
+#define CC4345_PIN_GPIO_12 (12)
+#define CC4345_PIN_GPIO_13 (13)
+#define CC4345_PIN_GPIO_14 (14)
+#define CC4345_PIN_GPIO_15 (15)
+#define CC4345_PIN_GPIO_16 (16)
+#define CC4345_PIN_SDIO_CLK (17)
+#define CC4345_PIN_SDIO_CMD (18)
+#define CC4345_PIN_SDIO_DATA0 (19)
+#define CC4345_PIN_SDIO_DATA1 (20)
+#define CC4345_PIN_SDIO_DATA2 (21)
+#define CC4345_PIN_SDIO_DATA3 (22)
+#define CC4345_PIN_RF_SW_CTRL_0 (23)
+#define CC4345_PIN_RF_SW_CTRL_1 (24)
+#define CC4345_PIN_RF_SW_CTRL_2 (25)
+#define CC4345_PIN_RF_SW_CTRL_3 (26)
+#define CC4345_PIN_RF_SW_CTRL_4 (27)
+#define CC4345_PIN_RF_SW_CTRL_5 (28)
+#define CC4345_PIN_RF_SW_CTRL_6 (29)
+#define CC4345_PIN_RF_SW_CTRL_7 (30)
+#define CC4345_PIN_RF_SW_CTRL_8 (31)
+#define CC4345_PIN_RF_SW_CTRL_9 (32)
+
+/* 4345 GCI function sel values
+*/
+#define CC4345_FNSEL_HWDEF (0)
+#define CC4345_FNSEL_SAMEASPIN (1)
+#define CC4345_FNSEL_GPIO0 (2)
+#define CC4345_FNSEL_GPIO1 (3)
+#define CC4345_FNSEL_GCI0 (4)
+#define CC4345_FNSEL_GCI1 (5)
+#define CC4345_FNSEL_UART (6)
+#define CC4345_FNSEL_SFLASH (7)
+#define CC4345_FNSEL_SPROM (8)
+#define CC4345_FNSEL_MISC0 (9)
+#define CC4345_FNSEL_MISC1 (10)
+#define CC4345_FNSEL_MISC2 (11)
+#define CC4345_FNSEL_IND (12)
+#define CC4345_FNSEL_PDN (13)
+#define CC4345_FNSEL_PUP (14)
+#define CC4345_FNSEL_TRI (15)
+
+#define MUXENAB4345_UART_MASK (0x0000000f)
+#define MUXENAB4345_UART_SHIFT 0
+#define MUXENAB4345_HOSTWAKE_MASK (0x000000f0)
+#define MUXENAB4345_HOSTWAKE_SHIFT 4
+
+/* GCI GPIO for function sel GCI-0/GCI-1 */
+#define CC_GCI_GPIO_0 (0)
+#define CC_GCI_GPIO_1 (1)
+#define CC_GCI_GPIO_2 (2)
+#define CC_GCI_GPIO_3 (3)
+#define CC_GCI_GPIO_4 (4)
+#define CC_GCI_GPIO_5 (5)
+#define CC_GCI_GPIO_6 (6)
+#define CC_GCI_GPIO_7 (7)
+
+/* indicates Invalid GPIO, e.g. when PAD GPIO doesn't map to GCI GPIO */
+#define CC_GCI_GPIO_INVALID 0xFF
+
+/* find the 4 bit mask given the bit position */
+#define GCIMASK(pos) (((uint32)0xF) << pos)
+/* get the value which can be used to directly OR with chipcontrol reg */
+#define GCIPOSVAL(val, pos) ((((uint32)val) << pos) & GCIMASK(pos))
+/* Extract nibble from a given position */
+#define GCIGETNBL(val, pos) ((val >> pos) & 0xF)
+
+
+/* find the 8 bit mask given the bit position */
+#define GCIMASK_8B(pos) (((uint32)0xFF) << pos)
+/* get the value which can be used to directly OR with chipcontrol reg */
+#define GCIPOSVAL_8B(val, pos) ((((uint32)val) << pos) & GCIMASK_8B(pos))
+/* Extract nibble from a given position */
+#define GCIGETNBL_8B(val, pos) ((val >> pos) & 0xFF)
+
+/* find the 4 bit mask given the bit position */
+#define GCIMASK_4B(pos) (((uint32)0xF) << pos)
+/* get the value which can be used to directly OR with chipcontrol reg */
+#define GCIPOSVAL_4B(val, pos) ((((uint32)val) << pos) & GCIMASK_4B(pos))
+/* Extract nibble from a given position */
+#define GCIGETNBL_4B(val, pos) ((val >> pos) & 0xF)
+
+
+#define GCI_INTSTATUS_GPIOINT (1 << 25)
+#define GCI_INTSTATUS_GPIOWAKE (1 << 26)
+#define GCI_INTMASK_GPIOINT (1 << 25)
+#define GCI_INTMASK_GPIOWAKE (1 << 26)
+#define GCI_WAKEMASK_GPIOINT (1 << 25)
+#define GCI_WAKEMASK_GPIOWAKE (1 << 26)
+
+
+/* 4335 MUX options. each nibble belongs to a setting. Non-zero value specifies a logic
+* for now only UART for bootloader.
+*/
+#define MUXENAB4335_UART_MASK (0x0000000f)
+
+#define MUXENAB4335_UART_SHIFT 0
+#define MUXENAB4335_HOSTWAKE_MASK (0x000000f0) /* configure GPIO for SDIO host_wake */
+#define MUXENAB4335_HOSTWAKE_SHIFT 4
+#define MUXENAB4335_GETIX(val, name) \
+ ((((val) & MUXENAB4335_ ## name ## _MASK) >> MUXENAB4335_ ## name ## _SHIFT) - 1)
+
+/*
+* Maximum delay for the PMU state transition in us.
+* This is an upper bound intended for spinwaits etc.
+*/
+#define PMU_MAX_TRANSITION_DLY 15000
+
+/* PMU resource up transition time in ILP cycles */
+#define PMURES_UP_TRANSITION 2
+
+
+/* SECI configuration */
+#define SECI_MODE_UART 0x0
+#define SECI_MODE_SECI 0x1
+#define SECI_MODE_LEGACY_3WIRE_BT 0x2
+#define SECI_MODE_LEGACY_3WIRE_WLAN 0x3
+#define SECI_MODE_HALF_SECI 0x4
+
+#define SECI_RESET (1 << 0)
+#define SECI_RESET_BAR_UART (1 << 1)
+#define SECI_ENAB_SECI_ECI (1 << 2)
+#define SECI_ENAB_SECIOUT_DIS (1 << 3)
+#define SECI_MODE_MASK 0x7
+#define SECI_MODE_SHIFT 4 /* (bits 5, 6, 7) */
+#define SECI_UPD_SECI (1 << 7)
+
+#define SECI_SIGNOFF_0 0xDB
+#define SECI_SIGNOFF_1 0
+
+/* seci clk_ctl_st bits */
+#define CLKCTL_STS_SECI_CLK_REQ (1 << 8)
+#define CLKCTL_STS_SECI_CLK_AVAIL (1 << 24)
+
+#define SECI_UART_MSR_CTS_STATE (1 << 0)
+#define SECI_UART_MSR_RTS_STATE (1 << 1)
+#define SECI_UART_SECI_IN_STATE (1 << 2)
+#define SECI_UART_SECI_IN2_STATE (1 << 3)
+
+/* SECI UART LCR/MCR register bits */
+#define SECI_UART_LCR_STOP_BITS (1 << 0) /* 0 - 1bit, 1 - 2bits */
+#define SECI_UART_LCR_PARITY_EN (1 << 1)
+#define SECI_UART_LCR_PARITY (1 << 2) /* 0 - odd, 1 - even */
+#define SECI_UART_LCR_RX_EN (1 << 3)
+#define SECI_UART_LCR_LBRK_CTRL (1 << 4) /* 1 => SECI_OUT held low */
+#define SECI_UART_LCR_TXO_EN (1 << 5)
+#define SECI_UART_LCR_RTSO_EN (1 << 6)
+#define SECI_UART_LCR_SLIPMODE_EN (1 << 7)
+#define SECI_UART_LCR_RXCRC_CHK (1 << 8)
+#define SECI_UART_LCR_TXCRC_INV (1 << 9)
+#define SECI_UART_LCR_TXCRC_LSBF (1 << 10)
+#define SECI_UART_LCR_TXCRC_EN (1 << 11)
+
+#define SECI_UART_MCR_TX_EN (1 << 0)
+#define SECI_UART_MCR_PRTS (1 << 1)
+#define SECI_UART_MCR_SWFLCTRL_EN (1 << 2)
+#define SECI_UART_MCR_HIGHRATE_EN (1 << 3)
+#define SECI_UART_MCR_LOOPBK_EN (1 << 4)
+#define SECI_UART_MCR_AUTO_RTS (1 << 5)
+#define SECI_UART_MCR_AUTO_TX_DIS (1 << 6)
+#define SECI_UART_MCR_BAUD_ADJ_EN (1 << 7)
+#define SECI_UART_MCR_XONOFF_RPT (1 << 9)
+
+/* WLAN channel numbers - used from wifi.h */
+
+/* WLAN BW */
+#define ECI_BW_20 0x0
+#define ECI_BW_25 0x1
+#define ECI_BW_30 0x2
+#define ECI_BW_35 0x3
+#define ECI_BW_40 0x4
+#define ECI_BW_45 0x5
+#define ECI_BW_50 0x6
+#define ECI_BW_ALL 0x7
+
+/* WLAN - number of antenna */
+#define WLAN_NUM_ANT1 TXANT_0
+#define WLAN_NUM_ANT2 TXANT_1
+
+/* otpctrl1 0xF4 */
+#define OTPC_FORCE_PWR_OFF 0x02000000
+/* chipcommon s/r registers introduced with cc rev >= 48 */
+#define CC_SR_CTL0_ENABLE_MASK 0x1
+#define CC_SR_CTL0_ENABLE_SHIFT 0
+#define CC_SR_CTL0_EN_SR_ENG_CLK_SHIFT 1 /* sr_clk to sr_memory enable */
+#define CC_SR_CTL0_RSRC_TRIGGER_SHIFT 2 /* Rising edge resource trigger 0 to sr_engine */
+#define CC_SR_CTL0_MIN_DIV_SHIFT 6 /* Min division value for fast clk in sr_engine */
+#define CC_SR_CTL0_EN_SBC_STBY_SHIFT 16 /* Allow Subcore mem StandBy? */
+#define CC_SR_CTL0_EN_SR_ALP_CLK_MASK_SHIFT 18
+#define CC_SR_CTL0_EN_SR_HT_CLK_SHIFT 19
+#define CC_SR_CTL0_ALLOW_PIC_SHIFT 20 /* Allow pic to separate power domains */
+#define CC_SR_CTL0_MAX_SR_LQ_CLK_CNT_SHIFT 25
+#define CC_SR_CTL0_EN_MEM_DISABLE_FOR_SLEEP 30
+
+#define ECI_INLO_PKTDUR_MASK 0x000000f0 /* [7:4] - 4 bits */
+#define ECI_INLO_PKTDUR_SHIFT 4
+
+/* gci chip control bits */
+#define GCI_GPIO_CHIPCTRL_ENAB_IN_BIT 0
+#define GCI_GPIO_CHIPCTRL_ENAB_OP_BIT 1
+#define GCI_GPIO_CHIPCTRL_INVERT_BIT 2
+#define GCI_GPIO_CHIPCTRL_PULLUP_BIT 3
+#define GCI_GPIO_CHIPCTRL_PULLDN_BIT 4
+#define GCI_GPIO_CHIPCTRL_ENAB_BTSIG_BIT 5
+#define GCI_GPIO_CHIPCTRL_ENAB_OD_OP_BIT 6
+#define GCI_GPIO_CHIPCTRL_ENAB_EXT_GPIO_BIT 7
+
+/* gci GPIO input status bits */
+#define GCI_GPIO_STS_VALUE_BIT 0
+#define GCI_GPIO_STS_POS_EDGE_BIT 1
+#define GCI_GPIO_STS_NEG_EDGE_BIT 2
+#define GCI_GPIO_STS_FAST_EDGE_BIT 3
+#define GCI_GPIO_STS_CLEAR 0xF
+
+#define GCI_GPIO_STS_VALUE (1 << GCI_GPIO_STS_VALUE_BIT)
+
+#endif /* _SBCHIPC_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbconfig.h b/drivers/net/wireless/bcmdhd/include/sbconfig.h
new file mode 100644
index 000000000000..65a3caaca165
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sbconfig.h
@@ -0,0 +1,282 @@
+/*
+ * Broadcom SiliconBackplane hardware register definitions.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sbconfig.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _SBCONFIG_H
+#define _SBCONFIG_H
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define _PADLINE(line) pad ## line
+#define _XSTR(line) _PADLINE(line)
+#define PAD _XSTR(__LINE__)
+#endif
+
+/* enumeration in SB is based on the premise that cores are contiguos in the
+ * enumeration space.
+ */
+#define SB_BUS_SIZE 0x10000 /* Each bus gets 64Kbytes for cores */
+#define SB_BUS_BASE(b) (SI_ENUM_BASE + (b) * SB_BUS_SIZE)
+#define SB_BUS_MAXCORES (SB_BUS_SIZE / SI_CORE_SIZE) /* Max cores per bus */
+
+/*
+ * Sonics Configuration Space Registers.
+ */
+#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */
+#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */
+
+#define SBIPSFLAG 0x08
+#define SBTPSFLAG 0x18
+#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */
+#define SBTMERRLOG 0x50 /* sonics >= 2.3 */
+#define SBADMATCH3 0x60
+#define SBADMATCH2 0x68
+#define SBADMATCH1 0x70
+#define SBIMSTATE 0x90
+#define SBINTVEC 0x94
+#define SBTMSTATELOW 0x98
+#define SBTMSTATEHIGH 0x9c
+#define SBBWA0 0xa0
+#define SBIMCONFIGLOW 0xa8
+#define SBIMCONFIGHIGH 0xac
+#define SBADMATCH0 0xb0
+#define SBTMCONFIGLOW 0xb8
+#define SBTMCONFIGHIGH 0xbc
+#define SBBCONFIG 0xc0
+#define SBBSTATE 0xc8
+#define SBACTCNFG 0xd8
+#define SBFLAGST 0xe8
+#define SBIDLOW 0xf8
+#define SBIDHIGH 0xfc
+
+/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have
+ * a few registers *below* that line. I think it would be very confusing to try
+ * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here,
+ */
+
+#define SBIMERRLOGA 0xea8
+#define SBIMERRLOG 0xeb0
+#define SBTMPORTCONNID0 0xed8
+#define SBTMPORTLOCK0 0xef8
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+typedef volatile struct _sbconfig {
+ uint32 PAD[2];
+ uint32 sbipsflag; /* initiator port ocp slave flag */
+ uint32 PAD[3];
+ uint32 sbtpsflag; /* target port ocp slave flag */
+ uint32 PAD[11];
+ uint32 sbtmerrloga; /* (sonics >= 2.3) */
+ uint32 PAD;
+ uint32 sbtmerrlog; /* (sonics >= 2.3) */
+ uint32 PAD[3];
+ uint32 sbadmatch3; /* address match3 */
+ uint32 PAD;
+ uint32 sbadmatch2; /* address match2 */
+ uint32 PAD;
+ uint32 sbadmatch1; /* address match1 */
+ uint32 PAD[7];
+ uint32 sbimstate; /* initiator agent state */
+ uint32 sbintvec; /* interrupt mask */
+ uint32 sbtmstatelow; /* target state */
+ uint32 sbtmstatehigh; /* target state */
+ uint32 sbbwa0; /* bandwidth allocation table0 */
+ uint32 PAD;
+ uint32 sbimconfiglow; /* initiator configuration */
+ uint32 sbimconfighigh; /* initiator configuration */
+ uint32 sbadmatch0; /* address match0 */
+ uint32 PAD;
+ uint32 sbtmconfiglow; /* target configuration */
+ uint32 sbtmconfighigh; /* target configuration */
+ uint32 sbbconfig; /* broadcast configuration */
+ uint32 PAD;
+ uint32 sbbstate; /* broadcast state */
+ uint32 PAD[3];
+ uint32 sbactcnfg; /* activate configuration */
+ uint32 PAD[3];
+ uint32 sbflagst; /* current sbflags */
+ uint32 PAD[3];
+ uint32 sbidlow; /* identification */
+ uint32 sbidhigh; /* identification */
+} sbconfig_t;
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+/* sbipsflag */
+#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */
+#define SBIPS_INT1_SHIFT 0
+#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */
+#define SBIPS_INT2_SHIFT 8
+#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */
+#define SBIPS_INT3_SHIFT 16
+#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */
+#define SBIPS_INT4_SHIFT 24
+
+/* sbtpsflag */
+#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */
+#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */
+
+/* sbtmerrlog */
+#define SBTMEL_CM 0x00000007 /* command */
+#define SBTMEL_CI 0x0000ff00 /* connection id */
+#define SBTMEL_EC 0x0f000000 /* error code */
+#define SBTMEL_ME 0x80000000 /* multiple error */
+
+/* sbimstate */
+#define SBIM_PC 0xf /* pipecount */
+#define SBIM_AP_MASK 0x30 /* arbitration policy */
+#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */
+#define SBIM_AP_TS 0x10 /* use timesliaces only */
+#define SBIM_AP_TK 0x20 /* use token only */
+#define SBIM_AP_RSV 0x30 /* reserved */
+#define SBIM_IBE 0x20000 /* inbanderror */
+#define SBIM_TO 0x40000 /* timeout */
+#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */
+#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */
+
+/* sbtmstatelow */
+#define SBTML_RESET 0x0001 /* reset */
+#define SBTML_REJ_MASK 0x0006 /* reject field */
+#define SBTML_REJ 0x0002 /* reject */
+#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */
+
+#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */
+
+/* sbtmstatehigh */
+#define SBTMH_SERR 0x0001 /* serror */
+#define SBTMH_INT 0x0002 /* interrupt */
+#define SBTMH_BUSY 0x0004 /* busy */
+#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */
+
+#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */
+
+/* sbbwa0 */
+#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */
+#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */
+#define SBBWA_TAB1_SHIFT 16
+
+/* sbimconfiglow */
+#define SBIMCL_STO_MASK 0x7 /* service timeout */
+#define SBIMCL_RTO_MASK 0x70 /* request timeout */
+#define SBIMCL_RTO_SHIFT 4
+#define SBIMCL_CID_MASK 0xff0000 /* connection id */
+#define SBIMCL_CID_SHIFT 16
+
+/* sbimconfighigh */
+#define SBIMCH_IEM_MASK 0xc /* inband error mode */
+#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */
+#define SBIMCH_TEM_SHIFT 4
+#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */
+#define SBIMCH_BEM_SHIFT 6
+
+/* sbadmatch0 */
+#define SBAM_TYPE_MASK 0x3 /* address type */
+#define SBAM_AD64 0x4 /* reserved */
+#define SBAM_ADINT0_MASK 0xf8 /* type0 size */
+#define SBAM_ADINT0_SHIFT 3
+#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */
+#define SBAM_ADINT1_SHIFT 3
+#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */
+#define SBAM_ADINT2_SHIFT 3
+#define SBAM_ADEN 0x400 /* enable */
+#define SBAM_ADNEG 0x800 /* negative decode */
+#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */
+#define SBAM_BASE0_SHIFT 8
+#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */
+#define SBAM_BASE1_SHIFT 12
+#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */
+#define SBAM_BASE2_SHIFT 16
+
+/* sbtmconfiglow */
+#define SBTMCL_CD_MASK 0xff /* clock divide */
+#define SBTMCL_CO_MASK 0xf800 /* clock offset */
+#define SBTMCL_CO_SHIFT 11
+#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */
+#define SBTMCL_IF_SHIFT 18
+#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */
+#define SBTMCL_IM_SHIFT 24
+
+/* sbtmconfighigh */
+#define SBTMCH_BM_MASK 0x3 /* busy mode */
+#define SBTMCH_RM_MASK 0x3 /* retry mode */
+#define SBTMCH_RM_SHIFT 2
+#define SBTMCH_SM_MASK 0x30 /* stop mode */
+#define SBTMCH_SM_SHIFT 4
+#define SBTMCH_EM_MASK 0x300 /* sb error mode */
+#define SBTMCH_EM_SHIFT 8
+#define SBTMCH_IM_MASK 0xc00 /* int mode */
+#define SBTMCH_IM_SHIFT 10
+
+/* sbbconfig */
+#define SBBC_LAT_MASK 0x3 /* sb latency */
+#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */
+#define SBBC_MAX0_SHIFT 16
+#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */
+#define SBBC_MAX1_SHIFT 20
+
+/* sbbstate */
+#define SBBS_SRD 0x1 /* st reg disable */
+#define SBBS_HRD 0x2 /* hold reg disable */
+
+/* sbidlow */
+#define SBIDL_CS_MASK 0x3 /* config space */
+#define SBIDL_AR_MASK 0x38 /* # address ranges supported */
+#define SBIDL_AR_SHIFT 3
+#define SBIDL_SYNCH 0x40 /* sync */
+#define SBIDL_INIT 0x80 /* initiator */
+#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */
+#define SBIDL_MINLAT_SHIFT 8
+#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */
+#define SBIDL_MAXLAT_SHIFT 12
+#define SBIDL_FIRST 0x10000 /* this initiator is first */
+#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */
+#define SBIDL_CW_SHIFT 18
+#define SBIDL_TP_MASK 0xf00000 /* target ports */
+#define SBIDL_TP_SHIFT 20
+#define SBIDL_IP_MASK 0xf000000 /* initiator ports */
+#define SBIDL_IP_SHIFT 24
+#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */
+#define SBIDL_RV_SHIFT 28
+#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */
+#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */
+
+/* sbidhigh */
+#define SBIDH_RC_MASK 0x000f /* revision code */
+#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
+#define SBIDH_RCE_SHIFT 8
+#define SBCOREREV(sbidh) \
+ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
+#define SBIDH_CC_MASK 0x8ff0 /* core code */
+#define SBIDH_CC_SHIFT 4
+#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
+#define SBIDH_VC_SHIFT 16
+
+#define SB_COMMIT 0xfd8 /* update buffered registers value */
+
+/* vendor codes */
+#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */
+
+#endif /* _SBCONFIG_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbhnddma.h b/drivers/net/wireless/bcmdhd/include/sbhnddma.h
new file mode 100644
index 000000000000..ea9d13f3899b
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sbhnddma.h
@@ -0,0 +1,416 @@
+/*
+ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface
+ * This supports the following chips: BCM42xx, 44xx, 47xx .
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sbhnddma.h 530682 2015-01-30 18:48:21Z $
+ */
+
+#ifndef _sbhnddma_h_
+#define _sbhnddma_h_
+
+/* DMA structure:
+ * support two DMA engines: 32 bits address or 64 bit addressing
+ * basic DMA register set is per channel(transmit or receive)
+ * a pair of channels is defined for convenience
+ */
+
+
+/* 32 bits addressing */
+
+/* dma registers per channel(xmt or rcv) */
+typedef volatile struct {
+ uint32 control; /* enable, et al */
+ uint32 addr; /* descriptor ring base address (4K aligned) */
+ uint32 ptr; /* last descriptor posted to chip */
+ uint32 status; /* current active descriptor, et al */
+} dma32regs_t;
+
+typedef volatile struct {
+ dma32regs_t xmt; /* dma tx channel */
+ dma32regs_t rcv; /* dma rx channel */
+} dma32regp_t;
+
+typedef volatile struct { /* diag access */
+ uint32 fifoaddr; /* diag address */
+ uint32 fifodatalow; /* low 32bits of data */
+ uint32 fifodatahigh; /* high 32bits of data */
+ uint32 pad; /* reserved */
+} dma32diag_t;
+
+/*
+ * DMA Descriptor
+ * Descriptors are only read by the hardware, never written back.
+ */
+typedef volatile struct {
+ uint32 ctrl; /* misc control bits & bufcount */
+ uint32 addr; /* data buffer address */
+} dma32dd_t;
+
+/*
+ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page.
+ */
+#define D32RINGALIGN_BITS 12
+#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS)
+#define D32RINGALIGN (1 << D32RINGALIGN_BITS)
+
+#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t))
+
+/* transmit channel control */
+#define XC_XE ((uint32)1 << 0) /* transmit enable */
+#define XC_SE ((uint32)1 << 1) /* transmit suspend request */
+#define XC_LE ((uint32)1 << 2) /* loopback enable */
+#define XC_FL ((uint32)1 << 4) /* flush request */
+#define XC_MR_MASK 0x000001C0 /* Multiple outstanding reads */
+#define XC_MR_SHIFT 6
+#define XC_PD ((uint32)1 << 11) /* parity check disable */
+#define XC_AE ((uint32)3 << 16) /* address extension bits */
+#define XC_AE_SHIFT 16
+#define XC_BL_MASK 0x001C0000 /* BurstLen bits */
+#define XC_BL_SHIFT 18
+#define XC_PC_MASK 0x00E00000 /* Prefetch control */
+#define XC_PC_SHIFT 21
+#define XC_PT_MASK 0x03000000 /* Prefetch threshold */
+#define XC_PT_SHIFT 24
+
+/* Multiple outstanding reads */
+#define DMA_MR_1 0
+#define DMA_MR_2 1
+#define DMA_MR_4 2
+#define DMA_MR_8 3
+#define DMA_MR_12 4
+#define DMA_MR_16 5
+#define DMA_MR_20 6
+#define DMA_MR_32 7
+
+/* DMA Burst Length in bytes */
+#define DMA_BL_16 0
+#define DMA_BL_32 1
+#define DMA_BL_64 2
+#define DMA_BL_128 3
+#define DMA_BL_256 4
+#define DMA_BL_512 5
+#define DMA_BL_1024 6
+
+/* Prefetch control */
+#define DMA_PC_0 0
+#define DMA_PC_4 1
+#define DMA_PC_8 2
+#define DMA_PC_16 3
+/* others: reserved */
+
+/* Prefetch threshold */
+#define DMA_PT_1 0
+#define DMA_PT_2 1
+#define DMA_PT_4 2
+#define DMA_PT_8 3
+
+/* transmit descriptor table pointer */
+#define XP_LD_MASK 0xfff /* last valid descriptor */
+
+/* transmit channel status */
+#define XS_CD_MASK 0x0fff /* current descriptor pointer */
+#define XS_XS_MASK 0xf000 /* transmit state */
+#define XS_XS_SHIFT 12
+#define XS_XS_DISABLED 0x0000 /* disabled */
+#define XS_XS_ACTIVE 0x1000 /* active */
+#define XS_XS_IDLE 0x2000 /* idle wait */
+#define XS_XS_STOPPED 0x3000 /* stopped */
+#define XS_XS_SUSP 0x4000 /* suspend pending */
+#define XS_XE_MASK 0xf0000 /* transmit errors */
+#define XS_XE_SHIFT 16
+#define XS_XE_NOERR 0x00000 /* no error */
+#define XS_XE_DPE 0x10000 /* descriptor protocol error */
+#define XS_XE_DFU 0x20000 /* data fifo underrun */
+#define XS_XE_BEBR 0x30000 /* bus error on buffer read */
+#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */
+#define XS_AD_MASK 0xfff00000 /* active descriptor */
+#define XS_AD_SHIFT 20
+
+/* receive channel control */
+#define RC_RE ((uint32)1 << 0) /* receive enable */
+#define RC_RO_MASK 0xfe /* receive frame offset */
+#define RC_RO_SHIFT 1
+#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */
+#define RC_SH ((uint32)1 << 9) /* separate rx header descriptor enable */
+#define RC_OC ((uint32)1 << 10) /* overflow continue */
+#define RC_PD ((uint32)1 << 11) /* parity check disable */
+#define RC_AE ((uint32)3 << 16) /* address extension bits */
+#define RC_AE_SHIFT 16
+#define RC_BL_MASK 0x001C0000 /* BurstLen bits */
+#define RC_BL_SHIFT 18
+#define RC_PC_MASK 0x00E00000 /* Prefetch control */
+#define RC_PC_SHIFT 21
+#define RC_PT_MASK 0x03000000 /* Prefetch threshold */
+#define RC_PT_SHIFT 24
+
+/* receive descriptor table pointer */
+#define RP_LD_MASK 0xfff /* last valid descriptor */
+
+/* receive channel status */
+#define RS_CD_MASK 0x0fff /* current descriptor pointer */
+#define RS_RS_MASK 0xf000 /* receive state */
+#define RS_RS_SHIFT 12
+#define RS_RS_DISABLED 0x0000 /* disabled */
+#define RS_RS_ACTIVE 0x1000 /* active */
+#define RS_RS_IDLE 0x2000 /* idle wait */
+#define RS_RS_STOPPED 0x3000 /* reserved */
+#define RS_RE_MASK 0xf0000 /* receive errors */
+#define RS_RE_SHIFT 16
+#define RS_RE_NOERR 0x00000 /* no error */
+#define RS_RE_DPE 0x10000 /* descriptor protocol error */
+#define RS_RE_DFO 0x20000 /* data fifo overflow */
+#define RS_RE_BEBW 0x30000 /* bus error on buffer write */
+#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */
+#define RS_AD_MASK 0xfff00000 /* active descriptor */
+#define RS_AD_SHIFT 20
+
+/* fifoaddr */
+#define FA_OFF_MASK 0xffff /* offset */
+#define FA_SEL_MASK 0xf0000 /* select */
+#define FA_SEL_SHIFT 16
+#define FA_SEL_XDD 0x00000 /* transmit dma data */
+#define FA_SEL_XDP 0x10000 /* transmit dma pointers */
+#define FA_SEL_RDD 0x40000 /* receive dma data */
+#define FA_SEL_RDP 0x50000 /* receive dma pointers */
+#define FA_SEL_XFD 0x80000 /* transmit fifo data */
+#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */
+#define FA_SEL_RFD 0xc0000 /* receive fifo data */
+#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */
+#define FA_SEL_RSD 0xe0000 /* receive frame status data */
+#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */
+
+/* descriptor control flags */
+#define CTRL_BC_MASK 0x00001fff /* buffer byte count, real data len must <= 4KB */
+#define CTRL_AE ((uint32)3 << 16) /* address extension bits */
+#define CTRL_AE_SHIFT 16
+#define CTRL_PARITY ((uint32)3 << 18) /* parity bit */
+#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */
+#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */
+#define CTRL_EOF ((uint32)1 << 30) /* end of frame */
+#define CTRL_SOF ((uint32)1 << 31) /* start of frame */
+
+/* control flags in the range [27:20] are core-specific and not defined here */
+#define CTRL_CORE_MASK 0x0ff00000
+
+/* 64 bits addressing */
+
+/* dma registers per channel(xmt or rcv) */
+typedef volatile struct {
+ uint32 control; /* enable, et al */
+ uint32 ptr; /* last descriptor posted to chip */
+ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */
+ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */
+ uint32 status0; /* current descriptor, xmt state */
+ uint32 status1; /* active descriptor, xmt error */
+} dma64regs_t;
+
+typedef volatile struct {
+ dma64regs_t tx; /* dma64 tx channel */
+ dma64regs_t rx; /* dma64 rx channel */
+} dma64regp_t;
+
+typedef volatile struct { /* diag access */
+ uint32 fifoaddr; /* diag address */
+ uint32 fifodatalow; /* low 32bits of data */
+ uint32 fifodatahigh; /* high 32bits of data */
+ uint32 pad; /* reserved */
+} dma64diag_t;
+
+/*
+ * DMA Descriptor
+ * Descriptors are only read by the hardware, never written back.
+ */
+typedef volatile struct {
+ uint32 ctrl1; /* misc control bits */
+ uint32 ctrl2; /* buffer count and address extension */
+ uint32 addrlow; /* memory address of the date buffer, bits 31:0 */
+ uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */
+} dma64dd_t;
+
+/*
+ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss.
+ */
+#define D64RINGALIGN_BITS 13
+#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS)
+#define D64RINGBOUNDARY (1 << D64RINGALIGN_BITS)
+
+#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t))
+
+/* for cores with large descriptor ring support, descriptor ring size can be up to 4096 */
+#define D64MAXDD_LARGE ((1 << 16) / sizeof (dma64dd_t))
+
+/* for cores with large descriptor ring support (4k descriptors), descriptor ring cannot cross
+ * 64K boundary
+ */
+#define D64RINGBOUNDARY_LARGE (1 << 16)
+
+/*
+ * Default DMA Burstlen values for USBRev >= 12 and SDIORev >= 11.
+ * When this field contains the value N, the burst length is 2**(N + 4) bytes.
+ */
+#define D64_DEF_USBBURSTLEN 2
+#define D64_DEF_SDIOBURSTLEN 1
+
+
+#ifndef D64_USBBURSTLEN
+#define D64_USBBURSTLEN DMA_BL_64
+#endif
+#ifndef D64_SDIOBURSTLEN
+#define D64_SDIOBURSTLEN DMA_BL_32
+#endif
+
+/* transmit channel control */
+#define D64_XC_XE 0x00000001 /* transmit enable */
+#define D64_XC_SE 0x00000002 /* transmit suspend request */
+#define D64_XC_LE 0x00000004 /* loopback enable */
+#define D64_XC_FL 0x00000010 /* flush request */
+#define D64_XC_MR_MASK 0x000001C0 /* Multiple outstanding reads */
+#define D64_XC_MR_SHIFT 6
+#define D64_XC_PD 0x00000800 /* parity check disable */
+#define D64_XC_AE 0x00030000 /* address extension bits */
+#define D64_XC_AE_SHIFT 16
+#define D64_XC_BL_MASK 0x001C0000 /* BurstLen bits */
+#define D64_XC_BL_SHIFT 18
+#define D64_XC_PC_MASK 0x00E00000 /* Prefetch control */
+#define D64_XC_PC_SHIFT 21
+#define D64_XC_PT_MASK 0x03000000 /* Prefetch threshold */
+#define D64_XC_PT_SHIFT 24
+
+/* transmit descriptor table pointer */
+#define D64_XP_LD_MASK 0x00001fff /* last valid descriptor */
+
+/* transmit channel status */
+#define D64_XS0_CD_MASK (di->d64_xs0_cd_mask) /* current descriptor pointer */
+#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */
+#define D64_XS0_XS_SHIFT 28
+#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */
+#define D64_XS0_XS_ACTIVE 0x10000000 /* active */
+#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */
+#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */
+#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */
+
+#define D64_XS1_AD_MASK (di->d64_xs1_ad_mask) /* active descriptor */
+#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */
+#define D64_XS1_XE_SHIFT 28
+#define D64_XS1_XE_NOERR 0x00000000 /* no error */
+#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */
+#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */
+#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */
+#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */
+#define D64_XS1_XE_COREE 0x50000000 /* core error */
+
+/* receive channel control */
+#define D64_RC_RE 0x00000001 /* receive enable */
+#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */
+#define D64_RC_RO_SHIFT 1
+#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */
+#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */
+#define D64_RC_SHIFT 9 /* separate rx header descriptor enable */
+#define D64_RC_OC 0x00000400 /* overflow continue */
+#define D64_RC_PD 0x00000800 /* parity check disable */
+#define D64_RC_GE 0x00004000 /* Glom enable */
+#define D64_RC_AE 0x00030000 /* address extension bits */
+#define D64_RC_AE_SHIFT 16
+#define D64_RC_BL_MASK 0x001C0000 /* BurstLen bits */
+#define D64_RC_BL_SHIFT 18
+#define D64_RC_PC_MASK 0x00E00000 /* Prefetch control */
+#define D64_RC_PC_SHIFT 21
+#define D64_RC_PT_MASK 0x03000000 /* Prefetch threshold */
+#define D64_RC_PT_SHIFT 24
+
+/* flags for dma controller */
+#define DMA_CTRL_PEN (1 << 0) /* partity enable */
+#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */
+#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */
+#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */
+#define DMA_CTRL_USB_BOUNDRY4KB_WAR (1 << 4)
+#define DMA_CTRL_DMA_AVOIDANCE_WAR (1 << 5) /* DMA avoidance WAR for 4331 */
+#define DMA_CTRL_RXSINGLE (1 << 6) /* always single buffer */
+
+/* receive descriptor table pointer */
+#define D64_RP_LD_MASK 0x00001fff /* last valid descriptor */
+
+/* receive channel status */
+#define D64_RS0_CD_MASK (di->d64_rs0_cd_mask) /* current descriptor pointer */
+#define D64_RS0_RS_MASK 0xf0000000 /* receive state */
+#define D64_RS0_RS_SHIFT 28
+#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */
+#define D64_RS0_RS_ACTIVE 0x10000000 /* active */
+#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */
+#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */
+#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */
+
+#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */
+#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */
+#define D64_RS1_RE_SHIFT 28
+#define D64_RS1_RE_NOERR 0x00000000 /* no error */
+#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */
+#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */
+#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */
+#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */
+#define D64_RS1_RE_COREE 0x50000000 /* core error */
+
+/* fifoaddr */
+#define D64_FA_OFF_MASK 0xffff /* offset */
+#define D64_FA_SEL_MASK 0xf0000 /* select */
+#define D64_FA_SEL_SHIFT 16
+#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */
+#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */
+#define D64_FA_SEL_RDD 0x40000 /* receive dma data */
+#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */
+#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */
+#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */
+#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */
+#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */
+#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */
+#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */
+
+/* descriptor control flags 1 */
+#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */
+#define D64_CTRL1_NOTPCIE ((uint32)1 << 18) /* buirst size control */
+#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */
+#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */
+#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */
+#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */
+
+/* descriptor control flags 2 */
+#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */
+#define D64_CTRL2_AE 0x00030000 /* address extension bits */
+#define D64_CTRL2_AE_SHIFT 16
+#define D64_CTRL2_PARITY 0x00040000 /* parity bit */
+
+/* control flags in the range [27:20] are core-specific and not defined here */
+#define D64_CTRL_CORE_MASK 0x0ff00000
+
+#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */
+#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */
+#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1, d11corerev >= 22 */
+#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */
+
+/* receive frame status */
+typedef volatile struct {
+ uint16 len;
+ uint16 flags;
+} dma_rxh_t;
+
+#endif /* _sbhnddma_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/sbpcmcia.h b/drivers/net/wireless/bcmdhd/include/sbpcmcia.h
new file mode 100644
index 000000000000..4f2d40c7ef1d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sbpcmcia.h
@@ -0,0 +1,113 @@
+/*
+ * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sbpcmcia.h 427964 2013-10-07 07:13:33Z $
+ */
+
+#ifndef _SBPCMCIA_H
+#define _SBPCMCIA_H
+
+/* All the addresses that are offsets in attribute space are divided
+ * by two to account for the fact that odd bytes are invalid in
+ * attribute space and our read/write routines make the space appear
+ * as if they didn't exist. Still we want to show the original numbers
+ * as documented in the hnd_pcmcia core manual.
+ */
+
+/* PCMCIA Function Configuration Registers */
+#define PCMCIA_FCR (0x700 / 2)
+
+#define FCR0_OFF 0
+#define FCR1_OFF (0x40 / 2)
+#define FCR2_OFF (0x80 / 2)
+#define FCR3_OFF (0xc0 / 2)
+
+#define PCMCIA_FCR0 (0x700 / 2)
+#define PCMCIA_FCR1 (0x740 / 2)
+#define PCMCIA_FCR2 (0x780 / 2)
+#define PCMCIA_FCR3 (0x7c0 / 2)
+
+/* Standard PCMCIA FCR registers */
+
+#define PCMCIA_COR 0
+
+#define COR_RST 0x80
+#define COR_LEV 0x40
+#define COR_IRQEN 0x04
+#define COR_BLREN 0x01
+#define COR_FUNEN 0x01
+
+
+#define PCICIA_FCSR (2 / 2)
+#define PCICIA_PRR (4 / 2)
+#define PCICIA_SCR (6 / 2)
+#define PCICIA_ESR (8 / 2)
+
+
+#define PCM_MEMOFF 0x0000
+#define F0_MEMOFF 0x1000
+#define F1_MEMOFF 0x2000
+#define F2_MEMOFF 0x3000
+#define F3_MEMOFF 0x4000
+
+/* Memory base in the function fcr's */
+#define MEM_ADDR0 (0x728 / 2)
+#define MEM_ADDR1 (0x72a / 2)
+#define MEM_ADDR2 (0x72c / 2)
+
+/* PCMCIA base plus Srom access in fcr0: */
+#define PCMCIA_ADDR0 (0x072e / 2)
+#define PCMCIA_ADDR1 (0x0730 / 2)
+#define PCMCIA_ADDR2 (0x0732 / 2)
+
+#define MEM_SEG (0x0734 / 2)
+#define SROM_CS (0x0736 / 2)
+#define SROM_DATAL (0x0738 / 2)
+#define SROM_DATAH (0x073a / 2)
+#define SROM_ADDRL (0x073c / 2)
+#define SROM_ADDRH (0x073e / 2)
+#define SROM_INFO2 (0x0772 / 2) /* Corerev >= 2 && <= 5 */
+#define SROM_INFO (0x07be / 2) /* Corerev >= 6 */
+
+/* Values for srom_cs: */
+#define SROM_IDLE 0
+#define SROM_WRITE 1
+#define SROM_READ 2
+#define SROM_WEN 4
+#define SROM_WDS 7
+#define SROM_DONE 8
+
+/* Fields in srom_info: */
+#define SRI_SZ_MASK 0x03
+#define SRI_BLANK 0x04
+#define SRI_OTP 0x80
+
+
+/* sbtmstatelow */
+#define SBTML_INT_ACK 0x40000 /* ack the sb interrupt */
+#define SBTML_INT_EN 0x20000 /* enable sb interrupt */
+
+/* sbtmstatehigh */
+#define SBTMH_INT_STATUS 0x40000 /* sb interrupt status */
+
+#endif /* _SBPCMCIA_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbsdio.h b/drivers/net/wireless/bcmdhd/include/sbsdio.h
new file mode 100644
index 000000000000..ecb5da0dcbed
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sbsdio.h
@@ -0,0 +1,186 @@
+/*
+ * SDIO device core hardware definitions.
+ * sdio is a portion of the pcmcia core in core rev 3 - rev 8
+ *
+ * SDIO core support 1bit, 4 bit SDIO mode as well as SPI mode.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sbsdio.h 383835 2013-02-07 23:32:39Z $
+ */
+
+#ifndef _SBSDIO_H
+#define _SBSDIO_H
+
+#define SBSDIO_NUM_FUNCTION 3 /* as of sdiod rev 0, supports 3 functions */
+
+/* function 1 miscellaneous registers */
+#define SBSDIO_SPROM_CS 0x10000 /* sprom command and status */
+#define SBSDIO_SPROM_INFO 0x10001 /* sprom info register */
+#define SBSDIO_SPROM_DATA_LOW 0x10002 /* sprom indirect access data byte 0 */
+#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* sprom indirect access data byte 1 */
+#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* sprom indirect access addr byte 0 */
+#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* sprom indirect access addr byte 0 */
+#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu (gpio) output */
+#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu (gpio) enable */
+#define SBSDIO_WATERMARK 0x10008 /* rev < 7, watermark for sdio device */
+#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */
+
+/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */
+#define SBSDIO_FUNC1_SBADDRLOW 0x1000A /* SB Address Window Low (b15) */
+#define SBSDIO_FUNC1_SBADDRMID 0x1000B /* SB Address Window Mid (b23:b16) */
+#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C /* SB Address Window High (b31:b24) */
+#define SBSDIO_FUNC1_FRAMECTRL 0x1000D /* Frame Control (frame term/abort) */
+#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E /* ChipClockCSR (ALP/HT ctl/status) */
+#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F /* SdioPullUp (on cmd, d0-d2) */
+#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 /* Write Frame Byte Count Low */
+#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A /* Write Frame Byte Count High */
+#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B /* Read Frame Byte Count Low */
+#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C /* Read Frame Byte Count High */
+#define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D /* MesBusyCtl at 0x1001D (rev 11) */
+
+#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
+#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
+
+/* Sdio Core Rev 12 */
+#define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1
+#define SBSDIO_FUNC1_SLEEPCSR 0x1001F
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1
+
+/* SBSDIO_SPROM_CS */
+#define SBSDIO_SPROM_IDLE 0
+#define SBSDIO_SPROM_WRITE 1
+#define SBSDIO_SPROM_READ 2
+#define SBSDIO_SPROM_WEN 4
+#define SBSDIO_SPROM_WDS 7
+#define SBSDIO_SPROM_DONE 8
+
+/* SBSDIO_SPROM_INFO */
+#define SROM_SZ_MASK 0x03 /* SROM size, 1: 4k, 2: 16k */
+#define SROM_BLANK 0x04 /* depreciated in corerev 6 */
+#define SROM_OTP 0x80 /* OTP present */
+
+/* SBSDIO_CHIP_CTRL */
+#define SBSDIO_CHIP_CTRL_XTAL 0x01 /* or'd with onchip xtal_pu,
+ * 1: power on oscillator
+ * (for 4318 only)
+ */
+/* SBSDIO_WATERMARK */
+#define SBSDIO_WATERMARK_MASK 0x7f /* number of words - 1 for sd device
+ * to wait before sending data to host
+ */
+
+/* SBSDIO_MESBUSYCTRL */
+/* When RX FIFO has less entries than this & MBE is set
+ * => busy signal is asserted between data blocks.
+*/
+#define SBSDIO_MESBUSYCTRL_MASK 0x7f
+#define SBSDIO_MESBUSYCTRL_ENAB 0x80 /* Enable busy capability for MES access */
+
+/* SBSDIO_DEVICE_CTL */
+#define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when
+ * receiving CMD53
+ */
+#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 /* 1: assertion of sdio interrupt is
+ * synchronous to the sdio clock
+ */
+#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 /* 1: mask all interrupts to host
+ * except the chipActive (rev 8)
+ */
+#define SBSDIO_DEVCTL_PADS_ISO 0x08 /* 1: isolate internal sdio signals, put
+ * external pads in tri-state; requires
+ * sdio bus power cycle to clear (rev 9)
+ */
+#define SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK 0x10 /* Enable function 2 tx for each block */
+#define SBSDIO_DEVCTL_F2WM_ENAB 0x10 /* Enable F2 Watermark */
+#define SBSDIO_DEVCTL_NONDAT_PADS_ISO 0x20 /* Isolate sdio clk and cmd (non-data) */
+
+/* SBSDIO_FUNC1_CHIPCLKCSR */
+#define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */
+#define SBSDIO_FORCE_HT 0x02 /* Force HT request to backplane */
+#define SBSDIO_FORCE_ILP 0x04 /* Force ILP request to backplane */
+#define SBSDIO_ALP_AVAIL_REQ 0x08 /* Make ALP ready (power up xtal) */
+#define SBSDIO_HT_AVAIL_REQ 0x10 /* Make HT ready (power up PLL) */
+#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 /* Squelch clock requests from HW */
+#define SBSDIO_ALP_AVAIL 0x40 /* Status: ALP is ready */
+#define SBSDIO_HT_AVAIL 0x80 /* Status: HT is ready */
+/* In rev8, actual avail bits followed original docs */
+#define SBSDIO_Rev8_HT_AVAIL 0x40
+#define SBSDIO_Rev8_ALP_AVAIL 0x80
+#define SBSDIO_CSR_MASK 0x1F
+
+#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
+#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
+#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
+#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
+#define SBSDIO_CLKAV(regval, alponly) (SBSDIO_ALPAV(regval) && \
+ (alponly ? 1 : SBSDIO_HTAV(regval)))
+
+/* SBSDIO_FUNC1_SDIOPULLUP */
+#define SBSDIO_PULLUP_D0 0x01 /* Enable D0/MISO pullup */
+#define SBSDIO_PULLUP_D1 0x02 /* Enable D1/INT# pullup */
+#define SBSDIO_PULLUP_D2 0x04 /* Enable D2 pullup */
+#define SBSDIO_PULLUP_CMD 0x08 /* Enable CMD/MOSI pullup */
+#define SBSDIO_PULLUP_ALL 0x0f /* All valid bits */
+
+/* function 1 OCP space */
+#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */
+#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
+#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */
+
+/* some duplication with sbsdpcmdev.h here */
+/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
+#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
+#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
+#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
+#define SBSDIO_SBWINDOW_MASK 0xffff8000 /* Address bits from SBADDR regs */
+
+/* direct(mapped) cis space */
+#define SBSDIO_CIS_BASE_COMMON 0x1000 /* MAPPED common CIS address */
+#define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */
+#define SBSDIO_OTP_CIS_SIZE_LIMIT 0x078 /* maximum bytes OTP CIS */
+
+#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF /* cis offset addr is < 17 bits */
+
+#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 /* manfid tuple length, include tuple,
+ * link bytes
+ */
+
+/* indirect cis access (in sprom) */
+#define SBSDIO_SPROM_CIS_OFFSET 0x8 /* 8 control bytes first, CIS starts from
+ * 8th byte
+ */
+
+#define SBSDIO_BYTEMODE_DATALEN_MAX 64 /* sdio byte mode: maximum length of one
+ * data comamnd
+ */
+
+#define SBSDIO_CORE_ADDR_MASK 0x1FFFF /* sdio core function one address mask */
+
+#endif /* _SBSDIO_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h
new file mode 100644
index 000000000000..9041f392f3fd
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h
@@ -0,0 +1,295 @@
+/*
+ * Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific
+ * device core support
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sbsdpcmdev.h 416730 2013-08-06 09:33:19Z $
+ */
+
+#ifndef _sbsdpcmdev_h_
+#define _sbsdpcmdev_h_
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define _PADLINE(line) pad ## line
+#define _XSTR(line) _PADLINE(line)
+#define PAD _XSTR(__LINE__)
+#endif /* PAD */
+
+
+typedef volatile struct {
+ dma64regs_t xmt; /* dma tx */
+ uint32 PAD[2];
+ dma64regs_t rcv; /* dma rx */
+ uint32 PAD[2];
+} dma64p_t;
+
+/* dma64 sdiod corerev >= 1 */
+typedef volatile struct {
+ dma64p_t dma64regs[2];
+ dma64diag_t dmafifo; /* DMA Diagnostic Regs, 0x280-0x28c */
+ uint32 PAD[92];
+} sdiodma64_t;
+
+/* dma32 sdiod corerev == 0 */
+typedef volatile struct {
+ dma32regp_t dma32regs[2]; /* dma tx & rx, 0x200-0x23c */
+ dma32diag_t dmafifo; /* DMA Diagnostic Regs, 0x240-0x24c */
+ uint32 PAD[108];
+} sdiodma32_t;
+
+/* dma32 regs for pcmcia core */
+typedef volatile struct {
+ dma32regp_t dmaregs; /* DMA Regs, 0x200-0x21c, rev8 */
+ dma32diag_t dmafifo; /* DMA Diagnostic Regs, 0x220-0x22c */
+ uint32 PAD[116];
+} pcmdma32_t;
+
+/* core registers */
+typedef volatile struct {
+ uint32 corecontrol; /* CoreControl, 0x000, rev8 */
+ uint32 corestatus; /* CoreStatus, 0x004, rev8 */
+ uint32 PAD[1];
+ uint32 biststatus; /* BistStatus, 0x00c, rev8 */
+
+ /* PCMCIA access */
+ uint16 pcmciamesportaladdr; /* PcmciaMesPortalAddr, 0x010, rev8 */
+ uint16 PAD[1];
+ uint16 pcmciamesportalmask; /* PcmciaMesPortalMask, 0x014, rev8 */
+ uint16 PAD[1];
+ uint16 pcmciawrframebc; /* PcmciaWrFrameBC, 0x018, rev8 */
+ uint16 PAD[1];
+ uint16 pcmciaunderflowtimer; /* PcmciaUnderflowTimer, 0x01c, rev8 */
+ uint16 PAD[1];
+
+ /* interrupt */
+ uint32 intstatus; /* IntStatus, 0x020, rev8 */
+ uint32 hostintmask; /* IntHostMask, 0x024, rev8 */
+ uint32 intmask; /* IntSbMask, 0x028, rev8 */
+ uint32 sbintstatus; /* SBIntStatus, 0x02c, rev8 */
+ uint32 sbintmask; /* SBIntMask, 0x030, rev8 */
+ uint32 funcintmask; /* SDIO Function Interrupt Mask, SDIO rev4 */
+ uint32 PAD[2];
+ uint32 tosbmailbox; /* ToSBMailbox, 0x040, rev8 */
+ uint32 tohostmailbox; /* ToHostMailbox, 0x044, rev8 */
+ uint32 tosbmailboxdata; /* ToSbMailboxData, 0x048, rev8 */
+ uint32 tohostmailboxdata; /* ToHostMailboxData, 0x04c, rev8 */
+
+ /* synchronized access to registers in SDIO clock domain */
+ uint32 sdioaccess; /* SdioAccess, 0x050, rev8 */
+ uint32 PAD[3];
+
+ /* PCMCIA frame control */
+ uint8 pcmciaframectrl; /* pcmciaFrameCtrl, 0x060, rev8 */
+ uint8 PAD[3];
+ uint8 pcmciawatermark; /* pcmciaWaterMark, 0x064, rev8 */
+ uint8 PAD[155];
+
+ /* interrupt batching control */
+ uint32 intrcvlazy; /* IntRcvLazy, 0x100, rev8 */
+ uint32 PAD[3];
+
+ /* counters */
+ uint32 cmd52rd; /* Cmd52RdCount, 0x110, rev8, SDIO: cmd52 reads */
+ uint32 cmd52wr; /* Cmd52WrCount, 0x114, rev8, SDIO: cmd52 writes */
+ uint32 cmd53rd; /* Cmd53RdCount, 0x118, rev8, SDIO: cmd53 reads */
+ uint32 cmd53wr; /* Cmd53WrCount, 0x11c, rev8, SDIO: cmd53 writes */
+ uint32 abort; /* AbortCount, 0x120, rev8, SDIO: aborts */
+ uint32 datacrcerror; /* DataCrcErrorCount, 0x124, rev8, SDIO: frames w/bad CRC */
+ uint32 rdoutofsync; /* RdOutOfSyncCount, 0x128, rev8, SDIO/PCMCIA: Rd Frm OOS */
+ uint32 wroutofsync; /* RdOutOfSyncCount, 0x12c, rev8, SDIO/PCMCIA: Wr Frm OOS */
+ uint32 writebusy; /* WriteBusyCount, 0x130, rev8, SDIO: dev asserted "busy" */
+ uint32 readwait; /* ReadWaitCount, 0x134, rev8, SDIO: read: no data avail */
+ uint32 readterm; /* ReadTermCount, 0x138, rev8, SDIO: rd frm terminates */
+ uint32 writeterm; /* WriteTermCount, 0x13c, rev8, SDIO: wr frm terminates */
+ uint32 PAD[40];
+ uint32 clockctlstatus; /* ClockCtlStatus, 0x1e0, rev8 */
+ uint32 PAD[7];
+
+ /* DMA engines */
+ volatile union {
+ pcmdma32_t pcm32;
+ sdiodma32_t sdiod32;
+ sdiodma64_t sdiod64;
+ } dma;
+
+ /* SDIO/PCMCIA CIS region */
+ char cis[512]; /* 512 byte CIS, 0x400-0x5ff, rev6 */
+
+ /* PCMCIA function control registers */
+ char pcmciafcr[256]; /* PCMCIA FCR, 0x600-6ff, rev6 */
+ uint16 PAD[55];
+
+ /* PCMCIA backplane access */
+ uint16 backplanecsr; /* BackplaneCSR, 0x76E, rev6 */
+ uint16 backplaneaddr0; /* BackplaneAddr0, 0x770, rev6 */
+ uint16 backplaneaddr1; /* BackplaneAddr1, 0x772, rev6 */
+ uint16 backplaneaddr2; /* BackplaneAddr2, 0x774, rev6 */
+ uint16 backplaneaddr3; /* BackplaneAddr3, 0x776, rev6 */
+ uint16 backplanedata0; /* BackplaneData0, 0x778, rev6 */
+ uint16 backplanedata1; /* BackplaneData1, 0x77a, rev6 */
+ uint16 backplanedata2; /* BackplaneData2, 0x77c, rev6 */
+ uint16 backplanedata3; /* BackplaneData3, 0x77e, rev6 */
+ uint16 PAD[31];
+
+ /* sprom "size" & "blank" info */
+ uint16 spromstatus; /* SPROMStatus, 0x7BE, rev2 */
+ uint32 PAD[464];
+
+ /* Sonics SiliconBackplane registers */
+ sbconfig_t sbconfig; /* SbConfig Regs, 0xf00-0xfff, rev8 */
+} sdpcmd_regs_t;
+
+/* corecontrol */
+#define CC_CISRDY (1 << 0) /* CIS Ready */
+#define CC_BPRESEN (1 << 1) /* CCCR RES signal causes backplane reset */
+#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */
+#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation bit (rev 11) */
+#define CC_XMTDATAAVAIL_MODE (1 << 4) /* data avail generates an interrupt */
+#define CC_XMTDATAAVAIL_CTRL (1 << 5) /* data avail interrupt ctrl */
+
+/* corestatus */
+#define CS_PCMCIAMODE (1 << 0) /* Device Mode; 0=SDIO, 1=PCMCIA */
+#define CS_SMARTDEV (1 << 1) /* 1=smartDev enabled */
+#define CS_F2ENABLED (1 << 2) /* 1=host has enabled the device */
+
+#define PCMCIA_MES_PA_MASK 0x7fff /* PCMCIA Message Portal Address Mask */
+#define PCMCIA_MES_PM_MASK 0x7fff /* PCMCIA Message Portal Mask Mask */
+#define PCMCIA_WFBC_MASK 0xffff /* PCMCIA Write Frame Byte Count Mask */
+#define PCMCIA_UT_MASK 0x07ff /* PCMCIA Underflow Timer Mask */
+
+/* intstatus */
+#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */
+#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */
+#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */
+#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */
+#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */
+#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */
+#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */
+#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */
+#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */
+#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */
+#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */
+#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */
+#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */
+#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */
+#define I_PC (1 << 10) /* descriptor error */
+#define I_PD (1 << 11) /* data error */
+#define I_DE (1 << 12) /* Descriptor protocol Error */
+#define I_RU (1 << 13) /* Receive descriptor Underflow */
+#define I_RO (1 << 14) /* Receive fifo Overflow */
+#define I_XU (1 << 15) /* Transmit fifo Underflow */
+#define I_RI (1 << 16) /* Receive Interrupt */
+#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */
+#define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */
+#define I_XI (1 << 24) /* Transmit Interrupt */
+#define I_RF_TERM (1 << 25) /* Read Frame Terminate */
+#define I_WF_TERM (1 << 26) /* Write Frame Terminate */
+#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */
+#define I_SBINT (1 << 28) /* sbintstatus Interrupt */
+#define I_CHIPACTIVE (1 << 29) /* chip transitioned from doze to active state */
+#define I_SRESET (1 << 30) /* CCCR RES interrupt */
+#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */
+#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) /* DMA Errors */
+#define I_DMA (I_RI | I_XI | I_ERRORS)
+
+/* sbintstatus */
+#define I_SB_SERR (1 << 8) /* Backplane SError (write) */
+#define I_SB_RESPERR (1 << 9) /* Backplane Response Error (read) */
+#define I_SB_SPROMERR (1 << 10) /* Error accessing the sprom */
+
+/* sdioaccess */
+#define SDA_DATA_MASK 0x000000ff /* Read/Write Data Mask */
+#define SDA_ADDR_MASK 0x000fff00 /* Read/Write Address Mask */
+#define SDA_ADDR_SHIFT 8 /* Read/Write Address Shift */
+#define SDA_WRITE 0x01000000 /* Write bit */
+#define SDA_READ 0x00000000 /* Write bit cleared for Read */
+#define SDA_BUSY 0x80000000 /* Busy bit */
+
+/* sdioaccess-accessible register address spaces */
+#define SDA_CCCR_SPACE 0x000 /* sdioAccess CCCR register space */
+#define SDA_F1_FBR_SPACE 0x100 /* sdioAccess F1 FBR register space */
+#define SDA_F2_FBR_SPACE 0x200 /* sdioAccess F2 FBR register space */
+#define SDA_F1_REG_SPACE 0x300 /* sdioAccess F1 core-specific register space */
+
+/* SDA_F1_REG_SPACE sdioaccess-accessible F1 reg space register offsets */
+#define SDA_CHIPCONTROLDATA 0x006 /* ChipControlData */
+#define SDA_CHIPCONTROLENAB 0x007 /* ChipControlEnable */
+#define SDA_F2WATERMARK 0x008 /* Function 2 Watermark */
+#define SDA_DEVICECONTROL 0x009 /* DeviceControl */
+#define SDA_SBADDRLOW 0x00a /* SbAddrLow */
+#define SDA_SBADDRMID 0x00b /* SbAddrMid */
+#define SDA_SBADDRHIGH 0x00c /* SbAddrHigh */
+#define SDA_FRAMECTRL 0x00d /* FrameCtrl */
+#define SDA_CHIPCLOCKCSR 0x00e /* ChipClockCSR */
+#define SDA_SDIOPULLUP 0x00f /* SdioPullUp */
+#define SDA_SDIOWRFRAMEBCLOW 0x019 /* SdioWrFrameBCLow */
+#define SDA_SDIOWRFRAMEBCHIGH 0x01a /* SdioWrFrameBCHigh */
+#define SDA_SDIORDFRAMEBCLOW 0x01b /* SdioRdFrameBCLow */
+#define SDA_SDIORDFRAMEBCHIGH 0x01c /* SdioRdFrameBCHigh */
+
+/* SDA_F2WATERMARK */
+#define SDA_F2WATERMARK_MASK 0x7f /* F2Watermark Mask */
+
+/* SDA_SBADDRLOW */
+#define SDA_SBADDRLOW_MASK 0x80 /* SbAddrLow Mask */
+
+/* SDA_SBADDRMID */
+#define SDA_SBADDRMID_MASK 0xff /* SbAddrMid Mask */
+
+/* SDA_SBADDRHIGH */
+#define SDA_SBADDRHIGH_MASK 0xff /* SbAddrHigh Mask */
+
+/* SDA_FRAMECTRL */
+#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */
+#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */
+#define SFC_CRC4WOOS (1 << 2) /* HW reports CRC error for write out of sync */
+#define SFC_ABORTALL (1 << 3) /* Abort cancels all in-progress frames */
+
+/* pcmciaframectrl */
+#define PFC_RF_TERM (1 << 0) /* Read Frame Terminate */
+#define PFC_WF_TERM (1 << 1) /* Write Frame Terminate */
+
+/* intrcvlazy */
+#define IRL_TO_MASK 0x00ffffff /* timeout */
+#define IRL_FC_MASK 0xff000000 /* frame count */
+#define IRL_FC_SHIFT 24 /* frame count */
+
+/* rx header */
+typedef volatile struct {
+ uint16 len;
+ uint16 flags;
+} sdpcmd_rxh_t;
+
+/* rx header flags */
+#define RXF_CRC 0x0001 /* CRC error detected */
+#define RXF_WOOS 0x0002 /* write frame out of sync */
+#define RXF_WF_TERM 0x0004 /* write frame terminated */
+#define RXF_ABORT 0x0008 /* write frame aborted */
+#define RXF_DISCARD (RXF_CRC | RXF_WOOS | RXF_WF_TERM | RXF_ABORT) /* bad frame */
+
+/* HW frame tag */
+#define SDPCM_FRAMETAG_LEN 4 /* HW frametag: 2 bytes len, 2 bytes check val */
+
+#define SDPCM_HWEXT_LEN 8
+
+#endif /* _sbsdpcmdev_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/sbsocram.h b/drivers/net/wireless/bcmdhd/include/sbsocram.h
new file mode 100644
index 000000000000..470307065f3d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sbsocram.h
@@ -0,0 +1,200 @@
+/*
+ * BCM47XX Sonics SiliconBackplane embedded ram core
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sbsocram.h 481592 2014-05-29 22:10:51Z $
+ */
+
+#ifndef _SBSOCRAM_H
+#define _SBSOCRAM_H
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define _PADLINE(line) pad ## line
+#define _XSTR(line) _PADLINE(line)
+#define PAD _XSTR(__LINE__)
+#endif /* PAD */
+
+/* Memcsocram core registers */
+typedef volatile struct sbsocramregs {
+ uint32 coreinfo;
+ uint32 bwalloc;
+ uint32 extracoreinfo;
+ uint32 biststat;
+ uint32 bankidx;
+ uint32 standbyctrl;
+
+ uint32 errlogstatus; /* rev 6 */
+ uint32 errlogaddr; /* rev 6 */
+ /* used for patching rev 3 & 5 */
+ uint32 cambankidx;
+ uint32 cambankstandbyctrl;
+ uint32 cambankpatchctrl;
+ uint32 cambankpatchtblbaseaddr;
+ uint32 cambankcmdreg;
+ uint32 cambankdatareg;
+ uint32 cambankmaskreg;
+ uint32 PAD[1];
+ uint32 bankinfo; /* corev 8 */
+ uint32 bankpda;
+ uint32 PAD[14];
+ uint32 extmemconfig;
+ uint32 extmemparitycsr;
+ uint32 extmemparityerrdata;
+ uint32 extmemparityerrcnt;
+ uint32 extmemwrctrlandsize;
+ uint32 PAD[84];
+ uint32 workaround;
+ uint32 pwrctl; /* corerev >= 2 */
+ uint32 PAD[133];
+ uint32 sr_control; /* corerev >= 15 */
+ uint32 sr_status; /* corerev >= 15 */
+ uint32 sr_address; /* corerev >= 15 */
+ uint32 sr_data; /* corerev >= 15 */
+} sbsocramregs_t;
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+/* Register offsets */
+#define SR_COREINFO 0x00
+#define SR_BWALLOC 0x04
+#define SR_BISTSTAT 0x0c
+#define SR_BANKINDEX 0x10
+#define SR_BANKSTBYCTL 0x14
+#define SR_PWRCTL 0x1e8
+
+/* Coreinfo register */
+#define SRCI_PT_MASK 0x00070000 /* corerev >= 6; port type[18:16] */
+#define SRCI_PT_SHIFT 16
+/* port types : SRCI_PT_<processorPT>_<backplanePT> */
+#define SRCI_PT_OCP_OCP 0
+#define SRCI_PT_AXI_OCP 1
+#define SRCI_PT_ARM7AHB_OCP 2
+#define SRCI_PT_CM3AHB_OCP 3
+#define SRCI_PT_AXI_AXI 4
+#define SRCI_PT_AHB_AXI 5
+/* corerev >= 3 */
+#define SRCI_LSS_MASK 0x00f00000
+#define SRCI_LSS_SHIFT 20
+#define SRCI_LRS_MASK 0x0f000000
+#define SRCI_LRS_SHIFT 24
+
+/* In corerev 0, the memory size is 2 to the power of the
+ * base plus 16 plus to the contents of the memsize field plus 1.
+ */
+#define SRCI_MS0_MASK 0xf
+#define SR_MS0_BASE 16
+
+/*
+ * In corerev 1 the bank size is 2 ^ the bank size field plus 14,
+ * the memory size is number of banks times bank size.
+ * The same applies to rom size.
+ */
+#define SRCI_ROMNB_MASK 0xf000
+#define SRCI_ROMNB_SHIFT 12
+#define SRCI_ROMBSZ_MASK 0xf00
+#define SRCI_ROMBSZ_SHIFT 8
+#define SRCI_SRNB_MASK 0xf0
+#define SRCI_SRNB_SHIFT 4
+#define SRCI_SRBSZ_MASK 0xf
+#define SRCI_SRBSZ_SHIFT 0
+
+#define SR_BSZ_BASE 14
+
+/* Standby control register */
+#define SRSC_SBYOVR_MASK 0x80000000
+#define SRSC_SBYOVR_SHIFT 31
+#define SRSC_SBYOVRVAL_MASK 0x60000000
+#define SRSC_SBYOVRVAL_SHIFT 29
+#define SRSC_SBYEN_MASK 0x01000000 /* rev >= 3 */
+#define SRSC_SBYEN_SHIFT 24
+
+/* Power control register */
+#define SRPC_PMU_STBYDIS_MASK 0x00000010 /* rev >= 3 */
+#define SRPC_PMU_STBYDIS_SHIFT 4
+#define SRPC_STBYOVRVAL_MASK 0x00000008
+#define SRPC_STBYOVRVAL_SHIFT 3
+#define SRPC_STBYOVR_MASK 0x00000007
+#define SRPC_STBYOVR_SHIFT 0
+
+/* Extra core capability register */
+#define SRECC_NUM_BANKS_MASK 0x000000F0
+#define SRECC_NUM_BANKS_SHIFT 4
+#define SRECC_BANKSIZE_MASK 0x0000000F
+#define SRECC_BANKSIZE_SHIFT 0
+
+#define SRECC_BANKSIZE(value) (1 << (value))
+
+/* CAM bank patch control */
+#define SRCBPC_PATCHENABLE 0x80000000
+
+#define SRP_ADDRESS 0x0001FFFC
+#define SRP_VALID 0x8000
+
+/* CAM bank command reg */
+#define SRCMD_WRITE 0x00020000
+#define SRCMD_READ 0x00010000
+#define SRCMD_DONE 0x80000000
+
+#define SRCMD_DONE_DLY 1000
+
+/* bankidx and bankinfo reg defines corerev >= 8 */
+#define SOCRAM_BANKINFO_SZMASK 0x7f
+#define SOCRAM_BANKIDX_ROM_MASK 0x100
+
+#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8
+/* socram bankinfo memtype */
+#define SOCRAM_MEMTYPE_RAM 0
+#define SOCRAM_MEMTYPE_R0M 1
+#define SOCRAM_MEMTYPE_DEVRAM 2
+
+#define SOCRAM_BANKINFO_REG 0x40
+#define SOCRAM_BANKIDX_REG 0x10
+#define SOCRAM_BANKINFO_STDBY_MASK 0x400
+#define SOCRAM_BANKINFO_STDBY_TIMER 0x800
+
+/* bankinfo rev >= 10 */
+#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT 13
+#define SOCRAM_BANKINFO_DEVRAMSEL_MASK 0x2000
+#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT 14
+#define SOCRAM_BANKINFO_DEVRAMPRO_MASK 0x4000
+#define SOCRAM_BANKINFO_SLPSUPP_SHIFT 15
+#define SOCRAM_BANKINFO_SLPSUPP_MASK 0x8000
+#define SOCRAM_BANKINFO_RETNTRAM_SHIFT 16
+#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000
+#define SOCRAM_BANKINFO_PDASZ_SHIFT 17
+#define SOCRAM_BANKINFO_PDASZ_MASK 0x003E0000
+#define SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT 24
+#define SOCRAM_BANKINFO_DEVRAMREMAP_MASK 0x01000000
+
+/* extracoreinfo register */
+#define SOCRAM_DEVRAMBANK_MASK 0xF000
+#define SOCRAM_DEVRAMBANK_SHIFT 12
+
+/* bank info to calculate bank size */
+#define SOCRAM_BANKINFO_SZBASE 8192
+#define SOCRAM_BANKSIZE_SHIFT 13 /* SOCRAM_BANKINFO_SZBASE */
+
+
+#endif /* _SBSOCRAM_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sdio.h b/drivers/net/wireless/bcmdhd/include/sdio.h
new file mode 100644
index 000000000000..2ada5ec5f67d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sdio.h
@@ -0,0 +1,619 @@
+/*
+ * SDIO spec header file
+ * Protocol and standard (common) device definitions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sdio.h 416730 2013-08-06 09:33:19Z $
+ */
+
+#ifndef _SDIO_H
+#define _SDIO_H
+
+
+/* CCCR structure for function 0 */
+typedef volatile struct {
+ uint8 cccr_sdio_rev; /* RO, cccr and sdio revision */
+ uint8 sd_rev; /* RO, sd spec revision */
+ uint8 io_en; /* I/O enable */
+ uint8 io_rdy; /* I/O ready reg */
+ uint8 intr_ctl; /* Master and per function interrupt enable control */
+ uint8 intr_status; /* RO, interrupt pending status */
+ uint8 io_abort; /* read/write abort or reset all functions */
+ uint8 bus_inter; /* bus interface control */
+ uint8 capability; /* RO, card capability */
+
+ uint8 cis_base_low; /* 0x9 RO, common CIS base address, LSB */
+ uint8 cis_base_mid;
+ uint8 cis_base_high; /* 0xB RO, common CIS base address, MSB */
+
+ /* suspend/resume registers */
+ uint8 bus_suspend; /* 0xC */
+ uint8 func_select; /* 0xD */
+ uint8 exec_flag; /* 0xE */
+ uint8 ready_flag; /* 0xF */
+
+ uint8 fn0_blk_size[2]; /* 0x10(LSB), 0x11(MSB) */
+
+ uint8 power_control; /* 0x12 (SDIO version 1.10) */
+
+ uint8 speed_control; /* 0x13 */
+} sdio_regs_t;
+
+/* SDIO Device CCCR offsets */
+#define SDIOD_CCCR_REV 0x00
+#define SDIOD_CCCR_SDREV 0x01
+#define SDIOD_CCCR_IOEN 0x02
+#define SDIOD_CCCR_IORDY 0x03
+#define SDIOD_CCCR_INTEN 0x04
+#define SDIOD_CCCR_INTPEND 0x05
+#define SDIOD_CCCR_IOABORT 0x06
+#define SDIOD_CCCR_BICTRL 0x07
+#define SDIOD_CCCR_CAPABLITIES 0x08
+#define SDIOD_CCCR_CISPTR_0 0x09
+#define SDIOD_CCCR_CISPTR_1 0x0A
+#define SDIOD_CCCR_CISPTR_2 0x0B
+#define SDIOD_CCCR_BUSSUSP 0x0C
+#define SDIOD_CCCR_FUNCSEL 0x0D
+#define SDIOD_CCCR_EXECFLAGS 0x0E
+#define SDIOD_CCCR_RDYFLAGS 0x0F
+#define SDIOD_CCCR_BLKSIZE_0 0x10
+#define SDIOD_CCCR_BLKSIZE_1 0x11
+#define SDIOD_CCCR_POWER_CONTROL 0x12
+#define SDIOD_CCCR_SPEED_CONTROL 0x13
+#define SDIOD_CCCR_UHSI_SUPPORT 0x14
+#define SDIOD_CCCR_DRIVER_STRENGTH 0x15
+#define SDIOD_CCCR_INTR_EXTN 0x16
+
+/* Broadcom extensions (corerev >= 1) */
+#define SDIOD_CCCR_BRCM_CARDCAP 0xf0
+#define SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
+#define SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
+#define SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
+#define SDIOD_CCCR_BRCM_CARDCTL 0xf1
+#define SDIOD_CCCR_BRCM_SEPINT 0xf2
+
+/* cccr_sdio_rev */
+#define SDIO_REV_SDIOID_MASK 0xf0 /* SDIO spec revision number */
+#define SDIO_REV_CCCRID_MASK 0x0f /* CCCR format version number */
+#define SDIO_SPEC_VERSION_3_0 0x40 /* SDIO spec version 3.0 */
+
+/* sd_rev */
+#define SD_REV_PHY_MASK 0x0f /* SD format version number */
+
+/* io_en */
+#define SDIO_FUNC_ENABLE_1 0x02 /* function 1 I/O enable */
+#define SDIO_FUNC_ENABLE_2 0x04 /* function 2 I/O enable */
+
+/* io_rdys */
+#define SDIO_FUNC_READY_1 0x02 /* function 1 I/O ready */
+#define SDIO_FUNC_READY_2 0x04 /* function 2 I/O ready */
+
+/* intr_ctl */
+#define INTR_CTL_MASTER_EN 0x1 /* interrupt enable master */
+#define INTR_CTL_FUNC1_EN 0x2 /* interrupt enable for function 1 */
+#define INTR_CTL_FUNC2_EN 0x4 /* interrupt enable for function 2 */
+
+/* intr_status */
+#define INTR_STATUS_FUNC1 0x2 /* interrupt pending for function 1 */
+#define INTR_STATUS_FUNC2 0x4 /* interrupt pending for function 2 */
+
+/* io_abort */
+#define IO_ABORT_RESET_ALL 0x08 /* I/O card reset */
+#define IO_ABORT_FUNC_MASK 0x07 /* abort selction: function x */
+
+/* bus_inter */
+#define BUS_CARD_DETECT_DIS 0x80 /* Card Detect disable */
+#define BUS_SPI_CONT_INTR_CAP 0x40 /* support continuous SPI interrupt */
+#define BUS_SPI_CONT_INTR_EN 0x20 /* continuous SPI interrupt enable */
+#define BUS_SD_DATA_WIDTH_MASK 0x03 /* bus width mask */
+#define BUS_SD_DATA_WIDTH_4BIT 0x02 /* bus width 4-bit mode */
+#define BUS_SD_DATA_WIDTH_1BIT 0x00 /* bus width 1-bit mode */
+
+/* capability */
+#define SDIO_CAP_4BLS 0x80 /* 4-bit support for low speed card */
+#define SDIO_CAP_LSC 0x40 /* low speed card */
+#define SDIO_CAP_E4MI 0x20 /* enable interrupt between block of data in 4-bit mode */
+#define SDIO_CAP_S4MI 0x10 /* support interrupt between block of data in 4-bit mode */
+#define SDIO_CAP_SBS 0x08 /* support suspend/resume */
+#define SDIO_CAP_SRW 0x04 /* support read wait */
+#define SDIO_CAP_SMB 0x02 /* support multi-block transfer */
+#define SDIO_CAP_SDC 0x01 /* Support Direct commands during multi-byte transfer */
+
+/* power_control */
+#define SDIO_POWER_SMPC 0x01 /* supports master power control (RO) */
+#define SDIO_POWER_EMPC 0x02 /* enable master power control (allow > 200mA) (RW) */
+
+/* speed_control (control device entry into high-speed clocking mode) */
+#define SDIO_SPEED_SHS 0x01 /* supports high-speed [clocking] mode (RO) */
+#define SDIO_SPEED_EHS 0x02 /* enable high-speed [clocking] mode (RW) */
+#define SDIO_SPEED_UHSI_DDR50 0x08
+
+/* for setting bus speed in card: 0x13h */
+#define SDIO_BUS_SPEED_UHSISEL_M BITFIELD_MASK(3)
+#define SDIO_BUS_SPEED_UHSISEL_S 1
+
+/* for getting bus speed cap in card: 0x14h */
+#define SDIO_BUS_SPEED_UHSICAP_M BITFIELD_MASK(3)
+#define SDIO_BUS_SPEED_UHSICAP_S 0
+
+/* for getting driver type CAP in card: 0x15h */
+#define SDIO_BUS_DRVR_TYPE_CAP_M BITFIELD_MASK(3)
+#define SDIO_BUS_DRVR_TYPE_CAP_S 0
+
+/* for setting driver type selection in card: 0x15h */
+#define SDIO_BUS_DRVR_TYPE_SEL_M BITFIELD_MASK(2)
+#define SDIO_BUS_DRVR_TYPE_SEL_S 4
+
+/* for getting async int support in card: 0x16h */
+#define SDIO_BUS_ASYNCINT_CAP_M BITFIELD_MASK(1)
+#define SDIO_BUS_ASYNCINT_CAP_S 0
+
+/* for setting async int selection in card: 0x16h */
+#define SDIO_BUS_ASYNCINT_SEL_M BITFIELD_MASK(1)
+#define SDIO_BUS_ASYNCINT_SEL_S 1
+
+/* brcm sepint */
+#define SDIO_SEPINT_MASK 0x01 /* route sdpcmdev intr onto separate pad (chip-specific) */
+#define SDIO_SEPINT_OE 0x02 /* 1 asserts output enable for above pad */
+#define SDIO_SEPINT_ACT_HI 0x04 /* use active high interrupt level instead of active low */
+
+/* FBR structure for function 1-7, FBR addresses and register offsets */
+typedef volatile struct {
+ uint8 devctr; /* device interface, CSA control */
+ uint8 ext_dev; /* extended standard I/O device type code */
+ uint8 pwr_sel; /* power selection support */
+ uint8 PAD[6]; /* reserved */
+
+ uint8 cis_low; /* CIS LSB */
+ uint8 cis_mid;
+ uint8 cis_high; /* CIS MSB */
+ uint8 csa_low; /* code storage area, LSB */
+ uint8 csa_mid;
+ uint8 csa_high; /* code storage area, MSB */
+ uint8 csa_dat_win; /* data access window to function */
+
+ uint8 fnx_blk_size[2]; /* block size, little endian */
+} sdio_fbr_t;
+
+/* Maximum number of I/O funcs */
+#define SDIOD_MAX_FUNCS 8
+#define SDIOD_MAX_IOFUNCS 7
+
+/* SDIO Device FBR Start Address */
+#define SDIOD_FBR_STARTADDR 0x100
+
+/* SDIO Device FBR Size */
+#define SDIOD_FBR_SIZE 0x100
+
+/* Macro to calculate FBR register base */
+#define SDIOD_FBR_BASE(n) ((n) * 0x100)
+
+/* Function register offsets */
+#define SDIOD_FBR_DEVCTR 0x00 /* basic info for function */
+#define SDIOD_FBR_EXT_DEV 0x01 /* extended I/O device code */
+#define SDIOD_FBR_PWR_SEL 0x02 /* power selection bits */
+
+/* SDIO Function CIS ptr offset */
+#define SDIOD_FBR_CISPTR_0 0x09
+#define SDIOD_FBR_CISPTR_1 0x0A
+#define SDIOD_FBR_CISPTR_2 0x0B
+
+/* Code Storage Area pointer */
+#define SDIOD_FBR_CSA_ADDR_0 0x0C
+#define SDIOD_FBR_CSA_ADDR_1 0x0D
+#define SDIOD_FBR_CSA_ADDR_2 0x0E
+#define SDIOD_FBR_CSA_DATA 0x0F
+
+/* SDIO Function I/O Block Size */
+#define SDIOD_FBR_BLKSIZE_0 0x10
+#define SDIOD_FBR_BLKSIZE_1 0x11
+
+/* devctr */
+#define SDIOD_FBR_DEVCTR_DIC 0x0f /* device interface code */
+#define SDIOD_FBR_DECVTR_CSA 0x40 /* CSA support flag */
+#define SDIOD_FBR_DEVCTR_CSA_EN 0x80 /* CSA enabled */
+/* interface codes */
+#define SDIOD_DIC_NONE 0 /* SDIO standard interface is not supported */
+#define SDIOD_DIC_UART 1
+#define SDIOD_DIC_BLUETOOTH_A 2
+#define SDIOD_DIC_BLUETOOTH_B 3
+#define SDIOD_DIC_GPS 4
+#define SDIOD_DIC_CAMERA 5
+#define SDIOD_DIC_PHS 6
+#define SDIOD_DIC_WLAN 7
+#define SDIOD_DIC_EXT 0xf /* extended device interface, read ext_dev register */
+
+/* pwr_sel */
+#define SDIOD_PWR_SEL_SPS 0x01 /* supports power selection */
+#define SDIOD_PWR_SEL_EPS 0x02 /* enable power selection (low-current mode) */
+
+/* misc defines */
+#define SDIO_FUNC_0 0
+#define SDIO_FUNC_1 1
+#define SDIO_FUNC_2 2
+#define SDIO_FUNC_3 3
+#define SDIO_FUNC_4 4
+#define SDIO_FUNC_5 5
+#define SDIO_FUNC_6 6
+#define SDIO_FUNC_7 7
+
+#define SD_CARD_TYPE_UNKNOWN 0 /* bad type or unrecognized */
+#define SD_CARD_TYPE_IO 1 /* IO only card */
+#define SD_CARD_TYPE_MEMORY 2 /* memory only card */
+#define SD_CARD_TYPE_COMBO 3 /* IO and memory combo card */
+
+#define SDIO_MAX_BLOCK_SIZE 2048 /* maximum block size for block mode operation */
+#define SDIO_MIN_BLOCK_SIZE 1 /* minimum block size for block mode operation */
+
+/* Card registers: status bit position */
+#define CARDREG_STATUS_BIT_OUTOFRANGE 31
+#define CARDREG_STATUS_BIT_COMCRCERROR 23
+#define CARDREG_STATUS_BIT_ILLEGALCOMMAND 22
+#define CARDREG_STATUS_BIT_ERROR 19
+#define CARDREG_STATUS_BIT_IOCURRENTSTATE3 12
+#define CARDREG_STATUS_BIT_IOCURRENTSTATE2 11
+#define CARDREG_STATUS_BIT_IOCURRENTSTATE1 10
+#define CARDREG_STATUS_BIT_IOCURRENTSTATE0 9
+#define CARDREG_STATUS_BIT_FUN_NUM_ERROR 4
+
+
+
+#define SD_CMD_GO_IDLE_STATE 0 /* mandatory for SDIO */
+#define SD_CMD_SEND_OPCOND 1
+#define SD_CMD_MMC_SET_RCA 3
+#define SD_CMD_IO_SEND_OP_COND 5 /* mandatory for SDIO */
+#define SD_CMD_SELECT_DESELECT_CARD 7
+#define SD_CMD_SEND_CSD 9
+#define SD_CMD_SEND_CID 10
+#define SD_CMD_STOP_TRANSMISSION 12
+#define SD_CMD_SEND_STATUS 13
+#define SD_CMD_GO_INACTIVE_STATE 15
+#define SD_CMD_SET_BLOCKLEN 16
+#define SD_CMD_READ_SINGLE_BLOCK 17
+#define SD_CMD_READ_MULTIPLE_BLOCK 18
+#define SD_CMD_WRITE_BLOCK 24
+#define SD_CMD_WRITE_MULTIPLE_BLOCK 25
+#define SD_CMD_PROGRAM_CSD 27
+#define SD_CMD_SET_WRITE_PROT 28
+#define SD_CMD_CLR_WRITE_PROT 29
+#define SD_CMD_SEND_WRITE_PROT 30
+#define SD_CMD_ERASE_WR_BLK_START 32
+#define SD_CMD_ERASE_WR_BLK_END 33
+#define SD_CMD_ERASE 38
+#define SD_CMD_LOCK_UNLOCK 42
+#define SD_CMD_IO_RW_DIRECT 52 /* mandatory for SDIO */
+#define SD_CMD_IO_RW_EXTENDED 53 /* mandatory for SDIO */
+#define SD_CMD_APP_CMD 55
+#define SD_CMD_GEN_CMD 56
+#define SD_CMD_READ_OCR 58
+#define SD_CMD_CRC_ON_OFF 59 /* mandatory for SDIO */
+#define SD_ACMD_SD_STATUS 13
+#define SD_ACMD_SEND_NUM_WR_BLOCKS 22
+#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT 23
+#define SD_ACMD_SD_SEND_OP_COND 41
+#define SD_ACMD_SET_CLR_CARD_DETECT 42
+#define SD_ACMD_SEND_SCR 51
+
+/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */
+#define SD_IO_OP_READ 0 /* Read_Write: Read */
+#define SD_IO_OP_WRITE 1 /* Read_Write: Write */
+#define SD_IO_RW_NORMAL 0 /* no RAW */
+#define SD_IO_RW_RAW 1 /* RAW */
+#define SD_IO_BYTE_MODE 0 /* Byte Mode */
+#define SD_IO_BLOCK_MODE 1 /* BlockMode */
+#define SD_IO_FIXED_ADDRESS 0 /* fix Address */
+#define SD_IO_INCREMENT_ADDRESS 1 /* IncrementAddress */
+
+/* build SD_CMD_IO_RW_DIRECT Argument */
+#define SDIO_IO_RW_DIRECT_ARG(rw, raw, func, addr, data) \
+ ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((raw) & 1) << 27) | \
+ (((addr) & 0x1FFFF) << 9) | ((data) & 0xFF))
+
+/* build SD_CMD_IO_RW_EXTENDED Argument */
+#define SDIO_IO_RW_EXTENDED_ARG(rw, blk, func, addr, inc_addr, count) \
+ ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((blk) & 1) << 27) | \
+ (((inc_addr) & 1) << 26) | (((addr) & 0x1FFFF) << 9) | ((count) & 0x1FF))
+
+/* SDIO response parameters */
+#define SD_RSP_NO_NONE 0
+#define SD_RSP_NO_1 1
+#define SD_RSP_NO_2 2
+#define SD_RSP_NO_3 3
+#define SD_RSP_NO_4 4
+#define SD_RSP_NO_5 5
+#define SD_RSP_NO_6 6
+
+ /* Modified R6 response (to CMD3) */
+#define SD_RSP_MR6_COM_CRC_ERROR 0x8000
+#define SD_RSP_MR6_ILLEGAL_COMMAND 0x4000
+#define SD_RSP_MR6_ERROR 0x2000
+
+ /* Modified R1 in R4 Response (to CMD5) */
+#define SD_RSP_MR1_SBIT 0x80
+#define SD_RSP_MR1_PARAMETER_ERROR 0x40
+#define SD_RSP_MR1_RFU5 0x20
+#define SD_RSP_MR1_FUNC_NUM_ERROR 0x10
+#define SD_RSP_MR1_COM_CRC_ERROR 0x08
+#define SD_RSP_MR1_ILLEGAL_COMMAND 0x04
+#define SD_RSP_MR1_RFU1 0x02
+#define SD_RSP_MR1_IDLE_STATE 0x01
+
+ /* R5 response (to CMD52 and CMD53) */
+#define SD_RSP_R5_COM_CRC_ERROR 0x80
+#define SD_RSP_R5_ILLEGAL_COMMAND 0x40
+#define SD_RSP_R5_IO_CURRENTSTATE1 0x20
+#define SD_RSP_R5_IO_CURRENTSTATE0 0x10
+#define SD_RSP_R5_ERROR 0x08
+#define SD_RSP_R5_RFU 0x04
+#define SD_RSP_R5_FUNC_NUM_ERROR 0x02
+#define SD_RSP_R5_OUT_OF_RANGE 0x01
+
+#define SD_RSP_R5_ERRBITS 0xCB
+
+
+/* ------------------------------------------------
+ * SDIO Commands and responses
+ *
+ * I/O only commands are:
+ * CMD0, CMD3, CMD5, CMD7, CMD14, CMD15, CMD52, CMD53
+ * ------------------------------------------------
+ */
+
+/* SDIO Commands */
+#define SDIOH_CMD_0 0
+#define SDIOH_CMD_3 3
+#define SDIOH_CMD_5 5
+#define SDIOH_CMD_7 7
+#define SDIOH_CMD_11 11
+#define SDIOH_CMD_14 14
+#define SDIOH_CMD_15 15
+#define SDIOH_CMD_19 19
+#define SDIOH_CMD_52 52
+#define SDIOH_CMD_53 53
+#define SDIOH_CMD_59 59
+
+/* SDIO Command Responses */
+#define SDIOH_RSP_NONE 0
+#define SDIOH_RSP_R1 1
+#define SDIOH_RSP_R2 2
+#define SDIOH_RSP_R3 3
+#define SDIOH_RSP_R4 4
+#define SDIOH_RSP_R5 5
+#define SDIOH_RSP_R6 6
+
+/*
+ * SDIO Response Error flags
+ */
+#define SDIOH_RSP5_ERROR_FLAGS 0xCB
+
+/* ------------------------------------------------
+ * SDIO Command structures. I/O only commands are:
+ *
+ * CMD0, CMD3, CMD5, CMD7, CMD15, CMD52, CMD53
+ * ------------------------------------------------
+ */
+
+#define CMD5_OCR_M BITFIELD_MASK(24)
+#define CMD5_OCR_S 0
+
+#define CMD5_S18R_M BITFIELD_MASK(1)
+#define CMD5_S18R_S 24
+
+#define CMD7_RCA_M BITFIELD_MASK(16)
+#define CMD7_RCA_S 16
+
+#define CMD14_RCA_M BITFIELD_MASK(16)
+#define CMD14_RCA_S 16
+#define CMD14_SLEEP_M BITFIELD_MASK(1)
+#define CMD14_SLEEP_S 15
+
+#define CMD_15_RCA_M BITFIELD_MASK(16)
+#define CMD_15_RCA_S 16
+
+#define CMD52_DATA_M BITFIELD_MASK(8) /* Bits [7:0] - Write Data/Stuff bits of CMD52
+ */
+#define CMD52_DATA_S 0
+#define CMD52_REG_ADDR_M BITFIELD_MASK(17) /* Bits [25:9] - register address */
+#define CMD52_REG_ADDR_S 9
+#define CMD52_RAW_M BITFIELD_MASK(1) /* Bit 27 - Read after Write flag */
+#define CMD52_RAW_S 27
+#define CMD52_FUNCTION_M BITFIELD_MASK(3) /* Bits [30:28] - Function number */
+#define CMD52_FUNCTION_S 28
+#define CMD52_RW_FLAG_M BITFIELD_MASK(1) /* Bit 31 - R/W flag */
+#define CMD52_RW_FLAG_S 31
+
+
+#define CMD53_BYTE_BLK_CNT_M BITFIELD_MASK(9) /* Bits [8:0] - Byte/Block Count of CMD53 */
+#define CMD53_BYTE_BLK_CNT_S 0
+#define CMD53_REG_ADDR_M BITFIELD_MASK(17) /* Bits [25:9] - register address */
+#define CMD53_REG_ADDR_S 9
+#define CMD53_OP_CODE_M BITFIELD_MASK(1) /* Bit 26 - R/W Operation Code */
+#define CMD53_OP_CODE_S 26
+#define CMD53_BLK_MODE_M BITFIELD_MASK(1) /* Bit 27 - Block Mode */
+#define CMD53_BLK_MODE_S 27
+#define CMD53_FUNCTION_M BITFIELD_MASK(3) /* Bits [30:28] - Function number */
+#define CMD53_FUNCTION_S 28
+#define CMD53_RW_FLAG_M BITFIELD_MASK(1) /* Bit 31 - R/W flag */
+#define CMD53_RW_FLAG_S 31
+
+/* ------------------------------------------------------
+ * SDIO Command Response structures for SD1 and SD4 modes
+ * -----------------------------------------------------
+ */
+#define RSP4_IO_OCR_M BITFIELD_MASK(24) /* Bits [23:0] - Card's OCR Bits [23:0] */
+#define RSP4_IO_OCR_S 0
+
+#define RSP4_S18A_M BITFIELD_MASK(1) /* Bits [23:0] - Card's OCR Bits [23:0] */
+#define RSP4_S18A_S 24
+
+#define RSP4_STUFF_M BITFIELD_MASK(3) /* Bits [26:24] - Stuff bits */
+#define RSP4_STUFF_S 24
+#define RSP4_MEM_PRESENT_M BITFIELD_MASK(1) /* Bit 27 - Memory present */
+#define RSP4_MEM_PRESENT_S 27
+#define RSP4_NUM_FUNCS_M BITFIELD_MASK(3) /* Bits [30:28] - Number of I/O funcs */
+#define RSP4_NUM_FUNCS_S 28
+#define RSP4_CARD_READY_M BITFIELD_MASK(1) /* Bit 31 - SDIO card ready */
+#define RSP4_CARD_READY_S 31
+
+#define RSP6_STATUS_M BITFIELD_MASK(16) /* Bits [15:0] - Card status bits [19,22,23,12:0]
+ */
+#define RSP6_STATUS_S 0
+#define RSP6_IO_RCA_M BITFIELD_MASK(16) /* Bits [31:16] - RCA bits[31-16] */
+#define RSP6_IO_RCA_S 16
+
+#define RSP1_AKE_SEQ_ERROR_M BITFIELD_MASK(1) /* Bit 3 - Authentication seq error */
+#define RSP1_AKE_SEQ_ERROR_S 3
+#define RSP1_APP_CMD_M BITFIELD_MASK(1) /* Bit 5 - Card expects ACMD */
+#define RSP1_APP_CMD_S 5
+#define RSP1_READY_FOR_DATA_M BITFIELD_MASK(1) /* Bit 8 - Ready for data (buff empty) */
+#define RSP1_READY_FOR_DATA_S 8
+#define RSP1_CURR_STATE_M BITFIELD_MASK(4) /* Bits [12:9] - State of card
+ * when Cmd was received
+ */
+#define RSP1_CURR_STATE_S 9
+#define RSP1_EARSE_RESET_M BITFIELD_MASK(1) /* Bit 13 - Erase seq cleared */
+#define RSP1_EARSE_RESET_S 13
+#define RSP1_CARD_ECC_DISABLE_M BITFIELD_MASK(1) /* Bit 14 - Card ECC disabled */
+#define RSP1_CARD_ECC_DISABLE_S 14
+#define RSP1_WP_ERASE_SKIP_M BITFIELD_MASK(1) /* Bit 15 - Partial blocks erased due to W/P */
+#define RSP1_WP_ERASE_SKIP_S 15
+#define RSP1_CID_CSD_OVERW_M BITFIELD_MASK(1) /* Bit 16 - Illegal write to CID or R/O bits
+ * of CSD
+ */
+#define RSP1_CID_CSD_OVERW_S 16
+#define RSP1_ERROR_M BITFIELD_MASK(1) /* Bit 19 - General/Unknown error */
+#define RSP1_ERROR_S 19
+#define RSP1_CC_ERROR_M BITFIELD_MASK(1) /* Bit 20 - Internal Card Control error */
+#define RSP1_CC_ERROR_S 20
+#define RSP1_CARD_ECC_FAILED_M BITFIELD_MASK(1) /* Bit 21 - Card internal ECC failed
+ * to correct data
+ */
+#define RSP1_CARD_ECC_FAILED_S 21
+#define RSP1_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 22 - Cmd not legal for the card state */
+#define RSP1_ILLEGAL_CMD_S 22
+#define RSP1_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 23 - CRC check of previous command failed
+ */
+#define RSP1_COM_CRC_ERROR_S 23
+#define RSP1_LOCK_UNLOCK_FAIL_M BITFIELD_MASK(1) /* Bit 24 - Card lock-unlock Cmd Seq error */
+#define RSP1_LOCK_UNLOCK_FAIL_S 24
+#define RSP1_CARD_LOCKED_M BITFIELD_MASK(1) /* Bit 25 - Card locked by the host */
+#define RSP1_CARD_LOCKED_S 25
+#define RSP1_WP_VIOLATION_M BITFIELD_MASK(1) /* Bit 26 - Attempt to program
+ * write-protected blocks
+ */
+#define RSP1_WP_VIOLATION_S 26
+#define RSP1_ERASE_PARAM_M BITFIELD_MASK(1) /* Bit 27 - Invalid erase blocks */
+#define RSP1_ERASE_PARAM_S 27
+#define RSP1_ERASE_SEQ_ERR_M BITFIELD_MASK(1) /* Bit 28 - Erase Cmd seq error */
+#define RSP1_ERASE_SEQ_ERR_S 28
+#define RSP1_BLK_LEN_ERR_M BITFIELD_MASK(1) /* Bit 29 - Block length error */
+#define RSP1_BLK_LEN_ERR_S 29
+#define RSP1_ADDR_ERR_M BITFIELD_MASK(1) /* Bit 30 - Misaligned address */
+#define RSP1_ADDR_ERR_S 30
+#define RSP1_OUT_OF_RANGE_M BITFIELD_MASK(1) /* Bit 31 - Cmd arg was out of range */
+#define RSP1_OUT_OF_RANGE_S 31
+
+
+#define RSP5_DATA_M BITFIELD_MASK(8) /* Bits [0:7] - data */
+#define RSP5_DATA_S 0
+#define RSP5_FLAGS_M BITFIELD_MASK(8) /* Bit [15:8] - Rsp flags */
+#define RSP5_FLAGS_S 8
+#define RSP5_STUFF_M BITFIELD_MASK(16) /* Bits [31:16] - Stuff bits */
+#define RSP5_STUFF_S 16
+
+/* ----------------------------------------------
+ * SDIO Command Response structures for SPI mode
+ * ----------------------------------------------
+ */
+#define SPIRSP4_IO_OCR_M BITFIELD_MASK(16) /* Bits [15:0] - Card's OCR Bits [23:8] */
+#define SPIRSP4_IO_OCR_S 0
+#define SPIRSP4_STUFF_M BITFIELD_MASK(3) /* Bits [18:16] - Stuff bits */
+#define SPIRSP4_STUFF_S 16
+#define SPIRSP4_MEM_PRESENT_M BITFIELD_MASK(1) /* Bit 19 - Memory present */
+#define SPIRSP4_MEM_PRESENT_S 19
+#define SPIRSP4_NUM_FUNCS_M BITFIELD_MASK(3) /* Bits [22:20] - Number of I/O funcs */
+#define SPIRSP4_NUM_FUNCS_S 20
+#define SPIRSP4_CARD_READY_M BITFIELD_MASK(1) /* Bit 23 - SDIO card ready */
+#define SPIRSP4_CARD_READY_S 23
+#define SPIRSP4_IDLE_STATE_M BITFIELD_MASK(1) /* Bit 24 - idle state */
+#define SPIRSP4_IDLE_STATE_S 24
+#define SPIRSP4_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 26 - Illegal Cmd error */
+#define SPIRSP4_ILLEGAL_CMD_S 26
+#define SPIRSP4_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 27 - COM CRC error */
+#define SPIRSP4_COM_CRC_ERROR_S 27
+#define SPIRSP4_FUNC_NUM_ERROR_M BITFIELD_MASK(1) /* Bit 28 - Function number error
+ */
+#define SPIRSP4_FUNC_NUM_ERROR_S 28
+#define SPIRSP4_PARAM_ERROR_M BITFIELD_MASK(1) /* Bit 30 - Parameter Error Bit */
+#define SPIRSP4_PARAM_ERROR_S 30
+#define SPIRSP4_START_BIT_M BITFIELD_MASK(1) /* Bit 31 - Start Bit */
+#define SPIRSP4_START_BIT_S 31
+
+#define SPIRSP5_DATA_M BITFIELD_MASK(8) /* Bits [23:16] - R/W Data */
+#define SPIRSP5_DATA_S 16
+#define SPIRSP5_IDLE_STATE_M BITFIELD_MASK(1) /* Bit 24 - Idle state */
+#define SPIRSP5_IDLE_STATE_S 24
+#define SPIRSP5_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 26 - Illegal Cmd error */
+#define SPIRSP5_ILLEGAL_CMD_S 26
+#define SPIRSP5_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 27 - COM CRC error */
+#define SPIRSP5_COM_CRC_ERROR_S 27
+#define SPIRSP5_FUNC_NUM_ERROR_M BITFIELD_MASK(1) /* Bit 28 - Function number error
+ */
+#define SPIRSP5_FUNC_NUM_ERROR_S 28
+#define SPIRSP5_PARAM_ERROR_M BITFIELD_MASK(1) /* Bit 30 - Parameter Error Bit */
+#define SPIRSP5_PARAM_ERROR_S 30
+#define SPIRSP5_START_BIT_M BITFIELD_MASK(1) /* Bit 31 - Start Bit */
+#define SPIRSP5_START_BIT_S 31
+
+/* RSP6 card status format; Pg 68 Physical Layer spec v 1.10 */
+#define RSP6STAT_AKE_SEQ_ERROR_M BITFIELD_MASK(1) /* Bit 3 - Authentication seq error
+ */
+#define RSP6STAT_AKE_SEQ_ERROR_S 3
+#define RSP6STAT_APP_CMD_M BITFIELD_MASK(1) /* Bit 5 - Card expects ACMD */
+#define RSP6STAT_APP_CMD_S 5
+#define RSP6STAT_READY_FOR_DATA_M BITFIELD_MASK(1) /* Bit 8 - Ready for data
+ * (buff empty)
+ */
+#define RSP6STAT_READY_FOR_DATA_S 8
+#define RSP6STAT_CURR_STATE_M BITFIELD_MASK(4) /* Bits [12:9] - Card state at
+ * Cmd reception
+ */
+#define RSP6STAT_CURR_STATE_S 9
+#define RSP6STAT_ERROR_M BITFIELD_MASK(1) /* Bit 13 - General/Unknown error Bit 19
+ */
+#define RSP6STAT_ERROR_S 13
+#define RSP6STAT_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 14 - Illegal cmd for
+ * card state Bit 22
+ */
+#define RSP6STAT_ILLEGAL_CMD_S 14
+#define RSP6STAT_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 15 - CRC previous command
+ * failed Bit 23
+ */
+#define RSP6STAT_COM_CRC_ERROR_S 15
+
+#define SDIOH_XFER_TYPE_READ SD_IO_OP_READ
+#define SDIOH_XFER_TYPE_WRITE SD_IO_OP_WRITE
+
+/* command issue options */
+#define CMD_OPTION_DEFAULT 0
+#define CMD_OPTION_TUNING 1
+#endif /* _SDIO_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sdioh.h b/drivers/net/wireless/bcmdhd/include/sdioh.h
new file mode 100644
index 000000000000..81d57d9efe2c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sdioh.h
@@ -0,0 +1,445 @@
+/*
+ * SDIO Host Controller Spec header file
+ * Register map and definitions for the Standard Host Controller
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sdioh.h 345499 2012-07-18 06:59:05Z $
+ */
+
+#ifndef _SDIOH_H
+#define _SDIOH_H
+
+#define SD_SysAddr 0x000
+#define SD_BlockSize 0x004
+#define SD_BlockCount 0x006
+#define SD_Arg0 0x008
+#define SD_Arg1 0x00A
+#define SD_TransferMode 0x00C
+#define SD_Command 0x00E
+#define SD_Response0 0x010
+#define SD_Response1 0x012
+#define SD_Response2 0x014
+#define SD_Response3 0x016
+#define SD_Response4 0x018
+#define SD_Response5 0x01A
+#define SD_Response6 0x01C
+#define SD_Response7 0x01E
+#define SD_BufferDataPort0 0x020
+#define SD_BufferDataPort1 0x022
+#define SD_PresentState 0x024
+#define SD_HostCntrl 0x028
+#define SD_PwrCntrl 0x029
+#define SD_BlockGapCntrl 0x02A
+#define SD_WakeupCntrl 0x02B
+#define SD_ClockCntrl 0x02C
+#define SD_TimeoutCntrl 0x02E
+#define SD_SoftwareReset 0x02F
+#define SD_IntrStatus 0x030
+#define SD_ErrorIntrStatus 0x032
+#define SD_IntrStatusEnable 0x034
+#define SD_ErrorIntrStatusEnable 0x036
+#define SD_IntrSignalEnable 0x038
+#define SD_ErrorIntrSignalEnable 0x03A
+#define SD_CMD12ErrorStatus 0x03C
+#define SD_Capabilities 0x040
+#define SD_Capabilities3 0x044
+#define SD_MaxCurCap 0x048
+#define SD_MaxCurCap_Reserved 0x04C
+#define SD_ADMA_ErrStatus 0x054
+#define SD_ADMA_SysAddr 0x58
+#define SD_SlotInterruptStatus 0x0FC
+#define SD_HostControllerVersion 0x0FE
+#define SD_GPIO_Reg 0x100
+#define SD_GPIO_OE 0x104
+#define SD_GPIO_Enable 0x108
+
+/* SD specific registers in PCI config space */
+#define SD_SlotInfo 0x40
+
+/* HC 3.0 specific registers and offsets */
+#define SD3_HostCntrl2 0x03E
+/* preset regsstart and count */
+#define SD3_PresetValStart 0x060
+#define SD3_PresetValCount 8
+/* preset-indiv regs */
+#define SD3_PresetVal_init 0x060
+#define SD3_PresetVal_default 0x062
+#define SD3_PresetVal_HS 0x064
+#define SD3_PresetVal_SDR12 0x066
+#define SD3_PresetVal_SDR25 0x068
+#define SD3_PresetVal_SDR50 0x06a
+#define SD3_PresetVal_SDR104 0x06c
+#define SD3_PresetVal_DDR50 0x06e
+/* SDIO3.0 Revx specific Registers */
+#define SD3_Tuning_Info_Register 0x0EC
+#define SD3_WL_BT_reset_register 0x0F0
+
+
+/* preset value indices */
+#define SD3_PRESETVAL_INITIAL_IX 0
+#define SD3_PRESETVAL_DESPEED_IX 1
+#define SD3_PRESETVAL_HISPEED_IX 2
+#define SD3_PRESETVAL_SDR12_IX 3
+#define SD3_PRESETVAL_SDR25_IX 4
+#define SD3_PRESETVAL_SDR50_IX 5
+#define SD3_PRESETVAL_SDR104_IX 6
+#define SD3_PRESETVAL_DDR50_IX 7
+
+/* SD_Capabilities reg (0x040) */
+#define CAP_TO_CLKFREQ_M BITFIELD_MASK(6)
+#define CAP_TO_CLKFREQ_S 0
+#define CAP_TO_CLKUNIT_M BITFIELD_MASK(1)
+#define CAP_TO_CLKUNIT_S 7
+/* Note: for sdio-2.0 case, this mask has to be 6 bits, but msb 2
+ bits are reserved. going ahead with 8 bits, as it is req for 3.0
+*/
+#define CAP_BASECLK_M BITFIELD_MASK(8)
+#define CAP_BASECLK_S 8
+#define CAP_MAXBLOCK_M BITFIELD_MASK(2)
+#define CAP_MAXBLOCK_S 16
+#define CAP_ADMA2_M BITFIELD_MASK(1)
+#define CAP_ADMA2_S 19
+#define CAP_ADMA1_M BITFIELD_MASK(1)
+#define CAP_ADMA1_S 20
+#define CAP_HIGHSPEED_M BITFIELD_MASK(1)
+#define CAP_HIGHSPEED_S 21
+#define CAP_DMA_M BITFIELD_MASK(1)
+#define CAP_DMA_S 22
+#define CAP_SUSPEND_M BITFIELD_MASK(1)
+#define CAP_SUSPEND_S 23
+#define CAP_VOLT_3_3_M BITFIELD_MASK(1)
+#define CAP_VOLT_3_3_S 24
+#define CAP_VOLT_3_0_M BITFIELD_MASK(1)
+#define CAP_VOLT_3_0_S 25
+#define CAP_VOLT_1_8_M BITFIELD_MASK(1)
+#define CAP_VOLT_1_8_S 26
+#define CAP_64BIT_HOST_M BITFIELD_MASK(1)
+#define CAP_64BIT_HOST_S 28
+
+#define SDIO_OCR_READ_FAIL (2)
+
+
+#define CAP_ASYNCINT_SUP_M BITFIELD_MASK(1)
+#define CAP_ASYNCINT_SUP_S 29
+
+#define CAP_SLOTTYPE_M BITFIELD_MASK(2)
+#define CAP_SLOTTYPE_S 30
+
+#define CAP3_MSBits_OFFSET (32)
+/* note: following are caps MSB32 bits.
+ So the bits start from 0, instead of 32. that is why
+ CAP3_MSBits_OFFSET is subtracted.
+*/
+#define CAP3_SDR50_SUP_M BITFIELD_MASK(1)
+#define CAP3_SDR50_SUP_S (32 - CAP3_MSBits_OFFSET)
+
+#define CAP3_SDR104_SUP_M BITFIELD_MASK(1)
+#define CAP3_SDR104_SUP_S (33 - CAP3_MSBits_OFFSET)
+
+#define CAP3_DDR50_SUP_M BITFIELD_MASK(1)
+#define CAP3_DDR50_SUP_S (34 - CAP3_MSBits_OFFSET)
+
+/* for knowing the clk caps in a single read */
+#define CAP3_30CLKCAP_M BITFIELD_MASK(3)
+#define CAP3_30CLKCAP_S (32 - CAP3_MSBits_OFFSET)
+
+#define CAP3_DRIVTYPE_A_M BITFIELD_MASK(1)
+#define CAP3_DRIVTYPE_A_S (36 - CAP3_MSBits_OFFSET)
+
+#define CAP3_DRIVTYPE_C_M BITFIELD_MASK(1)
+#define CAP3_DRIVTYPE_C_S (37 - CAP3_MSBits_OFFSET)
+
+#define CAP3_DRIVTYPE_D_M BITFIELD_MASK(1)
+#define CAP3_DRIVTYPE_D_S (38 - CAP3_MSBits_OFFSET)
+
+#define CAP3_RETUNING_TC_M BITFIELD_MASK(4)
+#define CAP3_RETUNING_TC_S (40 - CAP3_MSBits_OFFSET)
+
+#define CAP3_TUNING_SDR50_M BITFIELD_MASK(1)
+#define CAP3_TUNING_SDR50_S (45 - CAP3_MSBits_OFFSET)
+
+#define CAP3_RETUNING_MODES_M BITFIELD_MASK(2)
+#define CAP3_RETUNING_MODES_S (46 - CAP3_MSBits_OFFSET)
+
+#define CAP3_CLK_MULT_M BITFIELD_MASK(8)
+#define CAP3_CLK_MULT_S (48 - CAP3_MSBits_OFFSET)
+
+#define PRESET_DRIVR_SELECT_M BITFIELD_MASK(2)
+#define PRESET_DRIVR_SELECT_S 14
+
+#define PRESET_CLK_DIV_M BITFIELD_MASK(10)
+#define PRESET_CLK_DIV_S 0
+
+/* SD_MaxCurCap reg (0x048) */
+#define CAP_CURR_3_3_M BITFIELD_MASK(8)
+#define CAP_CURR_3_3_S 0
+#define CAP_CURR_3_0_M BITFIELD_MASK(8)
+#define CAP_CURR_3_0_S 8
+#define CAP_CURR_1_8_M BITFIELD_MASK(8)
+#define CAP_CURR_1_8_S 16
+
+/* SD_SysAddr: Offset 0x0000, Size 4 bytes */
+
+/* SD_BlockSize: Offset 0x004, Size 2 bytes */
+#define BLKSZ_BLKSZ_M BITFIELD_MASK(12)
+#define BLKSZ_BLKSZ_S 0
+#define BLKSZ_BNDRY_M BITFIELD_MASK(3)
+#define BLKSZ_BNDRY_S 12
+
+/* SD_BlockCount: Offset 0x006, size 2 bytes */
+
+/* SD_Arg0: Offset 0x008, size = 4 bytes */
+/* SD_TransferMode Offset 0x00C, size = 2 bytes */
+#define XFER_DMA_ENABLE_M BITFIELD_MASK(1)
+#define XFER_DMA_ENABLE_S 0
+#define XFER_BLK_COUNT_EN_M BITFIELD_MASK(1)
+#define XFER_BLK_COUNT_EN_S 1
+#define XFER_CMD_12_EN_M BITFIELD_MASK(1)
+#define XFER_CMD_12_EN_S 2
+#define XFER_DATA_DIRECTION_M BITFIELD_MASK(1)
+#define XFER_DATA_DIRECTION_S 4
+#define XFER_MULTI_BLOCK_M BITFIELD_MASK(1)
+#define XFER_MULTI_BLOCK_S 5
+
+/* SD_Command: Offset 0x00E, size = 2 bytes */
+/* resp_type field */
+#define RESP_TYPE_NONE 0
+#define RESP_TYPE_136 1
+#define RESP_TYPE_48 2
+#define RESP_TYPE_48_BUSY 3
+/* type field */
+#define CMD_TYPE_NORMAL 0
+#define CMD_TYPE_SUSPEND 1
+#define CMD_TYPE_RESUME 2
+#define CMD_TYPE_ABORT 3
+
+#define CMD_RESP_TYPE_M BITFIELD_MASK(2) /* Bits [0-1] - Response type */
+#define CMD_RESP_TYPE_S 0
+#define CMD_CRC_EN_M BITFIELD_MASK(1) /* Bit 3 - CRC enable */
+#define CMD_CRC_EN_S 3
+#define CMD_INDEX_EN_M BITFIELD_MASK(1) /* Bit 4 - Enable index checking */
+#define CMD_INDEX_EN_S 4
+#define CMD_DATA_EN_M BITFIELD_MASK(1) /* Bit 5 - Using DAT line */
+#define CMD_DATA_EN_S 5
+#define CMD_TYPE_M BITFIELD_MASK(2) /* Bit [6-7] - Normal, abort, resume, etc
+ */
+#define CMD_TYPE_S 6
+#define CMD_INDEX_M BITFIELD_MASK(6) /* Bits [8-13] - Command number */
+#define CMD_INDEX_S 8
+
+/* SD_BufferDataPort0 : Offset 0x020, size = 2 or 4 bytes */
+/* SD_BufferDataPort1 : Offset 0x022, size = 2 bytes */
+/* SD_PresentState : Offset 0x024, size = 4 bytes */
+#define PRES_CMD_INHIBIT_M BITFIELD_MASK(1) /* Bit 0 May use CMD */
+#define PRES_CMD_INHIBIT_S 0
+#define PRES_DAT_INHIBIT_M BITFIELD_MASK(1) /* Bit 1 May use DAT */
+#define PRES_DAT_INHIBIT_S 1
+#define PRES_DAT_BUSY_M BITFIELD_MASK(1) /* Bit 2 DAT is busy */
+#define PRES_DAT_BUSY_S 2
+#define PRES_PRESENT_RSVD_M BITFIELD_MASK(5) /* Bit [3-7] rsvd */
+#define PRES_PRESENT_RSVD_S 3
+#define PRES_WRITE_ACTIVE_M BITFIELD_MASK(1) /* Bit 8 Write is active */
+#define PRES_WRITE_ACTIVE_S 8
+#define PRES_READ_ACTIVE_M BITFIELD_MASK(1) /* Bit 9 Read is active */
+#define PRES_READ_ACTIVE_S 9
+#define PRES_WRITE_DATA_RDY_M BITFIELD_MASK(1) /* Bit 10 Write buf is avail */
+#define PRES_WRITE_DATA_RDY_S 10
+#define PRES_READ_DATA_RDY_M BITFIELD_MASK(1) /* Bit 11 Read buf data avail */
+#define PRES_READ_DATA_RDY_S 11
+#define PRES_CARD_PRESENT_M BITFIELD_MASK(1) /* Bit 16 Card present - debounced */
+#define PRES_CARD_PRESENT_S 16
+#define PRES_CARD_STABLE_M BITFIELD_MASK(1) /* Bit 17 Debugging */
+#define PRES_CARD_STABLE_S 17
+#define PRES_CARD_PRESENT_RAW_M BITFIELD_MASK(1) /* Bit 18 Not debounced */
+#define PRES_CARD_PRESENT_RAW_S 18
+#define PRES_WRITE_ENABLED_M BITFIELD_MASK(1) /* Bit 19 Write protected? */
+#define PRES_WRITE_ENABLED_S 19
+#define PRES_DAT_SIGNAL_M BITFIELD_MASK(4) /* Bit [20-23] Debugging */
+#define PRES_DAT_SIGNAL_S 20
+#define PRES_CMD_SIGNAL_M BITFIELD_MASK(1) /* Bit 24 Debugging */
+#define PRES_CMD_SIGNAL_S 24
+
+/* SD_HostCntrl: Offset 0x028, size = 1 bytes */
+#define HOST_LED_M BITFIELD_MASK(1) /* Bit 0 LED On/Off */
+#define HOST_LED_S 0
+#define HOST_DATA_WIDTH_M BITFIELD_MASK(1) /* Bit 1 4 bit enable */
+#define HOST_DATA_WIDTH_S 1
+#define HOST_HI_SPEED_EN_M BITFIELD_MASK(1) /* Bit 2 High speed vs low speed */
+#define HOST_DMA_SEL_S 3
+#define HOST_DMA_SEL_M BITFIELD_MASK(2) /* Bit 4:3 DMA Select */
+#define HOST_HI_SPEED_EN_S 2
+
+/* Host Control2: */
+#define HOSTCtrl2_PRESVAL_EN_M BITFIELD_MASK(1) /* 1 bit */
+#define HOSTCtrl2_PRESVAL_EN_S 15 /* bit# */
+
+#define HOSTCtrl2_ASYINT_EN_M BITFIELD_MASK(1) /* 1 bit */
+#define HOSTCtrl2_ASYINT_EN_S 14 /* bit# */
+
+#define HOSTCtrl2_SAMPCLK_SEL_M BITFIELD_MASK(1) /* 1 bit */
+#define HOSTCtrl2_SAMPCLK_SEL_S 7 /* bit# */
+
+#define HOSTCtrl2_EXEC_TUNING_M BITFIELD_MASK(1) /* 1 bit */
+#define HOSTCtrl2_EXEC_TUNING_S 6 /* bit# */
+
+#define HOSTCtrl2_DRIVSTRENGTH_SEL_M BITFIELD_MASK(2) /* 2 bit */
+#define HOSTCtrl2_DRIVSTRENGTH_SEL_S 4 /* bit# */
+
+#define HOSTCtrl2_1_8SIG_EN_M BITFIELD_MASK(1) /* 1 bit */
+#define HOSTCtrl2_1_8SIG_EN_S 3 /* bit# */
+
+#define HOSTCtrl2_UHSMODE_SEL_M BITFIELD_MASK(3) /* 3 bit */
+#define HOSTCtrl2_UHSMODE_SEL_S 0 /* bit# */
+
+#define HOST_CONTR_VER_2 (1)
+#define HOST_CONTR_VER_3 (2)
+
+/* misc defines */
+#define SD1_MODE 0x1 /* SD Host Cntrlr Spec */
+#define SD4_MODE 0x2 /* SD Host Cntrlr Spec */
+
+/* SD_PwrCntrl: Offset 0x029, size = 1 bytes */
+#define PWR_BUS_EN_M BITFIELD_MASK(1) /* Bit 0 Power the bus */
+#define PWR_BUS_EN_S 0
+#define PWR_VOLTS_M BITFIELD_MASK(3) /* Bit [1-3] Voltage Select */
+#define PWR_VOLTS_S 1
+
+/* SD_SoftwareReset: Offset 0x02F, size = 1 byte */
+#define SW_RESET_ALL_M BITFIELD_MASK(1) /* Bit 0 Reset All */
+#define SW_RESET_ALL_S 0
+#define SW_RESET_CMD_M BITFIELD_MASK(1) /* Bit 1 CMD Line Reset */
+#define SW_RESET_CMD_S 1
+#define SW_RESET_DAT_M BITFIELD_MASK(1) /* Bit 2 DAT Line Reset */
+#define SW_RESET_DAT_S 2
+
+/* SD_IntrStatus: Offset 0x030, size = 2 bytes */
+/* Defs also serve SD_IntrStatusEnable and SD_IntrSignalEnable */
+#define INTSTAT_CMD_COMPLETE_M BITFIELD_MASK(1) /* Bit 0 */
+#define INTSTAT_CMD_COMPLETE_S 0
+#define INTSTAT_XFER_COMPLETE_M BITFIELD_MASK(1)
+#define INTSTAT_XFER_COMPLETE_S 1
+#define INTSTAT_BLOCK_GAP_EVENT_M BITFIELD_MASK(1)
+#define INTSTAT_BLOCK_GAP_EVENT_S 2
+#define INTSTAT_DMA_INT_M BITFIELD_MASK(1)
+#define INTSTAT_DMA_INT_S 3
+#define INTSTAT_BUF_WRITE_READY_M BITFIELD_MASK(1)
+#define INTSTAT_BUF_WRITE_READY_S 4
+#define INTSTAT_BUF_READ_READY_M BITFIELD_MASK(1)
+#define INTSTAT_BUF_READ_READY_S 5
+#define INTSTAT_CARD_INSERTION_M BITFIELD_MASK(1)
+#define INTSTAT_CARD_INSERTION_S 6
+#define INTSTAT_CARD_REMOVAL_M BITFIELD_MASK(1)
+#define INTSTAT_CARD_REMOVAL_S 7
+#define INTSTAT_CARD_INT_M BITFIELD_MASK(1)
+#define INTSTAT_CARD_INT_S 8
+#define INTSTAT_RETUNING_INT_M BITFIELD_MASK(1) /* Bit 12 */
+#define INTSTAT_RETUNING_INT_S 12
+#define INTSTAT_ERROR_INT_M BITFIELD_MASK(1) /* Bit 15 */
+#define INTSTAT_ERROR_INT_S 15
+
+/* SD_ErrorIntrStatus: Offset 0x032, size = 2 bytes */
+/* Defs also serve SD_ErrorIntrStatusEnable and SD_ErrorIntrSignalEnable */
+#define ERRINT_CMD_TIMEOUT_M BITFIELD_MASK(1)
+#define ERRINT_CMD_TIMEOUT_S 0
+#define ERRINT_CMD_CRC_M BITFIELD_MASK(1)
+#define ERRINT_CMD_CRC_S 1
+#define ERRINT_CMD_ENDBIT_M BITFIELD_MASK(1)
+#define ERRINT_CMD_ENDBIT_S 2
+#define ERRINT_CMD_INDEX_M BITFIELD_MASK(1)
+#define ERRINT_CMD_INDEX_S 3
+#define ERRINT_DATA_TIMEOUT_M BITFIELD_MASK(1)
+#define ERRINT_DATA_TIMEOUT_S 4
+#define ERRINT_DATA_CRC_M BITFIELD_MASK(1)
+#define ERRINT_DATA_CRC_S 5
+#define ERRINT_DATA_ENDBIT_M BITFIELD_MASK(1)
+#define ERRINT_DATA_ENDBIT_S 6
+#define ERRINT_CURRENT_LIMIT_M BITFIELD_MASK(1)
+#define ERRINT_CURRENT_LIMIT_S 7
+#define ERRINT_AUTO_CMD12_M BITFIELD_MASK(1)
+#define ERRINT_AUTO_CMD12_S 8
+#define ERRINT_VENDOR_M BITFIELD_MASK(4)
+#define ERRINT_VENDOR_S 12
+#define ERRINT_ADMA_M BITFIELD_MASK(1)
+#define ERRINT_ADMA_S 9
+
+/* Also provide definitions in "normal" form to allow combined masks */
+#define ERRINT_CMD_TIMEOUT_BIT 0x0001
+#define ERRINT_CMD_CRC_BIT 0x0002
+#define ERRINT_CMD_ENDBIT_BIT 0x0004
+#define ERRINT_CMD_INDEX_BIT 0x0008
+#define ERRINT_DATA_TIMEOUT_BIT 0x0010
+#define ERRINT_DATA_CRC_BIT 0x0020
+#define ERRINT_DATA_ENDBIT_BIT 0x0040
+#define ERRINT_CURRENT_LIMIT_BIT 0x0080
+#define ERRINT_AUTO_CMD12_BIT 0x0100
+#define ERRINT_ADMA_BIT 0x0200
+
+/* Masks to select CMD vs. DATA errors */
+#define ERRINT_CMD_ERRS (ERRINT_CMD_TIMEOUT_BIT | ERRINT_CMD_CRC_BIT |\
+ ERRINT_CMD_ENDBIT_BIT | ERRINT_CMD_INDEX_BIT)
+#define ERRINT_DATA_ERRS (ERRINT_DATA_TIMEOUT_BIT | ERRINT_DATA_CRC_BIT |\
+ ERRINT_DATA_ENDBIT_BIT | ERRINT_ADMA_BIT)
+#define ERRINT_TRANSFER_ERRS (ERRINT_CMD_ERRS | ERRINT_DATA_ERRS)
+
+/* SD_WakeupCntr_BlockGapCntrl : Offset 0x02A , size = bytes */
+/* SD_ClockCntrl : Offset 0x02C , size = bytes */
+/* SD_SoftwareReset_TimeoutCntrl : Offset 0x02E , size = bytes */
+/* SD_IntrStatus : Offset 0x030 , size = bytes */
+/* SD_ErrorIntrStatus : Offset 0x032 , size = bytes */
+/* SD_IntrStatusEnable : Offset 0x034 , size = bytes */
+/* SD_ErrorIntrStatusEnable : Offset 0x036 , size = bytes */
+/* SD_IntrSignalEnable : Offset 0x038 , size = bytes */
+/* SD_ErrorIntrSignalEnable : Offset 0x03A , size = bytes */
+/* SD_CMD12ErrorStatus : Offset 0x03C , size = bytes */
+/* SD_Capabilities : Offset 0x040 , size = bytes */
+/* SD_MaxCurCap : Offset 0x048 , size = bytes */
+/* SD_MaxCurCap_Reserved: Offset 0x04C , size = bytes */
+/* SD_SlotInterruptStatus: Offset 0x0FC , size = bytes */
+/* SD_HostControllerVersion : Offset 0x0FE , size = bytes */
+
+/* SDIO Host Control Register DMA Mode Definitions */
+#define SDIOH_SDMA_MODE 0
+#define SDIOH_ADMA1_MODE 1
+#define SDIOH_ADMA2_MODE 2
+#define SDIOH_ADMA2_64_MODE 3
+
+#define ADMA2_ATTRIBUTE_VALID (1 << 0) /* ADMA Descriptor line valid */
+#define ADMA2_ATTRIBUTE_END (1 << 1) /* End of Descriptor */
+#define ADMA2_ATTRIBUTE_INT (1 << 2) /* Interrupt when line is done */
+#define ADMA2_ATTRIBUTE_ACT_NOP (0 << 4) /* Skip current line, go to next. */
+#define ADMA2_ATTRIBUTE_ACT_RSV (1 << 4) /* Same as NOP */
+#define ADMA1_ATTRIBUTE_ACT_SET (1 << 4) /* ADMA1 Only - set transfer length */
+#define ADMA2_ATTRIBUTE_ACT_TRAN (2 << 4) /* Transfer Data of one descriptor line. */
+#define ADMA2_ATTRIBUTE_ACT_LINK (3 << 4) /* Link Descriptor */
+
+/* ADMA2 Descriptor Table Entry for 32-bit Address */
+typedef struct adma2_dscr_32b {
+ uint32 len_attr;
+ uint32 phys_addr;
+} adma2_dscr_32b_t;
+
+/* ADMA1 Descriptor Table Entry */
+typedef struct adma1_dscr {
+ uint32 phys_addr_attr;
+} adma1_dscr_t;
+
+#endif /* _SDIOH_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sdiovar.h b/drivers/net/wireless/bcmdhd/include/sdiovar.h
new file mode 100644
index 000000000000..2abd48ec9b0f
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/sdiovar.h
@@ -0,0 +1,58 @@
+/*
+ * Structure used by apps whose drivers access SDIO drivers.
+ * Pulled out separately so dhdu and wlu can both use it.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sdiovar.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _sdiovar_h_
+#define _sdiovar_h_
+
+#include <typedefs.h>
+
+/* require default structure packing */
+#define BWL_DEFAULT_PACKING
+#include <packed_section_start.h>
+
+typedef struct sdreg {
+ int func;
+ int offset;
+ int value;
+} sdreg_t;
+
+/* Common msglevel constants */
+#define SDH_ERROR_VAL 0x0001 /* Error */
+#define SDH_TRACE_VAL 0x0002 /* Trace */
+#define SDH_INFO_VAL 0x0004 /* Info */
+#define SDH_DEBUG_VAL 0x0008 /* Debug */
+#define SDH_DATA_VAL 0x0010 /* Data */
+#define SDH_CTRL_VAL 0x0020 /* Control Regs */
+#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */
+#define SDH_DMA_VAL 0x0080 /* DMA */
+
+#define NUM_PREV_TRANSACTIONS 16
+
+
+#include <packed_section_end.h>
+
+#endif /* _sdiovar_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/siutils.h b/drivers/net/wireless/bcmdhd/include/siutils.h
new file mode 100644
index 000000000000..c6dae8970396
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/siutils.h
@@ -0,0 +1,440 @@
+/*
+ * Misc utility routines for accessing the SOC Interconnects
+ * of Broadcom HNBU chips.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: siutils.h 530682 2015-01-30 18:48:21Z $
+ */
+
+#ifndef _siutils_h_
+#define _siutils_h_
+
+
+#include <bcmutils.h>
+/*
+ * Data structure to export all chip specific common variables
+ * public (read-only) portion of siutils handle returned by si_attach()/si_kattach()
+ */
+struct si_pub {
+ uint socitype; /* SOCI_SB, SOCI_AI */
+
+ uint bustype; /* SI_BUS, PCI_BUS */
+ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
+ uint buscorerev; /* buscore rev */
+ uint buscoreidx; /* buscore index */
+ int ccrev; /* chip common core rev */
+ uint32 cccaps; /* chip common capabilities */
+ uint32 cccaps_ext; /* chip common capabilities extension */
+ int pmurev; /* pmu core rev */
+ uint32 pmucaps; /* pmu capabilities */
+ uint boardtype; /* board type */
+ uint boardrev; /* board rev */
+ uint boardvendor; /* board vendor */
+ uint boardflags; /* board flags */
+ uint boardflags2; /* board flags2 */
+ uint chip; /* chip number */
+ uint chiprev; /* chip revision */
+ uint chippkg; /* chip package option */
+ uint32 chipst; /* chip status */
+ bool issim; /* chip is in simulation or emulation */
+ uint socirev; /* SOC interconnect rev */
+ bool pci_pr32414;
+
+};
+
+/* for HIGH_ONLY driver, the si_t must be writable to allow states sync from BMAC to HIGH driver
+ * for monolithic driver, it is readonly to prevent accident change
+ */
+typedef const struct si_pub si_t;
+
+
+/*
+ * Many of the routines below take an 'sih' handle as their first arg.
+ * Allocate this by calling si_attach(). Free it by calling si_detach().
+ * At any one time, the sih is logically focused on one particular si core
+ * (the "current core").
+ * Use si_setcore() or si_setcoreidx() to change the association to another core.
+ */
+#define SI_OSH NULL /* Use for si_kattach when no osh is available */
+
+#define BADIDX (SI_MAXCORES + 1)
+
+/* clkctl xtal what flags */
+#define XTAL 0x1 /* primary crystal oscillator (2050) */
+#define PLL 0x2 /* main chip pll */
+
+/* clkctl clk mode */
+#define CLK_FAST 0 /* force fast (pll) clock */
+#define CLK_DYNAMIC 2 /* enable dynamic clock control */
+
+/* GPIO usage priorities */
+#define GPIO_DRV_PRIORITY 0 /* Driver */
+#define GPIO_APP_PRIORITY 1 /* Application */
+#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO reservation */
+
+/* GPIO pull up/down */
+#define GPIO_PULLUP 0
+#define GPIO_PULLDN 1
+
+/* GPIO event regtype */
+#define GPIO_REGEVT 0 /* GPIO register event */
+#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */
+#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */
+
+/* device path */
+#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */
+
+/* SI routine enumeration: to be used by update function with multiple hooks */
+#define SI_DOATTACH 1
+#define SI_PCIDOWN 2
+#define SI_PCIUP 3
+
+#define ISSIM_ENAB(sih) FALSE
+
+/* PMU clock/power control */
+#if defined(BCMPMUCTL)
+#define PMUCTL_ENAB(sih) (BCMPMUCTL)
+#else
+#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU)
+#endif
+
+/* chipcommon clock/power control (exclusive with PMU's) */
+#if defined(BCMPMUCTL) && BCMPMUCTL
+#define CCCTL_ENAB(sih) (0)
+#define CCPLL_ENAB(sih) (0)
+#else
+#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL)
+#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK)
+#endif
+
+typedef void (*gpio_handler_t)(uint32 stat, void *arg);
+typedef void (*gci_gpio_handler_t)(uint32 stat, void *arg);
+/* External BT Coex enable mask */
+#define CC_BTCOEX_EN_MASK 0x01
+/* External PA enable mask */
+#define GPIO_CTRL_EPA_EN_MASK 0x40
+/* WL/BT control enable mask */
+#define GPIO_CTRL_5_6_EN_MASK 0x60
+#define GPIO_CTRL_7_6_EN_MASK 0xC0
+#define GPIO_OUT_7_EN_MASK 0x80
+
+
+/* CR4 specific defines used by the host driver */
+#define SI_CR4_CAP (0x04)
+#define SI_CR4_BANKIDX (0x40)
+#define SI_CR4_BANKINFO (0x44)
+#define SI_CR4_BANKPDA (0x4C)
+
+#define ARMCR4_TCBBNB_MASK 0xf0
+#define ARMCR4_TCBBNB_SHIFT 4
+#define ARMCR4_TCBANB_MASK 0xf
+#define ARMCR4_TCBANB_SHIFT 0
+
+#define SICF_CPUHALT (0x0020)
+#define ARMCR4_BSZ_MASK 0x3f
+#define ARMCR4_BSZ_MULT 8192
+
+/* === exported functions === */
+extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype,
+ void *sdh, char **vars, uint *varsz);
+extern si_t *si_kattach(osl_t *osh);
+extern void si_detach(si_t *sih);
+extern bool si_pci_war16165(si_t *sih);
+
+extern uint si_corelist(si_t *sih, uint coreid[]);
+extern uint si_coreid(si_t *sih);
+extern uint si_flag(si_t *sih);
+extern uint si_flag_alt(si_t *sih);
+extern uint si_intflag(si_t *sih);
+extern uint si_coreidx(si_t *sih);
+extern uint si_coreunit(si_t *sih);
+extern uint si_corevendor(si_t *sih);
+extern uint si_corerev(si_t *sih);
+extern void *si_osh(si_t *sih);
+extern void si_setosh(si_t *sih, osl_t *osh);
+extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
+extern uint32 *si_corereg_addr(si_t *sih, uint coreidx, uint regoff);
+extern void *si_coreregs(si_t *sih);
+extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+extern uint si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val);
+extern void *si_wrapperregs(si_t *sih);
+extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val);
+extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val);
+extern bool si_iscoreup(si_t *sih);
+extern uint si_numcoreunits(si_t *sih, uint coreid);
+extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit);
+extern void *si_setcoreidx(si_t *sih, uint coreidx);
+extern void *si_setcore(si_t *sih, uint coreid, uint coreunit);
+extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val);
+extern void si_restore_core(si_t *sih, uint coreid, uint intr_val);
+extern int si_numaddrspaces(si_t *sih);
+extern uint32 si_addrspace(si_t *sih, uint asidx);
+extern uint32 si_addrspacesize(si_t *sih, uint asidx);
+extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size);
+extern int si_corebist(si_t *sih);
+extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
+extern void si_core_disable(si_t *sih, uint32 bits);
+extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m);
+extern uint si_chip_hostif(si_t *sih);
+extern bool si_read_pmu_autopll(si_t *sih);
+extern uint32 si_clock(si_t *sih);
+extern uint32 si_alp_clock(si_t *sih);
+extern uint32 si_ilp_clock(si_t *sih);
+extern void si_pci_setup(si_t *sih, uint coremask);
+extern void si_pcmcia_init(si_t *sih);
+extern void si_setint(si_t *sih, int siflag);
+extern bool si_backplane64(si_t *sih);
+extern void si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
+ void *intrsenabled_fn, void *intr_arg);
+extern void si_deregister_intr_callback(si_t *sih);
+extern void si_clkctl_init(si_t *sih);
+extern uint16 si_clkctl_fast_pwrup_delay(si_t *sih);
+extern bool si_clkctl_cc(si_t *sih, uint mode);
+extern int si_clkctl_xtal(si_t *sih, uint what, bool on);
+extern uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 val);
+extern void si_btcgpiowar(si_t *sih);
+extern bool si_deviceremoved(si_t *sih);
+extern uint32 si_socram_size(si_t *sih);
+extern uint32 si_socdevram_size(si_t *sih);
+extern uint32 si_socram_srmem_size(si_t *sih);
+extern void si_socram_set_bankpda(si_t *sih, uint32 bankidx, uint32 bankpda);
+extern void si_socdevram(si_t *sih, bool set, uint8 *ennable, uint8 *protect, uint8 *remap);
+extern bool si_socdevram_pkg(si_t *sih);
+extern bool si_socdevram_remap_isenb(si_t *sih);
+extern uint32 si_socdevram_remap_size(si_t *sih);
+
+extern void si_watchdog(si_t *sih, uint ticks);
+extern void si_watchdog_ms(si_t *sih, uint32 ms);
+extern uint32 si_watchdog_msticks(void);
+extern void *si_gpiosetcore(si_t *sih);
+extern uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioin(si_t *sih);
+extern uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_gpioreserve(si_t *sih, uint32 gpio_num, uint8 priority);
+extern uint32 si_gpiorelease(si_t *sih, uint32 gpio_num, uint8 priority);
+extern uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val);
+extern uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val);
+extern uint32 si_gpio_int_enable(si_t *sih, bool enable);
+extern void si_gci_enable_gpio(si_t *sih, uint8 gpio, uint32 mask, uint32 value);
+extern uint8 si_gci_host_wake_gpio_init(si_t *sih);
+extern void si_gci_host_wake_gpio_enable(si_t *sih, uint8 gpio, bool state);
+
+/* GPIO event handlers */
+extern void *si_gpio_handler_register(si_t *sih, uint32 e, bool lev, gpio_handler_t cb, void *arg);
+extern void si_gpio_handler_unregister(si_t *sih, void* gpioh);
+extern void si_gpio_handler_process(si_t *sih);
+
+/* GCI interrupt handlers */
+extern void si_gci_handler_process(si_t *sih);
+
+/* GCI GPIO event handlers */
+extern void *si_gci_gpioint_handler_register(si_t *sih, uint8 gpio, uint8 sts,
+ gci_gpio_handler_t cb, void *arg);
+extern void si_gci_gpioint_handler_unregister(si_t *sih, void* gci_i);
+
+/* Wake-on-wireless-LAN (WOWL) */
+extern bool si_pci_pmecap(si_t *sih);
+struct osl_info;
+extern bool si_pci_fastpmecap(struct osl_info *osh);
+extern bool si_pci_pmestat(si_t *sih);
+extern void si_pci_pmeclr(si_t *sih);
+extern void si_pci_pmeen(si_t *sih);
+extern void si_pci_pmestatclr(si_t *sih);
+extern uint si_pcie_readreg(void *sih, uint addrtype, uint offset);
+extern uint si_pcie_writereg(void *sih, uint addrtype, uint offset, uint val);
+
+
+extern void si_sdio_init(si_t *sih);
+
+extern uint16 si_d11_devid(si_t *sih);
+extern int si_corepciid(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
+ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, uint8 *pciheader);
+
+#define si_eci(sih) 0
+static INLINE void * si_eci_init(si_t *sih) {return NULL;}
+#define si_eci_notify_bt(sih, type, val) (0)
+#define si_seci(sih) 0
+#define si_seci_upd(sih, a) do {} while (0)
+static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;}
+static INLINE void * si_gci_init(si_t *sih) {return NULL;}
+#define si_seci_down(sih) do {} while (0)
+#define si_gci(sih) 0
+
+/* OTP status */
+extern bool si_is_otp_disabled(si_t *sih);
+extern bool si_is_otp_powered(si_t *sih);
+extern void si_otp_power(si_t *sih, bool on, uint32* min_res_mask);
+
+/* SPROM availability */
+extern bool si_is_sprom_available(si_t *sih);
+extern bool si_is_sprom_enabled(si_t *sih);
+extern void si_sprom_enable(si_t *sih, bool enable);
+
+/* OTP/SROM CIS stuff */
+extern int si_cis_source(si_t *sih);
+#define CIS_DEFAULT 0
+#define CIS_SROM 1
+#define CIS_OTP 2
+
+/* Fab-id information */
+#define DEFAULT_FAB 0x0 /* Original/first fab used for this chip */
+#define CSM_FAB7 0x1 /* CSM Fab7 chip */
+#define TSMC_FAB12 0x2 /* TSMC Fab12/Fab14 chip */
+#define SMIC_FAB4 0x3 /* SMIC Fab4 chip */
+
+extern int si_otp_fabid(si_t *sih, uint16 *fabid, bool rw);
+extern uint16 si_fabid(si_t *sih);
+
+/*
+ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ.
+ * The returned path is NULL terminated and has trailing '/'.
+ * Return 0 on success, nonzero otherwise.
+ */
+extern int si_devpath(si_t *sih, char *path, int size);
+/* Read variable with prepending the devpath to the name */
+extern char *si_getdevpathvar(si_t *sih, const char *name);
+extern int si_getdevpathintvar(si_t *sih, const char *name);
+extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name);
+
+
+extern uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val);
+extern uint8 si_pcieltrenable(si_t *sih, uint32 mask, uint32 val);
+extern uint8 si_pcieobffenable(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcieltr_reg(si_t *sih, uint32 reg, uint32 mask, uint32 val);
+extern uint32 si_pcieltrspacing_reg(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcieltrhysteresiscnt_reg(si_t *sih, uint32 mask, uint32 val);
+extern void si_pcie_set_error_injection(si_t *sih, uint32 mode);
+extern void si_pcie_set_L1substate(si_t *sih, uint32 substate);
+extern uint32 si_pcie_get_L1substate(si_t *sih);
+extern void si_war42780_clkreq(si_t *sih, bool clkreq);
+extern void si_pci_down(si_t *sih);
+extern void si_pci_up(si_t *sih);
+extern void si_pci_sleep(si_t *sih);
+extern void si_pcie_war_ovr_update(si_t *sih, uint8 aspm);
+extern void si_pcie_power_save_enable(si_t *sih, bool enable);
+extern void si_pcie_extendL1timer(si_t *sih, bool extend);
+extern int si_pci_fixcfg(si_t *sih);
+extern void si_chippkg_set(si_t *sih, uint);
+
+extern void si_chipcontrl_btshd0_4331(si_t *sih, bool on);
+extern void si_chipcontrl_restore(si_t *sih, uint32 val);
+extern uint32 si_chipcontrl_read(si_t *sih);
+extern void si_chipcontrl_epa4331(si_t *sih, bool on);
+extern void si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl);
+extern void si_chipcontrl_srom4360(si_t *sih, bool on);
+/* Enable BT-COEX & Ex-PA for 4313 */
+extern void si_epa_4313war(si_t *sih);
+extern void si_btc_enable_chipcontrol(si_t *sih);
+/* BT/WL selection for 4313 bt combo >= P250 boards */
+extern void si_btcombo_p250_4313_war(si_t *sih);
+extern void si_btcombo_43228_war(si_t *sih);
+extern void si_clk_pmu_htavail_set(si_t *sih, bool set_clear);
+extern void si_pmu_synth_pwrsw_4313_war(si_t *sih);
+extern uint si_pll_reset(si_t *sih);
+/* === debug routines === */
+
+extern bool si_taclear(si_t *sih, bool details);
+
+
+
+extern uint32 si_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+extern uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type);
+extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val);
+extern void si_pcie_set_request_size(si_t *sih, uint16 size);
+extern uint16 si_pcie_get_request_size(si_t *sih);
+extern void si_pcie_set_maxpayload_size(si_t *sih, uint16 size);
+extern uint16 si_pcie_get_maxpayload_size(si_t *sih);
+extern uint16 si_pcie_get_ssid(si_t *sih);
+extern uint32 si_pcie_get_bar0(si_t *sih);
+extern int si_pcie_configspace_cache(si_t *sih);
+extern int si_pcie_configspace_restore(si_t *sih);
+extern int si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size);
+
+char *si_getnvramflvar(si_t *sih, const char *name);
+
+
+extern uint32 si_tcm_size(si_t *sih);
+extern bool si_has_flops(si_t *sih);
+
+extern int si_set_sromctl(si_t *sih, uint32 value);
+extern uint32 si_get_sromctl(si_t *sih);
+
+extern uint32 si_gci_direct(si_t *sih, uint offset, uint32 mask, uint32 val);
+extern uint32 si_gci_indirect(si_t *sih, uint regidx, uint offset, uint32 mask, uint32 val);
+extern uint32 si_gci_output(si_t *sih, uint reg, uint32 mask, uint32 val);
+extern uint32 si_gci_input(si_t *sih, uint reg);
+extern uint32 si_gci_int_enable(si_t *sih, bool enable);
+extern void si_gci_reset(si_t *sih);
+extern void si_ercx_init(si_t *sih);
+extern void si_wci2_init(si_t *sih, uint baudrate);
+extern void si_gci_seci_init(si_t *sih);
+extern void si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel);
+extern uint8 si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos);
+extern uint32 si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val);
+extern uint32 si_gci_chipstatus(si_t *sih, uint reg);
+extern uint16 si_cc_get_reg16(uint32 reg_offs);
+extern uint32 si_cc_get_reg32(uint32 reg_offs);
+extern uint32 si_cc_set_reg32(uint32 reg_offs, uint32 val);
+extern uint32 si_gci_preinit_upd_indirect(uint32 regidx, uint32 setval, uint32 mask);
+extern uint8 si_enable_device_wake(si_t *sih, uint8 *wake_status, uint8 *cur_status);
+
+#define CHIPCTRLREG1 0x1
+#define CHIPCTRLREG2 0x2
+#define CHIPCTRLREG3 0x3
+#define CHIPCTRLREG4 0x4
+#define CHIPCTRLREG5 0x5
+#define MINRESMASKREG 0x618
+#define MAXRESMASKREG 0x61c
+#define CHIPCTRLADDR 0x650
+#define CHIPCTRLDATA 0x654
+#define RSRCTABLEADDR 0x620
+#define RSRCUPDWNTIME 0x628
+#define PMUREG_RESREQ_MASK 0x68c
+
+void si_update_masks(si_t *sih);
+void si_force_islanding(si_t *sih, bool enable);
+extern uint32 si_pmu_res_req_timer_clr(si_t *sih);
+extern void si_pmu_rfldo(si_t *sih, bool on);
+extern void si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 spert_val);
+extern void si_pcie_ltr_war(si_t *sih);
+
+/* Macro to enable clock gating changes in different cores */
+#define MEM_CLK_GATE_BIT 5
+#define GCI_CLK_GATE_BIT 18
+
+#define USBAPP_CLK_BIT 0
+#define PCIE_CLK_BIT 3
+#define ARMCR4_DBG_CLK_BIT 4
+#define SAMPLE_SYNC_CLK_BIT 17
+#define PCIE_TL_CLK_BIT 18
+#define HQ_REQ_BIT 24
+#define PLL_DIV2_BIT_START 9
+#define PLL_DIV2_MASK (0x37 << PLL_DIV2_BIT_START)
+#define PLL_DIV2_DIS_OP (0x37 << PLL_DIV2_BIT_START)
+
+#endif /* _siutils_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/spid.h b/drivers/net/wireless/bcmdhd/include/spid.h
new file mode 100644
index 000000000000..fb5536f8a184
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/spid.h
@@ -0,0 +1,165 @@
+/*
+ * SPI device spec header file
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: spid.h 358377 2012-09-23 11:30:22Z $
+ */
+
+#ifndef _SPI_H
+#define _SPI_H
+
+/*
+ * Brcm SPI Device Register Map.
+ *
+ */
+
+typedef volatile struct {
+ uint8 config; /* 0x00, len, endian, clock, speed, polarity, wakeup */
+ uint8 response_delay; /* 0x01, read response delay in bytes (corerev < 3) */
+ uint8 status_enable; /* 0x02, status-enable, intr with status, response_delay
+ * function selection, command/data error check
+ */
+ uint8 reset_bp; /* 0x03, reset on wlan/bt backplane reset (corerev >= 1) */
+ uint16 intr_reg; /* 0x04, Intr status register */
+ uint16 intr_en_reg; /* 0x06, Intr mask register */
+ uint32 status_reg; /* 0x08, RO, Status bits of last spi transfer */
+ uint16 f1_info_reg; /* 0x0c, RO, enabled, ready for data transfer, blocksize */
+ uint16 f2_info_reg; /* 0x0e, RO, enabled, ready for data transfer, blocksize */
+ uint16 f3_info_reg; /* 0x10, RO, enabled, ready for data transfer, blocksize */
+ uint32 test_read; /* 0x14, RO 0xfeedbead signature */
+ uint32 test_rw; /* 0x18, RW */
+ uint8 resp_delay_f0; /* 0x1c, read resp delay bytes for F0 (corerev >= 3) */
+ uint8 resp_delay_f1; /* 0x1d, read resp delay bytes for F1 (corerev >= 3) */
+ uint8 resp_delay_f2; /* 0x1e, read resp delay bytes for F2 (corerev >= 3) */
+ uint8 resp_delay_f3; /* 0x1f, read resp delay bytes for F3 (corerev >= 3) */
+} spi_regs_t;
+
+/* SPI device register offsets */
+#define SPID_CONFIG 0x00
+#define SPID_RESPONSE_DELAY 0x01
+#define SPID_STATUS_ENABLE 0x02
+#define SPID_RESET_BP 0x03 /* (corerev >= 1) */
+#define SPID_INTR_REG 0x04 /* 16 bits - Interrupt status */
+#define SPID_INTR_EN_REG 0x06 /* 16 bits - Interrupt mask */
+#define SPID_STATUS_REG 0x08 /* 32 bits */
+#define SPID_F1_INFO_REG 0x0C /* 16 bits */
+#define SPID_F2_INFO_REG 0x0E /* 16 bits */
+#define SPID_F3_INFO_REG 0x10 /* 16 bits */
+#define SPID_TEST_READ 0x14 /* 32 bits */
+#define SPID_TEST_RW 0x18 /* 32 bits */
+#define SPID_RESP_DELAY_F0 0x1c /* 8 bits (corerev >= 3) */
+#define SPID_RESP_DELAY_F1 0x1d /* 8 bits (corerev >= 3) */
+#define SPID_RESP_DELAY_F2 0x1e /* 8 bits (corerev >= 3) */
+#define SPID_RESP_DELAY_F3 0x1f /* 8 bits (corerev >= 3) */
+
+/* Bit masks for SPID_CONFIG device register */
+#define WORD_LENGTH_32 0x1 /* 0/1 16/32 bit word length */
+#define ENDIAN_BIG 0x2 /* 0/1 Little/Big Endian */
+#define CLOCK_PHASE 0x4 /* 0/1 clock phase delay */
+#define CLOCK_POLARITY 0x8 /* 0/1 Idle state clock polarity is low/high */
+#define HIGH_SPEED_MODE 0x10 /* 1/0 High Speed mode / Normal mode */
+#define INTR_POLARITY 0x20 /* 1/0 Interrupt active polarity is high/low */
+#define WAKE_UP 0x80 /* 0/1 Wake-up command from Host to WLAN */
+
+/* Bit mask for SPID_RESPONSE_DELAY device register */
+#define RESPONSE_DELAY_MASK 0xFF /* Configurable rd response delay in multiples of 8 bits */
+
+/* Bit mask for SPID_STATUS_ENABLE device register */
+#define STATUS_ENABLE 0x1 /* 1/0 Status sent/not sent to host after read/write */
+#define INTR_WITH_STATUS 0x2 /* 0/1 Do-not / do-interrupt if status is sent */
+#define RESP_DELAY_ALL 0x4 /* Applicability of resp delay to F1 or all func's read */
+#define DWORD_PKT_LEN_EN 0x8 /* Packet len denoted in dwords instead of bytes */
+#define CMD_ERR_CHK_EN 0x20 /* Command error check enable */
+#define DATA_ERR_CHK_EN 0x40 /* Data error check enable */
+
+/* Bit mask for SPID_RESET_BP device register */
+#define RESET_ON_WLAN_BP_RESET 0x4 /* enable reset for WLAN backplane */
+#define RESET_ON_BT_BP_RESET 0x8 /* enable reset for BT backplane */
+#define RESET_SPI 0x80 /* reset the above enabled logic */
+
+/* Bit mask for SPID_INTR_REG device register */
+#define DATA_UNAVAILABLE 0x0001 /* Requested data not available; Clear by writing a "1" */
+#define F2_F3_FIFO_RD_UNDERFLOW 0x0002
+#define F2_F3_FIFO_WR_OVERFLOW 0x0004
+#define COMMAND_ERROR 0x0008 /* Cleared by writing 1 */
+#define DATA_ERROR 0x0010 /* Cleared by writing 1 */
+#define F2_PACKET_AVAILABLE 0x0020
+#define F3_PACKET_AVAILABLE 0x0040
+#define F1_OVERFLOW 0x0080 /* Due to last write. Bkplane has pending write requests */
+#define MISC_INTR0 0x0100
+#define MISC_INTR1 0x0200
+#define MISC_INTR2 0x0400
+#define MISC_INTR3 0x0800
+#define MISC_INTR4 0x1000
+#define F1_INTR 0x2000
+#define F2_INTR 0x4000
+#define F3_INTR 0x8000
+
+/* Bit mask for 32bit SPID_STATUS_REG device register */
+#define STATUS_DATA_NOT_AVAILABLE 0x00000001
+#define STATUS_UNDERFLOW 0x00000002
+#define STATUS_OVERFLOW 0x00000004
+#define STATUS_F2_INTR 0x00000008
+#define STATUS_F3_INTR 0x00000010
+#define STATUS_F2_RX_READY 0x00000020
+#define STATUS_F3_RX_READY 0x00000040
+#define STATUS_HOST_CMD_DATA_ERR 0x00000080
+#define STATUS_F2_PKT_AVAILABLE 0x00000100
+#define STATUS_F2_PKT_LEN_MASK 0x000FFE00
+#define STATUS_F2_PKT_LEN_SHIFT 9
+#define STATUS_F3_PKT_AVAILABLE 0x00100000
+#define STATUS_F3_PKT_LEN_MASK 0xFFE00000
+#define STATUS_F3_PKT_LEN_SHIFT 21
+
+/* Bit mask for 16 bits SPID_F1_INFO_REG device register */
+#define F1_ENABLED 0x0001
+#define F1_RDY_FOR_DATA_TRANSFER 0x0002
+#define F1_MAX_PKT_SIZE 0x01FC
+
+/* Bit mask for 16 bits SPID_F2_INFO_REG device register */
+#define F2_ENABLED 0x0001
+#define F2_RDY_FOR_DATA_TRANSFER 0x0002
+#define F2_MAX_PKT_SIZE 0x3FFC
+
+/* Bit mask for 16 bits SPID_F3_INFO_REG device register */
+#define F3_ENABLED 0x0001
+#define F3_RDY_FOR_DATA_TRANSFER 0x0002
+#define F3_MAX_PKT_SIZE 0x3FFC
+
+/* Bit mask for 32 bits SPID_TEST_READ device register read in 16bit LE mode */
+#define TEST_RO_DATA_32BIT_LE 0xFEEDBEAD
+
+/* Maximum number of I/O funcs */
+#define SPI_MAX_IOFUNCS 4
+
+#define SPI_MAX_PKT_LEN (2048*4)
+
+/* Misc defines */
+#define SPI_FUNC_0 0
+#define SPI_FUNC_1 1
+#define SPI_FUNC_2 2
+#define SPI_FUNC_3 3
+
+#define WAIT_F2RXFIFORDY 100
+#define WAIT_F2RXFIFORDY_DELAY 20
+
+#endif /* _SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/trxhdr.h b/drivers/net/wireless/bcmdhd/include/trxhdr.h
new file mode 100644
index 000000000000..08010cec69ad
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/trxhdr.h
@@ -0,0 +1,92 @@
+/*
+ * TRX image file header format.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: trxhdr.h 349211 2012-08-07 09:45:24Z $
+ */
+
+#ifndef _TRX_HDR_H
+#define _TRX_HDR_H
+
+#include <typedefs.h>
+
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+#define TRX_MAX_LEN 0x3B0000 /* Max length */
+#define TRX_NO_HEADER 1 /* Do not write TRX header */
+#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
+#define TRX_EMBED_UCODE 0x8 /* Trx contains embedded ucode image */
+#define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */
+#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */
+#define TRX_BOOTLOADER 0x40 /* the image is a bootloader */
+
+#define TRX_V1 1
+#define TRX_V1_MAX_OFFSETS 3 /* V1: Max number of individual files */
+
+#ifndef BCMTRXV2
+#define TRX_VERSION TRX_V1 /* Version 1 */
+#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS
+#endif
+
+/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as
+ * Ver 2 of trx header. To make it generic, trx_header is structure is modified
+ * as below where size of "offsets" field will vary as per the TRX version.
+ * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well.
+ * To make sure, other applications like "dhdl" which are yet to be enhanced to support
+ * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2
+ * is defined.
+ */
+struct trx_header {
+ uint32 magic; /* "HDR0" */
+ uint32 len; /* Length of file including header */
+ uint32 crc32; /* 32-bit CRC from flag_version to end of file */
+ uint32 flag_version; /* 0:15 flags, 16:31 version */
+#ifndef BCMTRXV2
+ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
+#else
+ uint32 offsets[1]; /* Offsets of partitions from start of header */
+#endif
+};
+
+#ifdef BCMTRXV2
+#define TRX_VERSION TRX_V2 /* Version 2 */
+#define TRX_MAX_OFFSET TRX_V2_MAX_OFFSETS
+
+#define TRX_V2 2
+/* V2: Max number of individual files
+ * To support SDR signature + Config data region
+ */
+#define TRX_V2_MAX_OFFSETS 5
+#define SIZEOF_TRXHDR_V1 (sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32))
+#define SIZEOF_TRXHDR_V2 (sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32))
+#define TRX_VER(trx) (trx->flag_version>>16)
+#define ISTRX_V1(trx) (TRX_VER(trx) == TRX_V1)
+#define ISTRX_V2(trx) (TRX_VER(trx) == TRX_V2)
+/* For V2, return size of V2 size: others, return V1 size */
+#define SIZEOF_TRX(trx) (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1)
+#else
+#define SIZEOF_TRX(trx) (sizeof(struct trx_header))
+#endif /* BCMTRXV2 */
+
+/* Compatibility */
+typedef struct trx_header TRXHDR, *PTRXHDR;
+
+#endif /* _TRX_HDR_H */
diff --git a/drivers/net/wireless/bcmdhd/include/typedefs.h b/drivers/net/wireless/bcmdhd/include/typedefs.h
new file mode 100644
index 000000000000..4912b7b438a1
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/typedefs.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ * $Id: typedefs.h 453696 2014-02-06 01:10:20Z $
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+#ifdef SITE_TYPEDEFS
+
+/*
+ * Define SITE_TYPEDEFS in the compile to include a site-specific
+ * typedef file "site_typedefs.h".
+ *
+ * If SITE_TYPEDEFS is not defined, then the code section below makes
+ * inferences about the compile environment based on defined symbols and
+ * possibly compiler pragmas.
+ *
+ * Following these two sections is the Default Typedefs section.
+ * This section is only processed if USE_TYPEDEF_DEFAULTS is
+ * defined. This section has a default set of typedefs and a few
+ * preprocessor symbols (TRUE, FALSE, NULL, ...).
+ */
+
+#include "site_typedefs.h"
+
+#else
+
+/*
+ * Infer the compile environment based on preprocessor symbols and pragmas.
+ * Override type definitions as needed, and include configuration-dependent
+ * header files to define types.
+ */
+
+#ifdef __cplusplus
+
+#define TYPEDEF_BOOL
+#ifndef FALSE
+#define FALSE false
+#endif
+#ifndef TRUE
+#define TRUE true
+#endif
+
+#else /* ! __cplusplus */
+
+
+#endif /* ! __cplusplus */
+
+#if defined(__LP64__)
+#define TYPEDEF_UINTPTR
+typedef unsigned long long int uintptr;
+#endif
+
+
+
+
+
+#if defined(_NEED_SIZE_T_)
+typedef long unsigned int size_t;
+#endif
+
+
+
+
+
+#if defined(__sparc__)
+#define TYPEDEF_ULONG
+#endif
+
+
+/*
+ * If this is either a Linux hybrid build or the per-port code of a hybrid build
+ * then use the Linux header files to get some of the typedefs. Otherwise, define
+ * them entirely in this file. We can't always define the types because we get
+ * a duplicate typedef error; there is no way to "undefine" a typedef.
+ * We know when it's per-port code because each file defines LINUX_PORT at the top.
+ */
+#if !defined(LINUX_HYBRID) || defined(LINUX_PORT)
+#define TYPEDEF_UINT
+#ifndef TARGETENV_android
+#define TYPEDEF_USHORT
+#define TYPEDEF_ULONG
+#endif /* TARGETENV_android */
+#ifdef __KERNEL__
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
+#define TYPEDEF_BOOL
+#endif /* >= 2.6.19 */
+/* special detection for 2.6.18-128.7.1.0.1.el5 */
+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18))
+#include <linux/compiler.h>
+#ifdef noinline_for_stack
+#define TYPEDEF_BOOL
+#endif
+#endif /* == 2.6.18 */
+#endif /* __KERNEL__ */
+#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */
+
+
+
+
+/* Do not support the (u)int64 types with strict ansi for GNU C */
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+#endif /* defined(__GNUC__) && defined(__STRICT_ANSI__) */
+
+/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode
+ * for signed or unsigned
+ */
+#if defined(__ICL)
+
+#define TYPEDEF_INT64
+
+#if defined(__STDC__)
+#define TYPEDEF_UINT64
+#endif
+
+#endif /* __ICL */
+
+#if !defined(__DJGPP__)
+
+/* pick up ushort & uint from standard types.h */
+#if defined(__KERNEL__)
+
+/* See note above */
+#if !defined(LINUX_HYBRID) || defined(LINUX_PORT)
+#include <linux/types.h> /* sys/types.h and linux/types.h are oil and water */
+#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */
+
+#else
+
+
+#include <sys/types.h>
+
+#endif /* linux && __KERNEL__ */
+
+#endif
+
+
+
+/* use the default typedefs in the next section of this file */
+#define USE_TYPEDEF_DEFAULTS
+
+#endif /* SITE_TYPEDEFS */
+
+
+/*
+ * Default Typedefs
+ */
+
+#ifdef USE_TYPEDEF_DEFAULTS
+#undef USE_TYPEDEF_DEFAULTS
+
+#ifndef TYPEDEF_BOOL
+typedef /* @abstract@ */ unsigned char bool;
+#endif
+
+/* define uchar, ushort, uint, ulong */
+
+#ifndef TYPEDEF_UCHAR
+typedef unsigned char uchar;
+#endif
+
+#ifndef TYPEDEF_USHORT
+typedef unsigned short ushort;
+#endif
+
+#ifndef TYPEDEF_UINT
+typedef unsigned int uint;
+#endif
+
+#ifndef TYPEDEF_ULONG
+typedef unsigned long ulong;
+#endif
+
+/* define [u]int8/16/32/64, uintptr */
+
+#ifndef TYPEDEF_UINT8
+typedef unsigned char uint8;
+#endif
+
+#ifndef TYPEDEF_UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef TYPEDEF_UINT32
+typedef unsigned int uint32;
+#endif
+
+#ifndef TYPEDEF_UINT64
+typedef unsigned long long uint64;
+#endif
+
+#ifndef TYPEDEF_UINTPTR
+typedef unsigned int uintptr;
+#endif
+
+#ifndef TYPEDEF_INT8
+typedef signed char int8;
+#endif
+
+#ifndef TYPEDEF_INT16
+typedef signed short int16;
+#endif
+
+#ifndef TYPEDEF_INT32
+typedef signed int int32;
+#endif
+
+#ifndef TYPEDEF_INT64
+typedef signed long long int64;
+#endif
+
+/* define float32/64, float_t */
+
+#ifndef TYPEDEF_FLOAT32
+typedef float float32;
+#endif
+
+#ifndef TYPEDEF_FLOAT64
+typedef double float64;
+#endif
+
+/*
+ * abstracted floating point type allows for compile time selection of
+ * single or double precision arithmetic. Compiling with -DFLOAT32
+ * selects single precision; the default is double precision.
+ */
+
+#ifndef TYPEDEF_FLOAT_T
+
+#if defined(FLOAT32)
+typedef float32 float_t;
+#else /* default to double precision floating point */
+typedef float64 float_t;
+#endif
+
+#endif /* TYPEDEF_FLOAT_T */
+
+/* define macro values */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1 /* TRUE */
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+
+#ifndef ON
+#define ON 1 /* ON = 1 */
+#endif
+
+#define AUTO (-1) /* Auto = -1 */
+
+/* define PTRSZ, INLINE */
+
+#ifndef PTRSZ
+#define PTRSZ sizeof(char*)
+#endif
+
+
+/* Detect compiler type. */
+#if defined(__GNUC__) || defined(__lint)
+ #define BWL_COMPILER_GNU
+#elif defined(__CC_ARM) && __CC_ARM
+ #define BWL_COMPILER_ARMCC
+#else
+ #error "Unknown compiler!"
+#endif
+
+
+#ifndef INLINE
+ #if defined(BWL_COMPILER_MICROSOFT)
+ #define INLINE __inline
+ #elif defined(BWL_COMPILER_GNU)
+ #define INLINE __inline__
+ #elif defined(BWL_COMPILER_ARMCC)
+ #define INLINE __inline
+ #else
+ #define INLINE
+ #endif
+#endif /* INLINE */
+
+#undef TYPEDEF_BOOL
+#undef TYPEDEF_UCHAR
+#undef TYPEDEF_USHORT
+#undef TYPEDEF_UINT
+#undef TYPEDEF_ULONG
+#undef TYPEDEF_UINT8
+#undef TYPEDEF_UINT16
+#undef TYPEDEF_UINT32
+#undef TYPEDEF_UINT64
+#undef TYPEDEF_UINTPTR
+#undef TYPEDEF_INT8
+#undef TYPEDEF_INT16
+#undef TYPEDEF_INT32
+#undef TYPEDEF_INT64
+#undef TYPEDEF_FLOAT32
+#undef TYPEDEF_FLOAT64
+#undef TYPEDEF_FLOAT_T
+
+#endif /* USE_TYPEDEF_DEFAULTS */
+
+/* Suppress unused parameter warning */
+#define UNUSED_PARAMETER(x) (void)(x)
+
+/* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */
+#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr))
+
+/*
+ * Including the bcmdefs.h here, to make sure everyone including typedefs.h
+ * gets this automatically
+*/
+#include <bcmdefs.h>
+#endif /* _TYPEDEFS_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/wlfc_proto.h b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h
new file mode 100644
index 000000000000..4eb4a3a41a2e
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h
@@ -0,0 +1,304 @@
+/*
+* Copyright (C) 1999-2016, Broadcom Corporation
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2 (the "GPL"),
+* available at http://www.broadcom.com/licenses/GPLv2.php, with the
+* following added to such license:
+*
+* As a special exception, the copyright holders of this software give you
+* permission to link this software with independent modules, and to copy and
+* distribute the resulting executable under terms of your choice, provided that
+* you also meet, for each linked independent module, the terms and conditions of
+* the license of that module. An independent module is a module which is not
+* derived from this software. The special exception does not apply to any
+* modifications of the software.
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a license
+* other than the GPL, without Broadcom's express prior written consent.
+* $Id: wlfc_proto.h 431159 2013-10-22 19:40:51Z $
+*
+*/
+#ifndef __wlfc_proto_definitions_h__
+#define __wlfc_proto_definitions_h__
+
+ /* Use TLV to convey WLFC information.
+ ---------------------------------------------------------------------------
+ | Type | Len | value | Description
+ ---------------------------------------------------------------------------
+ | 1 | 1 | (handle) | MAC OPEN
+ ---------------------------------------------------------------------------
+ | 2 | 1 | (handle) | MAC CLOSE
+ ---------------------------------------------------------------------------
+ | 3 | 2 | (count, handle, prec_bmp)| Set the credit depth for a MAC dstn
+ ---------------------------------------------------------------------------
+ | 4 | 4+ | see pkttag comments | TXSTATUS
+ | | | TX status & timestamps | Present only when pkt timestamp is enabled
+ ---------------------------------------------------------------------------
+ | 5 | 4 | see pkttag comments | PKKTTAG [host->firmware]
+ ---------------------------------------------------------------------------
+ | 6 | 8 | (handle, ifid, MAC) | MAC ADD
+ ---------------------------------------------------------------------------
+ | 7 | 8 | (handle, ifid, MAC) | MAC DEL
+ ---------------------------------------------------------------------------
+ | 8 | 1 | (rssi) | RSSI - RSSI value for the packet.
+ ---------------------------------------------------------------------------
+ | 9 | 1 | (interface ID) | Interface OPEN
+ ---------------------------------------------------------------------------
+ | 10 | 1 | (interface ID) | Interface CLOSE
+ ---------------------------------------------------------------------------
+ | 11 | 8 | fifo credit returns map | FIFO credits back to the host
+ | | | |
+ | | | | --------------------------------------
+ | | | | | ac0 | ac1 | ac2 | ac3 | bcmc | atim |
+ | | | | --------------------------------------
+ | | | |
+ ---------------------------------------------------------------------------
+ | 12 | 2 | MAC handle, | Host provides a bitmap of pending
+ | | | AC[0-3] traffic bitmap | unicast traffic for MAC-handle dstn.
+ | | | | [host->firmware]
+ ---------------------------------------------------------------------------
+ | 13 | 3 | (count, handle, prec_bmp)| One time request for packet to a specific
+ | | | | MAC destination.
+ ---------------------------------------------------------------------------
+ | 15 | 12 | (pkttag, timestamps) | Send TX timestamp at reception from host
+ ---------------------------------------------------------------------------
+ | 16 | 12 | (pkttag, timestamps) | Send WLAN RX timestamp along with RX frame
+ ---------------------------------------------------------------------------
+ | 255 | N/A | N/A | FILLER - This is a special type
+ | | | | that has no length or value.
+ | | | | Typically used for padding.
+ ---------------------------------------------------------------------------
+ */
+
+#define WLFC_CTL_TYPE_MAC_OPEN 1
+#define WLFC_CTL_TYPE_MAC_CLOSE 2
+#define WLFC_CTL_TYPE_MAC_REQUEST_CREDIT 3
+#define WLFC_CTL_TYPE_TXSTATUS 4
+#define WLFC_CTL_TYPE_PKTTAG 5
+
+#define WLFC_CTL_TYPE_MACDESC_ADD 6
+#define WLFC_CTL_TYPE_MACDESC_DEL 7
+#define WLFC_CTL_TYPE_RSSI 8
+
+#define WLFC_CTL_TYPE_INTERFACE_OPEN 9
+#define WLFC_CTL_TYPE_INTERFACE_CLOSE 10
+
+#define WLFC_CTL_TYPE_FIFO_CREDITBACK 11
+
+#define WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP 12
+#define WLFC_CTL_TYPE_MAC_REQUEST_PACKET 13
+#define WLFC_CTL_TYPE_HOST_REORDER_RXPKTS 14
+
+
+#define WLFC_CTL_TYPE_TX_ENTRY_STAMP 15
+#define WLFC_CTL_TYPE_RX_STAMP 16
+
+#define WLFC_CTL_TYPE_TRANS_ID 18
+#define WLFC_CTL_TYPE_COMP_TXSTATUS 19
+
+
+#define WLFC_CTL_TYPE_FILLER 255
+
+#define WLFC_CTL_VALUE_LEN_MACDESC 8 /* handle, interface, MAC */
+
+#define WLFC_CTL_VALUE_LEN_MAC 1 /* MAC-handle */
+#define WLFC_CTL_VALUE_LEN_RSSI 1
+
+#define WLFC_CTL_VALUE_LEN_INTERFACE 1
+#define WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP 2
+
+#define WLFC_CTL_VALUE_LEN_TXSTATUS 4
+#define WLFC_CTL_VALUE_LEN_PKTTAG 4
+
+#define WLFC_CTL_VALUE_LEN_SEQ 2
+
+/* enough space to host all 4 ACs, bc/mc and atim fifo credit */
+#define WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK 6
+
+#define WLFC_CTL_VALUE_LEN_REQUEST_CREDIT 3 /* credit, MAC-handle, prec_bitmap */
+#define WLFC_CTL_VALUE_LEN_REQUEST_PACKET 3 /* credit, MAC-handle, prec_bitmap */
+
+
+#define WLFC_PKTFLAG_PKTFROMHOST 0x01
+#define WLFC_PKTFLAG_PKT_REQUESTED 0x02
+
+#define WL_TXSTATUS_STATUS_MASK 0xff /* allow 8 bits */
+#define WL_TXSTATUS_STATUS_SHIFT 24
+
+#define WL_TXSTATUS_SET_STATUS(x, status) ((x) = \
+ ((x) & ~(WL_TXSTATUS_STATUS_MASK << WL_TXSTATUS_STATUS_SHIFT)) | \
+ (((status) & WL_TXSTATUS_STATUS_MASK) << WL_TXSTATUS_STATUS_SHIFT))
+#define WL_TXSTATUS_GET_STATUS(x) (((x) >> WL_TXSTATUS_STATUS_SHIFT) & \
+ WL_TXSTATUS_STATUS_MASK)
+
+#define WL_TXSTATUS_GENERATION_MASK 1 /* allow 1 bit */
+#define WL_TXSTATUS_GENERATION_SHIFT 31
+
+#define WL_TXSTATUS_SET_GENERATION(x, gen) ((x) = \
+ ((x) & ~(WL_TXSTATUS_GENERATION_MASK << WL_TXSTATUS_GENERATION_SHIFT)) | \
+ (((gen) & WL_TXSTATUS_GENERATION_MASK) << WL_TXSTATUS_GENERATION_SHIFT))
+
+#define WL_TXSTATUS_GET_GENERATION(x) (((x) >> WL_TXSTATUS_GENERATION_SHIFT) & \
+ WL_TXSTATUS_GENERATION_MASK)
+
+#define WL_TXSTATUS_FLAGS_MASK 0xf /* allow 4 bits only */
+#define WL_TXSTATUS_FLAGS_SHIFT 27
+
+#define WL_TXSTATUS_SET_FLAGS(x, flags) ((x) = \
+ ((x) & ~(WL_TXSTATUS_FLAGS_MASK << WL_TXSTATUS_FLAGS_SHIFT)) | \
+ (((flags) & WL_TXSTATUS_FLAGS_MASK) << WL_TXSTATUS_FLAGS_SHIFT))
+#define WL_TXSTATUS_GET_FLAGS(x) (((x) >> WL_TXSTATUS_FLAGS_SHIFT) & \
+ WL_TXSTATUS_FLAGS_MASK)
+
+#define WL_TXSTATUS_FIFO_MASK 0x7 /* allow 3 bits for FIFO ID */
+#define WL_TXSTATUS_FIFO_SHIFT 24
+
+#define WL_TXSTATUS_SET_FIFO(x, flags) ((x) = \
+ ((x) & ~(WL_TXSTATUS_FIFO_MASK << WL_TXSTATUS_FIFO_SHIFT)) | \
+ (((flags) & WL_TXSTATUS_FIFO_MASK) << WL_TXSTATUS_FIFO_SHIFT))
+#define WL_TXSTATUS_GET_FIFO(x) (((x) >> WL_TXSTATUS_FIFO_SHIFT) & WL_TXSTATUS_FIFO_MASK)
+
+#define WL_TXSTATUS_PKTID_MASK 0xffffff /* allow 24 bits */
+#define WL_TXSTATUS_SET_PKTID(x, num) ((x) = \
+ ((x) & ~WL_TXSTATUS_PKTID_MASK) | (num))
+#define WL_TXSTATUS_GET_PKTID(x) ((x) & WL_TXSTATUS_PKTID_MASK)
+
+#define WL_TXSTATUS_HSLOT_MASK 0xffff /* allow 16 bits */
+#define WL_TXSTATUS_HSLOT_SHIFT 8
+
+#define WL_TXSTATUS_SET_HSLOT(x, hslot) ((x) = \
+ ((x) & ~(WL_TXSTATUS_HSLOT_MASK << WL_TXSTATUS_HSLOT_SHIFT)) | \
+ (((hslot) & WL_TXSTATUS_HSLOT_MASK) << WL_TXSTATUS_HSLOT_SHIFT))
+#define WL_TXSTATUS_GET_HSLOT(x) (((x) >> WL_TXSTATUS_HSLOT_SHIFT)& \
+ WL_TXSTATUS_HSLOT_MASK)
+
+#define WL_TXSTATUS_FREERUNCTR_MASK 0xff /* allow 8 bits */
+
+#define WL_TXSTATUS_SET_FREERUNCTR(x, ctr) ((x) = \
+ ((x) & ~(WL_TXSTATUS_FREERUNCTR_MASK)) | \
+ ((ctr) & WL_TXSTATUS_FREERUNCTR_MASK))
+#define WL_TXSTATUS_GET_FREERUNCTR(x) ((x)& WL_TXSTATUS_FREERUNCTR_MASK)
+
+#define WL_SEQ_FROMFW_MASK 0x1 /* allow 1 bit */
+#define WL_SEQ_FROMFW_SHIFT 13
+#define WL_SEQ_SET_FROMFW(x, val) ((x) = \
+ ((x) & ~(WL_SEQ_FROMFW_MASK << WL_SEQ_FROMFW_SHIFT)) | \
+ (((val) & WL_SEQ_FROMFW_MASK) << WL_SEQ_FROMFW_SHIFT))
+#define WL_SEQ_GET_FROMFW(x) (((x) >> WL_SEQ_FROMFW_SHIFT) & \
+ WL_SEQ_FROMFW_MASK)
+
+#define WL_SEQ_FROMDRV_MASK 0x1 /* allow 1 bit */
+#define WL_SEQ_FROMDRV_SHIFT 12
+#define WL_SEQ_SET_FROMDRV(x, val) ((x) = \
+ ((x) & ~(WL_SEQ_FROMDRV_MASK << WL_SEQ_FROMDRV_SHIFT)) | \
+ (((val) & WL_SEQ_FROMDRV_MASK) << WL_SEQ_FROMDRV_SHIFT))
+#define WL_SEQ_GET_FROMDRV(x) (((x) >> WL_SEQ_FROMDRV_SHIFT) & \
+ WL_SEQ_FROMDRV_MASK)
+
+#define WL_SEQ_NUM_MASK 0xfff /* allow 12 bit */
+#define WL_SEQ_NUM_SHIFT 0
+#define WL_SEQ_SET_NUM(x, val) ((x) = \
+ ((x) & ~(WL_SEQ_NUM_MASK << WL_SEQ_NUM_SHIFT)) | \
+ (((val) & WL_SEQ_NUM_MASK) << WL_SEQ_NUM_SHIFT))
+#define WL_SEQ_GET_NUM(x) (((x) >> WL_SEQ_NUM_SHIFT) & \
+ WL_SEQ_NUM_MASK)
+
+/* 32 STA should be enough??, 6 bits; Must be power of 2 */
+#define WLFC_MAC_DESC_TABLE_SIZE 32
+#define WLFC_MAX_IFNUM 16
+#define WLFC_MAC_DESC_ID_INVALID 0xff
+
+/* b[7:5] -reuse guard, b[4:0] -value */
+#define WLFC_MAC_DESC_GET_LOOKUP_INDEX(x) ((x) & 0x1f)
+
+#define WLFC_PKTFLAG_SET_PKTREQUESTED(x) (x) |= \
+ (WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT)
+
+#define WLFC_PKTFLAG_CLR_PKTREQUESTED(x) (x) &= \
+ ~(WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT)
+
+
+#define WLFC_MAX_PENDING_DATALEN 120
+
+/* host is free to discard the packet */
+#define WLFC_CTL_PKTFLAG_DISCARD 0
+/* D11 suppressed a packet */
+#define WLFC_CTL_PKTFLAG_D11SUPPRESS 1
+/* WL firmware suppressed a packet because MAC is
+ already in PSMode (short time window)
+*/
+#define WLFC_CTL_PKTFLAG_WLSUPPRESS 2
+/* Firmware tossed this packet */
+#define WLFC_CTL_PKTFLAG_TOSSED_BYWLC 3
+/* Firmware tossed after retries */
+#define WLFC_CTL_PKTFLAG_DISCARD_NOACK 4
+
+#define WLFC_D11_STATUS_INTERPRET(txs) \
+ (((txs)->status.suppr_ind != TX_STATUS_SUPR_NONE) ? \
+ WLFC_CTL_PKTFLAG_D11SUPPRESS : \
+ ((txs)->status.was_acked ? \
+ WLFC_CTL_PKTFLAG_DISCARD : WLFC_CTL_PKTFLAG_DISCARD_NOACK))
+
+#ifdef PROP_TXSTATUS_DEBUG
+#define WLFC_DBGMESG(x) printf x
+/* wlfc-breadcrumb */
+#define WLFC_BREADCRUMB(x) do {if ((x) == NULL) \
+ {printf("WLFC: %s():%d:caller:%p\n", \
+ __FUNCTION__, __LINE__, __builtin_return_address(0));}} while (0)
+#define WLFC_PRINTMAC(banner, ea) do {printf("%s MAC: [%02x:%02x:%02x:%02x:%02x:%02x]\n", \
+ banner, ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); } while (0)
+#define WLFC_WHEREIS(s) printf("WLFC: at %s():%d, %s\n", __FUNCTION__, __LINE__, (s))
+#else
+#define WLFC_DBGMESG(x)
+#define WLFC_BREADCRUMB(x)
+#define WLFC_PRINTMAC(banner, ea)
+#define WLFC_WHEREIS(s)
+#endif
+
+/* AMPDU host reorder packet flags */
+#define WLHOST_REORDERDATA_MAXFLOWS 256
+#define WLHOST_REORDERDATA_LEN 10
+#define WLHOST_REORDERDATA_TOTLEN (WLHOST_REORDERDATA_LEN + 1 + 1) /* +tag +len */
+
+#define WLHOST_REORDERDATA_FLOWID_OFFSET 0
+#define WLHOST_REORDERDATA_MAXIDX_OFFSET 2
+#define WLHOST_REORDERDATA_FLAGS_OFFSET 4
+#define WLHOST_REORDERDATA_CURIDX_OFFSET 6
+#define WLHOST_REORDERDATA_EXPIDX_OFFSET 8
+
+#define WLHOST_REORDERDATA_DEL_FLOW 0x01
+#define WLHOST_REORDERDATA_FLUSH_ALL 0x02
+#define WLHOST_REORDERDATA_CURIDX_VALID 0x04
+#define WLHOST_REORDERDATA_EXPIDX_VALID 0x08
+#define WLHOST_REORDERDATA_NEW_HOLE 0x10
+
+/* transaction id data len byte 0: rsvd, byte 1: seqnumber, byte 2-5 will be used for timestampe */
+#define WLFC_CTL_TRANS_ID_LEN 6
+#define WLFC_TYPE_TRANS_ID_LEN 6
+
+#define WLFC_MODE_HANGER 1 /* use hanger */
+#define WLFC_MODE_AFQ 2 /* use afq */
+#define WLFC_IS_OLD_DEF(x) ((x & 1) || (x & 2))
+
+#define WLFC_MODE_AFQ_SHIFT 2 /* afq bit */
+#define WLFC_SET_AFQ(x, val) ((x) = \
+ ((x) & ~(1 << WLFC_MODE_AFQ_SHIFT)) | \
+ (((val) & 1) << WLFC_MODE_AFQ_SHIFT))
+#define WLFC_GET_AFQ(x) (((x) >> WLFC_MODE_AFQ_SHIFT) & 1)
+
+#define WLFC_MODE_REUSESEQ_SHIFT 3 /* seq reuse bit */
+#define WLFC_SET_REUSESEQ(x, val) ((x) = \
+ ((x) & ~(1 << WLFC_MODE_REUSESEQ_SHIFT)) | \
+ (((val) & 1) << WLFC_MODE_REUSESEQ_SHIFT))
+#define WLFC_GET_REUSESEQ(x) (((x) >> WLFC_MODE_REUSESEQ_SHIFT) & 1)
+
+#define WLFC_MODE_REORDERSUPP_SHIFT 4 /* host reorder suppress pkt bit */
+#define WLFC_SET_REORDERSUPP(x, val) ((x) = \
+ ((x) & ~(1 << WLFC_MODE_REORDERSUPP_SHIFT)) | \
+ (((val) & 1) << WLFC_MODE_REORDERSUPP_SHIFT))
+#define WLFC_GET_REORDERSUPP(x) (((x) >> WLFC_MODE_REORDERSUPP_SHIFT) & 1)
+
+#endif /* __wlfc_proto_definitions_h__ */
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
new file mode 100644
index 000000000000..cc2d667ec670
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -0,0 +1,5008 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wlioctl.h 662961 2016-11-24 01:22:35Z $
+ */
+
+#ifndef _wlioctl_h_
+#define _wlioctl_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <proto/bcmip.h>
+#include <proto/bcmeth.h>
+#include <proto/bcmip.h>
+#include <proto/bcmevent.h>
+#include <proto/802.11.h>
+#include <proto/802.1d.h>
+#include <bcmwifi_channels.h>
+#include <bcmwifi_rates.h>
+#include <devctrl_if/wlioctl_defs.h>
+
+#include <bcm_mpool_pub.h>
+#include <bcmcdc.h>
+
+
+
+
+#ifndef INTF_NAME_SIZ
+#define INTF_NAME_SIZ 16
+#endif
+
+/* Used to send ioctls over the transport pipe */
+typedef struct remote_ioctl {
+ cdc_ioctl_t msg;
+ uint32 data_len;
+ char intf_name[INTF_NAME_SIZ];
+} rem_ioctl_t;
+#define REMOTE_SIZE sizeof(rem_ioctl_t)
+
+typedef struct {
+ uint32 num;
+ chanspec_t list[1];
+} chanspec_list_t;
+
+/* association decision information */
+typedef struct {
+ bool assoc_approved; /* (re)association approved */
+ uint16 reject_reason; /* reason code for rejecting association */
+ struct ether_addr da;
+ int64 sys_time; /* current system time */
+} assoc_decision_t;
+
+#define ACTION_FRAME_SIZE 1800
+
+typedef struct wl_action_frame {
+ struct ether_addr da;
+ uint16 len;
+ uint32 packetId;
+ uint8 data[ACTION_FRAME_SIZE];
+} wl_action_frame_t;
+
+#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame)
+
+typedef struct ssid_info
+{
+ uint8 ssid_len; /* the length of SSID */
+ uint8 ssid[32]; /* SSID string */
+} ssid_info_t;
+
+typedef struct wl_af_params {
+ uint32 channel;
+ int32 dwell_time;
+ struct ether_addr BSSID;
+ wl_action_frame_t action_frame;
+} wl_af_params_t;
+
+#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params)
+
+#define MFP_TEST_FLAG_NORMAL 0
+#define MFP_TEST_FLAG_ANY_KEY 1
+typedef struct wl_sa_query {
+ uint32 flag;
+ uint8 action;
+ uint16 id;
+ struct ether_addr da;
+} wl_sa_query_t;
+
+/* require default structure packing */
+#define BWL_DEFAULT_PACKING
+#include <packed_section_start.h>
+
+
+
+/* Legacy structure to help keep backward compatible wl tool and tray app */
+
+#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */
+
+typedef struct wl_bss_info_107 {
+ uint32 version; /* version field */
+ uint32 length; /* byte length of data in this record,
+ * starting at version and including IEs
+ */
+ struct ether_addr BSSID;
+ uint16 beacon_period; /* units are Kusec */
+ uint16 capability; /* Capability information */
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ uint8 channel; /* Channel no. */
+ uint16 atim_window; /* units are Kusec */
+ uint8 dtim_period; /* DTIM period */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ int8 phy_noise; /* noise (in dBm) */
+ uint32 ie_length; /* byte length of Information Elements */
+ /* variable length Information Elements */
+} wl_bss_info_107_t;
+
+/*
+ * Per-BSS information structure.
+ */
+
+#define LEGACY2_WL_BSS_INFO_VERSION 108 /* old version of wl_bss_info struct */
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in wl_scan_results_t)
+ */
+typedef struct wl_bss_info_108 {
+ uint32 version; /* version field */
+ uint32 length; /* byte length of data in this record,
+ * starting at version and including IEs
+ */
+ struct ether_addr BSSID;
+ uint16 beacon_period; /* units are Kusec */
+ uint16 capability; /* Capability information */
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ chanspec_t chanspec; /* chanspec for bss */
+ uint16 atim_window; /* units are Kusec */
+ uint8 dtim_period; /* DTIM period */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ int8 phy_noise; /* noise (in dBm) */
+
+ uint8 n_cap; /* BSS is 802.11N Capable */
+ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */
+ uint8 ctl_ch; /* 802.11N BSS control channel number */
+ uint32 reserved32[1]; /* Reserved for expansion of BSS properties */
+ uint8 flags; /* flags */
+ uint8 reserved[3]; /* Reserved for expansion of BSS properties */
+ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
+
+ uint16 ie_offset; /* offset at which IEs start, from beginning */
+ uint32 ie_length; /* byte length of Information Elements */
+ /* Add new fields here */
+ /* variable length Information Elements */
+} wl_bss_info_108_t;
+
+#define WL_BSS_INFO_VERSION 109 /* current version of wl_bss_info struct */
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in wl_scan_results_t)
+ */
+typedef struct wl_bss_info {
+ uint32 version; /* version field */
+ uint32 length; /* byte length of data in this record,
+ * starting at version and including IEs
+ */
+ struct ether_addr BSSID;
+ uint16 beacon_period; /* units are Kusec */
+ uint16 capability; /* Capability information */
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count; /* # rates in this set */
+ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ } rateset; /* supported rates */
+ chanspec_t chanspec; /* chanspec for bss */
+ uint16 atim_window; /* units are Kusec */
+ uint8 dtim_period; /* DTIM period */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ int8 phy_noise; /* noise (in dBm) */
+
+ uint8 n_cap; /* BSS is 802.11N Capable */
+ uint32 nbss_cap; /* 802.11N+AC BSS Capabilities */
+ uint8 ctl_ch; /* 802.11N BSS control channel number */
+ uint8 padding1[3]; /* explicit struct alignment padding */
+ uint16 vht_rxmcsmap; /* VHT rx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */
+ uint16 vht_txmcsmap; /* VHT tx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */
+ uint8 flags; /* flags */
+ uint8 vht_cap; /* BSS is vht capable */
+ uint8 reserved[2]; /* Reserved for expansion of BSS properties */
+ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
+
+ uint16 ie_offset; /* offset at which IEs start, from beginning */
+ uint32 ie_length; /* byte length of Information Elements */
+ int16 SNR; /* average SNR of during frame reception */
+ /* Add new fields here */
+ /* variable length Information Elements */
+} wl_bss_info_t;
+
+
+typedef struct wl_bsscfg {
+ uint32 bsscfg_idx;
+ uint32 wsec;
+ uint32 WPA_auth;
+ uint32 wsec_index;
+ uint32 associated;
+ uint32 BSS;
+ uint32 phytest_on;
+ struct ether_addr prev_BSSID;
+ struct ether_addr BSSID;
+ uint32 targetbss_wpa2_flags;
+ uint32 assoc_type;
+ uint32 assoc_state;
+} wl_bsscfg_t;
+
+typedef struct wl_if_add {
+ uint32 bsscfg_flags;
+ uint32 if_flags;
+ uint32 ap;
+ struct ether_addr mac_addr;
+} wl_if_add_t;
+
+typedef struct wl_bss_config {
+ uint32 atim_window;
+ uint32 beacon_period;
+ uint32 chanspec;
+} wl_bss_config_t;
+
+#define WL_BSS_USER_RADAR_CHAN_SELECT 0x1 /* User application will randomly select
+ * radar channel.
+ */
+
+#define DLOAD_HANDLER_VER 1 /* Downloader version */
+#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */
+#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */
+
+#define DL_CRC_NOT_INUSE 0x0001
+
+/* generic download types & flags */
+enum {
+ DL_TYPE_UCODE = 1,
+ DL_TYPE_CLM = 2
+};
+
+/* ucode type values */
+enum {
+ UCODE_FW,
+ INIT_VALS,
+ BS_INIT_VALS
+};
+
+struct wl_dload_data {
+ uint16 flag;
+ uint16 dload_type;
+ uint32 len;
+ uint32 crc;
+ uint8 data[1];
+};
+typedef struct wl_dload_data wl_dload_data_t;
+
+struct wl_ucode_info {
+ uint32 ucode_type;
+ uint32 num_chunks;
+ uint32 chunk_len;
+ uint32 chunk_num;
+ uint8 data_chunk[1];
+};
+typedef struct wl_ucode_info wl_ucode_info_t;
+
+struct wl_clm_dload_info {
+ uint32 ds_id;
+ uint32 clm_total_len;
+ uint32 num_chunks;
+ uint32 chunk_len;
+ uint32 chunk_offset;
+ uint8 data_chunk[1];
+};
+typedef struct wl_clm_dload_info wl_clm_dload_info_t;
+
+typedef struct wlc_ssid {
+ uint32 SSID_len;
+ uchar SSID[DOT11_MAX_SSID_LEN];
+} wlc_ssid_t;
+
+
+#define MAX_PREFERRED_AP_NUM 5
+typedef struct wlc_fastssidinfo {
+ uint32 SSID_channel[MAX_PREFERRED_AP_NUM];
+ wlc_ssid_t SSID_info[MAX_PREFERRED_AP_NUM];
+} wlc_fastssidinfo_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wnm_url {
+ uint8 len;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT wnm_url_t;
+
+typedef struct chan_scandata {
+ uint8 txpower;
+ uint8 pad;
+ chanspec_t channel; /* Channel num, bw, ctrl_sb and band */
+ uint32 channel_mintime;
+ uint32 channel_maxtime;
+} chan_scandata_t;
+
+typedef enum wl_scan_type {
+ EXTDSCAN_FOREGROUND_SCAN,
+ EXTDSCAN_BACKGROUND_SCAN,
+ EXTDSCAN_FORCEDBACKGROUND_SCAN
+} wl_scan_type_t;
+
+#define WLC_EXTDSCAN_MAX_SSID 5
+
+typedef struct wl_extdscan_params {
+ int8 nprobes; /* 0, passive, otherwise active */
+ int8 split_scan; /* split scan */
+ int8 band; /* band */
+ int8 pad;
+ wlc_ssid_t ssid[WLC_EXTDSCAN_MAX_SSID]; /* ssid list */
+ uint32 tx_rate; /* in 500ksec units */
+ wl_scan_type_t scan_type; /* enum */
+ int32 channel_num;
+ chan_scandata_t channel_list[1]; /* list of chandata structs */
+} wl_extdscan_params_t;
+
+#define WL_EXTDSCAN_PARAMS_FIXED_SIZE (sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t))
+
+#define WL_SCAN_PARAMS_SSID_MAX 10
+
+typedef struct wl_scan_params {
+ wlc_ssid_t ssid; /* default: {0, ""} */
+ struct ether_addr bssid; /* default: bcast */
+ int8 bss_type; /* default: any,
+ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
+ */
+ uint8 scan_type; /* flags, 0 use default */
+ int32 nprobes; /* -1 use default, number of probes per channel */
+ int32 active_time; /* -1 use default, dwell time per channel for
+ * active scanning
+ */
+ int32 passive_time; /* -1 use default, dwell time per channel
+ * for passive scanning
+ */
+ int32 home_time; /* -1 use default, dwell time for the home channel
+ * between channel scans
+ */
+ int32 channel_num; /* count of channels and ssids that follow
+ *
+ * low half is count of channels in channel_list, 0
+ * means default (use all available channels)
+ *
+ * high half is entries in wlc_ssid_t array that
+ * follows channel_list, aligned for int32 (4 bytes)
+ * meaning an odd channel count implies a 2-byte pad
+ * between end of channel_list and first ssid
+ *
+ * if ssid count is zero, single ssid in the fixed
+ * parameter portion is assumed, otherwise ssid in
+ * the fixed portion is ignored
+ */
+ uint16 channel_list[1]; /* list of chanspecs */
+} wl_scan_params_t;
+
+/* size of wl_scan_params not including variable length array */
+#define WL_SCAN_PARAMS_FIXED_SIZE 64
+
+#define ISCAN_REQ_VERSION 1
+
+/* incremental scan struct */
+typedef struct wl_iscan_params {
+ uint32 version;
+ uint16 action;
+ uint16 scan_duration;
+ wl_scan_params_t params;
+} wl_iscan_params_t;
+
+/* 3 fields + size of wl_scan_params, not including variable length array */
+#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t))
+
+typedef struct wl_scan_results {
+ uint32 buflen;
+ uint32 version;
+ uint32 count;
+ wl_bss_info_t bss_info[1];
+} wl_scan_results_t;
+
+/* size of wl_scan_results not including variable length array */
+#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t))
+
+/* Used in EXT_STA */
+#define DNGL_RXCTXT_SIZE 45
+
+
+#define ESCAN_REQ_VERSION 1
+
+typedef struct wl_escan_params {
+ uint32 version;
+ uint16 action;
+ uint16 sync_id;
+ wl_scan_params_t params;
+} wl_escan_params_t;
+
+#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t))
+
+typedef struct wl_escan_result {
+ uint32 buflen;
+ uint32 version;
+ uint16 sync_id;
+ uint16 bss_count;
+ wl_bss_info_t bss_info[1];
+} wl_escan_result_t;
+
+#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t))
+
+/* incremental scan results struct */
+typedef struct wl_iscan_results {
+ uint32 status;
+ wl_scan_results_t results;
+} wl_iscan_results_t;
+
+/* size of wl_iscan_results not including variable length array */
+#define WL_ISCAN_RESULTS_FIXED_SIZE \
+ (WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results))
+
+#define SCANOL_PARAMS_VERSION 1
+
+typedef struct scanol_params {
+ uint32 version;
+ uint32 flags; /* offload scanning flags */
+ int32 active_time; /* -1 use default, dwell time per channel for active scanning */
+ int32 passive_time; /* -1 use default, dwell time per channel for passive scanning */
+ int32 idle_rest_time; /* -1 use default, time idle between scan cycle */
+ int32 idle_rest_time_multiplier;
+ int32 active_rest_time;
+ int32 active_rest_time_multiplier;
+ int32 scan_cycle_idle_rest_time;
+ int32 scan_cycle_idle_rest_multiplier;
+ int32 scan_cycle_active_rest_time;
+ int32 scan_cycle_active_rest_multiplier;
+ int32 max_rest_time;
+ int32 max_scan_cycles;
+ int32 nprobes; /* -1 use default, number of probes per channel */
+ int32 scan_start_delay;
+ uint32 nchannels;
+ uint32 ssid_count;
+ wlc_ssid_t ssidlist[1];
+} scanol_params_t;
+
+typedef struct wl_probe_params {
+ wlc_ssid_t ssid;
+ struct ether_addr bssid;
+ struct ether_addr mac;
+} wl_probe_params_t;
+
+#define WL_MAXRATES_IN_SET 16 /* max # of rates in a rateset */
+typedef struct wl_rateset {
+ uint32 count; /* # rates in this set */
+ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */
+} wl_rateset_t;
+
+typedef struct wl_rateset_args {
+ uint32 count; /* # rates in this set */
+ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */
+ uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */
+ uint16 vht_mcs[VHT_CAP_MCS_MAP_NSS_MAX]; /* supported mcs index bit map per nss */
+} wl_rateset_args_t;
+
+#define TXBF_RATE_MCS_ALL 4
+#define TXBF_RATE_VHT_ALL 4
+#define TXBF_RATE_OFDM_ALL 8
+
+typedef struct wl_txbf_rateset {
+ uint8 txbf_rate_mcs[TXBF_RATE_MCS_ALL]; /* one for each stream */
+ uint8 txbf_rate_mcs_bcm[TXBF_RATE_MCS_ALL]; /* one for each stream */
+ uint16 txbf_rate_vht[TXBF_RATE_VHT_ALL]; /* one for each stream */
+ uint16 txbf_rate_vht_bcm[TXBF_RATE_VHT_ALL]; /* one for each stream */
+ uint8 txbf_rate_ofdm[TXBF_RATE_OFDM_ALL]; /* bitmap of ofdm rates that enables txbf */
+ uint8 txbf_rate_ofdm_bcm[TXBF_RATE_OFDM_ALL]; /* bitmap of ofdm rates that enables txbf */
+ uint8 txbf_rate_ofdm_cnt;
+ uint8 txbf_rate_ofdm_cnt_bcm;
+} wl_txbf_rateset_t;
+
+#define OFDM_RATE_MASK 0x0000007f
+typedef uint8 ofdm_rates_t;
+
+typedef struct wl_rates_info {
+ wl_rateset_t rs_tgt;
+ uint32 phy_type;
+ int32 bandtype;
+ uint8 cck_only;
+ uint8 rate_mask;
+ uint8 mcsallow;
+ uint8 bw;
+ uint8 txstreams;
+} wl_rates_info_t;
+
+/* uint32 list */
+typedef struct wl_uint32_list {
+ /* in - # of elements, out - # of entries */
+ uint32 count;
+ /* variable length uint32 list */
+ uint32 element[1];
+} wl_uint32_list_t;
+
+/* used for association with a specific BSSID and chanspec list */
+typedef struct wl_assoc_params {
+ struct ether_addr bssid; /* 00:00:00:00:00:00: broadcast scan */
+ uint16 bssid_cnt; /* 0: use chanspec_num, and the single bssid,
+ * otherwise count of chanspecs in chanspec_list
+ * AND paired bssids following chanspec_list
+ * also, chanspec_num has to be set to zero
+ * for bssid list to be used
+ */
+ int32 chanspec_num; /* 0: all available channels,
+ * otherwise count of chanspecs in chanspec_list
+ */
+ chanspec_t chanspec_list[1]; /* list of chanspecs */
+} wl_assoc_params_t;
+
+#define WL_ASSOC_PARAMS_FIXED_SIZE OFFSETOF(wl_assoc_params_t, chanspec_list)
+
+/* used for reassociation/roam to a specific BSSID and channel */
+typedef wl_assoc_params_t wl_reassoc_params_t;
+#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE
+
+/* used for association to a specific BSSID and channel */
+typedef wl_assoc_params_t wl_join_assoc_params_t;
+#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE
+
+/* used for join with or without a specific bssid and channel list */
+typedef struct wl_join_params {
+ wlc_ssid_t ssid;
+ wl_assoc_params_t params; /* optional field, but it must include the fixed portion
+ * of the wl_assoc_params_t struct when it does present.
+ */
+} wl_join_params_t;
+
+#define WL_JOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_join_params_t, params) + \
+ WL_ASSOC_PARAMS_FIXED_SIZE)
+/* scan params for extended join */
+typedef struct wl_join_scan_params {
+ uint8 scan_type; /* 0 use default, active or passive scan */
+ int32 nprobes; /* -1 use default, number of probes per channel */
+ int32 active_time; /* -1 use default, dwell time per channel for
+ * active scanning
+ */
+ int32 passive_time; /* -1 use default, dwell time per channel
+ * for passive scanning
+ */
+ int32 home_time; /* -1 use default, dwell time for the home channel
+ * between channel scans
+ */
+} wl_join_scan_params_t;
+
+/* extended join params */
+typedef struct wl_extjoin_params {
+ wlc_ssid_t ssid; /* {0, ""}: wildcard scan */
+ wl_join_scan_params_t scan;
+ wl_join_assoc_params_t assoc; /* optional field, but it must include the fixed portion
+ * of the wl_join_assoc_params_t struct when it does
+ * present.
+ */
+} wl_extjoin_params_t;
+#define WL_EXTJOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_extjoin_params_t, assoc) + \
+ WL_JOIN_ASSOC_PARAMS_FIXED_SIZE)
+
+#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */
+#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */
+typedef struct {
+ uint8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */
+ uint8 num_antcfg; /* number of available antenna configurations */
+} wlc_antselcfg_t;
+
+typedef struct {
+ uint32 duration; /* millisecs spent sampling this channel */
+ uint32 congest_ibss; /* millisecs in our bss (presumably this traffic will */
+ /* move if cur bss moves channels) */
+ uint32 congest_obss; /* traffic not in our bss */
+ uint32 interference; /* millisecs detecting a non 802.11 interferer. */
+ uint32 timestamp; /* second timestamp */
+} cca_congest_t;
+
+typedef struct {
+ chanspec_t chanspec; /* Which channel? */
+ uint8 num_secs; /* How many secs worth of data */
+ cca_congest_t secs[1]; /* Data */
+} cca_congest_channel_req_t;
+
+typedef struct {
+ uint32 msrmnt_time; /**< Time for Measurement (msec) */
+ uint32 msrmnt_done; /**< flag set when measurement complete */
+ char buf[1];
+} cca_stats_n_flags;
+
+typedef struct {
+ uint32 msrmnt_query; /* host to driver query for measurement done */
+ uint32 time_req; /* time required for measurement */
+ uint8 report_opt; /* option to print different stats in report */
+} cca_msrmnt_query;
+
+/* interference sources */
+enum interference_source {
+ ITFR_NONE = 0, /* interference */
+ ITFR_PHONE, /* wireless phone */
+ ITFR_VIDEO_CAMERA, /* wireless video camera */
+ ITFR_MICROWAVE_OVEN, /* microwave oven */
+ ITFR_BABY_MONITOR, /* wireless baby monitor */
+ ITFR_BLUETOOTH, /* bluetooth */
+ ITFR_VIDEO_CAMERA_OR_BABY_MONITOR, /* wireless camera or baby monitor */
+ ITFR_BLUETOOTH_OR_BABY_MONITOR, /* bluetooth or baby monitor */
+ ITFR_VIDEO_CAMERA_OR_PHONE, /* video camera or phone */
+ ITFR_UNIDENTIFIED /* interference from unidentified source */
+};
+
+/* structure for interference source report */
+typedef struct {
+ uint32 flags; /* flags. bit definitions below */
+ uint32 source; /* last detected interference source */
+ uint32 timestamp; /* second timestamp on interferenced flag change */
+} interference_source_rep_t;
+
+#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */
+
+
+typedef struct wl_country {
+ char country_abbrev[WLC_CNTRY_BUF_SZ]; /* nul-terminated country code used in
+ * the Country IE
+ */
+ int32 rev; /* revision specifier for ccode
+ * on set, -1 indicates unspecified.
+ * on get, rev >= 0
+ */
+ char ccode[WLC_CNTRY_BUF_SZ]; /* nul-terminated built-in country code.
+ * variable length, but fixed size in
+ * struct allows simple allocation for
+ * expected country strings <= 3 chars.
+ */
+} wl_country_t;
+
+typedef struct wl_channels_in_country {
+ uint32 buflen;
+ uint32 band;
+ char country_abbrev[WLC_CNTRY_BUF_SZ];
+ uint32 count;
+ uint32 channel[1];
+} wl_channels_in_country_t;
+
+typedef struct wl_country_list {
+ uint32 buflen;
+ uint32 band_set;
+ uint32 band;
+ uint32 count;
+ char country_abbrev[1];
+} wl_country_list_t;
+
+typedef struct wl_rm_req_elt {
+ int8 type;
+ int8 flags;
+ chanspec_t chanspec;
+ uint32 token; /* token for this measurement */
+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */
+ uint32 tsf_l; /* TSF low 32-bits */
+ uint32 dur; /* TUs */
+} wl_rm_req_elt_t;
+
+typedef struct wl_rm_req {
+ uint32 token; /* overall measurement set token */
+ uint32 count; /* number of measurement requests */
+ void *cb; /* completion callback function: may be NULL */
+ void *cb_arg; /* arg to completion callback function */
+ wl_rm_req_elt_t req[1]; /* variable length block of requests */
+} wl_rm_req_t;
+#define WL_RM_REQ_FIXED_LEN OFFSETOF(wl_rm_req_t, req)
+
+typedef struct wl_rm_rep_elt {
+ int8 type;
+ int8 flags;
+ chanspec_t chanspec;
+ uint32 token; /* token for this measurement */
+ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */
+ uint32 tsf_l; /* TSF low 32-bits */
+ uint32 dur; /* TUs */
+ uint32 len; /* byte length of data block */
+ uint8 data[1]; /* variable length data block */
+} wl_rm_rep_elt_t;
+#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */
+
+#define WL_RPI_REP_BIN_NUM 8
+typedef struct wl_rm_rpi_rep {
+ uint8 rpi[WL_RPI_REP_BIN_NUM];
+ int8 rpi_max[WL_RPI_REP_BIN_NUM];
+} wl_rm_rpi_rep_t;
+
+typedef struct wl_rm_rep {
+ uint32 token; /* overall measurement set token */
+ uint32 len; /* length of measurement report block */
+ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */
+} wl_rm_rep_t;
+#define WL_RM_REP_FIXED_LEN 8
+
+
+typedef enum sup_auth_status {
+ /* Basic supplicant authentication states */
+ WLC_SUP_DISCONNECTED = 0,
+ WLC_SUP_CONNECTING,
+ WLC_SUP_IDREQUIRED,
+ WLC_SUP_AUTHENTICATING,
+ WLC_SUP_AUTHENTICATED,
+ WLC_SUP_KEYXCHANGE,
+ WLC_SUP_KEYED,
+ WLC_SUP_TIMEOUT,
+ WLC_SUP_LAST_BASIC_STATE,
+
+ /* Extended supplicant authentication states */
+ /* Waiting to receive handshake msg M1 */
+ WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED,
+ /* Preparing to send handshake msg M2 */
+ WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE,
+ /* Waiting to receive handshake msg M3 */
+ WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE,
+ WLC_SUP_KEYXCHANGE_PREP_M4, /* Preparing to send handshake msg M4 */
+ WLC_SUP_KEYXCHANGE_WAIT_G1, /* Waiting to receive handshake msg G1 */
+ WLC_SUP_KEYXCHANGE_PREP_G2 /* Preparing to send handshake msg G2 */
+} sup_auth_status_t;
+
+typedef struct wl_wsec_key {
+ uint32 index; /* key index */
+ uint32 len; /* key length */
+ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */
+ uint32 pad_1[18];
+ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ uint32 flags; /* misc flags */
+ uint32 pad_2[2];
+ int pad_3;
+ int iv_initialized; /* has IV been initialized already? */
+ int pad_4;
+ /* Rx IV */
+ struct {
+ uint32 hi; /* upper 32 bits of IV */
+ uint16 lo; /* lower 16 bits of IV */
+ } rxiv;
+ uint32 pad_5[2];
+ struct ether_addr ea; /* per station */
+} wl_wsec_key_t;
+
+#define WSEC_MIN_PSK_LEN 8
+#define WSEC_MAX_PSK_LEN 64
+
+/* Flag for key material needing passhash'ing */
+#define WSEC_PASSPHRASE (1<<0)
+
+/* receptacle for WLC_SET_WSEC_PMK parameter */
+typedef struct {
+ ushort key_len; /* octets in key material */
+ ushort flags; /* key handling qualification */
+ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */
+} wsec_pmk_t;
+
+typedef struct _pmkid {
+ struct ether_addr BSSID;
+ uint8 PMKID[WPA2_PMKID_LEN];
+} pmkid_t;
+
+typedef struct _pmkid_list {
+ uint32 npmkid;
+ pmkid_t pmkid[1];
+} pmkid_list_t;
+
+typedef struct _pmkid_cand {
+ struct ether_addr BSSID;
+ uint8 preauth;
+} pmkid_cand_t;
+
+typedef struct _pmkid_cand_list {
+ uint32 npmkid_cand;
+ pmkid_cand_t pmkid_cand[1];
+} pmkid_cand_list_t;
+
+#define WL_STA_ANT_MAX 4 /* max possible rx antennas */
+
+typedef struct wl_assoc_info {
+ uint32 req_len;
+ uint32 resp_len;
+ uint32 flags;
+ struct dot11_assoc_req req;
+ struct ether_addr reassoc_bssid; /* used in reassoc's */
+ struct dot11_assoc_resp resp;
+} wl_assoc_info_t;
+
+typedef struct wl_led_info {
+ uint32 index; /* led index */
+ uint32 behavior;
+ uint8 activehi;
+} wl_led_info_t;
+
+
+/* srom read/write struct passed through ioctl */
+typedef struct {
+ uint byteoff; /* byte offset */
+ uint nbytes; /* number of bytes */
+ uint16 buf[1];
+} srom_rw_t;
+
+/* similar cis (srom or otp) struct [iovar: may not be aligned] */
+typedef struct {
+ uint32 source; /* cis source */
+ uint32 byteoff; /* byte offset */
+ uint32 nbytes; /* number of bytes */
+ /* data follows here */
+} cis_rw_t;
+
+/* R_REG and W_REG struct passed through ioctl */
+typedef struct {
+ uint32 byteoff; /* byte offset of the field in d11regs_t */
+ uint32 val; /* read/write value of the field */
+ uint32 size; /* sizeof the field */
+ uint band; /* band (optional) */
+} rw_reg_t;
+
+/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */
+/* PCL - Power Control Loop */
+typedef struct {
+ uint16 auto_ctrl; /* WL_ATTEN_XX */
+ uint16 bb; /* Baseband attenuation */
+ uint16 radio; /* Radio attenuation */
+ uint16 txctl1; /* Radio TX_CTL1 value */
+} atten_t;
+
+/* Per-AC retry parameters */
+struct wme_tx_params_s {
+ uint8 short_retry;
+ uint8 short_fallback;
+ uint8 long_retry;
+ uint8 long_fallback;
+ uint16 max_rate; /* In units of 512 Kbps */
+};
+
+typedef struct wme_tx_params_s wme_tx_params_t;
+
+#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT)
+
+typedef struct wl_plc_nodelist {
+ uint32 count; /* Number of nodes */
+ struct _node {
+ struct ether_addr ea; /* Node ether address */
+ uint32 node_type; /* Node type */
+ uint32 cost; /* PLC affinity */
+ } node[1];
+} wl_plc_nodelist_t;
+
+typedef struct wl_plc_params {
+ uint32 cmd; /* Command */
+ uint8 plc_failover; /* PLC failover control/status */
+ struct ether_addr node_ea; /* Node ether address */
+ uint32 cost; /* Link cost or mac cost */
+} wl_plc_params_t;
+
+/* Used to get specific link/ac parameters */
+typedef struct {
+ int32 ac;
+ uint8 val;
+ struct ether_addr ea;
+} link_val_t;
+
+
+
+typedef struct {
+ uint16 ver; /* version of this struct */
+ uint16 len; /* length in bytes of this structure */
+ uint16 cap; /* sta's advertised capabilities */
+ uint32 flags; /* flags defined below */
+ uint32 idle; /* time since data pkt rx'd from sta */
+ struct ether_addr ea; /* Station address */
+ wl_rateset_t rateset; /* rateset in use */
+ uint32 in; /* seconds elapsed since associated */
+ uint32 listen_interval_inms; /* Min Listen interval in ms for this STA */
+ uint32 tx_pkts; /* # of packets transmitted */
+ uint32 tx_failures; /* # of packets failed */
+ uint32 rx_ucast_pkts; /* # of unicast packets received */
+ uint32 rx_mcast_pkts; /* # of multicast packets received */
+ uint32 tx_rate; /* Rate of last successful tx frame */
+ uint32 rx_rate; /* Rate of last successful rx frame */
+ uint32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
+ uint32 rx_decrypt_failures; /* # of packet decrypted unsuccessfully */
+ uint32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
+ uint32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
+ uint32 tx_mcast_pkts; /* # of mcast pkts txed */
+ uint64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */
+ uint64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */
+ uint64 tx_ucast_bytes; /* data bytes txed (ucast) */
+ uint64 tx_mcast_bytes; /* # data bytes txed (mcast) */
+ uint64 rx_ucast_bytes; /* data bytes recvd (ucast) */
+ uint64 rx_mcast_bytes; /* data bytes recvd (mcast) */
+ int8 rssi[WL_STA_ANT_MAX]; /* average rssi per antenna
+ * of data frames
+ */
+ int8 nf[WL_STA_ANT_MAX]; /* per antenna noise floor */
+ uint16 aid; /* association ID */
+ uint16 ht_capabilities; /* advertised ht caps */
+ uint16 vht_flags; /* converted vht flags */
+ uint32 tx_pkts_retried; /* # of frames where a retry was necessary */
+ uint32 tx_pkts_retry_exhausted; /* # of frames where a retry was
+ * exhausted
+ */
+ int8 rx_lastpkt_rssi[WL_STA_ANT_MAX]; /* Per antenna RSSI of last
+ * received data frame.
+ */
+} sta_info_t;
+
+#define WL_OLD_STAINFO_SIZE OFFSETOF(sta_info_t, tx_tot_pkts)
+
+#define WL_STA_VER 4
+
+#define WLC_NUMRATES 16 /* max # of rates in a rateset */
+
+typedef struct wlc_rateset {
+ uint32 count; /* number of rates in rates[] */
+ uint8 rates[WLC_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */
+ uint8 htphy_membership; /* HT PHY Membership */
+ uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */
+ uint16 vht_mcsmap; /* supported vht mcs nss bit map */
+} wlc_rateset_t;
+
+/* Used to get specific STA parameters */
+typedef struct {
+ uint32 val;
+ struct ether_addr ea;
+} scb_val_t;
+
+/* Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */
+typedef struct {
+ uint32 code;
+ scb_val_t ioctl_args;
+} authops_t;
+
+/* channel encoding */
+typedef struct channel_info {
+ int hw_channel;
+ int target_channel;
+ int scan_channel;
+} channel_info_t;
+
+/* For ioctls that take a list of MAC addresses */
+struct maclist {
+ uint count; /* number of MAC addresses */
+ struct ether_addr ea[1]; /* variable length array of MAC addresses */
+};
+
+/* get pkt count struct passed through ioctl */
+typedef struct get_pktcnt {
+ uint rx_good_pkt;
+ uint rx_bad_pkt;
+ uint tx_good_pkt;
+ uint tx_bad_pkt;
+ uint rx_ocast_good_pkt; /* unicast packets destined for others */
+} get_pktcnt_t;
+
+/* NINTENDO2 */
+#define LQ_IDX_MIN 0
+#define LQ_IDX_MAX 1
+#define LQ_IDX_AVG 2
+#define LQ_IDX_SUM 2
+#define LQ_IDX_LAST 3
+#define LQ_STOP_MONITOR 0
+#define LQ_START_MONITOR 1
+
+/* Get averages RSSI, Rx PHY rate and SNR values */
+typedef struct {
+ int rssi[LQ_IDX_LAST]; /* Array to keep min, max, avg rssi */
+ int snr[LQ_IDX_LAST]; /* Array to keep min, max, avg snr */
+ int isvalid; /* Flag indicating whether above data is valid */
+} wl_lq_t; /* Link Quality */
+
+typedef enum wl_wakeup_reason_type {
+ LCD_ON = 1,
+ LCD_OFF,
+ DRC1_WAKE,
+ DRC2_WAKE,
+ REASON_LAST
+} wl_wr_type_t;
+
+typedef struct {
+/* Unique filter id */
+ uint32 id;
+
+/* stores the reason for the last wake up */
+ uint8 reason;
+} wl_wr_t;
+
+/* Get MAC specific rate histogram command */
+typedef struct {
+ struct ether_addr ea; /* MAC Address */
+ uint8 ac_cat; /* Access Category */
+ uint8 num_pkts; /* Number of packet entries to be averaged */
+} wl_mac_ratehisto_cmd_t; /* MAC Specific Rate Histogram command */
+
+/* Get MAC rate histogram response */
+typedef struct {
+ uint32 rate[DOT11_RATE_MAX + 1]; /* Rates */
+ uint32 mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX]; /* MCS counts */
+ uint32 vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX]; /* VHT counts */
+ uint32 tsf_timer[2][2]; /* Start and End time for 8bytes value */
+} wl_mac_ratehisto_res_t; /* MAC Specific Rate Histogram Response */
+
+/* Linux network driver ioctl encoding */
+typedef struct wl_ioctl {
+ uint cmd; /* common ioctl definition */
+ void *buf; /* pointer to user buffer */
+ uint len; /* length of user buffer */
+ uint8 set; /* 1=set IOCTL; 0=query IOCTL */
+ uint used; /* bytes read or written (optional) */
+ uint needed; /* bytes needed (optional) */
+} wl_ioctl_t;
+#ifdef CONFIG_COMPAT
+typedef struct compat_wl_ioctl {
+ uint cmd; /* common ioctl definition */
+ uint32 buf; /* pointer to user buffer */
+ uint len; /* length of user buffer */
+ uint8 set; /* 1=set IOCTL; 0=query IOCTL */
+ uint used; /* bytes read or written (optional) */
+ uint needed; /* bytes needed (optional) */
+} compat_wl_ioctl_t;
+#endif /* CONFIG_COMPAT */
+
+
+/*
+ * Structure for passing hardware and software
+ * revision info up from the driver.
+ */
+typedef struct wlc_rev_info {
+ uint vendorid; /* PCI vendor id */
+ uint deviceid; /* device id of chip */
+ uint radiorev; /* radio revision */
+ uint chiprev; /* chip revision */
+ uint corerev; /* core revision */
+ uint boardid; /* board identifier (usu. PCI sub-device id) */
+ uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */
+ uint boardrev; /* board revision */
+ uint driverrev; /* driver version */
+ uint ucoderev; /* microcode version */
+ uint bus; /* bus type */
+ uint chipnum; /* chip number */
+ uint phytype; /* phy type */
+ uint phyrev; /* phy revision */
+ uint anarev; /* anacore rev */
+ uint chippkg; /* chip package info */
+ uint nvramrev; /* nvram revision number */
+} wlc_rev_info_t;
+
+#define WL_REV_INFO_LEGACY_LENGTH 48
+
+#define WL_BRAND_MAX 10
+typedef struct wl_instance_info {
+ uint instance;
+ char brand[WL_BRAND_MAX];
+} wl_instance_info_t;
+
+/* structure to change size of tx fifo */
+typedef struct wl_txfifo_sz {
+ uint16 magic;
+ uint16 fifo;
+ uint16 size;
+} wl_txfifo_sz_t;
+
+/* Transfer info about an IOVar from the driver */
+/* Max supported IOV name size in bytes, + 1 for nul termination */
+#define WLC_IOV_NAME_LEN 30
+typedef struct wlc_iov_trx_s {
+ uint8 module;
+ uint8 type;
+ char name[WLC_IOV_NAME_LEN];
+} wlc_iov_trx_t;
+
+/* bump this number if you change the ioctl interface */
+#define WLC_IOCTL_VERSION 2
+#define WLC_IOCTL_VERSION_LEGACY_IOTYPES 1
+
+#ifdef CONFIG_USBRNDIS_RETAIL
+/* struct passed in for WLC_NDCONFIG_ITEM */
+typedef struct {
+ char *name;
+ void *param;
+} ndconfig_item_t;
+#endif
+
+
+#define WL_PHY_PAVARS_LEN 32 /* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */
+
+#define WL_PHY_PAVAR_VER 1 /* pavars version */
+#define WL_PHY_PAVARS2_NUM 3 /* a1, b0, b1 */
+typedef struct wl_pavars2 {
+ uint16 ver; /* version of this struct */
+ uint16 len; /* len of this structure */
+ uint16 inuse; /* driver return 1 for a1,b0,b1 in current band range */
+ uint16 phy_type; /* phy type */
+ uint16 bandrange;
+ uint16 chain;
+ uint16 inpa[WL_PHY_PAVARS2_NUM]; /* phy pavars for one band range */
+} wl_pavars2_t;
+
+typedef struct wl_po {
+ uint16 phy_type; /* Phy type */
+ uint16 band;
+ uint16 cckpo;
+ uint32 ofdmpo;
+ uint16 mcspo[8];
+} wl_po_t;
+
+#define WL_NUM_RPCALVARS 5 /* number of rpcal vars */
+
+typedef struct wl_rpcal {
+ uint16 value;
+ uint16 update;
+} wl_rpcal_t;
+
+typedef struct wl_aci_args {
+ int enter_aci_thresh; /* Trigger level to start detecting ACI */
+ int exit_aci_thresh; /* Trigger level to exit ACI mode */
+ int usec_spin; /* microsecs to delay between rssi samples */
+ int glitch_delay; /* interval between ACI scans when glitch count is consistently high */
+ uint16 nphy_adcpwr_enter_thresh; /* ADC power to enter ACI mitigation mode */
+ uint16 nphy_adcpwr_exit_thresh; /* ADC power to exit ACI mitigation mode */
+ uint16 nphy_repeat_ctr; /* Number of tries per channel to compute power */
+ uint16 nphy_num_samples; /* Number of samples to compute power on one channel */
+ uint16 nphy_undetect_window_sz; /* num of undetects to exit ACI Mitigation mode */
+ uint16 nphy_b_energy_lo_aci; /* low ACI power energy threshold for bphy */
+ uint16 nphy_b_energy_md_aci; /* mid ACI power energy threshold for bphy */
+ uint16 nphy_b_energy_hi_aci; /* high ACI power energy threshold for bphy */
+ uint16 nphy_noise_noassoc_glitch_th_up; /* wl interference 4 */
+ uint16 nphy_noise_noassoc_glitch_th_dn;
+ uint16 nphy_noise_assoc_glitch_th_up;
+ uint16 nphy_noise_assoc_glitch_th_dn;
+ uint16 nphy_noise_assoc_aci_glitch_th_up;
+ uint16 nphy_noise_assoc_aci_glitch_th_dn;
+ uint16 nphy_noise_assoc_enter_th;
+ uint16 nphy_noise_noassoc_enter_th;
+ uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th;
+ uint16 nphy_noise_noassoc_crsidx_incr;
+ uint16 nphy_noise_assoc_crsidx_incr;
+ uint16 nphy_noise_crsidx_decr;
+} wl_aci_args_t;
+
+#define WL_ACI_ARGS_LEGACY_LENGTH 16 /* bytes of pre NPHY aci args */
+#define WL_SAMPLECOLLECT_T_VERSION 2 /* version of wl_samplecollect_args_t struct */
+typedef struct wl_samplecollect_args {
+ /* version 0 fields */
+ uint8 coll_us;
+ int cores;
+ /* add'l version 1 fields */
+ uint16 version; /* see definition of WL_SAMPLECOLLECT_T_VERSION */
+ uint16 length; /* length of entire structure */
+ int8 trigger;
+ uint16 timeout;
+ uint16 mode;
+ uint32 pre_dur;
+ uint32 post_dur;
+ uint8 gpio_sel;
+ uint8 downsamp;
+ uint8 be_deaf;
+ uint8 agc; /* loop from init gain and going down */
+ uint8 filter; /* override high pass corners to lowest */
+ /* add'l version 2 fields */
+ uint8 trigger_state;
+ uint8 module_sel1;
+ uint8 module_sel2;
+ uint16 nsamps;
+ int bitStart;
+ uint32 gpioCapMask;
+} wl_samplecollect_args_t;
+
+#define WL_SAMPLEDATA_T_VERSION 1 /* version of wl_samplecollect_args_t struct */
+/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */
+#define WL_SAMPLEDATA_T_VERSION_SPEC_AN 2
+
+typedef struct wl_sampledata {
+ uint16 version; /* structure version */
+ uint16 size; /* size of structure */
+ uint16 tag; /* Header/Data */
+ uint16 length; /* data length */
+ uint32 flag; /* bit def */
+} wl_sampledata_t;
+
+
+/* WL_OTA START */
+/* OTA Test Status */
+enum {
+ WL_OTA_TEST_IDLE = 0, /* Default Idle state */
+ WL_OTA_TEST_ACTIVE = 1, /* Test Running */
+ WL_OTA_TEST_SUCCESS = 2, /* Successfully Finished Test */
+ WL_OTA_TEST_FAIL = 3 /* Test Failed in the Middle */
+};
+/* OTA SYNC Status */
+enum {
+ WL_OTA_SYNC_IDLE = 0, /* Idle state */
+ WL_OTA_SYNC_ACTIVE = 1, /* Waiting for Sync */
+ WL_OTA_SYNC_FAIL = 2 /* Sync pkt not recieved */
+};
+
+/* Various error states dut can get stuck during test */
+enum {
+ WL_OTA_SKIP_TEST_CAL_FAIL = 1, /* Phy calibration failed */
+ WL_OTA_SKIP_TEST_SYNCH_FAIL = 2, /* Sync Packet not recieved */
+ WL_OTA_SKIP_TEST_FILE_DWNLD_FAIL = 3, /* Cmd flow file download failed */
+ WL_OTA_SKIP_TEST_NO_TEST_FOUND = 4, /* No test found in Flow file */
+ WL_OTA_SKIP_TEST_WL_NOT_UP = 5, /* WL UP failed */
+ WL_OTA_SKIP_TEST_UNKNOWN_CALL /* Unintentional scheduling on ota test */
+};
+
+/* Differentiator for ota_tx and ota_rx */
+enum {
+ WL_OTA_TEST_TX = 0, /* ota_tx */
+ WL_OTA_TEST_RX = 1, /* ota_rx */
+};
+
+/* Catch 3 modes of operation: 20Mhz, 40Mhz, 20 in 40 Mhz */
+enum {
+ WL_OTA_TEST_BW_20_IN_40MHZ = 0, /* 20 in 40 operation */
+ WL_OTA_TEST_BW_20MHZ = 1, /* 20 Mhz operation */
+ WL_OTA_TEST_BW_40MHZ = 2 /* full 40Mhz operation */
+};
+typedef struct ota_rate_info {
+ uint8 rate_cnt; /* Total number of rates */
+ uint8 rate_val_mbps[WL_OTA_TEST_MAX_NUM_RATE]; /* array of rates from 1mbps to 130mbps */
+ /* for legacy rates : ratein mbps * 2 */
+ /* for HT rates : mcs index */
+} ota_rate_info_t;
+
+typedef struct ota_power_info {
+ int8 pwr_ctrl_on; /* power control on/off */
+ int8 start_pwr; /* starting power/index */
+ int8 delta_pwr; /* delta power/index */
+ int8 end_pwr; /* end power/index */
+} ota_power_info_t;
+
+typedef struct ota_packetengine {
+ uint16 delay; /* Inter-packet delay */
+ /* for ota_tx, delay is tx ifs in micro seconds */
+ /* for ota_rx, delay is wait time in milliseconds */
+ uint16 nframes; /* Number of frames */
+ uint16 length; /* Packet length */
+} ota_packetengine_t;
+
+/* Test info vector */
+typedef struct wl_ota_test_args {
+ uint8 cur_test; /* test phase */
+ uint8 chan; /* channel */
+ uint8 bw; /* bandwidth */
+ uint8 control_band; /* control band */
+ uint8 stf_mode; /* stf mode */
+ ota_rate_info_t rt_info; /* Rate info */
+ ota_packetengine_t pkteng; /* packeteng info */
+ uint8 txant; /* tx antenna */
+ uint8 rxant; /* rx antenna */
+ ota_power_info_t pwr_info; /* power sweep info */
+ uint8 wait_for_sync; /* wait for sync or not */
+} wl_ota_test_args_t;
+
+typedef struct wl_ota_test_vector {
+ wl_ota_test_args_t test_arg[WL_OTA_TEST_MAX_NUM_SEQ]; /* Test argument struct */
+ uint16 test_cnt; /* Total no of test */
+ uint8 file_dwnld_valid; /* File successfully downloaded */
+ uint8 sync_timeout; /* sync packet timeout */
+ int8 sync_fail_action; /* sync fail action */
+ struct ether_addr sync_mac; /* macaddress for sync pkt */
+ struct ether_addr tx_mac; /* macaddress for tx */
+ struct ether_addr rx_mac; /* macaddress for rx */
+ int8 loop_test; /* dbg feature to loop the test */
+} wl_ota_test_vector_t;
+
+
+/* struct copied back form dongle to host to query the status */
+typedef struct wl_ota_test_status {
+ int16 cur_test_cnt; /* test phase */
+ int8 skip_test_reason; /* skip test reasoin */
+ wl_ota_test_args_t test_arg; /* cur test arg details */
+ uint16 test_cnt; /* total no of test downloaded */
+ uint8 file_dwnld_valid; /* file successfully downloaded ? */
+ uint8 sync_timeout; /* sync timeout */
+ int8 sync_fail_action; /* sync fail action */
+ struct ether_addr sync_mac; /* macaddress for sync pkt */
+ struct ether_addr tx_mac; /* tx mac address */
+ struct ether_addr rx_mac; /* rx mac address */
+ uint8 test_stage; /* check the test status */
+ int8 loop_test; /* Debug feature to puts test enfine in a loop */
+ uint8 sync_status; /* sync status */
+} wl_ota_test_status_t;
+
+/* WL_OTA END */
+
+/* wl_radar_args_t */
+typedef struct {
+ int npulses; /* required number of pulses at n * t_int */
+ int ncontig; /* required number of pulses at t_int */
+ int min_pw; /* minimum pulse width (20 MHz clocks) */
+ int max_pw; /* maximum pulse width (20 MHz clocks) */
+ uint16 thresh0; /* Radar detection, thresh 0 */
+ uint16 thresh1; /* Radar detection, thresh 1 */
+ uint16 blank; /* Radar detection, blank control */
+ uint16 fmdemodcfg; /* Radar detection, fmdemod config */
+ int npulses_lp; /* Radar detection, minimum long pulses */
+ int min_pw_lp; /* Minimum pulsewidth for long pulses */
+ int max_pw_lp; /* Maximum pulsewidth for long pulses */
+ int min_fm_lp; /* Minimum fm for long pulses */
+ int max_span_lp; /* Maximum deltat for long pulses */
+ int min_deltat; /* Minimum spacing between pulses */
+ int max_deltat; /* Maximum spacing between pulses */
+ uint16 autocorr; /* Radar detection, autocorr on or off */
+ uint16 st_level_time; /* Radar detection, start_timing level */
+ uint16 t2_min; /* minimum clocks needed to remain in state 2 */
+ uint32 version; /* version */
+ uint32 fra_pulse_err; /* sample error margin for detecting French radar pulsed */
+ int npulses_fra; /* Radar detection, minimum French pulses set */
+ int npulses_stg2; /* Radar detection, minimum staggered-2 pulses set */
+ int npulses_stg3; /* Radar detection, minimum staggered-3 pulses set */
+ uint16 percal_mask; /* defines which period cal is masked from radar detection */
+ int quant; /* quantization resolution to pulse positions */
+ uint32 min_burst_intv_lp; /* minimum burst to burst interval for bin3 radar */
+ uint32 max_burst_intv_lp; /* maximum burst to burst interval for bin3 radar */
+ int nskip_rst_lp; /* number of skipped pulses before resetting lp buffer */
+ int max_pw_tol; /* maximum tollerance allowed in detected pulse width for radar detection */
+ uint16 feature_mask; /* 16-bit mask to specify enabled features */
+} wl_radar_args_t;
+
+#define WL_RADAR_ARGS_VERSION 2
+
+typedef struct {
+ uint32 version; /* version */
+ uint16 thresh0_20_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */
+ uint16 thresh1_20_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */
+ uint16 thresh0_40_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */
+ uint16 thresh1_40_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */
+ uint16 thresh0_80_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */
+ uint16 thresh1_80_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */
+ uint16 thresh0_20_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */
+ uint16 thresh1_20_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */
+ uint16 thresh0_40_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */
+ uint16 thresh1_40_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */
+ uint16 thresh0_80_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */
+ uint16 thresh1_80_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */
+#ifdef WL11AC160
+ uint16 thresh0_160_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */
+ uint16 thresh1_160_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */
+ uint16 thresh0_160_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */
+ uint16 thresh1_160_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */
+#endif /* WL11AC160 */
+} wl_radar_thr_t;
+
+#define WL_RADAR_THR_VERSION 2
+
+/* RSSI per antenna */
+typedef struct {
+ uint32 version; /* version field */
+ uint32 count; /* number of valid antenna rssi */
+ int8 rssi_ant[WL_RSSI_ANT_MAX]; /* rssi per antenna */
+} wl_rssi_ant_t;
+
+/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */
+typedef struct {
+ uint state; /* noted by WL_DFS_CACSTATE_XX. */
+ uint duration; /* time spent in ms in state. */
+ /* as dfs enters ISM state, it removes the operational channel from quiet channel
+ * list and notes the channel in channel_cleared. set to 0 if no channel is cleared
+ */
+ chanspec_t chanspec_cleared;
+ /* chanspec cleared used to be a uint, add another to uint16 to maintain size */
+ uint16 pad;
+} wl_dfs_status_t;
+
+/* data structure used in 'radar_status' wl interface, which is use to query radar det status */
+typedef struct {
+ bool detected;
+ int count;
+ bool pretended;
+ uint32 radartype;
+ uint32 timenow;
+ uint32 timefromL;
+ int lp_csect_single;
+ int detected_pulse_index;
+ int nconsecq_pulses;
+ chanspec_t ch;
+ int pw[10];
+ int intv[10];
+ int fm[10];
+} wl_radar_status_t;
+
+#define NUM_PWRCTRL_RATES 12
+
+typedef struct {
+ uint8 txpwr_band_max[NUM_PWRCTRL_RATES]; /* User set target */
+ uint8 txpwr_limit[NUM_PWRCTRL_RATES]; /* reg and local power limit */
+ uint8 txpwr_local_max; /* local max according to the AP */
+ uint8 txpwr_local_constraint; /* local constraint according to the AP */
+ uint8 txpwr_chan_reg_max; /* Regulatory max for this channel */
+ uint8 txpwr_target[2][NUM_PWRCTRL_RATES]; /* Latest target for 2.4 and 5 Ghz */
+ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */
+ uint8 txpwr_opo[NUM_PWRCTRL_RATES]; /* On G phy, OFDM power offset */
+ uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES]; /* Max CCK power for this band (SROM) */
+ uint8 txpwr_bphy_ofdm_max; /* Max OFDM power for this band (SROM) */
+ uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES]; /* Max power for A band (SROM) */
+ int8 txpwr_antgain[2]; /* Ant gain for each band - from SROM */
+ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */
+} tx_power_legacy_t;
+
+#define WL_TX_POWER_RATES_LEGACY 45
+#define WL_TX_POWER_MCS20_FIRST 12
+#define WL_TX_POWER_MCS20_NUM 16
+#define WL_TX_POWER_MCS40_FIRST 28
+#define WL_TX_POWER_MCS40_NUM 17
+
+typedef struct {
+ uint32 flags;
+ chanspec_t chanspec; /* txpwr report for this channel */
+ chanspec_t local_chanspec; /* channel on which we are associated */
+ uint8 local_max; /* local max according to the AP */
+ uint8 local_constraint; /* local constraint according to the AP */
+ int8 antgain[2]; /* Ant gain for each band - from SROM */
+ uint8 rf_cores; /* count of RF Cores being reported */
+ uint8 est_Pout[4]; /* Latest tx power out estimate per RF
+ * chain without adjustment
+ */
+ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */
+ uint8 user_limit[WL_TX_POWER_RATES_LEGACY]; /* User limit */
+ uint8 reg_limit[WL_TX_POWER_RATES_LEGACY]; /* Regulatory power limit */
+ uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */
+ uint8 target[WL_TX_POWER_RATES_LEGACY]; /* Latest target power */
+} tx_power_legacy2_t;
+
+/* TX Power index defines */
+#define WL_NUM_RATES_CCK 4 /* 1, 2, 5.5, 11 Mbps */
+#define WL_NUM_RATES_OFDM 8 /* 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */
+#define WL_NUM_RATES_MCS_1STREAM 8 /* MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */
+#define WL_NUM_RATES_EXTRA_VHT 2 /* Additional VHT 11AC rates */
+#define WL_NUM_RATES_VHT 10
+#define WL_NUM_RATES_MCS32 1
+
+#define WLC_NUM_RATES_CCK WL_NUM_RATES_CCK
+#define WLC_NUM_RATES_OFDM WL_NUM_RATES_OFDM
+#define WLC_NUM_RATES_MCS_1_STREAM WL_NUM_RATES_MCS_1STREAM
+#define WLC_NUM_RATES_MCS_2_STREAM WL_NUM_RATES_MCS_1STREAM
+#define WLC_NUM_RATES_MCS32 WL_NUM_RATES_MCS32
+#define WL_TX_POWER_CCK_NUM WL_NUM_RATES_CCK
+#define WL_TX_POWER_OFDM_NUM WL_NUM_RATES_OFDM
+#define WL_TX_POWER_MCS_1_STREAM_NUM WL_NUM_RATES_MCS_1STREAM
+#define WL_TX_POWER_MCS_2_STREAM_NUM WL_NUM_RATES_MCS_1STREAM
+#define WL_TX_POWER_MCS_32_NUM WL_NUM_RATES_MCS32
+
+#define WL_NUM_2x2_ELEMENTS 4
+#define WL_NUM_3x3_ELEMENTS 6
+
+typedef struct {
+ uint16 ver; /* version of this struct */
+ uint16 len; /* length in bytes of this structure */
+ uint32 flags;
+ chanspec_t chanspec; /* txpwr report for this channel */
+ chanspec_t local_chanspec; /* channel on which we are associated */
+ uint32 buflen; /* ppr buffer length */
+ uint8 pprbuf[1]; /* Latest target power buffer */
+} wl_txppr_t;
+
+#define WL_TXPPR_VERSION 1
+#define WL_TXPPR_LENGTH (sizeof(wl_txppr_t))
+#define TX_POWER_T_VERSION 44
+
+
+typedef struct tx_inst_power {
+ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */
+ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */
+} tx_inst_power_t;
+
+#define WL_NUM_TXCHAIN_MAX 4
+typedef struct wl_txchain_pwr_offsets {
+ int8 offset[WL_NUM_TXCHAIN_MAX]; /* quarter dBm signed offset for each chain */
+} wl_txchain_pwr_offsets_t;
+/* maximum channels returned by the get valid channels iovar */
+#define WL_NUMCHANNELS 64
+
+/*
+ * Join preference iovar value is an array of tuples. Each tuple has a one-byte type,
+ * a one-byte length, and a variable length value. RSSI type tuple must be present
+ * in the array.
+ *
+ * Types are defined in "join preference types" section.
+ *
+ * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple
+ * and must be set to zero.
+ *
+ * Values are defined below.
+ *
+ * 1. RSSI - 2 octets
+ * offset 0: reserved
+ * offset 1: reserved
+ *
+ * 2. WPA - 2 + 12 * n octets (n is # tuples defined below)
+ * offset 0: reserved
+ * offset 1: # of tuples
+ * offset 2: tuple 1
+ * offset 14: tuple 2
+ * ...
+ * offset 2 + 12 * (n - 1) octets: tuple n
+ *
+ * struct wpa_cfg_tuple {
+ * uint8 akm[DOT11_OUI_LEN+1]; akm suite
+ * uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite
+ * uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite
+ * };
+ *
+ * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY.
+ *
+ * 3. BAND - 2 octets
+ * offset 0: reserved
+ * offset 1: see "band preference" and "band types"
+ *
+ * 4. BAND RSSI - 2 octets
+ * offset 0: band types
+ * offset 1: +ve RSSI boost value in dB
+ */
+
+struct tsinfo_arg {
+ uint8 octets[3];
+};
+
+#define NFIFO 6 /* # tx/rx fifopairs */
+#define NREINITREASONCOUNT 8
+#define REINITREASONIDX(_x) (((_x) < NREINITREASONCOUNT) ? (_x) : 0)
+
+#define WL_CNT_T_VERSION 10 /* current version of wl_cnt_t struct */
+
+typedef struct {
+ uint16 version; /* see definition of WL_CNT_T_VERSION */
+ uint16 length; /* length of entire structure */
+
+ /* transmit stat counters */
+ uint32 txframe; /* tx data frames */
+ uint32 txbyte; /* tx data bytes */
+ uint32 txretrans; /* tx mac retransmits */
+ uint32 txerror; /* tx data errors (derived: sum of others) */
+ uint32 txctl; /* tx management frames */
+ uint32 txprshort; /* tx short preamble frames */
+ uint32 txserr; /* tx status errors */
+ uint32 txnobuf; /* tx out of buffers errors */
+ uint32 txnoassoc; /* tx discard because we're not associated */
+ uint32 txrunt; /* tx runt frames */
+ uint32 txchit; /* tx header cache hit (fastpath) */
+ uint32 txcmiss; /* tx header cache miss (slowpath) */
+
+ /* transmit chip error counters */
+ uint32 txuflo; /* tx fifo underflows */
+ uint32 txphyerr; /* tx phy errors (indicated in tx status) */
+ uint32 txphycrs;
+
+ /* receive stat counters */
+ uint32 rxframe; /* rx data frames */
+ uint32 rxbyte; /* rx data bytes */
+ uint32 rxerror; /* rx data errors (derived: sum of others) */
+ uint32 rxctl; /* rx management frames */
+ uint32 rxnobuf; /* rx out of buffers errors */
+ uint32 rxnondata; /* rx non data frames in the data channel errors */
+ uint32 rxbadds; /* rx bad DS errors */
+ uint32 rxbadcm; /* rx bad control or management frames */
+ uint32 rxfragerr; /* rx fragmentation errors */
+ uint32 rxrunt; /* rx runt frames */
+ uint32 rxgiant; /* rx giant frames */
+ uint32 rxnoscb; /* rx no scb error */
+ uint32 rxbadproto; /* rx invalid frames */
+ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */
+ uint32 rxbadda; /* rx frames tossed for invalid da */
+ uint32 rxfilter; /* rx frames filtered out */
+
+ /* receive chip error counters */
+ uint32 rxoflo; /* rx fifo overflow errors */
+ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */
+
+ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */
+ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */
+ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */
+
+ /* misc counters */
+ uint32 dmade; /* tx/rx dma descriptor errors */
+ uint32 dmada; /* tx/rx dma data errors */
+ uint32 dmape; /* tx/rx dma descriptor protocol errors */
+ uint32 reset; /* reset count */
+ uint32 tbtt; /* cnts the TBTT int's */
+ uint32 txdmawar;
+ uint32 pkt_callback_reg_fail; /* callbacks register failure */
+
+ /* MAC counters: 32-bit version of d11.h's macstat_t */
+ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS,
+ * Control Management (includes retransmissions)
+ */
+ uint32 txrtsfrm; /* number of RTS sent out by the MAC */
+ uint32 txctsfrm; /* number of CTS sent out by the MAC */
+ uint32 txackfrm; /* number of ACK frames sent out */
+ uint32 txdnlfrm; /* Not used */
+ uint32 txbcnfrm; /* beacons transmitted */
+ uint32 txfunfl[6]; /* per-fifo tx underflows */
+ uint32 rxtoolate; /* receive too late */
+ uint32 txfbw; /* transmit at fallback bw (dynamic bw) */
+ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS
+ * or BCN)
+ */
+ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for
+ * driver enqueued frames
+ */
+ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */
+ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */
+ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not
+ * data/control/management
+ */
+ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */
+ uint32 rxbadplcp; /* parity check of the PLCP header failed */
+ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */
+ uint32 rxstrt; /* Number of received frames with a good PLCP
+ * (i.e. passing parity check)
+ */
+ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
+ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
+ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */
+ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */
+ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */
+ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */
+ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */
+ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */
+ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */
+ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */
+ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */
+ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */
+ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */
+ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC
+ * (unlikely to see these)
+ */
+ uint32 rxbeaconmbss; /* beacons received from member of BSS */
+ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from
+ * other BSS (WDS FRAME)
+ */
+ uint32 rxbeaconobss; /* beacons received from other BSS */
+ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames
+ * expecting a response
+ */
+ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */
+ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */
+ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */
+ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */
+ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */
+ uint32 pmqovfl; /* Number of PMQ overflows */
+ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into
+ * the PRQ fifo
+ */
+ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */
+ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did
+ * not get ACK
+ */
+ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */
+ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ
+ * fifo because a probe response could not be sent out within
+ * the time limit defined in M_PRS_MAXTIME
+ */
+ uint32 rxnack; /* obsolete */
+ uint32 frmscons; /* obsolete */
+ uint32 txnack; /* obsolete */
+ uint32 rxback; /* blockack rxcnt */
+ uint32 txback; /* blockack txcnt */
+
+ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+ uint32 txfrag; /* dot11TransmittedFragmentCount */
+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */
+ uint32 txfail; /* dot11FailedCount */
+ uint32 txretry; /* dot11RetryCount */
+ uint32 txretrie; /* dot11MultipleRetryCount */
+ uint32 rxdup; /* dot11FrameduplicateCount */
+ uint32 txrts; /* dot11RTSSuccessCount */
+ uint32 txnocts; /* dot11RTSFailureCount */
+ uint32 txnoack; /* dot11ACKFailureCount */
+ uint32 rxfrag; /* dot11ReceivedFragmentCount */
+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */
+ uint32 rxcrc; /* dot11FCSErrorCount */
+ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */
+ uint32 rxundec; /* dot11WEPUndecryptableCount */
+
+ /* WPA2 counters (see rxundec for DecryptFailureCount) */
+ uint32 tkipmicfaill; /* TKIPLocalMICFailures */
+ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */
+ uint32 tkipreplay; /* TKIPReplays */
+ uint32 ccmpfmterr; /* CCMPFormatErrors */
+ uint32 ccmpreplay; /* CCMPReplays */
+ uint32 ccmpundec; /* CCMPDecryptErrors */
+ uint32 fourwayfail; /* FourWayHandshakeFailures */
+ uint32 wepundec; /* dot11WEPUndecryptableCount */
+ uint32 wepicverr; /* dot11WEPICVErrorCount */
+ uint32 decsuccess; /* DecryptSuccessCount */
+ uint32 tkipicverr; /* TKIPICVErrorCount */
+ uint32 wepexcluded; /* dot11WEPExcludedCount */
+
+ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */
+ uint32 psmwds; /* Count PSM watchdogs */
+ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */
+
+ /* MBSS counters, AP only */
+ uint32 prq_entries_handled; /* PRQ entries read in */
+ uint32 prq_undirected_entries; /* which were bcast bss & ssid */
+ uint32 prq_bad_entries; /* which could not be translated to info */
+ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */
+ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */
+ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */
+ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */
+
+ /* per-rate receive stat counters */
+ uint32 rx1mbps; /* packets rx at 1Mbps */
+ uint32 rx2mbps; /* packets rx at 2Mbps */
+ uint32 rx5mbps5; /* packets rx at 5.5Mbps */
+ uint32 rx6mbps; /* packets rx at 6Mbps */
+ uint32 rx9mbps; /* packets rx at 9Mbps */
+ uint32 rx11mbps; /* packets rx at 11Mbps */
+ uint32 rx12mbps; /* packets rx at 12Mbps */
+ uint32 rx18mbps; /* packets rx at 18Mbps */
+ uint32 rx24mbps; /* packets rx at 24Mbps */
+ uint32 rx36mbps; /* packets rx at 36Mbps */
+ uint32 rx48mbps; /* packets rx at 48Mbps */
+ uint32 rx54mbps; /* packets rx at 54Mbps */
+ uint32 rx108mbps; /* packets rx at 108mbps */
+ uint32 rx162mbps; /* packets rx at 162mbps */
+ uint32 rx216mbps; /* packets rx at 216 mbps */
+ uint32 rx270mbps; /* packets rx at 270 mbps */
+ uint32 rx324mbps; /* packets rx at 324 mbps */
+ uint32 rx378mbps; /* packets rx at 378 mbps */
+ uint32 rx432mbps; /* packets rx at 432 mbps */
+ uint32 rx486mbps; /* packets rx at 486 mbps */
+ uint32 rx540mbps; /* packets rx at 540 mbps */
+
+ /* pkteng rx frame stats */
+ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */
+ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */
+
+ uint32 rfdisable; /* count of radio disables */
+ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */
+ uint32 bphy_badplcp;
+
+ uint32 txexptime; /* Tx frames suppressed due to timer expiration */
+
+ uint32 txmpdu_sgi; /* count for sgi transmit */
+ uint32 rxmpdu_sgi; /* count for sgi received */
+ uint32 txmpdu_stbc; /* count for stbc transmit */
+ uint32 rxmpdu_stbc; /* count for stbc received */
+
+ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */
+
+ /* WPA2 counters (see rxundec for DecryptFailureCount) */
+ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */
+ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */
+ uint32 tkipreplay_mcst; /* TKIPReplays */
+ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */
+ uint32 ccmpreplay_mcst; /* CCMPReplays */
+ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */
+ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */
+ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */
+ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */
+ uint32 decsuccess_mcst; /* DecryptSuccessCount */
+ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */
+ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */
+
+ uint32 dma_hang; /* count for dma hang */
+ uint32 reinit; /* count for reinit */
+
+ uint32 pstatxucast; /* count of ucast frames xmitted on all psta assoc */
+ uint32 pstatxnoassoc; /* count of txnoassoc frames xmitted on all psta assoc */
+ uint32 pstarxucast; /* count of ucast frames received on all psta assoc */
+ uint32 pstarxbcmc; /* count of bcmc frames received on all psta */
+ uint32 pstatxbcmc; /* count of bcmc frames transmitted on all psta */
+
+ uint32 cso_passthrough; /* hw cso required but passthrough */
+ uint32 cso_normal; /* hw cso hdr for normal process */
+ uint32 chained; /* number of frames chained */
+ uint32 chainedsz1; /* number of chain size 1 frames */
+ uint32 unchained; /* number of frames not chained */
+ uint32 maxchainsz; /* max chain size so far */
+ uint32 currchainsz; /* current chain size */
+ uint32 rxdrop20s; /* drop secondary cnt */
+ uint32 pciereset; /* Secondary Bus Reset issued by driver */
+ uint32 cfgrestore; /* configspace restore by driver */
+ uint32 reinitreason[NREINITREASONCOUNT]; /* reinitreason counters; 0: Unknown reason */
+} wl_cnt_t;
+
+typedef struct {
+ uint16 version; /* see definition of WL_CNT_T_VERSION */
+ uint16 length; /* length of entire structure */
+
+ /* transmit stat counters */
+ uint32 txframe; /* tx data frames */
+ uint32 txbyte; /* tx data bytes */
+ uint32 txretrans; /* tx mac retransmits */
+ uint32 txerror; /* tx data errors (derived: sum of others) */
+ uint32 txctl; /* tx management frames */
+ uint32 txprshort; /* tx short preamble frames */
+ uint32 txserr; /* tx status errors */
+ uint32 txnobuf; /* tx out of buffers errors */
+ uint32 txnoassoc; /* tx discard because we're not associated */
+ uint32 txrunt; /* tx runt frames */
+ uint32 txchit; /* tx header cache hit (fastpath) */
+ uint32 txcmiss; /* tx header cache miss (slowpath) */
+
+ /* transmit chip error counters */
+ uint32 txuflo; /* tx fifo underflows */
+ uint32 txphyerr; /* tx phy errors (indicated in tx status) */
+ uint32 txphycrs;
+
+ /* receive stat counters */
+ uint32 rxframe; /* rx data frames */
+ uint32 rxbyte; /* rx data bytes */
+ uint32 rxerror; /* rx data errors (derived: sum of others) */
+ uint32 rxctl; /* rx management frames */
+ uint32 rxnobuf; /* rx out of buffers errors */
+ uint32 rxnondata; /* rx non data frames in the data channel errors */
+ uint32 rxbadds; /* rx bad DS errors */
+ uint32 rxbadcm; /* rx bad control or management frames */
+ uint32 rxfragerr; /* rx fragmentation errors */
+ uint32 rxrunt; /* rx runt frames */
+ uint32 rxgiant; /* rx giant frames */
+ uint32 rxnoscb; /* rx no scb error */
+ uint32 rxbadproto; /* rx invalid frames */
+ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */
+ uint32 rxbadda; /* rx frames tossed for invalid da */
+ uint32 rxfilter; /* rx frames filtered out */
+
+ /* receive chip error counters */
+ uint32 rxoflo; /* rx fifo overflow errors */
+ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */
+
+ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */
+ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */
+ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */
+
+ /* misc counters */
+ uint32 dmade; /* tx/rx dma descriptor errors */
+ uint32 dmada; /* tx/rx dma data errors */
+ uint32 dmape; /* tx/rx dma descriptor protocol errors */
+ uint32 reset; /* reset count */
+ uint32 tbtt; /* cnts the TBTT int's */
+ uint32 txdmawar;
+ uint32 pkt_callback_reg_fail; /* callbacks register failure */
+
+ /* MAC counters: 32-bit version of d11.h's macstat_t */
+ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS,
+ * Control Management (includes retransmissions)
+ */
+ uint32 txrtsfrm; /* number of RTS sent out by the MAC */
+ uint32 txctsfrm; /* number of CTS sent out by the MAC */
+ uint32 txackfrm; /* number of ACK frames sent out */
+ uint32 txdnlfrm; /* Not used */
+ uint32 txbcnfrm; /* beacons transmitted */
+ uint32 txfunfl[6]; /* per-fifo tx underflows */
+ uint32 rxtoolate; /* receive too late */
+ uint32 txfbw; /* transmit at fallback bw (dynamic bw) */
+ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS
+ * or BCN)
+ */
+ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for
+ * driver enqueued frames
+ */
+ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */
+ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */
+ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not
+ * data/control/management
+ */
+ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */
+ uint32 rxbadplcp; /* parity check of the PLCP header failed */
+ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */
+ uint32 rxstrt; /* Number of received frames with a good PLCP
+ * (i.e. passing parity check)
+ */
+ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
+ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
+ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */
+ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */
+ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */
+ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */
+ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */
+ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */
+ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */
+ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */
+ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */
+ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */
+ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */
+ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC
+ * (unlikely to see these)
+ */
+ uint32 rxbeaconmbss; /* beacons received from member of BSS */
+ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from
+ * other BSS (WDS FRAME)
+ */
+ uint32 rxbeaconobss; /* beacons received from other BSS */
+ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames
+ * expecting a response
+ */
+ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */
+ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */
+ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */
+ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */
+ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */
+ uint32 pmqovfl; /* Number of PMQ overflows */
+ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into
+ * the PRQ fifo
+ */
+ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */
+ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did
+ * not get ACK
+ */
+ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */
+ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ
+ * fifo because a probe response could not be sent out within
+ * the time limit defined in M_PRS_MAXTIME
+ */
+ uint32 rxnack;
+ uint32 frmscons;
+ uint32 txnack; /* obsolete */
+ uint32 rxback; /* blockack rxcnt */
+ uint32 txback; /* blockack txcnt */
+
+ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+ uint32 txfrag; /* dot11TransmittedFragmentCount */
+ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */
+ uint32 txfail; /* dot11FailedCount */
+ uint32 txretry; /* dot11RetryCount */
+ uint32 txretrie; /* dot11MultipleRetryCount */
+ uint32 rxdup; /* dot11FrameduplicateCount */
+ uint32 txrts; /* dot11RTSSuccessCount */
+ uint32 txnocts; /* dot11RTSFailureCount */
+ uint32 txnoack; /* dot11ACKFailureCount */
+ uint32 rxfrag; /* dot11ReceivedFragmentCount */
+ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */
+ uint32 rxcrc; /* dot11FCSErrorCount */
+ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */
+ uint32 rxundec; /* dot11WEPUndecryptableCount */
+
+ /* WPA2 counters (see rxundec for DecryptFailureCount) */
+ uint32 tkipmicfaill; /* TKIPLocalMICFailures */
+ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */
+ uint32 tkipreplay; /* TKIPReplays */
+ uint32 ccmpfmterr; /* CCMPFormatErrors */
+ uint32 ccmpreplay; /* CCMPReplays */
+ uint32 ccmpundec; /* CCMPDecryptErrors */
+ uint32 fourwayfail; /* FourWayHandshakeFailures */
+ uint32 wepundec; /* dot11WEPUndecryptableCount */
+ uint32 wepicverr; /* dot11WEPICVErrorCount */
+ uint32 decsuccess; /* DecryptSuccessCount */
+ uint32 tkipicverr; /* TKIPICVErrorCount */
+ uint32 wepexcluded; /* dot11WEPExcludedCount */
+
+ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */
+
+ /* WPA2 counters (see rxundec for DecryptFailureCount) */
+ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */
+ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */
+ uint32 tkipreplay_mcst; /* TKIPReplays */
+ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */
+ uint32 ccmpreplay_mcst; /* CCMPReplays */
+ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */
+ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */
+ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */
+ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */
+ uint32 decsuccess_mcst; /* DecryptSuccessCount */
+ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */
+ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */
+
+ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */
+ uint32 txexptime; /* Tx frames suppressed due to timer expiration */
+ uint32 psmwds; /* Count PSM watchdogs */
+ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */
+
+ /* MBSS counters, AP only */
+ uint32 prq_entries_handled; /* PRQ entries read in */
+ uint32 prq_undirected_entries; /* which were bcast bss & ssid */
+ uint32 prq_bad_entries; /* which could not be translated to info */
+ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */
+ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */
+ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */
+ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */
+
+ /* per-rate receive stat counters */
+ uint32 rx1mbps; /* packets rx at 1Mbps */
+ uint32 rx2mbps; /* packets rx at 2Mbps */
+ uint32 rx5mbps5; /* packets rx at 5.5Mbps */
+ uint32 rx6mbps; /* packets rx at 6Mbps */
+ uint32 rx9mbps; /* packets rx at 9Mbps */
+ uint32 rx11mbps; /* packets rx at 11Mbps */
+ uint32 rx12mbps; /* packets rx at 12Mbps */
+ uint32 rx18mbps; /* packets rx at 18Mbps */
+ uint32 rx24mbps; /* packets rx at 24Mbps */
+ uint32 rx36mbps; /* packets rx at 36Mbps */
+ uint32 rx48mbps; /* packets rx at 48Mbps */
+ uint32 rx54mbps; /* packets rx at 54Mbps */
+ uint32 rx108mbps; /* packets rx at 108mbps */
+ uint32 rx162mbps; /* packets rx at 162mbps */
+ uint32 rx216mbps; /* packets rx at 216 mbps */
+ uint32 rx270mbps; /* packets rx at 270 mbps */
+ uint32 rx324mbps; /* packets rx at 324 mbps */
+ uint32 rx378mbps; /* packets rx at 378 mbps */
+ uint32 rx432mbps; /* packets rx at 432 mbps */
+ uint32 rx486mbps; /* packets rx at 486 mbps */
+ uint32 rx540mbps; /* packets rx at 540 mbps */
+
+ /* pkteng rx frame stats */
+ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */
+ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */
+
+ uint32 rfdisable; /* count of radio disables */
+ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */
+ uint32 bphy_badplcp;
+
+ uint32 txmpdu_sgi; /* count for sgi transmit */
+ uint32 rxmpdu_sgi; /* count for sgi received */
+ uint32 txmpdu_stbc; /* count for stbc transmit */
+ uint32 rxmpdu_stbc; /* count for stbc received */
+
+ uint32 rxdrop20s; /* drop secondary cnt */
+
+} wl_cnt_ver_six_t;
+
+#define WL_DELTA_STATS_T_VERSION 2 /* current version of wl_delta_stats_t struct */
+
+typedef struct {
+ uint16 version; /* see definition of WL_DELTA_STATS_T_VERSION */
+ uint16 length; /* length of entire structure */
+
+ /* transmit stat counters */
+ uint32 txframe; /* tx data frames */
+ uint32 txbyte; /* tx data bytes */
+ uint32 txretrans; /* tx mac retransmits */
+ uint32 txfail; /* tx failures */
+
+ /* receive stat counters */
+ uint32 rxframe; /* rx data frames */
+ uint32 rxbyte; /* rx data bytes */
+
+ /* per-rate receive stat counters */
+ uint32 rx1mbps; /* packets rx at 1Mbps */
+ uint32 rx2mbps; /* packets rx at 2Mbps */
+ uint32 rx5mbps5; /* packets rx at 5.5Mbps */
+ uint32 rx6mbps; /* packets rx at 6Mbps */
+ uint32 rx9mbps; /* packets rx at 9Mbps */
+ uint32 rx11mbps; /* packets rx at 11Mbps */
+ uint32 rx12mbps; /* packets rx at 12Mbps */
+ uint32 rx18mbps; /* packets rx at 18Mbps */
+ uint32 rx24mbps; /* packets rx at 24Mbps */
+ uint32 rx36mbps; /* packets rx at 36Mbps */
+ uint32 rx48mbps; /* packets rx at 48Mbps */
+ uint32 rx54mbps; /* packets rx at 54Mbps */
+ uint32 rx108mbps; /* packets rx at 108mbps */
+ uint32 rx162mbps; /* packets rx at 162mbps */
+ uint32 rx216mbps; /* packets rx at 216 mbps */
+ uint32 rx270mbps; /* packets rx at 270 mbps */
+ uint32 rx324mbps; /* packets rx at 324 mbps */
+ uint32 rx378mbps; /* packets rx at 378 mbps */
+ uint32 rx432mbps; /* packets rx at 432 mbps */
+ uint32 rx486mbps; /* packets rx at 486 mbps */
+ uint32 rx540mbps; /* packets rx at 540 mbps */
+
+ /* phy stats */
+ uint32 rxbadplcp;
+ uint32 rxcrsglitch;
+ uint32 bphy_rxcrsglitch;
+ uint32 bphy_badplcp;
+
+} wl_delta_stats_t;
+
+typedef struct {
+ uint32 packets;
+ uint32 bytes;
+} wl_traffic_stats_t;
+
+typedef struct {
+ uint16 version; /* see definition of WL_WME_CNT_VERSION */
+ uint16 length; /* length of entire structure */
+
+ wl_traffic_stats_t tx[AC_COUNT]; /* Packets transmitted */
+ wl_traffic_stats_t tx_failed[AC_COUNT]; /* Packets dropped or failed to transmit */
+ wl_traffic_stats_t rx[AC_COUNT]; /* Packets received */
+ wl_traffic_stats_t rx_failed[AC_COUNT]; /* Packets failed to receive */
+
+ wl_traffic_stats_t forward[AC_COUNT]; /* Packets forwarded by AP */
+
+ wl_traffic_stats_t tx_expired[AC_COUNT]; /* packets dropped due to lifetime expiry */
+
+} wl_wme_cnt_t;
+
+struct wl_msglevel2 {
+ uint32 low;
+ uint32 high;
+};
+
+typedef struct wl_mkeep_alive_pkt {
+ uint16 version; /* Version for mkeep_alive */
+ uint16 length; /* length of fixed parameters in the structure */
+ uint32 period_msec;
+ uint16 len_bytes;
+ uint8 keep_alive_id; /* 0 - 3 for N = 4 */
+ uint8 data[1];
+} wl_mkeep_alive_pkt_t;
+
+#define WL_MKEEP_ALIVE_VERSION 1
+#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data)
+#define WL_MKEEP_ALIVE_PRECISION 500
+
+/* TCP Keep-Alive conn struct */
+typedef struct wl_mtcpkeep_alive_conn_pkt {
+ struct ether_addr saddr; /* src mac address */
+ struct ether_addr daddr; /* dst mac address */
+ struct ipv4_addr sipaddr; /* source IP addr */
+ struct ipv4_addr dipaddr; /* dest IP addr */
+ uint16 sport; /* src port */
+ uint16 dport; /* dest port */
+ uint32 seq; /* seq number */
+ uint32 ack; /* ACK number */
+ uint16 tcpwin; /* TCP window */
+} wl_mtcpkeep_alive_conn_pkt_t;
+
+/* TCP Keep-Alive interval struct */
+typedef struct wl_mtcpkeep_alive_timers_pkt {
+ uint16 interval; /* interval timer */
+ uint16 retry_interval; /* retry_interval timer */
+ uint16 retry_count; /* retry_count */
+} wl_mtcpkeep_alive_timers_pkt_t;
+
+typedef struct wake_info {
+ uint32 wake_reason;
+ uint32 wake_info_len; /* size of packet */
+ uchar packet[1];
+} wake_info_t;
+
+typedef struct wake_pkt {
+ uint32 wake_pkt_len; /* size of packet */
+ uchar packet[1];
+} wake_pkt_t;
+
+
+#define WL_MTCPKEEP_ALIVE_VERSION 1
+
+#ifdef WLBA
+
+#define WLC_BA_CNT_VERSION 1 /* current version of wlc_ba_cnt_t */
+
+/* block ack related stats */
+typedef struct wlc_ba_cnt {
+ uint16 version; /* WLC_BA_CNT_VERSION */
+ uint16 length; /* length of entire structure */
+
+ /* transmit stat counters */
+ uint32 txpdu; /* pdus sent */
+ uint32 txsdu; /* sdus sent */
+ uint32 txfc; /* tx side flow controlled packets */
+ uint32 txfci; /* tx side flow control initiated */
+ uint32 txretrans; /* retransmitted pdus */
+ uint32 txbatimer; /* ba resend due to timer */
+ uint32 txdrop; /* dropped packets */
+ uint32 txaddbareq; /* addba req sent */
+ uint32 txaddbaresp; /* addba resp sent */
+ uint32 txdelba; /* delba sent */
+ uint32 txba; /* ba sent */
+ uint32 txbar; /* bar sent */
+ uint32 txpad[4]; /* future */
+
+ /* receive side counters */
+ uint32 rxpdu; /* pdus recd */
+ uint32 rxqed; /* pdus buffered before sending up */
+ uint32 rxdup; /* duplicate pdus */
+ uint32 rxnobuf; /* pdus discarded due to no buf */
+ uint32 rxaddbareq; /* addba req recd */
+ uint32 rxaddbaresp; /* addba resp recd */
+ uint32 rxdelba; /* delba recd */
+ uint32 rxba; /* ba recd */
+ uint32 rxbar; /* bar recd */
+ uint32 rxinvba; /* invalid ba recd */
+ uint32 rxbaholes; /* ba recd with holes */
+ uint32 rxunexp; /* unexpected packets */
+ uint32 rxpad[4]; /* future */
+} wlc_ba_cnt_t;
+#endif /* WLBA */
+
+/* structure for per-tid ampdu control */
+struct ampdu_tid_control {
+ uint8 tid; /* tid */
+ uint8 enable; /* enable/disable */
+};
+
+/* struct for per-tid, per-mode ampdu control */
+struct ampdu_tid_control_mode {
+ struct ampdu_tid_control control[NUMPRIO]; /* tid will be 0xff for not used element */
+ char mode_name[8]; /* supported mode : AIBSS */
+};
+
+/* structure for identifying ea/tid for sending addba/delba */
+struct ampdu_ea_tid {
+ struct ether_addr ea; /* Station address */
+ uint8 tid; /* tid */
+};
+/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */
+struct ampdu_retry_tid {
+ uint8 tid; /* tid */
+ uint8 retry; /* retry value */
+};
+
+/* structure for dpt iovars */
+typedef struct dpt_iovar {
+ struct ether_addr ea; /* Station address */
+ uint8 mode; /* mode: depends on iovar */
+ uint32 pad; /* future */
+} dpt_iovar_t;
+
+#define DPT_FNAME_LEN 48 /* Max length of friendly name */
+
+typedef struct dpt_status {
+ uint8 status; /* flags to indicate status */
+ uint8 fnlen; /* length of friendly name */
+ uchar name[DPT_FNAME_LEN]; /* friendly name */
+ uint32 rssi; /* RSSI of the link */
+ sta_info_t sta; /* sta info */
+} dpt_status_t;
+
+/* structure for dpt list */
+typedef struct dpt_list {
+ uint32 num; /* number of entries in struct */
+ dpt_status_t status[1]; /* per station info */
+} dpt_list_t;
+
+/* structure for dpt friendly name */
+typedef struct dpt_fname {
+ uint8 len; /* length of friendly name */
+ uchar name[DPT_FNAME_LEN]; /* friendly name */
+} dpt_fname_t;
+
+#define BDD_FNAME_LEN 32 /* Max length of friendly name */
+typedef struct bdd_fname {
+ uint8 len; /* length of friendly name */
+ uchar name[BDD_FNAME_LEN]; /* friendly name */
+} bdd_fname_t;
+
+/* structure for addts arguments */
+/* For ioctls that take a list of TSPEC */
+struct tslist {
+ int count; /* number of tspecs */
+ struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */
+};
+
+#ifdef WLTDLS
+/* structure for tdls iovars */
+typedef struct tdls_iovar {
+ struct ether_addr ea; /* Station address */
+ uint8 mode; /* mode: depends on iovar */
+ chanspec_t chanspec;
+ uint32 pad; /* future */
+} tdls_iovar_t;
+
+#define TDLS_WFD_IE_SIZE 512
+/* structure for tdls wfd ie */
+typedef struct tdls_wfd_ie_iovar {
+ struct ether_addr ea; /* Station address */
+ uint8 mode;
+ uint16 length;
+ uint8 data[TDLS_WFD_IE_SIZE];
+} tdls_wfd_ie_iovar_t;
+#endif /* WLTDLS */
+
+/* structure for addts/delts arguments */
+typedef struct tspec_arg {
+ uint16 version; /* see definition of TSPEC_ARG_VERSION */
+ uint16 length; /* length of entire structure */
+ uint flag; /* bit field */
+ /* TSPEC Arguments */
+ struct tsinfo_arg tsinfo; /* TS Info bit field */
+ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */
+ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */
+ uint min_srv_interval; /* Minimum Service Interval (us) */
+ uint max_srv_interval; /* Maximum Service Interval (us) */
+ uint inactivity_interval; /* Inactivity Interval (us) */
+ uint suspension_interval; /* Suspension Interval (us) */
+ uint srv_start_time; /* Service Start Time (us) */
+ uint min_data_rate; /* Minimum Data Rate (bps) */
+ uint mean_data_rate; /* Mean Data Rate (bps) */
+ uint peak_data_rate; /* Peak Data Rate (bps) */
+ uint max_burst_size; /* Maximum Burst Size (bytes) */
+ uint delay_bound; /* Delay Bound (us) */
+ uint min_phy_rate; /* Minimum PHY Rate (bps) */
+ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0 to 8.0) */
+ uint16 medium_time; /* Medium Time (32 us/s periods) */
+ uint8 dialog_token; /* dialog token */
+} tspec_arg_t;
+
+/* tspec arg for desired station */
+typedef struct tspec_per_sta_arg {
+ struct ether_addr ea;
+ struct tspec_arg ts;
+} tspec_per_sta_arg_t;
+
+/* structure for max bandwidth for each access category */
+typedef struct wme_max_bandwidth {
+ uint32 ac[AC_COUNT]; /* max bandwidth for each access category */
+} wme_max_bandwidth_t;
+
+#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t))
+
+/* current version of wl_tspec_arg_t struct */
+#define TSPEC_ARG_VERSION 2 /* current version of wl_tspec_arg_t struct */
+#define TSPEC_ARG_LENGTH 55 /* argument length from tsinfo to medium_time */
+#define TSPEC_DEFAULT_DIALOG_TOKEN 42 /* default dialog token */
+#define TSPEC_DEFAULT_SBW_FACTOR 0x3000 /* default surplus bw */
+
+
+#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE 80
+#define WLC_WOWL_MAX_KEEPALIVE 2
+
+/* Packet lifetime configuration per ac */
+typedef struct wl_lifetime {
+ uint32 ac; /* access class */
+ uint32 lifetime; /* Packet lifetime value in ms */
+} wl_lifetime_t;
+
+/* Channel Switch Announcement param */
+typedef struct wl_chan_switch {
+ uint8 mode; /* value 0 or 1 */
+ uint8 count; /* count # of beacons before switching */
+ chanspec_t chspec; /* chanspec */
+ uint8 reg; /* regulatory class */
+ uint8 frame_type; /* csa frame type, unicast or broadcast */
+} wl_chan_switch_t;
+
+enum {
+ PFN_LIST_ORDER,
+ PFN_RSSI
+};
+
+enum {
+ DISABLE,
+ ENABLE
+};
+
+enum {
+ OFF_ADAPT,
+ SMART_ADAPT,
+ STRICT_ADAPT,
+ SLOW_ADAPT
+};
+
+#define SORT_CRITERIA_BIT 0
+#define AUTO_NET_SWITCH_BIT 1
+#define ENABLE_BKGRD_SCAN_BIT 2
+#define IMMEDIATE_SCAN_BIT 3
+#define AUTO_CONNECT_BIT 4
+#define ENABLE_BD_SCAN_BIT 5
+#define ENABLE_ADAPTSCAN_BIT 6
+#define IMMEDIATE_EVENT_BIT 8
+#define SUPPRESS_SSID_BIT 9
+#define ENABLE_NET_OFFLOAD_BIT 10
+/* report found/lost events for SSID and BSSID networks seperately */
+#define REPORT_SEPERATELY_BIT 11
+
+#define SORT_CRITERIA_MASK 0x0001
+#define AUTO_NET_SWITCH_MASK 0x0002
+#define ENABLE_BKGRD_SCAN_MASK 0x0004
+#define IMMEDIATE_SCAN_MASK 0x0008
+#define AUTO_CONNECT_MASK 0x0010
+
+#define ENABLE_BD_SCAN_MASK 0x0020
+#define ENABLE_ADAPTSCAN_MASK 0x00c0
+#define IMMEDIATE_EVENT_MASK 0x0100
+#define SUPPRESS_SSID_MASK 0x0200
+#define ENABLE_NET_OFFLOAD_MASK 0x0400
+/* report found/lost events for SSID and BSSID networks seperately */
+#define REPORT_SEPERATELY_MASK 0x0800
+
+#define PFN_VERSION 2
+#define PFN_SCANRESULT_VERSION 1
+#define MAX_PFN_LIST_COUNT 16
+
+#define PFN_COMPLETE 1
+#define PFN_INCOMPLETE 0
+
+#define DEFAULT_BESTN 2
+#define DEFAULT_MSCAN 0
+#define DEFAULT_REPEAT 10
+#define DEFAULT_EXP 2
+
+#define PFN_PARTIAL_SCAN_BIT 0
+#define PFN_PARTIAL_SCAN_MASK 1
+
+/* PFN network info structure */
+typedef struct wl_pfn_subnet_info {
+ struct ether_addr BSSID;
+ uint8 channel; /* channel number only */
+ uint8 SSID_len;
+ uint8 SSID[32];
+} wl_pfn_subnet_info_t;
+
+typedef struct wl_pfn_net_info {
+ wl_pfn_subnet_info_t pfnsubnet;
+ int16 RSSI; /* receive signal strength (in dBm) */
+ uint16 timestamp; /* age in seconds */
+} wl_pfn_net_info_t;
+
+typedef struct wl_pfn_lnet_info {
+ wl_pfn_subnet_info_t pfnsubnet; /* BSSID + channel + SSID len + SSID */
+ uint16 flags; /* partial scan, etc */
+ int16 RSSI; /* receive signal strength (in dBm) */
+ uint32 timestamp; /* age in miliseconds */
+ uint16 rtt0; /* estimated distance to this AP in centimeters */
+ uint16 rtt1; /* standard deviation of the distance to this AP in centimeters */
+} wl_pfn_lnet_info_t;
+
+typedef struct wl_pfn_lscanresults {
+ uint32 version;
+ uint32 status;
+ uint32 count;
+ wl_pfn_lnet_info_t netinfo[1];
+} wl_pfn_lscanresults_t;
+
+typedef struct wl_pfn_scanresults {
+ uint32 version;
+ uint32 status;
+ uint32 count;
+ wl_pfn_net_info_t netinfo[1];
+} wl_pfn_scanresults_t;
+
+/* PFN data structure */
+typedef struct wl_pfn_param {
+ int32 version; /* PNO parameters version */
+ int32 scan_freq; /* Scan frequency */
+ int32 lost_network_timeout; /* Timeout in sec. to declare
+ * discovered network as lost
+ */
+ int16 flags; /* Bit field to control features
+ * of PFN such as sort criteria auto
+ * enable switch and background scan
+ */
+ int16 rssi_margin; /* Margin to avoid jitter for choosing a
+ * PFN based on RSSI sort criteria
+ */
+ uint8 bestn; /* number of best networks in each scan */
+ uint8 mscan; /* number of scans recorded */
+ uint8 repeat; /* Minimum number of scan intervals
+ *before scan frequency changes in adaptive scan
+ */
+ uint8 exp; /* Exponent of 2 for maximum scan interval */
+ int32 slow_freq; /* slow scan period */
+} wl_pfn_param_t;
+
+typedef struct wl_pfn_bssid {
+ struct ether_addr macaddr;
+ /* Bit4: suppress_lost, Bit3: suppress_found */
+ uint16 flags;
+} wl_pfn_bssid_t;
+#define WL_PFN_SUPPRESSFOUND_MASK 0x08
+#define WL_PFN_SUPPRESSLOST_MASK 0x10
+#define WL_PFN_RSSI_MASK 0xff00
+#define WL_PFN_RSSI_SHIFT 8
+
+typedef struct wl_pfn_cfg {
+ uint32 reporttype;
+ int32 channel_num;
+ uint16 channel_list[WL_NUMCHANNELS];
+ uint32 flags;
+} wl_pfn_cfg_t;
+#define WL_PFN_REPORT_ALLNET 0
+#define WL_PFN_REPORT_SSIDNET 1
+#define WL_PFN_REPORT_BSSIDNET 2
+
+#define WL_PFN_CFG_FLAGS_PROHIBITED 0x00000001 /* Accept and use prohibited channels */
+#define WL_PFN_CFG_FLAGS_RESERVED 0xfffffffe /* Remaining reserved for future use */
+
+typedef struct wl_pfn {
+ wlc_ssid_t ssid; /* ssid name and its length */
+ int32 flags; /* bit2: hidden */
+ int32 infra; /* BSS Vs IBSS */
+ int32 auth; /* Open Vs Closed */
+ int32 wpa_auth; /* WPA type */
+ int32 wsec; /* wsec value */
+} wl_pfn_t;
+
+typedef struct wl_pfn_list {
+ uint32 version;
+ uint32 enabled;
+ uint32 count;
+ wl_pfn_t pfn[1];
+} wl_pfn_list_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct pfn_olmsg_params_t {
+ wlc_ssid_t ssid;
+ uint32 cipher_type;
+ uint32 auth_type;
+ uint8 channels[4];
+} BWL_POST_PACKED_STRUCT pfn_olmsg_params;
+
+#define WL_PFN_HIDDEN_BIT 2
+#define WL_PFN_HIDDEN_MASK 0x4
+
+#ifndef BESTN_MAX
+#define BESTN_MAX 3
+#endif
+
+#ifndef MSCAN_MAX
+#define MSCAN_MAX 90
+#endif
+
+/* Service discovery */
+typedef struct {
+ uint8 transaction_id; /* Transaction id */
+ uint8 protocol; /* Service protocol type */
+ uint16 query_len; /* Length of query */
+ uint16 response_len; /* Length of response */
+ uint8 qrbuf[1];
+} wl_p2po_qr_t;
+
+typedef struct {
+ uint16 period; /* extended listen period */
+ uint16 interval; /* extended listen interval */
+} wl_p2po_listen_t;
+
+/* ANQP offload */
+
+#define ANQPO_MAX_QUERY_SIZE 256
+typedef struct {
+ uint16 max_retransmit; /* ~0 use default, max retransmit on no ACK from peer */
+ uint16 response_timeout; /* ~0 use default, msec to wait for resp after tx packet */
+ uint16 max_comeback_delay; /* ~0 use default, max comeback delay in resp else fail */
+ uint16 max_retries; /* ~0 use default, max retries on failure */
+ uint16 query_len; /* length of ANQP query */
+ uint8 query_data[1]; /* ANQP encoded query (max ANQPO_MAX_QUERY_SIZE) */
+} wl_anqpo_set_t;
+
+typedef struct {
+ uint16 channel; /* channel of the peer */
+ struct ether_addr addr; /* addr of the peer */
+} wl_anqpo_peer_t;
+
+#define ANQPO_MAX_PEER_LIST 64
+typedef struct {
+ uint16 count; /* number of peers in list */
+ wl_anqpo_peer_t peer[1]; /* max ANQPO_MAX_PEER_LIST */
+} wl_anqpo_peer_list_t;
+
+#define ANQPO_MAX_IGNORE_SSID 64
+typedef struct {
+ bool is_clear; /* set to clear list (not used on GET) */
+ uint16 count; /* number of SSID in list */
+ wlc_ssid_t ssid[1]; /* max ANQPO_MAX_IGNORE_SSID */
+} wl_anqpo_ignore_ssid_list_t;
+
+#define ANQPO_MAX_IGNORE_BSSID 64
+typedef struct {
+ bool is_clear; /* set to clear list (not used on GET) */
+ uint16 count; /* number of addr in list */
+ struct ether_addr bssid[1]; /* max ANQPO_MAX_IGNORE_BSSID */
+} wl_anqpo_ignore_bssid_list_t;
+
+
+struct toe_ol_stats_t {
+ /* Num of tx packets that don't need to be checksummed */
+ uint32 tx_summed;
+
+ /* Num of tx packets where checksum is filled by offload engine */
+ uint32 tx_iph_fill;
+ uint32 tx_tcp_fill;
+ uint32 tx_udp_fill;
+ uint32 tx_icmp_fill;
+
+ /* Num of rx packets where toe finds out if checksum is good or bad */
+ uint32 rx_iph_good;
+ uint32 rx_iph_bad;
+ uint32 rx_tcp_good;
+ uint32 rx_tcp_bad;
+ uint32 rx_udp_good;
+ uint32 rx_udp_bad;
+ uint32 rx_icmp_good;
+ uint32 rx_icmp_bad;
+
+ /* Num of tx packets in which csum error is injected */
+ uint32 tx_tcp_errinj;
+ uint32 tx_udp_errinj;
+ uint32 tx_icmp_errinj;
+
+ /* Num of rx packets in which csum error is injected */
+ uint32 rx_tcp_errinj;
+ uint32 rx_udp_errinj;
+ uint32 rx_icmp_errinj;
+};
+
+/* Arp offload statistic counts */
+struct arp_ol_stats_t {
+ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */
+ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */
+
+ uint32 arp_table_entries; /* ARP table entries */
+ uint32 arp_table_overflow; /* ARP table additions skipped due to overflow */
+
+ uint32 host_request; /* ARP requests from host */
+ uint32 host_reply; /* ARP replies from host */
+ uint32 host_service; /* ARP requests from host serviced by ARP Agent */
+
+ uint32 peer_request; /* ARP requests received from network */
+ uint32 peer_request_drop; /* ARP requests from network that were dropped */
+ uint32 peer_reply; /* ARP replies received from network */
+ uint32 peer_reply_drop; /* ARP replies from network that were dropped */
+ uint32 peer_service; /* ARP request from host serviced by ARP Agent */
+};
+
+/* NS offload statistic counts */
+struct nd_ol_stats_t {
+ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */
+ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */
+ uint32 peer_request; /* NS requests received from network */
+ uint32 peer_request_drop; /* NS requests from network that were dropped */
+ uint32 peer_reply_drop; /* NA replies from network that were dropped */
+ uint32 peer_service; /* NS request from host serviced by firmware */
+};
+
+/*
+ * Keep-alive packet offloading.
+ */
+
+/* NAT keep-alive packets format: specifies the re-transmission period, the packet
+ * length, and packet contents.
+ */
+typedef struct wl_keep_alive_pkt {
+ uint32 period_msec; /* Retransmission period (0 to disable packet re-transmits) */
+ uint16 len_bytes; /* Size of packet to transmit (0 to disable packet re-transmits) */
+ uint8 data[1]; /* Variable length packet to transmit. Contents should include
+ * entire ethernet packet (enet header, IP header, UDP header,
+ * and UDP payload) in network byte order.
+ */
+} wl_keep_alive_pkt_t;
+
+#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data)
+
+
+/*
+ * Dongle pattern matching filter.
+ */
+
+#define MAX_WAKE_PACKET_CACHE_BYTES 128 /* Maximum cached wake packet */
+
+#define MAX_WAKE_PACKET_BYTES (DOT11_A3_HDR_LEN + \
+ DOT11_QOS_LEN + \
+ sizeof(struct dot11_llc_snap_header) + \
+ ETHER_MAX_DATA)
+
+typedef struct pm_wake_packet {
+ uint32 status; /* Is the wake reason a packet (if all the other field's valid) */
+ uint32 pattern_id; /* Pattern ID that matched */
+ uint32 original_packet_size;
+ uint32 saved_packet_size;
+ uchar packet[MAX_WAKE_PACKET_CACHE_BYTES];
+} pm_wake_packet_t;
+
+/* Packet filter types. Currently, only pattern matching is supported. */
+typedef enum wl_pkt_filter_type {
+ WL_PKT_FILTER_TYPE_PATTERN_MATCH=0, /* Pattern matching filter */
+ WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH=1, /* Magic packet match */
+ WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH=2, /* A pattern list (match all to match filter) */
+ WL_PKT_FILTER_TYPE_ENCRYPTED_PATTERN_MATCH=3, /* SECURE WOWL magic / net pattern match */
+ WL_PKT_FILTER_TYPE_APF_MATCH=4, /* Android packet filter match */
+ WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT=5, /* Pattern matching filter with timeout event */
+} wl_pkt_filter_type_t;
+
+#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t
+
+/* String mapping for types that may be used by applications or debug */
+#define WL_PKT_FILTER_TYPE_NAMES \
+ { "PATTERN", WL_PKT_FILTER_TYPE_PATTERN_MATCH }, \
+ { "MAGIC", WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH }, \
+ { "PATLIST", WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH }, \
+ { "SECURE WOWL", WL_PKT_FILTER_TYPE_ENCRYPTED_PATTERN_MATCH }, \
+ { "APF", WL_PKT_FILTER_TYPE_APF_MATCH }, \
+ { "PATTERN TIMEOUT", WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT }
+
+/* Pattern matching filter. Specifies an offset within received packets to
+ * start matching, the pattern to match, the size of the pattern, and a bitmask
+ * that indicates which bits within the pattern should be matched.
+ */
+typedef struct wl_pkt_filter_pattern {
+ uint32 offset; /* Offset within received packet to start pattern matching.
+ * Offset '0' is the first byte of the ethernet header.
+ */
+ uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */
+ uint8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts
+ * at offset 0. Pattern immediately follows mask.
+ */
+} wl_pkt_filter_pattern_t;
+
+/* A pattern list is a numerically specified list of modified pattern structures. */
+typedef struct wl_pkt_filter_pattern_listel {
+ uint16 rel_offs; /* Offset to begin match (relative to 'base' below) */
+ uint16 base_offs; /* Base for offset (defined below) */
+ uint16 size_bytes; /* Size of mask/pattern */
+ uint16 match_flags; /* Addition flags controlling the match */
+ uint8 mask_and_data[1]; /* Variable length mask followed by data, each size_bytes */
+} wl_pkt_filter_pattern_listel_t;
+
+typedef struct wl_pkt_filter_pattern_list {
+ uint8 list_cnt; /* Number of elements in the list */
+ uint8 PAD1[1]; /* Reserved (possible version: reserved) */
+ uint16 totsize; /* Total size of this pattern list (includes this struct) */
+ wl_pkt_filter_pattern_listel_t patterns[1]; /* Variable number of list elements */
+} wl_pkt_filter_pattern_list_t;
+
+
+typedef struct wl_pkt_filter_pattern_timeout {
+ uint32 offset; /* Offset within received packet to start pattern matching.
+ * Offset '0' is the first byte of the ethernet header.
+ */
+ uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */
+ uint32 timeout; /* Timeout(seconds) */
+ uint8 mask_and_pattern[1]; /* Variable length mask and pattern data.
+ * mask starts at offset 0. Pattern
+ * immediately follows mask.
+ */
+} wl_pkt_filter_pattern_timeout_t;
+
+/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
+typedef struct wl_pkt_filter {
+ uint32 id; /* Unique filter id, specified by app. */
+ uint32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
+ uint32 negate_match; /* Negate the result of filter matches */
+ union { /* Filter definitions */
+ wl_pkt_filter_pattern_t pattern; /* Pattern matching filter */
+ wl_pkt_filter_pattern_list_t patlist; /* List of patterns to match */
+ wl_pkt_filter_pattern_timeout_t pattern_timeout; /* Pattern timeout event filter */
+ } u;
+} wl_pkt_filter_t;
+
+/* IOVAR "tcp_keep_set" parameter. Used to install tcp keep_alive stuff. */
+typedef struct wl_tcp_keep_set {
+ uint32 val1;
+ uint32 val2;
+} wl_tcp_keep_set_t;
+
+#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u)
+#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern)
+#define WL_PKT_FILTER_PATTERN_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_list_t, patterns)
+#define WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN \
+ OFFSETOF(wl_pkt_filter_pattern_listel_t, mask_and_data)
+#define WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN \
+ OFFSETOF(wl_pkt_filter_pattern_timeout_t, mask_and_pattern)
+
+/* IOVAR "pkt_filter_enable" parameter. */
+typedef struct wl_pkt_filter_enable {
+ uint32 id; /* Unique filter id */
+ uint32 enable; /* Enable/disable bool */
+} wl_pkt_filter_enable_t;
+
+/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */
+typedef struct wl_pkt_filter_list {
+ uint32 num; /* Number of installed packet filters */
+ wl_pkt_filter_t filter[1]; /* Variable array of packet filters. */
+} wl_pkt_filter_list_t;
+
+#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter)
+
+/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */
+typedef struct wl_pkt_filter_stats {
+ uint32 num_pkts_matched; /* # filter matches for specified filter id */
+ uint32 num_pkts_forwarded; /* # packets fwded from dongle to host for all filters */
+ uint32 num_pkts_discarded; /* # packets discarded by dongle for all filters */
+} wl_pkt_filter_stats_t;
+
+/* IOVAR "pkt_filter_ports" parameter. Configure TCP/UDP port filters. */
+typedef struct wl_pkt_filter_ports {
+ uint8 version; /* Be proper */
+ uint8 reserved; /* Be really proper */
+ uint16 count; /* Number of ports following */
+ /* End of fixed data */
+ uint16 ports[1]; /* Placeholder for ports[<count>] */
+} wl_pkt_filter_ports_t;
+
+#define WL_PKT_FILTER_PORTS_FIXED_LEN OFFSETOF(wl_pkt_filter_ports_t, ports)
+
+#define WL_PKT_FILTER_PORTS_VERSION 0
+#define WL_PKT_FILTER_PORTS_MAX 128
+
+#define RSN_KCK_LENGTH 16
+#define RSN_KEK_LENGTH 16
+#define RSN_REPLAY_LEN 8
+typedef struct _gtkrefresh {
+ uchar KCK[RSN_KCK_LENGTH];
+ uchar KEK[RSN_KEK_LENGTH];
+ uchar ReplayCounter[RSN_REPLAY_LEN];
+} gtk_keyinfo_t, *pgtk_keyinfo_t;
+
+/* Sequential Commands ioctl */
+typedef struct wl_seq_cmd_ioctl {
+ uint32 cmd; /* common ioctl definition */
+ uint32 len; /* length of user buffer */
+} wl_seq_cmd_ioctl_t;
+
+#define WL_SEQ_CMD_ALIGN_BYTES 4
+
+/* These are the set of get IOCTLs that should be allowed when using
+ * IOCTL sequence commands. These are issued implicitly by wl.exe each time
+ * it is invoked. We never want to buffer these, or else wl.exe will stop working.
+ */
+#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \
+ (((cmd) == WLC_GET_MAGIC) || \
+ ((cmd) == WLC_GET_VERSION) || \
+ ((cmd) == WLC_GET_AP) || \
+ ((cmd) == WLC_GET_INSTANCE))
+
+typedef struct wl_pkteng {
+ uint32 flags;
+ uint32 delay; /* Inter-packet delay */
+ uint32 nframes; /* Number of frames */
+ uint32 length; /* Packet length */
+ uint8 seqno; /* Enable/disable sequence no. */
+ struct ether_addr dest; /* Destination address */
+ struct ether_addr src; /* Source address */
+} wl_pkteng_t;
+
+typedef struct wl_pkteng_stats {
+ uint32 lostfrmcnt; /* RX PER test: no of frames lost (skip seqno) */
+ int32 rssi; /* RSSI */
+ int32 snr; /* signal to noise ratio */
+ uint16 rxpktcnt[NUM_80211_RATES+1];
+ uint8 rssi_qdb; /* qdB portion of the computed rssi */
+} wl_pkteng_stats_t;
+
+
+typedef enum {
+ wowl_pattern_type_bitmap = 0,
+ wowl_pattern_type_arp,
+ wowl_pattern_type_na
+} wowl_pattern_type_t;
+
+typedef struct wl_wowl_pattern {
+ uint32 masksize; /* Size of the mask in #of bytes */
+ uint32 offset; /* Pattern byte offset in packet */
+ uint32 patternoffset; /* Offset of start of pattern in the structure */
+ uint32 patternsize; /* Size of the pattern itself in #of bytes */
+ uint32 id; /* id */
+ uint32 reasonsize; /* Size of the wakeup reason code */
+ wowl_pattern_type_t type; /* Type of pattern */
+ /* Mask follows the structure above */
+ /* Pattern follows the mask is at 'patternoffset' from the start */
+} wl_wowl_pattern_t;
+
+typedef struct wl_wowl_pattern_list {
+ uint count;
+ wl_wowl_pattern_t pattern[1];
+} wl_wowl_pattern_list_t;
+
+typedef struct wl_wowl_wakeind {
+ uint8 pci_wakeind; /* Whether PCI PMECSR PMEStatus bit was set */
+ uint32 ucode_wakeind; /* What wakeup-event indication was set by ucode */
+} wl_wowl_wakeind_t;
+
+typedef struct {
+ uint32 pktlen; /* size of packet */
+ void *sdu;
+} tcp_keepalive_wake_pkt_infop_t;
+
+/* per AC rate control related data structure */
+typedef struct wl_txrate_class {
+ uint8 init_rate;
+ uint8 min_rate;
+ uint8 max_rate;
+} wl_txrate_class_t;
+
+/* structure for Overlap BSS scan arguments */
+typedef struct wl_obss_scan_arg {
+ int16 passive_dwell;
+ int16 active_dwell;
+ int16 bss_widthscan_interval;
+ int16 passive_total;
+ int16 active_total;
+ int16 chanwidth_transition_delay;
+ int16 activity_threshold;
+} wl_obss_scan_arg_t;
+
+#define WL_OBSS_SCAN_PARAM_LEN sizeof(wl_obss_scan_arg_t)
+
+/* RSSI event notification configuration. */
+typedef struct wl_rssi_event {
+ uint32 rate_limit_msec; /* # of events posted to application will be limited to
+ * one per specified period (0 to disable rate limit).
+ */
+ uint8 num_rssi_levels; /* Number of entries in rssi_levels[] below */
+ int8 rssi_levels[MAX_RSSI_LEVELS]; /* Variable number of RSSI levels. An event
+ * will be posted each time the RSSI of received
+ * beacons/packets crosses a level.
+ */
+} wl_rssi_event_t;
+
+typedef struct wl_action_obss_coex_req {
+ uint8 info;
+ uint8 num;
+ uint8 ch_list[1];
+} wl_action_obss_coex_req_t;
+
+
+/* IOVar parameter block for small MAC address array with type indicator */
+#define WL_IOV_MAC_PARAM_LEN 4
+
+#define WL_IOV_PKTQ_LOG_PRECS 16
+
+typedef struct {
+ uint32 num_addrs;
+ char addr_type[WL_IOV_MAC_PARAM_LEN];
+ struct ether_addr ea[WL_IOV_MAC_PARAM_LEN];
+} wl_iov_mac_params_t;
+
+/* This is extra info that follows wl_iov_mac_params_t */
+typedef struct {
+ uint32 addr_info[WL_IOV_MAC_PARAM_LEN];
+} wl_iov_mac_extra_params_t;
+
+/* Combined structure */
+typedef struct {
+ wl_iov_mac_params_t params;
+ wl_iov_mac_extra_params_t extra_params;
+} wl_iov_mac_full_params_t;
+
+/* Parameter block for PKTQ_LOG statistics */
+#define PKTQ_LOG_COUNTERS_V4 \
+ /* packets requested to be stored */ \
+ uint32 requested; \
+ /* packets stored */ \
+ uint32 stored; \
+ /* packets saved, because a lowest priority queue has given away one packet */ \
+ uint32 saved; \
+ /* packets saved, because an older packet from the same queue has been dropped */ \
+ uint32 selfsaved; \
+ /* packets dropped, because pktq is full with higher precedence packets */ \
+ uint32 full_dropped; \
+ /* packets dropped because pktq per that precedence is full */ \
+ uint32 dropped; \
+ /* packets dropped, in order to save one from a queue of a highest priority */ \
+ uint32 sacrificed; \
+ /* packets droped because of hardware/transmission error */ \
+ uint32 busy; \
+ /* packets re-sent because they were not received */ \
+ uint32 retry; \
+ /* packets retried again (ps pretend) prior to moving power save mode */ \
+ uint32 ps_retry; \
+ /* suppressed packet count */ \
+ uint32 suppress; \
+ /* packets finally dropped after retry limit */ \
+ uint32 retry_drop; \
+ /* the high-water mark of the queue capacity for packets - goes to zero as queue fills */ \
+ uint32 max_avail; \
+ /* the high-water mark of the queue utilisation for packets - ('inverse' of max_avail) */ \
+ uint32 max_used; \
+ /* the maximum capacity of the queue */ \
+ uint32 queue_capacity; \
+ /* count of rts attempts that failed to receive cts */ \
+ uint32 rtsfail; \
+ /* count of packets sent (acked) successfully */ \
+ uint32 acked; \
+ /* running total of phy rate of packets sent successfully */ \
+ uint32 txrate_succ; \
+ /* running total of phy 'main' rate */ \
+ uint32 txrate_main; \
+ /* actual data transferred successfully */ \
+ uint32 throughput; \
+ /* time difference since last pktq_stats */ \
+ uint32 time_delta;
+
+typedef struct {
+ PKTQ_LOG_COUNTERS_V4
+} pktq_log_counters_v04_t;
+
+/* v5 is the same as V4 with extra parameter */
+typedef struct {
+ PKTQ_LOG_COUNTERS_V4
+ /* cumulative time to transmit */
+ uint32 airtime;
+} pktq_log_counters_v05_t;
+
+typedef struct {
+ uint8 num_prec[WL_IOV_MAC_PARAM_LEN];
+ pktq_log_counters_v04_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS];
+ uint32 counter_info[WL_IOV_MAC_PARAM_LEN];
+ uint32 pspretend_time_delta[WL_IOV_MAC_PARAM_LEN];
+ char headings[1];
+} pktq_log_format_v04_t;
+
+typedef struct {
+ uint8 num_prec[WL_IOV_MAC_PARAM_LEN];
+ pktq_log_counters_v05_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS];
+ uint32 counter_info[WL_IOV_MAC_PARAM_LEN];
+ uint32 pspretend_time_delta[WL_IOV_MAC_PARAM_LEN];
+ char headings[1];
+} pktq_log_format_v05_t;
+
+
+typedef struct {
+ uint32 version;
+ wl_iov_mac_params_t params;
+ union {
+ pktq_log_format_v04_t v04;
+ pktq_log_format_v05_t v05;
+ } pktq_log;
+} wl_iov_pktq_log_t;
+
+/* PKTQ_LOG_AUTO, PKTQ_LOG_DEF_PREC flags introduced in v05, they are ignored by v04 */
+#define PKTQ_LOG_AUTO (1 << 31)
+#define PKTQ_LOG_DEF_PREC (1 << 30)
+
+/*
+ * SCB_BS_DATA iovar definitions start.
+ */
+#define SCB_BS_DATA_STRUCT_VERSION 1
+
+/* The actual counters maintained for each station */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ /* The following counters are a subset of what pktq_stats provides per precedence. */
+ uint32 retry; /* packets re-sent because they were not received */
+ uint32 retry_drop; /* packets finally dropped after retry limit */
+ uint32 rtsfail; /* count of rts attempts that failed to receive cts */
+ uint32 acked; /* count of packets sent (acked) successfully */
+ uint32 txrate_succ; /* running total of phy rate of packets sent successfully */
+ uint32 txrate_main; /* running total of phy 'main' rate */
+ uint32 throughput; /* actual data transferred successfully */
+ uint32 time_delta; /* time difference since last pktq_stats */
+ uint32 airtime; /* cumulative total medium access delay in useconds */
+} BWL_POST_PACKED_STRUCT iov_bs_data_counters_t;
+
+/* The structure for individual station information. */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ struct ether_addr station_address; /* The station MAC address */
+ uint16 station_flags; /* Bit mask of flags, for future use. */
+ iov_bs_data_counters_t station_counters; /* The actual counter values */
+} BWL_POST_PACKED_STRUCT iov_bs_data_record_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint16 structure_version; /* Structure version number (for wl/wlu matching) */
+ uint16 structure_count; /* Number of iov_bs_data_record_t records following */
+ iov_bs_data_record_t structure_record[1]; /* 0 - structure_count records */
+} BWL_POST_PACKED_STRUCT iov_bs_data_struct_t;
+
+/* Bitmask of options that can be passed in to the iovar. */
+enum {
+ SCB_BS_DATA_FLAG_NO_RESET = (1<<0) /* Do not clear the counters after reading */
+};
+/*
+ * SCB_BS_DATA iovar definitions end.
+ */
+
+typedef struct wlc_extlog_cfg {
+ int max_number;
+ uint16 module; /* bitmap */
+ uint8 level;
+ uint8 flag;
+ uint16 version;
+} wlc_extlog_cfg_t;
+
+typedef struct log_record {
+ uint32 time;
+ uint16 module;
+ uint16 id;
+ uint8 level;
+ uint8 sub_unit;
+ uint8 seq_num;
+ int32 arg;
+ char str[MAX_ARGSTR_LEN];
+} log_record_t;
+
+typedef struct wlc_extlog_req {
+ uint32 from_last;
+ uint32 num;
+} wlc_extlog_req_t;
+
+typedef struct wlc_extlog_results {
+ uint16 version;
+ uint16 record_len;
+ uint32 num;
+ log_record_t logs[1];
+} wlc_extlog_results_t;
+
+typedef struct log_idstr {
+ uint16 id;
+ uint16 flag;
+ uint8 arg_type;
+ const char *fmt_str;
+} log_idstr_t;
+
+#define FMTSTRF_USER 1
+
+/* flat ID definitions
+ * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will
+ * affect backward compatibility with pre-existing apps
+ */
+typedef enum {
+ FMTSTR_DRIVER_UP_ID = 0,
+ FMTSTR_DRIVER_DOWN_ID = 1,
+ FMTSTR_SUSPEND_MAC_FAIL_ID = 2,
+ FMTSTR_NO_PROGRESS_ID = 3,
+ FMTSTR_RFDISABLE_ID = 4,
+ FMTSTR_REG_PRINT_ID = 5,
+ FMTSTR_EXPTIME_ID = 6,
+ FMTSTR_JOIN_START_ID = 7,
+ FMTSTR_JOIN_COMPLETE_ID = 8,
+ FMTSTR_NO_NETWORKS_ID = 9,
+ FMTSTR_SECURITY_MISMATCH_ID = 10,
+ FMTSTR_RATE_MISMATCH_ID = 11,
+ FMTSTR_AP_PRUNED_ID = 12,
+ FMTSTR_KEY_INSERTED_ID = 13,
+ FMTSTR_DEAUTH_ID = 14,
+ FMTSTR_DISASSOC_ID = 15,
+ FMTSTR_LINK_UP_ID = 16,
+ FMTSTR_LINK_DOWN_ID = 17,
+ FMTSTR_RADIO_HW_OFF_ID = 18,
+ FMTSTR_RADIO_HW_ON_ID = 19,
+ FMTSTR_EVENT_DESC_ID = 20,
+ FMTSTR_PNP_SET_POWER_ID = 21,
+ FMTSTR_RADIO_SW_OFF_ID = 22,
+ FMTSTR_RADIO_SW_ON_ID = 23,
+ FMTSTR_PWD_MISMATCH_ID = 24,
+ FMTSTR_FATAL_ERROR_ID = 25,
+ FMTSTR_AUTH_FAIL_ID = 26,
+ FMTSTR_ASSOC_FAIL_ID = 27,
+ FMTSTR_IBSS_FAIL_ID = 28,
+ FMTSTR_EXTAP_FAIL_ID = 29,
+ FMTSTR_MAX_ID
+} log_fmtstr_id_t;
+
+#ifdef DONGLEOVERLAYS
+typedef struct {
+ uint32 flags_idx; /* lower 8 bits: overlay index; upper 24 bits: flags */
+ uint32 offset; /* offset into overlay region to write code */
+ uint32 len; /* overlay code len */
+ /* overlay code follows this struct */
+} wl_ioctl_overlay_t;
+#endif /* DONGLEOVERLAYS */
+
+/* 11k Neighbor Report element */
+typedef struct nbr_element {
+ uint8 id;
+ uint8 len;
+ struct ether_addr bssid;
+ uint32 bssid_info;
+ uint8 reg;
+ uint8 channel;
+ uint8 phytype;
+ uint8 pad;
+} nbr_element_t;
+
+/* no default structure packing */
+#include <packed_section_end.h>
+
+typedef struct keepalives_max_idle {
+ uint16 keepalive_count; /* nmbr of keepalives per bss_max_idle period */
+ uint8 mkeepalive_index; /* mkeepalive_index for keepalive frame to be used */
+ uint8 PAD; /* to align next field */
+ uint16 max_interval; /* seconds */
+} keepalives_max_idle_t;
+
+#define PM_IGNORE_BCMC_PROXY_ARP (1 << 0)
+#define PM_IGNORE_BCMC_ALL_DMS_ACCEPTED (1 << 1)
+
+/* require strict packing */
+#include <packed_section_start.h>
+
+
+/* Structures and constants used for "vndr_ie" IOVar interface */
+#define VNDR_IE_CMD_LEN 4 /* length of the set command string:
+ * "add", "del" (+ NUL)
+ */
+
+#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32))
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */
+ vndr_ie_t vndr_ie_data; /* vendor IE data */
+} BWL_POST_PACKED_STRUCT vndr_ie_info_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ int iecount; /* number of entries in the vndr_ie_list[] array */
+ vndr_ie_info_t vndr_ie_list[1]; /* variable size list of vndr_ie_info_t structs */
+} BWL_POST_PACKED_STRUCT vndr_ie_buf_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ char cmd[VNDR_IE_CMD_LEN]; /* vndr_ie IOVar set command : "add", "del" + NUL */
+ vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */
+} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t;
+
+/* tag_ID/length/value_buffer tuple */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint8 id;
+ uint8 len;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT tlv_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */
+ tlv_t ie_data; /* IE data */
+} BWL_POST_PACKED_STRUCT ie_info_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ int iecount; /* number of entries in the ie_list[] array */
+ ie_info_t ie_list[1]; /* variable size list of ie_info_t structs */
+} BWL_POST_PACKED_STRUCT ie_buf_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ char cmd[VNDR_IE_CMD_LEN]; /* ie IOVar set command : "add" + NUL */
+ ie_buf_t ie_buffer; /* buffer containing IE list information */
+} BWL_POST_PACKED_STRUCT ie_setbuf_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */
+ uint8 id; /* IE type */
+} BWL_POST_PACKED_STRUCT ie_getbuf_t;
+
+/* structures used to define format of wps ie data from probe requests */
+/* passed up to applications via iovar "prbreq_wpsie" */
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr {
+ struct ether_addr staAddr;
+ uint16 ieLen;
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data {
+ sta_prbreq_wps_ie_hdr_t hdr;
+ uint8 ieData[1];
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list {
+ uint32 totLen;
+ uint8 ieDataList[1];
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t;
+
+
+#ifdef WLMEDIA_TXFAILEVENT
+typedef BWL_PRE_PACKED_STRUCT struct {
+ char dest[ETHER_ADDR_LEN]; /* destination MAC */
+ uint8 prio; /* Packet Priority */
+ uint8 flags; /* Flags */
+ uint32 tsf_l; /* TSF timer low */
+ uint32 tsf_h; /* TSF timer high */
+ uint16 rates; /* Main Rates */
+ uint16 txstatus; /* TX Status */
+} BWL_POST_PACKED_STRUCT txfailinfo_t;
+#endif /* WLMEDIA_TXFAILEVENT */
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint32 flags;
+ chanspec_t chanspec; /* txpwr report for this channel */
+ chanspec_t local_chanspec; /* channel on which we are associated */
+ uint8 local_max; /* local max according to the AP */
+ uint8 local_constraint; /* local constraint according to the AP */
+ int8 antgain[2]; /* Ant gain for each band - from SROM */
+ uint8 rf_cores; /* count of RF Cores being reported */
+ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */
+ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */
+ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */
+ uint8 tx_power_max[4]; /* Maximum target power among all rates */
+ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */
+ int8 clm_limits[WL_NUMRATES]; /* regulatory limits - 20, 40 or 80MHz */
+ int8 clm_limits_subchan1[WL_NUMRATES]; /* regulatory limits - 20in40 or 40in80 */
+ int8 clm_limits_subchan2[WL_NUMRATES]; /* regulatory limits - 20in80MHz */
+ int8 sar; /* SAR limit for display by wl executable */
+ int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */
+ uint8 version; /* Version of the data format wlu <--> driver */
+ uint8 display_core; /* Displayed curpower core */
+ int8 target_offsets[4]; /* Target power offsets for current rate per core */
+ uint32 last_tx_ratespec; /* Ratespec for last transmition */
+ uint user_target; /* user limit */
+ uint32 board_limit_len; /* length of board limit buffer */
+ uint32 target_len; /* length of target power buffer */
+ int8 SARLIMIT[MAX_STREAMS_SUPPORTED];
+ uint8 pprdata[1]; /* ppr serialization buffer */
+} BWL_POST_PACKED_STRUCT tx_pwr_rpt_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ struct ipv4_addr ipv4_addr;
+ struct ether_addr nexthop;
+} BWL_POST_PACKED_STRUCT ibss_route_entry_t;
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint32 num_entry;
+ ibss_route_entry_t route_entry[1];
+} BWL_POST_PACKED_STRUCT ibss_route_tbl_t;
+
+#define MAX_IBSS_ROUTE_TBL_ENTRY 64
+
+#define TXPWR_TARGET_VERSION 0
+typedef BWL_PRE_PACKED_STRUCT struct {
+ int32 version; /* version number */
+ chanspec_t chanspec; /* txpwr report for this channel */
+ int8 txpwr[WL_STA_ANT_MAX]; /* Max tx target power, in qdb */
+ uint8 rf_cores; /* count of RF Cores being reported */
+} BWL_POST_PACKED_STRUCT txpwr_target_max_t;
+
+#define BSS_PEER_INFO_PARAM_CUR_VER 0
+/* Input structure for IOV_BSS_PEER_INFO */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint16 version;
+ struct ether_addr ea; /* peer MAC address */
+} BWL_POST_PACKED_STRUCT bss_peer_info_param_t;
+
+#define BSS_PEER_INFO_CUR_VER 0
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint16 version;
+ struct ether_addr ea;
+ int32 rssi;
+ uint32 tx_rate; /* current tx rate */
+ uint32 rx_rate; /* current rx rate */
+ wl_rateset_t rateset; /* rateset in use */
+ uint32 age; /* age in seconds */
+} BWL_POST_PACKED_STRUCT bss_peer_info_t;
+
+#define BSS_PEER_LIST_INFO_CUR_VER 0
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint16 version;
+ uint16 bss_peer_info_len; /* length of bss_peer_info_t */
+ uint32 count; /* number of peer info */
+ bss_peer_info_t peer_info[1]; /* peer info */
+} BWL_POST_PACKED_STRUCT bss_peer_list_info_t;
+
+#define BSS_PEER_LIST_INFO_FIXED_LEN OFFSETOF(bss_peer_list_info_t, peer_info)
+
+#define AIBSS_BCN_FORCE_CONFIG_VER_0 0
+
+/* structure used to configure AIBSS beacon force xmit */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint16 version;
+ uint16 len;
+ uint32 initial_min_bcn_dur; /* dur in ms to check a bcn in bcn_flood period */
+ uint32 min_bcn_dur; /* dur in ms to check a bcn after bcn_flood period */
+ uint32 bcn_flood_dur; /* Initial bcn xmit period in ms */
+} BWL_POST_PACKED_STRUCT aibss_bcn_force_config_t;
+
+#define AIBSS_TXFAIL_CONFIG_VER_0 0
+
+/* structure used to configure aibss tx fail event */
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint16 version;
+ uint16 len;
+ uint32 bcn_timeout; /* dur in seconds to receive 1 bcn */
+ uint32 max_tx_retry; /* no of consecutive no acks to send txfail event */
+} BWL_POST_PACKED_STRUCT aibss_txfail_config_t;
+
+/* no strict structure packing */
+#include <packed_section_end.h>
+
+ /* Global ASSERT Logging */
+#define ASSERTLOG_CUR_VER 0x0100
+#define MAX_ASSRTSTR_LEN 64
+
+ typedef struct assert_record {
+ uint32 time;
+ uint8 seq_num;
+ char str[MAX_ASSRTSTR_LEN];
+ } assert_record_t;
+
+ typedef struct assertlog_results {
+ uint16 version;
+ uint16 record_len;
+ uint32 num;
+ assert_record_t logs[1];
+ } assertlog_results_t;
+
+#define LOGRRC_FIX_LEN 8
+#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type))
+
+
+ /* chanim acs record */
+ typedef struct {
+ bool valid;
+ uint8 trigger;
+ chanspec_t selected_chspc;
+ int8 bgnoise;
+ uint32 glitch_cnt;
+ uint8 ccastats;
+ uint timestamp;
+ } chanim_acs_record_t;
+
+ typedef struct {
+ chanim_acs_record_t acs_record[CHANIM_ACS_RECORD];
+ uint8 count;
+ uint timestamp;
+ } wl_acs_record_t;
+
+ typedef struct chanim_stats {
+ uint32 glitchcnt; /* normalized as per second count */
+ uint32 badplcp; /* normalized as per second count */
+ uint8 ccastats[CCASTATS_MAX]; /* normalized as 0-255 */
+ int8 bgnoise; /* background noise level (in dBm) */
+ chanspec_t chanspec;
+ uint32 timestamp;
+ uint32 bphy_glitchcnt; /* normalized as per second count */
+ uint32 bphy_badplcp; /* normalized as per second count */
+ uint8 chan_idle; /* normalized as 0~255 */
+ } chanim_stats_t;
+
+#define WL_CHANIM_STATS_VERSION 2
+
+typedef struct {
+ uint32 buflen;
+ uint32 version;
+ uint32 count;
+ chanim_stats_t stats[1];
+} wl_chanim_stats_t;
+
+#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats)
+
+/* Noise measurement metrics. */
+#define NOISE_MEASURE_KNOISE 0x1
+
+/* scb probe parameter */
+typedef struct {
+ uint32 scb_timeout;
+ uint32 scb_activity_time;
+ uint32 scb_max_probe;
+} wl_scb_probe_t;
+
+/* structure/defines for selective mgmt frame (smf) stats support */
+
+#define SMFS_VERSION 1
+/* selected mgmt frame (smf) stats element */
+typedef struct wl_smfs_elem {
+ uint32 count;
+ uint16 code; /* SC or RC code */
+} wl_smfs_elem_t;
+
+typedef struct wl_smf_stats {
+ uint32 version;
+ uint16 length; /* reserved for future usage */
+ uint8 type;
+ uint8 codetype;
+ uint32 ignored_cnt;
+ uint32 malformed_cnt;
+ uint32 count_total; /* count included the interested group */
+ wl_smfs_elem_t elem[1];
+} wl_smf_stats_t;
+
+#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem);
+
+enum {
+ SMFS_CODETYPE_SC,
+ SMFS_CODETYPE_RC
+};
+
+typedef enum smfs_type {
+ SMFS_TYPE_AUTH,
+ SMFS_TYPE_ASSOC,
+ SMFS_TYPE_REASSOC,
+ SMFS_TYPE_DISASSOC_TX,
+ SMFS_TYPE_DISASSOC_RX,
+ SMFS_TYPE_DEAUTH_TX,
+ SMFS_TYPE_DEAUTH_RX,
+ SMFS_TYPE_MAX
+} smfs_type_t;
+
+#ifdef PHYMON
+
+#define PHYMON_VERSION 1
+
+typedef struct wl_phycal_core_state {
+ /* Tx IQ/LO calibration coeffs */
+ int16 tx_iqlocal_a;
+ int16 tx_iqlocal_b;
+ int8 tx_iqlocal_ci;
+ int8 tx_iqlocal_cq;
+ int8 tx_iqlocal_di;
+ int8 tx_iqlocal_dq;
+ int8 tx_iqlocal_ei;
+ int8 tx_iqlocal_eq;
+ int8 tx_iqlocal_fi;
+ int8 tx_iqlocal_fq;
+
+ /* Rx IQ calibration coeffs */
+ int16 rx_iqcal_a;
+ int16 rx_iqcal_b;
+
+ uint8 tx_iqlocal_pwridx; /* Tx Power Index for Tx IQ/LO calibration */
+ uint32 papd_epsilon_table[64]; /* PAPD epsilon table */
+ int16 papd_epsilon_offset; /* PAPD epsilon offset */
+ uint8 curr_tx_pwrindex; /* Tx power index */
+ int8 idle_tssi; /* Idle TSSI */
+ int8 est_tx_pwr; /* Estimated Tx Power (dB) */
+ int8 est_rx_pwr; /* Estimated Rx Power (dB) from RSSI */
+ uint16 rx_gaininfo; /* Rx gain applied on last Rx pkt */
+ uint16 init_gaincode; /* initgain required for ACI */
+ int8 estirr_tx;
+ int8 estirr_rx;
+
+} wl_phycal_core_state_t;
+
+typedef struct wl_phycal_state {
+ int version;
+ int8 num_phy_cores; /* number of cores */
+ int8 curr_temperature; /* on-chip temperature sensor reading */
+ chanspec_t chspec; /* channspec for this state */
+ bool aci_state; /* ACI state: ON/OFF */
+ uint16 crsminpower; /* crsminpower required for ACI */
+ uint16 crsminpowerl; /* crsminpowerl required for ACI */
+ uint16 crsminpoweru; /* crsminpoweru required for ACI */
+ wl_phycal_core_state_t phycal_core[1];
+} wl_phycal_state_t;
+
+#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core)
+#endif /* PHYMON */
+
+/* discovery state */
+typedef struct wl_p2p_disc_st {
+ uint8 state; /* see state */
+ chanspec_t chspec; /* valid in listen state */
+ uint16 dwell; /* valid in listen state, in ms */
+} wl_p2p_disc_st_t;
+
+/* scan request */
+typedef struct wl_p2p_scan {
+ uint8 type; /* 'S' for WLC_SCAN, 'E' for "escan" */
+ uint8 reserved[3];
+ /* scan or escan parms... */
+} wl_p2p_scan_t;
+
+/* i/f request */
+typedef struct wl_p2p_if {
+ struct ether_addr addr;
+ uint8 type; /* see i/f type */
+ chanspec_t chspec; /* for p2p_ifadd GO */
+} wl_p2p_if_t;
+
+/* i/f query */
+typedef struct wl_p2p_ifq {
+ uint bsscfgidx;
+ char ifname[BCM_MSG_IFNAME_MAX];
+} wl_p2p_ifq_t;
+
+/* OppPS & CTWindow */
+typedef struct wl_p2p_ops {
+ uint8 ops; /* 0: disable 1: enable */
+ uint8 ctw; /* >= 10 */
+} wl_p2p_ops_t;
+
+/* absence and presence request */
+typedef struct wl_p2p_sched_desc {
+ uint32 start;
+ uint32 interval;
+ uint32 duration;
+ uint32 count; /* see count */
+} wl_p2p_sched_desc_t;
+
+typedef struct wl_p2p_sched {
+ uint8 type; /* see schedule type */
+ uint8 action; /* see schedule action */
+ uint8 option; /* see schedule option */
+ wl_p2p_sched_desc_t desc[1];
+} wl_p2p_sched_t;
+
+typedef struct wl_bcmdcs_data {
+ uint reason;
+ chanspec_t chspec;
+} wl_bcmdcs_data_t;
+
+
+/* NAT configuration */
+typedef struct {
+ uint32 ipaddr; /* interface ip address */
+ uint32 ipaddr_mask; /* interface ip address mask */
+ uint32 ipaddr_gateway; /* gateway ip address */
+ uint8 mac_gateway[6]; /* gateway mac address */
+ uint32 ipaddr_dns; /* DNS server ip address, valid only for public if */
+ uint8 mac_dns[6]; /* DNS server mac address, valid only for public if */
+ uint8 GUID[38]; /* interface GUID */
+} nat_if_info_t;
+
+typedef struct {
+ uint op; /* operation code */
+ bool pub_if; /* set for public if, clear for private if */
+ nat_if_info_t if_info; /* interface info */
+} nat_cfg_t;
+
+typedef struct {
+ int state; /* NAT state returned */
+} nat_state_t;
+
+
+#define BTA_STATE_LOG_SZ 64
+
+/* BTAMP Statemachine states */
+enum {
+ HCIReset = 1,
+ HCIReadLocalAMPInfo,
+ HCIReadLocalAMPASSOC,
+ HCIWriteRemoteAMPASSOC,
+ HCICreatePhysicalLink,
+ HCIAcceptPhysicalLinkRequest,
+ HCIDisconnectPhysicalLink,
+ HCICreateLogicalLink,
+ HCIAcceptLogicalLink,
+ HCIDisconnectLogicalLink,
+ HCILogicalLinkCancel,
+ HCIAmpStateChange,
+ HCIWriteLogicalLinkAcceptTimeout
+};
+
+typedef struct flush_txfifo {
+ uint32 txfifobmp;
+ uint32 hwtxfifoflush;
+ struct ether_addr ea;
+} flush_txfifo_t;
+
+enum {
+ SPATIAL_MODE_2G_IDX = 0,
+ SPATIAL_MODE_5G_LOW_IDX,
+ SPATIAL_MODE_5G_MID_IDX,
+ SPATIAL_MODE_5G_HIGH_IDX,
+ SPATIAL_MODE_5G_UPPER_IDX,
+ SPATIAL_MODE_MAX_IDX
+};
+
+#define WLC_TXCORE_MAX 4 /* max number of txcore supports */
+#define WLC_SUBBAND_MAX 4 /* max number of sub-band supports */
+typedef struct {
+ uint8 band2g[WLC_TXCORE_MAX];
+ uint8 band5g[WLC_SUBBAND_MAX][WLC_TXCORE_MAX];
+} sar_limit_t;
+
+/* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */
+typedef struct wl_mempool_stats {
+ int num; /* Number of memory pools */
+ bcm_mp_stats_t s[1]; /* Variable array of memory pool stats. */
+} wl_mempool_stats_t;
+
+typedef struct {
+ uint32 ipaddr;
+ uint32 ipaddr_netmask;
+ uint32 ipaddr_gateway;
+} nwoe_ifconfig_t;
+
+/* Traffic management priority classes */
+typedef enum trf_mgmt_priority_class {
+ trf_mgmt_priority_low = 0, /* Maps to 802.1p BK */
+ trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */
+ trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */
+ trf_mgmt_priority_nochange = 3, /* do not update the priority */
+ trf_mgmt_priority_invalid = (trf_mgmt_priority_nochange + 1)
+} trf_mgmt_priority_class_t;
+
+/* Traffic management configuration parameters */
+typedef struct trf_mgmt_config {
+ uint32 trf_mgmt_enabled; /* 0 - disabled, 1 - enabled */
+ uint32 flags; /* See TRF_MGMT_FLAG_xxx defines */
+ uint32 host_ip_addr; /* My IP address to determine subnet */
+ uint32 host_subnet_mask; /* My subnet mask */
+ uint32 downlink_bandwidth; /* In units of kbps */
+ uint32 uplink_bandwidth; /* In units of kbps */
+ uint32 min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; /* Minimum guaranteed tx bandwidth */
+ uint32 min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; /* Minimum guaranteed rx bandwidth */
+} trf_mgmt_config_t;
+
+/* Traffic management filter */
+typedef struct trf_mgmt_filter {
+ struct ether_addr dst_ether_addr; /* His L2 address */
+ uint32 dst_ip_addr; /* His IP address */
+ uint16 dst_port; /* His L4 port */
+ uint16 src_port; /* My L4 port */
+ uint16 prot; /* L4 protocol (only TCP or UDP) */
+ uint16 flags; /* TBD. For now, this must be zero. */
+ trf_mgmt_priority_class_t priority; /* Priority for filtered packets */
+ uint32 dscp; /* DSCP */
+} trf_mgmt_filter_t;
+
+/* Traffic management filter list (variable length) */
+typedef struct trf_mgmt_filter_list {
+ uint32 num_filters;
+ trf_mgmt_filter_t filter[1];
+} trf_mgmt_filter_list_t;
+
+/* Traffic management global info used for all queues */
+typedef struct trf_mgmt_global_info {
+ uint32 maximum_bytes_per_second;
+ uint32 maximum_bytes_per_sampling_period;
+ uint32 total_bytes_consumed_per_second;
+ uint32 total_bytes_consumed_per_sampling_period;
+ uint32 total_unused_bytes_per_sampling_period;
+} trf_mgmt_global_info_t;
+
+/* Traffic management shaping info per priority queue */
+typedef struct trf_mgmt_shaping_info {
+ uint32 gauranteed_bandwidth_percentage;
+ uint32 guaranteed_bytes_per_second;
+ uint32 guaranteed_bytes_per_sampling_period;
+ uint32 num_bytes_produced_per_second;
+ uint32 num_bytes_consumed_per_second;
+ uint32 num_queued_packets; /* Number of packets in queue */
+ uint32 num_queued_bytes; /* Number of bytes in queue */
+} trf_mgmt_shaping_info_t;
+
+/* Traffic management shaping info array */
+typedef struct trf_mgmt_shaping_info_array {
+ trf_mgmt_global_info_t tx_global_shaping_info;
+ trf_mgmt_shaping_info_t tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES];
+ trf_mgmt_global_info_t rx_global_shaping_info;
+ trf_mgmt_shaping_info_t rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES];
+} trf_mgmt_shaping_info_array_t;
+
+
+/* Traffic management statistical counters */
+typedef struct trf_mgmt_stats {
+ uint32 num_processed_packets; /* Number of packets processed */
+ uint32 num_processed_bytes; /* Number of bytes processed */
+ uint32 num_discarded_packets; /* Number of packets discarded from queue */
+} trf_mgmt_stats_t;
+
+/* Traffic management statisics array */
+typedef struct trf_mgmt_stats_array {
+ trf_mgmt_stats_t tx_queue_stats[TRF_MGMT_MAX_PRIORITIES];
+ trf_mgmt_stats_t rx_queue_stats[TRF_MGMT_MAX_PRIORITIES];
+} trf_mgmt_stats_array_t;
+
+typedef struct powersel_params {
+ /* LPC Params exposed via IOVAR */
+ int32 tp_ratio_thresh; /* Throughput ratio threshold */
+ uint8 rate_stab_thresh; /* Thresh for rate stability based on nupd */
+ uint8 pwr_stab_thresh; /* Number of successes before power step down */
+ uint8 pwr_sel_exp_time; /* Time lapse for expiry of database */
+} powersel_params_t;
+
+typedef struct lpc_params {
+ /* LPC Params exposed via IOVAR */
+ uint8 rate_stab_thresh; /* Thresh for rate stability based on nupd */
+ uint8 pwr_stab_thresh; /* Number of successes before power step down */
+ uint8 lpc_exp_time; /* Time lapse for expiry of database */
+ uint8 pwrup_slow_step; /* Step size for slow step up */
+ uint8 pwrup_fast_step; /* Step size for fast step up */
+ uint8 pwrdn_slow_step; /* Step size for slow step down */
+} lpc_params_t;
+
+/* tx pkt delay statistics */
+#define SCB_RETRY_SHORT_DEF 7 /* Default Short retry Limit */
+#define WLPKTDLY_HIST_NBINS 16 /* number of bins used in the Delay histogram */
+
+/* structure to store per-AC delay statistics */
+typedef struct scb_delay_stats {
+ uint32 txmpdu_lost; /* number of MPDUs lost */
+ uint32 txmpdu_cnt[SCB_RETRY_SHORT_DEF]; /* retry times histogram */
+ uint32 delay_sum[SCB_RETRY_SHORT_DEF]; /* cumulative packet latency */
+ uint32 delay_min; /* minimum packet latency observed */
+ uint32 delay_max; /* maximum packet latency observed */
+ uint32 delay_avg; /* packet latency average */
+ uint32 delay_hist[WLPKTDLY_HIST_NBINS]; /* delay histogram */
+} scb_delay_stats_t;
+
+/* structure for txdelay event */
+typedef struct txdelay_event {
+ uint8 status;
+ int rssi;
+ chanim_stats_t chanim_stats;
+ scb_delay_stats_t delay_stats[AC_COUNT];
+} txdelay_event_t;
+
+/* structure for txdelay parameters */
+typedef struct txdelay_params {
+ uint16 ratio; /* Avg Txdelay Delta */
+ uint8 cnt; /* Sample cnt */
+ uint8 period; /* Sample period */
+ uint8 tune; /* Debug */
+} txdelay_params_t;
+
+enum {
+ WNM_SERVICE_DMS = 1,
+ WNM_SERVICE_FMS = 2,
+ WNM_SERVICE_TFS = 3
+};
+
+/* Definitions for WNM/NPS TCLAS */
+typedef struct wl_tclas {
+ uint8 user_priority;
+ uint8 fc_len;
+ dot11_tclas_fc_t fc;
+} wl_tclas_t;
+
+#define WL_TCLAS_FIXED_SIZE OFFSETOF(wl_tclas_t, fc)
+
+typedef struct wl_tclas_list {
+ uint32 num;
+ wl_tclas_t tclas[1];
+} wl_tclas_list_t;
+
+/* Definitions for WNM/NPS Traffic Filter Service */
+typedef struct wl_tfs_req {
+ uint8 tfs_id;
+ uint8 tfs_actcode;
+ uint8 tfs_subelem_id;
+ uint8 send;
+} wl_tfs_req_t;
+
+typedef struct wl_tfs_filter {
+ uint8 status; /* Status returned by the AP */
+ uint8 tclas_proc; /* TCLAS processing value (0:and, 1:or) */
+ uint8 tclas_cnt; /* count of all wl_tclas_t in tclas array */
+ uint8 tclas[1]; /* VLA of wl_tclas_t */
+} wl_tfs_filter_t;
+#define WL_TFS_FILTER_FIXED_SIZE OFFSETOF(wl_tfs_filter_t, tclas)
+
+typedef struct wl_tfs_fset {
+ struct ether_addr ea; /* Address of AP/STA involved with this filter set */
+ uint8 tfs_id; /* TFS ID field chosen by STA host */
+ uint8 status; /* Internal status TFS_STATUS_xxx */
+ uint8 actcode; /* Action code DOT11_TFS_ACTCODE_xxx */
+ uint8 token; /* Token used in last request frame */
+ uint8 notify; /* Notify frame sent/received because of this set */
+ uint8 filter_cnt; /* count of all wl_tfs_filter_t in filter array */
+ uint8 filter[1]; /* VLA of wl_tfs_filter_t */
+} wl_tfs_fset_t;
+#define WL_TFS_FSET_FIXED_SIZE OFFSETOF(wl_tfs_fset_t, filter)
+
+enum {
+ TFS_STATUS_DISABLED = 0, /* TFS filter set disabled by user */
+ TFS_STATUS_DISABLING = 1, /* Empty request just sent to AP */
+ TFS_STATUS_VALIDATED = 2, /* Filter set validated by AP (but maybe not enabled!) */
+ TFS_STATUS_VALIDATING = 3, /* Filter set just sent to AP */
+ TFS_STATUS_NOT_ASSOC = 4, /* STA not associated */
+ TFS_STATUS_NOT_SUPPORT = 5, /* TFS not supported by AP */
+ TFS_STATUS_DENIED = 6, /* Filter set refused by AP (=> all sets are disabled!) */
+};
+
+typedef struct wl_tfs_status {
+ uint8 fset_cnt; /* count of all wl_tfs_fset_t in fset array */
+ wl_tfs_fset_t fset[1]; /* VLA of wl_tfs_fset_t */
+} wl_tfs_status_t;
+
+typedef struct wl_tfs_set {
+ uint8 send; /* Immediatly register registered sets on AP side */
+ uint8 tfs_id; /* ID of a specific set (existing or new), or nul for all */
+ uint8 actcode; /* Action code for this filter set */
+ uint8 tclas_proc; /* TCLAS processing operator for this filter set */
+} wl_tfs_set_t;
+
+typedef struct wl_tfs_term {
+ uint8 del; /* Delete internal set once confirmation received */
+ uint8 tfs_id; /* ID of a specific set (existing), or nul for all */
+} wl_tfs_term_t;
+
+
+#define DMS_DEP_PROXY_ARP (1 << 0)
+
+/* Definitions for WNM/NPS Directed Multicast Service */
+enum {
+ DMS_STATUS_DISABLED = 0, /* DMS desc disabled by user */
+ DMS_STATUS_ACCEPTED = 1, /* Request accepted by AP */
+ DMS_STATUS_NOT_ASSOC = 2, /* STA not associated */
+ DMS_STATUS_NOT_SUPPORT = 3, /* DMS not supported by AP */
+ DMS_STATUS_DENIED = 4, /* Request denied by AP */
+ DMS_STATUS_TERM = 5, /* Request terminated by AP */
+ DMS_STATUS_REMOVING = 6, /* Remove request just sent */
+ DMS_STATUS_ADDING = 7, /* Add request just sent */
+ DMS_STATUS_ERROR = 8, /* Non compliant AP behvior */
+ DMS_STATUS_IN_PROGRESS = 9, /* Request just sent */
+ DMS_STATUS_REQ_MISMATCH = 10 /* Conditions for sending DMS req not met */
+};
+
+typedef struct wl_dms_desc {
+ uint8 user_id;
+ uint8 status;
+ uint8 token;
+ uint8 dms_id;
+ uint8 tclas_proc;
+ uint8 mac_len; /* length of all ether_addr in data array, 0 if STA */
+ uint8 tclas_len; /* length of all wl_tclas_t in data array */
+ uint8 data[1]; /* VLA of 'ether_addr' and 'wl_tclas_t' (in this order ) */
+} wl_dms_desc_t;
+
+#define WL_DMS_DESC_FIXED_SIZE OFFSETOF(wl_dms_desc_t, data)
+
+typedef struct wl_dms_status {
+ uint32 cnt;
+ wl_dms_desc_t desc[1];
+} wl_dms_status_t;
+
+typedef struct wl_dms_set {
+ uint8 send;
+ uint8 user_id;
+ uint8 tclas_proc;
+} wl_dms_set_t;
+
+typedef struct wl_dms_term {
+ uint8 del;
+ uint8 user_id;
+} wl_dms_term_t;
+
+typedef struct wl_service_term {
+ uint8 service;
+ union {
+ wl_dms_term_t dms;
+ } u;
+} wl_service_term_t;
+
+/* Definitions for WNM/NPS BSS Transistion */
+typedef struct wl_bsstrans_req {
+ uint16 tbtt; /* time of BSS to end of life, in unit of TBTT */
+ uint16 dur; /* time of BSS to keep off, in unit of minute */
+ uint8 reqmode; /* request mode of BSS transition request */
+ uint8 unicast; /* request by unicast or by broadcast */
+} wl_bsstrans_req_t;
+
+enum {
+ BSSTRANS_RESP_AUTO = 0, /* Currently equivalent to ENABLE */
+ BSSTRANS_RESP_DISABLE = 1, /* Never answer BSS Trans Req frames */
+ BSSTRANS_RESP_ENABLE = 2, /* Always answer Req frames with preset data */
+ BSSTRANS_RESP_WAIT = 3, /* Send ind, wait and/or send preset data (NOT IMPL) */
+ BSSTRANS_RESP_IMMEDIATE = 4 /* After an ind, set data and send resp (NOT IMPL) */
+};
+
+typedef struct wl_bsstrans_resp {
+ uint8 policy;
+ uint8 status;
+ uint8 delay;
+ struct ether_addr target;
+} wl_bsstrans_resp_t;
+
+/* "wnm_bsstrans_resp" argument programming behavior after BSSTRANS Req reception */
+enum {
+ WL_BSSTRANS_RESP_ROAM_ALWAYS = 0, /* Roam (or disassociate) in all cases */
+ WL_BSSTRANS_RESP_ROAM_IF_MODE = 1, /* Roam only if requested by Request Mode field */
+ WL_BSSTRANS_RESP_ROAM_IF_PREF = 2, /* Roam only if Preferred BSS provided */
+ WL_BSSTRANS_RESP_WAIT = 3 /* Wait for deauth and send Accepted status */
+};
+
+/* Definitions for WNM/NPS TIM Broadcast */
+typedef struct wl_timbc_offset {
+ int16 offset; /* offset in us */
+ uint16 fix_intv; /* override interval sent from STA */
+ uint16 rate_override; /* use rate override to send high rate TIM broadcast frame */
+ uint8 tsf_present; /* show timestamp in TIM broadcast frame */
+} wl_timbc_offset_t;
+
+typedef struct wl_timbc_set {
+ uint8 interval; /* Interval in DTIM wished or required. */
+ uint8 flags; /* Bitfield described below */
+ uint16 rate_min; /* Minimum rate required for High/Low TIM frames. Optionnal */
+ uint16 rate_max; /* Maximum rate required for High/Low TIM frames. Optionnal */
+} wl_timbc_set_t;
+
+enum {
+ WL_TIMBC_SET_TSF_REQUIRED = 1, /* Enable TIMBC only if TSF in TIM frames */
+ WL_TIMBC_SET_NO_OVERRIDE = 2, /* ... if AP does not override interval */
+ WL_TIMBC_SET_PROXY_ARP = 4, /* ... if AP support Proxy ARP */
+ WL_TIMBC_SET_DMS_ACCEPTED = 8 /* ... if all DMS desc have been accepted */
+};
+
+typedef struct wl_timbc_status {
+ uint8 status_sta; /* Status from internal state machine (check below) */
+ uint8 status_ap; /* From AP response frame (check 8.4.2.86 from 802.11) */
+ uint8 interval;
+ uint8 pad;
+ int32 offset;
+ uint16 rate_high;
+ uint16 rate_low;
+} wl_timbc_status_t;
+
+enum {
+ WL_TIMBC_STATUS_DISABLE = 0, /* TIMBC disabled by user */
+ WL_TIMBC_STATUS_REQ_MISMATCH = 1, /* AP settings do no match user requirements */
+ WL_TIMBC_STATUS_NOT_ASSOC = 2, /* STA not associated */
+ WL_TIMBC_STATUS_NOT_SUPPORT = 3, /* TIMBC not supported by AP */
+ WL_TIMBC_STATUS_DENIED = 4, /* Req to disable TIMBC sent to AP */
+ WL_TIMBC_STATUS_ENABLE = 5 /* TIMBC enabled */
+};
+
+/* Definitions for PM2 Dynamic Fast Return To Sleep */
+typedef struct wl_pm2_sleep_ret_ext {
+ uint8 logic; /* DFRTS logic: see WL_DFRTS_LOGIC_* below */
+ uint16 low_ms; /* Low FRTS timeout */
+ uint16 high_ms; /* High FRTS timeout */
+ uint16 rx_pkts_threshold; /* switching threshold: # rx pkts */
+ uint16 tx_pkts_threshold; /* switching threshold: # tx pkts */
+ uint16 txrx_pkts_threshold; /* switching threshold: # (tx+rx) pkts */
+ uint32 rx_bytes_threshold; /* switching threshold: # rx bytes */
+ uint32 tx_bytes_threshold; /* switching threshold: # tx bytes */
+ uint32 txrx_bytes_threshold; /* switching threshold: # (tx+rx) bytes */
+} wl_pm2_sleep_ret_ext_t;
+
+#define WL_DFRTS_LOGIC_OFF 0 /* Feature is disabled */
+#define WL_DFRTS_LOGIC_OR 1 /* OR all non-zero threshold conditions */
+#define WL_DFRTS_LOGIC_AND 2 /* AND all non-zero threshold conditions */
+
+/* Values for the passive_on_restricted_mode iovar. When set to non-zero, this iovar
+ * disables automatic conversions of a channel from passively scanned to
+ * actively scanned. These values only have an effect for country codes such
+ * as XZ where some 5 GHz channels are defined to be passively scanned.
+ */
+#define WL_PASSACTCONV_DISABLE_NONE 0 /* Enable permanent and temporary conversions */
+#define WL_PASSACTCONV_DISABLE_ALL 1 /* Disable permanent and temporary conversions */
+#define WL_PASSACTCONV_DISABLE_PERM 2 /* Disable only permanent conversions */
+
+/* Definitions for Reliable Multicast */
+#define WL_RMC_CNT_VERSION 1
+#define WL_RMC_MAX_CLIENT 32
+#define WL_RMC_FLAG_INBLACKLIST 1
+#define WL_RMC_FLAG_ACTIVEACKER 2
+#define WL_RMC_FLAG_RELMCAST 4
+#define WL_RMC_MAX_TABLE_ENTRY 4
+
+#define WL_RMC_VER 1
+#define WL_RMC_INDEX_ACK_ALL 255
+#define WL_RMC_NUM_OF_MC_STREAMS 4
+#define WL_RMC_MAX_TRS_PER_GROUP 1
+#define WL_RMC_MAX_TRS_IN_ACKALL 1
+#define WL_RMC_ACK_MCAST0 0x02
+#define WL_RMC_ACK_MCAST_ALL 0x01
+#define WL_RMC_ACTF_TIME_MIN 300 /* time in ms */
+#define WL_RMC_ACTF_TIME_MAX 20000 /* time in ms */
+#define WL_RMC_ARTMO_MIN 350 /* time in ms */
+#define WL_RMC_ARTMO_MAX 40000 /* time in ms */
+
+/* RMC events in action frames */
+enum rmc_opcodes {
+ RELMCAST_ENTRY_OP_DISABLE = 0, /* Disable multi-cast group */
+ RELMCAST_ENTRY_OP_DELETE = 1, /* Delete multi-cast group */
+ RELMCAST_ENTRY_OP_ENABLE = 2, /* Enable multi-cast group */
+ RELMCAST_ENTRY_OP_ACK_ALL = 3 /* Enable ACK ALL bit in AMT */
+};
+
+/* RMC operational modes */
+enum rmc_modes {
+ WL_RMC_MODE_RECEIVER = 0, /* Receiver mode by default */
+ WL_RMC_MODE_TRANSMITTER = 1, /* Transmitter mode using wl ackreq */
+ WL_RMC_MODE_INITIATOR = 2 /* Initiator mode using wl ackreq */
+};
+
+/* Each RMC mcast client info */
+typedef struct wl_relmcast_client {
+ uint8 flag; /* status of client such as AR, R, or blacklisted */
+ int16 rssi; /* rssi value of RMC client */
+ struct ether_addr addr; /* mac address of RMC client */
+} wl_relmcast_client_t;
+
+/* RMC Counters */
+typedef struct wl_rmc_cnts {
+ uint16 version; /* see definition of WL_CNT_T_VERSION */
+ uint16 length; /* length of entire structure */
+ uint16 dupcnt; /* counter for duplicate rmc MPDU */
+ uint16 ackreq_err; /* counter for wl ackreq error */
+ uint16 af_tx_err; /* error count for action frame transmit */
+ uint16 null_tx_err; /* error count for rmc null frame transmit */
+ uint16 af_unicast_tx_err; /* error count for rmc unicast frame transmit */
+ uint16 mc_no_amt_slot; /* No mcast AMT entry available */
+ uint16 mc_no_glb_slot; /* No mcast entry available in global table */
+ uint16 mc_not_mirrored; /* mcast group is not mirrored */
+ uint16 mc_existing_tr; /* mcast group is already taken by transmitter */
+ uint16 mc_exist_in_amt; /* mcast group is already programmed in amt */
+ uint16 mc_not_exist_in_gbl; /* mcast group is not in global table */
+ uint16 mc_not_exist_in_amt; /* mcast group is not in AMT table */
+ uint16 mc_utilized; /* mcast addressed is already taken */
+ uint16 mc_taken_other_tr; /* multi-cast addressed is already taken */
+ uint32 rmc_rx_frames_mac; /* no of mc frames received from mac */
+ uint32 rmc_tx_frames_mac; /* no of mc frames transmitted to mac */
+ uint32 mc_null_ar_cnt; /* no. of times NULL AR is received */
+ uint32 mc_ar_role_selected; /* no. of times took AR role */
+ uint32 mc_ar_role_deleted; /* no. of times AR role cancelled */
+ uint32 mc_noacktimer_expired; /* no. of times noack timer expired */
+} wl_rmc_cnts_t;
+
+/* RMC Status */
+typedef struct wl_relmcast_st {
+ uint8 ver; /* version of RMC */
+ uint8 num; /* number of clients detected by transmitter */
+ wl_relmcast_client_t clients[WL_RMC_MAX_CLIENT];
+ uint16 err; /* error status (used in infra) */
+ uint16 actf_time; /* action frame time period */
+} wl_relmcast_status_t;
+
+/* Entry for each STA/node */
+typedef struct wl_rmc_entry {
+ /* operation on multi-cast entry such add,
+ * delete, ack-all
+ */
+ int8 flag;
+ struct ether_addr addr; /* multi-cast group mac address */
+} wl_rmc_entry_t;
+
+/* RMC table */
+typedef struct wl_rmc_entry_table {
+ uint8 index; /* index to a particular mac entry in table */
+ uint8 opcode; /* opcodes or operation on entry */
+ wl_rmc_entry_t entry[WL_RMC_MAX_TABLE_ENTRY];
+} wl_rmc_entry_table_t;
+
+/* Transmitter Info */
+typedef struct wl_rmc_trans_info {
+ struct ether_addr addr; /* transmitter mac */
+ uint32 time_val; /* timer val in case aging of entry is required */
+ uint16 seq; /* last seq number of packet received from transmitter */
+ uint16 artmo;
+} wl_rmc_trans_info_t;
+
+/* Multicast Group */
+typedef struct wl_rmc_grp_entry {
+ struct ether_addr mcaddr; /* multi-cast group mac */
+ struct ether_addr ar; /* active receiver for the group */
+ wl_rmc_trans_info_t tr_info[WL_RMC_MAX_TRS_PER_GROUP];
+} wl_rmc_grp_entry_t;
+
+/* RMC ACKALL Table */
+typedef struct wl_rmc_ackall_entry {
+ struct ether_addr ar; /* active receiver for the entry */
+ wl_rmc_trans_info_t tr_info[WL_RMC_NUM_OF_MC_STREAMS];
+} wl_rmc_ackall_entry_t;
+
+/* RMC Peers Table */
+typedef struct wl_rmc_gbl_table {
+ uint8 activeMask; /* mask to denote the entry(s) that are active */
+ wl_rmc_ackall_entry_t ackAll; /* structure to keep info related to ACK all */
+ wl_rmc_grp_entry_t mc_entry[WL_RMC_NUM_OF_MC_STREAMS];
+} wl_rmc_gbl_table_t;
+
+/* To update vendor specific ie for RMC */
+typedef struct wl_rmc_vsie {
+ uint8 oui[DOT11_OUI_LEN];
+ uint16 payload; /* IE Data Payload */
+} wl_rmc_vsie_t;
+
+/* structures & defines for proximity detection */
+enum proxd_method {
+ PROXD_UNDEFINED_METHOD = 0,
+ PROXD_RSSI_METHOD = 1,
+ PROXD_TOF_METHOD = 2
+};
+
+/* structures for proximity detection device role */
+#define WL_PROXD_MODE_DISABLE 0
+#define WL_PROXD_MODE_NEUTRAL 1
+#define WL_PROXD_MODE_INITIATOR 2
+#define WL_PROXD_MODE_TARGET 3
+
+#define WL_PROXD_ACTION_STOP 0
+#define WL_PROXD_ACTION_START 1
+
+#define WL_PROXD_FLAG_TARGET_REPORT 0x1
+#define WL_PROXD_FLAG_REPORT_FAILURE 0x2
+#define WL_PROXD_FLAG_INITIATOR_REPORT 0x4
+#define WL_PROXD_FLAG_NOCHANSWT 0x8
+#define WL_PROXD_FLAG_NETRUAL 0x10
+#define WL_PROXD_FLAG_INITIATOR_RPTRTT 0x20
+#define WL_PROXD_FLAG_ONEWAY 0x40
+#define WL_PROXD_FLAG_SEQ_EN 0x80
+
+#define WL_PROXD_RANDOM_WAKEUP 0x8000
+
+typedef struct wl_proxd_iovar {
+ uint16 method; /* Proxmity Detection method */
+ uint16 mode; /* Mode (neutral, initiator, target) */
+} wl_proxd_iovar_t;
+
+/*
+ * structures for proximity detection parameters
+ * consists of two parts, common and method specific params
+ * common params should be placed at the beginning
+ */
+
+/* require strict packing */
+#include <packed_section_start.h>
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_common {
+ chanspec_t chanspec; /* channel spec */
+ int16 tx_power; /* tx power of Proximity Detection(PD) frames (in dBm) */
+ uint16 tx_rate; /* tx rate of PD rames (in 500kbps units) */
+ uint16 timeout; /* timeout value */
+ uint16 interval; /* interval between neighbor finding attempts (in TU) */
+ uint16 duration; /* duration of neighbor finding attempts (in ms) */
+} BWL_POST_PACKED_STRUCT wl_proxd_params_common_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_rssi_method {
+ chanspec_t chanspec; /* chanspec for home channel */
+ int16 tx_power; /* tx power of Proximity Detection frames (in dBm) */
+ uint16 tx_rate; /* tx rate of PD frames, 500kbps units */
+ uint16 timeout; /* state machine wait timeout of the frames (in ms) */
+ uint16 interval; /* interval between neighbor finding attempts (in TU) */
+ uint16 duration; /* duration of neighbor finding attempts (in ms) */
+ /* method specific ones go after this line */
+ int16 rssi_thresh; /* RSSI threshold (in dBm) */
+ uint16 maxconvergtmo; /* max wait converge timeout (in ms) */
+} wl_proxd_params_rssi_method_t;
+
+#define Q1_NS 25 /* Q1 time units */
+
+#define TOF_BW_NUM 3 /* number of bandwidth that the TOF can support */
+#define TOF_BW_SEQ_NUM (TOF_BW_NUM+2) /* number of total index */
+enum tof_bw_index {
+ TOF_BW_20MHZ_INDEX = 0,
+ TOF_BW_40MHZ_INDEX = 1,
+ TOF_BW_80MHZ_INDEX = 2,
+ TOF_BW_SEQTX_INDEX = 3,
+ TOF_BW_SEQRX_INDEX = 4
+};
+
+#define BANDWIDTH_BASE 20 /* base value of bandwidth */
+#define TOF_BW_20MHZ (BANDWIDTH_BASE << TOF_BW_20MHZ_INDEX)
+#define TOF_BW_40MHZ (BANDWIDTH_BASE << TOF_BW_40MHZ_INDEX)
+#define TOF_BW_80MHZ (BANDWIDTH_BASE << TOF_BW_80MHZ_INDEX)
+#define TOF_BW_10MHZ 10
+
+#define NFFT_BASE 64 /* base size of fft */
+#define TOF_NFFT_20MHZ (NFFT_BASE << TOF_BW_20MHZ_INDEX)
+#define TOF_NFFT_40MHZ (NFFT_BASE << TOF_BW_40MHZ_INDEX)
+#define TOF_NFFT_80MHZ (NFFT_BASE << TOF_BW_80MHZ_INDEX)
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_method {
+ chanspec_t chanspec; /* chanspec for home channel */
+ int16 tx_power; /* tx power of Proximity Detection(PD) frames (in dBm) */
+ uint16 tx_rate; /* tx rate of PD rames (in 500kbps units) */
+ uint16 timeout; /* state machine wait timeout of the frames (in ms) */
+ uint16 interval; /* interval between neighbor finding attempts (in TU) */
+ uint16 duration; /* duration of neighbor finding attempts (in ms) */
+ /* specific for the method go after this line */
+ struct ether_addr tgt_mac; /* target mac addr for TOF method */
+ uint16 ftm_cnt; /* number of the frames txed by initiator */
+ uint16 retry_cnt; /* number of retransmit attampts for ftm frames */
+ int16 vht_rate; /* ht or vht rate */
+ /* add more params required for other methods can be added here */
+} BWL_POST_PACKED_STRUCT wl_proxd_params_tof_method_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_tune {
+ uint32 Ki; /* h/w delay K factor for initiator */
+ uint32 Kt; /* h/w delay K factor for target */
+ int16 vhtack; /* enable/disable VHT ACK */
+ int16 N_log2[TOF_BW_SEQ_NUM]; /* simple threshold crossing */
+ int16 w_offset[TOF_BW_NUM]; /* offset of threshold crossing window(per BW) */
+ int16 w_len[TOF_BW_NUM]; /* length of threshold crossing window(per BW) */
+ int32 maxDT; /* max time difference of T4/T1 or T3/T2 */
+ int32 minDT; /* min time difference of T4/T1 or T3/T2 */
+ uint8 totalfrmcnt; /* total count of transfered measurement frames */
+ uint16 rsv_media; /* reserve media value for TOF */
+ uint32 flags; /* flags */
+ uint8 core; /* core to use for tx */
+ uint8 force_K; /* set to force value of K */
+ int16 N_scale[TOF_BW_SEQ_NUM]; /* simple threshold crossing */
+ uint8 sw_adj; /* enable sw assisted timestamp adjustment */
+ uint8 hw_adj; /* enable hw assisted timestamp adjustment */
+ uint8 seq_en; /* enable ranging sequence */
+ uint8 ftm_cnt[TOF_BW_SEQ_NUM]; /* number of ftm frames based on bandwidth */
+} BWL_POST_PACKED_STRUCT wl_proxd_params_tof_tune_t;
+
+typedef struct wl_proxd_params_iovar {
+ uint16 method; /* Proxmity Detection method */
+ union {
+ /* common params for pdsvc */
+ wl_proxd_params_common_t cmn_params; /* common parameters */
+ /* method specific */
+ wl_proxd_params_rssi_method_t rssi_params; /* RSSI method parameters */
+ wl_proxd_params_tof_method_t tof_params; /* TOF meothod parameters */
+ /* tune parameters */
+ wl_proxd_params_tof_tune_t tof_tune; /* TOF tune parameters */
+ } u; /* Method specific optional parameters */
+} wl_proxd_params_iovar_t;
+
+#define PROXD_COLLECT_GET_STATUS 0
+#define PROXD_COLLECT_SET_STATUS 1
+#define PROXD_COLLECT_QUERY_HEADER 2
+#define PROXD_COLLECT_QUERY_DATA 3
+#define PROXD_COLLECT_QUERY_DEBUG 4
+#define PROXD_COLLECT_REMOTE_REQUEST 5
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_query {
+ uint32 method; /* method */
+ uint8 request; /* Query request. */
+ uint8 status; /* 0 -- disable, 1 -- enable collection, */
+ /* 2 -- enable collection & debug */
+ uint16 index; /* The current frame index [0 to total_frames - 1]. */
+ uint16 mode; /* Initiator or Target */
+ bool busy; /* tof sm is busy */
+ bool remote; /* Remote collect data */
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_query_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_header {
+ uint16 total_frames; /* The totral frames for this collect. */
+ uint16 nfft; /* nfft value */
+ uint16 bandwidth; /* bandwidth */
+ uint16 channel; /* channel number */
+ uint32 chanspec; /* channel spec */
+ uint32 fpfactor; /* avb timer value factor */
+ uint16 fpfactor_shift; /* avb timer value shift bits */
+ int32 distance; /* distance calculated by fw */
+ uint32 meanrtt; /* mean of RTTs */
+ uint32 modertt; /* mode of RTTs */
+ uint32 medianrtt; /* median of RTTs */
+ uint32 sdrtt; /* standard deviation of RTTs */
+ uint32 clkdivisor; /* clock divisor */
+ uint16 chipnum; /* chip type */
+ uint8 chiprev; /* chip revision */
+ uint8 phyver; /* phy version */
+ struct ether_addr loaclMacAddr; /* local mac address */
+ struct ether_addr remoteMacAddr; /* remote mac address */
+ wl_proxd_params_tof_tune_t params;
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_header_t;
+
+/* ********************** NAN wl interface struct types and defs ******************** */
+
+#define WL_NAN_IOCTL_VERSION 0x1
+
+/* wl_nan_sub_cmd may also be used in dhd */
+typedef struct wl_nan_sub_cmd wl_nan_sub_cmd_t;
+typedef int (cmd_handler_t)(void *wl, const wl_nan_sub_cmd_t *cmd, char **argv);
+/* nan cmd list entry */
+struct wl_nan_sub_cmd {
+ char *name;
+ uint8 version; /* cmd version */
+ uint16 id; /* id for the dongle f/w switch/case */
+ uint16 type; /* base type of argument */
+ cmd_handler_t *handler; /* cmd handler */
+};
+
+/* container for nan iovtls & events */
+typedef BWL_PRE_PACKED_STRUCT struct wl_nan_ioc {
+ uint16 version; /* interface command or event version */
+ uint16 id; /* nan ioctl cmd ID */
+ uint16 len; /* total length of all tlv records in data[] */
+ uint8 data [1]; /* var len payload of bcm_xtlv_t type */
+} BWL_POST_PACKED_STRUCT wl_nan_ioc_t;
+
+typedef struct wl_nan_status {
+ uint8 inited;
+ uint8 joined;
+ uint8 role;
+ uint8 hop_count;
+ uint32 chspec;
+ uint8 amr[8]; /* Anchor Master Rank */
+ uint32 cnt_pend_txfrm; /* pending TX frames */
+ uint32 cnt_bcn_tx; /* TX disc/sync beacon count */
+ uint32 cnt_bcn_rx; /* RX disc/sync beacon count */
+ uint32 cnt_svc_disc_tx; /* TX svc disc frame count */
+ uint32 cnt_svc_disc_rx; /* RX svc disc frame count */
+ struct ether_addr cid;
+} wl_nan_status_t;
+
+/* various params and ctl swithce for nan_debug instance */
+typedef struct nan_debug_params {
+ uint8 enabled; /* runtime debuging enabled */
+ uint8 collect; /* enables debug svc sdf monitor mode */
+ uint16 cmd; /* debug cmd to perform a debug action */
+ uint32 msglevel; /* msg level if enabled */
+ uint16 status;
+} nan_debug_params_t;
+
+
+/* nan passive scan params */
+#define NAN_SCAN_MAX_CHCNT 8
+typedef BWL_PRE_PACKED_STRUCT struct nan_scan_params {
+ uint16 scan_time;
+ uint16 home_time;
+ uint16 ms_intvl; /* interval between merge scan */
+ uint16 ms_dur; /* duration of merge scan */
+ uint16 chspec_num;
+ chanspec_t chspec_list[NAN_SCAN_MAX_CHCNT]; /* act. used 3, 5 rfu */
+} BWL_POST_PACKED_STRUCT nan_scan_params_t;
+
+enum wl_nan_role {
+ WL_NAN_ROLE_AUTO = 0,
+ WL_NAN_ROLE_NON_MASTER_NON_SYNC = 1,
+ WL_NAN_ROLE_NON_MASTER_SYNC = 2,
+ WL_NAN_ROLE_MASTER = 3,
+ WL_NAN_ROLE_ANCHOR_MASTER = 4
+};
+#define NAN_MASTER_RANK_LEN 8
+/* nan cmd IDs */
+enum wl_nan_cmds {
+ /* nan cfg /disc & dbg ioctls */
+ WL_NAN_CMD_ENABLE = 1,
+ WL_NAN_CMD_ATTR = 2,
+ WL_NAN_CMD_NAN_JOIN = 3,
+ WL_NAN_CMD_LEAVE = 4,
+ WL_NAN_CMD_MERGE = 5,
+ WL_NAN_CMD_STATUS = 6,
+ /* discovery engine commands */
+ WL_NAN_CMD_PUBLISH = 20,
+ WL_NAN_CMD_SUBSCRIBE = 21,
+ WL_NAN_CMD_CANCEL_PUBLISH = 22,
+ WL_NAN_CMD_CANCEL_SUBSCRIBE = 23,
+ WL_NAN_CMD_TRANSMIT = 24,
+ WL_NAN_CMD_CONNECTION = 25,
+ WL_NAN_CMD_SHOW = 26,
+ WL_NAN_CMD_STOP = 27, /* stop nan for a given cluster ID */
+ /* nan debug iovars & cmds */
+ WL_NAN_CMD_SCAN_PARAMS = 46,
+ WL_NAN_CMD_SCAN = 47,
+ WL_NAN_CMD_SCAN_RESULTS = 48,
+ WL_NAN_CMD_EVENT_MASK = 49,
+ WL_NAN_CMD_EVENT_CHECK = 50,
+
+ WL_NAN_CMD_DEBUG = 60,
+ WL_NAN_CMD_TEST1 = 61,
+ WL_NAN_CMD_TEST2 = 62,
+ WL_NAN_CMD_TEST3 = 63
+};
+
+/*
+ * tlv IDs uniquely identifies cmd parameters
+ * packed into wl_nan_ioc_t container
+ */
+enum wl_nan_cmd_xtlv_id {
+ /* 0x00 ~ 0xFF: standard TLV ID whose data format is the same as NAN attribute TLV */
+ WL_NAN_XTLV_ZERO = 0, /* used as tlv buf end marker */
+#ifdef NAN_STD_TLV /* rfu, don't use yet */
+ WL_NAN_XTLV_MASTER_IND = 1, /* == NAN_ATTR_MASTER_IND, */
+ WL_NAN_XTLV_CLUSTER = 2, /* == NAN_ATTR_CLUSTER, */
+ WL_NAN_XTLV_VENDOR = 221, /* == NAN_ATTR_VENDOR, */
+#endif
+ /* 0x02 ~ 0xFF: reserved. In case to use with the same data format as NAN attribute TLV */
+ /* 0x100 ~ : private TLV ID defined just for NAN command */
+ /* common types */
+ WL_NAN_XTLV_BUFFER = 0x101, /* generic type, function depends on cmd context */
+ WL_NAN_XTLV_MAC_ADDR = 0x102, /* used in various cmds */
+ WL_NAN_XTLV_REASON = 0x103,
+ WL_NAN_XTLV_ENABLE = 0x104,
+ /* explicit types, primarily for discovery engine iovars */
+ WL_NAN_XTLV_SVC_PARAMS = 0x120, /* Contains required params: wl_nan_disc_params_t */
+ WL_NAN_XTLV_MATCH_RX = 0x121, /* Matching filter to evaluate on receive */
+ WL_NAN_XTLV_MATCH_TX = 0x122, /* Matching filter to send */
+ WL_NAN_XTLV_SVC_INFO = 0x123, /* Service specific info */
+ WL_NAN_XTLV_SVC_NAME = 0x124, /* Optional UTF-8 service name, for debugging. */
+ WL_NAN_XTLV_INSTANCE_ID = 0x125, /* Identifies unique publish or subscribe instance */
+ WL_NAN_XTLV_PRIORITY = 0x126, /* used in transmit cmd context */
+ WL_NAN_XTLV_REQUESTOR_ID = 0x127, /* Requestor instance ID */
+ WL_NAN_XTLV_VNDR = 0x128, /* Vendor specific attribute */
+ /* explicit types, primarily for NAN MAC iovars */
+ WL_NAN_XTLV_DW_LEN = 0x140, /* discovery win length */
+ WL_NAN_XTLV_BCN_INTERVAL = 0x141, /* beacon interval, both sync and descovery bcns? */
+ WL_NAN_XTLV_CLUSTER_ID = 0x142,
+ WL_NAN_XTLV_IF_ADDR = 0x143,
+ WL_NAN_XTLV_MC_ADDR = 0x144,
+ WL_NAN_XTLV_ROLE = 0x145,
+ WL_NAN_XTLV_START = 0x146,
+
+ WL_NAN_XTLV_MASTER_PREF = 0x147,
+ WL_NAN_XTLV_DW_INTERVAL = 0x148,
+ WL_NAN_XTLV_PTBTT_OVERRIDE = 0x149,
+ /* nan status command xtlvs */
+ WL_NAN_XTLV_MAC_INITED = 0x14a,
+ WL_NAN_XTLV_MAC_ENABLED = 0x14b,
+ WL_NAN_XTLV_MAC_CHANSPEC = 0x14c,
+ WL_NAN_XTLV_MAC_AMR = 0x14d, /* anchormaster rank u8 amr[8] */
+ WL_NAN_XTLV_MAC_HOPCNT = 0x14e,
+ WL_NAN_XTLV_MAC_AMBTT = 0x14f,
+ WL_NAN_XTLV_MAC_TXRATE = 0x150,
+ WL_NAN_XTLV_MAC_STATUS = 0x151, /* xtlv payload is nan_status_t */
+ WL_NAN_XTLV_NAN_SCANPARAMS = 0x152, /* payload is nan_scan_params_t */
+ WL_NAN_XTLV_DEBUGPARAMS = 0x153, /* payload is nan_scan_params_t */
+ WL_NAN_XTLV_SUBSCR_ID = 0x154, /* subscriber id */
+ WL_NAN_XTLV_PUBLR_ID = 0x155, /* publisher id */
+ WL_NAN_XTLV_EVENT_MASK = 0x156,
+ WL_NAN_XTLV_MERGE = 0x157
+};
+
+/* Flag bits for Publish and Subscribe (wl_nan_disc_params_t flags) */
+#define WL_NAN_RANGE_LIMITED 0x0040
+/* Bits specific to Publish */
+/* Unsolicited transmissions */
+#define WL_NAN_PUB_UNSOLICIT 0x1000
+/* Solicited transmissions */
+#define WL_NAN_PUB_SOLICIT 0x2000
+#define WL_NAN_PUB_BOTH 0x3000
+/* Set for broadcast solicited transmission
+ * Do not set for unicast solicited transmission
+ */
+#define WL_NAN_PUB_BCAST 0x4000
+/* Generate event on each solicited transmission */
+#define WL_NAN_PUB_EVENT 0x8000
+/* Used for one-time solicited Publish functions to indicate transmision occurred */
+#define WL_NAN_PUB_SOLICIT_PENDING 0x10000
+/* Follow-up frames */
+#define WL_NAN_FOLLOWUP 0x20000
+/* Bits specific to Subscribe */
+/* Active subscribe mode (Leave unset for passive) */
+#define WL_NAN_SUB_ACTIVE 0x1000
+
+/* Special values for time to live (ttl) parameter */
+#define WL_NAN_TTL_UNTIL_CANCEL 0xFFFFFFFF
+/* Publish - runs until first transmission
+ * Subscribe - runs until first DiscoveryResult event
+ */
+#define WL_NAN_TTL_FIRST 0
+
+/* The service hash (service id) is exactly this many bytes. */
+#define WL_NAN_SVC_HASH_LEN 6
+
+/* Instance ID type (unique identifier) */
+typedef uint8 wl_nan_instance_id_t;
+
+/* Mandatory parameters for publish/subscribe iovars - NAN_TLV_SVC_PARAMS */
+typedef struct wl_nan_disc_params_s {
+ /* Periodicity of unsolicited/query transmissions, in DWs */
+ uint32 period;
+ /* Time to live in DWs */
+ uint32 ttl;
+ /* Flag bits */
+ uint32 flags;
+ /* Publish or subscribe service id, i.e. hash of the service name */
+ uint8 svc_hash[WL_NAN_SVC_HASH_LEN];
+ /* Publish or subscribe id */
+ wl_nan_instance_id_t instance_id;
+} wl_nan_disc_params_t;
+
+/*
+* desovery interface event structures *
+*/
+
+/* NAN Ranging */
+
+/* Bit defines for global flags */
+#define WL_NAN_RANGING_ENABLE 1 /* enable RTT */
+#define WL_NAN_RANGING_RANGED 2 /* Report to host if ranged as target */
+typedef struct nan_ranging_config {
+ uint32 chanspec; /* Ranging chanspec */
+ uint16 timeslot; /* NAN RTT start time slot 1-511 */
+ uint16 duration; /* NAN RTT duration in ms */
+ struct ether_addr allow_mac; /* peer initiated ranging: the allowed peer mac
+ * address, a unicast (for one peer) or
+ * a broadcast for all. Setting it to all zeros
+ * means responding to none,same as not setting
+ * the flag bit NAN_RANGING_RESPOND
+ */
+ uint16 flags;
+} wl_nan_ranging_config_t;
+
+/* list of peers for self initiated ranging */
+/* Bit defines for per peer flags */
+#define WL_NAN_RANGING_REPORT (1<<0) /* Enable reporting range to target */
+typedef struct nan_ranging_peer {
+ uint32 chanspec; /* desired chanspec for this peer */
+ uint32 abitmap; /* available bitmap */
+ struct ether_addr ea; /* peer MAC address */
+ uint8 frmcnt; /* frame count */
+ uint8 retrycnt; /* retry count */
+ uint16 flags; /* per peer flags, report or not */
+} wl_nan_ranging_peer_t;
+typedef struct nan_ranging_list {
+ uint8 count; /* number of MAC addresses */
+ uint8 num_peers_done; /* host set to 0, when read, shows number of peers
+ * completed, success or fail
+ */
+ uint8 num_dws; /* time period to do the ranging, specified in dws */
+ uint8 reserve; /* reserved field */
+ wl_nan_ranging_peer_t rp[1]; /* variable length array of peers */
+} wl_nan_ranging_list_t;
+
+/* ranging results, a list for self initiated ranging and one for peer initiated ranging */
+/* There will be one structure for each peer */
+#define WL_NAN_RANGING_STATUS_SUCCESS 1
+#define WL_NAN_RANGING_STATUS_FAIL 2
+#define WL_NAN_RANGING_STATUS_TIMEOUT 3
+#define WL_NAN_RANGING_STATUS_ABORT 4 /* with partial results if sounding count > 0 */
+typedef struct nan_ranging_result {
+ uint8 status; /* 1: Success, 2: Fail 3: Timeout 4: Aborted */
+ uint8 sounding_count; /* number of measurements completed (0 = failure) */
+ struct ether_addr ea; /* initiator MAC address */
+ uint32 chanspec; /* Chanspec where the ranging was done */
+ uint32 timestamp; /* 32bits of the TSF timestamp ranging was completed at */
+ uint32 distance; /* mean distance in meters expressed as Q4 number.
+ * Only valid when sounding_count > 0. Examples:
+ * 0x08 = 0.5m
+ * 0x10 = 1m
+ * 0x18 = 1.5m
+ * set to 0xffffffff to indicate invalid number
+ */
+ int32 rtt_var; /* standard deviation in 10th of ns of RTTs measured.
+ * Only valid when sounding_count > 0
+ */
+ struct ether_addr tgtea; /* target MAC address */
+} wl_nan_ranging_result_t;
+typedef struct nan_ranging_event_data {
+ uint8 mode; /* 1: Result of host initiated ranging */
+ /* 2: Result of peer initiated ranging */
+ uint8 reserved;
+ uint8 success_count; /* number of peers completed successfully */
+ uint8 count; /* number of peers in the list */
+ wl_nan_ranging_result_t rr[1]; /* variable array of ranging peers */
+} wl_nan_ranging_event_data_t;
+
+/* ********************* end of NAN section ******************************** */
+
+#define RSSI_THRESHOLD_SIZE 16
+#define MAX_IMP_RESP_SIZE 256
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_rssi_bias {
+ int32 version; /* version */
+ int32 threshold[RSSI_THRESHOLD_SIZE]; /* threshold */
+ int32 peak_offset; /* peak offset */
+ int32 bias; /* rssi bias */
+ int32 gd_delta; /* GD - GD_ADJ */
+ int32 imp_resp[MAX_IMP_RESP_SIZE]; /* (Hi*Hi)+(Hr*Hr) */
+} BWL_POST_PACKED_STRUCT wl_proxd_rssi_bias_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_rssi_bias_avg {
+ int32 avg_threshold[RSSI_THRESHOLD_SIZE]; /* avg threshold */
+ int32 avg_peak_offset; /* avg peak offset */
+ int32 avg_rssi; /* avg rssi */
+ int32 avg_bias; /* avg bias */
+} BWL_POST_PACKED_STRUCT wl_proxd_rssi_bias_avg_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_info {
+ uint16 type; /* type: 0 channel table, 1 channel smoothing table, 2 and 3 seq */
+ uint16 index; /* The current frame index, from 1 to total_frames. */
+ uint16 tof_cmd; /* M_TOF_CMD */
+ uint16 tof_rsp; /* M_TOF_RSP */
+ uint16 tof_avb_rxl; /* M_TOF_AVB_RX_L */
+ uint16 tof_avb_rxh; /* M_TOF_AVB_RX_H */
+ uint16 tof_avb_txl; /* M_TOF_AVB_TX_L */
+ uint16 tof_avb_txh; /* M_TOF_AVB_TX_H */
+ uint16 tof_id; /* M_TOF_ID */
+ uint8 tof_frame_type;
+ uint8 tof_frame_bw;
+ int8 tof_rssi;
+ int32 tof_cfo;
+ int32 gd_adj_ns; /* gound delay */
+ int32 gd_h_adj_ns; /* group delay + threshold crossing */
+#ifdef RSSI_REFINE
+ wl_proxd_rssi_bias_t rssi_bias; /* RSSI refinement info */
+#endif
+ int16 nfft; /* number of samples stored in H */
+
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_info_t;
+
+#define k_tof_collect_H_pad 1
+#define k_tof_collect_H_size (256+16+k_tof_collect_H_pad)
+#define k_tof_collect_Hraw_size (2*k_tof_collect_H_size)
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_data {
+ wl_proxd_collect_info_t info;
+ uint32 H[k_tof_collect_H_size]; /* raw data read from phy used to adjust timestamps */
+
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_data_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_debug_data {
+ uint8 count; /* number of packets */
+ uint8 stage; /* state machone stage */
+ uint8 received; /* received or txed */
+ uint8 paket_type; /* packet type */
+ uint8 category; /* category field */
+ uint8 action; /* action field */
+ uint8 token; /* token number */
+ uint8 follow_token; /* following token number */
+ uint16 index; /* index of the packet */
+ uint16 tof_cmd; /* M_TOF_CMD */
+ uint16 tof_rsp; /* M_TOF_RSP */
+ uint16 tof_avb_rxl; /* M_TOF_AVB_RX_L */
+ uint16 tof_avb_rxh; /* M_TOF_AVB_RX_H */
+ uint16 tof_avb_txl; /* M_TOF_AVB_TX_L */
+ uint16 tof_avb_txh; /* M_TOF_AVB_TX_H */
+ uint16 tof_id; /* M_TOF_ID */
+ uint16 tof_status0; /* M_TOF_STATUS_0 */
+ uint16 tof_status2; /* M_TOF_STATUS_2 */
+ uint16 tof_chsm0; /* M_TOF_CHNSM_0 */
+ uint16 tof_phyctl0; /* M_TOF_PHYCTL0 */
+ uint16 tof_phyctl1; /* M_TOF_PHYCTL1 */
+ uint16 tof_phyctl2; /* M_TOF_PHYCTL2 */
+ uint16 tof_lsig; /* M_TOF_LSIG */
+ uint16 tof_vhta0; /* M_TOF_VHTA0 */
+ uint16 tof_vhta1; /* M_TOF_VHTA1 */
+ uint16 tof_vhta2; /* M_TOF_VHTA2 */
+ uint16 tof_vhtb0; /* M_TOF_VHTB0 */
+ uint16 tof_vhtb1; /* M_TOF_VHTB1 */
+ uint16 tof_apmductl; /* M_TOF_AMPDU_CTL */
+ uint16 tof_apmdudlim; /* M_TOF_AMPDU_DLIM */
+ uint16 tof_apmdulen; /* M_TOF_AMPDU_LEN */
+} BWL_POST_PACKED_STRUCT wl_proxd_debug_data_t;
+
+/* version of the wl_wsec_info structure */
+#define WL_WSEC_INFO_VERSION 0x01
+
+/* start enum value for BSS properties */
+#define WL_WSEC_INFO_BSS_BASE 0x0100
+
+/* size of len and type fields of wl_wsec_info_tlv_t struct */
+#define WL_WSEC_INFO_TLV_HDR_LEN OFFSETOF(wl_wsec_info_tlv_t, data)
+
+/* Allowed wl_wsec_info properties; not all of them may be supported. */
+typedef enum {
+ WL_WSEC_INFO_NONE = 0,
+ WL_WSEC_INFO_MAX_KEYS = 1,
+ WL_WSEC_INFO_NUM_KEYS = 2,
+ WL_WSEC_INFO_NUM_HW_KEYS = 3,
+ WL_WSEC_INFO_MAX_KEY_IDX = 4,
+ WL_WSEC_INFO_NUM_REPLAY_CNTRS = 5,
+ WL_WSEC_INFO_SUPPORTED_ALGOS = 6,
+ WL_WSEC_INFO_MAX_KEY_LEN = 7,
+ WL_WSEC_INFO_FLAGS = 8,
+ /* add global/per-wlc properties above */
+ WL_WSEC_INFO_BSS_FLAGS = (WL_WSEC_INFO_BSS_BASE + 1),
+ WL_WSEC_INFO_BSS_WSEC = (WL_WSEC_INFO_BSS_BASE + 2),
+ WL_WSEC_INFO_BSS_TX_KEY_ID = (WL_WSEC_INFO_BSS_BASE + 3),
+ WL_WSEC_INFO_BSS_ALGO = (WL_WSEC_INFO_BSS_BASE + 4),
+ WL_WSEC_INFO_BSS_KEY_LEN = (WL_WSEC_INFO_BSS_BASE + 5),
+ /* add per-BSS properties above */
+ WL_WSEC_INFO_MAX = 0xffff
+} wl_wsec_info_type_t;
+
+/* tlv used to return wl_wsec_info properties */
+typedef struct {
+ uint16 type;
+ uint16 len; /* data length */
+ uint8 data[1]; /* data follows */
+} wl_wsec_info_tlv_t;
+
+/* input/output data type for wsec_info iovar */
+typedef struct wl_wsec_info {
+ uint8 version; /* structure version */
+ uint8 pad[2];
+ uint8 num_tlvs;
+ wl_wsec_info_tlv_t tlvs[1]; /* tlv data follows */
+} wl_wsec_info_t;
+
+/* no default structure packing */
+#include <packed_section_end.h>
+
+enum rssi_reason {
+ RSSI_REASON_UNKNOW = 0,
+ RSSI_REASON_LOWRSSI = 1,
+ RSSI_REASON_NSYC = 2,
+ RSSI_REASON_TIMEOUT = 3
+};
+
+enum tof_reason {
+ TOF_REASON_OK = 0,
+ TOF_REASON_REQEND = 1,
+ TOF_REASON_TIMEOUT = 2,
+ TOF_REASON_NOACK = 3,
+ TOF_REASON_INVALIDAVB = 4,
+ TOF_REASON_INITIAL = 5,
+ TOF_REASON_ABORT = 6
+};
+
+enum rssi_state {
+ RSSI_STATE_POLL = 0,
+ RSSI_STATE_TPAIRING = 1,
+ RSSI_STATE_IPAIRING = 2,
+ RSSI_STATE_THANDSHAKE = 3,
+ RSSI_STATE_IHANDSHAKE = 4,
+ RSSI_STATE_CONFIRMED = 5,
+ RSSI_STATE_PIPELINE = 6,
+ RSSI_STATE_NEGMODE = 7,
+ RSSI_STATE_MONITOR = 8,
+ RSSI_STATE_LAST = 9
+};
+
+enum tof_state {
+ TOF_STATE_IDLE = 0,
+ TOF_STATE_IWAITM = 1,
+ TOF_STATE_TWAITM = 2,
+ TOF_STATE_ILEGACY = 3,
+ TOF_STATE_IWAITCL = 4,
+ TOF_STATE_TWAITCL = 5,
+ TOF_STATE_ICONFIRM = 6,
+ TOF_STATE_IREPORT = 7
+};
+
+enum tof_mode_type {
+ TOF_LEGACY_UNKNOWN = 0,
+ TOF_LEGACY_AP = 1,
+ TOF_NONLEGACY_AP = 2
+};
+
+enum tof_way_type {
+ TOF_TYPE_ONE_WAY = 0,
+ TOF_TYPE_TWO_WAY = 1,
+ TOF_TYPE_REPORT = 2
+};
+
+enum tof_rate_type {
+ TOF_FRAME_RATE_VHT = 0,
+ TOF_FRAME_RATE_LEGACY = 1
+};
+
+#define TOF_ADJ_TYPE_NUM 4 /* number of assisted timestamp adjustment */
+enum tof_adj_mode {
+ TOF_ADJ_SOFTWARE = 0,
+ TOF_ADJ_HARDWARE = 1,
+ TOF_ADJ_SEQ = 2,
+ TOF_ADJ_NONE = 3
+};
+
+#define FRAME_TYPE_NUM 4 /* number of frame type */
+enum frame_type {
+ FRAME_TYPE_CCK = 0,
+ FRAME_TYPE_OFDM = 1,
+ FRAME_TYPE_11N = 2,
+ FRAME_TYPE_11AC = 3
+};
+
+typedef struct wl_proxd_status_iovar {
+ uint16 method; /* method */
+ uint8 mode; /* mode */
+ uint8 peermode; /* peer mode */
+ uint8 state; /* state */
+ uint8 reason; /* reason code */
+ uint32 distance; /* distance */
+ uint32 txcnt; /* tx pkt counter */
+ uint32 rxcnt; /* rx pkt counter */
+ struct ether_addr peer; /* peer mac address */
+ int8 avg_rssi; /* average rssi */
+ int8 hi_rssi; /* highest rssi */
+ int8 low_rssi; /* lowest rssi */
+ uint32 dbgstatus; /* debug status */
+ uint16 frame_type_cnt[FRAME_TYPE_NUM]; /* frame types */
+ uint8 adj_type_cnt[TOF_ADJ_TYPE_NUM]; /* adj types HW/SW */
+} wl_proxd_status_iovar_t;
+
+#ifdef NET_DETECT
+typedef struct net_detect_adapter_features {
+ bool wowl_enabled;
+ bool net_detect_enabled;
+ bool nlo_enabled;
+} net_detect_adapter_features_t;
+
+typedef enum net_detect_bss_type {
+ nd_bss_any = 0,
+ nd_ibss,
+ nd_ess
+} net_detect_bss_type_t;
+
+typedef struct net_detect_profile {
+ wlc_ssid_t ssid;
+ net_detect_bss_type_t bss_type; /* Ignore for now since Phase 1 is only for ESS */
+ uint32 cipher_type; /* DOT11_CIPHER_ALGORITHM enumeration values */
+ uint32 auth_type; /* DOT11_AUTH_ALGORITHM enumeration values */
+} net_detect_profile_t;
+
+typedef struct net_detect_profile_list {
+ uint32 num_nd_profiles;
+ net_detect_profile_t nd_profile[0];
+} net_detect_profile_list_t;
+
+typedef struct net_detect_config {
+ bool nd_enabled;
+ uint32 scan_interval;
+ uint32 wait_period;
+ bool wake_if_connected;
+ bool wake_if_disconnected;
+ net_detect_profile_list_t nd_profile_list;
+} net_detect_config_t;
+
+typedef enum net_detect_wake_reason {
+ nd_reason_unknown,
+ nd_net_detected,
+ nd_wowl_event,
+ nd_ucode_error
+} net_detect_wake_reason_t;
+
+typedef struct net_detect_wake_data {
+ net_detect_wake_reason_t nd_wake_reason;
+ uint32 nd_wake_date_length;
+ uint8 nd_wake_data[0]; /* Wake data (currently unused) */
+} net_detect_wake_data_t;
+
+#endif /* NET_DETECT */
+
+typedef struct bcnreq {
+ uint8 bcn_mode;
+ int dur;
+ int channel;
+ struct ether_addr da;
+ uint16 random_int;
+ wlc_ssid_t ssid;
+ uint16 reps;
+} bcnreq_t;
+
+typedef struct rrmreq {
+ struct ether_addr da;
+ uint8 reg;
+ uint8 chan;
+ uint16 random_int;
+ uint16 dur;
+ uint16 reps;
+} rrmreq_t;
+
+typedef struct framereq {
+ struct ether_addr da;
+ uint8 reg;
+ uint8 chan;
+ uint16 random_int;
+ uint16 dur;
+ struct ether_addr ta;
+ uint16 reps;
+} framereq_t;
+
+typedef struct statreq {
+ struct ether_addr da;
+ struct ether_addr peer;
+ uint16 random_int;
+ uint16 dur;
+ uint8 group_id;
+ uint16 reps;
+} statreq_t;
+
+typedef struct wlc_l2keepalive_ol_params {
+ uint8 flags;
+ uint8 prio;
+ uint16 period_ms;
+} wlc_l2keepalive_ol_params_t;
+
+typedef struct wlc_dwds_config {
+ uint32 enable;
+ uint32 mode; /* STA/AP interface */
+ struct ether_addr ea;
+} wlc_dwds_config_t;
+
+typedef struct wl_el_set_params_s {
+ uint8 set; /* Set number */
+ uint32 size; /* Size to make/expand */
+} wl_el_set_params_t;
+
+typedef struct wl_el_tag_params_s {
+ uint16 tag;
+ uint8 set;
+ uint8 flags;
+} wl_el_tag_params_t;
+
+/* Video Traffic Interference Monitor config */
+#define INTFER_VERSION 1
+typedef struct wl_intfer_params {
+ uint16 version; /* version */
+ uint8 period; /* sample period */
+ uint8 cnt; /* sample cnt */
+ uint8 txfail_thresh; /* non-TCP txfail threshold */
+ uint8 tcptxfail_thresh; /* tcptxfail threshold */
+} wl_intfer_params_t;
+
+typedef struct wl_staprio_cfg {
+ struct ether_addr ea; /* mac addr */
+ uint8 prio; /* scb priority */
+} wl_staprio_cfg_t;
+
+typedef enum wl_stamon_cfg_cmd_type {
+ STAMON_CFG_CMD_DEL = 0,
+ STAMON_CFG_CMD_ADD = 1
+} wl_stamon_cfg_cmd_type_t;
+
+typedef struct wlc_stamon_sta_config {
+ wl_stamon_cfg_cmd_type_t cmd; /* 0 - delete, 1 - add */
+ struct ether_addr ea;
+} wlc_stamon_sta_config_t;
+
+/* Received Beacons lengths information */
+#define WL_LAST_BCNS_INFO_FIXED_LEN OFFSETOF(wlc_bcn_len_hist_t, bcnlen_ring)
+typedef struct wlc_bcn_len_hist {
+ uint16 ver; /* version field */
+ uint16 cur_index; /* current pointed index in ring buffer */
+ uint32 max_bcnlen; /* Max beacon length received */
+ uint32 min_bcnlen; /* Min beacon length received */
+ uint32 ringbuff_len; /* Length of the ring buffer 'bcnlen_ring' */
+ uint32 bcnlen_ring[1]; /* ring buffer storing received beacon lengths */
+} wlc_bcn_len_hist_t;
+
+/* WDS net interface types */
+#define WL_WDSIFTYPE_NONE 0x0 /* The interface type is neither WDS nor DWDS. */
+#define WL_WDSIFTYPE_WDS 0x1 /* The interface is WDS type. */
+#define WL_WDSIFTYPE_DWDS 0x2 /* The interface is DWDS type. */
+
+typedef struct wl_bssload_static {
+ bool is_static;
+ uint16 sta_count;
+ uint8 chan_util;
+ uint16 aac;
+} wl_bssload_static_t;
+
+
+
+typedef enum event_msgs_ext_command {
+ EVENTMSGS_NONE = 0,
+ EVENTMSGS_SET_BIT = 1,
+ EVENTMSGS_RESET_BIT = 2,
+ EVENTMSGS_SET_MASK = 3
+} event_msgs_ext_command_t;
+
+#define EVENTMSGS_VER 1
+#define EVENTMSGS_EXT_STRUCT_SIZE OFFSETOF(eventmsgs_ext_t, mask[0])
+
+/* len - for SET it would be mask size from the application to the firmware
+ * for GET it would be actual firmware mask size
+ * maxgetsize - is only used for GET. indicate max mask size that the
+ * application can read from the firmware
+ */
+typedef struct eventmsgs_ext
+{
+ uint8 ver;
+ uint8 command;
+ uint8 len;
+ uint8 maxgetsize;
+ uint8 mask[1];
+} eventmsgs_ext_t;
+
+#endif /* _wlioctl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c
new file mode 100644
index 000000000000..5b0008d77a46
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/linux_osl.c
@@ -0,0 +1,1529 @@
+/*
+ * Linux OS Independent Layer
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: linux_osl.c 658506 2016-09-08 06:44:19Z $
+ */
+
+#define LINUX_PORT
+
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <linuxver.h>
+#include <bcmdefs.h>
+
+#ifdef __ARM_ARCH_7A__
+#include <asm/cacheflush.h>
+#endif /* __ARM_ARCH_7A__ */
+
+#include <osl.h>
+#include <bcmutils.h>
+#include <linux/delay.h>
+#include <pcicfg.h>
+
+
+
+#include <linux/fs.h>
+
+#define PCI_CFG_RETRY 10
+
+#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */
+#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */
+#define DUMPBUFSZ 1024
+
+#ifdef CONFIG_DHD_USE_STATIC_BUF
+#define DHD_SKB_HDRSIZE 336
+#define DHD_SKB_1PAGE_BUFSIZE ((PAGE_SIZE*1)-DHD_SKB_HDRSIZE)
+#define DHD_SKB_2PAGE_BUFSIZE ((PAGE_SIZE*2)-DHD_SKB_HDRSIZE)
+#define DHD_SKB_4PAGE_BUFSIZE ((PAGE_SIZE*4)-DHD_SKB_HDRSIZE)
+
+#define STATIC_BUF_MAX_NUM 16
+#define STATIC_BUF_SIZE (PAGE_SIZE*2)
+#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
+
+typedef struct bcm_static_buf {
+ spinlock_t static_lock;
+ unsigned char *buf_ptr;
+ unsigned char buf_use[STATIC_BUF_MAX_NUM];
+} bcm_static_buf_t;
+
+static bcm_static_buf_t *bcm_static_buf = 0;
+
+#define STATIC_PKT_MAX_NUM 8
+#if defined(ENHANCED_STATIC_BUF)
+#define STATIC_PKT_4PAGE_NUM 1
+#define DHD_SKB_MAX_BUFSIZE DHD_SKB_4PAGE_BUFSIZE
+#else
+#define STATIC_PKT_4PAGE_NUM 0
+#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE
+#endif /* ENHANCED_STATIC_BUF */
+
+typedef struct bcm_static_pkt {
+ struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM];
+ struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM];
+#ifdef ENHANCED_STATIC_BUF
+ struct sk_buff *skb_16k;
+#endif
+ struct semaphore osl_pkt_sem;
+ unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM];
+} bcm_static_pkt_t;
+
+static bcm_static_pkt_t *bcm_static_skb = 0;
+
+void* wifi_platform_prealloc(void *adapter, int section, unsigned long size);
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+
+typedef struct bcm_mem_link {
+ struct bcm_mem_link *prev;
+ struct bcm_mem_link *next;
+ uint size;
+ int line;
+ void *osh;
+ char file[BCM_MEM_FILENAME_LEN];
+} bcm_mem_link_t;
+
+struct osl_cmn_info {
+ atomic_t malloced;
+ atomic_t pktalloced; /* Number of allocated packet buffers */
+ spinlock_t dbgmem_lock;
+ bcm_mem_link_t *dbgmem_list;
+ spinlock_t pktalloc_lock;
+ atomic_t refcount; /* Number of references to this shared structure. */
+};
+typedef struct osl_cmn_info osl_cmn_t;
+
+struct osl_info {
+ osl_pubinfo_t pub;
+#ifdef CTFPOOL
+ ctfpool_t *ctfpool;
+#endif /* CTFPOOL */
+ uint magic;
+ void *pdev;
+ uint failed;
+ uint bustype;
+ osl_cmn_t *cmn; /* Common OSL related data shred between two OSH's */
+
+ void *bus_handle;
+#ifdef BCMDBG_CTRACE
+ spinlock_t ctrace_lock;
+ struct list_head ctrace_list;
+ int ctrace_num;
+#endif /* BCMDBG_CTRACE */
+};
+
+#define OSL_PKTTAG_CLEAR(p) \
+do { \
+ struct sk_buff *s = (struct sk_buff *)(p); \
+ ASSERT(OSL_PKTTAG_SZ == 32); \
+ *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \
+ *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \
+ *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
+ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
+} while (0)
+
+/* PCMCIA attribute space access macros */
+
+/* Global ASSERT type flag */
+uint32 g_assert_type = FALSE;
+
+static int16 linuxbcmerrormap[] =
+{ 0, /* 0 */
+ -EINVAL, /* BCME_ERROR */
+ -EINVAL, /* BCME_BADARG */
+ -EINVAL, /* BCME_BADOPTION */
+ -EINVAL, /* BCME_NOTUP */
+ -EINVAL, /* BCME_NOTDOWN */
+ -EINVAL, /* BCME_NOTAP */
+ -EINVAL, /* BCME_NOTSTA */
+ -EINVAL, /* BCME_BADKEYIDX */
+ -EINVAL, /* BCME_RADIOOFF */
+ -EINVAL, /* BCME_NOTBANDLOCKED */
+ -EINVAL, /* BCME_NOCLK */
+ -EINVAL, /* BCME_BADRATESET */
+ -EINVAL, /* BCME_BADBAND */
+ -E2BIG, /* BCME_BUFTOOSHORT */
+ -E2BIG, /* BCME_BUFTOOLONG */
+ -EBUSY, /* BCME_BUSY */
+ -EINVAL, /* BCME_NOTASSOCIATED */
+ -EINVAL, /* BCME_BADSSIDLEN */
+ -EINVAL, /* BCME_OUTOFRANGECHAN */
+ -EINVAL, /* BCME_BADCHAN */
+ -EFAULT, /* BCME_BADADDR */
+ -ENOMEM, /* BCME_NORESOURCE */
+ -EOPNOTSUPP, /* BCME_UNSUPPORTED */
+ -EMSGSIZE, /* BCME_BADLENGTH */
+ -EINVAL, /* BCME_NOTREADY */
+ -EPERM, /* BCME_EPERM */
+ -ENOMEM, /* BCME_NOMEM */
+ -EINVAL, /* BCME_ASSOCIATED */
+ -ERANGE, /* BCME_RANGE */
+ -EINVAL, /* BCME_NOTFOUND */
+ -EINVAL, /* BCME_WME_NOT_ENABLED */
+ -EINVAL, /* BCME_TSPEC_NOTFOUND */
+ -EINVAL, /* BCME_ACM_NOTSUPPORTED */
+ -EINVAL, /* BCME_NOT_WME_ASSOCIATION */
+ -EIO, /* BCME_SDIO_ERROR */
+ -ENODEV, /* BCME_DONGLE_DOWN */
+ -EINVAL, /* BCME_VERSION */
+ -EIO, /* BCME_TXFAIL */
+ -EIO, /* BCME_RXFAIL */
+ -ENODEV, /* BCME_NODEVICE */
+ -EINVAL, /* BCME_NMODE_DISABLED */
+ -ENODATA, /* BCME_NONRESIDENT */
+ -EINVAL, /* BCME_SCANREJECT */
+ -EINVAL, /* BCME_USAGE_ERROR */
+ -EIO, /* BCME_IOCTL_ERROR */
+ -EIO, /* BCME_SERIAL_PORT_ERR */
+ -EOPNOTSUPP, /* BCME_DISABLED, BCME_NOTENABLED */
+ -EIO, /* BCME_DECERR */
+ -EIO, /* BCME_ENCERR */
+ -EIO, /* BCME_MICERR */
+ -ERANGE, /* BCME_REPLAY */
+ -EINVAL, /* BCME_IE_NOTFOUND */
+
+/* When an new error code is added to bcmutils.h, add os
+ * specific error translation here as well
+ */
+/* check if BCME_LAST changed since the last time this function was updated */
+#if BCME_LAST != -52
+#error "You need to add a OS error translation in the linuxbcmerrormap \
+ for new error code defined in bcmutils.h"
+#endif
+};
+
+/* translate bcmerrors into linux errors */
+int
+osl_error(int bcmerror)
+{
+ if (bcmerror > 0)
+ bcmerror = 0;
+ else if (bcmerror < BCME_LAST)
+ bcmerror = BCME_ERROR;
+
+ /* Array bounds covered by ASSERT in osl_attach */
+ return linuxbcmerrormap[-bcmerror];
+}
+#ifdef SHARED_OSL_CMN
+osl_t *
+osl_attach(void *pdev, uint bustype, bool pkttag, void **osl_cmn)
+{
+#else
+osl_t *
+osl_attach(void *pdev, uint bustype, bool pkttag)
+{
+ void **osl_cmn = NULL;
+#endif /* SHARED_OSL_CMN */
+ osl_t *osh;
+ gfp_t flags;
+
+ flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
+ if (!(osh = kmalloc(sizeof(osl_t), flags)))
+ return osh;
+
+ ASSERT(osh);
+
+ bzero(osh, sizeof(osl_t));
+
+ if (osl_cmn == NULL || *osl_cmn == NULL) {
+ if (!(osh->cmn = kmalloc(sizeof(osl_cmn_t), flags))) {
+ kfree(osh);
+ return NULL;
+ }
+ bzero(osh->cmn, sizeof(osl_cmn_t));
+ if (osl_cmn)
+ *osl_cmn = osh->cmn;
+ atomic_set(&osh->cmn->malloced, 0);
+ osh->cmn->dbgmem_list = NULL;
+ spin_lock_init(&(osh->cmn->dbgmem_lock));
+
+ spin_lock_init(&(osh->cmn->pktalloc_lock));
+
+ } else {
+ osh->cmn = *osl_cmn;
+ }
+ atomic_add(1, &osh->cmn->refcount);
+
+ /* Check that error map has the right number of entries in it */
+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
+
+ osh->failed = 0;
+ osh->pdev = pdev;
+ osh->pub.pkttag = pkttag;
+ osh->bustype = bustype;
+ osh->magic = OS_HANDLE_MAGIC;
+
+ switch (bustype) {
+ case PCI_BUS:
+ case SI_BUS:
+ case PCMCIA_BUS:
+ osh->pub.mmbus = TRUE;
+ break;
+ case JTAG_BUS:
+ case SDIO_BUS:
+ case USB_BUS:
+ case SPI_BUS:
+ case RPC_BUS:
+ osh->pub.mmbus = FALSE;
+ break;
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+#ifdef BCMDBG_CTRACE
+ spin_lock_init(&osh->ctrace_lock);
+ INIT_LIST_HEAD(&osh->ctrace_list);
+ osh->ctrace_num = 0;
+#endif /* BCMDBG_CTRACE */
+
+
+ return osh;
+}
+
+int osl_static_mem_init(osl_t *osh, void *adapter)
+{
+#if defined(CONFIG_DHD_USE_STATIC_BUF)
+ if (!bcm_static_buf && adapter) {
+ if (!(bcm_static_buf = (bcm_static_buf_t *)wifi_platform_prealloc(adapter,
+ 3, STATIC_BUF_SIZE + STATIC_BUF_TOTAL_LEN))) {
+ printk("can not alloc static buf!\n");
+ bcm_static_skb = NULL;
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ kfree(osh);
+ return -ENOMEM;
+ } else {
+ printk("alloc static buf at %p!\n", bcm_static_buf);
+ }
+
+ spin_lock_init(&bcm_static_buf->static_lock);
+
+ bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE;
+ }
+
+ if (!bcm_static_skb && adapter) {
+ int i;
+ void *skb_buff_ptr = 0;
+ bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048);
+ skb_buff_ptr = wifi_platform_prealloc(adapter, 4, 0);
+ if (!skb_buff_ptr) {
+ printk("cannot alloc static buf!\n");
+ bcm_static_buf = NULL;
+ bcm_static_skb = NULL;
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ kfree(osh);
+ return -ENOMEM;
+ }
+
+ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) *
+ (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM));
+ for (i = 0; i < STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM; i++)
+ bcm_static_skb->pkt_use[i] = 0;
+
+ sema_init(&bcm_static_skb->osl_pkt_sem, 1);
+ }
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+
+ return 0;
+}
+
+void osl_set_bus_handle(osl_t *osh, void *bus_handle)
+{
+ osh->bus_handle = bus_handle;
+}
+
+void* osl_get_bus_handle(osl_t *osh)
+{
+ return osh->bus_handle;
+}
+
+void
+osl_detach(osl_t *osh)
+{
+ if (osh == NULL)
+ return;
+
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ atomic_sub(1, &osh->cmn->refcount);
+ if (atomic_read(&osh->cmn->refcount) == 0) {
+ kfree(osh->cmn);
+ }
+ kfree(osh);
+}
+
+int osl_static_mem_deinit(osl_t *osh, void *adapter)
+{
+#ifdef CONFIG_DHD_USE_STATIC_BUF
+ if (bcm_static_buf) {
+ bcm_static_buf = 0;
+ }
+ if (bcm_static_skb) {
+ bcm_static_skb = 0;
+ }
+#endif
+ return 0;
+}
+
+static struct sk_buff *osl_alloc_skb(osl_t *osh, unsigned int len)
+{
+ struct sk_buff *skb;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+ gfp_t flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
+#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_ZONE_DMA)
+ flags |= GFP_ATOMIC;
+#endif
+ skb = __dev_alloc_skb(len, flags);
+#else
+ skb = dev_alloc_skb(len);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */
+ return skb;
+}
+
+#ifdef CTFPOOL
+
+#ifdef CTFPOOL_SPINLOCK
+#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_irqsave(&(ctfpool)->lock, flags)
+#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_irqrestore(&(ctfpool)->lock, flags)
+#else
+#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_bh(&(ctfpool)->lock)
+#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_bh(&(ctfpool)->lock)
+#endif /* CTFPOOL_SPINLOCK */
+/*
+ * Allocate and add an object to packet pool.
+ */
+void *
+osl_ctfpool_add(osl_t *osh)
+{
+ struct sk_buff *skb;
+#ifdef CTFPOOL_SPINLOCK
+ unsigned long flags;
+#endif /* CTFPOOL_SPINLOCK */
+
+ if ((osh == NULL) || (osh->ctfpool == NULL))
+ return NULL;
+
+ CTFPOOL_LOCK(osh->ctfpool, flags);
+ ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj);
+
+ /* No need to allocate more objects */
+ if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) {
+ CTFPOOL_UNLOCK(osh->ctfpool, flags);
+ return NULL;
+ }
+
+ /* Allocate a new skb and add it to the ctfpool */
+ skb = osl_alloc_skb(osh, osh->ctfpool->obj_size);
+ if (skb == NULL) {
+ printf("%s: skb alloc of len %d failed\n", __FUNCTION__,
+ osh->ctfpool->obj_size);
+ CTFPOOL_UNLOCK(osh->ctfpool, flags);
+ return NULL;
+ }
+
+ /* Add to ctfpool */
+ skb->next = (struct sk_buff *)osh->ctfpool->head;
+ osh->ctfpool->head = skb;
+ osh->ctfpool->fast_frees++;
+ osh->ctfpool->curr_obj++;
+
+ /* Hijack a skb member to store ptr to ctfpool */
+ CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool;
+
+ /* Use bit flag to indicate skb from fast ctfpool */
+ PKTFAST(osh, skb) = FASTBUF;
+
+ CTFPOOL_UNLOCK(osh->ctfpool, flags);
+
+ return skb;
+}
+
+/*
+ * Add new objects to the pool.
+ */
+void
+osl_ctfpool_replenish(osl_t *osh, uint thresh)
+{
+ if ((osh == NULL) || (osh->ctfpool == NULL))
+ return;
+
+ /* Do nothing if no refills are required */
+ while ((osh->ctfpool->refills > 0) && (thresh--)) {
+ osl_ctfpool_add(osh);
+ osh->ctfpool->refills--;
+ }
+}
+
+/*
+ * Initialize the packet pool with specified number of objects.
+ */
+int32
+osl_ctfpool_init(osl_t *osh, uint numobj, uint size)
+{
+ gfp_t flags;
+
+ flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
+ osh->ctfpool = kzalloc(sizeof(ctfpool_t), flags);
+ ASSERT(osh->ctfpool);
+
+ osh->ctfpool->max_obj = numobj;
+ osh->ctfpool->obj_size = size;
+
+ spin_lock_init(&osh->ctfpool->lock);
+
+ while (numobj--) {
+ if (!osl_ctfpool_add(osh))
+ return -1;
+ osh->ctfpool->fast_frees--;
+ }
+
+ return 0;
+}
+
+/*
+ * Cleanup the packet pool objects.
+ */
+void
+osl_ctfpool_cleanup(osl_t *osh)
+{
+ struct sk_buff *skb, *nskb;
+#ifdef CTFPOOL_SPINLOCK
+ unsigned long flags;
+#endif /* CTFPOOL_SPINLOCK */
+
+ if ((osh == NULL) || (osh->ctfpool == NULL))
+ return;
+
+ CTFPOOL_LOCK(osh->ctfpool, flags);
+
+ skb = osh->ctfpool->head;
+
+ while (skb != NULL) {
+ nskb = skb->next;
+ dev_kfree_skb(skb);
+ skb = nskb;
+ osh->ctfpool->curr_obj--;
+ }
+
+ ASSERT(osh->ctfpool->curr_obj == 0);
+ osh->ctfpool->head = NULL;
+ CTFPOOL_UNLOCK(osh->ctfpool, flags);
+
+ kfree(osh->ctfpool);
+ osh->ctfpool = NULL;
+}
+
+void
+osl_ctfpool_stats(osl_t *osh, void *b)
+{
+ struct bcmstrbuf *bb;
+
+ if ((osh == NULL) || (osh->ctfpool == NULL))
+ return;
+
+#ifdef CONFIG_DHD_USE_STATIC_BUF
+ if (bcm_static_buf) {
+ bcm_static_buf = 0;
+ }
+ if (bcm_static_skb) {
+ bcm_static_skb = 0;
+ }
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+
+ bb = b;
+
+ ASSERT((osh != NULL) && (bb != NULL));
+
+ bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n",
+ osh->ctfpool->max_obj, osh->ctfpool->obj_size,
+ osh->ctfpool->curr_obj, osh->ctfpool->refills);
+ bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n",
+ osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees,
+ osh->ctfpool->slow_allocs);
+}
+
+static inline struct sk_buff *
+osl_pktfastget(osl_t *osh, uint len)
+{
+ struct sk_buff *skb;
+#ifdef CTFPOOL_SPINLOCK
+ unsigned long flags;
+#endif /* CTFPOOL_SPINLOCK */
+
+ /* Try to do fast allocate. Return null if ctfpool is not in use
+ * or if there are no items in the ctfpool.
+ */
+ if (osh->ctfpool == NULL)
+ return NULL;
+
+ CTFPOOL_LOCK(osh->ctfpool, flags);
+ if (osh->ctfpool->head == NULL) {
+ ASSERT(osh->ctfpool->curr_obj == 0);
+ osh->ctfpool->slow_allocs++;
+ CTFPOOL_UNLOCK(osh->ctfpool, flags);
+ return NULL;
+ }
+
+ if (len > osh->ctfpool->obj_size) {
+ CTFPOOL_UNLOCK(osh->ctfpool, flags);
+ return NULL;
+ }
+
+ ASSERT(len <= osh->ctfpool->obj_size);
+
+ /* Get an object from ctfpool */
+ skb = (struct sk_buff *)osh->ctfpool->head;
+ osh->ctfpool->head = (void *)skb->next;
+
+ osh->ctfpool->fast_allocs++;
+ osh->ctfpool->curr_obj--;
+ ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head);
+ CTFPOOL_UNLOCK(osh->ctfpool, flags);
+
+ /* Init skb struct */
+ skb->next = skb->prev = NULL;
+#if defined(__ARM_ARCH_7A__)
+ skb->data = skb->head + NET_SKB_PAD;
+ skb->tail = skb->head + NET_SKB_PAD;
+#else
+ skb->data = skb->head + 16;
+ skb->tail = skb->head + 16;
+#endif /* __ARM_ARCH_7A__ */
+ skb->len = 0;
+ skb->cloned = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+ skb->list = NULL;
+#endif
+ atomic_set(&skb->users, 1);
+
+ PKTSETCLINK(skb, NULL);
+ PKTCCLRATTR(skb);
+ PKTFAST(osh, skb) &= ~(CTFBUF | SKIPCT | CHAINED);
+
+ return skb;
+}
+#endif /* CTFPOOL */
+/* Convert a driver packet to native(OS) packet
+ * In the process, packettag is zeroed out before sending up
+ * IP code depends on skb->cb to be setup correctly with various options
+ * In our case, that means it should be 0
+ */
+struct sk_buff * BCMFASTPATH
+osl_pkt_tonative(osl_t *osh, void *pkt)
+{
+ struct sk_buff *nskb;
+#ifdef BCMDBG_CTRACE
+ struct sk_buff *nskb1, *nskb2;
+#endif
+
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(pkt);
+
+ /* Decrement the packet counter */
+ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
+ atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->cmn->pktalloced);
+
+#ifdef BCMDBG_CTRACE
+ for (nskb1 = nskb; nskb1 != NULL; nskb1 = nskb2) {
+ if (PKTISCHAINED(nskb1)) {
+ nskb2 = PKTCLINK(nskb1);
+ }
+ else
+ nskb2 = NULL;
+
+ DEL_CTRACE(osh, nskb1);
+ }
+#endif /* BCMDBG_CTRACE */
+ }
+ return (struct sk_buff *)pkt;
+}
+
+/* Convert a native(OS) packet to driver packet.
+ * In the process, native packet is destroyed, there is no copying
+ * Also, a packettag is zeroed out
+ */
+#ifdef BCMDBG_CTRACE
+void * BCMFASTPATH
+osl_pkt_frmnative(osl_t *osh, void *pkt, int line, char *file)
+#else
+void * BCMFASTPATH
+osl_pkt_frmnative(osl_t *osh, void *pkt)
+#endif /* BCMDBG_CTRACE */
+{
+ struct sk_buff *cskb;
+ struct sk_buff *nskb;
+ unsigned long pktalloced = 0;
+
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(pkt);
+
+ /* walk the PKTCLINK() list */
+ for (cskb = (struct sk_buff *)pkt;
+ cskb != NULL;
+ cskb = PKTISCHAINED(cskb) ? PKTCLINK(cskb) : NULL) {
+
+ /* walk the pkt buffer list */
+ for (nskb = cskb; nskb; nskb = nskb->next) {
+
+ /* Increment the packet counter */
+ pktalloced++;
+
+ /* clean the 'prev' pointer
+ * Kernel 3.18 is leaving skb->prev pointer set to skb
+ * to indicate a non-fragmented skb
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ nskb->prev = NULL;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) */
+
+
+#ifdef BCMDBG_CTRACE
+ ADD_CTRACE(osh, nskb, file, line);
+#endif /* BCMDBG_CTRACE */
+ }
+ }
+
+ /* Increment the packet counter */
+ atomic_add(pktalloced, &osh->cmn->pktalloced);
+
+ return (void *)pkt;
+}
+
+/* Return a new packet. zero out pkttag */
+#ifdef BCMDBG_CTRACE
+void * BCMFASTPATH
+osl_pktget(osl_t *osh, uint len, int line, char *file)
+#else
+void * BCMFASTPATH
+osl_pktget(osl_t *osh, uint len)
+#endif /* BCMDBG_CTRACE */
+{
+ struct sk_buff *skb;
+
+#ifdef CTFPOOL
+ /* Allocate from local pool */
+ skb = osl_pktfastget(osh, len);
+ if ((skb != NULL) || ((skb = osl_alloc_skb(osh, len)) != NULL)) {
+#else /* CTFPOOL */
+ if ((skb = osl_alloc_skb(osh, len))) {
+#endif /* CTFPOOL */
+ skb->tail += len;
+ skb->len += len;
+ skb->priority = 0;
+
+#ifdef BCMDBG_CTRACE
+ ADD_CTRACE(osh, skb, file, line);
+#endif
+ atomic_inc(&osh->cmn->pktalloced);
+ }
+
+ return ((void*) skb);
+}
+
+#ifdef CTFPOOL
+static inline void
+osl_pktfastfree(osl_t *osh, struct sk_buff *skb)
+{
+ ctfpool_t *ctfpool;
+#ifdef CTFPOOL_SPINLOCK
+ unsigned long flags;
+#endif /* CTFPOOL_SPINLOCK */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+ skb->tstamp.tv.sec = 0;
+#else
+ skb->stamp.tv_sec = 0;
+#endif
+
+ /* We only need to init the fields that we change */
+ skb->dev = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+ skb->dst = NULL;
+#endif
+ OSL_PKTTAG_CLEAR(skb);
+ skb->ip_summed = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ skb_orphan(skb);
+#else
+ skb->destructor = NULL;
+#endif
+
+ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb);
+ ASSERT(ctfpool != NULL);
+
+ /* Add object to the ctfpool */
+ CTFPOOL_LOCK(ctfpool, flags);
+ skb->next = (struct sk_buff *)ctfpool->head;
+ ctfpool->head = (void *)skb;
+
+ ctfpool->fast_frees++;
+ ctfpool->curr_obj++;
+
+ ASSERT(ctfpool->curr_obj <= ctfpool->max_obj);
+ CTFPOOL_UNLOCK(ctfpool, flags);
+}
+#endif /* CTFPOOL */
+
+/* Free the driver packet. Free the tag if present */
+void BCMFASTPATH
+osl_pktfree(osl_t *osh, void *p, bool send)
+{
+ struct sk_buff *skb, *nskb;
+ if (osh == NULL)
+ return;
+
+ skb = (struct sk_buff*) p;
+
+ if (send && osh->pub.tx_fn)
+ osh->pub.tx_fn(osh->pub.tx_ctx, p, 0);
+
+ PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE);
+
+ /* perversion: we use skb->next to chain multi-skb packets */
+ while (skb) {
+ nskb = skb->next;
+ skb->next = NULL;
+
+#ifdef BCMDBG_CTRACE
+ DEL_CTRACE(osh, skb);
+#endif
+
+
+#ifdef CTFPOOL
+ if (PKTISFAST(osh, skb)) {
+ if (atomic_read(&skb->users) == 1)
+ smp_rmb();
+ else if (!atomic_dec_and_test(&skb->users))
+ goto next_skb;
+ osl_pktfastfree(osh, skb);
+ } else
+#endif
+ {
+ if (skb->destructor)
+ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
+ * destructor exists
+ */
+ dev_kfree_skb_any(skb);
+ else
+ /* can free immediately (even in_irq()) if destructor
+ * does not exist
+ */
+ dev_kfree_skb(skb);
+ }
+#ifdef CTFPOOL
+next_skb:
+#endif
+ atomic_dec(&osh->cmn->pktalloced);
+ skb = nskb;
+ }
+}
+
+#ifdef CONFIG_DHD_USE_STATIC_BUF
+void*
+osl_pktget_static(osl_t *osh, uint len)
+{
+ int i = 0;
+ struct sk_buff *skb;
+
+ if (len > DHD_SKB_MAX_BUFSIZE) {
+ printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len);
+ return osl_pktget(osh, len);
+ }
+
+ down(&bcm_static_skb->osl_pkt_sem);
+
+ if (len <= DHD_SKB_1PAGE_BUFSIZE) {
+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+ if (bcm_static_skb->pkt_use[i] == 0)
+ break;
+ }
+
+ if (i != STATIC_PKT_MAX_NUM) {
+ bcm_static_skb->pkt_use[i] = 1;
+
+ skb = bcm_static_skb->skb_4k[i];
+ skb_set_tail_pointer(skb, len);
+ skb->len = len;
+
+ up(&bcm_static_skb->osl_pkt_sem);
+ return skb;
+ }
+ }
+
+ if (len <= DHD_SKB_2PAGE_BUFSIZE) {
+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+ if (bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM]
+ == 0)
+ break;
+ }
+
+ if (i != STATIC_PKT_MAX_NUM) {
+ bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 1;
+ skb = bcm_static_skb->skb_8k[i];
+ skb_set_tail_pointer(skb, len);
+ skb->len = len;
+
+ up(&bcm_static_skb->osl_pkt_sem);
+ return skb;
+ }
+ }
+
+#if defined(ENHANCED_STATIC_BUF)
+ if (bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] == 0) {
+ bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] = 1;
+
+ skb = bcm_static_skb->skb_16k;
+ skb_set_tail_pointer(skb, len);
+ skb->len = len;
+
+ up(&bcm_static_skb->osl_pkt_sem);
+ return skb;
+ }
+#endif
+
+ up(&bcm_static_skb->osl_pkt_sem);
+ printk("%s: all static pkt in use!\n", __FUNCTION__);
+ return osl_pktget(osh, len);
+}
+
+void
+osl_pktfree_static(osl_t *osh, void *p, bool send)
+{
+ int i;
+ if (!bcm_static_skb) {
+ osl_pktfree(osh, p, send);
+ return;
+ }
+
+ down(&bcm_static_skb->osl_pkt_sem);
+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+ if (p == bcm_static_skb->skb_4k[i]) {
+ bcm_static_skb->pkt_use[i] = 0;
+ up(&bcm_static_skb->osl_pkt_sem);
+ return;
+ }
+ }
+
+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+ if (p == bcm_static_skb->skb_8k[i]) {
+ bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0;
+ up(&bcm_static_skb->osl_pkt_sem);
+ return;
+ }
+ }
+#ifdef ENHANCED_STATIC_BUF
+ if (p == bcm_static_skb->skb_16k) {
+ bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] = 0;
+ up(&bcm_static_skb->osl_pkt_sem);
+ return;
+ }
+#endif
+ up(&bcm_static_skb->osl_pkt_sem);
+ osl_pktfree(osh, p, send);
+}
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+
+uint32
+osl_pci_read_config(osl_t *osh, uint offset, uint size)
+{
+ uint val = 0;
+ uint retry = PCI_CFG_RETRY;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ /* only 4byte access supported */
+ ASSERT(size == 4);
+
+ do {
+ pci_read_config_dword(osh->pdev, offset, &val);
+ if (val != 0xffffffff)
+ break;
+ } while (retry--);
+
+
+ return (val);
+}
+
+void
+osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
+{
+ uint retry = PCI_CFG_RETRY;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ /* only 4byte access supported */
+ ASSERT(size == 4);
+
+ do {
+ pci_write_config_dword(osh->pdev, offset, val);
+ if (offset != PCI_BAR0_WIN)
+ break;
+ if (osl_pci_read_config(osh, offset, size) == val)
+ break;
+ } while (retry--);
+
+}
+
+/* return bus # for the pci device pointed by osh->pdev */
+uint
+osl_pci_bus(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+ return ((struct pci_dev *)osh->pdev)->bus->number;
+}
+
+/* return slot # for the pci device pointed by osh->pdev */
+uint
+osl_pci_slot(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+#if defined(__ARM_ARCH_7A__) && LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1;
+#else
+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);
+#endif
+}
+
+/* return the pci device pointed by osh->pdev */
+struct pci_dev *
+osl_pci_device(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+ return osh->pdev;
+}
+
+static void
+osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write)
+{
+}
+
+void
+osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size)
+{
+ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE);
+}
+
+void
+osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size)
+{
+ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE);
+}
+
+void *
+osl_malloc(osl_t *osh, uint size)
+{
+ void *addr;
+ gfp_t flags;
+
+ /* only ASSERT if osh is defined */
+ if (osh)
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+#ifdef CONFIG_DHD_USE_STATIC_BUF
+ if (bcm_static_buf)
+ {
+ unsigned long irq_flags;
+ int i = 0;
+ if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE))
+ {
+ spin_lock_irqsave(&bcm_static_buf->static_lock, irq_flags);
+
+ for (i = 0; i < STATIC_BUF_MAX_NUM; i++)
+ {
+ if (bcm_static_buf->buf_use[i] == 0)
+ break;
+ }
+
+ if (i == STATIC_BUF_MAX_NUM)
+ {
+ spin_unlock_irqrestore(&bcm_static_buf->static_lock, irq_flags);
+ printk("all static buff in use!\n");
+ goto original;
+ }
+
+ bcm_static_buf->buf_use[i] = 1;
+ spin_unlock_irqrestore(&bcm_static_buf->static_lock, irq_flags);
+
+ bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size);
+ if (osh)
+ atomic_add(size, &osh->cmn->malloced);
+
+ return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i));
+ }
+ }
+original:
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+
+ flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
+ if ((addr = kmalloc(size, flags)) == NULL) {
+ if (osh)
+ osh->failed++;
+ return (NULL);
+ }
+ if (osh && osh->cmn)
+ atomic_add(size, &osh->cmn->malloced);
+
+ return (addr);
+}
+
+void *
+osl_mallocz(osl_t *osh, uint size)
+{
+ void *ptr;
+
+ ptr = osl_malloc(osh, size);
+
+ if (ptr != NULL) {
+ bzero(ptr, size);
+ }
+
+ return ptr;
+}
+
+void
+osl_mfree(osl_t *osh, void *addr, uint size)
+{
+#ifdef CONFIG_DHD_USE_STATIC_BUF
+ unsigned long flags;
+
+ if (bcm_static_buf)
+ {
+ if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr
+ <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN)))
+ {
+ int buf_idx = 0;
+
+ buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE;
+
+ spin_lock_irqsave(&bcm_static_buf->static_lock, flags);
+ bcm_static_buf->buf_use[buf_idx] = 0;
+ spin_unlock_irqrestore(&bcm_static_buf->static_lock, flags);
+
+ if (osh && osh->cmn) {
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ atomic_sub(size, &osh->cmn->malloced);
+ }
+ return;
+ }
+ }
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+ if (osh && osh->cmn) {
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+
+ ASSERT(size <= osl_malloced(osh));
+
+ atomic_sub(size, &osh->cmn->malloced);
+ }
+ kfree(addr);
+}
+
+uint
+osl_check_memleak(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ if (atomic_read(&osh->cmn->refcount) == 1)
+ return (atomic_read(&osh->cmn->malloced));
+ else
+ return 0;
+}
+
+uint
+osl_malloced(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ return (atomic_read(&osh->cmn->malloced));
+}
+
+uint
+osl_malloc_failed(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ return (osh->failed);
+}
+
+
+uint
+osl_dma_consistent_align(void)
+{
+ return (PAGE_SIZE);
+}
+
+void*
+osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, dmaaddr_t *pap)
+{
+ void *va;
+ uint16 align = (1 << align_bits);
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
+ size += align;
+ *alloced = size;
+
+#ifdef __ARM_ARCH_7A__
+ va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO);
+ if (va)
+ *pap = (ulong)__virt_to_phys((ulong)va);
+#else
+ {
+ dma_addr_t pap_lin;
+ va = pci_alloc_consistent(osh->pdev, size, &pap_lin);
+ *pap = (dmaaddr_t)pap_lin;
+ }
+#endif
+ return va;
+}
+
+void
+osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+#ifdef __ARM_ARCH_7A__
+ kfree(va);
+#else
+ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa);
+#endif
+}
+
+dmaaddr_t BCMFASTPATH
+osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah)
+{
+ int dir;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+
+#if defined(__ARM_ARCH_7A__) && defined(BCMDMASGLISTOSL)
+ if (dmah != NULL) {
+ int32 nsegs, i, totsegs = 0, totlen = 0;
+ struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2];
+ struct sk_buff *skb;
+ for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) {
+ sg = &_sg[totsegs];
+ if (skb_is_nonlinear(skb)) {
+ nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb));
+ ASSERT((nsegs > 0) && (totsegs + nsegs <= MAX_DMA_SEGS));
+ pci_map_sg(osh->pdev, sg, nsegs, dir);
+ } else {
+ nsegs = 1;
+ ASSERT(totsegs + nsegs <= MAX_DMA_SEGS);
+ sg->page_link = 0;
+ sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb));
+ pci_map_single(osh->pdev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir);
+ }
+ totsegs += nsegs;
+ totlen += PKTLEN(osh, skb);
+ }
+ dmah->nsegs = totsegs;
+ dmah->origsize = totlen;
+ for (i = 0, sg = _sg; i < totsegs; i++, sg++) {
+ dmah->segs[i].addr = sg_phys(sg);
+ dmah->segs[i].length = sg->length;
+ }
+ return dmah->segs[0].addr;
+ }
+#endif /* __ARM_ARCH_7A__ && BCMDMASGLISTOSL */
+
+ return (pci_map_single(osh->pdev, va, size, dir));
+}
+
+void BCMFASTPATH
+osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction)
+{
+ int dir;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+ pci_unmap_single(osh->pdev, (uint32)pa, size, dir);
+}
+
+
+#if defined(__ARM_ARCH_7A__)
+
+inline void BCMFASTPATH
+osl_cache_flush(void *va, uint size)
+{
+ dma_sync_single_for_device(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_TX);
+}
+
+inline void BCMFASTPATH
+osl_cache_inv(void *va, uint size)
+{
+ dma_sync_single_for_cpu(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_RX);
+}
+
+inline void osl_prefetch(const void *ptr)
+{
+ __asm__ __volatile__("pld\t%0" :: "o"(*(char *)ptr) : "cc");
+}
+#endif
+
+#if defined(BCMASSERT_LOG)
+void
+osl_assert(const char *exp, const char *file, int line)
+{
+ char tempbuf[256];
+ const char *basename;
+
+ basename = strrchr(file, '/');
+ /* skip the '/' */
+ if (basename)
+ basename++;
+
+ if (!basename)
+ basename = file;
+
+#ifdef BCMASSERT_LOG
+ snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n",
+ exp, basename, line);
+ printk("%s", tempbuf);
+#endif /* BCMASSERT_LOG */
+
+
+}
+#endif
+
+void
+osl_delay(uint usec)
+{
+ uint d;
+
+ while (usec > 0) {
+ d = MIN(usec, 1000);
+ udelay(d);
+ usec -= d;
+ }
+}
+
+void
+osl_sleep(uint ms)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ if (ms < 20)
+ usleep_range(ms*1000, ms*1000 + 1000);
+ else
+#endif
+ msleep(ms);
+}
+
+
+
+/* Clone a packet.
+ * The pkttag contents are NOT cloned.
+ */
+#ifdef BCMDBG_CTRACE
+void *
+osl_pktdup(osl_t *osh, void *skb, int line, char *file)
+#else
+void *
+osl_pktdup(osl_t *osh, void *skb)
+#endif /* BCMDBG_CTRACE */
+{
+ void * p;
+
+ ASSERT(!PKTISCHAINED(skb));
+
+ /* clear the CTFBUF flag if set and map the rest of the buffer
+ * before cloning.
+ */
+ PKTCTFMAP(osh, skb);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ if ((p = pskb_copy((struct sk_buff *)skb, GFP_ATOMIC)) == NULL)
+#else
+ if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL)
+#endif
+ return NULL;
+
+#ifdef CTFPOOL
+ if (PKTISFAST(osh, skb)) {
+ ctfpool_t *ctfpool;
+
+ /* if the buffer allocated from ctfpool is cloned then
+ * we can't be sure when it will be freed. since there
+ * is a chance that we will be losing a buffer
+ * from our pool, we increment the refill count for the
+ * object to be alloced later.
+ */
+ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb);
+ ASSERT(ctfpool != NULL);
+ PKTCLRFAST(osh, p);
+ PKTCLRFAST(osh, skb);
+ ctfpool->refills++;
+ }
+#endif /* CTFPOOL */
+
+ /* Clear PKTC context */
+ PKTSETCLINK(p, NULL);
+ PKTCCLRFLAGS(p);
+ PKTCSETCNT(p, 1);
+ PKTCSETLEN(p, PKTLEN(osh, skb));
+
+ /* skb_clone copies skb->cb.. we don't want that */
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(p);
+
+ /* Increment the packet counter */
+ atomic_inc(&osh->cmn->pktalloced);
+#ifdef BCMDBG_CTRACE
+ ADD_CTRACE(osh, (struct sk_buff *)p, file, line);
+#endif
+ return (p);
+}
+
+#ifdef BCMDBG_CTRACE
+int osl_pkt_is_frmnative(osl_t *osh, struct sk_buff *pkt)
+{
+ unsigned long flags;
+ struct sk_buff *skb;
+ int ck = FALSE;
+
+ spin_lock_irqsave(&osh->ctrace_lock, flags);
+
+ list_for_each_entry(skb, &osh->ctrace_list, ctrace_list) {
+ if (pkt == skb) {
+ ck = TRUE;
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&osh->ctrace_lock, flags);
+ return ck;
+}
+
+void osl_ctrace_dump(osl_t *osh, struct bcmstrbuf *b)
+{
+ unsigned long flags;
+ struct sk_buff *skb;
+ int idx = 0;
+ int i, j;
+
+ spin_lock_irqsave(&osh->ctrace_lock, flags);
+
+ if (b != NULL)
+ bcm_bprintf(b, " Total %d sbk not free\n", osh->ctrace_num);
+ else
+ printk(" Total %d sbk not free\n", osh->ctrace_num);
+
+ list_for_each_entry(skb, &osh->ctrace_list, ctrace_list) {
+ if (b != NULL)
+ bcm_bprintf(b, "[%d] skb %p:\n", ++idx, skb);
+ else
+ printk("[%d] skb %p:\n", ++idx, skb);
+
+ for (i = 0; i < skb->ctrace_count; i++) {
+ j = (skb->ctrace_start + i) % CTRACE_NUM;
+ if (b != NULL)
+ bcm_bprintf(b, " [%s(%d)]\n", skb->func[j], skb->line[j]);
+ else
+ printk(" [%s(%d)]\n", skb->func[j], skb->line[j]);
+ }
+ if (b != NULL)
+ bcm_bprintf(b, "\n");
+ else
+ printk("\n");
+ }
+
+ spin_unlock_irqrestore(&osh->ctrace_lock, flags);
+
+ return;
+}
+#endif /* BCMDBG_CTRACE */
+
+
+/*
+ * OSLREGOPS specifies the use of osl_XXX routines to be used for register access
+ */
+
+/*
+ * BINOSL selects the slightly slower function-call-based binary compatible osl.
+ */
+
+uint
+osl_pktalloced(osl_t *osh)
+{
+ if (atomic_read(&osh->cmn->refcount) == 1)
+ return (atomic_read(&osh->cmn->pktalloced));
+ else
+ return 0;
+}
+
+/* Linux Kernel: File Operations: start */
+void *
+osl_os_open_image(char *filename)
+{
+ struct file *fp;
+
+ fp = filp_open(filename, O_RDONLY, 0);
+ /*
+ * 2.6.11 (FC4) supports filp_open() but later revs don't?
+ * Alternative:
+ * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
+ * ???
+ */
+ if (IS_ERR(fp))
+ fp = NULL;
+
+ return fp;
+}
+
+int
+osl_os_get_image_block(char *buf, int len, void *image)
+{
+ struct file *fp = (struct file *)image;
+ int rdlen;
+
+ if (!image)
+ return 0;
+
+ rdlen = kernel_read(fp, fp->f_pos, buf, len);
+ if (rdlen > 0)
+ fp->f_pos += rdlen;
+
+ return rdlen;
+}
+
+void
+osl_os_close_image(void *image)
+{
+ if (image)
+ filp_close((struct file *)image, NULL);
+}
+
+int
+osl_os_image_size(void *image)
+{
+ int len = 0, curroffset;
+
+ if (image) {
+ /* store the current offset */
+ curroffset = generic_file_llseek(image, 0, 1);
+ /* goto end of file to get length */
+ len = generic_file_llseek(image, 0, 2);
+ /* restore back the offset */
+ generic_file_llseek(image, curroffset, 0);
+ }
+ return len;
+}
+
+/* Linux Kernel: File Operations: end */
diff --git a/drivers/net/wireless/bcmdhd/sbutils.c b/drivers/net/wireless/bcmdhd/sbutils.c
new file mode 100644
index 000000000000..bd99a9fd4ff2
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/sbutils.c
@@ -0,0 +1,1063 @@
+/*
+ * Misc utility routines for accessing chip-specific features
+ * of the SiliconBackplane-based Broadcom chips.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: sbutils.c 431423 2013-10-23 16:07:35Z $
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <bcmdevs.h>
+#include <hndsoc.h>
+#include <sbchipc.h>
+#include <pcicfg.h>
+#include <sbpcmcia.h>
+
+#include "siutils_priv.h"
+
+
+/* local prototypes */
+static uint _sb_coreidx(si_info_t *sii, uint32 sba);
+static uint _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba,
+ uint ncores);
+static uint32 _sb_coresba(si_info_t *sii);
+static void *_sb_setcoreidx(si_info_t *sii, uint coreidx);
+#define SET_SBREG(sii, r, mask, val) \
+ W_SBREG((sii), (r), ((R_SBREG((sii), (r)) & ~(mask)) | (val)))
+#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
+
+/* sonicsrev */
+#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
+#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
+
+#define R_SBREG(sii, sbr) sb_read_sbreg((sii), (sbr))
+#define W_SBREG(sii, sbr, v) sb_write_sbreg((sii), (sbr), (v))
+#define AND_SBREG(sii, sbr, v) W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) & (v)))
+#define OR_SBREG(sii, sbr, v) W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) | (v)))
+
+static uint32
+sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr)
+{
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint8 tmp;
+ uint32 val, intr_val = 0;
+
+
+ /*
+ * compact flash only has 11 bits address, while we needs 12 bits address.
+ * MEM_SEG will be OR'd with other 11 bits address in hardware,
+ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
+ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
+ */
+ if (PCMCIA(sii)) {
+ INTR_OFF(sii, intr_val);
+ tmp = 1;
+ OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
+ sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
+ }
+
+ val = R_REG(sii->osh, sbr);
+
+ if (PCMCIA(sii)) {
+ tmp = 0;
+ OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
+ INTR_RESTORE(sii, intr_val);
+ }
+
+ return (val);
+}
+
+static void
+sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v)
+{
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint8 tmp;
+ volatile uint32 dummy;
+ uint32 intr_val = 0;
+
+
+ /*
+ * compact flash only has 11 bits address, while we needs 12 bits address.
+ * MEM_SEG will be OR'd with other 11 bits address in hardware,
+ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
+ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
+ */
+ if (PCMCIA(sii)) {
+ INTR_OFF(sii, intr_val);
+ tmp = 1;
+ OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
+ sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
+ }
+
+ if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
+ dummy = R_REG(sii->osh, sbr);
+ BCM_REFERENCE(dummy);
+ W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff));
+ dummy = R_REG(sii->osh, sbr);
+ BCM_REFERENCE(dummy);
+ W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff));
+ } else
+ W_REG(sii->osh, sbr, v);
+
+ if (PCMCIA(sii)) {
+ tmp = 0;
+ OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
+ INTR_RESTORE(sii, intr_val);
+ }
+}
+
+uint
+sb_coreid(si_t *sih)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
+}
+
+uint
+sb_intflag(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ void *corereg;
+ sbconfig_t *sb;
+ uint origidx, intflag, intr_val = 0;
+
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+ corereg = si_setcore(sih, CC_CORE_ID, 0);
+ ASSERT(corereg != NULL);
+ sb = REGS2SB(corereg);
+ intflag = R_SBREG(sii, &sb->sbflagst);
+ sb_setcoreidx(sih, origidx);
+ INTR_RESTORE(sii, intr_val);
+
+ return intflag;
+}
+
+uint
+sb_flag(si_t *sih)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ return R_SBREG(sii, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
+}
+
+void
+sb_setint(si_t *sih, int siflag)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+ uint32 vec;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ if (siflag == -1)
+ vec = 0;
+ else
+ vec = 1 << siflag;
+ W_SBREG(sii, &sb->sbintvec, vec);
+}
+
+/* return core index of the core with address 'sba' */
+static uint
+_sb_coreidx(si_info_t *sii, uint32 sba)
+{
+ uint i;
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ for (i = 0; i < sii->numcores; i ++)
+ if (sba == cores_info->coresba[i])
+ return i;
+ return BADIDX;
+}
+
+/* return core address of the current core */
+static uint32
+_sb_coresba(si_info_t *sii)
+{
+ uint32 sbaddr;
+
+
+ switch (BUSTYPE(sii->pub.bustype)) {
+ case SI_BUS: {
+ sbconfig_t *sb = REGS2SB(sii->curmap);
+ sbaddr = sb_base(R_SBREG(sii, &sb->sbadmatch0));
+ break;
+ }
+
+ case PCI_BUS:
+ sbaddr = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
+ break;
+
+ case PCMCIA_BUS: {
+ uint8 tmp = 0;
+ OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1);
+ sbaddr = (uint32)tmp << 12;
+ OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1);
+ sbaddr |= (uint32)tmp << 16;
+ OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1);
+ sbaddr |= (uint32)tmp << 24;
+ break;
+ }
+
+ case SPI_BUS:
+ case SDIO_BUS:
+ sbaddr = (uint32)(uintptr)sii->curmap;
+ break;
+
+
+ default:
+ sbaddr = BADCOREADDR;
+ break;
+ }
+
+ return sbaddr;
+}
+
+uint
+sb_corevendor(si_t *sih)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
+}
+
+uint
+sb_corerev(si_t *sih)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+ uint sbidh;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+ sbidh = R_SBREG(sii, &sb->sbidhigh);
+
+ return (SBCOREREV(sbidh));
+}
+
+/* set core-specific control flags */
+void
+sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+ uint32 w;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ ASSERT((val & ~mask) == 0);
+
+ /* mask and set */
+ w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) |
+ (val << SBTML_SICF_SHIFT);
+ W_SBREG(sii, &sb->sbtmstatelow, w);
+}
+
+/* set/clear core-specific control flags */
+uint32
+sb_core_cflags(si_t *sih, uint32 mask, uint32 val)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+ uint32 w;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ ASSERT((val & ~mask) == 0);
+
+ /* mask and set */
+ if (mask || val) {
+ w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) |
+ (val << SBTML_SICF_SHIFT);
+ W_SBREG(sii, &sb->sbtmstatelow, w);
+ }
+
+ /* return the new value
+ * for write operation, the following readback ensures the completion of write opration.
+ */
+ return (R_SBREG(sii, &sb->sbtmstatelow) >> SBTML_SICF_SHIFT);
+}
+
+/* set/clear core-specific status flags */
+uint32
+sb_core_sflags(si_t *sih, uint32 mask, uint32 val)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+ uint32 w;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ ASSERT((val & ~mask) == 0);
+ ASSERT((mask & ~SISF_CORE_BITS) == 0);
+
+ /* mask and set */
+ if (mask || val) {
+ w = (R_SBREG(sii, &sb->sbtmstatehigh) & ~(mask << SBTMH_SISF_SHIFT)) |
+ (val << SBTMH_SISF_SHIFT);
+ W_SBREG(sii, &sb->sbtmstatehigh, w);
+ }
+
+ /* return the new value */
+ return (R_SBREG(sii, &sb->sbtmstatehigh) >> SBTMH_SISF_SHIFT);
+}
+
+bool
+sb_iscoreup(si_t *sih)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ return ((R_SBREG(sii, &sb->sbtmstatelow) &
+ (SBTML_RESET | SBTML_REJ_MASK | (SICF_CLOCK_EN << SBTML_SICF_SHIFT))) ==
+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+}
+
+/*
+ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
+ * switch back to the original core, and return the new value.
+ *
+ * When using the silicon backplane, no fidleing with interrupts or core switches are needed.
+ *
+ * Also, when using pci/pcie, we can optimize away the core switching for pci registers
+ * and (on newer pci cores) chipcommon registers.
+ */
+uint
+sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
+{
+ uint origidx = 0;
+ uint32 *r = NULL;
+ uint w;
+ uint intr_val = 0;
+ bool fast = FALSE;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ ASSERT(GOODIDX(coreidx));
+ ASSERT(regoff < SI_CORE_SIZE);
+ ASSERT((val & ~mask) == 0);
+
+ if (coreidx >= SI_MAXCORES)
+ return 0;
+
+ if (BUSTYPE(sii->pub.bustype) == SI_BUS) {
+ /* If internal bus, we can always get at everything */
+ fast = TRUE;
+ /* map if does not exist */
+ if (!cores_info->regs[coreidx]) {
+ cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
+ SI_CORE_SIZE);
+ ASSERT(GOODREGS(cores_info->regs[coreidx]));
+ }
+ r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
+ } else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
+ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
+
+ if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
+ /* Chipc registers are mapped at 12KB */
+
+ fast = TRUE;
+ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
+ } else if (sii->pub.buscoreidx == coreidx) {
+ /* pci registers are at either in the last 2KB of an 8KB window
+ * or, in pcie and pci rev 13 at 8KB
+ */
+ fast = TRUE;
+ if (SI_FAST(sii))
+ r = (uint32 *)((char *)sii->curmap +
+ PCI_16KB0_PCIREGS_OFFSET + regoff);
+ else
+ r = (uint32 *)((char *)sii->curmap +
+ ((regoff >= SBCONFIGOFF) ?
+ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
+ regoff);
+ }
+ }
+
+ if (!fast) {
+ INTR_OFF(sii, intr_val);
+
+ /* save current core index */
+ origidx = si_coreidx(&sii->pub);
+
+ /* switch core */
+ r = (uint32*) ((uchar*)sb_setcoreidx(&sii->pub, coreidx) + regoff);
+ }
+ ASSERT(r != NULL);
+
+ /* mask and set */
+ if (mask || val) {
+ if (regoff >= SBCONFIGOFF) {
+ w = (R_SBREG(sii, r) & ~mask) | val;
+ W_SBREG(sii, r, w);
+ } else {
+ w = (R_REG(sii->osh, r) & ~mask) | val;
+ W_REG(sii->osh, r, w);
+ }
+ }
+
+ /* readback */
+ if (regoff >= SBCONFIGOFF)
+ w = R_SBREG(sii, r);
+ else {
+ if ((CHIPID(sii->pub.chip) == BCM5354_CHIP_ID) &&
+ (coreidx == SI_CC_IDX) &&
+ (regoff == OFFSETOF(chipcregs_t, watchdog))) {
+ w = val;
+ } else
+ w = R_REG(sii->osh, r);
+ }
+
+ if (!fast) {
+ /* restore core index */
+ if (origidx != coreidx)
+ sb_setcoreidx(&sii->pub, origidx);
+
+ INTR_RESTORE(sii, intr_val);
+ }
+
+ return (w);
+}
+
+/*
+ * If there is no need for fiddling with interrupts or core switches (typically silicon
+ * back plane registers, pci registers and chipcommon registers), this function
+ * returns the register offset on this core to a mapped address. This address can
+ * be used for W_REG/R_REG directly.
+ *
+ * For accessing registers that would need a core switch, this function will return
+ * NULL.
+ */
+uint32 *
+sb_corereg_addr(si_t *sih, uint coreidx, uint regoff)
+{
+ uint32 *r = NULL;
+ bool fast = FALSE;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ ASSERT(GOODIDX(coreidx));
+ ASSERT(regoff < SI_CORE_SIZE);
+
+ if (coreidx >= SI_MAXCORES)
+ return 0;
+
+ if (BUSTYPE(sii->pub.bustype) == SI_BUS) {
+ /* If internal bus, we can always get at everything */
+ fast = TRUE;
+ /* map if does not exist */
+ if (!cores_info->regs[coreidx]) {
+ cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
+ SI_CORE_SIZE);
+ ASSERT(GOODREGS(cores_info->regs[coreidx]));
+ }
+ r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
+ } else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
+ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
+
+ if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
+ /* Chipc registers are mapped at 12KB */
+
+ fast = TRUE;
+ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
+ } else if (sii->pub.buscoreidx == coreidx) {
+ /* pci registers are at either in the last 2KB of an 8KB window
+ * or, in pcie and pci rev 13 at 8KB
+ */
+ fast = TRUE;
+ if (SI_FAST(sii))
+ r = (uint32 *)((char *)sii->curmap +
+ PCI_16KB0_PCIREGS_OFFSET + regoff);
+ else
+ r = (uint32 *)((char *)sii->curmap +
+ ((regoff >= SBCONFIGOFF) ?
+ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
+ regoff);
+ }
+ }
+
+ if (!fast)
+ return 0;
+
+ return (r);
+}
+
+/* Scan the enumeration space to find all cores starting from the given
+ * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba'
+ * is the default core address at chip POR time and 'regs' is the virtual
+ * address that the default core is mapped at. 'ncores' is the number of
+ * cores expected on bus 'sbba'. It returns the total number of cores
+ * starting from bus 'sbba', inclusive.
+ */
+#define SB_MAXBUSES 2
+static uint
+_sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, uint numcores)
+{
+ uint next;
+ uint ncc = 0;
+ uint i;
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ if (bus >= SB_MAXBUSES) {
+ SI_ERROR(("_sb_scan: bus 0x%08x at level %d is too deep to scan\n", sbba, bus));
+ return 0;
+ }
+ SI_MSG(("_sb_scan: scan bus 0x%08x assume %u cores\n", sbba, numcores));
+
+ /* Scan all cores on the bus starting from core 0.
+ * Core addresses must be contiguous on each bus.
+ */
+ for (i = 0, next = sii->numcores; i < numcores && next < SB_BUS_MAXCORES; i++, next++) {
+ cores_info->coresba[next] = sbba + (i * SI_CORE_SIZE);
+
+ /* keep and reuse the initial register mapping */
+ if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && (cores_info->coresba[next] == sba)) {
+ SI_VMSG(("_sb_scan: reuse mapped regs %p for core %u\n", regs, next));
+ cores_info->regs[next] = regs;
+ }
+
+ /* change core to 'next' and read its coreid */
+ sii->curmap = _sb_setcoreidx(sii, next);
+ sii->curidx = next;
+
+ cores_info->coreid[next] = sb_coreid(&sii->pub);
+
+ /* core specific processing... */
+ /* chipc provides # cores */
+ if (cores_info->coreid[next] == CC_CORE_ID) {
+ chipcregs_t *cc = (chipcregs_t *)sii->curmap;
+ uint32 ccrev = sb_corerev(&sii->pub);
+
+ /* determine numcores - this is the total # cores in the chip */
+ if (((ccrev == 4) || (ccrev >= 6))) {
+ ASSERT(cc);
+ numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >>
+ CID_CC_SHIFT;
+ } else {
+ /* Older chips */
+ uint chip = CHIPID(sii->pub.chip);
+
+ if (chip == BCM4306_CHIP_ID) /* < 4306c0 */
+ numcores = 6;
+ else if (chip == BCM4704_CHIP_ID)
+ numcores = 9;
+ else if (chip == BCM5365_CHIP_ID)
+ numcores = 7;
+ else {
+ SI_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n",
+ chip));
+ ASSERT(0);
+ numcores = 1;
+ }
+ }
+ SI_VMSG(("_sb_scan: there are %u cores in the chip %s\n", numcores,
+ sii->pub.issim ? "QT" : ""));
+ }
+ /* scan bridged SB(s) and add results to the end of the list */
+ else if (cores_info->coreid[next] == OCP_CORE_ID) {
+ sbconfig_t *sb = REGS2SB(sii->curmap);
+ uint32 nsbba = R_SBREG(sii, &sb->sbadmatch1);
+ uint nsbcc;
+
+ sii->numcores = next + 1;
+
+ if ((nsbba & 0xfff00000) != SI_ENUM_BASE)
+ continue;
+ nsbba &= 0xfffff000;
+ if (_sb_coreidx(sii, nsbba) != BADIDX)
+ continue;
+
+ nsbcc = (R_SBREG(sii, &sb->sbtmstatehigh) & 0x000f0000) >> 16;
+ nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc);
+ if (sbba == SI_ENUM_BASE)
+ numcores -= nsbcc;
+ ncc += nsbcc;
+ }
+ }
+
+ SI_MSG(("_sb_scan: found %u cores on bus 0x%08x\n", i, sbba));
+
+ sii->numcores = i + ncc;
+ return sii->numcores;
+}
+
+/* scan the sb enumerated space to identify all cores */
+void
+sb_scan(si_t *sih, void *regs, uint devid)
+{
+ uint32 origsba;
+ sbconfig_t *sb;
+ si_info_t *sii = SI_INFO(sih);
+
+ sb = REGS2SB(sii->curmap);
+
+ sii->pub.socirev = (R_SBREG(sii, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
+
+ /* Save the current core info and validate it later till we know
+ * for sure what is good and what is bad.
+ */
+ origsba = _sb_coresba(sii);
+
+ /* scan all SB(s) starting from SI_ENUM_BASE */
+ sii->numcores = _sb_scan(sii, origsba, regs, 0, SI_ENUM_BASE, 1);
+}
+
+/*
+ * This function changes logical "focus" to the indicated core;
+ * must be called with interrupts off.
+ * Moreover, callers should keep interrupts off during switching out of and back to d11 core
+ */
+void *
+sb_setcoreidx(si_t *sih, uint coreidx)
+{
+ si_info_t *sii = SI_INFO(sih);
+
+ if (coreidx >= sii->numcores)
+ return (NULL);
+
+ /*
+ * If the user has provided an interrupt mask enabled function,
+ * then assert interrupts are disabled before switching the core.
+ */
+ ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
+
+ sii->curmap = _sb_setcoreidx(sii, coreidx);
+ sii->curidx = coreidx;
+
+ return (sii->curmap);
+}
+
+/* This function changes the logical "focus" to the indicated core.
+ * Return the current core's virtual address.
+ */
+static void *
+_sb_setcoreidx(si_info_t *sii, uint coreidx)
+{
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint32 sbaddr = cores_info->coresba[coreidx];
+ void *regs;
+
+ switch (BUSTYPE(sii->pub.bustype)) {
+ case SI_BUS:
+ /* map new one */
+ if (!cores_info->regs[coreidx]) {
+ cores_info->regs[coreidx] = REG_MAP(sbaddr, SI_CORE_SIZE);
+ ASSERT(GOODREGS(cores_info->regs[coreidx]));
+ }
+ regs = cores_info->regs[coreidx];
+ break;
+
+ case PCI_BUS:
+ /* point bar0 window */
+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, sbaddr);
+ regs = sii->curmap;
+ break;
+
+ case PCMCIA_BUS: {
+ uint8 tmp = (sbaddr >> 12) & 0x0f;
+ OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1);
+ tmp = (sbaddr >> 16) & 0xff;
+ OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1);
+ tmp = (sbaddr >> 24) & 0xff;
+ OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1);
+ regs = sii->curmap;
+ break;
+ }
+ case SPI_BUS:
+ case SDIO_BUS:
+ /* map new one */
+ if (!cores_info->regs[coreidx]) {
+ cores_info->regs[coreidx] = (void *)(uintptr)sbaddr;
+ ASSERT(GOODREGS(cores_info->regs[coreidx]));
+ }
+ regs = cores_info->regs[coreidx];
+ break;
+
+
+ default:
+ ASSERT(0);
+ regs = NULL;
+ break;
+ }
+
+ return regs;
+}
+
+/* Return the address of sbadmatch0/1/2/3 register */
+static volatile uint32 *
+sb_admatch(si_info_t *sii, uint asidx)
+{
+ sbconfig_t *sb;
+ volatile uint32 *addrm;
+
+ sb = REGS2SB(sii->curmap);
+
+ switch (asidx) {
+ case 0:
+ addrm = &sb->sbadmatch0;
+ break;
+
+ case 1:
+ addrm = &sb->sbadmatch1;
+ break;
+
+ case 2:
+ addrm = &sb->sbadmatch2;
+ break;
+
+ case 3:
+ addrm = &sb->sbadmatch3;
+ break;
+
+ default:
+ SI_ERROR(("%s: Address space index (%d) out of range\n", __FUNCTION__, asidx));
+ return 0;
+ }
+
+ return (addrm);
+}
+
+/* Return the number of address spaces in current core */
+int
+sb_numaddrspaces(si_t *sih)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+
+ sii = SI_INFO(sih);
+ sb = REGS2SB(sii->curmap);
+
+ /* + 1 because of enumeration space */
+ return ((R_SBREG(sii, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT) + 1;
+}
+
+/* Return the address of the nth address space in the current core */
+uint32
+sb_addrspace(si_t *sih, uint asidx)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+
+ return (sb_base(R_SBREG(sii, sb_admatch(sii, asidx))));
+}
+
+/* Return the size of the nth address space in the current core */
+uint32
+sb_addrspacesize(si_t *sih, uint asidx)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+
+ return (sb_size(R_SBREG(sii, sb_admatch(sii, asidx))));
+}
+
+
+/* do buffered registers update */
+void
+sb_commit(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+
+ origidx = sii->curidx;
+ ASSERT(GOODIDX(origidx));
+
+ INTR_OFF(sii, intr_val);
+
+ /* switch over to chipcommon core if there is one, else use pci */
+ if (sii->pub.ccrev != NOREV) {
+ chipcregs_t *ccregs = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
+ ASSERT(ccregs != NULL);
+
+ /* do the buffer registers update */
+ W_REG(sii->osh, &ccregs->broadcastaddress, SB_COMMIT);
+ W_REG(sii->osh, &ccregs->broadcastdata, 0x0);
+ } else
+ ASSERT(0);
+
+ /* restore core index */
+ sb_setcoreidx(sih, origidx);
+ INTR_RESTORE(sii, intr_val);
+}
+
+void
+sb_core_disable(si_t *sih, uint32 bits)
+{
+ si_info_t *sii;
+ volatile uint32 dummy;
+ sbconfig_t *sb;
+
+ sii = SI_INFO(sih);
+
+ ASSERT(GOODREGS(sii->curmap));
+ sb = REGS2SB(sii->curmap);
+
+ /* if core is already in reset, just return */
+ if (R_SBREG(sii, &sb->sbtmstatelow) & SBTML_RESET)
+ return;
+
+ /* if clocks are not enabled, put into reset and return */
+ if ((R_SBREG(sii, &sb->sbtmstatelow) & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) == 0)
+ goto disable;
+
+ /* set target reject and spin until busy is clear (preserve core-specific bits) */
+ OR_SBREG(sii, &sb->sbtmstatelow, SBTML_REJ);
+ dummy = R_SBREG(sii, &sb->sbtmstatelow);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(1);
+ SPINWAIT((R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000);
+ if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY)
+ SI_ERROR(("%s: target state still busy\n", __FUNCTION__));
+
+ if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) {
+ OR_SBREG(sii, &sb->sbimstate, SBIM_RJ);
+ dummy = R_SBREG(sii, &sb->sbimstate);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(1);
+ SPINWAIT((R_SBREG(sii, &sb->sbimstate) & SBIM_BY), 100000);
+ }
+
+ /* set reset and reject while enabling the clocks */
+ W_SBREG(sii, &sb->sbtmstatelow,
+ (((bits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
+ SBTML_REJ | SBTML_RESET));
+ dummy = R_SBREG(sii, &sb->sbtmstatelow);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(10);
+
+ /* don't forget to clear the initiator reject bit */
+ if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT)
+ AND_SBREG(sii, &sb->sbimstate, ~SBIM_RJ);
+
+disable:
+ /* leave reset and reject asserted */
+ W_SBREG(sii, &sb->sbtmstatelow, ((bits << SBTML_SICF_SHIFT) | SBTML_REJ | SBTML_RESET));
+ OSL_DELAY(1);
+}
+
+/* reset and re-enable a core
+ * inputs:
+ * bits - core specific bits that are set during and after reset sequence
+ * resetbits - core specific bits that are set only during reset sequence
+ */
+void
+sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
+{
+ si_info_t *sii;
+ sbconfig_t *sb;
+ volatile uint32 dummy;
+
+ sii = SI_INFO(sih);
+ ASSERT(GOODREGS(sii->curmap));
+ sb = REGS2SB(sii->curmap);
+
+ /*
+ * Must do the disable sequence first to work for arbitrary current core state.
+ */
+ sb_core_disable(sih, (bits | resetbits));
+
+ /*
+ * Now do the initialization sequence.
+ */
+
+ /* set reset while enabling the clock and forcing them on throughout the core */
+ W_SBREG(sii, &sb->sbtmstatelow,
+ (((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
+ SBTML_RESET));
+ dummy = R_SBREG(sii, &sb->sbtmstatelow);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(1);
+
+ if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_SERR) {
+ W_SBREG(sii, &sb->sbtmstatehigh, 0);
+ }
+ if ((dummy = R_SBREG(sii, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) {
+ AND_SBREG(sii, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO));
+ }
+
+ /* clear reset and allow it to propagate throughout the core */
+ W_SBREG(sii, &sb->sbtmstatelow,
+ ((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT));
+ dummy = R_SBREG(sii, &sb->sbtmstatelow);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(1);
+
+ /* leave clock enabled */
+ W_SBREG(sii, &sb->sbtmstatelow, ((bits | SICF_CLOCK_EN) << SBTML_SICF_SHIFT));
+ dummy = R_SBREG(sii, &sb->sbtmstatelow);
+ BCM_REFERENCE(dummy);
+ OSL_DELAY(1);
+}
+
+/*
+ * Set the initiator timeout for the "master core".
+ * The master core is defined to be the core in control
+ * of the chip and so it issues accesses to non-memory
+ * locations (Because of dma *any* core can access memeory).
+ *
+ * The routine uses the bus to decide who is the master:
+ * SI_BUS => mips
+ * JTAG_BUS => chipc
+ * PCI_BUS => pci or pcie
+ * PCMCIA_BUS => pcmcia
+ * SDIO_BUS => pcmcia
+ *
+ * This routine exists so callers can disable initiator
+ * timeouts so accesses to very slow devices like otp
+ * won't cause an abort. The routine allows arbitrary
+ * settings of the service and request timeouts, though.
+ *
+ * Returns the timeout state before changing it or -1
+ * on error.
+ */
+
+#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK)
+
+uint32
+sb_set_initiator_to(si_t *sih, uint32 to, uint idx)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+ uint32 tmp, ret = 0xffffffff;
+ sbconfig_t *sb;
+
+
+ if ((to & ~TO_MASK) != 0)
+ return ret;
+
+ /* Figure out the master core */
+ if (idx == BADIDX) {
+ switch (BUSTYPE(sii->pub.bustype)) {
+ case PCI_BUS:
+ idx = sii->pub.buscoreidx;
+ break;
+ case JTAG_BUS:
+ idx = SI_CC_IDX;
+ break;
+ case PCMCIA_BUS:
+ case SDIO_BUS:
+ idx = si_findcoreidx(sih, PCMCIA_CORE_ID, 0);
+ break;
+ case SI_BUS:
+ idx = si_findcoreidx(sih, MIPS33_CORE_ID, 0);
+ break;
+ default:
+ ASSERT(0);
+ }
+ if (idx == BADIDX)
+ return ret;
+ }
+
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ sb = REGS2SB(sb_setcoreidx(sih, idx));
+
+ tmp = R_SBREG(sii, &sb->sbimconfiglow);
+ ret = tmp & TO_MASK;
+ W_SBREG(sii, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to);
+
+ sb_commit(sih);
+ sb_setcoreidx(sih, origidx);
+ INTR_RESTORE(sii, intr_val);
+ return ret;
+}
+
+uint32
+sb_base(uint32 admatch)
+{
+ uint32 base;
+ uint type;
+
+ type = admatch & SBAM_TYPE_MASK;
+ ASSERT(type < 3);
+
+ base = 0;
+
+ if (type == 0) {
+ base = admatch & SBAM_BASE0_MASK;
+ } else if (type == 1) {
+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
+ base = admatch & SBAM_BASE1_MASK;
+ } else if (type == 2) {
+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
+ base = admatch & SBAM_BASE2_MASK;
+ }
+
+ return (base);
+}
+
+uint32
+sb_size(uint32 admatch)
+{
+ uint32 size;
+ uint type;
+
+ type = admatch & SBAM_TYPE_MASK;
+ ASSERT(type < 3);
+
+ size = 0;
+
+ if (type == 0) {
+ size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1);
+ } else if (type == 1) {
+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
+ size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1);
+ } else if (type == 2) {
+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
+ size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1);
+ }
+
+ return (size);
+}
diff --git a/drivers/net/wireless/bcmdhd/siutils.c b/drivers/net/wireless/bcmdhd/siutils.c
new file mode 100644
index 000000000000..edcd1c141189
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/siutils.c
@@ -0,0 +1,2882 @@
+/*
+ * Misc utility routines for accessing chip-specific features
+ * of the SiliconBackplane-based Broadcom chips.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: siutils.c 550969 2015-04-22 00:27:43Z $
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <bcmdevs.h>
+#include <hndsoc.h>
+#include <sbchipc.h>
+#include <pcicfg.h>
+#include <sbpcmcia.h>
+#include <sbsocram.h>
+#include <bcmsdh.h>
+#include <sdio.h>
+#include <sbsdio.h>
+#include <sbhnddma.h>
+#include <sbsdpcmdev.h>
+#include <bcmsdpcm.h>
+#include <hndpmu.h>
+
+#ifdef BCM_SDRBL
+#include <hndcpu.h>
+#endif /* BCM_SDRBL */
+
+#include "siutils_priv.h"
+
+/* local prototypes */
+static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
+ uint bustype, void *sdh, char **vars, uint *varsz);
+static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
+static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
+ uint *origidx, void *regs);
+
+
+
+/* global variable to indicate reservation/release of gpio's */
+static uint32 si_gpioreservation = 0;
+
+/* global flag to prevent shared resources from being initialized multiple times in si_attach() */
+
+int do_4360_pcie2_war = 0;
+
+/* global kernel resource */
+static si_info_t ksii;
+static si_cores_info_t ksii_cores_info;
+
+/**
+ * Allocate an si handle. This function may be called multiple times.
+ *
+ * devid - pci device id (used to determine chip#)
+ * osh - opaque OS handle
+ * regs - virtual address of initial core registers
+ * bustype - pci/pcmcia/sb/sdio/etc
+ * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
+ * function set 'vars' to NULL, making dereferencing of this parameter undesired.
+ * varsz - pointer to int to return the size of the vars
+ */
+si_t *
+si_attach(uint devid, osl_t *osh, void *regs,
+ uint bustype, void *sdh, char **vars, uint *varsz)
+{
+ si_info_t *sii;
+ si_cores_info_t *cores_info;
+ /* alloc si_info_t */
+ if ((sii = MALLOCZ(osh, sizeof (si_info_t))) == NULL) {
+ SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
+ return (NULL);
+ }
+
+ /* alloc si_cores_info_t */
+ if ((cores_info = (si_cores_info_t *)MALLOCZ(osh, sizeof (si_cores_info_t))) == NULL) {
+ SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
+ MFREE(osh, sii, sizeof(si_info_t));
+ return (NULL);
+ }
+ sii->cores_info = cores_info;
+
+ if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
+ MFREE(osh, sii, sizeof(si_info_t));
+ MFREE(osh, cores_info, sizeof(si_cores_info_t));
+ return (NULL);
+ }
+ sii->vars = vars ? *vars : NULL;
+ sii->varsz = varsz ? *varsz : 0;
+
+ return (si_t *)sii;
+}
+
+
+static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
+
+/** generic kernel variant of si_attach() */
+si_t *
+si_kattach(osl_t *osh)
+{
+ static bool ksii_attached = FALSE;
+ si_cores_info_t *cores_info;
+
+ if (!ksii_attached) {
+ void *regs = NULL;
+ regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
+ cores_info = (si_cores_info_t *)&ksii_cores_info;
+ ksii.cores_info = cores_info;
+
+ ASSERT(osh);
+ if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
+ SI_BUS, NULL,
+ osh != SI_OSH ? &(ksii.vars) : NULL,
+ osh != SI_OSH ? &(ksii.varsz) : NULL) == NULL) {
+ SI_ERROR(("si_kattach: si_doattach failed\n"));
+ REG_UNMAP(regs);
+ return NULL;
+ }
+ REG_UNMAP(regs);
+
+ /* save ticks normalized to ms for si_watchdog_ms() */
+ if (PMUCTL_ENAB(&ksii.pub)) {
+ /* based on 32KHz ILP clock */
+ wd_msticks = 32;
+ } else {
+ wd_msticks = ALP_CLOCK / 1000;
+ }
+
+ ksii_attached = TRUE;
+ SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
+ ksii.pub.ccrev, wd_msticks));
+ }
+
+ return &ksii.pub;
+}
+
+
+static bool
+si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
+{
+ /* need to set memseg flag for CF card first before any sb registers access */
+ if (BUSTYPE(bustype) == PCMCIA_BUS)
+ sii->memseg = TRUE;
+
+
+ if (BUSTYPE(bustype) == SDIO_BUS) {
+ int err;
+ uint8 clkset;
+
+ /* Try forcing SDIO core to do ALPAvail request only */
+ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+ if (!err) {
+ uint8 clkval;
+
+ /* If register supported, wait for ALPAvail and then force ALP */
+ clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
+ if ((clkval & ~SBSDIO_AVBITS) == clkset) {
+ SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
+ PMU_MAX_TRANSITION_DLY);
+ if (!SBSDIO_ALPAV(clkval)) {
+ SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
+ clkval));
+ return FALSE;
+ }
+ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+ clkset, &err);
+ OSL_DELAY(65);
+ }
+ }
+
+ /* Also, disable the extra SDIO pull-ups */
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
+ }
+
+
+ return TRUE;
+}
+
+static bool
+si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
+ uint *origidx, void *regs)
+{
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ bool pci, pcie, pcie_gen2 = FALSE;
+ uint i;
+ uint pciidx, pcieidx, pcirev, pcierev;
+
+ cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
+ ASSERT((uintptr)cc);
+
+ /* get chipcommon rev */
+ sii->pub.ccrev = (int)si_corerev(&sii->pub);
+
+ /* get chipcommon chipstatus */
+ if (sii->pub.ccrev >= 11)
+ sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
+
+ /* get chipcommon capabilites */
+ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
+ /* get chipcommon extended capabilities */
+
+ if (sii->pub.ccrev >= 35)
+ sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
+
+ /* get pmu rev and caps */
+ if (sii->pub.cccaps & CC_CAP_PMU) {
+ sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
+ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
+ }
+
+ SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
+ sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
+ sii->pub.pmucaps));
+
+ /* figure out bus/orignal core idx */
+ sii->pub.buscoretype = NODEV_CORE_ID;
+ sii->pub.buscorerev = (uint)NOREV;
+ sii->pub.buscoreidx = BADIDX;
+
+ pci = pcie = FALSE;
+ pcirev = pcierev = (uint)NOREV;
+ pciidx = pcieidx = BADIDX;
+
+ for (i = 0; i < sii->numcores; i++) {
+ uint cid, crev;
+
+ si_setcoreidx(&sii->pub, i);
+ cid = si_coreid(&sii->pub);
+ crev = si_corerev(&sii->pub);
+
+ /* Display cores found */
+ SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
+ i, cid, crev, cores_info->coresba[i], cores_info->regs[i]));
+
+ if (BUSTYPE(bustype) == SI_BUS) {
+ /* now look at the chipstatus register to figure the pacakge */
+ /* for SDIO but downloaded on PCIE dev */
+ if (cid == PCIE2_CORE_ID) {
+ if ((CHIPID(sii->pub.chip) == BCM43602_CHIP_ID) ||
+ ((CHIPID(sii->pub.chip) == BCM4345_CHIP_ID) &&
+ CST4345_CHIPMODE_PCIE(sii->pub.chipst))) {
+ pcieidx = i;
+ pcierev = crev;
+ pcie = TRUE;
+ pcie_gen2 = TRUE;
+ }
+ }
+
+ }
+ else if (BUSTYPE(bustype) == PCI_BUS) {
+ if (cid == PCI_CORE_ID) {
+ pciidx = i;
+ pcirev = crev;
+ pci = TRUE;
+ } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) {
+ pcieidx = i;
+ pcierev = crev;
+ pcie = TRUE;
+ if (cid == PCIE2_CORE_ID)
+ pcie_gen2 = TRUE;
+ }
+ } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
+ (cid == PCMCIA_CORE_ID)) {
+ sii->pub.buscorerev = crev;
+ sii->pub.buscoretype = cid;
+ sii->pub.buscoreidx = i;
+ }
+ else if (((BUSTYPE(bustype) == SDIO_BUS) ||
+ (BUSTYPE(bustype) == SPI_BUS)) &&
+ ((cid == PCMCIA_CORE_ID) ||
+ (cid == SDIOD_CORE_ID))) {
+ sii->pub.buscorerev = crev;
+ sii->pub.buscoretype = cid;
+ sii->pub.buscoreidx = i;
+ }
+
+ /* find the core idx before entering this func. */
+ if ((savewin && (savewin == cores_info->coresba[i])) ||
+ (regs == cores_info->regs[i]))
+ *origidx = i;
+ }
+
+#if defined(PCIE_FULL_DONGLE)
+ pci = FALSE;
+#endif
+ if (pci) {
+ sii->pub.buscoretype = PCI_CORE_ID;
+ sii->pub.buscorerev = pcirev;
+ sii->pub.buscoreidx = pciidx;
+ } else if (pcie) {
+ if (pcie_gen2)
+ sii->pub.buscoretype = PCIE2_CORE_ID;
+ else
+ sii->pub.buscoretype = PCIE_CORE_ID;
+ sii->pub.buscorerev = pcierev;
+ sii->pub.buscoreidx = pcieidx;
+ }
+
+ SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
+ sii->pub.buscorerev));
+
+ if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
+ (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
+ OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
+
+
+ /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was
+ * already running.
+ */
+ if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
+ if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
+ si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
+ si_core_disable(&sii->pub, 0);
+ }
+
+ /* return to the original core */
+ si_setcoreidx(&sii->pub, *origidx);
+
+ return TRUE;
+}
+
+
+
+
+/**
+ * Allocate an si handle. This function may be called multiple times.
+ *
+ * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
+ * function set 'vars' to NULL.
+ */
+static si_info_t *
+si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
+ uint bustype, void *sdh, char **vars, uint *varsz)
+{
+ struct si_pub *sih = &sii->pub;
+ uint32 w, savewin;
+ chipcregs_t *cc;
+ char *pvars = NULL;
+ uint origidx;
+#if !defined(_CFEZ_) || defined(CFG_WL)
+#endif
+
+ ASSERT(GOODREGS(regs));
+
+ savewin = 0;
+
+ sih->buscoreidx = BADIDX;
+
+ sii->curmap = regs;
+ sii->sdh = sdh;
+ sii->osh = osh;
+
+
+ /* check to see if we are a si core mimic'ing a pci core */
+ if ((bustype == PCI_BUS) &&
+ (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
+ SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
+ "devid:0x%x\n", __FUNCTION__, devid));
+ bustype = SI_BUS;
+ }
+
+ /* find Chipcommon address */
+ if (bustype == PCI_BUS) {
+ savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
+ if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
+ savewin = SI_ENUM_BASE;
+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
+ if (!regs)
+ return NULL;
+ cc = (chipcregs_t *)regs;
+ } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) {
+ cc = (chipcregs_t *)sii->curmap;
+ } else {
+ cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
+ }
+
+ sih->bustype = bustype;
+ if (bustype != BUSTYPE(bustype)) {
+ SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
+ bustype, BUSTYPE(bustype)));
+ return NULL;
+ }
+
+ /* bus/core/clk setup for register access */
+ if (!si_buscore_prep(sii, bustype, devid, sdh)) {
+ SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
+ return NULL;
+ }
+
+ /* ChipID recognition.
+ * We assume we can read chipid at offset 0 from the regs arg.
+ * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
+ * some way of recognizing them needs to be added here.
+ */
+ if (!cc) {
+ SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__));
+ return NULL;
+ }
+ w = R_REG(osh, &cc->chipid);
+ if ((w & 0xfffff) == 148277) w -= 65532;
+ sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
+ /* Might as wll fill in chip id rev & pkg */
+ sih->chip = w & CID_ID_MASK;
+ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
+ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
+
+ if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
+ (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
+ sih->chippkg = BCM4329_182PIN_PKG_ID;
+ }
+ sih->issim = IS_SIM(sih->chippkg);
+
+ /* scan for cores */
+ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
+ SI_MSG(("Found chip type SB (0x%08x)\n", w));
+ sb_scan(&sii->pub, regs, devid);
+ } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) ||
+ (CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) {
+ if (CHIPTYPE(sii->pub.socitype) == SOCI_AI)
+ SI_MSG(("Found chip type AI (0x%08x)\n", w));
+ else
+ SI_MSG(("Found chip type NAI (0x%08x)\n", w));
+ /* pass chipc address instead of original core base */
+ ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
+ } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
+ SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
+ /* pass chipc address instead of original core base */
+ ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
+ } else {
+ SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
+ return NULL;
+ }
+ /* no cores found, bail out */
+ if (sii->numcores == 0) {
+ SI_ERROR(("si_doattach: could not find any cores\n"));
+ return NULL;
+ }
+ /* bus/core/clk setup */
+ origidx = SI_CC_IDX;
+ if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
+ SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
+ goto exit;
+ }
+
+#if !defined(_CFEZ_) || defined(CFG_WL)
+ if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
+ >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
+ CST4322_SPROM_PRESENT))) {
+ SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
+ return NULL;
+ }
+
+ /* assume current core is CC */
+ if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
+ CHIPID(sih->chip) == BCM43235_CHIP_ID ||
+ CHIPID(sih->chip) == BCM43234_CHIP_ID ||
+ CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
+ (CHIPREV(sii->pub.chiprev) <= 2))) {
+
+ if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
+ uint clkdiv;
+ clkdiv = R_REG(osh, &cc->clkdiv);
+ /* otp_clk_div is even number, 120/14 < 9mhz */
+ clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
+ W_REG(osh, &cc->clkdiv, clkdiv);
+ SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
+ }
+ OSL_DELAY(10);
+ }
+
+ if (bustype == PCI_BUS) {
+
+ }
+#endif
+#ifdef BCM_SDRBL
+ /* 4360 rom bootloader in PCIE case, if the SDR is enabled, But preotection is
+ * not turned on, then we want to hold arm in reset.
+ * Bottomline: In sdrenable case, we allow arm to boot only when protection is
+ * turned on.
+ */
+ if (CHIP_HOSTIF_PCIE(&(sii->pub))) {
+ uint32 sflags = si_arm_sflags(&(sii->pub));
+
+ /* If SDR is enabled but protection is not turned on
+ * then we want to force arm to WFI.
+ */
+ if ((sflags & (SISF_SDRENABLE | SISF_TCMPROT)) == SISF_SDRENABLE) {
+ disable_arm_irq();
+ while (1) {
+ hnd_cpu_wait(sih);
+ }
+ }
+ }
+#endif /* BCM_SDRBL */
+
+ pvars = NULL;
+ BCM_REFERENCE(pvars);
+
+
+
+ if (sii->pub.ccrev >= 20) {
+ uint32 gpiopullup = 0, gpiopulldown = 0;
+ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
+ ASSERT(cc != NULL);
+
+ /* 4314/43142 has pin muxing, don't clear gpio bits */
+ if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
+ (CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
+ gpiopullup |= 0x402e0;
+ gpiopulldown |= 0x20500;
+ }
+
+ W_REG(osh, &cc->gpiopullup, gpiopullup);
+ W_REG(osh, &cc->gpiopulldown, gpiopulldown);
+ si_setcoreidx(sih, origidx);
+ }
+
+
+ /* clear any previous epidiag-induced target abort */
+ ASSERT(!si_taclear(sih, FALSE));
+
+
+ return (sii);
+
+exit:
+
+ return NULL;
+}
+
+/** may be called with core in reset */
+void
+si_detach(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint idx;
+
+
+ if (BUSTYPE(sih->bustype) == SI_BUS)
+ for (idx = 0; idx < SI_MAXCORES; idx++)
+ if (cores_info->regs[idx]) {
+ REG_UNMAP(cores_info->regs[idx]);
+ cores_info->regs[idx] = NULL;
+ }
+
+
+#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
+ if (cores_info != &ksii_cores_info)
+#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
+ MFREE(sii->osh, cores_info, sizeof(si_cores_info_t));
+
+#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
+ if (sii != &ksii)
+#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
+ MFREE(sii->osh, sii, sizeof(si_info_t));
+}
+
+void *
+si_osh(si_t *sih)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+ return sii->osh;
+}
+
+void
+si_setosh(si_t *sih, osl_t *osh)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+ if (sii->osh != NULL) {
+ SI_ERROR(("osh is already set....\n"));
+ ASSERT(!sii->osh);
+ }
+ sii->osh = osh;
+}
+
+/** register driver interrupt disabling and restoring callback functions */
+void
+si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
+ void *intrsenabled_fn, void *intr_arg)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ sii->intr_arg = intr_arg;
+ sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
+ sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
+ sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
+ /* save current core id. when this function called, the current core
+ * must be the core which provides driver functions(il, et, wl, etc.)
+ */
+ sii->dev_coreid = cores_info->coreid[sii->curidx];
+}
+
+void
+si_deregister_intr_callback(si_t *sih)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+ sii->intrsoff_fn = NULL;
+}
+
+uint
+si_intflag(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_intflag(sih);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return R_REG(sii->osh, ((uint32 *)(uintptr)
+ (sii->oob_router + OOB_STATUSA)));
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+uint
+si_flag(si_t *sih)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_flag(sih);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_flag(sih);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_flag(sih);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+uint
+si_flag_alt(si_t *sih)
+{
+ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_flag_alt(sih);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+void
+si_setint(si_t *sih, int siflag)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ sb_setint(sih, siflag);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ ai_setint(sih, siflag);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ ub_setint(sih, siflag);
+ else
+ ASSERT(0);
+}
+
+uint
+si_coreid(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ return cores_info->coreid[sii->curidx];
+}
+
+uint
+si_coreidx(si_t *sih)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+ return sii->curidx;
+}
+
+/** return the core-type instantiation # of the current core */
+uint
+si_coreunit(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint idx;
+ uint coreid;
+ uint coreunit;
+ uint i;
+
+ coreunit = 0;
+
+ idx = sii->curidx;
+
+ ASSERT(GOODREGS(sii->curmap));
+ coreid = si_coreid(sih);
+
+ /* count the cores of our type */
+ for (i = 0; i < idx; i++)
+ if (cores_info->coreid[i] == coreid)
+ coreunit++;
+
+ return (coreunit);
+}
+
+uint
+si_corevendor(si_t *sih)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_corevendor(sih);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_corevendor(sih);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_corevendor(sih);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+bool
+si_backplane64(si_t *sih)
+{
+ return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
+}
+
+uint
+si_corerev(si_t *sih)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_corerev(sih);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_corerev(sih);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_corerev(sih);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+/** return index of coreid or BADIDX if not found */
+uint
+si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint found;
+ uint i;
+
+
+ found = 0;
+
+ for (i = 0; i < sii->numcores; i++)
+ if (cores_info->coreid[i] == coreid) {
+ if (found == coreunit)
+ return (i);
+ found++;
+ }
+
+ return (BADIDX);
+}
+
+/** return total coreunit of coreid or zero if not found */
+uint
+si_numcoreunits(si_t *sih, uint coreid)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint found;
+ uint i;
+
+ found = 0;
+
+ for (i = 0; i < sii->numcores; i++)
+ if (cores_info->coreid[i] == coreid) {
+ found++;
+ }
+
+ return (found == 0? 0:found);
+}
+
+/** return list of found cores */
+uint
+si_corelist(si_t *sih, uint coreid[])
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ bcopy((uchar*)cores_info->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
+ return (sii->numcores);
+}
+
+/** return current wrapper mapping */
+void *
+si_wrapperregs(si_t *sih)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+ ASSERT(GOODREGS(sii->curwrap));
+
+ return (sii->curwrap);
+}
+
+/** return current register mapping */
+void *
+si_coreregs(si_t *sih)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+ ASSERT(GOODREGS(sii->curmap));
+
+ return (sii->curmap);
+}
+
+/**
+ * This function changes logical "focus" to the indicated core;
+ * must be called with interrupts off.
+ * Moreover, callers should keep interrupts off during switching out of and back to d11 core
+ */
+void *
+si_setcore(si_t *sih, uint coreid, uint coreunit)
+{
+ uint idx;
+
+ idx = si_findcoreidx(sih, coreid, coreunit);
+ if (!GOODIDX(idx))
+ return (NULL);
+
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_setcoreidx(sih, idx);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_setcoreidx(sih, idx);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_setcoreidx(sih, idx);
+ else {
+ ASSERT(0);
+ return NULL;
+ }
+}
+
+void *
+si_setcoreidx(si_t *sih, uint coreidx)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_setcoreidx(sih, coreidx);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_setcoreidx(sih, coreidx);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_setcoreidx(sih, coreidx);
+ else {
+ ASSERT(0);
+ return NULL;
+ }
+}
+
+/** Turn off interrupt as required by sb_setcore, before switch core */
+void *
+si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
+{
+ void *cc;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ if (SI_FAST(sii)) {
+ /* Overloading the origidx variable to remember the coreid,
+ * this works because the core ids cannot be confused with
+ * core indices.
+ */
+ *origidx = coreid;
+ if (coreid == CC_CORE_ID)
+ return (void *)CCREGS_FAST(sii);
+ else if (coreid == sih->buscoretype)
+ return (void *)PCIEREGS(sii);
+ }
+ INTR_OFF(sii, *intr_val);
+ *origidx = sii->curidx;
+ cc = si_setcore(sih, coreid, 0);
+ ASSERT(cc != NULL);
+
+ return cc;
+}
+
+/* restore coreidx and restore interrupt */
+void
+si_restore_core(si_t *sih, uint coreid, uint intr_val)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
+ return;
+
+ si_setcoreidx(sih, coreid);
+ INTR_RESTORE(sii, intr_val);
+}
+
+int
+si_numaddrspaces(si_t *sih)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_numaddrspaces(sih);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_numaddrspaces(sih);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_numaddrspaces(sih);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+uint32
+si_addrspace(si_t *sih, uint asidx)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_addrspace(sih, asidx);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_addrspace(sih, asidx);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_addrspace(sih, asidx);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+uint32
+si_addrspacesize(si_t *sih, uint asidx)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_addrspacesize(sih, asidx);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_addrspacesize(sih, asidx);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_addrspacesize(sih, asidx);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+void
+si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
+{
+ /* Only supported for SOCI_AI */
+ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ ai_coreaddrspaceX(sih, asidx, addr, size);
+ else
+ *size = 0;
+}
+
+uint32
+si_core_cflags(si_t *sih, uint32 mask, uint32 val)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_core_cflags(sih, mask, val);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_core_cflags(sih, mask, val);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_core_cflags(sih, mask, val);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+void
+si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ sb_core_cflags_wo(sih, mask, val);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ ai_core_cflags_wo(sih, mask, val);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ ub_core_cflags_wo(sih, mask, val);
+ else
+ ASSERT(0);
+}
+
+uint32
+si_core_sflags(si_t *sih, uint32 mask, uint32 val)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_core_sflags(sih, mask, val);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_core_sflags(sih, mask, val);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_core_sflags(sih, mask, val);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+bool
+si_iscoreup(si_t *sih)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_iscoreup(sih);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_iscoreup(sih);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_iscoreup(sih);
+ else {
+ ASSERT(0);
+ return FALSE;
+ }
+}
+
+uint
+si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
+{
+ /* only for AI back plane chips */
+ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return (ai_wrap_reg(sih, offset, mask, val));
+ return 0;
+}
+
+uint
+si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_corereg(sih, coreidx, regoff, mask, val);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_corereg(sih, coreidx, regoff, mask, val);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ return ub_corereg(sih, coreidx, regoff, mask, val);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
+/*
+ * If there is no need for fiddling with interrupts or core switches (typically silicon
+ * back plane registers, pci registers and chipcommon registers), this function
+ * returns the register offset on this core to a mapped address. This address can
+ * be used for W_REG/R_REG directly.
+ *
+ * For accessing registers that would need a core switch, this function will return
+ * NULL.
+ */
+uint32 *
+si_corereg_addr(si_t *sih, uint coreidx, uint regoff)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_corereg_addr(sih, coreidx, regoff);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_corereg_addr(sih, coreidx, regoff);
+ else {
+ return 0;
+ }
+}
+
+void
+si_core_disable(si_t *sih, uint32 bits)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ sb_core_disable(sih, bits);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ ai_core_disable(sih, bits);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ ub_core_disable(sih, bits);
+}
+
+void
+si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ sb_core_reset(sih, bits, resetbits);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ ai_core_reset(sih, bits, resetbits);
+ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
+ ub_core_reset(sih, bits, resetbits);
+}
+
+/** Run bist on current core. Caller needs to take care of core-specific bist hazards */
+int
+si_corebist(si_t *sih)
+{
+ uint32 cflags;
+ int result = 0;
+
+ /* Read core control flags */
+ cflags = si_core_cflags(sih, 0, 0);
+
+ /* Set bist & fgc */
+ si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
+
+ /* Wait for bist done */
+ SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
+
+ if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
+ result = BCME_ERROR;
+
+ /* Reset core control flags */
+ si_core_cflags(sih, 0xffff, cflags);
+
+ return result;
+}
+
+static uint32
+factor6(uint32 x)
+{
+ switch (x) {
+ case CC_F6_2: return 2;
+ case CC_F6_3: return 3;
+ case CC_F6_4: return 4;
+ case CC_F6_5: return 5;
+ case CC_F6_6: return 6;
+ case CC_F6_7: return 7;
+ default: return 0;
+ }
+}
+
+/*
+ * Divide the clock by the divisor with protection for
+ * a zero divisor.
+ */
+static uint32
+divide_clock(uint32 clock, uint32 div)
+{
+ return div ? clock / div : 0;
+}
+
+
+/** calculate the speed the SI would run at given a set of clockcontrol values */
+uint32
+si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
+{
+ uint32 n1, n2, clock, m1, m2, m3, mc;
+
+ n1 = n & CN_N1_MASK;
+ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
+
+ if (pll_type == PLL_TYPE6) {
+ if (m & CC_T6_MMASK)
+ return CC_T6_M1;
+ else
+ return CC_T6_M0;
+ } else if ((pll_type == PLL_TYPE1) ||
+ (pll_type == PLL_TYPE3) ||
+ (pll_type == PLL_TYPE4) ||
+ (pll_type == PLL_TYPE7)) {
+ n1 = factor6(n1);
+ n2 += CC_F5_BIAS;
+ } else if (pll_type == PLL_TYPE2) {
+ n1 += CC_T2_BIAS;
+ n2 += CC_T2_BIAS;
+ ASSERT((n1 >= 2) && (n1 <= 7));
+ ASSERT((n2 >= 5) && (n2 <= 23));
+ } else if (pll_type == PLL_TYPE5) {
+ return (100000000);
+ } else
+ ASSERT(0);
+ /* PLL types 3 and 7 use BASE2 (25Mhz) */
+ if ((pll_type == PLL_TYPE3) ||
+ (pll_type == PLL_TYPE7)) {
+ clock = CC_CLOCK_BASE2 * n1 * n2;
+ } else
+ clock = CC_CLOCK_BASE1 * n1 * n2;
+
+ if (clock == 0)
+ return 0;
+
+ m1 = m & CC_M1_MASK;
+ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
+ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
+ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
+
+ if ((pll_type == PLL_TYPE1) ||
+ (pll_type == PLL_TYPE3) ||
+ (pll_type == PLL_TYPE4) ||
+ (pll_type == PLL_TYPE7)) {
+ m1 = factor6(m1);
+ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
+ m2 += CC_F5_BIAS;
+ else
+ m2 = factor6(m2);
+ m3 = factor6(m3);
+
+ switch (mc) {
+ case CC_MC_BYPASS: return (clock);
+ case CC_MC_M1: return divide_clock(clock, m1);
+ case CC_MC_M1M2: return divide_clock(clock, m1 * m2);
+ case CC_MC_M1M2M3: return divide_clock(clock, m1 * m2 * m3);
+ case CC_MC_M1M3: return divide_clock(clock, m1 * m3);
+ default: return (0);
+ }
+ } else {
+ ASSERT(pll_type == PLL_TYPE2);
+
+ m1 += CC_T2_BIAS;
+ m2 += CC_T2M2_BIAS;
+ m3 += CC_T2_BIAS;
+ ASSERT((m1 >= 2) && (m1 <= 7));
+ ASSERT((m2 >= 3) && (m2 <= 10));
+ ASSERT((m3 >= 2) && (m3 <= 7));
+
+ if ((mc & CC_T2MC_M1BYP) == 0)
+ clock /= m1;
+ if ((mc & CC_T2MC_M2BYP) == 0)
+ clock /= m2;
+ if ((mc & CC_T2MC_M3BYP) == 0)
+ clock /= m3;
+
+ return (clock);
+ }
+}
+
+/**
+ * Some chips could have multiple host interfaces, however only one will be active.
+ * For a given chip. Depending pkgopt and cc_chipst return the active host interface.
+ */
+uint
+si_chip_hostif(si_t *sih)
+{
+ uint hosti = 0;
+
+ switch (CHIPID(sih->chip)) {
+
+ case BCM43602_CHIP_ID:
+ hosti = CHIP_HOSTIF_PCIEMODE;
+ break;
+
+ case BCM4360_CHIP_ID:
+ /* chippkg bit-0 == 0 is PCIE only pkgs
+ * chippkg bit-0 == 1 has both PCIE and USB cores enabled
+ */
+ if ((sih->chippkg & 0x1) && (sih->chipst & CST4360_MODE_USB))
+ hosti = CHIP_HOSTIF_USBMODE;
+ else
+ hosti = CHIP_HOSTIF_PCIEMODE;
+
+ break;
+
+ case BCM4335_CHIP_ID:
+ /* TBD: like in 4360, do we need to check pkg? */
+ if (CST4335_CHIPMODE_USB20D(sih->chipst))
+ hosti = CHIP_HOSTIF_USBMODE;
+ else if (CST4335_CHIPMODE_SDIOD(sih->chipst))
+ hosti = CHIP_HOSTIF_SDIOMODE;
+ else
+ hosti = CHIP_HOSTIF_PCIEMODE;
+ break;
+
+ case BCM4345_CHIP_ID:
+ if (CST4345_CHIPMODE_USB20D(sih->chipst) || CST4345_CHIPMODE_HSIC(sih->chipst))
+ hosti = CHIP_HOSTIF_USBMODE;
+ else if (CST4345_CHIPMODE_SDIOD(sih->chipst))
+ hosti = CHIP_HOSTIF_SDIOMODE;
+ else if (CST4345_CHIPMODE_PCIE(sih->chipst))
+ hosti = CHIP_HOSTIF_PCIEMODE;
+ break;
+
+
+ case BCM4350_CHIP_ID:
+ case BCM4354_CHIP_ID:
+ case BCM4356_CHIP_ID:
+ case BCM43556_CHIP_ID:
+ case BCM43558_CHIP_ID:
+ case BCM43566_CHIP_ID:
+ case BCM43568_CHIP_ID:
+ case BCM43569_CHIP_ID:
+ if (CST4350_CHIPMODE_USB20D(sih->chipst) ||
+ CST4350_CHIPMODE_HSIC20D(sih->chipst) ||
+ CST4350_CHIPMODE_USB30D(sih->chipst) ||
+ CST4350_CHIPMODE_USB30D_WL(sih->chipst) ||
+ CST4350_CHIPMODE_HSIC30D(sih->chipst))
+ hosti = CHIP_HOSTIF_USBMODE;
+ else if (CST4350_CHIPMODE_SDIOD(sih->chipst))
+ hosti = CHIP_HOSTIF_SDIOMODE;
+ else if (CST4350_CHIPMODE_PCIE(sih->chipst))
+ hosti = CHIP_HOSTIF_PCIEMODE;
+ break;
+
+ default:
+ break;
+ }
+
+ return hosti;
+}
+
+
+/** set chip watchdog reset timer to fire in 'ticks' */
+void
+si_watchdog(si_t *sih, uint ticks)
+{
+ uint nb, maxt;
+
+ if (PMUCTL_ENAB(sih)) {
+
+#if !defined(_CFEZ_) || defined(CFG_WL)
+ if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
+ (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
+ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
+ si_setcore(sih, USB20D_CORE_ID, 0);
+ si_core_disable(sih, 1);
+ si_setcore(sih, CC_CORE_ID, 0);
+ }
+#endif
+
+ nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
+ /* The mips compiler uses the sllv instruction,
+ * so we specially handle the 32-bit case.
+ */
+ if (nb == 32)
+ maxt = 0xffffffff;
+ else
+ maxt = ((1 << nb) - 1);
+
+ if (ticks == 1)
+ ticks = 2;
+ else if (ticks > maxt)
+ ticks = maxt;
+
+ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
+ } else {
+ maxt = (1 << 28) - 1;
+ if (ticks > maxt)
+ ticks = maxt;
+
+ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
+ }
+}
+
+/** trigger watchdog reset after ms milliseconds */
+void
+si_watchdog_ms(si_t *sih, uint32 ms)
+{
+ si_watchdog(sih, wd_msticks * ms);
+}
+
+uint32 si_watchdog_msticks(void)
+{
+ return wd_msticks;
+}
+
+bool
+si_taclear(si_t *sih, bool details)
+{
+ return FALSE;
+}
+
+
+
+/** return the slow clock source - LPO, XTAL, or PCI */
+static uint
+si_slowclk_src(si_info_t *sii)
+{
+ chipcregs_t *cc;
+
+ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
+
+ if (sii->pub.ccrev < 6) {
+ if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
+ (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
+ PCI_CFG_GPIO_SCS))
+ return (SCC_SS_PCI);
+ else
+ return (SCC_SS_XTAL);
+ } else if (sii->pub.ccrev < 10) {
+ cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
+ ASSERT(cc);
+ return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
+ } else /* Insta-clock */
+ return (SCC_SS_XTAL);
+}
+
+/** return the ILP (slowclock) min or max frequency */
+static uint
+si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
+{
+ uint32 slowclk;
+ uint div;
+
+ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
+
+ /* shouldn't be here unless we've established the chip has dynamic clk control */
+ ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
+
+ slowclk = si_slowclk_src(sii);
+ if (sii->pub.ccrev < 6) {
+ if (slowclk == SCC_SS_PCI)
+ return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
+ else
+ return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
+ } else if (sii->pub.ccrev < 10) {
+ div = 4 *
+ (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
+ if (slowclk == SCC_SS_LPO)
+ return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
+ else if (slowclk == SCC_SS_XTAL)
+ return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
+ else if (slowclk == SCC_SS_PCI)
+ return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
+ else
+ ASSERT(0);
+ } else {
+ /* Chipc rev 10 is InstaClock */
+ div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
+ div = 4 * (div + 1);
+ return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
+ }
+ return (0);
+}
+
+static void
+si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
+{
+ chipcregs_t *cc = (chipcregs_t *)chipcregs;
+ uint slowmaxfreq, pll_delay, slowclk;
+ uint pll_on_delay, fref_sel_delay;
+
+ pll_delay = PLL_DELAY;
+
+ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
+ * since the xtal will also be powered down by dynamic clk control logic.
+ */
+
+ slowclk = si_slowclk_src(sii);
+ if (slowclk != SCC_SS_XTAL)
+ pll_delay += XTAL_ON_DELAY;
+
+ /* Starting with 4318 it is ILP that is used for the delays */
+ slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
+
+ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
+ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
+
+ W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
+ W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
+}
+
+/** initialize power control delay registers */
+void
+si_clkctl_init(si_t *sih)
+{
+ si_info_t *sii;
+ uint origidx = 0;
+ chipcregs_t *cc;
+ bool fast;
+
+ if (!CCCTL_ENAB(sih))
+ return;
+
+ sii = SI_INFO(sih);
+ fast = SI_FAST(sii);
+ if (!fast) {
+ origidx = sii->curidx;
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
+ return;
+ } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
+ return;
+ ASSERT(cc != NULL);
+
+ /* set all Instaclk chip ILP to 1 MHz */
+ if (sih->ccrev >= 10)
+ SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
+ (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
+
+ si_clkctl_setdelay(sii, (void *)(uintptr)cc);
+
+ OSL_DELAY(20000);
+
+ if (!fast)
+ si_setcoreidx(sih, origidx);
+}
+
+
+/** change logical "focus" to the gpio core for optimized access */
+void *
+si_gpiosetcore(si_t *sih)
+{
+ return (si_setcoreidx(sih, SI_CC_IDX));
+}
+
+/**
+ * mask & set gpiocontrol bits.
+ * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
+ * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
+ * to some chip-specific purpose.
+ */
+uint32
+si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
+{
+ uint regoff;
+
+ regoff = 0;
+
+ /* gpios could be shared on router platforms
+ * ignore reservation if it's high priority (e.g., test apps)
+ */
+ if ((priority != GPIO_HI_PRIORITY) &&
+ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
+ mask = priority ? (si_gpioreservation & mask) :
+ ((si_gpioreservation | mask) & ~(si_gpioreservation));
+ val &= mask;
+ }
+
+ regoff = OFFSETOF(chipcregs_t, gpiocontrol);
+ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
+}
+
+/** mask&set gpio output enable bits */
+uint32
+si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
+{
+ uint regoff;
+
+ regoff = 0;
+
+ /* gpios could be shared on router platforms
+ * ignore reservation if it's high priority (e.g., test apps)
+ */
+ if ((priority != GPIO_HI_PRIORITY) &&
+ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
+ mask = priority ? (si_gpioreservation & mask) :
+ ((si_gpioreservation | mask) & ~(si_gpioreservation));
+ val &= mask;
+ }
+
+ regoff = OFFSETOF(chipcregs_t, gpioouten);
+ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
+}
+
+/** mask&set gpio output bits */
+uint32
+si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
+{
+ uint regoff;
+
+ regoff = 0;
+
+ /* gpios could be shared on router platforms
+ * ignore reservation if it's high priority (e.g., test apps)
+ */
+ if ((priority != GPIO_HI_PRIORITY) &&
+ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
+ mask = priority ? (si_gpioreservation & mask) :
+ ((si_gpioreservation | mask) & ~(si_gpioreservation));
+ val &= mask;
+ }
+
+ regoff = OFFSETOF(chipcregs_t, gpioout);
+ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
+}
+
+/** reserve one gpio */
+uint32
+si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
+{
+ /* only cores on SI_BUS share GPIO's and only applcation users need to
+ * reserve/release GPIO
+ */
+ if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
+ ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
+ return 0xffffffff;
+ }
+ /* make sure only one bit is set */
+ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
+ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
+ return 0xffffffff;
+ }
+
+ /* already reserved */
+ if (si_gpioreservation & gpio_bitmask)
+ return 0xffffffff;
+ /* set reservation */
+ si_gpioreservation |= gpio_bitmask;
+
+ return si_gpioreservation;
+}
+
+/**
+ * release one gpio.
+ *
+ * releasing the gpio doesn't change the current value on the GPIO last write value
+ * persists till someone overwrites it.
+ */
+uint32
+si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
+{
+ /* only cores on SI_BUS share GPIO's and only applcation users need to
+ * reserve/release GPIO
+ */
+ if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
+ ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
+ return 0xffffffff;
+ }
+ /* make sure only one bit is set */
+ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
+ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
+ return 0xffffffff;
+ }
+
+ /* already released */
+ if (!(si_gpioreservation & gpio_bitmask))
+ return 0xffffffff;
+
+ /* clear reservation */
+ si_gpioreservation &= ~gpio_bitmask;
+
+ return si_gpioreservation;
+}
+
+/* return the current gpioin register value */
+uint32
+si_gpioin(si_t *sih)
+{
+ uint regoff;
+
+ regoff = OFFSETOF(chipcregs_t, gpioin);
+ return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
+}
+
+/* mask&set gpio interrupt polarity bits */
+uint32
+si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
+{
+ uint regoff;
+
+ /* gpios could be shared on router platforms */
+ if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
+ mask = priority ? (si_gpioreservation & mask) :
+ ((si_gpioreservation | mask) & ~(si_gpioreservation));
+ val &= mask;
+ }
+
+ regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
+ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
+}
+
+/* mask&set gpio interrupt mask bits */
+uint32
+si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
+{
+ uint regoff;
+
+ /* gpios could be shared on router platforms */
+ if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
+ mask = priority ? (si_gpioreservation & mask) :
+ ((si_gpioreservation | mask) & ~(si_gpioreservation));
+ val &= mask;
+ }
+
+ regoff = OFFSETOF(chipcregs_t, gpiointmask);
+ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
+}
+
+/* assign the gpio to an led */
+uint32
+si_gpioled(si_t *sih, uint32 mask, uint32 val)
+{
+ if (sih->ccrev < 16)
+ return 0xffffffff;
+
+ /* gpio led powersave reg */
+ return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
+}
+
+/* mask&set gpio timer val */
+uint32
+si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
+{
+ if (sih->ccrev < 16)
+ return 0xffffffff;
+
+ return (si_corereg(sih, SI_CC_IDX,
+ OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
+}
+
+uint32
+si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
+{
+ uint offs;
+
+ if (sih->ccrev < 20)
+ return 0xffffffff;
+
+ offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
+ return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
+}
+
+uint32
+si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
+{
+ uint offs;
+
+ if (sih->ccrev < 11)
+ return 0xffffffff;
+
+ if (regtype == GPIO_REGEVT)
+ offs = OFFSETOF(chipcregs_t, gpioevent);
+ else if (regtype == GPIO_REGEVT_INTMSK)
+ offs = OFFSETOF(chipcregs_t, gpioeventintmask);
+ else if (regtype == GPIO_REGEVT_INTPOL)
+ offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
+ else
+ return 0xffffffff;
+
+ return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
+}
+
+void *
+si_gpio_handler_register(si_t *sih, uint32 event,
+ bool level, gpio_handler_t cb, void *arg)
+{
+ si_info_t *sii = SI_INFO(sih);
+ gpioh_item_t *gi;
+
+ ASSERT(event);
+ ASSERT(cb != NULL);
+
+ if (sih->ccrev < 11)
+ return NULL;
+
+ if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
+ return NULL;
+
+ bzero(gi, sizeof(gpioh_item_t));
+ gi->event = event;
+ gi->handler = cb;
+ gi->arg = arg;
+ gi->level = level;
+
+ gi->next = sii->gpioh_head;
+ sii->gpioh_head = gi;
+
+ return (void *)(gi);
+}
+
+void
+si_gpio_handler_unregister(si_t *sih, void *gpioh)
+{
+ si_info_t *sii = SI_INFO(sih);
+ gpioh_item_t *p, *n;
+
+ if (sih->ccrev < 11)
+ return;
+
+ ASSERT(sii->gpioh_head != NULL);
+ if ((void*)sii->gpioh_head == gpioh) {
+ sii->gpioh_head = sii->gpioh_head->next;
+ MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
+ return;
+ } else {
+ p = sii->gpioh_head;
+ n = p->next;
+ while (n) {
+ if ((void*)n == gpioh) {
+ p->next = n->next;
+ MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
+ return;
+ }
+ p = n;
+ n = n->next;
+ }
+ }
+
+ ASSERT(0); /* Not found in list */
+}
+
+void
+si_gpio_handler_process(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ gpioh_item_t *h;
+ uint32 level = si_gpioin(sih);
+ uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
+ uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
+ uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
+
+ for (h = sii->gpioh_head; h != NULL; h = h->next) {
+ if (h->handler) {
+ uint32 status = (h->level ? level : edge) & h->event;
+ uint32 polarity = (h->level ? levelp : edgep) & h->event;
+
+ /* polarity bitval is opposite of status bitval */
+ if (status ^ polarity)
+ h->handler(status, h->arg);
+ }
+ }
+
+ si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
+}
+
+uint32
+si_gpio_int_enable(si_t *sih, bool enable)
+{
+ uint offs;
+
+ if (sih->ccrev < 11)
+ return 0xffffffff;
+
+ offs = OFFSETOF(chipcregs_t, intmask);
+ return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
+}
+
+
+/** Return the size of the specified SOCRAM bank */
+static uint
+socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
+{
+ uint banksize, bankinfo;
+ uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
+
+ ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
+
+ W_REG(sii->osh, &regs->bankidx, bankidx);
+ bankinfo = R_REG(sii->osh, &regs->bankinfo);
+ banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
+ return banksize;
+}
+
+void si_socram_set_bankpda(si_t *sih, uint32 bankidx, uint32 bankpda)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+ sbsocramregs_t *regs;
+ bool wasup;
+ uint corerev;
+
+ /* Block ints and save current core */
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ /* Switch to SOCRAM core */
+ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
+ goto done;
+
+ if (!(wasup = si_iscoreup(sih)))
+ si_core_reset(sih, 0, 0);
+
+ corerev = si_corerev(sih);
+ if (corerev >= 16) {
+ W_REG(sii->osh, &regs->bankidx, bankidx);
+ W_REG(sii->osh, &regs->bankpda, bankpda);
+ }
+
+ /* Return to previous state and core */
+ if (!wasup)
+ si_core_disable(sih, 0);
+ si_setcoreidx(sih, origidx);
+
+done:
+ INTR_RESTORE(sii, intr_val);
+}
+
+void
+si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+ sbsocramregs_t *regs;
+ bool wasup;
+ uint corerev;
+
+ /* Block ints and save current core */
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ if (!set)
+ *enable = *protect = *remap = 0;
+
+ /* Switch to SOCRAM core */
+ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
+ goto done;
+
+ /* Get info for determining size */
+ if (!(wasup = si_iscoreup(sih)))
+ si_core_reset(sih, 0, 0);
+
+ corerev = si_corerev(sih);
+ if (corerev >= 10) {
+ uint32 extcinfo;
+ uint8 nb;
+ uint8 i;
+ uint32 bankidx, bankinfo;
+
+ extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
+ nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
+ for (i = 0; i < nb; i++) {
+ bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
+ W_REG(sii->osh, &regs->bankidx, bankidx);
+ bankinfo = R_REG(sii->osh, &regs->bankinfo);
+ if (set) {
+ bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
+ bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
+ bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK;
+ if (*enable) {
+ bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
+ if (*protect)
+ bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
+ if ((corerev >= 16) && *remap)
+ bankinfo |=
+ (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT);
+ }
+ W_REG(sii->osh, &regs->bankinfo, bankinfo);
+ }
+ else if (i == 0) {
+ if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
+ *enable = 1;
+ if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
+ *protect = 1;
+ if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK)
+ *remap = 1;
+ }
+ }
+ }
+ }
+
+ /* Return to previous state and core */
+ if (!wasup)
+ si_core_disable(sih, 0);
+ si_setcoreidx(sih, origidx);
+
+done:
+ INTR_RESTORE(sii, intr_val);
+}
+
+bool
+si_socdevram_remap_isenb(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+ sbsocramregs_t *regs;
+ bool wasup, remap = FALSE;
+ uint corerev;
+ uint32 extcinfo;
+ uint8 nb;
+ uint8 i;
+ uint32 bankidx, bankinfo;
+
+ /* Block ints and save current core */
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ /* Switch to SOCRAM core */
+ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
+ goto done;
+
+ /* Get info for determining size */
+ if (!(wasup = si_iscoreup(sih)))
+ si_core_reset(sih, 0, 0);
+
+ corerev = si_corerev(sih);
+ if (corerev >= 16) {
+ extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
+ nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
+ for (i = 0; i < nb; i++) {
+ bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
+ W_REG(sii->osh, &regs->bankidx, bankidx);
+ bankinfo = R_REG(sii->osh, &regs->bankinfo);
+ if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
+ remap = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* Return to previous state and core */
+ if (!wasup)
+ si_core_disable(sih, 0);
+ si_setcoreidx(sih, origidx);
+
+done:
+ INTR_RESTORE(sii, intr_val);
+ return remap;
+}
+
+bool
+si_socdevram_pkg(si_t *sih)
+{
+ if (si_socdevram_size(sih) > 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+uint32
+si_socdevram_size(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+ uint32 memsize = 0;
+ sbsocramregs_t *regs;
+ bool wasup;
+ uint corerev;
+
+ /* Block ints and save current core */
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ /* Switch to SOCRAM core */
+ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
+ goto done;
+
+ /* Get info for determining size */
+ if (!(wasup = si_iscoreup(sih)))
+ si_core_reset(sih, 0, 0);
+
+ corerev = si_corerev(sih);
+ if (corerev >= 10) {
+ uint32 extcinfo;
+ uint8 nb;
+ uint8 i;
+
+ extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
+ nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
+ for (i = 0; i < nb; i++)
+ memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
+ }
+
+ /* Return to previous state and core */
+ if (!wasup)
+ si_core_disable(sih, 0);
+ si_setcoreidx(sih, origidx);
+
+done:
+ INTR_RESTORE(sii, intr_val);
+
+ return memsize;
+}
+
+uint32
+si_socdevram_remap_size(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+ uint32 memsize = 0, banksz;
+ sbsocramregs_t *regs;
+ bool wasup;
+ uint corerev;
+ uint32 extcinfo;
+ uint8 nb;
+ uint8 i;
+ uint32 bankidx, bankinfo;
+
+ /* Block ints and save current core */
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ /* Switch to SOCRAM core */
+ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
+ goto done;
+
+ /* Get info for determining size */
+ if (!(wasup = si_iscoreup(sih)))
+ si_core_reset(sih, 0, 0);
+
+ corerev = si_corerev(sih);
+ if (corerev >= 16) {
+ extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
+ nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
+
+ /*
+ * FIX: A0 Issue: Max addressable is 512KB, instead 640KB
+ * Only four banks are accessible to ARM
+ */
+ if ((corerev == 16) && (nb == 5))
+ nb = 4;
+
+ for (i = 0; i < nb; i++) {
+ bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
+ W_REG(sii->osh, &regs->bankidx, bankidx);
+ bankinfo = R_REG(sii->osh, &regs->bankinfo);
+ if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
+ banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
+ memsize += banksz;
+ } else {
+ /* Account only consecutive banks for now */
+ break;
+ }
+ }
+ }
+
+ /* Return to previous state and core */
+ if (!wasup)
+ si_core_disable(sih, 0);
+ si_setcoreidx(sih, origidx);
+
+done:
+ INTR_RESTORE(sii, intr_val);
+
+ return memsize;
+}
+
+/** Return the RAM size of the SOCRAM core */
+uint32
+si_socram_size(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+
+ sbsocramregs_t *regs;
+ bool wasup;
+ uint corerev;
+ uint32 coreinfo;
+ uint memsize = 0;
+
+ /* Block ints and save current core */
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ /* Switch to SOCRAM core */
+ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
+ goto done;
+
+ /* Get info for determining size */
+ if (!(wasup = si_iscoreup(sih)))
+ si_core_reset(sih, 0, 0);
+ corerev = si_corerev(sih);
+ coreinfo = R_REG(sii->osh, &regs->coreinfo);
+
+ /* Calculate size from coreinfo based on rev */
+ if (corerev == 0)
+ memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
+ else if (corerev < 3) {
+ memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
+ memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+ } else if ((corerev <= 7) || (corerev == 12)) {
+ uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+ uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
+ uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
+ if (lss != 0)
+ nb --;
+ memsize = nb * (1 << (bsz + SR_BSZ_BASE));
+ if (lss != 0)
+ memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
+ } else {
+ uint8 i;
+ uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+ for (i = 0; i < nb; i++)
+ memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
+ }
+
+ /* Return to previous state and core */
+ if (!wasup)
+ si_core_disable(sih, 0);
+ si_setcoreidx(sih, origidx);
+
+done:
+ INTR_RESTORE(sii, intr_val);
+
+ return memsize;
+}
+
+
+/** Return the TCM-RAM size of the ARMCR4 core. */
+uint32
+si_tcm_size(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+ uint8 *regs;
+ bool wasup;
+ uint32 corecap;
+ uint memsize = 0;
+ uint32 nab = 0;
+ uint32 nbb = 0;
+ uint32 totb = 0;
+ uint32 bxinfo = 0;
+ uint32 idx = 0;
+ uint32 *arm_cap_reg;
+ uint32 *arm_bidx;
+ uint32 *arm_binfo;
+
+ /* Block ints and save current core */
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ /* Switch to CR4 core */
+ if (!(regs = si_setcore(sih, ARMCR4_CORE_ID, 0)))
+ goto done;
+
+ /* Get info for determining size. If in reset, come out of reset,
+ * but remain in halt
+ */
+ if (!(wasup = si_iscoreup(sih)))
+ si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT);
+
+ arm_cap_reg = (uint32 *)(regs + SI_CR4_CAP);
+ corecap = R_REG(sii->osh, arm_cap_reg);
+
+ nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
+ nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
+ totb = nab + nbb;
+
+ arm_bidx = (uint32 *)(regs + SI_CR4_BANKIDX);
+ arm_binfo = (uint32 *)(regs + SI_CR4_BANKINFO);
+ for (idx = 0; idx < totb; idx++) {
+ W_REG(sii->osh, arm_bidx, idx);
+
+ bxinfo = R_REG(sii->osh, arm_binfo);
+ memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
+ }
+
+ /* Return to previous state and core */
+ if (!wasup)
+ si_core_disable(sih, 0);
+ si_setcoreidx(sih, origidx);
+
+done:
+ INTR_RESTORE(sii, intr_val);
+
+ return memsize;
+}
+
+bool
+si_has_flops(si_t *sih)
+{
+ uint origidx, cr4_rev;
+
+ /* Find out CR4 core revision */
+ origidx = si_coreidx(sih);
+ if (si_setcore(sih, ARMCR4_CORE_ID, 0)) {
+ cr4_rev = si_corerev(sih);
+ si_setcoreidx(sih, origidx);
+
+ if (cr4_rev == 1 || cr4_rev >= 3)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+uint32
+si_socram_srmem_size(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+
+ sbsocramregs_t *regs;
+ bool wasup;
+ uint corerev;
+ uint32 coreinfo;
+ uint memsize = 0;
+
+ if ((CHIPID(sih->chip) == BCM4334_CHIP_ID) && (CHIPREV(sih->chiprev) < 2)) {
+ return (32 * 1024);
+ }
+
+ if (CHIPID(sih->chip) == BCM43430_CHIP_ID) {
+ return (64 * 1024);
+ }
+
+ /* Block ints and save current core */
+ INTR_OFF(sii, intr_val);
+ origidx = si_coreidx(sih);
+
+ /* Switch to SOCRAM core */
+ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
+ goto done;
+
+ /* Get info for determining size */
+ if (!(wasup = si_iscoreup(sih)))
+ si_core_reset(sih, 0, 0);
+ corerev = si_corerev(sih);
+ coreinfo = R_REG(sii->osh, &regs->coreinfo);
+
+ /* Calculate size from coreinfo based on rev */
+ if (corerev >= 16) {
+ uint8 i;
+ uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+ for (i = 0; i < nb; i++) {
+ W_REG(sii->osh, &regs->bankidx, i);
+ if (R_REG(sii->osh, &regs->bankinfo) & SOCRAM_BANKINFO_RETNTRAM_MASK)
+ memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
+ }
+ }
+
+ /* Return to previous state and core */
+ if (!wasup)
+ si_core_disable(sih, 0);
+ si_setcoreidx(sih, origidx);
+
+done:
+ INTR_RESTORE(sii, intr_val);
+
+ return memsize;
+}
+
+
+#if !defined(_CFEZ_) || defined(CFG_WL)
+void
+si_btcgpiowar(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint origidx;
+ uint intr_val = 0;
+ chipcregs_t *cc;
+
+ /* Make sure that there is ChipCommon core present &&
+ * UART_TX is strapped to 1
+ */
+ if (!(sih->cccaps & CC_CAP_UARTGPIO))
+ return;
+
+ /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
+ INTR_OFF(sii, intr_val);
+
+ origidx = si_coreidx(sih);
+
+ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
+ ASSERT(cc != NULL);
+
+ W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
+
+ /* restore the original index */
+ si_setcoreidx(sih, origidx);
+
+ INTR_RESTORE(sii, intr_val);
+}
+
+void
+si_chipcontrl_btshd0_4331(si_t *sih, bool on)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ chipcregs_t *cc;
+ uint origidx;
+ uint32 val;
+ uint intr_val = 0;
+
+ INTR_OFF(sii, intr_val);
+
+ origidx = si_coreidx(sih);
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ val = R_REG(sii->osh, &cc->chipcontrol);
+
+ /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */
+ if (on) {
+ /* Enable bt_shd0 on gpio4: */
+ val |= (CCTRL4331_BT_SHD0_ON_GPIO4);
+ W_REG(sii->osh, &cc->chipcontrol, val);
+ } else {
+ val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4);
+ W_REG(sii->osh, &cc->chipcontrol, val);
+ }
+
+ /* restore the original index */
+ si_setcoreidx(sih, origidx);
+
+ INTR_RESTORE(sii, intr_val);
+}
+
+void
+si_chipcontrl_restore(si_t *sih, uint32 val)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ W_REG(sii->osh, &cc->chipcontrol, val);
+ si_setcoreidx(sih, origidx);
+}
+
+uint32
+si_chipcontrl_read(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+ uint32 val;
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return -1;
+ }
+
+ val = R_REG(sii->osh, &cc->chipcontrol);
+ si_setcoreidx(sih, origidx);
+ return val;
+}
+
+void
+si_chipcontrl_epa4331(si_t *sih, bool on)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+ uint32 val;
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ val = R_REG(sii->osh, &cc->chipcontrol);
+
+ if (on) {
+ if (sih->chippkg == 9 || sih->chippkg == 0xb) {
+ val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
+ /* Ext PA Controls for 4331 12x9 Package */
+ W_REG(sii->osh, &cc->chipcontrol, val);
+ } else {
+ /* Ext PA Controls for 4331 12x12 Package */
+ if (sih->chiprev > 0) {
+ W_REG(sii->osh, &cc->chipcontrol, val |
+ (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
+ } else {
+ W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
+ }
+ }
+ } else {
+ val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
+ W_REG(sii->osh, &cc->chipcontrol, val);
+ }
+
+ si_setcoreidx(sih, origidx);
+}
+
+/** switch muxed pins, on: SROM, off: FEMCTRL. Called for a family of ac chips, not just 4360. */
+void
+si_chipcontrl_srom4360(si_t *sih, bool on)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+ uint32 val;
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ val = R_REG(sii->osh, &cc->chipcontrol);
+
+ if (on) {
+ val &= ~(CCTRL4360_SECI_MODE |
+ CCTRL4360_BTSWCTRL_MODE |
+ CCTRL4360_EXTRA_FEMCTRL_MODE |
+ CCTRL4360_BT_LGCY_MODE |
+ CCTRL4360_CORE2FEMCTRL4_ON);
+
+ W_REG(sii->osh, &cc->chipcontrol, val);
+ } else {
+ }
+
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
+{
+ si_info_t *sii;
+ chipcregs_t *cc;
+ uint origidx;
+ uint32 val;
+ bool sel_chip;
+
+ sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
+ (CHIPID(sih->chip) == BCM43431_CHIP_ID);
+ sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
+
+ if (!sel_chip)
+ return;
+
+ sii = SI_INFO(sih);
+ origidx = si_coreidx(sih);
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ val = R_REG(sii->osh, &cc->chipcontrol);
+
+ if (enter_wowl) {
+ val |= CCTRL4331_EXTPA_EN;
+ W_REG(sii->osh, &cc->chipcontrol, val);
+ } else {
+ val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
+ W_REG(sii->osh, &cc->chipcontrol, val);
+ }
+ si_setcoreidx(sih, origidx);
+}
+#endif
+
+uint
+si_pll_reset(si_t *sih)
+{
+ uint err = 0;
+
+ return (err);
+}
+
+/** Enable BT-COEX & Ex-PA for 4313 */
+void
+si_epa_4313war(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ /* EPA Fix */
+ W_REG(sii->osh, &cc->gpiocontrol,
+ R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
+
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
+{
+}
+
+/** Re-enable synth_pwrsw resource in min_res_mask for 4313 */
+void
+si_pmu_synth_pwrsw_4313_war(si_t *sih)
+{
+}
+
+/** WL/BT control for 4313 btcombo boards >= P250 */
+void
+si_btcombo_p250_4313_war(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ W_REG(sii->osh, &cc->gpiocontrol,
+ R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
+
+ W_REG(sii->osh, &cc->gpioouten,
+ R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
+
+ si_setcoreidx(sih, origidx);
+}
+void
+si_btc_enable_chipcontrol(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ /* BT fix */
+ W_REG(sii->osh, &cc->chipcontrol,
+ R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
+
+ si_setcoreidx(sih, origidx);
+}
+void
+si_btcombo_43228_war(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+
+ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
+ SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
+ return;
+ }
+
+ W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK);
+ W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK);
+
+ si_setcoreidx(sih, origidx);
+}
+
+/** check if the device is removed */
+bool
+si_deviceremoved(si_t *sih)
+{
+ uint32 w;
+
+ switch (BUSTYPE(sih->bustype)) {
+ case PCI_BUS:
+ ASSERT(SI_INFO(sih)->osh != NULL);
+ w = OSL_PCI_READ_CONFIG(SI_INFO(sih)->osh, PCI_CFG_VID, sizeof(uint32));
+ if ((w & 0xFFFF) != VENDOR_BROADCOM)
+ return TRUE;
+ break;
+ }
+ return FALSE;
+}
+
+bool
+si_is_sprom_available(si_t *sih)
+{
+ if (sih->ccrev >= 31) {
+ si_info_t *sii;
+ uint origidx;
+ chipcregs_t *cc;
+ uint32 sromctrl;
+
+ if ((sih->cccaps & CC_CAP_SROM) == 0)
+ return FALSE;
+
+ sii = SI_INFO(sih);
+ origidx = sii->curidx;
+ cc = si_setcoreidx(sih, SI_CC_IDX);
+ ASSERT(cc);
+ sromctrl = R_REG(sii->osh, &cc->sromcontrol);
+ si_setcoreidx(sih, origidx);
+ return (sromctrl & SRC_PRESENT);
+ }
+
+ switch (CHIPID(sih->chip)) {
+ case BCM4312_CHIP_ID:
+ return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
+ case BCM4325_CHIP_ID:
+ return (sih->chipst & CST4325_SPROM_SEL) != 0;
+ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
+ case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
+ case BCM4342_CHIP_ID: {
+ uint32 spromotp;
+ spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
+ CST4322_SPROM_OTP_SEL_SHIFT;
+ return (spromotp & CST4322_SPROM_PRESENT) != 0;
+ }
+ case BCM4329_CHIP_ID:
+ return (sih->chipst & CST4329_SPROM_SEL) != 0;
+ case BCM4315_CHIP_ID:
+ return (sih->chipst & CST4315_SPROM_SEL) != 0;
+ case BCM4319_CHIP_ID:
+ return (sih->chipst & CST4319_SPROM_SEL) != 0;
+ case BCM4336_CHIP_ID:
+ case BCM43362_CHIP_ID:
+ return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
+ case BCM4330_CHIP_ID:
+ return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
+ case BCM4313_CHIP_ID:
+ return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
+ case BCM4331_CHIP_ID:
+ case BCM43431_CHIP_ID:
+ return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
+ case BCM43239_CHIP_ID:
+ return ((sih->chipst & CST43239_SPROM_MASK) &&
+ !(sih->chipst & CST43239_SFLASH_MASK));
+ case BCM4324_CHIP_ID:
+ case BCM43242_CHIP_ID:
+ return ((sih->chipst & CST4324_SPROM_MASK) &&
+ !(sih->chipst & CST4324_SFLASH_MASK));
+ case BCM4335_CHIP_ID:
+ case BCM4345_CHIP_ID:
+ return ((sih->chipst & CST4335_SPROM_MASK) &&
+ !(sih->chipst & CST4335_SFLASH_MASK));
+ case BCM4350_CHIP_ID:
+ case BCM4354_CHIP_ID:
+ case BCM4356_CHIP_ID:
+ case BCM43556_CHIP_ID:
+ case BCM43558_CHIP_ID:
+ case BCM43566_CHIP_ID:
+ case BCM43568_CHIP_ID:
+ case BCM43569_CHIP_ID:
+ return (sih->chipst & CST4350_SPROM_PRESENT) != 0;
+ case BCM43602_CHIP_ID:
+ return (sih->chipst & CST43602_SPROM_PRESENT) != 0;
+ case BCM43131_CHIP_ID:
+ case BCM43217_CHIP_ID:
+ case BCM43227_CHIP_ID:
+ case BCM43228_CHIP_ID:
+ case BCM43428_CHIP_ID:
+ return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
+ default:
+ return TRUE;
+ }
+}
+
+
+uint32 si_get_sromctl(si_t *sih)
+{
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+ uint32 sromctl;
+ osl_t *osh = si_osh(sih);
+
+ cc = si_setcoreidx(sih, SI_CC_IDX);
+ ASSERT((uintptr)cc);
+
+ sromctl = R_REG(osh, &cc->sromcontrol);
+
+ /* return to the original core */
+ si_setcoreidx(sih, origidx);
+ return sromctl;
+}
+
+int si_set_sromctl(si_t *sih, uint32 value)
+{
+ chipcregs_t *cc;
+ uint origidx = si_coreidx(sih);
+ osl_t *osh = si_osh(sih);
+
+ cc = si_setcoreidx(sih, SI_CC_IDX);
+ ASSERT((uintptr)cc);
+
+ /* get chipcommon rev */
+ if (si_corerev(sih) < 32)
+ return BCME_UNSUPPORTED;
+
+ W_REG(osh, &cc->sromcontrol, value);
+
+ /* return to the original core */
+ si_setcoreidx(sih, origidx);
+ return BCME_OK;
+
+}
+
+uint
+si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val)
+{
+ uint origidx;
+ uint ret_val;
+
+ origidx = si_coreidx(sih);
+
+ si_setcoreidx(sih, coreidx);
+
+ ret_val = si_wrapperreg(sih, offset, mask, val);
+
+ /* return to the original core */
+ si_setcoreidx(sih, origidx);
+ return ret_val;
+}
+
+
+/* cleanup the hndrte timer from the host when ARM is been halted
+ * without a chance for ARM cleanup its resources
+ * If left not cleanup, Intr from a software timer can still
+ * request HT clk when ARM is halted.
+ */
+uint32
+si_pmu_res_req_timer_clr(si_t *sih)
+{
+ uint32 mask;
+
+ mask = PRRT_REQ_ACTIVE | PRRT_INTEN;
+ if (CHIPID(sih->chip) != BCM4328_CHIP_ID)
+ mask <<= 14;
+ /* clear mask bits */
+ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, res_req_timer), mask, 0);
+ /* readback to ensure write completes */
+ return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, res_req_timer), 0, 0);
+}
+
+/** turn on/off rfldo */
+void
+si_pmu_rfldo(si_t *sih, bool on)
+{
+}
+
+#ifdef SURVIVE_PERST_ENAB
+static uint32
+si_pcie_survive_perst(si_t *sih, uint32 mask, uint32 val)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+
+ if (!PCIE(sii))
+ return (0);
+
+ return pcie_survive_perst(sii->pch, mask, val);
+}
+
+static void
+si_watchdog_reset(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint32 origidx, i;
+
+ origidx = si_coreidx(sih);
+ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
+ /* issue a watchdog reset */
+ W_REG(sii->osh, &cc->pmuwatchdog, 2);
+ /* do busy wait for 20ms */
+ for (i = 0; i < 2000; i++) {
+ OSL_DELAY(10);
+ }
+ si_setcoreidx(sih, origidx);
+}
+#endif /* SURVIVE_PERST_ENAB */
+
+void
+si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 sperst_val)
+{
+#ifdef SURVIVE_PERST_ENAB
+ if (BUSTYPE(sih->bustype) != PCI_BUS)
+ return;
+
+ if ((CHIPID(sih->chip) != BCM4360_CHIP_ID && CHIPID(sih->chip) != BCM4352_CHIP_ID) ||
+ (CHIPREV(sih->chiprev) >= 4))
+ return;
+
+ if (reset) {
+ si_info_t *sii = SI_INFO(sih);
+ uint32 bar0win, bar0win_after;
+
+ /* save the bar0win */
+ bar0win = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
+
+ si_watchdog_reset(sih);
+
+ bar0win_after = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
+ if (bar0win_after != bar0win) {
+ SI_ERROR(("%s: bar0win before %08x, bar0win after %08x\n",
+ __FUNCTION__, bar0win, bar0win_after));
+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), bar0win);
+ }
+ }
+ if (sperst_mask) {
+ /* enable survive perst */
+ si_pcie_survive_perst(sih, sperst_mask, sperst_val);
+ }
+#endif /* SURVIVE_PERST_ENAB */
+}
+
+void
+si_pcie_ltr_war(si_t *sih)
+{
+}
diff --git a/drivers/net/wireless/bcmdhd/siutils_priv.h b/drivers/net/wireless/bcmdhd/siutils_priv.h
new file mode 100644
index 000000000000..0bfb9d98b8f6
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/siutils_priv.h
@@ -0,0 +1,272 @@
+/*
+ * Include file private to the SOC Interconnect support files.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: siutils_priv.h 431423 2013-10-23 16:07:35Z $
+ */
+
+#ifndef _siutils_priv_h_
+#define _siutils_priv_h_
+
+#define SI_ERROR(args)
+
+#define SI_MSG(args)
+
+#ifdef BCMDBG_SI
+#define SI_VMSG(args) printf args
+#else
+#define SI_VMSG(args)
+#endif
+
+#define IS_SIM(chippkg) ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
+
+typedef uint32 (*si_intrsoff_t)(void *intr_arg);
+typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg);
+typedef bool (*si_intrsenabled_t)(void *intr_arg);
+
+typedef struct gpioh_item {
+ void *arg;
+ bool level;
+ gpio_handler_t handler;
+ uint32 event;
+ struct gpioh_item *next;
+} gpioh_item_t;
+
+
+#define SI_GPIO_MAX 16
+
+typedef struct gci_gpio_item {
+ void *arg;
+ uint8 gci_gpio;
+ uint8 status;
+ gci_gpio_handler_t handler;
+ struct gci_gpio_item *next;
+} gci_gpio_item_t;
+
+
+typedef struct si_cores_info {
+ void *regs[SI_MAXCORES]; /* other regs va */
+
+ uint coreid[SI_MAXCORES]; /* id of each core */
+ uint32 coresba[SI_MAXCORES]; /* backplane address of each core */
+ void *regs2[SI_MAXCORES]; /* va of each core second register set (usbh20) */
+ uint32 coresba2[SI_MAXCORES]; /* address of each core second register set (usbh20) */
+ uint32 coresba_size[SI_MAXCORES]; /* backplane address space size */
+ uint32 coresba2_size[SI_MAXCORES]; /* second address space size */
+
+ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */
+ uint32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */
+
+ uint32 cia[SI_MAXCORES]; /* erom cia entry for each core */
+ uint32 cib[SI_MAXCORES]; /* erom cia entry for each core */
+} si_cores_info_t;
+
+/* misc si info needed by some of the routines */
+typedef struct si_info {
+ struct si_pub pub; /* back plane public state (must be first field) */
+
+ void *osh; /* osl os handle */
+ void *sdh; /* bcmsdh handle */
+
+ uint dev_coreid; /* the core provides driver functions */
+ void *intr_arg; /* interrupt callback function arg */
+ si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */
+ si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */
+ si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */
+
+ void *pch; /* PCI/E core handle */
+
+ gpioh_item_t *gpioh_head; /* GPIO event handlers list */
+
+ bool memseg; /* flag to toggle MEM_SEG register */
+
+ char *vars;
+ uint varsz;
+
+ void *curmap; /* current regs va */
+
+ uint curidx; /* current core index */
+ uint numcores; /* # discovered cores */
+
+ void *curwrap; /* current wrapper va */
+
+ uint32 oob_router; /* oob router registers for axi */
+
+ void *cores_info;
+ gci_gpio_item_t *gci_gpio_head; /* gci gpio interrupts head */
+} si_info_t;
+
+
+#define SI_INFO(sih) ((si_info_t *)(uintptr)sih)
+
+#define GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
+ ISALIGNED((x), SI_CORE_SIZE))
+#define GOODREGS(regs) ((regs) != NULL && ISALIGNED((uintptr)(regs), SI_CORE_SIZE))
+#define BADCOREADDR 0
+#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES)
+#define NOREV -1 /* Invalid rev */
+
+#define PCI(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \
+ ((si)->pub.buscoretype == PCI_CORE_ID))
+
+#define PCIE_GEN1(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \
+ ((si)->pub.buscoretype == PCIE_CORE_ID))
+
+#define PCIE_GEN2(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \
+ ((si)->pub.buscoretype == PCIE2_CORE_ID))
+
+#define PCIE(si) (PCIE_GEN1(si) || PCIE_GEN2(si))
+
+#define PCMCIA(si) ((BUSTYPE((si)->pub.bustype) == PCMCIA_BUS) && ((si)->memseg == TRUE))
+
+/* Newer chips can access PCI/PCIE and CC core without requiring to change
+ * PCI BAR0 WIN
+ */
+#define SI_FAST(si) (PCIE(si) || (PCI(si) && ((si)->pub.buscorerev >= 13)))
+
+#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET))
+#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET))
+
+/*
+ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
+ * after core switching to avoid invalid register accesss inside ISR.
+ */
+#define INTR_OFF(si, intr_val) \
+ if ((si)->intrsoff_fn && (cores_info)->coreid[(si)->curidx] == (si)->dev_coreid) { \
+ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
+#define INTR_RESTORE(si, intr_val) \
+ if ((si)->intrsrestore_fn && (cores_info)->coreid[(si)->curidx] == (si)->dev_coreid) { \
+ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
+
+/* dynamic clock control defines */
+#define LPOMINFREQ 25000 /* low power oscillator min */
+#define LPOMAXFREQ 43000 /* low power oscillator max */
+#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
+#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
+#define PCIMINFREQ 25000000 /* 25 MHz */
+#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
+
+#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
+#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
+
+/* Force fast clock for 4360b0 */
+#define PCI_FORCEHT(si) \
+ (((PCIE_GEN1(si)) && (si->pub.chip == BCM4311_CHIP_ID) && ((si->pub.chiprev <= 1))) || \
+ ((PCI(si) || PCIE_GEN1(si)) && (si->pub.chip == BCM4321_CHIP_ID)) || \
+ (PCIE_GEN1(si) && (si->pub.chip == BCM4716_CHIP_ID)) || \
+ (PCIE_GEN1(si) && (si->pub.chip == BCM4748_CHIP_ID)))
+
+/* GPIO Based LED powersave defines */
+#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
+#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
+
+#ifndef DEFAULT_GPIOTIMERVAL
+#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
+#endif
+
+/* Silicon Backplane externs */
+extern void sb_scan(si_t *sih, void *regs, uint devid);
+extern uint sb_coreid(si_t *sih);
+extern uint sb_intflag(si_t *sih);
+extern uint sb_flag(si_t *sih);
+extern void sb_setint(si_t *sih, int siflag);
+extern uint sb_corevendor(si_t *sih);
+extern uint sb_corerev(si_t *sih);
+extern uint sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
+extern uint32 *sb_corereg_addr(si_t *sih, uint coreidx, uint regoff);
+extern bool sb_iscoreup(si_t *sih);
+extern void *sb_setcoreidx(si_t *sih, uint coreidx);
+extern uint32 sb_core_cflags(si_t *sih, uint32 mask, uint32 val);
+extern void sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
+extern uint32 sb_core_sflags(si_t *sih, uint32 mask, uint32 val);
+extern void sb_commit(si_t *sih);
+extern uint32 sb_base(uint32 admatch);
+extern uint32 sb_size(uint32 admatch);
+extern void sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
+extern void sb_core_disable(si_t *sih, uint32 bits);
+extern uint32 sb_addrspace(si_t *sih, uint asidx);
+extern uint32 sb_addrspacesize(si_t *sih, uint asidx);
+extern int sb_numaddrspaces(si_t *sih);
+
+extern uint32 sb_set_initiator_to(si_t *sih, uint32 to, uint idx);
+
+extern bool sb_taclear(si_t *sih, bool details);
+
+
+/* Wake-on-wireless-LAN (WOWL) */
+extern bool sb_pci_pmecap(si_t *sih);
+struct osl_info;
+extern bool sb_pci_fastpmecap(struct osl_info *osh);
+extern bool sb_pci_pmeclr(si_t *sih);
+extern void sb_pci_pmeen(si_t *sih);
+extern uint sb_pcie_readreg(void *sih, uint addrtype, uint offset);
+
+/* AMBA Interconnect exported externs */
+extern si_t *ai_attach(uint pcidev, osl_t *osh, void *regs, uint bustype,
+ void *sdh, char **vars, uint *varsz);
+extern si_t *ai_kattach(osl_t *osh);
+extern void ai_scan(si_t *sih, void *regs, uint devid);
+
+extern uint ai_flag(si_t *sih);
+extern uint ai_flag_alt(si_t *sih);
+extern void ai_setint(si_t *sih, int siflag);
+extern uint ai_coreidx(si_t *sih);
+extern uint ai_corevendor(si_t *sih);
+extern uint ai_corerev(si_t *sih);
+extern uint32 *ai_corereg_addr(si_t *sih, uint coreidx, uint regoff);
+extern bool ai_iscoreup(si_t *sih);
+extern void *ai_setcoreidx(si_t *sih, uint coreidx);
+extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val);
+extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
+extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val);
+extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
+extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
+extern void ai_core_disable(si_t *sih, uint32 bits);
+extern int ai_numaddrspaces(si_t *sih);
+extern uint32 ai_addrspace(si_t *sih, uint asidx);
+extern uint32 ai_addrspacesize(si_t *sih, uint asidx);
+extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size);
+extern uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+
+
+
+#define ub_scan(a, b, c) do {} while (0)
+#define ub_flag(a) (0)
+#define ub_setint(a, b) do {} while (0)
+#define ub_coreidx(a) (0)
+#define ub_corevendor(a) (0)
+#define ub_corerev(a) (0)
+#define ub_iscoreup(a) (0)
+#define ub_setcoreidx(a, b) (0)
+#define ub_core_cflags(a, b, c) (0)
+#define ub_core_cflags_wo(a, b, c) do {} while (0)
+#define ub_core_sflags(a, b, c) (0)
+#define ub_corereg(a, b, c, d, e) (0)
+#define ub_core_reset(a, b, c) do {} while (0)
+#define ub_core_disable(a, b) do {} while (0)
+#define ub_numaddrspaces(a) (0)
+#define ub_addrspace(a, b) (0)
+#define ub_addrspacesize(a, b) (0)
+#define ub_view(a, b) do {} while (0)
+#define ub_dumpregs(a, b) do {} while (0)
+
+#endif /* _siutils_priv_h_ */
diff --git a/drivers/net/wireless/bcmdhd/uamp_api.h b/drivers/net/wireless/bcmdhd/uamp_api.h
new file mode 100644
index 000000000000..9a4ec5fad19d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/uamp_api.h
@@ -0,0 +1,176 @@
+/*
+ * Name: uamp_api.h
+ *
+ * Description: Universal AMP API
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: uamp_api.h 294267 2011-11-04 23:41:52Z $
+ *
+ */
+#ifndef UAMP_API_H
+#define UAMP_API_H
+
+
+#include "typedefs.h"
+
+
+/*****************************************************************************
+** Constant and Type Definitions
+******************************************************************************
+*/
+
+#define BT_API
+
+/* Types. */
+typedef bool BOOLEAN;
+typedef uint8 UINT8;
+typedef uint16 UINT16;
+
+
+/* UAMP identifiers */
+#define UAMP_ID_1 1
+#define UAMP_ID_2 2
+typedef UINT8 tUAMP_ID;
+
+/* UAMP event ids (used by UAMP_CBACK) */
+#define UAMP_EVT_RX_READY 0 /* Data from AMP controller is ready to be read */
+#define UAMP_EVT_CTLR_REMOVED 1 /* Controller removed */
+#define UAMP_EVT_CTLR_READY 2 /* Controller added/ready */
+typedef UINT8 tUAMP_EVT;
+
+
+/* UAMP Channels */
+#define UAMP_CH_HCI_CMD 0 /* HCI Command channel */
+#define UAMP_CH_HCI_EVT 1 /* HCI Event channel */
+#define UAMP_CH_HCI_DATA 2 /* HCI ACL Data channel */
+typedef UINT8 tUAMP_CH;
+
+/* tUAMP_EVT_DATA: union for event-specific data, used by UAMP_CBACK */
+typedef union {
+ tUAMP_CH channel; /* UAMP_EVT_RX_READY: channel for which rx occured */
+} tUAMP_EVT_DATA;
+
+
+/*****************************************************************************
+**
+** Function: UAMP_CBACK
+**
+** Description: Callback for events. Register callback using UAMP_Init.
+**
+** Parameters amp_id: AMP device identifier that generated the event
+** amp_evt: event id
+** p_amp_evt_data: pointer to event-specific data
+**
+******************************************************************************
+*/
+typedef void (*tUAMP_CBACK)(tUAMP_ID amp_id, tUAMP_EVT amp_evt, tUAMP_EVT_DATA *p_amp_evt_data);
+
+/*****************************************************************************
+** external function declarations
+******************************************************************************
+*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+**
+** Function: UAMP_Init
+**
+** Description: Initialize UAMP driver
+**
+** Parameters p_cback: Callback function for UAMP event notification
+**
+******************************************************************************
+*/
+BT_API BOOLEAN UAMP_Init(tUAMP_CBACK p_cback);
+
+
+/*****************************************************************************
+**
+** Function: UAMP_Open
+**
+** Description: Open connection to local AMP device.
+**
+** Parameters app_id: Application specific AMP identifer. This value
+** will be included in AMP messages sent to the
+** BTU task, to identify source of the message
+**
+******************************************************************************
+*/
+BT_API BOOLEAN UAMP_Open(tUAMP_ID amp_id);
+
+/*****************************************************************************
+**
+** Function: UAMP_Close
+**
+** Description: Close connection to local AMP device.
+**
+** Parameters app_id: Application specific AMP identifer.
+**
+******************************************************************************
+*/
+BT_API void UAMP_Close(tUAMP_ID amp_id);
+
+
+/*****************************************************************************
+**
+** Function: UAMP_Write
+**
+** Description: Send buffer to AMP device. Frees GKI buffer when done.
+**
+**
+** Parameters: app_id: AMP identifer.
+** p_buf: pointer to buffer to write
+** num_bytes: number of bytes to write
+** channel: UAMP_CH_HCI_ACL, or UAMP_CH_HCI_CMD
+**
+** Returns: number of bytes written
+**
+******************************************************************************
+*/
+BT_API UINT16 UAMP_Write(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 num_bytes, tUAMP_CH channel);
+
+/*****************************************************************************
+**
+** Function: UAMP_Read
+**
+** Description: Read incoming data from AMP. Call after receiving a
+** UAMP_EVT_RX_READY callback event.
+**
+** Parameters: app_id: AMP identifer.
+** p_buf: pointer to buffer for holding incoming AMP data
+** buf_size: size of p_buf
+** channel: UAMP_CH_HCI_ACL, or UAMP_CH_HCI_EVT
+**
+** Returns: number of bytes read
+**
+******************************************************************************
+*/
+BT_API UINT16 UAMP_Read(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 buf_size, tUAMP_CH channel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UAMP_API_H */
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
new file mode 100644
index 000000000000..9d3580e48f9a
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -0,0 +1,2331 @@
+/*
+ * Linux cfg80211 driver - Android related functions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_android.c 662786 2016-11-11 09:06:37Z $
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <net/netlink.h>
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+
+#include <wl_android.h>
+#include <wldev_common.h>
+#include <wlioctl.h>
+#include <bcmutils.h>
+#include <linux_osl.h>
+#include <dhd_dbg.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <proto/bcmip.h>
+#ifdef PNO_SUPPORT
+#include <dhd_pno.h>
+#endif
+#include <bcmsdbus.h>
+#ifdef WL_CFG80211
+#include <wl_cfg80211.h>
+#endif
+#ifdef WL_NAN
+#include <wl_cfgnan.h>
+#endif /* WL_NAN */
+
+/*
+ * Android private command strings, PLEASE define new private commands here
+ * so they can be updated easily in the future (if needed)
+ */
+
+#define CMD_START "START"
+#define CMD_STOP "STOP"
+#define CMD_SCAN_ACTIVE "SCAN-ACTIVE"
+#define CMD_SCAN_PASSIVE "SCAN-PASSIVE"
+#define CMD_RSSI "RSSI"
+#define CMD_LINKSPEED "LINKSPEED"
+#define CMD_RXFILTER_START "RXFILTER-START"
+#define CMD_RXFILTER_STOP "RXFILTER-STOP"
+#define CMD_RXFILTER_ADD "RXFILTER-ADD"
+#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE"
+#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START"
+#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP"
+#define CMD_BTCOEXMODE "BTCOEXMODE"
+#define CMD_SETSUSPENDOPT "SETSUSPENDOPT"
+#define CMD_SETSUSPENDMODE "SETSUSPENDMODE"
+#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR"
+#define CMD_SETFWPATH "SETFWPATH"
+#define CMD_SETBAND "SETBAND"
+#define CMD_GETBAND "GETBAND"
+#define CMD_COUNTRY "COUNTRY"
+#define CMD_P2P_SET_NOA "P2P_SET_NOA"
+#if !defined WL_ENABLE_P2P_IF
+#define CMD_P2P_GET_NOA "P2P_GET_NOA"
+#endif /* WL_ENABLE_P2P_IF */
+#define CMD_P2P_SD_OFFLOAD "P2P_SD_"
+#define CMD_P2P_SET_PS "P2P_SET_PS"
+#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE"
+#define CMD_SETROAMMODE "SETROAMMODE"
+#define CMD_SETIBSSBEACONOUIDATA "SETIBSSBEACONOUIDATA"
+#define CMD_ADDIE "add_ie"
+#define CMD_DELIE "del_ie"
+#define CMD_MIRACAST "MIRACAST"
+#define CMD_NAN "NAN_"
+#if defined(WL_SUPPORT_AUTO_CHANNEL)
+#define CMD_GET_BEST_CHANNELS "GET_BEST_CHANNELS"
+#endif /* WL_SUPPORT_AUTO_CHANNEL */
+
+
+#define CMD_80211_MODE "MODE" /* 802.11 mode a/b/g/n/ac */
+#define CMD_CHANSPEC "CHANSPEC"
+#define CMD_DATARATE "DATARATE"
+#define CMD_ASSOC_CLIENTS "ASSOCLIST"
+#define CMD_SET_CSA "SETCSA"
+#define CMD_KEEP_ALIVE "KEEPALIVE"
+
+
+/* CCX Private Commands */
+
+#ifdef PNO_SUPPORT
+#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR"
+#define CMD_PNOSETUP_SET "PNOSETUP "
+#define CMD_PNOENABLE_SET "PNOFORCE"
+#define CMD_PNODEBUG_SET "PNODEBUG"
+#define CMD_WLS_BATCHING "WLS_BATCHING"
+#endif /* PNO_SUPPORT */
+
+#define CMD_OKC_SET_PMK "SET_PMK"
+#define CMD_OKC_ENABLE "OKC_ENABLE"
+
+#define CMD_HAPD_MAC_FILTER "HAPD_MAC_FILTER"
+
+
+
+
+#define CMD_ROAM_OFFLOAD "SETROAMOFFLOAD"
+
+#ifdef WLTDLS
+#define CMD_TDLS_RESET "TDLS_RESET"
+#endif /* WLTDLS */
+
+#define CMD_INTERFACE_CREATE "INTERFACE_CREATE"
+#define CMD_INTERFACE_DELETE "INTERFACE_DELETE"
+
+/* miracast related definition */
+#define MIRACAST_MODE_OFF 0
+#define MIRACAST_MODE_SOURCE 1
+#define MIRACAST_MODE_SINK 2
+
+#ifndef MIRACAST_AMPDU_SIZE
+#define MIRACAST_AMPDU_SIZE 8
+#endif
+
+#ifndef MIRACAST_MCHAN_ALGO
+#define MIRACAST_MCHAN_ALGO 1
+#endif
+
+#ifndef MIRACAST_MCHAN_BW
+#define MIRACAST_MCHAN_BW 25
+#endif
+
+#ifdef CONNECTION_STATISTICS
+#define CMD_GET_CONNECTION_STATS "GET_CONNECTION_STATS"
+
+struct connection_stats {
+ u32 txframe;
+ u32 txbyte;
+ u32 txerror;
+ u32 rxframe;
+ u32 rxbyte;
+ u32 txfail;
+ u32 txretry;
+ u32 txretrie;
+ u32 txrts;
+ u32 txnocts;
+ u32 txexptime;
+ u32 txrate;
+ u8 chan_idle;
+};
+#endif /* CONNECTION_STATISTICS */
+
+static LIST_HEAD(miracast_resume_list);
+static u8 miracast_cur_mode;
+
+struct io_cfg {
+ s8 *iovar;
+ s32 param;
+ u32 ioctl;
+ void *arg;
+ u32 len;
+ struct list_head list;
+};
+
+typedef struct _android_wifi_priv_cmd {
+ char *buf;
+ int used_len;
+ int total_len;
+} android_wifi_priv_cmd;
+
+#ifdef CONFIG_COMPAT
+typedef struct _compat_android_wifi_priv_cmd {
+ compat_caddr_t buf;
+ int used_len;
+ int total_len;
+} compat_android_wifi_priv_cmd;
+#endif /* CONFIG_COMPAT */
+
+#if defined(BCMFW_ROAM_ENABLE)
+#define CMD_SET_ROAMPREF "SET_ROAMPREF"
+
+#define MAX_NUM_SUITES 10
+#define WIDTH_AKM_SUITE 8
+#define JOIN_PREF_RSSI_LEN 0x02
+#define JOIN_PREF_RSSI_SIZE 4 /* RSSI pref header size in bytes */
+#define JOIN_PREF_WPA_HDR_SIZE 4 /* WPA pref header size in bytes */
+#define JOIN_PREF_WPA_TUPLE_SIZE 12 /* Tuple size in bytes */
+#define JOIN_PREF_MAX_WPA_TUPLES 16
+#define MAX_BUF_SIZE (JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE + \
+ (JOIN_PREF_WPA_TUPLE_SIZE * JOIN_PREF_MAX_WPA_TUPLES))
+#endif /* BCMFW_ROAM_ENABLE */
+
+
+/**
+ * Extern function declarations (TODO: move them to dhd_linux.h)
+ */
+int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
+int dhd_dev_init_ioctl(struct net_device *dev);
+#ifdef WL_CFG80211
+int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
+int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *command);
+#else
+int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
+{ return 0; }
+int wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
+{ return 0; }
+int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
+{ return 0; }
+int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
+{ return 0; }
+#endif /* WK_CFG80211 */
+
+
+#ifdef ENABLE_4335BT_WAR
+extern int bcm_bt_lock(int cookie);
+extern void bcm_bt_unlock(int cookie);
+static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24; /* cookie is "WiFi" */
+#endif /* ENABLE_4335BT_WAR */
+
+extern bool ap_fw_loaded;
+#if defined(CUSTOMER_HW2)
+extern char iface_name[IFNAMSIZ];
+#endif
+
+/**
+ * Local (static) functions and variables
+ */
+
+/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
+ * time (only) in dhd_open, subsequential wifi on will be handled by
+ * wl_android_wifi_on
+ */
+static int g_wifi_on = TRUE;
+
+/**
+ * Local (static) function definitions
+ */
+static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len)
+{
+ int link_speed;
+ int bytes_written;
+ int error;
+
+ error = wldev_get_link_speed(net, &link_speed);
+ if (error)
+ return -1;
+
+ /* Convert Kbps to Android Mbps */
+ link_speed = link_speed / 1000;
+ bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
+ DHD_INFO(("%s: command result is %s\n", __FUNCTION__, command));
+ return bytes_written;
+}
+
+static int wl_android_get_rssi(struct net_device *net, char *command, int total_len)
+{
+ wlc_ssid_t ssid = {0};
+ int bytes_written = 0;
+ int error = 0;
+ scb_val_t scbval;
+ char *delim = NULL;
+
+ delim = strchr(command, ' ');
+ /* For Ap mode rssi command would be
+ * driver rssi <sta_mac_addr>
+ * for STA/GC mode
+ * driver rssi
+ */
+ if (delim) {
+ /* Ap/GO mode
+ * driver rssi <sta_mac_addr>
+ */
+ DHD_TRACE(("%s: cmd:%s\n", __FUNCTION__, delim));
+ /* skip space from delim after finding char */
+ delim++;
+ if (!(bcm_ether_atoe((delim), &scbval.ea)))
+ {
+ DHD_ERROR(("%s:address err\n", __FUNCTION__));
+ return -1;
+ }
+ scbval.val = htod32(0);
+ DHD_TRACE(("%s: address:"MACDBG, __FUNCTION__, MAC2STRDBG(scbval.ea.octet)));
+ }
+ else {
+ /* STA/GC mode */
+ memset(&scbval, 0, sizeof(scb_val_t));
+ }
+
+ error = wldev_get_rssi(net, &scbval);
+ if (error)
+ return -1;
+
+ error = wldev_get_ssid(net, &ssid);
+ if (error)
+ return -1;
+ if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) {
+ DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__));
+ } else {
+ memcpy(command, ssid.SSID, ssid.SSID_len);
+ bytes_written = ssid.SSID_len;
+ }
+ bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", scbval.val);
+ DHD_TRACE(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
+ return bytes_written;
+}
+
+static int wl_android_set_suspendopt(struct net_device *dev, char *command, int total_len)
+{
+ int suspend_flag;
+ int ret_now;
+ int ret = 0;
+
+ suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0';
+
+ if (suspend_flag != 0)
+ suspend_flag = 1;
+ ret_now = net_os_set_suspend_disable(dev, suspend_flag);
+
+ if (ret_now != suspend_flag) {
+ if (!(ret = net_os_set_suspend(dev, ret_now, 1)))
+ DHD_INFO(("%s: Suspend Flag %d -> %d\n",
+ __FUNCTION__, ret_now, suspend_flag));
+ else
+ DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
+ }
+ return ret;
+}
+
+static int wl_android_set_suspendmode(struct net_device *dev, char *command, int total_len)
+{
+ int ret = 0;
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND)
+ int suspend_flag;
+
+ suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0';
+ if (suspend_flag != 0)
+ suspend_flag = 1;
+
+ if (!(ret = net_os_set_suspend(dev, suspend_flag, 0)))
+ DHD_INFO(("%s: Suspend Mode %d\n", __FUNCTION__, suspend_flag));
+ else
+ DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
+#endif
+
+ return ret;
+}
+
+int wl_android_get_80211_mode(struct net_device *dev, char *command, int total_len)
+{
+ uint8 mode[4];
+ int error = 0;
+ int bytes_written = 0;
+
+ error = wldev_get_mode(dev, mode);
+ if (error)
+ return -1;
+
+ DHD_INFO(("%s: mode:%s\n", __FUNCTION__, mode));
+ bytes_written = snprintf(command, total_len, "%s %s", CMD_80211_MODE, mode);
+ DHD_INFO(("%s: command:%s EXIT\n", __FUNCTION__, command));
+ return bytes_written;
+
+}
+
+extern chanspec_t
+wl_chspec_driver_to_host(chanspec_t chanspec);
+int wl_android_get_chanspec(struct net_device *dev, char *command, int total_len)
+{
+ int error = 0;
+ int bytes_written = 0;
+ int chsp = {0};
+ uint16 band = 0;
+ uint16 bw = 0;
+ uint16 channel = 0;
+ u32 sb = 0;
+ chanspec_t chanspec;
+
+ /* command is
+ * driver chanspec
+ */
+ error = wldev_iovar_getint(dev, "chanspec", &chsp);
+ if (error)
+ return -1;
+
+ chanspec = wl_chspec_driver_to_host(chsp);
+ DHD_INFO(("%s:return value of chanspec:%x\n", __FUNCTION__, chanspec));
+
+ channel = chanspec & WL_CHANSPEC_CHAN_MASK;
+ band = chanspec & WL_CHANSPEC_BAND_MASK;
+ bw = chanspec & WL_CHANSPEC_BW_MASK;
+
+ DHD_INFO(("%s:channel:%d band:%d bandwidth:%d\n", __FUNCTION__, channel, band, bw));
+
+ if (bw == WL_CHANSPEC_BW_80)
+ bw = WL_CH_BANDWIDTH_80MHZ;
+ else if (bw == WL_CHANSPEC_BW_40)
+ bw = WL_CH_BANDWIDTH_40MHZ;
+ else if (bw == WL_CHANSPEC_BW_20)
+ bw = WL_CH_BANDWIDTH_20MHZ;
+ else
+ bw = WL_CH_BANDWIDTH_20MHZ;
+
+ if (bw == WL_CH_BANDWIDTH_40MHZ) {
+ if (CHSPEC_SB_UPPER(chanspec)) {
+ channel += CH_10MHZ_APART;
+ } else {
+ channel -= CH_10MHZ_APART;
+ }
+ }
+ else if (bw == WL_CH_BANDWIDTH_80MHZ) {
+ sb = chanspec & WL_CHANSPEC_CTL_SB_MASK;
+ if (sb == WL_CHANSPEC_CTL_SB_LL) {
+ channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
+ } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
+ channel -= CH_10MHZ_APART;
+ } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
+ channel += CH_10MHZ_APART;
+ } else {
+ /* WL_CHANSPEC_CTL_SB_UU */
+ channel += (CH_10MHZ_APART + CH_20MHZ_APART);
+ }
+ }
+ bytes_written = snprintf(command, total_len, "%s channel %d band %s bw %d", CMD_CHANSPEC,
+ channel, band == WL_CHANSPEC_BAND_5G ? "5G":"2G", bw);
+
+ DHD_INFO(("%s: command:%s EXIT\n", __FUNCTION__, command));
+ return bytes_written;
+
+}
+
+/* returns current datarate datarate returned from firmware are in 500kbps */
+int wl_android_get_datarate(struct net_device *dev, char *command, int total_len)
+{
+ int error = 0;
+ int datarate = 0;
+ int bytes_written = 0;
+
+ error = wldev_get_datarate(dev, &datarate);
+ if (error)
+ return -1;
+
+ DHD_INFO(("%s:datarate:%d\n", __FUNCTION__, datarate));
+
+ bytes_written = snprintf(command, total_len, "%s %d", CMD_DATARATE, (datarate/2));
+ return bytes_written;
+}
+int wl_android_get_assoclist(struct net_device *dev, char *command, int total_len)
+{
+ int error = 0;
+ int bytes_written = 0;
+ uint i;
+ char mac_buf[MAX_NUM_OF_ASSOCLIST *
+ sizeof(struct ether_addr) + sizeof(uint)] = {0};
+ struct maclist *assoc_maclist = (struct maclist *)mac_buf;
+
+ DHD_TRACE(("%s: ENTER\n", __FUNCTION__));
+
+ assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST);
+
+ error = wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf), false);
+ if (error)
+ return -1;
+
+ assoc_maclist->count = dtoh32(assoc_maclist->count);
+ bytes_written = snprintf(command, total_len, "%s listcount: %d Stations:",
+ CMD_ASSOC_CLIENTS, assoc_maclist->count);
+
+ for (i = 0; i < assoc_maclist->count; i++) {
+ bytes_written += snprintf(command + bytes_written, total_len, " " MACDBG,
+ MAC2STRDBG(assoc_maclist->ea[i].octet));
+ }
+ return bytes_written;
+
+}
+extern chanspec_t
+wl_chspec_host_to_driver(chanspec_t chanspec);
+static int wl_android_set_csa(struct net_device *dev, char *command, int total_len)
+{
+ int error = 0;
+ char smbuf[WLC_IOCTL_SMLEN];
+ wl_chan_switch_t csa_arg;
+ char buf[32];
+ u32 chnsp = 0;
+ int err = 0;
+
+ DHD_INFO(("%s: command:%s\n", __FUNCTION__, command));
+
+ command = (command + strlen(CMD_SET_CSA));
+ /* Order is mode, count channel */
+ if (!*++command) {
+ DHD_ERROR(("%s:error missing arguments\n", __FUNCTION__));
+ return -1;
+ }
+ csa_arg.mode = bcm_atoi(command);
+ if (csa_arg.mode != 0 && csa_arg.mode != 1) {
+ DHD_ERROR(("Invalid mode\n"));
+ return -1;
+ } if (!*++command) {
+ DHD_ERROR(("%s:error missing count\n", __FUNCTION__));
+ return -1;
+ }
+ command++;
+ csa_arg.count = bcm_atoi(command);
+ if (!*++command) {
+ DHD_ERROR(("%s:error missing channel\n", __FUNCTION__));
+ return -1;
+ }
+ csa_arg.reg = 0;
+ csa_arg.chspec = 0;
+ command += 2;
+ if (sizeof(buf) > strlen(command))
+ bcm_strncpy_s(buf, sizeof(buf), command, strlen(command));
+ else {
+ DHD_ERROR(("%s:command is invalid\n", __FUNCTION__));
+ return -1;
+ }
+ chnsp = wf_chspec_aton(buf);
+ if (chnsp == 0) {
+ DHD_ERROR(("%s:chsp is not correct\n", __FUNCTION__));
+ return -1;
+ }
+ chnsp = wl_chspec_host_to_driver(chnsp);
+ csa_arg.chspec = chnsp;
+
+ if (chnsp & WL_CHANSPEC_BAND_5G) {
+ u32 chanspec = chnsp;
+ err = wldev_iovar_getint(dev, "per_chan_info", &chanspec);
+ if (!err) {
+ if ((chanspec & WL_CHAN_RADAR) || (chanspec & WL_CHAN_PASSIVE)) {
+ DHD_ERROR(("Channel is radar sensitive\n"));
+ return -1;
+ }
+ if (chanspec == 0) {
+ DHD_ERROR(("Invalid hw channel\n"));
+ return -1;
+ }
+ } else {
+ DHD_ERROR(("does not support per_chan_info\n"));
+ return -1;
+ }
+ DHD_INFO(("non radar sensitivity\n"));
+ }
+ error = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(csa_arg),
+ smbuf, sizeof(smbuf), NULL);
+ if (error) {
+ DHD_ERROR(("%s:set csa failed:%d\n", __FUNCTION__, error));
+ return -1;
+ }
+ return 0;
+}
+static int wl_android_get_band(struct net_device *dev, char *command, int total_len)
+{
+ uint band;
+ int bytes_written;
+ int error;
+
+ error = wldev_get_band(dev, &band);
+ if (error)
+ return -1;
+ bytes_written = snprintf(command, total_len, "Band %d", band);
+ return bytes_written;
+}
+
+
+#ifdef PNO_SUPPORT
+#define PNO_PARAM_SIZE 50
+#define VALUE_SIZE 50
+#define LIMIT_STR_FMT ("%50s %50s")
+static int
+wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len)
+{
+ int err = BCME_OK;
+ uint i, tokens;
+ char *pos, *pos2, *token, *token2, *delim;
+ char param[PNO_PARAM_SIZE+1], value[VALUE_SIZE+1];
+ struct dhd_pno_batch_params batch_params;
+ DHD_PNO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
+ if (total_len < strlen(CMD_WLS_BATCHING)) {
+ DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
+ err = BCME_ERROR;
+ goto exit;
+ }
+ pos = command + strlen(CMD_WLS_BATCHING) + 1;
+ memset(&batch_params, 0, sizeof(struct dhd_pno_batch_params));
+
+ if (!strncmp(pos, PNO_BATCHING_SET, strlen(PNO_BATCHING_SET))) {
+ pos += strlen(PNO_BATCHING_SET) + 1;
+ while ((token = strsep(&pos, PNO_PARAMS_DELIMETER)) != NULL) {
+ memset(param, 0, sizeof(param));
+ memset(value, 0, sizeof(value));
+ if (token == NULL || !*token)
+ break;
+ if (*token == '\0')
+ continue;
+ delim = strchr(token, PNO_PARAM_VALUE_DELLIMETER);
+ if (delim != NULL)
+ *delim = ' ';
+
+ tokens = sscanf(token, LIMIT_STR_FMT, param, value);
+ if (!strncmp(param, PNO_PARAM_SCANFREQ, strlen(PNO_PARAM_SCANFREQ))) {
+ batch_params.scan_fr = simple_strtol(value, NULL, 0);
+ DHD_PNO(("scan_freq : %d\n", batch_params.scan_fr));
+ } else if (!strncmp(param, PNO_PARAM_BESTN, strlen(PNO_PARAM_BESTN))) {
+ batch_params.bestn = simple_strtol(value, NULL, 0);
+ DHD_PNO(("bestn : %d\n", batch_params.bestn));
+ } else if (!strncmp(param, PNO_PARAM_MSCAN, strlen(PNO_PARAM_MSCAN))) {
+ batch_params.mscan = simple_strtol(value, NULL, 0);
+ DHD_PNO(("mscan : %d\n", batch_params.mscan));
+ } else if (!strncmp(param, PNO_PARAM_CHANNEL, strlen(PNO_PARAM_CHANNEL))) {
+ i = 0;
+ pos2 = value;
+ tokens = sscanf(value, "<%s>", value);
+ if (tokens != 1) {
+ err = BCME_ERROR;
+ DHD_ERROR(("%s : invalid format for channel"
+ " <> params\n", __FUNCTION__));
+ goto exit;
+ }
+ while ((token2 = strsep(&pos2,
+ PNO_PARAM_CHANNEL_DELIMETER)) != NULL) {
+ if (token2 == NULL || !*token2)
+ break;
+ if (*token2 == '\0')
+ continue;
+ if (*token2 == 'A' || *token2 == 'B') {
+ batch_params.band = (*token2 == 'A')?
+ WLC_BAND_5G : WLC_BAND_2G;
+ DHD_PNO(("band : %s\n",
+ (*token2 == 'A')? "A" : "B"));
+ } else {
+ if ((batch_params.nchan >= WL_NUMCHANNELS) ||
+ (i >= WL_NUMCHANNELS)) {
+ DHD_ERROR(("Too many nchan %d\n",
+ batch_params.nchan));
+ err = BCME_BUFTOOSHORT;
+ goto exit;
+ }
+ batch_params.chan_list[i++] =
+ simple_strtol(token2, NULL, 0);
+ batch_params.nchan++;
+ DHD_PNO(("channel :%d\n",
+ batch_params.chan_list[i-1]));
+ }
+ }
+ } else if (!strncmp(param, PNO_PARAM_RTT, strlen(PNO_PARAM_RTT))) {
+ batch_params.rtt = simple_strtol(value, NULL, 0);
+ DHD_PNO(("rtt : %d\n", batch_params.rtt));
+ } else {
+ DHD_ERROR(("%s : unknown param: %s\n", __FUNCTION__, param));
+ err = BCME_ERROR;
+ goto exit;
+ }
+ }
+ err = dhd_dev_pno_set_for_batch(dev, &batch_params);
+ if (err < 0) {
+ DHD_ERROR(("failed to configure batch scan\n"));
+ } else {
+ memset(command, 0, total_len);
+ err = sprintf(command, "%d", err);
+ }
+ } else if (!strncmp(pos, PNO_BATCHING_GET, strlen(PNO_BATCHING_GET))) {
+ err = dhd_dev_pno_get_for_batch(dev, command, total_len);
+ if (err < 0) {
+ DHD_ERROR(("failed to getting batching results\n"));
+ } else {
+ err = strlen(command);
+ }
+ } else if (!strncmp(pos, PNO_BATCHING_STOP, strlen(PNO_BATCHING_STOP))) {
+ err = dhd_dev_pno_stop_for_batch(dev);
+ if (err < 0) {
+ DHD_ERROR(("failed to stop batching scan\n"));
+ } else {
+ memset(command, 0, total_len);
+ err = sprintf(command, "OK");
+ }
+ } else {
+ DHD_ERROR(("%s : unknown command\n", __FUNCTION__));
+ err = BCME_ERROR;
+ goto exit;
+ }
+exit:
+ return err;
+}
+#ifndef WL_SCHED_SCAN
+static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
+{
+ wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
+ int res = -1;
+ int nssid = 0;
+ cmd_tlv_t *cmd_tlv_temp;
+ char *str_ptr;
+ int tlv_size_left;
+ int pno_time = 0;
+ int pno_repeat = 0;
+ int pno_freq_expo_max = 0;
+
+#ifdef PNO_SET_DEBUG
+ int i;
+ char pno_in_example[] = {
+ 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
+ 'S', '1', '2', '0',
+ 'S',
+ 0x05,
+ 'd', 'l', 'i', 'n', 'k',
+ 'S',
+ 0x04,
+ 'G', 'O', 'O', 'G',
+ 'T',
+ '0', 'B',
+ 'R',
+ '2',
+ 'M',
+ '2',
+ 0x00
+ };
+#endif /* PNO_SET_DEBUG */
+ DHD_PNO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
+
+ if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
+ DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
+ goto exit_proc;
+ }
+#ifdef PNO_SET_DEBUG
+ memcpy(command, pno_in_example, sizeof(pno_in_example));
+ total_len = sizeof(pno_in_example);
+#endif
+ str_ptr = command + strlen(CMD_PNOSETUP_SET);
+ tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
+
+ cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
+ memset(ssids_local, 0, sizeof(ssids_local));
+
+ if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
+ (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
+ (cmd_tlv_temp->subtype == PNO_TLV_SUBTYPE_LEGACY_PNO)) {
+
+ str_ptr += sizeof(cmd_tlv_t);
+ tlv_size_left -= sizeof(cmd_tlv_t);
+
+ if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local,
+ MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
+ DHD_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
+ goto exit_proc;
+ } else {
+ if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
+ DHD_ERROR(("%s scan duration corrupted field size %d\n",
+ __FUNCTION__, tlv_size_left));
+ goto exit_proc;
+ }
+ str_ptr++;
+ pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
+ DHD_PNO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
+
+ if (str_ptr[0] != 0) {
+ if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
+ DHD_ERROR(("%s pno repeat : corrupted field\n",
+ __FUNCTION__));
+ goto exit_proc;
+ }
+ str_ptr++;
+ pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
+ DHD_PNO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
+ if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
+ DHD_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n",
+ __FUNCTION__));
+ goto exit_proc;
+ }
+ str_ptr++;
+ pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
+ DHD_PNO(("%s: pno_freq_expo_max=%d\n",
+ __FUNCTION__, pno_freq_expo_max));
+ }
+ }
+ } else {
+ DHD_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
+ goto exit_proc;
+ }
+
+ res = dhd_dev_pno_set_for_ssid(dev, ssids_local, nssid, pno_time, pno_repeat,
+ pno_freq_expo_max, NULL, 0);
+exit_proc:
+ return res;
+}
+#endif /* !WL_SCHED_SCAN */
+#endif /* PNO_SUPPORT */
+
+static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
+{
+ int ret;
+ int bytes_written = 0;
+
+ ret = wl_cfg80211_get_p2p_dev_addr(ndev, (struct ether_addr*)command);
+ if (ret)
+ return 0;
+ bytes_written = sizeof(struct ether_addr);
+ return bytes_written;
+}
+
+
+#ifdef WLTDLS
+int wl_android_tdls_reset(struct net_device *dev)
+{
+ int ret = 0;
+ ret = dhd_tdls_enable(dev, false, false, NULL);
+ if (ret < 0) {
+ DHD_ERROR(("Disable tdls failed. %d\n", ret));
+ return ret;
+ }
+ ret = dhd_tdls_enable(dev, true, true, NULL);
+ if (ret < 0) {
+ DHD_ERROR(("enable tdls failed. %d\n", ret));
+ return ret;
+ }
+ return 0;
+}
+#endif /* WLTDLS */
+
+int
+wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist)
+{
+ int i, j, match;
+ int ret = 0;
+ char mac_buf[MAX_NUM_OF_ASSOCLIST *
+ sizeof(struct ether_addr) + sizeof(uint)] = {0};
+ struct maclist *assoc_maclist = (struct maclist *)mac_buf;
+
+ /* set filtering mode */
+ if ((ret = wldev_ioctl(dev, WLC_SET_MACMODE, &macmode, sizeof(macmode), true)) != 0) {
+ DHD_ERROR(("%s : WLC_SET_MACMODE error=%d\n", __FUNCTION__, ret));
+ return ret;
+ }
+ if (macmode != MACLIST_MODE_DISABLED) {
+ /* set the MAC filter list */
+ if ((ret = wldev_ioctl(dev, WLC_SET_MACLIST, maclist,
+ sizeof(int) + sizeof(struct ether_addr) * maclist->count, true)) != 0) {
+ DHD_ERROR(("%s : WLC_SET_MACLIST error=%d\n", __FUNCTION__, ret));
+ return ret;
+ }
+ /* get the current list of associated STAs */
+ assoc_maclist->count = MAX_NUM_OF_ASSOCLIST;
+ if ((ret = wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist,
+ sizeof(mac_buf), false)) != 0) {
+ DHD_ERROR(("%s : WLC_GET_ASSOCLIST error=%d\n", __FUNCTION__, ret));
+ return ret;
+ }
+ /* do we have any STA associated? */
+ if (assoc_maclist->count) {
+ /* iterate each associated STA */
+ for (i = 0; i < assoc_maclist->count; i++) {
+ match = 0;
+ /* compare with each entry */
+ for (j = 0; j < maclist->count; j++) {
+ DHD_INFO(("%s : associated="MACDBG " list="MACDBG "\n",
+ __FUNCTION__, MAC2STRDBG(assoc_maclist->ea[i].octet),
+ MAC2STRDBG(maclist->ea[j].octet)));
+ if (memcmp(assoc_maclist->ea[i].octet,
+ maclist->ea[j].octet, ETHER_ADDR_LEN) == 0) {
+ match = 1;
+ break;
+ }
+ }
+ /* do conditional deauth */
+ /* "if not in the allow list" or "if in the deny list" */
+ if ((macmode == MACLIST_MODE_ALLOW && !match) ||
+ (macmode == MACLIST_MODE_DENY && match)) {
+ scb_val_t scbval;
+
+ scbval.val = htod32(1);
+ memcpy(&scbval.ea, &assoc_maclist->ea[i],
+ ETHER_ADDR_LEN);
+ if ((ret = wldev_ioctl(dev,
+ WLC_SCB_DEAUTHENTICATE_FOR_REASON,
+ &scbval, sizeof(scb_val_t), true)) != 0)
+ DHD_ERROR(("%s WLC_SCB_DEAUTHENTICATE error=%d\n",
+ __FUNCTION__, ret));
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+/*
+ * HAPD_MAC_FILTER mac_mode mac_cnt mac_addr1 mac_addr2
+ *
+ */
+static int
+wl_android_set_mac_address_filter(struct net_device *dev, const char* str)
+{
+ int i;
+ int ret = 0;
+ int macnum = 0;
+ int macmode = MACLIST_MODE_DISABLED;
+ struct maclist *list;
+ char eabuf[ETHER_ADDR_STR_LEN];
+ char *token;
+
+ /* string should look like below (macmode/macnum/maclist) */
+ /* 1 2 00:11:22:33:44:55 00:11:22:33:44:ff */
+
+ /* get the MAC filter mode */
+ token = strsep((char**)&str, " ");
+ if (!token) {
+ return -1;
+ }
+ macmode = bcm_atoi(token);
+
+ if (macmode < MACLIST_MODE_DISABLED || macmode > MACLIST_MODE_ALLOW) {
+ DHD_ERROR(("%s : invalid macmode %d\n", __FUNCTION__, macmode));
+ return -1;
+ }
+
+ token = strsep((char**)&str, " ");
+ if (!token) {
+ return -1;
+ }
+ macnum = bcm_atoi(token);
+ if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
+ DHD_ERROR(("%s : invalid number of MAC address entries %d\n",
+ __FUNCTION__, macnum));
+ return -1;
+ }
+ /* allocate memory for the MAC list */
+ list = (struct maclist*)kmalloc(sizeof(int) +
+ sizeof(struct ether_addr) * macnum, GFP_KERNEL);
+ if (!list) {
+ DHD_ERROR(("%s : failed to allocate memory\n", __FUNCTION__));
+ return -1;
+ }
+ /* prepare the MAC list */
+ list->count = htod32(macnum);
+ bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
+ for (i = 0; i < list->count; i++) {
+ strncpy(eabuf, strsep((char**)&str, " "), ETHER_ADDR_STR_LEN - 1);
+ if (!(ret = bcm_ether_atoe(eabuf, &list->ea[i]))) {
+ DHD_ERROR(("%s : mac parsing err index=%d, addr=%s\n",
+ __FUNCTION__, i, eabuf));
+ list->count--;
+ break;
+ }
+ DHD_INFO(("%s : %d/%d MACADDR=%s", __FUNCTION__, i, list->count, eabuf));
+ }
+ /* set the list */
+ if ((ret = wl_android_set_ap_mac_list(dev, macmode, list)) != 0)
+ DHD_ERROR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
+
+ kfree(list);
+
+ return 0;
+}
+
+/**
+ * Global function definitions (declared in wl_android.h)
+ */
+
+int wl_android_wifi_on(struct net_device *dev)
+{
+ int ret = 0;
+ int retry = POWERUP_MAX_RETRY;
+
+ DHD_ERROR(("%s in\n", __FUNCTION__));
+ if (!dev) {
+ DHD_ERROR(("%s: dev is null\n", __FUNCTION__));
+ return -EINVAL;
+ }
+
+ dhd_net_if_lock(dev);
+ if (!g_wifi_on) {
+ do {
+ dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY);
+ ret = dhd_net_bus_resume(dev, 0);
+ if (ret == 0)
+ break;
+ DHD_ERROR(("\nfailed to power up wifi chip, retry again (%d left) **\n\n",
+ retry+1));
+ dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
+ } while (retry-- >= 0);
+ if (ret != 0) {
+ DHD_ERROR(("\nfailed to power up wifi chip, max retry reached **\n\n"));
+ goto exit;
+ }
+ ret = dhd_net_bus_devreset(dev, FALSE);
+ dhd_net_bus_resume(dev, 1);
+ if (!ret) {
+ if (dhd_dev_init_ioctl(dev) < 0)
+ ret = -EFAULT;
+ }
+ g_wifi_on = TRUE;
+ }
+
+exit:
+ dhd_net_if_unlock(dev);
+
+ return ret;
+}
+
+int wl_android_wifi_off(struct net_device *dev)
+{
+ int ret = 0;
+
+ DHD_ERROR(("%s in\n", __FUNCTION__));
+ if (!dev) {
+ DHD_TRACE(("%s: dev is null\n", __FUNCTION__));
+ return -EINVAL;
+ }
+
+ dhd_net_if_lock(dev);
+ if (g_wifi_on) {
+ ret = dhd_net_bus_devreset(dev, TRUE);
+ dhd_net_bus_suspend(dev);
+ dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
+ g_wifi_on = FALSE;
+ }
+ dhd_net_if_unlock(dev);
+
+ return ret;
+}
+
+static int wl_android_set_fwpath(struct net_device *net, char *command, int total_len)
+{
+ if ((strlen(command) - strlen(CMD_SETFWPATH)) > MOD_PARAM_PATHLEN)
+ return -1;
+ return dhd_net_set_fw_path(net, command + strlen(CMD_SETFWPATH) + 1);
+}
+
+#ifdef CONNECTION_STATISTICS
+static int
+wl_chanim_stats(struct net_device *dev, u8 *chan_idle)
+{
+ int err;
+ wl_chanim_stats_t *list;
+ /* Parameter _and_ returned buffer of chanim_stats. */
+ wl_chanim_stats_t param;
+ u8 result[WLC_IOCTL_SMLEN];
+ chanim_stats_t *stats;
+
+ memset(&param, 0, sizeof(param));
+ memset(result, 0, sizeof(result));
+
+ param.buflen = htod32(sizeof(wl_chanim_stats_t));
+ param.count = htod32(WL_CHANIM_COUNT_ONE);
+
+ if ((err = wldev_iovar_getbuf(dev, "chanim_stats", (char*)&param, sizeof(wl_chanim_stats_t),
+ (char*)result, sizeof(result), 0)) < 0) {
+ WL_ERR(("Failed to get chanim results %d \n", err));
+ return err;
+ }
+
+ list = (wl_chanim_stats_t*)result;
+
+ list->buflen = dtoh32(list->buflen);
+ list->version = dtoh32(list->version);
+ list->count = dtoh32(list->count);
+
+ if (list->buflen == 0) {
+ list->version = 0;
+ list->count = 0;
+ } else if (list->version != WL_CHANIM_STATS_VERSION) {
+ WL_ERR(("Sorry, firmware has wl_chanim_stats version %d "
+ "but driver supports only version %d.\n",
+ list->version, WL_CHANIM_STATS_VERSION));
+ list->buflen = 0;
+ list->count = 0;
+ }
+
+ stats = list->stats;
+ stats->glitchcnt = dtoh32(stats->glitchcnt);
+ stats->badplcp = dtoh32(stats->badplcp);
+ stats->chanspec = dtoh16(stats->chanspec);
+ stats->timestamp = dtoh32(stats->timestamp);
+ stats->chan_idle = dtoh32(stats->chan_idle);
+
+ WL_INFO(("chanspec: 0x%4x glitch: %d badplcp: %d idle: %d timestamp: %d\n",
+ stats->chanspec, stats->glitchcnt, stats->badplcp, stats->chan_idle,
+ stats->timestamp));
+
+ *chan_idle = stats->chan_idle;
+
+ return (err);
+}
+
+static int
+wl_android_get_connection_stats(struct net_device *dev, char *command, int total_len)
+{
+ wl_cnt_t* cnt = NULL;
+ int link_speed = 0;
+ struct connection_stats *output;
+ unsigned int bufsize = 0;
+ int bytes_written = 0;
+ int ret = 0;
+
+ WL_INFO(("%s: enter Get Connection Stats\n", __FUNCTION__));
+
+ if (total_len <= 0) {
+ WL_ERR(("%s: invalid buffer size %d\n", __FUNCTION__, total_len));
+ goto error;
+ }
+
+ bufsize = total_len;
+ if (bufsize < sizeof(struct connection_stats)) {
+ WL_ERR(("%s: not enough buffer size, provided=%u, requires=%u\n",
+ __FUNCTION__, bufsize,
+ sizeof(struct connection_stats)));
+ goto error;
+ }
+
+ if ((cnt = kmalloc(sizeof(*cnt), GFP_KERNEL)) == NULL) {
+ WL_ERR(("kmalloc failed\n"));
+ return -1;
+ }
+ memset(cnt, 0, sizeof(*cnt));
+
+ ret = wldev_iovar_getbuf(dev, "counters", NULL, 0, (char *)cnt, sizeof(wl_cnt_t), NULL);
+ if (ret) {
+ WL_ERR(("%s: wldev_iovar_getbuf() failed, ret=%d\n",
+ __FUNCTION__, ret));
+ goto error;
+ }
+
+ if (dtoh16(cnt->version) > WL_CNT_T_VERSION) {
+ WL_ERR(("%s: incorrect version of wl_cnt_t, expected=%u got=%u\n",
+ __FUNCTION__, WL_CNT_T_VERSION, cnt->version));
+ goto error;
+ }
+
+ /* link_speed is in kbps */
+ ret = wldev_get_link_speed(dev, &link_speed);
+ if (ret || link_speed < 0) {
+ WL_ERR(("%s: wldev_get_link_speed() failed, ret=%d, speed=%d\n",
+ __FUNCTION__, ret, link_speed));
+ goto error;
+ }
+
+ output = (struct connection_stats *)command;
+ output->txframe = dtoh32(cnt->txframe);
+ output->txbyte = dtoh32(cnt->txbyte);
+ output->txerror = dtoh32(cnt->txerror);
+ output->rxframe = dtoh32(cnt->rxframe);
+ output->rxbyte = dtoh32(cnt->rxbyte);
+ output->txfail = dtoh32(cnt->txfail);
+ output->txretry = dtoh32(cnt->txretry);
+ output->txretrie = dtoh32(cnt->txretrie);
+ output->txrts = dtoh32(cnt->txrts);
+ output->txnocts = dtoh32(cnt->txnocts);
+ output->txexptime = dtoh32(cnt->txexptime);
+ output->txrate = link_speed;
+
+ /* Channel idle ratio. */
+ if (wl_chanim_stats(dev, &(output->chan_idle)) < 0) {
+ output->chan_idle = 0;
+ };
+
+ kfree(cnt);
+
+ bytes_written = sizeof(struct connection_stats);
+ return bytes_written;
+
+error:
+ if (cnt) {
+ kfree(cnt);
+ }
+ return -1;
+}
+#endif /* CONNECTION_STATISTICS */
+
+static int
+wl_android_set_pmk(struct net_device *dev, char *command, int total_len)
+{
+ uchar pmk[33];
+ int error = 0;
+ char smbuf[WLC_IOCTL_SMLEN];
+#ifdef OKC_DEBUG
+ int i = 0;
+#endif
+
+ bzero(pmk, sizeof(pmk));
+ memcpy((char *)pmk, command + strlen("SET_PMK "), 32);
+ error = wldev_iovar_setbuf(dev, "okc_info_pmk", pmk, 32, smbuf, sizeof(smbuf), NULL);
+ if (error) {
+ DHD_ERROR(("Failed to set PMK for OKC, error = %d\n", error));
+ }
+#ifdef OKC_DEBUG
+ DHD_ERROR(("PMK is "));
+ for (i = 0; i < 32; i++)
+ DHD_ERROR(("%02X ", pmk[i]));
+
+ DHD_ERROR(("\n"));
+#endif
+ return error;
+}
+
+static int
+wl_android_okc_enable(struct net_device *dev, char *command, int total_len)
+{
+ int error = 0;
+ char okc_enable = 0;
+
+ okc_enable = command[strlen(CMD_OKC_ENABLE) + 1] - '0';
+ error = wldev_iovar_setint(dev, "okc_enable", okc_enable);
+ if (error) {
+ DHD_ERROR(("Failed to %s OKC, error = %d\n",
+ okc_enable ? "enable" : "disable", error));
+ }
+
+ wldev_iovar_setint(dev, "ccx_enable", 0);
+
+ return error;
+}
+
+
+
+int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len)
+{
+ int error = 0;
+ int mode = 0;
+
+ if (sscanf(command, "%*s %d", &mode) != 1) {
+ DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
+ return -1;
+ }
+
+ error = wldev_iovar_setint(dev, "roam_off", mode);
+ if (error) {
+ DHD_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n",
+ __FUNCTION__, mode, error));
+ return -1;
+ }
+ else
+ DHD_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n",
+ __FUNCTION__, mode, error));
+ return 0;
+}
+
+int wl_android_add_vendor_ie(struct net_device *dev, char *command, int total_len)
+{
+ char ie_buf[VNDR_IE_MAX_LEN];
+ char *ioctl_buf = NULL;
+ char hex[] = "XX";
+ char *pcmd = NULL;
+ int ielen = 0, datalen = 0, idx = 0, tot_len = 0;
+ vndr_ie_setbuf_t *vndr_ie = NULL;
+ s32 iecount;
+ uint32 pktflag;
+ u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+ s32 err = BCME_OK;
+
+ pcmd = command + strlen(CMD_ADDIE) + 1;
+
+ pktflag = simple_strtoul(pcmd, &pcmd, 16);
+
+ pcmd = pcmd + 1;
+
+ for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
+ hex[0] = *pcmd++;
+ hex[1] = *pcmd++;
+ ie_buf[idx] = (uint8)simple_strtoul(hex, NULL, 16);
+ }
+ pcmd++;
+ while ((*pcmd != '\0') && (idx < VNDR_IE_MAX_LEN)) {
+ hex[0] = *pcmd++;
+ hex[1] = *pcmd++;
+ ie_buf[idx++] = (uint8)simple_strtoul(hex, NULL, 16);
+ datalen++;
+ }
+
+ tot_len = sizeof(vndr_ie_setbuf_t) + (datalen - 1);
+ vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags);
+ if (!vndr_ie) {
+ WL_ERR(("IE memory alloc failed\n"));
+ return -ENOMEM;
+ }
+
+ /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
+ strncpy(vndr_ie->cmd, "add", VNDR_IE_CMD_LEN - 1);
+ vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+ /* Set the IE count - the buffer contains only 1 IE */
+ iecount = htod32(1);
+ memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
+
+ /* Set packet flag to indicate the appropriate frame will contain this IE */
+ pktflag = htod32(1<<pktflag);
+ memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
+ sizeof(u32));
+
+ /* Set the IE ID */
+ vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar) DOT11_MNG_PROPR_ID;
+
+ /* Set the OUI */
+ memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, &ie_buf,
+ DOT11_OUI_LEN);
+ /* Set the Data */
+ memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data,
+ &ie_buf[DOT11_OUI_LEN], datalen);
+
+ ielen = DOT11_OUI_LEN + datalen;
+ vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
+
+ ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+ if (!ioctl_buf) {
+ WL_ERR(("ioctl memory alloc failed\n"));
+ if (vndr_ie)
+ kfree(vndr_ie);
+ return -ENOMEM;
+ }
+ memset(ioctl_buf, 0, WLC_IOCTL_MEDLEN); /* init the buffer */
+ err = wldev_iovar_setbuf(dev, "ie", vndr_ie, tot_len, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
+
+ if (err != BCME_OK) {
+ err = -EINVAL;
+ if (vndr_ie)
+ kfree(vndr_ie);
+ }
+ else {
+ /* do NOT free 'vndr_ie' for the next process */
+ wl_cfg80211_ibss_vsie_set_buffer(vndr_ie, tot_len);
+ }
+
+ if (ioctl_buf)
+ kfree(ioctl_buf);
+
+ return err;
+}
+
+int wl_android_del_vendor_ie(struct net_device *dev, char *command, int total_len)
+{
+ char ie_buf[VNDR_IE_MAX_LEN];
+ char *ioctl_buf = NULL;
+ char hex[] = "XX";
+ char *pcmd = NULL;
+ int ielen = 0, datalen = 0, idx = 0, tot_len = 0;
+ vndr_ie_setbuf_t *vndr_ie = NULL;
+ s32 iecount;
+ uint32 pktflag;
+ u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+ s32 err = BCME_OK;
+
+ pcmd = command + strlen(CMD_ADDIE) + 1;
+
+ pktflag = simple_strtoul(pcmd, &pcmd, 16);
+
+ pcmd = pcmd + 1;
+ for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
+ hex[0] = *pcmd++;
+ hex[1] = *pcmd++;
+ ie_buf[idx] = (uint8)simple_strtoul(hex, NULL, 16);
+ }
+ pcmd++;
+ while ((*pcmd != '\0') && (idx < VNDR_IE_MAX_LEN)) {
+ hex[0] = *pcmd++;
+ hex[1] = *pcmd++;
+ ie_buf[idx++] = (uint8)simple_strtoul(hex, NULL, 16);
+ datalen++;
+ }
+
+ tot_len = sizeof(vndr_ie_setbuf_t) + (datalen - 1);
+ vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags);
+ if (!vndr_ie) {
+ WL_ERR(("IE memory alloc failed\n"));
+ return -ENOMEM;
+ }
+ /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
+ strncpy(vndr_ie->cmd, "del", VNDR_IE_CMD_LEN - 1);
+ vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+ /* Set the IE count - the buffer contains only 1 IE */
+ iecount = htod32(1);
+ memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
+
+ /* Set packet flag to indicate the appropriate frame will contain this IE */
+ pktflag = htod32(1<<pktflag);
+ memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
+ sizeof(u32));
+
+ /* Set the IE ID */
+ vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar) DOT11_MNG_PROPR_ID;
+
+ /* Set the OUI */
+ memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, &ie_buf,
+ DOT11_OUI_LEN);
+ /* Set the Data */
+ memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data,
+ &ie_buf[DOT11_OUI_LEN], datalen);
+
+ ielen = DOT11_OUI_LEN + datalen;
+ vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
+
+ ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+ if (!ioctl_buf) {
+ WL_ERR(("ioctl memory alloc failed\n"));
+ if (vndr_ie)
+ kfree(vndr_ie);
+ return -ENOMEM;
+ }
+ memset(ioctl_buf, 0, WLC_IOCTL_MEDLEN); /* init the buffer */
+ err = wldev_iovar_setbuf(dev, "ie", vndr_ie, tot_len, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
+
+ if (err != BCME_OK) {
+ err = -EINVAL;
+ if (vndr_ie)
+ kfree(vndr_ie);
+ }
+ else {
+ /* do NOT free 'vndr_ie' for the next process */
+ wl_cfg80211_ibss_vsie_set_buffer(vndr_ie, tot_len);
+ }
+
+ if (ioctl_buf)
+ kfree(ioctl_buf);
+ return err;
+}
+
+int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, int total_len)
+{
+ char ie_buf[VNDR_IE_MAX_LEN];
+ char *ioctl_buf = NULL;
+ char hex[] = "XX";
+ char *pcmd = NULL;
+ int ielen = 0, datalen = 0, idx = 0, tot_len = 0;
+ vndr_ie_setbuf_t *vndr_ie = NULL;
+ s32 iecount;
+ uint32 pktflag;
+ u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+ s32 err = BCME_OK;
+
+ /* Check the VSIE (Vendor Specific IE) which was added.
+ * If exist then send IOVAR to delete it
+ */
+ if (wl_cfg80211_ibss_vsie_delete(dev) != BCME_OK) {
+ return -EINVAL;
+ }
+
+ pcmd = command + strlen(CMD_SETIBSSBEACONOUIDATA) + 1;
+ for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
+ hex[0] = *pcmd++;
+ hex[1] = *pcmd++;
+ ie_buf[idx] = (uint8)simple_strtoul(hex, NULL, 16);
+ }
+ pcmd++;
+ while ((*pcmd != '\0') && (idx < VNDR_IE_MAX_LEN)) {
+ hex[0] = *pcmd++;
+ hex[1] = *pcmd++;
+ ie_buf[idx++] = (uint8)simple_strtoul(hex, NULL, 16);
+ datalen++;
+ }
+ tot_len = sizeof(vndr_ie_setbuf_t) + (datalen - 1);
+ vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags);
+ if (!vndr_ie) {
+ WL_ERR(("IE memory alloc failed\n"));
+ return -ENOMEM;
+ }
+ /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
+ strncpy(vndr_ie->cmd, "add", VNDR_IE_CMD_LEN - 1);
+ vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+ /* Set the IE count - the buffer contains only 1 IE */
+ iecount = htod32(1);
+ memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
+
+ /* Set packet flag to indicate that BEACON's will contain this IE */
+ pktflag = htod32(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG);
+ memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
+ sizeof(u32));
+ /* Set the IE ID */
+ vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar) DOT11_MNG_PROPR_ID;
+
+ memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, &ie_buf,
+ DOT11_OUI_LEN);
+ memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data,
+ &ie_buf[DOT11_OUI_LEN], datalen);
+
+ ielen = DOT11_OUI_LEN + datalen;
+ vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
+
+ ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+ if (!ioctl_buf) {
+ WL_ERR(("ioctl memory alloc failed\n"));
+ if (vndr_ie) {
+ kfree(vndr_ie);
+ }
+ return -ENOMEM;
+ }
+ memset(ioctl_buf, 0, WLC_IOCTL_MEDLEN); /* init the buffer */
+ err = wldev_iovar_setbuf(dev, "ie", vndr_ie, tot_len, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
+
+
+ if (err != BCME_OK) {
+ err = -EINVAL;
+ if (vndr_ie) {
+ kfree(vndr_ie);
+ }
+ }
+ else {
+ /* do NOT free 'vndr_ie' for the next process */
+ wl_cfg80211_ibss_vsie_set_buffer(vndr_ie, tot_len);
+ }
+
+ if (ioctl_buf) {
+ kfree(ioctl_buf);
+ }
+
+ return err;
+}
+
+#if defined(BCMFW_ROAM_ENABLE)
+static int
+wl_android_set_roampref(struct net_device *dev, char *command, int total_len)
+{
+ int error = 0;
+ char smbuf[WLC_IOCTL_SMLEN];
+ uint8 buf[MAX_BUF_SIZE];
+ uint8 *pref = buf;
+ char *pcmd;
+ int num_ucipher_suites = 0;
+ int num_akm_suites = 0;
+ wpa_suite_t ucipher_suites[MAX_NUM_SUITES];
+ wpa_suite_t akm_suites[MAX_NUM_SUITES];
+ int num_tuples = 0;
+ int total_bytes = 0;
+ int total_len_left;
+ int i, j;
+ char hex[] = "XX";
+
+ pcmd = command + strlen(CMD_SET_ROAMPREF) + 1;
+ total_len_left = total_len - strlen(CMD_SET_ROAMPREF) + 1;
+
+ num_akm_suites = simple_strtoul(pcmd, NULL, 16);
+ /* Increment for number of AKM suites field + space */
+ pcmd += 3;
+ total_len_left -= 3;
+
+ /* check to make sure pcmd does not overrun */
+ if (total_len_left < (num_akm_suites * WIDTH_AKM_SUITE))
+ return -1;
+
+ memset(buf, 0, sizeof(buf));
+ memset(akm_suites, 0, sizeof(akm_suites));
+ memset(ucipher_suites, 0, sizeof(ucipher_suites));
+
+ /* Save the AKM suites passed in the command */
+ for (i = 0; i < num_akm_suites; i++) {
+ /* Store the MSB first, as required by join_pref */
+ for (j = 0; j < 4; j++) {
+ hex[0] = *pcmd++;
+ hex[1] = *pcmd++;
+ buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
+ }
+ memcpy((uint8 *)&akm_suites[i], buf, sizeof(uint32));
+ }
+
+ total_len_left -= (num_akm_suites * WIDTH_AKM_SUITE);
+ num_ucipher_suites = simple_strtoul(pcmd, NULL, 16);
+ /* Increment for number of cipher suites field + space */
+ pcmd += 3;
+ total_len_left -= 3;
+
+ if (total_len_left < (num_ucipher_suites * WIDTH_AKM_SUITE))
+ return -1;
+
+ /* Save the cipher suites passed in the command */
+ for (i = 0; i < num_ucipher_suites; i++) {
+ /* Store the MSB first, as required by join_pref */
+ for (j = 0; j < 4; j++) {
+ hex[0] = *pcmd++;
+ hex[1] = *pcmd++;
+ buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
+ }
+ memcpy((uint8 *)&ucipher_suites[i], buf, sizeof(uint32));
+ }
+
+ /* Join preference for RSSI
+ * Type : 1 byte (0x01)
+ * Length : 1 byte (0x02)
+ * Value : 2 bytes (reserved)
+ */
+ *pref++ = WL_JOIN_PREF_RSSI;
+ *pref++ = JOIN_PREF_RSSI_LEN;
+ *pref++ = 0;
+ *pref++ = 0;
+
+ /* Join preference for WPA
+ * Type : 1 byte (0x02)
+ * Length : 1 byte (not used)
+ * Value : (variable length)
+ * reserved: 1 byte
+ * count : 1 byte (no of tuples)
+ * Tuple1 : 12 bytes
+ * akm[4]
+ * ucipher[4]
+ * mcipher[4]
+ * Tuple2 : 12 bytes
+ * Tuplen : 12 bytes
+ */
+ num_tuples = num_akm_suites * num_ucipher_suites;
+ if (num_tuples != 0) {
+ if (num_tuples <= JOIN_PREF_MAX_WPA_TUPLES) {
+ *pref++ = WL_JOIN_PREF_WPA;
+ *pref++ = 0;
+ *pref++ = 0;
+ *pref++ = (uint8)num_tuples;
+ total_bytes = JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE +
+ (JOIN_PREF_WPA_TUPLE_SIZE * num_tuples);
+ } else {
+ DHD_ERROR(("%s: Too many wpa configs for join_pref \n", __FUNCTION__));
+ return -1;
+ }
+ } else {
+ /* No WPA config, configure only RSSI preference */
+ total_bytes = JOIN_PREF_RSSI_SIZE;
+ }
+
+ /* akm-ucipher-mcipher tuples in the format required for join_pref */
+ for (i = 0; i < num_ucipher_suites; i++) {
+ for (j = 0; j < num_akm_suites; j++) {
+ memcpy(pref, (uint8 *)&akm_suites[j], WPA_SUITE_LEN);
+ pref += WPA_SUITE_LEN;
+ memcpy(pref, (uint8 *)&ucipher_suites[i], WPA_SUITE_LEN);
+ pref += WPA_SUITE_LEN;
+ /* Set to 0 to match any available multicast cipher */
+ memset(pref, 0, WPA_SUITE_LEN);
+ pref += WPA_SUITE_LEN;
+ }
+ }
+
+ prhex("join pref", (uint8 *)buf, total_bytes);
+ error = wldev_iovar_setbuf(dev, "join_pref", buf, total_bytes, smbuf, sizeof(smbuf), NULL);
+ if (error) {
+ DHD_ERROR(("Failed to set join_pref, error = %d\n", error));
+ }
+ return error;
+}
+#endif /* defined(BCMFW_ROAM_ENABLE */
+
+static int
+wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_cfg *config)
+{
+ struct io_cfg *resume_cfg;
+ s32 ret;
+
+ resume_cfg = kzalloc(sizeof(struct io_cfg), GFP_KERNEL);
+ if (!resume_cfg)
+ return -ENOMEM;
+
+ if (config->iovar) {
+ ret = wldev_iovar_getint(dev, config->iovar, &resume_cfg->param);
+ if (ret) {
+ DHD_ERROR(("%s: Failed to get current %s value\n",
+ __FUNCTION__, config->iovar));
+ goto error;
+ }
+
+ ret = wldev_iovar_setint(dev, config->iovar, config->param);
+ if (ret) {
+ DHD_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
+ config->iovar, config->param));
+ goto error;
+ }
+
+ resume_cfg->iovar = config->iovar;
+ } else {
+ resume_cfg->arg = kzalloc(config->len, GFP_KERNEL);
+ if (!resume_cfg->arg) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ ret = wldev_ioctl(dev, config->ioctl, resume_cfg->arg, config->len, false);
+ if (ret) {
+ DHD_ERROR(("%s: Failed to get ioctl %d\n", __FUNCTION__,
+ config->ioctl));
+ goto error;
+ }
+ ret = wldev_ioctl(dev, config->ioctl + 1, config->arg, config->len, true);
+ if (ret) {
+ DHD_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
+ config->iovar, config->param));
+ goto error;
+ }
+ if (config->ioctl + 1 == WLC_SET_PM)
+ wl_cfg80211_update_power_mode(dev);
+ resume_cfg->ioctl = config->ioctl;
+ resume_cfg->len = config->len;
+ }
+
+ list_add(&resume_cfg->list, head);
+
+ return 0;
+error:
+ kfree(resume_cfg->arg);
+ kfree(resume_cfg);
+ return ret;
+}
+
+static void
+wl_android_iolist_resume(struct net_device *dev, struct list_head *head)
+{
+ struct io_cfg *config;
+ struct list_head *cur, *q;
+ s32 ret = 0;
+
+ list_for_each_safe(cur, q, head) {
+ config = list_entry(cur, struct io_cfg, list);
+ if (config->iovar) {
+ if (!ret)
+ ret = wldev_iovar_setint(dev, config->iovar,
+ config->param);
+ } else {
+ if (!ret)
+ ret = wldev_ioctl(dev, config->ioctl + 1,
+ config->arg, config->len, true);
+ if (config->ioctl + 1 == WLC_SET_PM)
+ wl_cfg80211_update_power_mode(dev);
+ kfree(config->arg);
+ }
+ list_del(cur);
+ kfree(config);
+ }
+}
+
+static int
+wl_android_set_miracast(struct net_device *dev, char *command, int total_len)
+{
+ int mode, val;
+ int ret = 0;
+ struct io_cfg config;
+
+ if (sscanf(command, "%*s %d", &mode) != 1) {
+ DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
+ return -1;
+ }
+
+ DHD_INFO(("%s: enter miracast mode %d\n", __FUNCTION__, mode));
+
+ if (miracast_cur_mode == mode) {
+ return 0;
+ }
+
+ wl_android_iolist_resume(dev, &miracast_resume_list);
+ miracast_cur_mode = MIRACAST_MODE_OFF;
+
+ switch (mode) {
+ case MIRACAST_MODE_SOURCE:
+ /* setting mchan_algo to platform specific value */
+ config.iovar = "mchan_algo";
+
+ ret = wldev_ioctl(dev, WLC_GET_BCNPRD, &val, sizeof(int), false);
+ if (!ret && val > 100) {
+ config.param = 0;
+ DHD_ERROR(("%s: Connected station's beacon interval: "
+ "%d and set mchan_algo to %d \n",
+ __FUNCTION__, val, config.param));
+ } else {
+ config.param = MIRACAST_MCHAN_ALGO;
+ }
+ ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
+ if (ret) {
+ goto resume;
+ }
+
+ /* setting mchan_bw to platform specific value */
+ config.iovar = "mchan_bw";
+ config.param = MIRACAST_MCHAN_BW;
+ ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
+ if (ret) {
+ goto resume;
+ }
+
+ /* setting apmdu to platform specific value */
+ config.iovar = "ampdu_mpdu";
+ config.param = MIRACAST_AMPDU_SIZE;
+ ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
+ if (ret) {
+ goto resume;
+ }
+ /* FALLTROUGH */
+ /* Source mode shares most configurations with sink mode.
+ * Fall through here to avoid code duplication
+ */
+ case MIRACAST_MODE_SINK:
+ /* disable internal roaming */
+ config.iovar = "roam_off";
+ config.param = 1;
+ ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
+ if (ret) {
+ goto resume;
+ }
+
+ /* tunr off pm */
+ ret = wldev_ioctl(dev, WLC_GET_PM, &val, sizeof(val), false);
+ if (ret) {
+ goto resume;
+ }
+
+ if (val != PM_OFF) {
+ val = PM_OFF;
+ config.iovar = NULL;
+ config.ioctl = WLC_GET_PM;
+ config.arg = &val;
+ config.len = sizeof(int);
+ ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
+ if (ret) {
+ goto resume;
+ }
+ }
+
+ break;
+ case MIRACAST_MODE_OFF:
+ default:
+ break;
+ }
+ miracast_cur_mode = mode;
+
+ return 0;
+
+resume:
+ DHD_ERROR(("%s: turnoff miracast mode because of err%d\n", __FUNCTION__, ret));
+ wl_android_iolist_resume(dev, &miracast_resume_list);
+ return ret;
+}
+
+#define NETLINK_OXYGEN 30
+#define AIBSS_BEACON_TIMEOUT 10
+
+static struct sock *nl_sk = NULL;
+
+static void wl_netlink_recv(struct sk_buff *skb)
+{
+ WL_ERR(("netlink_recv called\n"));
+}
+
+static int wl_netlink_init(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+ struct netlink_kernel_cfg cfg = {
+ .input = wl_netlink_recv,
+ };
+#endif
+
+ if (nl_sk != NULL) {
+ WL_ERR(("nl_sk already exist\n"));
+ return BCME_ERROR;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+ nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN,
+ 0, wl_netlink_recv, NULL, THIS_MODULE);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
+ nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, THIS_MODULE, &cfg);
+#else
+ nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, &cfg);
+#endif
+
+ if (nl_sk == NULL) {
+ WL_ERR(("nl_sk is not ready\n"));
+ return BCME_ERROR;
+ }
+
+ return BCME_OK;
+}
+
+static void wl_netlink_deinit(void)
+{
+ if (nl_sk) {
+ netlink_kernel_release(nl_sk);
+ nl_sk = NULL;
+ }
+}
+
+s32
+wl_netlink_send_msg(int pid, int type, int seq, void *data, size_t size)
+{
+ struct sk_buff *skb = NULL;
+ struct nlmsghdr *nlh = NULL;
+ int ret = -1;
+
+ if (nl_sk == NULL) {
+ WL_ERR(("nl_sk was not initialized\n"));
+ goto nlmsg_failure;
+ }
+
+ skb = alloc_skb(NLMSG_SPACE(size), GFP_ATOMIC);
+ if (skb == NULL) {
+ WL_ERR(("failed to allocate memory\n"));
+ goto nlmsg_failure;
+ }
+
+ nlh = nlmsg_put(skb, 0, 0, 0, size, 0);
+ if (nlh == NULL) {
+ WL_ERR(("failed to build nlmsg, skb_tailroom:%d, nlmsg_total_size:%d\n",
+ skb_tailroom(skb), nlmsg_total_size(size)));
+ dev_kfree_skb(skb);
+ goto nlmsg_failure;
+ }
+
+ memcpy(nlmsg_data(nlh), data, size);
+ nlh->nlmsg_seq = seq;
+ nlh->nlmsg_type = type;
+
+ /* netlink_unicast() takes ownership of the skb and frees it itself. */
+ ret = netlink_unicast(nl_sk, skb, pid, 0);
+ WL_DBG(("netlink_unicast() pid=%d, ret=%d\n", pid, ret));
+
+nlmsg_failure:
+ return ret;
+}
+
+
+int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len)
+{
+ char buf[256];
+ const char *str;
+ wl_mkeep_alive_pkt_t mkeep_alive_pkt;
+ wl_mkeep_alive_pkt_t *mkeep_alive_pktp;
+ int buf_len;
+ int str_len;
+ int res = -1;
+ uint period_msec = 0;
+
+ if (extra == NULL)
+ {
+ DHD_ERROR(("%s: extra is NULL\n", __FUNCTION__));
+ return -1;
+ }
+ if (sscanf(extra, "%d", &period_msec) != 1)
+ {
+ DHD_ERROR(("%s: sscanf error. check period_msec value\n", __FUNCTION__));
+ return -EINVAL;
+ }
+ DHD_ERROR(("%s: period_msec is %d\n", __FUNCTION__, period_msec));
+
+ memset(&mkeep_alive_pkt, 0, sizeof(wl_mkeep_alive_pkt_t));
+
+ str = "mkeep_alive";
+ str_len = strlen(str);
+ strncpy(buf, str, str_len);
+ buf[ str_len ] = '\0';
+ mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1);
+ mkeep_alive_pkt.period_msec = period_msec;
+ buf_len = str_len + 1;
+ mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
+ mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
+
+ /* Setup keep alive zero for null packet generation */
+ mkeep_alive_pkt.keep_alive_id = 0;
+ mkeep_alive_pkt.len_bytes = 0;
+ buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
+ /* Keep-alive attributes are set in local variable (mkeep_alive_pkt), and
+ * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no
+ * guarantee that the buffer is properly aligned.
+ */
+ memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN);
+
+ if ((res = wldev_ioctl(dev, WLC_SET_VAR, buf, buf_len, TRUE)) < 0)
+ {
+ DHD_ERROR(("%s:keep_alive set failed. res[%d]\n", __FUNCTION__, res));
+ }
+ else
+ {
+ DHD_ERROR(("%s:keep_alive set ok. res[%d]\n", __FUNCTION__, res));
+ }
+
+ return res;
+}
+
+int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
+{
+#define PRIVATE_COMMAND_MAX_LEN 8192
+ int ret = 0;
+ char *command = NULL;
+ int bytes_written = 0;
+ android_wifi_priv_cmd priv_cmd;
+
+ net_os_wake_lock(net);
+
+ if (!capable(CAP_NET_ADMIN)) {
+ ret = -EPERM;
+ goto exit;
+ }
+
+ if (!ifr->ifr_data) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+#ifdef CONFIG_COMPAT
+ if (is_compat_task()) {
+ compat_android_wifi_priv_cmd compat_priv_cmd;
+ if (copy_from_user(&compat_priv_cmd, ifr->ifr_data,
+ sizeof(compat_android_wifi_priv_cmd))) {
+ ret = -EFAULT;
+ goto exit;
+
+ }
+ priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
+ priv_cmd.used_len = compat_priv_cmd.used_len;
+ priv_cmd.total_len = compat_priv_cmd.total_len;
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
+ ret = -EFAULT;
+ goto exit;
+ }
+ }
+ if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) {
+ DHD_ERROR(("%s: invalid length of private command : %d\n",
+ __FUNCTION__, priv_cmd.total_len));
+ ret = -EINVAL;
+ goto exit;
+ }
+ command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL);
+ if (!command)
+ {
+ DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__));
+ ret = -ENOMEM;
+ goto exit;
+ }
+ if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
+ ret = -EFAULT;
+ goto exit;
+ }
+ command[priv_cmd.total_len] = '\0';
+
+ DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name));
+
+ if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) {
+ DHD_INFO(("%s, Received regular START command\n", __FUNCTION__));
+ bytes_written = wl_android_wifi_on(net);
+ }
+ else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) {
+ bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len);
+ }
+
+ if (!g_wifi_on) {
+ DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n",
+ __FUNCTION__, command, ifr->ifr_name));
+ ret = 0;
+ goto exit;
+ }
+
+ if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
+ bytes_written = wl_android_wifi_off(net);
+ }
+ else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) {
+ /* TBD: SCAN-ACTIVE */
+ }
+ else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) {
+ /* TBD: SCAN-PASSIVE */
+ }
+ else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
+ bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len);
+ }
+ else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) {
+ bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len);
+ }
+#ifdef PKT_FILTER_SUPPORT
+ else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) {
+ bytes_written = net_os_enable_packet_filter(net, 1);
+ }
+ else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) {
+ bytes_written = net_os_enable_packet_filter(net, 0);
+ }
+ else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) {
+ int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
+ bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
+ }
+ else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) {
+ int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
+ bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
+ }
+#endif /* PKT_FILTER_SUPPORT */
+ else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) {
+ /* TBD: BTCOEXSCAN-START */
+ }
+ else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) {
+ /* TBD: BTCOEXSCAN-STOP */
+ }
+ else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) {
+#ifdef WL_CFG80211
+ void *dhdp = wl_cfg80211_get_dhdp();
+ bytes_written = wl_cfg80211_set_btcoex_dhcp(net, dhdp, command);
+#else
+#ifdef PKT_FILTER_SUPPORT
+ uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
+
+ if (mode == 1)
+ net_os_enable_packet_filter(net, 0); /* DHCP starts */
+ else
+ net_os_enable_packet_filter(net, 1); /* DHCP ends */
+#endif /* PKT_FILTER_SUPPORT */
+#endif /* WL_CFG80211 */
+ }
+ else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) {
+ bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
+ }
+ else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) {
+ bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len);
+ }
+ else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
+ uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
+ bytes_written = wldev_set_band(net, band);
+ }
+ else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
+ bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
+ }
+#ifdef WL_CFG80211
+ /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
+ else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
+ char *country_code = command + strlen(CMD_COUNTRY) + 1;
+ bytes_written = wldev_set_country(net, country_code, true, true);
+ }
+#endif /* WL_CFG80211 */
+ else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
+ bytes_written = wl_android_set_csa(net, command, priv_cmd.total_len);
+ } else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
+ bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
+ } else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
+ bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
+ } else if (strnicmp(command, CMD_DATARATE, strlen(CMD_DATARATE)) == 0) {
+ bytes_written = wl_android_get_datarate(net, command, priv_cmd.total_len);
+ } else if (strnicmp(command, CMD_ASSOC_CLIENTS, strlen(CMD_ASSOC_CLIENTS)) == 0) {
+ bytes_written = wl_android_get_assoclist(net, command, priv_cmd.total_len);
+ }
+
+#ifdef PNO_SUPPORT
+ else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
+ bytes_written = dhd_dev_pno_stop_for_ssid(net);
+ }
+#ifndef WL_SCHED_SCAN
+ else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) {
+ bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
+ }
+#endif /* !WL_SCHED_SCAN */
+ else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) {
+ int enable = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
+ bytes_written = (enable)? 0 : dhd_dev_pno_stop_for_ssid(net);
+ }
+ else if (strnicmp(command, CMD_WLS_BATCHING, strlen(CMD_WLS_BATCHING)) == 0) {
+ bytes_written = wls_parse_batching_cmd(net, command, priv_cmd.total_len);
+ }
+#endif /* PNO_SUPPORT */
+ else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
+ bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
+ }
+ else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
+ int skip = strlen(CMD_P2P_SET_NOA) + 1;
+ bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
+ priv_cmd.total_len - skip);
+ }
+#ifdef WL_NAN
+ else if (strnicmp(command, CMD_NAN, strlen(CMD_NAN)) == 0) {
+ bytes_written = wl_cfg80211_nan_cmd_handler(net, command,
+ priv_cmd.total_len);
+ }
+#endif /* WL_NAN */
+#if !defined WL_ENABLE_P2P_IF
+ else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) {
+ bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
+ }
+#endif /* WL_ENABLE_P2P_IF */
+ else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) {
+ int skip = strlen(CMD_P2P_SET_PS) + 1;
+ bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
+ priv_cmd.total_len - skip);
+ }
+#ifdef WL_CFG80211
+ else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE,
+ strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) {
+ int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3;
+ bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
+ priv_cmd.total_len - skip, *(command + skip - 2) - '0');
+ }
+#endif /* WL_CFG80211 */
+ else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0)
+ bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len);
+ else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0)
+ bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len);
+#if defined(WL_SUPPORT_AUTO_CHANNEL)
+ else if (strnicmp(command, CMD_GET_BEST_CHANNELS,
+ strlen(CMD_GET_BEST_CHANNELS)) == 0) {
+ bytes_written = wl_cfg80211_get_best_channels(net, command,
+ priv_cmd.total_len);
+ }
+#endif /* WL_SUPPORT_AUTO_CHANNEL */
+ else if (strnicmp(command, CMD_HAPD_MAC_FILTER, strlen(CMD_HAPD_MAC_FILTER)) == 0) {
+ int skip = strlen(CMD_HAPD_MAC_FILTER) + 1;
+ wl_android_set_mac_address_filter(net, (const char*)command+skip);
+ }
+ else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0)
+ bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len);
+#if defined(BCMFW_ROAM_ENABLE)
+ else if (strnicmp(command, CMD_SET_ROAMPREF, strlen(CMD_SET_ROAMPREF)) == 0) {
+ bytes_written = wl_android_set_roampref(net, command, priv_cmd.total_len);
+ }
+#endif /* BCMFW_ROAM_ENABLE */
+ else if (strnicmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)
+ bytes_written = wl_android_set_miracast(net, command, priv_cmd.total_len);
+ else if (strnicmp(command, CMD_SETIBSSBEACONOUIDATA, strlen(CMD_SETIBSSBEACONOUIDATA)) == 0)
+ bytes_written = wl_android_set_ibss_beacon_ouidata(net,
+ command, priv_cmd.total_len);
+ else if (strnicmp(command, CMD_ADDIE, strlen(CMD_ADDIE)) == 0)
+ bytes_written = wl_android_add_vendor_ie(net, command, priv_cmd.total_len);
+ else if (strnicmp(command, CMD_DELIE, strlen(CMD_DELIE)) == 0)
+ bytes_written = wl_android_del_vendor_ie(net, command, priv_cmd.total_len);
+ else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) {
+ int skip = strlen(CMD_KEEP_ALIVE) + 1;
+ bytes_written = wl_keep_alive_set(net, command + skip, priv_cmd.total_len - skip);
+ }
+ else if (strnicmp(command, CMD_ROAM_OFFLOAD, strlen(CMD_ROAM_OFFLOAD)) == 0) {
+ int enable = *(command + strlen(CMD_ROAM_OFFLOAD) + 1) - '0';
+ bytes_written = wl_cfg80211_enable_roam_offload(net, enable);
+ }
+#if defined(WL_VIRTUAL_APSTA)
+ else if (strnicmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) {
+ char *name = (command + strlen(CMD_INTERFACE_CREATE) +1);
+ WL_INFO(("Creating %s interface\n", name));
+ bytes_written = wl_cfg80211_interface_create(net, name);
+ }
+ else if (strnicmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) {
+ char *name = (command + strlen(CMD_INTERFACE_DELETE) +1);
+ WL_INFO(("Deleteing %s interface\n", name));
+ bytes_written = wl_cfg80211_interface_delete(net, name);
+ }
+#endif /* defined (WL_VIRTUAL_APSTA) */
+#ifdef CONNECTION_STATISTICS
+ else if (strnicmp(command, CMD_GET_CONNECTION_STATS,
+ strlen(CMD_GET_CONNECTION_STATS)) == 0) {
+ bytes_written = wl_android_get_connection_stats(net, command,
+ priv_cmd.total_len);
+ }
+#endif
+#ifdef WLTDLS
+ else if (strnicmp(command, CMD_TDLS_RESET, strlen(CMD_TDLS_RESET)) == 0) {
+ bytes_written = wl_android_tdls_reset(net);
+ }
+#endif /* WLTDLS */
+ else {
+ DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
+ snprintf(command, 3, "OK");
+ bytes_written = strlen("OK");
+ }
+
+ if (bytes_written >= 0) {
+ if ((bytes_written == 0) && (priv_cmd.total_len > 0))
+ command[0] = '\0';
+ if (bytes_written >= priv_cmd.total_len) {
+ DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written));
+ bytes_written = priv_cmd.total_len;
+ } else {
+ bytes_written++;
+ }
+ priv_cmd.used_len = bytes_written;
+ if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
+ DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__));
+ ret = -EFAULT;
+ }
+ }
+ else {
+ ret = bytes_written;
+ }
+
+exit:
+ net_os_wake_unlock(net);
+ if (command) {
+ kfree(command);
+ }
+
+ return ret;
+}
+
+int wl_android_init(void)
+{
+ int ret = 0;
+
+#ifdef ENABLE_INSMOD_NO_FW_LOAD
+ dhd_download_fw_on_driverload = FALSE;
+#endif /* ENABLE_INSMOD_NO_FW_LOAD */
+#if defined(CUSTOMER_HW2)
+ if (!iface_name[0]) {
+ memset(iface_name, 0, IFNAMSIZ);
+ bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ);
+ }
+#endif
+
+ wl_netlink_init();
+
+ return ret;
+}
+
+int wl_android_exit(void)
+{
+ int ret = 0;
+ struct io_cfg *cur, *q;
+
+ wl_netlink_deinit();
+
+ list_for_each_entry_safe(cur, q, &miracast_resume_list, list) {
+ list_del(&cur->list);
+ kfree(cur);
+ }
+
+ return ret;
+}
+
+void wl_android_post_init(void)
+{
+
+#ifdef ENABLE_4335BT_WAR
+ bcm_bt_unlock(lock_cookie_wifi);
+ printk("%s: btlock released\n", __FUNCTION__);
+#endif /* ENABLE_4335BT_WAR */
+
+ if (!dhd_download_fw_on_driverload)
+ g_wifi_on = FALSE;
+}
diff --git a/drivers/net/wireless/bcmdhd/wl_android.h b/drivers/net/wireless/bcmdhd/wl_android.h
new file mode 100644
index 000000000000..e925156e5d46
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_android.h
@@ -0,0 +1,77 @@
+/*
+ * Linux cfg80211 driver - Android related functions
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_android.h 513422 2014-11-06 11:06:57Z $
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <wldev_common.h>
+
+/* If any feature uses the Generic Netlink Interface, put it here to enable WL_GENL
+ * automatically
+ */
+#if defined(WL_NAN)
+#define WL_GENL
+#endif
+
+
+
+/**
+ * Android platform dependent functions, feel free to add Android specific functions here
+ * (save the macros in dhd). Please do NOT declare functions that are NOT exposed to dhd
+ * or cfg, define them as static in wl_android.c
+ */
+
+/**
+ * wl_android_init will be called from module init function (dhd_module_init now), similarly
+ * wl_android_exit will be called from module exit function (dhd_module_cleanup now)
+ */
+int wl_android_init(void);
+int wl_android_exit(void);
+void wl_android_post_init(void);
+int wl_android_wifi_on(struct net_device *dev);
+int wl_android_wifi_off(struct net_device *dev);
+int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
+
+s32 wl_netlink_send_msg(int pid, int type, int seq, void *data, size_t size);
+
+/* hostap mac mode */
+#define MACLIST_MODE_DISABLED 0
+#define MACLIST_MODE_DENY 1
+#define MACLIST_MODE_ALLOW 2
+
+/* max number of assoc list */
+#define MAX_NUM_OF_ASSOCLIST 64
+
+/* Bandwidth */
+#define WL_CH_BANDWIDTH_20MHZ 20
+#define WL_CH_BANDWIDTH_40MHZ 40
+#define WL_CH_BANDWIDTH_80MHZ 80
+
+/* max number of mac filter list
+ * restrict max number to 10 as maximum cmd string size is 255
+ */
+#define MAX_NUM_MAC_FILT 10
+
+int wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist);
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
new file mode 100644
index 000000000000..e041dcb63111
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -0,0 +1,14404 @@
+/*
+ * Linux cfg80211 driver
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfg80211.c 662965 2016-11-24 03:53:15Z $
+ */
+/* */
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+#include <linux/kernel.h>
+
+#include <bcmutils.h>
+#include <bcmwifi_channels.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+#include <proto/802.11.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_linux.h>
+#include <dhdioctl.h>
+#include <wlioctl.h>
+#include <dhd_cfg80211.h>
+#ifdef PNO_SUPPORT
+#include <dhd_pno.h>
+#endif /* PNO_SUPPORT */
+
+#include <proto/ethernet.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/wait.h>
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+
+#include <wlioctl.h>
+#include <wldev_common.h>
+#include <wl_cfg80211.h>
+#include <wl_cfgp2p.h>
+#include <wl_android.h>
+
+#ifdef WL_NAN
+#include <wl_cfgnan.h>
+#endif /* WL_NAN */
+#ifdef PROP_TXSTATUS
+#include <dhd_wlfc.h>
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+#include <wl_cfgvendor.h>
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
+#ifdef WL11U
+#if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
+#error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \
+ according to Kernel version and is supported only in Android-JB
+#endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
+#endif /* WL11U */
+
+
+#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+
+
+
+static struct device *cfg80211_parent_dev = NULL;
+/* g_bcm_cfg should be static. Do not change */
+static struct bcm_cfg80211 *g_bcm_cfg = NULL;
+u32 wl_dbg_level = WL_DBG_ERR;
+
+#ifdef VSDB
+/* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
+#define DEFAULT_SLEEP_TIME_VSDB 120
+#define OFF_CHAN_TIME_THRESHOLD_MS 200
+#define AF_RETRY_DELAY_TIME 40
+
+/* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
+#define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg) \
+ do { \
+ if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) || \
+ wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) { \
+ OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB); \
+ } \
+ } while (0)
+#else /* VSDB */
+/* if not VSDB, do nothing */
+#define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)
+#endif /* VSDB */
+
+#ifdef WL_CFG80211_SYNC_GON
+#define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) \
+ (wl_get_drv_status_all(cfg, SENDING_ACT_FRM) || \
+ wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN))
+#else
+#define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) wl_get_drv_status_all(cfg, SENDING_ACT_FRM)
+#endif /* WL_CFG80211_SYNC_GON */
+#define WL_IS_P2P_DEV_EVENT(e) ((e->emsg.ifidx == 0) && \
+ (e->emsg.bsscfgidx == P2PAPI_BSSCFG_DEVICE))
+
+#define COEX_DHCP
+
+#define WLAN_EID_SSID 0
+#define CH_MIN_5G_CHANNEL 34
+#define CH_MIN_2G_CHANNEL 1
+
+
+#ifdef WL_RELMCAST
+enum rmc_event_type {
+ RMC_EVENT_NONE,
+ RMC_EVENT_LEADER_CHECK_FAIL
+};
+#endif /* WL_RELMCAST */
+
+/* This is to override regulatory domains defined in cfg80211 module (reg.c)
+ * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
+ * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
+ * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
+ * All the chnages in world regulatory domain are to be done here.
+ */
+static const struct ieee80211_regdomain brcm_regdom = {
+ .n_reg_rules = 4,
+ .alpha2 = "99",
+ .reg_rules = {
+ /* IEEE 802.11b/g, channels 1..11 */
+ REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
+ /* If any */
+ /* IEEE 802.11 channel 14 - Only JP enables
+ * this and for 802.11b only
+ */
+ REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
+ /* IEEE 802.11a, channel 36..64 */
+ REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
+ /* IEEE 802.11a, channel 100..165 */
+ REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
+};
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
+ (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
+/*
+ * Possible interface combinations supported by driver
+ *
+ * ADHOC Mode - #ADHOC <= 1 on channels = 1
+ * SoftAP Mode - #AP <= 1 on channels = 1
+ * STA + P2P Mode - #STA <= 2, #{P2P-GO, P2P-client} <= 1, #P2P-device <= 1
+ * on channels = 2
+ */
+static const struct ieee80211_iface_limit common_if_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_AP),
+ },
+ {
+ /*
+ * During P2P-GO removal, P2P-GO is first changed to STA and later only
+ * removed. So setting maximum possible number of STA interfaces according
+ * to kernel version.
+ *
+ * less than linux-3.8 - max:3 (wlan0 + p2p0 + group removal of p2p-p2p0-x)
+ * linux-3.8 and above - max:2 (wlan0 + group removal of p2p-wlan0-x)
+ */
+#ifdef WL_ENABLE_P2P_IF
+ .max = 3,
+#else
+ .max = 2,
+#endif /* WL_ENABLE_P2P_IF */
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
+ },
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
+ },
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_ADHOC),
+ },
+};
+#ifdef BCM4330_CHIP
+#define NUM_DIFF_CHANNELS 1
+#else
+#define NUM_DIFF_CHANNELS 2
+#endif
+static const struct ieee80211_iface_combination
+common_iface_combinations[] = {
+ {
+ .num_different_channels = NUM_DIFF_CHANNELS,
+ .max_interfaces = 4,
+ .limits = common_if_limits,
+ .n_limits = ARRAY_SIZE(common_if_limits),
+ },
+};
+#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
+
+/* Data Element Definitions */
+#define WPS_ID_CONFIG_METHODS 0x1008
+#define WPS_ID_REQ_TYPE 0x103A
+#define WPS_ID_DEVICE_NAME 0x1011
+#define WPS_ID_VERSION 0x104A
+#define WPS_ID_DEVICE_PWD_ID 0x1012
+#define WPS_ID_REQ_DEV_TYPE 0x106A
+#define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
+#define WPS_ID_PRIM_DEV_TYPE 0x1054
+
+/* Device Password ID */
+#define DEV_PW_DEFAULT 0x0000
+#define DEV_PW_USER_SPECIFIED 0x0001,
+#define DEV_PW_MACHINE_SPECIFIED 0x0002
+#define DEV_PW_REKEY 0x0003
+#define DEV_PW_PUSHBUTTON 0x0004
+#define DEV_PW_REGISTRAR_SPECIFIED 0x0005
+
+/* Config Methods */
+#define WPS_CONFIG_USBA 0x0001
+#define WPS_CONFIG_ETHERNET 0x0002
+#define WPS_CONFIG_LABEL 0x0004
+#define WPS_CONFIG_DISPLAY 0x0008
+#define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
+#define WPS_CONFIG_INT_NFC_TOKEN 0x0020
+#define WPS_CONFIG_NFC_INTERFACE 0x0040
+#define WPS_CONFIG_PUSHBUTTON 0x0080
+#define WPS_CONFIG_KEYPAD 0x0100
+#define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
+#define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
+#define WPS_CONFIG_VIRT_DISPLAY 0x2008
+#define WPS_CONFIG_PHY_DISPLAY 0x4008
+
+
+#define WL_AKM_SUITE_SHA256_1X 0x000FAC05
+#define WL_AKM_SUITE_SHA256_PSK 0x000FAC06
+#define WL_MFP_CAPABLE 0x1
+#define WL_MFP_REQUIRED 0x2
+
+#ifndef IBSS_COALESCE_ALLOWED
+#define IBSS_COALESCE_ALLOWED 0
+#endif
+
+#ifndef IBSS_INITIAL_SCAN_ALLOWED
+#define IBSS_INITIAL_SCAN_ALLOWED 0
+#endif
+
+#define CUSTOM_RETRY_MASK 0xff000000 /* Mask for retry counter of custom dwell time */
+#define LONG_LISTEN_TIME 2000
+
+#define MAX_SCAN_ABORT_WAIT_CNT 20
+#define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
+
+/*
+ * cfg80211_ops api/callback list
+ */
+static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
+ const struct ether_addr *sa, const struct ether_addr *bssid,
+ u8 **pheader, u32 *body_len, u8 *pbody);
+static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request,
+ struct cfg80211_ssid *this_ssid);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
+#else
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
+static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params);
+static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
+ struct net_device *dev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *dev, const u8 *mac,
+ struct station_info *sinfo);
+#else
+static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *dev, u8 *mac,
+ struct station_info *sinfo);
+#endif
+static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *dev, bool enabled,
+ s32 timeout);
+static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, s32 mbm);
+#else
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+ enum nl80211_tx_power_setting type, s32 dbm);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev, s32 *dbm);
+#else
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev,
+ u8 key_idx, bool unicast, bool multicast);
+static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr,
+ struct key_params *params);
+static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr);
+static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr,
+ void *cookie, void (*callback) (void *cookie,
+ struct key_params *params));
+static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx);
+static s32 wl_cfg80211_resume(struct wiphy *wiphy);
+#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
+ 2, 0))
+static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
+ bcm_struct_cfgdev *cfgdev, u64 cookie);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
+static s32 wl_cfg80211_del_station(
+ struct wiphy *wiphy, struct net_device *ndev,
+ struct station_del_parameters *params);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
+ struct net_device *ndev, const u8* mac_addr);
+#else
+static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
+ struct net_device *ndev, u8* mac_addr);
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
+ struct net_device *dev, const u8 *mac, struct station_parameters *params);
+#else
+static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
+ struct net_device *dev, u8 *mac, struct station_parameters *params);
+#endif
+#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
+static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
+#else
+static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
+#endif
+static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa);
+static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa);
+static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
+ struct net_device *dev);
+#ifdef P2PONEINT
+void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
+#else
+static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
+#endif
+static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
+ struct net_device *ndev, bool aborted, bool fw_abort);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
+static s32
+wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
+ u32 peer_capability, bool initiator, const u8 *data, size_t len);
+#else
+#if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
+static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
+ u32 peer_capability, const u8 *data, size_t len);
+#else
+static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
+ size_t len);
+#endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+static s32
+wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, enum nl80211_tdls_operation oper);
+#else
+static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, enum nl80211_tdls_operation oper);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) */
+#endif
+#ifdef WL_SCHED_SCAN
+static int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev);
+#endif
+chanspec_t wl_chspec_driver_to_host(chanspec_t chanspec);
+
+#if defined(WL_VIRTUAL_APSTA)
+bcm_struct_cfgdev*
+wl_cfg80211_create_iface(struct wiphy *wiphy, enum nl80211_iftype
+ iface_type, u8 *mac_addr, const char *name);
+s32
+wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
+#endif /* defined(WL_VIRTUAL_APSTA) */
+
+s32 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
+ struct net_device *ndev, s32 bsscfg_idx,
+ enum nl80211_iftype iface_type, s32 del, u8 *addr);
+
+/*
+ * event & event Q handlers for cfg80211 interfaces
+ */
+static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg);
+static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg);
+static s32 wl_event_handler(void *data);
+static void wl_init_eq(struct bcm_cfg80211 *cfg);
+static void wl_flush_eq(struct bcm_cfg80211 *cfg);
+static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg);
+static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags);
+static void wl_init_eq_lock(struct bcm_cfg80211 *cfg);
+static void wl_init_event_handler(struct bcm_cfg80211 *cfg);
+static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg);
+static s32 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 type,
+ const wl_event_msg_t *msg, void *data);
+static void wl_put_event(struct wl_event_q *e);
+static void wl_wakeup_event(struct bcm_cfg80211 *cfg);
+static s32 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg,
+ bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
+static s32 wl_notify_roaming_status(struct bcm_cfg80211 *cfg,
+ bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
+static s32 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, bool completed);
+static s32 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data);
+#ifdef WL_SCHED_SCAN
+static s32
+wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+#endif /* WL_SCHED_SCAN */
+#ifdef PNO_SUPPORT
+static s32 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data);
+#endif /* PNO_SUPPORT */
+static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
+ enum wl_status state, bool set);
+
+#ifdef WLTDLS
+static s32 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data);
+#endif /* WLTDLS */
+/*
+ * register/deregister parent device
+ */
+static void wl_cfg80211_clear_parent_dev(void);
+
+/*
+ * ioctl utilites
+ */
+
+/*
+ * cfg80211 set_wiphy_params utilities
+ */
+static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
+static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
+static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
+
+/*
+ * cfg profile utilities
+ */
+static s32 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, s32 item);
+static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item);
+static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev);
+
+/*
+ * cfg80211 connect utilites
+ */
+static s32 wl_set_wpa_version(struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+static s32 wl_set_auth_type(struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+static s32 wl_set_set_cipher(struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+static s32 wl_set_key_mgmt(struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+static s32 wl_set_set_sharedkey(struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev);
+static void wl_ch_to_chanspec(int ch,
+ struct wl_join_params *join_params, size_t *join_params_size);
+
+/*
+ * information element utilities
+ */
+static void wl_rst_ie(struct bcm_cfg80211 *cfg);
+static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v);
+static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size, bool roam);
+static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size);
+static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size);
+static u32 wl_get_ielen(struct bcm_cfg80211 *cfg);
+
+#ifdef WL11U
+bcm_tlv_t *
+wl_cfg80211_find_interworking_ie(u8 *parse, u32 len);
+static s32
+wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
+ uint8 ie_id, uint8 *data, uint8 data_len);
+#endif /* WL11U */
+
+static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
+static void wl_free_wdev(struct bcm_cfg80211 *cfg);
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+static int
+wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
+
+static s32 wl_inform_bss(struct bcm_cfg80211 *cfg);
+static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam);
+static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam);
+#ifdef P2PONEINT
+chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
+#else
+static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
+#endif
+s32 wl_cfg80211_channel_to_freq(u32 channel);
+
+
+static void wl_cfg80211_work_handler(struct work_struct *work);
+static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr,
+ struct key_params *params);
+/*
+ * key indianess swap utilities
+ */
+static void swap_key_from_BE(struct wl_wsec_key *key);
+static void swap_key_to_BE(struct wl_wsec_key *key);
+
+/*
+ * bcm_cfg80211 memory init/deinit utilities
+ */
+static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg);
+static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg);
+
+static void wl_delay(u32 ms);
+
+/*
+ * ibss mode utilities
+ */
+static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev);
+static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg);
+
+/*
+ * link up/down , default configuration utilities
+ */
+static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg);
+static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg);
+static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
+static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e,
+ struct net_device *ndev);
+static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
+static void wl_link_up(struct bcm_cfg80211 *cfg);
+static void wl_link_down(struct bcm_cfg80211 *cfg);
+static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype);
+static void wl_init_conf(struct wl_conf *conf);
+static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
+ struct net_device* ndev);
+
+int wl_cfg80211_get_ioctl_version(void);
+
+/*
+ * find most significant bit set
+ */
+static __used u32 wl_find_msb(u16 bit16);
+
+/*
+ * rfkill support
+ */
+static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup);
+static int wl_rfkill_set(void *data, bool blocked);
+#ifdef DEBUGFS_CFG80211
+static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg);
+static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg);
+#endif
+
+static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
+ int nprobes, int *out_params_size);
+static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role);
+
+#ifdef WL_CFG80211_ACL
+/* ACL */
+static int wl_cfg80211_set_mac_acl(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ const struct cfg80211_acl_data *acl);
+#endif /* WL_CFG80211_ACL */
+
+/*
+ * Some external functions, TODO: move them to dhd_linux.h
+ */
+int dhd_add_monitor(char *name, struct net_device **new_ndev);
+int dhd_del_monitor(struct net_device *ndev);
+int dhd_monitor_init(void *dhd_pub);
+int dhd_monitor_uninit(void);
+int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
+
+
+static int wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const struct ether_addr *bssid);
+
+static s32 wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len, struct parsed_vndr_ies *vndr_ies);
+
+
+#define RETURN_EIO_IF_NOT_UP(wlpriv) \
+do { \
+ struct net_device *checkSysUpNDev = bcmcfg_to_prmry_ndev(wlpriv); \
+ if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) { \
+ WL_INFO(("device is not ready\n")); \
+ return -EIO; \
+ } \
+} while (0)
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
+#define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
+ cfg80211_disconnected(dev, reason, ie, len, gfp);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
+#define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
+ cfg80211_disconnected(dev, reason, ie, len, loc_gen, gfp);
+#endif
+
+#ifdef RSSI_OFFSET
+static s32 wl_rssi_offset(s32 rssi)
+{
+ rssi += RSSI_OFFSET;
+ if (rssi > 0)
+ rssi = 0;
+ return rssi;
+}
+#else
+#define wl_rssi_offset(x) x
+#endif
+
+#define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
+ (akm) == RSN_AKM_UNSPECIFIED || \
+ (akm) == RSN_AKM_PSK)
+
+
+extern int dhd_wait_pend8021x(struct net_device *dev);
+#ifdef PROP_TXSTATUS_VSDB
+extern int disable_proptx;
+#endif /* PROP_TXSTATUS_VSDB */
+static s32
+wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+const wl_event_msg_t *e, void *data);
+#if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
+ 0)))
+struct chan_info {
+ int freq;
+ int chan_type;
+};
+#endif
+
+
+#if (WL_DBG_LEVEL > 0)
+#define WL_DBG_ESTR_MAX 50
+static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
+ "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
+ "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
+ "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
+ "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
+ "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
+ "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
+ "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
+ "PFN_NET_LOST",
+ "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
+ "IBSS_ASSOC",
+ "RADIO", "PSM_WATCHDOG", "WLC_E_CCX_ASSOC_START", "WLC_E_CCX_ASSOC_ABORT",
+ "PROBREQ_MSG",
+ "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
+ "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
+ "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
+ "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
+ "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
+ "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
+ "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
+ "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
+ "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
+ "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
+ "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
+};
+#endif /* WL_DBG_LEVEL */
+
+#define CHAN2G(_channel, _freq, _flags) { \
+ .band = NL80211_BAND_2GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+#define CHAN5G(_channel, _flags) { \
+ .band = NL80211_BAND_5GHZ, \
+ .center_freq = 5000 + (5 * (_channel)), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
+#define RATETAB_ENT(_rateid, _flags) \
+ { \
+ .bitrate = RATE_TO_BASE100KBPS(_rateid), \
+ .hw_value = (_rateid), \
+ .flags = (_flags), \
+ }
+
+static struct ieee80211_rate __wl_rates[] = {
+ RATETAB_ENT(DOT11_RATE_1M, 0),
+ RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_6M, 0),
+ RATETAB_ENT(DOT11_RATE_9M, 0),
+ RATETAB_ENT(DOT11_RATE_12M, 0),
+ RATETAB_ENT(DOT11_RATE_18M, 0),
+ RATETAB_ENT(DOT11_RATE_24M, 0),
+ RATETAB_ENT(DOT11_RATE_36M, 0),
+ RATETAB_ENT(DOT11_RATE_48M, 0),
+ RATETAB_ENT(DOT11_RATE_54M, 0)
+};
+
+#define wl_a_rates (__wl_rates + 4)
+#define wl_a_rates_size 8
+#define wl_g_rates (__wl_rates + 0)
+#define wl_g_rates_size 12
+
+static struct ieee80211_channel __wl_2ghz_channels[] = {
+ CHAN2G(1, 2412, 0),
+ CHAN2G(2, 2417, 0),
+ CHAN2G(3, 2422, 0),
+ CHAN2G(4, 2427, 0),
+ CHAN2G(5, 2432, 0),
+ CHAN2G(6, 2437, 0),
+ CHAN2G(7, 2442, 0),
+ CHAN2G(8, 2447, 0),
+ CHAN2G(9, 2452, 0),
+ CHAN2G(10, 2457, 0),
+ CHAN2G(11, 2462, 0),
+ CHAN2G(12, 2467, 0),
+ CHAN2G(13, 2472, 0),
+ CHAN2G(14, 2484, 0)
+};
+
+static struct ieee80211_channel __wl_5ghz_a_channels[] = {
+ CHAN5G(34, 0), CHAN5G(36, 0),
+ CHAN5G(38, 0), CHAN5G(40, 0),
+ CHAN5G(42, 0), CHAN5G(44, 0),
+ CHAN5G(46, 0), CHAN5G(48, 0),
+ CHAN5G(52, 0), CHAN5G(56, 0),
+ CHAN5G(60, 0), CHAN5G(64, 0),
+ CHAN5G(100, 0), CHAN5G(104, 0),
+ CHAN5G(108, 0), CHAN5G(112, 0),
+ CHAN5G(116, 0), CHAN5G(120, 0),
+ CHAN5G(124, 0), CHAN5G(128, 0),
+ CHAN5G(132, 0), CHAN5G(136, 0),
+ CHAN5G(140, 0), CHAN5G(144, 0),
+ CHAN5G(149, 0), CHAN5G(153, 0),
+ CHAN5G(157, 0), CHAN5G(161, 0),
+ CHAN5G(165, 0)
+};
+
+static struct ieee80211_supported_band __wl_band_2ghz = {
+ .band = NL80211_BAND_2GHZ,
+ .channels = __wl_2ghz_channels,
+ .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
+ .bitrates = wl_g_rates,
+ .n_bitrates = wl_g_rates_size
+};
+
+static struct ieee80211_supported_band __wl_band_5ghz_a = {
+ .band = NL80211_BAND_5GHZ,
+ .channels = __wl_5ghz_a_channels,
+ .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
+ .bitrates = wl_a_rates,
+ .n_bitrates = wl_a_rates_size
+};
+
+static const u32 __wl_cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WLAN_CIPHER_SUITE_AES_CMAC,
+};
+
+#ifdef WL_SUPPORT_ACS
+/*
+ * The firmware code required for this feature to work is currently under
+ * BCMINTERNAL flag. In future if this is to enabled we need to bring the
+ * required firmware code out of the BCMINTERNAL flag.
+ */
+struct wl_dump_survey {
+ u32 obss;
+ u32 ibss;
+ u32 no_ctg;
+ u32 no_pckt;
+ u32 tx;
+ u32 idle;
+};
+#endif /* WL_SUPPORT_ACS */
+
+#ifdef WL_SUPPORT_ACS
+uint8 g_hostap_chan_count;
+uint16 g_hostap_chan_cache[50];
+#endif /* WL_SUPPORT_ACS */
+
+
+#if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
+static int maxrxpktglom = 0;
+#endif
+
+/* IOCtl version read from targeted driver */
+static int ioctl_version;
+#ifdef DEBUGFS_CFG80211
+#define S_SUBLOGLEVEL 20
+static const struct {
+ u32 log_level;
+ char *sublogname;
+} sublogname_map[] = {
+ {WL_DBG_ERR, "ERR"},
+ {WL_DBG_INFO, "INFO"},
+ {WL_DBG_DBG, "DBG"},
+ {WL_DBG_SCAN, "SCAN"},
+ {WL_DBG_TRACE, "TRACE"},
+ {WL_DBG_P2P_ACTION, "P2PACTION"}
+};
+#endif
+
+
+static void wl_add_remove_pm_enable_work(struct bcm_cfg80211 *cfg, bool add_remove,
+ enum wl_handler_del_type type)
+{
+ if (cfg == NULL)
+ return;
+
+ if (cfg->pm_enable_work_on) {
+ if (add_remove) {
+ schedule_delayed_work(&cfg->pm_enable_work,
+ msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
+ } else {
+ cancel_delayed_work_sync(&cfg->pm_enable_work);
+ switch (type) {
+ case WL_HANDLER_MAINTAIN:
+ schedule_delayed_work(&cfg->pm_enable_work,
+ msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
+ break;
+ case WL_HANDLER_PEND:
+ schedule_delayed_work(&cfg->pm_enable_work,
+ msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT*2));
+ break;
+ case WL_HANDLER_DEL:
+ default:
+ cfg->pm_enable_work_on = false;
+ break;
+ }
+ }
+ }
+}
+
+/* Return a new chanspec given a legacy chanspec
+ * Returns INVCHANSPEC on error
+ */
+static chanspec_t
+wl_chspec_from_legacy(chanspec_t legacy_chspec)
+{
+ chanspec_t chspec;
+
+ /* get the channel number */
+ chspec = LCHSPEC_CHANNEL(legacy_chspec);
+
+ /* convert the band */
+ if (LCHSPEC_IS2G(legacy_chspec)) {
+ chspec |= WL_CHANSPEC_BAND_2G;
+ } else {
+ chspec |= WL_CHANSPEC_BAND_5G;
+ }
+
+ /* convert the bw and sideband */
+ if (LCHSPEC_IS20(legacy_chspec)) {
+ chspec |= WL_CHANSPEC_BW_20;
+ } else {
+ chspec |= WL_CHANSPEC_BW_40;
+ if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
+ chspec |= WL_CHANSPEC_CTL_SB_L;
+ } else {
+ chspec |= WL_CHANSPEC_CTL_SB_U;
+ }
+ }
+
+ if (wf_chspec_malformed(chspec)) {
+ WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
+ chspec));
+ return INVCHANSPEC;
+ }
+
+ return chspec;
+}
+
+/* Return a legacy chanspec given a new chanspec
+ * Returns INVCHANSPEC on error
+ */
+static chanspec_t
+wl_chspec_to_legacy(chanspec_t chspec)
+{
+ chanspec_t lchspec;
+
+ if (wf_chspec_malformed(chspec)) {
+ WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
+ chspec));
+ return INVCHANSPEC;
+ }
+
+ /* get the channel number */
+ lchspec = CHSPEC_CHANNEL(chspec);
+
+ /* convert the band */
+ if (CHSPEC_IS2G(chspec)) {
+ lchspec |= WL_LCHANSPEC_BAND_2G;
+ } else {
+ lchspec |= WL_LCHANSPEC_BAND_5G;
+ }
+
+ /* convert the bw and sideband */
+ if (CHSPEC_IS20(chspec)) {
+ lchspec |= WL_LCHANSPEC_BW_20;
+ lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
+ } else if (CHSPEC_IS40(chspec)) {
+ lchspec |= WL_LCHANSPEC_BW_40;
+ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
+ lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
+ } else {
+ lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
+ }
+ } else {
+ /* cannot express the bandwidth */
+ char chanbuf[CHANSPEC_STR_LEN];
+ WL_ERR((
+ "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
+ "to pre-11ac format\n",
+ wf_chspec_ntoa(chspec, chanbuf), chspec));
+ return INVCHANSPEC;
+ }
+
+ return lchspec;
+}
+
+/* given a chanspec value, do the endian and chanspec version conversion to
+ * a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+chanspec_t
+wl_chspec_host_to_driver(chanspec_t chanspec)
+{
+ if (ioctl_version == 1) {
+ chanspec = wl_chspec_to_legacy(chanspec);
+ if (chanspec == INVCHANSPEC) {
+ return chanspec;
+ }
+ }
+ chanspec = htodchanspec(chanspec);
+
+ return chanspec;
+}
+
+/* given a channel value, do the endian and chanspec version conversion to
+ * a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+chanspec_t
+wl_ch_host_to_driver(u16 channel)
+{
+
+ chanspec_t chanspec;
+
+ chanspec = channel & WL_CHANSPEC_CHAN_MASK;
+
+ if (channel <= CH_MAX_2G_CHANNEL)
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ else
+ chanspec |= WL_CHANSPEC_BAND_5G;
+
+ chanspec |= WL_CHANSPEC_BW_20;
+ chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+
+ return wl_chspec_host_to_driver(chanspec);
+}
+
+/* given a chanspec value from the driver, do the endian and chanspec version conversion to
+ * a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+chanspec_t
+wl_chspec_driver_to_host(chanspec_t chanspec)
+{
+ chanspec = dtohchanspec(chanspec);
+ if (ioctl_version == 1) {
+ chanspec = wl_chspec_from_legacy(chanspec);
+ }
+
+ return chanspec;
+}
+
+/*
+ * convert ASCII string to MAC address (colon-delimited format)
+ * eg: 00:11:22:33:44:55
+ */
+int
+wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
+{
+ char *c = NULL;
+ int count = 0;
+
+ memset(n, 0, ETHER_ADDR_LEN);
+ for (;;) {
+ n->octet[count++] = (uint8)simple_strtoul(a, &c, 16);
+ if (!*c++ || count == ETHER_ADDR_LEN)
+ break;
+ a = c;
+ }
+ return (count == ETHER_ADDR_LEN);
+}
+
+/* convert hex string buffer to binary */
+int
+wl_cfg80211_hex_str_to_bin(unsigned char *data, int dlen, char *str)
+{
+ int count, slen;
+ int hvalue;
+ char tmp[3] = {0};
+ char *ptr = str, *endp = NULL;
+
+ if (!data || !str || !dlen) {
+ WL_DBG((" passed buffer is empty \n"));
+ return 0;
+ }
+
+ slen = strlen(str);
+ if (dlen * 2 < slen) {
+ WL_DBG((" destination buffer too short \n"));
+ return 0;
+ }
+
+ if (slen % 2) {
+ WL_DBG((" source buffer is of odd length \n"));
+ return 0;
+ }
+
+ for (count = 0; count < slen; count += 2) {
+ memcpy(tmp, ptr, 2);
+ hvalue = simple_strtol(tmp, &endp, 16);
+ if (*endp != '\0') {
+ WL_DBG((" non hexadecimal character encountered \n"));
+ return 0;
+ }
+ *data++ = (unsigned char)hvalue;
+ ptr += 2;
+ }
+
+ return (slen / 2);
+}
+
+/* There isn't a lot of sense in it, but you can transmit anything you like */
+static const struct ieee80211_txrx_stypes
+wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+ [NL80211_IFTYPE_ADHOC] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_STATION] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_AP] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_AP_VLAN] = {
+ /* copy AP */
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_P2P_CLIENT] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_P2P_GO] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ [NL80211_IFTYPE_P2P_DEVICE] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+#endif /* WL_CFG80211_P2P_DEV_IF */
+};
+
+static void swap_key_from_BE(struct wl_wsec_key *key)
+{
+ key->index = htod32(key->index);
+ key->len = htod32(key->len);
+ key->algo = htod32(key->algo);
+ key->flags = htod32(key->flags);
+ key->rxiv.hi = htod32(key->rxiv.hi);
+ key->rxiv.lo = htod16(key->rxiv.lo);
+ key->iv_initialized = htod32(key->iv_initialized);
+}
+
+static void swap_key_to_BE(struct wl_wsec_key *key)
+{
+ key->index = dtoh32(key->index);
+ key->len = dtoh32(key->len);
+ key->algo = dtoh32(key->algo);
+ key->flags = dtoh32(key->flags);
+ key->rxiv.hi = dtoh32(key->rxiv.hi);
+ key->rxiv.lo = dtoh16(key->rxiv.lo);
+ key->iv_initialized = dtoh32(key->iv_initialized);
+}
+
+/* Dump the contents of the encoded wps ie buffer and get pbc value */
+static void
+wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
+{
+ #define WPS_IE_FIXED_LEN 6
+ u16 len;
+ u8 *subel = NULL;
+ u16 subelt_id;
+ u16 subelt_len;
+ u16 val;
+ u8 *valptr = (uint8*) &val;
+ if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
+ WL_ERR(("invalid argument : NULL\n"));
+ return;
+ }
+ len = (u16)wps_ie[TLV_LEN_OFF];
+
+ if (len > wps_ie_len) {
+ WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
+ return;
+ }
+ WL_DBG(("wps_ie len=%d\n", len));
+ len -= 4; /* for the WPS IE's OUI, oui_type fields */
+ subel = wps_ie + WPS_IE_FIXED_LEN;
+ while (len >= 4) { /* must have attr id, attr len fields */
+ valptr[0] = *subel++;
+ valptr[1] = *subel++;
+ subelt_id = HTON16(val);
+
+ valptr[0] = *subel++;
+ valptr[1] = *subel++;
+ subelt_len = HTON16(val);
+
+ len -= 4; /* for the attr id, attr len fields */
+
+ if (len < subelt_len) {
+ WL_ERR(("not enough data, len %d, subelt_len %d\n", len,
+ subelt_len));
+ break;
+ }
+ len -= subelt_len; /* for the remaining fields in this attribute */
+
+ WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
+ subel, subelt_id, subelt_len));
+
+ if (subelt_id == WPS_ID_VERSION) {
+ WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel));
+ } else if (subelt_id == WPS_ID_REQ_TYPE) {
+ WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel));
+ } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
+ valptr[0] = *subel;
+ valptr[1] = *(subel + 1);
+ WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
+ } else if (subelt_id == WPS_ID_DEVICE_NAME) {
+ char devname[100];
+ int namelen = MIN(subelt_len, (sizeof(devname) - 1));
+
+ if (namelen) {
+ memcpy(devname, subel, namelen);
+ devname[namelen] = '\0';
+ /* Printing len as rx'ed in the IE */
+ WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
+ devname, subelt_len));
+ }
+ } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
+ valptr[0] = *subel;
+ valptr[1] = *(subel + 1);
+ WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
+ *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
+ } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
+ valptr[0] = *subel;
+ valptr[1] = *(subel + 1);
+ WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
+ valptr[0] = *(subel + 6);
+ valptr[1] = *(subel + 7);
+ WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
+ } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
+ valptr[0] = *subel;
+ valptr[1] = *(subel + 1);
+ WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
+ valptr[0] = *(subel + 6);
+ valptr[1] = *(subel + 7);
+ WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
+ } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
+ valptr[0] = *subel;
+ valptr[1] = *(subel + 1);
+ WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
+ ": cat=%u\n", HTON16(val)));
+ } else {
+ WL_DBG((" unknown attr 0x%x\n", subelt_id));
+ }
+
+ subel += subelt_len;
+ }
+}
+
+s32 wl_set_tx_power(struct net_device *dev,
+ enum nl80211_tx_power_setting type, s32 dbm)
+{
+ s32 err = 0;
+ s32 disable = 0;
+ s32 txpwrqdbm;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+#ifdef TEST_TX_POWER_CONTROL
+ char *tmppwr_str;
+#endif /* TEST_TX_POWER_CONTROL */
+
+ /* Make sure radio is off or on as far as software is concerned */
+ disable = WL_RADIO_SW_DISABLE << 16;
+ disable = htod32(disable);
+ err = wldev_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable), true);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
+ return err;
+ }
+
+ if (dbm > 0xffff)
+ dbm = 0xffff;
+ txpwrqdbm = dbm * 4;
+
+ err = wldev_iovar_setbuf_bsscfg(dev, "qtxpower", (void *)&txpwrqdbm,
+ sizeof(txpwrqdbm), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
+ &cfg->ioctl_buf_sync);
+
+ if (unlikely(err))
+ WL_ERR(("qtxpower error (%d)\n", err));
+ else
+ WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm, txpwrqdbm));
+
+ return err;
+}
+
+s32 wl_get_tx_power(struct net_device *dev, s32 *dbm)
+{
+ s32 err = 0;
+ s32 txpwrdbm;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ err = wldev_iovar_getint(dev, "qtxpower", &txpwrdbm);
+ err = wldev_iovar_getbuf_bsscfg(dev, "qtxpower",
+ NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ memcpy(&txpwrdbm, cfg->ioctl_buf, sizeof(txpwrdbm));
+ txpwrdbm = dtoh32(txpwrdbm);
+ *dbm = (txpwrdbm & ~WL_TXPWR_OVERRIDE) / 4;
+
+ WL_INFO(("dBm=%d, txpwrdbm=0x%x\n", *dbm, txpwrdbm));
+
+ return err;
+}
+
+#ifdef P2PONEINT
+chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
+#else
+static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
+#endif
+{
+ chanspec_t chspec;
+ int err = 0;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
+ struct ether_addr bssid;
+ struct wl_bss_info *bss = NULL;
+
+ if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
+ int chspc;
+ /* STA interface is not associated. So start the new interface on a temp
+ * channel . Later proper channel will be applied by the above framework
+ * via set_channel (cfg80211 API).
+ */
+ WL_DBG(("Not associated. Return first channel from supported channel list. \n"));
+ err = wldev_iovar_getint(dev, "chanspec", &chspc);
+ if (!err) {
+ return chspc;
+ } else {
+
+ return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
+ }
+ }
+
+ *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+ if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf,
+ WL_EXTRA_BUF_MAX, false))) {
+ WL_ERR(("Failed to get associated bss info, use temp channel \n"));
+ chspec = wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
+ }
+ else {
+ bss = (struct wl_bss_info *) (cfg->extra_buf + 4);
+ chspec = bss->chanspec;
+
+ WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
+ }
+ return chspec;
+}
+
+static bcm_struct_cfgdev *
+wl_cfg80211_add_monitor_if(char *name)
+{
+#if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
+ WL_INFO(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
+ return ERR_PTR(-EOPNOTSUPP);
+#else
+ struct net_device* ndev = NULL;
+
+ dhd_add_monitor(name, &ndev);
+ WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
+ return ndev_to_cfgdev(ndev);
+#endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
+}
+
+static bcm_struct_cfgdev *
+wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ const char *name,
+#else
+ char *name,
+#endif /* WL_CFG80211_P2P_DEV_IF */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+ unsigned char name_assign_type,
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ s32 err;
+ s32 timeout = -1;
+ s32 wlif_type = -1;
+ s32 mode = 0;
+ s32 val = 0;
+ s32 dhd_mode = 0;
+ chanspec_t chspec;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *primary_ndev;
+ struct net_device *new_ndev;
+ struct ether_addr primary_mac;
+#ifdef PROP_TXSTATUS_VSDB
+ s32 up = 1;
+ dhd_pub_t *dhd;
+ bool enabled;
+#endif /* PROP_TXSTATUS_VSDB */
+#ifdef WL_VIRTUAL_APSTA
+ bcm_struct_cfgdev *new_cfgdev;
+#endif /* WL_VIRTUAL_APSTA */
+
+ if (!cfg)
+ return ERR_PTR(-EINVAL);
+
+#ifdef PROP_TXSTATUS_VSDB
+ dhd = (dhd_pub_t *)(cfg->pub);
+#endif /* PROP_TXSTATUS_VSDB */
+
+
+ /* Use primary I/F for sending cmds down to firmware */
+ primary_ndev = bcmcfg_to_prmry_ndev(cfg);
+
+ if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
+ WL_ERR(("device is not ready\n"));
+ return ERR_PTR(-ENODEV);
+ }
+
+ WL_DBG(("if name: %s, type: %d\n", name, type));
+ switch (type) {
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_MESH_POINT:
+ WL_ERR(("Unsupported interface type\n"));
+ mode = WL_MODE_IBSS;
+ return NULL;
+ case NL80211_IFTYPE_MONITOR:
+ return wl_cfg80211_add_monitor_if((char *)name);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ case NL80211_IFTYPE_P2P_DEVICE:
+ return wl_cfgp2p_add_p2p_disc_if(cfg);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ case NL80211_IFTYPE_STATION:
+#ifdef WL_VIRTUAL_APSTA
+ if (!name) {
+ WL_ERR(("Interface name not provided \n"));
+ return ERR_PTR(-ENODEV);
+ }
+
+ if (wl_cfgp2p_vif_created(cfg)) {
+ WL_ERR(("Could not create new iface."
+ "Already one p2p interface is running"));
+ return ERR_PTR(-ENODEV);
+ }
+ new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
+ NL80211_IFTYPE_STATION, NULL, name);
+ if (!new_cfgdev)
+ return ERR_PTR(-ENOMEM);
+ else
+ return new_cfgdev;
+#endif /* WL_VIRTUAL_APSTA */
+ case NL80211_IFTYPE_P2P_CLIENT:
+ wlif_type = WL_P2P_IF_CLIENT;
+ mode = WL_MODE_BSS;
+ break;
+ case NL80211_IFTYPE_P2P_GO:
+ case NL80211_IFTYPE_AP:
+ WL_DBG(("Add virtual interface for AP (%d)\n", type));
+ wlif_type = WL_P2P_IF_GO;
+ mode = WL_MODE_AP;
+ break;
+ default:
+ WL_ERR(("Unsupported interface type\n"));
+ return NULL;
+ break;
+ }
+
+ if (!name) {
+ WL_ERR(("name is NULL\n"));
+ return NULL;
+ }
+ if (cfg->p2p_supported && (wlif_type != -1)) {
+ ASSERT(cfg->p2p); /* ensure expectation of p2p initialization */
+
+#ifdef PROP_TXSTATUS_VSDB
+ if (!dhd)
+ return ERR_PTR(-ENODEV);
+#endif /* PROP_TXSTATUS_VSDB */
+ if (!cfg->p2p)
+ return ERR_PTR(-ENODEV);
+
+ if (cfg->p2p && !cfg->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
+ p2p_on(cfg) = true;
+ wl_cfgp2p_set_firm_p2p(cfg);
+ wl_cfgp2p_init_discovery(cfg);
+ get_primary_mac(cfg, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac,
+ &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
+ }
+
+ memset(cfg->p2p->vir_ifname, 0, IFNAMSIZ);
+ strncpy(cfg->p2p->vir_ifname, name, IFNAMSIZ - 1);
+
+ wl_cfg80211_scan_abort(cfg);
+#ifdef PROP_TXSTATUS_VSDB
+ if (!cfg->wlfc_on && !disable_proptx) {
+ dhd_wlfc_get_enable(dhd, &enabled);
+ if (!enabled && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
+ dhd->op_mode != DHD_FLAG_IBSS_MODE) {
+ dhd_wlfc_init(dhd);
+ err = wldev_ioctl(primary_ndev, WLC_UP, &up, sizeof(s32), true);
+ if (err < 0)
+ WL_ERR(("WLC_UP return err:%d\n", err));
+ }
+ cfg->wlfc_on = true;
+ }
+#endif /* PROP_TXSTATUS_VSDB */
+
+ /* In concurrency case, STA may be already associated in a particular channel.
+ * so retrieve the current channel of primary interface and then start the virtual
+ * interface on that.
+ */
+ chspec = wl_cfg80211_get_shared_freq(wiphy);
+
+ /* For P2P mode, use P2P-specific driver features to create the
+ * bss: "cfg p2p_ifadd"
+ */
+ wl_set_p2p_status(cfg, IF_ADDING);
+ memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
+ if (wlif_type == WL_P2P_IF_GO)
+ wldev_iovar_setint(primary_ndev, "mpc", 0);
+ err = wl_cfgp2p_ifadd(cfg, &cfg->p2p->int_addr, htod32(wlif_type), chspec);
+ if (unlikely(err)) {
+ wl_clr_p2p_status(cfg, IF_ADDING);
+ WL_ERR((" virtual iface add failed (%d) \n", err));
+ return ERR_PTR(-ENOMEM);
+ }
+
+ timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
+ (wl_get_p2p_status(cfg, IF_ADDING) == false),
+ msecs_to_jiffies(MAX_WAIT_TIME));
+ if (timeout == 0) {
+ WL_ERR(("%d timeout waiting for IF_ADD.\n", __LINE__));
+ }
+
+ if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
+ struct wireless_dev *vwdev;
+ int pm_mode = PM_ENABLE;
+ wl_if_event_info *event = &cfg->if_event_info;
+
+ /* IF_ADD event has come back, we can proceed to to register
+ * the new interface now, use the interface name provided by caller (thus
+ * ignore the one from wlc)
+ */
+ strncpy(cfg->if_event_info.name, name, IFNAMSIZ - 1);
+ new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, cfg->p2p->vir_ifname,
+ event->mac, event->bssidx, event->name);
+ if (new_ndev == NULL)
+ goto fail;
+
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION) = new_ndev;
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION) = event->bssidx;
+ vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
+ if (unlikely(!vwdev)) {
+ WL_ERR(("Could not allocate wireless device\n"));
+ goto fail;
+ }
+ vwdev->wiphy = cfg->wdev->wiphy;
+ WL_INFO(("virtual interface(%s) is created\n", cfg->p2p->vir_ifname));
+ vwdev->iftype = type;
+ vwdev->netdev = new_ndev;
+ new_ndev->ieee80211_ptr = vwdev;
+ SET_NETDEV_DEV(new_ndev, wiphy_dev(vwdev->wiphy));
+ wl_set_drv_status(cfg, READY, new_ndev);
+ wl_set_mode_by_netdev(cfg, new_ndev, mode);
+
+ if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
+ wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
+ goto fail;
+ }
+ wl_alloc_netinfo(cfg, new_ndev, vwdev, mode, pm_mode, event->bssidx);
+ val = 1;
+ /* Disable firmware roaming for P2P interface */
+ wldev_iovar_setint(new_ndev, "roam_off", val);
+
+ if (mode != WL_MODE_AP)
+ wldev_iovar_setint(new_ndev, "buf_key_b4_m4", 1);
+
+ WL_ERR((" virtual interface(%s) is "
+ "created net attach done\n", cfg->p2p->vir_ifname));
+ if (mode == WL_MODE_AP)
+ wl_set_drv_status(cfg, CONNECTED, new_ndev);
+ if (type == NL80211_IFTYPE_P2P_CLIENT)
+ dhd_mode = DHD_FLAG_P2P_GC_MODE;
+ else if (type == NL80211_IFTYPE_P2P_GO)
+ dhd_mode = DHD_FLAG_P2P_GO_MODE;
+ DNGL_FUNC(dhd_cfg80211_set_p2p_info, (cfg, dhd_mode));
+ /* reinitialize completion to clear previous count */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
+ INIT_COMPLETION(cfg->iface_disable);
+#else
+ init_completion(&cfg->iface_disable);
+#endif
+ return ndev_to_cfgdev(new_ndev);
+ } else {
+ wl_clr_p2p_status(cfg, IF_ADDING);
+ WL_ERR((" virtual interface(%s) is not created \n", cfg->p2p->vir_ifname));
+
+ WL_ERR(("left timeout : %d\n", timeout));
+ WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg, IF_ADDING)));
+ WL_ERR(("event valid : %d\n", cfg->if_event_info.valid));
+
+ wl_clr_p2p_status(cfg, GO_NEG_PHASE);
+ wl_set_p2p_status(cfg, IF_DELETING);
+
+ err = wl_cfgp2p_ifdel(cfg, &cfg->p2p->int_addr);
+ if (err == BCME_OK) {
+ timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
+ (wl_get_p2p_status(cfg, IF_DELETING) == false),
+ msecs_to_jiffies(MAX_WAIT_TIME));
+ if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
+ cfg->if_event_info.valid) {
+ WL_ERR(("IFDEL operation done\n"));
+ } else {
+ WL_ERR(("IFDEL didn't complete properly\n"));
+ err = BCME_ERROR;
+ }
+ }
+ if (err != BCME_OK) {
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+
+ WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
+ err, ndev->name));
+ net_os_send_hang_message(ndev);
+ }
+
+ memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION) = -1;
+#ifdef PROP_TXSTATUS_VSDB
+ dhd_wlfc_get_enable(dhd, &enabled);
+ if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
+ dhd->op_mode != DHD_FLAG_IBSS_MODE) {
+ dhd_wlfc_deinit(dhd);
+ cfg->wlfc_on = false;
+ }
+#endif /* PROP_TXSTATUS_VSDB */
+ }
+ }
+
+fail:
+ if (wlif_type == WL_P2P_IF_GO)
+ wldev_iovar_setint(primary_ndev, "mpc", 1);
+ return ERR_PTR(-ENODEV);
+}
+
+static s32
+wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
+{
+ struct net_device *dev = NULL;
+ struct ether_addr p2p_mac;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 timeout = -1;
+ s32 ret = 0;
+ s32 index = -1;
+#ifdef CUSTOM_SET_CPUCORE
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+#endif /* CUSTOM_SET_CPUCORE */
+ WL_DBG(("Enter\n"));
+
+#ifdef CUSTOM_SET_CPUCORE
+ dhd->chan_isvht80 &= ~DHD_FLAG_P2P_MODE;
+ if (!(dhd->chan_isvht80))
+ dhd_set_cpucore(dhd, FALSE);
+#endif /* CUSTOM_SET_CPUCORE */
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
+ return wl_cfgp2p_del_p2p_disc_if(cfgdev, cfg);
+ }
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+#ifdef WL_VIRTUAL_APSTA
+ if (cfgdev == cfg->bss_cfgdev) {
+ return wl_cfg80211_del_iface(wiphy, cfgdev);
+ }
+#endif /* WL_VIRTUAL_APSTA */
+ if ((index = wl_get_bssidx_by_wdev(cfg, ndev_to_wdev(dev))) < 0) {
+ WL_ERR(("Find p2p index from wdev failed\n"));
+ return BCME_ERROR;
+ }
+ if (cfg->p2p_supported) {
+ memcpy(p2p_mac.octet, cfg->p2p->int_addr.octet, ETHER_ADDR_LEN);
+
+ /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
+ */
+ WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
+ wl_clr_p2p_status(cfg, GO_NEG_PHASE);
+ if (wl_cfgp2p_vif_created(cfg)) {
+ if (wl_get_drv_status(cfg, SCANNING, dev)) {
+ wl_notify_escan_complete(cfg, dev, true, true);
+ }
+ wldev_iovar_setint(dev, "mpc", 1);
+ /* Delete pm_enable_work */
+ wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_DEL);
+
+ /* for GC */
+ if (wl_get_drv_status(cfg, DISCONNECTING, dev) &&
+ (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)) {
+ WL_ERR(("Wait for Link Down event for GC !\n"));
+ wait_for_completion_timeout
+ (&cfg->iface_disable, msecs_to_jiffies(500));
+ }
+
+ memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
+ wl_set_p2p_status(cfg, IF_DELETING);
+ DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (cfg));
+
+ /* for GO */
+ if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
+ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
+ /* disable interface before bsscfg free */
+ ret = wl_cfgp2p_ifdisable(cfg, &p2p_mac);
+ /* if fw doesn't support "ifdis",
+ do not wait for link down of ap mode
+ */
+ if (ret == 0) {
+ WL_ERR(("Wait for Link Down event for GO !!!\n"));
+ wait_for_completion_timeout(&cfg->iface_disable,
+ msecs_to_jiffies(500));
+ } else if (ret != BCME_UNSUPPORTED) {
+ msleep(300);
+ }
+ }
+ wl_cfg80211_clear_per_bss_ies(cfg, index);
+
+ if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)
+ wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
+
+ /* delete interface after link down */
+ ret = wl_cfgp2p_ifdel(cfg, &p2p_mac);
+
+ if (ret != BCME_OK) {
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+
+ WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
+ ret, ndev->name));
+ #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
+ net_os_send_hang_message(ndev);
+ #endif
+ } else {
+ /* Wait for IF_DEL operation to be finished */
+ timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
+ (wl_get_p2p_status(cfg, IF_DELETING) == false),
+ msecs_to_jiffies(MAX_WAIT_TIME));
+ if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
+ cfg->if_event_info.valid) {
+
+ WL_DBG(("IFDEL operation done\n"));
+ wl_cfg80211_handle_ifdel(cfg, &cfg->if_event_info, dev);
+ } else {
+ WL_ERR(("IFDEL didn't complete properly\n"));
+ }
+ }
+
+ ret = dhd_del_monitor(dev);
+ if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
+ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t *)(cfg->pub));
+ }
+ }
+ }
+ return ret;
+}
+
+static s32
+wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ s32 ap = 0;
+ s32 infra = 0;
+ s32 ibss = 0;
+ s32 wlif_type;
+ s32 mode = 0;
+ s32 err = BCME_OK;
+ chanspec_t chspec;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ WL_DBG(("Enter type %d\n", type));
+ switch (type) {
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_MESH_POINT:
+ ap = 1;
+ WL_ERR(("type (%d) : currently we do not support this type\n",
+ type));
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ mode = WL_MODE_IBSS;
+ ibss = 1;
+ break;
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ mode = WL_MODE_BSS;
+ infra = 1;
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_P2P_GO:
+ mode = WL_MODE_AP;
+ ap = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (!dhd)
+ return -EINVAL;
+
+ /* If any scan is going on, abort it */
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ int wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
+ WL_ERR(("Scan in progress. Aborting the scan!\n"));
+ wl_cfg80211_scan_abort(cfg);
+ while (wl_get_drv_status_all(cfg, SCANNING) && wait_cnt) {
+ WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
+ wait_cnt--;
+ OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
+ }
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
+ }
+ }
+
+ if (ap) {
+ wl_set_mode_by_netdev(cfg, ndev, mode);
+ if (is_p2p_group_iface(ndev->ieee80211_ptr) &&
+ cfg->p2p_supported && wl_cfgp2p_vif_created(cfg)) {
+ WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg)));
+ wldev_iovar_setint(ndev, "mpc", 0);
+ wl_notify_escan_complete(cfg, ndev, true, true);
+
+ /* In concurrency case, STA may be already associated in a particular
+ * channel. so retrieve the current channel of primary interface and
+ * then start the virtual interface on that.
+ */
+ chspec = wl_cfg80211_get_shared_freq(wiphy);
+
+ wlif_type = WL_P2P_IF_GO;
+ WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n",
+ ndev->name, ap, infra, type));
+ wl_set_p2p_status(cfg, IF_CHANGING);
+ wl_clr_p2p_status(cfg, IF_CHANGED);
+ wl_cfgp2p_ifchange(cfg, &cfg->p2p->int_addr, htod32(wlif_type), chspec);
+ wait_event_interruptible_timeout(cfg->netif_change_event,
+ (wl_get_p2p_status(cfg, IF_CHANGED) == true),
+ msecs_to_jiffies(MAX_WAIT_TIME));
+ wl_set_mode_by_netdev(cfg, ndev, mode);
+ dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
+ dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
+ wl_clr_p2p_status(cfg, IF_CHANGING);
+ wl_clr_p2p_status(cfg, IF_CHANGED);
+ if (mode == WL_MODE_AP)
+ wl_set_drv_status(cfg, CONNECTED, ndev);
+ } else if (((ndev == bcmcfg_to_prmry_ndev(cfg)) ||
+ (ndev == ((struct net_device *)cfgdev_to_wlc_ndev(cfg->bss_cfgdev, cfg)))) &&
+ !wl_get_drv_status(cfg, AP_CREATED, ndev)) {
+ dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
+ wl_set_drv_status(cfg, AP_CREATING, ndev);
+ } else {
+ WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
+ return -EINVAL;
+ }
+ } else {
+ WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
+#ifdef P2PONEINT /* Cindy: Compare the change with add_virtual_iface */
+ wl_set_mode_by_netdev(cfg, ndev, mode);
+ if (cfg->p2p_supported && wl_cfgp2p_vif_created(cfg)) {
+ WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg)));
+ wldev_iovar_setint(ndev, "mpc", 0);
+ wl_notify_escan_complete(cfg, ndev, true, true);
+
+ /* In concurrency case, STA may be already associated in a particular
+ * channel. so retrieve the current channel of primary interface and
+ * then start the virtual interface on that.
+ */
+ chspec = wl_cfg80211_get_shared_freq(wiphy);
+
+ wlif_type = WL_P2P_IF_CLIENT;
+ WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d) chspec 0x%x \n",
+ ndev->name, ap, infra, type, chspec));
+ wl_set_p2p_status(cfg, IF_CHANGING);
+ wl_clr_p2p_status(cfg, IF_CHANGED);
+ wl_cfgp2p_ifchange(cfg, &cfg->p2p->int_addr, htod32(wlif_type), chspec);
+ wait_event_interruptible_timeout(cfg->netif_change_event,
+ (wl_get_p2p_status(cfg, IF_CHANGED) == true),
+ msecs_to_jiffies(MAX_WAIT_TIME));
+ wl_set_mode_by_netdev(cfg, ndev, mode);
+ dhd->op_mode |= DHD_FLAG_P2P_GC_MODE;
+ dhd->op_mode &= ~DHD_FLAG_P2P_GO_MODE;
+ wl_clr_p2p_status(cfg, IF_CHANGING);
+ wl_clr_p2p_status(cfg, IF_CHANGED);
+
+#define INIT_IE(IE_TYPE, BSS_TYPE) \
+ do { \
+ memset(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \
+ sizeof(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \
+ wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \
+ } while (0);
+
+ INIT_IE(probe_req, P2PAPI_BSSCFG_CONNECTION);
+ INIT_IE(probe_res, P2PAPI_BSSCFG_CONNECTION);
+ INIT_IE(assoc_req, P2PAPI_BSSCFG_CONNECTION);
+ INIT_IE(assoc_res, P2PAPI_BSSCFG_CONNECTION);
+ INIT_IE(beacon, P2PAPI_BSSCFG_CONNECTION);
+ }
+#endif /* P2PONEINT */
+ }
+
+ if (ibss || infra) {
+ wl_set_mode_by_netdev(cfg, ndev, mode);
+ err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+ if (err < 0) {
+ WL_ERR(("SET Adhoc error %d\n", err));
+ return -EINVAL;
+ }
+ }
+
+ ndev->ieee80211_ptr->iftype = type;
+ return 0;
+}
+
+s32
+wl_cfg80211_notify_ifadd(int ifidx, char *name, uint8 *mac, uint8 bssidx)
+{
+ bool ifadd_expected = FALSE;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
+ * redirect the IF_ADD event to ifchange as it is not a real "new" interface
+ */
+ if (wl_get_p2p_status(cfg, IF_CHANGING))
+ return wl_cfg80211_notify_ifchange(ifidx, name, mac, bssidx);
+
+ /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
+ if (wl_get_p2p_status(cfg, IF_ADDING)) {
+ ifadd_expected = TRUE;
+ wl_clr_p2p_status(cfg, IF_ADDING);
+ } else if (cfg->bss_pending_op) {
+ ifadd_expected = TRUE;
+ cfg->bss_pending_op = FALSE;
+ }
+
+ if (ifadd_expected) {
+ wl_if_event_info *if_event_info = &cfg->if_event_info;
+
+ if_event_info->valid = TRUE;
+ if_event_info->ifidx = ifidx;
+ if_event_info->bssidx = bssidx;
+ strncpy(if_event_info->name, name, IFNAMSIZ);
+ if_event_info->name[IFNAMSIZ] = '\0';
+ if (mac)
+ memcpy(if_event_info->mac, mac, ETHER_ADDR_LEN);
+
+ wake_up_interruptible(&cfg->netif_change_event);
+ return BCME_OK;
+ }
+
+ return BCME_ERROR;
+}
+
+s32
+wl_cfg80211_notify_ifdel(int ifidx, char *name, uint8 *mac, uint8 bssidx)
+{
+ bool ifdel_expected = FALSE;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ wl_if_event_info *if_event_info = &cfg->if_event_info;
+
+ WL_INFO(("%d: Enter %s\n", __LINE__, name));
+ if (wl_get_p2p_status(cfg, IF_DELETING)) {
+ ifdel_expected = TRUE;
+ wl_clr_p2p_status(cfg, IF_DELETING);
+ } else if (cfg->bss_pending_op) {
+ ifdel_expected = TRUE;
+ cfg->bss_pending_op = FALSE;
+ }
+
+ if (ifdel_expected) {
+ if_event_info->valid = TRUE;
+ if_event_info->ifidx = ifidx;
+ if_event_info->bssidx = bssidx;
+ wake_up_interruptible(&cfg->netif_change_event);
+ return BCME_OK;
+ }
+
+ return BCME_ERROR;
+}
+
+s32
+wl_cfg80211_notify_ifchange(int ifidx, char *name, uint8 *mac, uint8 bssidx)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ if (wl_get_p2p_status(cfg, IF_CHANGING)) {
+ wl_set_p2p_status(cfg, IF_CHANGED);
+ wake_up_interruptible(&cfg->netif_change_event);
+ return BCME_OK;
+ }
+
+ return BCME_ERROR;
+}
+
+static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
+ struct net_device* ndev)
+{
+ s32 type = -1;
+ s32 bssidx = -1;
+#ifdef PROP_TXSTATUS_VSDB
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ bool enabled;
+#endif /* PROP_TXSTATUS_VSDB */
+
+ bssidx = if_event_info->bssidx;
+ if ((bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION)) &&
+ (bssidx != cfg->cfgdev_bssidx)) {
+ WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx));
+ return BCME_ERROR;
+ }
+
+ if (p2p_is_on(cfg) && wl_cfgp2p_vif_created(cfg)) {
+
+ if (cfg->scan_request && (cfg->escan_info.ndev == ndev)) {
+ /* Abort any pending scan requests */
+ cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ WL_DBG(("ESCAN COMPLETED\n"));
+ wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, false);
+ }
+
+ memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
+ if (wl_cfgp2p_find_type(cfg, bssidx, &type) != BCME_OK) {
+ WL_ERR(("Find p2p type from bssidx(%d) failed\n", bssidx));
+ return BCME_ERROR;
+ }
+ wl_clr_drv_status(cfg, CONNECTED, wl_to_p2p_bss_ndev(cfg, type));
+ wl_to_p2p_bss_ndev(cfg, type) = NULL;
+ wl_to_p2p_bss_bssidx(cfg, type) = WL_INVALID;
+
+#ifdef PROP_TXSTATUS_VSDB
+ dhd_wlfc_get_enable(dhd, &enabled);
+ if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
+ dhd->op_mode != DHD_FLAG_IBSS_MODE) {
+ dhd_wlfc_deinit(dhd);
+ cfg->wlfc_on = false;
+ }
+#endif /* PROP_TXSTATUS_VSDB */
+ }
+
+ dhd_net_if_lock(ndev);
+ wl_cfg80211_remove_if(cfg, if_event_info->ifidx, ndev);
+ dhd_net_if_unlock(ndev);
+
+ return BCME_OK;
+}
+
+/* Find listen channel */
+static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
+ const u8 *ie, u32 ie_len)
+{
+ wifi_p2p_ie_t *p2p_ie;
+ u8 *end, *pos;
+ s32 listen_channel;
+
+ pos = (u8 *)ie;
+ p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
+
+ if (p2p_ie == NULL)
+ return 0;
+
+ pos = p2p_ie->subelts;
+ end = p2p_ie->subelts + (p2p_ie->len - 4);
+
+ CFGP2P_DBG((" found p2p ie ! lenth %d \n",
+ p2p_ie->len));
+
+ while (pos < end) {
+ uint16 attr_len;
+ if (pos + 2 >= end) {
+ CFGP2P_DBG((" -- Invalid P2P attribute"));
+ return 0;
+ }
+ attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
+
+ if (pos + 3 + attr_len > end) {
+ CFGP2P_DBG(("P2P: Attribute underflow "
+ "(len=%u left=%d)",
+ attr_len, (int) (end - pos - 3)));
+ return 0;
+ }
+
+ /* if Listen Channel att id is 6 and the vailue is valid,
+ * return the listen channel
+ */
+ if (pos[0] == 6) {
+ /* listen channel subel length format
+ * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
+ */
+ listen_channel = pos[1 + 2 + 3 + 1];
+
+ if (listen_channel == SOCIAL_CHAN_1 ||
+ listen_channel == SOCIAL_CHAN_2 ||
+ listen_channel == SOCIAL_CHAN_3) {
+ CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
+ return listen_channel;
+ }
+ }
+ pos += 3 + attr_len;
+ }
+ return 0;
+}
+
+static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
+{
+ u32 n_ssids;
+ u32 n_channels;
+ u16 channel;
+ chanspec_t chanspec;
+ s32 i = 0, j = 0, offset;
+ char *ptr;
+ wlc_ssid_t ssid;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
+ params->bss_type = DOT11_BSSTYPE_ANY;
+ params->scan_type = 0;
+ params->nprobes = -1;
+ params->active_time = -1;
+ params->passive_time = -1;
+ params->home_time = -1;
+ params->channel_num = 0;
+ memset(&params->ssid, 0, sizeof(wlc_ssid_t));
+
+ WL_SCAN(("Preparing Scan request\n"));
+ WL_SCAN(("nprobes=%d\n", params->nprobes));
+ WL_SCAN(("active_time=%d\n", params->active_time));
+ WL_SCAN(("passive_time=%d\n", params->passive_time));
+ WL_SCAN(("home_time=%d\n", params->home_time));
+ WL_SCAN(("scan_type=%d\n", params->scan_type));
+
+ params->nprobes = htod32(params->nprobes);
+ params->active_time = htod32(params->active_time);
+ params->passive_time = htod32(params->passive_time);
+ params->home_time = htod32(params->home_time);
+
+ /* if request is null just exit so it will be all channel broadcast scan */
+ if (!request)
+ return;
+
+ n_ssids = request->n_ssids;
+ n_channels = request->n_channels;
+
+ /* Copy channel array if applicable */
+ WL_SCAN(("### List of channelspecs to scan ###\n"));
+ if (n_channels > 0) {
+ for (i = 0; i < n_channels; i++) {
+ chanspec = 0;
+ channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
+ /* SKIP DFS channels for Secondary interface */
+ if ((cfg->escan_info.ndev != bcmcfg_to_prmry_ndev(cfg)) &&
+ (request->channels[i]->flags &
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+ (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
+#else
+ (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR)))
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
+ continue;
+
+ if (request->channels[i]->band == NL80211_BAND_2GHZ) {
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ } else {
+ chanspec |= WL_CHANSPEC_BAND_5G;
+ }
+
+ chanspec |= WL_CHANSPEC_BW_20;
+ chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+
+ params->channel_list[j] = channel;
+ params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
+ params->channel_list[j] |= chanspec;
+ WL_SCAN(("Chan : %d, Channel spec: %x \n",
+ channel, params->channel_list[j]));
+ params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
+ j++;
+ }
+ } else {
+ WL_SCAN(("Scanning all channels\n"));
+ }
+ n_channels = j;
+ /* Copy ssid array if applicable */
+ WL_SCAN(("### List of SSIDs to scan ###\n"));
+ if (n_ssids > 0) {
+ offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
+ offset = roundup(offset, sizeof(u32));
+ ptr = (char*)params + offset;
+ for (i = 0; i < n_ssids; i++) {
+ memset(&ssid, 0, sizeof(wlc_ssid_t));
+ ssid.SSID_len = MIN(request->ssids[i].ssid_len, DOT11_MAX_SSID_LEN);
+ memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
+ if (!ssid.SSID_len)
+ WL_SCAN(("%d: Broadcast scan\n", i));
+ else
+ WL_SCAN(("%d: scan for %s size =%d\n", i,
+ ssid.SSID, ssid.SSID_len));
+ memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
+ ptr += sizeof(wlc_ssid_t);
+ }
+ } else {
+ WL_SCAN(("Broadcast scan\n"));
+ }
+ /* Adding mask to channel numbers */
+ params->channel_num =
+ htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
+ (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
+
+ if (n_channels == 1) {
+ params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
+ params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
+ }
+}
+
+static s32
+wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
+{
+ wl_uint32_list_t *list;
+ s32 err = BCME_OK;
+ if (valid_chan_list == NULL || size <= 0)
+ return -ENOMEM;
+
+ memset(valid_chan_list, 0, size);
+ list = (wl_uint32_list_t *)(void *) valid_chan_list;
+ list->count = htod32(WL_NUMCHANNELS);
+ err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
+ if (err != 0) {
+ WL_ERR(("get channels failed with %d\n", err));
+ }
+
+ return err;
+}
+
+#if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
+#define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
+bool g_first_broadcast_scan = TRUE;
+#endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
+
+static s32
+wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ struct cfg80211_scan_request *request, uint16 action)
+{
+ s32 err = BCME_OK;
+ u32 n_channels;
+ u32 n_ssids;
+ s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
+ wl_escan_params_t *params = NULL;
+ u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
+ u32 num_chans = 0;
+ s32 channel;
+ u32 n_valid_chan;
+ s32 search_state = WL_P2P_DISC_ST_SCAN;
+ u32 i, j, n_nodfs = 0;
+ u16 *default_chan_list = NULL;
+ wl_uint32_list_t *list;
+ struct net_device *dev = NULL;
+#if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
+ bool is_first_init_2g_scan = false;
+#endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
+ p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
+
+ WL_DBG(("Enter \n"));
+
+ /* scan request can come with empty request : perform all default scan */
+ if (!cfg) {
+ err = -EINVAL;
+ goto exit;
+ }
+ if (!cfg->p2p_supported || !p2p_scan(cfg)) {
+ /* LEGACY SCAN TRIGGER */
+ WL_SCAN((" LEGACY E-SCAN START\n"));
+
+#if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
+ if (!request) {
+ err = -EINVAL;
+ goto exit;
+ }
+ if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
+#ifdef USE_INITIAL_2G_SCAN
+ struct ieee80211_channel tmp_channel_list[CH_MAX_2G_CHANNEL];
+ /* allow one 5G channel to add previous connected channel in 5G */
+ bool allow_one_5g_channel = TRUE;
+ j = 0;
+ for (i = 0; i < request->n_channels; i++) {
+ int tmp_chan = ieee80211_frequency_to_channel
+ (request->channels[i]->center_freq);
+ if (tmp_chan > CH_MAX_2G_CHANNEL) {
+ if (allow_one_5g_channel)
+ allow_one_5g_channel = FALSE;
+ else
+ continue;
+ }
+ if (j >= CH_MAX_2G_CHANNEL) {
+ WL_ERR(("Index %d exceeds max 2.4GHz channels %d"
+ " and previous 5G connected channel\n",
+ j, CH_MAX_2G_CHANNEL));
+ break;
+ }
+ bcopy(request->channels[i], &tmp_channel_list[j],
+ sizeof(struct ieee80211_channel));
+ WL_SCAN(("channel of request->channels[%d]=%d\n", i, tmp_chan));
+ j++;
+ }
+ if ((j > 0) && (j <= CH_MAX_2G_CHANNEL)) {
+ for (i = 0; i < j; i++)
+ bcopy(&tmp_channel_list[i], request->channels[i],
+ sizeof(struct ieee80211_channel));
+
+ request->n_channels = j;
+ is_first_init_2g_scan = true;
+ }
+ else
+ WL_ERR(("Invalid number of 2.4GHz channels %d\n", j));
+
+ WL_SCAN(("request->n_channels=%d\n", request->n_channels));
+#else /* USE_INITIAL_SHORT_DWELL_TIME */
+ is_first_init_2g_scan = true;
+#endif /* USE_INITIAL_2G_SCAN */
+ g_first_broadcast_scan = false;
+ }
+#endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
+
+ /* if scan request is not empty parse scan request paramters */
+ if (request != NULL) {
+ n_channels = request->n_channels;
+ n_ssids = request->n_ssids;
+ if (n_channels % 2)
+ /* If n_channels is odd, add a padd of u16 */
+ params_size += sizeof(u16) * (n_channels + 1);
+ else
+ params_size += sizeof(u16) * n_channels;
+
+ /* Allocate space for populating ssids in wl_escan_params_t struct */
+ params_size += sizeof(struct wlc_ssid) * n_ssids;
+ }
+ params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
+ if (params == NULL) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ wl_scan_prep(&params->params, request);
+
+#if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
+ /* Override active_time to reduce scan time if it's first bradcast scan. */
+ if (is_first_init_2g_scan)
+ params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
+#endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
+
+ params->version = htod32(ESCAN_REQ_VERSION);
+ params->action = htod16(action);
+ wl_escan_set_sync_id(params->sync_id, cfg);
+ wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
+ if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
+ WL_ERR(("ioctl buffer length not sufficient\n"));
+ kfree(params);
+ err = -ENOMEM;
+ goto exit;
+ }
+ err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
+ cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
+ if (unlikely(err)) {
+ if (err == BCME_EPERM)
+ /* Scan Not permitted at this point of time */
+ WL_DBG((" Escan not permitted at this time (%d)\n", err));
+ else
+ WL_ERR((" Escan set error (%d)\n", err));
+ }
+ kfree(params);
+ }
+ else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
+ /* P2P SCAN TRIGGER */
+ s32 _freq = 0;
+ n_nodfs = 0;
+ if (request && request->n_channels) {
+ num_chans = request->n_channels;
+ WL_SCAN((" chann number : %d\n", num_chans));
+ default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
+ GFP_KERNEL);
+ if (default_chan_list == NULL) {
+ WL_ERR(("channel list allocation failed \n"));
+ err = -ENOMEM;
+ goto exit;
+ }
+ if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
+ list = (wl_uint32_list_t *) chan_buf;
+ n_valid_chan = dtoh32(list->count);
+ for (i = 0; i < num_chans; i++)
+ {
+ _freq = request->channels[i]->center_freq;
+ channel = ieee80211_frequency_to_channel(_freq);
+
+ /* ignore DFS channels */
+ if (request->channels[i]->flags &
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ (IEEE80211_CHAN_NO_IR
+ | IEEE80211_CHAN_RADAR))
+#else
+ (IEEE80211_CHAN_RADAR
+ | IEEE80211_CHAN_PASSIVE_SCAN))
+#endif
+ continue;
+
+ for (j = 0; j < n_valid_chan; j++) {
+ /* allows only supported channel on
+ * current reguatory
+ */
+ if (channel == (dtoh32(list->element[j])))
+ default_chan_list[n_nodfs++] =
+ channel;
+ }
+
+ }
+ }
+ if (num_chans == SOCIAL_CHAN_CNT && (
+ (default_chan_list[0] == SOCIAL_CHAN_1) &&
+ (default_chan_list[1] == SOCIAL_CHAN_2) &&
+ (default_chan_list[2] == SOCIAL_CHAN_3))) {
+ /* SOCIAL CHANNELS 1, 6, 11 */
+ search_state = WL_P2P_DISC_ST_SEARCH;
+ p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
+ WL_INFO(("P2P SEARCH PHASE START \n"));
+ } else if ((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION)) &&
+ (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
+ /* If you are already a GO, then do SEARCH only */
+ WL_INFO(("Already a GO. Do SEARCH Only"));
+ search_state = WL_P2P_DISC_ST_SEARCH;
+ num_chans = n_nodfs;
+ p2p_scan_purpose = P2P_SCAN_NORMAL;
+
+ } else if (num_chans == 1) {
+ p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
+ } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
+ /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
+ * the supplicant
+ */
+ p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
+ } else {
+ WL_INFO(("P2P SCAN STATE START \n"));
+ num_chans = n_nodfs;
+ p2p_scan_purpose = P2P_SCAN_NORMAL;
+ }
+ } else {
+ err = -EINVAL;
+ goto exit;
+ }
+ err = wl_cfgp2p_escan(cfg, ndev, cfg->active_scan, num_chans, default_chan_list,
+ search_state, action,
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
+ p2p_scan_purpose);
+
+ if (!err)
+ cfg->p2p->search_state = search_state;
+
+ kfree(default_chan_list);
+ }
+exit:
+ if (unlikely(err)) {
+ /* Don't print Error incase of Scan suppress */
+ if ((err == BCME_EPERM) && cfg->scan_suppressed)
+ WL_DBG(("Escan failed: Scan Suppressed \n"));
+ else
+ WL_ERR(("error (%d)\n", err));
+ }
+ return err;
+}
+
+
+static s32
+wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request)
+{
+ s32 err = BCME_OK;
+ s32 passive_scan;
+ wl_scan_results_t *results;
+ WL_SCAN(("Enter \n"));
+ mutex_lock(&cfg->usr_sync);
+
+ results = wl_escan_get_buf(cfg, FALSE);
+ results->version = 0;
+ results->count = 0;
+ results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
+
+ cfg->escan_info.ndev = ndev;
+ cfg->escan_info.wiphy = wiphy;
+ cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
+ passive_scan = cfg->active_scan ? 0 : 1;
+ err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+ &passive_scan, sizeof(passive_scan), true);
+ if (unlikely(err)) {
+ WL_ERR(("error (%d)\n", err));
+ goto exit;
+ }
+
+ err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
+exit:
+ mutex_unlock(&cfg->usr_sync);
+ return err;
+}
+
+static s32
+__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request,
+ struct cfg80211_ssid *this_ssid)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct cfg80211_ssid *ssids;
+ struct ether_addr primary_mac;
+ bool p2p_ssid;
+#ifdef WL11U
+ bcm_tlv_t *interworking_ie;
+#endif
+ s32 err = 0;
+ s32 bssidx = -1;
+ s32 i;
+
+ unsigned long flags;
+ static s32 busy_count = 0;
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ struct net_device *remain_on_channel_ndev = NULL;
+#endif
+
+#ifdef WL_SUPPORT_ACS
+ /*
+ * Hostapd triggers scan before starting automatic channel selection
+ * to collect channel characteristics. However firmware scan engine
+ * doesn't support any channel characteristics collection along with
+ * scan. Hence return scan success.
+ */
+ if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
+ struct cfg80211_scan_info info = {
+ .aborted = 0,
+ };
+ /*
+ * In case of ACS, store the channel number that hostap
+ * interested in. can be used to filter out when
+ * wl_cfg80211_dump_survey() handler is called.
+ */
+ { struct ieee80211_channel *chan = request->channels[0];
+ g_hostap_chan_count = 0;
+ while (g_hostap_chan_count < request->n_channels)
+ {
+ g_hostap_chan_cache[g_hostap_chan_count] =
+ chan[g_hostap_chan_count].center_freq;
+ g_hostap_chan_count++;
+ }
+ WL_DBG(("channel count hostapd interested in %d",
+ g_hostap_chan_count));
+ }
+ /* Indicate cfg80211 that we are done with scan */
+ cfg80211_scan_done(request, &info);
+ WL_INFO(("Scan Command on SoftAP Interface. Ignoring...\n"));
+ return 0;
+ }
+#endif /* WL_SUPPORT_ACS */
+
+ ndev = ndev_to_wlc_ndev(ndev, cfg);
+
+ if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
+ WL_ERR(("Sending Action Frames. Try it again.\n"));
+ return -EAGAIN;
+ }
+
+ WL_DBG(("Enter wiphy (%p)\n", wiphy));
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ if (cfg->scan_request == NULL) {
+ wl_clr_drv_status_all(cfg, SCANNING);
+ WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
+ } else {
+ WL_ERR(("Scanning already\n"));
+ return -EAGAIN;
+ }
+ }
+ if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
+ WL_ERR(("Scanning being aborted\n"));
+ return -EAGAIN;
+ }
+ if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
+ WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
+ return -EOPNOTSUPP;
+ }
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
+ if (remain_on_channel_ndev) {
+ WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
+ wl_notify_escan_complete(cfg, remain_on_channel_ndev, true, true);
+ }
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+
+
+ /* Arm scan timeout timer */
+ mod_timer(&cfg->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
+ if (request) { /* scan bss */
+ ssids = request->ssids;
+ p2p_ssid = false;
+ for (i = 0; i < request->n_ssids; i++) {
+ if (ssids[i].ssid_len &&
+ IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
+ p2p_ssid = true;
+ break;
+ }
+ }
+ if (p2p_ssid) {
+ if (cfg->p2p_supported) {
+ /* p2p scan trigger */
+ if (p2p_on(cfg) == false) {
+ /* p2p on at the first time */
+ p2p_on(cfg) = true;
+ wl_cfgp2p_set_firm_p2p(cfg);
+ get_primary_mac(cfg, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac,
+ &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
+ }
+ wl_clr_p2p_status(cfg, GO_NEG_PHASE);
+ WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
+ p2p_scan(cfg) = true;
+ }
+ } else {
+ /* legacy scan trigger
+ * So, we have to disable p2p discovery if p2p discovery is on
+ */
+ if (cfg->p2p_supported) {
+ p2p_scan(cfg) = false;
+ /* If Netdevice is not equals to primary and p2p is on
+ * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
+ */
+
+ if (p2p_scan(cfg) == false) {
+ if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
+ err = wl_cfgp2p_discover_enable_search(cfg,
+ false);
+ if (unlikely(err)) {
+ goto scan_out;
+ }
+
+ }
+ }
+ }
+ if (!cfg->p2p_supported || !p2p_scan(cfg)) {
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg,
+ ndev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from wdev(%p) failed\n",
+ ndev->ieee80211_ptr));
+ err = BCME_ERROR;
+ goto scan_out;
+ }
+#ifdef WL11U
+ if ((interworking_ie = wl_cfg80211_find_interworking_ie(
+ (u8 *)request->ie, request->ie_len)) != NULL) {
+ err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
+ VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
+ interworking_ie->data, interworking_ie->len);
+
+ if (unlikely(err)) {
+ WL_ERR(("Failed to add interworking IE"));
+ }
+ } else if (cfg->iw_ie_len != 0) {
+ /* we have to clear IW IE and disable gratuitous APR */
+ wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
+ VNDR_IE_CUSTOM_FLAG,
+ DOT11_MNG_INTERWORKING_ID,
+ 0, 0);
+
+ err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0,
+ bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("Set grat_arp error (%d)\n", err));
+ goto scan_out;
+ }
+
+ cfg->iw_ie_len = 0;
+ memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
+
+ cfg->wl11u = FALSE;
+ /* we don't care about error */
+ }
+#endif /* WL11U */
+ err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev, bssidx,
+ VNDR_IE_PRBREQ_FLAG, (u8 *)request->ie,
+ request->ie_len);
+
+ if (unlikely(err)) {
+ goto scan_out;
+ }
+
+ }
+ }
+ } else { /* scan in ibss */
+ ssids = this_ssid;
+ }
+
+ if (request && cfg->p2p && !p2p_scan(cfg)) {
+ WL_TRACE_HW4(("START SCAN\n"));
+ }
+
+ cfg->scan_request = request;
+ wl_set_drv_status(cfg, SCANNING, ndev);
+
+ if (cfg->p2p_supported) {
+ if (p2p_on(cfg) && p2p_scan(cfg)) {
+
+ /* find my listen channel */
+ cfg->afx_hdl->my_listen_chan =
+ wl_find_listen_channel(cfg, request->ie,
+ request->ie_len);
+ err = wl_cfgp2p_enable_discovery(cfg, ndev,
+ request->ie, request->ie_len);
+
+ if (unlikely(err)) {
+ goto scan_out;
+ }
+ }
+ }
+ err = wl_do_escan(cfg, wiphy, ndev, request);
+ if (likely(!err))
+ goto scan_success;
+ else
+ goto scan_out;
+
+scan_success:
+ busy_count = 0;
+
+ return 0;
+
+scan_out:
+ if (err == BCME_BUSY || err == BCME_NOTREADY) {
+ WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
+ err = -EBUSY;
+ } else if ((err == BCME_EPERM) && cfg->scan_suppressed) {
+ WL_ERR(("Scan not permitted due to scan suppress\n"));
+ err = -EPERM;
+ } else {
+ /* For all other fw errors, use a generic error code as return
+ * value to cfg80211 stack
+ */
+ err = -EAGAIN;
+ }
+
+#define SCAN_EBUSY_RETRY_LIMIT 10
+ if (err == -EBUSY) {
+ if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
+ struct ether_addr bssid;
+ s32 ret = 0;
+ busy_count = 0;
+ WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
+ wl_get_drv_status(cfg, SCANNING, ndev),
+ wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
+ wl_get_drv_status(cfg, CONNECTING, ndev),
+ wl_get_drv_status(cfg, CONNECTED, ndev),
+ wl_get_drv_status(cfg, DISCONNECTING, ndev),
+ wl_get_drv_status(cfg, AP_CREATING, ndev),
+ wl_get_drv_status(cfg, AP_CREATED, ndev),
+ wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
+ wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
+
+ bzero(&bssid, sizeof(bssid));
+ if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
+ &bssid, ETHER_ADDR_LEN, false)) == 0)
+ WL_ERR(("FW is connected with " MACDBG "/n",
+ MAC2STRDBG(bssid.octet)));
+ else
+ WL_ERR(("GET BSSID failed with %d\n", ret));
+
+ wl_cfg80211_scan_abort(cfg);
+
+ }
+ } else {
+ busy_count = 0;
+ }
+
+ wl_clr_drv_status(cfg, SCANNING, ndev);
+ if (timer_pending(&cfg->scan_timeout))
+ del_timer_sync(&cfg->scan_timeout);
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+ cfg->scan_request = NULL;
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+
+ return err;
+}
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+#else
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request)
+#endif /* WL_CFG80211_P2P_DEV_IF */
+{
+ s32 err = 0;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+ WL_DBG(("Enter \n"));
+ RETURN_EIO_IF_NOT_UP(cfg);
+
+#ifdef P2PONEINT
+ ndev = bcmcfg_to_prmry_ndev(cfg);
+ WL_DBG(("scan use [dev name %s ] \n", ndev->name));
+#endif
+
+ err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
+ if (unlikely(err)) {
+ WL_ERR(("scan error (%d)\n", err));
+ return err;
+ }
+
+ return err;
+}
+
+static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
+{
+ s32 err = 0;
+
+ err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
+ if (unlikely(err)) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
+{
+ s32 err = 0;
+
+ err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
+ if (unlikely(err)) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
+{
+ s32 err = 0;
+ u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
+
+ retry = htod32(retry);
+ err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
+ if (unlikely(err)) {
+ WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ s32 err = 0;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ WL_DBG(("Enter\n"));
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
+ (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
+ cfg->conf->rts_threshold = wiphy->rts_threshold;
+ err = wl_set_rts(ndev, cfg->conf->rts_threshold);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
+ (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
+ cfg->conf->frag_threshold = wiphy->frag_threshold;
+ err = wl_set_frag(ndev, cfg->conf->frag_threshold);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_RETRY_LONG &&
+ (cfg->conf->retry_long != wiphy->retry_long)) {
+ cfg->conf->retry_long = wiphy->retry_long;
+ err = wl_set_retry(ndev, cfg->conf->retry_long, true);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_RETRY_SHORT &&
+ (cfg->conf->retry_short != wiphy->retry_short)) {
+ cfg->conf->retry_short = wiphy->retry_short;
+ err = wl_set_retry(ndev, cfg->conf->retry_short, false);
+ if (!err) {
+ return err;
+ }
+ }
+
+ return err;
+}
+static chanspec_t
+channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ u8 *buf = NULL;
+ wl_uint32_list_t *list;
+ int err = BCME_OK;
+ chanspec_t c = 0, ret_c = 0;
+ int bw = 0, tmp_bw = 0;
+ int i;
+ u32 tmp_c, sb;
+ u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+#define LOCAL_BUF_SIZE 1024
+ buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
+ if (!buf) {
+ WL_ERR(("buf memory alloc failed\n"));
+ goto exit;
+ }
+ list = (wl_uint32_list_t *)(void *)buf;
+ list->count = htod32(WL_NUMCHANSPECS);
+ err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
+ 0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
+ if (err != BCME_OK) {
+ WL_ERR(("get chanspecs failed with %d\n", err));
+ goto exit;
+ }
+ for (i = 0; i < dtoh32(list->count); i++) {
+ c = dtoh32(list->element[i]);
+ if (channel <= CH_MAX_2G_CHANNEL) {
+ if (!CHSPEC_IS20(c))
+ continue;
+ if (channel == CHSPEC_CHANNEL(c)) {
+ ret_c = c;
+ bw = 20;
+ goto exit;
+ }
+ }
+ if (CHSPEC_IS20(c)) {
+ tmp_c = CHSPEC_CHANNEL(c);
+ tmp_bw = WLC_BW_CAP_20MHZ;
+ }
+ else if (CHSPEC_IS40(c)) {
+ tmp_c = CHSPEC_CHANNEL(c);
+ if (CHSPEC_SB_UPPER(c)) {
+ tmp_c += CH_10MHZ_APART;
+ } else {
+ tmp_c -= CH_10MHZ_APART;
+ }
+ tmp_bw = WLC_BW_CAP_40MHZ;
+ }
+ else {
+ tmp_c = CHSPEC_CHANNEL(c);
+ sb = c & WL_CHANSPEC_CTL_SB_MASK;
+ if (sb == WL_CHANSPEC_CTL_SB_LL) {
+ tmp_c -= (CH_10MHZ_APART + CH_20MHZ_APART);
+ } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
+ tmp_c -= CH_10MHZ_APART;
+ } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
+ tmp_c += CH_10MHZ_APART;
+ } else {
+ /* WL_CHANSPEC_CTL_SB_UU */
+ tmp_c += (CH_10MHZ_APART + CH_20MHZ_APART);
+ }
+ tmp_bw = WLC_BW_CAP_80MHZ;
+ }
+ if (tmp_c != channel)
+ continue;
+
+ if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
+ bw = tmp_bw;
+ ret_c = c;
+ if (bw == bw_cap)
+ goto exit;
+ }
+ }
+exit:
+ if (buf)
+ kfree(buf);
+#undef LOCAL_BUF_SIZE
+ WL_INFO(("return chanspec %x %d\n", ret_c, bw));
+ return ret_c;
+}
+
+void
+wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ if (cfg != NULL && ibss_vsie != NULL) {
+ if (cfg->ibss_vsie != NULL) {
+ kfree(cfg->ibss_vsie);
+ }
+ cfg->ibss_vsie = ibss_vsie;
+ cfg->ibss_vsie_len = ibss_vsie_len;
+ }
+}
+
+static void
+wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211 *cfg)
+{
+ /* free & initiralize VSIE (Vendor Specific IE) */
+ if (cfg->ibss_vsie != NULL) {
+ kfree(cfg->ibss_vsie);
+ cfg->ibss_vsie = NULL;
+ cfg->ibss_vsie_len = 0;
+ }
+}
+
+s32
+wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ char *ioctl_buf = NULL;
+ s32 ret = BCME_OK;
+
+ if (cfg != NULL && cfg->ibss_vsie != NULL) {
+ ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+ if (!ioctl_buf) {
+ WL_ERR(("ioctl memory alloc failed\n"));
+ return -ENOMEM;
+ }
+
+ /* change the command from "add" to "del" */
+ strncpy(cfg->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
+ cfg->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+ ret = wldev_iovar_setbuf(dev, "ie",
+ cfg->ibss_vsie, cfg->ibss_vsie_len,
+ ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
+ WL_ERR(("ret=%d\n", ret));
+
+ if (ret == BCME_OK) {
+ /* free & initiralize VSIE */
+ kfree(cfg->ibss_vsie);
+ cfg->ibss_vsie = NULL;
+ cfg->ibss_vsie_len = 0;
+ }
+
+ if (ioctl_buf) {
+ kfree(ioctl_buf);
+ }
+ }
+
+ return ret;
+}
+
+static s32
+wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct cfg80211_bss *bss;
+ struct ieee80211_channel *chan;
+ struct wl_join_params join_params;
+ int scan_suppress;
+ struct cfg80211_ssid ssid;
+ s32 scan_retry = 0;
+ s32 err = 0;
+ size_t join_params_size;
+ chanspec_t chanspec = 0;
+ u32 param[2] = {0, 0};
+ u32 bw_cap = 0;
+
+ WL_TRACE(("In\n"));
+ RETURN_EIO_IF_NOT_UP(cfg);
+ WL_INFO(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
+ if (!params->ssid || params->ssid_len <= 0 ||
+ params->ssid_len > DOT11_MAX_SSID_LEN) {
+ WL_ERR(("Invalid parameter\n"));
+ return -EINVAL;
+ }
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ chan = params->chandef.chan;
+#else
+ chan = params->channel;
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ if (chan)
+ cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
+ if (wl_get_drv_status(cfg, CONNECTED, dev)) {
+ struct wlc_ssid *ssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
+ u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
+ u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
+ if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
+ (memcmp(params->ssid, ssid->SSID, ssid->SSID_len) == 0) &&
+ (*channel == cfg->channel))) {
+ WL_ERR(("Connection already existed to " MACDBG "\n",
+ MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
+ return -EISCONN;
+ }
+ WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
+ ssid->SSID, MAC2STRDBG(bssid)));
+ }
+
+ /* remove the VSIE */
+ wl_cfg80211_ibss_vsie_delete(dev);
+
+ bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
+ if (!bss) {
+ if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
+ memcpy(ssid.ssid, params->ssid, params->ssid_len);
+ ssid.ssid_len = params->ssid_len;
+ do {
+ if (unlikely
+ (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
+ -EBUSY)) {
+ wl_delay(150);
+ } else {
+ break;
+ }
+ } while (++scan_retry < WL_SCAN_RETRY_MAX);
+
+ /* rtnl lock code is removed here. don't see why rtnl lock
+ * needs to be released.
+ */
+
+ /* wait 4 secons till scan done.... */
+ schedule_timeout_interruptible(msecs_to_jiffies(4000));
+
+ bss = cfg80211_get_ibss(wiphy, NULL,
+ params->ssid, params->ssid_len);
+ }
+ }
+ if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
+ ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
+ !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
+ cfg->ibss_starter = false;
+ WL_DBG(("Found IBSS\n"));
+ } else {
+ cfg->ibss_starter = true;
+ }
+ if (chan) {
+ if (chan->band == NL80211_BAND_5GHZ)
+ param[0] = WLC_BAND_5G;
+ else if (chan->band == NL80211_BAND_2GHZ)
+ param[0] = WLC_BAND_2G;
+ err = wldev_iovar_getint(dev, "bw_cap", param);
+ if (unlikely(err)) {
+ WL_ERR(("Get bw_cap Failed (%d)\n", err));
+ return err;
+ }
+ bw_cap = param[0];
+ chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
+ }
+ /*
+ * Join with specific BSSID and cached SSID
+ * If SSID is zero join based on BSSID only
+ */
+ memset(&join_params, 0, sizeof(join_params));
+ memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
+ params->ssid_len);
+ join_params.ssid.SSID_len = htod32(params->ssid_len);
+ if (params->bssid) {
+ memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
+ err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
+ ETHER_ADDR_LEN, true);
+ if (unlikely(err)) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ } else
+ memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
+ wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
+
+ if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
+ scan_suppress = TRUE;
+ /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
+ err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
+ &scan_suppress, sizeof(int), true);
+ if (unlikely(err)) {
+ WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
+ return err;
+ }
+ }
+
+ join_params.params.chanspec_list[0] = chanspec;
+ join_params.params.chanspec_num = 1;
+ wldev_iovar_setint(dev, "chanspec", chanspec);
+ join_params_size = sizeof(join_params);
+
+ /* Disable Authentication, IBSS will add key if it required */
+ wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
+ wldev_iovar_setint(dev, "wsec", 0);
+
+
+ err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
+ join_params_size, true);
+ if (unlikely(err)) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+
+ if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
+ scan_suppress = FALSE;
+ /* Reset the SCAN SUPPRESS Flag */
+ err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
+ &scan_suppress, sizeof(int), true);
+ if (unlikely(err)) {
+ WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
+ return err;
+ }
+ }
+ wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
+ wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
+#ifdef WL_RELMCAST
+ cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
+#endif /* WL_RELMCAST */
+ return err;
+}
+
+static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 err = 0;
+ scb_val_t scbval;
+ u8 *curbssid;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ wl_link_down(cfg);
+
+ WL_ERR(("Leave IBSS\n"));
+ curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
+ wl_set_drv_status(cfg, DISCONNECTING, dev);
+ scbval.val = 0;
+ memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
+ err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
+ sizeof(scb_val_t), true);
+ if (unlikely(err)) {
+ wl_clr_drv_status(cfg, DISCONNECTING, dev);
+ WL_ERR(("error(%d)\n", err));
+ return err;
+ }
+
+ /* remove the VSIE */
+ wl_cfg80211_ibss_vsie_delete(dev);
+
+ return err;
+}
+
+s32
+wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
+ struct net_device *ndev, s32 bsscfg_idx,
+ enum nl80211_iftype iface_type, s32 del, u8 *addr)
+{
+ s32 ret = BCME_OK;
+ s32 val = 0;
+
+ struct {
+ s32 cfg;
+ s32 val;
+ struct ether_addr ea;
+ } bss_setbuf;
+
+ WL_INFO(("iface_type:%d del:%d \n", iface_type, del));
+
+ bzero(&bss_setbuf, sizeof(bss_setbuf));
+
+ /* AP=3, STA=2, up=1, down=0, val=-1 */
+ if (del) {
+ val = -1;
+ } else if (iface_type == NL80211_IFTYPE_AP) {
+ /* AP Interface */
+ WL_DBG(("Adding AP Interface \n"));
+ val = 3;
+ } else if (iface_type == NL80211_IFTYPE_STATION) {
+ WL_DBG(("Adding STA Interface \n"));
+ val = 2;
+ } else {
+ WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type));
+ return -EINVAL;
+ }
+
+ bss_setbuf.cfg = htod32(bsscfg_idx);
+ bss_setbuf.val = htod32(val);
+
+ if (addr) {
+ memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
+ }
+
+ ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (ret != 0)
+ WL_ERR(("'bss %d' failed with %d\n", val, ret));
+
+ return ret;
+}
+
+#if defined(WL_VIRTUAL_APSTA)
+/* Create a Generic Network Interface and initialize it depending up on
+ * the interface type
+ */
+bcm_struct_cfgdev*
+wl_cfg80211_create_iface(struct wiphy *wiphy,
+ enum nl80211_iftype iface_type,
+ u8 *mac_addr, const char *name)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *new_ndev = NULL;
+ struct net_device *primary_ndev = NULL;
+ s32 ret = BCME_OK;
+ s32 bsscfg_idx = 0;
+ u32 timeout;
+ wl_if_event_info *event = NULL;
+ struct wireless_dev *wdev = NULL;
+ u8 addr[ETH_ALEN];
+
+ WL_DBG(("Enter\n"));
+
+ if (!name) {
+ WL_ERR(("Interface name not provided\n"));
+ return NULL;
+ }
+
+ if (cfg->bss_cfgdev) {
+ WL_ERR(("More than one virtual interface is not needed/supported\n"));
+ return NULL;
+ }
+
+#ifdef DHD_IFDEBUG
+ primary_ndev = bcmcfg_to_prmry_ndev(cfg);
+ WL_ERR(("cfg=%p, primary_ndev=%p, ifname=%s\n", cfg, primary_ndev, name));
+#endif
+
+ /* If any scan is going on, abort it */
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ int wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
+ WL_ERR(("Scan in progress. Aborting the scan!\n"));
+ wl_cfg80211_scan_abort(cfg);
+ while (wl_get_drv_status_all(cfg, SCANNING) && wait_cnt) {
+ WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
+ wait_cnt--;
+ OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
+ }
+ if (!wait_cnt && wl_get_drv_status_all(cfg, SCANNING)) {
+ WL_ERR(("Failed to abort scan\n"));
+ return NULL;
+ }
+ }
+
+ primary_ndev = bcmcfg_to_prmry_ndev(cfg);
+ if (likely(!mac_addr)) {
+ /* Use primary MAC with the locally administered bit for the
+ * Secondary STA I/F
+ */
+ memcpy(addr, primary_ndev->dev_addr, ETH_ALEN);
+ addr[0] |= 0x02;
+
+ /* MAC Adress for virtual interface
+ */
+ addr[3] ^= 0xA0;
+ } else {
+ /* Use the application provided mac address (if any) */
+ memcpy(addr, mac_addr, ETH_ALEN);
+ }
+
+ if ((iface_type != NL80211_IFTYPE_STATION) && (iface_type != NL80211_IFTYPE_AP)) {
+ WL_ERR(("IFACE type:%d not supported. STA "
+ "or AP IFACE is only supported\n", iface_type));
+ return NULL;
+ }
+
+ cfg->bss_pending_op = TRUE;
+ memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
+
+ /* p2p-disc takes bsscfgidx=1 */
+ bsscfg_idx = 2;
+
+ /*
+ * Intialize the firmware I/F.
+ */
+ if ((ret = wl_cfg80211_add_del_bss(cfg, primary_ndev,
+ bsscfg_idx, iface_type, 0, addr)) < 0) {
+ WL_ERR(("Interface create failed!! ret(%d)\n", ret));
+ return NULL;
+ }
+
+ WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx));
+
+ /*
+ * Wait till the firmware send a confirmation event back.
+ */
+ WL_DBG(("Wait for the FW I/F Event\n"));
+ timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
+ !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
+ if (timeout <= 0 || cfg->bss_pending_op) {
+ WL_ERR(("timeout in waiting IF_ADD event\n"));
+ goto fail;
+ }
+
+ /*
+ * Since FW operation is successful,we can go ahead with the
+ * the host interface creation.
+ */
+ event = &cfg->if_event_info;
+ new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx,
+ (char*)name, addr, event->bssidx, event->name);
+ if (!new_ndev) {
+ WL_ERR(("I/F allocation failed! \n"));
+ goto fail;
+ } else {
+ WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
+ event->ifidx, event->bssidx));
+ }
+
+ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+ if (!wdev) {
+ WL_ERR(("wireless_dev alloc failed! \n"));
+ goto fail;
+ }
+
+ wdev->wiphy = wiphy;
+ wdev->iftype = iface_type;
+ new_ndev->ieee80211_ptr = wdev;
+ SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
+
+#ifdef DHD_IFDEBUG
+ WL_ERR(("wdev=%p, new_ndev=%p\n", wdev, new_ndev));
+#endif
+
+ /* RTNL lock must have been acquired. */
+ ASSERT_RTNL();
+
+ /* Set the locally administed mac addr, if not applied already */
+ if (memcmp(addr, event->mac, ETH_ALEN) != 0) {
+ ret = wldev_iovar_setbuf_bsscfg(new_ndev, "cur_etheraddr",
+ addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
+ event->bssidx, &cfg->ioctl_buf_sync);
+ if (unlikely(ret)) {
+ WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
+ goto fail;
+ }
+ memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
+ }
+
+ if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
+ WL_ERR(("IFACE register failed \n"));
+ goto fail;
+ }
+
+ /* Initialize with the station mode params */
+ wl_alloc_netinfo(cfg, new_ndev, wdev,
+ (iface_type == NL80211_IFTYPE_STATION) ?
+ WL_MODE_BSS : WL_MODE_AP, PM_ENABLE, event->bssidx);
+ cfg->bss_cfgdev = ndev_to_cfgdev(new_ndev);
+ cfg->cfgdev_bssidx = event->bssidx;
+
+ WL_DBG(("Host Network Interface for Secondary I/F created"));
+
+#ifdef DHD_IFDEBUG
+ WL_ERR(("cfg->bss_cfgdev=%p\n", cfg->bss_cfgdev));
+#endif
+
+ return cfg->bss_cfgdev;
+
+fail:
+ cfg->bss_pending_op = FALSE;
+ cfg->cfgdev_bssidx = -1;
+ if (wdev)
+ kfree(wdev);
+ if (new_ndev)
+ wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
+
+#ifdef DHD_IFDEBUG
+ WL_ERR(("failed!!!\n"));
+#endif
+
+ return NULL;
+}
+
+s32
+wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *ndev = NULL;
+#ifdef DHD_IFDEBUG
+ struct net_device *primary_ndev = NULL;
+#endif
+ s32 ret = BCME_OK;
+ u32 timeout = 0;
+ enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
+
+ WL_ERR(("Enter\n"));
+
+ if (!cfg->bss_cfgdev) {
+ WL_ERR(("There is no virtual interface found\n"));
+ return 0;
+ }
+
+ /* If any scan is going on, abort it */
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ WL_ERR(("Scan in progress. Aborting the scan!\n"));
+ wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
+ }
+
+ ndev = (struct net_device *)cfgdev_to_wlc_ndev(cfg->bss_cfgdev, cfg);
+#ifdef DHD_IFDEBUG
+ primary_ndev = bcmcfg_to_prmry_ndev(cfg);
+ WL_ERR(("cfg->bss_cfgdev=%p, ndev=%p, primary_ndev=%p\n",
+ cfg->bss_cfgdev, ndev, primary_ndev));
+#endif
+
+ cfg->bss_pending_op = TRUE;
+ memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
+
+ /* Delete the firmware interface. "interface_remove" command
+ * should go on the interface to be deleted
+ */
+ if ((ret = wl_cfg80211_add_del_bss(cfg, ndev,
+ cfg->cfgdev_bssidx, iface_type, true, NULL)) < 0) {
+ WL_ERR(("DEL bss failed ret:%d \n", ret));
+ goto exit;
+ }
+
+ timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
+ !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
+ if (timeout <= 0 || cfg->bss_pending_op) {
+ WL_ERR(("timeout in waiting IF_DEL event\n"));
+ }
+
+exit:
+ cfg->bss_cfgdev = NULL;
+ cfg->cfgdev_bssidx = -1;
+ cfg->bss_pending_op = FALSE;
+
+ WL_ERR(("IF_DEL Done.\n"));
+
+ return ret;
+}
+#endif /* defined(WL_VIRTUAL_APSTA) */
+
+
+static s32
+wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct wl_security *sec;
+ s32 val = 0;
+ s32 err = 0;
+ s32 bssidx;
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+ val = WPA_AUTH_PSK |
+ WPA_AUTH_UNSPECIFIED;
+ else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+ val = WPA2_AUTH_PSK|
+ WPA2_AUTH_UNSPECIFIED;
+ else
+ val = WPA_AUTH_DISABLED;
+
+ if (is_wps_conn(sme))
+ val = WPA_AUTH_DISABLED;
+
+ WL_DBG(("setting wpa_auth to 0x%0x\n", val));
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("set wpa_auth failed (%d)\n", err));
+ return err;
+ }
+ sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
+ sec->wpa_versions = sme->crypto.wpa_versions;
+ return err;
+}
+
+
+static s32
+wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct wl_security *sec;
+ s32 val = 0;
+ s32 err = 0;
+ s32 bssidx;
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ switch (sme->auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ val = WL_AUTH_OPEN_SYSTEM;
+ WL_DBG(("open system\n"));
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ val = WL_AUTH_SHARED_KEY;
+ WL_DBG(("shared key\n"));
+ break;
+ case NL80211_AUTHTYPE_AUTOMATIC:
+ val = WL_AUTH_OPEN_SHARED;
+ WL_DBG(("automatic\n"));
+ break;
+ default:
+ val = 2;
+ WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
+ break;
+ }
+
+ err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("set auth failed (%d)\n", err));
+ return err;
+ }
+ sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
+ sec->auth_type = sme->auth_type;
+ return err;
+}
+
+static s32
+wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct wl_security *sec;
+ s32 pval = 0;
+ s32 gval = 0;
+ s32 err = 0;
+ s32 wsec_val = 0;
+
+ s32 bssidx;
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ if (sme->crypto.n_ciphers_pairwise) {
+ switch (sme->crypto.ciphers_pairwise[0]) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ pval = WEP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ pval = TKIP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ pval = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("invalid cipher pairwise (%d)\n",
+ sme->crypto.ciphers_pairwise[0]));
+ return -EINVAL;
+ }
+ }
+ if (sme->crypto.cipher_group) {
+ switch (sme->crypto.cipher_group) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ gval = WEP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ gval = TKIP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ gval = AES_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ gval = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("invalid cipher group (%d)\n",
+ sme->crypto.cipher_group));
+ return -EINVAL;
+ }
+ }
+
+ WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
+
+ if (is_wps_conn(sme)) {
+ if (sme->privacy)
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
+ else
+ /* WPS-2.0 allows no security */
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
+ } else {
+ WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
+ wsec_val = pval | gval;
+
+ WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
+ err = wldev_iovar_setint_bsscfg(dev, "wsec",
+ wsec_val, bssidx);
+ }
+ if (unlikely(err)) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
+ sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
+ sec->cipher_group = sme->crypto.cipher_group;
+
+ return err;
+}
+
+static s32
+wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct wl_security *sec;
+ s32 val = 0;
+ s32 err = 0;
+ s32 bssidx;
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ if (sme->crypto.n_akm_suites) {
+ err = wldev_iovar_getint(dev, "wpa_auth", &val);
+ if (unlikely(err)) {
+ WL_ERR(("could not get wpa_auth (%d)\n", err));
+ return err;
+ }
+ if (val & (WPA_AUTH_PSK |
+ WPA_AUTH_UNSPECIFIED)) {
+ switch (sme->crypto.akm_suites[0]) {
+ case WLAN_AKM_SUITE_8021X:
+ val = WPA_AUTH_UNSPECIFIED;
+ break;
+ case WLAN_AKM_SUITE_PSK:
+ val = WPA_AUTH_PSK;
+ break;
+ default:
+ WL_ERR(("invalid akm suite (0x%x)\n",
+ sme->crypto.akm_suites[0]));
+ return -EINVAL;
+ }
+ } else if (val & (WPA2_AUTH_PSK |
+ WPA2_AUTH_UNSPECIFIED)) {
+ switch (sme->crypto.akm_suites[0]) {
+ case WLAN_AKM_SUITE_8021X:
+ val = WPA2_AUTH_UNSPECIFIED;
+ break;
+ case WLAN_AKM_SUITE_PSK:
+ val = WPA2_AUTH_PSK;
+ break;
+ default:
+ WL_ERR(("invalid akm suite (0x%x)\n",
+ sme->crypto.akm_suites[0]));
+ return -EINVAL;
+ }
+ }
+ WL_DBG(("setting wpa_auth to %d\n", val));
+
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("could not set wpa_auth (%d)\n", err));
+ return err;
+ }
+ }
+ sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
+ sec->wpa_auth = sme->crypto.akm_suites[0];
+
+ return err;
+}
+
+static s32
+wl_set_set_sharedkey(struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct wl_security *sec;
+ struct wl_wsec_key key;
+ s32 val;
+ s32 err = 0;
+ s32 bssidx;
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ WL_DBG(("key len (%d)\n", sme->key_len));
+ if (sme->key_len) {
+ sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
+ WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
+ sec->wpa_versions, sec->cipher_pairwise));
+ if ((!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
+ NL80211_WPA_VERSION_2))) &&
+ (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
+ WLAN_CIPHER_SUITE_WEP104)))
+ {
+ memset(&key, 0, sizeof(key));
+ key.len = (u32) sme->key_len;
+ key.index = (u32) sme->key_idx;
+ if (unlikely(key.len > sizeof(key.data))) {
+ WL_ERR(("Too long key length (%u)\n", key.len));
+ return -EINVAL;
+ }
+ memcpy(key.data, sme->key, key.len);
+ key.flags = WL_PRIMARY_KEY;
+ switch (sec->cipher_pairwise) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+ default:
+ WL_ERR(("Invalid algorithm (%d)\n",
+ sme->crypto.ciphers_pairwise[0]));
+ return -EINVAL;
+ }
+ /* Set the new key/index */
+ WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
+ key.len, key.index, key.algo));
+ WL_DBG(("key \"%s\"\n", key.data));
+ swap_key_from_BE(&key);
+ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ return err;
+ }
+ if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
+ WL_DBG(("set auth_type to shared key\n"));
+ val = WL_AUTH_SHARED_KEY; /* shared key */
+ err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("set auth failed (%d)\n", err));
+ return err;
+ }
+ }
+ }
+ }
+ return err;
+}
+
+#if defined(ESCAN_RESULT_PATCH)
+static u8 connect_req_bssid[6];
+static u8 broad_bssid[6];
+#endif /* ESCAN_RESULT_PATCH */
+
+
+
+#if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
+static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
+{
+ u32 chanspec = 0;
+ bool isvht80 = 0;
+
+ if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
+ chanspec = wl_chspec_driver_to_host(chanspec);
+
+ isvht80 = chanspec & WL_CHANSPEC_BW_80;
+ WL_INFO(("%s: chanspec(%x:%d)\n", __FUNCTION__, chanspec, isvht80));
+
+ return isvht80;
+}
+#endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
+
+static s32
+wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct ieee80211_channel *chan = sme->channel;
+ wl_extjoin_params_t *ext_join_params;
+ struct wl_join_params join_params;
+ size_t join_params_size;
+#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ s32 roam_trigger[2] = {0, 0};
+#endif /* ROAM_AP_ENV_DETECTION */
+ s32 err = 0;
+ wpa_ie_fixed_t *wpa_ie;
+ bcm_tlv_t *wpa2_ie;
+ u8* wpaie = 0;
+ u32 wpaie_len = 0;
+ u32 chan_cnt = 0;
+ struct ether_addr bssid;
+ s32 bssidx;
+ int ret;
+ int wait_cnt;
+
+ WL_DBG(("In\n"));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
+ if (sme->channel_hint) {
+ chan = sme->channel_hint;
+ WL_DBG(("channel_hint (%d), channel_hint center_freq (%d)\n",
+ ieee80211_frequency_to_channel(sme->channel_hint->center_freq),
+ sme->channel_hint->center_freq));
+ }
+ if (sme->bssid_hint) {
+ sme->bssid = sme->bssid_hint;
+ WL_DBG(("bssid_hint "MACDBG" \n", MAC2STRDBG(sme->bssid_hint)));
+ }
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
+ if (unlikely(!sme->ssid)) {
+ WL_ERR(("Invalid ssid\n"));
+ return -EOPNOTSUPP;
+ }
+
+ if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
+ WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
+ sme->ssid, sme->ssid_len));
+ return -EINVAL;
+ }
+
+ WL_DBG(("SME IE : len=%zu\n", sme->ie_len));
+ if (sme->ie != NULL && sme->ie_len > 0 && (wl_dbg_level & WL_DBG_DBG)) {
+ prhex(NULL, (void *)sme->ie, sme->ie_len);
+ }
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+
+ /*
+ * Cancel ongoing scan to sync up with sme state machine of cfg80211.
+ */
+#if !defined(ESCAN_RESULT_PATCH)
+ if (cfg->scan_request) {
+ wl_notify_escan_complete(cfg, dev, true, true);
+ }
+#endif
+#ifdef WL_SCHED_SCAN
+ if (cfg->sched_scan_req) {
+ wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
+ }
+#endif
+#if defined(ESCAN_RESULT_PATCH)
+ if (sme->bssid)
+ memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
+ else
+ bzero(connect_req_bssid, ETHER_ADDR_LEN);
+ bzero(broad_bssid, ETHER_ADDR_LEN);
+#endif
+#if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
+ maxrxpktglom = 0;
+#endif
+ bzero(&bssid, sizeof(bssid));
+ if (!wl_get_drv_status(cfg, CONNECTED, dev)&&
+ (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
+ if (!ETHER_ISNULLADDR(&bssid)) {
+ scb_val_t scbval;
+ wl_set_drv_status(cfg, DISCONNECTING, dev);
+ scbval.val = DOT11_RC_DISASSOC_LEAVING;
+ memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
+ scbval.val = htod32(scbval.val);
+
+ WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
+ MAC2STRDBG(bssid.octet)));
+ err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
+ sizeof(scb_val_t), true);
+ if (unlikely(err)) {
+ wl_clr_drv_status(cfg, DISCONNECTING, dev);
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ wait_cnt = 500/10;
+ while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
+ WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
+ wait_cnt));
+ wait_cnt--;
+ OSL_SLEEP(10);
+ }
+ } else
+ WL_DBG(("Currently not associated!\n"));
+ } else {
+ /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
+ wait_cnt = 200/10;
+ while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
+ WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
+ wait_cnt--;
+ OSL_SLEEP(10);
+ }
+ if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
+ WL_ERR(("Force clear DISCONNECTING status!\n"));
+ wl_clr_drv_status(cfg, DISCONNECTING, dev);
+ }
+ }
+
+ /* Clean BSSID */
+ bzero(&bssid, sizeof(bssid));
+ if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
+ wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
+
+ if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
+ /* we only allow to connect using virtual interface in case of P2P */
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
+ return BCME_ERROR;
+ }
+ wl_cfg80211_set_mgmt_vndr_ies(cfg, dev, bssidx,
+ VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
+ } else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
+ /* find the RSN_IE */
+ if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
+ DOT11_MNG_RSN_ID)) != NULL) {
+ WL_DBG((" WPA2 IE is found\n"));
+ }
+ /* find the WPA_IE */
+ if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
+ sme->ie_len)) != NULL) {
+ WL_DBG((" WPA IE is found\n"));
+ }
+ if (wpa_ie != NULL || wpa2_ie != NULL) {
+ wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
+ wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
+ wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
+ wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ } else {
+ wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ }
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
+ return BCME_ERROR;
+ }
+ err = wl_cfg80211_set_mgmt_vndr_ies(cfg, dev, bssidx,
+ VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len);
+ if (unlikely(err)) {
+ return err;
+ }
+ }
+#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
+ if (dhd->roam_env_detection) {
+ bool is_roamtrig_reset = TRUE;
+ bool is_roam_env_ok = (wldev_iovar_setint(dev, "roam_env_detection",
+ AP_ENV_DETECT_NOT_USED) == BCME_OK);
+ if (is_roamtrig_reset && is_roam_env_ok) {
+ roam_trigger[0] = WL_AUTO_ROAM_TRIGGER;
+ roam_trigger[1] = WLC_BAND_ALL;
+ err = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
+ sizeof(roam_trigger), true);
+ if (unlikely(err)) {
+ WL_ERR((" failed to restore roam_trigger for auto env"
+ " detection\n"));
+ }
+ }
+ }
+#endif /* ROAM_ENABLE && ROAM_AP_ENV_DETECTION */
+ if (chan) {
+ cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
+ chan_cnt = 1;
+ WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
+ chan->center_freq, chan_cnt));
+ } else
+ cfg->channel = 0;
+
+ WL_DBG(("3. set wapi version \n"));
+ err = wl_set_wpa_version(dev, sme);
+ if (unlikely(err)) {
+ WL_ERR(("Invalid wpa_version\n"));
+ return err;
+ }
+ err = wl_set_auth_type(dev, sme);
+ if (unlikely(err)) {
+ WL_ERR(("Invalid auth type\n"));
+ return err;
+ }
+
+ err = wl_set_set_cipher(dev, sme);
+ if (unlikely(err)) {
+ WL_ERR(("Invalid ciper\n"));
+ return err;
+ }
+
+ err = wl_set_key_mgmt(dev, sme);
+ if (unlikely(err)) {
+ WL_ERR(("Invalid key mgmt\n"));
+ return err;
+ }
+
+ err = wl_set_set_sharedkey(dev, sme);
+ if (unlikely(err)) {
+ WL_ERR(("Invalid shared key\n"));
+ return err;
+ }
+
+ /*
+ * Join with specific BSSID and cached SSID
+ * If SSID is zero join based on BSSID only
+ */
+ join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
+ chan_cnt * sizeof(chanspec_t);
+ ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
+ if (ext_join_params == NULL) {
+ err = -ENOMEM;
+ wl_clr_drv_status(cfg, CONNECTING, dev);
+ goto exit;
+ }
+ ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
+ memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
+ wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
+ ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
+ /* increate dwell time to receive probe response or detect Beacon
+ * from target AP at a noisy air only during connect command
+ */
+ ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
+ ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
+ /* Set up join scan parameters */
+ ext_join_params->scan.scan_type = -1;
+ ext_join_params->scan.nprobes = chan_cnt ?
+ (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
+ ext_join_params->scan.home_time = -1;
+
+ if (sme->bssid)
+ memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
+ else
+ memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
+ ext_join_params->assoc.chanspec_num = chan_cnt;
+ if (chan_cnt) {
+ u16 channel, band, bw, ctl_sb;
+ chanspec_t chspec;
+ channel = cfg->channel;
+ band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
+ : WL_CHANSPEC_BAND_5G;
+ bw = WL_CHANSPEC_BW_20;
+ ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
+ chspec = (channel | band | bw | ctl_sb);
+ ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
+ ext_join_params->assoc.chanspec_list[0] |= chspec;
+ ext_join_params->assoc.chanspec_list[0] =
+ wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
+ }
+ ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
+ if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+ WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
+ ext_join_params->ssid.SSID_len));
+ }
+ wl_set_drv_status(cfg, CONNECTING, dev);
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
+ kfree(ext_join_params);
+ return BCME_ERROR;
+ }
+ err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+
+ WL_ERR(("Connecting with" MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n",
+ MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), cfg->channel,
+ ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len));
+
+ kfree(ext_join_params);
+ if (err) {
+ wl_clr_drv_status(cfg, CONNECTING, dev);
+ if (err == BCME_UNSUPPORTED) {
+ WL_DBG(("join iovar is not supported\n"));
+ goto set_ssid;
+ } else {
+ WL_ERR(("error (%d)\n", err));
+ goto exit;
+ }
+ } else
+ goto exit;
+
+set_ssid:
+ memset(&join_params, 0, sizeof(join_params));
+ join_params_size = sizeof(join_params.ssid);
+
+ join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
+ memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
+ join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+ wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
+ if (sme->bssid)
+ memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
+ else
+ memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
+
+ wl_ch_to_chanspec(cfg->channel, &join_params, &join_params_size);
+ WL_DBG(("join_param_size %zu\n", join_params_size));
+
+ if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+ WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
+ join_params.ssid.SSID_len));
+ }
+ wl_set_drv_status(cfg, CONNECTING, dev);
+ err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ wl_clr_drv_status(cfg, CONNECTING, dev);
+ }
+exit:
+ return err;
+}
+
+static s32
+wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ scb_val_t scbval;
+ bool act = false;
+ s32 err = 0;
+ u8 *curbssid;
+#ifdef CUSTOM_SET_CPUCORE
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+#endif /* CUSTOM_SET_CPUCORE */
+ WL_ERR(("Reason %d\n", reason_code));
+ RETURN_EIO_IF_NOT_UP(cfg);
+ act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
+ curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
+ if (act) {
+ /*
+ * Cancel ongoing scan to sync up with sme state machine of cfg80211.
+ */
+#if !defined(ESCAN_RESULT_PATCH)
+ /* Let scan aborted by F/W */
+ if (cfg->scan_request) {
+ wl_notify_escan_complete(cfg, dev, true, true);
+ }
+#endif /* ESCAN_RESULT_PATCH */
+ if (wl_get_drv_status(cfg, CONNECTING, dev) ||
+ wl_get_drv_status(cfg, CONNECTED, dev)) {
+ wl_set_drv_status(cfg, DISCONNECTING, dev);
+ scbval.val = reason_code;
+ memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
+ scbval.val = htod32(scbval.val);
+ err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
+ sizeof(scb_val_t), true);
+ if (unlikely(err)) {
+ wl_clr_drv_status(cfg, DISCONNECTING, dev);
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ }
+ }
+#ifdef CUSTOM_SET_CPUCORE
+ /* set default cpucore */
+ if (dev == bcmcfg_to_prmry_ndev(cfg)) {
+ dhd->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
+ if (!(dhd->chan_isvht80))
+ dhd_set_cpucore(dhd, FALSE);
+ }
+#endif /* CUSTOM_SET_CPUCORE */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ /* cfg80211 expects disconnect event from DHD to release wdev->current_bss */
+ CFG80211_DISCONNECTED(dev, reason_code, NULL, 0, false, GFP_KERNEL);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
+
+ return err;
+}
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, s32 mbm)
+#else
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+ enum nl80211_tx_power_setting type, s32 dbm)
+#endif /* WL_CFG80211_P2P_DEV_IF */
+{
+
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ s32 err = 0;
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ s32 dbm = MBM_TO_DBM(mbm);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
+ defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
+ dbm = MBM_TO_DBM(dbm);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ switch (type) {
+ case NL80211_TX_POWER_AUTOMATIC:
+ break;
+ case NL80211_TX_POWER_LIMITED:
+ if (dbm < 0) {
+ WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
+ return -EINVAL;
+ }
+ break;
+ case NL80211_TX_POWER_FIXED:
+ if (dbm < 0) {
+ WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
+ return -EINVAL;
+ }
+ break;
+ }
+
+ err = wl_set_tx_power(ndev, type, dbm);
+ if (unlikely(err)) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ cfg->conf->tx_power = dbm;
+
+ return err;
+}
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev, s32 *dbm)
+#else
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
+#endif /* WL_CFG80211_P2P_DEV_IF */
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ s32 err = 0;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ err = wl_get_tx_power(ndev, dbm);
+ if (unlikely(err))
+ WL_ERR(("error (%d)\n", err));
+
+ return err;
+}
+
+static s32
+wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool unicast, bool multicast)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ u32 index;
+ s32 wsec;
+ s32 err = 0;
+ s32 bssidx;
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ WL_DBG(("key index (%d)\n", key_idx));
+ RETURN_EIO_IF_NOT_UP(cfg);
+ err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
+ return err;
+ }
+ if (wsec == WEP_ENABLED) {
+ /* Just select a new current key */
+ index = (u32) key_idx;
+ index = htod32(index);
+ err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
+ sizeof(index), true);
+ if (unlikely(err)) {
+ WL_ERR(("error (%d)\n", err));
+ }
+ }
+ return err;
+}
+
+static s32
+wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr, struct key_params *params)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct wl_wsec_key key;
+ s32 err = 0;
+ s32 bssidx;
+ s32 mode = wl_get_mode_by_netdev(cfg, dev);
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+ memset(&key, 0, sizeof(key));
+ key.index = (u32) key_idx;
+
+ if (!ETHER_ISMULTI(mac_addr))
+ memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
+ key.len = (u32) params->key_len;
+
+ /* check for key index change */
+ if (key.len == 0) {
+ /* key delete */
+ swap_key_from_BE(&key);
+ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("key delete error (%d)\n", err));
+ return err;
+ }
+ } else {
+ if (key.len > sizeof(key.data)) {
+ WL_ERR(("Invalid key length (%d)\n", key.len));
+ return -EINVAL;
+ }
+ WL_DBG(("Setting the key index %d\n", key.index));
+ memcpy(key.data, params->key, key.len);
+
+ if ((mode == WL_MODE_BSS) &&
+ (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
+ u8 keybuf[8];
+ memcpy(keybuf, &key.data[24], sizeof(keybuf));
+ memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
+ memcpy(&key.data[16], keybuf, sizeof(keybuf));
+ }
+
+ /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
+ if (params->seq && params->seq_len == 6) {
+ /* rx iv */
+ u8 *ivptr;
+ ivptr = (u8 *) params->seq;
+ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
+ (ivptr[3] << 8) | ivptr[2];
+ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
+ key.iv_initialized = true;
+ }
+
+ switch (params->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ key.algo = CRYPTO_ALGO_TKIP;
+ WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
+ break;
+ default:
+ WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
+ return -EINVAL;
+ }
+ swap_key_from_BE(&key);
+ /* need to guarantee EAPOL 4/4 send out before set key */
+ dhd_wait_pend8021x(dev);
+ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ return err;
+ }
+ }
+ return err;
+}
+
+int
+wl_cfg80211_enable_roam_offload(struct net_device *dev, bool enable)
+{
+ int err;
+ wl_eventmsg_buf_t ev_buf;
+
+ if (dev != bcmcfg_to_prmry_ndev(g_bcm_cfg)) {
+ /* roam offload is only for the primary device */
+ return -1;
+ }
+ err = wldev_iovar_setint(dev, "roam_offload", (int)enable);
+ if (err)
+ return err;
+
+ bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
+ wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable);
+ wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
+ wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
+ wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
+ wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
+ wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
+ err = wl_cfg80211_apply_eventbuffer(dev, g_bcm_cfg, &ev_buf);
+ if (!err) {
+ g_bcm_cfg->roam_offload = enable;
+ }
+ return err;
+}
+
+#if defined(WL_VIRTUAL_APSTA)
+int
+wl_cfg80211_interface_create(struct net_device *dev, char *name)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ bcm_struct_cfgdev *new_cfgdev;
+
+ new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
+ NL80211_IFTYPE_STATION, NULL, name);
+ if (!new_cfgdev) {
+ return BCME_ERROR;
+ }
+ else {
+ WL_DBG(("Iface %s created successfuly\n", name));
+ return BCME_OK;
+ }
+}
+
+int
+wl_cfg80211_interface_delete(struct net_device *dev, char *name)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct net_info *iter, *next;
+ int err = BCME_ERROR;
+
+ if (name == NULL) {
+ WL_ERR(("Iface name is NULL.\n"));
+ return BCME_ERROR;
+ }
+
+ for_each_ndev(cfg, iter, next) {
+ if (iter->ndev) {
+ if (strcmp(iter->ndev->name, name) == 0) {
+ err = wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
+ break;
+ }
+ }
+ }
+ if (!err) {
+ WL_DBG(("Iface %s deleted successfuly", name));
+ }
+ return err;
+}
+#endif /* defined (WL_VIRTUAL_APSTA) */
+
+static s32
+wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr,
+ struct key_params *params)
+{
+ struct wl_wsec_key key;
+ s32 val = 0;
+ s32 wsec = 0;
+ s32 err = 0;
+ u8 keybuf[8];
+ s32 bssidx = 0;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 mode = wl_get_mode_by_netdev(cfg, dev);
+ WL_DBG(("key index (%d)\n", key_idx));
+ RETURN_EIO_IF_NOT_UP(cfg);
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ if (mac_addr &&
+ ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
+ (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
+ wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
+ goto exit;
+ }
+ memset(&key, 0, sizeof(key));
+
+ key.len = (u32) params->key_len;
+ key.index = (u32) key_idx;
+
+ if (unlikely(key.len > sizeof(key.data))) {
+ WL_ERR(("Too long key length (%u)\n", key.len));
+ return -EINVAL;
+ }
+ memcpy(key.data, params->key, key.len);
+
+ key.flags = WL_PRIMARY_KEY;
+ switch (params->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ val = WEP_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ val = WEP_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ key.algo = CRYPTO_ALGO_TKIP;
+ val = TKIP_ENABLED;
+ /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
+ if (mode == WL_MODE_BSS) {
+ bcopy(&key.data[24], keybuf, sizeof(keybuf));
+ bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
+ bcopy(keybuf, &key.data[16], sizeof(keybuf));
+ }
+ WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ val = AES_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ val = AES_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
+ break;
+ default:
+ WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
+ return -EINVAL;
+ }
+
+ /* Set the new key/index */
+ if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
+ WL_ERR(("IBSS KEY setted\n"));
+ wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
+ }
+ swap_key_from_BE(&key);
+ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
+ WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ return err;
+ }
+
+exit:
+ err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("get wsec error (%d)\n", err));
+ return err;
+ }
+
+ wsec |= val;
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("set wsec error (%d)\n", err));
+ return err;
+ }
+
+ return err;
+}
+
+static s32
+wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr)
+{
+ struct wl_wsec_key key;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 err = 0;
+ s32 bssidx;
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+ WL_DBG(("Enter\n"));
+
+ if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
+ return -EINVAL;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ memset(&key, 0, sizeof(key));
+
+ key.flags = WL_PRIMARY_KEY;
+ key.algo = CRYPTO_ALGO_OFF;
+ key.index = (u32) key_idx;
+
+ WL_DBG(("key index (%d)\n", key_idx));
+ /* Set the new key/index */
+ swap_key_from_BE(&key);
+ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
+ WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ if (err == -EINVAL) {
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
+ /* we ignore this key index in this case */
+ WL_DBG(("invalid key index (%d)\n", key_idx));
+ }
+ } else {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ }
+ return err;
+ }
+ return err;
+}
+
+static s32
+wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
+ void (*callback) (void *cookie, struct key_params * params))
+{
+ struct key_params params;
+ struct wl_wsec_key key;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct wl_security *sec;
+ s32 wsec;
+ s32 err = 0;
+ s32 bssidx;
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+ WL_DBG(("key index (%d)\n", key_idx));
+ RETURN_EIO_IF_NOT_UP(cfg);
+ memset(&key, 0, sizeof(key));
+ key.index = key_idx;
+ swap_key_to_BE(&key);
+ memset(&params, 0, sizeof(params));
+ params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
+ memcpy((void *)params.key, key.data, params.key_len);
+
+ err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
+ return err;
+ }
+ switch (wsec & ~SES_OW_ENABLED) {
+ case WEP_ENABLED:
+ sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
+ if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
+ params.cipher = WLAN_CIPHER_SUITE_WEP40;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+ } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
+ params.cipher = WLAN_CIPHER_SUITE_WEP104;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ }
+ break;
+ case TKIP_ENABLED:
+ params.cipher = WLAN_CIPHER_SUITE_TKIP;
+ WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+ break;
+ case AES_ENABLED:
+ params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+ WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+ break;
+ default:
+ WL_ERR(("Invalid algo (0x%x)\n", wsec));
+ return -EINVAL;
+ }
+
+ callback(cookie, &params);
+ return err;
+}
+
+static s32
+wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx)
+{
+ WL_DBG(("not supported"));
+ return -EOPNOTSUPP;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+static s32
+wl_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *dev, const u8 *mac,
+ struct station_info *sinfo)
+#else
+static s32
+wl_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *dev, u8 *mac,
+ struct station_info *sinfo)
+#endif
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ scb_val_t scb_val;
+ s32 rssi;
+ s32 rate;
+ s32 err = 0;
+ sta_info_t *sta;
+ struct ether_addr bssid;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ s8 eabuf[ETHER_ADDR_STR_LEN];
+#endif
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ RETURN_EIO_IF_NOT_UP(cfg);
+ if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
+ err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
+ ETHER_ADDR_LEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+ if (err < 0) {
+ WL_ERR(("GET STA INFO failed, %d\n", err));
+ return err;
+ }
+ sinfo->filled = STA_INFO_BIT(INFO_INACTIVE_TIME);
+ sta = (sta_info_t *)cfg->ioctl_buf;
+ sta->len = dtoh16(sta->len);
+ sta->cap = dtoh16(sta->cap);
+ sta->flags = dtoh32(sta->flags);
+ sta->idle = dtoh32(sta->idle);
+ sta->in = dtoh32(sta->in);
+ sinfo->inactive_time = sta->idle * 1000;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ if (sta->flags & WL_STA_ASSOC) {
+ sinfo->filled |= STA_INFO_BIT(INFO_CONNECTED_TIME);
+ sinfo->connected_time = sta->in;
+ }
+ WL_INFO(("STA %s : idle time : %d sec, connected time :%d ms\n",
+ bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
+ sta->idle * 1000));
+#endif
+ } else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS ||
+ wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) {
+ get_pktcnt_t pktcnt;
+ u8 *curmacp;
+
+ if (cfg->roam_offload) {
+ err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
+ if (err) {
+ WL_ERR(("Failed to get current BSSID\n"));
+ } else {
+ if (!ETHER_ISNULLADDR(&bssid.octet) &&
+ memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
+ /* roaming is detected */
+ err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
+ if (err)
+ WL_ERR(("Failed to handle the delayed roam, "
+ "err=%d", err));
+ mac = (u8 *)bssid.octet;
+ }
+ }
+ }
+ if (!wl_get_drv_status(cfg, CONNECTED, dev) ||
+ (dhd_is_associated(dhd, 0, &err) == FALSE)) {
+ WL_ERR(("NOT assoc\n"));
+ if (err == -ERESTARTSYS)
+ return err;
+ err = -ENODEV;
+ return err;
+ }
+ curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
+ if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
+ WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
+ MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
+ }
+
+ /* Report the current tx rate */
+ err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
+ if (err) {
+ WL_ERR(("Could not get rate (%d)\n", err));
+ } else {
+#if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
+ int rxpktglom;
+#endif
+ rate = dtoh32(rate);
+ sinfo->filled |= STA_INFO_BIT(INFO_TX_BITRATE);
+ sinfo->txrate.legacy = rate * 5;
+ WL_DBG(("Rate %d Mbps\n", (rate / 2)));
+#if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
+ rxpktglom = ((rate/2) > 150) ? 20 : 10;
+
+ if (maxrxpktglom != rxpktglom) {
+ maxrxpktglom = rxpktglom;
+ WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
+ maxrxpktglom));
+ err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
+ (char*)&maxrxpktglom, 4, cfg->ioctl_buf,
+ WLC_IOCTL_MAXLEN, NULL);
+ if (err < 0) {
+ WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
+ }
+ }
+#endif
+ }
+
+ memset(&scb_val, 0, sizeof(scb_val));
+ scb_val.val = 0;
+ err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
+ sizeof(scb_val_t), false);
+ if (err) {
+ WL_ERR(("Could not get rssi (%d)\n", err));
+ goto get_station_err;
+ }
+ rssi = wl_rssi_offset(dtoh32(scb_val.val));
+ sinfo->filled |= STA_INFO_BIT(INFO_SIGNAL);
+ sinfo->signal = rssi;
+ WL_DBG(("RSSI %d dBm\n", rssi));
+ err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
+ sizeof(pktcnt), false);
+ if (!err) {
+ sinfo->filled |= (STA_INFO_BIT(INFO_RX_PACKETS) |
+ STA_INFO_BIT(INFO_RX_DROP_MISC) |
+ STA_INFO_BIT(INFO_TX_PACKETS) |
+ STA_INFO_BIT(INFO_TX_FAILED));
+ sinfo->rx_packets = pktcnt.rx_good_pkt;
+ sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
+ sinfo->tx_packets = pktcnt.tx_good_pkt;
+ sinfo->tx_failed = pktcnt.tx_bad_pkt;
+ }
+get_station_err:
+ if (err && (err != -ERESTARTSYS)) {
+ /* Disconnect due to zero BSSID or error to get RSSI */
+ WL_ERR(("force cfg80211_disconnected: %d\n", err));
+ wl_clr_drv_status(cfg, CONNECTED, dev);
+ CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
+ wl_link_down(cfg);
+ }
+ }
+ else {
+ WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
+ }
+
+ return err;
+}
+
+static s32
+wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, s32 timeout)
+{
+ s32 pm;
+ s32 err = 0;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ WL_DBG(("Enter\n"));
+ if (cfg->p2p_net == dev || _net_info == NULL || cfg->vsdb_mode ||
+ !wl_get_drv_status(cfg, CONNECTED, dev)) {
+ return err;
+ }
+
+ /* Delete pm_enable_work */
+ wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_PEND);
+
+ pm = enabled ? PM_FAST : PM_OFF;
+ if (_net_info->pm_block) {
+ WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
+ dev->name, _net_info->pm_block));
+ pm = PM_OFF;
+ }
+ pm = htod32(pm);
+ WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
+ err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
+ if (unlikely(err)) {
+ if (err == -ENODEV)
+ WL_DBG(("net_device is not ready yet\n"));
+ else
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ wl_cfg80211_update_power_mode(dev);
+ return err;
+}
+
+void wl_cfg80211_update_power_mode(struct net_device *dev)
+{
+ int err, pm = -1;
+
+ err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), true);
+ if (err)
+ WL_ERR(("%s:error (%d)\n", __FUNCTION__, err));
+ else if (pm != -1 && dev->ieee80211_ptr)
+ dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
+}
+
+static __used u32 wl_find_msb(u16 bit16)
+{
+ u32 ret = 0;
+
+ if (bit16 & 0xff00) {
+ ret += 8;
+ bit16 >>= 8;
+ }
+
+ if (bit16 & 0xf0) {
+ ret += 4;
+ bit16 >>= 4;
+ }
+
+ if (bit16 & 0xc) {
+ ret += 2;
+ bit16 >>= 2;
+ }
+
+ if (bit16 & 2)
+ ret += bit16 & 2;
+ else if (bit16)
+ ret += bit16;
+
+ return ret;
+}
+
+static s32 wl_cfg80211_resume(struct wiphy *wiphy)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ s32 err = BCME_OK;
+
+ if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
+ WL_INFO(("device is not ready\n"));
+ return err;
+ }
+
+
+ return err;
+}
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
+static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
+#else
+static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
+#endif
+{
+ s32 err = BCME_OK;
+#ifdef DHD_CLEAR_ON_SUSPEND
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_info *iter, *next;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ unsigned long flags;
+ if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
+ WL_INFO(("device is not ready : status (%d)\n",
+ (int)cfg->status));
+ return err;
+ }
+ for_each_ndev(cfg, iter, next)
+ wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+ if (cfg->scan_request) {
+ struct cfg80211_scan_info info = {e
+ .aborted = true,
+ };
+
+ cfg80211_scan_done(cfg->scan_request, &info);
+ cfg->scan_request = NULL;
+ }
+ for_each_ndev(cfg, iter, next) {
+ wl_clr_drv_status(cfg, SCANNING, iter->ndev);
+ wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
+ }
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+ for_each_ndev(cfg, iter, next) {
+ if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
+ wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
+ }
+ }
+#endif /* DHD_CLEAR_ON_SUSPEND */
+
+
+ return err;
+}
+
+static s32
+wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
+ s32 err)
+{
+ int i, j;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
+
+ if (!pmk_list) {
+ printk("pmk_list is NULL\n");
+ return -EINVAL;
+ }
+ /* pmk list is supported only for STA interface i.e. primary interface
+ * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
+ */
+ if (primary_dev != dev) {
+ WL_INFO(("Not supporting Flushing pmklist on virtual"
+ " interfaces than primary interface\n"));
+ return err;
+ }
+
+ WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
+ for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
+ WL_DBG(("PMKID[%d]: %pM =\n", i,
+ &pmk_list->pmkids.pmkid[i].BSSID));
+ for (j = 0; j < WPA2_PMKID_LEN; j++) {
+ WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
+ }
+ }
+ if (likely(!err)) {
+ err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
+ sizeof(*pmk_list), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ }
+
+ return err;
+}
+
+static s32
+wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 err = 0;
+ int i;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
+ if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
+ ETHER_ADDR_LEN))
+ break;
+ if (i < WL_NUM_PMKIDS_MAX) {
+ memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
+ ETHER_ADDR_LEN);
+ memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
+ WPA2_PMKID_LEN);
+ if (i == cfg->pmk_list->pmkids.npmkid)
+ cfg->pmk_list->pmkids.npmkid++;
+ } else {
+ err = -EINVAL;
+ }
+ WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
+ &cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].BSSID));
+ for (i = 0; i < WPA2_PMKID_LEN; i++) {
+ WL_DBG(("%02x\n",
+ cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].
+ PMKID[i]));
+ }
+
+ err = wl_update_pmklist(dev, cfg->pmk_list, err);
+
+ return err;
+}
+
+static s32
+wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct _pmkid_list pmkid = {0};
+ s32 err = 0;
+ int i;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+ memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+
+ WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
+ &pmkid.pmkid[0].BSSID));
+ for (i = 0; i < WPA2_PMKID_LEN; i++) {
+ WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
+ }
+
+ for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
+ if (!memcmp
+ (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
+ ETHER_ADDR_LEN))
+ break;
+
+ if ((cfg->pmk_list->pmkids.npmkid > 0) &&
+ (i < cfg->pmk_list->pmkids.npmkid)) {
+ memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
+ for (; i < (cfg->pmk_list->pmkids.npmkid - 1); i++) {
+ memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
+ &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
+ ETHER_ADDR_LEN);
+ memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
+ &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
+ WPA2_PMKID_LEN);
+ }
+ cfg->pmk_list->pmkids.npmkid--;
+ } else {
+ err = -EINVAL;
+ }
+
+ err = wl_update_pmklist(dev, cfg->pmk_list, err);
+
+ return err;
+
+}
+
+static s32
+wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 err = 0;
+ RETURN_EIO_IF_NOT_UP(cfg);
+ memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
+ err = wl_update_pmklist(dev, cfg->pmk_list, err);
+ return err;
+
+}
+
+static wl_scan_params_t *
+wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
+{
+ wl_scan_params_t *params;
+ int params_size;
+ int num_chans;
+
+ *out_params_size = 0;
+
+ /* Our scan params only need space for 1 channel and 0 ssids */
+ params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
+ params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
+ if (params == NULL) {
+ WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
+ return params;
+ }
+ memset(params, 0, params_size);
+ params->nprobes = nprobes;
+
+ num_chans = (channel == 0) ? 0 : 1;
+
+ memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
+ params->bss_type = DOT11_BSSTYPE_ANY;
+ params->scan_type = DOT11_SCANTYPE_ACTIVE;
+ params->nprobes = htod32(1);
+ params->active_time = htod32(-1);
+ params->passive_time = htod32(-1);
+ params->home_time = htod32(10);
+ if (channel == -1)
+ params->channel_list[0] = htodchanspec(channel);
+ else
+ params->channel_list[0] = wl_ch_host_to_driver(channel);
+
+ /* Our scan params have 1 channel and 0 ssids */
+ params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
+ (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
+
+ *out_params_size = params_size; /* rtn size to the caller */
+ return params;
+}
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
+#else
+static s32
+wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ struct ieee80211_channel * channel,
+ enum nl80211_channel_type channel_type,
+ unsigned int duration, u64 *cookie)
+#endif /* WL_CFG80211_P2P_DEV_IF */
+{
+ s32 target_channel;
+ u32 id;
+ s32 err = BCME_OK;
+ struct ether_addr primary_mac;
+ struct net_device *ndev = NULL;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
+ ieee80211_frequency_to_channel(channel->center_freq),
+ duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
+
+ if (!cfg->p2p) {
+ WL_ERR(("cfg->p2p is not initialized\n"));
+ err = BCME_ERROR;
+ goto exit;
+ }
+
+#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
+ }
+#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+
+ target_channel = ieee80211_frequency_to_channel(channel->center_freq);
+ memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
+#if defined(WL_ENABLE_P2P_IF)
+ cfg->remain_on_chan_type = channel_type;
+#endif /* WL_ENABLE_P2P_IF */
+ id = ++cfg->last_roc_id;
+ if (id == 0)
+ id = ++cfg->last_roc_id;
+ *cookie = id;
+
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ if (wl_get_drv_status(cfg, SCANNING, ndev)) {
+ struct timer_list *_timer;
+ WL_DBG(("scan is running. go to fake listen state\n"));
+
+ if (duration > LONG_LISTEN_TIME) {
+ wl_cfg80211_scan_abort(cfg);
+ } else {
+ wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
+
+ if (timer_pending(&cfg->p2p->listen_timer)) {
+ WL_DBG(("cancel current listen timer \n"));
+ del_timer_sync(&cfg->p2p->listen_timer);
+ }
+
+ _timer = &cfg->p2p->listen_timer;
+ wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
+
+ INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
+
+ err = BCME_OK;
+ goto exit;
+ }
+ }
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+
+#ifdef WL_CFG80211_SYNC_GON
+ if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
+ /* do not enter listen mode again if we are in listen mode already for next af.
+ * remain on channel completion will be returned by waiting next af completion.
+ */
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
+#else
+ wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+ goto exit;
+ }
+#endif /* WL_CFG80211_SYNC_GON */
+ if (cfg->p2p && !cfg->p2p->on) {
+ /* In case of p2p_listen command, supplicant send remain_on_channel
+ * without turning on P2P
+ */
+ get_primary_mac(cfg, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac, &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
+ p2p_on(cfg) = true;
+ }
+
+ if (p2p_is_on(cfg)) {
+ err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
+ if (unlikely(err)) {
+ goto exit;
+ }
+#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
+#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+ err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
+
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ if (err == BCME_OK) {
+ wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
+ } else {
+ /* if failed, firmware may be internal scanning state.
+ * so other scan request shall not abort it
+ */
+ wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
+ }
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+ /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
+ * and expire timer will send a completion to the upper layer
+ */
+ err = BCME_OK;
+ }
+
+exit:
+ if (err == BCME_OK) {
+ WL_INFO(("Success\n"));
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ cfg80211_ready_on_channel(cfgdev, *cookie, channel,
+ duration, GFP_KERNEL);
+#else
+ cfg80211_ready_on_channel(cfgdev, *cookie, channel,
+ channel_type, duration, GFP_KERNEL);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ } else {
+ WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
+ }
+ return err;
+}
+
+static s32
+wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
+ bcm_struct_cfgdev *cfgdev, u64 cookie)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 err = 0;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
+ WL_DBG((" enter ) on P2P dedicated discover interface\n"));
+ }
+#else
+ WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+ if (cfg->last_roc_id == cookie) {
+ wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
+ } else {
+ WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
+ __FUNCTION__, cookie, cfg->last_roc_id));
+ }
+
+ return err;
+}
+
+static void
+wl_cfg80211_afx_handler(struct work_struct *work)
+{
+ struct afx_hdl *afx_instance;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ s32 ret = BCME_OK;
+
+ afx_instance = container_of(work, struct afx_hdl, work);
+ if (afx_instance != NULL && cfg->afx_hdl->is_active) {
+ if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
+ ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
+ (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
+ } else {
+ ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
+ cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
+ NULL);
+ }
+ if (unlikely(ret != BCME_OK)) {
+ WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
+ if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
+ complete(&cfg->act_frm_scan);
+ }
+ }
+}
+
+static s32
+wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
+{
+ u32 max_retry = WL_CHANNEL_SYNC_RETRY;
+
+ if (dev == NULL)
+ return -1;
+
+ WL_DBG((" enter ) \n"));
+
+ wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
+ cfg->afx_hdl->is_active = TRUE;
+
+ /* Loop to wait until we find a peer's channel or the
+ * pending action frame tx is cancelled.
+ */
+ while ((cfg->afx_hdl->retry < max_retry) &&
+ (cfg->afx_hdl->peer_chan == WL_INVALID)) {
+ cfg->afx_hdl->is_listen = FALSE;
+ wl_set_drv_status(cfg, SCANNING, dev);
+ WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
+ cfg->afx_hdl->retry));
+ /* search peer on peer's listen channel */
+ schedule_work(&cfg->afx_hdl->work);
+ wait_for_completion_timeout(&cfg->act_frm_scan,
+ msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
+
+ if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
+ !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
+ break;
+
+ if (cfg->afx_hdl->my_listen_chan) {
+ WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
+ cfg->afx_hdl->my_listen_chan));
+ /* listen on my listen channel */
+ cfg->afx_hdl->is_listen = TRUE;
+ schedule_work(&cfg->afx_hdl->work);
+ wait_for_completion_timeout(&cfg->act_frm_scan,
+ msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
+ }
+ if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
+ !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
+ break;
+
+ cfg->afx_hdl->retry++;
+
+ WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
+ }
+
+ cfg->afx_hdl->is_active = FALSE;
+
+ wl_clr_drv_status(cfg, SCANNING, dev);
+ wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
+
+ return (cfg->afx_hdl->peer_chan);
+}
+
+struct p2p_config_af_params {
+ s32 max_tx_retry; /* max tx retry count if tx no ack */
+ /* To make sure to send successfully action frame, we have to turn off mpc
+ * 0: off, 1: on, (-1): do nothing
+ */
+ s32 mpc_onoff;
+#ifdef WL_CFG80211_SYNC_GON
+ bool extra_listen;
+#endif
+ bool search_channel; /* 1: search peer's channel to send af */
+};
+
+static s32
+wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
+ wl_action_frame_t *action_frame, wl_af_params_t *af_params,
+ struct p2p_config_af_params *config_af_params)
+{
+ s32 err = BCME_OK;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ wifi_p2p_pub_act_frame_t *act_frm =
+ (wifi_p2p_pub_act_frame_t *) (action_frame->data);
+
+ /* initialize default value */
+#ifdef WL_CFG80211_SYNC_GON
+ config_af_params->extra_listen = true;
+#endif
+ config_af_params->search_channel = false;
+ config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
+ config_af_params->mpc_onoff = -1;
+ cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
+
+ switch (act_frm->subtype) {
+ case P2P_PAF_GON_REQ: {
+ WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
+ wl_set_p2p_status(cfg, GO_NEG_PHASE);
+
+ config_af_params->mpc_onoff = 0;
+ config_af_params->search_channel = true;
+ cfg->next_af_subtype = act_frm->subtype + 1;
+
+ /* increase dwell time to wait for RESP frame */
+ af_params->dwell_time = WL_MED_DWELL_TIME;
+
+ break;
+ }
+ case P2P_PAF_GON_RSP: {
+ cfg->next_af_subtype = act_frm->subtype + 1;
+ /* increase dwell time to wait for CONF frame */
+ af_params->dwell_time = WL_MED_DWELL_TIME + 100;
+ break;
+ }
+ case P2P_PAF_GON_CONF: {
+ /* If we reached till GO Neg confirmation reset the filter */
+ WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
+ wl_clr_p2p_status(cfg, GO_NEG_PHASE);
+
+ /* turn on mpc again if go nego is done */
+ config_af_params->mpc_onoff = 1;
+
+ /* minimize dwell time */
+ af_params->dwell_time = WL_MIN_DWELL_TIME;
+
+#ifdef WL_CFG80211_SYNC_GON
+ config_af_params->extra_listen = false;
+#endif /* WL_CFG80211_SYNC_GON */
+ break;
+ }
+ case P2P_PAF_INVITE_REQ: {
+ config_af_params->search_channel = true;
+ cfg->next_af_subtype = act_frm->subtype + 1;
+
+ /* increase dwell time */
+ af_params->dwell_time = WL_MED_DWELL_TIME;
+ break;
+ }
+ case P2P_PAF_INVITE_RSP:
+ /* minimize dwell time */
+ af_params->dwell_time = WL_MIN_DWELL_TIME;
+#ifdef WL_CFG80211_SYNC_GON
+ config_af_params->extra_listen = false;
+#endif /* WL_CFG80211_SYNC_GON */
+ break;
+ case P2P_PAF_DEVDIS_REQ: {
+ if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
+ action_frame->len)) {
+ config_af_params->search_channel = true;
+ }
+
+ cfg->next_af_subtype = act_frm->subtype + 1;
+ /* maximize dwell time to wait for RESP frame */
+ af_params->dwell_time = WL_LONG_DWELL_TIME;
+ break;
+ }
+ case P2P_PAF_DEVDIS_RSP:
+ /* minimize dwell time */
+ af_params->dwell_time = WL_MIN_DWELL_TIME;
+#ifdef WL_CFG80211_SYNC_GON
+ config_af_params->extra_listen = false;
+#endif /* WL_CFG80211_SYNC_GON */
+ break;
+ case P2P_PAF_PROVDIS_REQ: {
+ if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
+ action_frame->len)) {
+ config_af_params->search_channel = true;
+ }
+
+ config_af_params->mpc_onoff = 0;
+ cfg->next_af_subtype = act_frm->subtype + 1;
+ /* increase dwell time to wait for RESP frame */
+ af_params->dwell_time = WL_MED_DWELL_TIME;
+ break;
+ }
+ case P2P_PAF_PROVDIS_RSP: {
+ cfg->next_af_subtype = P2P_PAF_GON_REQ;
+ af_params->dwell_time = WL_MIN_DWELL_TIME;
+#ifdef WL_CFG80211_SYNC_GON
+ config_af_params->extra_listen = false;
+#endif /* WL_CFG80211_SYNC_GON */
+ break;
+ }
+ default:
+ WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
+ act_frm->subtype));
+ err = BCME_BADARG;
+ }
+ return err;
+}
+
+#ifdef WL11U
+static bool
+wl_cfg80211_check_DFS_channel(struct bcm_cfg80211 *cfg, wl_af_params_t *af_params,
+ void *frame, u16 frame_len)
+{
+ struct wl_scan_results *bss_list;
+ struct wl_bss_info *bi = NULL;
+ bool result = false;
+ s32 i;
+ chanspec_t chanspec;
+
+ /* If DFS channel is 52~148, check to block it or not */
+ if (af_params &&
+ (af_params->channel >= 52 && af_params->channel <= 148)) {
+ if (!wl_cfgp2p_is_p2p_action(frame, frame_len)) {
+ bss_list = cfg->bss_list;
+ bi = next_bss(bss_list, bi);
+ for_each_bss(bss_list, bi, i) {
+ chanspec = wl_chspec_driver_to_host(bi->chanspec);
+ if (CHSPEC_IS5G(chanspec) &&
+ ((bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(chanspec))
+ == af_params->channel)) {
+ result = true; /* do not block the action frame */
+ break;
+ }
+ }
+ }
+ }
+ else {
+ result = true;
+ }
+
+ WL_DBG(("result=%s", result?"true":"false"));
+ return result;
+}
+#endif /* WL11U */
+
+
+static bool
+wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
+ bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
+ wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
+{
+#ifdef WL11U
+ struct net_device *ndev = NULL;
+#endif /* WL11U */
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ bool ack = false;
+ u8 category, action;
+ s32 tx_retry;
+ struct p2p_config_af_params config_af_params;
+#ifdef VSDB
+ ulong off_chan_started_jiffies = 0;
+#endif
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+
+ int32 requested_dwell = af_params->dwell_time;
+
+ /* Add the default dwell time
+ * Dwell time to stay off-channel to wait for a response action frame
+ * after transmitting an GO Negotiation action frame
+ */
+ af_params->dwell_time = WL_DWELL_TIME;
+
+#ifdef WL11U
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ ndev = dev;
+#else
+ ndev = ndev_to_cfgdev(cfgdev);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+#endif /* WL11U */
+
+ category = action_frame->data[DOT11_ACTION_CAT_OFF];
+ action = action_frame->data[DOT11_ACTION_ACT_OFF];
+
+ /* initialize variables */
+ tx_retry = 0;
+ cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
+ config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
+ config_af_params.mpc_onoff = -1;
+ config_af_params.search_channel = false;
+#ifdef WL_CFG80211_SYNC_GON
+ config_af_params.extra_listen = false;
+#endif
+
+ /* config parameters */
+ /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
+ if (category == DOT11_ACTION_CAT_PUBLIC) {
+ if ((action == P2P_PUB_AF_ACTION) &&
+ (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
+ /* p2p public action frame process */
+ if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
+ action_frame, af_params, &config_af_params)) {
+ WL_DBG(("Unknown subtype.\n"));
+ }
+
+ } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
+ /* service discovery process */
+ if (action == P2PSD_ACTION_ID_GAS_IREQ ||
+ action == P2PSD_ACTION_ID_GAS_CREQ) {
+ /* configure service discovery query frame */
+
+ config_af_params.search_channel = true;
+
+ /* save next af suptype to cancel remained dwell time */
+ cfg->next_af_subtype = action + 1;
+
+ af_params->dwell_time = WL_MED_DWELL_TIME;
+ if (requested_dwell & CUSTOM_RETRY_MASK) {
+ config_af_params.max_tx_retry =
+ (requested_dwell & CUSTOM_RETRY_MASK) >> 24;
+ af_params->dwell_time =
+ (requested_dwell & ~CUSTOM_RETRY_MASK);
+ WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
+ config_af_params.max_tx_retry,
+ af_params->dwell_time));
+ }
+ } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
+ action == P2PSD_ACTION_ID_GAS_CRESP) {
+ /* configure service discovery response frame */
+ af_params->dwell_time = WL_MIN_DWELL_TIME;
+ } else {
+ WL_DBG(("Unknown action type: %d\n", action));
+ }
+ } else {
+ WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
+ category, action, action_frame_len));
+ }
+ } else if (category == P2P_AF_CATEGORY) {
+ /* do not configure anything. it will be sent with a default configuration */
+ } else {
+ WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
+ category, action));
+ if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
+ wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
+ return false;
+ }
+ }
+
+ /* To make sure to send successfully action frame, we have to turn off mpc */
+ if (config_af_params.mpc_onoff == 0) {
+ wldev_iovar_setint(dev, "mpc", 0);
+ }
+
+ /* validate channel and p2p ies */
+ if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
+ wl_to_p2p_bss_saved_ie(cfg, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
+ config_af_params.search_channel = true;
+ } else {
+ config_af_params.search_channel = false;
+ }
+#ifdef WL11U
+ if (ndev == bcmcfg_to_prmry_ndev(cfg))
+ config_af_params.search_channel = false;
+#endif /* WL11U */
+
+#ifdef VSDB
+ /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
+ if (wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {
+ OSL_SLEEP(50);
+ }
+#endif
+
+ /* if scan is ongoing, abort current scan. */
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
+ }
+
+ /* Abort P2P listen */
+ if (discover_cfgdev(cfgdev, cfg)) {
+ if (cfg->p2p_supported && cfg->p2p) {
+ wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
+ }
+ }
+
+#ifdef WL11U
+ /* handling DFS channel exceptions */
+ if (!wl_cfg80211_check_DFS_channel(cfg, af_params, action_frame->data, action_frame->len)) {
+ return false; /* the action frame was blocked */
+ }
+#endif /* WL11U */
+
+ /* set status and destination address before sending af */
+ if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
+ /* set this status to cancel the remained dwell time in rx process */
+ wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
+ }
+ wl_set_drv_status(cfg, SENDING_ACT_FRM, dev);
+ memcpy(cfg->afx_hdl->tx_dst_addr.octet,
+ af_params->action_frame.da.octet,
+ sizeof(cfg->afx_hdl->tx_dst_addr.octet));
+
+ /* save af_params for rx process */
+ cfg->afx_hdl->pending_tx_act_frm = af_params;
+
+ if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
+ WL_DBG(("Set GAS action frame config.\n"));
+ config_af_params.search_channel = false;
+ config_af_params.max_tx_retry = 1;
+ }
+
+ /* search peer's channel */
+ if (config_af_params.search_channel) {
+ /* initialize afx_hdl */
+ if ((cfg->afx_hdl->bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ goto exit;
+ }
+ cfg->afx_hdl->dev = dev;
+ cfg->afx_hdl->retry = 0;
+ cfg->afx_hdl->peer_chan = WL_INVALID;
+
+ if (wl_cfg80211_af_searching_channel(cfg, dev) == WL_INVALID) {
+ WL_ERR(("couldn't find peer's channel.\n"));
+ wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
+ af_params->channel);
+ goto exit;
+ }
+
+ wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
+ /*
+ * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
+ * but after the check of piggyback algorithm.
+ * To take care of current piggback algo, lets abort the scan here itself.
+ */
+ wl_notify_escan_complete(cfg, dev, true, true);
+ /* Suspend P2P discovery's search-listen to prevent it from
+ * starting a scan or changing the channel.
+ */
+ wl_cfgp2p_discover_enable_search(cfg, false);
+
+ /* update channel */
+ af_params->channel = cfg->afx_hdl->peer_chan;
+ }
+
+#ifdef VSDB
+ off_chan_started_jiffies = jiffies;
+#endif /* VSDB */
+
+ wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
+
+ wl_cfgp2p_need_wait_actfrmae(cfg, action_frame->data, action_frame->len, true);
+
+ /* Now send a tx action frame */
+ ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ? false : true;
+
+ /* if failed, retry it. tx_retry_max value is configure by .... */
+ while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry)) {
+#ifdef VSDB
+ if (af_params->channel) {
+ if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
+ OFF_CHAN_TIME_THRESHOLD_MS) {
+ WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
+ off_chan_started_jiffies = jiffies;
+ } else
+ OSL_SLEEP(AF_RETRY_DELAY_TIME);
+ }
+#endif /* VSDB */
+ ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ?
+ false : true;
+ }
+
+ if (ack == false) {
+ WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
+ }
+ WL_DBG(("Complete to send action frame\n"));
+exit:
+ /* Clear SENDING_ACT_FRM after all sending af is done */
+ wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
+
+#ifdef WL_CFG80211_SYNC_GON
+ /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
+ * if we coundn't get the next action response frame and dongle does not keep
+ * the dwell time, go to listen state again to get next action response frame.
+ */
+ if (ack && config_af_params.extra_listen &&
+ wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM) &&
+ cfg->af_sent_channel == cfg->afx_hdl->my_listen_chan) {
+ s32 extar_listen_time;
+
+ extar_listen_time = af_params->dwell_time -
+ jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies);
+
+ if (extar_listen_time > 50) {
+ wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
+ WL_DBG(("Wait more time! actual af time:%d,"
+ "calculated extar listen:%d\n",
+ af_params->dwell_time, extar_listen_time));
+ if (wl_cfgp2p_discover_listen(cfg, cfg->af_sent_channel,
+ extar_listen_time + 100) == BCME_OK) {
+ wait_for_completion_timeout(&cfg->wait_next_af,
+ msecs_to_jiffies(extar_listen_time + 100 + 300));
+ }
+ wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
+ }
+ }
+#endif /* WL_CFG80211_SYNC_GON */
+ wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
+
+ if (cfg->afx_hdl->pending_tx_act_frm)
+ cfg->afx_hdl->pending_tx_act_frm = NULL;
+
+ WL_INFO(("-- sending Action Frame is %s, listen chan: %d\n",
+ (ack) ? "Succeeded!!":"Failed!!", cfg->afx_hdl->my_listen_chan));
+
+
+ /* if all done, turn mpc on again */
+ if (config_af_params.mpc_onoff == 1) {
+ wldev_iovar_setint(dev, "mpc", 1);
+ }
+
+ return ack;
+}
+
+#define MAX_NUM_OF_ASSOCIATED_DEV 64
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+static s32
+wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ struct cfg80211_mgmt_tx_params *params, u64 *cookie)
+#else
+static s32
+wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ struct ieee80211_channel *channel, bool offchan,
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
+ enum nl80211_channel_type channel_type,
+ bool channel_type_valid,
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) */
+ unsigned int wait, const u8* buf, size_t len,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+ bool no_cck,
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+ bool dont_wait_for_ack,
+#endif
+ u64 *cookie)
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
+{
+ wl_action_frame_t *action_frame;
+ wl_af_params_t *af_params;
+ scb_val_t scb_val;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ struct ieee80211_channel *channel = params->chan;
+ const u8 *buf = params->buf;
+ size_t len = params->len;
+#endif
+ const struct ieee80211_mgmt *mgmt;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *dev = NULL;
+ s32 err = BCME_OK;
+ s32 bssidx = 0;
+ u32 id;
+ bool ack = false;
+ s8 eabuf[ETHER_ADDR_STR_LEN];
+
+ WL_DBG(("Enter \n"));
+
+ dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE) */
+ if (discover_cfgdev(cfgdev, cfg)) {
+ bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
+ }
+ else {
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, ndev_to_wdev(dev))) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+ }
+
+ WL_DBG(("TX target bssidx=%d\n", bssidx));
+
+ if (p2p_is_on(cfg)) {
+ /* Suspend P2P discovery search-listen to prevent it from changing the
+ * channel.
+ */
+ if ((err = wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
+ WL_ERR(("Can not disable discovery mode\n"));
+ return -EFAULT;
+ }
+ }
+ *cookie = 0;
+ id = cfg->send_action_id++;
+ if (id == 0)
+ id = cfg->send_action_id++;
+ *cookie = id;
+ mgmt = (const struct ieee80211_mgmt *)buf;
+ if (ieee80211_is_mgmt(mgmt->frame_control)) {
+ if (ieee80211_is_probe_resp(mgmt->frame_control)) {
+ s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
+ s32 ie_len = len - ie_offset;
+#ifdef P2PONEINT
+ if (dev == wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION))
+ dev = bcmcfg_to_prmry_ndev(cfg);
+#endif
+ if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
+ bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
+ }
+ wl_cfg80211_set_mgmt_vndr_ies(cfg, dev, bssidx,
+ VNDR_IE_PRBRSP_FLAG, (u8 *)(buf + ie_offset), ie_len);
+ cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
+ goto exit;
+ } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
+ ieee80211_is_deauth(mgmt->frame_control)) {
+ char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
+ sizeof(struct ether_addr) + sizeof(uint)] = {0};
+ int num_associated = 0;
+ struct maclist *assoc_maclist = (struct maclist *)mac_buf;
+ if (!bcmp((const uint8 *)BSSID_BROADCAST,
+ (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
+ assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
+ err = wldev_ioctl(dev, WLC_GET_ASSOCLIST,
+ assoc_maclist, sizeof(mac_buf), false);
+ if (err < 0)
+ WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
+ else
+ num_associated = assoc_maclist->count;
+ }
+ memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
+ scb_val.val = mgmt->u.disassoc.reason_code;
+ err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
+ sizeof(scb_val_t), true);
+ if (err < 0)
+ WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
+ WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
+ bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
+ scb_val.val));
+
+ if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
+ wl_delay(400);
+
+ cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
+ goto exit;
+
+ } else if (ieee80211_is_action(mgmt->frame_control)) {
+ /* Abort the dwell time of any previous off-channel
+ * action frame that may be still in effect. Sending
+ * off-channel action frames relies on the driver's
+ * scan engine. If a previous off-channel action frame
+ * tx is still in progress (including the dwell time),
+ * then this new action frame will not be sent out.
+ */
+/* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
+ * And previous off-channel action frame must be ended before new af tx.
+ */
+#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ wl_notify_escan_complete(cfg, dev, true, true);
+#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+ }
+
+ } else {
+ WL_ERR(("Driver only allows MGMT packet type\n"));
+ goto exit;
+ }
+
+ af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
+
+ if (af_params == NULL)
+ {
+ WL_ERR(("unable to allocate frame\n"));
+ return -ENOMEM;
+ }
+
+ action_frame = &af_params->action_frame;
+
+ /* Add the packet Id */
+ action_frame->packetId = *cookie;
+ WL_DBG(("action frame %d\n", action_frame->packetId));
+ /* Add BSSID */
+ memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
+ memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
+
+ /* Add the length exepted for 802.11 header */
+ action_frame->len = len - DOT11_MGMT_HDR_LEN;
+ WL_DBG(("action_frame->len: %d\n", action_frame->len));
+
+ /* Add the channel */
+ af_params->channel =
+ ieee80211_frequency_to_channel(channel->center_freq);
+ /* Save listen_chan for searching common channel */
+ cfg->afx_hdl->peer_listen_chan = af_params->channel;
+ WL_DBG(("channel from upper layer %d\n", cfg->afx_hdl->peer_listen_chan));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ af_params->dwell_time = params->wait;
+#else
+ af_params->dwell_time = wait;
+#endif
+
+ memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
+
+ ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
+ action_frame, action_frame->len, bssidx);
+ cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
+
+ kfree(af_params);
+exit:
+ return err;
+}
+
+
+static void
+wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ u16 frame_type, bool reg)
+{
+
+ WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg));
+
+ if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
+ return;
+
+ return;
+}
+
+
+static s32
+wl_cfg80211_change_bss(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct bss_parameters *params)
+{
+ s32 err = 0;
+ s32 ap_isolate = 0;
+
+ if (params->use_cts_prot >= 0) {
+ }
+
+ if (params->use_short_preamble >= 0) {
+ }
+
+ if (params->use_short_slot_time >= 0) {
+ }
+
+ if (params->basic_rates) {
+ }
+
+ if (params->ap_isolate >= 0) {
+ ap_isolate = params->ap_isolate;
+ err = wldev_iovar_setint(dev, "ap_isolate", ap_isolate);
+ if (unlikely(err))
+ {
+ WL_ERR(("set ap_isolate Error (%d)\n", err));
+ }
+ }
+
+ if (params->ht_opmode >= 0) {
+ }
+
+
+ return 0;
+}
+
+static s32
+wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type)
+{
+ s32 _chan;
+ chanspec_t chspec = 0;
+ chanspec_t fw_chspec = 0;
+ u32 bw = WL_CHANSPEC_BW_20;
+
+ s32 err = BCME_OK;
+ s32 bw_cap = 0;
+ struct {
+ u32 band;
+ u32 bw_cap;
+ } param = {0, 0};
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+#ifdef CUSTOM_SET_CPUCORE
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+#endif /* CUSTOM_SET_CPUCORE */
+
+#ifndef P2PONEINT
+ dev = ndev_to_wlc_ndev(dev, cfg);
+#endif
+ _chan = ieee80211_frequency_to_channel(chan->center_freq);
+ WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
+ dev->ifindex, channel_type, _chan));
+
+
+ if (chan->band == NL80211_BAND_5GHZ) {
+ param.band = WLC_BAND_5G;
+ err = wldev_iovar_getbuf(dev, "bw_cap", &param, sizeof(param),
+ cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+ if (err) {
+ if (err != BCME_UNSUPPORTED) {
+ WL_ERR(("bw_cap failed, %d\n", err));
+ return err;
+ } else {
+ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
+ if (err) {
+ WL_ERR(("error get mimo_bw_cap (%d)\n", err));
+ }
+ if (bw_cap != WLC_N_BW_20ALL)
+ bw = WL_CHANSPEC_BW_40;
+ }
+ } else {
+ if (WL_BW_CAP_80MHZ(cfg->ioctl_buf[0]))
+ bw = WL_CHANSPEC_BW_80;
+ else if (WL_BW_CAP_40MHZ(cfg->ioctl_buf[0]))
+ bw = WL_CHANSPEC_BW_40;
+ else
+ bw = WL_CHANSPEC_BW_20;
+
+ }
+
+ } else if (chan->band == NL80211_BAND_2GHZ)
+ bw = WL_CHANSPEC_BW_20;
+set_channel:
+ chspec = wf_channel2chspec(_chan, bw);
+ if (wf_chspec_valid(chspec)) {
+ fw_chspec = wl_chspec_host_to_driver(chspec);
+ if (fw_chspec != INVCHANSPEC) {
+ if ((err = wldev_iovar_setint(dev, "chanspec",
+ fw_chspec)) == BCME_BADCHAN) {
+ if (bw == WL_CHANSPEC_BW_80)
+ goto change_bw;
+ err = wldev_ioctl(dev, WLC_SET_CHANNEL,
+ &_chan, sizeof(_chan), true);
+ if (err < 0) {
+ WL_ERR(("WLC_SET_CHANNEL error %d"
+ "chip may not be supporting this channel\n", err));
+ }
+ } else if (err) {
+ WL_ERR(("failed to set chanspec error %d\n", err));
+ }
+ } else {
+ WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
+ err = BCME_ERROR;
+ }
+ } else {
+change_bw:
+ if (bw == WL_CHANSPEC_BW_80)
+ bw = WL_CHANSPEC_BW_40;
+ else if (bw == WL_CHANSPEC_BW_40)
+ bw = WL_CHANSPEC_BW_20;
+ else
+ bw = 0;
+ if (bw)
+ goto set_channel;
+ WL_ERR(("Invalid chanspec 0x%x\n", chspec));
+ err = BCME_ERROR;
+ }
+#ifdef CUSTOM_SET_CPUCORE
+ if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
+ WL_DBG(("SoftAP mode do not need to set cpucore\n"));
+ } else if (chspec & WL_CHANSPEC_BW_80) {
+ /* SoftAp only mode do not need to set cpucore */
+ if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) &&
+ dev != bcmcfg_to_prmry_ndev(cfg)) {
+ /* Soft AP on virtual Iface (AP+STA case) */
+ dhd->chan_isvht80 |= DHD_FLAG_HOSTAP_MODE;
+ dhd_set_cpucore(dhd, TRUE);
+ } else if (is_p2p_group_iface(dev->ieee80211_ptr)) {
+ /* If P2P IF is vht80 */
+ dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE;
+ dhd_set_cpucore(dhd, TRUE);
+ }
+ }
+#endif
+ return err;
+}
+
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+struct net_device *
+wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg)
+{
+ struct net_info *_net_info, *next;
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (_net_info->ndev &&
+ test_bit(WL_STATUS_REMAINING_ON_CHANNEL, &_net_info->sme_state))
+ return _net_info->ndev;
+ }
+ return NULL;
+}
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+
+static s32
+wl_validate_opensecurity(struct net_device *dev, s32 bssidx)
+{
+ s32 err = BCME_OK;
+
+ /* set auth */
+ err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
+ if (err < 0) {
+ WL_ERR(("auth error %d\n", err));
+ return BCME_ERROR;
+ }
+ /* set wsec */
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
+ if (err < 0) {
+ WL_ERR(("wsec error %d\n", err));
+ return BCME_ERROR;
+ }
+
+ /* set upper-layer auth */
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_NONE, bssidx);
+ if (err < 0) {
+ WL_ERR(("wpa_auth error %d\n", err));
+ return BCME_ERROR;
+ }
+
+ return 0;
+}
+
+static s32
+wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
+{
+ s32 len = 0;
+ s32 err = BCME_OK;
+ u16 auth = 0; /* d11 open authentication */
+ u32 wsec;
+ u32 pval = 0;
+ u32 gval = 0;
+ u32 wpa_auth = 0;
+ wpa_suite_mcast_t *mcast;
+ wpa_suite_ucast_t *ucast;
+ wpa_suite_auth_key_mgmt_t *mgmt;
+ int cnt = 0;
+
+ u16 suite_count;
+ u8 rsn_cap[2];
+ u32 wme_bss_disable;
+
+ if (wpa2ie == NULL)
+ goto exit;
+
+ WL_DBG(("Enter \n"));
+ len = wpa2ie->len;
+ /* check the mcast cipher */
+ mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
+ switch (mcast->type) {
+ case WPA_CIPHER_NONE:
+ gval = 0;
+ break;
+ case WPA_CIPHER_WEP_40:
+ case WPA_CIPHER_WEP_104:
+ gval = WEP_ENABLED;
+ break;
+ case WPA_CIPHER_TKIP:
+ gval = TKIP_ENABLED;
+ break;
+ case WPA_CIPHER_AES_CCM:
+ gval = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("No Security Info\n"));
+ break;
+ }
+ if ((len -= WPA_SUITE_LEN) <= 0)
+ return BCME_BADLEN;
+
+ /* check the unicast cipher */
+ ucast = (wpa_suite_ucast_t *)&mcast[1];
+ suite_count = ltoh16_ua(&ucast->count);
+ switch (ucast->list[0].type) {
+ case WPA_CIPHER_NONE:
+ pval = 0;
+ break;
+ case WPA_CIPHER_WEP_40:
+ case WPA_CIPHER_WEP_104:
+ pval = WEP_ENABLED;
+ break;
+ case WPA_CIPHER_TKIP:
+ pval = TKIP_ENABLED;
+ break;
+ case WPA_CIPHER_AES_CCM:
+ pval = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("No Security Info\n"));
+ }
+ if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
+ return BCME_BADLEN;
+
+ /* FOR WPS , set SEC_OW_ENABLED */
+ wsec = (pval | gval | SES_OW_ENABLED);
+ /* check the AKM */
+ mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
+ suite_count = cnt = ltoh16_ua(&mgmt->count);
+ while (cnt--) {
+ switch (mgmt->list[cnt].type) {
+ case RSN_AKM_NONE:
+ wpa_auth |= WPA_AUTH_NONE;
+ break;
+ case RSN_AKM_UNSPECIFIED:
+ wpa_auth |= WPA2_AUTH_UNSPECIFIED;
+ break;
+ case RSN_AKM_PSK:
+ wpa_auth |= WPA2_AUTH_PSK;
+ break;
+ default:
+ WL_ERR(("No Key Mgmt Info\n"));
+ }
+ }
+
+ if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
+ rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
+ rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
+
+ if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
+ wme_bss_disable = 0;
+ } else {
+ wme_bss_disable = 1;
+ }
+
+
+ /* set wme_bss_disable to sync RSN Capabilities */
+ err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
+ if (err < 0) {
+ WL_ERR(("wme_bss_disable error %d\n", err));
+ return BCME_ERROR;
+ }
+ } else {
+ WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
+ }
+
+ /* set auth */
+ err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
+ if (err < 0) {
+ WL_ERR(("auth error %d\n", err));
+ return BCME_ERROR;
+ }
+
+ /* set wsec */
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
+ if (err < 0) {
+ WL_ERR(("wsec error %d\n", err));
+ return BCME_ERROR;
+ }
+
+
+ /* set upper-layer auth */
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
+ if (err < 0) {
+ WL_ERR(("wpa_auth error %d\n", err));
+ return BCME_ERROR;
+ }
+exit:
+ return 0;
+}
+
+static s32
+wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
+{
+ wpa_suite_mcast_t *mcast;
+ wpa_suite_ucast_t *ucast;
+ wpa_suite_auth_key_mgmt_t *mgmt;
+ u16 auth = 0; /* d11 open authentication */
+ u16 count;
+ s32 err = BCME_OK;
+ s32 len = 0;
+ u32 i;
+ u32 wsec;
+ u32 pval = 0;
+ u32 gval = 0;
+ u32 wpa_auth = 0;
+ u32 tmp = 0;
+
+ if (wpaie == NULL)
+ goto exit;
+ WL_DBG(("Enter \n"));
+ len = wpaie->length; /* value length */
+ len -= WPA_IE_TAG_FIXED_LEN;
+ /* check for multicast cipher suite */
+ if (len < WPA_SUITE_LEN) {
+ WL_INFO(("no multicast cipher suite\n"));
+ goto exit;
+ }
+
+ /* pick up multicast cipher */
+ mcast = (wpa_suite_mcast_t *)&wpaie[1];
+ len -= WPA_SUITE_LEN;
+ if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
+ if (IS_WPA_CIPHER(mcast->type)) {
+ tmp = 0;
+ switch (mcast->type) {
+ case WPA_CIPHER_NONE:
+ tmp = 0;
+ break;
+ case WPA_CIPHER_WEP_40:
+ case WPA_CIPHER_WEP_104:
+ tmp = WEP_ENABLED;
+ break;
+ case WPA_CIPHER_TKIP:
+ tmp = TKIP_ENABLED;
+ break;
+ case WPA_CIPHER_AES_CCM:
+ tmp = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("No Security Info\n"));
+ }
+ gval |= tmp;
+ }
+ }
+ /* Check for unicast suite(s) */
+ if (len < WPA_IE_SUITE_COUNT_LEN) {
+ WL_INFO(("no unicast suite\n"));
+ goto exit;
+ }
+ /* walk thru unicast cipher list and pick up what we recognize */
+ ucast = (wpa_suite_ucast_t *)&mcast[1];
+ count = ltoh16_ua(&ucast->count);
+ len -= WPA_IE_SUITE_COUNT_LEN;
+ for (i = 0; i < count && len >= WPA_SUITE_LEN;
+ i++, len -= WPA_SUITE_LEN) {
+ if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
+ if (IS_WPA_CIPHER(ucast->list[i].type)) {
+ tmp = 0;
+ switch (ucast->list[i].type) {
+ case WPA_CIPHER_NONE:
+ tmp = 0;
+ break;
+ case WPA_CIPHER_WEP_40:
+ case WPA_CIPHER_WEP_104:
+ tmp = WEP_ENABLED;
+ break;
+ case WPA_CIPHER_TKIP:
+ tmp = TKIP_ENABLED;
+ break;
+ case WPA_CIPHER_AES_CCM:
+ tmp = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("No Security Info\n"));
+ }
+ pval |= tmp;
+ }
+ }
+ }
+ len -= (count - i) * WPA_SUITE_LEN;
+ /* Check for auth key management suite(s) */
+ if (len < WPA_IE_SUITE_COUNT_LEN) {
+ WL_INFO((" no auth key mgmt suite\n"));
+ goto exit;
+ }
+ /* walk thru auth management suite list and pick up what we recognize */
+ mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
+ count = ltoh16_ua(&mgmt->count);
+ len -= WPA_IE_SUITE_COUNT_LEN;
+ for (i = 0; i < count && len >= WPA_SUITE_LEN;
+ i++, len -= WPA_SUITE_LEN) {
+ if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
+ if (IS_WPA_AKM(mgmt->list[i].type)) {
+ tmp = 0;
+ switch (mgmt->list[i].type) {
+ case RSN_AKM_NONE:
+ tmp = WPA_AUTH_NONE;
+ break;
+ case RSN_AKM_UNSPECIFIED:
+ tmp = WPA_AUTH_UNSPECIFIED;
+ break;
+ case RSN_AKM_PSK:
+ tmp = WPA_AUTH_PSK;
+ break;
+ default:
+ WL_ERR(("No Key Mgmt Info\n"));
+ }
+ wpa_auth |= tmp;
+ }
+ }
+
+ }
+ /* FOR WPS , set SEC_OW_ENABLED */
+ wsec = (pval | gval | SES_OW_ENABLED);
+ /* set auth */
+ err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
+ if (err < 0) {
+ WL_ERR(("auth error %d\n", err));
+ return BCME_ERROR;
+ }
+ /* set wsec */
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
+ if (err < 0) {
+ WL_ERR(("wsec error %d\n", err));
+ return BCME_ERROR;
+ }
+ /* set upper-layer auth */
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
+ if (err < 0) {
+ WL_ERR(("wpa_auth error %d\n", err));
+ return BCME_ERROR;
+ }
+exit:
+ return 0;
+}
+
+
+static s32
+wl_cfg80211_bcn_validate_sec(
+ struct net_device *dev,
+ struct parsed_ies *ies,
+ u32 dev_role,
+ s32 bssidx)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
+
+ if (!bss) {
+ WL_ERR(("cfgbss is NULL \n"));
+ return BCME_ERROR;
+ }
+
+ if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
+ /* For P2P GO, the sec type is WPA2-PSK */
+ WL_DBG(("P2P GO: validating wpa2_ie"));
+ if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0)
+ return BCME_ERROR;
+
+ } else if (dev_role == NL80211_IFTYPE_AP) {
+
+ WL_DBG(("SoftAP: validating security"));
+ /* If wpa2_ie or wpa_ie is present validate it */
+
+ if ((ies->wpa2_ie || ies->wpa_ie) &&
+ ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
+ wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
+ bss->security_mode = false;
+ return BCME_ERROR;
+ }
+
+ bss->security_mode = true;
+ if (bss->rsn_ie) {
+ kfree(bss->rsn_ie);
+ bss->rsn_ie = NULL;
+ }
+ if (bss->wpa_ie) {
+ kfree(bss->wpa_ie);
+ bss->wpa_ie = NULL;
+ }
+ if (bss->wps_ie) {
+ kfree(bss->wps_ie);
+ bss->wps_ie = NULL;
+ }
+ if (ies->wpa_ie != NULL) {
+ /* WPAIE */
+ bss->rsn_ie = NULL;
+ bss->wpa_ie = kmemdup(ies->wpa_ie,
+ ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+ GFP_KERNEL);
+ } else if (ies->wpa2_ie != NULL) {
+ /* RSNIE */
+ bss->wpa_ie = NULL;
+ bss->rsn_ie = kmemdup(ies->wpa2_ie,
+ ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+ GFP_KERNEL);
+ }
+ if (!ies->wpa2_ie && !ies->wpa_ie) {
+ wl_validate_opensecurity(dev, bssidx);
+ bss->security_mode = false;
+ }
+
+ if (ies->wps_ie) {
+ bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
+ }
+ }
+
+ return 0;
+
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+static s32 wl_cfg80211_bcn_set_params(
+ struct cfg80211_ap_settings *info,
+ struct net_device *dev,
+ u32 dev_role, s32 bssidx)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ s32 err = BCME_OK;
+
+ WL_DBG(("interval (%d) \ndtim_period (%d) \n",
+ info->beacon_interval, info->dtim_period));
+
+ if (info->beacon_interval) {
+ if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
+ &info->beacon_interval, sizeof(s32), true)) < 0) {
+ WL_ERR(("Beacon Interval Set Error, %d\n", err));
+ return err;
+ }
+ }
+
+ if (info->dtim_period) {
+ if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
+ &info->dtim_period, sizeof(s32), true)) < 0) {
+ WL_ERR(("DTIM Interval Set Error, %d\n", err));
+ return err;
+ }
+ }
+
+ if ((info->ssid) && (info->ssid_len > 0) &&
+ (info->ssid_len <= DOT11_MAX_SSID_LEN)) {
+ WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
+ if (dev_role == NL80211_IFTYPE_AP) {
+ /* Store the hostapd SSID */
+ memset(cfg->hostapd_ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
+ memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
+ cfg->hostapd_ssid.SSID_len = info->ssid_len;
+ } else {
+ /* P2P GO */
+ memset(cfg->p2p->ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
+ memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
+ cfg->p2p->ssid.SSID_len = info->ssid_len;
+ }
+ }
+
+ if (info->hidden_ssid) {
+ if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
+ WL_ERR(("failed to set hidden : %d\n", err));
+ WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
+ }
+
+ return err;
+}
+#endif
+
+static s32
+wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
+{
+ s32 err = BCME_OK;
+
+ memset(ies, 0, sizeof(struct parsed_ies));
+
+ /* find the WPSIE */
+ if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
+ WL_DBG(("WPSIE in beacon \n"));
+ ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
+ } else {
+ WL_ERR(("No WPSIE in beacon \n"));
+ }
+
+ /* find the RSN_IE */
+ if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
+ DOT11_MNG_RSN_ID)) != NULL) {
+ WL_DBG((" WPA2 IE found\n"));
+ ies->wpa2_ie_len = ies->wpa2_ie->len;
+ }
+
+ /* find the WPA_IE */
+ if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
+ WL_DBG((" WPA found\n"));
+ ies->wpa_ie_len = ies->wpa_ie->length;
+ }
+
+ return err;
+
+}
+
+static s32
+wl_cfg80211_bcn_bringup_ap(
+ struct net_device *dev,
+ struct parsed_ies *ies,
+ u32 dev_role, s32 bssidx)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct wl_join_params join_params;
+ bool is_bssup = false;
+ s32 infra = 1;
+ s32 join_params_size = 0;
+ s32 ap = 1;
+ s32 pm;
+ s32 err = BCME_OK;
+
+ WL_DBG(("Enter dev_role:%d bssidx:%d\n", dev_role, bssidx));
+
+ /* Common code for SoftAP and P2P GO */
+ wldev_iovar_setint(dev, "mpc", 0);
+
+ if (dev_role == NL80211_IFTYPE_P2P_GO) {
+ is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
+ if (!is_bssup && (ies->wpa2_ie != NULL)) {
+
+ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+ if (err < 0) {
+ WL_ERR(("SET INFRA error %d\n", err));
+ goto exit;
+ }
+
+ err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &cfg->p2p->ssid,
+ sizeof(cfg->p2p->ssid), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
+ bssidx, &cfg->ioctl_buf_sync);
+ if (err < 0) {
+ WL_ERR(("GO SSID setting error %d\n", err));
+ goto exit;
+ }
+
+ /* Do abort scan before creating GO */
+ wl_cfg80211_scan_abort(cfg);
+
+ if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 1)) < 0) {
+ WL_ERR(("GO Bring up error %d\n", err));
+ goto exit;
+ }
+ } else
+ WL_DBG(("Bss is already up\n"));
+ } else if ((dev_role == NL80211_IFTYPE_AP) &&
+ (wl_get_drv_status(cfg, AP_CREATING, dev))) {
+
+ /* Device role SoftAP */
+ WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx, dev_role));
+
+ if (bssidx == 0) {
+ if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx,
+ NL80211_IFTYPE_AP, 0, NULL)) < 0) {
+ WL_DBG(("wl add_del_bss returned error (%d)\n", err));
+ err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
+ if (err < 0) {
+ WL_ERR(("WLC_DOWN error %d\n", err));
+ goto exit;
+ }
+ if ((err = wldev_iovar_setint(dev, "apsta", 0)) < 0) {
+ WL_ERR(("wl apsta 0 error %d\n", err));
+ goto exit;
+ }
+ if ((err = wldev_ioctl(dev,
+ WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
+ WL_ERR(("setting AP mode failed %d \n", err));
+ goto exit;
+ }
+ }
+
+ pm = 0;
+ if ((err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true)) != 0) {
+ WL_ERR(("wl PM 0 returned error:%d\n", err));
+ goto exit;
+ }
+
+ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+ if (err < 0) {
+ WL_ERR(("SET INFRA error %d\n", err));
+ goto exit;
+ }
+ } else if (cfg->cfgdev_bssidx && (bssidx == cfg->cfgdev_bssidx)) {
+
+ WL_DBG(("Bringup SoftAP on virtual Interface bssidx:%d \n", bssidx));
+
+ if ((err = wl_cfg80211_add_del_bss(cfg, dev,
+ bssidx, NL80211_IFTYPE_AP, 0, NULL)) < 0) {
+ WL_ERR(("wl bss ap returned error:%d\n", err));
+ goto exit;
+ }
+ }
+
+
+ err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_UP error (%d)\n", err));
+ goto exit;
+ }
+
+ memset(&join_params, 0, sizeof(join_params));
+ /* join parameters starts with ssid */
+ join_params_size = sizeof(join_params.ssid);
+ join_params.ssid.SSID_len = MIN(cfg->hostapd_ssid.SSID_len,
+ (uint32)DOT11_MAX_SSID_LEN);
+ memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
+ join_params.ssid.SSID_len);
+ join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+
+ /* create softap */
+ if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
+ join_params_size, true)) == 0) {
+ WL_DBG(("SoftAP set SSID (%s) success\n", join_params.ssid.SSID));
+ wl_clr_drv_status(cfg, AP_CREATING, dev);
+ wl_set_drv_status(cfg, AP_CREATED, dev);
+ } else {
+ WL_ERR(("SoftAP set SSID (%s) failed!\n", join_params.ssid.SSID));
+ }
+ }
+
+
+exit:
+ return err;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+s32
+wl_cfg80211_parse_ap_ies(
+ struct net_device *dev,
+ struct cfg80211_beacon_data *info,
+ struct parsed_ies *ies)
+{
+ struct parsed_ies prb_ies;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ u8 *vndr = NULL;
+ u32 vndr_ie_len = 0;
+ s32 err = BCME_OK;
+
+ /* Parse Beacon IEs */
+ if (wl_cfg80211_parse_ies((u8 *)info->tail,
+ info->tail_len, ies) < 0) {
+ WL_ERR(("Beacon get IEs failed \n"));
+ err = -EINVAL;
+ goto fail;
+ }
+
+ vndr = (u8 *)info->proberesp_ies;
+ vndr_ie_len = info->proberesp_ies_len;
+
+ if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
+ /* SoftAP mode */
+ struct ieee80211_mgmt *mgmt;
+ mgmt = (struct ieee80211_mgmt *)info->probe_resp;
+ if (mgmt != NULL) {
+ vndr = (u8 *)&mgmt->u.probe_resp.variable;
+ vndr_ie_len = info->probe_resp_len -
+ offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ }
+ }
+
+ /* Parse Probe Response IEs */
+ if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
+ WL_ERR(("PROBE RESP get IEs failed \n"));
+ err = -EINVAL;
+ }
+
+fail:
+
+ return err;
+}
+
+s32
+wl_cfg80211_set_ies(
+ struct net_device *dev,
+ struct cfg80211_beacon_data *info,
+ s32 bssidx)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ u8 *vndr = NULL;
+ u32 vndr_ie_len = 0;
+ s32 err = BCME_OK;
+
+ /* Set Beacon IEs to FW */
+ if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, dev, bssidx,
+ VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
+ info->tail_len)) < 0) {
+ WL_ERR(("Set Beacon IE Failed \n"));
+ } else {
+ WL_DBG(("Applied Vndr IEs for Beacon \n"));
+ }
+
+ vndr = (u8 *)info->proberesp_ies;
+ vndr_ie_len = info->proberesp_ies_len;
+
+ if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
+ /* SoftAP mode */
+ struct ieee80211_mgmt *mgmt;
+ mgmt = (struct ieee80211_mgmt *)info->probe_resp;
+ if (mgmt != NULL) {
+ vndr = (u8 *)&mgmt->u.probe_resp.variable;
+ vndr_ie_len = info->probe_resp_len -
+ offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ }
+ }
+
+ /* Set Probe Response IEs to FW */
+ if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, dev, bssidx,
+ VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
+ WL_ERR(("Set Probe Resp IE Failed \n"));
+ } else {
+ WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
+ }
+
+ return err;
+}
+#endif
+
+static s32 wl_cfg80211_hostapd_sec(
+ struct net_device *dev,
+ struct parsed_ies *ies,
+ s32 bssidx)
+{
+ bool update_bss = 0;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
+
+ if (!bss) {
+ WL_ERR(("cfgbss is NULL \n"));
+ return -EINVAL;
+ }
+
+ if (ies->wps_ie) {
+ if (bss->wps_ie &&
+ memcmp(bss->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
+ WL_DBG((" WPS IE is changed\n"));
+ kfree(bss->wps_ie);
+ bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
+ } else if (bss->wps_ie == NULL) {
+ WL_DBG((" WPS IE is added\n"));
+ bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
+ }
+
+ if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
+ if (!bss->security_mode) {
+ /* change from open mode to security mode */
+ update_bss = true;
+ if (ies->wpa_ie != NULL) {
+ bss->wpa_ie = kmemdup(ies->wpa_ie,
+ ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+ GFP_KERNEL);
+ } else {
+ bss->rsn_ie = kmemdup(ies->wpa2_ie,
+ ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+ GFP_KERNEL);
+ }
+ } else if (bss->wpa_ie) {
+ /* change from WPA2 mode to WPA mode */
+ if (ies->wpa_ie != NULL) {
+ update_bss = true;
+ kfree(bss->rsn_ie);
+ bss->rsn_ie = NULL;
+ bss->wpa_ie = kmemdup(ies->wpa_ie,
+ ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+ GFP_KERNEL);
+ } else if (memcmp(bss->rsn_ie,
+ ies->wpa2_ie, ies->wpa2_ie->len
+ + WPA_RSN_IE_TAG_FIXED_LEN)) {
+ update_bss = true;
+ kfree(bss->rsn_ie);
+ bss->rsn_ie = kmemdup(ies->wpa2_ie,
+ ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+ GFP_KERNEL);
+ bss->wpa_ie = NULL;
+ }
+ }
+ if (update_bss) {
+ bss->security_mode = true;
+ wl_cfgp2p_bss(cfg, dev, bssidx, 0);
+ if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
+ wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
+ return BCME_ERROR;
+ }
+ wl_cfgp2p_bss(cfg, dev, bssidx, 1);
+ }
+ }
+ } else {
+ WL_ERR(("No WPSIE in beacon \n"));
+ }
+ return 0;
+}
+
+#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
+ 2, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
+static s32 wl_cfg80211_del_station(
+ struct wiphy *wiphy, struct net_device *ndev,
+ struct station_del_parameters *params)
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+static s32
+wl_cfg80211_del_station(struct wiphy *wiphy,
+ struct net_device *ndev, const u8* mac_addr)
+#else
+static s32
+wl_cfg80211_del_station(struct wiphy *wiphy,
+ struct net_device *ndev, u8* mac_addr)
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
+{
+ struct net_device *dev;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ scb_val_t scb_val;
+ s8 eabuf[ETHER_ADDR_STR_LEN];
+ int err;
+ char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
+ sizeof(struct ether_addr) + sizeof(uint)] = {0};
+ struct maclist *assoc_maclist = (struct maclist *)mac_buf;
+ int num_associated = 0;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
+ const u8 *mac_addr = params->mac;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
+
+ WL_DBG(("Entry\n"));
+ if (mac_addr == NULL) {
+ WL_DBG(("mac_addr is NULL ignore it\n"));
+ return 0;
+ }
+
+ dev = ndev_to_wlc_ndev(ndev, cfg);
+
+ if (p2p_is_on(cfg)) {
+ /* Suspend P2P discovery search-listen to prevent it from changing the
+ * channel.
+ */
+ if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
+ WL_ERR(("Can not disable discovery mode\n"));
+ return -EFAULT;
+ }
+ }
+
+ assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
+ err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
+ assoc_maclist, sizeof(mac_buf), false);
+ if (err < 0)
+ WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
+ else
+ num_associated = assoc_maclist->count;
+
+#ifdef REMOVE_P2PIE_BEFORE_DELIF
+ if (num_associated > 0 && ETHER_ISBCAST(mac_addr) && p2p_is_on(cfg))
+ {
+ s32 bssidx = -1;
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from ndev(%p) failed\n", dev));
+ } else {
+ wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
+ }
+ }
+#endif /* REMOVE_P2PIE_BEFORE_DELIF */
+
+ memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
+ scb_val.val = DOT11_RC_DEAUTH_LEAVING;
+ err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
+ sizeof(scb_val_t), true);
+ if (err < 0)
+ WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
+ WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
+ bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
+ scb_val.val));
+
+ if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
+ wl_delay(400);
+
+ return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+static s32
+wl_cfg80211_change_station(struct wiphy *wiphy,
+ struct net_device *dev, const u8 *mac, struct station_parameters *params)
+#else
+static s32
+wl_cfg80211_change_station(struct wiphy *wiphy,
+ struct net_device *dev, u8 *mac, struct station_parameters *params)
+#endif
+{
+ int err;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
+
+ /* Processing only authorize/de-authorize flag for now */
+ if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
+ return -ENOTSUPP;
+
+ if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+ err = wldev_ioctl(primary_ndev, WLC_SCB_AUTHORIZE, (u8 *)mac, ETH_ALEN, true);
+#else
+ err = wldev_ioctl(primary_ndev, WLC_SCB_AUTHORIZE, mac, ETH_ALEN, true);
+#endif
+ if (err)
+ WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err));
+ return err;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+ err = wldev_ioctl(primary_ndev, WLC_SCB_AUTHORIZE, (u8 *)mac, ETH_ALEN, true);
+#else
+ err = wldev_ioctl(primary_ndev, WLC_SCB_AUTHORIZE, mac, ETH_ALEN, true);
+#endif
+ if (err)
+ WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err));
+ return err;
+}
+#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+static s32
+wl_cfg80211_start_ap(
+ struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_ap_settings *info)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 err = BCME_OK;
+ struct parsed_ies ies;
+ s32 bssidx = 0;
+ u32 dev_role = 0;
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+
+#ifdef WL11U
+ bcm_tlv_t *interworking_ie;
+#endif
+
+ WL_DBG(("Enter \n"));
+
+ if ((dev == bcmcfg_to_prmry_ndev(cfg)) ||
+ (dev == ((struct net_device *)cfgdev_to_wlc_ndev(cfg->bss_cfgdev, cfg)))) {
+ WL_DBG(("Start AP req on primary iface: Softap\n"));
+ dev_role = NL80211_IFTYPE_AP;
+ }
+#if defined(WL_ENABLE_P2P_IF)
+ else if (dev == cfg->p2p_net) {
+ /* Group Add request on p2p0 */
+ WL_DBG(("Start AP req on P2P iface: GO\n"));
+#ifndef P2PONEINT
+ dev = bcmcfg_to_prmry_ndev(cfg);
+#endif
+ dev_role = NL80211_IFTYPE_P2P_GO;
+ }
+#endif /* WL_ENABLE_P2P_IF */
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ if (p2p_is_on(cfg) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
+ dev_role = NL80211_IFTYPE_P2P_GO;
+ WL_DBG(("Start AP req on P2P connection iface\n"));
+ } else if (dev_role == NL80211_IFTYPE_AP) {
+ WL_DBG(("Start AP req\n"));
+ dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
+
+#ifdef PKT_FILTER_SUPPORT
+ /* Disable packet filter */
+ if (dhd->early_suspended) {
+ WL_ERR(("Disable pkt_filter\n"));
+ dhd_enable_packet_filter(0, dhd);
+ }
+#endif /* PKT_FILTER_SUPPORT */
+#ifdef ARP_OFFLOAD_SUPPORT
+ /* IF SoftAP is enabled, disable arpoe */
+ if (dhd->op_mode & DHD_FLAG_STA_MODE) {
+ dhd_arp_offload_set(dhd, 0);
+ dhd_arp_offload_enable(dhd, FALSE);
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+ } else {
+ /* only AP or GO role need to be handled here. */
+ err = -EINVAL;
+ goto fail;
+ }
+
+ if (!check_dev_role_integrity(cfg, dev_role))
+ goto fail;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+ if ((err = wl_cfg80211_set_channel(wiphy, dev,
+ dev->ieee80211_ptr->preset_chandef.chan,
+ NL80211_CHAN_HT20) < 0)) {
+ WL_ERR(("Set channel failed \n"));
+ goto fail;
+ }
+#endif
+
+ if ((err = wl_cfg80211_bcn_set_params(info, dev,
+ dev_role, bssidx)) < 0) {
+ WL_ERR(("Beacon params set failed \n"));
+ goto fail;
+ }
+
+ /* Parse IEs */
+ if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
+ WL_ERR(("Set IEs failed \n"));
+ goto fail;
+ }
+
+ if ((wl_cfg80211_bcn_validate_sec(dev, &ies,
+ dev_role, bssidx)) < 0)
+ {
+ WL_ERR(("Beacon set security failed \n"));
+ goto fail;
+ }
+
+ if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
+ dev_role, bssidx)) < 0) {
+ WL_ERR(("Beacon bring up AP/GO failed \n"));
+ goto fail;
+ }
+
+ WL_DBG(("** AP/GO Created **\n"));
+
+#ifdef WL_CFG80211_ACL
+ /* Enfoce Admission Control. */
+ if ((err = wl_cfg80211_set_mac_acl(wiphy, dev, info->acl)) < 0) {
+ WL_ERR(("Set ACL failed\n"));
+ }
+#endif /* WL_CFG80211_ACL */
+
+#ifdef WL11U
+ /* Add interworking IE from beacon data */
+ if ((interworking_ie = wl_cfg80211_find_interworking_ie(
+ (u8 *)info->beacon.beacon_ies, info->beacon.beacon_ies_len)) != NULL) {
+ err = wl_cfg80211_add_iw_ie(cfg, dev, bssidx,
+ VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
+ interworking_ie->data, interworking_ie->len);
+ if (unlikely(err)) {
+ WL_ERR(("Failed to add interworking IE"));
+ }
+ } else if (cfg->iw_ie_len != 0) {
+ /* we have to clear IW IE and disable gratuitous APR */
+ wl_cfg80211_add_iw_ie(cfg, dev, bssidx,
+ VNDR_IE_CUSTOM_FLAG,
+ DOT11_MNG_INTERWORKING_ID,
+ 0, 0);
+
+ (void)wldev_iovar_setint_bsscfg(dev, "grat_arp", 0, bssidx);
+ cfg->wl11u = FALSE;
+ cfg->iw_ie_len = 0;
+ memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
+ /* we don't care about error */
+ }
+#endif /* WL11U */
+
+ /* Set IEs to FW */
+ if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
+ WL_ERR(("Set IEs failed \n"));
+
+ /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
+ if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
+ bool pbc = 0;
+ wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
+ if (pbc) {
+ WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
+ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
+ }
+ }
+
+fail:
+ if (err) {
+ WL_ERR(("ADD/SET beacon failed\n"));
+ wldev_iovar_setint(dev, "mpc", 1);
+ }
+
+ return err;
+}
+
+static s32
+wl_cfg80211_stop_ap(
+ struct wiphy *wiphy,
+ struct net_device *dev)
+{
+ int err = 0;
+ u32 dev_role = 0;
+ int infra = 0;
+ int ap = 0;
+ s32 bssidx = 0;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+
+ WL_DBG(("Enter \n"));
+
+ wl_clr_drv_status(cfg, AP_CREATING, dev);
+ wl_clr_drv_status(cfg, AP_CREATED, dev);
+
+ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
+ dev_role = NL80211_IFTYPE_AP;
+ WL_DBG(("stopping AP operation\n"));
+ } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
+ dev_role = NL80211_IFTYPE_P2P_GO;
+ WL_DBG(("stopping P2P GO operation\n"));
+ } else {
+ WL_ERR(("no AP/P2P GO interface is operational.\n"));
+ return -EINVAL;
+ }
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("find bss index from wdev(%p) failed\n", dev->ieee80211_ptr));
+ return BCME_ERROR;
+ }
+
+ if (!check_dev_role_integrity(cfg, dev_role))
+ goto exit;
+
+ if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 0)) < 0) {
+ WL_ERR(("bss down error %d\n", err));
+ }
+
+ if (dev_role == NL80211_IFTYPE_AP) {
+ /* SoftAp on primary Interface.
+ * Shut down AP and turn on MPC
+ */
+
+#ifdef PKT_FILTER_SUPPORT
+ /* Enable packet filter */
+ if (dhd->early_suspended) {
+ WL_ERR(("Enable pkt_filter\n"));
+ dhd_enable_packet_filter(1, dhd);
+ }
+#endif /* PKT_FILTER_SUPPORT */
+#ifdef ARP_OFFLOAD_SUPPORT
+ /* IF SoftAP is disabled, enable arpoe back for STA mode. */
+ if (dhd->op_mode & DHD_FLAG_STA_MODE) {
+ dhd_arp_offload_set(dhd, dhd_arp_mode);
+ dhd_arp_offload_enable(dhd, TRUE);
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+ /*
+ * Bring down the AP interface by changing role to STA.
+ * Don't do a down or "WLC_SET_AP 0" since the shared
+ * interface may be still running
+ */
+
+ WL_DBG(("Bring down AP interface by changing role to STA\n"));
+
+ if ((err = wl_cfg80211_add_del_bss(cfg, dev,
+ bssidx, NL80211_IFTYPE_STATION, 0, NULL)) < 0) {
+ WL_DBG(("wl add_del_bss returned error (%d)\n", err));
+ if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
+ WL_ERR(("setting AP mode failed %d \n", err));
+ err = -ENOTSUPP;
+ goto exit;
+ }
+ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+ if (err < 0) {
+ WL_ERR(("SET INFRA error %d\n", err));
+ err = -ENOTSUPP;
+ goto exit;
+ }
+
+ err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_UP error (%d)\n", err));
+ err = -EINVAL;
+ goto exit;
+ }
+ }
+
+ /* Turn on the MPC */
+ wldev_iovar_setint(dev, "mpc", 1);
+
+ wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
+ } else {
+ WL_DBG(("Stopping P2P GO \n"));
+ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
+ DHD_EVENT_TIMEOUT_MS*3);
+ DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
+ }
+
+exit:
+ if (dev_role == NL80211_IFTYPE_AP) {
+ /* clear the AP mode */
+ dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
+ }
+ return err;
+}
+
+static s32
+wl_cfg80211_change_beacon(
+ struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_beacon_data *info)
+{
+ s32 err = BCME_OK;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct parsed_ies ies;
+ u32 dev_role = 0;
+ s32 bssidx = 0;
+ bool pbc = 0;
+#ifdef WL11U
+ bcm_tlv_t *interworking_ie;
+#endif
+
+ WL_DBG(("Enter \n"));
+
+ if ((dev == bcmcfg_to_prmry_ndev(cfg)) ||
+ (dev == ((struct net_device *)cfgdev_to_wlc_ndev(cfg->bss_cfgdev, cfg)))) {
+ dev_role = NL80211_IFTYPE_AP;
+ }
+#if defined(WL_ENABLE_P2P_IF)
+ else if (dev == cfg->p2p_net) {
+ /* Group Add request on p2p0 */
+#ifndef P2PONEINT
+ dev = bcmcfg_to_prmry_ndev(cfg);
+#endif
+ dev_role = NL80211_IFTYPE_P2P_GO;
+ }
+#endif /* WL_ENABLE_P2P_IF */
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
+ dev_role = NL80211_IFTYPE_P2P_GO;
+ }
+
+ if (!check_dev_role_integrity(cfg, dev_role))
+ goto fail;
+
+ /* Parse IEs */
+ if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
+ WL_ERR(("Parse IEs failed \n"));
+ goto fail;
+ }
+
+ /* Set IEs to FW */
+ if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
+ WL_ERR(("Set IEs failed \n"));
+ goto fail;
+ }
+#ifdef WL11U
+ /* Add interworking IE from beacon data */
+ if ((interworking_ie = wl_cfg80211_find_interworking_ie(
+ (u8 *)info->beacon_ies, info->beacon_ies_len)) != NULL) {
+ err = wl_cfg80211_add_iw_ie(cfg, dev, bssidx,
+ VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
+ interworking_ie->data, interworking_ie->len);
+ if (unlikely(err)) {
+ WL_ERR(("Failed to add interworking IE"));
+ }
+ } else if (cfg->iw_ie_len != 0) {
+ /* we have to clear IW IE and disable gratuitous APR */
+ wl_cfg80211_add_iw_ie(cfg, dev, bssidx,
+ VNDR_IE_CUSTOM_FLAG,
+ DOT11_MNG_INTERWORKING_ID,
+ 0, 0);
+
+ (void)wldev_iovar_setint_bsscfg(dev, "grat_arp", 0, bssidx);
+ cfg->wl11u = FALSE;
+ cfg->iw_ie_len = 0;
+ memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
+ /* we don't care about error */
+ }
+#endif /* WL11U */
+
+
+ if (dev_role == NL80211_IFTYPE_AP) {
+ if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
+ WL_ERR(("Hostapd update sec failed \n"));
+ err = -EINVAL;
+ goto fail;
+ }
+ /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
+ if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
+ wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
+ WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
+ if (pbc)
+ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
+ else
+ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
+ }
+ }
+
+fail:
+ return err;
+}
+#else
+static s32
+wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
+ struct beacon_parameters *info)
+{
+ s32 err = BCME_OK;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ s32 ie_offset = 0;
+ s32 bssidx = 0;
+ u32 dev_role = NL80211_IFTYPE_AP;
+ struct parsed_ies ies;
+ bcm_tlv_t *ssid_ie;
+ bool pbc = 0;
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+
+ WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
+ info->interval, info->dtim_period, info->head_len, info->tail_len));
+
+ if (dev == bcmcfg_to_prmry_ndev(cfg)) {
+ dev_role = NL80211_IFTYPE_AP;
+ }
+#if defined(WL_ENABLE_P2P_IF)
+ else if (dev == cfg->p2p_net) {
+ /* Group Add request on p2p0 */
+#ifndef P2PONEINT
+ dev = bcmcfg_to_prmry_ndev(cfg);
+#endif
+ dev_role = NL80211_IFTYPE_P2P_GO;
+ }
+#endif /* WL_ENABLE_P2P_IF */
+
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
+ dev_role = NL80211_IFTYPE_P2P_GO;
+ } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
+ dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
+ }
+
+ if (!check_dev_role_integrity(cfg, dev_role))
+ goto fail;
+
+ ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
+ /* find the SSID */
+ if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
+ info->head_len - ie_offset,
+ DOT11_MNG_SSID_ID)) != NULL) {
+ if (dev_role == NL80211_IFTYPE_AP) {
+ /* Store the hostapd SSID */
+ memset(&cfg->hostapd_ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
+ cfg->hostapd_ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
+ memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data,
+ cfg->hostapd_ssid.SSID_len);
+ } else {
+ /* P2P GO */
+ memset(&cfg->p2p->ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
+ cfg->p2p->ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
+ memcpy(cfg->p2p->ssid.SSID, ssid_ie->data,
+ cfg->p2p->ssid.SSID_len);
+ }
+ }
+
+ if (wl_cfg80211_parse_ies((u8 *)info->tail,
+ info->tail_len, &ies) < 0) {
+ WL_ERR(("Beacon get IEs failed \n"));
+ err = -EINVAL;
+ goto fail;
+ }
+
+ if (wl_cfg80211_set_mgmt_vndr_ies(cfg, dev, bssidx,
+ VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
+ info->tail_len) < 0) {
+ WL_ERR(("Beacon set IEs failed \n"));
+ goto fail;
+ } else {
+ WL_DBG(("Applied Vndr IEs for Beacon \n"));
+ }
+ if (!wl_cfgp2p_bss_isup(dev, bssidx) &&
+ (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx) < 0))
+ {
+ WL_ERR(("Beacon set security failed \n"));
+ goto fail;
+ }
+
+ /* Set BI and DTIM period */
+ if (info->interval) {
+ if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
+ &info->interval, sizeof(s32), true)) < 0) {
+ WL_ERR(("Beacon Interval Set Error, %d\n", err));
+ return err;
+ }
+ }
+ if (info->dtim_period) {
+ if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
+ &info->dtim_period, sizeof(s32), true)) < 0) {
+ WL_ERR(("DTIM Interval Set Error, %d\n", err));
+ return err;
+ }
+ }
+
+ if (wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx) < 0) {
+ WL_ERR(("Beacon bring up AP/GO failed \n"));
+ goto fail;
+ }
+
+ if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
+ /* Soft AP already running. Update changed params */
+ if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
+ WL_ERR(("Hostapd update sec failed \n"));
+ err = -EINVAL;
+ goto fail;
+ }
+ }
+
+ /* Enable Probe Req filter */
+ if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
+ (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
+ wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
+ if (pbc)
+ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
+ }
+
+ WL_DBG(("** ADD/SET beacon done **\n"));
+
+fail:
+ if (err) {
+ WL_ERR(("ADD/SET beacon failed\n"));
+ wldev_iovar_setint(dev, "mpc", 1);
+ }
+ return err;
+
+}
+#endif
+
+#ifdef WL_SCHED_SCAN
+#define PNO_TIME 30
+#define PNO_REPEAT 4
+#define PNO_FREQ_EXPO_MAX 2
+static int
+wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_sched_scan_request *request)
+{
+ ushort pno_time = PNO_TIME;
+ int pno_repeat = PNO_REPEAT;
+ int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
+ wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct cfg80211_ssid *ssid = NULL;
+ int ssid_count = 0;
+ int i;
+ int ret = 0;
+
+ if (!request) {
+ WL_ERR(("Sched scan request was NULL\n"));
+ return -EINVAL;
+ }
+
+ WL_DBG(("Enter \n"));
+ WL_PNO((">>> SCHED SCAN START\n"));
+ WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
+ request->n_match_sets, request->n_ssids));
+ WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
+ request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
+
+
+ if (!request->n_ssids || !request->n_match_sets) {
+ WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
+ return -EINVAL;
+ }
+
+ memset(&ssids_local, 0, sizeof(ssids_local));
+
+ if (request->n_match_sets > 0) {
+ for (i = 0; i < request->n_match_sets; i++) {
+ ssid = &request->match_sets[i].ssid;
+ ssids_local[ssid_count].SSID_len = MIN(ssid->ssid_len,
+ (uint32)DOT11_MAX_SSID_LEN);
+ memcpy(ssids_local[ssid_count].SSID, ssid->ssid,
+ ssids_local[ssid_count].SSID_len);
+ WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
+ ssid_count++;
+ }
+ }
+
+ if (request->n_ssids > 0) {
+ for (i = 0; i < request->n_ssids; i++) {
+ /* Active scan req for ssids */
+ WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
+
+ /* match_set ssids is a supert set of n_ssid list, so we need
+ * not add these set seperately
+ */
+ }
+ }
+
+ if (ssid_count) {
+ if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets,
+ pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
+ WL_ERR(("PNO setup failed!! ret=%d \n", ret));
+ return -EINVAL;
+ }
+ cfg->sched_scan_req = request;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+
+ WL_DBG(("Enter \n"));
+ WL_PNO((">>> SCHED SCAN STOP\n"));
+
+ if (dhd_dev_pno_stop_for_ssid(dev) < 0)
+ WL_ERR(("PNO Stop for SSID failed"));
+
+ if (cfg->scan_request && cfg->sched_scan_running) {
+ WL_PNO((">>> Sched scan running. Aborting it..\n"));
+ wl_notify_escan_complete(cfg, dev, true, true);
+ }
+
+ cfg->sched_scan_req = NULL;
+ cfg->sched_scan_running = FALSE;
+
+ return 0;
+}
+#endif /* WL_SCHED_SCAN */
+
+#ifdef WL_SUPPORT_ACS
+/*
+ * Currently the dump_obss IOVAR is returning string as output so we need to
+ * parse the output buffer in an unoptimized way. Going forward if we get the
+ * IOVAR output in binary format this method can be optimized
+ */
+static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
+{
+ int i;
+ char *token;
+ char delim[] = " \n";
+
+ token = strsep(&buf, delim);
+ while (token != NULL) {
+ if (!strcmp(token, "OBSS")) {
+ for (i = 0; i < OBSS_TOKEN_IDX; i++)
+ token = strsep(&buf, delim);
+ survey->obss = simple_strtoul(token, NULL, 10);
+ }
+
+ if (!strcmp(token, "IBSS")) {
+ for (i = 0; i < IBSS_TOKEN_IDX; i++)
+ token = strsep(&buf, delim);
+ survey->ibss = simple_strtoul(token, NULL, 10);
+ }
+
+ if (!strcmp(token, "TXDur")) {
+ for (i = 0; i < TX_TOKEN_IDX; i++)
+ token = strsep(&buf, delim);
+ survey->tx = simple_strtoul(token, NULL, 10);
+ }
+
+ if (!strcmp(token, "Category")) {
+ for (i = 0; i < CTG_TOKEN_IDX; i++)
+ token = strsep(&buf, delim);
+ survey->no_ctg = simple_strtoul(token, NULL, 10);
+ }
+
+ if (!strcmp(token, "Packet")) {
+ for (i = 0; i < PKT_TOKEN_IDX; i++)
+ token = strsep(&buf, delim);
+ survey->no_pckt = simple_strtoul(token, NULL, 10);
+ }
+
+ if (!strcmp(token, "Opp(time):")) {
+ for (i = 0; i < IDLE_TOKEN_IDX; i++)
+ token = strsep(&buf, delim);
+ survey->idle = simple_strtoul(token, NULL, 10);
+ }
+
+ token = strsep(&buf, delim);
+ }
+
+ return 0;
+}
+
+static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
+ struct wl_dump_survey *survey)
+{
+ cca_stats_n_flags *results;
+ char *buf;
+ int retry, err;
+
+ buf = kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN, GFP_KERNEL);
+ if (unlikely(!buf)) {
+ WL_ERR(("%s: buf alloc failed\n", __func__));
+ return -ENOMEM;
+ }
+
+ retry = IOCTL_RETRY_COUNT;
+ while (retry--) {
+ err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
+ buf, WLC_IOCTL_MAXLEN, NULL);
+ if (err >= 0) {
+ break;
+ }
+ WL_DBG(("attempt = %d, err = %d, \n",
+ (IOCTL_RETRY_COUNT - retry), err));
+ }
+
+ if (retry <= 0) {
+ WL_ERR(("failure, dump_obss IOVAR failed\n"));
+ err = -EINVAL;
+ goto exit;
+ }
+
+ results = (cca_stats_n_flags *)(buf);
+ wl_parse_dump_obss(results->buf, survey);
+ kfree(buf);
+
+ return 0;
+exit:
+ kfree(buf);
+ return err;
+}
+
+static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
+ int idx, struct survey_info *info)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct wl_dump_survey *survey;
+ struct ieee80211_supported_band *band;
+ struct ieee80211_channel*chan;
+ cca_msrmnt_query req;
+ int val, err, noise, retry;
+ uint8 cache_idx;
+
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
+ return -ENOENT;
+ }
+ band = wiphy->bands[NL80211_BAND_2GHZ];
+ if (band && idx >= band->n_channels) {
+ idx -= band->n_channels;
+ band = NULL;
+ }
+
+ if (!band || idx >= band->n_channels) {
+ /* Move to 5G band */
+ band = wiphy->bands[NL80211_BAND_5GHZ];
+ if (!band || idx >= band->n_channels) {
+ return -ENOENT;
+ }
+ }
+
+ chan = &band->channels[idx];
+ /*
+ * Avoid unnecessary time spent on getting obss on channels
+ * which are not used by hostapd in current mode.
+ */
+ for (cache_idx = 0; cache_idx < g_hostap_chan_count; cache_idx++) {
+ if (g_hostap_chan_cache[cache_idx] == chan->center_freq)
+ break;
+ }
+ if (cache_idx == g_hostap_chan_count)
+ {
+ WL_DBG(("%s channel %d is ignored & dummy value is passed \n",
+ __func__, ieee80211_frequency_to_channel(chan->center_freq)));
+ info->channel = chan;
+ info->noise = 0;
+ info->channel_time = 0;
+ info->channel_time_busy = 0;
+ info->channel_time_rx = 0;
+ info->channel_time_tx = 0;
+ info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ return 0;
+ }
+
+ /* Setting current channel to the requested channel */
+ if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
+ NL80211_CHAN_HT20) < 0)) {
+ WL_ERR(("Set channel failed \n"));
+ }
+
+ if (!idx) {
+ /* Disable mpc */
+ val = 0;
+ err = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
+ sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
+ &cfg->ioctl_buf_sync);
+ if (err < 0) {
+ WL_ERR(("set 'mpc' failed, error = %d\n", err));
+ }
+
+ /* Set interface up, explicitly. */
+ val = 1;
+ err = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
+ if (err < 0) {
+ WL_ERR(("set interface up failed, error = %d\n", err));
+ }
+ }
+
+ /* Get noise value */
+ retry = IOCTL_RETRY_COUNT;
+ while (retry--) {
+ err = wldev_ioctl(ndev, WLC_GET_PHY_NOISE, &noise,
+ sizeof(noise), false);
+ if (err >= 0) {
+ break;
+ }
+ WL_DBG(("attempt = %d, err = %d, \n",
+ (IOCTL_RETRY_COUNT - retry), err));
+ }
+
+ if (retry <= 0) {
+ WL_ERR(("Get Phy Noise failed, error = %d\n", err));
+ noise = CHAN_NOISE_DUMMY;
+ }
+
+ survey = (struct wl_dump_survey *) kzalloc(sizeof(struct wl_dump_survey),
+ GFP_KERNEL);
+ if (unlikely(!survey)) {
+ WL_ERR(("%s: alloc failed\n", __func__));
+ return -ENOMEM;
+ }
+
+ /* Start Measurement for obss stats on current channel */
+ req.msrmnt_query = 0;
+ req.time_req = ACS_MSRMNT_DELAY;
+ if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
+ goto exit;
+ }
+
+ /*
+ * Wait for the meaurement to complete, adding a buffer value of 10 to take
+ * into consideration any delay in IOVAR completion
+ */
+ msleep(ACS_MSRMNT_DELAY + 10);
+
+ /* Issue IOVAR to collect measurement results */
+ req.msrmnt_query = 1;
+ if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
+ goto exit;
+ }
+
+ info->channel = chan;
+ info->noise = noise;
+ info->channel_time = ACS_MSRMNT_DELAY;
+ info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
+ info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
+ survey->no_pckt;
+ info->channel_time_tx = survey->tx;
+ info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ kfree(survey);
+
+ return 0;
+exit:
+ kfree(survey);
+ return err;
+}
+#endif /* WL_SUPPORT_ACS */
+
+static struct cfg80211_ops wl_cfg80211_ops = {
+ .add_virtual_intf = wl_cfg80211_add_virtual_iface,
+ .del_virtual_intf = wl_cfg80211_del_virtual_iface,
+ .change_virtual_intf = wl_cfg80211_change_virtual_iface,
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ .start_p2p_device = wl_cfgp2p_start_p2p_device,
+ .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ .scan = wl_cfg80211_scan,
+ .set_wiphy_params = wl_cfg80211_set_wiphy_params,
+ .join_ibss = wl_cfg80211_join_ibss,
+ .leave_ibss = wl_cfg80211_leave_ibss,
+ .get_station = wl_cfg80211_get_station,
+ .set_tx_power = wl_cfg80211_set_tx_power,
+ .get_tx_power = wl_cfg80211_get_tx_power,
+ .add_key = wl_cfg80211_add_key,
+ .del_key = wl_cfg80211_del_key,
+ .get_key = wl_cfg80211_get_key,
+ .set_default_key = wl_cfg80211_config_default_key,
+ .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
+ .set_power_mgmt = wl_cfg80211_set_power_mgmt,
+ .connect = wl_cfg80211_connect,
+ .disconnect = wl_cfg80211_disconnect,
+ .suspend = wl_cfg80211_suspend,
+ .resume = wl_cfg80211_resume,
+ .set_pmksa = wl_cfg80211_set_pmksa,
+ .del_pmksa = wl_cfg80211_del_pmksa,
+ .flush_pmksa = wl_cfg80211_flush_pmksa,
+ .remain_on_channel = wl_cfg80211_remain_on_channel,
+ .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
+ .mgmt_tx = wl_cfg80211_mgmt_tx,
+ .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
+ .change_bss = wl_cfg80211_change_bss,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+ .set_channel = wl_cfg80211_set_channel,
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
+ .set_beacon = wl_cfg80211_add_set_beacon,
+ .add_beacon = wl_cfg80211_add_set_beacon,
+#else
+ .change_beacon = wl_cfg80211_change_beacon,
+ .start_ap = wl_cfg80211_start_ap,
+ .stop_ap = wl_cfg80211_stop_ap,
+#endif
+#ifdef WL_SCHED_SCAN
+ .sched_scan_start = wl_cfg80211_sched_scan_start,
+ .sched_scan_stop = wl_cfg80211_sched_scan_stop,
+#endif /* WL_SCHED_SCAN */
+#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
+ 2, 0))
+ .del_station = wl_cfg80211_del_station,
+ .change_station = wl_cfg80211_change_station,
+ .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
+#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
+ .tdls_mgmt = wl_cfg80211_tdls_mgmt,
+ .tdls_oper = wl_cfg80211_tdls_oper,
+#endif
+#ifdef WL_SUPPORT_ACS
+ .dump_survey = wl_cfg80211_dump_survey,
+#endif /* WL_SUPPORT_ACS */
+#ifdef WL_CFG80211_ACL
+ .set_mac_acl = wl_cfg80211_set_mac_acl,
+#endif /* WL_CFG80211_ACL */
+ CFG80211_TESTMODE_CMD(dhd_cfg80211_testmode_cmd)
+};
+
+s32 wl_mode_to_nl80211_iftype(s32 mode)
+{
+ s32 err = 0;
+
+ switch (mode) {
+ case WL_MODE_BSS:
+ return NL80211_IFTYPE_STATION;
+ case WL_MODE_IBSS:
+ return NL80211_IFTYPE_ADHOC;
+ case WL_MODE_AP:
+ return NL80211_IFTYPE_AP;
+ default:
+ return NL80211_IFTYPE_UNSPECIFIED;
+ }
+
+ return err;
+}
+
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+static int
+wl_cfg80211_reg_notifier(
+ struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
+ int ret = 0;
+
+ if (!request || !cfg) {
+ WL_ERR(("Invalid arg\n"));
+ return -EINVAL;
+ }
+
+ WL_DBG(("ccode: %c%c Initiator: %d\n",
+ request->alpha2[0], request->alpha2[1], request->initiator));
+
+ /* We support only REGDOM_SET_BY_USER as of now */
+ if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
+ (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
+ WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
+ request->initiator));
+ /* in case of no supported country by regdb
+ lets driver setup platform default Locale
+ */
+ }
+
+ WL_ERR(("Set country code %c%c from %s\n",
+ request->alpha2[0], request->alpha2[1],
+ ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
+
+ if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
+ false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false))) < 0) {
+ WL_ERR(("set country Failed :%d\n", ret));
+ }
+
+ return ret;
+}
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
+
+#ifdef CONFIG_PM
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+static const struct wiphy_wowlan_support brcm_wowlan_support = {
+ .flags = WIPHY_WOWLAN_ANY,
+ .n_patterns = WL_WOWLAN_MAX_PATTERNS,
+ .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
+ .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+ .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
+};
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
+#endif /* CONFIG_PM */
+
+static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *context)
+{
+ s32 err = 0;
+#ifdef CONFIG_PM
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+ struct cfg80211_wowlan *brcm_wowlan_config = NULL;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
+#endif /* CONFIG_PM */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ dhd_pub_t *dhd = (dhd_pub_t *)context;
+ BCM_REFERENCE(dhd);
+
+ if (!dhd) {
+ WL_ERR(("DHD is NULL!!"));
+ err = -ENODEV;
+ return err;
+ }
+#endif
+
+ wdev->wiphy =
+ wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
+ if (unlikely(!wdev->wiphy)) {
+ WL_ERR(("Couldn not allocate wiphy device\n"));
+ err = -ENOMEM;
+ return err;
+ }
+ set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
+ wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
+ /* Report how many SSIDs Driver can support per Scan request */
+ wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
+ wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+#ifdef WL_SCHED_SCAN
+ wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
+ wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
+ wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
+ wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+#endif /* WL_SCHED_SCAN */
+ wdev->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_STATION)
+ | BIT(NL80211_IFTYPE_ADHOC)
+#if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
+ | BIT(NL80211_IFTYPE_MONITOR)
+#endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
+#if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
+ | BIT(NL80211_IFTYPE_P2P_CLIENT)
+ | BIT(NL80211_IFTYPE_P2P_GO)
+#endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ | BIT(NL80211_IFTYPE_P2P_DEVICE)
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ | BIT(NL80211_IFTYPE_AP);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
+ (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
+ WL_DBG(("Setting interface combinations for common mode\n"));
+ wdev->wiphy->iface_combinations = common_iface_combinations;
+ wdev->wiphy->n_iface_combinations =
+ ARRAY_SIZE(common_iface_combinations);
+#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
+
+ wdev->wiphy->bands[NL80211_BAND_2GHZ] = &__wl_band_2ghz;
+
+ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wdev->wiphy->cipher_suites = __wl_cipher_suites;
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+ wdev->wiphy->max_remain_on_channel_duration = 5000;
+ wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
+#ifndef WL_POWERSAVE_DISABLED
+ wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+#else
+ wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+#endif /* !WL_POWERSAVE_DISABLED */
+ wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
+ WIPHY_FLAG_4ADDR_AP |
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
+ WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
+#endif
+ WIPHY_FLAG_4ADDR_STATION;
+#if (defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
+ KERNEL_VERSION(3, 2, 0))
+ /* Please use supplicant ver >= 76 if FW_ROAM is enabled
+ * If driver advertises FW_ROAM, older supplicant wouldn't
+ * send the BSSID & Freq in the connect req command. This
+ * will delay the ASSOC as the FW need to do a full scan
+ * before attempting to connect. Supplicant >=76 has patch
+ * to allow bssid & freq to be sent down to driver even if
+ * FW ROAM is advertised.
+ */
+ wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+ wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+ WIPHY_FLAG_OFFCHAN_TX;
+#endif
+#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
+ 4, 0))
+ /* From 3.4 kernel ownards AP_SME flag can be advertised
+ * to remove the patch from supplicant
+ */
+ wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
+
+#ifdef WL_CFG80211_ACL
+ /* Configure ACL capabilities. */
+ wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ /* Supplicant distinguish between the SoftAP mode and other
+ * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
+ * response frame from Supplicant MR1 and Kernel 3.4.0 or
+ * later version. To add Vendor specific IE into the
+ * probe response frame in case of SoftAP mode,
+ * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
+ */
+ if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
+ wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+ wdev->wiphy->probe_resp_offload = 0;
+ }
+#endif
+#endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
+
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+ wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
+ wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
+#endif
+
+#if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
+ /*
+ * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
+ * disconnection of connected network before suspend. So a dummy wowlan
+ * filter is configured for kernels linux-3.8 and above.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+ wdev->wiphy->wowlan = &brcm_wowlan_support;
+
+ /* If this is not provided cfg stack will get disconnect
+ * during suspend.
+ */
+ brcm_wowlan_config = kzalloc(sizeof(struct cfg80211_wowlan), GFP_KERNEL);
+ if (brcm_wowlan_config) {
+ brcm_wowlan_config->disconnect = true;
+ brcm_wowlan_config->gtk_rekey_failure = true;
+ brcm_wowlan_config->eap_identity_req = true;
+ brcm_wowlan_config->four_way_handshake = true;
+ brcm_wowlan_config->patterns = NULL;
+ brcm_wowlan_config->n_patterns = 0;
+ brcm_wowlan_config->tcp = NULL;
+ } else {
+ WL_ERR(("Can not allocate memory for brcm_wowlan_config,"
+ " So wiphy->wowlan_config is set to NULL\n"));
+ }
+ wdev->wiphy->wowlan_config = brcm_wowlan_config;
+#else
+ wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
+ wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
+ wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
+ wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+ wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
+#endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
+
+ WL_DBG(("Registering custom regulatory)\n"));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+#else
+ wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+#endif
+ wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+ WL_INFO(("Registering Vendor80211)\n"));
+ err = wl_cfgvendor_attach(wdev->wiphy);
+ if (unlikely(err < 0)) {
+ WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
+ }
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
+
+
+ /* Now we can register wiphy with cfg80211 module */
+ err = wiphy_register(wdev->wiphy);
+ if (unlikely(err < 0)) {
+ WL_ERR(("Couldn not register wiphy device (%d)\n", err));
+ wiphy_free(wdev->wiphy);
+ }
+
+#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
+ KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
+ wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
+#endif
+
+ return err;
+}
+
+static void wl_free_wdev(struct bcm_cfg80211 *cfg)
+{
+ struct wireless_dev *wdev = cfg->wdev;
+ struct wiphy *wiphy = NULL;
+ if (!wdev) {
+ WL_ERR(("wdev is invalid\n"));
+ return;
+ }
+ if (wdev->wiphy) {
+ wiphy = wdev->wiphy;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+ wl_cfgvendor_detach(wdev->wiphy);
+ wdev->wiphy->wowlan = NULL;
+#endif /* if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
+ wiphy_unregister(wdev->wiphy);
+ wdev->wiphy->dev.parent = NULL;
+ wdev->wiphy = NULL;
+ }
+
+ wl_delete_all_netinfo(cfg);
+ if (wiphy)
+ wiphy_free(wiphy);
+ /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
+ * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
+ */
+}
+
+static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
+{
+ struct wl_scan_results *bss_list;
+ struct wl_bss_info *bi = NULL; /* must be initialized */
+ s32 err = 0;
+ s32 i;
+
+ bss_list = cfg->bss_list;
+ WL_DBG(("scanned AP count (%d)\n", bss_list->count));
+ bi = next_bss(bss_list, bi);
+ for_each_bss(bss_list, bi, i) {
+ err = wl_inform_single_bss(cfg, bi, false);
+ if (unlikely(err))
+ break;
+ }
+ return err;
+}
+
+static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam)
+{
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ struct ieee80211_mgmt *mgmt;
+ struct ieee80211_channel *channel;
+ struct ieee80211_supported_band *band;
+ struct wl_cfg80211_bss_info *notif_bss_info;
+ struct wl_scan_req *sr = wl_to_sr(cfg);
+ struct beacon_proberesp *beacon_proberesp;
+ struct cfg80211_bss *cbss = NULL;
+ s32 mgmt_type;
+ s32 signal;
+ u32 freq;
+ s32 err = 0;
+ gfp_t aflags;
+
+ if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
+ WL_DBG(("Beacon is larger than buffer. Discarding\n"));
+ return err;
+ }
+ aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
+ notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
+ - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
+ if (unlikely(!notif_bss_info)) {
+ WL_ERR(("notif_bss_info alloc failed\n"));
+ return -ENOMEM;
+ }
+ mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
+ notif_bss_info->channel =
+ bi->ctl_ch ? bi->ctl_ch : wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
+
+ if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[NL80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[NL80211_BAND_5GHZ];
+ if (!band) {
+ WL_ERR(("No valid band"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+ notif_bss_info->rssi = wl_rssi_offset(dtoh16(bi->RSSI));
+ memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
+ mgmt_type = cfg->active_scan ?
+ IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
+ if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
+ }
+ beacon_proberesp = cfg->active_scan ?
+ (struct beacon_proberesp *)&mgmt->u.probe_resp :
+ (struct beacon_proberesp *)&mgmt->u.beacon;
+ beacon_proberesp->timestamp = 0;
+ beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
+ beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
+ wl_rst_ie(cfg);
+ wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, roam);
+ wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
+ wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
+ offsetof(struct wl_cfg80211_bss_info, frame_buf));
+ notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
+ u.beacon.variable) + wl_get_ielen(cfg);
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+ freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
+ (void)band->band;
+#else
+ freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
+#endif
+ if (freq == 0) {
+ WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+ channel = ieee80211_get_channel(wiphy, freq);
+ if (unlikely(!channel)) {
+ WL_ERR(("ieee80211_get_channel error\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+ WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
+ "mgmt_type %d frame_len %d\n", bi->SSID,
+ notif_bss_info->rssi, notif_bss_info->channel,
+ mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
+ notif_bss_info->frame_len));
+
+ signal = notif_bss_info->rssi * 100;
+ if (!mgmt->u.probe_resp.timestamp) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+ struct timespec ts;
+ get_monotonic_boottime(&ts);
+ mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
+ + ts.tv_nsec / 1000;
+#else
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
+ + tv.tv_usec;
+#endif
+ }
+
+
+ cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
+ le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
+ if (unlikely(!cbss)) {
+ WL_ERR(("cfg80211_inform_bss_frame error\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+ cfg80211_put_bss(wiphy, cbss);
+#else
+ cfg80211_put_bss(cbss);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
+ kfree(notif_bss_info);
+ return err;
+}
+
+static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
+{
+ u32 event = ntoh32(e->event_type);
+ u32 status = ntoh32(e->status);
+ u16 flags = ntoh16(e->flags);
+
+ WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
+ if (event == WLC_E_SET_SSID) {
+ if (status == WLC_E_STATUS_SUCCESS) {
+ if (!wl_is_ibssmode(cfg, ndev))
+ return true;
+ }
+ } else if (event == WLC_E_LINK) {
+ if (flags & WLC_EVENT_MSG_LINK)
+ return true;
+ }
+
+ WL_DBG(("wl_is_linkup false\n"));
+ return false;
+}
+
+static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
+{
+ u32 event = ntoh32(e->event_type);
+ u16 flags = ntoh16(e->flags);
+
+ if (event == WLC_E_DEAUTH_IND ||
+ event == WLC_E_DISASSOC_IND ||
+ event == WLC_E_DISASSOC ||
+ event == WLC_E_DEAUTH) {
+#if (WL_DBG_LEVEL > 0)
+ WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
+#endif /* (WL_DBG_LEVEL > 0) */
+ return true;
+ } else if (event == WLC_E_LINK) {
+ if (!(flags & WLC_EVENT_MSG_LINK)) {
+#if (WL_DBG_LEVEL > 0)
+ WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
+#endif /* (WL_DBG_LEVEL > 0) */
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
+{
+ u32 event = ntoh32(e->event_type);
+ u32 status = ntoh32(e->status);
+
+ if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
+ return true;
+ if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
+ return true;
+
+ return false;
+}
+
+/* The mainline kernel >= 3.2.0 has support for indicating new/del station
+ * to AP/P2P GO via events. If this change is backported to kernel for which
+ * this driver is being built, then define WL_CFG80211_STA_EVENT. You
+ * should use this new/del sta event mechanism for BRCM supplicant >= 22.
+ */
+static s32
+wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = 0;
+ u32 event = ntoh32(e->event_type);
+ u32 reason = ntoh32(e->reason);
+ u32 len = ntoh32(e->datalen);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
+ bool isfree = false;
+ u8 *mgmt_frame;
+ u8 bsscfgidx = e->bsscfgidx;
+ s32 freq;
+ s32 channel;
+ u8 *body = NULL;
+ u16 fc = 0;
+
+ struct ieee80211_supported_band *band;
+ struct ether_addr da;
+ struct ether_addr bssid;
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ channel_info_t ci;
+#else
+ struct station_info sinfo;
+#endif
+
+ WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
+ /* if link down, bsscfg is disabled. */
+ if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
+ wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
+ wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
+ WL_INFO(("AP mode link down !! \n"));
+ complete(&cfg->iface_disable);
+ return 0;
+ }
+
+ if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
+ WL_ERR(("event %s(%d) status %d reason %d\n",
+ bcmevent_names[event].name, event, ntoh32(e->status), reason));
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
+ WL_DBG(("Enter \n"));
+ if (!len && (event == WLC_E_DEAUTH)) {
+ len = 2; /* reason code field */
+ data = &reason;
+ }
+ if (len) {
+ body = kzalloc(len, GFP_KERNEL);
+
+ if (body == NULL) {
+ WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
+ return WL_INVALID;
+ }
+ }
+ memset(&bssid, 0, ETHER_ADDR_LEN);
+ WL_DBG(("Enter event %d ndev %p\n", event, ndev));
+ if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
+ kfree(body);
+ return WL_INVALID;
+ }
+ if (len)
+ memcpy(body, data, len);
+
+ wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+ NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
+ memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
+ err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
+ switch (event) {
+ case WLC_E_ASSOC_IND:
+ fc = FC_ASSOC_REQ;
+ break;
+ case WLC_E_REASSOC_IND:
+ fc = FC_REASSOC_REQ;
+ break;
+ case WLC_E_DISASSOC_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH:
+ fc = FC_DISASSOC;
+ break;
+ default:
+ fc = 0;
+ goto exit;
+ }
+ if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
+ kfree(body);
+ return err;
+ }
+
+ channel = dtoh32(ci.hw_channel);
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[NL80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[NL80211_BAND_5GHZ];
+ if (!band) {
+ WL_ERR(("No valid band"));
+ if (body)
+ kfree(body);
+ return -EINVAL;
+ }
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+ freq = ieee80211_channel_to_frequency(channel);
+ (void)band->band;
+#else
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+
+ err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
+ &mgmt_frame, &len, body);
+ if (err < 0)
+ goto exit;
+ isfree = true;
+
+ if ((event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) ||
+ (event == WLC_E_DISASSOC_IND) ||
+ ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH))) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
+ defined(WL_COMPAT_WIRELESS)
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+ } else if (event == WLC_E_DISASSOC_IND) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+ } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+ }
+exit:
+ if (isfree)
+ kfree(mgmt_frame);
+ if (body)
+ kfree(body);
+#else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
+ sinfo.filled = 0;
+ if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
+ reason == DOT11_SC_SUCCESS) {
+ /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
+ * STATION_INFO_ASSOC_REQ_IES flag
+ */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
+ sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
+ if (!data) {
+ WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
+ return -EINVAL;
+ }
+ sinfo.assoc_req_ies = data;
+ sinfo.assoc_req_ies_len = len;
+ cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
+ } else if (event == WLC_E_DISASSOC_IND) {
+ cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
+ } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
+ cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
+ }
+#endif
+ return err;
+}
+
+static s32
+wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e)
+{
+ u32 reason = ntoh32(e->reason);
+ u32 event = ntoh32(e->event_type);
+ struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
+ WL_DBG(("event type : %d, reason : %d\n", event, reason));
+ if (sec) {
+ switch (event) {
+ case WLC_E_ASSOC:
+ case WLC_E_AUTH:
+ sec->auth_assoc_res_status = reason;
+ default:
+ break;
+ }
+ } else
+ WL_ERR(("sec is NULL\n"));
+ return 0;
+}
+
+static s32
+wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = 0;
+ u32 event = ntoh32(e->event_type);
+ u16 flags = ntoh16(e->flags);
+ u32 status = ntoh32(e->status);
+ bool active;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ struct ieee80211_channel *channel = NULL;
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ u32 chanspec, chan;
+ u32 freq, band;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
+
+ if (event == WLC_E_JOIN) {
+ WL_DBG(("joined in IBSS network\n"));
+ }
+ if (event == WLC_E_START) {
+ WL_DBG(("started IBSS network\n"));
+ }
+ if (event == WLC_E_JOIN || event == WLC_E_START ||
+ (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
+ if (unlikely(err)) {
+ WL_ERR(("Could not get chanspec %d\n", err));
+ return err;
+ }
+ chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
+ band = (chan <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
+ freq = ieee80211_channel_to_frequency(chan, band);
+ channel = ieee80211_get_channel(wiphy, freq);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
+ if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
+ /* ROAM or Redundant */
+ u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
+ if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
+ WL_DBG(("IBSS connected event from same BSSID("
+ MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
+ return err;
+ }
+ WL_INFO(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
+ MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr)));
+ wl_get_assoc_ies(cfg, ndev);
+ wl_update_prof(cfg, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
+ wl_update_bss_info(cfg, ndev, false);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ cfg80211_ibss_joined(ndev, (s8 *)&e->addr, channel, GFP_KERNEL);
+#else
+ cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
+#endif
+ }
+ else {
+ /* New connection */
+ WL_INFO(("IBSS connected to " MACDBG "\n", MAC2STRDBG((u8 *)&e->addr)));
+ wl_link_up(cfg);
+ wl_get_assoc_ies(cfg, ndev);
+ wl_update_prof(cfg, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
+ wl_update_bss_info(cfg, ndev, false);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ cfg80211_ibss_joined(ndev, (s8 *)&e->addr, channel, GFP_KERNEL);
+#else
+ cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
+#endif
+ wl_set_drv_status(cfg, CONNECTED, ndev);
+ active = true;
+ wl_update_prof(cfg, ndev, NULL, (void *)&active, WL_PROF_ACT);
+ }
+ } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
+ event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
+ wl_clr_drv_status(cfg, CONNECTED, ndev);
+ wl_clr_drv_status(cfg, DISCONNECTING, ndev);
+ wl_link_down(cfg);
+ wl_init_prof(cfg, ndev);
+ }
+ else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
+ WL_DBG(("no action - join fail (IBSS mode)\n"));
+ }
+ else {
+ WL_DBG(("no action (IBSS mode)\n"));
+}
+ return err;
+}
+
+static s32
+wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ bool act;
+ struct net_device *ndev = NULL;
+ s32 err = 0;
+ u32 event = ntoh32(e->event_type);
+ struct wiphy *wiphy = NULL;
+ struct cfg80211_bss *bss = NULL;
+ struct wlc_ssid *ssid = NULL;
+ u8 *bssid = 0;
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
+ err = wl_notify_connect_status_ap(cfg, ndev, e, data);
+ } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) {
+ err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
+ } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
+ WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
+ ntoh32(e->event_type), ntoh32(e->status), ndev));
+ if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
+ wl_get_auth_assoc_status(cfg, ndev, e);
+ return 0;
+ }
+ if (wl_is_linkup(cfg, e, ndev)) {
+ wl_link_up(cfg);
+ act = true;
+ if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
+ printk("wl_bss_connect_done succeeded with " MACDBG "\n",
+ MAC2STRDBG((u8*)(&e->addr)));
+ wl_bss_connect_done(cfg, ndev, e, data, true);
+ WL_DBG(("joined in BSS network \"%s\"\n",
+ ((struct wlc_ssid *)
+ wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
+ }
+ wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
+ wl_update_prof(cfg, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
+
+ } else if (wl_is_linkdown(cfg, e)) {
+ if (cfg->scan_request)
+ wl_notify_escan_complete(cfg, ndev, true, true);
+ /* Explicitly calling unlink to remove BSS in CFG */
+ wiphy = bcmcfg_to_wiphy(cfg);
+ ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
+ bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
+ if (ssid && bssid) {
+ bss = cfg80211_get_bss(wiphy, NULL, bssid,
+ ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+ if (bss) {
+ cfg80211_unlink_bss(wiphy, bss);
+ }
+ }
+ if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
+ scb_val_t scbval;
+ u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
+ s32 reason = 0;
+ struct ether_addr bssid;
+
+ if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
+ reason = ntoh32(e->reason);
+ /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
+ reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
+
+ printk("link down if %s may call cfg80211_disconnected. "
+ "event : %d, reason=%d from " MACDBG "\n",
+ ndev->name, event, ntoh32(e->reason),
+ MAC2STRDBG((u8*)(&e->addr)));
+
+ /* roam offload does not synch BSSID always, get it from dongle */
+ if (cfg->roam_offload) {
+ if (wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, sizeof(bssid),
+ false) == BCME_OK) {
+ curbssid = (u8 *)&bssid;
+ }
+ }
+
+ if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
+ WL_ERR(("BSSID of event is not the connected BSSID"
+ "(ignore it) cur: " MACDBG " event: " MACDBG"\n",
+ MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr))));
+ return 0;
+ }
+
+ wl_clr_drv_status(cfg, CONNECTED, ndev);
+
+ if (! wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
+ /* To make sure disconnect, explictly send dissassoc
+ * for BSSID 00:00:00:00:00:00 issue
+ */
+ scbval.val = WLAN_REASON_DEAUTH_LEAVING;
+
+ memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
+ scbval.val = htod32(scbval.val);
+ err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
+ sizeof(scb_val_t), true);
+ if (err < 0) {
+ WL_ERR(("WLC_DISASSOC error %d\n", err));
+ err = 0;
+ }
+ CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
+ false, GFP_KERNEL);
+ wl_link_down(cfg);
+ wl_init_prof(cfg, ndev);
+ }
+ }
+ else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
+ printk("link down, during connecting\n");
+#ifdef ESCAN_RESULT_PATCH
+ if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
+ (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
+ (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
+ /* In case this event comes while associating another AP */
+#endif /* ESCAN_RESULT_PATCH */
+ wl_bss_connect_done(cfg, ndev, e, data, false);
+ }
+ wl_clr_drv_status(cfg, DISCONNECTING, ndev);
+
+ /* if link down, bsscfg is diabled */
+ if (ndev != bcmcfg_to_prmry_ndev(cfg))
+ complete(&cfg->iface_disable);
+
+ } else if (wl_is_nonetwork(cfg, e)) {
+ printk("connect failed event=%d e->status %d e->reason %d \n",
+ event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
+ /* Clean up any pending scan request */
+ if (cfg->scan_request)
+ wl_notify_escan_complete(cfg, ndev, true, true);
+ if (wl_get_drv_status(cfg, CONNECTING, ndev))
+ wl_bss_connect_done(cfg, ndev, e, data, false);
+ } else {
+ WL_DBG(("%s nothing\n", __FUNCTION__));
+ }
+ }
+ else {
+ WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
+ }
+ return err;
+}
+
+#ifdef WL_RELMCAST
+void wl_cfg80211_set_rmc_pid(int pid)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ if (pid > 0)
+ cfg->rmc_event_pid = pid;
+ WL_DBG(("set pid for rmc event : pid=%d\n", pid));
+}
+#endif /* WL_RELMCAST */
+
+
+#ifdef WL_RELMCAST
+static s32
+wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ u32 evt = ntoh32(e->event_type);
+ u32 reason = ntoh32(e->reason);
+ int ret = -1;
+
+ switch (reason) {
+ case WLC_E_REASON_RMC_AR_LOST:
+ case WLC_E_REASON_RMC_AR_NO_ACK:
+ if (cfg->rmc_event_pid != 0) {
+ ret = wl_netlink_send_msg(cfg->rmc_event_pid,
+ RMC_EVENT_LEADER_CHECK_FAIL,
+ cfg->rmc_event_seq++, NULL, 0);
+ }
+ break;
+ default:
+ break;
+ }
+ WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
+ return ret;
+}
+#endif /* WL_RELMCAST */
+
+static s32
+wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ bool act;
+ struct net_device *ndev = NULL;
+ s32 err = 0;
+ u32 event = be32_to_cpu(e->event_type);
+ u32 status = be32_to_cpu(e->status);
+ WL_DBG(("Enter \n"));
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
+ wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
+ cfg->disable_roam_event = TRUE;
+ }
+
+ if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
+ return err;
+
+ if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
+ if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
+ if (cfg->roam_offload &&
+ memcmp(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN) == 0) {
+ WL_INFO(("BSSID already updated\n"));
+ return err;
+ }
+ wl_bss_roaming_done(cfg, ndev, e, data);
+ memcpy(&cfg->last_roamed_addr, (void *)&e->addr, ETHER_ADDR_LEN);
+ } else {
+ wl_bss_connect_done(cfg, ndev, e, data, true);
+ }
+ act = true;
+ wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
+ wl_update_prof(cfg, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
+ }
+ return err;
+}
+
+static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
+{
+ wl_assoc_info_t assoc_info;
+ struct wl_connect_info *conn_info = wl_to_conn(cfg);
+ s32 err = 0;
+
+ WL_DBG(("Enter \n"));
+ err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
+ WL_ASSOC_INFO_MAX, NULL);
+ if (unlikely(err)) {
+ WL_ERR(("could not get assoc info (%d)\n", err));
+ return err;
+ }
+ memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
+ assoc_info.req_len = htod32(assoc_info.req_len);
+ assoc_info.resp_len = htod32(assoc_info.resp_len);
+ assoc_info.flags = htod32(assoc_info.flags);
+ if (conn_info->req_ie_len) {
+ conn_info->req_ie_len = 0;
+ bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
+ }
+ if (conn_info->resp_ie_len) {
+ conn_info->resp_ie_len = 0;
+ bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
+ }
+ if (assoc_info.req_len) {
+ err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
+ WL_ASSOC_INFO_MAX, NULL);
+ if (unlikely(err)) {
+ WL_ERR(("could not get assoc req (%d)\n", err));
+ return err;
+ }
+ conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
+ if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
+ conn_info->req_ie_len -= ETHER_ADDR_LEN;
+ }
+ if (conn_info->req_ie_len <= MAX_REQ_LINE)
+ memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
+ else {
+ WL_ERR(("IE size %d above max %d size \n",
+ conn_info->req_ie_len, MAX_REQ_LINE));
+ return err;
+ }
+ } else {
+ conn_info->req_ie_len = 0;
+ }
+ if (assoc_info.resp_len) {
+ err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
+ WL_ASSOC_INFO_MAX, NULL);
+ if (unlikely(err)) {
+ WL_ERR(("could not get assoc resp (%d)\n", err));
+ return err;
+ }
+ conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
+ if (conn_info->resp_ie_len <= MAX_REQ_LINE)
+ memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
+ else {
+ WL_ERR(("IE size %d above max %d size \n",
+ conn_info->resp_ie_len, MAX_REQ_LINE));
+ return err;
+ }
+ } else {
+ conn_info->resp_ie_len = 0;
+ }
+ WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
+ conn_info->resp_ie_len));
+
+ return err;
+}
+
+static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
+ size_t *join_params_size)
+{
+ chanspec_t chanspec = 0;
+ if (ch != 0) {
+ join_params->params.chanspec_num = 1;
+ join_params->params.chanspec_list[0] = ch;
+
+ if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ else
+ chanspec |= WL_CHANSPEC_BAND_5G;
+
+ chanspec |= WL_CHANSPEC_BW_20;
+ chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+
+ *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
+ join_params->params.chanspec_num * sizeof(chanspec_t);
+
+ join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
+ join_params->params.chanspec_list[0] |= chanspec;
+ join_params->params.chanspec_list[0] =
+ wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
+
+ join_params->params.chanspec_num =
+ htod32(join_params->params.chanspec_num);
+ WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
+ join_params->params.chanspec_list[0],
+ join_params->params.chanspec_num));
+ }
+}
+
+static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam)
+{
+ struct cfg80211_bss *bss;
+ struct wl_bss_info *bi;
+ struct wlc_ssid *ssid;
+ struct bcm_tlv *tim;
+ s32 beacon_interval;
+ s32 dtim_period;
+ size_t ie_len;
+ u8 *ie;
+ u8 *curbssid;
+ s32 err = 0;
+ struct wiphy *wiphy;
+ u32 channel;
+
+ wiphy = bcmcfg_to_wiphy(cfg);
+
+ ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
+ curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
+ bss = cfg80211_get_bss(wiphy, NULL, curbssid,
+ ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+
+ mutex_lock(&cfg->usr_sync);
+
+ *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+ err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
+ cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
+ if (unlikely(err)) {
+ WL_ERR(("Could not get bss info %d\n", err));
+ goto update_bss_info_out;
+ }
+ bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
+ channel = bi->ctl_ch ? bi->ctl_ch :
+ CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
+ wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
+
+ if (!bss) {
+ WL_DBG(("Could not find the AP\n"));
+ if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
+ WL_ERR(("Bssid doesn't match\n"));
+ err = -EIO;
+ goto update_bss_info_out;
+ }
+ err = wl_inform_single_bss(cfg, bi, roam);
+ if (unlikely(err))
+ goto update_bss_info_out;
+
+ ie = ((u8 *)bi) + bi->ie_offset;
+ ie_len = bi->ie_length;
+ beacon_interval = cpu_to_le16(bi->beacon_period);
+ } else {
+ WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ ie = (u8 *)bss->ies->data;
+ ie_len = bss->ies->len;
+#else
+ ie = bss->information_elements;
+ ie_len = bss->len_information_elements;
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ beacon_interval = bss->beacon_interval;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+ cfg80211_put_bss(wiphy, bss);
+#else
+ cfg80211_put_bss(bss);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
+ }
+
+ tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+ if (tim) {
+ dtim_period = tim->data[1];
+ } else {
+ /*
+ * active scan was done so we could not get dtim
+ * information out of probe response.
+ * so we speficially query dtim information.
+ */
+ err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
+ &dtim_period, sizeof(dtim_period), false);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
+ goto update_bss_info_out;
+ }
+ }
+
+ wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
+ wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
+
+update_bss_info_out:
+ if (unlikely(err)) {
+ WL_ERR(("Failed with error %d\n", err));
+ }
+ mutex_unlock(&cfg->usr_sync);
+ return err;
+}
+
+static s32
+wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct wl_connect_info *conn_info = wl_to_conn(cfg);
+ s32 err = 0;
+ u8 *curbssid;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ struct ieee80211_supported_band *band;
+ struct ieee80211_channel *notify_channel = NULL;
+ u32 *channel;
+ u32 freq;
+#endif
+
+
+ wl_get_assoc_ies(cfg, ndev);
+ wl_update_prof(cfg, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
+ curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
+ wl_update_bss_info(cfg, ndev, true);
+ wl_update_pmklist(ndev, cfg->pmk_list, err);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
+ /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
+ channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
+ if (*channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[NL80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[NL80211_BAND_5GHZ];
+ freq = ieee80211_channel_to_frequency(*channel, band->band);
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+#endif
+ printk("wl_bss_roaming_done succeeded to " MACDBG "\n",
+ MAC2STRDBG((u8*)(&e->addr)));
+
+ cfg80211_roamed(ndev,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
+ notify_channel,
+#endif
+ curbssid,
+ conn_info->req_ie, conn_info->req_ie_len,
+ conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
+ WL_DBG(("Report roaming result\n"));
+
+ wl_set_drv_status(cfg, CONNECTED, ndev);
+
+ return err;
+}
+
+static s32
+wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, bool completed)
+{
+ struct wl_connect_info *conn_info = wl_to_conn(cfg);
+ struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
+#if (defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)) || \
+ defined(CUSTOM_SET_CPUCORE)
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+#endif /* (ROAM_ENABLE && ROAM_AP_ENV_DETECTION) || CUSTOM_SET_CPUCORE */
+ s32 err = 0;
+ u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
+ if (!sec) {
+ WL_ERR(("sec is NULL\n"));
+ return -ENODEV;
+ }
+ WL_DBG((" enter\n"));
+#ifdef ESCAN_RESULT_PATCH
+ if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
+ if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
+ WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
+ ntoh32(e->event_type), ntoh32(e->status)));
+ return err;
+ }
+ }
+ if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
+ memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
+ WL_DBG(("copy bssid\n"));
+ memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
+ }
+
+#else
+ if (cfg->scan_request) {
+ wl_notify_escan_complete(cfg, ndev, true, true);
+ }
+#endif /* ESCAN_RESULT_PATCH */
+ if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
+ wl_cfg80211_scan_abort(cfg);
+ wl_clr_drv_status(cfg, CONNECTING, ndev);
+ if (completed) {
+ wl_get_assoc_ies(cfg, ndev);
+ wl_update_prof(cfg, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
+ curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
+ wl_update_bss_info(cfg, ndev, false);
+ wl_update_pmklist(ndev, cfg->pmk_list, err);
+ wl_set_drv_status(cfg, CONNECTED, ndev);
+#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
+ if (dhd->roam_env_detection)
+ wldev_iovar_setint(ndev, "roam_env_detection",
+ AP_ENV_INDETERMINATE);
+#endif /* ROAM_AP_ENV_DETECTION */
+ if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
+ init_completion(&cfg->iface_disable);
+#else
+ /* reinitialize completion to clear previous count */
+ INIT_COMPLETION(cfg->iface_disable);
+#endif
+ }
+#ifdef CUSTOM_SET_CPUCORE
+ if (wl_get_chan_isvht80(ndev, dhd)) {
+ if (ndev == bcmcfg_to_prmry_ndev(cfg))
+ dhd->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
+ else if (is_p2p_group_iface(dev->ieee80211_ptr))
+ dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
+ dhd_set_cpucore(dhd, TRUE);
+ }
+#endif /* CUSTOM_SET_CPUCORE */
+ memset(&cfg->last_roamed_addr, 0, ETHER_ADDR_LEN);
+ }
+ cfg80211_connect_result(ndev,
+ curbssid,
+ conn_info->req_ie,
+ conn_info->req_ie_len,
+ conn_info->resp_ie,
+ conn_info->resp_ie_len,
+ completed ? WLAN_STATUS_SUCCESS :
+ (sec->auth_assoc_res_status) ?
+ sec->auth_assoc_res_status :
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
+ if (completed)
+ WL_INFO(("Report connect result - connection succeeded\n"));
+ else
+ WL_ERR(("Report connect result - connection failed\n"));
+ }
+#ifdef CONFIG_TCPACK_FASTTX
+ if (wl_get_chan_isvht80(ndev, dhd))
+ wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
+ else
+ wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
+#endif /* CONFIG_TCPACK_FASTTX */
+
+ return err;
+}
+
+static s32
+wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct net_device *ndev = NULL;
+ u16 flags = ntoh16(e->flags);
+ enum nl80211_key_type key_type;
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ mutex_lock(&cfg->usr_sync);
+ if (flags & WLC_EVENT_MSG_GROUP)
+ key_type = NL80211_KEYTYPE_GROUP;
+ else
+ key_type = NL80211_KEYTYPE_PAIRWISE;
+
+ cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
+ NULL, GFP_KERNEL);
+ mutex_unlock(&cfg->usr_sync);
+
+ return 0;
+}
+
+#ifdef PNO_SUPPORT
+static s32
+wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct net_device *ndev = NULL;
+
+ WL_ERR((">>> PNO Event\n"));
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+#ifndef WL_SCHED_SCAN
+ mutex_lock(&cfg->usr_sync);
+ /* TODO: Use cfg80211_sched_scan_results(wiphy); */
+ CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
+ mutex_unlock(&cfg->usr_sync);
+#else
+ /* If cfg80211 scheduled scan is supported, report the pno results via sched
+ * scan results
+ */
+ wl_notify_sched_scan_results(cfg, ndev, e, data);
+#endif /* WL_SCHED_SCAN */
+ return 0;
+}
+#endif /* PNO_SUPPORT */
+
+static s32
+wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct channel_info channel_inform;
+ struct wl_scan_results *bss_list;
+ struct net_device *ndev = NULL;
+ u32 len = WL_SCAN_BUF_MAX;
+ s32 err = 0;
+ unsigned long flags;
+
+ WL_DBG(("Enter \n"));
+ if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
+ WL_ERR(("scan is not ready \n"));
+ return err;
+ }
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ mutex_lock(&cfg->usr_sync);
+ wl_clr_drv_status(cfg, SCANNING, ndev);
+ err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
+ sizeof(channel_inform), false);
+ if (unlikely(err)) {
+ WL_ERR(("scan busy (%d)\n", err));
+ goto scan_done_out;
+ }
+ channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
+ if (unlikely(channel_inform.scan_channel)) {
+
+ WL_DBG(("channel_inform.scan_channel (%d)\n",
+ channel_inform.scan_channel));
+ }
+ cfg->bss_list = cfg->scan_results;
+ bss_list = cfg->bss_list;
+ memset(bss_list, 0, len);
+ bss_list->buflen = htod32(len);
+ err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
+ if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
+ WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
+ err = -EINVAL;
+ goto scan_done_out;
+ }
+ bss_list->buflen = dtoh32(bss_list->buflen);
+ bss_list->version = dtoh32(bss_list->version);
+ bss_list->count = dtoh32(bss_list->count);
+
+ err = wl_inform_bss(cfg);
+
+scan_done_out:
+ del_timer_sync(&cfg->scan_timeout);
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+ if (cfg->scan_request) {
+ struct cfg80211_scan_info info = {
+ .aborted = false,
+ };
+
+ cfg80211_scan_done(cfg->scan_request, &info);
+ cfg->scan_request = NULL;
+ }
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+ WL_DBG(("cfg80211_scan_done\n"));
+ mutex_unlock(&cfg->usr_sync);
+ return err;
+}
+
+static s32
+wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
+ const struct ether_addr *sa, const struct ether_addr *bssid,
+ u8 **pheader, u32 *body_len, u8 *pbody)
+{
+ struct dot11_management_header *hdr;
+ u32 totlen = 0;
+ s32 err = 0;
+ u8 *offset;
+ u32 prebody_len = *body_len;
+ switch (fc) {
+ case FC_ASSOC_REQ:
+ /* capability , listen interval */
+ totlen = DOT11_ASSOC_REQ_FIXED_LEN;
+ *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
+ break;
+
+ case FC_REASSOC_REQ:
+ /* capability, listen inteval, ap address */
+ totlen = DOT11_REASSOC_REQ_FIXED_LEN;
+ *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
+ break;
+ }
+ totlen += DOT11_MGMT_HDR_LEN + prebody_len;
+ *pheader = kzalloc(totlen, GFP_KERNEL);
+ if (*pheader == NULL) {
+ WL_ERR(("memory alloc failed \n"));
+ return -ENOMEM;
+ }
+ hdr = (struct dot11_management_header *) (*pheader);
+ hdr->fc = htol16(fc);
+ hdr->durid = 0;
+ hdr->seq = 0;
+ offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
+ bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
+ bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
+ bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
+ if ((pbody != NULL) && prebody_len)
+ bcopy((const char*)pbody, offset, prebody_len);
+ *body_len = totlen;
+ return err;
+}
+
+
+void
+wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev)
+{
+ if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
+ if (timer_pending(&cfg->p2p->listen_timer)) {
+ del_timer_sync(&cfg->p2p->listen_timer);
+ }
+ if (cfg->afx_hdl != NULL) {
+ if (cfg->afx_hdl->dev != NULL) {
+ wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
+ wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
+ }
+ cfg->afx_hdl->peer_chan = WL_INVALID;
+ }
+ complete(&cfg->act_frm_scan);
+ WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
+ } else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
+ if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
+ wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
+ wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
+
+ WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
+ /* if channel is not zero, "actfame" uses off channel scan.
+ * So abort scan for off channel completion.
+ */
+ if (cfg->af_sent_channel)
+ wl_cfg80211_scan_abort(cfg);
+ }
+#ifdef WL_CFG80211_SYNC_GON
+ else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
+ WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
+ /* So abort scan to cancel listen */
+ wl_cfg80211_scan_abort(cfg);
+ }
+#endif /* WL_CFG80211_SYNC_GON */
+}
+
+
+int wl_cfg80211_get_ioctl_version(void)
+{
+ return ioctl_version;
+}
+
+static s32
+wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct ieee80211_supported_band *band;
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ struct ether_addr da;
+ struct ether_addr bssid;
+ bool isfree = false;
+ s32 err = 0;
+ s32 freq;
+ struct net_device *ndev = NULL;
+ wifi_p2p_pub_act_frame_t *act_frm = NULL;
+ wifi_p2p_action_frame_t *p2p_act_frm = NULL;
+ wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
+ wl_event_rx_frame_data_t *rxframe =
+ (wl_event_rx_frame_data_t*)data;
+ u32 event = ntoh32(e->event_type);
+ u8 *mgmt_frame;
+ u8 bsscfgidx = e->bsscfgidx;
+ u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
+ u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
+ bool retval;
+ dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
+
+ memset(&bssid, 0, ETHER_ADDR_LEN);
+
+ if (cfg->bss_cfgdev &&
+ (dhdp->op_mode & DHD_FLAG_HOSTAP_MODE) &&
+ event == WLC_E_PROBREQ_MSG) {
+ /* Handle probe reqs frame
+ * WPS-AP certification 4.2.13
+ */
+ ndev = cfgdev_to_wlc_ndev(cfg->bss_cfgdev, cfg);
+ cfgdev = cfg->bss_cfgdev;
+ } else {
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+ }
+#ifdef P2PONEINT
+ WL_DBG((" device name is ndev %s \n", ndev->name));
+#endif
+
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[NL80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[NL80211_BAND_5GHZ];
+ if (!band) {
+ WL_ERR(("No valid band"));
+ return -EINVAL;
+ }
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+ freq = ieee80211_channel_to_frequency(channel);
+ (void)band->band;
+#else
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+ if (event == WLC_E_ACTION_FRAME_RX) {
+ wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+ NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
+
+ err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
+ if (err < 0)
+ WL_ERR(("WLC_GET_BSSID error %d\n", err));
+ memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
+ err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
+ &mgmt_frame, &mgmt_frame_len,
+ (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
+ if (err < 0) {
+ WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
+ mgmt_frame_len, channel, freq));
+ goto exit;
+ }
+ isfree = true;
+ if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
+ mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
+ act_frm = (wifi_p2p_pub_act_frame_t *)
+ (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
+ } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
+ mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
+ p2p_act_frm = (wifi_p2p_action_frame_t *)
+ (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
+ (void) p2p_act_frm;
+ } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
+ mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
+
+ sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
+ (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
+ if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
+ if (cfg->next_af_subtype == sd_act_frm->action) {
+ WL_DBG(("We got a right next frame of SD!(%d)\n",
+ sd_act_frm->action));
+ wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
+
+ /* Stop waiting for next AF. */
+ wl_stop_wait_next_action_frame(cfg, ndev);
+ }
+ }
+ (void) sd_act_frm;
+#ifdef WLTDLS
+ } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
+ WL_DBG((" TDLS Action Frame Received type = %d \n",
+ mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
+
+ if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
+ cfg->tdls_mgmt_frame = mgmt_frame;
+ cfg->tdls_mgmt_frame_len = mgmt_frame_len;
+ cfg->tdls_mgmt_freq = freq;
+ return 0;
+ }
+
+ } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_VENDOR_SPECIFIC) {
+ WL_DBG((" TDLS Vendor Specific Received type \n"));
+#endif
+ } else {
+
+ if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
+ u8 action = 0;
+ if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
+ mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
+ WL_DBG(("Recived action is not public action frame\n"));
+ } else if (cfg->next_af_subtype == action) {
+ WL_DBG(("Recived action is the waiting action(%d)\n",
+ action));
+ wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
+
+ /* Stop waiting for next AF. */
+ wl_stop_wait_next_action_frame(cfg, ndev);
+ }
+ }
+ }
+
+ if (act_frm) {
+
+ if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
+ if (cfg->next_af_subtype == act_frm->subtype) {
+ WL_DBG(("We got a right next frame!(%d)\n",
+ act_frm->subtype));
+ wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
+
+ if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
+ OSL_SLEEP(20);
+ }
+
+ /* Stop waiting for next AF. */
+ wl_stop_wait_next_action_frame(cfg, ndev);
+ }
+ }
+ }
+
+ wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
+ mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
+ /*
+ * After complete GO Negotiation, roll back to mpc mode
+ */
+ if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
+ (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
+ wldev_iovar_setint(ndev, "mpc", 1);
+ }
+ if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
+ WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
+ wl_clr_p2p_status(cfg, GO_NEG_PHASE);
+ }
+ } else if (event == WLC_E_PROBREQ_MSG) {
+
+ /* Handle probe reqs frame
+ * WPS-AP certification 4.2.13
+ */
+ struct parsed_ies prbreq_ies;
+ u32 prbreq_ie_len = 0;
+ bool pbc = 0;
+
+ WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
+ mgmt_frame = (u8 *)(data);
+ mgmt_frame_len = ntoh32(e->datalen);
+
+ prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
+
+ /* Parse prob_req IEs */
+ if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
+ prbreq_ie_len, &prbreq_ies) < 0) {
+ WL_ERR(("Prob req get IEs failed\n"));
+ return 0;
+ }
+ if (prbreq_ies.wps_ie != NULL) {
+ wl_validate_wps_ie((char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
+ WL_DBG((" wps_ie exist pbc = %d\n", pbc));
+ /* if pbc method, send prob_req mgmt frame to upper layer */
+ if (!pbc)
+ return 0;
+ } else
+ return 0;
+ } else {
+ mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
+
+ /* wpa supplicant use probe request event for restarting another GON Req.
+ * but it makes GON Req repetition.
+ * so if src addr of prb req is same as my target device,
+ * do not send probe request event during sending action frame.
+ */
+ if (event == WLC_E_P2P_PROBREQ_MSG) {
+ WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
+ "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
+
+
+ /* Filter any P2P probe reqs arriving during the
+ * GO-NEG Phase
+ */
+ if (cfg->p2p &&
+ wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
+ WL_DBG(("Filtering P2P probe_req while "
+ "being in GO-Neg state\n"));
+ return 0;
+ }
+ }
+ }
+
+#ifdef P2PONEINT
+ if (ndev == cfg->p2p_net && ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
+ ndev = bcmcfg_to_prmry_ndev(cfg);
+ cfgdev = ndev_to_cfgdev(ndev);
+ }
+ WL_DBG((" device name is ndev %s \n", ndev->name));
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ retval = cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+ retval = cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
+ defined(WL_COMPAT_WIRELESS)
+ retval = cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
+#else
+ retval = cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
+#endif /* LINUX_VERSION >= VERSION(3, 18, 0) */
+
+ WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d) retval (%d)\n",
+ mgmt_frame_len, ntoh32(e->datalen), channel, freq, retval));
+exit:
+ if (isfree)
+ kfree(mgmt_frame);
+ return 0;
+}
+
+#ifdef WL_SCHED_SCAN
+/* If target scan is not reliable, set the below define to "1" to do a
+ * full escan
+ */
+#define FULL_ESCAN_ON_PFN_NET_FOUND 0
+static s32
+wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ wl_pfn_net_info_t *netinfo, *pnetinfo;
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ int err = 0;
+ struct cfg80211_scan_request *request = NULL;
+ struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
+ struct ieee80211_channel *channel = NULL;
+ int channel_req = 0;
+ int band = 0;
+ struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
+ int n_pfn_results = pfn_result->count;
+
+ WL_DBG(("Enter\n"));
+
+ if ((e->event_type == WLC_E_PFN_NET_LOST) || !data) {
+ WL_PNO(("Do Nothing %d\n", e->event_type));
+ return 0;
+ }
+ if (pfn_result->version != PFN_SCANRESULT_VERSION) {
+ WL_ERR(("Incorrect version %d, expected %d\n", pfn_result->version,
+ PFN_SCANRESULT_VERSION));
+ return 0;
+ }
+ WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
+ if (n_pfn_results > 0) {
+ int i;
+
+ if (n_pfn_results > MAX_PFN_LIST_COUNT)
+ n_pfn_results = MAX_PFN_LIST_COUNT;
+ pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
+ - sizeof(wl_pfn_net_info_t));
+
+ memset(&ssid, 0x00, sizeof(ssid));
+
+ request = kzalloc(sizeof(*request)
+ + sizeof(*request->channels) * n_pfn_results,
+ GFP_KERNEL);
+ channel = (struct ieee80211_channel *)kzalloc(
+ (sizeof(struct ieee80211_channel) * n_pfn_results),
+ GFP_KERNEL);
+ if (!request || !channel) {
+ WL_ERR(("No memory"));
+ err = -ENOMEM;
+ goto out_err;
+ }
+
+ request->wiphy = wiphy;
+
+ for (i = 0; i < n_pfn_results; i++) {
+ netinfo = &pnetinfo[i];
+ if (!netinfo) {
+ WL_ERR(("Invalid netinfo ptr. index:%d", i));
+ err = -EINVAL;
+ goto out_err;
+ }
+ WL_PNO((">>> SSID:%s Channel:%d \n",
+ netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
+ /* PFN result doesn't have all the info which are required by the supplicant
+ * (For e.g IEs) Do a target Escan so that sched scan results are reported
+ * via wl_inform_single_bss in the required format. Escan does require the
+ * scan request in the form of cfg80211_scan_request. For timebeing, create
+ * cfg80211_scan_request one out of the received PNO event.
+ */
+ ssid[i].ssid_len = MIN(netinfo->pfnsubnet.SSID_len, DOT11_MAX_SSID_LEN);
+ memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID, ssid[i].ssid_len);
+ request->n_ssids++;
+
+ channel_req = netinfo->pfnsubnet.channel;
+ band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
+ : NL80211_BAND_5GHZ;
+ channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
+ channel[i].band = band;
+ channel[i].flags |= IEEE80211_CHAN_NO_HT40;
+ request->channels[i] = &channel[i];
+ request->n_channels++;
+ }
+
+ /* assign parsed ssid array */
+ if (request->n_ssids)
+ request->ssids = &ssid[0];
+
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ /* Abort any on-going scan */
+ wl_notify_escan_complete(cfg, ndev, true, true);
+ }
+
+ if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
+ WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
+ err = wl_cfgp2p_discover_enable_search(cfg, false);
+ if (unlikely(err)) {
+ wl_clr_drv_status(cfg, SCANNING, ndev);
+ goto out_err;
+ }
+ p2p_scan(cfg) = false;
+ }
+
+ wl_set_drv_status(cfg, SCANNING, ndev);
+#if FULL_ESCAN_ON_PFN_NET_FOUND
+ WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
+ err = wl_do_escan(cfg, wiphy, ndev, NULL);
+#else
+ WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
+ err = wl_do_escan(cfg, wiphy, ndev, request);
+#endif
+ if (err) {
+ wl_clr_drv_status(cfg, SCANNING, ndev);
+ goto out_err;
+ }
+ cfg->sched_scan_running = TRUE;
+ }
+ else {
+ WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
+ }
+out_err:
+ if (request)
+ kfree(request);
+ if (channel)
+ kfree(channel);
+ return err;
+}
+#endif /* WL_SCHED_SCAN */
+
+static void wl_init_conf(struct wl_conf *conf)
+{
+ WL_DBG(("Enter \n"));
+ conf->frag_threshold = (u32)-1;
+ conf->rts_threshold = (u32)-1;
+ conf->retry_short = (u32)-1;
+ conf->retry_long = (u32)-1;
+ conf->tx_power = -1;
+}
+
+static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
+{
+ unsigned long flags;
+ struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
+
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+ memset(profile, 0, sizeof(struct wl_profile));
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+}
+
+static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
+{
+ memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));
+
+ cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
+ cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
+ cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
+ cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
+ cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
+ cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
+ cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
+ cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
+ cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
+ cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
+#ifdef PNO_SUPPORT
+ cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
+#endif /* PNO_SUPPORT */
+#ifdef WLTDLS
+ cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
+#endif /* WLTDLS */
+ cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
+#ifdef WL_RELMCAST
+ cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
+#endif /* WL_RELMCAST */
+#ifdef WL_NAN
+ cfg->evt_handler[WLC_E_NAN] = wl_cfgnan_notify_nan_status;
+ cfg->evt_handler[WLC_E_PROXD] = wl_cfgnan_notify_proxd_status;
+#endif /* WL_NAN */
+
+ cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
+}
+
+#if defined(STATIC_WL_PRIV_STRUCT)
+static int
+wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
+{
+ cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
+ DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
+ if (cfg->escan_info.escan_buf == NULL) {
+ WL_ERR(("Failed to alloc ESCAN_BUF\n"));
+ return -ENOMEM;
+ }
+ bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
+
+ return 0;
+}
+
+static void
+wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
+{
+ if (cfg->escan_info.escan_buf != NULL) {
+ DHD_OS_PREFREE(cfg->pub, DHD_PREALLOC_WIPHY_ESCAN0,
+ cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
+ cfg->escan_info.escan_buf = NULL;
+ }
+}
+#endif /* STATIC_WL_PRIV_STRUCT */
+
+static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
+{
+ WL_DBG(("Enter \n"));
+ cfg->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
+ if (unlikely(!cfg->scan_results)) {
+ WL_ERR(("Scan results alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ cfg->conf = (void *)kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
+ if (unlikely(!cfg->conf)) {
+ WL_ERR(("wl_conf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ cfg->scan_req_int =
+ (void *)kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL);
+ if (unlikely(!cfg->scan_req_int)) {
+ WL_ERR(("Scan req alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ cfg->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
+ if (unlikely(!cfg->ioctl_buf)) {
+ WL_ERR(("Ioctl buf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ cfg->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
+ if (unlikely(!cfg->escan_ioctl_buf)) {
+ WL_ERR(("Ioctl buf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ cfg->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+ if (unlikely(!cfg->extra_buf)) {
+ WL_ERR(("Extra buf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ cfg->pmk_list = (void *)kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
+ if (unlikely(!cfg->pmk_list)) {
+ WL_ERR(("pmk list alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+
+#if defined(STATIC_WL_PRIV_STRUCT)
+ cfg->conn_info = (void *)kzalloc(sizeof(*cfg->conn_info), GFP_KERNEL);
+ if (unlikely(!cfg->conn_info)) {
+ WL_ERR(("cfg->conn_info alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ cfg->ie = (void *)kzalloc(sizeof(*cfg->ie), GFP_KERNEL);
+ if (unlikely(!cfg->ie)) {
+ WL_ERR(("cfg->ie alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ if (unlikely(wl_init_escan_result_buf(cfg))) {
+ WL_ERR(("Failed to init escan result buf\n"));
+ goto init_priv_mem_out;
+ }
+#endif /* STATIC_WL_PRIV_STRUCT */
+ cfg->afx_hdl = (void *)kzalloc(sizeof(*cfg->afx_hdl), GFP_KERNEL);
+ if (unlikely(!cfg->afx_hdl)) {
+ WL_ERR(("afx hdl alloc failed\n"));
+ goto init_priv_mem_out;
+ } else {
+ init_completion(&cfg->act_frm_scan);
+ init_completion(&cfg->wait_next_af);
+
+ INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
+ }
+ return 0;
+
+init_priv_mem_out:
+ wl_deinit_priv_mem(cfg);
+
+ return -ENOMEM;
+}
+
+static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
+{
+ kfree(cfg->scan_results);
+ cfg->scan_results = NULL;
+ kfree(cfg->conf);
+ cfg->conf = NULL;
+ kfree(cfg->scan_req_int);
+ cfg->scan_req_int = NULL;
+ kfree(cfg->ioctl_buf);
+ cfg->ioctl_buf = NULL;
+ kfree(cfg->escan_ioctl_buf);
+ cfg->escan_ioctl_buf = NULL;
+ kfree(cfg->extra_buf);
+ cfg->extra_buf = NULL;
+ kfree(cfg->pmk_list);
+ cfg->pmk_list = NULL;
+#if defined(STATIC_WL_PRIV_STRUCT)
+ kfree(cfg->conn_info);
+ cfg->conn_info = NULL;
+ kfree(cfg->ie);
+ cfg->ie = NULL;
+ wl_deinit_escan_result_buf(cfg);
+#endif /* STATIC_WL_PRIV_STRUCT */
+ if (cfg->afx_hdl) {
+ cancel_work_sync(&cfg->afx_hdl->work);
+ kfree(cfg->afx_hdl);
+ cfg->afx_hdl = NULL;
+ }
+
+#ifdef WLTDLS
+ if (cfg->tdls_mgmt_frame) {
+ kfree(cfg->tdls_mgmt_frame);
+ cfg->tdls_mgmt_frame = NULL;
+ }
+#endif /* WLTDLS */
+}
+
+static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
+{
+ int ret = 0;
+ WL_DBG(("Enter \n"));
+
+ /* Do not use DHD in cfg driver */
+ cfg->event_tsk.thr_pid = -1;
+
+ PROC_START(wl_event_handler, cfg, &cfg->event_tsk, 0, "wl_event_handler");
+ if (cfg->event_tsk.thr_pid < 0)
+ ret = -ENOMEM;
+ return ret;
+}
+
+static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
+{
+ if (cfg->event_tsk.thr_pid >= 0)
+ PROC_STOP(&cfg->event_tsk);
+}
+
+void wl_terminate_event_handler(void)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ if (cfg) {
+ wl_destroy_event_handler(cfg);
+ }
+}
+
+static void wl_scan_timeout(unsigned long data)
+{
+ wl_event_msg_t msg;
+ struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
+
+ if (!(cfg->scan_request)) {
+ WL_ERR(("timer expired but no scan request\n"));
+ return;
+ }
+ bzero(&msg, sizeof(wl_event_msg_t));
+ WL_ERR(("timer expired\n"));
+ msg.event_type = hton32(WLC_E_ESCAN_RESULT);
+ msg.status = hton32(WLC_E_STATUS_TIMEOUT);
+ msg.reason = 0xFFFFFFFF;
+ wl_cfg80211_event(bcmcfg_to_prmry_ndev(cfg), &msg, NULL);
+}
+
+static s32
+wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
+ unsigned long state,
+ void *ptr)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
+ struct net_device *dev = ptr;
+#else
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+#endif /* LINUX_VERSION < VERSION(3, 11, 0) */
+ struct wireless_dev *wdev = ndev_to_wdev(dev);
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ WL_DBG(("Enter \n"));
+
+ if (!wdev || !cfg || dev == bcmcfg_to_prmry_ndev(cfg))
+ return NOTIFY_DONE;
+
+ switch (state) {
+ case NETDEV_DOWN:
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
+ int max_wait_timeout = 2;
+ int max_wait_count = 100;
+ int refcnt = 0;
+ unsigned long limit = jiffies + max_wait_timeout * HZ;
+ while (work_pending(&wdev->cleanup_work)) {
+ if (refcnt%5 == 0) {
+ WL_ERR(("[NETDEV_DOWN] wait for "
+ "complete of cleanup_work"
+ " (%d th)\n", refcnt));
+ }
+ if (!time_before(jiffies, limit)) {
+ WL_ERR(("[NETDEV_DOWN] cleanup_work"
+ " of CFG80211 is not"
+ " completed in %d sec\n",
+ max_wait_timeout));
+ break;
+ }
+ if (refcnt >= max_wait_count) {
+ WL_ERR(("[NETDEV_DOWN] cleanup_work"
+ " of CFG80211 is not"
+ " completed in %d loop\n",
+ max_wait_count));
+ break;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(100);
+ set_current_state(TASK_RUNNING);
+ refcnt++;
+ }
+#endif /* LINUX_VERSION < VERSION(3, 11, 0) */
+ break;
+ }
+
+ case NETDEV_UNREGISTER:
+ /* after calling list_del_rcu(&wdev->list) */
+ wl_cfg80211_clear_per_bss_ies(cfg,
+ wl_get_bssidx_by_wdev(cfg, wdev));
+ wl_dealloc_netinfo_by_wdev(cfg, wdev);
+ break;
+ case NETDEV_GOING_DOWN:
+ /* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
+ * In front of door, the function checks
+ * whether current scan is working or not.
+ * If the scanning is still working, wdev_cleanup_work call WARN_ON and
+ * make the scan done forcibly.
+ */
+ if (wl_get_drv_status(cfg, SCANNING, dev))
+ wl_notify_escan_complete(cfg, dev, true, true);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+static struct notifier_block wl_cfg80211_netdev_notifier = {
+ .notifier_call = wl_cfg80211_netdev_notifier_call,
+};
+/* to make sure we won't register the same notifier twice, otherwise a loop is likely to be
+ * created in kernel notifier link list (with 'next' pointing to itself)
+ */
+static bool wl_cfg80211_netdev_notifier_registered = FALSE;
+
+#ifdef P2PONEINT
+void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
+#else
+static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
+#endif
+{
+ wl_scan_params_t *params = NULL;
+ s32 params_size = 0;
+ s32 err = BCME_OK;
+ struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
+ if (!in_atomic()) {
+ /* Our scan params only need space for 1 channel and 0 ssids */
+ params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
+ if (params == NULL) {
+ WL_ERR(("scan params allocation failed \n"));
+ err = -ENOMEM;
+ } else {
+ /* Do a scan abort to stop the driver's scan engine */
+ err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
+ if (err < 0) {
+ WL_ERR(("scan abort failed \n"));
+ }
+ kfree(params);
+ }
+ }
+}
+
+static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
+ struct net_device *ndev,
+ bool aborted, bool fw_abort)
+{
+ s32 err = BCME_OK;
+ unsigned long flags;
+ struct net_device *dev;
+
+ WL_DBG(("Enter \n"));
+ if (!ndev) {
+ WL_ERR(("ndev is null\n"));
+ err = BCME_ERROR;
+ return err;
+ }
+
+ if (cfg->escan_info.ndev != ndev) {
+ WL_ERR(("ndev is different %p %p\n", cfg->escan_info.ndev, ndev));
+ err = BCME_ERROR;
+ return err;
+ }
+
+ if (cfg->scan_request) {
+ dev = bcmcfg_to_prmry_ndev(cfg);
+#if defined(WL_ENABLE_P2P_IF)
+ if (cfg->scan_request->dev != cfg->p2p_net)
+ dev = cfg->scan_request->dev;
+#endif /* WL_ENABLE_P2P_IF */
+ }
+ else {
+ WL_DBG(("cfg->scan_request is NULL may be internal scan."
+ "doing scan_abort for ndev %p primary %p",
+ ndev, bcmcfg_to_prmry_ndev(cfg)));
+ dev = ndev;
+ }
+ if (fw_abort && !in_atomic())
+ wl_cfg80211_scan_abort(cfg);
+ if (timer_pending(&cfg->scan_timeout))
+ del_timer_sync(&cfg->scan_timeout);
+#if defined(ESCAN_RESULT_PATCH)
+ if (likely(cfg->scan_request)) {
+ cfg->bss_list = wl_escan_get_buf(cfg, aborted);
+ wl_inform_bss(cfg);
+ }
+#endif /* ESCAN_RESULT_PATCH */
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+#ifdef WL_SCHED_SCAN
+ if (cfg->sched_scan_req && !cfg->scan_request) {
+ WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
+ if (!aborted)
+ cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
+ cfg->sched_scan_running = FALSE;
+ cfg->sched_scan_req = NULL;
+ }
+#endif /* WL_SCHED_SCAN */
+ if (likely(cfg->scan_request)) {
+ struct cfg80211_scan_info info = {
+ .aborted = aborted,
+ };
+
+ cfg80211_scan_done(cfg->scan_request, &info);
+ cfg->scan_request = NULL;
+ }
+ if (p2p_is_on(cfg))
+ wl_clr_p2p_status(cfg, SCANNING);
+ wl_clr_drv_status(cfg, SCANNING, dev);
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+
+ return err;
+}
+
+#ifdef ESCAN_BUF_OVERFLOW_MGMT
+static void
+wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
+{
+ int idx;
+ for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
+ int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
+ if (bss->RSSI < candidate[idx].RSSI) {
+ if (len)
+ memcpy(&candidate[idx + 1], &candidate[idx],
+ sizeof(removal_element_t) * len);
+ candidate[idx].RSSI = bss->RSSI;
+ candidate[idx].length = bss->length;
+ memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
+ return;
+ }
+ }
+}
+
+static void
+wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
+ wl_bss_info_t *bi)
+{
+ int idx1, idx2;
+ int total_delete_len = 0;
+ for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
+ int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
+ wl_bss_info_t *bss = NULL;
+ if (candidate[idx1].RSSI >= bi->RSSI)
+ continue;
+ for (idx2 = 0; idx2 < list->count; idx2++) {
+ bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
+ list->bss_info;
+ if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
+ candidate[idx1].RSSI == bss->RSSI &&
+ candidate[idx1].length == dtoh32(bss->length)) {
+ u32 delete_len = dtoh32(bss->length);
+ WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
+ MAC2STRDBG(bss->BSSID.octet)));
+ if (idx2 < list->count -1) {
+ memmove((u8 *)bss, (u8 *)bss + delete_len,
+ list->buflen - cur_len - delete_len);
+ }
+ list->buflen -= delete_len;
+ list->count--;
+ total_delete_len += delete_len;
+ /* if delete_len is greater than or equal to result length */
+ if (total_delete_len >= bi->length) {
+ return;
+ }
+ break;
+ }
+ cur_len += dtoh32(bss->length);
+ }
+ }
+}
+#endif /* ESCAN_BUF_OVERFLOW_MGMT */
+
+static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = BCME_OK;
+ s32 status = ntoh32(e->status);
+ wl_bss_info_t *bi;
+ wl_escan_result_t *escan_result;
+ wl_bss_info_t *bss = NULL;
+ wl_scan_results_t *list;
+ wifi_p2p_ie_t * p2p_ie;
+ struct net_device *ndev = NULL;
+ u32 bi_length;
+ u32 i;
+ u8 *p2p_dev_addr = NULL;
+
+ WL_DBG((" enter event type : %d, status : %d \n",
+ ntoh32(e->event_type), ntoh32(e->status)));
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ mutex_lock(&cfg->usr_sync);
+ /* P2P SCAN is coming from primary interface */
+ if (wl_get_p2p_status(cfg, SCANNING)) {
+ if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
+ ndev = cfg->afx_hdl->dev;
+ else
+ ndev = cfg->escan_info.ndev;
+
+ }
+ if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
+ WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
+ ndev, wl_get_drv_status(cfg, SCANNING, ndev),
+ ntoh32(e->event_type), ntoh32(e->status)));
+ goto exit;
+ }
+ escan_result = (wl_escan_result_t *)data;
+
+ if (status == WLC_E_STATUS_PARTIAL) {
+ WL_INFO(("WLC_E_STATUS_PARTIAL \n"));
+ if (!escan_result) {
+ WL_ERR(("Invalid escan result (NULL pointer)\n"));
+ goto exit;
+ }
+ if (dtoh16(escan_result->bss_count) != 1) {
+ WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
+ goto exit;
+ }
+ bi = escan_result->bss_info;
+ if (!bi) {
+ WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
+ goto exit;
+ }
+ bi_length = dtoh32(bi->length);
+ if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
+ WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
+ goto exit;
+ }
+ if (wl_escan_check_sync_id(status, escan_result->sync_id,
+ cfg->escan_info.cur_sync_id) < 0)
+ goto exit;
+
+ if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
+ if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
+ WL_DBG(("Ignoring IBSS result\n"));
+ goto exit;
+ }
+ }
+
+ if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
+ p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
+ if (p2p_dev_addr && !memcmp(p2p_dev_addr,
+ cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
+ s32 channel = wf_chspec_ctlchan(
+ wl_chspec_driver_to_host(bi->chanspec));
+
+ if ((channel > MAXCHANNEL) || (channel <= 0))
+ channel = WL_INVALID;
+ else
+ WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
+ " channel : %d\n",
+ MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
+ channel));
+
+ wl_clr_p2p_status(cfg, SCANNING);
+ cfg->afx_hdl->peer_chan = channel;
+ complete(&cfg->act_frm_scan);
+ goto exit;
+ }
+
+ } else {
+ int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
+#ifdef ESCAN_BUF_OVERFLOW_MGMT
+ removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
+ int remove_lower_rssi = FALSE;
+
+ bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
+#endif /* ESCAN_BUF_OVERFLOW_MGMT */
+
+ list = wl_escan_get_buf(cfg, FALSE);
+ if (scan_req_match(cfg)) {
+ /* p2p scan && allow only probe response */
+ if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
+ (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
+ goto exit;
+ if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
+ bi->ie_length)) == NULL) {
+ WL_ERR(("Couldn't find P2PIE in probe"
+ " response/beacon\n"));
+ goto exit;
+ }
+ }
+#ifdef ESCAN_BUF_OVERFLOW_MGMT
+ if (bi_length > ESCAN_BUF_SIZE - list->buflen)
+ remove_lower_rssi = TRUE;
+#endif /* ESCAN_BUF_OVERFLOW_MGMT */
+
+ for (i = 0; i < list->count; i++) {
+ bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
+ : list->bss_info;
+#ifdef ESCAN_BUF_OVERFLOW_MGMT
+ WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
+ bss->SSID, MAC2STRDBG(bss->BSSID.octet),
+ i, bss->RSSI, list->count));
+
+ if (remove_lower_rssi)
+ wl_cfg80211_find_removal_candidate(bss, candidate);
+#endif /* ESCAN_BUF_OVERFLOW_MGMT */
+
+ if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
+ (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
+ == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
+ bi->SSID_len == bss->SSID_len &&
+ !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
+
+ /* do not allow beacon data to update
+ *the data recd from a probe response
+ */
+ if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
+ (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
+ goto exit;
+
+ WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d"
+ " flags 0x%x, new: RSSI %d flags 0x%x\n",
+ bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
+ bss->RSSI, bss->flags, bi->RSSI, bi->flags));
+
+ if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
+ (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
+ /* preserve max RSSI if the measurements are
+ * both on-channel or both off-channel
+ */
+ WL_SCAN(("%s("MACDBG"), same onchan"
+ ", RSSI: prev %d new %d\n",
+ bss->SSID, MAC2STRDBG(bi->BSSID.octet),
+ bss->RSSI, bi->RSSI));
+ bi->RSSI = MAX(bss->RSSI, bi->RSSI);
+ } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
+ (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
+ /* preserve the on-channel rssi measurement
+ * if the new measurement is off channel
+ */
+ WL_SCAN(("%s("MACDBG"), prev onchan"
+ ", RSSI: prev %d new %d\n",
+ bss->SSID, MAC2STRDBG(bi->BSSID.octet),
+ bss->RSSI, bi->RSSI));
+ bi->RSSI = bss->RSSI;
+ bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
+ }
+ if (dtoh32(bss->length) != bi_length) {
+ u32 prev_len = dtoh32(bss->length);
+
+ WL_SCAN(("bss info replacement"
+ " is occured(bcast:%d->probresp%d)\n",
+ bss->ie_length, bi->ie_length));
+ WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n",
+ bss->SSID, MAC2STRDBG(bi->BSSID.octet),
+ prev_len, bi_length));
+
+ if (list->buflen - prev_len + bi_length
+ > ESCAN_BUF_SIZE) {
+ WL_ERR(("Buffer is too small: keep the"
+ " previous result of this AP\n"));
+ /* Only update RSSI */
+ bss->RSSI = bi->RSSI;
+ bss->flags |= (bi->flags
+ & WL_BSS_FLAGS_RSSI_ONCHANNEL);
+ goto exit;
+ }
+
+ if (i < list->count - 1) {
+ /* memory copy required by this case only */
+ memmove((u8 *)bss + bi_length,
+ (u8 *)bss + prev_len,
+ list->buflen - cur_len - prev_len);
+ }
+ list->buflen -= prev_len;
+ list->buflen += bi_length;
+ }
+ list->version = dtoh32(bi->version);
+ memcpy((u8 *)bss, (u8 *)bi, bi_length);
+ goto exit;
+ }
+ cur_len += dtoh32(bss->length);
+ }
+ if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
+#ifdef ESCAN_BUF_OVERFLOW_MGMT
+ wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
+ if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
+ WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
+ MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
+ goto exit;
+ }
+#else
+ WL_ERR(("Buffer is too small: ignoring\n"));
+ goto exit;
+#endif /* ESCAN_BUF_OVERFLOW_MGMT */
+ }
+
+ memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
+ list->version = dtoh32(bi->version);
+ list->buflen += bi_length;
+ list->count++;
+
+ /*
+ * !Broadcast && number of ssid = 1 && number of channels =1
+ * means specific scan to association
+ */
+ if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
+ WL_ERR(("P2P assoc scan fast aborted.\n"));
+ wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
+ goto exit;
+ }
+ }
+
+ }
+ else if (status == WLC_E_STATUS_SUCCESS) {
+ cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
+ escan_result->sync_id);
+
+ if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
+ WL_INFO(("ACTION FRAME SCAN DONE\n"));
+ wl_clr_p2p_status(cfg, SCANNING);
+ wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
+ if (cfg->afx_hdl->peer_chan == WL_INVALID)
+ complete(&cfg->act_frm_scan);
+ } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
+ WL_INFO(("ESCAN COMPLETED\n"));
+ cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
+ if (!scan_req_match(cfg)) {
+ WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
+ cfg->bss_list->count));
+ }
+ wl_inform_bss(cfg);
+ wl_notify_escan_complete(cfg, ndev, false, false);
+ }
+ wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
+ }
+ else if (status == WLC_E_STATUS_ABORT) {
+ cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ wl_escan_print_sync_id(status, escan_result->sync_id,
+ cfg->escan_info.cur_sync_id);
+ if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
+ WL_INFO(("ACTION FRAME SCAN DONE\n"));
+ wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
+ wl_clr_p2p_status(cfg, SCANNING);
+ if (cfg->afx_hdl->peer_chan == WL_INVALID)
+ complete(&cfg->act_frm_scan);
+ } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
+ WL_INFO(("ESCAN ABORTED\n"));
+ cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
+ if (!scan_req_match(cfg)) {
+ WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
+ cfg->bss_list->count));
+ }
+ wl_inform_bss(cfg);
+ wl_notify_escan_complete(cfg, ndev, true, false);
+ }
+ wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
+ } else if (status == WLC_E_STATUS_NEWSCAN) {
+ WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", cfg->scan_request));
+ WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id,
+ escan_result->bss_count));
+ } else if (status == WLC_E_STATUS_TIMEOUT) {
+ WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
+ WL_ERR(("reason[0x%x]\n", e->reason));
+ if (e->reason == 0xFFFFFFFF) {
+ wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
+ }
+ } else {
+ WL_ERR(("unexpected Escan Event %d : abort\n", status));
+ cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ wl_escan_print_sync_id(status, escan_result->sync_id,
+ cfg->escan_info.cur_sync_id);
+ if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
+ WL_INFO(("ACTION FRAME SCAN DONE\n"));
+ wl_clr_p2p_status(cfg, SCANNING);
+ wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
+ if (cfg->afx_hdl->peer_chan == WL_INVALID)
+ complete(&cfg->act_frm_scan);
+ } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
+ cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
+ if (!scan_req_match(cfg)) {
+ WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
+ "scanned AP count=%d\n",
+ cfg->bss_list->count));
+ }
+ wl_inform_bss(cfg);
+ wl_notify_escan_complete(cfg, ndev, true, false);
+ }
+ wl_escan_increment_sync_id(cfg, 2);
+ }
+exit:
+ mutex_unlock(&cfg->usr_sync);
+ return err;
+}
+
+static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
+{
+ u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
+ struct net_info *iter, *next;
+ int err;
+
+ if (!cfg->roamoff_on_concurrent)
+ return;
+ if (enable && connected_cnt > 1) {
+ for_each_ndev(cfg, iter, next) {
+ /* Save the current roam setting */
+ if ((err = wldev_iovar_getint(iter->ndev, "roam_off",
+ (s32 *)&iter->roam_off)) != BCME_OK) {
+ WL_ERR(("%s:Failed to get current roam setting err %d\n",
+ iter->ndev->name, err));
+ continue;
+ }
+ if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) {
+ WL_ERR((" %s:failed to set roam_off : %d\n",
+ iter->ndev->name, err));
+ }
+ }
+ }
+ else if (!enable) {
+ for_each_ndev(cfg, iter, next) {
+ if (iter->roam_off != WL_INVALID) {
+ if ((err = wldev_iovar_setint(iter->ndev, "roam_off",
+ iter->roam_off)) == BCME_OK)
+ iter->roam_off = WL_INVALID;
+ else {
+ WL_ERR((" %s:failed to set roam_off : %d\n",
+ iter->ndev->name, err));
+ }
+ }
+ }
+ }
+ return;
+}
+
+static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
+{
+ struct net_info *iter, *next;
+ u32 ctl_chan = 0;
+ u32 chanspec = 0;
+ u32 pre_ctl_chan = 0;
+ u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
+ cfg->vsdb_mode = false;
+
+ if (connected_cnt <= 1) {
+ return;
+ }
+ for_each_ndev(cfg, iter, next) {
+ /* p2p discovery iface ndev could be null */
+ if (iter->ndev) {
+ chanspec = 0;
+ ctl_chan = 0;
+ if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
+ if (wldev_iovar_getint(iter->ndev, "chanspec",
+ (s32 *)&chanspec) == BCME_OK) {
+ chanspec = wl_chspec_driver_to_host(chanspec);
+ ctl_chan = wf_chspec_ctlchan(chanspec);
+ wl_update_prof(cfg, iter->ndev, NULL,
+ &ctl_chan, WL_PROF_CHAN);
+ }
+ if (!cfg->vsdb_mode) {
+ if (!pre_ctl_chan && ctl_chan)
+ pre_ctl_chan = ctl_chan;
+ else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
+ cfg->vsdb_mode = true;
+ }
+ }
+ }
+ }
+ }
+ WL_ERR(("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel"));
+ return;
+}
+
+static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
+ enum wl_status state, bool set)
+{
+ s32 pm = PM_FAST;
+ s32 err = BCME_OK;
+ u32 mode;
+ u32 chan = 0;
+ struct net_info *iter, *next;
+ struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
+ WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
+ state, set, _net_info->pm_restore, _net_info->ndev->name));
+
+ if (state != WL_STATUS_CONNECTED)
+ return 0;
+ mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
+ if (set) {
+ wl_cfg80211_concurrent_roam(cfg, 1);
+
+ if (mode == WL_MODE_AP) {
+
+ if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
+ WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
+ }
+ wl_cfg80211_determine_vsdb_mode(cfg);
+ if (cfg->vsdb_mode || _net_info->pm_block) {
+ /* Delete pm_enable_work */
+ wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_MAINTAIN);
+ /* save PM_FAST in _net_info to restore this
+ * if _net_info->pm_block is false
+ */
+ if (!_net_info->pm_block && (mode == WL_MODE_BSS)) {
+ _net_info->pm = PM_FAST;
+ _net_info->pm_restore = true;
+ }
+ pm = PM_OFF;
+ for_each_ndev(cfg, iter, next) {
+ if (iter->pm_restore || (iter->ndev == NULL))
+ continue;
+ /* Save the current power mode */
+ err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm,
+ sizeof(iter->pm), false);
+ WL_DBG(("%s:power save %s\n", iter->ndev->name,
+ iter->pm ? "enabled" : "disabled"));
+ if (!err && iter->pm) {
+ iter->pm_restore = true;
+ }
+
+ }
+ for_each_ndev(cfg, iter, next) {
+ if (iter->ndev) {
+ if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev))
+ continue;
+ if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
+ sizeof(pm), true)) != 0) {
+ if (err == -ENODEV)
+ WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
+ else
+ WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
+ wl_cfg80211_update_power_mode(iter->ndev);
+ }
+ }
+ }
+ } else {
+ /* add PM Enable timer to go to power save mode
+ * if supplicant control pm mode, it will be cleared or
+ * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P,
+ * PM will be configured when timer expired
+ */
+
+ /*
+ * before calling pm_enable_timer, we need to set PM -1 for all ndev
+ */
+ pm = PM_OFF;
+ if (!_net_info->pm_block) {
+ for_each_ndev(cfg, iter, next) {
+ if (iter->pm_restore || (iter->ndev == NULL))
+ continue;
+ /* Save the current power mode */
+ err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm,
+ sizeof(iter->pm), false);
+ WL_DBG(("%s:power save %s\n", iter->ndev->name,
+ iter->pm ? "enabled" : "disabled"));
+ if (!err && iter->pm) {
+ iter->pm_restore = true;
+ }
+ }
+ }
+ for_each_ndev(cfg, iter, next) {
+ /* p2p discovery iface ndev ptr could be null */
+ if (iter->ndev) {
+ if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev))
+ continue;
+ if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
+ sizeof(pm), true)) != 0) {
+ if (err == -ENODEV)
+ WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
+ else
+ WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
+ }
+ }
+ }
+
+ if (cfg->pm_enable_work_on) {
+ wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_DEL);
+ }
+
+ cfg->pm_enable_work_on = true;
+ wl_add_remove_pm_enable_work(cfg, TRUE, WL_HANDLER_NOTUSE);
+ }
+#if defined(WLTDLS)
+#if defined(DISABLE_TDLS_IN_P2P)
+ if (cfg->vsdb_mode || p2p_is_on(cfg))
+#else
+ if (cfg->vsdb_mode)
+#endif /* defined(DISABLE_TDLS_IN_P2P) */
+ {
+
+ err = wldev_iovar_setint(primary_dev, "tdls_enable", 0);
+ }
+#endif /* defined(WLTDLS) */
+ }
+ else { /* clear */
+ chan = 0;
+ /* clear chan information when the net device is disconnected */
+ wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
+ wl_cfg80211_determine_vsdb_mode(cfg);
+ for_each_ndev(cfg, iter, next) {
+ /* p2p discovery iface ndev ptr could be null */
+ if (iter->ndev) {
+ if (iter->pm_restore && iter->pm) {
+ WL_DBG(("%s:restoring power save %s\n",
+ iter->ndev->name, (iter->pm ? "enabled" : "disabled")));
+ err = wldev_ioctl(iter->ndev,
+ WLC_SET_PM, &iter->pm, sizeof(iter->pm), true);
+ if (unlikely(err)) {
+ if (err == -ENODEV)
+ WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
+ else
+ WL_ERR(("%s:error(%d)\n", iter->ndev->name, err));
+ break;
+ }
+ iter->pm_restore = 0;
+ wl_cfg80211_update_power_mode(iter->ndev);
+ }
+ }
+ }
+ wl_cfg80211_concurrent_roam(cfg, 0);
+#if defined(WLTDLS)
+ if (!cfg->vsdb_mode) {
+ err = wldev_iovar_setint(primary_dev, "tdls_enable", 1);
+ }
+#endif /* defined(WLTDLS) */
+ }
+ return err;
+}
+static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
+{
+ int err = 0;
+
+ cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
+ cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ wl_escan_init_sync_id(cfg);
+
+ /* Init scan_timeout timer */
+ init_timer(&cfg->scan_timeout);
+ cfg->scan_timeout.data = (unsigned long) cfg;
+ cfg->scan_timeout.function = wl_scan_timeout;
+
+ return err;
+}
+
+static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
+{
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ s32 err = 0;
+
+ cfg->scan_request = NULL;
+ cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
+ cfg->roam_on = false;
+ cfg->active_scan = true;
+ cfg->rf_blocked = false;
+ cfg->vsdb_mode = false;
+ cfg->wlfc_on = false;
+ cfg->roamoff_on_concurrent = true;
+ cfg->disable_roam_event = false;
+ cfg->cfgdev_bssidx = -1;
+ /* register interested state */
+ set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
+ spin_lock_init(&cfg->cfgdrv_lock);
+ mutex_init(&cfg->ioctl_buf_sync);
+ init_waitqueue_head(&cfg->netif_change_event);
+ init_completion(&cfg->send_af_done);
+ init_completion(&cfg->iface_disable);
+ wl_init_eq(cfg);
+ err = wl_init_priv_mem(cfg);
+ if (err)
+ return err;
+ if (wl_create_event_handler(cfg))
+ return -ENOMEM;
+ wl_init_event_handler(cfg);
+ mutex_init(&cfg->usr_sync);
+ mutex_init(&cfg->event_sync);
+ err = wl_init_scan(cfg);
+ if (err)
+ return err;
+ wl_init_conf(cfg->conf);
+ wl_init_prof(cfg, ndev);
+ wl_link_down(cfg);
+ DNGL_FUNC(dhd_cfg80211_init, (cfg));
+
+ return err;
+}
+
+static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
+{
+ DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
+ wl_destroy_event_handler(cfg);
+ wl_flush_eq(cfg);
+ wl_link_down(cfg);
+ del_timer_sync(&cfg->scan_timeout);
+ wl_deinit_priv_mem(cfg);
+ if (wl_cfg80211_netdev_notifier_registered) {
+ wl_cfg80211_netdev_notifier_registered = FALSE;
+ unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
+ }
+}
+
+#if defined(WL_ENABLE_P2P_IF) || defined(P2PONEINT)
+static s32 wl_cfg80211_attach_p2p(void)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ WL_TRACE(("Enter \n"));
+
+ if (wl_cfgp2p_register_ndev(cfg) < 0) {
+ WL_ERR(("P2P attach failed. \n"));
+ return -ENODEV;
+ }
+
+ return 0;
+}
+#endif
+
+#if defined(WL_ENABLE_P2P_IF)
+static s32 wl_cfg80211_detach_p2p(void)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct wireless_dev *wdev;
+
+ WL_DBG(("Enter \n"));
+ if (!cfg) {
+ WL_ERR(("Invalid Ptr\n"));
+ return -EINVAL;
+ } else
+ wdev = cfg->p2p_wdev;
+
+ if (!wdev) {
+ WL_ERR(("Invalid Ptr\n"));
+ return -EINVAL;
+ }
+
+ wl_cfgp2p_unregister_ndev(cfg);
+
+ cfg->p2p_wdev = NULL;
+ cfg->p2p_net = NULL;
+ WL_DBG(("Freeing 0x%p \n", wdev));
+ kfree(wdev);
+
+ return 0;
+}
+#endif
+
+s32 wl_cfg80211_attach_post(struct net_device *ndev)
+{
+ struct bcm_cfg80211 * cfg = NULL;
+ s32 err = 0;
+ s32 ret = 0;
+ WL_TRACE(("In\n"));
+ if (unlikely(!ndev)) {
+ WL_ERR(("ndev is invaild\n"));
+ return -ENODEV;
+ }
+ cfg = g_bcm_cfg;
+ if (unlikely(!cfg)) {
+ WL_ERR(("cfg is invaild\n"));
+ return -EINVAL;
+ }
+ if (!wl_get_drv_status(cfg, READY, ndev)) {
+ if (cfg->wdev) {
+ ret = wl_cfgp2p_supported(cfg, ndev);
+ if (ret > 0) {
+#if !defined(WL_ENABLE_P2P_IF)
+ cfg->wdev->wiphy->interface_modes |=
+ (BIT(NL80211_IFTYPE_P2P_CLIENT)|
+ BIT(NL80211_IFTYPE_P2P_GO));
+#endif /* !WL_ENABLE_P2P_IF */
+ if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
+ goto fail;
+
+#ifdef P2PONEINT
+ if (!cfg->p2p_net) {
+ cfg->p2p_supported = true;
+
+ err = wl_cfg80211_attach_p2p();
+ if (err)
+ goto fail;
+
+ cfg->p2p_supported = true;
+ }
+#endif
+#if defined(WL_ENABLE_P2P_IF) || defined(P2PONEINT)
+ if (cfg->p2p_net) {
+ /* Update MAC addr for p2p0 interface here. */
+ memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
+ cfg->p2p_net->dev_addr[0] |= 0x02;
+ WL_ERR(("%s: p2p_dev_addr="MACDBG "\n",
+ cfg->p2p_net->name,
+ MAC2STRDBG(cfg->p2p_net->dev_addr)));
+ } else {
+ WL_ERR(("p2p_net not yet populated."
+ " Couldn't update the MAC Address for p2p0 \n"));
+ return -ENODEV;
+ }
+#endif /* WL_ENABLE_P2P_IF */
+#ifndef P2PONEINT
+ cfg->p2p_supported = true;
+#endif
+ } else if (ret == 0) {
+ if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
+ goto fail;
+ } else {
+ /* SDIO bus timeout */
+ err = -ENODEV;
+ goto fail;
+ }
+ }
+ }
+ wl_set_drv_status(cfg, READY, ndev);
+fail:
+ return err;
+}
+
+s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
+{
+ struct wireless_dev *wdev;
+ struct bcm_cfg80211 *cfg;
+ s32 err = 0;
+ struct device *dev;
+
+ WL_TRACE(("In\n"));
+ if (!ndev) {
+ WL_ERR(("ndev is invaild\n"));
+ return -ENODEV;
+ }
+ WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
+ dev = wl_cfg80211_get_parent_dev();
+
+ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+ if (unlikely(!wdev)) {
+ WL_ERR(("Could not allocate wireless device\n"));
+ return -ENOMEM;
+ }
+ err = wl_setup_wiphy(wdev, dev, context);
+ if (unlikely(err)) {
+ kfree(wdev);
+ return -ENOMEM;
+ }
+ wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
+ cfg = (struct bcm_cfg80211 *)wiphy_priv(wdev->wiphy);
+ cfg->wdev = wdev;
+ cfg->pub = context;
+ INIT_LIST_HEAD(&cfg->net_list);
+ spin_lock_init(&cfg->net_list_sync);
+ ndev->ieee80211_ptr = wdev;
+ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
+ wdev->netdev = ndev;
+ cfg->state_notifier = wl_notifier_change_state;
+ err = wl_alloc_netinfo(cfg, ndev, wdev, WL_MODE_BSS, PM_ENABLE, 0);
+ if (err) {
+ WL_ERR(("Failed to alloc net_info (%d)\n", err));
+ goto cfg80211_attach_out;
+ }
+ err = wl_init_priv(cfg);
+ if (err) {
+ WL_ERR(("Failed to init iwm_priv (%d)\n", err));
+ goto cfg80211_attach_out;
+ }
+
+ err = wl_setup_rfkill(cfg, TRUE);
+ if (err) {
+ WL_ERR(("Failed to setup rfkill %d\n", err));
+ goto cfg80211_attach_out;
+ }
+#ifdef DEBUGFS_CFG80211
+ err = wl_setup_debugfs(cfg);
+ if (err) {
+ WL_ERR(("Failed to setup debugfs %d\n", err));
+ goto cfg80211_attach_out;
+ }
+#endif
+ if (!wl_cfg80211_netdev_notifier_registered) {
+ wl_cfg80211_netdev_notifier_registered = TRUE;
+ err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
+ if (err) {
+ wl_cfg80211_netdev_notifier_registered = FALSE;
+ WL_ERR(("Failed to register notifierl %d\n", err));
+ goto cfg80211_attach_out;
+ }
+ }
+#if defined(COEX_DHCP)
+ cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
+ if (!cfg->btcoex_info)
+ goto cfg80211_attach_out;
+#endif
+
+ g_bcm_cfg = cfg;
+
+#if defined(WL_ENABLE_P2P_IF)
+#ifndef P2PONEINT
+ err = wl_cfg80211_attach_p2p();
+ if (err)
+ goto cfg80211_attach_out;
+#endif
+#endif
+
+ return err;
+
+cfg80211_attach_out:
+ wl_setup_rfkill(cfg, FALSE);
+ wl_free_wdev(cfg);
+ return err;
+}
+
+void wl_cfg80211_detach(void *para)
+{
+ struct bcm_cfg80211 *cfg;
+
+ (void)para;
+ cfg = g_bcm_cfg;
+
+ WL_TRACE(("In\n"));
+
+ wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_DEL);
+
+#if defined(COEX_DHCP)
+ wl_cfg80211_btcoex_deinit();
+ cfg->btcoex_info = NULL;
+#endif
+
+ wl_setup_rfkill(cfg, FALSE);
+#ifdef DEBUGFS_CFG80211
+ wl_free_debugfs(cfg);
+#endif
+ if (cfg->p2p_supported) {
+ if (timer_pending(&cfg->p2p->listen_timer))
+ del_timer_sync(&cfg->p2p->listen_timer);
+ wl_cfgp2p_deinit_priv(cfg);
+ }
+
+ if (timer_pending(&cfg->scan_timeout))
+ del_timer_sync(&cfg->scan_timeout);
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+#if defined(WL_ENABLE_P2P_IF)
+ wl_cfg80211_detach_p2p();
+#endif
+
+ wl_cfg80211_ibss_vsie_free(cfg);
+ wl_cfg80211_clear_mgmt_vndr_ies(cfg);
+ wl_deinit_priv(cfg);
+ g_bcm_cfg = NULL;
+ wl_cfg80211_clear_parent_dev();
+ wl_free_wdev(cfg);
+ /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
+ * structure "cfg", which is the private part of wiphy, has been freed in
+ * wl_free_wdev !!!!!!!!!!!
+ */
+}
+
+static void wl_wakeup_event(struct bcm_cfg80211 *cfg)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+
+ if (dhd->up && (cfg->event_tsk.thr_pid >= 0)) {
+ DHD_OS_WAKE_LOCK(cfg->pub);
+ up(&cfg->event_tsk.sema);
+ }
+}
+
+#if defined(P2PONEINT)
+static int wl_is_p2p_event(struct wl_event_q *e)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ switch (e->etype) {
+ case WLC_E_IF:
+ WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n",
+ e->etype, e->emsg.ifidx));
+
+ (void)schedule_timeout(20);
+
+ if (wl_get_p2p_status(cfg, IF_ADDING) ||
+ wl_get_p2p_status(cfg, IF_DELETING) ||
+ wl_get_p2p_status(cfg, IF_CHANGING) ||
+ wl_get_p2p_status(cfg, IF_CHANGED)) {
+ WL_TRACE(("P2P Event on Primary I/F (ifidx:%d)."
+ " Sent it to p2p0 \n", e->emsg.ifidx));
+ return TRUE;
+ } else {
+ WL_TRACE(("Event is Not p2p event return False \n"));
+ return FALSE;
+ }
+
+ case WLC_E_P2P_PROBREQ_MSG:
+ case WLC_E_P2P_DISC_LISTEN_COMPLETE:
+ case WLC_E_ACTION_FRAME_RX:
+ case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
+ case WLC_E_ACTION_FRAME_COMPLETE:
+
+ if (e->emsg.ifidx != 0) {
+ WL_TRACE(("P2P event(%d) on virtual interface(ifidx:%d)\n",
+ e->etype, e->emsg.ifidx));
+ return FALSE;
+ } else {
+ WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n",
+ e->etype, e->emsg.ifidx));
+ return TRUE;
+ }
+ break;
+
+ default:
+ WL_TRACE(("NON-P2P event(%d) on interface(ifidx:%d)\n",
+ e->etype, e->emsg.ifidx));
+ return FALSE;
+ }
+}
+#endif
+
+static s32 wl_event_handler(void *data)
+{
+ struct bcm_cfg80211 *cfg = NULL;
+ struct wl_event_q *e;
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;
+ bcm_struct_cfgdev *cfgdev = NULL;
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ struct net_device *ndev = NULL;
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+ cfg = (struct bcm_cfg80211 *)tsk->parent;
+
+ WL_INFO(("tsk Enter, tsk = 0x%p\n", tsk));
+
+ while (down_interruptible (&tsk->sema) == 0) {
+ SMP_RD_BARRIER_DEPENDS();
+ if (tsk->terminated) {
+ DHD_OS_WAKE_UNLOCK(cfg->pub);
+ break;
+ }
+ while ((e = wl_deq_event(cfg))) {
+ WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
+ /* All P2P device address related events comes on primary interface since
+ * there is no corresponding bsscfg for P2P interface. Map it to p2p0
+ * interface.
+ */
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#ifdef P2PONEINT
+ if ((wl_is_p2p_event(e) == TRUE) && (cfg->p2p_wdev)) {
+#else
+ if (WL_IS_P2P_DEV_EVENT(e) && (cfg->p2p_wdev)) {
+#endif
+ cfgdev = bcmcfg_to_p2p_wdev(cfg);
+ } else if (cfg->bss_cfgdev && (e->emsg.bsscfgidx == cfg->cfgdev_bssidx)) {
+ /* STA / AP on virtual interface */
+ cfgdev = (ndev = cfgdev_to_wlc_ndev(cfg->bss_cfgdev, cfg)) ?
+ ndev_to_wdev(ndev) : NULL;
+ } else {
+
+ ndev = dhd_idx2net((struct dhd_pub *)(cfg->pub), e->emsg.ifidx);
+ if (ndev)
+ cfgdev = ndev_to_wdev(ndev);
+#ifdef P2PONEINT
+ else if (e->etype == WLC_E_IF) {
+ wl_put_event(e);
+ DHD_OS_WAKE_UNLOCK(cfg->pub);
+ continue;
+ }
+
+ if (cfgdev == NULL) {
+ if (e->etype == WLC_E_IF)
+ cfgdev = bcmcfg_to_prmry_wdev(cfg);
+ else {
+ cfgdev = ndev_to_wdev(wl_to_p2p_bss_ndev(cfg,
+ P2PAPI_BSSCFG_CONNECTION));
+ }
+ }
+#endif
+ }
+#elif defined(WL_ENABLE_P2P_IF)
+ if (WL_IS_P2P_DEV_EVENT(e) && (cfg->p2p_net)) {
+ cfgdev = cfg->p2p_net;
+ } else if (cfg->bss_cfgdev && (e->emsg.bsscfgidx == cfg->cfgdev_bssidx)) {
+ /* STA / AP on virtual interface */
+ cfgdev = cfgdev_to_wlc_ndev(cfg->bss_cfgdev, cfg);
+ } else {
+ cfgdev = dhd_idx2net((struct dhd_pub *)(cfg->pub),
+ e->emsg.ifidx);
+ }
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+ if (!cfgdev) {
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ cfgdev = bcmcfg_to_prmry_wdev(cfg);
+#elif defined(WL_ENABLE_P2P_IF)
+ cfgdev = bcmcfg_to_prmry_ndev(cfg);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ }
+ if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
+ dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
+ if (dhd->busstate == DHD_BUS_DOWN) {
+ WL_ERR((": BUS is DOWN.\n"));
+ } else
+ cfg->evt_handler[e->etype](cfg, cfgdev, &e->emsg, e->edata);
+ } else {
+ WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
+ }
+ wl_put_event(e);
+ }
+ DHD_OS_WAKE_UNLOCK(cfg->pub);
+ }
+ WL_INFO(("was terminated\n"));
+ complete_and_exit(&tsk->completed, 0);
+ return 0;
+}
+
+void
+wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
+{
+ u32 event_type = ntoh32(e->event_type);
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct net_info *netinfo;
+
+#if (WL_DBG_LEVEL > 0)
+ s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
+ wl_dbg_estr[event_type] : (s8 *) "Unknown";
+ WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
+#endif /* (WL_DBG_LEVEL > 0) */
+
+ if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
+ WL_ERR(("Stale event ignored\n"));
+ return;
+ }
+ if (wl_get_p2p_status(cfg, IF_CHANGING) || wl_get_p2p_status(cfg, IF_ADDING)) {
+ WL_ERR(("during IF change, ignore event %d\n", event_type));
+ return;
+ }
+
+#ifdef DHD_IFDEBUG
+ if (event_type != WLC_E_ESCAN_RESULT) {
+ WL_ERR(("Event_type %d , status : %d, reason : %d, bssidx:%d \n",
+ event_type, ntoh32(e->status), ntoh32(e->reason), e->bsscfgidx));
+ }
+#endif
+ netinfo = wl_get_netinfo_by_bssidx(cfg, e->bsscfgidx);
+ if (!netinfo) {
+ /* Since the netinfo entry is not there, the netdev entry is not
+ * created via cfg80211 interface. so the event is not of interest
+ * to the cfg80211 layer.
+ */
+ WL_ERR(("%d : ignore event %d, not interested\n", __LINE__, event_type));
+ return;
+ }
+
+ if (event_type == WLC_E_PFN_NET_FOUND) {
+ WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
+ }
+ else if (event_type == WLC_E_PFN_NET_LOST) {
+ WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
+ }
+
+ if (likely(!wl_enq_event(cfg, ndev, event_type, e, data)))
+ wl_wakeup_event(cfg);
+}
+
+static void wl_init_eq(struct bcm_cfg80211 *cfg)
+{
+ wl_init_eq_lock(cfg);
+ INIT_LIST_HEAD(&cfg->eq_list);
+}
+
+static void wl_flush_eq(struct bcm_cfg80211 *cfg)
+{
+ struct wl_event_q *e;
+ unsigned long flags;
+
+ flags = wl_lock_eq(cfg);
+ while (!list_empty(&cfg->eq_list)) {
+ e = list_first_entry(&cfg->eq_list, struct wl_event_q, eq_list);
+ list_del(&e->eq_list);
+ kfree(e);
+ }
+ wl_unlock_eq(cfg, flags);
+}
+
+/*
+* retrieve first queued event from head
+*/
+
+static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
+{
+ struct wl_event_q *e = NULL;
+ unsigned long flags;
+
+ flags = wl_lock_eq(cfg);
+ if (likely(!list_empty(&cfg->eq_list))) {
+ e = list_first_entry(&cfg->eq_list, struct wl_event_q, eq_list);
+ list_del(&e->eq_list);
+ }
+ wl_unlock_eq(cfg, flags);
+
+ return e;
+}
+
+/*
+ * push event to tail of the queue
+ */
+
+static s32
+wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
+ const wl_event_msg_t *msg, void *data)
+{
+ struct wl_event_q *e;
+ s32 err = 0;
+ uint32 evtq_size;
+ uint32 data_len;
+ unsigned long flags;
+ gfp_t aflags;
+
+ data_len = 0;
+ if (data)
+ data_len = ntoh32(msg->datalen);
+ evtq_size = sizeof(struct wl_event_q) + data_len;
+ aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
+ e = kzalloc(evtq_size, aflags);
+ if (unlikely(!e)) {
+ WL_ERR(("event alloc failed\n"));
+ return -ENOMEM;
+ }
+ e->etype = event;
+ memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
+ if (data)
+ memcpy(e->edata, data, data_len);
+ flags = wl_lock_eq(cfg);
+ list_add_tail(&e->eq_list, &cfg->eq_list);
+ wl_unlock_eq(cfg, flags);
+
+ return err;
+}
+
+static void wl_put_event(struct wl_event_q *e)
+{
+ kfree(e);
+}
+
+static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype)
+{
+ s32 infra = 0;
+ s32 err = 0;
+ s32 mode = 0;
+ switch (iftype) {
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_WDS:
+ WL_ERR(("type (%d) : currently we do not support this mode\n",
+ iftype));
+ err = -EINVAL;
+ return err;
+ case NL80211_IFTYPE_ADHOC:
+ mode = WL_MODE_IBSS;
+ break;
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ mode = WL_MODE_BSS;
+ infra = 1;
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ mode = WL_MODE_AP;
+ infra = 1;
+ break;
+ default:
+ err = -EINVAL;
+ WL_ERR(("invalid type (%d)\n", iftype));
+ return err;
+ }
+ infra = htod32(infra);
+ err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
+ if (unlikely(err)) {
+ WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
+ return err;
+ }
+
+ wl_set_mode_by_netdev(cfg, ndev, mode);
+
+ return 0;
+}
+
+void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
+{
+ if (!ev || (event > WLC_E_LAST))
+ return;
+
+ if (ev->num < MAX_EVENT_BUF_NUM) {
+ ev->event[ev->num].type = event;
+ ev->event[ev->num].set = set;
+ ev->num++;
+ } else {
+ WL_ERR(("evenbuffer doesn't support > %u events. Update"
+ " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
+ ASSERT(0);
+ }
+}
+
+s32 wl_cfg80211_apply_eventbuffer(
+ struct net_device *ndev,
+ struct bcm_cfg80211 *cfg,
+ wl_eventmsg_buf_t *ev)
+{
+ char eventmask[WL_EVENTING_MASK_LEN];
+ int i, ret = 0;
+ s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
+
+ if (!ev || (!ev->num))
+ return -EINVAL;
+
+ mutex_lock(&cfg->event_sync);
+
+ /* Read event_msgs mask */
+ bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
+ sizeof(iovbuf));
+ ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
+ if (unlikely(ret)) {
+ WL_ERR(("Get event_msgs error (%d)\n", ret));
+ goto exit;
+ }
+ memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
+
+ /* apply the set bits */
+ for (i = 0; i < ev->num; i++) {
+ if (ev->event[i].set)
+ setbit(eventmask, ev->event[i].type);
+ else
+ clrbit(eventmask, ev->event[i].type);
+ }
+
+ /* Write updated Event mask */
+ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+ sizeof(iovbuf));
+ ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
+ if (unlikely(ret)) {
+ WL_ERR(("Set event_msgs error (%d)\n", ret));
+ }
+
+exit:
+ mutex_unlock(&cfg->event_sync);
+ return ret;
+}
+
+s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
+{
+ s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
+ s8 eventmask[WL_EVENTING_MASK_LEN];
+ s32 err = 0;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ if (!ndev || !cfg)
+ return -ENODEV;
+
+ mutex_lock(&cfg->event_sync);
+
+ /* Setup event_msgs */
+ bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
+ sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
+ if (unlikely(err)) {
+ WL_ERR(("Get event_msgs error (%d)\n", err));
+ goto eventmsg_out;
+ }
+ memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
+ if (add) {
+ setbit(eventmask, event);
+ } else {
+ clrbit(eventmask, event);
+ }
+ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+ sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
+ if (unlikely(err)) {
+ WL_ERR(("Set event_msgs error (%d)\n", err));
+ goto eventmsg_out;
+ }
+
+eventmsg_out:
+ mutex_unlock(&cfg->event_sync);
+ return err;
+}
+
+static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
+{
+ struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
+ struct ieee80211_channel *band_chan_arr = NULL;
+ wl_uint32_list_t *list;
+ u32 i, j, index, n_2g, n_5g, band, channel, array_size;
+ u32 *n_cnt = NULL;
+ chanspec_t c = 0;
+ s32 err = BCME_OK;
+ bool update;
+ bool ht40_allowed;
+ u8 *pbuf = NULL;
+ bool dfs_radar_disabled = FALSE;
+
+#define LOCAL_BUF_LEN 1024
+ pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
+
+ if (pbuf == NULL) {
+ WL_ERR(("failed to allocate local buf\n"));
+ return -ENOMEM;
+ }
+ list = (wl_uint32_list_t *)(void *)pbuf;
+ list->count = htod32(WL_NUMCHANSPECS);
+
+
+ err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
+ 0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
+ if (err != 0) {
+ WL_ERR(("get chanspecs failed with %d\n", err));
+ kfree(pbuf);
+ return err;
+ }
+#undef LOCAL_BUF_LEN
+
+ list = (wl_uint32_list_t *)(void *)pbuf;
+ band = array_size = n_2g = n_5g = 0;
+ for (i = 0; i < dtoh32(list->count); i++) {
+ index = 0;
+ update = false;
+ ht40_allowed = false;
+ c = (chanspec_t)dtoh32(list->element[i]);
+ c = wl_chspec_driver_to_host(c);
+ channel = CHSPEC_CHANNEL(c);
+ if (CHSPEC_IS40(c)) {
+ if (CHSPEC_SB_UPPER(c))
+ channel += CH_10MHZ_APART;
+ else
+ channel -= CH_10MHZ_APART;
+ } else if (CHSPEC_IS80(c)) {
+ WL_DBG(("HT80 center channel : %d\n", channel));
+ continue;
+ }
+ if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
+ (channel <= CH_MAX_2G_CHANNEL)) {
+ band_chan_arr = __wl_2ghz_channels;
+ array_size = ARRAYSIZE(__wl_2ghz_channels);
+ n_cnt = &n_2g;
+ band = NL80211_BAND_2GHZ;
+ ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
+ } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
+ band_chan_arr = __wl_5ghz_a_channels;
+ array_size = ARRAYSIZE(__wl_5ghz_a_channels);
+ n_cnt = &n_5g;
+ band = NL80211_BAND_5GHZ;
+ ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
+ } else {
+ WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
+ continue;
+ }
+ if (!ht40_allowed && CHSPEC_IS40(c))
+ continue;
+ for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
+ if (band_chan_arr[j].hw_value == channel) {
+ update = true;
+ break;
+ }
+ }
+ if (update)
+ index = j;
+ else
+ index = *n_cnt;
+ if (index < array_size) {
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+ band_chan_arr[index].center_freq =
+ ieee80211_channel_to_frequency(channel);
+#else
+ band_chan_arr[index].center_freq =
+ ieee80211_channel_to_frequency(channel, band);
+#endif
+ band_chan_arr[index].hw_value = channel;
+
+ if (CHSPEC_IS40(c) && ht40_allowed) {
+ /* assuming the order is HT20, HT40 Upper,
+ * HT40 lower from chanspecs
+ */
+ u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
+ if (CHSPEC_SB_UPPER(c)) {
+ if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+ band_chan_arr[index].flags &=
+ ~IEEE80211_CHAN_NO_HT40;
+ band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
+ } else {
+ /* It should be one of
+ * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
+ */
+ band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
+ if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+ band_chan_arr[index].flags |=
+ IEEE80211_CHAN_NO_HT40MINUS;
+ }
+ } else {
+ band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
+ if (!dfs_radar_disabled) {
+ if (band == NL80211_BAND_2GHZ)
+ channel |= WL_CHANSPEC_BAND_2G;
+ else
+ channel |= WL_CHANSPEC_BAND_5G;
+ channel |= WL_CHANSPEC_BW_20;
+ channel = wl_chspec_host_to_driver(channel);
+ err = wldev_iovar_getint(dev, "per_chan_info", &channel);
+ if (!err) {
+ if (channel & WL_CHAN_RADAR) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+ band_chan_arr[index].flags |=
+ (IEEE80211_CHAN_RADAR
+ | IEEE80211_CHAN_NO_IBSS);
+#else
+ band_chan_arr[index].flags |=
+ IEEE80211_CHAN_RADAR;
+#endif
+ }
+
+ if (channel & WL_CHAN_PASSIVE)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+ band_chan_arr[index].flags |=
+ IEEE80211_CHAN_PASSIVE_SCAN;
+#else
+ band_chan_arr[index].flags |=
+ IEEE80211_CHAN_NO_IR;
+#endif
+ } else if (err == BCME_UNSUPPORTED) {
+ dfs_radar_disabled = TRUE;
+ WL_ERR(("does not support per_chan_info\n"));
+ }
+ }
+ }
+ if (!update)
+ (*n_cnt)++;
+ }
+
+ }
+ __wl_band_2ghz.n_channels = n_2g;
+ __wl_band_5ghz_a.n_channels = n_5g;
+ kfree(pbuf);
+ return err;
+}
+
+s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
+{
+ struct wiphy *wiphy;
+ struct net_device *dev;
+ u32 bandlist[3];
+ u32 nband = 0;
+ u32 i = 0;
+ s32 err = 0;
+ s32 index = 0;
+ s32 nmode = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+ u32 j = 0;
+ s32 vhtmode = 0;
+ s32 txstreams = 0;
+ s32 rxstreams = 0;
+ s32 ldpc_cap = 0;
+ s32 stbc_rx = 0;
+ s32 stbc_tx = 0;
+ s32 txbf_bfe_cap = 0;
+ s32 txbf_bfr_cap = 0;
+#endif
+ bool rollback_lock = false;
+ s32 bw_cap = 0;
+ s32 cur_band = -1;
+ struct ieee80211_supported_band *bands[NUM_NL80211_BANDS] = {NULL, };
+
+ if (cfg == NULL) {
+ cfg = g_bcm_cfg;
+ mutex_lock(&cfg->usr_sync);
+ rollback_lock = true;
+ }
+ dev = bcmcfg_to_prmry_ndev(cfg);
+
+ memset(bandlist, 0, sizeof(bandlist));
+ err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
+ sizeof(bandlist), false);
+ if (unlikely(err)) {
+ WL_ERR(("error read bandlist (%d)\n", err));
+ goto end_bands;
+ }
+ err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
+ sizeof(s32), false);
+ if (unlikely(err)) {
+ WL_ERR(("error (%d)\n", err));
+ goto end_bands;
+ }
+
+ err = wldev_iovar_getint(dev, "nmode", &nmode);
+ if (unlikely(err)) {
+ WL_ERR(("error reading nmode (%d)\n", err));
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+ err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
+ if (unlikely(err)) {
+ WL_ERR(("error reading vhtmode (%d)\n", err));
+ }
+
+ if (vhtmode) {
+ err = wldev_iovar_getint(dev, "txstreams", &txstreams);
+ if (unlikely(err)) {
+ WL_ERR(("error reading txstreams (%d)\n", err));
+ }
+
+ err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
+ if (unlikely(err)) {
+ WL_ERR(("error reading rxstreams (%d)\n", err));
+ }
+
+ err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
+ if (unlikely(err)) {
+ WL_ERR(("error reading ldpc_cap (%d)\n", err));
+ }
+
+ err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
+ if (unlikely(err)) {
+ WL_ERR(("error reading stbc_rx (%d)\n", err));
+ }
+
+ err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
+ if (unlikely(err)) {
+ WL_ERR(("error reading stbc_tx (%d)\n", err));
+ }
+
+ err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
+ if (unlikely(err)) {
+ WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
+ }
+
+ err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
+ if (unlikely(err)) {
+ WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
+ }
+ }
+#endif
+
+ /* For nmode and vhtmode check bw cap */
+ if (nmode ||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+ vhtmode ||
+#endif
+ 0) {
+ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
+ if (unlikely(err)) {
+ WL_ERR(("error get mimo_bw_cap (%d)\n", err));
+ }
+ }
+
+ err = wl_construct_reginfo(cfg, bw_cap);
+ if (err) {
+ WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
+ if (err != BCME_UNSUPPORTED)
+ goto end_bands;
+ err = 0;
+ }
+ wiphy = bcmcfg_to_wiphy(cfg);
+ nband = bandlist[0];
+
+ for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
+ index = -1;
+ if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
+ bands[NL80211_BAND_5GHZ] =
+ &__wl_band_5ghz_a;
+ index = NL80211_BAND_5GHZ;
+ if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
+ bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+ /* VHT capabilities. */
+ if (vhtmode) {
+ /* Supported */
+ bands[index]->vht_cap.vht_supported = TRUE;
+
+ for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
+ /* TX stream rates. */
+ if (j <= txstreams) {
+ VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
+ bands[index]->vht_cap.vht_mcs.tx_mcs_map);
+ } else {
+ VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
+ bands[index]->vht_cap.vht_mcs.tx_mcs_map);
+ }
+
+ /* RX stream rates. */
+ if (j <= rxstreams) {
+ VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
+ bands[index]->vht_cap.vht_mcs.rx_mcs_map);
+ } else {
+ VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
+ bands[index]->vht_cap.vht_mcs.rx_mcs_map);
+ }
+ }
+
+
+ /* Capabilities */
+ /* 80 MHz is mandatory */
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_SHORT_GI_80;
+
+ if (WL_BW_CAP_160MHZ(bw_cap)) {
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_SHORT_GI_160;
+ }
+
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
+
+ if (ldpc_cap)
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_RXLDPC;
+
+ if (stbc_tx)
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_TXSTBC;
+
+ if (stbc_rx)
+ bands[index]->vht_cap.cap |=
+ (stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
+
+ if (txbf_bfe_cap)
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
+
+ if (txbf_bfr_cap) {
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
+ }
+
+ if (txbf_bfe_cap || txbf_bfr_cap) {
+ bands[index]->vht_cap.cap |=
+ (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
+ bands[index]->vht_cap.cap |=
+ ((txstreams - 1) <<
+ VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
+ bands[index]->vht_cap.cap |=
+ IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
+ }
+
+ /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
+ bands[index]->vht_cap.cap |=
+ (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
+ WL_INFO(("%s band[%d] vht_enab=%d vht_cap=%08x "
+ "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
+ __FUNCTION__, index,
+ bands[index]->vht_cap.vht_supported,
+ bands[index]->vht_cap.cap,
+ bands[index]->vht_cap.vht_mcs.rx_mcs_map,
+ bands[index]->vht_cap.vht_mcs.tx_mcs_map));
+ }
+#endif
+ }
+ else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
+ bands[NL80211_BAND_2GHZ] =
+ &__wl_band_2ghz;
+ index = NL80211_BAND_2GHZ;
+ if (bw_cap == WLC_N_BW_40ALL)
+ bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+ }
+
+ if ((index >= 0) && nmode) {
+ bands[index]->ht_cap.cap |=
+ (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
+ bands[index]->ht_cap.ht_supported = TRUE;
+ bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+ /* An HT shall support all EQM rates for one spatial stream */
+ bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
+ }
+
+ }
+
+ wiphy->bands[NL80211_BAND_2GHZ] = bands[NL80211_BAND_2GHZ];
+ wiphy->bands[NL80211_BAND_5GHZ] = bands[NL80211_BAND_5GHZ];
+
+ /* check if any bands populated otherwise makes 2Ghz as default */
+ if (wiphy->bands[NL80211_BAND_2GHZ] == NULL &&
+ wiphy->bands[NL80211_BAND_5GHZ] == NULL) {
+ /* Setup 2Ghz band as default */
+ wiphy->bands[NL80211_BAND_2GHZ] = &__wl_band_2ghz;
+ }
+
+ if (notify) {
+ struct ieee80211_supported_band *sband;
+ enum nl80211_band wiphy_band;
+ struct ieee80211_channel *chan;
+ for (wiphy_band = 0; wiphy_band < NUM_NL80211_BANDS;
+ wiphy_band++) {
+ sband = wiphy->bands[wiphy_band];
+ if (!sband)
+ continue;
+ for (i = 0; i < sband->n_channels; i++) {
+ chan = &sband->channels[i];
+ chan->beacon_found = false;
+ }
+ }
+ wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
+ }
+
+ end_bands:
+ if (rollback_lock)
+ mutex_unlock(&cfg->usr_sync);
+ return err;
+}
+
+static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
+{
+ s32 err = 0;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ struct wireless_dev *wdev = ndev->ieee80211_ptr;
+
+ WL_DBG(("In\n"));
+
+ err = dhd_config_dongle(cfg);
+ if (unlikely(err))
+ return err;
+
+ err = wl_config_ifmode(cfg, ndev, wdev->iftype);
+ if (unlikely(err && err != -EINPROGRESS)) {
+ WL_ERR(("wl_config_ifmode failed\n"));
+ if (err == -1) {
+ WL_ERR(("return error %d\n", err));
+ return err;
+ }
+ }
+ err = wl_update_wiphybands(cfg, true);
+ if (unlikely(err)) {
+ WL_ERR(("wl_update_wiphybands failed\n"));
+ if (err == -1) {
+ WL_ERR(("return error %d\n", err));
+ return err;
+ }
+ }
+ if (!dhd_download_fw_on_driverload) {
+ err = wl_create_event_handler(cfg);
+ if (err) {
+ WL_ERR(("wl_create_event_handler failed\n"));
+ return err;
+ }
+ wl_init_event_handler(cfg);
+ }
+
+ err = wl_init_scan(cfg);
+ if (err) {
+ WL_ERR(("wl_init_scan failed\n"));
+ return err;
+ }
+
+ err = dhd_monitor_init(cfg->pub);
+
+ INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
+ wl_set_drv_status(cfg, READY, ndev);
+ return err;
+}
+
+static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
+{
+ s32 err = 0;
+ unsigned long flags;
+ struct net_info *iter, *next;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+#if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF) && !defined(PLATFORM_SLP)
+ struct net_device *p2p_net = cfg->p2p_net;
+#endif
+#ifdef PROP_TXSTATUS_VSDB
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+#endif /* PROP_TXSTATUS_VSDB */
+ WL_DBG(("In\n"));
+ /* Delete pm_enable_work */
+ wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_DEL);
+
+#ifdef WL_NAN
+ wl_cfgnan_stop_handler(ndev, g_bcm_cfg, NULL, NULL);
+#endif /* WL_NAN */
+
+ if (cfg->p2p_supported) {
+ wl_clr_p2p_status(cfg, GO_NEG_PHASE);
+#ifdef PROP_TXSTATUS_VSDB
+ if (wl_cfgp2p_vif_created(cfg)) {
+ bool enabled = false;
+ dhd_wlfc_get_enable(dhd, &enabled);
+ if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
+ dhd->op_mode != DHD_FLAG_IBSS_MODE) {
+ dhd_wlfc_deinit(dhd);
+ cfg->wlfc_on = false;
+ }
+ }
+#endif /* PROP_TXSTATUS_VSDB */
+ }
+
+ /* Check if cfg80211 interface is already down */
+ if (!wl_get_drv_status(cfg, READY, ndev)) {
+ WL_DBG(("cfg80211 interface is already down"));
+ return err; /* it is even not ready */
+ }
+
+
+ /* If primary BSS is operational (for e.g SoftAP), bring it down */
+ if (wl_cfgp2p_bss_isup(ndev, 0)) {
+ if (wl_cfgp2p_bss(cfg, ndev, 0, 0) < 0)
+ WL_ERR(("BSS down failed \n"));
+ }
+
+ for_each_ndev(cfg, iter, next) {
+ /* p2p discovery iface ndev ptr could be null */
+ if (iter->ndev) {
+ wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
+ }
+ }
+
+
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+ if (cfg->scan_request) {
+ struct cfg80211_scan_info info = {
+ .aborted = true,
+ };
+
+ cfg80211_scan_done(cfg->scan_request, &info);
+ cfg->scan_request = NULL;
+ }
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+
+ for_each_ndev(cfg, iter, next) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
+ CFG80211_DISCONNECTED(iter->ndev, 0, NULL, 0, false, GFP_KERNEL);
+ }
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
+ wl_clr_drv_status(cfg, READY, iter->ndev);
+ wl_clr_drv_status(cfg, SCANNING, iter->ndev);
+ wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
+ wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
+ wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
+ wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
+ wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
+ wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
+ }
+ bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
+ NL80211_IFTYPE_STATION;
+#if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF) && !defined(PLATFORM_SLP)
+ if (p2p_net)
+ dev_close(p2p_net);
+#endif
+ DNGL_FUNC(dhd_cfg80211_down, (cfg));
+
+ if (!dhd_download_fw_on_driverload) {
+ /* Avoid deadlock from wl_cfg80211_down */
+ mutex_unlock(&cfg->usr_sync);
+ wl_destroy_event_handler(cfg);
+ mutex_lock(&cfg->usr_sync);
+ }
+ wl_flush_eq(cfg);
+ wl_link_down(cfg);
+ if (cfg->p2p_supported) {
+ if (timer_pending(&cfg->p2p->listen_timer))
+ del_timer_sync(&cfg->p2p->listen_timer);
+ wl_cfgp2p_down(cfg);
+ }
+
+ if (timer_pending(&cfg->scan_timeout)) {
+ del_timer_sync(&cfg->scan_timeout);
+ }
+
+ dhd_monitor_uninit();
+
+#if defined(WL_VIRTUAL_APSTA)
+ /* Clean up if not removed already */
+ if (cfg->bss_cfgdev) {
+ wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
+ }
+#endif /* defined (WL_VIRTUAL_APSTA) */
+
+#ifdef WL11U
+ /* Clear interworking element. */
+ if (cfg->wl11u) {
+ cfg->wl11u = FALSE;
+ cfg->iw_ie_len = 0;
+ memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
+ }
+#endif /* WL11U */
+
+#ifdef DHD_IFDEBUG
+ /* Printout all netinfo entries */
+ wl_probe_wdev_all(cfg);
+#endif /* DHD_IFDEBUG */
+
+ return err;
+}
+
+s32 wl_cfg80211_up(void *para)
+{
+ struct bcm_cfg80211 *cfg;
+ s32 err = 0;
+ int val = 1;
+ dhd_pub_t *dhd;
+ (void)para;
+ WL_DBG(("In\n"));
+ cfg = g_bcm_cfg;
+
+ if ((err = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
+ sizeof(int), false) < 0)) {
+ WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
+ return err;
+ }
+ val = dtoh32(val);
+ if (val != WLC_IOCTL_VERSION && val != 1) {
+ WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
+ val, WLC_IOCTL_VERSION));
+ return BCME_VERSION;
+ }
+ ioctl_version = val;
+ WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
+
+ mutex_lock(&cfg->usr_sync);
+ dhd = (dhd_pub_t *)(cfg->pub);
+ if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
+ err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
+ if (unlikely(err)) {
+ mutex_unlock(&cfg->usr_sync);
+ return err;
+ }
+ } else {
+ WL_ERR(("Disable p2p support in hostap mode\n"));
+ cfg->p2p_supported = FALSE;
+ }
+ err = __wl_cfg80211_up(cfg);
+ if (unlikely(err))
+ WL_ERR(("__wl_cfg80211_up failed\n"));
+
+
+ mutex_unlock(&cfg->usr_sync);
+ return err;
+}
+
+/* Private Event to Supplicant with indication that chip hangs */
+int wl_cfg80211_hang(struct net_device *dev, u16 reason)
+{
+ struct bcm_cfg80211 *cfg;
+#if defined(SOFTAP_SEND_HANGEVT)
+ /* specifc mac address used for hang event */
+ uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
+ dhd_pub_t *dhd;
+#endif /* SOFTAP_SEND_HANGEVT */
+ if (!g_bcm_cfg) {
+ return BCME_ERROR;
+ }
+ cfg = g_bcm_cfg;
+
+ WL_ERR(("In : chip crash eventing\n"));
+ wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_DEL);
+#if defined(SOFTAP_SEND_HANGEVT)
+ dhd = (dhd_pub_t *)(cfg->pub);
+ if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
+ cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
+ } else
+#endif /* SOFTAP_SEND_HANGEVT */
+ {
+ CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
+ }
+ if (cfg != NULL) {
+ wl_link_down(cfg);
+ }
+ return 0;
+}
+
+s32 wl_cfg80211_down(void *para)
+{
+ struct bcm_cfg80211 *cfg;
+ s32 err = 0;
+
+ (void)para;
+ WL_DBG(("In\n"));
+ cfg = g_bcm_cfg;
+ mutex_lock(&cfg->usr_sync);
+ err = __wl_cfg80211_down(cfg);
+ mutex_unlock(&cfg->usr_sync);
+
+ return err;
+}
+
+static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
+{
+ unsigned long flags;
+ void *rptr = NULL;
+ struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
+
+ if (!profile)
+ return NULL;
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+ switch (item) {
+ case WL_PROF_SEC:
+ rptr = &profile->sec;
+ break;
+ case WL_PROF_ACT:
+ rptr = &profile->active;
+ break;
+ case WL_PROF_BSSID:
+ rptr = profile->bssid;
+ break;
+ case WL_PROF_SSID:
+ rptr = &profile->ssid;
+ break;
+ case WL_PROF_CHAN:
+ rptr = &profile->channel;
+ break;
+ }
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+ if (!rptr)
+ WL_ERR(("invalid item (%d)\n", item));
+ return rptr;
+}
+
+static s32
+wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, s32 item)
+{
+ s32 err = 0;
+ struct wlc_ssid *ssid;
+ unsigned long flags;
+ struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
+
+ if (!profile)
+ return WL_INVALID;
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+ switch (item) {
+ case WL_PROF_SSID:
+ ssid = (wlc_ssid_t *) data;
+ memset(profile->ssid.SSID, 0,
+ sizeof(profile->ssid.SSID));
+ profile->ssid.SSID_len = MIN(ssid->SSID_len, DOT11_MAX_SSID_LEN);
+ memcpy(profile->ssid.SSID, ssid->SSID, profile->ssid.SSID_len);
+ break;
+ case WL_PROF_BSSID:
+ if (data)
+ memcpy(profile->bssid, data, ETHER_ADDR_LEN);
+ else
+ memset(profile->bssid, 0, ETHER_ADDR_LEN);
+ break;
+ case WL_PROF_SEC:
+ memcpy(&profile->sec, data, sizeof(profile->sec));
+ break;
+ case WL_PROF_ACT:
+ profile->active = *(bool *)data;
+ break;
+ case WL_PROF_BEACONINT:
+ profile->beacon_interval = *(u16 *)data;
+ break;
+ case WL_PROF_DTIMPERIOD:
+ profile->dtim_period = *(u8 *)data;
+ break;
+ case WL_PROF_CHAN:
+ profile->channel = *(u32*)data;
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+
+ if (err == -EOPNOTSUPP)
+ WL_ERR(("unsupported item (%d)\n", item));
+
+ return err;
+}
+
+void wl_cfg80211_dbg_level(u32 level)
+{
+ /*
+ * prohibit to change debug level
+ * by insmod parameter.
+ * eventually debug level will be configured
+ * in compile time by using CONFIG_XXX
+ */
+ /* wl_dbg_level = level; */
+}
+
+static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
+{
+ return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
+}
+
+static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
+{
+ return cfg->ibss_starter;
+}
+
+static void wl_rst_ie(struct bcm_cfg80211 *cfg)
+{
+ struct wl_ie *ie = wl_to_ie(cfg);
+
+ ie->offset = 0;
+}
+
+static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
+{
+ struct wl_ie *ie = wl_to_ie(cfg);
+ s32 err = 0;
+
+ if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
+ WL_ERR(("ei crosses buffer boundary\n"));
+ return -ENOSPC;
+ }
+ ie->buf[ie->offset] = t;
+ ie->buf[ie->offset + 1] = l;
+ memcpy(&ie->buf[ie->offset + 2], v, l);
+ ie->offset += l + 2;
+
+ return err;
+}
+
+static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size, bool roam)
+{
+ u8 *ssidie;
+ int32 ssid_len = MIN(bi->SSID_len, DOT11_MAX_SSID_LEN);
+ int32 remaining_ie_buf_len, available_buffer_len;
+ ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
+
+ /* ERROR out if
+ * 1. No ssid IE is FOUND or
+ * 2. New ssid length is > what was allocated for existing ssid (as
+ * we do not want to overwrite the rest of the IEs) or
+ * 3. If in case of erroneous buffer input where ssid length doesnt match the space
+ * allocated to it.
+ */
+ if (!ssidie)
+ return;
+ available_buffer_len = ((int)(*ie_size)) - (ssidie + 2 - ie_stream);
+ remaining_ie_buf_len = available_buffer_len - (int)ssidie[1];
+ if ((ssid_len > ssidie[1]) ||
+ (ssidie[1] > available_buffer_len)) {
+ return;
+ }
+ if (ssidie[1] != ssid_len) {
+ if (ssidie[1]) {
+ WL_ERR(("%s: Wrong SSID len: %d != %d\n",
+ __FUNCTION__, ssidie[1], bi->SSID_len));
+ }
+ if (roam) {
+ WL_ERR(("Changing the SSID Info.\n"));
+ memmove(ssidie + ssid_len + 2,
+ (ssidie + 2) + ssidie[1],
+ *ie_size - (ssidie + 2 + ssidie[1] - ie_stream));
+ memcpy(ssidie + 2, bi->SSID, ssid_len);
+ *ie_size = *ie_size + ssid_len - ssidie[1];
+ ssidie[1] = ssid_len;
+ }
+ return;
+ }
+ if (*(ssidie + 2) == '\0')
+ memcpy(ssidie + 2, bi->SSID, ssid_len);
+ return;
+}
+
+static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
+{
+ struct wl_ie *ie = wl_to_ie(cfg);
+ s32 err = 0;
+
+ if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
+ WL_ERR(("ei_stream crosses buffer boundary\n"));
+ return -ENOSPC;
+ }
+ memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
+ ie->offset += ie_size;
+
+ return err;
+}
+
+static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
+{
+ struct wl_ie *ie = wl_to_ie(cfg);
+ s32 err = 0;
+
+ if (unlikely(ie->offset > dst_size)) {
+ WL_ERR(("dst_size is not enough\n"));
+ return -ENOSPC;
+ }
+ memcpy(dst, &ie->buf[0], ie->offset);
+
+ return err;
+}
+
+static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
+{
+ struct wl_ie *ie = wl_to_ie(cfg);
+
+ return ie->offset;
+}
+
+static void wl_link_up(struct bcm_cfg80211 *cfg)
+{
+ cfg->link_up = true;
+}
+
+static void wl_link_down(struct bcm_cfg80211 *cfg)
+{
+ struct wl_connect_info *conn_info = wl_to_conn(cfg);
+
+ WL_DBG(("In\n"));
+ cfg->link_up = false;
+ conn_info->req_ie_len = 0;
+ conn_info->resp_ie_len = 0;
+}
+
+static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cfg->eq_lock, flags);
+ return flags;
+}
+
+static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
+{
+ spin_unlock_irqrestore(&cfg->eq_lock, flags);
+}
+
+static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
+{
+ spin_lock_init(&cfg->eq_lock);
+}
+
+static void wl_delay(u32 ms)
+{
+ if (in_atomic() || (ms < jiffies_to_msecs(1))) {
+ OSL_DELAY(ms*1000);
+ } else {
+ OSL_SLEEP(ms);
+ }
+}
+
+s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ struct ether_addr p2pif_addr;
+ struct ether_addr primary_mac;
+ if (!cfg->p2p)
+ return -1;
+ if (!p2p_is_on(cfg)) {
+ get_primary_mac(cfg, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
+ } else {
+ memcpy(p2pdev_addr->octet,
+ cfg->p2p->dev_addr.octet, ETHER_ADDR_LEN);
+ }
+
+
+ return 0;
+}
+s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
+{
+ struct bcm_cfg80211 *cfg;
+
+ cfg = g_bcm_cfg;
+
+ return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
+}
+
+s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
+{
+ struct bcm_cfg80211 *cfg;
+ cfg = g_bcm_cfg;
+
+ return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
+}
+
+s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
+{
+ struct bcm_cfg80211 *cfg;
+ cfg = g_bcm_cfg;
+
+ return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
+}
+
+s32 wl_cfg80211_channel_to_freq(u32 channel)
+{
+ int freq = 0;
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+ freq = ieee80211_channel_to_frequency(channel);
+#else
+ {
+ u16 band = 0;
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = NL80211_BAND_2GHZ;
+ else
+ band = NL80211_BAND_5GHZ;
+ freq = ieee80211_channel_to_frequency(channel, band);
+ }
+#endif
+ return freq;
+}
+
+
+#ifdef WLTDLS
+static s32
+wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data) {
+
+ struct net_device *ndev = NULL;
+ u32 reason = ntoh32(e->reason);
+ s8 *msg = NULL;
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ switch (reason) {
+ case WLC_E_TDLS_PEER_DISCOVERED :
+ msg = " TDLS PEER DISCOVERD ";
+ break;
+ case WLC_E_TDLS_PEER_CONNECTED :
+ if (cfg->tdls_mgmt_frame) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
+ cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+ cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
+ cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0,
+ GFP_ATOMIC);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
+ defined(WL_COMPAT_WIRELESS)
+ cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
+ cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
+ GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
+ cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, GFP_ATOMIC);
+
+#endif
+ }
+ msg = " TDLS PEER CONNECTED ";
+ break;
+ case WLC_E_TDLS_PEER_DISCONNECTED :
+ if (cfg->tdls_mgmt_frame) {
+ kfree(cfg->tdls_mgmt_frame);
+ cfg->tdls_mgmt_frame = NULL;
+ cfg->tdls_mgmt_freq = 0;
+ }
+ msg = "TDLS PEER DISCONNECTED ";
+ break;
+ }
+ if (msg) {
+ WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
+ (bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
+ }
+ return 0;
+
+}
+#endif /* WLTDLS */
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
+static s32
+wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
+ u32 peer_capability, bool initiator, const u8 *data, size_t len)
+#else
+static s32
+#if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
+wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
+ u32 peer_capability, const u8 *data, size_t len)
+#else
+wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
+ size_t len)
+#endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) */
+{
+ s32 ret = 0;
+#ifdef WLTDLS
+ struct bcm_cfg80211 *cfg;
+ tdls_wfd_ie_iovar_t info;
+ memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+ cfg = g_bcm_cfg;
+
+#if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
+ /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
+ * and that cuases build error
+ */
+ BCM_REFERENCE(peer_capability);
+#endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
+
+ switch (action_code) {
+ /* We need to set TDLS Wifi Display IE to firmware
+ * using tdls_wfd_ie iovar
+ */
+ case WLAN_TDLS_SET_PROBE_WFD_IE:
+ info.mode = TDLS_WFD_PROBE_IE_TX;
+ memcpy(&info.data, data, len);
+ info.length = len;
+ break;
+ case WLAN_TDLS_SET_SETUP_WFD_IE:
+ info.mode = TDLS_WFD_IE_TX;
+ memcpy(&info.data, data, len);
+ info.length = len;
+ break;
+ default:
+ WL_ERR(("Unsupported action code : %d\n", action_code));
+ goto out;
+ }
+
+ ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+
+ if (ret) {
+ WL_ERR(("tdls_wfd_ie error %d\n", ret));
+ }
+out:
+#endif /* WLTDLS */
+ return ret;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+static s32
+wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, enum nl80211_tdls_operation oper)
+#else
+static s32
+wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, enum nl80211_tdls_operation oper)
+#endif
+{
+ s32 ret = 0;
+#ifdef WLTDLS
+ struct bcm_cfg80211 *cfg;
+ tdls_iovar_t info;
+ cfg = g_bcm_cfg;
+ memset(&info, 0, sizeof(tdls_iovar_t));
+ if (peer) {
+ memcpy(&info.ea, peer, ETHER_ADDR_LEN);
+ } else {
+ return -1;
+ }
+ switch (oper) {
+ case NL80211_TDLS_DISCOVERY_REQ:
+ /* turn on TDLS */
+ ret = dhd_tdls_enable(dev, true, false, NULL);
+ if (ret < 0)
+ return ret;
+ /* If the discovery request is broadcast then we need to set
+ * info.mode to Tunneled Probe Request
+ */
+ if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
+ info.mode = TDLS_MANUAL_EP_WFD_TPQ;
+ }
+ else {
+ info.mode = TDLS_MANUAL_EP_DISCOVERY;
+ }
+ break;
+ case NL80211_TDLS_SETUP:
+ /* auto mode on */
+ ret = dhd_tdls_enable(dev, true, true, (struct ether_addr *)peer);
+ if (ret < 0)
+ return ret;
+ break;
+ case NL80211_TDLS_TEARDOWN:
+ info.mode = TDLS_MANUAL_EP_DELETE;
+ /* auto mode off */
+ ret = dhd_tdls_enable(dev, true, false, (struct ether_addr *)peer);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ WL_ERR(("Unsupported operation : %d\n", oper));
+ goto out;
+ }
+ if (info.mode) {
+ ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (ret) {
+ WL_ERR(("tdls_endpoint error %d\n", ret));
+ }
+ }
+out:
+#endif /* WLTDLS */
+ return ret;
+}
+#endif
+
+s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
+ enum wl_management_type type)
+{
+ struct bcm_cfg80211 *cfg;
+ struct net_device *ndev = NULL;
+ struct ether_addr primary_mac;
+ s32 ret = 0;
+ s32 bssidx = 0;
+ s32 pktflag = 0;
+ cfg = g_bcm_cfg;
+
+ if (wl_get_drv_status(cfg, AP_CREATING, net)) {
+ /* Vendor IEs should be set to FW
+ * after SoftAP interface is brought up
+ */
+ goto exit;
+ } else if (wl_get_drv_status(cfg, AP_CREATED, net)) {
+ ndev = net;
+ bssidx = 0;
+ } else if (cfg->p2p) {
+ net = ndev_to_wlc_ndev(net, cfg);
+ if (!cfg->p2p->on) {
+ get_primary_mac(cfg, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac, &cfg->p2p->dev_addr,
+ &cfg->p2p->int_addr);
+ /* In case of p2p_listen command, supplicant send remain_on_channel
+ * without turning on P2P
+ */
+
+ p2p_on(cfg) = true;
+ ret = wl_cfgp2p_enable_discovery(cfg, net, NULL, 0);
+
+ if (unlikely(ret)) {
+ goto exit;
+ }
+ }
+ if (net == bcmcfg_to_prmry_ndev(cfg)) {
+ ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
+ bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
+ } else {
+ ndev = net;
+ bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
+ }
+ }
+ if (ndev != NULL) {
+ switch (type) {
+ case WL_BEACON:
+ pktflag = VNDR_IE_BEACON_FLAG;
+ break;
+ case WL_PROBE_RESP:
+ pktflag = VNDR_IE_PRBRSP_FLAG;
+ break;
+ case WL_ASSOC_RESP:
+ pktflag = VNDR_IE_ASSOCRSP_FLAG;
+ break;
+ }
+ if (pktflag)
+ ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev, bssidx, pktflag, buf, len);
+ }
+exit:
+ return ret;
+}
+
+#ifdef WL_SUPPORT_AUTO_CHANNEL
+static s32
+wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
+{
+ u32 val = 0;
+ s32 ret = BCME_ERROR;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ /* Disable mpc, to avoid automatic interface down. */
+ val = 0;
+
+ ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
+ sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
+ &cfg->ioctl_buf_sync);
+ if (ret < 0) {
+ WL_ERR(("set 'mpc' failed, error = %d\n", ret));
+ goto done;
+ }
+
+ /* Set interface up, explicitly. */
+ val = 1;
+
+ ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
+ if (ret < 0) {
+ WL_ERR(("set interface up failed, error = %d\n", ret));
+ goto done;
+ }
+
+ /* Stop all scan explicitly, till auto channel selection complete. */
+ wl_set_drv_status(cfg, SCANNING, ndev);
+ if (cfg->escan_info.ndev == NULL) {
+ ret = BCME_OK;
+ goto done;
+ }
+ ret = wl_notify_escan_complete(cfg, ndev, true, true);
+ if (ret < 0) {
+ WL_ERR(("set scan abort failed, error = %d\n", ret));
+ goto done;
+ }
+
+done:
+ return ret;
+}
+
+static bool
+wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
+{
+ bool valid = false;
+
+ if (ioctl_version != 1) {
+ if ((chanspec = wl_chspec_to_legacy(chanspec)) == INVCHANSPEC) {
+ return valid;
+ }
+ }
+
+ /* channel 1 to 14 */
+ if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
+ valid = true;
+ }
+ /* channel 36 to 48 */
+ else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
+ valid = true;
+ }
+ /* channel 149 to 161 */
+ else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
+ valid = true;
+ }
+ else {
+ valid = false;
+ WL_INFO(("invalid P2P chanspec, channel = %d, chanspec = %04x\n",
+ CHSPEC_CHANNEL(chanspec), chanspec));
+ }
+
+ return valid;
+}
+
+s32
+wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
+{
+ s32 ret = BCME_ERROR;
+ struct bcm_cfg80211 *cfg = NULL;
+ wl_uint32_list_t *list = NULL;
+ chanspec_t chanspec = 0;
+
+ memset(buf, 0, buflen);
+
+ cfg = g_bcm_cfg;
+ list = (wl_uint32_list_t *)buf;
+ list->count = htod32(WL_NUMCHANSPECS);
+
+ /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
+ chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
+ WL_CHANSPEC_CTL_SB_NONE);
+ chanspec = wl_chspec_host_to_driver(chanspec);
+
+ ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
+ sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
+ if (ret < 0) {
+ WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
+ }
+
+ return ret;
+}
+
+s32
+wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
+{
+ u32 channel = 0;
+ s32 ret = BCME_ERROR;
+ s32 i = 0;
+ s32 j = 0;
+ struct bcm_cfg80211 *cfg = NULL;
+ wl_uint32_list_t *list = NULL;
+ chanspec_t chanspec = 0;
+
+ memset(buf, 0, buflen);
+
+ cfg = g_bcm_cfg;
+ list = (wl_uint32_list_t *)buf;
+ list->count = htod32(WL_NUMCHANSPECS);
+
+ /* Restrict channels to 5GHz, 20MHz BW, no SB. */
+ chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
+ WL_CHANSPEC_CTL_SB_NONE);
+ chanspec = wl_chspec_host_to_driver(chanspec);
+
+ ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
+ sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
+ if (ret < 0) {
+ WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
+ goto done;
+ }
+
+ /* Skip DFS and inavlid P2P channel. */
+ for (i = 0, j = 0; i < dtoh32(list->count); i++) {
+ chanspec = (chanspec_t) dtoh32(list->element[i]);
+ channel = CHSPEC_CHANNEL(chanspec);
+
+ ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
+ if (ret < 0) {
+ WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
+ goto done;
+ }
+
+ if (CHANNEL_IS_RADAR(channel) ||
+ !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
+ continue;
+ } else {
+ list->element[j] = list->element[i];
+ }
+
+ j++;
+ }
+
+ list->count = j;
+
+done:
+ return ret;
+}
+
+static s32
+wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
+ int *channel)
+{
+ s32 ret = BCME_ERROR;
+ int chosen = 0;
+ int retry = 0;
+
+ /* Start auto channel selection scan. */
+ ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
+ if (ret < 0) {
+ WL_ERR(("can't start auto channel scan, error = %d\n", ret));
+ *channel = 0;
+ goto done;
+ }
+
+ /* Wait for auto channel selection, worst case possible delay is 5250ms. */
+ retry = CHAN_SEL_RETRY_COUNT;
+
+ while (retry--) {
+ OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
+
+ ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
+ false);
+ if ((ret == 0) && (dtoh32(chosen) != 0)) {
+ *channel = (u16)(chosen & 0x00FF);
+ WL_INFO(("selected channel = %d\n", *channel));
+ break;
+ }
+ WL_INFO(("attempt = %d, ret = %d, chosen = %d\n",
+ (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
+ }
+
+ if (retry <= 0) {
+ WL_ERR(("failure, auto channel selection timed out\n"));
+ *channel = 0;
+ ret = BCME_ERROR;
+ }
+
+done:
+ return ret;
+}
+
+static s32
+wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
+{
+ u32 val = 0;
+ s32 ret = BCME_ERROR;
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ /* Clear scan stop driver status. */
+ wl_clr_drv_status(cfg, SCANNING, ndev);
+
+ /* Enable mpc back to 1, irrespective of initial state. */
+ val = 1;
+
+ ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
+ sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
+ &cfg->ioctl_buf_sync);
+ if (ret < 0) {
+ WL_ERR(("set 'mpc' failed, error = %d\n", ret));
+ }
+
+ return ret;
+}
+
+s32
+wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
+{
+ int channel = 0;
+ s32 ret = BCME_ERROR;
+ u8 *buf = NULL;
+ char *pos = cmd;
+ struct bcm_cfg80211 *cfg = NULL;
+ struct net_device *ndev = NULL;
+
+ memset(cmd, 0, total_len);
+
+ buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
+ if (buf == NULL) {
+ WL_ERR(("failed to allocate chanspec buffer\n"));
+ return -ENOMEM;
+ }
+
+ /*
+ * Always use primary interface, irrespective of interface on which
+ * command came.
+ */
+ cfg = g_bcm_cfg;
+ ndev = bcmcfg_to_prmry_ndev(cfg);
+
+ /*
+ * Make sure that FW and driver are in right state to do auto channel
+ * selection scan.
+ */
+ ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
+ if (ret < 0) {
+ WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
+ goto done;
+ }
+
+ /* Best channel selection in 2.4GHz band. */
+ ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
+ if (ret < 0) {
+ WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
+ goto done;
+ }
+
+ ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
+ &channel);
+ if (ret < 0) {
+ WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
+ goto done;
+ }
+
+ if (CHANNEL_IS_2G(channel)) {
+ channel = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
+ } else {
+ WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
+ channel = 0;
+ }
+
+ sprintf(pos, "%04d ", channel);
+ pos += 5;
+
+ /* Best channel selection in 5GHz band. */
+ ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
+ if (ret < 0) {
+ WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
+ goto done;
+ }
+
+ ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
+ &channel);
+ if (ret < 0) {
+ WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
+ goto done;
+ }
+
+ if (CHANNEL_IS_5G(channel)) {
+ channel = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
+ } else {
+ WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
+ channel = 0;
+ }
+
+ sprintf(pos, "%04d ", channel);
+ pos += 5;
+
+ /* Set overall best channel same as 5GHz best channel. */
+ sprintf(pos, "%04d ", channel);
+ pos += 5;
+
+done:
+ if (NULL != buf) {
+ kfree(buf);
+ }
+
+ /* Restore FW and driver back to normal state. */
+ ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
+ if (ret < 0) {
+ WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
+ }
+
+ return (pos - cmd);
+}
+#endif /* WL_SUPPORT_AUTO_CHANNEL */
+
+static const struct rfkill_ops wl_rfkill_ops = {
+ .set_block = wl_rfkill_set
+};
+
+static int wl_rfkill_set(void *data, bool blocked)
+{
+ struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
+
+ WL_DBG(("Enter \n"));
+ WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
+
+ if (!cfg)
+ return -EINVAL;
+
+ cfg->rf_blocked = blocked;
+
+ return 0;
+}
+
+static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
+{
+ s32 err = 0;
+
+ WL_DBG(("Enter \n"));
+ if (!cfg)
+ return -EINVAL;
+ if (setup) {
+ cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
+ wl_cfg80211_get_parent_dev(),
+ RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
+
+ if (!cfg->rfkill) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ err = rfkill_register(cfg->rfkill);
+
+ if (err)
+ rfkill_destroy(cfg->rfkill);
+ } else {
+ if (!cfg->rfkill) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ rfkill_unregister(cfg->rfkill);
+ rfkill_destroy(cfg->rfkill);
+ }
+
+err_out:
+ return err;
+}
+
+#ifdef DEBUGFS_CFG80211
+/**
+* Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
+* to turn on SCAN and DBG log.
+* To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
+* To see current setting of debug level,
+* cat /sys/kernel/debug/dhd/debug_level
+*/
+static ssize_t
+wl_debuglevel_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
+ char *params, *token, *colon;
+ uint i, tokens, log_on = 0;
+ memset(tbuf, 0, sizeof(tbuf));
+ memset(sublog, 0, sizeof(sublog));
+ if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count)))
+ return -EFAULT;
+
+ params = &tbuf[0];
+ colon = strchr(params, '\n');
+ if (colon != NULL)
+ *colon = '\0';
+ while ((token = strsep(&params, " ")) != NULL) {
+ memset(sublog, 0, sizeof(sublog));
+ if (token == NULL || !*token)
+ break;
+ if (*token == '\0')
+ continue;
+ colon = strchr(token, ':');
+ if (colon != NULL) {
+ *colon = ' ';
+ }
+ tokens = sscanf(token, "%s %u", sublog, &log_on);
+ if (colon != NULL)
+ *colon = ':';
+
+ if (tokens == 2) {
+ for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
+ if (!strncmp(sublog, sublogname_map[i].sublogname,
+ strlen(sublogname_map[i].sublogname))) {
+ if (log_on)
+ wl_dbg_level |=
+ (sublogname_map[i].log_level);
+ else
+ wl_dbg_level &=
+ ~(sublogname_map[i].log_level);
+ }
+ }
+ } else
+ WL_ERR(("%s: can't parse '%s' as a "
+ "SUBMODULE:LEVEL (%d tokens)\n",
+ tbuf, token, tokens));
+
+
+ }
+ return count;
+}
+
+static ssize_t
+wl_debuglevel_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char *param;
+ char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
+ uint i;
+ memset(tbuf, 0, sizeof(tbuf));
+ param = &tbuf[0];
+ for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
+ param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
+ sublogname_map[i].sublogname,
+ (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
+ }
+ *param = '\n';
+ return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
+
+}
+static const struct file_operations fops_debuglevel = {
+ .open = NULL,
+ .write = wl_debuglevel_write,
+ .read = wl_debuglevel_read,
+ .owner = THIS_MODULE,
+ .llseek = NULL,
+};
+
+static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
+{
+ s32 err = 0;
+ struct dentry *_dentry;
+ if (!cfg)
+ return -EINVAL;
+ cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
+ if (cfg->debugfs == ERR_PTR(-ENODEV))
+ WL_ERR(("Debugfs is not enabled on this kernel\n"));
+ else
+ WL_ERR(("Can not create debugfs directory\n"));
+ cfg->debugfs = NULL;
+ goto exit;
+
+ }
+ _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
+ cfg->debugfs, cfg, &fops_debuglevel);
+ if (!_dentry || IS_ERR(_dentry)) {
+ WL_ERR(("failed to create debug_level debug file\n"));
+ wl_free_debugfs(cfg);
+ }
+exit:
+ return err;
+}
+static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
+{
+ if (!cfg)
+ return -EINVAL;
+ if (cfg->debugfs)
+ debugfs_remove_recursive(cfg->debugfs);
+ cfg->debugfs = NULL;
+ return 0;
+}
+#endif /* DEBUGFS_CFG80211 */
+
+struct device *wl_cfg80211_get_parent_dev(void)
+{
+ return cfg80211_parent_dev;
+}
+
+void wl_cfg80211_set_parent_dev(void *dev)
+{
+ cfg80211_parent_dev = dev;
+}
+
+static void wl_cfg80211_clear_parent_dev(void)
+{
+ cfg80211_parent_dev = NULL;
+}
+
+void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
+{
+ wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr", NULL,
+ 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
+ memcpy(mac->octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
+}
+static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ if (((dev_role == NL80211_IFTYPE_AP) &&
+ !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
+ ((dev_role == NL80211_IFTYPE_P2P_GO) &&
+ !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
+ {
+ WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
+ return false;
+ }
+ return true;
+}
+
+int wl_cfg80211_do_driver_init(struct net_device *net)
+{
+ struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
+
+ if (!cfg || !cfg->wdev)
+ return -EINVAL;
+
+#if !defined(P2PONEINT)
+ if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
+ return -1;
+#endif /* BCMDONGLEHOST */
+
+ return 0;
+}
+
+void wl_cfg80211_enable_trace(bool set, u32 level)
+{
+ if (set)
+ wl_dbg_level = level & WL_DBG_LEVEL;
+ else
+ wl_dbg_level |= (WL_DBG_LEVEL & level);
+}
+#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
+ 2, 0))
+static s32
+wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
+ bcm_struct_cfgdev *cfgdev, u64 cookie)
+{
+ /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
+ * is passed with CMD_FRAME. This callback is supposed to cancel
+ * the OFFCHANNEL Wait. Since we are already taking care of that
+ * with the tx_mgmt logic, do nothing here.
+ */
+
+ return 0;
+}
+#endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
+
+#ifdef WL11U
+bcm_tlv_t *
+wl_cfg80211_find_interworking_ie(u8 *parse, u32 len)
+{
+ bcm_tlv_t *ie;
+
+ while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) {
+ return (bcm_tlv_t *)ie;
+ }
+ return NULL;
+}
+
+
+static s32
+wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
+ uint8 ie_id, uint8 *data, uint8 data_len)
+{
+ s32 err = BCME_OK;
+ s32 buf_len;
+ s32 iecount;
+ ie_setbuf_t *ie_setbuf;
+
+ if (ie_id != DOT11_MNG_INTERWORKING_ID)
+ return BCME_UNSUPPORTED;
+
+ /* Validate the pktflag parameter */
+ if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
+ VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
+ VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
+ VNDR_IE_CUSTOM_FLAG))) {
+ WL_ERR(("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag));
+ return -1;
+ }
+
+ /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
+ pktflag = htod32(pktflag);
+
+ buf_len = sizeof(ie_setbuf_t) + data_len - 1;
+ ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
+
+ if (!ie_setbuf) {
+ WL_ERR(("Error allocating buffer for IE\n"));
+ return -ENOMEM;
+ }
+
+ if (cfg->iw_ie_len == data_len && !memcmp(cfg->iw_ie, data, data_len)) {
+ WL_ERR(("Previous IW IE is equals to current IE\n"));
+ err = BCME_OK;
+ goto exit;
+ }
+
+ strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
+ ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+ /* Buffer contains only 1 IE */
+ iecount = htod32(1);
+ memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
+ memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32));
+
+ /* Now, add the IE to the buffer */
+ ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id;
+
+ /* if already set with previous values, delete it first */
+ if (cfg->iw_ie_len != 0) {
+ WL_DBG(("Different IW_IE was already set. clear first\n"));
+
+ ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0;
+
+ err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+
+ if (err != BCME_OK)
+ goto exit;
+ }
+
+ ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
+ memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
+
+ err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+
+ if (err == BCME_OK) {
+ memcpy(cfg->iw_ie, data, data_len);
+ cfg->iw_ie_len = data_len;
+ cfg->wl11u = TRUE;
+
+ err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
+ }
+
+exit:
+ if (ie_setbuf)
+ kfree(ie_setbuf);
+ return err;
+}
+#endif /* WL11U */
+
+
+
+int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev)
+{
+ struct bcm_cfg80211 *cfg = NULL;
+ struct net_device *ndev = NULL;
+ unsigned long flags;
+ int clear_flag = 0;
+ int ret = 0;
+
+ WL_TRACE(("Enter\n"));
+
+ cfg = g_bcm_cfg;
+ if (!cfg)
+ return -EINVAL;
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
+#ifdef WL_CFG80211_P2P_DEV_IF
+ if (cfg->scan_request && cfg->scan_request->wdev == cfgdev) {
+#else
+ if (cfg->scan_request && cfg->scan_request->dev == cfgdev) {
+#endif
+ struct cfg80211_scan_info info = {
+ .aborted = true,
+ };
+
+ cfg80211_scan_done(cfg->scan_request, &info);
+ cfg->scan_request = NULL;
+ clear_flag = 1;
+ }
+ spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+
+ if (clear_flag)
+ wl_clr_drv_status(cfg, SCANNING, ndev);
+
+ return ret;
+}
+
+bool wl_cfg80211_is_vsdb_mode(void)
+{
+ return (g_bcm_cfg && g_bcm_cfg->vsdb_mode);
+}
+
+void* wl_cfg80211_get_dhdp()
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+
+ return cfg->pub;
+}
+
+bool wl_cfg80211_is_p2p_active(void)
+{
+ return (g_bcm_cfg && g_bcm_cfg->p2p);
+}
+
+static void wl_cfg80211_work_handler(struct work_struct * work)
+{
+ struct bcm_cfg80211 *cfg = NULL;
+ struct net_info *iter, *next;
+ s32 err = BCME_OK;
+ s32 pm = PM_FAST;
+
+ cfg = container_of(work, struct bcm_cfg80211, pm_enable_work.work);
+ WL_DBG(("Enter \n"));
+ if (cfg->pm_enable_work_on) {
+ cfg->pm_enable_work_on = false;
+ for_each_ndev(cfg, iter, next) {
+ /* p2p discovery iface ndev could be null */
+ if (iter->ndev) {
+ if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
+ (wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
+ wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
+ continue;
+ if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
+ &pm, sizeof(pm), true)) != 0) {
+ if (err == -ENODEV)
+ WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
+ else
+ WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
+ } else
+ wl_cfg80211_update_power_mode(iter->ndev);
+ }
+ }
+ }
+}
+
+u8
+wl_get_action_category(void *frame, u32 frame_len)
+{
+ u8 category;
+ u8 *ptr = (u8 *)frame;
+ if (frame == NULL)
+ return DOT11_ACTION_CAT_ERR_MASK;
+ if (frame_len < DOT11_ACTION_HDR_LEN)
+ return DOT11_ACTION_CAT_ERR_MASK;
+ category = ptr[DOT11_ACTION_CAT_OFF];
+ WL_INFO(("Action Category: %d\n", category));
+ return category;
+}
+
+int
+wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
+{
+ u8 *ptr = (u8 *)frame;
+ if (frame == NULL || ret_action == NULL)
+ return BCME_ERROR;
+ if (frame_len < DOT11_ACTION_HDR_LEN)
+ return BCME_ERROR;
+ if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
+ return BCME_ERROR;
+ *ret_action = ptr[DOT11_ACTION_ACT_OFF];
+ WL_INFO(("Public Action : %d\n", *ret_action));
+ return BCME_OK;
+}
+
+static int
+wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const struct ether_addr *bssid)
+{
+ s32 err;
+ wl_event_msg_t e;
+
+ bzero(&e, sizeof(e));
+ e.event_type = cpu_to_be32(WLC_E_ROAM);
+ memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
+ /* trigger the roam event handler */
+ WL_INFO(("Delayed roam to " MACDBG "\n", MAC2STRDBG((u8*)(bssid))));
+ err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
+
+ return err;
+}
+
+
+static s32
+wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len,
+ struct parsed_vndr_ies *vndr_ies)
+{
+ s32 err = BCME_OK;
+ vndr_ie_t *vndrie;
+ bcm_tlv_t *ie;
+ struct parsed_vndr_ie_info *parsed_info;
+ u32 count = 0;
+ s32 remained_len;
+
+ remained_len = (s32)len;
+ memset(vndr_ies, 0, sizeof(*vndr_ies));
+
+ WL_INFO(("---> len %d\n", len));
+ ie = (bcm_tlv_t *) parse;
+ if (!bcm_valid_tlv(ie, remained_len))
+ ie = NULL;
+ while (ie) {
+ if (count >= MAX_VNDR_IE_NUMBER)
+ break;
+ if (ie->id == DOT11_MNG_VS_ID) {
+ vndrie = (vndr_ie_t *) ie;
+ /* len should be bigger than OUI length + one data length at least */
+ if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
+ WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
+ __FUNCTION__, vndrie->len));
+ goto end;
+ }
+ /* if wpa or wme ie, do not add ie */
+ if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
+ ((vndrie->data[0] == WPA_OUI_TYPE) ||
+ (vndrie->data[0] == WME_OUI_TYPE))) {
+ CFGP2P_DBG(("Found WPA/WME oui. Do not add it\n"));
+ goto end;
+ }
+
+ parsed_info = &vndr_ies->ie_info[count++];
+
+ /* save vndr ie information */
+ parsed_info->ie_ptr = (char *)vndrie;
+ parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
+ memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
+ vndr_ies->count = count;
+
+ WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
+ parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
+ parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0],
+ parsed_info->ie_len));
+ }
+end:
+ ie = bcm_next_tlv(ie, &remained_len);
+ }
+ return err;
+}
+
+s32
+wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx)
+{
+ s32 index;
+ struct net_info *netinfo;
+ s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
+ VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
+
+ netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
+ if (!netinfo || !netinfo->wdev) {
+ WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
+ return -1;
+ }
+
+ WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx));
+ /* Clear the IEs set in the firmware so that host is in sync with firmware */
+ for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
+ if (wl_cfg80211_set_mgmt_vndr_ies(cfg, netinfo->ndev,
+ bssidx, vndrie_flag[index], NULL, 0) < 0)
+ WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
+ }
+
+ return 0;
+}
+
+s32
+wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
+{
+ struct net_info *iter, *next;
+
+ WL_DBG(("clear management vendor IEs \n"));
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+ 4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#endif
+ for_each_ndev(cfg, iter, next) {
+ wl_cfg80211_clear_per_bss_ies(cfg, iter->bssidx);
+ }
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+ 4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic pop")
+#endif
+ return 0;
+}
+
+#define WL_VNDR_IE_MAXLEN 2048
+static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
+int
+wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
+{
+ s32 ret = BCME_OK;
+ u8 *curr_ie_buf = NULL;
+ u8 *mgmt_ie_buf = NULL;
+ u32 mgmt_ie_buf_len = 0;
+ u32 *mgmt_ie_len = 0;
+ u32 del_add_ie_buf_len = 0;
+ u32 total_ie_buf_len = 0;
+ u32 parsed_ie_buf_len = 0;
+ struct parsed_vndr_ies old_vndr_ies;
+ struct parsed_vndr_ies new_vndr_ies;
+ s32 i;
+ u8 *ptr;
+ s32 remained_buf_len;
+ wl_bss_vndr_ies_t *ies = NULL;
+ struct net_info *netinfo;
+
+ WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
+ pktflag, bssidx, vndr_ie_len));
+
+ if (bssidx > WL_MAX_IFS) {
+ WL_ERR(("bssidx > supported concurrent Ifaces \n"));
+ return -EINVAL;
+ }
+
+ netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
+ if (!netinfo) {
+ WL_ERR(("net_info ptr is NULL \n"));
+ return -EINVAL;
+ }
+
+ /* Clear the global buffer */
+ memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
+ curr_ie_buf = g_mgmt_ie_buf;
+ ies = &netinfo->bss.ies;
+
+ switch (pktflag) {
+ case VNDR_IE_PRBRSP_FLAG :
+ mgmt_ie_buf = ies->probe_res_ie;
+ mgmt_ie_len = &ies->probe_res_ie_len;
+ mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
+ break;
+ case VNDR_IE_ASSOCRSP_FLAG :
+ mgmt_ie_buf = ies->assoc_res_ie;
+ mgmt_ie_len = &ies->assoc_res_ie_len;
+ mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
+ break;
+ case VNDR_IE_BEACON_FLAG :
+ mgmt_ie_buf = ies->beacon_ie;
+ mgmt_ie_len = &ies->beacon_ie_len;
+ mgmt_ie_buf_len = sizeof(ies->beacon_ie);
+ break;
+ case VNDR_IE_PRBREQ_FLAG :
+ mgmt_ie_buf = ies->probe_req_ie;
+ mgmt_ie_len = &ies->probe_req_ie_len;
+ mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
+ break;
+ case VNDR_IE_ASSOCREQ_FLAG :
+ mgmt_ie_buf = ies->assoc_req_ie;
+ mgmt_ie_len = &ies->assoc_req_ie_len;
+ mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
+ break;
+ default:
+ mgmt_ie_buf = NULL;
+ mgmt_ie_len = NULL;
+ WL_ERR(("not suitable packet type (%d)\n", pktflag));
+ return BCME_ERROR;
+ }
+
+ if (vndr_ie_len > mgmt_ie_buf_len) {
+ WL_ERR(("extra IE size too big\n"));
+ ret = -ENOMEM;
+ } else {
+ /* parse and save new vndr_ie in curr_ie_buff before comparing it */
+ if (vndr_ie && vndr_ie_len && curr_ie_buf) {
+ ptr = curr_ie_buf;
+/* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
+ * causes cascade of errors in other places, fix involves const casts there
+ */
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+ 4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#endif
+ if ((ret = wl_cfg80211_parse_vndr_ies((u8 *)vndr_ie,
+ vndr_ie_len, &new_vndr_ies)) < 0) {
+ WL_ERR(("parse vndr ie failed \n"));
+ goto exit;
+ }
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+ 4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic pop")
+#endif
+ for (i = 0; i < new_vndr_ies.count; i++) {
+ struct parsed_vndr_ie_info *vndrie_info =
+ &new_vndr_ies.ie_info[i];
+
+ if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
+ WL_ERR(("IE size is too big (%d > %d)\n",
+ parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
+ vndrie_info->ie_len);
+ parsed_ie_buf_len += vndrie_info->ie_len;
+ }
+ }
+
+ if (mgmt_ie_buf != NULL) {
+ if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
+ (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
+ WL_INFO(("Previous mgmt IE is equals to current IE"));
+ goto exit;
+ }
+
+ /* parse old vndr_ie */
+ if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
+ &old_vndr_ies)) < 0) {
+ WL_ERR(("parse vndr ie failed \n"));
+ goto exit;
+ }
+ /* make a command to delete old ie */
+ for (i = 0; i < old_vndr_ies.count; i++) {
+ struct parsed_vndr_ie_info *vndrie_info =
+ &old_vndr_ies.ie_info[i];
+
+ WL_INFO(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
+ vndrie_info->vndrie.id, vndrie_info->vndrie.len,
+ vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
+ vndrie_info->vndrie.oui[2]));
+
+ del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
+ pktflag, vndrie_info->vndrie.oui,
+ vndrie_info->vndrie.id,
+ vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
+ vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
+ "del");
+
+ curr_ie_buf += del_add_ie_buf_len;
+ total_ie_buf_len += del_add_ie_buf_len;
+ }
+ }
+
+ *mgmt_ie_len = 0;
+ /* Add if there is any extra IE */
+ if (mgmt_ie_buf && parsed_ie_buf_len) {
+ ptr = mgmt_ie_buf;
+
+ remained_buf_len = mgmt_ie_buf_len;
+
+ /* make a command to add new ie */
+ for (i = 0; i < new_vndr_ies.count; i++) {
+ struct parsed_vndr_ie_info *vndrie_info =
+ &new_vndr_ies.ie_info[i];
+
+ WL_INFO(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
+ vndrie_info->vndrie.id, vndrie_info->vndrie.len,
+ vndrie_info->ie_len - 2,
+ vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
+ vndrie_info->vndrie.oui[2]));
+
+ del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
+ pktflag, vndrie_info->vndrie.oui,
+ vndrie_info->vndrie.id,
+ vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
+ vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
+ "add");
+
+ /* verify remained buf size before copy data */
+ if (remained_buf_len >= vndrie_info->ie_len) {
+ remained_buf_len -= vndrie_info->ie_len;
+ } else {
+ WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
+ "found vndr ies # = %d(cur %d), remained len %d, "
+ "cur mgmt_ie_len %d, new ie len = %d\n",
+ pktflag, new_vndr_ies.count, i, remained_buf_len,
+ *mgmt_ie_len, vndrie_info->ie_len));
+ break;
+ }
+
+ /* save the parsed IE in cfg struct */
+ memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
+ vndrie_info->ie_len);
+ *mgmt_ie_len += vndrie_info->ie_len;
+ curr_ie_buf += del_add_ie_buf_len;
+ total_ie_buf_len += del_add_ie_buf_len;
+ }
+ }
+
+ if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
+ ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
+ total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
+ bssidx, &cfg->ioctl_buf_sync);
+ if (ret)
+ WL_ERR(("vndr ie set error : %d\n", ret));
+ }
+ }
+exit:
+
+return ret;
+}
+
+#ifdef WL_CFG80211_ACL
+static int
+wl_cfg80211_set_mac_acl(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ const struct cfg80211_acl_data *acl)
+{
+ int i;
+ int ret = 0;
+ int macnum = 0;
+ int macmode = MACLIST_MODE_DISABLED;
+ struct maclist *list;
+
+ /* get the MAC filter mode */
+ if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
+ macmode = MACLIST_MODE_ALLOW;
+ } else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
+ acl->n_acl_entries) {
+ macmode = MACLIST_MODE_DENY;
+ }
+
+ /* if acl == NULL, macmode is still disabled.. */
+ if (macmode == MACLIST_MODE_DISABLED) {
+ if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
+ WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
+
+ return ret;
+ }
+
+ macnum = acl->n_acl_entries;
+ if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
+ WL_ERR(("%s : invalid number of MAC address entries %d\n",
+ __FUNCTION__, macnum));
+ return -1;
+ }
+
+ /* allocate memory for the MAC list */
+ list = (struct maclist*)kmalloc(sizeof(int) +
+ sizeof(struct ether_addr) * macnum, GFP_KERNEL);
+ if (!list) {
+ WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__));
+ return -1;
+ }
+
+ /* prepare the MAC list */
+ list->count = htod32(macnum);
+ for (i = 0; i < macnum; i++) {
+ memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
+ }
+ /* set the list */
+ if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
+ WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
+
+ kfree(list);
+
+ return ret;
+}
+#endif /* WL_CFG80211_ACL */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
+int wl_chspec_chandef(chanspec_t chanspec,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+struct cfg80211_chan_def *chandef,
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
+ \
+ \
+ 0)))
+struct chan_info *chaninfo,
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
+struct wiphy *wiphy)
+{
+ uint16 freq = 0;
+ int chan_type;
+ int channel = 0;
+
+ if (!chandef) {
+ return -1;
+ }
+ channel = CHSPEC_CHANNEL(chanspec);
+
+ switch (CHSPEC_BW(chanspec)) {
+ case WL_CHANSPEC_BW_20:
+ chan_type = NL80211_CHAN_HT20;
+ break;
+ case WL_CHANSPEC_BW_40:
+ {
+ if (CHSPEC_SB_UPPER(chanspec)) {
+ channel += CH_10MHZ_APART;
+ } else {
+ channel -= CH_10MHZ_APART;
+ }
+ }
+ chan_type = NL80211_CHAN_HT40PLUS;
+ break;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
+ case WL_CHANSPEC_BW_80:
+ case WL_CHANSPEC_BW_8080:
+ {
+ uint16 sb = CHSPEC_CTL_SB(chanspec);
+
+ if (sb == WL_CHANSPEC_CTL_SB_LL) {
+ channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
+ } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
+ channel -= CH_10MHZ_APART;
+ } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
+ channel += CH_10MHZ_APART;
+ } else {
+ /* WL_CHANSPEC_CTL_SB_UU */
+ channel += (CH_10MHZ_APART + CH_20MHZ_APART);
+ }
+ }
+
+ chan_type = NL80211_CHAN_WIDTH_80P80;
+ break;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
+ default:
+ chan_type = NL80211_CHAN_HT20;
+ break;
+
+ }
+
+ if (CHSPEC_IS5G(chanspec))
+ freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
+ else
+ freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
+ cfg80211_chandef_create(chandef, ieee80211_get_channel(wiphy, freq), chan_type);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
+ \
+ \
+ 0)))
+ chaninfo->freq = freq;
+ chaninfo->chan_type = chan_type;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
+ return 0;
+}
+
+void
+wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
+ struct cfg80211_chan_def chandef;
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
+ \
+ \
+ 0)))
+ struct chan_info chaninfo;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
+
+ if (!wiphy) {
+ printk("wiphy is null\n");
+ return;
+ }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
+ if (wl_chspec_chandef(chanspec, &chandef, wiphy)) {
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
+ \
+ \
+ 0)))
+ if (wl_chspec_chandef(chanspec, &chaninfo, wiphy)) {
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
+
+ WL_ERR(("%s:chspec_chandef failed\n", __FUNCTION__));
+ return;
+ }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
+ cfg80211_ch_switch_notify(dev, &chandef);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
+ \
+ \
+ 0)))
+ cfg80211_ch_switch_notify(dev, chan_info.freq, chan_info.chan_type);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
+ return;
+}
+
+static s32
+wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+const wl_event_msg_t *e, void *data)
+{
+ int error = 0;
+ int chsp = 0;
+ struct net_device *ndev = NULL;
+ struct wiphy *wiphy = NULL;
+ chanspec_t chanspec;
+
+ WL_ERR(("%s\n", __FUNCTION__));
+ if (e->status)
+ return -1;
+ if (cfgdev) {
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+ wiphy = bcmcfg_to_wiphy(cfg);
+ error = wldev_iovar_getint(ndev, "chanspec", &chsp);
+ if (error)
+ return -1;
+ chanspec = wl_chspec_driver_to_host(chsp);
+ wl_cfg80211_ch_switch_notify(ndev, chanspec, wiphy);
+ } else {
+ WL_ERR(("%s:cfgdev is null\n", __FUNCTION__));
+ return -1;
+ }
+
+
+ return 0;
+}
+#else
+static s32
+wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+const wl_event_msg_t *e, void *data)
+{
+ WL_ERR(("%s:Not sup for kernel < 3.5\n", __FUNCTION__));
+ return 0;
+}
+#endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
+
+#ifdef WL_NAN
+int
+wl_cfg80211_nan_cmd_handler(struct net_device *ndev, char *cmd, int cmd_len)
+{
+ return wl_cfgnan_cmd_handler(ndev, g_bcm_cfg, cmd, cmd_len);
+}
+#endif /* WL_NAN */
+#if defined(WL_SUPPORT_AUTO_CHANNEL)
+int
+wl_cfg80211_set_spect(struct net_device *dev, int spect)
+{
+ struct bcm_cfg80211 *cfg = g_bcm_cfg;
+ int down = 1;
+ int up = 1;
+ int err = BCME_OK;
+
+ if (!wl_get_drv_status_all(cfg, CONNECTED)) {
+ err = wldev_ioctl(dev, WLC_DOWN, &down, sizeof(down), true);
+ if (err) {
+ WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
+ return err;
+ }
+
+ err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect), true);
+ if (err) {
+ WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
+ return err;
+ }
+
+ err = wldev_ioctl(dev, WLC_UP, &up, sizeof(up), true);
+ if (err) {
+ WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
+ return err;
+ }
+ }
+ return err;
+}
+
+int
+wl_cfg80211_get_sta_channel(struct net_device *dev)
+{
+ if (wl_get_drv_status(g_bcm_cfg, CONNECTED, dev)) {
+ return g_bcm_cfg->channel;
+ }
+ return BCME_OK;
+}
+#endif /* WL_SUPPORT_AUTO_CHANNEL */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
new file mode 100644
index 000000000000..5f363bfcb111
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -0,0 +1,1264 @@
+/*
+ * Linux cfg80211 driver
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfg80211.h 662786 2016-11-11 09:06:37Z $
+ */
+
+#ifndef _wl_cfg80211_h_
+#define _wl_cfg80211_h_
+
+#include <linux/wireless.h>
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <wlioctl.h>
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+#include <linux/rfkill.h>
+
+#include <wl_cfgp2p.h>
+
+struct wl_conf;
+struct wl_iface;
+struct bcm_cfg80211;
+struct wl_security;
+struct wl_ibss;
+
+
+#define htod32(i) (i)
+#define htod16(i) (i)
+#define dtoh32(i) (i)
+#define dtoh16(i) (i)
+#define htodchanspec(i) (i)
+#define dtohchanspec(i) (i)
+
+#define WL_DBG_NONE 0
+#define WL_DBG_P2P_ACTION (1 << 5)
+#define WL_DBG_TRACE (1 << 4)
+#define WL_DBG_SCAN (1 << 3)
+#define WL_DBG_DBG (1 << 2)
+#define WL_DBG_INFO (1 << 1)
+#define WL_DBG_ERR (1 << 0)
+
+/* 0 invalidates all debug messages. default is 1 */
+#define WL_DBG_LEVEL 0xFF
+
+#define CFG80211_ERROR_TEXT "CFG80211-ERROR) "
+
+#define MAX_WAIT_TIME 1500
+#define DNGL_FUNC(func, parameters) func parameters;
+
+#define PM_BLOCK 1
+#define PM_ENABLE 0
+
+#if defined(DHD_DEBUG)
+#define WL_ERR(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_ERR) { \
+ printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__); \
+ printk args; \
+ } \
+} while (0)
+#else /* defined(DHD_DEBUG) */
+#define WL_ERR(args) \
+do { \
+ if ((wl_dbg_level & WL_DBG_ERR) && net_ratelimit()) { \
+ printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__); \
+ printk args; \
+ } \
+} while (0)
+#endif /* defined(DHD_DEBUG) */
+
+#ifdef WL_INFO
+#undef WL_INFO
+#endif
+#define WL_INFO(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_INFO) { \
+ printk(KERN_INFO "CFG80211-INFO) %s : ", __func__); \
+ printk args; \
+ } \
+} while (0)
+#ifdef WL_SCAN
+#undef WL_SCAN
+#endif
+#define WL_SCAN(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_SCAN) { \
+ printk(KERN_INFO "CFG80211-SCAN) %s :", __func__); \
+ printk args; \
+ } \
+} while (0)
+#ifdef WL_TRACE
+#undef WL_TRACE
+#endif
+#define WL_TRACE(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_TRACE) { \
+ printk(KERN_INFO "CFG80211-TRACE) %s :", __func__); \
+ printk args; \
+ } \
+} while (0)
+#ifdef WL_TRACE_HW4
+#undef WL_TRACE_HW4
+#endif
+#define WL_TRACE_HW4 WL_TRACE
+#if (WL_DBG_LEVEL > 0)
+#define WL_DBG(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_DBG) { \
+ printk(KERN_DEBUG "CFG80211-DEBUG) %s :", __func__); \
+ printk args; \
+ } \
+} while (0)
+#else /* !(WL_DBG_LEVEL > 0) */
+#define WL_DBG(args)
+#endif /* (WL_DBG_LEVEL > 0) */
+#define WL_PNO(x)
+#define WL_SD(x)
+
+
+#define WL_SCAN_RETRY_MAX 3
+#define WL_NUM_PMKIDS_MAX MAXPMKID
+#define WL_SCAN_BUF_MAX (1024 * 8)
+#define WL_TLV_INFO_MAX 1500
+#define WL_SCAN_IE_LEN_MAX 2048
+#define WL_BSS_INFO_MAX 2048
+#define WL_ASSOC_INFO_MAX 512
+#define WL_IOCTL_LEN_MAX 2048
+#define WL_EXTRA_BUF_MAX 2048
+#define WL_SCAN_ERSULTS_LAST (WL_SCAN_RESULTS_NO_MEM+1)
+#define WL_AP_MAX 256
+#define WL_FILE_NAME_MAX 256
+#define WL_DWELL_TIME 200
+#define WL_MED_DWELL_TIME 400
+#define WL_MIN_DWELL_TIME 100
+#define WL_LONG_DWELL_TIME 1000
+#define IFACE_MAX_CNT 4
+#define WL_SCAN_CONNECT_DWELL_TIME_MS 200
+#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20
+#define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320
+#define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400
+#define WL_AF_TX_MAX_RETRY 5
+
+#define WL_AF_SEARCH_TIME_MAX 450
+#define WL_AF_TX_EXTRA_TIME_MAX 200
+
+#define WL_SCAN_TIMER_INTERVAL_MS 10000 /* Scan timeout */
+#define WL_CHANNEL_SYNC_RETRY 5
+#define WL_INVALID -1
+
+/* Bring down SCB Timeout to 20secs from 60secs default */
+#ifndef WL_SCB_TIMEOUT
+#define WL_SCB_TIMEOUT 20
+#endif
+
+/* SCAN_SUPPRESS timer values in ms */
+#define WL_SCAN_SUPPRESS_TIMEOUT 31000 /* default Framwork DHCP timeout is 30 sec */
+#define WL_SCAN_SUPPRESS_RETRY 3000
+
+#define WL_PM_ENABLE_TIMEOUT 10000
+
+/* cfg80211 wowlan definitions */
+#define WL_WOWLAN_MAX_PATTERNS 8
+#define WL_WOWLAN_MIN_PATTERN_LEN 1
+#define WL_WOWLAN_MAX_PATTERN_LEN 255
+#define WL_WOWLAN_PKT_FILTER_ID_FIRST 201
+#define WL_WOWLAN_PKT_FILTER_ID_LAST (WL_WOWLAN_PKT_FILTER_ID_FIRST + \
+ WL_WOWLAN_MAX_PATTERNS - 1)
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+#define strnicmp(str1, str2, len) strncasecmp((str1), (str2), (len))
+#define STA_INFO_BIT(info) (1ul << NL80211_STA_ ## info)
+#else
+#define STA_INFO_BIT(info) (STATION_ ## info)
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
+
+/* driver status */
+enum wl_status {
+ WL_STATUS_READY = 0,
+ WL_STATUS_SCANNING,
+ WL_STATUS_SCAN_ABORTING,
+ WL_STATUS_CONNECTING,
+ WL_STATUS_CONNECTED,
+ WL_STATUS_DISCONNECTING,
+ WL_STATUS_AP_CREATING,
+ WL_STATUS_AP_CREATED,
+ /* whole sending action frame procedure:
+ * includes a) 'finding common channel' for public action request frame
+ * and b) 'sending af via 'actframe' iovar'
+ */
+ WL_STATUS_SENDING_ACT_FRM,
+ /* find a peer to go to a common channel before sending public action req frame */
+ WL_STATUS_FINDING_COMMON_CHANNEL,
+ /* waiting for next af to sync time of supplicant.
+ * it includes SENDING_ACT_FRM and WAITING_NEXT_ACT_FRM_LISTEN
+ */
+ WL_STATUS_WAITING_NEXT_ACT_FRM,
+#ifdef WL_CFG80211_SYNC_GON
+ /* go to listen state to wait for next af after SENDING_ACT_FRM */
+ WL_STATUS_WAITING_NEXT_ACT_FRM_LISTEN,
+#endif /* WL_CFG80211_SYNC_GON */
+ /* it will be set when upper layer requests listen and succeed in setting listen mode.
+ * if set, other scan request can abort current listen state
+ */
+ WL_STATUS_REMAINING_ON_CHANNEL,
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ /* it's fake listen state to keep current scan state.
+ * it will be set when upper layer requests listen but scan is running. then just run
+ * a expire timer without actual listen state.
+ * if set, other scan request does not need to abort scan.
+ */
+ WL_STATUS_FAKE_REMAINING_ON_CHANNEL
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+};
+
+/* wi-fi mode */
+enum wl_mode {
+ WL_MODE_BSS,
+ WL_MODE_IBSS,
+ WL_MODE_AP
+};
+
+/* driver profile list */
+enum wl_prof_list {
+ WL_PROF_MODE,
+ WL_PROF_SSID,
+ WL_PROF_SEC,
+ WL_PROF_IBSS,
+ WL_PROF_BAND,
+ WL_PROF_CHAN,
+ WL_PROF_BSSID,
+ WL_PROF_ACT,
+ WL_PROF_BEACONINT,
+ WL_PROF_DTIMPERIOD
+};
+
+/* donlge escan state */
+enum wl_escan_state {
+ WL_ESCAN_STATE_IDLE,
+ WL_ESCAN_STATE_SCANING
+};
+/* fw downloading status */
+enum wl_fw_status {
+ WL_FW_LOADING_DONE,
+ WL_NVRAM_LOADING_DONE
+};
+
+enum wl_management_type {
+ WL_BEACON = 0x1,
+ WL_PROBE_RESP = 0x2,
+ WL_ASSOC_RESP = 0x4
+};
+
+enum wl_handler_del_type {
+ WL_HANDLER_NOTUSE,
+ WL_HANDLER_DEL,
+ WL_HANDLER_MAINTAIN,
+ WL_HANDLER_PEND
+};
+
+/* beacon / probe_response */
+struct beacon_proberesp {
+ __le64 timestamp;
+ __le16 beacon_int;
+ __le16 capab_info;
+ u8 variable[0];
+} __attribute__ ((packed));
+
+/* driver configuration */
+struct wl_conf {
+ u32 frag_threshold;
+ u32 rts_threshold;
+ u32 retry_short;
+ u32 retry_long;
+ s32 tx_power;
+ struct ieee80211_channel channel;
+};
+
+typedef s32(*EVENT_HANDLER) (struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data);
+
+/* bss inform structure for cfg80211 interface */
+struct wl_cfg80211_bss_info {
+ u16 band;
+ u16 channel;
+ s16 rssi;
+ u16 frame_len;
+ u8 frame_buf[1];
+};
+
+/* basic structure of scan request */
+struct wl_scan_req {
+ struct wlc_ssid ssid;
+};
+
+/* basic structure of information element */
+struct wl_ie {
+ u16 offset;
+ u8 buf[WL_TLV_INFO_MAX];
+};
+
+/* event queue for cfg80211 main event */
+struct wl_event_q {
+ struct list_head eq_list;
+ u32 etype;
+ wl_event_msg_t emsg;
+ s8 edata[1];
+};
+
+/* security information with currently associated ap */
+struct wl_security {
+ u32 wpa_versions;
+ u32 auth_type;
+ u32 cipher_pairwise;
+ u32 cipher_group;
+ u32 wpa_auth;
+ u32 auth_assoc_res_status;
+};
+
+/* ibss information for currently joined ibss network */
+struct wl_ibss {
+ u8 beacon_interval; /* in millisecond */
+ u8 atim; /* in millisecond */
+ s8 join_only;
+ u8 band;
+ u8 channel;
+};
+
+typedef struct wl_bss_vndr_ies {
+ u8 probe_req_ie[VNDR_IES_BUF_LEN];
+ u8 probe_res_ie[VNDR_IES_MAX_BUF_LEN];
+ u8 assoc_req_ie[VNDR_IES_BUF_LEN];
+ u8 assoc_res_ie[VNDR_IES_BUF_LEN];
+ u8 beacon_ie[VNDR_IES_MAX_BUF_LEN];
+ u32 probe_req_ie_len;
+ u32 probe_res_ie_len;
+ u32 assoc_req_ie_len;
+ u32 assoc_res_ie_len;
+ u32 beacon_ie_len;
+} wl_bss_vndr_ies_t;
+
+typedef struct wl_cfgbss {
+ u8 *wpa_ie;
+ u8 *rsn_ie;
+ u8 *wps_ie;
+ bool security_mode;
+ struct wl_bss_vndr_ies ies; /* Common for STA, P2P GC, GO, AP, P2P Disc Interface */
+} wl_cfgbss_t;
+
+/* cfg driver profile */
+struct wl_profile {
+ u32 mode;
+ s32 band;
+ u32 channel;
+ struct wlc_ssid ssid;
+ struct wl_security sec;
+ struct wl_ibss ibss;
+ u8 bssid[ETHER_ADDR_LEN];
+ u16 beacon_interval;
+ u8 dtim_period;
+ bool active;
+};
+
+struct net_info {
+ struct net_device *ndev;
+ struct wireless_dev *wdev;
+ struct wl_profile profile;
+ s32 mode;
+ s32 roam_off;
+ unsigned long sme_state;
+ bool pm_restore;
+ bool pm_block;
+ s32 pm;
+ s32 bssidx;
+ wl_cfgbss_t bss;
+ struct list_head list; /* list of all net_info structure */
+};
+
+#ifdef DHD_MAX_IFS
+#define WL_MAX_IFS DHD_MAX_IFS
+#else
+#define WL_MAX_IFS 16
+#endif
+
+/* association inform */
+#define MAX_REQ_LINE 1024
+struct wl_connect_info {
+ u8 req_ie[MAX_REQ_LINE];
+ s32 req_ie_len;
+ u8 resp_ie[MAX_REQ_LINE];
+ s32 resp_ie_len;
+};
+
+/* firmware /nvram downloading controller */
+struct wl_fw_ctrl {
+ const struct firmware *fw_entry;
+ unsigned long status;
+ u32 ptr;
+ s8 fw_name[WL_FILE_NAME_MAX];
+ s8 nvram_name[WL_FILE_NAME_MAX];
+};
+
+/* assoc ie length */
+struct wl_assoc_ielen {
+ u32 req_len;
+ u32 resp_len;
+};
+
+/* wpa2 pmk list */
+struct wl_pmk_list {
+ pmkid_list_t pmkids;
+ pmkid_t foo[MAXPMKID - 1];
+};
+
+
+#define ESCAN_BUF_SIZE (64 * 1024)
+
+struct escan_info {
+ u32 escan_state;
+#ifdef STATIC_WL_PRIV_STRUCT
+#ifndef CONFIG_DHD_USE_STATIC_BUF
+#error STATIC_WL_PRIV_STRUCT should be used with CONFIG_DHD_USE_STATIC_BUF
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+ u8 *escan_buf;
+#else
+ u8 escan_buf[ESCAN_BUF_SIZE];
+#endif /* STATIC_WL_PRIV_STRUCT */
+ struct wiphy *wiphy;
+ struct net_device *ndev;
+};
+
+#ifdef ESCAN_BUF_OVERFLOW_MGMT
+#define BUF_OVERFLOW_MGMT_COUNT 3
+typedef struct {
+ int RSSI;
+ int length;
+ struct ether_addr BSSID;
+} removal_element_t;
+#endif /* ESCAN_BUF_OVERFLOW_MGMT */
+
+struct ap_info {
+/* Structure to hold WPS, WPA IEs for a AP */
+ u8 probe_res_ie[VNDR_IES_MAX_BUF_LEN];
+ u8 beacon_ie[VNDR_IES_MAX_BUF_LEN];
+ u8 assoc_res_ie[VNDR_IES_MAX_BUF_LEN];
+ u32 probe_res_ie_len;
+ u32 beacon_ie_len;
+ u32 assoc_res_ie_len;
+ u8 *wpa_ie;
+ u8 *rsn_ie;
+ u8 *wps_ie;
+ bool security_mode;
+};
+
+struct sta_info {
+ /* Structure to hold WPS IE for a STA */
+ u8 probe_req_ie[VNDR_IES_BUF_LEN];
+ u8 assoc_req_ie[VNDR_IES_BUF_LEN];
+ u32 probe_req_ie_len;
+ u32 assoc_req_ie_len;
+};
+
+struct afx_hdl {
+ wl_af_params_t *pending_tx_act_frm;
+ struct ether_addr tx_dst_addr;
+ struct net_device *dev;
+ struct work_struct work;
+ u32 bssidx;
+ u32 retry;
+ s32 peer_chan;
+ s32 peer_listen_chan; /* search channel: configured by upper layer */
+ s32 my_listen_chan; /* listen chanel: extract it from prb req or gon req */
+ bool is_listen;
+ bool ack_recv;
+ bool is_active;
+};
+
+struct parsed_ies {
+ wpa_ie_fixed_t *wps_ie;
+ u32 wps_ie_len;
+ wpa_ie_fixed_t *wpa_ie;
+ u32 wpa_ie_len;
+ bcm_tlv_t *wpa2_ie;
+ u32 wpa2_ie_len;
+};
+
+
+#ifdef WL11U
+/* Max length of Interworking element */
+#define IW_IES_MAX_BUF_LEN 9
+#endif
+#define MAX_EVENT_BUF_NUM 16
+typedef struct wl_eventmsg_buf {
+ u16 num;
+ struct {
+ u16 type;
+ bool set;
+ } event [MAX_EVENT_BUF_NUM];
+} wl_eventmsg_buf_t;
+
+typedef struct wl_if_event_info {
+ bool valid;
+ int ifidx;
+ int bssidx;
+ uint8 mac[ETHER_ADDR_LEN];
+ char name[IFNAMSIZ+1];
+} wl_if_event_info;
+
+/* private data of cfg80211 interface */
+struct bcm_cfg80211 {
+ struct wireless_dev *wdev; /* representing cfg cfg80211 device */
+
+ struct wireless_dev *p2p_wdev; /* representing cfg cfg80211 device for P2P */
+ struct net_device *p2p_net; /* reference to p2p0 interface */
+
+ struct wl_conf *conf;
+ struct cfg80211_scan_request *scan_request; /* scan request object */
+ EVENT_HANDLER evt_handler[WLC_E_LAST];
+ struct list_head eq_list; /* used for event queue */
+ struct list_head net_list; /* used for struct net_info */
+ spinlock_t net_list_sync; /* to protect scan status (and others if needed) */
+ spinlock_t eq_lock; /* for event queue synchronization */
+ spinlock_t cfgdrv_lock; /* to protect scan status (and others if needed) */
+ struct completion act_frm_scan;
+ struct completion iface_disable;
+ struct completion wait_next_af;
+ struct mutex usr_sync; /* maily for up/down synchronization */
+ struct wl_scan_results *bss_list;
+ struct wl_scan_results *scan_results;
+
+ /* scan request object for internal purpose */
+ struct wl_scan_req *scan_req_int;
+ /* information element object for internal purpose */
+#if defined(STATIC_WL_PRIV_STRUCT)
+ struct wl_ie *ie;
+#else
+ struct wl_ie ie;
+#endif
+
+ /* association information container */
+#if defined(STATIC_WL_PRIV_STRUCT)
+ struct wl_connect_info *conn_info;
+#else
+ struct wl_connect_info conn_info;
+#endif
+#ifdef DEBUGFS_CFG80211
+ struct dentry *debugfs;
+#endif /* DEBUGFS_CFG80211 */
+ struct wl_pmk_list *pmk_list; /* wpa2 pmk list */
+ tsk_ctl_t event_tsk; /* task of main event handler thread */
+ void *pub;
+ u32 iface_cnt;
+ u32 channel; /* current channel */
+ u32 af_sent_channel; /* channel action frame is sent */
+ /* next af subtype to cancel the remained dwell time in rx process */
+ u8 next_af_subtype;
+#ifdef WL_CFG80211_SYNC_GON
+ ulong af_tx_sent_jiffies;
+#endif /* WL_CFG80211_SYNC_GON */
+ struct escan_info escan_info; /* escan information */
+ bool active_scan; /* current scan mode */
+ bool ibss_starter; /* indicates this sta is ibss starter */
+ bool link_up; /* link/connection up flag */
+
+ /* indicate whether chip to support power save mode */
+ bool pwr_save;
+ bool roam_on; /* on/off switch for self-roaming */
+ bool scan_tried; /* indicates if first scan attempted */
+ bool wlfc_on;
+ bool vsdb_mode;
+ bool roamoff_on_concurrent;
+ u8 *ioctl_buf; /* ioctl buffer */
+ struct mutex ioctl_buf_sync;
+ u8 *escan_ioctl_buf;
+ u8 *extra_buf; /* maily to grab assoc information */
+ struct dentry *debugfsdir;
+ struct rfkill *rfkill;
+ bool rf_blocked;
+ struct ieee80211_channel remain_on_chan;
+ enum nl80211_channel_type remain_on_chan_type;
+ u64 send_action_id;
+ u64 last_roc_id;
+ wait_queue_head_t netif_change_event;
+ wl_if_event_info if_event_info;
+ struct completion send_af_done;
+ struct afx_hdl *afx_hdl;
+ struct p2p_info *p2p;
+ bool p2p_supported;
+ void *btcoex_info;
+ struct timer_list scan_timeout; /* Timer for catch scan event timeout */
+ s32(*state_notifier) (struct bcm_cfg80211 *cfg,
+ struct net_info *_net_info, enum wl_status state, bool set);
+ unsigned long interrested_state;
+ wlc_ssid_t hostapd_ssid;
+#ifdef WL11U
+ bool wl11u;
+ u8 iw_ie[IW_IES_MAX_BUF_LEN];
+ u32 iw_ie_len;
+#endif /* WL11U */
+ bool sched_scan_running; /* scheduled scan req status */
+#ifdef WL_SCHED_SCAN
+ struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */
+#endif /* WL_SCHED_SCAN */
+ bool scan_suppressed;
+ struct timer_list scan_supp_timer;
+ struct work_struct wlan_work;
+ struct mutex event_sync; /* maily for up/down synchronization */
+ bool disable_roam_event;
+ bool pm_enable_work_on;
+ struct delayed_work pm_enable_work;
+ vndr_ie_setbuf_t *ibss_vsie; /* keep the VSIE for IBSS */
+ int ibss_vsie_len;
+#ifdef WL_RELMCAST
+ u32 rmc_event_pid;
+ u32 rmc_event_seq;
+#endif /* WL_RELMCAST */
+ bool roam_offload;
+ bcm_struct_cfgdev *bss_cfgdev; /* For DUAL STA/STA+AP */
+ s32 cfgdev_bssidx;
+ bool bss_pending_op; /* indicate where there is a pending IF operation */
+#ifdef WLTDLS
+ u8 *tdls_mgmt_frame;
+ u32 tdls_mgmt_frame_len;
+ s32 tdls_mgmt_freq;
+#endif /* WLTDLS */
+ bool nan_running;
+ bool need_wait_afrx;
+ struct ether_addr last_roamed_addr;
+};
+
+
+static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
+{
+ return bss = bss ?
+ (struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info;
+}
+
+static inline void
+wl_probe_wdev_all(struct bcm_cfg80211 *cfg)
+{
+ struct net_info *_net_info, *next;
+ unsigned long int flags;
+ int idx = 0;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ WL_ERR(("%s: net_list[%d] bssidx: %d, "
+ "ndev: %p, wdev: %p \n", __FUNCTION__,
+ idx++, _net_info->bssidx,
+ _net_info->ndev, _net_info->wdev));
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return;
+}
+
+static inline struct net_info *
+wl_get_netinfo_by_bssidx(struct bcm_cfg80211 *cfg, s32 bssidx)
+{
+ struct net_info *_net_info, *next, *info = NULL;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if ((bssidx >= 0) && (_net_info->bssidx == bssidx)) {
+ info = _net_info;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return info;
+}
+
+static inline void
+wl_dealloc_netinfo_by_wdev(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev)
+{
+ struct net_info *_net_info, *next;
+ unsigned long int flags;
+
+#ifdef DHD_IFDEBUG
+ WL_ERR(("dealloc_netinfo enter wdev=%p \n", wdev));
+#endif
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (wdev && (_net_info->wdev == wdev)) {
+ wl_cfgbss_t *bss = &_net_info->bss;
+
+ kfree(bss->wpa_ie);
+ bss->wpa_ie = NULL;
+ kfree(bss->rsn_ie);
+ bss->rsn_ie = NULL;
+ kfree(bss->wps_ie);
+ bss->wps_ie = NULL;
+ list_del(&_net_info->list);
+ cfg->iface_cnt--;
+ kfree(_net_info);
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+#ifdef DHD_IFDEBUG
+ WL_ERR(("dealloc_netinfo exit iface_cnt=%d \n", cfg->iface_cnt));
+#endif
+}
+
+static inline s32
+wl_alloc_netinfo(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ struct wireless_dev * wdev, s32 mode, bool pm_block, u8 bssidx)
+{
+ struct net_info *_net_info;
+ s32 err = 0;
+ unsigned long int flags;
+
+#ifdef DHD_IFDEBUG
+ WL_ERR(("alloc_netinfo enter bssidx=%d wdev=%p ndev=%p\n", bssidx, wdev, ndev));
+#endif
+ /* Check whether there is any duplicate entry for the
+ * same bssidx *
+ */
+ if ((_net_info = wl_get_netinfo_by_bssidx(cfg, bssidx))) {
+ /* We have a duplicate entry for the same bssidx
+ * already present which shouldn't have been the case.
+ * Attempt recovery.
+ */
+ WL_ERR(("Duplicate entry for bssidx=%d present\n", bssidx));
+ wl_probe_wdev_all(cfg);
+#ifdef DHD_DEBUG
+ ASSERT(0);
+#endif /* DHD_DEBUG */
+ WL_ERR(("Removing the Dup entry for bssidx=%d \n", bssidx));
+ wl_dealloc_netinfo_by_wdev(cfg, _net_info->wdev);
+ }
+ if (cfg->iface_cnt == IFACE_MAX_CNT) {
+ WL_ERR(("Max interfaces (%d) reached.\n", IFACE_MAX_CNT));
+ return -ENOMEM;
+ }
+ _net_info = kzalloc(sizeof(struct net_info), GFP_KERNEL);
+ if (!_net_info) {
+ WL_ERR(("Insufficient memory in the system.\n"));
+ err = -ENOMEM;
+ }
+ else {
+ _net_info->mode = mode;
+ _net_info->ndev = ndev;
+ _net_info->wdev = wdev;
+ _net_info->pm_restore = 0;
+ _net_info->pm = 0;
+ _net_info->pm_block = pm_block;
+ _net_info->roam_off = WL_INVALID;
+ _net_info->bssidx = bssidx;
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ cfg->iface_cnt++;
+ list_add(&_net_info->list, &cfg->net_list);
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ }
+ return err;
+}
+
+static inline void
+wl_delete_all_netinfo(struct bcm_cfg80211 *cfg)
+{
+ struct net_info *_net_info, *next;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ wl_cfgbss_t *bss = &_net_info->bss;
+
+ kfree(bss->wpa_ie);
+ bss->wpa_ie = NULL;
+ kfree(bss->rsn_ie);
+ bss->rsn_ie = NULL;
+ kfree(bss->wps_ie);
+ bss->wps_ie = NULL;
+ list_del(&_net_info->list);
+ if (_net_info->wdev)
+ kfree(_net_info->wdev);
+ kfree(_net_info);
+ }
+ cfg->iface_cnt = 0;
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+}
+static inline u32
+wl_get_status_all(struct bcm_cfg80211 *cfg, s32 status)
+
+{
+ struct net_info *_net_info, *next;
+ u32 cnt = 0;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (_net_info->ndev &&
+ test_bit(status, &_net_info->sme_state))
+ cnt++;
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return cnt;
+}
+static inline void
+wl_set_status_all(struct bcm_cfg80211 *cfg, s32 status, u32 op)
+{
+ struct net_info *_net_info, *next;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ switch (op) {
+ case 1:
+ return; /* set all status is not allowed */
+ case 2:
+ clear_bit(status, &_net_info->sme_state);
+ if (cfg->state_notifier &&
+ test_bit(status, &(cfg->interrested_state)))
+ cfg->state_notifier(cfg, _net_info, status, false);
+ break;
+ case 4:
+ return; /* change all status is not allowed */
+ default:
+ return; /* unknown operation */
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+}
+static inline void
+wl_set_status_by_netdev(struct bcm_cfg80211 *cfg, s32 status,
+ struct net_device *ndev, u32 op)
+{
+ struct net_info *_net_info, *next;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (ndev && (_net_info->ndev == ndev)) {
+ switch (op) {
+ case 1:
+ /*
+ * Release the spinlock before calling notifier. Else there
+ * will be nested calls
+ */
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ set_bit(status, &_net_info->sme_state);
+ if (cfg->state_notifier &&
+ test_bit(status, &(cfg->interrested_state)))
+ cfg->state_notifier(cfg, _net_info, status, true);
+ return;
+ case 2:
+ /*
+ * Release the spinlock before calling notifier. Else there
+ * will be nested calls
+ */
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ clear_bit(status, &_net_info->sme_state);
+ if (cfg->state_notifier &&
+ test_bit(status, &(cfg->interrested_state)))
+ cfg->state_notifier(cfg, _net_info, status, false);
+ return;
+ case 4:
+ change_bit(status, &_net_info->sme_state);
+ break;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+}
+
+static inline u32
+wl_get_status_by_netdev(struct bcm_cfg80211 *cfg, s32 status,
+ struct net_device *ndev)
+{
+ struct net_info *_net_info, *next;
+ u32 stat = 0;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (ndev && (_net_info->ndev == ndev)) {
+ stat = test_bit(status, &_net_info->sme_state);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return stat;
+}
+
+static inline wl_cfgbss_t *
+wl_get_cfgbss_by_wdev(struct bcm_cfg80211 *cfg,
+ struct wireless_dev *wdev)
+{
+ struct net_info *_net_info, *next;
+ wl_cfgbss_t *bss = NULL;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (wdev && (_net_info->wdev == wdev)) {
+ bss = &_net_info->bss;
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return bss;
+}
+
+static inline s32
+wl_get_mode_by_netdev(struct bcm_cfg80211 *cfg, struct net_device *ndev)
+{
+ struct net_info *_net_info, *next;
+ s32 mode = -1;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (ndev && (_net_info->ndev == ndev)) {
+ mode = _net_info->mode;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return mode;
+}
+
+
+static inline void
+wl_set_mode_by_netdev(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ s32 mode)
+{
+ struct net_info *_net_info, *next;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (ndev && (_net_info->ndev == ndev))
+ _net_info->mode = mode;
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+}
+
+static inline struct wl_profile *
+wl_get_profile_by_netdev(struct bcm_cfg80211 *cfg, struct net_device *ndev)
+{
+ struct net_info *_net_info, *next;
+ struct wl_profile *prof = NULL;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (ndev && (_net_info->ndev == ndev)) {
+ prof = &_net_info->profile;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return prof;
+}
+
+static inline struct net_info *
+wl_get_netinfo_by_netdev(struct bcm_cfg80211 *cfg, struct net_device *ndev)
+{
+ struct net_info *_net_info, *next, *info = NULL;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (ndev && (_net_info->ndev == ndev)) {
+ info = _net_info;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return info;
+}
+
+static inline s32
+wl_get_bssidx_by_wdev(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev)
+{
+ struct net_info *_net_info, *next;
+ s32 bssidx = -1;
+ unsigned long int flags;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (_net_info->wdev && (_net_info->wdev == wdev)) {
+ bssidx = _net_info->bssidx;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return bssidx;
+}
+
+static inline struct wireless_dev *
+wl_get_wdev_by_bssidx(struct bcm_cfg80211 *cfg, s32 bssidx)
+{
+ struct net_info *_net_info, *next;
+ struct wireless_dev *wdev = NULL;
+ unsigned long int flags;
+
+ if (bssidx < 0)
+ return NULL;
+
+ spin_lock_irqsave(&cfg->net_list_sync, flags);
+ list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
+ if (_net_info->bssidx == bssidx) {
+ wdev = _net_info->wdev;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cfg->net_list_sync, flags);
+ return wdev;
+}
+
+#define is_p2p_group_iface(wdev) (((wdev->iftype == NL80211_IFTYPE_P2P_GO) || \
+ (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) ? 1 : 0)
+#define bcmcfg_to_wiphy(cfg) (cfg->wdev->wiphy)
+#define bcmcfg_to_prmry_ndev(cfg) (cfg->wdev->netdev)
+#define bcmcfg_to_prmry_wdev(cfg) (cfg->wdev)
+#define bcmcfg_to_p2p_wdev(cfg) (cfg->p2p_wdev)
+#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr))
+#define ndev_to_wdev(ndev) (ndev->ieee80211_ptr)
+#define wdev_to_ndev(wdev) (wdev->netdev)
+
+#if defined(WL_ENABLE_P2P_IF)
+#define ndev_to_wlc_ndev(ndev, cfg) ((ndev == cfg->p2p_net) ? \
+ bcmcfg_to_prmry_ndev(cfg) : ndev)
+#else
+#define ndev_to_wlc_ndev(ndev, cfg) (ndev)
+#endif /* WL_ENABLE_P2P_IF */
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#define wdev_to_wlc_ndev(wdev, cfg) \
+ ((wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) ? \
+ bcmcfg_to_prmry_ndev(cfg) : wdev_to_ndev(wdev))
+#define cfgdev_to_wlc_ndev(cfgdev, cfg) (cfgdev ? wdev_to_wlc_ndev(cfgdev, cfg) : NULL)
+#define bcmcfg_to_prmry_cfgdev(cfgdev, cfg) bcmcfg_to_prmry_wdev(cfg)
+#elif defined(WL_ENABLE_P2P_IF)
+#define cfgdev_to_wlc_ndev(cfgdev, cfg) ndev_to_wlc_ndev(cfgdev, cfg)
+#define bcmcfg_to_prmry_cfgdev(cfgdev, cfg) bcmcfg_to_prmry_ndev(cfg)
+#else
+#define cfgdev_to_wlc_ndev(cfgdev, cfg) (cfgdev)
+#define bcmcfg_to_prmry_cfgdev(cfgdev, cfg) (cfgdev)
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#define ndev_to_cfgdev(ndev) ndev_to_wdev(ndev)
+#define discover_cfgdev(cfgdev, cfg) (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE)
+#else
+#define ndev_to_cfgdev(ndev) (ndev)
+#define discover_cfgdev(cfgdev, cfg) (cfgdev == cfg->p2p_net)
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#define scan_req_match(cfg) (((cfg) && (cfg->scan_request) && \
+ (cfg->scan_request->wdev == cfg->p2p_wdev)) ? true : false)
+#elif defined(WL_ENABLE_P2P_IF)
+#define scan_req_match(cfg) (((cfg) && (cfg->scan_request) && \
+ (cfg->scan_request->dev == cfg->p2p_net)) ? true : false)
+#else
+#define scan_req_match(cfg) (((cfg) && p2p_is_on(cfg) && p2p_scan(cfg)) ? \
+ true : false)
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+#define scan_req_iftype(req) (req->dev->ieee80211_ptr->iftype)
+#else
+#define scan_req_iftype(req) (req->wdev->iftype)
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) */
+
+#define wl_to_sr(w) (w->scan_req_int)
+#if defined(STATIC_WL_PRIV_STRUCT)
+#define wl_to_ie(w) (w->ie)
+#define wl_to_conn(w) (w->conn_info)
+#else
+#define wl_to_ie(w) (&w->ie)
+#define wl_to_conn(w) (&w->conn_info)
+#endif
+#define wiphy_from_scan(w) (w->escan_info.wiphy)
+#define wl_get_drv_status_all(cfg, stat) \
+ (wl_get_status_all(cfg, WL_STATUS_ ## stat))
+#define wl_get_drv_status(cfg, stat, ndev) \
+ (wl_get_status_by_netdev(cfg, WL_STATUS_ ## stat, ndev))
+#define wl_set_drv_status(cfg, stat, ndev) \
+ (wl_set_status_by_netdev(cfg, WL_STATUS_ ## stat, ndev, 1))
+#define wl_clr_drv_status(cfg, stat, ndev) \
+ (wl_set_status_by_netdev(cfg, WL_STATUS_ ## stat, ndev, 2))
+#define wl_clr_drv_status_all(cfg, stat) \
+ (wl_set_status_all(cfg, WL_STATUS_ ## stat, 2))
+#define wl_chg_drv_status(cfg, stat, ndev) \
+ (wl_set_status_by_netdev(cfg, WL_STATUS_ ## stat, ndev, 4))
+
+#define for_each_bss(list, bss, __i) \
+ for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
+
+#define for_each_ndev(cfg, iter, next) \
+ list_for_each_entry_safe(iter, next, &cfg->net_list, list)
+
+
+/* In case of WPS from wpa_supplicant, pairwise siute and group suite is 0.
+ * In addtion to that, wpa_version is WPA_VERSION_1
+ */
+#define is_wps_conn(_sme) \
+ ((wl_cfgp2p_find_wpsie((u8 *)_sme->ie, _sme->ie_len) != NULL) && \
+ (!_sme->crypto.n_ciphers_pairwise) && \
+ (!_sme->crypto.cipher_group))
+extern s32 wl_cfg80211_attach(struct net_device *ndev, void *context);
+extern s32 wl_cfg80211_attach_post(struct net_device *ndev);
+extern void wl_cfg80211_detach(void *para);
+
+extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e,
+ void *data);
+void wl_cfg80211_set_parent_dev(void *dev);
+struct device *wl_cfg80211_get_parent_dev(void);
+
+/* clear IEs */
+extern s32 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg);
+extern s32 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx);
+
+extern s32 wl_cfg80211_up(void *para);
+extern s32 wl_cfg80211_down(void *para);
+extern s32 wl_cfg80211_notify_ifadd(int ifidx, char *name, uint8 *mac, uint8 bssidx);
+extern s32 wl_cfg80211_notify_ifdel(int ifidx, char *name, uint8 *mac, uint8 bssidx);
+extern s32 wl_cfg80211_notify_ifchange(int ifidx, char *name, uint8 *mac, uint8 bssidx);
+extern struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
+ uint8 *mac, uint8 bssidx, char *dngl_name);
+extern int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev);
+extern int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev);
+extern int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev);
+extern bool wl_cfg80211_is_vsdb_mode(void);
+extern void* wl_cfg80211_get_dhdp(void);
+extern bool wl_cfg80211_is_p2p_active(void);
+extern void wl_cfg80211_dbg_level(u32 level);
+extern s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
+extern s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len);
+extern s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len);
+extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
+ enum wl_management_type type);
+extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len);
+
+/* btcoex functions */
+void* wl_cfg80211_btcoex_init(struct net_device *ndev);
+void wl_cfg80211_btcoex_deinit(void);
+
+#ifdef WL_SUPPORT_AUTO_CHANNEL
+#define CHANSPEC_BUF_SIZE 1024
+#define CHAN_SEL_IOCTL_DELAY 300
+#define CHAN_SEL_RETRY_COUNT 15
+#define CHANNEL_IS_RADAR(channel) (((channel & WL_CHAN_RADAR) || \
+ (channel & WL_CHAN_PASSIVE)) ? true : false)
+#define CHANNEL_IS_2G(channel) (((channel >= 1) && (channel <= 14)) ? \
+ true : false)
+#define CHANNEL_IS_5G(channel) (((channel >= 36) && (channel <= 165)) ? \
+ true : false)
+extern s32 wl_cfg80211_get_best_channels(struct net_device *dev, char* command,
+ int total_len);
+#endif /* WL_SUPPORT_AUTO_CHANNEL */
+
+extern int wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n);
+extern int wl_cfg80211_hex_str_to_bin(unsigned char *data, int dlen, char *str);
+extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
+extern s32 wl_mode_to_nl80211_iftype(s32 mode);
+int wl_cfg80211_do_driver_init(struct net_device *net);
+void wl_cfg80211_enable_trace(bool set, u32 level);
+extern s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify);
+extern s32 wl_cfg80211_if_is_group_owner(void);
+extern chanspec_t wl_chspec_host_to_driver(chanspec_t chanspec);
+extern chanspec_t wl_ch_host_to_driver(u16 channel);
+extern s32 wl_set_tx_power(struct net_device *dev,
+ enum nl80211_tx_power_setting type, s32 dbm);
+extern s32 wl_get_tx_power(struct net_device *dev, s32 *dbm);
+extern s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add);
+extern void wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev);
+extern void wl_cfg80211_add_to_eventbuffer(wl_eventmsg_buf_t *ev, u16 event, bool set);
+extern s32 wl_cfg80211_apply_eventbuffer(struct net_device *ndev,
+ struct bcm_cfg80211 *cfg, wl_eventmsg_buf_t *ev);
+extern void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac);
+extern void wl_cfg80211_update_power_mode(struct net_device *dev);
+extern void wl_terminate_event_handler(void);
+extern s32
+wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen);
+extern s32
+wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen);
+extern int
+wl_cfg80211_set_spect(struct net_device *dev, int spect);
+extern int
+wl_cfg80211_get_sta_channel(struct net_device *dev);
+
+#define SCAN_BUF_CNT 2
+#define SCAN_BUF_NEXT 1
+#define WL_SCANTYPE_LEGACY 0x1
+#define WL_SCANTYPE_P2P 0x2
+#define wl_escan_set_sync_id(a, b) ((a) = htod16(0x1234))
+#define wl_escan_set_type(a, b)
+#define wl_escan_get_buf(a, b) ((wl_scan_results_t *) (a)->escan_info.escan_buf)
+#define wl_escan_check_sync_id(a, b, c) 0
+#define wl_escan_print_sync_id(a, b, c)
+#define wl_escan_increment_sync_id(a, b)
+#define wl_escan_init_sync_id(a)
+
+extern void wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len);
+extern s32 wl_cfg80211_ibss_vsie_delete(struct net_device *dev);
+#ifdef WL_RELMCAST
+extern void wl_cfg80211_set_rmc_pid(int pid);
+#endif /* WL_RELMCAST */
+
+extern int wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg,
+ struct net_device *ndev, s32 bssidx, s32 pktflag,
+ const u8 *vndr_ie, u32 vndr_ie_len);
+
+/* Action frame specific functions */
+extern u8 wl_get_action_category(void *frame, u32 frame_len);
+extern int wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action);
+
+#ifdef WL_SUPPORT_ACS
+#define ACS_MSRMNT_DELAY 1000 /* dump_obss delay in ms */
+#define IOCTL_RETRY_COUNT 5
+#define CHAN_NOISE_DUMMY -80
+#define OBSS_TOKEN_IDX 15
+#define IBSS_TOKEN_IDX 15
+#define TX_TOKEN_IDX 14
+#define CTG_TOKEN_IDX 13
+#define PKT_TOKEN_IDX 15
+#define IDLE_TOKEN_IDX 12
+#endif /* WL_SUPPORT_ACS */
+extern int wl_cfg80211_enable_roam_offload(struct net_device *dev, bool enable);
+#ifdef WL_NAN
+extern int wl_cfg80211_nan_cmd_handler(struct net_device *ndev, char *cmd,
+ int cmd_len);
+#endif /* WL_NAN */
+
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+struct net_device *wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg);
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+
+extern int wl_cfg80211_get_ioctl_version(void);
+
+#if defined(WL_VIRTUAL_APSTA)
+extern int wl_cfg80211_interface_create(struct net_device *dev, char *name);
+extern int wl_cfg80211_interface_delete(struct net_device *dev, char *name);
+#endif /* defined (WL_VIRTUAL_APSTA) */
+
+#ifdef WL_CFG80211_P2P_DEV_IF
+extern void wl_cfg80211_del_p2p_wdev(void);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+#endif /* _wl_cfg80211_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg_btcoex.c b/drivers/net/wireless/bcmdhd/wl_cfg_btcoex.c
new file mode 100644
index 000000000000..886c2c49dacc
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_cfg_btcoex.c
@@ -0,0 +1,545 @@
+/*
+ * Linux cfg80211 driver - Dongle Host Driver (DHD) related
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfg_btcoex.c 638311 2016-05-17 09:20:23Z $
+ */
+
+#include <net/rtnetlink.h>
+
+#include <bcmutils.h>
+#include <wldev_common.h>
+#include <wl_cfg80211.h>
+#include <dhd_cfg80211.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhdioctl.h>
+#include <wlioctl.h>
+
+#ifdef PKT_FILTER_SUPPORT
+extern uint dhd_pkt_filter_enable;
+extern uint dhd_master_mode;
+extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
+#endif
+
+struct btcoex_info {
+ struct timer_list timer;
+ u32 timer_ms;
+ u32 timer_on;
+ u32 ts_dhcp_start; /* ms ts ecord time stats */
+ u32 ts_dhcp_ok; /* ms ts ecord time stats */
+ bool dhcp_done; /* flag, indicates that host done with
+ * dhcp before t1/t2 expiration
+ */
+ s32 bt_state;
+ struct work_struct work;
+ struct net_device *dev;
+};
+
+static struct btcoex_info *btcoex_info_loc = NULL;
+
+/* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */
+
+/* use New SCO/eSCO smart YG suppression */
+#define BT_DHCP_eSCO_FIX
+/* this flag boost wifi pkt priority to max, caution: -not fair to sco */
+#define BT_DHCP_USE_FLAGS
+/* T1 start SCO/ESCo priority suppression */
+#define BT_DHCP_OPPR_WIN_TIME 2500
+/* T2 turn off SCO/SCO supperesion is (timeout) */
+#define BT_DHCP_FLAG_FORCE_TIME 5500
+
+enum wl_cfg80211_btcoex_status {
+ BT_DHCP_IDLE,
+ BT_DHCP_START,
+ BT_DHCP_OPPR_WIN,
+ BT_DHCP_FLAG_FORCE_TIMEOUT
+};
+
+/*
+ * get named driver variable to uint register value and return error indication
+ * calling example: dev_wlc_intvar_get_reg(dev, "btc_params",66, &reg_value)
+ */
+static int
+dev_wlc_intvar_get_reg(struct net_device *dev, char *name,
+ uint reg, int *retval)
+{
+ union {
+ char buf[WLC_IOCTL_SMLEN];
+ int val;
+ } var;
+ int error;
+
+ bcm_mkiovar(name, (char *)(&reg), sizeof(reg),
+ (char *)(&var), sizeof(var.buf));
+ error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false);
+
+ *retval = dtoh32(var.val);
+ return (error);
+}
+
+static int
+dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len)
+{
+ char ioctlbuf_local[WLC_IOCTL_SMLEN];
+
+ bcm_mkiovar(name, buf, len, ioctlbuf_local, sizeof(ioctlbuf_local));
+
+ return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf_local, sizeof(ioctlbuf_local), true));
+}
+/*
+get named driver variable to uint register value and return error indication
+calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value)
+*/
+static int
+dev_wlc_intvar_set_reg(struct net_device *dev, char *name, char *addr, char * val)
+{
+ char reg_addr[8];
+
+ memset(reg_addr, 0, sizeof(reg_addr));
+ memcpy((char *)&reg_addr[0], (char *)addr, 4);
+ memcpy((char *)&reg_addr[4], (char *)val, 4);
+
+ return (dev_wlc_bufvar_set(dev, name, (char *)&reg_addr[0], sizeof(reg_addr)));
+}
+
+static bool btcoex_is_sco_active(struct net_device *dev)
+{
+ int ioc_res = 0;
+ bool res = FALSE;
+ int sco_id_cnt = 0;
+ int param27;
+ int i;
+
+ for (i = 0; i < 12; i++) {
+
+ ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, &param27);
+
+ WL_TRACE(("sample[%d], btc params: 27:%x\n", i, param27));
+
+ if (ioc_res < 0) {
+ WL_ERR(("ioc read btc params error\n"));
+ break;
+ }
+
+ if ((param27 & 0x6) == 2) { /* count both sco & esco */
+ sco_id_cnt++;
+ }
+
+ if (sco_id_cnt > 2) {
+ WL_TRACE(("sco/esco detected, pkt id_cnt:%d samples:%d\n",
+ sco_id_cnt, i));
+ res = TRUE;
+ break;
+ }
+
+ OSL_SLEEP(5);
+ }
+
+ return res;
+}
+
+#if defined(BT_DHCP_eSCO_FIX)
+/* Enhanced BT COEX settings for eSCO compatibility during DHCP window */
+static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
+{
+ static bool saved_status = FALSE;
+
+ char buf_reg50va_dhcp_on[8] =
+ { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
+ char buf_reg51va_dhcp_on[8] =
+ { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
+ char buf_reg64va_dhcp_on[8] =
+ { 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
+ char buf_reg65va_dhcp_on[8] =
+ { 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
+ char buf_reg71va_dhcp_on[8] =
+ { 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
+ uint32 regaddr;
+ static uint32 saved_reg50;
+ static uint32 saved_reg51;
+ static uint32 saved_reg64;
+ static uint32 saved_reg65;
+ static uint32 saved_reg71;
+
+ if (trump_sco) {
+ /* this should reduce eSCO agressive retransmit
+ * w/o breaking it
+ */
+
+ /* 1st save current */
+ WL_TRACE(("Do new SCO/eSCO coex algo {save &"
+ "override}\n"));
+ if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
+ saved_status = TRUE;
+ WL_TRACE(("saved bt_params[50,51,64,65,71]:"
+ "0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ saved_reg50, saved_reg51,
+ saved_reg64, saved_reg65, saved_reg71));
+ } else {
+ WL_ERR((":%s: save btc_params failed\n",
+ __FUNCTION__));
+ saved_status = FALSE;
+ return -1;
+ }
+
+ WL_TRACE(("override with [50,51,64,65,71]:"
+ "0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ *(u32 *)(buf_reg50va_dhcp_on+4),
+ *(u32 *)(buf_reg51va_dhcp_on+4),
+ *(u32 *)(buf_reg64va_dhcp_on+4),
+ *(u32 *)(buf_reg65va_dhcp_on+4),
+ *(u32 *)(buf_reg71va_dhcp_on+4)));
+
+ dev_wlc_bufvar_set(dev, "btc_params",
+ (char *)&buf_reg50va_dhcp_on[0], 8);
+ dev_wlc_bufvar_set(dev, "btc_params",
+ (char *)&buf_reg51va_dhcp_on[0], 8);
+ dev_wlc_bufvar_set(dev, "btc_params",
+ (char *)&buf_reg64va_dhcp_on[0], 8);
+ dev_wlc_bufvar_set(dev, "btc_params",
+ (char *)&buf_reg65va_dhcp_on[0], 8);
+ dev_wlc_bufvar_set(dev, "btc_params",
+ (char *)&buf_reg71va_dhcp_on[0], 8);
+
+ saved_status = TRUE;
+ } else if (saved_status) {
+ /* restore previously saved bt params */
+ WL_TRACE(("Do new SCO/eSCO coex algo {save &"
+ "override}\n"));
+
+ regaddr = 50;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg50);
+ regaddr = 51;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg51);
+ regaddr = 64;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg64);
+ regaddr = 65;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg65);
+ regaddr = 71;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg71);
+
+ WL_TRACE(("restore bt_params[50,51,64,65,71]:"
+ "0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ saved_reg50, saved_reg51, saved_reg64,
+ saved_reg65, saved_reg71));
+
+ saved_status = FALSE;
+ } else {
+ WL_ERR((":%s att to restore not saved BTCOEX params\n",
+ __FUNCTION__));
+ return -1;
+ }
+ return 0;
+}
+#endif /* BT_DHCP_eSCO_FIX */
+
+static void
+wl_cfg80211_bt_setflag(struct net_device *dev, bool set)
+{
+#if defined(BT_DHCP_USE_FLAGS)
+ char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
+ char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
+#endif
+
+
+#if defined(BT_DHCP_eSCO_FIX)
+ /* set = 1, save & turn on 0 - off & restore prev settings */
+ set_btc_esco_params(dev, set);
+#endif
+
+#if defined(BT_DHCP_USE_FLAGS)
+ WL_TRACE(("WI-FI priority boost via bt flags, set:%d\n", set));
+ if (set == TRUE)
+ /* Forcing bt_flag7 */
+ dev_wlc_bufvar_set(dev, "btc_flags",
+ (char *)&buf_flag7_dhcp_on[0],
+ sizeof(buf_flag7_dhcp_on));
+ else
+ /* Restoring default bt flag7 */
+ dev_wlc_bufvar_set(dev, "btc_flags",
+ (char *)&buf_flag7_default[0],
+ sizeof(buf_flag7_default));
+#endif
+}
+
+static void wl_cfg80211_bt_timerfunc(ulong data)
+{
+ struct btcoex_info *bt_local = (struct btcoex_info *)data;
+ WL_TRACE(("Enter\n"));
+ bt_local->timer_on = 0;
+ schedule_work(&bt_local->work);
+}
+
+static void wl_cfg80211_bt_handler(struct work_struct *work)
+{
+ struct btcoex_info *btcx_inf;
+
+ btcx_inf = container_of(work, struct btcoex_info, work);
+
+ if (btcx_inf->timer_on) {
+ btcx_inf->timer_on = 0;
+ del_timer_sync(&btcx_inf->timer);
+ }
+
+ switch (btcx_inf->bt_state) {
+ case BT_DHCP_START:
+ /* DHCP started
+ * provide OPPORTUNITY window to get DHCP address
+ */
+ WL_TRACE(("bt_dhcp stm: started \n"));
+
+ btcx_inf->bt_state = BT_DHCP_OPPR_WIN;
+ mod_timer(&btcx_inf->timer,
+ jiffies + msecs_to_jiffies(BT_DHCP_OPPR_WIN_TIME));
+ btcx_inf->timer_on = 1;
+ break;
+
+ case BT_DHCP_OPPR_WIN:
+ if (btcx_inf->dhcp_done) {
+ WL_TRACE(("DHCP Done before T1 expiration\n"));
+ goto btc_coex_idle;
+ }
+
+ /* DHCP is not over yet, start lowering BT priority
+ * enforce btc_params + flags if necessary
+ */
+ WL_TRACE(("DHCP T1:%d expired\n", BT_DHCP_OPPR_WIN_TIME));
+ if (btcx_inf->dev)
+ wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE);
+ btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
+ mod_timer(&btcx_inf->timer,
+ jiffies + msecs_to_jiffies(BT_DHCP_FLAG_FORCE_TIME));
+ btcx_inf->timer_on = 1;
+ break;
+
+ case BT_DHCP_FLAG_FORCE_TIMEOUT:
+ if (btcx_inf->dhcp_done) {
+ WL_TRACE(("DHCP Done before T2 expiration\n"));
+ } else {
+ /* Noo dhcp during T1+T2, restore BT priority */
+ WL_TRACE(("DHCP wait interval T2:%d msec expired\n",
+ BT_DHCP_FLAG_FORCE_TIME));
+ }
+
+ /* Restoring default bt priority */
+ if (btcx_inf->dev)
+ wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
+btc_coex_idle:
+ btcx_inf->bt_state = BT_DHCP_IDLE;
+ btcx_inf->timer_on = 0;
+ break;
+
+ default:
+ WL_ERR(("error g_status=%d !!!\n", btcx_inf->bt_state));
+ if (btcx_inf->dev)
+ wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
+ btcx_inf->bt_state = BT_DHCP_IDLE;
+ btcx_inf->timer_on = 0;
+ break;
+ }
+
+ net_os_wake_unlock(btcx_inf->dev);
+}
+
+void* wl_cfg80211_btcoex_init(struct net_device *ndev)
+{
+ struct btcoex_info *btco_inf = NULL;
+
+ btco_inf = kmalloc(sizeof(struct btcoex_info), GFP_KERNEL);
+ if (!btco_inf)
+ return NULL;
+
+ btco_inf->bt_state = BT_DHCP_IDLE;
+ btco_inf->ts_dhcp_start = 0;
+ btco_inf->ts_dhcp_ok = 0;
+ /* Set up timer for BT */
+ btco_inf->timer_ms = 10;
+ init_timer(&btco_inf->timer);
+ btco_inf->timer.data = (ulong)btco_inf;
+ btco_inf->timer.function = wl_cfg80211_bt_timerfunc;
+
+ btco_inf->dev = ndev;
+
+ INIT_WORK(&btco_inf->work, wl_cfg80211_bt_handler);
+
+ btcoex_info_loc = btco_inf;
+ return btco_inf;
+}
+
+void wl_cfg80211_btcoex_deinit()
+{
+ if (!btcoex_info_loc)
+ return;
+
+ if (btcoex_info_loc->timer_on) {
+ btcoex_info_loc->timer_on = 0;
+ del_timer_sync(&btcoex_info_loc->timer);
+ }
+
+ cancel_work_sync(&btcoex_info_loc->work);
+
+ kfree(btcoex_info_loc);
+}
+
+int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *command)
+{
+
+ struct btcoex_info *btco_inf = btcoex_info_loc;
+ char powermode_val = 0;
+ char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
+ char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
+ char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
+
+ uint32 regaddr;
+ static uint32 saved_reg66;
+ static uint32 saved_reg41;
+ static uint32 saved_reg68;
+ static bool saved_status = FALSE;
+
+ char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
+
+ /* Figure out powermode 1 or o command */
+ strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1);
+
+ if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
+ WL_TRACE_HW4(("DHCP session starts\n"));
+
+
+#ifdef PKT_FILTER_SUPPORT
+ dhd->dhcp_in_progress = 1;
+
+ if (dhd->early_suspended) {
+ WL_TRACE_HW4(("DHCP in progressing , disable packet filter!!!\n"));
+ dhd_enable_packet_filter(0, dhd);
+ }
+#endif
+
+ /* Retrieve and saved orig regs value */
+ if ((saved_status == FALSE) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
+ saved_status = TRUE;
+ WL_TRACE(("Saved 0x%x 0x%x 0x%x\n",
+ saved_reg66, saved_reg41, saved_reg68));
+
+ /* Disable PM mode during dhpc session */
+
+ /* Disable PM mode during dhpc session */
+ /* Start BT timer only for SCO connection */
+ if (btcoex_is_sco_active(dev)) {
+ /* btc_params 66 */
+ dev_wlc_bufvar_set(dev, "btc_params",
+ (char *)&buf_reg66va_dhcp_on[0],
+ sizeof(buf_reg66va_dhcp_on));
+ /* btc_params 41 0x33 */
+ dev_wlc_bufvar_set(dev, "btc_params",
+ (char *)&buf_reg41va_dhcp_on[0],
+ sizeof(buf_reg41va_dhcp_on));
+ /* btc_params 68 0x190 */
+ dev_wlc_bufvar_set(dev, "btc_params",
+ (char *)&buf_reg68va_dhcp_on[0],
+ sizeof(buf_reg68va_dhcp_on));
+ saved_status = TRUE;
+
+ btco_inf->bt_state = BT_DHCP_START;
+ btco_inf->timer_on = 1;
+ mod_timer(&btco_inf->timer, btco_inf->timer.expires);
+ WL_TRACE(("enable BT DHCP Timer\n"));
+ }
+ }
+ else if (saved_status == TRUE) {
+ WL_ERR(("was called w/o DHCP OFF. Continue\n"));
+ }
+ }
+ else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) {
+
+
+
+#ifdef PKT_FILTER_SUPPORT
+ dhd->dhcp_in_progress = 0;
+ WL_TRACE_HW4(("DHCP is complete \n"));
+
+ /* Enable packet filtering */
+ if (dhd->early_suspended) {
+ WL_TRACE_HW4(("DHCP is complete , enable packet filter!!!\n"));
+ dhd_enable_packet_filter(1, dhd);
+ }
+#endif /* PKT_FILTER_SUPPORT */
+
+ /* Restoring PM mode */
+
+ /* Stop any bt timer because DHCP session is done */
+ WL_TRACE(("disable BT DHCP Timer\n"));
+ if (btco_inf->timer_on) {
+ btco_inf->timer_on = 0;
+ del_timer_sync(&btco_inf->timer);
+
+ if (btco_inf->bt_state != BT_DHCP_IDLE) {
+ /* need to restore original btc flags & extra btc params */
+ WL_TRACE(("bt->bt_state:%d\n", btco_inf->bt_state));
+ /* wake up btcoex thread to restore btlags+params */
+ schedule_work(&btco_inf->work);
+ }
+ }
+
+ /* Restoring btc_flag paramter anyway */
+ if (saved_status == TRUE)
+ dev_wlc_bufvar_set(dev, "btc_flags",
+ (char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
+
+ /* Restore original values */
+ if (saved_status == TRUE) {
+ regaddr = 66;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg66);
+ regaddr = 41;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg41);
+ regaddr = 68;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg68);
+
+ WL_TRACE(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n",
+ saved_reg66, saved_reg41, saved_reg68));
+ }
+ saved_status = FALSE;
+
+ }
+ else {
+ WL_ERR(("Unkwown yet power setting, ignored\n"));
+ }
+
+ snprintf(command, 3, "OK");
+
+ return (strlen("OK"));
+}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
new file mode 100644
index 000000000000..8c3787b97a24
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -0,0 +1,2539 @@
+/*
+ * Linux cfgp2p driver
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfgp2p.c 662965 2016-11-24 03:53:15Z $
+ *
+ */
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+#include <proto/802.11.h>
+#include <net/rtnetlink.h>
+
+#include <wl_cfg80211.h>
+#include <wl_cfgp2p.h>
+#include <wldev_common.h>
+#include <wl_android.h>
+
+#if defined(P2PONEINT)
+#include <dngl_stats.h>
+#include <dhd.h>
+#endif
+
+static s8 scanparambuf[WLC_IOCTL_SMLEN];
+static bool
+wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
+
+static s32 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ struct wireless_dev *wdev, bool notify);
+
+#ifdef P2PONEINT
+void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
+chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
+s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val);
+int wl_cfgp2p_if_open(struct net_device *net);
+int wl_cfgp2p_if_stop(struct net_device *net);
+#endif
+
+#if defined(WL_ENABLE_P2P_IF)
+static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
+static int wl_cfgp2p_if_open(struct net_device *net);
+static int wl_cfgp2p_if_stop(struct net_device *net);
+
+static const struct net_device_ops wl_cfgp2p_if_ops = {
+ .ndo_open = wl_cfgp2p_if_open,
+ .ndo_stop = wl_cfgp2p_if_stop,
+ .ndo_do_ioctl = wl_cfgp2p_do_ioctl,
+#ifndef P2PONEINT
+ .ndo_start_xmit = wl_cfgp2p_start_xmit,
+#endif
+};
+#endif /* WL_ENABLE_P2P_IF */
+
+
+bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len)
+{
+ wifi_p2p_pub_act_frame_t *pact_frm;
+
+ if (frame == NULL)
+ return false;
+ pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
+ if (frame_len < sizeof(wifi_p2p_pub_act_frame_t) -1)
+ return false;
+
+ if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
+ pact_frm->action == P2P_PUB_AF_ACTION &&
+ pact_frm->oui_type == P2P_VER &&
+ memcmp(pact_frm->oui, P2P_OUI, sizeof(pact_frm->oui)) == 0) {
+ return true;
+ }
+
+ return false;
+}
+
+bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len)
+{
+ wifi_p2p_action_frame_t *act_frm;
+
+ if (frame == NULL)
+ return false;
+ act_frm = (wifi_p2p_action_frame_t *)frame;
+ if (frame_len < sizeof(wifi_p2p_action_frame_t) -1)
+ return false;
+
+ if (act_frm->category == P2P_AF_CATEGORY &&
+ act_frm->type == P2P_VER &&
+ memcmp(act_frm->OUI, P2P_OUI, DOT11_OUI_LEN) == 0) {
+ return true;
+ }
+
+ return false;
+}
+
+#define GAS_RESP_LEN 2
+#define DOUBLE_TLV_BODY_OFF 4
+#define GAS_RESP_OFFSET 4
+#define GAS_CRESP_OFFSET 5
+
+bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len)
+{
+ bcm_tlv_t *ie = (bcm_tlv_t *)data;
+ u8 *frame = NULL;
+ u16 id, flen;
+
+ /* Skipped first ANQP Element, if frame has anqp elemnt */
+ ie = bcm_parse_tlvs(ie, (int)len, DOT11_MNG_ADVERTISEMENT_ID);
+
+ if (ie == NULL)
+ return false;
+
+ frame = (uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
+ id = ((u16) (((frame)[1] << 8) | (frame)[0]));
+ flen = ((u16) (((frame)[3] << 8) | (frame)[2]));
+
+ /* If the contents match the OUI and the type */
+ if (flen >= WFA_OUI_LEN + 1 &&
+ id == P2PSD_GAS_NQP_INFOID &&
+ !bcmp(&frame[DOUBLE_TLV_BODY_OFF], (const uint8*)WFA_OUI, WFA_OUI_LEN) &&
+ subtype == frame[DOUBLE_TLV_BODY_OFF+WFA_OUI_LEN]) {
+ return true;
+ }
+
+ return false;
+}
+
+bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len)
+{
+
+ wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
+
+ if (frame == NULL)
+ return false;
+
+ sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
+ if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1))
+ return false;
+ if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
+ return false;
+
+ if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
+ sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP ||
+ sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ ||
+ sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
+ return true;
+ else
+ return false;
+}
+
+bool wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len)
+{
+
+ wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
+
+ if (frame == NULL)
+ return false;
+
+ sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
+ if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1))
+ return false;
+ if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
+ return false;
+
+ if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ)
+ return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE,
+ (u8 *)sd_act_frm->query_data,
+ frame_len);
+ else
+ return false;
+}
+
+void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel)
+{
+ wifi_p2p_pub_act_frame_t *pact_frm;
+ wifi_p2p_action_frame_t *act_frm;
+ wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
+ if (!frame || frame_len <= 2)
+ return;
+
+ if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
+ pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
+ switch (pact_frm->subtype) {
+ case P2P_PAF_GON_REQ:
+ CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_PAF_GON_RSP:
+ CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_PAF_GON_CONF:
+ CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_PAF_INVITE_REQ:
+ CFGP2P_ACTION(("%s P2P Invitation Request Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_PAF_INVITE_RSP:
+ CFGP2P_ACTION(("%s P2P Invitation Response Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_PAF_DEVDIS_REQ:
+ CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_PAF_DEVDIS_RSP:
+ CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_PAF_PROVDIS_REQ:
+ CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_PAF_PROVDIS_RSP:
+ CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ default:
+ CFGP2P_ACTION(("%s Unknown P2P Public Action Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+
+ }
+
+ } else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) {
+ act_frm = (wifi_p2p_action_frame_t *)frame;
+ switch (act_frm->subtype) {
+ case P2P_AF_NOTICE_OF_ABSENCE:
+ CFGP2P_ACTION(("%s P2P Notice of Absence Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_AF_PRESENCE_REQ:
+ CFGP2P_ACTION(("%s P2P Presence Request Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_AF_PRESENCE_RSP:
+ CFGP2P_ACTION(("%s P2P Presence Response Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ case P2P_AF_GO_DISC_REQ:
+ CFGP2P_ACTION(("%s P2P Discoverability Request Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ break;
+ default:
+ CFGP2P_ACTION(("%s Unknown P2P Action Frame,"
+ " channel=%d\n", (tx)? "TX": "RX", channel));
+ }
+
+ } else if (wl_cfgp2p_is_gas_action(frame, frame_len)) {
+ sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
+ switch (sd_act_frm->action) {
+ case P2PSD_ACTION_ID_GAS_IREQ:
+ CFGP2P_ACTION(("%s P2P GAS Initial Request,"
+ " channel=%d\n", (tx)? "TX" : "RX", channel));
+ break;
+ case P2PSD_ACTION_ID_GAS_IRESP:
+ CFGP2P_ACTION(("%s P2P GAS Initial Response,"
+ " channel=%d\n", (tx)? "TX" : "RX", channel));
+ break;
+ case P2PSD_ACTION_ID_GAS_CREQ:
+ CFGP2P_ACTION(("%s P2P GAS Comback Request,"
+ " channel=%d\n", (tx)? "TX" : "RX", channel));
+ break;
+ case P2PSD_ACTION_ID_GAS_CRESP:
+ CFGP2P_ACTION(("%s P2P GAS Comback Response,"
+ " channel=%d\n", (tx)? "TX" : "RX", channel));
+ break;
+ default:
+ CFGP2P_ACTION(("%s Unknown P2P GAS Frame,"
+ " channel=%d\n", (tx)? "TX" : "RX", channel));
+ }
+
+
+ }
+}
+
+/*
+ * Initialize variables related to P2P
+ *
+ */
+s32
+wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg)
+{
+ if (!(cfg->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) {
+ CFGP2P_ERR(("struct p2p_info allocation failed\n"));
+ return -ENOMEM;
+ }
+
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY) = bcmcfg_to_prmry_ndev(cfg);
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY) = 0;
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION) = NULL;
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION) = -1;
+ return BCME_OK;
+
+}
+/*
+ * Deinitialize variables related to P2P
+ *
+ */
+void
+wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg)
+{
+ CFGP2P_ERR(("In\n"));
+ if (cfg->p2p) {
+ kfree(cfg->p2p);
+ cfg->p2p = NULL;
+ }
+ cfg->p2p_supported = 0;
+}
+/*
+ * Set P2P functions into firmware
+ */
+s32
+wl_cfgp2p_set_firm_p2p(struct bcm_cfg80211 *cfg)
+{
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ struct ether_addr null_eth_addr = { { 0, 0, 0, 0, 0, 0 } };
+ s32 ret = BCME_OK;
+ s32 val = 0;
+ /* Do we have to check whether APSTA is enabled or not ? */
+ ret = wldev_iovar_getint(ndev, "apsta", &val);
+ if (ret < 0) {
+ CFGP2P_ERR(("get apsta error %d\n", ret));
+ return ret;
+ }
+ if (val == 0) {
+ val = 1;
+ ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
+ if (ret < 0) {
+ CFGP2P_ERR(("WLC_DOWN error %d\n", ret));
+ return ret;
+ }
+ wldev_iovar_setint(ndev, "apsta", val);
+ ret = wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
+ if (ret < 0) {
+ CFGP2P_ERR(("WLC_UP error %d\n", ret));
+ return ret;
+ }
+ }
+
+ /* In case of COB type, firmware has default mac address
+ * After Initializing firmware, we have to set current mac address to
+ * firmware for P2P device address
+ */
+ ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr,
+ sizeof(null_eth_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &cfg->ioctl_buf_sync);
+ if (ret && ret != BCME_UNSUPPORTED) {
+ CFGP2P_ERR(("failed to update device address ret %d\n", ret));
+ }
+ return ret;
+}
+
+/* Create a new P2P BSS.
+ * Parameters:
+ * @mac : MAC address of the BSS to create
+ * @if_type : interface type: WL_P2P_IF_GO or WL_P2P_IF_CLIENT
+ * @chspec : chspec to use if creating a GO BSS.
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
+ chanspec_t chspec)
+{
+ wl_p2p_if_t ifreq;
+ s32 err;
+ u32 scb_timeout = WL_SCB_TIMEOUT;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+
+ ifreq.type = if_type;
+ ifreq.chspec = chspec;
+ memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
+
+ CFGP2P_DBG(("---cfg p2p_ifadd "MACDBG" %s %u\n",
+ MAC2STRDBG(ifreq.addr.octet),
+ (if_type == WL_P2P_IF_GO) ? "go" : "client",
+ (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
+
+ err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+
+ if (unlikely(err < 0))
+ printk("'cfg p2p_ifadd' error %d\n", err);
+ else if (if_type == WL_P2P_IF_GO) {
+ err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
+ if (unlikely(err < 0))
+ printk("'cfg scb_timeout' error %d\n", err);
+ }
+ return err;
+}
+
+/* Disable a P2P BSS.
+ * Parameters:
+ * @mac : MAC address of the BSS to disable
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
+{
+ s32 ret;
+ struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
+
+ CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdis "MACDBG"\n",
+ netdev->ifindex, MAC2STRDBG(mac->octet)));
+ ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (unlikely(ret < 0)) {
+ printk("'cfg p2p_ifdis' error %d\n", ret);
+ }
+ return ret;
+}
+
+/* Delete a P2P BSS.
+ * Parameters:
+ * @mac : MAC address of the BSS to delete
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
+{
+ s32 ret;
+ struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
+
+ CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdel "MACDBG"\n",
+ netdev->ifindex, MAC2STRDBG(mac->octet)));
+ ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (unlikely(ret < 0)) {
+ printk("'cfg p2p_ifdel' error %d\n", ret);
+ }
+ return ret;
+}
+
+/* Change a P2P Role.
+ * Parameters:
+ * @mac : MAC address of the BSS to change a role
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
+ chanspec_t chspec)
+{
+ wl_p2p_if_t ifreq;
+ s32 err;
+ u32 scb_timeout = WL_SCB_TIMEOUT;
+
+ struct net_device *netdev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION);
+
+ ifreq.type = if_type;
+ ifreq.chspec = chspec;
+ memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
+
+ CFGP2P_INFO(("---cfg p2p_ifchange "MACDBG" %s %u"
+ " chanspec 0x%04x\n", MAC2STRDBG(ifreq.addr.octet),
+ (if_type == WL_P2P_IF_GO) ? "go" : "client",
+ (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT,
+ ifreq.chspec));
+
+ err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+
+ if (unlikely(err < 0)) {
+ printk("'cfg p2p_ifupd' error %d\n", err);
+ } else if (if_type == WL_P2P_IF_GO) {
+ err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
+ if (unlikely(err < 0))
+ printk("'cfg scb_timeout' error %d\n", err);
+ }
+ return err;
+}
+
+
+/* Get the index of a created P2P BSS.
+ * Parameters:
+ * @mac : MAC address of the created BSS
+ * @index : output: index of created BSS
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_ifidx(struct bcm_cfg80211 *cfg, struct ether_addr *mac, s32 *index)
+{
+ s32 ret;
+ u8 getbuf[64];
+ struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
+
+ CFGP2P_INFO(("---cfg p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet)));
+
+ ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf,
+ sizeof(getbuf), wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY), NULL);
+
+ if (ret == 0) {
+ memcpy(index, getbuf, sizeof(s32));
+ CFGP2P_INFO(("---cfg p2p_if ==> %d\n", *index));
+ }
+
+ return ret;
+}
+
+static s32
+wl_cfgp2p_set_discovery(struct bcm_cfg80211 *cfg, s32 on)
+{
+ s32 ret = BCME_OK;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ CFGP2P_DBG(("enter\n"));
+
+ ret = wldev_iovar_setint(ndev, "p2p_disc", on);
+
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("p2p_disc %d error %d\n", on, ret));
+ }
+
+ return ret;
+}
+
+/* Set the WL driver's P2P mode.
+ * Parameters :
+ * @mode : is one of WL_P2P_DISC_ST_{SCAN,LISTEN,SEARCH}.
+ * @channel : the channel to listen
+ * @listen_ms : the time (milli seconds) to wait
+ * @bssidx : bss index for BSSCFG
+ * Returns 0 if success
+ */
+
+s32
+wl_cfgp2p_set_p2p_mode(struct bcm_cfg80211 *cfg, u8 mode, u32 channel, u16 listen_ms, int bssidx)
+{
+ wl_p2p_disc_st_t discovery_mode;
+ s32 ret;
+ struct net_device *dev;
+ CFGP2P_DBG(("enter\n"));
+
+ if (unlikely(bssidx == WL_INVALID)) {
+ CFGP2P_ERR((" %d index out of range\n", bssidx));
+ return -1;
+ }
+
+ dev = wl_cfgp2p_find_ndev(cfg, bssidx);
+ if (unlikely(dev == NULL)) {
+ CFGP2P_ERR(("bssidx %d is not assigned\n", bssidx));
+ return BCME_NOTFOUND;
+ }
+
+ /* Put the WL driver into P2P Listen Mode to respond to P2P probe reqs */
+ discovery_mode.state = mode;
+ discovery_mode.chspec = wl_ch_host_to_driver(channel);
+ discovery_mode.dwell = listen_ms;
+ ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
+ sizeof(discovery_mode), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
+ bssidx, &cfg->ioctl_buf_sync);
+
+ return ret;
+}
+
+/* Get the index of the P2P Discovery BSS */
+static s32
+wl_cfgp2p_get_disc_idx(struct bcm_cfg80211 *cfg, s32 *index)
+{
+ s32 ret;
+ struct net_device *dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
+
+ ret = wldev_iovar_getint(dev, "p2p_dev", index);
+ CFGP2P_INFO(("p2p_dev bsscfg_idx=%d ret=%d\n", *index, ret));
+
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("'p2p_dev' error %d\n", ret));
+ return ret;
+ }
+ return ret;
+}
+
+s32
+wl_cfgp2p_init_discovery(struct bcm_cfg80211 *cfg)
+{
+
+ s32 index = 0;
+ s32 ret = BCME_OK;
+
+ CFGP2P_DBG(("enter\n"));
+
+ if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) != 0) {
+ CFGP2P_ERR(("do nothing, already initialized\n"));
+ return ret;
+ }
+
+ ret = wl_cfgp2p_set_discovery(cfg, 1);
+ if (ret < 0) {
+ CFGP2P_ERR(("set discover error\n"));
+ return ret;
+ }
+ /* Enable P2P Discovery in the WL Driver */
+ ret = wl_cfgp2p_get_disc_idx(cfg, &index);
+
+ if (ret < 0) {
+ return ret;
+ }
+ /* In case of CFG80211 case, check if p2p_discovery interface has allocated p2p_wdev */
+ if (!cfg->p2p_wdev) {
+ CFGP2P_ERR(("p2p_wdev is NULL.\n"));
+ return BCME_NODEVICE;
+ }
+ /* Make an entry in the netinfo */
+ wl_alloc_netinfo(cfg, cfg->p2p_net, cfg->p2p_wdev, WL_MODE_BSS, 0, index);
+
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) =
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = index;
+
+ /* Set the initial discovery state to SCAN */
+ ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
+
+ if (unlikely(ret != 0)) {
+ CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
+ wl_cfgp2p_set_discovery(cfg, 0);
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
+ return 0;
+ }
+ return ret;
+}
+
+/* Deinitialize P2P Discovery
+ * Parameters :
+ * @cfg : wl_private data
+ * Returns 0 if succes
+ */
+static s32
+wl_cfgp2p_deinit_discovery(struct bcm_cfg80211 *cfg)
+{
+ s32 ret = BCME_OK;
+ CFGP2P_DBG(("enter\n"));
+
+ if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) == 0) {
+ CFGP2P_ERR(("do nothing, not initialized\n"));
+ return -1;
+ }
+ /* Set the discovery state to SCAN */
+ ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
+ /* Disable P2P discovery in the WL driver (deletes the discovery BSSCFG) */
+ ret = wl_cfgp2p_set_discovery(cfg, 0);
+
+ /* Remove the p2p disc entry in the netinfo */
+#ifdef DHD_IFDEBUG
+ WL_ERR(("dealloc_net_info by wdev=%p\n", cfg->p2p_wdev));
+#endif
+ wl_dealloc_netinfo_by_wdev(cfg, cfg->p2p_wdev);
+
+ /* Clear our saved WPS and P2P IEs for the discovery BSS. The driver
+ * deleted these IEs when wl_cfgp2p_set_discovery() deleted the discovery
+ * BSS.
+ */
+
+ /* Clear the saved bsscfg index of the discovery BSSCFG to indicate we
+ * have no discovery BSS.
+ */
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = WL_INVALID;
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
+
+ return ret;
+
+}
+/* Enable P2P Discovery
+ * Parameters:
+ * @cfg : wl_private data
+ * @ie : probe request ie (WPS IE + P2P IE)
+ * @ie_len : probe request ie length
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_enable_discovery(struct bcm_cfg80211 *cfg, struct net_device *dev,
+ const u8 *ie, u32 ie_len)
+{
+ s32 ret = BCME_OK;
+ s32 bssidx;
+
+ CFGP2P_DBG(("enter\n"));
+
+ if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
+ CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n"));
+ goto set_ie;
+ }
+
+ ret = wl_cfgp2p_init_discovery(cfg);
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR((" init discovery error %d\n", ret));
+ goto exit;
+ }
+
+ wl_set_p2p_status(cfg, DISCOVERY_ON);
+ /* Set wsec to any non-zero value in the discovery bsscfg to ensure our
+ * P2P probe responses have the privacy bit set in the 802.11 WPA IE.
+ * Some peer devices may not initiate WPS with us if this bit is not set.
+ */
+ ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE),
+ "wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR((" wsec error %d\n", ret));
+ }
+set_ie:
+ if (ie_len) {
+ if (bcmcfg_to_prmry_ndev(cfg) == dev) {
+ bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
+ } else if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfg->p2p_wdev)) < 0) {
+ WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
+ return BCME_ERROR;
+ }
+
+ ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, dev,
+ bssidx,
+ VNDR_IE_PRBREQ_FLAG, ie, ie_len);
+
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
+ goto exit;
+ }
+ }
+exit:
+ return ret;
+}
+
+/* Disable P2P Discovery
+ * Parameters:
+ * @cfg : wl_private_data
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_disable_discovery(struct bcm_cfg80211 *cfg)
+{
+ s32 ret = BCME_OK;
+ CFGP2P_DBG((" enter\n"));
+ wl_clr_p2p_status(cfg, DISCOVERY_ON);
+
+ if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) == 0) {
+ CFGP2P_ERR((" do nothing, not initialized\n"));
+ goto exit;
+ }
+
+ ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
+
+ if (unlikely(ret < 0)) {
+
+ CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
+ }
+ /* Do a scan abort to stop the driver's scan engine in case it is still
+ * waiting out an action frame tx dwell time.
+ */
+ wl_clr_p2p_status(cfg, DISCOVERY_ON);
+ ret = wl_cfgp2p_deinit_discovery(cfg);
+
+exit:
+ return ret;
+}
+
+s32
+wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active,
+ u32 num_chans, u16 *channels,
+ s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
+ p2p_scan_purpose_t p2p_scan_purpose)
+{
+ s32 ret = BCME_OK;
+ s32 memsize;
+ s32 eparams_size;
+ u32 i;
+ s8 *memblk;
+ wl_p2p_scan_t *p2p_params;
+ wl_escan_params_t *eparams;
+ wlc_ssid_t ssid;
+ /* Scan parameters */
+#define P2PAPI_SCAN_NPROBES 1
+#define P2PAPI_SCAN_DWELL_TIME_MS 80
+#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
+#define P2PAPI_SCAN_HOME_TIME_MS 60
+#define P2PAPI_SCAN_NPROBS_TIME_MS 30
+#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
+
+ struct net_device *pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
+ /* Allocate scan params which need space for 3 channels and 0 ssids */
+ eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
+ OFFSETOF(wl_escan_params_t, params)) +
+ num_chans * sizeof(eparams->params.channel_list[0]);
+
+ memsize = sizeof(wl_p2p_scan_t) + eparams_size;
+ memblk = scanparambuf;
+ if (memsize > sizeof(scanparambuf)) {
+ CFGP2P_ERR((" scanpar buf too small (%u > %zu)\n",
+ memsize, sizeof(scanparambuf)));
+ return -1;
+ }
+ memset(memblk, 0, memsize);
+ memset(cfg->ioctl_buf, 0, WLC_IOCTL_MAXLEN);
+ if (search_state == WL_P2P_DISC_ST_SEARCH) {
+ /*
+ * If we in SEARCH STATE, we don't need to set SSID explictly
+ * because dongle use P2P WILDCARD internally by default
+ */
+ wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx);
+ /* use null ssid */
+ ssid.SSID_len = 0;
+ memset(&ssid.SSID, 0, sizeof(ssid.SSID));
+ } else if (search_state == WL_P2P_DISC_ST_SCAN) {
+ /* SCAN STATE 802.11 SCAN
+ * WFD Supplicant has p2p_find command with (type=progressive, type= full)
+ * So if P2P_find command with type=progressive,
+ * we have to set ssid to P2P WILDCARD because
+ * we just do broadcast scan unless setting SSID
+ */
+ wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
+ /* use wild card ssid */
+ ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN;
+ memset(&ssid.SSID, 0, sizeof(ssid.SSID));
+ memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN);
+ } else {
+ CFGP2P_ERR((" invalid search state %d\n", search_state));
+ return -1;
+ }
+
+
+ /* Fill in the P2P scan structure at the start of the iovar param block */
+ p2p_params = (wl_p2p_scan_t*) memblk;
+ p2p_params->type = 'E';
+ /* Fill in the Scan structure that follows the P2P scan structure */
+ eparams = (wl_escan_params_t*) (p2p_params + 1);
+ eparams->params.bss_type = DOT11_BSSTYPE_ANY;
+ if (active)
+ eparams->params.scan_type = DOT11_SCANTYPE_ACTIVE;
+ else
+ eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE;
+
+ if (tx_dst_addr == NULL)
+ memcpy(&eparams->params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+ else
+ memcpy(&eparams->params.bssid, tx_dst_addr, ETHER_ADDR_LEN);
+
+ if (ssid.SSID_len)
+ memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t));
+
+ eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
+
+ switch (p2p_scan_purpose) {
+ case P2P_SCAN_SOCIAL_CHANNEL:
+ eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS);
+ break;
+ case P2P_SCAN_AFX_PEER_NORMAL:
+ case P2P_SCAN_AFX_PEER_REDUCED:
+ eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS);
+ break;
+ case P2P_SCAN_CONNECT_TRY:
+ eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
+ break;
+ default :
+ if (wl_get_drv_status_all(cfg, CONNECTED))
+ eparams->params.active_time = -1;
+ else
+ eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS);
+ break;
+ }
+
+ if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY)
+ eparams->params.nprobes = htod32(eparams->params.active_time /
+ WL_SCAN_JOIN_PROBE_INTERVAL_MS);
+ else
+ eparams->params.nprobes = htod32((eparams->params.active_time /
+ P2PAPI_SCAN_NPROBS_TIME_MS));
+
+
+ if (eparams->params.nprobes <= 0)
+ eparams->params.nprobes = 1;
+ CFGP2P_DBG(("nprobes # %d, active_time %d\n",
+ eparams->params.nprobes, eparams->params.active_time));
+ eparams->params.passive_time = htod32(-1);
+ eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
+ (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
+
+ for (i = 0; i < num_chans; i++) {
+ eparams->params.channel_list[i] = wl_ch_host_to_driver(channels[i]);
+ }
+ eparams->version = htod32(ESCAN_REQ_VERSION);
+ eparams->action = htod16(action);
+ wl_escan_set_sync_id(eparams->sync_id, cfg);
+ wl_escan_set_type(cfg, WL_SCANTYPE_P2P);
+ CFGP2P_INFO(("SCAN CHANNELS : "));
+
+ for (i = 0; i < num_chans; i++) {
+ if (i == 0) CFGP2P_INFO(("%d", channels[i]));
+ else CFGP2P_INFO((",%d", channels[i]));
+ }
+
+ CFGP2P_INFO(("\n"));
+
+ ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan",
+ memblk, memsize, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+ if (ret == BCME_OK)
+ wl_set_p2p_status(cfg, SCANNING);
+ return ret;
+}
+
+/* search function to reach at common channel to send action frame
+ * Parameters:
+ * @cfg : wl_private data
+ * @ndev : net device for bssidx
+ * @bssidx : bssidx for BSS
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_act_frm_search(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr)
+{
+ s32 ret = 0;
+ u32 chan_cnt = 0;
+ u16 *default_chan_list = NULL;
+ p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_AFX_PEER_NORMAL;
+ if (!p2p_is_on(cfg) || ndev == NULL || bssidx == WL_INVALID)
+ return -BCME_ERROR;
+ WL_TRACE_HW4((" Enter\n"));
+ if (bssidx == wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY))
+ bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
+ if (channel)
+ chan_cnt = AF_PEER_SEARCH_CNT;
+ else
+ chan_cnt = SOCIAL_CHAN_CNT;
+ default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL);
+ if (default_chan_list == NULL) {
+ CFGP2P_ERR(("channel list allocation failed \n"));
+ ret = -ENOMEM;
+ goto exit;
+ }
+ if (channel) {
+ u32 i;
+ /* insert same channel to the chan_list */
+ for (i = 0; i < chan_cnt; i++) {
+ default_chan_list[i] = channel;
+ }
+ } else {
+ default_chan_list[0] = SOCIAL_CHAN_1;
+ default_chan_list[1] = SOCIAL_CHAN_2;
+ default_chan_list[2] = SOCIAL_CHAN_3;
+ }
+ ret = wl_cfgp2p_escan(cfg, ndev, true, chan_cnt,
+ default_chan_list, WL_P2P_DISC_ST_SEARCH,
+ WL_SCAN_ACTION_START, bssidx, NULL, p2p_scan_purpose);
+ kfree(default_chan_list);
+exit:
+ return ret;
+}
+
+/* Check whether pointed-to IE looks like WPA. */
+#define wl_cfgp2p_is_wpa_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
+ (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE)
+/* Check whether pointed-to IE looks like WPS. */
+#define wl_cfgp2p_is_wps_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
+ (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE)
+/* Check whether the given IE looks like WFA P2P IE. */
+#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
+ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
+/* Check whether the given IE looks like WFA WFDisplay IE. */
+#ifndef WFA_OUI_TYPE_WFD
+#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */
+#endif
+#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
+ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
+
+
+/* Is any of the tlvs the expected entry? If
+ * not update the tlvs buffer pointer/length.
+ */
+static bool
+wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type)
+{
+ /* If the contents match the OUI and the type */
+ if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
+ !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
+ type == ie[TLV_BODY_OFF + oui_len]) {
+ return TRUE;
+ }
+
+ if (tlvs == NULL)
+ return FALSE;
+ /* point to the next ie */
+ ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
+ /* calculate the length of the rest of the buffer */
+ *tlvs_len -= (int)(ie - *tlvs);
+ /* update the pointer to the start of the buffer */
+ *tlvs = ie;
+
+ return FALSE;
+}
+
+wpa_ie_fixed_t *
+wl_cfgp2p_find_wpaie(u8 *parse, u32 len)
+{
+ bcm_tlv_t *ie;
+
+ while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_wpa_ie((u8*)ie, &parse, &len)) {
+ return (wpa_ie_fixed_t *)ie;
+ }
+ }
+ return NULL;
+}
+
+wpa_ie_fixed_t *
+wl_cfgp2p_find_wpsie(u8 *parse, u32 len)
+{
+ bcm_tlv_t *ie;
+
+ while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_wps_ie((u8*)ie, &parse, &len)) {
+ return (wpa_ie_fixed_t *)ie;
+ }
+ }
+ return NULL;
+}
+
+wifi_p2p_ie_t *
+wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
+{
+ bcm_tlv_t *ie;
+
+ while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len)) {
+ return (wifi_p2p_ie_t *)ie;
+ }
+ }
+ return NULL;
+}
+
+wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
+{
+ bcm_tlv_t *ie;
+
+ while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
+ return (wifi_wfd_ie_t *)ie;
+ }
+ }
+ return NULL;
+}
+u32
+wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
+ s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd)
+{
+ vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */
+ s32 iecount;
+ u32 data_offset;
+
+ /* Validate the pktflag parameter */
+ if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
+ VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
+ VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG))) {
+ CFGP2P_ERR(("p2pwl_vndr_ie: Invalid packet flag 0x%x\n", pktflag));
+ return -1;
+ }
+
+ /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
+ strncpy(hdr.cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
+ hdr.cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+ /* Set the IE count - the buffer contains only 1 IE */
+ iecount = htod32(1);
+ memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32));
+
+ /* Copy packet flags that indicate which packets will contain this IE */
+ pktflag = htod32(pktflag);
+ memcpy((void *)&hdr.vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
+ sizeof(u32));
+
+ /* Add the IE ID to the buffer */
+ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = ie_id;
+
+ /* Add the IE length to the buffer */
+ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len =
+ (uint8) VNDR_IE_MIN_LEN + datalen;
+
+ /* Add the IE OUI to the buffer */
+ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0] = oui[0];
+ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[1] = oui[1];
+ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[2] = oui[2];
+
+ /* Copy the aligned temporary vndr_ie buffer header to the IE buffer */
+ memcpy(iebuf, &hdr, sizeof(hdr) - 1);
+
+ /* Copy the IE data to the IE buffer */
+ data_offset =
+ (u8*)&hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0] -
+ (u8*)&hdr;
+ memcpy(iebuf + data_offset, data, datalen);
+ return data_offset + datalen;
+
+}
+
+struct net_device *
+wl_cfgp2p_find_ndev(struct bcm_cfg80211 *cfg, s32 bssidx)
+{
+ u32 i;
+ struct net_device *ndev = NULL;
+ if (bssidx < 0) {
+ CFGP2P_ERR((" bsscfg idx is invalid\n"));
+ goto exit;
+ }
+
+ for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
+ if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
+ ndev = wl_to_p2p_bss_ndev(cfg, i);
+ break;
+ }
+ }
+
+exit:
+ return ndev;
+}
+/*
+ * Search the driver array idx based on bssidx argument
+ * Parameters:
+ * @cfg : wl_private data
+ * @bssidx : bssidx which indicate bsscfg->idx of firmware.
+ * @type : output arg to store array idx of p2p->bss.
+ * Returns error
+ */
+
+s32
+wl_cfgp2p_find_type(struct bcm_cfg80211 *cfg, s32 bssidx, s32 *type)
+{
+ u32 i;
+ if (bssidx < 0 || type == NULL) {
+ CFGP2P_ERR((" argument is invalid\n"));
+ goto exit;
+ }
+
+ for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
+ if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
+ *type = i;
+ return BCME_OK;
+ }
+ }
+
+exit:
+ return BCME_BADARG;
+}
+
+/*
+ * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE
+ */
+s32
+wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 ret = BCME_OK;
+ struct net_device *ndev = NULL;
+
+ if (!cfg || !cfg->p2p || !cfgdev)
+ return BCME_ERROR;
+
+ CFGP2P_DBG((" Enter\n"));
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ if (wl_get_p2p_status(cfg, LISTEN_EXPIRED) == 0) {
+ wl_set_p2p_status(cfg, LISTEN_EXPIRED);
+ if (timer_pending(&cfg->p2p->listen_timer)) {
+ del_timer_sync(&cfg->p2p->listen_timer);
+ }
+
+ if (cfg->afx_hdl->is_listen == TRUE &&
+ wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
+ WL_DBG(("Listen DONE for action frame\n"));
+ complete(&cfg->act_frm_scan);
+ }
+#ifdef WL_CFG80211_SYNC_GON
+ else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
+ wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, ndev);
+ WL_DBG(("Listen DONE and wake up wait_next_af !!(%d)\n",
+ jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies)));
+
+ if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM))
+ wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
+
+ complete(&cfg->wait_next_af);
+ }
+#endif /* WL_CFG80211_SYNC_GON */
+
+#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL)) {
+#else
+ if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL) ||
+ wl_get_drv_status_all(cfg, FAKE_REMAINING_ON_CHANNEL)) {
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+ WL_DBG(("Listen DONE for ramain on channel expired\n"));
+ wl_clr_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ wl_clr_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+ if (ndev && (ndev->ieee80211_ptr != NULL)) {
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ if (bcmcfg_to_p2p_wdev(cfg)) {
+ cfg80211_remain_on_channel_expired(
+ bcmcfg_to_p2p_wdev(cfg), cfg->last_roc_id,
+ &cfg->remain_on_chan, GFP_KERNEL);
+ }
+#else
+ cfg80211_remain_on_channel_expired(cfg->p2p_net, cfg->last_roc_id,
+ &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ }
+ }
+ if (wl_add_remove_eventmsg(bcmcfg_to_prmry_ndev(cfg),
+ WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) {
+ CFGP2P_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
+ }
+ } else
+ wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
+
+ return ret;
+
+}
+
+/*
+ * Timer expire callback function for LISTEN
+ * We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
+ * so lets do it from thread context.
+ */
+void
+wl_cfgp2p_listen_expired(unsigned long data)
+{
+ wl_event_msg_t msg;
+ struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
+ CFGP2P_DBG((" Enter\n"));
+ bzero(&msg, sizeof(wl_event_msg_t));
+ msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
+#if defined(WL_ENABLE_P2P_IF)
+ wl_cfg80211_event(cfg->p2p_net ? cfg->p2p_net :
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
+#else
+ wl_cfg80211_event(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg,
+ NULL);
+#endif /* WL_ENABLE_P2P_IF */
+}
+/*
+ * Routine for cancelling the P2P LISTEN
+ */
+static s32
+wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ struct wireless_dev *wdev, bool notify)
+{
+ WL_DBG(("Enter \n"));
+ /* Irrespective of whether timer is running or not, reset
+ * the LISTEN state.
+ */
+ if (timer_pending(&cfg->p2p->listen_timer)) {
+ del_timer_sync(&cfg->p2p->listen_timer);
+ if (notify) {
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#ifdef P2PONEINT
+ if (wdev == NULL)
+ wdev = bcmcfg_to_p2p_wdev(cfg);
+#endif
+ if (wdev)
+ cfg80211_remain_on_channel_expired(
+ bcmcfg_to_p2p_wdev(cfg), cfg->last_roc_id,
+ &cfg->remain_on_chan, GFP_KERNEL);
+#else
+ if (ndev && ndev->ieee80211_ptr)
+ cfg80211_remain_on_channel_expired(cfg->p2p_net, cfg->last_roc_id,
+ &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ }
+ }
+ return 0;
+}
+/*
+ * Do a P2P Listen on the given channel for the given duration.
+ * A listen consists of sitting idle and responding to P2P probe requests
+ * with a P2P probe response.
+ *
+ * This fn assumes dongle p2p device discovery is already enabled.
+ * Parameters :
+ * @cfg : wl_private data
+ * @channel : channel to listen
+ * @duration_ms : the time (milli seconds) to wait
+ */
+s32
+wl_cfgp2p_discover_listen(struct bcm_cfg80211 *cfg, s32 channel, u32 duration_ms)
+{
+#define EXTRA_DELAY_TIME 100
+ s32 ret = BCME_OK;
+ struct timer_list *_timer;
+ s32 extra_delay;
+ struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
+
+ CFGP2P_DBG((" Enter Listen Channel : %d, Duration : %d\n", channel, duration_ms));
+ if (unlikely(wl_get_p2p_status(cfg, DISCOVERY_ON) == 0)) {
+
+ CFGP2P_ERR((" Discovery is not set, so we have noting to do\n"));
+
+ ret = BCME_NOTREADY;
+ goto exit;
+ }
+ if (timer_pending(&cfg->p2p->listen_timer)) {
+ CFGP2P_DBG(("previous LISTEN is not completed yet\n"));
+ goto exit;
+
+ }
+#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ else
+ wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
+#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+ if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, true) != BCME_OK) {
+ CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n"));
+ }
+
+ ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms,
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
+ _timer = &cfg->p2p->listen_timer;
+
+ /* We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle ,
+ * otherwise we will wait up to duration_ms + 100ms + duration / 10
+ */
+ if (ret == BCME_OK) {
+ extra_delay = EXTRA_DELAY_TIME + (duration_ms / 10);
+ } else {
+ /* if failed to set listen, it doesn't need to wait whole duration. */
+ duration_ms = 100 + duration_ms / 20;
+ extra_delay = 0;
+ }
+
+ INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration_ms, extra_delay);
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
+
+#undef EXTRA_DELAY_TIME
+exit:
+ return ret;
+}
+
+
+s32
+wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable)
+{
+ s32 ret = BCME_OK;
+ CFGP2P_DBG((" Enter\n"));
+ if (!wl_get_p2p_status(cfg, DISCOVERY_ON)) {
+
+ CFGP2P_DBG((" do nothing, discovery is off\n"));
+ return ret;
+ }
+ if (wl_get_p2p_status(cfg, SEARCH_ENABLED) == enable) {
+ CFGP2P_DBG(("already : %d\n", enable));
+ return ret;
+ }
+
+ wl_chg_p2p_status(cfg, SEARCH_ENABLED);
+ /* When disabling Search, reset the WL driver's p2p discovery state to
+ * WL_P2P_DISC_ST_SCAN.
+ */
+ if (!enable) {
+ wl_clr_p2p_status(cfg, SCANNING);
+ ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
+ }
+
+ return ret;
+}
+
+/*
+ * Callback function for WLC_E_ACTION_FRAME_COMPLETE, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE
+ */
+s32
+wl_cfgp2p_action_tx_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 ret = BCME_OK;
+ u32 event_type = ntoh32(e->event_type);
+ u32 status = ntoh32(e->status);
+ struct net_device *ndev = NULL;
+ CFGP2P_DBG((" Enter\n"));
+
+ ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+ if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
+ if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
+
+ CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
+ if (status == WLC_E_STATUS_SUCCESS) {
+ wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
+ CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n"));
+ if (!cfg->need_wait_afrx && cfg->af_sent_channel) {
+ CFGP2P_DBG(("no need to wait next AF.\n"));
+ wl_stop_wait_next_action_frame(cfg, ndev);
+ }
+ }
+ else if (!wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
+ wl_set_p2p_status(cfg, ACTION_TX_NOACK);
+ CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
+ wl_stop_wait_next_action_frame(cfg, ndev);
+ }
+ } else {
+ CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
+ "status : %d\n", status));
+
+ if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
+ complete(&cfg->send_af_done);
+ }
+ }
+ return ret;
+}
+/* Send an action frame immediately without doing channel synchronization.
+ *
+ * This function does not wait for a completion event before returning.
+ * The WLC_E_ACTION_FRAME_COMPLETE event will be received when the action
+ * frame is transmitted.
+ * The WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE event will be received when an
+ * 802.11 ack has been received for the sent action frame.
+ */
+s32
+wl_cfgp2p_tx_action_frame(struct bcm_cfg80211 *cfg, struct net_device *dev,
+ wl_af_params_t *af_params, s32 bssidx)
+{
+ s32 ret = BCME_OK;
+ s32 evt_ret = BCME_OK;
+ s32 timeout = 0;
+ wl_eventmsg_buf_t buf;
+
+
+ CFGP2P_INFO(("\n"));
+ CFGP2P_INFO(("channel : %u , dwell time : %u\n",
+ af_params->channel, af_params->dwell_time));
+
+ wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
+ wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
+
+ bzero(&buf, sizeof(wl_eventmsg_buf_t));
+ wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, true);
+ wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, true);
+ if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0)
+ return evt_ret;
+
+ cfg->af_sent_channel = af_params->channel;
+#ifdef WL_CFG80211_SYNC_GON
+ cfg->af_tx_sent_jiffies = jiffies;
+#endif /* WL_CFG80211_SYNC_GON */
+
+ ret = wldev_iovar_setbuf_bsscfg(dev, "actframe", af_params, sizeof(*af_params),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
+
+ if (ret < 0) {
+ CFGP2P_ERR((" sending action frame is failed\n"));
+ goto exit;
+ }
+
+ timeout = wait_for_completion_timeout(&cfg->send_af_done,
+ msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX));
+
+ if (timeout >= 0 && wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
+ CFGP2P_INFO(("tx action frame operation is completed\n"));
+ ret = BCME_OK;
+ } else if (ETHER_ISBCAST(&cfg->afx_hdl->tx_dst_addr)) {
+ CFGP2P_INFO(("bcast tx action frame operation is completed\n"));
+ ret = BCME_OK;
+ } else {
+ ret = BCME_ERROR;
+ CFGP2P_INFO(("tx action frame operation is failed\n"));
+ }
+ /* clear status bit for action tx */
+ wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
+ wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
+
+exit:
+ CFGP2P_INFO((" via act frame iovar : status = %d\n", ret));
+
+ bzero(&buf, sizeof(wl_eventmsg_buf_t));
+ wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false);
+ wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, false);
+ if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0) {
+ WL_ERR(("TX frame events revert back failed \n"));
+ return evt_ret;
+ }
+
+ return ret;
+}
+
+/* Generate our P2P Device Address and P2P Interface Address from our primary
+ * MAC address.
+ */
+void
+wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr,
+ struct ether_addr *out_dev_addr, struct ether_addr *out_int_addr)
+{
+ memset(out_dev_addr, 0, sizeof(*out_dev_addr));
+ memset(out_int_addr, 0, sizeof(*out_int_addr));
+
+ /* Generate the P2P Device Address. This consists of the device's
+ * primary MAC address with the locally administered bit set.
+ */
+ memcpy(out_dev_addr, primary_addr, sizeof(*out_dev_addr));
+ out_dev_addr->octet[0] |= 0x02;
+
+ /* Generate the P2P Interface Address. If the discovery and connection
+ * BSSCFGs need to simultaneously co-exist, then this address must be
+ * different from the P2P Device Address.
+ */
+ memcpy(out_int_addr, out_dev_addr, sizeof(*out_int_addr));
+#ifndef P2PONEINT
+ out_int_addr->octet[3] ^= 0x80;
+#endif
+
+}
+
+/* P2P IF Address change to Virtual Interface MAC Address */
+void
+wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id)
+{
+ wifi_p2p_ie_t *ie = (wifi_p2p_ie_t*) buf;
+ u16 len = ie->len;
+ u8 *subel;
+ u8 subelt_id;
+ u16 subelt_len;
+ CFGP2P_DBG((" Enter\n"));
+
+ /* Point subel to the P2P IE's subelt field.
+ * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
+ */
+ subel = ie->subelts;
+ len -= 4; /* exclude OUI + OUI_TYPE */
+
+ while (len >= 3) {
+ /* attribute id */
+ subelt_id = *subel;
+ subel += 1;
+ len -= 1;
+
+ /* 2-byte little endian */
+ subelt_len = *subel++;
+ subelt_len |= *subel++ << 8;
+
+ len -= 2;
+ len -= subelt_len; /* for the remaining subelt fields */
+
+ if (subelt_id == element_id) {
+ if (subelt_id == P2P_SEID_INTINTADDR) {
+ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
+ CFGP2P_INFO(("Intended P2P Interface Address ATTR FOUND\n"));
+ } else if (subelt_id == P2P_SEID_DEV_ID) {
+ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
+ CFGP2P_INFO(("Device ID ATTR FOUND\n"));
+ } else if (subelt_id == P2P_SEID_DEV_INFO) {
+ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
+ CFGP2P_INFO(("Device INFO ATTR FOUND\n"));
+ } else if (subelt_id == P2P_SEID_GROUP_ID) {
+ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
+ CFGP2P_INFO(("GROUP ID ATTR FOUND\n"));
+ } return;
+ } else {
+ CFGP2P_DBG(("OTHER id : %d\n", subelt_id));
+ }
+ subel += subelt_len;
+ }
+}
+/*
+ * Check if a BSS is up.
+ * This is a common implementation called by most OSL implementations of
+ * p2posl_bss_isup(). DO NOT call this function directly from the
+ * common code -- call p2posl_bss_isup() instead to allow the OSL to
+ * override the common implementation if necessary.
+ */
+bool
+wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx)
+{
+ s32 result, val;
+ bool isup = false;
+ s8 getbuf[64];
+
+ /* Check if the BSS is up */
+ *(int*)getbuf = -1;
+ result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
+ sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
+ if (result != 0) {
+ CFGP2P_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
+ CFGP2P_ERR(("NOTE: this ioctl error is normal "
+ "when the BSS has not been created yet.\n"));
+ } else {
+ val = *(int*)getbuf;
+ val = dtoh32(val);
+ CFGP2P_INFO(("---cfg bss -C %d ==> %d\n", bsscfg_idx, val));
+ isup = (val ? TRUE : FALSE);
+ }
+ return isup;
+}
+
+
+/* Bring up or down a BSS */
+s32
+wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 up)
+{
+ s32 ret = BCME_OK;
+ s32 val = up ? 1 : 0;
+
+ struct {
+ s32 cfg;
+ s32 val;
+ } bss_setbuf;
+
+ bss_setbuf.cfg = htod32(bsscfg_idx);
+ bss_setbuf.val = htod32(val);
+ CFGP2P_INFO(("---cfg bss -C %d %s\n", bsscfg_idx, up ? "up" : "down"));
+ ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+
+ if (ret != 0) {
+ CFGP2P_ERR(("'bss %d' failed with %d\n", up, ret));
+ }
+
+ return ret;
+}
+
+/* Check if 'p2p' is supported in the driver */
+s32
+wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev)
+{
+ s32 ret = BCME_OK;
+ s32 p2p_supported = 0;
+ ret = wldev_iovar_getint(ndev, "p2p",
+ &p2p_supported);
+ if (ret < 0) {
+ if (ret == BCME_UNSUPPORTED) {
+ CFGP2P_INFO(("p2p is unsupported\n"));
+ return 0;
+ } else {
+ CFGP2P_ERR(("cfg p2p error %d\n", ret));
+ return ret;
+ }
+ }
+ if (p2p_supported == 1) {
+ CFGP2P_INFO(("p2p is supported\n"));
+ } else {
+ CFGP2P_INFO(("p2p is unsupported\n"));
+ p2p_supported = 0;
+ }
+ return p2p_supported;
+}
+/* Cleanup P2P resources */
+s32
+wl_cfgp2p_down(struct bcm_cfg80211 *cfg)
+{
+ struct net_device *ndev = NULL;
+ struct wireless_dev *wdev = NULL;
+ s32 i = 0, index = -1;
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ wdev = bcmcfg_to_p2p_wdev(cfg);
+#ifdef P2PONEINT
+ ndev = wdev_to_ndev(wdev);
+#else
+ ndev = bcmcfg_to_prmry_ndev(cfg);
+#endif
+#elif defined(WL_ENABLE_P2P_IF)
+ ndev = cfg->p2p_net ? cfg->p2p_net : bcmcfg_to_prmry_ndev(cfg);
+ wdev = ndev_to_wdev(ndev);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+ wl_cfgp2p_cancel_listen(cfg, ndev, wdev, TRUE);
+ for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
+ index = wl_to_p2p_bss_bssidx(cfg, i);
+ if (index != WL_INVALID)
+ wl_cfg80211_clear_per_bss_ies(cfg, index);
+ }
+ wl_cfgp2p_deinit_priv(cfg);
+ return 0;
+}
+
+int wl_cfgp2p_vif_created(struct bcm_cfg80211 *cfg)
+{
+ if (cfg->p2p && (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION) != -1))
+ return true;
+ else
+ return false;
+}
+
+s32
+wl_cfgp2p_set_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
+{
+ s32 ret = -1;
+ int count, start, duration;
+ wl_p2p_sched_t dongle_noa;
+
+ CFGP2P_DBG((" Enter\n"));
+
+ memset(&dongle_noa, 0, sizeof(dongle_noa));
+
+ if (wl_cfgp2p_vif_created(cfg)) {
+
+ cfg->p2p->noa.desc[0].start = 0;
+
+ sscanf(buf, "%10d %10d %10d", &count, &start, &duration);
+ CFGP2P_DBG(("set_p2p_noa count %d start %d duration %d\n",
+ count, start, duration));
+ if (count != -1)
+ cfg->p2p->noa.desc[0].count = count;
+
+ /* supplicant gives interval as start */
+ if (start != -1)
+ cfg->p2p->noa.desc[0].interval = start;
+
+ if (duration != -1)
+ cfg->p2p->noa.desc[0].duration = duration;
+
+ if (cfg->p2p->noa.desc[0].count < 255 && cfg->p2p->noa.desc[0].count > 1) {
+ cfg->p2p->noa.desc[0].start = 0;
+ dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
+ dongle_noa.action = WL_P2P_SCHED_ACTION_NONE;
+ dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS;
+ }
+ else if (cfg->p2p->noa.desc[0].count == 1) {
+ cfg->p2p->noa.desc[0].start = 200;
+ dongle_noa.type = WL_P2P_SCHED_TYPE_REQ_ABS;
+ dongle_noa.action = WL_P2P_SCHED_ACTION_GOOFF;
+ dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS;
+ }
+ else if (cfg->p2p->noa.desc[0].count == 0) {
+ cfg->p2p->noa.desc[0].start = 0;
+ dongle_noa.action = WL_P2P_SCHED_ACTION_RESET;
+ }
+ else {
+ /* Continuous NoA interval. */
+ dongle_noa.action = WL_P2P_SCHED_ACTION_DOZE;
+ dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
+ if ((cfg->p2p->noa.desc[0].interval == 102) ||
+ (cfg->p2p->noa.desc[0].interval == 100)) {
+ cfg->p2p->noa.desc[0].start = 100 -
+ cfg->p2p->noa.desc[0].duration;
+ dongle_noa.option = WL_P2P_SCHED_OPTION_BCNPCT;
+ }
+ else {
+ dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL;
+ }
+ }
+ /* Put the noa descriptor in dongle format for dongle */
+ dongle_noa.desc[0].count = htod32(cfg->p2p->noa.desc[0].count);
+ if (dongle_noa.option == WL_P2P_SCHED_OPTION_BCNPCT) {
+ dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start);
+ dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration);
+ }
+ else {
+ dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start*1000);
+ dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration*1000);
+ }
+ dongle_noa.desc[0].interval = htod32(cfg->p2p->noa.desc[0].interval*1000);
+
+ ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION),
+ "p2p_noa", &dongle_noa, sizeof(dongle_noa), cfg->ioctl_buf,
+ WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+
+ if (ret < 0) {
+ CFGP2P_ERR(("fw set p2p_noa failed %d\n", ret));
+ }
+ }
+ else {
+ CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
+ }
+ return ret;
+}
+s32
+wl_cfgp2p_get_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int buf_len)
+{
+
+ wifi_p2p_noa_desc_t *noa_desc;
+ int len = 0, i;
+ char _buf[200];
+
+ CFGP2P_DBG((" Enter\n"));
+ buf[0] = '\0';
+ if (wl_cfgp2p_vif_created(cfg)) {
+ if (cfg->p2p->noa.desc[0].count || cfg->p2p->ops.ops) {
+ _buf[0] = 1; /* noa index */
+ _buf[1] = (cfg->p2p->ops.ops ? 0x80: 0) |
+ (cfg->p2p->ops.ctw & 0x7f); /* ops + ctw */
+ len += 2;
+ if (cfg->p2p->noa.desc[0].count) {
+ noa_desc = (wifi_p2p_noa_desc_t*)&_buf[len];
+ noa_desc->cnt_type = cfg->p2p->noa.desc[0].count;
+ noa_desc->duration = cfg->p2p->noa.desc[0].duration;
+ noa_desc->interval = cfg->p2p->noa.desc[0].interval;
+ noa_desc->start = cfg->p2p->noa.desc[0].start;
+ len += sizeof(wifi_p2p_noa_desc_t);
+ }
+ if (buf_len <= len * 2) {
+ CFGP2P_ERR(("ERROR: buf_len %d in not enough for"
+ "returning noa in string format\n", buf_len));
+ return -1;
+ }
+ /* We have to convert the buffer data into ASCII strings */
+ for (i = 0; i < len; i++) {
+ snprintf(buf, 3, "%02x", _buf[i]);
+ buf += 2;
+ }
+ buf[i*2] = '\0';
+ }
+ }
+ else {
+ CFGP2P_ERR(("ERROR: get_noa in non-p2p mode\n"));
+ return -1;
+ }
+ return len * 2;
+}
+s32
+wl_cfgp2p_set_p2p_ps(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
+{
+ int ps, ctw;
+ int ret = -1;
+ s32 legacy_ps;
+ struct net_device *dev;
+
+ CFGP2P_DBG((" Enter\n"));
+ if (wl_cfgp2p_vif_created(cfg)) {
+ sscanf(buf, "%10d %10d %10d", &legacy_ps, &ps, &ctw);
+ CFGP2P_DBG((" Enter legacy_ps %d ps %d ctw %d\n", legacy_ps, ps, ctw));
+ dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION);
+ if (ctw != -1) {
+ cfg->p2p->ops.ctw = ctw;
+ ret = 0;
+ }
+ if (ps != -1) {
+ cfg->p2p->ops.ops = ps;
+ ret = wldev_iovar_setbuf(dev,
+ "p2p_ops", &cfg->p2p->ops, sizeof(cfg->p2p->ops),
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (ret < 0) {
+ CFGP2P_ERR(("fw set p2p_ops failed %d\n", ret));
+ }
+ }
+
+ if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) {
+ ret = wldev_ioctl(dev,
+ WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true);
+ if (unlikely(ret))
+ CFGP2P_ERR(("error (%d)\n", ret));
+ wl_cfg80211_update_power_mode(dev);
+ }
+ else
+ CFGP2P_ERR(("ilegal setting\n"));
+ }
+ else {
+ CFGP2P_ERR(("ERROR: set_p2p_ps in non-p2p mode\n"));
+ ret = -1;
+ }
+ return ret;
+}
+
+u8 *
+wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
+{
+ wifi_p2p_ie_t *ie = NULL;
+ u16 len = 0;
+ u8 *subel;
+ u8 subelt_id;
+ u16 subelt_len;
+
+ if (!buf) {
+ WL_ERR(("P2P IE not present"));
+ return 0;
+ }
+
+ ie = (wifi_p2p_ie_t*) buf;
+ len = ie->len;
+
+ /* Point subel to the P2P IE's subelt field.
+ * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
+ */
+ subel = ie->subelts;
+ len -= 4; /* exclude OUI + OUI_TYPE */
+
+ while (len >= 3) {
+ /* attribute id */
+ subelt_id = *subel;
+ subel += 1;
+ len -= 1;
+
+ /* 2-byte little endian */
+ subelt_len = *subel++;
+ subelt_len |= *subel++ << 8;
+
+ len -= 2;
+ len -= subelt_len; /* for the remaining subelt fields */
+
+ if (subelt_id == element_id) {
+ /* This will point to start of subelement attrib after
+ * attribute id & len
+ */
+ return subel;
+ }
+
+ /* Go to next subelement */
+ subel += subelt_len;
+ }
+
+ /* Not Found */
+ return NULL;
+}
+
+#define P2P_GROUP_CAPAB_GO_BIT 0x01
+
+u8*
+wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib)
+{
+ bcm_tlv_t *ie;
+ u8* pAttrib;
+
+ CFGP2P_INFO(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
+ while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len) == TRUE) {
+ /* Have the P2p ie. Now check for attribute */
+ if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(parse, attrib)) != NULL) {
+ CFGP2P_INFO(("P2P attribute %d was found at parse %p",
+ attrib, parse));
+ return pAttrib;
+ }
+ else {
+ parse += (ie->len + TLV_HDR_LEN);
+ len -= (ie->len + TLV_HDR_LEN);
+ CFGP2P_INFO(("P2P Attribute %d not found Moving parse"
+ " to %p len to %d", attrib, parse, len));
+ }
+ }
+ else {
+ /* It was not p2p IE. parse will get updated automatically to next TLV */
+ CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, len));
+ }
+ }
+ CFGP2P_ERR(("P2P attribute %d was NOT found", attrib));
+ return NULL;
+}
+
+u8 *
+wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length)
+{
+ u8 *capability = NULL;
+ bool p2p_go = 0;
+ u8 *ptr = NULL;
+
+ if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
+ bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) {
+ WL_ERR(("P2P Capability attribute not found"));
+ return NULL;
+ }
+
+ /* Check Group capability for Group Owner bit */
+ p2p_go = capability[1] & P2P_GROUP_CAPAB_GO_BIT;
+ if (!p2p_go) {
+ return bi->BSSID.octet;
+ }
+
+ /* In probe responses, DEVICE INFO attribute will be present */
+ if (!(ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
+ bi->ie_length, P2P_SEID_DEV_INFO))) {
+ /* If DEVICE_INFO is not found, this might be a beacon frame.
+ * check for DEVICE_ID in the beacon frame.
+ */
+ ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
+ bi->ie_length, P2P_SEID_DEV_ID);
+ }
+
+ if (!ptr)
+ WL_ERR((" Both DEVICE_ID & DEVICE_INFO attribute not present in P2P IE "));
+
+ return ptr;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+static void
+wl_cfgp2p_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
+{
+ snprintf(info->driver, sizeof(info->driver), "p2p");
+ snprintf(info->version, sizeof(info->version), "%lu", (unsigned long)(0));
+}
+
+struct ethtool_ops cfgp2p_ethtool_ops = {
+ .get_drvinfo = wl_cfgp2p_ethtool_get_drvinfo
+};
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
+
+#if defined(WL_ENABLE_P2P_IF) || defined(P2PONEINT)
+#ifdef P2PONEINT
+s32
+wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
+{
+
+ struct net_device *_ndev;
+ struct ether_addr primary_mac;
+ struct net_device *new_ndev;
+ chanspec_t chspec;
+ uint8 name[IFNAMSIZ];
+ s32 mode = 0;
+ s32 val = 0;
+
+
+ s32 wlif_type = -1;
+ s32 err, timeout = -1;
+
+ memset(name, 0, IFNAMSIZ);
+ strncpy(name, "p2p0", 4);
+ name[IFNAMSIZ - 1] = '\0';
+
+ if (cfg->p2p_net) {
+ CFGP2P_ERR(("p2p_net defined already.\n"));
+ return -EINVAL;
+ }
+
+ if (!cfg->p2p)
+ return -EINVAL;
+
+ if (cfg->p2p && !cfg->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
+ p2p_on(cfg) = true;
+ wl_cfgp2p_set_firm_p2p(cfg);
+ wl_cfgp2p_init_discovery(cfg);
+ get_primary_mac(cfg, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac,
+ &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
+ }
+
+ _ndev = bcmcfg_to_prmry_ndev(cfg);
+ memset(cfg->p2p->vir_ifname, 0, IFNAMSIZ);
+ strncpy(cfg->p2p->vir_ifname, name, IFNAMSIZ - 1);
+
+ wl_cfg80211_scan_abort(cfg);
+
+
+ /* In concurrency case, STA may be already associated in a particular channel.
+ * so retrieve the current channel of primary interface and then start the virtual
+ * interface on that.
+ */
+ chspec = wl_cfg80211_get_shared_freq(cfg->wdev->wiphy);
+
+ /* For P2P mode, use P2P-specific driver features to create the
+ * bss: "cfg p2p_ifadd"
+ */
+ wl_set_p2p_status(cfg, IF_ADDING);
+ memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
+ wlif_type = WL_P2P_IF_CLIENT;
+
+
+ err = wl_cfgp2p_ifadd(cfg, &cfg->p2p->int_addr, htod32(wlif_type), chspec);
+ if (unlikely(err)) {
+ wl_clr_p2p_status(cfg, IF_ADDING);
+ WL_ERR((" virtual iface add failed (%d) \n", err));
+ return -ENOMEM;
+ }
+
+ timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
+ (wl_get_p2p_status(cfg, IF_ADDING) == false),
+ msecs_to_jiffies(MAX_WAIT_TIME));
+
+
+ if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
+ struct wireless_dev *vwdev;
+ int pm_mode = PM_ENABLE;
+ wl_if_event_info *event = &cfg->if_event_info;
+
+ /* IF_ADD event has come back, we can proceed to to register
+ * the new interface now, use the interface name provided by caller (thus
+ * ignore the one from wlc)
+ */
+ strncpy(cfg->if_event_info.name, name, IFNAMSIZ - 1);
+ new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, cfg->p2p->vir_ifname,
+ event->mac, event->bssidx, event->name);
+ if (new_ndev == NULL)
+ goto fail;
+
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION) = new_ndev;
+ wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION) = event->bssidx;
+
+ vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
+ if (unlikely(!vwdev)) {
+ WL_ERR(("Could not allocate wireless device\n"));
+ goto fail;
+ }
+ vwdev->wiphy = cfg->wdev->wiphy;
+ WL_TRACE(("virtual interface(%s) is created\n", cfg->p2p->vir_ifname));
+ vwdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
+ vwdev->netdev = new_ndev;
+ new_ndev->ieee80211_ptr = vwdev;
+ SET_NETDEV_DEV(new_ndev, wiphy_dev(vwdev->wiphy));
+ wl_set_drv_status(cfg, READY, new_ndev);
+ wl_set_mode_by_netdev(cfg, new_ndev, mode);
+
+ if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
+ wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
+ goto fail;
+ }
+
+ wl_alloc_netinfo(cfg, new_ndev, vwdev, mode, pm_mode);
+ val = 1;
+ /* Disable firmware roaming for P2P interface */
+ wldev_iovar_setint(new_ndev, "roam_off", val);
+
+ if (mode != WL_MODE_AP)
+ wldev_iovar_setint(new_ndev, "buf_key_b4_m4", 1);
+
+ WL_ERR((" virtual interface(%s) is "
+ "created net attach done\n", cfg->p2p->vir_ifname));
+
+ /* reinitialize completion to clear previous count */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
+ INIT_COMPLETION(cfg->iface_disable);
+#else
+ init_completion(&cfg->iface_disable);
+#endif
+ cfg->p2p_net = new_ndev;
+ cfg->p2p_wdev = vwdev;
+
+ return 0;
+ } else {
+ wl_clr_p2p_status(cfg, IF_ADDING);
+ WL_ERR((" virtual interface(%s) is not created \n", cfg->p2p->vir_ifname));
+ memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
+ }
+
+
+fail:
+ if (wlif_type == WL_P2P_IF_GO)
+ wldev_iovar_setint(_ndev, "mpc", 1);
+ return -ENODEV;
+
+}
+#else
+s32
+wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
+{
+ int ret = 0;
+ struct net_device* net = NULL;
+ struct wireless_dev *wdev = NULL;
+ uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 };
+
+ if (cfg->p2p_net) {
+ CFGP2P_ERR(("p2p_net defined already.\n"));
+ return -EINVAL;
+ }
+
+ /* Allocate etherdev, including space for private structure */
+ if (!(net = alloc_etherdev(sizeof(struct bcm_cfg80211 *)))) {
+ CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __FUNCTION__));
+ return -ENODEV;
+ }
+
+ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+ if (unlikely(!wdev)) {
+ WL_ERR(("Could not allocate wireless device\n"));
+ free_netdev(net);
+ return -ENOMEM;
+ }
+
+ strncpy(net->name, "p2p%d", sizeof(net->name) - 1);
+ net->name[IFNAMSIZ - 1] = '\0';
+
+ /* Copy the reference to bcm_cfg80211 */
+ memcpy((void *)netdev_priv(net), &cfg, sizeof(struct bcm_cfg80211 *));
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
+ ASSERT(!net->open);
+ net->do_ioctl = wl_cfgp2p_do_ioctl;
+ net->hard_start_xmit = wl_cfgp2p_start_xmit;
+ net->open = wl_cfgp2p_if_open;
+ net->stop = wl_cfgp2p_if_stop;
+#else
+ ASSERT(!net->netdev_ops);
+ net->netdev_ops = &wl_cfgp2p_if_ops;
+#endif
+
+ /* Register with a dummy MAC addr */
+ memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
+
+ wdev->wiphy = cfg->wdev->wiphy;
+
+ wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
+
+ net->ieee80211_ptr = wdev;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+ net->ethtool_ops = &cfgp2p_ethtool_ops;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
+
+ SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy));
+
+ /* Associate p2p0 network interface with new wdev */
+ wdev->netdev = net;
+
+ ret = register_netdev(net);
+ if (ret) {
+ CFGP2P_ERR((" register_netdevice failed (%d)\n", ret));
+ free_netdev(net);
+ kfree(wdev);
+ return -ENODEV;
+ }
+
+ /* store p2p net ptr for further reference. Note that iflist won't have this
+ * entry as there corresponding firmware interface is a "Hidden" interface.
+ */
+ cfg->p2p_wdev = wdev;
+ cfg->p2p_net = net;
+
+ printk("%s: P2P Interface Registered\n", net->name);
+
+ return ret;
+}
+#endif /* P2PONEINT */
+
+s32
+wl_cfgp2p_unregister_ndev(struct bcm_cfg80211 *cfg)
+{
+
+ if (!cfg || !cfg->p2p_net) {
+ CFGP2P_ERR(("Invalid Ptr\n"));
+ return -EINVAL;
+ }
+
+ unregister_netdev(cfg->p2p_net);
+ free_netdev(cfg->p2p_net);
+
+ return 0;
+}
+
+#ifndef P2PONEINT
+static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+
+ if (skb)
+ {
+ CFGP2P_DBG(("(%s) is not used for data operations.Droping the packet.\n",
+ ndev->name));
+ dev_kfree_skb_any(skb);
+ }
+
+ return 0;
+}
+
+static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd)
+{
+ int ret = 0;
+ struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+
+ /* There is no ifidx corresponding to p2p0 in our firmware. So we should
+ * not Handle any IOCTL cmds on p2p0 other than ANDROID PRIVATE CMDs.
+ * For Android PRIV CMD handling map it to primary I/F
+ */
+ if (cmd == SIOCDEVPRIVATE+1) {
+ ret = wl_android_priv_cmd(ndev, ifr, cmd);
+
+ } else {
+ CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n",
+ __FUNCTION__, cmd));
+ return -1;
+ }
+
+ return ret;
+}
+#endif /* P2PONEINT */
+#endif
+
+
+#if defined(WL_ENABLE_P2P_IF) || defined(P2PONEINT)
+#ifdef P2PONEINT
+int wl_cfgp2p_if_open(struct net_device *net)
+#else
+static int wl_cfgp2p_if_open(struct net_device *net)
+#endif /* P2PONEINT */
+{
+ struct wireless_dev *wdev = net->ieee80211_ptr;
+
+ if (!wdev || !wl_cfg80211_is_p2p_active())
+ return -EINVAL;
+ WL_TRACE(("Enter\n"));
+#if !defined(WL_IFACE_COMB_NUM_CHANNELS)
+ /* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now,
+ * do it here. This will make sure that in concurrent mode, supplicant
+ * is not dependent on a particular order of interface initialization.
+ * i.e you may give wpa_supp -iwlan0 -N -ip2p0 or wpa_supp -ip2p0 -N
+ * -iwlan0.
+ */
+ wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)
+ | BIT(NL80211_IFTYPE_P2P_GO));
+#endif /* !WL_IFACE_COMB_NUM_CHANNELS */
+ wl_cfg80211_do_driver_init(net);
+
+ return 0;
+}
+
+#ifdef P2PONEINT
+int wl_cfgp2p_if_stop(struct net_device *net)
+#else
+static int wl_cfgp2p_if_stop(struct net_device *net)
+#endif
+{
+ struct wireless_dev *wdev = net->ieee80211_ptr;
+#ifdef P2PONEINT
+ bcm_struct_cfgdev *cfgdev;
+#endif
+ if (!wdev)
+ return -EINVAL;
+
+#ifdef P2PONEINT
+ cfgdev = ndev_to_cfgdev(net);
+ wl_cfg80211_scan_stop(cfgdev);
+#else
+ wl_cfg80211_scan_stop(net);
+#endif
+
+#if !defined(WL_IFACE_COMB_NUM_CHANNELS)
+ wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes)
+ & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)|
+ BIT(NL80211_IFTYPE_P2P_GO)));
+#endif /* !WL_IFACE_COMB_NUM_CHANNELS */
+
+ return 0;
+}
+#endif /* defined(WL_ENABLE_P2P_IF) || defined(P2PONEINT) */
+
+#if defined(WL_ENABLE_P2P_IF)
+bool wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops)
+{
+ return (if_ops == &wl_cfgp2p_if_ops);
+}
+#endif /* WL_ENABLE_P2P_IF */
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+struct wireless_dev *
+wl_cfgp2p_add_p2p_disc_if(struct bcm_cfg80211 *cfg)
+{
+ struct wireless_dev *wdev = NULL;
+ struct ether_addr primary_mac;
+
+ if (!cfg || !(cfg->p2p))
+ return ERR_PTR(-EINVAL);
+
+ WL_TRACE(("Enter\n"));
+
+ if (cfg->p2p_wdev) {
+ CFGP2P_ERR(("p2p_wdev defined already.\n"));
+ wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
+ CFGP2P_ERR(("p2p_wdev deleted.\n"));
+ }
+
+ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+ if (unlikely(!wdev)) {
+ WL_ERR(("Could not allocate wireless device\n"));
+ return ERR_PTR(-ENOMEM);
+ }
+
+ memset(&primary_mac, 0, sizeof(primary_mac));
+ get_primary_mac(cfg, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac,
+ &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
+
+ wdev->wiphy = cfg->wdev->wiphy;
+ wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
+ memcpy(wdev->address, &cfg->p2p->dev_addr, ETHER_ADDR_LEN);
+
+
+ /* store p2p wdev ptr for further reference. */
+ cfg->p2p_wdev = wdev;
+
+ CFGP2P_ERR(("P2P interface registered\n"));
+
+
+ return wdev;
+}
+
+int
+wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+ int ret = 0;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+
+ if (!cfg)
+ return -EINVAL;
+
+ WL_TRACE(("Enter\n"));
+
+ ret = wl_cfgp2p_set_firm_p2p(cfg);
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("Set P2P in firmware failed, ret=%d\n", ret));
+ goto exit;
+ }
+
+ ret = wl_cfgp2p_enable_discovery(cfg, bcmcfg_to_prmry_ndev(cfg), NULL, 0);
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("P2P enable discovery failed, ret=%d\n", ret));
+ goto exit;
+ }
+
+ p2p_on(cfg) = true;
+
+ CFGP2P_DBG(("P2P interface started\n"));
+
+exit:
+ return ret;
+}
+
+void
+wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+ int ret = 0;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+
+ if (!cfg)
+ return;
+
+ WL_TRACE(("Enter\n"));
+
+ ret = wl_cfg80211_scan_stop(wdev);
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
+ }
+
+ if (!cfg->p2p)
+ return;
+
+ ret = wl_cfgp2p_disable_discovery(cfg);
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("P2P disable discovery failed, ret=%d\n", ret));
+ }
+
+ p2p_on(cfg) = false;
+
+ CFGP2P_DBG(("P2P interface stopped\n"));
+
+ return;
+}
+
+
+int
+wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev, struct bcm_cfg80211 *cfg)
+{
+ bool rollback_lock = false;
+
+ if (!wdev)
+ return -EINVAL;
+
+#ifdef P2PONEINT
+ return -EINVAL;
+#endif
+
+ WL_TRACE(("Enter\n"));
+
+ if (!rtnl_is_locked()) {
+ rtnl_lock();
+ rollback_lock = true;
+ }
+
+ cfg80211_unregister_wdev(wdev);
+
+ if (rollback_lock)
+ rtnl_unlock();
+
+ synchronize_rcu();
+
+ kfree(wdev);
+
+ if (cfg)
+ cfg->p2p_wdev = NULL;
+
+ CFGP2P_ERR(("P2P interface unregistered\n"));
+
+
+ return 0;
+}
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+void
+wl_cfgp2p_need_wait_actfrmae(struct bcm_cfg80211 *cfg, void *frame, u32 frame_len, bool tx)
+{
+ wifi_p2p_pub_act_frame_t *pact_frm;
+ int status = 0;
+
+ if (!frame || (frame_len < (sizeof(*pact_frm) + WL_P2P_AF_STATUS_OFFSET - 1))) {
+ return;
+ }
+
+ if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
+ pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
+ if (pact_frm->subtype == P2P_PAF_GON_RSP && tx) {
+ CFGP2P_ACTION(("Check TX P2P Group Owner Negotiation Rsp Frame status\n"));
+ status = pact_frm->elts[WL_P2P_AF_STATUS_OFFSET];
+ if (status) {
+ cfg->need_wait_afrx = false;
+ return;
+ }
+ }
+ }
+
+ cfg->need_wait_afrx = true;
+ return;
+}
+
+int
+wl_cfgp2p_is_p2p_specific_scan(struct cfg80211_scan_request *request)
+{
+ if (request && (request->n_ssids == 1) &&
+ (request->n_channels == 1) &&
+ IS_P2P_SSID(request->ssids[0].ssid, WL_P2P_WILDCARD_SSID_LEN) &&
+ (request->ssids[0].ssid_len > WL_P2P_WILDCARD_SSID_LEN)) {
+ return true;
+ }
+ return false;
+}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
new file mode 100644
index 000000000000..5108c21c6188
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -0,0 +1,414 @@
+/*
+ * Linux cfgp2p driver
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfgp2p.h 662786 2016-11-11 09:06:37Z $
+ */
+#ifndef _wl_cfgp2p_h_
+#define _wl_cfgp2p_h_
+#include <proto/802.11.h>
+#include <proto/p2p.h>
+
+struct bcm_cfg80211;
+extern u32 wl_dbg_level;
+
+typedef struct wifi_p2p_ie wifi_wfd_ie_t;
+/* Enumeration of the usages of the BSSCFGs used by the P2P Library. Do not
+ * confuse this with a bsscfg index. This value is an index into the
+ * saved_ie[] array of structures which in turn contains a bsscfg index field.
+ */
+typedef enum {
+ P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */
+ P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */
+ P2PAPI_BSSCFG_CONNECTION, /* maps to driver's P2P connection bsscfg */
+ P2PAPI_BSSCFG_MAX
+} p2p_bsscfg_type_t;
+
+typedef enum {
+ P2P_SCAN_PURPOSE_MIN,
+ P2P_SCAN_SOCIAL_CHANNEL, /* scan for social channel */
+ P2P_SCAN_AFX_PEER_NORMAL, /* scan for action frame search */
+ P2P_SCAN_AFX_PEER_REDUCED, /* scan for action frame search with short time */
+ P2P_SCAN_DURING_CONNECTED, /* scan during connected status */
+ P2P_SCAN_CONNECT_TRY, /* scan for connecting */
+ P2P_SCAN_NORMAL, /* scan during not-connected status */
+ P2P_SCAN_PURPOSE_MAX
+} p2p_scan_purpose_t;
+
+/* vendor ies max buffer length for probe response or beacon */
+#define VNDR_IES_MAX_BUF_LEN 1400
+/* normal vendor ies buffer length */
+#define VNDR_IES_BUF_LEN 512
+
+/* Structure to hold all saved P2P and WPS IEs for a BSSCFG */
+struct p2p_saved_ie {
+ u8 p2p_probe_req_ie[VNDR_IES_BUF_LEN];
+ u8 p2p_probe_res_ie[VNDR_IES_MAX_BUF_LEN];
+ u8 p2p_assoc_req_ie[VNDR_IES_BUF_LEN];
+ u8 p2p_assoc_res_ie[VNDR_IES_BUF_LEN];
+ u8 p2p_beacon_ie[VNDR_IES_MAX_BUF_LEN];
+ u32 p2p_probe_req_ie_len;
+ u32 p2p_probe_res_ie_len;
+ u32 p2p_assoc_req_ie_len;
+ u32 p2p_assoc_res_ie_len;
+ u32 p2p_beacon_ie_len;
+};
+
+struct p2p_bss {
+ u32 bssidx;
+ struct net_device *dev;
+ struct p2p_saved_ie saved_ie;
+ void *private_data;
+};
+
+struct p2p_info {
+ bool on; /* p2p on/off switch */
+ bool scan;
+ int16 search_state;
+ s8 vir_ifname[IFNAMSIZ];
+ unsigned long status;
+ struct ether_addr dev_addr;
+ struct ether_addr int_addr;
+ struct p2p_bss bss[P2PAPI_BSSCFG_MAX];
+ struct timer_list listen_timer;
+ wl_p2p_sched_t noa;
+ wl_p2p_ops_t ops;
+ wlc_ssid_t ssid;
+};
+
+#define MAX_VNDR_IE_NUMBER 10
+
+struct parsed_vndr_ie_info {
+ char *ie_ptr;
+ u32 ie_len; /* total length including id & length field */
+ vndr_ie_t vndrie;
+};
+
+struct parsed_vndr_ies {
+ u32 count;
+ struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER];
+};
+
+/* dongle status */
+enum wl_cfgp2p_status {
+ WLP2P_STATUS_DISCOVERY_ON = 0,
+ WLP2P_STATUS_SEARCH_ENABLED,
+ WLP2P_STATUS_IF_ADDING,
+ WLP2P_STATUS_IF_DELETING,
+ WLP2P_STATUS_IF_CHANGING,
+ WLP2P_STATUS_IF_CHANGED,
+ WLP2P_STATUS_LISTEN_EXPIRED,
+ WLP2P_STATUS_ACTION_TX_COMPLETED,
+ WLP2P_STATUS_ACTION_TX_NOACK,
+ WLP2P_STATUS_SCANNING,
+ WLP2P_STATUS_GO_NEG_PHASE,
+ WLP2P_STATUS_DISC_IN_PROGRESS
+};
+
+
+#define wl_to_p2p_bss_ndev(cfg, type) ((cfg)->p2p->bss[type].dev)
+#define wl_to_p2p_bss_bssidx(cfg, type) ((cfg)->p2p->bss[type].bssidx)
+#define wl_to_p2p_bss_saved_ie(cfg, type) ((cfg)->p2p->bss[type].saved_ie)
+#define wl_to_p2p_bss_private(cfg, type) ((cfg)->p2p->bss[type].private_data)
+#define wl_to_p2p_bss(cfg, type) ((cfg)->p2p->bss[type])
+#define wl_get_p2p_status(cfg, stat) ((!(cfg)->p2p_supported) ? 0 : \
+ test_bit(WLP2P_STATUS_ ## stat, &(cfg)->p2p->status))
+#define wl_set_p2p_status(cfg, stat) ((!(cfg)->p2p_supported) ? 0 : \
+ set_bit(WLP2P_STATUS_ ## stat, &(cfg)->p2p->status))
+#define wl_clr_p2p_status(cfg, stat) ((!(cfg)->p2p_supported) ? 0 : \
+ clear_bit(WLP2P_STATUS_ ## stat, &(cfg)->p2p->status))
+#define wl_chg_p2p_status(cfg, stat) ((!(cfg)->p2p_supported) ? 0 : \
+ change_bit(WLP2P_STATUS_ ## stat, &(cfg)->p2p->status))
+#define p2p_on(cfg) ((cfg)->p2p->on)
+#define p2p_scan(cfg) ((cfg)->p2p->scan)
+#define p2p_is_on(cfg) ((cfg)->p2p && (cfg)->p2p->on)
+
+/* dword align allocation */
+#define WLC_IOCTL_MAXLEN 8192
+
+#define CFGP2P_ERROR_TEXT "CFGP2P-ERROR) "
+
+
+#define CFGP2P_ERR(args) \
+ do { \
+ if (wl_dbg_level & WL_DBG_ERR) { \
+ printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__); \
+ printk args; \
+ } \
+ } while (0)
+#define CFGP2P_INFO(args) \
+ do { \
+ if (wl_dbg_level & WL_DBG_INFO) { \
+ printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__); \
+ printk args; \
+ } \
+ } while (0)
+#define CFGP2P_DBG(args) \
+ do { \
+ if (wl_dbg_level & WL_DBG_DBG) { \
+ printk(KERN_DEBUG "CFGP2P-DEBUG) %s :", __func__); \
+ printk args; \
+ } \
+ } while (0)
+
+#define CFGP2P_ACTION(args) \
+ do { \
+ if (wl_dbg_level & WL_DBG_P2P_ACTION) { \
+ printk(KERN_DEBUG "CFGP2P-ACTION) %s :", __func__); \
+ printk args; \
+ } \
+ } while (0)
+#define INIT_TIMER(timer, func, duration, extra_delay) \
+ do { \
+ init_timer(timer); \
+ timer->function = func; \
+ timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \
+ timer->data = (unsigned long) cfg; \
+ add_timer(timer); \
+ } while (0);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) && !defined(WL_CFG80211_P2P_DEV_IF)
+#define WL_CFG80211_P2P_DEV_IF
+
+#ifdef WL_ENABLE_P2P_IF
+#undef WL_ENABLE_P2P_IF
+#endif
+
+#ifdef WL_SUPPORT_BACKPORTED_KPATCHES
+#undef WL_SUPPORT_BACKPORTED_KPATCHES
+#endif
+#endif /* (LINUX_VERSION >= VERSION(3, 8, 0)) */
+
+#ifndef WL_CFG80211_P2P_DEV_IF
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+#if defined(WL_ENABLE_P2P_IF) && (defined(WL_CFG80211_P2P_DEV_IF) || \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)))
+#error Disable 'WL_ENABLE_P2P_IF', if 'WL_CFG80211_P2P_DEV_IF' is enabled \
+ or kernel version is 3.8.0 or above
+#endif /* WL_ENABLE_P2P_IF && (WL_CFG80211_P2P_DEV_IF || (LINUX_VERSION >= VERSION(3, 8, 0))) */
+
+#if !defined(WLP2P) && (defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF))
+#error WLP2P not defined
+#endif /* !WLP2P && (WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF) */
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#define bcm_struct_cfgdev struct wireless_dev
+#else
+#define bcm_struct_cfgdev struct net_device
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+extern void
+wl_cfgp2p_listen_expired(unsigned long data);
+extern bool
+wl_cfgp2p_is_pub_action(void *frame, u32 frame_len);
+extern bool
+wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len);
+extern bool
+wl_cfgp2p_is_gas_action(void *frame, u32 frame_len);
+extern bool
+wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len);
+extern bool
+wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len);
+extern void
+wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel);
+extern s32
+wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg);
+extern void
+wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg);
+extern s32
+wl_cfgp2p_set_firm_p2p(struct bcm_cfg80211 *cfg);
+extern s32
+wl_cfgp2p_set_p2p_mode(struct bcm_cfg80211 *cfg, u8 mode,
+ u32 channel, u16 listen_ms, int bssidx);
+extern s32
+wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
+ chanspec_t chspec);
+extern s32
+wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac);
+extern s32
+wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac);
+extern s32
+wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type, chanspec_t chspec);
+
+extern s32
+wl_cfgp2p_ifidx(struct bcm_cfg80211 *cfg, struct ether_addr *mac, s32 *index);
+
+extern s32
+wl_cfgp2p_init_discovery(struct bcm_cfg80211 *cfg);
+extern s32
+wl_cfgp2p_enable_discovery(struct bcm_cfg80211 *cfg, struct net_device *dev, const u8 *ie,
+ u32 ie_len);
+extern s32
+wl_cfgp2p_disable_discovery(struct bcm_cfg80211 *cfg);
+extern s32
+wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active, u32 num_chans,
+ u16 *channels,
+ s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
+ p2p_scan_purpose_t p2p_scan_purpose);
+
+extern s32
+wl_cfgp2p_act_frm_search(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr);
+
+extern wpa_ie_fixed_t *
+wl_cfgp2p_find_wpaie(u8 *parse, u32 len);
+
+extern wpa_ie_fixed_t *
+wl_cfgp2p_find_wpsie(u8 *parse, u32 len);
+
+extern wifi_p2p_ie_t *
+wl_cfgp2p_find_p2pie(u8 *parse, u32 len);
+
+extern wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(u8 *parse, u32 len);
+
+extern struct net_device *
+wl_cfgp2p_find_ndev(struct bcm_cfg80211 *cfg, s32 bssidx);
+extern s32
+wl_cfgp2p_find_type(struct bcm_cfg80211 *cfg, s32 bssidx, s32 *type);
+
+
+extern s32
+wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data);
+extern s32
+wl_cfgp2p_discover_listen(struct bcm_cfg80211 *cfg, s32 channel, u32 duration_ms);
+
+extern s32
+wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable);
+
+extern s32
+wl_cfgp2p_action_tx_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+ const wl_event_msg_t *e, void *data);
+
+extern s32
+wl_cfgp2p_tx_action_frame(struct bcm_cfg80211 *cfg, struct net_device *dev,
+ wl_af_params_t *af_params, s32 bssidx);
+
+extern void
+wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr, struct ether_addr *out_dev_addr,
+ struct ether_addr *out_int_addr);
+
+extern void
+wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id);
+extern bool
+wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx);
+
+extern s32
+wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 up);
+
+
+extern s32
+wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev);
+
+extern s32
+wl_cfgp2p_down(struct bcm_cfg80211 *cfg);
+
+extern s32
+wl_cfgp2p_set_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len);
+
+extern s32
+wl_cfgp2p_get_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len);
+
+extern s32
+wl_cfgp2p_set_p2p_ps(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len);
+
+extern u8 *
+wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id);
+
+extern u8*
+wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib);
+
+extern u8 *
+wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length);
+
+extern s32
+wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg);
+
+extern s32
+wl_cfgp2p_unregister_ndev(struct bcm_cfg80211 *cfg);
+
+extern bool
+wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops);
+
+extern u32
+wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
+ s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd);
+
+extern
+int wl_cfgp2p_vif_created(struct bcm_cfg80211 *cfg);
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+extern struct wireless_dev *
+wl_cfgp2p_add_p2p_disc_if(struct bcm_cfg80211 *cfg);
+
+extern int
+wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+
+extern void
+wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+
+extern int
+wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev, struct bcm_cfg80211 *cfg);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
+extern void
+wl_cfgp2p_need_wait_actfrmae(struct bcm_cfg80211 *cfg, void *frame, u32 frame_len, bool tx);
+
+extern int
+wl_cfgp2p_is_p2p_specific_scan(struct cfg80211_scan_request *request);
+
+/* WiFi Direct */
+#define SOCIAL_CHAN_1 1
+#define SOCIAL_CHAN_2 6
+#define SOCIAL_CHAN_3 11
+#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \
+ (channel == SOCIAL_CHAN_2) || \
+ (channel == SOCIAL_CHAN_3))
+#define SOCIAL_CHAN_CNT 3
+#define AF_PEER_SEARCH_CNT 2
+#define WL_P2P_WILDCARD_SSID "DIRECT-"
+#define WL_P2P_WILDCARD_SSID_LEN 7
+#define WL_P2P_INTERFACE_PREFIX "p2p"
+#define WL_P2P_TEMP_CHAN 11
+#define WL_P2P_AF_STATUS_OFFSET 9
+
+/* If the provision discovery is for JOIN operations,
+ * or the device discoverablity frame is destined to GO
+ * then we need not do an internal scan to find GO.
+ */
+#define IS_ACTPUB_WITHOUT_GROUP_ID(p2p_ie, len) \
+ (wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID) == NULL)
+
+#define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \
+ ((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \
+ (frame->action == P2PSD_ACTION_ID_GAS_CREQ)))
+
+#define IS_P2P_PUB_ACT_RSP_SUBTYPE(subtype) ((subtype == P2P_PAF_GON_RSP) || \
+ ((subtype == P2P_PAF_GON_CONF) || \
+ (subtype == P2P_PAF_INVITE_RSP) || \
+ (subtype == P2P_PAF_PROVDIS_RSP)))
+#define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3))
+#define IS_P2P_SSID(ssid, len) (!memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) && \
+ (len == WL_P2P_WILDCARD_SSID_LEN))
+#endif /* _wl_cfgp2p_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
new file mode 100644
index 000000000000..c17a49e137b2
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
@@ -0,0 +1,201 @@
+/*
+ * Linux cfg80211 Vendor Extension Code
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfgvendor.c 455257 2014-02-13 08:10:24Z $
+*/
+
+/*
+ * New vendor interface additon to nl80211/cfg80211 to allow vendors
+ * to implement proprietary features over the cfg80211 stack.
+*/
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+#include <linux/kernel.h>
+
+#include <bcmutils.h>
+#include <bcmwifi_channels.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+#include <proto/802.11.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhdioctl.h>
+#include <wlioctl.h>
+#include <dhd_cfg80211.h>
+#ifdef PNO_SUPPORT
+#include <dhd_pno.h>
+#endif /* PNO_SUPPORT */
+
+#include <proto/ethernet.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/wait.h>
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+
+#include <wlioctl.h>
+#include <wldev_common.h>
+#include <wl_cfg80211.h>
+#include <wl_cfgp2p.h>
+#include <wl_android.h>
+#include <wl_cfgvendor.h>
+#ifdef PROP_TXSTATUS
+#include <dhd_wlfc.h>
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+/*
+ * This API is to be used for asynchronous vendor events. This
+ * shouldn't be used in response to a vendor command from its
+ * do_it handler context (instead wl_cfgvendor_send_cmd_reply should
+ * be used).
+ */
+int wl_cfgvendor_send_async_event(struct wiphy *wiphy,
+ struct net_device *dev, int event_id, const void *data, int len)
+{
+ u16 kflags;
+ struct sk_buff *skb;
+
+ kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+
+ /* Alloc the SKB for vendor_event */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+ skb = cfg80211_vendor_event_alloc(wiphy, NULL, len, event_id, kflags);
+#else
+ skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, kflags);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
+ if (!skb) {
+ WL_ERR(("skb alloc failed"));
+ return -ENOMEM;
+ }
+
+ /* Push the data to the skb */
+ nla_put_nohdr(skb, len, data);
+
+ cfg80211_vendor_event(skb, kflags);
+
+ return 0;
+}
+
+static int wl_cfgvendor_send_cmd_reply(struct wiphy *wiphy,
+ struct net_device *dev, const void *data, int len)
+{
+ struct sk_buff *skb;
+
+ /* Alloc the SKB for vendor_event */
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
+ if (unlikely(!skb)) {
+ WL_ERR(("skb alloc failed"));
+ return -ENOMEM;
+ }
+
+ /* Push the data to the skb */
+ nla_put_nohdr(skb, len, data);
+
+ return cfg80211_vendor_cmd_reply(skb);
+}
+
+static int wl_cfgvendor_priv_string_handler(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int len)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ int err = 0;
+ int data_len = 0;
+
+ WL_INFO(("%s: Enter \n", __func__));
+
+ bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
+
+ if (strncmp((char *)data, BRCM_VENDOR_SCMD_CAPA, strlen(BRCM_VENDOR_SCMD_CAPA)) == 0) {
+ err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "cap", NULL, 0,
+ cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ data_len = strlen(cfg->ioctl_buf);
+ cfg->ioctl_buf[data_len] = '\0';
+ }
+
+ err = wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
+ cfg->ioctl_buf, data_len+1);
+ if (unlikely(err))
+ WL_ERR(("Vendor Command reply failed ret:%d \n", err));
+ else
+ WL_INFO(("Vendor Command reply sent successfully!\n"));
+
+ return err;
+}
+
+static const struct wiphy_vendor_command wl_vendor_cmds [] = {
+ {
+ {
+ .vendor_id = OUI_BRCM,
+ .subcmd = BRCM_VENDOR_SCMD_PRIV_STR
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_priv_string_handler
+ },
+};
+
+static const struct nl80211_vendor_cmd_info wl_vendor_events [] = {
+ { OUI_BRCM, BRCM_VENDOR_EVENT_UNSPEC },
+ { OUI_BRCM, BRCM_VENDOR_EVENT_PRIV_STR },
+};
+
+int wl_cfgvendor_attach(struct wiphy *wiphy)
+{
+
+ WL_INFO(("Vendor: Register BRCM cfg80211 vendor cmd(0x%x) interface \n",
+ NL80211_CMD_VENDOR));
+
+ wiphy->vendor_commands = wl_vendor_cmds;
+ wiphy->n_vendor_commands = ARRAY_SIZE(wl_vendor_cmds);
+ wiphy->vendor_events = wl_vendor_events;
+ wiphy->n_vendor_events = ARRAY_SIZE(wl_vendor_events);
+
+ return 0;
+}
+
+int wl_cfgvendor_detach(struct wiphy *wiphy)
+{
+ WL_INFO(("Vendor: Unregister BRCM cfg80211 vendor interface \n"));
+
+ wiphy->vendor_commands = NULL;
+ wiphy->vendor_events = NULL;
+ wiphy->n_vendor_commands = 0;
+ wiphy->n_vendor_events = 0;
+
+ return 0;
+}
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.h b/drivers/net/wireless/bcmdhd/wl_cfgvendor.h
new file mode 100644
index 000000000000..349a9f145698
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.h
@@ -0,0 +1,56 @@
+/*
+ * Linux cfg80211 Vendor Extension Code
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_cfgvendor.h 455257 2014-02-13 08:10:24Z $
+ */
+
+/*
+ * New vendor interface additon to nl80211/cfg80211 to allow vendors
+ * to implement proprietary features over the cfg80211 stack.
+ */
+
+#ifndef _wl_cfgvendor_h_
+#define _wl_cfgvendor_h_
+
+#define OUI_BRCM 0x001018
+#define BRCM_VENDOR_SUBCMD_PRIV_STR 1
+
+enum wl_vendor_subcmd {
+ BRCM_VENDOR_SCMD_UNSPEC,
+ BRCM_VENDOR_SCMD_PRIV_STR
+};
+
+enum wl_vendor_event {
+ BRCM_VENDOR_EVENT_UNSPEC,
+ BRCM_VENDOR_EVENT_PRIV_STR
+};
+
+/* Capture the BRCM_VENDOR_SUBCMD_PRIV_STRINGS* here */
+#define BRCM_VENDOR_SCMD_CAPA "cap"
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
+extern int wl_cfgvendor_attach(struct wiphy *wiphy);
+extern int wl_cfgvendor_detach(struct wiphy *wiphy);
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
+
+#endif /* _wl_cfgvendor_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_dbg.h b/drivers/net/wireless/bcmdhd/wl_dbg.h
new file mode 100644
index 000000000000..cddd29bbdde0
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_dbg.h
@@ -0,0 +1,67 @@
+/*
+ * Minimal debug/trace/assert driver definitions for
+ * Broadcom 802.11 Networking Adapter.
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_dbg.h 430628 2013-10-19 04:07:25Z $
+ */
+
+
+#ifndef _wl_dbg_h_
+#define _wl_dbg_h_
+
+/* wl_msg_level is a bit vector with defs in wlioctl.h */
+extern uint32 wl_msg_level;
+extern uint32 wl_msg_level2;
+
+#define WL_TIMESTAMP()
+
+#define WL_PRINT(args) do { WL_TIMESTAMP(); printf args; } while (0)
+
+#if defined(EVENT_LOG_COMPILE) && defined(WLMSG_SRSCAN)
+#define _WL_SRSCAN(fmt, ...) EVENT_LOG(EVENT_LOG_TAG_SRSCAN, fmt, ##__VA_ARGS__)
+#define WL_SRSCAN(args) _WL_SRSCAN args
+#else
+#define WL_SRSCAN(args)
+#endif
+
+
+/* To disable a message completely ... until you need it again */
+#define WL_NONE(args)
+
+#define WL_ERROR(args)
+#define WL_TRACE(args)
+#define WL_APSTA_UPDN(args)
+#define WL_APSTA_RX(args)
+#ifdef WLMSG_WSEC
+#define WL_WSEC(args) WL_PRINT(args)
+#define WL_WSEC_DUMP(args) WL_PRINT(args)
+#else
+#define WL_WSEC(args)
+#define WL_WSEC_DUMP(args)
+#endif
+#define WL_PCIE(args) do {if (wl_msg_level2 & WL_PCIE_VAL) WL_PRINT(args);} while (0)
+#define WL_PCIE_ON() (wl_msg_level2 & WL_PCIE_VAL)
+
+extern uint32 wl_msg_level;
+extern uint32 wl_msg_level2;
+#endif /* _wl_dbg_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
new file mode 100644
index 000000000000..a14e57155ae9
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -0,0 +1,3689 @@
+/*
+ * Linux Wireless Extensions support
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_iw.c 425990 2013-09-26 07:28:16Z $
+ */
+
+#if defined(USE_IW)
+#define LINUX_PORT
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+typedef const struct si_pub si_t;
+#include <wlioctl.h>
+
+
+#include <wl_dbg.h>
+#include <wl_iw.h>
+
+
+/* Broadcom extensions to WEXT, linux upstream has obsoleted WEXT */
+#ifndef IW_AUTH_KEY_MGMT_FT_802_1X
+#define IW_AUTH_KEY_MGMT_FT_802_1X 0x04
+#endif
+
+#ifndef IW_AUTH_KEY_MGMT_FT_PSK
+#define IW_AUTH_KEY_MGMT_FT_PSK 0x08
+#endif
+
+#ifndef IW_ENC_CAPA_FW_ROAM_ENABLE
+#define IW_ENC_CAPA_FW_ROAM_ENABLE 0x00000020
+#endif
+
+
+/* FC9: wireless.h 2.6.25-14.fc9.i686 is missing these, even though WIRELESS_EXT is set to latest
+ * version 22.
+ */
+#ifndef IW_ENCODE_ALG_PMK
+#define IW_ENCODE_ALG_PMK 4
+#endif
+#ifndef IW_ENC_CAPA_4WAY_HANDSHAKE
+#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010
+#endif
+/* End FC9. */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+#include <linux/rtnetlink.h>
+#endif
+#if defined(SOFTAP)
+struct net_device *ap_net_dev = NULL;
+tsk_ctl_t ap_eth_ctl; /* apsta AP netdev waiter thread */
+#endif /* SOFTAP */
+
+extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
+ uint32 reason, char* stringBuf, uint buflen);
+
+uint wl_msg_level = WL_ERROR_VAL;
+
+#define MAX_WLIW_IOCTL_LEN 1024
+
+/* IOCTL swapping mode for Big Endian host with Little Endian dongle. Default to off */
+#define htod32(i) (i)
+#define htod16(i) (i)
+#define dtoh32(i) (i)
+#define dtoh16(i) (i)
+#define htodchanspec(i) (i)
+#define dtohchanspec(i) (i)
+
+extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
+extern int dhd_wait_pend8021x(struct net_device *dev);
+
+#if WIRELESS_EXT < 19
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
+#endif /* WIRELESS_EXT < 19 */
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#define DAEMONIZE(a) do { \
+ allow_signal(SIGKILL); \
+ allow_signal(SIGTERM); \
+ } while (0)
+#elif ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)))
+#define DAEMONIZE(a) daemonize(a); \
+ allow_signal(SIGKILL); \
+ allow_signal(SIGTERM);
+#else /* Linux 2.4 (w/o preemption patch) */
+#define RAISE_RX_SOFTIRQ() \
+ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
+#define DAEMONIZE(a) daemonize(); \
+ do { if (a) \
+ strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \
+ } while (0);
+#endif /* LINUX_VERSION_CODE */
+
+#define ISCAN_STATE_IDLE 0
+#define ISCAN_STATE_SCANING 1
+
+/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */
+#define WLC_IW_ISCAN_MAXLEN 2048
+typedef struct iscan_buf {
+ struct iscan_buf * next;
+ char iscan_buf[WLC_IW_ISCAN_MAXLEN];
+} iscan_buf_t;
+
+typedef struct iscan_info {
+ struct net_device *dev;
+ struct timer_list timer;
+ uint32 timer_ms;
+ uint32 timer_on;
+ int iscan_state;
+ iscan_buf_t * list_hdr;
+ iscan_buf_t * list_cur;
+
+ /* Thread to work on iscan */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
+ struct task_struct *kthread;
+#endif
+ long sysioc_pid;
+ struct semaphore sysioc_sem;
+ struct completion sysioc_exited;
+
+
+ char ioctlbuf[WLC_IOCTL_SMLEN];
+} iscan_info_t;
+iscan_info_t *g_iscan = NULL;
+static void wl_iw_timerfunc(ulong data);
+static void wl_iw_set_event_mask(struct net_device *dev);
+static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action);
+
+/* priv_link becomes netdev->priv and is the link between netdev and wlif struct */
+typedef struct priv_link {
+ wl_iw_t *wliw;
+} priv_link_t;
+
+/* dev to priv_link */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#define WL_DEV_LINK(dev) (priv_link_t*)(dev->priv)
+#else
+#define WL_DEV_LINK(dev) (priv_link_t*)netdev_priv(dev)
+#endif
+
+/* dev to wl_iw_t */
+#define IW_DEV_IF(dev) ((wl_iw_t*)(WL_DEV_LINK(dev))->wliw)
+
+static void swap_key_from_BE(
+ wl_wsec_key_t *key
+)
+{
+ key->index = htod32(key->index);
+ key->len = htod32(key->len);
+ key->algo = htod32(key->algo);
+ key->flags = htod32(key->flags);
+ key->rxiv.hi = htod32(key->rxiv.hi);
+ key->rxiv.lo = htod16(key->rxiv.lo);
+ key->iv_initialized = htod32(key->iv_initialized);
+}
+
+static void swap_key_to_BE(
+ wl_wsec_key_t *key
+)
+{
+ key->index = dtoh32(key->index);
+ key->len = dtoh32(key->len);
+ key->algo = dtoh32(key->algo);
+ key->flags = dtoh32(key->flags);
+ key->rxiv.hi = dtoh32(key->rxiv.hi);
+ key->rxiv.lo = dtoh16(key->rxiv.lo);
+ key->iv_initialized = dtoh32(key->iv_initialized);
+}
+
+static int
+dev_wlc_ioctl(
+ struct net_device *dev,
+ int cmd,
+ void *arg,
+ int len
+)
+{
+ struct ifreq ifr;
+ wl_ioctl_t ioc;
+ mm_segment_t fs;
+ int ret;
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+
+ strcpy(ifr.ifr_name, dev->name);
+ ifr.ifr_data = (caddr_t) &ioc;
+
+ fs = get_fs();
+ set_fs(get_ds());
+#if defined(WL_USE_NETDEV_OPS)
+ ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#else
+ ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#endif
+ set_fs(fs);
+
+ return ret;
+}
+
+/*
+set named driver variable to int value and return error indication
+calling example: dev_wlc_intvar_set(dev, "arate", rate)
+*/
+
+static int
+dev_wlc_intvar_set(
+ struct net_device *dev,
+ char *name,
+ int val)
+{
+ char buf[WLC_IOCTL_SMLEN];
+ uint len;
+
+ val = htod32(val);
+ len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+ ASSERT(len);
+
+ return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
+}
+
+static int
+dev_iw_iovar_setbuf(
+ struct net_device *dev,
+ char *iovar,
+ void *param,
+ int paramlen,
+ void *bufptr,
+ int buflen)
+{
+ int iolen;
+
+ iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ ASSERT(iolen);
+ BCM_REFERENCE(iolen);
+
+ return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen));
+}
+
+static int
+dev_iw_iovar_getbuf(
+ struct net_device *dev,
+ char *iovar,
+ void *param,
+ int paramlen,
+ void *bufptr,
+ int buflen)
+{
+ int iolen;
+
+ iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ ASSERT(iolen);
+ BCM_REFERENCE(iolen);
+
+ return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen));
+}
+
+#if WIRELESS_EXT > 17
+static int
+dev_wlc_bufvar_set(
+ struct net_device *dev,
+ char *name,
+ char *buf, int len)
+{
+ char *ioctlbuf;
+ uint buflen;
+ int error;
+
+ ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
+ if (!ioctlbuf)
+ return -ENOMEM;
+
+ buflen = bcm_mkiovar(name, buf, len, ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ ASSERT(buflen);
+ error = dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen);
+
+ kfree(ioctlbuf);
+ return error;
+}
+#endif /* WIRELESS_EXT > 17 */
+
+/*
+get named driver variable to int value and return error indication
+calling example: dev_wlc_bufvar_get(dev, "arate", &rate)
+*/
+
+static int
+dev_wlc_bufvar_get(
+ struct net_device *dev,
+ char *name,
+ char *buf, int buflen)
+{
+ char *ioctlbuf;
+ int error;
+
+ uint len;
+
+ ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
+ if (!ioctlbuf)
+ return -ENOMEM;
+ len = bcm_mkiovar(name, NULL, 0, ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ ASSERT(len);
+ BCM_REFERENCE(len);
+ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ if (!error)
+ bcopy(ioctlbuf, buf, buflen);
+
+ kfree(ioctlbuf);
+ return (error);
+}
+
+/*
+get named driver variable to int value and return error indication
+calling example: dev_wlc_intvar_get(dev, "arate", &rate)
+*/
+
+static int
+dev_wlc_intvar_get(
+ struct net_device *dev,
+ char *name,
+ int *retval)
+{
+ union {
+ char buf[WLC_IOCTL_SMLEN];
+ int val;
+ } var;
+ int error;
+
+ uint len;
+ uint data_null;
+
+ len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
+ ASSERT(len);
+ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
+
+ *retval = dtoh32(var.val);
+
+ return (error);
+}
+
+/* Maintain backward compatibility */
+#if WIRELESS_EXT < 13
+struct iw_request_info
+{
+ __u16 cmd; /* Wireless Extension command */
+ __u16 flags; /* More to come ;-) */
+};
+
+typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
+ void *wrqu, char *extra);
+#endif /* WIRELESS_EXT < 13 */
+
+#if WIRELESS_EXT > 12
+static int
+wl_iw_set_leddc(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int dc = *(int *)extra;
+ int error;
+
+ error = dev_wlc_intvar_set(dev, "leddc", dc);
+ return error;
+}
+
+static int
+wl_iw_set_vlanmode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int mode = *(int *)extra;
+ int error;
+
+ mode = htod32(mode);
+ error = dev_wlc_intvar_set(dev, "vlan_mode", mode);
+ return error;
+}
+
+static int
+wl_iw_set_pm(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int pm = *(int *)extra;
+ int error;
+
+ pm = htod32(pm);
+ error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+ return error;
+}
+
+#if WIRELESS_EXT > 17
+#endif /* WIRELESS_EXT > 17 */
+#endif /* WIRELESS_EXT > 12 */
+
+int
+wl_iw_send_priv_event(
+ struct net_device *dev,
+ char *flag
+)
+{
+ union iwreq_data wrqu;
+ char extra[IW_CUSTOM_MAX + 1];
+ int cmd;
+
+ cmd = IWEVCUSTOM;
+ memset(&wrqu, 0, sizeof(wrqu));
+ if (strlen(flag) > sizeof(extra))
+ return -1;
+
+ strcpy(extra, flag);
+ wrqu.data.length = strlen(extra);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
+
+ return 0;
+}
+
+static int
+wl_iw_config_commit(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ void *zwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+ struct sockaddr bssid;
+
+ WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid))))
+ return error;
+
+ ssid.SSID_len = dtoh32(ssid.SSID_len);
+
+ if (!ssid.SSID_len)
+ return 0;
+
+ bzero(&bssid, sizeof(struct sockaddr));
+ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
+ WL_ERROR(("%s: WLC_REASSOC failed (%d)\n", __FUNCTION__, error));
+ return error;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_name(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *cwrq,
+ char *extra
+)
+{
+ int phytype, err;
+ uint band[3];
+ char cap[5];
+
+ WL_TRACE(("%s: SIOCGIWNAME\n", dev->name));
+
+ cap[0] = 0;
+ if ((err = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))) < 0)
+ goto done;
+ if ((err = dev_wlc_ioctl(dev, WLC_GET_BANDLIST, band, sizeof(band))) < 0)
+ goto done;
+
+ band[0] = dtoh32(band[0]);
+ switch (phytype) {
+ case WLC_PHY_TYPE_A:
+ strcpy(cap, "a");
+ break;
+ case WLC_PHY_TYPE_B:
+ strcpy(cap, "b");
+ break;
+ case WLC_PHY_TYPE_LP:
+ case WLC_PHY_TYPE_G:
+ if (band[0] >= 2)
+ strcpy(cap, "abg");
+ else
+ strcpy(cap, "bg");
+ break;
+ case WLC_PHY_TYPE_N:
+ if (band[0] >= 2)
+ strcpy(cap, "abgn");
+ else
+ strcpy(cap, "bgn");
+ break;
+ }
+done:
+ snprintf(cwrq->name, IFNAMSIZ, "IEEE 802.11%s", cap);
+ return 0;
+}
+
+static int
+wl_iw_set_freq(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra
+)
+{
+ int error, chan;
+ uint sf = 0;
+
+ WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name));
+
+ /* Setting by channel number */
+ if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
+ chan = fwrq->m;
+ }
+
+ /* Setting by frequency */
+ else {
+ /* Convert to MHz as best we can */
+ if (fwrq->e >= 6) {
+ fwrq->e -= 6;
+ while (fwrq->e--)
+ fwrq->m *= 10;
+ } else if (fwrq->e < 6) {
+ while (fwrq->e++ < 6)
+ fwrq->m /= 10;
+ }
+ /* handle 4.9GHz frequencies as Japan 4 GHz based channelization */
+ if (fwrq->m > 4000 && fwrq->m < 5000)
+ sf = WF_CHAN_FACTOR_4_G; /* start factor for 4 GHz */
+
+ chan = wf_mhz2channel(fwrq->m, sf);
+ }
+ chan = htod32(chan);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
+ return error;
+
+ /* -EINPROGRESS: Call commit handler */
+ return -EINPROGRESS;
+}
+
+static int
+wl_iw_get_freq(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra
+)
+{
+ channel_info_t ci;
+ int error;
+
+ WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
+ return error;
+
+ /* Return radio channel in channel form */
+ fwrq->m = dtoh32(ci.hw_channel);
+ fwrq->e = dtoh32(0);
+ return 0;
+}
+
+static int
+wl_iw_set_mode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra
+)
+{
+ int infra = 0, ap = 0, error = 0;
+
+ WL_TRACE(("%s: SIOCSIWMODE\n", dev->name));
+
+ switch (*uwrq) {
+ case IW_MODE_MASTER:
+ infra = ap = 1;
+ break;
+ case IW_MODE_ADHOC:
+ case IW_MODE_AUTO:
+ break;
+ case IW_MODE_INFRA:
+ infra = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ infra = htod32(infra);
+ ap = htod32(ap);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
+ (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap))))
+ return error;
+
+ /* -EINPROGRESS: Call commit handler */
+ return -EINPROGRESS;
+}
+
+static int
+wl_iw_get_mode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra
+)
+{
+ int error, infra = 0, ap = 0;
+
+ WL_TRACE(("%s: SIOCGIWMODE\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap))))
+ return error;
+
+ infra = dtoh32(infra);
+ ap = dtoh32(ap);
+ *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
+
+ return 0;
+}
+
+static int
+wl_iw_get_range(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+ static int channels[MAXCHANNEL+1];
+ wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
+ wl_rateset_t rateset;
+ int error, i, k;
+ uint sf, ch;
+
+ int phytype;
+ int bw_cap = 0, sgi_tx = 0, nmode = 0;
+ channel_info_t ci;
+ uint8 nrate_list2copy = 0;
+ uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
+ {14, 29, 43, 58, 87, 116, 130, 144},
+ {27, 54, 81, 108, 162, 216, 243, 270},
+ {30, 60, 90, 120, 180, 240, 270, 300}};
+ int fbt_cap = 0;
+
+ WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ dwrq->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(*range));
+
+ /* We don't use nwids */
+ range->min_nwid = range->max_nwid = 0;
+
+ /* Set available channels/frequencies */
+ list->count = htod32(MAXCHANNEL);
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels))))
+ return error;
+ for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
+ range->freq[i].i = dtoh32(list->element[i]);
+
+ ch = dtoh32(list->element[i]);
+ if (ch <= CH_MAX_2G_CHANNEL)
+ sf = WF_CHAN_FACTOR_2_4_G;
+ else
+ sf = WF_CHAN_FACTOR_5_G;
+
+ range->freq[i].m = wf_channel2mhz(ch, sf);
+ range->freq[i].e = 6;
+ }
+ range->num_frequency = range->num_channels = i;
+
+ /* Link quality (use NDIS cutoffs) */
+ range->max_qual.qual = 5;
+ /* Signal level (use RSSI) */
+ range->max_qual.level = 0x100 - 200; /* -200 dBm */
+ /* Noise level (use noise) */
+ range->max_qual.noise = 0x100 - 200; /* -200 dBm */
+ /* Signal level threshold range (?) */
+ range->sensitivity = 65535;
+
+#if WIRELESS_EXT > 11
+ /* Link quality (use NDIS cutoffs) */
+ range->avg_qual.qual = 3;
+ /* Signal level (use RSSI) */
+ range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
+ /* Noise level (use noise) */
+ range->avg_qual.noise = 0x100 - 75; /* -75 dBm */
+#endif /* WIRELESS_EXT > 11 */
+
+ /* Set available bitrates */
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+ return error;
+ rateset.count = dtoh32(rateset.count);
+ range->num_bitrates = rateset.count;
+ for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
+ range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; /* convert to bps */
+ if ((error = dev_wlc_intvar_get(dev, "nmode", &nmode)))
+ return error;
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))))
+ return error;
+ if (nmode == 1 && ((phytype == WLC_PHY_TYPE_SSN) || (phytype == WLC_PHY_TYPE_LCN) ||
+ (phytype == WLC_PHY_TYPE_LCN40))) {
+ if ((error = dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap)))
+ return error;
+ if ((error = dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx)))
+ return error;
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t))))
+ return error;
+ ci.hw_channel = dtoh32(ci.hw_channel);
+
+ if (bw_cap == 0 ||
+ (bw_cap == 2 && ci.hw_channel <= 14)) {
+ if (sgi_tx == 0)
+ nrate_list2copy = 0;
+ else
+ nrate_list2copy = 1;
+ }
+ if (bw_cap == 1 ||
+ (bw_cap == 2 && ci.hw_channel >= 36)) {
+ if (sgi_tx == 0)
+ nrate_list2copy = 2;
+ else
+ nrate_list2copy = 3;
+ }
+ range->num_bitrates += 8;
+ ASSERT(range->num_bitrates < IW_MAX_BITRATES);
+ for (k = 0; i < range->num_bitrates; k++, i++) {
+ /* convert to bps */
+ range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
+ }
+ }
+
+ /* Set an indication of the max TCP throughput
+ * in bit/s that we can expect using this interface.
+ * May be use for QoS stuff... Jean II
+ */
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
+ return error;
+ i = dtoh32(i);
+ if (i == WLC_PHY_TYPE_A)
+ range->throughput = 24000000; /* 24 Mbits/s */
+ else
+ range->throughput = 1500000; /* 1.5 Mbits/s */
+
+ /* RTS and fragmentation thresholds */
+ range->min_rts = 0;
+ range->max_rts = 2347;
+ range->min_frag = 256;
+ range->max_frag = 2346;
+
+ range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
+ range->num_encoding_sizes = 4;
+ range->encoding_size[0] = WEP1_KEY_SIZE;
+ range->encoding_size[1] = WEP128_KEY_SIZE;
+#if WIRELESS_EXT > 17
+ range->encoding_size[2] = TKIP_KEY_SIZE;
+#else
+ range->encoding_size[2] = 0;
+#endif
+ range->encoding_size[3] = AES_KEY_SIZE;
+
+ /* Do not support power micro-management */
+ range->min_pmp = 0;
+ range->max_pmp = 0;
+ range->min_pmt = 0;
+ range->max_pmt = 0;
+ range->pmp_flags = 0;
+ range->pm_capa = 0;
+
+ /* Transmit Power - values are in mW */
+ range->num_txpower = 2;
+ range->txpower[0] = 1;
+ range->txpower[1] = 255;
+ range->txpower_capa = IW_TXPOW_MWATT;
+
+#if WIRELESS_EXT > 10
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 19;
+
+ /* Only support retry limits */
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->r_time_flags = 0;
+ /* SRL and LRL limits */
+ range->min_retry = 1;
+ range->max_retry = 255;
+ /* Retry lifetime limits unsupported */
+ range->min_r_time = 0;
+ range->max_r_time = 0;
+#endif /* WIRELESS_EXT > 10 */
+
+#if WIRELESS_EXT > 17
+ range->enc_capa = IW_ENC_CAPA_WPA;
+ range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
+ range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
+ range->enc_capa |= IW_ENC_CAPA_WPA2;
+
+ /* Determine driver FBT capability. */
+ if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) {
+ if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) {
+ /* Tell the host (e.g. wpa_supplicant) to let driver do the handshake */
+ range->enc_capa |= IW_ENC_CAPA_4WAY_HANDSHAKE;
+ }
+ }
+
+#ifdef BCMFW_ROAM_ENABLE_WEXT
+ /* Advertise firmware roam capability to the external supplicant */
+ range->enc_capa |= IW_ENC_CAPA_FW_ROAM_ENABLE;
+#endif /* BCMFW_ROAM_ENABLE_WEXT */
+
+ /* Event capability (kernel) */
+ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+ /* Event capability (driver) */
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
+
+#if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID)
+ /* FC7 wireless.h defines EXT 22 but doesn't define scan_capa bits */
+ range->scan_capa = IW_SCAN_CAPA_ESSID;
+#endif
+#endif /* WIRELESS_EXT > 17 */
+
+ return 0;
+}
+
+static int
+rssi_to_qual(int rssi)
+{
+ if (rssi <= WL_IW_RSSI_NO_SIGNAL)
+ return 0;
+ else if (rssi <= WL_IW_RSSI_VERY_LOW)
+ return 1;
+ else if (rssi <= WL_IW_RSSI_LOW)
+ return 2;
+ else if (rssi <= WL_IW_RSSI_GOOD)
+ return 3;
+ else if (rssi <= WL_IW_RSSI_VERY_GOOD)
+ return 4;
+ else
+ return 5;
+}
+
+static int
+wl_iw_set_spy(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ int i;
+
+ WL_TRACE(("%s: SIOCSIWSPY\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length);
+ for (i = 0; i < iw->spy_num; i++)
+ memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN);
+ memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
+
+ return 0;
+}
+
+static int
+wl_iw_get_spy(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
+ int i;
+
+ WL_TRACE(("%s: SIOCGIWSPY\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ dwrq->length = iw->spy_num;
+ for (i = 0; i < iw->spy_num; i++) {
+ memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN);
+ addr[i].sa_family = AF_UNIX;
+ memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
+ iw->spy_qual[i].updated = 0;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_set_wap(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ int error = -EINVAL;
+
+ WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
+
+ if (awrq->sa_family != ARPHRD_ETHER) {
+ WL_ERROR(("%s: Invalid Header...sa_family\n", __FUNCTION__));
+ return -EINVAL;
+ }
+
+ /* Ignore "auto" or "off" */
+ if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
+ scb_val_t scbval;
+ bzero(&scbval, sizeof(scb_val_t));
+ if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) {
+ WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error));
+ }
+ return 0;
+ }
+ /* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(awrq->sa_data),
+ * eabuf)));
+ */
+ /* Reassociate to the specified AP */
+ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) {
+ WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error));
+ return error;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_wap(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
+
+ awrq->sa_family = ARPHRD_ETHER;
+ memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
+
+ /* Ignore error (may be down or disassociated) */
+ (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static int
+wl_iw_mlme(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ struct iw_mlme *mlme;
+ scb_val_t scbval;
+ int error = -EINVAL;
+
+ WL_TRACE(("%s: SIOCSIWMLME\n", dev->name));
+
+ mlme = (struct iw_mlme *)extra;
+ if (mlme == NULL) {
+ WL_ERROR(("Invalid ioctl data.\n"));
+ return error;
+ }
+
+ scbval.val = mlme->reason_code;
+ bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN);
+
+ if (mlme->cmd == IW_MLME_DISASSOC) {
+ scbval.val = htod32(scbval.val);
+ error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
+ }
+ else if (mlme->cmd == IW_MLME_DEAUTH) {
+ scbval.val = htod32(scbval.val);
+ error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
+ sizeof(scb_val_t));
+ }
+ else {
+ WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__));
+ return error;
+ }
+
+ return error;
+}
+#endif /* WIRELESS_EXT > 17 */
+
+static int
+wl_iw_get_aplist(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_scan_results_t *list;
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ struct iw_quality qual[IW_MAX_AP];
+ wl_bss_info_t *bi = NULL;
+ int error, i;
+ uint buflen = dwrq->length;
+
+ WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ /* Get scan results (too large to put on the stack) */
+ list = kmalloc(buflen, GFP_KERNEL);
+ if (!list)
+ return -ENOMEM;
+ memset(list, 0, buflen);
+ list->buflen = htod32(buflen);
+ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
+ WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
+ kfree(list);
+ return error;
+ }
+ list->buflen = dtoh32(list->buflen);
+ list->version = dtoh32(list->version);
+ list->count = dtoh32(list->count);
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ buflen));
+
+ /* Infrastructure only */
+ if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+ continue;
+
+ /* BSSID */
+ memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ addr[dwrq->length].sa_family = ARPHRD_ETHER;
+ qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
+ qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+ qual[dwrq->length].noise = 0x100 + bi->phy_noise;
+
+ /* Updated qual, level, and noise */
+#if WIRELESS_EXT > 18
+ qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+#else
+ qual[dwrq->length].updated = 7;
+#endif /* WIRELESS_EXT > 18 */
+
+ dwrq->length++;
+ }
+
+ kfree(list);
+
+ if (dwrq->length) {
+ memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
+ /* Provided qual */
+ dwrq->flags = 1;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_iscan_get_aplist(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_scan_results_t *list;
+ iscan_buf_t * buf;
+ iscan_info_t *iscan = g_iscan;
+
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ struct iw_quality qual[IW_MAX_AP];
+ wl_bss_info_t *bi = NULL;
+ int i;
+
+ WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if ((!iscan) || (iscan->sysioc_pid < 0)) {
+ return wl_iw_get_aplist(dev, info, dwrq, extra);
+ }
+
+ buf = iscan->list_hdr;
+ /* Get scan results (too large to put on the stack) */
+ while (buf) {
+ list = &((wl_iscan_results_t*)buf->iscan_buf)->results;
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ bi = NULL;
+ for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ WLC_IW_ISCAN_MAXLEN));
+
+ /* Infrastructure only */
+ if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+ continue;
+
+ /* BSSID */
+ memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ addr[dwrq->length].sa_family = ARPHRD_ETHER;
+ qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
+ qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+ qual[dwrq->length].noise = 0x100 + bi->phy_noise;
+
+ /* Updated qual, level, and noise */
+#if WIRELESS_EXT > 18
+ qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+#else
+ qual[dwrq->length].updated = 7;
+#endif /* WIRELESS_EXT > 18 */
+
+ dwrq->length++;
+ }
+ buf = buf->next;
+ }
+ if (dwrq->length) {
+ memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
+ /* Provided qual */
+ dwrq->flags = 1;
+ }
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 13
+static int
+wl_iw_set_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+
+ WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
+
+ /* default Broadcast scan */
+ memset(&ssid, 0, sizeof(ssid));
+
+#if WIRELESS_EXT > 17
+ /* check for given essid */
+ if (wrqu->data.length == sizeof(struct iw_scan_req)) {
+ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
+ memcpy(ssid.SSID, req->essid, ssid.SSID_len);
+ ssid.SSID_len = htod32(ssid.SSID_len);
+ }
+ }
+#endif
+ /* Ignore error (most likely scan in progress) */
+ (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid));
+
+ return 0;
+}
+
+static int
+wl_iw_iscan_set_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ iscan_info_t *iscan = g_iscan;
+
+ WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
+
+ /* use backup if our thread is not successful */
+ if ((!iscan) || (iscan->sysioc_pid < 0)) {
+ return wl_iw_set_scan(dev, info, wrqu, extra);
+ }
+ if (iscan->iscan_state == ISCAN_STATE_SCANING) {
+ return 0;
+ }
+
+ /* default Broadcast scan */
+ memset(&ssid, 0, sizeof(ssid));
+
+#if WIRELESS_EXT > 17
+ /* check for given essid */
+ if (wrqu->data.length == sizeof(struct iw_scan_req)) {
+ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
+ memcpy(ssid.SSID, req->essid, ssid.SSID_len);
+ ssid.SSID_len = htod32(ssid.SSID_len);
+ }
+ }
+#endif
+
+ iscan->list_cur = iscan->list_hdr;
+ iscan->iscan_state = ISCAN_STATE_SCANING;
+
+
+ wl_iw_set_event_mask(dev);
+ wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+
+ iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
+ add_timer(&iscan->timer);
+ iscan->timer_on = 1;
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static bool
+ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
+{
+/* Is this body of this tlvs entry a WPA entry? If */
+/* not update the tlvs buffer pointer/length */
+ uint8 *ie = *wpaie;
+
+ /* If the contents match the WPA_OUI and type=1 */
+ if ((ie[1] >= 6) &&
+ !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
+ return TRUE;
+ }
+
+ /* point to the next ie */
+ ie += ie[1] + 2;
+ /* calculate the length of the rest of the buffer */
+ *tlvs_len -= (int)(ie - *tlvs);
+ /* update the pointer to the start of the buffer */
+ *tlvs = ie;
+ return FALSE;
+}
+
+static bool
+ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
+{
+/* Is this body of this tlvs entry a WPS entry? If */
+/* not update the tlvs buffer pointer/length */
+ uint8 *ie = *wpsie;
+
+ /* If the contents match the WPA_OUI and type=4 */
+ if ((ie[1] >= 4) &&
+ !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
+ return TRUE;
+ }
+
+ /* point to the next ie */
+ ie += ie[1] + 2;
+ /* calculate the length of the rest of the buffer */
+ *tlvs_len -= (int)(ie - *tlvs);
+ /* update the pointer to the start of the buffer */
+ *tlvs = ie;
+ return FALSE;
+}
+#endif /* WIRELESS_EXT > 17 */
+
+
+static int
+wl_iw_handle_scanresults_ies(char **event_p, char *end,
+ struct iw_request_info *info, wl_bss_info_t *bi)
+{
+#if WIRELESS_EXT > 17
+ struct iw_event iwe;
+ char *event;
+
+ event = *event_p;
+ if (bi->ie_length) {
+ /* look for wpa/rsn ies in the ie list... */
+ bcm_tlv_t *ie;
+ uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ int ptr_len = bi->ie_length;
+
+ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ }
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+
+ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_MDIE_ID))) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ }
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+ /* look for WPS IE */
+ if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ ptr_len = bi->ie_length;
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+ if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ *event_p = event;
+ }
+
+#endif /* WIRELESS_EXT > 17 */
+ return 0;
+}
+static int
+wl_iw_get_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ channel_info_t ci;
+ wl_scan_results_t *list;
+ struct iw_event iwe;
+ wl_bss_info_t *bi = NULL;
+ int error, i, j;
+ char *event = extra, *end = extra + dwrq->length, *value;
+ uint buflen = dwrq->length;
+
+ WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ /* Check for scan in progress */
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
+ return error;
+ ci.scan_channel = dtoh32(ci.scan_channel);
+ if (ci.scan_channel)
+ return -EAGAIN;
+
+ /* Get scan results (too large to put on the stack) */
+ list = kmalloc(buflen, GFP_KERNEL);
+ if (!list)
+ return -ENOMEM;
+ memset(list, 0, buflen);
+ list->buflen = htod32(buflen);
+ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
+ kfree(list);
+ return error;
+ }
+ list->buflen = dtoh32(list->buflen);
+ list->version = dtoh32(list->version);
+ list->count = dtoh32(list->count);
+
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ buflen));
+
+ /* First entry must be the BSSID */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
+
+ /* SSID */
+ iwe.u.data.length = dtoh32(bi->SSID_len);
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
+
+ /* Mode */
+ if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+ iwe.cmd = SIOCGIWMODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+ iwe.u.mode = IW_MODE_INFRA;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
+ }
+
+ /* Channel */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
+ CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
+ iwe.u.freq.e = 6;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
+
+ /* Channel quality */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
+ iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+ iwe.u.qual.noise = 0x100 + bi->phy_noise;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
+
+ /* WPA, WPA2, WPS, WAPI IEs */
+ wl_iw_handle_scanresults_ies(&event, end, info, bi);
+
+ /* Encryption */
+ iwe.cmd = SIOCGIWENCODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
+
+ /* Rates */
+ if (bi->rateset.count) {
+ value = event + IW_EV_LCP_LEN;
+ iwe.cmd = SIOCGIWRATE;
+ /* Those two flags are ignored... */
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+ for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
+ iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
+ value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+ event = value;
+ }
+ }
+
+ kfree(list);
+
+ dwrq->length = event - extra;
+ dwrq->flags = 0; /* todo */
+
+ return 0;
+}
+
+static int
+wl_iw_iscan_get_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_scan_results_t *list;
+ struct iw_event iwe;
+ wl_bss_info_t *bi = NULL;
+ int ii, j;
+ int apcnt;
+ char *event = extra, *end = extra + dwrq->length, *value;
+ iscan_info_t *iscan = g_iscan;
+ iscan_buf_t * p_buf;
+
+ WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ /* use backup if our thread is not successful */
+ if ((!iscan) || (iscan->sysioc_pid < 0)) {
+ return wl_iw_get_scan(dev, info, dwrq, extra);
+ }
+
+ /* Check for scan in progress */
+ if (iscan->iscan_state == ISCAN_STATE_SCANING)
+ return -EAGAIN;
+
+ apcnt = 0;
+ p_buf = iscan->list_hdr;
+ /* Get scan results */
+ while (p_buf != iscan->list_cur) {
+ list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
+
+ if (list->version != WL_BSS_INFO_VERSION) {
+ WL_ERROR(("list->version %d != WL_BSS_INFO_VERSION\n", list->version));
+ }
+
+ bi = NULL;
+ for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ WLC_IW_ISCAN_MAXLEN));
+
+ /* overflow check cover fields before wpa IEs */
+ if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
+ IW_EV_QUAL_LEN >= end)
+ return -E2BIG;
+ /* First entry must be the BSSID */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
+
+ /* SSID */
+ iwe.u.data.length = dtoh32(bi->SSID_len);
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
+
+ /* Mode */
+ if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+ iwe.cmd = SIOCGIWMODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+ iwe.u.mode = IW_MODE_INFRA;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
+ }
+
+ /* Channel */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
+ CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
+ iwe.u.freq.e = 6;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
+
+ /* Channel quality */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
+ iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+ iwe.u.qual.noise = 0x100 + bi->phy_noise;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
+
+ /* WPA, WPA2, WPS, WAPI IEs */
+ wl_iw_handle_scanresults_ies(&event, end, info, bi);
+
+ /* Encryption */
+ iwe.cmd = SIOCGIWENCODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
+
+ /* Rates */
+ if (bi->rateset.count <= sizeof(bi->rateset.rates)) {
+ if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
+ return -E2BIG;
+
+ value = event + IW_EV_LCP_LEN;
+ iwe.cmd = SIOCGIWRATE;
+ /* Those two flags are ignored... */
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+ for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
+ iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
+ value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+ event = value;
+ }
+ }
+ p_buf = p_buf->next;
+ } /* while (p_buf) */
+
+ dwrq->length = event - extra;
+ dwrq->flags = 0; /* todo */
+
+ return 0;
+}
+
+#endif /* WIRELESS_EXT > 13 */
+
+
+static int
+wl_iw_set_essid(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+
+ WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
+
+ /* default Broadcast SSID */
+ memset(&ssid, 0, sizeof(ssid));
+ if (dwrq->length && extra) {
+#if WIRELESS_EXT > 20
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length);
+#else
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1);
+#endif
+ memcpy(ssid.SSID, extra, ssid.SSID_len);
+ ssid.SSID_len = htod32(ssid.SSID_len);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))
+ return error;
+ }
+ /* If essid null then it is "iwconfig <interface> essid off" command */
+ else {
+ scb_val_t scbval;
+ bzero(&scbval, sizeof(scb_val_t));
+ if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t))))
+ return error;
+ }
+ return 0;
+}
+
+static int
+wl_iw_get_essid(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+
+ WL_TRACE(("%s: SIOCGIWESSID\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
+ WL_ERROR(("Error getting the SSID\n"));
+ return error;
+ }
+
+ ssid.SSID_len = dtoh32(ssid.SSID_len);
+
+ /* Get the current SSID */
+ memcpy(extra, ssid.SSID, ssid.SSID_len);
+
+ dwrq->length = ssid.SSID_len;
+
+ dwrq->flags = 1; /* active */
+
+ return 0;
+}
+
+static int
+wl_iw_set_nick(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ /* Check the size of the string */
+ if (dwrq->length > sizeof(iw->nickname))
+ return -E2BIG;
+
+ memcpy(iw->nickname, extra, dwrq->length);
+ iw->nickname[dwrq->length - 1] = '\0';
+
+ return 0;
+}
+
+static int
+wl_iw_get_nick(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ strcpy(extra, iw->nickname);
+ dwrq->length = strlen(extra) + 1;
+
+ return 0;
+}
+
+static int wl_iw_set_rate(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ wl_rateset_t rateset;
+ int error, rate, i, error_bg, error_a;
+
+ WL_TRACE(("%s: SIOCSIWRATE\n", dev->name));
+
+ /* Get current rateset */
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+ return error;
+
+ rateset.count = dtoh32(rateset.count);
+
+ if (vwrq->value < 0) {
+ /* Select maximum rate */
+ rate = rateset.rates[rateset.count - 1] & 0x7f;
+ } else if (vwrq->value < rateset.count) {
+ /* Select rate by rateset index */
+ rate = rateset.rates[vwrq->value] & 0x7f;
+ } else {
+ /* Specified rate in bps */
+ rate = vwrq->value / 500000;
+ }
+
+ if (vwrq->fixed) {
+ /*
+ Set rate override,
+ Since the is a/b/g-blind, both a/bg_rate are enforced.
+ */
+ error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
+ error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
+
+ if (error_bg && error_a)
+ return (error_bg | error_a);
+ } else {
+ /*
+ clear rate override
+ Since the is a/b/g-blind, both a/bg_rate are enforced.
+ */
+ /* 0 is for clearing rate override */
+ error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
+ /* 0 is for clearing rate override */
+ error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
+
+ if (error_bg && error_a)
+ return (error_bg | error_a);
+
+ /* Remove rates above selected rate */
+ for (i = 0; i < rateset.count; i++)
+ if ((rateset.rates[i] & 0x7f) > rate)
+ break;
+ rateset.count = htod32(i);
+
+ /* Set current rateset */
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset))))
+ return error;
+ }
+
+ return 0;
+}
+
+static int wl_iw_get_rate(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rate;
+
+ WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
+
+ /* Report the current tx rate */
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
+ return error;
+ rate = dtoh32(rate);
+ vwrq->value = rate * 500000;
+
+ return 0;
+}
+
+static int
+wl_iw_set_rts(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rts;
+
+ WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
+
+ if (vwrq->disabled)
+ rts = DOT11_DEFAULT_RTS_LEN;
+ else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
+ return -EINVAL;
+ else
+ rts = vwrq->value;
+
+ if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts)))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_rts(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rts;
+
+ WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
+
+ if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts)))
+ return error;
+
+ vwrq->value = rts;
+ vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+static int
+wl_iw_set_frag(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, frag;
+
+ WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
+
+ if (vwrq->disabled)
+ frag = DOT11_DEFAULT_FRAG_LEN;
+ else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
+ return -EINVAL;
+ else
+ frag = vwrq->value;
+
+ if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag)))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_frag(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, fragthreshold;
+
+ WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
+
+ if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold)))
+ return error;
+
+ vwrq->value = fragthreshold;
+ vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+static int
+wl_iw_set_txpow(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, disable;
+ uint16 txpwrmw;
+ WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
+
+ /* Make sure radio is off or on as far as software is concerned */
+ disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
+ disable += WL_RADIO_SW_DISABLE << 16;
+
+ disable = htod32(disable);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable))))
+ return error;
+
+ /* If Radio is off, nothing more to do */
+ if (disable & WL_RADIO_SW_DISABLE)
+ return 0;
+
+ /* Only handle mW */
+ if (!(vwrq->flags & IW_TXPOW_MWATT))
+ return -EINVAL;
+
+ /* Value < 0 means just "on" or "off" */
+ if (vwrq->value < 0)
+ return 0;
+
+ if (vwrq->value > 0xffff) txpwrmw = 0xffff;
+ else txpwrmw = (uint16)vwrq->value;
+
+
+ error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
+ return error;
+}
+
+static int
+wl_iw_get_txpow(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, disable, txpwrdbm;
+ uint8 result;
+
+ WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) ||
+ (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm)))
+ return error;
+
+ disable = dtoh32(disable);
+ result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
+ vwrq->value = (int32)bcm_qdbm_to_mw(result);
+ vwrq->fixed = 0;
+ vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
+ vwrq->flags = IW_TXPOW_MWATT;
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 10
+static int
+wl_iw_set_retry(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, lrl, srl;
+
+ WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
+
+ /* Do not handle "off" or "lifetime" */
+ if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
+ return -EINVAL;
+
+ /* Handle "[min|max] limit" */
+ if (vwrq->flags & IW_RETRY_LIMIT) {
+ /* "max limit" or just "limit" */
+#if WIRELESS_EXT > 20
+ if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
+ !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
+#else
+ if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
+#endif /* WIRELESS_EXT > 20 */
+
+ lrl = htod32(vwrq->value);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
+ return error;
+ }
+ /* "min limit" or just "limit" */
+#if WIRELESS_EXT > 20
+ if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
+ !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
+#else
+ if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
+#endif /* WIRELESS_EXT > 20 */
+
+ srl = htod32(vwrq->value);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_retry(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, lrl, srl;
+
+ WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
+
+ vwrq->disabled = 0; /* Can't be disabled */
+
+ /* Do not handle lifetime queries */
+ if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
+ return -EINVAL;
+
+ /* Get retry limits */
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl))))
+ return error;
+
+ lrl = dtoh32(lrl);
+ srl = dtoh32(srl);
+
+ /* Note : by default, display the min retry number */
+ if (vwrq->flags & IW_RETRY_MAX) {
+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+ vwrq->value = lrl;
+ } else {
+ vwrq->flags = IW_RETRY_LIMIT;
+ vwrq->value = srl;
+ if (srl != lrl)
+ vwrq->flags |= IW_RETRY_MIN;
+ }
+
+ return 0;
+}
+#endif /* WIRELESS_EXT > 10 */
+
+static int
+wl_iw_set_encode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error, val, wsec;
+
+ WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name));
+
+ memset(&key, 0, sizeof(key));
+
+ if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
+ /* Find the current key */
+ for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
+ val = htod32(key.index);
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ val = dtoh32(val);
+ if (val)
+ break;
+ }
+ /* Default to 0 */
+ if (key.index == DOT11_MAX_DEFAULT_KEYS)
+ key.index = 0;
+ } else {
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS)
+ return -EINVAL;
+ }
+
+ /* Interpret "off" to mean no encryption */
+ wsec = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
+
+ if ((error = dev_wlc_intvar_set(dev, "wsec", wsec)))
+ return error;
+
+ /* Old API used to pass a NULL pointer instead of IW_ENCODE_NOKEY */
+ if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
+ /* Just select a new current key */
+ val = htod32(key.index);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ } else {
+ key.len = dwrq->length;
+
+ if (dwrq->length > sizeof(key.data))
+ return -EINVAL;
+
+ memcpy(key.data, extra, dwrq->length);
+
+ key.flags = WL_PRIMARY_KEY;
+ switch (key.len) {
+ case WEP1_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_WEP1;
+ break;
+ case WEP128_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+ case TKIP_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_TKIP;
+ break;
+#endif
+ case AES_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Set the new key/index */
+ swap_key_from_BE(&key);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))
+ return error;
+ }
+
+ /* Interpret "restricted" to mean shared key authentication */
+ val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
+ val = htod32(val);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_encode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error, val, wsec, auth;
+
+ WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name));
+
+ /* assure default values of zero for things we don't touch */
+ bzero(&key, sizeof(wl_wsec_key_t));
+
+ if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
+ /* Find the current key */
+ for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
+ val = key.index;
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ val = dtoh32(val);
+ if (val)
+ break;
+ }
+ } else
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS)
+ key.index = 0;
+
+ /* Get info */
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth))))
+ return error;
+
+ swap_key_to_BE(&key);
+
+ wsec = dtoh32(wsec);
+ auth = dtoh32(auth);
+ /* Get key length */
+ dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len);
+
+ /* Get flags */
+ dwrq->flags = key.index + 1;
+ if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) {
+ /* Interpret "off" to mean no encryption */
+ dwrq->flags |= IW_ENCODE_DISABLED;
+ }
+ if (auth) {
+ /* Interpret "restricted" to mean shared key authentication */
+ dwrq->flags |= IW_ENCODE_RESTRICTED;
+ }
+
+ /* Get key */
+ if (dwrq->length && extra)
+ memcpy(extra, key.data, dwrq->length);
+
+ return 0;
+}
+
+static int
+wl_iw_set_power(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, pm;
+
+ WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
+
+ pm = vwrq->disabled ? PM_OFF : PM_MAX;
+
+ pm = htod32(pm);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_power(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, pm;
+
+ WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))))
+ return error;
+
+ pm = dtoh32(pm);
+ vwrq->disabled = pm ? 0 : 1;
+ vwrq->flags = IW_POWER_ALL_R;
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static int
+wl_iw_set_wpaie(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *iwp,
+ char *extra
+)
+{
+ dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
+
+ return 0;
+}
+
+static int
+wl_iw_get_wpaie(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *iwp,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
+ iwp->length = 64;
+ dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
+ return 0;
+}
+
+static int
+wl_iw_set_encodeext(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error;
+ struct iw_encode_ext *iwe;
+
+ WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
+
+ memset(&key, 0, sizeof(key));
+ iwe = (struct iw_encode_ext *)extra;
+
+ /* disable encryption completely */
+ if (dwrq->flags & IW_ENCODE_DISABLED) {
+
+ }
+
+ /* get the key index */
+ key.index = 0;
+ if (dwrq->flags & IW_ENCODE_INDEX)
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+ key.len = iwe->key_len;
+
+ /* Instead of bcast for ea address for default wep keys, driver needs it to be Null */
+ if (!ETHER_ISMULTI(iwe->addr.sa_data))
+ bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN);
+
+ /* check for key index change */
+ if (key.len == 0) {
+ if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ WL_WSEC(("Changing the the primary Key to %d\n", key.index));
+ /* change the key index .... */
+ key.index = htod32(key.index);
+ error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
+ &key.index, sizeof(key.index));
+ if (error)
+ return error;
+ }
+ /* key delete */
+ else {
+ swap_key_from_BE(&key);
+ error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (error)
+ return error;
+ }
+ }
+ /* This case is used to allow an external 802.1x supplicant
+ * to pass the PMK to the in-driver supplicant for use in
+ * the 4-way handshake.
+ */
+ else if (iwe->alg == IW_ENCODE_ALG_PMK) {
+ int j;
+ wsec_pmk_t pmk;
+ char keystring[WSEC_MAX_PSK_LEN + 1];
+ char* charptr = keystring;
+ uint len;
+
+ /* copy the raw hex key to the appropriate format */
+ for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) {
+ sprintf(charptr, "%02x", iwe->key[j]);
+ charptr += 2;
+ }
+ len = strlen(keystring);
+ pmk.key_len = htod16(len);
+ bcopy(keystring, pmk.key, len);
+ pmk.flags = htod16(WSEC_PASSPHRASE);
+
+ error = dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk));
+ if (error)
+ return error;
+ }
+
+ else {
+ if (iwe->key_len > sizeof(key.data))
+ return -EINVAL;
+
+ WL_WSEC(("Setting the key index %d\n", key.index));
+ if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ WL_WSEC(("key is a Primary Key\n"));
+ key.flags = WL_PRIMARY_KEY;
+ }
+
+ bcopy((void *)iwe->key, key.data, iwe->key_len);
+
+ if (iwe->alg == IW_ENCODE_ALG_TKIP) {
+ uint8 keybuf[8];
+ bcopy(&key.data[24], keybuf, sizeof(keybuf));
+ bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
+ bcopy(keybuf, &key.data[16], sizeof(keybuf));
+ }
+
+ /* rx iv */
+ if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+ uchar *ivptr;
+ ivptr = (uchar *)iwe->rx_seq;
+ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
+ (ivptr[3] << 8) | ivptr[2];
+ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
+ key.iv_initialized = TRUE;
+ }
+
+ switch (iwe->alg) {
+ case IW_ENCODE_ALG_NONE:
+ key.algo = CRYPTO_ALGO_OFF;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (iwe->key_len == WEP1_KEY_SIZE)
+ key.algo = CRYPTO_ALGO_WEP1;
+ else
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ key.algo = CRYPTO_ALGO_TKIP;
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ break;
+ default:
+ break;
+ }
+ swap_key_from_BE(&key);
+
+ dhd_wait_pend8021x(dev);
+
+ error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (error)
+ return error;
+ }
+ return 0;
+}
+
+
+#if WIRELESS_EXT > 17
+struct {
+ pmkid_list_t pmkids;
+ pmkid_t foo[MAXPMKID-1];
+} pmkid_list;
+static int
+wl_iw_set_pmksa(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ struct iw_pmksa *iwpmksa;
+ uint i;
+ char eabuf[ETHER_ADDR_STR_LEN];
+ pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid;
+
+ WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name));
+ iwpmksa = (struct iw_pmksa *)extra;
+ bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
+ if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
+ WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
+ bzero((char *)&pmkid_list, sizeof(pmkid_list));
+ }
+ if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
+ pmkid_list_t pmkid, *pmkidptr;
+ pmkidptr = &pmkid;
+ bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
+ {
+ uint j;
+ WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
+ bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
+ WL_TRACE(("\n"));
+ }
+ for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
+ if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID,
+ ETHER_ADDR_LEN))
+ break;
+ for (; i < pmkid_list.pmkids.npmkid; i++) {
+ bcopy(&pmkid_array[i+1].BSSID,
+ &pmkid_array[i].BSSID,
+ ETHER_ADDR_LEN);
+ bcopy(&pmkid_array[i+1].PMKID,
+ &pmkid_array[i].PMKID,
+ WPA2_PMKID_LEN);
+ }
+ pmkid_list.pmkids.npmkid--;
+ }
+ if (iwpmksa->cmd == IW_PMKSA_ADD) {
+ bcopy(&iwpmksa->bssid.sa_data[0],
+ &pmkid_array[pmkid_list.pmkids.npmkid].BSSID,
+ ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->pmkid[0], &pmkid_array[pmkid_list.pmkids.npmkid].PMKID,
+ WPA2_PMKID_LEN);
+ {
+ uint j;
+ uint k;
+ k = pmkid_list.pmkids.npmkid;
+ BCM_REFERENCE(k);
+ WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
+ bcm_ether_ntoa(&pmkid_array[k].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkid_array[k].PMKID[j]));
+ WL_TRACE(("\n"));
+ }
+ pmkid_list.pmkids.npmkid++;
+ }
+ WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid));
+ for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
+ uint j;
+ WL_TRACE(("PMKID[%d]: %s = ", i,
+ bcm_ether_ntoa(&pmkid_array[i].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkid_array[i].PMKID[j]));
+ printf("\n");
+ }
+ WL_TRACE(("\n"));
+ dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
+ return 0;
+}
+#endif /* WIRELESS_EXT > 17 */
+
+static int
+wl_iw_get_encodeext(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name));
+ return 0;
+}
+
+static int
+wl_iw_set_wpaauth(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error = 0;
+ int paramid;
+ int paramval;
+ uint32 cipher_combined;
+ int val = 0;
+ wl_iw_t *iw = IW_DEV_IF(dev);
+
+ WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name));
+
+ paramid = vwrq->flags & IW_AUTH_INDEX;
+ paramval = vwrq->value;
+
+ WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
+ dev->name, paramid, paramval));
+
+ switch (paramid) {
+
+ case IW_AUTH_WPA_VERSION:
+ /* supported wpa version disabled or wpa or wpa2 */
+ if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
+ val = WPA_AUTH_DISABLED;
+ else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
+ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+ else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
+ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+ WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP: {
+ int fbt_cap = 0;
+
+ if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
+ iw->pwsec = paramval;
+ }
+ else {
+ iw->gwsec = paramval;
+ }
+
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
+ return error;
+
+ cipher_combined = iw->gwsec | iw->pwsec;
+ val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
+ if (cipher_combined & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
+ val |= WEP_ENABLED;
+ if (cipher_combined & IW_AUTH_CIPHER_TKIP)
+ val |= TKIP_ENABLED;
+ if (cipher_combined & IW_AUTH_CIPHER_CCMP)
+ val |= AES_ENABLED;
+
+ if (iw->privacy_invoked && !val) {
+ WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming "
+ "we're a WPS enrollee\n", dev->name, __FUNCTION__));
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
+ WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else if (val) {
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ }
+
+ if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
+ return error;
+
+ /* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way
+ * handshake.
+ */
+ if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) {
+ if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) {
+ if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val & AES_ENABLED)) {
+ if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1)))
+ return error;
+ }
+ else if (val == 0) {
+ if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0)))
+ return error;
+ }
+ }
+ }
+ break;
+ }
+
+ case IW_AUTH_KEY_MGMT:
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+
+ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+ if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK))
+ val = WPA_AUTH_PSK;
+ else
+ val = WPA_AUTH_UNSPECIFIED;
+ if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK))
+ val |= WPA2_AUTH_FT;
+ }
+ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+ if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK))
+ val = WPA2_AUTH_PSK;
+ else
+ val = WPA2_AUTH_UNSPECIFIED;
+ if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK))
+ val |= WPA2_AUTH_FT;
+ }
+ WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ /* open shared */
+ WL_ERROR(("Setting the D11auth %d\n", paramval));
+ if (paramval & IW_AUTH_ALG_OPEN_SYSTEM)
+ val = 0;
+ else if (paramval & IW_AUTH_ALG_SHARED_KEY)
+ val = 1;
+ else
+ error = 1;
+ if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ if (paramval == 0) {
+ val = 0;
+ WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ error = dev_wlc_intvar_set(dev, "wpa_auth", val);
+ return error;
+ }
+ else {
+ /* If WPA is enabled, wpa_auth is set elsewhere */
+ }
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
+ break;
+
+#if WIRELESS_EXT > 17
+
+ case IW_AUTH_ROAMING_CONTROL:
+ WL_TRACE(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
+ /* driver control or user space app control */
+ break;
+
+ case IW_AUTH_PRIVACY_INVOKED: {
+ int wsec;
+
+ if (paramval == 0) {
+ iw->privacy_invoked = FALSE;
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else {
+ iw->privacy_invoked = TRUE;
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
+ return error;
+
+ if (!WSEC_ENABLED(wsec)) {
+ /* if privacy is true, but wsec is false, we are a WPS enrollee */
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
+ WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else {
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ }
+ }
+ break;
+ }
+
+
+#endif /* WIRELESS_EXT > 17 */
+
+
+ default:
+ break;
+ }
+ return 0;
+}
+#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
+
+static int
+wl_iw_get_wpaauth(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error;
+ int paramid;
+ int paramval = 0;
+ int val;
+ wl_iw_t *iw = IW_DEV_IF(dev);
+
+ WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name));
+
+ paramid = vwrq->flags & IW_AUTH_INDEX;
+
+ switch (paramid) {
+ case IW_AUTH_WPA_VERSION:
+ /* supported wpa version disabled or wpa or wpa2 */
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED))
+ paramval = IW_AUTH_WPA_VERSION_DISABLED;
+ else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED))
+ paramval = IW_AUTH_WPA_VERSION_WPA;
+ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED))
+ paramval = IW_AUTH_WPA_VERSION_WPA2;
+ break;
+
+ case IW_AUTH_CIPHER_PAIRWISE:
+ paramval = iw->pwsec;
+ break;
+
+ case IW_AUTH_CIPHER_GROUP:
+ paramval = iw->gwsec;
+ break;
+
+ case IW_AUTH_KEY_MGMT:
+ /* psk, 1x */
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (VAL_PSK(val))
+ paramval = IW_AUTH_KEY_MGMT_PSK;
+ else
+ paramval = IW_AUTH_KEY_MGMT_802_1X;
+
+ break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ /* open, shared, leap */
+ if ((error = dev_wlc_intvar_get(dev, "auth", &val)))
+ return error;
+ if (!val)
+ paramval = IW_AUTH_ALG_OPEN_SYSTEM;
+ else
+ paramval = IW_AUTH_ALG_SHARED_KEY;
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (val)
+ paramval = TRUE;
+ else
+ paramval = FALSE;
+ break;
+
+#if WIRELESS_EXT > 17
+
+ case IW_AUTH_ROAMING_CONTROL:
+ WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
+ /* driver control or user space app control */
+ break;
+
+ case IW_AUTH_PRIVACY_INVOKED:
+ paramval = iw->privacy_invoked;
+ break;
+
+#endif /* WIRELESS_EXT > 17 */
+ }
+ vwrq->value = paramval;
+ return 0;
+}
+#endif /* WIRELESS_EXT > 17 */
+
+static const iw_handler wl_iw_handler[] =
+{
+ (iw_handler) wl_iw_config_commit, /* SIOCSIWCOMMIT */
+ (iw_handler) wl_iw_get_name, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) wl_iw_set_freq, /* SIOCSIWFREQ */
+ (iw_handler) wl_iw_get_freq, /* SIOCGIWFREQ */
+ (iw_handler) wl_iw_set_mode, /* SIOCSIWMODE */
+ (iw_handler) wl_iw_get_mode, /* SIOCGIWMODE */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* SIOCSIWRANGE */
+ (iw_handler) wl_iw_get_range, /* SIOCGIWRANGE */
+ (iw_handler) NULL, /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* SIOCSIWSTATS */
+ (iw_handler) NULL, /* SIOCGIWSTATS */
+ (iw_handler) wl_iw_set_spy, /* SIOCSIWSPY */
+ (iw_handler) wl_iw_get_spy, /* SIOCGIWSPY */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) wl_iw_set_wap, /* SIOCSIWAP */
+ (iw_handler) wl_iw_get_wap, /* SIOCGIWAP */
+#if WIRELESS_EXT > 17
+ (iw_handler) wl_iw_mlme, /* SIOCSIWMLME */
+#else
+ (iw_handler) NULL, /* -- hole -- */
+#endif
+ (iw_handler) wl_iw_iscan_get_aplist, /* SIOCGIWAPLIST */
+#if WIRELESS_EXT > 13
+ (iw_handler) wl_iw_iscan_set_scan, /* SIOCSIWSCAN */
+ (iw_handler) wl_iw_iscan_get_scan, /* SIOCGIWSCAN */
+#else /* WIRELESS_EXT > 13 */
+ (iw_handler) NULL, /* SIOCSIWSCAN */
+ (iw_handler) NULL, /* SIOCGIWSCAN */
+#endif /* WIRELESS_EXT > 13 */
+ (iw_handler) wl_iw_set_essid, /* SIOCSIWESSID */
+ (iw_handler) wl_iw_get_essid, /* SIOCGIWESSID */
+ (iw_handler) wl_iw_set_nick, /* SIOCSIWNICKN */
+ (iw_handler) wl_iw_get_nick, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) wl_iw_set_rate, /* SIOCSIWRATE */
+ (iw_handler) wl_iw_get_rate, /* SIOCGIWRATE */
+ (iw_handler) wl_iw_set_rts, /* SIOCSIWRTS */
+ (iw_handler) wl_iw_get_rts, /* SIOCGIWRTS */
+ (iw_handler) wl_iw_set_frag, /* SIOCSIWFRAG */
+ (iw_handler) wl_iw_get_frag, /* SIOCGIWFRAG */
+ (iw_handler) wl_iw_set_txpow, /* SIOCSIWTXPOW */
+ (iw_handler) wl_iw_get_txpow, /* SIOCGIWTXPOW */
+#if WIRELESS_EXT > 10
+ (iw_handler) wl_iw_set_retry, /* SIOCSIWRETRY */
+ (iw_handler) wl_iw_get_retry, /* SIOCGIWRETRY */
+#endif /* WIRELESS_EXT > 10 */
+ (iw_handler) wl_iw_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) wl_iw_get_encode, /* SIOCGIWENCODE */
+ (iw_handler) wl_iw_set_power, /* SIOCSIWPOWER */
+ (iw_handler) wl_iw_get_power, /* SIOCGIWPOWER */
+#if WIRELESS_EXT > 17
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) wl_iw_set_wpaie, /* SIOCSIWGENIE */
+ (iw_handler) wl_iw_get_wpaie, /* SIOCGIWGENIE */
+ (iw_handler) wl_iw_set_wpaauth, /* SIOCSIWAUTH */
+ (iw_handler) wl_iw_get_wpaauth, /* SIOCGIWAUTH */
+ (iw_handler) wl_iw_set_encodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) wl_iw_get_encodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) wl_iw_set_pmksa, /* SIOCSIWPMKSA */
+#endif /* WIRELESS_EXT > 17 */
+};
+
+#if WIRELESS_EXT > 12
+enum {
+ WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV,
+ WL_IW_SET_VLANMODE,
+ WL_IW_SET_PM,
+#if WIRELESS_EXT > 17
+#endif /* WIRELESS_EXT > 17 */
+ WL_IW_SET_LAST
+};
+
+static iw_handler wl_iw_priv_handler[] = {
+ wl_iw_set_leddc,
+ wl_iw_set_vlanmode,
+ wl_iw_set_pm,
+#if WIRELESS_EXT > 17
+#endif /* WIRELESS_EXT > 17 */
+ NULL
+};
+
+static struct iw_priv_args wl_iw_priv_args[] = {
+ {
+ WL_IW_SET_LEDDC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_leddc"
+ },
+ {
+ WL_IW_SET_VLANMODE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_vlanmode"
+ },
+ {
+ WL_IW_SET_PM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_pm"
+ },
+#if WIRELESS_EXT > 17
+#endif /* WIRELESS_EXT > 17 */
+ { 0, 0, 0, { 0 } }
+};
+
+const struct iw_handler_def wl_iw_handler_def =
+{
+ .num_standard = ARRAYSIZE(wl_iw_handler),
+ .num_private = ARRAY_SIZE(wl_iw_priv_handler),
+ .num_private_args = ARRAY_SIZE(wl_iw_priv_args),
+ .standard = (iw_handler *) wl_iw_handler,
+ .private = wl_iw_priv_handler,
+ .private_args = wl_iw_priv_args,
+#if WIRELESS_EXT >= 19
+ get_wireless_stats: dhd_get_wireless_stats,
+#endif /* WIRELESS_EXT >= 19 */
+ };
+#endif /* WIRELESS_EXT > 12 */
+
+int
+wl_iw_ioctl(
+ struct net_device *dev,
+ struct ifreq *rq,
+ int cmd
+)
+{
+ struct iwreq *wrq = (struct iwreq *) rq;
+ struct iw_request_info info;
+ iw_handler handler;
+ char *extra = NULL;
+ size_t token_size = 1;
+ int max_tokens = 0, ret = 0;
+
+ if (cmd < SIOCIWFIRST ||
+ IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
+ !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)]))
+ return -EOPNOTSUPP;
+
+ switch (cmd) {
+
+ case SIOCSIWESSID:
+ case SIOCGIWESSID:
+ case SIOCSIWNICKN:
+ case SIOCGIWNICKN:
+ max_tokens = IW_ESSID_MAX_SIZE + 1;
+ break;
+
+ case SIOCSIWENCODE:
+ case SIOCGIWENCODE:
+#if WIRELESS_EXT > 17
+ case SIOCSIWENCODEEXT:
+ case SIOCGIWENCODEEXT:
+#endif
+ max_tokens = IW_ENCODING_TOKEN_MAX;
+ break;
+
+ case SIOCGIWRANGE:
+ max_tokens = sizeof(struct iw_range);
+ break;
+
+ case SIOCGIWAPLIST:
+ token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
+ max_tokens = IW_MAX_AP;
+ break;
+
+#if WIRELESS_EXT > 13
+ case SIOCGIWSCAN:
+ if (g_iscan)
+ max_tokens = wrq->u.data.length;
+ else
+ max_tokens = IW_SCAN_MAX_DATA;
+ break;
+#endif /* WIRELESS_EXT > 13 */
+
+ case SIOCSIWSPY:
+ token_size = sizeof(struct sockaddr);
+ max_tokens = IW_MAX_SPY;
+ break;
+
+ case SIOCGIWSPY:
+ token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
+ max_tokens = IW_MAX_SPY;
+ break;
+ default:
+ break;
+ }
+
+ if (max_tokens && wrq->u.data.pointer) {
+ if (wrq->u.data.length > max_tokens)
+ return -E2BIG;
+
+ if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+ }
+
+ info.cmd = cmd;
+ info.flags = 0;
+
+ ret = handler(dev, &info, &wrq->u, extra);
+
+ if (extra) {
+ if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ kfree(extra);
+ }
+
+ return ret;
+}
+
+/* Convert a connection status event into a connection status string.
+ * Returns TRUE if a matching connection status string was found.
+ */
+bool
+wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason,
+ char* stringBuf, uint buflen)
+{
+ typedef struct conn_fail_event_map_t {
+ uint32 inEvent; /* input: event type to match */
+ uint32 inStatus; /* input: event status code to match */
+ uint32 inReason; /* input: event reason code to match */
+ const char* outName; /* output: failure type */
+ const char* outCause; /* output: failure cause */
+ } conn_fail_event_map_t;
+
+ /* Map of WLC_E events to connection failure strings */
+# define WL_IW_DONT_CARE 9999
+ const conn_fail_event_map_t event_map [] = {
+ /* inEvent inStatus inReason */
+ /* outName outCause */
+ {WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE,
+ "Conn", "Success"},
+ {WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE,
+ "Conn", "NoNetworks"},
+ {WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "ConfigMismatch"},
+ {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH,
+ "Conn", "EncrypMismatch"},
+ {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH,
+ "Conn", "RsnMismatch"},
+ {WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
+ "Conn", "AuthTimeout"},
+ {WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "AuthFail"},
+ {WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE,
+ "Conn", "AuthNoAck"},
+ {WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "ReassocFail"},
+ {WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
+ "Conn", "ReassocTimeout"},
+ {WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE,
+ "Conn", "ReassocAbort"},
+ {WLC_E_PSK_SUP, WLC_SUP_KEYED, WL_IW_DONT_CARE,
+ "Sup", "ConnSuccess"},
+ {WLC_E_PSK_SUP, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Sup", "WpaHandshakeFail"},
+ {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "Deauth"},
+ {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "DisassocInd"},
+ {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "Disassoc"}
+ };
+
+ const char* name = "";
+ const char* cause = NULL;
+ int i;
+
+ /* Search the event map table for a matching event */
+ for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) {
+ const conn_fail_event_map_t* row = &event_map[i];
+ if (row->inEvent == event_type &&
+ (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) &&
+ (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) {
+ name = row->outName;
+ cause = row->outCause;
+ break;
+ }
+ }
+
+ /* If found, generate a connection failure string and return TRUE */
+ if (cause) {
+ memset(stringBuf, 0, buflen);
+ snprintf(stringBuf, buflen, "%s %s %02d %02d",
+ name, cause, status, reason);
+ WL_TRACE(("Connection status: %s\n", stringBuf));
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+#if (WIRELESS_EXT > 14)
+/* Check if we have received an event that indicates connection failure
+ * If so, generate a connection failure report string.
+ * The caller supplies a buffer to hold the generated string.
+ */
+static bool
+wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen)
+{
+ uint32 event = ntoh32(e->event_type);
+ uint32 status = ntoh32(e->status);
+ uint32 reason = ntoh32(e->reason);
+
+ if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
+ return TRUE;
+ } else
+ {
+ return FALSE;
+ }
+}
+#endif /* WIRELESS_EXT > 14 */
+
+#ifndef IW_CUSTOM_MAX
+#define IW_CUSTOM_MAX 256 /* size of extra buffer used for translation of events */
+#endif /* IW_CUSTOM_MAX */
+
+void
+wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
+{
+#if WIRELESS_EXT > 13
+ union iwreq_data wrqu;
+ char extra[IW_CUSTOM_MAX + 1];
+ int cmd = 0;
+ uint32 event_type = ntoh32(e->event_type);
+ uint16 flags = ntoh16(e->flags);
+ uint32 datalen = ntoh32(e->datalen);
+ uint32 status = ntoh32(e->status);
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ memset(extra, 0, sizeof(extra));
+
+ memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ switch (event_type) {
+ case WLC_E_TXFAIL:
+ cmd = IWEVTXDROP;
+ break;
+#if WIRELESS_EXT > 14
+ case WLC_E_JOIN:
+ case WLC_E_ASSOC_IND:
+ case WLC_E_REASSOC_IND:
+ cmd = IWEVREGISTERED;
+ break;
+ case WLC_E_DEAUTH_IND:
+ case WLC_E_DISASSOC_IND:
+ cmd = SIOCGIWAP;
+ wrqu.data.length = strlen(extra);
+ bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
+ bzero(&extra, ETHER_ADDR_LEN);
+ break;
+
+ case WLC_E_LINK:
+ case WLC_E_NDIS_LINK:
+ cmd = SIOCGIWAP;
+ wrqu.data.length = strlen(extra);
+ if (!(flags & WLC_EVENT_MSG_LINK)) {
+ bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
+ bzero(&extra, ETHER_ADDR_LEN);
+ }
+ break;
+ case WLC_E_ACTION_FRAME:
+ cmd = IWEVCUSTOM;
+ if (datalen + 1 <= sizeof(extra)) {
+ wrqu.data.length = datalen + 1;
+ extra[0] = WLC_E_ACTION_FRAME;
+ memcpy(&extra[1], data, datalen);
+ WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length));
+ }
+ break;
+
+ case WLC_E_ACTION_FRAME_COMPLETE:
+ cmd = IWEVCUSTOM;
+ if (sizeof(status) + 1 <= sizeof(extra)) {
+ wrqu.data.length = sizeof(status) + 1;
+ extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
+ memcpy(&extra[1], &status, sizeof(status));
+ WL_TRACE(("wl_iw_event status %d \n", status));
+ }
+ break;
+#endif /* WIRELESS_EXT > 14 */
+#if WIRELESS_EXT > 17
+ case WLC_E_MIC_ERROR: {
+ struct iw_michaelmicfailure *micerrevt = (struct iw_michaelmicfailure *)&extra;
+ cmd = IWEVMICHAELMICFAILURE;
+ wrqu.data.length = sizeof(struct iw_michaelmicfailure);
+ if (flags & WLC_EVENT_MSG_GROUP)
+ micerrevt->flags |= IW_MICFAILURE_GROUP;
+ else
+ micerrevt->flags |= IW_MICFAILURE_PAIRWISE;
+ memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ micerrevt->src_addr.sa_family = ARPHRD_ETHER;
+
+ break;
+ }
+
+ case WLC_E_ASSOC_REQ_IE:
+ cmd = IWEVASSOCREQIE;
+ wrqu.data.length = datalen;
+ if (datalen < sizeof(extra))
+ memcpy(extra, data, datalen);
+ break;
+
+ case WLC_E_ASSOC_RESP_IE:
+ cmd = IWEVASSOCRESPIE;
+ wrqu.data.length = datalen;
+ if (datalen < sizeof(extra))
+ memcpy(extra, data, datalen);
+ break;
+
+ case WLC_E_PMKID_CACHE: {
+ struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra;
+ pmkid_cand_list_t *pmkcandlist;
+ pmkid_cand_t *pmkidcand;
+ int count;
+
+ if (data == NULL)
+ break;
+
+ cmd = IWEVPMKIDCAND;
+ pmkcandlist = data;
+ count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand);
+ wrqu.data.length = sizeof(struct iw_pmkid_cand);
+ pmkidcand = pmkcandlist->pmkid_cand;
+ while (count) {
+ bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand));
+ if (pmkidcand->preauth)
+ iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH;
+ bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data,
+ ETHER_ADDR_LEN);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ pmkidcand++;
+ count--;
+ }
+ break;
+ }
+#endif /* WIRELESS_EXT > 17 */
+
+ case WLC_E_SCAN_COMPLETE:
+#if WIRELESS_EXT > 14
+ cmd = SIOCGIWSCAN;
+#endif
+ WL_TRACE(("event WLC_E_SCAN_COMPLETE\n"));
+ if ((g_iscan) && (g_iscan->sysioc_pid >= 0) &&
+ (g_iscan->iscan_state != ISCAN_STATE_IDLE))
+ up(&g_iscan->sysioc_sem);
+ break;
+
+ default:
+ /* Cannot translate event */
+ break;
+ }
+
+ if (cmd) {
+ if (cmd == SIOCGIWSCAN)
+ wireless_send_event(dev, cmd, &wrqu, NULL);
+ else
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ }
+
+#if WIRELESS_EXT > 14
+ /* Look for WLC events that indicate a connection failure.
+ * If found, generate an IWEVCUSTOM event.
+ */
+ memset(extra, 0, sizeof(extra));
+ if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
+ cmd = IWEVCUSTOM;
+ wrqu.data.length = strlen(extra);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ }
+#endif /* WIRELESS_EXT > 14 */
+
+#endif /* WIRELESS_EXT > 13 */
+}
+
+int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
+{
+ int res = 0;
+ wl_cnt_t cnt;
+ int phy_noise;
+ int rssi;
+ scb_val_t scb_val;
+
+ phy_noise = 0;
+ if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
+ goto done;
+
+ phy_noise = dtoh32(phy_noise);
+ WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise));
+
+ scb_val.val = 0;
+ if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
+ goto done;
+
+ rssi = dtoh32(scb_val.val);
+ WL_TRACE(("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi));
+ if (rssi <= WL_IW_RSSI_NO_SIGNAL)
+ wstats->qual.qual = 0;
+ else if (rssi <= WL_IW_RSSI_VERY_LOW)
+ wstats->qual.qual = 1;
+ else if (rssi <= WL_IW_RSSI_LOW)
+ wstats->qual.qual = 2;
+ else if (rssi <= WL_IW_RSSI_GOOD)
+ wstats->qual.qual = 3;
+ else if (rssi <= WL_IW_RSSI_VERY_GOOD)
+ wstats->qual.qual = 4;
+ else
+ wstats->qual.qual = 5;
+
+ /* Wraps to 0 if RSSI is 0 */
+ wstats->qual.level = 0x100 + rssi;
+ wstats->qual.noise = 0x100 + phy_noise;
+#if WIRELESS_EXT > 18
+ wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
+#else
+ wstats->qual.updated |= 7;
+#endif /* WIRELESS_EXT > 18 */
+
+#if WIRELESS_EXT > 11
+ WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n *****", (int)sizeof(wl_cnt_t)));
+
+ memset(&cnt, 0, sizeof(wl_cnt_t));
+ res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
+ if (res)
+ {
+ WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res));
+ goto done;
+ }
+
+ cnt.version = dtoh16(cnt.version);
+ if (cnt.version != WL_CNT_T_VERSION) {
+ WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
+ WL_CNT_T_VERSION, cnt.version));
+ goto done;
+ }
+
+ wstats->discard.nwid = 0;
+ wstats->discard.code = dtoh32(cnt.rxundec);
+ wstats->discard.fragment = dtoh32(cnt.rxfragerr);
+ wstats->discard.retries = dtoh32(cnt.txfail);
+ wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant);
+ wstats->miss.beacon = 0;
+
+ WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
+ dtoh32(cnt.txframe), dtoh32(cnt.txbyte)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant)));
+
+#endif /* WIRELESS_EXT > 11 */
+
+done:
+ return res;
+}
+
+static void
+wl_iw_timerfunc(ulong data)
+{
+ iscan_info_t *iscan = (iscan_info_t *)data;
+ iscan->timer_on = 0;
+ if (iscan->iscan_state != ISCAN_STATE_IDLE) {
+ WL_TRACE(("timer trigger\n"));
+ up(&iscan->sysioc_sem);
+ }
+}
+
+static void
+wl_iw_set_event_mask(struct net_device *dev)
+{
+ char eventmask[WL_EVENTING_MASK_LEN];
+ char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
+
+ dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
+ bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
+ setbit(eventmask, WLC_E_SCAN_COMPLETE);
+ dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
+ iovbuf, sizeof(iovbuf));
+
+}
+
+static int
+wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
+{
+ int err = 0;
+
+ memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
+ params->bss_type = DOT11_BSSTYPE_ANY;
+ params->scan_type = 0;
+ params->nprobes = -1;
+ params->active_time = -1;
+ params->passive_time = -1;
+ params->home_time = -1;
+ params->channel_num = 0;
+
+ params->nprobes = htod32(params->nprobes);
+ params->active_time = htod32(params->active_time);
+ params->passive_time = htod32(params->passive_time);
+ params->home_time = htod32(params->home_time);
+ if (ssid && ssid->SSID_len)
+ memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
+
+ return err;
+}
+
+static int
+wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
+{
+ int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
+ wl_iscan_params_t *params;
+ int err = 0;
+
+ if (ssid && ssid->SSID_len) {
+ params_size += sizeof(wlc_ssid_t);
+ }
+ params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
+ if (params == NULL) {
+ return -ENOMEM;
+ }
+ memset(params, 0, params_size);
+ ASSERT(params_size < WLC_IOCTL_SMLEN);
+
+ err = wl_iw_iscan_prep(&params->params, ssid);
+
+ if (!err) {
+ params->version = htod32(ISCAN_REQ_VERSION);
+ params->action = htod16(action);
+ params->scan_duration = htod16(0);
+
+ /* params_size += OFFSETOF(wl_iscan_params_t, params); */
+ (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
+ iscan->ioctlbuf, WLC_IOCTL_SMLEN);
+ }
+
+ kfree(params);
+ return err;
+}
+
+static uint32
+wl_iw_iscan_get(iscan_info_t *iscan)
+{
+ iscan_buf_t * buf;
+ iscan_buf_t * ptr;
+ wl_iscan_results_t * list_buf;
+ wl_iscan_results_t list;
+ wl_scan_results_t *results;
+ uint32 status;
+
+ /* buffers are allocated on demand */
+ if (iscan->list_cur) {
+ buf = iscan->list_cur;
+ iscan->list_cur = buf->next;
+ }
+ else {
+ buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL);
+ if (!buf)
+ return WL_SCAN_RESULTS_ABORTED;
+ buf->next = NULL;
+ if (!iscan->list_hdr)
+ iscan->list_hdr = buf;
+ else {
+ ptr = iscan->list_hdr;
+ while (ptr->next) {
+ ptr = ptr->next;
+ }
+ ptr->next = buf;
+ }
+ }
+ memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
+ list_buf = (wl_iscan_results_t*)buf->iscan_buf;
+ results = &list_buf->results;
+ results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
+ results->version = 0;
+ results->count = 0;
+
+ memset(&list, 0, sizeof(list));
+ list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+ (void) dev_iw_iovar_getbuf(
+ iscan->dev,
+ "iscanresults",
+ &list,
+ WL_ISCAN_RESULTS_FIXED_SIZE,
+ buf->iscan_buf,
+ WLC_IW_ISCAN_MAXLEN);
+ results->buflen = dtoh32(results->buflen);
+ results->version = dtoh32(results->version);
+ results->count = dtoh32(results->count);
+ WL_TRACE(("results->count = %d\n", results->count));
+
+ WL_TRACE(("results->buflen = %d\n", results->buflen));
+ status = dtoh32(list_buf->status);
+ return status;
+}
+
+static void wl_iw_send_scan_complete(iscan_info_t *iscan)
+{
+ union iwreq_data wrqu;
+
+ memset(&wrqu, 0, sizeof(wrqu));
+
+ /* wext expects to get no data for SIOCGIWSCAN Event */
+ wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
+static int
+_iscan_sysioc_thread(void *data)
+{
+ uint32 status;
+ iscan_info_t *iscan = (iscan_info_t *)data;
+
+ DAEMONIZE("iscan_sysioc");
+
+ status = WL_SCAN_RESULTS_PARTIAL;
+ while (down_interruptible(&iscan->sysioc_sem) == 0) {
+ if (iscan->timer_on) {
+ del_timer(&iscan->timer);
+ iscan->timer_on = 0;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+ status = wl_iw_iscan_get(iscan);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+
+ switch (status) {
+ case WL_SCAN_RESULTS_PARTIAL:
+ WL_TRACE(("iscanresults incomplete\n"));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+ /* make sure our buffer size is enough before going next round */
+ wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+ /* Reschedule the timer */
+ iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
+ add_timer(&iscan->timer);
+ iscan->timer_on = 1;
+ break;
+ case WL_SCAN_RESULTS_SUCCESS:
+ WL_TRACE(("iscanresults complete\n"));
+ iscan->iscan_state = ISCAN_STATE_IDLE;
+ wl_iw_send_scan_complete(iscan);
+ break;
+ case WL_SCAN_RESULTS_PENDING:
+ WL_TRACE(("iscanresults pending\n"));
+ /* Reschedule the timer */
+ iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
+ add_timer(&iscan->timer);
+ iscan->timer_on = 1;
+ break;
+ case WL_SCAN_RESULTS_ABORTED:
+ WL_TRACE(("iscanresults aborted\n"));
+ iscan->iscan_state = ISCAN_STATE_IDLE;
+ wl_iw_send_scan_complete(iscan);
+ break;
+ default:
+ WL_TRACE(("iscanresults returned unknown status %d\n", status));
+ break;
+ }
+ }
+ complete_and_exit(&iscan->sysioc_exited, 0);
+}
+
+int
+wl_iw_attach(struct net_device *dev, void * dhdp)
+{
+ iscan_info_t *iscan = NULL;
+
+ if (!dev)
+ return 0;
+
+ iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
+ if (!iscan)
+ return -ENOMEM;
+ memset(iscan, 0, sizeof(iscan_info_t));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
+ iscan->kthread = NULL;
+#endif
+ iscan->sysioc_pid = -1;
+ /* we only care about main interface so save a global here */
+ g_iscan = iscan;
+ iscan->dev = dev;
+ iscan->iscan_state = ISCAN_STATE_IDLE;
+
+
+ /* Set up the timer */
+ iscan->timer_ms = 2000;
+ init_timer(&iscan->timer);
+ iscan->timer.data = (ulong)iscan;
+ iscan->timer.function = wl_iw_timerfunc;
+
+ sema_init(&iscan->sysioc_sem, 0);
+ init_completion(&iscan->sysioc_exited);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
+ iscan->kthread = kthread_run(_iscan_sysioc_thread, iscan, "iscan_sysioc");
+ iscan->sysioc_pid = iscan->kthread->pid;
+#else
+ iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0);
+#endif
+ if (iscan->sysioc_pid < 0)
+ return -ENOMEM;
+ return 0;
+}
+
+void wl_iw_detach(void)
+{
+ iscan_buf_t *buf;
+ iscan_info_t *iscan = g_iscan;
+ if (!iscan)
+ return;
+ if (iscan->sysioc_pid >= 0) {
+ KILL_PROC(iscan->sysioc_pid, SIGTERM);
+ wait_for_completion(&iscan->sysioc_exited);
+ }
+
+ while (iscan->list_hdr) {
+ buf = iscan->list_hdr->next;
+ kfree(iscan->list_hdr);
+ iscan->list_hdr = buf;
+ }
+ kfree(iscan);
+ g_iscan = NULL;
+}
+
+#endif /* USE_IW */
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h
new file mode 100644
index 000000000000..abdfa8c2e462
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_iw.h
@@ -0,0 +1,159 @@
+/*
+ * Linux Wireless Extensions support
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_iw.h 490106 2014-07-09 12:35:17Z $
+ */
+
+#ifndef _wl_iw_h_
+#define _wl_iw_h_
+
+#include <linux/wireless.h>
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <wlioctl.h>
+
+#define WL_SCAN_PARAMS_SSID_MAX 10
+#define GET_SSID "SSID="
+#define GET_CHANNEL "CH="
+#define GET_NPROBE "NPROBE="
+#define GET_ACTIVE_ASSOC_DWELL "ACTIVE="
+#define GET_PASSIVE_ASSOC_DWELL "PASSIVE="
+#define GET_HOME_DWELL "HOME="
+#define GET_SCAN_TYPE "TYPE="
+
+#define BAND_GET_CMD "GETBAND"
+#define BAND_SET_CMD "SETBAND"
+#define DTIM_SKIP_GET_CMD "DTIMSKIPGET"
+#define DTIM_SKIP_SET_CMD "DTIMSKIPSET"
+#define SETSUSPEND_CMD "SETSUSPENDOPT"
+#define PNOSSIDCLR_SET_CMD "PNOSSIDCLR"
+/* Lin - Is the extra space needed? */
+#define PNOSETUP_SET_CMD "PNOSETUP " /* TLV command has extra end space */
+#define PNOENABLE_SET_CMD "PNOFORCE"
+#define PNODEBUG_SET_CMD "PNODEBUG"
+#define TXPOWER_SET_CMD "TXPOWER"
+
+
+/* Structure to keep global parameters */
+typedef struct wl_iw_extra_params {
+ int target_channel; /* target channel */
+} wl_iw_extra_params_t;
+
+struct cntry_locales_custom {
+ char iso_abbrev[WLC_CNTRY_BUF_SZ]; /* ISO 3166-1 country abbreviation */
+ char custom_locale[WLC_CNTRY_BUF_SZ]; /* Custom firmware locale */
+ int32 custom_locale_rev; /* Custom local revisin default -1 */
+};
+/* ============================================== */
+/* Defines from wlc_pub.h */
+#define WL_IW_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */
+#define WL_IW_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */
+#define WL_IW_RSSI_VERY_LOW -80 /* Very low quality cutoffs */
+#define WL_IW_RSSI_LOW -70 /* Low quality cutoffs */
+#define WL_IW_RSSI_GOOD -68 /* Good quality cutoffs */
+#define WL_IW_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */
+#define WL_IW_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */
+#define WL_IW_RSSI_INVALID 0 /* invalid RSSI value */
+#define MAX_WX_STRING 80
+#define SSID_FMT_BUF_LEN ((4 * 32) + 1)
+#define isprint(c) bcm_isprint(c)
+#define WL_IW_SET_ACTIVE_SCAN (SIOCIWFIRSTPRIV+1)
+#define WL_IW_GET_RSSI (SIOCIWFIRSTPRIV+3)
+#define WL_IW_SET_PASSIVE_SCAN (SIOCIWFIRSTPRIV+5)
+#define WL_IW_GET_LINK_SPEED (SIOCIWFIRSTPRIV+7)
+#define WL_IW_GET_CURR_MACADDR (SIOCIWFIRSTPRIV+9)
+#define WL_IW_SET_STOP (SIOCIWFIRSTPRIV+11)
+#define WL_IW_SET_START (SIOCIWFIRSTPRIV+13)
+
+#define G_SCAN_RESULTS 8*1024
+#define WE_ADD_EVENT_FIX 0x80
+#define G_WLAN_SET_ON 0
+#define G_WLAN_SET_OFF 1
+
+
+typedef struct wl_iw {
+ char nickname[IW_ESSID_MAX_SIZE];
+
+ struct iw_statistics wstats;
+
+ int spy_num;
+ uint32 pwsec; /* pairwise wsec setting */
+ uint32 gwsec; /* group wsec setting */
+ bool privacy_invoked; /* IW_AUTH_PRIVACY_INVOKED setting */
+ struct ether_addr spy_addr[IW_MAX_SPY];
+ struct iw_quality spy_qual[IW_MAX_SPY];
+ void *wlinfo;
+} wl_iw_t;
+
+struct wl_ctrl {
+ struct timer_list *timer;
+ struct net_device *dev;
+ long sysioc_pid;
+ struct semaphore sysioc_sem;
+ struct completion sysioc_exited;
+};
+
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+extern const struct iw_handler_def wl_iw_handler_def;
+#endif /* WIRELESS_EXT > 12 */
+
+extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data);
+extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats);
+int wl_iw_attach(struct net_device *dev, void * dhdp);
+int wl_iw_send_priv_event(struct net_device *dev, char *flag);
+
+void wl_iw_detach(void);
+
+#define CSCAN_COMMAND "CSCAN "
+#define CSCAN_TLV_PREFIX 'S'
+#define CSCAN_TLV_VERSION 1
+#define CSCAN_TLV_SUBVERSION 0
+#define CSCAN_TLV_TYPE_SSID_IE 'S'
+#define CSCAN_TLV_TYPE_CHANNEL_IE 'C'
+#define CSCAN_TLV_TYPE_NPROBE_IE 'N'
+#define CSCAN_TLV_TYPE_ACTIVE_IE 'A'
+#define CSCAN_TLV_TYPE_PASSIVE_IE 'P'
+#define CSCAN_TLV_TYPE_HOME_IE 'H'
+#define CSCAN_TLV_TYPE_STYPE_IE 'T'
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_event(info, stream, ends, iwe, extra)
+#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
+ iwe_stream_add_value(info, event, value, ends, iwe, event_len)
+#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_point(info, stream, ends, iwe, extra)
+#else
+#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_event(stream, ends, iwe, extra)
+#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
+ iwe_stream_add_value(event, value, ends, iwe, event_len)
+#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_point(stream, ends, iwe, extra)
+#endif
+
+#endif /* _wl_iw_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_linux_mon.c b/drivers/net/wireless/bcmdhd/wl_linux_mon.c
new file mode 100644
index 000000000000..56817ce1e77c
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_linux_mon.c
@@ -0,0 +1,403 @@
+/*
+ * Broadcom Dongle Host Driver (DHD), Linux monitor network interface
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_linux_mon.c 425343 2013-09-23 23:04:47Z $
+ */
+
+#include <osl.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/ieee80211.h>
+#include <linux/rtnetlink.h>
+#include <net/ieee80211_radiotap.h>
+
+#include <wlioctl.h>
+#include <bcmutils.h>
+#include <dhd_dbg.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+
+typedef enum monitor_states
+{
+ MONITOR_STATE_DEINIT = 0x0,
+ MONITOR_STATE_INIT = 0x1,
+ MONITOR_STATE_INTERFACE_ADDED = 0x2,
+ MONITOR_STATE_INTERFACE_DELETED = 0x4
+} monitor_states_t;
+int dhd_add_monitor(char *name, struct net_device **new_ndev);
+extern int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
+int dhd_del_monitor(struct net_device *ndev);
+int dhd_monitor_init(void *dhd_pub);
+int dhd_monitor_uninit(void);
+
+/**
+ * Local declarations and defintions (not exposed)
+ */
+#ifndef DHD_MAX_IFS
+#define DHD_MAX_IFS 16
+#endif
+#define MON_PRINT(format, ...) printk("DHD-MON: %s " format, __func__, ##__VA_ARGS__)
+#define MON_TRACE MON_PRINT
+
+typedef struct monitor_interface {
+ int radiotap_enabled;
+ struct net_device* real_ndev; /* The real interface that the monitor is on */
+ struct net_device* mon_ndev;
+} monitor_interface;
+
+typedef struct dhd_linux_monitor {
+ void *dhd_pub;
+ monitor_states_t monitor_state;
+ monitor_interface mon_if[DHD_MAX_IFS];
+ struct mutex lock; /* lock to protect mon_if */
+} dhd_linux_monitor_t;
+
+static dhd_linux_monitor_t g_monitor;
+
+static struct net_device* lookup_real_netdev(char *name);
+static monitor_interface* ndev_to_monif(struct net_device *ndev);
+static int dhd_mon_if_open(struct net_device *ndev);
+static int dhd_mon_if_stop(struct net_device *ndev);
+static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+static void dhd_mon_if_set_multicast_list(struct net_device *ndev);
+static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr);
+
+static const struct net_device_ops dhd_mon_if_ops = {
+ .ndo_open = dhd_mon_if_open,
+ .ndo_stop = dhd_mon_if_stop,
+ .ndo_start_xmit = dhd_mon_if_subif_start_xmit,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+ .ndo_set_rx_mode = dhd_mon_if_set_multicast_list,
+#else
+ .ndo_set_multicast_list = dhd_mon_if_set_multicast_list,
+#endif
+ .ndo_set_mac_address = dhd_mon_if_change_mac,
+};
+
+/**
+ * Local static function defintions
+ */
+
+/* Look up dhd's net device table to find a match (e.g. interface "eth0" is a match for "mon.eth0"
+ * "p2p-eth0-0" is a match for "mon.p2p-eth0-0")
+ */
+static struct net_device* lookup_real_netdev(char *name)
+{
+ struct net_device *ndev_found = NULL;
+
+ int i;
+ int len = 0;
+ int last_name_len = 0;
+ struct net_device *ndev;
+
+ /* We need to find interface "p2p-p2p-0" corresponding to monitor interface "mon-p2p-0",
+ * Once mon iface name reaches IFNAMSIZ, it is reset to p2p0-0 and corresponding mon
+ * iface would be mon-p2p0-0.
+ */
+ for (i = 0; i < DHD_MAX_IFS; i++) {
+ ndev = dhd_idx2net(g_monitor.dhd_pub, i);
+
+ /* Skip "p2p" and look for "-p2p0-x" in monitor interface name. If it
+ * it matches, then this netdev is the corresponding real_netdev.
+ */
+ if (ndev && strstr(ndev->name, "p2p-p2p0")) {
+ len = strlen("p2p");
+ } else {
+ /* if p2p- is not present, then the IFNAMSIZ have reached and name
+ * would have got reset. In this casse,look for p2p0-x in mon-p2p0-x
+ */
+ len = 0;
+ }
+ if (ndev && strstr(name, (ndev->name + len))) {
+ if (strlen(ndev->name) > last_name_len) {
+ ndev_found = ndev;
+ last_name_len = strlen(ndev->name);
+ }
+ }
+ }
+
+ return ndev_found;
+}
+
+static monitor_interface* ndev_to_monif(struct net_device *ndev)
+{
+ int i;
+
+ for (i = 0; i < DHD_MAX_IFS; i++) {
+ if (g_monitor.mon_if[i].mon_ndev == ndev)
+ return &g_monitor.mon_if[i];
+ }
+
+ return NULL;
+}
+
+static int dhd_mon_if_open(struct net_device *ndev)
+{
+ int ret = 0;
+
+ MON_PRINT("enter\n");
+ return ret;
+}
+
+static int dhd_mon_if_stop(struct net_device *ndev)
+{
+ int ret = 0;
+
+ MON_PRINT("enter\n");
+ return ret;
+}
+
+static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ int ret = 0;
+ int rtap_len;
+ int qos_len = 0;
+ int dot11_hdr_len = 24;
+ int snap_len = 6;
+ unsigned char *pdata;
+ unsigned short frame_ctl;
+ unsigned char src_mac_addr[6];
+ unsigned char dst_mac_addr[6];
+ struct ieee80211_hdr *dot11_hdr;
+ struct ieee80211_radiotap_header *rtap_hdr;
+ monitor_interface* mon_if;
+
+ MON_PRINT("enter\n");
+
+ mon_if = ndev_to_monif(ndev);
+ if (mon_if == NULL || mon_if->real_ndev == NULL) {
+ MON_PRINT(" cannot find matched net dev, skip the packet\n");
+ goto fail;
+ }
+
+ if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
+ goto fail;
+
+ rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
+ if (unlikely(rtap_hdr->it_version))
+ goto fail;
+
+ rtap_len = ieee80211_get_radiotap_len(skb->data);
+ if (unlikely(skb->len < rtap_len))
+ goto fail;
+
+ MON_PRINT("radiotap len (should be 14): %d\n", rtap_len);
+
+ /* Skip the ratio tap header */
+ skb_pull(skb, rtap_len);
+
+ dot11_hdr = (struct ieee80211_hdr *)skb->data;
+ frame_ctl = le16_to_cpu(dot11_hdr->frame_control);
+ /* Check if the QoS bit is set */
+ if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
+ /* Check if this ia a Wireless Distribution System (WDS) frame
+ * which has 4 MAC addresses
+ */
+ if (dot11_hdr->frame_control & 0x0080)
+ qos_len = 2;
+ if ((dot11_hdr->frame_control & 0x0300) == 0x0300)
+ dot11_hdr_len += 6;
+
+ memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
+ memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
+
+ /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for
+ * for two MAC addresses
+ */
+ skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2);
+ pdata = (unsigned char*)skb->data;
+ memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));
+ memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr));
+ PKTSETPRIO(skb, 0);
+
+ MON_PRINT("if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name);
+
+ /* Use the real net device to transmit the packet */
+ ret = dhd_start_xmit(skb, mon_if->real_ndev);
+
+ return ret;
+ }
+fail:
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+static void dhd_mon_if_set_multicast_list(struct net_device *ndev)
+{
+ monitor_interface* mon_if;
+
+ mon_if = ndev_to_monif(ndev);
+ if (mon_if == NULL || mon_if->real_ndev == NULL) {
+ MON_PRINT(" cannot find matched net dev, skip the packet\n");
+ } else {
+ MON_PRINT("enter, if name: %s, matched if name %s\n",
+ ndev->name, mon_if->real_ndev->name);
+ }
+}
+
+static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr)
+{
+ int ret = 0;
+ monitor_interface* mon_if;
+
+ mon_if = ndev_to_monif(ndev);
+ if (mon_if == NULL || mon_if->real_ndev == NULL) {
+ MON_PRINT(" cannot find matched net dev, skip the packet\n");
+ } else {
+ MON_PRINT("enter, if name: %s, matched if name %s\n",
+ ndev->name, mon_if->real_ndev->name);
+ }
+ return ret;
+}
+
+/**
+ * Global function definitions (declared in dhd_linux_mon.h)
+ */
+
+int dhd_add_monitor(char *name, struct net_device **new_ndev)
+{
+ int i;
+ int idx = -1;
+ int ret = 0;
+ struct net_device* ndev = NULL;
+ dhd_linux_monitor_t **dhd_mon;
+
+ mutex_lock(&g_monitor.lock);
+
+ MON_TRACE("enter, if name: %s\n", name);
+ if (!name || !new_ndev) {
+ MON_PRINT("invalid parameters\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Find a vacancy
+ */
+ for (i = 0; i < DHD_MAX_IFS; i++)
+ if (g_monitor.mon_if[i].mon_ndev == NULL) {
+ idx = i;
+ break;
+ }
+ if (idx == -1) {
+ MON_PRINT("exceeds maximum interfaces\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ndev = alloc_etherdev(sizeof(dhd_linux_monitor_t*));
+ if (!ndev) {
+ MON_PRINT("failed to allocate memory\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ndev->type = ARPHRD_IEEE80211_RADIOTAP;
+ strncpy(ndev->name, name, IFNAMSIZ);
+ ndev->name[IFNAMSIZ - 1] = 0;
+ ndev->netdev_ops = &dhd_mon_if_ops;
+
+ ret = register_netdevice(ndev);
+ if (ret) {
+ MON_PRINT(" register_netdevice failed (%d)\n", ret);
+ goto out;
+ }
+
+ *new_ndev = ndev;
+ g_monitor.mon_if[idx].radiotap_enabled = TRUE;
+ g_monitor.mon_if[idx].mon_ndev = ndev;
+ g_monitor.mon_if[idx].real_ndev = lookup_real_netdev(name);
+ dhd_mon = (dhd_linux_monitor_t **)netdev_priv(ndev);
+ *dhd_mon = &g_monitor;
+ g_monitor.monitor_state = MONITOR_STATE_INTERFACE_ADDED;
+ MON_PRINT("net device returned: 0x%p\n", ndev);
+ MON_PRINT("found a matched net device, name %s\n", g_monitor.mon_if[idx].real_ndev->name);
+
+out:
+ if (ret && ndev)
+ free_netdev(ndev);
+
+ mutex_unlock(&g_monitor.lock);
+ return ret;
+
+}
+
+int dhd_del_monitor(struct net_device *ndev)
+{
+ int i;
+ if (!ndev)
+ return -EINVAL;
+ mutex_lock(&g_monitor.lock);
+ for (i = 0; i < DHD_MAX_IFS; i++) {
+ if (g_monitor.mon_if[i].mon_ndev == ndev ||
+ g_monitor.mon_if[i].real_ndev == ndev) {
+
+ g_monitor.mon_if[i].real_ndev = NULL;
+ unregister_netdevice(g_monitor.mon_if[i].mon_ndev);
+ free_netdev(g_monitor.mon_if[i].mon_ndev);
+ g_monitor.mon_if[i].mon_ndev = NULL;
+ g_monitor.monitor_state = MONITOR_STATE_INTERFACE_DELETED;
+ break;
+ }
+ }
+
+ if (g_monitor.monitor_state != MONITOR_STATE_INTERFACE_DELETED)
+ MON_PRINT("IF not found in monitor array, is this a monitor IF? 0x%p\n", ndev);
+ mutex_unlock(&g_monitor.lock);
+
+ return 0;
+}
+
+int dhd_monitor_init(void *dhd_pub)
+{
+ if (g_monitor.monitor_state == MONITOR_STATE_DEINIT) {
+ g_monitor.dhd_pub = dhd_pub;
+ mutex_init(&g_monitor.lock);
+ g_monitor.monitor_state = MONITOR_STATE_INIT;
+ }
+ return 0;
+}
+
+int dhd_monitor_uninit(void)
+{
+ int i;
+ struct net_device *ndev;
+ mutex_lock(&g_monitor.lock);
+ if (g_monitor.monitor_state != MONITOR_STATE_DEINIT) {
+ for (i = 0; i < DHD_MAX_IFS; i++) {
+ ndev = g_monitor.mon_if[i].mon_ndev;
+ if (ndev) {
+ unregister_netdevice(ndev);
+ free_netdev(ndev);
+ g_monitor.mon_if[i].real_ndev = NULL;
+ g_monitor.mon_if[i].mon_ndev = NULL;
+ }
+ }
+ g_monitor.monitor_state = MONITOR_STATE_DEINIT;
+ }
+ mutex_unlock(&g_monitor.lock);
+ return 0;
+}
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
new file mode 100644
index 000000000000..64f3443b2a02
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wldev_common.c
@@ -0,0 +1,479 @@
+/*
+ * Common function shared by Linux WEXT, cfg80211 and p2p drivers
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wldev_common.c 657248 2016-08-31 11:29:39Z $
+ */
+
+#include <osl.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+
+#include <wldev_common.h>
+#include <bcmutils.h>
+
+#define htod32(i) (i)
+#define htod16(i) (i)
+#define dtoh32(i) (i)
+#define dtoh16(i) (i)
+#define htodchanspec(i) (i)
+#define dtohchanspec(i) (i)
+
+#define WLDEV_ERROR(args) \
+ do { \
+ printk(KERN_ERR "WLDEV-ERROR) "); \
+ printk args; \
+ } while (0)
+
+#define WLDEV_INFO(args) \
+ do { \
+ printk(KERN_INFO "WLDEV-INFO) "); \
+ printk args; \
+ } while (0)
+
+extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd);
+
+#define MAX_NUM_OF_ASSOCLIST 64
+s32 wldev_ioctl(
+ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
+{
+ s32 ret = 0;
+ struct wl_ioctl ioc;
+
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+ ioc.set = set;
+
+ ret = dhd_ioctl_entry_local(dev, &ioc, cmd);
+
+ return ret;
+}
+
+/* Format a iovar buffer, not bsscfg indexed. The bsscfg index will be
+ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to
+ * wl_iw, wl_cfg80211 and wl_cfgp2p
+ */
+static s32 wldev_mkiovar(
+ s8 *iovar_name, s8 *param, s32 paramlen,
+ s8 *iovar_buf, u32 buflen)
+{
+ s32 iolen = 0;
+
+ iolen = bcm_mkiovar(iovar_name, param, paramlen, iovar_buf, buflen);
+ return iolen;
+}
+
+s32 wldev_iovar_getbuf(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync)
+{
+ s32 ret = 0;
+ if (buf_sync) {
+ mutex_lock(buf_sync);
+ }
+ wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
+ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE);
+ if (buf_sync)
+ mutex_unlock(buf_sync);
+ return ret;
+}
+
+
+s32 wldev_iovar_setbuf(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync)
+{
+ s32 ret = 0;
+ s32 iovar_len;
+ if (buf_sync) {
+ mutex_lock(buf_sync);
+ }
+ iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
+ if (iovar_len > 0)
+ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
+ else
+ ret = BCME_BUFTOOSHORT;
+
+ if (buf_sync)
+ mutex_unlock(buf_sync);
+ return ret;
+}
+
+s32 wldev_iovar_setint(
+ struct net_device *dev, s8 *iovar, s32 val)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+ val = htod32(val);
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf,
+ sizeof(iovar_buf), NULL);
+}
+
+
+s32 wldev_iovar_getint(
+ struct net_device *dev, s8 *iovar, s32 *pval)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ s32 err;
+
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf,
+ sizeof(iovar_buf), NULL);
+ if (err == 0)
+ {
+ memcpy(pval, iovar_buf, sizeof(*pval));
+ *pval = dtoh32(*pval);
+ }
+ return err;
+}
+
+/** Format a bsscfg indexed iovar buffer. The bsscfg index will be
+ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to
+ * wl_iw, wl_cfg80211 and wl_cfgp2p
+ */
+s32 wldev_mkiovar_bsscfg(
+ const s8 *iovar_name, s8 *param, s32 paramlen,
+ s8 *iovar_buf, s32 buflen, s32 bssidx)
+{
+ const s8 *prefix = "bsscfg:";
+ s8 *p;
+ u32 prefixlen;
+ u32 namelen;
+ u32 iolen;
+
+ if (bssidx == 0) {
+ return wldev_mkiovar((s8*)iovar_name, (s8 *)param, paramlen,
+ (s8 *) iovar_buf, buflen);
+ }
+
+ prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
+ namelen = (u32) strlen(iovar_name) + 1; /* lengh of iovar name + null */
+ iolen = prefixlen + namelen + sizeof(u32) + paramlen;
+
+ if (buflen < 0 || iolen > (u32)buflen)
+ {
+ WLDEV_ERROR(("%s: buffer is too short\n", __FUNCTION__));
+ return BCME_BUFTOOSHORT;
+ }
+
+ p = (s8 *)iovar_buf;
+
+ /* copy prefix, no null */
+ memcpy(p, prefix, prefixlen);
+ p += prefixlen;
+
+ /* copy iovar name including null */
+ memcpy(p, iovar_name, namelen);
+ p += namelen;
+
+ /* bss config index as first param */
+ bssidx = htod32(bssidx);
+ memcpy(p, &bssidx, sizeof(u32));
+ p += sizeof(u32);
+
+ /* parameter buffer follows */
+ if (paramlen)
+ memcpy(p, param, paramlen);
+
+ return iolen;
+
+}
+
+s32 wldev_iovar_getbuf_bsscfg(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
+{
+ s32 ret = 0;
+ if (buf_sync) {
+ mutex_lock(buf_sync);
+ }
+
+ wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
+ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE);
+ if (buf_sync) {
+ mutex_unlock(buf_sync);
+ }
+ return ret;
+
+}
+
+s32 wldev_iovar_setbuf_bsscfg(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
+{
+ s32 ret = 0;
+ s32 iovar_len;
+ if (buf_sync) {
+ mutex_lock(buf_sync);
+ }
+ iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
+ if (iovar_len > 0)
+ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
+ else {
+ ret = BCME_BUFTOOSHORT;
+ }
+
+ if (buf_sync) {
+ mutex_unlock(buf_sync);
+ }
+ return ret;
+}
+
+s32 wldev_iovar_setint_bsscfg(
+ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+ val = htod32(val);
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf,
+ sizeof(iovar_buf), bssidx, NULL);
+}
+
+
+s32 wldev_iovar_getint_bsscfg(
+ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ s32 err;
+
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf,
+ sizeof(iovar_buf), bssidx, NULL);
+ if (err == 0)
+ {
+ memcpy(pval, iovar_buf, sizeof(*pval));
+ *pval = dtoh32(*pval);
+ }
+ return err;
+}
+
+int wldev_get_link_speed(
+ struct net_device *dev, int *plink_speed)
+{
+ int error;
+
+ if (!plink_speed)
+ return -ENOMEM;
+ error = wldev_ioctl(dev, WLC_GET_RATE, plink_speed, sizeof(int), 0);
+ if (unlikely(error))
+ return error;
+
+ /* Convert internal 500Kbps to Kbps */
+ *plink_speed *= 500;
+ return error;
+}
+
+int wldev_get_rssi(
+ struct net_device *dev, scb_val_t *scb_val)
+{
+ int error;
+
+ if (!scb_val)
+ return -ENOMEM;
+
+ error = wldev_ioctl(dev, WLC_GET_RSSI, scb_val, sizeof(scb_val_t), 0);
+ if (unlikely(error))
+ return error;
+
+ return error;
+}
+
+int wldev_get_ssid(
+ struct net_device *dev, wlc_ssid_t *pssid)
+{
+ int error;
+
+ if (!pssid)
+ return -ENOMEM;
+ error = wldev_ioctl(dev, WLC_GET_SSID, pssid, sizeof(wlc_ssid_t), 0);
+ if (unlikely(error))
+ return error;
+ pssid->SSID_len = dtoh32(pssid->SSID_len);
+ return error;
+}
+
+int wldev_get_band(
+ struct net_device *dev, uint *pband)
+{
+ int error;
+
+ error = wldev_ioctl(dev, WLC_GET_BAND, pband, sizeof(uint), 0);
+ return error;
+}
+
+int wldev_set_band(
+ struct net_device *dev, uint band)
+{
+ int error = -1;
+
+ if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
+ error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
+ if (!error)
+ dhd_bus_band_set(dev, band);
+ }
+ return error;
+}
+
+int wldev_get_datarate(struct net_device *dev, int *datarate)
+{
+ int error = 0;
+
+ error = wldev_ioctl(dev, WLC_GET_RATE, datarate, sizeof(int), false);
+ if (error) {
+ return -1;
+ } else {
+ *datarate = dtoh32(*datarate);
+ }
+
+ return error;
+}
+
+extern chanspec_t
+wl_chspec_driver_to_host(chanspec_t chanspec);
+#define WL_EXTRA_BUF_MAX 2048
+int wldev_get_mode(
+ struct net_device *dev, uint8 *cap)
+{
+ int error = 0;
+ int chanspec = 0;
+ uint16 band = 0;
+ uint16 bandwidth = 0;
+ wl_bss_info_t *bss = NULL;
+ char* buf = NULL;
+
+ buf = kmalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+
+ if (!buf) {
+ WLDEV_ERROR(("%s:NOMEM\n", __FUNCTION__));
+ return -ENOMEM;
+ }
+
+ *(u32*) buf = htod32(WL_EXTRA_BUF_MAX);
+ error = wldev_ioctl(dev, WLC_GET_BSS_INFO, (void*)buf, WL_EXTRA_BUF_MAX, false);
+ if (error) {
+ WLDEV_ERROR(("%s:failed:%d\n", __FUNCTION__, error));
+ kfree(buf);
+ buf = NULL;
+ return error;
+ }
+ bss = (struct wl_bss_info *)(buf + 4);
+ chanspec = wl_chspec_driver_to_host(bss->chanspec);
+
+ band = chanspec & WL_CHANSPEC_BAND_MASK;
+ bandwidth = chanspec & WL_CHANSPEC_BW_MASK;
+
+ if (band == WL_CHANSPEC_BAND_2G) {
+ if (bss->n_cap)
+ strcpy(cap, "n");
+ else
+ strcpy(cap, "bg");
+ } else if (band == WL_CHANSPEC_BAND_5G) {
+ if (bandwidth == WL_CHANSPEC_BW_80)
+ strcpy(cap, "ac");
+ else if ((bandwidth == WL_CHANSPEC_BW_40) || (bandwidth == WL_CHANSPEC_BW_20)) {
+ if ((bss->nbss_cap & 0xf00) && (bss->n_cap))
+ strcpy(cap, "n|ac");
+ else if (bss->n_cap)
+ strcpy(cap, "n");
+ else if (bss->vht_cap)
+ strcpy(cap, "ac");
+ else
+ strcpy(cap, "a");
+ } else {
+ WLDEV_ERROR(("%s:Mode get failed\n", __FUNCTION__));
+ error = BCME_ERROR;
+ }
+
+ }
+ kfree(buf);
+ buf = NULL;
+ return error;
+}
+#define MAX_NUM_OF_ASSOCLIST 64
+int wldev_get_assoclist(
+ struct net_device *dev, struct maclist *assoc_maclist, uint length)
+{
+ int ret = 0;
+
+/* get the current list of associated STAs */
+ assoc_maclist->count = MAX_NUM_OF_ASSOCLIST;
+ if ((ret = wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist,
+ length, false)) != 0) {
+ return ret;
+ }
+ return 0;
+}
+
+int wldev_set_country(
+ struct net_device *dev, char *country_code, bool notify, bool user_enforced)
+{
+ int error = -1;
+ wl_country_t cspec = {{0}, 0, {0}};
+ scb_val_t scbval;
+ char smbuf[WLC_IOCTL_SMLEN];
+
+ if (!country_code)
+ return error;
+
+ bzero(&scbval, sizeof(scb_val_t));
+ error = wldev_iovar_getbuf(dev, "country", NULL, 0, &cspec, sizeof(cspec), NULL);
+ if (error < 0) {
+ WLDEV_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error));
+ return error;
+ }
+
+ if ((error < 0) ||
+ (strncmp(country_code, cspec.ccode, WLC_CNTRY_BUF_SZ) != 0)) {
+
+ if (user_enforced) {
+ bzero(&scbval, sizeof(scb_val_t));
+ error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
+ if (error < 0) {
+ WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n",
+ __FUNCTION__, error));
+ return error;
+ }
+ }
+
+ cspec.rev = -1;
+ memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ);
+ memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
+ dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);
+ error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec),
+ smbuf, sizeof(smbuf), NULL);
+ if (error < 0) {
+ WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n",
+ __FUNCTION__, country_code, cspec.ccode, cspec.rev));
+ return error;
+ }
+ dhd_bus_country_set(dev, &cspec, notify);
+ WLDEV_INFO(("%s: set country for %s as %s rev %d\n",
+ __FUNCTION__, country_code, cspec.ccode, cspec.rev));
+ }
+ return 0;
+}
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h
new file mode 100644
index 000000000000..65e1f6b5e171
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wldev_common.h
@@ -0,0 +1,121 @@
+/*
+ * Common function shared by Linux WEXT, cfg80211 and p2p drivers
+ *
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wldev_common.h 513422 2014-11-06 11:06:57Z $
+ */
+#ifndef __WLDEV_COMMON_H__
+#define __WLDEV_COMMON_H__
+
+#include <wlioctl.h>
+
+/* wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or
+ * netdev_ops->ndo_do_ioctl in new kernels)
+ * @dev: the net_device handle
+ */
+s32 wldev_ioctl(
+ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set);
+
+/** Retrieve named IOVARs, this function calls wl_dev_ioctl with
+ * WLC_GET_VAR IOCTL code
+ */
+s32 wldev_iovar_getbuf(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync);
+
+/** Set named IOVARs, this function calls wl_dev_ioctl with
+ * WLC_SET_VAR IOCTL code
+ */
+s32 wldev_iovar_setbuf(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync);
+
+s32 wldev_iovar_setint(
+ struct net_device *dev, s8 *iovar, s32 val);
+
+s32 wldev_iovar_getint(
+ struct net_device *dev, s8 *iovar, s32 *pval);
+
+/** The following function can be implemented if there is a need for bsscfg
+ * indexed IOVARs
+ */
+
+s32 wldev_mkiovar_bsscfg(
+ const s8 *iovar_name, s8 *param, s32 paramlen,
+ s8 *iovar_buf, s32 buflen, s32 bssidx);
+
+/** Retrieve named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
+ * WLC_GET_VAR IOCTL code
+ */
+s32 wldev_iovar_getbuf_bsscfg(
+ struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen,
+ void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync);
+
+/** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
+ * WLC_SET_VAR IOCTL code
+ */
+s32 wldev_iovar_setbuf_bsscfg(
+ struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen,
+ void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync);
+
+s32 wldev_iovar_getint_bsscfg(
+ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx);
+
+s32 wldev_iovar_setint_bsscfg(
+ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx);
+
+extern int dhd_net_set_fw_path(struct net_device *dev, char *fw);
+extern int dhd_net_bus_suspend(struct net_device *dev);
+extern int dhd_net_bus_resume(struct net_device *dev, uint8 stage);
+extern int dhd_net_wifi_platform_set_power(struct net_device *dev, bool on,
+ unsigned long delay_msec);
+extern void dhd_get_customized_country_code(struct net_device *dev, char *country_iso_code,
+ wl_country_t *cspec);
+extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify);
+extern void dhd_bus_band_set(struct net_device *dev, uint band);
+extern int wldev_set_country(struct net_device *dev, char *country_code, bool notify,
+ bool user_enforced);
+extern int net_os_wake_lock(struct net_device *dev);
+extern int net_os_wake_unlock(struct net_device *dev);
+extern int net_os_wake_lock_timeout(struct net_device *dev);
+extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val);
+extern int net_os_set_dtim_skip(struct net_device *dev, int val);
+extern int net_os_set_suspend_disable(struct net_device *dev, int val);
+extern int net_os_set_suspend(struct net_device *dev, int val, int force);
+extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid,
+ int max, int *bytes_left);
+
+/* Get the link speed from dongle, speed is in kpbs */
+int wldev_get_link_speed(struct net_device *dev, int *plink_speed);
+
+int wldev_get_rssi(struct net_device *dev, scb_val_t *prssi);
+
+int wldev_get_ssid(struct net_device *dev, wlc_ssid_t *pssid);
+
+int wldev_get_band(struct net_device *dev, uint *pband);
+int wldev_get_mode(struct net_device *dev, uint8 *pband);
+int wldev_get_chanspec(struct net_device *dev, uint16 *pband);
+int wldev_get_datarate(struct net_device *dev, int *datarate);
+int wldev_get_assoclist(struct net_device *dev, struct maclist *maclist, uint length);
+int wldev_set_band(struct net_device *dev, uint band);
+
+#endif /* __WLDEV_COMMON_H__ */
diff --git a/drivers/of/base.c b/drivers/of/base.c
index a0bccb54a9bd..4d6cbfe6a111 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2049,6 +2049,36 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np,
ap->alias, ap->stem, ap->id, of_node_full_name(np));
}
+/*
+ * of_alias_max_index() - get the maximum index for a given alias stem
+ * @stem: The alias stem for which the maximum index is searched for
+ *
+ * Given an alias stem (the alias without the number) this function
+ * returns the maximum number for which an alias exists.
+ *
+ * Return: The maximum existing alias index or -ENODEV if no alias
+ * exists for this stem.
+ */
+int of_alias_max_index(const char *stem)
+{
+ struct alias_prop *app;
+ int max = -ENODEV;
+
+ mutex_lock(&of_mutex);
+
+ list_for_each_entry(app, &aliases_lookup, link) {
+ if (strcmp(app->stem, stem))
+ continue;
+ if (app->id > max)
+ max = app->id;
+ }
+
+ mutex_unlock(&of_mutex);
+
+ return max;
+}
+EXPORT_SYMBOL_GPL(of_alias_max_index);
+
/**
* of_alias_scan - Scan all properties of the 'aliases' node
*
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 366d8c3c7989..8459c5eb3114 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -31,11 +31,15 @@ static int reserved_mem_count;
#if defined(CONFIG_HAVE_MEMBLOCK)
#include <linux/memblock.h>
-int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
- phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
- phys_addr_t *res_base)
+int __init __weak early_init_dt_alloc_reserved_memory_arch(unsigned long node,
+ phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end,
+ bool nomap, phys_addr_t *res_base)
{
phys_addr_t base;
+ phys_addr_t highmem_start;
+
+ highmem_start = __pa(high_memory - 1) + 1;
+
/*
* We use __memblock_alloc_base() because memblock_alloc_base()
* panic()s on allocation failure.
@@ -53,15 +57,34 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
return -ENOMEM;
}
+ /*
+ * Sanity check for the cma reserved region:If the reserved region
+ * crosses the low/high memory boundary, try to fix it up and then
+ * fall back to allocate the cma region from the low mememory space.
+ */
+
+ if (IS_ENABLED(CONFIG_CMA)
+ && of_flat_dt_is_compatible(node, "shared-dma-pool")
+ && of_get_flat_dt_prop(node, "reusable", NULL) && !nomap) {
+ if (base < highmem_start && (base + size) > highmem_start) {
+ memblock_free(base, size);
+ base = memblock_alloc_range(size, align, start,
+ highmem_start,
+ MEMBLOCK_NONE);
+ if (!base)
+ return -ENOMEM;
+ }
+ }
+
*res_base = base;
if (nomap)
return memblock_remove(base, size);
return 0;
}
#else
-int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
- phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
- phys_addr_t *res_base)
+int __init __weak early_init_dt_alloc_reserved_memory_arch(unsigned long node,
+ phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end,
+ bool nomap, phys_addr_t *res_base)
{
pr_err("Reserved memory not supported, ignoring region 0x%llx%s\n",
size, nomap ? " (nomap)" : "");
@@ -155,8 +178,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
end = start + dt_mem_next_cell(dt_root_size_cells,
&prop);
- ret = early_init_dt_alloc_reserved_memory_arch(size,
- align, start, end, nomap, &base);
+ ret = early_init_dt_alloc_reserved_memory_arch(node,
+ size, align, start, end, nomap, &base);
if (ret == 0) {
pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n",
uname, &base,
@@ -167,8 +190,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
}
} else {
- ret = early_init_dt_alloc_reserved_memory_arch(size, align,
- 0, 0, nomap, &base);
+ ret = early_init_dt_alloc_reserved_memory_arch(node,
+ size, align, 0, 0, nomap, &base);
if (ret == 0)
pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n",
uname, &base, (unsigned long)size / SZ_1M);
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index d7e7c0a827c3..abe803c5398d 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -62,11 +62,33 @@ config PCI_EXYNOS
config PCI_IMX6
bool "Freescale i.MX6 PCIe controller"
- depends on SOC_IMX6Q
+ depends on SOC_IMX6Q || SOC_IMX6SX || SOC_IMX7D
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW
+config PCI_IMX6_COMPLIANCE_TEST
+ bool "Enable pcie compliance tests on imx6"
+ depends on PCI_IMX6
+ default n
+ help
+ Say Y here if you want do the compliance tests on imx6 pcie rc found
+ on FSL iMX SoCs. The pcie clks wouldn't be turned off, and the link
+ speed wouldn't be limited to gen1 when the Y is set here.
+
+config EP_MODE_IN_EP_RC_SYS
+ bool "PCI Express EP mode in the IMX6 RC/EP interconnection system"
+ depends on PCI_IMX6
+
+config RC_MODE_IN_EP_RC_SYS
+ bool "PCI Express RC mode in the IMX6 RC/EP interconnection system"
+ depends on PCI_IMX6 && EP_MODE_IN_EP_RC_SYS!=y
+
+config PCI_IMX_EP_DRV
+ bool "i.MX6 PCI Express EP skeleton driver"
+ depends on RC_MODE_IN_EP_RC_SYS
+ default y
+
config PCI_TEGRA
bool "NVIDIA Tegra PCIe controller"
depends on ARCH_TEGRA && !ARM64
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 084cb4983645..8d1fbb2d2b50 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -1,9 +1,11 @@
+
obj-$(CONFIG_PCIE_DW) += pcie-designware.o
obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
+obj-$(CONFIG_PCI_IMX_EP_DRV) += pci-imx6-ep-driver.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
diff --git a/drivers/pci/host/pci-imx6-ep-driver.c b/drivers/pci/host/pci-imx6-ep-driver.c
new file mode 100644
index 000000000000..192ced7cbffc
--- /dev/null
+++ b/drivers/pci/host/pci-imx6-ep-driver.c
@@ -0,0 +1,171 @@
+/*
+ * PCIe endpoint skeleton driver for IMX6 SOCs
+ *
+ * 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.
+
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+
+#define DRV_DESCRIPTION "i.MX PCIE endpoint device driver"
+#define DRV_VERSION "version 0.1"
+#define DRV_NAME "imx_pcie_ep"
+
+struct imx_pcie_ep_priv {
+ struct pci_dev *pci_dev;
+ void __iomem *hw_base;
+};
+
+/**
+ * imx_pcie_ep_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @id: entry in id_tbl
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int imx_pcie_ep_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int ret = 0;
+ unsigned int msi_addr = 0;
+ struct device_node *np;
+ struct device *dev = &pdev->dev;
+ struct imx_pcie_ep_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(dev, "can't alloc imx pcie priv\n");
+ return -ENOMEM;
+ }
+
+ priv->pci_dev = pdev;
+
+ if (pci_enable_device(pdev)) {
+ ret = -ENODEV;
+ goto out;
+ }
+ pci_set_master(pdev);
+
+ pci_set_drvdata(pdev, priv);
+
+ priv->hw_base = pci_iomap(pdev, 0, 0);
+ if (!priv->hw_base) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ pr_info("pci_resource_len = 0x%08llx\n",
+ (unsigned long long) pci_resource_len(pdev, 0));
+ pr_info("pci_resource_base = %p\n", priv->hw_base);
+
+ ret = pci_enable_msi(priv->pci_dev);
+ if (ret < 0) {
+ dev_err(dev, "can't enable msi\n");
+ return ret;
+ }
+
+ np = of_find_compatible_node(NULL, NULL, "snps,dw-pcie");
+
+ /*
+ * Force to use the hardcode MSI address to do the MSI demo
+ */
+ if (of_device_is_compatible(np, "fsl,imx7d-pcie"))
+ msi_addr = 0x4FFC0000;
+ else if (of_device_is_compatible(np, "fsl,imx6sx-pcie"))
+ msi_addr = 0x08FF8000;
+ else
+ msi_addr = 0x01FF8000;
+
+ pr_info("pci_msi_addr = 0x%08x\n", msi_addr);
+ pci_bus_write_config_dword(pdev->bus, 0, 0x54, msi_addr);
+ pci_bus_write_config_dword(pdev->bus->parent, 0, 0x820, msi_addr);
+
+ /* configure rc's msi cap */
+ pci_bus_read_config_dword(pdev->bus->parent, 0, 0x50, &ret);
+ ret |= (PCI_MSI_FLAGS_ENABLE << 16);
+ pci_bus_write_config_dword(pdev->bus->parent, 0, 0x50, ret);
+ pci_bus_write_config_dword(pdev->bus->parent, 0, 0x828, 0x1);
+ pci_bus_write_config_dword(pdev->bus->parent, 0, 0x82C, 0xFFFFFFFE);
+
+ return 0;
+
+out:
+ return ret;
+}
+
+static void imx_pcie_ep_remove(struct pci_dev *pdev)
+{
+ struct imx_pcie_ep_priv *priv = pci_get_drvdata(pdev);
+
+ if (!priv)
+ return;
+ pr_info("***imx pcie ep driver unload***\n");
+}
+
+static struct pci_device_id imx_pcie_ep_ids[] = {
+ {
+ .class = PCI_CLASS_MEMORY_RAM << 8,
+ .class_mask = ~0,
+ .vendor = 0xbeaf,
+ .device = 0xdead,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ { } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, imx_pcie_ep_ids);
+
+static struct pci_driver imx_pcie_ep_driver = {
+ .name = DRV_NAME,
+ .id_table = imx_pcie_ep_ids,
+ .probe = imx_pcie_ep_probe,
+ .remove = imx_pcie_ep_remove,
+};
+
+static int __init imx_pcie_ep_init(void)
+{
+ int ret;
+ pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+
+ ret = pci_register_driver(&imx_pcie_ep_driver);
+ if (ret)
+ pr_err("Unable to initialize PCI module\n");
+
+ return ret;
+}
+
+static void __exit imx_pcie_ep_exit(void)
+{
+ pci_unregister_driver(&imx_pcie_ep_driver);
+}
+
+module_exit(imx_pcie_ep_exit);
+module_init(imx_pcie_ep_init);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("imx_pcie_ep");
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index c8cefb078218..1fb3ec9ecf71 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -17,16 +17,22 @@
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
#include <linux/module.h>
-#include <linux/of_gpio.h>
+#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/resource.h>
#include <linux/signal.h>
#include <linux/types.h>
#include <linux/interrupt.h>
+#include <linux/busfreq-imx.h>
+#include <linux/regulator/consumer.h>
#include "pcie-designware.h"
@@ -36,16 +42,32 @@ enum imx6_pcie_variants {
IMX6Q,
IMX6SX,
IMX6QP,
+ IMX7D,
};
+/*
+ * The default value of the reserved ddr memory
+ * used to verify EP/RC memory space access operations.
+ * The layout of the 1G ddr on SD boards
+ * [imx6qdl-sd-ard boards]0x1000_0000 ~ 0x4FFF_FFFF
+ * [imx6sx,imx7d platforms]0x8000_0000 ~ 0xBFFF_FFFF
+ *
+ */
+static u32 ddr_test_region = 0, test_region_size = SZ_2M;
+
struct imx6_pcie {
struct pcie_port pp; /* pp.dbi_base is DT 0th resource */
+ u32 ext_osc;
+ int dis_gpio;
+ int power_on_gpio;
int reset_gpio;
bool gpio_active_high;
struct clk *pcie_bus;
- struct clk *pcie_phy;
struct clk *pcie_inbound_axi;
+ struct clk *pcie_phy;
struct clk *pcie;
+ struct clk *pcie_ext;
+ struct clk *pcie_ext_src;
struct regmap *iomuxc_gpr;
enum imx6_pcie_variants variant;
u32 tx_deemph_gen1;
@@ -54,6 +76,10 @@ struct imx6_pcie {
u32 tx_swing_full;
u32 tx_swing_low;
int link_gen;
+ struct regmap *reg_src;
+ void __iomem *phy_base;
+ struct regulator *pcie_phy_regulator;
+ struct regulator *pcie_bus_regulator;
};
/* PCIe Root Complex registers (memory-mapped) */
@@ -95,6 +121,31 @@ struct imx6_pcie {
#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
+#define SSP_CR_SUP_DIG_MPLL_OVRD_IN_LO 0x0011
+/* FIELD: RES_ACK_IN_OVRD [15:15]
+ * FIELD: RES_ACK_IN [14:14]
+ * FIELD: RES_REQ_IN_OVRD [13:13]
+ * FIELD: RES_REQ_IN [12:12]
+ * FIELD: RTUNE_REQ_OVRD [11:11]
+ * FIELD: RTUNE_REQ [10:10]
+ * FIELD: MPLL_MULTIPLIER_OVRD [9:9]
+ * FIELD: MPLL_MULTIPLIER [8:2]
+ * FIELD: MPLL_EN_OVRD [1:1]
+ * FIELD: MPLL_EN [0:0]
+ */
+
+#define SSP_CR_SUP_DIG_ATEOVRD 0x0010
+/* FIELD: ateovrd_en [2:2]
+ * FIELD: ref_usb2_en [1:1]
+ * FIELD: ref_clkdiv2 [0:0]
+ */
+
+/* iMX7 PCIe PHY registers */
+#define PCIE_PHY_CMN_REG15 0x54
+#define PCIE_PHY_CMN_REG15_DLY_4 (1 << 2)
+#define PCIE_PHY_CMN_REG15_PLL_PD (1 << 5)
+#define PCIE_PHY_CMN_REG15_OVRD_PLL_PD (1 << 7)
+
static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val)
{
struct pcie_port *pp = &imx6_pcie->pp;
@@ -298,6 +349,12 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
break;
+ case IMX7D:
+ /* G_RST */
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c, BIT(1), BIT(1));
+ /* BTNRST */
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c, BIT(2), BIT(2));
+ break;
}
}
@@ -333,33 +390,65 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
break;
+ case IMX7D:
+ break;
}
return ret;
}
+static void pci_imx_phy_pll_locked(struct imx6_pcie *imx6_pcie)
+{
+ u32 val;
+ int count = 20000;
+
+ while (count--) {
+ regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val);
+ if (val & BIT(31))
+ break;
+ udelay(10);
+ if (count == 0)
+ pr_info("pcie phy pll can't be locked.\n");
+ }
+}
+
static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
{
struct pcie_port *pp = &imx6_pcie->pp;
struct device *dev = pp->dev;
int ret;
+ u32 val;
- ret = clk_prepare_enable(imx6_pcie->pcie_phy);
+ if (gpio_is_valid(imx6_pcie->power_on_gpio))
+ gpio_set_value_cansleep(imx6_pcie->power_on_gpio, 1);
+
+ request_bus_freq(BUS_FREQ_HIGH);
+ ret = clk_prepare_enable(imx6_pcie->pcie);
if (ret) {
- dev_err(dev, "unable to enable pcie_phy clock\n");
+ dev_err(dev, "unable to enable pcie clock\n");
return;
}
- ret = clk_prepare_enable(imx6_pcie->pcie_bus);
- if (ret) {
- dev_err(dev, "unable to enable pcie_bus clock\n");
- goto err_pcie_bus;
+ if (imx6_pcie->ext_osc) {
+ clk_set_parent(imx6_pcie->pcie_ext,
+ imx6_pcie->pcie_ext_src);
+ ret = clk_prepare_enable(imx6_pcie->pcie_ext);
+ if (ret) {
+ dev_err(pp->dev, "unable to enable pcie_ext clock\n");
+ goto err_pcie_bus;
+ }
+ } else {
+ ret = clk_prepare_enable(imx6_pcie->pcie_bus);
+ if (ret) {
+ dev_err(pp->dev, "unable to enable pcie_bus clock\n");
+ goto err_pcie_bus;
+ }
}
- ret = clk_prepare_enable(imx6_pcie->pcie);
+ ret = clk_prepare_enable(imx6_pcie->pcie_phy);
if (ret) {
- dev_err(dev, "unable to enable pcie clock\n");
- goto err_pcie;
+ dev_err(dev, "unable to enable pcie_phy clock\n");
+ goto err_pcie_phy;
}
ret = imx6_pcie_enable_ref_clk(imx6_pcie);
@@ -369,16 +458,7 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
}
/* allow the clocks to stabilize */
- usleep_range(200, 500);
-
- /* Some boards don't have PCIe reset GPIO. */
- if (gpio_is_valid(imx6_pcie->reset_gpio)) {
- gpio_set_value_cansleep(imx6_pcie->reset_gpio,
- imx6_pcie->gpio_active_high);
- msleep(100);
- gpio_set_value_cansleep(imx6_pcie->reset_gpio,
- !imx6_pcie->gpio_active_high);
- }
+ udelay(200);
switch (imx6_pcie->variant) {
case IMX6SX:
@@ -389,68 +469,190 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_SW_RST, 0);
- usleep_range(200, 500);
+ udelay(200);
+
+ /* Configure the PHY when 100Mhz external OSC is used as input clock */
+ if (!imx6_pcie->ext_osc)
+ break;
+
+ mdelay(4);
+ pcie_phy_read(imx6_pcie, SSP_CR_SUP_DIG_MPLL_OVRD_IN_LO, &val);
+ /* MPLL_MULTIPLIER [8:2] */
+ val &= ~(0x7F << 2);
+ val |= (0x19 << 2);
+ /* MPLL_MULTIPLIER_OVRD [9:9] */
+ val |= (0x1 << 9);
+ pcie_phy_write(imx6_pcie, SSP_CR_SUP_DIG_MPLL_OVRD_IN_LO, val);
+ mdelay(4);
+
+ pcie_phy_read(imx6_pcie, SSP_CR_SUP_DIG_ATEOVRD, &val);
+ /* ref_clkdiv2 [0:0] */
+ val &= ~0x1;
+ /* ateovrd_en [2:2] */
+ val |= 0x4;
+ pcie_phy_write(imx6_pcie, SSP_CR_SUP_DIG_ATEOVRD, val);
+ mdelay(4);
+
break;
- case IMX6Q: /* Nothing to do */
+ case IMX6Q:
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_SW_RST, 0);
+ /*
+ * some delay are required by 6qp, after the SW_RST is
+ * cleared, before access the cfg register.
+ */
+ udelay(200);
+ break;
+ case IMX7D:
+ /* wait for more than 10us to release phy g_rst and btnrst */
+ udelay(10);
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c, BIT(6), 0);
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c, BIT(1), 0);
+
+ /* Add the workaround for ERR010728 */
+ if (unlikely(imx6_pcie->phy_base == NULL)) {
+ pr_err("phy base shouldn't be null.\n");
+ } else {
+ writel(PCIE_PHY_CMN_REG15_DLY_4,
+ imx6_pcie->phy_base + PCIE_PHY_CMN_REG15);
+ writel(PCIE_PHY_CMN_REG15_DLY_4
+ | PCIE_PHY_CMN_REG15_PLL_PD
+ | PCIE_PHY_CMN_REG15_OVRD_PLL_PD,
+ imx6_pcie->phy_base + PCIE_PHY_CMN_REG15);
+ writel(PCIE_PHY_CMN_REG15_DLY_4,
+ imx6_pcie->phy_base + PCIE_PHY_CMN_REG15);
+ }
+
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c, BIT(2), 0);
+
+ /* wait for phy pll lock firstly. */
+ pci_imx_phy_pll_locked(imx6_pcie);
break;
}
+ /* Some boards don't have PCIe reset GPIO. */
+ if (gpio_is_valid(imx6_pcie->reset_gpio)) {
+ gpio_set_value_cansleep(imx6_pcie->reset_gpio,
+ imx6_pcie->gpio_active_high);
+ mdelay(20);
+ gpio_set_value_cansleep(imx6_pcie->reset_gpio,
+ !imx6_pcie->gpio_active_high);
+ mdelay(20);
+ }
+
return;
err_ref_clk:
- clk_disable_unprepare(imx6_pcie->pcie);
-err_pcie:
- clk_disable_unprepare(imx6_pcie->pcie_bus);
-err_pcie_bus:
clk_disable_unprepare(imx6_pcie->pcie_phy);
+err_pcie_phy:
+ if (!imx6_pcie->ext_osc)
+ clk_disable_unprepare(imx6_pcie->pcie_bus);
+err_pcie_bus:
+ clk_disable_unprepare(imx6_pcie->pcie);
}
static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
{
+ int ret;
+
if (imx6_pcie->variant == IMX6SX)
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
IMX6SX_GPR12_PCIE_RX_EQ_MASK,
IMX6SX_GPR12_PCIE_RX_EQ_2);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
-
- /* configure constant input signal to the pcie ctrl and phy */
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
-
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_DEEMPH_GEN1,
- imx6_pcie->tx_deemph_gen1 << 0);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
- imx6_pcie->tx_deemph_gen2_3p5db << 6);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
- imx6_pcie->tx_deemph_gen2_6db << 12);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_SWING_FULL,
- imx6_pcie->tx_swing_full << 18);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_SWING_LOW,
- imx6_pcie->tx_swing_low << 25);
+ if (imx6_pcie->variant == IMX7D) {
+ /* Enable PCIe PHY 1P0D */
+ regulator_set_voltage(imx6_pcie->pcie_phy_regulator,
+ 1000000, 1000000);
+ ret = regulator_enable(imx6_pcie->pcie_phy_regulator);
+ if (ret)
+ dev_err(imx6_pcie->pp.dev,
+ "failed to enable pcie regulator\n");
+
+ /* pcie phy ref clock select; 1? internal pll : external osc */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ BIT(5), 0);
+ } else if (imx6_pcie->variant == IMX6SX) {
+ /* Force PCIe PHY reset */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
+ IMX6SX_GPR5_PCIE_BTNRST_RESET,
+ IMX6SX_GPR5_PCIE_BTNRST_RESET);
+
+ regulator_set_voltage(imx6_pcie->pcie_phy_regulator,
+ 1100000, 1100000);
+ ret = regulator_enable(imx6_pcie->pcie_phy_regulator);
+ if (ret)
+ dev_err(imx6_pcie->pp.dev,
+ "failed to enable pcie regulator.\n");
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6SX_GPR12_PCIE_RX_EQ_MASK,
+ IMX6SX_GPR12_PCIE_RX_EQ_2);
+ }
+
+ if (imx6_pcie->pcie_bus_regulator != NULL) {
+ ret = regulator_enable(imx6_pcie->pcie_bus_regulator);
+ if (ret)
+ dev_err(imx6_pcie->pp.dev, "failed to enable pcie regulator.\n");
+ }
+
+ if (imx6_pcie->variant != IMX7D) {
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
+
+ /* configure constant input signal to the pcie ctrl and phy */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_LOS_LEVEL, IMX6Q_GPR12_LOS_LEVEL_9);
+
+
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+ IMX6Q_GPR8_TX_DEEMPH_GEN1,
+ imx6_pcie->tx_deemph_gen1 << 0);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+ IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
+ imx6_pcie->tx_deemph_gen2_3p5db << 6);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+ IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
+ imx6_pcie->tx_deemph_gen2_6db << 12);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+ IMX6Q_GPR8_TX_SWING_FULL,
+ imx6_pcie->tx_swing_full << 18);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+ IMX6Q_GPR8_TX_SWING_LOW,
+ imx6_pcie->tx_swing_low << 25);
+ }
+
+ /* configure the device type */
+ if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS))
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_DEVICE_TYPE,
+ PCI_EXP_TYPE_ENDPOINT << 12);
+ else
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_DEVICE_TYPE,
+ PCI_EXP_TYPE_ROOT_PORT << 12);
}
static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
{
+ int count = 20000;
struct pcie_port *pp = &imx6_pcie->pp;
struct device *dev = pp->dev;
/* check if the link is up or not */
- if (!dw_pcie_wait_for_link(pp))
- return 0;
- dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
- dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0),
- dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1));
- return -ETIMEDOUT;
+ while (!dw_pcie_link_up(pp)) {
+ udelay(10);
+ if (--count)
+ continue;
+
+ dev_err(pp->dev, "phy link never came up\n");
+ dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
+ dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0),
+ dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1));
+ return -ETIMEDOUT;
+ }
+
+ return 0;
}
static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
@@ -465,7 +667,7 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
/* Test if the speed change finished. */
if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
return 0;
- usleep_range(100, 1000);
+ udelay(100);
}
dev_err(dev, "Speed change timeout\n");
@@ -492,14 +694,19 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
* started in Gen2 mode, there is a possibility the devices on the
* bus will not be detected at all. This happens with PCIe switches.
*/
- tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR);
- tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
- tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
- dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp);
+ if (!IS_ENABLED(CONFIG_PCI_IMX6_COMPLIANCE_TEST)) {
+ tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR);
+ tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
+ tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
+ dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp);
+ }
/* Start LTSSM. */
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
+ if (imx6_pcie->variant == IMX7D)
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c, BIT(6), BIT(6));
+ else
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
ret = imx6_pcie_wait_for_link(imx6_pcie);
if (ret) {
@@ -515,6 +722,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp);
} else {
dev_info(dev, "Link: Gen2 disabled\n");
+ goto out;
}
/*
@@ -527,8 +735,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
ret = imx6_pcie_wait_for_speed_change(imx6_pcie);
if (ret) {
- dev_err(dev, "Failed to bring link up!\n");
- goto err_reset_phy;
+ dev_info(dev, "Roll back to GEN1 link!\n");
}
/* Make sure link training is finished as well! */
@@ -538,6 +745,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
goto err_reset_phy;
}
+out:
tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCSR);
dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf);
return 0;
@@ -547,21 +755,45 @@ err_reset_phy:
dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0),
dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1));
imx6_pcie_reset_phy(imx6_pcie);
+
+ if (!IS_ENABLED(CONFIG_PCI_IMX6_COMPLIANCE_TEST)) {
+ clk_disable_unprepare(imx6_pcie->pcie);
+ if (!imx6_pcie->ext_osc)
+ clk_disable_unprepare(imx6_pcie->pcie_bus);
+ clk_disable_unprepare(imx6_pcie->pcie_phy);
+ if (imx6_pcie->variant == IMX6SX)
+ clk_disable_unprepare(imx6_pcie->pcie_inbound_axi);
+ release_bus_freq(BUS_FREQ_HIGH);
+ if (imx6_pcie->pcie_phy_regulator != NULL)
+ regulator_disable(imx6_pcie->pcie_phy_regulator);
+ if (imx6_pcie->pcie_bus_regulator != NULL)
+ regulator_disable(imx6_pcie->pcie_bus_regulator);
+ }
+
return ret;
}
-static void imx6_pcie_host_init(struct pcie_port *pp)
+static int imx6_pcie_host_init(struct pcie_port *pp)
{
+ int ret;
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ /* enable disp_mix power domain */
+ if (imx6_pcie->variant == IMX7D)
+ pm_runtime_get_sync(pp->dev);
+
imx6_pcie_assert_core_reset(imx6_pcie);
imx6_pcie_init_phy(imx6_pcie);
imx6_pcie_deassert_core_reset(imx6_pcie);
dw_pcie_setup_rc(pp);
- imx6_pcie_establish_link(imx6_pcie);
+ ret = imx6_pcie_establish_link(imx6_pcie);
+ if (ret < 0)
+ return ret;
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
+
+ return 0;
}
static int imx6_pcie_link_up(struct pcie_port *pp)
@@ -575,7 +807,7 @@ static struct pcie_host_ops imx6_pcie_host_ops = {
.host_init = imx6_pcie_host_init,
};
-static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
+static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
struct platform_device *pdev)
{
struct pcie_port *pp = &imx6_pcie->pp;
@@ -611,11 +843,350 @@ static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
return 0;
}
-static int __init imx6_pcie_probe(struct platform_device *pdev)
+static ssize_t imx_pcie_bar0_addr_info(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+ struct pcie_port *pp = &imx6_pcie->pp;
+
+ return sprintf(buf, "imx-pcie-bar0-addr-info start 0x%08x\n",
+ readl(pp->dbi_base + PCI_BASE_ADDRESS_0));
+}
+
+static ssize_t imx_pcie_bar0_addr_start(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ u32 bar_start;
+ struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+ struct pcie_port *pp = &imx6_pcie->pp;
+
+ sscanf(buf, "%x\n", &bar_start);
+ writel(bar_start, pp->dbi_base + PCI_BASE_ADDRESS_0);
+
+ return count;
+}
+
+static void imx_pcie_regions_setup(struct device *dev)
+{
+ struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+ struct pcie_port *pp = &imx6_pcie->pp;
+
+ if (imx6_pcie->variant == IMX7D && ddr_test_region == 0)
+ ddr_test_region = 0xb0000000;
+ else if (imx6_pcie->variant == IMX6SX && ddr_test_region == 0)
+ ddr_test_region = 0xb0000000;
+ else if (ddr_test_region == 0)
+ ddr_test_region = 0x40000000;
+
+ /*
+ * region2 outbound used to access rc/ep mem
+ * in imx6 pcie ep/rc validation system
+ */
+ writel(2, pp->dbi_base + 0x900);
+ writel((u32)pp->mem_base, pp->dbi_base + 0x90c);
+ writel(0, pp->dbi_base + 0x910);
+ writel((u32)pp->mem_base + test_region_size, pp->dbi_base + 0x914);
+
+ writel(ddr_test_region, pp->dbi_base + 0x918);
+ writel(0, pp->dbi_base + 0x91c);
+ writel(0, pp->dbi_base + 0x904);
+ writel(1 << 31, pp->dbi_base + 0x908);
+}
+
+static ssize_t imx_pcie_memw_info(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return sprintf(buf, "imx-pcie-rc-memw-info start 0x%08x, size 0x%08x\n",
+ ddr_test_region, test_region_size);
+}
+
+static ssize_t
+imx_pcie_memw_start(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 memw_start;
+ struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+
+ sscanf(buf, "%x\n", &memw_start);
+
+ if (imx6_pcie->variant == IMX7D || imx6_pcie->variant == IMX6SX) {
+ if (memw_start < 0x80000000 || memw_start > 0xb0000000) {
+ dev_err(dev, "Invalid memory start addr.\n");
+ dev_info(dev, "e.x: echo 0xb0000000 > /sys/...");
+ return -1;
+ }
+ } else {
+ if (memw_start < 0x10000000 || memw_start > 0x40000000) {
+ dev_err(dev, "Invalid imx6q sd memory start addr.\n");
+ dev_info(dev, "e.x: echo 0x30000000 > /sys/...");
+ return -1;
+ }
+ }
+
+ if (ddr_test_region != memw_start) {
+ ddr_test_region = memw_start;
+ imx_pcie_regions_setup(dev);
+ }
+
+ return count;
+}
+
+static ssize_t
+imx_pcie_memw_size(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 memw_size;
+
+ sscanf(buf, "%x\n", &memw_size);
+
+ if ((memw_size > (SZ_16M - SZ_1M)) || (memw_size < SZ_64K)) {
+ dev_err(dev, "Invalid, should be [SZ_64K,SZ_16M - SZ_1MB].\n");
+ dev_info(dev, "For example: echo 0x200000 > /sys/...");
+ return -1;
+ }
+
+ if (test_region_size != memw_size) {
+ test_region_size = memw_size;
+ imx_pcie_regions_setup(dev);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(memw_info, S_IRUGO, imx_pcie_memw_info, NULL);
+static DEVICE_ATTR(memw_start_set, S_IWUSR, NULL, imx_pcie_memw_start);
+static DEVICE_ATTR(memw_size_set, S_IWUSR, NULL, imx_pcie_memw_size);
+static DEVICE_ATTR(ep_bar0_addr, S_IWUSR | S_IRUGO, imx_pcie_bar0_addr_info,
+ imx_pcie_bar0_addr_start);
+
+static struct attribute *imx_pcie_attrs[] = {
+ /*
+ * The start address, and the limitation (64KB ~ (16MB - 1MB))
+ * of the ddr mem window reserved by RC, and used for EP to access.
+ * BTW, these attrs are only configured at EP side.
+ */
+ &dev_attr_memw_info.attr,
+ &dev_attr_memw_start_set.attr,
+ &dev_attr_memw_size_set.attr,
+ &dev_attr_ep_bar0_addr.attr,
+ NULL
+};
+
+static struct attribute_group imx_pcie_attrgroup = {
+ .attrs = imx_pcie_attrs,
+};
+
+static void imx6_pcie_setup_ep(struct pcie_port *pp)
+{
+ /* CMD reg:I/O space, MEM space, and Bus Master Enable */
+ writel(readl(pp->dbi_base + PCI_COMMAND)
+ | PCI_COMMAND_IO
+ | PCI_COMMAND_MEMORY
+ | PCI_COMMAND_MASTER,
+ pp->dbi_base + PCI_COMMAND);
+
+ /*
+ * configure the class_rev(emaluate one memory ram ep device),
+ * bar0 and bar1 of ep
+ */
+ writel(0xdeadbeaf, pp->dbi_base + PCI_VENDOR_ID);
+ writel(readl(pp->dbi_base + PCI_CLASS_REVISION)
+ | (PCI_CLASS_MEMORY_RAM << 16),
+ pp->dbi_base + PCI_CLASS_REVISION);
+ writel(0xdeadbeaf, pp->dbi_base
+ + PCI_SUBSYSTEM_VENDOR_ID);
+
+ /* 32bit none-prefetchable 8M bytes memory on bar0 */
+ writel(0x0, pp->dbi_base + PCI_BASE_ADDRESS_0);
+ writel(SZ_8M - 1, pp->dbi_base + (1 << 12)
+ + PCI_BASE_ADDRESS_0);
+
+ /* None used bar1 */
+ writel(0x0, pp->dbi_base + PCI_BASE_ADDRESS_1);
+ writel(0, pp->dbi_base + (1 << 12) + PCI_BASE_ADDRESS_1);
+
+ /* 4K bytes IO on bar2 */
+ writel(0x1, pp->dbi_base + PCI_BASE_ADDRESS_2);
+ writel(SZ_4K - 1, pp->dbi_base + (1 << 12) +
+ PCI_BASE_ADDRESS_2);
+
+ /*
+ * 32bit prefetchable 1M bytes memory on bar3
+ * FIXME BAR MASK3 is not changable, the size
+ * is fixed to 256 bytes.
+ */
+ writel(0x8, pp->dbi_base + PCI_BASE_ADDRESS_3);
+ writel(SZ_1M - 1, pp->dbi_base + (1 << 12)
+ + PCI_BASE_ADDRESS_3);
+
+ /*
+ * 64bit prefetchable 1M bytes memory on bar4-5.
+ * FIXME BAR4,5 are not enabled yet
+ */
+ writel(0xc, pp->dbi_base + PCI_BASE_ADDRESS_4);
+ writel(SZ_1M - 1, pp->dbi_base + (1 << 12)
+ + PCI_BASE_ADDRESS_4);
+ writel(0, pp->dbi_base + (1 << 12) + PCI_BASE_ADDRESS_5);
+}
+
+#ifdef CONFIG_PM_SLEEP
+/* PM_TURN_OFF */
+static void pci_imx_pm_turn_off(struct imx6_pcie *imx6_pcie)
+{
+ /* PM_TURN_OFF */
+ if (imx6_pcie->variant == IMX7D) {
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c,
+ BIT(11), BIT(11));
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c,
+ BIT(11), 0);
+ } else if (imx6_pcie->variant == IMX6SX) {
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6SX_GPR12_PCIE_PM_TURN_OFF,
+ IMX6SX_GPR12_PCIE_PM_TURN_OFF);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6SX_GPR12_PCIE_PM_TURN_OFF, 0);
+ } else if (imx6_pcie->variant == IMX6QP) {
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_PM_TURN_OFF,
+ IMX6Q_GPR12_PCIE_PM_TURN_OFF);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_PM_TURN_OFF, 0);
+ } else {
+ pr_info("Info: don't support pm_turn_off yet.\n");
+ return;
+ }
+
+ udelay(1000);
+ if (gpio_is_valid(imx6_pcie->reset_gpio))
+ gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0);
+}
+
+static int pci_imx_suspend_noirq(struct device *dev)
+{
+ struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+ struct pcie_port *pp = &imx6_pcie->pp;
+
+ if (IS_ENABLED(CONFIG_PCI_MSI))
+ dw_pcie_msi_cfg_store(pp);
+
+ pci_imx_pm_turn_off(imx6_pcie);
+
+ if (imx6_pcie->variant == IMX7D || imx6_pcie->variant == IMX6SX
+ || imx6_pcie->variant == IMX6QP) {
+ /* Disable clks */
+ clk_disable_unprepare(imx6_pcie->pcie);
+ clk_disable_unprepare(imx6_pcie->pcie_phy);
+ if (!imx6_pcie->ext_osc)
+ clk_disable_unprepare(imx6_pcie->pcie_bus);
+ if (imx6_pcie->variant == IMX6SX)
+ clk_disable_unprepare(imx6_pcie->pcie_inbound_axi);
+ else if (imx6_pcie->variant == IMX7D)
+ /* turn off external osc input */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ BIT(5), BIT(5));
+ else if (imx6_pcie->variant == IMX6QP) {
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_REF_CLK_EN, 0);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD,
+ IMX6Q_GPR1_PCIE_TEST_PD);
+ }
+ release_bus_freq(BUS_FREQ_HIGH);
+
+ /* Power down PCIe PHY. */
+ if (imx6_pcie->pcie_phy_regulator != NULL)
+ regulator_disable(imx6_pcie->pcie_phy_regulator);
+ if (imx6_pcie->pcie_bus_regulator != NULL)
+ regulator_disable(imx6_pcie->pcie_bus_regulator);
+ if (gpio_is_valid(imx6_pcie->power_on_gpio))
+ gpio_set_value_cansleep(imx6_pcie->power_on_gpio, 0);
+ } else {
+ /*
+ * L2 can exit by 'reset' or Inband beacon (from remote EP)
+ * toggling phy_powerdown has same effect as 'inband beacon'
+ * So, toggle bit18 of GPR1, used as a workaround of errata
+ * "PCIe PCIe does not support L2 Power Down"
+ */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD,
+ IMX6Q_GPR1_PCIE_TEST_PD);
+ }
+
+ return 0;
+}
+
+static int pci_imx_resume_noirq(struct device *dev)
+{
+ int ret = 0;
+ struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+ struct pcie_port *pp = &imx6_pcie->pp;
+
+ if (imx6_pcie->variant == IMX7D || imx6_pcie->variant == IMX6SX ||
+ imx6_pcie->variant == IMX6QP) {
+ if (imx6_pcie->variant == IMX7D)
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c, BIT(6), 0);
+ else
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_CTL_2, 0);
+
+ imx6_pcie_assert_core_reset(imx6_pcie);
+
+ imx6_pcie_init_phy(imx6_pcie);
+
+ imx6_pcie_deassert_core_reset(imx6_pcie);
+
+ /*
+ * controller maybe turn off, re-configure again
+ */
+ dw_pcie_setup_rc(pp);
+
+ if (IS_ENABLED(CONFIG_PCI_MSI))
+ dw_pcie_msi_cfg_restore(pp);
+
+ if (imx6_pcie->variant == IMX7D) {
+ /* wait for phy pll lock firstly. */
+ pci_imx_phy_pll_locked(imx6_pcie);
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c,
+ BIT(6), BIT(6));
+ } else {
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_CTL_2,
+ IMX6Q_GPR12_PCIE_CTL_2);
+ }
+
+ ret = imx6_pcie_wait_for_link(imx6_pcie);
+ if (ret < 0)
+ pr_info("pcie link is down after resume.\n");
+ } else {
+ /*
+ * L2 can exit by 'reset' or Inband beacon (from remote EP)
+ * toggling phy_powerdown has same effect as 'inband beacon'
+ * So, toggle bit18 of GPR1, used as a workaround of errata
+ * "PCIe PCIe does not support L2 Power Down"
+ */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD, 0);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops pci_imx_pm_ops = {
+ .suspend_noirq = pci_imx_suspend_noirq,
+ .resume_noirq = pci_imx_resume_noirq,
+ .freeze_noirq = pci_imx_suspend_noirq,
+ .thaw_noirq = pci_imx_resume_noirq,
+ .poweroff_noirq = pci_imx_suspend_noirq,
+ .restore_noirq = pci_imx_resume_noirq,
+};
+#endif
+
+static int imx6_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct imx6_pcie *imx6_pcie;
struct pcie_port *pp;
+ struct device_node *np;
struct resource *dbi_base;
struct device_node *node = dev->of_node;
int ret;
@@ -630,9 +1201,13 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
imx6_pcie->variant =
(enum imx6_pcie_variants)of_device_get_match_data(dev);
- /* Added for PCI abort handling */
- hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
- "imprecise external abort");
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx-pcie-phy");
+ if (np != NULL) {
+ imx6_pcie->phy_base = of_iomap(np, 0);
+ WARN_ON(!imx6_pcie->phy_base);
+ } else {
+ imx6_pcie->phy_base = NULL;
+ }
dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
@@ -640,6 +1215,28 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
return PTR_ERR(pp->dbi_base);
/* Fetch GPIOs */
+ imx6_pcie->dis_gpio = of_get_named_gpio(node, "disable-gpio", 0);
+ if (gpio_is_valid(imx6_pcie->dis_gpio)) {
+ ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->dis_gpio,
+ GPIOF_OUT_INIT_HIGH, "PCIe DIS");
+ if (ret) {
+ dev_err(&pdev->dev, "unable to get disable gpio\n");
+ return ret;
+ }
+ }
+
+ imx6_pcie->power_on_gpio = of_get_named_gpio(node, "power-on-gpio", 0);
+ if (gpio_is_valid(imx6_pcie->power_on_gpio)) {
+ ret = devm_gpio_request_one(&pdev->dev,
+ imx6_pcie->power_on_gpio,
+ GPIOF_OUT_INIT_LOW,
+ "PCIe power enable");
+ if (ret) {
+ dev_err(&pdev->dev, "unable to get power-on gpio\n");
+ return ret;
+ }
+ }
+
imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
imx6_pcie->gpio_active_high = of_property_read_bool(node,
"reset-gpio-active-high");
@@ -653,6 +1250,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
dev_err(dev, "unable to get reset gpio\n");
return ret;
}
+ } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) {
+ return imx6_pcie->reset_gpio;
}
/* Fetch clocks */
@@ -668,6 +1267,26 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
return PTR_ERR(imx6_pcie->pcie_bus);
}
+ if (of_property_read_u32(node, "ext_osc", &imx6_pcie->ext_osc) < 0)
+ imx6_pcie->ext_osc = 0;
+
+ if (imx6_pcie->ext_osc) {
+ imx6_pcie->pcie_ext = devm_clk_get(&pdev->dev, "pcie_ext");
+ if (IS_ERR(imx6_pcie->pcie_ext)) {
+ dev_err(&pdev->dev,
+ "pcie_ext clock source missing or invalid\n");
+ return PTR_ERR(imx6_pcie->pcie_ext);
+ }
+
+ imx6_pcie->pcie_ext_src = devm_clk_get(&pdev->dev,
+ "pcie_ext_src");
+ if (IS_ERR(imx6_pcie->pcie_ext_src)) {
+ dev_err(&pdev->dev,
+ "pcie_ext_src clk src missing or invalid\n");
+ return PTR_ERR(imx6_pcie->pcie_ext_src);
+ }
+ }
+
imx6_pcie->pcie = devm_clk_get(dev, "pcie");
if (IS_ERR(imx6_pcie->pcie)) {
dev_err(dev, "pcie clock source missing or invalid\n");
@@ -683,10 +1302,50 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
return PTR_ERR(imx6_pcie->pcie_inbound_axi);
}
}
+ if (imx6_pcie->variant == IMX6QP) {
+ imx6_pcie->pcie_bus_regulator = devm_regulator_get(pp->dev,
+ "pcie-bus");
+ if (PTR_ERR(imx6_pcie->pcie_bus_regulator) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ if (IS_ERR(imx6_pcie->pcie_bus_regulator))
+ imx6_pcie->pcie_bus_regulator = NULL;
+ } else {
+ imx6_pcie->pcie_bus_regulator = NULL;
+ }
/* Grab GPR config register range */
- imx6_pcie->iomuxc_gpr =
+ if (imx6_pcie->variant == IMX7D) {
+ imx6_pcie->iomuxc_gpr =
+ syscon_regmap_lookup_by_compatible
+ ("fsl,imx7d-iomuxc-gpr");
+ imx6_pcie->reg_src =
+ syscon_regmap_lookup_by_compatible("fsl,imx7d-src");
+ if (IS_ERR(imx6_pcie->reg_src)) {
+ dev_err(&pdev->dev,
+ "imx7d pcie phy src missing or invalid\n");
+ return PTR_ERR(imx6_pcie->reg_src);
+ }
+ imx6_pcie->pcie_phy_regulator = devm_regulator_get(pp->dev,
+ "pcie-phy");
+ } else if (imx6_pcie->variant == IMX6SX) {
+ imx6_pcie->pcie_inbound_axi = devm_clk_get(&pdev->dev,
+ "pcie_inbound_axi");
+ if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
+ dev_err(&pdev->dev,
+ "pcie clock source missing or invalid\n");
+ return PTR_ERR(imx6_pcie->pcie_inbound_axi);
+ }
+
+ imx6_pcie->pcie_phy_regulator = devm_regulator_get(pp->dev,
+ "pcie-phy");
+
+ imx6_pcie->iomuxc_gpr =
+ syscon_regmap_lookup_by_compatible
+ ("fsl,imx6sx-iomuxc-gpr");
+ } else {
+ imx6_pcie->iomuxc_gpr =
syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ }
if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
dev_err(dev, "unable to find iomuxc registers\n");
return PTR_ERR(imx6_pcie->iomuxc_gpr);
@@ -695,11 +1354,11 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
/* Grab PCIe PHY Tx Settings */
if (of_property_read_u32(node, "fsl,tx-deemph-gen1",
&imx6_pcie->tx_deemph_gen1))
- imx6_pcie->tx_deemph_gen1 = 0;
+ imx6_pcie->tx_deemph_gen1 = 20;
if (of_property_read_u32(node, "fsl,tx-deemph-gen2-3p5db",
&imx6_pcie->tx_deemph_gen2_3p5db))
- imx6_pcie->tx_deemph_gen2_3p5db = 0;
+ imx6_pcie->tx_deemph_gen2_3p5db = 20;
if (of_property_read_u32(node, "fsl,tx-deemph-gen2-6db",
&imx6_pcie->tx_deemph_gen2_6db))
@@ -707,11 +1366,11 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
if (of_property_read_u32(node, "fsl,tx-swing-full",
&imx6_pcie->tx_swing_full))
- imx6_pcie->tx_swing_full = 127;
+ imx6_pcie->tx_swing_full = 115;
if (of_property_read_u32(node, "fsl,tx-swing-low",
&imx6_pcie->tx_swing_low))
- imx6_pcie->tx_swing_low = 127;
+ imx6_pcie->tx_swing_low = 115;
/* Limit link speed */
ret = of_property_read_u32(node, "fsl,max-link-speed",
@@ -719,11 +1378,175 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
if (ret)
imx6_pcie->link_gen = 1;
- ret = imx6_add_pcie_port(imx6_pcie, pdev);
- if (ret < 0)
- return ret;
+ if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)) {
+ int i;
+ void *test_reg1, *test_reg2;
+ void __iomem *pcie_arb_base_addr;
+ struct timeval tv1s, tv1e, tv2s, tv2e;
+ u32 tv_count1, tv_count2;
+ struct device_node *np = pp->dev->of_node;
+ LIST_HEAD(res);
+ struct resource_entry *win, *tmp;
+
+ /* add attributes for device */
+ ret = sysfs_create_group(&pdev->dev.kobj, &imx_pcie_attrgroup);
+ if (ret)
+ return -EINVAL;
+
+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
+ &pp->io_base);
+ if (ret)
+ return ret;
+
+ ret = devm_request_pci_bus_resources(&pdev->dev, &res);
+ if (ret) {
+ dev_err(pp->dev, "missing ranges property\n");
+ pci_free_resource_list(&res);
+ return ret;
+ }
- platform_set_drvdata(pdev, imx6_pcie);
+ /* Get the I/O and memory ranges from DT */
+ resource_list_for_each_entry_safe(win, tmp, &res) {
+ switch (resource_type(win->res)) {
+ case IORESOURCE_MEM:
+ pp->mem = win->res;
+ pp->mem->name = "MEM";
+ pp->mem_size = resource_size(pp->mem);
+ pp->mem_bus_addr = pp->mem->start - win->offset;
+ break;
+ }
+ }
+
+ pp->mem_base = pp->mem->start;
+ pp->ops = &imx6_pcie_host_ops;
+
+ /* enable disp_mix power domain */
+ if (imx6_pcie->variant == IMX7D)
+ pm_runtime_get_sync(pp->dev);
+
+ imx6_pcie_assert_core_reset(imx6_pcie);
+ imx6_pcie_init_phy(imx6_pcie);
+ imx6_pcie_deassert_core_reset(imx6_pcie);
+
+ /*
+ * iMX6SX PCIe has the stand-alone power domain.
+ * refer to the initialization for iMX6SX PCIe,
+ * release the PCIe PHY reset here,
+ * before LTSSM enable is set
+ * .
+ */
+ if (imx6_pcie->variant == IMX6SX)
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
+ BIT(19), 0 << 19);
+
+ /* assert LTSSM enable */
+ if (imx6_pcie->variant == IMX7D) {
+ regmap_update_bits(imx6_pcie->reg_src, 0x2c,
+ BIT(6), BIT(6));
+ } else {
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
+ }
+
+ dev_info(&pdev->dev, "PCIe EP: waiting for link up...\n");
+
+ platform_set_drvdata(pdev, imx6_pcie);
+ /* link is indicated by the bit4 of DB_R1 register */
+ do {
+ usleep_range(10, 20);
+ } while ((readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & 0x10) == 0);
+
+ imx6_pcie_setup_ep(pp);
+
+ imx_pcie_regions_setup(&pdev->dev);
+
+ /* self io test */
+ test_reg1 = devm_kzalloc(&pdev->dev,
+ test_region_size, GFP_KERNEL);
+ if (!test_reg1) {
+ pr_err("pcie ep: can't alloc the test reg1.\n");
+ ret = PTR_ERR(test_reg1);
+ return ret;
+ }
+
+ test_reg2 = devm_kzalloc(&pdev->dev,
+ test_region_size, GFP_KERNEL);
+ if (!test_reg2) {
+ pr_err("pcie ep: can't alloc the test reg2.\n");
+ ret = PTR_ERR(test_reg1);
+ return ret;
+ }
+
+ /*
+ * FIXME when the ddr_test_region is mapped as cache-able,
+ * system hang when read the ddr memory content back from rc
+ * reserved ddr memory after write the ddr_test_region
+ * content to rc.
+ */
+ pcie_arb_base_addr = ioremap_nocache(pp->mem_base,
+ test_region_size);
+
+ if (!pcie_arb_base_addr) {
+ pr_err("error with ioremap in ep selftest\n");
+ ret = PTR_ERR(pcie_arb_base_addr);
+ return ret;
+ }
+
+ for (i = 0; i < test_region_size; i = i + 4) {
+ writel(0xE6600D00 + i, test_reg1 + i);
+ writel(0xDEADBEAF, test_reg2 + i);
+ }
+
+ /* PCIe EP start the data transfer after link up */
+ pr_info("pcie ep: Starting data transfer...\n");
+ do_gettimeofday(&tv1s);
+
+ memcpy((unsigned int *)pcie_arb_base_addr,
+ (unsigned int *)test_reg1,
+ test_region_size);
+
+ do_gettimeofday(&tv1e);
+
+ do_gettimeofday(&tv2s);
+
+ memcpy((unsigned int *)test_reg2,
+ (unsigned int *)pcie_arb_base_addr,
+ test_region_size);
+
+ do_gettimeofday(&tv2e);
+ if (memcmp(test_reg2, test_reg1, test_region_size) == 0) {
+ tv_count1 = (tv1e.tv_sec - tv1s.tv_sec)
+ * USEC_PER_SEC
+ + tv1e.tv_usec - tv1s.tv_usec;
+ tv_count2 = (tv2e.tv_sec - tv2s.tv_sec)
+ * USEC_PER_SEC
+ + tv2e.tv_usec - tv2s.tv_usec;
+
+ pr_info("pcie ep: Data transfer is successful."
+ " tv_count1 %dus,"
+ " tv_count2 %dus.\n",
+ tv_count1, tv_count2);
+ pr_info("pcie ep: Data write speed:%ldMB/s.\n",
+ ((test_region_size/1024)
+ * MSEC_PER_SEC)
+ /(tv_count1));
+ pr_info("pcie ep: Data read speed:%ldMB/s.\n",
+ ((test_region_size/1024)
+ * MSEC_PER_SEC)
+ /(tv_count2));
+ } else {
+ pr_info("pcie ep: Data transfer is failed.\n");
+ } /* end of self io test. */
+ } else {
+ ret = imx6_add_pcie_port(imx6_pcie, pdev);
+ if (ret < 0)
+ return ret;
+
+ platform_set_drvdata(pdev, imx6_pcie);
+
+ if (IS_ENABLED(CONFIG_RC_MODE_IN_EP_RC_SYS))
+ imx_pcie_regions_setup(&pdev->dev);
+ }
return 0;
}
@@ -739,6 +1562,7 @@ static const struct of_device_id imx6_pcie_of_match[] = {
{ .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, },
{ .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, },
{ .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, },
+ { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, },
{},
};
@@ -746,12 +1570,24 @@ static struct platform_driver imx6_pcie_driver = {
.driver = {
.name = "imx6q-pcie",
.of_match_table = imx6_pcie_of_match,
+ .pm = &pci_imx_pm_ops,
},
+ .probe = imx6_pcie_probe,
.shutdown = imx6_pcie_shutdown,
};
static int __init imx6_pcie_init(void)
{
- return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe);
+ /*
+ * Since probe() can be deferred we need to make sure that
+ * hook_fault_code is not called after __init memory is freed
+ * by kernel and since imx6q_pcie_abort_handler() is a no-op,
+ * we can install the handler here without risking it
+ * accessing some uninitialized driver state.
+ */
+ hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
+ "imprecise external abort");
+
+ return platform_driver_register(&imx6_pcie_driver);
}
device_initcall(imx6_pcie_init);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index af8f6e92e885..1974e973115b 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -241,7 +241,8 @@ static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index,
if (val == PCIE_ATU_ENABLE)
return;
- usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+ if (!IS_ENABLED(CONFIG_PCI_IMX6))
+ usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
}
dev_err(pp->dev, "iATU is not being enabled\n");
}
@@ -296,6 +297,28 @@ void dw_pcie_msi_init(struct pcie_port *pp)
(u32)(msi_target >> 32 & 0xffffffff));
}
+void dw_pcie_msi_cfg_store(struct pcie_port *pp)
+{
+ int i;
+
+ for (i = 0; i < MAX_MSI_CTRLS; i++)
+ dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + i * 12, 4,
+ &pp->msi_enable[i]);
+}
+
+void dw_pcie_msi_cfg_restore(struct pcie_port *pp)
+{
+ int i;
+
+ for (i = 0; i < MAX_MSI_CTRLS; i++) {
+ dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
+ virt_to_phys((void *)pp->msi_data));
+ dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0);
+ dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + i * 12, 4,
+ pp->msi_enable[i]);
+ }
+}
+
static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
{
unsigned int res, bit, val;
@@ -637,8 +660,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
}
}
- if (pp->ops->host_init)
- pp->ops->host_init(pp);
+ if (pp->ops->host_init) {
+ ret = pp->ops->host_init(pp);
+ if (ret < 0)
+ return ret;
+ }
pp->root_bus_nr = pp->busn->start;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
@@ -882,9 +908,11 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
dev_dbg(pp->dev, "iATU unroll: %s\n",
pp->iatu_unroll_enabled ? "enabled" : "disabled");
- dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
- PCIE_ATU_TYPE_MEM, pp->mem_base,
- pp->mem_bus_addr, pp->mem_size);
+ if (!IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)
+ && !IS_ENABLED(CONFIG_RC_MODE_IN_EP_RC_SYS))
+ dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
+ PCIE_ATU_TYPE_MEM, pp->mem_base,
+ pp->mem_bus_addr, pp->mem_size);
if (pp->num_viewport > 2)
dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX2,
PCIE_ATU_TYPE_IO, pp->io_base,
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index a567ea288ee2..bc8adda1b31d 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -50,6 +50,7 @@ struct pcie_port {
struct irq_domain *irq_domain;
unsigned long msi_data;
u8 iatu_unroll_enabled;
+ unsigned int msi_enable[MAX_MSI_CTRLS];
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
};
@@ -63,7 +64,7 @@ struct pcie_host_ops {
int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val);
int (*link_up)(struct pcie_port *pp);
- void (*host_init)(struct pcie_port *pp);
+ int (*host_init)(struct pcie_port *pp);
void (*msi_set_irq)(struct pcie_port *pp, int irq);
void (*msi_clear_irq)(struct pcie_port *pp, int irq);
phys_addr_t (*get_msi_addr)(struct pcie_port *pp);
@@ -79,6 +80,8 @@ int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val);
irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
void dw_pcie_msi_init(struct pcie_port *pp);
int dw_pcie_wait_for_link(struct pcie_port *pp);
+void dw_pcie_msi_cfg_store(struct pcie_port *pp);
+void dw_pcie_msi_cfg_restore(struct pcie_port *pp);
int dw_pcie_link_up(struct pcie_port *pp);
void dw_pcie_setup_rc(struct pcie_port *pp);
int dw_pcie_host_init(struct pcie_port *pp);
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index 54dad89fc9bf..1f890267cb72 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
@@ -166,6 +167,43 @@ static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
return dt_remember_or_free_map(p, statename, NULL, map, 1);
}
+static int dt_gpio_assert_pinctrl(struct pinctrl *p)
+{
+ struct device_node *np = p->dev->of_node;
+ enum of_gpio_flags flags;
+ int gpio;
+ int index = 0;
+ int ret;
+
+ if (!of_find_property(np, "pinctrl-assert-gpios", NULL))
+ return 0; /* Missing the property, so nothing to be done */
+
+ for (;; index++) {
+ gpio = of_get_named_gpio_flags(np, "pinctrl-assert-gpios",
+ index, &flags);
+ if (gpio < 0)
+ break; /* End of the phandle list */
+
+ if (!gpio_is_valid(gpio))
+ return -EINVAL;
+
+ ret = devm_gpio_request_one(p->dev, gpio, GPIOF_OUT_INIT_LOW,
+ NULL);
+ if (ret < 0)
+ return ret;
+
+ if (flags & OF_GPIO_ACTIVE_LOW)
+ continue;
+
+ if (gpio_cansleep(gpio))
+ gpio_set_value_cansleep(gpio, 1);
+ else
+ gpio_set_value(gpio, 1);
+ }
+
+ return 0;
+}
+
int pinctrl_dt_to_map(struct pinctrl *p)
{
struct device_node *np = p->dev->of_node;
@@ -186,6 +224,12 @@ int pinctrl_dt_to_map(struct pinctrl *p)
return 0;
}
+ ret = dt_gpio_assert_pinctrl(p);
+ if (ret) {
+ dev_dbg(p->dev, "failed to assert pinctrl setting: %d\n", ret);
+ return ret;
+ }
+
/* We may store pointers to property names within the node */
of_node_get(np);
diff --git a/drivers/pinctrl/freescale/Kconfig b/drivers/pinctrl/freescale/Kconfig
index fc8cbf611723..24b8593d4ada 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -95,6 +95,13 @@ config PINCTRL_IMX6UL
help
Say Y here to enable the imx6ul pinctrl driver
+config PINCTRL_IMX6SLL
+ bool "IMX6SLL pinctrl driver"
+ depends on SOC_IMX6SLL
+ select PINCTRL_IMX
+ help
+ Say Y here to enable the imx6sll pinctrl driver
+
config PINCTRL_IMX7D
bool "IMX7D pinctrl driver"
depends on SOC_IMX7D
@@ -102,6 +109,13 @@ config PINCTRL_IMX7D
help
Say Y here to enable the imx7d pinctrl driver
+config PINCTRL_IMX7ULP
+ bool "IMX7ULP pinctrl driver"
+ depends on SOC_IMX7ULP
+ select PINCTRL_IMX
+ help
+ Say Y here to enable the imx7ulp pinctrl driver
+
config PINCTRL_VF610
bool "Freescale Vybrid VF610 pinctrl driver"
depends on SOC_VF610
diff --git a/drivers/pinctrl/freescale/Makefile b/drivers/pinctrl/freescale/Makefile
index d44c9e253f21..5ad70aa2f72b 100644
--- a/drivers/pinctrl/freescale/Makefile
+++ b/drivers/pinctrl/freescale/Makefile
@@ -13,7 +13,9 @@ obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6dl.o
obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.o
obj-$(CONFIG_PINCTRL_IMX6SX) += pinctrl-imx6sx.o
obj-$(CONFIG_PINCTRL_IMX6UL) += pinctrl-imx6ul.o
+obj-$(CONFIG_PINCTRL_IMX6SLL) += pinctrl-imx6sll.o
obj-$(CONFIG_PINCTRL_IMX7D) += pinctrl-imx7d.o
+obj-$(CONFIG_PINCTRL_IMX7ULP) += pinctrl-imx7ulp.o
obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index 5ef7e875b50e..622248b30569 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -33,6 +33,8 @@
#define IMX_NO_PAD_CTL 0x80000000 /* no pin config need */
#define IMX_PAD_SION 0x40000000 /* set SION */
+#define IOMUXC_IBE (1 << 16)
+#define IOMUXC_OBE (1 << 17)
/**
* @dev: a pointer back to containing device
* @base: the offset to the controller in virtual memory
@@ -204,6 +206,7 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
for (i = 0; i < npins; i++) {
struct imx_pin *pin = &grp->pins[i];
+ u32 mux_shift = info->mux_mask ? ffs(info->mux_mask) - 1 : 0;
pin_id = pin->pin;
pin_reg = &info->pin_regs[pin_id];
@@ -216,8 +219,8 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
if (info->flags & SHARE_MUX_CONF_REG) {
u32 reg;
reg = readl(ipctl->base + pin_reg->mux_reg);
- reg &= ~(0x7 << 20);
- reg |= (pin->mux_mode << 20);
+ reg &= ~info->mux_mask;
+ reg |= (pin->mux_mode << mux_shift);
writel(reg, ipctl->base + pin_reg->mux_reg);
} else {
writel(pin->mux_mode, ipctl->base + pin_reg->mux_reg);
@@ -311,7 +314,7 @@ static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
struct imx_pin_group *grp;
struct imx_pin *imx_pin;
unsigned int pin, group;
- u32 reg;
+ u32 reg, mux_shift;
/* Currently implementation only for shared mux/conf register */
if (!(info->flags & SHARE_MUX_CONF_REG))
@@ -326,7 +329,7 @@ static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
grp = &info->groups[group];
for (pin = 0; pin < grp->npins; pin++) {
imx_pin = &grp->pins[pin];
- if (imx_pin->pin == offset && !imx_pin->mux_mode)
+ if (imx_pin->pin == offset)
goto mux_pin;
}
}
@@ -335,7 +338,10 @@ static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
mux_pin:
reg = readl(ipctl->base + pin_reg->mux_reg);
- reg &= ~(0x7 << 20);
+ reg &= ~info->mux_mask;
+ mux_shift = info->mux_mask ? ffs(info->mux_mask) - 1 : 0;
+ reg |= (imx_pin->mux_mode << mux_shift);
+ imx_pin->config &= ~info->mux_mask;
reg |= imx_pin->config;
writel(reg, ipctl->base + pin_reg->mux_reg);
@@ -376,8 +382,8 @@ static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
u32 reg;
/*
- * Only Vybrid has the input/output buffer enable flags (IBE/OBE)
- * They are part of the shared mux/conf register.
+ * Only Vybrid and i.MX7ULP have the input/output buffer enable
+ * flags (IBE/OBE) They are part of the shared mux/conf register.
*/
if (!(info->flags & SHARE_MUX_CONF_REG))
return 0;
@@ -388,10 +394,21 @@ static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
/* IBE always enabled allows us to read the value "on the wire" */
reg = readl(ipctl->base + pin_reg->mux_reg);
- if (input)
- reg &= ~0x2;
- else
- reg |= 0x2;
+ if (input) {
+ if (info->flags & CONFIG_IBE_OBE) {
+ reg &= ~IOMUXC_OBE;
+ reg |= IOMUXC_IBE;
+ } else {
+ reg &= ~0x2;
+ }
+ } else {
+ if (info->flags & CONFIG_IBE_OBE) {
+ reg &= ~IOMUXC_IBE;
+ reg |= IOMUXC_OBE;
+ } else {
+ reg |= 0x2;
+ }
+ }
writel(reg, ipctl->base + pin_reg->mux_reg);
return 0;
@@ -423,7 +440,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
*config = readl(ipctl->base + pin_reg->conf_reg);
if (info->flags & SHARE_MUX_CONF_REG)
- *config &= 0xffff;
+ *config &= ~info->mux_mask;
return 0;
}
@@ -450,7 +467,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
if (info->flags & SHARE_MUX_CONF_REG) {
u32 reg;
reg = readl(ipctl->base + pin_reg->conf_reg);
- reg &= ~0xffff;
+ reg &= info->mux_mask;
reg |= configs[i];
writel(reg, ipctl->base + pin_reg->conf_reg);
} else {
@@ -754,6 +771,9 @@ int imx_pinctrl_probe(struct platform_device *pdev,
if (IS_ERR(ipctl->base))
return PTR_ERR(ipctl->base);
+ /* only for share mux and conf reg */
+ of_property_read_u32(dev_np, "fsl,mux_mask", &info->mux_mask);
+
if (of_property_read_bool(dev_np, "fsl,input-sel")) {
np = of_parse_phandle(dev_np, "fsl,input-sel", 0);
if (!np) {
@@ -803,3 +823,23 @@ int imx_pinctrl_probe(struct platform_device *pdev,
return 0;
}
+
+int imx_pinctrl_suspend(struct device *dev)
+{
+ struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+ if (!ipctl)
+ return -EINVAL;
+
+ return pinctrl_force_sleep(ipctl->pctl);
+}
+
+int imx_pinctrl_resume(struct device *dev)
+{
+ struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+ if (!ipctl)
+ return -EINVAL;
+
+ return pinctrl_force_default(ipctl->pctl);
+}
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h b/drivers/pinctrl/freescale/pinctrl-imx.h
index 8af8aa2897ab..8f1f69315d2b 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.h
+++ b/drivers/pinctrl/freescale/pinctrl-imx.h
@@ -83,10 +83,12 @@ struct imx_pinctrl_soc_info {
unsigned int nfunctions;
unsigned int flags;
const char *gpr_compatible;
+ unsigned int mux_mask;
};
#define SHARE_MUX_CONF_REG 0x1
#define ZERO_OFFSET_VALID 0x2
+#define CONFIG_IBE_OBE 0x4
#define NO_MUX 0x0
#define NO_PAD 0x0
@@ -99,4 +101,6 @@ struct imx_pinctrl_soc_info {
int imx_pinctrl_probe(struct platform_device *pdev,
struct imx_pinctrl_soc_info *info);
+int imx_pinctrl_suspend(struct device *dev);
+int imx_pinctrl_resume(struct device *dev);
#endif /* __DRIVERS_PINCTRL_IMX_H */
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6sll.c b/drivers/pinctrl/freescale/pinctrl-imx6sll.c
new file mode 100644
index 000000000000..371fb143e039
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx6sll.c
@@ -0,0 +1,388 @@
+/*
+ * 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 <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx6sll_pads {
+ MX6SLL_PAD_RESERVE0 = 0,
+ MX6SLL_PAD_RESERVE1 = 1,
+ MX6SLL_PAD_RESERVE2 = 2,
+ MX6SLL_PAD_RESERVE3 = 3,
+ MX6SLL_PAD_RESERVE4 = 4,
+ MX6SLL_PAD_WDOG_B = 5,
+ MX6SLL_PAD_REF_CLK_24M = 6,
+ MX6SLL_PAD_REF_CLK_32K = 7,
+ MX6SLL_PAD_PWM1 = 8,
+ MX6SLL_PAD_KEY_COL0 = 9,
+ MX6SLL_PAD_KEY_ROW0 = 10,
+ MX6SLL_PAD_KEY_COL1 = 11,
+ MX6SLL_PAD_KEY_ROW1 = 12,
+ MX6SLL_PAD_KEY_COL2 = 13,
+ MX6SLL_PAD_KEY_ROW2 = 14,
+ MX6SLL_PAD_KEY_COL3 = 15,
+ MX6SLL_PAD_KEY_ROW3 = 16,
+ MX6SLL_PAD_KEY_COL4 = 17,
+ MX6SLL_PAD_KEY_ROW4 = 18,
+ MX6SLL_PAD_KEY_COL5 = 19,
+ MX6SLL_PAD_KEY_ROW5 = 20,
+ MX6SLL_PAD_KEY_COL6 = 21,
+ MX6SLL_PAD_KEY_ROW6 = 22,
+ MX6SLL_PAD_KEY_COL7 = 23,
+ MX6SLL_PAD_KEY_ROW7 = 24,
+ MX6SLL_PAD_EPDC_DATA00 = 25,
+ MX6SLL_PAD_EPDC_DATA01 = 26,
+ MX6SLL_PAD_EPDC_DATA02 = 27,
+ MX6SLL_PAD_EPDC_DATA03 = 28,
+ MX6SLL_PAD_EPDC_DATA04 = 29,
+ MX6SLL_PAD_EPDC_DATA05 = 30,
+ MX6SLL_PAD_EPDC_DATA06 = 31,
+ MX6SLL_PAD_EPDC_DATA07 = 32,
+ MX6SLL_PAD_EPDC_DATA08 = 33,
+ MX6SLL_PAD_EPDC_DATA09 = 34,
+ MX6SLL_PAD_EPDC_DATA10 = 35,
+ MX6SLL_PAD_EPDC_DATA11 = 36,
+ MX6SLL_PAD_EPDC_DATA12 = 37,
+ MX6SLL_PAD_EPDC_DATA13 = 38,
+ MX6SLL_PAD_EPDC_DATA14 = 39,
+ MX6SLL_PAD_EPDC_DATA15 = 40,
+ MX6SLL_PAD_EPDC_SDCLK = 41,
+ MX6SLL_PAD_EPDC_SDLE = 42,
+ MX6SLL_PAD_EPDC_SDOE = 43,
+ MX6SLL_PAD_EPDC_SDSHR = 44,
+ MX6SLL_PAD_EPDC_SDCE0 = 45,
+ MX6SLL_PAD_EPDC_SDCE1 = 46,
+ MX6SLL_PAD_EPDC_SDCE2 = 47,
+ MX6SLL_PAD_EPDC_SDCE3 = 48,
+ MX6SLL_PAD_EPDC_GDCLK = 49,
+ MX6SLL_PAD_EPDC_GDOE = 50,
+ MX6SLL_PAD_EPDC_GDRL = 51,
+ MX6SLL_PAD_EPDC_GDSP = 52,
+ MX6SLL_PAD_EPDC_VCOM0 = 53,
+ MX6SLL_PAD_EPDC_VCOM1 = 54,
+ MX6SLL_PAD_EPDC_BDR0 = 55,
+ MX6SLL_PAD_EPDC_BDR1 = 56,
+ MX6SLL_PAD_EPDC_PWR_CTRL0 = 57,
+ MX6SLL_PAD_EPDC_PWR_CTRL1 = 58,
+ MX6SLL_PAD_EPDC_PWR_CTRL2 = 59,
+ MX6SLL_PAD_EPDC_PWR_CTRL3 = 60,
+ MX6SLL_PAD_EPDC_PWR_COM = 61,
+ MX6SLL_PAD_EPDC_PWR_INT = 62,
+ MX6SLL_PAD_EPDC_PWR_STAT = 63,
+ MX6SLL_PAD_EPDC_PWR_WAKE = 64,
+ MX6SLL_PAD_LCD_CLK = 65,
+ MX6SLL_PAD_LCD_ENABLE = 66,
+ MX6SLL_PAD_LCD_HSYNC = 67,
+ MX6SLL_PAD_LCD_VSYNC = 68,
+ MX6SLL_PAD_LCD_RESET = 69,
+ MX6SLL_PAD_LCD_DATA00 = 70,
+ MX6SLL_PAD_LCD_DATA01 = 71,
+ MX6SLL_PAD_LCD_DATA02 = 72,
+ MX6SLL_PAD_LCD_DATA03 = 73,
+ MX6SLL_PAD_LCD_DATA04 = 74,
+ MX6SLL_PAD_LCD_DATA05 = 75,
+ MX6SLL_PAD_LCD_DATA06 = 76,
+ MX6SLL_PAD_LCD_DATA07 = 77,
+ MX6SLL_PAD_LCD_DATA08 = 78,
+ MX6SLL_PAD_LCD_DATA09 = 79,
+ MX6SLL_PAD_LCD_DATA10 = 80,
+ MX6SLL_PAD_LCD_DATA11 = 81,
+ MX6SLL_PAD_LCD_DATA12 = 82,
+ MX6SLL_PAD_LCD_DATA13 = 83,
+ MX6SLL_PAD_LCD_DATA14 = 84,
+ MX6SLL_PAD_LCD_DATA15 = 85,
+ MX6SLL_PAD_LCD_DATA16 = 86,
+ MX6SLL_PAD_LCD_DATA17 = 87,
+ MX6SLL_PAD_LCD_DATA18 = 88,
+ MX6SLL_PAD_LCD_DATA19 = 89,
+ MX6SLL_PAD_LCD_DATA20 = 90,
+ MX6SLL_PAD_LCD_DATA21 = 91,
+ MX6SLL_PAD_LCD_DATA22 = 92,
+ MX6SLL_PAD_LCD_DATA23 = 93,
+ MX6SLL_PAD_AUD_RXFS = 94,
+ MX6SLL_PAD_AUD_RXC = 95,
+ MX6SLL_PAD_AUD_RXD = 96,
+ MX6SLL_PAD_AUD_TXC = 97,
+ MX6SLL_PAD_AUD_TXFS = 98,
+ MX6SLL_PAD_AUD_TXD = 99,
+ MX6SLL_PAD_AUD_MCLK = 100,
+ MX6SLL_PAD_UART1_RXD = 101,
+ MX6SLL_PAD_UART1_TXD = 102,
+ MX6SLL_PAD_I2C1_SCL = 103,
+ MX6SLL_PAD_I2C1_SDA = 104,
+ MX6SLL_PAD_I2C2_SCL = 105,
+ MX6SLL_PAD_I2C2_SDA = 106,
+ MX6SLL_PAD_ECSPI1_SCLK = 107,
+ MX6SLL_PAD_ECSPI1_MOSI = 108,
+ MX6SLL_PAD_ECSPI1_MISO = 109,
+ MX6SLL_PAD_ECSPI1_SS0 = 110,
+ MX6SLL_PAD_ECSPI2_SCLK = 111,
+ MX6SLL_PAD_ECSPI2_MOSI = 112,
+ MX6SLL_PAD_ECSPI2_MISO = 113,
+ MX6SLL_PAD_ECSPI2_SS0 = 114,
+ MX6SLL_PAD_SD1_CLK = 115,
+ MX6SLL_PAD_SD1_CMD = 116,
+ MX6SLL_PAD_SD1_DATA0 = 117,
+ MX6SLL_PAD_SD1_DATA1 = 118,
+ MX6SLL_PAD_SD1_DATA2 = 119,
+ MX6SLL_PAD_SD1_DATA3 = 120,
+ MX6SLL_PAD_SD1_DATA4 = 121,
+ MX6SLL_PAD_SD1_DATA5 = 122,
+ MX6SLL_PAD_SD1_DATA6 = 123,
+ MX6SLL_PAD_SD1_DATA7 = 124,
+ MX6SLL_PAD_SD2_RESET = 125,
+ MX6SLL_PAD_SD2_CLK = 126,
+ MX6SLL_PAD_SD2_CMD = 127,
+ MX6SLL_PAD_SD2_DATA0 = 128,
+ MX6SLL_PAD_SD2_DATA1 = 129,
+ MX6SLL_PAD_SD2_DATA2 = 130,
+ MX6SLL_PAD_SD2_DATA3 = 131,
+ MX6SLL_PAD_SD2_DATA4 = 132,
+ MX6SLL_PAD_SD2_DATA5 = 133,
+ MX6SLL_PAD_SD2_DATA6 = 134,
+ MX6SLL_PAD_SD2_DATA7 = 135,
+ MX6SLL_PAD_SD3_CLK = 136,
+ MX6SLL_PAD_SD3_CMD = 137,
+ MX6SLL_PAD_SD3_DATA0 = 138,
+ MX6SLL_PAD_SD3_DATA1 = 139,
+ MX6SLL_PAD_SD3_DATA2 = 140,
+ MX6SLL_PAD_SD3_DATA3 = 141,
+ MX6SLL_PAD_GPIO4_IO20 = 142,
+ MX6SLL_PAD_GPIO4_IO21 = 143,
+ MX6SLL_PAD_GPIO4_IO19 = 144,
+ MX6SLL_PAD_GPIO4_IO25 = 145,
+ MX6SLL_PAD_GPIO4_IO18 = 146,
+ MX6SLL_PAD_GPIO4_IO24 = 147,
+ MX6SLL_PAD_GPIO4_IO23 = 148,
+ MX6SLL_PAD_GPIO4_IO17 = 149,
+ MX6SLL_PAD_GPIO4_IO22 = 150,
+ MX6SLL_PAD_GPIO4_IO16 = 151,
+ MX6SLL_PAD_GPIO4_IO26 = 152,
+};
+
+enum imx6sll_lpsr_pads {
+ MX6SLL_PAD_SNVS_TAMPER = 0,
+ MX6SLL_PAD_SNVS_PMIC_ON_REQ = 1,
+ MX6SLL_PAD_SNVS_PMIC_STBY_REQ = 2,
+ MX6SLL_PAD_SNVS_BOOT_MODE0 = 3,
+ MX6SLL_PAD_SNVS_BOOT_MODE1 = 4,
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx6sll_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_WDOG_B),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_REF_CLK_24M),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_REF_CLK_32K),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_PWM1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL5),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW5),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL6),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW6),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL7),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW7),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA00),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA01),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA02),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA03),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA04),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA05),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA06),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA07),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA08),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA09),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA10),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA11),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA12),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA13),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA14),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA15),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDLE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDOE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDSHR),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCE0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCE1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCE2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCE3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_GDCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_GDOE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_GDRL),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_GDSP),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_VCOM0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_VCOM1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_BDR0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_BDR1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_CTRL0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_CTRL1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_CTRL2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_CTRL3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_COM),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_INT),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_STAT),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_WAKE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_CLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_ENABLE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_HSYNC),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_VSYNC),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_RESET),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA00),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA01),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA02),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA03),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA04),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA05),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA06),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA07),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA08),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA09),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA10),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA11),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA12),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA13),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA14),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA15),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA16),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA17),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA18),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA19),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA20),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA21),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA22),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA23),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_RXFS),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_RXC),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_RXD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_TXC),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_TXFS),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_TXD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_MCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_UART1_RXD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_UART1_TXD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_I2C1_SCL),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_I2C1_SDA),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_I2C2_SCL),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_I2C2_SDA),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI1_SCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI1_MOSI),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI1_MISO),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI1_SS0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI2_SCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI2_MOSI),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI2_MISO),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI2_SS0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_CLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_CMD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA5),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA6),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA7),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_RESET),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_CLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_CMD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA5),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA6),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA7),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_CLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_CMD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_DATA0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_DATA1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_DATA2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_DATA3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO20),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO21),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO19),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO25),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO18),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO24),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO23),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO17),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO22),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO16),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO26),
+};
+
+static struct imx_pinctrl_soc_info imx6sll_pinctrl_info = {
+ .pins = imx6sll_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx6sll_pinctrl_pads),
+};
+
+static struct of_device_id imx6sll_pinctrl_of_match[] = {
+ { .compatible = "fsl,imx6sll-iomuxc", .data = &imx6sll_pinctrl_info, },
+ { /* sentinel */ }
+};
+
+static int imx6sll_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct imx_pinctrl_soc_info *pinctrl_info;
+
+ match = of_match_device(imx6sll_pinctrl_of_match, &pdev->dev);
+
+ if (!match)
+ return -ENODEV;
+
+ pinctrl_info = (struct imx_pinctrl_soc_info *) match->data;
+
+ return imx_pinctrl_probe(pdev, pinctrl_info);
+}
+
+static struct platform_driver imx6sll_pinctrl_driver = {
+ .driver = {
+ .name = "imx6sll-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(imx6sll_pinctrl_of_match),
+ },
+ .probe = imx6sll_pinctrl_probe,
+};
+
+static int __init imx6sll_pinctrl_init(void)
+{
+ return platform_driver_register(&imx6sll_pinctrl_driver);
+}
+arch_initcall(imx6sll_pinctrl_init);
+
+static void __exit imx6sll_pinctrl_exit(void)
+{
+ platform_driver_unregister(&imx6sll_pinctrl_driver);
+}
+module_exit(imx6sll_pinctrl_exit);
+
+MODULE_AUTHOR("Bai Ping <ping.bai@nxp.com>");
+MODULE_DESCRIPTION("Freescale imx6sll pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6ul.c b/drivers/pinctrl/freescale/pinctrl-imx6ul.c
index 1aeb840aae1d..cbad1c69226d 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx6ul.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx6ul.c
@@ -150,6 +150,21 @@ enum imx6ul_pads {
MX6UL_PAD_CSI_DATA07 = 128,
};
+enum imx6ull_lpsr_pads {
+ MX6ULL_PAD_BOOT_MODE0 = 0,
+ MX6ULL_PAD_BOOT_MODE1 = 1,
+ MX6ULL_PAD_SNVS_TAMPER0 = 2,
+ MX6ULL_PAD_SNVS_TAMPER1 = 3,
+ MX6ULL_PAD_SNVS_TAMPER2 = 4,
+ MX6ULL_PAD_SNVS_TAMPER3 = 5,
+ MX6ULL_PAD_SNVS_TAMPER4 = 6,
+ MX6ULL_PAD_SNVS_TAMPER5 = 7,
+ MX6ULL_PAD_SNVS_TAMPER6 = 8,
+ MX6ULL_PAD_SNVS_TAMPER7 = 9,
+ MX6ULL_PAD_SNVS_TAMPER8 = 10,
+ MX6ULL_PAD_SNVS_TAMPER9 = 11,
+};
+
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc imx6ul_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE0),
@@ -283,20 +298,53 @@ static const struct pinctrl_pin_desc imx6ul_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA07),
};
+/* pad for i.MX6ULL lpsr pinmux */
+static struct pinctrl_pin_desc imx6ull_snvs_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX6ULL_PAD_BOOT_MODE0),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_BOOT_MODE1),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER0),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER1),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER2),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER3),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER4),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER5),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER6),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER7),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER8),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER9),
+};
+
static struct imx_pinctrl_soc_info imx6ul_pinctrl_info = {
.pins = imx6ul_pinctrl_pads,
.npins = ARRAY_SIZE(imx6ul_pinctrl_pads),
.gpr_compatible = "fsl,imx6ul-iomuxc-gpr",
};
+static struct imx_pinctrl_soc_info imx6ull_snvs_pinctrl_info = {
+ .pins = imx6ull_snvs_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx6ull_snvs_pinctrl_pads),
+ .flags = ZERO_OFFSET_VALID,
+};
+
static struct of_device_id imx6ul_pinctrl_of_match[] = {
- { .compatible = "fsl,imx6ul-iomuxc", },
+ { .compatible = "fsl,imx6ul-iomuxc", .data = &imx6ul_pinctrl_info, },
+ { .compatible = "fsl,imx6ull-iomuxc-snvs", .data = &imx6ull_snvs_pinctrl_info, },
{ /* sentinel */ }
};
static int imx6ul_pinctrl_probe(struct platform_device *pdev)
{
- return imx_pinctrl_probe(pdev, &imx6ul_pinctrl_info);
+ const struct of_device_id *match;
+ struct imx_pinctrl_soc_info *pinctrl_info;
+
+ match = of_match_device(imx6ul_pinctrl_of_match, &pdev->dev);
+
+ if (!match)
+ return -ENODEV;
+
+ pinctrl_info = (struct imx_pinctrl_soc_info *) match->data;
+
+ return imx_pinctrl_probe(pdev, pinctrl_info);
}
static struct platform_driver imx6ul_pinctrl_driver = {
diff --git a/drivers/pinctrl/freescale/pinctrl-imx7d.c b/drivers/pinctrl/freescale/pinctrl-imx7d.c
index a465a66c3ef4..9f6d8ba7ce61 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx7d.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx7d.c
@@ -391,10 +391,27 @@ static int imx7d_pinctrl_probe(struct platform_device *pdev)
return imx_pinctrl_probe(pdev, pinctrl_info);
}
+static int imx7d_pinctrl_suspend(struct device *dev)
+{
+
+ return imx_pinctrl_suspend(dev);
+}
+
+static int imx7d_pinctrl_resume(struct device *dev)
+{
+
+ return imx_pinctrl_resume(dev);
+}
+
+static const struct dev_pm_ops imx7d_pinctrl_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(imx7d_pinctrl_suspend, imx7d_pinctrl_resume)
+};
+
static struct platform_driver imx7d_pinctrl_driver = {
.driver = {
.name = "imx7d-pinctrl",
.of_match_table = of_match_ptr(imx7d_pinctrl_of_match),
+ .pm = &imx7d_pinctrl_pm_ops,
},
.probe = imx7d_pinctrl_probe,
};
diff --git a/drivers/pinctrl/freescale/pinctrl-imx7ulp.c b/drivers/pinctrl/freescale/pinctrl-imx7ulp.c
new file mode 100644
index 000000000000..e31425c8fa87
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx7ulp.c
@@ -0,0 +1,438 @@
+/*
+ * 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 <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx7ulp_pads {
+ ULP1_PAD_PTA0 = 0,
+ ULP1_PAD_PTA1,
+ ULP1_PAD_PTA2,
+ ULP1_PAD_PTA3,
+ ULP1_PAD_PTA4,
+ ULP1_PAD_PTA5,
+ ULP1_PAD_PTA6,
+ ULP1_PAD_PTA7,
+ ULP1_PAD_PTA8,
+ ULP1_PAD_PTA9,
+ ULP1_PAD_PTA10,
+ ULP1_PAD_PTA11,
+ ULP1_PAD_PTA12,
+ ULP1_PAD_PTA13,
+ ULP1_PAD_PTA14,
+ ULP1_PAD_PTA15,
+ ULP1_PAD_PTA16,
+ ULP1_PAD_PTA17,
+ ULP1_PAD_PTA18,
+ ULP1_PAD_PTA19,
+ ULP1_PAD_PTA20,
+ ULP1_PAD_PTA21,
+ ULP1_PAD_PTA22,
+ ULP1_PAD_PTA23,
+ ULP1_PAD_PTA24,
+ ULP1_PAD_PTA25,
+ ULP1_PAD_PTA26,
+ ULP1_PAD_PTA27,
+ ULP1_PAD_PTA28,
+ ULP1_PAD_PTA29,
+ ULP1_PAD_PTA30,
+ ULP1_PAD_PTA31,
+ ULP1_PAD_PTB0,
+ ULP1_PAD_PTB1,
+ ULP1_PAD_PTB2,
+ ULP1_PAD_PTB3,
+ ULP1_PAD_PTB4,
+ ULP1_PAD_PTB5,
+ ULP1_PAD_PTB6,
+ ULP1_PAD_PTB7,
+ ULP1_PAD_PTB8,
+ ULP1_PAD_PTB9,
+ ULP1_PAD_PTB10,
+ ULP1_PAD_PTB11,
+ ULP1_PAD_PTB12,
+ ULP1_PAD_PTB13,
+ ULP1_PAD_PTB14,
+ ULP1_PAD_PTB15,
+ ULP1_PAD_PTB16,
+ ULP1_PAD_PTB17,
+ ULP1_PAD_PTB18,
+ ULP1_PAD_PTB19 = 51,
+ ULP1_PAD_PTC0 = 0,
+ ULP1_PAD_PTC1,
+ ULP1_PAD_PTC2,
+ ULP1_PAD_PTC3,
+ ULP1_PAD_PTC4,
+ ULP1_PAD_PTC5,
+ ULP1_PAD_PTC6,
+ ULP1_PAD_PTC7,
+ ULP1_PAD_PTC8,
+ ULP1_PAD_PTC9,
+ ULP1_PAD_PTC10,
+ ULP1_PAD_PTC11,
+ ULP1_PAD_PTC12,
+ ULP1_PAD_PTC13,
+ ULP1_PAD_PTC14,
+ ULP1_PAD_PTC15,
+ ULP1_PAD_PTC16,
+ ULP1_PAD_PTC17,
+ ULP1_PAD_PTC18,
+ ULP1_PAD_PTC19,
+ ULP1_PAD_RESERVE0,
+ ULP1_PAD_RESERVE1,
+ ULP1_PAD_RESERVE2,
+ ULP1_PAD_RESERVE3,
+ ULP1_PAD_RESERVE4,
+ ULP1_PAD_RESERVE5,
+ ULP1_PAD_RESERVE6,
+ ULP1_PAD_RESERVE7,
+ ULP1_PAD_RESERVE8,
+ ULP1_PAD_RESERVE9,
+ ULP1_PAD_RESERVE10,
+ ULP1_PAD_RESERVE11,
+ ULP1_PAD_PTD0,
+ ULP1_PAD_PTD1,
+ ULP1_PAD_PTD2,
+ ULP1_PAD_PTD3,
+ ULP1_PAD_PTD4,
+ ULP1_PAD_PTD5,
+ ULP1_PAD_PTD6,
+ ULP1_PAD_PTD7,
+ ULP1_PAD_PTD8,
+ ULP1_PAD_PTD9,
+ ULP1_PAD_PTD10,
+ ULP1_PAD_PTD11,
+ ULP1_PAD_RESERVE12,
+ ULP1_PAD_RESERVE13,
+ ULP1_PAD_RESERVE14,
+ ULP1_PAD_RESERVE15,
+ ULP1_PAD_RESERVE16,
+ ULP1_PAD_RESERVE17,
+ ULP1_PAD_RESERVE18,
+ ULP1_PAD_RESERVE19,
+ ULP1_PAD_RESERVE20,
+ ULP1_PAD_RESERVE21,
+ ULP1_PAD_RESERVE22,
+ ULP1_PAD_RESERVE23,
+ ULP1_PAD_RESERVE24,
+ ULP1_PAD_RESERVE25,
+ ULP1_PAD_RESERVE26,
+ ULP1_PAD_RESERVE27,
+ ULP1_PAD_RESERVE28,
+ ULP1_PAD_RESERVE29,
+ ULP1_PAD_RESERVE30,
+ ULP1_PAD_RESERVE31,
+ ULP1_PAD_PTE0,
+ ULP1_PAD_PTE1,
+ ULP1_PAD_PTE2,
+ ULP1_PAD_PTE3,
+ ULP1_PAD_PTE4,
+ ULP1_PAD_PTE5,
+ ULP1_PAD_PTE6,
+ ULP1_PAD_PTE7,
+ ULP1_PAD_PTE8,
+ ULP1_PAD_PTE9,
+ ULP1_PAD_PTE10,
+ ULP1_PAD_PTE11,
+ ULP1_PAD_PTE12,
+ ULP1_PAD_PTE13,
+ ULP1_PAD_PTE14,
+ ULP1_PAD_PTE15,
+ ULP1_PAD_RESERVE32,
+ ULP1_PAD_RESERVE33,
+ ULP1_PAD_RESERVE34,
+ ULP1_PAD_RESERVE35,
+ ULP1_PAD_RESERVE36,
+ ULP1_PAD_RESERVE37,
+ ULP1_PAD_RESERVE38,
+ ULP1_PAD_RESERVE39,
+ ULP1_PAD_RESERVE40,
+ ULP1_PAD_RESERVE41,
+ ULP1_PAD_RESERVE42,
+ ULP1_PAD_RESERVE43,
+ ULP1_PAD_RESERVE44,
+ ULP1_PAD_RESERVE45,
+ ULP1_PAD_RESERVE46,
+ ULP1_PAD_RESERVE47,
+ ULP1_PAD_PTF0,
+ ULP1_PAD_PTF1,
+ ULP1_PAD_PTF2,
+ ULP1_PAD_PTF3,
+ ULP1_PAD_PTF4,
+ ULP1_PAD_PTF5,
+ ULP1_PAD_PTF6,
+ ULP1_PAD_PTF7,
+ ULP1_PAD_PTF8,
+ ULP1_PAD_PTF9,
+ ULP1_PAD_PTF10,
+ ULP1_PAD_PTF11,
+ ULP1_PAD_PTF12,
+ ULP1_PAD_PTF13,
+ ULP1_PAD_PTF14,
+ ULP1_PAD_PTF15,
+ ULP1_PAD_PTF16,
+ ULP1_PAD_PTF17,
+ ULP1_PAD_PTF18,
+ ULP1_PAD_PTF19,
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx7ulp_pinctrl_pads_0[] = {
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA0),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA1),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA2),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA3),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA4),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA5),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA6),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA7),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA8),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA9),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA10),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA11),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA12),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA13),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA14),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA15),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA16),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA17),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA18),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA19),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA20),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA21),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA22),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA23),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA24),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA25),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA26),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA27),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA28),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA29),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA30),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTA31),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB0),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB1),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB2),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB3),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB4),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB5),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB6),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB7),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB8),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB9),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB10),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB11),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB12),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB13),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB14),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB15),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB16),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB17),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB18),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTB19),
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx7ulp_pinctrl_pads_1[] = {
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC0),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC1),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC2),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC3),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC4),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC5),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC6),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC7),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC8),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC9),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC10),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC11),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC12),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC13),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC14),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC15),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC16),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC17),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC18),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTC19),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE0),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE1),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE2),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE3),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE4),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE5),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE6),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE7),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE8),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE9),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE10),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE11),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD0),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD1),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD2),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD3),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD4),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD5),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD6),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD7),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD8),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD9),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD10),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTD11),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE12),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE13),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE14),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE15),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE16),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE17),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE18),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE19),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE20),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE21),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE22),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE23),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE24),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE25),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE26),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE27),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE28),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE29),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE30),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE31),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE0),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE1),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE2),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE3),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE4),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE5),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE6),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE7),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE8),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE9),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE10),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE11),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE12),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE13),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE14),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTE15),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE32),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE33),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE34),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE35),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE36),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE37),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE38),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE39),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE40),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE41),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE42),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE43),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE44),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE45),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE46),
+ IMX_PINCTRL_PIN(ULP1_PAD_RESERVE47),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF0),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF1),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF2),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF3),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF4),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF5),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF6),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF7),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF8),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF9),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF10),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF11),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF12),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF13),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF14),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF15),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF16),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF17),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF18),
+ IMX_PINCTRL_PIN(ULP1_PAD_PTF19),
+};
+
+static struct imx_pinctrl_soc_info imx7ulp_pinctrl_info_0 = {
+ .pins = imx7ulp_pinctrl_pads_0,
+ .npins = ARRAY_SIZE(imx7ulp_pinctrl_pads_0),
+ .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE,
+};
+
+static struct imx_pinctrl_soc_info imx7ulp_pinctrl_info_1 = {
+ .pins = imx7ulp_pinctrl_pads_1,
+ .npins = ARRAY_SIZE(imx7ulp_pinctrl_pads_1),
+ .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE,
+};
+
+static struct of_device_id imx7ulp_pinctrl_of_match[] = {
+ { .compatible = "fsl,imx7ulp-iomuxc-0", .data = &imx7ulp_pinctrl_info_0 },
+ { .compatible = "fsl,imx7ulp-iomuxc-1", .data = &imx7ulp_pinctrl_info_1,},
+ { /* sentinel */ }
+};
+
+static int imx7ulp_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct imx_pinctrl_soc_info *pinctrl_info;
+
+ match = of_match_device(imx7ulp_pinctrl_of_match, &pdev->dev);
+
+ if (!match)
+ return -ENODEV;
+
+ pinctrl_info = (struct imx_pinctrl_soc_info *) match->data;
+
+ return imx_pinctrl_probe(pdev, pinctrl_info);
+}
+
+static int __maybe_unused imx7ulp_pinctrl_suspend(struct device *dev)
+{
+ return imx_pinctrl_suspend(dev);
+}
+
+static int __maybe_unused imx7ulp_pinctrl_resume(struct device *dev)
+{
+ return imx_pinctrl_resume(dev);
+}
+
+static const struct dev_pm_ops imx7ulp_pinctrl_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(imx7ulp_pinctrl_suspend,
+ imx7ulp_pinctrl_resume)
+};
+
+static struct platform_driver imx7ulp_pinctrl_driver = {
+ .driver = {
+ .name = "imx7ulp-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(imx7ulp_pinctrl_of_match),
+ .pm = &imx7ulp_pinctrl_pm_ops,
+ },
+ .probe = imx7ulp_pinctrl_probe,
+};
+
+static int __init imx7ulp_pinctrl_init(void)
+{
+ return platform_driver_register(&imx7ulp_pinctrl_driver);
+}
+arch_initcall(imx7ulp_pinctrl_init);
+
+static void __exit imx7ulp_pinctrl_exit(void)
+{
+ platform_driver_unregister(&imx7ulp_pinctrl_driver);
+}
+module_exit(imx7ulp_pinctrl_exit);
+
+MODULE_AUTHOR("Fugang Duan <fugang.duan@nxp.com>");
+MODULE_DESCRIPTION("Freescale imx7ulp pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 76806a0be820..e7407876da8b 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -281,6 +281,12 @@ config CHARGER_PCF50633
help
Say Y to include support for NXP PCF50633 Main Battery Charger.
+config CHARGER_PF1550
+ tristate "Freescale PF1550 battery charger driver"
+ depends on MFD_PF1550
+ help
+ Say Y to enable support for the Freescale PF1550 battery charger.
+
config BATTERY_JZ4740
tristate "Ingenic JZ4740 battery"
depends on MACH_JZ4740
@@ -511,4 +517,12 @@ config AXP20X_POWER
This driver provides support for the power supply features of
AXP20x PMIC.
+config SABRESD_MAX8903
+ tristate "Sabresd Board Battery DC-DC Charger for USB and Adapter Power"
+ depends on TOUCHSCREEN_MAX11801
+ help
+ Say Y to enable support for the MAX8903 DC-DC charger and sysfs on
+ sabresd board.The driver supports controlling charger and battery
+ based on the status of charger connections with interrupt handlers.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 36c599d9a495..110df86baebb 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -46,11 +46,13 @@ obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o
obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o
obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o
obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
+obj-$(CONFIG_CHARGER_PF1550) += pf1550_charger.o
obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o
obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o pm2301_charger.o
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
+obj-$(CONFIG_SABRESD_MAX8903) += sabresd_battery.o
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
diff --git a/drivers/power/supply/pf1550_charger.c b/drivers/power/supply/pf1550_charger.c
new file mode 100644
index 000000000000..d14ef2b29ffd
--- /dev/null
+++ b/drivers/power/supply/pf1550_charger.c
@@ -0,0 +1,656 @@
+/*
+ * pf1550_charger.c - regulator driver for the PF1550
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Robin Gong <yibin.gong@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/mfd/pf1550.h>
+
+#define PF1550_CHARGER_NAME "pf1550-charger"
+#define PF1550_DEFAULT_CONSTANT_VOLT 4200000
+#define PF1550_DEFAULT_MIN_SYSTEM_VOLT 3500000
+#define PF1550_DEFAULT_THERMAL_TEMP 75
+
+static const char *pf1550_charger_model = "PF1550";
+static const char *pf1550_charger_manufacturer = "Freescale";
+
+struct pf1550_charger {
+ struct device *dev;
+ struct pf1550_dev *pf1550;
+ struct power_supply *charger;
+ struct power_supply_desc psy_desc;
+ int irq;
+ struct delayed_work irq_work;
+ struct mutex mutex;
+
+ u32 constant_volt;
+ u32 min_system_volt;
+ u32 thermal_regulation_temp;
+};
+
+static struct pf1550_irq_info pf1550_charger_irqs[] = {
+ { PF1550_CHARG_IRQ_BAT2SOCI, "BAT2SOC" },
+ { PF1550_CHARG_IRQ_BATI, "BAT" },
+ { PF1550_CHARG_IRQ_CHGI, "CHG" },
+ { PF1550_CHARG_IRQ_VBUSI, "VBUS" },
+ { PF1550_CHARG_IRQ_THMI, "THM" },
+};
+
+static int pf1550_get_charger_state(struct regmap *regmap, int *val)
+{
+ int ret;
+ unsigned int data;
+
+ ret = regmap_read(regmap, PF1550_CHARG_REG_CHG_SNS, &data);
+ if (ret < 0)
+ return ret;
+
+ data &= PF1550_CHG_SNS_MASK;
+
+ switch (data) {
+ case PF1550_CHG_PRECHARGE:
+ case PF1550_CHG_CONSTANT_CURRENT:
+ case PF1550_CHG_CONSTANT_VOL:
+ case PF1550_CHG_EOC:
+ *val = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ case PF1550_CHG_DONE:
+ *val = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case PF1550_CHG_TIMER_FAULT:
+ case PF1550_CHG_SUSPEND:
+ *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ case PF1550_CHG_OFF_INV:
+ case PF1550_CHG_OFF_TEMP:
+ case PF1550_CHG_LINEAR_ONLY:
+ *val = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ default:
+ *val = POWER_SUPPLY_STATUS_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static int pf1550_get_charge_type(struct regmap *regmap, int *val)
+{
+ int ret;
+ unsigned int data;
+
+ ret = regmap_read(regmap, PF1550_CHARG_REG_CHG_SNS, &data);
+ if (ret < 0)
+ return ret;
+
+ data &= PF1550_CHG_SNS_MASK;
+
+ switch (data) {
+ case PF1550_CHG_SNS_MASK:
+ *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ case PF1550_CHG_CONSTANT_CURRENT:
+ case PF1550_CHG_CONSTANT_VOL:
+ case PF1550_CHG_EOC:
+ *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ break;
+ case PF1550_CHG_DONE:
+ case PF1550_CHG_TIMER_FAULT:
+ case PF1550_CHG_SUSPEND:
+ case PF1550_CHG_OFF_INV:
+ case PF1550_CHG_BAT_OVER:
+ case PF1550_CHG_OFF_TEMP:
+ case PF1550_CHG_LINEAR_ONLY:
+ *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ break;
+ default:
+ *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+ }
+
+ return 0;
+}
+
+/*
+ * Supported health statuses:
+ * - POWER_SUPPLY_HEALTH_DEAD
+ * - POWER_SUPPLY_HEALTH_GOOD
+ * - POWER_SUPPLY_HEALTH_OVERVOLTAGE
+ * - POWER_SUPPLY_HEALTH_UNKNOWN
+ */
+static int pf1550_get_battery_health(struct regmap *regmap, int *val)
+{
+ int ret;
+ unsigned int data;
+
+ ret = regmap_read(regmap, PF1550_CHARG_REG_BATT_SNS, &data);
+ if (ret < 0)
+ return ret;
+
+ data &= PF1550_BAT_SNS_MASK;
+
+ switch (data) {
+ case PF1550_BAT_NO_DETECT:
+ *val = POWER_SUPPLY_HEALTH_DEAD;
+ break;
+ case PF1550_BAT_NO_VBUS:
+ case PF1550_BAT_LOW_THAN_PRECHARG:
+ case PF1550_BAT_CHARG_FAIL:
+ case PF1550_BAT_HIGH_THAN_PRECHARG:
+ *val = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ case PF1550_BAT_OVER_VOL:
+ *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ break;
+ default:
+ *val = POWER_SUPPLY_HEALTH_UNKNOWN;
+ break;
+ }
+
+ return 0;
+}
+
+static int pf1550_get_present(struct regmap *regmap, int *val)
+{
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(regmap, PF1550_CHARG_REG_BATT_SNS, &data);
+ if (ret < 0)
+ return ret;
+
+ data &= PF1550_BAT_SNS_MASK;
+ *val = (data == PF1550_BAT_NO_DETECT) ? 0 : 1;
+
+ return 0;
+}
+
+static int pf1550_get_online(struct regmap *regmap, int *val)
+{
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(regmap, PF1550_CHARG_REG_VBUS_SNS, &data);
+ if (ret < 0)
+ return ret;
+
+ *val = (data & PF1550_VBUS_VALID) ? 1 : 0;
+
+ return 0;
+}
+
+static void pf1550_chg_bat_isr(struct pf1550_charger *chg)
+{
+ unsigned int data;
+
+ if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_BATT_SNS, &data)) {
+ dev_err(chg->dev, "Read BATT_SNS error.\n");
+ return;
+ }
+
+ switch (data & PF1550_BAT_SNS_MASK) {
+ case PF1550_BAT_NO_VBUS:
+ dev_dbg(chg->dev, "No valid VBUS input.\n");
+ break;
+ case PF1550_BAT_LOW_THAN_PRECHARG:
+ dev_dbg(chg->dev, "VBAT < VPRECHG.LB.\n");
+ break;
+ case PF1550_BAT_CHARG_FAIL:
+ dev_dbg(chg->dev, "Battery charging failed.\n");
+ break;
+ case PF1550_BAT_HIGH_THAN_PRECHARG:
+ dev_dbg(chg->dev, "VBAT > VPRECHG.LB.\n");
+ break;
+ case PF1550_BAT_OVER_VOL:
+ dev_dbg(chg->dev, "VBAT > VBATOV.\n");
+ break;
+ case PF1550_BAT_NO_DETECT:
+ dev_dbg(chg->dev, "Battery not detected.\n");
+ break;
+ default:
+ dev_err(chg->dev, "Unknown value read:%x\n",
+ data & PF1550_CHG_SNS_MASK);
+ }
+}
+
+static void pf1550_chg_chg_isr(struct pf1550_charger *chg)
+{
+ unsigned int data;
+
+ if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_SNS, &data)) {
+ dev_err(chg->dev, "Read CHG_SNS error.\n");
+ return;
+ }
+
+ switch (data & PF1550_CHG_SNS_MASK) {
+ case PF1550_CHG_PRECHARGE:
+ dev_dbg(chg->dev, "In pre-charger mode.\n");
+ break;
+ case PF1550_CHG_CONSTANT_CURRENT:
+ dev_dbg(chg->dev, "In fast-charge constant current mode.\n");
+ break;
+ case PF1550_CHG_CONSTANT_VOL:
+ dev_dbg(chg->dev, "In fast-charge constant voltage mode.\n");
+ break;
+ case PF1550_CHG_EOC:
+ dev_dbg(chg->dev, "In EOC mode.\n");
+ break;
+ case PF1550_CHG_DONE:
+ dev_dbg(chg->dev, "In DONE mode.\n");
+ break;
+ case PF1550_CHG_TIMER_FAULT:
+ dev_info(chg->dev, "In timer fault mode.\n");
+ break;
+ case PF1550_CHG_SUSPEND:
+ dev_info(chg->dev, "In thermistor suspend mode.\n");
+ break;
+ case PF1550_CHG_OFF_INV:
+ dev_info(chg->dev, "Input invalid, charger off.\n");
+ break;
+ case PF1550_CHG_BAT_OVER:
+ dev_info(chg->dev, "Battery over-voltage.\n");
+ break;
+ case PF1550_CHG_OFF_TEMP:
+ dev_info(chg->dev, "Temp high, charger off.\n");
+ break;
+ case PF1550_CHG_LINEAR_ONLY:
+ dev_dbg(chg->dev, "In Linear mode, not charging.\n");
+ break;
+ default:
+ dev_err(chg->dev, "Unknown value read:%x\n",
+ data & PF1550_CHG_SNS_MASK);
+ }
+}
+
+static void pf1550_chg_vbus_isr(struct pf1550_charger *chg)
+{
+ enum power_supply_type old_type;
+ unsigned int data;
+
+ if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_VBUS_SNS, &data)) {
+ dev_err(chg->dev, "Read VBUS_SNS error.\n");
+ return;
+ }
+
+ old_type = chg->psy_desc.type;
+
+ if (data & PF1550_VBUS_UVLO) {
+ chg->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ dev_dbg(chg->dev, "VBUS deattached.\n");
+ }
+ if (data & PF1550_VBUS_IN2SYS)
+ dev_dbg(chg->dev, "VBUS_IN2SYS_SNS.\n");
+ if (data & PF1550_VBUS_OVLO)
+ dev_dbg(chg->dev, "VBUS_OVLO_SNS.\n");
+ if (data & PF1550_VBUS_VALID) {
+ chg->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
+ dev_dbg(chg->dev, "VBUS attached.\n");
+ }
+
+ if (old_type != chg->psy_desc.type)
+ power_supply_changed(chg->charger);
+}
+
+static irqreturn_t pf1550_charger_irq_handler(int irq, void *data)
+{
+ struct pf1550_charger *chg = data;
+
+ chg->irq = irq;
+ schedule_delayed_work(&chg->irq_work, msecs_to_jiffies(10));
+
+ return IRQ_HANDLED;
+}
+
+static void pf1550_charger_irq_work(struct work_struct *work)
+{
+ struct pf1550_charger *chg = container_of(to_delayed_work(work),
+ struct pf1550_charger,
+ irq_work);
+ int i, irq_type = -1;
+ unsigned int status;
+
+ if (!chg->charger)
+ return;
+
+ mutex_lock(&chg->mutex);
+
+ for (i = 0; i < ARRAY_SIZE(pf1550_charger_irqs); i++)
+ if (chg->irq == pf1550_charger_irqs[i].virq)
+ irq_type = pf1550_charger_irqs[i].irq;
+
+ switch (irq_type) {
+ case PF1550_CHARG_IRQ_BAT2SOCI:
+ dev_info(chg->dev, "BAT to SYS Overcurrent interrupt.\n");
+ break;
+ case PF1550_CHARG_IRQ_BATI:
+ pf1550_chg_bat_isr(chg);
+ break;
+ case PF1550_CHARG_IRQ_CHGI:
+ pf1550_chg_chg_isr(chg);
+ break;
+ case PF1550_CHARG_IRQ_VBUSI:
+ pf1550_chg_vbus_isr(chg);
+ break;
+ case PF1550_CHARG_IRQ_THMI:
+ dev_info(chg->dev, "Thermal interrupt.\n");
+ break;
+ default:
+ dev_err(chg->dev, "unknown interrupt occurred.\n");
+ }
+
+ if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_INT, &status))
+ dev_err(chg->dev, "Read CHG_INT error.\n");
+ if (regmap_write(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_INT, status))
+ dev_err(chg->dev, "clear CHG_INT error.\n");
+
+ mutex_unlock(&chg->mutex);
+}
+
+static enum power_supply_property pf1550_charger_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static int pf1550_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pf1550_charger *chg = power_supply_get_drvdata(psy);
+ struct regmap *regmap = chg->pf1550->regmap;
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ ret = pf1550_get_charger_state(regmap, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ ret = pf1550_get_charge_type(regmap, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ ret = pf1550_get_battery_health(regmap, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ ret = pf1550_get_present(regmap, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = pf1550_get_online(regmap, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = pf1550_charger_model;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = pf1550_charger_manufacturer;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int pf1550_set_constant_volt(struct pf1550_charger *chg,
+ unsigned int uvolt)
+{
+ unsigned int data;
+
+ if (uvolt >= 3500000 && uvolt <= 4440000)
+ data = 8 + (uvolt - 3500000) / 20000;
+ else {
+ dev_err(chg->dev, "Wrong value for constant voltage\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(chg->dev, "Charging constant voltage: %u (0x%x)\n", uvolt,
+ data);
+
+ return regmap_update_bits(chg->pf1550->regmap,
+ PF1550_CHARG_REG_BATT_REG,
+ PF1550_CHARG_REG_BATT_REG_CHGCV_MASK, data);
+}
+
+static int pf1550_set_min_system_volt(struct pf1550_charger *chg,
+ unsigned int uvolt)
+{
+ unsigned int data;
+
+ switch (uvolt) {
+ case 3500000:
+ data = 0x0;
+ break;
+ case 3700000:
+ data = 0x1;
+ break;
+ case 4300000:
+ data = 0x2;
+ break;
+ default:
+ dev_err(chg->dev, "Wrong value for minimum system voltage\n");
+ return -EINVAL;
+ }
+
+ data <<= PF1550_CHARG_REG_BATT_REG_VMINSYS_SHIFT;
+
+ dev_dbg(chg->dev, "Minimum system regulation voltage: %u (0x%x)\n",
+ uvolt, data);
+
+ return regmap_update_bits(chg->pf1550->regmap,
+ PF1550_CHARG_REG_BATT_REG,
+ PF1550_CHARG_REG_BATT_REG_VMINSYS_MASK, data);
+}
+
+static int pf1550_set_thermal_regulation_temp(struct pf1550_charger *chg,
+ unsigned int cels)
+{
+ unsigned int data;
+
+ switch (cels) {
+ case 60:
+ data = 0x0;
+ break;
+ case 75:
+ data = 0x1;
+ break;
+ case 90:
+ data = 0x2;
+ break;
+ case 105:
+ data = 0x3;
+ break;
+ default:
+ dev_err(chg->dev, "Wrong value for thermal temperature\n");
+ return -EINVAL;
+ }
+
+ data <<= PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_SHIFT;
+
+ dev_dbg(chg->dev, "Thermal regulation loop temperature: %u (0x%x)\n",
+ cels, data);
+
+ return regmap_update_bits(chg->pf1550->regmap,
+ PF1550_CHARG_REG_THM_REG_CNFG,
+ PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_MASK, data);
+}
+
+/*
+ * Sets charger registers to proper and safe default values.
+ */
+static int pf1550_reg_init(struct pf1550_charger *chg)
+{
+ int ret;
+ unsigned int data;
+
+ /* Unmask charger interrupt, mask DPMI and reserved bit */
+ ret = regmap_write(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_INT_MASK,
+ 0x51);
+ if (ret) {
+ dev_err(chg->dev, "Error unmask charger interrupt: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_VBUS_SNS,
+ &data);
+ if (ret) {
+ dev_err(chg->dev, "Read charg vbus_sns error: %d\n", ret);
+ return ret;
+ }
+
+ if (data & PF1550_VBUS_VALID)
+ chg->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
+
+ ret = pf1550_set_constant_volt(chg, chg->constant_volt);
+ if (ret)
+ return ret;
+
+ ret = pf1550_set_min_system_volt(chg, chg->min_system_volt);
+ if (ret)
+ return ret;
+
+ ret = pf1550_set_thermal_regulation_temp(chg,
+ chg->thermal_regulation_temp);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int pf1550_dt_init(struct device *dev, struct pf1550_charger *chg)
+{
+ struct device_node *np = dev->of_node;
+
+ if (!np) {
+ dev_err(dev, "no charger OF node\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(np, "fsl,constant-microvolt",
+ &chg->constant_volt))
+ chg->constant_volt = PF1550_DEFAULT_CONSTANT_VOLT;
+
+ if (of_property_read_u32(np, "fsl,min-system-microvolt",
+ &chg->min_system_volt))
+ chg->min_system_volt = PF1550_DEFAULT_MIN_SYSTEM_VOLT;
+
+ if (of_property_read_u32(np, "fsl,thermal-regulation",
+ &chg->thermal_regulation_temp))
+ chg->thermal_regulation_temp = PF1550_DEFAULT_THERMAL_TEMP;
+
+ return 0;
+}
+
+static int pf1550_charger_probe(struct platform_device *pdev)
+{
+ struct pf1550_charger *chg;
+ struct power_supply_config psy_cfg = {};
+ struct pf1550_dev *pf1550 = dev_get_drvdata(pdev->dev.parent);
+ int i, ret;
+
+ chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL);
+ if (!chg)
+ return -ENOMEM;
+
+ chg->dev = &pdev->dev;
+ chg->pf1550 = pf1550;
+
+ platform_set_drvdata(pdev, chg);
+
+ ret = pf1550_dt_init(&pdev->dev, chg);
+ if (ret)
+ return ret;
+
+ mutex_init(&chg->mutex);
+
+ INIT_DELAYED_WORK(&chg->irq_work, pf1550_charger_irq_work);
+
+ for (i = 0; i < ARRAY_SIZE(pf1550_charger_irqs); i++) {
+ struct pf1550_irq_info *charger_irq =
+ &pf1550_charger_irqs[i];
+ unsigned int virq = 0;
+
+ virq = regmap_irq_get_virq(pf1550->irq_data_charger,
+ charger_irq->irq);
+ if (!virq)
+ return -EINVAL;
+
+ charger_irq->virq = virq;
+
+ ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
+ pf1550_charger_irq_handler,
+ IRQF_NO_SUSPEND,
+ charger_irq->name, chg);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed: irq request (IRQ: %d, error :%d)\n",
+ charger_irq->irq, ret);
+ return ret;
+ }
+ }
+
+ psy_cfg.drv_data = chg;
+
+ chg->psy_desc.name = PF1550_CHARGER_NAME;
+ chg->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ chg->psy_desc.get_property = pf1550_charger_get_property;
+ chg->psy_desc.properties = pf1550_charger_props;
+ chg->psy_desc.num_properties = ARRAY_SIZE(pf1550_charger_props);
+
+ chg->charger = power_supply_register(&pdev->dev, &chg->psy_desc,
+ &psy_cfg);
+ if (IS_ERR(chg->charger)) {
+ dev_err(&pdev->dev, "failed: power supply register\n");
+ ret = PTR_ERR(chg->charger);
+ return ret;
+ }
+
+ ret = pf1550_reg_init(chg);
+
+ return ret;
+}
+
+static int pf1550_charger_remove(struct platform_device *pdev)
+{
+ struct pf1550_charger *chg = platform_get_drvdata(pdev);
+
+ cancel_delayed_work_sync(&chg->irq_work);
+ power_supply_unregister(chg->charger);
+
+ return 0;
+}
+
+static const struct platform_device_id pf1550_charger_id[] = {
+ { "pf1550-charger", 0, },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, pf1550_charger_id);
+
+static struct platform_driver pf1550_charger_driver = {
+ .driver = {
+ .name = "pf1550-charger",
+ },
+ .probe = pf1550_charger_probe,
+ .remove = pf1550_charger_remove,
+ .id_table = pf1550_charger_id,
+};
+module_platform_driver(pf1550_charger_driver);
+
+MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
+MODULE_DESCRIPTION("PF1550 charger driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/sabresd_battery.c b/drivers/power/supply/sabresd_battery.c
new file mode 100644
index 000000000000..5f479f83525a
--- /dev/null
+++ b/drivers/power/supply/sabresd_battery.c
@@ -0,0 +1,1014 @@
+/*
+ * sabresd_battery.c - Maxim 8903 USB/Adapter Charger Driver
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc.
+ * Based on max8903_charger.c
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/power_supply.h>
+#include <linux/platform_device.h>
+#include <linux/power/sabresd_battery.h>
+#include <linux/slab.h>
+
+#define BATTERY_UPDATE_INTERVAL 5 /*seconds*/
+#define LOW_VOLT_THRESHOLD 2800000
+#define HIGH_VOLT_THRESHOLD 4200000
+#define ADC_SAMPLE_COUNT 6
+
+struct max8903_data {
+ struct max8903_pdata *pdata;
+ struct device *dev;
+ struct power_supply *psy;
+ struct power_supply *usb;
+ struct power_supply *bat;
+ struct power_supply *detect_usb;
+ bool fault;
+ bool usb_in;
+ bool ta_in;
+ bool chg_state;
+ struct delayed_work work;
+ unsigned int interval;
+ unsigned short thermal_raw;
+ int voltage_uV;
+ int current_uA;
+ int battery_status;
+ int charger_online;
+ int charger_voltage_uV;
+ int real_capacity;
+ int percent;
+ int old_percent;
+ int usb_charger_online;
+ int first_delay_count;
+};
+
+typedef struct {
+ u32 voltage;
+ u32 percent;
+} battery_capacity , *pbattery_capacity;
+
+static int offset_discharger;
+static int offset_charger;
+static int offset_usb_charger;
+
+static battery_capacity chargingTable[] = {
+ {4050, 99},
+ {4040, 98},
+ {4020, 97},
+ {4010, 96},
+ {3990, 95},
+ {3980, 94},
+ {3970, 93},
+ {3960, 92},
+ {3950, 91},
+ {3940, 90},
+ {3930, 85},
+ {3920, 81},
+ {3910, 77},
+ {3900, 73},
+ {3890, 70},
+ {3860, 65},
+ {3830, 60},
+ {3780, 55},
+ {3760, 50},
+ {3740, 45},
+ {3720, 40},
+ {3700, 35},
+ {3680, 30},
+ {3660, 25},
+ {3640, 20},
+ {3620, 17},
+ {3600, 14},
+ {3580, 13},
+ {3560, 12},
+ {3540, 11},
+ {3520, 10},
+ {3500, 9},
+ {3480, 8},
+ {3460, 7},
+ {3440, 6},
+ {3430, 5},
+ {3420, 4},
+ {3020, 0},
+};
+
+static battery_capacity dischargingTable[] = {
+ {4050, 100},
+ {4035, 99},
+ {4020, 98},
+ {4010, 97},
+ {4000, 96},
+ {3990, 96},
+ {3980, 95},
+ {3970, 92},
+ {3960, 91},
+ {3950, 90},
+ {3940, 88},
+ {3930, 86},
+ {3920, 84},
+ {3910, 82},
+ {3900, 80},
+ {3890, 74},
+ {3860, 69},
+ {3830, 64},
+ {3780, 59},
+ {3760, 54},
+ {3740, 49},
+ {3720, 44},
+ {3700, 39},
+ {3680, 34},
+ {3660, 29},
+ {3640, 24},
+ {3620, 19},
+ {3600, 14},
+ {3580, 13},
+ {3560, 12},
+ {3540, 11},
+ {3520, 10},
+ {3500, 9},
+ {3480, 8},
+ {3460, 7},
+ {3440, 6},
+ {3430, 5},
+ {3420, 4},
+ {3020, 0},
+};
+
+u32 calibrate_battery_capability_percent(struct max8903_data *data)
+{
+ u8 i;
+ pbattery_capacity pTable;
+ u32 tableSize;
+
+ if (data->battery_status == POWER_SUPPLY_STATUS_DISCHARGING) {
+ pTable = dischargingTable;
+ tableSize = sizeof(dischargingTable)/
+ sizeof(dischargingTable[0]);
+ } else {
+ pTable = chargingTable;
+ tableSize = sizeof(chargingTable)/
+ sizeof(chargingTable[0]);
+ }
+ for (i = 0; i < tableSize; i++) {
+ if (data->voltage_uV >= pTable[i].voltage)
+ return pTable[i].percent;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property max8903_charger_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static enum power_supply_property max8903_battery_props[] = {
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+};
+
+extern int max11801_read_adc(void);
+
+static void max8903_charger_update_status(struct max8903_data *data)
+{
+ if (data->ta_in) {
+ data->charger_online = 1;
+ } else if (data->usb_in) {
+ data->usb_charger_online = 1;
+ } else {
+ data->charger_online = 0;
+ data->usb_charger_online = 0;
+ }
+
+ if (!data->charger_online && !data->usb_charger_online) {
+ data->battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
+ } else if (gpio_get_value(data->pdata->chg) == 0) {
+ data->battery_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else if ((data->ta_in || data->usb_in) &&
+ gpio_get_value(data->pdata->chg) > 0) {
+ if (!data->pdata->feature_flag) {
+ if (data->percent >= 99)
+ data->battery_status = POWER_SUPPLY_STATUS_FULL;
+ else
+ data->battery_status =
+ POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ data->battery_status = POWER_SUPPLY_STATUS_FULL;
+ }
+ }
+}
+
+u32 calibration_voltage(struct max8903_data *data)
+{
+ u32 voltage_data = 0;
+ int adc_val = 0;
+ int i;
+ int offset;
+
+ if (!data->charger_online && !data->usb_charger_online)
+ offset = offset_discharger;
+ else if (data->usb_charger_online)
+ offset = offset_usb_charger;
+ else if (data->charger_online)
+ offset = offset_charger;
+
+ /* simple average */
+ for (i = 0; i < ADC_SAMPLE_COUNT; i++) {
+ adc_val = max11801_read_adc();
+ /* Check if touch driver is probed */
+ if (max11801_read_adc() < 0)
+ break;
+ voltage_data += adc_val - offset;
+ }
+ voltage_data = voltage_data / ADC_SAMPLE_COUNT;
+ dev_dbg(data->dev, "volt: %d\n", voltage_data);
+
+ return voltage_data;
+}
+
+static void max8903_battery_update_status(struct max8903_data *data)
+{
+ if (!data->pdata->feature_flag) {
+ data->voltage_uV = calibration_voltage(data);
+ data->percent = calibrate_battery_capability_percent(data);
+ if (data->percent != data->old_percent) {
+ data->old_percent = data->percent;
+ power_supply_changed(data->bat);
+ }
+ /*
+ * because boot time gap between led framwork and charger
+ * framwork,when system boots with charger attatched,
+ * charger led framwork loses the first charger online event,
+ * add once extra power_supply_changed can fix this issure
+ */
+ if (data->first_delay_count < 200) {
+ data->first_delay_count = data->first_delay_count + 1;
+ power_supply_changed(data->bat);
+ }
+ }
+}
+
+static int max8903_battery_get_property(struct power_supply *bat,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max8903_data *di = power_supply_get_drvdata(bat);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ if (gpio_get_value(di->pdata->chg) == 0) {
+ di->battery_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else if ((di->ta_in || di->usb_in) &&
+ gpio_get_value(di->pdata->chg) > 0) {
+ if (!di->pdata->feature_flag) {
+ if (di->percent >= 99)
+ di->battery_status =
+ POWER_SUPPLY_STATUS_FULL;
+ else
+ di->battery_status =
+ POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ di->battery_status = POWER_SUPPLY_STATUS_FULL;
+ }
+ }
+ val->intval = di->battery_status;
+ return 0;
+ default:
+ break;
+ }
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = di->voltage_uV;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = HIGH_VOLT_THRESHOLD;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = LOW_VOLT_THRESHOLD;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = di->percent < 0 ? 0 :
+ (di->percent > 100 ? 100 : di->percent);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ if (di->fault)
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ if (di->battery_status == POWER_SUPPLY_STATUS_FULL)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (di->percent <= 15)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int max8903_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max8903_data *data = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = 0;
+ if (data->ta_in)
+ val->intval = 1;
+ data->charger_online = val->intval;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int max8903_get_usb_property(struct power_supply *usb,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max8903_data *data = power_supply_get_drvdata(usb);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = 0;
+ if (data->usb_in)
+ val->intval = 1;
+ data->usb_charger_online = val->intval;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t max8903_dcin(int irq, void *_data)
+{
+ struct max8903_data *data = _data;
+ struct max8903_pdata *pdata = data->pdata;
+ bool ta_in = false;
+
+ if (pdata->dok)
+ ta_in = gpio_get_value(pdata->dok) ? false : true;
+
+ if (ta_in == data->ta_in)
+ return IRQ_HANDLED;
+
+ data->ta_in = ta_in;
+ dev_info(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ?
+ "Connected" : "Disconnected");
+ max8903_charger_update_status(data);
+ power_supply_changed(data->psy);
+ power_supply_changed(data->bat);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t max8903_usbin(int irq, void *_data)
+{
+ struct max8903_data *data = _data;
+ struct max8903_pdata *pdata = data->pdata;
+ bool usb_in = false;
+
+ if (pdata->uok)
+ usb_in = gpio_get_value(pdata->uok) ? false : true;
+ if (usb_in == data->usb_in)
+ return IRQ_HANDLED;
+ data->usb_in = usb_in;
+ dev_info(data->dev, "USB Charger %s.\n", usb_in ?
+ "Connected" : "Disconnected");
+ max8903_charger_update_status(data);
+ power_supply_changed(data->bat);
+ power_supply_changed(data->usb);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t max8903_fault(int irq, void *_data)
+{
+ struct max8903_data *data = _data;
+ struct max8903_pdata *pdata = data->pdata;
+ bool fault;
+
+ fault = gpio_get_value(pdata->flt) ? false : true;
+
+ if (fault == data->fault)
+ return IRQ_HANDLED;
+ data->fault = fault;
+
+ if (fault)
+ dev_err(data->dev, "Charger suffers a fault and stops.\n");
+ else
+ dev_err(data->dev, "Charger recovered from a fault.\n");
+ max8903_charger_update_status(data);
+ power_supply_changed(data->psy);
+ power_supply_changed(data->bat);
+ power_supply_changed(data->usb);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t max8903_chg(int irq, void *_data)
+{
+ struct max8903_data *data = _data;
+ struct max8903_pdata *pdata = data->pdata;
+ int chg_state;
+
+ chg_state = gpio_get_value(pdata->chg) ? false : true;
+
+ if (chg_state == data->chg_state)
+ return IRQ_HANDLED;
+ data->chg_state = chg_state;
+ max8903_charger_update_status(data);
+ power_supply_changed(data->psy);
+ power_supply_changed(data->bat);
+ power_supply_changed(data->usb);
+
+ return IRQ_HANDLED;
+}
+
+static void max8903_battery_work(struct work_struct *work)
+{
+ struct max8903_data *data;
+
+ data = container_of(work, struct max8903_data, work.work);
+ data->interval = HZ * BATTERY_UPDATE_INTERVAL;
+
+ max8903_charger_update_status(data);
+ max8903_battery_update_status(data);
+ dev_dbg(data->dev, "battery voltage: %4d mV\n", data->voltage_uV);
+ dev_dbg(data->dev, "charger online status: %d\n",
+ data->charger_online);
+ dev_dbg(data->dev, "battery status : %d\n" , data->battery_status);
+ dev_dbg(data->dev, "battery capacity percent: %3d\n", data->percent);
+ dev_dbg(data->dev, "data->usb_in: %x , data->ta_in: %x\n",
+ data->usb_in, data->ta_in);
+ /* reschedule for the next time */
+ schedule_delayed_work(&data->work, data->interval);
+}
+
+static ssize_t max8903_voltage_offset_discharger_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "read offset_discharger:%04d\n",
+ offset_discharger);
+}
+
+static ssize_t max8903_voltage_offset_discharger_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int ret;
+ unsigned long data;
+
+ ret = kstrtoul(buf, 10, &data);
+ offset_discharger = (int)data;
+ pr_info("read offset_discharger:%04d\n", offset_discharger);
+
+ return count;
+}
+
+static ssize_t max8903_voltage_offset_charger_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "read offset_charger:%04d\n",
+ offset_charger);
+}
+
+static ssize_t max8903_voltage_offset_charger_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int ret;
+ unsigned long data;
+
+ ret = kstrtoul(buf, 10, &data);
+ offset_charger = (int)data;
+ pr_info("read offset_charger:%04d\n", offset_charger);
+ return count;
+}
+
+static ssize_t max8903_voltage_offset_usb_charger_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "read offset_usb_charger:%04d\n",
+ offset_usb_charger);
+}
+
+static ssize_t max8903_voltage_offset_usb_charger_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int ret;
+ unsigned long data;
+
+ ret = kstrtoul(buf, 10, &data);
+ offset_usb_charger = (int)data;
+ pr_info("read offset_charger:%04d\n", offset_usb_charger);
+
+ return count;
+}
+
+static struct device_attribute max8903_discharger_dev_attr = {
+ .attr = {
+ .name = "max8903_ctl_offset_discharger",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .show = max8903_voltage_offset_discharger_show,
+ .store = max8903_voltage_offset_discharger_store,
+};
+
+static struct device_attribute max8903_charger_dev_attr = {
+ .attr = {
+ .name = "max8903_ctl_offset_charger",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .show = max8903_voltage_offset_charger_show,
+ .store = max8903_voltage_offset_charger_store,
+};
+
+static struct device_attribute max8903_usb_charger_dev_attr = {
+ .attr = {
+ .name = "max8903_ctl_offset_usb_charger",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .show = max8903_voltage_offset_usb_charger_show,
+ .store = max8903_voltage_offset_usb_charger_store,
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id max8903_dt_ids[] = {
+ { .compatible = "fsl,max8903-charger", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, max8903_dt_ids);
+
+static struct max8903_pdata *max8903_of_populate_pdata(
+ struct device *dev)
+{
+ struct device_node *of_node = dev->of_node;
+ struct max8903_pdata *pdata = dev->platform_data;
+
+ if (!of_node || pdata)
+ return pdata;
+
+ pdata = devm_kzalloc(dev, sizeof(struct max8903_pdata),
+ GFP_KERNEL);
+ if (!pdata)
+ return pdata;
+
+ if (of_get_property(of_node, "fsl,dcm_always_high", NULL))
+ pdata->dcm_always_high = true;
+ if (of_get_property(of_node, "fsl,dc_valid", NULL))
+ pdata->dc_valid = true;
+ if (of_get_property(of_node, "fsl,usb_valid", NULL))
+ pdata->usb_valid = true;
+ if (of_get_property(of_node, "fsl,adc_disable", NULL))
+ pdata->feature_flag = true;
+
+ if (pdata->dc_valid) {
+ pdata->dok = of_get_named_gpio(of_node, "dok_input", 0);
+ if (!gpio_is_valid(pdata->dok)) {
+ dev_err(dev, "pin pdata->dok: invalid gpio %d\n", pdata->dok);
+ return NULL;
+ }
+ }
+ if (pdata->usb_valid) {
+ pdata->uok = of_get_named_gpio(of_node, "uok_input", 0);
+ if (!gpio_is_valid(pdata->uok)) {
+ dev_err(dev, "pin pdata->uok: invalid gpio %d\n", pdata->uok);
+ return NULL;
+ }
+ }
+ pdata->chg = of_get_named_gpio(of_node, "chg_input", 0);
+ if (!gpio_is_valid(pdata->chg)) {
+ dev_err(dev, "pin pdata->chg: invalid gpio %d\n", pdata->chg);
+ return NULL;
+ }
+ pdata->flt = of_get_named_gpio(of_node, "flt_input", 0);
+ if (!gpio_is_valid(pdata->flt)) {
+ dev_err(dev, "pin pdata->flt: invalid gpio %d\n", pdata->flt);
+ return NULL;
+ }
+
+ /* no need check offset without adc converter */
+ if (!pdata->feature_flag) {
+ if (of_property_read_u32(of_node, "offset-charger",
+ &offset_charger))
+ dev_err(dev, "Not setting offset-charger in dts!\n");
+
+ if (of_property_read_u32(of_node, "offset-discharger",
+ &offset_discharger))
+ dev_err(dev, "Not setting offset-discharger in dts!\n");
+
+ if (of_property_read_u32(of_node, "offset-usb-charger",
+ &offset_usb_charger))
+ dev_err(dev, "Not setting offset-usb-charger in dts!\n");
+ }
+
+ return pdata;
+}
+#endif
+
+static const struct power_supply_desc max8903_ac_desc = {
+ .name = "max8903-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .get_property = max8903_get_property,
+ .properties = max8903_charger_props,
+ .num_properties = ARRAY_SIZE(max8903_charger_props),
+};
+
+static const struct power_supply_desc max8903_usb_desc = {
+ .name = "max8903-usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .get_property = max8903_get_usb_property,
+ .properties = max8903_charger_props,
+ .num_properties = ARRAY_SIZE(max8903_charger_props),
+};
+
+static const struct power_supply_desc max8903_bat_desc = {
+ .name = "max8903-charger",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = max8903_battery_props,
+ .num_properties = ARRAY_SIZE(max8903_battery_props),
+ .get_property = max8903_battery_get_property,
+ .use_for_apm = 1,
+};
+
+static int max8903_probe(struct platform_device *pdev)
+{
+ struct max8903_data *data;
+ struct device *dev = &pdev->dev;
+ struct max8903_pdata *pdata = pdev->dev.platform_data;
+ int ret = 0;
+ int gpio = 0;
+ int ta_in = 0;
+ int usb_in = 0;
+ struct power_supply_config psy_cfg = {};
+
+ data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ pdata = max8903_of_populate_pdata(&pdev->dev);
+ if (!pdata)
+ return -EINVAL;
+ }
+
+ data->first_delay_count = 0;
+ data->pdata = pdata;
+ data->dev = dev;
+ data->usb_in = 0;
+ data->ta_in = 0;
+ platform_set_drvdata(pdev, data);
+
+ if (pdata->dc_valid == false && pdata->usb_valid == false) {
+ dev_err(dev, "No valid power sources.\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (pdata->dc_valid) {
+ if (pdata->dok && pdata->dcm_always_high) {
+ gpio = pdata->dok;
+ ret = gpio_request_one(gpio, GPIOF_IN, "max8903-DOK");
+ if (ret) {
+ dev_err(dev, "request max8903-DOK error!!\n");
+ goto err;
+ }
+ ta_in = gpio_get_value(gpio) ? 0 : 1;
+ } else {
+ dev_err(dev, "When DC is wired, DOK and DCM should be"
+ " wired as well or set dcm always high!\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ if (pdata->usb_valid) {
+ if (pdata->uok) {
+ gpio = pdata->uok;
+ ret = gpio_request_one(gpio, GPIOF_IN, "max8903-UOK");
+ if (ret) {
+ dev_err(dev, "request max8903-UOK error!!\n");
+ goto err;
+ }
+ usb_in = gpio_get_value(gpio) ? 0 : 1;
+ } else {
+ dev_err(dev, "When USB is wired, UOK should be wired"
+ " as well.\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ if (pdata->chg) {
+ ret = gpio_request_one(pdata->chg, GPIOF_IN, "max8903-CHG");
+ if (ret) {
+ dev_err(dev, "request max8903-CHG error!!\n");
+ goto err;
+ }
+ }
+
+ if (pdata->flt) {
+ ret = gpio_request_one(pdata->flt, GPIOF_IN, "max8903-FLT");
+ if (ret) {
+ dev_err(dev, "request max8903-FLT error!!\n");
+ goto err;
+ }
+ }
+
+ data->fault = false;
+ data->ta_in = ta_in;
+ data->usb_in = usb_in;
+
+ psy_cfg.of_node = dev->of_node;
+ psy_cfg.drv_data = data;
+
+ data->psy = power_supply_register(dev, &max8903_ac_desc, &psy_cfg);
+ if (IS_ERR(data->psy)) {
+ dev_err(dev, "failed: power supply register.\n");
+ goto err;
+ }
+
+ data->usb = power_supply_register(dev, &max8903_usb_desc, &psy_cfg);
+ if (IS_ERR(data->usb)) {
+ dev_err(dev, "failed: power supply register.\n");
+ goto err_psy;
+ }
+
+ data->bat = power_supply_register(dev, &max8903_bat_desc, &psy_cfg);
+ if (IS_ERR(data->bat)) {
+ dev_err(data->dev, "failed to register battery\n");
+ goto err_usb;
+ }
+
+ INIT_DELAYED_WORK(&data->work, max8903_battery_work);
+ schedule_delayed_work(&data->work, data->interval);
+
+ if (pdata->dc_valid) {
+ ret = request_threaded_irq(gpio_to_irq(pdata->dok), NULL,
+ max8903_dcin, IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "MAX8903 DC IN",
+ data);
+ if (ret) {
+ dev_err(dev, "Cannot request irq %d for DC (%d)\n",
+ gpio_to_irq(pdata->dok), ret);
+ goto err_dc_irq;
+ }
+ }
+
+ if (pdata->usb_valid) {
+ ret = request_threaded_irq(gpio_to_irq(pdata->uok), NULL,
+ max8903_usbin, IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "MAX8903 USB IN",
+ data);
+ if (ret) {
+ dev_err(dev, "Cannot request irq %d for USB (%d)\n",
+ gpio_to_irq(pdata->uok), ret);
+ goto err_usb_irq;
+ }
+ }
+
+ if (pdata->flt) {
+ ret = request_threaded_irq(gpio_to_irq(pdata->flt), NULL,
+ max8903_fault, IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "MAX8903 Fault",
+ data);
+ if (ret) {
+ dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
+ gpio_to_irq(pdata->flt), ret);
+ goto err_flt_irq;
+ }
+ }
+
+ if (pdata->chg) {
+ ret = request_threaded_irq(gpio_to_irq(pdata->chg), NULL,
+ max8903_chg, IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "MAX8903 Status",
+ data);
+ if (ret) {
+ dev_err(dev, "Cannot request irq %d for Status (%d)\n",
+ gpio_to_irq(pdata->flt), ret);
+ goto err_chg_irq;
+ }
+ }
+
+ ret = device_create_file(&pdev->dev, &max8903_discharger_dev_attr);
+ if (ret)
+ dev_err(&pdev->dev, "create device file failed!\n");
+ ret = device_create_file(&pdev->dev, &max8903_charger_dev_attr);
+ if (ret)
+ dev_err(&pdev->dev, "create device file failed!\n");
+ ret = device_create_file(&pdev->dev, &max8903_usb_charger_dev_attr);
+ if (ret)
+ dev_err(&pdev->dev, "create device file failed!\n");
+
+ device_set_wakeup_capable(&pdev->dev, true);
+
+ max8903_charger_update_status(data);
+ max8903_battery_update_status(data);
+
+ return 0;
+err_chg_irq:
+ if (pdata->chg)
+ free_irq(gpio_to_irq(pdata->chg), data);
+err_flt_irq:
+ if (pdata->flt)
+ free_irq(gpio_to_irq(pdata->flt), data);
+err_usb_irq:
+ if (pdata->usb_valid)
+ free_irq(gpio_to_irq(pdata->uok), data);
+err_dc_irq:
+ if (pdata->dc_valid)
+ free_irq(gpio_to_irq(pdata->dok), data);
+ cancel_delayed_work(&data->work);
+ power_supply_unregister(data->bat);
+err_usb:
+ power_supply_unregister(data->usb);
+err_psy:
+ power_supply_unregister(data->psy);
+err:
+ if (pdata->uok)
+ gpio_free(pdata->uok);
+ if (pdata->dok)
+ gpio_free(pdata->dok);
+ if (pdata->flt)
+ gpio_free(pdata->flt);
+ if (pdata->chg)
+ gpio_free(pdata->chg);
+ return ret;
+}
+
+static int max8903_remove(struct platform_device *pdev)
+{
+ struct max8903_data *data = platform_get_drvdata(pdev);
+ if (data) {
+ struct max8903_pdata *pdata = data->pdata;
+
+ cancel_delayed_work_sync(&data->work);
+ power_supply_unregister(data->psy);
+ power_supply_unregister(data->usb);
+ power_supply_unregister(data->bat);
+
+ if (pdata->flt) {
+ free_irq(gpio_to_irq(pdata->flt), data);
+ gpio_free(pdata->flt);
+ }
+ if (pdata->usb_valid && pdata->uok) {
+ free_irq(gpio_to_irq(pdata->uok), data);
+ gpio_free(pdata->uok);
+ }
+ if (pdata->dc_valid) {
+ if (pdata->dok) {
+ free_irq(gpio_to_irq(pdata->dok), data);
+ gpio_free(pdata->dok);
+ } else if (pdata->chg) {
+ free_irq(gpio_to_irq(pdata->chg), data);
+ gpio_free(pdata->chg);
+ }
+ }
+
+ device_remove_file(&pdev->dev, &max8903_discharger_dev_attr);
+ device_remove_file(&pdev->dev, &max8903_charger_dev_attr);
+ device_remove_file(&pdev->dev, &max8903_usb_charger_dev_attr);
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(data);
+ }
+
+ return 0;
+}
+
+static int max8903_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct max8903_data *data = platform_get_drvdata(pdev);
+ int irq;
+ if (data) {
+ struct max8903_pdata *pdata = data->pdata;
+ if (pdata) {
+ if (pdata->dc_valid && device_may_wakeup(&pdev->dev)) {
+ irq = gpio_to_irq(pdata->dok);
+ enable_irq_wake(irq);
+ }
+
+ if (pdata->usb_valid && device_may_wakeup(&pdev->dev)) {
+ irq = gpio_to_irq(pdata->uok);
+ enable_irq_wake(irq);
+ }
+ cancel_delayed_work(&data->work);
+ }
+ }
+ return 0;
+}
+
+static int max8903_resume(struct platform_device *pdev)
+{
+ struct max8903_data *data = platform_get_drvdata(pdev);
+ bool ta_in = false;
+ bool usb_in = false;
+ int irq;
+
+ if (data) {
+ struct max8903_pdata *pdata = data->pdata;
+
+ if (pdata) {
+ if (pdata->dok)
+ ta_in = gpio_get_value(pdata->dok) ? false : true;
+ if (pdata->uok)
+ usb_in = gpio_get_value(pdata->uok) ? false : true;
+
+ if (ta_in != data->ta_in) {
+ data->ta_in = ta_in;
+ dev_info(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ?
+ "Connected" : "Disconnected");
+ max8903_charger_update_status(data);
+ power_supply_changed(data->psy);
+ }
+
+ if (usb_in != data->usb_in) {
+ data->usb_in = usb_in;
+ dev_info(data->dev, "USB Charger %s.\n", usb_in ?
+ "Connected" : "Disconnected");
+ max8903_charger_update_status(data);
+ power_supply_changed(data->usb);
+ }
+
+ if (pdata->dc_valid && device_may_wakeup(&pdev->dev)) {
+ irq = gpio_to_irq(pdata->dok);
+ disable_irq_wake(irq);
+ }
+ if (pdata->usb_valid && device_may_wakeup(&pdev->dev)) {
+ irq = gpio_to_irq(pdata->uok);
+ disable_irq_wake(irq);
+ }
+
+ schedule_delayed_work(&data->work,
+ BATTERY_UPDATE_INTERVAL);
+ }
+ }
+
+ return 0;
+}
+
+static struct platform_driver max8903_driver = {
+ .probe = max8903_probe,
+ .remove = max8903_remove,
+ .suspend = max8903_suspend,
+ .resume = max8903_resume,
+ .driver = {
+ .name = "max8903-charger",
+ .owner = THIS_MODULE,
+ .of_match_table = max8903_dt_ids,
+ },
+};
+module_platform_driver(max8903_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Sabresd Battery Driver");
+MODULE_ALIAS("sabresd_battery");
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index bf0128899c09..cf1f35945503 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -197,6 +197,15 @@ config PWM_IMX
To compile this driver as a module, choose M here: the module
will be called pwm-imx.
+config PWM_TPM
+ tristate "i.MX TPM PWM support"
+ depends on ARCH_MXC
+ help
+ Generic PWM framework driver for i.MX TPM.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-tpm.
+
config PWM_JZ4740
tristate "Ingenic JZ4740 PWM support"
depends on MACH_JZ4740
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 1194c54efcc2..e13e3b19ce36 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
obj-$(CONFIG_PWM_IMG) += pwm-img.o
obj-$(CONFIG_PWM_IMX) += pwm-imx.o
+obj-$(CONFIG_PWM_TPM) += pwm-tpm.o
obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o
obj-$(CONFIG_PWM_LPC18XX_SCT) += pwm-lpc18xx-sct.o
diff --git a/drivers/pwm/pwm-tpm.c b/drivers/pwm/pwm-tpm.c
new file mode 100644
index 000000000000..949bed600f74
--- /dev/null
+++ b/drivers/pwm/pwm-tpm.c
@@ -0,0 +1,253 @@
+/*
+ * 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/bitops.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#define TPM_GLOBAL 0x8
+#define TPM_SC 0x10
+#define TPM_CNT 0x14
+#define TPM_MOD 0x18
+#define TPM_C0SC 0x20
+#define TPM_C0V 0x24
+
+#define SC_CMOD 3
+#define SC_CPWMS BIT(5)
+#define MSnB BIT(5)
+#define MSnA BIT(4)
+#define ELSnB BIT(3)
+#define ELSnA BIT(2)
+
+#define PERIOD_PERIOD_MAX 0x10000
+#define PERIOD_DIV_MAX 8
+
+struct tpm_pwm_chip {
+ struct pwm_chip chip;
+ struct clk *clk;
+ void __iomem *base;
+};
+
+static const unsigned int prediv[8] = {
+ 1, 2, 4, 8, 16, 32, 64, 128
+};
+
+#define to_tpm_pwm_chip(_chip) container_of(_chip, struct tpm_pwm_chip, chip)
+
+static int tpm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct tpm_pwm_chip *tpm = to_tpm_pwm_chip(chip);
+ int ret, div = 0;
+ unsigned int period_cycles, duty_cycles;
+ unsigned long rate;
+ u64 c;
+
+ rate = clk_get_rate(tpm->clk);
+ /* calculate the period_cycles and duty_cycles */
+ while (1) {
+ c = rate / prediv[div];
+ c = c * period_ns;
+ do_div(c, 1000000000);
+ if (c < PERIOD_PERIOD_MAX)
+ break;
+ div++;
+ if (div >= 8)
+ return -EINVAL;
+ }
+
+ /* enable the clock before writing the register */
+ if (!pwm_is_enabled(pwm)) {
+ ret = clk_prepare_enable(tpm->clk);
+ if (ret)
+ return ret;
+ }
+
+ period_cycles = c;
+ c *= duty_ns;
+ do_div(c, period_ns);
+ duty_cycles = c;
+
+ writel(period_cycles & 0xffff, tpm->base + TPM_MOD);
+ writel(duty_cycles & 0xffff, tpm->base + TPM_C0V + pwm->hwpwm * 0x8);
+
+ /* if pwm is not enabled, disable clk after setting */
+ if (!pwm_is_enabled(pwm))
+ clk_disable_unprepare(tpm->clk);
+
+ return 0;
+}
+
+static int tpm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct tpm_pwm_chip *tpm = to_tpm_pwm_chip(chip);
+ int val;
+
+ clk_prepare_enable(tpm->clk);
+ /*
+ * To enable a tpm channel, CPWMS = 0, MSnB:MSnA = 0x0,
+ * for TPM normal polarity ELSnB:ELSnA = 2b'10,
+ * inverse ELSnB:ELSnA = 2b'01
+ */
+ val = readl(tpm->base + TPM_C0SC + pwm->hwpwm * 0x8);
+
+ val &= ~(MSnB | MSnA | ELSnB | ELSnA);
+ val |= MSnB;
+ val |= pwm->state.polarity ? ELSnA : ELSnB;
+
+ writel(val, tpm->base + TPM_C0SC + pwm->hwpwm * 0x8);
+
+ /* start the counter */
+ val = readl(tpm->base + TPM_SC);
+ val |= 0x1 << SC_CMOD;
+ writel(val, tpm->base + TPM_SC);
+
+ return 0;
+}
+
+static void tpm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct tpm_pwm_chip *tpm = to_tpm_pwm_chip(chip);
+
+ clk_disable_unprepare(tpm->clk);
+}
+
+static int tpm_pwm_set_polarity(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ enum pwm_polarity polarity)
+{
+ struct tpm_pwm_chip *tpm = to_tpm_pwm_chip(chip);
+ int ret, val;
+
+ /* enable the clock before writing the register */
+ if (!pwm_is_enabled(pwm)) {
+ ret = clk_prepare_enable(tpm->clk);
+ if (ret)
+ return ret;
+ }
+
+ val = readl(tpm->base + TPM_C0SC + pwm->hwpwm * 0x8);
+ val &= ~(ELSnB | ELSnA);
+ val |= pwm->state.polarity ? ELSnA : ELSnB;
+ writel(val, tpm->base + TPM_C0SC + pwm->hwpwm * 0x8);
+
+ if (!pwm_is_enabled(pwm))
+ clk_disable_unprepare(tpm->clk);
+
+ return 0;
+}
+
+static const struct pwm_ops tpm_pwm_ops = {
+ .config = tpm_pwm_config,
+ .enable = tpm_pwm_enable,
+ .disable = tpm_pwm_disable,
+ .set_polarity = tpm_pwm_set_polarity,
+ .owner = THIS_MODULE,
+};
+
+static int tpm_pwm_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct tpm_pwm_chip *tpm;
+ struct resource *res;
+ int ret;
+
+ tpm = devm_kzalloc(&pdev->dev, sizeof(*tpm), GFP_KERNEL);
+ if (!tpm)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ tpm->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(tpm->base))
+ return PTR_ERR(tpm->base);
+
+ tpm->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(tpm->clk))
+ return PTR_ERR(tpm->clk);
+
+ tpm->chip.dev = &pdev->dev;
+ tpm->chip.ops = &tpm_pwm_ops;
+ tpm->chip.base = -1;
+ tpm->chip.can_sleep = true;
+ /*
+ * init the number of pwm in the pwm chip. if no "fsl,pwm-number"
+ * found, init the npwm to 2, as tpm module has at least two pwm channel
+ */
+ ret = of_property_read_u32(np, "nxp,pwm-number", &tpm->chip.npwm);
+ if (ret < 0) {
+ dev_info(&pdev->dev, "default two pwm channel");
+ tpm->chip.npwm = 2;
+ }
+
+ ret = pwmchip_add(&tpm->chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, tpm);
+
+ return 0;
+}
+
+static int tpm_pwm_remove(struct platform_device *pdev)
+{
+ struct tpm_pwm_chip *tpm = platform_get_drvdata(pdev);
+
+ return pwmchip_remove(&tpm->chip);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tpm_pwm_suspend(struct device *dev)
+{
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static int tpm_pwm_resume(struct device *dev)
+{
+ pinctrl_pm_select_default_state(dev);
+
+ return 0;
+};
+#endif
+
+static SIMPLE_DEV_PM_OPS(tpm_pwm_pm, tpm_pwm_suspend, tpm_pwm_resume);
+
+static const struct of_device_id tpm_pwm_dt_ids[] = {
+ { .compatible = "nxp,tpm-pwm", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tpm_pwm_dt_ids);
+
+static struct platform_driver tpm_pwm_driver = {
+ .driver = {
+ .name = "tpm-pwm",
+ .of_match_table = tpm_pwm_dt_ids,
+ .pm = &tpm_pwm_pm,
+ },
+ .probe = tpm_pwm_probe,
+ .remove = tpm_pwm_remove,
+};
+module_platform_driver(tpm_pwm_driver);
+
+MODULE_ALIAS("platform:tpm-pwm");
+MODULE_AUTHOR("Jacky Bai <ping.bai@nxp.com>");
+MODULE_DESCRIPTION("NXP TPM PWM Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 936f7ccc9736..9fa9aa29affe 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -377,6 +377,10 @@ config REGULATOR_MAX1586
regulator via I2C bus. The provided regulator is suitable
for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
+config REGULATOR_MAX17135
+ tristate "Maxim MAX17135 Regulator Support"
+ depends on MFD_MAX17135
+
config REGULATOR_MAX77620
tristate "Maxim 77620/MAX20024 voltage regulator"
depends on MFD_MAX77620
@@ -590,6 +594,21 @@ config REGULATOR_PV88090
Say y here to support the voltage regulators and convertors
on PV88090
+config REGULATOR_PF1550
+ tristate "Freescale PF1550 regulator"
+ depends on MFD_PF1550
+ help
+ This driver controls a PF1550 regulator via I2C bus.
+ The regulators include three switch and three ldo.
+
+config REGULATOR_PF1550_RPMSG
+ tristate "Freescale PF1550 rpmsg regulator driver"
+ depends on RPMSG
+ help
+ This driver controls a PF1550 regulator which connected in M4
+ side via RPMSG.The regulators include three switch and three
+ ldo.
+
config REGULATOR_PWM
tristate "PWM voltage regulator"
depends on PWM
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2142a5d3fc08..3a18d9bf57d8 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o
obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o
obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
+obj-$(CONFIG_REGULATOR_MAX17135) += max17135-regulator.o
obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
@@ -72,6 +73,8 @@ obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_PF1550) += pf1550.o
+obj-$(CONFIG_REGULATOR_PF1550_RPMSG) += pf1550-regulator-rpmsg.o
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
obj-$(CONFIG_REGULATOR_PV88060) += pv88060-regulator.o
obj-$(CONFIG_REGULATOR_PV88080) += pv88080-regulator.o
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 3a6d0290c54c..21f72f1c1100 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -38,6 +38,8 @@
#define LDO_POWER_GATE 0x00
#define LDO_FET_FULL_ON 0x1f
+#define LDO_MIN_DROPOUT_UV 125000
+
struct anatop_regulator {
const char *name;
u32 control_reg;
@@ -54,8 +56,12 @@ struct anatop_regulator {
struct regulator_init_data *initdata;
bool bypass;
int sel;
+ u32 enable_bit;
};
+static struct anatop_regulator *vddpu;
+static struct anatop_regulator *vddsoc;
+
static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg,
unsigned int old_sel,
unsigned int new_sel)
@@ -82,21 +88,32 @@ static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg,
return ret;
}
-static int anatop_regmap_enable(struct regulator_dev *reg)
+static int anatop_core_regmap_enable(struct regulator_dev *reg)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
int sel;
+ /*
+ * The vddpu has to stay at the same voltage level as vddsoc
+ * whenever it's about to be enabled.
+ */
+ if (anatop_reg == vddpu && vddsoc) {
+ anatop_reg->sel = vddsoc->sel;
+ anatop_reg->bypass = vddsoc->bypass;
+ if (anatop_reg->bypass)
+ anatop_reg->rdesc.min_dropout_uV = 0;
+ }
+
sel = anatop_reg->bypass ? LDO_FET_FULL_ON : anatop_reg->sel;
return regulator_set_voltage_sel_regmap(reg, sel);
}
-static int anatop_regmap_disable(struct regulator_dev *reg)
+static int anatop_core_regmap_disable(struct regulator_dev *reg)
{
return regulator_set_voltage_sel_regmap(reg, LDO_POWER_GATE);
}
-static int anatop_regmap_is_enabled(struct regulator_dev *reg)
+static int anatop_core_regmap_is_enabled(struct regulator_dev *reg)
{
return regulator_get_voltage_sel_regmap(reg) != LDO_POWER_GATE;
}
@@ -107,7 +124,7 @@ static int anatop_regmap_core_set_voltage_sel(struct regulator_dev *reg,
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
int ret;
- if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg)) {
+ if (anatop_reg->bypass || !anatop_core_regmap_is_enabled(reg)) {
anatop_reg->sel = selector;
return 0;
}
@@ -122,7 +139,7 @@ static int anatop_regmap_core_get_voltage_sel(struct regulator_dev *reg)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
- if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg))
+ if (anatop_reg->bypass || !anatop_core_regmap_is_enabled(reg))
return anatop_reg->sel;
return regulator_get_voltage_sel_regmap(reg);
@@ -153,11 +170,52 @@ static int anatop_regmap_set_bypass(struct regulator_dev *reg, bool enable)
sel = enable ? LDO_FET_FULL_ON : anatop_reg->sel;
anatop_reg->bypass = enable;
+ if (anatop_reg->bypass)
+ anatop_reg->rdesc.min_dropout_uV = 0;
+ else
+ anatop_reg->rdesc.min_dropout_uV = LDO_MIN_DROPOUT_UV;
return regulator_set_voltage_sel_regmap(reg, sel);
}
+static int anatop_regmap_enable(struct regulator_dev *reg)
+{
+ u32 val;
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+
+ regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
+ val |= (1 << anatop_reg->enable_bit);
+ regmap_write(anatop_reg->anatop, anatop_reg->control_reg, val);
+
+ return 0;
+}
+
+static int anatop_regmap_disable(struct regulator_dev *reg)
+{
+ u32 val;
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+
+ regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
+ val &= ~(1 << anatop_reg->enable_bit);
+ regmap_write(anatop_reg->anatop, anatop_reg->control_reg, val);
+
+ return 0;
+}
+
+static int anatop_regmap_is_enabled(struct regulator_dev *reg)
+{
+ u32 val;
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+
+ regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
+
+ return !!(val & (1 << anatop_reg->enable_bit));
+}
+
static struct regulator_ops anatop_rops = {
+ .enable = anatop_regmap_enable,
+ .disable = anatop_regmap_disable,
+ .is_enabled = anatop_regmap_is_enabled,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
@@ -165,9 +223,9 @@ static struct regulator_ops anatop_rops = {
};
static struct regulator_ops anatop_core_rops = {
- .enable = anatop_regmap_enable,
- .disable = anatop_regmap_disable,
- .is_enabled = anatop_regmap_is_enabled,
+ .enable = anatop_core_regmap_enable,
+ .disable = anatop_core_regmap_disable,
+ .is_enabled = anatop_core_regmap_is_enabled,
.set_voltage_sel = anatop_regmap_core_set_voltage_sel,
.set_voltage_time_sel = anatop_regmap_set_voltage_time_sel,
.get_voltage_sel = anatop_regmap_core_get_voltage_sel,
@@ -194,6 +252,12 @@ static int anatop_regulator_probe(struct platform_device *pdev)
if (!sreg)
return -ENOMEM;
sreg->name = of_get_property(np, "regulator-name", NULL);
+
+ if (!sreg->name) {
+ dev_err(dev, "no regulator-name set\n");
+ return -EINVAL;
+ }
+
rdesc = &sreg->rdesc;
rdesc->name = sreg->name;
rdesc->type = REGULATOR_VOLTAGE;
@@ -203,6 +267,11 @@ static int anatop_regulator_probe(struct platform_device *pdev)
initdata->supply_regulator = "vin";
sreg->initdata = initdata;
+ if (strcmp(sreg->name, "vddpu") == 0)
+ vddpu = sreg;
+ else if (strcmp(sreg->name, "vddsoc") == 0)
+ vddsoc = sreg;
+
anatop_np = of_get_parent(np);
if (!anatop_np)
return -ENODEV;
@@ -256,6 +325,9 @@ static int anatop_regulator_probe(struct platform_device *pdev)
of_property_read_u32(np, "anatop-delay-bit-shift",
&sreg->delay_bit_shift);
+ /* Only 3p0, 2p5, and 1p1 has enable bit */
+ of_property_read_u32(np, "anatop-enable-bit", &sreg->enable_bit);
+
rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1
+ sreg->min_bit_val;
rdesc->min_uV = sreg->min_voltage;
@@ -264,7 +336,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
rdesc->vsel_reg = sreg->control_reg;
rdesc->vsel_mask = ((1 << sreg->vol_bit_width) - 1) <<
sreg->vol_bit_shift;
- rdesc->min_dropout_uV = 125000;
+ rdesc->min_dropout_uV = LDO_MIN_DROPOUT_UV;
config.dev = &pdev->dev;
config.init_data = initdata;
@@ -286,6 +358,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
if (sreg->sel == LDO_FET_FULL_ON) {
sreg->sel = 0;
sreg->bypass = true;
+ rdesc->min_dropout_uV = 0;
}
/*
@@ -296,6 +369,10 @@ static int anatop_regulator_probe(struct platform_device *pdev)
if (!sreg->sel && !strcmp(sreg->name, "vddpu"))
sreg->sel = 22;
+ /* set the default voltage of the pcie phy to be 1.100v */
+ if (!sreg->sel && !strcmp(sreg->name, "vddpcie-phy"))
+ sreg->sel = 0x10;
+
if (!sreg->bypass && !sreg->sel) {
dev_err(&pdev->dev, "Failed to read a valid default voltage selector.\n");
return -EINVAL;
@@ -307,9 +384,10 @@ static int anatop_regulator_probe(struct platform_device *pdev)
/* register regulator */
rdev = devm_regulator_register(dev, rdesc, &config);
if (IS_ERR(rdev)) {
- dev_err(dev, "failed to register %s\n",
- rdesc->name);
- return PTR_ERR(rdev);
+ ret = PTR_ERR(rdev);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to register %s\n", rdesc->name);
+ return ret;
}
platform_set_drvdata(pdev, rdev);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 9403245503de..df2fb57e9991 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2075,6 +2075,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
{
int ret, delay;
+ _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_DO_ENABLE, NULL);
/* Query before enabling in case configuration dependent. */
ret = _regulator_get_enable_time(rdev);
if (ret >= 0) {
@@ -2134,6 +2135,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
_regulator_enable_delay(delay);
trace_regulator_enable_complete(rdev_get_name(rdev));
+ _notifier_call_chain(rdev, REGULATOR_EVENT_AFT_DO_ENABLE, NULL);
return 0;
}
@@ -2213,6 +2215,7 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
{
int ret;
+ _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_DO_DISABLE, NULL);
trace_regulator_disable(rdev_get_name(rdev));
if (rdev->ena_pin) {
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 988a7472c2ab..136a9a3c7e30 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -30,6 +30,7 @@
#include <linux/of_gpio.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
+#include <linux/pinctrl/consumer.h>
struct fixed_voltage_data {
struct regulator_desc desc;
@@ -83,6 +84,7 @@ of_get_fixed_voltage_config(struct device *dev,
return ERR_PTR(config->gpio);
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+ of_property_read_u32(np, "off-on-delay", &config->off_on_delay);
config->enable_high = of_property_read_bool(np, "enable-active-high");
config->gpio_is_open_drain = of_property_read_bool(np,
@@ -133,6 +135,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->desc.ops = &fixed_voltage_ops;
drvdata->desc.enable_time = config->startup_delay;
+ drvdata->desc.off_on_delay = config->off_on_delay;
if (config->input_supply) {
drvdata->desc.supply_name = devm_kstrdup(&pdev->dev,
@@ -199,11 +202,32 @@ static const struct of_device_id fixed_of_match[] = {
MODULE_DEVICE_TABLE(of, fixed_of_match);
#endif
+#ifdef CONFIG_PM_SLEEP
+static int reg_fixed_voltage_suspend(struct device *dev)
+{
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+static int reg_fixed_voltage_resume(struct device *dev)
+{
+ pinctrl_pm_select_default_state(dev);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops reg_fixed_voltage_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(reg_fixed_voltage_suspend,
+ reg_fixed_voltage_resume)
+};
+
static struct platform_driver regulator_fixed_voltage_driver = {
.probe = reg_fixed_voltage_probe,
.driver = {
.name = "reg-fixed-voltage",
.of_match_table = of_match_ptr(fixed_of_match),
+ .pm = &reg_fixed_voltage_pm_ops,
},
};
diff --git a/drivers/regulator/max17135-regulator.c b/drivers/regulator/max17135-regulator.c
new file mode 100644
index 000000000000..90a2665c3d64
--- /dev/null
+++ b/drivers/regulator/max17135-regulator.c
@@ -0,0 +1,858 @@
+/*
+ * Copyright (C) 2010-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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/max17135.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+/*
+ * Regulator definitions
+ * *_MIN_uV - minimum microvolt for regulator
+ * *_MAX_uV - maximum microvolt for regulator
+ * *_STEP_uV - microvolts between regulator output levels
+ * *_MIN_VAL - minimum register field value for regulator
+ * *_MAX_VAL - maximum register field value for regulator
+ */
+#define MAX17135_HVINP_MIN_uV 5000000
+#define MAX17135_HVINP_MAX_uV 20000000
+#define MAX17135_HVINP_STEP_uV 1000000
+#define MAX17135_HVINP_MIN_VAL 0
+#define MAX17135_HVINP_MAX_VAL 12
+
+#define MAX17135_HVINN_MIN_uV 5000000
+#define MAX17135_HVINN_MAX_uV 20000000
+#define MAX17135_HVINN_STEP_uV 1000000
+#define MAX17135_HVINN_MIN_VAL 0
+#define MAX17135_HVINN_MAX_VAL 1
+
+#define MAX17135_GVDD_MIN_uV 5000000
+#define MAX17135_GVDD_MAX_uV 20000000
+#define MAX17135_GVDD_STEP_uV 1000000
+#define MAX17135_GVDD_MIN_VAL 0
+#define MAX17135_GVDD_MAX_VAL 1
+
+#define MAX17135_GVEE_MIN_uV 5000000
+#define MAX17135_GVEE_MAX_uV 20000000
+#define MAX17135_GVEE_STEP_uV 1000000
+#define MAX17135_GVEE_MIN_VAL 0
+#define MAX17135_GVEE_MAX_VAL 1
+
+#define MAX17135_VCOM_MIN_VAL 0
+#define MAX17135_VCOM_MAX_VAL 255
+
+#define MAX17135_VNEG_MIN_uV 5000000
+#define MAX17135_VNEG_MAX_uV 20000000
+#define MAX17135_VNEG_STEP_uV 1000000
+#define MAX17135_VNEG_MIN_VAL 0
+#define MAX17135_VNEG_MAX_VAL 1
+
+#define MAX17135_VPOS_MIN_uV 5000000
+#define MAX17135_VPOS_MAX_uV 20000000
+#define MAX17135_VPOS_STEP_uV 1000000
+#define MAX17135_VPOS_MIN_VAL 0
+#define MAX17135_VPOS_MAX_VAL 1
+
+struct max17135_vcom_programming_data {
+ int vcom_min_uV;
+ int vcom_max_uV;
+ int vcom_step_uV;
+};
+
+struct max17135_data {
+ int num_regulators;
+ struct max17135 *max17135;
+ struct regulator_dev **rdev;
+};
+
+static long unsigned int max17135_pass_num = { 1 };
+static int max17135_vcom = { -1250000 };
+
+struct max17135_vcom_programming_data vcom_data[2] = {
+ {
+ -4325000,
+ -500000,
+ 15000,
+ },
+ {
+ -3050000,
+ -500000,
+ 10000,
+ },
+};
+
+static int max17135_is_power_good(struct max17135 *max17135);
+
+/*
+ * Regulator operations
+ */
+static int max17135_hvinp_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV, unsigned *selector)
+{
+ unsigned int reg_val;
+ unsigned int fld_val;
+
+ if ((uV >= MAX17135_HVINP_MIN_uV) &&
+ (uV <= MAX17135_HVINP_MAX_uV))
+ fld_val = (uV - MAX17135_HVINP_MIN_uV) /
+ MAX17135_HVINP_STEP_uV;
+ else
+ return -EINVAL;
+
+ max17135_reg_read(REG_MAX17135_HVINP, &reg_val);
+
+ reg_val &= ~BITFMASK(HVINP);
+ reg_val |= BITFVAL(HVINP, fld_val); /* shift to correct bit */
+
+ return max17135_reg_write(REG_MAX17135_HVINP, reg_val);
+}
+
+static int max17135_hvinp_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int reg_val;
+ unsigned int fld_val;
+ int volt;
+
+ max17135_reg_read(REG_MAX17135_HVINP, &reg_val);
+
+ fld_val = (reg_val & BITFMASK(HVINP)) >> HVINP_LSH;
+
+ if ((fld_val >= MAX17135_HVINP_MIN_VAL) &&
+ (fld_val <= MAX17135_HVINP_MAX_VAL)) {
+ volt = (fld_val * MAX17135_HVINP_STEP_uV) +
+ MAX17135_HVINP_MIN_uV;
+ } else {
+ printk(KERN_ERR "MAX17135: HVINP voltage is out of range\n");
+ volt = 0;
+ }
+ return volt;
+}
+
+static int max17135_hvinp_enable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int max17135_hvinp_disable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+/* Convert uV to the VCOM register bitfield setting */
+static inline int vcom_uV_to_rs(int uV, int pass_num)
+{
+ return (vcom_data[pass_num].vcom_max_uV - uV)
+ / vcom_data[pass_num].vcom_step_uV;
+}
+
+/* Convert the VCOM register bitfield setting to uV */
+static inline int vcom_rs_to_uV(int rs, int pass_num)
+{
+ return vcom_data[pass_num].vcom_max_uV
+ - (vcom_data[pass_num].vcom_step_uV * rs);
+}
+
+/*
+ * This function should only be called with positive voltage values because
+ * negative ones are considered errors by the regulator core implementation.
+ *
+ * The given positive value if the absolute value of the desired negative one.
+ */
+static int max17135_vcom_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV, unsigned *selector)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+ unsigned int reg_val;
+ int vcom_read;
+
+ /* Transform uV for our negative land values */
+ uV = -uV;
+
+ if ((uV < vcom_data[max17135->pass_num-1].vcom_min_uV)
+ || (uV > vcom_data[max17135->pass_num-1].vcom_max_uV))
+ return -EINVAL;
+
+ max17135_reg_read(REG_MAX17135_DVR, &reg_val);
+
+ /*
+ * Only program VCOM if it is not set to the desired value.
+ * Programming VCOM excessively degrades ability to keep
+ * DVR register value persistent.
+ */
+ vcom_read = vcom_rs_to_uV(reg_val, max17135->pass_num-1);
+ if (vcom_read != max17135->vcom_uV) {
+ reg_val &= ~BITFMASK(DVR);
+ reg_val |= BITFVAL(DVR, vcom_uV_to_rs(uV,
+ max17135->pass_num-1));
+ max17135_reg_write(REG_MAX17135_DVR, reg_val);
+
+ reg_val = BITFVAL(CTRL_DVR, true); /* shift to correct bit */
+ return max17135_reg_write(REG_MAX17135_PRGM_CTRL, reg_val);
+ }
+
+ return 0;
+}
+
+/*
+ * This function should only return positive voltage values because negative
+ * ones are considered errors by the regulator core implementation.
+ */
+static int max17135_vcom_get_voltage(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+ unsigned int reg_val;
+ int uV;
+
+ max17135_reg_read(REG_MAX17135_DVR, &reg_val);
+ uV = vcom_rs_to_uV(BITFEXT(reg_val, DVR), max17135->pass_num-1);
+
+ /* Transform uV to positive value */
+ uV = -uV;
+
+ return uV;
+}
+
+static int max17135_vcom_enable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+ int uV;
+
+ /*
+ * Check to see if we need to set the VCOM voltage.
+ * Should only be done one time. And, we can
+ * only change vcom voltage if we have been enabled.
+ */
+ if (!max17135->vcom_setup && max17135_is_power_good(max17135)) {
+ uV = (-1) * max17135->vcom_uV;
+
+ max17135_vcom_set_voltage(reg, uV, uV, NULL);
+ max17135->vcom_setup = true;
+ }
+
+ /* enable VCOM regulator output */
+ if (max17135->pass_num == 1)
+ gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 1);
+ else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= ~BITFMASK(VCOM_ENABLE);
+ reg_val |= BITFVAL(VCOM_ENABLE, 1); /* shift to correct bit */
+ max17135_reg_write(REG_MAX17135_ENABLE, reg_val);
+ }
+
+ return 0;
+}
+
+static int max17135_vcom_disable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ if (max17135->pass_num == 1)
+ gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 0);
+ else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= ~BITFMASK(VCOM_ENABLE);
+ max17135_reg_write(REG_MAX17135_ENABLE, reg_val);
+ }
+
+ return 0;
+}
+
+static int max17135_vcom_is_enabled(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ /* read VCOM regulator enable setting */
+ if (max17135->pass_num == 1) {
+ int gpio = gpio_get_value(max17135->gpio_pmic_vcom_ctrl);
+ if (gpio == 0)
+ return 0;
+ else
+ return 1;
+ } else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= BITFMASK(VCOM_ENABLE);
+ if (reg_val != 0)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+static int max17135_is_power_good(struct max17135 *max17135)
+{
+ unsigned int reg_val;
+ unsigned int fld_val;
+
+ max17135_reg_read(REG_MAX17135_FAULT, &reg_val);
+ fld_val = (reg_val & BITFMASK(FAULT_POK)) >> FAULT_POK_LSH;
+
+ /* Check the POK bit */
+ return fld_val;
+}
+
+static int max17135_wait_power_good(struct max17135 *max17135)
+{
+ int i;
+
+ for (i = 0; i < max17135->max_wait * 3; i++) {
+ if (max17135_is_power_good(max17135))
+ return 0;
+
+ msleep(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int max17135_display_enable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ /* The Pass 1 parts cannot turn on the PMIC via I2C. */
+ if (max17135->pass_num == 1)
+ gpio_set_value(max17135->gpio_pmic_wakeup, 1);
+ else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= ~BITFMASK(ENABLE);
+ reg_val |= BITFVAL(ENABLE, 1);
+ max17135_reg_write(REG_MAX17135_ENABLE, reg_val);
+ }
+
+ return max17135_wait_power_good(max17135);
+}
+
+static int max17135_display_disable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ if (max17135->pass_num == 1)
+ gpio_set_value(max17135->gpio_pmic_wakeup, 0);
+ else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= ~BITFMASK(ENABLE);
+ max17135_reg_write(REG_MAX17135_ENABLE, reg_val);
+ }
+
+ msleep(max17135->max_wait);
+
+ return 0;
+}
+
+static int max17135_display_is_enabled(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+ int gpio = gpio_get_value(max17135->gpio_pmic_wakeup);
+
+ if (gpio == 0)
+ return 0;
+ else
+ return 1;
+}
+
+static int max17135_v3p3_enable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ gpio_set_value(max17135->gpio_pmic_v3p3, 1);
+ return 0;
+}
+
+static int max17135_v3p3_disable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ gpio_set_value(max17135->gpio_pmic_v3p3, 0);
+ return 0;
+}
+
+static int max17135_v3p3_is_enabled(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+ int gpio = gpio_get_value(max17135->gpio_pmic_v3p3);
+
+ if (gpio == 0)
+ return 0;
+ else
+ return 1;
+}
+
+/*
+ * Regulator operations
+ */
+
+static struct regulator_ops max17135_display_ops = {
+ .enable = max17135_display_enable,
+ .disable = max17135_display_disable,
+ .is_enabled = max17135_display_is_enabled,
+};
+
+static struct regulator_ops max17135_gvdd_ops = {
+};
+
+static struct regulator_ops max17135_gvee_ops = {
+};
+
+static struct regulator_ops max17135_hvinn_ops = {
+};
+
+static struct regulator_ops max17135_hvinp_ops = {
+ .enable = max17135_hvinp_enable,
+ .disable = max17135_hvinp_disable,
+ .get_voltage = max17135_hvinp_get_voltage,
+ .set_voltage = max17135_hvinp_set_voltage,
+};
+
+static struct regulator_ops max17135_vcom_ops = {
+ .enable = max17135_vcom_enable,
+ .disable = max17135_vcom_disable,
+ .get_voltage = max17135_vcom_get_voltage,
+ .set_voltage = max17135_vcom_set_voltage,
+ .is_enabled = max17135_vcom_is_enabled,
+};
+
+static struct regulator_ops max17135_vneg_ops = {
+};
+
+static struct regulator_ops max17135_vpos_ops = {
+};
+
+static struct regulator_ops max17135_v3p3_ops = {
+ .enable = max17135_v3p3_enable,
+ .disable = max17135_v3p3_disable,
+ .is_enabled = max17135_v3p3_is_enabled,
+};
+
+
+/*
+ * Regulator descriptors
+ */
+static struct regulator_desc max17135_reg[MAX17135_NUM_REGULATORS] = {
+{
+ .name = "DISPLAY",
+ .id = MAX17135_DISPLAY,
+ .ops = &max17135_display_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "GVDD",
+ .id = MAX17135_GVDD,
+ .ops = &max17135_gvdd_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "GVEE",
+ .id = MAX17135_GVEE,
+ .ops = &max17135_gvee_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "HVINN",
+ .id = MAX17135_HVINN,
+ .ops = &max17135_hvinn_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "HVINP",
+ .id = MAX17135_HVINP,
+ .ops = &max17135_hvinp_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "VCOM",
+ .id = MAX17135_VCOM,
+ .ops = &max17135_vcom_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "VNEG",
+ .id = MAX17135_VNEG,
+ .ops = &max17135_vneg_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "VPOS",
+ .id = MAX17135_VPOS,
+ .ops = &max17135_vpos_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "V3P3",
+ .id = MAX17135_V3P3,
+ .ops = &max17135_v3p3_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+};
+
+static void max17135_setup_timings(struct max17135 *max17135)
+{
+ unsigned int reg_val;
+
+ int timing1, timing2, timing3, timing4,
+ timing5, timing6, timing7, timing8;
+
+ max17135_reg_read(REG_MAX17135_TIMING1, &timing1);
+ max17135_reg_read(REG_MAX17135_TIMING2, &timing2);
+ max17135_reg_read(REG_MAX17135_TIMING3, &timing3);
+ max17135_reg_read(REG_MAX17135_TIMING4, &timing4);
+ max17135_reg_read(REG_MAX17135_TIMING5, &timing5);
+ max17135_reg_read(REG_MAX17135_TIMING6, &timing6);
+ max17135_reg_read(REG_MAX17135_TIMING7, &timing7);
+ max17135_reg_read(REG_MAX17135_TIMING8, &timing8);
+
+ if ((timing1 != max17135->gvee_pwrup) ||
+ (timing2 != max17135->vneg_pwrup) ||
+ (timing3 != max17135->vpos_pwrup) ||
+ (timing4 != max17135->gvdd_pwrup) ||
+ (timing5 != max17135->gvdd_pwrdn) ||
+ (timing6 != max17135->vpos_pwrdn) ||
+ (timing7 != max17135->vneg_pwrdn) ||
+ (timing8 != max17135->gvee_pwrdn)) {
+ max17135_reg_write(REG_MAX17135_TIMING1, max17135->gvee_pwrup);
+ max17135_reg_write(REG_MAX17135_TIMING2, max17135->vneg_pwrup);
+ max17135_reg_write(REG_MAX17135_TIMING3, max17135->vpos_pwrup);
+ max17135_reg_write(REG_MAX17135_TIMING4, max17135->gvdd_pwrup);
+ max17135_reg_write(REG_MAX17135_TIMING5, max17135->gvdd_pwrdn);
+ max17135_reg_write(REG_MAX17135_TIMING6, max17135->vpos_pwrdn);
+ max17135_reg_write(REG_MAX17135_TIMING7, max17135->vneg_pwrdn);
+ max17135_reg_write(REG_MAX17135_TIMING8, max17135->gvee_pwrdn);
+
+ reg_val = BITFVAL(CTRL_TIMING, true); /* shift to correct bit */
+ max17135_reg_write(REG_MAX17135_PRGM_CTRL, reg_val);
+ }
+}
+
+#define CHECK_PROPERTY_ERROR_KFREE(prop) \
+do { \
+ int ret = of_property_read_u32(max17135->dev->of_node, \
+ #prop, &max17135->prop); \
+ if (ret < 0) { \
+ return ret; \
+ } \
+} while (0);
+
+#ifdef CONFIG_OF
+static int max17135_pmic_dt_parse_pdata(struct platform_device *pdev,
+ struct max17135_platform_data *pdata)
+{
+ struct max17135 *max17135 = dev_get_drvdata(pdev->dev.parent);
+ struct device_node *pmic_np, *regulators_np, *reg_np;
+ struct max17135_regulator_data *rdata;
+ int i, ret;
+
+ pmic_np = of_node_get(max17135->dev->of_node);
+ if (!pmic_np) {
+ dev_err(&pdev->dev, "could not find pmic sub-node\n");
+ return -ENODEV;
+ }
+
+ regulators_np = of_find_node_by_name(pmic_np, "regulators");
+ if (!regulators_np) {
+ dev_err(&pdev->dev, "could not find regulators sub-node\n");
+ return -EINVAL;
+ }
+
+ pdata->num_regulators = of_get_child_count(regulators_np);
+ dev_dbg(&pdev->dev, "num_regulators %d\n", pdata->num_regulators);
+
+ rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
+ pdata->num_regulators, GFP_KERNEL);
+ if (!rdata) {
+ of_node_put(regulators_np);
+ dev_err(&pdev->dev, "could not allocate memory for"
+ "regulator data\n");
+ return -ENOMEM;
+ }
+
+ pdata->regulators = rdata;
+ for_each_child_of_node(regulators_np, reg_np) {
+ for (i = 0; i < ARRAY_SIZE(max17135_reg); i++)
+ if (!of_node_cmp(reg_np->name, max17135_reg[i].name))
+ break;
+
+ if (i == ARRAY_SIZE(max17135_reg)) {
+ dev_warn(&pdev->dev, "don't know how to configure"
+ "regulator %s\n", reg_np->name);
+ continue;
+ }
+
+ rdata->id = i;
+ rdata->initdata = of_get_regulator_init_data(&pdev->dev,
+ reg_np,
+ &max17135_reg[i]);
+ rdata->reg_node = reg_np;
+ rdata++;
+ }
+ of_node_put(regulators_np);
+
+ CHECK_PROPERTY_ERROR_KFREE(vneg_pwrup);
+ CHECK_PROPERTY_ERROR_KFREE(gvee_pwrup);
+ CHECK_PROPERTY_ERROR_KFREE(vpos_pwrup);
+ CHECK_PROPERTY_ERROR_KFREE(gvdd_pwrup);
+ CHECK_PROPERTY_ERROR_KFREE(gvdd_pwrdn);
+ CHECK_PROPERTY_ERROR_KFREE(vpos_pwrdn);
+ CHECK_PROPERTY_ERROR_KFREE(gvee_pwrdn);
+ CHECK_PROPERTY_ERROR_KFREE(vneg_pwrdn);
+
+ dev_dbg(&pdev->dev, "vneg_pwrup %d, vneg_pwrdn %d, vpos_pwrup %d,"
+ "vpos_pwrdn %d, gvdd_pwrup %d, gvdd_pwrdn %d, gvee_pwrup %d,"
+ "gvee_pwrdn %d\n", max17135->vneg_pwrup, max17135->vneg_pwrdn,
+ max17135->vpos_pwrup, max17135->vpos_pwrdn,
+ max17135->gvdd_pwrup, max17135->gvdd_pwrdn,
+ max17135->gvee_pwrup, max17135->gvee_pwrdn);
+
+ max17135->max_wait = max17135->vpos_pwrup + max17135->vneg_pwrup +
+ max17135->gvdd_pwrup + max17135->gvee_pwrup;
+
+ max17135->gpio_pmic_wakeup = of_get_named_gpio(pmic_np,
+ "gpio_pmic_wakeup", 0);
+ if (!gpio_is_valid(max17135->gpio_pmic_wakeup)) {
+ dev_err(&pdev->dev, "no epdc pmic wakeup pin available\n");
+ goto err;
+ }
+ ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_wakeup,
+ GPIOF_OUT_INIT_LOW, "epdc-pmic-wake");
+ if (ret < 0)
+ goto err;
+
+ max17135->gpio_pmic_vcom_ctrl = of_get_named_gpio(pmic_np,
+ "gpio_pmic_vcom_ctrl", 0);
+ if (!gpio_is_valid(max17135->gpio_pmic_vcom_ctrl)) {
+ dev_err(&pdev->dev, "no epdc pmic vcom_ctrl pin available\n");
+ goto err;
+ }
+ ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_vcom_ctrl,
+ GPIOF_OUT_INIT_LOW, "epdc-vcom");
+ if (ret < 0)
+ goto err;
+
+ max17135->gpio_pmic_v3p3 = of_get_named_gpio(pmic_np,
+ "gpio_pmic_v3p3", 0);
+ if (!gpio_is_valid(max17135->gpio_pmic_v3p3)) {
+ dev_err(&pdev->dev, "no epdc pmic v3p3 pin available\n");
+ goto err;
+ }
+ ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_v3p3,
+ GPIOF_OUT_INIT_LOW, "epdc-v3p3");
+ if (ret < 0)
+ goto err;
+
+ max17135->gpio_pmic_intr = of_get_named_gpio(pmic_np,
+ "gpio_pmic_intr", 0);
+ if (!gpio_is_valid(max17135->gpio_pmic_intr)) {
+ dev_err(&pdev->dev, "no epdc pmic intr pin available\n");
+ goto err;
+ }
+ ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_intr,
+ GPIOF_IN, "epdc-pmic-int");
+ if (ret < 0)
+ goto err;
+
+ max17135->gpio_pmic_pwrgood = of_get_named_gpio(pmic_np,
+ "gpio_pmic_pwrgood", 0);
+ if (!gpio_is_valid(max17135->gpio_pmic_pwrgood)) {
+ dev_err(&pdev->dev, "no epdc pmic pwrgood pin available\n");
+ goto err;
+ }
+ ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_pwrgood,
+ GPIOF_IN, "epdc-pwrstat");
+ if (ret < 0)
+ goto err;
+
+err:
+ return 0;
+
+}
+#else
+static int max17135_pmic_dt_parse_pdata(struct platform_device *pdev,
+ struct max17135 *max17135)
+{
+ return 0;
+}
+#endif /* !CONFIG_OF */
+
+/*
+ * Regulator init/probing/exit functions
+ */
+static int max17135_regulator_probe(struct platform_device *pdev)
+{
+ struct max17135 *max17135 = dev_get_drvdata(pdev->dev.parent);
+ struct max17135_platform_data *pdata = max17135->pdata;
+ struct max17135_data *priv;
+ struct regulator_dev **rdev;
+ struct regulator_config config = { };
+ int size, i, ret = 0;
+
+ if (max17135->dev->of_node) {
+ ret = max17135_pmic_dt_parse_pdata(pdev, pdata);
+ if (ret)
+ return ret;
+ }
+ priv = devm_kzalloc(&pdev->dev, sizeof(struct max17135_data),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ size = sizeof(struct regulator_dev *) * pdata->num_regulators;
+ priv->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (!priv->rdev)
+ return -ENOMEM;
+
+ rdev = priv->rdev;
+ priv->num_regulators = pdata->num_regulators;
+ platform_set_drvdata(pdev, priv);
+
+ max17135->vcom_setup = false;
+ max17135->pass_num = max17135_pass_num;
+ max17135->vcom_uV = max17135_vcom;
+
+ for (i = 0; i < pdata->num_regulators; i++) {
+ int id = pdata->regulators[i].id;
+
+ config.dev = max17135->dev;
+ config.init_data = pdata->regulators[i].initdata;
+ config.driver_data = max17135;
+ config.of_node = pdata->regulators[i].reg_node;
+
+ rdev[i] = regulator_register(&max17135_reg[id], &config);
+ if (IS_ERR(rdev[i])) {
+ ret = PTR_ERR(rdev[i]);
+ dev_err(&pdev->dev, "regulator init failed for %d\n",
+ id);
+ rdev[i] = NULL;
+ goto err;
+ }
+ }
+
+ /*
+ * Set up PMIC timing values.
+ * Should only be done one time! Timing values may only be
+ * changed a limited number of times according to spec.
+ */
+ max17135_setup_timings(max17135);
+
+ return 0;
+err:
+ while (--i >= 0)
+ regulator_unregister(rdev[i]);
+ return ret;
+}
+
+static int max17135_regulator_remove(struct platform_device *pdev)
+{
+ struct max17135_data *priv = platform_get_drvdata(pdev);
+ struct regulator_dev **rdev = priv->rdev;
+ int i;
+
+ for (i = 0; i < priv->num_regulators; i++)
+ regulator_unregister(rdev[i]);
+ return 0;
+}
+
+static const struct platform_device_id max17135_pmic_id[] = {
+ { "max17135-pmic", 0},
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, max17135_pmic_id);
+
+static struct platform_driver max17135_regulator_driver = {
+ .probe = max17135_regulator_probe,
+ .remove = max17135_regulator_remove,
+ .id_table = max17135_pmic_id,
+ .driver = {
+ .name = "max17135-pmic",
+ },
+};
+
+static int __init max17135_regulator_init(void)
+{
+ return platform_driver_register(&max17135_regulator_driver);
+}
+subsys_initcall_sync(max17135_regulator_init);
+
+static void __exit max17135_regulator_exit(void)
+{
+ platform_driver_unregister(&max17135_regulator_driver);
+}
+module_exit(max17135_regulator_exit);
+
+/*
+ * Parse user specified options (`max17135:')
+ * example:
+ * max17135:pass=2,vcom=-1250000
+ */
+static int __init max17135_setup(char *options)
+{
+ int ret;
+ char *opt;
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+ if (!strncmp(opt, "pass=", 5)) {
+ ret = kstrtoul(opt + 5, 0, &max17135_pass_num);
+ if (ret < 0)
+ return ret;
+ }
+ if (!strncmp(opt, "vcom=", 5)) {
+ int offs = 5;
+ if (opt[5] == '-')
+ offs = 6;
+ ret = kstrtoul(opt + offs, 0,
+ (long *)&max17135_vcom);
+ if (ret < 0)
+ return ret;
+ max17135_vcom = -max17135_vcom;
+ }
+ }
+
+ return 1;
+}
+
+__setup("max17135:", max17135_setup);
+
+/* Module information */
+MODULE_DESCRIPTION("MAX17135 regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/pf1550-regulator-rpmsg.c b/drivers/regulator/pf1550-regulator-rpmsg.c
new file mode 100644
index 000000000000..11a893373390
--- /dev/null
+++ b/drivers/regulator/pf1550-regulator-rpmsg.c
@@ -0,0 +1,512 @@
+/*
+ * pf1550.c - regulator driver for the PF1550
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright (C) 2017 NXP.
+ * Robin Gong <yibin.gong@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
+#include <linux/rpmsg.h>
+#include <linux/uaccess.h>
+#include <linux/virtio.h>
+
+#define PF1550_DBGFS
+#define PF1550_MAX_REGULATOR 7
+#define RPMSG_TIMEOUT 1000
+
+enum pf1550_regs {
+ PF1550_SW1,
+ PF1550_SW2,
+ PF1550_SW3,
+ PF1550_VREFDDR,
+ PF1550_LDO1,
+ PF1550_LDO2,
+ PF1550_LDO3,
+};
+
+enum pf1550_rpmsg_cmd {
+ PF1550_ENABLE,
+ PF1550_DISABLE,
+ PF1550_IS_ENABLED,
+ PF1550_SET_VOL,
+ PF1550_GET_VOL,
+ PF1550_GET_REG,
+ PF1550_SET_REG,
+};
+
+enum pf1550_resp {
+ PF1550_SUCCESS,
+ PF1550_FAILED,
+ PF1550_UNSURPPORT,
+};
+
+enum pf1550_status {
+ PF1550_DISABLED,
+ PF1550_ENABLED,
+};
+
+struct pf1550_regulator_info {
+ struct rpmsg_device *rpdev;
+ struct device *dev;
+ struct pf1550_regulator_rpmsg *msg;
+ struct completion cmd_complete;
+ struct pm_qos_request pm_qos_req;
+ struct mutex lock;
+ struct regulator_desc *regulators;
+};
+
+static struct pf1550_regulator_info pf1550_info;
+
+struct pf1550_regulator_rpmsg {
+ /* common head */
+ struct imx_rpmsg_head header;
+ /* pmic structure */
+ union {
+ u8 regulator;
+ u8 reg;
+ };
+ u8 response;
+ u8 status;
+ union {
+ u32 voltage; /* uV */
+ u32 val;
+ };
+} __attribute__ ((packed));
+
+static int pf1550_send_message(struct pf1550_regulator_rpmsg *msg,
+ struct pf1550_regulator_info *info)
+{
+ 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);
+
+ msg->header.cate = IMX_RPMSG_PMIC;
+ msg->header.major = IMX_RMPSG_MAJOR;
+ msg->header.minor = IMX_RMPSG_MINOR;
+ msg->header.type = 0;
+
+ /* wait response from rpmsg */
+ reinit_completion(&info->cmd_complete);
+
+ err = rpmsg_send(info->rpdev->ept, (void *)msg,
+ sizeof(struct pf1550_regulator_rpmsg));
+ if (err) {
+ dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err);
+ goto err_out;
+ }
+ 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;
+ }
+
+ err = 0;
+
+err_out:
+ pm_qos_remove_request(&info->pm_qos_req);
+ mutex_unlock(&info->lock);
+
+ dev_dbg(&info->rpdev->dev, "cmd:%d, reg:%d, resp:%d.\n",
+ msg->header.cmd, msg->regulator, msg->response);
+
+ return err;
+}
+
+static int pf1550_enable(struct regulator_dev *reg)
+{
+ struct pf1550_regulator_info *info = rdev_get_drvdata(reg);
+ struct pf1550_regulator_rpmsg msg;
+
+ msg.header.cmd = PF1550_ENABLE;
+ msg.regulator = reg->desc->id;
+
+ return pf1550_send_message(&msg, info);
+}
+
+static int pf1550_disable(struct regulator_dev *reg)
+{
+ struct pf1550_regulator_info *info = rdev_get_drvdata(reg);
+ struct pf1550_regulator_rpmsg msg;
+
+ msg.header.cmd = PF1550_DISABLE;
+ msg.regulator = reg->desc->id;
+
+ return pf1550_send_message(&msg, info);
+}
+
+static int pf1550_is_enabled(struct regulator_dev *reg)
+{
+ struct pf1550_regulator_info *info = rdev_get_drvdata(reg);
+ struct pf1550_regulator_rpmsg msg;
+ int err;
+
+ msg.header.cmd = PF1550_IS_ENABLED;
+ msg.regulator = reg->desc->id;
+
+ err = pf1550_send_message(&msg, info);
+ if (err)
+ return err;
+ /* Here SUCCESS means ENABLED */
+ if (info->msg->status == PF1550_ENABLED)
+ return 1;
+ else
+ return 0;
+}
+
+static int pf1550_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV, unsigned *selector)
+{
+ struct pf1550_regulator_info *info = rdev_get_drvdata(reg);
+ struct pf1550_regulator_rpmsg msg;
+ int err;
+
+ msg.header.cmd = PF1550_SET_VOL;
+ msg.regulator = reg->desc->id;
+ msg.voltage = minuV;
+
+ err = pf1550_send_message(&msg, info);
+ if (err)
+ return err;
+
+ if (info->msg->response == PF1550_UNSURPPORT) {
+ dev_err(info->dev, "Voltages not allowed to set to %d!\n", uV);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int pf1550_get_voltage(struct regulator_dev *reg)
+{
+ struct pf1550_regulator_info *info = rdev_get_drvdata(reg);
+ struct pf1550_regulator_rpmsg msg;
+ int err;
+
+ msg.header.cmd = PF1550_GET_VOL;
+ msg.regulator = reg->desc->id;
+ msg.voltage = 0;
+
+ err = pf1550_send_message(&msg, info);
+ if (err)
+ return err;
+
+ return info->msg->voltage;
+}
+
+/* return the fix voltage */
+static int pf1550_get_fix_voltage(struct regulator_dev *dev)
+{
+ return dev->desc->fixed_uV;
+}
+
+static struct regulator_ops pf1550_sw_ops = {
+ .set_voltage = pf1550_set_voltage,
+ .get_voltage = pf1550_get_voltage,
+};
+
+static struct regulator_ops pf1550_ldo_ops = {
+ .enable = pf1550_enable,
+ .disable = pf1550_disable,
+ .is_enabled = pf1550_is_enabled,
+ .set_voltage = pf1550_set_voltage,
+ .get_voltage = pf1550_get_voltage,
+};
+
+static struct regulator_ops pf1550_fixed_ops = {
+ .enable = pf1550_enable,
+ .disable = pf1550_disable,
+ .get_voltage = pf1550_get_fix_voltage,
+ .is_enabled = pf1550_is_enabled,
+};
+
+static struct regulator_desc pf1550_regulators[PF1550_MAX_REGULATOR] = {
+{
+ .name = "SW1",
+ .of_match = of_match_ptr("SW1"),
+ .id = PF1550_SW1,
+ .ops = &pf1550_sw_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "SW2",
+ .of_match = of_match_ptr("SW2"),
+ .id = PF1550_SW2,
+ .ops = &pf1550_sw_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "SW3",
+ .of_match = of_match_ptr("SW3"),
+ .id = PF1550_SW3,
+ .ops = &pf1550_sw_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "VREFDDR",
+ .of_match = of_match_ptr("VREFDDR"),
+ .id = PF1550_VREFDDR,
+ .ops = &pf1550_fixed_ops,
+ .type = REGULATOR_VOLTAGE,
+ .fixed_uV = 1200000,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "LDO1",
+ .of_match = of_match_ptr("LDO1"),
+ .id = PF1550_LDO1,
+ .ops = &pf1550_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "LDO2",
+ .of_match = of_match_ptr("LDO2"),
+ .id = PF1550_LDO2,
+ .ops = &pf1550_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "LDO3",
+ .of_match = of_match_ptr("LDO3"),
+ .id = PF1550_LDO3,
+ .ops = &pf1550_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+};
+
+
+static int rpmsg_regulator_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+ struct pf1550_regulator_rpmsg *msg = (struct pf1550_regulator_rpmsg *)data;
+
+
+ dev_dbg(&rpdev->dev, "get from%d: cmd:%d, reg:%d, resp:%d.\n",
+ src, msg->header.cmd, msg->regulator, msg->response);
+
+ pf1550_info.msg = msg;
+
+ complete(&pf1550_info.cmd_complete);
+
+ return 0;
+}
+
+static int rpmsg_regulator_probe(struct rpmsg_device *rpdev)
+{
+ pf1550_info.rpdev = rpdev;
+
+ init_completion(&pf1550_info.cmd_complete);
+ mutex_init(&pf1550_info.lock);
+
+ dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+ rpdev->src, rpdev->dst);
+ return 0;
+}
+
+static void rpmsg_regulator_remove(struct rpmsg_device *rpdev)
+{
+ dev_info(&rpdev->dev, "rpmsg regulator driver is removed\n");
+}
+
+static struct rpmsg_device_id rpmsg_regulator_id_table[] = {
+ { .name = "rpmsg-regulator-channel" },
+ { },
+};
+
+static struct rpmsg_driver rpmsg_regulator_driver = {
+ .drv.name = "regulator_rpmsg",
+ .drv.owner = THIS_MODULE,
+ .id_table = rpmsg_regulator_id_table,
+ .probe = rpmsg_regulator_probe,
+ .callback = rpmsg_regulator_cb,
+ .remove = rpmsg_regulator_remove,
+};
+
+#ifdef PF1550_DBGFS
+#define MAX_REGS 0xff
+
+/*
+ * Alligned the below two functions as the same as regmap_map_read_file
+ * and regmap_map_write_file in regmap-debugfs.c
+ */
+static ssize_t pf1550_registers_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int i;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pf1550_regulator_info *info = platform_get_drvdata(pdev);
+ struct pf1550_regulator_rpmsg msg;
+ int err;
+ size_t bufpos = 0, count = MAX_REGS * 7;
+
+ for (i = 0; i < MAX_REGS; i++) {
+ snprintf(buf + bufpos, count - bufpos, "%.*x: ", 2, i);
+ bufpos += 4;
+
+ msg.header.cmd = PF1550_GET_REG;
+ msg.reg = i;
+ msg.val = 0;
+
+ err = pf1550_send_message(&msg, info);
+ if (err)
+ return err;
+
+ if (info->msg->response != PF1550_SUCCESS) {
+ dev_err(info->dev, "Get register failed %x, resp=%x!\n",
+ i, info->msg->response);
+ return -EINVAL;
+ }
+
+ snprintf(buf + bufpos, count - bufpos, "%.*x\n", 2,
+ info->msg->val);
+ bufpos += 2;
+
+ buf[bufpos++] = '\n';
+ }
+
+ return bufpos;
+}
+
+static ssize_t pf1550_register_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pf1550_regulator_info *info = platform_get_drvdata(pdev);
+ struct pf1550_regulator_rpmsg msg;
+ char *start = (char *)buf;
+ unsigned long reg, value;
+ int err;
+
+ while (*start == ' ')
+ start++;
+ reg = simple_strtoul(start, &start, 16);
+
+ while (*start == ' ')
+ start++;
+ if (kstrtoul(start, 16, &value))
+ return -EINVAL;
+
+ msg.header.cmd = PF1550_SET_REG;
+ msg.reg = reg;
+ msg.val = value;
+
+ err = pf1550_send_message(&msg, info);
+ if (err)
+ return err;
+
+ if (info->msg->response != PF1550_SUCCESS) {
+ dev_err(info->dev, "set register failed %lx!\n", reg);
+ return -EINVAL;
+ }
+
+ return size;
+}
+
+static DEVICE_ATTR(regs, 0644, pf1550_registers_show, pf1550_register_store);
+#endif
+
+static int pf1550_regulator_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int i;
+ struct regulator_config config = { };
+
+ if (!np)
+ return -ENODEV;
+
+ config.dev = &pdev->dev;
+ config.driver_data = &pf1550_info;
+ pf1550_info.dev = &pdev->dev;
+ pf1550_info.regulators = pf1550_regulators;
+
+ for (i = 0; i < ARRAY_SIZE(pf1550_regulators); i++) {
+ struct regulator_dev *rdev;
+ struct regulator_desc *desc;
+
+ desc = &pf1550_info.regulators[i];
+ rdev = devm_regulator_register(&pdev->dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "Failed to initialize regulator-%d\n", i);
+ return PTR_ERR(rdev);
+ }
+ }
+
+#ifdef PF1550_DBGFS
+ i = sysfs_create_file(&config.dev->kobj, &dev_attr_regs.attr);
+ if (i) {
+ dev_err(&pdev->dev, "Failed to create pf1550 debug sysfs.\n");
+ return i;
+ }
+#endif
+
+ platform_set_drvdata(pdev, &pf1550_info);
+
+ return 0;
+}
+
+static const struct of_device_id pf1550_regulator_id[] = {
+ {"fsl,pf1550-rpmsg",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, pf1550_regulator_id);
+
+static struct platform_driver pf1550_regulator_driver = {
+ .driver = {
+ .name = "pf1550-rpmsg",
+ .owner = THIS_MODULE,
+ .of_match_table = pf1550_regulator_id,
+ },
+ .probe = pf1550_regulator_probe,
+};
+
+static int __init pf1550_rpmsg_init(void)
+{
+ return register_rpmsg_driver(&rpmsg_regulator_driver);
+}
+
+module_platform_driver(pf1550_regulator_driver);
+module_init(pf1550_rpmsg_init);
+
+MODULE_DESCRIPTION("Freescale PF1550 regulator rpmsg driver");
+MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/pf1550.c b/drivers/regulator/pf1550.c
new file mode 100644
index 000000000000..f6837052859b
--- /dev/null
+++ b/drivers/regulator/pf1550.c
@@ -0,0 +1,390 @@
+/*
+ * pf1550.c - regulator driver for the PF1550
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Robin Gong <yibin.gong@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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.
+ *
+ * This driver is based on pfuze100-regulator.c
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/mfd/pf1550.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
+#include <linux/platform_device.h>
+
+#define PF1550_MAX_REGULATOR 7
+
+struct pf1550_desc {
+ struct regulator_desc desc;
+ unsigned char stby_reg;
+ unsigned char stby_mask;
+};
+
+struct pf1550_regulator_info {
+ struct device *dev;
+ struct pf1550_dev *pf1550;
+ struct pf1550_desc regulator_descs[PF1550_MAX_REGULATOR];
+ int irq;
+};
+
+static struct pf1550_irq_info pf1550_regulator_irqs[] = {
+ { PF1550_PMIC_IRQ_SW1_LS, "sw1-lowside" },
+ { PF1550_PMIC_IRQ_SW2_LS, "sw2-lowside" },
+ { PF1550_PMIC_IRQ_SW3_LS, "sw3-lowside" },
+
+ { PF1550_PMIC_IRQ_SW1_HS, "sw1-highside" },
+ { PF1550_PMIC_IRQ_SW2_HS, "sw2-highside" },
+ { PF1550_PMIC_IRQ_SW3_HS, "sw3-highside" },
+
+ { PF1550_PMIC_IRQ_LDO1_FAULT, "ldo1-fault" },
+ { PF1550_PMIC_IRQ_LDO2_FAULT, "ldo2-fault" },
+ { PF1550_PMIC_IRQ_LDO3_FAULT, "ldo3-fault" },
+
+ { PF1550_PMIC_IRQ_TEMP_110, "temp-110" },
+ { PF1550_PMIC_IRQ_TEMP_125, "temp-125" },
+};
+
+static const int pf1550_sw12_volts[] = {
+ 1100000, 1200000, 1350000, 1500000, 1800000, 2500000, 3000000, 3300000,
+};
+
+static const int pf1550_ldo13_volts[] = {
+ 750000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
+ 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+ 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+ 2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
+};
+
+static int pf1550_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ int id = rdev_get_id(rdev);
+ unsigned int ramp_bits;
+ int ret;
+
+ if (id < PF1550_VREFDDR) {
+ ramp_delay = 6250 / ramp_delay;
+ ramp_bits = ramp_delay >> 1;
+ ret = regmap_update_bits(rdev->regmap,
+ rdev->desc->vsel_reg + 4,
+ 0x10, ramp_bits << 4);
+ if (ret < 0)
+ dev_err(&rdev->dev, "ramp failed, err %d\n", ret);
+ } else
+ ret = -EACCES;
+
+ return ret;
+}
+
+static struct regulator_ops pf1550_sw1_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_ramp_delay = pf1550_set_ramp_delay,
+};
+
+static struct regulator_ops pf1550_sw2_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_ramp_delay = pf1550_set_ramp_delay,
+};
+
+static struct regulator_ops pf1550_ldo1_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static struct regulator_ops pf1550_ldo2_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static struct regulator_ops pf1550_fixed_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+};
+
+#define PF_VREF(_chip, _name, voltage) { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = 1, \
+ .ops = &pf1550_fixed_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = _chip ## _ ## _name, \
+ .owner = THIS_MODULE, \
+ .min_uV = (voltage), \
+ .enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
+ .enable_mask = 0x1, \
+ }, \
+ .stby_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
+ .stby_mask = 0x2, \
+}
+
+#define PF_SW1(_chip, _name, mask, voltages) { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = ARRAY_SIZE(voltages), \
+ .ops = &pf1550_sw1_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = _chip ## _ ## _name, \
+ .owner = THIS_MODULE, \
+ .volt_table = voltages, \
+ .vsel_reg = _chip ## _PMIC_REG_ ## _name ## _VOLT, \
+ .vsel_mask = (mask), \
+ }, \
+ .stby_reg = _chip ## _PMIC_REG_ ## _name ## _STBY_VOLT, \
+ .stby_mask = (mask), \
+}
+
+#define PF_SW3(_chip, _name, min, max, mask, step) { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .ops = &pf1550_sw2_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = _chip ## _ ## _name, \
+ .owner = THIS_MODULE, \
+ .min_uV = (min), \
+ .uV_step = (step), \
+ .vsel_reg = _chip ## _PMIC_REG_ ## _name ## _VOLT, \
+ .vsel_mask = (mask), \
+ }, \
+ .stby_reg = _chip ## _PMIC_REG_ ## _name ## _STBY_VOLT, \
+ .stby_mask = (mask), \
+}
+
+#define PF_LDO1(_chip, _name, mask, voltages) { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = ARRAY_SIZE(voltages), \
+ .ops = &pf1550_ldo1_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = _chip ## _ ## _name, \
+ .owner = THIS_MODULE, \
+ .volt_table = voltages, \
+ .vsel_reg = _chip ## _PMIC_REG_ ## _name ## _VOLT, \
+ .vsel_mask = (mask), \
+ .enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
+ .enable_mask = 0x1, \
+ }, \
+ .stby_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
+ .stby_mask = 0x2, \
+}
+
+#define PF_LDO2(_chip, _name, mask, min, max, step) { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .ops = &pf1550_ldo2_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = _chip ## _ ## _name, \
+ .owner = THIS_MODULE, \
+ .min_uV = (min), \
+ .uV_step = (step), \
+ .vsel_reg = _chip ## _PMIC_REG_ ## _name ## _VOLT, \
+ .vsel_mask = (mask), \
+ .enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
+ .enable_mask = 0x1, \
+ }, \
+ .stby_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
+ .stby_mask = 0x2, \
+}
+
+static struct pf1550_desc pf1550_regulators[] = {
+ PF_SW3(PF1550, SW1, 600000, 1387500, 0x3f, 12500),
+ PF_SW3(PF1550, SW2, 600000, 1387500, 0x3f, 12500),
+ PF_SW3(PF1550, SW3, 1800000, 3300000, 0xf, 100000),
+ PF_VREF(PF1550, VREFDDR, 1200000),
+ PF_LDO1(PF1550, LDO1, 0x1f, pf1550_ldo13_volts),
+ PF_LDO2(PF1550, LDO2, 0xf, 1800000, 3300000, 100000),
+ PF_LDO1(PF1550, LDO3, 0x1f, pf1550_ldo13_volts),
+};
+
+static irqreturn_t pf1550_regulator_irq_handler(int irq, void *data)
+{
+ struct pf1550_regulator_info *info = data;
+ int i, irq_type = -1;
+
+ info->irq = irq;
+
+ for (i = 0; i < ARRAY_SIZE(pf1550_regulator_irqs); i++)
+ if (info->irq == pf1550_regulator_irqs[i].virq)
+ irq_type = pf1550_regulator_irqs[i].irq;
+
+ switch (irq_type) {
+ case PF1550_PMIC_IRQ_SW1_LS:
+ case PF1550_PMIC_IRQ_SW2_LS:
+ case PF1550_PMIC_IRQ_SW3_LS:
+ dev_info(info->dev, "lowside interrupt trigged! irq_type=%d\n",
+ irq_type);
+ break;
+ case PF1550_PMIC_IRQ_SW1_HS:
+ case PF1550_PMIC_IRQ_SW2_HS:
+ case PF1550_PMIC_IRQ_SW3_HS:
+ dev_info(info->dev, "highside interrupt triggered! irq_type=%d\n",
+ irq_type);
+ break;
+ case PF1550_PMIC_IRQ_LDO1_FAULT:
+ case PF1550_PMIC_IRQ_LDO2_FAULT:
+ case PF1550_PMIC_IRQ_LDO3_FAULT:
+ dev_info(info->dev, "ldo fault triggered! irq_type=%d\n",
+ irq_type);
+ break;
+ case PF1550_PMIC_IRQ_TEMP_110:
+ case PF1550_PMIC_IRQ_TEMP_125:
+ dev_info(info->dev, "thermal exception triggered! irq_type=%d\n",
+ irq_type);
+ break;
+ default:
+ dev_err(info->dev, "regulator interrupt: irq %d occurred\n",
+ irq_type);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int pf1550_regulator_probe(struct platform_device *pdev)
+{
+ struct pf1550_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct device_node *np = pdev->dev.of_node;
+ struct pf1550_regulator_info *info;
+ int i, ret = 0;
+ struct regulator_config config = { };
+
+ if (!np)
+ return -ENODEV;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(struct pf1550_regulator_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ config.dev = iodev->dev;
+ config.regmap = iodev->regmap;
+ info->dev = &pdev->dev;
+ info->pf1550 = iodev;
+
+ memcpy(info->regulator_descs, pf1550_regulators,
+ sizeof(info->regulator_descs));
+
+ for (i = 0; i < ARRAY_SIZE(pf1550_regulators); i++) {
+ struct regulator_dev *rdev;
+ struct regulator_desc *desc;
+ unsigned int val;
+
+ desc = &info->regulator_descs[i].desc;
+
+ if (desc->id == PF1550_SW2) {
+ pf1550_read_otp(info->pf1550, 0x1f, &val);
+ /* OTP_SW2_DVS_ENB == 1? */
+ if ((val & 0x8)) {
+ desc->volt_table = pf1550_sw12_volts;
+ desc->n_voltages = ARRAY_SIZE(pf1550_sw12_volts);
+ desc->ops = &pf1550_sw1_ops;
+ }
+ }
+
+ rdev = devm_regulator_register(&pdev->dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "Failed to initialize regulator-%d\n", i);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ platform_set_drvdata(pdev, info);
+
+ for (i = 0; i < ARRAY_SIZE(pf1550_regulator_irqs); i++) {
+ struct pf1550_irq_info *regulator_irq =
+ &pf1550_regulator_irqs[i];
+ unsigned int virq = 0;
+
+ virq = regmap_irq_get_virq(iodev->irq_data_regulator,
+ regulator_irq->irq);
+
+ if (!virq)
+ return -EINVAL;
+ regulator_irq->virq = virq;
+
+ ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
+ pf1550_regulator_irq_handler,
+ IRQF_NO_SUSPEND,
+ regulator_irq->name, info);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed: irq request (IRQ: %d, error :%d)\n",
+ regulator_irq->irq, ret);
+ return ret;
+ }
+ }
+
+ /* unmask all exception interrupts for regulators */
+ regmap_write(info->pf1550->regmap, PF1550_PMIC_REG_SW_INT_MASK0, 0);
+ regmap_write(info->pf1550->regmap, PF1550_PMIC_REG_SW_INT_MASK1, 0);
+ regmap_write(info->pf1550->regmap, PF1550_PMIC_REG_LDO_INT_MASK0, 0);
+ regmap_write(info->pf1550->regmap, PF1550_PMIC_REG_TEMP_INT_MASK0, 0);
+
+ return 0;
+}
+
+static const struct platform_device_id pf1550_regulator_id[] = {
+ {"pf1550-regulator", PF1550},
+ {},
+};
+
+MODULE_DEVICE_TABLE(platform, pf1550_regulator_id);
+
+static struct platform_driver pf1550_regulator_driver = {
+ .driver = {
+ .name = "pf1550-regulator",
+ },
+ .probe = pf1550_regulator_probe,
+ .id_table = pf1550_regulator_id,
+};
+
+module_platform_driver(pf1550_regulator_driver);
+
+MODULE_DESCRIPTION("Freescale PF1550 regulator driver");
+MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
index cb18b5c4f2db..4a655c2f5a57 100644
--- a/drivers/regulator/pfuze100-regulator.c
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -35,6 +35,15 @@
#define PFUZE100_STANDBY_OFFSET 1
#define PFUZE100_MODE_OFFSET 3
#define PFUZE100_CONF_OFFSET 4
+/*
+ * below regs will lost after exit from LPSR mode(PFUZE3000), need to be saved
+ * and restored:
+ * 0x20~0x40: 33
+ * 0x66~0x71: 12
+ * 0x7f: 1
+ * total 46 registers.
+ */
+#define PFUZE100_REG_SAVED_NUM (33 + 12 + 1)
#define PFUZE100_DEVICEID 0x0
#define PFUZE100_REVID 0x3
@@ -68,6 +77,8 @@ struct pfuze_chip {
int chip_id;
struct regmap *regmap;
struct device *dev;
+ bool need_restore;
+ unsigned int reg_save_array[PFUZE100_REG_SAVED_NUM];
struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR];
struct regulator_dev *regulators[PFUZE100_MAX_REGULATOR];
struct pfuze_regulator *pfuze_regulators;
@@ -81,6 +92,13 @@ static const int pfuze100_vsnvs[] = {
1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000,
};
+static const int pfuze3000_sw1a[] = {
+ 700000, 725000, 750000, 775000, 800000, 825000, 850000, 875000,
+ 900000, 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000,
+ 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000,
+ 1300000, 1325000, 1350000, 1375000, 1400000, 1425000, 1800000, 3300000,
+};
+
static const int pfuze3000_sw2lo[] = {
1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000,
};
@@ -153,6 +171,7 @@ static struct regulator_ops pfuze100_sw_regulator_ops = {
static struct regulator_ops pfuze100_swb_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -320,7 +339,7 @@ static struct pfuze_regulator pfuze200_regulators[] = {
};
static struct pfuze_regulator pfuze3000_regulators[] = {
- PFUZE100_SW_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 700000, 1475000, 25000),
+ PFUZE100_SWB_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
PFUZE100_SW_REG(PFUZE3000, SW1B, PFUZE100_SW1CVOL, 700000, 1475000, 25000),
PFUZE100_SWB_REG(PFUZE3000, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
PFUZE3000_SW3_REG(PFUZE3000, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000),
@@ -635,14 +654,95 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
}
}
+
+ if (of_get_property(client->dev.of_node, "fsl,lpsr-mode", NULL))
+ pfuze_chip->need_restore = true;
+
+ return 0;
+}
+
+static int pfuze_reg_save_restore(struct pfuze_chip *pfuze_chip, int start,
+ int end, int index, bool save)
+{
+ int i, ret;
+
+ for (i = 0; i < end - start + 1; i++) {
+ if (save)
+ ret = regmap_read(pfuze_chip->regmap, start + i,
+ &pfuze_chip->reg_save_array[index + i]);
+ else
+ ret = regmap_write(pfuze_chip->regmap, start + i,
+ pfuze_chip->reg_save_array[index + i]);
+
+ if (ret)
+ return ret;
+ }
+
+ return index + i;
+}
+
+static int pfuze_suspend(struct device *dev)
+{
+ struct pfuze_chip *pfuze_chip = i2c_get_clientdata(to_i2c_client(dev));
+ int index = 0;
+
+ if (pfuze_chip->need_restore) {
+ /* 0x20~0x40 */
+ index = pfuze_reg_save_restore(pfuze_chip, 0x20, 0x40, index, true);
+ if (index < 0)
+ goto err_ret;
+ /* 0x66~0x71 */
+ index = pfuze_reg_save_restore(pfuze_chip, 0x66, 0x71, ++index, true);
+ if (index < 0)
+ goto err_ret;
+ /* 0x7f */
+ index = pfuze_reg_save_restore(pfuze_chip, 0x7f, 0x7f, ++index, true);
+ if (index < 0)
+ goto err_ret;
+ }
+
+ return 0;
+
+err_ret:
+ return index;
+}
+
+static int pfuze_resume(struct device *dev)
+{
+ struct pfuze_chip *pfuze_chip = i2c_get_clientdata(to_i2c_client(dev));
+ int index = 0;
+
+ if (pfuze_chip->need_restore) {
+ /* 0x20~0x40 */
+ index = pfuze_reg_save_restore(pfuze_chip, 0x20, 0x40, index, false);
+ if (index < 0)
+ goto err_ret;
+ /* 0x66~0x71 */
+ index = pfuze_reg_save_restore(pfuze_chip, 0x66, 0x71, ++index, false);
+ if (index < 0)
+ goto err_ret;
+ /* 0x7f */
+ index = pfuze_reg_save_restore(pfuze_chip, 0x7f, 0x7f, ++index, false);
+ if (index < 0)
+ goto err_ret;
+ }
+
return 0;
+
+err_ret:
+ return index;
}
+static const struct dev_pm_ops pfuze_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pfuze_suspend, pfuze_resume)
+};
+
static struct i2c_driver pfuze_driver = {
.id_table = pfuze_device_id,
.driver = {
.name = "pfuze100-regulator",
.of_match_table = pfuze_dt_ids,
+ .pm = &pfuze_pm_ops,
},
.probe = pfuze100_regulator_probe,
};
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 06d9fa2f3bc0..155746d32a65 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -27,6 +27,14 @@ config RESET_BERLIN
help
This enables the reset controller driver for Marvell Berlin SoCs.
+config RESET_GPIO
+ tristate "GPIO reset controller support"
+ default y
+ depends on GPIOLIB && OF
+ help
+ This driver provides support for reset lines that are controlled
+ directly by GPIOs.
+
config RESET_LPC18XX
bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
default ARCH_LPC18XX
@@ -95,4 +103,5 @@ config RESET_ZYNQ
source "drivers/reset/sti/Kconfig"
source "drivers/reset/hisilicon/Kconfig"
+
endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index bbe7026617fc..391cad3c91ce 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,6 +3,7 @@ obj-y += hisilicon/
obj-$(CONFIG_ARCH_STI) += sti/
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
+obj-$(CONFIG_RESET_GPIO) += gpio-reset.o
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
diff --git a/drivers/reset/gpio-reset.c b/drivers/reset/gpio-reset.c
new file mode 100644
index 000000000000..3049b2202073
--- /dev/null
+++ b/drivers/reset/gpio-reset.c
@@ -0,0 +1,184 @@
+/*
+ * GPIO Reset Controller driver
+ *
+ * Copyright 2013 Philipp Zabel, Pengutronix
+ *
+ * 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 <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+struct gpio_reset_data {
+ struct reset_controller_dev rcdev;
+ unsigned int gpio;
+ bool active_low;
+ s32 delay_us;
+};
+
+static void gpio_reset_set(struct reset_controller_dev *rcdev, int asserted)
+{
+ struct gpio_reset_data *drvdata = container_of(rcdev,
+ struct gpio_reset_data, rcdev);
+ int value = asserted;
+
+ if (drvdata->active_low)
+ value = !value;
+
+ gpio_set_value_cansleep(drvdata->gpio, value);
+}
+
+static int gpio_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ struct gpio_reset_data *drvdata = container_of(rcdev,
+ struct gpio_reset_data, rcdev);
+
+ if (drvdata->delay_us < 0)
+ return -ENOSYS;
+
+ gpio_reset_set(rcdev, 1);
+ udelay(drvdata->delay_us);
+ gpio_reset_set(rcdev, 0);
+
+ return 0;
+}
+
+static int gpio_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ gpio_reset_set(rcdev, 1);
+
+ return 0;
+}
+
+static int gpio_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ gpio_reset_set(rcdev, 0);
+
+ return 0;
+}
+
+static struct reset_control_ops gpio_reset_ops = {
+ .reset = gpio_reset,
+ .assert = gpio_reset_assert,
+ .deassert = gpio_reset_deassert,
+};
+
+static int of_gpio_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ if (WARN_ON(reset_spec->args_count != 0))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int gpio_reset_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct gpio_reset_data *drvdata;
+ enum of_gpio_flags flags;
+ unsigned long gpio_flags;
+ bool initially_in_reset;
+ int ret;
+
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+ if (drvdata == NULL)
+ return -ENOMEM;
+
+ if (of_gpio_named_count(np, "reset-gpios") != 1) {
+ dev_err(&pdev->dev,
+ "reset-gpios property missing, or not a single gpio\n");
+ return -EINVAL;
+ }
+
+ drvdata->gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags);
+ if (drvdata->gpio == -EPROBE_DEFER) {
+ return drvdata->gpio;
+ } else if (!gpio_is_valid(drvdata->gpio)) {
+ dev_err(&pdev->dev, "invalid reset gpio: %d\n", drvdata->gpio);
+ return drvdata->gpio;
+ }
+
+ drvdata->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+ ret = of_property_read_u32(np, "reset-delay-us", &drvdata->delay_us);
+ if (ret < 0)
+ drvdata->delay_us = -1;
+ else if (drvdata->delay_us < 0)
+ dev_warn(&pdev->dev, "reset delay too high\n");
+
+ initially_in_reset = of_property_read_bool(np, "initially-in-reset");
+ if (drvdata->active_low ^ initially_in_reset)
+ gpio_flags = GPIOF_OUT_INIT_HIGH;
+ else
+ gpio_flags = GPIOF_OUT_INIT_LOW;
+
+ ret = devm_gpio_request_one(&pdev->dev, drvdata->gpio, gpio_flags, NULL);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request gpio %d: %d\n",
+ drvdata->gpio, ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, drvdata);
+
+ drvdata->rcdev.of_node = np;
+ drvdata->rcdev.owner = THIS_MODULE;
+ drvdata->rcdev.nr_resets = 1;
+ drvdata->rcdev.ops = &gpio_reset_ops;
+ drvdata->rcdev.of_xlate = of_gpio_reset_xlate;
+ reset_controller_register(&drvdata->rcdev);
+
+ return 0;
+}
+
+static int gpio_reset_remove(struct platform_device *pdev)
+{
+ struct gpio_reset_data *drvdata = platform_get_drvdata(pdev);
+
+ reset_controller_unregister(&drvdata->rcdev);
+
+ return 0;
+}
+
+static struct of_device_id gpio_reset_dt_ids[] = {
+ { .compatible = "gpio-reset" },
+ { }
+};
+
+static struct platform_driver gpio_reset_driver = {
+ .probe = gpio_reset_probe,
+ .remove = gpio_reset_remove,
+ .driver = {
+ .name = "gpio-reset",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(gpio_reset_dt_ids),
+ },
+};
+
+static int __init gpio_reset_init(void)
+{
+ return platform_driver_register(&gpio_reset_driver);
+}
+arch_initcall(gpio_reset_init);
+
+static void __exit gpio_reset_exit(void)
+{
+ platform_driver_unregister(&gpio_reset_driver);
+}
+module_exit(gpio_reset_exit);
+
+MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
+MODULE_DESCRIPTION("gpio reset controller");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-reset");
+MODULE_DEVICE_TABLE(of, gpio_reset_dt_ids);
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index de31c5f14dd9..d7f1ae8118c5 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -20,4 +20,19 @@ config RPMSG_VIRTIO
select VIRTIO
select VIRTUALIZATION
+config HAVE_IMX_RPMSG
+ bool "IMX RPMSG driver on the AMP SOCs"
+ select RPMSG
+ select RPMSG_VIRTIO
+
+config IMX_RPMSG_PINGPONG
+ tristate "IMX RPMSG pingpong driver -- loadable modules only"
+ default m
+ depends on RPMSG && m
+
+config IMX_RPMSG_TTY
+ tristate "IMX RPMSG tty driver -- loadable modules only"
+ default m
+ depends on RPMSG && m
+
endmenu
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index ae9c9132cf76..1c287ca6f1c9 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,3 +1,6 @@
obj-$(CONFIG_RPMSG) += rpmsg_core.o
obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o
obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
+obj-$(CONFIG_HAVE_IMX_RPMSG) += imx_rpmsg.o
+obj-$(CONFIG_IMX_RPMSG_PINGPONG) += imx_rpmsg_pingpong.o
+obj-$(CONFIG_IMX_RPMSG_TTY) += imx_rpmsg_tty.o
diff --git a/drivers/rpmsg/imx_rpmsg.c b/drivers/rpmsg/imx_rpmsg.c
new file mode 100644
index 000000000000..44ec65aa1275
--- /dev/null
+++ b/drivers/rpmsg/imx_rpmsg.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * derived from the omap-rpmsg implementation.
+ *
+ * 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/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/rpmsg.h>
+#include <linux/slab.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_ring.h>
+#include <linux/imx_rpmsg.h>
+#include <linux/imx_mu.h>
+
+enum imx_rpmsg_variants {
+ IMX6SX,
+ IMX7D,
+ IMX7ULP,
+};
+static enum imx_rpmsg_variants variant;
+
+struct imx_virdev {
+ struct virtio_device vdev;
+ unsigned int vring[2];
+ struct virtqueue *vq[2];
+ int base_vq_id;
+ int num_of_vqs;
+ struct notifier_block nb;
+};
+
+struct imx_rpmsg_vproc {
+ char *rproc_name;
+ struct mutex lock;
+ int vdev_nums;
+#define MAX_VDEV_NUMS 7
+ struct imx_virdev ivdev[MAX_VDEV_NUMS];
+};
+
+struct imx_mu_rpmsg_box {
+ const char *name;
+ struct blocking_notifier_head notifier;
+};
+
+static struct imx_mu_rpmsg_box mu_rpmsg_box = {
+ .name = "m4",
+};
+
+#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 DEFINE_SPINLOCK(mu_lock);
+static struct delayed_work rpmsg_work;
+
+/*
+ * For now, allocate 256 buffers of 512 bytes for each side. each buffer
+ * will then have 16B for the msg header and 496B for the payload.
+ * This will require a total space of 256KB for the buffers themselves, and
+ * 3 pages for every vring (the size of the vring depends on the number of
+ * buffers it supports).
+ */
+#define RPMSG_NUM_BUFS (512)
+#define RPMSG_BUF_SIZE (512)
+#define RPMSG_BUFS_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE)
+
+/*
+ * The alignment between the consumer and producer parts of the vring.
+ * Note: this is part of the "wire" protocol. If you change this, you need
+ * to update your BIOS image as well
+ */
+#define RPMSG_VRING_ALIGN (4096)
+
+/* With 256 buffers, our vring will occupy 3 pages */
+#define RPMSG_RING_SIZE ((DIV_ROUND_UP(vring_size(RPMSG_NUM_BUFS / 2, \
+ RPMSG_VRING_ALIGN), PAGE_SIZE)) * PAGE_SIZE)
+
+#define to_imx_virdev(vd) container_of(vd, struct imx_virdev, vdev)
+#define to_imx_rpdev(vd, id) container_of(vd, struct imx_rpmsg_vproc, ivdev[id])
+
+struct imx_rpmsg_vq_info {
+ __u16 num; /* number of entries in the virtio_ring */
+ __u16 vq_id; /* a globaly unique index of this virtqueue */
+ void *addr; /* address where we mapped the virtio ring */
+ struct imx_rpmsg_vproc *rpdev;
+};
+
+static u64 imx_rpmsg_get_features(struct virtio_device *vdev)
+{
+ /* VIRTIO_RPMSG_F_NS has been made private */
+ return 1 << 0;
+}
+
+static int imx_rpmsg_finalize_features(struct virtio_device *vdev)
+{
+ /* Give virtio_ring a chance to accept features */
+ vring_transport_features(vdev);
+ return 0;
+}
+
+/* kick the remote processor, and let it know which virtqueue to poke at */
+static bool imx_rpmsg_notify(struct virtqueue *vq)
+{
+ unsigned int mu_rpmsg = 0;
+ struct imx_rpmsg_vq_info *rpvq = vq->priv;
+
+ mu_rpmsg = rpvq->vq_id << 16;
+ mutex_lock(&rpvq->rpdev->lock);
+ /* send the index of the triggered virtqueue as the mu payload */
+ MU_SendMessage(mu_base, 1, mu_rpmsg);
+ mutex_unlock(&rpvq->rpdev->lock);
+
+ return true;
+}
+
+static int imx_mu_rpmsg_callback(struct notifier_block *this,
+ unsigned long index, void *data)
+{
+ u32 mu_msg = (phys_addr_t) data;
+ struct imx_virdev *virdev;
+
+ virdev = container_of(this, struct imx_virdev, nb);
+
+ pr_debug("%s mu_msg: 0x%x\n", __func__, mu_msg);
+ /* ignore vq indices which are clearly not for us */
+ mu_msg = mu_msg >> 16;
+ if (mu_msg < virdev->base_vq_id || mu_msg > virdev->base_vq_id + 1) {
+ pr_debug("mu_msg: 0x%x is invalid\n", mu_msg);
+ return NOTIFY_DONE;
+ }
+
+ mu_msg -= virdev->base_vq_id;
+
+ /*
+ * Currently both PENDING_MSG and explicit-virtqueue-index
+ * messaging are supported.
+ * Whatever approach is taken, at this point 'mu_msg' contains
+ * the index of the vring which was just triggered.
+ */
+ if (mu_msg < virdev->num_of_vqs)
+ vring_interrupt(mu_msg, virdev->vq[mu_msg]);
+
+ return NOTIFY_DONE;
+}
+
+int imx_mu_rpmsg_register_nb(const char *name, struct notifier_block *nb)
+{
+ if ((name == NULL) || (nb == NULL))
+ return -EINVAL;
+
+ if (!strcmp(mu_rpmsg_box.name, name))
+ blocking_notifier_chain_register(&(mu_rpmsg_box.notifier), nb);
+ else
+ return -ENOENT;
+
+ return 0;
+}
+
+int imx_mu_rpmsg_unregister_nb(const char *name, struct notifier_block *nb)
+{
+ if ((name == NULL) || (nb == NULL))
+ return -EINVAL;
+
+ if (!strcmp(mu_rpmsg_box.name, name))
+ blocking_notifier_chain_unregister(&(mu_rpmsg_box.notifier),
+ nb);
+ else
+ return -ENOENT;
+
+ return 0;
+}
+
+static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
+ unsigned int index,
+ void (*callback)(struct virtqueue *vq),
+ const char *name)
+{
+ struct imx_virdev *virdev = to_imx_virdev(vdev);
+ struct imx_rpmsg_vproc *rpdev = to_imx_rpdev(virdev,
+ virdev->base_vq_id / 2);
+ struct imx_rpmsg_vq_info *rpvq;
+ struct virtqueue *vq;
+ int err;
+
+ rpvq = kmalloc(sizeof(*rpvq), GFP_KERNEL);
+ if (!rpvq)
+ return ERR_PTR(-ENOMEM);
+
+ /* ioremap'ing normal memory, so we cast away sparse's complaints */
+ rpvq->addr = (__force void *) ioremap_nocache(virdev->vring[index],
+ RPMSG_RING_SIZE);
+ if (!rpvq->addr) {
+ err = -ENOMEM;
+ goto free_rpvq;
+ }
+
+ memset(rpvq->addr, 0, RPMSG_RING_SIZE);
+
+ pr_debug("vring%d: phys 0x%x, virt 0x%p\n", index, virdev->vring[index],
+ rpvq->addr);
+
+ vq = vring_new_virtqueue(index, RPMSG_NUM_BUFS / 2, RPMSG_VRING_ALIGN,
+ vdev, true, rpvq->addr, imx_rpmsg_notify, callback,
+ name);
+ if (!vq) {
+ pr_err("vring_new_virtqueue failed\n");
+ err = -ENOMEM;
+ goto unmap_vring;
+ }
+
+ virdev->vq[index] = vq;
+ vq->priv = rpvq;
+ /* system-wide unique id for this virtqueue */
+ rpvq->vq_id = virdev->base_vq_id + index;
+ rpvq->rpdev = rpdev;
+ mutex_init(&rpdev->lock);
+
+ return vq;
+
+unmap_vring:
+ /* iounmap normal memory, so make sparse happy */
+ iounmap((__force void __iomem *) rpvq->addr);
+free_rpvq:
+ kfree(rpvq);
+ return ERR_PTR(err);
+}
+
+static void imx_rpmsg_del_vqs(struct virtio_device *vdev)
+{
+ struct virtqueue *vq, *n;
+ struct imx_virdev *virdev = to_imx_virdev(vdev);
+ struct imx_rpmsg_vproc *rpdev = to_imx_rpdev(virdev,
+ virdev->base_vq_id / 2);
+
+ list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
+ struct imx_rpmsg_vq_info *rpvq = vq->priv;
+
+ iounmap(rpvq->addr);
+ vring_del_virtqueue(vq);
+ kfree(rpvq);
+ }
+
+ if (&virdev->nb)
+ imx_mu_rpmsg_unregister_nb((const char *)rpdev->rproc_name,
+ &virdev->nb);
+}
+
+static int imx_rpmsg_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
+ struct virtqueue *vqs[],
+ vq_callback_t *callbacks[],
+ const char * const names[])
+{
+ struct imx_virdev *virdev = to_imx_virdev(vdev);
+ struct imx_rpmsg_vproc *rpdev = to_imx_rpdev(virdev,
+ virdev->base_vq_id / 2);
+ int i, err;
+
+ /* we maintain two virtqueues per remote processor (for RX and TX) */
+ if (nvqs != 2)
+ return -EINVAL;
+
+ for (i = 0; i < nvqs; ++i) {
+ vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
+ if (IS_ERR(vqs[i])) {
+ err = PTR_ERR(vqs[i]);
+ goto error;
+ }
+ }
+
+ virdev->num_of_vqs = nvqs;
+
+ virdev->nb.notifier_call = imx_mu_rpmsg_callback;
+ imx_mu_rpmsg_register_nb((const char *)rpdev->rproc_name, &virdev->nb);
+
+ return 0;
+
+error:
+ imx_rpmsg_del_vqs(vdev);
+ return err;
+}
+
+static void imx_rpmsg_reset(struct virtio_device *vdev)
+{
+ dev_dbg(&vdev->dev, "reset !\n");
+}
+
+static u8 imx_rpmsg_get_status(struct virtio_device *vdev)
+{
+ return 0;
+}
+
+static void imx_rpmsg_set_status(struct virtio_device *vdev, u8 status)
+{
+ dev_dbg(&vdev->dev, "%s new status: %d\n", __func__, status);
+}
+
+static void imx_rpmsg_vproc_release(struct device *dev)
+{
+ /* this handler is provided so driver core doesn't yell at us */
+}
+
+static struct virtio_config_ops imx_rpmsg_config_ops = {
+ .get_features = imx_rpmsg_get_features,
+ .finalize_features = imx_rpmsg_finalize_features,
+ .find_vqs = imx_rpmsg_find_vqs,
+ .del_vqs = imx_rpmsg_del_vqs,
+ .reset = imx_rpmsg_reset,
+ .set_status = imx_rpmsg_set_status,
+ .get_status = imx_rpmsg_get_status,
+};
+
+static struct imx_rpmsg_vproc imx_rpmsg_vprocs[] = {
+ {
+ .rproc_name = "m4",
+ },
+};
+
+static const struct of_device_id imx_rpmsg_dt_ids[] = {
+ { .compatible = "fsl,imx6sx-rpmsg", .data = (void *)IMX6SX, },
+ { .compatible = "fsl,imx7d-rpmsg", .data = (void *)IMX7D, },
+ { .compatible = "fsl,imx7ulp-rpmsg", .data = (void *)IMX7ULP, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_rpmsg_dt_ids);
+
+static int set_vring_phy_buf(struct platform_device *pdev,
+ struct imx_rpmsg_vproc *rpdev, int vdev_nums)
+{
+ struct resource *res;
+ resource_size_t size;
+ unsigned int start, end;
+ int i, ret = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res) {
+ size = resource_size(res);
+ start = res->start;
+ end = res->start + size;
+ for (i = 0; i < vdev_nums; i++) {
+ rpdev->ivdev[i].vring[0] = start;
+ rpdev->ivdev[i].vring[1] = start +
+ 0x8000;
+ start += 0x10000;
+ if (start > end) {
+ pr_err("Too small memory size %x!\n",
+ (u32)size);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ } else {
+ return -ENOMEM;
+ }
+
+ return ret;
+}
+
+static void rpmsg_work_handler(struct work_struct *work)
+{
+ u32 message;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mu_lock, flags);
+ /* handle all incoming mu message */
+ while (in_idx != out_idx) {
+ message = m4_message[out_idx % MAX_NUM];
+ spin_unlock_irqrestore(&mu_lock, flags);
+
+ blocking_notifier_call_chain(&(mu_rpmsg_box.notifier), 4,
+ (void *)(phys_addr_t)message);
+
+ spin_lock_irqsave(&mu_lock, flags);
+ m4_message[out_idx % MAX_NUM] = 0;
+ out_idx++;
+ }
+ spin_unlock_irqrestore(&mu_lock, flags);
+}
+
+static irqreturn_t imx_mu_rpmsg_isr(int irq, void *param)
+{
+ u32 irqs, message;
+ unsigned long flags;
+
+ irqs = MU_ReadStatus(mu_base);
+
+ /* RPMSG */
+ if (irqs & (1 << 26)) {
+ spin_lock_irqsave(&mu_lock, flags);
+ /* get message from receive buffer */
+ MU_ReceiveMsg(mu_base, 1, &message);
+ m4_message[in_idx % MAX_NUM] = message;
+ in_idx++;
+ /*
+ * Too many mu message not be handled in timely, can enlarge
+ * MAX_NUM
+ */
+ 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(&rpmsg_work, 0);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int imx_rpmsg_probe(struct platform_device *pdev)
+{
+ int i, j, ret = 0;
+ u32 irq;
+ struct clk *clk;
+ struct device_node *np_mu;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+
+ variant = (enum imx_rpmsg_variants)of_device_get_match_data(dev);
+
+ /* Initialize the mu unit used by rpmsg */
+ np_mu = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-mu");
+ if (!np_mu)
+ pr_info("Cannot find MU-RPMSG entry in device tree\n");
+ mu_base = of_iomap(np_mu, 0);
+ WARN_ON(!mu_base);
+
+ if (variant == IMX7ULP)
+ irq = of_irq_get(np_mu, 1);
+ else
+ irq = of_irq_get(np_mu, 0);
+
+ ret = request_irq(irq, imx_mu_rpmsg_isr,
+ IRQF_EARLY_RESUME | IRQF_SHARED,
+ "imx-mu-rpmsg", dev);
+ if (ret) {
+ pr_err("%s: register interrupt %d failed, rc %d\n",
+ __func__, irq, ret);
+ return ret;
+ }
+
+ if (variant == IMX7D) {
+ clk = of_clk_get(np_mu, 0);
+ if (IS_ERR(clk)) {
+ pr_err("mu clock source missing or invalid\n");
+ return PTR_ERR(clk);
+ }
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ pr_err("unable to enable mu clock\n");
+ return ret;
+ }
+ }
+
+ INIT_DELAYED_WORK(&rpmsg_work, rpmsg_work_handler);
+ /*
+ * bit26 is used by rpmsg channels.
+ * bit0 of MX7ULP_MU_CR used to let m4 to know MU is ready now
+ */
+ if (variant == IMX7ULP) {
+ MU_EnableRxFullInt(mu_base, 1);
+ MU_SetFn(mu_base, 1);
+ } else {
+ MU_EnableRxFullInt(mu_base, 1);
+ }
+ BLOCKING_INIT_NOTIFIER_HEAD(&(mu_rpmsg_box.notifier));
+
+ pr_info("MU is ready for cross core communication!\n");
+
+ for (i = 0; i < ARRAY_SIZE(imx_rpmsg_vprocs); i++) {
+ struct imx_rpmsg_vproc *rpdev = &imx_rpmsg_vprocs[i];
+
+ ret = of_property_read_u32_index(np, "vdev-nums", i,
+ &rpdev->vdev_nums);
+ if (ret)
+ rpdev->vdev_nums = 1;
+ if (rpdev->vdev_nums > MAX_VDEV_NUMS) {
+ pr_err("vdev-nums exceed the max %d\n", MAX_VDEV_NUMS);
+ return -EINVAL;
+ }
+
+ if (!strcmp(rpdev->rproc_name, "m4")) {
+ ret = set_vring_phy_buf(pdev, rpdev,
+ rpdev->vdev_nums);
+ if (ret) {
+ pr_err("No vring buffer.\n");
+ return -ENOMEM;
+ }
+ } else {
+ pr_err("No remote m4 processor.\n");
+ return -ENODEV;
+ }
+
+ for (j = 0; j < rpdev->vdev_nums; j++) {
+ pr_debug("%s rpdev%d vdev%d: vring0 0x%x, vring1 0x%x\n",
+ __func__, i, rpdev->vdev_nums,
+ rpdev->ivdev[j].vring[0],
+ rpdev->ivdev[j].vring[1]);
+ rpdev->ivdev[j].vdev.id.device = VIRTIO_ID_RPMSG;
+ rpdev->ivdev[j].vdev.config = &imx_rpmsg_config_ops;
+ rpdev->ivdev[j].vdev.dev.parent = &pdev->dev;
+ rpdev->ivdev[j].vdev.dev.release = imx_rpmsg_vproc_release;
+ rpdev->ivdev[j].base_vq_id = j * 2;
+
+ ret = register_virtio_device(&rpdev->ivdev[j].vdev);
+ if (ret) {
+ pr_err("%s failed to register rpdev: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ }
+ }
+
+ return ret;
+}
+
+static struct platform_driver imx_rpmsg_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "imx-rpmsg",
+ .of_match_table = imx_rpmsg_dt_ids,
+ },
+ .probe = imx_rpmsg_probe,
+};
+
+static int __init imx_rpmsg_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&imx_rpmsg_driver);
+ if (ret)
+ pr_err("Unable to initialize rpmsg driver\n");
+ else
+ pr_info("imx rpmsg driver is registered.\n");
+
+ return ret;
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("iMX remote processor messaging virtio device");
+MODULE_LICENSE("GPL v2");
+subsys_initcall(imx_rpmsg_init);
diff --git a/drivers/rpmsg/imx_rpmsg_pingpong.c b/drivers/rpmsg/imx_rpmsg_pingpong.c
new file mode 100644
index 000000000000..341cd7eb8f53
--- /dev/null
+++ b/drivers/rpmsg/imx_rpmsg_pingpong.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * derived from the omap-rpmsg implementation.
+ * Remote processor messaging transport - pingpong driver
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/rpmsg.h>
+
+#define MSG "hello world!"
+#define MSG_LIMIT 100000
+static unsigned int rpmsg_pingpong;
+static int rx_count;
+
+static int rpmsg_pingpong_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+ int err;
+
+ /* reply */
+ rpmsg_pingpong = *(unsigned int *)data;
+ pr_info("get %d (src: 0x%x)\n",
+ rpmsg_pingpong, src);
+ rx_count++;
+
+ /* pingpongs should not live forever */
+ if (rx_count >= MSG_LIMIT) {
+ dev_info(&rpdev->dev, "goodbye!\n");
+ return 0;
+ }
+ rpmsg_pingpong++;
+ err = rpmsg_sendto(rpdev->ept, (void *)(&rpmsg_pingpong), 4, src);
+
+ if (err)
+ dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", err);
+
+ return err;
+}
+
+static int rpmsg_pingpong_probe(struct rpmsg_device *rpdev)
+{
+ int err;
+
+ dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+ rpdev->src, rpdev->dst);
+
+ /*
+ * send a message to our remote processor, and tell remote
+ * processor about this channel
+ */
+ err = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
+ if (err) {
+ dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", err);
+ return err;
+ }
+
+ rpmsg_pingpong = 0;
+ rx_count = 0;
+ err = rpmsg_sendto(rpdev->ept, (void *)(&rpmsg_pingpong), 4, rpdev->dst);
+ if (err) {
+ dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static void rpmsg_pingpong_remove(struct rpmsg_device *rpdev)
+{
+ dev_info(&rpdev->dev, "rpmsg pingpong driver is removed\n");
+}
+
+static struct rpmsg_device_id rpmsg_driver_pingpong_id_table[] = {
+ { .name = "rpmsg-openamp-demo-channel" },
+ { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_pingpong_id_table);
+
+static struct rpmsg_driver rpmsg_pingpong_driver = {
+ .drv.name = KBUILD_MODNAME,
+ .drv.owner = THIS_MODULE,
+ .id_table = rpmsg_driver_pingpong_id_table,
+ .probe = rpmsg_pingpong_probe,
+ .callback = rpmsg_pingpong_cb,
+ .remove = rpmsg_pingpong_remove,
+};
+
+static int __init init(void)
+{
+ return register_rpmsg_driver(&rpmsg_pingpong_driver);
+}
+
+static void __exit fini(void)
+{
+ unregister_rpmsg_driver(&rpmsg_pingpong_driver);
+}
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("iMX virtio remote processor messaging pingpong driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rpmsg/imx_rpmsg_tty.c b/drivers/rpmsg/imx_rpmsg_tty.c
new file mode 100644
index 000000000000..42b245db3d5a
--- /dev/null
+++ b/drivers/rpmsg/imx_rpmsg_tty.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright (C) 2017 NXP
+ *
+ * derived from the omap-rpmsg implementation.
+ * Remote processor messaging transport - tty driver
+ *
+ * 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/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/virtio.h>
+
+/*
+ * struct rpmsgtty_port - Wrapper struct for imx rpmsg tty port.
+ * @port: TTY port data
+ */
+struct rpmsgtty_port {
+ struct tty_port port;
+ spinlock_t rx_lock;
+ struct rpmsg_device *rpdev;
+};
+
+static struct rpmsgtty_port rpmsg_tty_port;
+
+/* this needs to be less then (RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) */
+#define RPMSG_MAX_SIZE 256
+#define MSG "hello world!"
+
+static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+ int space;
+ unsigned char *cbuf;
+ struct rpmsgtty_port *cport = &rpmsg_tty_port;
+
+ /* flush the recv-ed none-zero data to tty node */
+ if (len == 0)
+ return 0;
+
+ dev_dbg(&rpdev->dev, "msg(<- src 0x%x) len %d\n", src, len);
+
+ print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1,
+ data, len, true);
+
+ spin_lock_bh(&cport->rx_lock);
+ space = tty_prepare_flip_string(&cport->port, &cbuf, len);
+ if (space <= 0) {
+ dev_err(&rpdev->dev, "No memory for tty_prepare_flip_string\n");
+ spin_unlock_bh(&cport->rx_lock);
+ return -ENOMEM;
+ }
+
+ memcpy(cbuf, data, len);
+ tty_flip_buffer_push(&cport->port);
+ spin_unlock_bh(&cport->rx_lock);
+
+ return 0;
+}
+
+static struct tty_port_operations rpmsgtty_port_ops = { };
+
+static int rpmsgtty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ return tty_port_install(&rpmsg_tty_port.port, driver, tty);
+}
+
+static int rpmsgtty_open(struct tty_struct *tty, struct file *filp)
+{
+ return tty_port_open(tty->port, tty, filp);
+}
+
+static void rpmsgtty_close(struct tty_struct *tty, struct file *filp)
+{
+ return tty_port_close(tty->port, tty, filp);
+}
+
+static int rpmsgtty_write(struct tty_struct *tty, const unsigned char *buf,
+ int total)
+{
+ int count, ret = 0;
+ const unsigned char *tbuf;
+ struct rpmsgtty_port *rptty_port = container_of(tty->port,
+ struct rpmsgtty_port, port);
+ struct rpmsg_device *rpdev = rptty_port->rpdev;
+
+ if (NULL == buf) {
+ pr_err("buf shouldn't be null.\n");
+ return -ENOMEM;
+ }
+
+ count = total;
+ tbuf = buf;
+ do {
+ /* send a message to our remote processor */
+ ret = rpmsg_send(rpdev->ept, (void *)tbuf,
+ count > RPMSG_MAX_SIZE ? RPMSG_MAX_SIZE : count);
+ if (ret) {
+ dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
+ return ret;
+ }
+
+ if (count > RPMSG_MAX_SIZE) {
+ count -= RPMSG_MAX_SIZE;
+ tbuf += RPMSG_MAX_SIZE;
+ } else {
+ count = 0;
+ }
+ } while (count > 0);
+
+ return total;
+}
+
+static int rpmsgtty_write_room(struct tty_struct *tty)
+{
+ /* report the space in the rpmsg buffer */
+ return RPMSG_MAX_SIZE;
+}
+
+static const struct tty_operations imxrpmsgtty_ops = {
+ .install = rpmsgtty_install,
+ .open = rpmsgtty_open,
+ .close = rpmsgtty_close,
+ .write = rpmsgtty_write,
+ .write_room = rpmsgtty_write_room,
+};
+
+static struct tty_driver *rpmsgtty_driver;
+
+static int rpmsg_tty_probe(struct rpmsg_device *rpdev)
+{
+ int err;
+ struct rpmsgtty_port *cport = &rpmsg_tty_port;
+
+ dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+ rpdev->src, rpdev->dst);
+
+ /*
+ * send a message to our remote processor, and tell remote
+ * processor about this channel
+ */
+ err = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
+ if (err) {
+ dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", err);
+ return err;
+ }
+
+ rpmsgtty_driver = tty_alloc_driver(1, TTY_DRIVER_UNNUMBERED_NODE);
+ if (IS_ERR(rpmsgtty_driver))
+ return PTR_ERR(rpmsgtty_driver);
+
+ rpmsgtty_driver->driver_name = "rpmsg_tty";
+ rpmsgtty_driver->name = "ttyRPMSG";
+ rpmsgtty_driver->major = TTYAUX_MAJOR;
+ rpmsgtty_driver->minor_start = 3;
+ rpmsgtty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
+ rpmsgtty_driver->init_termios = tty_std_termios;
+
+ tty_set_operations(rpmsgtty_driver, &imxrpmsgtty_ops);
+
+ tty_port_init(&cport->port);
+ cport->port.ops = &rpmsgtty_port_ops;
+ spin_lock_init(&cport->rx_lock);
+ cport->port.low_latency = cport->port.flags | ASYNC_LOW_LATENCY;
+
+ err = tty_register_driver(rpmsgtty_driver);
+ if (err < 0) {
+ pr_err("Couldn't install rpmsg tty driver: err %d\n", err);
+ goto error;
+ } else
+ pr_info("Install rpmsg tty driver!\n");
+ cport->rpdev = rpdev;
+
+ return 0;
+
+error:
+ tty_unregister_driver(rpmsgtty_driver);
+ put_tty_driver(rpmsgtty_driver);
+ tty_port_destroy(&cport->port);
+ rpmsgtty_driver = NULL;
+
+ return err;
+}
+
+static void rpmsg_tty_remove(struct rpmsg_device *rpdev)
+{
+ struct rpmsgtty_port *cport = &rpmsg_tty_port;
+
+ dev_info(&rpdev->dev, "rpmsg tty driver is removed\n");
+
+ tty_unregister_driver(rpmsgtty_driver);
+ put_tty_driver(rpmsgtty_driver);
+ tty_port_destroy(&cport->port);
+ rpmsgtty_driver = NULL;
+}
+
+static struct rpmsg_device_id rpmsg_driver_tty_id_table[] = {
+ { .name = "rpmsg-virtual-tty-channel" },
+ { .name = "rpmsg-openamp-demo-channel" },
+ { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_tty_id_table);
+
+static struct rpmsg_driver rpmsg_tty_driver = {
+ .drv.name = KBUILD_MODNAME,
+ .drv.owner = THIS_MODULE,
+ .id_table = rpmsg_driver_tty_id_table,
+ .probe = rpmsg_tty_probe,
+ .callback = rpmsg_tty_cb,
+ .remove = rpmsg_tty_remove,
+};
+
+static int __init init(void)
+{
+ return register_rpmsg_driver(&rpmsg_tty_driver);
+}
+
+static void __exit fini(void)
+{
+ unregister_rpmsg_driver(&rpmsg_tty_driver);
+}
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("iMX virtio remote processor messaging tty driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 3090b0d3072f..15a8fa77c9fc 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -495,6 +495,27 @@ static void rpmsg_downref_sleepers(struct virtproc_info *vrp)
mutex_unlock(&vrp->tx_lock);
}
+static int sg_init_one_full(struct scatterlist *sg, const void *buf,
+ unsigned int buflen)
+{
+ const bool vmalloced_buf = is_vmalloc_addr(buf);
+ struct page *vm_page;
+
+ /* get page for high memory */
+ if (vmalloced_buf) {
+ vm_page = vmalloc_to_page(buf);
+ if (!vm_page)
+ return -ENOMEM;
+
+ sg_init_table(sg, 1);
+ sg_set_page(sg, vm_page, RPMSG_BUF_SIZE,
+ offset_in_page(buf));
+ } else
+ sg_init_one(sg, buf, buflen);
+
+ return 0;
+}
+
/**
* rpmsg_send_offchannel_raw() - send a message across to the remote processor
* @rpdev: the rpmsg channel
@@ -604,7 +625,11 @@ static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev,
msg, sizeof(*msg) + msg->len, true);
#endif
- sg_init_one(&sg, msg, sizeof(*msg) + len);
+ err = sg_init_one_full(&sg, msg, sizeof(*msg) + len);
+ if (err) {
+ dev_err(dev, "virtqueue_add_outbuf sg_init failed: %d\n", err);
+ return err;
+ }
mutex_lock(&vrp->tx_lock);
@@ -729,7 +754,11 @@ static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
dev_warn(dev, "msg received with no recipient\n");
/* publish the real size of the buffer */
- sg_init_one(&sg, msg, RPMSG_BUF_SIZE);
+ err = sg_init_one_full(&sg, msg, RPMSG_BUF_SIZE);
+ if (err) {
+ dev_err(dev, "rpmsg_recv_done sg_init failed: %d\n", err);
+ return err;
+ }
/* add the buffer back to the remote processor's virtqueue */
err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, msg, GFP_KERNEL);
@@ -911,7 +940,11 @@ static int rpmsg_probe(struct virtio_device *vdev)
struct scatterlist sg;
void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE;
- sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE);
+ err = sg_init_one_full(&sg, cpu_addr, RPMSG_BUF_SIZE);
+ if (err) {
+ dev_err(&vdev->dev, "rpmsg_probe sg_init failed.\n");
+ return err;
+ }
err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr,
GFP_KERNEL);
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index 0f11c2a228e3..2b086be7dccb 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-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
@@ -18,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
@@ -64,7 +66,12 @@ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
read2 <<= 32;
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
read2 |= val;
- } while (read1 != read2);
+ /*
+ * when CPU/BUS are running at low speed, there is chance that
+ * we never get same value during two consecutive read, so here
+ * we only compare the second value.
+ */
+ } while ((read1 >> CNTR_TO_SECS_SH) != (read2 >> CNTR_TO_SECS_SH));
/* Convert 47-bit counter to 32-bit raw second count */
return (u32) (read1 >> CNTR_TO_SECS_SH);
@@ -138,6 +145,8 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* Disable RTC first */
snvs_rtc_enable(data, false);
+ udelay(50);
+
/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
@@ -184,6 +193,7 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
rtc_tm_to_time(alrm_tm, &time);
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
+ rtc_write_sync_lp(data);
regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
/* Clear alarm interrupt status bit */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 106a6adbd6f1..3c30d66bcaf2 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -59,6 +59,12 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd);
static int scsi_try_to_abort_cmd(struct scsi_host_template *,
struct scsi_cmnd *);
+#ifdef CONFIG_AHCI_IMX
+extern void *sg_io_buffer_hack;
+#else
+#define sg_io_buffer_hack NULL
+#endif
+
/* called with shost->host_lock held */
void scsi_eh_wakeup(struct Scsi_Host *shost)
{
@@ -67,6 +73,11 @@ void scsi_eh_wakeup(struct Scsi_Host *shost)
wake_up_process(shost->ehandler);
SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost,
"Waking error handler thread\n"));
+ } else if ((shost->host_failed > 0) || (sg_io_buffer_hack != NULL)) {
+ trace_scsi_eh_wakeup(shost);
+ wake_up_process(shost->ehandler);
+ SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost,
+ "Waking error handler thread\n"));
}
}
@@ -2190,8 +2201,15 @@ int scsi_error_handler(void *data)
if (kthread_should_stop())
break;
+ /*
+ * Do not go to sleep, when there is host_failed when the
+ * one-PRD per command workaroud is tiggered.
+ * Because that ata/scsi subsystem maybe hang, when CD_ROM
+ * and HDD are accessed simultaneously.
+ */
if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
- shost->host_failed != atomic_read(&shost->host_busy)) {
+ ((shost->host_failed != atomic_read(&shost->host_busy)) &&
+ (sg_io_buffer_hack == NULL) && (shost->host_failed > 0))) {
SCSI_LOG_ERROR_RECOVERY(1,
shost_printk(KERN_INFO, shost,
"scsi_eh_%d: sleeping\n",
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 50c23d0bd457..489df4d77687 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_SOC_TI) += ti/
obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_PLAT_VERSATILE) += versatile/
+obj-y += imx/
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
new file mode 100644
index 000000000000..0084b281cdc5
--- /dev/null
+++ b/drivers/soc/imx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_HAVE_IMX_MU) += mu/
diff --git a/drivers/soc/imx/mu/Makefile b/drivers/soc/imx/mu/Makefile
new file mode 100644
index 000000000000..0047c3e69528
--- /dev/null
+++ b/drivers/soc/imx/mu/Makefile
@@ -0,0 +1 @@
+obj-y += imx_mu.o
diff --git a/drivers/soc/imx/mu/imx_mu.c b/drivers/soc/imx/mu/imx_mu.c
new file mode 100644
index 000000000000..39cb9d3c49b3
--- /dev/null
+++ b/drivers/soc/imx/mu/imx_mu.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/imx_mu.h>
+
+/*!
+ * This function sets the Flag n of the MU.
+ */
+int32_t MU_SetFn(void __iomem *base, uint32_t Fn)
+{
+ uint32_t reg, offset;
+
+ reg = Fn & (~MU_CR_Fn_MASK1);
+ if (reg > 0)
+ return -EINVAL;
+
+ offset = unlikely((readl_relaxed(base) >> 16) == MU_VER_ID_V10)
+ ? MU_V10_ACR_OFFSET1 : MU_ACR_OFFSET1;
+
+ reg = readl_relaxed(base + offset);
+ /* Clear ABFn. */
+ reg &= ~MU_CR_Fn_MASK1;
+ reg |= Fn;
+ writel_relaxed(reg, base + offset);
+
+ return 0;
+}
+
+/*!
+ * This function reads the status from status register.
+ */
+uint32_t MU_ReadStatus(void __iomem *base)
+{
+ uint32_t reg, offset;
+
+ offset = unlikely((readl_relaxed(base) >> 16) == MU_VER_ID_V10)
+ ? MU_V10_ASR_OFFSET1 : MU_ASR_OFFSET1;
+
+ reg = readl_relaxed(base + offset);
+
+ return reg;
+}
+
+/*!
+ * This function enables specific RX full interrupt.
+ */
+void MU_EnableRxFullInt(void __iomem *base, uint32_t index)
+{
+ uint32_t reg, offset;
+
+ offset = unlikely((readl_relaxed(base) >> 16) == MU_VER_ID_V10)
+ ? MU_V10_ACR_OFFSET1 : MU_ACR_OFFSET1;
+
+ reg = readl_relaxed(base + offset);
+ reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1);
+ reg |= MU_CR_RIE0_MASK1 >> index;
+ writel_relaxed(reg, base + offset);
+}
+
+/*!
+ * This function enables specific general purpose interrupt.
+ */
+void MU_EnableGeneralInt(void __iomem *base, uint32_t index)
+{
+ uint32_t reg, offset;
+
+ offset = unlikely((readl_relaxed(base) >> 16) == MU_VER_ID_V10)
+ ? MU_V10_ACR_OFFSET1 : MU_ACR_OFFSET1;
+
+ reg = readl_relaxed(base + offset);
+ reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1);
+ reg |= MU_CR_GIE0_MASK1 >> index;
+ writel_relaxed(reg, base + offset);
+}
+
+/*
+ * Wait and send message to the other core.
+ */
+void MU_SendMessage(void __iomem *base, uint32_t regIndex, uint32_t msg)
+{
+ uint32_t mask = MU_SR_TE0_MASK1 >> regIndex;
+
+ if (unlikely((readl_relaxed(base) >> 16) == MU_VER_ID_V10)) {
+ /* Wait TX register to be empty. */
+ while (!(readl_relaxed(base + MU_V10_ASR_OFFSET1) & mask))
+ ;
+ writel_relaxed(msg, base + MU_V10_ATR0_OFFSET1
+ + (regIndex * 4));
+ } else {
+ /* Wait TX register to be empty. */
+ while (!(readl_relaxed(base + MU_ASR_OFFSET1) & mask))
+ ;
+ writel_relaxed(msg, base + MU_ATR0_OFFSET1 + (regIndex * 4));
+ }
+}
+
+
+/*
+ * Wait to receive message from the other core.
+ */
+void MU_ReceiveMsg(void __iomem *base, uint32_t regIndex, uint32_t *msg)
+{
+ uint32_t mask = MU_SR_RF0_MASK1 >> regIndex;
+
+ if (unlikely((readl_relaxed(base) >> 16) == MU_VER_ID_V10)) {
+ /* Wait RX register to be full. */
+ while (!(readl_relaxed(base + MU_V10_ASR_OFFSET1) & mask))
+ ;
+ *msg = readl_relaxed(base + MU_V10_ARR0_OFFSET1
+ + (regIndex * 4));
+ } else {
+ /* Wait RX register to be full. */
+ while (!(readl_relaxed(base + MU_ASR_OFFSET1) & mask))
+ ;
+ *msg = readl_relaxed(base + MU_ARR0_OFFSET1 + (regIndex * 4));
+ }
+}
+
+
+
+void MU_Init(void __iomem *base)
+{
+ uint32_t reg, offset;
+
+ offset = unlikely((readl_relaxed(base) >> 16) == MU_VER_ID_V10)
+ ? MU_V10_ACR_OFFSET1 : MU_ACR_OFFSET1;
+
+
+ reg = readl_relaxed(base + offset);
+ /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
+ reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1
+ | MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1 | MU_CR_Fn_MASK1);
+ writel_relaxed(reg, base + offset);
+}
+
+/**@}*/
+
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 0e7415f6d093..8658887136d0 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -380,6 +380,13 @@ config SPI_FSL_ESPI
From MPC8536, 85xx platform uses the controller, and all P10xx,
P20xx, P30xx,P40xx, P50xx uses this controller.
+config SPI_FSL_LPSPI
+ tristate "Freescale i.MX LPSPI controller"
+ depends on ARCH_MXC || COMPILE_TEST
+ select SPI_BITBANG
+ help
+ This enables Freescale i.MX LPSPI controllers in master mode.
+
config SPI_MESON_SPIFC
tristate "Amlogic Meson SPIFC controller"
depends on ARCH_MESON || COMPILE_TEST
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index aa939d955521..aaeb91e8e6ad 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
+obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o
obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o
obj-$(CONFIG_SPI_IMX) += spi-imx.o
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
new file mode 100644
index 000000000000..cf79a48da9c4
--- /dev/null
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -0,0 +1,500 @@
+/*
+ * Freescale i.MX7ULP LPSPI driver
+ *
+ * Copyright 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 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.
+ */
+#define DEBUG
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#define DRIVER_NAME "fsl_lpspi"
+
+/* i.MX7ULP LPSPI registers */
+#define IMX7ULP_VERID 0x0
+#define IMX7ULP_PARAM 0x4
+#define IMX7ULP_CR 0x10
+#define IMX7ULP_SR 0x14
+#define IMX7ULP_IER 0x18
+#define IMX7ULP_DER 0x1c
+#define IMX7ULP_CFGR0 0x20
+#define IMX7ULP_CFGR1 0x24
+#define IMX7ULP_DMR0 0x30
+#define IMX7ULP_DMR1 0x34
+#define IMX7ULP_CCR 0x40
+#define IMX7ULP_FCR 0x58
+#define IMX7ULP_FSR 0x5c
+#define IMX7ULP_TCR 0x60
+#define IMX7ULP_TDR 0x64
+#define IMX7ULP_RSR 0x70
+#define IMX7ULP_RDR 0x74
+
+/* General control register field define */
+#define CR_RRF (1 << 9)
+#define CR_RTF (1 << 8)
+#define CR_RST (1 << 1)
+#define CR_MEN (1 << 0)
+#define SR_TCF (1 << 10)
+#define SR_RDF (1 << 1)
+#define SR_TDF (1 << 0)
+#define IER_TCIE (1 << 10)
+#define IER_RDIE (1 << 1)
+#define IER_TDIE (1 << 0)
+#define CFGR1_PCSCFG (1 << 27) /* PCS[3:2] disabled */
+#define CFGR1_PCSPOL (1 << 8) /* PCS active high */
+#define CFGR1_NOSTALL (1 << 3) /* NO STALL */
+#define CFGR1_MASTER (1 << 0) /* MASTER MODE */
+#define RSR_RXEMPTY (1 << 1)
+#define TCR_CPOL (1 << 31)
+#define TCR_CPHA (1 << 30)
+#define TCR_CONT (1 << 21)
+#define TCR_CONTC (1 << 20)
+#define TCR_RXMSK (1 << 19)
+#define TCR_TXMSK (1 << 18)
+
+static int clkdivs[] = {1, 2, 4, 8, 16, 32, 64, 128};
+
+struct lpspi_config {
+ u8 bpw;
+ u8 chip_select;
+ u8 prescale;
+ u16 mode;
+ u32 speed_hz;
+};
+
+struct fsl_lpspi_data {
+ struct spi_bitbang bitbang;
+ struct device *dev;
+
+ struct completion xfer_done;
+ void __iomem *base;
+ struct clk *clk;
+
+ void *rx_buf;
+ const void *tx_buf;
+ void (*tx)(struct fsl_lpspi_data *);
+ void (*rx)(struct fsl_lpspi_data *);
+ struct lpspi_config config;
+
+ u8 txfifosize;
+ u8 rxfifosize;
+ unsigned remain;
+};
+
+static const struct of_device_id fsl_lpspi_dt_ids[] = {
+ { .compatible = "fsl,imx7ulp-spi", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_lpspi_dt_ids);
+
+#define LPSPI_BUF_RX(type) \
+static void fsl_lpspi_buf_rx_##type(struct fsl_lpspi_data *fsl_lpspi) \
+{ \
+ unsigned int val = readl(fsl_lpspi->base + IMX7ULP_RDR); \
+ \
+ if (fsl_lpspi->rx_buf) { \
+ *(type *)fsl_lpspi->rx_buf = val; \
+ fsl_lpspi->rx_buf += sizeof(type); \
+ } \
+}
+
+#define LPSPI_BUF_TX(type) \
+static void fsl_lpspi_buf_tx_##type(struct fsl_lpspi_data *fsl_lpspi) \
+{ \
+ type val = 0; \
+ \
+ if (fsl_lpspi->tx_buf) { \
+ val = *(type *)fsl_lpspi->tx_buf; \
+ fsl_lpspi->tx_buf += sizeof(type); \
+ } \
+ \
+ fsl_lpspi->remain -= sizeof(type); \
+ writel(val, fsl_lpspi->base + IMX7ULP_TDR); \
+}
+
+LPSPI_BUF_RX(u8)
+LPSPI_BUF_TX(u8)
+LPSPI_BUF_RX(u16)
+LPSPI_BUF_TX(u16)
+LPSPI_BUF_RX(u32)
+LPSPI_BUF_TX(u32)
+
+static void fsl_lpspi_intctrl(
+ struct fsl_lpspi_data *fsl_lpspi, unsigned int enable)
+{
+ writel(enable, fsl_lpspi->base + IMX7ULP_IER);
+}
+
+static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
+{
+ u8 txfifo_cnt;
+ u32 temp;
+
+ txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
+
+ while (txfifo_cnt < fsl_lpspi->txfifosize) {
+ if (!fsl_lpspi->remain)
+ break;
+ fsl_lpspi->tx(fsl_lpspi);
+ txfifo_cnt++;
+ }
+
+ if (txfifo_cnt < fsl_lpspi->txfifosize) {
+ temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
+ temp &= ~TCR_CONTC;
+ writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
+
+ fsl_lpspi_intctrl(fsl_lpspi, IER_TCIE);
+ } else
+ fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE);
+}
+
+static void fsl_lpspi_read_rx_fifo(struct fsl_lpspi_data *fsl_lpspi)
+{
+ while (!(readl(fsl_lpspi->base + IMX7ULP_RSR) & RSR_RXEMPTY))
+ fsl_lpspi->rx(fsl_lpspi);
+}
+
+static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi)
+{
+ u32 temp = 0;
+
+ temp |= TCR_CONT;
+ temp |= fsl_lpspi->config.bpw - 1;
+ temp |= fsl_lpspi->config.prescale << 27;
+ temp |= (fsl_lpspi->config.mode & 0x11) << 30;
+ temp |= (fsl_lpspi->config.chip_select & 0x3) << 24;
+
+ writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
+
+ dev_dbg(fsl_lpspi->dev, "TCR=0x%x\n", temp);
+}
+
+static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi)
+{
+ u32 temp;
+ u8 txwatermark, rxwatermark;
+
+ temp = readl(fsl_lpspi->base + IMX7ULP_PARAM);
+
+ fsl_lpspi->txfifosize = 1 << (temp & 0x0f);
+ fsl_lpspi->rxfifosize = 1 << ((temp >> 8) & 0x0f);
+
+ rxwatermark = fsl_lpspi->txfifosize >> 1;
+ txwatermark = fsl_lpspi->rxfifosize >> 1;
+ temp = txwatermark | rxwatermark << 16;
+
+ writel(temp, fsl_lpspi->base + IMX7ULP_FCR);
+
+ dev_dbg(fsl_lpspi->dev, "FCR=0x%x\n", temp);
+}
+
+static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
+{
+ u8 prescale;
+ unsigned int perclk_rate, scldiv;
+ struct lpspi_config config = fsl_lpspi->config;
+
+ perclk_rate = clk_get_rate(fsl_lpspi->clk);
+
+ for (prescale = 0; prescale < 8; prescale++) {
+ scldiv = perclk_rate / (clkdivs[prescale] * config.speed_hz) - 2;
+ if (scldiv < 256) {
+ fsl_lpspi->config.prescale = prescale;
+ break;
+ }
+ }
+
+ if (prescale == 8 && scldiv >= 256)
+ return -EINVAL;
+
+ writel(scldiv, fsl_lpspi->base + IMX7ULP_CCR);
+
+ dev_dbg(fsl_lpspi->dev, "perclk=%d, speed=%d, prescale =%d, scldiv=%d\n",
+ perclk_rate, config.speed_hz, prescale, scldiv);
+
+ return 0;
+}
+
+static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
+{
+ int ret;
+ u32 temp;
+
+ temp = CR_RST;
+ writel(temp, fsl_lpspi->base + IMX7ULP_CR);
+ writel(0, fsl_lpspi->base + IMX7ULP_CR);
+
+ ret = fsl_lpspi_set_bitrate(fsl_lpspi);
+ if (ret)
+ return ret;
+
+ fsl_lpspi_set_watermark(fsl_lpspi);
+
+ temp = CFGR1_PCSCFG | CFGR1_MASTER | CFGR1_NOSTALL;
+
+ /* chip select polarity */
+ if (fsl_lpspi->config.mode & SPI_CS_HIGH)
+ temp |= CFGR1_PCSPOL;
+
+ writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1);
+
+ temp = readl(fsl_lpspi->base + IMX7ULP_CR);
+ temp |= CR_RRF | CR_RTF | CR_MEN;
+ writel(temp, fsl_lpspi->base + IMX7ULP_CR);
+
+ return 0;
+}
+
+static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id)
+{
+ u32 temp;
+ struct fsl_lpspi_data *fsl_lpspi = dev_id;
+
+ fsl_lpspi_intctrl(fsl_lpspi, 0);
+ temp = readl(fsl_lpspi->base + IMX7ULP_SR);
+
+ fsl_lpspi_read_rx_fifo(fsl_lpspi);
+
+ if ((temp & SR_TDF) && !(temp & SR_TCF)) {
+ fsl_lpspi_write_tx_fifo(fsl_lpspi);
+ return IRQ_HANDLED;
+ }
+
+ if (temp & SR_TCF) {
+ complete(&fsl_lpspi->xfer_done);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int fsl_lpspi_setupxfer(struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(spi->master);
+
+ fsl_lpspi->config.mode = spi->mode;
+ fsl_lpspi->config.bpw = t ? t->bits_per_word : spi->bits_per_word;
+ fsl_lpspi->config.speed_hz = t ? t->speed_hz : spi->max_speed_hz;
+ fsl_lpspi->config.chip_select = spi->chip_select;
+
+ if (!fsl_lpspi->config.speed_hz)
+ fsl_lpspi->config.speed_hz = spi->max_speed_hz;
+ if (!fsl_lpspi->config.bpw)
+ fsl_lpspi->config.bpw = spi->bits_per_word;
+
+ /* Initialize the functions for transfer */
+ if (fsl_lpspi->config.bpw <= 8) {
+ fsl_lpspi->rx = fsl_lpspi_buf_rx_u8;
+ fsl_lpspi->tx = fsl_lpspi_buf_tx_u8;
+ } else if (fsl_lpspi->config.bpw <= 16) {
+ fsl_lpspi->rx = fsl_lpspi_buf_rx_u16;
+ fsl_lpspi->tx = fsl_lpspi_buf_tx_u16;
+ } else {
+ fsl_lpspi->rx = fsl_lpspi_buf_rx_u32;
+ fsl_lpspi->tx = fsl_lpspi_buf_tx_u32;
+ }
+
+ fsl_lpspi_config(fsl_lpspi);
+
+ return 0;
+}
+
+static int fsl_lpspi_transfer(struct spi_device *spi,
+ struct spi_transfer *transfer)
+{
+ struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(spi->master);
+
+ fsl_lpspi->tx_buf = transfer->tx_buf;
+ fsl_lpspi->rx_buf = transfer->rx_buf;
+ fsl_lpspi->remain = transfer->len;
+
+ reinit_completion(&fsl_lpspi->xfer_done);
+ fsl_lpspi_set_cmd(fsl_lpspi);
+ fsl_lpspi_write_tx_fifo(fsl_lpspi);
+ wait_for_completion(&fsl_lpspi->xfer_done);
+
+ return transfer->len;
+}
+
+/* The following funs are decided by spi framework */
+static void fsl_lpspi_chipselect(struct spi_device *spi, int is_active)
+{
+}
+
+static int fsl_lpspi_setup(struct spi_device *spi)
+{
+ return 0;
+}
+
+static void fsl_lpspi_cleanup(struct spi_device *spi)
+{
+}
+
+static int
+fsl_lpspi_prepare_message(struct spi_master *master, struct spi_message *msg)
+{
+ struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master);
+
+ return clk_enable(fsl_lpspi->clk);
+}
+
+static int
+fsl_lpspi_unprepare_message(struct spi_master *master, struct spi_message *msg)
+{
+ struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master);
+
+ clk_disable(fsl_lpspi->clk);
+
+ return 0;
+}
+
+static int fsl_lpspi_probe(struct platform_device *pdev)
+{
+ struct spi_master *master;
+ struct fsl_lpspi_data *fsl_lpspi;
+ struct resource *res;
+ int ret, irq;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_lpspi_data));
+ if (!master)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, master);
+
+ master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
+ master->bus_num = pdev->id;
+
+ fsl_lpspi = spi_master_get_devdata(master);
+ fsl_lpspi->bitbang.master = master;
+ fsl_lpspi->dev = &pdev->dev;
+
+ fsl_lpspi->bitbang.chipselect = fsl_lpspi_chipselect;
+ fsl_lpspi->bitbang.master->setup = fsl_lpspi_setup;
+ fsl_lpspi->bitbang.master->cleanup = fsl_lpspi_cleanup;
+ fsl_lpspi->bitbang.setup_transfer = fsl_lpspi_setupxfer;
+ fsl_lpspi->bitbang.txrx_bufs = fsl_lpspi_transfer;
+ fsl_lpspi->bitbang.master->prepare_message = fsl_lpspi_prepare_message;
+ fsl_lpspi->bitbang.master->unprepare_message = fsl_lpspi_unprepare_message;
+ fsl_lpspi->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+ fsl_lpspi->bitbang.master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
+
+ init_completion(&fsl_lpspi->xfer_done);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ fsl_lpspi->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(fsl_lpspi->base)) {
+ ret = PTR_ERR(fsl_lpspi->base);
+ goto out_master_put;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
+ goto out_master_put;
+ }
+
+ fsl_lpspi->clk = devm_clk_get(&pdev->dev, "ipg");
+ if (IS_ERR(fsl_lpspi->clk)) {
+ ret = PTR_ERR(fsl_lpspi->clk);
+ goto out_master_put;
+ }
+
+ master->dev.of_node = pdev->dev.of_node;
+ ret = spi_bitbang_start(&fsl_lpspi->bitbang);
+ if (ret) {
+ dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
+ goto out_master_put;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, fsl_lpspi_isr, 0,
+ dev_name(&pdev->dev), fsl_lpspi);
+ if (ret) {
+ dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret);
+ goto out_master_put;
+ }
+
+ ret = clk_prepare(fsl_lpspi->clk);
+ if (ret)
+ goto out_master_put;
+
+ return ret;
+
+out_master_put:
+ spi_master_put(master);
+
+ return ret;
+}
+
+static int fsl_lpspi_remove(struct platform_device *pdev)
+{
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master);
+
+ spi_bitbang_stop(&fsl_lpspi->bitbang);
+
+ clk_unprepare(fsl_lpspi->clk);
+ spi_master_put(master);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int fsl_lpspi_suspend(struct device *dev)
+{
+ pinctrl_pm_select_sleep_state(dev);
+ return 0;
+}
+
+static int fsl_lpspi_resume(struct device *dev)
+{
+ pinctrl_pm_select_default_state(dev);
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(imx_lpspi_pm, fsl_lpspi_suspend, fsl_lpspi_resume);
+#define IMX_LPSPI_PM (&imx_lpspi_pm)
+#else
+#define IMX_LPSPI_PM NULL
+#endif
+
+static struct platform_driver fsl_lpspi_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = fsl_lpspi_dt_ids,
+ .pm = IMX_LPSPI_PM,
+ },
+ .probe = fsl_lpspi_probe,
+ .remove = fsl_lpspi_remove,
+};
+module_platform_driver(fsl_lpspi_driver);
+
+MODULE_DESCRIPTION("SPI Master Controller driver");
+MODULE_AUTHOR("Gao Pan <pandy.gao@nxp.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index a6e34f05d44d..284a0de26fd8 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -68,6 +68,7 @@ enum spi_imx_devtype {
IMX31_CSPI,
IMX35_CSPI, /* CSPI on all i.mx except above */
IMX51_ECSPI, /* ECSPI on i.mx51 and later */
+ IMX6UL_ECSPI,
};
struct spi_imx_data;
@@ -124,7 +125,8 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
static inline int is_imx51_ecspi(struct spi_imx_data *d)
{
- return d->devtype_data->devtype == IMX51_ECSPI;
+ return d->devtype_data->devtype == IMX51_ECSPI ||
+ d->devtype_data->devtype == IMX6UL_ECSPI;
}
static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
@@ -326,10 +328,17 @@ static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
{
- u32 reg;
-
- reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
- reg |= MX51_ECSPI_CTRL_XCH;
+ u32 reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
+ /*
+ * To workaround ERR008517, SDMA script need use XCH instead of SMC
+ * just like PIO mode and it fix on i.mx6ul
+ */
+ if (!spi_imx->usedma)
+ reg |= MX51_ECSPI_CTRL_XCH;
+ else if (spi_imx->devtype_data->devtype == IMX6UL_ECSPI)
+ reg |= MX51_ECSPI_CTRL_SMC;
+ else
+ reg &= ~MX51_ECSPI_CTRL_SMC;
writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
}
@@ -340,6 +349,7 @@ static int mx51_ecspi_config(struct spi_device *spi,
u32 ctrl = MX51_ECSPI_CTRL_ENABLE;
u32 clk = config->speed_hz, delay, reg;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
+ int tx_wml = 0;
/*
* The hardware seems to have a race condition when changing modes. The
@@ -414,9 +424,11 @@ static int mx51_ecspi_config(struct spi_device *spi,
* Configure the DMA register: setup the watermark
* and enable DMA request.
*/
+ if (spi_imx->devtype_data->devtype == IMX6UL_ECSPI)
+ tx_wml = spi_imx->wml / 2;
writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml) |
- MX51_ECSPI_DMA_TX_WML(spi_imx->wml) |
+ MX51_ECSPI_DMA_TX_WML(tx_wml) |
MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) |
MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN |
MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA);
@@ -723,7 +735,16 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
.devtype = IMX51_ECSPI,
};
-static const struct platform_device_id spi_imx_devtype[] = {
+static struct spi_imx_devtype_data imx6ul_ecspi_devtype_data = {
+ .intctrl = mx51_ecspi_intctrl,
+ .config = mx51_ecspi_config,
+ .trigger = mx51_ecspi_trigger,
+ .rx_available = mx51_ecspi_rx_available,
+ .reset = mx51_ecspi_reset,
+ .devtype = IMX6UL_ECSPI,
+};
+
+static struct platform_device_id spi_imx_devtype[] = {
{
.name = "imx1-cspi",
.driver_data = (kernel_ulong_t) &imx1_cspi_devtype_data,
@@ -743,6 +764,9 @@ static const struct platform_device_id spi_imx_devtype[] = {
.name = "imx51-ecspi",
.driver_data = (kernel_ulong_t) &imx51_ecspi_devtype_data,
}, {
+ .name = "imx6ul-ecspi",
+ .driver_data = (kernel_ulong_t) &imx6ul_ecspi_devtype_data,
+ }, {
/* sentinel */
}
};
@@ -754,6 +778,7 @@ static const struct of_device_id spi_imx_dt_ids[] = {
{ .compatible = "fsl,imx31-cspi", .data = &imx31_cspi_devtype_data, },
{ .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, },
{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
+ { .compatible = "fsl,imx6ul-ecspi", .data = &imx6ul_ecspi_devtype_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spi_imx_dt_ids);
@@ -839,7 +864,7 @@ static int spi_imx_dma_configure(struct spi_master *master,
tx.direction = DMA_MEM_TO_DEV;
tx.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
tx.dst_addr_width = buswidth;
- tx.dst_maxburst = spi_imx->wml;
+ tx.dst_maxburst = spi_imx->wml / 2;
ret = dmaengine_slave_config(master->dma_tx, &tx);
if (ret) {
dev_err(spi_imx->dev, "TX dma configuration failed with %d\n", ret);
@@ -925,10 +950,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
{
int ret;
- /* use pio mode for i.mx6dl chip TKT238285 */
- if (of_machine_is_compatible("fsl,imx6dl"))
- return 0;
-
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
/* Prepare for TX DMA: */
@@ -1033,6 +1054,8 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
+ spi_imx->devtype_data->trigger(spi_imx);
+
/* Wait SDMA to finish the data transfer.*/
timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion,
transfer_timeout);
@@ -1121,13 +1144,13 @@ spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
int ret;
- ret = clk_enable(spi_imx->clk_per);
+ ret = clk_prepare_enable(spi_imx->clk_per);
if (ret)
return ret;
- ret = clk_enable(spi_imx->clk_ipg);
+ ret = clk_prepare_enable(spi_imx->clk_ipg);
if (ret) {
- clk_disable(spi_imx->clk_per);
+ clk_disable_unprepare(spi_imx->clk_per);
return ret;
}
@@ -1139,8 +1162,8 @@ spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg)
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
- clk_disable(spi_imx->clk_ipg);
- clk_disable(spi_imx->clk_per);
+ clk_disable_unprepare(spi_imx->clk_ipg);
+ clk_disable_unprepare(spi_imx->clk_per);
return 0;
}
@@ -1289,8 +1312,8 @@ static int spi_imx_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "probed\n");
- clk_disable(spi_imx->clk_ipg);
- clk_disable(spi_imx->clk_per);
+ clk_disable_unprepare(spi_imx->clk_ipg);
+ clk_disable_unprepare(spi_imx->clk_per);
return ret;
out_clk_put:
@@ -1330,11 +1353,31 @@ static int spi_imx_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int spi_imx_suspend(struct device *dev)
+{
+ pinctrl_pm_select_sleep_state(dev);
+ return 0;
+}
+
+static int spi_imx_resume(struct device *dev)
+{
+ pinctrl_pm_select_default_state(dev);
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(imx_spi_pm, spi_imx_suspend, spi_imx_resume);
+#define IMX_SPI_PM (&imx_spi_pm)
+#else
+#define IMX_SPI_PM NULL
+#endif
+
static struct platform_driver spi_imx_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = spi_imx_dt_ids,
- },
+ .pm = IMX_SPI_PM,
+ },
.id_table = spi_imx_devtype,
.probe = spi_imx_probe,
.remove = spi_imx_remove,
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 6db80635ace8..e0309c0a15b1 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -722,6 +722,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
int desc_len;
int sgs;
struct page *vm_page;
+ struct scatterlist *sg;
void *sg_buf;
size_t min;
int i, ret;
@@ -740,6 +741,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
if (ret != 0)
return ret;
+ sg = &sgt->sgl[0];
for (i = 0; i < sgs; i++) {
if (vmalloced_buf || kmap_buf) {
@@ -753,16 +755,17 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
sg_free_table(sgt);
return -ENOMEM;
}
- sg_set_page(&sgt->sgl[i], vm_page,
+ sg_set_page(sg, vm_page,
min, offset_in_page(buf));
} else {
min = min_t(size_t, len, desc_len);
sg_buf = buf;
- sg_set_buf(&sgt->sgl[i], sg_buf, min);
+ sg_set_buf(sg, sg_buf, min);
}
buf += min;
len -= min;
+ sg = sg_next(sg);
}
ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 2fa9745db614..27a8ba7ee973 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_MFD_NVEC) += nvec/
-obj-$(CONFIG_ANDROID) += android/
+obj-y += android/
obj-$(CONFIG_STAGING_BOARD) += board/
obj-$(CONFIG_LTE_GDM724X) += gdm724x/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 6c00d6f765c6..6b2b942ebfc3 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -24,8 +24,8 @@ config ANDROID_LOW_MEMORY_KILLER
scripts (/init.rc), and it defines priority values with minimum free memory size
for each priority.
-source "drivers/staging/android/ion/Kconfig"
-
endif # if ANDROID
+source "drivers/staging/android/ion/Kconfig"
+
endmenu
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index c8fb4134c55d..22ab23074c16 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -42,6 +42,13 @@ config ION_HISI
source "drivers/staging/android/ion/hisilicon/Kconfig"
+config ION_MXC
+ tristate "Ion for imx platform"
+ depends on ION
+ select VIDEOBUF2_DMA_CONTIG
+ help
+ Choose this option if you wish to use ion on imx platform.
+
config ION_OF
bool "Devicetree support for Ion"
depends on ION && OF_ADDRESS
@@ -52,3 +59,4 @@ config ION_OF
extensions
If using Ion and devicetree, you should say Y here
+
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index 5d630a088381..724f014cb005 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -9,5 +9,5 @@ endif
obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o
obj-$(CONFIG_ION_TEGRA) += tegra/
obj-$(CONFIG_ION_HISI) += hisilicon/
+obj-$(CONFIG_ION_MXC) += mxc/
obj-$(CONFIG_ION_OF) += ion_of.o
-
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 209a8f7ef02b..21c14a228ed5 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -3,6 +3,7 @@
* drivers/staging/android/ion/ion.c
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -361,6 +362,26 @@ struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
return handle;
}
+/* for used in mxc_ion.c */
+int ion_handle_put_wrap(struct ion_handle *handle)
+{
+ return ion_handle_put(handle);
+}
+
+struct ion_handle *ion_handle_get_by_id_wrap(struct ion_client *client,
+ int id)
+{
+ return ion_handle_get_by_id(client, id);
+}
+
+struct device *ion_device_get_by_client(struct ion_client *client)
+{
+ if (client)
+ return client->dev->dev.this_device;
+ else
+ return NULL;
+}
+
static bool ion_handle_validate(struct ion_client *client,
struct ion_handle *handle)
{
@@ -1013,6 +1034,21 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
return 0;
}
+static void *ion_dma_buf_vmap(struct dma_buf *dmabuf)
+{
+ struct ion_buffer *buffer = dmabuf->priv;
+
+ if (ion_dma_buf_begin_cpu_access(dmabuf, DMA_NONE) != 0)
+ return NULL;
+
+ return buffer->vaddr;
+}
+
+static void ion_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
+{
+ ion_dma_buf_end_cpu_access(dmabuf, DMA_NONE);
+}
+
static struct dma_buf_ops dma_buf_ops = {
.map_dma_buf = ion_map_dma_buf,
.unmap_dma_buf = ion_unmap_dma_buf,
@@ -1024,6 +1060,8 @@ static struct dma_buf_ops dma_buf_ops = {
.kunmap_atomic = ion_dma_buf_kunmap,
.kmap = ion_dma_buf_kmap,
.kunmap = ion_dma_buf_kunmap,
+ .vmap = ion_dma_buf_vmap,
+ .vunmap = ion_dma_buf_vunmap,
};
struct dma_buf *ion_share_dma_buf(struct ion_client *client,
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index 3c3b3245275d..2d4ef0d93d99 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -2,6 +2,7 @@
* drivers/staging/android/ion/ion_priv.h
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -470,4 +471,9 @@ int ion_handle_put(struct ion_handle *handle);
int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query);
+int ion_handle_put_wrap(struct ion_handle *handle);
+struct ion_handle *ion_handle_get_by_id_wrap(struct ion_client *client,
+ int id);
+struct device *ion_device_get_by_client(struct ion_client *client);
+
#endif /* _ION_PRIV_H */
diff --git a/drivers/staging/android/ion/mxc/Makefile b/drivers/staging/android/ion/mxc/Makefile
new file mode 100644
index 000000000000..df308e51837a
--- /dev/null
+++ b/drivers/staging/android/ion/mxc/Makefile
@@ -0,0 +1,2 @@
+ccflags-y += -I../
+obj-y += mxc_ion.o
diff --git a/drivers/staging/android/ion/mxc/mxc_ion.c b/drivers/staging/android/ion/mxc/mxc_ion.c
new file mode 100644
index 000000000000..14ae747a5385
--- /dev/null
+++ b/drivers/staging/android/ion/mxc/mxc_ion.c
@@ -0,0 +1,308 @@
+/*
+ * drivers/gpu/mxc/mxc_ion.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2012-2016 Freescale Semiconductor, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/uaccess.h>
+#include <media/videobuf2-dma-contig.h>
+#include <linux/dma-buf.h>
+
+#include "../ion_priv.h"
+
+static struct ion_device *idev;
+static int num_heaps = 1;
+static struct ion_heap **heaps;
+static int cacheable;
+
+struct ion_platform_data *
+mxc_ion_parse_of(struct platform_device *pdev)
+{
+ struct ion_platform_data *pdata = 0;
+ const struct device_node *node = pdev->dev.of_node;
+ int ret = 0;
+ unsigned int val = 0;
+ struct ion_platform_heap *heap = NULL;
+
+ pdata = kzalloc(sizeof(struct ion_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ heap = kzalloc(sizeof(struct ion_platform_heap), GFP_KERNEL);
+ if (!heap) {
+ kfree(pdata);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ heap->type = ION_HEAP_TYPE_DMA;
+ heap->priv = &pdev->dev;
+ heap->name = "mxc_ion";
+
+ pdata->heaps = heap;
+ pdata->nr = num_heaps;
+
+ ret = of_property_read_u32(node, "fsl,heap-cacheable", &val);
+ if (!ret)
+ cacheable = 1;
+
+ val = 0;
+ ret = of_property_read_u32(node, "fsl,heap-id", &val);
+ if (!ret)
+ heap->id = val;
+ else
+ heap->id = 0;
+
+ return pdata;
+}
+
+static long
+mxc_custom_ioctl(struct ion_client *client, unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+ case ION_IOC_PHYS:
+ {
+ struct ion_handle *handle;
+ struct ion_phys_data data;
+ struct device *dev;
+ void *vaddr;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_data)))
+ return -EFAULT;
+ handle = ion_handle_get_by_id_wrap(client, data.handle);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ vaddr = ion_map_kernel(client, handle);
+ ion_handle_put_wrap(handle);
+
+ if (IS_ERR(vaddr))
+ return PTR_ERR(vaddr);
+
+ dev = ion_device_get_by_client(client);
+ data.phys = virt_to_dma(dev, vaddr);
+
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_data)))
+ return -EFAULT;
+ return 0;
+ }
+ case ION_IOC_PHYS_DMA:
+ {
+ int ret = 0;
+ struct device *dev = NULL;
+ struct dma_buf *dmabuf = NULL;
+ unsigned long phys = 0;
+ u64 dma_mask = DMA_BIT_MASK(32);
+ size_t len = 0;
+ struct ion_phys_dma_data data;
+ const struct vb2_mem_ops *mem_ops =
+ &vb2_dma_contig_memops;
+ dma_addr_t *addr;
+ void *mem_priv;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_dma_data)))
+ return -EFAULT;
+
+ /* Get physical address from dmafd */
+ dmabuf = dma_buf_get(data.dmafd);
+ if (!dmabuf)
+ return -1;
+
+ dev = ion_device_get_by_client(client);
+ dev->dma_mask = &dma_mask;
+
+ mem_priv = mem_ops->attach_dmabuf(dev,
+ dmabuf, dmabuf->size,
+ DMA_BIDIRECTIONAL);
+ if (IS_ERR(mem_priv))
+ goto err1;
+ ret = mem_ops->map_dmabuf(mem_priv);
+ if (ret)
+ goto err0;
+
+ addr = mem_ops->cookie(mem_priv);
+ phys = *addr;
+ len = dmabuf->size;
+
+ data.phys = phys;
+ data.size = len;
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_dma_data))) {
+ ret = -EFAULT;
+ }
+
+ /* unmap and detach */
+ mem_ops->unmap_dmabuf(mem_priv);
+err0:
+ mem_ops->detach_dmabuf(mem_priv);
+err1:
+ dma_buf_put(dmabuf);
+
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
+ case ION_IOC_PHYS_VIRT:
+ {
+ struct device *dev = NULL;
+ u64 dma_mask = DMA_BIT_MASK(32);
+ struct ion_phys_virt_data data;
+ const struct vb2_mem_ops *mem_ops =
+ &vb2_dma_contig_memops;
+ dma_addr_t *addr;
+ void *mem_priv;
+
+ if (copy_from_user(&data, (void __user *) arg,
+ sizeof(struct ion_phys_virt_data)))
+ return -EFAULT;
+
+ /* Get physical address from virtual address */
+ if (!data.virt)
+ return -1;
+
+ dev = ion_device_get_by_client(client);
+ dev->dma_mask = &dma_mask;
+
+ mem_priv = mem_ops->get_userptr(dev,
+ data.virt, data.size,
+ DMA_BIDIRECTIONAL);
+ if (IS_ERR(mem_priv))
+ return -1;
+
+ addr = mem_ops->cookie(mem_priv);
+ mem_ops->put_userptr(mem_priv);
+
+ data.phys = *addr;
+ if (copy_to_user((void __user *) arg, &data,
+ sizeof(struct ion_phys_virt_data)))
+ return -EFAULT;
+ return 0;
+ }
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+int
+mxc_ion_probe(struct platform_device *pdev)
+{
+ struct ion_platform_data *pdata = NULL;
+ int pdata_is_created = 0;
+ int err;
+ int i;
+
+ if (pdev->dev.of_node) {
+ pdata = mxc_ion_parse_of(pdev);
+ pdata_is_created = 1;
+ } else {
+ pdata = pdev->dev.platform_data;
+ }
+
+ if (IS_ERR_OR_NULL(pdata))
+ return PTR_ERR(pdata);
+
+ num_heaps = pdata->nr;
+
+ heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL);
+
+ idev = ion_device_create(mxc_custom_ioctl);
+ if (IS_ERR_OR_NULL(idev)) {
+ err = PTR_ERR(idev);
+ goto err;
+ }
+
+ /* create the heaps as specified in the board file */
+ for (i = 0; i < num_heaps; i++) {
+ struct ion_platform_heap *heap_data = &pdata->heaps[i];
+
+ heaps[i] = ion_heap_create(heap_data);
+ if (IS_ERR_OR_NULL(heaps[i])) {
+ err = PTR_ERR(heaps[i]);
+ heaps[i] = NULL;
+ goto err;
+ }
+ ion_device_add_heap(idev, heaps[i]);
+ }
+ platform_set_drvdata(pdev, idev);
+ return 0;
+err:
+ for (i = 0; i < num_heaps; i++) {
+ if (heaps[i])
+ ion_heap_destroy(heaps[i]);
+ }
+ kfree(heaps);
+ if (pdata_is_created) {
+ kfree(pdata->heaps);
+ kfree(pdata);
+ }
+ return err;
+}
+
+int
+mxc_ion_remove(struct platform_device *pdev)
+{
+ struct ion_device *idev = platform_get_drvdata(pdev);
+ int i;
+
+ ion_device_destroy(idev);
+ for (i = 0; i < num_heaps; i++)
+ ion_heap_destroy(heaps[i]);
+ kfree(heaps);
+ return 0;
+}
+
+static struct of_device_id ion_match_table[] = {
+ {.compatible = "fsl,mxc-ion"},
+ {},
+};
+
+static struct platform_driver ion_driver = {
+ .probe = mxc_ion_probe,
+ .remove = mxc_ion_remove,
+ .driver = {
+ .name = "ion-mxc",
+ .of_match_table = ion_match_table,
+ },
+};
+
+static int __init
+ion_init(void)
+{
+ return platform_driver_register(&ion_driver);
+}
+
+static void __exit
+ion_exit(void)
+{
+ platform_driver_unregister(&ion_driver);
+}
+
+module_init(ion_init);
+module_exit(ion_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC ion allocator driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("fb");
diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h
index 14cd8738ecfc..401d59edcd0f 100644
--- a/drivers/staging/android/uapi/ion.h
+++ b/drivers/staging/android/uapi/ion.h
@@ -2,6 +2,7 @@
* drivers/staging/android/uapi/ion.h
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -46,6 +47,7 @@ enum ion_heap_type {
*/
};
+#define ION_CMA_HEAP_ID 0
#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
/**
@@ -158,6 +160,23 @@ struct ion_heap_query {
__u32 reserved2;
};
+struct ion_phys_data {
+ ion_user_handle_t handle;
+ unsigned long phys;
+};
+
+struct ion_phys_dma_data {
+ unsigned long phys;
+ size_t size;
+ int dmafd;
+};
+
+struct ion_phys_virt_data {
+ unsigned long virt;
+ unsigned long phys;
+ size_t size;
+};
+
#define ION_IOC_MAGIC 'I'
/**
@@ -233,4 +252,10 @@ struct ion_heap_query {
#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, \
struct ion_heap_query)
+#define ION_IOC_PHYS _IOWR(ION_IOC_MAGIC, 8, struct ion_phys_data)
+
+#define ION_IOC_PHYS_DMA _IOWR(ION_IOC_MAGIC, 9, struct ion_phys_dma_data)
+
+#define ION_IOC_PHYS_VIRT _IOWR(ION_IOC_MAGIC, 10, struct ion_phys_virt_data)
+
#endif /* _UAPI_LINUX_ION_H */
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 6356295672cb..9e35c5161a02 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -215,6 +215,13 @@ config QORIQ_THERMAL
cpufreq is used as the cooling device to throttle CPUs when the
passive trip is crossed.
+config DEVICE_THERMAL
+ tristate "generic device cooling support"
+ help
+ Support for device cooling.
+ It supports notification of crossing passive trip for devices,
+ devices need to do their own actions to cool down the SOC.
+
config SPEAR_THERMAL
tristate "SPEAr thermal sensor driver"
depends on PLAT_SPEAR || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c92eb22a41ff..842efac4711f 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
+obj-$(CONFIG_DEVICE_THERMAL) += device_cooling.o
obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
diff --git a/drivers/thermal/device_cooling.c b/drivers/thermal/device_cooling.c
new file mode 100644
index 000000000000..844b074a2532
--- /dev/null
+++ b/drivers/thermal/device_cooling.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2013-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/module.h>
+#include <linux/thermal.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+struct devfreq_cooling_device {
+ int id;
+ struct thermal_cooling_device *cool_dev;
+ unsigned int devfreq_state;
+};
+
+static DEFINE_IDR(devfreq_idr);
+static DEFINE_MUTEX(devfreq_cooling_lock);
+
+#define MAX_STATE 1
+
+static BLOCKING_NOTIFIER_HEAD(devfreq_cooling_chain_head);
+
+int register_devfreq_cooling_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(
+ &devfreq_cooling_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(register_devfreq_cooling_notifier);
+
+int unregister_devfreq_cooling_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(
+ &devfreq_cooling_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_devfreq_cooling_notifier);
+
+static int devfreq_cooling_notifier_call_chain(unsigned long val)
+{
+ return (blocking_notifier_call_chain(
+ &devfreq_cooling_chain_head, val, NULL)
+ == NOTIFY_BAD) ? -EINVAL : 0;
+}
+
+static int devfreq_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state)
+{
+ struct devfreq_cooling_device *devfreq_device = cdev->devdata;
+ int ret;
+
+ ret = devfreq_cooling_notifier_call_chain(state);
+ if (ret)
+ return -EINVAL;
+ devfreq_device->devfreq_state = state;
+
+ return 0;
+}
+
+static int devfreq_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ *state = MAX_STATE;
+
+ return 0;
+}
+
+static int devfreq_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct devfreq_cooling_device *devfreq_device = cdev->devdata;
+
+ *state = devfreq_device->devfreq_state;
+
+ return 0;
+}
+
+static struct thermal_cooling_device_ops const devfreq_cooling_ops = {
+ .get_max_state = devfreq_get_max_state,
+ .get_cur_state = devfreq_get_cur_state,
+ .set_cur_state = devfreq_set_cur_state,
+};
+
+static int get_idr(struct idr *idr, int *id)
+{
+ int ret;
+
+ mutex_lock(&devfreq_cooling_lock);
+ ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+ mutex_unlock(&devfreq_cooling_lock);
+ if (unlikely(ret < 0))
+ return ret;
+ *id = ret;
+
+ return 0;
+}
+
+static void release_idr(struct idr *idr, int id)
+{
+ mutex_lock(&devfreq_cooling_lock);
+ idr_remove(idr, id);
+ mutex_unlock(&devfreq_cooling_lock);
+}
+
+struct thermal_cooling_device *devfreq_cooling_register(void)
+{
+ struct thermal_cooling_device *cool_dev;
+ struct devfreq_cooling_device *devfreq_dev = NULL;
+ char dev_name[THERMAL_NAME_LENGTH];
+ int ret = 0;
+
+ devfreq_dev = kzalloc(sizeof(struct devfreq_cooling_device),
+ GFP_KERNEL);
+ if (!devfreq_dev)
+ return ERR_PTR(-ENOMEM);
+
+ ret = get_idr(&devfreq_idr, &devfreq_dev->id);
+ if (ret) {
+ kfree(devfreq_dev);
+ return ERR_PTR(-EINVAL);
+ }
+
+ snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d",
+ devfreq_dev->id);
+
+ cool_dev = thermal_cooling_device_register(dev_name, devfreq_dev,
+ &devfreq_cooling_ops);
+ if (!cool_dev) {
+ release_idr(&devfreq_idr, devfreq_dev->id);
+ kfree(devfreq_dev);
+ return ERR_PTR(-EINVAL);
+ }
+ devfreq_dev->cool_dev = cool_dev;
+ devfreq_dev->devfreq_state = 0;
+
+ return cool_dev;
+}
+EXPORT_SYMBOL_GPL(devfreq_cooling_register);
+
+void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
+{
+ struct devfreq_cooling_device *devfreq_dev = cdev->devdata;
+
+ thermal_cooling_device_unregister(devfreq_dev->cool_dev);
+ release_idr(&devfreq_idr, devfreq_dev->id);
+ kfree(devfreq_dev);
+}
+EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 06912f0602b7..586b3f16023e 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -1,16 +1,18 @@
/*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-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/clk.h>
#include <linux/cpu_cooling.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/device_cooling.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -37,17 +39,20 @@
#define MISC1_IRQ_TEMPLOW (1 << 28)
#define MISC1_IRQ_TEMPPANIC (1 << 27)
-#define TEMPSENSE0 0x0180
-#define TEMPSENSE0_ALARM_VALUE_SHIFT 20
-#define TEMPSENSE0_ALARM_VALUE_MASK (0xfff << TEMPSENSE0_ALARM_VALUE_SHIFT)
-#define TEMPSENSE0_TEMP_CNT_SHIFT 8
-#define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
-#define TEMPSENSE0_FINISHED (1 << 2)
-#define TEMPSENSE0_MEASURE_TEMP (1 << 1)
-#define TEMPSENSE0_POWER_DOWN (1 << 0)
-
-#define TEMPSENSE1 0x0190
-#define TEMPSENSE1_MEASURE_FREQ 0xffff
+/* i.MX6 specific */
+#define IMX6_TEMPSENSE0 0X180
+#define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT 20
+#define IMX6_TEMPSENSE0_ALARM_VALUE_MASK (0xfff << 20)
+#define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT 8
+#define IMX6_TEMPSENSE0_TEMP_CNT_MASK (0xfff << 8)
+#define IMX6_TEMPSENSE0_FINISHED (1 << 2)
+#define IMX6_TEMPSENSE0_MEASURE_TEMP (1 << 1)
+#define IMX6_TEMPSENSE0_POWER_DOWN (1 << 0)
+
+#define IMX6_TEMPSENSE1 0X190
+#define IMX6_TEMPSENSE1_MEASURE_FREQ 0xffff
+#define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT 0
+
/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
#define TEMPSENSE2 0x0290
#define TEMPSENSE2_LOW_VALUE_SHIFT 0
@@ -58,6 +63,29 @@
#define OCOTP_MEM0 0x0480
#define OCOTP_ANA1 0x04e0
+/* i.MX7D specific */
+#define IMX7_ANADIG_DIGPROG 0x800
+#define IMX7_TEMPSENSE0 0X300
+#define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT 18
+#define IMX7_TEMPSENSE0_PANIC_ALARM_MASK (0x1ff << 18)
+#define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT 9
+#define IMX7_TEMPSENSE0_HIGH_ALARM_MASK (0x1ff << 9)
+#define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT 0
+#define IMX7_TEMPSENSE0_LOW_ALARM_MASK 0x1ff
+
+#define IMX7_TEMPSENSE1 0X310
+#define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT 16
+#define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK (0xffff << 16)
+#define IMX7_TEMPSENSE1_FINISHED (1 << 11)
+#define IMX7_TEMPSENSE1_MEASURE_TEMP (1 << 10)
+#define IMX7_TEMPSENSE1_POWER_DOWN (1 << 9)
+#define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT 0
+#define IMX7_TEMPSENSE1_TEMP_VALUE_MASK 0x1ff
+
+#define IMX6_OCOTP_ANA1 0x04e0
+#define IMX7_OCOTP_ANA1 0x04f0
+#define IMX7_OCOTP_TESTER3 0x0440
+
/* The driver supports 1 passive trip point and 1 critical trip point */
enum imx_thermal_trip {
IMX_TRIP_PASSIVE,
@@ -65,31 +93,133 @@ enum imx_thermal_trip {
IMX_TRIP_NUM,
};
+#define IMX_TEMP_PASSIVE_COOL_DELTA 10000
+
#define IMX_POLLING_DELAY 2000 /* millisecond */
#define IMX_PASSIVE_DELAY 1000
#define FACTOR0 10000000
-#define FACTOR1 15976
-#define FACTOR2 4297157
+#define FACTOR1 15423
+#define FACTOR2 4148468
+#define OFFSET 3580661
#define TEMPMON_IMX6Q 1
#define TEMPMON_IMX6SX 2
+#define TEMPMON_IMX7 3
+
+/* the register offsets and bitfields may change across
+ * i.MX SOCs, use below struct as a description of the
+ * register.
+ */
struct thermal_soc_data {
+ u32 sensor_ctrl; /* tempmon sensor basic control */
+ u32 power_down_mask;
+ u32 measure_temp_mask;
+
+ u32 measure_freq_ctrl;
+ u32 measure_freq_mask;
+ u32 measure_freq_shift;
+
+ u32 temp_data;
+ u32 temp_value_mask;
+ u32 temp_value_shift;
+ u32 temp_valid_mask;
+
+ u32 panic_alarm_ctrl;
+ u32 panic_alarm_mask;
+ u32 panic_alarm_shift;
+
+ u32 high_alarm_ctrl;
+ u32 high_alarm_mask;
+ u32 high_alarm_shift;
+
+ u32 low_alarm_ctrl;
+ u32 low_alarm_mask;
+ u32 low_alarm_shift;
+
u32 version;
};
static struct thermal_soc_data thermal_imx6q_data = {
.version = TEMPMON_IMX6Q,
+
+ .sensor_ctrl = IMX6_TEMPSENSE0,
+ .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
+ .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
+
+ .measure_freq_ctrl = IMX6_TEMPSENSE1,
+ .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
+ .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
+
+ .temp_data = IMX6_TEMPSENSE0,
+ .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
+ .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
+ .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
+
+ .high_alarm_ctrl = IMX6_TEMPSENSE0,
+ .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
+ .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
};
static struct thermal_soc_data thermal_imx6sx_data = {
.version = TEMPMON_IMX6SX,
+
+ .sensor_ctrl = IMX6_TEMPSENSE0,
+ .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
+ .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
+
+ .measure_freq_ctrl = IMX6_TEMPSENSE1,
+ .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
+ .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
+
+ .temp_data = IMX6_TEMPSENSE0,
+ .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
+ .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
+ .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
+
+ .high_alarm_ctrl = IMX6_TEMPSENSE0,
+ .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
+ .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
+
+ .panic_alarm_ctrl = TEMPSENSE2,
+ .panic_alarm_mask = TEMPSENSE2_PANIC_VALUE_MASK,
+ .panic_alarm_shift = TEMPSENSE2_PANIC_VALUE_SHIFT,
+};
+
+static struct thermal_soc_data thermal_imx7d_data = {
+ .version = TEMPMON_IMX7,
+
+ .sensor_ctrl = IMX7_TEMPSENSE1,
+ .power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN,
+ .measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP,
+
+ .measure_freq_ctrl = IMX7_TEMPSENSE1,
+ .measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT,
+ .measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK,
+
+ .temp_data = IMX7_TEMPSENSE1,
+ .temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK,
+ .temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT,
+ .temp_valid_mask = IMX7_TEMPSENSE1_FINISHED,
+
+ .panic_alarm_ctrl = IMX7_TEMPSENSE1,
+ .panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK,
+ .panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT,
+
+ .high_alarm_ctrl = IMX7_TEMPSENSE0,
+ .high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK,
+ .high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT,
+
+ .low_alarm_ctrl = IMX7_TEMPSENSE0,
+ .low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK,
+ .low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT,
+
};
struct imx_thermal_data {
struct thermal_zone_device *tz;
- struct thermal_cooling_device *cdev;
+ struct thermal_cooling_device *cdev[2];
enum thermal_device_mode mode;
struct regmap *tempmon;
u32 c1, c2; /* See formula in imx_get_sensor_data() */
@@ -101,55 +231,78 @@ struct imx_thermal_data {
bool irq_enabled;
int irq;
struct clk *thermal_clk;
+ struct mutex mutex;
const struct thermal_soc_data *socdata;
const char *temp_grade;
};
+static struct imx_thermal_data *imx_thermal_data;
+static int skip_finish_check;
+static u32 imx7_lpsr_save[2];
+
static void imx_set_panic_temp(struct imx_thermal_data *data,
int panic_temp)
{
+ const struct thermal_soc_data *soc_data = data->socdata;
struct regmap *map = data->tempmon;
int critical_value;
- critical_value = (data->c2 - panic_temp) / data->c1;
- regmap_write(map, TEMPSENSE2 + REG_CLR, TEMPSENSE2_PANIC_VALUE_MASK);
- regmap_write(map, TEMPSENSE2 + REG_SET, critical_value <<
- TEMPSENSE2_PANIC_VALUE_SHIFT);
+ if (data->socdata->version == TEMPMON_IMX7)
+ critical_value = panic_temp / 1000 + data->c1 - 25;
+ else
+ critical_value = (data->c2 - panic_temp) / data->c1;
+
+ regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR,
+ soc_data->panic_alarm_mask);
+ regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET,
+ critical_value << soc_data->panic_alarm_shift);
}
static void imx_set_alarm_temp(struct imx_thermal_data *data,
int alarm_temp)
{
+ const struct thermal_soc_data *soc_data = data->socdata;
struct regmap *map = data->tempmon;
int alarm_value;
data->alarm_temp = alarm_temp;
- alarm_value = (data->c2 - alarm_temp) / data->c1;
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
- regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
- TEMPSENSE0_ALARM_VALUE_SHIFT);
+
+ if (data->socdata->version == TEMPMON_IMX7)
+ alarm_value = alarm_temp / 1000 + data->c1 - 25;
+ else
+ alarm_value = (data->c2 - alarm_temp) / data->c1;
+
+ regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR,
+ soc_data->high_alarm_mask);
+ regmap_write(map, soc_data->high_alarm_ctrl + REG_SET,
+ alarm_value << soc_data->high_alarm_shift);
}
static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
{
struct imx_thermal_data *data = tz->devdata;
+ const struct thermal_soc_data *soc_data = data->socdata;
struct regmap *map = data->tempmon;
unsigned int n_meas;
bool wait;
u32 val;
+ mutex_lock(&data->mutex);
if (data->mode == THERMAL_DEVICE_ENABLED) {
/* Check if a measurement is currently in progress */
- regmap_read(map, TEMPSENSE0, &val);
- wait = !(val & TEMPSENSE0_FINISHED);
+ regmap_read(map, soc_data->temp_data, &val);
+ wait = !(val & soc_data->temp_valid_mask);
} else {
/*
* Every time we measure the temperature, we will power on the
* temperature sensor, enable measurements, take a reading,
* disable measurements, power off the temperature sensor.
*/
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+ clk_prepare_enable(data->thermal_clk);
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->power_down_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->measure_temp_mask);
wait = true;
}
@@ -158,25 +311,41 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
* According to the temp sensor designers, it may require up to ~17us
* to complete a measurement.
*/
- if (wait)
- usleep_range(20, 50);
-
- regmap_read(map, TEMPSENSE0, &val);
+ if (wait) {
+ /*
+ * On i.MX7 TO1.0, the finish bit can only keep 1us after
+ * the measured data available. It is hard for software to
+ * polling this bit. So wait for 20ms to make sure the
+ * measured data is valid.
+ */
+ if (data->socdata->version == TEMPMON_IMX7 && skip_finish_check)
+ msleep(20);
+ else
+ usleep_range(20, 50);
+ regmap_read(map, soc_data->temp_data, &val);
+ }
if (data->mode != THERMAL_DEVICE_ENABLED) {
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->measure_temp_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->power_down_mask);
+ clk_disable_unprepare(data->thermal_clk);
}
- if ((val & TEMPSENSE0_FINISHED) == 0) {
+ if (!skip_finish_check && ((val & soc_data->temp_valid_mask) == 0)) {
dev_dbg(&tz->device, "temp measurement never finished\n");
+ mutex_unlock(&data->mutex);
return -EAGAIN;
}
- n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
-
+ n_meas = (val & soc_data->temp_value_mask) >> soc_data->temp_value_shift;
/* See imx_get_sensor_data() for formula derivation */
*temp = data->c2 - n_meas * data->c1;
+ if (data->socdata->version == TEMPMON_IMX7)
+ *temp = (n_meas - data->c1 + 25) * 1000;
+ else
+ *temp = data->c2 - n_meas * data->c1;
/* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
if (data->socdata->version == TEMPMON_IMX6Q) {
@@ -201,6 +370,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
data->irq_enabled = true;
enable_irq(data->irq);
}
+ mutex_unlock(&data->mutex);
return 0;
}
@@ -219,22 +389,26 @@ static int imx_set_mode(struct thermal_zone_device *tz,
enum thermal_device_mode mode)
{
struct imx_thermal_data *data = tz->devdata;
+ const struct thermal_soc_data *soc_data = data->socdata;
struct regmap *map = data->tempmon;
if (mode == THERMAL_DEVICE_ENABLED) {
tz->polling_delay = IMX_POLLING_DELAY;
tz->passive_delay = IMX_PASSIVE_DELAY;
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
-
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->power_down_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->measure_temp_mask);
if (!data->irq_enabled) {
data->irq_enabled = true;
enable_irq(data->irq);
}
} else {
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->measure_temp_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->power_down_mask);
tz->polling_delay = 0;
tz->passive_delay = 0;
@@ -282,17 +456,18 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
{
struct imx_thermal_data *data = tz->devdata;
- /* do not allow changing critical threshold */
- if (trip == IMX_TRIP_CRITICAL)
- return -EPERM;
-
- /* do not allow passive to be set higher than critical */
- if (temp < 0 || temp > data->temp_critical)
- return -EINVAL;
-
- data->temp_passive = temp;
+ if (trip == IMX_TRIP_CRITICAL) {
+ data->temp_critical = temp;
+ if (data->socdata->version == TEMPMON_IMX6SX)
+ imx_set_panic_temp(data, temp);
+ }
- imx_set_alarm_temp(data, temp);
+ if (trip == IMX_TRIP_PASSIVE) {
+ if (temp > (data->temp_max - (1000 * 10)))
+ return -EINVAL;
+ data->temp_passive = temp;
+ imx_set_alarm_temp(data, temp);
+ }
return 0;
}
@@ -332,6 +507,23 @@ static int imx_unbind(struct thermal_zone_device *tz,
return 0;
}
+static int imx_get_trend(struct thermal_zone_device *tz,
+ int trip, enum thermal_trend *trend)
+{
+ int ret;
+ int trip_temp;
+
+ ret = imx_get_trip_temp(tz, trip, &trip_temp);
+ if (ret < 0)
+ return ret;
+
+ if (tz->temperature >= (trip_temp - IMX_TEMP_PASSIVE_COOL_DELTA))
+ *trend = THERMAL_TREND_RAISE_FULL;
+ else
+ *trend = THERMAL_TREND_DROP_FULL;
+
+ return 0;
+}
static struct thermal_zone_device_ops imx_tz_ops = {
.bind = imx_bind,
.unbind = imx_unbind,
@@ -342,69 +534,102 @@ static struct thermal_zone_device_ops imx_tz_ops = {
.get_trip_temp = imx_get_trip_temp,
.get_crit_temp = imx_get_crit_temp,
.set_trip_temp = imx_set_trip_temp,
+ .get_trend = imx_get_trend,
};
-static int imx_get_sensor_data(struct platform_device *pdev)
+static inline void imx6_calibrate_data(struct imx_thermal_data *data, u32 val)
{
- struct imx_thermal_data *data = platform_get_drvdata(pdev);
- struct regmap *map;
- int t1, n1;
- int ret;
- u32 val;
+ int t1, t2, n1, n2;
u64 temp64;
-
- map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
- "fsl,tempmon-data");
- if (IS_ERR(map)) {
- ret = PTR_ERR(map);
- dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
- return ret;
- }
-
- ret = regmap_read(map, OCOTP_ANA1, &val);
- if (ret) {
- dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
- return ret;
- }
-
- if (val == 0 || val == ~0) {
- dev_err(&pdev->dev, "invalid sensor calibration data\n");
- return -EINVAL;
- }
-
/*
* Sensor data layout:
* [31:20] - sensor value @ 25C
+ * [19:8] - sensor value of hot
+ * [7:0] - hot temperature value
* Use universal formula now and only need sensor value @ 25C
* slope = 0.4297157 - (0.0015976 * 25C fuse)
*/
n1 = val >> 20;
+ n2 = (val & 0xfff00) >> 8;
+ t2 = val & 0xff;
t1 = 25; /* t1 always 25C */
/*
* Derived from linear interpolation:
* slope = 0.4297157 - (0.0015976 * 25C fuse)
* slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
+ * offset = OFFSET / 1000000
* (Nmeas - n1) / (Tmeas - t1) = slope
* We want to reduce this down to the minimum computation necessary
* for each temperature read. Also, we want Tmeas in millicelsius
* and we don't want to lose precision from integer division. So...
- * Tmeas = (Nmeas - n1) / slope + t1
- * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1
- * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1
+ * Tmeas = (Nmeas - n1) / slope + t1 + offset
+ * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1 + OFFSET / 1000
+ * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1 + OFFSET /1000
* Let constant c1 = (-1000 / slope)
- * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1
- * Let constant c2 = n1 *c1 + 1000 * t1
+ * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1 + OFFSET / 1000
+ * Let constant c2 = n1 *c1 + 1000 * t1 + OFFSET / 1000
* milli_Tmeas = c2 - Nmeas * c1
*/
temp64 = FACTOR0;
temp64 *= 1000;
do_div(temp64, FACTOR1 * n1 - FACTOR2);
data->c1 = temp64;
- data->c2 = n1 * data->c1 + 1000 * t1;
+ temp64 = OFFSET;
+ do_div(temp64, 1000);
+ data->c2 = n1 * data->c1 + 1000 * t1 + temp64;
+}
+
+/*
+ * On i.MX7, we only use the calibration data at 25C to get the temp,
+ * Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C.
+ */
+static inline void imx7_calibrate_data(struct imx_thermal_data *data, u32 val)
+{
+ data->c1 = (val >> 9) & 0x1ff;
+}
+
+static int imx_get_sensor_data(struct platform_device *pdev)
+{
+ struct imx_thermal_data *data = platform_get_drvdata(pdev);
+ struct regmap *map;
+ int ret;
+ u32 val;
+
+ map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "fsl,tempmon-data");
+ if (IS_ERR(map)) {
+ ret = PTR_ERR(map);
+ dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
+ return ret;
+ }
+
+ if (data->socdata->version == TEMPMON_IMX7)
+ ret = regmap_read(map, IMX7_OCOTP_ANA1, &val);
+ else
+ ret = regmap_read(map, IMX6_OCOTP_ANA1, &val);
+
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
+ return ret;
+ }
+
+ if (val == 0 || val == ~0) {
+ dev_err(&pdev->dev, "invalid sensor calibration data\n");
+ return -EINVAL;
+ }
+
+ if (data->socdata->version == TEMPMON_IMX7)
+ imx7_calibrate_data(data, val);
+ else
+ imx6_calibrate_data(data, val);
/* use OTP for thermal grade */
- ret = regmap_read(map, OCOTP_MEM0, &val);
+ if (data->socdata->version == TEMPMON_IMX7)
+ ret = regmap_read(map, IMX7_OCOTP_TESTER3, &val);
+ else
+ ret = regmap_read(map, OCOTP_MEM0, &val);
+
if (ret) {
dev_err(&pdev->dev, "failed to read temp grade: %d\n", ret);
return ret;
@@ -465,20 +690,68 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
static const struct of_device_id of_imx_thermal_match[] = {
{ .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
{ .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
+ { .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, },
{ /* end */ }
};
MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
+static int thermal_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ const struct thermal_soc_data *soc_data = imx_thermal_data->socdata;
+ struct regmap *map = imx_thermal_data->tempmon;
+
+ mutex_lock(&imx_thermal_data->mutex);
+
+ switch (event) {
+ /*
+ * In low_bus_freq_mode, the thermal sensor auto measurement
+ * can be disabled to low the power consumption.
+ */
+ case LOW_BUSFREQ_ENTER:
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->measure_temp_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->power_down_mask);
+ imx_thermal_data->mode = THERMAL_DEVICE_DISABLED;
+ disable_irq(imx_thermal_data->irq);
+ clk_disable_unprepare(imx_thermal_data->thermal_clk);
+ break;
+
+ /* Enabled thermal auto measurement when exiting low_bus_freq_mode */
+ case LOW_BUSFREQ_EXIT:
+ clk_prepare_enable(imx_thermal_data->thermal_clk);
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->power_down_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->measure_temp_mask);
+ imx_thermal_data->mode = THERMAL_DEVICE_ENABLED;
+ enable_irq(imx_thermal_data->irq);
+ break;
+
+ default:
+ break;
+ }
+ mutex_unlock(&imx_thermal_data->mutex);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block thermal_notifier = {
+ .notifier_call = thermal_notifier_event,
+};
+
static int imx_thermal_probe(struct platform_device *pdev)
{
struct imx_thermal_data *data;
struct regmap *map;
int measure_freq;
- int ret;
+ int ret, revision;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+ imx_thermal_data = data;
map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
if (IS_ERR(map)) {
@@ -514,16 +787,29 @@ static int imx_thermal_probe(struct platform_device *pdev)
return ret;
}
+ /*
+ * for i.MX7D TO1.0, finish bit is not available, check the
+ * SOC revision to skip checking the finish bit status.
+ */
+ regmap_read(map, IMX7_ANADIG_DIGPROG, &revision);
+ if ((revision & 0xff) == 0x10)
+ skip_finish_check = 1;
+
/* Make sure sensor is in known good state for measurements */
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
- regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
- regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
-
- data->cdev = cpufreq_cooling_register(cpu_present_mask);
- if (IS_ERR(data->cdev)) {
- ret = PTR_ERR(data->cdev);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->power_down_mask);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->measure_temp_mask);
+ regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
+ data->socdata->measure_freq_mask);
+ if (data->socdata->version != TEMPMON_IMX7)
+ regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->power_down_mask);
+
+ data->cdev[0] = cpufreq_cooling_register(cpu_present_mask);
+ if (IS_ERR(data->cdev[0])) {
+ ret = PTR_ERR(data->cdev[0]);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to register cpufreq cooling device: %d\n",
@@ -531,13 +817,25 @@ static int imx_thermal_probe(struct platform_device *pdev)
return ret;
}
+ data->cdev[1] = devfreq_cooling_register();
+ if (IS_ERR(data->cdev[1])) {
+ ret = PTR_ERR(data->cdev[1]);
+ if (ret != -EPROBE_DEFER) {
+ dev_err(&pdev->dev,
+ "failed to register cpufreq cooling device: %d\n",
+ ret);
+ cpufreq_cooling_unregister(data->cdev[0]);
+ }
+ return ret;
+ }
+
data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->thermal_clk)) {
ret = PTR_ERR(data->thermal_clk);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to get thermal clk: %d\n", ret);
- cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cooling_unregister(data->cdev[0]);
return ret;
}
@@ -551,13 +849,15 @@ static int imx_thermal_probe(struct platform_device *pdev)
ret = clk_prepare_enable(data->thermal_clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
- cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cooling_unregister(data->cdev[0]);
+ devfreq_cooling_unregister(data->cdev[1]);
return ret;
}
+ mutex_init(&data->mutex);
data->tz = thermal_zone_device_register("imx_thermal_zone",
IMX_TRIP_NUM,
- BIT(IMX_TRIP_PASSIVE), data,
+ (1 << IMX_TRIP_NUM) - 1, data,
&imx_tz_ops, NULL,
IMX_PASSIVE_DELAY,
IMX_POLLING_DELAY);
@@ -566,7 +866,8 @@ static int imx_thermal_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"failed to register thermal zone device %d\n", ret);
clk_disable_unprepare(data->thermal_clk);
- cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cooling_unregister(data->cdev[0]);
+ devfreq_cooling_unregister(data->cdev[1]);
return ret;
}
@@ -576,16 +877,20 @@ static int imx_thermal_probe(struct platform_device *pdev)
data->temp_passive / 1000);
/* Enable measurements at ~ 10 Hz */
- regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
+ regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
+ data->socdata->measure_freq_mask);
measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
- regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
+ regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,
+ measure_freq << data->socdata->measure_freq_shift);
imx_set_alarm_temp(data, data->temp_passive);
if (data->socdata->version == TEMPMON_IMX6SX)
imx_set_panic_temp(data, data->temp_critical);
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->power_down_mask);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->measure_temp_mask);
ret = devm_request_threaded_irq(&pdev->dev, data->irq,
imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
@@ -594,13 +899,18 @@ static int imx_thermal_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
clk_disable_unprepare(data->thermal_clk);
thermal_zone_device_unregister(data->tz);
- cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cooling_unregister(data->cdev[0]);
+ devfreq_cooling_unregister(data->cdev[1]);
return ret;
}
data->irq_enabled = true;
data->mode = THERMAL_DEVICE_ENABLED;
+ /* register the busfreq notifier called in low bus freq */
+ if (data->socdata->version != TEMPMON_IMX7)
+ register_busfreq_notifier(&thermal_notifier);
+
return 0;
}
@@ -610,12 +920,18 @@ static int imx_thermal_remove(struct platform_device *pdev)
struct regmap *map = data->tempmon;
/* Disable measurements */
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->power_down_mask);
if (!IS_ERR(data->thermal_clk))
clk_disable_unprepare(data->thermal_clk);
+ /* unregister the busfreq notifier called in low bus freq */
+ if (data->socdata->version != TEMPMON_IMX7)
+ unregister_busfreq_notifier(&thermal_notifier);
+
thermal_zone_device_unregister(data->tz);
- cpufreq_cooling_unregister(data->cdev);
+ cpufreq_cooling_unregister(data->cdev[0]);
+ devfreq_cooling_unregister(data->cdev[1]);
return 0;
}
@@ -632,8 +948,20 @@ static int imx_thermal_suspend(struct device *dev)
* temperature will be read as the thermal sensor is powered
* down.
*/
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->measure_temp_mask);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->power_down_mask);
+
+ /*
+ * Save the temp sensor registers of i.MX7D as the tempmon
+ * will lost power in LPSR mode
+ */
+ if (data->socdata->version == TEMPMON_IMX7) {
+ regmap_read(map, data->socdata->sensor_ctrl, &imx7_lpsr_save[0]);
+ regmap_read(map, data->socdata->high_alarm_ctrl, &imx7_lpsr_save[1]);
+ }
+
data->mode = THERMAL_DEVICE_DISABLED;
clk_disable_unprepare(data->thermal_clk);
@@ -646,9 +974,21 @@ static int imx_thermal_resume(struct device *dev)
struct regmap *map = data->tempmon;
clk_prepare_enable(data->thermal_clk);
+
+ /*
+ * restore the temp sensor registers of i.MX7D as the tempmon
+ * will lost power in LPSR mode
+ */
+ if (data->socdata->version == TEMPMON_IMX7) {
+ regmap_write(map, data->socdata->sensor_ctrl, imx7_lpsr_save[0]);
+ regmap_write(map, data->socdata->high_alarm_ctrl, imx7_lpsr_save[1]);
+ }
+
/* Enabled thermal sensor after resume */
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->power_down_mask);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->measure_temp_mask);
data->mode = THERMAL_DEVICE_ENABLED;
return 0;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 76103f2c4a80..247286c91c66 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2,6 +2,7 @@
* Freescale lpuart serial port driver
*
* Copyright 2012-2014 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 as published by
@@ -24,6 +25,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
+#include <linux/reset.h>
#include <linux/serial_core.h>
#include <linux/slab.h>
#include <linux/tty_flip.h>
@@ -118,20 +120,21 @@
#define UARTSFIFO_RXUF 0x01
/* 32-bit register defination */
-#define UARTBAUD 0x00
-#define UARTSTAT 0x04
-#define UARTCTRL 0x08
-#define UARTDATA 0x0C
-#define UARTMATCH 0x10
-#define UARTMODIR 0x14
-#define UARTFIFO 0x18
-#define UARTWATER 0x1c
+#define UARTBAUD 0x10
+#define UARTSTAT 0x14
+#define UARTCTRL 0x18
+#define UARTDATA 0x1C
+#define UARTMATCH 0x20
+#define UARTMODIR 0x24
+#define UARTFIFO 0x28
+#define UARTWATER 0x2c
#define UARTBAUD_MAEN1 0x80000000
#define UARTBAUD_MAEN2 0x40000000
#define UARTBAUD_M10 0x20000000
#define UARTBAUD_TDMAE 0x00800000
#define UARTBAUD_RDMAE 0x00200000
+#define UARTBAUD_RIDMAE 0x00100000
#define UARTBAUD_MATCFG 0x00400000
#define UARTBAUD_BOTHEDGE 0x00020000
#define UARTBAUD_RESYNCDIS 0x00010000
@@ -140,6 +143,8 @@
#define UARTBAUD_SBNS 0x00002000
#define UARTBAUD_SBR 0x00000000
#define UARTBAUD_SBR_MASK 0x1fff
+#define UARTBAUD_OSR_MASK 0x1f
+#define UARTBAUD_OSR_SHIFT 24
#define UARTSTAT_LBKDIF 0x80000000
#define UARTSTAT_RXEDGIF 0x40000000
@@ -178,7 +183,7 @@
#define UARTCTRL_SBK 0x00010000
#define UARTCTRL_MA1IE 0x00008000
#define UARTCTRL_MA2IE 0x00004000
-#define UARTCTRL_IDLECFG 0x00000100
+#define UARTCTRL_IDLECFG_OFF 0x8
#define UARTCTRL_LOOPS 0x00000080
#define UARTCTRL_DOZEEN 0x00000040
#define UARTCTRL_RSRC 0x00000020
@@ -193,9 +198,12 @@
#define UARTDATA_FRETSC 0x00002000
#define UARTDATA_RXEMPT 0x00001000
#define UARTDATA_IDLINE 0x00000800
+#define UARTDATA_INVALID 0x0000F000
#define UARTDATA_MASK 0x3ff
#define UARTMODIR_IREN 0x00020000
+#define UARTMODIR_RTSWATER_S 0x8
+#define UARTMODIR_RTSWATER_M 0x0000ff00
#define UARTMODIR_TXCTSSRC 0x00000020
#define UARTMODIR_TXCTSC 0x00000010
#define UARTMODIR_RXRTSE 0x00000008
@@ -209,6 +217,8 @@
#define UARTFIFO_RXUF 0x00010000
#define UARTFIFO_TXFLUSH 0x00008000
#define UARTFIFO_RXFLUSH 0x00004000
+#define UARTFIFO_RXIDEN_MASK 0x7
+#define UARTFIFO_RXIDEN_OFF 10
#define UARTFIFO_TXOFE 0x00000200
#define UARTFIFO_RXUFE 0x00000100
#define UARTFIFO_TXFE 0x00000080
@@ -224,8 +234,9 @@
#define UARTWATER_TXWATER_OFF 0
#define UARTWATER_RXWATER_OFF 16
-/* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
-#define DMA_RX_TIMEOUT (10)
+#define UARTFIFO_RXIDEN_RDRF 0x3
+#define UARTCTRL_IDLECFG 0x7
+#define FSL_UART_RX_DMA_BUFFER_SIZE 64
#define DRIVER_NAME "fsl-lpuart"
#define DEV_NAME "ttyLP"
@@ -233,27 +244,33 @@
struct lpuart_port {
struct uart_port port;
- struct clk *clk;
+ struct clk *ipg_clk;
+ struct clk *per_clk;
unsigned int txfifo_size;
unsigned int rxfifo_size;
+ unsigned int txfifo_watermark;
+ unsigned int rxfifo_watermark;
bool lpuart32;
bool lpuart_dma_tx_use;
bool lpuart_dma_rx_use;
+ bool dma_rx_chan_active;
struct dma_chan *dma_tx_chan;
struct dma_chan *dma_rx_chan;
struct dma_async_tx_descriptor *dma_tx_desc;
struct dma_async_tx_descriptor *dma_rx_desc;
+ dma_addr_t dma_rx_buf_bus;
dma_cookie_t dma_tx_cookie;
dma_cookie_t dma_rx_cookie;
+ unsigned char *dma_rx_buf_virt;
unsigned int dma_tx_bytes;
unsigned int dma_rx_bytes;
+ size_t rxdma_len;
bool dma_tx_in_progress;
+ bool dma_rx_in_progress;
unsigned int dma_rx_timeout;
struct timer_list lpuart_timer;
struct scatterlist rx_sgl, tx_sgl[2];
- struct circ_buf rx_ring;
- int rx_dma_rng_buf_len;
unsigned int dma_tx_nents;
wait_queue_head_t dma_wait;
};
@@ -265,21 +282,26 @@ static const struct of_device_id lpuart_dt_ids[] = {
{
.compatible = "fsl,ls1021a-lpuart",
},
+ {
+ .compatible = "fsl,imx7ulp-lpuart",
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
/* Forward declare this for the dma callbacks*/
+static int lpuart_dma_rx(struct lpuart_port *sport);
static void lpuart_dma_tx_complete(void *arg);
+static inline void lpuart_prepare_rx(struct lpuart_port *sport);
static u32 lpuart32_read(void __iomem *addr)
{
- return ioread32be(addr);
+ return readl(addr);
}
static void lpuart32_write(u32 val, void __iomem *addr)
{
- iowrite32be(val, addr);
+ writel(val, addr);
}
static void lpuart_stop_tx(struct uart_port *port)
@@ -401,15 +423,18 @@ static int lpuart_dma_tx_request(struct uart_port *port)
struct dma_slave_config dma_tx_sconfig = {};
int ret;
- dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
+ if (sport->lpuart32)
+ dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDATA;
+ else
+ dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_tx_sconfig.dst_maxburst = 1;
dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
ret = dmaengine_slave_config(sport->dma_tx_chan, &dma_tx_sconfig);
- if (ret) {
+ if (ret < 0) {
dev_err(sport->port.dev,
- "DMA slave config failed, err = %d\n", ret);
+ "Dma slave config failed, err = %d\n", ret);
return ret;
}
@@ -419,7 +444,6 @@ static int lpuart_dma_tx_request(struct uart_port *port)
static void lpuart_flush_buffer(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
-
if (sport->lpuart_dma_tx_use) {
if (sport->dma_tx_in_progress) {
dma_unmap_sg(sport->port.dev, &sport->tx_sgl[0],
@@ -479,13 +503,13 @@ static void lpuart_start_tx(struct uart_port *port)
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned char temp;
- temp = readb(port->membase + UARTCR2);
- writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
-
if (sport->lpuart_dma_tx_use) {
if (!uart_circ_empty(xmit) && !uart_tx_stopped(port))
lpuart_dma_tx(sport);
} else {
+ temp = readb(port->membase + UARTCR2);
+ writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
+
if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
lpuart_transmit_buffer(sport);
}
@@ -494,13 +518,19 @@ static void lpuart_start_tx(struct uart_port *port)
static void lpuart32_start_tx(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+ struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long temp;
- temp = lpuart32_read(port->membase + UARTCTRL);
- lpuart32_write(temp | UARTCTRL_TIE, port->membase + UARTCTRL);
-
- if (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE)
- lpuart32_transmit_buffer(sport);
+ if (sport->lpuart_dma_tx_use) {
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(port))
+ lpuart_dma_tx(sport);
+ } else {
+ temp = lpuart32_read(port->membase + UARTCTRL);
+ lpuart32_write(temp | UARTCTRL_TIE, port->membase + UARTCTRL);
+ if (lpuart32_read(sport->port.membase + UARTSTAT) &
+ UARTSTAT_TDRE)
+ lpuart32_transmit_buffer(sport);
+ }
}
/* return TIOCSER_TEMT when transmitter is not busy */
@@ -522,8 +552,18 @@ static unsigned int lpuart_tx_empty(struct uart_port *port)
static unsigned int lpuart32_tx_empty(struct uart_port *port)
{
- return (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TC) ?
- TIOCSER_TEMT : 0;
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+ unsigned int sr1 = lpuart32_read(port->membase + UARTSTAT);
+ unsigned int sfifo = lpuart32_read(sport->port.membase + UARTFIFO);
+
+ if (sport->dma_tx_in_progress)
+ return 0;
+
+ if (sr1 & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT)
+ return TIOCSER_TEMT;
+
+ return 0;
}
static irqreturn_t lpuart_txint(int irq, void *dev_id)
@@ -638,13 +678,19 @@ static irqreturn_t lpuart32_rxint(int irq, void *dev_id)
while (!(lpuart32_read(sport->port.membase + UARTFIFO) & UARTFIFO_RXEMPT)) {
flg = TTY_NORMAL;
sport->port.icount.rx++;
+
/*
* to clear the FE, OR, NF, FE, PE flags,
* read STAT then read DATA reg
*/
sr = lpuart32_read(sport->port.membase + UARTSTAT);
rx = lpuart32_read(sport->port.membase + UARTDATA);
- rx &= 0x3ff;
+
+ if ((sr & UARTSTAT_FE) && (rx & UARTDATA_FRETSC) &&
+ !(rx & UARTDATA_MASK)) {
+ if (uart_handle_break(&sport->port))
+ continue;
+ }
if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
continue;
@@ -679,6 +725,10 @@ static irqreturn_t lpuart32_rxint(int irq, void *dev_id)
#endif
}
+ if (rx & UARTDATA_INVALID)
+ continue;
+
+ rx &= UARTDATA_MASK;
tty_insert_flip_char(port, rx, flg);
}
@@ -692,14 +742,19 @@ out:
static irqreturn_t lpuart_int(int irq, void *dev_id)
{
struct lpuart_port *sport = dev_id;
- unsigned char sts;
+ unsigned char sts, crdma;
sts = readb(sport->port.membase + UARTSR1);
+ crdma = readb(sport->port.membase + UARTCR5);
- if (sts & UARTSR1_RDRF)
- lpuart_rxint(irq, dev_id);
+ if (sts & UARTSR1_RDRF && !(crdma & UARTCR5_RDMAS)) {
+ if (sport->lpuart_dma_rx_use)
+ lpuart_prepare_rx(sport);
+ else
+ lpuart_rxint(irq, dev_id);
+ }
- if (sts & UARTSR1_TDRE)
+ if (sts & UARTSR1_TDRE && !sport->lpuart_dma_tx_use)
lpuart_txint(irq, dev_id);
return IRQ_HANDLED;
@@ -708,195 +763,144 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
static irqreturn_t lpuart32_int(int irq, void *dev_id)
{
struct lpuart_port *sport = dev_id;
- unsigned long sts, rxcount;
+ unsigned long sts, rxcount, crdma;
sts = lpuart32_read(sport->port.membase + UARTSTAT);
rxcount = lpuart32_read(sport->port.membase + UARTWATER);
rxcount = rxcount >> UARTWATER_RXCNT_OFF;
+ crdma = lpuart32_read(sport->port.membase + UARTBAUD);
- if (sts & UARTSTAT_RDRF || rxcount > 0)
- lpuart32_rxint(irq, dev_id);
+ if (!sts)
+ return IRQ_NONE;
+
+ if (!(crdma & UARTBAUD_RDMAE) && rxcount > 0) {
+ if (!sport->lpuart_dma_rx_use ||
+ (sts & (UARTSTAT_PE | UARTSTAT_NF | UARTSTAT_FE)))
+ lpuart32_rxint(irq, dev_id);
+ else if (sport->lpuart_dma_rx_use && sport->dma_rx_chan_active)
+ lpuart_prepare_rx(sport);
+ }
- if ((sts & UARTSTAT_TDRE) &&
- !(lpuart32_read(sport->port.membase + UARTBAUD) & UARTBAUD_TDMAE))
+ if (sts & UARTSTAT_TDRE && !sport->lpuart_dma_tx_use)
lpuart_txint(irq, dev_id);
lpuart32_write(sts, sport->port.membase + UARTSTAT);
return IRQ_HANDLED;
}
-static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
+static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
+ struct tty_port *tty, int count)
{
- struct tty_port *port = &sport->port.state->port;
- struct dma_tx_state state;
- enum dma_status dmastat;
- struct circ_buf *ring = &sport->rx_ring;
- unsigned long flags;
- int count = 0;
- unsigned char sr;
+ int copied;
- sr = readb(sport->port.membase + UARTSR1);
+ sport->port.icount.rx += count;
- if (sr & (UARTSR1_PE | UARTSR1_FE)) {
- /* Read DR to clear the error flags */
- readb(sport->port.membase + UARTDR);
-
- if (sr & UARTSR1_PE)
- sport->port.icount.parity++;
- else if (sr & UARTSR1_FE)
- sport->port.icount.frame++;
- }
-
- async_tx_ack(sport->dma_rx_desc);
-
- spin_lock_irqsave(&sport->port.lock, flags);
-
- dmastat = dmaengine_tx_status(sport->dma_rx_chan,
- sport->dma_rx_cookie,
- &state);
-
- if (dmastat == DMA_ERROR) {
- dev_err(sport->port.dev, "Rx DMA transfer failed!\n");
- spin_unlock_irqrestore(&sport->port.lock, flags);
+ if (!tty) {
+ dev_err(sport->port.dev, "No tty port\n");
return;
}
- /* CPU claims ownership of RX DMA buffer */
- dma_sync_sg_for_cpu(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(sport->port.dev, sport->dma_rx_buf_bus,
+ sport->rxdma_len, DMA_FROM_DEVICE);
+ copied = tty_insert_flip_string(tty,
+ ((unsigned char *)(sport->dma_rx_buf_virt)), count);
- /*
- * ring->head points to the end of data already written by the DMA.
- * ring->tail points to the beginning of data to be read by the
- * framework.
- * The current transfer size should not be larger than the dma buffer
- * length.
- */
- ring->head = sport->rx_sgl.length - state.residue;
- BUG_ON(ring->head > sport->rx_sgl.length);
- /*
- * At this point ring->head may point to the first byte right after the
- * last byte of the dma buffer:
- * 0 <= ring->head <= sport->rx_sgl.length
- *
- * However ring->tail must always points inside the dma buffer:
- * 0 <= ring->tail <= sport->rx_sgl.length - 1
- *
- * Since we use a ring buffer, we have to handle the case
- * where head is lower than tail. In such a case, we first read from
- * tail to the end of the buffer then reset tail.
- */
- if (ring->head < ring->tail) {
- count = sport->rx_sgl.length - ring->tail;
+ if (copied != count)
+ sport->port.icount.buf_overrun += count - copied;
+ sport->port.icount.rx += copied;
+}
- tty_insert_flip_string(port, ring->buf + ring->tail, count);
- ring->tail = 0;
- sport->port.icount.rx += count;
- }
+static void lpuart_dma_stop(struct lpuart_port *sport, bool enable_pio)
+{
+ unsigned int temp;
+ unsigned int crdma;
- /* Finally we read data from tail to head */
- if (ring->tail < ring->head) {
- count = ring->head - ring->tail;
- tty_insert_flip_string(port, ring->buf + ring->tail, count);
- /* Wrap ring->head if needed */
- if (ring->head >= sport->rx_sgl.length)
- ring->head = 0;
- ring->tail = ring->head;
- sport->port.icount.rx += count;
+ if (sport->lpuart32) {
+ lpuart32_write(UARTSTAT_IDLE, sport->port.membase + UARTSTAT);
+ crdma = lpuart32_read(sport->port.membase + UARTBAUD);
+ lpuart32_write(crdma & ~(UARTBAUD_RDMAE),
+ sport->port.membase + UARTBAUD);
+ if (enable_pio) {
+ temp = lpuart32_read(sport->port.membase + UARTCTRL);
+ temp |= (UARTCTRL_RIE | UARTCTRL_ILIE);
+ lpuart32_write(temp, sport->port.membase + UARTCTRL);
+ }
+ } else {
+ temp = readb(sport->port.membase + UARTCR5);
+ writeb(temp & ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
}
-
- dma_sync_sg_for_device(sport->port.dev, &sport->rx_sgl, 1,
- DMA_FROM_DEVICE);
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
-
- tty_flip_buffer_push(port);
- mod_timer(&sport->lpuart_timer, jiffies + sport->dma_rx_timeout);
}
static void lpuart_dma_rx_complete(void *arg)
{
struct lpuart_port *sport = arg;
+ struct tty_port *port = &sport->port.state->port;
+ unsigned long flags;
+ struct dma_tx_state state;
+ int count;
- lpuart_copy_rx_to_tty(sport);
-}
+ async_tx_ack(sport->dma_rx_desc);
+ mod_timer(&sport->lpuart_timer, jiffies + sport->dma_rx_timeout);
-static void lpuart_timer_func(unsigned long data)
-{
- struct lpuart_port *sport = (struct lpuart_port *)data;
+ spin_lock_irqsave(&sport->port.lock, flags);
+ sport->dma_rx_in_progress = false;
+ dmaengine_tx_status(sport->dma_rx_chan, sport->dma_rx_cookie, &state);
+ count = sport->rxfifo_watermark - state.residue;
+ lpuart_copy_rx_to_tty(sport, port, count);
+ tty_flip_buffer_push(port);
- lpuart_copy_rx_to_tty(sport);
+ if (count < sport->rxfifo_watermark)
+ lpuart_dma_stop(sport, true);
+ else
+ lpuart_dma_rx(sport);
+
+ spin_unlock_irqrestore(&sport->port.lock, flags);
}
-static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
+static void lpuart_timer_func(unsigned long data)
{
- struct dma_slave_config dma_rx_sconfig = {};
- struct circ_buf *ring = &sport->rx_ring;
- int ret, nent;
- int bits, baud;
- struct tty_struct *tty = tty_port_tty_get(&sport->port.state->port);
- struct ktermios *termios = &tty->termios;
-
- baud = tty_get_baud_rate(tty);
-
- bits = (termios->c_cflag & CSIZE) == CS7 ? 9 : 10;
- if (termios->c_cflag & PARENB)
- bits++;
+ struct lpuart_port *sport = (struct lpuart_port *)data;
+ struct tty_port *port = &sport->port.state->port;
+ struct dma_tx_state state;
+ unsigned long flags;
+ int count;
- /*
- * Calculate length of one DMA buffer size to keep latency below
- * 10ms at any baud rate.
- */
- sport->rx_dma_rng_buf_len = (DMA_RX_TIMEOUT * baud / bits / 1000) * 2;
- sport->rx_dma_rng_buf_len = (1 << (fls(sport->rx_dma_rng_buf_len) - 1));
- if (sport->rx_dma_rng_buf_len < 16)
- sport->rx_dma_rng_buf_len = 16;
-
- ring->buf = kmalloc(sport->rx_dma_rng_buf_len, GFP_ATOMIC);
- if (!ring->buf) {
- dev_err(sport->port.dev, "Ring buf alloc failed\n");
- return -ENOMEM;
- }
+ del_timer(&sport->lpuart_timer);
+ dmaengine_pause(sport->dma_rx_chan);
+ dmaengine_tx_status(sport->dma_rx_chan, sport->dma_rx_cookie, &state);
+ dmaengine_terminate_all(sport->dma_rx_chan);
+ count = sport->rxdma_len - state.residue;
+ async_tx_ack(sport->dma_rx_desc);
- sg_init_one(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len);
- sg_set_buf(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len);
- nent = dma_map_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
+ spin_lock_irqsave(&sport->port.lock, flags);
- if (!nent) {
- dev_err(sport->port.dev, "DMA Rx mapping error\n");
- return -EINVAL;
- }
+ sport->dma_rx_in_progress = false;
+ lpuart_copy_rx_to_tty(sport, port, count);
+ tty_flip_buffer_push(port);
+ lpuart_dma_stop(sport, true);
- dma_rx_sconfig.src_addr = sport->port.mapbase + UARTDR;
- dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- dma_rx_sconfig.src_maxburst = 1;
- dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
- ret = dmaengine_slave_config(sport->dma_rx_chan, &dma_rx_sconfig);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+}
- if (ret < 0) {
- dev_err(sport->port.dev,
- "DMA Rx slave config failed, err = %d\n", ret);
- return ret;
- }
+static int lpuart_dma_rx(struct lpuart_port *sport)
+{
+ dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
+ sport->rxdma_len, DMA_FROM_DEVICE);
+ sport->dma_rx_desc = dmaengine_prep_slave_single(sport->dma_rx_chan,
+ sport->dma_rx_buf_bus, sport->rxdma_len,
+ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
- sport->dma_rx_desc = dmaengine_prep_dma_cyclic(sport->dma_rx_chan,
- sg_dma_address(&sport->rx_sgl),
- sport->rx_sgl.length,
- sport->rx_sgl.length / 2,
- DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT);
if (!sport->dma_rx_desc) {
- dev_err(sport->port.dev, "Cannot prepare cyclic DMA\n");
- return -EFAULT;
+ dev_err(sport->port.dev, "Not able to get desc for rx\n");
+ return -EIO;
}
sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
sport->dma_rx_desc->callback_param = sport;
+ sport->dma_rx_in_progress = true;
sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc);
dma_async_issue_pending(sport->dma_rx_chan);
- writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_RDMAS,
- sport->port.membase + UARTCR5);
-
return 0;
}
@@ -905,15 +909,39 @@ static void lpuart_dma_rx_free(struct uart_port *port)
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
- if (sport->dma_rx_chan)
- dmaengine_terminate_all(sport->dma_rx_chan);
+ sport->dma_rx_chan_active = false;
+ dma_unmap_single(sport->port.dev, sport->dma_rx_buf_bus,
+ sport->rxdma_len, DMA_FROM_DEVICE);
- dma_unmap_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
- kfree(sport->rx_ring.buf);
- sport->rx_ring.tail = 0;
- sport->rx_ring.head = 0;
- sport->dma_rx_desc = NULL;
- sport->dma_rx_cookie = -EINVAL;
+ sport->dma_rx_buf_bus = 0;
+ sport->dma_rx_buf_virt = NULL;
+}
+
+static inline void lpuart_prepare_rx(struct lpuart_port *sport)
+{
+ unsigned long flags;
+ unsigned int temp;
+ unsigned int crdma;
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+
+ sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
+ add_timer(&sport->lpuart_timer);
+
+ lpuart_dma_rx(sport);
+ if (sport->lpuart32) {
+ temp = lpuart32_read(sport->port.membase + UARTCTRL);
+ temp &= ~(UARTCTRL_RIE | UARTCTRL_ILIE);
+ lpuart32_write(temp, sport->port.membase + UARTCTRL);
+ crdma = lpuart32_read(sport->port.membase + UARTBAUD);
+ lpuart32_write(crdma | UARTBAUD_RDMAE,
+ sport->port.membase + UARTBAUD);
+ } else {
+ temp = readb(sport->port.membase + UARTCR5);
+ writeb(temp | UARTCR5_RDMAS, sport->port.membase + UARTCR5);
+ }
+
+ spin_unlock_irqrestore(&sport->port.lock, flags);
}
static int lpuart_config_rs485(struct uart_port *port,
@@ -989,11 +1017,15 @@ static unsigned int lpuart32_get_mctrl(struct uart_port *port)
if (reg & UARTMODIR_RXRTSE)
temp |= TIOCM_RTS;
+ if (lpuart32_read(port->membase + UARTCTRL) & UARTCTRL_LOOPS)
+ temp |= TIOCM_LOOP;
+
return temp;
}
static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
+ /* No flow control for user handle */
unsigned char temp;
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
@@ -1017,16 +1049,10 @@ static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
unsigned long temp;
- temp = lpuart32_read(port->membase + UARTMODIR) &
- ~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
-
- if (mctrl & TIOCM_RTS)
- temp |= UARTMODIR_RXRTSE;
-
- if (mctrl & TIOCM_CTS)
- temp |= UARTMODIR_TXCTSE;
-
- lpuart32_write(temp, port->membase + UARTMODIR);
+ temp = lpuart32_read(port->membase + UARTCTRL);
+ if (mctrl & TIOCM_LOOP)
+ temp |= UARTCTRL_LOOPS;
+ lpuart32_write(temp, port->membase + UARTCTRL);
}
static void lpuart_break_ctl(struct uart_port *port, int break_state)
@@ -1100,22 +1126,75 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport)
val = lpuart32_read(sport->port.membase + UARTFIFO);
val |= UARTFIFO_TXFE | UARTFIFO_RXFE;
val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH;
+ val &= ~(UARTFIFO_RXIDEN_MASK << UARTFIFO_RXIDEN_OFF);
+ val |= ((UARTFIFO_RXIDEN_RDRF & UARTFIFO_RXIDEN_MASK) <<
+ UARTFIFO_RXIDEN_OFF);
lpuart32_write(val, sport->port.membase + UARTFIFO);
/* set the watermark */
- val = (0x1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF);
+ if (uart_console(&sport->port)) {
+ val = (0x1 << UARTWATER_RXWATER_OFF) |
+ (0x0 << UARTWATER_TXWATER_OFF);
+ } else {
+ val = lpuart32_read(sport->port.membase + UARTMODIR);
+ val = sport->rxfifo_watermark << UARTMODIR_RTSWATER_S;
+ lpuart32_write(val, sport->port.membase + UARTMODIR);
+ val = (0x1 << UARTWATER_RXWATER_OFF) |
+ (sport->txfifo_watermark << UARTWATER_TXWATER_OFF);
+ }
lpuart32_write(val, sport->port.membase + UARTWATER);
/* Restore cr2 */
lpuart32_write(ctrl_saved, sport->port.membase + UARTCTRL);
}
-static void rx_dma_timer_init(struct lpuart_port *sport)
+static int lpuart_dma_rx_request(struct uart_port *port)
{
- setup_timer(&sport->lpuart_timer, lpuart_timer_func,
- (unsigned long)sport);
- sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
- add_timer(&sport->lpuart_timer);
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+ struct dma_slave_config dma_rx_sconfig;
+ dma_addr_t dma_bus;
+ unsigned char *dma_buf;
+ int ret;
+
+ dma_buf = devm_kzalloc(sport->port.dev,
+ FSL_UART_RX_DMA_BUFFER_SIZE, GFP_KERNEL);
+
+ if (!dma_buf) {
+ dev_err(sport->port.dev, "Dma rx alloc failed\n");
+ return -ENOMEM;
+ }
+
+ dma_bus = dma_map_single(sport->port.dev, dma_buf,
+ FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(sport->port.dev, dma_bus)) {
+ dev_err(sport->port.dev, "dma_map_single rx failed\n");
+ return -ENOMEM;
+ }
+
+ if (sport->lpuart32)
+ dma_rx_sconfig.src_addr = sport->port.mapbase + UARTDATA;
+ else
+ dma_rx_sconfig.src_addr = sport->port.mapbase + UARTDR;
+
+ dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ dma_rx_sconfig.src_maxburst = 1;
+ dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
+ ret = dmaengine_slave_config(sport->dma_rx_chan, &dma_rx_sconfig);
+
+ if (ret < 0) {
+ dev_err(sport->port.dev,
+ "Dma slave config failed, err = %d\n", ret);
+ return ret;
+ }
+
+ sport->dma_rx_buf_virt = dma_buf;
+ sport->dma_rx_buf_bus = dma_bus;
+ sport->dma_rx_in_progress = false;
+ sport->dma_rx_chan_active = true;
+
+ return 0;
}
static int lpuart_startup(struct uart_port *port)
@@ -1125,6 +1204,15 @@ static int lpuart_startup(struct uart_port *port)
unsigned long flags;
unsigned char temp;
+ ret = clk_prepare_enable(sport->ipg_clk);
+ if (ret)
+ return ret;
+ ret = clk_prepare_enable(sport->per_clk);
+ if (ret) {
+ clk_disable_unprepare(sport->ipg_clk);
+ return ret;
+ }
+
/* determine FIFO size and enable FIFO mode */
temp = readb(sport->port.membase + UARTPFIFO);
@@ -1135,6 +1223,24 @@ static int lpuart_startup(struct uart_port *port)
sport->rxfifo_size = 0x1 << (((temp >> UARTPFIFO_RXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK) + 1);
+ sport->rxdma_len = FSL_UART_RX_DMA_BUFFER_SIZE;
+
+ if (sport->dma_rx_chan && !lpuart_dma_rx_request(port)) {
+ sport->lpuart_dma_rx_use = true;
+ setup_timer(&sport->lpuart_timer, lpuart_timer_func,
+ (unsigned long)sport);
+ } else
+ sport->lpuart_dma_rx_use = false;
+
+
+ if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
+ init_waitqueue_head(&sport->dma_wait);
+ sport->lpuart_dma_tx_use = true;
+ temp = readb(port->membase + UARTCR5);
+ temp &= ~UARTCR5_RDMAS;
+ writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
+ } else
+ sport->lpuart_dma_tx_use = false;
ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0,
DRIVER_NAME, sport);
@@ -1146,50 +1252,68 @@ static int lpuart_startup(struct uart_port *port)
lpuart_setup_watermark(sport);
temp = readb(sport->port.membase + UARTCR2);
- temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE);
+ temp |= (UARTCR2_RIE | UARTCR2_RE | UARTCR2_TE);
writeb(temp, sport->port.membase + UARTCR2);
- if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
- /* set Rx DMA timeout */
- sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
- if (!sport->dma_rx_timeout)
- sport->dma_rx_timeout = 1;
-
- sport->lpuart_dma_rx_use = true;
- rx_dma_timer_init(sport);
- } else {
- sport->lpuart_dma_rx_use = false;
- }
-
- if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
- init_waitqueue_head(&sport->dma_wait);
- sport->lpuart_dma_tx_use = true;
- temp = readb(port->membase + UARTCR5);
- writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
- } else {
- sport->lpuart_dma_tx_use = false;
- }
-
spin_unlock_irqrestore(&sport->port.lock, flags);
-
return 0;
}
static int lpuart32_startup(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+ struct tty_port *tty_port = &sport->port.state->port;
int ret;
unsigned long flags;
unsigned long temp;
+ /* some modem may need reset */
+ if (!tty_port_suspended(tty_port)) {
+ ret = device_reset(sport->port.dev);
+ if (ret && ret != -ENOENT)
+ return ret;
+ }
+
+ ret = clk_prepare_enable(sport->ipg_clk);
+ if (ret)
+ return ret;
+ ret = clk_prepare_enable(sport->per_clk);
+ if (ret) {
+ clk_disable_unprepare(sport->ipg_clk);
+ return ret;
+ }
+
/* determine FIFO size */
temp = lpuart32_read(sport->port.membase + UARTFIFO);
sport->txfifo_size = 0x1 << (((temp >> UARTFIFO_TXSIZE_OFF) &
- UARTFIFO_FIFOSIZE_MASK) - 1);
+ UARTFIFO_FIFOSIZE_MASK) + 1);
+
+ sport->port.fifosize = sport->txfifo_size;
sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) &
- UARTFIFO_FIFOSIZE_MASK) - 1);
+ UARTFIFO_FIFOSIZE_MASK) + 1);
+
+ sport->txfifo_watermark = sport->txfifo_size >> 1;
+ sport->rxfifo_watermark = sport->rxfifo_size >> 1;
+ sport->rxdma_len = sport->rxfifo_watermark;
+
+ if (sport->dma_rx_chan && !lpuart_dma_rx_request(port)) {
+ sport->lpuart_dma_rx_use = true;
+ setup_timer(&sport->lpuart_timer, lpuart_timer_func,
+ (unsigned long)sport);
+ } else
+ sport->lpuart_dma_rx_use = false;
+
+
+ if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
+ init_waitqueue_head(&sport->dma_wait);
+ sport->lpuart_dma_tx_use = true;
+ temp = lpuart32_read(sport->port.membase + UARTBAUD);
+ temp |= UARTBAUD_TDMAE;
+ lpuart32_write(temp, sport->port.membase + UARTBAUD);
+ } else
+ sport->lpuart_dma_tx_use = false;
ret = devm_request_irq(port->dev, port->irq, lpuart32_int, 0,
DRIVER_NAME, sport);
@@ -1201,8 +1325,9 @@ static int lpuart32_startup(struct uart_port *port)
lpuart32_setup_watermark(sport);
temp = lpuart32_read(sport->port.membase + UARTCTRL);
- temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE | UARTCTRL_TE);
+ temp |= (UARTCTRL_RIE | UARTCTRL_RE | UARTCTRL_TE);
temp |= UARTCTRL_ILIE;
+ temp |= UARTCTRL_IDLECFG << UARTCTRL_IDLECFG_OFF;
lpuart32_write(temp, sport->port.membase + UARTCTRL);
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1214,6 +1339,7 @@ static void lpuart_shutdown(struct uart_port *port)
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned char temp;
unsigned long flags;
+ int ret;
spin_lock_irqsave(&port->lock, flags);
@@ -1228,19 +1354,26 @@ static void lpuart_shutdown(struct uart_port *port)
devm_free_irq(port->dev, port->irq, sport);
if (sport->lpuart_dma_rx_use) {
- del_timer_sync(&sport->lpuart_timer);
+ ret = wait_event_interruptible_timeout(sport->dma_wait,
+ !sport->dma_rx_in_progress, msecs_to_jiffies(1));
+ if (ret <= 0) {
+ sport->dma_rx_in_progress = false;
+ dmaengine_terminate_all(sport->dma_rx_chan);
+ }
lpuart_dma_rx_free(&sport->port);
+ del_timer_sync(&sport->lpuart_timer);
}
if (sport->lpuart_dma_tx_use) {
- if (wait_event_interruptible(sport->dma_wait,
- !sport->dma_tx_in_progress) != false) {
+ ret = wait_event_interruptible_timeout(sport->dma_wait,
+ !sport->dma_tx_in_progress, msecs_to_jiffies(1));
+ if (ret <= 0) {
sport->dma_tx_in_progress = false;
dmaengine_terminate_all(sport->dma_tx_chan);
}
-
- lpuart_stop_tx(port);
}
+ clk_disable_unprepare(sport->per_clk);
+ clk_disable_unprepare(sport->ipg_clk);
}
static void lpuart32_shutdown(struct uart_port *port)
@@ -1248,18 +1381,48 @@ static void lpuart32_shutdown(struct uart_port *port)
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long temp;
unsigned long flags;
+ int ret;
spin_lock_irqsave(&port->lock, flags);
+ /* disable Rx/Tx DMA */
+ temp = lpuart32_read(sport->port.membase + UARTBAUD);
+ temp &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
+ lpuart32_write(temp, sport->port.membase + UARTBAUD);
+
/* disable Rx/Tx and interrupts */
temp = lpuart32_read(port->membase + UARTCTRL);
- temp &= ~(UARTCTRL_TE | UARTCTRL_RE |
- UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
+ temp &= ~(UARTCTRL_TE | UARTCTRL_RE | UARTCTRL_TIE |
+ UARTCTRL_TCIE | UARTCTRL_RIE | UARTCTRL_ILIE |
+ UARTCTRL_LOOPS);
lpuart32_write(temp, port->membase + UARTCTRL);
+ lpuart32_write(0, sport->port.membase + UARTMODIR);
spin_unlock_irqrestore(&port->lock, flags);
devm_free_irq(port->dev, port->irq, sport);
+
+ if (sport->lpuart_dma_rx_use) {
+ ret = wait_event_interruptible_timeout(sport->dma_wait,
+ !sport->dma_rx_in_progress, msecs_to_jiffies(1));
+ if (ret <= 0) {
+ sport->dma_rx_in_progress = false;
+ dmaengine_terminate_all(sport->dma_rx_chan);
+ }
+ lpuart_dma_rx_free(&sport->port);
+ del_timer_sync(&sport->lpuart_timer);
+ }
+
+ if (sport->lpuart_dma_tx_use) {
+ ret = wait_event_interruptible_timeout(sport->dma_wait,
+ !sport->dma_tx_in_progress, msecs_to_jiffies(1));
+ if (ret <= 0) {
+ sport->dma_tx_in_progress = false;
+ dmaengine_terminate_all(sport->dma_tx_chan);
+ }
+ }
+ clk_disable_unprepare(sport->per_clk);
+ clk_disable_unprepare(sport->ipg_clk);
}
static void
@@ -1373,6 +1536,17 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
/* update the per-port timeout */
uart_update_timeout(port, termios->c_cflag, baud);
+ if (sport->lpuart_dma_rx_use) {
+ /* Calculate delay for 1.5 DMA buffers */
+ sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
+ FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
+ sport->rxfifo_size / 2;
+ dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
+ sport->dma_rx_timeout * 1000 / HZ, sport->port.timeout);
+ if (sport->dma_rx_timeout < msecs_to_jiffies(20))
+ sport->dma_rx_timeout = msecs_to_jiffies(20);
+ }
+
/* wait transmit engin complete */
while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
barrier();
@@ -1397,25 +1571,60 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
/* restore control register */
writeb(old_cr2, sport->port.membase + UARTCR2);
- /*
- * If new baud rate is set, we will also need to update the Ring buffer
- * length according to the selected baud rate and restart Rx DMA path.
- */
- if (old) {
- if (sport->lpuart_dma_rx_use) {
- del_timer_sync(&sport->lpuart_timer);
- lpuart_dma_rx_free(&sport->port);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static void
+lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
+{
+ u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
+ u32 clk = sport->port.uartclk;
+
+ baud_diff = baudrate;
+ osr = 0;
+ sbr = 0;
+ for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+ tmp_sbr = (clk / (baudrate * tmp_osr));
+ if (tmp_sbr == 0)
+ tmp_sbr = 1;
+
+ /*calculate difference in actual buad w/ current values */
+ tmp_diff = (clk / (tmp_osr * tmp_sbr));
+ tmp_diff = tmp_diff - baudrate;
+
+ /* select best values between sbr and sbr+1 */
+ if (tmp_diff > (baudrate - (clk / (tmp_osr * (tmp_sbr + 1))))) {
+ tmp_diff = baudrate - (clk / (tmp_osr * (tmp_sbr + 1)));
+ tmp_sbr++;
}
- if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
- sport->lpuart_dma_rx_use = true;
- rx_dma_timer_init(sport);
- } else {
- sport->lpuart_dma_rx_use = false;
+ if (tmp_diff <= baud_diff) {
+ baud_diff = tmp_diff;
+ osr = tmp_osr;
+ sbr = tmp_sbr;
}
}
- spin_unlock_irqrestore(&sport->port.lock, flags);
+ /*TODO handle buadrate outside acceptable rate
+ * if (baudDiff > ((config->baudRate_Bps / 100) * 3))
+ * {
+ * Unacceptable baud rate difference of more than 3%
+ * return kStatus_LPUART_BaudrateNotSupport;
+ * }
+ *
+ */
+ tmp = lpuart32_read(sport->port.membase + UARTBAUD);
+
+ if ((osr > 3) && (osr < 8))
+ tmp |= UARTBAUD_BOTHEDGE;
+
+ tmp &= ~(UARTBAUD_OSR_MASK << UARTBAUD_OSR_SHIFT);
+ tmp |= (((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT);
+
+ tmp &= ~UARTBAUD_SBR_MASK;
+ tmp |= sbr & UARTBAUD_SBR_MASK;
+
+ lpuart32_write(tmp, sport->port.membase + UARTBAUD);
}
static void
@@ -1427,7 +1636,6 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned long ctrl, old_ctrl, bd, modem;
unsigned int baud;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
- unsigned int sbr;
ctrl = old_ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
bd = lpuart32_read(sport->port.membase + UARTBAUD);
@@ -1467,7 +1675,9 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
}
if (termios->c_cflag & CSTOPB)
- termios->c_cflag &= ~CSTOPB;
+ bd |= UARTBAUD_SBNS;
+ else
+ bd &= ~UARTBAUD_SBNS;
/* parity must be enabled when CS7 to match 8-bits format */
if ((termios->c_cflag & CSIZE) == CS7)
@@ -1489,7 +1699,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
}
/* ask the core to calculate the divisor */
- baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+ baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4);
spin_lock_irqsave(&sport->port.lock, flags);
@@ -1516,7 +1726,19 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
/* update the per-port timeout */
uart_update_timeout(port, termios->c_cflag, baud);
- /* wait transmit engin complete */
+ if (sport->lpuart_dma_rx_use) {
+ /* Calculate delay for 1.5 DMA buffers */
+ sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
+ sport->rxdma_len * 3 /
+ sport->rxfifo_size / 2;
+ dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
+ sport->dma_rx_timeout * 1000 / HZ, sport->port.timeout);
+ if (sport->dma_rx_timeout < msecs_to_jiffies(20))
+ sport->dma_rx_timeout = msecs_to_jiffies(20);
+ }
+
+ /* wait transmit engin complete, there disable flow control */
+ lpuart32_write(0, sport->port.membase + UARTMODIR);
while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
barrier();
@@ -1524,15 +1746,10 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
lpuart32_write(old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
sport->port.membase + UARTCTRL);
- sbr = sport->port.uartclk / (16 * baud);
- bd &= ~UARTBAUD_SBR_MASK;
- bd |= sbr & UARTBAUD_SBR_MASK;
- bd |= UARTBAUD_BOTHEDGE;
- bd &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
lpuart32_write(bd, sport->port.membase + UARTBAUD);
+ lpuart32_serial_setbrg(sport, baud);
lpuart32_write(modem, sport->port.membase + UARTMODIR);
lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
- /* restore control register */
spin_unlock_irqrestore(&sport->port.lock, flags);
}
@@ -1719,7 +1936,10 @@ lpuart_console_get_options(struct lpuart_port *sport, int *baud,
brfa = readb(sport->port.membase + UARTCR4);
brfa &= UARTCR4_BRFA_MASK;
- uartclk = clk_get_rate(sport->clk);
+ if (sport->per_clk)
+ uartclk = clk_get_rate(sport->per_clk);
+ else
+ uartclk = clk_get_rate(sport->ipg_clk);
/*
* baud = mod_clk/(16*(sbr[13]+(brfa)/32)
*/
@@ -1735,7 +1955,7 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
int *parity, int *bits)
{
unsigned long cr, bd;
- unsigned int sbr, uartclk, baud_raw;
+ unsigned int sbr, osr, uartclk, baud_raw;
cr = lpuart32_read(sport->port.membase + UARTCTRL);
cr &= UARTCTRL_TE | UARTCTRL_RE;
@@ -1762,12 +1982,13 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
bd = lpuart32_read(sport->port.membase + UARTBAUD);
bd &= UARTBAUD_SBR_MASK;
sbr = bd;
- uartclk = clk_get_rate(sport->clk);
- /*
- * baud = mod_clk/(16*(sbr[13]+(brfa)/32)
- */
- baud_raw = uartclk / (16 * sbr);
+ osr = (bd >> UARTBAUD_OSR_SHIFT) & UARTBAUD_OSR_MASK;
+ if (sport->per_clk)
+ uartclk = clk_get_rate(sport->per_clk);
+ else
+ uartclk = clk_get_rate(sport->ipg_clk);
+ baud_raw = uartclk / ((osr + 1) * sbr);
if (*baud != baud_raw)
printk(KERN_INFO "Serial: Console lpuart rounded baud rate"
"from %d to %d\n", baud_raw, *baud);
@@ -1780,6 +2001,7 @@ static int __init lpuart_console_setup(struct console *co, char *options)
int bits = 8;
int parity = 'n';
int flow = 'n';
+ int ret;
/*
* check whether an invalid uart number has been specified, and
@@ -1793,6 +2015,15 @@ static int __init lpuart_console_setup(struct console *co, char *options)
if (sport == NULL)
return -ENODEV;
+ ret = clk_prepare_enable(sport->ipg_clk);
+ if (ret)
+ return ret;
+ ret = clk_prepare_enable(sport->per_clk);
+ if (ret) {
+ clk_disable_unprepare(sport->ipg_clk);
+ return ret;
+ }
+
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
@@ -1830,21 +2061,24 @@ static struct console lpuart32_console = {
.data = &lpuart_reg,
};
-static void lpuart_early_write(struct console *con, const char *s, unsigned n)
+static void
+lpuart_early_write(struct console *con, const char *s, unsigned int n)
{
struct earlycon_device *dev = con->data;
uart_console_write(&dev->port, s, n, lpuart_console_putchar);
}
-static void lpuart32_early_write(struct console *con, const char *s, unsigned n)
+static void
+lpuart32_early_write(struct console *con, const char *s, unsigned int n)
{
struct earlycon_device *dev = con->data;
uart_console_write(&dev->port, s, n, lpuart32_console_putchar);
}
-static int __init lpuart_early_console_setup(struct earlycon_device *device,
+static int __init
+lpuart_early_console_setup(struct earlycon_device *device,
const char *opt)
{
if (!device->port.membase)
@@ -1854,8 +2088,8 @@ static int __init lpuart_early_console_setup(struct earlycon_device *device,
return 0;
}
-static int __init lpuart32_early_console_setup(struct earlycon_device *device,
- const char *opt)
+static int __init
+lpuart32_early_console_setup(struct earlycon_device *device, const char *opt)
{
if (!device->port.membase)
return -ENODEV;
@@ -1864,8 +2098,12 @@ static int __init lpuart32_early_console_setup(struct earlycon_device *device,
return 0;
}
-OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
-OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart",
+ lpuart_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart",
+ lpuart32_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,lpuart",
+ lpuart32_early_console_setup);
EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
@@ -1895,15 +2133,14 @@ static int lpuart_probe(struct platform_device *pdev)
if (!sport)
return -ENOMEM;
- pdev->dev.coherent_dma_mask = 0;
-
ret = of_alias_get_id(np, "serial");
if (ret < 0) {
dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
return ret;
}
sport->port.line = ret;
- sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
+ sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart") |
+ of_device_is_compatible(np, "fsl,imx7ulp-lpuart");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
@@ -1927,22 +2164,34 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.ops = &lpuart_pops;
sport->port.flags = UPF_BOOT_AUTOCONF;
- sport->port.rs485_config = lpuart_config_rs485;
+ if (!sport->lpuart32)
+ sport->port.rs485_config = lpuart_config_rs485;
- sport->clk = devm_clk_get(&pdev->dev, "ipg");
- if (IS_ERR(sport->clk)) {
- ret = PTR_ERR(sport->clk);
- dev_err(&pdev->dev, "failed to get uart clk: %d\n", ret);
+ sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+ if (IS_ERR(sport->ipg_clk)) {
+ ret = PTR_ERR(sport->per_clk);
+ dev_err(&pdev->dev, "failed to get ipg clk: %d\n", ret);
return ret;
}
+ sport->per_clk = devm_clk_get(&pdev->dev, "per");
+ if (IS_ERR(sport->per_clk))
+ sport->per_clk = NULL;
- ret = clk_prepare_enable(sport->clk);
+ ret = clk_prepare_enable(sport->ipg_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable uart ipg clk: %d\n", ret);
+ return ret;
+ }
+ ret = clk_prepare_enable(sport->per_clk);
if (ret) {
+ clk_disable_unprepare(sport->ipg_clk);
dev_err(&pdev->dev, "failed to enable uart clk: %d\n", ret);
return ret;
}
-
- sport->port.uartclk = clk_get_rate(sport->clk);
+ if (sport->per_clk)
+ sport->port.uartclk = clk_get_rate(sport->per_clk);
+ else
+ sport->port.uartclk = clk_get_rate(sport->ipg_clk);
lpuart_ports[sport->port.line] = sport;
@@ -1955,26 +2204,28 @@ static int lpuart_probe(struct platform_device *pdev)
ret = uart_add_one_port(&lpuart_reg, &sport->port);
if (ret) {
- clk_disable_unprepare(sport->clk);
+ clk_disable_unprepare(sport->per_clk);
+ clk_disable_unprepare(sport->ipg_clk);
return ret;
}
sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
if (!sport->dma_tx_chan)
- dev_info(sport->port.dev, "DMA tx channel request failed, "
- "operating without tx DMA\n");
+ dev_info(sport->port.dev, "NO DMA tx channel, run at cpu mode\n");
sport->dma_rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
if (!sport->dma_rx_chan)
- dev_info(sport->port.dev, "DMA rx channel request failed, "
- "operating without rx DMA\n");
+ dev_info(sport->port.dev, "NO DMA rx channel, run at cpu mode\n");
- if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time")) {
+ if (!sport->lpuart32 &&
+ of_property_read_bool(np, "linux,rs485-enabled-at-boot-time")) {
sport->port.rs485.flags |= SER_RS485_ENABLED;
sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND;
writeb(UARTMODEM_TXRTSE, sport->port.membase + UARTMODEM);
}
+ clk_disable_unprepare(sport->per_clk);
+ clk_disable_unprepare(sport->ipg_clk);
return 0;
}
@@ -1984,8 +2235,6 @@ static int lpuart_remove(struct platform_device *pdev)
uart_remove_one_port(&lpuart_reg, &sport->port);
- clk_disable_unprepare(sport->clk);
-
if (sport->dma_tx_chan)
dma_release_channel(sport->dma_tx_chan);
@@ -1996,102 +2245,252 @@ static int lpuart_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM_SLEEP
+static void serial_lpuart_enable_wakeup(struct lpuart_port *sport, bool on)
+{
+ unsigned int val;
+
+ if (sport->lpuart32) {
+ val = lpuart32_read(sport->port.membase + UARTCTRL);
+ if (on)
+ val |= (UARTCTRL_RIE | UARTCTRL_ILIE);
+ else
+ val &= ~(UARTCTRL_RIE | UARTCTRL_ILIE);
+ lpuart32_write(val, sport->port.membase + UARTCTRL);
+ } else {
+ val = readb(sport->port.membase + UARTCR2);
+ if (on)
+ val |= UARTCR2_RIE;
+ else
+ val &= ~UARTCR2_RIE;
+ writeb(val, sport->port.membase + UARTCR2);
+ }
+}
+
+static int lpuart_suspend_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct lpuart_port *sport = platform_get_drvdata(pdev);
+
+ serial_lpuart_enable_wakeup(sport, true);
+
+ clk_disable(sport->ipg_clk);
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static int lpuart_resume_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct lpuart_port *sport = platform_get_drvdata(pdev);
+ unsigned int val;
+ int ret;
+
+ pinctrl_pm_select_default_state(dev);
+ ret = clk_enable(sport->ipg_clk);
+ if (ret)
+ return ret;
+
+ serial_lpuart_enable_wakeup(sport, false);
+
+ /* clear the wakeup flags */
+ if (sport->lpuart32) {
+ val = lpuart32_read(sport->port.membase + UARTSTAT);
+ lpuart32_write(val, sport->port.membase + UARTSTAT);
+ }
+
+ return 0;
+}
+
static int lpuart_suspend(struct device *dev)
{
struct lpuart_port *sport = dev_get_drvdata(dev);
+ struct tty_port *port = &sport->port.state->port;
unsigned long temp;
+ unsigned long flags;
+ int ret;
+
+ ret = clk_prepare_enable(sport->ipg_clk);
+ if (ret)
+ return ret;
+
+ uart_suspend_port(&lpuart_reg, &sport->port);
if (sport->lpuart32) {
- /* disable Rx/Tx and interrupts */
temp = lpuart32_read(sport->port.membase + UARTCTRL);
temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE);
lpuart32_write(temp, sport->port.membase + UARTCTRL);
} else {
- /* disable Rx/Tx and interrupts */
temp = readb(sport->port.membase + UARTCR2);
temp &= ~(UARTCR2_TE | UARTCR2_TIE | UARTCR2_TCIE);
writeb(temp, sport->port.membase + UARTCR2);
}
- uart_suspend_port(&lpuart_reg, &sport->port);
-
- if (sport->lpuart_dma_rx_use) {
- /*
- * EDMA driver during suspend will forcefully release any
- * non-idle DMA channels. If port wakeup is enabled or if port
- * is console port or 'no_console_suspend' is set the Rx DMA
- * cannot resume as as expected, hence gracefully release the
- * Rx DMA path before suspend and start Rx DMA path on resume.
- */
- if (sport->port.irq_wake) {
- del_timer_sync(&sport->lpuart_timer);
- lpuart_dma_rx_free(&sport->port);
- }
+ if (sport->lpuart_dma_rx_use && sport->port.irq_wake &&
+ tty_port_initialized(port)) {
+ spin_lock_irqsave(&sport->port.lock, flags);
+ lpuart_dma_stop(sport, false);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
- /* Disable Rx DMA to use UART port as wakeup source */
- writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_RDMAS,
- sport->port.membase + UARTCR5);
+ dmaengine_terminate_all(sport->dma_rx_chan);
+ del_timer_sync(&sport->lpuart_timer);
+ lpuart_dma_rx_free(&sport->port);
}
- if (sport->lpuart_dma_tx_use) {
+ if (sport->lpuart_dma_tx_use && sport->port.irq_wake &&
+ tty_port_initialized(port)) {
+ if (sport->lpuart32) {
+ temp = lpuart32_read(sport->port.membase + UARTBAUD);
+ temp &= ~UARTBAUD_TDMAE;
+ lpuart32_write(temp, sport->port.membase + UARTBAUD);
+ } else {
+ temp = readb(sport->port.membase + UARTCR5);
+ temp &= ~UARTCR5_TDMAS;
+ writeb(temp, sport->port.membase + UARTCR5);
+ }
sport->dma_tx_in_progress = false;
dmaengine_terminate_all(sport->dma_tx_chan);
}
- if (sport->port.suspended && !sport->port.irq_wake)
- clk_disable_unprepare(sport->clk);
-
return 0;
}
-static int lpuart_resume(struct device *dev)
+static inline void lpuart32_resume_init(struct lpuart_port *sport)
{
- struct lpuart_port *sport = dev_get_drvdata(dev);
+ struct tty_port *port = &sport->port.state->port;
unsigned long temp;
+ unsigned long flags;
- if (sport->port.suspended && !sport->port.irq_wake)
- clk_prepare_enable(sport->clk);
+ spin_lock_irqsave(&sport->port.lock, flags);
+ lpuart32_setup_watermark(sport);
+
+ temp = lpuart32_read(sport->port.membase + UARTCTRL);
+ temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE |
+ UARTCTRL_TE | UARTCTRL_ILIE);
+
+ if (sport->dma_rx_chan)
+ temp &= ~(UARTCTRL_RIE | UARTCTRL_ILIE | UARTCTRL_RE);
+
+ if (sport->dma_tx_chan)
+ temp &= ~(UARTCTRL_TIE | UARTCTRL_TE);
+
+ lpuart32_write(temp, sport->port.membase + UARTCTRL);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+
+ if (sport->lpuart_dma_rx_use && sport->port.irq_wake &&
+ tty_port_initialized(port)) {
+ if (!lpuart_dma_rx_request(&sport->port)) {
+ sport->lpuart_dma_rx_use = true;
+ setup_timer(&sport->lpuart_timer, lpuart_timer_func,
+ (unsigned long)sport);
+ } else {
+ sport->lpuart_dma_rx_use = false;
+ }
- if (sport->lpuart32) {
- lpuart32_setup_watermark(sport);
temp = lpuart32_read(sport->port.membase + UARTCTRL);
- temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE |
- UARTCTRL_TE | UARTCTRL_ILIE);
+ temp |= (UARTCTRL_RIE | UARTCTRL_ILIE | UARTCTRL_RE);
+ temp |= UARTCTRL_IDLECFG << UARTCTRL_IDLECFG_OFF;
lpuart32_write(temp, sport->port.membase + UARTCTRL);
- } else {
- lpuart_setup_watermark(sport);
- temp = readb(sport->port.membase + UARTCR2);
- temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE);
- writeb(temp, sport->port.membase + UARTCR2);
}
- if (sport->lpuart_dma_rx_use) {
- if (sport->port.irq_wake) {
- if (!lpuart_start_rx_dma(sport)) {
- sport->lpuart_dma_rx_use = true;
- rx_dma_timer_init(sport);
- } else {
- sport->lpuart_dma_rx_use = false;
- }
+ if (sport->lpuart_dma_tx_use && sport->port.irq_wake &&
+ tty_port_initialized(port)) {
+ if (!lpuart_dma_tx_request(&sport->port)) {
+ init_waitqueue_head(&sport->dma_wait);
+ temp = lpuart32_read(sport->port.membase + UARTBAUD);
+ temp |= UARTBAUD_TDMAE;
+ lpuart32_write(temp, sport->port.membase + UARTBAUD);
+ } else {
+ sport->lpuart_dma_tx_use = false;
}
+
+ temp = lpuart32_read(sport->port.membase + UARTCTRL);
+ temp |= UARTCTRL_TE;
+ lpuart32_write(temp, sport->port.membase + UARTCTRL);
}
+}
+
+static inline void lpuart_resume_init(struct lpuart_port *sport)
+{
+ struct tty_port *port = &sport->port.state->port;
+ unsigned char temp;
+ unsigned long flags;
- if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) {
+ spin_lock_irqsave(&sport->port.lock, flags);
+ lpuart_setup_watermark(sport);
+ temp = readb(sport->port.membase + UARTCR2);
+ temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE);
+
+ if (sport->dma_rx_chan)
+ temp &= ~(UARTCR2_RIE | UARTCR2_RE);
+
+ if (sport->dma_tx_chan)
+ temp &= ~(UARTCR2_TIE | UARTCR2_TE);
+
+ writeb(temp, sport->port.membase + UARTCR2);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+
+ if (sport->lpuart_dma_rx_use && sport->port.irq_wake &&
+ tty_port_initialized(port)) {
+ if (!lpuart_dma_rx_request(&sport->port)) {
+ sport->lpuart_dma_rx_use = true;
+ setup_timer(&sport->lpuart_timer,
+ lpuart_timer_func,
+ (unsigned long)sport);
+ } else {
+ sport->lpuart_dma_rx_use = false;
+ }
+
+ temp = readb(sport->port.membase + UARTCR2);
+ temp |= (UARTCR2_RIE | UARTCR2_RE);
+ writeb(temp, sport->port.membase + UARTCR2);
+ }
+
+ if (sport->lpuart_dma_tx_use && sport->port.irq_wake &&
+ tty_port_initialized(port)) {
+ if (!lpuart_dma_tx_request(&sport->port)) {
init_waitqueue_head(&sport->dma_wait);
- sport->lpuart_dma_tx_use = true;
- writeb(readb(sport->port.membase + UARTCR5) |
- UARTCR5_TDMAS, sport->port.membase + UARTCR5);
- } else {
- sport->lpuart_dma_tx_use = false;
+ temp = readb(sport->port.membase + UARTCR5);
+ temp |= UARTCR5_TDMAS;
+ writeb(temp, sport->port.membase + UARTCR5);
+ } else {
+ sport->lpuart_dma_tx_use = false;
+ }
+
+ temp = readb(sport->port.membase + UARTCR2);
+ temp |= UARTCR2_TE;
+ writeb(temp, sport->port.membase + UARTCR2);
}
+}
+
+static int lpuart_resume(struct device *dev)
+{
+ struct lpuart_port *sport = dev_get_drvdata(dev);
+
+ if (sport->lpuart32)
+ lpuart32_resume_init(sport);
+ else
+ lpuart_resume_init(sport);
uart_resume_port(&lpuart_reg, &sport->port);
+ clk_disable_unprepare(sport->ipg_clk);
+
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(lpuart_pm_ops, lpuart_suspend, lpuart_resume);
+static const struct dev_pm_ops lpuart_pm_ops = {
+ .suspend_noirq = lpuart_suspend_noirq,
+ .resume_noirq = lpuart_resume_noirq,
+ .suspend = lpuart_suspend,
+ .resume = lpuart_resume,
+};
+#define SERIAL_LPUART_PM_OPS (&lpuart_pm_ops)
+
+#else /* !CONFIG_PM_SLEEP */
+
+#define SERIAL_LPUART_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
static struct platform_driver lpuart_driver = {
.probe = lpuart_probe,
@@ -2099,7 +2498,7 @@ static struct platform_driver lpuart_driver = {
.driver = {
.name = "fsl-lpuart",
.of_match_table = lpuart_dt_ids,
- .pm = &lpuart_pm_ops,
+ .pm = SERIAL_LPUART_PM_OPS,
},
};
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 521a6e450755..fe070db12a03 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -34,6 +34,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/rational.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -185,6 +186,8 @@
#define DRIVER_NAME "IMX-uart"
#define UART_NR 8
+#define IMX_RXBD_NUM 20
+#define IMX_MODULE_MAX_CLK_RATE 80000000
/* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
enum imx_uart_type {
@@ -200,6 +203,24 @@ struct imx_uart_data {
enum imx_uart_type devtype;
};
+struct imx_dma_bufinfo {
+ bool filled;
+ unsigned int rx_bytes;
+};
+
+struct imx_dma_rxbuf {
+ unsigned int periods;
+ unsigned int period_len;
+ unsigned int buf_len;
+
+ void *buf;
+ dma_addr_t dmaaddr;
+ unsigned int cur_idx;
+ unsigned int last_completed_idx;
+ dma_cookie_t cookie;
+ struct imx_dma_bufinfo buf_info[IMX_RXBD_NUM];
+};
+
struct imx_port {
struct uart_port port;
struct timer_list timer;
@@ -221,16 +242,16 @@ struct imx_port {
unsigned int dma_is_rxing:1;
unsigned int dma_is_txing:1;
struct dma_chan *dma_chan_rx, *dma_chan_tx;
- struct scatterlist rx_sgl, tx_sgl[2];
- void *rx_buf;
- struct circ_buf rx_ring;
- unsigned int rx_periods;
- dma_cookie_t rx_cookie;
+ struct scatterlist tx_sgl[2];
+ struct imx_dma_rxbuf rx_buf;
unsigned int tx_bytes;
unsigned int dma_tx_nents;
+ struct work_struct tsk_dma_tx;
wait_queue_head_t dma_wait;
unsigned int saved_reg[10];
bool context_saved;
+#define DMA_TX_IS_WORKING 1
+ unsigned long flags;
};
struct imx_port_ucrs {
@@ -405,12 +426,14 @@ static void imx_stop_rx(struct uart_port *port)
}
}
- temp = readl(sport->port.membase + UCR2);
- writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2);
-
- /* disable the `Receiver Ready Interrrupt` */
+ /* disable the Receiver Ready and overrun Interrrupt */
temp = readl(sport->port.membase + UCR1);
writel(temp & ~UCR1_RRDYEN, sport->port.membase + UCR1);
+ temp = readl(sport->port.membase + UCR4);
+ writel(temp & ~UCR4_OREN, sport->port.membase + UCR4);
+
+ temp = readl(sport->port.membase + UCR2);
+ writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2);
}
/*
@@ -425,7 +448,6 @@ static void imx_enable_ms(struct uart_port *port)
mctrl_gpio_enable_ms(sport->gpios);
}
-static void imx_dma_tx(struct imx_port *sport);
static inline void imx_transmit_buffer(struct imx_port *sport)
{
struct circ_buf *xmit = &sport->port.state->xmit;
@@ -456,7 +478,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
writel(temp, sport->port.membase + UCR1);
} else {
writel(temp, sport->port.membase + UCR1);
- imx_dma_tx(sport);
+ schedule_work(&sport->tsk_dma_tx);
}
}
@@ -482,95 +504,89 @@ static void dma_tx_callback(void *data)
struct scatterlist *sgl = &sport->tx_sgl[0];
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long flags;
- unsigned long temp;
-
- spin_lock_irqsave(&sport->port.lock, flags);
dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
- temp = readl(sport->port.membase + UCR1);
- temp &= ~UCR1_TDMAEN;
- writel(temp, sport->port.membase + UCR1);
+ sport->dma_is_txing = 0;
/* update the stat */
+ spin_lock_irqsave(&sport->port.lock, flags);
xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1);
sport->port.icount.tx += sport->tx_bytes;
+ spin_unlock_irqrestore(&sport->port.lock, flags);
dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
- sport->dma_is_txing = 0;
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
+ clear_bit(DMA_TX_IS_WORKING, &sport->flags);
+ smp_mb__after_atomic();
+ uart_write_wakeup(&sport->port);
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&sport->port);
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port))
+ schedule_work(&sport->tsk_dma_tx);
if (waitqueue_active(&sport->dma_wait)) {
wake_up(&sport->dma_wait);
dev_dbg(sport->port.dev, "exit in %s.\n", __func__);
return;
}
-
- spin_lock_irqsave(&sport->port.lock, flags);
- if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port))
- imx_dma_tx(sport);
- spin_unlock_irqrestore(&sport->port.lock, flags);
}
-static void imx_dma_tx(struct imx_port *sport)
+static void dma_tx_work(struct work_struct *w)
{
+ struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx);
struct circ_buf *xmit = &sport->port.state->xmit;
struct scatterlist *sgl = sport->tx_sgl;
struct dma_async_tx_descriptor *desc;
struct dma_chan *chan = sport->dma_chan_tx;
struct device *dev = sport->port.dev;
- unsigned long temp;
+ unsigned long flags;
int ret;
- if (sport->dma_is_txing)
+ if (test_and_set_bit(DMA_TX_IS_WORKING, &sport->flags))
return;
+ spin_lock_irqsave(&sport->port.lock, flags);
sport->tx_bytes = uart_circ_chars_pending(xmit);
- if (xmit->tail < xmit->head) {
- sport->dma_tx_nents = 1;
- sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
- } else {
- sport->dma_tx_nents = 2;
- sg_init_table(sgl, 2);
- sg_set_buf(sgl, xmit->buf + xmit->tail,
- UART_XMIT_SIZE - xmit->tail);
- sg_set_buf(sgl + 1, xmit->buf, xmit->head);
- }
+ if (sport->tx_bytes > 0) {
+ if (xmit->tail > xmit->head && xmit->head > 0) {
+ sport->dma_tx_nents = 2;
+ sg_init_table(sgl, 2);
+ sg_set_buf(sgl, xmit->buf + xmit->tail,
+ UART_XMIT_SIZE - xmit->tail);
+ sg_set_buf(sgl + 1, xmit->buf, xmit->head);
+ } else {
+ sport->dma_tx_nents = 1;
+ sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
+ }
+ spin_unlock_irqrestore(&sport->port.lock, flags);
- ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
- if (ret == 0) {
- dev_err(dev, "DMA mapping error for TX.\n");
- return;
- }
- desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents,
- DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
- if (!desc) {
- dma_unmap_sg(dev, sgl, sport->dma_tx_nents,
- DMA_TO_DEVICE);
- dev_err(dev, "We cannot prepare for the TX slave dma!\n");
+ ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
+ if (ret == 0) {
+ dev_err(dev, "DMA mapping error for TX.\n");
+ goto err_out;
+ }
+ desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents,
+ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
+ if (!desc) {
+ dev_err(dev, "We cannot prepare for the TX slave dma!\n");
+ goto err_out;
+ }
+ desc->callback = dma_tx_callback;
+ desc->callback_param = sport;
+
+ dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n",
+ uart_circ_chars_pending(xmit));
+ /* fire it */
+ sport->dma_is_txing = 1;
+ dmaengine_submit(desc);
+ dma_async_issue_pending(chan);
return;
}
- desc->callback = dma_tx_callback;
- desc->callback_param = sport;
-
- dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n",
- uart_circ_chars_pending(xmit));
-
- temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_TDMAEN;
- writel(temp, sport->port.membase + UCR1);
-
- /* fire it */
- sport->dma_is_txing = 1;
- dmaengine_submit(desc);
- dma_async_issue_pending(chan);
- return;
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+err_out:
+ clear_bit(DMA_TX_IS_WORKING, &sport->flags);
+ smp_mb__after_atomic();
}
/*
@@ -615,7 +631,7 @@ static void imx_start_tx(struct uart_port *port)
if (!uart_circ_empty(&port->state->xmit) &&
!uart_tx_stopped(port))
- imx_dma_tx(sport);
+ schedule_work(&sport->tsk_dma_tx);
return;
}
}
@@ -718,56 +734,22 @@ out:
return IRQ_HANDLED;
}
-static void clear_rx_errors(struct imx_port *sport);
-static int start_rx_dma(struct imx_port *sport);
-/*
- * If the RXFIFO is filled with some data, and then we
- * arise a DMA operation to receive them.
- */
-static void imx_dma_rxint(struct imx_port *sport)
-{
- unsigned long temp;
- unsigned long flags;
-
- spin_lock_irqsave(&sport->port.lock, flags);
-
- temp = readl(sport->port.membase + USR2);
- if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
- sport->dma_is_rxing = 1;
-
- /* disable the receiver ready and aging timer interrupts */
- temp = readl(sport->port.membase + UCR1);
- temp &= ~(UCR1_RRDYEN);
- writel(temp, sport->port.membase + UCR1);
-
- temp = readl(sport->port.membase + UCR2);
- temp &= ~(UCR2_ATEN);
- writel(temp, sport->port.membase + UCR2);
-
- /* disable the rx errors interrupts */
- temp = readl(sport->port.membase + UCR4);
- temp &= ~UCR4_OREN;
- writel(temp, sport->port.membase + UCR4);
-
- /* tell the DMA to receive the data. */
- start_rx_dma(sport);
- }
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
/*
* We have a modem side uart, so the meanings of RTS and CTS are inverted.
*/
static unsigned int imx_get_hwmctrl(struct imx_port *sport)
{
- unsigned int tmp = TIOCM_DSR;
- unsigned usr1 = readl(sport->port.membase + USR1);
- unsigned usr2 = readl(sport->port.membase + USR2);
+ unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
+ unsigned int usr1 = readl(sport->port.membase + USR1);
+ unsigned int usr2 = readl(sport->port.membase + USR2);
+ unsigned int ucr2 = readl(sport->port.membase + UCR2);
if (usr1 & USR1_RTSS)
tmp |= TIOCM_CTS;
+ if (ucr2 & UCR2_CTS)
+ tmp |= TIOCM_RTS;
+
/* in DCE mode DCDIN is always 0 */
if (!(usr2 & USR2_DCDIN))
tmp |= TIOCM_CAR;
@@ -776,6 +758,9 @@ static unsigned int imx_get_hwmctrl(struct imx_port *sport)
if (!(readl(sport->port.membase + USR2) & USR2_RIIN))
tmp |= TIOCM_RI;
+ if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP)
+ tmp |= TIOCM_LOOP;
+
return tmp;
}
@@ -811,26 +796,22 @@ static irqreturn_t imx_int(int irq, void *dev_id)
struct imx_port *sport = dev_id;
unsigned int sts;
unsigned int sts2;
- irqreturn_t ret = IRQ_NONE;
sts = readl(sport->port.membase + USR1);
sts2 = readl(sport->port.membase + USR2);
- if (sts & (USR1_RRDY | USR1_AGTIM)) {
- if (sport->dma_is_enabled)
- imx_dma_rxint(sport);
- else
- imx_rxint(irq, dev_id);
- ret = IRQ_HANDLED;
+ if ((sts & USR1_RRDY || sts & USR1_AGTIM) &&
+ !sport->dma_is_enabled) {
+ if (sts & USR1_AGTIM)
+ writel(USR1_AGTIM, sport->port.membase + USR1);
+ imx_rxint(irq, dev_id);
}
if ((sts & USR1_TRDY &&
readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) ||
(sts2 & USR2_TXDC &&
- readl(sport->port.membase + UCR4) & UCR4_TCEN)) {
+ readl(sport->port.membase + UCR4) & UCR4_TCEN))
imx_txint(irq, dev_id);
- ret = IRQ_HANDLED;
- }
if (sts & USR1_DTRD) {
unsigned long flags;
@@ -841,27 +822,20 @@ static irqreturn_t imx_int(int irq, void *dev_id)
spin_lock_irqsave(&sport->port.lock, flags);
imx_mctrl_check(sport);
spin_unlock_irqrestore(&sport->port.lock, flags);
-
- ret = IRQ_HANDLED;
}
- if (sts & USR1_RTSD) {
+ if (sts & USR1_RTSD)
imx_rtsint(irq, dev_id);
- ret = IRQ_HANDLED;
- }
- if (sts & USR1_AWAKE) {
+ if (sts & USR1_AWAKE)
writel(USR1_AWAKE, sport->port.membase + USR1);
- ret = IRQ_HANDLED;
- }
if (sts2 & USR2_ORE) {
sport->port.icount.overrun++;
writel(USR2_ORE, sport->port.membase + USR2);
- ret = IRQ_HANDLED;
}
- return ret;
+ return IRQ_HANDLED;
}
/*
@@ -881,6 +855,9 @@ static unsigned int imx_tx_empty(struct uart_port *port)
return ret;
}
+/*
+ * We have a modem side uart, so the meanings of RTS and CTS are inverted.
+ */
static unsigned int imx_get_mctrl(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
@@ -937,6 +914,97 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore(&sport->port.lock, flags);
}
+#define TXTL 2 /* reset default */
+#define RXTL 1 /* For console port */
+#define RXTL_UART 16 /* For uart */
+
+static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
+{
+ unsigned int val;
+ unsigned int rx_fifo_trig;
+
+ if (uart_console(&sport->port))
+ rx_fifo_trig = RXTL;
+ else
+ rx_fifo_trig = RXTL_UART;
+
+ /* set receiver / transmitter trigger level */
+ val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
+ val |= TXTL << UFCR_TXTL_SHF | rx_fifo_trig;
+ writel(val, sport->port.membase + UFCR);
+ return 0;
+}
+
+#define RX_BUF_SIZE (PAGE_SIZE)
+static void dma_rx_push_data(struct imx_port *sport, struct tty_struct *tty,
+ unsigned int start, unsigned int end)
+{
+ unsigned int i;
+ struct tty_port *port = &sport->port.state->port;
+
+ for (i = start; i < end; i++) {
+ if (sport->rx_buf.buf_info[i].filled) {
+ tty_insert_flip_string(port, sport->rx_buf.buf + (i
+ * RX_BUF_SIZE), sport->rx_buf.buf_info[i].rx_bytes);
+ tty_flip_buffer_push(port);
+ sport->rx_buf.buf_info[i].filled = false;
+ sport->rx_buf.last_completed_idx++;
+ sport->rx_buf.last_completed_idx %= IMX_RXBD_NUM;
+ sport->port.icount.rx += sport->rx_buf.buf_info[i].rx_bytes;
+ }
+ }
+}
+
+static void dma_rx_work(struct imx_port *sport)
+{
+ struct tty_struct *tty = sport->port.state->port.tty;
+ unsigned int cur_idx = sport->rx_buf.cur_idx;
+
+ if (sport->rx_buf.last_completed_idx < cur_idx) {
+ dma_rx_push_data(sport, tty, sport->rx_buf.last_completed_idx + 1, cur_idx);
+ } else if (sport->rx_buf.last_completed_idx == (IMX_RXBD_NUM - 1)) {
+ dma_rx_push_data(sport, tty, 0, cur_idx);
+ } else {
+ dma_rx_push_data(sport, tty, sport->rx_buf.last_completed_idx + 1,
+ IMX_RXBD_NUM);
+ dma_rx_push_data(sport, tty, 0, cur_idx);
+ }
+}
+
+static void imx_rx_dma_done(struct imx_port *sport)
+{
+ sport->dma_is_rxing = 0;
+
+ /* Is the shutdown waiting for us? */
+ if (waitqueue_active(&sport->dma_wait))
+ wake_up(&sport->dma_wait);
+}
+
+static void clear_rx_errors(struct imx_port *sport)
+{
+ unsigned int status_usr1, status_usr2;
+
+ status_usr1 = readl(sport->port.membase + USR1);
+ status_usr2 = readl(sport->port.membase + USR2);
+
+ if (status_usr2 & USR2_BRCD) {
+ sport->port.icount.brk++;
+ writel(USR2_BRCD, sport->port.membase + USR2);
+ } else if (status_usr1 & USR1_FRAMERR) {
+ sport->port.icount.frame++;
+ writel(USR1_FRAMERR, sport->port.membase + USR1);
+ } else if (status_usr1 & USR1_PARITYERR) {
+ sport->port.icount.parity++;
+ writel(USR1_PARITYERR, sport->port.membase + USR1);
+ }
+
+ if (status_usr2 & USR2_ORE) {
+ sport->port.icount.overrun++;
+ writel(USR2_ORE, sport->port.membase + USR2);
+ }
+
+}
+
/*
* This is our per-port timeout handler, for checking the
* modem status signals.
@@ -955,184 +1023,96 @@ static void imx_timeout(unsigned long data)
}
}
-#define RX_BUF_SIZE (PAGE_SIZE)
-
/*
- * There are two kinds of RX DMA interrupts(such as in the MX6Q):
+ * There are three kinds of RX DMA interrupts(such as in the MX6Q):
* [1] the RX DMA buffer is full.
- * [2] the aging timer expires
+ * [2] the Aging timer expires(wait for 8 bytes long)
+ * [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
*
- * Condition [2] is triggered when a character has been sitting in the FIFO
- * for at least 8 byte durations.
+ * The [2] is trigger when a character was been sitting in the FIFO
+ * meanwhile [3] can wait for 32 bytes long when the RX line is
+ * on IDLE state and RxFIFO is empty.
*/
static void dma_rx_callback(void *data)
{
struct imx_port *sport = data;
struct dma_chan *chan = sport->dma_chan_rx;
- struct scatterlist *sgl = &sport->rx_sgl;
- struct tty_port *port = &sport->port.state->port;
+ struct tty_struct *tty = sport->port.state->port.tty;
struct dma_tx_state state;
- struct circ_buf *rx_ring = &sport->rx_ring;
enum dma_status status;
- unsigned int w_bytes = 0;
- unsigned int r_bytes;
- unsigned int bd_size;
+ unsigned int count;
- status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
+ /* If we have finish the reading. we will not accept any more data. */
+ if (tty->closing) {
+ imx_rx_dma_done(sport);
+ return;
+ }
+ status = dmaengine_tx_status(chan, sport->rx_buf.cookie, &state);
if (status == DMA_ERROR) {
dev_err(sport->port.dev, "DMA transaction error.\n");
clear_rx_errors(sport);
return;
}
- if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
-
- /*
- * The state-residue variable represents the empty space
- * relative to the entire buffer. Taking this in consideration
- * the head is always calculated base on the buffer total
- * length - DMA transaction residue. The UART script from the
- * SDMA firmware will jump to the next buffer descriptor,
- * once a DMA transaction if finalized (IMX53 RM - A.4.1.2.4).
- * Taking this in consideration the tail is always at the
- * beginning of the buffer descriptor that contains the head.
- */
-
- /* Calculate the head */
- rx_ring->head = sg_dma_len(sgl) - state.residue;
+ count = RX_BUF_SIZE - state.residue;
+ sport->rx_buf.buf_info[sport->rx_buf.cur_idx].filled = true;
+ sport->rx_buf.buf_info[sport->rx_buf.cur_idx].rx_bytes = count;
+ sport->rx_buf.cur_idx++;
+ sport->rx_buf.cur_idx %= IMX_RXBD_NUM;
+ dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
- /* Calculate the tail. */
- bd_size = sg_dma_len(sgl) / sport->rx_periods;
- rx_ring->tail = ((rx_ring->head-1) / bd_size) * bd_size;
+ if (sport->rx_buf.cur_idx == sport->rx_buf.last_completed_idx)
+ dev_err(sport->port.dev, "overwrite!\n");
- if (rx_ring->head <= sg_dma_len(sgl) &&
- rx_ring->head > rx_ring->tail) {
-
- /* Move data from tail to head */
- r_bytes = rx_ring->head - rx_ring->tail;
-
- /* CPU claims ownership of RX DMA buffer */
- dma_sync_sg_for_cpu(sport->port.dev, sgl, 1,
- DMA_FROM_DEVICE);
-
- w_bytes = tty_insert_flip_string(port,
- sport->rx_buf + rx_ring->tail, r_bytes);
-
- /* UART retrieves ownership of RX DMA buffer */
- dma_sync_sg_for_device(sport->port.dev, sgl, 1,
- DMA_FROM_DEVICE);
-
- if (w_bytes != r_bytes)
- sport->port.icount.buf_overrun++;
-
- sport->port.icount.rx += w_bytes;
- } else {
- WARN_ON(rx_ring->head > sg_dma_len(sgl));
- WARN_ON(rx_ring->head <= rx_ring->tail);
- }
- }
-
- if (w_bytes) {
- tty_flip_buffer_push(port);
- dev_dbg(sport->port.dev, "We get %d bytes.\n", w_bytes);
- }
+ if (count)
+ dma_rx_work(sport);
}
-/* RX DMA buffer periods */
-#define RX_DMA_PERIODS 4
-
static int start_rx_dma(struct imx_port *sport)
{
- struct scatterlist *sgl = &sport->rx_sgl;
struct dma_chan *chan = sport->dma_chan_rx;
- struct device *dev = sport->port.dev;
struct dma_async_tx_descriptor *desc;
- int ret;
-
- sport->rx_ring.head = 0;
- sport->rx_ring.tail = 0;
- sport->rx_periods = RX_DMA_PERIODS;
-
- sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
- ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
- if (ret == 0) {
- dev_err(dev, "DMA mapping error for RX.\n");
- return -EINVAL;
- }
- desc = dmaengine_prep_dma_cyclic(chan, sg_dma_address(sgl),
- sg_dma_len(sgl), sg_dma_len(sgl) / sport->rx_periods,
+ sport->rx_buf.periods = IMX_RXBD_NUM;
+ sport->rx_buf.period_len = RX_BUF_SIZE;
+ sport->rx_buf.buf_len = IMX_RXBD_NUM * RX_BUF_SIZE;
+ sport->rx_buf.cur_idx = 0;
+ sport->rx_buf.last_completed_idx = -1;
+ desc = dmaengine_prep_dma_cyclic(chan, sport->rx_buf.dmaaddr,
+ sport->rx_buf.buf_len, sport->rx_buf.period_len,
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
-
if (!desc) {
- dma_unmap_sg(dev, sgl, 1, DMA_FROM_DEVICE);
- dev_err(dev, "We cannot prepare for the RX slave dma!\n");
+ dev_err(sport->port.dev, "Prepare for the RX slave dma failed!\n");
return -EINVAL;
}
+
desc->callback = dma_rx_callback;
desc->callback_param = sport;
- dev_dbg(dev, "RX: prepare for the DMA.\n");
- sport->rx_cookie = dmaengine_submit(desc);
+ dev_dbg(sport->port.dev, "RX: prepare for the DMA.\n");
+ sport->rx_buf.cookie = dmaengine_submit(desc);
dma_async_issue_pending(chan);
- return 0;
-}
-
-static void clear_rx_errors(struct imx_port *sport)
-{
- unsigned int status_usr1, status_usr2;
-
- status_usr1 = readl(sport->port.membase + USR1);
- status_usr2 = readl(sport->port.membase + USR2);
-
- if (status_usr2 & USR2_BRCD) {
- sport->port.icount.brk++;
- writel(USR2_BRCD, sport->port.membase + USR2);
- } else if (status_usr1 & USR1_FRAMERR) {
- sport->port.icount.frame++;
- writel(USR1_FRAMERR, sport->port.membase + USR1);
- } else if (status_usr1 & USR1_PARITYERR) {
- sport->port.icount.parity++;
- writel(USR1_PARITYERR, sport->port.membase + USR1);
- }
-
- if (status_usr2 & USR2_ORE) {
- sport->port.icount.overrun++;
- writel(USR2_ORE, sport->port.membase + USR2);
- }
-
-}
-
-#define TXTL_DEFAULT 2 /* reset default */
-#define RXTL_DEFAULT 1 /* reset default */
-#define TXTL_DMA 8 /* DMA burst setting */
-#define RXTL_DMA 9 /* DMA burst setting */
-
-static void imx_setup_ufcr(struct imx_port *sport,
- unsigned char txwl, unsigned char rxwl)
-{
- unsigned int val;
- /* set receiver / transmitter trigger level */
- val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
- val |= txwl << UFCR_TXTL_SHF | rxwl;
- writel(val, sport->port.membase + UFCR);
+ sport->dma_is_rxing = 1;
+ return 0;
}
static void imx_uart_dma_exit(struct imx_port *sport)
{
if (sport->dma_chan_rx) {
- dmaengine_terminate_sync(sport->dma_chan_rx);
dma_release_channel(sport->dma_chan_rx);
sport->dma_chan_rx = NULL;
- sport->rx_cookie = -EINVAL;
- kfree(sport->rx_buf);
- sport->rx_buf = NULL;
+
+ if (sport->rx_buf.buf) {
+ dma_free_coherent(sport->port.dev, IMX_RXBD_NUM * RX_BUF_SIZE,
+ (void *)sport->rx_buf.buf,
+ sport->rx_buf.dmaaddr);
+ sport->rx_buf.buf = NULL;
+ }
}
if (sport->dma_chan_tx) {
- dmaengine_terminate_sync(sport->dma_chan_tx);
dma_release_channel(sport->dma_chan_tx);
sport->dma_chan_tx = NULL;
}
@@ -1144,7 +1124,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
{
struct dma_slave_config slave_config = {};
struct device *dev = sport->port.dev;
- int ret;
+ int ret, i;
/* Prepare for RX : */
sport->dma_chan_rx = dma_request_slave_channel(dev, "rx");
@@ -1157,20 +1137,25 @@ static int imx_uart_dma_init(struct imx_port *sport)
slave_config.direction = DMA_DEV_TO_MEM;
slave_config.src_addr = sport->port.mapbase + URXD0;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- /* one byte less than the watermark level to enable the aging timer */
- slave_config.src_maxburst = RXTL_DMA - 1;
+ slave_config.src_maxburst = RXTL_UART;
ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config);
if (ret) {
dev_err(dev, "error in RX dma configuration.\n");
goto err;
}
- sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (!sport->rx_buf) {
+ sport->rx_buf.buf = dma_alloc_coherent(sport->port.dev, IMX_RXBD_NUM * RX_BUF_SIZE,
+ &sport->rx_buf.dmaaddr, GFP_KERNEL);
+ if (!sport->rx_buf.buf) {
+ dev_err(dev, "cannot alloc DMA buffer.\n");
ret = -ENOMEM;
goto err;
}
- sport->rx_ring.buf = sport->rx_buf;
+
+ for (i = 0; i < IMX_RXBD_NUM; i++) {
+ sport->rx_buf.buf_info[i].rx_bytes = 0;
+ sport->rx_buf.buf_info[i].filled = false;
+ }
/* Prepare for TX : */
sport->dma_chan_tx = dma_request_slave_channel(dev, "tx");
@@ -1183,7 +1168,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr = sport->port.mapbase + URTX0;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- slave_config.dst_maxburst = TXTL_DMA;
+ slave_config.dst_maxburst = TXTL;
ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config);
if (ret) {
dev_err(dev, "error in TX dma configuration.");
@@ -1203,17 +1188,19 @@ static void imx_enable_dma(struct imx_port *sport)
unsigned long temp;
init_waitqueue_head(&sport->dma_wait);
+ sport->flags = 0;
/* set UCR1 */
temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN;
+ temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
+ /* wait for 32 idle frames for IDDMA interrupt */
+ UCR1_ICD_REG(3);
writel(temp, sport->port.membase + UCR1);
- temp = readl(sport->port.membase + UCR2);
- temp |= UCR2_ATEN;
- writel(temp, sport->port.membase + UCR2);
-
- imx_setup_ufcr(sport, TXTL_DMA, RXTL_DMA);
+ /* set UCR4 */
+ temp = readl(sport->port.membase + UCR4);
+ temp |= UCR4_IDDMAEN;
+ writel(temp, sport->port.membase + UCR4);
sport->dma_is_enabled = 1;
}
@@ -1229,10 +1216,13 @@ static void imx_disable_dma(struct imx_port *sport)
/* clear UCR2 */
temp = readl(sport->port.membase + UCR2);
- temp &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
+ temp &= ~(UCR2_CTSC | UCR2_CTS);
writel(temp, sport->port.membase + UCR2);
- imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ /* clear UCR4 */
+ temp = readl(sport->port.membase + UCR4);
+ temp &= ~UCR4_IDDMAEN;
+ writel(temp, sport->port.membase + UCR4);
sport->dma_is_enabled = 0;
}
@@ -1243,9 +1233,17 @@ static void imx_disable_dma(struct imx_port *sport)
static int imx_startup(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
+ struct tty_port *tty_port = &sport->port.state->port;
int retval, i;
unsigned long flags, temp;
+ /* some modem may need reset */
+ if (!tty_port_suspended(tty_port)) {
+ retval = device_reset(sport->port.dev);
+ if (retval && retval != -ENOENT)
+ return retval;
+ }
+
retval = clk_prepare_enable(sport->clk_per);
if (retval)
return retval;
@@ -1255,7 +1253,7 @@ static int imx_startup(struct uart_port *port)
return retval;
}
- imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ imx_setup_ufcr(sport, 0);
/* disable the DREN bit (Data Ready interrupt enable) before
* requesting IRQs
@@ -1268,11 +1266,6 @@ static int imx_startup(struct uart_port *port)
writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
- /* Can we enable the DMA support? */
- if (!uart_console(port) && !sport->dma_is_inited)
- imx_uart_dma_init(sport);
-
- spin_lock_irqsave(&sport->port.lock, flags);
/* Reset fifo's and state machines */
i = 100;
@@ -1283,18 +1276,28 @@ static int imx_startup(struct uart_port *port)
while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
udelay(1);
+ /* Can we enable the DMA support? */
+ if (is_imx6q_uart(sport) && !uart_console(port)
+ && !sport->dma_is_inited)
+ imx_uart_dma_init(sport);
+
+ if (sport->dma_is_inited)
+ INIT_WORK(&sport->tsk_dma_tx, dma_tx_work);
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+
/*
* Finally, clear and enable interrupts
*/
- writel(USR1_RTSD | USR1_DTRD, sport->port.membase + USR1);
+ writel(USR1_RTSD, sport->port.membase + USR1);
writel(USR2_ORE, sport->port.membase + USR2);
- if (sport->dma_is_inited && !sport->dma_is_enabled)
- imx_enable_dma(sport);
-
temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
-
+ if (!sport->dma_is_inited)
+ temp |= UCR1_RRDYEN;
+ if (sport->have_rtscts)
+ temp |= UCR1_RTSDEN;
+ temp |= UCR1_UARTEN;
writel(temp, sport->port.membase + UCR1);
temp = readl(sport->port.membase + UCR4);
@@ -1350,10 +1353,20 @@ static void imx_shutdown(struct uart_port *port)
unsigned long flags;
if (sport->dma_is_enabled) {
- sport->dma_is_rxing = 0;
- sport->dma_is_txing = 0;
- dmaengine_terminate_sync(sport->dma_chan_tx);
- dmaengine_terminate_sync(sport->dma_chan_rx);
+ int ret;
+
+ /* We have to wait for the DMA to finish. */
+ ret = wait_event_interruptible_timeout(sport->dma_wait,
+ !sport->dma_is_rxing && !sport->dma_is_txing,
+ msecs_to_jiffies(1));
+ if (ret <= 0) {
+ sport->dma_is_rxing = 0;
+ sport->dma_is_txing = 0;
+ dmaengine_terminate_all(sport->dma_chan_tx);
+ dmaengine_terminate_all(sport->dma_chan_rx);
+ }
+
+ cancel_work_sync(&sport->tsk_dma_tx);
spin_lock_irqsave(&sport->port.lock, flags);
imx_stop_tx(port);
@@ -1442,10 +1455,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct imx_port *sport = (struct imx_port *)port;
unsigned long flags;
- unsigned long ucr2, old_ucr1, old_ucr2;
- unsigned int baud, quot;
+ unsigned long ucr2, old_ucr1, old_txrxen, baud, quot;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
- unsigned long div, ufcr;
+ unsigned int div, ufcr;
unsigned long num, denom;
uint64_t tdiv64;
@@ -1493,7 +1505,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
imx_port_rts_active(sport, &ucr2);
}
-
if (termios->c_cflag & CSTOPB)
ucr2 |= UCR2_STPB;
if (termios->c_cflag & PARENB) {
@@ -1553,10 +1564,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
barrier();
/* then, disable everything */
- old_ucr2 = readl(sport->port.membase + UCR2);
- writel(old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN),
+ old_txrxen = readl(sport->port.membase + UCR2);
+ writel(old_txrxen & ~(UCR2_TXEN | UCR2_RXEN),
sport->port.membase + UCR2);
- old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
+ old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
/* custom-baudrate handling */
div = sport->port.uartclk / (baud * 16);
@@ -1597,11 +1608,21 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
writel(old_ucr1, sport->port.membase + UCR1);
/* set the parity, stop bits and data size */
- writel(ucr2 | old_ucr2, sport->port.membase + UCR2);
+ writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
imx_enable_ms(&sport->port);
+ if (sport->dma_is_inited && !sport->dma_is_enabled) {
+ imx_enable_dma(sport);
+ start_rx_dma(sport);
+ }
+
+ if (!sport->dma_is_enabled) {
+ ucr2 = readl(sport->port.membase + UCR2);
+ writel(ucr2 | UCR2_ATEN, sport->port.membase + UCR2);
+ }
+
spin_unlock_irqrestore(&sport->port.lock, flags);
}
@@ -1667,7 +1688,7 @@ static int imx_poll_init(struct uart_port *port)
if (retval)
clk_disable_unprepare(sport->clk_ipg);
- imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ imx_setup_ufcr(sport, 0);
spin_lock_irqsave(&sport->port.lock, flags);
@@ -1942,7 +1963,7 @@ imx_console_setup(struct console *co, char *options)
else
imx_console_get_options(sport, &baud, &parity, &bits);
- imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ imx_setup_ufcr(sport, 0);
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
@@ -2135,6 +2156,14 @@ static int serial_imx_probe(struct platform_device *pdev)
}
sport->port.uartclk = clk_get_rate(sport->clk_per);
+ if (sport->port.uartclk > IMX_MODULE_MAX_CLK_RATE) {
+ ret = clk_set_rate(sport->clk_per, IMX_MODULE_MAX_CLK_RATE);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "clk_set_rate() failed\n");
+ return ret;
+ }
+ }
+ sport->port.uartclk = clk_get_rate(sport->clk_per);
/* For register access, we only need to enable the ipg clock. */
ret = clk_prepare_enable(sport->clk_ipg);
@@ -2259,10 +2288,15 @@ static int imx_serial_port_suspend_noirq(struct device *dev)
if (ret)
return ret;
+ /* enable wakeup from i.MX UART */
+ serial_imx_enable_wakeup(sport, true);
+
serial_imx_save_context(sport);
clk_disable(sport->clk_ipg);
+ pinctrl_pm_select_sleep_state(dev);
+
return 0;
}
@@ -2270,14 +2304,23 @@ static int imx_serial_port_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
+ unsigned int val;
int ret;
+ pinctrl_pm_select_default_state(dev);
+
ret = clk_enable(sport->clk_ipg);
if (ret)
return ret;
serial_imx_restore_context(sport);
+ /* disable wakeup from i.MX UART */
+ serial_imx_enable_wakeup(sport, false);
+ val = readl(sport->port.membase + USR1);
+ if (val & (USR1_AWAKE | USR1_RTSD))
+ writel(USR1_AWAKE | USR1_RTSD, sport->port.membase + USR1);
+
clk_disable(sport->clk_ipg);
return 0;
@@ -2288,9 +2331,6 @@ static int imx_serial_port_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
- /* enable wakeup from i.MX UART */
- serial_imx_enable_wakeup(sport, true);
-
uart_suspend_port(&imx_reg, &sport->port);
/* Needed to enable clock in suspend_noirq */
@@ -2302,9 +2342,6 @@ static int imx_serial_port_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct imx_port *sport = platform_get_drvdata(pdev);
- /* disable wakeup from i.MX UART */
- serial_imx_enable_wakeup(sport, false);
-
uart_resume_port(&imx_reg, &sport->port);
clk_unprepare(sport->clk_ipg);
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 05bc4d631cb9..33c99e2fc8fe 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -125,12 +125,16 @@ enum ci_revision {
* @start: start this role
* @stop: stop this role
* @irq: irq handler for this role
+ * @suspend: system suspend handler for this role
+ * @resume: system resume handler for this role
* @name: role name string (host/gadget)
*/
struct ci_role_driver {
int (*start)(struct ci_hdrc *);
void (*stop)(struct ci_hdrc *);
irqreturn_t (*irq)(struct ci_hdrc *);
+ void (*suspend)(struct ci_hdrc *);
+ void (*resume)(struct ci_hdrc *, bool power_lost);
const char *name;
};
@@ -174,6 +178,7 @@ struct hw_bank {
* @td_pool: allocation pool for transfer descriptors
* @gadget: device side representation for peripheral controller
* @driver: gadget driver
+ * @resume_state: save the state of gadget suspend from
* @hw_ep_max: total number of endpoints supported by hardware
* @ci_hw_ep: array of endpoints
* @ep0_dir: ep0 direction
@@ -193,12 +198,14 @@ struct hw_bank {
* @debugfs: root dentry for this controller in debugfs
* @id_event: indicates there is an id event, and handled at ci_otg_work
* @b_sess_valid_event: indicates there is a vbus event, and handled
+ * @vbus_glitch_check_event: check if vbus change is a glitch
* at ci_otg_work
* @imx28_write_fix: Freescale imx28 needs swp instruction for writing
* @supports_runtime_pm: if runtime pm is supported
* @in_lpm: if the core in low power mode
* @wakeup_int: if wakeup interrupt occur
* @rev: The revision number for controller
+ * @mutex: protect code from concorrent running
*/
struct ci_hdrc {
struct device *dev;
@@ -222,6 +229,7 @@ struct ci_hdrc {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
+ enum usb_device_state resume_state;
unsigned hw_ep_max;
struct ci_hw_ep ci_hw_ep[ENDPT_MAX];
u32 ep0_dir;
@@ -243,11 +251,25 @@ struct ci_hdrc {
struct dentry *debugfs;
bool id_event;
bool b_sess_valid_event;
+ bool vbus_glitch_check_event;
bool imx28_write_fix;
bool supports_runtime_pm;
bool in_lpm;
bool wakeup_int;
enum ci_revision rev;
+ /* register save area for suspend&resume */
+ u32 pm_command;
+ u32 pm_status;
+ u32 pm_intr_enable;
+ u32 pm_frame_index;
+ u32 pm_segment;
+ u32 pm_frame_list;
+ u32 pm_async_next;
+ u32 pm_configured_flag;
+ u32 pm_portsc;
+ u32 pm_usbmode;
+ struct work_struct power_lost_work;
+ struct mutex mutex;
};
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
@@ -267,9 +289,21 @@ static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role)
return -ENXIO;
ret = ci->roles[role]->start(ci);
- if (!ret)
- ci->role = role;
- return ret;
+ if (ret)
+ return ret;
+
+ ci->role = role;
+
+ if (ci->usb_phy) {
+ if (role == CI_ROLE_HOST)
+ usb_phy_set_mode(ci->usb_phy,
+ USB_MODE_HOST);
+ else
+ usb_phy_set_mode(ci->usb_phy,
+ USB_MODE_DEVICE);
+ }
+
+ return 0;
}
static inline void ci_role_stop(struct ci_hdrc *ci)
@@ -282,6 +316,9 @@ static inline void ci_role_stop(struct ci_hdrc *ci)
ci->role = CI_ROLE_END;
ci->roles[role]->stop(ci);
+
+ if (ci->usb_phy)
+ usb_phy_set_mode(ci->usb_phy, USB_MODE_NONE);
}
/**
@@ -429,6 +466,7 @@ int hw_port_test_set(struct ci_hdrc *ci, u8 mode);
u8 hw_port_test_get(struct ci_hdrc *ci);
void ci_platform_configure(struct ci_hdrc *ci);
+int hw_controller_reset(struct ci_hdrc *ci);
int dbg_create_files(struct ci_hdrc *ci);
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 099179457f60..c4847c51b3f1 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2016 Freescale Semiconductor, Inc.
* Copyright (C) 2012 Marek Vasut <marex@denx.de>
* on behalf of DENX Software Engineering GmbH
*
@@ -19,6 +19,12 @@
#include <linux/dma-mapping.h>
#include <linux/usb/chipidea.h>
#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regulator/consumer.h>
+#include <linux/busfreq-imx.h>
+#include <linux/pm_qos.h>
#include "ci.h"
#include "ci_hdrc_imx.h"
@@ -40,25 +46,29 @@ static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
.flags = CI_HDRC_IMX28_WRITE_FIX |
CI_HDRC_TURN_VBUS_EARLY_ON |
- CI_HDRC_DISABLE_STREAMING,
+ CI_HDRC_DISABLE_STREAMING |
+ CI_HDRC_IMX_EHCI_QUIRK,
};
static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
CI_HDRC_TURN_VBUS_EARLY_ON |
- CI_HDRC_DISABLE_STREAMING,
+ CI_HDRC_DISABLE_STREAMING |
+ CI_HDRC_IMX_EHCI_QUIRK,
};
static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
CI_HDRC_TURN_VBUS_EARLY_ON |
- CI_HDRC_DISABLE_HOST_STREAMING,
+ CI_HDRC_DISABLE_HOST_STREAMING |
+ CI_HDRC_IMX_EHCI_QUIRK,
};
static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
CI_HDRC_TURN_VBUS_EARLY_ON |
- CI_HDRC_DISABLE_HOST_STREAMING,
+ CI_HDRC_DISABLE_HOST_STREAMING |
+ CI_HDRC_IMX_EHCI_QUIRK,
};
static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = {
@@ -70,6 +80,12 @@ static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = {
.flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
};
+static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = {
+ .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+ CI_HDRC_IMX_EHCI_QUIRK |
+ CI_HDRC_PMQOS,
+};
+
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx23-usb", .data = &imx23_usb_data},
{ .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
@@ -79,6 +95,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
{ .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data},
{ .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
+ { .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
@@ -90,14 +107,60 @@ struct ci_hdrc_imx_data {
struct imx_usbmisc_data *usbmisc_data;
bool supports_runtime_pm;
bool in_lpm;
+ bool imx_usb_charger_detection;
+ struct usb_charger charger;
+ struct regmap *anatop;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pinctrl_hsic_active;
+ struct regulator *hsic_pad_regulator;
+ const struct ci_hdrc_imx_platform_flag *data;
/* SoC before i.mx6 (except imx23/imx28) needs three clks */
bool need_three_clks;
struct clk *clk_ipg;
struct clk *clk_ahb;
struct clk *clk_per;
/* --------------------------------- */
+ struct pm_qos_request pm_qos_req;
+};
+
+#ifdef CONFIG_POWER_SUPPLY
+static char *imx_usb_charger_supplied_to[] = {
+ "imx_usb_charger",
};
+static enum power_supply_property imx_usb_charger_power_props[] = {
+ POWER_SUPPLY_PROP_PRESENT, /* Charger detected */
+ POWER_SUPPLY_PROP_ONLINE, /* VBUS online */
+ POWER_SUPPLY_PROP_CURRENT_MAX, /* Maximum current in mA */
+};
+#endif
+
+static inline bool is_imx6q_con(struct ci_hdrc_imx_data *imx_data)
+{
+ return imx_data->data == &imx6q_usb_data;
+}
+
+static inline bool is_imx6sl_con(struct ci_hdrc_imx_data *imx_data)
+{
+ return imx_data->data == &imx6sl_usb_data;
+}
+
+static inline bool is_imx6sx_con(struct ci_hdrc_imx_data *imx_data)
+{
+ return imx_data->data == &imx6sx_usb_data;
+}
+
+static inline bool is_imx7d_con(struct ci_hdrc_imx_data *imx_data)
+{
+ return imx_data->data == &imx7d_usb_data;
+}
+
+static inline bool imx_has_hsic_con(struct ci_hdrc_imx_data *imx_data)
+{
+ return is_imx6q_con(imx_data) || is_imx6sl_con(imx_data)
+ || is_imx6sx_con(imx_data) || is_imx7d_con(imx_data);
+}
+
/* Common functions shared by usbmisc drivers */
static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
@@ -146,6 +209,26 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
if (of_find_property(np, "external-vbus-divider", NULL))
data->evdo = 1;
+ if (of_find_property(np, "osc-clkgate-delay", NULL)) {
+ ret = of_property_read_u32(np, "osc-clkgate-delay",
+ &data->osc_clkgate_delay);
+ if (ret) {
+ dev_err(dev,
+ "failed to get osc-clkgate-delay value\n");
+ return ERR_PTR(ret);
+ }
+ /*
+ * 0 <= osc_clkgate_delay <=7
+ * - 0x0 (default) is 0.5ms,
+ * - 0x1-0x7: 1-7ms
+ */
+ if (data->osc_clkgate_delay > 7) {
+ dev_err(dev,
+ "value of osc-clkgate-delay is incorrect\n");
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
return data;
}
@@ -247,16 +330,153 @@ static void imx_disable_unprepare_clks(struct device *dev)
}
}
+static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned event)
+{
+ struct device *dev = ci->dev->parent;
+ struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+ int ret = 0;
+
+ switch (event) {
+#ifdef CONFIG_POWER_SUPPLY
+ case CI_HDRC_CONTROLLER_VBUS_EVENT:
+ if (data->usbmisc_data && ci->vbus_active) {
+ if (data->imx_usb_charger_detection) {
+ ret = imx_usbmisc_charger_detection(
+ data->usbmisc_data, true);
+ if (!ret && data->charger.psy_desc.type !=
+ POWER_SUPPLY_TYPE_USB)
+ ret = CI_HDRC_NOTIFY_RET_DEFER_EVENT;
+ }
+ } else if (data->usbmisc_data && !ci->vbus_active) {
+ if (data->imx_usb_charger_detection)
+ ret = imx_usbmisc_charger_detection(
+ data->usbmisc_data, false);
+ }
+ break;
+ case CI_HDRC_CONTROLLER_CHARGER_POST_EVENT:
+ if (!data->imx_usb_charger_detection)
+ return ret;
+ imx_usbmisc_charger_secondary_detection(data->usbmisc_data);
+ break;
+#endif
+ case CI_HDRC_IMX_HSIC_ACTIVE_EVENT:
+ if (!IS_ERR(data->pinctrl) &&
+ !IS_ERR(data->pinctrl_hsic_active)) {
+ ret = pinctrl_select_state(data->pinctrl,
+ data->pinctrl_hsic_active);
+ if (ret)
+ dev_err(dev,
+ "hsic_active select failed, err=%d\n",
+ ret);
+ return ret;
+ }
+ break;
+ case CI_HDRC_IMX_HSIC_SUSPEND_EVENT:
+ if (data->usbmisc_data) {
+ ret = imx_usbmisc_hsic_set_connect(data->usbmisc_data);
+ if (ret)
+ dev_err(dev,
+ "hsic_set_connect failed, err=%d\n",
+ ret);
+ return ret;
+ }
+ break;
+ case CI_HDRC_IMX_TERM_SELECT_OVERRIDE_FS:
+ if (data->usbmisc_data)
+ return imx_usbmisc_term_select_override(
+ data->usbmisc_data, true, 1);
+ break;
+ case CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF:
+ if (data->usbmisc_data)
+ return imx_usbmisc_term_select_override(
+ data->usbmisc_data, false, 0);
+ break;
+ default:
+ dev_dbg(dev, "unknown event\n");
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_POWER_SUPPLY
+static int imx_usb_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct usb_charger *charger =
+ container_of(psy->desc, struct usb_charger, psy_desc);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = charger->present;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = charger->online;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = charger->max_current;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * imx_usb_register_charger - register a USB charger
+ * @charger: the charger to be initialized
+ * @name: name for the power supply
+
+ * Registers a power supply for the charger. The USB Controller
+ * driver will call this after filling struct usb_charger.
+ */
+static int imx_usb_register_charger(struct usb_charger *charger,
+ const char *name)
+{
+ struct power_supply_desc *desc = &charger->psy_desc;
+
+ if (!charger->dev)
+ return -EINVAL;
+
+ if (name)
+ desc->name = name;
+ else
+ desc->name = "imx_usb_charger";
+
+ charger->bc = BATTERY_CHARGING_SPEC_1_2;
+ mutex_init(&charger->lock);
+
+ desc->type = POWER_SUPPLY_TYPE_MAINS;
+ desc->properties = imx_usb_charger_power_props;
+ desc->num_properties = ARRAY_SIZE(imx_usb_charger_power_props);
+ desc->get_property = imx_usb_charger_get_property;
+
+ charger->psy = devm_power_supply_register(charger->dev,
+ &charger->psy_desc, NULL);
+ if (IS_ERR(charger->psy))
+ return PTR_ERR(charger->psy);
+
+ charger->psy->supplied_to = imx_usb_charger_supplied_to;
+ charger->psy->num_supplicants = sizeof(imx_usb_charger_supplied_to)
+ / sizeof(char *);
+
+ return 0;
+}
+#endif
+
static int ci_hdrc_imx_probe(struct platform_device *pdev)
{
struct ci_hdrc_imx_data *data;
struct ci_hdrc_platform_data pdata = {
.name = dev_name(&pdev->dev),
.capoffset = DEF_CAPOFFSET,
+ .notify_event = ci_hdrc_imx_notify_event,
};
int ret;
const struct of_device_id *of_id;
const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
+ struct device_node *np = pdev->dev.of_node;
+ struct pinctrl_state *pinctrl_hsic_idle;
of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
if (!of_id)
@@ -269,17 +489,54 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, data);
+
+ data->data = imx_platform_flag;
+ pdata.flags |= imx_platform_flag->flags;
data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
if (IS_ERR(data->usbmisc_data))
return PTR_ERR(data->usbmisc_data);
+ data->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(data->pinctrl)) {
+ dev_dbg(&pdev->dev, "pinctrl get failed, err=%ld\n",
+ PTR_ERR(data->pinctrl));
+ } else {
+ pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle");
+ if (IS_ERR(pinctrl_hsic_idle)) {
+ dev_dbg(&pdev->dev,
+ "pinctrl_hsic_idle lookup failed, err=%ld\n",
+ PTR_ERR(pinctrl_hsic_idle));
+ } else {
+ ret = pinctrl_select_state(data->pinctrl,
+ pinctrl_hsic_idle);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "hsic_idle select failed, err=%d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl,
+ "active");
+ if (IS_ERR(data->pinctrl_hsic_active))
+ dev_dbg(&pdev->dev,
+ "pinctrl_hsic_active lookup failed, err=%ld\n",
+ PTR_ERR(data->pinctrl_hsic_active));
+ }
+
ret = imx_get_clks(&pdev->dev);
if (ret)
return ret;
+ request_bus_freq(BUS_FREQ_HIGH);
+ if (pdata.flags & CI_HDRC_PMQOS)
+ pm_qos_add_request(&data->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, 0);
+
ret = imx_prepare_enable_clks(&pdev->dev);
if (ret)
- return ret;
+ goto err_bus_freq;
data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
if (IS_ERR(data->phy)) {
@@ -291,14 +548,73 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
}
pdata.usb_phy = data->phy;
- pdata.flags |= imx_platform_flag->flags;
if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
data->supports_runtime_pm = true;
+ if (data->usbmisc_data && data->usbmisc_data->index > 1
+ && (imx_has_hsic_con(data))) {
+ pdata.flags |= CI_HDRC_IMX_IS_HSIC;
+ data->hsic_pad_regulator = devm_regulator_get(&pdev->dev,
+ "pad");
+ if (PTR_ERR(data->hsic_pad_regulator) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_clk;
+ } else if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) {
+ /* no pad regualator is needed */
+ data->hsic_pad_regulator = NULL;
+ } else if (IS_ERR(data->hsic_pad_regulator)) {
+ dev_err(&pdev->dev,
+ "Get hsic pad regulator error: %ld\n",
+ PTR_ERR(data->hsic_pad_regulator));
+ ret = PTR_ERR(data->hsic_pad_regulator);
+ goto err_clk;
+ }
+
+ if (data->hsic_pad_regulator) {
+ ret = regulator_enable(data->hsic_pad_regulator);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Fail to enable hsic pad regulator\n");
+ goto err_clk;
+ }
+ }
+ }
+
+ if (of_find_property(np, "fsl,anatop", NULL) && data->usbmisc_data) {
+ data->anatop = syscon_regmap_lookup_by_phandle(np,
+ "fsl,anatop");
+ if (IS_ERR(data->anatop)) {
+ dev_dbg(&pdev->dev,
+ "failed to find regmap for anatop\n");
+ ret = PTR_ERR(data->anatop);
+ goto disable_hsic_regulator;
+ }
+ data->usbmisc_data->anatop = data->anatop;
+ }
+
+ if (of_find_property(np, "imx-usb-charger-detection", NULL) &&
+ data->usbmisc_data) {
+#ifdef CONFIG_POWER_SUPPLY
+ data->imx_usb_charger_detection = true;
+ data->charger.dev = &pdev->dev;
+ data->usbmisc_data->charger = &data->charger;
+ ret = imx_usb_register_charger(&data->charger,
+ "imx_usb_charger");
+ if (ret && ret != -ENODEV)
+ goto disable_hsic_regulator;
+ if (!ret)
+ dev_dbg(&pdev->dev,
+ "USB Charger is created\n");
+#else
+ dev_err(&pdev->dev,
+ "USB Charger requires CONFIG_POWER_SUPPLY\n");
+#endif
+ }
+
ret = imx_usbmisc_init(data->usbmisc_data);
if (ret) {
dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret);
- goto err_clk;
+ goto disable_hsic_regulator;
}
data->ci_pdev = ci_hdrc_add_device(&pdev->dev,
@@ -309,7 +625,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"ci_hdrc_add_device failed, err=%d\n", ret);
- goto err_clk;
+ goto disable_hsic_regulator;
}
ret = imx_usbmisc_init_post(data->usbmisc_data);
@@ -318,6 +634,17 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
goto disable_device;
}
+ ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
+ if (ret) {
+ dev_err(&pdev->dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
+ goto disable_device;
+ }
+
+ /* usbmisc needs to know dr mode to choose wakeup setting */
+ if (data->usbmisc_data)
+ data->usbmisc_data->available_role =
+ ci_hdrc_query_available_role(data->ci_pdev);
+
if (data->supports_runtime_pm) {
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
@@ -329,8 +656,15 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device:
ci_hdrc_remove_device(data->ci_pdev);
+disable_hsic_regulator:
+ if (data->hsic_pad_regulator)
+ ret = regulator_disable(data->hsic_pad_regulator);
err_clk:
imx_disable_unprepare_clks(&pdev->dev);
+err_bus_freq:
+ if (pdata.flags & CI_HDRC_PMQOS)
+ pm_qos_remove_request(&data->pm_qos_req);
+ release_bus_freq(BUS_FREQ_HIGH);
return ret;
}
@@ -345,6 +679,11 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
}
ci_hdrc_remove_device(data->ci_pdev);
imx_disable_unprepare_clks(&pdev->dev);
+ if (data->data->flags & CI_HDRC_PMQOS)
+ pm_qos_remove_request(&data->pm_qos_req);
+ release_bus_freq(BUS_FREQ_HIGH);
+ if (data->hsic_pad_regulator)
+ regulator_disable(data->hsic_pad_regulator);
return 0;
}
@@ -358,10 +697,23 @@ static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
static int imx_controller_suspend(struct device *dev)
{
struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+ int ret;
dev_dbg(dev, "at %s\n", __func__);
+ if (data->usbmisc_data) {
+ ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false);
+ if (ret) {
+ dev_err(dev,
+ "usbmisc hsic_set_clk failed, ret=%d\n", ret);
+ return ret;
+ }
+ }
+
imx_disable_unprepare_clks(dev);
+ if (data->data->flags & CI_HDRC_PMQOS)
+ pm_qos_remove_request(&data->pm_qos_req);
+ release_bus_freq(BUS_FREQ_HIGH);
data->in_lpm = true;
return 0;
@@ -379,22 +731,48 @@ static int imx_controller_resume(struct device *dev)
return 0;
}
+ request_bus_freq(BUS_FREQ_HIGH);
+ if (data->data->flags & CI_HDRC_PMQOS)
+ pm_qos_add_request(&data->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, 0);
ret = imx_prepare_enable_clks(dev);
if (ret)
- return ret;
+ goto err_bus_freq;
data->in_lpm = false;
+ ret = imx_usbmisc_power_lost_check(data->usbmisc_data);
+ /* re-init if resume from power lost */
+ if (ret > 0) {
+ ret = imx_usbmisc_init(data->usbmisc_data);
+ if (ret) {
+ dev_err(dev, "usbmisc init failed, ret=%d\n", ret);
+ goto clk_disable;
+ }
+ }
+
ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
if (ret) {
dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
goto clk_disable;
}
+ ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true);
+ if (ret) {
+ dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret);
+ goto hsic_set_clk_fail;
+ }
+
return 0;
+hsic_set_clk_fail:
+ imx_usbmisc_set_wakeup(data->usbmisc_data, true);
clk_disable:
imx_disable_unprepare_clks(dev);
+err_bus_freq:
+ if (data->data->flags & CI_HDRC_PMQOS)
+ pm_qos_remove_request(&data->pm_qos_req);
+ release_bus_freq(BUS_FREQ_HIGH);
return ret;
}
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 409aa5ca8dda..5ab88b54053f 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-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
@@ -11,18 +11,59 @@
#ifndef __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H
#define __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H
+#include <linux/usb/otg.h>
+#include <linux/power_supply.h>
+
+enum battery_charging_spec {
+ BATTERY_CHARGING_SPEC_NONE = 0,
+ BATTERY_CHARGING_SPEC_UNKNOWN,
+ BATTERY_CHARGING_SPEC_1_0,
+ BATTERY_CHARGING_SPEC_1_1,
+ BATTERY_CHARGING_SPEC_1_2,
+};
+
+struct usb_charger {
+ /* USB controller */
+ struct device *dev;
+ struct power_supply *psy;
+ struct power_supply_desc psy_desc;
+ struct mutex lock;
+
+ /* Compliant with Battery Charging Specification version (if any) */
+ enum battery_charging_spec bc;
+
+ /* properties */
+ unsigned present:1;
+ unsigned online:1;
+ unsigned max_current;
+};
struct imx_usbmisc_data {
struct device *dev;
int index;
+ struct regmap *anatop;
+ struct usb_charger *charger;
unsigned int disable_oc:1; /* over current detect disabled */
unsigned int oc_polarity:1; /* over current polarity if oc enabled */
unsigned int evdo:1; /* set external vbus divider option */
+ /*
+ * Specifies the delay between powering up the xtal 24MHz clock
+ * and release the clock to the digital logic inside the analog block
+ */
+ unsigned int osc_clkgate_delay;
+ enum usb_dr_mode available_role;
};
int imx_usbmisc_init(struct imx_usbmisc_data *);
int imx_usbmisc_init_post(struct imx_usbmisc_data *);
int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool);
+int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect);
+int imx_usbmisc_charger_secondary_detection(struct imx_usbmisc_data *data);
+int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *);
+int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *);
+int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *, bool);
+int imx_usbmisc_term_select_override(struct imx_usbmisc_data *data,
+ bool enable, int val);
#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 37591a4b1346..6d5cf973dba6 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -17,7 +17,7 @@
#define MSM_USB_BASE (ci->hw_bank.abs)
-static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
+static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
{
struct device *dev = ci->gadget.dev.parent;
@@ -40,6 +40,8 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
dev_dbg(dev, "unknown ci_hdrc event\n");
break;
}
+
+ return 0;
}
static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 6e0d614a8075..08a468683e0a 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -461,7 +461,7 @@ void ci_platform_configure(struct ci_hdrc *ci)
*
* This function returns an error code
*/
-static int hw_controller_reset(struct ci_hdrc *ci)
+int hw_controller_reset(struct ci_hdrc *ci)
{
int count = 0;
@@ -523,6 +523,13 @@ static irqreturn_t ci_irq(int irq, void *data)
u32 otgsc = 0;
if (ci->in_lpm) {
+ /*
+ * If we already have a wakeup irq pending there,
+ * let's just return to wait resume finished firstly.
+ */
+ if (ci->wakeup_int)
+ return IRQ_HANDLED;
+
disable_irq_nosync(irq);
ci->wakeup_int = true;
pm_runtime_get(ci->dev);
@@ -555,7 +562,7 @@ static irqreturn_t ci_irq(int irq, void *data)
* and disconnection events.
*/
if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) {
- ci->b_sess_valid_event = true;
+ ci->vbus_glitch_check_event = true;
/* Clear BSV irq */
hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
ci_otg_queue_work(ci);
@@ -569,35 +576,14 @@ static irqreturn_t ci_irq(int irq, void *data)
return ret;
}
-static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event,
- void *ptr)
-{
- struct ci_hdrc_cable *vbus = container_of(nb, struct ci_hdrc_cable, nb);
- struct ci_hdrc *ci = vbus->ci;
-
- if (event)
- vbus->state = true;
- else
- vbus->state = false;
-
- vbus->changed = true;
-
- ci_irq(ci->irq, ci);
- return NOTIFY_DONE;
-}
-
-static int ci_id_notifier(struct notifier_block *nb, unsigned long event,
- void *ptr)
+static int ci_cable_notifier(struct notifier_block *nb, unsigned long event,
+ void *ptr)
{
- struct ci_hdrc_cable *id = container_of(nb, struct ci_hdrc_cable, nb);
- struct ci_hdrc *ci = id->ci;
-
- if (event)
- id->state = false;
- else
- id->state = true;
+ struct ci_hdrc_cable *cbl = container_of(nb, struct ci_hdrc_cable, nb);
+ struct ci_hdrc *ci = cbl->ci;
- id->changed = true;
+ cbl->connected = event;
+ cbl->changed = true;
ci_irq(ci->irq, ci);
return NOTIFY_DONE;
@@ -706,27 +692,27 @@ static int ci_get_platdata(struct device *dev,
}
cable = &platdata->vbus_extcon;
- cable->nb.notifier_call = ci_vbus_notifier;
+ cable->nb.notifier_call = ci_cable_notifier;
cable->edev = ext_vbus;
if (!IS_ERR(ext_vbus)) {
- ret = extcon_get_cable_state_(cable->edev, EXTCON_USB);
+ ret = extcon_get_state(cable->edev, EXTCON_USB);
if (ret)
- cable->state = true;
+ cable->connected = true;
else
- cable->state = false;
+ cable->connected = false;
}
cable = &platdata->id_extcon;
- cable->nb.notifier_call = ci_id_notifier;
+ cable->nb.notifier_call = ci_cable_notifier;
cable->edev = ext_id;
if (!IS_ERR(ext_id)) {
- ret = extcon_get_cable_state_(cable->edev, EXTCON_USB_HOST);
+ ret = extcon_get_state(cable->edev, EXTCON_USB_HOST);
if (ret)
- cable->state = false;
+ cable->connected = true;
else
- cable->state = true;
+ cable->connected = false;
}
return 0;
}
@@ -739,8 +725,8 @@ static int ci_extcon_register(struct ci_hdrc *ci)
id = &ci->platdata->id_extcon;
id->ci = ci;
if (!IS_ERR(id->edev)) {
- ret = extcon_register_notifier(id->edev, EXTCON_USB_HOST,
- &id->nb);
+ ret = devm_extcon_register_notifier(ci->dev, id->edev,
+ EXTCON_USB_HOST, &id->nb);
if (ret < 0) {
dev_err(ci->dev, "register ID failed\n");
return ret;
@@ -750,11 +736,9 @@ static int ci_extcon_register(struct ci_hdrc *ci)
vbus = &ci->platdata->vbus_extcon;
vbus->ci = ci;
if (!IS_ERR(vbus->edev)) {
- ret = extcon_register_notifier(vbus->edev, EXTCON_USB,
- &vbus->nb);
+ ret = devm_extcon_register_notifier(ci->dev, vbus->edev,
+ EXTCON_USB, &vbus->nb);
if (ret < 0) {
- extcon_unregister_notifier(id->edev, EXTCON_USB_HOST,
- &id->nb);
dev_err(ci->dev, "register VBUS failed\n");
return ret;
}
@@ -763,20 +747,6 @@ static int ci_extcon_register(struct ci_hdrc *ci)
return 0;
}
-static void ci_extcon_unregister(struct ci_hdrc *ci)
-{
- struct ci_hdrc_cable *cable;
-
- cable = &ci->platdata->id_extcon;
- if (!IS_ERR(cable->edev))
- extcon_unregister_notifier(cable->edev, EXTCON_USB_HOST,
- &cable->nb);
-
- cable = &ci->platdata->vbus_extcon;
- if (!IS_ERR(cable->edev))
- extcon_unregister_notifier(cable->edev, EXTCON_USB, &cable->nb);
-}
-
static DEFINE_IDA(ci_ida);
struct platform_device *ci_hdrc_add_device(struct device *dev,
@@ -835,12 +805,39 @@ void ci_hdrc_remove_device(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(ci_hdrc_remove_device);
+/**
+ * ci_hdrc_query_available_role: get runtime available operation mode
+ *
+ * The glue layer can get current operation mode (host/peripheral/otg)
+ * This function should be called after ci core device has created.
+ *
+ * @pdev: the platform device of ci core.
+ *
+ * Return USB_DR_MODE_XXX.
+ */
+enum usb_dr_mode ci_hdrc_query_available_role(struct platform_device *pdev)
+{
+ struct ci_hdrc *ci = platform_get_drvdata(pdev);
+
+ if (!ci)
+ return USB_DR_MODE_UNKNOWN;
+ if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET])
+ return USB_DR_MODE_OTG;
+ else if (ci->roles[CI_ROLE_HOST])
+ return USB_DR_MODE_HOST;
+ else if (ci->roles[CI_ROLE_GADGET])
+ return USB_DR_MODE_PERIPHERAL;
+ else
+ return USB_DR_MODE_UNKNOWN;
+}
+EXPORT_SYMBOL_GPL(ci_hdrc_query_available_role);
+
static inline void ci_role_destroy(struct ci_hdrc *ci)
{
- ci_hdrc_gadget_destroy(ci);
- ci_hdrc_host_destroy(ci);
if (ci->is_otg)
ci_hdrc_otg_destroy(ci);
+ ci_hdrc_gadget_destroy(ci);
+ ci_hdrc_host_destroy(ci);
}
static void ci_get_otg_capable(struct ci_hdrc *ci)
@@ -859,6 +856,54 @@ static void ci_get_otg_capable(struct ci_hdrc *ci)
}
}
+static enum ci_role ci_get_role(struct ci_hdrc *ci)
+{
+ if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
+ if (ci->is_otg) {
+ hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);
+ return ci_otg_role(ci);
+ } else {
+ /*
+ * If the controller is not OTG capable, but support
+ * role switch, the defalt role is gadget, and the
+ * user can switch it through debugfs.
+ */
+ return CI_ROLE_GADGET;
+ }
+ } else {
+ return ci->roles[CI_ROLE_HOST]
+ ? CI_ROLE_HOST
+ : CI_ROLE_GADGET;
+ }
+}
+
+static void ci_start_new_role(struct ci_hdrc *ci)
+{
+ enum ci_role role = ci_get_role(ci);
+
+ if (ci->role != role) {
+ ci_handle_id_switch(ci);
+ } else if (role == CI_ROLE_GADGET) {
+ if (ci->vbus_active)
+ usb_gadget_vbus_disconnect(&ci->gadget);
+ ci_handle_vbus_connected(ci);
+ }
+}
+
+static void ci_power_lost_work(struct work_struct *work)
+{
+ struct ci_hdrc *ci = container_of(work, struct ci_hdrc,
+ power_lost_work);
+
+ pm_runtime_get_sync(ci->dev);
+ if (!ci_otg_is_fsm_mode(ci))
+ ci_start_new_role(ci);
+ else
+ ci_hdrc_otg_fsm_restart(ci);
+ pm_runtime_put_sync(ci->dev);
+ enable_irq(ci->irq);
+}
+
static int ci_hdrc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -963,30 +1008,12 @@ static int ci_hdrc_probe(struct platform_device *pdev)
}
}
- if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
- if (ci->is_otg) {
- ci->role = ci_otg_role(ci);
- /* Enable ID change irq */
- hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);
- } else {
- /*
- * If the controller is not OTG capable, but support
- * role switch, the defalt role is gadget, and the
- * user can switch it through debugfs.
- */
- ci->role = CI_ROLE_GADGET;
- }
- } else {
- ci->role = ci->roles[CI_ROLE_HOST]
- ? CI_ROLE_HOST
- : CI_ROLE_GADGET;
- }
+ ci->role = ci_get_role(ci);
+ /* only update vbus status for peripheral */
+ if (ci->role == CI_ROLE_GADGET)
+ ci_handle_vbus_connected(ci);
if (!ci_otg_is_fsm_mode(ci)) {
- /* only update vbus status for peripheral */
- if (ci->role == CI_ROLE_GADGET)
- ci_handle_vbus_change(ci);
-
ret = ci_role_start(ci, ci->role);
if (ret) {
dev_err(dev, "can't start %s role\n",
@@ -1018,11 +1045,14 @@ static int ci_hdrc_probe(struct platform_device *pdev)
device_set_wakeup_capable(&pdev->dev, true);
+ /* Init workqueue for controller power lost handling */
+ INIT_WORK(&ci->power_lost_work, ci_power_lost_work);
+ mutex_init(&ci->mutex);
+
ret = dbg_create_files(ci);
if (!ret)
return 0;
- ci_extcon_unregister(ci);
stop:
ci_role_destroy(ci);
deinit_phy:
@@ -1042,7 +1072,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
}
dbg_remove_files(ci);
- ci_extcon_unregister(ci);
ci_role_destroy(ci);
ci_hdrc_enter_lpm(ci, true);
ci_usb_phy_exit(ci);
@@ -1068,13 +1097,10 @@ static void ci_otg_fsm_wakeup_by_srp(struct ci_hdrc *ci)
{
if ((ci->fsm.otg->state == OTG_STATE_A_IDLE) &&
(ci->fsm.a_bus_drop == 1) && (ci->fsm.a_bus_req == 0)) {
- if (!hw_read_otgsc(ci, OTGSC_ID)) {
- ci->fsm.a_srp_det = 1;
- ci->fsm.a_bus_drop = 0;
- } else {
+ if (!hw_read_otgsc(ci, OTGSC_ID))
+ otg_add_timer(&ci->fsm, A_DP_END);
+ else
ci->fsm.id = 1;
- }
- ci_otg_queue_work(ci);
}
}
@@ -1090,6 +1116,29 @@ static void ci_controller_suspend(struct ci_hdrc *ci)
enable_irq(ci->irq);
}
+/*
+ * Handle the wakeup interrupt triggered by extcon connector
+ * We need to call ci_irq again for extcon since the first
+ * interrupt (wakeup int) only let the controller be out of
+ * low power mode, but not handle any interrupts.
+ */
+static void ci_extcon_wakeup_int(struct ci_hdrc *ci)
+{
+ struct ci_hdrc_cable *cable_id, *cable_vbus;
+ u32 otgsc = hw_read_otgsc(ci, ~0);
+
+ cable_id = &ci->platdata->id_extcon;
+ cable_vbus = &ci->platdata->vbus_extcon;
+
+ if (!IS_ERR(cable_id->edev) && ci->is_otg &&
+ (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS))
+ ci_irq(ci->irq, ci);
+
+ if (!IS_ERR(cable_vbus->edev) && ci->is_otg &&
+ (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS))
+ ci_irq(ci->irq, ci);
+}
+
static int ci_controller_resume(struct device *dev)
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
@@ -1116,6 +1165,7 @@ static int ci_controller_resume(struct device *dev)
enable_irq(ci->irq);
if (ci_otg_is_fsm_mode(ci))
ci_otg_fsm_wakeup_by_srp(ci);
+ ci_extcon_wakeup_int(ci);
}
return 0;
@@ -1142,6 +1192,10 @@ static int ci_suspend(struct device *dev)
return 0;
}
+ /* Extra routine per role before system suspend */
+ if (ci->role != CI_ROLE_END && ci_role(ci)->suspend)
+ ci_role(ci)->suspend(ci);
+
if (device_may_wakeup(dev)) {
if (ci_otg_is_fsm_mode(ci))
ci_otg_fsm_suspend_for_srp(ci);
@@ -1158,8 +1212,18 @@ static int ci_suspend(struct device *dev)
static int ci_resume(struct device *dev)
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
+ bool power_lost = false;
+ u32 sample_reg_val;
int ret;
+ /* Check if controller resume from power lost */
+ sample_reg_val = hw_read(ci, OP_ENDPTLISTADDR, ~0);
+ if (sample_reg_val == 0)
+ power_lost = true;
+ else if (sample_reg_val == 0xFFFFFFFF)
+ /* Restore value 0 if it was set for power lost check */
+ hw_write(ci, OP_ENDPTLISTADDR, ~0, 0);
+
if (device_may_wakeup(dev))
disable_irq_wake(ci->irq);
@@ -1167,6 +1231,21 @@ static int ci_resume(struct device *dev)
if (ret)
return ret;
+ if (power_lost) {
+ /* shutdown and re-init for phy */
+ ci_usb_phy_exit(ci);
+ ci_usb_phy_init(ci);
+ }
+
+ /* Extra routine per role after system resume */
+ if (ci->role != CI_ROLE_END && ci_role(ci)->resume)
+ ci_role(ci)->resume(ci, power_lost);
+
+ if (power_lost) {
+ disable_irq_nosync(ci->irq);
+ schedule_work(&ci->power_lost_work);
+ }
+
if (ci->supports_runtime_pm) {
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 111b0e0b8698..afef075180da 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -25,6 +25,7 @@
#include <linux/usb/hcd.h>
#include <linux/usb/chipidea.h>
#include <linux/regulator/consumer.h>
+#include <linux/imx_gpc.h>
#include "../host/ehci.h"
@@ -34,11 +35,29 @@
static struct hc_driver __read_mostly ci_ehci_hc_driver;
static int (*orig_bus_suspend)(struct usb_hcd *hcd);
+static int (*orig_bus_resume)(struct usb_hcd *hcd);
+static int (*orig_hub_control)(struct usb_hcd *hcd,
+ u16 typeReq, u16 wValue, u16 wIndex,
+ char *buf, u16 wLength);
struct ehci_ci_priv {
struct regulator *reg_vbus;
};
+/* This function is used to override WKCN, WKDN, and WKOC */
+static void ci_ehci_override_wakeup_flag(struct ehci_hcd *ehci,
+ u32 __iomem *reg, u32 flags, bool set)
+{
+ u32 val = ehci_readl(ehci, reg);
+
+ if (set)
+ val |= flags;
+ else
+ val &= ~flags;
+
+ ehci_writel(ehci, val, reg);
+}
+
static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -101,9 +120,164 @@ static const struct ehci_driver_overrides ehci_ci_overrides = {
.reset = ehci_ci_reset,
};
+static int ci_imx_ehci_bus_resume(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ int port;
+
+ int ret = orig_bus_resume(hcd);
+
+ if (ret)
+ return ret;
+
+ port = HCS_N_PORTS(ehci->hcs_params);
+ while (port--) {
+ u32 __iomem *reg = &ehci->regs->port_status[port];
+ u32 portsc = ehci_readl(ehci, reg);
+ /*
+ * Notify PHY after resume signal has finished, it is
+ * for global suspend case.
+ */
+ if (hcd->usb_phy
+ && test_bit(port, &ehci->bus_suspended)
+ && (portsc & PORT_CONNECT)
+ && (ehci_port_speed(ehci, portsc) ==
+ USB_PORT_STAT_HIGH_SPEED))
+ /* notify the USB PHY */
+ usb_phy_notify_resume(hcd->usb_phy, USB_SPEED_HIGH);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_USB_OTG
+
+static int ci_start_port_reset(struct usb_hcd *hcd, unsigned port)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ u32 __iomem *reg;
+ u32 status;
+
+ if (!port)
+ return -EINVAL;
+ port--;
+ /* start port reset before HNP protocol time out */
+ reg = &ehci->regs->port_status[port];
+ status = ehci_readl(ehci, reg);
+ if (!(status & PORT_CONNECT))
+ return -ENODEV;
+
+ /* khubd will finish the reset later */
+ if (ehci_is_TDI(ehci))
+ ehci_writel(ehci, status | (PORT_RESET & ~PORT_RWC_BITS), reg);
+ else
+ ehci_writel(ehci, status | PORT_RESET, reg);
+
+ return 0;
+}
+
+#else
+
+#define ci_start_port_reset NULL
+
+#endif
+
+/* The below code is based on tegra ehci driver */
+static int ci_imx_ehci_hub_control(
+ struct usb_hcd *hcd,
+ u16 typeReq,
+ u16 wValue,
+ u16 wIndex,
+ char *buf,
+ u16 wLength
+)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ u32 __iomem *status_reg;
+ u32 temp;
+ unsigned long flags;
+ int retval = 0;
+ struct device *dev = hcd->self.controller;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
+
+ spin_lock_irqsave(&ehci->lock, flags);
+
+ if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
+ temp = ehci_readl(ehci, status_reg);
+ if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
+ retval = -EPIPE;
+ goto done;
+ }
+
+ temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E);
+ temp |= PORT_WKDISC_E | PORT_WKOC_E;
+ ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+
+ /*
+ * If a transaction is in progress, there may be a delay in
+ * suspending the port. Poll until the port is suspended.
+ */
+ if (ehci_handshake(ehci, status_reg, PORT_SUSPEND,
+ PORT_SUSPEND, 5000))
+ ehci_err(ehci, "timeout waiting for SUSPEND\n");
+
+ if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
+ if (ci->platdata->notify_event)
+ ci->platdata->notify_event
+ (ci, CI_HDRC_IMX_HSIC_SUSPEND_EVENT);
+ ci_ehci_override_wakeup_flag(ehci, status_reg,
+ PORT_WKDISC_E | PORT_WKCONN_E, false);
+ }
+
+ spin_unlock_irqrestore(&ehci->lock, flags);
+ if (ehci_port_speed(ehci, temp) ==
+ USB_PORT_STAT_HIGH_SPEED && hcd->usb_phy) {
+ /* notify the USB PHY */
+ usb_phy_notify_suspend(hcd->usb_phy, USB_SPEED_HIGH);
+ }
+ spin_lock_irqsave(&ehci->lock, flags);
+
+ set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
+ goto done;
+ }
+
+ /*
+ * After resume has finished, it needs do some post resume
+ * operation for some SoCs.
+ */
+ else if (typeReq == ClearPortFeature &&
+ wValue == USB_PORT_FEAT_C_SUSPEND) {
+
+ /* Make sure the resume has finished, it should be finished */
+ if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 25000))
+ ehci_err(ehci, "timeout waiting for resume\n");
+
+ temp = ehci_readl(ehci, status_reg);
+
+ if (ehci_port_speed(ehci, temp) ==
+ USB_PORT_STAT_HIGH_SPEED && hcd->usb_phy) {
+ /* notify the USB PHY */
+ usb_phy_notify_resume(hcd->usb_phy, USB_SPEED_HIGH);
+ }
+ }
+
+ spin_unlock_irqrestore(&ehci->lock, flags);
+
+ /* Handle the hub control events here */
+ return orig_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+done:
+ spin_unlock_irqrestore(&ehci->lock, flags);
+ return retval;
+}
+
static irqreturn_t host_irq(struct ci_hdrc *ci)
{
- return usb_hcd_irq(ci->irq, ci->hcd);
+ if (ci->hcd)
+ return usb_hcd_irq(ci->irq, ci->hcd);
+ else
+ return IRQ_NONE;
}
static int host_start(struct ci_hdrc *ci)
@@ -156,6 +330,13 @@ static int host_start(struct ci_hdrc *ci)
}
}
+ if (ci_otg_is_fsm_mode(ci)) {
+ if (ci->fsm.id && ci->fsm.otg->state <= OTG_STATE_B_HOST)
+ hcd->self.is_b_host = 1;
+ else
+ hcd->self.is_b_host = 0;
+ }
+
ret = usb_add_hcd(hcd, 0, 0);
if (ret) {
goto disable_reg;
@@ -165,11 +346,17 @@ static int host_start(struct ci_hdrc *ci)
ci->hcd = hcd;
if (ci_otg_is_fsm_mode(ci)) {
+ hcd->self.otg_fsm = &ci->fsm;
otg->host = &hcd->self;
hcd->self.otg_port = 1;
}
}
+ if (ci->platdata->notify_event &&
+ (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC))
+ ci->platdata->notify_event
+ (ci, CI_HDRC_IMX_HSIC_ACTIVE_EVENT);
+
return ret;
disable_reg:
@@ -194,16 +381,123 @@ static void host_stop(struct ci_hdrc *ci)
if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
(ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
regulator_disable(ci->platdata->reg_vbus);
+ if (hcd->self.is_b_host)
+ hcd->self.is_b_host = 0;
}
ci->hcd = NULL;
ci->otg.host = NULL;
}
+bool ci_hdrc_host_has_device(struct ci_hdrc *ci)
+{
+ struct usb_device *roothub;
+ int i;
+
+ if ((ci->role == CI_ROLE_HOST) && ci->hcd) {
+ roothub = ci->hcd->self.root_hub;
+ for (i = 0; i < roothub->maxchild; ++i) {
+ if (usb_hub_find_child(roothub, (i + 1)))
+ return true;
+ }
+ }
+ return false;
+}
+
+static void ci_hdrc_host_save_for_power_lost(struct ci_hdrc *ci)
+{
+ struct ehci_hcd *ehci;
+
+ if (!ci->hcd)
+ return;
+
+ ehci = hcd_to_ehci(ci->hcd);
+ /* save EHCI registers */
+ ci->pm_usbmode = ehci_readl(ehci, &ehci->regs->usbmode);
+ ci->pm_command = ehci_readl(ehci, &ehci->regs->command);
+ ci->pm_command &= ~CMD_RUN;
+ ci->pm_status = ehci_readl(ehci, &ehci->regs->status);
+ ci->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable);
+ ci->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index);
+ ci->pm_segment = ehci_readl(ehci, &ehci->regs->segment);
+ ci->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list);
+ ci->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next);
+ ci->pm_configured_flag =
+ ehci_readl(ehci, &ehci->regs->configured_flag);
+ ci->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]);
+}
+
+static void ci_hdrc_host_restore_from_power_lost(struct ci_hdrc *ci)
+{
+ struct ehci_hcd *ehci;
+ unsigned long flags;
+ u32 tmp;
+ int step_ms;
+ /*
+ * If the vbus is off during system suspend, most of devices will pull
+ * DP up within 200ms when they see vbus, set 1000ms for safety.
+ */
+ int timeout_ms = 1000;
+
+ if (!ci->hcd)
+ return;
+
+ hw_controller_reset(ci);
+
+ ehci = hcd_to_ehci(ci->hcd);
+ spin_lock_irqsave(&ehci->lock, flags);
+ /* Restore EHCI registers */
+ ehci_writel(ehci, ci->pm_usbmode, &ehci->regs->usbmode);
+ ehci_writel(ehci, ci->pm_portsc, &ehci->regs->port_status[0]);
+ ehci_writel(ehci, ci->pm_command, &ehci->regs->command);
+ ehci_writel(ehci, ci->pm_intr_enable, &ehci->regs->intr_enable);
+ ehci_writel(ehci, ci->pm_frame_index, &ehci->regs->frame_index);
+ ehci_writel(ehci, ci->pm_segment, &ehci->regs->segment);
+ ehci_writel(ehci, ci->pm_frame_list, &ehci->regs->frame_list);
+ ehci_writel(ehci, ci->pm_async_next, &ehci->regs->async_next);
+ ehci_writel(ehci, ci->pm_configured_flag,
+ &ehci->regs->configured_flag);
+ /* Restore the PHY's connect notifier setting */
+ if (ci->pm_portsc & PORTSC_HSP)
+ usb_phy_notify_connect(ci->usb_phy, USB_SPEED_HIGH);
+
+ tmp = ehci_readl(ehci, &ehci->regs->command);
+ tmp |= CMD_RUN;
+ ehci_writel(ehci, tmp, &ehci->regs->command);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+
+ if (!(ci->pm_portsc & PORTSC_CCS))
+ return;
+
+ for (step_ms = 0; step_ms < timeout_ms; step_ms += 25) {
+ if (ehci_readl(ehci, &ehci->regs->port_status[0]) & PORTSC_CCS)
+ break;
+ msleep(25);
+ }
+}
+
+static void ci_hdrc_host_suspend(struct ci_hdrc *ci)
+{
+ if (ci_hdrc_host_has_device(ci))
+ imx_gpc_mf_request_on(ci->irq, 1);
+
+ ci_hdrc_host_save_for_power_lost(ci);
+}
+
+static void ci_hdrc_host_resume(struct ci_hdrc *ci, bool power_lost)
+{
+ imx_gpc_mf_request_on(ci->irq, 0);
+
+ if (power_lost)
+ ci_hdrc_host_restore_from_power_lost(ci);
+}
void ci_hdrc_host_destroy(struct ci_hdrc *ci)
{
- if (ci->role == CI_ROLE_HOST && ci->hcd)
+ if (ci->role == CI_ROLE_HOST && ci->hcd) {
+ disable_irq_nosync(ci->irq);
host_stop(ci);
+ enable_irq(ci->irq);
+ }
}
static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
@@ -211,6 +505,8 @@ static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
int port;
u32 tmp;
+ struct device *dev = hcd->self.controller;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
int ret = orig_bus_suspend(hcd);
@@ -240,6 +536,30 @@ static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
* It needs a short delay between set RS bit and PHCD.
*/
usleep_range(150, 200);
+
+ /*
+ * If a transaction is in progress, there may be
+ * a delay in suspending the port. Poll until the
+ * port is suspended.
+ */
+ if (test_bit(port, &ehci->bus_suspended) &&
+ ehci_handshake(ehci, reg, PORT_SUSPEND,
+ PORT_SUSPEND, 5000))
+ ehci_err(ehci, "timeout waiting for SUSPEND\n");
+
+ if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC)
+ ci_ehci_override_wakeup_flag(ehci, reg,
+ PORT_WKDISC_E | PORT_WKCONN_E, false);
+
+ if (hcd->usb_phy && test_bit(port, &ehci->bus_suspended)
+ && (ehci_port_speed(ehci, portsc) ==
+ USB_PORT_STAT_HIGH_SPEED))
+ /*
+ * notify the USB PHY, it is for global
+ * suspend case.
+ */
+ usb_phy_notify_suspend(hcd->usb_phy,
+ USB_SPEED_HIGH);
break;
}
}
@@ -261,6 +581,8 @@ int ci_hdrc_host_init(struct ci_hdrc *ci)
rdrv->start = host_start;
rdrv->stop = host_stop;
rdrv->irq = host_irq;
+ rdrv->suspend = ci_hdrc_host_suspend;
+ rdrv->resume = ci_hdrc_host_resume;
rdrv->name = "host";
ci->roles[CI_ROLE_HOST] = rdrv;
@@ -271,5 +593,11 @@ void ci_hdrc_host_driver_init(void)
{
ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
+ orig_bus_resume = ci_ehci_hc_driver.bus_resume;
+ orig_hub_control = ci_ehci_hc_driver.hub_control;
+
ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
+ ci_ehci_hc_driver.bus_resume = ci_imx_ehci_bus_resume;
+ ci_ehci_hc_driver.hub_control = ci_imx_ehci_hub_control;
+ ci_ehci_hc_driver.start_port_reset = ci_start_port_reset;
}
diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h
index 0f12f131bdd3..4dfb59a05a1a 100644
--- a/drivers/usb/chipidea/host.h
+++ b/drivers/usb/chipidea/host.h
@@ -6,6 +6,7 @@
int ci_hdrc_host_init(struct ci_hdrc *ci);
void ci_hdrc_host_destroy(struct ci_hdrc *ci);
void ci_hdrc_host_driver_init(void);
+bool ci_hdrc_host_has_device(struct ci_hdrc *ci);
#else
@@ -19,11 +20,16 @@ static inline void ci_hdrc_host_destroy(struct ci_hdrc *ci)
}
-static void ci_hdrc_host_driver_init(void)
+static inline void ci_hdrc_host_driver_init(void)
{
}
+static inline bool ci_hdrc_host_has_device(struct ci_hdrc *ci)
+{
+ return false;
+}
+
#endif
#endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index f36a1ac3bfbd..e55f51d668ae 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -1,7 +1,8 @@
/*
* otg.c - ChipIdea USB IP core OTG driver
*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
*
* Author: Peter Chen
*
@@ -23,6 +24,7 @@
#include "bits.h"
#include "otg.h"
#include "otg_fsm.h"
+#include "host.h"
/**
* hw_read_otgsc returns otgsc register bits value.
@@ -44,7 +46,7 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
else
val &= ~OTGSC_BSVIS;
- if (cable->state)
+ if (cable->connected)
val |= OTGSC_BSV;
else
val &= ~OTGSC_BSV;
@@ -62,10 +64,10 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
else
val &= ~OTGSC_IDIS;
- if (cable->state)
- val |= OTGSC_ID;
+ if (cable->connected)
+ val &= ~OTGSC_ID; /* host */
else
- val &= ~OTGSC_ID;
+ val |= OTGSC_ID; /* device */
if (cable->enabled)
val |= OTGSC_IDIE;
@@ -129,6 +131,46 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci)
return role;
}
+/*
+ * Handling vbus glitch
+ * We only need to consider glitch for without usb connection,
+ * With usb connection, we consider it as real disconnection.
+ *
+ * If the vbus can't be kept above B session valid for timeout value,
+ * we think it is a vbus glitch, otherwise it's a valid vbus.
+ */
+#define CI_VBUS_CONNECT_TIMEOUT_MS 300
+static int ci_is_vbus_glitch(struct ci_hdrc *ci)
+{
+ int i;
+
+ for (i = 0; i < CI_VBUS_CONNECT_TIMEOUT_MS/20; i++) {
+ if (hw_read_otgsc(ci, OTGSC_AVV)) {
+ return 0;
+ } else if (!hw_read_otgsc(ci, OTGSC_BSV)) {
+ dev_warn(ci->dev, "there is a vbus glitch\n");
+ return 1;
+ }
+ msleep(20);
+ }
+
+ return 0;
+}
+
+void ci_handle_vbus_connected(struct ci_hdrc *ci)
+{
+ /*
+ * TODO: if the platform does not supply 5v to udc, or use other way
+ * to supply 5v, it needs to use other conditions to call
+ * usb_gadget_vbus_connect.
+ */
+ if (!ci->is_otg)
+ return;
+
+ if (hw_read_otgsc(ci, OTGSC_BSV) && !ci_is_vbus_glitch(ci))
+ usb_gadget_vbus_connect(&ci->gadget);
+}
+
void ci_handle_vbus_change(struct ci_hdrc *ci)
{
if (!ci->is_otg)
@@ -165,33 +207,72 @@ static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
return 0;
}
-static void ci_handle_id_switch(struct ci_hdrc *ci)
+void ci_handle_id_switch(struct ci_hdrc *ci)
{
- enum ci_role role = ci_otg_role(ci);
+ enum ci_role role;
+ int ret = 0;
+ mutex_lock(&ci->mutex);
+ role = ci_otg_role(ci);
if (role != ci->role) {
dev_dbg(ci->dev, "switching from %s to %s\n",
ci_role(ci)->name, ci->roles[role]->name);
ci_role_stop(ci);
- if (role == CI_ROLE_GADGET &&
- IS_ERR(ci->platdata->vbus_extcon.edev))
+ if (role == CI_ROLE_GADGET)
/*
- * Wait vbus lower than OTGSC_BSV before connecting
- * to host. If connecting status is from an external
- * connector instead of register, we don't need to
- * care vbus on the board, since it will not affect
- * external connector status.
+ * wait vbus lower than OTGSC_BSV before connecting
+ * to host
*/
- hw_wait_vbus_lower_bsv(ci);
+ ret = hw_wait_vbus_lower_bsv(ci);
+ else if (ci->vbus_active)
+ /*
+ * If the role switch happens(e.g. during
+ * system sleep), and we lose vbus drop
+ * event, disconnect gadget for it before
+ * start host.
+ */
+ usb_gadget_vbus_disconnect(&ci->gadget);
ci_role_start(ci, role);
- /* vbus change may have already occurred */
- if (role == CI_ROLE_GADGET)
- ci_handle_vbus_change(ci);
+ /*
+ * If the role switch happens(e.g. during system
+ * sleep) and vbus keeps on afterwards, we connect
+ * gadget as vbus connect event lost.
+ */
+ if (ret == -ETIMEDOUT)
+ usb_gadget_vbus_connect(&ci->gadget);
+
}
+ mutex_unlock(&ci->mutex);
}
+
+static void ci_handle_vbus_glitch(struct ci_hdrc *ci)
+{
+ bool valid_vbus_change = false;
+
+ if (hw_read_otgsc(ci, OTGSC_BSV)) {
+ if (!ci_is_vbus_glitch(ci)) {
+ if (ci_otg_is_fsm_mode(ci)) {
+ ci->fsm.b_sess_vld = 1;
+ ci->fsm.b_ssend_srp = 0;
+ otg_del_timer(&ci->fsm, B_SSEND_SRP);
+ otg_del_timer(&ci->fsm, B_SRP_FAIL);
+ }
+ valid_vbus_change = true;
+ }
+ } else {
+ if (ci->vbus_active && !ci_otg_is_fsm_mode(ci))
+ valid_vbus_change = true;
+ }
+
+ if (valid_vbus_change) {
+ ci->b_sess_valid_event = true;
+ ci_otg_queue_work(ci);
+ }
+}
+
/**
* ci_otg_work - perform otg (vbus/id) event handle
* @work: work struct
@@ -200,6 +281,15 @@ static void ci_otg_work(struct work_struct *work)
{
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
+ if (ci->vbus_glitch_check_event) {
+ ci->vbus_glitch_check_event = false;
+ pm_runtime_get_sync(ci->dev);
+ ci_handle_vbus_glitch(ci);
+ pm_runtime_put_sync(ci->dev);
+ enable_irq(ci->irq);
+ return;
+ }
+
if (ci_otg_is_fsm_mode(ci) && !ci_otg_fsm_work(ci)) {
enable_irq(ci->irq);
return;
@@ -245,13 +335,14 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci)
*/
void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
{
+ /* Disable all OTG irq and clear status */
+ hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
+ OTGSC_INT_STATUS_BITS);
if (ci->wq) {
flush_workqueue(ci->wq);
destroy_workqueue(ci->wq);
+ ci->wq = NULL;
}
- /* Disable all OTG irq and clear status */
- hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
- OTGSC_INT_STATUS_BITS);
if (ci_otg_is_fsm_mode(ci))
ci_hdrc_otg_fsm_remove(ci);
}
diff --git a/drivers/usb/chipidea/otg.h b/drivers/usb/chipidea/otg.h
index 9ecb598e48f0..95fa6c2b675a 100644
--- a/drivers/usb/chipidea/otg.h
+++ b/drivers/usb/chipidea/otg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
*
* Author: Peter Chen
*
@@ -17,10 +17,17 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci);
void ci_hdrc_otg_destroy(struct ci_hdrc *ci);
enum ci_role ci_otg_role(struct ci_hdrc *ci);
void ci_handle_vbus_change(struct ci_hdrc *ci);
+void ci_handle_id_switch(struct ci_hdrc *ci);
+void ci_handle_vbus_connected(struct ci_hdrc *ci);
static inline void ci_otg_queue_work(struct ci_hdrc *ci)
{
- disable_irq_nosync(ci->irq);
- queue_work(ci->wq, &ci->work);
+ if (ci->wq) {
+ disable_irq_nosync(ci->irq);
+ if (!queue_work(ci->wq, &ci->work))
+ enable_irq(ci->irq);
+ } else {
+ WARN_ON(!ci->wq);
+ }
}
#endif /* __DRIVERS_USB_CHIPIDEA_OTG_H */
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index de8e22ec3902..05ff5f155e96 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -1,7 +1,7 @@
/*
* otg_fsm.c - ChipIdea USB IP core OTG FSM driver
*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
*
* Author: Jun Li
*
@@ -28,7 +28,10 @@
#include "ci.h"
#include "bits.h"
#include "otg.h"
+#include "udc.h"
#include "otg_fsm.h"
+#include "udc.h"
+#include "host.h"
/* Add for otg: interact with user space app */
static ssize_t
@@ -215,6 +218,11 @@ static unsigned otg_timer_ms[] = {
0,
TB_DATA_PLS,
TB_SSEND_SRP,
+ TA_DP_END,
+ TA_TST_MAINT,
+ TB_SRP_REQD,
+ TB_TST_SUSP,
+ 0,
};
/*
@@ -300,6 +308,7 @@ static int a_wait_vfall_tmout(struct ci_hdrc *ci)
static int a_wait_bcon_tmout(struct ci_hdrc *ci)
{
ci->fsm.a_wait_bcon_tmout = 1;
+ dev_warn(ci->dev, "Device No Response\n");
return 0;
}
@@ -312,6 +321,7 @@ static int a_aidl_bdis_tmout(struct ci_hdrc *ci)
static int b_ase0_brst_tmout(struct ci_hdrc *ci)
{
ci->fsm.b_ase0_brst_tmout = 1;
+ dev_warn(ci->dev, "Device No Response\n");
return 0;
}
@@ -336,6 +346,7 @@ static int b_se0_srp_tmout(struct ci_hdrc *ci)
static int b_srp_fail_tmout(struct ci_hdrc *ci)
{
ci->fsm.b_srp_done = 1;
+ dev_warn(ci->dev, "Device No Response\n");
return 1;
}
@@ -360,6 +371,57 @@ static int b_ssend_srp_tmout(struct ci_hdrc *ci)
return 1;
}
+static int a_dp_end_tmout(struct ci_hdrc *ci)
+{
+ ci->fsm.a_bus_drop = 0;
+ ci->fsm.a_srp_det = 1;
+ return 0;
+}
+
+static int a_tst_maint_tmout(struct ci_hdrc *ci)
+{
+ ci->fsm.tst_maint = 0;
+ if (ci->fsm.otg_vbus_off) {
+ ci->fsm.otg_vbus_off = 0;
+ dev_dbg(ci->dev,
+ "test device does not disconnect, end the session!\n");
+ }
+
+ /* End the session */
+ ci->fsm.a_bus_req = 0;
+ ci->fsm.a_bus_drop = 1;
+ return 0;
+}
+
+/*
+ * otg_srp_reqd feature
+ * After A(PET) turn off vbus, B(UUT) should start this timer to do SRP
+ * when the timer expires.
+ */
+static int b_srp_reqd_tmout(struct ci_hdrc *ci)
+{
+ ci->fsm.otg_srp_reqd = 0;
+ if (ci->fsm.otg->state == OTG_STATE_B_IDLE) {
+ ci->fsm.b_bus_req = 1;
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * otg_hnp_reqd feature
+ * After B(UUT) switch to host, B should hand host role back
+ * to A(PET) within TB_TST_SUSP after setting configuration.
+ */
+static int b_tst_susp_tmout(struct ci_hdrc *ci)
+{
+ if (ci->fsm.otg->state == OTG_STATE_B_HOST) {
+ ci->fsm.b_bus_req = 0;
+ return 0;
+ }
+ return 1;
+}
+
/*
* Keep this list in the same order as timers indexed
* by enum otg_fsm_timer in include/linux/usb/otg-fsm.h
@@ -377,6 +439,11 @@ static int (*otg_timer_handlers[])(struct ci_hdrc *) = {
NULL, /* A_WAIT_ENUM */
b_data_pls_tmout, /* B_DATA_PLS */
b_ssend_srp_tmout, /* B_SSEND_SRP */
+ a_dp_end_tmout, /* A_DP_END */
+ a_tst_maint_tmout, /* A_TST_MAINT */
+ b_srp_reqd_tmout, /* B_SRP_REQD */
+ b_tst_susp_tmout, /* B_TST_SUSP */
+ NULL, /* HNP_POLLING */
};
/*
@@ -463,6 +530,9 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
if (on) {
+ ci->platdata->notify_event(ci,
+ CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF);
+
/* Enable power power */
hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP,
PORTSC_PP);
@@ -486,6 +556,7 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
fsm->a_bus_drop = 1;
fsm->a_bus_req = 0;
+ fsm->b_conn = 0;
}
}
@@ -562,11 +633,16 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on)
static int ci_otg_start_gadget(struct otg_fsm *fsm, int on)
{
struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+ unsigned long flags;
+ int gadget_ready = 0;
- if (on)
- usb_gadget_vbus_connect(&ci->gadget);
- else
- usb_gadget_vbus_disconnect(&ci->gadget);
+ spin_lock_irqsave(&ci->lock, flags);
+ ci->vbus_active = on;
+ if (ci->driver)
+ gadget_ready = 1;
+ spin_unlock_irqrestore(&ci->lock, flags);
+ if (gadget_ready)
+ ci_hdrc_gadget_connect(&ci->gadget, on);
return 0;
}
@@ -584,13 +660,26 @@ static struct otg_fsm_ops ci_otg_ops = {
int ci_otg_fsm_work(struct ci_hdrc *ci)
{
- /*
- * Don't do fsm transition for B device
- * when there is no gadget class driver
- */
- if (ci->fsm.id && !(ci->driver) &&
- ci->fsm.otg->state < OTG_STATE_A_IDLE)
- return 0;
+ if (ci->fsm.id && ci->fsm.otg->state < OTG_STATE_A_IDLE) {
+ unsigned long flags;
+
+ /* Charger detection */
+ spin_lock_irqsave(&ci->lock, flags);
+ if (ci->b_sess_valid_event) {
+ ci->b_sess_valid_event = false;
+ ci->vbus_active = ci->fsm.b_sess_vld;
+ spin_unlock_irqrestore(&ci->lock, flags);
+ ci_usb_charger_connect(ci, ci->fsm.b_sess_vld);
+ spin_lock_irqsave(&ci->lock, flags);
+ }
+ spin_unlock_irqrestore(&ci->lock, flags);
+ /*
+ * Don't do fsm transition for B device if gadget
+ * driver is not binded.
+ */
+ if (!ci->driver)
+ return 0;
+ }
pm_runtime_get_sync(ci->dev);
if (otg_statemachine(&ci->fsm)) {
@@ -612,10 +701,14 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
PORTSC_PP, 0);
hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
hw_write_otgsc(ci, OTGSC_DPIE, OTGSC_DPIE);
+ /* FS termination override if needed */
+ ci->platdata->notify_event(ci,
+ CI_HDRC_IMX_TERM_SELECT_OVERRIDE_FS);
}
if (ci->id_event)
ci->id_event = false;
} else if (ci->fsm.otg->state == OTG_STATE_B_IDLE) {
+ ci->fsm.b_sess_vld = hw_read_otgsc(ci, OTGSC_BSV);
if (ci->fsm.b_sess_vld) {
ci->fsm.power_up = 0;
/*
@@ -624,7 +717,8 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
*/
ci_otg_queue_work(ci);
}
- } else if (ci->fsm.otg->state == OTG_STATE_A_HOST) {
+ } else if (ci->fsm.otg->state == OTG_STATE_A_HOST ||
+ ci->fsm.otg->state == OTG_STATE_A_WAIT_VFALL) {
pm_runtime_mark_last_busy(ci->dev);
pm_runtime_put_autosuspend(ci->dev);
return 0;
@@ -678,25 +772,16 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci)
}
break;
case OTG_STATE_A_PERIPHERAL:
- if (intr_sts & USBi_SLI) {
- fsm->b_bus_suspend = 1;
+ if (intr_sts & USBi_SLI)
/*
* Init a timer to know how long this suspend
* will continue, if time out, indicates B no longer
* wants to be host role
*/
ci_otg_add_timer(ci, A_BIDL_ADIS);
- }
- if (intr_sts & USBi_URI)
+ if (intr_sts & (USBi_URI | USBi_PCI))
ci_otg_del_timer(ci, A_BIDL_ADIS);
-
- if (intr_sts & USBi_PCI) {
- if (fsm->b_bus_suspend == 1) {
- ci_otg_del_timer(ci, A_BIDL_ADIS);
- fsm->b_bus_suspend = 0;
- }
- }
break;
case OTG_STATE_A_SUSPEND:
if ((intr_sts & USBi_PCI) && !port_conn) {
@@ -713,6 +798,15 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci)
case OTG_STATE_A_HOST:
if ((intr_sts & USBi_PCI) && !port_conn) {
fsm->b_conn = 0;
+ if (fsm->tst_maint) {
+ ci_otg_del_timer(ci, A_TST_MAINT);
+ if (fsm->otg_vbus_off) {
+ fsm->a_bus_req = 0;
+ fsm->a_bus_drop = 1;
+ fsm->otg_vbus_off = 0;
+ }
+ fsm->tst_maint = 0;
+ }
ci_otg_queue_work(ci);
}
break;
@@ -746,26 +840,36 @@ irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci)
if (otg_int_src) {
if (otg_int_src & OTGSC_DPIS) {
hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
- fsm->a_srp_det = 1;
- fsm->a_bus_drop = 0;
+ ci->platdata->notify_event(ci,
+ CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF);
+ ci_otg_add_timer(ci, A_DP_END);
} else if (otg_int_src & OTGSC_IDIS) {
hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS);
if (fsm->id == 0) {
fsm->a_bus_drop = 0;
fsm->a_bus_req = 1;
ci->id_event = true;
+ } else {
+ /*
+ * Disable term select override and data pulse
+ * for B device.
+ */
+ ci->platdata->notify_event(ci,
+ CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF);
}
} else if (otg_int_src & OTGSC_BSVIS) {
hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
- if (otgsc & OTGSC_BSV) {
- fsm->b_sess_vld = 1;
- ci_otg_del_timer(ci, B_SSEND_SRP);
- ci_otg_del_timer(ci, B_SRP_FAIL);
- fsm->b_ssend_srp = 0;
- } else {
+ if (!(otgsc & OTGSC_BSV) && fsm->b_sess_vld) {
+ ci->b_sess_valid_event = true;
fsm->b_sess_vld = 0;
if (fsm->id)
ci_otg_add_timer(ci, B_SSEND_SRP);
+ if (fsm->b_bus_req)
+ fsm->b_bus_req = 0;
+ if (fsm->otg_srp_reqd)
+ ci_otg_add_timer(ci, B_SRP_REQD);
+ } else {
+ ci->vbus_glitch_check_event = true;
}
} else if (otg_int_src & OTGSC_AVVIS) {
hw_write_otgsc(ci, OTGSC_AVVIS, OTGSC_AVVIS);
@@ -802,6 +906,7 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
ci->otg.gadget = &ci->gadget;
ci->fsm.otg = &ci->otg;
ci->fsm.power_up = 1;
+ ci->fsm.hnp_polling = 1;
ci->fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0;
ci->fsm.otg->state = OTG_STATE_UNDEFINED;
ci->fsm.ops = &ci_otg_ops;
@@ -844,5 +949,56 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
{
+ enum otg_fsm_timer i;
+
+ mutex_lock(&ci->fsm.lock);
+ ci->fsm.otg->state = OTG_STATE_UNDEFINED;
+ mutex_unlock(&ci->fsm.lock);
+
+ for (i = 0; i < NUM_OTG_FSM_TIMERS; i++)
+ otg_del_timer(&ci->fsm, i);
+
+ ci->enabled_otg_timer_bits = 0;
+
+ /* Turn off vbus if vbus is on */
+ if (ci->fsm.drv_vbus)
+ otg_drv_vbus(&ci->fsm, 0);
+
sysfs_remove_group(&ci->dev->kobj, &inputs_attr_group);
}
+
+/* Restart OTG fsm if resume from power lost */
+void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci)
+{
+ struct otg_fsm *fsm = &ci->fsm;
+ int id_status = fsm->id;
+
+ /* Update fsm if power lost in peripheral state */
+ if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
+ fsm->b_sess_vld = 0;
+ otg_statemachine(fsm);
+ }
+
+ hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);
+ hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE);
+
+ /* Update fsm variables for restart */
+ fsm->id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0;
+ if (fsm->id) {
+ fsm->b_ssend_srp =
+ hw_read_otgsc(ci, OTGSC_BSV) ? 0 : 1;
+ fsm->b_sess_vld =
+ hw_read_otgsc(ci, OTGSC_BSV) ? 1 : 0;
+ } else if (fsm->id != id_status) {
+ /* ID changes to be 0 */
+ fsm->a_bus_drop = 0;
+ fsm->a_bus_req = 1;
+ ci->id_event = true;
+ }
+
+ if (ci_hdrc_host_has_device(ci) &&
+ !hw_read(ci, OP_PORTSC, PORTSC_CCS))
+ fsm->b_conn = 0;
+
+ ci_otg_fsm_work(ci);
+}
diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h
index 6366fe398ba6..ff77d2e1bb64 100644
--- a/drivers/usb/chipidea/otg_fsm.h
+++ b/drivers/usb/chipidea/otg_fsm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
*
* Author: Jun Li
*
@@ -25,7 +25,7 @@
* ->DC Electrical Timing
*/
/* Wait for VBUS Fall */
-#define TA_WAIT_VFALL (1000) /* a_wait_vfall: section 7.1.7
+#define TA_WAIT_VFALL (500) /* a_wait_vfall: section 7.1.7
* a_wait_vfall_tmr: section: 7.4.5.2
*/
/* Wait for B-Connect */
@@ -38,9 +38,13 @@
* TA_AIDL_BDIS: section 5.5, Table 5-1
*/
/* B-Idle to A-Disconnect */
-#define TA_BIDL_ADIS (500) /* TA_BIDL_ADIS: section 5.2.1
- * 500ms is used for B switch to host
- * for safe
+#define TA_BIDL_ADIS (160) /* TA_BIDL_ADIS: section 5.2.1
+ * 155ms ~ 200 ms
+ */
+
+#define TA_DP_END (200)
+#define TA_TST_MAINT (9900) /* OTG test device session maintain
+ * timer, 9.9s~10.1s
*/
/*
@@ -63,6 +67,14 @@
#define TB_SSEND_SRP (1500) /* minimum 1.5 sec, section:5.1.2 */
#define TB_AIDL_BDIS (20) /* 4ms ~ 150ms, section 5.2.1 */
+#define TB_SRP_REQD (2000) /* For otg_srp_reqd to start data
+ * pulse after A(PET) turn off v-bus
+ */
+
+#define TB_TST_SUSP (20) /* B-dev hand host role back to A-dev
+ * via suspend bus after set config.
+ * max: 100ms
+ */
#if IS_ENABLED(CONFIG_USB_OTG_FSM)
@@ -71,6 +83,7 @@ int ci_otg_fsm_work(struct ci_hdrc *ci);
irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci);
void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci);
void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci);
+void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci);
#else
@@ -99,6 +112,11 @@ static inline void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
}
+static inline void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci)
+{
+
+}
+
#endif
#endif /* __DRIVERS_USB_CHIPIDEA_OTG_FSM_H */
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 6a15b7250e9c..31f7ea1b5123 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -709,12 +709,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
unsigned long flags;
- spin_lock_irqsave(&ci->lock, flags);
- ci->gadget.speed = USB_SPEED_UNKNOWN;
- ci->remote_wakeup = 0;
- ci->suspended = 0;
- spin_unlock_irqrestore(&ci->lock, flags);
-
/* flush all endpoints */
gadget_for_each_ep(ep, gadget) {
usb_ep_fifo_flush(ep);
@@ -732,6 +726,12 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
ci->status = NULL;
}
+ spin_lock_irqsave(&ci->lock, flags);
+ ci->gadget.speed = USB_SPEED_UNKNOWN;
+ ci->remote_wakeup = 0;
+ ci->suspended = 0;
+ spin_unlock_irqrestore(&ci->lock, flags);
+
return 0;
}
@@ -750,6 +750,11 @@ __acquires(ci->lock)
{
int retval;
+ if (ci_otg_is_fsm_mode(ci)) {
+ ci->fsm.otg_srp_reqd = 0;
+ ci->fsm.otg_hnp_reqd = 0;
+ }
+
spin_unlock(&ci->lock);
if (ci->gadget.speed != USB_SPEED_UNKNOWN)
usb_gadget_udc_reset(&ci->gadget, ci->driver);
@@ -873,7 +878,10 @@ __acquires(hwep->lock)
return -ENOMEM;
req->complete = isr_get_status_complete;
- req->length = 2;
+ if (setup->wIndex == OTG_STS_SELECTOR)
+ req->length = 1;
+ else
+ req->length = 2;
req->buf = kzalloc(req->length, gfp_flags);
if (req->buf == NULL) {
retval = -ENOMEM;
@@ -881,8 +889,16 @@ __acquires(hwep->lock)
}
if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
- *(u16 *)req->buf = (ci->remote_wakeup << 1) |
- ci->gadget.is_selfpowered;
+ if ((setup->wIndex == OTG_STS_SELECTOR) &&
+ ci_otg_is_fsm_mode(ci)) {
+ if (ci->gadget.host_request_flag)
+ *(u8 *)req->buf = HOST_REQUEST_FLAG;
+ else
+ *(u8 *)req->buf = 0;
+ } else {
+ *(u16 *)req->buf = (ci->remote_wakeup << 1) |
+ ci->gadget.is_selfpowered;
+ }
} else if ((setup->bRequestType & USB_RECIP_MASK) \
== USB_RECIP_ENDPOINT) {
dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
@@ -1007,6 +1023,28 @@ static int otg_a_alt_hnp_support(struct ci_hdrc *ci)
return isr_setup_status_phase(ci);
}
+static int otg_srp_reqd(struct ci_hdrc *ci)
+{
+ if (ci_otg_is_fsm_mode(ci)) {
+ ci->fsm.otg_srp_reqd = 1;
+ return isr_setup_status_phase(ci);
+ } else {
+ return -ENOTSUPP;
+ }
+}
+
+static int otg_hnp_reqd(struct ci_hdrc *ci)
+{
+ if (ci_otg_is_fsm_mode(ci)) {
+ ci->fsm.otg_hnp_reqd = 1;
+ ci->fsm.b_bus_req = 1;
+ ci->gadget.host_request_flag = 1;
+ return isr_setup_status_phase(ci);
+ } else {
+ return -ENOTSUPP;
+ }
+}
+
/**
* isr_setup_packet_handler: setup packet handler
* @ci: UDC descriptor
@@ -1077,8 +1115,9 @@ __acquires(ci->lock)
type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
type != (USB_DIR_IN|USB_RECIP_INTERFACE))
goto delegate;
- if (le16_to_cpu(req.wLength) != 2 ||
- le16_to_cpu(req.wValue) != 0)
+ if ((le16_to_cpu(req.wLength) != 2 &&
+ le16_to_cpu(req.wLength) != 1) ||
+ le16_to_cpu(req.wValue) != 0)
break;
err = isr_get_status_response(ci, &req);
break;
@@ -1129,6 +1168,12 @@ __acquires(ci->lock)
err = isr_setup_status_phase(
ci);
break;
+ case TEST_OTG_SRP_REQD:
+ err = otg_srp_reqd(ci);
+ break;
+ case TEST_OTG_HNP_REQD:
+ err = otg_hnp_reqd(ci);
+ break;
default:
break;
}
@@ -1306,6 +1351,10 @@ static int ep_disable(struct usb_ep *ep)
return -EBUSY;
spin_lock_irqsave(hwep->lock, flags);
+ if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+ spin_unlock_irqrestore(hwep->lock, flags);
+ return 0;
+ }
/* only internal SW should disable ctrl endpts */
@@ -1395,6 +1444,10 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
return -EINVAL;
spin_lock_irqsave(hwep->lock, flags);
+ if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+ spin_unlock_irqrestore(hwep->lock, flags);
+ return 0;
+ }
retval = _ep_queue(ep, req, gfp_flags);
spin_unlock_irqrestore(hwep->lock, flags);
return retval;
@@ -1418,8 +1471,8 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
return -EINVAL;
spin_lock_irqsave(hwep->lock, flags);
-
- hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
+ if (hwep->ci->gadget.speed != USB_SPEED_UNKNOWN)
+ hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) {
dma_pool_free(hwep->td_pool, node->ptr, node->dma);
@@ -1490,6 +1543,10 @@ static void ep_fifo_flush(struct usb_ep *ep)
}
spin_lock_irqsave(hwep->lock, flags);
+ if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+ spin_unlock_irqrestore(hwep->lock, flags);
+ return;
+ }
hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
@@ -1527,27 +1584,19 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
gadget_ready = 1;
spin_unlock_irqrestore(&ci->lock, flags);
- if (gadget_ready) {
- if (is_active) {
- pm_runtime_get_sync(&_gadget->dev);
- hw_device_reset(ci);
- hw_device_state(ci, ci->ep0out->qh.dma);
- usb_gadget_set_state(_gadget, USB_STATE_POWERED);
- usb_udc_vbus_handler(_gadget, true);
- } else {
- usb_udc_vbus_handler(_gadget, false);
- if (ci->driver)
- ci->driver->disconnect(&ci->gadget);
- hw_device_state(ci, 0);
- if (ci->platdata->notify_event)
- ci->platdata->notify_event(ci,
- CI_HDRC_CONTROLLER_STOPPED_EVENT);
- _gadget_stop_activity(&ci->gadget);
- pm_runtime_put_sync(&_gadget->dev);
- usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED);
- }
+ /* Charger Detection */
+ ci_usb_charger_connect(ci, is_active);
+
+ if (ci->usb_phy) {
+ if (is_active)
+ usb_phy_set_event(ci->usb_phy, USB_EVENT_VBUS);
+ else
+ usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE);
}
+ if (gadget_ready)
+ ci_hdrc_gadget_connect(_gadget, is_active);
+
return 0;
}
@@ -1558,6 +1607,10 @@ static int ci_udc_wakeup(struct usb_gadget *_gadget)
int ret = 0;
spin_lock_irqsave(&ci->lock, flags);
+ if (ci->gadget.speed == USB_SPEED_UNKNOWN) {
+ spin_unlock_irqrestore(&ci->lock, flags);
+ return 0;
+ }
if (!ci->remote_wakeup) {
ret = -EOPNOTSUPP;
goto out;
@@ -1725,7 +1778,6 @@ static int ci_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
- unsigned long flags;
int retval = -ENOMEM;
if (driver->disconnect == NULL)
@@ -1745,25 +1797,14 @@ static int ci_udc_start(struct usb_gadget *gadget,
ci->driver = driver;
/* Start otg fsm for B-device */
- if (ci_otg_is_fsm_mode(ci) && ci->fsm.id) {
- ci_hdrc_otg_fsm_start(ci);
+ if (ci_otg_is_fsm_mode(ci)) {
+ if (ci->fsm.id)
+ ci_hdrc_otg_fsm_start(ci);
return retval;
}
- pm_runtime_get_sync(&ci->gadget.dev);
- if (ci->vbus_active) {
- spin_lock_irqsave(&ci->lock, flags);
- hw_device_reset(ci);
- } else {
- usb_udc_vbus_handler(&ci->gadget, false);
- pm_runtime_put_sync(&ci->gadget.dev);
- return retval;
- }
-
- retval = hw_device_state(ci, ci->ep0out->qh.dma);
- spin_unlock_irqrestore(&ci->lock, flags);
- if (retval)
- pm_runtime_put_sync(&ci->gadget.dev);
+ if (ci->vbus_active)
+ ci_hdrc_gadget_connect(&ci->gadget, 1);
return retval;
}
@@ -1848,27 +1889,35 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
if (USBi_PCI & intr) {
ci->gadget.speed = hw_port_is_high_speed(ci) ?
USB_SPEED_HIGH : USB_SPEED_FULL;
- if (ci->suspended && ci->driver->resume) {
- spin_unlock(&ci->lock);
- ci->driver->resume(&ci->gadget);
- spin_lock(&ci->lock);
+ if (ci->usb_phy)
+ usb_phy_set_event(ci->usb_phy,
+ USB_EVENT_ENUMERATED);
+ if (ci->suspended) {
+ if (ci->driver->resume) {
+ spin_unlock(&ci->lock);
+ ci->driver->resume(&ci->gadget);
+ spin_lock(&ci->lock);
+ }
ci->suspended = 0;
+ usb_gadget_set_state(&ci->gadget,
+ ci->resume_state);
}
}
if (USBi_UI & intr)
isr_tr_complete_handler(ci);
- if (USBi_SLI & intr) {
+ if ((USBi_SLI & intr) && !(ci->suspended)) {
+ ci->suspended = 1;
+ ci->resume_state = ci->gadget.state;
if (ci->gadget.speed != USB_SPEED_UNKNOWN &&
ci->driver->suspend) {
- ci->suspended = 1;
spin_unlock(&ci->lock);
ci->driver->suspend(&ci->gadget);
- usb_gadget_set_state(&ci->gadget,
- USB_STATE_SUSPENDED);
spin_lock(&ci->lock);
}
+ usb_gadget_set_state(&ci->gadget,
+ USB_STATE_SUSPENDED);
}
retval = IRQ_HANDLED;
} else {
@@ -1958,10 +2007,74 @@ void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
dma_pool_destroy(ci->qh_pool);
}
+int ci_usb_charger_connect(struct ci_hdrc *ci, int is_active)
+{
+ int ret = 0;
+
+ if (is_active)
+ pm_runtime_get_sync(ci->dev);
+
+ if (ci->platdata->notify_event) {
+ if (is_active)
+ hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+
+ ret = ci->platdata->notify_event(ci,
+ CI_HDRC_CONTROLLER_VBUS_EVENT);
+ if (ret == CI_HDRC_NOTIFY_RET_DEFER_EVENT) {
+ hw_device_reset(ci);
+ /* Pull up dp */
+ hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
+ ci->platdata->notify_event(ci,
+ CI_HDRC_CONTROLLER_CHARGER_POST_EVENT);
+ /* Pull down dp */
+ hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+ }
+ }
+
+ if (!is_active)
+ pm_runtime_put_sync(ci->dev);
+
+ return ret;
+}
+
+/**
+ * ci_hdrc_gadget_connect: caller make sure gadget driver is binded
+ */
+void ci_hdrc_gadget_connect(struct usb_gadget *gadget, int is_active)
+{
+ struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
+
+ if (is_active) {
+ pm_runtime_get_sync(&gadget->dev);
+ hw_device_reset(ci);
+ hw_device_state(ci, ci->ep0out->qh.dma);
+ usb_gadget_set_state(gadget, USB_STATE_POWERED);
+ usb_udc_vbus_handler(gadget, true);
+ } else {
+ usb_udc_vbus_handler(gadget, false);
+ if (ci->driver)
+ ci->driver->disconnect(gadget);
+ hw_device_state(ci, 0);
+ if (ci->platdata->notify_event)
+ ci->platdata->notify_event(ci,
+ CI_HDRC_CONTROLLER_STOPPED_EVENT);
+ _gadget_stop_activity(gadget);
+ pm_runtime_put_sync(&gadget->dev);
+ usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
+ }
+}
+
static int udc_id_switch_for_device(struct ci_hdrc *ci)
{
- if (ci->is_otg)
- /* Clear and enable BSV irq */
+ if (!ci->is_otg)
+ return 0;
+
+ /*
+ * Clear and enable BSV irq for A-device switch to B-device
+ * (in otg fsm mode, means A_IDLE->B_DILE) due to ID change.
+ */
+ if (!ci_otg_is_fsm_mode(ci) ||
+ ci->fsm.otg->state == OTG_STATE_A_IDLE)
hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE,
OTGSC_BSVIS | OTGSC_BSVIE);
@@ -1970,14 +2083,57 @@ static int udc_id_switch_for_device(struct ci_hdrc *ci)
static void udc_id_switch_for_host(struct ci_hdrc *ci)
{
+ if (!ci->is_otg)
+ return;
+
/*
- * host doesn't care B_SESSION_VALID event
- * so clear and disbale BSV irq
+ * Clear and disbale BSV irq for B-device switch to A-device
+ * (in otg fsm mode, means B_IDLE->A_IDLE) due to ID change.
*/
- if (ci->is_otg)
+ if (!ci_otg_is_fsm_mode(ci) ||
+ ci->fsm.otg->state == OTG_STATE_B_IDLE ||
+ ci->fsm.otg->state == OTG_STATE_UNDEFINED)
hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, OTGSC_BSVIS);
}
+static void udc_suspend_for_power_lost(struct ci_hdrc *ci)
+{
+ /*
+ * Set OP_ENDPTLISTADDR to be non-zero for
+ * checking if controller resume from power lost
+ * in non-host mode.
+ */
+ if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0)
+ hw_write(ci, OP_ENDPTLISTADDR, ~0, ~0);
+}
+
+/* Power lost with device mode */
+static void udc_resume_from_power_lost(struct ci_hdrc *ci)
+{
+ if (ci->is_otg)
+ hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE,
+ OTGSC_BSVIS | OTGSC_BSVIE);
+}
+
+static void udc_suspend(struct ci_hdrc *ci)
+{
+ udc_suspend_for_power_lost(ci);
+
+ if (ci->driver && ci->vbus_active &&
+ (ci->gadget.state != USB_STATE_SUSPENDED))
+ usb_gadget_disconnect(&ci->gadget);
+}
+
+static void udc_resume(struct ci_hdrc *ci, bool power_lost)
+{
+ if (power_lost) {
+ udc_resume_from_power_lost(ci);
+ } else {
+ if (ci->driver && ci->vbus_active)
+ usb_gadget_connect(&ci->gadget);
+ }
+}
+
/**
* ci_hdrc_gadget_init - initialize device related bits
* ci: the controller
@@ -1999,6 +2155,8 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci)
rdrv->start = udc_id_switch_for_device;
rdrv->stop = udc_id_switch_for_host;
rdrv->irq = udc_irq;
+ rdrv->suspend = udc_suspend;
+ rdrv->resume = udc_resume;
rdrv->name = "gadget";
ret = udc_start(ci);
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h
index e66df0020bd4..7c3af66aa8f4 100644
--- a/drivers/usb/chipidea/udc.h
+++ b/drivers/usb/chipidea/udc.h
@@ -85,6 +85,8 @@ struct ci_hw_req {
int ci_hdrc_gadget_init(struct ci_hdrc *ci);
void ci_hdrc_gadget_destroy(struct ci_hdrc *ci);
+int ci_usb_charger_connect(struct ci_hdrc *ci, int is_active);
+void ci_hdrc_gadget_connect(struct usb_gadget *gadget, int is_active);
#else
@@ -98,6 +100,17 @@ static inline void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
}
+static inline int ci_usb_charger_connect(struct ci_hdrc *ci, int is_active)
+{
+ return 0;
+}
+
+static inline void ci_hdrc_gadget_connect(struct usb_gadget *gadget,
+ int is_active)
+{
+
+}
+
#endif
#endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 20d02a5e418d..c467f09a9fb7 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-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
@@ -14,6 +15,8 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include "ci_hdrc_imx.h"
@@ -58,10 +61,22 @@
#define MX6_BM_OVER_CUR_DIS BIT(7)
#define MX6_BM_OVER_CUR_POLARITY BIT(8)
#define MX6_BM_WAKEUP_ENABLE BIT(10)
+#define MX6_BM_UTMI_ON_CLOCK BIT(13)
#define MX6_BM_ID_WAKEUP BIT(16)
#define MX6_BM_VBUS_WAKEUP BIT(17)
#define MX6SX_BM_DPDM_WAKEUP_EN BIT(29)
#define MX6_BM_WAKEUP_INTR BIT(31)
+
+#define MX6_USB_HSIC_CTRL_OFFSET 0x10
+/* Send resume signal without 480Mhz PHY clock */
+#define MX6SX_BM_HSIC_AUTO_RESUME BIT(23)
+/* set before portsc.suspendM = 1 */
+#define MX6_BM_HSIC_DEV_CONN BIT(21)
+/* HSIC enable */
+#define MX6_BM_HSIC_EN BIT(12)
+/* Force HSIC module 480M clock on, even when in Host is in suspend mode */
+#define MX6_BM_HSIC_CLK_ON BIT(11)
+
#define MX6_USB_OTG1_PHY_CTRL 0x18
/* For imx6dql, it is host-only controller, for later imx6, it is otg's */
#define MX6_USB_OTG2_PHY_CTRL 0x1c
@@ -74,12 +89,49 @@
#define VF610_OVER_CUR_DIS BIT(7)
#define MX7D_USBNC_USB_CTRL2 0x4
+#define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN BIT(8)
+#define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK (BIT(7) | BIT(6))
+#define MX7D_USBNC_USB_CTRL2_OPMODE(v) (v << 6)
+#define MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING MX7D_USBNC_USB_CTRL2_OPMODE(1)
+
#define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK 0x3
#define MX7D_USB_VBUS_WAKEUP_SOURCE(v) (v << 0)
#define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS MX7D_USB_VBUS_WAKEUP_SOURCE(0)
#define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1)
#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2)
#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3)
+#define MX7D_USB_TERMSEL_OVERRIDE BIT(4)
+#define MX7D_USB_TERMSEL_OVERRIDE_EN BIT(5)
+
+#define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB BIT(3)
+#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2)
+#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 BIT(1)
+#define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL BIT(0)
+#define MX7D_USB_OTG_PHY_CFG2 0x34
+
+#define MX7D_USB_OTG_PHY_STATUS 0x3c
+#define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29)
+#define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD BIT(3)
+#define MX7D_USB_OTG_PHY_STATUS_LINE_STATE1 BIT(1)
+#define MX7D_USB_OTG_PHY_STATUS_LINE_STATE0 BIT(0)
+
+#define ANADIG_ANA_MISC0 0x150
+#define ANADIG_ANA_MISC0_SET 0x154
+#define ANADIG_ANA_MISC0_CLK_DELAY(x) ((x >> 26) & 0x7)
+
+#define ANADIG_USB1_CHRG_DETECT_SET 0x1b4
+#define ANADIG_USB1_CHRG_DETECT_CLR 0x1b8
+#define ANADIG_USB1_CHRG_DETECT_EN_B BIT(20)
+#define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B BIT(19)
+#define ANADIG_USB1_CHRG_DETECT_CHK_CONTACT BIT(18)
+
+#define ANADIG_USB1_VBUS_DET_STAT 0x1c0
+#define ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3)
+
+#define ANADIG_USB1_CHRG_DET_STAT 0x1d0
+#define ANADIG_USB1_CHRG_DET_STAT_DM_STATE BIT(2)
+#define ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED BIT(1)
+#define ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT BIT(0)
struct usbmisc_ops {
/* It's called once when probe a usb device */
@@ -88,6 +140,19 @@ struct usbmisc_ops {
int (*post)(struct imx_usbmisc_data *data);
/* It's called when we need to enable/disable usb wakeup */
int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
+ /* usb charger contact and primary detection */
+ int (*charger_primary_detection)(struct imx_usbmisc_data *data);
+ /* usb charger secondary detection */
+ int (*charger_secondary_detection)(struct imx_usbmisc_data *data);
+ /* It's called when system resume from usb power lost */
+ int (*power_lost_check)(struct imx_usbmisc_data *data);
+ /* It's called before setting portsc.suspendM */
+ int (*hsic_set_connect)(struct imx_usbmisc_data *data);
+ /* It's called during suspend/resume */
+ int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
+ /* override UTMI termination select */
+ int (*term_select_override)(struct imx_usbmisc_data *data,
+ bool enable, int val);
};
struct imx_usbmisc {
@@ -96,6 +161,8 @@ struct imx_usbmisc {
const struct usbmisc_ops *ops;
};
+static struct regulator *vbus_wakeup_reg;
+
static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
{
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
@@ -227,15 +294,66 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
return 0;
}
+static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
+{
+ unsigned long flags;
+ u32 val;
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ if (data->index == 2 || data->index == 3) {
+ val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
+ + (data->index - 2) * 4);
+ if (!(val & MX6_BM_HSIC_DEV_CONN))
+ writel(val | MX6_BM_HSIC_DEV_CONN,
+ usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
+ + (data->index - 2) * 4);
+ }
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ return 0;
+}
+
+static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
+{
+ unsigned long flags;
+ u32 val;
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ if (data->index == 2 || data->index == 3) {
+ val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
+ + (data->index - 2) * 4);
+ val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
+ if (on)
+ val |= MX6_BM_HSIC_CLK_ON;
+ else
+ val &= ~MX6_BM_HSIC_CLK_ON;
+ writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
+ + (data->index - 2) * 4);
+ }
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ return 0;
+}
+
+static u32 imx6q_finalize_wakeup_setting(struct imx_usbmisc_data *data)
+{
+ if (data->available_role == USB_DR_MODE_PERIPHERAL)
+ return MX6_BM_VBUS_WAKEUP;
+ else if (data->available_role == USB_DR_MODE_OTG)
+ return MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP;
+
+ return 0;
+}
+
static int usbmisc_imx6q_set_wakeup
(struct imx_usbmisc_data *data, bool enabled)
{
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
unsigned long flags;
- u32 val;
- u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
- MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
int ret = 0;
+ u32 val, wakeup_setting = MX6_BM_WAKEUP_ENABLE;
if (data->index > 3)
return -EINVAL;
@@ -243,15 +361,20 @@ static int usbmisc_imx6q_set_wakeup
spin_lock_irqsave(&usbmisc->lock, flags);
val = readl(usbmisc->base + data->index * 4);
if (enabled) {
- val |= wakeup_setting;
- writel(val, usbmisc->base + data->index * 4);
+ wakeup_setting |= imx6q_finalize_wakeup_setting(data);
+ writel(val | wakeup_setting, usbmisc->base + data->index * 4);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ if (vbus_wakeup_reg)
+ ret = regulator_enable(vbus_wakeup_reg);
} else {
if (val & MX6_BM_WAKEUP_INTR)
pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
- val &= ~wakeup_setting;
- writel(val, usbmisc->base + data->index * 4);
+ wakeup_setting |= MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP;
+ writel(val & ~wakeup_setting, usbmisc->base + data->index * 4);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ if (vbus_wakeup_reg && regulator_is_enabled(vbus_wakeup_reg))
+ regulator_disable(vbus_wakeup_reg);
}
- spin_unlock_irqrestore(&usbmisc->lock, flags);
return ret;
}
@@ -260,7 +383,7 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
{
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
unsigned long flags;
- u32 reg;
+ u32 reg, val;
if (data->index > 3)
return -EINVAL;
@@ -281,6 +404,27 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
writel(reg | MX6_BM_NON_BURST_SETTING,
usbmisc->base + data->index * 4);
+ /* For HSIC controller */
+ if (data->index == 2 || data->index == 3) {
+ val = readl(usbmisc->base + data->index * 4);
+ writel(val | MX6_BM_UTMI_ON_CLOCK,
+ usbmisc->base + data->index * 4);
+ val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
+ + (data->index - 2) * 4);
+ val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
+ writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
+ + (data->index - 2) * 4);
+
+ /*
+ * Need to add delay to wait 24M OSC to be stable,
+ * It is board specific.
+ */
+ regmap_read(data->anatop, ANADIG_ANA_MISC0, &val);
+ /* 0 <= data->osc_clkgate_delay <= 7 */
+ if (data->osc_clkgate_delay > ANADIG_ANA_MISC0_CLK_DELAY(val))
+ regmap_write(data->anatop, ANADIG_ANA_MISC0_SET,
+ (data->osc_clkgate_delay) << 26);
+ }
spin_unlock_irqrestore(&usbmisc->lock, flags);
usbmisc_imx6q_set_wakeup(data, false);
@@ -297,9 +441,9 @@ static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
usbmisc_imx6q_init(data);
+ spin_lock_irqsave(&usbmisc->lock, flags);
if (data->index == 0 || data->index == 1) {
reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
- spin_lock_irqsave(&usbmisc->lock, flags);
/* Set vbus wakeup source as bvalid */
val = readl(reg);
writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
@@ -310,9 +454,18 @@ static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
val = readl(usbmisc->base + data->index * 4);
writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
usbmisc->base + data->index * 4);
- spin_unlock_irqrestore(&usbmisc->lock, flags);
}
+ /* For HSIC controller */
+ if (data->index == 2) {
+ val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
+ + (data->index - 2) * 4);
+ val |= MX6SX_BM_HSIC_AUTO_RESUME;
+ writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
+ + (data->index - 2) * 4);
+ }
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
return 0;
}
@@ -342,16 +495,17 @@ static int usbmisc_imx7d_set_wakeup
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
unsigned long flags;
u32 val;
- u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
- MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
+ u32 wakeup_setting = MX6_BM_WAKEUP_ENABLE;
spin_lock_irqsave(&usbmisc->lock, flags);
val = readl(usbmisc->base);
if (enabled) {
+ wakeup_setting |= imx6q_finalize_wakeup_setting(data);
writel(val | wakeup_setting, usbmisc->base);
} else {
if (val & MX6_BM_WAKEUP_INTR)
dev_dbg(data->dev, "wakeup int\n");
+ wakeup_setting |= MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP;
writel(val & ~wakeup_setting, usbmisc->base);
}
spin_unlock_irqrestore(&usbmisc->lock, flags);
@@ -378,6 +532,10 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
}
writel(reg, usbmisc->base);
+ /* SoC non-burst setting */
+ reg = readl(usbmisc->base);
+ writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
+
reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
@@ -389,6 +547,375 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
return 0;
}
+static int usbmisc_imx7d_power_lost_check(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ val = readl(usbmisc->base);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ /*
+ * Here use a power on reset value to judge
+ * if the controller experienced a power lost
+ */
+ if (val == 0x30001000)
+ return 1;
+ else
+ return 0;
+}
+
+
+/***************************************************************************/
+/* imx usb charger detecton */
+/***************************************************************************/
+#ifdef CONFIG_POWER_SUPPLY
+static void usb_charger_is_present(struct usb_charger *charger, bool present)
+{
+ if (present)
+ charger->present = 1;
+ else
+ charger->present = 0;
+
+ power_supply_changed(charger->psy);
+ sysfs_notify(&charger->psy->dev.kobj, NULL, "present");
+}
+
+static void imx6_disable_charger_detector(struct imx_usbmisc_data *data)
+{
+ struct regmap *regmap = data->anatop;
+
+ regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET,
+ ANADIG_USB1_CHRG_DETECT_EN_B |
+ ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
+}
+
+static int imx6_charger_data_contact_detect(struct imx_usbmisc_data *data)
+{
+ struct regmap *regmap = data->anatop;
+ struct usb_charger *charger = data->charger;
+ u32 val;
+ int i, data_pin_contact_count = 0;
+
+ /* check if vbus is valid */
+ regmap_read(regmap, ANADIG_USB1_VBUS_DET_STAT, &val);
+ if (!(val & ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)) {
+ dev_err(charger->dev, "vbus is error\n");
+ return -EINVAL;
+ }
+
+ /* Enable charger detector */
+ regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_CLR,
+ ANADIG_USB1_CHRG_DETECT_EN_B);
+ /*
+ * - Do not check whether a charger is connected to the USB port
+ * - Check whether the USB plug has been in contact with each other
+ */
+ regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET,
+ ANADIG_USB1_CHRG_DETECT_CHK_CONTACT |
+ ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
+
+ /* Check if plug is connected */
+ for (i = 0; i < 100; i = i + 1) {
+ regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
+ if (val & ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT) {
+ data_pin_contact_count++;
+ if (data_pin_contact_count > 5)
+ /* Data pin makes contact */
+ break;
+ else
+ usleep_range(5000, 10000);
+ } else {
+ data_pin_contact_count = 0;
+ usleep_range(5000, 6000);
+ }
+ }
+
+ if (i == 100) {
+ dev_err(charger->dev,
+ "VBUS is coming from a dedicated power supply.\n");
+ imx6_disable_charger_detector(data);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static int imx6_charger_primary_detection(struct imx_usbmisc_data *data)
+{
+ struct regmap *regmap = data->anatop;
+ struct usb_charger *charger = data->charger;
+ u32 val;
+ int ret;
+
+ ret = imx6_charger_data_contact_detect(data);
+ if (ret)
+ return ret;
+
+ /*
+ * - Do check whether a charger is connected to the USB port
+ * - Do not Check whether the USB plug has been in contact with
+ * each other
+ */
+ regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_CLR,
+ ANADIG_USB1_CHRG_DETECT_CHK_CONTACT |
+ ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
+
+ msleep(100);
+
+ /* Check if it is a charger */
+ regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
+ if (!(val & ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED)) {
+ dev_dbg(charger->dev, "It is a stardard downstream port\n");
+ charger->psy_desc.type = POWER_SUPPLY_TYPE_USB;
+ charger->max_current = 500;
+ }
+
+ imx6_disable_charger_detector(data);
+ return 0;
+}
+
+/*
+ * It must be called after dp is pulled up (from USB controller driver),
+ * That is used to differentiate DCP and CDP
+ */
+int imx6_charger_secondary_detection(struct imx_usbmisc_data *data)
+{
+ struct regmap *regmap = data->anatop;
+ struct usb_charger *charger = data->charger;
+ int val;
+
+ msleep(80);
+
+ mutex_lock(&charger->lock);
+ regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
+ if (val & ANADIG_USB1_CHRG_DET_STAT_DM_STATE) {
+ dev_dbg(charger->dev, "It is a dedicate charging port\n");
+ charger->psy_desc.type = POWER_SUPPLY_TYPE_USB_DCP;
+ charger->max_current = 1500;
+ } else {
+ dev_dbg(charger->dev, "It is a charging downstream port\n");
+ charger->psy_desc.type = POWER_SUPPLY_TYPE_USB_CDP;
+ charger->max_current = 900;
+ }
+
+ usb_charger_is_present(charger, true);
+ mutex_unlock(&charger->lock);
+
+ return 0;
+}
+
+static int usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ val = readl(usbmisc->base + data->index * 4);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ /*
+ * Here use a power on reset value to judge
+ * if the controller experienced a power lost
+ */
+ if (val == 0x30001000)
+ return 1;
+ else
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_POWER_SUPPLY
+static void imx7_disable_charger_detector(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
+ val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB |
+ MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
+ MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
+ MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL);
+ writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
+
+ /* Set OPMODE to be 2'b00 and disable its override */
+ val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
+ writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
+
+ val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+}
+
+static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ struct usb_charger *charger = data->charger;
+ unsigned long flags;
+ u32 val;
+ int i, data_pin_contact_count = 0;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+
+ /* check if vbus is valid */
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
+ if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) {
+ dev_err(charger->dev, "vbus is error\n");
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ return -EINVAL;
+ }
+
+ /*
+ * - Do not check whether a charger is connected to the USB port
+ * - Check whether the USB plug has been in contact with each other
+ */
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
+ writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
+ usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
+
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ /* Check if plug is connected */
+ for (i = 0; i < 100; i = i + 1) {
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
+ if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) {
+ if (data_pin_contact_count++ > 5)
+ /* Data pin makes contact */
+ break;
+ else
+ usleep_range(5000, 10000);
+ } else {
+ data_pin_contact_count = 0;
+ usleep_range(5000, 6000);
+ }
+ }
+
+ if (i == 100) {
+ dev_err(charger->dev,
+ "VBUS is coming from a dedicated power supply.\n");
+ imx7_disable_charger_detector(data);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ struct usb_charger *charger = data->charger;
+ unsigned long flags;
+ u32 val;
+ int ret;
+
+ ret = imx7d_charger_data_contact_detect(data);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ /* Set OPMODE to be non-driving mode */
+ val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
+ val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING;
+ writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
+
+ val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+
+ /*
+ * - Do check whether a charger is connected to the USB port
+ * - Do not Check whether the USB plug has been in contact with
+ * each other
+ */
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
+ writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
+ MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0,
+ usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ usleep_range(1000, 2000);
+
+ /* Check if it is a charger */
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
+ if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) {
+ dev_dbg(charger->dev, "It is a stardard downstream port\n");
+ charger->psy_desc.type = POWER_SUPPLY_TYPE_USB;
+ charger->max_current = 500;
+ }
+
+ imx7_disable_charger_detector(data);
+
+ return 0;
+}
+
+/*
+ * It must be called after dp is pulled up (from USB controller driver),
+ * That is used to differentiate DCP and CDP
+ */
+int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ struct usb_charger *charger = data->charger;
+ int val;
+
+ msleep(80);
+
+ mutex_lock(&charger->lock);
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
+ if (val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE1) {
+ dev_dbg(charger->dev, "It is a dedicate charging port\n");
+ charger->psy_desc.type = POWER_SUPPLY_TYPE_USB_DCP;
+ charger->max_current = 1500;
+ } else {
+ dev_dbg(charger->dev, "It is a charging downstream port\n");
+ charger->psy_desc.type = POWER_SUPPLY_TYPE_USB_CDP;
+ charger->max_current = 900;
+ }
+
+ usb_charger_is_present(charger, true);
+ mutex_unlock(&charger->lock);
+
+ return 0;
+}
+#endif
+
+static int usbmisc_term_select_override(struct imx_usbmisc_data *data,
+ bool enable, int val)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+
+ reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ if (enable) {
+ if (val)
+ writel(reg | MX7D_USB_TERMSEL_OVERRIDE,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ else
+ writel(reg & ~MX7D_USB_TERMSEL_OVERRIDE,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+
+ reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ writel(reg | MX7D_USB_TERMSEL_OVERRIDE_EN,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ } else {
+ writel(reg & ~MX7D_USB_TERMSEL_OVERRIDE_EN,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ }
+
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ return 0;
+}
+
static const struct usbmisc_ops imx25_usbmisc_ops = {
.init = usbmisc_imx25_init,
.post = usbmisc_imx25_post,
@@ -405,6 +932,12 @@ static const struct usbmisc_ops imx53_usbmisc_ops = {
static const struct usbmisc_ops imx6q_usbmisc_ops = {
.set_wakeup = usbmisc_imx6q_set_wakeup,
.init = usbmisc_imx6q_init,
+#ifdef CONFIG_POWER_SUPPLY
+ .charger_primary_detection = imx6_charger_primary_detection,
+ .charger_secondary_detection = imx6_charger_secondary_detection,
+#endif
+ .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
+ .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
};
static const struct usbmisc_ops vf610_usbmisc_ops = {
@@ -414,11 +947,30 @@ static const struct usbmisc_ops vf610_usbmisc_ops = {
static const struct usbmisc_ops imx6sx_usbmisc_ops = {
.set_wakeup = usbmisc_imx6q_set_wakeup,
.init = usbmisc_imx6sx_init,
+#ifdef CONFIG_POWER_SUPPLY
+ .charger_primary_detection = imx6_charger_primary_detection,
+ .charger_secondary_detection = imx6_charger_secondary_detection,
+ .power_lost_check = usbmisc_imx6sx_power_lost_check,
+#endif
+ .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
+ .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
};
static const struct usbmisc_ops imx7d_usbmisc_ops = {
.init = usbmisc_imx7d_init,
.set_wakeup = usbmisc_imx7d_set_wakeup,
+#ifdef CONFIG_POWER_SUPPLY
+ .power_lost_check = usbmisc_imx7d_power_lost_check,
+ .charger_primary_detection = imx7d_charger_primary_detection,
+ .charger_secondary_detection = imx7d_charger_secondary_detection,
+#endif
+ .term_select_override = usbmisc_term_select_override,
+};
+
+static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
+ .init = usbmisc_imx7d_init,
+ .set_wakeup = usbmisc_imx7d_set_wakeup,
+ .power_lost_check = usbmisc_imx7d_power_lost_check,
};
int imx_usbmisc_init(struct imx_usbmisc_data *data)
@@ -463,6 +1015,117 @@ int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
}
EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
+#ifdef CONFIG_POWER_SUPPLY
+int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect)
+{
+ struct imx_usbmisc *usbmisc;
+ struct usb_charger *charger;
+ int ret = 0;
+
+ if (!data)
+ return -EINVAL;
+
+ charger = data->charger;
+ usbmisc = dev_get_drvdata(data->dev);
+ if (!usbmisc->ops->charger_primary_detection)
+ return -ENOTSUPP;
+
+ mutex_lock(&charger->lock);
+ if (connect) {
+ charger->online = 1;
+ ret = usbmisc->ops->charger_primary_detection(data);
+ if (ret) {
+ dev_err(charger->dev,
+ "Error occurs during detection: %d\n",
+ ret);
+ } else {
+ if (charger->psy_desc.type == POWER_SUPPLY_TYPE_USB)
+ usb_charger_is_present(charger, true);
+ }
+ } else {
+ charger->online = 0;
+ charger->max_current = 0;
+ charger->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
+
+ usb_charger_is_present(charger, false);
+ }
+ mutex_unlock(&charger->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection);
+
+int imx_usbmisc_charger_secondary_detection(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc;
+
+ if (!data)
+ return 0;
+
+ usbmisc = dev_get_drvdata(data->dev);
+ if (!usbmisc->ops->charger_secondary_detection)
+ return 0;
+ return usbmisc->ops->charger_secondary_detection(data);
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_charger_secondary_detection);
+#endif
+
+int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc;
+
+ if (!data)
+ return 0;
+
+ usbmisc = dev_get_drvdata(data->dev);
+ if (!usbmisc->ops->power_lost_check)
+ return 0;
+ return usbmisc->ops->power_lost_check(data);
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_power_lost_check);
+
+int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc;
+
+ if (!data)
+ return 0;
+
+ usbmisc = dev_get_drvdata(data->dev);
+ if (!usbmisc->ops->hsic_set_connect)
+ return 0;
+ return usbmisc->ops->hsic_set_connect(data);
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
+
+int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
+{
+ struct imx_usbmisc *usbmisc;
+
+ if (!data)
+ return 0;
+
+ usbmisc = dev_get_drvdata(data->dev);
+ if (!usbmisc->ops->hsic_set_clk)
+ return 0;
+ return usbmisc->ops->hsic_set_clk(data, on);
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
+
+int imx_usbmisc_term_select_override(struct imx_usbmisc_data *data,
+ bool enable, int val)
+{
+ struct imx_usbmisc *usbmisc;
+
+ if (!data)
+ return 0;
+
+ usbmisc = dev_get_drvdata(data->dev);
+ if (!usbmisc->ops->term_select_override)
+ return 0;
+ return usbmisc->ops->term_select_override(data, enable, val);
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_term_select_override);
+
static const struct of_device_id usbmisc_imx_dt_ids[] = {
{
.compatible = "fsl,imx25-usbmisc",
@@ -504,6 +1167,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
.compatible = "fsl,imx7d-usbmisc",
.data = &imx7d_usbmisc_ops,
},
+ {
+ .compatible = "fsl,imx7ulp-usbmisc",
+ .data = &imx7ulp_usbmisc_ops,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
@@ -532,6 +1199,18 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
data->ops = (const struct usbmisc_ops *)of_id->data;
platform_set_drvdata(pdev, data);
+ vbus_wakeup_reg = devm_regulator_get(&pdev->dev, "vbus-wakeup");
+ if (PTR_ERR(vbus_wakeup_reg) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ else if (PTR_ERR(vbus_wakeup_reg) == -ENODEV)
+ /* no vbus regualator is needed */
+ vbus_wakeup_reg = NULL;
+ else if (IS_ERR(vbus_wakeup_reg)) {
+ dev_err(&pdev->dev, "Getting regulator error: %ld\n",
+ PTR_ERR(vbus_wakeup_reg));
+ return PTR_ERR(vbus_wakeup_reg);
+ }
+
return 0;
}
diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 2f537bbdda09..23009e3d8ca9 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -68,6 +68,7 @@ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
switch (old_state) {
case OTG_STATE_B_IDLE:
otg_del_timer(fsm, B_SE0_SRP);
+ otg_del_timer(fsm, B_SRP_FAIL);
fsm->b_se0_srp = 0;
fsm->adp_sns = 0;
fsm->adp_prb = 0;
@@ -85,6 +86,11 @@ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
fsm->b_ase0_brst_tmout = 0;
break;
case OTG_STATE_B_HOST:
+ if (fsm->otg_hnp_reqd) {
+ fsm->otg_hnp_reqd = 0;
+ fsm->b_bus_req = 0;
+ }
+ fsm->a_conn = 0;
break;
case OTG_STATE_A_IDLE:
fsm->adp_prb = 0;
@@ -131,8 +137,10 @@ static void otg_hnp_polling_work(struct work_struct *work)
enum usb_otg_state state = fsm->otg->state;
u8 flag;
int retval;
+ struct usb_otg_descriptor *desc = NULL;
- if (state != OTG_STATE_A_HOST && state != OTG_STATE_B_HOST)
+ if ((state != OTG_STATE_A_HOST || !fsm->b_hnp_enable) &&
+ state != OTG_STATE_B_HOST)
return;
udev = usb_hub_find_child(fsm->otg->host->root_hub, 1);
@@ -142,6 +150,31 @@ static void otg_hnp_polling_work(struct work_struct *work)
return;
}
+ if (udev->state != USB_STATE_CONFIGURED) {
+ dev_dbg(&udev->dev, "the B dev is not resumed!\n");
+ schedule_delayed_work(&fsm->hnp_polling_work,
+ msecs_to_jiffies(T_HOST_REQ_POLL));
+ return;
+ }
+
+ /*
+ * Legacy otg test device does not support HNP polling,
+ * start HNP directly for legacy otg test device.
+ */
+ if (fsm->tst_maint &&
+ (__usb_get_extra_descriptor(udev->rawdescriptors[0],
+ le16_to_cpu(udev->config[0].desc.wTotalLength),
+ USB_DT_OTG, (void **) &desc) == 0)) {
+ /* shorter bLength of OTG 1.3 or earlier */
+ if (desc->bLength < 5) {
+ fsm->a_bus_req = 0;
+ fsm->tst_maint = 0;
+ otg_del_timer(fsm, A_TST_MAINT);
+ *fsm->host_req_flag = HOST_REQUEST_FLAG;
+ return;
+ }
+ }
+
*fsm->host_req_flag = 0;
/* Get host request flag from connected USB device */
retval = usb_control_msg(udev,
@@ -183,6 +216,11 @@ static void otg_hnp_polling_work(struct work_struct *work)
fsm->otg->host->b_hnp_enable = 1;
}
fsm->a_bus_req = 0;
+ if (fsm->tst_maint) {
+ fsm->tst_maint = 0;
+ fsm->otg_vbus_off = 0;
+ otg_del_timer(fsm, A_TST_MAINT);
+ }
} else if (state == OTG_STATE_B_HOST) {
fsm->b_bus_req = 0;
}
@@ -224,6 +262,10 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
otg_start_adp_sns(fsm);
otg_set_protocol(fsm, PROTO_UNDEF);
otg_add_timer(fsm, B_SE0_SRP);
+ if (fsm->otg_hnp_reqd) {
+ fsm->otg_hnp_reqd = 0;
+ fsm->b_bus_req = 0;
+ }
break;
case OTG_STATE_B_SRP_INIT:
otg_start_pulse(fsm);
@@ -236,6 +278,7 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
otg_loc_sof(fsm, 0);
otg_set_protocol(fsm, PROTO_GADGET);
otg_loc_conn(fsm, 1);
+ fsm->b_bus_req = 0;
break;
case OTG_STATE_B_WAIT_ACON:
otg_chrg_vbus(fsm, 0);
@@ -250,8 +293,6 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
otg_loc_conn(fsm, 0);
otg_loc_sof(fsm, 1);
otg_set_protocol(fsm, PROTO_HOST);
- usb_bus_start_enum(fsm->otg->host,
- fsm->otg->host->otg_port);
otg_start_hnp_polling(fsm);
break;
case OTG_STATE_A_IDLE:
@@ -406,8 +447,7 @@ int otg_statemachine(struct otg_fsm *fsm)
case OTG_STATE_A_HOST:
if (fsm->id || fsm->a_bus_drop)
otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
- else if ((!fsm->a_bus_req || fsm->a_suspend_req_inf) &&
- fsm->otg->host->b_hnp_enable)
+ else if (!fsm->a_bus_req || fsm->a_suspend_req_inf)
otg_set_state(fsm, OTG_STATE_A_SUSPEND);
else if (!fsm->b_conn)
otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
@@ -415,9 +455,9 @@ int otg_statemachine(struct otg_fsm *fsm)
otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
break;
case OTG_STATE_A_SUSPEND:
- if (!fsm->b_conn && fsm->otg->host->b_hnp_enable)
+ if (!fsm->b_conn && fsm->a_set_b_hnp_en)
otg_set_state(fsm, OTG_STATE_A_PERIPHERAL);
- else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable)
+ else if (!fsm->b_conn && !fsm->a_set_b_hnp_en)
otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
else if (fsm->a_bus_req || fsm->b_bus_resume)
otg_set_state(fsm, OTG_STATE_A_HOST);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d0d3f9ef9f10..1cad3ea0b048 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -21,6 +21,7 @@
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h>
#include <linux/usb/otg.h>
+#include <linux/usb/otg-fsm.h>
#include <linux/usb/quirks.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
@@ -1108,6 +1109,10 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
need_debounce_delay = true;
usb_clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_C_CONNECTION);
+#ifdef CONFIG_USB_OTG
+ if (hdev->bus->is_b_host)
+ usb_bus_start_enum(hdev->bus, port1);
+#endif
}
if (portchange & USB_PORT_STAT_C_ENABLE) {
need_debounce_delay = true;
@@ -2198,9 +2203,9 @@ static inline void announce_device(struct usb_device *udev) { }
*/
static int usb_enumerate_device_otg(struct usb_device *udev)
{
+#ifdef CONFIG_USB_OTG
int err = 0;
-#ifdef CONFIG_USB_OTG
/*
* OTG-aware devices on OTG-capable root hubs may be able to use SRP,
* to wake us after we've powered off VBUS; and HNP, switching roles
@@ -2241,6 +2246,12 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
err);
bus->b_hnp_enable = 0;
}
+
+ if (bus->otg_fsm) {
+ bus->otg_fsm->b_hnp_enable = 1;
+ if (bus->b_hnp_enable)
+ bus->otg_fsm->a_set_b_hnp_en = 1;
+ }
} else if (desc->bLength == sizeof
(struct usb_otg_descriptor)) {
/* Set a_alt_hnp_support for legacy otg device */
@@ -2257,7 +2268,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
}
}
#endif
- return err;
+ return 0;
}
@@ -2279,6 +2290,7 @@ static int usb_enumerate_device(struct usb_device *udev)
{
int err;
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+ struct otg_fsm *fsm = udev->bus->otg_fsm;
if (udev->config == NULL) {
err = usb_get_configuration(udev);
@@ -2310,8 +2322,10 @@ static int usb_enumerate_device(struct usb_device *udev)
err = usb_port_suspend(udev, PMSG_AUTO_SUSPEND);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
+ return -ENOTSUPP;
+ } else if (!fsm || !fsm->b_hnp_enable || !fsm->hnp_polling) {
+ return -ENOTSUPP;
}
- return -ENOTSUPP;
}
usb_detect_interface_quirks(udev);
@@ -4519,7 +4533,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
}
if (r) {
if (r != -ENODEV)
- dev_err(&udev->dev, "device descriptor read/64, error %d\n",
+ dev_err(&udev->dev,
+ "device no response, device descriptor read/64, error %d\n",
r);
retval = -EMSGSIZE;
continue;
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index 085049d37d7a..68b4f7e80b47 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -17,35 +17,64 @@
*/
static struct usb_device_id whitelist_table[] = {
-
-/* hubs are optional in OTG, but very handy ... */
-{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
-{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
-
-#ifdef CONFIG_USB_PRINTER /* ignoring nonstatic linkage! */
-/* FIXME actually, printers are NOT supposed to use device classes;
- * they're supposed to use interface classes...
- */
-{ USB_DEVICE_INFO(7, 1, 1) },
-{ USB_DEVICE_INFO(7, 1, 2) },
-{ USB_DEVICE_INFO(7, 1, 3) },
+/* Add FSL i.mx whitelist, the default list is for USB Compliance Test */
+#if defined(CONFIG_USB_EHSET_TEST_FIXTURE) \
+ || defined(CONFIG_USB_EHSET_TEST_FIXTURE_MODULE)
+#define TEST_SE0_NAK_PID 0x0101
+#define TEST_J_PID 0x0102
+#define TEST_K_PID 0x0103
+#define TEST_PACKET_PID 0x0104
+#define TEST_HS_HOST_PORT_SUSPEND_RESUME 0x0106
+#define TEST_SINGLE_STEP_GET_DEV_DESC 0x0107
+#define TEST_SINGLE_STEP_SET_FEATURE 0x0108
+#define TEST_OTG_TEST_DEVICE_SUPPORT 0x0200
+{ USB_DEVICE(0x1a0a, TEST_SE0_NAK_PID) },
+{ USB_DEVICE(0x1a0a, TEST_J_PID) },
+{ USB_DEVICE(0x1a0a, TEST_K_PID) },
+{ USB_DEVICE(0x1a0a, TEST_PACKET_PID) },
+{ USB_DEVICE(0x1a0a, TEST_HS_HOST_PORT_SUSPEND_RESUME) },
+{ USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_GET_DEV_DESC) },
+{ USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_SET_FEATURE) },
+{ USB_DEVICE(0x1a0a, TEST_OTG_TEST_DEVICE_SUPPORT) },
#endif
-#ifdef CONFIG_USB_NET_CDCETHER
-/* Linux-USB CDC Ethernet gadget */
-{ USB_DEVICE(0x0525, 0xa4a1), },
-/* Linux-USB CDC Ethernet + RNDIS gadget */
-{ USB_DEVICE(0x0525, 0xa4a2), },
-#endif
+#define USB_INTERFACE_CLASS_INFO(cl) \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, \
+ .bInterfaceClass = (cl)
-#if IS_ENABLED(CONFIG_USB_TEST)
-/* gadget zero, for testing */
-{ USB_DEVICE(0x0525, 0xa4a0), },
+{USB_INTERFACE_CLASS_INFO(USB_CLASS_HUB) },
+#if defined(CONFIG_USB_STORAGE) || defined(CONFIG_USB_STORAGE_MODULE)
+{USB_INTERFACE_CLASS_INFO(USB_CLASS_MASS_STORAGE) },
+#endif
+#if defined(CONFIG_USB_HID) || defined(CONFIG_USB_HID_MODULE)
+{USB_INTERFACE_CLASS_INFO(USB_CLASS_HID) },
#endif
{ } /* Terminating entry */
};
+static bool match_int_class(struct usb_device_id *id, struct usb_device *udev)
+{
+ struct usb_host_config *c;
+ int num_configs, i;
+
+ /* Copy the code from generic.c */
+ c = udev->config;
+ num_configs = udev->descriptor.bNumConfigurations;
+ for (i = 0; i < num_configs; (i++, c++)) {
+ struct usb_interface_descriptor *desc = NULL;
+
+ /* It's possible that a config has no interfaces! */
+ if (c->desc.bNumInterfaces > 0)
+ desc = &c->intf_cache[0]->altsetting->desc;
+
+ if (desc && (desc->bInterfaceClass == id->bInterfaceClass))
+ return true;
+ }
+
+ return false;
+}
+
static int is_targeted(struct usb_device *dev)
{
struct usb_device_id *id = whitelist_table;
@@ -60,6 +89,19 @@ static int is_targeted(struct usb_device *dev)
le16_to_cpu(dev->descriptor.idProduct) == 0x0200))
return 1;
+ /* Unknown Device Not Supporting HNP */
+ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x0201)) {
+ dev_warn(&dev->dev, "Unsupported Device\n");
+ return 0;
+ }
+ /* Unknown Device Supporting HNP */
+ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x0202)) {
+ dev_warn(&dev->dev, "Device no Responding\n");
+ return 0;
+ }
+
/* NOTE: can't use usb_match_id() since interface caches
* aren't set up yet. this is cut/paste from that code.
*/
@@ -94,6 +136,10 @@ static int is_targeted(struct usb_device *dev)
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
continue;
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
+ (!match_int_class(id, dev)))
+ continue;
+
return 1;
}
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index d2fc237cd87a..87f607b07aff 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -329,8 +329,15 @@ struct fsg_dev {
struct usb_ep *bulk_in;
struct usb_ep *bulk_out;
+#ifdef CONFIG_FSL_UTP
+ void *utp;
+#endif
};
+#ifdef CONFIG_FSL_UTP
+#include "fsl_updater.h"
+#endif
+
static inline int __fsg_is_set(struct fsg_common *common,
const char *func, unsigned line)
{
@@ -1148,6 +1155,13 @@ static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
}
#endif
+#ifdef CONFIG_FSL_UTP
+ if (utp_get_sense(common->fsg) == 0) { /* got the sense from the UTP */
+ sd = UTP_CTX(common->fsg)->sd;
+ sdinfo = UTP_CTX(common->fsg)->sdinfo;
+ valid = 0;
+ } else
+#endif
if (!curlun) { /* Unsupported LUNs are okay */
common->bad_lun_okay = 1;
sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
@@ -1169,6 +1183,9 @@ static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
buf[7] = 18 - 8; /* Additional sense length */
buf[12] = ASC(sd);
buf[13] = ASCQ(sd);
+#ifdef CONFIG_FSL_UTP
+ put_unaligned_be32(UTP_CTX(common->fsg)->sdinfo_h, &buf[8]);
+#endif
return 18;
}
@@ -1662,7 +1679,18 @@ static int send_status(struct fsg_common *common)
sd = SS_INVALID_COMMAND;
} else if (sd != SS_NO_SENSE) {
DBG(common, "sending command-failure status\n");
+#ifdef CONFIG_FSL_UTP
+/*
+ * mfgtool host frequently reset bus during transfer
+ * - the response in csw to request sense will be 1 due to UTP change
+ * some storage information
+ * - host will reset the bus if response to request sense is 1
+ * - change the response to 0 if CONFIG_FSL_UTP is defined
+ */
+ status = US_BULK_STAT_OK;
+#else
status = US_BULK_STAT_FAIL;
+#endif
VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
" info x%x\n",
SK(sd), ASC(sd), ASCQ(sd), sdinfo);
@@ -1853,6 +1881,13 @@ static int do_scsi_command(struct fsg_common *common)
common->phase_error = 0;
common->short_packet_received = 0;
+#ifdef CONFIG_FSL_UTP
+ reply = utp_handle_message(common->fsg, common->cmnd, reply);
+
+ if (reply != -EINVAL)
+ return reply;
+#endif
+
down_read(&common->filesem); /* We're using the backing file */
switch (common->cmnd[0]) {
@@ -2517,12 +2552,14 @@ static int fsg_main_thread(void *common_)
/* Allow the thread to be frozen */
set_freezable();
+#ifndef CONFIG_FSL_UTP
/*
* Arrange for userspace references to be interpreted as kernel
* pointers. That way we can pass a kernel pointer to a routine
* that expects a __user pointer and it will work okay.
*/
set_fs(get_ds());
+#endif
/* The main loop */
while (common->state != FSG_STATE_TERMINATED) {
@@ -2988,6 +3025,10 @@ static void fsg_common_release(struct kref *ref)
/*-------------------------------------------------------------------------*/
+#ifdef CONFIG_FSL_UTP
+#include "fsl_updater.c"
+#endif
+
static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
@@ -3039,6 +3080,10 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
fsg_intf_desc.bInterfaceNumber = i;
fsg->interface_number = i;
+#ifdef CONFIG_FSL_UTP
+ utp_init(fsg);
+#endif
+
/* Find all the endpoints we will use */
ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
if (!ep)
@@ -3102,6 +3147,11 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
}
usb_free_all_descriptors(&fsg->function);
+
+#ifdef CONFIG_FSL_UTP
+ utp_exit(fsg);
+#endif
+
}
static inline struct fsg_lun_opts *to_fsg_lun_opts(struct config_item *item)
diff --git a/drivers/usb/gadget/function/fsl_updater.c b/drivers/usb/gadget/function/fsl_updater.c
new file mode 100644
index 000000000000..490300371d9d
--- /dev/null
+++ b/drivers/usb/gadget/function/fsl_updater.c
@@ -0,0 +1,594 @@
+/*
+ * Freescale UUT driver
+ *
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
+ * Copyright 2008-2009 Embedded Alley Solutions, 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
+ */
+
+static u64 get_be64(u8 *buf)
+{
+ return ((u64)get_unaligned_be32(buf) << 32) |
+ get_unaligned_be32(buf + 4);
+}
+
+static int utp_init(struct fsg_dev *fsg)
+{
+ init_waitqueue_head(&utp_context.wq);
+ init_waitqueue_head(&utp_context.list_full_wq);
+
+ INIT_LIST_HEAD(&utp_context.read);
+ INIT_LIST_HEAD(&utp_context.write);
+ mutex_init(&utp_context.lock);
+
+ /* the max message is 64KB */
+ utp_context.buffer = vmalloc(0x10000);
+ if (!utp_context.buffer)
+ return -EIO;
+ utp_context.utp_version = 0x1ull;
+ fsg->utp = &utp_context;
+ return misc_register(&utp_dev);
+}
+
+static void utp_exit(struct fsg_dev *fsg)
+{
+ vfree(utp_context.buffer);
+ misc_deregister(&utp_dev);
+}
+
+static struct utp_user_data *utp_user_data_alloc(size_t size)
+{
+ struct utp_user_data *uud;
+
+ uud = vmalloc(size + sizeof(*uud));
+ if (!uud)
+ return uud;
+ memset(uud, 0, size + sizeof(*uud));
+ uud->data.size = size + sizeof(uud->data);
+ INIT_LIST_HEAD(&uud->link);
+ return uud;
+}
+
+static void utp_user_data_free(struct utp_user_data *uud)
+{
+ mutex_lock(&utp_context.lock);
+ list_del(&uud->link);
+ mutex_unlock(&utp_context.lock);
+ vfree(uud);
+}
+
+/* Get the number of element for list */
+static u32 count_list(struct list_head *l)
+{
+ u32 count = 0;
+ struct list_head *tmp;
+
+ mutex_lock(&utp_context.lock);
+ list_for_each(tmp, l) {
+ count++;
+ }
+ mutex_unlock(&utp_context.lock);
+
+ return count;
+}
+/* The routine will not go on if utp_context.queue is empty */
+#define WAIT_ACTIVITY(queue) \
+ wait_event_interruptible(utp_context.wq, !list_empty(&utp_context.queue))
+
+/* Called by userspace program (uuc) */
+static ssize_t utp_file_read(struct file *file,
+ char __user *buf,
+ size_t size,
+ loff_t *off)
+{
+ struct utp_user_data *uud;
+ size_t size_to_put;
+ int free = 0;
+
+ WAIT_ACTIVITY(read);
+
+ mutex_lock(&utp_context.lock);
+ uud = list_first_entry(&utp_context.read, struct utp_user_data, link);
+ mutex_unlock(&utp_context.lock);
+ size_to_put = uud->data.size;
+
+ if (size >= size_to_put)
+ free = !0;
+ if (copy_to_user(buf, &uud->data, size_to_put)) {
+ printk(KERN_INFO "[ %s ] copy error\n", __func__);
+ return -EACCES;
+ }
+ if (free)
+ utp_user_data_free(uud);
+ else {
+ pr_info("sizeof = %d, size = %d\n",
+ sizeof(uud->data),
+ uud->data.size);
+
+ pr_err("Will not free utp_user_data, because buffer size = %d,"
+ "need to put %d\n", size, size_to_put);
+ }
+
+ /*
+ * The user program has already finished data process,
+ * go on getting data from the host
+ */
+ wake_up(&utp_context.list_full_wq);
+
+ return size_to_put;
+}
+
+static ssize_t utp_file_write(struct file *file, const char __user *buf,
+ size_t size, loff_t *off)
+{
+ struct utp_user_data *uud;
+
+ if (size < sizeof(uud->data))
+ return -EINVAL;
+ uud = utp_user_data_alloc(size);
+ if (uud == NULL)
+ return -ENOMEM;
+ if (copy_from_user(&uud->data, buf, size)) {
+ printk(KERN_INFO "[ %s ] copy error!\n", __func__);
+ vfree(uud);
+ return -EACCES;
+ }
+ mutex_lock(&utp_context.lock);
+ list_add_tail(&uud->link, &utp_context.write);
+ /* Go on EXEC routine process */
+ wake_up(&utp_context.wq);
+ mutex_unlock(&utp_context.lock);
+ return size;
+}
+
+/*
+ * uuc should change to use soc bus infrastructure to soc information
+ * /sys/devices/soc0/soc_id
+ * this function can be removed.
+ */
+static long
+utp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int cpu_id = 0;
+
+ switch (cmd) {
+ case UTP_GET_CPU_ID:
+ return put_user(cpu_id, (int __user *)arg);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/* Will be called when the host wants to get the sense data */
+static int utp_get_sense(struct fsg_dev *fsg)
+{
+ if (UTP_CTX(fsg)->processed == 0)
+ return -1;
+
+ UTP_CTX(fsg)->processed = 0;
+ return 0;
+}
+
+static int utp_do_read(struct fsg_dev *fsg, void *data, size_t size)
+{
+ struct fsg_buffhd *bh;
+ int rc;
+ u32 amount_left;
+ unsigned int amount;
+
+ /* Get the starting Logical Block Address and check that it's
+ * not too big */
+
+ amount_left = size;
+ if (unlikely(amount_left == 0))
+ return -EIO; /* No default reply*/
+
+ pr_debug("%s: sending %d\n", __func__, size);
+ for (;;) {
+ /* Figure out how much we need to read:
+ * Try to read the remaining amount.
+ * But don't read more than the buffer size.
+ * And don't try to read past the end of the file.
+ * Finally, if we're not at a page boundary, don't read past
+ * the next page.
+ * If this means reading 0 then we were asked to read past
+ * the end of file. */
+ amount = min((unsigned int) amount_left, FSG_BUFLEN);
+
+ /* Wait for the next buffer to become available */
+ bh = fsg->common->next_buffhd_to_fill;
+ while (bh->state != BUF_STATE_EMPTY) {
+ rc = sleep_thread(fsg->common, true);
+ if (rc)
+ return rc;
+ }
+
+ /* If we were asked to read past the end of file,
+ * end with an empty buffer. */
+ if (amount == 0) {
+ bh->inreq->length = 0;
+ bh->state = BUF_STATE_FULL;
+ break;
+ }
+
+ /* Perform the read */
+ pr_info("Copied to %p, %d bytes started from %d\n",
+ bh->buf, amount, size - amount_left);
+ /* from upt buffer to file_storeage buffer */
+ memcpy(bh->buf, data + size - amount_left, amount);
+ amount_left -= amount;
+ fsg->common->residue -= amount;
+
+ bh->inreq->length = amount;
+ bh->state = BUF_STATE_FULL;
+
+ /* Send this buffer and go read some more */
+ bh->inreq->zero = 0;
+
+ /* USB Physical transfer: Data from device to host */
+ start_transfer(fsg, fsg->bulk_in, bh->inreq,
+ &bh->inreq_busy, &bh->state);
+
+ fsg->common->next_buffhd_to_fill = bh->next;
+
+ if (amount_left <= 0)
+ break;
+ }
+
+ return size - amount_left;
+}
+
+static int utp_do_write(struct fsg_dev *fsg, void *data, size_t size)
+{
+ struct fsg_buffhd *bh;
+ int get_some_more;
+ u32 amount_left_to_req, amount_left_to_write;
+ unsigned int amount;
+ int rc;
+ loff_t offset;
+
+ /* Carry out the file writes */
+ get_some_more = 1;
+ amount_left_to_req = amount_left_to_write = size;
+
+ if (unlikely(amount_left_to_write == 0))
+ return -EIO;
+
+ offset = 0;
+ while (amount_left_to_write > 0) {
+
+ /* Queue a request for more data from the host */
+ bh = fsg->common->next_buffhd_to_fill;
+ if (bh->state == BUF_STATE_EMPTY && get_some_more) {
+
+ /* Figure out how much we want to get:
+ * Try to get the remaining amount.
+ * But don't get more than the buffer size.
+ * And don't try to go past the end of the file.
+ * If we're not at a page boundary,
+ * don't go past the next page.
+ * If this means getting 0, then we were asked
+ * to write past the end of file.
+ * Finally, round down to a block boundary. */
+ amount = min(amount_left_to_req, FSG_BUFLEN);
+
+ if (amount == 0) {
+ get_some_more = 0;
+ /* cry now */
+ continue;
+ }
+
+ /* Get the next buffer */
+ amount_left_to_req -= amount;
+ if (amount_left_to_req == 0)
+ get_some_more = 0;
+
+ /* amount is always divisible by 512, hence by
+ * the bulk-out maxpacket size */
+ bh->outreq->length = bh->bulk_out_intended_length =
+ amount;
+ bh->outreq->short_not_ok = 1;
+ start_transfer(fsg, fsg->bulk_out, bh->outreq,
+ &bh->outreq_busy, &bh->state);
+ fsg->common->next_buffhd_to_fill = bh->next;
+ continue;
+ }
+
+ /* Write the received data to the backing file */
+ bh = fsg->common->next_buffhd_to_drain;
+ if (bh->state == BUF_STATE_EMPTY && !get_some_more)
+ break; /* We stopped early */
+ if (bh->state == BUF_STATE_FULL) {
+ smp_rmb();
+ fsg->common->next_buffhd_to_drain = bh->next;
+ bh->state = BUF_STATE_EMPTY;
+
+ /* Did something go wrong with the transfer? */
+ if (bh->outreq->status != 0)
+ /* cry again, COMMUNICATION_FAILURE */
+ break;
+
+ amount = bh->outreq->actual;
+
+ /* Perform the write */
+ memcpy(data + offset, bh->buf, amount);
+
+ offset += amount;
+ if (signal_pending(current))
+ return -EINTR; /* Interrupted!*/
+ amount_left_to_write -= amount;
+ fsg->common->residue -= amount;
+
+ /* Did the host decide to stop early? */
+ if (bh->outreq->actual != bh->outreq->length) {
+ fsg->common->short_packet_received = 1;
+ break;
+ }
+ continue;
+ }
+
+ /* Wait for something to happen */
+ rc = sleep_thread(fsg->common, true);
+ if (rc)
+ return rc;
+ }
+
+ return -EIO;
+}
+
+static inline void utp_set_sense(struct fsg_dev *fsg, u16 code, u64 reply)
+{
+ UTP_CTX(fsg)->processed = true;
+ UTP_CTX(fsg)->sdinfo = reply & 0xFFFFFFFF;
+ UTP_CTX(fsg)->sdinfo_h = (reply >> 32) & 0xFFFFFFFF;
+ UTP_CTX(fsg)->sd = (UTP_SENSE_KEY << 16) | code;
+}
+
+static void utp_poll(struct fsg_dev *fsg)
+{
+ struct utp_context *ctx = UTP_CTX(fsg);
+ struct utp_user_data *uud = NULL;
+
+ mutex_lock(&ctx->lock);
+ if (!list_empty(&ctx->write))
+ uud = list_first_entry(&ctx->write, struct utp_user_data, link);
+ mutex_unlock(&ctx->lock);
+
+ if (uud) {
+ if (uud->data.flags & UTP_FLAG_STATUS) {
+ printk(KERN_WARNING "%s: exit with status %d\n",
+ __func__, uud->data.status);
+ UTP_SS_EXIT(fsg, uud->data.status);
+ } else if (uud->data.flags & UTP_FLAG_REPORT_BUSY) {
+ UTP_SS_BUSY(fsg, --ctx->counter);
+ } else {
+ printk("%s: pass returned.\n", __func__);
+ UTP_SS_PASS(fsg);
+ }
+ utp_user_data_free(uud);
+ } else {
+ if (utp_context.cur_state & UTP_FLAG_DATA) {
+ if (count_list(&ctx->read) < 7) {
+ pr_debug("%s: pass returned in POLL stage. \n", __func__);
+ UTP_SS_PASS(fsg);
+ utp_context.cur_state = 0;
+ return;
+ }
+ }
+ UTP_SS_BUSY(fsg, --ctx->counter);
+ }
+}
+
+static int utp_exec(struct fsg_dev *fsg,
+ char *command,
+ int cmdsize,
+ unsigned long long payload)
+{
+ struct utp_user_data *uud = NULL, *uud2r;
+ struct utp_context *ctx = UTP_CTX(fsg);
+
+ ctx->counter = 0xFFFF;
+ uud2r = utp_user_data_alloc(cmdsize + 1);
+ if (!uud2r)
+ return -ENOMEM;
+ uud2r->data.flags = UTP_FLAG_COMMAND;
+ uud2r->data.payload = payload;
+ strncpy(uud2r->data.command, command, cmdsize);
+
+ mutex_lock(&ctx->lock);
+ list_add_tail(&uud2r->link, &ctx->read);
+ mutex_unlock(&ctx->lock);
+ /* wake up the read routine */
+ wake_up(&ctx->wq);
+
+ if (command[0] == '!') /* there will be no response */
+ return 0;
+
+ /*
+ * the user program (uuc) will return utp_message
+ * and add list to write list
+ */
+ WAIT_ACTIVITY(write);
+
+ mutex_lock(&ctx->lock);
+ if (!list_empty(&ctx->write)) {
+ uud = list_first_entry(&ctx->write, struct utp_user_data, link);
+#ifdef DEBUG
+ pr_info("UUD:\n\tFlags = %02X\n", uud->data.flags);
+ if (uud->data.flags & UTP_FLAG_DATA) {
+ pr_info("\tbufsize = %d\n", uud->data.bufsize);
+ print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_NONE,
+ 16, 2, uud->data.data, uud->data.bufsize, true);
+ }
+ if (uud->data.flags & UTP_FLAG_REPORT_BUSY)
+ pr_info("\tBUSY\n");
+#endif
+ }
+ mutex_unlock(&ctx->lock);
+
+ if (uud->data.flags & UTP_FLAG_DATA) {
+ memcpy(ctx->buffer, uud->data.data, uud->data.bufsize);
+ UTP_SS_SIZE(fsg, uud->data.bufsize);
+ } else if (uud->data.flags & UTP_FLAG_REPORT_BUSY) {
+ UTP_SS_BUSY(fsg, ctx->counter);
+ } else if (uud->data.flags & UTP_FLAG_STATUS) {
+ printk(KERN_WARNING "%s: exit with status %d\n", __func__,
+ uud->data.status);
+ UTP_SS_EXIT(fsg, uud->data.status);
+ } else {
+ pr_debug("%s: pass returned in EXEC stage. \n", __func__);
+ UTP_SS_PASS(fsg);
+ }
+ utp_user_data_free(uud);
+ return 0;
+}
+
+static int utp_send_status(struct fsg_dev *fsg)
+{
+ struct fsg_buffhd *bh;
+ u8 status = US_BULK_STAT_OK;
+ struct bulk_cs_wrap *csw;
+ int rc;
+
+ /* Wait for the next buffer to become available */
+ bh = fsg->common->next_buffhd_to_fill;
+ while (bh->state != BUF_STATE_EMPTY) {
+ rc = sleep_thread(fsg->common, true);
+ if (rc)
+ return rc;
+ }
+
+ if (fsg->common->phase_error) {
+ DBG(fsg, "sending phase-error status\n");
+ status = US_BULK_STAT_PHASE;
+
+ } else if ((UTP_CTX(fsg)->sd & 0xFFFF) != UTP_REPLY_PASS) {
+ status = US_BULK_STAT_FAIL;
+ }
+
+ csw = bh->buf;
+
+ /* Store and send the Bulk-only CSW */
+ csw->Signature = __constant_cpu_to_le32(US_BULK_CS_SIGN);
+ csw->Tag = fsg->common->tag;
+ csw->Residue = cpu_to_le32(fsg->common->residue);
+ csw->Status = status;
+
+ bh->inreq->length = US_BULK_CS_WRAP_LEN;
+ bh->inreq->zero = 0;
+ start_transfer(fsg, fsg->bulk_in, bh->inreq,
+ &bh->inreq_busy, &bh->state);
+ fsg->common->next_buffhd_to_fill = bh->next;
+ return 0;
+}
+
+static int utp_handle_message(struct fsg_dev *fsg,
+ char *cdb_data,
+ int default_reply)
+{
+ struct utp_msg *m = (struct utp_msg *)cdb_data;
+ void *data = NULL;
+ int r;
+ struct utp_user_data *uud2r;
+ unsigned long long param;
+ unsigned long tag;
+
+ if (m->f0 != 0xF0)
+ return default_reply;
+
+ tag = get_unaligned_be32((void *)&m->utp_msg_tag);
+ param = get_be64((void *)&m->param);
+ pr_debug("Type 0x%x, tag 0x%08lx, param %llx\n",
+ m->utp_msg_type, tag, param);
+
+ switch ((enum utp_msg_type)m->utp_msg_type) {
+
+ case UTP_POLL:
+ if (get_be64((void *)&m->param) == 1) {
+ pr_debug("%s: version request\n", __func__);
+ UTP_SS_EXIT(fsg, UTP_CTX(fsg)->utp_version);
+ break;
+ }
+ utp_poll(fsg);
+ break;
+ case UTP_EXEC:
+ pr_debug("%s: EXEC\n", __func__);
+ data = vmalloc(fsg->common->data_size);
+ memset(data, 0, fsg->common->data_size);
+ /* copy data from usb buffer to utp buffer */
+ utp_do_write(fsg, data, fsg->common->data_size);
+ utp_exec(fsg, data, fsg->common->data_size, param);
+ vfree(data);
+ break;
+ case UTP_GET: /* data from device to host */
+ pr_debug("%s: GET, %d bytes\n", __func__,
+ fsg->common->data_size);
+ r = utp_do_read(fsg, UTP_CTX(fsg)->buffer,
+ fsg->common->data_size);
+ UTP_SS_PASS(fsg);
+ break;
+ case UTP_PUT:
+ utp_context.cur_state = UTP_FLAG_DATA;
+ pr_debug("%s: PUT, Received %d bytes\n", __func__, fsg->common->data_size);/* data from host to device */
+ uud2r = utp_user_data_alloc(fsg->common->data_size);
+ if (!uud2r)
+ return -ENOMEM;
+ uud2r->data.bufsize = fsg->common->data_size;
+ uud2r->data.flags = UTP_FLAG_DATA;
+ utp_do_write(fsg, uud2r->data.data, fsg->common->data_size);
+ /* don't know what will be written */
+ mutex_lock(&UTP_CTX(fsg)->lock);
+ list_add_tail(&uud2r->link, &UTP_CTX(fsg)->read);
+ mutex_unlock(&UTP_CTX(fsg)->lock);
+ wake_up(&UTP_CTX(fsg)->wq);
+ /*
+ * Return PASS or FAIL according to uuc's status
+ * Please open it if need to check uuc's status
+ * and use another version uuc
+ */
+#if 0
+ struct utp_user_data *uud = NULL;
+ struct utp_context *ctx;
+ WAIT_ACTIVITY(write);
+ ctx = UTP_CTX(fsg);
+ mutex_lock(&ctx->lock);
+
+ if (!list_empty(&ctx->write))
+ uud = list_first_entry(&ctx->write,
+ struct utp_user_data, link);
+
+ mutex_unlock(&ctx->lock);
+ if (uud) {
+ if (uud->data.flags & UTP_FLAG_STATUS) {
+ printk(KERN_WARNING "%s: exit with status %d\n",
+ __func__, uud->data.status);
+ UTP_SS_EXIT(fsg, uud->data.status);
+ } else {
+ pr_debug("%s: pass\n", __func__);
+ UTP_SS_PASS(fsg);
+ }
+ utp_user_data_free(uud);
+ } else{
+ UTP_SS_PASS(fsg);
+ }
+#endif
+ if (count_list(&UTP_CTX(fsg)->read) < 7) {
+ utp_context.cur_state = 0;
+ UTP_SS_PASS(fsg);
+ } else
+ UTP_SS_BUSY(fsg, UTP_CTX(fsg)->counter);
+
+ break;
+ }
+
+ utp_send_status(fsg);
+ return -1;
+}
diff --git a/drivers/usb/gadget/function/fsl_updater.h b/drivers/usb/gadget/function/fsl_updater.h
new file mode 100644
index 000000000000..15ebc09bfd2f
--- /dev/null
+++ b/drivers/usb/gadget/function/fsl_updater.h
@@ -0,0 +1,150 @@
+/*
+ * Freescale UUT driver
+ *
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
+ * Copyright 2008-2009 Embedded Alley Solutions, 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
+ */
+
+#ifndef __FSL_UPDATER_H
+#define __FSL_UPDATER_H
+
+#include <linux/miscdevice.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/ioctl.h>
+/* #include <mach/hardware.h> */
+
+static int utp_init(struct fsg_dev *fsg);
+static void utp_exit(struct fsg_dev *fsg);
+static ssize_t utp_file_read(struct file *file,
+ char __user *buf,
+ size_t size,
+ loff_t *off);
+
+static ssize_t utp_file_write(struct file *file,
+ const char __user *buf,
+ size_t size,
+ loff_t *off);
+
+static long utp_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg);
+static struct utp_user_data *utp_user_data_alloc(size_t size);
+static void utp_user_data_free(struct utp_user_data *uud);
+static int utp_get_sense(struct fsg_dev *fsg);
+static int utp_do_read(struct fsg_dev *fsg, void *data, size_t size);
+static int utp_do_write(struct fsg_dev *fsg, void *data, size_t size);
+static inline void utp_set_sense(struct fsg_dev *fsg, u16 code, u64 reply);
+static int utp_handle_message(struct fsg_dev *fsg,
+ char *cdb_data,
+ int default_reply);
+
+#define UTP_REPLY_PASS 0
+#define UTP_REPLY_EXIT 0x8001
+#define UTP_REPLY_BUSY 0x8002
+#define UTP_REPLY_SIZE 0x8003
+#define UTP_SENSE_KEY 9
+
+#define UTP_MINOR 222
+/* MISC_DYNAMIC_MINOR would be better, but... */
+
+#define UTP_COMMAND_SIZE 80
+
+#define UTP_SS_EXIT(fsg, r) utp_set_sense(fsg, UTP_REPLY_EXIT, (u64)r)
+#define UTP_SS_PASS(fsg) utp_set_sense(fsg, UTP_REPLY_PASS, 0)
+#define UTP_SS_BUSY(fsg, r) utp_set_sense(fsg, UTP_REPLY_BUSY, (u64)r)
+#define UTP_SS_SIZE(fsg, r) utp_set_sense(fsg, UTP_REPLY_SIZE, (u64)r)
+
+#define UTP_IOCTL_BASE 'U'
+#define UTP_GET_CPU_ID _IOR(UTP_IOCTL_BASE, 0, int)
+/* the structure of utp message which is mapped to 16-byte SCSI CBW's CDB */
+#pragma pack(1)
+struct utp_msg {
+ u8 f0;
+ u8 utp_msg_type;
+ u32 utp_msg_tag;
+ union {
+ struct {
+ u32 param_lsb;
+ u32 param_msb;
+ };
+ u64 param;
+ };
+};
+
+enum utp_msg_type {
+ UTP_POLL = 0,
+ UTP_EXEC,
+ UTP_GET,
+ UTP_PUT,
+};
+
+static struct utp_context {
+ wait_queue_head_t wq;
+ wait_queue_head_t list_full_wq;
+ struct mutex lock;
+ struct list_head read;
+ struct list_head write;
+ u32 sd, sdinfo, sdinfo_h; /* sense data */
+ int processed;
+ u8 *buffer;
+ u32 counter;
+ u64 utp_version;
+ u32 cur_state;
+} utp_context;
+
+static const struct file_operations utp_fops = {
+ .open = nonseekable_open,
+ .read = utp_file_read,
+ .write = utp_file_write,
+ /* .ioctl = utp_ioctl, */
+ .unlocked_ioctl = utp_ioctl,
+};
+
+static struct miscdevice utp_dev = {
+ .minor = UTP_MINOR,
+ .name = "utp",
+ .fops = &utp_fops,
+};
+
+#define UTP_FLAG_COMMAND 0x00000001
+#define UTP_FLAG_DATA 0x00000002
+#define UTP_FLAG_STATUS 0x00000004
+#define UTP_FLAG_REPORT_BUSY 0x10000000
+struct utp_message {
+ u32 flags;
+ size_t size;
+ union {
+ struct {
+ u64 payload;
+ char command[1];
+ };
+ struct {
+ size_t bufsize;
+ u8 data[1];
+ };
+ u32 status;
+ };
+};
+
+struct utp_user_data {
+ struct list_head link;
+ struct utp_message data;
+};
+#pragma pack()
+
+static inline struct utp_context *UTP_CTX(struct fsg_dev *fsg)
+{
+ return (struct utp_context *)fsg->utp;
+}
+
+#endif /* __FSL_UPDATER_H */
+
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
index 0b36878eb5fd..28198f60f6d1 100644
--- a/drivers/usb/gadget/legacy/Kconfig
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -245,6 +245,12 @@ config USB_MASS_STORAGE
Say "y" to link the driver statically, or "m" to build
a dynamically linked module called "g_mass_storage".
+config FSL_UTP
+ bool "UTP over Storage Gadget"
+ depends on USB_MASS_STORAGE
+ help
+ Freescale's extension to MSC protocol
+
config USB_GADGET_TARGET
tristate "USB Gadget Target Fabric Module"
depends on TARGET_CORE
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 063064801ceb..a36fdedfe889 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -93,7 +93,7 @@ module_param (log2_irq_thresh, int, S_IRUGO);
MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
/* initial park setting: slower than hw default */
-static unsigned park = 0;
+static unsigned park = 3;
module_param (park, uint, S_IRUGO);
MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 74f62d68f013..6a96628374a3 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -935,7 +935,7 @@ int ehci_hub_control(
break;
#ifdef CONFIG_USB_OTG
if ((hcd->self.otg_port == (wIndex + 1))
- && hcd->self.b_hnp_enable) {
+ && hcd->self.b_hnp_enable && !hcd->self.otg_fsm) {
otg_start_hnp(hcd->usb_phy->otg);
break;
}
diff --git a/drivers/usb/misc/ehset.c b/drivers/usb/misc/ehset.c
index c31b4a33e6bb..f54473cd25b3 100644
--- a/drivers/usb/misc/ehset.c
+++ b/drivers/usb/misc/ehset.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/ch11.h>
+#include <linux/usb/otg-fsm.h>
#define TEST_SE0_NAK_PID 0x0101
#define TEST_J_PID 0x0102
@@ -25,6 +26,7 @@
#define TEST_HS_HOST_PORT_SUSPEND_RESUME 0x0106
#define TEST_SINGLE_STEP_GET_DEV_DESC 0x0107
#define TEST_SINGLE_STEP_SET_FEATURE 0x0108
+#define TEST_OTG_TEST_DEVICE_SUPPORT 0x0200
static int ehset_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -35,6 +37,7 @@ static int ehset_probe(struct usb_interface *intf,
struct usb_device_descriptor *buf;
u8 portnum = dev->portnum;
u16 test_pid = le16_to_cpu(dev->descriptor.idProduct);
+ struct otg_fsm *fsm = dev->bus->otg_fsm;
switch (test_pid) {
case TEST_SE0_NAK_PID:
@@ -115,6 +118,27 @@ static int ehset_probe(struct usb_interface *intf,
NULL, 0, 60 * 1000);
break;
+ case TEST_OTG_TEST_DEVICE_SUPPORT:
+ if (!fsm)
+ return ret;
+
+ /* B host enumerate test device */
+ if (dev->bus->is_b_host) {
+ otg_add_timer(fsm, B_TST_SUSP);
+ ret = 0;
+ break;
+ }
+
+ mutex_lock(&fsm->lock);
+ fsm->tst_maint = 1;
+ if (le16_to_cpu(dev->descriptor.bcdDevice) & 0x1)
+ fsm->otg_vbus_off = 1;
+ else
+ fsm->otg_vbus_off = 0;
+ mutex_unlock(&fsm->lock);
+ otg_add_timer(fsm, A_TST_MAINT);
+ ret = 0;
+ break;
default:
dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n",
__func__, test_pid);
@@ -135,6 +159,7 @@ static const struct usb_device_id ehset_id_table[] = {
{ USB_DEVICE(0x1a0a, TEST_HS_HOST_PORT_SUSPEND_RESUME) },
{ USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_GET_DEV_DESC) },
{ USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_SET_FEATURE) },
+ { USB_DEVICE(0x1a0a, TEST_OTG_TEST_DEVICE_SUPPORT) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, ehset_id_table);
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index 8311ba2968cd..cdc6f862dcdb 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -59,6 +59,16 @@ EXPORT_SYMBOL_GPL(usb_phy_generic_unregister);
static int nop_set_suspend(struct usb_phy *x, int suspend)
{
+ struct usb_phy_generic *nop = dev_get_drvdata(x->dev);
+
+ if (IS_ERR(nop->clk))
+ return 0;
+
+ if (suspend)
+ clk_disable_unprepare(nop->clk);
+ else
+ clk_prepare_enable(nop->clk);
+
return 0;
}
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 0e2f1a36d315..92b94341b1b4 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2012-2014 Freescale Semiconductor, Inc.
+ * Copyright 2012-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
* Copyright (C) 2012 Marek Vasut <marex@denx.de>
* on behalf of DENX Software Engineering GmbH
*
@@ -23,9 +24,11 @@
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
+#include <linux/regulator/consumer.h>
#define DRIVER_NAME "mxs_phy"
+/* Register Macro */
#define HW_USBPHY_PWD 0x00
#define HW_USBPHY_TX 0x10
#define HW_USBPHY_CTRL 0x30
@@ -43,6 +46,11 @@
#define GM_USBPHY_TX_TXCAL45DN(x) (((x) & 0xf) << 8)
#define GM_USBPHY_TX_D_CAL(x) (((x) & 0xf) << 0)
+/* imx7ulp */
+#define HW_USBPHY_PLL_SIC 0xa4
+#define HW_USBPHY_PLL_SIC_SET 0xa4
+#define HW_USBPHY_PLL_SIC_CLR 0xa8
+
#define BM_USBPHY_CTRL_SFTRST BIT(31)
#define BM_USBPHY_CTRL_CLKGATE BIT(30)
#define BM_USBPHY_CTRL_OTG_ID_VALUE BIT(27)
@@ -61,8 +69,20 @@
#define BM_USBPHY_IP_FIX (BIT(17) | BIT(18))
#define BM_USBPHY_DEBUG_CLKGATE BIT(30)
+/* imx7ulp */
+#define BM_USBPHY_PLL_LOCK BIT(31)
+#define BM_USBPHY_PLL_REG_ENABLE BIT(21)
+#define BM_USBPHY_PLL_BYPASS BIT(16)
+#define BM_USBPHY_PLL_POWER BIT(12)
+#define BM_USBPHY_PLL_EN_USB_CLKS BIT(6)
/* Anatop Registers */
+#define ANADIG_PLL_USB2 0x20
+#define ANADIG_PLL_USB2_SET 0x24
+#define ANADIG_PLL_USB2_CLR 0x28
+#define ANADIG_REG_1P1_SET 0x114
+#define ANADIG_REG_1P1_CLR 0x118
+
#define ANADIG_ANA_MISC0 0x150
#define ANADIG_ANA_MISC0_SET 0x154
#define ANADIG_ANA_MISC0_CLR 0x158
@@ -94,6 +114,11 @@
#define BM_ANADIG_USB2_MISC_RX_VPIN_FS BIT(29)
#define BM_ANADIG_USB2_MISC_RX_VMIN_FS BIT(28)
+#define BM_ANADIG_REG_1P1_ENABLE_WEAK_LINREG BIT(18)
+#define BM_ANADIG_REG_1P1_TRACK_VDD_SOC_CAP BIT(19)
+
+#define BM_ANADIG_PLL_USB2_HOLD_RING_OFF BIT(11)
+
#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
/* Do disconnection between PHY and controller without vbus */
@@ -126,6 +151,16 @@
#define MXS_PHY_TX_D_CAL_MIN 79
#define MXS_PHY_TX_D_CAL_MAX 119
+/*
+ * At some versions, the PHY2's clock is controlled by hardware directly,
+ * eg, according to PHY's suspend status. In these PHYs, we only need to
+ * open the clock at the initialization and close it at its shutdown routine.
+ * It will be benefit for remote wakeup case which needs to send resume
+ * signal as soon as possible, and in this case, the resume signal can be sent
+ * out without software interfere.
+ */
+#define MXS_PHY_HARDWARE_CONTROL_PHY2_CLK BIT(4)
+
struct mxs_phy_data {
unsigned int flags;
};
@@ -137,12 +172,14 @@ static const struct mxs_phy_data imx23_phy_data = {
static const struct mxs_phy_data imx6q_phy_data = {
.flags = MXS_PHY_SENDING_SOF_TOO_FAST |
MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
- MXS_PHY_NEED_IP_FIX,
+ MXS_PHY_NEED_IP_FIX |
+ MXS_PHY_HARDWARE_CONTROL_PHY2_CLK,
};
static const struct mxs_phy_data imx6sl_phy_data = {
.flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
- MXS_PHY_NEED_IP_FIX,
+ MXS_PHY_NEED_IP_FIX |
+ MXS_PHY_HARDWARE_CONTROL_PHY2_CLK,
};
static const struct mxs_phy_data vf610_phy_data = {
@@ -151,14 +188,21 @@ static const struct mxs_phy_data vf610_phy_data = {
};
static const struct mxs_phy_data imx6sx_phy_data = {
- .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
+ .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
+ MXS_PHY_HARDWARE_CONTROL_PHY2_CLK,
};
static const struct mxs_phy_data imx6ul_phy_data = {
- .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
+ .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
+ MXS_PHY_HARDWARE_CONTROL_PHY2_CLK,
+};
+
+static const struct mxs_phy_data imx7ulp_phy_data = {
};
static const struct of_device_id mxs_phy_dt_ids[] = {
+ { .compatible = "fsl,imx7ulp-usbphy", .data = &imx7ulp_phy_data, },
+ { .compatible = "fsl,imx6ul-usbphy", .data = &imx6sx_phy_data, },
{ .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
{ .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
{ .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
@@ -177,6 +221,9 @@ struct mxs_phy {
int port_id;
u32 tx_reg_set;
u32 tx_reg_mask;
+ struct regulator *phy_3p0;
+ bool hardware_control_phy2_clk;
+ enum usb_current_mode mode;
};
static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
@@ -189,6 +236,16 @@ static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
return mxs_phy->data == &imx6sl_phy_data;
}
+static inline bool is_imx6ul_phy(struct mxs_phy *mxs_phy)
+{
+ return mxs_phy->data == &imx6ul_phy_data;
+}
+
+static inline bool is_imx7ulp_phy(struct mxs_phy *mxs_phy)
+{
+ return mxs_phy->data == &imx7ulp_phy_data;
+}
+
/*
* PHY needs some 32K cycles to switch from 32K clock to
* bus (such as AHB/AXI, etc) clock.
@@ -212,14 +269,69 @@ static void mxs_phy_tx_init(struct mxs_phy *mxs_phy)
}
}
+static int wait_for_pll_lock(const void __iomem *base)
+{
+ int loop_count = 100;
+
+ /* Wait for PLL to lock */
+ do {
+ if (readl(base + HW_USBPHY_PLL_SIC) & BM_USBPHY_PLL_LOCK)
+ break;
+ usleep_range(100, 150);
+ } while (loop_count-- > 0);
+
+ return readl(base + HW_USBPHY_PLL_SIC) & BM_USBPHY_PLL_LOCK
+ ? 0 : -ETIMEDOUT;
+}
+
+static int mxs_phy_pll_enable(void __iomem *base, bool enable)
+{
+ int ret = 0;
+
+ if (enable) {
+ writel(BM_USBPHY_PLL_REG_ENABLE, base + HW_USBPHY_PLL_SIC_SET);
+ writel(BM_USBPHY_PLL_BYPASS, base + HW_USBPHY_PLL_SIC_CLR);
+ writel(BM_USBPHY_PLL_POWER, base + HW_USBPHY_PLL_SIC_SET);
+ ret = wait_for_pll_lock(base);
+ if (ret)
+ return ret;
+ writel(BM_USBPHY_PLL_EN_USB_CLKS, base +
+ HW_USBPHY_PLL_SIC_SET);
+ } else {
+ writel(BM_USBPHY_PLL_EN_USB_CLKS, base +
+ HW_USBPHY_PLL_SIC_CLR);
+ writel(BM_USBPHY_PLL_POWER, base + HW_USBPHY_PLL_SIC_CLR);
+ writel(BM_USBPHY_PLL_BYPASS, base + HW_USBPHY_PLL_SIC_SET);
+ writel(BM_USBPHY_PLL_REG_ENABLE, base + HW_USBPHY_PLL_SIC_CLR);
+ }
+
+ return ret;
+}
+
static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
{
int ret;
void __iomem *base = mxs_phy->phy.io_priv;
+ if (is_imx7ulp_phy(mxs_phy)) {
+ ret = mxs_phy_pll_enable(base, true);
+ if (ret)
+ return ret;
+ }
+
ret = stmp_reset_block(base + HW_USBPHY_CTRL);
if (ret)
- return ret;
+ goto disable_pll;
+
+ if (mxs_phy->phy_3p0) {
+ ret = regulator_enable(mxs_phy->phy_3p0);
+ if (ret) {
+ dev_err(mxs_phy->phy.dev,
+ "Failed to enable 3p0 regulator, ret=%d\n",
+ ret);
+ goto disable_pll;
+ }
+ }
/* Power up the PHY */
writel(0, base + HW_USBPHY_PWD);
@@ -244,6 +356,11 @@ static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
mxs_phy_tx_init(mxs_phy);
return 0;
+
+disable_pll:
+ if (is_imx7ulp_phy(mxs_phy))
+ mxs_phy_pll_enable(base, false);
+ return ret;
}
/* Return true if the vbus is there */
@@ -301,21 +418,10 @@ static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
usleep_range(500, 1000);
}
-static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy)
-{
- void __iomem *base = mxs_phy->phy.io_priv;
- u32 phyctrl = readl(base + HW_USBPHY_CTRL);
-
- if (IS_ENABLED(CONFIG_USB_OTG) &&
- !(phyctrl & BM_USBPHY_CTRL_OTG_ID_VALUE))
- return true;
-
- return false;
-}
-
static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
{
bool vbus_is_on = false;
+ enum usb_phy_events last_event = mxs_phy->phy.last_event;
/* If the SoCs don't need to disconnect line without vbus, quit */
if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS))
@@ -327,7 +433,8 @@ static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
- if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy))
+ if (on && ((!vbus_is_on && mxs_phy->mode != USB_MODE_HOST) ||
+ (last_event == USB_EVENT_VBUS)))
__mxs_phy_disconnect_line(mxs_phy, true);
else
__mxs_phy_disconnect_line(mxs_phy, false);
@@ -365,6 +472,9 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
writel(BM_USBPHY_CTRL_CLKGATE,
phy->io_priv + HW_USBPHY_CTRL_SET);
+ if (mxs_phy->phy_3p0)
+ regulator_disable(mxs_phy->phy_3p0);
+
clk_disable_unprepare(mxs_phy->clk);
}
@@ -418,14 +528,49 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend)
} else {
writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
}
+
+ /*
+ * USB2 PLL use ring VCO, when the PLL power up, the ring
+ * VCO’s supply also ramp up. There is a possibility that
+ * the ring VCO start oscillation at multi nodes in this
+ * phase, especially for VCO which has many stages, then
+ * the multiwave will be kept until PLL power down. the bit
+ * hold_ring_off can force the VCO in one determined state
+ * to avoid the multiwave issue when VCO supply start ramp
+ * up.
+ */
+ if (mxs_phy->port_id == 1 && mxs_phy->regmap_anatop)
+ regmap_write(mxs_phy->regmap_anatop,
+ ANADIG_PLL_USB2_SET,
+ BM_ANADIG_PLL_USB2_HOLD_RING_OFF);
+
writel(BM_USBPHY_CTRL_CLKGATE,
x->io_priv + HW_USBPHY_CTRL_SET);
- clk_disable_unprepare(mxs_phy->clk);
+ if (!(mxs_phy->port_id == 1 &&
+ mxs_phy->hardware_control_phy2_clk))
+ clk_disable_unprepare(mxs_phy->clk);
} else {
mxs_phy_clock_switch_delay();
- ret = clk_prepare_enable(mxs_phy->clk);
- if (ret)
- return ret;
+ if (!(mxs_phy->port_id == 1 &&
+ mxs_phy->hardware_control_phy2_clk)) {
+ ret = clk_prepare_enable(mxs_phy->clk);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Per IC design's requirement, hold_ring_off bit can be
+ * cleared 25us after PLL power up and 25us before any USB
+ * TX/RX.
+ */
+ if (mxs_phy->port_id == 1 && mxs_phy->regmap_anatop) {
+ udelay(25);
+ regmap_write(mxs_phy->regmap_anatop,
+ ANADIG_PLL_USB2_CLR,
+ BM_ANADIG_PLL_USB2_HOLD_RING_OFF);
+ udelay(25);
+ }
+
writel(BM_USBPHY_CTRL_CLKGATE,
x->io_priv + HW_USBPHY_CTRL_CLR);
writel(0, x->io_priv + HW_USBPHY_PWD);
@@ -479,6 +624,61 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy,
return 0;
}
+static int mxs_phy_on_suspend(struct usb_phy *phy,
+ enum usb_device_speed speed)
+{
+ struct mxs_phy *mxs_phy = to_mxs_phy(phy);
+
+ dev_dbg(phy->dev, "%s device has suspended\n",
+ (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
+
+ /* delay 4ms to wait bus entering idle */
+ usleep_range(4000, 5000);
+
+ if (mxs_phy->data->flags & MXS_PHY_ABNORMAL_IN_SUSPEND) {
+ writel_relaxed(0xffffffff, phy->io_priv + HW_USBPHY_PWD);
+ writel_relaxed(0, phy->io_priv + HW_USBPHY_PWD);
+ }
+
+ if (speed == USB_SPEED_HIGH)
+ writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ phy->io_priv + HW_USBPHY_CTRL_CLR);
+
+ return 0;
+}
+
+/*
+ * The resume signal must be finished here.
+ */
+static int mxs_phy_on_resume(struct usb_phy *phy,
+ enum usb_device_speed speed)
+{
+ dev_dbg(phy->dev, "%s device has resumed\n",
+ (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
+
+ if (speed == USB_SPEED_HIGH) {
+ /* Make sure the device has switched to High-Speed mode */
+ udelay(500);
+ writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ phy->io_priv + HW_USBPHY_CTRL_SET);
+ }
+
+ return 0;
+}
+
+/*
+ * Set the usb current role for phy.
+ */
+static int mxs_phy_set_mode(struct usb_phy *phy,
+ enum usb_current_mode mode)
+{
+ struct mxs_phy *mxs_phy = to_mxs_phy(phy);
+
+ mxs_phy->mode = mode;
+
+ return 0;
+}
+
static int mxs_phy_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -556,6 +756,8 @@ static int mxs_phy_probe(struct platform_device *pdev)
if (ret < 0)
dev_dbg(&pdev->dev, "failed to get alias id, errno %d\n", ret);
mxs_phy->port_id = ret;
+ mxs_phy->clk = clk;
+ mxs_phy->data = of_id->data;
mxs_phy->phy.io_priv = base;
mxs_phy->phy.dev = &pdev->dev;
@@ -567,9 +769,28 @@ static int mxs_phy_probe(struct platform_device *pdev)
mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect;
mxs_phy->phy.type = USB_PHY_TYPE_USB2;
mxs_phy->phy.set_wakeup = mxs_phy_set_wakeup;
+ mxs_phy->phy.set_mode = mxs_phy_set_mode;
+ if (mxs_phy->data->flags & MXS_PHY_SENDING_SOF_TOO_FAST) {
+ mxs_phy->phy.notify_suspend = mxs_phy_on_suspend;
+ mxs_phy->phy.notify_resume = mxs_phy_on_resume;
+ }
- mxs_phy->clk = clk;
- mxs_phy->data = of_id->data;
+ mxs_phy->phy_3p0 = devm_regulator_get(&pdev->dev, "phy-3p0");
+ if (PTR_ERR(mxs_phy->phy_3p0) == -EPROBE_DEFER) {
+ return -EPROBE_DEFER;
+ } else if (PTR_ERR(mxs_phy->phy_3p0) == -ENODEV) {
+ /* not exist */
+ mxs_phy->phy_3p0 = NULL;
+ } else if (IS_ERR(mxs_phy->phy_3p0)) {
+ dev_err(&pdev->dev, "Getting regulator error: %ld\n",
+ PTR_ERR(mxs_phy->phy_3p0));
+ return PTR_ERR(mxs_phy->phy_3p0);
+ }
+ if (mxs_phy->phy_3p0)
+ regulator_set_voltage(mxs_phy->phy_3p0, 3200000, 3200000);
+
+ if (mxs_phy->data->flags & MXS_PHY_HARDWARE_CONTROL_PHY2_CLK)
+ mxs_phy->hardware_control_phy2_clk = true;
platform_set_drvdata(pdev, mxs_phy);
@@ -590,18 +811,30 @@ static int mxs_phy_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
{
- unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
+ unsigned int reg;
+ u32 value;
/* If the SoCs don't have anatop, quit */
if (!mxs_phy->regmap_anatop)
return;
- if (is_imx6q_phy(mxs_phy))
+ if (is_imx6q_phy(mxs_phy)) {
+ reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
regmap_write(mxs_phy->regmap_anatop, reg,
BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
- else if (is_imx6sl_phy(mxs_phy))
+ } else if (is_imx6sl_phy(mxs_phy)) {
+ reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
regmap_write(mxs_phy->regmap_anatop,
reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
+ } else if (is_imx6ul_phy(mxs_phy)) {
+ reg = on ? ANADIG_REG_1P1_SET : ANADIG_REG_1P1_CLR;
+ value = BM_ANADIG_REG_1P1_ENABLE_WEAK_LINREG |
+ BM_ANADIG_REG_1P1_TRACK_VDD_SOC_CAP;
+ if (mxs_phy_get_vbus_status(mxs_phy) && on)
+ regmap_write(mxs_phy->regmap_anatop, reg, value);
+ else if (!on)
+ regmap_write(mxs_phy->regmap_anatop, reg, value);
+ }
}
static int mxs_phy_system_suspend(struct device *dev)
diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c
index 18134416b154..e3f08fe4ce75 100644
--- a/drivers/video/backlight/gpio_backlight.c
+++ b/drivers/video/backlight/gpio_backlight.c
@@ -154,10 +154,26 @@ static struct of_device_id gpio_backlight_of_match[] = {
MODULE_DEVICE_TABLE(of, gpio_backlight_of_match);
#endif
+static int gpio_backlight_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int gpio_backlight_resume(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops mipi_dsi_pm_ops = {
+ .suspend = gpio_backlight_suspend,
+ .resume = gpio_backlight_resume,
+};
+
static struct platform_driver gpio_backlight_driver = {
.driver = {
.name = "gpio-backlight",
.of_match_table = of_match_ptr(gpio_backlight_of_match),
+ .pm = &mipi_dsi_pm_ops,
},
.probe = gpio_backlight_probe,
};
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index d95ae092f154..7582e2829bb5 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -41,6 +41,7 @@ struct pwm_bl_data {
int brightness);
int (*check_fb)(struct device *, struct fb_info *);
void (*exit)(struct device *);
+ char fb_id[16];
};
static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness)
@@ -133,6 +134,17 @@ static const struct backlight_ops pwm_backlight_ops = {
};
#ifdef CONFIG_OF
+static int pwm_backlight_check_fb_name(struct device *dev, struct fb_info *info)
+{
+ struct backlight_device *bl = dev_get_drvdata(dev);
+ struct pwm_bl_data *pb = bl_get_data(bl);
+
+ if (strcmp(info->fix.id, pb->fb_id) == 0)
+ return true;
+
+ return false;
+}
+
static int pwm_backlight_parse_dt(struct device *dev,
struct platform_pwm_backlight_data *data)
{
@@ -141,6 +153,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
int length;
u32 value;
int ret;
+ const char *names;
if (!node)
return -ENODEV;
@@ -177,6 +190,11 @@ static int pwm_backlight_parse_dt(struct device *dev,
data->max_brightness--;
}
+ if (!of_property_read_string(node, "fb-names", &names)){
+ strcpy(data->fb_id, names);
+ data->check_fb = &pwm_backlight_check_fb_name;
+ }
+
data->enable_gpio = -EINVAL;
return 0;
}
@@ -246,6 +264,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
pb->exit = data->exit;
pb->dev = &pdev->dev;
pb->enabled = false;
+ strcpy(pb->fb_id, data->fb_id);
pb->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
GPIOD_ASIS);
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 4db10d7990c9..478b577ccab2 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -3215,6 +3215,8 @@ static void fbcon_new_modelist(struct fb_info *info)
if (!fb_display[i].mode)
continue;
vc = vc_cons[i].d;
+ if (!vc)
+ continue;
display_to_var(&var, &fb_display[i]);
mode = fb_find_nearest_mode(fb_display[i].mode,
&info->modelist);
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 5d3b0db5ce0a..77a0457fd1d4 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2449,6 +2449,10 @@ source "drivers/video/fbdev/omap/Kconfig"
source "drivers/video/fbdev/omap2/Kconfig"
source "drivers/video/fbdev/mmp/Kconfig"
+if ARCH_MXC
+source "drivers/video/fbdev/mxc/Kconfig"
+endif
+
config FB_SH_MOBILE_MERAM
tristate "SuperH Mobile MERAM read ahead support"
depends on (SUPERH || ARCH_SHMOBILE)
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index ee8c81405a7f..098f3b5d1066 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_FB_KYRO) += kyro/
obj-$(CONFIG_FB_SAVAGE) += savage/
obj-$(CONFIG_FB_GEODE) += geode/
obj-$(CONFIG_FB_MBX) += mbx/
+obj-$(CONFIG_FB_MXC) += mxc/
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
obj-$(CONFIG_FB_CONTROL) += controlfb.o
diff --git a/drivers/video/fbdev/mxc/Kconfig b/drivers/video/fbdev/mxc/Kconfig
new file mode 100644
index 000000000000..0b79ee371c6d
--- /dev/null
+++ b/drivers/video/fbdev/mxc/Kconfig
@@ -0,0 +1,116 @@
+config FB_MXC
+ tristate "MXC Framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
+ default y
+ help
+ This is a framebuffer device for the MXC LCD Controller.
+ See <http://www.linux-fbdev.org/> for information on framebuffer
+ devices.
+
+ If you plan to use the LCD display with your MXC system, say
+ Y here.
+
+config FB_MXC_SYNC_PANEL
+ depends on FB_MXC
+ tristate "Synchronous Panel Framebuffer"
+
+config FB_MXC_OVERLAY
+ depends on FB_MXC
+ tristate "Overlay Framebuffer"
+ default n
+ help
+ Enhanced LCD controller of MXC has overlay function.
+
+config FB_MXC_MIPI_DSI
+ tristate "MXC MIPI_DSI"
+ depends on FB_MXC_SYNC_PANEL
+ depends on MXC_IPU_V3
+
+config FB_MXC_MIPI_DSI_SAMSUNG
+ tristate "MXC MIPI_DSI_SAMSUNG"
+ depends on FB_MXC_SYNC_PANEL
+ depends on FB_MXS
+
+config FB_MXC_MIPI_DSI_NORTHWEST
+ tristate "MXC MIPI_DSI_NORTHWEST"
+ depends on FB_MXC_SYNC_PANEL
+ depends on FB_MXS
+
+config FB_MXC_TRULY_WVGA_SYNC_PANEL
+ tristate "TRULY WVGA Panel"
+ depends on FB_MXC_SYNC_PANEL
+ depends on FB_MXC_MIPI_DSI || FB_MXC_MIPI_DSI_SAMSUNG || FB_MXC_MIPI_DSI_NORTHWEST
+
+config FB_MXC_TRULY_PANEL_TFT3P5079E
+ tristate "TRULY Panel TFT3P5079E"
+ depends on FB_MXC_SYNC_PANEL
+ depends on FB_MXC_MIPI_DSI_SAMSUNG
+
+config FB_MXC_TRULY_PANEL_TFT3P5581E
+ tristate "TRULY Panel TFT3P5581E"
+ depends on FB_MXC_SYNC_PANEL
+ depends on FB_MXC_MIPI_DSI_SAMSUNG || FB_MXC_MIPI_DSI_NORTHWEST
+
+config FB_MXC_LDB
+ tristate "MXC LDB"
+ depends on FB_MXC_SYNC_PANEL
+ depends on MXC_IPU_V3 || FB_MXS
+ select VIDEOMODE_HELPERS
+
+config FB_MXC_HDMI
+ depends on FB_MXC_SYNC_PANEL
+ depends on MXC_IPU_V3
+ depends on I2C
+ tristate "MXC HDMI driver support"
+ select MFD_MXC_HDMI
+ help
+ Driver for the on-chip MXC HDMI controller.
+
+config FB_MXC_EDID
+ depends on FB_MXC && I2C
+ tristate "MXC EDID support"
+ default y
+
+config FB_MXS_SII902X
+ tristate "Si Image SII9022 DVI/HDMI Interface Chip"
+ depends on FB_MXS && I2C
+
+config FB_MXC_DCIC
+ tristate "MXC DCIC"
+ depends on FB_MXC_SYNC_PANEL
+ depends on MXC_IPU_V3 || FB_MXS
+ select VIDEOMODE_HELPERS
+
+config FB_MXC_ADV7535
+ tristate "ADI ADV7535 support"
+ depends on I2C
+ help
+ Driver support for the ADV7535 DSI-to-HDMI module
+
+config HANNSTAR_CABC
+ tristate "Hannstar CABC function"
+ help
+ Say yes here to support switching on/off Hannstar CABC
+ function. This function turns backlight density of a
+ display panel automatically according to the content
+ shown on the panel.
+
+config FB_MXC_EINK_PANEL
+ depends on FB_MXC
+ depends on DMA_ENGINE
+ select FB_DEFERRED_IO
+ tristate "E-Ink Panel Framebuffer"
+
+config FB_MXC_EINK_V2_PANEL
+ depends on FB_MXC
+ depends on DMA_ENGINE
+ select FB_DEFERRED_IO
+ tristate "E-Ink Panel Framebuffer based on EPDC V2"
+
+config FB_MXC_EINK_AUTO_UPDATE_MODE
+ bool "E-Ink Auto-update Mode Support"
+ depends on FB_MXC_EINK_PANEL
diff --git a/drivers/video/fbdev/mxc/Makefile b/drivers/video/fbdev/mxc/Makefile
new file mode 100644
index 000000000000..6ec78c6305c1
--- /dev/null
+++ b/drivers/video/fbdev/mxc/Makefile
@@ -0,0 +1,17 @@
+obj-y += mxc_dispdrv.o
+obj-$(CONFIG_FB_MXC_MIPI_DSI) += mipi_dsi.o
+obj-$(CONFIG_FB_MXC_MIPI_DSI_SAMSUNG) += mipi_dsi_samsung.o
+obj-$(CONFIG_FB_MXC_MIPI_DSI_NORTHWEST) += mipi_dsi_northwest.o
+obj-$(CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL) += mxcfb_hx8369_wvga.o
+obj-$(CONFIG_FB_MXC_TRULY_PANEL_TFT3P5079E) += mxcfb_otm8018b_wvga.o
+obj-$(CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E) += mxcfb_hx8363_wvga.o
+obj-$(CONFIG_FB_MXC_LDB) += ldb.o
+obj-$(CONFIG_FB_MXC_HDMI) += mxc_hdmi.o
+obj-$(CONFIG_FB_MXC_EDID) += mxc_edid.o
+obj-$(CONFIG_FB_MXC_ADV7535) += adv7535.o
+obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_lcdif.o mxc_ipuv3_fb.o
+obj-$(CONFIG_FB_MXC_EINK_PANEL) += mxc_epdc_fb.o
+obj-$(CONFIG_FB_MXC_EINK_V2_PANEL) += mxc_epdc_v2_fb.o
+obj-$(CONFIG_FB_MXS_SII902X) += mxsfb_sii902x.o
+obj-$(CONFIG_FB_MXC_DCIC) += mxc_dcic.o
+obj-$(CONFIG_HANNSTAR_CABC) += hannstar_cabc.o
diff --git a/drivers/video/fbdev/mxc/adv7535.c b/drivers/video/fbdev/mxc/adv7535.c
new file mode 100644
index 000000000000..3035dc5554d0
--- /dev/null
+++ b/drivers/video/fbdev/mxc/adv7535.c
@@ -0,0 +1,349 @@
+/*
+ * 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/device.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/pm_runtime.h>
+#include <video/mxc_edid.h>
+
+#include "mipi_dsi.h"
+
+/* main registers addr*/
+#define ADV7535_CHIP_REVISION 0x0
+#define ADV7535_DSI_CEC_ADDR 0xE1
+
+struct adv7535_info {
+ int rev;
+ struct device *dev;
+ struct i2c_client *i2c_main;
+ struct i2c_client *i2c_dsi_cec;
+ struct fb_videomode *fb_vmode;
+ unsigned int bpp;
+};
+
+static int adv7535_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int adv7535_remove(struct i2c_client *client);
+static int adv7535_detect(struct i2c_client *client,
+ struct i2c_board_info *info);
+
+static const struct i2c_device_id adv7535_id[] = {
+ {"adv7535", 0},
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, adv7535_id);
+
+static const struct of_device_id adv7535_dt_ids[] = {
+ { .compatible = "adi,adv7535", .data = NULL, },
+ { /* sentinel */ }
+};
+
+static struct i2c_driver adv7535_i2c_driver = {
+ .driver = {
+ .name = "adv7535",
+ .owner = THIS_MODULE,
+ .of_match_table = adv7535_dt_ids,
+ },
+ .probe = adv7535_probe,
+ .remove = adv7535_remove,
+ .id_table = adv7535_id,
+ .detect = adv7535_detect,
+};
+
+#define adv7535_write_reg(reg, val) { \
+ int err; \
+ \
+ err = i2c_smbus_write_byte_data(client, reg, val); \
+ if (err < 0) { \
+ dev_err(&client->dev, \
+ "%s:write reg error:reg=%2x, val=%2x\n",\
+ __func__, reg, val); \
+ return err; \
+ } \
+} \
+
+static int adv7535_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ s8 ret;
+ u8 chip_rev;
+ struct i2c_adapter *adapter = client->adapter;
+
+ /* check i2c functionality */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ /* i2c detection */
+ ret = i2c_smbus_read_byte_data(client,
+ ADV7535_CHIP_REVISION);
+ if (ret < 0) {
+ dev_err(&adapter->dev, "ADV7535 not found\n");
+ return -ENODEV;
+ }
+
+ chip_rev = ret;
+ if (chip_rev != 0x14) {
+ dev_info(&adapter->dev, "Unsupported chip id: 0x%2x\n",
+ chip_rev);
+ return -ENODEV;
+ }
+
+ dev_info(&adapter->dev, "chip_rev = 0x%x\n", ret);
+ return 0;
+}
+
+static int adv7535_setup_cfg(struct adv7535_info *info)
+{
+ struct i2c_client *client = NULL;
+
+ client = info->i2c_main;
+ adv7535_write_reg(0xd6, 0x48); /* HPD Override */
+ adv7535_write_reg(0x41, 0x10); /* Power Up */
+
+ adv7535_write_reg(0x16, 0x20); /* Fixed Init */
+ adv7535_write_reg(0x9A, 0xE0);
+ adv7535_write_reg(0xBA, 0x70);
+ adv7535_write_reg(0xDE, 0x82);
+ adv7535_write_reg(0xE4, 0x40);
+ adv7535_write_reg(0xE5, 0x80);
+
+ client = info->i2c_dsi_cec;
+ adv7535_write_reg(0x15, 0xD0);
+ adv7535_write_reg(0x17, 0xD0);
+ adv7535_write_reg(0x24, 0x20);
+ adv7535_write_reg(0x57, 0x11);
+
+ return 0;
+}
+
+static int adv7535_vmode_cfg(struct adv7535_info *info)
+{
+ struct i2c_client *client = NULL;
+ struct fb_videomode *fb_vmode = info->fb_vmode;
+ u32 line_length, frame_height;
+ u8 low, high;
+
+ line_length = fb_vmode->xres + fb_vmode->left_margin +
+ fb_vmode->right_margin + fb_vmode->hsync_len;
+ frame_height = fb_vmode->yres + fb_vmode->upper_margin +
+ fb_vmode->lower_margin + fb_vmode->vsync_len;
+
+ client = info->i2c_dsi_cec;
+ adv7535_write_reg(0x1C, 0x20); /* 2 Data Lanes */
+ adv7535_write_reg(0x16, 0x00); /* Pixel Clock */
+ adv7535_write_reg(0x27, 0xCB); /* INT_TIMING_GEN */
+
+ /* video mode settings */
+ low = (line_length << 4);
+ high = (line_length >> 4);
+ adv7535_write_reg(0x28, high); /* Total Line Length */
+ adv7535_write_reg(0x29, low);
+
+ low = (fb_vmode->hsync_len << 4);
+ high = (fb_vmode->hsync_len >> 4);
+ adv7535_write_reg(0x2A, high); /* Hsync Active Width */
+ adv7535_write_reg(0x2B, low);
+
+ low = (fb_vmode->right_margin << 4);
+ high = (fb_vmode->right_margin >> 4);
+ adv7535_write_reg(0x2C, high); /* Horizontal FP Width */
+ adv7535_write_reg(0x2D, low);
+
+ low = (fb_vmode->left_margin << 4);
+ high = (fb_vmode->left_margin >> 4);
+ adv7535_write_reg(0x2E, high); /* Horizontal BP Width */
+ adv7535_write_reg(0x2F, low);
+
+ low = (frame_height << 4);
+ high = (frame_height >> 4);
+ adv7535_write_reg(0x30, high); /* Total Frame Height */
+ adv7535_write_reg(0x31, low);
+
+ low = (fb_vmode->vsync_len << 4);
+ high = (fb_vmode->vsync_len >> 4);
+ adv7535_write_reg(0x32, high); /* Vsync Active Height */
+ adv7535_write_reg(0x33, low);
+
+ low = (fb_vmode->lower_margin << 4);
+ high = (fb_vmode->lower_margin >> 4);
+ adv7535_write_reg(0x34, high); /* Vertical FP Height */
+ adv7535_write_reg(0x35, low);
+
+ low = (fb_vmode->upper_margin << 4);
+ high = (fb_vmode->upper_margin >> 4);
+ adv7535_write_reg(0x36, high); /* Vertical BP Height */
+ adv7535_write_reg(0x37, low);
+
+ /* Reset Internal Timing Generator */
+ adv7535_write_reg(0x27, 0xCB);
+ adv7535_write_reg(0x27, 0x8B);
+ adv7535_write_reg(0x27, 0xCB);
+
+ client = info->i2c_main;
+ adv7535_write_reg(0xAF, 0x16); /* HDMI Output */
+ adv7535_write_reg(0x55, 0x10); /* AVI Info-frame */
+ adv7535_write_reg(0x56, 0x18);
+ adv7535_write_reg(0x40, 0x80); /* GCP Enable */
+ adv7535_write_reg(0x4C, 0x04); /* 24bpp */
+ adv7535_write_reg(0x49, 0x00);
+ adv7535_write_reg(0x17, 0x60); /* VS & HS Low Polarity, DE disabled */
+
+ /*TODO Audio Setup */
+
+ client = info->i2c_dsi_cec;
+ adv7535_write_reg(0xBE, 0x3D); /* CEC Power Mode */
+
+ adv7535_write_reg(0x03, 0x89);
+
+ return 0;
+}
+
+static int adv7535_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ u32 vmode_index;
+ int ret = 0, addr;
+ struct adv7535_info *info;
+ struct device *dev = &client->dev;
+ struct device_node *endpoint = NULL;
+
+ pr_info("adv7535 probing phase\n");
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = &client->dev;
+ info->i2c_main = client;
+ i2c_set_clientdata(client, info);
+
+ dev_info(dev, "main addr = 0x%x\n", info->i2c_main->addr);
+ /* get dsi source endpoint */
+ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+ if (!endpoint) {
+ dev_err(dev, "DSI source endpoint not exsit\n");
+ ret = -ENODEV;
+ goto err1;
+ }
+
+ info->fb_vmode = devm_kzalloc(dev, sizeof(struct fb_videomode),
+ GFP_KERNEL);
+ if (!info->fb_vmode) {
+ return -ENOMEM;
+ goto err1;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "video-mode", &vmode_index);
+ if (ret < 0) {
+ dev_err(dev, "failed to get required video mode\n");
+ goto err2;
+ }
+ if (vmode_index >= ARRAY_SIZE(mxc_cea_mode))
+ goto err2;
+
+ memcpy(info->fb_vmode, &mxc_cea_mode[vmode_index],
+ sizeof(struct fb_videomode));
+
+ ret = of_property_read_u32(dev->of_node, "bpp", &info->bpp);
+ if (ret < 0) {
+ dev_err(dev, "failed to get bpp\n");
+ goto err2;
+ }
+
+ if ((ret = adv7535_detect(client, NULL)))
+ goto err2;
+
+ addr = i2c_smbus_read_byte_data(client,
+ ADV7535_DSI_CEC_ADDR);
+ if (addr < 0) {
+ dev_err(dev, "Cannot get dsi_cec addr\n");
+ ret = addr;
+ goto err2;
+ }
+
+ dev_info(dev, "dsi cec addr = 0x%x\n", addr);
+ info->i2c_dsi_cec = i2c_new_dummy(client->adapter, addr >> 1);
+ if (!info->i2c_dsi_cec) {
+ dev_err(dev, "Failed to allocate I2C device for dsi_cec\n");
+ ret = -ENOMEM;
+ goto err2;
+ }
+
+ i2c_set_clientdata(info->i2c_dsi_cec, info);
+
+ /*TODO interrupts */
+
+ if ((ret = adv7535_setup_cfg(info)))
+ goto err3;
+
+ if ((ret = adv7535_vmode_cfg(info)))
+ goto err3;
+
+ pm_runtime_enable(info->dev);
+
+ dev_info(dev, "adv7535 probe finished\n");
+
+ return 0;
+err3:
+ i2c_unregister_device(info->i2c_dsi_cec);
+err2:
+ devm_kfree(dev, info->fb_vmode);
+err1:
+ devm_kfree(dev, info);
+
+ return ret;
+}
+
+static int adv7535_remove(struct i2c_client *client)
+{
+ struct adv7535_info *info;
+
+ info = i2c_get_clientdata(client);
+ i2c_set_clientdata(client, NULL);
+
+ pm_runtime_disable(info->dev);
+
+ i2c_unregister_device(info->i2c_dsi_cec);
+
+ kfree(info->fb_vmode);
+ kfree(info);
+
+ return 0;
+}
+
+static __init int adv7535_init(void)
+{
+ u8 err = 0;
+
+
+ err = i2c_add_driver(&adv7535_i2c_driver);
+ if (err != 0)
+ pr_err("%s: i2c driver register failed, error = %d\n",
+ __func__, err);
+
+ pr_debug("%s (ret=%d)\n", __func__, err);
+ return err;
+}
+
+static void __exit adv7535_exit(void)
+{
+ i2c_del_driver(&adv7535_i2c_driver);
+}
+
+module_init(adv7535_init);
+module_exit(adv7535_exit);
+
+MODULE_AUTHOR("NXP Semiconductor");
+MODULE_DESCRIPTION("ADV7535 video encoder driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mxc/crtc.h b/drivers/video/fbdev/mxc/crtc.h
new file mode 100644
index 000000000000..8bd1c1b95bd1
--- /dev/null
+++ b/drivers/video/fbdev/mxc/crtc.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 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
+ */
+#ifndef __CRTC__
+#define __CRTC__
+
+enum crtc {
+ CRTC_IPU_DI0,
+ CRTC_IPU_DI1,
+ CRTC_IPU1_DI0,
+ CRTC_IPU1_DI1,
+ CRTC_IPU2_DI0,
+ CRTC_IPU2_DI1,
+ CRTC_LCDIF,
+ CRTC_LCDIF1,
+ CRTC_LCDIF2,
+ CRTC_MAX,
+};
+
+struct ipu_di_crtc_map {
+ enum crtc crtc;
+ int ipu_id;
+ int ipu_di;
+};
+
+static const struct ipu_di_crtc_map ipu_di_crtc_maps[] = {
+ {CRTC_IPU1_DI0, 0 , 0}, {CRTC_IPU1_DI1, 0 , 1},
+ {CRTC_IPU2_DI0, 1 , 0}, {CRTC_IPU2_DI1, 1 , 1},
+};
+
+static inline int ipu_di_to_crtc(struct device *dev, int ipu_id,
+ int ipu_di, enum crtc *crtc)
+{
+ int i = 0;
+
+ for (; i < ARRAY_SIZE(ipu_di_crtc_maps); i++)
+ if (ipu_di_crtc_maps[i].ipu_id == ipu_id &&
+ ipu_di_crtc_maps[i].ipu_di == ipu_di) {
+ *crtc = ipu_di_crtc_maps[i].crtc;
+ return 0;
+ }
+
+ dev_err(dev, "failed to get valid ipu di crtc "
+ "ipu_id %d, ipu_di %d\n", ipu_id, ipu_di);
+ return -EINVAL;
+}
+
+#endif
diff --git a/drivers/video/fbdev/mxc/epdc_regs.h b/drivers/video/fbdev/mxc/epdc_regs.h
new file mode 100644
index 000000000000..d4e6e525b7b9
--- /dev/null
+++ b/drivers/video/fbdev/mxc/epdc_regs.h
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2010-2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __EPDC_REGS_INCLUDED__
+#define __EPDC_REGS_INCLUDED__
+
+extern void __iomem *epdc_base;
+
+/*************************************
+ * Register addresses
+ **************************************/
+
+#define EPDC_CTRL (epdc_base + 0x000)
+#define EPDC_CTRL_SET (epdc_base + 0x004)
+#define EPDC_CTRL_CLEAR (epdc_base + 0x008)
+#define EPDC_CTRL_TOGGLE (epdc_base + 0x00C)
+#define EPDC_WVADDR (epdc_base + 0x020)
+#define EPDC_WB_ADDR (epdc_base + 0x030)
+#define EPDC_RES (epdc_base + 0x040)
+#define EPDC_FORMAT (epdc_base + 0x050)
+#define EPDC_FORMAT_SET (epdc_base + 0x054)
+#define EPDC_FORMAT_CLEAR (epdc_base + 0x058)
+#define EPDC_FORMAT_TOGGLE (epdc_base + 0x05C)
+#define EPDC_FIFOCTRL (epdc_base + 0x0A0)
+#define EPDC_FIFOCTRL_SET (epdc_base + 0x0A4)
+#define EPDC_FIFOCTRL_CLEAR (epdc_base + 0x0A8)
+#define EPDC_FIFOCTRL_TOGGLE (epdc_base + 0x0AC)
+#define EPDC_UPD_ADDR (epdc_base + 0x100)
+#define EPDC_UPD_STRIDE (epdc_base + 0x110)
+#define EPDC_UPD_CORD (epdc_base + 0x120)
+#define EPDC_UPD_SIZE (epdc_base + 0x140)
+#define EPDC_UPD_CTRL (epdc_base + 0x160)
+#define EPDC_UPD_FIXED (epdc_base + 0x180)
+#define EPDC_TEMP (epdc_base + 0x1A0)
+#define EPDC_AUTOWV_LUT (epdc_base + 0x1C0)
+#define EPDC_TCE_CTRL (epdc_base + 0x200)
+#define EPDC_TCE_SDCFG (epdc_base + 0x220)
+#define EPDC_TCE_GDCFG (epdc_base + 0x240)
+#define EPDC_TCE_HSCAN1 (epdc_base + 0x260)
+#define EPDC_TCE_HSCAN2 (epdc_base + 0x280)
+#define EPDC_TCE_VSCAN (epdc_base + 0x2A0)
+#define EPDC_TCE_OE (epdc_base + 0x2C0)
+#define EPDC_TCE_POLARITY (epdc_base + 0x2E0)
+#define EPDC_TCE_TIMING1 (epdc_base + 0x300)
+#define EPDC_TCE_TIMING2 (epdc_base + 0x310)
+#define EPDC_TCE_TIMING3 (epdc_base + 0x320)
+#define EPDC_PIGEON_CTRL0 (epdc_base + 0x380)
+#define EPDC_PIGEON_CTRL1 (epdc_base + 0x390)
+#define EPDC_IRQ_MASK1 (epdc_base + 0x3C0)
+#define EPDC_IRQ_MASK1_SET (epdc_base + 0x3C4)
+#define EPDC_IRQ_MASK1_CLEAR (epdc_base + 0x3C8)
+#define EPDC_IRQ_MASK1_TOGGLE (epdc_base + 0x3CC)
+#define EPDC_IRQ_MASK2 (epdc_base + 0x3D0)
+#define EPDC_IRQ_MASK2_SET (epdc_base + 0x3D4)
+#define EPDC_IRQ_MASK2_CLEAR (epdc_base + 0x3D8)
+#define EPDC_IRQ_MASK2_TOGGLE (epdc_base + 0x3DC)
+#define EPDC_IRQ1 (epdc_base + 0x3E0)
+#define EPDC_IRQ1_SET (epdc_base + 0x3E4)
+#define EPDC_IRQ1_CLEAR (epdc_base + 0x3E8)
+#define EPDC_IRQ1_TOGGLE (epdc_base + 0x3EC)
+#define EPDC_IRQ2 (epdc_base + 0x3F0)
+#define EPDC_IRQ2_SET (epdc_base + 0x3F4)
+#define EPDC_IRQ2_CLEAR (epdc_base + 0x3F8)
+#define EPDC_IRQ2_TOGGLE (epdc_base + 0x3FC)
+#define EPDC_IRQ_MASK (epdc_base + 0x400)
+#define EPDC_IRQ_MASK_SET (epdc_base + 0x404)
+#define EPDC_IRQ_MASK_CLEAR (epdc_base + 0x408)
+#define EPDC_IRQ_MASK_TOGGLE (epdc_base + 0x40C)
+#define EPDC_IRQ (epdc_base + 0x420)
+#define EPDC_IRQ_SET (epdc_base + 0x424)
+#define EPDC_IRQ_CLEAR (epdc_base + 0x428)
+#define EPDC_IRQ_TOGGLE (epdc_base + 0x42C)
+#define EPDC_STATUS_LUTS (epdc_base + 0x440)
+#define EPDC_STATUS_LUTS_SET (epdc_base + 0x444)
+#define EPDC_STATUS_LUTS_CLEAR (epdc_base + 0x448)
+#define EPDC_STATUS_LUTS_TOGGLE (epdc_base + 0x44C)
+#define EPDC_STATUS_LUTS2 (epdc_base + 0x450)
+#define EPDC_STATUS_LUTS2_SET (epdc_base + 0x454)
+#define EPDC_STATUS_LUTS2_CLEAR (epdc_base + 0x458)
+#define EPDC_STATUS_LUTS2_TOGGLE (epdc_base + 0x45C)
+#define EPDC_STATUS_NEXTLUT (epdc_base + 0x460)
+#define EPDC_STATUS_COL (epdc_base + 0x480)
+#define EPDC_STATUS_COL2 (epdc_base + 0x490)
+#define EPDC_STATUS (epdc_base + 0x4A0)
+#define EPDC_STATUS_SET (epdc_base + 0x4A4)
+#define EPDC_STATUS_CLEAR (epdc_base + 0x4A8)
+#define EPDC_STATUS_TOGGLE (epdc_base + 0x4AC)
+#define EPDC_UPD_COL_CORD (epdc_base + 0x4C0)
+#define EPDC_UPD_COL_SIZE (epdc_base + 0x4E0)
+#define EPDC_DEBUG (epdc_base + 0x500)
+#define EPDC_DEBUG_LUT (epdc_base + 0x530)
+#define EPDC_HIST1_PARAM (epdc_base + 0x600)
+#define EPDC_HIST2_PARAM (epdc_base + 0x610)
+#define EPDC_HIST4_PARAM (epdc_base + 0x620)
+#define EPDC_HIST8_PARAM0 (epdc_base + 0x630)
+#define EPDC_HIST8_PARAM1 (epdc_base + 0x640)
+#define EPDC_HIST16_PARAM0 (epdc_base + 0x650)
+#define EPDC_HIST16_PARAM1 (epdc_base + 0x660)
+#define EPDC_HIST16_PARAM2 (epdc_base + 0x670)
+#define EPDC_HIST16_PARAM3 (epdc_base + 0x680)
+#define EPDC_GPIO (epdc_base + 0x700)
+#define EPDC_VERSION (epdc_base + 0x7F0)
+#define EPDC_PIGEON_0_0 (epdc_base + 0x800)
+#define EPDC_PIGEON_0_1 (epdc_base + 0x810)
+#define EPDC_PIGEON_0_2 (epdc_base + 0x820)
+#define EPDC_PIGEON_1_0 (epdc_base + 0x840)
+#define EPDC_PIGEON_1_1 (epdc_base + 0x850)
+#define EPDC_PIGEON_1_2 (epdc_base + 0x860)
+#define EPDC_PIGEON_2_0 (epdc_base + 0x880)
+#define EPDC_PIGEON_2_1 (epdc_base + 0x890)
+#define EPDC_PIGEON_2_2 (epdc_base + 0x8A0)
+#define EPDC_PIGEON_3_0 (epdc_base + 0x8C0)
+#define EPDC_PIGEON_3_1 (epdc_base + 0x8D0)
+#define EPDC_PIGEON_3_2 (epdc_base + 0x8E0)
+#define EPDC_PIGEON_4_0 (epdc_base + 0x900)
+#define EPDC_PIGEON_4_1 (epdc_base + 0x910)
+#define EPDC_PIGEON_4_2 (epdc_base + 0x920)
+#define EPDC_PIGEON_5_0 (epdc_base + 0x940)
+#define EPDC_PIGEON_5_1 (epdc_base + 0x950)
+#define EPDC_PIGEON_5_2 (epdc_base + 0x960)
+#define EPDC_PIGEON_6_0 (epdc_base + 0x980)
+#define EPDC_PIGEON_6_1 (epdc_base + 0x990)
+#define EPDC_PIGEON_6_2 (epdc_base + 0x9A0)
+#define EPDC_PIGEON_7_0 (epdc_base + 0x9C0)
+#define EPDC_PIGEON_7_1 (epdc_base + 0x9D0)
+#define EPDC_PIGEON_7_2 (epdc_base + 0x9E0)
+#define EPDC_PIGEON_8_0 (epdc_base + 0xA00)
+#define EPDC_PIGEON_8_1 (epdc_base + 0xA10)
+#define EPDC_PIGEON_8_2 (epdc_base + 0xA20)
+#define EPDC_PIGEON_9_0 (epdc_base + 0xA40)
+#define EPDC_PIGEON_9_1 (epdc_base + 0xA50)
+#define EPDC_PIGEON_9_2 (epdc_base + 0xA60)
+#define EPDC_PIGEON_10_0 (epdc_base + 0xA80)
+#define EPDC_PIGEON_10_1 (epdc_base + 0xA90)
+#define EPDC_PIGEON_10_2 (epdc_base + 0xAA0)
+#define EPDC_PIGEON_11_0 (epdc_base + 0xAC0)
+#define EPDC_PIGEON_11_1 (epdc_base + 0xAD0)
+#define EPDC_PIGEON_11_2 (epdc_base + 0xAE0)
+#define EPDC_PIGEON_12_0 (epdc_base + 0xB00)
+#define EPDC_PIGEON_12_1 (epdc_base + 0xB10)
+#define EPDC_PIGEON_12_2 (epdc_base + 0xB20)
+#define EPDC_PIGEON_13_0 (epdc_base + 0xB40)
+#define EPDC_PIGEON_13_1 (epdc_base + 0xB50)
+#define EPDC_PIGEON_13_2 (epdc_base + 0xB60)
+#define EPDC_PIGEON_14_0 (epdc_base + 0xB80)
+#define EPDC_PIGEON_14_1 (epdc_base + 0xB90)
+#define EPDC_PIGEON_14_2 (epdc_base + 0xBA0)
+#define EPDC_PIGEON_15_0 (epdc_base + 0xBC0)
+#define EPDC_PIGEON_15_1 (epdc_base + 0xBD0)
+#define EPDC_PIGEON_15_2 (epdc_base + 0xBE0)
+#define EPDC_WB_ADDR_TCE (epdc_base + 0xC10)
+
+/*
+ * Register field definitions
+ */
+
+enum {
+/* EPDC_CTRL field values */
+ EPDC_CTRL_SFTRST = 0x80000000,
+ EPDC_CTRL_CLKGATE = 0x40000000,
+ EPDC_CTRL_SRAM_POWERDOWN = 0x100,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_MASK = 0xC0,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP = 0,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_ALL_BYTES_SWAP = 0x40,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_HWD_SWAP = 0x80,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_HWD_BYTE_SWAP = 0xC0,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_MASK = 0x30,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP = 0,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_ALL_BYTES_SWAP = 0x10,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_HWD_SWAP = 0x20,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_HWD_BYTE_SWAP = 0x30,
+ EPDC_CTRL_BURST_LEN_8_8 = 0x1,
+ EPDC_CTRL_BURST_LEN_8_16 = 0,
+
+/* EPDC_RES field values */
+ EPDC_RES_VERTICAL_MASK = 0x1FFF0000,
+ EPDC_RES_VERTICAL_OFFSET = 16,
+ EPDC_RES_HORIZONTAL_MASK = 0x1FFF,
+ EPDC_RES_HORIZONTAL_OFFSET = 0,
+
+/* EPDC_FORMAT field values */
+ EPDC_FORMAT_BUF_PIXEL_SCALE_ROUND = 0x1000000,
+ EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK = 0xFF0000,
+ EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET = 16,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_MASK = 0x700,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P2N = 0x200,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P3N = 0x300,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N = 0x400,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N = 0x500,
+ EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT = 0x0,
+ EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT_VCOM = 0x1,
+ EPDC_FORMAT_TFT_PIXEL_FORMAT_4BIT = 0x2,
+ EPDC_FORMAT_TFT_PIXEL_FORMAT_4BIT_VCOM = 0x3,
+
+/* EPDC_FIFOCTRL field values */
+ EPDC_FIFOCTRL_ENABLE_PRIORITY = 0x80000000,
+ EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK = 0xFF0000,
+ EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET = 16,
+ EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK = 0xFF00,
+ EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET = 8,
+ EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK = 0xFF,
+ EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET = 0,
+
+/* EPDC_UPD_CORD field values */
+ EPDC_UPD_CORD_YCORD_MASK = 0x1FFF0000,
+ EPDC_UPD_CORD_YCORD_OFFSET = 16,
+ EPDC_UPD_CORD_XCORD_MASK = 0x1FFF,
+ EPDC_UPD_CORD_XCORD_OFFSET = 0,
+
+/* EPDC_UPD_SIZE field values */
+ EPDC_UPD_SIZE_HEIGHT_MASK = 0x1FFF0000,
+ EPDC_UPD_SIZE_HEIGHT_OFFSET = 16,
+ EPDC_UPD_SIZE_WIDTH_MASK = 0x1FFF,
+ EPDC_UPD_SIZE_WIDTH_OFFSET = 0,
+
+/* EPDC_UPD_CTRL field values */
+ EPDC_UPD_CTRL_USE_FIXED = 0x80000000,
+ EPDC_UPD_CTRL_LUT_SEL_MASK = 0x3F0000,
+ EPDC_UPD_CTRL_LUT_SEL_OFFSET = 16,
+ EPDC_UPD_CTRL_WAVEFORM_MODE_MASK = 0xFF00,
+ EPDC_UPD_CTRL_WAVEFORM_MODE_OFFSET = 8,
+ EPDC_UPD_CTRL_AUTOWV_PAUSE = 0x8,
+ EPDC_UPD_CTRL_AUTOWV = 0x4,
+ EPDC_UPD_CTRL_DRY_RUN = 0x2,
+ EPDC_UPD_CTRL_UPDATE_MODE_FULL = 0x1,
+
+/* EPDC_UPD_FIXED field values */
+ EPDC_UPD_FIXED_FIXNP_EN = 0x80000000,
+ EPDC_UPD_FIXED_FIXCP_EN = 0x40000000,
+ EPDC_UPD_FIXED_FIXNP_MASK = 0xFF00,
+ EPDC_UPD_FIXED_FIXNP_OFFSET = 8,
+ EPDC_UPD_FIXED_FIXCP_MASK = 0xFF,
+ EPDC_UPD_FIXED_FIXCP_OFFSET = 0,
+
+/* EPDC_AUTOWV_LUT field values */
+ EPDC_AUTOWV_LUT_DATA_MASK = 0xFF0000,
+ EPDC_AUTOWV_LUT_DATA_OFFSET = 16,
+ EPDC_AUTOWV_LUT_ADDR_MASK = 0xFF,
+ EPDC_AUTOWV_LUT_ADDR_OFFSET = 0,
+
+/* EPDC_TCE_CTRL field values */
+ EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK = 0x1FF0000,
+ EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET = 16,
+ EPDC_TCE_CTRL_VCOM_VAL_MASK = 0xC00,
+ EPDC_TCE_CTRL_VCOM_VAL_OFFSET = 10,
+ EPDC_TCE_CTRL_VCOM_MODE_AUTO = 0x200,
+ EPDC_TCE_CTRL_VCOM_MODE_MANUAL = 0x000,
+ EPDC_TCE_CTRL_DDR_MODE_ENABLE = 0x100,
+ EPDC_TCE_CTRL_LVDS_MODE_CE_ENABLE = 0x80,
+ EPDC_TCE_CTRL_LVDS_MODE_ENABLE = 0x40,
+ EPDC_TCE_CTRL_SCAN_DIR_1_UP = 0x20,
+ EPDC_TCE_CTRL_SCAN_DIR_0_UP = 0x10,
+ EPDC_TCE_CTRL_DUAL_SCAN_ENABLE = 0x8,
+ EPDC_TCE_CTRL_SDDO_WIDTH_16BIT = 0x4,
+ EPDC_TCE_CTRL_PIXELS_PER_SDCLK_2 = 1,
+ EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4 = 2,
+ EPDC_TCE_CTRL_PIXELS_PER_SDCLK_8 = 3,
+
+/* EPDC_TCE_SDCFG field values */
+ EPDC_TCE_SDCFG_SDCLK_HOLD = 0x200000,
+ EPDC_TCE_SDCFG_SDSHR = 0x100000,
+ EPDC_TCE_SDCFG_NUM_CE_MASK = 0xF0000,
+ EPDC_TCE_SDCFG_NUM_CE_OFFSET = 16,
+ EPDC_TCE_SDCFG_SDDO_REFORMAT_STANDARD = 0,
+ EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS = 0x4000,
+ EPDC_TCE_SDCFG_SDDO_INVERT_ENABLE = 0x2000,
+ EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK = 0x1FFF,
+ EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET = 0,
+
+/* EPDC_TCE_GDCFG field values */
+ EPDC_TCE_SDCFG_GDRL = 0x10,
+ EPDC_TCE_SDCFG_GDOE_MODE_DELAYED_GDCLK = 0x2,
+ EPDC_TCE_SDCFG_GDSP_MODE_FRAME_SYNC = 0x1,
+ EPDC_TCE_SDCFG_GDSP_MODE_ONE_LINE = 0x0,
+
+/* EPDC_TCE_HSCAN1 field values */
+ EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK = 0xFFF0000,
+ EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET = 16,
+ EPDC_TCE_HSCAN1_LINE_SYNC_MASK = 0xFFF,
+ EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET = 0,
+
+/* EPDC_TCE_HSCAN2 field values */
+ EPDC_TCE_HSCAN2_LINE_END_MASK = 0xFFF0000,
+ EPDC_TCE_HSCAN2_LINE_END_OFFSET = 16,
+ EPDC_TCE_HSCAN2_LINE_BEGIN_MASK = 0xFFF,
+ EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET = 0,
+
+/* EPDC_TCE_VSCAN field values */
+ EPDC_TCE_VSCAN_FRAME_END_MASK = 0xFF0000,
+ EPDC_TCE_VSCAN_FRAME_END_OFFSET = 16,
+ EPDC_TCE_VSCAN_FRAME_BEGIN_MASK = 0xFF00,
+ EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET = 8,
+ EPDC_TCE_VSCAN_FRAME_SYNC_MASK = 0xFF,
+ EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET = 0,
+
+/* EPDC_TCE_OE field values */
+ EPDC_TCE_OE_SDOED_WIDTH_MASK = 0xFF000000,
+ EPDC_TCE_OE_SDOED_WIDTH_OFFSET = 24,
+ EPDC_TCE_OE_SDOED_DLY_MASK = 0xFF0000,
+ EPDC_TCE_OE_SDOED_DLY_OFFSET = 16,
+ EPDC_TCE_OE_SDOEZ_WIDTH_MASK = 0xFF00,
+ EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET = 8,
+ EPDC_TCE_OE_SDOEZ_DLY_MASK = 0xFF,
+ EPDC_TCE_OE_SDOEZ_DLY_OFFSET = 0,
+
+/* EPDC_TCE_POLARITY field values */
+ EPDC_TCE_POLARITY_GDSP_POL_ACTIVE_HIGH = 0x10,
+ EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH = 0x8,
+ EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH = 0x4,
+ EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH = 0x2,
+ EPDC_TCE_POLARITY_SDCE_POL_ACTIVE_HIGH = 0x1,
+
+/* EPDC_TCE_TIMING1 field values */
+ EPDC_TCE_TIMING1_SDLE_SHIFT_NONE = 0x00,
+ EPDC_TCE_TIMING1_SDLE_SHIFT_1 = 0x10,
+ EPDC_TCE_TIMING1_SDLE_SHIFT_2 = 0x20,
+ EPDC_TCE_TIMING1_SDLE_SHIFT_3 = 0x30,
+ EPDC_TCE_TIMING1_SDCLK_INVERT = 0x8,
+ EPDC_TCE_TIMING1_SDCLK_SHIFT_NONE = 0,
+ EPDC_TCE_TIMING1_SDCLK_SHIFT_1CYCLE = 1,
+ EPDC_TCE_TIMING1_SDCLK_SHIFT_2CYCLES = 2,
+ EPDC_TCE_TIMING1_SDCLK_SHIFT_3CYCLES = 3,
+
+/* EPDC_TCE_TIMING2 field values */
+ EPDC_TCE_TIMING2_GDCLK_HP_MASK = 0xFFFF0000,
+ EPDC_TCE_TIMING2_GDCLK_HP_OFFSET = 16,
+ EPDC_TCE_TIMING2_GDSP_OFFSET_MASK = 0xFFFF,
+ EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET = 0,
+
+/* EPDC_TCE_TIMING3 field values */
+ EPDC_TCE_TIMING3_GDOE_OFFSET_MASK = 0xFFFF0000,
+ EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET = 16,
+ EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK = 0xFFFF,
+ EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET = 0,
+
+/* EPDC_IRQ_MASK/EPDC_IRQ field values */
+ EPDC_IRQ_WB_CMPLT_IRQ = 0x10000,
+ EPDC_IRQ_LUT_COL_IRQ = 0x20000,
+ EPDC_IRQ_TCE_UNDERRUN_IRQ = 0x40000,
+ EPDC_IRQ_FRAME_END_IRQ = 0x80000,
+ EPDC_IRQ_BUS_ERROR_IRQ = 0x100000,
+ EPDC_IRQ_TCE_IDLE_IRQ = 0x200000,
+ EPDC_IRQ_UPD_DONE_IRQ = 0x400000,
+ EPDC_IRQ_PWR_IRQ = 0x800000,
+
+/* EPDC_STATUS_NEXTLUT field values */
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_VALID = 0x100,
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_MASK = 0x3F,
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_OFFSET = 0,
+
+/* EPDC_STATUS field values */
+ EPDC_STATUS_HISTOGRAM_CP_MASK = 0x1F0000,
+ EPDC_STATUS_HISTOGRAM_CP_OFFSET = 16,
+ EPDC_STATUS_HISTOGRAM_NP_MASK = 0x1F00,
+ EPDC_STATUS_HISTOGRAM_NP_OFFSET = 8,
+ EPDC_STATUS_UPD_VOID = 0x8,
+ EPDC_STATUS_LUTS_UNDERRUN = 0x4,
+ EPDC_STATUS_LUTS_BUSY = 0x2,
+ EPDC_STATUS_WB_BUSY = 0x1,
+
+/* EPDC_UPD_COL_CORD field values */
+ EPDC_UPD_COL_CORD_YCORD_MASK = 0x1FFF0000,
+ EPDC_UPD_COL_CORD_YCORD_OFFSET = 16,
+ EPDC_UPD_COL_CORD_XCORD_MASK = 0x1FFF,
+ EPDC_UPD_COL_CORD_XCORD_OFFSET = 0,
+
+/* EPDC_UPD_COL_SIZE field values */
+ EPDC_UPD_COL_SIZE_HEIGHT_MASK = 0x1FFF0000,
+ EPDC_UPD_COL_SIZE_HEIGHT_OFFSET = 16,
+ EPDC_UPD_COL_SIZE_WIDTH_MASK = 0x1FFF,
+ EPDC_UPD_COL_SIZE_WIDTH_OFFSET = 0,
+
+/* EPDC_DEBUG field values */
+ EPDC_DEBUG_UNDERRUN_RECOVER = 0x2,
+ EPDC_DEBUG_COLLISION_OFF = 0x1,
+
+/* EPDC_HISTx_PARAM field values */
+ EPDC_HIST_PARAM_VALUE0_MASK = 0x1F,
+ EPDC_HIST_PARAM_VALUE0_OFFSET = 0,
+ EPDC_HIST_PARAM_VALUE1_MASK = 0x1F00,
+ EPDC_HIST_PARAM_VALUE1_OFFSET = 8,
+ EPDC_HIST_PARAM_VALUE2_MASK = 0x1F0000,
+ EPDC_HIST_PARAM_VALUE2_OFFSET = 16,
+ EPDC_HIST_PARAM_VALUE3_MASK = 0x1F000000,
+ EPDC_HIST_PARAM_VALUE3_OFFSET = 24,
+ EPDC_HIST_PARAM_VALUE4_MASK = 0x1F,
+ EPDC_HIST_PARAM_VALUE4_OFFSET = 0,
+ EPDC_HIST_PARAM_VALUE5_MASK = 0x1F00,
+ EPDC_HIST_PARAM_VALUE5_OFFSET = 8,
+ EPDC_HIST_PARAM_VALUE6_MASK = 0x1F0000,
+ EPDC_HIST_PARAM_VALUE6_OFFSET = 16,
+ EPDC_HIST_PARAM_VALUE7_MASK = 0x1F000000,
+ EPDC_HIST_PARAM_VALUE7_OFFSET = 24,
+ EPDC_HIST_PARAM_VALUE8_MASK = 0x1F,
+ EPDC_HIST_PARAM_VALUE8_OFFSET = 0,
+ EPDC_HIST_PARAM_VALUE9_MASK = 0x1F00,
+ EPDC_HIST_PARAM_VALUE9_OFFSET = 8,
+ EPDC_HIST_PARAM_VALUE10_MASK = 0x1F0000,
+ EPDC_HIST_PARAM_VALUE10_OFFSET = 16,
+ EPDC_HIST_PARAM_VALUE11_MASK = 0x1F000000,
+ EPDC_HIST_PARAM_VALUE11_OFFSET = 24,
+ EPDC_HIST_PARAM_VALUE12_MASK = 0x1F,
+ EPDC_HIST_PARAM_VALUE12_OFFSET = 0,
+ EPDC_HIST_PARAM_VALUE13_MASK = 0x1F00,
+ EPDC_HIST_PARAM_VALUE13_OFFSET = 8,
+ EPDC_HIST_PARAM_VALUE14_MASK = 0x1F0000,
+ EPDC_HIST_PARAM_VALUE14_OFFSET = 16,
+ EPDC_HIST_PARAM_VALUE15_MASK = 0x1F000000,
+ EPDC_HIST_PARAM_VALUE15_OFFSET = 24,
+
+/* EPDC_GPIO field values */
+ EPDC_GPIO_PWRCOM = 0x40,
+ EPDC_GPIO_PWRCTRL_MASK = 0x3C,
+ EPDC_GPIO_PWRCTRL_OFFSET = 2,
+ EPDC_GPIO_BDR_MASK = 0x3,
+ EPDC_GPIO_BDR_OFFSET = 0,
+
+/* EPDC_VERSION field values */
+ EPDC_VERSION_MAJOR_MASK = 0xFF000000,
+ EPDC_VERSION_MAJOR_OFFSET = 24,
+ EPDC_VERSION_MINOR_MASK = 0xFF0000,
+ EPDC_VERSION_MINOR_OFFSET = 16,
+ EPDC_VERSION_STEP_MASK = 0xFFFF,
+ EPDC_VERSION_STEP_OFFSET = 0,
+};
+
+#endif /* __EPDC_REGS_INCLUDED__ */
diff --git a/drivers/video/fbdev/mxc/epdc_v2_regs.h b/drivers/video/fbdev/mxc/epdc_v2_regs.h
new file mode 100644
index 000000000000..052df13151fc
--- /dev/null
+++ b/drivers/video/fbdev/mxc/epdc_v2_regs.h
@@ -0,0 +1,533 @@
+/*
+ * 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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __EPDC_REGS_INCLUDED__
+#define __EPDC_REGS_INCLUDED__
+
+extern void __iomem *epdc_v2_base;
+
+/*************************************
+ * Register addresses
+ **************************************/
+
+#define EPDC_CTRL (epdc_v2_base + 0x000)
+#define EPDC_CTRL_SET (epdc_v2_base + 0x004)
+#define EPDC_CTRL_CLEAR (epdc_v2_base + 0x008)
+#define EPDC_CTRL_TOGGLE (epdc_v2_base + 0x00C)
+#define EPDC_WVADDR (epdc_v2_base + 0x020)
+#define EPDC_WB_ADDR (epdc_v2_base + 0x030)
+#define EPDC_RES (epdc_v2_base + 0x040)
+#define EPDC_FORMAT (epdc_v2_base + 0x050)
+#define EPDC_FORMAT_SET (epdc_v2_base + 0x054)
+#define EPDC_FORMAT_CLEAR (epdc_v2_base + 0x058)
+#define EPDC_FORMAT_TOGGLE (epdc_v2_base + 0x05C)
+#define EPDC_WB_FIELD0 (epdc_v2_base + 0x060)
+#define EPDC_WB_FIELD0_SET (epdc_v2_base + 0x064)
+#define EPDC_WB_FIELD0_CLEAR (epdc_v2_base + 0x068)
+#define EPDC_WB_FIELD0_TOGGLE (epdc_v2_base + 0x06C)
+#define EPDC_WB_FIELD1 (epdc_v2_base + 0x070)
+#define EPDC_WB_FIELD1_SET (epdc_v2_base + 0x074)
+#define EPDC_WB_FIELD1_CLEAR (epdc_v2_base + 0x078)
+#define EPDC_WB_FIELD1_TOGGLE (epdc_v2_base + 0x07C)
+#define EPDC_WB_FIELD2 (epdc_v2_base + 0x080)
+#define EPDC_WB_FIELD2_SET (epdc_v2_base + 0x084)
+#define EPDC_WB_FIELD2_CLEAR (epdc_v2_base + 0x088)
+#define EPDC_WB_FIELD2_TOGGLE (epdc_v2_base + 0x08C)
+#define EPDC_WB_FIELD3 (epdc_v2_base + 0x090)
+#define EPDC_WB_FIELD3_SET (epdc_v2_base + 0x094)
+#define EPDC_WB_FIELD3_CLEAR (epdc_v2_base + 0x098)
+#define EPDC_WB_FIELD3_TOGGLE (epdc_v2_base + 0x09C)
+#define EPDC_FIFOCTRL (epdc_v2_base + 0x0A0)
+#define EPDC_FIFOCTRL_SET (epdc_v2_base + 0x0A4)
+#define EPDC_FIFOCTRL_CLEAR (epdc_v2_base + 0x0A8)
+#define EPDC_FIFOCTRL_TOGGLE (epdc_v2_base + 0x0AC)
+#define EPDC_UPD_ADDR (epdc_v2_base + 0x100)
+#define EPDC_UPD_STRIDE (epdc_v2_base + 0x110)
+#define EPDC_UPD_CORD (epdc_v2_base + 0x120)
+#define EPDC_UPD_SIZE (epdc_v2_base + 0x140)
+#define EPDC_UPD_CTRL (epdc_v2_base + 0x160)
+#define EPDC_UPD_FIXED (epdc_v2_base + 0x180)
+#define EPDC_TEMP (epdc_v2_base + 0x1A0)
+#define EPDC_AUTOWV_LUT (epdc_v2_base + 0x1C0)
+#define EPDC_LUT_STANDBY1 (epdc_v2_base + 0x1E0)
+#define EPDC_LUT_STANDBY1_SET (epdc_v2_base + 0x1E4)
+#define EPDC_LUT_STANDBY1_CLEAR (epdc_v2_base + 0x1E8)
+#define EPDC_LUT_STANDBY1_TOGGLE (epdc_v2_base + 0x1EC)
+#define EPDC_LUT_STANDBY2 (epdc_v2_base + 0x1F0)
+#define EPDC_LUT_STANDBY2_SET (epdc_v2_base + 0x1F4)
+#define EPDC_LUT_STANDBY2_CLEAR (epdc_v2_base + 0x1F8)
+#define EPDC_LUT_STANDBY2_TOGGLE (epdc_v2_base + 0x1FC)
+#define EPDC_TCE_CTRL (epdc_v2_base + 0x200)
+#define EPDC_TCE_SDCFG (epdc_v2_base + 0x220)
+#define EPDC_TCE_GDCFG (epdc_v2_base + 0x240)
+#define EPDC_TCE_HSCAN1 (epdc_v2_base + 0x260)
+#define EPDC_TCE_HSCAN2 (epdc_v2_base + 0x280)
+#define EPDC_TCE_VSCAN (epdc_v2_base + 0x2A0)
+#define EPDC_TCE_OE (epdc_v2_base + 0x2C0)
+#define EPDC_TCE_POLARITY (epdc_v2_base + 0x2E0)
+#define EPDC_TCE_TIMING1 (epdc_v2_base + 0x300)
+#define EPDC_TCE_TIMING2 (epdc_v2_base + 0x310)
+#define EPDC_TCE_TIMING3 (epdc_v2_base + 0x320)
+#define EPDC_PIGEON_CTRL0 (epdc_v2_base + 0x380)
+#define EPDC_PIGEON_CTRL1 (epdc_v2_base + 0x390)
+#define EPDC_IRQ_MASK1 (epdc_v2_base + 0x3C0)
+#define EPDC_IRQ_MASK1_SET (epdc_v2_base + 0x3C4)
+#define EPDC_IRQ_MASK1_CLEAR (epdc_v2_base + 0x3C8)
+#define EPDC_IRQ_MASK1_TOGGLE (epdc_v2_base + 0x3CC)
+#define EPDC_IRQ_MASK2 (epdc_v2_base + 0x3D0)
+#define EPDC_IRQ_MASK2_SET (epdc_v2_base + 0x3D4)
+#define EPDC_IRQ_MASK2_CLEAR (epdc_v2_base + 0x3D8)
+#define EPDC_IRQ_MASK2_TOGGLE (epdc_v2_base + 0x3DC)
+#define EPDC_IRQ1 (epdc_v2_base + 0x3E0)
+#define EPDC_IRQ1_SET (epdc_v2_base + 0x3E4)
+#define EPDC_IRQ1_CLEAR (epdc_v2_base + 0x3E8)
+#define EPDC_IRQ1_TOGGLE (epdc_v2_base + 0x3EC)
+#define EPDC_IRQ2 (epdc_v2_base + 0x3F0)
+#define EPDC_IRQ2_SET (epdc_v2_base + 0x3F4)
+#define EPDC_IRQ2_CLEAR (epdc_v2_base + 0x3F8)
+#define EPDC_IRQ2_TOGGLE (epdc_v2_base + 0x3FC)
+#define EPDC_IRQ_MASK (epdc_v2_base + 0x400)
+#define EPDC_IRQ_MASK_SET (epdc_v2_base + 0x404)
+#define EPDC_IRQ_MASK_CLEAR (epdc_v2_base + 0x408)
+#define EPDC_IRQ_MASK_TOGGLE (epdc_v2_base + 0x40C)
+#define EPDC_IRQ (epdc_v2_base + 0x420)
+#define EPDC_IRQ_SET (epdc_v2_base + 0x424)
+#define EPDC_IRQ_CLEAR (epdc_v2_base + 0x428)
+#define EPDC_IRQ_TOGGLE (epdc_v2_base + 0x42C)
+#define EPDC_STATUS_LUTS (epdc_v2_base + 0x440)
+#define EPDC_STATUS_LUTS_SET (epdc_v2_base + 0x444)
+#define EPDC_STATUS_LUTS_CLEAR (epdc_v2_base + 0x448)
+#define EPDC_STATUS_LUTS_TOGGLE (epdc_v2_base + 0x44C)
+#define EPDC_STATUS_LUTS2 (epdc_v2_base + 0x450)
+#define EPDC_STATUS_LUTS2_SET (epdc_v2_base + 0x454)
+#define EPDC_STATUS_LUTS2_CLEAR (epdc_v2_base + 0x458)
+#define EPDC_STATUS_LUTS2_TOGGLE (epdc_v2_base + 0x45C)
+#define EPDC_STATUS_NEXTLUT (epdc_v2_base + 0x460)
+#define EPDC_STATUS_COL (epdc_v2_base + 0x480)
+#define EPDC_STATUS_COL2 (epdc_v2_base + 0x490)
+#define EPDC_STATUS (epdc_v2_base + 0x4A0)
+#define EPDC_STATUS_SET (epdc_v2_base + 0x4A4)
+#define EPDC_STATUS_CLEAR (epdc_v2_base + 0x4A8)
+#define EPDC_STATUS_TOGGLE (epdc_v2_base + 0x4AC)
+#define EPDC_UPD_COL_CORD (epdc_v2_base + 0x4C0)
+#define EPDC_UPD_COL_SIZE (epdc_v2_base + 0x4E0)
+#define EPDC_DEBUG (epdc_v2_base + 0x500)
+#define EPDC_DEBUG_LUT (epdc_v2_base + 0x530)
+#define EPDC_HIST1_PARAM (epdc_v2_base + 0x600)
+#define EPDC_HIST2_PARAM (epdc_v2_base + 0x610)
+#define EPDC_HIST4_PARAM (epdc_v2_base + 0x620)
+#define EPDC_HIST8_PARAM0 (epdc_v2_base + 0x630)
+#define EPDC_HIST8_PARAM1 (epdc_v2_base + 0x640)
+#define EPDC_HIST16_PARAM0 (epdc_v2_base + 0x650)
+#define EPDC_HIST16_PARAM1 (epdc_v2_base + 0x660)
+#define EPDC_HIST16_PARAM2 (epdc_v2_base + 0x670)
+#define EPDC_HIST16_PARAM3 (epdc_v2_base + 0x680)
+#define EPDC_GPIO (epdc_v2_base + 0x700)
+#define EPDC_VERSION (epdc_v2_base + 0x7F0)
+#define EPDC_PIGEON_0_0 (epdc_v2_base + 0x800)
+#define EPDC_PIGEON_0_1 (epdc_v2_base + 0x810)
+#define EPDC_PIGEON_0_2 (epdc_v2_base + 0x820)
+#define EPDC_PIGEON_1_0 (epdc_v2_base + 0x840)
+#define EPDC_PIGEON_1_1 (epdc_v2_base + 0x850)
+#define EPDC_PIGEON_1_2 (epdc_v2_base + 0x860)
+#define EPDC_PIGEON_2_0 (epdc_v2_base + 0x880)
+#define EPDC_PIGEON_2_1 (epdc_v2_base + 0x890)
+#define EPDC_PIGEON_2_2 (epdc_v2_base + 0x8A0)
+#define EPDC_PIGEON_3_0 (epdc_v2_base + 0x8C0)
+#define EPDC_PIGEON_3_1 (epdc_v2_base + 0x8D0)
+#define EPDC_PIGEON_3_2 (epdc_v2_base + 0x8E0)
+#define EPDC_PIGEON_4_0 (epdc_v2_base + 0x900)
+#define EPDC_PIGEON_4_1 (epdc_v2_base + 0x910)
+#define EPDC_PIGEON_4_2 (epdc_v2_base + 0x920)
+#define EPDC_PIGEON_5_0 (epdc_v2_base + 0x940)
+#define EPDC_PIGEON_5_1 (epdc_v2_base + 0x950)
+#define EPDC_PIGEON_5_2 (epdc_v2_base + 0x960)
+#define EPDC_PIGEON_6_0 (epdc_v2_base + 0x980)
+#define EPDC_PIGEON_6_1 (epdc_v2_base + 0x990)
+#define EPDC_PIGEON_6_2 (epdc_v2_base + 0x9A0)
+#define EPDC_PIGEON_7_0 (epdc_v2_base + 0x9C0)
+#define EPDC_PIGEON_7_1 (epdc_v2_base + 0x9D0)
+#define EPDC_PIGEON_7_2 (epdc_v2_base + 0x9E0)
+#define EPDC_PIGEON_8_0 (epdc_v2_base + 0xA00)
+#define EPDC_PIGEON_8_1 (epdc_v2_base + 0xA10)
+#define EPDC_PIGEON_8_2 (epdc_v2_base + 0xA20)
+#define EPDC_PIGEON_9_0 (epdc_v2_base + 0xA40)
+#define EPDC_PIGEON_9_1 (epdc_v2_base + 0xA50)
+#define EPDC_PIGEON_9_2 (epdc_v2_base + 0xA60)
+#define EPDC_PIGEON_10_0 (epdc_v2_base + 0xA80)
+#define EPDC_PIGEON_10_1 (epdc_v2_base + 0xA90)
+#define EPDC_PIGEON_10_2 (epdc_v2_base + 0xAA0)
+#define EPDC_PIGEON_11_0 (epdc_v2_base + 0xAC0)
+#define EPDC_PIGEON_11_1 (epdc_v2_base + 0xAD0)
+#define EPDC_PIGEON_11_2 (epdc_v2_base + 0xAE0)
+#define EPDC_PIGEON_12_0 (epdc_v2_base + 0xB00)
+#define EPDC_PIGEON_12_1 (epdc_v2_base + 0xB10)
+#define EPDC_PIGEON_12_2 (epdc_v2_base + 0xB20)
+#define EPDC_PIGEON_13_0 (epdc_v2_base + 0xB40)
+#define EPDC_PIGEON_13_1 (epdc_v2_base + 0xB50)
+#define EPDC_PIGEON_13_2 (epdc_v2_base + 0xB60)
+#define EPDC_PIGEON_14_0 (epdc_v2_base + 0xB80)
+#define EPDC_PIGEON_14_1 (epdc_v2_base + 0xB90)
+#define EPDC_PIGEON_14_2 (epdc_v2_base + 0xBA0)
+#define EPDC_PIGEON_15_0 (epdc_v2_base + 0xBC0)
+#define EPDC_PIGEON_15_1 (epdc_v2_base + 0xBD0)
+#define EPDC_PIGEON_15_2 (epdc_v2_base + 0xBE0)
+#define EPDC_PIGEON_16_0 (epdc_v2_base + 0xC00)
+#define EPDC_PIGEON_16_1 (epdc_v2_base + 0xC10)
+#define EPDC_PIGEON_16_2 (epdc_v2_base + 0xC20)
+#define EPDC_WB_ADDR_TCE (epdc_v2_base + 0x010)
+
+/*
+ * Register field definitions
+ */
+
+enum {
+/* EPDC_CTRL field values */
+ EPDC_CTRL_SFTRST = 0x80000000,
+ EPDC_CTRL_CLKGATE = 0x40000000,
+ EPDC_CTRL_SRAM_POWERDOWN = 0x100,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_MASK = 0xC0,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP = 0,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_ALL_BYTES_SWAP = 0x40,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_HWD_SWAP = 0x80,
+ EPDC_CTRL_UPD_DATA_SWIZZLE_HWD_BYTE_SWAP = 0xC0,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_MASK = 0x30,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP = 0,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_ALL_BYTES_SWAP = 0x10,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_HWD_SWAP = 0x20,
+ EPDC_CTRL_LUT_DATA_SWIZZLE_HWD_BYTE_SWAP = 0x30,
+ EPDC_CTRL_BURST_LEN_8_8 = 0x1,
+ EPDC_CTRL_BURST_LEN_8_16 = 0,
+
+/* EPDC_RES field values */
+ EPDC_RES_VERTICAL_MASK = 0x1FFF0000,
+ EPDC_RES_VERTICAL_OFFSET = 16,
+ EPDC_RES_HORIZONTAL_MASK = 0x1FFF,
+ EPDC_RES_HORIZONTAL_OFFSET = 0,
+
+/* EPDC_FORMAT field values */
+ EPDC_FORMAT_BUF_PIXEL_SCALE_ROUND = 0x1000000,
+ EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK = 0xFF0000,
+ EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET = 16,
+ EPDC_FORMAT_WB_ADDR_NO_COPY = 0x4000,
+ EPDC_FORMAT_WB_TYPE_MASK = 0x3000,
+ EPDC_FORMAT_WB_TYPE_OFFSET = 12,
+ EPDC_FORMAT_WB_TYPE_WB_INTERNAL = 0x0,
+ EPDC_FORMAT_WB_TYPE_WB_WAVEFORM = 0x1000,
+ EPDC_FORMAT_WB_TYPE_WB_EXTERNAL16 = 0x2000,
+ EPDC_FORMAT_WB_TYPE_WB_EXTERNAL32 = 0x3000,
+ EPDC_FORMAT_WB_COMPRESS = 0x800,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_MASK = 0x700,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P2N = 0x200,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P3N = 0x300,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N = 0x400,
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N = 0x500,
+ EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT = 0x0,
+ EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT_VCOM = 0x1,
+ EPDC_FORMAT_TFT_PIXEL_FORMAT_4BIT = 0x2,
+ EPDC_FORMAT_TFT_PIXEL_FORMAT_4BIT_VCOM = 0x3,
+
+/* EPDC_WB_FIELD field values */
+ EPDC_WB_FIELD_FIXED_MASK = 0xFF000000,
+ EPDC_WB_FIELD_FIXED_OFFSET = 24,
+ EPDC_WB_FIELD_USE_FIXED_MASK = 0x30000,
+ EPDC_WB_FIELD_USE_FIXED_OFFSET = 16,
+ EPDC_WB_FIELD_USE_FIXED_NO_FIXED = 0x0,
+ EPDC_WB_FIELD_USE_FIXED_USE_FIXED = 0x1,
+ EPDC_WB_FIELD_USE_FIXED_NE_FIXED = 0x2,
+ EPDC_WB_FIELD_USE_FIXED_EQ_FIXED = 0x3,
+ EPDC_WB_FIELD_USAGE_MASK = 0xE000,
+ EPDC_WB_FIELD_USAGE_OFFSET = 13,
+ EPDC_WB_FIELD_USAGE_NOT_USED = 0x0,
+ EPDC_WB_FIELD_USAGE_PARTIAL = 0x3,
+ EPDC_WB_FIELD_USAGE_LUT = 0x4,
+ EPDC_WB_FIELD_USAGE_CP = 0x5,
+ EPDC_WB_FIELD_USAGE_NP = 0x6,
+ EPDC_WB_FIELD_USAGE_PTS = 0x7,
+ EPDC_WB_FIELD_FROM_MASK = 0x1F00,
+ EPDC_WB_FIELD_FROM_OFFSET = 8,
+ EPDC_WB_FIELD_TO_MASK = 0xF0,
+ EPDC_WB_FIELD_TO_OFFSET = 4,
+ EPDC_WB_FIELD_LEN_MASK = 0xF,
+ EPDC_WB_FIELD_LEN_OFFSET = 0,
+
+/* EPDC_FIFOCTRL field values */
+ EPDC_FIFOCTRL_ENABLE_PRIORITY = 0x80000000,
+ EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK = 0xFF0000,
+ EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET = 16,
+ EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK = 0xFF00,
+ EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET = 8,
+ EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK = 0xFF,
+ EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET = 0,
+
+/* EPDC_UPD_CORD field values */
+ EPDC_UPD_CORD_YCORD_MASK = 0x1FFF0000,
+ EPDC_UPD_CORD_YCORD_OFFSET = 16,
+ EPDC_UPD_CORD_XCORD_MASK = 0x1FFF,
+ EPDC_UPD_CORD_XCORD_OFFSET = 0,
+
+/* EPDC_UPD_SIZE field values */
+ EPDC_UPD_SIZE_HEIGHT_MASK = 0x1FFF0000,
+ EPDC_UPD_SIZE_HEIGHT_OFFSET = 16,
+ EPDC_UPD_SIZE_WIDTH_MASK = 0x1FFF,
+ EPDC_UPD_SIZE_WIDTH_OFFSET = 0,
+
+/* EPDC_UPD_CTRL field values */
+ EPDC_UPD_CTRL_USE_FIXED = 0x80000000,
+ EPDC_UPD_CTRL_LUT_SEL_MASK = 0x3F0000,
+ EPDC_UPD_CTRL_LUT_SEL_OFFSET = 16,
+ EPDC_UPD_CTRL_WAVEFORM_MODE_MASK = 0xFF00,
+ EPDC_UPD_CTRL_WAVEFORM_MODE_OFFSET = 8,
+ EPDC_UPD_CTRL_NO_LUT_CANCEL = 0x10,
+ EPDC_UPD_CTRL_AUTOWV_PAUSE = 0x8,
+ EPDC_UPD_CTRL_AUTOWV = 0x4,
+ EPDC_UPD_CTRL_DRY_RUN = 0x2,
+ EPDC_UPD_CTRL_UPDATE_MODE_FULL = 0x1,
+
+/* EPDC_UPD_FIXED field values */
+ EPDC_UPD_FIXED_FIXNP_EN = 0x80000000,
+ EPDC_UPD_FIXED_FIXCP_EN = 0x40000000,
+ EPDC_UPD_FIXED_FIXNP_MASK = 0xFF00,
+ EPDC_UPD_FIXED_FIXNP_OFFSET = 8,
+ EPDC_UPD_FIXED_FIXCP_MASK = 0xFF,
+ EPDC_UPD_FIXED_FIXCP_OFFSET = 0,
+
+/* EPDC_AUTOWV_LUT field values */
+ EPDC_AUTOWV_LUT_DATA_MASK = 0xFF0000,
+ EPDC_AUTOWV_LUT_DATA_OFFSET = 16,
+ EPDC_AUTOWV_LUT_ADDR_MASK = 0x7,
+ EPDC_AUTOWV_LUT_ADDR_OFFSET = 0,
+
+/* EPDC_TCE_CTRL field values */
+ EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK = 0x1FF0000,
+ EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET = 16,
+ EPDC_TCE_CTRL_VCOM_VAL_MASK = 0xC00,
+ EPDC_TCE_CTRL_VCOM_VAL_OFFSET = 10,
+ EPDC_TCE_CTRL_VCOM_MODE_AUTO = 0x200,
+ EPDC_TCE_CTRL_VCOM_MODE_MANUAL = 0x000,
+ EPDC_TCE_CTRL_DDR_MODE_ENABLE = 0x100,
+ EPDC_TCE_CTRL_LVDS_MODE_CE_ENABLE = 0x80,
+ EPDC_TCE_CTRL_LVDS_MODE_ENABLE = 0x40,
+ EPDC_TCE_CTRL_SCAN_DIR_1_UP = 0x20,
+ EPDC_TCE_CTRL_SCAN_DIR_0_UP = 0x10,
+ EPDC_TCE_CTRL_DUAL_SCAN_ENABLE = 0x8,
+ EPDC_TCE_CTRL_SDDO_WIDTH_16BIT = 0x4,
+ EPDC_TCE_CTRL_PIXELS_PER_SDCLK_2 = 1,
+ EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4 = 2,
+ EPDC_TCE_CTRL_PIXELS_PER_SDCLK_8 = 3,
+
+/* EPDC_TCE_SDCFG field values */
+ EPDC_TCE_SDCFG_SDCLK_HOLD = 0x200000,
+ EPDC_TCE_SDCFG_SDSHR = 0x100000,
+ EPDC_TCE_SDCFG_NUM_CE_MASK = 0xF0000,
+ EPDC_TCE_SDCFG_NUM_CE_OFFSET = 16,
+ EPDC_TCE_SDCFG_SDDO_REFORMAT_STANDARD = 0,
+ EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS = 0x4000,
+ EPDC_TCE_SDCFG_SDDO_INVERT_ENABLE = 0x2000,
+ EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK = 0x1FFF,
+ EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET = 0,
+
+/* EPDC_TCE_GDCFG field values */
+ EPDC_TCE_SDCFG_GDRL = 0x10,
+ EPDC_TCE_SDCFG_GDOE_MODE_DELAYED_GDCLK = 0x2,
+ EPDC_TCE_SDCFG_GDSP_MODE_FRAME_SYNC = 0x1,
+ EPDC_TCE_SDCFG_GDSP_MODE_ONE_LINE = 0x0,
+
+/* EPDC_TCE_HSCAN1 field values */
+ EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK = 0xFFF0000,
+ EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET = 16,
+ EPDC_TCE_HSCAN1_LINE_SYNC_MASK = 0xFFF,
+ EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET = 0,
+
+/* EPDC_TCE_HSCAN2 field values */
+ EPDC_TCE_HSCAN2_LINE_END_MASK = 0xFFF0000,
+ EPDC_TCE_HSCAN2_LINE_END_OFFSET = 16,
+ EPDC_TCE_HSCAN2_LINE_BEGIN_MASK = 0xFFF,
+ EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET = 0,
+
+/* EPDC_TCE_VSCAN field values */
+ EPDC_TCE_VSCAN_FRAME_END_MASK = 0xFF0000,
+ EPDC_TCE_VSCAN_FRAME_END_OFFSET = 16,
+ EPDC_TCE_VSCAN_FRAME_BEGIN_MASK = 0xFF00,
+ EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET = 8,
+ EPDC_TCE_VSCAN_FRAME_SYNC_MASK = 0xFF,
+ EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET = 0,
+
+/* EPDC_TCE_OE field values */
+ EPDC_TCE_OE_SDOED_WIDTH_MASK = 0xFF000000,
+ EPDC_TCE_OE_SDOED_WIDTH_OFFSET = 24,
+ EPDC_TCE_OE_SDOED_DLY_MASK = 0xFF0000,
+ EPDC_TCE_OE_SDOED_DLY_OFFSET = 16,
+ EPDC_TCE_OE_SDOEZ_WIDTH_MASK = 0xFF00,
+ EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET = 8,
+ EPDC_TCE_OE_SDOEZ_DLY_MASK = 0xFF,
+ EPDC_TCE_OE_SDOEZ_DLY_OFFSET = 0,
+
+/* EPDC_TCE_POLARITY field values */
+ EPDC_TCE_POLARITY_GDSP_POL_ACTIVE_HIGH = 0x10,
+ EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH = 0x8,
+ EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH = 0x4,
+ EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH = 0x2,
+ EPDC_TCE_POLARITY_SDCE_POL_ACTIVE_HIGH = 0x1,
+
+/* EPDC_TCE_TIMING1 field values */
+ EPDC_TCE_TIMING1_SDLE_SHIFT_NONE = 0x00,
+ EPDC_TCE_TIMING1_SDLE_SHIFT_1 = 0x10,
+ EPDC_TCE_TIMING1_SDLE_SHIFT_2 = 0x20,
+ EPDC_TCE_TIMING1_SDLE_SHIFT_3 = 0x30,
+ EPDC_TCE_TIMING1_SDCLK_INVERT = 0x8,
+ EPDC_TCE_TIMING1_SDCLK_SHIFT_NONE = 0,
+ EPDC_TCE_TIMING1_SDCLK_SHIFT_1CYCLE = 1,
+ EPDC_TCE_TIMING1_SDCLK_SHIFT_2CYCLES = 2,
+ EPDC_TCE_TIMING1_SDCLK_SHIFT_3CYCLES = 3,
+
+/* EPDC_TCE_TIMING2 field values */
+ EPDC_TCE_TIMING2_GDCLK_HP_MASK = 0xFFFF0000,
+ EPDC_TCE_TIMING2_GDCLK_HP_OFFSET = 16,
+ EPDC_TCE_TIMING2_GDSP_OFFSET_MASK = 0xFFFF,
+ EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET = 0,
+
+/* EPDC_TCE_TIMING3 field values */
+ EPDC_TCE_TIMING3_GDOE_OFFSET_MASK = 0xFFFF0000,
+ EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET = 16,
+ EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK = 0xFFFF,
+ EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET = 0,
+
+/* EPDC EPDC_PIGEON_CTRL0 field values */
+ EPDC_PIGEON_CTRL0_LD_PERIOD_MASK = 0xFFF0000,
+ EPDC_PIGEON_CTRL0_LD_PERIOD_OFFSET = 16,
+ EPDC_PIGEON_CTRL0_FD_PERIOD_MASK = 0xFFF,
+ EPDC_PIGEON_CTRL0_FD_PERIOD_OFFSET = 0,
+
+/* EPDC EPDC_PIGEON_CTRL1 field values */
+ EPDC_PIGEON_CTRL1_LD_PERIOD_MASK = 0xFFF0000,
+ EPDC_PIGEON_CTRL1_LD_PERIOD_OFFSET = 16,
+ EPDC_PIGEON_CTRL1_FD_PERIOD_MASK = 0xFFF,
+ EPDC_PIGEON_CTRL1_FD_PERIOD_OFFSET = 0,
+
+/* EPDC_IRQ_MASK/EPDC_IRQ field values */
+ EPDC_IRQ_WB_CMPLT_IRQ = 0x10000,
+ EPDC_IRQ_LUT_COL_IRQ = 0x20000,
+ EPDC_IRQ_TCE_UNDERRUN_IRQ = 0x40000,
+ EPDC_IRQ_FRAME_END_IRQ = 0x80000,
+ EPDC_IRQ_BUS_ERROR_IRQ = 0x100000,
+ EPDC_IRQ_TCE_IDLE_IRQ = 0x200000,
+ EPDC_IRQ_UPD_DONE_IRQ = 0x400000,
+ EPDC_IRQ_PWR_IRQ = 0x800000,
+
+/* EPDC_STATUS_NEXTLUT field values */
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_VALID = 0x100,
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_MASK = 0x3F,
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_OFFSET = 0,
+
+/* EPDC_STATUS field values */
+ EPDC_STATUS_HISTOGRAM_CP_MASK = 0x1F0000,
+ EPDC_STATUS_HISTOGRAM_CP_OFFSET = 16,
+ EPDC_STATUS_HISTOGRAM_NP_MASK = 0x1F00,
+ EPDC_STATUS_HISTOGRAM_NP_OFFSET = 8,
+ EPDC_STATUS_UPD_VOID = 0x8,
+ EPDC_STATUS_LUTS_UNDERRUN = 0x4,
+ EPDC_STATUS_LUTS_BUSY = 0x2,
+ EPDC_STATUS_WB_BUSY = 0x1,
+
+/* EPDC_UPD_COL_CORD field values */
+ EPDC_UPD_COL_CORD_YCORD_MASK = 0x1FFF0000,
+ EPDC_UPD_COL_CORD_YCORD_OFFSET = 16,
+ EPDC_UPD_COL_CORD_XCORD_MASK = 0x1FFF,
+ EPDC_UPD_COL_CORD_XCORD_OFFSET = 0,
+
+/* EPDC_UPD_COL_SIZE field values */
+ EPDC_UPD_COL_SIZE_HEIGHT_MASK = 0x1FFF0000,
+ EPDC_UPD_COL_SIZE_HEIGHT_OFFSET = 16,
+ EPDC_UPD_COL_SIZE_WIDTH_MASK = 0x1FFF,
+ EPDC_UPD_COL_SIZE_WIDTH_OFFSET = 0,
+
+/* EPDC_DEBUG field values */
+ EPDC_DEBUG_DEBUG_LUT_SEL_MASK = 0x3F00000,
+ EPDC_DEBUG_DEBUG_LUT_SEL_OFFSET = 24,
+ EPDC_DEBUG_UBW_BURST_LEN_MASK = 0xF000,
+ EPDC_DEBUG_UBW_BURST_LEN_OFFSET = 12,
+ EPDC_DEBUG_UBR_BURST_LEN_MASK = 0xF00,
+ EPDC_DEBUG_UBR_BURST_LEN = 8,
+ EPDC_DEBUG_UPD_BURST_LEN_MASK = 0xF0,
+ EPDC_DEBUG_UPD_BURST_LEN_OFFSET = 4,
+ EPDC_DEBUG_UPDATE_SAME = 0x4,
+ EPDC_DEBUG_UNDERRUN_RECOVER = 0x2,
+ EPDC_DEBUG_COLLISION_OFF = 0x1,
+
+/* EPDC_DEBUG_LUT field values */
+ EPDC_DEBUG_LUT_LUTADDR_MASK = 0x3FF0000,
+ EPDC_DEBUG_LUT_LUTADDR_OFFSET = 16,
+ EPDC_DEBUG_LUT_FRAME_MASK = 0x7FE0,
+ EPDC_DEBUG_LUT_FRAME_OFFSET = 5,
+ EPDC_DEBUG_LUT_STATEMACHINE_MASK = 0x1F,
+ EPDC_DEBUG_LUT_STATEMACHINE_OFFSET = 0,
+
+/* EPDC_HISTx_PARAM field values */
+ EPDC_HIST_PARAM_VALUE0_MASK = 0x1F,
+ EPDC_HIST_PARAM_VALUE0_OFFSET = 0,
+ EPDC_HIST_PARAM_VALUE1_MASK = 0x1F00,
+ EPDC_HIST_PARAM_VALUE1_OFFSET = 8,
+ EPDC_HIST_PARAM_VALUE2_MASK = 0x1F0000,
+ EPDC_HIST_PARAM_VALUE2_OFFSET = 16,
+ EPDC_HIST_PARAM_VALUE3_MASK = 0x1F000000,
+ EPDC_HIST_PARAM_VALUE3_OFFSET = 24,
+ EPDC_HIST_PARAM_VALUE4_MASK = 0x1F,
+ EPDC_HIST_PARAM_VALUE4_OFFSET = 0,
+ EPDC_HIST_PARAM_VALUE5_MASK = 0x1F00,
+ EPDC_HIST_PARAM_VALUE5_OFFSET = 8,
+ EPDC_HIST_PARAM_VALUE6_MASK = 0x1F0000,
+ EPDC_HIST_PARAM_VALUE6_OFFSET = 16,
+ EPDC_HIST_PARAM_VALUE7_MASK = 0x1F000000,
+ EPDC_HIST_PARAM_VALUE7_OFFSET = 24,
+ EPDC_HIST_PARAM_VALUE8_MASK = 0x1F,
+ EPDC_HIST_PARAM_VALUE8_OFFSET = 0,
+ EPDC_HIST_PARAM_VALUE9_MASK = 0x1F00,
+ EPDC_HIST_PARAM_VALUE9_OFFSET = 8,
+ EPDC_HIST_PARAM_VALUE10_MASK = 0x1F0000,
+ EPDC_HIST_PARAM_VALUE10_OFFSET = 16,
+ EPDC_HIST_PARAM_VALUE11_MASK = 0x1F000000,
+ EPDC_HIST_PARAM_VALUE11_OFFSET = 24,
+ EPDC_HIST_PARAM_VALUE12_MASK = 0x1F,
+ EPDC_HIST_PARAM_VALUE12_OFFSET = 0,
+ EPDC_HIST_PARAM_VALUE13_MASK = 0x1F00,
+ EPDC_HIST_PARAM_VALUE13_OFFSET = 8,
+ EPDC_HIST_PARAM_VALUE14_MASK = 0x1F0000,
+ EPDC_HIST_PARAM_VALUE14_OFFSET = 16,
+ EPDC_HIST_PARAM_VALUE15_MASK = 0x1F000000,
+ EPDC_HIST_PARAM_VALUE15_OFFSET = 24,
+
+/* EPDC_GPIO field values */
+ EPDC_GPIO_PWRSTAT = 0x100,
+ EPDC_GPIO_PWRWAKE = 0x80,
+ EPDC_GPIO_PWRCOM = 0x40,
+ EPDC_GPIO_PWRCTRL_MASK = 0x3C,
+ EPDC_GPIO_PWRCTRL_OFFSET = 2,
+ EPDC_GPIO_BDR_MASK = 0x3,
+ EPDC_GPIO_BDR_OFFSET = 0,
+
+/* EPDC_VERSION field values */
+ EPDC_VERSION_MAJOR_MASK = 0xFF000000,
+ EPDC_VERSION_MAJOR_OFFSET = 24,
+ EPDC_VERSION_MINOR_MASK = 0xFF0000,
+ EPDC_VERSION_MINOR_OFFSET = 16,
+ EPDC_VERSION_STEP_MASK = 0xFFFF,
+ EPDC_VERSION_STEP_OFFSET = 0,
+};
+
+#endif /* __EPDC_REGS_INCLUDED__ */
diff --git a/drivers/video/fbdev/mxc/hannstar_cabc.c b/drivers/video/fbdev/mxc/hannstar_cabc.c
new file mode 100644
index 000000000000..14528c8c6511
--- /dev/null
+++ b/drivers/video/fbdev/mxc/hannstar_cabc.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014-2015 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
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+
+#define DRIVER_NAME "hannstar-cabc"
+
+static const struct of_device_id cabc_dt_ids[] = {
+ { .compatible = "hannstar,cabc", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cabc_dt_ids);
+
+static int cabc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node, *pp;
+ int cabc_gpio, ret = 0;
+ bool cabc_enable;
+ unsigned long gpio_flag;
+ enum of_gpio_flags flags;
+
+ for_each_child_of_node(np, pp) {
+ if (!of_find_property(pp, "gpios", NULL)) {
+ dev_warn(&pdev->dev, "Found interface without "
+ "gpios\n");
+ continue;
+ }
+
+ cabc_gpio = of_get_gpio_flags(pp, 0, &flags);
+ if (!gpio_is_valid(cabc_gpio)) {
+ ret = cabc_gpio;
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "Failed to get gpio flags, "
+ "error: %d\n", ret);
+ return ret;
+ }
+
+ cabc_enable = of_property_read_bool(pp, "cabc-enable");
+
+ if (flags & OF_GPIO_ACTIVE_LOW)
+ gpio_flag = cabc_enable ?
+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
+ else
+ gpio_flag = cabc_enable ?
+ GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+
+ devm_gpio_request_one(&pdev->dev, cabc_gpio,
+ gpio_flag, "hannstar-cabc");
+ }
+
+ return ret;
+}
+
+static struct platform_driver cabc_driver = {
+ .probe = cabc_probe,
+ .driver = {
+ .of_match_table = cabc_dt_ids,
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+module_platform_driver(cabc_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Hannstar CABC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/video/fbdev/mxc/ldb.c b/drivers/video/fbdev/mxc/ldb.c
new file mode 100644
index 000000000000..1d6c9e08590c
--- /dev/null
+++ b/drivers/video/fbdev/mxc/ldb.c
@@ -0,0 +1,910 @@
+/*
+ * Copyright (C) 2012-2015 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
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+#include "mxc_dispdrv.h"
+
+#define DRIVER_NAME "ldb"
+
+#define LDB_BGREF_RMODE_INT (0x1 << 15)
+
+#define LDB_DI1_VS_POL_ACT_LOW (0x1 << 10)
+#define LDB_DI0_VS_POL_ACT_LOW (0x1 << 9)
+
+#define LDB_BIT_MAP_CH1_JEIDA (0x1 << 8)
+#define LDB_BIT_MAP_CH0_JEIDA (0x1 << 6)
+
+#define LDB_DATA_WIDTH_CH1_24 (0x1 << 7)
+#define LDB_DATA_WIDTH_CH0_24 (0x1 << 5)
+
+#define LDB_CH1_MODE_MASK (0x3 << 2)
+#define LDB_CH1_MODE_EN_TO_DI1 (0x3 << 2)
+#define LDB_CH1_MODE_EN_TO_DI0 (0x1 << 2)
+#define LDB_CH0_MODE_MASK (0x3 << 0)
+#define LDB_CH0_MODE_EN_TO_DI1 (0x3 << 0)
+#define LDB_CH0_MODE_EN_TO_DI0 (0x1 << 0)
+
+#define LDB_SPLIT_MODE_EN (0x1 << 4)
+
+#define INVALID_BUS_REG (~0UL)
+
+struct crtc_mux {
+ enum crtc crtc;
+ u32 val;
+};
+
+struct bus_mux {
+ int reg;
+ int shift;
+ int mask;
+ int crtc_mux_num;
+ const struct crtc_mux *crtcs;
+};
+
+struct ldb_info {
+ bool split_cap;
+ bool dual_cap;
+ bool ext_bgref_cap;
+ bool clk_fixup;
+ int ctrl_reg;
+ int bus_mux_num;
+ const struct bus_mux *buses;
+};
+
+struct ldb_data;
+
+struct ldb_chan {
+ struct ldb_data *ldb;
+ struct fb_info *fbi;
+ struct videomode vm;
+ enum crtc crtc;
+ int chno;
+ bool is_used;
+ bool online;
+};
+
+struct ldb_data {
+ struct regmap *regmap;
+ struct device *dev;
+ struct mxc_dispdrv_handle *mddh;
+ struct ldb_chan chan[2];
+ int bus_mux_num;
+ const struct bus_mux *buses;
+ int primary_chno;
+ int ctrl_reg;
+ u32 ctrl;
+ bool spl_mode;
+ bool dual_mode;
+ bool clk_fixup;
+ struct clk *di_clk[4];
+ struct clk *ldb_di_clk[2];
+ struct clk *div_3_5_clk[2];
+ struct clk *div_7_clk[2];
+ struct clk *div_sel_clk[2];
+};
+
+static const struct crtc_mux imx6q_lvds0_crtc_mux[] = {
+ {
+ .crtc = CRTC_IPU1_DI0,
+ .val = IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI0,
+ }, {
+ .crtc = CRTC_IPU1_DI1,
+ .val = IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI1,
+ }, {
+ .crtc = CRTC_IPU2_DI0,
+ .val = IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI0,
+ }, {
+ .crtc = CRTC_IPU2_DI1,
+ .val = IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI1,
+ }
+};
+
+static const struct crtc_mux imx6q_lvds1_crtc_mux[] = {
+ {
+ .crtc = CRTC_IPU1_DI0,
+ .val = IMX6Q_GPR3_LVDS1_MUX_CTL_IPU1_DI0,
+ }, {
+ .crtc = CRTC_IPU1_DI1,
+ .val = IMX6Q_GPR3_LVDS1_MUX_CTL_IPU1_DI1,
+ }, {
+ .crtc = CRTC_IPU2_DI0,
+ .val = IMX6Q_GPR3_LVDS1_MUX_CTL_IPU2_DI0,
+ }, {
+ .crtc = CRTC_IPU2_DI1,
+ .val = IMX6Q_GPR3_LVDS1_MUX_CTL_IPU2_DI1,
+ }
+};
+
+static const struct bus_mux imx6q_ldb_buses[] = {
+ {
+ .reg = IOMUXC_GPR3,
+ .shift = 6,
+ .mask = IMX6Q_GPR3_LVDS0_MUX_CTL_MASK,
+ .crtc_mux_num = ARRAY_SIZE(imx6q_lvds0_crtc_mux),
+ .crtcs = imx6q_lvds0_crtc_mux,
+ }, {
+ .reg = IOMUXC_GPR3,
+ .shift = 8,
+ .mask = IMX6Q_GPR3_LVDS1_MUX_CTL_MASK,
+ .crtc_mux_num = ARRAY_SIZE(imx6q_lvds1_crtc_mux),
+ .crtcs = imx6q_lvds1_crtc_mux,
+ }
+};
+
+static const struct ldb_info imx6q_ldb_info = {
+ .split_cap = true,
+ .dual_cap = true,
+ .ext_bgref_cap = false,
+ .clk_fixup = false,
+ .ctrl_reg = IOMUXC_GPR2,
+ .bus_mux_num = ARRAY_SIZE(imx6q_ldb_buses),
+ .buses = imx6q_ldb_buses,
+};
+
+static const struct ldb_info imx6qp_ldb_info = {
+ .split_cap = true,
+ .dual_cap = true,
+ .ext_bgref_cap = false,
+ .clk_fixup = true,
+ .ctrl_reg = IOMUXC_GPR2,
+ .bus_mux_num = ARRAY_SIZE(imx6q_ldb_buses),
+ .buses = imx6q_ldb_buses,
+};
+
+static const struct crtc_mux imx6dl_lvds0_crtc_mux[] = {
+ {
+ .crtc = CRTC_IPU1_DI0,
+ .val = IMX6DL_GPR3_LVDS0_MUX_CTL_IPU1_DI0,
+ }, {
+ .crtc = CRTC_IPU1_DI1,
+ .val = IMX6DL_GPR3_LVDS0_MUX_CTL_IPU1_DI1,
+ }, {
+ .crtc = CRTC_LCDIF1,
+ .val = IMX6DL_GPR3_LVDS0_MUX_CTL_LCDIF,
+ }
+};
+
+static const struct crtc_mux imx6dl_lvds1_crtc_mux[] = {
+ {
+ .crtc = CRTC_IPU1_DI0,
+ .val = IMX6DL_GPR3_LVDS1_MUX_CTL_IPU1_DI0,
+ }, {
+ .crtc = CRTC_IPU1_DI1,
+ .val = IMX6DL_GPR3_LVDS1_MUX_CTL_IPU1_DI1,
+ }, {
+ .crtc = CRTC_LCDIF1,
+ .val = IMX6DL_GPR3_LVDS1_MUX_CTL_LCDIF,
+ }
+};
+
+static const struct bus_mux imx6dl_ldb_buses[] = {
+ {
+ .reg = IOMUXC_GPR3,
+ .shift = 6,
+ .mask = IMX6DL_GPR3_LVDS0_MUX_CTL_MASK,
+ .crtc_mux_num = ARRAY_SIZE(imx6dl_lvds0_crtc_mux),
+ .crtcs = imx6dl_lvds0_crtc_mux,
+ }, {
+ .reg = IOMUXC_GPR3,
+ .shift = 8,
+ .mask = IMX6DL_GPR3_LVDS1_MUX_CTL_MASK,
+ .crtc_mux_num = ARRAY_SIZE(imx6dl_lvds1_crtc_mux),
+ .crtcs = imx6dl_lvds1_crtc_mux,
+ }
+};
+
+static const struct ldb_info imx6dl_ldb_info = {
+ .split_cap = true,
+ .dual_cap = true,
+ .ext_bgref_cap = false,
+ .clk_fixup = false,
+ .ctrl_reg = IOMUXC_GPR2,
+ .bus_mux_num = ARRAY_SIZE(imx6dl_ldb_buses),
+ .buses = imx6dl_ldb_buses,
+};
+
+static const struct crtc_mux imx6sx_lvds_crtc_mux[] = {
+ {
+ .crtc = CRTC_LCDIF1,
+ .val = IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF1,
+ }, {
+ .crtc = CRTC_LCDIF2,
+ .val = IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF2,
+ }
+};
+
+static const struct bus_mux imx6sx_ldb_buses[] = {
+ {
+ .reg = IOMUXC_GPR5,
+ .shift = 3,
+ .mask = IMX6SX_GPR5_DISP_MUX_LDB_CTRL_MASK,
+ .crtc_mux_num = ARRAY_SIZE(imx6sx_lvds_crtc_mux),
+ .crtcs = imx6sx_lvds_crtc_mux,
+ }
+};
+
+static const struct ldb_info imx6sx_ldb_info = {
+ .split_cap = false,
+ .dual_cap = false,
+ .ext_bgref_cap = false,
+ .clk_fixup = false,
+ .ctrl_reg = IOMUXC_GPR6,
+ .bus_mux_num = ARRAY_SIZE(imx6sx_ldb_buses),
+ .buses = imx6sx_ldb_buses,
+};
+
+static const struct crtc_mux imx53_lvds0_crtc_mux[] = {
+ { .crtc = CRTC_IPU1_DI0, },
+};
+
+static const struct crtc_mux imx53_lvds1_crtc_mux[] = {
+ { .crtc = CRTC_IPU1_DI1, }
+};
+
+static const struct bus_mux imx53_ldb_buses[] = {
+ {
+ .reg = INVALID_BUS_REG,
+ .crtc_mux_num = ARRAY_SIZE(imx53_lvds0_crtc_mux),
+ .crtcs = imx53_lvds0_crtc_mux,
+ }, {
+ .reg = INVALID_BUS_REG,
+ .crtc_mux_num = ARRAY_SIZE(imx53_lvds1_crtc_mux),
+ .crtcs = imx53_lvds1_crtc_mux,
+ }
+};
+
+static const struct ldb_info imx53_ldb_info = {
+ .split_cap = true,
+ .dual_cap = false,
+ .ext_bgref_cap = true,
+ .clk_fixup = false,
+ .ctrl_reg = IOMUXC_GPR2,
+ .bus_mux_num = ARRAY_SIZE(imx53_ldb_buses),
+ .buses = imx53_ldb_buses,
+};
+
+static const struct of_device_id ldb_dt_ids[] = {
+ { .compatible = "fsl,imx6qp-ldb", .data = &imx6qp_ldb_info, },
+ { .compatible = "fsl,imx6q-ldb", .data = &imx6q_ldb_info, },
+ { .compatible = "fsl,imx6dl-ldb", .data = &imx6dl_ldb_info, },
+ { .compatible = "fsl,imx6sx-ldb", .data = &imx6sx_ldb_info, },
+ { .compatible = "fsl,imx53-ldb", .data = &imx53_ldb_info, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ldb_dt_ids);
+
+static int ldb_init(struct mxc_dispdrv_handle *mddh,
+ struct mxc_dispdrv_setting *setting)
+{
+ struct ldb_data *ldb = mxc_dispdrv_getdata(mddh);
+ struct device *dev = ldb->dev;
+ struct fb_info *fbi = setting->fbi;
+ struct ldb_chan *chan;
+ struct fb_videomode fb_vm;
+ int chno;
+
+ chno = ldb->chan[ldb->primary_chno].is_used ?
+ !ldb->primary_chno : ldb->primary_chno;
+
+ chan = &ldb->chan[chno];
+
+ if (chan->is_used) {
+ dev_err(dev, "LVDS channel%d is already used\n", chno);
+ return -EBUSY;
+ }
+ if (!chan->online) {
+ dev_err(dev, "LVDS channel%d is not online\n", chno);
+ return -ENODEV;
+ }
+
+ chan->is_used = true;
+
+ chan->fbi = fbi;
+
+ fb_videomode_from_videomode(&chan->vm, &fb_vm);
+ fb_videomode_to_var(&fbi->var, &fb_vm);
+
+ setting->crtc = chan->crtc;
+
+ return 0;
+}
+
+static int get_di_clk_id(struct ldb_chan chan, int *id)
+{
+ struct ldb_data *ldb = chan.ldb;
+ int i = 0, chno = chan.chno, mask, shift;
+ enum crtc crtc;
+ u32 val;
+
+ /* no pre-muxing, such as mx53 */
+ if (ldb->buses[chno].reg == INVALID_BUS_REG) {
+ *id = chno;
+ return 0;
+ }
+
+ for (; i < ldb->buses[chno].crtc_mux_num; i++) {
+ crtc = ldb->buses[chno].crtcs[i].crtc;
+ val = ldb->buses[chno].crtcs[i].val;
+ mask = ldb->buses[chno].mask;
+ shift = ldb->buses[chno].shift;
+ if (chan.crtc == crtc) {
+ *id = (val & mask) >> shift;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int get_mux_val(struct bus_mux bus_mux, enum crtc crtc,
+ u32 *mux_val)
+{
+ int i = 0;
+
+ for (; i < bus_mux.crtc_mux_num; i++)
+ if (bus_mux.crtcs[i].crtc == crtc) {
+ *mux_val = bus_mux.crtcs[i].val;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int find_ldb_chno(struct ldb_data *ldb,
+ struct fb_info *fbi, int *chno)
+{
+ struct device *dev = ldb->dev;
+ int i = 0;
+
+ for (; i < 2; i++)
+ if (ldb->chan[i].fbi == fbi) {
+ *chno = ldb->chan[i].chno;
+ return 0;
+ }
+ dev_err(dev, "failed to find channel number\n");
+ return -EINVAL;
+}
+
+static void ldb_disable(struct mxc_dispdrv_handle *mddh,
+ struct fb_info *fbi);
+
+static int ldb_setup(struct mxc_dispdrv_handle *mddh,
+ struct fb_info *fbi)
+{
+ struct ldb_data *ldb = mxc_dispdrv_getdata(mddh);
+ struct ldb_chan chan;
+ struct device *dev = ldb->dev;
+ struct clk *ldb_di_parent, *ldb_di_sel, *ldb_di_sel_parent;
+ struct clk *other_ldb_di_sel = NULL;
+ struct bus_mux bus_mux;
+ int ret = 0, id = 0, chno, other_chno;
+ unsigned long serial_clk;
+ u32 mux_val;
+
+ ret = find_ldb_chno(ldb, fbi, &chno);
+ if (ret < 0)
+ return ret;
+
+ other_chno = chno ? 0 : 1;
+
+ chan = ldb->chan[chno];
+
+ bus_mux = ldb->buses[chno];
+
+ ret = get_di_clk_id(chan, &id);
+ if (ret < 0) {
+ dev_err(dev, "failed to get ch%d di clk id\n",
+ chan.chno);
+ return ret;
+ }
+
+ ret = get_mux_val(bus_mux, chan.crtc, &mux_val);
+ if (ret < 0) {
+ dev_err(dev, "failed to get ch%d mux val\n",
+ chan.chno);
+ return ret;
+ }
+
+
+ if (ldb->clk_fixup) {
+ /*
+ * ldb_di_sel_parent(plls) -> ldb_di_sel -> ldb_di[chno] ->
+ *
+ * -> div_3_5[chno] ->
+ * -> | |-> div_sel[chno] -> di[id]
+ * -> div_7[chno] ->
+ */
+ clk_set_parent(ldb->di_clk[id], ldb->div_sel_clk[chno]);
+ } else {
+ /*
+ * ldb_di_sel_parent(plls) -> ldb_di_sel ->
+ *
+ * -> div_3_5[chno] ->
+ * -> | |-> div_sel[chno] ->
+ * -> div_7[chno] ->
+ *
+ * -> ldb_di[chno] -> di[id]
+ */
+ clk_set_parent(ldb->di_clk[id], ldb->ldb_di_clk[chno]);
+ }
+ ldb_di_parent = ldb->spl_mode ? ldb->div_3_5_clk[chno] :
+ ldb->div_7_clk[chno];
+ clk_set_parent(ldb->div_sel_clk[chno], ldb_di_parent);
+ ldb_di_sel = clk_get_parent(ldb_di_parent);
+ ldb_di_sel_parent = clk_get_parent(ldb_di_sel);
+ serial_clk = ldb->spl_mode ? chan.vm.pixelclock * 7 / 2 :
+ chan.vm.pixelclock * 7;
+ clk_set_rate(ldb_di_sel_parent, serial_clk);
+
+ /*
+ * split mode or dual mode:
+ * clock tree for the other channel
+ */
+ if (ldb->spl_mode) {
+ clk_set_parent(ldb->div_sel_clk[other_chno],
+ ldb->div_3_5_clk[other_chno]);
+ other_ldb_di_sel =
+ clk_get_parent(ldb->div_3_5_clk[other_chno]);;
+ }
+
+ if (ldb->dual_mode) {
+ clk_set_parent(ldb->div_sel_clk[other_chno],
+ ldb->div_7_clk[other_chno]);
+ other_ldb_di_sel =
+ clk_get_parent(ldb->div_7_clk[other_chno]);;
+ }
+
+ if (ldb->spl_mode || ldb->dual_mode)
+ clk_set_parent(other_ldb_di_sel, ldb_di_sel_parent);
+
+ if (!(chan.fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)) {
+ if (ldb->spl_mode && bus_mux.reg == INVALID_BUS_REG)
+ /* no pre-muxing, such as mx53 */
+ ldb->ctrl |= (id == 0 ? LDB_DI0_VS_POL_ACT_LOW :
+ LDB_DI1_VS_POL_ACT_LOW);
+ else
+ ldb->ctrl |= (chno == 0 ? LDB_DI0_VS_POL_ACT_LOW :
+ LDB_DI1_VS_POL_ACT_LOW);
+ }
+
+ if (bus_mux.reg != INVALID_BUS_REG)
+ regmap_update_bits(ldb->regmap, bus_mux.reg,
+ bus_mux.mask, mux_val);
+
+ regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ctrl);
+
+ /* disable channel for correct sequence */
+ ldb_disable(mddh, fbi);
+
+ return ret;
+}
+
+static int ldb_enable(struct mxc_dispdrv_handle *mddh,
+ struct fb_info *fbi)
+{
+ struct ldb_data *ldb = mxc_dispdrv_getdata(mddh);
+ struct ldb_chan chan;
+ struct device *dev = ldb->dev;
+ struct bus_mux bus_mux;
+ int ret = 0, id = 0, chno, other_chno;
+
+ ret = find_ldb_chno(ldb, fbi, &chno);
+ if (ret < 0)
+ return ret;
+
+ chan = ldb->chan[chno];
+
+ bus_mux = ldb->buses[chno];
+
+ if (ldb->spl_mode || ldb->dual_mode) {
+ other_chno = chno ? 0 : 1;
+ clk_prepare_enable(ldb->ldb_di_clk[other_chno]);
+ }
+
+ if ((ldb->spl_mode || ldb->dual_mode) &&
+ bus_mux.reg == INVALID_BUS_REG) {
+ /* no pre-muxing, such as mx53 */
+ ret = get_di_clk_id(chan, &id);
+ if (ret < 0) {
+ dev_err(dev, "failed to get ch%d di clk id\n",
+ chan.chno);
+ return ret;
+ }
+
+ ldb->ctrl |= id ?
+ (LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1) :
+ (LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0);
+ } else {
+ if (ldb->spl_mode || ldb->dual_mode)
+ ldb->ctrl |= LDB_CH0_MODE_EN_TO_DI0 |
+ LDB_CH1_MODE_EN_TO_DI0;
+ else
+ ldb->ctrl |= chno ? LDB_CH1_MODE_EN_TO_DI1 :
+ LDB_CH0_MODE_EN_TO_DI0;
+ }
+
+ regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ctrl);
+ return 0;
+}
+
+static void ldb_disable(struct mxc_dispdrv_handle *mddh,
+ struct fb_info *fbi)
+{
+ struct ldb_data *ldb = mxc_dispdrv_getdata(mddh);
+ int ret, chno, other_chno;
+
+ ret = find_ldb_chno(ldb, fbi, &chno);
+ if (ret < 0)
+ return;
+
+ if (ldb->spl_mode || ldb->dual_mode) {
+ ldb->ctrl &= ~(LDB_CH1_MODE_MASK | LDB_CH0_MODE_MASK);
+ other_chno = chno ? 0 : 1;
+ clk_disable_unprepare(ldb->ldb_di_clk[other_chno]);
+ } else {
+ ldb->ctrl &= ~(chno ? LDB_CH1_MODE_MASK :
+ LDB_CH0_MODE_MASK);
+ }
+
+ regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ctrl);
+ return;
+}
+
+static struct mxc_dispdrv_driver ldb_drv = {
+ .name = DRIVER_NAME,
+ .init = ldb_init,
+ .setup = ldb_setup,
+ .enable = ldb_enable,
+ .disable = ldb_disable
+};
+
+enum {
+ LVDS_BIT_MAP_SPWG,
+ LVDS_BIT_MAP_JEIDA,
+};
+
+static const char *ldb_bit_mappings[] = {
+ [LVDS_BIT_MAP_SPWG] = "spwg",
+ [LVDS_BIT_MAP_JEIDA] = "jeida",
+};
+
+static int of_get_data_mapping(struct device_node *np)
+{
+ const char *bm;
+ int ret, i;
+
+ ret = of_property_read_string(np, "fsl,data-mapping", &bm);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(ldb_bit_mappings); i++)
+ if (!strcasecmp(bm, ldb_bit_mappings[i]))
+ return i;
+
+ return -EINVAL;
+}
+
+static const char *ldb_crtc_mappings[] = {
+ [CRTC_IPU_DI0] = "ipu-di0",
+ [CRTC_IPU_DI1] = "ipu-di1",
+ [CRTC_IPU1_DI0] = "ipu1-di0",
+ [CRTC_IPU1_DI1] = "ipu1-di1",
+ [CRTC_IPU2_DI0] = "ipu2-di0",
+ [CRTC_IPU2_DI1] = "ipu2-di1",
+ [CRTC_LCDIF] = "lcdif",
+ [CRTC_LCDIF1] = "lcdif1",
+ [CRTC_LCDIF2] = "lcdif2",
+};
+
+static enum crtc of_get_crtc_mapping(struct device_node *np)
+{
+ const char *cm;
+ enum crtc i;
+ int ret;
+
+ ret = of_property_read_string(np, "crtc", &cm);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(ldb_crtc_mappings); i++)
+ if (!strcasecmp(cm, ldb_crtc_mappings[i])) {
+ switch (i) {
+ case CRTC_IPU_DI0:
+ i = CRTC_IPU1_DI0;
+ break;
+ case CRTC_IPU_DI1:
+ i = CRTC_IPU1_DI1;
+ break;
+ case CRTC_LCDIF:
+ i = CRTC_LCDIF1;
+ break;
+ default:
+ break;
+ }
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static int mux_count(struct ldb_data *ldb)
+{
+ int i, j, count = 0;
+ bool should_count[CRTC_MAX];
+ enum crtc crtc;
+
+ for (i = 0; i < CRTC_MAX; i++)
+ should_count[i] = true;
+
+ for (i = 0; i < ldb->bus_mux_num; i++) {
+ for (j = 0; j < ldb->buses[i].crtc_mux_num; j++) {
+ crtc = ldb->buses[i].crtcs[j].crtc;
+ if (should_count[crtc]) {
+ count++;
+ should_count[crtc] = false;
+ }
+ }
+ }
+
+ return count;
+}
+
+static bool is_valid_crtc(struct ldb_data *ldb, enum crtc crtc,
+ int chno)
+{
+ int i = 0;
+
+ if (chno > ldb->bus_mux_num - 1)
+ return false;
+
+ for (; i < ldb->buses[chno].crtc_mux_num; i++)
+ if (ldb->buses[chno].crtcs[i].crtc == crtc)
+ return true;
+
+ return false;
+}
+
+static int ldb_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id =
+ of_match_device(ldb_dt_ids, dev);
+ const struct ldb_info *ldb_info =
+ (const struct ldb_info *)of_id->data;
+ struct device_node *np = dev->of_node, *child;
+ struct ldb_data *ldb;
+ bool ext_ref;
+ int i, data_width, mapping, child_count = 0;
+ char clkname[16];
+
+ ldb = devm_kzalloc(dev, sizeof(*ldb), GFP_KERNEL);
+ if (!ldb)
+ return -ENOMEM;
+
+ ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
+ if (IS_ERR(ldb->regmap)) {
+ dev_err(dev, "failed to get parent regmap\n");
+ return PTR_ERR(ldb->regmap);
+ }
+
+ ldb->dev = dev;
+ ldb->bus_mux_num = ldb_info->bus_mux_num;
+ ldb->buses = ldb_info->buses;
+ ldb->ctrl_reg = ldb_info->ctrl_reg;
+ ldb->clk_fixup = ldb_info->clk_fixup;
+ ldb->primary_chno = -1;
+
+ ext_ref = of_property_read_bool(np, "ext-ref");
+ if (!ext_ref && ldb_info->ext_bgref_cap)
+ ldb->ctrl |= LDB_BGREF_RMODE_INT;
+
+ ldb->spl_mode = of_property_read_bool(np, "split-mode");
+ if (ldb->spl_mode) {
+ if (ldb_info->split_cap) {
+ ldb->ctrl |= LDB_SPLIT_MODE_EN;
+ dev_info(dev, "split mode\n");
+ } else {
+ dev_err(dev, "cannot support split mode\n");
+ return -EINVAL;
+ }
+ }
+
+ ldb->dual_mode = of_property_read_bool(np, "dual-mode");
+ if (ldb->dual_mode) {
+ if (ldb_info->dual_cap) {
+ dev_info(dev, "dual mode\n");
+ } else {
+ dev_err(dev, "cannot support dual mode\n");
+ return -EINVAL;
+ }
+ }
+
+ if (ldb->dual_mode && ldb->spl_mode) {
+ dev_err(dev, "cannot support dual mode and split mode "
+ "simultaneously\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < mux_count(ldb); i++) {
+ sprintf(clkname, "di%d_sel", i);
+ ldb->di_clk[i] = devm_clk_get(dev, clkname);
+ if (IS_ERR(ldb->di_clk[i])) {
+ dev_err(dev, "failed to get clk %s\n", clkname);
+ return PTR_ERR(ldb->di_clk[i]);
+ }
+ }
+
+ for_each_child_of_node(np, child) {
+ struct ldb_chan *chan;
+ enum crtc crtc;
+ bool is_primary;
+ int ret;
+
+ ret = of_property_read_u32(child, "reg", &i);
+ if (ret || i < 0 || i > 1 || i >= ldb->bus_mux_num) {
+ dev_err(dev, "wrong LVDS channel number\n");
+ return -EINVAL;
+ }
+
+ if ((ldb->spl_mode || ldb->dual_mode) && i > 0) {
+ dev_warn(dev, "split mode or dual mode, ignoring "
+ "second output\n");
+ continue;
+ }
+
+ if (!of_device_is_available(child))
+ continue;
+
+ if (++child_count > ldb->bus_mux_num) {
+ dev_err(dev, "too many LVDS channels\n");
+ return -EINVAL;
+ }
+
+ chan = &ldb->chan[i];
+ chan->chno = i;
+ chan->ldb = ldb;
+ chan->online = true;
+
+ is_primary = of_property_read_bool(child, "primary");
+
+ if (ldb->bus_mux_num == 1 || (ldb->primary_chno == -1 &&
+ (is_primary || ldb->spl_mode || ldb->dual_mode)))
+ ldb->primary_chno = chan->chno;
+
+ ret = of_property_read_u32(child, "fsl,data-width",
+ &data_width);
+ if (ret || (data_width != 18 && data_width != 24)) {
+ dev_err(dev, "data width not specified or invalid\n");
+ return -EINVAL;
+ }
+
+ mapping = of_get_data_mapping(child);
+ switch (mapping) {
+ case LVDS_BIT_MAP_SPWG:
+ if (data_width == 24) {
+ if (i == 0 || ldb->spl_mode || ldb->dual_mode)
+ ldb->ctrl |= LDB_DATA_WIDTH_CH0_24;
+ if (i == 1 || ldb->spl_mode || ldb->dual_mode)
+ ldb->ctrl |= LDB_DATA_WIDTH_CH1_24;
+ }
+ break;
+ case LVDS_BIT_MAP_JEIDA:
+ if (data_width == 18) {
+ dev_err(dev, "JEIDA only support 24bit\n");
+ return -EINVAL;
+ }
+ if (i == 0 || ldb->spl_mode || ldb->dual_mode)
+ ldb->ctrl |= LDB_DATA_WIDTH_CH0_24 |
+ LDB_BIT_MAP_CH0_JEIDA;
+ if (i == 1 || ldb->spl_mode || ldb->dual_mode)
+ ldb->ctrl |= LDB_DATA_WIDTH_CH1_24 |
+ LDB_BIT_MAP_CH1_JEIDA;
+ break;
+ default:
+ dev_err(dev, "data mapping not specified or invalid\n");
+ return -EINVAL;
+ }
+
+ crtc = of_get_crtc_mapping(child);
+ if (is_valid_crtc(ldb, crtc, chan->chno)) {
+ ldb->chan[i].crtc = crtc;
+ } else {
+ dev_err(dev, "crtc not specified or invalid\n");
+ return -EINVAL;
+ }
+
+ ret = of_get_videomode(child, &chan->vm, 0);
+ if (ret)
+ return -EINVAL;
+
+ sprintf(clkname, "ldb_di%d", i);
+ ldb->ldb_di_clk[i] = devm_clk_get(dev, clkname);
+ if (IS_ERR(ldb->ldb_di_clk[i])) {
+ dev_err(dev, "failed to get clk %s\n", clkname);
+ return PTR_ERR(ldb->ldb_di_clk[i]);
+ }
+
+ sprintf(clkname, "ldb_di%d_div_3_5", i);
+ ldb->div_3_5_clk[i] = devm_clk_get(dev, clkname);
+ if (IS_ERR(ldb->div_3_5_clk[i])) {
+ dev_err(dev, "failed to get clk %s\n", clkname);
+ return PTR_ERR(ldb->div_3_5_clk[i]);
+ }
+
+ sprintf(clkname, "ldb_di%d_div_7", i);
+ ldb->div_7_clk[i] = devm_clk_get(dev, clkname);
+ if (IS_ERR(ldb->div_7_clk[i])) {
+ dev_err(dev, "failed to get clk %s\n", clkname);
+ return PTR_ERR(ldb->div_7_clk[i]);
+ }
+
+ sprintf(clkname, "ldb_di%d_div_sel", i);
+ ldb->div_sel_clk[i] = devm_clk_get(dev, clkname);
+ if (IS_ERR(ldb->div_sel_clk[i])) {
+ dev_err(dev, "failed to get clk %s\n", clkname);
+ return PTR_ERR(ldb->div_sel_clk[i]);
+ }
+ }
+
+ if (child_count == 0) {
+ dev_err(dev, "failed to find valid LVDS channel\n");
+ return -EINVAL;
+ }
+
+ if (ldb->primary_chno == -1) {
+ dev_err(dev, "failed to know primary channel\n");
+ return -EINVAL;
+ }
+
+ ldb->mddh = mxc_dispdrv_register(&ldb_drv);
+ mxc_dispdrv_setdata(ldb->mddh, ldb);
+ dev_set_drvdata(&pdev->dev, ldb);
+
+ return 0;
+}
+
+static int ldb_remove(struct platform_device *pdev)
+{
+ struct ldb_data *ldb = dev_get_drvdata(&pdev->dev);
+
+ mxc_dispdrv_puthandle(ldb->mddh);
+ mxc_dispdrv_unregister(ldb->mddh);
+ return 0;
+}
+
+static struct platform_driver ldb_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = ldb_dt_ids,
+ },
+ .probe = ldb_probe,
+ .remove = ldb_remove,
+};
+
+module_platform_driver(ldb_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("LDB driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/video/fbdev/mxc/mipi_dsi.c b/drivers/video/fbdev/mxc/mipi_dsi.c
new file mode 100644
index 000000000000..68a9bfa2aa9f
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mipi_dsi.c
@@ -0,0 +1,1039 @@
+/*
+ * Copyright (C) 2011-2015 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
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/ipu.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/mipi_dsi.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <linux/backlight.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <video/mipi_display.h>
+
+#include "mipi_dsi.h"
+
+#define DISPDRV_MIPI "mipi_dsi"
+#define ROUND_UP(x) ((x)+1)
+#define NS2PS_RATIO (1000)
+#define NUMBER_OF_CHUNKS (0x8)
+#define NULL_PKT_SIZE (0x8)
+#define PHY_BTA_MAXTIME (0xd00)
+#define PHY_LP2HS_MAXTIME (0x40)
+#define PHY_HS2LP_MAXTIME (0x40)
+#define PHY_STOP_WAIT_TIME (0x20)
+#define DSI_CLKMGR_CFG_CLK_DIV (0x107)
+#define DSI_GEN_PLD_DATA_BUF_ENTRY (0x10)
+#define MIPI_MUX_CTRL(v) (((v) & 0x3) << 4)
+#define MIPI_LCD_SLEEP_MODE_DELAY (120)
+#define MIPI_DSI_REG_RW_TIMEOUT (20)
+#define MIPI_DSI_PHY_TIMEOUT (10)
+
+static struct mipi_dsi_match_lcd mipi_dsi_lcd_db[] = {
+#ifdef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
+ {
+ "TRULY-WVGA",
+ {mipid_hx8369_get_lcd_videomode, mipid_hx8369_lcd_setup}
+ },
+#endif
+ {
+ "", {NULL, NULL}
+ }
+};
+
+struct _mipi_dsi_phy_pll_clk {
+ u32 max_phy_clk;
+ u32 config;
+};
+
+/* configure data for DPHY PLL 27M reference clk out */
+static const struct _mipi_dsi_phy_pll_clk mipi_dsi_phy_pll_clk_table[] = {
+ {1000, 0x74}, /* 950-1000MHz */
+ {950, 0x54}, /* 900-950Mhz */
+ {900, 0x34}, /* 850-900Mhz */
+ {850, 0x14}, /* 800-850MHz */
+ {800, 0x32}, /* 750-800MHz */
+ {750, 0x12}, /* 700-750Mhz */
+ {700, 0x30}, /* 650-700Mhz */
+ {650, 0x10}, /* 600-650MHz */
+ {600, 0x2e}, /* 550-600MHz */
+ {550, 0x0e}, /* 500-550Mhz */
+ {500, 0x2c}, /* 450-500Mhz */
+ {450, 0x0c}, /* 400-450MHz */
+ {400, 0x4a}, /* 360-400MHz */
+ {360, 0x2a}, /* 330-360Mhz */
+ {330, 0x48}, /* 300-330Mhz */
+ {300, 0x28}, /* 270-300MHz */
+ {270, 0x08}, /* 250-270MHz */
+ {250, 0x46}, /* 240-250Mhz */
+ {240, 0x26}, /* 210-240Mhz */
+ {210, 0x06}, /* 200-210MHz */
+ {200, 0x44}, /* 180-200MHz */
+ {180, 0x24}, /* 160-180MHz */
+ {160, 0x04}, /* 150-160MHz */
+};
+
+static int valid_mode(int pixel_fmt)
+{
+ return ((pixel_fmt == IPU_PIX_FMT_RGB24) ||
+ (pixel_fmt == IPU_PIX_FMT_BGR24) ||
+ (pixel_fmt == IPU_PIX_FMT_RGB666) ||
+ (pixel_fmt == IPU_PIX_FMT_RGB565) ||
+ (pixel_fmt == IPU_PIX_FMT_BGR666) ||
+ (pixel_fmt == IPU_PIX_FMT_RGB332));
+}
+
+static inline void mipi_dsi_read_register(struct mipi_dsi_info *mipi_dsi,
+ u32 reg, u32 *val)
+{
+ *val = ioread32(mipi_dsi->mmio_base + reg);
+ dev_dbg(&mipi_dsi->pdev->dev, "read_reg:0x%02x, val:0x%08x.\n",
+ reg, *val);
+}
+
+static inline void mipi_dsi_write_register(struct mipi_dsi_info *mipi_dsi,
+ u32 reg, u32 val)
+{
+ iowrite32(val, mipi_dsi->mmio_base + reg);
+ dev_dbg(&mipi_dsi->pdev->dev, "\t\twrite_reg:0x%02x, val:0x%08x.\n",
+ reg, val);
+}
+
+static int mipi_dsi_pkt_write(struct mipi_dsi_info *mipi_dsi,
+ u8 data_type, const u32 *buf, int len)
+{
+ u32 val;
+ u32 status = 0;
+ int write_len = len;
+ uint32_t timeout = 0;
+
+ if (len) {
+ /* generic long write command */
+ while (len / DSI_GEN_PLD_DATA_BUF_SIZE) {
+ mipi_dsi_write_register(mipi_dsi,
+ MIPI_DSI_GEN_PLD_DATA, *buf);
+ buf++;
+ len -= DSI_GEN_PLD_DATA_BUF_SIZE;
+ mipi_dsi_read_register(mipi_dsi,
+ MIPI_DSI_CMD_PKT_STATUS, &status);
+ while ((status & DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL) ==
+ DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL) {
+ msleep(1);
+ timeout++;
+ if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
+ return -EIO;
+ mipi_dsi_read_register(mipi_dsi,
+ MIPI_DSI_CMD_PKT_STATUS, &status);
+ }
+ }
+ /* write the remainder bytes */
+ if (len > 0) {
+ while ((status & DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL) ==
+ DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL) {
+ msleep(1);
+ timeout++;
+ if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
+ return -EIO;
+ mipi_dsi_read_register(mipi_dsi,
+ MIPI_DSI_CMD_PKT_STATUS, &status);
+ }
+ mipi_dsi_write_register(mipi_dsi,
+ MIPI_DSI_GEN_PLD_DATA, *buf);
+ }
+
+ val = data_type | ((write_len & DSI_GEN_HDR_DATA_MASK)
+ << DSI_GEN_HDR_DATA_SHIFT);
+ } else {
+ /* generic short write command */
+ val = data_type | ((*buf & DSI_GEN_HDR_DATA_MASK)
+ << DSI_GEN_HDR_DATA_SHIFT);
+ }
+
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS, &status);
+ while ((status & DSI_CMD_PKT_STATUS_GEN_CMD_FULL) ==
+ DSI_CMD_PKT_STATUS_GEN_CMD_FULL) {
+ msleep(1);
+ timeout++;
+ if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
+ return -EIO;
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
+ &status);
+ }
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_GEN_HDR, val);
+
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS, &status);
+ while (!((status & DSI_CMD_PKT_STATUS_GEN_CMD_EMPTY) ==
+ DSI_CMD_PKT_STATUS_GEN_CMD_EMPTY) ||
+ !((status & DSI_CMD_PKT_STATUS_GEN_PLD_W_EMPTY) ==
+ DSI_CMD_PKT_STATUS_GEN_PLD_W_EMPTY)) {
+ msleep(1);
+ timeout++;
+ if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
+ return -EIO;
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
+ &status);
+ }
+
+ return 0;
+}
+
+static int mipi_dsi_pkt_read(struct mipi_dsi_info *mipi_dsi,
+ u8 data_type, u32 *buf, int len)
+{
+ u32 val;
+ int read_len = 0;
+ uint32_t timeout = 0;
+
+ if (!len) {
+ mipi_dbg("%s, len = 0 invalid error!\n", __func__);
+ return -EINVAL;
+ }
+
+ val = data_type | ((*buf & DSI_GEN_HDR_DATA_MASK)
+ << DSI_GEN_HDR_DATA_SHIFT);
+ memset(buf, 0, len);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_GEN_HDR, val);
+
+ /* wait for cmd to sent out */
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS, &val);
+ while ((val & DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY) !=
+ DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY) {
+ msleep(1);
+ timeout++;
+ if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
+ return -EIO;
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
+ &val);
+ }
+ /* wait for entire response stroed in FIFO */
+ while ((val & DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY) ==
+ DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY) {
+ msleep(1);
+ timeout++;
+ if (timeout == MIPI_DSI_REG_RW_TIMEOUT)
+ return -EIO;
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
+ &val);
+ }
+
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS, &val);
+ while (!(val & DSI_CMD_PKT_STATUS_GEN_PLD_R_EMPTY)) {
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_GEN_PLD_DATA, buf);
+ read_len += DSI_GEN_PLD_DATA_BUF_SIZE;
+ buf++;
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_PKT_STATUS,
+ &val);
+ if (read_len == (DSI_GEN_PLD_DATA_BUF_ENTRY *
+ DSI_GEN_PLD_DATA_BUF_SIZE))
+ break;
+ }
+
+ if ((len <= read_len) &&
+ ((len + DSI_GEN_PLD_DATA_BUF_SIZE) >= read_len))
+ return 0;
+ else {
+ dev_err(&mipi_dsi->pdev->dev,
+ "actually read_len:%d != len:%d.\n", read_len, len);
+ return -ERANGE;
+ }
+}
+
+static int mipi_dsi_dcs_cmd(struct mipi_dsi_info *mipi_dsi,
+ u8 cmd, const u32 *param, int num)
+{
+ int err = 0;
+ u32 buf[DSI_CMD_BUF_MAXSIZE];
+
+ switch (cmd) {
+ case MIPI_DCS_EXIT_SLEEP_MODE:
+ case MIPI_DCS_ENTER_SLEEP_MODE:
+ case MIPI_DCS_SET_DISPLAY_ON:
+ case MIPI_DCS_SET_DISPLAY_OFF:
+ buf[0] = cmd;
+ err = mipi_dsi_pkt_write(mipi_dsi,
+ MIPI_DSI_DCS_SHORT_WRITE, buf, 0);
+ break;
+
+ default:
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command:0x%x Not supported!\n", cmd);
+ break;
+ }
+
+ return err;
+}
+
+static void mipi_dsi_dphy_init(struct mipi_dsi_info *mipi_dsi,
+ u32 cmd, u32 data)
+{
+ u32 val;
+ u32 timeout = 0;
+
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_IF_CTRL,
+ DSI_PHY_IF_CTRL_RESET);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP, DSI_PWRUP_POWERUP);
+
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 0);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL1,
+ (0x10000 | cmd));
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 2);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 0);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL1, (0 | data));
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 2);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TST_CTRL0, 0);
+ val = DSI_PHY_RSTZ_EN_CLK | DSI_PHY_RSTZ_DISABLE_RST |
+ DSI_PHY_RSTZ_DISABLE_SHUTDOWN;
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_RSTZ, val);
+
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_PHY_STATUS, &val);
+ while ((val & DSI_PHY_STATUS_LOCK) != DSI_PHY_STATUS_LOCK) {
+ msleep(1);
+ timeout++;
+ if (timeout == MIPI_DSI_PHY_TIMEOUT) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "Error: phy lock timeout!\n");
+ break;
+ }
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_PHY_STATUS, &val);
+ }
+ timeout = 0;
+ while ((val & DSI_PHY_STATUS_STOPSTATE_CLK_LANE) !=
+ DSI_PHY_STATUS_STOPSTATE_CLK_LANE) {
+ msleep(1);
+ timeout++;
+ if (timeout == MIPI_DSI_PHY_TIMEOUT) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "Error: phy lock lane timeout!\n");
+ break;
+ }
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_PHY_STATUS, &val);
+ }
+}
+
+static void mipi_dsi_enable_controller(struct mipi_dsi_info *mipi_dsi,
+ bool init)
+{
+ u32 val = 0;
+ u32 lane_byte_clk_period;
+ struct fb_videomode *mode = mipi_dsi->mode;
+ struct mipi_lcd_config *lcd_config = mipi_dsi->lcd_config;
+
+ if (init) {
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
+ DSI_PWRUP_RESET);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_RSTZ,
+ DSI_PHY_RSTZ_RST);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_CLKMGR_CFG,
+ DSI_CLKMGR_CFG_CLK_DIV);
+
+ if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
+ val = DSI_DPI_CFG_VSYNC_ACT_LOW;
+ if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
+ val |= DSI_DPI_CFG_HSYNC_ACT_LOW;
+ if ((mode->sync & FB_SYNC_OE_LOW_ACT))
+ val |= DSI_DPI_CFG_DATAEN_ACT_LOW;
+ if (MIPI_RGB666_LOOSELY == lcd_config->dpi_fmt)
+ val |= DSI_DPI_CFG_EN18LOOSELY;
+ val |= (lcd_config->dpi_fmt & DSI_DPI_CFG_COLORCODE_MASK)
+ << DSI_DPI_CFG_COLORCODE_SHIFT;
+ val |= (lcd_config->virtual_ch & DSI_DPI_CFG_VID_MASK)
+ << DSI_DPI_CFG_VID_SHIFT;
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_DPI_CFG, val);
+
+ val = DSI_PCKHDL_CFG_EN_BTA |
+ DSI_PCKHDL_CFG_EN_ECC_RX |
+ DSI_PCKHDL_CFG_EN_CRC_RX;
+
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PCKHDL_CFG, val);
+
+ val = (mode->xres & DSI_VID_PKT_CFG_VID_PKT_SZ_MASK)
+ << DSI_VID_PKT_CFG_VID_PKT_SZ_SHIFT;
+ val |= (NUMBER_OF_CHUNKS & DSI_VID_PKT_CFG_NUM_CHUNKS_MASK)
+ << DSI_VID_PKT_CFG_NUM_CHUNKS_SHIFT;
+ val |= (NULL_PKT_SIZE & DSI_VID_PKT_CFG_NULL_PKT_SZ_MASK)
+ << DSI_VID_PKT_CFG_NULL_PKT_SZ_SHIFT;
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_VID_PKT_CFG, val);
+
+ /* enable LP mode when TX DCS cmd and enable DSI command mode */
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG,
+ MIPI_DSI_CMD_MODE_CFG_EN_LOWPOWER);
+
+ /* mipi lane byte clk period in ns unit */
+ lane_byte_clk_period = NS2PS_RATIO /
+ (lcd_config->max_phy_clk / BITS_PER_BYTE);
+ val = ROUND_UP(mode->hsync_len * mode->pixclock /
+ NS2PS_RATIO / lane_byte_clk_period)
+ << DSI_TME_LINE_CFG_HSA_TIME_SHIFT;
+ val |= ROUND_UP(mode->left_margin * mode->pixclock /
+ NS2PS_RATIO / lane_byte_clk_period)
+ << DSI_TME_LINE_CFG_HBP_TIME_SHIFT;
+ val |= ROUND_UP((mode->left_margin + mode->right_margin +
+ mode->hsync_len + mode->xres) * mode->pixclock
+ / NS2PS_RATIO / lane_byte_clk_period)
+ << DSI_TME_LINE_CFG_HLINE_TIME_SHIFT;
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_TMR_LINE_CFG, val);
+
+ val = ((mode->vsync_len & DSI_VTIMING_CFG_VSA_LINES_MASK)
+ << DSI_VTIMING_CFG_VSA_LINES_SHIFT);
+ val |= ((mode->upper_margin & DSI_VTIMING_CFG_VBP_LINES_MASK)
+ << DSI_VTIMING_CFG_VBP_LINES_SHIFT);
+ val |= ((mode->lower_margin & DSI_VTIMING_CFG_VFP_LINES_MASK)
+ << DSI_VTIMING_CFG_VFP_LINES_SHIFT);
+ val |= ((mode->yres & DSI_VTIMING_CFG_V_ACT_LINES_MASK)
+ << DSI_VTIMING_CFG_V_ACT_LINES_SHIFT);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_VTIMING_CFG, val);
+
+ val = ((PHY_BTA_MAXTIME & DSI_PHY_TMR_CFG_BTA_TIME_MASK)
+ << DSI_PHY_TMR_CFG_BTA_TIME_SHIFT);
+ val |= ((PHY_LP2HS_MAXTIME & DSI_PHY_TMR_CFG_LP2HS_TIME_MASK)
+ << DSI_PHY_TMR_CFG_LP2HS_TIME_SHIFT);
+ val |= ((PHY_HS2LP_MAXTIME & DSI_PHY_TMR_CFG_HS2LP_TIME_MASK)
+ << DSI_PHY_TMR_CFG_HS2LP_TIME_SHIFT);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_TMR_CFG, val);
+
+ val = (((lcd_config->data_lane_num - 1) &
+ DSI_PHY_IF_CFG_N_LANES_MASK)
+ << DSI_PHY_IF_CFG_N_LANES_SHIFT);
+ val |= ((PHY_STOP_WAIT_TIME & DSI_PHY_IF_CFG_WAIT_TIME_MASK)
+ << DSI_PHY_IF_CFG_WAIT_TIME_SHIFT);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_IF_CFG, val);
+
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_ST0, &val);
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_ST1, &val);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_ERROR_MSK0, 0);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_ERROR_MSK1, 0);
+
+ mipi_dsi_dphy_init(mipi_dsi, DSI_PHY_CLK_INIT_COMMAND,
+ mipi_dsi->dphy_pll_config);
+ } else {
+ mipi_dsi_dphy_init(mipi_dsi, DSI_PHY_CLK_INIT_COMMAND,
+ mipi_dsi->dphy_pll_config);
+ }
+}
+
+static void mipi_dsi_disable_controller(struct mipi_dsi_info *mipi_dsi)
+{
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_IF_CTRL,
+ DSI_PHY_IF_CTRL_RESET);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP, DSI_PWRUP_RESET);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_RSTZ, DSI_PHY_RSTZ_RST);
+}
+
+static irqreturn_t mipi_dsi_irq_handler(int irq, void *data)
+{
+ u32 mask0;
+ u32 mask1;
+ u32 status0;
+ u32 status1;
+ struct mipi_dsi_info *mipi_dsi;
+
+ mipi_dsi = (struct mipi_dsi_info *)data;
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_ST0, &status0);
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_ST1, &status1);
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_MSK0, &mask0);
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_ERROR_MSK1, &mask1);
+
+ if ((status0 & (~mask0)) || (status1 & (~mask1))) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "mipi_dsi IRQ status0:0x%x, status1:0x%x!\n",
+ status0, status1);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static inline void mipi_dsi_set_mode(struct mipi_dsi_info *mipi_dsi,
+ bool cmd_mode)
+{
+ u32 val;
+
+ if (cmd_mode) {
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
+ DSI_PWRUP_RESET);
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG, &val);
+ val |= MIPI_DSI_CMD_MODE_CFG_EN_CMD_MODE;
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG, val);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_VID_MODE_CFG, 0);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
+ DSI_PWRUP_POWERUP);
+ } else {
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
+ DSI_PWRUP_RESET);
+ /* Disable Command mode when tranfering video data */
+ mipi_dsi_read_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG, &val);
+ val &= ~MIPI_DSI_CMD_MODE_CFG_EN_CMD_MODE;
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_CMD_MODE_CFG, val);
+ val = DSI_VID_MODE_CFG_EN | DSI_VID_MODE_CFG_EN_BURSTMODE |
+ DSI_VID_MODE_CFG_EN_LP_MODE;
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_VID_MODE_CFG, val);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PWR_UP,
+ DSI_PWRUP_POWERUP);
+ mipi_dsi_write_register(mipi_dsi, MIPI_DSI_PHY_IF_CTRL,
+ DSI_PHY_IF_CTRL_TX_REQ_CLK_HS);
+ }
+}
+
+static int mipi_dsi_power_on(struct mxc_dispdrv_handle *disp)
+{
+ int err;
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ if (!mipi_dsi->dsi_power_on) {
+ clk_prepare_enable(mipi_dsi->dphy_clk);
+ clk_prepare_enable(mipi_dsi->cfg_clk);
+ mipi_dsi_enable_controller(mipi_dsi, false);
+ mipi_dsi_set_mode(mipi_dsi, false);
+ /* host send pclk/hsync/vsync for two frames before sleep-out */
+ msleep((1000/mipi_dsi->mode->refresh + 1) << 1);
+ mipi_dsi_set_mode(mipi_dsi, true);
+ err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_EXIT_SLEEP_MODE,
+ NULL, 0);
+ if (err) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command sleep-in error!\n");
+ }
+ msleep(MIPI_LCD_SLEEP_MODE_DELAY);
+ mipi_dsi_set_mode(mipi_dsi, false);
+ mipi_dsi->dsi_power_on = 1;
+ }
+
+ return 0;
+}
+
+void mipi_dsi_power_off(struct mxc_dispdrv_handle *disp)
+{
+ int err;
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ if (mipi_dsi->dsi_power_on) {
+ mipi_dsi_set_mode(mipi_dsi, true);
+ err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_ENTER_SLEEP_MODE,
+ NULL, 0);
+ if (err) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command display on error!\n");
+ }
+ /* To allow time for the supply voltages
+ * and clock circuits to stabilize.
+ */
+ msleep(5);
+ /* video stream timing on */
+ mipi_dsi_set_mode(mipi_dsi, false);
+ msleep(MIPI_LCD_SLEEP_MODE_DELAY);
+
+ mipi_dsi_set_mode(mipi_dsi, true);
+ mipi_dsi_disable_controller(mipi_dsi);
+ mipi_dsi->dsi_power_on = 0;
+ clk_disable_unprepare(mipi_dsi->dphy_clk);
+ clk_disable_unprepare(mipi_dsi->cfg_clk);
+ }
+}
+
+static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi,
+ struct mxc_dispdrv_setting *setting)
+{
+ int err;
+ int size;
+ int i;
+ struct fb_videomode *mipi_lcd_modedb;
+ struct fb_videomode mode;
+ struct device *dev = &mipi_dsi->pdev->dev;
+
+ for (i = 0; i < ARRAY_SIZE(mipi_dsi_lcd_db); i++) {
+ if (!strcmp(mipi_dsi->lcd_panel,
+ mipi_dsi_lcd_db[i].lcd_panel)) {
+ mipi_dsi->lcd_callback =
+ &mipi_dsi_lcd_db[i].lcd_callback;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(mipi_dsi_lcd_db)) {
+ dev_err(dev, "failed to find supported lcd panel.\n");
+ return -EINVAL;
+ }
+ /* get the videomode in the order: cmdline->platform data->driver */
+ mipi_dsi->lcd_callback->get_mipi_lcd_videomode(&mipi_lcd_modedb, &size,
+ &mipi_dsi->lcd_config);
+ err = fb_find_mode(&setting->fbi->var, setting->fbi,
+ setting->dft_mode_str,
+ mipi_lcd_modedb, size, NULL,
+ setting->default_bpp);
+ if (err != 1)
+ fb_videomode_to_var(&setting->fbi->var, mipi_lcd_modedb);
+
+ INIT_LIST_HEAD(&setting->fbi->modelist);
+ for (i = 0; i < size; i++) {
+ fb_var_to_videomode(&mode, &setting->fbi->var);
+ if (fb_mode_is_equal(&mode, mipi_lcd_modedb + i)) {
+ err = fb_add_videomode(mipi_lcd_modedb + i,
+ &setting->fbi->modelist);
+ /* Note: only support fb mode from driver */
+ mipi_dsi->mode = mipi_lcd_modedb + i;
+ break;
+ }
+ }
+ if ((err < 0) || (size == i)) {
+ dev_err(dev, "failed to add videomode.\n");
+ return err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mipi_dsi_phy_pll_clk_table); i++) {
+ if (mipi_dsi_phy_pll_clk_table[i].max_phy_clk <
+ mipi_dsi->lcd_config->max_phy_clk)
+ break;
+ }
+ if ((i == ARRAY_SIZE(mipi_dsi_phy_pll_clk_table)) ||
+ (mipi_dsi->lcd_config->max_phy_clk >
+ mipi_dsi_phy_pll_clk_table[0].max_phy_clk)) {
+ dev_err(dev, "failed to find data in"
+ "mipi_dsi_phy_pll_clk_table.\n");
+ return -EINVAL;
+ }
+ mipi_dsi->dphy_pll_config = mipi_dsi_phy_pll_clk_table[--i].config;
+ dev_dbg(dev, "dphy_pll_config:0x%x.\n", mipi_dsi->dphy_pll_config);
+
+ return 0;
+}
+
+static int mipi_dsi_enable(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ int err;
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ if (!mipi_dsi->lcd_inited) {
+ err = clk_prepare_enable(mipi_dsi->dphy_clk);
+ err |= clk_prepare_enable(mipi_dsi->cfg_clk);
+ if (err)
+ dev_err(&mipi_dsi->pdev->dev,
+ "clk enable error:%d!\n", err);
+ mipi_dsi_enable_controller(mipi_dsi, true);
+ err = mipi_dsi->lcd_callback->mipi_lcd_setup(
+ mipi_dsi);
+ if (err < 0) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "failed to init mipi lcd.");
+ clk_disable_unprepare(mipi_dsi->dphy_clk);
+ clk_disable_unprepare(mipi_dsi->cfg_clk);
+ return err;
+ }
+ mipi_dsi_set_mode(mipi_dsi, false);
+ mipi_dsi->dsi_power_on = 1;
+ mipi_dsi->lcd_inited = 1;
+ }
+ mipi_dsi_power_on(mipi_dsi->disp_mipi);
+
+ return 0;
+}
+
+static void mipi_dsi_disable(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ mipi_dsi_power_off(mipi_dsi->disp_mipi);
+}
+
+static int mipi_dsi_disp_init(struct mxc_dispdrv_handle *disp,
+ struct mxc_dispdrv_setting *setting)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+ struct device *dev = &mipi_dsi->pdev->dev;
+ int ret = 0;
+
+ if (!valid_mode(setting->if_fmt)) {
+ dev_warn(dev, "Input pixel format not valid"
+ "use default RGB24\n");
+ setting->if_fmt = IPU_PIX_FMT_RGB24;
+ }
+
+ ret = ipu_di_to_crtc(dev, mipi_dsi->dev_id,
+ mipi_dsi->disp_id, &setting->crtc);
+ if (ret < 0)
+ return ret;
+
+ ret = mipi_dsi_lcd_init(mipi_dsi, setting);
+ if (ret) {
+ dev_err(dev, "failed to init mipi dsi lcd\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "MIPI DSI dispdrv inited!\n");
+ return ret;
+}
+
+static void mipi_dsi_disp_deinit(struct mxc_dispdrv_handle *disp)
+{
+ struct mipi_dsi_info *mipi_dsi;
+
+ mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ mipi_dsi_power_off(mipi_dsi->disp_mipi);
+ if (mipi_dsi->bl)
+ backlight_device_unregister(mipi_dsi->bl);
+}
+
+static int mipi_dsi_setup(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+ int xres_virtual = fbi->var.xres_virtual;
+ int yres_virtual = fbi->var.yres_virtual;
+ int xoffset = fbi->var.xoffset;
+ int yoffset = fbi->var.yoffset;
+ int pixclock = fbi->var.pixclock;
+
+ if (!mipi_dsi->mode)
+ return 0;
+
+ /* set the mode back to var in case userspace changes it */
+ fb_videomode_to_var(&fbi->var, mipi_dsi->mode);
+
+ /* restore some var entries cached */
+ fbi->var.xres_virtual = xres_virtual;
+ fbi->var.yres_virtual = yres_virtual;
+ fbi->var.xoffset = xoffset;
+ fbi->var.yoffset = yoffset;
+ fbi->var.pixclock = pixclock;
+ return 0;
+}
+
+static struct mxc_dispdrv_driver mipi_dsi_drv = {
+ .name = DISPDRV_MIPI,
+ .init = mipi_dsi_disp_init,
+ .deinit = mipi_dsi_disp_deinit,
+ .enable = mipi_dsi_enable,
+ .disable = mipi_dsi_disable,
+ .setup = mipi_dsi_setup,
+};
+
+static int device_reset(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ enum of_gpio_flags flags;
+ unsigned long gpio_flags;
+ unsigned int gpio;
+ bool initially_in_reset;
+ bool active_low;
+ s32 delay_us;
+ int ret;
+
+ gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags);
+ if (gpio == -EPROBE_DEFER) {
+ return gpio;
+ } else if (!gpio_is_valid(gpio)) {
+ dev_err(dev, "invalid reset gpio: %d\n", gpio);
+ return gpio;
+ }
+
+ active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+ ret = of_property_read_u32(np, "reset-delay-us", &delay_us);
+ if (ret < 0 || delay_us < 0) {
+ dev_err(dev, "invalid reset delay\n");
+ return -EINVAL;
+ }
+
+ initially_in_reset = of_property_read_bool(np, "initially-in-reset");
+ if (active_low ^ initially_in_reset)
+ gpio_flags = GPIOF_OUT_INIT_HIGH;
+ else
+ gpio_flags = GPIOF_OUT_INIT_LOW;
+
+ ret = devm_gpio_request_one(dev, gpio, gpio_flags, NULL);
+ if (ret < 0) {
+ dev_err(dev, "failed to request gpio %d: %d\n", gpio, ret);
+ return ret;
+ }
+
+ gpio_set_value_cansleep(gpio, active_low ? 0 : 1);
+ udelay(delay_us);
+ gpio_set_value_cansleep(gpio, active_low ? 1 : 0);
+
+ return 0;
+}
+
+static int imx6q_mipi_dsi_get_mux(int dev_id, int disp_id)
+{
+ if (dev_id > 1 || disp_id > 1)
+ return -EINVAL;
+
+ return (dev_id << 5) | (disp_id << 4);
+}
+
+static struct mipi_dsi_bus_mux imx6q_mipi_dsi_mux[] = {
+ {
+ .reg = IOMUXC_GPR3,
+ .mask = IMX6Q_GPR3_MIPI_MUX_CTL_MASK,
+ .get_mux = imx6q_mipi_dsi_get_mux,
+ },
+};
+
+static int imx6dl_mipi_dsi_get_mux(int dev_id, int disp_id)
+{
+ if (dev_id > 1 || disp_id > 1)
+ return -EINVAL;
+
+ /* MIPI DSI source is LCDIF */
+ if (dev_id)
+ disp_id = 0;
+
+ return (dev_id << 5) | (disp_id << 4);
+}
+
+static struct mipi_dsi_bus_mux imx6dl_mipi_dsi_mux[] = {
+ {
+ .reg = IOMUXC_GPR3,
+ .mask = IMX6Q_GPR3_MIPI_MUX_CTL_MASK,
+ .get_mux = imx6dl_mipi_dsi_get_mux,
+ },
+};
+
+static const struct of_device_id imx_mipi_dsi_dt_ids[] = {
+ { .compatible = "fsl,imx6q-mipi-dsi", .data = imx6q_mipi_dsi_mux, },
+ { .compatible = "fsl,imx6dl-mipi-dsi", .data = imx6dl_mipi_dsi_mux, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, imx_mipi_dsi_dt_ids);
+
+/**
+ * This function is called by the driver framework to initialize the MIPI DSI
+ * device.
+ *
+ * @param pdev The device structure for the MIPI DSI passed in by the
+ * driver framework.
+ *
+ * @return Returns 0 on success or negative error code on error
+ */
+static int mipi_dsi_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(of_match_ptr(imx_mipi_dsi_dt_ids),
+ &pdev->dev);
+ struct mipi_dsi_info *mipi_dsi;
+ struct resource *res;
+ u32 dev_id, disp_id;
+ const char *lcd_panel;
+ int mux;
+ int ret = 0;
+
+ if (!np) {
+ dev_err(&pdev->dev, "failed to find device tree node\n");
+ return -ENODEV;
+ }
+
+ mipi_dsi = devm_kzalloc(&pdev->dev, sizeof(*mipi_dsi), GFP_KERNEL);
+ if (!mipi_dsi)
+ return -ENOMEM;
+
+ ret = of_property_read_string(np, "lcd_panel", &lcd_panel);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read of property lcd_panel\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "dev_id", &dev_id);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read of property dev_id\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "disp_id", &disp_id);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read of property disp_id\n");
+ return ret;
+ }
+ mipi_dsi->dev_id = dev_id;
+ mipi_dsi->disp_id = disp_id;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get platform resource 0\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
+
+ mipi_dsi->mmio_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!mipi_dsi->mmio_base)
+ return -EBUSY;
+
+ mipi_dsi->irq = platform_get_irq(pdev, 0);
+ if (mipi_dsi->irq < 0) {
+ dev_err(&pdev->dev, "failed get device irq\n");
+ return -ENODEV;
+ }
+
+ ret = devm_request_irq(&pdev->dev, mipi_dsi->irq,
+ mipi_dsi_irq_handler,
+ 0, "mipi_dsi", mipi_dsi);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request irq\n");
+ return ret;
+ }
+
+ mipi_dsi->dphy_clk = devm_clk_get(&pdev->dev, "mipi_pllref_clk");
+ if (IS_ERR(mipi_dsi->dphy_clk)) {
+ dev_err(&pdev->dev, "failed to get dphy pll_ref_clk\n");
+ return PTR_ERR(mipi_dsi->dphy_clk);
+ }
+
+ mipi_dsi->cfg_clk = devm_clk_get(&pdev->dev, "mipi_cfg_clk");
+ if (IS_ERR(mipi_dsi->cfg_clk)) {
+ dev_err(&pdev->dev, "failed to get cfg_clk\n");
+ return PTR_ERR(mipi_dsi->cfg_clk);
+ }
+
+ mipi_dsi->disp_power_on = devm_regulator_get(&pdev->dev,
+ "disp-power-on");
+ if (!IS_ERR(mipi_dsi->disp_power_on)) {
+ ret = regulator_enable(mipi_dsi->disp_power_on);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable display "
+ "power regulator, err=%d\n", ret);
+ return ret;
+ }
+ } else {
+ mipi_dsi->disp_power_on = NULL;
+ }
+
+ ret = device_reset(&pdev->dev);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "failed to reset: %d\n", ret);
+ goto dev_reset_fail;
+ }
+
+ if (of_id)
+ mipi_dsi->bus_mux = of_id->data;
+
+ mipi_dsi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
+ if (IS_ERR(mipi_dsi->regmap)) {
+ dev_err(&pdev->dev, "failed to get parent regmap\n");
+ ret = PTR_ERR(mipi_dsi->regmap);
+ goto get_parent_regmap_fail;
+ }
+
+ mux = mipi_dsi->bus_mux->get_mux(dev_id, disp_id);
+ if (mux >= 0)
+ regmap_update_bits(mipi_dsi->regmap, mipi_dsi->bus_mux->reg,
+ mipi_dsi->bus_mux->mask, (unsigned int)mux);
+ else
+ dev_warn(&pdev->dev, "invalid dev_id or disp_id muxing\n");
+
+ mipi_dsi->lcd_panel = kstrdup(lcd_panel, GFP_KERNEL);
+ if (!mipi_dsi->lcd_panel) {
+ dev_err(&pdev->dev, "failed to allocate lcd panel name\n");
+ ret = -ENOMEM;
+ goto kstrdup_fail;
+ }
+
+ mipi_dsi->pdev = pdev;
+ mipi_dsi->disp_mipi = mxc_dispdrv_register(&mipi_dsi_drv);
+ if (IS_ERR(mipi_dsi->disp_mipi)) {
+ dev_err(&pdev->dev, "mxc_dispdrv_register error\n");
+ ret = PTR_ERR(mipi_dsi->disp_mipi);
+ goto dispdrv_reg_fail;
+ }
+
+ mipi_dsi->mipi_dsi_pkt_read = mipi_dsi_pkt_read;
+ mipi_dsi->mipi_dsi_pkt_write = mipi_dsi_pkt_write;
+ mipi_dsi->mipi_dsi_dcs_cmd = mipi_dsi_dcs_cmd;
+
+ mxc_dispdrv_setdata(mipi_dsi->disp_mipi, mipi_dsi);
+ dev_set_drvdata(&pdev->dev, mipi_dsi);
+
+ dev_info(&pdev->dev, "i.MX MIPI DSI driver probed\n");
+ return ret;
+
+dispdrv_reg_fail:
+ kfree(mipi_dsi->lcd_panel);
+kstrdup_fail:
+get_parent_regmap_fail:
+dev_reset_fail:
+ if (mipi_dsi->disp_power_on)
+ regulator_disable(mipi_dsi->disp_power_on);
+ return ret;
+}
+
+static void mipi_dsi_shutdown(struct platform_device *pdev)
+{
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ mipi_dsi_power_off(mipi_dsi->disp_mipi);
+}
+
+static int mipi_dsi_remove(struct platform_device *pdev)
+{
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ mxc_dispdrv_puthandle(mipi_dsi->disp_mipi);
+ mxc_dispdrv_unregister(mipi_dsi->disp_mipi);
+
+ if (mipi_dsi->disp_power_on)
+ regulator_disable(mipi_dsi->disp_power_on);
+
+ kfree(mipi_dsi->lcd_panel);
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver mipi_dsi_driver = {
+ .driver = {
+ .of_match_table = imx_mipi_dsi_dt_ids,
+ .name = "mxc_mipi_dsi",
+ },
+ .probe = mipi_dsi_probe,
+ .remove = mipi_dsi_remove,
+ .shutdown = mipi_dsi_shutdown,
+};
+
+static int __init mipi_dsi_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&mipi_dsi_driver);
+ if (err) {
+ pr_err("mipi_dsi_driver register failed\n");
+ return -ENODEV;
+ }
+ pr_debug("MIPI DSI driver module loaded: %s\n", mipi_dsi_driver.driver.name);
+ return 0;
+}
+
+static void __exit mipi_dsi_cleanup(void)
+{
+ platform_driver_unregister(&mipi_dsi_driver);
+}
+
+module_init(mipi_dsi_init);
+module_exit(mipi_dsi_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX MIPI DSI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mxc/mipi_dsi.h b/drivers/video/fbdev/mxc/mipi_dsi.h
new file mode 100644
index 000000000000..6cbdd702641a
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mipi_dsi.h
@@ -0,0 +1,125 @@
+/*
+ * 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
+ */
+#ifndef __MIPI_DSI_H__
+#define __MIPI_DSI_H__
+
+#include <linux/regmap.h>
+#include "mxc_dispdrv.h"
+
+#ifdef DEBUG
+#define mipi_dbg(fmt, ...) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define mipi_dbg(fmt, ...)
+#endif
+
+#define DSI_CMD_BUF_MAXSIZE (128)
+
+#define DSI_NON_BURST_WITH_SYNC_PULSE 0
+#define DSI_NON_BURST_WITH_SYNC_EVENT 1
+#define DSI_BURST_MODE 2
+
+/* DPI interface pixel color coding map */
+enum mipi_dsi_dpi_fmt {
+ MIPI_RGB565_PACKED = 0,
+ MIPI_RGB565_LOOSELY,
+ MIPI_RGB565_CONFIG3,
+ MIPI_RGB666_PACKED,
+ MIPI_RGB666_LOOSELY,
+ MIPI_RGB888,
+};
+
+struct mipi_lcd_config {
+ u32 virtual_ch;
+ u32 data_lane_num;
+ /* device max DPHY clock in MHz unit */
+ u32 max_phy_clk;
+ enum mipi_dsi_dpi_fmt dpi_fmt;
+};
+
+struct mipi_dsi_info;
+struct mipi_dsi_lcd_callback {
+ /* callback for lcd panel operation */
+ void (*get_mipi_lcd_videomode)(struct fb_videomode **, int *,
+ struct mipi_lcd_config **);
+ int (*mipi_lcd_setup)(struct mipi_dsi_info *);
+
+};
+
+struct mipi_dsi_match_lcd {
+ char *lcd_panel;
+ struct mipi_dsi_lcd_callback lcd_callback;
+};
+
+struct mipi_dsi_bus_mux {
+ int reg;
+ int mask;
+ int (*get_mux) (int dev_id, int disp_id);
+};
+
+/* driver private data */
+struct mipi_dsi_info {
+ struct platform_device *pdev;
+ void __iomem *mmio_base;
+ struct regmap *regmap;
+ const struct mipi_dsi_bus_mux *bus_mux;
+ int dsi_power_on;
+ int lcd_inited;
+ int encoder;
+ int traffic_mode;
+ u32 dphy_pll_config;
+ int dev_id;
+ int disp_id;
+ char *lcd_panel;
+ int irq;
+ struct clk *dphy_clk;
+ struct clk *cfg_clk;
+ struct clk *esc_clk;
+ struct mxc_dispdrv_handle *disp_mipi;
+ struct fb_videomode *mode;
+ struct regulator *disp_power_on;
+ struct mipi_lcd_config *lcd_config;
+ /* board related power control */
+ struct backlight_device *bl;
+ /* callback for lcd panel operation */
+ struct mipi_dsi_lcd_callback *lcd_callback;
+
+ int (*mipi_dsi_pkt_read)(struct mipi_dsi_info *mipi,
+ u8 data_type, u32 *buf, int len);
+ int (*mipi_dsi_pkt_write)(struct mipi_dsi_info *mipi_dsi,
+ u8 data_type, const u32 *buf, int len);
+ int (*mipi_dsi_dcs_cmd)(struct mipi_dsi_info *mipi,
+ u8 cmd, const u32 *param, int num);
+};
+
+#ifdef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
+void mipid_hx8369_get_lcd_videomode(struct fb_videomode **mode, int *size,
+ struct mipi_lcd_config **data);
+int mipid_hx8369_lcd_setup(struct mipi_dsi_info *);
+#endif
+#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5079E
+void mipid_otm8018b_get_lcd_videomode(struct fb_videomode **mode, int *size,
+ struct mipi_lcd_config **data);
+int mipid_otm8018b_lcd_setup(struct mipi_dsi_info *);
+#endif
+#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E
+void mipid_hx8363_get_lcd_videomode(struct fb_videomode **mode, int *size,
+ struct mipi_lcd_config **data);
+int mipid_hx8363_lcd_setup(struct mipi_dsi_info *);
+#endif
+
+#ifndef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
+#error "Please configure MIPI LCD panel, we cannot find one!"
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/mxc/mipi_dsi_northwest.c b/drivers/video/fbdev/mxc/mipi_dsi_northwest.c
new file mode 100644
index 000000000000..d2a26086fbc0
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mipi_dsi_northwest.c
@@ -0,0 +1,1125 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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 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/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/mipi_dsi_northwest.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <linux/pm_runtime.h>
+#include <linux/busfreq-imx.h>
+#include <linux/backlight.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <video/mipi_display.h>
+#include <video/mxc_edid.h>
+#include <linux/mfd/syscon.h>
+
+#include "mipi_dsi.h"
+
+#define DISPDRV_MIPI "mipi_dsi_northwest"
+#define ROUND_UP(x) ((x)+1)
+#define NS2PS_RATIO (1000)
+#define MIPI_LCD_SLEEP_MODE_DELAY (120)
+#define MIPI_FIFO_TIMEOUT msecs_to_jiffies(250)
+
+static struct mipi_dsi_match_lcd mipi_dsi_lcd_db[] = {
+#ifdef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
+ {
+ "TRULY-WVGA",
+ {mipid_hx8369_get_lcd_videomode, mipid_hx8369_lcd_setup}
+ },
+#endif
+#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5079E
+ {
+ "TRULY-WVGA-TFT3P5079E",
+ {mipid_otm8018b_get_lcd_videomode, mipid_otm8018b_lcd_setup}
+ },
+#endif
+#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E
+ {
+ "TRULY-WVGA-TFT3P5581E",
+ {mipid_hx8363_get_lcd_videomode, mipid_hx8363_lcd_setup}
+ },
+#endif
+ {
+ "", {NULL, NULL}
+ }
+};
+
+enum mipi_dsi_mode {
+ DSI_COMMAND_MODE,
+ DSI_VIDEO_MODE
+};
+
+#define DSI_LP_MODE 0
+#define DSI_HS_MODE 1
+
+enum mipi_dsi_payload {
+ DSI_PAYLOAD_CMD,
+ DSI_PAYLOAD_VIDEO,
+};
+
+struct pll_divider {
+ unsigned int cm; /* multiplier */
+ unsigned int cn; /* predivider */
+ unsigned int co; /* outdivider */
+};
+
+static DECLARE_COMPLETION(dsi_rx_done);
+static DECLARE_COMPLETION(dsi_tx_done);
+
+static void mipi_dsi_set_mode(struct mipi_dsi_info *mipi_dsi,
+ uint8_t mode);
+static int mipi_dsi_dcs_cmd(struct mipi_dsi_info *mipi_dsi,
+ u8 cmd, const u32 *param, int num);
+
+static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi,
+ struct mxc_dispdrv_setting *setting)
+{
+ u32 data_lane_num, max_data_rate;
+ int i, size, err = 0;
+ struct fb_videomode *mipi_lcd_modedb;
+ struct fb_videomode mode;
+ struct device *dev = &mipi_dsi->pdev->dev;
+
+ if (mipi_dsi->encoder) {
+ err = of_property_read_u32(dev->of_node,
+ "data-lanes-num", &data_lane_num);
+ if (err)
+ goto err0;
+
+ err = of_property_read_u32(dev->of_node,
+ "max-data-rate", &max_data_rate);
+ if (err)
+ goto err0;
+
+ mipi_dsi->lcd_config->virtual_ch = 0;
+ mipi_dsi->lcd_config->data_lane_num = data_lane_num;
+ mipi_dsi->lcd_config->max_phy_clk = max_data_rate;
+ mipi_dsi->lcd_config->dpi_fmt = MIPI_RGB888;
+ setting->fbi->var.bits_per_pixel = 32;
+
+ /* TODO Add bandwidth check */
+
+ if (setting->fbi->fbops->fb_check_var)
+ err = setting->fbi->fbops->fb_check_var(&setting->fbi->var,
+ setting->fbi);
+ if (err)
+ goto err0;
+
+ err = fb_add_videomode(mipi_dsi->mode,
+ &setting->fbi->modelist);
+ if (err)
+ goto err0;
+
+ fb_videomode_to_var(&setting->fbi->var, mipi_dsi->mode);
+ setting->fbi->mode = mipi_dsi->mode;
+ err0:
+ return err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mipi_dsi_lcd_db); i++) {
+ if (!strcmp(mipi_dsi->lcd_panel,
+ mipi_dsi_lcd_db[i].lcd_panel)) {
+ mipi_dsi->lcd_callback =
+ &mipi_dsi_lcd_db[i].lcd_callback;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(mipi_dsi_lcd_db)) {
+ dev_err(dev, "failed to find supported lcd panel.\n");
+ return -EINVAL;
+ }
+
+ /* set default bpp to 32 if not set*/
+ if (!setting->default_bpp)
+ setting->default_bpp = 32;
+
+ mipi_dsi->lcd_callback->get_mipi_lcd_videomode(&mipi_lcd_modedb, &size,
+ &mipi_dsi->lcd_config);
+
+ err = fb_find_mode(&setting->fbi->var, setting->fbi,
+ setting->dft_mode_str,
+ mipi_lcd_modedb, size, NULL,
+ setting->default_bpp);
+ if (err != 1)
+ fb_videomode_to_var(&setting->fbi->var, mipi_lcd_modedb);
+
+ INIT_LIST_HEAD(&setting->fbi->modelist);
+ for (i = 0; i < size; i++) {
+ fb_var_to_videomode(&mode, &setting->fbi->var);
+ if (fb_mode_is_equal(&mode, mipi_lcd_modedb + i)) {
+ err = fb_add_videomode(mipi_lcd_modedb + i,
+ &setting->fbi->modelist);
+ mipi_dsi->mode = mipi_lcd_modedb + i;
+ break;
+ }
+ }
+
+ if ((err < 0) || (size == i)) {
+ dev_err(dev, "failed to add videomode.\n");
+ return err;
+ }
+
+ setting->fbi->mode = mipi_dsi->mode;
+
+ return 0;
+}
+
+static int mipi_dsi_disp_init(struct mxc_dispdrv_handle *disp,
+ struct mxc_dispdrv_setting *setting)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+ struct device *dev = &mipi_dsi->pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct reset_control *reset = NULL;
+ int ret = 0;
+
+ reset = of_reset_control_get(np, NULL);
+ if (IS_ERR(reset))
+ return PTR_ERR(reset);
+
+ ret = mipi_dsi_lcd_init(mipi_dsi, setting);
+ if (ret) {
+ dev_err(dev, "failed to init mipi dsi lcd\n");
+ goto out;
+ }
+
+ dev_info(dev, "MIPI DSI dispdv inited\n");
+
+out:
+ reset_control_put(reset);
+ return ret;
+}
+
+static void mipi_dsi_disp_deinit(struct mxc_dispdrv_handle *disp)
+{
+ struct mipi_dsi_info *mipi_dsi;
+
+ mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ if (mipi_dsi->bl)
+ backlight_device_unregister(mipi_dsi->bl);
+}
+
+static void mipi_dsi_set_mode(struct mipi_dsi_info *mipi_dsi,
+ uint8_t mode)
+{
+ uint32_t pkt_control;
+
+ pkt_control = readl(mipi_dsi->mmio_base + HOST_PKT_CONTROL);
+
+ switch (mode) {
+ case DSI_LP_MODE:
+ writel(0x1, mipi_dsi->mmio_base + HOST_CFG_NONCONTINUOUS_CLK);
+ break;
+ case DSI_HS_MODE:
+ writel(0x0, mipi_dsi->mmio_base + HOST_CFG_NONCONTINUOUS_CLK);
+ break;
+ default:
+ dev_err(&mipi_dsi->pdev->dev,
+ "invalid dsi mode\n");
+ return;
+ }
+
+ mdelay(1);
+}
+
+static uint32_t fmt_to_bpp(enum mipi_dsi_dpi_fmt dpi_fmt)
+{
+ switch (dpi_fmt) {
+ case MIPI_RGB888:
+ return 24;
+ case MIPI_RGB565_PACKED:
+ return 16;
+ default:
+ return 0;
+ }
+}
+
+/*
+static void dphy_calc_dividers(int *cm, int *cn, int *co)
+{
+}
+*/
+
+static int mipi_dsi_dphy_init(struct mipi_dsi_info *mipi_dsi)
+{
+ uint32_t bpp, time_out = 100;
+ uint32_t lock;
+ uint32_t req_bit_clk;
+ struct pll_divider div;
+ struct fb_videomode *mode = mipi_dsi->mode;
+ struct mipi_lcd_config *lcd_config = mipi_dsi->lcd_config;
+
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1,
+ MIPI_ISO_DISABLE, MIPI_ISO_DISABLE);
+
+ bpp = fmt_to_bpp(lcd_config->dpi_fmt);
+ req_bit_clk = PICOS2KHZ(mode->pixclock) * bpp * 1000U;
+ switch (lcd_config->data_lane_num) {
+ case 1:
+ break;
+ case 2:
+ req_bit_clk = req_bit_clk >> 1;
+ break;
+ case 4:
+ req_bit_clk = req_bit_clk >> 2;
+ break;
+ default:
+ dev_err(&mipi_dsi->pdev->dev,
+ "requested data lane num is invalid\n");
+ return -EINVAL;
+ }
+
+ if (mipi_dsi->encoder) {
+ if (req_bit_clk > lcd_config->max_phy_clk)
+ return -EINVAL;
+ }
+
+ if (!mipi_dsi->encoder) {
+ /* PLL out clock = refclk * CM / (CN * CO)
+ * refclock = 24MHz
+ * pll vco = 24 * 40 / (3 * 1) = 320MHz
+ */
+ div.cn = 0x10; /* 3 */
+ div.cm = 0xc8; /* 40 */
+ div.co = 0x0; /* 1 */
+ } else {
+ /* pll vco = 24 * 63 / (5 * 1) = 302.4MHz */
+ div.cn = 0x1C; /* 5 */
+ div.cm = 0xDF; /* 63 */
+ div.co = 0x0; /* 1 */
+ }
+
+ writel(div.cn, mipi_dsi->mmio_base + DPHY_CN);
+ writel(div.cm, mipi_dsi->mmio_base + DPHY_CM);
+ writel(div.co, mipi_dsi->mmio_base + DPHY_CO);
+
+ writel(0x25, mipi_dsi->mmio_base + DPHY_TST);
+ writel(0x0, mipi_dsi->mmio_base + DPHY_PD_PLL);
+
+ while(!(lock = readl(mipi_dsi->mmio_base + DPHY_LOCK))) {
+ udelay(10);
+ time_out--;
+ if (time_out == 0) {
+ dev_err(&mipi_dsi->pdev->dev, "cannot get the dphy lock = 0x%x\n", lock);
+ return -EINVAL;
+ }
+ }
+ printk(KERN_EMERG "%s: dphy lock = 0x%x\n", __func__, lock);
+
+ writel(0x0, mipi_dsi->mmio_base + DPHY_LOCK_BYP);
+ writel(0x1, mipi_dsi->mmio_base + DPHY_RTERM_SEL);
+ writel(0x0, mipi_dsi->mmio_base + DPHY_AUTO_PD_EN);
+ writel(0x1, mipi_dsi->mmio_base + DPHY_RXLPRP);
+ writel(0x1, mipi_dsi->mmio_base + DPHY_RXCDRP);
+ writel(0x0, mipi_dsi->mmio_base + DPHY_M_PRG_HS_PREPARE);
+ writel(0x0, mipi_dsi->mmio_base + DPHY_MC_PRG_HS_PREPARE);
+ writel(0x9, mipi_dsi->mmio_base + DPHY_M_PRG_HS_ZERO);
+ writel(0x20, mipi_dsi->mmio_base + DPHY_MC_PRG_HS_ZERO);
+ writel(0x5, mipi_dsi->mmio_base + DPHY_M_PRG_HS_TRAIL);
+ writel(0x5, mipi_dsi->mmio_base + DPHY_MC_PRG_HS_TRAIL);
+ writel(0x0, mipi_dsi->mmio_base + DPHY_PD_DPHY);
+
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1CFG,
+ DSI_PLL_EN, DSI_PLL_EN);
+ return 0;
+}
+
+static int mipi_dsi_host_init(struct mipi_dsi_info *mipi_dsi)
+{
+ uint32_t lane_num;
+ struct mipi_lcd_config *lcd_config = mipi_dsi->lcd_config;
+
+ switch (lcd_config->data_lane_num) {
+ case 1:
+ lane_num = 0x0;
+ break;
+ case 2:
+ lane_num = 0x1;
+ break;
+ default:
+ /* Invalid lane num */
+ return -EINVAL;
+ }
+
+ writel(lane_num, mipi_dsi->mmio_base + HOST_CFG_NUM_LANES);
+ writel(mipi_dsi->encoder ? 0x0 : 0x1,
+ mipi_dsi->mmio_base + HOST_CFG_NONCONTINUOUS_CLK);
+ writel(0x1, mipi_dsi->mmio_base + HOST_CFG_T_PRE);
+ writel(52, mipi_dsi->mmio_base + HOST_CFG_T_POST);
+ writel(13, mipi_dsi->mmio_base + HOST_CFG_TX_GAP);
+ writel(mipi_dsi->encoder ? 0x0 : 0x1,
+ mipi_dsi->mmio_base + HOST_CFG_AUTOINSERT_EOTP);
+ writel(0x0, mipi_dsi->mmio_base + HOST_CFG_EXTRA_CMDS_AFTER_EOTP);
+ writel(0x0, mipi_dsi->mmio_base + HOST_CFG_HTX_TO_COUNT);
+ writel(0x0, mipi_dsi->mmio_base + HOST_CFG_LRX_H_TO_COUNT);
+ writel(0x0, mipi_dsi->mmio_base + HOST_CFG_BTA_H_TO_COUNT);
+ writel(0x3A98, mipi_dsi->mmio_base + HOST_CFG_TWAKEUP);
+
+ return 0;
+}
+
+static int mipi_dsi_dpi_init(struct mipi_dsi_info *mipi_dsi)
+{
+ uint32_t bpp, color_coding, pixel_fmt;
+ struct fb_videomode *mode = mipi_dsi->mode;
+ struct mipi_lcd_config *lcd_config = mipi_dsi->lcd_config;
+
+ bpp = fmt_to_bpp(lcd_config->dpi_fmt);
+
+ writel(mode->xres, mipi_dsi->mmio_base + DPI_PIXEL_PAYLOAD_SIZE);
+ writel(mode->xres, mipi_dsi->mmio_base + DPI_PIXEL_FIFO_SEND_LEVEL);
+
+ switch (bpp) {
+ case 24:
+ color_coding = 5;
+ pixel_fmt = 3;
+ break;
+ case 16:
+ case 18:
+ default:
+ break;
+ }
+ writel(color_coding, mipi_dsi->mmio_base + DPI_INTERFACE_COLOR_CODING);
+ writel(pixel_fmt, mipi_dsi->mmio_base + DPI_PIXEL_FORMAT);
+ writel(0x0, mipi_dsi->mmio_base + DPI_VSYNC_POLARITY);
+ writel(0x0, mipi_dsi->mmio_base + DPI_HSYNC_POLARITY);
+ writel(mipi_dsi->traffic_mode,
+ mipi_dsi->mmio_base + DPI_VIDEO_MODE);
+
+ switch (mipi_dsi->traffic_mode) {
+ case DSI_NON_BURST_WITH_SYNC_PULSE:
+ writel(0x10, mipi_dsi->mmio_base + DPI_HFP);
+ writel(0x60, mipi_dsi->mmio_base + DPI_HBP);
+ writel(0xf0, mipi_dsi->mmio_base + DPI_HSA);
+ break;
+ case DSI_BURST_MODE:
+ writel(mode->right_margin * (bpp >> 3),
+ mipi_dsi->mmio_base + DPI_HFP);
+ writel(mode->left_margin * (bpp >> 3),
+ mipi_dsi->mmio_base + DPI_HBP);
+ writel(mode->hsync_len * (bpp >> 3),
+ mipi_dsi->mmio_base + DPI_HSA);
+ break;
+ default:
+ pr_debug("unsupport traffic mode: %d\n",
+ mipi_dsi->traffic_mode);
+ return -EINVAL;
+ }
+ writel(0x0, mipi_dsi->mmio_base + DPI_ENABLE_MULT_PKTS);
+
+ writel(mode->upper_margin, mipi_dsi->mmio_base + DPI_VBP);
+ writel(mode->lower_margin, mipi_dsi->mmio_base + DPI_VFP);
+ writel(0x1, mipi_dsi->mmio_base + DPI_BLLP_MODE);
+ writel(0x0, mipi_dsi->mmio_base + DPI_USE_NULL_PKT_BLLP);
+
+ writel(mode->yres - 1, mipi_dsi->mmio_base + DPI_VACTIVE);
+
+ writel(0x0, mipi_dsi->mmio_base + DPI_VC);
+
+ return 0;
+}
+
+static void mipi_dsi_init_interrupt(struct mipi_dsi_info *mipi_dsi)
+{
+ uint32_t irqs_enable;
+
+ /* disable all the irqs */
+ writel(0xffffffff, mipi_dsi->mmio_base + HOST_IRQ_MASK);
+ writel(0x7, mipi_dsi->mmio_base + HOST_IRQ_MASK2);
+
+ irqs_enable = ~(HOST_IRQ_MASK_TX_PKT_DONE_MASK |
+ HOST_IRQ_MASK_RX_PKT_HDR_RCVD_MASK);
+
+ writel(irqs_enable, mipi_dsi->mmio_base + HOST_IRQ_MASK);
+}
+
+static int mipi_display_enter_sleep(struct mxc_dispdrv_handle *disp)
+{
+ int err;
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_SET_DISPLAY_OFF,
+ NULL, 0);
+ if (err)
+ return -EINVAL;
+ msleep(50);
+
+ err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_ENTER_SLEEP_MODE,
+ NULL, 0);
+ if (err) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command sleep in error!\n");
+ }
+ msleep(MIPI_LCD_SLEEP_MODE_DELAY);
+
+ return err;
+}
+
+static int mipi_display_exit_sleep(struct mxc_dispdrv_handle *disp)
+{
+ int err;
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_EXIT_SLEEP_MODE,
+ NULL, 0);
+ if (err) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command sleep-out error!\n");
+ return err;
+ }
+ msleep(MIPI_LCD_SLEEP_MODE_DELAY);
+
+ err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_SET_DISPLAY_ON,
+ NULL, 0);
+ msleep(20);
+
+ return err;
+}
+
+static void reset_dsi_domains(struct mipi_dsi_info *mipi_dsi, bool reset)
+{
+ /* escape domain */
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1CFG,
+ DSI_RST_ESC_N, (reset ? 0 : DSI_RST_ESC_N));
+ /* byte domain */
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1CFG,
+ DSI_RST_BYTE_N, (reset ? 0 : DSI_RST_BYTE_N));
+
+ /* dpi domain */
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1CFG,
+ DSI_RST_DPI_N, (reset ? 0 : DSI_RST_DPI_N));
+}
+
+static int mipi_dsi_enable(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ int ret;
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ if (!mipi_dsi->dsi_power_on)
+ pm_runtime_get_sync(&mipi_dsi->pdev->dev);
+
+ if (!mipi_dsi->lcd_inited) {
+ ret = clk_set_rate(mipi_dsi->esc_clk, 80000000);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "clk enable error: %d!\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(mipi_dsi->esc_clk);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "clk enable error: %d!\n", ret);
+ return -EINVAL;
+ }
+
+ if ((ret = mipi_dsi_dphy_init(mipi_dsi)) < 0)
+ return ret;
+
+ if ((ret = mipi_dsi_host_init(mipi_dsi)) < 0)
+ return ret;
+
+ mipi_dsi_dpi_init(mipi_dsi);
+
+ reset_dsi_domains(mipi_dsi, 0);
+
+ /* display_en */
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1CFG,
+ DSI_SD, 0x0);
+ /* normal cm */
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1CFG,
+ DSI_CM, 0x0);
+ msleep(20);
+
+ if (!mipi_dsi->encoder) {
+ ret = device_reset(&mipi_dsi->pdev->dev);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "failed to reset device: %d\n", ret);
+ return -EINVAL;
+ }
+ msleep(60);
+
+ mipi_dsi_init_interrupt(mipi_dsi);
+
+ ret = mipi_dsi->lcd_callback->mipi_lcd_setup(mipi_dsi);
+ if (ret < 0) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "failed to init mipi lcd.\n");
+ return ret;
+ }
+ mipi_dsi_set_mode(mipi_dsi, DSI_HS_MODE);
+ }
+
+ mipi_dsi->lcd_inited = 1;
+ } else {
+ ret = clk_prepare_enable(mipi_dsi->esc_clk);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "clk enable error: %d!\n", ret);
+ return -EINVAL;
+ }
+
+ reset_dsi_domains(mipi_dsi, 0);
+
+ if (!mipi_dsi->encoder) {
+ ret = mipi_display_exit_sleep(mipi_dsi->disp_mipi);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev, "exit sleep failed\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void mipi_dsi_wr_tx_header(struct mipi_dsi_info *mipi_dsi,
+ u8 di, u8 data0, u8 data1, u8 mode, u8 need_bta)
+{
+ uint32_t pkt_control = 0;
+ uint16_t word_count = 0;
+
+ word_count = data0 | (data1 << 8);
+ pkt_control = HOST_PKT_CONTROL_WC(word_count) |
+ HOST_PKT_CONTROL_VC(0) |
+ HOST_PKT_CONTROL_DT(di) |
+ HOST_PKT_CONTROL_HS_SEL(mode) |
+ HOST_PKT_CONTROL_BTA_TX(need_bta);
+
+ dev_dbg(&mipi_dsi->pdev->dev, "pkt_control = %x\n", pkt_control);
+ writel(pkt_control, mipi_dsi->mmio_base + HOST_PKT_CONTROL);
+}
+
+static void mipi_dsi_wr_tx_data(struct mipi_dsi_info *mipi_dsi,
+ uint32_t tx_data)
+{
+ writel(tx_data, mipi_dsi->mmio_base + HOST_TX_PAYLOAD);
+}
+
+static void mipi_dsi_long_data_wr(struct mipi_dsi_info *mipi_dsi,
+ const uint8_t *data0, uint32_t data_size)
+{
+ uint32_t data_cnt = 0, payload = 0;
+
+ /* in case that data count is more than 4 */
+ for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
+ /*
+ * after sending 4bytes per one time,
+ * send remainder data less then 4.
+ */
+ if ((data_size - data_cnt) < 4) {
+ if ((data_size - data_cnt) == 3) {
+ payload = data0[data_cnt] |
+ (data0[data_cnt + 1] << 8) |
+ (data0[data_cnt + 2] << 16);
+ dev_dbg(&mipi_dsi->pdev->dev, "count = 3 payload = %x, %x %x %x\n",
+ payload, data0[data_cnt], data0[data_cnt + 1], data0[data_cnt + 2]);
+ } else if ((data_size - data_cnt) == 2) {
+ payload = data0[data_cnt] |
+ (data0[data_cnt + 1] << 8);
+ dev_dbg(&mipi_dsi->pdev->dev, "count = 2 payload = %x, %x %x\n",
+ payload, data0[data_cnt], data0[data_cnt + 1]);
+ } else if ((data_size - data_cnt) == 1) {
+ payload = data0[data_cnt];
+ dev_dbg(&mipi_dsi->pdev->dev, "count = 1 payload = %x, %x\n",
+ payload, data0[data_cnt]);
+ }
+
+ mipi_dsi_wr_tx_data(mipi_dsi, payload);
+ } else {
+ payload = data0[data_cnt] |
+ (data0[data_cnt + 1] << 8) |
+ (data0[data_cnt + 2] << 16) |
+ (data0[data_cnt + 3] << 24);
+
+ dev_dbg(&mipi_dsi->pdev->dev,
+ "count = 4 payload = %x, %x %x %x %x\n",
+ payload, *(u8 *)(data0 + data_cnt),
+ data0[data_cnt + 1],
+ data0[data_cnt + 2],
+ data0[data_cnt + 3]);
+
+ mipi_dsi_wr_tx_data(mipi_dsi, payload);
+ }
+ }
+}
+
+static int mipi_dsi_pkt_write(struct mipi_dsi_info *mipi_dsi,
+ u8 data_type, const u32 *buf, int len)
+{
+ int ret = 0;
+ struct platform_device *pdev = mipi_dsi->pdev;
+ const uint8_t *data = (const uint8_t *)buf;
+
+ if (len == 0)
+ /* handle generic long write command */
+ mipi_dsi_wr_tx_header(mipi_dsi, data_type, data[0], data[1], DSI_LP_MODE, 0);
+ else {
+ reinit_completion(&dsi_tx_done);
+
+ /* handle generic long write command */
+ mipi_dsi_long_data_wr(mipi_dsi, data, len);
+ mipi_dsi_wr_tx_header(mipi_dsi, data_type, len & 0xff,
+ (len & 0xff00) >> 8, DSI_LP_MODE, 0);
+ }
+
+ /* send packet */
+ writel(0x1, mipi_dsi->mmio_base + HOST_SEND_PACKET);
+ ret = wait_for_completion_timeout(&dsi_tx_done, MIPI_FIFO_TIMEOUT);
+
+ if (!ret) {
+ dev_err(&pdev->dev, "wait tx done timeout!\n");
+ return -ETIMEDOUT;
+ }
+ mdelay(10);
+
+ return 0;
+}
+
+static uint32_t mipi_dsi_rd_rx_header(struct mipi_dsi_info *mipi_dsi)
+{
+ return readl(mipi_dsi->mmio_base + HOST_PKT_RX_PKT_HEADER);
+}
+
+static int mipi_dsi_pkt_read(struct mipi_dsi_info *mipi_dsi,
+ uint8_t data_type, uint32_t *buf, int len)
+{
+ int ret;
+ uint32_t rx_hdr;
+ struct platform_device *pdev = mipi_dsi->pdev;
+ const uint8_t *data = (const uint8_t *)buf;
+
+ if (len <= 4) {
+ reinit_completion(&dsi_rx_done);
+
+ mipi_dsi_wr_tx_header(mipi_dsi, data_type, data[0], data[1], DSI_LP_MODE, 1);
+ writel(0x1, mipi_dsi->mmio_base + HOST_SEND_PACKET);
+
+ ret = wait_for_completion_timeout(&dsi_rx_done, MIPI_FIFO_TIMEOUT);
+ if (!ret) {
+ dev_err(&pdev->dev, "wait rx done timeout!\n");
+ return -ETIMEDOUT;
+ }
+
+ rx_hdr = mipi_dsi_rd_rx_header(mipi_dsi);
+ dev_info(&pdev->dev, "rx: rx_hdr = 0x%x, data type = 0x%x, word_count = 0x%x\n",
+ rx_hdr, (rx_hdr >> 16) & 0x3f, rx_hdr & 0xffff);
+
+ buf[0] = rx_hdr & 0xff;
+ } else {
+ /* TODO: add support later */
+ }
+
+ return 0;
+}
+
+static int mipi_dsi_dcs_cmd(struct mipi_dsi_info *mipi_dsi,
+ u8 cmd, const u32 *param, int num)
+{
+ int err = 0;
+ u32 buf[DSI_CMD_BUF_MAXSIZE];
+
+ switch (cmd) {
+ case MIPI_DCS_EXIT_SLEEP_MODE:
+ case MIPI_DCS_ENTER_SLEEP_MODE:
+ case MIPI_DCS_SET_DISPLAY_ON:
+ case MIPI_DCS_SET_DISPLAY_OFF:
+ buf[0] = cmd;
+ buf[1] = 0x0;
+ err = mipi_dsi_pkt_write(mipi_dsi,
+ MIPI_DSI_DCS_SHORT_WRITE, buf, 0);
+ break;
+
+ default:
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command:0x%x Not supported!\n", cmd);
+ break;
+ }
+
+ return err;
+}
+
+static void mipi_dsi_disable(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ if (!mipi_dsi->encoder)
+ mipi_display_enter_sleep(mipi_dsi->disp_mipi);
+
+ clk_disable_unprepare(mipi_dsi->esc_clk);
+
+ reset_dsi_domains(mipi_dsi, 1);
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1CFG,
+ DSI_PLL_EN, 0x0);
+}
+
+static int mipi_dsi_setup(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+ int xres_virtual = fbi->var.xres_virtual;
+ int yres_virtual = fbi->var.yres_virtual;
+ int xoffset = fbi->var.xoffset;
+ int yoffset = fbi->var.yoffset;
+ int pixclock = fbi->var.pixclock;
+
+ if (!mipi_dsi->mode)
+ return 0;
+
+ /* set the mode back to var in case userspace changes it */
+ fb_videomode_to_var(&fbi->var, mipi_dsi->mode);
+
+ /* restore some var entries cached */
+ fbi->var.xres_virtual = xres_virtual;
+ fbi->var.yres_virtual = yres_virtual;
+ fbi->var.xoffset = xoffset;
+ fbi->var.yoffset = yoffset;
+ fbi->var.pixclock = pixclock;
+
+ return 0;
+}
+
+static struct mxc_dispdrv_driver mipi_dsi_drv = {
+ .name = DISPDRV_MIPI,
+ .init = mipi_dsi_disp_init,
+ .deinit = mipi_dsi_disp_deinit,
+ .enable = mipi_dsi_enable,
+ .disable = mipi_dsi_disable,
+ .setup = mipi_dsi_setup,
+};
+
+static irqreturn_t mipi_dsi_irq_handler(int irq, void *data)
+{
+ uint32_t irq_status;
+ struct mipi_dsi_info *mipi_dsi = data;
+ struct platform_device *pdev = mipi_dsi->pdev;
+
+ irq_status = readl(mipi_dsi->mmio_base + HOST_IRQ_STATUS);
+
+ dev_dbg(&pdev->dev, "irq_status = 0x%x\n", irq_status);
+
+ if (irq_status & HOST_IRQ_STATUS_TX_PKT_DONE) {
+ dev_dbg(&pdev->dev, "payload tx finished\n");
+ complete(&dsi_tx_done);
+ }
+
+ if (irq_status & HOST_IRQ_STATUS_RX_PKT_HDR_RCVD) {
+ dev_dbg(&pdev->dev, "rx data finished\n");
+ complete(&dsi_rx_done);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * This function is called by the driver framework to initialize the MIPI DSI
+ * device.
+ *
+ * @param pdev The device structure for the MIPI DSI passed in by the
+ * driver framework.
+ *
+ * @return Returns 0 on success or negative error code on error
+ */
+static int mipi_dsi_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct mipi_dsi_info *mipi_dsi;
+ struct device_node *endpoint = NULL, *remote;
+ struct resource *res;
+ const char *lcd_panel;
+ int ret = 0;
+ u32 vmode_index;
+
+ mipi_dsi = devm_kzalloc(&pdev->dev, sizeof(*mipi_dsi), GFP_KERNEL);
+ if (!mipi_dsi)
+ return -ENOMEM;
+ mipi_dsi->pdev = pdev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get platform mem resource\n");
+ return -ENOMEM;
+ }
+
+ mipi_dsi->mmio_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mipi_dsi->mmio_base))
+ return -ENODEV;
+
+ mipi_dsi->irq = platform_get_irq(pdev, 0);
+ if (mipi_dsi->irq < 0) {
+ dev_err(&pdev->dev, "failed to get device irq\n");
+ return -EINVAL;
+ }
+
+ ret = devm_request_irq(&pdev->dev, mipi_dsi->irq,
+ mipi_dsi_irq_handler,
+ 0, "mipi_dsi_northwest", mipi_dsi);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request mipi dsi irq\n");
+ return ret;
+ }
+
+ mipi_dsi->esc_clk = devm_clk_get(&pdev->dev, "mipi_dsi_clk");
+ if (IS_ERR(mipi_dsi->esc_clk)) {
+ dev_err(&pdev->dev, "failed to get esc clk\n");
+ return PTR_ERR(mipi_dsi->esc_clk);
+ }
+
+ mipi_dsi->regmap = syscon_regmap_lookup_by_phandle(np, "sim");
+ if (IS_ERR(mipi_dsi->regmap)) {
+ dev_err(&pdev->dev, "failed to get parent regmap\n");
+ return -EINVAL;
+ }
+
+ /* check whether an encoder exists */
+ endpoint = of_graph_get_next_endpoint(np, NULL);
+ if (endpoint) {
+ remote = of_graph_get_remote_port_parent(endpoint);
+ if (!remote)
+ return -EINVAL;
+
+ ret = of_property_read_u32(remote, "video-mode", &vmode_index);
+ if ((ret < 0) || (vmode_index >= ARRAY_SIZE(mxc_cea_mode)))
+ return -EINVAL;
+
+ mipi_dsi->mode = devm_kzalloc(&pdev->dev,
+ sizeof(struct fb_videomode),
+ GFP_KERNEL);
+ if (!mipi_dsi->mode)
+ return -ENOMEM;
+
+ memcpy(mipi_dsi->mode, &mxc_cea_mode[vmode_index],
+ sizeof(struct fb_videomode));
+
+ ret = of_property_read_u32(remote, "dsi-traffic-mode",
+ &mipi_dsi->traffic_mode);
+ if (ret < 0 || mipi_dsi->traffic_mode > 2) {
+ devm_kfree(&pdev->dev, mipi_dsi->mode);
+ return -EINVAL;
+ }
+
+ mipi_dsi->lcd_config = devm_kzalloc(&pdev->dev,
+ sizeof(struct mipi_lcd_config),
+ GFP_KERNEL);
+ if (!mipi_dsi->lcd_config) {
+ kfree(mipi_dsi->mode);
+ return -ENOMEM;
+ }
+
+ mipi_dsi->encoder = 1;
+ } else
+ /* Default, using 'BURST-MODE' for mipi panel */
+ mipi_dsi->traffic_mode = 2;
+
+ ret = of_property_read_string(np, "lcd_panel", &lcd_panel);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read lcd_panel property\n");
+ return ret;
+ }
+
+ /* mipi VDDA is sw1 in PMIC which is always on */
+
+ mipi_dsi->lcd_panel = kstrdup(lcd_panel, GFP_KERNEL);
+ if (!mipi_dsi->lcd_panel) {
+ dev_err(&pdev->dev, "failed to allocate lcd panel\n");
+ ret = -ENOMEM;
+ }
+
+ mipi_dsi->disp_mipi = mxc_dispdrv_register(&mipi_dsi_drv);
+ if (IS_ERR(mipi_dsi->disp_mipi)) {
+ dev_err(&pdev->dev, "mxc_dispdrv_register error\n");
+ ret = PTR_ERR(mipi_dsi->disp_mipi);
+ goto dispdrv_reg_fail;
+ }
+
+ mipi_dsi->mipi_dsi_pkt_read = mipi_dsi_pkt_read;
+ mipi_dsi->mipi_dsi_pkt_write = mipi_dsi_pkt_write;
+ mipi_dsi->mipi_dsi_dcs_cmd = mipi_dsi_dcs_cmd;
+
+ pm_runtime_enable(&pdev->dev);
+
+ mxc_dispdrv_setdata(mipi_dsi->disp_mipi, mipi_dsi);
+ dev_set_drvdata(&pdev->dev, mipi_dsi);
+
+ dev_info(&pdev->dev, "i.MX MIPI DSI driver probed\n");
+ return ret;
+
+dispdrv_reg_fail:
+ kfree(mipi_dsi->lcd_panel);
+ return ret;
+}
+
+static int mipi_dsi_remove(struct platform_device *pdev)
+{
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ mxc_dispdrv_puthandle(mipi_dsi->disp_mipi);
+ mxc_dispdrv_unregister(mipi_dsi->disp_mipi);
+
+ kfree(mipi_dsi->lcd_panel);
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static void mipi_dsi_shutdown(struct platform_device *pdev)
+{
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ if (mipi_dsi->lcd_inited) {
+ clk_prepare_enable(mipi_dsi->esc_clk);
+ if (!mipi_dsi->encoder)
+ mipi_display_enter_sleep(mipi_dsi->disp_mipi);
+
+ writel(0x1, mipi_dsi->mmio_base + DPHY_PD_PLL);
+ writel(0x1, mipi_dsi->mmio_base + DPHY_PD_DPHY);
+
+ clk_disable_unprepare(mipi_dsi->esc_clk);
+
+ mipi_dsi->lcd_inited = 0;
+ }
+
+ reset_dsi_domains(mipi_dsi, 1);
+ regmap_update_bits(mipi_dsi->regmap, SIM_SOPT1CFG,
+ DSI_PLL_EN, 0x0);
+}
+
+static const struct of_device_id imx_mipi_dsi_dt_ids[] = {
+ { .compatible = "fsl,imx7ulp-mipi-dsi", .data = NULL, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, imx_mipi_dsi_dt_ids);
+
+static int mipi_dsi_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ mipi_dsi->dsi_power_on = 0;
+
+ return 0;
+}
+
+static int mipi_dsi_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ if (!mipi_dsi->dsi_power_on) {
+ request_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "mipi dsi busfreq high request.\n");
+
+ mipi_dsi->dsi_power_on = 1;
+ }
+
+ return 0;
+}
+
+static int mipi_dsi_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ if (unlikely(mipi_dsi->lcd_inited)) {
+ clk_prepare_enable(mipi_dsi->esc_clk);
+
+ writel(0x1, mipi_dsi->mmio_base + DPHY_PD_PLL);
+ writel(0x1, mipi_dsi->mmio_base + DPHY_PD_DPHY);
+
+ clk_disable_unprepare(mipi_dsi->esc_clk);
+ mipi_dsi->lcd_inited = 0;
+ }
+
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static int mipi_dsi_resume(struct device *dev)
+{
+ pinctrl_pm_select_default_state(dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops mipi_dsi_pm_ops = {
+ .suspend = mipi_dsi_suspend,
+ .resume = mipi_dsi_resume,
+ .runtime_suspend = mipi_dsi_runtime_suspend,
+ .runtime_resume = mipi_dsi_runtime_resume,
+ .runtime_idle = NULL,
+};
+
+static struct platform_driver mipi_dsi_driver = {
+ .driver = {
+ .of_match_table = imx_mipi_dsi_dt_ids,
+ .name = "mipi_dsi_northwest",
+ .pm = &mipi_dsi_pm_ops,
+ },
+ .probe = mipi_dsi_probe,
+ .remove = mipi_dsi_remove,
+ .shutdown = mipi_dsi_shutdown,
+};
+
+static int __init mipi_dsi_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&mipi_dsi_driver);
+ if (err) {
+ pr_err("mipi_dsi_driver register failed\n");
+ return err;
+ }
+
+ pr_debug("MIPI DSI driver module loaded: %s\n", mipi_dsi_driver.driver.name);
+
+ return 0;
+}
+
+static void __exit mipi_dsi_exit(void)
+{
+ platform_driver_unregister(&mipi_dsi_driver);
+}
+
+module_init(mipi_dsi_init);
+module_exit(mipi_dsi_exit);
+
+MODULE_AUTHOR("NXP Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX MIPI DSI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mxc/mipi_dsi_samsung.c b/drivers/video/fbdev/mxc/mipi_dsi_samsung.c
new file mode 100644
index 000000000000..d6bcf2a3de9f
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mipi_dsi_samsung.c
@@ -0,0 +1,952 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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 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/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/mipi_dsi_samsung.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <linux/pm_runtime.h>
+#include <linux/busfreq-imx.h>
+#include <linux/backlight.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <video/mipi_display.h>
+#include <linux/mfd/syscon.h>
+
+#include "mipi_dsi.h"
+
+#define DISPDRV_MIPI "mipi_dsi_samsung"
+#define ROUND_UP(x) ((x)+1)
+#define NS2PS_RATIO (1000)
+#define MIPI_LCD_SLEEP_MODE_DELAY (120)
+#define MIPI_FIFO_TIMEOUT msecs_to_jiffies(250)
+
+static struct mipi_dsi_match_lcd mipi_dsi_lcd_db[] = {
+#ifdef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
+ {
+ "TRULY-WVGA",
+ {mipid_hx8369_get_lcd_videomode, mipid_hx8369_lcd_setup}
+ },
+#endif
+#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5079E
+ {
+ "TRULY-WVGA-TFT3P5079E",
+ {mipid_otm8018b_get_lcd_videomode, mipid_otm8018b_lcd_setup}
+ },
+#endif
+#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E
+ {
+ "TRULY-WVGA-TFT3P5581E",
+ {mipid_hx8363_get_lcd_videomode, mipid_hx8363_lcd_setup}
+ },
+#endif
+ {
+ "", {NULL, NULL}
+ }
+};
+
+enum mipi_dsi_mode {
+ DSI_COMMAND_MODE,
+ DSI_VIDEO_MODE
+};
+
+enum mipi_dsi_trans_mode {
+ DSI_LP_MODE,
+ DSI_HS_MODE
+};
+
+static struct regulator *mipi_phy_reg;
+static DECLARE_COMPLETION(dsi_rx_done);
+static DECLARE_COMPLETION(dsi_tx_done);
+
+static void mipi_dsi_dphy_power_down(void);
+static void mipi_dsi_set_mode(struct mipi_dsi_info *mipi_dsi,
+ enum mipi_dsi_trans_mode mode);
+
+static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi,
+ struct mxc_dispdrv_setting *setting)
+{
+ int i, size, err;
+ struct fb_videomode *mipi_lcd_modedb;
+ struct fb_videomode mode;
+ struct device *dev = &mipi_dsi->pdev->dev;
+
+ for (i = 0; i < ARRAY_SIZE(mipi_dsi_lcd_db); i++) {
+ if (!strcmp(mipi_dsi->lcd_panel,
+ mipi_dsi_lcd_db[i].lcd_panel)) {
+ mipi_dsi->lcd_callback =
+ &mipi_dsi_lcd_db[i].lcd_callback;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(mipi_dsi_lcd_db)) {
+ dev_err(dev, "failed to find supported lcd panel.\n");
+ return -EINVAL;
+ }
+
+ /* set default bpp to 32 if not set*/
+ if (!setting->default_bpp)
+ setting->default_bpp = 32;
+
+ mipi_dsi->lcd_callback->get_mipi_lcd_videomode(&mipi_lcd_modedb, &size,
+ &mipi_dsi->lcd_config);
+
+ err = fb_find_mode(&setting->fbi->var, setting->fbi,
+ setting->dft_mode_str,
+ mipi_lcd_modedb, size, NULL,
+ setting->default_bpp);
+ if (err != 1)
+ fb_videomode_to_var(&setting->fbi->var, mipi_lcd_modedb);
+
+ INIT_LIST_HEAD(&setting->fbi->modelist);
+ for (i = 0; i < size; i++) {
+ fb_var_to_videomode(&mode, &setting->fbi->var);
+ if (fb_mode_is_equal(&mode, mipi_lcd_modedb + i)) {
+ err = fb_add_videomode(mipi_lcd_modedb + i,
+ &setting->fbi->modelist);
+ mipi_dsi->mode = mipi_lcd_modedb + i;
+ break;
+ }
+ }
+
+ if ((err < 0) || (size == i)) {
+ dev_err(dev, "failed to add videomode.\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static void mipi_dsi_wr_tx_header(struct mipi_dsi_info *mipi_dsi,
+ u8 di, u8 data0, u8 data1)
+{
+ unsigned int reg;
+
+ reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
+
+ writel(reg, mipi_dsi->mmio_base + MIPI_DSI_PKTHDR);
+}
+
+static void mipi_dsi_wr_tx_data(struct mipi_dsi_info *mipi_dsi,
+ unsigned int tx_data)
+{
+ writel(tx_data, mipi_dsi->mmio_base + MIPI_DSI_PAYLOAD);
+}
+
+static void mipi_dsi_long_data_wr(struct mipi_dsi_info *mipi_dsi,
+ const unsigned char *data0, unsigned int data_size)
+{
+ unsigned int data_cnt = 0, payload = 0;
+
+ /* in case that data count is more then 4 */
+ for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
+ /*
+ * after sending 4bytes per one time,
+ * send remainder data less then 4.
+ */
+ if ((data_size - data_cnt) < 4) {
+ if ((data_size - data_cnt) == 3) {
+ payload = data0[data_cnt] |
+ data0[data_cnt + 1] << 8 |
+ data0[data_cnt + 2] << 16;
+ dev_dbg(&mipi_dsi->pdev->dev, "count = 3 payload = %x, %x %x %x\n",
+ payload, data0[data_cnt],
+ data0[data_cnt + 1],
+ data0[data_cnt + 2]);
+ } else if ((data_size - data_cnt) == 2) {
+ payload = data0[data_cnt] |
+ data0[data_cnt + 1] << 8;
+ dev_dbg(&mipi_dsi->pdev->dev,
+ "count = 2 payload = %x, %x %x\n", payload,
+ data0[data_cnt],
+ data0[data_cnt + 1]);
+ } else if ((data_size - data_cnt) == 1) {
+ payload = data0[data_cnt];
+ }
+
+ mipi_dsi_wr_tx_data(mipi_dsi, payload);
+ /* send 4bytes per one time. */
+ } else {
+ payload = data0[data_cnt] |
+ data0[data_cnt + 1] << 8 |
+ data0[data_cnt + 2] << 16 |
+ data0[data_cnt + 3] << 24;
+
+ dev_dbg(&mipi_dsi->pdev->dev,
+ "count = 4 payload = %x, %x %x %x %x\n",
+ payload, *(u8 *)(data0 + data_cnt),
+ data0[data_cnt + 1],
+ data0[data_cnt + 2],
+ data0[data_cnt + 3]);
+
+ mipi_dsi_wr_tx_data(mipi_dsi, payload);
+ }
+ }
+}
+
+static int mipi_dsi_pkt_write(struct mipi_dsi_info *mipi_dsi,
+ u8 data_type, const u32 *buf, int len)
+{
+ int ret = 0;
+ struct platform_device *pdev = mipi_dsi->pdev;
+ const unsigned char *data = (const unsigned char*)buf;
+
+ if (len == 0)
+ /* handle generic short write command */
+ mipi_dsi_wr_tx_header(mipi_dsi, data_type, data[0], data[1]);
+ else {
+ reinit_completion(&dsi_tx_done);
+
+ /* handle generic long write command */
+ mipi_dsi_long_data_wr(mipi_dsi, data, len);
+ mipi_dsi_wr_tx_header(mipi_dsi, data_type, len & 0xff, (len & 0xff00) >> 8);
+
+ ret = wait_for_completion_timeout(&dsi_tx_done, MIPI_FIFO_TIMEOUT);
+ if (!ret) {
+ dev_err(&pdev->dev, "wait tx done timeout!\n");
+ return -ETIMEDOUT;
+ }
+ }
+ mdelay(10);
+
+ return 0;
+}
+
+static void mipi_dsi_rd_tx_header(struct mipi_dsi_info *mipi_dsi,
+ u8 data_type, u8 data0)
+{
+ unsigned int reg = (data_type << 0) | (data0 << 8);
+
+ writel(reg, mipi_dsi->mmio_base + MIPI_DSI_PKTHDR);
+}
+
+static unsigned int mipi_dsi_rd_rx_fifo(struct mipi_dsi_info *mipi_dsi)
+{
+ return readl(mipi_dsi->mmio_base + MIPI_DSI_RXFIFO);
+}
+
+static int mipi_dsi_pkt_read(struct mipi_dsi_info *mipi_dsi,
+ u8 data_type, u32 *buf, int len)
+{
+ int ret;
+ struct platform_device *pdev = mipi_dsi->pdev;
+
+ if (len <= 4) {
+ reinit_completion(&dsi_rx_done);
+
+ mipi_dsi_rd_tx_header(mipi_dsi, data_type, buf[0]);
+
+ ret = wait_for_completion_timeout(&dsi_rx_done, MIPI_FIFO_TIMEOUT);
+ if (!ret) {
+ dev_err(&pdev->dev, "wait rx done timeout!\n");
+ return -ETIMEDOUT;
+ }
+
+ buf[0] = mipi_dsi_rd_rx_fifo(mipi_dsi);
+ buf[0] = buf[0] >> 8;
+ }
+ else {
+ /* TODO: add support later */
+ }
+
+ return 0;
+}
+
+int mipi_dsi_dcs_cmd(struct mipi_dsi_info *mipi_dsi,
+ u8 cmd, const u32 *param, int num)
+{
+ int err = 0;
+ u32 buf[DSI_CMD_BUF_MAXSIZE];
+
+ switch (cmd) {
+ case MIPI_DCS_EXIT_SLEEP_MODE:
+ case MIPI_DCS_ENTER_SLEEP_MODE:
+ case MIPI_DCS_SET_DISPLAY_ON:
+ case MIPI_DCS_SET_DISPLAY_OFF:
+ buf[0] = cmd;
+ err = mipi_dsi_pkt_write(mipi_dsi,
+ MIPI_DSI_DCS_SHORT_WRITE, buf, 0);
+ break;
+
+ default:
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command:0x%x Not supported!\n", cmd);
+ break;
+ }
+
+ return err;
+}
+
+static void mipi_dsi_set_main_standby(struct mipi_dsi_info *mipi_dsi,
+ unsigned int enable)
+{
+ unsigned int reg;
+
+ reg = readl(mipi_dsi->mmio_base + MIPI_DSI_MDRESOL);
+
+ reg &= ~MIPI_DSI_MAIN_STANDBY(1);
+
+ if (enable)
+ reg |= MIPI_DSI_MAIN_STANDBY(1);
+
+ writel(reg, mipi_dsi->mmio_base + MIPI_DSI_MDRESOL);
+}
+
+static void mipi_dsi_power_off(struct mxc_dispdrv_handle *disp)
+{
+ int err;
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_ENTER_SLEEP_MODE,
+ NULL, 0);
+ if (err) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command display on error!\n");
+ }
+ msleep(MIPI_LCD_SLEEP_MODE_DELAY);
+
+ mipi_dsi_set_main_standby(mipi_dsi, 0);
+
+ clk_disable_unprepare(mipi_dsi->dphy_clk);
+ clk_disable_unprepare(mipi_dsi->cfg_clk);
+}
+
+static void mipi_dsi_dphy_power_on(struct platform_device *pdev)
+{
+ int ret;
+
+ regulator_set_voltage(mipi_phy_reg, 1000000, 1000000);
+
+ ret = regulator_enable(mipi_phy_reg);
+ if (ret){
+ dev_err(&pdev->dev, "failed to enable mipi phy regulatore\n");
+ BUG_ON(1);
+ }
+}
+
+static void mipi_dsi_dphy_power_down(void)
+{
+ regulator_disable(mipi_phy_reg);
+}
+
+static int mipi_dsi_lane_stop_state(struct mipi_dsi_info *mipi_dsi)
+{
+ unsigned int reg;
+
+ reg = readl(mipi_dsi->mmio_base + MIPI_DSI_STATUS);
+
+ if (((reg & MIPI_DSI_STOP_STATE_DAT(0x3)) == 0x3) &&
+ ((reg & MIPI_DSI_STOP_STATE_CLK(0x1)) ||
+ (reg & MIPI_DSI_TX_READY_HS_CLK(0x1))))
+ return 1;
+
+ return 0;
+}
+
+static void mipi_dsi_init_interrupt(struct mipi_dsi_info *mipi_dsi)
+{
+ unsigned int intsrc, intmsk;
+
+ intsrc = (INTSRC_SFR_PL_FIFO_EMPTY | INTSRC_RX_DATA_DONE);
+ writel(intsrc, mipi_dsi->mmio_base + MIPI_DSI_INTSRC);
+
+ intmsk = ~(INTMSK_SFR_PL_FIFO_EMPTY | INTMSK_RX_DATA_DONE);
+ writel(intmsk, mipi_dsi->mmio_base + MIPI_DSI_INTMSK);
+}
+
+static int mipi_dsi_master_init(struct mipi_dsi_info *mipi_dsi,
+ bool init)
+{
+ unsigned int time_out = 100;
+ unsigned int reg, byte_clk, esc_div;
+ struct fb_videomode *mode = mipi_dsi->mode;
+ struct device *dev = &mipi_dsi->pdev->dev;
+
+ /* configure DPHY PLL clock */
+ writel(MIPI_DSI_TX_REQUEST_HSCLK(0) |
+ MIPI_DSI_DPHY_SEL(0) |
+ MIPI_DSI_PLL_BYPASS(0) |
+ MIPI_DSI_BYTE_CLK_SRC(0),
+ mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
+ if (!strcmp(mipi_dsi->lcd_panel, "TRULY-WVGA-TFT3P5581E"))
+ writel(MIPI_DSI_PLL_EN(1) | MIPI_DSI_PMS(0x3141),
+ mipi_dsi->mmio_base + MIPI_DSI_PLLCTRL);
+ else
+ writel(MIPI_DSI_PLL_EN(1) | MIPI_DSI_PMS(0x4190),
+ mipi_dsi->mmio_base + MIPI_DSI_PLLCTRL);
+
+ /* set PLLTMR: stable time */
+ writel(33024, mipi_dsi->mmio_base + MIPI_DSI_PLLTMR);
+ udelay(300);
+
+ /* configure byte clock */
+ reg = readl(mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
+ reg |= MIPI_DSI_BYTE_CLK_EN(1);
+ byte_clk = 1500000000 / 8;
+ esc_div = DIV_ROUND_UP(byte_clk, 20 * 1000000);
+ reg |= (esc_div & 0xffff);
+ /* enable escape clock for clock lane and data lane0 and lane1 */
+ reg |= MIPI_DSI_LANE_ESC_CLK_EN(0x7);
+ reg |= MIPI_DSI_ESC_CLK_EN(1);
+ writel(reg, mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
+
+ /* set main display resolution */
+ writel(MIPI_DSI_MAIN_HRESOL(mode->xres) |
+ MIPI_DSI_MAIN_VRESOL(mode->yres) |
+ MIPI_DSI_MAIN_STANDBY(0),
+ mipi_dsi->mmio_base + MIPI_DSI_MDRESOL);
+
+ /* set config register */
+ writel(MIPI_DSI_MFLUSH_VS(1) |
+ MIPI_DSI_SYNC_IN_FORM(0) |
+ MIPI_DSI_BURST_MODE(1) |
+ MIPI_DSI_VIDEO_MODE(1) |
+ MIPI_DSI_AUTO_MODE(0) |
+ MIPI_DSI_HSE_DISABLE_MODE(0) |
+ MIPI_DSI_HFP_DISABLE_MODE(0) |
+ MIPI_DSI_HBP_DISABLE_MODE(0) |
+ MIPI_DSI_HSA_DISABLE_MODE(0) |
+ MIPI_DSI_MAIN_VC(0) |
+ MIPI_DSI_SUB_VC(1) |
+ MIPI_DSI_MAIN_PIX_FORMAT(0x7) |
+ MIPI_DSI_SUB_PIX_FORMAT(0x7) |
+ MIPI_DSI_NUM_OF_DATALANE(0x1) |
+ MIPI_DSI_LANE_EN(0x7), /* enable data lane 0 and 1 */
+ mipi_dsi->mmio_base + MIPI_DSI_CONFIG);
+
+ /* set main display vporch */
+ writel(MIPI_DSI_CMDALLOW(0xf) |
+ MIPI_DSI_STABLE_VFP(mode->lower_margin) |
+ MIPI_DSI_MAIN_VBP(mode->upper_margin),
+ mipi_dsi->mmio_base + MIPI_DSI_MVPORCH);
+ /* set main display hporch */
+ writel(MIPI_DSI_MAIN_HFP(mode->right_margin) |
+ MIPI_DSI_MAIN_HBP(mode->left_margin),
+ mipi_dsi->mmio_base + MIPI_DSI_MHPORCH);
+ /* set main display sync */
+ writel(MIPI_DSI_MAIN_VSA(mode->vsync_len) |
+ MIPI_DSI_MAIN_HSA(mode->hsync_len),
+ mipi_dsi->mmio_base + MIPI_DSI_MSYNC);
+
+ /* configure d-phy timings */
+ if (!strcmp(mipi_dsi->lcd_panel, "TRULY-WVGA-TFT3P5581E")) {
+ writel(MIPI_DSI_M_TLPXCTL(2) | MIPI_DSI_M_THSEXITCTL(4),
+ mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING);
+ writel(MIPI_DSI_M_TCLKPRPRCTL(5) |
+ MIPI_DSI_M_TCLKZEROCTL(14) |
+ MIPI_DSI_M_TCLKPOSTCTL(8) |
+ MIPI_DSI_M_TCLKTRAILCTL(3),
+ mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING1);
+ writel(MIPI_DSI_M_THSPRPRCTL(3) |
+ MIPI_DSI_M_THSZEROCTL(3) |
+ MIPI_DSI_M_THSTRAILCTL(3),
+ mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING2);
+ } else {
+ writel(MIPI_DSI_M_TLPXCTL(11) | MIPI_DSI_M_THSEXITCTL(18),
+ mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING);
+ writel(MIPI_DSI_M_TCLKPRPRCTL(13) |
+ MIPI_DSI_M_TCLKZEROCTL(65) |
+ MIPI_DSI_M_TCLKPOSTCTL(17) |
+ MIPI_DSI_M_TCLKTRAILCTL(13),
+ mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING1);
+ writel(MIPI_DSI_M_THSPRPRCTL(16) |
+ MIPI_DSI_M_THSZEROCTL(24) |
+ MIPI_DSI_M_THSTRAILCTL(16),
+ mipi_dsi->mmio_base + MIPI_DSI_PHYTIMING2);
+ }
+
+ writel(0xf000f, mipi_dsi->mmio_base + MIPI_DSI_TIMEOUT);
+
+ /* Init FIFO */
+ writel(0x0, mipi_dsi->mmio_base + MIPI_DSI_FIFOCTRL);
+ udelay(300);
+ writel(0x1f, mipi_dsi->mmio_base + MIPI_DSI_FIFOCTRL);
+
+ /* check clock and data lanes are in stop state
+ * which means dphy is in low power mode
+ */
+ while (!mipi_dsi_lane_stop_state(mipi_dsi)) {
+ time_out--;
+ if (time_out == 0) {
+ dev_err(dev, "MIPI DSI is not stop state.\n");
+ return -EINVAL;
+ }
+ }
+
+ /* transfer commands always in lp mode */
+ writel(MIPI_DSI_CMD_LPDT, mipi_dsi->mmio_base + MIPI_DSI_ESCMODE);
+
+ mipi_dsi_init_interrupt(mipi_dsi);
+
+ return 0;
+}
+
+static int mipi_dsi_disp_init(struct mxc_dispdrv_handle *disp,
+ struct mxc_dispdrv_setting *setting)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+ struct device *dev = &mipi_dsi->pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct reset_control *reset = NULL;
+ int ret = 0;
+
+ reset = of_reset_control_get(np, NULL);
+ if (IS_ERR(reset))
+ return PTR_ERR(reset);
+
+ ret = mipi_dsi_lcd_init(mipi_dsi, setting);
+ if (ret) {
+ dev_err(dev, "failed to init mipi dsi lcd\n");
+ goto out;
+ }
+
+ dev_info(dev, "MIPI DSI dispdrv inited!\n");
+
+out:
+ reset_control_put(reset);
+ return ret;
+}
+
+static void mipi_dsi_disp_deinit(struct mxc_dispdrv_handle *disp)
+{
+ struct mipi_dsi_info *mipi_dsi;
+
+ mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ mipi_dsi_power_off(mipi_dsi->disp_mipi);
+ if (mipi_dsi->bl)
+ backlight_device_unregister(mipi_dsi->bl);
+}
+
+static void mipi_dsi_set_mode(struct mipi_dsi_info *mipi_dsi,
+ enum mipi_dsi_trans_mode mode)
+{
+ unsigned int dsi_clkctrl;
+
+ dsi_clkctrl = readl(mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
+
+ switch (mode) {
+ case DSI_LP_MODE:
+ dsi_clkctrl &= ~MIPI_DSI_TX_REQUEST_HSCLK(1);
+ break;
+ case DSI_HS_MODE:
+ dsi_clkctrl |= MIPI_DSI_TX_REQUEST_HSCLK(1);
+ break;
+ default:
+ dev_err(&mipi_dsi->pdev->dev,
+ "invalid dsi mode\n");
+ return;
+ }
+
+ writel(dsi_clkctrl, mipi_dsi->mmio_base + MIPI_DSI_CLKCTRL);
+ mdelay(1);
+}
+
+static int mipi_dsi_enable(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ int ret;
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ if (fbi->state == FBINFO_STATE_SUSPENDED) {
+ if (mipi_dsi->disp_power_on) {
+ ret = regulator_enable(mipi_dsi->disp_power_on);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev, "failed to enable display "
+ "power regulator, err = %d\n", ret);
+ return ret;
+ }
+ }
+ }
+
+ if (!mipi_dsi->dsi_power_on)
+ pm_runtime_get_sync(&mipi_dsi->pdev->dev);
+
+ ret = clk_prepare_enable(mipi_dsi->dphy_clk);
+ ret |= clk_prepare_enable(mipi_dsi->cfg_clk);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "clk enable error:%d!\n", ret);
+ return -EINVAL;
+ }
+
+ if (!mipi_dsi->lcd_inited) {
+ ret = mipi_dsi_master_init(mipi_dsi, true);
+ if (ret)
+ return -EINVAL;
+
+ msleep(20);
+ ret = device_reset(&mipi_dsi->pdev->dev);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev, "failed to reset device: %d\n", ret);
+ return -EINVAL;
+ }
+ msleep(120);
+
+ /* the panel should be config under LP mode */
+ ret = mipi_dsi->lcd_callback->mipi_lcd_setup(mipi_dsi);
+ if (ret < 0) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "failed to init mipi lcd.\n");
+ return ret ;
+ }
+ mipi_dsi->lcd_inited = 1;
+
+ /* change to HS mode for panel display */
+ mipi_dsi_set_mode(mipi_dsi, DSI_HS_MODE);
+ } else {
+ ret = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_EXIT_SLEEP_MODE,
+ NULL, 0);
+ if (ret) {
+ dev_err(&mipi_dsi->pdev->dev,
+ "MIPI DSI DCS Command sleep-in error!\n");
+ }
+ msleep(MIPI_LCD_SLEEP_MODE_DELAY);
+ }
+
+ mipi_dsi_set_main_standby(mipi_dsi, 1);
+
+ return 0;
+}
+
+static void mipi_dsi_disable(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+
+ mipi_dsi_power_off(mipi_dsi->disp_mipi);
+
+ if (fbi->state == FBINFO_STATE_SUSPENDED) {
+ if (mipi_dsi->dsi_power_on) {
+ pm_runtime_put_noidle(&mipi_dsi->pdev->dev);
+ pm_runtime_put_sync_suspend(&mipi_dsi->pdev->dev);
+ pm_runtime_get_noresume(&mipi_dsi->pdev->dev);
+ }
+
+ if (mipi_dsi->disp_power_on)
+ regulator_disable(mipi_dsi->disp_power_on);
+
+ mipi_dsi->lcd_inited = 0;
+ }
+}
+
+static int mipi_dsi_setup(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp);
+ int xres_virtual = fbi->var.xres_virtual;
+ int yres_virtual = fbi->var.yres_virtual;
+ int xoffset = fbi->var.xoffset;
+ int yoffset = fbi->var.yoffset;
+ int pixclock = fbi->var.pixclock;
+
+ if (!mipi_dsi->mode)
+ return 0;
+
+ /* set the mode back to var in case userspace changes it */
+ fb_videomode_to_var(&fbi->var, mipi_dsi->mode);
+
+ /* restore some var entries cached */
+ fbi->var.xres_virtual = xres_virtual;
+ fbi->var.yres_virtual = yres_virtual;
+ fbi->var.xoffset = xoffset;
+ fbi->var.yoffset = yoffset;
+ fbi->var.pixclock = pixclock;
+
+ return 0;
+}
+
+static struct mxc_dispdrv_driver mipi_dsi_drv = {
+ .name = DISPDRV_MIPI,
+ .init = mipi_dsi_disp_init,
+ .deinit = mipi_dsi_disp_deinit,
+ .enable = mipi_dsi_enable,
+ .disable = mipi_dsi_disable,
+ .setup = mipi_dsi_setup,
+};
+
+static const struct of_device_id imx_mipi_dsi_dt_ids[] = {
+ { .compatible = "fsl,imx7d-mipi-dsi", .data = NULL, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, imx_mipi_dsi_dt_ids);
+
+static irqreturn_t mipi_dsi_irq_handler(int irq, void *data)
+{
+ unsigned int intsrc, intclr;
+ struct mipi_dsi_info *mipi_dsi = data;
+ struct platform_device *pdev = mipi_dsi->pdev;
+
+ intclr = 0;
+ intsrc = readl(mipi_dsi->mmio_base + MIPI_DSI_INTSRC);
+
+ dev_dbg(&pdev->dev, "intsrc = 0x%x\n", intsrc);
+
+ if (intsrc & INTSRC_SFR_PL_FIFO_EMPTY) {
+ dev_dbg(&pdev->dev, "playload tx finished\n");
+ intclr |= INTSRC_SFR_PL_FIFO_EMPTY;
+ complete(&dsi_tx_done);
+ }
+
+ if(intsrc & INTSRC_RX_DATA_DONE) {
+ dev_dbg(&pdev->dev, "rx data finished\n");
+ intclr |= INTSRC_RX_DATA_DONE;
+ complete(&dsi_rx_done);
+ }
+
+ /* clear the interrupts */
+ if (intclr)
+ writel(intclr, mipi_dsi->mmio_base + MIPI_DSI_INTSRC);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * This function is called by the driver framework to initialize the MIPI DSI
+ * device.
+ *
+ * @param pdev The device structure for the MIPI DSI passed in by the
+ * driver framework.
+ *
+ * @return Returns 0 on success or negative error code on error
+ */
+static int mipi_dsi_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct mipi_dsi_info *mipi_dsi;
+ struct resource *res;
+ const char *lcd_panel;
+ int ret = 0;
+
+ mipi_dsi = devm_kzalloc(&pdev->dev, sizeof(*mipi_dsi), GFP_KERNEL);
+ if (!mipi_dsi)
+ return -ENOMEM;
+ mipi_dsi->pdev = pdev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get platform resource mem\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
+
+ mipi_dsi->mmio_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!mipi_dsi->mmio_base)
+ return -ENOMEM;
+
+ mipi_dsi->irq = platform_get_irq(pdev, 0);
+ if (mipi_dsi->irq < 0) {
+ dev_err(&pdev->dev, "failed to get device irq\n");
+ return -EINVAL;
+ }
+
+ ret = devm_request_irq(&pdev->dev, mipi_dsi->irq,
+ mipi_dsi_irq_handler,
+ 0, "mipi_dsi_samsung", mipi_dsi);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request mipi dsi irq\n");
+ return ret;
+ }
+
+ mipi_dsi->dphy_clk = devm_clk_get(&pdev->dev, "mipi_pllref_clk");
+ if (IS_ERR(mipi_dsi->dphy_clk)) {
+ dev_err(&pdev->dev, "failed to get dphy pll_ref_clk\n");
+ return PTR_ERR(mipi_dsi->dphy_clk);
+ }
+
+ mipi_dsi->cfg_clk = devm_clk_get(&pdev->dev, "mipi_cfg_clk");
+ if (IS_ERR(mipi_dsi->cfg_clk)) {
+ dev_err(&pdev->dev, "failed to get cfg_clk\n");
+ return PTR_ERR(mipi_dsi->cfg_clk);
+ }
+
+ ret = of_property_read_string(np, "lcd_panel", &lcd_panel);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read lcd_panel property\n");
+ return ret;
+ }
+
+ mipi_phy_reg = devm_regulator_get(&pdev->dev, "mipi-phy");
+ if (IS_ERR(mipi_phy_reg)) {
+ dev_err(&pdev->dev, "mipi phy power supply not found\n");
+ return ret;
+ }
+
+ mipi_dsi->disp_power_on = devm_regulator_get(&pdev->dev,
+ "disp-power-on");
+ if (!IS_ERR(mipi_dsi->disp_power_on)) {
+ ret = regulator_enable(mipi_dsi->disp_power_on);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable display "
+ "power regulator, err = %d\n", ret);
+ return ret;
+ }
+ }
+
+ mipi_dsi->lcd_panel = kstrdup(lcd_panel, GFP_KERNEL);
+ if (!mipi_dsi->lcd_panel) {
+ dev_err(&pdev->dev, "failed to allocate lcd panel name\n");
+ ret = -ENOMEM;
+ goto kstrdup_fail;
+ }
+
+ mipi_dsi->disp_mipi = mxc_dispdrv_register(&mipi_dsi_drv);
+ if (IS_ERR(mipi_dsi->disp_mipi)) {
+ dev_err(&pdev->dev, "mxc_dispdrv_register error\n");
+ ret = PTR_ERR(mipi_dsi->disp_mipi);
+ goto dispdrv_reg_fail;
+ }
+
+ mipi_dsi->mipi_dsi_pkt_read = mipi_dsi_pkt_read;
+ mipi_dsi->mipi_dsi_pkt_write = mipi_dsi_pkt_write;
+ mipi_dsi->mipi_dsi_dcs_cmd = mipi_dsi_dcs_cmd;
+
+ pm_runtime_enable(&pdev->dev);
+
+ mxc_dispdrv_setdata(mipi_dsi->disp_mipi, mipi_dsi);
+ dev_set_drvdata(&pdev->dev, mipi_dsi);
+
+ dev_info(&pdev->dev, "i.MX MIPI DSI driver probed\n");
+ return ret;
+
+dispdrv_reg_fail:
+ kfree(mipi_dsi->lcd_panel);
+kstrdup_fail:
+ if (mipi_dsi->disp_power_on)
+ regulator_disable(mipi_dsi->disp_power_on);
+
+ return ret;
+}
+
+static void mipi_dsi_shutdown(struct platform_device *pdev)
+{
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ mipi_dsi_power_off(mipi_dsi->disp_mipi);
+ mipi_dsi_dphy_power_down();
+}
+
+static int mipi_dsi_remove(struct platform_device *pdev)
+{
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ mxc_dispdrv_puthandle(mipi_dsi->disp_mipi);
+ mxc_dispdrv_unregister(mipi_dsi->disp_mipi);
+
+ if (mipi_dsi->disp_power_on)
+ regulator_disable(mipi_dsi->disp_power_on);
+
+ kfree(mipi_dsi->lcd_panel);
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static int mipi_dsi_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ if (mipi_dsi->dsi_power_on) {
+ release_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "mipi dsi busfreq high release.\n");
+
+ mipi_dsi_dphy_power_down();
+ mipi_dsi->dsi_power_on = 0;
+ }
+
+ return 0;
+}
+
+static int mipi_dsi_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mipi_dsi_info *mipi_dsi = dev_get_drvdata(&pdev->dev);
+
+ if (!mipi_dsi->dsi_power_on) {
+ request_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "mipi dsi busfreq high request.\n");
+
+ mipi_dsi_dphy_power_on(pdev);
+ mipi_dsi->dsi_power_on = 1;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops mipi_dsi_pm_ops = {
+ .runtime_suspend = mipi_dsi_runtime_suspend,
+ .runtime_resume = mipi_dsi_runtime_resume,
+ .runtime_idle = NULL,
+};
+
+static struct platform_driver mipi_dsi_driver = {
+ .driver = {
+ .of_match_table = imx_mipi_dsi_dt_ids,
+ .name = "mxc_mipi_dsi_samsung",
+ .pm = &mipi_dsi_pm_ops,
+ },
+ .probe = mipi_dsi_probe,
+ .remove = mipi_dsi_remove,
+ .shutdown = mipi_dsi_shutdown,
+};
+
+static int __init mipi_dsi_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&mipi_dsi_driver);
+ if (err) {
+ pr_err("mipi_dsi_driver register failed\n");
+ return err;
+ }
+
+ pr_debug("MIPI DSI driver module loaded: %s\n", mipi_dsi_driver.driver.name);
+
+ return 0;
+}
+
+static void __exit mipi_dsi_cleanup(void)
+{
+ platform_driver_unregister(&mipi_dsi_driver);
+}
+
+module_init(mipi_dsi_init);
+module_exit(mipi_dsi_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX MIPI DSI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mxc/mxc_dcic.c b/drivers/video/fbdev/mxc/mxc_dcic.c
new file mode 100644
index 000000000000..cae872a05f7f
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_dcic.c
@@ -0,0 +1,592 @@
+/*
+ * Copyright (C) 2014-2015 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
+ */
+#include <linux/clk.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioctl.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/module.h>
+#include <linux/mxc_dcic.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <video/videomode.h>
+#include <video/of_videomode.h>
+
+#define DRIVER_NAME "mxc_dcic"
+
+#define DCIC_IPU1_DI0 "dcic-ipu1-di0"
+#define DCIC_IPU1_DI1 "dcic-ipu1-di1"
+#define DCIC_IPU2_DI0 "dcic-ipu2-di0"
+#define DCIC_IPU2_DI1 "dcic-ipu2-di1"
+#define DCIC_LCDIF "dcic-lcdif"
+#define DCIC_LCDIF1 "dcic-lcdif1"
+#define DCIC_LCDIF2 "dcic-lcdif2"
+#define DCIC_LVDS "dcic-lvds"
+#define DCIC_LVDS0 "dcic-lvds0"
+#define DCIC_LVDS1 "dcic-lvds1"
+#define DCIC_HDMI "dcic-hdmi"
+
+#define DCIC0_DEV_NAME "mxc_dcic0"
+#define DCIC1_DEV_NAME "mxc_dcic1"
+
+#define FB_SYNC_OE_LOW_ACT 0x80000000
+#define FB_SYNC_CLK_LAT_FALL 0x40000000
+
+static const struct dcic_mux imx6q_dcic0_mux[] = {
+ {
+ .dcic = DCIC_IPU1_DI0,
+ .val = IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI0,
+ }, {
+ .dcic = DCIC_LVDS0,
+ .val = IMX6Q_GPR10_DCIC1_MUX_CTL_LVDS0,
+ }, {
+ .dcic = DCIC_LVDS1,
+ .val = IMX6Q_GPR10_DCIC1_MUX_CTL_LVDS1,
+ }, {
+ .dcic = DCIC_HDMI,
+ .val = IMX6Q_GPR10_DCIC1_MUX_CTL_HDMI,
+ }
+};
+
+static const struct dcic_mux imx6q_dcic1_mux[] = {
+ {
+ .dcic = DCIC_IPU1_DI1,
+ .val = IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI1,
+ }, {
+ .dcic = DCIC_LVDS0,
+ .val = IMX6Q_GPR10_DCIC2_MUX_CTL_LVDS0,
+ }, {
+ .dcic = DCIC_LVDS1,
+ .val = IMX6Q_GPR10_DCIC2_MUX_CTL_LVDS1,
+ }, {
+ .dcic = DCIC_HDMI,
+ .val = IMX6Q_GPR10_DCIC2_MUX_CTL_MIPI,
+ }
+};
+
+static const struct bus_mux imx6q_dcic_buses[] = {
+ {
+ .name = DCIC0_DEV_NAME,
+ .reg = IOMUXC_GPR10,
+ .shift = 0,
+ .mask = IMX6Q_GPR10_DCIC1_MUX_CTL_MASK,
+ .dcic_mux_num = ARRAY_SIZE(imx6q_dcic0_mux),
+ .dcics = imx6q_dcic0_mux,
+ }, {
+ .name = DCIC1_DEV_NAME,
+ .reg = IOMUXC_GPR10,
+ .shift = 2,
+ .mask = IMX6Q_GPR10_DCIC2_MUX_CTL_MASK,
+ .dcic_mux_num = ARRAY_SIZE(imx6q_dcic1_mux),
+ .dcics = imx6q_dcic1_mux,
+ }
+};
+
+static const struct dcic_info imx6q_dcic_info = {
+ .bus_mux_num = ARRAY_SIZE(imx6q_dcic_buses),
+ .buses = imx6q_dcic_buses,
+};
+
+static const struct dcic_mux imx6sx_dcic0_mux[] = {
+ {
+ .dcic = DCIC_LCDIF1,
+ .val = IMX6SX_GPR5_DISP_MUX_DCIC1_LCDIF1,
+ }, {
+ .dcic = DCIC_LVDS,
+ .val = IMX6SX_GPR5_DISP_MUX_DCIC1_LVDS,
+ }
+};
+
+static const struct dcic_mux imx6sx_dcic1_mux[] = {
+ {
+ .dcic = DCIC_LCDIF2,
+ .val = IMX6SX_GPR5_DISP_MUX_DCIC2_LCDIF2,
+ }, {
+ .dcic = DCIC_LVDS,
+ .val = IMX6SX_GPR5_DISP_MUX_DCIC2_LVDS,
+ }
+};
+
+static const struct bus_mux imx6sx_dcic_buses[] = {
+ {
+ .name = DCIC0_DEV_NAME,
+ .reg = IOMUXC_GPR5,
+ .shift = 1,
+ .mask = IMX6SX_GPR5_DISP_MUX_DCIC1_MASK,
+ .dcic_mux_num = ARRAY_SIZE(imx6sx_dcic0_mux),
+ .dcics = imx6sx_dcic0_mux,
+ }, {
+ .name = DCIC1_DEV_NAME,
+ .reg = IOMUXC_GPR5,
+ .shift = 2,
+ .mask = IMX6SX_GPR5_DISP_MUX_DCIC2_MASK,
+ .dcic_mux_num = ARRAY_SIZE(imx6sx_dcic1_mux),
+ .dcics = imx6sx_dcic1_mux,
+ }
+};
+
+static const struct dcic_info imx6sx_dcic_info = {
+ .bus_mux_num = ARRAY_SIZE(imx6sx_dcic_buses),
+ .buses = imx6sx_dcic_buses,
+};
+
+static const struct of_device_id dcic_dt_ids[] = {
+ { .compatible = "fsl,imx6q-dcic", .data = &imx6q_dcic_info, },
+ { .compatible = "fsl,imx6sx-dcic", .data = &imx6sx_dcic_info, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dcic_dt_ids);
+
+static int of_get_dcic_val(struct device_node *np, struct dcic_data *dcic)
+{
+ const char *mux;
+ int ret;
+ u32 i, dcic_id;
+
+ ret = of_property_read_string(np, "dcic_mux", &mux);
+ if (ret < 0) {
+ dev_err(dcic->dev, "Can not get dcic_mux\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "dcic_id", &dcic_id);
+ if (ret < 0) {
+ dev_err(dcic->dev, "Can not get dcic_id\n");
+ return ret;
+ }
+
+ dcic->bus_n = dcic_id;
+
+ for (i = 0; i < dcic->buses[dcic_id].dcic_mux_num; i++)
+ if (!strcmp(mux, dcic->buses[dcic_id].dcics[i].dcic)) {
+ dcic->mux_n = i;
+ return dcic->buses[dcic_id].dcics[i].val;
+ }
+
+ return -EINVAL;
+}
+
+static void dcic_enable(struct dcic_data *dcic)
+{
+ u32 val;
+
+ val = readl(&dcic->regs->dcicc);
+ val |= DCICC_IC_ENABLE;
+ writel(val, &dcic->regs->dcicc);
+}
+
+void dcic_disable(struct dcic_data *dcic)
+{
+ u32 val;
+
+ val = readl(&dcic->regs->dcicc);
+ val &= ~DCICC_IC_MASK;
+ val |= DCICC_IC_DISABLE;
+ writel(val, &dcic->regs->dcicc);
+}
+
+static void roi_enable(struct dcic_data *dcic, struct roi_params *roi_param)
+{
+ u32 val;
+ u32 roi_n = roi_param->roi_n;
+
+ val = readl(&dcic->regs->ROI[roi_n].dcicrc);
+ val |= DCICRC_ROI_ENABLE;
+ if (roi_param->freeze)
+ val |= DCICRC_ROI_FROZEN;
+ writel(val, &dcic->regs->ROI[roi_n].dcicrc);
+}
+
+static void roi_disable(struct dcic_data *dcic, u32 roi_n)
+{
+ u32 val;
+
+ val = readl(&dcic->regs->ROI[roi_n].dcicrc);
+ val &= ~DCICRC_ROI_ENABLE;
+ writel(val, &dcic->regs->ROI[roi_n].dcicrc);
+}
+
+static bool roi_configure(struct dcic_data *dcic, struct roi_params *roi_param)
+{
+ struct roi_regs *roi_reg;
+ u32 val;
+
+ if (roi_param->roi_n < 0 || roi_param->roi_n >= 16) {
+ printk(KERN_ERR "Error, Wrong ROI number %d\n", roi_param->roi_n);
+ return false;
+ }
+
+ if (roi_param->end_x <= roi_param->start_x ||
+ roi_param->end_y <= roi_param->start_y) {
+ printk(KERN_ERR "Error, Wrong ROI\n");
+ return false;
+ }
+
+ roi_reg = (struct roi_regs *) &dcic->regs->ROI[roi_param->roi_n];
+
+ /* init roi block size */
+ val = roi_param->start_y << 16 | roi_param->start_x;
+ writel(val, &roi_reg->dcicrc);
+
+ val = roi_param->end_y << 16 | roi_param->end_x;
+ writel(val, &roi_reg->dcicrs);
+
+ writel(roi_param->ref_sig, &roi_reg->dcicrrs);
+
+ roi_enable(dcic, roi_param);
+ return true;
+}
+
+static void dcic_int_enable(struct dcic_data *dcic)
+{
+ u32 val;
+
+ /* Clean pending interrupt before enable int */
+ writel(DCICS_FI_STAT_PENDING, &dcic->regs->dcics);
+ writel(0xffffffff, &dcic->regs->dcics);
+
+ /* Enable function interrupt */
+ val = readl(&dcic->regs->dcicic);
+ val &= ~DCICIC_FUN_INT_MASK;
+ val |= DCICIC_FUN_INT_ENABLE;
+ writel(val, &dcic->regs->dcicic);
+}
+
+static void dcic_int_disable(struct dcic_data *dcic)
+{
+ u32 val;
+
+ /* Disable both function and error interrupt */
+ val = readl(&dcic->regs->dcicic);
+ val = DCICIC_ERROR_INT_DISABLE | DCICIC_FUN_INT_DISABLE;
+ writel(val, &dcic->regs->dcicic);
+}
+
+static irqreturn_t dcic_irq_handler(int irq, void *data)
+{
+ u32 i;
+
+ struct dcic_data *dcic = data;
+ u32 dcics = readl(&dcic->regs->dcics);
+
+ dcic->result = dcics & 0xffff;
+
+ dcic_int_disable(dcic);
+
+ /* clean dcic interrupt state */
+ writel(DCICS_FI_STAT_PENDING, &dcic->regs->dcics);
+ writel(dcics, &dcic->regs->dcics);
+
+ for (i = 0; i < 16; i++) {
+ printk(KERN_INFO "ROI=%d,crcRS=0x%x, crcCS=0x%x\n", i,
+ readl(&dcic->regs->ROI[i].dcicrrs),
+ readl(&dcic->regs->ROI[i].dcicrcs));
+ }
+ complete(&dcic->roi_crc_comp);
+
+ return 0;
+}
+
+static int dcic_configure(struct dcic_data *dcic, unsigned int sync)
+{
+ u32 val;
+ val = 0;
+
+ /* vsync, hsync, DE, clk_pol */
+ if (!(sync & FB_SYNC_HOR_HIGH_ACT))
+ val |= DCICC_HSYNC_POL_ACTIVE_LOW;
+ if (!(sync & FB_SYNC_VERT_HIGH_ACT))
+ val |= DCICC_VSYNC_POL_ACTIVE_LOW;
+ if (sync & FB_SYNC_OE_LOW_ACT)
+ val |= DCICC_DE_ACTIVE_LOW;
+ if (sync & FB_SYNC_CLK_LAT_FALL)
+ val |= DCICC_CLK_POL_INVERTED;
+
+ writel(val, &dcic->regs->dcicc);
+ return 0;
+}
+
+static int dcic_open(struct inode *inode, struct file *file)
+{
+ struct dcic_data *dcic;
+
+ dcic = container_of(inode->i_cdev, struct dcic_data, cdev);
+
+ mutex_lock(&dcic->lock);
+
+ clk_prepare_enable(dcic->disp_axi_clk);
+ clk_prepare_enable(dcic->dcic_clk);
+
+ file->private_data = dcic;
+ mutex_unlock(&dcic->lock);
+ return 0;
+}
+
+static int dcic_release(struct inode *inode, struct file *file)
+{
+ struct dcic_data *dcic = file->private_data;
+ u32 i;
+
+ mutex_lock(&dcic->lock);
+
+ for (i = 0; i < 16; i++)
+ roi_disable(dcic, i);
+
+ clk_disable_unprepare(dcic->dcic_clk);
+ clk_disable_unprepare(dcic->disp_axi_clk);
+
+ mutex_unlock(&dcic->lock);
+ return 0;
+}
+
+static int dcic_init(struct device_node *np, struct dcic_data *dcic)
+{
+ u32 val, bus;
+
+ val = of_get_dcic_val(np, dcic);
+ if (val < 0) {
+ printk(KERN_ERR "Error incorrect\n");
+ return -1;
+ }
+
+ bus = dcic->bus_n;
+
+ regmap_update_bits(dcic->regmap, dcic->buses[bus].reg ,
+ dcic->buses[bus].mask, val);
+
+ return 0;
+}
+
+static long dcic_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int __user *argp = (void __user *)arg;
+ struct dcic_data *dcic = file->private_data;
+ struct roi_params roi_param;
+ unsigned int sync;
+ int ret = 0;
+
+ switch (cmd) {
+ case DCIC_IOC_CONFIG_DCIC:
+ if (!copy_from_user(&sync, argp, sizeof(unsigned int)))
+ dcic_configure(dcic, sync);
+ break;
+ case DCIC_IOC_CONFIG_ROI:
+ if (copy_from_user(&roi_param, argp, sizeof(roi_param)))
+ return -EFAULT;
+ else
+ if (!roi_configure(dcic, &roi_param))
+ return -EINVAL;
+ break;
+ case DCIC_IOC_GET_RESULT:
+ init_completion(&dcic->roi_crc_comp);
+
+ dcic_enable(dcic);
+
+ dcic->result = 0;
+ msleep(25);
+
+ dcic_int_enable(dcic);
+
+ ret = wait_for_completion_interruptible_timeout(
+ &dcic->roi_crc_comp, 1 * HZ);
+ if (ret == 0) {
+ dev_err(dcic->dev,
+ "dcic wait for roi crc cal timeout\n");
+ ret = -ETIME;
+ } else if (ret > 0) {
+ if (copy_to_user(argp, &dcic->result, sizeof(dcic->result)))
+ return -EFAULT;
+ ret = 0;
+ }
+ dcic_disable(dcic);
+ break;
+ default:
+ printk(KERN_ERR "%s, Unsupport cmd %d\n", __func__, cmd);
+ break;
+ }
+ return ret;
+}
+
+
+static const struct file_operations mxc_dcic_fops = {
+ .owner = THIS_MODULE,
+ .open = dcic_open,
+ .release = dcic_release,
+ .unlocked_ioctl = dcic_ioctl,
+};
+
+static int dcic_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id =
+ of_match_device(dcic_dt_ids, dev);
+ const struct dcic_info *dcic_info =
+ (const struct dcic_info *)of_id->data;
+ struct device_node *np = dev->of_node;
+ struct dcic_data *dcic;
+ struct resource *res;
+ const char *name;
+ dev_t devt;
+ int ret = 0;
+ int irq;
+
+ dcic = devm_kzalloc(&pdev->dev,
+ sizeof(struct dcic_data),
+ GFP_KERNEL);
+ if (!dcic) {
+ dev_err(&pdev->dev, "Cannot allocate device data\n");
+ ret = -ENOMEM;
+ goto ealloc;
+ }
+
+ platform_set_drvdata(pdev, dcic);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "No dcic base address found.\n");
+ ret = -ENODEV;
+ goto ealloc;
+ }
+
+ dcic->regs = (struct dcic_regs *) devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!dcic->regs) {
+ dev_err(&pdev->dev, "ioremap failed with dcic base\n");
+ ret = -ENOMEM;
+ goto ealloc;
+ }
+
+ dcic->dev = dev;
+ dcic->buses = dcic_info->buses;
+
+ dcic->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
+ if (IS_ERR(dcic->regmap)) {
+ dev_err(dev, "failed to get parent regmap\n");
+ ret = PTR_ERR(dcic->regmap);
+ goto ealloc;
+ }
+
+ /* clock */
+ dcic->disp_axi_clk = devm_clk_get(&pdev->dev, "disp-axi");
+ if (IS_ERR(dcic->disp_axi_clk)) {
+ dev_err(&pdev->dev, "get disp-axi clock failed\n");
+ ret = PTR_ERR(dcic->disp_axi_clk);
+ goto ealloc;
+ }
+
+ dcic->dcic_clk = devm_clk_get(&pdev->dev, "dcic");
+ if (IS_ERR(dcic->dcic_clk)) {
+ dev_err(&pdev->dev, "get dcic clk failed\n");
+ ret = PTR_ERR(dcic->dcic_clk);
+ goto ealloc;
+ }
+
+ mutex_init(&dcic->lock);
+ ret = dcic_init(np, dcic);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed init dcic\n");
+ goto ealloc;
+ }
+
+ /* register device */
+ name = dcic->buses[dcic->bus_n].name;
+ dcic->major = register_chrdev(0, name, &mxc_dcic_fops);
+ if (dcic->major < 0) {
+ printk(KERN_ERR "DCIC: unable to get a major for dcic\n");
+ ret = -EBUSY;
+ goto ealloc;
+ }
+
+ dcic->class = class_create(THIS_MODULE, name);
+ if (IS_ERR(dcic->class)) {
+ ret = PTR_ERR(dcic->class);
+ goto err_out_chrdev;
+ }
+
+ /* create char device */
+ devt = MKDEV(dcic->major, 0);
+ dcic->devt = devt;
+
+ cdev_init(&dcic->cdev, &mxc_dcic_fops);
+ dcic->cdev.owner = THIS_MODULE;
+ ret = cdev_add(&dcic->cdev, devt, 1);
+ if (ret)
+ goto err_out_class;
+
+ device_create(dcic->class, NULL, devt,
+ NULL, name);
+
+ /* IRQ */
+ irq = platform_get_irq(pdev, 0);
+
+ ret = devm_request_irq(&pdev->dev, irq, dcic_irq_handler, 0,
+ dev_name(&pdev->dev), dcic);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
+ irq, ret);
+ goto err_out_cdev;
+ }
+
+ return 0;
+
+err_out_cdev:
+ cdev_del(&dcic->cdev);
+err_out_class:
+ device_destroy(dcic->class, devt);
+ class_destroy(dcic->class);
+err_out_chrdev:
+ unregister_chrdev(dcic->major, name);
+ealloc:
+ return ret;
+}
+
+static int dcic_remove(struct platform_device *pdev)
+{
+ struct dcic_data *dcic = platform_get_drvdata(pdev);
+ const char *name;
+
+ name = dcic->buses[dcic->bus_n].name;
+
+ device_destroy(dcic->class, dcic->devt);
+ cdev_del(&dcic->cdev);
+ class_destroy(dcic->class);
+ unregister_chrdev(dcic->major, name);
+ mutex_destroy(&dcic->lock);
+
+ return 0;
+}
+
+static struct platform_driver dcic_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = dcic_dt_ids,
+ },
+ .probe = dcic_probe,
+ .remove = dcic_remove,
+};
+
+module_platform_driver(dcic_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC DCIC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/video/fbdev/mxc/mxc_dispdrv.c b/drivers/video/fbdev/mxc/mxc_dispdrv.c
new file mode 100644
index 000000000000..77c0d50babea
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_dispdrv.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2011-2015 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 mxc_dispdrv.c
+ * @brief mxc display driver framework.
+ *
+ * A display device driver could call mxc_dispdrv_register(drv) in its dev_probe() function.
+ * Move all dev_probe() things into mxc_dispdrv_driver->init(), init() function should init
+ * and feedback setting;
+ * Move all dev_remove() things into mxc_dispdrv_driver->deinit();
+ * Move all dev_suspend() things into fb_notifier for SUSPEND, if there is;
+ * Move all dev_resume() things into fb_notifier for RESUME, if there is;
+ *
+ * mxc fb driver could call mxc_dispdrv_gethandle(name, setting) before a fb
+ * need be added, with fbi param passing by setting, after
+ * mxc_dispdrv_gethandle() return, FB driver should get the basic setting
+ * about fbi info and crtc.
+ *
+ * @ingroup Framebuffer
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include "mxc_dispdrv.h"
+
+static LIST_HEAD(dispdrv_list);
+static DEFINE_MUTEX(dispdrv_lock);
+
+struct mxc_dispdrv_entry {
+ /* Note: drv always the first element */
+ struct mxc_dispdrv_driver *drv;
+ bool active;
+ void *priv;
+ struct list_head list;
+};
+
+struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv)
+{
+ struct mxc_dispdrv_entry *new;
+
+ mutex_lock(&dispdrv_lock);
+
+ new = kzalloc(sizeof(struct mxc_dispdrv_entry), GFP_KERNEL);
+ if (!new) {
+ mutex_unlock(&dispdrv_lock);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ new->drv = drv;
+ list_add_tail(&new->list, &dispdrv_list);
+
+ mutex_unlock(&dispdrv_lock);
+
+ return (struct mxc_dispdrv_handle *)new;
+}
+EXPORT_SYMBOL_GPL(mxc_dispdrv_register);
+
+int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle)
+{
+ struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
+
+ if (entry) {
+ mutex_lock(&dispdrv_lock);
+ list_del(&entry->list);
+ mutex_unlock(&dispdrv_lock);
+ kfree(entry);
+ return 0;
+ } else
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(mxc_dispdrv_unregister);
+
+struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name,
+ struct mxc_dispdrv_setting *setting)
+{
+ int ret = -ENODEV, found = 0;
+ struct mxc_dispdrv_entry *entry;
+
+ mutex_lock(&dispdrv_lock);
+ list_for_each_entry(entry, &dispdrv_list, list) {
+ if (!strcmp(entry->drv->name, name) && (entry->drv->init)) {
+ ret = entry->drv->init((struct mxc_dispdrv_handle *)
+ entry, setting);
+ if (ret >= 0) {
+ entry->active = true;
+ found = 1;
+ break;
+ }
+ }
+ }
+ mutex_unlock(&dispdrv_lock);
+
+ return found ? (struct mxc_dispdrv_handle *)entry:ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(mxc_dispdrv_gethandle);
+
+void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle)
+{
+ struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
+
+ mutex_lock(&dispdrv_lock);
+ if (entry && entry->active && entry->drv->deinit) {
+ entry->drv->deinit(handle);
+ entry->active = false;
+ }
+ mutex_unlock(&dispdrv_lock);
+
+}
+EXPORT_SYMBOL_GPL(mxc_dispdrv_puthandle);
+
+int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data)
+{
+ struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
+
+ if (entry) {
+ entry->priv = data;
+ return 0;
+ } else
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(mxc_dispdrv_setdata);
+
+void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle)
+{
+ struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle;
+
+ if (entry) {
+ return entry->priv;
+ } else
+ return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(mxc_dispdrv_getdata);
diff --git a/drivers/video/fbdev/mxc/mxc_dispdrv.h b/drivers/video/fbdev/mxc/mxc_dispdrv.h
new file mode 100644
index 000000000000..58d8a07d3380
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_dispdrv.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2014 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
+ */
+#ifndef __MXC_DISPDRV_H__
+#define __MXC_DISPDRV_H__
+#include <linux/fb.h>
+#include "crtc.h"
+
+struct mxc_dispdrv_handle {
+ struct mxc_dispdrv_driver *drv;
+};
+
+struct mxc_dispdrv_setting {
+ /*input-feedback parameter*/
+ struct fb_info *fbi;
+ int if_fmt;
+ int default_bpp;
+ char *dft_mode_str;
+
+ /* feedback parameter */
+ enum crtc crtc;
+};
+
+struct mxc_dispdrv_driver {
+ const char *name;
+ int (*init) (struct mxc_dispdrv_handle *, struct mxc_dispdrv_setting *);
+ void (*deinit) (struct mxc_dispdrv_handle *);
+ /* display driver enable function for extension */
+ int (*enable) (struct mxc_dispdrv_handle *, struct fb_info *);
+ /* display driver disable function, called at early part of fb_blank */
+ void (*disable) (struct mxc_dispdrv_handle *, struct fb_info *);
+ /* display driver setup function, called at early part of fb_set_par */
+ int (*setup) (struct mxc_dispdrv_handle *, struct fb_info *fbi);
+};
+
+struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv);
+int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle);
+struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name,
+ struct mxc_dispdrv_setting *setting);
+void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle);
+int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data);
+void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle);
+#endif
diff --git a/drivers/video/fbdev/mxc/mxc_edid.c b/drivers/video/fbdev/mxc/mxc_edid.c
new file mode 100644
index 000000000000..23110ce784db
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_edid.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright 2009-2015 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
+ */
+
+/*!
+ * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
+ */
+
+/*!
+ * @file mxc_edid.c
+ *
+ * @brief MXC EDID driver
+ *
+ * @ingroup Framebuffer
+ */
+
+/*!
+ * Include files
+ */
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <video/mxc_edid.h>
+#include "../edid.h"
+
+#undef DEBUG /* define this for verbose EDID parsing output */
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(fmt, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+const struct fb_videomode mxc_cea_mode[64] = {
+ /* #1: 640x480p@59.94/60Hz 4:3 */
+ [1] = {
+ NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
+ },
+ /* #2: 720x480p@59.94/60Hz 4:3 */
+ [2] = {
+ NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
+ },
+ /* #3: 720x480p@59.94/60Hz 16:9 */
+ [3] = {
+ NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #4: 1280x720p@59.94/60Hz 16:9 */
+ [4] = {
+ NULL, 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
+ },
+ /* #5: 1920x1080i@59.94/60Hz 16:9 */
+ [5] = {
+ NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #6: 720(1440)x480iH@59.94/60Hz 4:3 */
+ [6] = {
+ NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
+ FB_VMODE_INTERLACED | FB_VMODE_ASPECT_4_3, 0,
+ },
+ /* #7: 720(1440)x480iH@59.94/60Hz 16:9 */
+ [7] = {
+ NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
+ FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #8: 720(1440)x240pH@59.94/60Hz 4:3 */
+ [8] = {
+ NULL, 60, 1440, 240, 37108, 114, 38, 15, 4, 124, 3, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
+ },
+ /* #9: 720(1440)x240pH@59.94/60Hz 16:9 */
+ [9] = {
+ NULL, 60, 1440, 240, 37108, 114, 38, 15, 4, 124, 3, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #14: 1440x480p@59.94/60Hz 4:3 */
+ [14] = {
+ NULL, 60, 1440, 480, 18500, 120, 32, 30, 9, 124, 6, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
+ },
+ /* #15: 1440x480p@59.94/60Hz 16:9 */
+ [15] = {
+ NULL, 60, 1440, 480, 18500, 120, 32, 30, 9, 124, 6, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #16: 1920x1080p@60Hz 16:9 */
+ [16] = {
+ NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #17: 720x576pH@50Hz 4:3 */
+ [17] = {
+ NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
+ },
+ /* #18: 720x576pH@50Hz 16:9 */
+ [18] = {
+ NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #19: 1280x720p@50Hz */
+ [19] = {
+ NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #20: 1920x1080i@50Hz */
+ [20] = {
+ NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #23: 720(1440)x288pH@50Hz 4:3 */
+ [23] = {
+ NULL, 50, 1440, 288, 37037, 138, 24, 19, 2, 126, 3, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
+ },
+ /* #24: 720(1440)x288pH@50Hz 16:9 */
+ [24] = {
+ NULL, 50, 1440, 288, 37037, 138, 24, 19, 2, 126, 3, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #29: 720(1440)x576pH@50Hz 4:3 */
+ [29] = {
+ NULL, 50, 1440, 576, 18518, 136, 24, 39, 5, 128, 5, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
+ },
+ /* #30: 720(1440)x576pH@50Hz 16:9 */
+ [30] = {
+ NULL, 50, 1440, 576, 18518, 136, 24, 39, 5, 128, 5, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #31: 1920x1080p@50Hz */
+ [31] = {
+ NULL, 50, 1920, 1080, 6734, 148, 528, 36, 4, 44, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #32: 1920x1080p@23.98/24Hz */
+ [32] = {
+ NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #33: 1920x1080p@25Hz */
+ [33] = {
+ NULL, 25, 1920, 1080, 13468, 148, 528, 36, 4, 44, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #34: 1920x1080p@30Hz */
+ [34] = {
+ NULL, 30, 1920, 1080, 13468, 148, 88, 36, 4, 44, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
+ },
+ /* #41: 1280x720p@100Hz 16:9 */
+ [41] = {
+ NULL, 100, 1280, 720, 6734, 220, 440, 20, 5, 40, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
+ },
+ /* #47: 1280x720p@119.88/120Hz 16:9 */
+ [47] = {
+ NULL, 120, 1280, 720, 6734, 220, 110, 20, 5, 40, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
+ },
+};
+
+/*
+ * We have a special version of fb_mode_is_equal that ignores
+ * pixclock, since for many CEA modes, 2 frequencies are supported
+ * e.g. 640x480 @ 60Hz or 59.94Hz
+ */
+int mxc_edid_fb_mode_is_equal(bool use_aspect,
+ const struct fb_videomode *mode1,
+ const struct fb_videomode *mode2)
+{
+ u32 mask;
+
+ if (use_aspect)
+ mask = ~0;
+ else
+ mask = ~FB_VMODE_ASPECT_MASK;
+
+ return (mode1->xres == mode2->xres &&
+ mode1->yres == mode2->yres &&
+ mode1->hsync_len == mode2->hsync_len &&
+ mode1->vsync_len == mode2->vsync_len &&
+ mode1->left_margin == mode2->left_margin &&
+ mode1->right_margin == mode2->right_margin &&
+ mode1->upper_margin == mode2->upper_margin &&
+ mode1->lower_margin == mode2->lower_margin &&
+ mode1->sync == mode2->sync &&
+ /* refresh check, 59.94Hz and 60Hz have the same parameter
+ * in struct of mxc_cea_mode */
+ abs(mode1->refresh - mode2->refresh) <= 1 &&
+ (mode1->vmode & mask) == (mode2->vmode & mask));
+}
+
+static void get_detailed_timing(unsigned char *block,
+ struct fb_videomode *mode)
+{
+ mode->xres = H_ACTIVE;
+ mode->yres = V_ACTIVE;
+ mode->pixclock = PIXEL_CLOCK;
+ mode->pixclock /= 1000;
+ mode->pixclock = KHZ2PICOS(mode->pixclock);
+ mode->right_margin = H_SYNC_OFFSET;
+ mode->left_margin = (H_ACTIVE + H_BLANKING) -
+ (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+ mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+ V_SYNC_WIDTH;
+ mode->lower_margin = V_SYNC_OFFSET;
+ mode->hsync_len = H_SYNC_WIDTH;
+ mode->vsync_len = V_SYNC_WIDTH;
+ if (HSYNC_POSITIVE)
+ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (VSYNC_POSITIVE)
+ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+ mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
+ (V_ACTIVE + V_BLANKING));
+ if (INTERLACED) {
+ mode->yres *= 2;
+ mode->upper_margin *= 2;
+ mode->lower_margin *= 2;
+ mode->vsync_len *= 2;
+ mode->vmode |= FB_VMODE_INTERLACED;
+ }
+ mode->flag = FB_MODE_IS_DETAILED;
+
+ if ((H_SIZE / 16) == (V_SIZE / 9))
+ mode->vmode |= FB_VMODE_ASPECT_16_9;
+ else if ((H_SIZE / 4) == (V_SIZE / 3))
+ mode->vmode |= FB_VMODE_ASPECT_4_3;
+ else if ((mode->xres / 16) == (mode->yres / 9))
+ mode->vmode |= FB_VMODE_ASPECT_16_9;
+ else if ((mode->xres / 4) == (mode->yres / 3))
+ mode->vmode |= FB_VMODE_ASPECT_4_3;
+
+ if (mode->vmode & FB_VMODE_ASPECT_16_9)
+ DPRINTK("Aspect ratio: 16:9\n");
+ if (mode->vmode & FB_VMODE_ASPECT_4_3)
+ DPRINTK("Aspect ratio: 4:3\n");
+ DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
+ DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
+ H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
+ DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
+ V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+ DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
+ (VSYNC_POSITIVE) ? "+" : "-");
+}
+
+int mxc_edid_parse_ext_blk(unsigned char *edid,
+ struct mxc_edid_cfg *cfg,
+ struct fb_monspecs *specs)
+{
+ char detail_timing_desc_offset;
+ struct fb_videomode *mode, *m;
+ unsigned char index = 0x0;
+ unsigned char *block;
+ int i, num = 0, revision;
+
+ if (edid[index++] != 0x2) /* only support cea ext block now */
+ return 0;
+ revision = edid[index++];
+ DPRINTK("cea extent revision %d\n", revision);
+ mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
+ if (mode == NULL)
+ return -1;
+
+ detail_timing_desc_offset = edid[index++];
+
+ if (revision >= 2) {
+ cfg->cea_underscan = (edid[index] >> 7) & 0x1;
+ cfg->cea_basicaudio = (edid[index] >> 6) & 0x1;
+ cfg->cea_ycbcr444 = (edid[index] >> 5) & 0x1;
+ cfg->cea_ycbcr422 = (edid[index] >> 4) & 0x1;
+
+ DPRINTK("CEA underscan %d\n", cfg->cea_underscan);
+ DPRINTK("CEA basicaudio %d\n", cfg->cea_basicaudio);
+ DPRINTK("CEA ycbcr444 %d\n", cfg->cea_ycbcr444);
+ DPRINTK("CEA ycbcr422 %d\n", cfg->cea_ycbcr422);
+ }
+
+ if (revision >= 3) {
+ /* short desc */
+ DPRINTK("CEA Short desc timmings\n");
+ index++;
+ while (index < detail_timing_desc_offset) {
+ unsigned char tagcode, blklen;
+
+ tagcode = (edid[index] >> 5) & 0x7;
+ blklen = (edid[index]) & 0x1f;
+
+ DPRINTK("Tagcode %x Len %d\n", tagcode, blklen);
+
+ switch (tagcode) {
+ case 0x2: /*Video data block*/
+ {
+ int cea_idx;
+ i = 0;
+ while (i < blklen) {
+ index++;
+ cea_idx = edid[index] & 0x7f;
+ if (cea_idx < ARRAY_SIZE(mxc_cea_mode) &&
+ (mxc_cea_mode[cea_idx].xres)) {
+ DPRINTK("Support CEA Format #%d\n", cea_idx);
+ mode[num] = mxc_cea_mode[cea_idx];
+ mode[num].flag |= FB_MODE_IS_STANDARD;
+ num++;
+ }
+ i++;
+ }
+ break;
+ }
+ case 0x3: /*Vendor specific data*/
+ {
+ unsigned char IEEE_reg_iden[3];
+ unsigned char deep_color;
+ unsigned char latency_present;
+ unsigned char I_latency_present;
+ unsigned char hdmi_video_present;
+ unsigned char hdmi_3d_present;
+ unsigned char hdmi_3d_multi_present;
+ unsigned char hdmi_vic_len;
+ unsigned char hdmi_3d_len;
+ unsigned char index_inc = 0;
+ unsigned char vsd_end;
+
+ vsd_end = index + blklen;
+
+ IEEE_reg_iden[0] = edid[index+1];
+ IEEE_reg_iden[1] = edid[index+2];
+ IEEE_reg_iden[2] = edid[index+3];
+ cfg->physical_address[0] = (edid[index+4] & 0xf0) >> 4;
+ cfg->physical_address[1] = (edid[index+4] & 0x0f);
+ cfg->physical_address[2] = (edid[index+5] & 0xf0) >> 4;
+ cfg->physical_address[3] = (edid[index+5] & 0x0f);
+
+ if ((IEEE_reg_iden[0] == 0x03) &&
+ (IEEE_reg_iden[1] == 0x0c) &&
+ (IEEE_reg_iden[2] == 0x00))
+ cfg->hdmi_cap = 1;
+
+ if (blklen > 5) {
+ deep_color = edid[index+6];
+ if (deep_color & 0x80)
+ cfg->vsd_support_ai = true;
+ if (deep_color & 0x40)
+ cfg->vsd_dc_48bit = true;
+ if (deep_color & 0x20)
+ cfg->vsd_dc_36bit = true;
+ if (deep_color & 0x10)
+ cfg->vsd_dc_30bit = true;
+ if (deep_color & 0x08)
+ cfg->vsd_dc_y444 = true;
+ if (deep_color & 0x01)
+ cfg->vsd_dvi_dual = true;
+ }
+
+ DPRINTK("VSD hdmi capability %d\n", cfg->hdmi_cap);
+ DPRINTK("VSD support ai %d\n", cfg->vsd_support_ai);
+ DPRINTK("VSD support deep color 48bit %d\n", cfg->vsd_dc_48bit);
+ DPRINTK("VSD support deep color 36bit %d\n", cfg->vsd_dc_36bit);
+ DPRINTK("VSD support deep color 30bit %d\n", cfg->vsd_dc_30bit);
+ DPRINTK("VSD support deep color y444 %d\n", cfg->vsd_dc_y444);
+ DPRINTK("VSD support dvi dual %d\n", cfg->vsd_dvi_dual);
+
+ if (blklen > 6)
+ cfg->vsd_max_tmdsclk_rate = edid[index+7] * 5;
+ DPRINTK("VSD MAX TMDS CLOCK RATE %d\n", cfg->vsd_max_tmdsclk_rate);
+
+ if (blklen > 7) {
+ latency_present = edid[index+8] >> 7;
+ I_latency_present = (edid[index+8] & 0x40) >> 6;
+ hdmi_video_present = (edid[index+8] & 0x20) >> 5;
+ cfg->vsd_cnc3 = (edid[index+8] & 0x8) >> 3;
+ cfg->vsd_cnc2 = (edid[index+8] & 0x4) >> 2;
+ cfg->vsd_cnc1 = (edid[index+8] & 0x2) >> 1;
+ cfg->vsd_cnc0 = edid[index+8] & 0x1;
+
+ DPRINTK("VSD cnc0 %d\n", cfg->vsd_cnc0);
+ DPRINTK("VSD cnc1 %d\n", cfg->vsd_cnc1);
+ DPRINTK("VSD cnc2 %d\n", cfg->vsd_cnc2);
+ DPRINTK("VSD cnc3 %d\n", cfg->vsd_cnc3);
+ DPRINTK("latency_present %d\n", latency_present);
+ DPRINTK("I_latency_present %d\n", I_latency_present);
+ DPRINTK("hdmi_video_present %d\n", hdmi_video_present);
+
+ } else {
+ index += blklen;
+ break;
+ }
+
+ index += 9;
+
+ /*latency present */
+ if (latency_present) {
+ cfg->vsd_video_latency = edid[index++];
+ cfg->vsd_audio_latency = edid[index++];
+
+ if (I_latency_present) {
+ cfg->vsd_I_video_latency = edid[index++];
+ cfg->vsd_I_audio_latency = edid[index++];
+ } else {
+ cfg->vsd_I_video_latency = cfg->vsd_video_latency;
+ cfg->vsd_I_audio_latency = cfg->vsd_audio_latency;
+ }
+
+ DPRINTK("VSD latency video_latency %d\n", cfg->vsd_video_latency);
+ DPRINTK("VSD latency audio_latency %d\n", cfg->vsd_audio_latency);
+ DPRINTK("VSD latency I_video_latency %d\n", cfg->vsd_I_video_latency);
+ DPRINTK("VSD latency I_audio_latency %d\n", cfg->vsd_I_audio_latency);
+ }
+
+ if (hdmi_video_present) {
+ hdmi_3d_present = edid[index] >> 7;
+ hdmi_3d_multi_present = (edid[index] & 0x60) >> 5;
+ index++;
+ hdmi_vic_len = (edid[index] & 0xe0) >> 5;
+ hdmi_3d_len = edid[index] & 0x1f;
+ index++;
+
+ DPRINTK("hdmi_3d_present %d\n", hdmi_3d_present);
+ DPRINTK("hdmi_3d_multi_present %d\n", hdmi_3d_multi_present);
+ DPRINTK("hdmi_vic_len %d\n", hdmi_vic_len);
+ DPRINTK("hdmi_3d_len %d\n", hdmi_3d_len);
+
+ if (hdmi_vic_len > 0) {
+ for (i = 0; i < hdmi_vic_len; i++) {
+ cfg->hdmi_vic[i] = edid[index++];
+ DPRINTK("HDMI_vic=%d\n", cfg->hdmi_vic[i]);
+ }
+ }
+
+ if (hdmi_3d_len > 0) {
+ if (hdmi_3d_present) {
+ if (hdmi_3d_multi_present == 0x1) {
+ cfg->hdmi_3d_struct_all = (edid[index] << 8) | edid[index+1];
+ index_inc = 2;
+ } else if (hdmi_3d_multi_present == 0x2) {
+ cfg->hdmi_3d_struct_all = (edid[index] << 8) | edid[index+1];
+ cfg->hdmi_3d_mask_all = (edid[index+2] << 8) | edid[index+3];
+ index_inc = 4;
+ } else
+ index_inc = 0;
+ }
+
+ DPRINTK("HDMI 3d struct all =0x%x\n", cfg->hdmi_3d_struct_all);
+ DPRINTK("HDMI 3d mask all =0x%x\n", cfg->hdmi_3d_mask_all);
+
+ /* Read 2D vic 3D_struct */
+ if ((hdmi_3d_len - index_inc) > 0) {
+ DPRINTK("Support 3D video format\n");
+ i = 0;
+ while ((hdmi_3d_len - index_inc) > 0) {
+
+ cfg->hdmi_3d_format[i].vic_order_2d = edid[index+index_inc] >> 4;
+ cfg->hdmi_3d_format[i].struct_3d = edid[index+index_inc] & 0x0f;
+ index_inc++;
+
+ if (cfg->hdmi_3d_format[i].struct_3d == 8) {
+ cfg->hdmi_3d_format[i].detail_3d = edid[index+index_inc] >> 4;
+ index_inc++;
+ } else if (cfg->hdmi_3d_format[i].struct_3d > 8) {
+ cfg->hdmi_3d_format[i].detail_3d = 0;
+ index_inc++;
+ }
+
+ DPRINTK("vic_order_2d=%d, 3d_struct=%d, 3d_detail=0x%x\n",
+ cfg->hdmi_3d_format[i].vic_order_2d,
+ cfg->hdmi_3d_format[i].struct_3d,
+ cfg->hdmi_3d_format[i].detail_3d);
+ i++;
+ }
+ }
+ index += index_inc;
+ }
+ }
+
+ index = vsd_end;
+
+ break;
+ }
+ case 0x1: /*Audio data block*/
+ {
+ u8 audio_format, max_ch, byte1, byte2, byte3;
+
+ i = 0;
+ cfg->max_channels = 0;
+ cfg->sample_rates = 0;
+ cfg->sample_sizes = 0;
+
+ while (i < blklen) {
+ byte1 = edid[index + 1];
+ byte2 = edid[index + 2];
+ byte3 = edid[index + 3];
+ index += 3;
+ i += 3;
+
+ audio_format = byte1 >> 3;
+ max_ch = (byte1 & 0x07) + 1;
+
+ DPRINTK("Audio Format Descriptor : %2d\n", audio_format);
+ DPRINTK("Max Number of Channels : %2d\n", max_ch);
+ DPRINTK("Sample Rates : %02x\n", byte2);
+
+ /* ALSA can't specify specific compressed
+ * formats, so only care about PCM for now. */
+ if (audio_format == AUDIO_CODING_TYPE_LPCM) {
+ if (max_ch > cfg->max_channels)
+ cfg->max_channels = max_ch;
+
+ cfg->sample_rates |= byte2;
+ cfg->sample_sizes |= byte3 & 0x7;
+ DPRINTK("Sample Sizes : %02x\n",
+ byte3 & 0x7);
+ }
+ }
+ break;
+ }
+ case 0x4: /*Speaker allocation block*/
+ {
+ i = 0;
+ while (i < blklen) {
+ cfg->speaker_alloc = edid[index + 1];
+ index += 3;
+ i += 3;
+ DPRINTK("Speaker Alloc : %02x\n", cfg->speaker_alloc);
+ }
+ break;
+ }
+ case 0x7: /*User extended block*/
+ default:
+ /* skip */
+ DPRINTK("Not handle block, tagcode = 0x%x\n", tagcode);
+ index += blklen;
+ break;
+ }
+
+ index++;
+ }
+ }
+
+ /* long desc */
+ DPRINTK("CEA long desc timmings\n");
+ index = detail_timing_desc_offset;
+ block = edid + index;
+ while (index < (EDID_LENGTH - DETAILED_TIMING_DESCRIPTION_SIZE)) {
+ if (!(block[0] == 0x00 && block[1] == 0x00)) {
+ get_detailed_timing(block, &mode[num]);
+ num++;
+ }
+ block += DETAILED_TIMING_DESCRIPTION_SIZE;
+ index += DETAILED_TIMING_DESCRIPTION_SIZE;
+ }
+
+ if (!num) {
+ kfree(mode);
+ return 0;
+ }
+
+ m = kmalloc((num + specs->modedb_len) *
+ sizeof(struct fb_videomode), GFP_KERNEL);
+ if (!m) {
+ kfree(mode);
+ return 0;
+ }
+
+ if (specs->modedb_len) {
+ memmove(m, specs->modedb,
+ specs->modedb_len * sizeof(struct fb_videomode));
+ kfree(specs->modedb);
+ }
+ memmove(m+specs->modedb_len, mode,
+ num * sizeof(struct fb_videomode));
+ kfree(mode);
+
+ specs->modedb_len += num;
+ specs->modedb = m;
+
+ return 0;
+}
+EXPORT_SYMBOL(mxc_edid_parse_ext_blk);
+
+static int mxc_edid_readblk(struct i2c_adapter *adp,
+ unsigned short addr, unsigned char *edid)
+{
+ int ret = 0, extblknum = 0;
+ unsigned char regaddr = 0x0;
+ struct i2c_msg msg[2] = {
+ {
+ .addr = addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &regaddr,
+ }, {
+ .addr = addr,
+ .flags = I2C_M_RD,
+ .len = EDID_LENGTH,
+ .buf = edid,
+ },
+ };
+
+ ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
+ if (ret != ARRAY_SIZE(msg)) {
+ DPRINTK("unable to read EDID block\n");
+ return -EIO;
+ }
+
+ if (edid[1] == 0x00)
+ return -ENOENT;
+
+ extblknum = edid[0x7E];
+
+ if (extblknum) {
+ regaddr = 128;
+ msg[1].buf = edid + EDID_LENGTH;
+
+ ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
+ if (ret != ARRAY_SIZE(msg)) {
+ DPRINTK("unable to read EDID ext block\n");
+ return -EIO;
+ }
+ }
+
+ return extblknum;
+}
+
+static int mxc_edid_readsegblk(struct i2c_adapter *adp, unsigned short addr,
+ unsigned char *edid, int seg_num)
+{
+ int ret = 0;
+ unsigned char segment = 0x1, regaddr = 0;
+ struct i2c_msg msg[3] = {
+ {
+ .addr = 0x30,
+ .flags = 0,
+ .len = 1,
+ .buf = &segment,
+ }, {
+ .addr = addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &regaddr,
+ }, {
+ .addr = addr,
+ .flags = I2C_M_RD,
+ .len = EDID_LENGTH,
+ .buf = edid,
+ },
+ };
+
+ ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
+ if (ret != ARRAY_SIZE(msg)) {
+ DPRINTK("unable to read EDID block\n");
+ return -EIO;
+ }
+
+ if (seg_num == 2) {
+ regaddr = 128;
+ msg[2].buf = edid + EDID_LENGTH;
+
+ ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
+ if (ret != ARRAY_SIZE(msg)) {
+ DPRINTK("unable to read EDID block\n");
+ return -EIO;
+ }
+ }
+
+ return ret;
+}
+
+int mxc_edid_var_to_vic(struct fb_var_screeninfo *var)
+{
+ int i;
+ struct fb_videomode m;
+
+ for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
+ fb_var_to_videomode(&m, var);
+ if (mxc_edid_fb_mode_is_equal(false, &m, &mxc_cea_mode[i]))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(mxc_cea_mode))
+ return 0;
+
+ return i;
+}
+EXPORT_SYMBOL(mxc_edid_var_to_vic);
+
+int mxc_edid_mode_to_vic(const struct fb_videomode *mode)
+{
+ int i;
+ bool use_aspect = (mode->vmode & FB_VMODE_ASPECT_MASK);
+
+ for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
+ if (mxc_edid_fb_mode_is_equal(use_aspect, mode, &mxc_cea_mode[i]))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(mxc_cea_mode))
+ return 0;
+
+ return i;
+}
+EXPORT_SYMBOL(mxc_edid_mode_to_vic);
+
+/* make sure edid has 512 bytes*/
+int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
+ unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi)
+{
+ int ret = 0, extblknum;
+ if (!adp || !edid || !cfg || !fbi)
+ return -EINVAL;
+
+ memset(edid, 0, EDID_LENGTH*4);
+ memset(cfg, 0, sizeof(struct mxc_edid_cfg));
+
+ extblknum = mxc_edid_readblk(adp, addr, edid);
+ if (extblknum < 0)
+ return extblknum;
+
+ /* edid first block parsing */
+ memset(&fbi->monspecs, 0, sizeof(fbi->monspecs));
+ fb_edid_to_monspecs(edid, &fbi->monspecs);
+
+ if (extblknum) {
+ int i;
+
+ /* FIXME: mxc_edid_readsegblk() won't read more than 2 blocks
+ * and the for-loop will read past the end of the buffer! :-( */
+ if (extblknum > 3) {
+ WARN_ON(true);
+ return -EINVAL;
+ }
+
+ /* need read segment block? */
+ if (extblknum > 1) {
+ ret = mxc_edid_readsegblk(adp, addr,
+ edid + EDID_LENGTH*2, extblknum - 1);
+ if (ret < 0)
+ return ret;
+ }
+
+ for (i = 1; i <= extblknum; i++)
+ /* edid ext block parsing */
+ mxc_edid_parse_ext_blk(edid + i*EDID_LENGTH,
+ cfg, &fbi->monspecs);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mxc_edid_read);
+
diff --git a/drivers/video/fbdev/mxc/mxc_epdc_fb.c b/drivers/video/fbdev/mxc/mxc_epdc_fb.c
new file mode 100644
index 000000000000..0109b0371b76
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_epdc_fb.c
@@ -0,0 +1,5601 @@
+/*
+ * Copyright (C) 2010-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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+/*
+ * Based on STMP378X LCDIF
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+#include <linux/busfreq-imx.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+#include <linux/cpufreq.h>
+#include <linux/firmware.h>
+#include <linux/kthread.h>
+#include <linux/dmaengine.h>
+#include <linux/pxp_dma.h>
+#include <linux/pm_runtime.h>
+#include <linux/mxcfb.h>
+#include <linux/mxcfb_epdc.h>
+#include <linux/gpio.h>
+#include <linux/regulator/driver.h>
+#include <linux/fsl_devices.h>
+#include <linux/bitops.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/dma-imx.h>
+#include <asm/cacheflush.h>
+
+#include "epdc_regs.h"
+
+/*
+ * Enable this define to have a default panel
+ * loaded during driver initialization
+ */
+/*#define DEFAULT_PANEL_HW_INIT*/
+
+#define NUM_SCREENS_MIN 2
+
+#define EPDC_V1_NUM_LUTS 16
+#define EPDC_V1_MAX_NUM_UPDATES 20
+#define EPDC_V2_NUM_LUTS 64
+#define EPDC_V2_MAX_NUM_UPDATES 64
+#define EPDC_MAX_NUM_BUFFERS 2
+#define INVALID_LUT (-1)
+#define DRY_RUN_NO_LUT 100
+
+/* Maximum update buffer image width due to v2.0 and v2.1 errata ERR005313. */
+#define EPDC_V2_MAX_UPDATE_WIDTH 2047
+#define EPDC_V2_ROTATION_ALIGNMENT 8
+
+#define DEFAULT_TEMP_INDEX 0
+#define DEFAULT_TEMP 20 /* room temp in deg Celsius */
+
+#define INIT_UPDATE_MARKER 0x12345678
+#define PAN_UPDATE_MARKER 0x12345679
+
+#define POWER_STATE_OFF 0
+#define POWER_STATE_ON 1
+
+#define MERGE_OK 0
+#define MERGE_FAIL 1
+#define MERGE_BLOCK 2
+
+static unsigned long default_bpp = 16;
+static DEFINE_MUTEX(hard_lock);
+
+struct update_marker_data {
+ struct list_head full_list;
+ struct list_head upd_list;
+ u32 update_marker;
+ struct completion update_completion;
+ int lut_num;
+ bool collision_test;
+ bool waiting;
+};
+
+struct update_desc_list {
+ struct list_head list;
+ struct mxcfb_update_data upd_data;/* Update parameters */
+ u32 epdc_offs; /* Added to buffer ptr to resolve alignment */
+ u32 epdc_stride; /* Depends on rotation & whether we skip PxP */
+ struct list_head upd_marker_list; /* List of markers for this update */
+ u32 update_order; /* Numeric ordering value for update */
+};
+
+/* This structure represents a list node containing both
+ * a memory region allocated as an output buffer for the PxP
+ * update processing task, and the update description (mode, region, etc.) */
+struct update_data_list {
+ struct list_head list;
+ dma_addr_t phys_addr; /* Pointer to phys address of processed Y buf */
+ void *virt_addr;
+ struct update_desc_list *update_desc;
+ int lut_num; /* Assigned before update is processed into working buffer */
+ u64 collision_mask; /* Set when update creates collision */
+ /* Mask of the LUTs the update collides with */
+};
+
+struct mxc_epdc_fb_data {
+ struct fb_info info;
+ struct fb_var_screeninfo epdc_fb_var; /* Internal copy of screeninfo
+ so we can sync changes to it */
+ u32 pseudo_palette[16];
+ char fw_str[24];
+ struct list_head list;
+ struct imx_epdc_fb_mode *cur_mode;
+ struct imx_epdc_fb_platform_data *pdata;
+ int blank;
+ u32 max_pix_size;
+ ssize_t map_size;
+ dma_addr_t phys_start;
+ u32 fb_offset;
+ int default_bpp;
+ int native_width;
+ int native_height;
+ int num_screens;
+ int epdc_irq;
+ struct device *dev;
+ int power_state;
+ int wait_for_powerdown;
+ struct completion powerdown_compl;
+ struct clk *epdc_clk_axi;
+ struct clk *epdc_clk_pix;
+ struct regulator *display_regulator;
+ struct regulator *vcom_regulator;
+ struct regulator *v3p3_regulator;
+ bool fw_default_load;
+ int rev;
+
+ /* FB elements related to EPDC updates */
+ int num_luts;
+ int max_num_updates;
+ bool in_init;
+ bool hw_ready;
+ bool hw_initializing;
+ bool waiting_for_idle;
+ u32 auto_mode;
+ u32 upd_scheme;
+ struct list_head upd_pending_list;
+ struct list_head upd_buf_queue;
+ struct list_head upd_buf_free_list;
+ struct list_head upd_buf_collision_list;
+ struct update_data_list *cur_update;
+ struct mutex queue_mutex;
+ int trt_entries;
+ int temp_index;
+ u8 *temp_range_bounds;
+ struct mxcfb_waveform_modes wv_modes;
+ bool wv_modes_update;
+ u32 *waveform_buffer_virt;
+ u32 waveform_buffer_phys;
+ u32 waveform_buffer_size;
+ u32 *working_buffer_virt;
+ u32 working_buffer_phys;
+ u32 working_buffer_size;
+ dma_addr_t *phys_addr_updbuf;
+ void **virt_addr_updbuf;
+ u32 upd_buffer_num;
+ u32 max_num_buffers;
+ dma_addr_t phys_addr_copybuf; /* Phys address of copied update data */
+ void *virt_addr_copybuf; /* Used for PxP SW workaround */
+ u32 order_cnt;
+ struct list_head full_marker_list;
+ u32 *lut_update_order; /* Array size = number of luts */
+ u64 epdc_colliding_luts;
+ u64 luts_complete_wb;
+ struct completion updates_done;
+ struct delayed_work epdc_done_work;
+ struct workqueue_struct *epdc_submit_workqueue;
+ struct work_struct epdc_submit_work;
+ struct workqueue_struct *epdc_intr_workqueue;
+ struct work_struct epdc_intr_work;
+ bool waiting_for_wb;
+ bool waiting_for_lut;
+ bool waiting_for_lut15;
+ struct completion update_res_free;
+ struct completion lut15_free;
+ struct completion eof_event;
+ int eof_sync_period;
+ struct mutex power_mutex;
+ bool powering_down;
+ bool updates_active;
+ int pwrdown_delay;
+ unsigned long tce_prevent;
+ bool restrict_width; /* work around rev >=2.0 width and
+ stride restriction */
+
+ /* FB elements related to PxP DMA */
+ struct completion pxp_tx_cmpl;
+ struct pxp_channel *pxp_chan;
+ struct pxp_config_data pxp_conf;
+ struct dma_async_tx_descriptor *txd;
+ dma_cookie_t cookie;
+ struct scatterlist sg[2];
+ struct mutex pxp_mutex; /* protects access to PxP */
+};
+
+struct waveform_data_header {
+ unsigned int wi0;
+ unsigned int wi1;
+ unsigned int wi2;
+ unsigned int wi3;
+ unsigned int wi4;
+ unsigned int wi5;
+ unsigned int wi6;
+ unsigned int xwia:24;
+ unsigned int cs1:8;
+ unsigned int wmta:24;
+ unsigned int fvsn:8;
+ unsigned int luts:8;
+ unsigned int mc:8;
+ unsigned int trc:8;
+ unsigned int reserved0_0:8;
+ unsigned int eb:8;
+ unsigned int sb:8;
+ unsigned int reserved0_1:8;
+ unsigned int reserved0_2:8;
+ unsigned int reserved0_3:8;
+ unsigned int reserved0_4:8;
+ unsigned int reserved0_5:8;
+ unsigned int cs2:8;
+};
+
+struct mxcfb_waveform_data_file {
+ struct waveform_data_header wdh;
+ u32 *data; /* Temperature Range Table + Waveform Data */
+};
+
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 30000000,
+ .left_margin = 8,
+ .right_margin = 164,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e060scm_mode = {
+ .name = "E060SCM",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 26666667,
+ .left_margin = 8,
+ .right_margin = 100,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct imx_epdc_fb_mode panel_modes[] = {
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 465, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 9, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e060scm_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 419, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 5, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+
+static struct imx_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+};
+
+void __iomem *epdc_base;
+
+struct mxc_epdc_fb_data *g_fb_data;
+
+/* forward declaration */
+static int mxc_epdc_fb_get_temp_index(struct mxc_epdc_fb_data *fb_data,
+ int temp);
+static void mxc_epdc_fb_flush_updates(struct mxc_epdc_fb_data *fb_data);
+static int mxc_epdc_fb_blank(int blank, struct fb_info *info);
+static int mxc_epdc_fb_init_hw(struct fb_info *info);
+static int pxp_process_update(struct mxc_epdc_fb_data *fb_data,
+ u32 src_width, u32 src_height,
+ struct mxcfb_rect *update_region);
+static int pxp_complete_update(struct mxc_epdc_fb_data *fb_data, u32 *hist_stat);
+
+static void draw_mode0(struct mxc_epdc_fb_data *fb_data);
+static bool is_free_list_full(struct mxc_epdc_fb_data *fb_data);
+
+static void do_dithering_processing_Y1_v1_0(
+ unsigned char *update_region_virt_ptr,
+ dma_addr_t update_region_phys_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist);
+static void do_dithering_processing_Y4_v1_0(
+ unsigned char *update_region_virt_ptr,
+ dma_addr_t update_region_phys_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist);
+
+#ifdef DEBUG
+static void dump_pxp_config(struct mxc_epdc_fb_data *fb_data,
+ struct pxp_config_data *pxp_conf)
+{
+ dev_info(fb_data->dev, "S0 fmt 0x%x",
+ pxp_conf->s0_param.pixel_fmt);
+ dev_info(fb_data->dev, "S0 width 0x%x",
+ pxp_conf->s0_param.width);
+ dev_info(fb_data->dev, "S0 height 0x%x",
+ pxp_conf->s0_param.height);
+ dev_info(fb_data->dev, "S0 ckey 0x%x",
+ pxp_conf->s0_param.color_key);
+ dev_info(fb_data->dev, "S0 ckey en 0x%x",
+ pxp_conf->s0_param.color_key_enable);
+
+ dev_info(fb_data->dev, "OL0 combine en 0x%x",
+ pxp_conf->ol_param[0].combine_enable);
+ dev_info(fb_data->dev, "OL0 fmt 0x%x",
+ pxp_conf->ol_param[0].pixel_fmt);
+ dev_info(fb_data->dev, "OL0 width 0x%x",
+ pxp_conf->ol_param[0].width);
+ dev_info(fb_data->dev, "OL0 height 0x%x",
+ pxp_conf->ol_param[0].height);
+ dev_info(fb_data->dev, "OL0 ckey 0x%x",
+ pxp_conf->ol_param[0].color_key);
+ dev_info(fb_data->dev, "OL0 ckey en 0x%x",
+ pxp_conf->ol_param[0].color_key_enable);
+ dev_info(fb_data->dev, "OL0 alpha 0x%x",
+ pxp_conf->ol_param[0].global_alpha);
+ dev_info(fb_data->dev, "OL0 alpha en 0x%x",
+ pxp_conf->ol_param[0].global_alpha_enable);
+ dev_info(fb_data->dev, "OL0 local alpha en 0x%x",
+ pxp_conf->ol_param[0].local_alpha_enable);
+
+ dev_info(fb_data->dev, "Out fmt 0x%x",
+ pxp_conf->out_param.pixel_fmt);
+ dev_info(fb_data->dev, "Out width 0x%x",
+ pxp_conf->out_param.width);
+ dev_info(fb_data->dev, "Out height 0x%x",
+ pxp_conf->out_param.height);
+
+ dev_info(fb_data->dev,
+ "drect left 0x%x right 0x%x width 0x%x height 0x%x",
+ pxp_conf->proc_data.drect.left, pxp_conf->proc_data.drect.top,
+ pxp_conf->proc_data.drect.width,
+ pxp_conf->proc_data.drect.height);
+ dev_info(fb_data->dev,
+ "srect left 0x%x right 0x%x width 0x%x height 0x%x",
+ pxp_conf->proc_data.srect.left, pxp_conf->proc_data.srect.top,
+ pxp_conf->proc_data.srect.width,
+ pxp_conf->proc_data.srect.height);
+ dev_info(fb_data->dev, "Scaling en 0x%x", pxp_conf->proc_data.scaling);
+ dev_info(fb_data->dev, "HFlip en 0x%x", pxp_conf->proc_data.hflip);
+ dev_info(fb_data->dev, "VFlip en 0x%x", pxp_conf->proc_data.vflip);
+ dev_info(fb_data->dev, "Rotation 0x%x", pxp_conf->proc_data.rotate);
+ dev_info(fb_data->dev, "BG Color 0x%x", pxp_conf->proc_data.bgcolor);
+}
+
+static void dump_epdc_reg(void)
+{
+ printk(KERN_DEBUG "\n\n");
+ printk(KERN_DEBUG "EPDC_CTRL 0x%x\n", __raw_readl(EPDC_CTRL));
+ printk(KERN_DEBUG "EPDC_WVADDR 0x%x\n", __raw_readl(EPDC_WVADDR));
+ printk(KERN_DEBUG "EPDC_WB_ADDR 0x%x\n", __raw_readl(EPDC_WB_ADDR));
+ printk(KERN_DEBUG "EPDC_RES 0x%x\n", __raw_readl(EPDC_RES));
+ printk(KERN_DEBUG "EPDC_FORMAT 0x%x\n", __raw_readl(EPDC_FORMAT));
+ printk(KERN_DEBUG "EPDC_FIFOCTRL 0x%x\n", __raw_readl(EPDC_FIFOCTRL));
+ printk(KERN_DEBUG "EPDC_UPD_ADDR 0x%x\n", __raw_readl(EPDC_UPD_ADDR));
+ printk(KERN_DEBUG "EPDC_UPD_STRIDE 0x%x\n", __raw_readl(EPDC_UPD_STRIDE));
+ printk(KERN_DEBUG "EPDC_UPD_FIXED 0x%x\n", __raw_readl(EPDC_UPD_FIXED));
+ printk(KERN_DEBUG "EPDC_UPD_CORD 0x%x\n", __raw_readl(EPDC_UPD_CORD));
+ printk(KERN_DEBUG "EPDC_UPD_SIZE 0x%x\n", __raw_readl(EPDC_UPD_SIZE));
+ printk(KERN_DEBUG "EPDC_UPD_CTRL 0x%x\n", __raw_readl(EPDC_UPD_CTRL));
+ printk(KERN_DEBUG "EPDC_TEMP 0x%x\n", __raw_readl(EPDC_TEMP));
+ printk(KERN_DEBUG "EPDC_AUTOWV_LUT 0x%x\n", __raw_readl(EPDC_AUTOWV_LUT));
+ printk(KERN_DEBUG "EPDC_TCE_CTRL 0x%x\n", __raw_readl(EPDC_TCE_CTRL));
+ printk(KERN_DEBUG "EPDC_TCE_SDCFG 0x%x\n", __raw_readl(EPDC_TCE_SDCFG));
+ printk(KERN_DEBUG "EPDC_TCE_GDCFG 0x%x\n", __raw_readl(EPDC_TCE_GDCFG));
+ printk(KERN_DEBUG "EPDC_TCE_HSCAN1 0x%x\n", __raw_readl(EPDC_TCE_HSCAN1));
+ printk(KERN_DEBUG "EPDC_TCE_HSCAN2 0x%x\n", __raw_readl(EPDC_TCE_HSCAN2));
+ printk(KERN_DEBUG "EPDC_TCE_VSCAN 0x%x\n", __raw_readl(EPDC_TCE_VSCAN));
+ printk(KERN_DEBUG "EPDC_TCE_OE 0x%x\n", __raw_readl(EPDC_TCE_OE));
+ printk(KERN_DEBUG "EPDC_TCE_POLARITY 0x%x\n", __raw_readl(EPDC_TCE_POLARITY));
+ printk(KERN_DEBUG "EPDC_TCE_TIMING1 0x%x\n", __raw_readl(EPDC_TCE_TIMING1));
+ printk(KERN_DEBUG "EPDC_TCE_TIMING2 0x%x\n", __raw_readl(EPDC_TCE_TIMING2));
+ printk(KERN_DEBUG "EPDC_TCE_TIMING3 0x%x\n", __raw_readl(EPDC_TCE_TIMING3));
+ printk(KERN_DEBUG "EPDC_PIGEON_CTRL0 0x%x\n", __raw_readl(EPDC_PIGEON_CTRL0));
+ printk(KERN_DEBUG "EPDC_PIGEON_CTRL1 0x%x\n", __raw_readl(EPDC_PIGEON_CTRL1));
+ printk(KERN_DEBUG "EPDC_IRQ_MASK1 0x%x\n", __raw_readl(EPDC_IRQ_MASK1));
+ printk(KERN_DEBUG "EPDC_IRQ_MASK2 0x%x\n", __raw_readl(EPDC_IRQ_MASK2));
+ printk(KERN_DEBUG "EPDC_IRQ1 0x%x\n", __raw_readl(EPDC_IRQ1));
+ printk(KERN_DEBUG "EPDC_IRQ2 0x%x\n", __raw_readl(EPDC_IRQ2));
+ printk(KERN_DEBUG "EPDC_IRQ_MASK 0x%x\n", __raw_readl(EPDC_IRQ_MASK));
+ printk(KERN_DEBUG "EPDC_IRQ 0x%x\n", __raw_readl(EPDC_IRQ));
+ printk(KERN_DEBUG "EPDC_STATUS_LUTS 0x%x\n", __raw_readl(EPDC_STATUS_LUTS));
+ printk(KERN_DEBUG "EPDC_STATUS_LUTS2 0x%x\n", __raw_readl(EPDC_STATUS_LUTS2));
+ printk(KERN_DEBUG "EPDC_STATUS_NEXTLUT 0x%x\n", __raw_readl(EPDC_STATUS_NEXTLUT));
+ printk(KERN_DEBUG "EPDC_STATUS_COL1 0x%x\n", __raw_readl(EPDC_STATUS_COL));
+ printk(KERN_DEBUG "EPDC_STATUS_COL2 0x%x\n", __raw_readl(EPDC_STATUS_COL2));
+ printk(KERN_DEBUG "EPDC_STATUS 0x%x\n", __raw_readl(EPDC_STATUS));
+ printk(KERN_DEBUG "EPDC_UPD_COL_CORD 0x%x\n", __raw_readl(EPDC_UPD_COL_CORD));
+ printk(KERN_DEBUG "EPDC_UPD_COL_SIZE 0x%x\n", __raw_readl(EPDC_UPD_COL_SIZE));
+ printk(KERN_DEBUG "EPDC_DEBUG 0x%x\n", __raw_readl(EPDC_DEBUG));
+ printk(KERN_DEBUG "EPDC_DEBUG_LUT 0x%x\n", __raw_readl(EPDC_DEBUG_LUT));
+ printk(KERN_DEBUG "EPDC_HIST1_PARAM 0x%x\n", __raw_readl(EPDC_HIST1_PARAM));
+ printk(KERN_DEBUG "EPDC_HIST2_PARAM 0x%x\n", __raw_readl(EPDC_HIST2_PARAM));
+ printk(KERN_DEBUG "EPDC_HIST4_PARAM 0x%x\n", __raw_readl(EPDC_HIST4_PARAM));
+ printk(KERN_DEBUG "EPDC_HIST8_PARAM0 0x%x\n", __raw_readl(EPDC_HIST8_PARAM0));
+ printk(KERN_DEBUG "EPDC_HIST8_PARAM1 0x%x\n", __raw_readl(EPDC_HIST8_PARAM1));
+ printk(KERN_DEBUG "EPDC_HIST16_PARAM0 0x%x\n", __raw_readl(EPDC_HIST16_PARAM0));
+ printk(KERN_DEBUG "EPDC_HIST16_PARAM1 0x%x\n", __raw_readl(EPDC_HIST16_PARAM1));
+ printk(KERN_DEBUG "EPDC_HIST16_PARAM2 0x%x\n", __raw_readl(EPDC_HIST16_PARAM2));
+ printk(KERN_DEBUG "EPDC_HIST16_PARAM3 0x%x\n", __raw_readl(EPDC_HIST16_PARAM3));
+ printk(KERN_DEBUG "EPDC_GPIO 0x%x\n", __raw_readl(EPDC_GPIO));
+ printk(KERN_DEBUG "EPDC_VERSION 0x%x\n", __raw_readl(EPDC_VERSION));
+ printk(KERN_DEBUG "\n\n");
+}
+
+static void dump_update_data(struct device *dev,
+ struct update_data_list *upd_data_list)
+{
+ dev_info(dev,
+ "X = %d, Y = %d, Width = %d, Height = %d, WaveMode = %d, "
+ "LUT = %d, Coll Mask = 0x%llx, order = %d\n",
+ upd_data_list->update_desc->upd_data.update_region.left,
+ upd_data_list->update_desc->upd_data.update_region.top,
+ upd_data_list->update_desc->upd_data.update_region.width,
+ upd_data_list->update_desc->upd_data.update_region.height,
+ upd_data_list->update_desc->upd_data.waveform_mode,
+ upd_data_list->lut_num,
+ upd_data_list->collision_mask,
+ upd_data_list->update_desc->update_order);
+}
+
+static void dump_collision_list(struct mxc_epdc_fb_data *fb_data)
+{
+ struct update_data_list *plist;
+
+ dev_info(fb_data->dev, "Collision List:\n");
+ if (list_empty(&fb_data->upd_buf_collision_list))
+ dev_info(fb_data->dev, "Empty");
+ list_for_each_entry(plist, &fb_data->upd_buf_collision_list, list) {
+ dev_info(fb_data->dev, "Virt Addr = 0x%x, Phys Addr = 0x%x ",
+ (u32)plist->virt_addr, plist->phys_addr);
+ dump_update_data(fb_data->dev, plist);
+ }
+}
+
+static void dump_free_list(struct mxc_epdc_fb_data *fb_data)
+{
+ struct update_data_list *plist;
+
+ dev_info(fb_data->dev, "Free List:\n");
+ if (list_empty(&fb_data->upd_buf_free_list))
+ dev_info(fb_data->dev, "Empty");
+ list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
+ dev_info(fb_data->dev, "Virt Addr = 0x%x, Phys Addr = 0x%x ",
+ (u32)plist->virt_addr, plist->phys_addr);
+}
+
+static void dump_queue(struct mxc_epdc_fb_data *fb_data)
+{
+ struct update_data_list *plist;
+
+ dev_info(fb_data->dev, "Queue:\n");
+ if (list_empty(&fb_data->upd_buf_queue))
+ dev_info(fb_data->dev, "Empty");
+ list_for_each_entry(plist, &fb_data->upd_buf_queue, list) {
+ dev_info(fb_data->dev, "Virt Addr = 0x%x, Phys Addr = 0x%x ",
+ (u32)plist->virt_addr, plist->phys_addr);
+ dump_update_data(fb_data->dev, plist);
+ }
+}
+
+static void dump_desc_data(struct device *dev,
+ struct update_desc_list *upd_desc_list)
+{
+ dev_info(dev,
+ "X = %d, Y = %d, Width = %d, Height = %d, WaveMode = %d, "
+ "order = %d\n",
+ upd_desc_list->upd_data.update_region.left,
+ upd_desc_list->upd_data.update_region.top,
+ upd_desc_list->upd_data.update_region.width,
+ upd_desc_list->upd_data.update_region.height,
+ upd_desc_list->upd_data.waveform_mode,
+ upd_desc_list->update_order);
+}
+
+static void dump_pending_list(struct mxc_epdc_fb_data *fb_data)
+{
+ struct update_desc_list *plist;
+
+ dev_info(fb_data->dev, "Queue:\n");
+ if (list_empty(&fb_data->upd_pending_list))
+ dev_info(fb_data->dev, "Empty");
+ list_for_each_entry(plist, &fb_data->upd_pending_list, list)
+ dump_desc_data(fb_data->dev, plist);
+}
+
+static void dump_all_updates(struct mxc_epdc_fb_data *fb_data)
+{
+ dump_free_list(fb_data);
+ dump_queue(fb_data);
+ dump_collision_list(fb_data);
+ dev_info(fb_data->dev, "Current update being processed:\n");
+ if (fb_data->cur_update == NULL)
+ dev_info(fb_data->dev, "No current update\n");
+ else
+ dump_update_data(fb_data->dev, fb_data->cur_update);
+}
+#else
+static inline void dump_pxp_config(struct mxc_epdc_fb_data *fb_data,
+ struct pxp_config_data *pxp_conf) {}
+static inline void dump_epdc_reg(void) {}
+static inline void dump_update_data(struct device *dev,
+ struct update_data_list *upd_data_list) {}
+static inline void dump_collision_list(struct mxc_epdc_fb_data *fb_data) {}
+static inline void dump_free_list(struct mxc_epdc_fb_data *fb_data) {}
+static inline void dump_queue(struct mxc_epdc_fb_data *fb_data) {}
+static inline void dump_all_updates(struct mxc_epdc_fb_data *fb_data) {}
+
+#endif
+
+
+/********************************************************
+ * Start Low-Level EPDC Functions
+ ********************************************************/
+
+static inline void epdc_lut_complete_intr(int rev, u32 lut_num, bool enable)
+{
+ if (rev < 20) {
+ if (enable)
+ __raw_writel(1 << lut_num, EPDC_IRQ_MASK_SET);
+ else
+ __raw_writel(1 << lut_num, EPDC_IRQ_MASK_CLEAR);
+ } else {
+ if (enable) {
+ if (lut_num < 32)
+ __raw_writel(1 << lut_num, EPDC_IRQ_MASK1_SET);
+ else
+ __raw_writel(1 << (lut_num - 32),
+ EPDC_IRQ_MASK2_SET);
+ } else {
+ if (lut_num < 32)
+ __raw_writel(1 << lut_num,
+ EPDC_IRQ_MASK1_CLEAR);
+ else
+ __raw_writel(1 << (lut_num - 32),
+ EPDC_IRQ_MASK2_CLEAR);
+ }
+ }
+}
+
+static inline void epdc_working_buf_intr(bool enable)
+{
+ if (enable)
+ __raw_writel(EPDC_IRQ_WB_CMPLT_IRQ, EPDC_IRQ_MASK_SET);
+ else
+ __raw_writel(EPDC_IRQ_WB_CMPLT_IRQ, EPDC_IRQ_MASK_CLEAR);
+}
+
+static inline void epdc_clear_working_buf_irq(void)
+{
+ __raw_writel(EPDC_IRQ_WB_CMPLT_IRQ | EPDC_IRQ_LUT_COL_IRQ,
+ EPDC_IRQ_CLEAR);
+}
+
+static inline void epdc_eof_intr(bool enable)
+{
+ if (enable)
+ __raw_writel(EPDC_IRQ_FRAME_END_IRQ, EPDC_IRQ_MASK_SET);
+ else
+ __raw_writel(EPDC_IRQ_FRAME_END_IRQ, EPDC_IRQ_MASK_CLEAR);
+}
+
+static inline void epdc_clear_eof_irq(void)
+{
+ __raw_writel(EPDC_IRQ_FRAME_END_IRQ, EPDC_IRQ_CLEAR);
+}
+
+static inline bool epdc_signal_eof(void)
+{
+ return (__raw_readl(EPDC_IRQ_MASK) & __raw_readl(EPDC_IRQ)
+ & EPDC_IRQ_FRAME_END_IRQ) ? true : false;
+}
+
+static inline void epdc_set_temp(u32 temp)
+{
+ __raw_writel(temp, EPDC_TEMP);
+}
+
+static inline void epdc_set_screen_res(u32 width, u32 height)
+{
+ u32 val = (height << EPDC_RES_VERTICAL_OFFSET) | width;
+ __raw_writel(val, EPDC_RES);
+}
+
+static inline void epdc_set_update_addr(u32 addr)
+{
+ __raw_writel(addr, EPDC_UPD_ADDR);
+}
+
+static inline void epdc_set_update_coord(u32 x, u32 y)
+{
+ u32 val = (y << EPDC_UPD_CORD_YCORD_OFFSET) | x;
+ __raw_writel(val, EPDC_UPD_CORD);
+}
+
+static inline void epdc_set_update_dimensions(u32 width, u32 height)
+{
+ u32 val = (height << EPDC_UPD_SIZE_HEIGHT_OFFSET) | width;
+ __raw_writel(val, EPDC_UPD_SIZE);
+}
+
+static void epdc_set_update_waveform(struct mxcfb_waveform_modes *wv_modes)
+{
+ u32 val;
+
+ /* Configure the auto-waveform look-up table based on waveform modes */
+
+ /* Entry 1 = DU, 2 = GC4, 3 = GC8, etc. */
+ val = (wv_modes->mode_du << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (0 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_du << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (1 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_gc4 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (2 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_gc8 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (3 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_gc16 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (4 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_gc32 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (5 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+}
+
+static void epdc_set_update_stride(u32 stride)
+{
+ __raw_writel(stride, EPDC_UPD_STRIDE);
+}
+
+static void epdc_submit_update(u32 lut_num, u32 waveform_mode, u32 update_mode,
+ bool use_dry_run, bool use_test_mode, u32 np_val)
+{
+ u32 reg_val = 0;
+
+ if (use_test_mode) {
+ reg_val |=
+ ((np_val << EPDC_UPD_FIXED_FIXNP_OFFSET) &
+ EPDC_UPD_FIXED_FIXNP_MASK) | EPDC_UPD_FIXED_FIXNP_EN;
+
+ __raw_writel(reg_val, EPDC_UPD_FIXED);
+
+ reg_val = EPDC_UPD_CTRL_USE_FIXED;
+ } else {
+ __raw_writel(reg_val, EPDC_UPD_FIXED);
+ }
+
+ if (waveform_mode == WAVEFORM_MODE_AUTO)
+ reg_val |= EPDC_UPD_CTRL_AUTOWV;
+ else
+ reg_val |= ((waveform_mode <<
+ EPDC_UPD_CTRL_WAVEFORM_MODE_OFFSET) &
+ EPDC_UPD_CTRL_WAVEFORM_MODE_MASK);
+
+ reg_val |= (use_dry_run ? EPDC_UPD_CTRL_DRY_RUN : 0) |
+ ((lut_num << EPDC_UPD_CTRL_LUT_SEL_OFFSET) &
+ EPDC_UPD_CTRL_LUT_SEL_MASK) |
+ update_mode;
+
+ __raw_writel(reg_val, EPDC_UPD_CTRL);
+}
+
+static inline bool epdc_is_lut_complete(int rev, u32 lut_num)
+{
+ u32 val;
+ bool is_compl;
+ if (rev < 20) {
+ val = __raw_readl(EPDC_IRQ);
+ is_compl = val & (1 << lut_num) ? true : false;
+ } else if (lut_num < 32) {
+ val = __raw_readl(EPDC_IRQ1);
+ is_compl = val & (1 << lut_num) ? true : false;
+ } else {
+ val = __raw_readl(EPDC_IRQ2);
+ is_compl = val & (1 << (lut_num - 32)) ? true : false;
+ }
+
+ return is_compl;
+}
+
+static inline void epdc_clear_lut_complete_irq(int rev, u32 lut_num)
+{
+ if (rev < 20)
+ __raw_writel(1 << lut_num, EPDC_IRQ_CLEAR);
+ else if (lut_num < 32)
+ __raw_writel(1 << lut_num, EPDC_IRQ1_CLEAR);
+ else
+ __raw_writel(1 << (lut_num - 32), EPDC_IRQ2_CLEAR);
+}
+
+static inline bool epdc_is_lut_active(u32 lut_num)
+{
+ u32 val;
+ bool is_active;
+
+ if (lut_num < 32) {
+ val = __raw_readl(EPDC_STATUS_LUTS);
+ is_active = val & (1 << lut_num) ? true : false;
+ } else {
+ val = __raw_readl(EPDC_STATUS_LUTS2);
+ is_active = val & (1 << (lut_num - 32)) ? true : false;
+ }
+
+ return is_active;
+}
+
+static inline bool epdc_any_luts_active(int rev)
+{
+ bool any_active;
+
+ if (rev < 20)
+ any_active = __raw_readl(EPDC_STATUS_LUTS) ? true : false;
+ else
+ any_active = (__raw_readl(EPDC_STATUS_LUTS) |
+ __raw_readl(EPDC_STATUS_LUTS2)) ? true : false;
+
+ return any_active;
+}
+
+static inline bool epdc_any_luts_available(void)
+{
+ bool luts_available =
+ (__raw_readl(EPDC_STATUS_NEXTLUT) &
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_VALID) ? true : false;
+ return luts_available;
+}
+
+static inline int epdc_get_next_lut(void)
+{
+ u32 val =
+ __raw_readl(EPDC_STATUS_NEXTLUT) &
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_MASK;
+ return val;
+}
+
+static int epdc_choose_next_lut(int rev, int *next_lut)
+{
+ u64 luts_status, unprocessed_luts, used_luts;
+ /* Available LUTs are reduced to 16 in 5-bit waveform mode */
+ bool format_p5n = ((__raw_readl(EPDC_FORMAT) &
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_MASK) ==
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N);
+
+ luts_status = __raw_readl(EPDC_STATUS_LUTS);
+ if ((rev < 20) || format_p5n)
+ luts_status &= 0xFFFF;
+ else
+ luts_status |= ((u64)__raw_readl(EPDC_STATUS_LUTS2) << 32);
+
+ if (rev < 20) {
+ unprocessed_luts = __raw_readl(EPDC_IRQ) & 0xFFFF;
+ } else {
+ unprocessed_luts = __raw_readl(EPDC_IRQ1) |
+ ((u64)__raw_readl(EPDC_IRQ2) << 32);
+ if (format_p5n)
+ unprocessed_luts &= 0xFFFF;
+ }
+
+ /*
+ * Note on unprocessed_luts: There is a race condition
+ * where a LUT completes, but has not been processed by
+ * IRQ handler workqueue, and then a new update request
+ * attempts to use that LUT. We prevent that here by
+ * ensuring that the LUT we choose doesn't have its IRQ
+ * bit set (indicating it has completed but not yet been
+ * processed).
+ */
+ used_luts = luts_status | unprocessed_luts;
+
+ /*
+ * Selecting a LUT to minimize incidence of TCE Underrun Error
+ * --------------------------------------------------------
+ * We want to find the lowest order LUT that is of greater
+ * order than all other active LUTs. If highest order LUT
+ * is active, then we want to choose the lowest order
+ * available LUT.
+ *
+ * NOTE: For EPDC version 2.0 and later, TCE Underrun error
+ * bug is fixed, so it doesn't matter which LUT is used.
+ */
+
+ if ((rev < 20) || format_p5n) {
+ *next_lut = fls64(used_luts);
+ if (*next_lut > 15)
+ *next_lut = ffz(used_luts);
+ } else {
+ if ((u32)used_luts != ~0UL)
+ *next_lut = ffz((u32)used_luts);
+ else if ((u32)(used_luts >> 32) != ~0UL)
+ *next_lut = ffz((u32)(used_luts >> 32)) + 32;
+ else
+ *next_lut = INVALID_LUT;
+ }
+
+ if (used_luts & 0x8000)
+ return 1;
+ else
+ return 0;
+}
+
+static inline bool epdc_is_working_buffer_busy(void)
+{
+ u32 val = __raw_readl(EPDC_STATUS);
+ bool is_busy = (val & EPDC_STATUS_WB_BUSY) ? true : false;
+
+ return is_busy;
+}
+
+static inline bool epdc_is_working_buffer_complete(void)
+{
+ u32 val = __raw_readl(EPDC_IRQ);
+ bool is_compl = (val & EPDC_IRQ_WB_CMPLT_IRQ) ? true : false;
+
+ return is_compl;
+}
+
+static inline bool epdc_is_lut_cancelled(void)
+{
+ u32 val = __raw_readl(EPDC_STATUS);
+ bool is_void = (val & EPDC_STATUS_UPD_VOID) ? true : false;
+
+ return is_void;
+}
+
+static inline bool epdc_is_collision(void)
+{
+ u32 val = __raw_readl(EPDC_IRQ);
+ return (val & EPDC_IRQ_LUT_COL_IRQ) ? true : false;
+}
+
+static inline u64 epdc_get_colliding_luts(int rev)
+{
+ u32 val = __raw_readl(EPDC_STATUS_COL);
+ if (rev >= 20)
+ val |= (u64)__raw_readl(EPDC_STATUS_COL2) << 32;
+ return val;
+}
+
+static void epdc_set_horizontal_timing(u32 horiz_start, u32 horiz_end,
+ u32 hsync_width, u32 hsync_line_length)
+{
+ u32 reg_val =
+ ((hsync_width << EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET) &
+ EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK)
+ | ((hsync_line_length << EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET) &
+ EPDC_TCE_HSCAN1_LINE_SYNC_MASK);
+ __raw_writel(reg_val, EPDC_TCE_HSCAN1);
+
+ reg_val =
+ ((horiz_start << EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET) &
+ EPDC_TCE_HSCAN2_LINE_BEGIN_MASK)
+ | ((horiz_end << EPDC_TCE_HSCAN2_LINE_END_OFFSET) &
+ EPDC_TCE_HSCAN2_LINE_END_MASK);
+ __raw_writel(reg_val, EPDC_TCE_HSCAN2);
+}
+
+static void epdc_set_vertical_timing(u32 vert_start, u32 vert_end,
+ u32 vsync_width)
+{
+ u32 reg_val =
+ ((vert_start << EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET) &
+ EPDC_TCE_VSCAN_FRAME_BEGIN_MASK)
+ | ((vert_end << EPDC_TCE_VSCAN_FRAME_END_OFFSET) &
+ EPDC_TCE_VSCAN_FRAME_END_MASK)
+ | ((vsync_width << EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET) &
+ EPDC_TCE_VSCAN_FRAME_SYNC_MASK);
+ __raw_writel(reg_val, EPDC_TCE_VSCAN);
+}
+
+static void epdc_init_settings(struct mxc_epdc_fb_data *fb_data)
+{
+ struct imx_epdc_fb_mode *epdc_mode = fb_data->cur_mode;
+ struct fb_var_screeninfo *screeninfo = &fb_data->epdc_fb_var;
+ u32 reg_val;
+ int num_ce;
+ int i;
+
+ /* Enable clocks to access EPDC regs */
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+
+ /* Reset */
+ __raw_writel(EPDC_CTRL_SFTRST, EPDC_CTRL_SET);
+ while (!(__raw_readl(EPDC_CTRL) & EPDC_CTRL_CLKGATE))
+ ;
+ __raw_writel(EPDC_CTRL_SFTRST, EPDC_CTRL_CLEAR);
+
+ /* Enable clock gating (clear to enable) */
+ __raw_writel(EPDC_CTRL_CLKGATE, EPDC_CTRL_CLEAR);
+ while (__raw_readl(EPDC_CTRL) & (EPDC_CTRL_SFTRST | EPDC_CTRL_CLKGATE))
+ ;
+
+ /* EPDC_CTRL */
+ reg_val = __raw_readl(EPDC_CTRL);
+ reg_val &= ~EPDC_CTRL_UPD_DATA_SWIZZLE_MASK;
+ reg_val |= EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP;
+ reg_val &= ~EPDC_CTRL_LUT_DATA_SWIZZLE_MASK;
+ reg_val |= EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP;
+ __raw_writel(reg_val, EPDC_CTRL_SET);
+
+ /* EPDC_FORMAT - 2bit TFT and 4bit Buf pixel format */
+ reg_val = EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT
+ | EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N
+ | ((0x0 << EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET) &
+ EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK);
+ __raw_writel(reg_val, EPDC_FORMAT);
+
+ /* EPDC_FIFOCTRL (disabled) */
+ reg_val =
+ ((100 << EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET) &
+ EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK)
+ | ((200 << EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET) &
+ EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK)
+ | ((100 << EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET) &
+ EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK);
+ __raw_writel(reg_val, EPDC_FIFOCTRL);
+
+ /* EPDC_TEMP - Use default temp to get index */
+ epdc_set_temp(mxc_epdc_fb_get_temp_index(fb_data, DEFAULT_TEMP));
+
+ /* EPDC_RES */
+ epdc_set_screen_res(epdc_mode->vmode->xres, epdc_mode->vmode->yres);
+
+ /* EPDC_AUTOWV_LUT */
+ /* Initialize all auto-wavefrom look-up values to 2 - GC16 */
+ for (i = 0; i < 8; i++)
+ __raw_writel((2 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (i << EPDC_AUTOWV_LUT_ADDR_OFFSET), EPDC_AUTOWV_LUT);
+
+ /*
+ * EPDC_TCE_CTRL
+ * VSCAN_HOLDOFF = 4
+ * VCOM_MODE = MANUAL
+ * VCOM_VAL = 0
+ * DDR_MODE = DISABLED
+ * LVDS_MODE_CE = DISABLED
+ * LVDS_MODE = DISABLED
+ * DUAL_SCAN = DISABLED
+ * SDDO_WIDTH = 8bit
+ * PIXELS_PER_SDCLK = 4
+ */
+ reg_val =
+ ((epdc_mode->vscan_holdoff << EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET) &
+ EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK)
+ | EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4;
+ __raw_writel(reg_val, EPDC_TCE_CTRL);
+
+ /* EPDC_TCE_HSCAN */
+ epdc_set_horizontal_timing(screeninfo->left_margin,
+ screeninfo->right_margin,
+ screeninfo->hsync_len,
+ screeninfo->hsync_len);
+
+ /* EPDC_TCE_VSCAN */
+ epdc_set_vertical_timing(screeninfo->upper_margin,
+ screeninfo->lower_margin,
+ screeninfo->vsync_len);
+
+ /* EPDC_TCE_OE */
+ reg_val =
+ ((epdc_mode->sdoed_width << EPDC_TCE_OE_SDOED_WIDTH_OFFSET) &
+ EPDC_TCE_OE_SDOED_WIDTH_MASK)
+ | ((epdc_mode->sdoed_delay << EPDC_TCE_OE_SDOED_DLY_OFFSET) &
+ EPDC_TCE_OE_SDOED_DLY_MASK)
+ | ((epdc_mode->sdoez_width << EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET) &
+ EPDC_TCE_OE_SDOEZ_WIDTH_MASK)
+ | ((epdc_mode->sdoez_delay << EPDC_TCE_OE_SDOEZ_DLY_OFFSET) &
+ EPDC_TCE_OE_SDOEZ_DLY_MASK);
+ __raw_writel(reg_val, EPDC_TCE_OE);
+
+ /* EPDC_TCE_TIMING1 */
+ __raw_writel(0x0, EPDC_TCE_TIMING1);
+
+ /* EPDC_TCE_TIMING2 */
+ reg_val =
+ ((epdc_mode->gdclk_hp_offs << EPDC_TCE_TIMING2_GDCLK_HP_OFFSET) &
+ EPDC_TCE_TIMING2_GDCLK_HP_MASK)
+ | ((epdc_mode->gdsp_offs << EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET) &
+ EPDC_TCE_TIMING2_GDSP_OFFSET_MASK);
+ __raw_writel(reg_val, EPDC_TCE_TIMING2);
+
+ /* EPDC_TCE_TIMING3 */
+ reg_val =
+ ((epdc_mode->gdoe_offs << EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET) &
+ EPDC_TCE_TIMING3_GDOE_OFFSET_MASK)
+ | ((epdc_mode->gdclk_offs << EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET) &
+ EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK);
+ __raw_writel(reg_val, EPDC_TCE_TIMING3);
+
+ /*
+ * EPDC_TCE_SDCFG
+ * SDCLK_HOLD = 1
+ * SDSHR = 1
+ * NUM_CE = 1
+ * SDDO_REFORMAT = FLIP_PIXELS
+ * SDDO_INVERT = DISABLED
+ * PIXELS_PER_CE = display horizontal resolution
+ */
+ num_ce = epdc_mode->num_ce;
+ if (num_ce == 0)
+ num_ce = 1;
+ reg_val = EPDC_TCE_SDCFG_SDCLK_HOLD | EPDC_TCE_SDCFG_SDSHR
+ | ((num_ce << EPDC_TCE_SDCFG_NUM_CE_OFFSET) &
+ EPDC_TCE_SDCFG_NUM_CE_MASK)
+ | EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS
+ | ((epdc_mode->vmode->xres/num_ce << EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET) &
+ EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK);
+ __raw_writel(reg_val, EPDC_TCE_SDCFG);
+
+ /*
+ * EPDC_TCE_GDCFG
+ * GDRL = 1
+ * GDOE_MODE = 0;
+ * GDSP_MODE = 0;
+ */
+ reg_val = EPDC_TCE_SDCFG_GDRL;
+ __raw_writel(reg_val, EPDC_TCE_GDCFG);
+
+ /*
+ * EPDC_TCE_POLARITY
+ * SDCE_POL = ACTIVE LOW
+ * SDLE_POL = ACTIVE HIGH
+ * SDOE_POL = ACTIVE HIGH
+ * GDOE_POL = ACTIVE HIGH
+ * GDSP_POL = ACTIVE LOW
+ */
+ reg_val = EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH
+ | EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH
+ | EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH;
+ __raw_writel(reg_val, EPDC_TCE_POLARITY);
+
+ /* EPDC_IRQ_MASK */
+ __raw_writel(EPDC_IRQ_TCE_UNDERRUN_IRQ, EPDC_IRQ_MASK);
+
+ /*
+ * EPDC_GPIO
+ * PWRCOM = ?
+ * PWRCTRL = ?
+ * BDR = ?
+ */
+ reg_val = ((0 << EPDC_GPIO_PWRCTRL_OFFSET) & EPDC_GPIO_PWRCTRL_MASK)
+ | ((0 << EPDC_GPIO_BDR_OFFSET) & EPDC_GPIO_BDR_MASK);
+ __raw_writel(reg_val, EPDC_GPIO);
+
+ __raw_writel(fb_data->waveform_buffer_phys, EPDC_WVADDR);
+ __raw_writel(fb_data->working_buffer_phys, EPDC_WB_ADDR);
+ __raw_writel(fb_data->working_buffer_phys, EPDC_WB_ADDR_TCE);
+
+ /* Disable clock */
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+}
+
+static void epdc_powerup(struct mxc_epdc_fb_data *fb_data)
+{
+ int ret = 0;
+ mutex_lock(&fb_data->power_mutex);
+
+ /*
+ * If power down request is pending, clear
+ * powering_down to cancel the request.
+ */
+ if (fb_data->powering_down)
+ fb_data->powering_down = false;
+
+ if (fb_data->power_state == POWER_STATE_ON) {
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+
+ dev_dbg(fb_data->dev, "EPDC Powerup\n");
+
+ fb_data->updates_active = true;
+
+ /* Enable the v3p3 regulator */
+ ret = regulator_enable(fb_data->v3p3_regulator);
+ if (IS_ERR((void *)ret)) {
+ dev_err(fb_data->dev, "Unable to enable V3P3 regulator."
+ "err = 0x%x\n", ret);
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+
+ msleep(1);
+
+ pm_runtime_get_sync(fb_data->dev);
+
+ /* Enable clocks to EPDC */
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+
+ __raw_writel(EPDC_CTRL_CLKGATE, EPDC_CTRL_CLEAR);
+
+ /* Enable power to the EPD panel */
+ ret = regulator_enable(fb_data->display_regulator);
+ if (IS_ERR((void *)ret)) {
+ dev_err(fb_data->dev, "Unable to enable DISPLAY regulator."
+ "err = 0x%x\n", ret);
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+ ret = regulator_enable(fb_data->vcom_regulator);
+ if (IS_ERR((void *)ret)) {
+ dev_err(fb_data->dev, "Unable to enable VCOM regulator."
+ "err = 0x%x\n", ret);
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+
+ fb_data->power_state = POWER_STATE_ON;
+
+ mutex_unlock(&fb_data->power_mutex);
+}
+
+static void epdc_powerdown(struct mxc_epdc_fb_data *fb_data)
+{
+ mutex_lock(&fb_data->power_mutex);
+
+ /* If powering_down has been cleared, a powerup
+ * request is pre-empting this powerdown request.
+ */
+ if (!fb_data->powering_down
+ || (fb_data->power_state == POWER_STATE_OFF)) {
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+
+ dev_dbg(fb_data->dev, "EPDC Powerdown\n");
+
+ /* Disable power to the EPD panel */
+ regulator_disable(fb_data->vcom_regulator);
+ regulator_disable(fb_data->display_regulator);
+
+ /* Disable clocks to EPDC */
+ __raw_writel(EPDC_CTRL_CLKGATE, EPDC_CTRL_SET);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+
+ pm_runtime_put_sync_suspend(fb_data->dev);
+
+ /* turn off the V3p3 */
+ regulator_disable(fb_data->v3p3_regulator);
+
+ fb_data->power_state = POWER_STATE_OFF;
+ fb_data->powering_down = false;
+
+ if (fb_data->wait_for_powerdown) {
+ fb_data->wait_for_powerdown = false;
+ complete(&fb_data->powerdown_compl);
+ }
+
+ mutex_unlock(&fb_data->power_mutex);
+}
+
+static void epdc_init_sequence(struct mxc_epdc_fb_data *fb_data)
+{
+ /* Initialize EPDC, passing pointer to EPDC registers */
+ epdc_init_settings(fb_data);
+ fb_data->in_init = true;
+ epdc_powerup(fb_data);
+ draw_mode0(fb_data);
+ /* Force power down event */
+ fb_data->powering_down = true;
+ epdc_powerdown(fb_data);
+ fb_data->updates_active = false;
+}
+
+static int mxc_epdc_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ u32 len;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ if (offset < info->fix.smem_len) {
+ /* mapping framebuffer memory */
+ len = info->fix.smem_len - offset;
+ vma->vm_pgoff = (info->fix.smem_start + offset) >> PAGE_SHIFT;
+ } else
+ return -EINVAL;
+
+ len = PAGE_ALIGN(len);
+ if (vma->vm_end - vma->vm_start > len)
+ return -EINVAL;
+
+ /* make buffers bufferable */
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+ dev_dbg(info->device, "mmap remap_pfn_range failed\n");
+ return -ENOBUFS;
+ }
+
+ return 0;
+}
+
+static inline u_int _chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int mxc_epdc_fb_setcolreg(u_int regno, u_int red, u_int green,
+ u_int blue, u_int transp, struct fb_info *info)
+{
+ unsigned int val;
+ int ret = 1;
+
+ /*
+ * If greyscale is true, then we convert the RGB value
+ * to greyscale no matter what visual we are using.
+ */
+ if (info->var.grayscale)
+ red = green = blue = (19595 * red + 38470 * green +
+ 7471 * blue) >> 16;
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ /*
+ * 16-bit True Colour. We encode the RGB value
+ * according to the RGB bitfield information.
+ */
+ if (regno < 16) {
+ u32 *pal = info->pseudo_palette;
+
+ val = _chan_to_field(red, &info->var.red);
+ val |= _chan_to_field(green, &info->var.green);
+ val |= _chan_to_field(blue, &info->var.blue);
+
+ pal[regno] = val;
+ ret = 0;
+ }
+ break;
+
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ break;
+ }
+
+ return ret;
+}
+
+static int mxc_epdc_fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ int count, index, r;
+ u16 *red, *green, *blue, *transp;
+ u16 trans = 0xffff;
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ int i;
+
+ dev_dbg(fb_data->dev, "setcmap\n");
+
+ if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
+ /* Only support an 8-bit, 256 entry lookup */
+ if (cmap->len != 256)
+ return 1;
+
+ mxc_epdc_fb_flush_updates(fb_data);
+
+ mutex_lock(&fb_data->pxp_mutex);
+ /*
+ * Store colormap in pxp_conf structure for later transmit
+ * to PxP during update process to convert gray pixels.
+ *
+ * Since red=blue=green for pseudocolor visuals, we can
+ * just use red values.
+ */
+ for (i = 0; i < 256; i++)
+ fb_data->pxp_conf.proc_data.lut_map[i] = cmap->red[i] & 0xFF;
+
+ fb_data->pxp_conf.proc_data.lut_map_updated = true;
+
+ mutex_unlock(&fb_data->pxp_mutex);
+ } else {
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ index = cmap->start;
+
+ for (count = 0; count < cmap->len; count++) {
+ if (transp)
+ trans = *transp++;
+ r = mxc_epdc_fb_setcolreg(index++, *red++, *green++, *blue++,
+ trans, info);
+ if (r != 0)
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+static void adjust_coordinates(u32 xres, u32 yres, u32 rotation,
+ struct mxcfb_rect *update_region, struct mxcfb_rect *adj_update_region)
+{
+ u32 temp;
+
+ /* If adj_update_region == NULL, pass result back in update_region */
+ /* If adj_update_region == valid, use it to pass back result */
+ if (adj_update_region)
+ switch (rotation) {
+ case FB_ROTATE_UR:
+ adj_update_region->top = update_region->top;
+ adj_update_region->left = update_region->left;
+ adj_update_region->width = update_region->width;
+ adj_update_region->height = update_region->height;
+ break;
+ case FB_ROTATE_CW:
+ adj_update_region->top = update_region->left;
+ adj_update_region->left = yres -
+ (update_region->top + update_region->height);
+ adj_update_region->width = update_region->height;
+ adj_update_region->height = update_region->width;
+ break;
+ case FB_ROTATE_UD:
+ adj_update_region->width = update_region->width;
+ adj_update_region->height = update_region->height;
+ adj_update_region->top = yres -
+ (update_region->top + update_region->height);
+ adj_update_region->left = xres -
+ (update_region->left + update_region->width);
+ break;
+ case FB_ROTATE_CCW:
+ adj_update_region->left = update_region->top;
+ adj_update_region->top = xres -
+ (update_region->left + update_region->width);
+ adj_update_region->width = update_region->height;
+ adj_update_region->height = update_region->width;
+ break;
+ }
+ else
+ switch (rotation) {
+ case FB_ROTATE_UR:
+ /* No adjustment needed */
+ break;
+ case FB_ROTATE_CW:
+ temp = update_region->top;
+ update_region->top = update_region->left;
+ update_region->left = yres -
+ (temp + update_region->height);
+ temp = update_region->width;
+ update_region->width = update_region->height;
+ update_region->height = temp;
+ break;
+ case FB_ROTATE_UD:
+ update_region->top = yres -
+ (update_region->top + update_region->height);
+ update_region->left = xres -
+ (update_region->left + update_region->width);
+ break;
+ case FB_ROTATE_CCW:
+ temp = update_region->left;
+ update_region->left = update_region->top;
+ update_region->top = xres -
+ (temp + update_region->width);
+ temp = update_region->width;
+ update_region->width = update_region->height;
+ update_region->height = temp;
+ break;
+ }
+}
+
+/*
+ * Set fixed framebuffer parameters based on variable settings.
+ *
+ * @param info framebuffer information pointer
+ */
+static int mxc_epdc_fb_set_fix(struct fb_info *info)
+{
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct fb_var_screeninfo *var = &info->var;
+
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->accel = FB_ACCEL_NONE;
+ if (var->grayscale)
+ fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ else
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+
+ return 0;
+}
+
+/*
+ * This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ *
+ */
+static int mxc_epdc_fb_set_par(struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ struct fb_var_screeninfo *screeninfo = &fb_data->info.var;
+ struct imx_epdc_fb_mode *epdc_modes = fb_data->pdata->epdc_mode;
+ int i;
+ int ret;
+ __u32 xoffset_old, yoffset_old;
+
+ /*
+ * Can't change the FB parameters until current updates have completed.
+ * This function returns when all active updates are done.
+ */
+ mxc_epdc_fb_flush_updates(fb_data);
+
+ mutex_lock(&fb_data->queue_mutex);
+ /*
+ * Set all screeninfo except for xoffset/yoffset
+ * Subsequent call to pan_display will handle those.
+ */
+ xoffset_old = fb_data->epdc_fb_var.xoffset;
+ yoffset_old = fb_data->epdc_fb_var.yoffset;
+ fb_data->epdc_fb_var = *screeninfo;
+ fb_data->epdc_fb_var.xoffset = xoffset_old;
+ fb_data->epdc_fb_var.yoffset = yoffset_old;
+ mutex_unlock(&fb_data->queue_mutex);
+
+ mutex_lock(&fb_data->pxp_mutex);
+
+ /*
+ * Update PxP config data (used to process FB regions for updates)
+ * based on FB info and processing tasks required
+ */
+
+ /* Initialize non-channel-specific PxP parameters */
+ proc_data->drect.left = proc_data->srect.left = 0;
+ proc_data->drect.top = proc_data->srect.top = 0;
+ proc_data->drect.width = proc_data->srect.width = screeninfo->xres;
+ proc_data->drect.height = proc_data->srect.height = screeninfo->yres;
+ proc_data->scaling = 0;
+ proc_data->hflip = 0;
+ proc_data->vflip = 0;
+ proc_data->rotate = screeninfo->rotate;
+ proc_data->bgcolor = 0;
+ proc_data->overlay_state = 0;
+ proc_data->lut_transform = PXP_LUT_NONE;
+
+ /*
+ * configure S0 channel parameters
+ * Parameters should match FB format/width/height
+ */
+ if (screeninfo->grayscale)
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_GREY;
+ else {
+ switch (screeninfo->bits_per_pixel) {
+ case 16:
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
+ break;
+ case 24:
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB24;
+ break;
+ case 32:
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_XRGB32;
+ break;
+ default:
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
+ break;
+ }
+ }
+ pxp_conf->s0_param.width = screeninfo->xres_virtual;
+ pxp_conf->s0_param.height = screeninfo->yres;
+ pxp_conf->s0_param.color_key = -1;
+ pxp_conf->s0_param.color_key_enable = false;
+
+ /*
+ * Initialize Output channel parameters
+ * Output is Y-only greyscale
+ * Output width/height will vary based on update region size
+ */
+ pxp_conf->out_param.width = screeninfo->xres;
+ pxp_conf->out_param.height = screeninfo->yres;
+ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_GREY;
+
+ mutex_unlock(&fb_data->pxp_mutex);
+
+ /*
+ * If HW not yet initialized, check to see if we are being sent
+ * an initialization request.
+ */
+ if (!fb_data->hw_ready) {
+ struct fb_videomode mode;
+ u32 xres_temp;
+
+ fb_var_to_videomode(&mode, screeninfo);
+
+ /* When comparing requested fb mode,
+ we need to use unrotated dimensions */
+ if ((screeninfo->rotate == FB_ROTATE_CW) ||
+ (screeninfo->rotate == FB_ROTATE_CCW)) {
+ xres_temp = mode.xres;
+ mode.xres = mode.yres;
+ mode.yres = xres_temp;
+ }
+
+ /*
+ * If requested video mode does not match current video
+ * mode, search for a matching panel.
+ */
+ if (fb_data->cur_mode &&
+ !fb_mode_is_equal(fb_data->cur_mode->vmode,
+ &mode)) {
+ bool found_match = false;
+
+ /* Match videomode against epdc modes */
+ for (i = 0; i < fb_data->pdata->num_modes; i++) {
+ if (!fb_mode_is_equal(epdc_modes[i].vmode,
+ &mode))
+ continue;
+ fb_data->cur_mode = &epdc_modes[i];
+ found_match = true;
+ break;
+ }
+
+ if (!found_match) {
+ dev_err(fb_data->dev,
+ "Failed to match requested "
+ "video mode\n");
+ return EINVAL;
+ }
+ }
+
+ /* Found a match - Grab timing params */
+ screeninfo->left_margin = mode.left_margin;
+ screeninfo->right_margin = mode.right_margin;
+ screeninfo->upper_margin = mode.upper_margin;
+ screeninfo->lower_margin = mode.lower_margin;
+ screeninfo->hsync_len = mode.hsync_len;
+ screeninfo->vsync_len = mode.vsync_len;
+
+ fb_data->hw_initializing = true;
+
+ /* Initialize EPDC settings and init panel */
+ ret =
+ mxc_epdc_fb_init_hw((struct fb_info *)fb_data);
+ if (ret) {
+ dev_err(fb_data->dev,
+ "Failed to load panel waveform data\n");
+ return ret;
+ }
+ }
+
+ /*
+ * EOF sync delay (in us) should be equal to the vscan holdoff time
+ * VSCAN_HOLDOFF time = (VSCAN_HOLDOFF value + 1) * Vertical lines
+ * Add 25us for additional margin
+ */
+ fb_data->eof_sync_period = (fb_data->cur_mode->vscan_holdoff + 1) *
+ 1000000/(fb_data->cur_mode->vmode->refresh *
+ (fb_data->cur_mode->vmode->upper_margin +
+ fb_data->cur_mode->vmode->yres +
+ fb_data->cur_mode->vmode->lower_margin +
+ fb_data->cur_mode->vmode->vsync_len)) + 25;
+
+ mxc_epdc_fb_set_fix(info);
+
+ return 0;
+}
+
+static int mxc_epdc_fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+
+ if (!var->xres)
+ var->xres = 1;
+ if (!var->yres)
+ var->yres = 1;
+
+ if (var->xres_virtual < var->xoffset + var->xres)
+ var->xres_virtual = var->xoffset + var->xres;
+ if (var->yres_virtual < var->yoffset + var->yres)
+ var->yres_virtual = var->yoffset + var->yres;
+
+ if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
+ (var->bits_per_pixel != 16) && (var->bits_per_pixel != 8))
+ var->bits_per_pixel = default_bpp;
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ if (var->grayscale != 0) {
+ /*
+ * For 8-bit grayscale, R, G, and B offset are equal.
+ *
+ */
+ var->red.length = 8;
+ var->red.offset = 0;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 0;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ } else {
+ var->red.length = 3;
+ var->red.offset = 5;
+ var->red.msb_right = 0;
+
+ var->green.length = 3;
+ var->green.offset = 2;
+ var->green.msb_right = 0;
+
+ var->blue.length = 2;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ }
+ break;
+ case 16:
+ var->red.length = 5;
+ var->red.offset = 11;
+ var->red.msb_right = 0;
+
+ var->green.length = 6;
+ var->green.offset = 5;
+ var->green.msb_right = 0;
+
+ var->blue.length = 5;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 24:
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 32:
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 8;
+ var->transp.offset = 24;
+ var->transp.msb_right = 0;
+ break;
+ }
+
+ switch (var->rotate) {
+ case FB_ROTATE_UR:
+ case FB_ROTATE_UD:
+ var->xres = fb_data->native_width;
+ var->yres = fb_data->native_height;
+ break;
+ case FB_ROTATE_CW:
+ case FB_ROTATE_CCW:
+ var->xres = fb_data->native_height;
+ var->yres = fb_data->native_width;
+ break;
+ default:
+ /* Invalid rotation value */
+ var->rotate = 0;
+ dev_dbg(fb_data->dev, "Invalid rotation request\n");
+ return -EINVAL;
+ }
+
+ var->xres_virtual = ALIGN(var->xres, 32);
+ var->yres_virtual = ALIGN(var->yres, 128) * fb_data->num_screens;
+
+ var->height = -1;
+ var->width = -1;
+
+ return 0;
+}
+
+void mxc_epdc_fb_set_waveform_modes(struct mxcfb_waveform_modes *modes,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ mutex_lock(&fb_data->queue_mutex);
+
+ memcpy(&fb_data->wv_modes, modes, sizeof(struct mxcfb_waveform_modes));
+
+ /* Set flag to ensure that new waveform modes
+ * are programmed into EPDC before next update */
+ fb_data->wv_modes_update = true;
+
+ mutex_unlock(&fb_data->queue_mutex);
+}
+EXPORT_SYMBOL(mxc_epdc_fb_set_waveform_modes);
+
+static int mxc_epdc_fb_get_temp_index(struct mxc_epdc_fb_data *fb_data, int temp)
+{
+ int i;
+ int index = -1;
+
+ if (fb_data->trt_entries == 0) {
+ dev_err(fb_data->dev,
+ "No TRT exists...using default temp index\n");
+ return DEFAULT_TEMP_INDEX;
+ }
+
+ /* Search temperature ranges for a match */
+ for (i = 0; i < fb_data->trt_entries - 1; i++) {
+ if ((temp >= fb_data->temp_range_bounds[i])
+ && (temp < fb_data->temp_range_bounds[i+1])) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0) {
+ dev_err(fb_data->dev,
+ "No TRT index match...using default temp index\n");
+ return DEFAULT_TEMP_INDEX;
+ }
+
+ dev_dbg(fb_data->dev, "Using temperature index %d\n", index);
+
+ return index;
+}
+
+int mxc_epdc_fb_set_temperature(int temperature, struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ /* Store temp index. Used later when configuring updates. */
+ mutex_lock(&fb_data->queue_mutex);
+ fb_data->temp_index = mxc_epdc_fb_get_temp_index(fb_data, temperature);
+ mutex_unlock(&fb_data->queue_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(mxc_epdc_fb_set_temperature);
+
+int mxc_epdc_fb_set_auto_update(u32 auto_mode, struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ dev_dbg(fb_data->dev, "Setting auto update mode to %d\n", auto_mode);
+
+ if ((auto_mode == AUTO_UPDATE_MODE_AUTOMATIC_MODE)
+ || (auto_mode == AUTO_UPDATE_MODE_REGION_MODE))
+ fb_data->auto_mode = auto_mode;
+ else {
+ dev_err(fb_data->dev, "Invalid auto update mode parameter.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mxc_epdc_fb_set_auto_update);
+
+int mxc_epdc_fb_set_upd_scheme(u32 upd_scheme, struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ dev_dbg(fb_data->dev, "Setting optimization level to %d\n", upd_scheme);
+
+ /*
+ * Can't change the scheme until current updates have completed.
+ * This function returns when all active updates are done.
+ */
+ mxc_epdc_fb_flush_updates(fb_data);
+
+ if ((upd_scheme == UPDATE_SCHEME_SNAPSHOT)
+ || (upd_scheme == UPDATE_SCHEME_QUEUE)
+ || (upd_scheme == UPDATE_SCHEME_QUEUE_AND_MERGE))
+ fb_data->upd_scheme = upd_scheme;
+ else {
+ dev_err(fb_data->dev, "Invalid update scheme specified.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mxc_epdc_fb_set_upd_scheme);
+
+static void copy_before_process(struct mxc_epdc_fb_data *fb_data,
+ struct update_data_list *upd_data_list)
+{
+ struct mxcfb_update_data *upd_data =
+ &upd_data_list->update_desc->upd_data;
+ int i;
+ unsigned char *temp_buf_ptr = fb_data->virt_addr_copybuf;
+ unsigned char *src_ptr;
+ struct mxcfb_rect *src_upd_region;
+ int temp_buf_stride;
+ int src_stride;
+ int bpp = fb_data->epdc_fb_var.bits_per_pixel;
+ int left_offs, right_offs;
+ int x_trailing_bytes, y_trailing_bytes;
+ int alt_buf_offset;
+
+ /* Set source buf pointer based on input source, panning, etc. */
+ if (upd_data->flags & EPDC_FLAG_USE_ALT_BUFFER) {
+ src_upd_region = &upd_data->alt_buffer_data.alt_update_region;
+ src_stride =
+ upd_data->alt_buffer_data.width * bpp/8;
+ alt_buf_offset = upd_data->alt_buffer_data.phys_addr -
+ fb_data->info.fix.smem_start;
+ src_ptr = fb_data->info.screen_base + alt_buf_offset
+ + src_upd_region->top * src_stride;
+ } else {
+ src_upd_region = &upd_data->update_region;
+ src_stride = fb_data->epdc_fb_var.xres_virtual * bpp/8;
+ src_ptr = fb_data->info.screen_base + fb_data->fb_offset
+ + src_upd_region->top * src_stride;
+ }
+
+ temp_buf_stride = ALIGN(src_upd_region->width, 8) * bpp/8;
+ left_offs = src_upd_region->left * bpp/8;
+ right_offs = src_upd_region->width * bpp/8;
+ x_trailing_bytes = (ALIGN(src_upd_region->width, 8)
+ - src_upd_region->width) * bpp/8;
+
+ for (i = 0; i < src_upd_region->height; i++) {
+ /* Copy the full line */
+ memcpy(temp_buf_ptr, src_ptr + left_offs,
+ src_upd_region->width * bpp/8);
+
+ /* Clear any unwanted pixels at the end of each line */
+ if (src_upd_region->width & 0x7) {
+ memset(temp_buf_ptr + right_offs, 0x0,
+ x_trailing_bytes);
+ }
+
+ temp_buf_ptr += temp_buf_stride;
+ src_ptr += src_stride;
+ }
+
+ /* Clear any unwanted pixels at the bottom of the end of each line */
+ if (src_upd_region->height & 0x7) {
+ y_trailing_bytes = (ALIGN(src_upd_region->height, 8)
+ - src_upd_region->height) *
+ ALIGN(src_upd_region->width, 8) * bpp/8;
+ memset(temp_buf_ptr, 0x0, y_trailing_bytes);
+ }
+}
+
+static int epdc_process_update(struct update_data_list *upd_data_list,
+ struct mxc_epdc_fb_data *fb_data)
+{
+ struct mxcfb_rect *src_upd_region; /* Region of src buffer for update */
+ struct mxcfb_rect pxp_upd_region;
+ u32 src_width, src_height;
+ u32 offset_from_4, bytes_per_pixel;
+ u32 post_rotation_xcoord, post_rotation_ycoord, width_pxp_blocks;
+ u32 pxp_input_offs, pxp_output_offs, pxp_output_shift;
+ u32 hist_stat = 0;
+ int width_unaligned, height_unaligned;
+ bool input_unaligned = false;
+ bool line_overflow = false;
+ int pix_per_line_added;
+ bool use_temp_buf = false;
+ struct mxcfb_rect temp_buf_upd_region;
+ struct update_desc_list *upd_desc_list = upd_data_list->update_desc;
+
+ int ret;
+
+ /*
+ * Gotta do a whole bunch of buffer ptr manipulation to
+ * work around HW restrictions for PxP & EPDC
+ * Note: Applies to pre-2.0 versions of EPDC/PxP
+ */
+
+ /*
+ * Are we using FB or an alternate (overlay)
+ * buffer for source of update?
+ */
+ if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_ALT_BUFFER) {
+ src_width = upd_desc_list->upd_data.alt_buffer_data.width;
+ src_height = upd_desc_list->upd_data.alt_buffer_data.height;
+ src_upd_region = &upd_desc_list->upd_data.alt_buffer_data.alt_update_region;
+ } else {
+ src_width = fb_data->epdc_fb_var.xres_virtual;
+ src_height = fb_data->epdc_fb_var.yres;
+ src_upd_region = &upd_desc_list->upd_data.update_region;
+ }
+
+ bytes_per_pixel = fb_data->epdc_fb_var.bits_per_pixel/8;
+
+ /*
+ * SW workaround for PxP limitation (for pre-v2.0 HW)
+ *
+ * There are 3 cases where we cannot process the update data
+ * directly from the input buffer:
+ *
+ * 1) PxP must process 8x8 pixel blocks, and all pixels in each block
+ * are considered for auto-waveform mode selection. If the
+ * update region is not 8x8 aligned, additional unwanted pixels
+ * will be considered in auto-waveform mode selection.
+ *
+ * 2) PxP input must be 32-bit aligned, so any update
+ * address not 32-bit aligned must be shifted to meet the
+ * 32-bit alignment. The PxP will thus end up processing pixels
+ * outside of the update region to satisfy this alignment restriction,
+ * which can affect auto-waveform mode selection.
+ *
+ * 3) If input fails 32-bit alignment, and the resulting expansion
+ * of the processed region would add at least 8 pixels more per
+ * line than the original update line width, the EPDC would
+ * cause screen artifacts by incorrectly handling the 8+ pixels
+ * at the end of each line.
+ *
+ * Workaround is to copy from source buffer into a temporary
+ * buffer, which we pad with zeros to match the 8x8 alignment
+ * requirement. This temp buffer becomes the input to the PxP.
+ */
+ width_unaligned = src_upd_region->width & 0x7;
+ height_unaligned = src_upd_region->height & 0x7;
+
+ offset_from_4 = src_upd_region->left & 0x3;
+ input_unaligned = ((offset_from_4 * bytes_per_pixel % 4) != 0) ?
+ true : false;
+
+ pix_per_line_added = (offset_from_4 * bytes_per_pixel % 4)
+ / bytes_per_pixel;
+ if ((((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) ||
+ fb_data->epdc_fb_var.rotate == FB_ROTATE_UD)) &&
+ (ALIGN(src_upd_region->width, 8) <
+ ALIGN(src_upd_region->width + pix_per_line_added, 8)))
+ line_overflow = true;
+
+ /* Grab pxp_mutex here so that we protect access
+ * to copybuf in addition to the PxP structures */
+ mutex_lock(&fb_data->pxp_mutex);
+
+ if (((((width_unaligned || height_unaligned || input_unaligned) &&
+ (upd_desc_list->upd_data.waveform_mode == WAVEFORM_MODE_AUTO))
+ || line_overflow) && (fb_data->rev < 20)) ||
+ fb_data->restrict_width) {
+ dev_dbg(fb_data->dev, "Copying update before processing.\n");
+
+ /* Update to reflect what the new source buffer will be */
+ src_width = ALIGN(src_upd_region->width, 8);
+ src_height = ALIGN(src_upd_region->height, 8);
+
+ copy_before_process(fb_data, upd_data_list);
+
+ /*
+ * src_upd_region should now describe
+ * the new update buffer attributes.
+ */
+ temp_buf_upd_region.left = 0;
+ temp_buf_upd_region.top = 0;
+ temp_buf_upd_region.width = src_upd_region->width;
+ temp_buf_upd_region.height = src_upd_region->height;
+ src_upd_region = &temp_buf_upd_region;
+
+ use_temp_buf = true;
+ }
+
+ /*
+ * For pre-2.0 HW, input address must be 32-bit aligned
+ * Compute buffer offset to account for this PxP limitation
+ */
+ offset_from_4 = src_upd_region->left & 0x3;
+ input_unaligned = ((offset_from_4 * bytes_per_pixel % 4) != 0) ?
+ true : false;
+ if ((fb_data->rev < 20) && input_unaligned) {
+ /* Leave a gap between PxP input addr and update region pixels */
+ pxp_input_offs =
+ (src_upd_region->top * src_width + src_upd_region->left)
+ * bytes_per_pixel & 0xFFFFFFFC;
+ /* Update region left changes to reflect relative position to input ptr */
+ pxp_upd_region.left = (offset_from_4 * bytes_per_pixel % 4)
+ / bytes_per_pixel;
+ } else {
+ pxp_input_offs =
+ (src_upd_region->top * src_width + src_upd_region->left)
+ * bytes_per_pixel;
+ pxp_upd_region.left = 0;
+ }
+
+ pxp_upd_region.top = 0;
+
+ /*
+ * For version 2.0 and later of EPDC & PxP, if no rotation, we don't
+ * need to align width & height (rotation always requires 8-pixel
+ * width & height alignment, per PxP limitations)
+ */
+ if ((fb_data->epdc_fb_var.rotate == 0) && (fb_data->rev >= 20)) {
+ pxp_upd_region.width = src_upd_region->width;
+ pxp_upd_region.height = src_upd_region->height;
+ } else {
+ /* Update region dimensions to meet 8x8 pixel requirement */
+ pxp_upd_region.width = ALIGN(src_upd_region->width + pxp_upd_region.left, 8);
+ pxp_upd_region.height = ALIGN(src_upd_region->height, 8);
+ }
+
+ switch (fb_data->epdc_fb_var.rotate) {
+ case FB_ROTATE_UR:
+ default:
+ post_rotation_xcoord = pxp_upd_region.left;
+ post_rotation_ycoord = pxp_upd_region.top;
+ width_pxp_blocks = pxp_upd_region.width;
+ break;
+ case FB_ROTATE_CW:
+ width_pxp_blocks = pxp_upd_region.height;
+ post_rotation_xcoord = width_pxp_blocks - src_upd_region->height;
+ post_rotation_ycoord = pxp_upd_region.left;
+ break;
+ case FB_ROTATE_UD:
+ width_pxp_blocks = pxp_upd_region.width;
+ post_rotation_xcoord = width_pxp_blocks - src_upd_region->width - pxp_upd_region.left;
+ post_rotation_ycoord = pxp_upd_region.height - src_upd_region->height - pxp_upd_region.top;
+ break;
+ case FB_ROTATE_CCW:
+ width_pxp_blocks = pxp_upd_region.height;
+ post_rotation_xcoord = pxp_upd_region.top;
+ post_rotation_ycoord = pxp_upd_region.width - src_upd_region->width - pxp_upd_region.left;
+ break;
+ }
+
+ /* Update region start coord to force PxP to process full 8x8 regions */
+ pxp_upd_region.top &= ~0x7;
+ pxp_upd_region.left &= ~0x7;
+
+ if (fb_data->rev < 20) {
+ pxp_output_shift = ALIGN(post_rotation_xcoord, 8)
+ - post_rotation_xcoord;
+
+ pxp_output_offs = post_rotation_ycoord * width_pxp_blocks
+ + pxp_output_shift;
+
+ upd_desc_list->epdc_offs = ALIGN(pxp_output_offs, 8);
+ } else {
+ pxp_output_shift = 0;
+ pxp_output_offs = post_rotation_ycoord * width_pxp_blocks
+ + post_rotation_xcoord;
+
+ upd_desc_list->epdc_offs = pxp_output_offs;
+ }
+
+ upd_desc_list->epdc_stride = width_pxp_blocks;
+
+ /* Source address either comes from alternate buffer
+ provided in update data, or from the framebuffer. */
+ if (use_temp_buf)
+ sg_dma_address(&fb_data->sg[0]) =
+ fb_data->phys_addr_copybuf;
+ else if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_ALT_BUFFER)
+ sg_dma_address(&fb_data->sg[0]) =
+ upd_desc_list->upd_data.alt_buffer_data.phys_addr
+ + pxp_input_offs;
+ else {
+ sg_dma_address(&fb_data->sg[0]) =
+ fb_data->info.fix.smem_start + fb_data->fb_offset
+ + pxp_input_offs;
+ sg_set_page(&fb_data->sg[0],
+ virt_to_page(fb_data->info.screen_base),
+ fb_data->info.fix.smem_len,
+ offset_in_page(fb_data->info.screen_base));
+ }
+
+ /* Update sg[1] to point to output of PxP proc task */
+ sg_dma_address(&fb_data->sg[1]) = upd_data_list->phys_addr
+ + pxp_output_shift;
+ sg_set_page(&fb_data->sg[1], virt_to_page(upd_data_list->virt_addr),
+ fb_data->max_pix_size,
+ offset_in_page(upd_data_list->virt_addr));
+
+ /*
+ * Set PxP LUT transform type based on update flags.
+ */
+ fb_data->pxp_conf.proc_data.lut_transform = 0;
+ if (upd_desc_list->upd_data.flags & EPDC_FLAG_ENABLE_INVERSION)
+ fb_data->pxp_conf.proc_data.lut_transform |= PXP_LUT_INVERT;
+ if (upd_desc_list->upd_data.flags & EPDC_FLAG_FORCE_MONOCHROME)
+ fb_data->pxp_conf.proc_data.lut_transform |=
+ PXP_LUT_BLACK_WHITE;
+ if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_CMAP)
+ fb_data->pxp_conf.proc_data.lut_transform |=
+ PXP_LUT_USE_CMAP;
+
+ /*
+ * Toggle inversion processing if 8-bit
+ * inverted is the current pixel format.
+ */
+ if (fb_data->epdc_fb_var.grayscale == GRAYSCALE_8BIT_INVERTED)
+ fb_data->pxp_conf.proc_data.lut_transform ^= PXP_LUT_INVERT;
+
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_process_update(fb_data, src_width, src_height,
+ &pxp_upd_region);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ /* If needed, enable EPDC HW while ePxP is processing */
+ if ((fb_data->power_state == POWER_STATE_OFF)
+ || fb_data->powering_down) {
+ epdc_powerup(fb_data);
+ }
+
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_complete_update(fb_data, &hist_stat);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to complete PxP update task.\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ mutex_unlock(&fb_data->pxp_mutex);
+
+ /* Update waveform mode from PxP histogram results */
+ if ((fb_data->rev <= 20) &&
+ (upd_desc_list->upd_data.waveform_mode == WAVEFORM_MODE_AUTO)) {
+ if (hist_stat & 0x1)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_du;
+ else if (hist_stat & 0x2)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc4;
+ else if (hist_stat & 0x4)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc8;
+ else if (hist_stat & 0x8)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc16;
+ else
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc32;
+
+ dev_dbg(fb_data->dev, "hist_stat = 0x%x, new waveform = 0x%x\n",
+ hist_stat, upd_desc_list->upd_data.waveform_mode);
+ }
+
+ return 0;
+}
+
+static int epdc_submit_merge(struct update_desc_list *upd_desc_list,
+ struct update_desc_list *update_to_merge,
+ struct mxc_epdc_fb_data *fb_data)
+{
+ struct mxcfb_update_data *a, *b;
+ struct mxcfb_rect *arect, *brect;
+ struct mxcfb_rect combine;
+ bool use_flags = false;
+
+ a = &upd_desc_list->upd_data;
+ b = &update_to_merge->upd_data;
+ arect = &upd_desc_list->upd_data.update_region;
+ brect = &update_to_merge->upd_data.update_region;
+
+ /* Do not merge a dry-run collision test update */
+ if ((a->flags & EPDC_FLAG_TEST_COLLISION) ||
+ (b->flags & EPDC_FLAG_TEST_COLLISION))
+ return MERGE_BLOCK;
+
+ /*
+ * Updates with different flags must be executed sequentially.
+ * Halt the merge process to ensure this.
+ */
+ if (a->flags != b->flags) {
+ /*
+ * Special exception: if update regions are identical,
+ * we may be able to merge them.
+ */
+ if ((arect->left != brect->left) ||
+ (arect->top != brect->top) ||
+ (arect->width != brect->width) ||
+ (arect->height != brect->height))
+ return MERGE_BLOCK;
+
+ use_flags = true;
+ }
+
+ if (a->update_mode != b->update_mode)
+ a->update_mode = UPDATE_MODE_FULL;
+
+ if (a->waveform_mode != b->waveform_mode)
+ a->waveform_mode = WAVEFORM_MODE_AUTO;
+
+ if (arect->left > (brect->left + brect->width) ||
+ brect->left > (arect->left + arect->width) ||
+ arect->top > (brect->top + brect->height) ||
+ brect->top > (arect->top + arect->height))
+ return MERGE_FAIL;
+
+ combine.left = arect->left < brect->left ? arect->left : brect->left;
+ combine.top = arect->top < brect->top ? arect->top : brect->top;
+ combine.width = (arect->left + arect->width) >
+ (brect->left + brect->width) ?
+ (arect->left + arect->width - combine.left) :
+ (brect->left + brect->width - combine.left);
+ combine.height = (arect->top + arect->height) >
+ (brect->top + brect->height) ?
+ (arect->top + arect->height - combine.top) :
+ (brect->top + brect->height - combine.top);
+
+ /* Don't merge if combined width exceeds max width */
+ if (fb_data->restrict_width) {
+ u32 max_width = EPDC_V2_MAX_UPDATE_WIDTH;
+ u32 combined_width = combine.width;
+ if (fb_data->epdc_fb_var.rotate != FB_ROTATE_UR)
+ max_width -= EPDC_V2_ROTATION_ALIGNMENT;
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_CW) ||
+ (fb_data->epdc_fb_var.rotate == FB_ROTATE_CCW))
+ combined_width = combine.height;
+ if (combined_width > max_width)
+ return MERGE_FAIL;
+ }
+
+ *arect = combine;
+
+ /* Use flags of the later update */
+ if (use_flags)
+ a->flags = b->flags;
+
+ /* Merge markers */
+ list_splice_tail(&update_to_merge->upd_marker_list,
+ &upd_desc_list->upd_marker_list);
+
+ /* Merged update should take on the earliest order */
+ upd_desc_list->update_order =
+ (upd_desc_list->update_order > update_to_merge->update_order) ?
+ upd_desc_list->update_order : update_to_merge->update_order;
+
+ return MERGE_OK;
+}
+
+static void epdc_submit_work_func(struct work_struct *work)
+{
+ int temp_index;
+ struct update_data_list *next_update, *temp_update;
+ struct update_desc_list *next_desc, *temp_desc;
+ struct update_marker_data *next_marker, *temp_marker;
+ struct mxc_epdc_fb_data *fb_data =
+ container_of(work, struct mxc_epdc_fb_data, epdc_submit_work);
+ struct update_data_list *upd_data_list = NULL;
+ struct mxcfb_rect adj_update_region, *upd_region;
+ bool end_merge = false;
+ bool is_transform;
+ u32 update_addr;
+ int *err_dist;
+ int ret;
+
+ /* Protect access to buffer queues and to update HW */
+ mutex_lock(&fb_data->queue_mutex);
+
+ /*
+ * Are any of our collision updates able to go now?
+ * Go through all updates in the collision list and check to see
+ * if the collision mask has been fully cleared
+ */
+ list_for_each_entry_safe(next_update, temp_update,
+ &fb_data->upd_buf_collision_list, list) {
+
+ if (next_update->collision_mask != 0)
+ continue;
+
+ dev_dbg(fb_data->dev, "A collision update is ready to go!\n");
+
+ /* Force waveform mode to auto for resubmitted collisions */
+ next_update->update_desc->upd_data.waveform_mode =
+ WAVEFORM_MODE_AUTO;
+
+ /*
+ * We have a collision cleared, so select it for resubmission.
+ * If an update is already selected, attempt to merge.
+ */
+ if (!upd_data_list) {
+ upd_data_list = next_update;
+ list_del_init(&next_update->list);
+ if (fb_data->upd_scheme == UPDATE_SCHEME_QUEUE)
+ /* If not merging, we have our update */
+ break;
+ } else {
+ switch (epdc_submit_merge(upd_data_list->update_desc,
+ next_update->update_desc,
+ fb_data)) {
+ case MERGE_OK:
+ dev_dbg(fb_data->dev,
+ "Update merged [collision]\n");
+ list_del_init(&next_update->update_desc->list);
+ kfree(next_update->update_desc);
+ next_update->update_desc = NULL;
+ list_del_init(&next_update->list);
+ /* Add to free buffer list */
+ list_add_tail(&next_update->list,
+ &fb_data->upd_buf_free_list);
+ break;
+ case MERGE_FAIL:
+ dev_dbg(fb_data->dev,
+ "Update not merged [collision]\n");
+ break;
+ case MERGE_BLOCK:
+ dev_dbg(fb_data->dev,
+ "Merge blocked [collision]\n");
+ end_merge = true;
+ break;
+ }
+
+ if (end_merge) {
+ end_merge = false;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Skip pending update list only if we found a collision
+ * update and we are not merging
+ */
+ if (!((fb_data->upd_scheme == UPDATE_SCHEME_QUEUE) &&
+ upd_data_list)) {
+ /*
+ * If we didn't find a collision update ready to go, we
+ * need to get a free buffer and match it to a pending update.
+ */
+
+ /*
+ * Can't proceed if there are no free buffers (and we don't
+ * already have a collision update selected)
+ */
+ if (!upd_data_list &&
+ list_empty(&fb_data->upd_buf_free_list)) {
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ list_for_each_entry_safe(next_desc, temp_desc,
+ &fb_data->upd_pending_list, list) {
+
+ dev_dbg(fb_data->dev, "Found a pending update!\n");
+
+ if (!upd_data_list) {
+ if (list_empty(&fb_data->upd_buf_free_list))
+ break;
+ upd_data_list =
+ list_entry(fb_data->upd_buf_free_list.next,
+ struct update_data_list, list);
+ list_del_init(&upd_data_list->list);
+ upd_data_list->update_desc = next_desc;
+ list_del_init(&next_desc->list);
+ if (fb_data->upd_scheme == UPDATE_SCHEME_QUEUE)
+ /* If not merging, we have an update */
+ break;
+ } else {
+ switch (epdc_submit_merge(upd_data_list->update_desc,
+ next_desc, fb_data)) {
+ case MERGE_OK:
+ dev_dbg(fb_data->dev,
+ "Update merged [queue]\n");
+ list_del_init(&next_desc->list);
+ kfree(next_desc);
+ break;
+ case MERGE_FAIL:
+ dev_dbg(fb_data->dev,
+ "Update not merged [queue]\n");
+ break;
+ case MERGE_BLOCK:
+ dev_dbg(fb_data->dev,
+ "Merge blocked [collision]\n");
+ end_merge = true;
+ break;
+ }
+
+ if (end_merge)
+ break;
+ }
+ }
+ }
+
+ /* Is update list empty? */
+ if (!upd_data_list) {
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ /*
+ * If no processing required, skip update processing
+ * No processing means:
+ * - FB unrotated
+ * - FB pixel format = 8-bit grayscale
+ * - No look-up transformations (inversion, posterization, etc.)
+ *
+ * Note: A bug with EPDC stride prevents us from skipping
+ * PxP in versions 2.0 and earlier of EPDC.
+ */
+ is_transform = upd_data_list->update_desc->upd_data.flags &
+ (EPDC_FLAG_ENABLE_INVERSION | EPDC_FLAG_USE_DITHERING_Y1 |
+ EPDC_FLAG_USE_DITHERING_Y4 | EPDC_FLAG_FORCE_MONOCHROME |
+ EPDC_FLAG_USE_CMAP) ? true : false;
+
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) &&
+ (fb_data->epdc_fb_var.grayscale == GRAYSCALE_8BIT) &&
+ !is_transform && (fb_data->rev > 20) &&
+ !fb_data->restrict_width) {
+
+ /* If needed, enable EPDC HW while ePxP is processing */
+ if ((fb_data->power_state == POWER_STATE_OFF)
+ || fb_data->powering_down)
+ epdc_powerup(fb_data);
+
+ /*
+ * Set update buffer pointer to the start of
+ * the update region in the frame buffer.
+ */
+ upd_region = &upd_data_list->update_desc->upd_data.update_region;
+ update_addr = fb_data->info.fix.smem_start +
+ ((upd_region->top * fb_data->info.var.xres_virtual) +
+ upd_region->left) * fb_data->info.var.bits_per_pixel/8;
+ upd_data_list->update_desc->epdc_stride =
+ fb_data->info.var.xres_virtual *
+ fb_data->info.var.bits_per_pixel/8;
+ } else {
+ /* Select from PxP output buffers */
+ upd_data_list->phys_addr =
+ fb_data->phys_addr_updbuf[fb_data->upd_buffer_num];
+ upd_data_list->virt_addr =
+ fb_data->virt_addr_updbuf[fb_data->upd_buffer_num];
+ fb_data->upd_buffer_num++;
+ if (fb_data->upd_buffer_num > fb_data->max_num_buffers-1)
+ fb_data->upd_buffer_num = 0;
+
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+
+ /* Perform PXP processing - EPDC power will also be enabled */
+ if (epdc_process_update(upd_data_list, fb_data)) {
+ dev_dbg(fb_data->dev, "PXP processing error.\n");
+ /* Protect access to buffer queues and to update HW */
+ mutex_lock(&fb_data->queue_mutex);
+ list_del_init(&upd_data_list->update_desc->list);
+ kfree(upd_data_list->update_desc);
+ upd_data_list->update_desc = NULL;
+ /* Add to free buffer list */
+ list_add_tail(&upd_data_list->list,
+ &fb_data->upd_buf_free_list);
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ /* Protect access to buffer queues and to update HW */
+ mutex_lock(&fb_data->queue_mutex);
+
+ update_addr = upd_data_list->phys_addr
+ + upd_data_list->update_desc->epdc_offs;
+ }
+
+ /* Get rotation-adjusted coordinates */
+ adjust_coordinates(fb_data->epdc_fb_var.xres,
+ fb_data->epdc_fb_var.yres, fb_data->epdc_fb_var.rotate,
+ &upd_data_list->update_desc->upd_data.update_region,
+ &adj_update_region);
+
+ /*
+ * Is the working buffer idle?
+ * If the working buffer is busy, we must wait for the resource
+ * to become free. The IST will signal this event.
+ */
+ if (fb_data->cur_update != NULL) {
+ dev_dbg(fb_data->dev, "working buf busy!\n");
+
+ /* Initialize event signalling an update resource is free */
+ init_completion(&fb_data->update_res_free);
+
+ fb_data->waiting_for_wb = true;
+
+ /* Leave spinlock while waiting for WB to complete */
+ mutex_unlock(&fb_data->queue_mutex);
+ wait_for_completion(&fb_data->update_res_free);
+ mutex_lock(&fb_data->queue_mutex);
+ }
+
+ /*
+ * Dithering Processing (Version 1.0 - for i.MX508 and i.MX6SL)
+ */
+ if (upd_data_list->update_desc->upd_data.flags &
+ EPDC_FLAG_USE_DITHERING_Y1) {
+
+ err_dist = kzalloc((fb_data->info.var.xres_virtual + 3) * 3
+ * sizeof(int), GFP_KERNEL);
+
+ /* Dithering Y8 -> Y1 */
+ do_dithering_processing_Y1_v1_0(
+ (uint8_t *)(upd_data_list->virt_addr +
+ upd_data_list->update_desc->epdc_offs),
+ upd_data_list->phys_addr +
+ upd_data_list->update_desc->epdc_offs,
+ &adj_update_region,
+ (fb_data->rev < 20) ?
+ ALIGN(adj_update_region.width, 8) :
+ adj_update_region.width,
+ err_dist);
+
+ kfree(err_dist);
+ } else if (upd_data_list->update_desc->upd_data.flags &
+ EPDC_FLAG_USE_DITHERING_Y4) {
+
+ err_dist = kzalloc((fb_data->info.var.xres_virtual + 3) * 3
+ * sizeof(int), GFP_KERNEL);
+
+ /* Dithering Y8 -> Y1 */
+ do_dithering_processing_Y4_v1_0(
+ (uint8_t *)(upd_data_list->virt_addr +
+ upd_data_list->update_desc->epdc_offs),
+ upd_data_list->phys_addr +
+ upd_data_list->update_desc->epdc_offs,
+ &adj_update_region,
+ (fb_data->rev < 20) ?
+ ALIGN(adj_update_region.width, 8) :
+ adj_update_region.width,
+ err_dist);
+
+ kfree(err_dist);
+ }
+
+ /*
+ * If there are no LUTs available,
+ * then we must wait for the resource to become free.
+ * The IST will signal this event.
+ */
+ if (!epdc_any_luts_available()) {
+ dev_dbg(fb_data->dev, "no luts available!\n");
+
+ /* Initialize event signalling an update resource is free */
+ init_completion(&fb_data->update_res_free);
+
+ fb_data->waiting_for_lut = true;
+
+ /* Leave spinlock while waiting for LUT to free up */
+ mutex_unlock(&fb_data->queue_mutex);
+ wait_for_completion(&fb_data->update_res_free);
+ mutex_lock(&fb_data->queue_mutex);
+ }
+
+ ret = epdc_choose_next_lut(fb_data->rev, &upd_data_list->lut_num);
+ /*
+ * If LUT15 is in use (for pre-EPDC v2.0 hardware):
+ * - Wait for LUT15 to complete is if TCE underrun prevent is enabled
+ * - If we go ahead with update, sync update submission with EOF
+ */
+ if (ret && fb_data->tce_prevent && (fb_data->rev < 20)) {
+ dev_dbg(fb_data->dev, "Waiting for LUT15\n");
+
+ /* Initialize event signalling that lut15 is free */
+ init_completion(&fb_data->lut15_free);
+
+ fb_data->waiting_for_lut15 = true;
+
+ /* Leave spinlock while waiting for LUT to free up */
+ mutex_unlock(&fb_data->queue_mutex);
+ wait_for_completion(&fb_data->lut15_free);
+ mutex_lock(&fb_data->queue_mutex);
+
+ epdc_choose_next_lut(fb_data->rev, &upd_data_list->lut_num);
+ } else if (ret && (fb_data->rev < 20)) {
+ /* Synchronize update submission time to reduce
+ chances of TCE underrun */
+ init_completion(&fb_data->eof_event);
+
+ epdc_eof_intr(true);
+
+ /* Leave spinlock while waiting for EOF event */
+ mutex_unlock(&fb_data->queue_mutex);
+ ret = wait_for_completion_timeout(&fb_data->eof_event,
+ msecs_to_jiffies(1000));
+ if (!ret) {
+ dev_err(fb_data->dev, "Missed EOF event!\n");
+ epdc_eof_intr(false);
+ }
+ udelay(fb_data->eof_sync_period);
+ mutex_lock(&fb_data->queue_mutex);
+
+ }
+
+ /* LUTs are available, so we get one here */
+ fb_data->cur_update = upd_data_list;
+
+ /* Reset mask for LUTS that have completed during WB processing */
+ fb_data->luts_complete_wb = 0;
+
+ /* If we are just testing for collision, we don't assign a LUT,
+ * so we don't need to update LUT-related resources. */
+ if (!(upd_data_list->update_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION)) {
+ /* Associate LUT with update marker */
+ list_for_each_entry_safe(next_marker, temp_marker,
+ &upd_data_list->update_desc->upd_marker_list, upd_list)
+ next_marker->lut_num = fb_data->cur_update->lut_num;
+
+ /* Mark LUT with order */
+ fb_data->lut_update_order[upd_data_list->lut_num] =
+ upd_data_list->update_desc->update_order;
+
+ epdc_lut_complete_intr(fb_data->rev, upd_data_list->lut_num,
+ true);
+ }
+
+ /* Enable Collision and WB complete IRQs */
+ epdc_working_buf_intr(true);
+
+ /* Program EPDC update to process buffer */
+ if (upd_data_list->update_desc->upd_data.temp != TEMP_USE_AMBIENT) {
+ temp_index = mxc_epdc_fb_get_temp_index(fb_data,
+ upd_data_list->update_desc->upd_data.temp);
+ epdc_set_temp(temp_index);
+ } else
+ epdc_set_temp(fb_data->temp_index);
+ epdc_set_update_addr(update_addr);
+ epdc_set_update_coord(adj_update_region.left, adj_update_region.top);
+ epdc_set_update_dimensions(adj_update_region.width,
+ adj_update_region.height);
+ if (fb_data->rev > 20)
+ epdc_set_update_stride(upd_data_list->update_desc->epdc_stride);
+ if (fb_data->wv_modes_update &&
+ (upd_data_list->update_desc->upd_data.waveform_mode
+ == WAVEFORM_MODE_AUTO)) {
+ epdc_set_update_waveform(&fb_data->wv_modes);
+ fb_data->wv_modes_update = false;
+ }
+
+ epdc_submit_update(upd_data_list->lut_num,
+ upd_data_list->update_desc->upd_data.waveform_mode,
+ upd_data_list->update_desc->upd_data.update_mode,
+ (upd_data_list->update_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION) ? true : false,
+ false, 0);
+
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+}
+
+static int mxc_epdc_fb_send_single_update(struct mxcfb_update_data *upd_data,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+ struct update_data_list *upd_data_list = NULL;
+ struct mxcfb_rect *screen_upd_region; /* Region on screen to update */
+ int temp_index;
+ int ret;
+ struct update_desc_list *upd_desc;
+ struct update_marker_data *marker_data, *next_marker, *temp_marker;
+
+ /* Has EPDC HW been initialized? */
+ if (!fb_data->hw_ready) {
+ /* Throw message if we are not mid-initialization */
+ if (!fb_data->hw_initializing)
+ dev_err(fb_data->dev, "Display HW not properly"
+ "initialized. Aborting update.\n");
+ return -EPERM;
+ }
+
+ /* Check validity of update params */
+ if ((upd_data->update_mode != UPDATE_MODE_PARTIAL) &&
+ (upd_data->update_mode != UPDATE_MODE_FULL)) {
+ dev_err(fb_data->dev,
+ "Update mode 0x%x is invalid. Aborting update.\n",
+ upd_data->update_mode);
+ return -EINVAL;
+ }
+ if ((upd_data->waveform_mode > 255) &&
+ (upd_data->waveform_mode != WAVEFORM_MODE_AUTO)) {
+ dev_err(fb_data->dev,
+ "Update waveform mode 0x%x is invalid."
+ " Aborting update.\n",
+ upd_data->waveform_mode);
+ return -EINVAL;
+ }
+
+ mutex_lock(&fb_data->queue_mutex);
+ if ((upd_data->update_region.left + upd_data->update_region.width > fb_data->epdc_fb_var.xres) ||
+ (upd_data->update_region.top + upd_data->update_region.height > fb_data->epdc_fb_var.yres)) {
+ mutex_unlock(&fb_data->queue_mutex);
+ dev_err(fb_data->dev,
+ "Update region is outside bounds of framebuffer."
+ "Aborting update.\n");
+ return -EINVAL;
+ }
+ mutex_unlock(&fb_data->queue_mutex);
+
+ if (upd_data->flags & EPDC_FLAG_USE_ALT_BUFFER) {
+ if ((upd_data->update_region.width !=
+ upd_data->alt_buffer_data.alt_update_region.width) ||
+ (upd_data->update_region.height !=
+ upd_data->alt_buffer_data.alt_update_region.height)) {
+ dev_err(fb_data->dev,
+ "Alternate update region dimensions must "
+ "match screen update region dimensions.\n");
+ return -EINVAL;
+ }
+ /* Validate physical address parameter */
+ if ((upd_data->alt_buffer_data.phys_addr <
+ fb_data->info.fix.smem_start) ||
+ (upd_data->alt_buffer_data.phys_addr >
+ fb_data->info.fix.smem_start + fb_data->map_size)) {
+ dev_err(fb_data->dev,
+ "Invalid physical address for alternate "
+ "buffer. Aborting update...\n");
+ return -EINVAL;
+ }
+ }
+
+ mutex_lock(&fb_data->queue_mutex);
+
+ /*
+ * If we are waiting to go into suspend, or the FB is blanked,
+ * we do not accept new updates
+ */
+ if ((fb_data->waiting_for_idle) ||
+ (fb_data->blank != FB_BLANK_UNBLANK)) {
+ dev_dbg(fb_data->dev, "EPDC not active."
+ "Update request abort.\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return -EPERM;
+ }
+
+ if (fb_data->upd_scheme == UPDATE_SCHEME_SNAPSHOT) {
+ int count = 0;
+ struct update_data_list *plist;
+
+ /*
+ * If next update is a FULL mode update, then we must
+ * ensure that all pending & active updates are complete
+ * before submitting the update. Otherwise, the FULL
+ * mode update may cause an endless collision loop with
+ * other updates. Block here until updates are flushed.
+ */
+ if (upd_data->update_mode == UPDATE_MODE_FULL) {
+ mutex_unlock(&fb_data->queue_mutex);
+ mxc_epdc_fb_flush_updates(fb_data);
+ mutex_lock(&fb_data->queue_mutex);
+ }
+
+ /* Count buffers in free buffer list */
+ list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
+ count++;
+
+ /* Use count to determine if we have enough
+ * free buffers to handle this update request */
+ if (count + fb_data->max_num_buffers
+ <= fb_data->max_num_updates) {
+ dev_err(fb_data->dev,
+ "No free intermediate buffers available.\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return -ENOMEM;
+ }
+
+ /* Grab first available buffer and delete from the free list */
+ upd_data_list =
+ list_entry(fb_data->upd_buf_free_list.next,
+ struct update_data_list, list);
+
+ list_del_init(&upd_data_list->list);
+ }
+
+ /*
+ * Create new update data structure, fill it with new update
+ * data and add it to the list of pending updates
+ */
+ upd_desc = kzalloc(sizeof(struct update_desc_list), GFP_KERNEL);
+ if (!upd_desc) {
+ dev_err(fb_data->dev,
+ "Insufficient system memory for update! Aborting.\n");
+ if (fb_data->upd_scheme == UPDATE_SCHEME_SNAPSHOT) {
+ list_add(&upd_data_list->list,
+ &fb_data->upd_buf_free_list);
+ }
+ mutex_unlock(&fb_data->queue_mutex);
+ return -EPERM;
+ }
+ /* Initialize per-update marker list */
+ INIT_LIST_HEAD(&upd_desc->upd_marker_list);
+ upd_desc->upd_data = *upd_data;
+ upd_desc->update_order = fb_data->order_cnt++;
+ list_add_tail(&upd_desc->list, &fb_data->upd_pending_list);
+
+ /* If marker specified, associate it with a completion */
+ if (upd_data->update_marker != 0) {
+ /* Allocate new update marker and set it up */
+ marker_data = kzalloc(sizeof(struct update_marker_data),
+ GFP_KERNEL);
+ if (!marker_data) {
+ dev_err(fb_data->dev, "No memory for marker!\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return -ENOMEM;
+ }
+ list_add_tail(&marker_data->upd_list,
+ &upd_desc->upd_marker_list);
+ marker_data->update_marker = upd_data->update_marker;
+ if (upd_desc->upd_data.flags & EPDC_FLAG_TEST_COLLISION)
+ marker_data->lut_num = DRY_RUN_NO_LUT;
+ else
+ marker_data->lut_num = INVALID_LUT;
+ init_completion(&marker_data->update_completion);
+ /* Add marker to master marker list */
+ list_add_tail(&marker_data->full_list,
+ &fb_data->full_marker_list);
+ }
+
+ if (fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT) {
+ /* Queued update scheme processing */
+
+ mutex_unlock(&fb_data->queue_mutex);
+
+ /* Signal workqueue to handle new update */
+ queue_work(fb_data->epdc_submit_workqueue,
+ &fb_data->epdc_submit_work);
+
+ return 0;
+ }
+
+ /* Snapshot update scheme processing */
+
+ /* Set descriptor for current update, delete from pending list */
+ upd_data_list->update_desc = upd_desc;
+ list_del_init(&upd_desc->list);
+
+ mutex_unlock(&fb_data->queue_mutex);
+
+ /*
+ * Hold on to original screen update region, which we
+ * will ultimately use when telling EPDC where to update on panel
+ */
+ screen_upd_region = &upd_desc->upd_data.update_region;
+
+ /* Select from PxP output buffers */
+ upd_data_list->phys_addr =
+ fb_data->phys_addr_updbuf[fb_data->upd_buffer_num];
+ upd_data_list->virt_addr =
+ fb_data->virt_addr_updbuf[fb_data->upd_buffer_num];
+ fb_data->upd_buffer_num++;
+ if (fb_data->upd_buffer_num > fb_data->max_num_buffers-1)
+ fb_data->upd_buffer_num = 0;
+
+ ret = epdc_process_update(upd_data_list, fb_data);
+ if (ret) {
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ /* Pass selected waveform mode back to user */
+ upd_data->waveform_mode = upd_desc->upd_data.waveform_mode;
+
+ /* Get rotation-adjusted coordinates */
+ adjust_coordinates(fb_data->epdc_fb_var.xres,
+ fb_data->epdc_fb_var.yres, fb_data->epdc_fb_var.rotate,
+ &upd_desc->upd_data.update_region, NULL);
+
+ /* Grab lock for queue manipulation and update submission */
+ mutex_lock(&fb_data->queue_mutex);
+
+ /*
+ * Is the working buffer idle?
+ * If either the working buffer is busy, or there are no LUTs available,
+ * then we return and let the ISR handle the update later
+ */
+ if ((fb_data->cur_update != NULL) || !epdc_any_luts_available()) {
+ /* Add processed Y buffer to update list */
+ list_add_tail(&upd_data_list->list, &fb_data->upd_buf_queue);
+
+ /* Return and allow the update to be submitted by the ISR. */
+ mutex_unlock(&fb_data->queue_mutex);
+ return 0;
+ }
+
+ /* LUTs are available, so we get one here */
+ ret = epdc_choose_next_lut(fb_data->rev, &upd_data_list->lut_num);
+ if (ret && fb_data->tce_prevent && (fb_data->rev < 20)) {
+ dev_dbg(fb_data->dev, "Must wait for LUT15\n");
+ /* Add processed Y buffer to update list */
+ list_add_tail(&upd_data_list->list, &fb_data->upd_buf_queue);
+
+ /* Return and allow the update to be submitted by the ISR. */
+ mutex_unlock(&fb_data->queue_mutex);
+ return 0;
+ }
+
+ if (!(upd_data_list->update_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION)) {
+
+ /* Save current update */
+ fb_data->cur_update = upd_data_list;
+
+ /* Reset mask for LUTS that have completed during WB processing */
+ fb_data->luts_complete_wb = 0;
+
+ /* Associate LUT with update marker */
+ list_for_each_entry_safe(next_marker, temp_marker,
+ &upd_data_list->update_desc->upd_marker_list, upd_list)
+ next_marker->lut_num = upd_data_list->lut_num;
+
+ /* Mark LUT as containing new update */
+ fb_data->lut_update_order[upd_data_list->lut_num] =
+ upd_desc->update_order;
+
+ epdc_lut_complete_intr(fb_data->rev, upd_data_list->lut_num,
+ true);
+ }
+
+ /* Clear status and Enable LUT complete and WB complete IRQs */
+ epdc_working_buf_intr(true);
+
+ /* Program EPDC update to process buffer */
+ epdc_set_update_addr(upd_data_list->phys_addr + upd_desc->epdc_offs);
+ epdc_set_update_coord(screen_upd_region->left, screen_upd_region->top);
+ epdc_set_update_dimensions(screen_upd_region->width,
+ screen_upd_region->height);
+ if (fb_data->rev > 20)
+ epdc_set_update_stride(upd_desc->epdc_stride);
+ if (upd_desc->upd_data.temp != TEMP_USE_AMBIENT) {
+ temp_index = mxc_epdc_fb_get_temp_index(fb_data,
+ upd_desc->upd_data.temp);
+ epdc_set_temp(temp_index);
+ } else
+ epdc_set_temp(fb_data->temp_index);
+ if (fb_data->wv_modes_update &&
+ (upd_desc->upd_data.waveform_mode == WAVEFORM_MODE_AUTO)) {
+ epdc_set_update_waveform(&fb_data->wv_modes);
+ fb_data->wv_modes_update = false;
+ }
+
+ epdc_submit_update(upd_data_list->lut_num,
+ upd_desc->upd_data.waveform_mode,
+ upd_desc->upd_data.update_mode,
+ (upd_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION) ? true : false,
+ false, 0);
+
+ mutex_unlock(&fb_data->queue_mutex);
+ return 0;
+}
+
+int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ if (!fb_data->restrict_width) {
+ /* No width restriction, send entire update region */
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+ } else {
+ int ret;
+ __u32 width, left;
+ __u32 marker;
+ __u32 *region_width, *region_left;
+ u32 max_upd_width = EPDC_V2_MAX_UPDATE_WIDTH;
+
+ /* Further restrict max width due to pxp rotation
+ * alignment requirement
+ */
+ if (fb_data->epdc_fb_var.rotate != FB_ROTATE_UR)
+ max_upd_width -= EPDC_V2_ROTATION_ALIGNMENT;
+
+ /* Select split of width or height based on rotation */
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) ||
+ (fb_data->epdc_fb_var.rotate == FB_ROTATE_UD)) {
+ region_width = &upd_data->update_region.width;
+ region_left = &upd_data->update_region.left;
+ } else {
+ region_width = &upd_data->update_region.height;
+ region_left = &upd_data->update_region.top;
+ }
+
+ if (*region_width <= max_upd_width)
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+
+ width = *region_width;
+ left = *region_left;
+ marker = upd_data->update_marker;
+ upd_data->update_marker = 0;
+
+ do {
+ *region_width = max_upd_width;
+ *region_left = left;
+ ret = mxc_epdc_fb_send_single_update(upd_data, info);
+ if (ret)
+ return ret;
+ width -= max_upd_width;
+ left += max_upd_width;
+ } while (width > max_upd_width);
+
+ *region_width = width;
+ *region_left = left;
+ upd_data->update_marker = marker;
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+ }
+}
+EXPORT_SYMBOL(mxc_epdc_fb_send_update);
+
+int mxc_epdc_fb_wait_update_complete(struct mxcfb_update_marker_data *marker_data,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+ struct update_marker_data *next_marker;
+ struct update_marker_data *temp;
+ bool marker_found = false;
+ int ret = 0;
+
+ /* 0 is an invalid update_marker value */
+ if (marker_data->update_marker == 0)
+ return -EINVAL;
+
+ /*
+ * Find completion associated with update_marker requested.
+ * Note: If update completed already, marker will have been
+ * cleared, it won't be found, and function will just return.
+ */
+
+ /* Grab queue lock to protect access to marker list */
+ mutex_lock(&fb_data->queue_mutex);
+
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->full_marker_list, full_list) {
+ if (next_marker->update_marker == marker_data->update_marker) {
+ dev_dbg(fb_data->dev, "Waiting for marker %d\n",
+ marker_data->update_marker);
+ next_marker->waiting = true;
+ marker_found = true;
+ break;
+ }
+ }
+
+ mutex_unlock(&fb_data->queue_mutex);
+
+ /*
+ * If marker not found, it has either been signalled already
+ * or the update request failed. In either case, just return.
+ */
+ if (!marker_found)
+ return ret;
+
+ ret = wait_for_completion_timeout(&next_marker->update_completion,
+ msecs_to_jiffies(5000));
+ if (!ret) {
+ dev_err(fb_data->dev,
+ "Timed out waiting for update completion\n");
+ return -ETIMEDOUT;
+ }
+
+ marker_data->collision_test = next_marker->collision_test;
+
+ /* Free update marker object */
+ kfree(next_marker);
+
+ return ret;
+}
+EXPORT_SYMBOL(mxc_epdc_fb_wait_update_complete);
+
+int mxc_epdc_fb_set_pwrdown_delay(u32 pwrdown_delay,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ fb_data->pwrdown_delay = pwrdown_delay;
+
+ return 0;
+}
+EXPORT_SYMBOL(mxc_epdc_fb_set_pwrdown_delay);
+
+int mxc_epdc_get_pwrdown_delay(struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ return fb_data->pwrdown_delay;
+}
+EXPORT_SYMBOL(mxc_epdc_get_pwrdown_delay);
+
+static int mxc_epdc_fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int ret = -EINVAL;
+
+ switch (cmd) {
+ case MXCFB_SET_WAVEFORM_MODES:
+ {
+ struct mxcfb_waveform_modes modes;
+ if (!copy_from_user(&modes, argp, sizeof(modes))) {
+ mxc_epdc_fb_set_waveform_modes(&modes, info);
+ ret = 0;
+ }
+ break;
+ }
+ case MXCFB_SET_TEMPERATURE:
+ {
+ int temperature;
+ if (!get_user(temperature, (int32_t __user *) arg))
+ ret = mxc_epdc_fb_set_temperature(temperature,
+ info);
+ break;
+ }
+ case MXCFB_SET_AUTO_UPDATE_MODE:
+ {
+ u32 auto_mode = 0;
+ if (!get_user(auto_mode, (__u32 __user *) arg))
+ ret = mxc_epdc_fb_set_auto_update(auto_mode,
+ info);
+ break;
+ }
+ case MXCFB_SET_UPDATE_SCHEME:
+ {
+ u32 upd_scheme = 0;
+ if (!get_user(upd_scheme, (__u32 __user *) arg))
+ ret = mxc_epdc_fb_set_upd_scheme(upd_scheme,
+ info);
+ break;
+ }
+ case MXCFB_SEND_UPDATE:
+ {
+ struct mxcfb_update_data upd_data;
+
+ if (mutex_lock_interruptible(&hard_lock) < 0)
+ return -ERESTARTSYS;
+
+ if (!copy_from_user(&upd_data, argp,
+ sizeof(upd_data))) {
+ ret = mxc_epdc_fb_send_update(&upd_data, info);
+ if (ret == 0 && copy_to_user(argp, &upd_data,
+ sizeof(upd_data)))
+ ret = -EFAULT;
+ } else {
+ ret = -EFAULT;
+ }
+
+ mutex_unlock(&hard_lock);
+
+ break;
+ }
+ case MXCFB_WAIT_FOR_UPDATE_COMPLETE:
+ {
+ struct mxcfb_update_marker_data upd_marker_data;
+ if (!copy_from_user(&upd_marker_data, argp,
+ sizeof(upd_marker_data))) {
+ ret = mxc_epdc_fb_wait_update_complete(
+ &upd_marker_data, info);
+ if (copy_to_user(argp, &upd_marker_data,
+ sizeof(upd_marker_data)))
+ ret = -EFAULT;
+ } else {
+ ret = -EFAULT;
+ }
+
+ break;
+ }
+
+ case MXCFB_SET_PWRDOWN_DELAY:
+ {
+ int delay = 0;
+ if (!get_user(delay, (__u32 __user *) arg))
+ ret =
+ mxc_epdc_fb_set_pwrdown_delay(delay, info);
+ break;
+ }
+
+ case MXCFB_GET_PWRDOWN_DELAY:
+ {
+ int pwrdown_delay = mxc_epdc_get_pwrdown_delay(info);
+ if (put_user(pwrdown_delay,
+ (int __user *)argp))
+ ret = -EFAULT;
+ ret = 0;
+ break;
+ }
+
+ case MXCFB_GET_WORK_BUFFER:
+ {
+ /* copy the epdc working buffer to the user space */
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+ flush_cache_all();
+ outer_flush_range(fb_data->working_buffer_phys,
+ fb_data->working_buffer_phys +
+ fb_data->working_buffer_size);
+ if (copy_to_user((void __user *)arg,
+ (const void *) fb_data->working_buffer_virt,
+ fb_data->working_buffer_size))
+ ret = -EFAULT;
+ else
+ ret = 0;
+ flush_cache_all();
+ outer_flush_range(fb_data->working_buffer_phys,
+ fb_data->working_buffer_phys +
+ fb_data->working_buffer_size);
+ break;
+ }
+
+ case MXCFB_DISABLE_EPDC_ACCESS:
+ {
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+ mxc_epdc_fb_flush_updates(fb_data);
+ /* disable handling any user update request */
+ mutex_lock(&hard_lock);
+ ret = 0;
+ break;
+ }
+
+ case MXCFB_ENABLE_EPDC_ACCESS:
+ {
+ /* enable user update handling again */
+ mutex_unlock(&hard_lock);
+ ret = 0;
+ break;
+ }
+
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void mxc_epdc_fb_update_pages(struct mxc_epdc_fb_data *fb_data,
+ u16 y1, u16 y2)
+{
+ struct mxcfb_update_data update;
+
+ /* Do partial screen update, Update full horizontal lines */
+ update.update_region.left = 0;
+ update.update_region.width = fb_data->epdc_fb_var.xres;
+ update.update_region.top = y1;
+ update.update_region.height = y2 - y1;
+ update.waveform_mode = WAVEFORM_MODE_AUTO;
+ update.update_mode = UPDATE_MODE_FULL;
+ update.update_marker = 0;
+ update.temp = TEMP_USE_AMBIENT;
+ update.flags = 0;
+
+ mxc_epdc_fb_send_update(&update, &fb_data->info);
+}
+
+/* this is called back from the deferred io workqueue */
+static void mxc_epdc_fb_deferred_io(struct fb_info *info,
+ struct list_head *pagelist)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ struct page *page;
+ unsigned long beg, end;
+ int y1, y2, miny, maxy;
+
+ if (fb_data->auto_mode != AUTO_UPDATE_MODE_AUTOMATIC_MODE)
+ return;
+
+ miny = INT_MAX;
+ maxy = 0;
+ list_for_each_entry(page, pagelist, lru) {
+ beg = page->index << PAGE_SHIFT;
+ end = beg + PAGE_SIZE - 1;
+ y1 = beg / info->fix.line_length;
+ y2 = end / info->fix.line_length;
+ if (y2 >= fb_data->epdc_fb_var.yres)
+ y2 = fb_data->epdc_fb_var.yres - 1;
+ if (miny > y1)
+ miny = y1;
+ if (maxy < y2)
+ maxy = y2;
+ }
+
+ mxc_epdc_fb_update_pages(fb_data, miny, maxy);
+}
+
+void mxc_epdc_fb_flush_updates(struct mxc_epdc_fb_data *fb_data)
+{
+ int ret;
+
+ if (fb_data->in_init)
+ return;
+
+ /* Grab queue lock to prevent any new updates from being submitted */
+ mutex_lock(&fb_data->queue_mutex);
+
+ /*
+ * 3 places to check for updates that are active or pending:
+ * 1) Updates in the pending list
+ * 2) Update buffers in use (e.g., PxP processing)
+ * 3) Active updates to panel - We can key off of EPDC
+ * power state to know if we have active updates.
+ */
+ if (!list_empty(&fb_data->upd_pending_list) ||
+ !is_free_list_full(fb_data) ||
+ (fb_data->updates_active == true)) {
+ /* Initialize event signalling updates are done */
+ init_completion(&fb_data->updates_done);
+ fb_data->waiting_for_idle = true;
+
+ mutex_unlock(&fb_data->queue_mutex);
+ /* Wait for any currently active updates to complete */
+ ret = wait_for_completion_timeout(&fb_data->updates_done,
+ msecs_to_jiffies(8000));
+ if (!ret)
+ dev_err(fb_data->dev,
+ "Flush updates timeout! ret = 0x%x\n", ret);
+
+ mutex_lock(&fb_data->queue_mutex);
+ fb_data->waiting_for_idle = false;
+ }
+
+ mutex_unlock(&fb_data->queue_mutex);
+}
+
+static int mxc_epdc_fb_blank(int blank, struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ int ret;
+
+ dev_dbg(fb_data->dev, "blank = %d\n", blank);
+
+ if (fb_data->blank == blank)
+ return 0;
+
+ fb_data->blank = blank;
+
+ switch (blank) {
+ case FB_BLANK_POWERDOWN:
+ mxc_epdc_fb_flush_updates(fb_data);
+ /* Wait for powerdown */
+ mutex_lock(&fb_data->power_mutex);
+ if ((fb_data->power_state == POWER_STATE_ON) &&
+ (fb_data->pwrdown_delay == FB_POWERDOWN_DISABLE)) {
+
+ /* Powerdown disabled, so we disable EPDC manually */
+ int count = 0;
+ int sleep_ms = 10;
+
+ mutex_unlock(&fb_data->power_mutex);
+
+ /* If any active updates, wait for them to complete */
+ while (fb_data->updates_active) {
+ /* Timeout after 1 sec */
+ if ((count * sleep_ms) > 1000)
+ break;
+ msleep(sleep_ms);
+ count++;
+ }
+
+ fb_data->powering_down = true;
+ epdc_powerdown(fb_data);
+ } else if (fb_data->power_state != POWER_STATE_OFF) {
+ fb_data->wait_for_powerdown = true;
+ init_completion(&fb_data->powerdown_compl);
+ mutex_unlock(&fb_data->power_mutex);
+ ret = wait_for_completion_timeout(&fb_data->powerdown_compl,
+ msecs_to_jiffies(5000));
+ if (!ret) {
+ dev_err(fb_data->dev,
+ "No powerdown received!\n");
+ return -ETIMEDOUT;
+ }
+ } else
+ mutex_unlock(&fb_data->power_mutex);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ mxc_epdc_fb_flush_updates(fb_data);
+ break;
+ }
+ return 0;
+}
+
+static int mxc_epdc_fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ u_int y_bottom;
+
+ dev_dbg(info->device, "%s: var->yoffset %d, info->var.yoffset %d\n",
+ __func__, var->yoffset, info->var.yoffset);
+ /* check if var is valid; also, xpan is not supported */
+ if (!var || (var->xoffset != info->var.xoffset) ||
+ (var->yoffset + var->yres > var->yres_virtual)) {
+ dev_dbg(info->device, "x panning not supported\n");
+ return -EINVAL;
+ }
+
+ if ((fb_data->epdc_fb_var.xoffset == var->xoffset) &&
+ (fb_data->epdc_fb_var.yoffset == var->yoffset))
+ return 0; /* No change, do nothing */
+
+ y_bottom = var->yoffset;
+
+ if (!(var->vmode & FB_VMODE_YWRAP))
+ y_bottom += var->yres;
+
+ if (y_bottom > info->var.yres_virtual)
+ return -EINVAL;
+
+ mutex_lock(&fb_data->queue_mutex);
+
+ fb_data->fb_offset = (var->yoffset * var->xres_virtual + var->xoffset)
+ * (var->bits_per_pixel) / 8;
+
+ fb_data->epdc_fb_var.xoffset = var->xoffset;
+ fb_data->epdc_fb_var.yoffset = var->yoffset;
+
+ if (var->vmode & FB_VMODE_YWRAP)
+ info->var.vmode |= FB_VMODE_YWRAP;
+ else
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+
+ mutex_unlock(&fb_data->queue_mutex);
+
+ return 0;
+}
+
+static struct fb_ops mxc_epdc_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = mxc_epdc_fb_check_var,
+ .fb_set_par = mxc_epdc_fb_set_par,
+ .fb_setcmap = mxc_epdc_fb_setcmap,
+ .fb_setcolreg = mxc_epdc_fb_setcolreg,
+ .fb_pan_display = mxc_epdc_fb_pan_display,
+ .fb_ioctl = mxc_epdc_fb_ioctl,
+ .fb_mmap = mxc_epdc_fb_mmap,
+ .fb_blank = mxc_epdc_fb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static struct fb_deferred_io mxc_epdc_fb_defio = {
+ .delay = HZ,
+ .deferred_io = mxc_epdc_fb_deferred_io,
+};
+
+static void epdc_done_work_func(struct work_struct *work)
+{
+ struct mxc_epdc_fb_data *fb_data =
+ container_of(work, struct mxc_epdc_fb_data,
+ epdc_done_work.work);
+ epdc_powerdown(fb_data);
+}
+
+static bool is_free_list_full(struct mxc_epdc_fb_data *fb_data)
+{
+ int count = 0;
+ struct update_data_list *plist;
+
+ /* Count buffers in free buffer list */
+ list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
+ count++;
+
+ /* Check to see if all buffers are in this list */
+ if (count == fb_data->max_num_updates)
+ return true;
+ else
+ return false;
+}
+
+static irqreturn_t mxc_epdc_irq_handler(int irq, void *dev_id)
+{
+ struct mxc_epdc_fb_data *fb_data = dev_id;
+ u32 ints_fired, luts1_ints_fired, luts2_ints_fired;
+
+ /*
+ * If we just completed one-time panel init, bypass
+ * queue handling, clear interrupt and return
+ */
+ if (fb_data->in_init) {
+ if (epdc_is_working_buffer_complete()) {
+ epdc_working_buf_intr(false);
+ epdc_clear_working_buf_irq();
+ dev_dbg(fb_data->dev, "Cleared WB for init update\n");
+ }
+
+ if (epdc_is_lut_complete(fb_data->rev, 0)) {
+ epdc_lut_complete_intr(fb_data->rev, 0, false);
+ epdc_clear_lut_complete_irq(fb_data->rev, 0);
+ fb_data->in_init = false;
+ dev_dbg(fb_data->dev, "Cleared LUT complete for init update\n");
+ }
+
+ return IRQ_HANDLED;
+ }
+
+ ints_fired = __raw_readl(EPDC_IRQ_MASK) & __raw_readl(EPDC_IRQ);
+ if (fb_data->rev < 20) {
+ luts1_ints_fired = 0;
+ luts2_ints_fired = 0;
+ } else {
+ luts1_ints_fired = __raw_readl(EPDC_IRQ_MASK1) & __raw_readl(EPDC_IRQ1);
+ luts2_ints_fired = __raw_readl(EPDC_IRQ_MASK2) & __raw_readl(EPDC_IRQ2);
+ }
+
+ if (!(ints_fired || luts1_ints_fired || luts2_ints_fired))
+ return IRQ_HANDLED;
+
+ if (__raw_readl(EPDC_IRQ) & EPDC_IRQ_TCE_UNDERRUN_IRQ) {
+ dev_err(fb_data->dev,
+ "TCE underrun! Will continue to update panel\n");
+ /* Clear TCE underrun IRQ */
+ __raw_writel(EPDC_IRQ_TCE_UNDERRUN_IRQ, EPDC_IRQ_CLEAR);
+ }
+
+ /* Check if we are waiting on EOF to sync a new update submission */
+ if (epdc_signal_eof()) {
+ epdc_eof_intr(false);
+ epdc_clear_eof_irq();
+ complete(&fb_data->eof_event);
+ }
+
+ /*
+ * Workaround for EPDC v2.0/v2.1 errata: Must read collision status
+ * before clearing IRQ, or else collision status for bits 16:63
+ * will be automatically cleared. So we read it here, and there is
+ * no conflict with using it in epdc_intr_work_func since the
+ * working buffer processing flow is strictly sequential (i.e.,
+ * only one WB processing done at a time, so the data grabbed
+ * here should be up-to-date and accurate when the WB processing
+ * completes. Also, note that there is no impact to other versions
+ * of EPDC by reading LUT status here.
+ */
+ if (fb_data->cur_update != NULL)
+ fb_data->epdc_colliding_luts = epdc_get_colliding_luts(fb_data->rev);
+
+ /* Clear the interrupt mask for any interrupts signalled */
+ __raw_writel(ints_fired, EPDC_IRQ_MASK_CLEAR);
+ __raw_writel(luts1_ints_fired, EPDC_IRQ_MASK1_CLEAR);
+ __raw_writel(luts2_ints_fired, EPDC_IRQ_MASK2_CLEAR);
+
+ dev_dbg(fb_data->dev, "EPDC interrupts fired = 0x%x, "
+ "LUTS1 fired = 0x%x, LUTS2 fired = 0x%x\n",
+ ints_fired, luts1_ints_fired, luts2_ints_fired);
+
+ queue_work(fb_data->epdc_intr_workqueue,
+ &fb_data->epdc_intr_work);
+
+ return IRQ_HANDLED;
+}
+
+static void epdc_intr_work_func(struct work_struct *work)
+{
+ struct mxc_epdc_fb_data *fb_data =
+ container_of(work, struct mxc_epdc_fb_data, epdc_intr_work);
+ struct update_data_list *collision_update;
+ struct mxcfb_rect *next_upd_region;
+ struct update_marker_data *next_marker;
+ struct update_marker_data *temp;
+ int temp_index;
+ u64 temp_mask;
+ u32 lut;
+ bool ignore_collision = false;
+ int i;
+ bool wb_lut_done = false;
+ bool free_update = true;
+ int next_lut, epdc_next_lut_15;
+ u32 epdc_luts_active, epdc_wb_busy, epdc_luts_avail, epdc_lut_cancelled;
+ u32 epdc_collision;
+ u64 epdc_irq_stat;
+ bool epdc_waiting_on_wb;
+ u32 coll_coord, coll_size;
+ struct mxcfb_rect coll_region;
+
+ /* Protect access to buffer queues and to update HW */
+ mutex_lock(&fb_data->queue_mutex);
+
+ /* Capture EPDC status one time to limit exposure to race conditions */
+ epdc_luts_active = epdc_any_luts_active(fb_data->rev);
+ epdc_wb_busy = epdc_is_working_buffer_busy();
+ epdc_lut_cancelled = epdc_is_lut_cancelled();
+ epdc_luts_avail = epdc_any_luts_available();
+ epdc_collision = epdc_is_collision();
+ if (fb_data->rev < 20)
+ epdc_irq_stat = __raw_readl(EPDC_IRQ);
+ else
+ epdc_irq_stat = (u64)__raw_readl(EPDC_IRQ1) |
+ ((u64)__raw_readl(EPDC_IRQ2) << 32);
+ epdc_waiting_on_wb = (fb_data->cur_update != NULL) ? true : false;
+
+ /* Free any LUTs that have completed */
+ for (i = 0; i < fb_data->num_luts; i++) {
+ if ((epdc_irq_stat & (1ULL << i)) == 0)
+ continue;
+
+ dev_dbg(fb_data->dev, "LUT %d completed\n", i);
+
+ /* Disable IRQ for completed LUT */
+ epdc_lut_complete_intr(fb_data->rev, i, false);
+
+ /*
+ * Go through all updates in the collision list and
+ * unmask any updates that were colliding with
+ * the completed LUT.
+ */
+ list_for_each_entry(collision_update,
+ &fb_data->upd_buf_collision_list, list) {
+ collision_update->collision_mask =
+ collision_update->collision_mask & ~(1 << i);
+ }
+
+ epdc_clear_lut_complete_irq(fb_data->rev, i);
+
+ fb_data->luts_complete_wb |= 1ULL << i;
+
+ fb_data->lut_update_order[i] = 0;
+
+ /* Signal completion if submit workqueue needs a LUT */
+ if (fb_data->waiting_for_lut) {
+ complete(&fb_data->update_res_free);
+ fb_data->waiting_for_lut = false;
+ }
+
+ /* Signal completion if LUT15 free and is needed */
+ if (fb_data->waiting_for_lut15 && (i == 15)) {
+ complete(&fb_data->lut15_free);
+ fb_data->waiting_for_lut15 = false;
+ }
+
+ /* Detect race condition where WB and its LUT complete
+ (i.e. full update completes) in one swoop */
+ if (epdc_waiting_on_wb &&
+ (i == fb_data->cur_update->lut_num))
+ wb_lut_done = true;
+
+ /* Signal completion if anyone waiting on this LUT */
+ if (!wb_lut_done)
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->full_marker_list,
+ full_list) {
+ if (next_marker->lut_num != i)
+ continue;
+
+ /* Found marker to signal - remove from list */
+ list_del_init(&next_marker->full_list);
+
+ /* Signal completion of update */
+ dev_dbg(fb_data->dev, "Signaling marker %d\n",
+ next_marker->update_marker);
+ if (next_marker->waiting)
+ complete(&next_marker->update_completion);
+ else
+ kfree(next_marker);
+ }
+ }
+
+ /* Check to see if all updates have completed */
+ if (list_empty(&fb_data->upd_pending_list) &&
+ is_free_list_full(fb_data) &&
+ !epdc_waiting_on_wb &&
+ !epdc_luts_active) {
+
+ fb_data->updates_active = false;
+
+ if (fb_data->pwrdown_delay != FB_POWERDOWN_DISABLE) {
+ /*
+ * Set variable to prevent overlapping
+ * enable/disable requests
+ */
+ fb_data->powering_down = true;
+
+ /* Schedule task to disable EPDC HW until next update */
+ schedule_delayed_work(&fb_data->epdc_done_work,
+ msecs_to_jiffies(fb_data->pwrdown_delay));
+
+ /* Reset counter to reduce chance of overflow */
+ fb_data->order_cnt = 0;
+ }
+
+ if (fb_data->waiting_for_idle)
+ complete(&fb_data->updates_done);
+ }
+
+ /* Is Working Buffer busy? */
+ if (epdc_wb_busy) {
+ /* Can't submit another update until WB is done */
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ /*
+ * Were we waiting on working buffer?
+ * If so, update queues and check for collisions
+ */
+ if (epdc_waiting_on_wb) {
+ dev_dbg(fb_data->dev, "\nWorking buffer completed\n");
+
+ /* Signal completion if submit workqueue was waiting on WB */
+ if (fb_data->waiting_for_wb) {
+ complete(&fb_data->update_res_free);
+ fb_data->waiting_for_wb = false;
+ }
+
+ if (fb_data->cur_update->update_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION) {
+ /* This was a dry run to test for collision */
+
+ /* Signal marker */
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->full_marker_list,
+ full_list) {
+ if (next_marker->lut_num != DRY_RUN_NO_LUT)
+ continue;
+
+ if (epdc_collision)
+ next_marker->collision_test = true;
+ else
+ next_marker->collision_test = false;
+
+ dev_dbg(fb_data->dev,
+ "In IRQ, collision_test = %d\n",
+ next_marker->collision_test);
+
+ /* Found marker to signal - remove from list */
+ list_del_init(&next_marker->full_list);
+
+ /* Signal completion of update */
+ dev_dbg(fb_data->dev, "Signaling marker "
+ "for dry-run - %d\n",
+ next_marker->update_marker);
+ complete(&next_marker->update_completion);
+ }
+ } else if (epdc_lut_cancelled && !epdc_collision) {
+ /*
+ * Note: The update may be cancelled (void) if all
+ * pixels collided. In that case we handle it as a
+ * collision, not a cancel.
+ */
+
+ /* Clear LUT status (might be set if no AUTOWV used) */
+
+ /*
+ * Disable and clear IRQ for the LUT used.
+ * Even though LUT is cancelled in HW, the LUT
+ * complete bit may be set if AUTOWV not used.
+ */
+ epdc_lut_complete_intr(fb_data->rev,
+ fb_data->cur_update->lut_num, false);
+ epdc_clear_lut_complete_irq(fb_data->rev,
+ fb_data->cur_update->lut_num);
+
+ fb_data->lut_update_order[fb_data->cur_update->lut_num] = 0;
+
+ /* Signal completion if submit workqueue needs a LUT */
+ if (fb_data->waiting_for_lut) {
+ complete(&fb_data->update_res_free);
+ fb_data->waiting_for_lut = false;
+ }
+
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->cur_update->update_desc->upd_marker_list,
+ upd_list) {
+
+ /* Del from per-update & full list */
+ list_del_init(&next_marker->upd_list);
+ list_del_init(&next_marker->full_list);
+
+ /* Signal completion of update */
+ dev_dbg(fb_data->dev,
+ "Signaling marker (cancelled) %d\n",
+ next_marker->update_marker);
+ if (next_marker->waiting)
+ complete(&next_marker->update_completion);
+ else
+ kfree(next_marker);
+ }
+ } else if (epdc_collision) {
+ /* Real update (no dry-run), collision occurred */
+
+ /* Check list of colliding LUTs, and add to our collision mask */
+ fb_data->cur_update->collision_mask =
+ fb_data->epdc_colliding_luts;
+
+ /* Clear collisions that completed since WB began */
+ fb_data->cur_update->collision_mask &=
+ ~fb_data->luts_complete_wb;
+
+ dev_dbg(fb_data->dev, "Collision mask = 0x%llx\n",
+ fb_data->epdc_colliding_luts);
+
+ /* For EPDC 2.0 and later, minimum collision bounds
+ are provided by HW. Recompute new bounds here. */
+ if ((fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT)
+ && (fb_data->rev >= 20)) {
+ u32 xres, yres, rotate;
+ struct mxcfb_rect *cur_upd_rect =
+ &fb_data->cur_update->update_desc->upd_data.update_region;
+
+ /* Get collision region coords from EPDC */
+ coll_coord = __raw_readl(EPDC_UPD_COL_CORD);
+ coll_size = __raw_readl(EPDC_UPD_COL_SIZE);
+ coll_region.left =
+ (coll_coord & EPDC_UPD_COL_CORD_XCORD_MASK)
+ >> EPDC_UPD_COL_CORD_XCORD_OFFSET;
+ coll_region.top =
+ (coll_coord & EPDC_UPD_COL_CORD_YCORD_MASK)
+ >> EPDC_UPD_COL_CORD_YCORD_OFFSET;
+ coll_region.width =
+ (coll_size & EPDC_UPD_COL_SIZE_WIDTH_MASK)
+ >> EPDC_UPD_COL_SIZE_WIDTH_OFFSET;
+ coll_region.height =
+ (coll_size & EPDC_UPD_COL_SIZE_HEIGHT_MASK)
+ >> EPDC_UPD_COL_SIZE_HEIGHT_OFFSET;
+ dev_dbg(fb_data->dev, "Coll region: l = %d, "
+ "t = %d, w = %d, h = %d\n",
+ coll_region.left, coll_region.top,
+ coll_region.width, coll_region.height);
+
+ /* Convert coords back to orig orientation */
+ switch (fb_data->epdc_fb_var.rotate) {
+ case FB_ROTATE_CW:
+ xres = fb_data->epdc_fb_var.yres;
+ yres = fb_data->epdc_fb_var.xres;
+ rotate = FB_ROTATE_CCW;
+ break;
+ case FB_ROTATE_UD:
+ xres = fb_data->epdc_fb_var.xres;
+ yres = fb_data->epdc_fb_var.yres;
+ rotate = FB_ROTATE_UD;
+ break;
+ case FB_ROTATE_CCW:
+ xres = fb_data->epdc_fb_var.yres;
+ yres = fb_data->epdc_fb_var.xres;
+ rotate = FB_ROTATE_CW;
+ break;
+ default:
+ xres = fb_data->epdc_fb_var.xres;
+ yres = fb_data->epdc_fb_var.yres;
+ rotate = FB_ROTATE_UR;
+ break;
+ }
+ adjust_coordinates(xres, yres, rotate,
+ &coll_region, cur_upd_rect);
+
+ dev_dbg(fb_data->dev, "Adj coll region: l = %d, "
+ "t = %d, w = %d, h = %d\n",
+ cur_upd_rect->left, cur_upd_rect->top,
+ cur_upd_rect->width,
+ cur_upd_rect->height);
+ }
+
+ /*
+ * If we collide with newer updates, then
+ * we don't need to re-submit the update. The
+ * idea is that the newer updates should take
+ * precedence anyways, so we don't want to
+ * overwrite them.
+ */
+ for (temp_mask = fb_data->cur_update->collision_mask, lut = 0;
+ temp_mask != 0;
+ lut++, temp_mask = temp_mask >> 1) {
+ if (!(temp_mask & 0x1))
+ continue;
+
+ if (fb_data->lut_update_order[lut] >=
+ fb_data->cur_update->update_desc->update_order) {
+ dev_dbg(fb_data->dev,
+ "Ignoring collision with"
+ "newer update.\n");
+ ignore_collision = true;
+ break;
+ }
+ }
+
+ if (!ignore_collision) {
+ free_update = false;
+ /*
+ * If update has markers, clear the LUTs to
+ * avoid signalling that they have completed.
+ */
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->cur_update->update_desc->upd_marker_list,
+ upd_list)
+ next_marker->lut_num = INVALID_LUT;
+
+ /* Move to collision list */
+ list_add_tail(&fb_data->cur_update->list,
+ &fb_data->upd_buf_collision_list);
+ }
+ }
+
+ /* Do we need to free the current update descriptor? */
+ if (free_update) {
+ /* Handle condition where WB & LUT are both complete */
+ if (wb_lut_done)
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->cur_update->update_desc->upd_marker_list,
+ upd_list) {
+
+ /* Del from per-update & full list */
+ list_del_init(&next_marker->upd_list);
+ list_del_init(&next_marker->full_list);
+
+ /* Signal completion of update */
+ dev_dbg(fb_data->dev,
+ "Signaling marker (wb) %d\n",
+ next_marker->update_marker);
+ if (next_marker->waiting)
+ complete(&next_marker->update_completion);
+ else
+ kfree(next_marker);
+ }
+
+ /* Free marker list and update descriptor */
+ kfree(fb_data->cur_update->update_desc);
+
+ /* Add to free buffer list */
+ list_add_tail(&fb_data->cur_update->list,
+ &fb_data->upd_buf_free_list);
+
+ /* Check to see if all updates have completed */
+ if (list_empty(&fb_data->upd_pending_list) &&
+ is_free_list_full(fb_data) &&
+ !epdc_luts_active) {
+
+ fb_data->updates_active = false;
+
+ if (fb_data->pwrdown_delay !=
+ FB_POWERDOWN_DISABLE) {
+ /*
+ * Set variable to prevent overlapping
+ * enable/disable requests
+ */
+ fb_data->powering_down = true;
+
+ /* Schedule EPDC disable */
+ schedule_delayed_work(&fb_data->epdc_done_work,
+ msecs_to_jiffies(fb_data->pwrdown_delay));
+
+ /* Reset counter to reduce chance of overflow */
+ fb_data->order_cnt = 0;
+ }
+
+ if (fb_data->waiting_for_idle)
+ complete(&fb_data->updates_done);
+ }
+ }
+
+ /* Clear current update */
+ fb_data->cur_update = NULL;
+
+ /* Clear IRQ for working buffer */
+ epdc_working_buf_intr(false);
+ epdc_clear_working_buf_irq();
+ }
+
+ if (fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT) {
+ /* Queued update scheme processing */
+
+ /* Schedule task to submit collision and pending update */
+ if (!fb_data->powering_down)
+ queue_work(fb_data->epdc_submit_workqueue,
+ &fb_data->epdc_submit_work);
+
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+
+ return;
+ }
+
+ /* Snapshot update scheme processing */
+
+ /* Check to see if any LUTs are free */
+ if (!epdc_luts_avail) {
+ dev_dbg(fb_data->dev, "No luts available.\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ epdc_next_lut_15 = epdc_choose_next_lut(fb_data->rev, &next_lut);
+ /* Check to see if there is a valid LUT to use */
+ if (epdc_next_lut_15 && fb_data->tce_prevent && (fb_data->rev < 20)) {
+ dev_dbg(fb_data->dev, "Must wait for LUT15\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ /*
+ * Are any of our collision updates able to go now?
+ * Go through all updates in the collision list and check to see
+ * if the collision mask has been fully cleared
+ */
+ list_for_each_entry(collision_update,
+ &fb_data->upd_buf_collision_list, list) {
+
+ if (collision_update->collision_mask != 0)
+ continue;
+
+ dev_dbg(fb_data->dev, "A collision update is ready to go!\n");
+ /*
+ * We have a collision cleared, so select it
+ * and we will retry the update
+ */
+ fb_data->cur_update = collision_update;
+ list_del_init(&fb_data->cur_update->list);
+ break;
+ }
+
+ /*
+ * If we didn't find a collision update ready to go,
+ * we try to grab one from the update queue
+ */
+ if (fb_data->cur_update == NULL) {
+ /* Is update list empty? */
+ if (list_empty(&fb_data->upd_buf_queue)) {
+ dev_dbg(fb_data->dev, "No pending updates.\n");
+
+ /* No updates pending, so we are done */
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ } else {
+ dev_dbg(fb_data->dev, "Found a pending update!\n");
+
+ /* Process next item in update list */
+ fb_data->cur_update =
+ list_entry(fb_data->upd_buf_queue.next,
+ struct update_data_list, list);
+ list_del_init(&fb_data->cur_update->list);
+ }
+ }
+
+ /* Use LUT selected above */
+ fb_data->cur_update->lut_num = next_lut;
+
+ /* Associate LUT with update markers */
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->cur_update->update_desc->upd_marker_list, upd_list)
+ next_marker->lut_num = fb_data->cur_update->lut_num;
+
+ /* Mark LUT as containing new update */
+ fb_data->lut_update_order[fb_data->cur_update->lut_num] =
+ fb_data->cur_update->update_desc->update_order;
+
+ /* Enable Collision and WB complete IRQs */
+ epdc_working_buf_intr(true);
+ epdc_lut_complete_intr(fb_data->rev, fb_data->cur_update->lut_num, true);
+
+ /* Program EPDC update to process buffer */
+ next_upd_region =
+ &fb_data->cur_update->update_desc->upd_data.update_region;
+ if (fb_data->cur_update->update_desc->upd_data.temp
+ != TEMP_USE_AMBIENT) {
+ temp_index = mxc_epdc_fb_get_temp_index(fb_data,
+ fb_data->cur_update->update_desc->upd_data.temp);
+ epdc_set_temp(temp_index);
+ } else
+ epdc_set_temp(fb_data->temp_index);
+ epdc_set_update_addr(fb_data->cur_update->phys_addr +
+ fb_data->cur_update->update_desc->epdc_offs);
+ epdc_set_update_coord(next_upd_region->left, next_upd_region->top);
+ epdc_set_update_dimensions(next_upd_region->width,
+ next_upd_region->height);
+ if (fb_data->rev > 20)
+ epdc_set_update_stride(fb_data->cur_update->update_desc->epdc_stride);
+ if (fb_data->wv_modes_update &&
+ (fb_data->cur_update->update_desc->upd_data.waveform_mode
+ == WAVEFORM_MODE_AUTO)) {
+ epdc_set_update_waveform(&fb_data->wv_modes);
+ fb_data->wv_modes_update = false;
+ }
+
+ epdc_submit_update(fb_data->cur_update->lut_num,
+ fb_data->cur_update->update_desc->upd_data.waveform_mode,
+ fb_data->cur_update->update_desc->upd_data.update_mode,
+ false, false, 0);
+
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+
+ return;
+}
+
+static void draw_mode0(struct mxc_epdc_fb_data *fb_data)
+{
+ u32 *upd_buf_ptr;
+ int i;
+ struct fb_var_screeninfo *screeninfo = &fb_data->epdc_fb_var;
+ u32 xres, yres;
+
+ upd_buf_ptr = (u32 *)fb_data->info.screen_base;
+
+ epdc_working_buf_intr(true);
+ epdc_lut_complete_intr(fb_data->rev, 0, true);
+
+ /* Use unrotated (native) width/height */
+ if ((screeninfo->rotate == FB_ROTATE_CW) ||
+ (screeninfo->rotate == FB_ROTATE_CCW)) {
+ xres = screeninfo->yres;
+ yres = screeninfo->xres;
+ } else {
+ xres = screeninfo->xres;
+ yres = screeninfo->yres;
+ }
+
+ /* Program EPDC update to process buffer */
+ epdc_set_update_addr(fb_data->phys_start);
+ epdc_set_update_coord(0, 0);
+ epdc_set_update_dimensions(xres, yres);
+ if (fb_data->rev > 20)
+ epdc_set_update_stride(0);
+ epdc_submit_update(0, fb_data->wv_modes.mode_init, UPDATE_MODE_FULL,
+ false, true, 0xFF);
+
+ dev_dbg(fb_data->dev, "Mode0 update - Waiting for LUT to complete...\n");
+
+ /* Will timeout after ~4-5 seconds */
+
+ for (i = 0; i < 40; i++) {
+ if (!epdc_is_lut_active(0)) {
+ dev_dbg(fb_data->dev, "Mode0 init complete\n");
+ return;
+ }
+ msleep(100);
+ }
+
+ dev_err(fb_data->dev, "Mode0 init failed!\n");
+
+ return;
+}
+
+
+static void mxc_epdc_fb_fw_handler(const struct firmware *fw,
+ void *context)
+{
+ struct mxc_epdc_fb_data *fb_data = context;
+ int ret;
+ struct mxcfb_waveform_data_file *wv_file;
+ int wv_data_offs;
+ int i;
+ struct mxcfb_update_data update;
+ struct mxcfb_update_marker_data upd_marker_data;
+ struct fb_var_screeninfo *screeninfo = &fb_data->epdc_fb_var;
+ u32 xres, yres;
+ struct clk *epdc_parent;
+ unsigned long rounded_parent_rate, epdc_pix_rate,
+ rounded_pix_clk, target_pix_clk;
+
+ if (fw == NULL) {
+ /* If default FW file load failed, we give up */
+ if (fb_data->fw_default_load)
+ return;
+
+ /* Try to load default waveform */
+ dev_dbg(fb_data->dev,
+ "Can't find firmware. Trying fallback fw\n");
+ fb_data->fw_default_load = true;
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ "imx/epdc/epdc.fw", fb_data->dev, GFP_KERNEL, fb_data,
+ mxc_epdc_fb_fw_handler);
+ if (ret)
+ dev_err(fb_data->dev,
+ "Failed request_firmware_nowait err %d\n", ret);
+
+ return;
+ }
+
+ wv_file = (struct mxcfb_waveform_data_file *)fw->data;
+
+ /* Get size and allocate temperature range table */
+ fb_data->trt_entries = wv_file->wdh.trc + 1;
+ fb_data->temp_range_bounds = kzalloc(fb_data->trt_entries, GFP_KERNEL);
+
+ for (i = 0; i < fb_data->trt_entries; i++)
+ dev_dbg(fb_data->dev, "trt entry #%d = 0x%x\n", i, *((u8 *)&wv_file->data + i));
+
+ /* Copy TRT data */
+ memcpy(fb_data->temp_range_bounds, &wv_file->data, fb_data->trt_entries);
+
+ /* Set default temperature index using TRT and room temp */
+ fb_data->temp_index = mxc_epdc_fb_get_temp_index(fb_data, DEFAULT_TEMP);
+
+ /* Get offset and size for waveform data */
+ wv_data_offs = sizeof(wv_file->wdh) + fb_data->trt_entries + 1;
+ fb_data->waveform_buffer_size = fw->size - wv_data_offs;
+
+ /* Allocate memory for waveform data */
+ fb_data->waveform_buffer_virt = dma_alloc_coherent(fb_data->dev,
+ fb_data->waveform_buffer_size,
+ &fb_data->waveform_buffer_phys,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->waveform_buffer_virt == NULL) {
+ dev_err(fb_data->dev, "Can't allocate mem for waveform!\n");
+ return;
+ }
+
+ memcpy(fb_data->waveform_buffer_virt, (u8 *)(fw->data) + wv_data_offs,
+ fb_data->waveform_buffer_size);
+
+ release_firmware(fw);
+
+ /* Enable clocks to access EPDC regs */
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+
+ target_pix_clk = fb_data->cur_mode->vmode->pixclock;
+ /* Enable pix clk for EPDC */
+ rounded_pix_clk = clk_round_rate(fb_data->epdc_clk_pix, target_pix_clk);
+
+ if (((rounded_pix_clk >= target_pix_clk + target_pix_clk/100) ||
+ (rounded_pix_clk <= target_pix_clk - target_pix_clk/100))) {
+ /* Can't get close enough without changing parent clk */
+ epdc_parent = clk_get_parent(fb_data->epdc_clk_pix);
+ rounded_parent_rate = clk_round_rate(epdc_parent, target_pix_clk);
+
+ epdc_pix_rate = target_pix_clk;
+ while (epdc_pix_rate < rounded_parent_rate)
+ epdc_pix_rate *= 2;
+ clk_set_rate(epdc_parent, epdc_pix_rate);
+
+ rounded_pix_clk = clk_round_rate(fb_data->epdc_clk_pix, target_pix_clk);
+ if (((rounded_pix_clk >= target_pix_clk + target_pix_clk/100) ||
+ (rounded_pix_clk <= target_pix_clk - target_pix_clk/100)))
+ /* Still can't get a good clock, provide warning */
+ dev_err(fb_data->dev, "Unable to get an accurate EPDC pix clk"
+ "desired = %lu, actual = %lu\n", target_pix_clk,
+ rounded_pix_clk);
+ }
+
+ clk_set_rate(fb_data->epdc_clk_pix, rounded_pix_clk);
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+
+ epdc_init_sequence(fb_data);
+
+ /* Disable clocks */
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+
+ fb_data->hw_ready = true;
+ fb_data->hw_initializing = false;
+
+ /* Use unrotated (native) width/height */
+ if ((screeninfo->rotate == FB_ROTATE_CW) ||
+ (screeninfo->rotate == FB_ROTATE_CCW)) {
+ xres = screeninfo->yres;
+ yres = screeninfo->xres;
+ } else {
+ xres = screeninfo->xres;
+ yres = screeninfo->yres;
+ }
+
+ update.update_region.left = 0;
+ update.update_region.width = xres;
+ update.update_region.top = 0;
+ update.update_region.height = yres;
+ update.update_mode = UPDATE_MODE_FULL;
+ update.waveform_mode = WAVEFORM_MODE_AUTO;
+ update.update_marker = INIT_UPDATE_MARKER;
+ update.temp = TEMP_USE_AMBIENT;
+ update.flags = 0;
+
+ upd_marker_data.update_marker = update.update_marker;
+
+ mxc_epdc_fb_send_update(&update, &fb_data->info);
+
+ /* Block on initial update */
+ ret = mxc_epdc_fb_wait_update_complete(&upd_marker_data,
+ &fb_data->info);
+ if (ret < 0)
+ dev_err(fb_data->dev,
+ "Wait for initial update complete failed."
+ " Error = 0x%x", ret);
+}
+
+static int mxc_epdc_fb_init_hw(struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ int ret;
+
+ /*
+ * Create fw search string based on ID string in selected videomode.
+ * Format is "imx/epdc_[panel string].fw"
+ */
+ if (fb_data->cur_mode) {
+ strcat(fb_data->fw_str, "imx/epdc/epdc_");
+ strcat(fb_data->fw_str, fb_data->cur_mode->vmode->name);
+ strcat(fb_data->fw_str, ".fw");
+ }
+
+ fb_data->fw_default_load = false;
+
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ fb_data->fw_str, fb_data->dev, GFP_KERNEL,
+ fb_data, mxc_epdc_fb_fw_handler);
+ if (ret)
+ dev_dbg(fb_data->dev,
+ "Failed request_firmware_nowait err %d\n", ret);
+
+ return ret;
+}
+
+static ssize_t store_update(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxcfb_update_data update;
+ struct fb_info *info = dev_get_drvdata(device);
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+
+ if (strncmp(buf, "direct", 6) == 0)
+ update.waveform_mode = fb_data->wv_modes.mode_du;
+ else if (strncmp(buf, "gc16", 4) == 0)
+ update.waveform_mode = fb_data->wv_modes.mode_gc16;
+ else if (strncmp(buf, "gc4", 3) == 0)
+ update.waveform_mode = fb_data->wv_modes.mode_gc4;
+
+ /* Now, request full screen update */
+ update.update_region.left = 0;
+ update.update_region.width = fb_data->epdc_fb_var.xres;
+ update.update_region.top = 0;
+ update.update_region.height = fb_data->epdc_fb_var.yres;
+ update.update_mode = UPDATE_MODE_FULL;
+ update.temp = TEMP_USE_AMBIENT;
+ update.update_marker = 0;
+ update.flags = 0;
+
+ mxc_epdc_fb_send_update(&update, info);
+
+ return count;
+}
+
+static struct device_attribute fb_attrs[] = {
+ __ATTR(update, S_IRUGO|S_IWUSR, NULL, store_update),
+};
+
+static const struct of_device_id imx_epdc_dt_ids[] = {
+ { .compatible = "fsl,imx6dl-epdc", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_epdc_dt_ids);
+
+int mxc_epdc_fb_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct pinctrl *pinctrl;
+ struct mxc_epdc_fb_data *fb_data;
+ struct resource *res;
+ struct fb_info *info;
+ char *options, *opt;
+ char *panel_str = NULL;
+ char name[] = "mxcepdcfb";
+ struct fb_videomode *vmode;
+ int xres_virt, yres_virt, buf_size;
+ int xres_virt_rot, yres_virt_rot, pix_size_rot;
+ struct fb_var_screeninfo *var_info;
+ struct fb_fix_screeninfo *fix_info;
+ struct pxp_config_data *pxp_conf;
+ struct pxp_proc_data *proc_data;
+ struct scatterlist *sg;
+ struct update_data_list *upd_list;
+ struct update_data_list *plist, *temp_list;
+ int i;
+ unsigned long x_mem_size = 0;
+ u32 val;
+ int irq;
+
+ fb_data = (struct mxc_epdc_fb_data *)framebuffer_alloc(
+ sizeof(struct mxc_epdc_fb_data), &pdev->dev);
+ if (fb_data == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Get platform data and check validity */
+ fb_data->pdata = &epdc_data;
+ if ((fb_data->pdata == NULL) || (fb_data->pdata->num_modes < 1)
+ || (fb_data->pdata->epdc_mode == NULL)
+ || (fb_data->pdata->epdc_mode->vmode == NULL)) {
+ ret = -EINVAL;
+ goto out_fbdata;
+ }
+
+ if (fb_get_options(name, &options)) {
+ ret = -ENODEV;
+ goto out_fbdata;
+ }
+
+ fb_data->tce_prevent = 0;
+
+ if (options)
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+
+ if (!strncmp(opt, "bpp=", 4))
+ fb_data->default_bpp =
+ simple_strtoul(opt + 4, NULL, 0);
+ else if (!strncmp(opt, "x_mem=", 6))
+ x_mem_size = memparse(opt + 6, NULL);
+ else if (!strncmp(opt, "tce_prevent", 11))
+ fb_data->tce_prevent = 1;
+ else
+ panel_str = opt;
+ }
+
+ fb_data->dev = &pdev->dev;
+
+ if (!fb_data->default_bpp)
+ fb_data->default_bpp = 16;
+
+ /* Set default (first defined mode) before searching for a match */
+ fb_data->cur_mode = &fb_data->pdata->epdc_mode[0];
+
+ if (panel_str)
+ for (i = 0; i < fb_data->pdata->num_modes; i++)
+ if (!strcmp(fb_data->pdata->epdc_mode[i].vmode->name,
+ panel_str)) {
+ fb_data->cur_mode =
+ &fb_data->pdata->epdc_mode[i];
+ break;
+ }
+
+ vmode = fb_data->cur_mode->vmode;
+
+ platform_set_drvdata(pdev, fb_data);
+ info = &fb_data->info;
+
+ /* Allocate color map for the FB */
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret)
+ goto out_fbdata;
+
+ dev_dbg(&pdev->dev, "resolution %dx%d, bpp %d\n",
+ vmode->xres, vmode->yres, fb_data->default_bpp);
+
+ /*
+ * GPU alignment restrictions dictate framebuffer parameters:
+ * - 32-byte alignment for buffer width
+ * - 128-byte alignment for buffer height
+ * => 4K buffer alignment for buffer start
+ */
+ xres_virt = ALIGN(vmode->xres, 32);
+ yres_virt = ALIGN(vmode->yres, 128);
+ fb_data->max_pix_size = PAGE_ALIGN(xres_virt * yres_virt);
+
+ /*
+ * Have to check to see if aligned buffer size when rotated
+ * is bigger than when not rotated, and use the max
+ */
+ xres_virt_rot = ALIGN(vmode->yres, 32);
+ yres_virt_rot = ALIGN(vmode->xres, 128);
+ pix_size_rot = PAGE_ALIGN(xres_virt_rot * yres_virt_rot);
+ fb_data->max_pix_size = (fb_data->max_pix_size > pix_size_rot) ?
+ fb_data->max_pix_size : pix_size_rot;
+
+ buf_size = fb_data->max_pix_size * fb_data->default_bpp/8;
+
+ /* Compute the number of screens needed based on X memory requested */
+ if (x_mem_size > 0) {
+ fb_data->num_screens = DIV_ROUND_UP(x_mem_size, buf_size);
+ if (fb_data->num_screens < NUM_SCREENS_MIN)
+ fb_data->num_screens = NUM_SCREENS_MIN;
+ else if (buf_size * fb_data->num_screens > SZ_16M)
+ fb_data->num_screens = SZ_16M / buf_size;
+ } else
+ fb_data->num_screens = NUM_SCREENS_MIN;
+
+ fb_data->map_size = buf_size * fb_data->num_screens;
+ dev_dbg(&pdev->dev, "memory to allocate: %d\n", fb_data->map_size);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ ret = -ENODEV;
+ goto out_cmap;
+ }
+
+ epdc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (epdc_base == NULL) {
+ ret = -ENOMEM;
+ goto out_cmap;
+ }
+
+ /* Allocate FB memory */
+ info->screen_base = dma_alloc_writecombine(&pdev->dev,
+ fb_data->map_size,
+ &fb_data->phys_start,
+ GFP_DMA | GFP_KERNEL);
+
+ if (info->screen_base == NULL) {
+ ret = -ENOMEM;
+ goto out_cmap;
+ }
+ dev_dbg(&pdev->dev, "allocated at %p:0x%x\n", info->screen_base,
+ fb_data->phys_start);
+
+ var_info = &info->var;
+ var_info->activate = FB_ACTIVATE_TEST;
+ var_info->bits_per_pixel = fb_data->default_bpp;
+ var_info->xres = vmode->xres;
+ var_info->yres = vmode->yres;
+ var_info->xres_virtual = xres_virt;
+ /* Additional screens allow for panning and buffer flipping */
+ var_info->yres_virtual = yres_virt * fb_data->num_screens;
+
+ var_info->pixclock = vmode->pixclock;
+ var_info->left_margin = vmode->left_margin;
+ var_info->right_margin = vmode->right_margin;
+ var_info->upper_margin = vmode->upper_margin;
+ var_info->lower_margin = vmode->lower_margin;
+ var_info->hsync_len = vmode->hsync_len;
+ var_info->vsync_len = vmode->vsync_len;
+ var_info->vmode = FB_VMODE_NONINTERLACED;
+
+ switch (fb_data->default_bpp) {
+ case 32:
+ case 24:
+ var_info->red.offset = 16;
+ var_info->red.length = 8;
+ var_info->green.offset = 8;
+ var_info->green.length = 8;
+ var_info->blue.offset = 0;
+ var_info->blue.length = 8;
+ break;
+
+ case 16:
+ var_info->red.offset = 11;
+ var_info->red.length = 5;
+ var_info->green.offset = 5;
+ var_info->green.length = 6;
+ var_info->blue.offset = 0;
+ var_info->blue.length = 5;
+ break;
+
+ case 8:
+ /*
+ * For 8-bit grayscale, R, G, and B offset are equal.
+ *
+ */
+ var_info->grayscale = GRAYSCALE_8BIT;
+
+ var_info->red.length = 8;
+ var_info->red.offset = 0;
+ var_info->red.msb_right = 0;
+ var_info->green.length = 8;
+ var_info->green.offset = 0;
+ var_info->green.msb_right = 0;
+ var_info->blue.length = 8;
+ var_info->blue.offset = 0;
+ var_info->blue.msb_right = 0;
+ break;
+
+ default:
+ dev_err(&pdev->dev, "unsupported bitwidth %d\n",
+ fb_data->default_bpp);
+ ret = -EINVAL;
+ goto out_dma_fb;
+ }
+
+ fix_info = &info->fix;
+
+ strcpy(fix_info->id, "mxc_epdc_fb");
+ fix_info->type = FB_TYPE_PACKED_PIXELS;
+ fix_info->visual = FB_VISUAL_TRUECOLOR;
+ fix_info->xpanstep = 0;
+ fix_info->ypanstep = 0;
+ fix_info->ywrapstep = 0;
+ fix_info->accel = FB_ACCEL_NONE;
+ fix_info->smem_start = fb_data->phys_start;
+ fix_info->smem_len = fb_data->map_size;
+ fix_info->ypanstep = 0;
+
+ fb_data->native_width = vmode->xres;
+ fb_data->native_height = vmode->yres;
+
+ info->fbops = &mxc_epdc_fb_ops;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->pseudo_palette = fb_data->pseudo_palette;
+ info->screen_size = info->fix.smem_len;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ mxc_epdc_fb_set_fix(info);
+
+ fb_data->auto_mode = AUTO_UPDATE_MODE_REGION_MODE;
+ fb_data->upd_scheme = UPDATE_SCHEME_QUEUE_AND_MERGE;
+
+ /* Initialize our internal copy of the screeninfo */
+ fb_data->epdc_fb_var = *var_info;
+ fb_data->fb_offset = 0;
+ fb_data->eof_sync_period = 0;
+
+ fb_data->epdc_clk_axi = clk_get(fb_data->dev, "epdc_axi");
+ if (IS_ERR(fb_data->epdc_clk_axi)) {
+ dev_err(&pdev->dev, "Unable to get EPDC AXI clk."
+ "err = %d\n", (int)fb_data->epdc_clk_axi);
+ ret = -ENODEV;
+ goto out_dma_fb;
+ }
+ fb_data->epdc_clk_pix = clk_get(fb_data->dev, "epdc_pix");
+ if (IS_ERR(fb_data->epdc_clk_pix)) {
+ dev_err(&pdev->dev, "Unable to get EPDC pix clk."
+ "err = %d\n", (int)fb_data->epdc_clk_pix);
+ ret = -ENODEV;
+ goto out_dma_fb;
+ }
+
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+ val = __raw_readl(EPDC_VERSION);
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+ fb_data->rev = ((val & EPDC_VERSION_MAJOR_MASK) >>
+ EPDC_VERSION_MAJOR_OFFSET) * 10
+ + ((val & EPDC_VERSION_MINOR_MASK) >>
+ EPDC_VERSION_MINOR_OFFSET);
+ dev_dbg(&pdev->dev, "EPDC version = %d\n", fb_data->rev);
+
+ if (fb_data->rev < 20) {
+ fb_data->num_luts = EPDC_V1_NUM_LUTS;
+ fb_data->max_num_updates = EPDC_V1_MAX_NUM_UPDATES;
+ } else {
+ fb_data->num_luts = EPDC_V2_NUM_LUTS;
+ fb_data->max_num_updates = EPDC_V2_MAX_NUM_UPDATES;
+ if (vmode->xres > EPDC_V2_MAX_UPDATE_WIDTH)
+ fb_data->restrict_width = true;
+ }
+ fb_data->max_num_buffers = EPDC_MAX_NUM_BUFFERS;
+
+ /*
+ * Initialize lists for pending updates,
+ * active update requests, update collisions,
+ * and freely available updates.
+ */
+ INIT_LIST_HEAD(&fb_data->upd_pending_list);
+ INIT_LIST_HEAD(&fb_data->upd_buf_queue);
+ INIT_LIST_HEAD(&fb_data->upd_buf_free_list);
+ INIT_LIST_HEAD(&fb_data->upd_buf_collision_list);
+
+ /* Allocate update buffers and add them to the list */
+ for (i = 0; i < fb_data->max_num_updates; i++) {
+ upd_list = kzalloc(sizeof(*upd_list), GFP_KERNEL);
+ if (upd_list == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_lists;
+ }
+
+ /* Add newly allocated buffer to free list */
+ list_add(&upd_list->list, &fb_data->upd_buf_free_list);
+ }
+
+ fb_data->virt_addr_updbuf =
+ kzalloc(sizeof(void *) * fb_data->max_num_buffers, GFP_KERNEL);
+ fb_data->phys_addr_updbuf =
+ kzalloc(sizeof(dma_addr_t) * fb_data->max_num_buffers,
+ GFP_KERNEL);
+ for (i = 0; i < fb_data->max_num_buffers; i++) {
+ /*
+ * Allocate memory for PxP output buffer.
+ * Each update buffer is 1 byte per pixel, and can
+ * be as big as the full-screen frame buffer
+ */
+ fb_data->virt_addr_updbuf[i] =
+ kmalloc(fb_data->max_pix_size, GFP_KERNEL);
+ fb_data->phys_addr_updbuf[i] =
+ virt_to_phys(fb_data->virt_addr_updbuf[i]);
+ if (fb_data->virt_addr_updbuf[i] == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_buffers;
+ }
+
+ dev_dbg(fb_data->info.device, "allocated %d bytes @ 0x%08X\n",
+ fb_data->max_pix_size, fb_data->phys_addr_updbuf[i]);
+ }
+
+ /* Counter indicating which update buffer should be used next. */
+ fb_data->upd_buffer_num = 0;
+
+ /*
+ * Allocate memory for PxP SW workaround buffer
+ * These buffers are used to hold copy of the update region,
+ * before sending it to PxP for processing.
+ */
+ fb_data->virt_addr_copybuf =
+ dma_alloc_coherent(fb_data->info.device, fb_data->max_pix_size*2,
+ &fb_data->phys_addr_copybuf,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->virt_addr_copybuf == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_buffers;
+ }
+
+ fb_data->working_buffer_size = vmode->yres * vmode->xres * 2;
+ /* Allocate memory for EPDC working buffer */
+ fb_data->working_buffer_virt =
+ dma_alloc_coherent(&pdev->dev, fb_data->working_buffer_size,
+ &fb_data->working_buffer_phys,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->working_buffer_virt == NULL) {
+ dev_err(&pdev->dev, "Can't allocate mem for working buf!\n");
+ ret = -ENOMEM;
+ goto out_copybuffer;
+ }
+
+ /* Initialize EPDC pins */
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(&pdev->dev, "can't get/select pinctrl\n");
+ ret = PTR_ERR(pinctrl);
+ goto out_copybuffer;
+ }
+
+ fb_data->in_init = false;
+
+ fb_data->hw_ready = false;
+ fb_data->hw_initializing = false;
+
+ /*
+ * Set default waveform mode values.
+ * Should be overwritten via ioctl.
+ */
+ fb_data->wv_modes.mode_init = 0;
+ fb_data->wv_modes.mode_du = 1;
+ fb_data->wv_modes.mode_gc4 = 3;
+ fb_data->wv_modes.mode_gc8 = 2;
+ fb_data->wv_modes.mode_gc16 = 2;
+ fb_data->wv_modes.mode_gc32 = 2;
+ fb_data->wv_modes_update = true;
+
+ /* Initialize marker list */
+ INIT_LIST_HEAD(&fb_data->full_marker_list);
+
+ /* Initialize all LUTs to inactive */
+ fb_data->lut_update_order =
+ kzalloc(fb_data->num_luts * sizeof(u32 *), GFP_KERNEL);
+ for (i = 0; i < fb_data->num_luts; i++)
+ fb_data->lut_update_order[i] = 0;
+
+ INIT_DELAYED_WORK(&fb_data->epdc_done_work, epdc_done_work_func);
+ fb_data->epdc_submit_workqueue = alloc_workqueue("EPDC Submit",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI |
+ WQ_CPU_INTENSIVE | WQ_UNBOUND, 1);
+ INIT_WORK(&fb_data->epdc_submit_work, epdc_submit_work_func);
+ fb_data->epdc_intr_workqueue = alloc_workqueue("EPDC Interrupt",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI |
+ WQ_CPU_INTENSIVE | WQ_UNBOUND, 1);
+ INIT_WORK(&fb_data->epdc_intr_work, epdc_intr_work_func);
+
+ /* Retrieve EPDC IRQ num */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "cannot get IRQ resource\n");
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+ fb_data->epdc_irq = irq;
+
+ /* Register IRQ handler */
+ ret = devm_request_irq(&pdev->dev, fb_data->epdc_irq,
+ mxc_epdc_irq_handler, 0, "epdc", fb_data);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
+ fb_data->epdc_irq, ret);
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+
+ info->fbdefio = &mxc_epdc_fb_defio;
+#ifdef CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE
+ fb_deferred_io_init(info);
+#endif
+
+ /* get pmic regulators */
+ fb_data->display_regulator = devm_regulator_get(&pdev->dev, "DISPLAY");
+ if (IS_ERR(fb_data->display_regulator)) {
+ dev_err(&pdev->dev, "Unable to get display PMIC regulator."
+ "err = 0x%x\n", (int)fb_data->display_regulator);
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+ fb_data->vcom_regulator = devm_regulator_get(&pdev->dev, "VCOM");
+ if (IS_ERR(fb_data->vcom_regulator)) {
+ dev_err(&pdev->dev, "Unable to get VCOM regulator."
+ "err = 0x%x\n", (int)fb_data->vcom_regulator);
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+ fb_data->v3p3_regulator = devm_regulator_get(&pdev->dev, "V3P3");
+ if (IS_ERR(fb_data->v3p3_regulator)) {
+ dev_err(&pdev->dev, "Unable to get V3P3 regulator."
+ "err = 0x%x\n", (int)fb_data->vcom_regulator);
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+
+ if (device_create_file(info->dev, &fb_attrs[0]))
+ dev_err(&pdev->dev, "Unable to create file from fb_attrs\n");
+
+ fb_data->cur_update = NULL;
+
+ mutex_init(&fb_data->queue_mutex);
+ mutex_init(&fb_data->pxp_mutex);
+ mutex_init(&fb_data->power_mutex);
+
+ /*
+ * Fill out PxP config data structure based on FB info and
+ * processing tasks required
+ */
+ pxp_conf = &fb_data->pxp_conf;
+ proc_data = &pxp_conf->proc_data;
+
+ /* Initialize non-channel-specific PxP parameters */
+ proc_data->drect.left = proc_data->srect.left = 0;
+ proc_data->drect.top = proc_data->srect.top = 0;
+ proc_data->drect.width = proc_data->srect.width = fb_data->info.var.xres;
+ proc_data->drect.height = proc_data->srect.height = fb_data->info.var.yres;
+ proc_data->scaling = 0;
+ proc_data->hflip = 0;
+ proc_data->vflip = 0;
+ proc_data->rotate = 0;
+ proc_data->bgcolor = 0;
+ proc_data->overlay_state = 0;
+ proc_data->lut_transform = PXP_LUT_NONE;
+ proc_data->lut_map = NULL;
+
+ /*
+ * We initially configure PxP for RGB->YUV conversion,
+ * and only write out Y component of the result.
+ */
+
+ /*
+ * Initialize S0 channel parameters
+ * Parameters should match FB format/width/height
+ */
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
+ pxp_conf->s0_param.width = fb_data->info.var.xres_virtual;
+ pxp_conf->s0_param.height = fb_data->info.var.yres;
+ pxp_conf->s0_param.color_key = -1;
+ pxp_conf->s0_param.color_key_enable = false;
+
+ /*
+ * Initialize OL0 channel parameters
+ * No overlay will be used for PxP operation
+ */
+ pxp_conf->ol_param[0].combine_enable = false;
+ pxp_conf->ol_param[0].width = 0;
+ pxp_conf->ol_param[0].height = 0;
+ pxp_conf->ol_param[0].pixel_fmt = PXP_PIX_FMT_RGB565;
+ pxp_conf->ol_param[0].color_key_enable = false;
+ pxp_conf->ol_param[0].color_key = -1;
+ pxp_conf->ol_param[0].global_alpha_enable = false;
+ pxp_conf->ol_param[0].global_alpha = 0;
+ pxp_conf->ol_param[0].local_alpha_enable = false;
+
+ /*
+ * Initialize Output channel parameters
+ * Output is Y-only greyscale
+ * Output width/height will vary based on update region size
+ */
+ pxp_conf->out_param.width = fb_data->info.var.xres;
+ pxp_conf->out_param.height = fb_data->info.var.yres;
+ pxp_conf->out_param.stride = pxp_conf->out_param.width;
+ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_GREY;
+
+ /* Initialize color map for conversion of 8-bit gray pixels */
+ fb_data->pxp_conf.proc_data.lut_map = kmalloc(256, GFP_KERNEL);
+ if (fb_data->pxp_conf.proc_data.lut_map == NULL) {
+ dev_err(&pdev->dev, "Can't allocate mem for lut map!\n");
+ ret = -ENOMEM;
+ goto out_dma_work_buf;
+ }
+ for (i = 0; i < 256; i++)
+ fb_data->pxp_conf.proc_data.lut_map[i] = i;
+
+ fb_data->pxp_conf.proc_data.lut_map_updated = true;
+
+ /*
+ * Ensure this is set to NULL here...we will initialize pxp_chan
+ * later in our thread.
+ */
+ fb_data->pxp_chan = NULL;
+
+ /* Initialize Scatter-gather list containing 2 buffer addresses. */
+ sg = fb_data->sg;
+ sg_init_table(sg, 2);
+
+ /*
+ * For use in PxP transfers:
+ * sg[0] holds the FB buffer pointer
+ * sg[1] holds the Output buffer pointer (configured before TX request)
+ */
+ sg_dma_address(&sg[0]) = info->fix.smem_start;
+ sg_set_page(&sg[0], virt_to_page(info->screen_base),
+ info->fix.smem_len, offset_in_page(info->screen_base));
+
+ fb_data->order_cnt = 0;
+ fb_data->waiting_for_wb = false;
+ fb_data->waiting_for_lut = false;
+ fb_data->waiting_for_lut15 = false;
+ fb_data->waiting_for_idle = false;
+ fb_data->blank = FB_BLANK_UNBLANK;
+ fb_data->power_state = POWER_STATE_OFF;
+ fb_data->powering_down = false;
+ fb_data->wait_for_powerdown = false;
+ fb_data->updates_active = false;
+ fb_data->pwrdown_delay = 0;
+
+ /* Register FB */
+ ret = register_framebuffer(info);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "register_framebuffer failed with error %d\n", ret);
+ goto out_lutmap;
+ }
+
+ g_fb_data = fb_data;
+
+ pm_runtime_enable(fb_data->dev);
+
+#ifdef DEFAULT_PANEL_HW_INIT
+ ret = mxc_epdc_fb_init_hw((struct fb_info *)fb_data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to initialize HW!\n");
+ }
+#endif
+
+ goto out;
+
+out_lutmap:
+ kfree(fb_data->pxp_conf.proc_data.lut_map);
+out_dma_work_buf:
+ dma_free_writecombine(&pdev->dev, fb_data->working_buffer_size,
+ fb_data->working_buffer_virt, fb_data->working_buffer_phys);
+out_copybuffer:
+ dma_free_writecombine(&pdev->dev, fb_data->max_pix_size*2,
+ fb_data->virt_addr_copybuf,
+ fb_data->phys_addr_copybuf);
+out_upd_buffers:
+ for (i = 0; i < fb_data->max_num_buffers; i++)
+ if (fb_data->virt_addr_updbuf[i] != NULL)
+ kfree(fb_data->virt_addr_updbuf[i]);
+ if (fb_data->virt_addr_updbuf != NULL)
+ kfree(fb_data->virt_addr_updbuf);
+ if (fb_data->phys_addr_updbuf != NULL)
+ kfree(fb_data->phys_addr_updbuf);
+out_upd_lists:
+ list_for_each_entry_safe(plist, temp_list, &fb_data->upd_buf_free_list,
+ list) {
+ list_del(&plist->list);
+ kfree(plist);
+ }
+out_dma_fb:
+ dma_free_writecombine(&pdev->dev, fb_data->map_size, info->screen_base,
+ fb_data->phys_start);
+
+out_cmap:
+ fb_dealloc_cmap(&info->cmap);
+out_fbdata:
+ kfree(fb_data);
+out:
+ return ret;
+}
+
+static int mxc_epdc_fb_remove(struct platform_device *pdev)
+{
+ struct update_data_list *plist, *temp_list;
+ struct mxc_epdc_fb_data *fb_data = platform_get_drvdata(pdev);
+ int i;
+
+ mxc_epdc_fb_blank(FB_BLANK_POWERDOWN, &fb_data->info);
+
+ flush_workqueue(fb_data->epdc_submit_workqueue);
+ destroy_workqueue(fb_data->epdc_submit_workqueue);
+
+ unregister_framebuffer(&fb_data->info);
+
+ for (i = 0; i < fb_data->max_num_buffers; i++)
+ if (fb_data->virt_addr_updbuf[i] != NULL)
+ kfree(fb_data->virt_addr_updbuf[i]);
+ if (fb_data->virt_addr_updbuf != NULL)
+ kfree(fb_data->virt_addr_updbuf);
+ if (fb_data->phys_addr_updbuf != NULL)
+ kfree(fb_data->phys_addr_updbuf);
+
+ dma_free_writecombine(&pdev->dev, fb_data->working_buffer_size,
+ fb_data->working_buffer_virt,
+ fb_data->working_buffer_phys);
+ if (fb_data->waveform_buffer_virt != NULL)
+ dma_free_writecombine(&pdev->dev, fb_data->waveform_buffer_size,
+ fb_data->waveform_buffer_virt,
+ fb_data->waveform_buffer_phys);
+ if (fb_data->virt_addr_copybuf != NULL)
+ dma_free_writecombine(&pdev->dev, fb_data->max_pix_size*2,
+ fb_data->virt_addr_copybuf,
+ fb_data->phys_addr_copybuf);
+ list_for_each_entry_safe(plist, temp_list, &fb_data->upd_buf_free_list,
+ list) {
+ list_del(&plist->list);
+ kfree(plist);
+ }
+#ifdef CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE
+ fb_deferred_io_cleanup(&fb_data->info);
+#endif
+
+ dma_free_writecombine(&pdev->dev, fb_data->map_size, fb_data->info.screen_base,
+ fb_data->phys_start);
+
+ /* Release PxP-related resources */
+ if (fb_data->pxp_chan != NULL)
+ dma_release_channel(&fb_data->pxp_chan->dma_chan);
+
+ fb_dealloc_cmap(&fb_data->info.cmap);
+
+ framebuffer_release(&fb_data->info);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mxc_epdc_fb_suspend(struct device *dev)
+{
+ struct mxc_epdc_fb_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ data->pwrdown_delay = FB_POWERDOWN_DISABLE;
+ ret = mxc_epdc_fb_blank(FB_BLANK_POWERDOWN, &data->info);
+ if (ret)
+ goto out;
+
+out:
+ return ret;
+}
+
+static int mxc_epdc_fb_resume(struct device *dev)
+{
+ struct mxc_epdc_fb_data *data = dev_get_drvdata(dev);
+
+ mxc_epdc_fb_blank(FB_BLANK_UNBLANK, &data->info);
+ epdc_init_settings(data);
+ data->updates_active = false;
+
+ return 0;
+}
+#else
+#define mxc_epdc_fb_suspend NULL
+#define mxc_epdc_fb_resume NULL
+#endif
+
+#ifdef CONFIG_PM
+static int mxc_epdc_fb_runtime_suspend(struct device *dev)
+{
+ release_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "epdc busfreq high release.\n");
+
+ return 0;
+}
+
+static int mxc_epdc_fb_runtime_resume(struct device *dev)
+{
+ request_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "epdc busfreq high request.\n");
+
+ return 0;
+}
+#else
+#define mxc_epdc_fb_runtime_suspend NULL
+#define mxc_epdc_fb_runtime_resume NULL
+#endif
+
+static const struct dev_pm_ops mxc_epdc_fb_pm_ops = {
+ SET_RUNTIME_PM_OPS(mxc_epdc_fb_runtime_suspend,
+ mxc_epdc_fb_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(mxc_epdc_fb_suspend, mxc_epdc_fb_resume)
+};
+
+static void mxc_epdc_fb_shutdown(struct platform_device *pdev)
+{
+ struct mxc_epdc_fb_data *fb_data = platform_get_drvdata(pdev);
+
+ /* Disable power to the EPD panel */
+ if (regulator_is_enabled(fb_data->vcom_regulator))
+ regulator_disable(fb_data->vcom_regulator);
+ if (regulator_is_enabled(fb_data->display_regulator))
+ regulator_disable(fb_data->display_regulator);
+
+ /* Disable clocks to EPDC */
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+ __raw_writel(EPDC_CTRL_CLKGATE, EPDC_CTRL_SET);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+
+ /* turn off the V3p3 */
+ if (regulator_is_enabled(fb_data->v3p3_regulator))
+ regulator_disable(fb_data->v3p3_regulator);
+}
+
+static struct platform_driver mxc_epdc_fb_driver = {
+ .probe = mxc_epdc_fb_probe,
+ .remove = mxc_epdc_fb_remove,
+ .shutdown = mxc_epdc_fb_shutdown,
+ .driver = {
+ .name = "imx_epdc_fb",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(imx_epdc_dt_ids),
+ .pm = &mxc_epdc_fb_pm_ops,
+ },
+};
+
+/* Callback function triggered after PxP receives an EOF interrupt */
+static void pxp_dma_done(void *arg)
+{
+ struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
+ struct dma_chan *chan = tx_desc->txd.chan;
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct mxc_epdc_fb_data *fb_data = pxp_chan->client;
+
+ /* This call will signal wait_for_completion_timeout() in send_buffer_to_pxp */
+ complete(&fb_data->pxp_tx_cmpl);
+}
+
+static bool chan_filter(struct dma_chan *chan, void *arg)
+{
+ if (imx_dma_is_pxp(chan))
+ return true;
+ else
+ return false;
+}
+
+/* Function to request PXP DMA channel */
+static int pxp_chan_init(struct mxc_epdc_fb_data *fb_data)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+
+ /*
+ * Request a free channel
+ */
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_PRIVATE, mask);
+ chan = dma_request_channel(mask, chan_filter, NULL);
+ if (!chan) {
+ dev_err(fb_data->dev, "Unsuccessfully received channel!!!!\n");
+ return -EBUSY;
+ }
+
+ fb_data->pxp_chan = to_pxp_channel(chan);
+ fb_data->pxp_chan->client = fb_data;
+
+ init_completion(&fb_data->pxp_tx_cmpl);
+
+ return 0;
+}
+
+/*
+ * Function to call PxP DMA driver and send our latest FB update region
+ * through the PxP and out to an intermediate buffer.
+ * Note: This is a blocking call, so upon return the PxP tx should be complete.
+ */
+static int pxp_process_update(struct mxc_epdc_fb_data *fb_data,
+ u32 src_width, u32 src_height,
+ struct mxcfb_rect *update_region)
+{
+ dma_cookie_t cookie;
+ struct scatterlist *sg = fb_data->sg;
+ struct dma_chan *dma_chan;
+ struct pxp_tx_desc *desc;
+ struct dma_async_tx_descriptor *txd;
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
+ int i, ret;
+ int length;
+
+ dev_dbg(fb_data->dev, "Starting PxP Send Buffer\n");
+
+ /* First, check to see that we have acquired a PxP Channel object */
+ if (fb_data->pxp_chan == NULL) {
+ /*
+ * PxP Channel has not yet been created and initialized,
+ * so let's go ahead and try
+ */
+ ret = pxp_chan_init(fb_data);
+ if (ret) {
+ /*
+ * PxP channel init failed, and we can't use the
+ * PxP until the PxP DMA driver has loaded, so we abort
+ */
+ dev_err(fb_data->dev, "PxP chan init failed\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Init completion, so that we
+ * can be properly informed of the completion
+ * of the PxP task when it is done.
+ */
+ init_completion(&fb_data->pxp_tx_cmpl);
+
+ dma_chan = &fb_data->pxp_chan->dma_chan;
+
+ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2,
+ DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT,
+ NULL);
+ if (!txd) {
+ dev_err(fb_data->info.device,
+ "Error preparing a DMA transaction descriptor.\n");
+ return -EIO;
+ }
+
+ txd->callback_param = txd;
+ txd->callback = pxp_dma_done;
+
+ /*
+ * Configure PxP for processing of new update region
+ * The rest of our config params were set up in
+ * probe() and should not need to be changed.
+ */
+ pxp_conf->s0_param.width = src_width;
+ pxp_conf->s0_param.height = src_height;
+ proc_data->srect.top = update_region->top;
+ proc_data->srect.left = update_region->left;
+ proc_data->srect.width = update_region->width;
+ proc_data->srect.height = update_region->height;
+
+ /*
+ * Because only YUV/YCbCr image can be scaled, configure
+ * drect equivalent to srect, as such do not perform scaling.
+ */
+ proc_data->drect.top = 0;
+ proc_data->drect.left = 0;
+
+ /* PXP expects rotation in terms of degrees */
+ proc_data->rotate = fb_data->epdc_fb_var.rotate * 90;
+ if (proc_data->rotate > 270)
+ proc_data->rotate = 0;
+
+ /* Just as V4L2 PXP, we should pass the rotated values to PXP */
+ if ((proc_data->rotate == 90) || (proc_data->rotate == 270)) {
+ proc_data->drect.width = proc_data->srect.height;
+ proc_data->drect.height = proc_data->srect.width;
+ pxp_conf->out_param.width = update_region->height;
+ pxp_conf->out_param.height = update_region->width;
+ pxp_conf->out_param.stride = update_region->height;
+ } else {
+ proc_data->drect.width = proc_data->srect.width;
+ proc_data->drect.height = proc_data->srect.height;
+ pxp_conf->out_param.width = update_region->width;
+ pxp_conf->out_param.height = update_region->height;
+ pxp_conf->out_param.stride = update_region->width;
+ }
+
+ /* For EPDC v2.0, we need output to be 64-bit
+ * aligned since EPDC stride does not work. */
+ if (fb_data->rev <= 20)
+ pxp_conf->out_param.stride = ALIGN(pxp_conf->out_param.stride, 8);
+
+
+ desc = to_tx_desc(txd);
+ length = desc->len;
+ for (i = 0; i < length; i++) {
+ if (i == 0) {/* S0 */
+ memcpy(&desc->proc_data, proc_data, sizeof(struct pxp_proc_data));
+ pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]);
+ memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param,
+ sizeof(struct pxp_layer_param));
+ } else if (i == 1) {
+ pxp_conf->out_param.paddr = sg_dma_address(&sg[1]);
+ memcpy(&desc->layer_param.out_param, &pxp_conf->out_param,
+ sizeof(struct pxp_layer_param));
+ }
+ /* TODO: OverLay */
+
+ desc = desc->next;
+ }
+
+ /* Submitting our TX starts the PxP processing task */
+ cookie = txd->tx_submit(txd);
+ if (cookie < 0) {
+ dev_err(fb_data->info.device, "Error sending FB through PxP\n");
+ return -EIO;
+ }
+
+ fb_data->txd = txd;
+
+ /* trigger ePxP */
+ dma_async_issue_pending(dma_chan);
+
+ return 0;
+}
+
+static int pxp_complete_update(struct mxc_epdc_fb_data *fb_data, u32 *hist_stat)
+{
+ int ret;
+ /*
+ * Wait for completion event, which will be set
+ * through our TX callback function.
+ */
+ ret = wait_for_completion_timeout(&fb_data->pxp_tx_cmpl, HZ / 10);
+ if (ret <= 0) {
+ dev_info(fb_data->info.device,
+ "PxP operation failed due to %s\n",
+ ret < 0 ? "user interrupt" : "timeout");
+ dma_release_channel(&fb_data->pxp_chan->dma_chan);
+ fb_data->pxp_chan = NULL;
+ return ret ? : -ETIMEDOUT;
+ }
+
+ if ((fb_data->pxp_conf.proc_data.lut_transform & EPDC_FLAG_USE_CMAP) &&
+ fb_data->pxp_conf.proc_data.lut_map_updated)
+ fb_data->pxp_conf.proc_data.lut_map_updated = false;
+
+ *hist_stat = to_tx_desc(fb_data->txd)->hist_status;
+ dma_release_channel(&fb_data->pxp_chan->dma_chan);
+ fb_data->pxp_chan = NULL;
+
+ dev_dbg(fb_data->dev, "TX completed\n");
+
+ return 0;
+}
+
+/*
+ * Different dithering algorithm can be used. We chose
+ * to implement Bill Atkinson's algorithm as an example
+ * Thanks Bill Atkinson for his dithering algorithm.
+ */
+
+/*
+ * Dithering algorithm implementation - Y8->Y1 version 1.0 for i.MX
+ */
+static void do_dithering_processing_Y1_v1_0(
+ unsigned char *update_region_virt_ptr,
+ dma_addr_t update_region_phys_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist)
+{
+
+ /* create a temp error distribution array */
+ int bwPix;
+ int y;
+ int col;
+ int *err_dist_l0, *err_dist_l1, *err_dist_l2, distrib_error;
+ int width_3 = update_region->width + 3;
+ char *y8buf;
+ int x_offset = 0;
+
+ /* prime a few elements the error distribution array */
+ for (y = 0; y < update_region->height; y++) {
+ /* Dithering the Y8 in sbuf to BW suitable for A2 waveform */
+ err_dist_l0 = err_dist + (width_3) * (y % 3);
+ err_dist_l1 = err_dist + (width_3) * ((y + 1) % 3);
+ err_dist_l2 = err_dist + (width_3) * ((y + 2) % 3);
+
+ y8buf = update_region_virt_ptr + x_offset;
+
+ /* scan the line and convert the Y8 to BW */
+ for (col = 1; col <= update_region->width; col++) {
+ bwPix = *(err_dist_l0 + col) + *y8buf;
+
+ if (bwPix >= 128) {
+ *y8buf++ = 0xff;
+ distrib_error = (bwPix - 255) >> 3;
+ } else {
+ *y8buf++ = 0;
+ distrib_error = bwPix >> 3;
+ }
+
+ /* modify the error distribution buffer */
+ *(err_dist_l0 + col + 2) += distrib_error;
+ *(err_dist_l1 + col + 1) += distrib_error;
+ *(err_dist_l0 + col + 1) += distrib_error;
+ *(err_dist_l1 + col - 1) += distrib_error;
+ *(err_dist_l1 + col) += distrib_error;
+ *(err_dist_l2 + col) = distrib_error;
+ }
+ x_offset += update_region_stride;
+ }
+
+ flush_cache_all();
+ outer_flush_range(update_region_phys_ptr, update_region_phys_ptr +
+ update_region->height * update_region->width);
+}
+
+/*
+ * Dithering algorithm implementation - Y8->Y4 version 1.0 for i.MX
+ */
+
+static void do_dithering_processing_Y4_v1_0(
+ unsigned char *update_region_virt_ptr,
+ dma_addr_t update_region_phys_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist)
+{
+
+ /* create a temp error distribution array */
+ int gcPix;
+ int y;
+ int col;
+ int *err_dist_l0, *err_dist_l1, *err_dist_l2, distrib_error;
+ int width_3 = update_region->width + 3;
+ char *y8buf;
+ int x_offset = 0;
+
+ /* prime a few elements the error distribution array */
+ for (y = 0; y < update_region->height; y++) {
+ /* Dithering the Y8 in sbuf to Y4 */
+ err_dist_l0 = err_dist + (width_3) * (y % 3);
+ err_dist_l1 = err_dist + (width_3) * ((y + 1) % 3);
+ err_dist_l2 = err_dist + (width_3) * ((y + 2) % 3);
+
+ y8buf = update_region_virt_ptr + x_offset;
+
+ /* scan the line and convert the Y8 to Y4 */
+ for (col = 1; col <= update_region->width; col++) {
+ gcPix = *(err_dist_l0 + col) + *y8buf;
+
+ if (gcPix > 255)
+ gcPix = 255;
+ else if (gcPix < 0)
+ gcPix = 0;
+
+ distrib_error = (*y8buf - (gcPix & 0xf0)) >> 3;
+
+ *y8buf++ = gcPix & 0xf0;
+
+ /* modify the error distribution buffer */
+ *(err_dist_l0 + col + 2) += distrib_error;
+ *(err_dist_l1 + col + 1) += distrib_error;
+ *(err_dist_l0 + col + 1) += distrib_error;
+ *(err_dist_l1 + col - 1) += distrib_error;
+ *(err_dist_l1 + col) += distrib_error;
+ *(err_dist_l2 + col) = distrib_error;
+ }
+ x_offset += update_region_stride;
+ }
+
+ flush_cache_all();
+ outer_flush_range(update_region_phys_ptr, update_region_phys_ptr +
+ update_region->height * update_region->width);
+}
+
+static int __init mxc_epdc_fb_init(void)
+{
+ return platform_driver_register(&mxc_epdc_fb_driver);
+}
+late_initcall(mxc_epdc_fb_init);
+
+static void __exit mxc_epdc_fb_exit(void)
+{
+ platform_driver_unregister(&mxc_epdc_fb_driver);
+}
+module_exit(mxc_epdc_fb_exit);
+
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC EPDC framebuffer driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("fb");
diff --git a/drivers/video/fbdev/mxc/mxc_epdc_v2_fb.c b/drivers/video/fbdev/mxc/mxc_epdc_v2_fb.c
new file mode 100644
index 000000000000..b908ad79689e
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_epdc_v2_fb.c
@@ -0,0 +1,6833 @@
+/*
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+/*
+ * Based on STMP378X LCDIF
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+#include <linux/busfreq-imx.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+#include <linux/cpufreq.h>
+#include <linux/firmware.h>
+#include <linux/kthread.h>
+#include <linux/dmaengine.h>
+#include <linux/pxp_dma.h>
+#include <linux/pm_runtime.h>
+#include <linux/mxcfb.h>
+#include <linux/mxcfb_epdc.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/max17135.h>
+#include <linux/fsl_devices.h>
+#include <linux/bitops.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/dma-imx.h>
+#include <asm/cacheflush.h>
+
+#include "epdc_v2_regs.h"
+
+#define EPDC_STANDARD_MODE
+
+#define USE_PS_AS_OUTPUT
+
+/*
+ * Enable this define to have a default panel
+ * loaded during driver initialization
+ */
+/*#define DEFAULT_PANEL_HW_INIT*/
+
+#define SG_NUM 14 /* 2+4+4+4 */
+#define NUM_SCREENS_MIN 2
+
+#define EPDC_V1_NUM_LUTS 16
+#define EPDC_V1_MAX_NUM_UPDATES 20
+#define EPDC_V2_NUM_LUTS 64
+#define EPDC_V2_MAX_NUM_UPDATES 64
+#define EPDC_MAX_NUM_BUFFERS 2
+#define INVALID_LUT (-1)
+#define DRY_RUN_NO_LUT 100
+
+/* Maximum update buffer image width due to v2.0 and v2.1 errata ERR005313. */
+#define EPDC_V2_MAX_UPDATE_WIDTH 2047
+#define EPDC_V2_ROTATION_ALIGNMENT 8
+
+#define DEFAULT_TEMP_INDEX 0
+#define DEFAULT_TEMP 20 /* room temp in deg Celsius */
+
+#define INIT_UPDATE_MARKER 0x12345678
+#define PAN_UPDATE_MARKER 0x12345679
+
+#define POWER_STATE_OFF 0
+#define POWER_STATE_ON 1
+
+#define MERGE_OK 0
+#define MERGE_FAIL 1
+#define MERGE_BLOCK 2
+
+static u64 used_luts = 0x1; /* do not use LUT0 */
+static unsigned long default_bpp = 16;
+
+struct update_marker_data {
+ struct list_head full_list;
+ struct list_head upd_list;
+ u32 update_marker;
+ struct completion update_completion;
+ int lut_num;
+ bool collision_test;
+ bool waiting;
+};
+
+struct update_desc_list {
+ struct list_head list;
+ struct mxcfb_update_data upd_data;/* Update parameters */
+ u32 epdc_offs; /* Added to buffer ptr to resolve alignment */
+ u32 epdc_stride; /* Depends on rotation & whether we skip PxP */
+ struct list_head upd_marker_list; /* List of markers for this update */
+ u32 update_order; /* Numeric ordering value for update */
+};
+
+/* This structure represents a list node containing both
+ * a memory region allocated as an output buffer for the PxP
+ * update processing task, and the update description (mode, region, etc.) */
+struct update_data_list {
+ struct list_head list;
+ dma_addr_t phys_addr; /* Pointer to phys address of processed Y buf */
+ void *virt_addr;
+ struct update_desc_list *update_desc;
+ int lut_num; /* Assigned before update is processed into working buffer */
+ u64 collision_mask; /* Set when update creates collision */
+ /* Mask of the LUTs the update collides with */
+};
+
+struct mxc_epdc_fb_data {
+ struct fb_info info;
+ struct fb_var_screeninfo epdc_fb_var; /* Internal copy of screeninfo
+ so we can sync changes to it */
+ u32 pseudo_palette[16];
+ char fw_str[24];
+ struct list_head list;
+ struct imx_epdc_fb_mode *cur_mode;
+ struct imx_epdc_fb_platform_data *pdata;
+ int blank;
+ u32 max_pix_size;
+ ssize_t map_size;
+ dma_addr_t phys_start;
+ void *virt_start;
+ u32 fb_offset;
+ int default_bpp;
+ int native_width;
+ int native_height;
+ int num_screens;
+ int epdc_irq;
+ struct device *dev;
+ int power_state;
+ int wait_for_powerdown;
+ struct completion powerdown_compl;
+ struct clk *epdc_clk_axi;
+ struct clk *epdc_clk_pix;
+ struct regulator *display_regulator;
+ struct regulator *vcom_regulator;
+ struct regulator *v3p3_regulator;
+ bool fw_default_load;
+ int rev;
+
+ /* FB elements related to EPDC updates */
+ int num_luts;
+ int max_num_updates;
+ bool in_init;
+ bool hw_ready;
+ bool hw_initializing;
+ bool waiting_for_idle;
+ u32 auto_mode;
+ u32 upd_scheme;
+ struct list_head upd_pending_list;
+ struct list_head upd_buf_queue;
+ struct list_head upd_buf_free_list;
+ struct list_head upd_buf_collision_list;
+ struct update_data_list *cur_update;
+ struct mutex queue_mutex;
+ int trt_entries;
+ int temp_index;
+ u8 *temp_range_bounds;
+ struct mxcfb_waveform_modes wv_modes;
+ bool wv_modes_update;
+ bool waveform_is_advanced;
+ u32 *waveform_buffer_virt;
+ u32 waveform_buffer_phys;
+ u32 waveform_buffer_size;
+ u32 *working_buffer_virt;
+ u32 working_buffer_phys;
+ u32 working_buffer_size;
+ u32 *tmp_working_buffer_virt;
+ u32 tmp_working_buffer_phys;
+ dma_addr_t *phys_addr_updbuf;
+ void **virt_addr_updbuf;
+ u32 upd_buffer_num;
+ u32 max_num_buffers;
+ dma_addr_t phys_addr_copybuf; /* Phys address of copied update data */
+ void *virt_addr_copybuf; /* Used for PxP SW workaround */
+ dma_addr_t phys_addr_y4;
+ void *virt_addr_y4;
+ dma_addr_t phys_addr_y4c;
+ void *virt_addr_y4c;
+ dma_addr_t phys_addr_black;
+ void *virt_addr_black;
+ u32 order_cnt;
+ struct list_head full_marker_list;
+ u32 *lut_update_order; /* Array size = number of luts */
+ u64 epdc_colliding_luts;
+ u64 luts_complete_wb;
+ u64 luts_complete;
+ struct completion updates_done;
+ struct delayed_work epdc_done_work;
+ struct workqueue_struct *epdc_submit_workqueue;
+ struct work_struct epdc_submit_work;
+ struct workqueue_struct *epdc_intr_workqueue;
+ struct work_struct epdc_intr_work;
+ bool waiting_for_wb;
+ bool waiting_for_lut;
+ bool waiting_for_lut15;
+ struct completion update_res_free;
+ struct completion lut15_free;
+ struct completion eof_event;
+ int eof_sync_period;
+ struct mutex power_mutex;
+ bool powering_down;
+ bool updates_active;
+ int pwrdown_delay;
+ unsigned long tce_prevent;
+ bool restrict_width; /* work around rev >=2.0 width and
+ stride restriction */
+
+ /* FB elements related to PxP DMA */
+ struct completion pxp_tx_cmpl;
+ struct pxp_channel *pxp_chan;
+ struct pxp_config_data pxp_conf;
+ struct dma_async_tx_descriptor *txd;
+ dma_cookie_t cookie;
+ struct scatterlist sg[SG_NUM];
+ struct mutex pxp_mutex; /* protects access to PxP */
+
+ /* external mode or internal mode */
+ int epdc_wb_mode;
+ struct pxp_collision_info col_info;
+ u32 hist_status;
+
+ struct regmap *gpr;
+ u8 req_gpr;
+ u8 req_bit;
+};
+
+struct waveform_data_header {
+ unsigned int wi0;
+ unsigned int wi1;
+ unsigned int wi2;
+ unsigned int wi3;
+ unsigned int wi4;
+ unsigned int wi5;
+ unsigned int wi6;
+ unsigned int xwia:24;
+ unsigned int cs1:8;
+ unsigned int wmta:24;
+ unsigned int fvsn:8;
+ unsigned int luts:8;
+ unsigned int mc:8;
+ unsigned int trc:8;
+ unsigned int reserved0_0:8;
+ unsigned int eb:8;
+ unsigned int sb:8;
+ unsigned int reserved0_1:8;
+ unsigned int reserved0_2:8;
+ unsigned int reserved0_3:8;
+ unsigned int reserved0_4:8;
+ unsigned int reserved0_5:8;
+ unsigned int cs2:8;
+};
+
+struct mxcfb_waveform_data_file {
+ struct waveform_data_header wdh;
+ u32 *data; /* Temperature Range Table + Waveform Data */
+};
+
+#define WAVEFORM_HDR_LUT_ADVANCED_ALGO_MASK 0xc
+
+static struct fb_videomode ed060xh2c1mode = {
+ .name = "ED060XH2C1",
+ .refresh = 85,
+ .xres = 1024,
+ .yres = 758,
+ .pixclock = 40000000,
+ .left_margin = 12,
+ .right_margin = 76,
+ .upper_margin = 4,
+ .lower_margin = 5,
+ .hsync_len = 12,
+ .vsync_len = 2,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 30000000,
+ .left_margin = 8,
+ .right_margin = 164,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e060scm_mode = {
+ .name = "E060SCM",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 26666667,
+ .left_margin = 8,
+ .right_margin = 100,
+ .upper_margin = 4,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct imx_epdc_fb_mode panel_modes[] = {
+ {
+ &ed060xh2c1mode, /* struct fb_videomode *mode */
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 524, /* GDCLK_HP */
+ 327, /* GDSP_OFF */
+ 0, /* GDOE_OFF */
+ 19, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 465, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 9, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e060scm_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 419, /* gdclk_hp_offs */
+ 263, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 5, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+
+static struct imx_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+};
+
+void __iomem *epdc_v2_base;
+
+static struct mxc_epdc_fb_data *g_fb_data;
+
+/* forward declaration */
+static int mxc_epdc_fb_get_temp_index(struct mxc_epdc_fb_data *fb_data,
+ int temp);
+static void mxc_epdc_fb_flush_updates(struct mxc_epdc_fb_data *fb_data);
+static int mxc_epdc_fb_blank(int blank, struct fb_info *info);
+static int mxc_epdc_fb_init_hw(struct fb_info *info);
+static int pxp_legacy_process(struct mxc_epdc_fb_data *fb_data,
+ u32 src_width, u32 src_height,
+ struct mxcfb_rect *update_region);
+static int pxp_process_dithering(struct mxc_epdc_fb_data *fb_data,
+ struct mxcfb_rect *update_region);
+static int pxp_wfe_a_process(struct mxc_epdc_fb_data *fb_data,
+ struct mxcfb_rect *update_region,
+ struct update_data_list *upd_data_list);
+static int pxp_wfe_b_process_update(struct mxc_epdc_fb_data *fb_data,
+ struct mxcfb_rect *update_region);
+static int pxp_wfe_a_process_clear_workingbuffer(struct mxc_epdc_fb_data *fb_data,
+ u32 src_width, u32 src_height);
+static int pxp_complete_update(struct mxc_epdc_fb_data *fb_data, u32 *hist_stat);
+
+static void draw_mode0(struct mxc_epdc_fb_data *fb_data);
+static bool is_free_list_full(struct mxc_epdc_fb_data *fb_data);
+
+static void do_dithering_processing_Y1_v1_0(
+ unsigned char *update_region_virt_ptr,
+ dma_addr_t update_region_phys_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist);
+static void do_dithering_processing_Y4_v1_0(
+ unsigned char *update_region_virt_ptr,
+ dma_addr_t update_region_phys_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist);
+static inline void epdc_set_used_lut(u64 used_bit);
+static inline void epdc_reset_used_lut(void);
+static int pxp_clear_wb_work_func(struct mxc_epdc_fb_data *fb_data);
+static int epdc_working_buffer_update(struct mxc_epdc_fb_data *fb_data,
+ struct update_data_list *upd_data_list,
+ struct mxcfb_rect *update_region);
+extern void pxp_get_collision_info(struct pxp_collision_info *info);
+
+#ifdef DEBUG
+static void dump_pxp_config(struct mxc_epdc_fb_data *fb_data,
+ struct pxp_config_data *pxp_conf)
+{
+ dev_info(fb_data->dev, "S0 fmt 0x%x",
+ pxp_conf->s0_param.pixel_fmt);
+ dev_info(fb_data->dev, "S0 width 0x%x",
+ pxp_conf->s0_param.width);
+ dev_info(fb_data->dev, "S0 height 0x%x",
+ pxp_conf->s0_param.height);
+ dev_info(fb_data->dev, "S0 ckey 0x%x",
+ pxp_conf->s0_param.color_key);
+ dev_info(fb_data->dev, "S0 ckey en 0x%x",
+ pxp_conf->s0_param.color_key_enable);
+
+ dev_info(fb_data->dev, "OL0 combine en 0x%x",
+ pxp_conf->ol_param[0].combine_enable);
+ dev_info(fb_data->dev, "OL0 fmt 0x%x",
+ pxp_conf->ol_param[0].pixel_fmt);
+ dev_info(fb_data->dev, "OL0 width 0x%x",
+ pxp_conf->ol_param[0].width);
+ dev_info(fb_data->dev, "OL0 height 0x%x",
+ pxp_conf->ol_param[0].height);
+ dev_info(fb_data->dev, "OL0 ckey 0x%x",
+ pxp_conf->ol_param[0].color_key);
+ dev_info(fb_data->dev, "OL0 ckey en 0x%x",
+ pxp_conf->ol_param[0].color_key_enable);
+ dev_info(fb_data->dev, "OL0 alpha 0x%x",
+ pxp_conf->ol_param[0].global_alpha);
+ dev_info(fb_data->dev, "OL0 alpha en 0x%x",
+ pxp_conf->ol_param[0].global_alpha_enable);
+ dev_info(fb_data->dev, "OL0 local alpha en 0x%x",
+ pxp_conf->ol_param[0].local_alpha_enable);
+
+ dev_info(fb_data->dev, "Out fmt 0x%x",
+ pxp_conf->out_param.pixel_fmt);
+ dev_info(fb_data->dev, "Out width 0x%x",
+ pxp_conf->out_param.width);
+ dev_info(fb_data->dev, "Out height 0x%x",
+ pxp_conf->out_param.height);
+
+ dev_info(fb_data->dev,
+ "drect left 0x%x right 0x%x width 0x%x height 0x%x",
+ pxp_conf->proc_data.drect.left, pxp_conf->proc_data.drect.top,
+ pxp_conf->proc_data.drect.width,
+ pxp_conf->proc_data.drect.height);
+ dev_info(fb_data->dev,
+ "srect left 0x%x right 0x%x width 0x%x height 0x%x",
+ pxp_conf->proc_data.srect.left, pxp_conf->proc_data.srect.top,
+ pxp_conf->proc_data.srect.width,
+ pxp_conf->proc_data.srect.height);
+ dev_info(fb_data->dev, "Scaling en 0x%x", pxp_conf->proc_data.scaling);
+ dev_info(fb_data->dev, "HFlip en 0x%x", pxp_conf->proc_data.hflip);
+ dev_info(fb_data->dev, "VFlip en 0x%x", pxp_conf->proc_data.vflip);
+ dev_info(fb_data->dev, "Rotation 0x%x", pxp_conf->proc_data.rotate);
+ dev_info(fb_data->dev, "BG Color 0x%x", pxp_conf->proc_data.bgcolor);
+}
+
+static void dump_epdc_reg(void)
+{
+ printk(KERN_DEBUG "\n\n");
+ printk(KERN_DEBUG "EPDC_CTRL 0x%x\n", __raw_readl(EPDC_CTRL));
+ printk(KERN_DEBUG "EPDC_WVADDR 0x%x\n", __raw_readl(EPDC_WVADDR));
+ printk(KERN_DEBUG "EPDC_WB_ADDR 0x%x\n", __raw_readl(EPDC_WB_ADDR));
+ printk(KERN_DEBUG "EPDC_RES 0x%x\n", __raw_readl(EPDC_RES));
+ printk(KERN_DEBUG "EPDC_FORMAT 0x%x\n", __raw_readl(EPDC_FORMAT));
+ printk(KERN_DEBUG "EPDC_FIFOCTRL 0x%x\n", __raw_readl(EPDC_FIFOCTRL));
+ printk(KERN_DEBUG "EPDC_UPD_ADDR 0x%x\n", __raw_readl(EPDC_UPD_ADDR));
+ printk(KERN_DEBUG "EPDC_UPD_STRIDE 0x%x\n", __raw_readl(EPDC_UPD_STRIDE));
+ printk(KERN_DEBUG "EPDC_UPD_FIXED 0x%x\n", __raw_readl(EPDC_UPD_FIXED));
+ printk(KERN_DEBUG "EPDC_UPD_CORD 0x%x\n", __raw_readl(EPDC_UPD_CORD));
+ printk(KERN_DEBUG "EPDC_UPD_SIZE 0x%x\n", __raw_readl(EPDC_UPD_SIZE));
+ printk(KERN_DEBUG "EPDC_UPD_CTRL 0x%x\n", __raw_readl(EPDC_UPD_CTRL));
+ printk(KERN_DEBUG "EPDC_TEMP 0x%x\n", __raw_readl(EPDC_TEMP));
+ printk(KERN_DEBUG "EPDC_AUTOWV_LUT 0x%x\n", __raw_readl(EPDC_AUTOWV_LUT));
+ printk(KERN_DEBUG "EPDC_TCE_CTRL 0x%x\n", __raw_readl(EPDC_TCE_CTRL));
+ printk(KERN_DEBUG "EPDC_TCE_SDCFG 0x%x\n", __raw_readl(EPDC_TCE_SDCFG));
+ printk(KERN_DEBUG "EPDC_TCE_GDCFG 0x%x\n", __raw_readl(EPDC_TCE_GDCFG));
+ printk(KERN_DEBUG "EPDC_TCE_HSCAN1 0x%x\n", __raw_readl(EPDC_TCE_HSCAN1));
+ printk(KERN_DEBUG "EPDC_TCE_HSCAN2 0x%x\n", __raw_readl(EPDC_TCE_HSCAN2));
+ printk(KERN_DEBUG "EPDC_TCE_VSCAN 0x%x\n", __raw_readl(EPDC_TCE_VSCAN));
+ printk(KERN_DEBUG "EPDC_TCE_OE 0x%x\n", __raw_readl(EPDC_TCE_OE));
+ printk(KERN_DEBUG "EPDC_TCE_POLARITY 0x%x\n", __raw_readl(EPDC_TCE_POLARITY));
+ printk(KERN_DEBUG "EPDC_TCE_TIMING1 0x%x\n", __raw_readl(EPDC_TCE_TIMING1));
+ printk(KERN_DEBUG "EPDC_TCE_TIMING2 0x%x\n", __raw_readl(EPDC_TCE_TIMING2));
+ printk(KERN_DEBUG "EPDC_TCE_TIMING3 0x%x\n", __raw_readl(EPDC_TCE_TIMING3));
+ printk(KERN_DEBUG "EPDC_PIGEON_CTRL0 0x%x\n", __raw_readl(EPDC_PIGEON_CTRL0));
+ printk(KERN_DEBUG "EPDC_PIGEON_CTRL1 0x%x\n", __raw_readl(EPDC_PIGEON_CTRL1));
+ printk(KERN_DEBUG "EPDC_IRQ_MASK1 0x%x\n", __raw_readl(EPDC_IRQ_MASK1));
+ printk(KERN_DEBUG "EPDC_IRQ_MASK2 0x%x\n", __raw_readl(EPDC_IRQ_MASK2));
+ printk(KERN_DEBUG "EPDC_IRQ1 0x%x\n", __raw_readl(EPDC_IRQ1));
+ printk(KERN_DEBUG "EPDC_IRQ2 0x%x\n", __raw_readl(EPDC_IRQ2));
+ printk(KERN_DEBUG "EPDC_IRQ_MASK 0x%x\n", __raw_readl(EPDC_IRQ_MASK));
+ printk(KERN_DEBUG "EPDC_IRQ 0x%x\n", __raw_readl(EPDC_IRQ));
+ printk(KERN_DEBUG "EPDC_STATUS_LUTS 0x%x\n", __raw_readl(EPDC_STATUS_LUTS));
+ printk(KERN_DEBUG "EPDC_STATUS_LUTS2 0x%x\n", __raw_readl(EPDC_STATUS_LUTS2));
+ printk(KERN_DEBUG "EPDC_STATUS_NEXTLUT 0x%x\n", __raw_readl(EPDC_STATUS_NEXTLUT));
+ printk(KERN_DEBUG "EPDC_STATUS_COL1 0x%x\n", __raw_readl(EPDC_STATUS_COL));
+ printk(KERN_DEBUG "EPDC_STATUS_COL2 0x%x\n", __raw_readl(EPDC_STATUS_COL2));
+ printk(KERN_DEBUG "EPDC_STATUS 0x%x\n", __raw_readl(EPDC_STATUS));
+ printk(KERN_DEBUG "EPDC_UPD_COL_CORD 0x%x\n", __raw_readl(EPDC_UPD_COL_CORD));
+ printk(KERN_DEBUG "EPDC_UPD_COL_SIZE 0x%x\n", __raw_readl(EPDC_UPD_COL_SIZE));
+ printk(KERN_DEBUG "EPDC_DEBUG 0x%x\n", __raw_readl(EPDC_DEBUG));
+ printk(KERN_DEBUG "EPDC_DEBUG_LUT 0x%x\n", __raw_readl(EPDC_DEBUG_LUT));
+ printk(KERN_DEBUG "EPDC_HIST1_PARAM 0x%x\n", __raw_readl(EPDC_HIST1_PARAM));
+ printk(KERN_DEBUG "EPDC_HIST2_PARAM 0x%x\n", __raw_readl(EPDC_HIST2_PARAM));
+ printk(KERN_DEBUG "EPDC_HIST4_PARAM 0x%x\n", __raw_readl(EPDC_HIST4_PARAM));
+ printk(KERN_DEBUG "EPDC_HIST8_PARAM0 0x%x\n", __raw_readl(EPDC_HIST8_PARAM0));
+ printk(KERN_DEBUG "EPDC_HIST8_PARAM1 0x%x\n", __raw_readl(EPDC_HIST8_PARAM1));
+ printk(KERN_DEBUG "EPDC_HIST16_PARAM0 0x%x\n", __raw_readl(EPDC_HIST16_PARAM0));
+ printk(KERN_DEBUG "EPDC_HIST16_PARAM1 0x%x\n", __raw_readl(EPDC_HIST16_PARAM1));
+ printk(KERN_DEBUG "EPDC_HIST16_PARAM2 0x%x\n", __raw_readl(EPDC_HIST16_PARAM2));
+ printk(KERN_DEBUG "EPDC_HIST16_PARAM3 0x%x\n", __raw_readl(EPDC_HIST16_PARAM3));
+ printk(KERN_DEBUG "EPDC_GPIO 0x%x\n", __raw_readl(EPDC_GPIO));
+ printk(KERN_DEBUG "EPDC_VERSION 0x%x\n", __raw_readl(EPDC_VERSION));
+ printk(KERN_DEBUG "\n\n");
+}
+
+static void dump_update_data(struct device *dev,
+ struct update_data_list *upd_data_list)
+{
+ dev_info(dev,
+ "X = %d, Y = %d, Width = %d, Height = %d, WaveMode = %d, "
+ "LUT = %d, Coll Mask = 0x%llx, order = %d\n",
+ upd_data_list->update_desc->upd_data.update_region.left,
+ upd_data_list->update_desc->upd_data.update_region.top,
+ upd_data_list->update_desc->upd_data.update_region.width,
+ upd_data_list->update_desc->upd_data.update_region.height,
+ upd_data_list->update_desc->upd_data.waveform_mode,
+ upd_data_list->lut_num,
+ upd_data_list->collision_mask,
+ upd_data_list->update_desc->update_order);
+}
+
+static void dump_collision_list(struct mxc_epdc_fb_data *fb_data)
+{
+ struct update_data_list *plist;
+
+ dev_info(fb_data->dev, "Collision List:\n");
+ if (list_empty(&fb_data->upd_buf_collision_list))
+ dev_info(fb_data->dev, "Empty");
+ list_for_each_entry(plist, &fb_data->upd_buf_collision_list, list) {
+ dev_info(fb_data->dev, "Virt Addr = 0x%x, Phys Addr = 0x%x ",
+ (u32)plist->virt_addr, plist->phys_addr);
+ dump_update_data(fb_data->dev, plist);
+ }
+}
+
+static void dump_free_list(struct mxc_epdc_fb_data *fb_data)
+{
+ struct update_data_list *plist;
+
+ dev_info(fb_data->dev, "Free List:\n");
+ if (list_empty(&fb_data->upd_buf_free_list))
+ dev_info(fb_data->dev, "Empty");
+ list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
+ dev_info(fb_data->dev, "Virt Addr = 0x%x, Phys Addr = 0x%x ",
+ (u32)plist->virt_addr, plist->phys_addr);
+}
+
+static void dump_queue(struct mxc_epdc_fb_data *fb_data)
+{
+ struct update_data_list *plist;
+
+ dev_info(fb_data->dev, "Queue:\n");
+ if (list_empty(&fb_data->upd_buf_queue))
+ dev_info(fb_data->dev, "Empty");
+ list_for_each_entry(plist, &fb_data->upd_buf_queue, list) {
+ dev_info(fb_data->dev, "Virt Addr = 0x%x, Phys Addr = 0x%x ",
+ (u32)plist->virt_addr, plist->phys_addr);
+ dump_update_data(fb_data->dev, plist);
+ }
+}
+
+static void dump_desc_data(struct device *dev,
+ struct update_desc_list *upd_desc_list)
+{
+ dev_info(dev,
+ "X = %d, Y = %d, Width = %d, Height = %d, WaveMode = %d, "
+ "order = %d\n",
+ upd_desc_list->upd_data.update_region.left,
+ upd_desc_list->upd_data.update_region.top,
+ upd_desc_list->upd_data.update_region.width,
+ upd_desc_list->upd_data.update_region.height,
+ upd_desc_list->upd_data.waveform_mode,
+ upd_desc_list->update_order);
+}
+
+static void dump_pending_list(struct mxc_epdc_fb_data *fb_data)
+{
+ struct update_desc_list *plist;
+
+ dev_info(fb_data->dev, "Queue:\n");
+ if (list_empty(&fb_data->upd_pending_list))
+ dev_info(fb_data->dev, "Empty");
+ list_for_each_entry(plist, &fb_data->upd_pending_list, list)
+ dump_desc_data(fb_data->dev, plist);
+}
+
+static void dump_all_updates(struct mxc_epdc_fb_data *fb_data)
+{
+ dump_free_list(fb_data);
+ dump_queue(fb_data);
+ dump_collision_list(fb_data);
+ dev_info(fb_data->dev, "Current update being processed:\n");
+ if (fb_data->cur_update == NULL)
+ dev_info(fb_data->dev, "No current update\n");
+ else
+ dump_update_data(fb_data->dev, fb_data->cur_update);
+}
+
+static void dump_fw_header(struct device *dev,
+ struct mxcfb_waveform_data_file *fw)
+{
+ dev_dbg(dev, "Firmware Header:\n");
+ dev_dbg(dev, "wi0 0x%08x\n", fw->wdh.wi0);
+ dev_dbg(dev, "wi1 0x%08x\n", fw->wdh.wi1);
+ dev_dbg(dev, "wi2 0x%08x\n", fw->wdh.wi2);
+ dev_dbg(dev, "wi3 0x%08x\n", fw->wdh.wi3);
+ dev_dbg(dev, "wi4 0x%08x\n", fw->wdh.wi4);
+ dev_dbg(dev, "wi5 0x%08x\n", fw->wdh.wi5);
+ dev_dbg(dev, "wi6 0x%08x\n", fw->wdh.wi6);
+ dev_dbg(dev, "xwia:24 0x%06x\n", fw->wdh.xwia);
+ dev_dbg(dev, "cs1:8 0x%02x\n", fw->wdh.cs1);
+ dev_dbg(dev, "wmta:24 0x%06x\n", fw->wdh.wmta);
+ dev_dbg(dev, "fvsn:8 0x%02x\n", fw->wdh.fvsn);
+ dev_dbg(dev, "luts:8 0x%02x\n", fw->wdh.luts);
+ dev_dbg(dev, "mc:8 0x%02x\n", fw->wdh.mc);
+ dev_dbg(dev, "trc:8 0x%02x\n", fw->wdh.trc);
+ dev_dbg(dev, "reserved0_0 0x%02x\n", fw->wdh.reserved0_0);
+ dev_dbg(dev, "eb:8 0x%02x\n", fw->wdh.eb);
+ dev_dbg(dev, "sb:8 0x%02x\n", fw->wdh.sb);
+ dev_dbg(dev, "reserved0_1 0x%02x\n", fw->wdh.reserved0_1);
+ dev_dbg(dev, "reserved0_2 0x%02x\n", fw->wdh.reserved0_2);
+ dev_dbg(dev, "reserved0_3 0x%02x\n", fw->wdh.reserved0_3);
+ dev_dbg(dev, "reserved0_4 0x%02x\n", fw->wdh.reserved0_4);
+ dev_dbg(dev, "reserved0_5 0x%02x\n", fw->wdh.reserved0_5);
+ dev_dbg(dev, "cs2:8 0x%02x\n", fw->wdh.cs2);
+}
+
+#else
+static inline void dump_pxp_config(struct mxc_epdc_fb_data *fb_data,
+ struct pxp_config_data *pxp_conf) {}
+static inline void dump_epdc_reg(void) {}
+static inline void dump_update_data(struct device *dev,
+ struct update_data_list *upd_data_list) {}
+static inline void dump_collision_list(struct mxc_epdc_fb_data *fb_data) {}
+static inline void dump_free_list(struct mxc_epdc_fb_data *fb_data) {}
+static inline void dump_queue(struct mxc_epdc_fb_data *fb_data) {}
+static inline void dump_all_updates(struct mxc_epdc_fb_data *fb_data) {}
+static void dump_fw_header(struct device *dev,
+ struct mxcfb_waveform_data_file *fw) {}
+
+#endif
+
+
+/********************************************************
+ * Start Low-Level EPDC Functions
+ ********************************************************/
+
+static inline void epdc_lut_complete_intr(int rev, u32 lut_num, bool enable)
+{
+ if (rev < 20) {
+ if (enable)
+ __raw_writel(1 << lut_num, EPDC_IRQ_MASK_SET);
+ else
+ __raw_writel(1 << lut_num, EPDC_IRQ_MASK_CLEAR);
+ } else {
+ if (enable) {
+ if (lut_num < 32)
+ __raw_writel(1 << lut_num, EPDC_IRQ_MASK1_SET);
+ else
+ __raw_writel(1 << (lut_num - 32),
+ EPDC_IRQ_MASK2_SET);
+ } else {
+ if (lut_num < 32)
+ __raw_writel(1 << lut_num,
+ EPDC_IRQ_MASK1_CLEAR);
+ else
+ __raw_writel(1 << (lut_num - 32),
+ EPDC_IRQ_MASK2_CLEAR);
+ }
+ }
+}
+
+static inline void epdc_working_buf_intr(bool enable)
+{
+ if (enable)
+ __raw_writel(EPDC_IRQ_WB_CMPLT_IRQ, EPDC_IRQ_MASK_SET);
+ else
+ __raw_writel(EPDC_IRQ_WB_CMPLT_IRQ, EPDC_IRQ_MASK_CLEAR);
+}
+
+static inline void epdc_clear_working_buf_irq(void)
+{
+ __raw_writel(EPDC_IRQ_WB_CMPLT_IRQ | EPDC_IRQ_LUT_COL_IRQ,
+ EPDC_IRQ_CLEAR);
+}
+
+static inline void epdc_eof_intr(bool enable)
+{
+ if (enable)
+ __raw_writel(EPDC_IRQ_FRAME_END_IRQ, EPDC_IRQ_MASK_SET);
+ else
+ __raw_writel(EPDC_IRQ_FRAME_END_IRQ, EPDC_IRQ_MASK_CLEAR);
+}
+
+static inline void epdc_clear_eof_irq(void)
+{
+ __raw_writel(EPDC_IRQ_FRAME_END_IRQ, EPDC_IRQ_CLEAR);
+}
+
+static inline bool epdc_signal_eof(void)
+{
+ return (__raw_readl(EPDC_IRQ_MASK) & __raw_readl(EPDC_IRQ)
+ & EPDC_IRQ_FRAME_END_IRQ) ? true : false;
+}
+
+static inline void epdc_set_temp(u32 temp)
+{
+ int ret = 0;
+ /* used to store external panel temperature value */
+ unsigned int ext_temp, ext_temp_index = temp;
+
+ if (temp == DEFAULT_TEMP_INDEX) {
+ ret = max17135_reg_read(REG_MAX17135_EXT_TEMP, &ext_temp);
+ if (ret == 0) {
+ ext_temp = ext_temp >> 8;
+ dev_dbg(g_fb_data->dev, "the current external temperature is %d\n",
+ ext_temp);
+ ext_temp_index = mxc_epdc_fb_get_temp_index(g_fb_data, ext_temp);
+ }
+ }
+
+ __raw_writel(ext_temp_index, EPDC_TEMP);
+}
+
+static inline void epdc_set_screen_res(u32 width, u32 height)
+{
+ u32 val = (height << EPDC_RES_VERTICAL_OFFSET) | width;
+ __raw_writel(val, EPDC_RES);
+}
+
+static inline void epdc_set_update_addr(u32 addr)
+{
+#ifdef EPDC_STANDARD_MODE
+ __raw_writel(0, EPDC_UPD_ADDR);
+#else
+ __raw_writel(addr, EPDC_UPD_ADDR);
+#endif
+}
+
+static inline void epdc_set_update_coord(u32 x, u32 y)
+{
+ u32 val = (y << EPDC_UPD_CORD_YCORD_OFFSET) | x;
+ __raw_writel(val, EPDC_UPD_CORD);
+}
+
+static inline void epdc_set_update_dimensions(u32 width, u32 height)
+{
+ u32 val = (height << EPDC_UPD_SIZE_HEIGHT_OFFSET) | width;
+ __raw_writel(val, EPDC_UPD_SIZE);
+}
+
+static void epdc_set_update_waveform(struct mxcfb_waveform_modes *wv_modes)
+{
+ u32 val;
+
+#ifdef EPDC_STANDARD_MODE
+ return;
+#endif
+
+ /* Configure the auto-waveform look-up table based on waveform modes */
+
+ /* Entry 1 = DU, 2 = GC4, 3 = GC8, etc. */
+ val = (wv_modes->mode_du << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (0 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_du << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (1 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_gc4 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (2 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_gc8 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (3 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_gc16 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (4 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+ val = (wv_modes->mode_gc32 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (5 << EPDC_AUTOWV_LUT_ADDR_OFFSET);
+ __raw_writel(val, EPDC_AUTOWV_LUT);
+}
+
+static void epdc_set_update_stride(u32 stride)
+{
+#ifdef EPDC_STANDARD_MODE
+ __raw_writel(0, EPDC_UPD_STRIDE);
+#else
+ __raw_writel(stride, EPDC_UPD_STRIDE);
+#endif
+}
+
+static void epdc_submit_update(u32 lut_num, u32 waveform_mode, u32 update_mode,
+ bool use_dry_run, bool use_test_mode, u32 np_val)
+{
+ u32 reg_val = 0;
+
+ if (use_test_mode) {
+ reg_val |=
+ ((np_val << EPDC_UPD_FIXED_FIXNP_OFFSET) &
+ EPDC_UPD_FIXED_FIXNP_MASK) | EPDC_UPD_FIXED_FIXNP_EN;
+ reg_val |=
+ ((np_val << EPDC_UPD_FIXED_FIXCP_OFFSET) &
+ EPDC_UPD_FIXED_FIXCP_MASK) | EPDC_UPD_FIXED_FIXCP_EN;
+
+ __raw_writel(reg_val, EPDC_UPD_FIXED);
+
+ reg_val = EPDC_UPD_CTRL_USE_FIXED;
+ } else {
+ __raw_writel(reg_val, EPDC_UPD_FIXED);
+ }
+
+ if (waveform_mode == WAVEFORM_MODE_AUTO)
+ reg_val |= EPDC_UPD_CTRL_AUTOWV;
+ else
+ reg_val |= ((waveform_mode <<
+ EPDC_UPD_CTRL_WAVEFORM_MODE_OFFSET) &
+ EPDC_UPD_CTRL_WAVEFORM_MODE_MASK);
+
+ reg_val |= (use_dry_run ? EPDC_UPD_CTRL_DRY_RUN : 0) |
+ ((lut_num << EPDC_UPD_CTRL_LUT_SEL_OFFSET) &
+ EPDC_UPD_CTRL_LUT_SEL_MASK) |
+ update_mode;
+
+#ifdef EPDC_STANDARD_MODE
+ reg_val |= 0x80000000;
+
+ epdc_set_used_lut(lut_num);
+#endif
+ dump_epdc_reg();
+ __raw_writel(reg_val, EPDC_UPD_CTRL);
+}
+
+static inline bool epdc_is_lut_complete(int rev, u32 lut_num)
+{
+ u32 val;
+ bool is_compl;
+ if (rev < 20) {
+ val = __raw_readl(EPDC_IRQ);
+ is_compl = val & (1 << lut_num) ? true : false;
+ } else if (lut_num < 32) {
+ val = __raw_readl(EPDC_IRQ1);
+ is_compl = val & (1 << lut_num) ? true : false;
+ } else {
+ val = __raw_readl(EPDC_IRQ2);
+ is_compl = val & (1 << (lut_num - 32)) ? true : false;
+ }
+
+ return is_compl;
+}
+
+static inline void epdc_clear_lut_complete_irq(int rev, u32 lut_num)
+{
+ if (rev < 20)
+ __raw_writel(1 << lut_num, EPDC_IRQ_CLEAR);
+ else if (lut_num < 32)
+ __raw_writel(1 << lut_num, EPDC_IRQ1_CLEAR);
+ else
+ __raw_writel(1 << (lut_num - 32), EPDC_IRQ2_CLEAR);
+}
+
+static inline bool epdc_is_lut_active(u32 lut_num)
+{
+ u32 val;
+ bool is_active;
+
+ if (lut_num < 32) {
+ val = __raw_readl(EPDC_STATUS_LUTS);
+ is_active = val & (1 << lut_num) ? true : false;
+ } else {
+ val = __raw_readl(EPDC_STATUS_LUTS2);
+ is_active = val & (1 << (lut_num - 32)) ? true : false;
+ }
+
+ return is_active;
+}
+
+static inline bool epdc_any_luts_active(int rev)
+{
+ bool any_active;
+
+ if (rev < 20)
+ any_active = __raw_readl(EPDC_STATUS_LUTS) ? true : false;
+ else
+ any_active = (__raw_readl(EPDC_STATUS_LUTS) |
+ __raw_readl(EPDC_STATUS_LUTS2)) ? true : false;
+
+ return any_active;
+}
+
+static inline bool epdc_any_luts_real_available(void)
+{
+ if ((__raw_readl(EPDC_STATUS_LUTS) != 0xfffffffe) ||
+ (__raw_readl(EPDC_STATUS_LUTS2) != ~0UL))
+ return true;
+ else
+ return false;
+}
+
+static inline bool epdc_any_luts_available(void)
+{
+#ifdef EPDC_STANDARD_MODE
+ if (((u32)used_luts != ~0UL) || ((u32)(used_luts >> 32) != ~0UL))
+ return 1;
+ else
+ return 0;
+#else
+ bool luts_available =
+ (__raw_readl(EPDC_STATUS_NEXTLUT) &
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_VALID) ? true : false;
+ return luts_available;
+#endif
+}
+
+static inline int epdc_get_next_lut(void)
+{
+ u32 val =
+ __raw_readl(EPDC_STATUS_NEXTLUT) &
+ EPDC_STATUS_NEXTLUT_NEXT_LUT_MASK;
+ return val;
+}
+
+static inline void epdc_set_used_lut(u64 used_bit)
+{
+ used_luts |= (u64)1 << used_bit;
+}
+
+static inline void epdc_reset_used_lut(void)
+{
+ used_luts = 0x1;
+}
+
+#ifdef EPDC_STANDARD_MODE
+/*
+ * in previous flow, when all LUTs are used, the LUT cleanup operation
+ * need to wait for all the LUT to finish, it will not happen util last LUT
+ * is done. while in new flow, the cleanup operation does not need to wait
+ * for all LUTs to finish, instead it can start when there's LUT's done.
+ * The saved time is multiple LUT operation time.
+ */
+static int epdc_choose_next_lut(struct mxc_epdc_fb_data *fb_data, int *next_lut)
+{
+ while (!epdc_any_luts_available()) {
+ u64 luts_complete = fb_data->luts_complete;
+ pxp_clear_wb_work_func(fb_data);
+ used_luts &= ~luts_complete;
+ fb_data->luts_complete &= ~luts_complete;
+ }
+
+ used_luts |= 0x1;
+
+ if ((u32)used_luts != ~0UL)
+ *next_lut = ffz((u32)used_luts);
+ else if ((u32)(used_luts >> 32) != ~0UL)
+ *next_lut = ffz((u32)(used_luts >> 32)) + 32;
+
+ return 0;
+}
+#else
+static int epdc_choose_next_lut(struct mxc_epdc_fb_data *fb_data, int *next_lut)
+{
+ u64 luts_status, unprocessed_luts, used_luts;
+ /* Available LUTs are reduced to 16 in 5-bit waveform mode */
+ bool format_p5n = ((__raw_readl(EPDC_FORMAT) &
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_MASK) ==
+ EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N);
+
+ luts_status = __raw_readl(EPDC_STATUS_LUTS);
+ if ((fb_data->rev < 20) || format_p5n)
+ luts_status &= 0xFFFF;
+ else
+ luts_status |= ((u64)__raw_readl(EPDC_STATUS_LUTS2) << 32);
+
+ if (fb_data->rev < 20) {
+ unprocessed_luts = __raw_readl(EPDC_IRQ) & 0xFFFF;
+ } else {
+ unprocessed_luts = __raw_readl(EPDC_IRQ1) |
+ ((u64)__raw_readl(EPDC_IRQ2) << 32);
+ if (format_p5n)
+ unprocessed_luts &= 0xFFFF;
+ }
+
+ /*
+ * Note on unprocessed_luts: There is a race condition
+ * where a LUT completes, but has not been processed by
+ * IRQ handler workqueue, and then a new update request
+ * attempts to use that LUT. We prevent that here by
+ * ensuring that the LUT we choose doesn't have its IRQ
+ * bit set (indicating it has completed but not yet been
+ * processed).
+ */
+ used_luts = luts_status | unprocessed_luts;
+
+ /*
+ * Selecting a LUT to minimize incidence of TCE Underrun Error
+ * --------------------------------------------------------
+ * We want to find the lowest order LUT that is of greater
+ * order than all other active LUTs. If highest order LUT
+ * is active, then we want to choose the lowest order
+ * available LUT.
+ *
+ * NOTE: For EPDC version 2.0 and later, TCE Underrun error
+ * bug is fixed, so it doesn't matter which LUT is used.
+ */
+
+ if ((fb_data->rev < 20) || format_p5n) {
+ *next_lut = fls64(used_luts);
+ if (*next_lut > 15)
+ *next_lut = ffz(used_luts);
+ } else {
+ if ((u32)used_luts != ~0UL)
+ *next_lut = ffz((u32)used_luts);
+ else if ((u32)(used_luts >> 32) != ~0UL)
+ *next_lut = ffz((u32)(used_luts >> 32)) + 32;
+ else
+ *next_lut = INVALID_LUT;
+ }
+
+ if (used_luts & 0x8000)
+ return 1;
+ else
+ return 0;
+}
+#endif
+
+static inline bool epdc_is_working_buffer_busy(void)
+{
+ u32 val = __raw_readl(EPDC_STATUS);
+ bool is_busy = (val & EPDC_STATUS_WB_BUSY) ? true : false;
+
+ return is_busy;
+}
+
+static inline bool epdc_is_working_buffer_complete(void)
+{
+ u32 val = __raw_readl(EPDC_IRQ);
+ bool is_compl = (val & EPDC_IRQ_WB_CMPLT_IRQ) ? true : false;
+
+ return is_compl;
+}
+
+static inline bool epdc_is_lut_cancelled(void)
+{
+ u32 val = __raw_readl(EPDC_STATUS);
+ bool is_void = (val & EPDC_STATUS_UPD_VOID) ? true : false;
+
+ return is_void;
+}
+
+static inline bool epdc_is_collision(void)
+{
+ u32 val = __raw_readl(EPDC_IRQ);
+ return (val & EPDC_IRQ_LUT_COL_IRQ) ? true : false;
+}
+
+static inline u64 epdc_get_colliding_luts(int rev)
+{
+ u32 val = __raw_readl(EPDC_STATUS_COL);
+ if (rev >= 20)
+ val |= (u64)__raw_readl(EPDC_STATUS_COL2) << 32;
+ return val;
+}
+
+static void epdc_set_horizontal_timing(u32 horiz_start, u32 horiz_end,
+ u32 hsync_width, u32 hsync_line_length)
+{
+ u32 reg_val =
+ ((hsync_width << EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET) &
+ EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK)
+ | ((hsync_line_length << EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET) &
+ EPDC_TCE_HSCAN1_LINE_SYNC_MASK);
+ __raw_writel(reg_val, EPDC_TCE_HSCAN1);
+
+ reg_val =
+ ((horiz_start << EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET) &
+ EPDC_TCE_HSCAN2_LINE_BEGIN_MASK)
+ | ((horiz_end << EPDC_TCE_HSCAN2_LINE_END_OFFSET) &
+ EPDC_TCE_HSCAN2_LINE_END_MASK);
+ __raw_writel(reg_val, EPDC_TCE_HSCAN2);
+}
+
+static void epdc_set_vertical_timing(u32 vert_start, u32 vert_end,
+ u32 vsync_width)
+{
+ u32 reg_val =
+ ((vert_start << EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET) &
+ EPDC_TCE_VSCAN_FRAME_BEGIN_MASK)
+ | ((vert_end << EPDC_TCE_VSCAN_FRAME_END_OFFSET) &
+ EPDC_TCE_VSCAN_FRAME_END_MASK)
+ | ((vsync_width << EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET) &
+ EPDC_TCE_VSCAN_FRAME_SYNC_MASK);
+ __raw_writel(reg_val, EPDC_TCE_VSCAN);
+}
+
+static void epdc_init_settings(struct mxc_epdc_fb_data *fb_data)
+{
+ struct imx_epdc_fb_mode *epdc_mode = fb_data->cur_mode;
+ struct fb_var_screeninfo *screeninfo = &fb_data->epdc_fb_var;
+ u32 reg_val;
+ int num_ce;
+#ifndef EPDC_STANDARD_MODE
+ int i;
+#endif
+ int j;
+ unsigned char *bb_p;
+
+ /* Enable clocks to access EPDC regs */
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+
+ /* Reset */
+ __raw_writel(EPDC_CTRL_SFTRST, EPDC_CTRL_SET);
+ while (!(__raw_readl(EPDC_CTRL) & EPDC_CTRL_CLKGATE))
+ ;
+ __raw_writel(EPDC_CTRL_SFTRST, EPDC_CTRL_CLEAR);
+
+ /* Enable clock gating (clear to enable) */
+ __raw_writel(EPDC_CTRL_CLKGATE, EPDC_CTRL_CLEAR);
+ while (__raw_readl(EPDC_CTRL) & (EPDC_CTRL_SFTRST | EPDC_CTRL_CLKGATE))
+ ;
+
+ /* EPDC_CTRL */
+ reg_val = __raw_readl(EPDC_CTRL);
+ reg_val &= ~EPDC_CTRL_UPD_DATA_SWIZZLE_MASK;
+#ifdef EPDC_STANDARD_MODE
+ reg_val |= EPDC_CTRL_UPD_DATA_SWIZZLE_ALL_BYTES_SWAP;
+#else
+ reg_val |= EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP;
+#endif
+ reg_val &= ~EPDC_CTRL_LUT_DATA_SWIZZLE_MASK;
+ reg_val |= EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP;
+ __raw_writel(reg_val, EPDC_CTRL_SET);
+
+ /* EPDC_FORMAT - 2bit TFT and 4bit Buf pixel format */
+ reg_val = EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT
+#ifdef EPDC_STANDARD_MODE
+ | EPDC_FORMAT_WB_TYPE_WB_EXTERNAL16
+#endif
+ | EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N
+ | ((0x0 << EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET) &
+ EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK);
+ __raw_writel(reg_val, EPDC_FORMAT);
+
+#ifdef EPDC_STANDARD_MODE
+ reg_val = 0;
+ if (fb_data->waveform_is_advanced) {
+ reg_val =
+ ((EPDC_WB_FIELD_USAGE_PTS << EPDC_WB_FIELD_USAGE_OFFSET) &
+ EPDC_WB_FIELD_USAGE_MASK)
+ | ((0x8 << EPDC_WB_FIELD_FROM_OFFSET) &
+ EPDC_WB_FIELD_FROM_MASK)
+ | ((0x8 << EPDC_WB_FIELD_TO_OFFSET) &
+ EPDC_WB_FIELD_TO_MASK)
+ | ((0x1 << EPDC_WB_FIELD_LEN_OFFSET) &
+ EPDC_WB_FIELD_LEN_MASK);
+ }
+ __raw_writel(reg_val, EPDC_WB_FIELD3);
+#endif
+
+ /* EPDC_FIFOCTRL (disabled) */
+ reg_val =
+ ((100 << EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET) &
+ EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK)
+ | ((200 << EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET) &
+ EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK)
+ | ((100 << EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET) &
+ EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK);
+ __raw_writel(reg_val, EPDC_FIFOCTRL);
+
+ /* EPDC_TEMP - Use default temp to get index */
+ epdc_set_temp(mxc_epdc_fb_get_temp_index(fb_data, DEFAULT_TEMP));
+
+ /* EPDC_RES */
+ epdc_set_screen_res(epdc_mode->vmode->xres, epdc_mode->vmode->yres);
+
+#ifndef EPDC_STANDARD_MODE
+ /* EPDC_AUTOWV_LUT */
+ /* Initialize all auto-wavefrom look-up values to 2 - GC16 */
+ for (i = 0; i < 8; i++)
+ __raw_writel((2 << EPDC_AUTOWV_LUT_DATA_OFFSET) |
+ (i << EPDC_AUTOWV_LUT_ADDR_OFFSET), EPDC_AUTOWV_LUT);
+#endif
+
+ /*
+ * EPDC_TCE_CTRL
+ * VSCAN_HOLDOFF = 4
+ * VCOM_MODE = MANUAL
+ * VCOM_VAL = 0
+ * DDR_MODE = DISABLED
+ * LVDS_MODE_CE = DISABLED
+ * LVDS_MODE = DISABLED
+ * DUAL_SCAN = DISABLED
+ * SDDO_WIDTH = 8bit
+ * PIXELS_PER_SDCLK = 4
+ */
+ reg_val =
+ ((epdc_mode->vscan_holdoff << EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET) &
+ EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK)
+ | EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4;
+ __raw_writel(reg_val, EPDC_TCE_CTRL);
+
+ /* EPDC_TCE_HSCAN */
+ epdc_set_horizontal_timing(screeninfo->left_margin,
+ screeninfo->right_margin,
+ screeninfo->hsync_len,
+ screeninfo->hsync_len);
+
+ /* EPDC_TCE_VSCAN */
+ epdc_set_vertical_timing(screeninfo->upper_margin,
+ screeninfo->lower_margin,
+ screeninfo->vsync_len);
+
+ /* EPDC_TCE_OE */
+ reg_val =
+ ((epdc_mode->sdoed_width << EPDC_TCE_OE_SDOED_WIDTH_OFFSET) &
+ EPDC_TCE_OE_SDOED_WIDTH_MASK)
+ | ((epdc_mode->sdoed_delay << EPDC_TCE_OE_SDOED_DLY_OFFSET) &
+ EPDC_TCE_OE_SDOED_DLY_MASK)
+ | ((epdc_mode->sdoez_width << EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET) &
+ EPDC_TCE_OE_SDOEZ_WIDTH_MASK)
+ | ((epdc_mode->sdoez_delay << EPDC_TCE_OE_SDOEZ_DLY_OFFSET) &
+ EPDC_TCE_OE_SDOEZ_DLY_MASK);
+ __raw_writel(reg_val, EPDC_TCE_OE);
+
+ /* EPDC_TCE_TIMING1 */
+ __raw_writel(0x0, EPDC_TCE_TIMING1);
+
+ /* EPDC_TCE_TIMING2 */
+ reg_val =
+ ((epdc_mode->gdclk_hp_offs << EPDC_TCE_TIMING2_GDCLK_HP_OFFSET) &
+ EPDC_TCE_TIMING2_GDCLK_HP_MASK)
+ | ((epdc_mode->gdsp_offs << EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET) &
+ EPDC_TCE_TIMING2_GDSP_OFFSET_MASK);
+ __raw_writel(reg_val, EPDC_TCE_TIMING2);
+
+ /* EPDC_TCE_TIMING3 */
+ reg_val =
+ ((epdc_mode->gdoe_offs << EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET) &
+ EPDC_TCE_TIMING3_GDOE_OFFSET_MASK)
+ | ((epdc_mode->gdclk_offs << EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET) &
+ EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK);
+ __raw_writel(reg_val, EPDC_TCE_TIMING3);
+
+ /*
+ * EPDC_TCE_SDCFG
+ * SDCLK_HOLD = 1
+ * SDSHR = 1
+ * NUM_CE = 1
+ * SDDO_REFORMAT = FLIP_PIXELS
+ * SDDO_INVERT = DISABLED
+ * PIXELS_PER_CE = display horizontal resolution
+ */
+ num_ce = epdc_mode->num_ce;
+ if (num_ce == 0)
+ num_ce = 1;
+ reg_val = EPDC_TCE_SDCFG_SDCLK_HOLD | EPDC_TCE_SDCFG_SDSHR
+ | ((num_ce << EPDC_TCE_SDCFG_NUM_CE_OFFSET) &
+ EPDC_TCE_SDCFG_NUM_CE_MASK)
+ | EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS
+ | ((epdc_mode->vmode->xres/num_ce << EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET) &
+ EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK);
+ __raw_writel(reg_val, EPDC_TCE_SDCFG);
+
+ /*
+ * EPDC_TCE_GDCFG
+ * GDRL = 1
+ * GDOE_MODE = 0;
+ * GDSP_MODE = 0;
+ */
+ reg_val = EPDC_TCE_SDCFG_GDRL;
+ __raw_writel(reg_val, EPDC_TCE_GDCFG);
+
+ /*
+ * EPDC_TCE_POLARITY
+ * SDCE_POL = ACTIVE LOW
+ * SDLE_POL = ACTIVE HIGH
+ * SDOE_POL = ACTIVE HIGH
+ * GDOE_POL = ACTIVE HIGH
+ * GDSP_POL = ACTIVE LOW
+ */
+ reg_val = EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH
+ | EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH
+ | EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH;
+ __raw_writel(reg_val, EPDC_TCE_POLARITY);
+
+ /* EPDC_IRQ_MASK */
+ __raw_writel(EPDC_IRQ_TCE_UNDERRUN_IRQ, EPDC_IRQ_MASK);
+
+ /*
+ * EPDC_GPIO
+ * PWRCOM = ?
+ * PWRCTRL = ?
+ * BDR = ?
+ */
+ reg_val = ((0 << EPDC_GPIO_PWRCTRL_OFFSET) & EPDC_GPIO_PWRCTRL_MASK)
+ | ((0 << EPDC_GPIO_BDR_OFFSET) & EPDC_GPIO_BDR_MASK);
+ __raw_writel(reg_val, EPDC_GPIO);
+
+ __raw_writel(fb_data->waveform_buffer_phys, EPDC_WVADDR);
+ __raw_writel(fb_data->working_buffer_phys, EPDC_WB_ADDR);
+ __raw_writel(fb_data->working_buffer_phys, EPDC_WB_ADDR_TCE);
+
+ bb_p = (unsigned char *)fb_data->virt_addr_black;
+ for (j = 0; j < fb_data->cur_mode->vmode->xres * fb_data->cur_mode->vmode->yres; j++) {
+ *bb_p = 0x0;
+ bb_p++;
+ }
+
+ /* Disable clock */
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+}
+
+static void epdc_powerup(struct mxc_epdc_fb_data *fb_data)
+{
+ int ret = 0;
+ mutex_lock(&fb_data->power_mutex);
+
+ /*
+ * If power down request is pending, clear
+ * powering_down to cancel the request.
+ */
+ if (fb_data->powering_down)
+ fb_data->powering_down = false;
+
+ if (fb_data->power_state == POWER_STATE_ON) {
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+
+ dev_dbg(fb_data->dev, "EPDC Powerup\n");
+
+ fb_data->updates_active = true;
+
+ /* Enable the v3p3 regulator */
+ ret = regulator_enable(fb_data->v3p3_regulator);
+ if (IS_ERR((void *)ret)) {
+ dev_err(fb_data->dev, "Unable to enable V3P3 regulator."
+ "err = 0x%x\n", ret);
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+
+ msleep(1);
+
+ pm_runtime_get_sync(fb_data->dev);
+
+ /* Enable clocks to EPDC */
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+
+ __raw_writel(EPDC_CTRL_CLKGATE, EPDC_CTRL_CLEAR);
+
+ /* Enable power to the EPD panel */
+ ret = regulator_enable(fb_data->display_regulator);
+ if (IS_ERR((void *)ret)) {
+ dev_err(fb_data->dev, "Unable to enable DISPLAY regulator."
+ "err = 0x%x\n", ret);
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+ ret = regulator_enable(fb_data->vcom_regulator);
+ if (IS_ERR((void *)ret)) {
+ dev_err(fb_data->dev, "Unable to enable VCOM regulator."
+ "err = 0x%x\n", ret);
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+
+ fb_data->power_state = POWER_STATE_ON;
+
+ mutex_unlock(&fb_data->power_mutex);
+}
+
+static void epdc_powerdown(struct mxc_epdc_fb_data *fb_data)
+{
+ mutex_lock(&fb_data->power_mutex);
+
+ /* If powering_down has been cleared, a powerup
+ * request is pre-empting this powerdown request.
+ */
+ if (!fb_data->powering_down
+ || (fb_data->power_state == POWER_STATE_OFF)) {
+ mutex_unlock(&fb_data->power_mutex);
+ return;
+ }
+
+ dev_dbg(fb_data->dev, "EPDC Powerdown\n");
+
+ /* Disable power to the EPD panel */
+ regulator_disable(fb_data->vcom_regulator);
+ regulator_disable(fb_data->display_regulator);
+
+ /* Disable clocks to EPDC */
+ __raw_writel(EPDC_CTRL_CLKGATE, EPDC_CTRL_SET);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+
+ pm_runtime_put_sync_suspend(fb_data->dev);
+
+ /* turn off the V3p3 */
+ regulator_disable(fb_data->v3p3_regulator);
+
+ fb_data->power_state = POWER_STATE_OFF;
+ fb_data->powering_down = false;
+
+ if (fb_data->wait_for_powerdown) {
+ fb_data->wait_for_powerdown = false;
+ complete(&fb_data->powerdown_compl);
+ }
+
+ mutex_unlock(&fb_data->power_mutex);
+}
+
+static void epdc_init_sequence(struct mxc_epdc_fb_data *fb_data)
+{
+ /* Initialize EPDC, passing pointer to EPDC registers */
+ epdc_init_settings(fb_data);
+
+ fb_data->in_init = true;
+ epdc_powerup(fb_data);
+ draw_mode0(fb_data);
+ /* Force power down event */
+ fb_data->powering_down = true;
+ epdc_powerdown(fb_data);
+ fb_data->updates_active = false;
+}
+
+static int mxc_epdc_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ u32 len;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ if (offset < info->fix.smem_len) {
+ /* mapping framebuffer memory */
+ len = info->fix.smem_len - offset;
+ vma->vm_pgoff = (info->fix.smem_start + offset) >> PAGE_SHIFT;
+ } else
+ return -EINVAL;
+
+ len = PAGE_ALIGN(len);
+ if (vma->vm_end - vma->vm_start > len)
+ return -EINVAL;
+
+ /* make buffers bufferable */
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+ dev_dbg(info->device, "mmap remap_pfn_range failed\n");
+ return -ENOBUFS;
+ }
+
+ return 0;
+}
+
+static inline u_int _chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int mxc_epdc_fb_setcolreg(u_int regno, u_int red, u_int green,
+ u_int blue, u_int transp, struct fb_info *info)
+{
+ unsigned int val;
+ int ret = 1;
+
+ /*
+ * If greyscale is true, then we convert the RGB value
+ * to greyscale no matter what visual we are using.
+ */
+ if (info->var.grayscale)
+ red = green = blue = (19595 * red + 38470 * green +
+ 7471 * blue) >> 16;
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ /*
+ * 16-bit True Colour. We encode the RGB value
+ * according to the RGB bitfield information.
+ */
+ if (regno < 16) {
+ u32 *pal = info->pseudo_palette;
+
+ val = _chan_to_field(red, &info->var.red);
+ val |= _chan_to_field(green, &info->var.green);
+ val |= _chan_to_field(blue, &info->var.blue);
+
+ pal[regno] = val;
+ ret = 0;
+ }
+ break;
+
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ break;
+ }
+
+ return ret;
+}
+
+static int mxc_epdc_fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ int count, index, r;
+ u16 *red, *green, *blue, *transp;
+ u16 trans = 0xffff;
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ int i;
+
+ dev_dbg(fb_data->dev, "setcmap\n");
+
+ if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
+ /* Only support an 8-bit, 256 entry lookup */
+ if (cmap->len != 256)
+ return 1;
+
+ mxc_epdc_fb_flush_updates(fb_data);
+
+ mutex_lock(&fb_data->pxp_mutex);
+ /*
+ * Store colormap in pxp_conf structure for later transmit
+ * to PxP during update process to convert gray pixels.
+ *
+ * Since red=blue=green for pseudocolor visuals, we can
+ * just use red values.
+ */
+ for (i = 0; i < 256; i++)
+ fb_data->pxp_conf.proc_data.lut_map[i] = cmap->red[i] & 0xFF;
+
+ fb_data->pxp_conf.proc_data.lut_map_updated = true;
+
+ mutex_unlock(&fb_data->pxp_mutex);
+ } else {
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ index = cmap->start;
+
+ for (count = 0; count < cmap->len; count++) {
+ if (transp)
+ trans = *transp++;
+ r = mxc_epdc_fb_setcolreg(index++, *red++, *green++, *blue++,
+ trans, info);
+ if (r != 0)
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+static void adjust_coordinates(u32 xres, u32 yres, u32 rotation,
+ struct mxcfb_rect *update_region, struct mxcfb_rect *adj_update_region)
+{
+ u32 temp;
+
+ /* If adj_update_region == NULL, pass result back in update_region */
+ /* If adj_update_region == valid, use it to pass back result */
+ if (adj_update_region)
+ switch (rotation) {
+ case FB_ROTATE_UR:
+ adj_update_region->top = update_region->top;
+ adj_update_region->left = update_region->left;
+ adj_update_region->width = update_region->width;
+ adj_update_region->height = update_region->height;
+ break;
+ case FB_ROTATE_CW:
+ adj_update_region->top = update_region->left;
+ adj_update_region->left = yres -
+ (update_region->top + update_region->height);
+ adj_update_region->width = update_region->height;
+ adj_update_region->height = update_region->width;
+ break;
+ case FB_ROTATE_UD:
+ adj_update_region->width = update_region->width;
+ adj_update_region->height = update_region->height;
+ adj_update_region->top = yres -
+ (update_region->top + update_region->height);
+ adj_update_region->left = xres -
+ (update_region->left + update_region->width);
+ break;
+ case FB_ROTATE_CCW:
+ adj_update_region->left = update_region->top;
+ adj_update_region->top = xres -
+ (update_region->left + update_region->width);
+ adj_update_region->width = update_region->height;
+ adj_update_region->height = update_region->width;
+ break;
+ }
+ else
+ switch (rotation) {
+ case FB_ROTATE_UR:
+ /* No adjustment needed */
+ break;
+ case FB_ROTATE_CW:
+ temp = update_region->top;
+ update_region->top = update_region->left;
+ update_region->left = yres -
+ (temp + update_region->height);
+ temp = update_region->width;
+ update_region->width = update_region->height;
+ update_region->height = temp;
+ break;
+ case FB_ROTATE_UD:
+ update_region->top = yres -
+ (update_region->top + update_region->height);
+ update_region->left = xres -
+ (update_region->left + update_region->width);
+ break;
+ case FB_ROTATE_CCW:
+ temp = update_region->left;
+ update_region->left = update_region->top;
+ update_region->top = xres -
+ (temp + update_region->width);
+ temp = update_region->width;
+ update_region->width = update_region->height;
+ update_region->height = temp;
+ break;
+ }
+}
+
+/*
+ * Set fixed framebuffer parameters based on variable settings.
+ *
+ * @param info framebuffer information pointer
+ */
+static int mxc_epdc_fb_set_fix(struct fb_info *info)
+{
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct fb_var_screeninfo *var = &info->var;
+
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->accel = FB_ACCEL_NONE;
+ if (var->grayscale)
+ fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ else
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+
+ return 0;
+}
+
+/*
+ * This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ *
+ */
+static int mxc_epdc_fb_set_par(struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ struct fb_var_screeninfo *screeninfo = &fb_data->info.var;
+ struct imx_epdc_fb_mode *epdc_modes = fb_data->pdata->epdc_mode;
+ int i;
+ int ret;
+ __u32 xoffset_old, yoffset_old;
+
+ /*
+ * Can't change the FB parameters until current updates have completed.
+ * This function returns when all active updates are done.
+ */
+ mxc_epdc_fb_flush_updates(fb_data);
+
+ mutex_lock(&fb_data->queue_mutex);
+ /*
+ * Set all screeninfo except for xoffset/yoffset
+ * Subsequent call to pan_display will handle those.
+ */
+ xoffset_old = fb_data->epdc_fb_var.xoffset;
+ yoffset_old = fb_data->epdc_fb_var.yoffset;
+ fb_data->epdc_fb_var = *screeninfo;
+ fb_data->epdc_fb_var.xoffset = xoffset_old;
+ fb_data->epdc_fb_var.yoffset = yoffset_old;
+ mutex_unlock(&fb_data->queue_mutex);
+
+ mutex_lock(&fb_data->pxp_mutex);
+
+ /*
+ * Update PxP config data (used to process FB regions for updates)
+ * based on FB info and processing tasks required
+ */
+
+ /* Initialize non-channel-specific PxP parameters */
+ proc_data->drect.left = proc_data->srect.left = 0;
+ proc_data->drect.top = proc_data->srect.top = 0;
+ proc_data->drect.width = proc_data->srect.width = screeninfo->xres;
+ proc_data->drect.height = proc_data->srect.height = screeninfo->yres;
+ proc_data->scaling = 0;
+ proc_data->hflip = 0;
+ proc_data->vflip = 0;
+ proc_data->rotate = screeninfo->rotate;
+ proc_data->bgcolor = 0;
+ proc_data->overlay_state = 0;
+ proc_data->lut_transform = PXP_LUT_NONE;
+
+ /*
+ * configure S0 channel parameters
+ * Parameters should match FB format/width/height
+ */
+ if (screeninfo->grayscale)
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_GREY;
+ else {
+ switch (screeninfo->bits_per_pixel) {
+ case 16:
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
+ break;
+ case 24:
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB24;
+ break;
+ case 32:
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_XRGB32;
+ break;
+ default:
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
+ break;
+ }
+ }
+ pxp_conf->s0_param.width = screeninfo->xres_virtual;
+ pxp_conf->s0_param.stride = (screeninfo->bits_per_pixel * pxp_conf->s0_param.width) >> 3;
+ pxp_conf->s0_param.height = screeninfo->yres;
+ pxp_conf->s0_param.color_key = -1;
+ pxp_conf->s0_param.color_key_enable = false;
+
+ /*
+ * Initialize Output channel parameters
+ * Output is Y-only greyscale
+ * Output width/height will vary based on update region size
+ */
+ pxp_conf->out_param.width = screeninfo->xres;
+ pxp_conf->out_param.height = screeninfo->yres;
+ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_GREY;
+
+ mutex_unlock(&fb_data->pxp_mutex);
+
+ /*
+ * If HW not yet initialized, check to see if we are being sent
+ * an initialization request.
+ */
+ if (!fb_data->hw_ready) {
+ struct fb_videomode mode;
+ u32 xres_temp;
+
+ fb_var_to_videomode(&mode, screeninfo);
+
+ /* When comparing requested fb mode,
+ we need to use unrotated dimensions */
+ if ((screeninfo->rotate == FB_ROTATE_CW) ||
+ (screeninfo->rotate == FB_ROTATE_CCW)) {
+ xres_temp = mode.xres;
+ mode.xres = mode.yres;
+ mode.yres = xres_temp;
+ }
+
+ /*
+ * If requested video mode does not match current video
+ * mode, search for a matching panel.
+ */
+ if (fb_data->cur_mode &&
+ !fb_mode_is_equal(fb_data->cur_mode->vmode,
+ &mode)) {
+ bool found_match = false;
+
+ /* Match videomode against epdc modes */
+ for (i = 0; i < fb_data->pdata->num_modes; i++) {
+ if (!fb_mode_is_equal(epdc_modes[i].vmode,
+ &mode))
+ continue;
+ fb_data->cur_mode = &epdc_modes[i];
+ found_match = true;
+ break;
+ }
+
+ if (!found_match) {
+ dev_err(fb_data->dev,
+ "Failed to match requested "
+ "video mode\n");
+ return EINVAL;
+ }
+ }
+
+ /* Found a match - Grab timing params */
+ screeninfo->left_margin = mode.left_margin;
+ screeninfo->right_margin = mode.right_margin;
+ screeninfo->upper_margin = mode.upper_margin;
+ screeninfo->lower_margin = mode.lower_margin;
+ screeninfo->hsync_len = mode.hsync_len;
+ screeninfo->vsync_len = mode.vsync_len;
+
+ fb_data->hw_initializing = true;
+
+ /* Initialize EPDC settings and init panel */
+ ret =
+ mxc_epdc_fb_init_hw((struct fb_info *)fb_data);
+ if (ret) {
+ dev_err(fb_data->dev,
+ "Failed to load panel waveform data\n");
+ return ret;
+ }
+ }
+
+ /*
+ * EOF sync delay (in us) should be equal to the vscan holdoff time
+ * VSCAN_HOLDOFF time = (VSCAN_HOLDOFF value + 1) * Vertical lines
+ * Add 25us for additional margin
+ */
+ fb_data->eof_sync_period = (fb_data->cur_mode->vscan_holdoff + 1) *
+ 1000000/(fb_data->cur_mode->vmode->refresh *
+ (fb_data->cur_mode->vmode->upper_margin +
+ fb_data->cur_mode->vmode->yres +
+ fb_data->cur_mode->vmode->lower_margin +
+ fb_data->cur_mode->vmode->vsync_len)) + 25;
+
+ mxc_epdc_fb_set_fix(info);
+
+ return 0;
+}
+
+static int mxc_epdc_fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+
+ if (!var->xres)
+ var->xres = 1;
+ if (!var->yres)
+ var->yres = 1;
+
+ if (var->xres_virtual < var->xoffset + var->xres)
+ var->xres_virtual = var->xoffset + var->xres;
+ if (var->yres_virtual < var->yoffset + var->yres)
+ var->yres_virtual = var->yoffset + var->yres;
+
+ if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
+ (var->bits_per_pixel != 16) && (var->bits_per_pixel != 8))
+ var->bits_per_pixel = default_bpp;
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ if (var->grayscale != 0) {
+ /*
+ * For 8-bit grayscale, R, G, and B offset are equal.
+ *
+ */
+ var->red.length = 8;
+ var->red.offset = 0;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 0;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ } else {
+ var->red.length = 3;
+ var->red.offset = 5;
+ var->red.msb_right = 0;
+
+ var->green.length = 3;
+ var->green.offset = 2;
+ var->green.msb_right = 0;
+
+ var->blue.length = 2;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ }
+ break;
+ case 16:
+ var->red.length = 5;
+ var->red.offset = 11;
+ var->red.msb_right = 0;
+
+ var->green.length = 6;
+ var->green.offset = 5;
+ var->green.msb_right = 0;
+
+ var->blue.length = 5;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 24:
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 32:
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 8;
+ var->transp.offset = 24;
+ var->transp.msb_right = 0;
+ break;
+ }
+
+ switch (var->rotate) {
+ case FB_ROTATE_UR:
+ case FB_ROTATE_UD:
+ var->xres = fb_data->native_width;
+ var->yres = fb_data->native_height;
+ break;
+ case FB_ROTATE_CW:
+ case FB_ROTATE_CCW:
+ var->xres = fb_data->native_height;
+ var->yres = fb_data->native_width;
+ break;
+ default:
+ /* Invalid rotation value */
+ var->rotate = 0;
+ dev_dbg(fb_data->dev, "Invalid rotation request\n");
+ return -EINVAL;
+ }
+
+ var->xres_virtual = ALIGN(var->xres, 32);
+ var->yres_virtual = ALIGN(var->yres, 128) * fb_data->num_screens;
+
+ var->height = -1;
+ var->width = -1;
+
+ return 0;
+}
+
+static void mxc_epdc_fb_set_waveform_modes(struct mxcfb_waveform_modes *modes,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ mutex_lock(&fb_data->queue_mutex);
+
+ memcpy(&fb_data->wv_modes, modes, sizeof(struct mxcfb_waveform_modes));
+
+ /* Set flag to ensure that new waveform modes
+ * are programmed into EPDC before next update */
+ fb_data->wv_modes_update = true;
+
+ mutex_unlock(&fb_data->queue_mutex);
+}
+
+static int mxc_epdc_fb_get_temp_index(struct mxc_epdc_fb_data *fb_data, int temp)
+{
+ int i;
+ int index = -1;
+
+ if (fb_data->trt_entries == 0) {
+ dev_err(fb_data->dev,
+ "No TRT exists...using default temp index\n");
+ return DEFAULT_TEMP_INDEX;
+ }
+
+ /* Search temperature ranges for a match */
+ for (i = 0; i < fb_data->trt_entries - 1; i++) {
+ if ((temp >= fb_data->temp_range_bounds[i])
+ && (temp < fb_data->temp_range_bounds[i+1])) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0) {
+ dev_err(fb_data->dev,
+ "No TRT index match...using default temp index\n");
+ return DEFAULT_TEMP_INDEX;
+ }
+
+ dev_dbg(fb_data->dev, "Using temperature index %d\n", index);
+
+ return index;
+}
+
+static int mxc_epdc_fb_set_temperature(int temperature, struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ /* Store temp index. Used later when configuring updates. */
+ mutex_lock(&fb_data->queue_mutex);
+ fb_data->temp_index = mxc_epdc_fb_get_temp_index(fb_data, temperature);
+ mutex_unlock(&fb_data->queue_mutex);
+
+ return 0;
+}
+
+static int mxc_epdc_fb_set_auto_update(u32 auto_mode, struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ dev_dbg(fb_data->dev, "Setting auto update mode to %d\n", auto_mode);
+
+ if ((auto_mode == AUTO_UPDATE_MODE_AUTOMATIC_MODE)
+ || (auto_mode == AUTO_UPDATE_MODE_REGION_MODE))
+ fb_data->auto_mode = auto_mode;
+ else {
+ dev_err(fb_data->dev, "Invalid auto update mode parameter.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mxc_epdc_fb_set_upd_scheme(u32 upd_scheme, struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ dev_dbg(fb_data->dev, "Setting optimization level to %d\n", upd_scheme);
+
+ /*
+ * Can't change the scheme until current updates have completed.
+ * This function returns when all active updates are done.
+ */
+ mxc_epdc_fb_flush_updates(fb_data);
+
+ if ((upd_scheme == UPDATE_SCHEME_SNAPSHOT)
+ || (upd_scheme == UPDATE_SCHEME_QUEUE)
+ || (upd_scheme == UPDATE_SCHEME_QUEUE_AND_MERGE))
+ fb_data->upd_scheme = upd_scheme;
+ else {
+ dev_err(fb_data->dev, "Invalid update scheme specified.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void copy_before_process(struct mxc_epdc_fb_data *fb_data,
+ struct update_data_list *upd_data_list)
+{
+ struct mxcfb_update_data *upd_data =
+ &upd_data_list->update_desc->upd_data;
+ int i;
+ unsigned char *temp_buf_ptr = fb_data->virt_addr_copybuf;
+ unsigned char *src_ptr;
+ struct mxcfb_rect *src_upd_region;
+ int temp_buf_stride;
+ int src_stride;
+ int bpp = fb_data->epdc_fb_var.bits_per_pixel;
+ int left_offs, right_offs;
+ int x_trailing_bytes, y_trailing_bytes;
+ int alt_buf_offset;
+
+ /* Set source buf pointer based on input source, panning, etc. */
+ if (upd_data->flags & EPDC_FLAG_USE_ALT_BUFFER) {
+ src_upd_region = &upd_data->alt_buffer_data.alt_update_region;
+ src_stride =
+ upd_data->alt_buffer_data.width * bpp/8;
+ alt_buf_offset = upd_data->alt_buffer_data.phys_addr -
+ fb_data->info.fix.smem_start;
+ src_ptr = fb_data->info.screen_base + alt_buf_offset
+ + src_upd_region->top * src_stride;
+ } else {
+ src_upd_region = &upd_data->update_region;
+ src_stride = fb_data->epdc_fb_var.xres_virtual * bpp/8;
+ src_ptr = fb_data->info.screen_base + fb_data->fb_offset
+ + src_upd_region->top * src_stride;
+ }
+
+ temp_buf_stride = ALIGN(src_upd_region->width, 8) * bpp/8;
+ left_offs = src_upd_region->left * bpp/8;
+ right_offs = src_upd_region->width * bpp/8;
+ x_trailing_bytes = (ALIGN(src_upd_region->width, 8)
+ - src_upd_region->width) * bpp/8;
+
+ for (i = 0; i < src_upd_region->height; i++) {
+ /* Copy the full line */
+ memcpy(temp_buf_ptr, src_ptr + left_offs,
+ src_upd_region->width * bpp/8);
+
+ /* Clear any unwanted pixels at the end of each line */
+ if (src_upd_region->width & 0x7) {
+ memset(temp_buf_ptr + right_offs, 0x0,
+ x_trailing_bytes);
+ }
+
+ temp_buf_ptr += temp_buf_stride;
+ src_ptr += src_stride;
+ }
+
+ /* Clear any unwanted pixels at the bottom of the end of each line */
+ if (src_upd_region->height & 0x7) {
+ y_trailing_bytes = (ALIGN(src_upd_region->height, 8)
+ - src_upd_region->height) *
+ ALIGN(src_upd_region->width, 8) * bpp/8;
+ memset(temp_buf_ptr, 0x0, y_trailing_bytes);
+ }
+}
+
+/* Before every update to panel, we should call this
+ * function to update the working buffer first.
+ */
+static int epdc_working_buffer_update(struct mxc_epdc_fb_data *fb_data,
+ struct update_data_list *upd_data_list,
+ struct mxcfb_rect *update_region)
+{
+ struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
+ u32 wv_mode = upd_data_list->update_desc->upd_data.waveform_mode;
+ int ret = 0;
+ u32 hist_stat;
+ struct update_desc_list *upd_desc_list;
+
+ ret = pxp_wfe_a_process(fb_data, update_region, upd_data_list);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ /* If needed, enable EPDC HW while ePxP is processing */
+ if ((fb_data->power_state == POWER_STATE_OFF)
+ || fb_data->powering_down) {
+ epdc_powerup(fb_data);
+ }
+
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_complete_update(fb_data, &fb_data->hist_status);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to complete PxP update task: main process\n");
+ return ret;
+ }
+
+ upd_desc_list = upd_data_list->update_desc;
+ if (fb_data->epdc_wb_mode &&
+ (upd_desc_list->upd_data.waveform_mode == WAVEFORM_MODE_AUTO)) {
+ hist_stat = fb_data->hist_status;
+
+ if (hist_stat & 0x1)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_du;
+ else if (hist_stat & 0x2)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc4;
+ else if (hist_stat & 0x4)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc8;
+ else if (hist_stat & 0x8)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc16;
+ else
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc32;
+
+ dev_dbg(fb_data->dev, "hist_stat = 0x%x, new waveform = 0x%x\n",
+ hist_stat, upd_desc_list->upd_data.waveform_mode);
+ }
+
+ if (proc_data->detection_only == 1) {
+ dev_dbg(fb_data->dev, "collision detection only, no real update\n");
+ return 0;
+ }
+
+ if (fb_data->col_info.pixel_cnt) {
+ dev_dbg(fb_data->dev, "collision detected, can not do REAGl/-D\n");
+ return 0;
+ }
+
+ /* for REAGL/-D Processing */
+ if (wv_mode == WAVEFORM_MODE_GLR16
+ || wv_mode == WAVEFORM_MODE_GLD16) {
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_wfe_b_process_update(fb_data, update_region);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ /* If needed, enable EPDC HW while ePxP is processing */
+ if ((fb_data->power_state == POWER_STATE_OFF)
+ || fb_data->powering_down) {
+ epdc_powerup(fb_data);
+ }
+
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_complete_update(fb_data, &hist_stat);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to complete PxP update task: reagl/-d process\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ }
+
+ return 0;
+}
+
+static int epdc_process_update(struct update_data_list *upd_data_list,
+ struct mxc_epdc_fb_data *fb_data)
+{
+ struct mxcfb_rect *src_upd_region; /* Region of src buffer for update */
+ struct mxcfb_rect pxp_upd_region;
+ u32 src_width, src_height;
+ u32 offset_from_4, bytes_per_pixel;
+ u32 post_rotation_xcoord, post_rotation_ycoord, width_pxp_blocks;
+ u32 pxp_input_offs, pxp_output_offs, pxp_output_shift;
+ u32 hist_stat = 0;
+ int width_unaligned, height_unaligned;
+ bool input_unaligned = false;
+ bool line_overflow = false;
+ int pix_per_line_added;
+ bool use_temp_buf = false;
+ struct mxcfb_rect temp_buf_upd_region;
+ struct update_desc_list *upd_desc_list = upd_data_list->update_desc;
+
+ int ret;
+
+ /*
+ * Gotta do a whole bunch of buffer ptr manipulation to
+ * work around HW restrictions for PxP & EPDC
+ * Note: Applies to pre-2.0 versions of EPDC/PxP
+ */
+
+ /*
+ * Are we using FB or an alternate (overlay)
+ * buffer for source of update?
+ */
+ if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_ALT_BUFFER) {
+ src_width = upd_desc_list->upd_data.alt_buffer_data.width;
+ src_height = upd_desc_list->upd_data.alt_buffer_data.height;
+ src_upd_region = &upd_desc_list->upd_data.alt_buffer_data.alt_update_region;
+ } else {
+ src_width = fb_data->epdc_fb_var.xres_virtual;
+ src_height = fb_data->epdc_fb_var.yres;
+ src_upd_region = &upd_desc_list->upd_data.update_region;
+ }
+
+ bytes_per_pixel = fb_data->epdc_fb_var.bits_per_pixel/8;
+
+ /*
+ * SW workaround for PxP limitation (for pre-v2.0 HW)
+ *
+ * There are 3 cases where we cannot process the update data
+ * directly from the input buffer:
+ *
+ * 1) PxP must process 8x8 pixel blocks, and all pixels in each block
+ * are considered for auto-waveform mode selection. If the
+ * update region is not 8x8 aligned, additional unwanted pixels
+ * will be considered in auto-waveform mode selection.
+ *
+ * 2) PxP input must be 32-bit aligned, so any update
+ * address not 32-bit aligned must be shifted to meet the
+ * 32-bit alignment. The PxP will thus end up processing pixels
+ * outside of the update region to satisfy this alignment restriction,
+ * which can affect auto-waveform mode selection.
+ *
+ * 3) If input fails 32-bit alignment, and the resulting expansion
+ * of the processed region would add at least 8 pixels more per
+ * line than the original update line width, the EPDC would
+ * cause screen artifacts by incorrectly handling the 8+ pixels
+ * at the end of each line.
+ *
+ * Workaround is to copy from source buffer into a temporary
+ * buffer, which we pad with zeros to match the 8x8 alignment
+ * requirement. This temp buffer becomes the input to the PxP.
+ */
+ width_unaligned = src_upd_region->width & 0x7;
+ height_unaligned = src_upd_region->height & 0x7;
+
+ offset_from_4 = src_upd_region->left & 0x3;
+ input_unaligned = ((offset_from_4 * bytes_per_pixel % 4) != 0) ?
+ true : false;
+
+ pix_per_line_added = (offset_from_4 * bytes_per_pixel % 4)
+ / bytes_per_pixel;
+ if ((((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) ||
+ fb_data->epdc_fb_var.rotate == FB_ROTATE_UD)) &&
+ (ALIGN(src_upd_region->width, 8) <
+ ALIGN(src_upd_region->width + pix_per_line_added, 8)))
+ line_overflow = true;
+
+ /* Grab pxp_mutex here so that we protect access
+ * to copybuf in addition to the PxP structures */
+ mutex_lock(&fb_data->pxp_mutex);
+
+ if (((((width_unaligned || height_unaligned || input_unaligned) &&
+ (upd_desc_list->upd_data.waveform_mode == WAVEFORM_MODE_AUTO))
+ || line_overflow) && (fb_data->rev < 20)) ||
+ fb_data->restrict_width) {
+ dev_dbg(fb_data->dev, "Copying update before processing.\n");
+
+ /* Update to reflect what the new source buffer will be */
+ src_width = ALIGN(src_upd_region->width, 8);
+ src_height = ALIGN(src_upd_region->height, 8);
+
+ copy_before_process(fb_data, upd_data_list);
+
+ /*
+ * src_upd_region should now describe
+ * the new update buffer attributes.
+ */
+ temp_buf_upd_region.left = 0;
+ temp_buf_upd_region.top = 0;
+ temp_buf_upd_region.width = src_upd_region->width;
+ temp_buf_upd_region.height = src_upd_region->height;
+ src_upd_region = &temp_buf_upd_region;
+
+ use_temp_buf = true;
+ }
+
+ /*
+ * For pre-2.0 HW, input address must be 32-bit aligned
+ * Compute buffer offset to account for this PxP limitation
+ */
+ offset_from_4 = src_upd_region->left & 0x3;
+ input_unaligned = ((offset_from_4 * bytes_per_pixel % 4) != 0) ?
+ true : false;
+ if ((fb_data->rev < 20) && input_unaligned) {
+ /* Leave a gap between PxP input addr and update region pixels */
+ pxp_input_offs =
+ (src_upd_region->top * src_width + src_upd_region->left)
+ * bytes_per_pixel & 0xFFFFFFFC;
+ /* Update region left changes to reflect relative position to input ptr */
+ pxp_upd_region.left = (offset_from_4 * bytes_per_pixel % 4)
+ / bytes_per_pixel;
+ } else {
+ pxp_input_offs =
+ (src_upd_region->top * src_width + src_upd_region->left)
+ * bytes_per_pixel;
+ pxp_upd_region.left = 0;
+ }
+
+ pxp_upd_region.top = 0;
+
+ /*
+ * For version 2.0 and later of EPDC & PxP, if no rotation, we don't
+ * need to align width & height (rotation always requires 8-pixel
+ * width & height alignment, per PxP limitations)
+ */
+ if ((fb_data->epdc_fb_var.rotate == 0) && (fb_data->rev >= 20)) {
+ pxp_upd_region.width = src_upd_region->width;
+ pxp_upd_region.height = src_upd_region->height;
+ } else {
+ /* Update region dimensions to meet 8x8 pixel requirement */
+ pxp_upd_region.width = ALIGN(src_upd_region->width + pxp_upd_region.left, 8);
+ pxp_upd_region.height = ALIGN(src_upd_region->height, 8);
+ }
+
+ switch (fb_data->epdc_fb_var.rotate) {
+ case FB_ROTATE_UR:
+ default:
+ post_rotation_xcoord = pxp_upd_region.left;
+ post_rotation_ycoord = pxp_upd_region.top;
+ width_pxp_blocks = pxp_upd_region.width;
+ break;
+ case FB_ROTATE_CW:
+ width_pxp_blocks = pxp_upd_region.height;
+ post_rotation_xcoord = width_pxp_blocks - src_upd_region->height;
+ post_rotation_ycoord = pxp_upd_region.left;
+ break;
+ case FB_ROTATE_UD:
+ width_pxp_blocks = pxp_upd_region.width;
+ post_rotation_xcoord = width_pxp_blocks - src_upd_region->width - pxp_upd_region.left;
+ post_rotation_ycoord = pxp_upd_region.height - src_upd_region->height - pxp_upd_region.top;
+ break;
+ case FB_ROTATE_CCW:
+ width_pxp_blocks = pxp_upd_region.height;
+ post_rotation_xcoord = pxp_upd_region.top;
+ post_rotation_ycoord = pxp_upd_region.width - src_upd_region->width - pxp_upd_region.left;
+ break;
+ }
+
+ /* Update region start coord to force PxP to process full 8x8 regions */
+ pxp_upd_region.top &= ~0x7;
+ pxp_upd_region.left &= ~0x7;
+
+ if (fb_data->rev < 20) {
+ pxp_output_shift = ALIGN(post_rotation_xcoord, 8)
+ - post_rotation_xcoord;
+
+ pxp_output_offs = post_rotation_ycoord * width_pxp_blocks
+ + pxp_output_shift;
+
+ upd_desc_list->epdc_offs = ALIGN(pxp_output_offs, 8);
+ } else {
+ pxp_output_shift = 0;
+ pxp_output_offs = post_rotation_ycoord * width_pxp_blocks
+ + post_rotation_xcoord;
+
+ upd_desc_list->epdc_offs = pxp_output_offs;
+ }
+
+ upd_desc_list->epdc_stride = width_pxp_blocks;
+
+ /* Source address either comes from alternate buffer
+ provided in update data, or from the framebuffer. */
+ if (use_temp_buf)
+ sg_dma_address(&fb_data->sg[0]) =
+ fb_data->phys_addr_copybuf;
+ else if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_ALT_BUFFER)
+ sg_dma_address(&fb_data->sg[0]) =
+ upd_desc_list->upd_data.alt_buffer_data.phys_addr
+ + pxp_input_offs;
+ else {
+ sg_dma_address(&fb_data->sg[0]) =
+ fb_data->info.fix.smem_start + fb_data->fb_offset
+ + pxp_input_offs;
+ sg_set_page(&fb_data->sg[0],
+ virt_to_page(fb_data->info.screen_base),
+ fb_data->info.fix.smem_len,
+ offset_in_page(fb_data->info.screen_base));
+ }
+
+ /* Update sg[1] to point to output of PxP proc task */
+ sg_dma_address(&fb_data->sg[1]) = upd_data_list->phys_addr
+ + pxp_output_shift;
+ sg_set_page(&fb_data->sg[1], virt_to_page(upd_data_list->virt_addr),
+ fb_data->max_pix_size,
+ offset_in_page(upd_data_list->virt_addr));
+
+ /*
+ * Set PxP LUT transform type based on update flags.
+ */
+ fb_data->pxp_conf.proc_data.lut_transform = 0;
+ if (upd_desc_list->upd_data.flags & EPDC_FLAG_ENABLE_INVERSION)
+ fb_data->pxp_conf.proc_data.lut_transform |= PXP_LUT_INVERT;
+ if (upd_desc_list->upd_data.flags & EPDC_FLAG_FORCE_MONOCHROME)
+ fb_data->pxp_conf.proc_data.lut_transform |=
+ PXP_LUT_BLACK_WHITE;
+ if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_CMAP)
+ fb_data->pxp_conf.proc_data.lut_transform |=
+ PXP_LUT_USE_CMAP;
+
+ /*
+ * Toggle inversion processing if 8-bit
+ * inverted is the current pixel format.
+ */
+ if (fb_data->epdc_fb_var.grayscale == GRAYSCALE_8BIT_INVERTED)
+ fb_data->pxp_conf.proc_data.lut_transform ^= PXP_LUT_INVERT;
+
+#ifdef USE_PS_AS_OUTPUT
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_legacy_process(fb_data, src_width, src_height,
+ &pxp_upd_region);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ /* If needed, enable EPDC HW while ePxP is processing */
+ if ((fb_data->power_state == POWER_STATE_OFF)
+ || fb_data->powering_down) {
+ epdc_powerup(fb_data);
+ }
+
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_complete_update(fb_data, &hist_stat);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to complete PxP update task: pre_prcoess.\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+#endif
+ pr_debug(" upd_data.dither_mode %d \n", upd_desc_list->upd_data.dither_mode);
+ fb_data->pxp_conf.proc_data.dither_mode = 0;
+
+ /* Dithering */
+ if ((EPDC_FLAG_USE_DITHERING_PASSTHROUGH < upd_desc_list->upd_data.dither_mode) &&
+ (upd_desc_list->upd_data.dither_mode < EPDC_FLAG_USE_DITHERING_MAX)) {
+
+ fb_data->pxp_conf.proc_data.dither_mode = upd_desc_list->upd_data.dither_mode;
+ fb_data->pxp_conf.proc_data.quant_bit = upd_desc_list->upd_data.quant_bit;
+
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_process_dithering(fb_data, &pxp_upd_region);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ /* If needed, enable EPDC HW while ePxP is processing */
+ if ((fb_data->power_state == POWER_STATE_OFF)
+ || fb_data->powering_down) {
+ epdc_powerup(fb_data);
+ }
+
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_complete_update(fb_data, &hist_stat);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to complete PxP update task: dithering process\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ }
+
+ /* Regal D Processing */
+ fb_data->pxp_conf.proc_data.reagl_d_en =
+ (upd_desc_list->upd_data.waveform_mode == WAVEFORM_MODE_GLD16);
+
+ mutex_unlock(&fb_data->pxp_mutex);
+
+ /* Update waveform mode from PxP histogram results */
+ if ((fb_data->rev <= 20) &&
+ (upd_desc_list->upd_data.waveform_mode == WAVEFORM_MODE_AUTO)) {
+ if (hist_stat & 0x1)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_du;
+ else if (hist_stat & 0x2)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc4;
+ else if (hist_stat & 0x4)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc8;
+ else if (hist_stat & 0x8)
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc16;
+ else
+ upd_desc_list->upd_data.waveform_mode =
+ fb_data->wv_modes.mode_gc32;
+
+ dev_dbg(fb_data->dev, "hist_stat = 0x%x, new waveform = 0x%x\n",
+ hist_stat, upd_desc_list->upd_data.waveform_mode);
+ }
+
+ return 0;
+}
+
+static int epdc_submit_merge(struct update_desc_list *upd_desc_list,
+ struct update_desc_list *update_to_merge,
+ struct mxc_epdc_fb_data *fb_data)
+{
+ struct mxcfb_update_data *a, *b;
+ struct mxcfb_rect *arect, *brect;
+ struct mxcfb_rect combine;
+ bool use_flags = false;
+
+ a = &upd_desc_list->upd_data;
+ b = &update_to_merge->upd_data;
+ arect = &upd_desc_list->upd_data.update_region;
+ brect = &update_to_merge->upd_data.update_region;
+
+ /* Do not merge a dry-run collision test update */
+ if ((a->flags & EPDC_FLAG_TEST_COLLISION) ||
+ (b->flags & EPDC_FLAG_TEST_COLLISION))
+ return MERGE_BLOCK;
+
+ /*
+ * Updates with different flags must be executed sequentially.
+ * Halt the merge process to ensure this.
+ */
+ if (a->flags != b->flags) {
+ /*
+ * Special exception: if update regions are identical,
+ * we may be able to merge them.
+ */
+ if ((arect->left != brect->left) ||
+ (arect->top != brect->top) ||
+ (arect->width != brect->width) ||
+ (arect->height != brect->height))
+ return MERGE_BLOCK;
+
+ use_flags = true;
+ }
+
+ if (a->update_mode != b->update_mode)
+ a->update_mode = UPDATE_MODE_FULL;
+
+ if (a->waveform_mode != b->waveform_mode)
+ a->waveform_mode = WAVEFORM_MODE_AUTO;
+
+ if (arect->left > (brect->left + brect->width) ||
+ brect->left > (arect->left + arect->width) ||
+ arect->top > (brect->top + brect->height) ||
+ brect->top > (arect->top + arect->height))
+ return MERGE_FAIL;
+
+ combine.left = arect->left < brect->left ? arect->left : brect->left;
+ combine.top = arect->top < brect->top ? arect->top : brect->top;
+ combine.width = (arect->left + arect->width) >
+ (brect->left + brect->width) ?
+ (arect->left + arect->width - combine.left) :
+ (brect->left + brect->width - combine.left);
+ combine.height = (arect->top + arect->height) >
+ (brect->top + brect->height) ?
+ (arect->top + arect->height - combine.top) :
+ (brect->top + brect->height - combine.top);
+
+ /* Don't merge if combined width exceeds max width */
+ if (fb_data->restrict_width) {
+ u32 max_width = EPDC_V2_MAX_UPDATE_WIDTH;
+ u32 combined_width = combine.width;
+ if (fb_data->epdc_fb_var.rotate != FB_ROTATE_UR)
+ max_width -= EPDC_V2_ROTATION_ALIGNMENT;
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_CW) ||
+ (fb_data->epdc_fb_var.rotate == FB_ROTATE_CCW))
+ combined_width = combine.height;
+ if (combined_width > max_width)
+ return MERGE_FAIL;
+ }
+
+ *arect = combine;
+
+ /* Use flags of the later update */
+ if (use_flags)
+ a->flags = b->flags;
+
+ /* Merge markers */
+ list_splice_tail(&update_to_merge->upd_marker_list,
+ &upd_desc_list->upd_marker_list);
+
+ /* Merged update should take on the earliest order */
+ upd_desc_list->update_order =
+ (upd_desc_list->update_order > update_to_merge->update_order) ?
+ upd_desc_list->update_order : update_to_merge->update_order;
+
+ return MERGE_OK;
+}
+
+static void epdc_submit_work_func(struct work_struct *work)
+{
+ int temp_index;
+ struct update_data_list *next_update, *temp_update;
+ struct update_desc_list *next_desc, *temp_desc;
+ struct update_marker_data *next_marker, *temp_marker;
+ struct mxc_epdc_fb_data *fb_data =
+ container_of(work, struct mxc_epdc_fb_data, epdc_submit_work);
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+ struct update_data_list *upd_data_list = NULL;
+ struct mxcfb_rect adj_update_region, *upd_region;
+ bool end_merge = false;
+ bool is_transform;
+ u32 update_addr;
+ int *err_dist;
+ int ret;
+
+ /* Protect access to buffer queues and to update HW */
+ mutex_lock(&fb_data->queue_mutex);
+
+ /*
+ * Are any of our collision updates able to go now?
+ * Go through all updates in the collision list and check to see
+ * if the collision mask has been fully cleared
+ */
+ list_for_each_entry_safe(next_update, temp_update,
+ &fb_data->upd_buf_collision_list, list) {
+
+ if (next_update->collision_mask != 0)
+ continue;
+
+ dev_dbg(fb_data->dev, "A collision update is ready to go!\n");
+
+ /* Force waveform mode to auto for resubmitted collisions */
+ next_update->update_desc->upd_data.waveform_mode =
+ WAVEFORM_MODE_AUTO;
+
+ /*
+ * We have a collision cleared, so select it for resubmission.
+ * If an update is already selected, attempt to merge.
+ */
+ if (!upd_data_list) {
+ upd_data_list = next_update;
+ list_del_init(&next_update->list);
+ if (fb_data->upd_scheme == UPDATE_SCHEME_QUEUE)
+ /* If not merging, we have our update */
+ break;
+ } else {
+ switch (epdc_submit_merge(upd_data_list->update_desc,
+ next_update->update_desc,
+ fb_data)) {
+ case MERGE_OK:
+ dev_dbg(fb_data->dev,
+ "Update merged [collision]\n");
+ list_del_init(&next_update->update_desc->list);
+ kfree(next_update->update_desc);
+ next_update->update_desc = NULL;
+ list_del_init(&next_update->list);
+ /* Add to free buffer list */
+ list_add_tail(&next_update->list,
+ &fb_data->upd_buf_free_list);
+ break;
+ case MERGE_FAIL:
+ dev_dbg(fb_data->dev,
+ "Update not merged [collision]\n");
+ break;
+ case MERGE_BLOCK:
+ dev_dbg(fb_data->dev,
+ "Merge blocked [collision]\n");
+ end_merge = true;
+ break;
+ }
+
+ if (end_merge) {
+ end_merge = false;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Skip pending update list only if we found a collision
+ * update and we are not merging
+ */
+ if (!((fb_data->upd_scheme == UPDATE_SCHEME_QUEUE) &&
+ upd_data_list)) {
+ /*
+ * If we didn't find a collision update ready to go, we
+ * need to get a free buffer and match it to a pending update.
+ */
+
+ /*
+ * Can't proceed if there are no free buffers (and we don't
+ * already have a collision update selected)
+ */
+ if (!upd_data_list &&
+ list_empty(&fb_data->upd_buf_free_list)) {
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ list_for_each_entry_safe(next_desc, temp_desc,
+ &fb_data->upd_pending_list, list) {
+
+ dev_dbg(fb_data->dev, "Found a pending update!\n");
+
+ if (!upd_data_list) {
+ if (list_empty(&fb_data->upd_buf_free_list))
+ break;
+ upd_data_list =
+ list_entry(fb_data->upd_buf_free_list.next,
+ struct update_data_list, list);
+ list_del_init(&upd_data_list->list);
+ upd_data_list->update_desc = next_desc;
+ list_del_init(&next_desc->list);
+ if (fb_data->upd_scheme == UPDATE_SCHEME_QUEUE)
+ /* If not merging, we have an update */
+ break;
+ } else {
+ switch (epdc_submit_merge(upd_data_list->update_desc,
+ next_desc, fb_data)) {
+ case MERGE_OK:
+ dev_dbg(fb_data->dev,
+ "Update merged [queue]\n");
+ list_del_init(&next_desc->list);
+ kfree(next_desc);
+ break;
+ case MERGE_FAIL:
+ dev_dbg(fb_data->dev,
+ "Update not merged [queue]\n");
+ break;
+ case MERGE_BLOCK:
+ dev_dbg(fb_data->dev,
+ "Merge blocked [collision]\n");
+ end_merge = true;
+ break;
+ }
+
+ if (end_merge)
+ break;
+ }
+ }
+ }
+
+ /* Is update list empty? */
+ if (!upd_data_list) {
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ /*
+ * If no processing required, skip update processing
+ * No processing means:
+ * - FB unrotated
+ * - FB pixel format = 8-bit grayscale
+ * - No look-up transformations (inversion, posterization, etc.)
+ * - No scaling/flip
+ */
+ is_transform = ((upd_data_list->update_desc->upd_data.flags &
+ (EPDC_FLAG_ENABLE_INVERSION | EPDC_FLAG_USE_DITHERING_Y1 |
+ EPDC_FLAG_USE_DITHERING_Y4 | EPDC_FLAG_FORCE_MONOCHROME |
+ EPDC_FLAG_USE_CMAP)) && (proc_data->scaling == 0) &&
+ (proc_data->hflip == 0) && (proc_data->vflip == 0)) ?
+ true : false;
+
+ /*XXX if we use external mode, we should first use pxp
+ * to update upd buffer data to working buffer first.
+ */
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) &&
+ (fb_data->epdc_fb_var.grayscale == GRAYSCALE_8BIT) &&
+ !is_transform && (proc_data->dither_mode == 0) &&
+ !fb_data->restrict_width) {
+
+ /* If needed, enable EPDC HW while ePxP is processing */
+ if ((fb_data->power_state == POWER_STATE_OFF)
+ || fb_data->powering_down)
+ epdc_powerup(fb_data);
+
+ /*
+ * Set update buffer pointer to the start of
+ * the update region in the frame buffer.
+ */
+ upd_region = &upd_data_list->update_desc->upd_data.update_region;
+ update_addr = fb_data->info.fix.smem_start +
+ ((upd_region->top * fb_data->info.var.xres_virtual) +
+ upd_region->left) * fb_data->info.var.bits_per_pixel/8;
+ upd_data_list->update_desc->epdc_stride =
+ fb_data->info.var.xres_virtual *
+ fb_data->info.var.bits_per_pixel/8;
+ } else {
+ /* Select from PxP output buffers */
+ upd_data_list->phys_addr =
+ fb_data->phys_addr_updbuf[fb_data->upd_buffer_num];
+ upd_data_list->virt_addr =
+ fb_data->virt_addr_updbuf[fb_data->upd_buffer_num];
+ fb_data->upd_buffer_num++;
+ if (fb_data->upd_buffer_num > fb_data->max_num_buffers-1)
+ fb_data->upd_buffer_num = 0;
+
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+
+ /* Perform PXP processing - EPDC power will also be enabled */
+ if (epdc_process_update(upd_data_list, fb_data)) {
+ dev_dbg(fb_data->dev, "PXP processing error.\n");
+ /* Protect access to buffer queues and to update HW */
+ mutex_lock(&fb_data->queue_mutex);
+ list_del_init(&upd_data_list->update_desc->list);
+ kfree(upd_data_list->update_desc);
+ upd_data_list->update_desc = NULL;
+ /* Add to free buffer list */
+ list_add_tail(&upd_data_list->list,
+ &fb_data->upd_buf_free_list);
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ /* Protect access to buffer queues and to update HW */
+ mutex_lock(&fb_data->queue_mutex);
+
+ update_addr = upd_data_list->phys_addr
+ + upd_data_list->update_desc->epdc_offs;
+ }
+
+ /* Get rotation-adjusted coordinates */
+ adjust_coordinates(fb_data->epdc_fb_var.xres,
+ fb_data->epdc_fb_var.yres, fb_data->epdc_fb_var.rotate,
+ &upd_data_list->update_desc->upd_data.update_region,
+ &adj_update_region);
+
+ /*
+ * Is the working buffer idle?
+ * If the working buffer is busy, we must wait for the resource
+ * to become free. The IST will signal this event.
+ */
+ if (fb_data->cur_update != NULL) {
+ dev_dbg(fb_data->dev, "working buf busy!\n");
+
+ /* Initialize event signalling an update resource is free */
+ init_completion(&fb_data->update_res_free);
+
+ fb_data->waiting_for_wb = true;
+
+ /* Leave spinlock while waiting for WB to complete */
+ mutex_unlock(&fb_data->queue_mutex);
+ wait_for_completion(&fb_data->update_res_free);
+ mutex_lock(&fb_data->queue_mutex);
+ }
+
+ /*
+ * Dithering Processing (Version 1.0 - for i.MX508 and i.MX6SL)
+ */
+ if (upd_data_list->update_desc->upd_data.flags &
+ EPDC_FLAG_USE_DITHERING_Y1) {
+
+ err_dist = kzalloc((fb_data->info.var.xres_virtual + 3) * 3
+ * sizeof(int), GFP_KERNEL);
+
+ /* Dithering Y8 -> Y1 */
+ do_dithering_processing_Y1_v1_0(
+ (uint8_t *)(upd_data_list->virt_addr +
+ upd_data_list->update_desc->epdc_offs),
+ upd_data_list->phys_addr +
+ upd_data_list->update_desc->epdc_offs,
+ &adj_update_region,
+ (fb_data->rev < 20) ?
+ ALIGN(adj_update_region.width, 8) :
+ adj_update_region.width,
+ err_dist);
+
+ kfree(err_dist);
+ } else if (upd_data_list->update_desc->upd_data.flags &
+ EPDC_FLAG_USE_DITHERING_Y4) {
+
+ err_dist = kzalloc((fb_data->info.var.xres_virtual + 3) * 3
+ * sizeof(int), GFP_KERNEL);
+
+ /* Dithering Y8 -> Y1 */
+ do_dithering_processing_Y4_v1_0(
+ (uint8_t *)(upd_data_list->virt_addr +
+ upd_data_list->update_desc->epdc_offs),
+ upd_data_list->phys_addr +
+ upd_data_list->update_desc->epdc_offs,
+ &adj_update_region,
+ (fb_data->rev < 20) ?
+ ALIGN(adj_update_region.width, 8) :
+ adj_update_region.width,
+ err_dist);
+
+ kfree(err_dist);
+ }
+
+ /*
+ * If there are no LUTs available,
+ * then we must wait for the resource to become free.
+ * The IST will signal this event.
+ */
+ {
+ bool luts_available;
+
+ luts_available = fb_data->epdc_wb_mode ? epdc_any_luts_real_available() :
+ epdc_any_luts_available();
+ if (!luts_available) {
+ dev_dbg(fb_data->dev, "no luts available!\n");
+
+ /* Initialize event signalling an update resource is free */
+ init_completion(&fb_data->update_res_free);
+
+ fb_data->waiting_for_lut = true;
+
+ /* Leave spinlock while waiting for LUT to free up */
+ mutex_unlock(&fb_data->queue_mutex);
+ wait_for_completion(&fb_data->update_res_free);
+ mutex_lock(&fb_data->queue_mutex);
+ }
+ }
+
+ ret = epdc_choose_next_lut(fb_data, &upd_data_list->lut_num);
+ /*
+ * If LUT15 is in use (for pre-EPDC v2.0 hardware):
+ * - Wait for LUT15 to complete is if TCE underrun prevent is enabled
+ * - If we go ahead with update, sync update submission with EOF
+ */
+ if (ret && fb_data->tce_prevent && (fb_data->rev < 20)) {
+ dev_dbg(fb_data->dev, "Waiting for LUT15\n");
+
+ /* Initialize event signalling that lut15 is free */
+ init_completion(&fb_data->lut15_free);
+
+ fb_data->waiting_for_lut15 = true;
+
+ /* Leave spinlock while waiting for LUT to free up */
+ mutex_unlock(&fb_data->queue_mutex);
+ wait_for_completion(&fb_data->lut15_free);
+ mutex_lock(&fb_data->queue_mutex);
+
+ epdc_choose_next_lut(fb_data, &upd_data_list->lut_num);
+ } else if (ret && (fb_data->rev < 20)) {
+ /* Synchronize update submission time to reduce
+ chances of TCE underrun */
+ init_completion(&fb_data->eof_event);
+
+ epdc_eof_intr(true);
+
+ /* Leave spinlock while waiting for EOF event */
+ mutex_unlock(&fb_data->queue_mutex);
+ ret = wait_for_completion_timeout(&fb_data->eof_event,
+ msecs_to_jiffies(1000));
+ if (!ret) {
+ dev_err(fb_data->dev, "Missed EOF event!\n");
+ epdc_eof_intr(false);
+ }
+ udelay(fb_data->eof_sync_period);
+ mutex_lock(&fb_data->queue_mutex);
+
+ }
+
+ /* LUTs are available, so we get one here */
+ fb_data->cur_update = upd_data_list;
+
+ /* Reset mask for LUTS that have completed during WB processing */
+ fb_data->luts_complete_wb = 0;
+
+ /* If we are just testing for collision, we don't assign a LUT,
+ * so we don't need to update LUT-related resources. */
+ if (!(upd_data_list->update_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION)) {
+ /* Associate LUT with update marker */
+ list_for_each_entry_safe(next_marker, temp_marker,
+ &upd_data_list->update_desc->upd_marker_list, upd_list)
+ next_marker->lut_num = fb_data->cur_update->lut_num;
+
+ /* Mark LUT with order */
+ fb_data->lut_update_order[upd_data_list->lut_num] =
+ upd_data_list->update_desc->update_order;
+
+ epdc_lut_complete_intr(fb_data->rev, upd_data_list->lut_num,
+ true);
+ }
+
+ /* Enable Collision and WB complete IRQs */
+ epdc_working_buf_intr(true);
+
+ /* add working buffer update here for external mode */
+ if (fb_data->epdc_wb_mode)
+ ret = epdc_working_buffer_update(fb_data, upd_data_list,
+ &adj_update_region);
+
+ /* Program EPDC update to process buffer */
+ if (upd_data_list->update_desc->upd_data.temp != TEMP_USE_AMBIENT) {
+ temp_index = mxc_epdc_fb_get_temp_index(fb_data,
+ upd_data_list->update_desc->upd_data.temp);
+ epdc_set_temp(temp_index);
+ } else
+ epdc_set_temp(fb_data->temp_index);
+
+ epdc_set_update_addr(update_addr);
+ epdc_set_update_coord(adj_update_region.left, adj_update_region.top);
+ epdc_set_update_dimensions(adj_update_region.width,
+ adj_update_region.height);
+ if (fb_data->rev > 20)
+ epdc_set_update_stride(upd_data_list->update_desc->epdc_stride);
+ if (fb_data->wv_modes_update &&
+ (upd_data_list->update_desc->upd_data.waveform_mode
+ == WAVEFORM_MODE_AUTO)) {
+ epdc_set_update_waveform(&fb_data->wv_modes);
+ fb_data->wv_modes_update = false;
+ }
+
+ epdc_submit_update(upd_data_list->lut_num,
+ upd_data_list->update_desc->upd_data.waveform_mode,
+ upd_data_list->update_desc->upd_data.update_mode,
+ (upd_data_list->update_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION) ? true : false,
+ false, 0);
+
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+}
+
+static int mxc_epdc_fb_send_single_update(struct mxcfb_update_data *upd_data,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+ struct update_data_list *upd_data_list = NULL;
+ struct mxcfb_rect *screen_upd_region; /* Region on screen to update */
+ int temp_index;
+ int ret;
+ struct update_desc_list *upd_desc;
+ struct update_marker_data *marker_data, *next_marker, *temp_marker;
+
+ /* Has EPDC HW been initialized? */
+ if (!fb_data->hw_ready) {
+ /* Throw message if we are not mid-initialization */
+ if (!fb_data->hw_initializing)
+ dev_err(fb_data->dev, "Display HW not properly"
+ "initialized. Aborting update.\n");
+ return -EPERM;
+ }
+
+ /* Check validity of update params */
+ if ((upd_data->update_mode != UPDATE_MODE_PARTIAL) &&
+ (upd_data->update_mode != UPDATE_MODE_FULL)) {
+ dev_err(fb_data->dev,
+ "Update mode 0x%x is invalid. Aborting update.\n",
+ upd_data->update_mode);
+ return -EINVAL;
+ }
+ if ((upd_data->waveform_mode > 255) &&
+ (upd_data->waveform_mode != WAVEFORM_MODE_AUTO)) {
+ dev_err(fb_data->dev,
+ "Update waveform mode 0x%x is invalid."
+ " Aborting update.\n",
+ upd_data->waveform_mode);
+ return -EINVAL;
+ }
+ if ((upd_data->update_region.left >= fb_data->epdc_fb_var.xres) ||
+ (upd_data->update_region.top >= fb_data->epdc_fb_var.yres) ||
+ (upd_data->update_region.width > fb_data->epdc_fb_var.xres) ||
+ (upd_data->update_region.height > fb_data->epdc_fb_var.yres) ||
+ (upd_data->update_region.left + upd_data->update_region.width > fb_data->epdc_fb_var.xres) ||
+ (upd_data->update_region.top + upd_data->update_region.height > fb_data->epdc_fb_var.yres)) {
+ dev_err(fb_data->dev,
+ "Update region is outside bounds of framebuffer."
+ "Aborting update.\n");
+ return -EINVAL;
+ }
+ if (upd_data->flags & EPDC_FLAG_USE_ALT_BUFFER) {
+ if ((upd_data->update_region.width !=
+ upd_data->alt_buffer_data.alt_update_region.width) ||
+ (upd_data->update_region.height !=
+ upd_data->alt_buffer_data.alt_update_region.height)) {
+ dev_err(fb_data->dev,
+ "Alternate update region dimensions must "
+ "match screen update region dimensions.\n");
+ return -EINVAL;
+ }
+ /* Validate physical address parameter */
+ if ((upd_data->alt_buffer_data.phys_addr <
+ fb_data->info.fix.smem_start) ||
+ (upd_data->alt_buffer_data.phys_addr >
+ fb_data->info.fix.smem_start + fb_data->map_size)) {
+ dev_err(fb_data->dev,
+ "Invalid physical address for alternate "
+ "buffer. Aborting update...\n");
+ return -EINVAL;
+ }
+ }
+
+ mutex_lock(&fb_data->queue_mutex);
+
+ /*
+ * If we are waiting to go into suspend, or the FB is blanked,
+ * we do not accept new updates
+ */
+ if ((fb_data->waiting_for_idle) ||
+ (fb_data->blank != FB_BLANK_UNBLANK)) {
+ dev_dbg(fb_data->dev, "EPDC not active."
+ "Update request abort.\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return -EPERM;
+ }
+
+ if (fb_data->upd_scheme == UPDATE_SCHEME_SNAPSHOT) {
+ int count = 0;
+ struct update_data_list *plist;
+
+ /*
+ * If next update is a FULL mode update, then we must
+ * ensure that all pending & active updates are complete
+ * before submitting the update. Otherwise, the FULL
+ * mode update may cause an endless collision loop with
+ * other updates. Block here until updates are flushed.
+ */
+ if (upd_data->update_mode == UPDATE_MODE_FULL) {
+ mutex_unlock(&fb_data->queue_mutex);
+ mxc_epdc_fb_flush_updates(fb_data);
+ mutex_lock(&fb_data->queue_mutex);
+ }
+
+ /* Count buffers in free buffer list */
+ list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
+ count++;
+
+ /* Use count to determine if we have enough
+ * free buffers to handle this update request */
+ if (count + fb_data->max_num_buffers
+ <= fb_data->max_num_updates) {
+ dev_err(fb_data->dev,
+ "No free intermediate buffers available.\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return -ENOMEM;
+ }
+
+ /* Grab first available buffer and delete from the free list */
+ upd_data_list =
+ list_entry(fb_data->upd_buf_free_list.next,
+ struct update_data_list, list);
+
+ list_del_init(&upd_data_list->list);
+ }
+
+ /*
+ * Create new update data structure, fill it with new update
+ * data and add it to the list of pending updates
+ */
+ upd_desc = kzalloc(sizeof(struct update_desc_list), GFP_KERNEL);
+ if (!upd_desc) {
+ dev_err(fb_data->dev,
+ "Insufficient system memory for update! Aborting.\n");
+ if (fb_data->upd_scheme == UPDATE_SCHEME_SNAPSHOT) {
+ list_add(&upd_data_list->list,
+ &fb_data->upd_buf_free_list);
+ }
+ mutex_unlock(&fb_data->queue_mutex);
+ return -EPERM;
+ }
+ /* Initialize per-update marker list */
+ INIT_LIST_HEAD(&upd_desc->upd_marker_list);
+ upd_desc->upd_data = *upd_data;
+ upd_desc->update_order = fb_data->order_cnt++;
+ list_add_tail(&upd_desc->list, &fb_data->upd_pending_list);
+
+ /* If marker specified, associate it with a completion */
+ if (upd_data->update_marker != 0) {
+ /* Allocate new update marker and set it up */
+ marker_data = kzalloc(sizeof(struct update_marker_data),
+ GFP_KERNEL);
+ if (!marker_data) {
+ dev_err(fb_data->dev, "No memory for marker!\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return -ENOMEM;
+ }
+ list_add_tail(&marker_data->upd_list,
+ &upd_desc->upd_marker_list);
+ marker_data->update_marker = upd_data->update_marker;
+ if (upd_desc->upd_data.flags & EPDC_FLAG_TEST_COLLISION)
+ marker_data->lut_num = DRY_RUN_NO_LUT;
+ else
+ marker_data->lut_num = INVALID_LUT;
+ init_completion(&marker_data->update_completion);
+ /* Add marker to master marker list */
+ list_add_tail(&marker_data->full_list,
+ &fb_data->full_marker_list);
+ }
+
+ if (fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT) {
+ /* Queued update scheme processing */
+
+ mutex_unlock(&fb_data->queue_mutex);
+
+ /* Signal workqueue to handle new update */
+ queue_work(fb_data->epdc_submit_workqueue,
+ &fb_data->epdc_submit_work);
+
+ return 0;
+ }
+
+ /* Snapshot update scheme processing */
+
+ /* Set descriptor for current update, delete from pending list */
+ upd_data_list->update_desc = upd_desc;
+ list_del_init(&upd_desc->list);
+
+ mutex_unlock(&fb_data->queue_mutex);
+
+ /*
+ * Hold on to original screen update region, which we
+ * will ultimately use when telling EPDC where to update on panel
+ */
+ screen_upd_region = &upd_desc->upd_data.update_region;
+
+ /* Select from PxP output buffers */
+ upd_data_list->phys_addr =
+ fb_data->phys_addr_updbuf[fb_data->upd_buffer_num];
+ upd_data_list->virt_addr =
+ fb_data->virt_addr_updbuf[fb_data->upd_buffer_num];
+ fb_data->upd_buffer_num++;
+ if (fb_data->upd_buffer_num > fb_data->max_num_buffers-1)
+ fb_data->upd_buffer_num = 0;
+
+ ret = epdc_process_update(upd_data_list, fb_data);
+ if (ret) {
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ /* Pass selected waveform mode back to user */
+ upd_data->waveform_mode = upd_desc->upd_data.waveform_mode;
+
+ /* Get rotation-adjusted coordinates */
+ adjust_coordinates(fb_data->epdc_fb_var.xres,
+ fb_data->epdc_fb_var.yres, fb_data->epdc_fb_var.rotate,
+ &upd_desc->upd_data.update_region, NULL);
+
+ /* Grab lock for queue manipulation and update submission */
+ mutex_lock(&fb_data->queue_mutex);
+
+ /*
+ * Is the working buffer idle?
+ * If either the working buffer is busy, or there are no LUTs available,
+ * then we return and let the ISR handle the update later
+ */
+ {
+ bool luts_available;
+
+ luts_available = fb_data->epdc_wb_mode ? epdc_any_luts_real_available() :
+ epdc_any_luts_available();
+ if ((fb_data->cur_update != NULL) || !luts_available) {
+ /* Add processed Y buffer to update list */
+ list_add_tail(&upd_data_list->list, &fb_data->upd_buf_queue);
+
+ /* Return and allow the update to be submitted by the ISR. */
+ mutex_unlock(&fb_data->queue_mutex);
+ return 0;
+ }
+ }
+
+ /* LUTs are available, so we get one here */
+ ret = epdc_choose_next_lut(fb_data, &upd_data_list->lut_num);
+ if (ret && fb_data->tce_prevent && (fb_data->rev < 20)) {
+ dev_dbg(fb_data->dev, "Must wait for LUT15\n");
+ /* Add processed Y buffer to update list */
+ list_add_tail(&upd_data_list->list, &fb_data->upd_buf_queue);
+
+ /* Return and allow the update to be submitted by the ISR. */
+ mutex_unlock(&fb_data->queue_mutex);
+ return 0;
+ }
+
+ if (!(upd_data_list->update_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION)) {
+
+ /* Save current update */
+ fb_data->cur_update = upd_data_list;
+
+ /* Reset mask for LUTS that have completed during WB processing */
+ fb_data->luts_complete_wb = 0;
+
+ /* Associate LUT with update marker */
+ list_for_each_entry_safe(next_marker, temp_marker,
+ &upd_data_list->update_desc->upd_marker_list, upd_list)
+ next_marker->lut_num = upd_data_list->lut_num;
+
+ /* Mark LUT as containing new update */
+ fb_data->lut_update_order[upd_data_list->lut_num] =
+ upd_desc->update_order;
+
+ epdc_lut_complete_intr(fb_data->rev, upd_data_list->lut_num,
+ true);
+ }
+
+ /* Clear status and Enable LUT complete and WB complete IRQs */
+ epdc_working_buf_intr(true);
+
+ /* add working buffer update before display for external mode */
+ if (fb_data->epdc_wb_mode)
+ ret = epdc_working_buffer_update(fb_data, upd_data_list,
+ screen_upd_region);
+
+ /* Program EPDC update to process buffer */
+ epdc_set_update_addr(upd_data_list->phys_addr + upd_desc->epdc_offs);
+ epdc_set_update_coord(screen_upd_region->left, screen_upd_region->top);
+ epdc_set_update_dimensions(screen_upd_region->width,
+ screen_upd_region->height);
+ if (fb_data->rev > 20)
+ epdc_set_update_stride(upd_desc->epdc_stride);
+ if (upd_desc->upd_data.temp != TEMP_USE_AMBIENT) {
+ temp_index = mxc_epdc_fb_get_temp_index(fb_data,
+ upd_desc->upd_data.temp);
+ epdc_set_temp(temp_index);
+ } else
+ epdc_set_temp(fb_data->temp_index);
+ if (fb_data->wv_modes_update &&
+ (upd_desc->upd_data.waveform_mode == WAVEFORM_MODE_AUTO)) {
+ epdc_set_update_waveform(&fb_data->wv_modes);
+ fb_data->wv_modes_update = false;
+ }
+
+ epdc_submit_update(upd_data_list->lut_num,
+ upd_desc->upd_data.waveform_mode,
+ upd_desc->upd_data.update_mode,
+ (upd_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION) ? true : false,
+ false, 0);
+
+ mutex_unlock(&fb_data->queue_mutex);
+ return 0;
+}
+
+static int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ if (!fb_data->restrict_width) {
+ /* No width restriction, send entire update region */
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+ } else {
+ int ret;
+ __u32 width, left;
+ __u32 marker;
+ __u32 *region_width, *region_left;
+ u32 max_upd_width = EPDC_V2_MAX_UPDATE_WIDTH;
+
+ /* Further restrict max width due to pxp rotation
+ * alignment requirement
+ */
+ if (fb_data->epdc_fb_var.rotate != FB_ROTATE_UR)
+ max_upd_width -= EPDC_V2_ROTATION_ALIGNMENT;
+
+ /* Select split of width or height based on rotation */
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) ||
+ (fb_data->epdc_fb_var.rotate == FB_ROTATE_UD)) {
+ region_width = &upd_data->update_region.width;
+ region_left = &upd_data->update_region.left;
+ } else {
+ region_width = &upd_data->update_region.height;
+ region_left = &upd_data->update_region.top;
+ }
+
+ if (*region_width <= max_upd_width)
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+
+ width = *region_width;
+ left = *region_left;
+ marker = upd_data->update_marker;
+ upd_data->update_marker = 0;
+
+ do {
+ *region_width = max_upd_width;
+ *region_left = left;
+ ret = mxc_epdc_fb_send_single_update(upd_data, info);
+ if (ret)
+ return ret;
+ width -= max_upd_width;
+ left += max_upd_width;
+ } while (width > max_upd_width);
+
+ *region_width = width;
+ *region_left = left;
+ upd_data->update_marker = marker;
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+ }
+}
+
+static int mxc_epdc_fb_wait_update_complete(struct mxcfb_update_marker_data *marker_data,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+ struct update_marker_data *next_marker;
+ struct update_marker_data *temp;
+ bool marker_found = false;
+ int ret = 0;
+
+ /* 0 is an invalid update_marker value */
+ if (marker_data->update_marker == 0)
+ return -EINVAL;
+
+ /*
+ * Find completion associated with update_marker requested.
+ * Note: If update completed already, marker will have been
+ * cleared, it won't be found, and function will just return.
+ */
+
+ /* Grab queue lock to protect access to marker list */
+ mutex_lock(&fb_data->queue_mutex);
+
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->full_marker_list, full_list) {
+ if (next_marker->update_marker == marker_data->update_marker) {
+ dev_dbg(fb_data->dev, "Waiting for marker %d\n",
+ marker_data->update_marker);
+ next_marker->waiting = true;
+ marker_found = true;
+ break;
+ }
+ }
+
+ mutex_unlock(&fb_data->queue_mutex);
+
+ /*
+ * If marker not found, it has either been signalled already
+ * or the update request failed. In either case, just return.
+ */
+ if (!marker_found)
+ return ret;
+
+ ret = wait_for_completion_timeout(&next_marker->update_completion,
+ msecs_to_jiffies(5000));
+ if (!ret) {
+ dev_err(fb_data->dev,
+ "Timed out waiting for update completion\n");
+ return -ETIMEDOUT;
+ }
+
+ marker_data->collision_test = next_marker->collision_test;
+
+ /* Free update marker object */
+ kfree(next_marker);
+
+ return ret;
+}
+
+static int mxc_epdc_fb_set_pwrdown_delay(u32 pwrdown_delay,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ fb_data->pwrdown_delay = pwrdown_delay;
+
+ return 0;
+}
+
+static int mxc_epdc_get_pwrdown_delay(struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ return fb_data->pwrdown_delay;
+}
+
+static int mxc_epdc_fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int ret = -EINVAL;
+
+ switch (cmd) {
+ case MXCFB_SET_WAVEFORM_MODES:
+ {
+ struct mxcfb_waveform_modes modes;
+ if (!copy_from_user(&modes, argp, sizeof(modes))) {
+ mxc_epdc_fb_set_waveform_modes(&modes, info);
+ ret = 0;
+ }
+ break;
+ }
+ case MXCFB_SET_TEMPERATURE:
+ {
+ int temperature;
+ if (!get_user(temperature, (int32_t __user *) arg))
+ ret = mxc_epdc_fb_set_temperature(temperature,
+ info);
+ break;
+ }
+ case MXCFB_SET_AUTO_UPDATE_MODE:
+ {
+ u32 auto_mode = 0;
+ if (!get_user(auto_mode, (__u32 __user *) arg))
+ ret = mxc_epdc_fb_set_auto_update(auto_mode,
+ info);
+ break;
+ }
+ case MXCFB_SET_UPDATE_SCHEME:
+ {
+ u32 upd_scheme = 0;
+ if (!get_user(upd_scheme, (__u32 __user *) arg))
+ ret = mxc_epdc_fb_set_upd_scheme(upd_scheme,
+ info);
+ break;
+ }
+ case MXCFB_SEND_UPDATE:
+ {
+ struct mxcfb_update_data upd_data;
+ if (!copy_from_user(&upd_data, argp,
+ sizeof(upd_data))) {
+ ret = mxc_epdc_fb_send_update(&upd_data, info);
+ if (ret == 0 && copy_to_user(argp, &upd_data,
+ sizeof(upd_data)))
+ ret = -EFAULT;
+ } else {
+ ret = -EFAULT;
+ }
+
+ break;
+ }
+ case MXCFB_WAIT_FOR_UPDATE_COMPLETE:
+ {
+ struct mxcfb_update_marker_data upd_marker_data;
+ if (!copy_from_user(&upd_marker_data, argp,
+ sizeof(upd_marker_data))) {
+ ret = mxc_epdc_fb_wait_update_complete(
+ &upd_marker_data, info);
+ if (copy_to_user(argp, &upd_marker_data,
+ sizeof(upd_marker_data)))
+ ret = -EFAULT;
+ } else {
+ ret = -EFAULT;
+ }
+
+ break;
+ }
+
+ case MXCFB_SET_PWRDOWN_DELAY:
+ {
+ int delay = 0;
+ if (!get_user(delay, (__u32 __user *) arg))
+ ret =
+ mxc_epdc_fb_set_pwrdown_delay(delay, info);
+ break;
+ }
+
+ case MXCFB_GET_PWRDOWN_DELAY:
+ {
+ int pwrdown_delay = mxc_epdc_get_pwrdown_delay(info);
+ if (put_user(pwrdown_delay,
+ (int __user *)argp))
+ ret = -EFAULT;
+ ret = 0;
+ break;
+ }
+
+ case MXCFB_GET_WORK_BUFFER:
+ {
+ /* copy the epdc working buffer to the user space */
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+ flush_cache_all();
+ outer_flush_range(fb_data->working_buffer_phys,
+ fb_data->working_buffer_phys +
+ fb_data->working_buffer_size);
+ if (copy_to_user((void __user *)arg,
+ (const void *) fb_data->working_buffer_virt,
+ fb_data->working_buffer_size))
+ ret = -EFAULT;
+ else
+ ret = 0;
+ flush_cache_all();
+ outer_flush_range(fb_data->working_buffer_phys,
+ fb_data->working_buffer_phys +
+ fb_data->working_buffer_size);
+ break;
+ }
+
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void mxc_epdc_fb_update_pages(struct mxc_epdc_fb_data *fb_data,
+ u16 y1, u16 y2)
+{
+ struct mxcfb_update_data update;
+
+ /* Do partial screen update, Update full horizontal lines */
+ update.update_region.left = 0;
+ update.update_region.width = fb_data->epdc_fb_var.xres;
+ update.update_region.top = y1;
+ update.update_region.height = y2 - y1;
+ update.waveform_mode = WAVEFORM_MODE_AUTO;
+ update.update_mode = UPDATE_MODE_FULL;
+ update.update_marker = 0;
+ update.temp = TEMP_USE_AMBIENT;
+ update.flags = 0;
+
+ mxc_epdc_fb_send_update(&update, &fb_data->info);
+}
+
+/* this is called back from the deferred io workqueue */
+static void mxc_epdc_fb_deferred_io(struct fb_info *info,
+ struct list_head *pagelist)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ struct page *page;
+ unsigned long beg, end;
+ int y1, y2, miny, maxy;
+
+ if (fb_data->auto_mode != AUTO_UPDATE_MODE_AUTOMATIC_MODE)
+ return;
+
+ miny = INT_MAX;
+ maxy = 0;
+ list_for_each_entry(page, pagelist, lru) {
+ beg = page->index << PAGE_SHIFT;
+ end = beg + PAGE_SIZE - 1;
+ y1 = beg / info->fix.line_length;
+ y2 = end / info->fix.line_length;
+ if (y2 >= fb_data->epdc_fb_var.yres)
+ y2 = fb_data->epdc_fb_var.yres - 1;
+ if (miny > y1)
+ miny = y1;
+ if (maxy < y2)
+ maxy = y2;
+ }
+
+ mxc_epdc_fb_update_pages(fb_data, miny, maxy);
+}
+
+void mxc_epdc_fb_flush_updates(struct mxc_epdc_fb_data *fb_data)
+{
+ int ret;
+
+ if (fb_data->in_init)
+ return;
+
+ /* Grab queue lock to prevent any new updates from being submitted */
+ mutex_lock(&fb_data->queue_mutex);
+
+ /*
+ * 3 places to check for updates that are active or pending:
+ * 1) Updates in the pending list
+ * 2) Update buffers in use (e.g., PxP processing)
+ * 3) Active updates to panel - We can key off of EPDC
+ * power state to know if we have active updates.
+ */
+ if (!list_empty(&fb_data->upd_pending_list) ||
+ !is_free_list_full(fb_data) ||
+ (fb_data->updates_active == true)) {
+ /* Initialize event signalling updates are done */
+ init_completion(&fb_data->updates_done);
+ fb_data->waiting_for_idle = true;
+
+ mutex_unlock(&fb_data->queue_mutex);
+ /* Wait for any currently active updates to complete */
+ ret = wait_for_completion_timeout(&fb_data->updates_done,
+ msecs_to_jiffies(8000));
+ if (!ret)
+ dev_err(fb_data->dev,
+ "Flush updates timeout! ret = 0x%x\n", ret);
+
+ mutex_lock(&fb_data->queue_mutex);
+ fb_data->waiting_for_idle = false;
+ }
+
+ mutex_unlock(&fb_data->queue_mutex);
+}
+
+static int mxc_epdc_fb_blank(int blank, struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ int ret;
+
+ dev_dbg(fb_data->dev, "blank = %d\n", blank);
+
+ if (fb_data->blank == blank)
+ return 0;
+
+ fb_data->blank = blank;
+
+ switch (blank) {
+ case FB_BLANK_POWERDOWN:
+ mxc_epdc_fb_flush_updates(fb_data);
+ /* Wait for powerdown */
+ mutex_lock(&fb_data->power_mutex);
+ if ((fb_data->power_state == POWER_STATE_ON) &&
+ (fb_data->pwrdown_delay == FB_POWERDOWN_DISABLE)) {
+
+ /* Powerdown disabled, so we disable EPDC manually */
+ int count = 0;
+ int sleep_ms = 10;
+
+ mutex_unlock(&fb_data->power_mutex);
+
+ /* If any active updates, wait for them to complete */
+ while (fb_data->updates_active) {
+ /* Timeout after 1 sec */
+ if ((count * sleep_ms) > 1000)
+ break;
+ msleep(sleep_ms);
+ count++;
+ }
+
+ fb_data->powering_down = true;
+ epdc_powerdown(fb_data);
+ } else if (fb_data->power_state != POWER_STATE_OFF) {
+ fb_data->wait_for_powerdown = true;
+ init_completion(&fb_data->powerdown_compl);
+ mutex_unlock(&fb_data->power_mutex);
+ ret = wait_for_completion_timeout(&fb_data->powerdown_compl,
+ msecs_to_jiffies(5000));
+ if (!ret) {
+ dev_err(fb_data->dev,
+ "No powerdown received!\n");
+ return -ETIMEDOUT;
+ }
+ } else
+ mutex_unlock(&fb_data->power_mutex);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ mxc_epdc_fb_flush_updates(fb_data);
+ break;
+ }
+ return 0;
+}
+
+static int mxc_epdc_fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ u_int y_bottom;
+
+ dev_dbg(info->device, "%s: var->yoffset %d, info->var.yoffset %d\n",
+ __func__, var->yoffset, info->var.yoffset);
+ /* check if var is valid; also, xpan is not supported */
+ if (!var || (var->xoffset != info->var.xoffset) ||
+ (var->yoffset + var->yres > var->yres_virtual)) {
+ dev_dbg(info->device, "x panning not supported\n");
+ return -EINVAL;
+ }
+
+ if ((fb_data->epdc_fb_var.xoffset == var->xoffset) &&
+ (fb_data->epdc_fb_var.yoffset == var->yoffset))
+ return 0; /* No change, do nothing */
+
+ y_bottom = var->yoffset;
+
+ if (!(var->vmode & FB_VMODE_YWRAP))
+ y_bottom += var->yres;
+
+ if (y_bottom > info->var.yres_virtual)
+ return -EINVAL;
+
+ mutex_lock(&fb_data->queue_mutex);
+
+ fb_data->fb_offset = (var->yoffset * var->xres_virtual + var->xoffset)
+ * (var->bits_per_pixel) / 8;
+
+ fb_data->epdc_fb_var.xoffset = var->xoffset;
+ fb_data->epdc_fb_var.yoffset = var->yoffset;
+
+ if (var->vmode & FB_VMODE_YWRAP)
+ info->var.vmode |= FB_VMODE_YWRAP;
+ else
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+
+ mutex_unlock(&fb_data->queue_mutex);
+
+ return 0;
+}
+
+static struct fb_ops mxc_epdc_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = mxc_epdc_fb_check_var,
+ .fb_set_par = mxc_epdc_fb_set_par,
+ .fb_setcmap = mxc_epdc_fb_setcmap,
+ .fb_setcolreg = mxc_epdc_fb_setcolreg,
+ .fb_pan_display = mxc_epdc_fb_pan_display,
+ .fb_ioctl = mxc_epdc_fb_ioctl,
+ .fb_mmap = mxc_epdc_fb_mmap,
+ .fb_blank = mxc_epdc_fb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static struct fb_deferred_io mxc_epdc_fb_defio = {
+ .delay = HZ,
+ .deferred_io = mxc_epdc_fb_deferred_io,
+};
+
+static void epdc_done_work_func(struct work_struct *work)
+{
+ struct mxc_epdc_fb_data *fb_data =
+ container_of(work, struct mxc_epdc_fb_data,
+ epdc_done_work.work);
+ epdc_powerdown(fb_data);
+}
+
+static bool is_free_list_full(struct mxc_epdc_fb_data *fb_data)
+{
+ int count = 0;
+ struct update_data_list *plist;
+
+ /* Count buffers in free buffer list */
+ list_for_each_entry(plist, &fb_data->upd_buf_free_list, list)
+ count++;
+
+ /* Check to see if all buffers are in this list */
+ if (count == fb_data->max_num_updates)
+ return true;
+ else
+ return false;
+}
+
+static irqreturn_t mxc_epdc_irq_handler(int irq, void *dev_id)
+{
+ struct mxc_epdc_fb_data *fb_data = dev_id;
+ u32 ints_fired, luts1_ints_fired, luts2_ints_fired;
+
+ /*
+ * If we just completed one-time panel init, bypass
+ * queue handling, clear interrupt and return
+ */
+ if (fb_data->in_init) {
+ if (epdc_is_working_buffer_complete()) {
+ epdc_working_buf_intr(false);
+ epdc_clear_working_buf_irq();
+ dev_dbg(fb_data->dev, "Cleared WB for init update\n");
+ }
+
+ if (epdc_is_lut_complete(fb_data->rev, 0)) {
+ epdc_lut_complete_intr(fb_data->rev, 0, false);
+ epdc_clear_lut_complete_irq(fb_data->rev, 0);
+ fb_data->in_init = false;
+ dev_dbg(fb_data->dev, "Cleared LUT complete for init update\n");
+ }
+
+ return IRQ_HANDLED;
+ }
+
+ ints_fired = __raw_readl(EPDC_IRQ_MASK) & __raw_readl(EPDC_IRQ);
+ if (fb_data->rev < 20) {
+ luts1_ints_fired = 0;
+ luts2_ints_fired = 0;
+ } else {
+ luts1_ints_fired = __raw_readl(EPDC_IRQ_MASK1) & __raw_readl(EPDC_IRQ1);
+ luts2_ints_fired = __raw_readl(EPDC_IRQ_MASK2) & __raw_readl(EPDC_IRQ2);
+ }
+
+ if (!(ints_fired || luts1_ints_fired || luts2_ints_fired))
+ return IRQ_HANDLED;
+
+ if (__raw_readl(EPDC_IRQ) & EPDC_IRQ_TCE_UNDERRUN_IRQ) {
+ dev_err(fb_data->dev,
+ "TCE underrun! Will continue to update panel\n");
+ /* Clear TCE underrun IRQ */
+ __raw_writel(EPDC_IRQ_TCE_UNDERRUN_IRQ, EPDC_IRQ_CLEAR);
+ }
+
+ /* Check if we are waiting on EOF to sync a new update submission */
+ if (epdc_signal_eof()) {
+ epdc_eof_intr(false);
+ epdc_clear_eof_irq();
+ complete(&fb_data->eof_event);
+ }
+
+ /*
+ * Workaround for EPDC v2.0/v2.1 errata: Must read collision status
+ * before clearing IRQ, or else collision status for bits 16:63
+ * will be automatically cleared. So we read it here, and there is
+ * no conflict with using it in epdc_intr_work_func since the
+ * working buffer processing flow is strictly sequential (i.e.,
+ * only one WB processing done at a time, so the data grabbed
+ * here should be up-to-date and accurate when the WB processing
+ * completes. Also, note that there is no impact to other versions
+ * of EPDC by reading LUT status here.
+ */
+ if (fb_data->cur_update != NULL)
+ fb_data->epdc_colliding_luts = epdc_get_colliding_luts(fb_data->rev);
+
+ /* Clear the interrupt mask for any interrupts signalled */
+ __raw_writel(ints_fired, EPDC_IRQ_MASK_CLEAR);
+ __raw_writel(luts1_ints_fired, EPDC_IRQ_MASK1_CLEAR);
+ __raw_writel(luts2_ints_fired, EPDC_IRQ_MASK2_CLEAR);
+
+ dev_dbg(fb_data->dev, "EPDC interrupts fired = 0x%x, "
+ "LUTS1 fired = 0x%x, LUTS2 fired = 0x%x\n",
+ ints_fired, luts1_ints_fired, luts2_ints_fired);
+
+ queue_work(fb_data->epdc_intr_workqueue,
+ &fb_data->epdc_intr_work);
+
+ return IRQ_HANDLED;
+}
+
+static void epdc_intr_work_func(struct work_struct *work)
+{
+ struct mxc_epdc_fb_data *fb_data =
+ container_of(work, struct mxc_epdc_fb_data, epdc_intr_work);
+ struct update_data_list *collision_update;
+ struct mxcfb_rect *next_upd_region;
+ struct update_marker_data *next_marker;
+ struct update_marker_data *temp;
+ int temp_index;
+ u64 temp_mask;
+ u32 lut;
+ bool ignore_collision = false;
+ int i;
+ bool wb_lut_done = false;
+ bool free_update = true;
+ int next_lut, epdc_next_lut_15;
+ u32 epdc_luts_active, epdc_wb_busy, epdc_luts_avail, epdc_lut_cancelled;
+ u32 epdc_collision;
+ u64 epdc_irq_stat;
+ bool epdc_waiting_on_wb;
+ u32 coll_coord, coll_size;
+ struct mxcfb_rect coll_region;
+
+ /* Protect access to buffer queues and to update HW */
+ mutex_lock(&fb_data->queue_mutex);
+
+ /* Capture EPDC status one time to limit exposure to race conditions */
+ epdc_luts_active = epdc_any_luts_active(fb_data->rev);
+ epdc_wb_busy = epdc_is_working_buffer_busy();
+
+ /*XXX unsupport update cancelled in external mode temporarily */
+ if (fb_data->epdc_wb_mode)
+ epdc_lut_cancelled = 0;
+ else
+ epdc_lut_cancelled = epdc_is_lut_cancelled();
+
+ if (fb_data->epdc_wb_mode)
+ epdc_luts_avail = epdc_any_luts_real_available();
+ else
+ epdc_luts_avail = epdc_any_luts_available();
+
+ if (fb_data->epdc_wb_mode)
+ epdc_collision = fb_data->col_info.pixel_cnt ? 1 : 0;
+ else
+ epdc_collision = epdc_is_collision();
+
+ if (fb_data->rev < 20)
+ epdc_irq_stat = __raw_readl(EPDC_IRQ);
+ else
+ epdc_irq_stat = (u64)__raw_readl(EPDC_IRQ1) |
+ ((u64)__raw_readl(EPDC_IRQ2) << 32);
+ epdc_waiting_on_wb = (fb_data->cur_update != NULL) ? true : false;
+
+ /* Free any LUTs that have completed */
+ for (i = 0; i < fb_data->num_luts; i++) {
+ if ((epdc_irq_stat & (1ULL << i)) == 0)
+ continue;
+
+ dev_dbg(fb_data->dev, "LUT %d completed\n", i);
+
+ /* Disable IRQ for completed LUT */
+ epdc_lut_complete_intr(fb_data->rev, i, false);
+
+ /*
+ * Go through all updates in the collision list and
+ * unmask any updates that were colliding with
+ * the completed LUT.
+ */
+ list_for_each_entry(collision_update,
+ &fb_data->upd_buf_collision_list, list) {
+ collision_update->collision_mask =
+ collision_update->collision_mask & ~(1ULL << i);
+ }
+
+ epdc_clear_lut_complete_irq(fb_data->rev, i);
+
+ fb_data->luts_complete_wb |= 1ULL << i;
+ if (i != 0)
+ fb_data->luts_complete |= 1ULL << i;
+
+ fb_data->lut_update_order[i] = 0;
+
+ /* Signal completion if submit workqueue needs a LUT */
+ if (fb_data->waiting_for_lut) {
+ complete(&fb_data->update_res_free);
+ fb_data->waiting_for_lut = false;
+ }
+
+ /* Signal completion if LUT15 free and is needed */
+ if (fb_data->waiting_for_lut15 && (i == 15)) {
+ complete(&fb_data->lut15_free);
+ fb_data->waiting_for_lut15 = false;
+ }
+
+ /* Detect race condition where WB and its LUT complete
+ (i.e. full update completes) in one swoop */
+ if (epdc_waiting_on_wb &&
+ (i == fb_data->cur_update->lut_num))
+ wb_lut_done = true;
+
+ /* Signal completion if anyone waiting on this LUT */
+ if (!wb_lut_done)
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->full_marker_list,
+ full_list) {
+ if (next_marker->lut_num != i)
+ continue;
+
+ /* Found marker to signal - remove from list */
+ list_del_init(&next_marker->full_list);
+
+ /* Signal completion of update */
+ dev_dbg(fb_data->dev, "Signaling marker %d\n",
+ next_marker->update_marker);
+ if (next_marker->waiting)
+ complete(&next_marker->update_completion);
+ else
+ kfree(next_marker);
+ }
+ }
+
+ /* Check to see if all updates have completed */
+ if (list_empty(&fb_data->upd_pending_list) &&
+ is_free_list_full(fb_data) &&
+ !epdc_waiting_on_wb &&
+ !epdc_luts_active) {
+
+ fb_data->updates_active = false;
+
+ if (fb_data->pwrdown_delay != FB_POWERDOWN_DISABLE) {
+ /*
+ * Set variable to prevent overlapping
+ * enable/disable requests
+ */
+ fb_data->powering_down = true;
+
+ /* Schedule task to disable EPDC HW until next update */
+ schedule_delayed_work(&fb_data->epdc_done_work,
+ msecs_to_jiffies(fb_data->pwrdown_delay));
+
+ /* Reset counter to reduce chance of overflow */
+ fb_data->order_cnt = 0;
+ }
+
+ if (fb_data->waiting_for_idle)
+ complete(&fb_data->updates_done);
+ }
+
+ /* Is Working Buffer busy? */
+ if (epdc_wb_busy) {
+ /* Can't submit another update until WB is done */
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ /*
+ * Were we waiting on working buffer?
+ * If so, update queues and check for collisions
+ */
+ if (epdc_waiting_on_wb) {
+ dev_dbg(fb_data->dev, "\nWorking buffer completed\n");
+
+ /* Signal completion if submit workqueue was waiting on WB */
+ if (fb_data->waiting_for_wb) {
+ complete(&fb_data->update_res_free);
+ fb_data->waiting_for_wb = false;
+ }
+
+ if (fb_data->cur_update->update_desc->upd_data.flags
+ & EPDC_FLAG_TEST_COLLISION) {
+ /* This was a dry run to test for collision */
+
+ /* Signal marker */
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->full_marker_list,
+ full_list) {
+ if (next_marker->lut_num != DRY_RUN_NO_LUT)
+ continue;
+
+ if (epdc_collision)
+ next_marker->collision_test = true;
+ else
+ next_marker->collision_test = false;
+
+ dev_dbg(fb_data->dev,
+ "In IRQ, collision_test = %d\n",
+ next_marker->collision_test);
+
+ /* Found marker to signal - remove from list */
+ list_del_init(&next_marker->full_list);
+
+ /* Signal completion of update */
+ dev_dbg(fb_data->dev, "Signaling marker "
+ "for dry-run - %d\n",
+ next_marker->update_marker);
+ complete(&next_marker->update_completion);
+ }
+ memset(&fb_data->col_info, 0x0, sizeof(struct pxp_collision_info));
+ } else if (epdc_lut_cancelled && !epdc_collision) {
+ /*
+ * Note: The update may be cancelled (void) if all
+ * pixels collided. In that case we handle it as a
+ * collision, not a cancel.
+ */
+
+ /* Clear LUT status (might be set if no AUTOWV used) */
+
+ /*
+ * Disable and clear IRQ for the LUT used.
+ * Even though LUT is cancelled in HW, the LUT
+ * complete bit may be set if AUTOWV not used.
+ */
+ epdc_lut_complete_intr(fb_data->rev,
+ fb_data->cur_update->lut_num, false);
+ epdc_clear_lut_complete_irq(fb_data->rev,
+ fb_data->cur_update->lut_num);
+
+ fb_data->lut_update_order[fb_data->cur_update->lut_num] = 0;
+
+ /* Signal completion if submit workqueue needs a LUT */
+ if (fb_data->waiting_for_lut) {
+ complete(&fb_data->update_res_free);
+ fb_data->waiting_for_lut = false;
+ }
+
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->cur_update->update_desc->upd_marker_list,
+ upd_list) {
+
+ /* Del from per-update & full list */
+ list_del_init(&next_marker->upd_list);
+ list_del_init(&next_marker->full_list);
+
+ /* Signal completion of update */
+ dev_dbg(fb_data->dev,
+ "Signaling marker (cancelled) %d\n",
+ next_marker->update_marker);
+ if (next_marker->waiting)
+ complete(&next_marker->update_completion);
+ else
+ kfree(next_marker);
+ }
+ } else if (epdc_collision) {
+ /* Real update (no dry-run), collision occurred */
+
+ /* Check list of colliding LUTs, and add to our collision mask */
+ if (fb_data->epdc_wb_mode)
+ fb_data->epdc_colliding_luts = (u64)fb_data->col_info.victim_luts[0] |
+ (((u64)fb_data->col_info.victim_luts[1]) << 32);
+
+ fb_data->cur_update->collision_mask =
+ fb_data->epdc_colliding_luts;
+
+ /* Clear collisions that completed since WB began */
+ fb_data->cur_update->collision_mask &=
+ ~fb_data->luts_complete_wb;
+
+ dev_dbg(fb_data->dev, "Collision mask = 0x%llx\n",
+ fb_data->epdc_colliding_luts);
+
+ /* For EPDC 2.0 and later, minimum collision bounds
+ are provided by HW. Recompute new bounds here. */
+ if ((fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT)
+ && (fb_data->rev >= 20)) {
+ u32 xres, yres, rotate;
+ struct mxcfb_rect adj_update_region;
+ struct mxcfb_rect *cur_upd_rect =
+ &fb_data->cur_update->update_desc->upd_data.update_region;
+
+ if (fb_data->epdc_wb_mode) {
+ adjust_coordinates(fb_data->epdc_fb_var.xres,
+ fb_data->epdc_fb_var.yres, fb_data->epdc_fb_var.rotate,
+ cur_upd_rect, &adj_update_region);
+
+ coll_region.left = fb_data->col_info.rect_min_x + adj_update_region.left;
+ coll_region.top = fb_data->col_info.rect_min_y + adj_update_region.top;
+ coll_region.width = fb_data->col_info.rect_max_x - fb_data->col_info.rect_min_x + 1;
+ coll_region.height = fb_data->col_info.rect_max_y - fb_data->col_info.rect_min_y + 1;
+ memset(&fb_data->col_info, 0x0, sizeof(struct pxp_collision_info));
+ } else {
+ /* Get collision region coords from EPDC */
+ coll_coord = __raw_readl(EPDC_UPD_COL_CORD);
+ coll_size = __raw_readl(EPDC_UPD_COL_SIZE);
+ coll_region.left =
+ (coll_coord & EPDC_UPD_COL_CORD_XCORD_MASK)
+ >> EPDC_UPD_COL_CORD_XCORD_OFFSET;
+ coll_region.top =
+ (coll_coord & EPDC_UPD_COL_CORD_YCORD_MASK)
+ >> EPDC_UPD_COL_CORD_YCORD_OFFSET;
+ coll_region.width =
+ (coll_size & EPDC_UPD_COL_SIZE_WIDTH_MASK)
+ >> EPDC_UPD_COL_SIZE_WIDTH_OFFSET;
+ coll_region.height =
+ (coll_size & EPDC_UPD_COL_SIZE_HEIGHT_MASK)
+ >> EPDC_UPD_COL_SIZE_HEIGHT_OFFSET;
+ }
+ dev_dbg(fb_data->dev, "Coll region: l = %d, "
+ "t = %d, w = %d, h = %d\n",
+ coll_region.left, coll_region.top,
+ coll_region.width, coll_region.height);
+
+ /* Convert coords back to orig orientation */
+ switch (fb_data->epdc_fb_var.rotate) {
+ case FB_ROTATE_CW:
+ xres = fb_data->epdc_fb_var.yres;
+ yres = fb_data->epdc_fb_var.xres;
+ rotate = FB_ROTATE_CCW;
+ break;
+ case FB_ROTATE_UD:
+ xres = fb_data->epdc_fb_var.xres;
+ yres = fb_data->epdc_fb_var.yres;
+ rotate = FB_ROTATE_UD;
+ break;
+ case FB_ROTATE_CCW:
+ xres = fb_data->epdc_fb_var.yres;
+ yres = fb_data->epdc_fb_var.xres;
+ rotate = FB_ROTATE_CW;
+ break;
+ default:
+ xres = fb_data->epdc_fb_var.xres;
+ yres = fb_data->epdc_fb_var.yres;
+ rotate = FB_ROTATE_UR;
+ break;
+ }
+ adjust_coordinates(xres, yres, rotate,
+ &coll_region, cur_upd_rect);
+
+ dev_dbg(fb_data->dev, "Adj coll region: l = %d, "
+ "t = %d, w = %d, h = %d\n",
+ cur_upd_rect->left, cur_upd_rect->top,
+ cur_upd_rect->width,
+ cur_upd_rect->height);
+ }
+
+ /*
+ * If we collide with newer updates, then
+ * we don't need to re-submit the update. The
+ * idea is that the newer updates should take
+ * precedence anyways, so we don't want to
+ * overwrite them.
+ */
+ for (temp_mask = fb_data->cur_update->collision_mask, lut = 0;
+ temp_mask != 0;
+ lut++, temp_mask = temp_mask >> 1) {
+ if (!(temp_mask & 0x1))
+ continue;
+
+ if (fb_data->lut_update_order[lut] >=
+ fb_data->cur_update->update_desc->update_order) {
+ dev_dbg(fb_data->dev,
+ "Ignoring collision with"
+ "newer update.\n");
+ ignore_collision = true;
+ break;
+ }
+ }
+
+ if (!ignore_collision) {
+ free_update = false;
+ /*
+ * If update has markers, clear the LUTs to
+ * avoid signalling that they have completed.
+ */
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->cur_update->update_desc->upd_marker_list,
+ upd_list)
+ next_marker->lut_num = INVALID_LUT;
+
+ /* Move to collision list */
+ list_add_tail(&fb_data->cur_update->list,
+ &fb_data->upd_buf_collision_list);
+ }
+ }
+
+ /* Do we need to free the current update descriptor? */
+ if (free_update) {
+ /* Handle condition where WB & LUT are both complete */
+ if (wb_lut_done)
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->cur_update->update_desc->upd_marker_list,
+ upd_list) {
+
+ /* Del from per-update & full list */
+ list_del_init(&next_marker->upd_list);
+ list_del_init(&next_marker->full_list);
+
+ /* Signal completion of update */
+ dev_dbg(fb_data->dev,
+ "Signaling marker (wb) %d\n",
+ next_marker->update_marker);
+ if (next_marker->waiting)
+ complete(&next_marker->update_completion);
+ else
+ kfree(next_marker);
+ }
+
+ /* Free marker list and update descriptor */
+ kfree(fb_data->cur_update->update_desc);
+
+ /* Add to free buffer list */
+ list_add_tail(&fb_data->cur_update->list,
+ &fb_data->upd_buf_free_list);
+
+ /* Check to see if all updates have completed */
+ if (list_empty(&fb_data->upd_pending_list) &&
+ is_free_list_full(fb_data) &&
+ !epdc_luts_active) {
+
+ fb_data->updates_active = false;
+
+ if (fb_data->pwrdown_delay !=
+ FB_POWERDOWN_DISABLE) {
+ /*
+ * Set variable to prevent overlapping
+ * enable/disable requests
+ */
+ fb_data->powering_down = true;
+
+ /* Schedule EPDC disable */
+ schedule_delayed_work(&fb_data->epdc_done_work,
+ msecs_to_jiffies(fb_data->pwrdown_delay));
+
+ /* Reset counter to reduce chance of overflow */
+ fb_data->order_cnt = 0;
+ }
+
+ if (fb_data->waiting_for_idle)
+ complete(&fb_data->updates_done);
+ }
+ }
+
+ /* Clear current update */
+ fb_data->cur_update = NULL;
+
+ /* Clear IRQ for working buffer */
+ epdc_working_buf_intr(false);
+ epdc_clear_working_buf_irq();
+ }
+
+ if (fb_data->upd_scheme != UPDATE_SCHEME_SNAPSHOT) {
+ /* Queued update scheme processing */
+
+ /* Schedule task to submit collision and pending update */
+ if (!fb_data->powering_down)
+ queue_work(fb_data->epdc_submit_workqueue,
+ &fb_data->epdc_submit_work);
+
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+
+ return;
+ }
+
+ /* Snapshot update scheme processing */
+
+ /* Check to see if any LUTs are free */
+ if (!epdc_luts_avail) {
+ dev_dbg(fb_data->dev, "No luts available.\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ epdc_next_lut_15 = epdc_choose_next_lut(fb_data, &next_lut);
+ /* Check to see if there is a valid LUT to use */
+ if (epdc_next_lut_15 && fb_data->tce_prevent && (fb_data->rev < 20)) {
+ dev_dbg(fb_data->dev, "Must wait for LUT15\n");
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ }
+
+ /*
+ * Are any of our collision updates able to go now?
+ * Go through all updates in the collision list and check to see
+ * if the collision mask has been fully cleared
+ */
+ list_for_each_entry(collision_update,
+ &fb_data->upd_buf_collision_list, list) {
+
+ if (collision_update->collision_mask != 0)
+ continue;
+
+ dev_dbg(fb_data->dev, "A collision update is ready to go!\n");
+ /*
+ * We have a collision cleared, so select it
+ * and we will retry the update
+ */
+ fb_data->cur_update = collision_update;
+ list_del_init(&fb_data->cur_update->list);
+ break;
+ }
+
+ /*
+ * If we didn't find a collision update ready to go,
+ * we try to grab one from the update queue
+ */
+ if (fb_data->cur_update == NULL) {
+ /* Is update list empty? */
+ if (list_empty(&fb_data->upd_buf_queue)) {
+ dev_dbg(fb_data->dev, "No pending updates.\n");
+
+ /* No updates pending, so we are done */
+ mutex_unlock(&fb_data->queue_mutex);
+ return;
+ } else {
+ dev_dbg(fb_data->dev, "Found a pending update!\n");
+
+ /* Process next item in update list */
+ fb_data->cur_update =
+ list_entry(fb_data->upd_buf_queue.next,
+ struct update_data_list, list);
+ list_del_init(&fb_data->cur_update->list);
+ }
+ }
+
+ /* Use LUT selected above */
+ fb_data->cur_update->lut_num = next_lut;
+
+ /* Associate LUT with update markers */
+ list_for_each_entry_safe(next_marker, temp,
+ &fb_data->cur_update->update_desc->upd_marker_list, upd_list)
+ next_marker->lut_num = fb_data->cur_update->lut_num;
+
+ /* Mark LUT as containing new update */
+ fb_data->lut_update_order[fb_data->cur_update->lut_num] =
+ fb_data->cur_update->update_desc->update_order;
+
+ /* Enable Collision and WB complete IRQs */
+ epdc_working_buf_intr(true);
+ epdc_lut_complete_intr(fb_data->rev, fb_data->cur_update->lut_num, true);
+
+ /* Program EPDC update to process buffer */
+ next_upd_region =
+ &fb_data->cur_update->update_desc->upd_data.update_region;
+
+ /* add working buffer update here for external mode */
+ if (fb_data->epdc_wb_mode)
+ epdc_working_buffer_update(fb_data, fb_data->cur_update,
+ next_upd_region);
+
+ if (fb_data->cur_update->update_desc->upd_data.temp
+ != TEMP_USE_AMBIENT) {
+ temp_index = mxc_epdc_fb_get_temp_index(fb_data,
+ fb_data->cur_update->update_desc->upd_data.temp);
+ epdc_set_temp(temp_index);
+ } else
+ epdc_set_temp(fb_data->temp_index);
+ epdc_set_update_addr(fb_data->cur_update->phys_addr +
+ fb_data->cur_update->update_desc->epdc_offs);
+ epdc_set_update_coord(next_upd_region->left, next_upd_region->top);
+ epdc_set_update_dimensions(next_upd_region->width,
+ next_upd_region->height);
+ if (fb_data->rev > 20)
+ epdc_set_update_stride(fb_data->cur_update->update_desc->epdc_stride);
+ if (fb_data->wv_modes_update &&
+ (fb_data->cur_update->update_desc->upd_data.waveform_mode
+ == WAVEFORM_MODE_AUTO)) {
+ epdc_set_update_waveform(&fb_data->wv_modes);
+ fb_data->wv_modes_update = false;
+ }
+
+ epdc_submit_update(fb_data->cur_update->lut_num,
+ fb_data->cur_update->update_desc->upd_data.waveform_mode,
+ fb_data->cur_update->update_desc->upd_data.update_mode,
+ false, false, 0);
+
+ /* Release buffer queues */
+ mutex_unlock(&fb_data->queue_mutex);
+
+ return;
+}
+
+static void draw_mode0(struct mxc_epdc_fb_data *fb_data)
+{
+ u32 *upd_buf_ptr;
+ int i;
+ struct fb_var_screeninfo *screeninfo = &fb_data->epdc_fb_var;
+ u32 xres, yres;
+
+ upd_buf_ptr = (u32 *)fb_data->info.screen_base;
+
+ epdc_working_buf_intr(true);
+ epdc_lut_complete_intr(fb_data->rev, 0, true);
+
+ /* Use unrotated (native) width/height */
+ if ((screeninfo->rotate == FB_ROTATE_CW) ||
+ (screeninfo->rotate == FB_ROTATE_CCW)) {
+ xres = screeninfo->yres;
+ yres = screeninfo->xres;
+ } else {
+ xres = screeninfo->xres;
+ yres = screeninfo->yres;
+ }
+
+ /* Program EPDC update to process buffer */
+ epdc_set_update_addr(fb_data->phys_start);
+ epdc_set_update_coord(0, 0);
+ epdc_set_update_dimensions(xres, yres);
+ if (fb_data->rev > 20)
+ epdc_set_update_stride(0);
+ epdc_submit_update(0, fb_data->wv_modes.mode_init, UPDATE_MODE_FULL,
+ false, true, 0xFF);
+
+ dev_dbg(fb_data->dev, "Mode0 update - Waiting for LUT to complete...\n");
+
+ /* Will timeout after ~4-5 seconds */
+
+ for (i = 0; i < 40; i++) {
+ if (!epdc_is_lut_active(0)) {
+ dev_dbg(fb_data->dev, "Mode0 init complete\n");
+ return;
+ }
+ msleep(100);
+ }
+
+ dev_err(fb_data->dev, "Mode0 init failed!\n");
+
+ return;
+}
+
+
+static void mxc_epdc_fb_fw_handler(const struct firmware *fw,
+ void *context)
+{
+ struct mxc_epdc_fb_data *fb_data = context;
+ int ret;
+ struct mxcfb_waveform_data_file *wv_file;
+ int wv_data_offs;
+ int i;
+ struct mxcfb_update_data update;
+ struct mxcfb_update_marker_data upd_marker_data;
+ struct fb_var_screeninfo *screeninfo = &fb_data->epdc_fb_var;
+ u32 xres, yres;
+ struct clk *epdc_parent;
+ unsigned long rounded_parent_rate, epdc_pix_rate,
+ rounded_pix_clk, target_pix_clk;
+
+ if (fw == NULL) {
+ /* If default FW file load failed, we give up */
+ if (fb_data->fw_default_load)
+ return;
+
+ /* Try to load default waveform */
+ dev_dbg(fb_data->dev,
+ "Can't find firmware. Trying fallback fw\n");
+ fb_data->fw_default_load = true;
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ "imx/epdc/epdc.fw", fb_data->dev, GFP_KERNEL, fb_data,
+ mxc_epdc_fb_fw_handler);
+ if (ret)
+ dev_err(fb_data->dev,
+ "Failed request_firmware_nowait err %d\n", ret);
+
+ return;
+ }
+
+ wv_file = (struct mxcfb_waveform_data_file *)fw->data;
+
+ dump_fw_header(fb_data->dev, wv_file);
+
+ /* Get size and allocate temperature range table */
+ fb_data->trt_entries = wv_file->wdh.trc + 1;
+ fb_data->temp_range_bounds = kzalloc(fb_data->trt_entries, GFP_KERNEL);
+
+ for (i = 0; i < fb_data->trt_entries; i++)
+ dev_dbg(fb_data->dev, "trt entry #%d = 0x%x\n", i, *((u8 *)&wv_file->data + i));
+
+ /* Copy TRT data */
+ memcpy(fb_data->temp_range_bounds, &wv_file->data, fb_data->trt_entries);
+
+ /* Set default temperature index using TRT and room temp */
+ fb_data->temp_index = mxc_epdc_fb_get_temp_index(fb_data, DEFAULT_TEMP);
+
+ /* Get offset and size for waveform data */
+ wv_data_offs = sizeof(wv_file->wdh) + fb_data->trt_entries + 1;
+ fb_data->waveform_buffer_size = fw->size - wv_data_offs;
+
+ /* Allocate memory for waveform data */
+ fb_data->waveform_buffer_virt = dma_alloc_coherent(fb_data->dev,
+ fb_data->waveform_buffer_size,
+ &fb_data->waveform_buffer_phys,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->waveform_buffer_virt == NULL) {
+ dev_err(fb_data->dev, "Can't allocate mem for waveform!\n");
+ return;
+ }
+
+ memcpy(fb_data->waveform_buffer_virt, (u8 *)(fw->data) + wv_data_offs,
+ fb_data->waveform_buffer_size);
+
+ /* Check for advanced algorithms */
+ if ((wv_file->wdh.luts & WAVEFORM_HDR_LUT_ADVANCED_ALGO_MASK) != 0) {
+ dev_dbg(fb_data->dev,
+ "Waveform file supports advanced algorithms\n");
+ fb_data->waveform_is_advanced = true;
+ } else {
+ dev_dbg(fb_data->dev,
+ "Waveform file does not support advanced algorithms\n");
+ fb_data->waveform_is_advanced = false;
+ }
+
+ release_firmware(fw);
+
+ /* Enable clocks to access EPDC regs */
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+
+ target_pix_clk = fb_data->cur_mode->vmode->pixclock;
+
+ rounded_pix_clk = clk_round_rate(fb_data->epdc_clk_pix, target_pix_clk);
+
+ if (((rounded_pix_clk >= target_pix_clk + target_pix_clk/100) ||
+ (rounded_pix_clk <= target_pix_clk - target_pix_clk/100))) {
+ /* Can't get close enough without changing parent clk */
+ epdc_parent = clk_get_parent(fb_data->epdc_clk_pix);
+ rounded_parent_rate = clk_round_rate(epdc_parent, target_pix_clk);
+
+ epdc_pix_rate = target_pix_clk;
+ while (epdc_pix_rate < rounded_parent_rate)
+ epdc_pix_rate *= 2;
+ clk_set_rate(epdc_parent, epdc_pix_rate);
+
+ rounded_pix_clk = clk_round_rate(fb_data->epdc_clk_pix, target_pix_clk);
+ if (((rounded_pix_clk >= target_pix_clk + target_pix_clk/100) ||
+ (rounded_pix_clk <= target_pix_clk - target_pix_clk/100)))
+ /* Still can't get a good clock, provide warning */
+ dev_err(fb_data->dev, "Unable to get an accurate EPDC pix clk"
+ "desired = %lu, actual = %lu\n", target_pix_clk,
+ rounded_pix_clk);
+ }
+
+ clk_set_rate(fb_data->epdc_clk_pix, rounded_pix_clk);
+
+ /* Enable pix clk for EPDC */
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+
+ epdc_init_sequence(fb_data);
+
+ /* Disable clocks */
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+
+ fb_data->hw_ready = true;
+ fb_data->hw_initializing = false;
+
+ /* Use unrotated (native) width/height */
+ if ((screeninfo->rotate == FB_ROTATE_CW) ||
+ (screeninfo->rotate == FB_ROTATE_CCW)) {
+ xres = screeninfo->yres;
+ yres = screeninfo->xres;
+ } else {
+ xres = screeninfo->xres;
+ yres = screeninfo->yres;
+ }
+
+ update.update_region.left = 0;
+ update.update_region.width = xres;
+ update.update_region.top = 0;
+ update.update_region.height = yres;
+ update.update_mode = UPDATE_MODE_FULL;
+ update.waveform_mode = WAVEFORM_MODE_AUTO;
+ update.update_marker = INIT_UPDATE_MARKER;
+ update.temp = TEMP_USE_AMBIENT;
+ update.flags = 0;
+ update.dither_mode = 0;
+
+ upd_marker_data.update_marker = update.update_marker;
+
+ mxc_epdc_fb_send_update(&update, &fb_data->info);
+
+ /* Block on initial update */
+ ret = mxc_epdc_fb_wait_update_complete(&upd_marker_data,
+ &fb_data->info);
+ if (ret < 0)
+ dev_err(fb_data->dev,
+ "Wait for initial update complete failed."
+ " Error = 0x%x", ret);
+}
+
+static int mxc_epdc_fb_init_hw(struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+ int ret;
+
+ /*
+ * Create fw search string based on ID string in selected videomode.
+ * Format is "imx/epdc/epdc_[panel string].fw"
+ */
+ if (fb_data->cur_mode) {
+ strcat(fb_data->fw_str, "imx/epdc/epdc_");
+ strcat(fb_data->fw_str, fb_data->cur_mode->vmode->name);
+ strcat(fb_data->fw_str, ".fw");
+ }
+
+ fb_data->fw_default_load = false;
+
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ fb_data->fw_str, fb_data->dev, GFP_KERNEL,
+ fb_data, mxc_epdc_fb_fw_handler);
+ if (ret)
+ dev_dbg(fb_data->dev,
+ "Failed request_firmware_nowait err %d\n", ret);
+
+ return ret;
+}
+
+static ssize_t store_update(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxcfb_update_data update;
+ struct fb_info *info = dev_get_drvdata(device);
+ struct mxc_epdc_fb_data *fb_data = (struct mxc_epdc_fb_data *)info;
+
+ if (strncmp(buf, "direct", 6) == 0)
+ update.waveform_mode = fb_data->wv_modes.mode_du;
+ else if (strncmp(buf, "gc16", 4) == 0)
+ update.waveform_mode = fb_data->wv_modes.mode_gc16;
+ else if (strncmp(buf, "gc4", 3) == 0)
+ update.waveform_mode = fb_data->wv_modes.mode_gc4;
+
+ /* Now, request full screen update */
+ update.update_region.left = 0;
+ update.update_region.width = fb_data->epdc_fb_var.xres;
+ update.update_region.top = 0;
+ update.update_region.height = fb_data->epdc_fb_var.yres;
+ update.update_mode = UPDATE_MODE_FULL;
+ update.temp = TEMP_USE_AMBIENT;
+ update.update_marker = 0;
+ update.flags = 0;
+
+ mxc_epdc_fb_send_update(&update, info);
+
+ return count;
+}
+
+static struct device_attribute fb_attrs[] = {
+ __ATTR(update, S_IRUGO|S_IWUSR, NULL, store_update),
+};
+
+static const struct of_device_id imx_epdc_dt_ids[] = {
+ { .compatible = "fsl,imx7d-epdc", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_epdc_dt_ids);
+
+static int mxc_epdc_fb_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct pinctrl *pinctrl;
+ struct mxc_epdc_fb_data *fb_data;
+ struct resource *res;
+ struct fb_info *info;
+ char *options, *opt;
+ char *panel_str = NULL;
+ char name[] = "mxcepdcfb";
+ struct fb_videomode *vmode;
+ int xres_virt, yres_virt, buf_size;
+ int xres_virt_rot, yres_virt_rot, pix_size_rot;
+ struct fb_var_screeninfo *var_info;
+ struct fb_fix_screeninfo *fix_info;
+ struct pxp_config_data *pxp_conf;
+ struct pxp_proc_data *proc_data;
+ struct scatterlist *sg;
+ struct update_data_list *upd_list;
+ struct update_data_list *plist, *temp_list;
+ int i;
+ unsigned long x_mem_size = 0;
+ u32 val;
+ int irq;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *node;
+ phandle phandle;
+ u32 out_val[3];
+ int enable_gpio;
+ enum of_gpio_flags flag;
+ unsigned short *wk_p;
+
+ if (!np)
+ return -EINVAL;
+
+ fb_data = (struct mxc_epdc_fb_data *)framebuffer_alloc(
+ sizeof(struct mxc_epdc_fb_data), &pdev->dev);
+ if (fb_data == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = of_property_read_u32_array(np, "epdc-ram", out_val, 3);
+ if (ret) {
+ dev_dbg(&pdev->dev, "no epdc-ram property found\n");
+ } else {
+ phandle = *out_val;
+
+ node = of_find_node_by_phandle(phandle);
+ if (!node) {
+ dev_dbg(&pdev->dev, "not find gpr node by phandle\n");
+ ret = PTR_ERR(node);
+ goto out_fbdata;
+ }
+ fb_data->gpr = syscon_node_to_regmap(node);
+ if (IS_ERR(fb_data->gpr)) {
+ dev_err(&pdev->dev, "failed to get gpr regmap\n");
+ ret = PTR_ERR(fb_data->gpr);
+ goto out_fbdata;
+ }
+ of_node_put(node);
+ fb_data->req_gpr = out_val[1];
+ fb_data->req_bit = out_val[2];
+
+ regmap_update_bits(fb_data->gpr, fb_data->req_gpr,
+ 1 << fb_data->req_bit, 0);
+ }
+
+ if (of_find_property(np, "en-gpios", NULL)) {
+ enable_gpio = of_get_named_gpio_flags(np, "en-gpios", 0, &flag);
+ if (enable_gpio == -EPROBE_DEFER) {
+ dev_info(&pdev->dev, "GPIO requested is not"
+ "here yet, deferring the probe\n");
+ return -EPROBE_DEFER;
+ }
+ if (!gpio_is_valid(enable_gpio)) {
+ dev_warn(&pdev->dev, "No dt property: en-gpios\n");
+ } else {
+
+ ret = devm_gpio_request_one(&pdev->dev,
+ enable_gpio,
+ (flag & OF_GPIO_ACTIVE_LOW)
+ ? GPIOF_OUT_INIT_LOW :
+ GPIOF_OUT_INIT_HIGH,
+ "en_pins");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request gpio"
+ " %d: %d\n", enable_gpio, ret);
+ return -EINVAL;
+ }
+ }
+ }
+
+ /* Get platform data and check validity */
+ fb_data->pdata = &epdc_data;
+ if ((fb_data->pdata == NULL) || (fb_data->pdata->num_modes < 1)
+ || (fb_data->pdata->epdc_mode == NULL)
+ || (fb_data->pdata->epdc_mode->vmode == NULL)) {
+ ret = -EINVAL;
+ goto out_fbdata;
+ }
+
+ if (fb_get_options(name, &options)) {
+ ret = -ENODEV;
+ goto out_fbdata;
+ }
+
+ fb_data->epdc_wb_mode = 1;
+ fb_data->tce_prevent = 0;
+
+ if (options)
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+
+ if (!strncmp(opt, "bpp=", 4))
+ fb_data->default_bpp =
+ simple_strtoul(opt + 4, NULL, 0);
+ else if (!strncmp(opt, "x_mem=", 6))
+ x_mem_size = memparse(opt + 6, NULL);
+ else if (!strncmp(opt, "tce_prevent", 11))
+ fb_data->tce_prevent = 1;
+ else
+ panel_str = opt;
+ }
+
+ fb_data->dev = &pdev->dev;
+
+ if (!fb_data->default_bpp)
+ fb_data->default_bpp = 16;
+
+ /* Set default (first defined mode) before searching for a match */
+ fb_data->cur_mode = &fb_data->pdata->epdc_mode[0];
+
+ if (panel_str)
+ for (i = 0; i < fb_data->pdata->num_modes; i++)
+ if (!strcmp(fb_data->pdata->epdc_mode[i].vmode->name,
+ panel_str)) {
+ fb_data->cur_mode =
+ &fb_data->pdata->epdc_mode[i];
+ break;
+ }
+
+ vmode = fb_data->cur_mode->vmode;
+
+ platform_set_drvdata(pdev, fb_data);
+ info = &fb_data->info;
+
+ /* Allocate color map for the FB */
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret)
+ goto out_fbdata;
+
+ dev_dbg(&pdev->dev, "resolution %dx%d, bpp %d\n",
+ vmode->xres, vmode->yres, fb_data->default_bpp);
+
+ /*
+ * GPU alignment restrictions dictate framebuffer parameters:
+ * - 32-byte alignment for buffer width
+ * - 128-byte alignment for buffer height
+ * => 4K buffer alignment for buffer start
+ */
+ xres_virt = ALIGN(vmode->xres, 32);
+ yres_virt = ALIGN(vmode->yres, 128);
+ fb_data->max_pix_size = PAGE_ALIGN(xres_virt * yres_virt);
+
+ /*
+ * Have to check to see if aligned buffer size when rotated
+ * is bigger than when not rotated, and use the max
+ */
+ xres_virt_rot = ALIGN(vmode->yres, 32);
+ yres_virt_rot = ALIGN(vmode->xres, 128);
+ pix_size_rot = PAGE_ALIGN(xres_virt_rot * yres_virt_rot);
+ fb_data->max_pix_size = (fb_data->max_pix_size > pix_size_rot) ?
+ fb_data->max_pix_size : pix_size_rot;
+
+ buf_size = fb_data->max_pix_size * fb_data->default_bpp/8;
+
+ /* Compute the number of screens needed based on X memory requested */
+ if (x_mem_size > 0) {
+ fb_data->num_screens = DIV_ROUND_UP(x_mem_size, buf_size);
+ if (fb_data->num_screens < NUM_SCREENS_MIN)
+ fb_data->num_screens = NUM_SCREENS_MIN;
+ else if (buf_size * fb_data->num_screens > SZ_16M)
+ fb_data->num_screens = SZ_16M / buf_size;
+ } else
+ fb_data->num_screens = NUM_SCREENS_MIN;
+
+ fb_data->map_size = buf_size * fb_data->num_screens;
+ dev_dbg(&pdev->dev, "memory to allocate: %d\n", fb_data->map_size);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ ret = -ENODEV;
+ goto out_cmap;
+ }
+
+ epdc_v2_base = devm_ioremap_resource(&pdev->dev, res);
+ if (epdc_v2_base == NULL) {
+ ret = -ENOMEM;
+ goto out_cmap;
+ }
+
+ /* Allocate FB memory */
+ info->screen_base = dma_alloc_writecombine(&pdev->dev,
+ fb_data->map_size,
+ &fb_data->phys_start,
+ GFP_DMA | GFP_KERNEL);
+
+ if (info->screen_base == NULL) {
+ ret = -ENOMEM;
+ goto out_cmap;
+ }
+ dev_dbg(&pdev->dev, "allocated at %p:0x%x\n", info->screen_base,
+ fb_data->phys_start);
+
+ var_info = &info->var;
+ var_info->activate = FB_ACTIVATE_TEST;
+ var_info->bits_per_pixel = fb_data->default_bpp;
+ var_info->xres = vmode->xres;
+ var_info->yres = vmode->yres;
+ var_info->xres_virtual = xres_virt;
+ /* Additional screens allow for panning and buffer flipping */
+ var_info->yres_virtual = yres_virt * fb_data->num_screens;
+
+ var_info->pixclock = vmode->pixclock;
+ var_info->left_margin = vmode->left_margin;
+ var_info->right_margin = vmode->right_margin;
+ var_info->upper_margin = vmode->upper_margin;
+ var_info->lower_margin = vmode->lower_margin;
+ var_info->hsync_len = vmode->hsync_len;
+ var_info->vsync_len = vmode->vsync_len;
+ var_info->vmode = FB_VMODE_NONINTERLACED;
+
+ switch (fb_data->default_bpp) {
+ case 32:
+ case 24:
+ var_info->red.offset = 16;
+ var_info->red.length = 8;
+ var_info->green.offset = 8;
+ var_info->green.length = 8;
+ var_info->blue.offset = 0;
+ var_info->blue.length = 8;
+ break;
+
+ case 16:
+ var_info->red.offset = 11;
+ var_info->red.length = 5;
+ var_info->green.offset = 5;
+ var_info->green.length = 6;
+ var_info->blue.offset = 0;
+ var_info->blue.length = 5;
+ break;
+
+ case 8:
+ /*
+ * For 8-bit grayscale, R, G, and B offset are equal.
+ *
+ */
+ var_info->grayscale = GRAYSCALE_8BIT;
+
+ var_info->red.length = 8;
+ var_info->red.offset = 0;
+ var_info->red.msb_right = 0;
+ var_info->green.length = 8;
+ var_info->green.offset = 0;
+ var_info->green.msb_right = 0;
+ var_info->blue.length = 8;
+ var_info->blue.offset = 0;
+ var_info->blue.msb_right = 0;
+ break;
+
+ default:
+ dev_err(&pdev->dev, "unsupported bitwidth %d\n",
+ fb_data->default_bpp);
+ ret = -EINVAL;
+ goto out_dma_fb;
+ }
+
+ fix_info = &info->fix;
+
+ strcpy(fix_info->id, "mxc_epdc_fb");
+ fix_info->type = FB_TYPE_PACKED_PIXELS;
+ fix_info->visual = FB_VISUAL_TRUECOLOR;
+ fix_info->xpanstep = 0;
+ fix_info->ypanstep = 0;
+ fix_info->ywrapstep = 0;
+ fix_info->accel = FB_ACCEL_NONE;
+ fix_info->smem_start = fb_data->phys_start;
+ fix_info->smem_len = fb_data->map_size;
+ fix_info->ypanstep = 0;
+
+ fb_data->native_width = vmode->xres;
+ fb_data->native_height = vmode->yres;
+
+ info->fbops = &mxc_epdc_fb_ops;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->pseudo_palette = fb_data->pseudo_palette;
+ info->screen_size = info->fix.smem_len;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ mxc_epdc_fb_set_fix(info);
+
+ fb_data->auto_mode = AUTO_UPDATE_MODE_REGION_MODE;
+ fb_data->upd_scheme = UPDATE_SCHEME_QUEUE_AND_MERGE;
+
+ /* Initialize our internal copy of the screeninfo */
+ fb_data->epdc_fb_var = *var_info;
+ fb_data->fb_offset = 0;
+ fb_data->eof_sync_period = 0;
+
+ fb_data->epdc_clk_axi = clk_get(fb_data->dev, "epdc_axi");
+ if (IS_ERR(fb_data->epdc_clk_axi)) {
+ dev_err(&pdev->dev, "Unable to get EPDC AXI clk."
+ "err = %d\n", (int)fb_data->epdc_clk_axi);
+ ret = -ENODEV;
+ goto out_dma_fb;
+ }
+ fb_data->epdc_clk_pix = clk_get(fb_data->dev, "epdc_pix");
+ if (IS_ERR(fb_data->epdc_clk_pix)) {
+ dev_err(&pdev->dev, "Unable to get EPDC pix clk."
+ "err = %d\n", (int)fb_data->epdc_clk_pix);
+ ret = -ENODEV;
+ goto out_dma_fb;
+ }
+
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+ val = __raw_readl(EPDC_VERSION);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+ fb_data->rev = ((val & EPDC_VERSION_MAJOR_MASK) >>
+ EPDC_VERSION_MAJOR_OFFSET) * 10
+ + ((val & EPDC_VERSION_MINOR_MASK) >>
+ EPDC_VERSION_MINOR_OFFSET);
+ dev_dbg(&pdev->dev, "EPDC version = %d\n", fb_data->rev);
+
+ if (fb_data->rev < 20) {
+ fb_data->num_luts = EPDC_V1_NUM_LUTS;
+ fb_data->max_num_updates = EPDC_V1_MAX_NUM_UPDATES;
+ } else {
+ fb_data->num_luts = EPDC_V2_NUM_LUTS;
+ fb_data->max_num_updates = EPDC_V2_MAX_NUM_UPDATES;
+ if (vmode->xres > EPDC_V2_MAX_UPDATE_WIDTH)
+ fb_data->restrict_width = true;
+ }
+ fb_data->max_num_buffers = EPDC_MAX_NUM_BUFFERS;
+
+ /*
+ * Initialize lists for pending updates,
+ * active update requests, update collisions,
+ * and freely available updates.
+ */
+ INIT_LIST_HEAD(&fb_data->upd_pending_list);
+ INIT_LIST_HEAD(&fb_data->upd_buf_queue);
+ INIT_LIST_HEAD(&fb_data->upd_buf_free_list);
+ INIT_LIST_HEAD(&fb_data->upd_buf_collision_list);
+
+ /* Allocate update buffers and add them to the list */
+ for (i = 0; i < fb_data->max_num_updates; i++) {
+ upd_list = kzalloc(sizeof(*upd_list), GFP_KERNEL);
+ if (upd_list == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_lists;
+ }
+
+ /* Add newly allocated buffer to free list */
+ list_add(&upd_list->list, &fb_data->upd_buf_free_list);
+ }
+
+ fb_data->virt_addr_updbuf =
+ kzalloc(sizeof(void *) * fb_data->max_num_buffers, GFP_KERNEL);
+ fb_data->phys_addr_updbuf =
+ kzalloc(sizeof(dma_addr_t) * fb_data->max_num_buffers,
+ GFP_KERNEL);
+ for (i = 0; i < fb_data->max_num_buffers; i++) {
+ /*
+ * Allocate memory for PxP output buffer.
+ * Each update buffer is 1 byte per pixel, and can
+ * be as big as the full-screen frame buffer
+ */
+ fb_data->virt_addr_updbuf[i] =
+ kmalloc(fb_data->max_pix_size, GFP_KERNEL);
+ fb_data->phys_addr_updbuf[i] =
+ virt_to_phys(fb_data->virt_addr_updbuf[i]);
+ if (fb_data->virt_addr_updbuf[i] == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_buffers;
+ }
+
+ dev_dbg(fb_data->info.device, "allocated %d bytes @ 0x%08X\n",
+ fb_data->max_pix_size, fb_data->phys_addr_updbuf[i]);
+ }
+
+ /* Counter indicating which update buffer should be used next. */
+ fb_data->upd_buffer_num = 0;
+
+ /*
+ * Allocate memory for PxP SW workaround buffer
+ * These buffers are used to hold copy of the update region,
+ * before sending it to PxP for processing.
+ */
+ fb_data->virt_addr_copybuf =
+ dma_alloc_coherent(fb_data->info.device, fb_data->max_pix_size*2,
+ &fb_data->phys_addr_copybuf,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->virt_addr_copybuf == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_buffers;
+ }
+
+ fb_data->virt_addr_y4 =
+ dma_alloc_coherent(fb_data->info.device, fb_data->max_pix_size*2,
+ &fb_data->phys_addr_y4,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->virt_addr_y4 == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_buffers;
+ }
+
+ fb_data->virt_addr_y4c =
+ dma_alloc_coherent(fb_data->info.device, fb_data->max_pix_size*2,
+ &fb_data->phys_addr_y4c,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->virt_addr_y4c == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_buffers;
+ }
+
+ fb_data->virt_addr_black =
+ dma_alloc_coherent(fb_data->info.device, fb_data->max_pix_size*2,
+ &fb_data->phys_addr_black,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->virt_addr_black == NULL) {
+ ret = -ENOMEM;
+ goto out_upd_buffers;
+ }
+
+ fb_data->working_buffer_size = vmode->yres * vmode->xres * 2;
+
+ /* Allocate memory for EPDC working buffer */
+ fb_data->working_buffer_virt =
+ dma_alloc_coherent(&pdev->dev, fb_data->working_buffer_size,
+ &fb_data->working_buffer_phys,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->working_buffer_virt == NULL) {
+ dev_err(&pdev->dev, "Can't allocate mem for working buf!\n");
+ ret = -ENOMEM;
+ goto out_copybuffer;
+ }
+
+ /* initialize the working buffer */
+ wk_p = (unsigned short *)fb_data->working_buffer_virt;
+ for (i = 0; i < fb_data->cur_mode->vmode->xres *
+ fb_data->cur_mode->vmode->yres; i++) {
+ *wk_p = 0x00F0;
+ wk_p++;
+ }
+
+ fb_data->tmp_working_buffer_virt =
+ dma_alloc_coherent(&pdev->dev, fb_data->working_buffer_size,
+ &fb_data->tmp_working_buffer_phys,
+ GFP_DMA | GFP_KERNEL);
+ if (fb_data->tmp_working_buffer_virt == NULL) {
+ dev_err(&pdev->dev, "Can't allocate mem for tmp working buf!\n");
+ ret = -ENOMEM;
+ goto out_copybuffer;
+ }
+
+ /* Initialize EPDC pins */
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(&pdev->dev, "can't get/select pinctrl\n");
+ ret = PTR_ERR(pinctrl);
+ goto out_copybuffer;
+ }
+
+ fb_data->in_init = false;
+
+ fb_data->hw_ready = false;
+ fb_data->hw_initializing = false;
+
+ /*
+ * Set default waveform mode values.
+ * Should be overwritten via ioctl.
+ */
+ fb_data->wv_modes.mode_init = 0;
+ fb_data->wv_modes.mode_du = 1;
+ fb_data->wv_modes.mode_gc4 = 3;
+ fb_data->wv_modes.mode_gc8 = 2;
+ fb_data->wv_modes.mode_gc16 = 2;
+ fb_data->wv_modes.mode_gc32 = 2;
+ fb_data->wv_modes_update = true;
+
+ /* Initialize marker list */
+ INIT_LIST_HEAD(&fb_data->full_marker_list);
+
+ /* Initialize all LUTs to inactive */
+ fb_data->lut_update_order =
+ kzalloc(fb_data->num_luts * sizeof(u32 *), GFP_KERNEL);
+ for (i = 0; i < fb_data->num_luts; i++)
+ fb_data->lut_update_order[i] = 0;
+
+ INIT_DELAYED_WORK(&fb_data->epdc_done_work, epdc_done_work_func);
+ fb_data->epdc_submit_workqueue = alloc_workqueue("EPDC Submit",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI |
+ WQ_CPU_INTENSIVE | WQ_UNBOUND, 1);
+ INIT_WORK(&fb_data->epdc_submit_work, epdc_submit_work_func);
+ fb_data->epdc_intr_workqueue = alloc_workqueue("EPDC Interrupt",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI |
+ WQ_CPU_INTENSIVE | WQ_UNBOUND, 1);
+ INIT_WORK(&fb_data->epdc_intr_work, epdc_intr_work_func);
+
+ /* Retrieve EPDC IRQ num */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "cannot get IRQ resource\n");
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+ fb_data->epdc_irq = irq;
+
+ /* Register IRQ handler */
+ ret = devm_request_irq(&pdev->dev, fb_data->epdc_irq,
+ mxc_epdc_irq_handler, 0, "epdc", fb_data);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
+ fb_data->epdc_irq, ret);
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+
+ info->fbdefio = &mxc_epdc_fb_defio;
+#ifdef CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE
+ fb_deferred_io_init(info);
+#endif
+
+ /* get pmic regulators */
+ fb_data->display_regulator = devm_regulator_get(&pdev->dev, "DISPLAY");
+ if (IS_ERR(fb_data->display_regulator)) {
+ dev_err(&pdev->dev, "Unable to get display PMIC regulator."
+ "err = 0x%x\n", (int)fb_data->display_regulator);
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+ fb_data->vcom_regulator = devm_regulator_get(&pdev->dev, "VCOM");
+ if (IS_ERR(fb_data->vcom_regulator)) {
+ dev_err(&pdev->dev, "Unable to get VCOM regulator."
+ "err = 0x%x\n", (int)fb_data->vcom_regulator);
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+ fb_data->v3p3_regulator = devm_regulator_get(&pdev->dev, "V3P3");
+ if (IS_ERR(fb_data->v3p3_regulator)) {
+ dev_err(&pdev->dev, "Unable to get V3P3 regulator."
+ "err = 0x%x\n", (int)fb_data->vcom_regulator);
+ ret = -ENODEV;
+ goto out_dma_work_buf;
+ }
+
+ if (device_create_file(info->dev, &fb_attrs[0]))
+ dev_err(&pdev->dev, "Unable to create file from fb_attrs\n");
+
+ fb_data->cur_update = NULL;
+
+ mutex_init(&fb_data->queue_mutex);
+ mutex_init(&fb_data->pxp_mutex);
+ mutex_init(&fb_data->power_mutex);
+
+ /*
+ * Fill out PxP config data structure based on FB info and
+ * processing tasks required
+ */
+ pxp_conf = &fb_data->pxp_conf;
+ proc_data = &pxp_conf->proc_data;
+
+ /* Initialize non-channel-specific PxP parameters */
+ proc_data->drect.left = proc_data->srect.left = 0;
+ proc_data->drect.top = proc_data->srect.top = 0;
+ proc_data->drect.width = proc_data->srect.width = fb_data->info.var.xres;
+ proc_data->drect.height = proc_data->srect.height = fb_data->info.var.yres;
+ proc_data->scaling = 0;
+ proc_data->hflip = 0;
+ proc_data->vflip = 0;
+ proc_data->rotate = 0;
+ proc_data->bgcolor = 0;
+ proc_data->overlay_state = 0;
+ proc_data->lut_transform = PXP_LUT_NONE;
+ proc_data->lut_map = NULL;
+
+ /*
+ * We initially configure PxP for RGB->YUV conversion,
+ * and only write out Y component of the result.
+ */
+
+ /*
+ * Initialize S0 channel parameters
+ * Parameters should match FB format/width/height
+ */
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_RGB565;
+ pxp_conf->s0_param.width = fb_data->info.var.xres_virtual;
+ pxp_conf->s0_param.stride = (var_info->bits_per_pixel * pxp_conf->s0_param.width) >> 3;
+ pxp_conf->s0_param.height = fb_data->info.var.yres;
+ pxp_conf->s0_param.color_key = -1;
+ pxp_conf->s0_param.color_key_enable = false;
+
+ /*
+ * Initialize OL0 channel parameters
+ * No overlay will be used for PxP operation
+ */
+ pxp_conf->ol_param[0].combine_enable = false;
+ pxp_conf->ol_param[0].width = 0;
+ pxp_conf->ol_param[0].height = 0;
+ pxp_conf->ol_param[0].pixel_fmt = PXP_PIX_FMT_RGB565;
+ pxp_conf->ol_param[0].color_key_enable = false;
+ pxp_conf->ol_param[0].color_key = -1;
+ pxp_conf->ol_param[0].global_alpha_enable = false;
+ pxp_conf->ol_param[0].global_alpha = 0;
+ pxp_conf->ol_param[0].local_alpha_enable = false;
+
+ /*
+ * Initialize Output channel parameters
+ * Output is Y-only greyscale
+ * Output width/height will vary based on update region size
+ */
+ pxp_conf->out_param.width = fb_data->info.var.xres;
+ pxp_conf->out_param.height = fb_data->info.var.yres;
+ pxp_conf->out_param.stride = pxp_conf->out_param.width;
+ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_GREY;
+
+ /* Initialize color map for conversion of 8-bit gray pixels */
+ fb_data->pxp_conf.proc_data.lut_map = kmalloc(256, GFP_KERNEL);
+ if (fb_data->pxp_conf.proc_data.lut_map == NULL) {
+ dev_err(&pdev->dev, "Can't allocate mem for lut map!\n");
+ ret = -ENOMEM;
+ goto out_dma_work_buf;
+ }
+ for (i = 0; i < 256; i++)
+ fb_data->pxp_conf.proc_data.lut_map[i] = i;
+
+ fb_data->pxp_conf.proc_data.lut_map_updated = true;
+
+ /*
+ * Ensure this is set to NULL here...we will initialize pxp_chan
+ * later in our thread.
+ */
+ fb_data->pxp_chan = NULL;
+
+ /* Initialize Scatter-gather list containing 2 buffer addresses. */
+ sg = fb_data->sg;
+ sg_init_table(sg, SG_NUM);
+
+ /*
+ * For use in PxP transfers:
+ * sg[0] holds the FB buffer pointer
+ * sg[1] holds the Output buffer pointer (configured before TX request)
+ */
+ sg_dma_address(&sg[0]) = info->fix.smem_start;
+ sg_set_page(&sg[0], virt_to_page(info->screen_base),
+ info->fix.smem_len, offset_in_page(info->screen_base));
+
+ fb_data->order_cnt = 0;
+ fb_data->waiting_for_wb = false;
+ fb_data->waiting_for_lut = false;
+ fb_data->waiting_for_lut15 = false;
+ fb_data->waiting_for_idle = false;
+ fb_data->blank = FB_BLANK_UNBLANK;
+ fb_data->power_state = POWER_STATE_OFF;
+ fb_data->powering_down = false;
+ fb_data->wait_for_powerdown = false;
+ fb_data->updates_active = false;
+ fb_data->pwrdown_delay = 0;
+
+ /* Register FB */
+ ret = register_framebuffer(info);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "register_framebuffer failed with error %d\n", ret);
+ goto out_lutmap;
+ }
+
+ g_fb_data = fb_data;
+
+ pm_runtime_enable(fb_data->dev);
+
+#ifdef DEFAULT_PANEL_HW_INIT
+ ret = mxc_epdc_fb_init_hw((struct fb_info *)fb_data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to initialize HW!\n");
+ }
+#endif
+
+ goto out;
+
+out_lutmap:
+ kfree(fb_data->pxp_conf.proc_data.lut_map);
+out_dma_work_buf:
+ dma_free_writecombine(&pdev->dev, fb_data->working_buffer_size,
+ fb_data->working_buffer_virt, fb_data->working_buffer_phys);
+out_copybuffer:
+ dma_free_writecombine(&pdev->dev, fb_data->max_pix_size*2,
+ fb_data->virt_addr_copybuf,
+ fb_data->phys_addr_copybuf);
+out_upd_buffers:
+ for (i = 0; i < fb_data->max_num_buffers; i++)
+ if (fb_data->virt_addr_updbuf[i] != NULL)
+ kfree(fb_data->virt_addr_updbuf[i]);
+ if (fb_data->virt_addr_updbuf != NULL)
+ kfree(fb_data->virt_addr_updbuf);
+ if (fb_data->phys_addr_updbuf != NULL)
+ kfree(fb_data->phys_addr_updbuf);
+out_upd_lists:
+ list_for_each_entry_safe(plist, temp_list, &fb_data->upd_buf_free_list,
+ list) {
+ list_del(&plist->list);
+ kfree(plist);
+ }
+out_dma_fb:
+ dma_free_writecombine(&pdev->dev, fb_data->map_size, info->screen_base,
+ fb_data->phys_start);
+
+out_cmap:
+ fb_dealloc_cmap(&info->cmap);
+out_fbdata:
+ kfree(fb_data);
+out:
+ return ret;
+}
+
+static int mxc_epdc_fb_remove(struct platform_device *pdev)
+{
+ struct update_data_list *plist, *temp_list;
+ struct mxc_epdc_fb_data *fb_data = platform_get_drvdata(pdev);
+ int i;
+
+ mxc_epdc_fb_blank(FB_BLANK_POWERDOWN, &fb_data->info);
+
+ flush_workqueue(fb_data->epdc_submit_workqueue);
+ destroy_workqueue(fb_data->epdc_submit_workqueue);
+
+ unregister_framebuffer(&fb_data->info);
+
+ for (i = 0; i < fb_data->max_num_buffers; i++)
+ if (fb_data->virt_addr_updbuf[i] != NULL)
+ kfree(fb_data->virt_addr_updbuf[i]);
+ if (fb_data->virt_addr_updbuf != NULL)
+ kfree(fb_data->virt_addr_updbuf);
+ if (fb_data->phys_addr_updbuf != NULL)
+ kfree(fb_data->phys_addr_updbuf);
+
+ dma_free_writecombine(&pdev->dev, fb_data->working_buffer_size,
+ fb_data->working_buffer_virt,
+ fb_data->working_buffer_phys);
+ if (fb_data->waveform_buffer_virt != NULL)
+ dma_free_writecombine(&pdev->dev, fb_data->waveform_buffer_size,
+ fb_data->waveform_buffer_virt,
+ fb_data->waveform_buffer_phys);
+ if (fb_data->virt_addr_copybuf != NULL)
+ dma_free_writecombine(&pdev->dev, fb_data->max_pix_size*2,
+ fb_data->virt_addr_copybuf,
+ fb_data->phys_addr_copybuf);
+ list_for_each_entry_safe(plist, temp_list, &fb_data->upd_buf_free_list,
+ list) {
+ list_del(&plist->list);
+ kfree(plist);
+ }
+#ifdef CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE
+ fb_deferred_io_cleanup(&fb_data->info);
+#endif
+
+ dma_free_writecombine(&pdev->dev, fb_data->map_size, fb_data->info.screen_base,
+ fb_data->phys_start);
+
+ /* Release PxP-related resources */
+ if (fb_data->pxp_chan != NULL)
+ dma_release_channel(&fb_data->pxp_chan->dma_chan);
+
+ fb_dealloc_cmap(&fb_data->info.cmap);
+
+ framebuffer_release(&fb_data->info);
+ if (!IS_ERR_OR_NULL(fb_data->gpr))
+ regmap_update_bits(fb_data->gpr, fb_data->req_gpr,
+ 1 << fb_data->req_bit, 1 << fb_data->req_bit);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mxc_epdc_fb_suspend(struct device *dev)
+{
+ struct mxc_epdc_fb_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ data->pwrdown_delay = FB_POWERDOWN_DISABLE;
+ ret = mxc_epdc_fb_blank(FB_BLANK_POWERDOWN, &data->info);
+
+ if (ret)
+ goto out;
+
+out:
+ pinctrl_pm_select_sleep_state(dev);
+
+ return ret;
+}
+
+static int mxc_epdc_fb_resume(struct device *dev)
+{
+ struct mxc_epdc_fb_data *data = dev_get_drvdata(dev);
+
+ pinctrl_pm_select_default_state(dev);
+
+ mxc_epdc_fb_blank(FB_BLANK_UNBLANK, &data->info);
+ epdc_init_settings(data);
+ data->updates_active = false;
+
+ return 0;
+}
+#else
+#define mxc_epdc_fb_suspend NULL
+#define mxc_epdc_fb_resume NULL
+#endif
+
+#ifdef CONFIG_PM
+static int mxc_epdc_fb_runtime_suspend(struct device *dev)
+{
+ release_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "epdc busfreq high release.\n");
+
+ return 0;
+}
+
+static int mxc_epdc_fb_runtime_resume(struct device *dev)
+{
+ request_bus_freq(BUS_FREQ_HIGH);
+ dev_dbg(dev, "epdc busfreq high request.\n");
+
+ return 0;
+}
+#else
+#define mxc_epdc_fb_runtime_suspend NULL
+#define mxc_epdc_fb_runtime_resume NULL
+#endif
+
+static const struct dev_pm_ops mxc_epdc_fb_pm_ops = {
+ SET_RUNTIME_PM_OPS(mxc_epdc_fb_runtime_suspend,
+ mxc_epdc_fb_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(mxc_epdc_fb_suspend, mxc_epdc_fb_resume)
+};
+
+static void mxc_epdc_fb_shutdown(struct platform_device *pdev)
+{
+ struct mxc_epdc_fb_data *fb_data = platform_get_drvdata(pdev);
+
+ /* Disable power to the EPD panel */
+ if (regulator_is_enabled(fb_data->vcom_regulator))
+ regulator_disable(fb_data->vcom_regulator);
+ if (regulator_is_enabled(fb_data->display_regulator))
+ regulator_disable(fb_data->display_regulator);
+
+ /* Disable clocks to EPDC */
+ clk_prepare_enable(fb_data->epdc_clk_axi);
+ clk_prepare_enable(fb_data->epdc_clk_pix);
+ __raw_writel(EPDC_CTRL_CLKGATE, EPDC_CTRL_SET);
+ clk_disable_unprepare(fb_data->epdc_clk_pix);
+ clk_disable_unprepare(fb_data->epdc_clk_axi);
+
+ /* turn off the V3p3 */
+ if (regulator_is_enabled(fb_data->v3p3_regulator))
+ regulator_disable(fb_data->v3p3_regulator);
+}
+
+static struct platform_driver mxc_epdc_fb_driver = {
+ .probe = mxc_epdc_fb_probe,
+ .remove = mxc_epdc_fb_remove,
+ .shutdown = mxc_epdc_fb_shutdown,
+ .driver = {
+ .name = "imx_epdc_v2_fb",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(imx_epdc_dt_ids),
+ .pm = &mxc_epdc_fb_pm_ops,
+ },
+};
+
+/* Callback function triggered after PxP receives an EOF interrupt */
+static void pxp_dma_done(void *arg)
+{
+ struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
+ struct dma_chan *chan = tx_desc->txd.chan;
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ struct mxc_epdc_fb_data *fb_data = pxp_chan->client;
+
+ /*
+ * if epd works in external mode, we should queue epdc_intr_workqueue
+ * after a wfe_a process finishes.
+ */
+ if (fb_data->epdc_wb_mode && (tx_desc->proc_data.engine_enable & PXP_ENABLE_WFE_A)) {
+ pxp_get_collision_info(&fb_data->col_info);
+ queue_work(fb_data->epdc_intr_workqueue,
+ &fb_data->epdc_intr_work);
+ }
+
+ /* This call will signal wait_for_completion_timeout() in send_buffer_to_pxp */
+ complete(&fb_data->pxp_tx_cmpl);
+}
+
+static bool chan_filter(struct dma_chan *chan, void *arg)
+{
+ if (imx_dma_is_pxp(chan))
+ return true;
+ else
+ return false;
+}
+
+/* Function to request PXP DMA channel */
+static int pxp_chan_init(struct mxc_epdc_fb_data *fb_data)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+
+ /*
+ * Request a free channel
+ */
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_PRIVATE, mask);
+ chan = dma_request_channel(mask, chan_filter, NULL);
+ if (!chan) {
+ dev_err(fb_data->dev, "Unsuccessfully received channel!!!!\n");
+ return -EBUSY;
+ }
+
+ fb_data->pxp_chan = to_pxp_channel(chan);
+ fb_data->pxp_chan->client = fb_data;
+
+ init_completion(&fb_data->pxp_tx_cmpl);
+
+ return 0;
+}
+
+static int pxp_wfe_a_process_clear_workingbuffer(struct mxc_epdc_fb_data *fb_data,
+ u32 panel_width, u32 panel_height)
+{
+ dma_cookie_t cookie;
+ struct scatterlist *sg = fb_data->sg;
+ struct dma_chan *dma_chan;
+ struct pxp_tx_desc *desc;
+ struct dma_async_tx_descriptor *txd;
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
+ int i, j = 0, ret;
+ int length;
+
+ dev_dbg(fb_data->dev, "Starting PxP WFE_A process for clearing WB.\n");
+
+ /* First, check to see that we have acquired a PxP Channel object */
+ if (fb_data->pxp_chan == NULL) {
+ /*
+ * PxP Channel has not yet been created and initialized,
+ * so let's go ahead and try
+ */
+ ret = pxp_chan_init(fb_data);
+ if (ret) {
+ /*
+ * PxP channel init failed, and we can't use the
+ * PxP until the PxP DMA driver has loaded, so we abort
+ */
+ dev_err(fb_data->dev, "PxP chan init failed\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Init completion, so that we
+ * can be properly informed of the completion
+ * of the PxP task when it is done.
+ */
+ init_completion(&fb_data->pxp_tx_cmpl);
+
+ dma_chan = &fb_data->pxp_chan->dma_chan;
+
+ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2 + 4,
+ DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT,
+ NULL);
+ if (!txd) {
+ dev_err(fb_data->info.device,
+ "Error preparing a DMA transaction descriptor.\n");
+ return -EIO;
+ }
+
+ txd->callback_param = txd;
+ txd->callback = pxp_dma_done;
+
+ proc_data->working_mode = PXP_MODE_STANDARD;
+ proc_data->engine_enable = PXP_ENABLE_WFE_A;
+ proc_data->lut = 0;
+ proc_data->detection_only = 0;
+ proc_data->reagl_en = 0;
+ proc_data->partial_update = 0;
+ proc_data->alpha_en = 1;
+ proc_data->lut_sels = fb_data->luts_complete;
+ proc_data->lut_cleanup = 1;
+
+ pxp_conf->wfe_a_fetch_param[0].stride = panel_width;
+ pxp_conf->wfe_a_fetch_param[0].width = panel_width;
+ pxp_conf->wfe_a_fetch_param[0].height = panel_height;
+ pxp_conf->wfe_a_fetch_param[0].paddr = fb_data->phys_addr_black;
+ pxp_conf->wfe_a_fetch_param[1].stride = panel_width;
+ pxp_conf->wfe_a_fetch_param[1].width = panel_width;
+ pxp_conf->wfe_a_fetch_param[1].height = panel_height;
+ pxp_conf->wfe_a_fetch_param[1].paddr = fb_data->working_buffer_phys;
+ pxp_conf->wfe_a_fetch_param[0].left = 0;
+ pxp_conf->wfe_a_fetch_param[0].top = 0;
+ pxp_conf->wfe_a_fetch_param[1].left = 0;
+ pxp_conf->wfe_a_fetch_param[1].top = 0;
+
+ pxp_conf->wfe_a_store_param[0].stride = panel_width;
+ pxp_conf->wfe_a_store_param[0].width = panel_width;
+ pxp_conf->wfe_a_store_param[0].height = panel_height;
+ pxp_conf->wfe_a_store_param[0].paddr = fb_data->phys_addr_y4c;
+ pxp_conf->wfe_a_store_param[1].stride = panel_width;
+ pxp_conf->wfe_a_store_param[1].width = panel_width;
+ pxp_conf->wfe_a_store_param[1].height = panel_height;
+ pxp_conf->wfe_a_store_param[1].paddr = fb_data->working_buffer_phys;
+ pxp_conf->wfe_a_store_param[0].left = 0;
+ pxp_conf->wfe_a_store_param[0].top = 0;
+ pxp_conf->wfe_a_store_param[1].left = 0;
+ pxp_conf->wfe_a_store_param[1].top = 0;
+
+ desc = to_tx_desc(txd);
+ length = desc->len;
+
+ memcpy(&desc->proc_data, proc_data, sizeof(struct pxp_proc_data));
+ for (i = 0; i < length; i++) {
+ if (i == 0 || i == 1) {/* wfe_a won't use s0 or output at all */
+ desc = desc->next;
+
+ } else if ((pxp_conf->proc_data.engine_enable & PXP_ENABLE_WFE_A) && (j < 4)) {
+ for (j = 0; j < 4; j++) {
+ if (j == 0) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_fetch_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_FETCH0;
+ } else if (j == 1) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_fetch_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_FETCH1;
+ } else if (j == 2) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_store_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_STORE0;
+ } else if (j == 3) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_store_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_STORE1;
+ }
+
+ desc = desc->next;
+ }
+
+ i += 4;
+ }
+ }
+
+ /* Submitting our TX starts the PxP processing task */
+ cookie = txd->tx_submit(txd);
+ if (cookie < 0) {
+ dev_err(fb_data->info.device, "Error sending FB through PxP\n");
+ return -EIO;
+ }
+
+ fb_data->txd = txd;
+
+ /* trigger ePxP */
+ dma_async_issue_pending(dma_chan);
+
+ return 0;
+}
+
+static int pxp_clear_wb_work_func(struct mxc_epdc_fb_data *fb_data)
+{
+ unsigned int hist_stat;
+ int ret;
+
+ dev_dbg(fb_data->dev, "PxP WFE to clear working buffer.\n");
+
+ mutex_lock(&fb_data->pxp_mutex);
+ ret = pxp_wfe_a_process_clear_workingbuffer(fb_data, fb_data->cur_mode->vmode->xres, fb_data->cur_mode->vmode->yres);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to submit PxP update task.\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+ mutex_unlock(&fb_data->pxp_mutex);
+
+ /* If needed, enable EPDC HW while ePxP is processing */
+ if ((fb_data->power_state == POWER_STATE_OFF)
+ || fb_data->powering_down) {
+ epdc_powerup(fb_data);
+ }
+
+ /* This is a blocking call, so upon return PxP tx should be done */
+ ret = pxp_complete_update(fb_data, &hist_stat);
+ if (ret) {
+ dev_err(fb_data->dev, "Unable to complete PxP update task: clear wb process\n");
+ mutex_unlock(&fb_data->pxp_mutex);
+ return ret;
+ }
+
+ return 0;
+}
+
+
+/* PS_AS_OUT */
+static int pxp_legacy_process(struct mxc_epdc_fb_data *fb_data,
+ u32 src_width, u32 src_height,
+ struct mxcfb_rect *update_region)
+{
+ dma_cookie_t cookie;
+ struct scatterlist *sg = fb_data->sg;
+ struct dma_chan *dma_chan;
+ struct pxp_tx_desc *desc;
+ struct dma_async_tx_descriptor *txd;
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
+ struct fb_var_screeninfo *screeninfo = &fb_data->info.var;
+ int i, ret;
+ int length;
+
+ dev_dbg(fb_data->dev, "Starting PxP legacy process.\n");
+
+ /* First, check to see that we have acquired a PxP Channel object */
+ if (fb_data->pxp_chan == NULL) {
+ /*
+ * PxP Channel has not yet been created and initialized,
+ * so let's go ahead and try
+ */
+ ret = pxp_chan_init(fb_data);
+ if (ret) {
+ /*
+ * PxP channel init failed, and we can't use the
+ * PxP until the PxP DMA driver has loaded, so we abort
+ */
+ dev_err(fb_data->dev, "PxP chan init failed\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Init completion, so that we
+ * can be properly informed of the completion
+ * of the PxP task when it is done.
+ */
+ init_completion(&fb_data->pxp_tx_cmpl);
+
+ dma_chan = &fb_data->pxp_chan->dma_chan;
+
+ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2,
+ DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT,
+ NULL);
+ if (!txd) {
+ dev_err(fb_data->info.device,
+ "Error preparing a DMA transaction descriptor.\n");
+ return -EIO;
+ }
+
+ txd->callback_param = txd;
+ txd->callback = pxp_dma_done;
+
+ proc_data->working_mode = PXP_MODE_LEGACY;
+ proc_data->engine_enable = PXP_ENABLE_PS_AS_OUT;
+
+ /*
+ * Configure PxP for processing of new update region
+ * The rest of our config params were set up in
+ * probe() and should not need to be changed.
+ */
+ pxp_conf->s0_param.width = src_width;
+ pxp_conf->s0_param.stride = (screeninfo->bits_per_pixel * src_width) >> 3;
+ pxp_conf->s0_param.height = src_height;
+ proc_data->srect.top = update_region->top;
+ proc_data->srect.left = update_region->left;
+ proc_data->srect.width = update_region->width;
+ proc_data->srect.height = update_region->height;
+ proc_data->lut_cleanup = 0;
+
+ /*
+ * Because only YUV/YCbCr image can be scaled, configure
+ * drect equivalent to srect, as such do not perform scaling.
+ */
+ proc_data->drect.top = 0;
+ proc_data->drect.left = 0;
+
+ /* PXP expects rotation in terms of degrees */
+ proc_data->rotate = fb_data->epdc_fb_var.rotate * 90;
+ if (proc_data->rotate > 270)
+ proc_data->rotate = 0;
+
+ /* we should pass the rotated values to PXP */
+ if ((proc_data->rotate == 90) || (proc_data->rotate == 270)) {
+ proc_data->drect.width = proc_data->srect.height;
+ proc_data->drect.height = proc_data->srect.width;
+ pxp_conf->out_param.width = update_region->height;
+ pxp_conf->out_param.height = update_region->width;
+ pxp_conf->out_param.stride = update_region->height;
+ } else {
+ proc_data->drect.width = proc_data->srect.width;
+ proc_data->drect.height = proc_data->srect.height;
+ pxp_conf->out_param.width = update_region->width;
+ pxp_conf->out_param.height = update_region->height;
+ pxp_conf->out_param.stride = update_region->width;
+ }
+
+ /* For EPDC v2.0, we need output to be 64-bit
+ * aligned since EPDC stride does not work. */
+ if (fb_data->rev <= 20)
+ pxp_conf->out_param.stride = ALIGN(pxp_conf->out_param.stride, 8);
+
+ desc = to_tx_desc(txd);
+ length = desc->len;
+
+ for (i = 0; i < length; i++) {
+ if (i == 0) {/* S0 */
+ memcpy(&desc->proc_data, proc_data, sizeof(struct pxp_proc_data));
+ pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]);
+ memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+
+ } else if (i == 1) {
+ pxp_conf->out_param.paddr = sg_dma_address(&sg[1]);
+ memcpy(&desc->layer_param.out_param, &pxp_conf->out_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+ }
+ }
+
+ /* Submitting our TX starts the PxP processing task */
+ cookie = txd->tx_submit(txd);
+ if (cookie < 0) {
+ dev_err(fb_data->info.device, "Error sending FB through PxP\n");
+ return -EIO;
+ }
+
+ fb_data->txd = txd;
+
+ /* trigger ePxP */
+ dma_async_issue_pending(dma_chan);
+
+ return 0;
+}
+
+static int pxp_process_dithering(struct mxc_epdc_fb_data *fb_data,
+ struct mxcfb_rect *update_region)
+{
+ dma_cookie_t cookie;
+ struct scatterlist *sg = fb_data->sg;
+ struct dma_chan *dma_chan;
+ struct pxp_tx_desc *desc;
+ struct dma_async_tx_descriptor *txd;
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
+ int i, j = 0, ret;
+ int length;
+
+ dev_dbg(fb_data->dev, "Starting PxP Dithering process.\n");
+
+ /* First, check to see that we have acquired a PxP Channel object */
+ if (fb_data->pxp_chan == NULL) {
+ /*
+ * PxP Channel has not yet been created and initialized,
+ * so let's go ahead and try
+ */
+ ret = pxp_chan_init(fb_data);
+ if (ret) {
+ /*
+ * PxP channel init failed, and we can't use the
+ * PxP until the PxP DMA driver has loaded, so we abort
+ */
+ dev_err(fb_data->dev, "PxP chan init failed\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Init completion, so that we
+ * can be properly informed of the completion
+ * of the PxP task when it is done.
+ */
+ init_completion(&fb_data->pxp_tx_cmpl);
+
+ dma_chan = &fb_data->pxp_chan->dma_chan;
+
+ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2 + 4,
+ DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT,
+ NULL);
+ if (!txd) {
+ dev_err(fb_data->info.device,
+ "Error preparing a DMA transaction descriptor.\n");
+ return -EIO;
+ }
+
+ txd->callback_param = txd;
+ txd->callback = pxp_dma_done;
+
+ proc_data->working_mode = PXP_MODE_STANDARD;
+ proc_data->engine_enable = PXP_ENABLE_DITHER;
+
+ pxp_conf->dither_fetch_param[0].stride = update_region->width;
+ pxp_conf->dither_fetch_param[0].width = update_region->width;
+ pxp_conf->dither_fetch_param[0].height = update_region->height;
+#ifdef USE_PS_AS_OUTPUT
+ pxp_conf->dither_fetch_param[0].paddr = sg_dma_address(&sg[1]);
+#else
+ pxp_conf->dither_fetch_param[0].paddr = sg_dma_address(&sg[0]);
+#endif
+ pxp_conf->dither_fetch_param[1].stride = update_region->width;
+ pxp_conf->dither_fetch_param[1].width = update_region->width;
+ pxp_conf->dither_fetch_param[1].height = update_region->height;
+ pxp_conf->dither_fetch_param[1].paddr = pxp_conf->dither_fetch_param[0].paddr;
+
+ pxp_conf->dither_store_param[0].stride = update_region->width;
+ pxp_conf->dither_store_param[0].width = update_region->width;
+ pxp_conf->dither_store_param[0].height = update_region->height;
+ pxp_conf->dither_store_param[0].paddr = fb_data->phys_addr_y4;
+ pxp_conf->dither_store_param[1].stride = update_region->width;
+ pxp_conf->dither_store_param[1].width = update_region->width;
+ pxp_conf->dither_store_param[1].height = update_region->height;
+ pxp_conf->dither_store_param[1].paddr = pxp_conf->dither_store_param[0].paddr;
+
+ desc = to_tx_desc(txd);
+ length = desc->len;
+
+ for (i = 0; i < length; i++) {
+ if (i == 0) {/* S0 */
+ memcpy(&desc->proc_data, proc_data, sizeof(struct pxp_proc_data));
+ pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]);
+ memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+ } else if (i == 1) {
+ pxp_conf->out_param.paddr = sg_dma_address(&sg[1]);
+ memcpy(&desc->layer_param.out_param, &pxp_conf->out_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+ } else if ((pxp_conf->proc_data.engine_enable & PXP_ENABLE_DITHER) && (j < 4)) {
+ for (j = 0; j < 4; j++) {
+ if (j == 0) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->dither_fetch_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_DITHER_FETCH0;
+ } else if (j == 1) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->dither_fetch_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_DITHER_FETCH1;
+ } else if (j == 2) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->dither_store_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_DITHER_STORE0;
+ } else if (j == 3) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->dither_store_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_DITHER_STORE1;
+ }
+
+ desc = desc->next;
+ }
+
+ i += 4;
+ }
+ }
+
+ /* Submitting our TX starts the PxP processing task */
+ cookie = txd->tx_submit(txd);
+ if (cookie < 0) {
+ dev_err(fb_data->info.device, "Error sending FB through PxP\n");
+ return -EIO;
+ }
+
+ fb_data->txd = txd;
+
+ /* trigger ePxP */
+ dma_async_issue_pending(dma_chan);
+
+ return 0;
+}
+
+/*
+ * Function to call PxP DMA driver and send our latest FB update region
+ * through the PxP and out to an intermediate buffer.
+ * Note: This is a blocking call, so upon return the PxP tx should be complete.
+ */
+static int pxp_wfe_a_process(struct mxc_epdc_fb_data *fb_data,
+ struct mxcfb_rect *update_region,
+ struct update_data_list *upd_data_list)
+{
+ dma_cookie_t cookie;
+ struct scatterlist *sg = fb_data->sg;
+ struct dma_chan *dma_chan;
+ struct pxp_tx_desc *desc;
+ struct dma_async_tx_descriptor *txd;
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
+ u32 wv_mode = upd_data_list->update_desc->upd_data.waveform_mode;
+ int i, j = 0, ret;
+ int length;
+ bool is_transform;
+
+ dev_dbg(fb_data->dev, "Starting PxP WFE_A process.\n");
+
+ /* First, check to see that we have acquired a PxP Channel object */
+ if (fb_data->pxp_chan == NULL) {
+ /*
+ * PxP Channel has not yet been created and initialized,
+ * so let's go ahead and try
+ */
+ ret = pxp_chan_init(fb_data);
+ if (ret) {
+ /*
+ * PxP channel init failed, and we can't use the
+ * PxP until the PxP DMA driver has loaded, so we abort
+ */
+ dev_err(fb_data->dev, "PxP chan init failed\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Init completion, so that we
+ * can be properly informed of the completion
+ * of the PxP task when it is done.
+ */
+ init_completion(&fb_data->pxp_tx_cmpl);
+
+ dma_chan = &fb_data->pxp_chan->dma_chan;
+
+ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2 + 4,
+ DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT,
+ NULL);
+ if (!txd) {
+ dev_err(fb_data->info.device,
+ "Error preparing a DMA transaction descriptor.\n");
+ return -EIO;
+ }
+
+ txd->callback_param = txd;
+ txd->callback = pxp_dma_done;
+
+ proc_data->working_mode = PXP_MODE_STANDARD;
+ proc_data->engine_enable = PXP_ENABLE_WFE_A;
+ proc_data->lut = upd_data_list->lut_num;
+ proc_data->alpha_en = 0;
+ proc_data->lut_sels = fb_data->luts_complete;
+ proc_data->lut_status_1 = __raw_readl(EPDC_STATUS_LUTS);
+ proc_data->lut_status_2 = __raw_readl(EPDC_STATUS_LUTS2);
+ proc_data->lut_cleanup = 0;
+
+ if (upd_data_list->update_desc->upd_data.flags & EPDC_FLAG_TEST_COLLISION) {
+ proc_data->detection_only = 1;
+ dev_dbg(fb_data->info.device,
+ "collision test_only send to pxp\n");
+ } else
+ proc_data->detection_only = 0;
+
+ if (wv_mode == WAVEFORM_MODE_GLR16
+ || wv_mode == WAVEFORM_MODE_GLD16)
+ proc_data->reagl_en = 1;
+
+ if (upd_data_list->update_desc->upd_data.update_mode == UPDATE_MODE_PARTIAL)
+ proc_data->partial_update = 1;
+ else
+ proc_data->partial_update = 0;
+
+ /* fetch0 is upd buffer */
+ pxp_conf->wfe_a_fetch_param[0].stride = upd_data_list->update_desc->epdc_stride;
+ pxp_conf->wfe_a_fetch_param[0].width = update_region->width;
+ pxp_conf->wfe_a_fetch_param[0].height = update_region->height;
+ /* upd buffer left and top should be always 0 */
+ pxp_conf->wfe_a_fetch_param[0].left = 0;
+ pxp_conf->wfe_a_fetch_param[0].top = 0;
+ if (proc_data->dither_mode) {
+ pxp_conf->wfe_a_fetch_param[0].paddr = fb_data->phys_addr_y4;
+ } else {
+ is_transform = ((upd_data_list->update_desc->upd_data.flags &
+ (EPDC_FLAG_ENABLE_INVERSION | EPDC_FLAG_USE_DITHERING_Y1 |
+ EPDC_FLAG_USE_DITHERING_Y4 | EPDC_FLAG_FORCE_MONOCHROME |
+ EPDC_FLAG_USE_CMAP)) && (proc_data->scaling == 0) &&
+ (proc_data->hflip == 0) && (proc_data->vflip == 0)) ?
+ true : false;
+
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) &&
+ (fb_data->epdc_fb_var.grayscale == GRAYSCALE_8BIT) &&
+ !is_transform && (proc_data->dither_mode == 0) &&
+ !(upd_data_list->update_desc->upd_data.flags &
+ EPDC_FLAG_USE_ALT_BUFFER) &&
+ !fb_data->restrict_width) {
+ sg_dma_address(&sg[0]) = fb_data->info.fix.smem_start;
+ sg_set_page(&sg[0],
+ virt_to_page(fb_data->info.screen_base),
+ fb_data->info.fix.smem_len,
+ offset_in_page(fb_data->info.screen_base));
+ pxp_conf->wfe_a_fetch_param[0].paddr =
+ sg_dma_address(&sg[0]);
+
+ pxp_conf->wfe_a_fetch_param[0].left = update_region->left;
+ pxp_conf->wfe_a_fetch_param[0].top = update_region->top;
+ } else
+ pxp_conf->wfe_a_fetch_param[0].paddr =
+ upd_data_list->phys_addr + upd_data_list->update_desc->epdc_offs;
+ }
+
+ /* fetch1 is working buffer */
+ pxp_conf->wfe_a_fetch_param[1].stride = fb_data->cur_mode->vmode->xres;
+ pxp_conf->wfe_a_fetch_param[1].width = update_region->width;
+ pxp_conf->wfe_a_fetch_param[1].height = update_region->height;
+ pxp_conf->wfe_a_fetch_param[1].paddr = fb_data->working_buffer_phys;
+ pxp_conf->wfe_a_fetch_param[1].left = update_region->left;
+ pxp_conf->wfe_a_fetch_param[1].top = update_region->top;
+
+ /* store0 is y4c buffer */
+ pxp_conf->wfe_a_store_param[0].stride = fb_data->cur_mode->vmode->xres;
+ pxp_conf->wfe_a_store_param[0].width = update_region->width;
+ pxp_conf->wfe_a_store_param[0].height = update_region->height;
+ pxp_conf->wfe_a_store_param[0].paddr = fb_data->phys_addr_y4c;
+
+ /* store1 is (temp) working buffer */
+ pxp_conf->wfe_a_store_param[1].stride = fb_data->cur_mode->vmode->xres;
+ pxp_conf->wfe_a_store_param[1].width = update_region->width;
+ pxp_conf->wfe_a_store_param[1].height = update_region->height;
+ if (wv_mode == WAVEFORM_MODE_GLR16
+ || wv_mode == WAVEFORM_MODE_GLD16)
+ pxp_conf->wfe_a_store_param[1].paddr = fb_data->tmp_working_buffer_phys;
+ else
+ pxp_conf->wfe_a_store_param[1].paddr = fb_data->working_buffer_phys;
+ pxp_conf->wfe_a_store_param[1].left = update_region->left;
+ pxp_conf->wfe_a_store_param[1].top = update_region->top;
+
+ desc = to_tx_desc(txd);
+ length = desc->len;
+
+ memcpy(&desc->proc_data, proc_data, sizeof(struct pxp_proc_data));
+ for (i = 0; i < length; i++) {
+ if (i == 0 || i == 1) {/* wfe_a won't use s0 or output at all */
+ desc = desc->next;
+ } else if ((pxp_conf->proc_data.engine_enable & PXP_ENABLE_WFE_A) && (j < 4)) {
+ for (j = 0; j < 4; j++) {
+ if (j == 0) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_fetch_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_FETCH0;
+ } else if (j == 1) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_fetch_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_FETCH1;
+ } else if (j == 2) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_store_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_STORE0;
+ } else if (j == 3) {
+ memcpy(&desc->layer_param.processing_param,
+ &pxp_conf->wfe_a_store_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.flag = PXP_BUF_FLAG_WFE_A_STORE1;
+ }
+
+ desc = desc->next;
+ }
+
+ i += 4;
+ }
+ }
+
+ /* Submitting our TX starts the PxP processing task */
+ cookie = txd->tx_submit(txd);
+ if (cookie < 0) {
+ dev_err(fb_data->info.device, "Error sending FB through PxP\n");
+ return -EIO;
+ }
+
+ fb_data->txd = txd;
+
+ /* trigger ePxP */
+ dma_async_issue_pending(dma_chan);
+
+ return 0;
+}
+
+/* For REAGL/-D processing */
+static int pxp_wfe_b_process_update(struct mxc_epdc_fb_data *fb_data,
+ struct mxcfb_rect *update_region)
+{
+ dma_cookie_t cookie;
+ struct scatterlist *sg = fb_data->sg;
+ struct dma_chan *dma_chan;
+ struct pxp_tx_desc *desc;
+ struct dma_async_tx_descriptor *txd;
+ struct pxp_config_data *pxp_conf = &fb_data->pxp_conf;
+ struct pxp_proc_data *proc_data = &fb_data->pxp_conf.proc_data;
+ int i, j = 0, ret;
+ int length;
+
+ dev_dbg(fb_data->dev, "Starting PxP WFE_B process.\n");
+
+ /* First, check to see that we have acquired a PxP Channel object */
+ if (fb_data->pxp_chan == NULL) {
+ /*
+ * PxP Channel has not yet been created and initialized,
+ * so let's go ahead and try
+ */
+ ret = pxp_chan_init(fb_data);
+ if (ret) {
+ /*
+ * PxP channel init failed, and we can't use the
+ * PxP until the PxP DMA driver has loaded, so we abort
+ */
+ dev_err(fb_data->dev, "PxP chan init failed\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Init completion, so that we
+ * can be properly informed of the completion
+ * of the PxP task when it is done.
+ */
+ init_completion(&fb_data->pxp_tx_cmpl);
+
+ dma_chan = &fb_data->pxp_chan->dma_chan;
+
+ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2 + 4,
+ DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT,
+ NULL);
+ if (!txd) {
+ dev_err(fb_data->info.device,
+ "Error preparing a DMA transaction descriptor.\n");
+ return -EIO;
+ }
+
+ txd->callback_param = txd;
+ txd->callback = pxp_dma_done;
+
+ proc_data->working_mode = PXP_MODE_STANDARD;
+ proc_data->engine_enable = PXP_ENABLE_WFE_B;
+ proc_data->lut_update = false;
+ proc_data->lut_cleanup = 0;
+
+ pxp_conf->wfe_b_fetch_param[0].stride = fb_data->cur_mode->vmode->xres;
+ pxp_conf->wfe_b_fetch_param[0].width = fb_data->cur_mode->vmode->xres;
+ pxp_conf->wfe_b_fetch_param[0].height = fb_data->cur_mode->vmode->yres;
+ pxp_conf->wfe_b_fetch_param[0].paddr = fb_data->phys_addr_black;
+ pxp_conf->wfe_b_fetch_param[1].stride = fb_data->cur_mode->vmode->xres;
+ pxp_conf->wfe_b_fetch_param[1].width = update_region->width;
+ pxp_conf->wfe_b_fetch_param[1].height = update_region->height;
+ pxp_conf->wfe_b_fetch_param[1].top = update_region->top;
+ pxp_conf->wfe_b_fetch_param[1].left = update_region->left;
+ pxp_conf->wfe_b_fetch_param[1].paddr = fb_data->tmp_working_buffer_phys;
+
+ pxp_conf->wfe_b_store_param[0].stride = fb_data->cur_mode->vmode->xres;
+ pxp_conf->wfe_b_store_param[0].width = update_region->width;
+ pxp_conf->wfe_b_store_param[0].height = update_region->height;
+ pxp_conf->wfe_b_store_param[0].top = update_region->top;
+ pxp_conf->wfe_b_store_param[0].left = update_region->left;
+ pxp_conf->wfe_b_store_param[0].paddr = fb_data->working_buffer_phys;
+ pxp_conf->wfe_b_store_param[1].stride = fb_data->cur_mode->vmode->xres;
+ pxp_conf->wfe_b_store_param[1].width = update_region->width;
+ pxp_conf->wfe_b_store_param[1].height = update_region->height;
+ pxp_conf->wfe_b_store_param[1].paddr = 0;
+
+ desc = to_tx_desc(txd);
+ length = desc->len;
+
+ for (i = 0; i < length; i++) {
+ if (i == 0) { /* S0 */
+ memcpy(&desc->proc_data, proc_data,
+ sizeof(struct pxp_proc_data));
+ pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]);
+ memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+ } else if (i == 1) {
+ pxp_conf->out_param.paddr = sg_dma_address(&sg[1]);
+ memcpy(&desc->layer_param.out_param,
+ &pxp_conf->out_param,
+ sizeof(struct pxp_layer_param));
+ desc = desc->next;
+ } else
+ if ((pxp_conf->proc_data.engine_enable & PXP_ENABLE_WFE_B)
+ && (j < 4)) {
+ for (j = 0; j < 4; j++) {
+ if (j == 0) {
+ memcpy(&desc->layer_param.
+ processing_param,
+ &pxp_conf->wfe_b_fetch_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.
+ flag = PXP_BUF_FLAG_WFE_B_FETCH0;
+ } else if (j == 1) {
+ memcpy(&desc->layer_param.
+ processing_param,
+ &pxp_conf->wfe_b_fetch_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.
+ flag = PXP_BUF_FLAG_WFE_B_FETCH1;
+ } else if (j == 2) {
+ memcpy(&desc->layer_param.
+ processing_param,
+ &pxp_conf->wfe_b_store_param[0],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.
+ flag = PXP_BUF_FLAG_WFE_B_STORE0;
+ } else if (j == 3) {
+ memcpy(&desc->layer_param.
+ processing_param,
+ &pxp_conf->wfe_b_store_param[1],
+ sizeof(struct pxp_layer_param));
+ desc->layer_param.processing_param.
+ flag = PXP_BUF_FLAG_WFE_B_STORE1;
+ }
+
+ desc = desc->next;
+ }
+
+ i += 4;
+ }
+ }
+
+ /* Submitting our TX starts the PxP processing task */
+ cookie = txd->tx_submit(txd);
+ if (cookie < 0) {
+ dev_err(fb_data->info.device, "Error sending FB through PxP\n");
+ return -EIO;
+ }
+
+ fb_data->txd = txd;
+
+ /* trigger ePxP */
+ dma_async_issue_pending(dma_chan);
+
+ return 0;
+}
+
+static int pxp_complete_update(struct mxc_epdc_fb_data *fb_data, u32 *hist_stat)
+{
+ int ret;
+ /*
+ * Wait for completion event, which will be set
+ * through our TX callback function.
+ */
+ ret = wait_for_completion_timeout(&fb_data->pxp_tx_cmpl, HZ * 2);
+ if (ret <= 0) {
+ dev_info(fb_data->info.device,
+ "PxP operation failed due to %s\n",
+ ret < 0 ? "user interrupt" : "timeout");
+ dma_release_channel(&fb_data->pxp_chan->dma_chan);
+ fb_data->pxp_chan = NULL;
+ return ret ? : -ETIMEDOUT;
+ }
+
+ if ((fb_data->pxp_conf.proc_data.lut_transform & EPDC_FLAG_USE_CMAP) &&
+ fb_data->pxp_conf.proc_data.lut_map_updated)
+ fb_data->pxp_conf.proc_data.lut_map_updated = false;
+
+ *hist_stat = to_tx_desc(fb_data->txd)->hist_status;
+ dma_release_channel(&fb_data->pxp_chan->dma_chan);
+ fb_data->pxp_chan = NULL;
+
+ dev_dbg(fb_data->dev, "TX completed\n");
+
+ return 0;
+}
+
+/*
+ * Different dithering algorithm can be used. We chose
+ * to implement Bill Atkinson's algorithm as an example
+ * Thanks Bill Atkinson for his dithering algorithm.
+ */
+
+/*
+ * Dithering algorithm implementation - Y8->Y1 version 1.0 for i.MX
+ */
+static void do_dithering_processing_Y1_v1_0(
+ unsigned char *update_region_virt_ptr,
+ dma_addr_t update_region_phys_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist)
+{
+
+ /* create a temp error distribution array */
+ int bwPix;
+ int y;
+ int col;
+ int *err_dist_l0, *err_dist_l1, *err_dist_l2, distrib_error;
+ int width_3 = update_region->width + 3;
+ char *y8buf;
+ int x_offset = 0;
+
+ /* prime a few elements the error distribution array */
+ for (y = 0; y < update_region->height; y++) {
+ /* Dithering the Y8 in sbuf to BW suitable for A2 waveform */
+ err_dist_l0 = err_dist + (width_3) * (y % 3);
+ err_dist_l1 = err_dist + (width_3) * ((y + 1) % 3);
+ err_dist_l2 = err_dist + (width_3) * ((y + 2) % 3);
+
+ y8buf = update_region_virt_ptr + x_offset;
+
+ /* scan the line and convert the Y8 to BW */
+ for (col = 1; col <= update_region->width; col++) {
+ bwPix = *(err_dist_l0 + col) + *y8buf;
+
+ if (bwPix >= 128) {
+ *y8buf++ = 0xff;
+ distrib_error = (bwPix - 255) >> 3;
+ } else {
+ *y8buf++ = 0;
+ distrib_error = bwPix >> 3;
+ }
+
+ /* modify the error distribution buffer */
+ *(err_dist_l0 + col + 2) += distrib_error;
+ *(err_dist_l1 + col + 1) += distrib_error;
+ *(err_dist_l0 + col + 1) += distrib_error;
+ *(err_dist_l1 + col - 1) += distrib_error;
+ *(err_dist_l1 + col) += distrib_error;
+ *(err_dist_l2 + col) = distrib_error;
+ }
+ x_offset += update_region_stride;
+ }
+
+ flush_cache_all();
+ outer_flush_range(update_region_phys_ptr, update_region_phys_ptr +
+ update_region->height * update_region->width);
+}
+
+/*
+ * Dithering algorithm implementation - Y8->Y4 version 1.0 for i.MX
+ */
+
+static void do_dithering_processing_Y4_v1_0(
+ unsigned char *update_region_virt_ptr,
+ dma_addr_t update_region_phys_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist)
+{
+
+ /* create a temp error distribution array */
+ int gcPix;
+ int y;
+ int col;
+ int *err_dist_l0, *err_dist_l1, *err_dist_l2, distrib_error;
+ int width_3 = update_region->width + 3;
+ char *y8buf;
+ int x_offset = 0;
+
+ /* prime a few elements the error distribution array */
+ for (y = 0; y < update_region->height; y++) {
+ /* Dithering the Y8 in sbuf to Y4 */
+ err_dist_l0 = err_dist + (width_3) * (y % 3);
+ err_dist_l1 = err_dist + (width_3) * ((y + 1) % 3);
+ err_dist_l2 = err_dist + (width_3) * ((y + 2) % 3);
+
+ y8buf = update_region_virt_ptr + x_offset;
+
+ /* scan the line and convert the Y8 to Y4 */
+ for (col = 1; col <= update_region->width; col++) {
+ gcPix = *(err_dist_l0 + col) + *y8buf;
+
+ if (gcPix > 255)
+ gcPix = 255;
+ else if (gcPix < 0)
+ gcPix = 0;
+
+ distrib_error = (*y8buf - (gcPix & 0xf0)) >> 3;
+
+ *y8buf++ = gcPix & 0xf0;
+
+ /* modify the error distribution buffer */
+ *(err_dist_l0 + col + 2) += distrib_error;
+ *(err_dist_l1 + col + 1) += distrib_error;
+ *(err_dist_l0 + col + 1) += distrib_error;
+ *(err_dist_l1 + col - 1) += distrib_error;
+ *(err_dist_l1 + col) += distrib_error;
+ *(err_dist_l2 + col) = distrib_error;
+ }
+ x_offset += update_region_stride;
+ }
+
+ flush_cache_all();
+ outer_flush_range(update_region_phys_ptr, update_region_phys_ptr +
+ update_region->height * update_region->width);
+}
+
+static int __init mxc_epdc_fb_init(void)
+{
+ return platform_driver_register(&mxc_epdc_fb_driver);
+}
+late_initcall(mxc_epdc_fb_init);
+
+static void __exit mxc_epdc_fb_exit(void)
+{
+ platform_driver_unregister(&mxc_epdc_fb_driver);
+}
+module_exit(mxc_epdc_fb_exit);
+
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC EPDC V2 framebuffer driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("fb");
diff --git a/drivers/video/fbdev/mxc/mxc_hdmi.c b/drivers/video/fbdev/mxc/mxc_hdmi.c
new file mode 100644
index 000000000000..ebec8d2dd8b8
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_hdmi.c
@@ -0,0 +1,2977 @@
+/*
+ * Copyright (C) 2011-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
+ */
+/*
+ * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
+ * for SLISHDMI13T and SLIPHDMIT IP cores
+ *
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+#include <linux/cpufreq.h>
+#include <linux/firmware.h>
+#include <linux/kthread.h>
+#include <linux/regulator/driver.h>
+#include <linux/fsl_devices.h>
+#include <linux/ipu.h>
+#include <linux/regmap.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/of_device.h>
+
+#include <linux/console.h>
+#include <linux/types.h>
+
+#include "../edid.h"
+#include <video/mxc_edid.h>
+#include <video/mxc_hdmi.h>
+#include "mxc_dispdrv.h"
+
+#include <linux/mfd/mxc-hdmi-core.h>
+
+#define DISPDRV_HDMI "hdmi"
+#define HDMI_EDID_LEN 512
+
+/* status codes for reading edid */
+#define HDMI_EDID_SUCCESS 0
+#define HDMI_EDID_FAIL -1
+#define HDMI_EDID_SAME -2
+#define HDMI_EDID_NO_MODES -3
+
+#define NUM_CEA_VIDEO_MODES 64
+#define DEFAULT_VIDEO_MODE 16 /* 1080P */
+
+#define RGB 0
+#define YCBCR444 1
+#define YCBCR422_16BITS 2
+#define YCBCR422_8BITS 3
+#define XVYCC444 4
+
+/*
+ * We follow a flowchart which is in the "Synopsys DesignWare Courses
+ * HDMI Transmitter Controller User Guide, 1.30a", section 3.1
+ * (dwc_hdmi_tx_user.pdf)
+ *
+ * Below are notes that say "HDMI Initialization Step X"
+ * These correspond to the flowchart.
+ */
+
+/*
+ * We are required to configure VGA mode before reading edid
+ * in HDMI Initialization Step B
+ */
+static const struct fb_videomode vga_mode = {
+ /* 640x480 @ 60 Hz, 31.5 kHz hsync */
+ NULL, 60, 640, 480, 39721, 48, 16, 33, 10, 96, 2, 0,
+ FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, FB_MODE_IS_VESA,
+};
+
+enum hdmi_datamap {
+ RGB444_8B = 0x01,
+ RGB444_10B = 0x03,
+ RGB444_12B = 0x05,
+ RGB444_16B = 0x07,
+ YCbCr444_8B = 0x09,
+ YCbCr444_10B = 0x0B,
+ YCbCr444_12B = 0x0D,
+ YCbCr444_16B = 0x0F,
+ YCbCr422_8B = 0x16,
+ YCbCr422_10B = 0x14,
+ YCbCr422_12B = 0x12,
+};
+
+enum hdmi_colorimetry {
+ eITU601,
+ eITU709,
+};
+
+struct hdmi_vmode {
+ bool mDVI;
+ bool mHSyncPolarity;
+ bool mVSyncPolarity;
+ bool mInterlaced;
+ bool mDataEnablePolarity;
+
+ unsigned int mPixelClock;
+ unsigned int mPixelRepetitionInput;
+ unsigned int mPixelRepetitionOutput;
+};
+
+struct hdmi_data_info {
+ unsigned int enc_in_format;
+ unsigned int enc_out_format;
+ unsigned int enc_color_depth;
+ unsigned int colorimetry;
+ unsigned int pix_repet_factor;
+ unsigned int hdcp_enable;
+ unsigned int rgb_out_enable;
+ struct hdmi_vmode video_mode;
+};
+
+struct hdmi_phy_reg_config {
+ /* HDMI PHY register config for pass HCT */
+ u16 reg_vlev;
+ u16 reg_cksymtx;
+};
+
+struct mxc_hdmi {
+ struct platform_device *pdev;
+ struct platform_device *core_pdev;
+ struct mxc_dispdrv_handle *disp_mxc_hdmi;
+ struct fb_info *fbi;
+ struct clk *hdmi_isfr_clk;
+ struct clk *hdmi_iahb_clk;
+ struct clk *mipi_core_clk;
+ struct delayed_work hotplug_work;
+ struct delayed_work hdcp_hdp_work;
+
+ struct notifier_block nb;
+
+ struct hdmi_data_info hdmi_data;
+ int vic;
+ struct mxc_edid_cfg edid_cfg;
+ u8 edid[HDMI_EDID_LEN];
+ bool fb_reg;
+ bool cable_plugin;
+ u8 blank;
+ bool dft_mode_set;
+ char *dft_mode_str;
+ int default_bpp;
+ u8 latest_intr_stat;
+ bool irq_enabled;
+ spinlock_t irq_lock;
+ bool phy_enabled;
+ struct fb_videomode default_mode;
+ struct fb_videomode previous_non_vga_mode;
+ bool requesting_vga_for_initialization;
+
+ int *gpr_base;
+ int *gpr_hdmi_base;
+ int *gpr_sdma_base;
+ int cpu_type;
+ int cpu_version;
+ struct hdmi_phy_reg_config phy_config;
+
+ struct pinctrl *pinctrl;
+};
+
+static int hdmi_major;
+static struct class *hdmi_class;
+
+struct i2c_client *hdmi_i2c;
+struct mxc_hdmi *g_hdmi;
+
+static bool hdmi_inited;
+static bool hdcp_init;
+static struct regulator *hdmi_regulator;
+
+extern const struct fb_videomode mxc_cea_mode[64];
+extern void mxc_hdmi_cec_handle(u16 cec_stat);
+
+static void mxc_hdmi_setup(struct mxc_hdmi *hdmi, unsigned long event);
+static void hdmi_enable_overflow_interrupts(void);
+static void hdmi_disable_overflow_interrupts(void);
+
+static struct platform_device_id imx_hdmi_devtype[] = {
+ {
+ .name = "hdmi-imx6DL",
+ .driver_data = IMX6DL_HDMI,
+ }, {
+ .name = "hdmi-imx6Q",
+ .driver_data = IMX6Q_HDMI,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imx_hdmi_devtype);
+
+static const struct of_device_id imx_hdmi_dt_ids[] = {
+ { .compatible = "fsl,imx6dl-hdmi-video", .data = &imx_hdmi_devtype[IMX6DL_HDMI], },
+ { .compatible = "fsl,imx6q-hdmi-video", .data = &imx_hdmi_devtype[IMX6Q_HDMI], },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
+
+static inline int cpu_is_imx6dl(struct mxc_hdmi *hdmi)
+{
+ return hdmi->cpu_type == IMX6DL_HDMI;
+}
+#ifdef DEBUG
+static void dump_fb_videomode(const struct fb_videomode *m)
+{
+ pr_debug("fb_videomode = %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ m->refresh, m->xres, m->yres, m->pixclock, m->left_margin,
+ m->right_margin, m->upper_margin, m->lower_margin,
+ m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
+}
+#else
+static void dump_fb_videomode(const struct fb_videomode *m)
+{}
+#endif
+
+static ssize_t mxc_hdmi_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
+
+ strcpy(buf, hdmi->fbi->fix.id);
+ sprintf(buf+strlen(buf), "\n");
+
+ return strlen(buf);
+}
+
+static DEVICE_ATTR(fb_name, S_IRUGO, mxc_hdmi_show_name, NULL);
+
+static ssize_t mxc_hdmi_show_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
+
+ if (hdmi->cable_plugin == false)
+ strcpy(buf, "plugout\n");
+ else
+ strcpy(buf, "plugin\n");
+
+ return strlen(buf);
+}
+
+static DEVICE_ATTR(cable_state, S_IRUGO, mxc_hdmi_show_state, NULL);
+
+static ssize_t mxc_hdmi_show_edid(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
+ int i, j, len = 0;
+
+ for (j = 0; j < HDMI_EDID_LEN/16; j++) {
+ for (i = 0; i < 16; i++)
+ len += sprintf(buf+len, "0x%02X ",
+ hdmi->edid[j*16 + i]);
+ len += sprintf(buf+len, "\n");
+ }
+
+ return len;
+}
+
+static DEVICE_ATTR(edid, S_IRUGO, mxc_hdmi_show_edid, NULL);
+
+static ssize_t mxc_hdmi_show_rgb_out_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
+
+ if (hdmi->hdmi_data.rgb_out_enable == true)
+ strcpy(buf, "RGB out\n");
+ else
+ strcpy(buf, "YCbCr out\n");
+
+ return strlen(buf);
+}
+
+static ssize_t mxc_hdmi_store_rgb_out_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &value);
+ if (ret)
+ return ret;
+
+ hdmi->hdmi_data.rgb_out_enable = value;
+
+ /* Reconfig HDMI for output color space change */
+ mxc_hdmi_setup(hdmi, 0);
+
+ return count;
+}
+
+static DEVICE_ATTR(rgb_out_enable, S_IRUGO | S_IWUSR,
+ mxc_hdmi_show_rgb_out_enable,
+ mxc_hdmi_store_rgb_out_enable);
+
+static ssize_t mxc_hdmi_show_hdcp_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
+
+ if (hdmi->hdmi_data.hdcp_enable == false)
+ strcpy(buf, "hdcp disable\n");
+ else
+ strcpy(buf, "hdcp enable\n");
+
+ return strlen(buf);
+
+}
+
+static ssize_t mxc_hdmi_store_hdcp_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mxc_hdmi *hdmi = dev_get_drvdata(dev);
+ char event_string[32];
+ char *envp[] = { event_string, NULL };
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &value);
+ if (ret)
+ return ret;
+
+ hdmi->hdmi_data.hdcp_enable = value;
+
+ /* Reconfig HDMI for HDCP */
+ mxc_hdmi_setup(hdmi, 0);
+
+ if (hdmi->hdmi_data.hdcp_enable == false) {
+ sprintf(event_string, "EVENT=hdcpdisable");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+ } else {
+ sprintf(event_string, "EVENT=hdcpenable");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+ }
+
+ return count;
+
+}
+
+static DEVICE_ATTR(hdcp_enable, S_IRUGO | S_IWUSR,
+ mxc_hdmi_show_hdcp_enable, mxc_hdmi_store_hdcp_enable);
+
+/*!
+ * this submodule is responsible for the video data synchronization.
+ * for example, for RGB 4:4:4 input, the data map is defined as
+ * pin{47~40} <==> R[7:0]
+ * pin{31~24} <==> G[7:0]
+ * pin{15~8} <==> B[7:0]
+ */
+static void hdmi_video_sample(struct mxc_hdmi *hdmi)
+{
+ int color_format = 0;
+ u8 val;
+
+ if (hdmi->hdmi_data.enc_in_format == RGB) {
+ if (hdmi->hdmi_data.enc_color_depth == 8)
+ color_format = 0x01;
+ else if (hdmi->hdmi_data.enc_color_depth == 10)
+ color_format = 0x03;
+ else if (hdmi->hdmi_data.enc_color_depth == 12)
+ color_format = 0x05;
+ else if (hdmi->hdmi_data.enc_color_depth == 16)
+ color_format = 0x07;
+ else
+ return;
+ } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
+ if (hdmi->hdmi_data.enc_color_depth == 8)
+ color_format = 0x09;
+ else if (hdmi->hdmi_data.enc_color_depth == 10)
+ color_format = 0x0B;
+ else if (hdmi->hdmi_data.enc_color_depth == 12)
+ color_format = 0x0D;
+ else if (hdmi->hdmi_data.enc_color_depth == 16)
+ color_format = 0x0F;
+ else
+ return;
+ } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
+ if (hdmi->hdmi_data.enc_color_depth == 8)
+ color_format = 0x16;
+ else if (hdmi->hdmi_data.enc_color_depth == 10)
+ color_format = 0x14;
+ else if (hdmi->hdmi_data.enc_color_depth == 12)
+ color_format = 0x12;
+ else
+ return;
+ }
+
+ val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
+ ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
+ HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
+ hdmi_writeb(val, HDMI_TX_INVID0);
+
+ /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
+ val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
+ hdmi_writeb(val, HDMI_TX_INSTUFFING);
+ hdmi_writeb(0x0, HDMI_TX_GYDATA0);
+ hdmi_writeb(0x0, HDMI_TX_GYDATA1);
+ hdmi_writeb(0x0, HDMI_TX_RCRDATA0);
+ hdmi_writeb(0x0, HDMI_TX_RCRDATA1);
+ hdmi_writeb(0x0, HDMI_TX_BCBDATA0);
+ hdmi_writeb(0x0, HDMI_TX_BCBDATA1);
+}
+
+static int isColorSpaceConversion(struct mxc_hdmi *hdmi)
+{
+ return (hdmi->hdmi_data.enc_in_format !=
+ hdmi->hdmi_data.enc_out_format);
+}
+
+static int isColorSpaceDecimation(struct mxc_hdmi *hdmi)
+{
+ return ((hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) &&
+ (hdmi->hdmi_data.enc_in_format == RGB ||
+ hdmi->hdmi_data.enc_in_format == YCBCR444));
+}
+
+static int isColorSpaceInterpolation(struct mxc_hdmi *hdmi)
+{
+ return ((hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) &&
+ (hdmi->hdmi_data.enc_out_format == RGB
+ || hdmi->hdmi_data.enc_out_format == YCBCR444));
+}
+
+/*!
+ * update the color space conversion coefficients.
+ */
+static void update_csc_coeffs(struct mxc_hdmi *hdmi)
+{
+ unsigned short csc_coeff[3][4];
+ unsigned int csc_scale = 1;
+ u8 val;
+ bool coeff_selected = false;
+
+ if (isColorSpaceConversion(hdmi)) { /* csc needed */
+ if (hdmi->hdmi_data.enc_out_format == RGB) {
+ if (hdmi->hdmi_data.colorimetry == eITU601) {
+ csc_coeff[0][0] = 0x2000;
+ csc_coeff[0][1] = 0x6926;
+ csc_coeff[0][2] = 0x74fd;
+ csc_coeff[0][3] = 0x010e;
+
+ csc_coeff[1][0] = 0x2000;
+ csc_coeff[1][1] = 0x2cdd;
+ csc_coeff[1][2] = 0x0000;
+ csc_coeff[1][3] = 0x7e9a;
+
+ csc_coeff[2][0] = 0x2000;
+ csc_coeff[2][1] = 0x0000;
+ csc_coeff[2][2] = 0x38b4;
+ csc_coeff[2][3] = 0x7e3b;
+
+ csc_scale = 1;
+ coeff_selected = true;
+ } else if (hdmi->hdmi_data.colorimetry == eITU709) {
+ csc_coeff[0][0] = 0x2000;
+ csc_coeff[0][1] = 0x7106;
+ csc_coeff[0][2] = 0x7a02;
+ csc_coeff[0][3] = 0x00a7;
+
+ csc_coeff[1][0] = 0x2000;
+ csc_coeff[1][1] = 0x3264;
+ csc_coeff[1][2] = 0x0000;
+ csc_coeff[1][3] = 0x7e6d;
+
+ csc_coeff[2][0] = 0x2000;
+ csc_coeff[2][1] = 0x0000;
+ csc_coeff[2][2] = 0x3b61;
+ csc_coeff[2][3] = 0x7e25;
+
+ csc_scale = 1;
+ coeff_selected = true;
+ }
+ } else if (hdmi->hdmi_data.enc_in_format == RGB) {
+ if (hdmi->hdmi_data.colorimetry == eITU601) {
+ csc_coeff[0][0] = 0x2591;
+ csc_coeff[0][1] = 0x1322;
+ csc_coeff[0][2] = 0x074b;
+ csc_coeff[0][3] = 0x0000;
+
+ csc_coeff[1][0] = 0x6535;
+ csc_coeff[1][1] = 0x2000;
+ csc_coeff[1][2] = 0x7acc;
+ csc_coeff[1][3] = 0x0200;
+
+ csc_coeff[2][0] = 0x6acd;
+ csc_coeff[2][1] = 0x7534;
+ csc_coeff[2][2] = 0x2000;
+ csc_coeff[2][3] = 0x0200;
+
+ csc_scale = 0;
+ coeff_selected = true;
+ } else if (hdmi->hdmi_data.colorimetry == eITU709) {
+ csc_coeff[0][0] = 0x2dc5;
+ csc_coeff[0][1] = 0x0d9b;
+ csc_coeff[0][2] = 0x049e;
+ csc_coeff[0][3] = 0x0000;
+
+ csc_coeff[1][0] = 0x62f0;
+ csc_coeff[1][1] = 0x2000;
+ csc_coeff[1][2] = 0x7d11;
+ csc_coeff[1][3] = 0x0200;
+
+ csc_coeff[2][0] = 0x6756;
+ csc_coeff[2][1] = 0x78ab;
+ csc_coeff[2][2] = 0x2000;
+ csc_coeff[2][3] = 0x0200;
+
+ csc_scale = 0;
+ coeff_selected = true;
+ }
+ }
+ }
+
+ if (!coeff_selected) {
+ csc_coeff[0][0] = 0x2000;
+ csc_coeff[0][1] = 0x0000;
+ csc_coeff[0][2] = 0x0000;
+ csc_coeff[0][3] = 0x0000;
+
+ csc_coeff[1][0] = 0x0000;
+ csc_coeff[1][1] = 0x2000;
+ csc_coeff[1][2] = 0x0000;
+ csc_coeff[1][3] = 0x0000;
+
+ csc_coeff[2][0] = 0x0000;
+ csc_coeff[2][1] = 0x0000;
+ csc_coeff[2][2] = 0x2000;
+ csc_coeff[2][3] = 0x0000;
+
+ csc_scale = 1;
+ }
+
+ /* Update CSC parameters in HDMI CSC registers */
+ hdmi_writeb((unsigned char)(csc_coeff[0][0] & 0xFF),
+ HDMI_CSC_COEF_A1_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[0][0] >> 8),
+ HDMI_CSC_COEF_A1_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[0][1] & 0xFF),
+ HDMI_CSC_COEF_A2_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[0][1] >> 8),
+ HDMI_CSC_COEF_A2_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[0][2] & 0xFF),
+ HDMI_CSC_COEF_A3_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[0][2] >> 8),
+ HDMI_CSC_COEF_A3_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[0][3] & 0xFF),
+ HDMI_CSC_COEF_A4_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[0][3] >> 8),
+ HDMI_CSC_COEF_A4_MSB);
+
+ hdmi_writeb((unsigned char)(csc_coeff[1][0] & 0xFF),
+ HDMI_CSC_COEF_B1_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[1][0] >> 8),
+ HDMI_CSC_COEF_B1_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[1][1] & 0xFF),
+ HDMI_CSC_COEF_B2_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[1][1] >> 8),
+ HDMI_CSC_COEF_B2_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[1][2] & 0xFF),
+ HDMI_CSC_COEF_B3_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[1][2] >> 8),
+ HDMI_CSC_COEF_B3_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[1][3] & 0xFF),
+ HDMI_CSC_COEF_B4_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[1][3] >> 8),
+ HDMI_CSC_COEF_B4_MSB);
+
+ hdmi_writeb((unsigned char)(csc_coeff[2][0] & 0xFF),
+ HDMI_CSC_COEF_C1_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[2][0] >> 8),
+ HDMI_CSC_COEF_C1_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[2][1] & 0xFF),
+ HDMI_CSC_COEF_C2_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[2][1] >> 8),
+ HDMI_CSC_COEF_C2_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[2][2] & 0xFF),
+ HDMI_CSC_COEF_C3_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[2][2] >> 8),
+ HDMI_CSC_COEF_C3_MSB);
+ hdmi_writeb((unsigned char)(csc_coeff[2][3] & 0xFF),
+ HDMI_CSC_COEF_C4_LSB);
+ hdmi_writeb((unsigned char)(csc_coeff[2][3] >> 8),
+ HDMI_CSC_COEF_C4_MSB);
+
+ val = hdmi_readb(HDMI_CSC_SCALE);
+ val &= ~HDMI_CSC_SCALE_CSCSCALE_MASK;
+ val |= csc_scale & HDMI_CSC_SCALE_CSCSCALE_MASK;
+ hdmi_writeb(val, HDMI_CSC_SCALE);
+}
+
+static void hdmi_video_csc(struct mxc_hdmi *hdmi)
+{
+ int color_depth = 0;
+ int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
+ int decimation = 0;
+ u8 val;
+
+ /* YCC422 interpolation to 444 mode */
+ if (isColorSpaceInterpolation(hdmi))
+ interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
+ else if (isColorSpaceDecimation(hdmi))
+ decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
+
+ if (hdmi->hdmi_data.enc_color_depth == 8)
+ color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
+ else if (hdmi->hdmi_data.enc_color_depth == 10)
+ color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
+ else if (hdmi->hdmi_data.enc_color_depth == 12)
+ color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
+ else if (hdmi->hdmi_data.enc_color_depth == 16)
+ color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
+ else
+ return;
+
+ /*configure the CSC registers */
+ hdmi_writeb(interpolation | decimation, HDMI_CSC_CFG);
+ val = hdmi_readb(HDMI_CSC_SCALE);
+ val &= ~HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK;
+ val |= color_depth;
+ hdmi_writeb(val, HDMI_CSC_SCALE);
+
+ update_csc_coeffs(hdmi);
+}
+
+/*!
+ * HDMI video packetizer is used to packetize the data.
+ * for example, if input is YCC422 mode or repeater is used,
+ * data should be repacked this module can be bypassed.
+ */
+static void hdmi_video_packetize(struct mxc_hdmi *hdmi)
+{
+ unsigned int color_depth = 0;
+ unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
+ unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
+ struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
+ u8 val;
+
+ if (hdmi_data->enc_out_format == RGB
+ || hdmi_data->enc_out_format == YCBCR444) {
+ if (hdmi_data->enc_color_depth == 0)
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+ else if (hdmi_data->enc_color_depth == 8) {
+ color_depth = 4;
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+ } else if (hdmi_data->enc_color_depth == 10)
+ color_depth = 5;
+ else if (hdmi_data->enc_color_depth == 12)
+ color_depth = 6;
+ else if (hdmi_data->enc_color_depth == 16)
+ color_depth = 7;
+ else
+ return;
+ } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
+ if (hdmi_data->enc_color_depth == 0 ||
+ hdmi_data->enc_color_depth == 8)
+ remap_size = HDMI_VP_REMAP_YCC422_16bit;
+ else if (hdmi_data->enc_color_depth == 10)
+ remap_size = HDMI_VP_REMAP_YCC422_20bit;
+ else if (hdmi_data->enc_color_depth == 12)
+ remap_size = HDMI_VP_REMAP_YCC422_24bit;
+ else
+ return;
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
+ } else
+ return;
+
+ /* HDMI not support deep color,
+ * because IPU MAX support color depth is 24bit */
+ color_depth = 0;
+
+ /* set the packetizer registers */
+ val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
+ HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
+ ((hdmi_data->pix_repet_factor <<
+ HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
+ HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
+ hdmi_writeb(val, HDMI_VP_PR_CD);
+
+ val = hdmi_readb(HDMI_VP_STUFF);
+ val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK;
+ val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE;
+ hdmi_writeb(val, HDMI_VP_STUFF);
+
+ /* Data from pixel repeater block */
+ if (hdmi_data->pix_repet_factor > 1) {
+ val = hdmi_readb(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_PR_EN_MASK |
+ HDMI_VP_CONF_BYPASS_SELECT_MASK);
+ val |= HDMI_VP_CONF_PR_EN_ENABLE |
+ HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
+ hdmi_writeb(val, HDMI_VP_CONF);
+ } else { /* data from packetizer block */
+ val = hdmi_readb(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_PR_EN_MASK |
+ HDMI_VP_CONF_BYPASS_SELECT_MASK);
+ val |= HDMI_VP_CONF_PR_EN_DISABLE |
+ HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
+ hdmi_writeb(val, HDMI_VP_CONF);
+ }
+
+ val = hdmi_readb(HDMI_VP_STUFF);
+ val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK;
+ val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET;
+ hdmi_writeb(val, HDMI_VP_STUFF);
+
+ hdmi_writeb(remap_size, HDMI_VP_REMAP);
+
+ if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
+ val = hdmi_readb(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
+ HDMI_VP_CONF_PP_EN_ENMASK |
+ HDMI_VP_CONF_YCC422_EN_MASK);
+ val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
+ HDMI_VP_CONF_PP_EN_ENABLE |
+ HDMI_VP_CONF_YCC422_EN_DISABLE;
+ hdmi_writeb(val, HDMI_VP_CONF);
+ } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
+ val = hdmi_readb(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
+ HDMI_VP_CONF_PP_EN_ENMASK |
+ HDMI_VP_CONF_YCC422_EN_MASK);
+ val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
+ HDMI_VP_CONF_PP_EN_DISABLE |
+ HDMI_VP_CONF_YCC422_EN_ENABLE;
+ hdmi_writeb(val, HDMI_VP_CONF);
+ } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
+ val = hdmi_readb(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
+ HDMI_VP_CONF_PP_EN_ENMASK |
+ HDMI_VP_CONF_YCC422_EN_MASK);
+ val |= HDMI_VP_CONF_BYPASS_EN_ENABLE |
+ HDMI_VP_CONF_PP_EN_DISABLE |
+ HDMI_VP_CONF_YCC422_EN_DISABLE;
+ hdmi_writeb(val, HDMI_VP_CONF);
+ } else {
+ return;
+ }
+
+ val = hdmi_readb(HDMI_VP_STUFF);
+ val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK |
+ HDMI_VP_STUFF_YCC422_STUFFING_MASK);
+ val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+ HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE;
+ hdmi_writeb(val, HDMI_VP_STUFF);
+
+ val = hdmi_readb(HDMI_VP_CONF);
+ val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK;
+ val |= output_select;
+ hdmi_writeb(val, HDMI_VP_CONF);
+}
+
+#if 0
+/* Force a fixed color screen */
+static void hdmi_video_force_output(struct mxc_hdmi *hdmi, unsigned char force)
+{
+ u8 val;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ if (force) {
+ hdmi_writeb(0x00, HDMI_FC_DBGTMDS2); /* R */
+ hdmi_writeb(0x00, HDMI_FC_DBGTMDS1); /* G */
+ hdmi_writeb(0xFF, HDMI_FC_DBGTMDS0); /* B */
+ val = hdmi_readb(HDMI_FC_DBGFORCE);
+ val |= HDMI_FC_DBGFORCE_FORCEVIDEO;
+ hdmi_writeb(val, HDMI_FC_DBGFORCE);
+ } else {
+ val = hdmi_readb(HDMI_FC_DBGFORCE);
+ val &= ~HDMI_FC_DBGFORCE_FORCEVIDEO;
+ hdmi_writeb(val, HDMI_FC_DBGFORCE);
+ hdmi_writeb(0x00, HDMI_FC_DBGTMDS2); /* R */
+ hdmi_writeb(0x00, HDMI_FC_DBGTMDS1); /* G */
+ hdmi_writeb(0x00, HDMI_FC_DBGTMDS0); /* B */
+ }
+}
+#endif
+
+static inline void hdmi_phy_test_clear(struct mxc_hdmi *hdmi,
+ unsigned char bit)
+{
+ u8 val = hdmi_readb(HDMI_PHY_TST0);
+ val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
+ val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
+ HDMI_PHY_TST0_TSTCLR_MASK;
+ hdmi_writeb(val, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_enable(struct mxc_hdmi *hdmi,
+ unsigned char bit)
+{
+ u8 val = hdmi_readb(HDMI_PHY_TST0);
+ val &= ~HDMI_PHY_TST0_TSTEN_MASK;
+ val |= (bit << HDMI_PHY_TST0_TSTEN_OFFSET) &
+ HDMI_PHY_TST0_TSTEN_MASK;
+ hdmi_writeb(val, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_clock(struct mxc_hdmi *hdmi,
+ unsigned char bit)
+{
+ u8 val = hdmi_readb(HDMI_PHY_TST0);
+ val &= ~HDMI_PHY_TST0_TSTCLK_MASK;
+ val |= (bit << HDMI_PHY_TST0_TSTCLK_OFFSET) &
+ HDMI_PHY_TST0_TSTCLK_MASK;
+ hdmi_writeb(val, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_din(struct mxc_hdmi *hdmi,
+ unsigned char bit)
+{
+ hdmi_writeb(bit, HDMI_PHY_TST1);
+}
+
+static inline void hdmi_phy_test_dout(struct mxc_hdmi *hdmi,
+ unsigned char bit)
+{
+ hdmi_writeb(bit, HDMI_PHY_TST2);
+}
+
+static bool hdmi_phy_wait_i2c_done(struct mxc_hdmi *hdmi, int msec)
+{
+ unsigned char val = 0;
+ val = hdmi_readb(HDMI_IH_I2CMPHY_STAT0) & 0x3;
+ while (val == 0) {
+ udelay(1000);
+ if (msec-- == 0)
+ return false;
+ val = hdmi_readb(HDMI_IH_I2CMPHY_STAT0) & 0x3;
+ }
+ return true;
+}
+
+static void hdmi_phy_i2c_write(struct mxc_hdmi *hdmi, unsigned short data,
+ unsigned char addr)
+{
+ hdmi_writeb(0xFF, HDMI_IH_I2CMPHY_STAT0);
+ hdmi_writeb(addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
+ hdmi_writeb((unsigned char)(data >> 8),
+ HDMI_PHY_I2CM_DATAO_1_ADDR);
+ hdmi_writeb((unsigned char)(data >> 0),
+ HDMI_PHY_I2CM_DATAO_0_ADDR);
+ hdmi_writeb(HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
+ HDMI_PHY_I2CM_OPERATION_ADDR);
+ hdmi_phy_wait_i2c_done(hdmi, 1000);
+}
+
+#if 0
+static unsigned short hdmi_phy_i2c_read(struct mxc_hdmi *hdmi,
+ unsigned char addr)
+{
+ unsigned short data;
+ unsigned char msb = 0, lsb = 0;
+ hdmi_writeb(0xFF, HDMI_IH_I2CMPHY_STAT0);
+ hdmi_writeb(addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
+ hdmi_writeb(HDMI_PHY_I2CM_OPERATION_ADDR_READ,
+ HDMI_PHY_I2CM_OPERATION_ADDR);
+ hdmi_phy_wait_i2c_done(hdmi, 1000);
+ msb = hdmi_readb(HDMI_PHY_I2CM_DATAI_1_ADDR);
+ lsb = hdmi_readb(HDMI_PHY_I2CM_DATAI_0_ADDR);
+ data = (msb << 8) | lsb;
+ return data;
+}
+
+static int hdmi_phy_i2c_write_verify(struct mxc_hdmi *hdmi, unsigned short data,
+ unsigned char addr)
+{
+ unsigned short val = 0;
+ hdmi_phy_i2c_write(hdmi, data, addr);
+ val = hdmi_phy_i2c_read(hdmi, addr);
+ return (val == data);
+}
+#endif
+
+static bool hdmi_edid_wait_i2c_done(struct mxc_hdmi *hdmi, int msec)
+{
+ unsigned char val = 0;
+ val = hdmi_readb(HDMI_IH_I2CM_STAT0) & 0x2;
+ while (val == 0) {
+
+ udelay(1000);
+ if (msec-- == 0) {
+ dev_dbg(&hdmi->pdev->dev,
+ "HDMI EDID i2c operation time out!!\n");
+ return false;
+ }
+ val = hdmi_readb(HDMI_IH_I2CM_STAT0) & 0x2;
+ }
+ return true;
+}
+
+static u8 hdmi_edid_i2c_read(struct mxc_hdmi *hdmi,
+ u8 addr, u8 blockno)
+{
+ u8 spointer = blockno / 2;
+ u8 edidaddress = ((blockno % 2) * 0x80) + addr;
+ u8 data;
+
+ hdmi_writeb(0xFF, HDMI_IH_I2CM_STAT0);
+ hdmi_writeb(edidaddress, HDMI_I2CM_ADDRESS);
+ hdmi_writeb(spointer, HDMI_I2CM_SEGADDR);
+ if (spointer == 0)
+ hdmi_writeb(HDMI_I2CM_OPERATION_READ,
+ HDMI_I2CM_OPERATION);
+ else
+ hdmi_writeb(HDMI_I2CM_OPERATION_READ_EXT,
+ HDMI_I2CM_OPERATION);
+
+ hdmi_edid_wait_i2c_done(hdmi, 30);
+ data = hdmi_readb(HDMI_I2CM_DATAI);
+ hdmi_writeb(0xFF, HDMI_IH_I2CM_STAT0);
+ return data;
+}
+
+
+/* "Power-down enable (active low)"
+ * That mean that power up == 1! */
+static void mxc_hdmi_phy_enable_power(u8 enable)
+{
+ hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_PDZ_OFFSET,
+ HDMI_PHY_CONF0_PDZ_MASK);
+}
+
+static void mxc_hdmi_phy_enable_tmds(u8 enable)
+{
+ hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_ENTMDS_OFFSET,
+ HDMI_PHY_CONF0_ENTMDS_MASK);
+}
+
+static void mxc_hdmi_phy_gen2_pddq(u8 enable)
+{
+ hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
+ HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
+}
+
+static void mxc_hdmi_phy_gen2_txpwron(u8 enable)
+{
+ hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
+ HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
+}
+
+#if 0
+static void mxc_hdmi_phy_gen2_enhpdrxsense(u8 enable)
+{
+ hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET,
+ HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK);
+}
+#endif
+
+static void mxc_hdmi_phy_sel_data_en_pol(u8 enable)
+{
+ hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
+ HDMI_PHY_CONF0_SELDATAENPOL_MASK);
+}
+
+static void mxc_hdmi_phy_sel_interface_control(u8 enable)
+{
+ hdmi_mask_writeb(enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_SELDIPIF_OFFSET,
+ HDMI_PHY_CONF0_SELDIPIF_MASK);
+}
+
+static int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
+ unsigned char cRes, int cscOn)
+{
+ u8 val;
+ u8 msec;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* color resolution 0 is 8 bit colour depth */
+ if (cRes == 0)
+ cRes = 8;
+
+ if (pRep != 0)
+ return false;
+ else if (cRes != 8 && cRes != 12)
+ return false;
+
+ /* Enable csc path */
+ if (cscOn)
+ val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
+ else
+ val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
+
+ hdmi_writeb(val, HDMI_MC_FLOWCTRL);
+
+ /* gen2 tx power off */
+ mxc_hdmi_phy_gen2_txpwron(0);
+
+ /* gen2 pddq */
+ mxc_hdmi_phy_gen2_pddq(1);
+
+ /* PHY reset */
+ hdmi_writeb(HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
+ hdmi_writeb(HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
+
+ hdmi_writeb(HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
+
+ hdmi_phy_test_clear(hdmi, 1);
+ hdmi_writeb(HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
+ HDMI_PHY_I2CM_SLAVE_ADDR);
+ hdmi_phy_test_clear(hdmi, 0);
+
+ if (hdmi->hdmi_data.video_mode.mPixelClock < 0) {
+ dev_dbg(&hdmi->pdev->dev, "Pixel clock (%d) must be positive\n",
+ hdmi->hdmi_data.video_mode.mPixelClock);
+ return false;
+ }
+
+ if (hdmi->hdmi_data.video_mode.mPixelClock <= 45250000) {
+ switch (cRes) {
+ case 8:
+ /* PLL/MPLL Cfg */
+ hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); /* GMPCTRL */
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x21e1, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x41e2, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
+ break;
+ default:
+ return false;
+ }
+ } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 92500000) {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x0140, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x2141, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x4142, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
+ default:
+ return false;
+ }
+ } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 148500000) {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x20a1, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x40a2, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
+ default:
+ return false;
+ }
+ } else {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x2001, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x4002, 0x06);
+ hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
+ default:
+ return false;
+ }
+ }
+
+ if (hdmi->hdmi_data.video_mode.mPixelClock <= 54000000) {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); /* CURRCTRL */
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
+ break;
+ default:
+ return false;
+ }
+ } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 58400000) {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
+ break;
+ default:
+ return false;
+ }
+ } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 72000000) {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+ break;
+ default:
+ return false;
+ }
+ } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 74250000) {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+ break;
+ default:
+ return false;
+ }
+ } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 118800000) {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
+ break;
+ default:
+ return false;
+ }
+ } else if (hdmi->hdmi_data.video_mode.mPixelClock <= 216000000) {
+ switch (cRes) {
+ case 8:
+ hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
+ break;
+ case 10:
+ hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
+ break;
+ case 12:
+ hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
+ break;
+ default:
+ return false;
+ }
+ } else {
+ dev_err(&hdmi->pdev->dev,
+ "Pixel clock %d - unsupported by HDMI\n",
+ hdmi->hdmi_data.video_mode.mPixelClock);
+ return false;
+ }
+
+ hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
+ hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
+ /* RESISTANCE TERM 133Ohm Cfg */
+ hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */
+ /* PREEMP Cgf 0.00 */
+ hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */
+ /* TX/CK LVL 10 */
+ hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */
+
+ /* Board specific setting for PHY register 0x09, 0x0e to pass HCT */
+ if (hdmi->phy_config.reg_cksymtx != 0)
+ hdmi_phy_i2c_write(hdmi, hdmi->phy_config.reg_cksymtx, 0x09);
+
+ if (hdmi->phy_config.reg_vlev != 0)
+ hdmi_phy_i2c_write(hdmi, hdmi->phy_config.reg_vlev, 0x0E);
+
+ /* REMOVE CLK TERM */
+ hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
+
+ if (hdmi->hdmi_data.video_mode.mPixelClock > 148500000) {
+ hdmi_phy_i2c_write(hdmi, 0x800b, 0x09);
+ hdmi_phy_i2c_write(hdmi, 0x0129, 0x0E);
+ }
+
+ mxc_hdmi_phy_enable_power(1);
+
+ /* toggle TMDS enable */
+ mxc_hdmi_phy_enable_tmds(0);
+ mxc_hdmi_phy_enable_tmds(1);
+
+ /* gen2 tx power on */
+ mxc_hdmi_phy_gen2_txpwron(1);
+ mxc_hdmi_phy_gen2_pddq(0);
+
+ /*Wait for PHY PLL lock */
+ msec = 4;
+ val = hdmi_readb(HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+ while (val == 0) {
+ udelay(1000);
+ if (msec-- == 0) {
+ dev_dbg(&hdmi->pdev->dev, "PHY PLL not locked\n");
+ return false;
+ }
+ val = hdmi_readb(HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+ }
+
+ return true;
+}
+
+static void mxc_hdmi_phy_init(struct mxc_hdmi *hdmi)
+{
+ int i;
+ bool cscon = false;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* Never do phy init if pixel clock is gated.
+ * Otherwise HDMI PHY will get messed up and generate an overflow
+ * interrupt that can't be cleared or detected by accessing the
+ * status register. */
+ if (!hdmi->fb_reg || !hdmi->cable_plugin
+ || (hdmi->blank != FB_BLANK_UNBLANK))
+ return;
+
+ if (!hdmi->hdmi_data.video_mode.mDVI)
+ hdmi_enable_overflow_interrupts();
+
+ /*check csc whether needed activated in HDMI mode */
+ cscon = (isColorSpaceConversion(hdmi) &&
+ !hdmi->hdmi_data.video_mode.mDVI);
+
+ /* HDMI Phy spec says to do the phy initialization sequence twice */
+ for (i = 0 ; i < 2 ; i++) {
+ mxc_hdmi_phy_sel_data_en_pol(1);
+ mxc_hdmi_phy_sel_interface_control(0);
+ mxc_hdmi_phy_enable_tmds(0);
+ mxc_hdmi_phy_enable_power(0);
+
+ /* Enable CSC */
+ hdmi_phy_configure(hdmi, 0, 8, cscon);
+ }
+
+ hdmi->phy_enabled = true;
+}
+
+static void hdmi_config_AVI(struct mxc_hdmi *hdmi)
+{
+ u8 val;
+ u8 pix_fmt;
+ u8 under_scan;
+ u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry;
+ struct fb_videomode mode;
+ const struct fb_videomode *edid_mode;
+ bool aspect_16_9;
+
+ dev_dbg(&hdmi->pdev->dev, "set up AVI frame\n");
+
+ fb_var_to_videomode(&mode, &hdmi->fbi->var);
+ /* Use mode from list extracted from EDID to get aspect ratio */
+ if (!list_empty(&hdmi->fbi->modelist)) {
+ edid_mode = fb_find_nearest_mode(&mode, &hdmi->fbi->modelist);
+ if (edid_mode->vmode & FB_VMODE_ASPECT_16_9)
+ aspect_16_9 = true;
+ else
+ aspect_16_9 = false;
+ } else
+ aspect_16_9 = false;
+
+ /********************************************
+ * AVI Data Byte 1
+ ********************************************/
+ if (hdmi->hdmi_data.enc_out_format == YCBCR444)
+ pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444;
+ else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
+ pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422;
+ else
+ pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB;
+
+ if (hdmi->edid_cfg.cea_underscan)
+ under_scan = HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN;
+ else
+ under_scan = HDMI_FC_AVICONF0_SCAN_INFO_NODATA;
+
+ /*
+ * Active format identification data is present in the AVI InfoFrame.
+ * Under scan info, no bar data
+ */
+ val = pix_fmt | under_scan |
+ HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT |
+ HDMI_FC_AVICONF0_BAR_DATA_NO_DATA;
+
+ hdmi_writeb(val, HDMI_FC_AVICONF0);
+
+ /********************************************
+ * AVI Data Byte 2
+ ********************************************/
+
+ /* Set the Aspect Ratio */
+ if (aspect_16_9) {
+ act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9;
+ coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9;
+ } else {
+ act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3;
+ coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3;
+ }
+
+ /* Set up colorimetry */
+ if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
+ colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO;
+ if (hdmi->hdmi_data.colorimetry == eITU601)
+ ext_colorimetry =
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+ else /* hdmi->hdmi_data.colorimetry == eITU709 */
+ ext_colorimetry =
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709;
+ } else if (hdmi->hdmi_data.enc_out_format != RGB) {
+ if (hdmi->hdmi_data.colorimetry == eITU601)
+ colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE;
+ else /* hdmi->hdmi_data.colorimetry == eITU709 */
+ colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR;
+ ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+ } else { /* Carries no data */
+ colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA;
+ ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+ }
+
+ val = colorimetry | coded_ratio | act_ratio;
+ hdmi_writeb(val, HDMI_FC_AVICONF1);
+
+ /********************************************
+ * AVI Data Byte 3
+ ********************************************/
+
+ val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry |
+ HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT |
+ HDMI_FC_AVICONF2_SCALING_NONE;
+ hdmi_writeb(val, HDMI_FC_AVICONF2);
+
+ /********************************************
+ * AVI Data Byte 4
+ ********************************************/
+ hdmi_writeb(hdmi->vic, HDMI_FC_AVIVID);
+
+ /********************************************
+ * AVI Data Byte 5
+ ********************************************/
+
+ /* Set up input and output pixel repetition */
+ val = (((hdmi->hdmi_data.video_mode.mPixelRepetitionInput + 1) <<
+ HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
+ HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) |
+ ((hdmi->hdmi_data.video_mode.mPixelRepetitionOutput <<
+ HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) &
+ HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
+ hdmi_writeb(val, HDMI_FC_PRCONF);
+
+ /* IT Content and quantization range = don't care */
+ val = HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS |
+ HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED;
+ hdmi_writeb(val, HDMI_FC_AVICONF3);
+
+ /********************************************
+ * AVI Data Bytes 6-13
+ ********************************************/
+ hdmi_writeb(0, HDMI_FC_AVIETB0);
+ hdmi_writeb(0, HDMI_FC_AVIETB1);
+ hdmi_writeb(0, HDMI_FC_AVISBB0);
+ hdmi_writeb(0, HDMI_FC_AVISBB1);
+ hdmi_writeb(0, HDMI_FC_AVIELB0);
+ hdmi_writeb(0, HDMI_FC_AVIELB1);
+ hdmi_writeb(0, HDMI_FC_AVISRB0);
+ hdmi_writeb(0, HDMI_FC_AVISRB1);
+}
+
+/*!
+ * this submodule is responsible for the video/audio data composition.
+ */
+static void hdmi_av_composer(struct mxc_hdmi *hdmi)
+{
+ u8 inv_val;
+ struct fb_info *fbi = hdmi->fbi;
+ struct fb_videomode fb_mode;
+ struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
+ int hblank, vblank;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ fb_var_to_videomode(&fb_mode, &fbi->var);
+
+ vmode->mHSyncPolarity = ((fb_mode.sync & FB_SYNC_HOR_HIGH_ACT) != 0);
+ vmode->mVSyncPolarity = ((fb_mode.sync & FB_SYNC_VERT_HIGH_ACT) != 0);
+ vmode->mInterlaced = ((fb_mode.vmode & FB_VMODE_INTERLACED) != 0);
+ vmode->mPixelClock = (fb_mode.xres + fb_mode.left_margin +
+ fb_mode.right_margin + fb_mode.hsync_len) * (fb_mode.yres +
+ fb_mode.upper_margin + fb_mode.lower_margin +
+ fb_mode.vsync_len) * fb_mode.refresh;
+
+ dev_dbg(&hdmi->pdev->dev, "final pixclk = %d\n", vmode->mPixelClock);
+
+ /* Set up HDMI_FC_INVIDCONF */
+ inv_val = (hdmi->hdmi_data.hdcp_enable ?
+ HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
+ HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
+
+ inv_val |= (vmode->mVSyncPolarity ?
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
+
+ inv_val |= (vmode->mHSyncPolarity ?
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
+
+ inv_val |= (vmode->mDataEnablePolarity ?
+ HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
+ HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
+
+ if (hdmi->vic == 39)
+ inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
+ else
+ inv_val |= (vmode->mInterlaced ?
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
+
+ inv_val |= (vmode->mInterlaced ?
+ HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
+ HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
+
+ inv_val |= (vmode->mDVI ?
+ HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
+ HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE);
+
+ hdmi_writeb(inv_val, HDMI_FC_INVIDCONF);
+
+ /* Set up horizontal active pixel region width */
+ hdmi_writeb(fb_mode.xres >> 8, HDMI_FC_INHACTV1);
+ hdmi_writeb(fb_mode.xres, HDMI_FC_INHACTV0);
+
+ /* Set up vertical blanking pixel region width */
+ hdmi_writeb(fb_mode.yres >> 8, HDMI_FC_INVACTV1);
+ hdmi_writeb(fb_mode.yres, HDMI_FC_INVACTV0);
+
+ /* Set up horizontal blanking pixel region width */
+ hblank = fb_mode.left_margin + fb_mode.right_margin +
+ fb_mode.hsync_len;
+ hdmi_writeb(hblank >> 8, HDMI_FC_INHBLANK1);
+ hdmi_writeb(hblank, HDMI_FC_INHBLANK0);
+
+ /* Set up vertical blanking pixel region width */
+ vblank = fb_mode.upper_margin + fb_mode.lower_margin +
+ fb_mode.vsync_len;
+ hdmi_writeb(vblank, HDMI_FC_INVBLANK);
+
+ /* Set up HSYNC active edge delay width (in pixel clks) */
+ hdmi_writeb(fb_mode.right_margin >> 8, HDMI_FC_HSYNCINDELAY1);
+ hdmi_writeb(fb_mode.right_margin, HDMI_FC_HSYNCINDELAY0);
+
+ /* Set up VSYNC active edge delay (in pixel clks) */
+ hdmi_writeb(fb_mode.lower_margin, HDMI_FC_VSYNCINDELAY);
+
+ /* Set up HSYNC active pulse width (in pixel clks) */
+ hdmi_writeb(fb_mode.hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
+ hdmi_writeb(fb_mode.hsync_len, HDMI_FC_HSYNCINWIDTH0);
+
+ /* Set up VSYNC active edge delay (in pixel clks) */
+ hdmi_writeb(fb_mode.vsync_len, HDMI_FC_VSYNCINWIDTH);
+
+ dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__);
+}
+
+static int mxc_edid_read_internal(struct mxc_hdmi *hdmi, unsigned char *edid,
+ struct mxc_edid_cfg *cfg, struct fb_info *fbi)
+{
+ int extblknum;
+ int i, j, ret;
+ unsigned char *ediddata = edid;
+ unsigned char tmpedid[EDID_LENGTH];
+
+ dev_info(&hdmi->pdev->dev, "%s\n", __func__);
+
+ if (!edid || !cfg || !fbi)
+ return -EINVAL;
+
+ /* init HDMI I2CM for read edid*/
+ hdmi_writeb(0x0, HDMI_I2CM_DIV);
+ hdmi_writeb(0x00, HDMI_I2CM_SS_SCL_HCNT_1_ADDR);
+ hdmi_writeb(0x79, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
+ hdmi_writeb(0x00, HDMI_I2CM_SS_SCL_LCNT_1_ADDR);
+ hdmi_writeb(0x91, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
+
+ hdmi_writeb(0x00, HDMI_I2CM_FS_SCL_HCNT_1_ADDR);
+ hdmi_writeb(0x0F, HDMI_I2CM_FS_SCL_HCNT_0_ADDR);
+ hdmi_writeb(0x00, HDMI_I2CM_FS_SCL_LCNT_1_ADDR);
+ hdmi_writeb(0x21, HDMI_I2CM_FS_SCL_LCNT_0_ADDR);
+
+ hdmi_writeb(0x50, HDMI_I2CM_SLAVE);
+ hdmi_writeb(0x30, HDMI_I2CM_SEGADDR);
+
+ /* Umask edid interrupt */
+ hdmi_writeb(HDMI_I2CM_INT_DONE_POL,
+ HDMI_I2CM_INT);
+
+ hdmi_writeb(HDMI_I2CM_CTLINT_NAC_POL |
+ HDMI_I2CM_CTLINT_ARBITRATION_POL,
+ HDMI_I2CM_CTLINT);
+
+ /* reset edid data zero */
+ memset(edid, 0, EDID_LENGTH*4);
+ memset(cfg, 0, sizeof(struct mxc_edid_cfg));
+
+ /* Check first three byte of EDID head */
+ if (!(hdmi_edid_i2c_read(hdmi, 0, 0) == 0x00) ||
+ !(hdmi_edid_i2c_read(hdmi, 1, 0) == 0xFF) ||
+ !(hdmi_edid_i2c_read(hdmi, 2, 0) == 0xFF)) {
+ dev_info(&hdmi->pdev->dev, "EDID head check failed!");
+ return -ENOENT;
+ }
+
+ for (i = 0; i < 128; i++) {
+ *ediddata = hdmi_edid_i2c_read(hdmi, i, 0);
+ ediddata++;
+ }
+
+ extblknum = edid[0x7E];
+ if (extblknum == 255)
+ extblknum = 0;
+
+ if (extblknum) {
+ ediddata = edid + EDID_LENGTH;
+ for (i = 0; i < 128; i++) {
+ *ediddata = hdmi_edid_i2c_read(hdmi, i, 1);
+ ediddata++;
+ }
+ }
+
+ /* edid first block parsing */
+ memset(&fbi->monspecs, 0, sizeof(fbi->monspecs));
+ fb_edid_to_monspecs(edid, &fbi->monspecs);
+
+ if (extblknum) {
+ ret = mxc_edid_parse_ext_blk(edid + EDID_LENGTH,
+ cfg, &fbi->monspecs);
+ if (ret < 0)
+ return -ENOENT;
+ }
+
+ /* need read segment block? */
+ if (extblknum > 1) {
+ for (j = 2; j <= extblknum; j++) {
+ for (i = 0; i < 128; i++)
+ tmpedid[i] = hdmi_edid_i2c_read(hdmi, i, j);
+
+ /* edid ext block parsing */
+ ret = mxc_edid_parse_ext_blk(tmpedid,
+ cfg, &fbi->monspecs);
+ if (ret < 0)
+ return -ENOENT;
+ }
+ }
+
+ return 0;
+}
+
+static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi)
+{
+ int ret;
+ u8 edid_old[HDMI_EDID_LEN];
+ u8 clkdis;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* save old edid */
+ memcpy(edid_old, hdmi->edid, HDMI_EDID_LEN);
+
+ /* Read EDID via HDMI DDC when HDCP Enable */
+ if (!hdcp_init)
+ ret = mxc_edid_read(hdmi_i2c->adapter, hdmi_i2c->addr,
+ hdmi->edid, &hdmi->edid_cfg, hdmi->fbi);
+ else {
+
+ /* Disable HDCP clk */
+ if (hdmi->hdmi_data.hdcp_enable) {
+ clkdis = hdmi_readb(HDMI_MC_CLKDIS);
+ clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE;
+ hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
+ }
+
+ ret = mxc_edid_read_internal(hdmi, hdmi->edid,
+ &hdmi->edid_cfg, hdmi->fbi);
+
+ /* Enable HDCP clk */
+ if (hdmi->hdmi_data.hdcp_enable) {
+ clkdis = hdmi_readb(HDMI_MC_CLKDIS);
+ clkdis &= ~HDMI_MC_CLKDIS_HDCPCLK_DISABLE;
+ hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
+ }
+
+ }
+ if (ret < 0) {
+ dev_dbg(&hdmi->pdev->dev, "read failed\n");
+ return HDMI_EDID_FAIL;
+ }
+
+ /* Save edid cfg for audio driver */
+ hdmi_set_edid_cfg(&hdmi->edid_cfg);
+
+ if (!memcmp(edid_old, hdmi->edid, HDMI_EDID_LEN)) {
+ dev_info(&hdmi->pdev->dev, "same edid\n");
+ return HDMI_EDID_SAME;
+ }
+
+ if (hdmi->fbi->monspecs.modedb_len == 0) {
+ dev_info(&hdmi->pdev->dev, "No modes read from edid\n");
+ return HDMI_EDID_NO_MODES;
+ }
+
+ return HDMI_EDID_SUCCESS;
+}
+
+static void mxc_hdmi_phy_disable(struct mxc_hdmi *hdmi)
+{
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ if (!hdmi->phy_enabled)
+ return;
+
+ hdmi_disable_overflow_interrupts();
+
+ /* Setting PHY to reset status */
+ hdmi_writeb(HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
+
+ /* Power down PHY */
+ mxc_hdmi_phy_enable_tmds(0);
+ mxc_hdmi_phy_enable_power(0);
+ mxc_hdmi_phy_gen2_txpwron(0);
+ mxc_hdmi_phy_gen2_pddq(1);
+
+ hdmi->phy_enabled = false;
+ dev_dbg(&hdmi->pdev->dev, "%s - exit\n", __func__);
+}
+
+/* HDMI Initialization Step B.4 */
+static void mxc_hdmi_enable_video_path(struct mxc_hdmi *hdmi)
+{
+ u8 clkdis;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* control period minimum duration */
+ hdmi_writeb(12, HDMI_FC_CTRLDUR);
+ hdmi_writeb(32, HDMI_FC_EXCTRLDUR);
+ hdmi_writeb(1, HDMI_FC_EXCTRLSPAC);
+
+ /* Set to fill TMDS data channels */
+ hdmi_writeb(0x0B, HDMI_FC_CH0PREAM);
+ hdmi_writeb(0x16, HDMI_FC_CH1PREAM);
+ hdmi_writeb(0x21, HDMI_FC_CH2PREAM);
+
+ /* Enable pixel clock and tmds data path */
+ clkdis = 0x7F;
+ clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
+ hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
+
+ clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+ hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
+
+ /* Enable csc path */
+ if (isColorSpaceConversion(hdmi)) {
+ clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
+ hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
+ }
+}
+
+static void hdmi_enable_audio_clk(struct mxc_hdmi *hdmi)
+{
+ u8 clkdis;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ clkdis = hdmi_readb(HDMI_MC_CLKDIS);
+ clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
+ hdmi_writeb(clkdis, HDMI_MC_CLKDIS);
+}
+
+/* Workaround to clear the overflow condition */
+static void mxc_hdmi_clear_overflow(struct mxc_hdmi *hdmi)
+{
+ int count;
+ u8 val;
+
+ /* TMDS software reset */
+ hdmi_writeb((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
+
+ val = hdmi_readb(HDMI_FC_INVIDCONF);
+
+ if (cpu_is_imx6dl(hdmi)) {
+ hdmi_writeb(val, HDMI_FC_INVIDCONF);
+ return;
+ }
+
+ for (count = 0 ; count < 5 ; count++)
+ hdmi_writeb(val, HDMI_FC_INVIDCONF);
+}
+
+static void hdmi_enable_overflow_interrupts(void)
+{
+ pr_debug("%s\n", __func__);
+ hdmi_writeb(0, HDMI_FC_MASK2);
+ hdmi_writeb(0, HDMI_IH_MUTE_FC_STAT2);
+}
+
+static void hdmi_disable_overflow_interrupts(void)
+{
+ pr_debug("%s\n", __func__);
+ hdmi_writeb(HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK,
+ HDMI_IH_MUTE_FC_STAT2);
+ hdmi_writeb(0xff, HDMI_FC_MASK2);
+}
+
+static void mxc_hdmi_notify_fb(struct mxc_hdmi *hdmi)
+{
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* Don't notify if we aren't registered yet */
+ WARN_ON(!hdmi->fb_reg);
+
+ /* disable the phy before ipu changes mode */
+ mxc_hdmi_phy_disable(hdmi);
+
+ /*
+ * Note that fb_set_var will block. During this time,
+ * FB_EVENT_MODE_CHANGE callback will happen.
+ * So by the end of this function, mxc_hdmi_setup()
+ * will be done.
+ */
+ hdmi->fbi->var.activate |= FB_ACTIVATE_FORCE;
+ console_lock();
+ hdmi->fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_set_var(hdmi->fbi, &hdmi->fbi->var);
+ hdmi->fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+
+ dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__);
+}
+
+static void mxc_hdmi_edid_rebuild_modelist(struct mxc_hdmi *hdmi)
+{
+ int i;
+ struct fb_videomode *mode;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ console_lock();
+
+ fb_destroy_modelist(&hdmi->fbi->modelist);
+ fb_add_videomode(&vga_mode, &hdmi->fbi->modelist);
+
+ for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) {
+ /*
+ * We might check here if mode is supported by HDMI.
+ * We do not currently support interlaced modes.
+ * And add CEA modes in the modelist.
+ */
+ mode = &hdmi->fbi->monspecs.modedb[i];
+
+ if (!(mode->vmode & FB_VMODE_INTERLACED) &&
+ (mxc_edid_mode_to_vic(mode) != 0)) {
+
+ dev_dbg(&hdmi->pdev->dev, "Added mode %d:", i);
+ dev_dbg(&hdmi->pdev->dev,
+ "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n",
+ hdmi->fbi->monspecs.modedb[i].xres,
+ hdmi->fbi->monspecs.modedb[i].yres,
+ hdmi->fbi->monspecs.modedb[i].refresh,
+ hdmi->fbi->monspecs.modedb[i].vmode,
+ hdmi->fbi->monspecs.modedb[i].flag);
+
+ fb_add_videomode(mode, &hdmi->fbi->modelist);
+ }
+ }
+
+ fb_new_modelist(hdmi->fbi);
+
+ console_unlock();
+}
+
+static void mxc_hdmi_default_edid_cfg(struct mxc_hdmi *hdmi)
+{
+ /* Default setting HDMI working in HDMI mode */
+ hdmi->edid_cfg.hdmi_cap = true;
+}
+
+static void mxc_hdmi_default_modelist(struct mxc_hdmi *hdmi)
+{
+ struct fb_modelist *modelist;
+ struct fb_videomode *m;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* If no EDID data read, set up default modelist; since we don't know
+ * the supported modes of the current sink, we will use only one mode in
+ * this modelist:
+ * the default_mode set up at init (usually got from cmdline)
+ */
+ dev_info(&hdmi->pdev->dev, "create default modelist\n");
+
+ /* If the current modelist is already default, don't re-create it*/
+ if (list_is_singular(&hdmi->fbi->modelist)) {
+ modelist = list_entry((&hdmi->fbi->modelist)->next,
+ struct fb_modelist, list);
+ m = &modelist->mode;
+ if (fb_mode_is_equal(m, &hdmi->default_mode)) {
+ dev_info(&hdmi->pdev->dev,
+ "Modelist is already default, no need to re-create!\n");
+ return;
+ }
+
+ }
+
+ console_lock();
+ fb_destroy_modelist(&hdmi->fbi->modelist);
+ fb_add_videomode(&hdmi->default_mode, &hdmi->fbi->modelist);
+ fb_new_modelist(hdmi->fbi);
+ console_unlock();
+}
+
+static void mxc_hdmi_set_mode_to_vga_dvi(struct mxc_hdmi *hdmi)
+{
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ hdmi_disable_overflow_interrupts();
+
+ fb_videomode_to_var(&hdmi->fbi->var, &vga_mode);
+
+ hdmi->requesting_vga_for_initialization = true;
+ mxc_hdmi_notify_fb(hdmi);
+ hdmi->requesting_vga_for_initialization = false;
+}
+
+static void mxc_hdmi_set_mode(struct mxc_hdmi *hdmi)
+{
+ const struct fb_videomode *mode;
+ struct fb_videomode m;
+ struct fb_var_screeninfo var;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* Set the default mode only once. */
+ if (!hdmi->dft_mode_set) {
+ fb_videomode_to_var(&var, &hdmi->default_mode);
+ hdmi->dft_mode_set = true;
+ } else
+ fb_videomode_to_var(&var, &hdmi->previous_non_vga_mode);
+
+ fb_var_to_videomode(&m, &var);
+ dump_fb_videomode(&m);
+
+ mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist);
+ if (!mode) {
+ pr_err("%s: could not find mode in modelist\n", __func__);
+ return;
+ }
+
+ /* If both video mode and work mode same as previous,
+ * init HDMI again */
+ if (fb_mode_is_equal(&hdmi->previous_non_vga_mode, mode) &&
+ (hdmi->edid_cfg.hdmi_cap != hdmi->hdmi_data.video_mode.mDVI)) {
+ dev_dbg(&hdmi->pdev->dev,
+ "%s: Video mode same as previous\n", __func__);
+ /* update fbi mode in case modelist is updated */
+ hdmi->fbi->mode = (struct fb_videomode *)mode;
+ fb_videomode_to_var(&hdmi->fbi->var, mode);
+ /* update hdmi setting in case EDID data updated */
+ mxc_hdmi_setup(hdmi, 0);
+ } else {
+ dev_dbg(&hdmi->pdev->dev, "%s: New video mode\n", __func__);
+ mxc_hdmi_set_mode_to_vga_dvi(hdmi);
+ fb_videomode_to_var(&hdmi->fbi->var, mode);
+ dump_fb_videomode((struct fb_videomode *)mode);
+ mxc_hdmi_notify_fb(hdmi);
+ }
+
+}
+
+static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi)
+{
+ int edid_status;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ hdmi->cable_plugin = true;
+
+ /* HDMI Initialization Step C */
+ edid_status = mxc_hdmi_read_edid(hdmi);
+
+ /* Read EDID again if first EDID read failed */
+ if (edid_status == HDMI_EDID_NO_MODES ||
+ edid_status == HDMI_EDID_FAIL) {
+ int retry_status;
+ dev_info(&hdmi->pdev->dev, "Read EDID again\n");
+ msleep(200);
+ retry_status = mxc_hdmi_read_edid(hdmi);
+ /* If we get NO_MODES on the 1st and SAME on the 2nd attempt we
+ * want NO_MODES as final result. */
+ if (retry_status != HDMI_EDID_SAME)
+ edid_status = retry_status;
+ }
+
+ /* HDMI Initialization Steps D, E, F */
+ switch (edid_status) {
+ case HDMI_EDID_SUCCESS:
+ mxc_hdmi_edid_rebuild_modelist(hdmi);
+ break;
+
+ /* Nothing to do if EDID same */
+ case HDMI_EDID_SAME:
+ break;
+
+ case HDMI_EDID_FAIL:
+ mxc_hdmi_default_edid_cfg(hdmi);
+ /* No break here */
+ case HDMI_EDID_NO_MODES:
+ default:
+ mxc_hdmi_default_modelist(hdmi);
+ break;
+ }
+
+ /* Setting video mode */
+ mxc_hdmi_set_mode(hdmi);
+
+ dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__);
+}
+
+static int mxc_hdmi_power_on(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
+ mxc_hdmi_phy_init(hdmi);
+ return 0;
+}
+
+static void mxc_hdmi_power_off(struct mxc_dispdrv_handle *disp,
+ struct fb_info *fbi)
+{
+ struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
+ mxc_hdmi_phy_disable(hdmi);
+}
+
+static void mxc_hdmi_cable_disconnected(struct mxc_hdmi *hdmi)
+{
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* Disable All HDMI clock */
+ hdmi_writeb(0xff, HDMI_MC_CLKDIS);
+
+ mxc_hdmi_phy_disable(hdmi);
+
+ hdmi_disable_overflow_interrupts();
+
+ hdmi->cable_plugin = false;
+}
+
+static void hotplug_worker(struct work_struct *work)
+{
+ struct delayed_work *delay_work = to_delayed_work(work);
+ struct mxc_hdmi *hdmi =
+ container_of(delay_work, struct mxc_hdmi, hotplug_work);
+ u32 phy_int_stat, phy_int_pol, phy_int_mask;
+ u8 val;
+ unsigned long flags;
+ char event_string[32];
+ char *envp[] = { event_string, NULL };
+
+ phy_int_stat = hdmi->latest_intr_stat;
+ phy_int_pol = hdmi_readb(HDMI_PHY_POL0);
+
+ dev_dbg(&hdmi->pdev->dev, "phy_int_stat=0x%x, phy_int_pol=0x%x\n",
+ phy_int_stat, phy_int_pol);
+
+ /* check cable status */
+ if (phy_int_stat & HDMI_IH_PHY_STAT0_HPD) {
+ /* cable connection changes */
+ if (phy_int_pol & HDMI_PHY_HPD) {
+ /* Plugin event */
+ dev_dbg(&hdmi->pdev->dev, "EVENT=plugin\n");
+ mxc_hdmi_cable_connected(hdmi);
+
+ /* Make HPD intr active low to capture unplug event */
+ val = hdmi_readb(HDMI_PHY_POL0);
+ val &= ~HDMI_PHY_HPD;
+ hdmi_writeb(val, HDMI_PHY_POL0);
+
+ hdmi_set_cable_state(1);
+
+ sprintf(event_string, "EVENT=plugin");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+#ifdef CONFIG_MXC_HDMI_CEC
+ mxc_hdmi_cec_handle(0x80);
+#endif
+ } else if (!(phy_int_pol & HDMI_PHY_HPD)) {
+ /* Plugout event */
+ dev_dbg(&hdmi->pdev->dev, "EVENT=plugout\n");
+ hdmi_set_cable_state(0);
+ mxc_hdmi_abort_stream();
+ mxc_hdmi_cable_disconnected(hdmi);
+
+ /* Make HPD intr active high to capture plugin event */
+ val = hdmi_readb(HDMI_PHY_POL0);
+ val |= HDMI_PHY_HPD;
+ hdmi_writeb(val, HDMI_PHY_POL0);
+
+ sprintf(event_string, "EVENT=plugout");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+#ifdef CONFIG_MXC_HDMI_CEC
+ mxc_hdmi_cec_handle(0x100);
+#endif
+
+ } else
+ dev_dbg(&hdmi->pdev->dev, "EVENT=none?\n");
+ }
+
+ /* Lock here to ensure full powerdown sequence
+ * completed before next interrupt processed */
+ spin_lock_irqsave(&hdmi->irq_lock, flags);
+
+ /* Re-enable HPD interrupts */
+ phy_int_mask = hdmi_readb(HDMI_PHY_MASK0);
+ phy_int_mask &= ~HDMI_PHY_HPD;
+ hdmi_writeb(phy_int_mask, HDMI_PHY_MASK0);
+
+ /* Unmute interrupts */
+ hdmi_writeb(~HDMI_IH_MUTE_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+
+ if (hdmi_readb(HDMI_IH_FC_STAT2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK)
+ mxc_hdmi_clear_overflow(hdmi);
+
+ spin_unlock_irqrestore(&hdmi->irq_lock, flags);
+}
+
+static void hdcp_hdp_worker(struct work_struct *work)
+{
+ struct delayed_work *delay_work = to_delayed_work(work);
+ struct mxc_hdmi *hdmi =
+ container_of(delay_work, struct mxc_hdmi, hdcp_hdp_work);
+ char event_string[32];
+ char *envp[] = { event_string, NULL };
+
+ /* HDCP interrupt */
+ sprintf(event_string, "EVENT=hdcpint");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+
+ /* Unmute interrupts in HDCP application*/
+}
+
+static irqreturn_t mxc_hdmi_hotplug(int irq, void *data)
+{
+ struct mxc_hdmi *hdmi = data;
+ u8 val, intr_stat;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hdmi->irq_lock, flags);
+
+ /* Check and clean packet overflow interrupt.*/
+ if (hdmi_readb(HDMI_IH_FC_STAT2) &
+ HDMI_IH_FC_STAT2_OVERFLOW_MASK) {
+ mxc_hdmi_clear_overflow(hdmi);
+
+ dev_dbg(&hdmi->pdev->dev, "Overflow interrupt received\n");
+ /* clear irq status */
+ hdmi_writeb(HDMI_IH_FC_STAT2_OVERFLOW_MASK,
+ HDMI_IH_FC_STAT2);
+ }
+
+ /*
+ * We could not disable the irq. Probably the audio driver
+ * has enabled it. Masking off the HDMI interrupts using
+ * HDMI registers.
+ */
+ /* Capture status - used in hotplug_worker ISR */
+ intr_stat = hdmi_readb(HDMI_IH_PHY_STAT0);
+
+ if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
+
+ dev_dbg(&hdmi->pdev->dev, "Hotplug interrupt received\n");
+ hdmi->latest_intr_stat = intr_stat;
+
+ /* Mute interrupts until handled */
+
+ val = hdmi_readb(HDMI_IH_MUTE_PHY_STAT0);
+ val |= HDMI_IH_MUTE_PHY_STAT0_HPD;
+ hdmi_writeb(val, HDMI_IH_MUTE_PHY_STAT0);
+
+ val = hdmi_readb(HDMI_PHY_MASK0);
+ val |= HDMI_PHY_HPD;
+ hdmi_writeb(val, HDMI_PHY_MASK0);
+
+ /* Clear Hotplug interrupts */
+ hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+
+ schedule_delayed_work(&(hdmi->hotplug_work), msecs_to_jiffies(20));
+ }
+
+ /* Check HDCP interrupt state */
+ if (hdmi->hdmi_data.hdcp_enable) {
+ val = hdmi_readb(HDMI_A_APIINTSTAT);
+ if (val != 0) {
+ /* Mute interrupts until interrupt handled */
+ val = 0xFF;
+ hdmi_writeb(val, HDMI_A_APIINTMSK);
+ schedule_delayed_work(&(hdmi->hdcp_hdp_work), msecs_to_jiffies(50));
+ }
+ }
+
+ spin_unlock_irqrestore(&hdmi->irq_lock, flags);
+ return IRQ_HANDLED;
+}
+
+static void mxc_hdmi_setup(struct mxc_hdmi *hdmi, unsigned long event)
+{
+ struct fb_videomode m;
+ const struct fb_videomode *edid_mode;
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ fb_var_to_videomode(&m, &hdmi->fbi->var);
+ dump_fb_videomode(&m);
+
+ dev_dbg(&hdmi->pdev->dev, "%s - video mode changed\n", __func__);
+
+ hdmi->vic = 0;
+ if (!hdmi->requesting_vga_for_initialization) {
+ /* Save mode if this isn't the result of requesting
+ * vga default. */
+ memcpy(&hdmi->previous_non_vga_mode, &m,
+ sizeof(struct fb_videomode));
+ if (!list_empty(&hdmi->fbi->modelist)) {
+ edid_mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist);
+ pr_debug("edid mode ");
+ dump_fb_videomode((struct fb_videomode *)edid_mode);
+ /* update fbi mode */
+ hdmi->fbi->mode = (struct fb_videomode *)edid_mode;
+ hdmi->vic = mxc_edid_mode_to_vic(edid_mode);
+ }
+ }
+
+ hdmi_disable_overflow_interrupts();
+
+ dev_dbg(&hdmi->pdev->dev, "CEA mode used vic=%d\n", hdmi->vic);
+ if (hdmi->edid_cfg.hdmi_cap)
+ hdmi->hdmi_data.video_mode.mDVI = false;
+ else {
+ dev_dbg(&hdmi->pdev->dev, "CEA mode vic=%d work in DVI\n", hdmi->vic);
+ hdmi->hdmi_data.video_mode.mDVI = true;
+ }
+
+ if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
+ (hdmi->vic == 21) || (hdmi->vic == 22) ||
+ (hdmi->vic == 2) || (hdmi->vic == 3) ||
+ (hdmi->vic == 17) || (hdmi->vic == 18))
+ hdmi->hdmi_data.colorimetry = eITU601;
+ else
+ hdmi->hdmi_data.colorimetry = eITU709;
+
+ if ((hdmi->vic == 10) || (hdmi->vic == 11) ||
+ (hdmi->vic == 12) || (hdmi->vic == 13) ||
+ (hdmi->vic == 14) || (hdmi->vic == 15) ||
+ (hdmi->vic == 25) || (hdmi->vic == 26) ||
+ (hdmi->vic == 27) || (hdmi->vic == 28) ||
+ (hdmi->vic == 29) || (hdmi->vic == 30) ||
+ (hdmi->vic == 35) || (hdmi->vic == 36) ||
+ (hdmi->vic == 37) || (hdmi->vic == 38))
+ hdmi->hdmi_data.video_mode.mPixelRepetitionOutput = 1;
+ else
+ hdmi->hdmi_data.video_mode.mPixelRepetitionOutput = 0;
+
+ hdmi->hdmi_data.video_mode.mPixelRepetitionInput = 0;
+
+ /* TODO: Get input format from IPU (via FB driver iface) */
+ hdmi->hdmi_data.enc_in_format = RGB;
+
+ hdmi->hdmi_data.enc_out_format = RGB;
+
+ /* YCbCr only enabled in HDMI mode */
+ if (!hdmi->hdmi_data.video_mode.mDVI &&
+ !hdmi->hdmi_data.rgb_out_enable) {
+ if (hdmi->edid_cfg.cea_ycbcr444)
+ hdmi->hdmi_data.enc_out_format = YCBCR444;
+ else if (hdmi->edid_cfg.cea_ycbcr422)
+ hdmi->hdmi_data.enc_out_format = YCBCR422_8BITS;
+ }
+
+ /* IPU not support depth color output */
+ hdmi->hdmi_data.enc_color_depth = 8;
+ hdmi->hdmi_data.pix_repet_factor = 0;
+ hdmi->hdmi_data.video_mode.mDataEnablePolarity = true;
+
+ /* HDMI Initialization Step B.1 */
+ hdmi_av_composer(hdmi);
+
+ /* HDMI Initializateion Step B.2 */
+ mxc_hdmi_phy_init(hdmi);
+
+ /* HDMI Initialization Step B.3 */
+ mxc_hdmi_enable_video_path(hdmi);
+
+ /* not for DVI mode */
+ if (hdmi->hdmi_data.video_mode.mDVI)
+ dev_dbg(&hdmi->pdev->dev, "%s DVI mode\n", __func__);
+ else {
+ dev_dbg(&hdmi->pdev->dev, "%s CEA mode\n", __func__);
+
+ /* HDMI Initialization Step E - Configure audio */
+ hdmi_clk_regenerator_update_pixel_clock(hdmi->fbi->var.pixclock);
+ hdmi_enable_audio_clk(hdmi);
+
+ /* HDMI Initialization Step F - Configure AVI InfoFrame */
+ hdmi_config_AVI(hdmi);
+ }
+
+ hdmi_video_packetize(hdmi);
+ hdmi_video_csc(hdmi);
+ hdmi_video_sample(hdmi);
+
+ mxc_hdmi_clear_overflow(hdmi);
+
+ dev_dbg(&hdmi->pdev->dev, "%s exit\n\n", __func__);
+
+}
+
+/* Wait until we are registered to enable interrupts */
+static void mxc_hdmi_fb_registered(struct mxc_hdmi *hdmi)
+{
+ unsigned long flags;
+
+ if (hdmi->fb_reg)
+ return;
+
+ spin_lock_irqsave(&hdmi->irq_lock, flags);
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ hdmi_writeb(HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
+ HDMI_PHY_I2CM_INT_ADDR);
+
+ hdmi_writeb(HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
+ HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
+ HDMI_PHY_I2CM_CTLINT_ADDR);
+
+ /* enable cable hot plug irq */
+ hdmi_writeb((u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
+
+ /* Clear Hotplug interrupts */
+ hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+
+ /* Unmute interrupts */
+ hdmi_writeb(~HDMI_IH_MUTE_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+
+ hdmi->fb_reg = true;
+
+ spin_unlock_irqrestore(&hdmi->irq_lock, flags);
+
+}
+
+static int mxc_hdmi_fb_event(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct fb_event *event = v;
+ struct mxc_hdmi *hdmi = container_of(nb, struct mxc_hdmi, nb);
+
+ if (strcmp(event->info->fix.id, hdmi->fbi->fix.id))
+ return 0;
+
+ switch (val) {
+ case FB_EVENT_FB_REGISTERED:
+ dev_dbg(&hdmi->pdev->dev, "event=FB_EVENT_FB_REGISTERED\n");
+ mxc_hdmi_fb_registered(hdmi);
+ hdmi_set_registered(1);
+ break;
+
+ case FB_EVENT_FB_UNREGISTERED:
+ dev_dbg(&hdmi->pdev->dev, "event=FB_EVENT_FB_UNREGISTERED\n");
+ hdmi->fb_reg = false;
+ hdmi_set_registered(0);
+ break;
+
+ case FB_EVENT_MODE_CHANGE:
+ dev_dbg(&hdmi->pdev->dev, "event=FB_EVENT_MODE_CHANGE\n");
+ if (hdmi->fb_reg)
+ mxc_hdmi_setup(hdmi, val);
+ break;
+
+ case FB_EVENT_BLANK:
+ if ((*((int *)event->data) == FB_BLANK_UNBLANK) &&
+ (*((int *)event->data) != hdmi->blank)) {
+ dev_dbg(&hdmi->pdev->dev,
+ "event=FB_EVENT_BLANK - UNBLANK\n");
+
+ hdmi->blank = *((int *)event->data);
+
+ if (hdmi->fb_reg && hdmi->cable_plugin)
+ mxc_hdmi_setup(hdmi, val);
+ hdmi_set_blank_state(1);
+
+ } else if (*((int *)event->data) != hdmi->blank) {
+ dev_dbg(&hdmi->pdev->dev,
+ "event=FB_EVENT_BLANK - BLANK\n");
+ hdmi_set_blank_state(0);
+ mxc_hdmi_abort_stream();
+
+ mxc_hdmi_phy_disable(hdmi);
+
+ hdmi->blank = *((int *)event->data);
+ } else
+ dev_dbg(&hdmi->pdev->dev,
+ "FB BLANK state no changed!\n");
+
+ break;
+
+ case FB_EVENT_SUSPEND:
+ dev_dbg(&hdmi->pdev->dev,
+ "event=FB_EVENT_SUSPEND\n");
+
+ if (hdmi->blank == FB_BLANK_UNBLANK) {
+ mxc_hdmi_phy_disable(hdmi);
+ clk_disable(hdmi->hdmi_iahb_clk);
+ clk_disable(hdmi->hdmi_isfr_clk);
+ clk_disable(hdmi->mipi_core_clk);
+ }
+ break;
+
+ case FB_EVENT_RESUME:
+ dev_dbg(&hdmi->pdev->dev,
+ "event=FB_EVENT_RESUME\n");
+
+ if (hdmi->blank == FB_BLANK_UNBLANK) {
+ clk_enable(hdmi->mipi_core_clk);
+ clk_enable(hdmi->hdmi_iahb_clk);
+ clk_enable(hdmi->hdmi_isfr_clk);
+ mxc_hdmi_phy_init(hdmi);
+ }
+ break;
+
+ }
+ return 0;
+}
+
+static void hdmi_init_route(struct mxc_hdmi *hdmi)
+{
+ uint32_t hdmi_mux_setting, reg;
+ int ipu_id, disp_id;
+
+ ipu_id = mxc_hdmi_ipu_id;
+ disp_id = mxc_hdmi_disp_id;
+
+ if ((ipu_id > 1) || (ipu_id < 0)) {
+ pr_err("Invalid IPU select for HDMI: %d. Set to 0\n", ipu_id);
+ ipu_id = 0;
+ }
+
+ if ((disp_id > 1) || (disp_id < 0)) {
+ pr_err("Invalid DI select for HDMI: %d. Set to 0\n", disp_id);
+ disp_id = 0;
+ }
+
+ reg = readl(hdmi->gpr_hdmi_base);
+
+ /* Configure the connection between IPU1/2 and HDMI */
+ hdmi_mux_setting = 2*ipu_id + disp_id;
+
+ /* GPR3, bits 2-3 = HDMI_MUX_CTL */
+ reg &= ~0xd;
+ reg |= hdmi_mux_setting << 2;
+
+ writel(reg, hdmi->gpr_hdmi_base);
+
+ /* Set HDMI event as SDMA event2 for HDMI audio */
+ reg = readl(hdmi->gpr_sdma_base);
+ reg |= 0x1;
+ writel(reg, hdmi->gpr_sdma_base);
+}
+
+static void hdmi_hdcp_get_property(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+
+ /* Check hdcp enable by dts.*/
+ hdcp_init = of_property_read_bool(np, "fsl,hdcp");
+ if (hdcp_init)
+ dev_dbg(&pdev->dev, "hdcp enable\n");
+ else
+ dev_dbg(&pdev->dev, "hdcp disable\n");
+}
+
+static void hdmi_get_of_property(struct mxc_hdmi *hdmi)
+{
+ struct platform_device *pdev = hdmi->pdev;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(imx_hdmi_dt_ids, &pdev->dev);
+ int ret;
+ u32 phy_reg_vlev = 0, phy_reg_cksymtx = 0;
+
+ if (of_id) {
+ pdev->id_entry = of_id->data;
+ hdmi->cpu_type = pdev->id_entry->driver_data;
+ }
+
+ /* HDMI PHY register vlev and cksymtx preperty is optional.
+ * It is for specific board to pass HCT electrical part.
+ * Default value will been setting in HDMI PHY config function
+ * if it is not define in device tree.
+ */
+ ret = of_property_read_u32(np, "fsl,phy_reg_vlev", &phy_reg_vlev);
+ if (ret)
+ dev_dbg(&pdev->dev, "No board specific HDMI PHY vlev\n");
+
+ ret = of_property_read_u32(np, "fsl,phy_reg_cksymtx", &phy_reg_cksymtx);
+ if (ret)
+ dev_dbg(&pdev->dev, "No board specific HDMI PHY cksymtx\n");
+
+ /* Specific phy config */
+ hdmi->phy_config.reg_cksymtx = phy_reg_cksymtx;
+ hdmi->phy_config.reg_vlev = phy_reg_vlev;
+
+}
+
+/* HDMI Initialization Step A */
+static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp,
+ struct mxc_dispdrv_setting *setting)
+{
+ int ret = 0;
+ u32 i;
+ const struct fb_videomode *mode;
+ struct fb_videomode m;
+ struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
+ int irq = platform_get_irq(hdmi->pdev, 0);
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ /* Check hdmi disp init once */
+ if (hdmi_inited) {
+ dev_err(&hdmi->pdev->dev,
+ "Error only one HDMI output support now!\n");
+ return -1;
+ }
+
+ hdmi_get_of_property(hdmi);
+
+ if (irq < 0)
+ return -ENODEV;
+
+ /* Setting HDMI default to blank state */
+ hdmi->blank = FB_BLANK_POWERDOWN;
+
+ ret = ipu_di_to_crtc(&hdmi->pdev->dev, mxc_hdmi_ipu_id,
+ mxc_hdmi_disp_id, &setting->crtc);
+ if (ret < 0)
+ return ret;
+
+ setting->if_fmt = IPU_PIX_FMT_RGB24;
+
+ hdmi->dft_mode_str = setting->dft_mode_str;
+ hdmi->default_bpp = setting->default_bpp;
+ dev_dbg(&hdmi->pdev->dev, "%s - default mode %s bpp=%d\n",
+ __func__, hdmi->dft_mode_str, hdmi->default_bpp);
+
+ hdmi->fbi = setting->fbi;
+
+ hdmi_init_route(hdmi);
+
+ hdmi->mipi_core_clk = clk_get(&hdmi->pdev->dev, "mipi_core");
+ if (IS_ERR(hdmi->mipi_core_clk)) {
+ ret = PTR_ERR(hdmi->mipi_core_clk);
+ dev_err(&hdmi->pdev->dev,
+ "Unable to get mipi core clk: %d\n", ret);
+ goto egetclk;
+ }
+
+ ret = clk_prepare_enable(hdmi->mipi_core_clk);
+ if (ret < 0) {
+ dev_err(&hdmi->pdev->dev,
+ "Cannot enable mipi core clock: %d\n", ret);
+ goto erate;
+ }
+
+ hdmi->hdmi_isfr_clk = clk_get(&hdmi->pdev->dev, "hdmi_isfr");
+ if (IS_ERR(hdmi->hdmi_isfr_clk)) {
+ ret = PTR_ERR(hdmi->hdmi_isfr_clk);
+ dev_err(&hdmi->pdev->dev,
+ "Unable to get HDMI clk: %d\n", ret);
+ goto egetclk1;
+ }
+
+ ret = clk_prepare_enable(hdmi->hdmi_isfr_clk);
+ if (ret < 0) {
+ dev_err(&hdmi->pdev->dev,
+ "Cannot enable HDMI isfr clock: %d\n", ret);
+ goto erate1;
+ }
+
+ hdmi->hdmi_iahb_clk = clk_get(&hdmi->pdev->dev, "hdmi_iahb");
+ if (IS_ERR(hdmi->hdmi_iahb_clk)) {
+ ret = PTR_ERR(hdmi->hdmi_iahb_clk);
+ dev_err(&hdmi->pdev->dev,
+ "Unable to get HDMI clk: %d\n", ret);
+ goto egetclk2;
+ }
+
+ ret = clk_prepare_enable(hdmi->hdmi_iahb_clk);
+ if (ret < 0) {
+ dev_err(&hdmi->pdev->dev,
+ "Cannot enable HDMI iahb clock: %d\n", ret);
+ goto erate2;
+ }
+
+ dev_dbg(&hdmi->pdev->dev, "Enabled HDMI clocks\n");
+
+ /* Init DDC pins for HDCP */
+ if (hdcp_init) {
+ hdmi->pinctrl = devm_pinctrl_get_select_default(&hdmi->pdev->dev);
+ if (IS_ERR(hdmi->pinctrl)) {
+ dev_err(&hdmi->pdev->dev, "can't get/select DDC pinctrl\n");
+ goto erate2;
+ }
+ }
+
+ /* Product and revision IDs */
+ dev_info(&hdmi->pdev->dev,
+ "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
+ hdmi_readb(HDMI_DESIGN_ID),
+ hdmi_readb(HDMI_REVISION_ID),
+ hdmi_readb(HDMI_PRODUCT_ID0),
+ hdmi_readb(HDMI_PRODUCT_ID1));
+
+ /* To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
+ * N and cts values before enabling phy */
+ hdmi_init_clk_regenerator();
+
+ INIT_LIST_HEAD(&hdmi->fbi->modelist);
+
+ spin_lock_init(&hdmi->irq_lock);
+
+ /* Set the default mode and modelist when disp init. */
+ fb_find_mode(&hdmi->fbi->var, hdmi->fbi,
+ hdmi->dft_mode_str, NULL, 0, NULL,
+ hdmi->default_bpp);
+
+ console_lock();
+
+ fb_destroy_modelist(&hdmi->fbi->modelist);
+
+ /*Add all no interlaced CEA mode to default modelist */
+ for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
+ mode = &mxc_cea_mode[i];
+ if (!(mode->vmode & FB_VMODE_INTERLACED) && (mode->xres != 0))
+ fb_add_videomode(mode, &hdmi->fbi->modelist);
+ }
+
+ console_unlock();
+
+ /* Find a nearest mode in default modelist */
+ fb_var_to_videomode(&m, &hdmi->fbi->var);
+
+ hdmi->dft_mode_set = false;
+ mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist);
+ if (!mode) {
+ pr_err("%s: could not find mode in modelist\n", __func__);
+ return -1;
+ }
+ dump_fb_videomode(mode);
+ /* Save default video mode */
+ memcpy(&hdmi->default_mode, mode, sizeof(struct fb_videomode));
+
+ fb_videomode_to_var(&hdmi->fbi->var, mode);
+
+ /* update fbi mode */
+ hdmi->fbi->mode = (struct fb_videomode *)mode;
+
+ /* Default setting HDMI working in HDMI mode*/
+ hdmi->edid_cfg.hdmi_cap = true;
+
+ INIT_DELAYED_WORK(&hdmi->hotplug_work, hotplug_worker);
+ INIT_DELAYED_WORK(&hdmi->hdcp_hdp_work, hdcp_hdp_worker);
+
+ /* Configure registers related to HDMI interrupt
+ * generation before registering IRQ. */
+ hdmi_writeb(HDMI_PHY_HPD, HDMI_PHY_POL0);
+
+ /* Clear Hotplug interrupts */
+ hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+
+ hdmi->nb.notifier_call = mxc_hdmi_fb_event;
+ ret = fb_register_client(&hdmi->nb);
+ if (ret < 0)
+ goto efbclient;
+
+ memset(&hdmi->hdmi_data, 0, sizeof(struct hdmi_data_info));
+
+ /* Default HDMI working in RGB mode */
+ hdmi->hdmi_data.rgb_out_enable = true;
+
+ ret = devm_request_irq(&hdmi->pdev->dev, irq, mxc_hdmi_hotplug, IRQF_SHARED,
+ dev_name(&hdmi->pdev->dev), hdmi);
+ if (ret < 0) {
+ dev_err(&hdmi->pdev->dev,
+ "Unable to request irq: %d\n", ret);
+ goto ereqirq;
+ }
+
+ ret = device_create_file(&hdmi->pdev->dev, &dev_attr_fb_name);
+ if (ret < 0)
+ dev_warn(&hdmi->pdev->dev,
+ "cound not create sys node for fb name\n");
+ ret = device_create_file(&hdmi->pdev->dev, &dev_attr_cable_state);
+ if (ret < 0)
+ dev_warn(&hdmi->pdev->dev,
+ "cound not create sys node for cable state\n");
+ ret = device_create_file(&hdmi->pdev->dev, &dev_attr_edid);
+ if (ret < 0)
+ dev_warn(&hdmi->pdev->dev,
+ "cound not create sys node for edid\n");
+
+ ret = device_create_file(&hdmi->pdev->dev, &dev_attr_rgb_out_enable);
+ if (ret < 0)
+ dev_warn(&hdmi->pdev->dev,
+ "cound not create sys node for rgb out enable\n");
+
+ ret = device_create_file(&hdmi->pdev->dev, &dev_attr_hdcp_enable);
+ if (ret < 0)
+ dev_warn(&hdmi->pdev->dev,
+ "cound not create sys node for hdcp enable\n");
+
+ dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__);
+
+ hdmi_inited = true;
+
+ return ret;
+
+efbclient:
+ free_irq(irq, hdmi);
+ereqirq:
+ clk_disable_unprepare(hdmi->hdmi_iahb_clk);
+erate2:
+ clk_put(hdmi->hdmi_iahb_clk);
+egetclk2:
+ clk_disable_unprepare(hdmi->hdmi_isfr_clk);
+erate1:
+ clk_put(hdmi->hdmi_isfr_clk);
+egetclk1:
+ clk_disable_unprepare(hdmi->mipi_core_clk);
+erate:
+ clk_put(hdmi->mipi_core_clk);
+egetclk:
+ dev_dbg(&hdmi->pdev->dev, "%s error exit\n", __func__);
+
+ return ret;
+}
+
+static void mxc_hdmi_disp_deinit(struct mxc_dispdrv_handle *disp)
+{
+ struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
+
+ dev_dbg(&hdmi->pdev->dev, "%s\n", __func__);
+
+ fb_unregister_client(&hdmi->nb);
+
+ clk_disable_unprepare(hdmi->hdmi_isfr_clk);
+ clk_put(hdmi->hdmi_isfr_clk);
+ clk_disable_unprepare(hdmi->hdmi_iahb_clk);
+ clk_put(hdmi->hdmi_iahb_clk);
+ clk_disable_unprepare(hdmi->mipi_core_clk);
+ clk_put(hdmi->mipi_core_clk);
+
+ platform_device_unregister(hdmi->pdev);
+
+ hdmi_inited = false;
+}
+
+static struct mxc_dispdrv_driver mxc_hdmi_drv = {
+ .name = DISPDRV_HDMI,
+ .init = mxc_hdmi_disp_init,
+ .deinit = mxc_hdmi_disp_deinit,
+ .enable = mxc_hdmi_power_on,
+ .disable = mxc_hdmi_power_off,
+};
+
+
+static int mxc_hdmi_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static long mxc_hdmi_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int __user *argp = (void __user *)arg;
+ int ret = 0;
+
+ switch (cmd) {
+ case HDMI_IOC_GET_RESOURCE:
+ ret = copy_to_user(argp, &g_hdmi->hdmi_data,
+ sizeof(g_hdmi->hdmi_data)) ? -EFAULT : 0;
+ break;
+ case HDMI_IOC_GET_CPU_TYPE:
+ ret = put_user(g_hdmi->cpu_type, argp);
+ break;
+ default:
+ pr_debug("Unsupport cmd %d\n", cmd);
+ break;
+ }
+
+ return ret;
+}
+
+static int mxc_hdmi_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static const struct file_operations mxc_hdmi_fops = {
+ .owner = THIS_MODULE,
+ .open = mxc_hdmi_open,
+ .release = mxc_hdmi_release,
+ .unlocked_ioctl = mxc_hdmi_ioctl,
+};
+
+
+static int mxc_hdmi_probe(struct platform_device *pdev)
+{
+ struct mxc_hdmi *hdmi;
+ struct device *temp_class;
+ struct resource *res;
+ int ret = 0;
+
+ /* Check I2C driver is loaded and available
+ * check hdcp function is enable by dts */
+ hdmi_hdcp_get_property(pdev);
+ if (!hdmi_i2c && !hdcp_init)
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOENT;
+
+ hdmi = devm_kzalloc(&pdev->dev,
+ sizeof(struct mxc_hdmi),
+ GFP_KERNEL);
+ if (!hdmi) {
+ dev_err(&pdev->dev, "Cannot allocate device data\n");
+ ret = -ENOMEM;
+ goto ealloc;
+ }
+ g_hdmi = hdmi;
+
+ hdmi_major = register_chrdev(hdmi_major, "mxc_hdmi", &mxc_hdmi_fops);
+ if (hdmi_major < 0) {
+ printk(KERN_ERR "HDMI: unable to get a major for HDMI\n");
+ ret = -EBUSY;
+ goto ealloc;
+ }
+
+ hdmi_class = class_create(THIS_MODULE, "mxc_hdmi");
+ if (IS_ERR(hdmi_class)) {
+ ret = PTR_ERR(hdmi_class);
+ goto err_out_chrdev;
+ }
+
+ temp_class = device_create(hdmi_class, NULL, MKDEV(hdmi_major, 0),
+ NULL, "mxc_hdmi");
+ if (IS_ERR(temp_class)) {
+ ret = PTR_ERR(temp_class);
+ goto err_out_class;
+ }
+
+ hdmi->pdev = pdev;
+
+ hdmi->core_pdev = platform_device_alloc("mxc_hdmi_core", -1);
+ if (!hdmi->core_pdev) {
+ pr_err("%s failed platform_device_alloc for hdmi core\n",
+ __func__);
+ ret = -ENOMEM;
+ goto ecore;
+ }
+
+ hdmi->gpr_base = ioremap(res->start, resource_size(res));
+ if (!hdmi->gpr_base) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto eiomap;
+ }
+
+ hdmi->gpr_hdmi_base = hdmi->gpr_base + 3;
+ hdmi->gpr_sdma_base = hdmi->gpr_base;
+
+ hdmi_inited = false;
+
+ hdmi->disp_mxc_hdmi = mxc_dispdrv_register(&mxc_hdmi_drv);
+ if (IS_ERR(hdmi->disp_mxc_hdmi)) {
+ dev_err(&pdev->dev, "Failed to register dispdrv - 0x%x\n",
+ (int)hdmi->disp_mxc_hdmi);
+ ret = (int)hdmi->disp_mxc_hdmi;
+ goto edispdrv;
+ }
+ mxc_dispdrv_setdata(hdmi->disp_mxc_hdmi, hdmi);
+
+ platform_set_drvdata(pdev, hdmi);
+
+ hdmi_regulator = devm_regulator_get(&pdev->dev, "HDMI");
+ if (!IS_ERR(hdmi_regulator)) {
+ ret = regulator_enable(hdmi_regulator);
+ if (ret) {
+ dev_err(&pdev->dev, "enable 5v hdmi regulator failed\n");
+ goto edispdrv;
+ }
+ } else {
+ hdmi_regulator = NULL;
+ dev_warn(&pdev->dev, "No hdmi 5v supply\n");
+ }
+
+ return 0;
+edispdrv:
+ iounmap(hdmi->gpr_base);
+eiomap:
+ platform_device_put(hdmi->core_pdev);
+ecore:
+ kfree(hdmi);
+err_out_class:
+ device_destroy(hdmi_class, MKDEV(hdmi_major, 0));
+ class_destroy(hdmi_class);
+err_out_chrdev:
+ unregister_chrdev(hdmi_major, "mxc_hdmi");
+ealloc:
+ return ret;
+}
+
+static int mxc_hdmi_remove(struct platform_device *pdev)
+{
+ struct mxc_hdmi *hdmi = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
+
+ fb_unregister_client(&hdmi->nb);
+
+ mxc_dispdrv_puthandle(hdmi->disp_mxc_hdmi);
+ mxc_dispdrv_unregister(hdmi->disp_mxc_hdmi);
+ iounmap(hdmi->gpr_base);
+ /* No new work will be scheduled, wait for running ISR */
+ free_irq(irq, hdmi);
+ kfree(hdmi);
+
+ if (hdmi_regulator)
+ regulator_disable(hdmi_regulator);
+
+ g_hdmi = NULL;
+
+ return 0;
+}
+
+static struct platform_driver mxc_hdmi_driver = {
+ .probe = mxc_hdmi_probe,
+ .remove = mxc_hdmi_remove,
+ .driver = {
+ .name = "mxc_hdmi",
+ .of_match_table = imx_hdmi_dt_ids,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mxc_hdmi_init(void)
+{
+ return platform_driver_register(&mxc_hdmi_driver);
+}
+module_init(mxc_hdmi_init);
+
+static void __exit mxc_hdmi_exit(void)
+{
+ if (hdmi_major > 0) {
+ device_destroy(hdmi_class, MKDEV(hdmi_major, 0));
+ class_destroy(hdmi_class);
+ unregister_chrdev(hdmi_major, "mxc_hdmi");
+ hdmi_major = 0;
+ }
+
+ platform_driver_unregister(&mxc_hdmi_driver);
+}
+module_exit(mxc_hdmi_exit);
+
+static int mxc_hdmi_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+ return -ENODEV;
+
+ hdmi_i2c = client;
+
+ return 0;
+}
+
+static int mxc_hdmi_i2c_remove(struct i2c_client *client)
+{
+ hdmi_i2c = NULL;
+ return 0;
+}
+
+static const struct of_device_id imx_hdmi_i2c_match[] = {
+ { .compatible = "fsl,imx6-hdmi-i2c", },
+ { /* sentinel */ }
+};
+
+static const struct i2c_device_id mxc_hdmi_i2c_id[] = {
+ { "mxc_hdmi_i2c", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, mxc_hdmi_i2c_id);
+
+static struct i2c_driver mxc_hdmi_i2c_driver = {
+ .driver = {
+ .name = "mxc_hdmi_i2c",
+ .of_match_table = imx_hdmi_i2c_match,
+ },
+ .probe = mxc_hdmi_i2c_probe,
+ .remove = mxc_hdmi_i2c_remove,
+ .id_table = mxc_hdmi_i2c_id,
+};
+
+static int __init mxc_hdmi_i2c_init(void)
+{
+ return i2c_add_driver(&mxc_hdmi_i2c_driver);
+}
+
+static void __exit mxc_hdmi_i2c_exit(void)
+{
+ i2c_del_driver(&mxc_hdmi_i2c_driver);
+}
+
+module_init(mxc_hdmi_i2c_init);
+module_exit(mxc_hdmi_i2c_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
diff --git a/drivers/video/fbdev/mxc/mxc_ipuv3_fb.c b/drivers/video/fbdev/mxc/mxc_ipuv3_fb.c
new file mode 100644
index 000000000000..c6001b6a73d2
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_ipuv3_fb.c
@@ -0,0 +1,3673 @@
+/*
+ * Copyright 2004-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
+ */
+
+/*!
+ * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
+ */
+
+/*!
+ * @file mxcfb.c
+ *
+ * @brief MXC Frame buffer driver for SDC
+ *
+ * @ingroup Framebuffer
+ */
+
+/*!
+ * Include files
+ */
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/fsl_devices.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/ipu.h>
+#include <linux/ipu-v3.h>
+#include <linux/ipu-v3-pre.h>
+#include <linux/ipu-v3-prg.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+
+#include "mxc_dispdrv.h"
+
+/*
+ * Driver name
+ */
+#define MXCFB_NAME "mxc_sdc_fb"
+
+/* Display port number */
+#define MXCFB_PORT_NUM 2
+/*!
+ * Structure containing the MXC specific framebuffer information.
+ */
+struct mxcfb_info {
+ int default_bpp;
+ int cur_blank;
+ int next_blank;
+ ipu_channel_t ipu_ch;
+ int ipu_id;
+ int ipu_di;
+ int pre_num;
+ u32 ipu_di_pix_fmt;
+ bool ipu_int_clk;
+ bool overlay;
+ bool alpha_chan_en;
+ bool late_init;
+ bool first_set_par;
+ bool resolve;
+ bool prefetch;
+ bool on_the_fly;
+ uint32_t final_pfmt;
+ unsigned long gpu_sec_buf_off;
+ unsigned long base;
+ uint32_t x_crop;
+ uint32_t y_crop;
+ unsigned int sec_buf_off;
+ unsigned int trd_buf_off;
+ dma_addr_t store_addr;
+ dma_addr_t alpha_phy_addr0;
+ dma_addr_t alpha_phy_addr1;
+ void *alpha_virt_addr0;
+ void *alpha_virt_addr1;
+ uint32_t alpha_mem_len;
+ uint32_t ipu_ch_irq;
+ uint32_t ipu_ch_nf_irq;
+ uint32_t ipu_alp_ch_irq;
+ uint32_t cur_ipu_buf;
+ uint32_t cur_ipu_alpha_buf;
+
+ u32 pseudo_palette[16];
+
+ bool mode_found;
+ struct completion flip_complete;
+ struct completion alpha_flip_complete;
+ struct completion vsync_complete;
+ struct completion otf_complete; /* on the fly */
+
+ void *ipu;
+ struct fb_info *ovfbi;
+
+ struct mxc_dispdrv_handle *dispdrv;
+
+ struct fb_var_screeninfo cur_var;
+ uint32_t cur_ipu_pfmt;
+ uint32_t cur_fb_pfmt;
+ bool cur_prefetch;
+ spinlock_t spin_lock; /* for PRE small yres cases */
+ struct ipu_pre_context *pre_config;
+};
+
+struct mxcfb_pfmt {
+ u32 fb_pix_fmt;
+ int bpp;
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+};
+
+struct mxcfb_tile_block {
+ u32 fb_pix_fmt;
+ int bw; /* in pixel */
+ int bh; /* in pixel */
+};
+
+#define NA (~0x0UL)
+static const struct mxcfb_pfmt mxcfb_pfmts[] = {
+ /* pixel bpp red green blue transp */
+ {IPU_PIX_FMT_RGB565, 16, {11, 5, 0}, { 5, 6, 0}, { 0, 5, 0}, { 0, 0, 0} },
+ {IPU_PIX_FMT_BGRA4444, 16, { 8, 4, 0}, { 4, 4, 0}, { 0, 4, 0}, { 12, 4, 0} },
+ {IPU_PIX_FMT_BGRA5551, 16, {10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0} },
+ {IPU_PIX_FMT_RGB24, 24, { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0}, { 0, 0, 0} },
+ {IPU_PIX_FMT_BGR24, 24, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0} },
+ {IPU_PIX_FMT_RGB32, 32, { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0}, {24, 8, 0} },
+ {IPU_PIX_FMT_BGR32, 32, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, {24, 8, 0} },
+ {IPU_PIX_FMT_ABGR32, 32, {24, 8, 0}, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0} },
+ /* pixel bpp red green blue transp */
+ {IPU_PIX_FMT_YUV420P2, 12, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_YUV420P, 12, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_YVU420P, 12, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_NV12, 12, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {PRE_PIX_FMT_NV21, 12, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_NV16, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {PRE_PIX_FMT_NV61, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_YUV422P, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_YVU422P, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_UYVY, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_YUYV, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_YUV444, 24, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_YUV444P, 24, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_AYUV, 32, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ /* pixel bpp red green blue transp */
+ {IPU_PIX_FMT_GPU32_SB_ST, 32, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_GPU32_SB_SRT, 32, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_GPU32_ST, 32, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_GPU32_SRT, 32, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_GPU16_SB_ST, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_GPU16_SB_SRT, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_GPU16_ST, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+ {IPU_PIX_FMT_GPU16_SRT, 16, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA}, {NA, NA, NA} },
+};
+
+/* Tile fb alignment */
+static const struct mxcfb_tile_block tas[] = {
+ {IPU_PIX_FMT_GPU32_SB_ST, 16, 8},
+ {IPU_PIX_FMT_GPU32_SB_SRT, 64, 128},
+ {IPU_PIX_FMT_GPU32_ST, 16, 4},
+ {IPU_PIX_FMT_GPU32_SRT, 64, 64},
+ {IPU_PIX_FMT_GPU16_SB_ST, 16, 8},
+ {IPU_PIX_FMT_GPU16_SB_SRT, 64, 128},
+ {IPU_PIX_FMT_GPU16_ST, 16, 4},
+ {IPU_PIX_FMT_GPU16_SRT, 64, 64},
+};
+
+/* The block can be resolved */
+static const struct mxcfb_tile_block trs[] = {
+ /* pixel w h */
+ {IPU_PIX_FMT_GPU32_SB_ST, 16, 4},
+ {IPU_PIX_FMT_GPU32_SB_SRT, 16, 4},
+ {IPU_PIX_FMT_GPU32_ST, 16, 4},
+ {IPU_PIX_FMT_GPU32_SRT, 16, 4},
+ {IPU_PIX_FMT_GPU16_SB_ST, 16, 4},
+ {IPU_PIX_FMT_GPU16_SB_SRT, 16, 4},
+ {IPU_PIX_FMT_GPU16_ST, 16, 4},
+ {IPU_PIX_FMT_GPU16_SRT, 16, 4},
+};
+
+struct mxcfb_alloc_list {
+ struct list_head list;
+ dma_addr_t phy_addr;
+ void *cpu_addr;
+ u32 size;
+};
+
+enum {
+ BOTH_ON,
+ SRC_ON,
+ TGT_ON,
+ BOTH_OFF
+};
+
+static bool g_dp_in_use[2];
+LIST_HEAD(fb_alloc_list);
+
+/* Return default standard(RGB) pixel format */
+static uint32_t bpp_to_pixfmt(int bpp)
+{
+ uint32_t pixfmt = 0;
+
+ switch (bpp) {
+ case 24:
+ pixfmt = IPU_PIX_FMT_BGR24;
+ break;
+ case 32:
+ pixfmt = IPU_PIX_FMT_BGR32;
+ break;
+ case 16:
+ pixfmt = IPU_PIX_FMT_RGB565;
+ break;
+ }
+ return pixfmt;
+}
+
+static inline int bitfield_is_equal(struct fb_bitfield f1,
+ struct fb_bitfield f2)
+{
+ return !memcmp(&f1, &f2, sizeof(f1));
+}
+
+static int pixfmt_to_var(uint32_t pixfmt, struct fb_var_screeninfo *var)
+{
+ int i, ret = -1;
+
+ for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
+ if (pixfmt == mxcfb_pfmts[i].fb_pix_fmt) {
+ var->red = mxcfb_pfmts[i].red;
+ var->green = mxcfb_pfmts[i].green;
+ var->blue = mxcfb_pfmts[i].blue;
+ var->transp = mxcfb_pfmts[i].transp;
+ var->bits_per_pixel = mxcfb_pfmts[i].bpp;
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int bpp_to_var(int bpp, struct fb_var_screeninfo *var)
+{
+ uint32_t pixfmt = 0;
+
+ if (var->nonstd)
+ return -1;
+
+ pixfmt = bpp_to_pixfmt(bpp);
+ if (pixfmt)
+ return pixfmt_to_var(pixfmt, var);
+ else
+ return -1;
+}
+
+static int check_var_pixfmt(struct fb_var_screeninfo *var)
+{
+ int i, ret = -1;
+
+ if (var->nonstd) {
+ for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
+ if (mxcfb_pfmts[i].fb_pix_fmt == var->nonstd) {
+ var->bits_per_pixel = mxcfb_pfmts[i].bpp;
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
+ if (bitfield_is_equal(var->red, mxcfb_pfmts[i].red) &&
+ bitfield_is_equal(var->green, mxcfb_pfmts[i].green) &&
+ bitfield_is_equal(var->blue, mxcfb_pfmts[i].blue) &&
+ bitfield_is_equal(var->transp, mxcfb_pfmts[i].transp) &&
+ var->bits_per_pixel == mxcfb_pfmts[i].bpp) {
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
+static uint32_t fb_to_store_pixfmt(uint32_t fb_pixfmt)
+{
+ switch (fb_pixfmt) {
+ case IPU_PIX_FMT_RGB32:
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_ABGR32:
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_BGRA4444:
+ case IPU_PIX_FMT_BGRA5551:
+ case IPU_PIX_FMT_UYVY:
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_YUV444:
+ case IPU_PIX_FMT_AYUV:
+ return fb_pixfmt;
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YVU422P:
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_NV12:
+ case PRE_PIX_FMT_NV21:
+ case IPU_PIX_FMT_NV16:
+ case PRE_PIX_FMT_NV61:
+ case IPU_PIX_FMT_YUV420P:
+ return IPU_PIX_FMT_UYVY;
+ case IPU_PIX_FMT_YUV444P:
+ return IPU_PIX_FMT_AYUV;
+ default:
+ return 0;
+ }
+}
+
+static uint32_t fbi_to_pixfmt(struct fb_info *fbi, bool original_fb)
+{
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+ int i;
+ uint32_t pixfmt = 0;
+
+ if (fbi->var.nonstd) {
+ if (mxc_fbi->prefetch && !original_fb) {
+ if (ipu_pixel_format_is_gpu_tile(fbi->var.nonstd))
+ goto next;
+
+ return fb_to_store_pixfmt(fbi->var.nonstd);
+ } else {
+ return fbi->var.nonstd;
+ }
+ }
+
+next:
+ for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
+ if (bitfield_is_equal(fbi->var.red, mxcfb_pfmts[i].red) &&
+ bitfield_is_equal(fbi->var.green, mxcfb_pfmts[i].green) &&
+ bitfield_is_equal(fbi->var.blue, mxcfb_pfmts[i].blue) &&
+ bitfield_is_equal(fbi->var.transp, mxcfb_pfmts[i].transp)) {
+ pixfmt = mxcfb_pfmts[i].fb_pix_fmt;
+ break;
+ }
+ }
+
+ if (pixfmt == 0)
+ dev_err(fbi->device, "cannot get pixel format\n");
+
+ return pixfmt;
+}
+
+static void fmt_to_tile_alignment(uint32_t fmt, int *bw, int *bh)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tas); i++) {
+ if (tas[i].fb_pix_fmt == fmt) {
+ *bw = tas[i].bw;
+ *bh = tas[i].bh;
+ }
+ }
+
+ BUG_ON(!(*bw) || !(*bh));
+}
+
+static void fmt_to_tile_block(uint32_t fmt, int *bw, int *bh)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(trs); i++) {
+ if (trs[i].fb_pix_fmt == fmt) {
+ *bw = trs[i].bw;
+ *bh = trs[i].bh;
+ }
+ }
+
+ BUG_ON(!(*bw) || !(*bh));
+}
+
+static struct fb_info *found_registered_fb(ipu_channel_t ipu_ch, int ipu_id)
+{
+ int i;
+ struct mxcfb_info *mxc_fbi;
+ struct fb_info *fbi = NULL;
+
+ for (i = 0; i < num_registered_fb; i++) {
+ mxc_fbi =
+ ((struct mxcfb_info *)(registered_fb[i]->par));
+
+ if ((mxc_fbi->ipu_ch == ipu_ch) &&
+ (mxc_fbi->ipu_id == ipu_id)) {
+ fbi = registered_fb[i];
+ break;
+ }
+ }
+ return fbi;
+}
+
+static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id);
+static irqreturn_t mxcfb_nf_irq_handler(int irq, void *dev_id);
+static int mxcfb_blank(int blank, struct fb_info *info);
+static int mxcfb_map_video_memory(struct fb_info *fbi);
+static int mxcfb_unmap_video_memory(struct fb_info *fbi);
+static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd,
+ unsigned long arg);
+
+/*
+ * Set fixed framebuffer parameters based on variable settings.
+ *
+ * @param info framebuffer information pointer
+ */
+static int mxcfb_set_fix(struct fb_info *info)
+{
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct fb_var_screeninfo *var = &info->var;
+
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->accel = FB_ACCEL_NONE;
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->xpanstep = 1;
+ fix->ywrapstep = 1;
+ fix->ypanstep = 1;
+
+ return 0;
+}
+
+static int _setup_disp_channel1(struct fb_info *fbi)
+{
+ ipu_channel_params_t params;
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+
+ memset(&params, 0, sizeof(params));
+
+ if (mxc_fbi->ipu_ch == MEM_DC_SYNC) {
+ params.mem_dc_sync.di = mxc_fbi->ipu_di;
+ if (fbi->var.vmode & FB_VMODE_INTERLACED)
+ params.mem_dc_sync.interlaced = true;
+ params.mem_dc_sync.out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
+ params.mem_dc_sync.in_pixel_fmt = mxc_fbi->on_the_fly ?
+ mxc_fbi->final_pfmt :
+ fbi_to_pixfmt(fbi, false);
+ } else {
+ params.mem_dp_bg_sync.di = mxc_fbi->ipu_di;
+ if (fbi->var.vmode & FB_VMODE_INTERLACED)
+ params.mem_dp_bg_sync.interlaced = true;
+ params.mem_dp_bg_sync.out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
+ params.mem_dp_bg_sync.in_pixel_fmt = mxc_fbi->on_the_fly ?
+ mxc_fbi->final_pfmt :
+ fbi_to_pixfmt(fbi, false);
+ if (mxc_fbi->alpha_chan_en)
+ params.mem_dp_bg_sync.alpha_chan_en = true;
+ }
+ if (ipu_init_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, &params) < 0) {
+ dev_err(fbi->device, "init ipu channel fail\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int _setup_disp_channel2(struct fb_info *fbi)
+{
+ int retval = 0;
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+ int fb_stride, ipu_stride, bw = 0, bh = 0;
+ unsigned long base, ipu_base;
+ unsigned int fr_xoff, fr_yoff, fr_w, fr_h;
+ unsigned int prg_width;
+ struct ipu_pre_context pre;
+ bool post_pre_disable = false;
+
+ switch (fbi_to_pixfmt(fbi, true)) {
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_NV12:
+ case PRE_PIX_FMT_NV21:
+ case IPU_PIX_FMT_NV16:
+ case PRE_PIX_FMT_NV61:
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YVU422P:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YUV444P:
+ fb_stride = fbi->var.xres_virtual;
+ break;
+ default:
+ fb_stride = fbi->fix.line_length;
+ }
+
+ base = fbi->fix.smem_start;
+ fr_xoff = fbi->var.xoffset;
+ fr_w = fbi->var.xres_virtual;
+ if (!(fbi->var.vmode & FB_VMODE_YWRAP)) {
+ dev_dbg(fbi->device, "Y wrap disabled\n");
+ fr_yoff = fbi->var.yoffset % fbi->var.yres;
+ fr_h = fbi->var.yres;
+ base += fbi->fix.line_length * fbi->var.yres *
+ (fbi->var.yoffset / fbi->var.yres);
+ if (ipu_pixel_format_is_split_gpu_tile(fbi->var.nonstd))
+ base += (mxc_fbi->gpu_sec_buf_off -
+ fbi->fix.line_length * fbi->var.yres / 2) *
+ (fbi->var.yoffset / fbi->var.yres);
+ } else {
+ dev_dbg(fbi->device, "Y wrap enabled\n");
+ fr_yoff = fbi->var.yoffset;
+ fr_h = fbi->var.yres_virtual;
+ }
+
+ /* pixel block alignment for resolving cases */
+ if (mxc_fbi->resolve) {
+ fmt_to_tile_block(fbi->var.nonstd, &bw, &bh);
+ } else {
+ base += fr_yoff * fb_stride + fr_xoff *
+ bytes_per_pixel(fbi_to_pixfmt(fbi, true));
+ }
+
+ if (!mxc_fbi->on_the_fly)
+ mxc_fbi->cur_ipu_buf = 2;
+ init_completion(&mxc_fbi->flip_complete);
+ /*
+ * We don't need to wait for vsync at the first time
+ * we do pan display after fb is initialized, as IPU will
+ * switch to the newly selected buffer automatically,
+ * so we call complete() for both mxc_fbi->flip_complete
+ * and mxc_fbi->alpha_flip_complete.
+ */
+ if (!mxc_fbi->prefetch ||
+ (mxc_fbi->prefetch && !ipu_pre_yres_is_small(fbi->var.yres)))
+ complete(&mxc_fbi->flip_complete);
+ if (mxc_fbi->alpha_chan_en) {
+ mxc_fbi->cur_ipu_alpha_buf = 1;
+ init_completion(&mxc_fbi->alpha_flip_complete);
+ complete(&mxc_fbi->alpha_flip_complete);
+ }
+
+ if (mxc_fbi->prefetch) {
+ struct ipu_prg_config prg;
+ struct fb_var_screeninfo from_var, to_var;
+
+ if (mxc_fbi->pre_num < 0) {
+ mxc_fbi->pre_num = ipu_pre_alloc(mxc_fbi->ipu_id,
+ mxc_fbi->ipu_ch);
+ if (mxc_fbi->pre_num < 0) {
+ dev_dbg(fbi->device, "failed to alloc PRE\n");
+ mxc_fbi->prefetch = mxc_fbi->cur_prefetch;
+ mxc_fbi->resolve = false;
+ if (!mxc_fbi->on_the_fly)
+ mxc_fbi->cur_blank = FB_BLANK_POWERDOWN;
+ return mxc_fbi->pre_num;
+ }
+ }
+ pre.repeat = true;
+ pre.vflip = fbi->var.rotate ? true : false;
+ pre.handshake_en = true;
+ pre.hsk_abort_en = true;
+ pre.hsk_line_num = 0;
+ pre.sdw_update = true;
+ pre.cur_buf = base;
+ pre.next_buf = pre.cur_buf;
+ if (fbi->var.vmode & FB_VMODE_INTERLACED) {
+ pre.interlaced = 2;
+ if (mxc_fbi->resolve) {
+ pre.field_inverse = fbi->var.rotate;
+ pre.interlace_offset = 0;
+ } else {
+ pre.field_inverse = 0;
+ if (fbi->var.rotate) {
+ pre.interlace_offset = ~(fbi->var.xres_virtual *
+ bytes_per_pixel(fbi_to_pixfmt(fbi, true))) + 1;
+ pre.cur_buf += fbi->var.xres_virtual * bytes_per_pixel(fbi_to_pixfmt(fbi, true));
+ pre.next_buf = pre.cur_buf;
+ } else {
+ pre.interlace_offset = fbi->var.xres_virtual *
+ bytes_per_pixel(fbi_to_pixfmt(fbi, true));
+ }
+ }
+ } else {
+ pre.interlaced = 0;
+ pre.interlace_offset = 0;
+ }
+ pre.prefetch_mode = mxc_fbi->resolve ? 1 : 0;
+ pre.tile_fmt = mxc_fbi->resolve ? fbi->var.nonstd : 0;
+ pre.read_burst = mxc_fbi->resolve ? 0x4 : 0x3;
+ if (fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_RGB24 ||
+ fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_BGR24 ||
+ fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_YUV444) {
+ if ((fbi->var.xres * 3) % 8 == 0 &&
+ (fbi->var.xres_virtual * 3) % 8 == 0)
+ pre.prefetch_input_bpp = 64;
+ else if ((fbi->var.xres * 3) % 4 == 0 &&
+ (fbi->var.xres_virtual * 3) % 4 == 0)
+ pre.prefetch_input_bpp = 32;
+ else if ((fbi->var.xres * 3) % 2 == 0 &&
+ (fbi->var.xres_virtual * 3) % 2 == 0)
+ pre.prefetch_input_bpp = 16;
+ else
+ pre.prefetch_input_bpp = 8;
+ } else {
+ pre.prefetch_input_bpp =
+ 8 * bytes_per_pixel(fbi_to_pixfmt(fbi, true));
+ }
+ pre.prefetch_input_pixel_fmt = mxc_fbi->resolve ?
+ 0x1 : (fbi->var.nonstd ? fbi->var.nonstd : 0);
+ pre.shift_bypass = (mxc_fbi->on_the_fly &&
+ mxc_fbi->final_pfmt != fbi_to_pixfmt(fbi, false)) ?
+ false : true;
+ pixfmt_to_var(fbi_to_pixfmt(fbi, false), &from_var);
+ pixfmt_to_var(mxc_fbi->final_pfmt, &to_var);
+ if (mxc_fbi->on_the_fly &&
+ (format_to_colorspace(fbi_to_pixfmt(fbi, true)) == RGB) &&
+ (bytes_per_pixel(fbi_to_pixfmt(fbi, true)) == 4)) {
+ pre.prefetch_shift_offset = (from_var.red.offset << to_var.red.offset) |
+ (from_var.green.offset << to_var.green.offset) |
+ (from_var.blue.offset << to_var.blue.offset) |
+ (from_var.transp.offset << to_var.transp.offset);
+ pre.prefetch_shift_width = (to_var.red.length << (to_var.red.offset/2)) |
+ (to_var.green.length << (to_var.green.offset/2)) |
+ (to_var.blue.length << (to_var.blue.offset/2)) |
+ (to_var.transp.length << (to_var.transp.offset/2));
+ } else {
+ pre.prefetch_shift_offset = 0;
+ pre.prefetch_shift_width = 0;
+ }
+ pre.tpr_coor_offset_en = mxc_fbi->resolve ? true : false;
+ pre.prefetch_output_size.left = mxc_fbi->resolve ? (fr_xoff & ~(bw - 1)) : 0;
+ pre.prefetch_output_size.top = mxc_fbi->resolve ? (fr_yoff & ~(bh - 1)) : 0;
+ if (fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_RGB24 ||
+ fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_BGR24 ||
+ fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_YUV444) {
+ pre.prefetch_output_size.width = (fbi->var.xres * 3) /
+ (pre.prefetch_input_bpp / 8);
+ pre.store_output_bpp = pre.prefetch_input_bpp;
+ } else {
+ pre.prefetch_output_size.width = fbi->var.xres;
+ pre.store_output_bpp = 8 *
+ bytes_per_pixel(fbi_to_pixfmt(fbi, false));
+ }
+ pre.prefetch_output_size.height = fbi->var.yres;
+ pre.prefetch_input_active_width = pre.prefetch_output_size.width;
+ if (fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_RGB24 ||
+ fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_BGR24 ||
+ fbi_to_pixfmt(fbi, true) == IPU_PIX_FMT_YUV444)
+ pre.prefetch_input_width = (fbi->var.xres_virtual * 3) /
+ (pre.prefetch_input_bpp / 8);
+ else
+ pre.prefetch_input_width = fbi->var.xres_virtual;
+ pre.prefetch_input_height = fbi->var.yres;
+ prg_width = pre.prefetch_output_size.width;
+ if (!(pre.prefetch_input_active_width % 32))
+ pre.block_size = 0;
+ else if (!(pre.prefetch_input_active_width % 16))
+ pre.block_size = 1;
+ else
+ pre.block_size = 0;
+ if (mxc_fbi->resolve) {
+ int bs = pre.block_size ? 16 : 32;
+ pre.prefetch_input_active_width += fr_xoff % bw;
+ if (((fr_xoff % bw) + pre.prefetch_input_active_width) % bs)
+ pre.prefetch_input_active_width =
+ ALIGN(pre.prefetch_input_active_width, bs);
+ pre.prefetch_output_size.width =
+ pre.prefetch_input_active_width;
+ prg_width = pre.prefetch_output_size.width;
+ pre.prefetch_input_height += fr_yoff % bh;
+ if (((fr_yoff % bh) + fbi->var.yres) % 4) {
+ pre.prefetch_input_height =
+ (fbi->var.vmode & FB_VMODE_INTERLACED) ?
+ ALIGN(pre.prefetch_input_height, 8) :
+ ALIGN(pre.prefetch_input_height, 4);
+ } else {
+ if (fbi->var.vmode & FB_VMODE_INTERLACED)
+ pre.prefetch_input_height =
+ ALIGN(pre.prefetch_input_height, 8);
+ }
+ pre.prefetch_output_size.height = pre.prefetch_input_height;
+ }
+
+ /* store output pitch 8-byte aligned */
+ while ((pre.store_output_bpp * prg_width) % 64)
+ prg_width++;
+
+ pre.store_pitch = (pre.store_output_bpp * prg_width) / 8;
+
+ pre.store_en = true;
+ pre.write_burst = 0x3;
+ ipu_get_channel_offset(fbi_to_pixfmt(fbi, true),
+ fbi->var.xres,
+ fr_h,
+ fr_w,
+ 0, 0,
+ fr_yoff,
+ fr_xoff,
+ &pre.sec_buf_off,
+ &pre.trd_buf_off);
+ if (mxc_fbi->resolve)
+ pre.sec_buf_off = mxc_fbi->gpu_sec_buf_off;
+
+ ipu_pre_config(mxc_fbi->pre_num, &pre);
+ ipu_stride = pre.store_pitch;
+ ipu_base = pre.store_addr;
+ mxc_fbi->store_addr = ipu_base;
+
+ if (mxc_fbi->cur_prefetch && mxc_fbi->on_the_fly) {
+ /*
+ * Make sure any pending interrupt is handled so that
+ * the buffer panned can start to be scanned out.
+ */
+ if (!ipu_pre_yres_is_small(fbi->var.yres)) {
+ mxcfb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC,
+ (unsigned long)fbi->par);
+ mxcfb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC,
+ (unsigned long)fbi->par);
+ }
+
+ mxc_fbi->pre_config = &pre;
+
+ /*
+ * Write the PRE control register in the flip interrupt
+ * handler in this on-the-fly case to workaround the
+ * SoC design bug recorded by errata ERR009624.
+ */
+ init_completion(&mxc_fbi->otf_complete);
+ ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+ ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+ retval = wait_for_completion_timeout(
+ &mxc_fbi->otf_complete, HZ/2);
+ if (retval == 0) {
+ dev_err(fbi->device, "timeout when waiting "
+ "for on the fly config irq\n");
+ return -ETIMEDOUT;
+ } else {
+ retval = 0;
+ }
+ } else {
+ retval = ipu_pre_set_ctrl(mxc_fbi->pre_num, &pre);
+ if (retval < 0)
+ return retval;
+ }
+
+ if (!mxc_fbi->on_the_fly || !mxc_fbi->cur_prefetch) {
+ prg.id = mxc_fbi->ipu_id;
+ prg.pre_num = mxc_fbi->pre_num;
+ prg.ipu_ch = mxc_fbi->ipu_ch;
+ prg.so = (fbi->var.vmode & FB_VMODE_INTERLACED) ?
+ PRG_SO_INTERLACE : PRG_SO_PROGRESSIVE;
+ prg.vflip = fbi->var.rotate ? true : false;
+ prg.block_mode = mxc_fbi->resolve ? PRG_BLOCK_MODE : PRG_SCAN_MODE;
+ prg.stride = (fbi->var.vmode & FB_VMODE_INTERLACED) ?
+ ipu_stride * 2 : ipu_stride;
+ prg.ilo = (fbi->var.vmode & FB_VMODE_INTERLACED) ?
+ ipu_stride : 0;
+ prg.height = mxc_fbi->resolve ?
+ pre.prefetch_output_size.height : fbi->var.yres;
+ prg.ipu_height = fbi->var.yres;
+ prg.crop_line = mxc_fbi->resolve ?
+ ((fbi->var.vmode & FB_VMODE_INTERLACED) ? (fr_yoff % bh) / 2 : fr_yoff % bh) : 0;
+ prg.baddr = pre.store_addr;
+ prg.offset = mxc_fbi->resolve ? (prg.crop_line * prg.stride +
+ (fr_xoff % bw) *
+ bytes_per_pixel(fbi_to_pixfmt(fbi, false))) : 0;
+ ipu_base += prg.offset;
+ if (ipu_base % 8) {
+ dev_err(fbi->device,
+ "IPU base address is not 8byte aligned\n");
+ return -EINVAL;
+ }
+ mxc_fbi->store_addr = ipu_base;
+
+ if (!mxc_fbi->on_the_fly) {
+ retval = ipu_init_channel_buffer(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
+ fbi_to_pixfmt(fbi, false),
+ fbi->var.xres, fbi->var.yres,
+ ipu_stride,
+ fbi->var.rotate,
+ ipu_base,
+ ipu_base,
+ fbi->var.accel_flags &
+ FB_ACCEL_DOUBLE_FLAG ? 0 : ipu_base,
+ 0, 0);
+ if (retval) {
+ dev_err(fbi->device,
+ "ipu_init_channel_buffer error %d\n", retval);
+ return retval;
+ }
+ }
+
+ retval = ipu_prg_config(&prg);
+ if (retval < 0) {
+ dev_err(fbi->device,
+ "failed to configure PRG %d\n", retval);
+ return retval;
+ }
+
+ retval = ipu_pre_enable(mxc_fbi->pre_num);
+ if (retval < 0) {
+ ipu_prg_disable(mxc_fbi->ipu_id, mxc_fbi->pre_num);
+ dev_err(fbi->device,
+ "failed to enable PRE %d\n", retval);
+ return retval;
+ }
+
+ retval = ipu_prg_wait_buf_ready(mxc_fbi->ipu_id,
+ mxc_fbi->pre_num,
+ pre.hsk_line_num,
+ pre.prefetch_output_size.height);
+ if (retval < 0) {
+ ipu_prg_disable(mxc_fbi->ipu_id, mxc_fbi->pre_num);
+ ipu_pre_disable(mxc_fbi->pre_num);
+ ipu_pre_free(&mxc_fbi->pre_num);
+ dev_err(fbi->device, "failed to wait PRG ready %d\n", retval);
+ return retval;
+ }
+ }
+ } else {
+ ipu_stride = fb_stride;
+ ipu_base = base;
+ if (mxc_fbi->on_the_fly)
+ post_pre_disable = true;
+ }
+
+ if (mxc_fbi->on_the_fly && ((mxc_fbi->cur_prefetch && !mxc_fbi->prefetch) ||
+ (!mxc_fbi->cur_prefetch && mxc_fbi->prefetch))) {
+ int htotal = fbi->var.xres + fbi->var.right_margin +
+ fbi->var.hsync_len + fbi->var.left_margin;
+ int vtotal = fbi->var.yres + fbi->var.lower_margin +
+ fbi->var.vsync_len + fbi->var.upper_margin;
+ int timeout = ((htotal * vtotal) / PICOS2KHZ(fbi->var.pixclock)) * 2 ;
+ int cur_buf = 0;
+
+ BUG_ON(timeout <= 0);
+
+ ++mxc_fbi->cur_ipu_buf;
+ mxc_fbi->cur_ipu_buf %= 3;
+ if (ipu_update_channel_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER,
+ mxc_fbi->cur_ipu_buf,
+ ipu_base) == 0) {
+ if (!mxc_fbi->prefetch)
+ ipu_update_channel_offset(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER,
+ fbi_to_pixfmt(fbi, true),
+ fr_w,
+ fr_h,
+ fr_w,
+ 0, 0,
+ fr_yoff,
+ fr_xoff);
+ ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, mxc_fbi->cur_ipu_buf);
+ for (; timeout > 0; timeout--) {
+ cur_buf = ipu_get_cur_buffer_idx(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER);
+ if (cur_buf == mxc_fbi->cur_ipu_buf)
+ break;
+
+ udelay(1000);
+ }
+ if (!timeout)
+ dev_err(fbi->device, "Timeout for switch to buf %d "
+ "to address=0x%08lX, current buf %d, "
+ "buf0 ready %d, buf1 ready %d, buf2 ready "
+ "%d\n", mxc_fbi->cur_ipu_buf, ipu_base,
+ ipu_get_cur_buffer_idx(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER),
+ ipu_check_buffer_ready(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 0),
+ ipu_check_buffer_ready(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 1),
+ ipu_check_buffer_ready(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 2));
+ }
+ } else if (!mxc_fbi->on_the_fly && !mxc_fbi->prefetch) {
+ retval = ipu_init_channel_buffer(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
+ mxc_fbi->on_the_fly ? mxc_fbi->final_pfmt :
+ fbi_to_pixfmt(fbi, false),
+ fbi->var.xres, fbi->var.yres,
+ ipu_stride,
+ fbi->var.rotate,
+ ipu_base,
+ ipu_base,
+ fbi->var.accel_flags &
+ FB_ACCEL_DOUBLE_FLAG ? 0 : ipu_base,
+ 0, 0);
+ if (retval) {
+ dev_err(fbi->device,
+ "ipu_init_channel_buffer error %d\n", retval);
+ return retval;
+ }
+ /* update u/v offset */
+ if (!mxc_fbi->prefetch)
+ ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER,
+ fbi_to_pixfmt(fbi, true),
+ fr_w,
+ fr_h,
+ fr_w,
+ 0, 0,
+ fr_yoff,
+ fr_xoff);
+ }
+
+ if (post_pre_disable) {
+ ipu_prg_disable(mxc_fbi->ipu_id, mxc_fbi->pre_num);
+ ipu_pre_disable(mxc_fbi->pre_num);
+ ipu_pre_free(&mxc_fbi->pre_num);
+ }
+
+ if (mxc_fbi->alpha_chan_en) {
+ retval = ipu_init_channel_buffer(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ IPU_ALPHA_IN_BUFFER,
+ IPU_PIX_FMT_GENERIC,
+ fbi->var.xres, fbi->var.yres,
+ fbi->var.xres,
+ fbi->var.rotate,
+ mxc_fbi->alpha_phy_addr1,
+ mxc_fbi->alpha_phy_addr0,
+ 0,
+ 0, 0);
+ if (retval) {
+ dev_err(fbi->device,
+ "ipu_init_channel_buffer error %d\n", retval);
+ return retval;
+ }
+ }
+
+ return retval;
+}
+
+static bool mxcfb_need_to_set_par(struct fb_info *fbi)
+{
+ struct mxcfb_info *mxc_fbi = fbi->par;
+
+ if ((fbi->var.activate & FB_ACTIVATE_FORCE) &&
+ (fbi->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+ return true;
+
+ /*
+ * Ignore xoffset and yoffset update,
+ * because pan display handles this case.
+ */
+ mxc_fbi->cur_var.xoffset = fbi->var.xoffset;
+ mxc_fbi->cur_var.yoffset = fbi->var.yoffset;
+
+ return !!memcmp(&mxc_fbi->cur_var, &fbi->var,
+ sizeof(struct fb_var_screeninfo));
+}
+
+static bool mxcfb_can_set_par_on_the_fly(struct fb_info *fbi,
+ uint32_t *final_pfmt)
+{
+ struct mxcfb_info *mxc_fbi = fbi->par;
+ struct fb_var_screeninfo cur_var = mxc_fbi->cur_var;
+ uint32_t cur_pfmt = mxc_fbi->cur_ipu_pfmt;
+ uint32_t new_pfmt = fbi_to_pixfmt(fbi, false);
+ uint32_t new_fb_pfmt = fbi_to_pixfmt(fbi, true);
+ int cur_bpp, new_bpp, cur_bw, cur_bh, new_bw, new_bh;
+ unsigned int mem_len;
+ ipu_color_space_t cur_space, new_space;
+
+ cur_space = format_to_colorspace(cur_pfmt);
+ new_space = format_to_colorspace(new_pfmt);
+
+ cur_bpp = bytes_per_pixel(cur_pfmt);
+ new_bpp = bytes_per_pixel(new_pfmt);
+
+ if (mxc_fbi->first_set_par || mxc_fbi->cur_blank != FB_BLANK_UNBLANK)
+ return false;
+
+ if (!mxc_fbi->prefetch && !mxc_fbi->cur_prefetch)
+ return false;
+
+ if (!mxc_fbi->prefetch && cur_pfmt != new_pfmt)
+ return false;
+
+ if (cur_space == RGB && (cur_bpp == 2 || cur_bpp == 3) &&
+ cur_pfmt != new_pfmt)
+ return false;
+
+ if (!(mxc_fbi->cur_prefetch && mxc_fbi->prefetch) &&
+ ((cur_var.xres_virtual != fbi->var.xres_virtual) ||
+ (cur_var.xres != cur_var.xres_virtual) ||
+ (fbi->var.xres != fbi->var.xres_virtual)))
+ return false;
+
+ if (cur_space != new_space ||
+ (new_space == RGB && cur_bpp != new_bpp))
+ return false;
+
+ if (new_space == YCbCr)
+ return false;
+
+ mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
+ if (mxc_fbi->resolve && mxc_fbi->gpu_sec_buf_off) {
+ if (fbi->var.vmode & FB_VMODE_YWRAP)
+ mem_len = mxc_fbi->gpu_sec_buf_off + mem_len / 2;
+ else
+ mem_len = mxc_fbi->gpu_sec_buf_off *
+ (fbi->var.yres_virtual / fbi->var.yres) + mem_len / 2;
+ }
+ if (mem_len > fbi->fix.smem_len)
+ return false;
+
+ if (mxc_fbi->resolve && ipu_pixel_format_is_gpu_tile(mxc_fbi->cur_fb_pfmt)) {
+ fmt_to_tile_block(mxc_fbi->cur_fb_pfmt, &cur_bw, &cur_bh);
+ fmt_to_tile_block(new_fb_pfmt, &new_bw, &new_bh);
+
+ if (cur_bw != new_bw || cur_bh != new_bh ||
+ cur_var.xoffset % cur_bw != fbi->var.xoffset % new_bw ||
+ cur_var.yoffset % cur_bh != fbi->var.yoffset % new_bh)
+ return false;
+ } else if (mxc_fbi->resolve && mxc_fbi->cur_prefetch) {
+ fmt_to_tile_block(new_fb_pfmt, &new_bw, &new_bh);
+ if (fbi->var.xoffset % new_bw || fbi->var.yoffset % new_bh ||
+ fbi->var.xres % 16 || fbi->var.yres %
+ (fbi->var.vmode & FB_VMODE_INTERLACED ? 8 : 4))
+ return false;
+ } else if (mxc_fbi->prefetch && ipu_pixel_format_is_gpu_tile(mxc_fbi->cur_fb_pfmt)) {
+ fmt_to_tile_block(mxc_fbi->cur_fb_pfmt, &cur_bw, &cur_bh);
+ if (cur_var.xoffset % cur_bw || cur_var.yoffset % cur_bh ||
+ cur_var.xres % 16 || cur_var.yres %
+ (cur_var.vmode & FB_VMODE_INTERLACED ? 8 : 4))
+ return false;
+ }
+
+ cur_var.xres_virtual = fbi->var.xres_virtual;
+ cur_var.yres_virtual = fbi->var.yres_virtual;
+ cur_var.xoffset = fbi->var.xoffset;
+ cur_var.yoffset = fbi->var.yoffset;
+ cur_var.red = fbi->var.red;
+ cur_var.green = fbi->var.green;
+ cur_var.blue = fbi->var.blue;
+ cur_var.transp = fbi->var.transp;
+ cur_var.nonstd = fbi->var.nonstd;
+ if (memcmp(&cur_var, &fbi->var,
+ sizeof(struct fb_var_screeninfo)))
+ return false;
+
+ *final_pfmt = cur_pfmt;
+
+ return true;
+}
+
+static void mxcfb_check_resolve(struct fb_info *fbi)
+{
+ struct mxcfb_info *mxc_fbi = fbi->par;
+
+ switch (fbi->var.nonstd) {
+ case IPU_PIX_FMT_GPU32_ST:
+ case IPU_PIX_FMT_GPU32_SRT:
+ case IPU_PIX_FMT_GPU16_ST:
+ case IPU_PIX_FMT_GPU16_SRT:
+ mxc_fbi->gpu_sec_buf_off = 0;
+ case IPU_PIX_FMT_GPU32_SB_ST:
+ case IPU_PIX_FMT_GPU32_SB_SRT:
+ case IPU_PIX_FMT_GPU16_SB_ST:
+ case IPU_PIX_FMT_GPU16_SB_SRT:
+ mxc_fbi->prefetch = true;
+ mxc_fbi->resolve = true;
+ break;
+ default:
+ mxc_fbi->resolve = false;
+ }
+}
+
+static void mxcfb_check_yuv(struct fb_info *fbi)
+{
+ struct mxcfb_info *mxc_fbi = fbi->par;
+
+ if (fbi->var.vmode & FB_VMODE_INTERLACED) {
+ if (ipu_pixel_format_is_multiplanar_yuv(fbi_to_pixfmt(fbi, true)))
+ mxc_fbi->prefetch = false;
+ } else {
+ if (fbi->var.nonstd == PRE_PIX_FMT_NV21 ||
+ fbi->var.nonstd == PRE_PIX_FMT_NV61)
+ mxc_fbi->prefetch = true;
+ }
+}
+
+/*
+ * Set framebuffer parameters and change the operating mode.
+ *
+ * @param info framebuffer information pointer
+ */
+static int mxcfb_set_par(struct fb_info *fbi)
+{
+ int retval = 0;
+ u32 mem_len, alpha_mem_len;
+ ipu_di_signal_cfg_t sig_cfg;
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+ uint32_t final_pfmt = 0;
+ int16_t ov_pos_x = 0, ov_pos_y = 0;
+ int ov_pos_ret = 0;
+ struct mxcfb_info *mxc_fbi_fg = NULL;
+ bool ovfbi_enable = false, on_the_fly;
+
+ if (ipu_ch_param_bad_alpha_pos(fbi_to_pixfmt(fbi, true)) &&
+ mxc_fbi->alpha_chan_en) {
+ dev_err(fbi->device, "Bad pixel format for "
+ "graphics plane fb\n");
+ return -EINVAL;
+ }
+
+ if (mxc_fbi->ovfbi)
+ mxc_fbi_fg = (struct mxcfb_info *)mxc_fbi->ovfbi->par;
+
+ if (mxc_fbi->ovfbi && mxc_fbi_fg)
+ if (mxc_fbi_fg->next_blank == FB_BLANK_UNBLANK)
+ ovfbi_enable = true;
+
+ if (!mxcfb_need_to_set_par(fbi))
+ return 0;
+
+ dev_dbg(fbi->device, "Reconfiguring framebuffer\n");
+
+ if (fbi->var.xres == 0 || fbi->var.yres == 0)
+ return 0;
+
+ mxcfb_set_fix(fbi);
+
+ mxcfb_check_resolve(fbi);
+
+ mxcfb_check_yuv(fbi);
+
+ on_the_fly = mxcfb_can_set_par_on_the_fly(fbi, &final_pfmt);
+ mxc_fbi->on_the_fly = on_the_fly;
+ mxc_fbi->final_pfmt = final_pfmt;
+
+ if (on_the_fly)
+ dev_dbg(fbi->device, "Reconfiguring framebuffer on the fly\n");
+
+ if (ovfbi_enable) {
+ ov_pos_ret = ipu_disp_get_window_pos(
+ mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch,
+ &ov_pos_x, &ov_pos_y);
+ if (ov_pos_ret < 0)
+ dev_err(fbi->device, "Get overlay pos failed, dispdrv:%s.\n",
+ mxc_fbi->dispdrv->drv->name);
+
+ if (!on_the_fly) {
+ ipu_clear_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_irq);
+ ipu_disable_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_irq);
+ ipu_clear_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_nf_irq);
+ ipu_disable_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_nf_irq);
+ ipu_disable_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch, true);
+ ipu_uninit_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
+ if (mxc_fbi_fg->cur_prefetch) {
+ ipu_prg_disable(mxc_fbi_fg->ipu_id, mxc_fbi_fg->pre_num);
+ ipu_pre_disable(mxc_fbi_fg->pre_num);
+ ipu_pre_free(&mxc_fbi_fg->pre_num);
+ }
+ }
+ }
+
+ if (!on_the_fly) {
+ ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+ ipu_disable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+ ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
+ ipu_disable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
+ ipu_disable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, true);
+ ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
+ if (mxc_fbi->cur_prefetch) {
+ ipu_prg_disable(mxc_fbi->ipu_id, mxc_fbi->pre_num);
+ ipu_pre_disable(mxc_fbi->pre_num);
+ ipu_pre_free(&mxc_fbi->pre_num);
+ }
+ }
+
+ /*
+ * Disable IPU hsp clock if it is enabled for an
+ * additional time in ipu common driver.
+ */
+ if (mxc_fbi->first_set_par && mxc_fbi->late_init)
+ ipu_disable_hsp_clk(mxc_fbi->ipu);
+
+ mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
+ if (mxc_fbi->resolve && mxc_fbi->gpu_sec_buf_off) {
+ if (fbi->var.vmode & FB_VMODE_YWRAP)
+ mem_len = mxc_fbi->gpu_sec_buf_off + mem_len / 2;
+ else
+ mem_len = mxc_fbi->gpu_sec_buf_off *
+ (fbi->var.yres_virtual / fbi->var.yres) + mem_len / 2;
+ }
+ if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) {
+ if (fbi->fix.smem_start)
+ mxcfb_unmap_video_memory(fbi);
+
+ if (mxcfb_map_video_memory(fbi) < 0)
+ return -ENOMEM;
+ }
+
+ if (mxc_fbi->first_set_par) {
+ /*
+ * Clear the screen in case uboot fb pixel format is not
+ * the same to kernel fb pixel format.
+ */
+ if (mxc_fbi->late_init)
+ memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
+
+ mxc_fbi->first_set_par = false;
+ }
+
+ if (mxc_fbi->alpha_chan_en) {
+ alpha_mem_len = fbi->var.xres * fbi->var.yres;
+ if ((!mxc_fbi->alpha_phy_addr0 && !mxc_fbi->alpha_phy_addr1) ||
+ (alpha_mem_len > mxc_fbi->alpha_mem_len)) {
+ if (mxc_fbi->alpha_phy_addr0)
+ dma_free_coherent(fbi->device,
+ mxc_fbi->alpha_mem_len,
+ mxc_fbi->alpha_virt_addr0,
+ mxc_fbi->alpha_phy_addr0);
+ if (mxc_fbi->alpha_phy_addr1)
+ dma_free_coherent(fbi->device,
+ mxc_fbi->alpha_mem_len,
+ mxc_fbi->alpha_virt_addr1,
+ mxc_fbi->alpha_phy_addr1);
+
+ mxc_fbi->alpha_virt_addr0 =
+ dma_alloc_coherent(fbi->device,
+ alpha_mem_len,
+ &mxc_fbi->alpha_phy_addr0,
+ GFP_DMA | GFP_KERNEL);
+
+ mxc_fbi->alpha_virt_addr1 =
+ dma_alloc_coherent(fbi->device,
+ alpha_mem_len,
+ &mxc_fbi->alpha_phy_addr1,
+ GFP_DMA | GFP_KERNEL);
+ if (mxc_fbi->alpha_virt_addr0 == NULL ||
+ mxc_fbi->alpha_virt_addr1 == NULL) {
+ dev_err(fbi->device, "mxcfb: dma alloc for"
+ " alpha buffer failed.\n");
+ if (mxc_fbi->alpha_virt_addr0)
+ dma_free_coherent(fbi->device,
+ mxc_fbi->alpha_mem_len,
+ mxc_fbi->alpha_virt_addr0,
+ mxc_fbi->alpha_phy_addr0);
+ if (mxc_fbi->alpha_virt_addr1)
+ dma_free_coherent(fbi->device,
+ mxc_fbi->alpha_mem_len,
+ mxc_fbi->alpha_virt_addr1,
+ mxc_fbi->alpha_phy_addr1);
+ return -ENOMEM;
+ }
+ mxc_fbi->alpha_mem_len = alpha_mem_len;
+ }
+ }
+
+ if (mxc_fbi->next_blank != FB_BLANK_UNBLANK)
+ return retval;
+
+ if (!on_the_fly && mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->setup) {
+ retval = mxc_fbi->dispdrv->drv->setup(mxc_fbi->dispdrv, fbi);
+ if (retval < 0) {
+ dev_err(fbi->device, "setup error, dispdrv:%s.\n",
+ mxc_fbi->dispdrv->drv->name);
+ return -EINVAL;
+ }
+ }
+
+ if (!on_the_fly) {
+ _setup_disp_channel1(fbi);
+ if (ovfbi_enable)
+ _setup_disp_channel1(mxc_fbi->ovfbi);
+ }
+
+ if (!mxc_fbi->overlay && !on_the_fly) {
+ uint32_t out_pixel_fmt;
+
+ memset(&sig_cfg, 0, sizeof(sig_cfg));
+ if (fbi->var.vmode & FB_VMODE_INTERLACED)
+ sig_cfg.interlaced = true;
+ out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
+ if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */
+ sig_cfg.odd_field_first = true;
+ if (mxc_fbi->ipu_int_clk)
+ sig_cfg.int_clk = true;
+ if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ sig_cfg.Hsync_pol = true;
+ if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ sig_cfg.Vsync_pol = true;
+ if (!(fbi->var.sync & FB_SYNC_CLK_LAT_FALL))
+ sig_cfg.clk_pol = true;
+ if (fbi->var.sync & FB_SYNC_DATA_INVERT)
+ sig_cfg.data_pol = true;
+ if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT))
+ sig_cfg.enable_pol = true;
+ if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
+ sig_cfg.clkidle_en = true;
+
+ dev_dbg(fbi->device, "pixclock = %ul Hz\n",
+ (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
+
+ if (ipu_init_sync_panel(mxc_fbi->ipu, mxc_fbi->ipu_di,
+ (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
+ fbi->var.xres, fbi->var.yres,
+ out_pixel_fmt,
+ fbi->var.left_margin,
+ fbi->var.hsync_len,
+ fbi->var.right_margin,
+ fbi->var.upper_margin,
+ fbi->var.vsync_len,
+ fbi->var.lower_margin,
+ 0, sig_cfg) != 0) {
+ dev_err(fbi->device,
+ "mxcfb: Error initializing panel.\n");
+ return -EINVAL;
+ }
+
+ fbi->mode =
+ (struct fb_videomode *)fb_match_mode(&fbi->var,
+ &fbi->modelist);
+
+ ipu_disp_set_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch, 0, 0);
+ }
+
+ retval = _setup_disp_channel2(fbi);
+ if (retval) {
+ if (!on_the_fly)
+ ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
+ return retval;
+ }
+
+ if (ovfbi_enable && !on_the_fly) {
+ if (ov_pos_ret >= 0)
+ ipu_disp_set_window_pos(
+ mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch,
+ ov_pos_x, ov_pos_y);
+ retval = _setup_disp_channel2(mxc_fbi->ovfbi);
+ if (retval) {
+ ipu_uninit_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
+ ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
+ return retval;
+ }
+ }
+
+ if (!on_the_fly) {
+ ipu_enable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
+ if (ovfbi_enable)
+ ipu_enable_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
+ }
+
+ if (!on_the_fly && mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->enable) {
+ retval = mxc_fbi->dispdrv->drv->enable(mxc_fbi->dispdrv, fbi);
+ if (retval < 0) {
+ dev_err(fbi->device, "enable error, dispdrv:%s.\n",
+ mxc_fbi->dispdrv->drv->name);
+ return -EINVAL;
+ }
+ }
+
+ mxc_fbi->cur_var = fbi->var;
+ mxc_fbi->cur_ipu_pfmt = on_the_fly ? mxc_fbi->final_pfmt :
+ fbi_to_pixfmt(fbi, false);
+ mxc_fbi->cur_fb_pfmt = fbi_to_pixfmt(fbi, true);
+ mxc_fbi->cur_prefetch = mxc_fbi->prefetch;
+
+ return retval;
+}
+
+static int _swap_channels(struct fb_info *fbi_from,
+ struct fb_info *fbi_to, bool both_on)
+{
+ int retval, tmp;
+ ipu_channel_t old_ch;
+ struct fb_info *ovfbi;
+ struct mxcfb_info *mxc_fbi_from = (struct mxcfb_info *)fbi_from->par;
+ struct mxcfb_info *mxc_fbi_to = (struct mxcfb_info *)fbi_to->par;
+
+ if (both_on) {
+ ipu_disable_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch, true);
+ ipu_uninit_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch);
+ }
+
+ /* switch the mxc fbi parameters */
+ old_ch = mxc_fbi_from->ipu_ch;
+ mxc_fbi_from->ipu_ch = mxc_fbi_to->ipu_ch;
+ mxc_fbi_to->ipu_ch = old_ch;
+ tmp = mxc_fbi_from->ipu_ch_irq;
+ mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
+ mxc_fbi_to->ipu_ch_irq = tmp;
+ tmp = mxc_fbi_from->ipu_ch_nf_irq;
+ mxc_fbi_from->ipu_ch_nf_irq = mxc_fbi_to->ipu_ch_nf_irq;
+ mxc_fbi_to->ipu_ch_nf_irq = tmp;
+ ovfbi = mxc_fbi_from->ovfbi;
+ mxc_fbi_from->ovfbi = mxc_fbi_to->ovfbi;
+ mxc_fbi_to->ovfbi = ovfbi;
+
+ _setup_disp_channel1(fbi_from);
+ retval = _setup_disp_channel2(fbi_from);
+ if (retval)
+ return retval;
+
+ /* switch between dp and dc, disable old idmac, enable new idmac */
+ retval = ipu_swap_channel(mxc_fbi_from->ipu, old_ch, mxc_fbi_from->ipu_ch);
+ ipu_uninit_channel(mxc_fbi_from->ipu, old_ch);
+
+ if (both_on) {
+ _setup_disp_channel1(fbi_to);
+ retval = _setup_disp_channel2(fbi_to);
+ if (retval)
+ return retval;
+ ipu_enable_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch);
+ }
+
+ return retval;
+}
+
+static int swap_channels(struct fb_info *fbi_from)
+{
+ int i;
+ int swap_mode;
+ ipu_channel_t ch_to;
+ struct mxcfb_info *mxc_fbi_from = (struct mxcfb_info *)fbi_from->par;
+ struct fb_info *fbi_to = NULL;
+ struct mxcfb_info *mxc_fbi_to;
+
+ /* what's the target channel? */
+ if (mxc_fbi_from->ipu_ch == MEM_BG_SYNC)
+ ch_to = MEM_DC_SYNC;
+ else
+ ch_to = MEM_BG_SYNC;
+
+ fbi_to = found_registered_fb(ch_to, mxc_fbi_from->ipu_id);
+ if (!fbi_to)
+ return -1;
+ mxc_fbi_to = (struct mxcfb_info *)fbi_to->par;
+
+ ipu_clear_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq);
+ ipu_clear_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq);
+ ipu_free_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq, fbi_from);
+ ipu_free_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq, fbi_to);
+ ipu_clear_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq);
+ ipu_clear_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq);
+ ipu_free_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq, fbi_from);
+ ipu_free_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq, fbi_to);
+
+ if (mxc_fbi_from->cur_blank == FB_BLANK_UNBLANK) {
+ if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
+ swap_mode = BOTH_ON;
+ else
+ swap_mode = SRC_ON;
+ } else {
+ if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
+ swap_mode = TGT_ON;
+ else
+ swap_mode = BOTH_OFF;
+ }
+
+ switch (swap_mode) {
+ case BOTH_ON:
+ /* disable target->switch src->enable target */
+ _swap_channels(fbi_from, fbi_to, true);
+ break;
+ case SRC_ON:
+ /* just switch src */
+ _swap_channels(fbi_from, fbi_to, false);
+ break;
+ case TGT_ON:
+ /* just switch target */
+ _swap_channels(fbi_to, fbi_from, false);
+ break;
+ case BOTH_OFF:
+ /* switch directly, no more need to do */
+ mxc_fbi_to->ipu_ch = mxc_fbi_from->ipu_ch;
+ mxc_fbi_from->ipu_ch = ch_to;
+ i = mxc_fbi_from->ipu_ch_irq;
+ mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
+ mxc_fbi_to->ipu_ch_irq = i;
+ i = mxc_fbi_from->ipu_ch_nf_irq;
+ mxc_fbi_from->ipu_ch_nf_irq = mxc_fbi_to->ipu_ch_nf_irq;
+ mxc_fbi_to->ipu_ch_nf_irq = i;
+ break;
+ default:
+ break;
+ }
+
+ if (ipu_request_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq,
+ mxcfb_irq_handler, IPU_IRQF_ONESHOT,
+ MXCFB_NAME, fbi_from) != 0) {
+ dev_err(fbi_from->device, "Error registering irq %d\n",
+ mxc_fbi_from->ipu_ch_irq);
+ return -EBUSY;
+ }
+ ipu_disable_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq);
+ if (ipu_request_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq,
+ mxcfb_irq_handler, IPU_IRQF_ONESHOT,
+ MXCFB_NAME, fbi_to) != 0) {
+ dev_err(fbi_to->device, "Error registering irq %d\n",
+ mxc_fbi_to->ipu_ch_irq);
+ return -EBUSY;
+ }
+ ipu_disable_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq);
+ if (ipu_request_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq,
+ mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT,
+ MXCFB_NAME, fbi_from) != 0) {
+ dev_err(fbi_from->device, "Error registering irq %d\n",
+ mxc_fbi_from->ipu_ch_nf_irq);
+ return -EBUSY;
+ }
+ ipu_disable_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq);
+ if (ipu_request_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq,
+ mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT,
+ MXCFB_NAME, fbi_to) != 0) {
+ dev_err(fbi_to->device, "Error registering irq %d\n",
+ mxc_fbi_to->ipu_ch_nf_irq);
+ return -EBUSY;
+ }
+ ipu_disable_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq);
+
+ return 0;
+}
+
+/*
+ * Check framebuffer variable parameters and adjust to valid values.
+ *
+ * @param var framebuffer variable parameters
+ *
+ * @param info framebuffer information pointer
+ */
+static int mxcfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ u32 vtotal;
+ u32 htotal;
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par;
+ struct fb_info tmp_fbi;
+ unsigned int fr_xoff, fr_yoff, fr_w, fr_h, line_length;
+ unsigned long base = 0;
+ int ret, bw = 0, bh = 0;
+ bool triple_buffer = false;
+
+ if (var->xres == 0 || var->yres == 0)
+ return 0;
+
+ /* fg should not bigger than bg */
+ if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
+ struct fb_info *fbi_tmp;
+ int bg_xres = 0, bg_yres = 0;
+ int16_t pos_x, pos_y;
+
+ bg_xres = var->xres;
+ bg_yres = var->yres;
+
+ fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
+ if (!fbi_tmp) {
+ dev_err(info->device,
+ "cannot find background fb for overlay fb\n");
+ return -EINVAL;
+ }
+
+ bg_xres = fbi_tmp->var.xres;
+ bg_yres = fbi_tmp->var.yres;
+
+ ipu_disp_get_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch, &pos_x, &pos_y);
+
+ if ((var->xres + pos_x) > bg_xres)
+ var->xres = bg_xres - pos_x;
+ if ((var->yres + pos_y) > bg_yres)
+ var->yres = bg_yres - pos_y;
+
+ if (fbi_tmp->var.vmode & FB_VMODE_INTERLACED)
+ var->vmode |= FB_VMODE_INTERLACED;
+ else
+ var->vmode &= ~FB_VMODE_INTERLACED;
+
+ var->pixclock = fbi_tmp->var.pixclock;
+ var->right_margin = fbi_tmp->var.right_margin;
+ var->hsync_len = fbi_tmp->var.hsync_len;
+ var->left_margin = fbi_tmp->var.left_margin +
+ fbi_tmp->var.xres - var->xres;
+ var->upper_margin = fbi_tmp->var.upper_margin;
+ var->vsync_len = fbi_tmp->var.vsync_len;
+ var->lower_margin = fbi_tmp->var.lower_margin +
+ fbi_tmp->var.yres - var->yres;
+ }
+
+ if (var->rotate > IPU_ROTATE_VERT_FLIP)
+ var->rotate = IPU_ROTATE_NONE;
+
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+
+ if (var->yres_virtual < var->yres) {
+ var->yres_virtual = var->yres * 3;
+ triple_buffer = true;
+ }
+
+ if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
+ (var->bits_per_pixel != 16) && (var->bits_per_pixel != 12) &&
+ (var->bits_per_pixel != 8))
+ var->bits_per_pixel = 16;
+
+ if (check_var_pixfmt(var)) {
+ /* Fall back to default */
+ ret = bpp_to_var(var->bits_per_pixel, var);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (ipu_pixel_format_is_gpu_tile(var->nonstd)) {
+ fmt_to_tile_alignment(var->nonstd, &bw, &bh);
+ var->xres_virtual = ALIGN(var->xres_virtual, bw);
+ if (triple_buffer)
+ var->yres_virtual = 3 * ALIGN(var->yres, bh);
+ else
+ var->yres_virtual = ALIGN(var->yres_virtual, bh);
+ }
+
+ line_length = var->xres_virtual * var->bits_per_pixel / 8;
+ fr_xoff = var->xoffset;
+ fr_w = var->xres_virtual;
+ if (!(var->vmode & FB_VMODE_YWRAP)) {
+ fr_yoff = var->yoffset % var->yres;
+ fr_h = var->yres;
+ base = line_length * var->yres *
+ (var->yoffset / var->yres);
+ if (ipu_pixel_format_is_split_gpu_tile(var->nonstd))
+ base += (mxc_fbi->gpu_sec_buf_off -
+ line_length * var->yres / 2) *
+ (var->yoffset / var->yres);
+ } else {
+ fr_yoff = var->yoffset;
+ fr_h = var->yres_virtual;
+ }
+
+ tmp_fbi.device = info->device;
+ tmp_fbi.var = *var;
+ tmp_fbi.par = mxc_fbi;
+ if (ipu_pixel_format_is_gpu_tile(var->nonstd)) {
+ unsigned int crop_line, prg_width = var->xres, offset;
+ int ipu_stride, prg_stride, bs;
+ bool tmp_prefetch = mxc_fbi->prefetch;
+
+ if (!(var->xres % 32))
+ bs = 32;
+ else if (!(var->xres % 16))
+ bs = 16;
+ else
+ bs = 32;
+
+ prg_width += fr_xoff % bw;
+ if (((fr_xoff % bw) + prg_width) % bs)
+ prg_width = ALIGN(prg_width, bs);
+
+ mxc_fbi->prefetch = true;
+ ipu_stride = prg_width *
+ bytes_per_pixel(fbi_to_pixfmt(&tmp_fbi, false));
+
+ if (var->vmode & FB_VMODE_INTERLACED) {
+ if ((fr_yoff % bh) % 2) {
+ dev_err(info->device,
+ "wrong crop value in interlaced mode\n");
+ return -EINVAL;
+ }
+ crop_line = (fr_yoff % bh) / 2;
+ prg_stride = ipu_stride * 2;
+ } else {
+ crop_line = fr_yoff % bh;
+ prg_stride = ipu_stride;
+ }
+
+ offset = crop_line * prg_stride +
+ (fr_xoff % bw) *
+ bytes_per_pixel(fbi_to_pixfmt(&tmp_fbi, false));
+ mxc_fbi->prefetch = tmp_prefetch;
+ if (offset % 8) {
+ dev_err(info->device,
+ "IPU base address is not 8byte aligned\n");
+ return -EINVAL;
+ }
+ } else {
+ unsigned int uoff = 0, voff = 0;
+ int fb_stride;
+
+ switch (fbi_to_pixfmt(&tmp_fbi, true)) {
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_NV12:
+ case PRE_PIX_FMT_NV21:
+ case IPU_PIX_FMT_NV16:
+ case PRE_PIX_FMT_NV61:
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YVU422P:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YUV444P:
+ fb_stride = var->xres_virtual;
+ break;
+ default:
+ fb_stride = line_length;
+ }
+ base += fr_yoff * fb_stride +
+ fr_xoff * var->bits_per_pixel / 8;
+
+ ipu_get_channel_offset(fbi_to_pixfmt(&tmp_fbi, true),
+ var->xres,
+ fr_h,
+ fr_w,
+ 0, 0,
+ fr_yoff,
+ fr_xoff,
+ &uoff,
+ &voff);
+ if (base % 8 || uoff % 8 || voff % 8) {
+ dev_err(info->device,
+ "IPU base address is not 8byte aligned\n");
+ return -EINVAL;
+ }
+ }
+
+ if (var->pixclock < 1000) {
+ htotal = var->xres + var->right_margin + var->hsync_len +
+ var->left_margin;
+ vtotal = var->yres + var->lower_margin + var->vsync_len +
+ var->upper_margin;
+ var->pixclock = (vtotal * htotal * 6UL) / 100UL;
+ var->pixclock = KHZ2PICOS(var->pixclock);
+ dev_dbg(info->device,
+ "pixclock set for 60Hz refresh = %u ps\n",
+ var->pixclock);
+ }
+
+ var->height = -1;
+ var->width = -1;
+ var->grayscale = 0;
+
+ return 0;
+}
+
+static inline u_int _chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int mxcfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int trans, struct fb_info *fbi)
+{
+ unsigned int val;
+ int ret = 1;
+
+ /*
+ * If greyscale is true, then we convert the RGB value
+ * to greyscale no matter what visual we are using.
+ */
+ if (fbi->var.grayscale)
+ red = green = blue = (19595 * red + 38470 * green +
+ 7471 * blue) >> 16;
+ switch (fbi->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ /*
+ * 16-bit True Colour. We encode the RGB value
+ * according to the RGB bitfield information.
+ */
+ if (regno < 16) {
+ u32 *pal = fbi->pseudo_palette;
+
+ val = _chan_to_field(red, &fbi->var.red);
+ val |= _chan_to_field(green, &fbi->var.green);
+ val |= _chan_to_field(blue, &fbi->var.blue);
+
+ pal[regno] = val;
+ ret = 0;
+ }
+ break;
+
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Function to handle custom ioctls for MXC framebuffer.
+ *
+ * @param inode inode struct
+ *
+ * @param file file struct
+ *
+ * @param cmd Ioctl command to handle
+ *
+ * @param arg User pointer to command arguments
+ *
+ * @param fbi framebuffer information pointer
+ */
+static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+ int __user *argp = (void __user *)arg;
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+
+ switch (cmd) {
+ case MXCFB_SET_GBL_ALPHA:
+ {
+ struct mxcfb_gbl_alpha ga;
+
+ if (copy_from_user(&ga, (void *)arg, sizeof(ga))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if (ipu_disp_set_global_alpha(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ (bool)ga.enable,
+ ga.alpha)) {
+ retval = -EINVAL;
+ break;
+ }
+
+ if (ga.enable)
+ mxc_fbi->alpha_chan_en = false;
+
+ if (ga.enable)
+ dev_dbg(fbi->device,
+ "Set global alpha of %s to %d\n",
+ fbi->fix.id, ga.alpha);
+ break;
+ }
+ case MXCFB_SET_LOC_ALPHA:
+ {
+ struct mxcfb_loc_alpha la;
+ bool bad_pixfmt =
+ ipu_ch_param_bad_alpha_pos(fbi_to_pixfmt(fbi, true));
+
+ if (copy_from_user(&la, (void *)arg, sizeof(la))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if (la.enable && !la.alpha_in_pixel) {
+ struct fb_info *fbi_tmp;
+ ipu_channel_t ipu_ch;
+
+ if (bad_pixfmt) {
+ dev_err(fbi->device, "Bad pixel format "
+ "for graphics plane fb\n");
+ retval = -EINVAL;
+ break;
+ }
+
+ mxc_fbi->alpha_chan_en = true;
+
+ if (mxc_fbi->ipu_ch == MEM_FG_SYNC)
+ ipu_ch = MEM_BG_SYNC;
+ else if (mxc_fbi->ipu_ch == MEM_BG_SYNC)
+ ipu_ch = MEM_FG_SYNC;
+ else {
+ retval = -EINVAL;
+ break;
+ }
+
+ fbi_tmp = found_registered_fb(ipu_ch, mxc_fbi->ipu_id);
+ if (fbi_tmp)
+ ((struct mxcfb_info *)(fbi_tmp->par))->alpha_chan_en = false;
+ } else
+ mxc_fbi->alpha_chan_en = false;
+
+ if (ipu_disp_set_global_alpha(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ !(bool)la.enable, 0)) {
+ retval = -EINVAL;
+ break;
+ }
+
+ fbi->var.activate = (fbi->var.activate & ~FB_ACTIVATE_MASK) |
+ FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+ mxcfb_set_par(fbi);
+
+ la.alpha_phy_addr0 = mxc_fbi->alpha_phy_addr0;
+ la.alpha_phy_addr1 = mxc_fbi->alpha_phy_addr1;
+ if (copy_to_user((void *)arg, &la, sizeof(la))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if (la.enable)
+ dev_dbg(fbi->device,
+ "Enable DP local alpha for %s\n",
+ fbi->fix.id);
+ break;
+ }
+ case MXCFB_SET_LOC_ALP_BUF:
+ {
+ unsigned long base;
+ uint32_t ipu_alp_ch_irq;
+
+ if (!(((mxc_fbi->ipu_ch == MEM_FG_SYNC) ||
+ (mxc_fbi->ipu_ch == MEM_BG_SYNC)) &&
+ (mxc_fbi->alpha_chan_en))) {
+ dev_err(fbi->device,
+ "Should use background or overlay "
+ "framebuffer to set the alpha buffer "
+ "number\n");
+ return -EINVAL;
+ }
+
+ if (get_user(base, argp))
+ return -EFAULT;
+
+ if (base != mxc_fbi->alpha_phy_addr0 &&
+ base != mxc_fbi->alpha_phy_addr1) {
+ dev_err(fbi->device,
+ "Wrong alpha buffer physical address "
+ "%lu\n", base);
+ return -EINVAL;
+ }
+
+ if (mxc_fbi->ipu_ch == MEM_FG_SYNC)
+ ipu_alp_ch_irq = IPU_IRQ_FG_ALPHA_SYNC_EOF;
+ else
+ ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
+
+ retval = wait_for_completion_timeout(
+ &mxc_fbi->alpha_flip_complete, HZ/2);
+ if (retval == 0) {
+ dev_err(fbi->device, "timeout when waiting for alpha flip irq\n");
+ retval = -ETIMEDOUT;
+ break;
+ }
+
+ mxc_fbi->cur_ipu_alpha_buf =
+ !mxc_fbi->cur_ipu_alpha_buf;
+ if (ipu_update_channel_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_ALPHA_IN_BUFFER,
+ mxc_fbi->
+ cur_ipu_alpha_buf,
+ base) == 0) {
+ ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_ALPHA_IN_BUFFER,
+ mxc_fbi->cur_ipu_alpha_buf);
+ ipu_clear_irq(mxc_fbi->ipu, ipu_alp_ch_irq);
+ ipu_enable_irq(mxc_fbi->ipu, ipu_alp_ch_irq);
+ } else {
+ dev_err(fbi->device,
+ "Error updating %s SDC alpha buf %d "
+ "to address=0x%08lX\n",
+ fbi->fix.id,
+ mxc_fbi->cur_ipu_alpha_buf, base);
+ }
+ break;
+ }
+ case MXCFB_SET_CLR_KEY:
+ {
+ struct mxcfb_color_key key;
+ if (copy_from_user(&key, (void *)arg, sizeof(key))) {
+ retval = -EFAULT;
+ break;
+ }
+ retval = ipu_disp_set_color_key(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ key.enable,
+ key.color_key);
+ dev_dbg(fbi->device, "Set color key to 0x%08X\n",
+ key.color_key);
+ break;
+ }
+ case MXCFB_SET_GAMMA:
+ {
+ struct mxcfb_gamma gamma;
+ if (copy_from_user(&gamma, (void *)arg, sizeof(gamma))) {
+ retval = -EFAULT;
+ break;
+ }
+ retval = ipu_disp_set_gamma_correction(mxc_fbi->ipu,
+ mxc_fbi->ipu_ch,
+ gamma.enable,
+ gamma.constk,
+ gamma.slopek);
+ break;
+ }
+ case MXCFB_SET_GPU_SPLIT_FMT:
+ {
+ struct mxcfb_gpu_split_fmt fmt;
+
+ if (copy_from_user(&fmt, (void *)arg, sizeof(fmt))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if (fmt.var.nonstd != IPU_PIX_FMT_GPU32_SB_ST &&
+ fmt.var.nonstd != IPU_PIX_FMT_GPU32_SB_SRT &&
+ fmt.var.nonstd != IPU_PIX_FMT_GPU16_SB_ST &&
+ fmt.var.nonstd != IPU_PIX_FMT_GPU16_SB_SRT) {
+ retval = -EINVAL;
+ break;
+ }
+
+ mxc_fbi->gpu_sec_buf_off = fmt.offset;
+ fmt.var.activate = (fbi->var.activate & ~FB_ACTIVATE_MASK) |
+ FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+ console_lock();
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ retval = fb_set_var(fbi, &fmt.var);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+ break;
+ }
+ case MXCFB_SET_PREFETCH:
+ {
+ int enable;
+
+ if (copy_from_user(&enable, (void *)arg, sizeof(enable))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if (!enable) {
+ if (ipu_pixel_format_is_gpu_tile(fbi_to_pixfmt(fbi, true))) {
+ dev_err(fbi->device, "Cannot disable prefetch in "
+ "resolving mode\n");
+ retval = -EINVAL;
+ break;
+ }
+ if (ipu_pixel_format_is_pre_yuv(fbi_to_pixfmt(fbi, true))) {
+ dev_err(fbi->device, "Cannot disable prefetch when "
+ "PRE gets NV61 or NV21\n");
+ retval = -EINVAL;
+ break;
+ }
+ } else {
+ if ((fbi->var.vmode & FB_VMODE_INTERLACED) &&
+ ipu_pixel_format_is_multiplanar_yuv(fbi_to_pixfmt(fbi, true))) {
+ dev_err(fbi->device, "Cannot enable prefetch when "
+ "PRE gets multiplanar YUV frames\n");
+ retval = -EINVAL;
+ break;
+ }
+ }
+
+ retval = mxcfb_check_var(&fbi->var, fbi);
+ if (retval)
+ break;
+
+ mxc_fbi->prefetch = !!enable;
+
+ if (mxc_fbi->cur_prefetch == mxc_fbi->prefetch)
+ break;
+
+ fbi->var.activate = (fbi->var.activate & ~FB_ACTIVATE_MASK) |
+ FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+ retval = mxcfb_set_par(fbi);
+ break;
+ }
+ case MXCFB_GET_PREFETCH:
+ {
+ struct mxcfb_info *mxc_fbi =
+ (struct mxcfb_info *)fbi->par;
+
+ if (put_user(mxc_fbi->cur_prefetch, argp))
+ return -EFAULT;
+ break;
+ }
+ case MXCFB_WAIT_FOR_VSYNC:
+ {
+ if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
+ /* BG should poweron */
+ struct mxcfb_info *bg_mxcfbi = NULL;
+ struct fb_info *fbi_tmp;
+
+ fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
+ if (fbi_tmp)
+ bg_mxcfbi = ((struct mxcfb_info *)(fbi_tmp->par));
+
+ if (!bg_mxcfbi) {
+ retval = -EINVAL;
+ break;
+ }
+ if (bg_mxcfbi->cur_blank != FB_BLANK_UNBLANK) {
+ retval = -EINVAL;
+ break;
+ }
+ }
+ if (mxc_fbi->cur_blank != FB_BLANK_UNBLANK) {
+ retval = -EINVAL;
+ break;
+ }
+
+ init_completion(&mxc_fbi->vsync_complete);
+ ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
+ ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
+ retval = wait_for_completion_interruptible_timeout(
+ &mxc_fbi->vsync_complete, 1 * HZ);
+ if (retval == 0) {
+ dev_err(fbi->device,
+ "MXCFB_WAIT_FOR_VSYNC: timeout %d\n",
+ retval);
+ retval = -ETIME;
+ } else if (retval > 0) {
+ retval = 0;
+ }
+ break;
+ }
+ case FBIO_ALLOC:
+ {
+ int size;
+ struct mxcfb_alloc_list *mem;
+
+ mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+ if (mem == NULL)
+ return -ENOMEM;
+
+ if (get_user(size, argp)) {
+ kfree(mem);
+ return -EFAULT;
+ }
+
+ mem->size = PAGE_ALIGN(size);
+
+ mem->cpu_addr = dma_alloc_coherent(fbi->device, size,
+ &mem->phy_addr,
+ GFP_KERNEL);
+ if (mem->cpu_addr == NULL) {
+ kfree(mem);
+ return -ENOMEM;
+ }
+
+ list_add(&mem->list, &fb_alloc_list);
+
+ if (put_user(mem->phy_addr, argp)) {
+ list_del(&mem->list);
+ dma_free_coherent(fbi->device,
+ mem->size,
+ mem->cpu_addr,
+ mem->phy_addr);
+ kfree(mem);
+ return -EFAULT;
+ }
+
+ dev_dbg(fbi->device, "allocated %d bytes @ 0x%08X\n",
+ mem->size, mem->phy_addr);
+
+ break;
+ }
+ case FBIO_FREE:
+ {
+ unsigned long offset;
+ struct mxcfb_alloc_list *mem;
+
+ if (get_user(offset, argp))
+ return -EFAULT;
+
+ retval = -EINVAL;
+ list_for_each_entry(mem, &fb_alloc_list, list) {
+ if (mem->phy_addr == offset) {
+ list_del(&mem->list);
+ dma_free_coherent(fbi->device,
+ mem->size,
+ mem->cpu_addr,
+ mem->phy_addr);
+ kfree(mem);
+ retval = 0;
+ break;
+ }
+ }
+
+ break;
+ }
+ case MXCFB_SET_OVERLAY_POS:
+ {
+ struct mxcfb_pos pos;
+ struct fb_info *bg_fbi = NULL;
+ struct mxcfb_info *bg_mxcfbi = NULL;
+
+ if (mxc_fbi->ipu_ch != MEM_FG_SYNC) {
+ dev_err(fbi->device, "Should use the overlay "
+ "framebuffer to set the position of "
+ "the overlay window\n");
+ retval = -EINVAL;
+ break;
+ }
+
+ if (copy_from_user(&pos, (void *)arg, sizeof(pos))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ bg_fbi = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
+ if (bg_fbi)
+ bg_mxcfbi = ((struct mxcfb_info *)(bg_fbi->par));
+
+ if (bg_fbi == NULL) {
+ dev_err(fbi->device, "Cannot find the "
+ "background framebuffer\n");
+ retval = -ENOENT;
+ break;
+ }
+
+ /* if fb is unblank, check if the pos fit the display */
+ if (mxc_fbi->cur_blank == FB_BLANK_UNBLANK) {
+ if (fbi->var.xres + pos.x > bg_fbi->var.xres) {
+ if (bg_fbi->var.xres < fbi->var.xres)
+ pos.x = 0;
+ else
+ pos.x = bg_fbi->var.xres - fbi->var.xres;
+ }
+ if (fbi->var.yres + pos.y > bg_fbi->var.yres) {
+ if (bg_fbi->var.yres < fbi->var.yres)
+ pos.y = 0;
+ else
+ pos.y = bg_fbi->var.yres - fbi->var.yres;
+ }
+ }
+
+ retval = ipu_disp_set_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ pos.x, pos.y);
+
+ if (copy_to_user((void *)arg, &pos, sizeof(pos))) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+ }
+ case MXCFB_GET_FB_IPU_CHAN:
+ {
+ struct mxcfb_info *mxc_fbi =
+ (struct mxcfb_info *)fbi->par;
+
+ if (put_user(mxc_fbi->ipu_ch, argp))
+ return -EFAULT;
+ break;
+ }
+ case MXCFB_GET_DIFMT:
+ {
+ struct mxcfb_info *mxc_fbi =
+ (struct mxcfb_info *)fbi->par;
+
+ if (put_user(mxc_fbi->ipu_di_pix_fmt, argp))
+ return -EFAULT;
+ break;
+ }
+ case MXCFB_GET_FB_IPU_DI:
+ {
+ struct mxcfb_info *mxc_fbi =
+ (struct mxcfb_info *)fbi->par;
+
+ if (put_user(mxc_fbi->ipu_di, argp))
+ return -EFAULT;
+ break;
+ }
+ case MXCFB_GET_FB_BLANK:
+ {
+ struct mxcfb_info *mxc_fbi =
+ (struct mxcfb_info *)fbi->par;
+
+ if (put_user(mxc_fbi->cur_blank, argp))
+ return -EFAULT;
+ break;
+ }
+ case MXCFB_SET_DIFMT:
+ {
+ struct mxcfb_info *mxc_fbi =
+ (struct mxcfb_info *)fbi->par;
+
+ if (get_user(mxc_fbi->ipu_di_pix_fmt, argp))
+ return -EFAULT;
+
+ break;
+ }
+ case MXCFB_CSC_UPDATE:
+ {
+ struct mxcfb_csc_matrix csc;
+
+ if (copy_from_user(&csc, (void *) arg, sizeof(csc)))
+ return -EFAULT;
+
+ if ((mxc_fbi->ipu_ch != MEM_FG_SYNC) &&
+ (mxc_fbi->ipu_ch != MEM_BG_SYNC) &&
+ (mxc_fbi->ipu_ch != MEM_BG_ASYNC0))
+ return -EFAULT;
+ ipu_set_csc_coefficients(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ csc.param);
+ break;
+ }
+ default:
+ retval = -EINVAL;
+ }
+ return retval;
+}
+
+/*
+ * mxcfb_blank():
+ * Blank the display.
+ */
+static int mxcfb_blank(int blank, struct fb_info *info)
+{
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par;
+ int ret = 0;
+
+ dev_dbg(info->device, "blank = %d\n", blank);
+
+ if (blank)
+ blank = FB_BLANK_POWERDOWN;
+
+ if (mxc_fbi->cur_blank == blank)
+ return 0;
+
+ mxc_fbi->next_blank = blank;
+
+ if (blank == FB_BLANK_UNBLANK) {
+ info->var.activate = (info->var.activate & ~FB_ACTIVATE_MASK) |
+ FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+ ret = fb_set_var(info, &info->var);
+ } else {
+ if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->disable)
+ mxc_fbi->dispdrv->drv->disable(mxc_fbi->dispdrv, info);
+ ipu_disable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, true);
+ if (mxc_fbi->ipu_di >= 0)
+ ipu_uninit_sync_panel(mxc_fbi->ipu, mxc_fbi->ipu_di);
+ ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
+ if (mxc_fbi->cur_prefetch) {
+ ipu_prg_disable(mxc_fbi->ipu_id, mxc_fbi->pre_num);
+ ipu_pre_disable(mxc_fbi->pre_num);
+ ipu_pre_free(&mxc_fbi->pre_num);
+ }
+ }
+ if (!ret)
+ mxc_fbi->cur_blank = blank;
+ return ret;
+}
+
+/*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ *
+ * @param var Variable screen buffer information
+ * @param info Framebuffer information pointer
+ */
+static int
+mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par,
+ *mxc_graphic_fbi = NULL;
+ u_int y_bottom;
+ unsigned int fr_xoff, fr_yoff, fr_w, fr_h;
+ unsigned long base, ipu_base = 0, active_alpha_phy_addr = 0;
+ bool loc_alpha_en = false;
+ int fb_stride;
+ int bw = 0, bh = 0;
+ int i;
+ int ret;
+
+ /* no pan display during fb blank */
+ if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
+ struct mxcfb_info *bg_mxcfbi = NULL;
+ struct fb_info *fbi_tmp;
+
+ fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
+ if (fbi_tmp)
+ bg_mxcfbi = ((struct mxcfb_info *)(fbi_tmp->par));
+ if (!bg_mxcfbi)
+ return -EINVAL;
+ if (bg_mxcfbi->cur_blank != FB_BLANK_UNBLANK)
+ return -EINVAL;
+ }
+ if (mxc_fbi->cur_blank != FB_BLANK_UNBLANK)
+ return -EINVAL;
+
+ if (mxc_fbi->resolve) {
+ fmt_to_tile_block(info->var.nonstd, &bw, &bh);
+
+ if (mxc_fbi->cur_var.xoffset % bw != var->xoffset % bw ||
+ mxc_fbi->cur_var.yoffset % bh != var->yoffset % bh) {
+ dev_err(info->device, "do not support panning "
+ "with tile crop settings changed\n");
+ return -EINVAL;
+ }
+ }
+
+ y_bottom = var->yoffset;
+
+ if (y_bottom > info->var.yres_virtual)
+ return -EINVAL;
+
+ switch (fbi_to_pixfmt(info, true)) {
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YVU420P:
+ case IPU_PIX_FMT_NV12:
+ case PRE_PIX_FMT_NV21:
+ case IPU_PIX_FMT_NV16:
+ case PRE_PIX_FMT_NV61:
+ case IPU_PIX_FMT_YUV422P:
+ case IPU_PIX_FMT_YVU422P:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YUV444P:
+ fb_stride = info->var.xres_virtual;
+ break;
+ default:
+ fb_stride = info->fix.line_length;
+ }
+
+ base = info->fix.smem_start;
+ fr_xoff = var->xoffset;
+ fr_w = info->var.xres_virtual;
+ if (!(var->vmode & FB_VMODE_YWRAP)) {
+ dev_dbg(info->device, "Y wrap disabled\n");
+ fr_yoff = var->yoffset % info->var.yres;
+ fr_h = info->var.yres;
+ base += info->fix.line_length * info->var.yres *
+ (var->yoffset / info->var.yres);
+ if (ipu_pixel_format_is_split_gpu_tile(var->nonstd))
+ base += (mxc_fbi->gpu_sec_buf_off -
+ info->fix.line_length * info->var.yres / 2) *
+ (var->yoffset / info->var.yres);
+ } else {
+ dev_dbg(info->device, "Y wrap enabled\n");
+ fr_yoff = var->yoffset;
+ fr_h = info->var.yres_virtual;
+ }
+ if (!mxc_fbi->resolve) {
+ base += fr_yoff * fb_stride + fr_xoff *
+ bytes_per_pixel(fbi_to_pixfmt(info, true));
+
+ if (mxc_fbi->cur_prefetch && (info->var.vmode & FB_VMODE_INTERLACED))
+ base += info->var.rotate ?
+ fr_w * bytes_per_pixel(fbi_to_pixfmt(info, true)) : 0;
+ }
+
+ if (mxc_fbi->cur_prefetch) {
+ unsigned long lock_flags = 0;
+
+ if (ipu_pre_yres_is_small(info->var.yres))
+ /*
+ * Update the PRE buffer address in the flip interrupt
+ * handler in this case to workaround the SoC design
+ * bug recorded by errata ERR009624.
+ */
+ spin_lock_irqsave(&mxc_fbi->spin_lock, lock_flags);
+
+ if (mxc_fbi->resolve) {
+ mxc_fbi->x_crop = fr_xoff & ~(bw - 1);
+ mxc_fbi->y_crop = fr_yoff & ~(bh - 1);
+ } else {
+ mxc_fbi->x_crop = 0;
+ mxc_fbi->y_crop = 0;
+ }
+
+ ipu_get_channel_offset(fbi_to_pixfmt(info, true),
+ info->var.xres,
+ fr_h,
+ fr_w,
+ 0, 0,
+ fr_yoff,
+ fr_xoff,
+ &mxc_fbi->sec_buf_off,
+ &mxc_fbi->trd_buf_off);
+ if (mxc_fbi->resolve)
+ mxc_fbi->sec_buf_off = mxc_fbi->gpu_sec_buf_off;
+
+ if (ipu_pre_yres_is_small(info->var.yres)) {
+ mxc_fbi->base = base;
+ spin_unlock_irqrestore(&mxc_fbi->spin_lock, lock_flags);
+ }
+ } else {
+ ipu_base = base;
+ }
+
+ /* Check if DP local alpha is enabled and find the graphic fb */
+ if (mxc_fbi->ipu_ch == MEM_BG_SYNC || mxc_fbi->ipu_ch == MEM_FG_SYNC) {
+ for (i = 0; i < num_registered_fb; i++) {
+ char bg_id[] = "DISP3 BG";
+ char fg_id[] = "DISP3 FG";
+ char *idstr = registered_fb[i]->fix.id;
+ bg_id[4] += mxc_fbi->ipu_id;
+ fg_id[4] += mxc_fbi->ipu_id;
+ if ((strcmp(idstr, bg_id) == 0 ||
+ strcmp(idstr, fg_id) == 0) &&
+ ((struct mxcfb_info *)
+ (registered_fb[i]->par))->alpha_chan_en) {
+ loc_alpha_en = true;
+ mxc_graphic_fbi = (struct mxcfb_info *)
+ (registered_fb[i]->par);
+ active_alpha_phy_addr =
+ mxc_fbi->cur_ipu_alpha_buf ?
+ mxc_graphic_fbi->alpha_phy_addr1 :
+ mxc_graphic_fbi->alpha_phy_addr0;
+ dev_dbg(info->device, "Updating SDC alpha "
+ "buf %d address=0x%08lX\n",
+ !mxc_fbi->cur_ipu_alpha_buf,
+ active_alpha_phy_addr);
+ break;
+ }
+ }
+ }
+
+ if (!mxc_fbi->cur_prefetch ||
+ (mxc_fbi->cur_prefetch && !ipu_pre_yres_is_small(info->var.yres))) {
+ ret = wait_for_completion_timeout(&mxc_fbi->flip_complete,
+ HZ/2);
+ if (ret == 0) {
+ dev_err(info->device, "timeout when waiting for flip "
+ "irq\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ if (!mxc_fbi->cur_prefetch) {
+ ++mxc_fbi->cur_ipu_buf;
+ mxc_fbi->cur_ipu_buf %= 3;
+ dev_dbg(info->device, "Updating SDC %s buf %d address=0x%08lX\n",
+ info->fix.id, mxc_fbi->cur_ipu_buf, base);
+ }
+ mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
+
+ if (mxc_fbi->cur_prefetch)
+ goto next;
+
+ if (ipu_update_channel_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
+ mxc_fbi->cur_ipu_buf, ipu_base) == 0) {
+next:
+ /* Update the DP local alpha buffer only for graphic plane */
+ if (loc_alpha_en && mxc_graphic_fbi == mxc_fbi &&
+ ipu_update_channel_buffer(mxc_graphic_fbi->ipu, mxc_graphic_fbi->ipu_ch,
+ IPU_ALPHA_IN_BUFFER,
+ mxc_fbi->cur_ipu_alpha_buf,
+ active_alpha_phy_addr) == 0) {
+ ipu_select_buffer(mxc_graphic_fbi->ipu, mxc_graphic_fbi->ipu_ch,
+ IPU_ALPHA_IN_BUFFER,
+ mxc_fbi->cur_ipu_alpha_buf);
+ }
+
+ /* update u/v offset */
+ if (!mxc_fbi->cur_prefetch) {
+ ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER,
+ fbi_to_pixfmt(info, true),
+ fr_w,
+ fr_h,
+ fr_w,
+ 0, 0,
+ fr_yoff,
+ fr_xoff);
+
+ ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, mxc_fbi->cur_ipu_buf);
+ } else if (!ipu_pre_yres_is_small(info->var.yres)) {
+ ipu_pre_set_fb_buffer(mxc_fbi->pre_num,
+ mxc_fbi->resolve,
+ base, info->var.yres,
+ mxc_fbi->x_crop,
+ mxc_fbi->y_crop,
+ mxc_fbi->sec_buf_off,
+ mxc_fbi->trd_buf_off);
+ }
+ ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+ ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+ } else {
+ dev_err(info->device,
+ "Error updating SDC buf %d to address=0x%08lX, "
+ "current buf %d, buf0 ready %d, buf1 ready %d, "
+ "buf2 ready %d\n", mxc_fbi->cur_ipu_buf, base,
+ ipu_get_cur_buffer_idx(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER),
+ ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 0),
+ ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 1),
+ ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 2));
+ if (!mxc_fbi->cur_prefetch) {
+ ++mxc_fbi->cur_ipu_buf;
+ mxc_fbi->cur_ipu_buf %= 3;
+ ++mxc_fbi->cur_ipu_buf;
+ mxc_fbi->cur_ipu_buf %= 3;
+ }
+ mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
+ ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+ ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+ return -EBUSY;
+ }
+
+ if (mxc_fbi->cur_prefetch && ipu_pre_yres_is_small(info->var.yres)) {
+ ret = wait_for_completion_timeout(&mxc_fbi->flip_complete,
+ HZ/2);
+ if (ret == 0) {
+ dev_err(info->device, "timeout when waiting for flip "
+ "irq\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ dev_dbg(info->device, "Update complete\n");
+
+ info->var.yoffset = var->yoffset;
+ mxc_fbi->cur_var.xoffset = var->xoffset;
+ mxc_fbi->cur_var.yoffset = var->yoffset;
+
+ return 0;
+}
+
+/*
+ * Function to handle custom mmap for MXC framebuffer.
+ *
+ * @param fbi framebuffer information pointer
+ *
+ * @param vma Pointer to vm_area_struct
+ */
+static int mxcfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
+{
+ bool found = false;
+ u32 len;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ struct mxcfb_alloc_list *mem;
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+
+ if (offset < fbi->fix.smem_len) {
+ /* mapping framebuffer memory */
+ len = fbi->fix.smem_len - offset;
+ vma->vm_pgoff = (fbi->fix.smem_start + offset) >> PAGE_SHIFT;
+ } else if ((vma->vm_pgoff ==
+ (mxc_fbi->alpha_phy_addr0 >> PAGE_SHIFT)) ||
+ (vma->vm_pgoff ==
+ (mxc_fbi->alpha_phy_addr1 >> PAGE_SHIFT))) {
+ len = mxc_fbi->alpha_mem_len;
+ } else {
+ list_for_each_entry(mem, &fb_alloc_list, list) {
+ if (offset == mem->phy_addr) {
+ found = true;
+ len = mem->size;
+ break;
+ }
+ }
+ if (!found)
+ return -EINVAL;
+ }
+
+ len = PAGE_ALIGN(len);
+ if (vma->vm_end - vma->vm_start > len)
+ return -EINVAL;
+
+ /* make buffers bufferable */
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ vma->vm_flags |= VM_IO;
+
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+ dev_dbg(fbi->device, "mmap remap_pfn_range failed\n");
+ return -ENOBUFS;
+ }
+
+ return 0;
+}
+
+/*!
+ * This structure contains the pointers to the control functions that are
+ * invoked by the core framebuffer driver to perform operations like
+ * blitting, rectangle filling, copy regions and cursor definition.
+ */
+static struct fb_ops mxcfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_set_par = mxcfb_set_par,
+ .fb_check_var = mxcfb_check_var,
+ .fb_setcolreg = mxcfb_setcolreg,
+ .fb_pan_display = mxcfb_pan_display,
+ .fb_ioctl = mxcfb_ioctl,
+ .fb_mmap = mxcfb_mmap,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_blank = mxcfb_blank,
+};
+
+static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id)
+{
+ struct fb_info *fbi = dev_id;
+ struct mxcfb_info *mxc_fbi = fbi->par;
+
+ if (mxc_fbi->pre_config) {
+ ipu_pre_set_ctrl(mxc_fbi->pre_num, mxc_fbi->pre_config);
+ mxc_fbi->pre_config = NULL;
+ complete(&mxc_fbi->otf_complete);
+ return IRQ_HANDLED;
+ }
+
+ if (mxc_fbi->cur_prefetch && ipu_pre_yres_is_small(fbi->var.yres)) {
+ spin_lock(&mxc_fbi->spin_lock);
+ ipu_pre_set_fb_buffer(mxc_fbi->pre_num,
+ mxc_fbi->resolve,
+ mxc_fbi->base, fbi->var.yres,
+ mxc_fbi->x_crop, mxc_fbi->y_crop,
+ mxc_fbi->sec_buf_off,
+ mxc_fbi->trd_buf_off);
+ spin_unlock(&mxc_fbi->spin_lock);
+ }
+
+ complete(&mxc_fbi->flip_complete);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mxcfb_nf_irq_handler(int irq, void *dev_id)
+{
+ struct fb_info *fbi = dev_id;
+ struct mxcfb_info *mxc_fbi = fbi->par;
+
+ complete(&mxc_fbi->vsync_complete);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mxcfb_alpha_irq_handler(int irq, void *dev_id)
+{
+ struct fb_info *fbi = dev_id;
+ struct mxcfb_info *mxc_fbi = fbi->par;
+
+ complete(&mxc_fbi->alpha_flip_complete);
+ return IRQ_HANDLED;
+}
+
+/*
+ * Suspends the framebuffer and blanks the screen. Power management support
+ */
+static int mxcfb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct fb_info *fbi = platform_get_drvdata(pdev);
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+ int saved_blank;
+#ifdef CONFIG_FB_MXC_LOW_PWR_DISPLAY
+ void *fbmem;
+#endif
+
+ if (mxc_fbi->ovfbi) {
+ struct mxcfb_info *mxc_fbi_fg =
+ (struct mxcfb_info *)mxc_fbi->ovfbi->par;
+
+ console_lock();
+ fb_set_suspend(mxc_fbi->ovfbi, 1);
+ saved_blank = mxc_fbi_fg->cur_blank;
+ mxcfb_blank(FB_BLANK_POWERDOWN, mxc_fbi->ovfbi);
+ mxc_fbi_fg->next_blank = saved_blank;
+ console_unlock();
+ }
+
+ console_lock();
+ fb_set_suspend(fbi, 1);
+ saved_blank = mxc_fbi->cur_blank;
+ mxcfb_blank(FB_BLANK_POWERDOWN, fbi);
+ mxc_fbi->next_blank = saved_blank;
+ console_unlock();
+
+ return 0;
+}
+
+/*
+ * Resumes the framebuffer and unblanks the screen. Power management support
+ */
+static int mxcfb_resume(struct platform_device *pdev)
+{
+ struct fb_info *fbi = platform_get_drvdata(pdev);
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+
+ console_lock();
+ mxcfb_blank(mxc_fbi->next_blank, fbi);
+ fb_set_suspend(fbi, 0);
+ console_unlock();
+
+ if (mxc_fbi->ovfbi) {
+ struct mxcfb_info *mxc_fbi_fg =
+ (struct mxcfb_info *)mxc_fbi->ovfbi->par;
+ console_lock();
+ mxcfb_blank(mxc_fbi_fg->next_blank, mxc_fbi->ovfbi);
+ fb_set_suspend(mxc_fbi->ovfbi, 0);
+ console_unlock();
+ }
+
+ return 0;
+}
+
+/*
+ * Main framebuffer functions
+ */
+
+/*!
+ * Allocates the DRAM memory for the frame buffer. This buffer is remapped
+ * into a non-cached, non-buffered, memory region to allow palette and pixel
+ * writes to occur without flushing the cache. Once this area is remapped,
+ * all virtual memory access to the video memory should occur at the new region.
+ *
+ * @param fbi framebuffer information pointer
+ *
+ * @return Error code indicating success or failure
+ */
+static int mxcfb_map_video_memory(struct fb_info *fbi)
+{
+ struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+
+ if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length)
+ fbi->fix.smem_len = fbi->var.yres_virtual *
+ fbi->fix.line_length;
+
+ if (mxc_fbi->resolve && mxc_fbi->gpu_sec_buf_off) {
+ if (fbi->var.vmode & FB_VMODE_YWRAP)
+ fbi->fix.smem_len = mxc_fbi->gpu_sec_buf_off +
+ fbi->fix.smem_len / 2;
+ else
+ fbi->fix.smem_len = mxc_fbi->gpu_sec_buf_off *
+ (fbi->var.yres_virtual / fbi->var.yres) +
+ fbi->fix.smem_len / 2;
+ }
+
+ fbi->screen_base = dma_alloc_writecombine(fbi->device,
+ fbi->fix.smem_len,
+ (dma_addr_t *)&fbi->fix.smem_start,
+ GFP_DMA | GFP_KERNEL);
+ if (fbi->screen_base == 0) {
+ dev_err(fbi->device, "Unable to allocate framebuffer memory\n");
+ fbi->fix.smem_len = 0;
+ fbi->fix.smem_start = 0;
+ return -EBUSY;
+ }
+
+ dev_dbg(fbi->device, "allocated fb @ paddr=0x%08X, size=%d.\n",
+ (uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
+
+ fbi->screen_size = fbi->fix.smem_len;
+
+ /* Clear the screen */
+ memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
+
+ return 0;
+}
+
+/*!
+ * De-allocates the DRAM memory for the frame buffer.
+ *
+ * @param fbi framebuffer information pointer
+ *
+ * @return Error code indicating success or failure
+ */
+static int mxcfb_unmap_video_memory(struct fb_info *fbi)
+{
+ dma_free_writecombine(fbi->device, fbi->fix.smem_len,
+ fbi->screen_base, fbi->fix.smem_start);
+ fbi->screen_base = 0;
+ fbi->fix.smem_start = 0;
+ fbi->fix.smem_len = 0;
+ return 0;
+}
+
+/*!
+ * Initializes the framebuffer information pointer. After allocating
+ * sufficient memory for the framebuffer structure, the fields are
+ * filled with custom information passed in from the configurable
+ * structures. This includes information such as bits per pixel,
+ * color maps, screen width/height and RGBA offsets.
+ *
+ * @return Framebuffer structure initialized with our information
+ */
+static struct fb_info *mxcfb_init_fbinfo(struct device *dev, struct fb_ops *ops)
+{
+ struct fb_info *fbi;
+ struct mxcfb_info *mxcfbi;
+ struct ipuv3_fb_platform_data *plat_data = dev->platform_data;
+
+ /*
+ * Allocate sufficient memory for the fb structure
+ */
+ fbi = framebuffer_alloc(sizeof(struct mxcfb_info), dev);
+ if (!fbi)
+ return NULL;
+
+ mxcfbi = (struct mxcfb_info *)fbi->par;
+
+ fbi->var.activate = FB_ACTIVATE_NOW;
+
+ bpp_to_var(plat_data->default_bpp, &fbi->var);
+
+ fbi->fbops = ops;
+ fbi->flags = FBINFO_FLAG_DEFAULT;
+ fbi->pseudo_palette = mxcfbi->pseudo_palette;
+
+ /*
+ * Allocate colormap
+ */
+ fb_alloc_cmap(&fbi->cmap, 16, 0);
+
+ return fbi;
+}
+
+static ssize_t show_disp_chan(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
+
+ if (mxcfbi->ipu_ch == MEM_BG_SYNC)
+ return sprintf(buf, "2-layer-fb-bg\n");
+ else if (mxcfbi->ipu_ch == MEM_FG_SYNC)
+ return sprintf(buf, "2-layer-fb-fg\n");
+ else if (mxcfbi->ipu_ch == MEM_DC_SYNC)
+ return sprintf(buf, "1-layer-fb\n");
+ else
+ return sprintf(buf, "err: no display chan\n");
+}
+
+static ssize_t swap_disp_chan(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
+ struct mxcfb_info *fg_mxcfbi = NULL;
+
+ console_lock();
+ /* swap only happen between DP-BG and DC, while DP-FG disable */
+ if (((mxcfbi->ipu_ch == MEM_BG_SYNC) &&
+ (strstr(buf, "1-layer-fb") != NULL)) ||
+ ((mxcfbi->ipu_ch == MEM_DC_SYNC) &&
+ (strstr(buf, "2-layer-fb-bg") != NULL))) {
+ struct fb_info *fbi_fg;
+
+ fbi_fg = found_registered_fb(MEM_FG_SYNC, mxcfbi->ipu_id);
+ if (fbi_fg)
+ fg_mxcfbi = (struct mxcfb_info *)fbi_fg->par;
+
+ if (!fg_mxcfbi ||
+ fg_mxcfbi->cur_blank == FB_BLANK_UNBLANK) {
+ dev_err(dev,
+ "Can not switch while fb2(fb-fg) is on.\n");
+ console_unlock();
+ return count;
+ }
+
+ if (swap_channels(info) < 0)
+ dev_err(dev, "Swap display channel failed.\n");
+ }
+
+ console_unlock();
+ return count;
+}
+static DEVICE_ATTR(fsl_disp_property, S_IWUSR | S_IRUGO,
+ show_disp_chan, swap_disp_chan);
+
+static ssize_t show_disp_dev(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
+
+ if (mxcfbi->ipu_ch == MEM_FG_SYNC)
+ return sprintf(buf, "overlay\n");
+ else
+ return sprintf(buf, "%s\n", mxcfbi->dispdrv->drv->name);
+}
+static DEVICE_ATTR(fsl_disp_dev_property, S_IRUGO, show_disp_dev, NULL);
+
+static int mxcfb_get_crtc(struct device *dev, struct mxcfb_info *mxcfbi,
+ enum crtc crtc)
+{
+ int i = 0;
+
+ for (; i < ARRAY_SIZE(ipu_di_crtc_maps); i++)
+ if (ipu_di_crtc_maps[i].crtc == crtc) {
+ mxcfbi->ipu_id = ipu_di_crtc_maps[i].ipu_id;
+ mxcfbi->ipu_di = ipu_di_crtc_maps[i].ipu_di;
+ return 0;
+ }
+
+ dev_err(dev, "failed to get valid crtc\n");
+ return -EINVAL;
+}
+
+static int mxcfb_dispdrv_init(struct platform_device *pdev,
+ struct fb_info *fbi)
+{
+ struct ipuv3_fb_platform_data *plat_data = pdev->dev.platform_data;
+ struct mxcfb_info *mxcfbi = (struct mxcfb_info *)fbi->par;
+ struct mxc_dispdrv_setting setting;
+ char disp_dev[32], *default_dev = "lcd";
+ int ret = 0;
+
+ setting.if_fmt = plat_data->interface_pix_fmt;
+ setting.dft_mode_str = plat_data->mode_str;
+ setting.default_bpp = plat_data->default_bpp;
+ if (!setting.default_bpp)
+ setting.default_bpp = 16;
+ setting.fbi = fbi;
+ if (!strlen(plat_data->disp_dev)) {
+ memcpy(disp_dev, default_dev, strlen(default_dev));
+ disp_dev[strlen(default_dev)] = '\0';
+ } else {
+ memcpy(disp_dev, plat_data->disp_dev,
+ strlen(plat_data->disp_dev));
+ disp_dev[strlen(plat_data->disp_dev)] = '\0';
+ }
+
+ mxcfbi->dispdrv = mxc_dispdrv_gethandle(disp_dev, &setting);
+ if (IS_ERR(mxcfbi->dispdrv)) {
+ ret = PTR_ERR(mxcfbi->dispdrv);
+ dev_err(&pdev->dev, "NO mxc display driver found!\n");
+ return ret;
+ } else {
+ /* fix-up */
+ mxcfbi->ipu_di_pix_fmt = setting.if_fmt;
+ mxcfbi->default_bpp = setting.default_bpp;
+
+ ret = mxcfb_get_crtc(&pdev->dev, mxcfbi, setting.crtc);
+ if (ret)
+ return ret;
+
+ dev_dbg(&pdev->dev, "di_pixfmt:0x%x, bpp:0x%x, di:%d, ipu:%d\n",
+ setting.if_fmt, setting.default_bpp,
+ mxcfbi->ipu_di, mxcfbi->ipu_id);
+ }
+
+ dev_info(&pdev->dev, "registered mxc display driver %s\n", disp_dev);
+
+ return ret;
+}
+
+/*
+ * Parse user specified options (`video=trident:')
+ * example:
+ * video=mxcfb0:dev=lcd,800x480M-16@55,if=RGB565,bpp=16,noaccel
+ * video=mxcfb0:dev=lcd,800x480M-16@55,if=RGB565,fbpix=RGB565
+ */
+static int mxcfb_option_setup(struct platform_device *pdev, struct fb_info *fbi)
+{
+ struct ipuv3_fb_platform_data *pdata = pdev->dev.platform_data;
+ char *options, *opt, *fb_mode_str = NULL;
+ char name[] = "mxcfb0";
+ uint32_t fb_pix_fmt = 0;
+
+ name[5] += pdev->id;
+ if (fb_get_options(name, &options)) {
+ dev_err(&pdev->dev, "Can't get fb option for %s!\n", name);
+ return -ENODEV;
+ }
+
+ if (!options || !*options)
+ return 0;
+
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+
+ if (!strncmp(opt, "dev=", 4)) {
+ memcpy(pdata->disp_dev, opt + 4, strlen(opt) - 4);
+ pdata->disp_dev[strlen(opt) - 4] = '\0';
+ } else if (!strncmp(opt, "if=", 3)) {
+ if (!strncmp(opt+3, "RGB24", 5))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_RGB24;
+ else if (!strncmp(opt+3, "BGR24", 5))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_BGR24;
+ else if (!strncmp(opt+3, "GBR24", 5))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_GBR24;
+ else if (!strncmp(opt+3, "RGB565", 6))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_RGB565;
+ else if (!strncmp(opt+3, "RGB666", 6))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_RGB666;
+ else if (!strncmp(opt+3, "YUV444", 6))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_YUV444;
+ else if (!strncmp(opt+3, "LVDS666", 7))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_LVDS666;
+ else if (!strncmp(opt+3, "YUYV16", 6))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_YUYV;
+ else if (!strncmp(opt+3, "UYVY16", 6))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_UYVY;
+ else if (!strncmp(opt+3, "YVYU16", 6))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_YVYU;
+ else if (!strncmp(opt+3, "VYUY16", 6))
+ pdata->interface_pix_fmt = IPU_PIX_FMT_VYUY;
+ } else if (!strncmp(opt, "fbpix=", 6)) {
+ if (!strncmp(opt+6, "RGB24", 5))
+ fb_pix_fmt = IPU_PIX_FMT_RGB24;
+ else if (!strncmp(opt+6, "BGR24", 5))
+ fb_pix_fmt = IPU_PIX_FMT_BGR24;
+ else if (!strncmp(opt+6, "RGB32", 5))
+ fb_pix_fmt = IPU_PIX_FMT_RGB32;
+ else if (!strncmp(opt+6, "BGR32", 5))
+ fb_pix_fmt = IPU_PIX_FMT_BGR32;
+ else if (!strncmp(opt+6, "ABGR32", 6))
+ fb_pix_fmt = IPU_PIX_FMT_ABGR32;
+ else if (!strncmp(opt+6, "RGB565", 6))
+ fb_pix_fmt = IPU_PIX_FMT_RGB565;
+ else if (!strncmp(opt+6, "BGRA4444", 8))
+ fb_pix_fmt = IPU_PIX_FMT_BGRA4444;
+ else if (!strncmp(opt+6, "BGRA5551", 8))
+ fb_pix_fmt = IPU_PIX_FMT_BGRA5551;
+
+ if (fb_pix_fmt) {
+ pixfmt_to_var(fb_pix_fmt, &fbi->var);
+ pdata->default_bpp =
+ fbi->var.bits_per_pixel;
+ }
+ } else if (!strncmp(opt, "int_clk", 7)) {
+ pdata->int_clk = true;
+ continue;
+ } else if (!strncmp(opt, "bpp=", 4)) {
+ /* bpp setting cannot overwirte fbpix setting */
+ if (fb_pix_fmt)
+ continue;
+
+ pdata->default_bpp =
+ simple_strtoul(opt + 4, NULL, 0);
+
+ fb_pix_fmt = bpp_to_pixfmt(pdata->default_bpp);
+ if (fb_pix_fmt)
+ pixfmt_to_var(fb_pix_fmt, &fbi->var);
+ } else
+ fb_mode_str = opt;
+ }
+
+ if (fb_mode_str)
+ pdata->mode_str = fb_mode_str;
+
+ return 0;
+}
+
+static int mxcfb_register(struct fb_info *fbi)
+{
+ struct mxcfb_info *mxcfbi = (struct mxcfb_info *)fbi->par;
+ struct fb_videomode m;
+ int ret = 0;
+ char bg0_id[] = "DISP3 BG";
+ char bg1_id[] = "DISP3 BG - DI1";
+ char fg_id[] = "DISP3 FG";
+
+ if (mxcfbi->ipu_di == 0) {
+ bg0_id[4] += mxcfbi->ipu_id;
+ strcpy(fbi->fix.id, bg0_id);
+ } else if (mxcfbi->ipu_di == 1) {
+ bg1_id[4] += mxcfbi->ipu_id;
+ strcpy(fbi->fix.id, bg1_id);
+ } else { /* Overlay */
+ fg_id[4] += mxcfbi->ipu_id;
+ strcpy(fbi->fix.id, fg_id);
+ }
+
+ mxcfb_check_var(&fbi->var, fbi);
+
+ mxcfb_set_fix(fbi);
+
+ /* Added first mode to fbi modelist. */
+ if (!fbi->modelist.next || !fbi->modelist.prev)
+ INIT_LIST_HEAD(&fbi->modelist);
+ fb_var_to_videomode(&m, &fbi->var);
+ fb_add_videomode(&m, &fbi->modelist);
+
+ if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq,
+ mxcfb_irq_handler, IPU_IRQF_ONESHOT, MXCFB_NAME, fbi) != 0) {
+ dev_err(fbi->device, "Error registering EOF irq handler.\n");
+ ret = -EBUSY;
+ goto err0;
+ }
+ ipu_disable_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq);
+ if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq,
+ mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT, MXCFB_NAME, fbi) != 0) {
+ dev_err(fbi->device, "Error registering NFACK irq handler.\n");
+ ret = -EBUSY;
+ goto err1;
+ }
+ ipu_disable_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq);
+
+ if (mxcfbi->ipu_alp_ch_irq != -1)
+ if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq,
+ mxcfb_alpha_irq_handler, IPU_IRQF_ONESHOT,
+ MXCFB_NAME, fbi) != 0) {
+ dev_err(fbi->device, "Error registering alpha irq "
+ "handler.\n");
+ ret = -EBUSY;
+ goto err2;
+ }
+
+ if (!mxcfbi->late_init) {
+ fbi->var.activate |= FB_ACTIVATE_FORCE;
+ console_lock();
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ ret = fb_set_var(fbi, &fbi->var);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+ if (ret < 0) {
+ dev_err(fbi->device, "Error fb_set_var ret:%d\n", ret);
+ goto err3;
+ }
+
+ if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
+ console_lock();
+ ret = fb_blank(fbi, FB_BLANK_UNBLANK);
+ console_unlock();
+ if (ret < 0) {
+ dev_err(fbi->device,
+ "Error fb_blank ret:%d\n", ret);
+ goto err4;
+ }
+ }
+ } else {
+ /*
+ * Setup the channel again though bootloader
+ * has done this, then set_par() can stop the
+ * channel neatly and re-initialize it .
+ */
+ if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
+ console_lock();
+ _setup_disp_channel1(fbi);
+ ipu_enable_channel(mxcfbi->ipu, mxcfbi->ipu_ch);
+ console_unlock();
+ }
+ }
+
+
+ ret = register_framebuffer(fbi);
+ if (ret < 0)
+ goto err5;
+
+ return ret;
+err5:
+ if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
+ console_lock();
+ if (!mxcfbi->late_init)
+ fb_blank(fbi, FB_BLANK_POWERDOWN);
+ else {
+ ipu_disable_channel(mxcfbi->ipu, mxcfbi->ipu_ch,
+ true);
+ ipu_uninit_channel(mxcfbi->ipu, mxcfbi->ipu_ch);
+ }
+ console_unlock();
+ }
+err4:
+err3:
+ if (mxcfbi->ipu_alp_ch_irq != -1)
+ ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq, fbi);
+err2:
+ ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, fbi);
+err1:
+ ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, fbi);
+err0:
+ return ret;
+}
+
+static void mxcfb_unregister(struct fb_info *fbi)
+{
+ struct mxcfb_info *mxcfbi = (struct mxcfb_info *)fbi->par;
+
+ if (mxcfbi->ipu_alp_ch_irq != -1)
+ ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq, fbi);
+ if (mxcfbi->ipu_ch_irq)
+ ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, fbi);
+ if (mxcfbi->ipu_ch_nf_irq)
+ ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, fbi);
+
+ unregister_framebuffer(fbi);
+}
+
+static int mxcfb_setup_overlay(struct platform_device *pdev,
+ struct fb_info *fbi_bg, struct resource *res)
+{
+ struct fb_info *ovfbi;
+ struct mxcfb_info *mxcfbi_bg = (struct mxcfb_info *)fbi_bg->par;
+ struct mxcfb_info *mxcfbi_fg;
+ int ret = 0;
+
+ ovfbi = mxcfb_init_fbinfo(&pdev->dev, &mxcfb_ops);
+ if (!ovfbi) {
+ ret = -ENOMEM;
+ goto init_ovfbinfo_failed;
+ }
+ mxcfbi_fg = (struct mxcfb_info *)ovfbi->par;
+
+ mxcfbi_fg->ipu = ipu_get_soc(mxcfbi_bg->ipu_id);
+ if (IS_ERR(mxcfbi_fg->ipu)) {
+ ret = -ENODEV;
+ goto get_ipu_failed;
+ }
+ mxcfbi_fg->ipu_id = mxcfbi_bg->ipu_id;
+ mxcfbi_fg->ipu_ch_irq = IPU_IRQ_FG_SYNC_EOF;
+ mxcfbi_fg->ipu_ch_nf_irq = IPU_IRQ_FG_SYNC_NFACK;
+ mxcfbi_fg->ipu_alp_ch_irq = IPU_IRQ_FG_ALPHA_SYNC_EOF;
+ mxcfbi_fg->ipu_ch = MEM_FG_SYNC;
+ mxcfbi_fg->ipu_di = -1;
+ mxcfbi_fg->ipu_di_pix_fmt = mxcfbi_bg->ipu_di_pix_fmt;
+ mxcfbi_fg->overlay = true;
+ mxcfbi_fg->cur_blank = mxcfbi_fg->next_blank = FB_BLANK_POWERDOWN;
+ mxcfbi_fg->prefetch = false;
+ mxcfbi_fg->resolve = false;
+ mxcfbi_fg->pre_num = -1;
+
+ /* Need dummy values until real panel is configured */
+ ovfbi->var.xres = 240;
+ ovfbi->var.yres = 320;
+
+ if (res && res->start && res->end) {
+ ovfbi->fix.smem_len = res->end - res->start + 1;
+ ovfbi->fix.smem_start = res->start;
+ ovfbi->screen_base = ioremap(
+ ovfbi->fix.smem_start,
+ ovfbi->fix.smem_len);
+ }
+
+ ret = mxcfb_register(ovfbi);
+ if (ret < 0)
+ goto register_ov_failed;
+
+ mxcfbi_bg->ovfbi = ovfbi;
+
+ return ret;
+
+register_ov_failed:
+get_ipu_failed:
+ fb_dealloc_cmap(&ovfbi->cmap);
+ framebuffer_release(ovfbi);
+init_ovfbinfo_failed:
+ return ret;
+}
+
+static void mxcfb_unsetup_overlay(struct fb_info *fbi_bg)
+{
+ struct mxcfb_info *mxcfbi_bg = (struct mxcfb_info *)fbi_bg->par;
+ struct fb_info *ovfbi = mxcfbi_bg->ovfbi;
+
+ mxcfb_unregister(ovfbi);
+
+ if (&ovfbi->cmap)
+ fb_dealloc_cmap(&ovfbi->cmap);
+ framebuffer_release(ovfbi);
+}
+
+static bool ipu_usage[2][2];
+static int ipu_test_set_usage(int ipu, int di)
+{
+ if (ipu_usage[ipu][di])
+ return -EBUSY;
+ else
+ ipu_usage[ipu][di] = true;
+ return 0;
+}
+
+static void ipu_clear_usage(int ipu, int di)
+{
+ ipu_usage[ipu][di] = false;
+}
+
+static int mxcfb_get_of_property(struct platform_device *pdev,
+ struct ipuv3_fb_platform_data *plat_data)
+{
+ struct device_node *np = pdev->dev.of_node;
+ const char *disp_dev;
+ const char *mode_str = NULL;
+ const char *pixfmt;
+ int err;
+ int len;
+ u32 bpp, int_clk;
+ u32 late_init;
+
+ err = of_property_read_string(np, "disp_dev", &disp_dev);
+ if (err < 0) {
+ dev_dbg(&pdev->dev, "get of property disp_dev fail\n");
+ return err;
+ }
+ err = of_property_read_string(np, "mode_str", &mode_str);
+ if (err < 0)
+ dev_dbg(&pdev->dev, "get of property mode_str fail\n");
+ err = of_property_read_string(np, "interface_pix_fmt", &pixfmt);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property pix fmt fail\n");
+ return err;
+ }
+ err = of_property_read_u32(np, "default_bpp", &bpp);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property bpp fail\n");
+ return err;
+ }
+ err = of_property_read_u32(np, "int_clk", &int_clk);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property int_clk fail\n");
+ return err;
+ }
+ err = of_property_read_u32(np, "late_init", &late_init);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property late_init fail\n");
+ return err;
+ }
+
+ plat_data->prefetch = of_property_read_bool(np, "prefetch");
+
+ if (!strncmp(pixfmt, "RGB24", 5))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB24;
+ else if (!strncmp(pixfmt, "BGR24", 5))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_BGR24;
+ else if (!strncmp(pixfmt, "GBR24", 5))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_GBR24;
+ else if (!strncmp(pixfmt, "RGB565", 6))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB565;
+ else if (!strncmp(pixfmt, "RGB666", 6))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB666;
+ else if (!strncmp(pixfmt, "YUV444", 6))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_YUV444;
+ else if (!strncmp(pixfmt, "LVDS666", 7))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_LVDS666;
+ else if (!strncmp(pixfmt, "YUYV16", 6))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_YUYV;
+ else if (!strncmp(pixfmt, "UYVY16", 6))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_UYVY;
+ else if (!strncmp(pixfmt, "YVYU16", 6))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_YVYU;
+ else if (!strncmp(pixfmt, "VYUY16", 6))
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_VYUY;
+ else {
+ dev_err(&pdev->dev, "err interface_pix_fmt!\n");
+ return -ENOENT;
+ }
+
+ len = min(sizeof(plat_data->disp_dev) - 1, strlen(disp_dev));
+ memcpy(plat_data->disp_dev, disp_dev, len);
+ plat_data->disp_dev[len] = '\0';
+ plat_data->mode_str = (char *)mode_str;
+ plat_data->default_bpp = bpp;
+ plat_data->int_clk = (bool)int_clk;
+ plat_data->late_init = (bool)late_init;
+ return err;
+}
+
+/*!
+ * Probe routine for the framebuffer driver. It is called during the
+ * driver binding process. The following functions are performed in
+ * this routine: Framebuffer initialization, Memory allocation and
+ * mapping, Framebuffer registration, IPU initialization.
+ *
+ * @return Appropriate error code to the kernel common code
+ */
+static int mxcfb_probe(struct platform_device *pdev)
+{
+ struct ipuv3_fb_platform_data *plat_data;
+ struct fb_info *fbi;
+ struct mxcfb_info *mxcfbi;
+ struct resource *res;
+ int ret = 0;
+
+ dev_dbg(&pdev->dev, "%s enter\n", __func__);
+ pdev->id = of_alias_get_id(pdev->dev.of_node, "mxcfb");
+ if (pdev->id < 0) {
+ dev_err(&pdev->dev, "can not get alias id\n");
+ return pdev->id;
+ }
+
+ plat_data = devm_kzalloc(&pdev->dev, sizeof(struct
+ ipuv3_fb_platform_data), GFP_KERNEL);
+ if (!plat_data)
+ return -ENOMEM;
+ pdev->dev.platform_data = plat_data;
+
+ ret = mxcfb_get_of_property(pdev, plat_data);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "get mxcfb of property fail\n");
+ return ret;
+ }
+
+ /* Initialize FB structures */
+ fbi = mxcfb_init_fbinfo(&pdev->dev, &mxcfb_ops);
+ if (!fbi) {
+ ret = -ENOMEM;
+ goto init_fbinfo_failed;
+ }
+
+ ret = mxcfb_option_setup(pdev, fbi);
+ if (ret)
+ goto get_fb_option_failed;
+
+ mxcfbi = (struct mxcfb_info *)fbi->par;
+ mxcfbi->ipu_int_clk = plat_data->int_clk;
+ mxcfbi->late_init = plat_data->late_init;
+ mxcfbi->first_set_par = true;
+ mxcfbi->prefetch = plat_data->prefetch;
+ mxcfbi->pre_num = -1;
+ spin_lock_init(&mxcfbi->spin_lock);
+
+ ret = mxcfb_dispdrv_init(pdev, fbi);
+ if (ret < 0)
+ goto init_dispdrv_failed;
+
+ ret = ipu_test_set_usage(mxcfbi->ipu_id, mxcfbi->ipu_di);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "ipu%d-di%d already in use\n",
+ mxcfbi->ipu_id, mxcfbi->ipu_di);
+ goto ipu_in_busy;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res && res->start && res->end) {
+ fbi->fix.smem_len = res->end - res->start + 1;
+ fbi->fix.smem_start = res->start;
+ fbi->screen_base = ioremap(fbi->fix.smem_start, fbi->fix.smem_len);
+ /* Do not clear the fb content drawn in bootloader. */
+ if (!mxcfbi->late_init)
+ memset(fbi->screen_base, 0, fbi->fix.smem_len);
+ }
+
+ mxcfbi->ipu = ipu_get_soc(mxcfbi->ipu_id);
+ if (IS_ERR(mxcfbi->ipu)) {
+ ret = -ENODEV;
+ goto get_ipu_failed;
+ }
+
+ /* first user uses DP with alpha feature */
+ if (!g_dp_in_use[mxcfbi->ipu_id]) {
+ mxcfbi->ipu_ch_irq = IPU_IRQ_BG_SYNC_EOF;
+ mxcfbi->ipu_ch_nf_irq = IPU_IRQ_BG_SYNC_NFACK;
+ mxcfbi->ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
+ mxcfbi->ipu_ch = MEM_BG_SYNC;
+ /* Unblank the primary fb only by default */
+ if (pdev->id == 0)
+ mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_UNBLANK;
+ else
+ mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;
+
+ ret = mxcfb_register(fbi);
+ if (ret < 0)
+ goto mxcfb_register_failed;
+
+ ipu_disp_set_global_alpha(mxcfbi->ipu, mxcfbi->ipu_ch,
+ true, 0x80);
+ ipu_disp_set_color_key(mxcfbi->ipu, mxcfbi->ipu_ch, false, 0);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ ret = mxcfb_setup_overlay(pdev, fbi, res);
+
+ if (ret < 0) {
+ mxcfb_unregister(fbi);
+ goto mxcfb_setupoverlay_failed;
+ }
+
+ g_dp_in_use[mxcfbi->ipu_id] = true;
+
+ ret = device_create_file(mxcfbi->ovfbi->dev,
+ &dev_attr_fsl_disp_property);
+ if (ret)
+ dev_err(mxcfbi->ovfbi->dev, "Error %d on creating "
+ "file for disp property\n",
+ ret);
+
+ ret = device_create_file(mxcfbi->ovfbi->dev,
+ &dev_attr_fsl_disp_dev_property);
+ if (ret)
+ dev_err(mxcfbi->ovfbi->dev, "Error %d on creating "
+ "file for disp device "
+ "propety\n", ret);
+ } else {
+ mxcfbi->ipu_ch_irq = IPU_IRQ_DC_SYNC_EOF;
+ mxcfbi->ipu_ch_nf_irq = IPU_IRQ_DC_SYNC_NFACK;
+ mxcfbi->ipu_alp_ch_irq = -1;
+ mxcfbi->ipu_ch = MEM_DC_SYNC;
+ mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;
+
+ ret = mxcfb_register(fbi);
+ if (ret < 0)
+ goto mxcfb_register_failed;
+ }
+
+ platform_set_drvdata(pdev, fbi);
+
+ ret = device_create_file(fbi->dev, &dev_attr_fsl_disp_property);
+ if (ret)
+ dev_err(&pdev->dev, "Error %d on creating file for disp "
+ "property\n", ret);
+
+ ret = device_create_file(fbi->dev, &dev_attr_fsl_disp_dev_property);
+ if (ret)
+ dev_err(&pdev->dev, "Error %d on creating file for disp "
+ " device propety\n", ret);
+
+ return 0;
+
+mxcfb_setupoverlay_failed:
+mxcfb_register_failed:
+get_ipu_failed:
+ ipu_clear_usage(mxcfbi->ipu_id, mxcfbi->ipu_di);
+ipu_in_busy:
+init_dispdrv_failed:
+ fb_dealloc_cmap(&fbi->cmap);
+ framebuffer_release(fbi);
+get_fb_option_failed:
+init_fbinfo_failed:
+ return ret;
+}
+
+static int mxcfb_remove(struct platform_device *pdev)
+{
+ struct fb_info *fbi = platform_get_drvdata(pdev);
+ struct mxcfb_info *mxc_fbi = fbi->par;
+
+ device_remove_file(fbi->dev, &dev_attr_fsl_disp_dev_property);
+ device_remove_file(fbi->dev, &dev_attr_fsl_disp_property);
+ mxcfb_blank(FB_BLANK_POWERDOWN, fbi);
+ mxcfb_unregister(fbi);
+ mxcfb_unmap_video_memory(fbi);
+
+ if (mxc_fbi->ovfbi) {
+ device_remove_file(mxc_fbi->ovfbi->dev,
+ &dev_attr_fsl_disp_dev_property);
+ device_remove_file(mxc_fbi->ovfbi->dev,
+ &dev_attr_fsl_disp_property);
+ mxcfb_blank(FB_BLANK_POWERDOWN, mxc_fbi->ovfbi);
+ mxcfb_unsetup_overlay(fbi);
+ mxcfb_unmap_video_memory(mxc_fbi->ovfbi);
+ }
+
+ ipu_clear_usage(mxc_fbi->ipu_id, mxc_fbi->ipu_di);
+ if (&fbi->cmap)
+ fb_dealloc_cmap(&fbi->cmap);
+ framebuffer_release(fbi);
+ return 0;
+}
+
+static const struct of_device_id imx_mxcfb_dt_ids[] = {
+ { .compatible = "fsl,mxc_sdc_fb"},
+ { /* sentinel */ }
+};
+
+/*!
+ * This structure contains pointers to the power management callback functions.
+ */
+static struct platform_driver mxcfb_driver = {
+ .driver = {
+ .name = MXCFB_NAME,
+ .of_match_table = imx_mxcfb_dt_ids,
+ },
+ .probe = mxcfb_probe,
+ .remove = mxcfb_remove,
+ .suspend = mxcfb_suspend,
+ .resume = mxcfb_resume,
+};
+
+/*!
+ * Main entry function for the framebuffer. The function registers the power
+ * management callback functions with the kernel and also registers the MXCFB
+ * callback functions with the core Linux framebuffer driver \b fbmem.c
+ *
+ * @return Error code indicating success or failure
+ */
+int __init mxcfb_init(void)
+{
+ return platform_driver_register(&mxcfb_driver);
+}
+
+void mxcfb_exit(void)
+{
+ platform_driver_unregister(&mxcfb_driver);
+}
+
+module_init(mxcfb_init);
+module_exit(mxcfb_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC framebuffer driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("fb");
diff --git a/drivers/video/fbdev/mxc/mxc_lcdif.c b/drivers/video/fbdev/mxc/mxc_lcdif.c
new file mode 100644
index 000000000000..59d429c82017
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_lcdif.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2011-2015 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
+ */
+
+#include <linux/init.h>
+#include <linux/ipu.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+
+#include "mxc_dispdrv.h"
+
+struct mxc_lcd_platform_data {
+ u32 default_ifmt;
+ u32 ipu_id;
+ u32 disp_id;
+};
+
+struct mxc_lcdif_data {
+ struct platform_device *pdev;
+ struct mxc_dispdrv_handle *disp_lcdif;
+};
+
+#define DISPDRV_LCD "lcd"
+
+static struct fb_videomode lcdif_modedb[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 27MHz */
+ "CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ /* 800x480 @ 60 Hz , pixel clk @ 32MHz */
+ "SEIKO-WVGA", 60, 800, 480, 29850, 89, 164, 23, 10, 10, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+static int lcdif_modedb_sz = ARRAY_SIZE(lcdif_modedb);
+
+static int lcdif_init(struct mxc_dispdrv_handle *disp,
+ struct mxc_dispdrv_setting *setting)
+{
+ int ret, i;
+ struct mxc_lcdif_data *lcdif = mxc_dispdrv_getdata(disp);
+ struct device *dev = &lcdif->pdev->dev;
+ struct mxc_lcd_platform_data *plat_data = dev->platform_data;
+ struct fb_videomode *modedb = lcdif_modedb;
+ int modedb_sz = lcdif_modedb_sz;
+
+ /* use platform defined ipu/di */
+ ret = ipu_di_to_crtc(dev, plat_data->ipu_id,
+ plat_data->disp_id, &setting->crtc);
+ if (ret < 0)
+ return ret;
+
+ ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str,
+ modedb, modedb_sz, NULL, setting->default_bpp);
+ if (!ret) {
+ fb_videomode_to_var(&setting->fbi->var, &modedb[0]);
+ setting->if_fmt = plat_data->default_ifmt;
+ }
+
+ INIT_LIST_HEAD(&setting->fbi->modelist);
+ for (i = 0; i < modedb_sz; i++) {
+ struct fb_videomode m;
+ fb_var_to_videomode(&m, &setting->fbi->var);
+ if (fb_mode_is_equal(&m, &modedb[i])) {
+ fb_add_videomode(&modedb[i],
+ &setting->fbi->modelist);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void lcdif_deinit(struct mxc_dispdrv_handle *disp)
+{
+ /*TODO*/
+}
+
+static struct mxc_dispdrv_driver lcdif_drv = {
+ .name = DISPDRV_LCD,
+ .init = lcdif_init,
+ .deinit = lcdif_deinit,
+};
+
+static int lcd_get_of_property(struct platform_device *pdev,
+ struct mxc_lcd_platform_data *plat_data)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int err;
+ u32 ipu_id, disp_id;
+ const char *default_ifmt;
+
+ err = of_property_read_string(np, "default_ifmt", &default_ifmt);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property default_ifmt fail\n");
+ return err;
+ }
+ err = of_property_read_u32(np, "ipu_id", &ipu_id);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property ipu_id fail\n");
+ return err;
+ }
+ err = of_property_read_u32(np, "disp_id", &disp_id);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property disp_id fail\n");
+ return err;
+ }
+
+ plat_data->ipu_id = ipu_id;
+ plat_data->disp_id = disp_id;
+ if (!strncmp(default_ifmt, "RGB24", 5))
+ plat_data->default_ifmt = IPU_PIX_FMT_RGB24;
+ else if (!strncmp(default_ifmt, "BGR24", 5))
+ plat_data->default_ifmt = IPU_PIX_FMT_BGR24;
+ else if (!strncmp(default_ifmt, "GBR24", 5))
+ plat_data->default_ifmt = IPU_PIX_FMT_GBR24;
+ else if (!strncmp(default_ifmt, "RGB565", 6))
+ plat_data->default_ifmt = IPU_PIX_FMT_RGB565;
+ else if (!strncmp(default_ifmt, "RGB666", 6))
+ plat_data->default_ifmt = IPU_PIX_FMT_RGB666;
+ else if (!strncmp(default_ifmt, "YUV444", 6))
+ plat_data->default_ifmt = IPU_PIX_FMT_YUV444;
+ else if (!strncmp(default_ifmt, "LVDS666", 7))
+ plat_data->default_ifmt = IPU_PIX_FMT_LVDS666;
+ else if (!strncmp(default_ifmt, "YUYV16", 6))
+ plat_data->default_ifmt = IPU_PIX_FMT_YUYV;
+ else if (!strncmp(default_ifmt, "UYVY16", 6))
+ plat_data->default_ifmt = IPU_PIX_FMT_UYVY;
+ else if (!strncmp(default_ifmt, "YVYU16", 6))
+ plat_data->default_ifmt = IPU_PIX_FMT_YVYU;
+ else if (!strncmp(default_ifmt, "VYUY16", 6))
+ plat_data->default_ifmt = IPU_PIX_FMT_VYUY;
+ else {
+ dev_err(&pdev->dev, "err default_ifmt!\n");
+ return -ENOENT;
+ }
+
+ return err;
+}
+
+static int mxc_lcdif_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct pinctrl *pinctrl;
+ struct mxc_lcdif_data *lcdif;
+ struct mxc_lcd_platform_data *plat_data;
+
+ dev_dbg(&pdev->dev, "%s enter\n", __func__);
+ lcdif = devm_kzalloc(&pdev->dev, sizeof(struct mxc_lcdif_data),
+ GFP_KERNEL);
+ if (!lcdif)
+ return -ENOMEM;
+ plat_data = devm_kzalloc(&pdev->dev,
+ sizeof(struct mxc_lcd_platform_data),
+ GFP_KERNEL);
+ if (!plat_data)
+ return -ENOMEM;
+ pdev->dev.platform_data = plat_data;
+
+ ret = lcd_get_of_property(pdev, plat_data);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "get lcd of property fail\n");
+ return ret;
+ }
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(&pdev->dev, "can't get/select pinctrl\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ lcdif->pdev = pdev;
+ lcdif->disp_lcdif = mxc_dispdrv_register(&lcdif_drv);
+ mxc_dispdrv_setdata(lcdif->disp_lcdif, lcdif);
+
+ dev_set_drvdata(&pdev->dev, lcdif);
+ dev_dbg(&pdev->dev, "%s exit\n", __func__);
+
+ return ret;
+}
+
+static int mxc_lcdif_remove(struct platform_device *pdev)
+{
+ struct mxc_lcdif_data *lcdif = dev_get_drvdata(&pdev->dev);
+
+ mxc_dispdrv_puthandle(lcdif->disp_lcdif);
+ mxc_dispdrv_unregister(lcdif->disp_lcdif);
+ kfree(lcdif);
+ return 0;
+}
+
+static const struct of_device_id imx_lcd_dt_ids[] = {
+ { .compatible = "fsl,lcd"},
+ { /* sentinel */ }
+};
+static struct platform_driver mxc_lcdif_driver = {
+ .driver = {
+ .name = "mxc_lcdif",
+ .of_match_table = imx_lcd_dt_ids,
+ },
+ .probe = mxc_lcdif_probe,
+ .remove = mxc_lcdif_remove,
+};
+
+static int __init mxc_lcdif_init(void)
+{
+ return platform_driver_register(&mxc_lcdif_driver);
+}
+
+static void __exit mxc_lcdif_exit(void)
+{
+ platform_driver_unregister(&mxc_lcdif_driver);
+}
+
+module_init(mxc_lcdif_init);
+module_exit(mxc_lcdif_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX ipuv3 LCD extern port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c b/drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c
new file mode 100644
index 000000000000..155e8491d765
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c
@@ -0,0 +1,220 @@
+/*
+ * 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.
+
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/mipi_dsi.h>
+#include <linux/mxcfb.h>
+#include <linux/backlight.h>
+#include <video/mipi_display.h>
+
+#include "mipi_dsi.h"
+
+#define HX8363_TWO_DATA_LANE (0x2)
+#define HX8363_MAX_DPHY_CLK (800)
+#define HX8363_CMD_GETHXID (0xF4)
+#define HX8363_CMD_GETHXID_LEN (0x4)
+#define HX8363_ID (0x84)
+#define HX8363_ID_MASK (0xFF)
+
+
+#define CHECK_RETCODE(ret) \
+do { \
+ if (ret < 0) { \
+ dev_err(&mipi_dsi->pdev->dev, \
+ "%s ERR: ret:%d, line:%d.\n", \
+ __func__, ret, __LINE__); \
+ return ret; \
+ } \
+} while (0)
+
+static void parse_variadic(int n, u8 *buf, ...)
+{
+ int i = 0;
+ va_list args;
+
+ if (unlikely(!n)) return;
+
+ va_start(args, buf);
+
+ for (i = 0; i < n; i++)
+ buf[i + 1] = (u8)va_arg(args, int);
+
+ va_end(args);
+}
+
+#define TC358763_DCS_write_1A_nP(n, addr, ...) { \
+ int err; \
+ \
+ buf[0] = addr; \
+ parse_variadic(n, buf, ##__VA_ARGS__); \
+ \
+ if (n >= 2) \
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, \
+ MIPI_DSI_DCS_LONG_WRITE, (u32*)buf, n + 1); \
+ else if (n == 1) \
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, \
+ MIPI_DSI_DCS_SHORT_WRITE_PARAM, (u32*)buf, 0); \
+ else if (n == 0) \
+ { \
+ buf[1] = 0; \
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, \
+ MIPI_DSI_DCS_SHORT_WRITE, (u32*)buf, 0); \
+ } \
+ CHECK_RETCODE(err); \
+}
+
+#define TC358763_DCS_write_1A_0P(addr) \
+ TC358763_DCS_write_1A_nP(0, addr)
+
+#define TC358763_DCS_write_1A_1P(addr, ...) \
+ TC358763_DCS_write_1A_nP(1, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_2P(addr, ...) \
+ TC358763_DCS_write_1A_nP(2, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_3P(addr, ...) \
+ TC358763_DCS_write_1A_nP(3, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_5P(addr, ...) \
+ TC358763_DCS_write_1A_nP(5, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_6P(addr, ...) \
+ TC358763_DCS_write_1A_nP(6, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_7P(addr, ...) \
+ TC358763_DCS_write_1A_nP(7, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_12P(addr, ...) \
+ TC358763_DCS_write_1A_nP(12, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_13P(addr, ...) \
+ TC358763_DCS_write_1A_nP(13, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_14P(addr, ...) \
+ TC358763_DCS_write_1A_nP(14, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_19P(addr, ...) \
+ TC358763_DCS_write_1A_nP(19, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_34P(addr, ...) \
+ TC358763_DCS_write_1A_nP(34, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_127P(addr, ...) \
+ TC358763_DCS_write_1A_nP(127, addr, __VA_ARGS__)
+
+static int hx8363bl_brightness;
+
+#define ACTIVE_HIGH_NAME "TRUULY-WVGA-SYNC-HIGH"
+#define ACTIVE_LOW_NAME "TRUULY-WVGA-SYNC-LOW"
+
+static struct fb_videomode truly_lcd_modedb[] = {
+ {
+ ACTIVE_HIGH_NAME, 50, 480, 854, 41042,
+ 40, 60,
+ 3, 3,
+ 8, 4,
+ 0x0,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ }, {
+ ACTIVE_LOW_NAME, 50, 480, 854, 41042,
+ 40, 60,
+ 3, 3,
+ 8, 4,
+ FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ },
+};
+
+static struct mipi_lcd_config lcd_config = {
+ .virtual_ch = 0x0,
+ .data_lane_num = HX8363_TWO_DATA_LANE,
+ .max_phy_clk = HX8363_MAX_DPHY_CLK,
+ .dpi_fmt = MIPI_RGB888,
+};
+
+void mipid_hx8363_get_lcd_videomode(struct fb_videomode **mode, int *size,
+ struct mipi_lcd_config **data)
+{
+ *mode = &truly_lcd_modedb[0];
+ *size = ARRAY_SIZE(truly_lcd_modedb);
+ *data = &lcd_config;
+}
+
+int mipid_hx8363_lcd_setup(struct mipi_dsi_info *mipi_dsi)
+{
+ u8 buf[DSI_CMD_BUF_MAXSIZE];
+
+ dev_dbg(&mipi_dsi->pdev->dev, "MIPI DSI LCD HX8363 setup.\n");
+
+ TC358763_DCS_write_1A_3P(0xB9,0xFF,0x83,0x63);/* SET password */
+
+ TC358763_DCS_write_1A_19P(0xB1,0x01,0x00,0x44,0x08,0x01,0x10,0x10,0x36,
+ 0x3E,0x1A,0x1A,0x40,0x12,0x00,0xE6,0xE6,0xE6,0xE6,0xE6);/* Set Power */
+ TC358763_DCS_write_1A_2P(0xB2,0x08,0x03);/* Set DISP */
+ TC358763_DCS_write_1A_7P(0xB4,0x02,0x18,0x9C,0x08,0x18,0x04,0x6C);
+ TC358763_DCS_write_1A_1P(0xB6,0x00);/* Set VCOM */
+ TC358763_DCS_write_1A_1P(0xCC,0x0B);/* Set Panel */
+ TC358763_DCS_write_1A_34P(0xE0,0x0E,0x15,0x19,0x30,0x31,0x3F,0x27,0x3C,0x88,0x8F,0xD1,0xD5,0xD7,0x16,0x16,
+ 0x0C,0x1E,0x0E,0x15,0x19,0x30,0x31,0x3F,0x27,0x3C,0x88,0x8F,
+ 0xD1,0xD5,0xD7,0x16,0x16,0x0C,0x1E);
+ mdelay(5);
+
+ TC358763_DCS_write_1A_1P(0x3A,0x77);/* 24bit */
+ TC358763_DCS_write_1A_14P(0xBA,0x11,0x00,0x56,0xC6,0x10,0x89,0xFF,0x0F,0x32,0x6E,0x04,0x07,0x9A,0x92);
+ TC358763_DCS_write_1A_0P(0x21);
+
+ TC358763_DCS_write_1A_0P(0x11);
+ msleep(10);
+
+ TC358763_DCS_write_1A_0P(0x29);
+ msleep(120);
+
+ return 0;
+}
+
+static int mipid_bl_update_status(struct backlight_device *bl)
+{
+ return 0;
+}
+
+static int mipid_bl_get_brightness(struct backlight_device *bl)
+{
+ return hx8363bl_brightness;
+}
+
+static int mipi_bl_check_fb(struct backlight_device *bl, struct fb_info *fbi)
+{
+ return 0;
+}
+
+static const struct backlight_ops mipid_lcd_bl_ops = {
+ .update_status = mipid_bl_update_status,
+ .get_brightness = mipid_bl_get_brightness,
+ .check_fb = mipi_bl_check_fb,
+};
diff --git a/drivers/video/fbdev/mxc/mxcfb_hx8369_wvga.c b/drivers/video/fbdev/mxc/mxcfb_hx8369_wvga.c
new file mode 100644
index 000000000000..581eccad0dcd
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxcfb_hx8369_wvga.c
@@ -0,0 +1,451 @@
+/*
+ * 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.
+
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/mipi_dsi.h>
+#include <linux/mxcfb.h>
+#include <linux/backlight.h>
+#include <video/mipi_display.h>
+
+#include "mipi_dsi.h"
+
+#define MIPI_DSI_MAX_RET_PACK_SIZE (0x4)
+
+#define HX8369BL_MAX_BRIGHT (255)
+#define HX8369BL_DEF_BRIGHT (255)
+
+#define HX8369_MAX_DPHY_CLK (800)
+#define HX8369_ONE_DATA_LANE (0x1)
+#define HX8369_TWO_DATA_LANE (0x2)
+
+#define HX8369_CMD_SETEXTC (0xB9)
+#define HX8369_CMD_SETEXTC_LEN (0x4)
+#define HX8369_CMD_SETEXTC_PARAM_1 (0x6983ff)
+
+#define HX8369_CMD_GETHXID (0xF4)
+#define HX8369_CMD_GETHXID_LEN (0x4)
+#define HX8369_ID (0x69)
+#define HX8369_ID_MASK (0xFF)
+
+#define HX8369_CMD_SETDISP (0xB2)
+#define HX8369_CMD_SETDISP_LEN (16)
+#define HX8369_CMD_SETDISP_1_HALT (0x00)
+#define HX8369_CMD_SETDISP_2_RES_MODE (0x23)
+#define HX8369_CMD_SETDISP_3_BP (0x03)
+#define HX8369_CMD_SETDISP_4_FP (0x03)
+#define HX8369_CMD_SETDISP_5_SAP (0x70)
+#define HX8369_CMD_SETDISP_6_GENON (0x00)
+#define HX8369_CMD_SETDISP_7_GENOFF (0xff)
+#define HX8369_CMD_SETDISP_8_RTN (0x00)
+#define HX8369_CMD_SETDISP_9_TEI (0x00)
+#define HX8369_CMD_SETDISP_10_TEP_UP (0x00)
+#define HX8369_CMD_SETDISP_11_TEP_LOW (0x00)
+#define HX8369_CMD_SETDISP_12_BP_PE (0x03)
+#define HX8369_CMD_SETDISP_13_FP_PE (0x03)
+#define HX8369_CMD_SETDISP_14_RTN_PE (0x00)
+#define HX8369_CMD_SETDISP_15_GON (0x01)
+
+#define HX8369_CMD_SETCYC (0xB4)
+#define HX8369_CMD_SETCYC_LEN (6)
+#define HX8369_CMD_SETCYC_PARAM_1 (0x5f1d00)
+#define HX8369_CMD_SETCYC_PARAM_2 (0x060e)
+
+#define HX8369_CMD_SETGIP (0xD5)
+#define HX8369_CMD_SETGIP_LEN (27)
+#define HX8369_CMD_SETGIP_PARAM_1 (0x030400)
+#define HX8369_CMD_SETGIP_PARAM_2 (0x1c050100)
+#define HX8369_CMD_SETGIP_PARAM_3 (0x00030170)
+#define HX8369_CMD_SETGIP_PARAM_4 (0x51064000)
+#define HX8369_CMD_SETGIP_PARAM_5 (0x41000007)
+#define HX8369_CMD_SETGIP_PARAM_6 (0x07075006)
+#define HX8369_CMD_SETGIP_PARAM_7 (0x040f)
+
+#define HX8369_CMD_SETPOWER (0xB1)
+#define HX8369_CMD_SETPOWER_LEN (20)
+#define HX8369_CMD_SETPOWER_PARAM_1 (0x340001)
+#define HX8369_CMD_SETPOWER_PARAM_2 (0x0f0f0006)
+#define HX8369_CMD_SETPOWER_PARAM_3 (0x3f3f322a)
+#define HX8369_CMD_SETPOWER_PARAM_4 (0xe6013a07)
+#define HX8369_CMD_SETPOWER_PARAM_5 (0xe6e6e6e6)
+
+#define HX8369_CMD_SETVCOM (0xB6)
+#define HX8369_CMD_SETVCOM_LEN (3)
+#define HX8369_CMD_SETVCOM_PARAM_1 (0x5656)
+
+#define HX8369_CMD_SETPANEL (0xCC)
+#define HX8369_CMD_SETPANEL_PARAM_1 (0x02)
+
+#define HX8369_CMD_SETGAMMA (0xE0)
+#define HX8369_CMD_SETGAMMA_LEN (35)
+#define HX8369_CMD_SETGAMMA_PARAM_1 (0x221d00)
+#define HX8369_CMD_SETGAMMA_PARAM_2 (0x2e3f3d38)
+#define HX8369_CMD_SETGAMMA_PARAM_3 (0x0f0d064a)
+#define HX8369_CMD_SETGAMMA_PARAM_4 (0x16131513)
+#define HX8369_CMD_SETGAMMA_PARAM_5 (0x1d001910)
+#define HX8369_CMD_SETGAMMA_PARAM_6 (0x3f3d3822)
+#define HX8369_CMD_SETGAMMA_PARAM_7 (0x0d064a2e)
+#define HX8369_CMD_SETGAMMA_PARAM_8 (0x1315130f)
+#define HX8369_CMD_SETGAMMA_PARAM_9 (0x191016)
+
+#define HX8369_CMD_SETMIPI (0xBA)
+#define HX8369_CMD_SETMIPI_LEN (14)
+#define HX8369_CMD_SETMIPI_PARAM_1 (0xc6a000)
+#define HX8369_CMD_SETMIPI_PARAM_2 (0x10000a00)
+#define HX8369_CMD_SETMIPI_ONELANE (0x10 << 24)
+#define HX8369_CMD_SETMIPI_TWOLANE (0x11 << 24)
+#define HX8369_CMD_SETMIPI_PARAM_3 (0x00026f30)
+#define HX8369_CMD_SETMIPI_PARAM_4 (0x4018)
+
+#define HX8369_CMD_SETPIXEL_FMT (0x3A)
+#define HX8369_CMD_SETPIXEL_FMT_24BPP (0x77)
+#define HX8369_CMD_SETPIXEL_FMT_18BPP (0x66)
+#define HX8369_CMD_SETPIXEL_FMT_16BPP (0x55)
+
+#define HX8369_CMD_SETCLUMN_ADDR (0x2A)
+#define HX8369_CMD_SETCLUMN_ADDR_LEN (5)
+#define HX8369_CMD_SETCLUMN_ADDR_PARAM_1 (0xdf0000)
+#define HX8369_CMD_SETCLUMN_ADDR_PARAM_2 (0x01)
+
+#define HX8369_CMD_SETPAGE_ADDR (0x2B)
+#define HX8369_CMD_SETPAGE_ADDR_LEN (5)
+#define HX8369_CMD_SETPAGE_ADDR_PARAM_1 (0x1f0000)
+#define HX8369_CMD_SETPAGE_ADDR_PARAM_2 (0x03)
+
+#define HX8369_CMD_WRT_DISP_BRIGHT (0x51)
+#define HX8369_CMD_WRT_DISP_BRIGHT_PARAM_1 (0xFF)
+
+#define HX8369_CMD_WRT_CABC_MIN_BRIGHT (0x5E)
+#define HX8369_CMD_WRT_CABC_MIN_BRIGHT_PARAM_1 (0x20)
+
+#define HX8369_CMD_WRT_CABC_CTRL (0x55)
+#define HX8369_CMD_WRT_CABC_CTRL_PARAM_1 (0x1)
+
+#define HX8369_CMD_WRT_CTRL_DISP (0x53)
+#define HX8369_CMD_WRT_CTRL_DISP_PARAM_1 (0x24)
+
+#define CHECK_RETCODE(ret) \
+do { \
+ if (ret < 0) { \
+ dev_err(&mipi_dsi->pdev->dev, \
+ "%s ERR: ret:%d, line:%d.\n", \
+ __func__, ret, __LINE__); \
+ return ret; \
+ } \
+} while (0)
+
+static int hx8369bl_brightness;
+static int mipid_init_backlight(struct mipi_dsi_info *mipi_dsi);
+
+static struct fb_videomode truly_lcd_modedb[] = {
+ {
+ "TRULY-WVGA", 64, 480, 800, 37880,
+ 8, 8,
+ 6, 6,
+ 8, 6,
+ FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ },
+};
+
+static struct mipi_lcd_config lcd_config = {
+ .virtual_ch = 0x0,
+ .data_lane_num = HX8369_TWO_DATA_LANE,
+ .max_phy_clk = HX8369_MAX_DPHY_CLK,
+ .dpi_fmt = MIPI_RGB888,
+};
+void mipid_hx8369_get_lcd_videomode(struct fb_videomode **mode, int *size,
+ struct mipi_lcd_config **data)
+{
+ *mode = &truly_lcd_modedb[0];
+ *size = ARRAY_SIZE(truly_lcd_modedb);
+ *data = &lcd_config;
+}
+
+int mipid_hx8369_lcd_setup(struct mipi_dsi_info *mipi_dsi)
+{
+ u32 buf[DSI_CMD_BUF_MAXSIZE];
+ int err;
+
+ dev_dbg(&mipi_dsi->pdev->dev, "MIPI DSI LCD setup.\n");
+ buf[0] = HX8369_CMD_SETEXTC | (HX8369_CMD_SETEXTC_PARAM_1 << 8);
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
+ buf, HX8369_CMD_SETEXTC_LEN);
+ CHECK_RETCODE(err);
+ buf[0] = MIPI_DSI_MAX_RET_PACK_SIZE;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi,
+ MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
+ buf, 0);
+ CHECK_RETCODE(err);
+ buf[0] = HX8369_CMD_GETHXID;
+ err = mipi_dsi->mipi_dsi_pkt_read(mipi_dsi,
+ MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM,
+ buf, HX8369_CMD_GETHXID_LEN);
+ if (!err && ((buf[0] & HX8369_ID_MASK) == HX8369_ID)) {
+ dev_info(&mipi_dsi->pdev->dev,
+ "MIPI DSI LCD ID:0x%x.\n", buf[0]);
+ } else {
+ dev_err(&mipi_dsi->pdev->dev,
+ "mipi_dsi_pkt_read err:%d, data:0x%x.\n",
+ err, buf[0]);
+ dev_info(&mipi_dsi->pdev->dev,
+ "MIPI DSI LCD not detected!\n");
+ return err;
+ }
+
+ /* set LCD resolution as 480RGBx800, DPI interface,
+ * display operation mode: RGB data bypass GRAM mode.
+ */
+ buf[0] = HX8369_CMD_SETDISP | (HX8369_CMD_SETDISP_1_HALT << 8) |
+ (HX8369_CMD_SETDISP_2_RES_MODE << 16) |
+ (HX8369_CMD_SETDISP_3_BP << 24);
+ buf[1] = HX8369_CMD_SETDISP_4_FP | (HX8369_CMD_SETDISP_5_SAP << 8) |
+ (HX8369_CMD_SETDISP_6_GENON << 16) |
+ (HX8369_CMD_SETDISP_7_GENOFF << 24);
+ buf[2] = HX8369_CMD_SETDISP_8_RTN | (HX8369_CMD_SETDISP_9_TEI << 8) |
+ (HX8369_CMD_SETDISP_10_TEP_UP << 16) |
+ (HX8369_CMD_SETDISP_11_TEP_LOW << 24);
+ buf[3] = HX8369_CMD_SETDISP_12_BP_PE |
+ (HX8369_CMD_SETDISP_13_FP_PE << 8) |
+ (HX8369_CMD_SETDISP_14_RTN_PE << 16) |
+ (HX8369_CMD_SETDISP_15_GON << 24);
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
+ buf, HX8369_CMD_SETDISP_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set display waveform cycle */
+ buf[0] = HX8369_CMD_SETCYC | (HX8369_CMD_SETCYC_PARAM_1 << 8);
+ buf[1] = HX8369_CMD_SETCYC_PARAM_2;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
+ buf, HX8369_CMD_SETCYC_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set GIP timing output control */
+ buf[0] = HX8369_CMD_SETGIP | (HX8369_CMD_SETGIP_PARAM_1 << 8);
+ buf[1] = HX8369_CMD_SETGIP_PARAM_2;
+ buf[2] = HX8369_CMD_SETGIP_PARAM_3;
+ buf[3] = HX8369_CMD_SETGIP_PARAM_4;
+ buf[4] = HX8369_CMD_SETGIP_PARAM_5;
+ buf[5] = HX8369_CMD_SETGIP_PARAM_6;
+ buf[6] = HX8369_CMD_SETGIP_PARAM_7;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
+ HX8369_CMD_SETGIP_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set power: standby, DC etc. */
+ buf[0] = HX8369_CMD_SETPOWER | (HX8369_CMD_SETPOWER_PARAM_1 << 8);
+ buf[1] = HX8369_CMD_SETPOWER_PARAM_2;
+ buf[2] = HX8369_CMD_SETPOWER_PARAM_3;
+ buf[3] = HX8369_CMD_SETPOWER_PARAM_4;
+ buf[4] = HX8369_CMD_SETPOWER_PARAM_5;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
+ HX8369_CMD_SETPOWER_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set VCOM voltage. */
+ buf[0] = HX8369_CMD_SETVCOM | (HX8369_CMD_SETVCOM_PARAM_1 << 8);
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
+ HX8369_CMD_SETVCOM_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set Panel: BGR/RGB or Inversion. */
+ buf[0] = HX8369_CMD_SETPANEL | (HX8369_CMD_SETPANEL_PARAM_1 << 8);
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi,
+ MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM, buf, 0);
+ CHECK_RETCODE(err);
+
+ /* Set gamma curve related setting */
+ buf[0] = HX8369_CMD_SETGAMMA | (HX8369_CMD_SETGAMMA_PARAM_1 << 8);
+ buf[1] = HX8369_CMD_SETGAMMA_PARAM_2;
+ buf[2] = HX8369_CMD_SETGAMMA_PARAM_3;
+ buf[3] = HX8369_CMD_SETGAMMA_PARAM_4;
+ buf[4] = HX8369_CMD_SETGAMMA_PARAM_5;
+ buf[5] = HX8369_CMD_SETGAMMA_PARAM_6;
+ buf[6] = HX8369_CMD_SETGAMMA_PARAM_7;
+ buf[7] = HX8369_CMD_SETGAMMA_PARAM_8;
+ buf[8] = HX8369_CMD_SETGAMMA_PARAM_9;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
+ HX8369_CMD_SETGAMMA_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set MIPI: DPHYCMD & DSICMD, data lane number */
+ buf[0] = HX8369_CMD_SETMIPI | (HX8369_CMD_SETMIPI_PARAM_1 << 8);
+ buf[1] = HX8369_CMD_SETMIPI_PARAM_2;
+ buf[2] = HX8369_CMD_SETMIPI_PARAM_3;
+ if (lcd_config.data_lane_num == HX8369_ONE_DATA_LANE)
+ buf[2] |= HX8369_CMD_SETMIPI_ONELANE;
+ else
+ buf[2] |= HX8369_CMD_SETMIPI_TWOLANE;
+ buf[3] = HX8369_CMD_SETMIPI_PARAM_4;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE, buf,
+ HX8369_CMD_SETMIPI_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set pixel format:24bpp */
+ buf[0] = HX8369_CMD_SETPIXEL_FMT;
+ switch (lcd_config.dpi_fmt) {
+ case MIPI_RGB565_PACKED:
+ case MIPI_RGB565_LOOSELY:
+ case MIPI_RGB565_CONFIG3:
+ buf[0] |= (HX8369_CMD_SETPIXEL_FMT_16BPP << 8);
+ break;
+
+ case MIPI_RGB666_LOOSELY:
+ case MIPI_RGB666_PACKED:
+ buf[0] |= (HX8369_CMD_SETPIXEL_FMT_18BPP << 8);
+ break;
+
+ case MIPI_RGB888:
+ buf[0] |= (HX8369_CMD_SETPIXEL_FMT_24BPP << 8);
+ break;
+
+ default:
+ buf[0] |= (HX8369_CMD_SETPIXEL_FMT_24BPP << 8);
+ break;
+ }
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
+ buf, 0);
+ CHECK_RETCODE(err);
+
+ /* Set column address: 0~479 */
+ buf[0] = HX8369_CMD_SETCLUMN_ADDR |
+ (HX8369_CMD_SETCLUMN_ADDR_PARAM_1 << 8);
+ buf[1] = HX8369_CMD_SETCLUMN_ADDR_PARAM_2;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
+ buf, HX8369_CMD_SETCLUMN_ADDR_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set page address: 0~799 */
+ buf[0] = HX8369_CMD_SETPAGE_ADDR |
+ (HX8369_CMD_SETPAGE_ADDR_PARAM_1 << 8);
+ buf[1] = HX8369_CMD_SETPAGE_ADDR_PARAM_2;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_LONG_WRITE,
+ buf, HX8369_CMD_SETPAGE_ADDR_LEN);
+ CHECK_RETCODE(err);
+
+ /* Set display brightness related */
+ buf[0] = HX8369_CMD_WRT_DISP_BRIGHT |
+ (HX8369_CMD_WRT_DISP_BRIGHT_PARAM_1 << 8);
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
+ buf, 0);
+ CHECK_RETCODE(err);
+
+ buf[0] = HX8369_CMD_WRT_CABC_CTRL |
+ (HX8369_CMD_WRT_CABC_CTRL_PARAM_1 << 8);
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
+ buf, 0);
+ CHECK_RETCODE(err);
+
+ buf[0] = HX8369_CMD_WRT_CTRL_DISP |
+ (HX8369_CMD_WRT_CTRL_DISP_PARAM_1 << 8);
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
+ buf, 0);
+ CHECK_RETCODE(err);
+
+ /* exit sleep mode and set display on */
+ buf[0] = MIPI_DCS_EXIT_SLEEP_MODE;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM,
+ buf, 0);
+ CHECK_RETCODE(err);
+ /* To allow time for the supply voltages
+ * and clock circuits to stabilize.
+ */
+ msleep(5);
+ buf[0] = MIPI_DCS_SET_DISPLAY_ON;
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM,
+ buf, 0);
+ CHECK_RETCODE(err);
+
+ err = mipid_init_backlight(mipi_dsi);
+ return err;
+}
+
+static int mipid_bl_update_status(struct backlight_device *bl)
+{
+ int err;
+ u32 buf;
+ int brightness = bl->props.brightness;
+ struct mipi_dsi_info *mipi_dsi = bl_get_data(bl);
+
+ if (bl->props.power != FB_BLANK_UNBLANK ||
+ bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ buf = HX8369_CMD_WRT_DISP_BRIGHT |
+ ((brightness & HX8369BL_MAX_BRIGHT) << 8);
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM,
+ &buf, 0);
+ CHECK_RETCODE(err);
+
+ hx8369bl_brightness = brightness & HX8369BL_MAX_BRIGHT;
+
+ dev_dbg(&bl->dev, "mipid backlight bringtness:%d.\n", brightness);
+ return 0;
+}
+
+static int mipid_bl_get_brightness(struct backlight_device *bl)
+{
+ return hx8369bl_brightness;
+}
+
+static int mipi_bl_check_fb(struct backlight_device *bl, struct fb_info *fbi)
+{
+ return 0;
+}
+
+static const struct backlight_ops mipid_lcd_bl_ops = {
+ .update_status = mipid_bl_update_status,
+ .get_brightness = mipid_bl_get_brightness,
+ .check_fb = mipi_bl_check_fb,
+};
+
+static int mipid_init_backlight(struct mipi_dsi_info *mipi_dsi)
+{
+ struct backlight_properties props;
+ struct backlight_device *bl;
+
+ if (mipi_dsi->bl) {
+ pr_debug("mipid backlight already init!\n");
+ return 0;
+ }
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.max_brightness = HX8369BL_MAX_BRIGHT;
+ props.type = BACKLIGHT_RAW;
+ bl = backlight_device_register("mipid-bl", &mipi_dsi->pdev->dev,
+ mipi_dsi, &mipid_lcd_bl_ops, &props);
+ if (IS_ERR(bl)) {
+ pr_err("error %ld on backlight register\n", PTR_ERR(bl));
+ return PTR_ERR(bl);
+ }
+ mipi_dsi->bl = bl;
+ bl->props.power = FB_BLANK_UNBLANK;
+ bl->props.fb_blank = FB_BLANK_UNBLANK;
+ bl->props.brightness = HX8369BL_DEF_BRIGHT;
+
+ mipid_bl_update_status(bl);
+ return 0;
+}
diff --git a/drivers/video/fbdev/mxc/mxcfb_otm8018b_wvga.c b/drivers/video/fbdev/mxc/mxcfb_otm8018b_wvga.c
new file mode 100644
index 000000000000..fa7db02f37f6
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxcfb_otm8018b_wvga.c
@@ -0,0 +1,266 @@
+/*
+ * 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.
+
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/mipi_dsi.h>
+#include <linux/mxcfb.h>
+#include <linux/backlight.h>
+#include <video/mipi_display.h>
+
+#include "mipi_dsi.h"
+
+#define OTM8018B_TWO_DATA_LANE (0x2)
+#define OTM8018B_MAX_DPHY_CLK (800)
+
+#define CHECK_RETCODE(ret) \
+do { \
+ if (ret < 0) { \
+ dev_err(&mipi_dsi->pdev->dev, \
+ "%s ERR: ret:%d, line:%d.\n", \
+ __func__, ret, __LINE__); \
+ return ret; \
+ } \
+} while (0)
+
+static void parse_variadic(int n, u8 *buf, ...)
+{
+ int i = 0;
+ va_list args;
+
+ if (unlikely(!n)) return;
+
+ va_start(args, buf);
+
+ for (i = 0; i < n; i++)
+ buf[i + 1] = (u8)va_arg(args, int);
+
+ va_end(args);
+}
+
+#define TC358763_DCS_write_1A_nP(n, addr, ...) { \
+ int err; \
+ \
+ buf[0] = addr; \
+ parse_variadic(n, buf, ##__VA_ARGS__); \
+ \
+ err = mipi_dsi->mipi_dsi_pkt_write(mipi_dsi, \
+ MIPI_DSI_GENERIC_LONG_WRITE, (u32*)buf, n + 1); \
+ CHECK_RETCODE(err); \
+}
+
+#define TC358763_DCS_write_1A_0P(addr) \
+ TC358763_DCS_write_1A_nP(0, addr)
+
+#define TC358763_DCS_write_1A_1P(addr, ...) \
+ TC358763_DCS_write_1A_nP(1, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_2P(addr, ...) \
+ TC358763_DCS_write_1A_nP(2, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_3P(addr, ...) \
+ TC358763_DCS_write_1A_nP(3, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_5P(addr, ...) \
+ TC358763_DCS_write_1A_nP(5, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_6P(addr, ...) \
+ TC358763_DCS_write_1A_nP(6, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_12P(addr, ...) \
+ TC358763_DCS_write_1A_nP(12, addr, __VA_ARGS__)
+
+#define TC358763_DCS_write_1A_14P(addr, ...) \
+ TC358763_DCS_write_1A_nP(14, addr, __VA_ARGS__)
+
+static int otm8018bbl_brightness;
+
+static struct fb_videomode truly_lcd_modedb[] = {
+ {
+ "TRULY-WVGA", 64, 480, 800, 37880,
+ 8, 8,
+ 6, 6,
+ 8, 6,
+ FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ },
+};
+
+static struct mipi_lcd_config lcd_config = {
+ .virtual_ch = 0x0,
+ .data_lane_num = OTM8018B_TWO_DATA_LANE,
+ .max_phy_clk = OTM8018B_MAX_DPHY_CLK,
+ .dpi_fmt = MIPI_RGB888,
+};
+
+void mipid_otm8018b_get_lcd_videomode(struct fb_videomode **mode, int *size,
+ struct mipi_lcd_config **data)
+{
+ *mode = &truly_lcd_modedb[0];
+ *size = ARRAY_SIZE(truly_lcd_modedb);
+ *data = &lcd_config;
+}
+
+int mipid_otm8018b_lcd_setup(struct mipi_dsi_info *mipi_dsi)
+{
+ u8 buf[DSI_CMD_BUF_MAXSIZE];
+
+ dev_dbg(&mipi_dsi->pdev->dev, "MIPI DSI LCD setup.\n");
+
+ TC358763_DCS_write_1A_3P(0xFF,0x80,0x09,0x01);
+ TC358763_DCS_write_1A_1P(0x00,0x80);
+ TC358763_DCS_write_1A_2P(0xFF,0x80,0x09);
+
+ TC358763_DCS_write_1A_1P(0x00,0x03);
+ TC358763_DCS_write_1A_1P(0xff,0x01);
+
+ TC358763_DCS_write_1A_1P(0x00,0xb4);
+ TC358763_DCS_write_1A_1P(0xc0,0x10);
+
+ TC358763_DCS_write_1A_1P(0x00,0x82);
+ TC358763_DCS_write_1A_1P(0xC5,0xa3);
+
+ TC358763_DCS_write_1A_1P(0x00,0x90);
+ TC358763_DCS_write_1A_2P(0xC5,0x96,0x76);
+
+ TC358763_DCS_write_1A_1P(0x00,0x00);
+ TC358763_DCS_write_1A_2P(0xD8,0x75,0x73);
+
+ TC358763_DCS_write_1A_1P(0x00,0x00);
+ TC358763_DCS_write_1A_1P(0xD9,0x5e);
+
+ TC358763_DCS_write_1A_1P(0x00,0x81);
+ TC358763_DCS_write_1A_1P(0xC1,0x66);
+
+ TC358763_DCS_write_1A_1P(0x00,0xA1);
+ TC358763_DCS_write_1A_1P(0xC1,0x08);
+
+ TC358763_DCS_write_1A_1P(0x00,0x89);
+ TC358763_DCS_write_1A_1P(0xC4,0x08);
+
+ TC358763_DCS_write_1A_1P(0x00,0xA2);
+ TC358763_DCS_write_1A_3P(0xC0,0x1B,0x00,0x02);
+
+ TC358763_DCS_write_1A_1P(0x00,0x81);
+ TC358763_DCS_write_1A_1P(0xC4,0x83);
+
+ TC358763_DCS_write_1A_1P(0x00,0x92);
+ TC358763_DCS_write_1A_1P(0xC5,0x01);
+
+ TC358763_DCS_write_1A_1P(0x00,0xb1);
+ TC358763_DCS_write_1A_1P(0xC5,0xa9);
+
+ TC358763_DCS_write_1A_1P(0x00,0x90);
+ TC358763_DCS_write_1A_6P(0xC0,0x00,0x44,0x00,0x00,0x00,0x03);
+
+ TC358763_DCS_write_1A_1P(0x00,0xA6);
+ TC358763_DCS_write_1A_3P(0xC1,0x00,0x00,0x00);
+
+ TC358763_DCS_write_1A_1P(0x00,0x80);
+ TC358763_DCS_write_1A_12P(0xCE,0x87,0x03,0x00,0x85,0x03,0x00,
+ 0x86,0x03,0x00,0x84,0x03,0x00);
+
+ TC358763_DCS_write_1A_1P(0x00,0xA0);
+ TC358763_DCS_write_1A_14P(0xCE,0x38,0x03,0x03,0x58,0x00,0x00,
+ 0x00,0x38,0x02,0x03,0x59,0x00,0x00,0x00);
+
+ TC358763_DCS_write_1A_1P(0x00,0xB0);
+ TC358763_DCS_write_1A_14P(0xCE,0x38,0x01,0x03,0x5a,0x00,0x00,
+ 0x00,0x38,0x00,0x03,0x5b,0x00,0x00,0x00);
+
+ TC358763_DCS_write_1A_1P(0x00,0xC0);
+ TC358763_DCS_write_1A_14P(0xCE,0x30,0x00,0x03,0x5c,0x00,0x00,
+ 0x00,0x30,0x01,0x03,0x5d,0x00,0x00,0x00);
+
+ TC358763_DCS_write_1A_1P(0x00,0xD0);
+ TC358763_DCS_write_1A_14P(0xCE,0x30,0x02,0x03,0x5e,0x00,0x00,
+ 0x00,0x30,0x03,0x03,0x5f,0x00,0x00,0x00);
+
+ TC358763_DCS_write_1A_1P(0x00,0xC7);
+ TC358763_DCS_write_1A_1P(0xCF,0x00);
+
+ TC358763_DCS_write_1A_1P(0x00,0xC9);
+ TC358763_DCS_write_1A_1P(0xCF,0x00);
+
+ TC358763_DCS_write_1A_1P(0x00,0xC4);
+ TC358763_DCS_write_1A_6P(0xCB,0x04,0x04,0x04,0x04,0x04,0x04);
+
+ TC358763_DCS_write_1A_1P(0x00,0xd9);
+ TC358763_DCS_write_1A_6P(0xCB,0x04,0x04,0x04,0x04,0x04,0x04);
+
+ TC358763_DCS_write_1A_1P(0x00,0x84);
+ TC358763_DCS_write_1A_6P(0xCc,0x0c,0x0a,0x10,0x0e,0x03,0x04);
+
+ TC358763_DCS_write_1A_1P(0x00,0x9e);
+ TC358763_DCS_write_1A_1P(0xCc,0x0b);
+
+ TC358763_DCS_write_1A_1P(0x00,0xA0);
+ TC358763_DCS_write_1A_5P(0xCC,0x09,0x0f,0x0d,0x01,0x02);
+
+ TC358763_DCS_write_1A_1P(0x00,0xb4);
+ TC358763_DCS_write_1A_5P(0xCC,0x0d,0x09,0x0b,0x02,0x01);
+
+ TC358763_DCS_write_1A_1P(0x00,0xce);
+ TC358763_DCS_write_1A_1P(0xCc,0x0e);
+
+ TC358763_DCS_write_1A_1P(0x00,0xD0);
+ TC358763_DCS_write_1A_5P(0xCC,0x10,0x0a,0x0c,0x04,0x03);
+
+ TC358763_DCS_write_1A_1P(0x00,0x00);
+ TC358763_DCS_write_1A_1P(0x3a,0x77);
+
+ TC358763_DCS_write_1A_0P(0x11);
+
+ msleep(200);
+
+ TC358763_DCS_write_1A_0P(0x29);
+
+ TC358763_DCS_write_1A_0P(0x2C);
+
+ return 0;
+}
+
+static int mipid_bl_update_status(struct backlight_device *bl)
+{
+ return 0;
+}
+
+static int mipid_bl_get_brightness(struct backlight_device *bl)
+{
+ return otm8018bbl_brightness;
+}
+
+static int mipi_bl_check_fb(struct backlight_device *bl, struct fb_info *fbi)
+{
+ return 0;
+}
+
+static const struct backlight_ops mipid_lcd_bl_ops = {
+ .update_status = mipid_bl_update_status,
+ .get_brightness = mipid_bl_get_brightness,
+ .check_fb = mipi_bl_check_fb,
+};
diff --git a/drivers/video/fbdev/mxc/mxsfb_sii902x.c b/drivers/video/fbdev/mxc/mxsfb_sii902x.c
new file mode 100644
index 000000000000..b9ab7db822ed
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxsfb_sii902x.c
@@ -0,0 +1,558 @@
+/*
+ * Copyright (C) 2010-2015 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
+ */
+
+/*!
+ * @defgroup Framebuffer Framebuffer Driver for Sii902x.
+ */
+
+/*!
+ * @file mxsfb_sii902x.c
+ *
+ * @brief Frame buffer driver for SII902x
+ *
+ * @ingroup Framebuffer
+ */
+
+/*!
+ * Include files
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/i2c.h>
+#include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
+#include <linux/reset.h>
+#include <asm/mach-types.h>
+#include <video/mxc_edid.h>
+
+#define SII_EDID_LEN 512
+#define DRV_NAME "sii902x"
+
+struct sii902x_data {
+ struct i2c_client *client;
+ struct delayed_work det_work;
+ struct fb_info *fbi;
+ struct mxc_edid_cfg edid_cfg;
+ u8 cable_plugin;
+ u8 edid[SII_EDID_LEN];
+ bool dft_mode_set;
+ const char *mode_str;
+ int bits_per_pixel;
+} sii902x;
+
+static void sii902x_poweron(void);
+static void sii902x_poweroff(void);
+
+static int sii902x_in_init_state;
+
+#ifdef DEBUG
+static void dump_fb_videomode(struct fb_videomode *m)
+{
+ pr_debug("fb_videomode = %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ m->refresh, m->xres, m->yres, m->pixclock, m->left_margin,
+ m->right_margin, m->upper_margin, m->lower_margin,
+ m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
+}
+#else
+static void dump_fb_videomode(struct fb_videomode *m)
+{}
+#endif
+
+static __attribute__ ((unused)) void dump_regs(u8 reg, int len)
+{
+ u8 buf[50];
+ int i;
+
+ i2c_smbus_read_i2c_block_data(sii902x.client, reg, len, buf);
+ for (i = 0; i < len; i++)
+ dev_dbg(&sii902x.client->dev, "reg[0x%02X]: 0x%02X\n",
+ i+reg, buf[i]);
+}
+
+static ssize_t sii902x_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ strcpy(buf, sii902x.fbi->fix.id);
+ sprintf(buf+strlen(buf), "\n");
+
+ return strlen(buf);
+}
+
+static DEVICE_ATTR(fb_name, S_IRUGO, sii902x_show_name, NULL);
+
+static ssize_t sii902x_show_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (sii902x.cable_plugin == 0)
+ strcpy(buf, "plugout\n");
+ else
+ strcpy(buf, "plugin\n");
+
+ return strlen(buf);
+}
+
+static DEVICE_ATTR(cable_state, S_IRUGO, sii902x_show_state, NULL);
+
+static ssize_t sii902x_show_edid(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int i, j, len = 0;
+
+ for (j = 0; j < SII_EDID_LEN/16; j++) {
+ for (i = 0; i < 16; i++)
+ len += sprintf(buf+len, "0x%02X ",
+ sii902x.edid[j*16 + i]);
+ len += sprintf(buf+len, "\n");
+ }
+
+ return len;
+}
+
+static DEVICE_ATTR(edid, S_IRUGO, sii902x_show_edid, NULL);
+
+static void sii902x_setup(struct fb_info *fbi)
+{
+ u16 data[4];
+ u32 refresh;
+ u8 *tmp;
+ int i;
+
+ dev_dbg(&sii902x.client->dev, "Sii902x: setup..\n");
+
+ /* Power up */
+ i2c_smbus_write_byte_data(sii902x.client, 0x1E, 0x00);
+
+ /* set TPI video mode */
+ data[0] = PICOS2KHZ(fbi->var.pixclock) / 10;
+ data[2] = fbi->var.hsync_len + fbi->var.left_margin +
+ fbi->var.xres + fbi->var.right_margin;
+ data[3] = fbi->var.vsync_len + fbi->var.upper_margin +
+ fbi->var.yres + fbi->var.lower_margin;
+ refresh = data[2] * data[3];
+ refresh = (PICOS2KHZ(fbi->var.pixclock) * 1000) / refresh;
+ data[1] = refresh * 100;
+ tmp = (u8 *)data;
+ for (i = 0; i < 8; i++)
+ i2c_smbus_write_byte_data(sii902x.client, i, tmp[i]);
+
+ /* input bus/pixel: full pixel wide (24bit), rising edge */
+ i2c_smbus_write_byte_data(sii902x.client, 0x08, 0x70);
+ /* Set input format to RGB */
+ i2c_smbus_write_byte_data(sii902x.client, 0x09, 0x00);
+ /* set output format to RGB */
+ i2c_smbus_write_byte_data(sii902x.client, 0x0A, 0x00);
+}
+
+static void sii902x_audio_setup(void)
+{
+ /* audio setup */
+ i2c_smbus_write_byte_data(sii902x.client, 0x25, 0x00);
+ i2c_smbus_write_byte_data(sii902x.client, 0x26, 0x40);
+ i2c_smbus_write_byte_data(sii902x.client, 0x27, 0x00);
+}
+
+#ifdef CONFIG_FB_MODE_HELPERS
+static int sii902x_read_edid(struct fb_info *fbi)
+{
+ int old, dat, ret, cnt = 100;
+ unsigned short addr = 0x50;
+
+ dev_dbg(&sii902x.client->dev, "%s\n", __func__);
+
+ old = i2c_smbus_read_byte_data(sii902x.client, 0x1A);
+
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, old | 0x4);
+ do {
+ cnt--;
+ msleep(10);
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1A);
+ } while ((!(dat & 0x2)) && cnt);
+
+ if (!cnt) {
+ ret = -1;
+ goto done;
+ }
+
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, old | 0x06);
+
+ /* edid reading */
+ ret = mxc_edid_read(sii902x.client->adapter, addr,
+ sii902x.edid, &sii902x.edid_cfg, fbi);
+
+ cnt = 100;
+ do {
+ cnt--;
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, old & ~0x6);
+ msleep(10);
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1A);
+ } while ((dat & 0x6) && cnt);
+
+ if (!cnt)
+ ret = -1;
+
+done:
+
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, old);
+ return ret;
+}
+#else
+static int sii902x_read_edid(struct fb_info *fbi)
+{
+ return -1;
+}
+#endif
+
+static void sii902x_cable_connected(void)
+{
+ int i;
+ const struct fb_videomode *mode;
+ struct fb_videomode m;
+
+ if (sii902x_read_edid(sii902x.fbi) < 0)
+ dev_err(&sii902x.client->dev,
+ "Sii902x: read edid fail\n");
+ else {
+ if (sii902x.fbi->monspecs.modedb_len > 0) {
+
+ fb_destroy_modelist(&sii902x.fbi->modelist);
+
+ for (i = 0; i < sii902x.fbi->monspecs.modedb_len; i++) {
+
+ mode = &sii902x.fbi->monspecs.modedb[i];
+
+ if (!(mode->vmode & FB_VMODE_INTERLACED)) {
+ dev_dbg(&sii902x.client->dev, "Added mode %d:", i);
+ dev_dbg(&sii902x.client->dev,
+ "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n",
+ mode->xres, mode->yres, mode->refresh,
+ mode->vmode, mode->flag);
+
+ fb_add_videomode(mode, &sii902x.fbi->modelist);
+ }
+ }
+
+ /* Set the default mode only once. */
+ if (!sii902x.dft_mode_set &&
+ sii902x.mode_str && sii902x.bits_per_pixel) {
+
+ dev_dbg(&sii902x.client->dev, "%s: setting to default=%s bpp=%d\n",
+ __func__, sii902x.mode_str, sii902x.bits_per_pixel);
+
+ fb_find_mode(&sii902x.fbi->var, sii902x.fbi,
+ sii902x.mode_str, NULL, 0, NULL,
+ sii902x.bits_per_pixel);
+
+ sii902x.dft_mode_set = true;
+ }
+
+ fb_var_to_videomode(&m, &sii902x.fbi->var);
+ dump_fb_videomode(&m);
+
+ mode = fb_find_nearest_mode(&m,
+ &sii902x.fbi->modelist);
+
+ /* update fbi mode */
+ sii902x.fbi->mode = (struct fb_videomode *)mode;
+
+ fb_videomode_to_var(&sii902x.fbi->var, mode);
+
+ sii902x.fbi->var.activate |= FB_ACTIVATE_FORCE;
+ console_lock();
+ sii902x.fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_set_var(sii902x.fbi, &sii902x.fbi->var);
+ sii902x.fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+ }
+ /* Power on sii902x */
+ sii902x_poweron();
+ }
+}
+
+static void det_worker(struct work_struct *work)
+{
+ int dat;
+ char event_string[16];
+ char *envp[] = { event_string, NULL };
+
+ dev_dbg(&sii902x.client->dev, "%s\n", __func__);
+
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x3D);
+
+ /* cable connection state */
+ if (dat & 0x4) {
+ sii902x.cable_plugin = 1;
+ dev_dbg(&sii902x.client->dev, "EVENT=plugin\n");
+ sprintf(event_string, "EVENT=plugin");
+ sii902x_cable_connected();
+ } else {
+ sii902x.cable_plugin = 0;
+ dev_dbg(&sii902x.client->dev, "EVENT=plugout\n");
+ sprintf(event_string, "EVENT=plugout");
+ /* Power off sii902x */
+ sii902x_poweroff();
+ }
+ kobject_uevent_env(&sii902x.client->dev.kobj, KOBJ_CHANGE, envp);
+
+ i2c_smbus_write_byte_data(sii902x.client, 0x3D, dat);
+
+ dev_dbg(&sii902x.client->dev, "exit %s\n", __func__);
+
+}
+
+static irqreturn_t sii902x_detect_handler(int irq, void *data)
+{
+ if (sii902x.fbi)
+ schedule_delayed_work(&(sii902x.det_work), msecs_to_jiffies(50));
+
+ return IRQ_HANDLED;
+}
+
+static int sii902x_fb_event(struct notifier_block *nb, unsigned long val, void *v)
+{
+ struct fb_event *event = v;
+ struct fb_info *fbi = event->info;
+
+ dev_dbg(&sii902x.client->dev, "%s event=0x%lx\n", __func__, val);
+
+ if (sii902x_in_init_state) {
+ if (val == FB_EVENT_FB_REGISTERED && !sii902x.fbi)
+ sii902x.fbi = fbi;
+
+ return 0;
+ }
+
+ switch (val) {
+ case FB_EVENT_FB_REGISTERED:
+ if (sii902x.fbi == NULL)
+ sii902x.fbi = fbi;
+ /* Manually trigger a plugin/plugout interrupter to check cable state */
+ schedule_delayed_work(&(sii902x.det_work), msecs_to_jiffies(50));
+
+ fb_show_logo(fbi, 0);
+
+ break;
+ case FB_EVENT_MODE_CHANGE:
+ sii902x_setup(fbi);
+ break;
+ case FB_EVENT_BLANK:
+ if (*((int *)event->data) == FB_BLANK_UNBLANK) {
+ dev_dbg(&sii902x.client->dev, "FB_BLANK_UNBLANK\n");
+ sii902x_poweron();
+ } else {
+ dev_dbg(&sii902x.client->dev, "FB_BLANK_BLANK\n");
+ sii902x_poweroff();
+ }
+ break;
+ }
+ return 0;
+}
+
+static struct notifier_block nb = {
+ .notifier_call = sii902x_fb_event,
+};
+
+static int mxsfb_get_of_property(void)
+{
+ struct device_node *np = sii902x.client->dev.of_node;
+ const char *mode_str;
+ int bits_per_pixel, ret;
+
+ ret = of_property_read_string(np, "mode_str", &mode_str);
+ if (ret < 0) {
+ dev_warn(&sii902x.client->dev, "get of property mode_str fail\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "bits-per-pixel", &bits_per_pixel);
+ if (ret) {
+ dev_warn(&sii902x.client->dev, "get of property bpp fail\n");
+ return ret;
+ }
+
+ sii902x.mode_str = mode_str;
+ sii902x.bits_per_pixel = bits_per_pixel;
+
+ return ret;
+}
+
+static int sii902x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int i, dat, ret;
+ struct fb_info edid_fbi;
+ struct fb_info *init_fbi = sii902x.fbi;
+
+ memset(&sii902x, 0, sizeof(sii902x));
+
+ sii902x.client = client;
+
+ dev_dbg(&sii902x.client->dev, "%s\n", __func__);;
+
+ /* Reset sii902x */
+ ret = device_reset(&sii902x.client->dev);
+ if (ret)
+ dev_warn(&sii902x.client->dev, "No reset pin found\n");
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ /* Set 902x in hardware TPI mode on and jump out of D3 state */
+ if (i2c_smbus_write_byte_data(sii902x.client, 0xc7, 0x00) < 0) {
+ dev_err(&sii902x.client->dev,
+ "Sii902x: cound not find device\n");
+ return -ENODEV;
+ }
+
+ /* read device ID */
+ for (i = 10; i > 0; i--) {
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1B);
+ dev_dbg(&sii902x.client->dev, "Sii902x: read id = 0x%02X", dat);
+ if (dat == 0xb0) {
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1C);
+ dev_dbg(&sii902x.client->dev, "-0x%02X", dat);
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1D);
+ dev_dbg(&sii902x.client->dev, "-0x%02X", dat);
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x30);
+ dev_dbg(&sii902x.client->dev, "-0x%02X\n", dat);
+ break;
+ }
+ }
+ if (i == 0) {
+ dev_err(&sii902x.client->dev,
+ "Sii902x: cound not find device\n");
+ return -ENODEV;
+ }
+
+ /* enable hmdi audio */
+ sii902x_audio_setup();
+
+ /* try to read edid, only if cable is plugged in */
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x3D);
+ if (dat & 0x04) {
+ ret = sii902x_read_edid(&edid_fbi);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev, "Can not read edid\n");
+ }
+
+ if (sii902x.client->irq) {
+ ret = request_irq(sii902x.client->irq, sii902x_detect_handler,
+ IRQF_TRIGGER_FALLING,
+ "SII902x_det", &sii902x);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev,
+ "Sii902x: cound not request det irq %d\n",
+ sii902x.client->irq);
+ else {
+ /*enable cable hot plug irq*/
+ i2c_smbus_write_byte_data(sii902x.client, 0x3c, 0x01);
+ INIT_DELAYED_WORK(&(sii902x.det_work), det_worker);
+ }
+ ret = device_create_file(&sii902x.client->dev, &dev_attr_fb_name);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev,
+ "Sii902x: cound not create sys node for fb name\n");
+ ret = device_create_file(&sii902x.client->dev, &dev_attr_cable_state);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev,
+ "Sii902x: cound not create sys node for cable state\n");
+ ret = device_create_file(&sii902x.client->dev, &dev_attr_edid);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev,
+ "Sii902x: cound not create sys node for edid\n");
+
+ }
+
+ mxsfb_get_of_property();
+
+ if (init_fbi) {
+ sii902x.fbi = init_fbi;
+
+ /* Manually trigger a plugin/plugout interrupter to check cable state */
+ schedule_delayed_work(&(sii902x.det_work), msecs_to_jiffies(50));
+ }
+
+ sii902x_in_init_state = 0;
+
+ return 0;
+}
+
+static int sii902x_remove(struct i2c_client *client)
+{
+ fb_unregister_client(&nb);
+ sii902x_poweroff();
+
+ return 0;
+}
+
+static void sii902x_poweron(void)
+{
+ /* Turn on DVI or HDMI */
+ if (sii902x.edid_cfg.hdmi_cap)
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x01);
+ else
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x00);
+ return;
+}
+
+static void sii902x_poweroff(void)
+{
+ /* disable tmds before changing resolution */
+ if (sii902x.edid_cfg.hdmi_cap)
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x11);
+ else
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x10);
+
+ return;
+}
+
+static int __init sii902x_init(void)
+{
+ sii902x_in_init_state = 1;
+
+ return fb_register_client(&nb);
+}
+fs_initcall_sync(sii902x_init);
+
+static const struct i2c_device_id sii902x_id[] = {
+ { DRV_NAME, 0},
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, sii902x_id);
+
+static const struct of_device_id sii902x_dt_ids[] = {
+ { .compatible = "SiI,sii902x", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sii902x_dt_ids);
+
+static struct i2c_driver sii902x_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = sii902x_dt_ids,
+ },
+ .probe = sii902x_probe,
+ .remove = sii902x_remove,
+ .id_table = sii902x_id,
+};
+
+module_i2c_driver(sii902x_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("SII902x DVI/HDMI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
index 7846f0e8bbbb..853d395fa273 100644
--- a/drivers/video/fbdev/mxsfb.c
+++ b/drivers/video/fbdev/mxsfb.c
@@ -4,7 +4,8 @@
* This code is based on:
* Author: Vitaly Wool <vital@embeddedalley.com>
*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
+ * Copyright 2008-2015 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
@@ -39,18 +40,30 @@
* the required value in the imx_fb_videomode structure.
*/
+#include <linux/busfreq-imx.h>
+#include <linux/console.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pm_qos.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/fb.h>
+#include <linux/mxcfb.h>
#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
#include <video/of_display_timing.h>
-#include <video/of_videomode.h>
#include <video/videomode.h>
+#include <linux/uaccess.h>
+
+#include "mxc/mxc_dispdrv.h"
#define REG_SET 4
#define REG_CLR 8
@@ -79,6 +92,9 @@
#define LCDC_V3_DATA 0x1b0
#define LCDC_V4_DEBUG0 0x1d0
#define LCDC_V3_DEBUG0 0x1f0
+#define LCDC_AS_CTRL 0x210
+#define LCDC_AS_BUF 0x220
+#define LCDC_AS_NEXT_BUF 0x230
#define CTRL_SFTRST (1 << 31)
#define CTRL_CLKGATE (1 << 30)
@@ -96,9 +112,30 @@
#define CTRL_DF24 (1 << 1)
#define CTRL_RUN (1 << 0)
-#define CTRL1_FIFO_CLEAR (1 << 21)
-#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
-#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
+#define CTRL1_RECOVERY_ON_UNDERFLOW (1 << 24)
+#define CTRL1_FIFO_CLEAR (1 << 21)
+#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
+#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
+#define CTRL1_OVERFLOW_IRQ_EN (1 << 15)
+#define CTRL1_UNDERFLOW_IRQ_EN (1 << 14)
+#define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13)
+#define CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12)
+#define CTRL1_OVERFLOW_IRQ (1 << 11)
+#define CTRL1_UNDERFLOW_IRQ (1 << 10)
+#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9)
+#define CTRL1_VSYNC_EDGE_IRQ (1 << 8)
+#define CTRL1_IRQ_ENABLE_MASK (CTRL1_OVERFLOW_IRQ_EN | \
+ CTRL1_UNDERFLOW_IRQ_EN | \
+ CTRL1_CUR_FRAME_DONE_IRQ_EN | \
+ CTRL1_VSYNC_EDGE_IRQ_EN)
+#define CTRL1_IRQ_ENABLE_SHIFT 12
+#define CTRL1_IRQ_STATUS_MASK (CTRL1_OVERFLOW_IRQ | \
+ CTRL1_UNDERFLOW_IRQ | \
+ CTRL1_CUR_FRAME_DONE_IRQ | \
+ CTRL1_VSYNC_EDGE_IRQ)
+#define CTRL1_IRQ_STATUS_SHIFT 8
+
+#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
@@ -149,12 +186,13 @@
#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
-#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6)
-#define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negtive edge sampling */
+#define FB_SYNC_OE_LOW_ACT 0x80000000
+#define FB_SYNC_CLK_LAT_FALL 0x40000000
enum mxsfb_devtype {
MXSFB_V3,
MXSFB_V4,
+ MXSFB_V5,
};
/* CPU dependent register offsets */
@@ -166,26 +204,79 @@ struct mxsfb_devdata {
unsigned hs_wdth_mask;
unsigned hs_wdth_shift;
unsigned ipversion;
+ u32 flags;
+};
+
+struct mxsfb_layer;
+
+struct mxsfb_layer_ops {
+ void (*enable)(struct mxsfb_layer *ofb);
+ void (*disable)(struct mxsfb_layer *ofb);
+ void (*setup)(struct mxsfb_layer *ofb);
+};
+
+struct mxsfb_layer {
+ struct fb_info *ol_fb;
+ int id;
+ int registered;
+ atomic_t usage;
+ int blank_state;
+ uint32_t global_alpha;
+
+ struct mxsfb_layer_ops *ops;
+
+ struct device *dev;
+ void __iomem *video_mem;
+ unsigned long video_mem_phys;
+ size_t video_mem_size;
+
+ struct mxsfb_info *fbi;
};
+#define NAME_LEN 32
+
struct mxsfb_info {
- struct fb_info fb_info;
+ struct fb_info *fb_info;
struct platform_device *pdev;
- struct clk *clk;
+ struct clk *clk_pix;
struct clk *clk_axi;
struct clk *clk_disp_axi;
+ bool clk_pix_enabled;
+ bool clk_axi_enabled;
+ bool clk_disp_axi_enabled;
void __iomem *base; /* registers */
+ u32 sync; /* record display timing polarities */
unsigned allocated_size;
int enabled;
unsigned ld_intf_width;
unsigned dotclk_delay;
const struct mxsfb_devdata *devdata;
- u32 sync;
struct regulator *reg_lcd;
+ bool wait4vsync;
+ struct completion vsync_complete;
+ struct completion flip_complete;
+ int cur_blank;
+ int restore_blank;
+ char disp_dev[NAME_LEN];
+ struct mxc_dispdrv_handle *dispdrv;
+ int id;
+ struct fb_var_screeninfo var;
+ struct pm_qos_request pm_qos_req;
+
+ char disp_videomode[NAME_LEN];
+
+#ifdef CONFIG_FB_MXC_OVERLAY
+ struct mxsfb_layer overlay;
+#endif
};
#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
#define mxsfb_is_v4(host) (host->devdata->ipversion == 4)
+#define mxsfb_is_v5(host) (host->devdata->ipversion == 5)
+
+#define MXSFB_FLAG_NULL 0x0
+#define MXSFB_FLAG_BUSFREQ 0x1
+#define MXSFB_FLAG_PMQOS 0x2
static const struct mxsfb_devdata mxsfb_devdata[] = {
[MXSFB_V3] = {
@@ -196,6 +287,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
.hs_wdth_mask = 0xff,
.hs_wdth_shift = 24,
.ipversion = 3,
+ .flags = MXSFB_FLAG_NULL,
},
[MXSFB_V4] = {
.transfer_count = LCDC_V4_TRANSFER_COUNT,
@@ -205,10 +297,77 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
.hs_wdth_mask = 0x3fff,
.hs_wdth_shift = 18,
.ipversion = 4,
+ .flags = MXSFB_FLAG_BUSFREQ,
+ },
+ [MXSFB_V5] = {
+ .transfer_count = LCDC_V4_TRANSFER_COUNT,
+ .cur_buf = LCDC_V4_CUR_BUF,
+ .next_buf = LCDC_V4_NEXT_BUF,
+ .debug0 = LCDC_V4_DEBUG0,
+ .hs_wdth_mask = 0x3fff,
+ .hs_wdth_shift = 18,
+ .ipversion = 4,
+ .flags = MXSFB_FLAG_PMQOS,
},
};
-#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
+static int mxsfb_map_videomem(struct fb_info *info);
+static int mxsfb_unmap_videomem(struct fb_info *info);
+static int mxsfb_set_par(struct fb_info *fb_info);
+
+/* enable lcdif pix clock */
+static inline void clk_enable_pix(struct mxsfb_info *host)
+{
+ if (!host->clk_pix_enabled && (host->clk_pix != NULL)) {
+ clk_prepare_enable(host->clk_pix);
+ host->clk_pix_enabled = true;
+ }
+}
+
+/* disable lcdif pix clock */
+static inline void clk_disable_pix(struct mxsfb_info *host)
+{
+ if (host->clk_pix_enabled && (host->clk_pix != NULL)) {
+ clk_disable_unprepare(host->clk_pix);
+ host->clk_pix_enabled = false;
+ }
+}
+
+/* enable lcdif axi clock */
+static inline void clk_enable_axi(struct mxsfb_info *host)
+{
+ if (!host->clk_axi_enabled && (host->clk_axi != NULL)) {
+ clk_prepare_enable(host->clk_axi);
+ host->clk_axi_enabled = true;
+ }
+}
+
+/* disable lcdif axi clock */
+static inline void clk_disable_axi(struct mxsfb_info *host)
+{
+ if (host->clk_axi_enabled && (host->clk_axi != NULL)) {
+ clk_disable_unprepare(host->clk_axi);
+ host->clk_axi_enabled = false;
+ }
+}
+
+/* enable DISP axi clock */
+static inline void clk_enable_disp_axi(struct mxsfb_info *host)
+{
+ if (!host->clk_disp_axi_enabled && (host->clk_disp_axi != NULL)) {
+ clk_prepare_enable(host->clk_disp_axi);
+ host->clk_disp_axi_enabled = true;
+ }
+}
+
+/* disable DISP axi clock */
+static inline void clk_disable_disp_axi(struct mxsfb_info *host)
+{
+ if (host->clk_disp_axi_enabled && (host->clk_disp_axi != NULL)) {
+ clk_disable_unprepare(host->clk_disp_axi);
+ host->clk_disp_axi_enabled = false;
+ }
+}
/* mask and shift depends on architecture */
static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
@@ -241,6 +400,105 @@ static const struct fb_bitfield def_rgb565[] = {
}
};
+#ifdef CONFIG_FB_MXC_OVERLAY
+static u32 saved_as_ctrl;
+static u32 saved_as_next_buf;
+
+static const struct fb_bitfield def_argb555[] = {
+ [RED] = {
+ .offset = 10,
+ .length = 5,
+ },
+ [GREEN] = {
+ .offset = 5,
+ .length = 5,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 5,
+ },
+ [TRANSP] = {
+ .offset = 15,
+ .length = 0,
+ }
+};
+
+static const struct fb_bitfield def_rgb555[] = {
+ [RED] = {
+ .offset = 10,
+ .length = 5,
+ },
+ [GREEN] = {
+ .offset = 5,
+ .length = 5,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 5,
+ },
+ [TRANSP] = {
+ .offset = 0,
+ .length = 0,
+ }
+};
+
+static const struct fb_bitfield def_argb444[] = {
+ [RED] = {
+ .offset = 8,
+ .length = 4,
+ },
+ [GREEN] = {
+ .offset = 4,
+ .length = 4,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 4,
+ },
+ [TRANSP] = {
+ .offset = 12,
+ .length = 4,
+ }
+};
+
+static const struct fb_bitfield def_rgb444[] = {
+ [RED] = {
+ .offset = 8,
+ .length = 4,
+ },
+ [GREEN] = {
+ .offset = 4,
+ .length = 4,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 4,
+ },
+ [TRANSP] = {
+ .offset = 0,
+ .length = 0,
+ }
+};
+#endif
+
+static const struct fb_bitfield def_rgb666[] = {
+ [RED] = {
+ .offset = 16,
+ .length = 6,
+ },
+ [GREEN] = {
+ .offset = 8,
+ .length = 6,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 6,
+ },
+ [TRANSP] = { /* no support for transparency */
+ .length = 0,
+ }
+};
+
static const struct fb_bitfield def_rgb888[] = {
[RED] = {
.offset = 16,
@@ -259,6 +517,38 @@ static const struct fb_bitfield def_rgb888[] = {
}
};
+static const struct fb_bitfield def_argb32[] = {
+ [RED] = {
+ .offset = 16,
+ .length = 8,
+ },
+ [GREEN] = {
+ .offset = 8,
+ .length = 8,
+ },
+ [BLUE] = {
+ .offset = 0,
+ .length = 8,
+ },
+ [TRANSP] = {
+ .offset = 24,
+ .length = 8,
+ }
+};
+
+#define bitfield_is_equal(f1, f2) (!memcmp(&(f1), &(f2), sizeof(f1)))
+
+static inline bool pixfmt_is_equal(struct fb_var_screeninfo *var,
+ const struct fb_bitfield *f)
+{
+ if (bitfield_is_equal(var->red, f[RED]) &&
+ bitfield_is_equal(var->green, f[GREEN]) &&
+ bitfield_is_equal(var->blue, f[BLUE]))
+ return true;
+
+ return false;
+}
+
static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
{
chan &= 0xffff;
@@ -266,10 +556,46 @@ static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
return chan << bf->offset;
}
+static irqreturn_t mxsfb_irq_handler(int irq, void *dev_id)
+{
+ struct mxsfb_info *host = dev_id;
+ u32 ctrl1, enable, status, acked_status;
+
+ ctrl1 = readl(host->base + LCDC_CTRL1);
+ enable = (ctrl1 & CTRL1_IRQ_ENABLE_MASK) >> CTRL1_IRQ_ENABLE_SHIFT;
+ status = (ctrl1 & CTRL1_IRQ_STATUS_MASK) >> CTRL1_IRQ_STATUS_SHIFT;
+ acked_status = (enable & status) << CTRL1_IRQ_STATUS_SHIFT;
+
+ if ((acked_status & CTRL1_VSYNC_EDGE_IRQ) && host->wait4vsync) {
+ writel(CTRL1_VSYNC_EDGE_IRQ,
+ host->base + LCDC_CTRL1 + REG_CLR);
+ writel(CTRL1_VSYNC_EDGE_IRQ_EN,
+ host->base + LCDC_CTRL1 + REG_CLR);
+ host->wait4vsync = 0;
+ complete(&host->vsync_complete);
+ }
+
+ if (acked_status & CTRL1_CUR_FRAME_DONE_IRQ) {
+ writel(CTRL1_CUR_FRAME_DONE_IRQ,
+ host->base + LCDC_CTRL1 + REG_CLR);
+ writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
+ host->base + LCDC_CTRL1 + REG_CLR);
+ complete(&host->flip_complete);
+ }
+
+ if (acked_status & CTRL1_UNDERFLOW_IRQ)
+ writel(CTRL1_UNDERFLOW_IRQ, host->base + LCDC_CTRL1 + REG_CLR);
+
+ if (acked_status & CTRL1_OVERFLOW_IRQ)
+ writel(CTRL1_OVERFLOW_IRQ, host->base + LCDC_CTRL1 + REG_CLR);
+
+ return IRQ_HANDLED;
+}
+
static int mxsfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *fb_info)
{
- struct mxsfb_info *host = to_imxfb_host(fb_info);
+ struct mxsfb_info *host = fb_info->par;
const struct fb_bitfield *rgb = NULL;
if (var->xres < MIN_XRES)
@@ -277,9 +603,18 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
if (var->yres < MIN_YRES)
var->yres = MIN_YRES;
- var->xres_virtual = var->xres;
+ if (var->xres_virtual > var->xres) {
+ dev_dbg(fb_info->device, "stride not supported\n");
+ return -EINVAL;
+ }
- var->yres_virtual = var->yres;
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+
+ if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 16))
+ var->bits_per_pixel = 32;
switch (var->bits_per_pixel) {
case 16:
@@ -290,17 +625,35 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
switch (host->ld_intf_width) {
case STMLCDIF_8BIT:
pr_debug("Unsupported LCD bus width mapping\n");
- break;
+ return -EINVAL;
case STMLCDIF_16BIT:
+ /* 24 bit to 18 bit mapping */
+ rgb = def_rgb666;
+ break;
case STMLCDIF_18BIT:
+ if (pixfmt_is_equal(var, def_rgb666))
+ /* 24 bit to 18 bit mapping */
+ rgb = def_rgb666;
+ else
+ rgb = def_rgb888;
+ break;
case STMLCDIF_24BIT:
/* real 24 bit */
rgb = def_rgb888;
break;
+ default:
+ /*
+ * 32-bit output is possible through I/O muxing, if this
+ * option is available on chip. Currently not
+ * implemented.
+ */
+ pr_debug("Currently unsupported output colour depth: %u\n",
+ host->ld_intf_width);
+ return -EINVAL;
}
break;
default:
- pr_err("Unsupported colour depth: %u\n", var->bits_per_pixel);
+ pr_debug("Unsupported colour depth: %u\n", var->bits_per_pixel);
return -EINVAL;
}
@@ -316,26 +669,24 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
return 0;
}
-static inline void mxsfb_enable_axi_clk(struct mxsfb_info *host)
-{
- if (host->clk_axi)
- clk_prepare_enable(host->clk_axi);
-}
-
-static inline void mxsfb_disable_axi_clk(struct mxsfb_info *host)
-{
- if (host->clk_axi)
- clk_disable_unprepare(host->clk_axi);
-}
-
static void mxsfb_enable_controller(struct fb_info *fb_info)
{
- struct mxsfb_info *host = to_imxfb_host(fb_info);
+ struct mxsfb_info *host = fb_info->par;
u32 reg;
int ret;
dev_dbg(&host->pdev->dev, "%s\n", __func__);
+ if (host->dispdrv && host->dispdrv->drv->setup) {
+ ret = host->dispdrv->drv->setup(host->dispdrv, fb_info);
+ if (ret < 0) {
+ dev_err(&host->pdev->dev, "failed to setup"
+ "dispdrv:%s\n", host->dispdrv->drv->name);
+ return;
+ }
+ host->sync = fb_info->var.sync;
+ }
+
if (host->reg_lcd) {
ret = regulator_enable(host->reg_lcd);
if (ret) {
@@ -345,12 +696,36 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
}
}
- if (host->clk_disp_axi)
- clk_prepare_enable(host->clk_disp_axi);
- clk_prepare_enable(host->clk);
- clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
+ if (host->dispdrv && host->dispdrv->drv->enable) {
+ ret = host->dispdrv->drv->enable(host->dispdrv, fb_info);
+ if (ret < 0)
+ dev_err(&host->pdev->dev, "failed to enable "
+ "dispdrv:%s\n", host->dispdrv->drv->name);
+ }
+
+ /* the pixel clock should be disabled before
+ * trying to set its clock rate successfully.
+ */
+ clk_disable_pix(host);
+ ret = clk_set_rate(host->clk_pix,
+ PICOS2KHZ(fb_info->var.pixclock) * 1000U);
+ if (ret) {
+ dev_err(&host->pdev->dev,
+ "lcd pixel rate set failed: %d\n", ret);
+
+ if (host->reg_lcd) {
+ ret = regulator_disable(host->reg_lcd);
+ if (ret)
+ dev_err(&host->pdev->dev,
+ "lcd regulator disable failed: %d\n",
+ ret);
+ }
+ return;
+ }
+ clk_enable_pix(host);
- mxsfb_enable_axi_clk(host);
+ writel(CTRL2_OUTSTANDING_REQS__REQ_16,
+ host->base + LCDC_V4_CTRL2 + REG_SET);
/* if it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
@@ -360,20 +735,30 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
reg |= VDCTRL4_SYNC_SIGNALS_ON;
writel(reg, host->base + LCDC_VDCTRL4);
+ writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_SET);
writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
+ /* Recovery on underflow */
+ writel(CTRL1_RECOVERY_ON_UNDERFLOW, host->base + LCDC_CTRL1 + REG_SET);
+
host->enabled = 1;
+
}
static void mxsfb_disable_controller(struct fb_info *fb_info)
{
- struct mxsfb_info *host = to_imxfb_host(fb_info);
+ struct mxsfb_info *host = fb_info->par;
unsigned loop;
u32 reg;
int ret;
dev_dbg(&host->pdev->dev, "%s\n", __func__);
+ writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
+
+ if (host->dispdrv && host->dispdrv->drv->disable)
+ host->dispdrv->drv->disable(host->dispdrv, fb_info);
+
/*
* Even if we disable the controller here, it will still continue
* until its FIFOs are running out of data
@@ -388,15 +773,11 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
loop--;
}
+ writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_CLR);
+
reg = readl(host->base + LCDC_VDCTRL4);
writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
- mxsfb_disable_axi_clk(host);
-
- clk_disable_unprepare(host->clk);
- if (host->clk_disp_axi)
- clk_disable_unprepare(host->clk_disp_axi);
-
host->enabled = 0;
if (host->reg_lcd) {
@@ -407,20 +788,60 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
}
}
+/**
+ This function compare the fb parameter see whether it was different
+ parameter for hardware, if it was different parameter, the hardware
+ will reinitialize. All will compared except x/y offset.
+ */
+static bool mxsfb_par_equal(struct fb_info *fbi, struct mxsfb_info *host)
+{
+ /* Here we set the xoffset, yoffset to zero, and compare two
+ * var see have different or not. */
+ struct fb_var_screeninfo oldvar = host->var;
+ struct fb_var_screeninfo newvar = fbi->var;
+
+ if ((fbi->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW &&
+ fbi->var.activate & FB_ACTIVATE_FORCE)
+ return false;
+
+ oldvar.xoffset = newvar.xoffset = 0;
+ oldvar.yoffset = newvar.yoffset = 0;
+
+ return memcmp(&oldvar, &newvar, sizeof(struct fb_var_screeninfo)) == 0;
+}
+
static int mxsfb_set_par(struct fb_info *fb_info)
{
- struct mxsfb_info *host = to_imxfb_host(fb_info);
+ struct mxsfb_info *host = fb_info->par;
u32 ctrl, vdctrl0, vdctrl4;
int line_size, fb_size;
int reenable = 0;
+ static u32 equal_bypass = 0;
+
+ if (likely(equal_bypass > 1)) {
+ /* If parameter no change, don't reconfigure. */
+ if (mxsfb_par_equal(fb_info, host))
+ return 0;
+ } else
+ equal_bypass++;
+
+ dev_dbg(&host->pdev->dev, "%s\n", __func__);
+
+ /* If fb is in blank mode, it is
+ * unnecessary to really set par here.
+ * It can be delayed when unblank fb
+ */
+ if (host->cur_blank != FB_BLANK_UNBLANK)
+ return 0;
line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
+ fb_info->fix.line_length = line_size;
fb_size = fb_info->var.yres_virtual * line_size;
- if (fb_size > fb_info->fix.smem_len)
+ if (fb_size > fb_info->fix.smem_len) {
+ dev_err(&host->pdev->dev, "exceeds the fb buffer size limit!\n");
return -ENOMEM;
-
- fb_info->fix.line_length = line_size;
+ }
/*
* It seems, you can't re-program the controller if it is still running.
@@ -432,8 +853,6 @@ static int mxsfb_set_par(struct fb_info *fb_info)
mxsfb_disable_controller(fb_info);
}
- mxsfb_enable_axi_clk(host);
-
/* clear the FIFOs */
writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
@@ -451,12 +870,22 @@ static int mxsfb_set_par(struct fb_info *fb_info)
ctrl |= CTRL_SET_WORD_LENGTH(3);
switch (host->ld_intf_width) {
case STMLCDIF_8BIT:
- mxsfb_disable_axi_clk(host);
- dev_err(&host->pdev->dev,
+ dev_dbg(&host->pdev->dev,
"Unsupported LCD bus width mapping\n");
return -EINVAL;
case STMLCDIF_16BIT:
+ /* 24 bit to 18 bit mapping */
+ ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
+ * each colour component
+ */
+ break;
case STMLCDIF_18BIT:
+ if (pixfmt_is_equal(&fb_info->var, def_rgb666))
+ /* 24 bit to 18 bit mapping */
+ ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
+ * each colour component
+ */
+ break;
case STMLCDIF_24BIT:
/* real 24 bit */
break;
@@ -465,8 +894,7 @@ static int mxsfb_set_par(struct fb_info *fb_info)
writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
break;
default:
- mxsfb_disable_axi_clk(host);
- dev_err(&host->pdev->dev, "Unhandled color depth of %u\n",
+ dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n",
fb_info->var.bits_per_pixel);
return -EINVAL;
}
@@ -481,13 +909,14 @@ static int mxsfb_set_par(struct fb_info *fb_info)
VDCTRL0_VSYNC_PERIOD_UNIT |
VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
- if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ /* use the saved sync to avoid wrong sync information */
+ if (host->sync & FB_SYNC_HOR_HIGH_ACT)
vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
- if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ if (host->sync & FB_SYNC_VERT_HIGH_ACT)
vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
- if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT)
+ if (!(host->sync & FB_SYNC_OE_LOW_ACT))
vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
- if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT)
+ if (host->sync & FB_SYNC_CLK_LAT_FALL)
vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
writel(vdctrl0, host->base + LCDC_VDCTRL0);
@@ -519,11 +948,15 @@ static int mxsfb_set_par(struct fb_info *fb_info)
fb_info->fix.line_length * fb_info->var.yoffset,
host->base + host->devdata->next_buf);
- mxsfb_disable_axi_clk(host);
-
if (reenable)
mxsfb_enable_controller(fb_info);
+ /* Clear activate as not Reconfiguring framebuffer again */
+ if ((fb_info->var.activate & FB_ACTIVATE_FORCE) &&
+ (fb_info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+ fb_info->var.activate = FB_ACTIVATE_NOW;
+
+ host->var = fb_info->var;
return 0;
}
@@ -567,22 +1000,86 @@ static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return ret;
}
+static int mxsfb_wait_for_vsync(struct fb_info *fb_info)
+{
+ struct mxsfb_info *host = fb_info->par;
+ int ret = 0;
+
+ if (host->cur_blank != FB_BLANK_UNBLANK) {
+ dev_err(fb_info->device, "can't wait for VSYNC when fb "
+ "is blank\n");
+ return -EINVAL;
+ }
+
+ init_completion(&host->vsync_complete);
+
+ host->wait4vsync = 1;
+ writel(CTRL1_VSYNC_EDGE_IRQ_EN,
+ host->base + LCDC_CTRL1 + REG_SET);
+ ret = wait_for_completion_interruptible_timeout(
+ &host->vsync_complete, 1 * HZ);
+ if (ret == 0) {
+ dev_err(fb_info->device,
+ "mxs wait for vsync timeout\n");
+ host->wait4vsync = 0;
+ ret = -ETIME;
+ } else if (ret > 0) {
+ ret = 0;
+ }
+ return ret;
+}
+
+static int mxsfb_ioctl(struct fb_info *fb_info, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -EINVAL;
+
+ switch (cmd) {
+ case MXCFB_WAIT_FOR_VSYNC:
+ ret = mxsfb_wait_for_vsync(fb_info);
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
static int mxsfb_blank(int blank, struct fb_info *fb_info)
{
- struct mxsfb_info *host = to_imxfb_host(fb_info);
+ struct mxsfb_info *host = fb_info->par;
+
+ host->cur_blank = blank;
switch (blank) {
case FB_BLANK_POWERDOWN:
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_NORMAL:
- if (host->enabled)
+ if (host->enabled) {
mxsfb_disable_controller(fb_info);
+ pm_runtime_put_sync_suspend(&host->pdev->dev);
+ }
+
+ clk_disable_disp_axi(host);
+ clk_disable_axi(host);
+ clk_disable_pix(host);
break;
case FB_BLANK_UNBLANK:
- if (!host->enabled)
+ fb_info->var.activate = (fb_info->var.activate & ~FB_ACTIVATE_MASK) |
+ FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+
+ clk_enable_pix(host);
+ clk_enable_axi(host);
+ clk_enable_disp_axi(host);
+
+ if (!host->enabled) {
+ pm_runtime_get_sync(&host->pdev->dev);
+
+ writel(0, host->base + LCDC_CTRL);
+ mxsfb_set_par(host->fb_info);
mxsfb_enable_controller(fb_info);
+ }
break;
}
return 0;
@@ -591,21 +1088,71 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info)
static int mxsfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *fb_info)
{
- struct mxsfb_info *host = to_imxfb_host(fb_info);
+ int ret = 0;
+ struct mxsfb_info *host = fb_info->par;
unsigned offset;
- if (var->xoffset != 0)
+ if (host->cur_blank != FB_BLANK_UNBLANK) {
+ dev_dbg(fb_info->device, "can't do pan display when fb "
+ "is blank\n");
return -EINVAL;
+ }
- offset = fb_info->fix.line_length * var->yoffset;
+ if (var->xoffset > 0) {
+ dev_dbg(fb_info->device, "x panning not supported\n");
+ return -EINVAL;
+ }
+
+ if ((var->yoffset + var->yres > var->yres_virtual)) {
+ dev_err(fb_info->device, "y panning exceeds\n");
+ return -EINVAL;
+ }
- mxsfb_enable_axi_clk(host);
+ init_completion(&host->flip_complete);
+
+ offset = fb_info->fix.line_length * var->yoffset;
/* update on next VSYNC */
writel(fb_info->fix.smem_start + offset,
host->base + host->devdata->next_buf);
- mxsfb_disable_axi_clk(host);
+ writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
+ host->base + LCDC_CTRL1 + REG_SET);
+
+ ret = wait_for_completion_timeout(&host->flip_complete, HZ / 2);
+ if (!ret) {
+ dev_err(fb_info->device,
+ "mxs wait for pan flip timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int mxsfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ u32 len;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ if (offset < info->fix.smem_len) {
+ /* mapping framebuffer memory */
+ len = info->fix.smem_len - offset;
+ vma->vm_pgoff = (info->fix.smem_start + offset) >> PAGE_SHIFT;
+ } else
+ return -EINVAL;
+
+ len = PAGE_ALIGN(len);
+ if (vma->vm_end - vma->vm_start > len)
+ return -EINVAL;
+
+ /* make buffers bufferable */
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+ dev_dbg(info->device, "mmap remap_pfn_range failed\n");
+ return -ENOBUFS;
+ }
return 0;
}
@@ -615,31 +1162,41 @@ static struct fb_ops mxsfb_ops = {
.fb_check_var = mxsfb_check_var,
.fb_set_par = mxsfb_set_par,
.fb_setcolreg = mxsfb_setcolreg,
+ .fb_ioctl = mxsfb_ioctl,
.fb_blank = mxsfb_blank,
.fb_pan_display = mxsfb_pan_display,
+ .fb_mmap = mxsfb_mmap,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
-static int mxsfb_restore_mode(struct mxsfb_info *host,
- struct fb_videomode *vmode)
+static int mxsfb_restore_mode(struct mxsfb_info *host)
{
- struct fb_info *fb_info = &host->fb_info;
+ struct fb_info *fb_info = host->fb_info;
unsigned line_count;
unsigned period;
unsigned long pa, fbsize;
- int bits_per_pixel, ofs, ret = 0;
+ int bits_per_pixel, ofs;
u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
+ struct fb_videomode vmode;
- mxsfb_enable_axi_clk(host);
+ clk_enable_axi(host);
+ clk_enable_disp_axi(host);
+
+ /* Enable pixel clock earlier since in 7D
+ * the lcdif registers should be accessed
+ * when the pixel clock is enabled, otherwise
+ * the bus will be hang.
+ */
+ clk_enable_pix(host);
/* Only restore the mode when the controller is running */
ctrl = readl(host->base + LCDC_CTRL);
- if (!(ctrl & CTRL_RUN)) {
- ret = -EINVAL;
- goto err;
- }
+ if (!(ctrl & CTRL_RUN))
+ return -EINVAL;
+
+ memset(&vmode, 0, sizeof(vmode));
vdctrl0 = readl(host->base + LCDC_VDCTRL0);
vdctrl2 = readl(host->base + LCDC_VDCTRL2);
@@ -648,8 +1205,8 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
transfer_count = readl(host->base + host->devdata->transfer_count);
- vmode->xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
- vmode->yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
+ vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
+ vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
switch (CTRL_GET_WORD_LENGTH(ctrl)) {
case 0:
@@ -660,53 +1217,49 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
break;
case 1:
default:
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
fb_info->var.bits_per_pixel = bits_per_pixel;
- vmode->pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U);
- vmode->hsync_len = get_hsync_pulse_width(host, vdctrl2);
- vmode->left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode->hsync_len;
- vmode->right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) -
- vmode->hsync_len - vmode->left_margin - vmode->xres;
- vmode->vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
+ vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk_pix) / 1000U);
+ vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
+ vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
+ vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
+ vmode.left_margin - vmode.xres;
+ vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
period = readl(host->base + LCDC_VDCTRL1);
- vmode->upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode->vsync_len;
- vmode->lower_margin = period - vmode->vsync_len -
- vmode->upper_margin - vmode->yres;
+ vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len;
+ vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres;
- vmode->vmode = FB_VMODE_NONINTERLACED;
+ vmode.vmode = FB_VMODE_NONINTERLACED;
- vmode->sync = 0;
+ vmode.sync = 0;
if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
- vmode->sync |= FB_SYNC_HOR_HIGH_ACT;
+ vmode.sync |= FB_SYNC_HOR_HIGH_ACT;
if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
- vmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+ vmode.sync |= FB_SYNC_VERT_HIGH_ACT;
pr_debug("Reconstructed video mode:\n");
pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
- vmode->xres, vmode->yres, vmode->hsync_len, vmode->left_margin,
- vmode->right_margin, vmode->vsync_len, vmode->upper_margin,
- vmode->lower_margin);
- pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode->pixclock));
+ vmode.xres, vmode.yres,
+ vmode.hsync_len, vmode.left_margin, vmode.right_margin,
+ vmode.vsync_len, vmode.upper_margin, vmode.lower_margin);
+ pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock));
+
+ fb_add_videomode(&vmode, &fb_info->modelist);
host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
- fb_info->fix.line_length = vmode->xres * (bits_per_pixel >> 3);
+ fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3);
pa = readl(host->base + host->devdata->cur_buf);
- fbsize = fb_info->fix.line_length * vmode->yres;
- if (pa < fb_info->fix.smem_start) {
- ret = -EINVAL;
- goto err;
- }
- if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) {
- ret = -EINVAL;
- goto err;
- }
+ fbsize = fb_info->fix.line_length * vmode.yres;
+ if (pa < fb_info->fix.smem_start)
+ return -EINVAL;
+ if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
+ return -EINVAL;
ofs = pa - fb_info->fix.smem_start;
if (ofs) {
memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
@@ -715,28 +1268,27 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
fb_info->fix.ypanstep = 1;
+ fb_info->fix.ywrapstep = 1;
- clk_prepare_enable(host->clk);
host->enabled = 1;
-err:
- if (ret)
- mxsfb_disable_axi_clk(host);
-
- return ret;
+ return 0;
}
-static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host,
- struct fb_videomode *vmode)
+static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
{
- struct fb_info *fb_info = &host->fb_info;
+ struct fb_info *fb_info = host->fb_info;
struct fb_var_screeninfo *var = &fb_info->var;
struct device *dev = &host->pdev->dev;
struct device_node *np = host->pdev->dev.of_node;
struct device_node *display_np;
- struct videomode vm;
+ struct display_timings *timings = NULL;
+ const char *disp_dev, *disp_videomode;
u32 width;
- int ret;
+ int i;
+ int ret = 0;
+
+ host->id = of_alias_get_id(np, "lcdif");
display_np = of_parse_phandle(np, "display", 0);
if (!display_np) {
@@ -776,77 +1328,222 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host,
goto put_display_node;
}
- ret = of_get_videomode(display_np, &vm, OF_USE_NATIVE_MODE);
- if (ret) {
- dev_err(dev, "failed to get videomode from DT\n");
+ ret = of_property_read_string(np, "disp-dev", &disp_dev);
+ if (!ret) {
+ memcpy(host->disp_dev, disp_dev, strlen(disp_dev));
+
+ if (!of_property_read_string(np, "disp-videomode",
+ &disp_videomode)) {
+ memcpy(host->disp_videomode, disp_videomode,
+ strlen(disp_videomode));
+ }
+
+ /* Timing is from encoder driver */
goto put_display_node;
}
- ret = fb_videomode_from_videomode(&vm, vmode);
- if (ret < 0)
+ timings = of_get_display_timings(display_np);
+ if (!timings) {
+ dev_err(dev, "failed to get display timings\n");
+ ret = -ENOENT;
goto put_display_node;
+ }
+
+ for (i = 0; i < timings->num_timings; i++) {
+ struct videomode vm;
+ struct fb_videomode fb_vm;
+
+ /* Only consider native mode */
+ if (i != timings->native_mode)
+ continue;
+
+ ret = videomode_from_timings(timings, &vm, i);
+ if (ret < 0)
+ goto put_display_node;
+
+ ret = fb_videomode_from_videomode(&vm, &fb_vm);
+ if (ret < 0)
+ goto put_display_node;
- if (vm.flags & DISPLAY_FLAGS_DE_HIGH)
- host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
- if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
- host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT;
+ if (!(vm.flags & DISPLAY_FLAGS_DE_HIGH))
+ fb_vm.sync |= FB_SYNC_OE_LOW_ACT;
+
+ /*
+ * The PIXDATA flags of the display_flags enum are controller
+ * centric, e.g. NEGEDGE means drive data on negative edge.
+ * However, the drivers flag is display centric: Sample the
+ * data on negative (falling) edge. Therefore, check for the
+ * POSEDGE flag:
+ * drive on positive edge => sample on negative edge
+ */
+ if (vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
+ fb_vm.sync |= FB_SYNC_CLK_LAT_FALL;
+ fb_add_videomode(&fb_vm, &fb_info->modelist);
+ }
put_display_node:
+ if (timings)
+ kfree(timings);
of_node_put(display_np);
return ret;
}
-static int mxsfb_init_fbinfo(struct mxsfb_info *host,
- struct fb_videomode *vmode)
+static int mxsfb_init_fbinfo(struct mxsfb_info *host)
{
int ret;
- struct device *dev = &host->pdev->dev;
- struct fb_info *fb_info = &host->fb_info;
+ struct fb_info *fb_info = host->fb_info;
struct fb_var_screeninfo *var = &fb_info->var;
- dma_addr_t fb_phys;
- void *fb_virt;
- unsigned fb_size;
+ struct fb_modelist *modelist;
fb_info->fbops = &mxsfb_ops;
fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
- strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id));
fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
fb_info->fix.ypanstep = 1;
+ fb_info->fix.ywrapstep = 1;
fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
fb_info->fix.accel = FB_ACCEL_NONE;
- ret = mxsfb_init_fbinfo_dt(host, vmode);
+ ret = mxsfb_init_fbinfo_dt(host);
if (ret)
return ret;
+ if (host->id < 0)
+ sprintf(fb_info->fix.id, "mxs-lcdif");
+ else
+ sprintf(fb_info->fix.id, "mxs-lcdif%d", host->id);
+
+ if (!list_empty(&fb_info->modelist)) {
+ /* first video mode in the modelist as default video mode */
+ modelist = list_first_entry(&fb_info->modelist,
+ struct fb_modelist, list);
+ fb_videomode_to_var(var, &modelist->mode);
+ }
+ /* save the sync value getting from dtb */
+ host->sync = fb_info->var.sync;
+
var->nonstd = 0;
var->activate = FB_ACTIVATE_NOW;
var->accel_flags = 0;
var->vmode = FB_VMODE_NONINTERLACED;
+ /* init the color fields */
+ mxsfb_check_var(var, fb_info);
+
+ fb_info->fix.line_length =
+ fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
+ fb_info->fix.smem_len = SZ_32M;
+
/* Memory allocation for framebuffer */
- fb_size = SZ_2M;
- fb_virt = dma_alloc_wc(dev, PAGE_ALIGN(fb_size), &fb_phys, GFP_KERNEL);
- if (!fb_virt)
+ if (mxsfb_map_videomem(fb_info) < 0)
return -ENOMEM;
- fb_info->fix.smem_start = fb_phys;
- fb_info->screen_base = fb_virt;
- fb_info->screen_size = fb_info->fix.smem_len = fb_size;
+ if (mxsfb_restore_mode(host))
+ memset((char *)fb_info->screen_base, 0, fb_info->fix.smem_len);
+
+ return 0;
+}
+
+static int mxsfb_dispdrv_init(struct platform_device *pdev,
+ struct fb_info *fbi)
+{
+ struct mxsfb_info *host = fbi->par;
+ struct mxc_dispdrv_setting setting;
+ struct device *dev = &pdev->dev;
+ char disp_dev[32];
+
+ memset(&setting, 0x0, sizeof(setting));
+ setting.fbi = fbi;
+ memcpy(disp_dev, host->disp_dev, strlen(host->disp_dev));
+ disp_dev[strlen(host->disp_dev)] = '\0';
+
+ /* Use videomode name from dtb, if any given */
+ if (host->disp_videomode) {
+ setting.dft_mode_str = kmalloc(NAME_LEN, GFP_KERNEL);
+ if (setting.dft_mode_str) {
+ memset(setting.dft_mode_str, 0x0, NAME_LEN);
+ memcpy(setting.dft_mode_str, host->disp_videomode,
+ strlen(host->disp_videomode));
+ }
+ }
+
+ host->dispdrv = mxc_dispdrv_gethandle(disp_dev, &setting);
+
+ kfree(setting.dft_mode_str);
- if (mxsfb_restore_mode(host, vmode))
- memset(fb_virt, 0, fb_size);
+ if (IS_ERR(host->dispdrv)) {
+ if (PTR_ERR(host->dispdrv) == -EPROBE_DEFER)
+ return PTR_ERR(host->dispdrv);
+
+ host->dispdrv = NULL;
+ dev_info(dev, "failed to find mxc display driver %s\n",
+ disp_dev);
+ } else
+ dev_info(dev, "registered mxc display driver %s\n",
+ disp_dev);
return 0;
}
static void mxsfb_free_videomem(struct mxsfb_info *host)
{
- struct device *dev = &host->pdev->dev;
- struct fb_info *fb_info = &host->fb_info;
+ struct fb_info *fb_info = host->fb_info;
- dma_free_wc(dev, fb_info->screen_size, fb_info->screen_base,
- fb_info->fix.smem_start);
+ mxsfb_unmap_videomem(fb_info);
+}
+
+/*!
+ * Allocates the DRAM memory for the frame buffer. This buffer is remapped
+ * into a non-cached, non-buffered, memory region to allow palette and pixel
+ * writes to occur without flushing the cache. Once this area is remapped,
+ * all virtual memory access to the video memory should occur at the new region.
+ *
+ * @param fbi framebuffer information pointer
+ *
+ * @return Error code indicating success or failure
+ */
+static int mxsfb_map_videomem(struct fb_info *fbi)
+{
+ if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length)
+ fbi->fix.smem_len = fbi->var.yres_virtual *
+ fbi->fix.line_length;
+
+ fbi->screen_base = dma_alloc_writecombine(fbi->device,
+ fbi->fix.smem_len,
+ (dma_addr_t *)&fbi->fix.smem_start,
+ GFP_DMA | GFP_KERNEL);
+ if (fbi->screen_base == 0) {
+ dev_err(fbi->device, "Unable to allocate framebuffer memory\n");
+ fbi->fix.smem_len = 0;
+ fbi->fix.smem_start = 0;
+ return -EBUSY;
+ }
+
+ dev_dbg(fbi->device, "allocated fb @ paddr=0x%08X, size=%d.\n",
+ (uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
+
+ fbi->screen_size = fbi->fix.smem_len;
+
+ /* Clear the screen */
+ memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
+
+ return 0;
+}
+
+/*!
+ * De-allocates the DRAM memory for the frame buffer.
+ *
+ * @param fbi framebuffer information pointer
+ *
+ * @return Error code indicating success or failure
+ */
+static int mxsfb_unmap_videomem(struct fb_info *fbi)
+{
+ dma_free_writecombine(fbi->device, fbi->fix.smem_len,
+ fbi->screen_base, fbi->fix.smem_start);
+ fbi->screen_base = 0;
+ fbi->fix.smem_start = 0;
+ fbi->fix.smem_len = 0;
+ return 0;
}
static const struct platform_device_id mxsfb_devtype[] = {
@@ -857,6 +1554,9 @@ static const struct platform_device_id mxsfb_devtype[] = {
.name = "imx28-fb",
.driver_data = MXSFB_V4,
}, {
+ .name = "imx7ulp-fb",
+ .driver_data = MXSFB_V5,
+ }, {
/* sentinel */
}
};
@@ -865,10 +1565,601 @@ MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
static const struct of_device_id mxsfb_dt_ids[] = {
{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
+ { .compatible = "fsl,imx7ulp-lcdif", .data = &mxsfb_devtype[2], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
+#ifdef CONFIG_FB_MXC_OVERLAY
+static int overlay_fmt_support(uint32_t fmt)
+{
+ switch (fmt) {
+ case V4L2_PIX_FMT_ARGB32:
+ case V4L2_PIX_FMT_XRGB32:
+ return 32;
+ case V4L2_PIX_FMT_ARGB555:
+ case V4L2_PIX_FMT_ARGB444:
+ case V4L2_PIX_FMT_XRGB555:
+ case V4L2_PIX_FMT_RGB444:
+ case V4L2_PIX_FMT_RGB565:
+ return 16;
+ default:
+ return -EINVAL;
+ }
+}
+
+/* alpha mode */
+#define ALPHA_CTRL_EMBEDDED 0x0
+#define ALPHA_CTRL_OVERRIDE 0x1
+#define ALPHA_CTRL_MULTIPLY 0x2
+#define ALPHA_CTRL_ROPS 0x3
+
+static void overlayfb_enable(struct mxsfb_layer *ofb)
+{
+ struct mxsfb_info *fbi = ofb->fbi;
+
+ if (!lock_fb_info(fbi->fb_info))
+ return;
+
+ if (fbi->cur_blank == FB_BLANK_UNBLANK) {
+ mxsfb_disable_controller(fbi->fb_info);
+ writel(CTRL1_FIFO_CLEAR, fbi->base + LCDC_CTRL1 + REG_SET);
+ }
+
+ writel(0x1, fbi->base + LCDC_AS_CTRL + REG_SET);
+
+ if (fbi->cur_blank == FB_BLANK_UNBLANK) {
+ writel(CTRL1_FIFO_CLEAR, fbi->base + LCDC_CTRL1 + REG_CLR);
+ mxsfb_enable_controller(fbi->fb_info);
+ }
+ unlock_fb_info(fbi->fb_info);
+}
+
+static void overlayfb_disable(struct mxsfb_layer *ofb)
+{
+ struct mxsfb_info *fbi = ofb->fbi;
+
+ writel(0x1, fbi->base + LCDC_AS_CTRL + REG_CLR);
+}
+
+static void overlayfb_setup(struct mxsfb_layer *ofb)
+{
+ uint32_t as_next_buf, as_ctrl = 0;
+ uint8_t format, alpha_ctrl, global_alpha_en = 0;
+ struct mxsfb_info *fbi = ofb->fbi;
+ struct fb_var_screeninfo *var = &ofb->ol_fb->var;
+
+ /* set fb1 framebuffer address */
+ as_next_buf = ofb->video_mem_phys;
+ writel(as_next_buf, fbi->base + LCDC_AS_NEXT_BUF);
+
+ /* clear the LCDC_AS_CTRL */
+ writel(0x0, fbi->base + LCDC_AS_CTRL);
+
+ switch (var->grayscale) {
+ case 0: /* color */
+ switch (var->bits_per_pixel) {
+ case 16: /* RGB565 */
+ format = 0xE;
+ global_alpha_en = 1;
+ break;
+ case 32: /* ARGB8888 */
+ format = 0x0;
+ break;
+ default:
+ return;
+ }
+ break;
+ case 1: /* grayscale */
+ return;
+ default:
+ switch (var->grayscale) {
+ case V4L2_PIX_FMT_ARGB32:
+ format = 0x0;
+ break;
+ case V4L2_PIX_FMT_XRGB32:
+ format = 0x4;
+ global_alpha_en = 1;
+ break;
+ case V4L2_PIX_FMT_ARGB555:
+ format = 0x8;
+ break;
+ case V4L2_PIX_FMT_ARGB444:
+ format = 0x9;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ format = 0xC;
+ global_alpha_en = 1;
+ break;
+ case V4L2_PIX_FMT_RGB444:
+ format = 0xD;
+ global_alpha_en = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ format = 0xE;
+ global_alpha_en = 1;
+ break;
+ default:
+ return;
+ }
+ break;
+ }
+ as_ctrl |= ((format & 0xf) << 4);
+
+ alpha_ctrl = global_alpha_en ? ALPHA_CTRL_OVERRIDE :
+ ALPHA_CTRL_EMBEDDED;
+ as_ctrl |= ((alpha_ctrl & 0x3) << 1);
+ if (global_alpha_en)
+ as_ctrl |= ((ofb->global_alpha & 0xff) << 8);
+
+ writel(as_ctrl, fbi->base + LCDC_AS_CTRL);
+}
+
+static struct mxsfb_layer_ops ofb_ops = {
+ .enable = overlayfb_enable,
+ .disable = overlayfb_disable,
+ .setup = overlayfb_setup,
+};
+
+static int overlayfb_open(struct fb_info *info, int user)
+{
+ struct mxsfb_layer *ofb = (struct mxsfb_layer*)info->par;
+ struct mxsfb_info *fbi = ofb->fbi;
+
+ if (atomic_inc_return(&ofb->usage) == 1) {
+ ofb->ol_fb->var.xres = fbi->fb_info->var.xres;
+ ofb->ol_fb->var.yres = fbi->fb_info->var.yres;
+ ofb->ol_fb->var.xres_virtual = fbi->fb_info->var.xres_virtual;
+ ofb->ol_fb->var.yres_virtual = fbi->fb_info->var.yres;
+ ofb->ol_fb->var.bits_per_pixel = fbi->fb_info->var.bits_per_pixel;
+ ofb->ol_fb->var.vmode = FB_VMODE_NONINTERLACED;
+ }
+
+ return 0;
+}
+
+static int overlayfb_release(struct fb_info *info, int user)
+{
+ struct mxsfb_layer *ofb = (struct mxsfb_layer*)info->par;
+
+ BUG_ON(!atomic_read(&ofb->usage));
+
+ if (atomic_dec_return(&ofb->usage) == 0) {
+ if (ofb->blank_state == FB_BLANK_UNBLANK)
+ ofb->ops->disable(ofb);
+
+ ofb->blank_state = -1;
+ }
+
+ return 0;
+}
+
+static void fill_fmt_bitfields(struct fb_var_screeninfo *var,
+ const struct fb_bitfield *color)
+{
+ var->red = color[RED];
+ var->green = color[GREEN];
+ var->blue = color[BLUE];
+ var->transp = color[TRANSP];
+}
+
+static int overlayfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int bpp;
+ struct mxsfb_layer *ofb = (struct mxsfb_layer*)info->par;
+ struct mxsfb_info *fbi = ofb->fbi;
+ const struct fb_bitfield *rgb = NULL;
+
+ /* lcdif doesn't support different bpp of AS and PS */
+ if (var->bits_per_pixel != fbi->fb_info->var.bits_per_pixel)
+ return -EINVAL;
+
+ /* overlay width & should be equal to fb0 */
+ if ((var->xres != fbi->fb_info->var.xres) ||
+ (var->yres != fbi->fb_info->var.yres))
+ return -EINVAL;
+
+ if ((var->xres > 2048) || (var->yres > 2048))
+ return -EINVAL;
+
+ if (var->xres_virtual > var->xres)
+ return -EINVAL;
+
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+
+ switch (var->grayscale) {
+ case 0: /* color */
+ switch (var->bits_per_pixel) {
+ case 16:/* RGB565 */
+ rgb = def_rgb565;
+ break;
+ case 32:/* ARGB8888 */
+ rgb = def_argb32;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case 1: /* grayscale */
+ return -EINVAL;
+ default: /* fourcc */
+ if ((bpp = overlay_fmt_support(var->grayscale)) < 0) {
+ dev_err(info->dev, "unsupport pixel format for overlay\n");
+ return -EINVAL;
+ }
+
+ var->bits_per_pixel = bpp;
+ if (var->bits_per_pixel < 16)
+ return -EINVAL;
+
+ switch (var->grayscale) {
+ case V4L2_PIX_FMT_ARGB32:
+ rgb = def_argb32;
+ break;
+ case V4L2_PIX_FMT_XRGB32:
+ rgb = def_rgb888;
+ break;
+ case V4L2_PIX_FMT_ARGB555:
+ rgb = def_argb555;
+ break;
+ case V4L2_PIX_FMT_ARGB444:
+ rgb = def_argb444;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ rgb = def_rgb555;
+ break;
+ case V4L2_PIX_FMT_RGB444:
+ rgb = def_rgb444;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ rgb = def_rgb565;
+ break;
+ default:
+ /*
+ * This should never be reached since the verification
+ * is done in overlay_fmt_support(), but handle this in
+ * case there will be a sync error between formats
+ * supported in fmt_support and this function.
+ */
+ return -EINVAL;
+ }
+ break;
+ }
+
+ if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
+ info->fix.smem_len)
+ return -EINVAL;
+
+ fill_fmt_bitfields(var, rgb);
+
+ return 0;
+}
+
+static int overlayfb_set_par(struct fb_info *info)
+{
+ int size, bpp;
+ struct mxsfb_layer *ofb = (struct mxsfb_layer*)info->par;
+ struct mxsfb_info *fbi = ofb->fbi;
+ struct fb_var_screeninfo *var = &ofb->ol_fb->var;
+
+ bpp = var->bits_per_pixel;
+ ofb->ol_fb->fix.line_length = var->xres_virtual * bpp / 8;
+
+ size = PAGE_ALIGN(ofb->ol_fb->fix.line_length * var->yres_virtual);
+ if (ofb->video_mem_size < size)
+ return -EINVAL;
+
+ if (!lock_fb_info(fbi->fb_info))
+ return -EINVAL;
+
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ clk_enable_pix(fbi);
+ clk_enable_axi(fbi);
+ clk_enable_disp_axi(fbi);
+ }
+ unlock_fb_info(fbi->fb_info);
+
+ if (ofb->blank_state == FB_BLANK_UNBLANK)
+ ofb->ops->disable(ofb);
+
+ ofb->ops->setup(ofb);
+
+ if (ofb->blank_state == FB_BLANK_UNBLANK)
+ ofb->ops->enable(ofb);
+
+ if (!lock_fb_info(fbi->fb_info))
+ return -EINVAL;
+
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ clk_disable_disp_axi(fbi);
+ clk_disable_axi(fbi);
+ clk_disable_pix(fbi);
+ }
+ unlock_fb_info(fbi->fb_info);
+
+ if ((var->activate & FB_ACTIVATE_FORCE) &&
+ (var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+ var->activate = FB_ACTIVATE_NOW;
+
+ return 0;
+}
+
+static int overlayfb_blank(int blank, struct fb_info *info)
+{
+ struct mxsfb_layer *ofb = (struct mxsfb_layer*)info->par;
+ struct mxsfb_info *fbi = ofb->fbi;
+
+ if (ofb->blank_state == blank)
+ return 0;
+
+ if (!lock_fb_info(fbi->fb_info))
+ return -EINVAL;
+
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ clk_enable_pix(fbi);
+ clk_enable_axi(fbi);
+ clk_enable_disp_axi(fbi);
+ }
+ unlock_fb_info(fbi->fb_info);
+
+ switch (blank) {
+ case FB_BLANK_POWERDOWN:
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ ofb->ops->disable(ofb);
+ break;
+ case FB_BLANK_UNBLANK:
+ ofb->ops->enable(ofb);
+ break;
+ }
+
+ if (!lock_fb_info(fbi->fb_info))
+ return -EINVAL;
+
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ clk_disable_disp_axi(fbi);
+ clk_disable_axi(fbi);
+ clk_disable_pix(fbi);
+ }
+ unlock_fb_info(fbi->fb_info);
+
+ ofb->blank_state = blank;
+
+ return 0;
+}
+
+static int overlayfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int ret = 0;
+ unsigned int bytes_offset;
+ struct mxsfb_layer *ofb = (struct mxsfb_layer *)info->par;
+ struct mxsfb_info *fbi = ofb->fbi;
+
+ init_completion(&fbi->flip_complete);
+
+ if (!lock_fb_info(fbi->fb_info))
+ return -EINVAL;
+
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ unlock_fb_info(fbi->fb_info);
+ return -EINVAL;
+ }
+
+ unlock_fb_info(fbi->fb_info);
+
+ bytes_offset = info->fix.line_length * var->yoffset;
+ writel(info->fix.smem_start + bytes_offset,
+ fbi->base + LCDC_AS_NEXT_BUF);
+
+ /* update on next VSYNC */
+ writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
+ fbi->base + LCDC_CTRL1 + REG_SET);
+
+ ret = wait_for_completion_timeout(&fbi->flip_complete, HZ / 2);
+ if (!ret) {
+ dev_err(info->device,
+ "overlay wait for pane flip timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static struct fb_ops overlay_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = overlayfb_open,
+ .fb_release = overlayfb_release,
+ .fb_check_var = overlayfb_check_var,
+ .fb_set_par = overlayfb_set_par,
+ .fb_blank = overlayfb_blank,
+ .fb_pan_display = overlayfb_pan_display,
+ .fb_mmap = mxsfb_mmap,
+};
+
+static void init_mxsfb_overlay(struct mxsfb_info *fbi,
+ struct mxsfb_layer *ofb)
+{
+ dev_dbg(&fbi->pdev->dev, "AS overlay init\n");
+
+ ofb->ol_fb->fix.type = FB_TYPE_PACKED_PIXELS;
+ ofb->ol_fb->fix.xpanstep = 0;
+ ofb->ol_fb->fix.ypanstep = 1;
+ ofb->ol_fb->fix.ywrapstep = 1;
+ ofb->ol_fb->fix.visual = FB_VISUAL_TRUECOLOR;
+ ofb->ol_fb->fix.accel = FB_ACCEL_NONE;
+
+ ofb->ol_fb->var.activate = FB_ACTIVATE_NXTOPEN;
+ ofb->ol_fb->var.xres = fbi->fb_info->var.xres;
+ ofb->ol_fb->var.yres = fbi->fb_info->var.yres;
+ ofb->ol_fb->var.xres_virtual = fbi->fb_info->var.xres_virtual;
+ ofb->ol_fb->var.yres_virtual = fbi->fb_info->var.yres;
+ ofb->ol_fb->var.bits_per_pixel = fbi->fb_info->var.bits_per_pixel;
+ ofb->ol_fb->var.vmode = FB_VMODE_NONINTERLACED;
+ ofb->ol_fb->var.nonstd = 0;
+
+ /* Copy timings of primary fb */
+ ofb->ol_fb->var.pixclock = fbi->fb_info->var.pixclock;
+ ofb->ol_fb->var.left_margin = fbi->fb_info->var.left_margin;
+ ofb->ol_fb->var.right_margin = fbi->fb_info->var.right_margin;
+ ofb->ol_fb->var.upper_margin = fbi->fb_info->var.upper_margin;
+ ofb->ol_fb->var.lower_margin = fbi->fb_info->var.lower_margin;
+ ofb->ol_fb->var.hsync_len = fbi->fb_info->var.hsync_len;
+ ofb->ol_fb->var.vsync_len = fbi->fb_info->var.vsync_len;
+
+ ofb->ol_fb->fbops = &overlay_fb_ops;
+ ofb->ol_fb->node = -1;
+ ofb->ol_fb->par = ofb;
+ INIT_LIST_HEAD(&ofb->ol_fb->modelist);
+
+ ofb->id = 0;
+ ofb->ops = &ofb_ops;
+ atomic_set(&ofb->usage, 0);
+ ofb->blank_state = -1;
+ ofb->global_alpha = 255;
+ ofb->fbi = fbi;
+
+ sprintf(ofb->ol_fb->fix.id, "FG");
+}
+
+static int mxsfb_overlay_map_video_memory(struct mxsfb_info *fbi,
+ struct mxsfb_layer *ofb)
+{
+ struct fb_info *fb = fbi->fb_info;
+ BUG_ON(!fb->fix.smem_len);
+
+ ofb->video_mem_size = fb->fix.smem_len;
+ ofb->video_mem = dma_alloc_writecombine(ofb->dev,
+ ofb->video_mem_size,
+ (dma_addr_t *)&ofb->video_mem_phys,
+ GFP_DMA | GFP_KERNEL);
+
+ if (ofb->video_mem == NULL) {
+ dev_err(ofb->dev, "Unable to allocate overlay fb memory\n");
+ return -ENOMEM;
+ }
+
+ /* clear overlay fb memory buffer */
+ memset(ofb->video_mem, 0x0, ofb->video_mem_size);
+
+ ofb->ol_fb->fix.smem_start = ofb->video_mem_phys;
+ ofb->ol_fb->fix.smem_len = ofb->video_mem_size;
+ ofb->ol_fb->screen_base = ofb->video_mem;
+
+ return 0;
+}
+
+static void mxsfb_overlay_init(struct mxsfb_info *fbi)
+{
+ int ret;
+ struct mxsfb_layer *ofb = &fbi->overlay;
+ struct fb_videomode ofb_vm;
+
+ ofb->dev = &fbi->pdev->dev;
+ ofb->ol_fb = framebuffer_alloc(0, ofb->dev);
+ if (!ofb->ol_fb) {
+ dev_err(ofb->dev, "Faild to allocate overlay fbinfo\n");
+ return;
+ }
+
+ init_mxsfb_overlay(fbi, ofb);
+
+ /* add videomode to overlay fb */
+ fb_var_to_videomode(&ofb_vm, &fbi->fb_info->var);
+ ret = fb_add_videomode(&ofb_vm, &ofb->ol_fb->modelist);
+ if (ret) {
+ dev_err(ofb->dev, "add vm to ofb failed\n");
+ goto fb_release;
+ }
+
+ ret = register_framebuffer(ofb->ol_fb);
+ if (ret) {
+ dev_err(ofb->dev, "failed to register overlay\n");
+ goto fb_release;
+ }
+
+ ret = mxsfb_overlay_map_video_memory(fbi, ofb);
+ if (ret) {
+ dev_err(ofb->dev, "failed to map video mem for overlay\n");
+ goto fb_unregister;
+ }
+
+ /* setup the initial params for overlay fb */
+ overlayfb_check_var(&ofb->ol_fb->var, ofb->ol_fb);
+ overlayfb_set_par(ofb->ol_fb);
+
+ ofb->registered = 1;
+
+ return;
+
+fb_unregister:
+ unregister_framebuffer(ofb->ol_fb);
+fb_release:
+ framebuffer_release(ofb->ol_fb);
+}
+
+static void mxsfb_overlay_exit(struct mxsfb_info *fbi)
+{
+ struct mxsfb_layer *ofb = &fbi->overlay;
+
+ if (ofb->registered) {
+ if (ofb->video_mem)
+ dma_free_writecombine(ofb->dev, ofb->video_mem_size,
+ ofb->video_mem, ofb->video_mem_phys);
+
+ unregister_framebuffer(ofb->ol_fb);
+ framebuffer_release(ofb->ol_fb);
+ }
+}
+
+static void mxsfb_overlay_resume(struct mxsfb_info *fbi)
+{
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ clk_enable_pix(fbi);
+ clk_enable_axi(fbi);
+ clk_enable_disp_axi(fbi);
+ }
+
+ writel(saved_as_ctrl, fbi->base + LCDC_AS_CTRL);
+ writel(saved_as_next_buf, fbi->base + LCDC_AS_NEXT_BUF);
+
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ clk_disable_disp_axi(fbi);
+ clk_disable_axi(fbi);
+ clk_disable_pix(fbi);
+ }
+
+}
+
+static void mxsfb_overlay_suspend(struct mxsfb_info *fbi)
+{
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ clk_enable_pix(fbi);
+ clk_enable_axi(fbi);
+ clk_enable_disp_axi(fbi);
+ }
+
+ saved_as_ctrl = readl(fbi->base + LCDC_AS_CTRL);
+ saved_as_next_buf = readl(fbi->base + LCDC_AS_NEXT_BUF);
+
+ if (fbi->cur_blank != FB_BLANK_UNBLANK) {
+ clk_disable_disp_axi(fbi);
+ clk_disable_axi(fbi);
+ clk_disable_pix(fbi);
+ }
+}
+#else
+static void mxsfb_overlay_init(struct mxsfb_info *fbi) {}
+static void mxsfb_overlay_exit(struct mxsfb_info *fbi) {}
+static void mxsfb_overlay_resume(struct mxsfb_info *fbi) {}
+static void mxsfb_overlay_suspend(struct mxsfb_info *fbi) {}
+#endif
+
static int mxsfb_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
@@ -876,28 +2167,58 @@ static int mxsfb_probe(struct platform_device *pdev)
struct resource *res;
struct mxsfb_info *host;
struct fb_info *fb_info;
- struct fb_videomode *mode;
- int ret;
+ struct pinctrl *pinctrl;
+ int irq = platform_get_irq(pdev, 0);
+ int gpio, ret;
if (of_id)
pdev->id_entry = of_id->data;
- fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev);
- if (!fb_info) {
- dev_err(&pdev->dev, "Failed to allocate fbdev\n");
+ gpio = of_get_named_gpio(pdev->dev.of_node, "enable-gpio", 0);
+ if (gpio == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ if (gpio_is_valid(gpio)) {
+ ret = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_OUT_INIT_LOW, "lcd_pwr_en");
+ if (ret) {
+ dev_err(&pdev->dev, "faild to request gpio %d, ret = %d\n", gpio, ret);
+ return ret;
+ }
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Cannot get memory IO resource\n");
+ return -ENODEV;
+ }
+
+ host = devm_kzalloc(&pdev->dev, sizeof(struct mxsfb_info), GFP_KERNEL);
+ if (!host) {
+ dev_err(&pdev->dev, "Failed to allocate IO resource\n");
return -ENOMEM;
}
- mode = devm_kzalloc(&pdev->dev, sizeof(struct fb_videomode),
- GFP_KERNEL);
- if (mode == NULL)
+ fb_info = framebuffer_alloc(0, &pdev->dev);
+ if (!fb_info) {
+ dev_err(&pdev->dev, "Failed to allocate fbdev\n");
+ devm_kfree(&pdev->dev, host);
return -ENOMEM;
+ }
+ host->fb_info = fb_info;
+ fb_info->par = host;
- host = to_imxfb_host(fb_info);
+ ret = devm_request_irq(&pdev->dev, irq, mxsfb_irq_handler, 0,
+ dev_name(&pdev->dev), host);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
+ irq, ret);
+ ret = -ENODEV;
+ goto fb_release;
+ }
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(host->base)) {
+ dev_err(&pdev->dev, "ioremap failed\n");
ret = PTR_ERR(host->base);
goto fb_release;
}
@@ -907,19 +2228,28 @@ static int mxsfb_probe(struct platform_device *pdev)
host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
- host->clk = devm_clk_get(&host->pdev->dev, NULL);
- if (IS_ERR(host->clk)) {
- ret = PTR_ERR(host->clk);
+ host->clk_pix = devm_clk_get(&host->pdev->dev, "pix");
+ if (IS_ERR(host->clk_pix)) {
+ host->clk_pix = NULL;
+ ret = PTR_ERR(host->clk_pix);
goto fb_release;
}
host->clk_axi = devm_clk_get(&host->pdev->dev, "axi");
- if (IS_ERR(host->clk_axi))
+ if (IS_ERR(host->clk_axi)) {
host->clk_axi = NULL;
+ ret = PTR_ERR(host->clk_axi);
+ dev_err(&pdev->dev, "Failed to get axi clock: %d\n", ret);
+ goto fb_release;
+ }
host->clk_disp_axi = devm_clk_get(&host->pdev->dev, "disp_axi");
- if (IS_ERR(host->clk_disp_axi))
+ if (IS_ERR(host->clk_disp_axi)) {
host->clk_disp_axi = NULL;
+ ret = PTR_ERR(host->clk_disp_axi);
+ dev_err(&pdev->dev, "Failed to get disp_axi clock: %d\n", ret);
+ goto fb_release;
+ }
host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd");
if (IS_ERR(host->reg_lcd))
@@ -929,79 +2259,199 @@ static int mxsfb_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!fb_info->pseudo_palette) {
ret = -ENOMEM;
+ dev_err(&pdev->dev, "Failed to allocate pseudo_palette memory\n");
goto fb_release;
}
- ret = mxsfb_init_fbinfo(host, mode);
- if (ret != 0)
- goto fb_release;
+ INIT_LIST_HEAD(&fb_info->modelist);
- fb_videomode_to_var(&fb_info->var, mode);
+ pm_runtime_enable(&host->pdev->dev);
- /* init the color fields */
- mxsfb_check_var(&fb_info->var, fb_info);
-
- platform_set_drvdata(pdev, fb_info);
+ ret = mxsfb_init_fbinfo(host);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to initialize fbinfo: %d\n", ret);
+ goto fb_pm_runtime_disable;
+ }
- ret = register_framebuffer(fb_info);
+ ret = mxsfb_dispdrv_init(pdev, fb_info);
if (ret != 0) {
- dev_err(&pdev->dev,"Failed to register framebuffer\n");
- goto fb_destroy;
+ if (ret == -EPROBE_DEFER)
+ dev_info(&pdev->dev,
+ "Defer fb probe due to dispdrv not ready\n");
+ goto fb_pm_runtime_disable;
+ }
+
+ if (!host->dispdrv) {
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto fb_pm_runtime_disable;
+ }
}
if (!host->enabled) {
- mxsfb_enable_axi_clk(host);
writel(0, host->base + LCDC_CTRL);
- mxsfb_disable_axi_clk(host);
mxsfb_set_par(fb_info);
mxsfb_enable_controller(fb_info);
+ pm_runtime_get_sync(&host->pdev->dev);
+ }
+
+ ret = register_framebuffer(fb_info);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to register framebuffer\n");
+ goto fb_destroy;
+ }
+
+ mxsfb_overlay_init(host);
+
+ console_lock();
+ ret = fb_blank(fb_info, FB_BLANK_UNBLANK);
+ console_unlock();
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to unblank framebuffer\n");
+ goto fb_unregister;
}
dev_info(&pdev->dev, "initialized\n");
return 0;
+fb_unregister:
+ unregister_framebuffer(fb_info);
fb_destroy:
- if (host->enabled)
- clk_disable_unprepare(host->clk);
+ fb_destroy_modelist(&fb_info->modelist);
+fb_pm_runtime_disable:
+ clk_disable_pix(host);
+ clk_disable_axi(host);
+ clk_disable_disp_axi(host);
+
+ pm_runtime_disable(&host->pdev->dev);
+ devm_kfree(&pdev->dev, fb_info->pseudo_palette);
fb_release:
framebuffer_release(fb_info);
+ devm_kfree(&pdev->dev, host);
return ret;
}
static int mxsfb_remove(struct platform_device *pdev)
{
- struct fb_info *fb_info = platform_get_drvdata(pdev);
- struct mxsfb_info *host = to_imxfb_host(fb_info);
+ struct mxsfb_info *host = platform_get_drvdata(pdev);
+ struct fb_info *fb_info = host->fb_info;
if (host->enabled)
mxsfb_disable_controller(fb_info);
+ if (host->devdata->flags & MXSFB_FLAG_PMQOS)
+ pm_qos_remove_request(&host->pm_qos_req);
+
+ pm_runtime_disable(&host->pdev->dev);
+ mxsfb_overlay_exit(host);
unregister_framebuffer(fb_info);
mxsfb_free_videomem(host);
+ platform_set_drvdata(pdev, NULL);
+
+ devm_kfree(&pdev->dev, fb_info->pseudo_palette);
framebuffer_release(fb_info);
+ devm_kfree(&pdev->dev, host);
return 0;
}
static void mxsfb_shutdown(struct platform_device *pdev)
{
- struct fb_info *fb_info = platform_get_drvdata(pdev);
- struct mxsfb_info *host = to_imxfb_host(fb_info);
-
- mxsfb_enable_axi_clk(host);
+ struct mxsfb_info *host = platform_get_drvdata(pdev);
/*
* Force stop the LCD controller as keeping it running during reboot
* might interfere with the BootROM's boot mode pads sampling.
*/
- writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
+ if (host->cur_blank == FB_BLANK_UNBLANK) {
+ writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
+ writel(CTRL_MASTER, host->base + LCDC_CTRL + REG_CLR);
+ }
+}
+
+#ifdef CONFIG_PM
+static int mxsfb_runtime_suspend(struct device *dev)
+{
+ struct mxsfb_info *host = dev_get_drvdata(dev);
- mxsfb_disable_axi_clk(host);
+ if (host->devdata->flags & MXSFB_FLAG_BUSFREQ)
+ release_bus_freq(BUS_FREQ_HIGH);
+
+ if (host->devdata->flags & MXSFB_FLAG_PMQOS)
+ pm_qos_remove_request(&host->pm_qos_req);
+
+ dev_dbg(dev, "mxsfb busfreq high release.\n");
+
+ return 0;
}
+static int mxsfb_runtime_resume(struct device *dev)
+{
+ struct mxsfb_info *host = dev_get_drvdata(dev);
+
+ if (host->devdata->flags & MXSFB_FLAG_BUSFREQ)
+ request_bus_freq(BUS_FREQ_HIGH);
+
+ if (host->devdata->flags & MXSFB_FLAG_PMQOS)
+ pm_qos_add_request(&host->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, 0);
+
+ dev_dbg(dev, "mxsfb busfreq high request.\n");
+
+ return 0;
+}
+
+static int mxsfb_suspend(struct device *pdev)
+{
+ struct mxsfb_info *host = dev_get_drvdata(pdev);
+ struct fb_info *fb_info = host->fb_info;
+ int saved_blank;
+
+ console_lock();
+ mxsfb_overlay_suspend(host);
+ fb_set_suspend(fb_info, 1);
+ saved_blank = host->cur_blank;
+ mxsfb_blank(FB_BLANK_POWERDOWN, fb_info);
+ host->restore_blank = saved_blank;
+ console_unlock();
+
+ pinctrl_pm_select_sleep_state(pdev);
+
+ return 0;
+}
+
+static int mxsfb_resume(struct device *pdev)
+{
+ struct mxsfb_info *host = dev_get_drvdata(pdev);
+ struct fb_info *fb_info = host->fb_info;
+
+ pinctrl_pm_select_default_state(pdev);
+
+ console_lock();
+ mxsfb_blank(host->restore_blank, fb_info);
+ fb_set_suspend(fb_info, 0);
+ mxsfb_overlay_resume(host);
+ console_unlock();
+
+ return 0;
+}
+#else
+#define mxsfb_runtime_suspend NULL
+#define mxsfb_runtime_resume NULL
+
+#define mxsfb_suspend NULL
+#define mxsfb_resume NULL
+#endif
+
+static const struct dev_pm_ops mxsfb_pm_ops = {
+ SET_RUNTIME_PM_OPS(mxsfb_runtime_suspend, mxsfb_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(mxsfb_suspend, mxsfb_resume)
+};
+
static struct platform_driver mxsfb_driver = {
.probe = mxsfb_probe,
.remove = mxsfb_remove,
@@ -1010,6 +2460,7 @@ static struct platform_driver mxsfb_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = mxsfb_dt_ids,
+ .pm = &mxsfb_pm_ops,
},
};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 3eb58cb51e56..b39f89841573 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -552,6 +552,19 @@ config IMX2_WDT
To compile this driver as a module, choose M here: the
module will be called imx2_wdt.
+config IMX7ULP_WDT
+ tristate "IMX7ULP Watchdog"
+ depends on ARCH_MXC
+ select WATCHDOG_CORE
+ help
+ This is the driver for the hardware watchdog
+ on the Freescale IMX7ULP and later processors.
+ If you have one of these processors and wish to have
+ watchdog support enabled, say Y, otherwise say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called imx7ulp_wdt.
+
config UX500_WATCHDOG
tristate "ST-Ericsson Ux500 watchdog"
depends on MFD_DB8500_PRCMU
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4aa492a..1954250cb07c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
obj-$(CONFIG_TS4800_WATCHDOG) += ts4800_wdt.o
obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
+obj-$(CONFIG_IMX7ULP_WDT) += imx7ulp_wdt.o
obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o
obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o
obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 518dfa1047cb..93ccdb35c44f 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -2,7 +2,8 @@
* Watchdog driver for IMX2 and later processors
*
* Copyright (C) 2010 Wolfram Sang, Pengutronix e.K. <w.sang@pengutronix.de>
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP.
*
* some parts adapted by similar drivers from Darius Augulis and Vladimir
* Zapolskiy, additional improvements by Wim Van Sebroeck.
@@ -106,6 +107,7 @@ static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action,
/* Assert SRS signal */
regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
+
/*
* Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
* written twice), we add another two writes to ensure there must be at
diff --git a/drivers/watchdog/imx7ulp_wdt.c b/drivers/watchdog/imx7ulp_wdt.c
new file mode 100644
index 000000000000..b54268849ce6
--- /dev/null
+++ b/drivers/watchdog/imx7ulp_wdt.c
@@ -0,0 +1,291 @@
+/*
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/watchdog.h>
+
+#define WDOG_CS 0x0
+#define WDOG_CS_CMD32EN (1 << 13)
+#define WDOG_CS_ULK (1 << 11)
+#define WDOG_CS_RCS (1 << 10)
+#define WDOG_CS_EN (1 << 7)
+#define WDOG_CS_UPDATE (1 << 5)
+
+#define WDOG_CNT 0x4
+#define WDOG_TOVAL 0x8
+
+#define REFRESH_SEQ0 0xA602
+#define REFRESH_SEQ1 0xB480
+#define REFRESH ((REFRESH_SEQ1 << 16) | (REFRESH_SEQ0))
+
+#define UNLOCK_SEQ0 0xC520
+#define UNLOCK_SEQ1 0xD928
+#define UNLOCK ((UNLOCK_SEQ1 << 16) | (UNLOCK_SEQ0))
+
+struct imx7ulp_wdt {
+ void __iomem *base;
+ int rate;
+ struct watchdog_device wdd;
+ struct notifier_block restart_handler;
+};
+
+static inline void imx7ulp_wdt_enable(void __iomem *base, bool enable)
+{
+ u32 val = readl(base + WDOG_CS);
+
+ local_irq_disable();
+
+ writel(UNLOCK, base + WDOG_CNT);
+ if (enable)
+ writel(val | WDOG_CS_EN, base + WDOG_CS);
+ else
+ writel(val & ~WDOG_CS_EN, base + WDOG_CS);
+
+ local_irq_enable();
+}
+
+static inline bool imx7ulp_wdt_is_enabled(void __iomem *base)
+{
+ u32 val = readl(base + WDOG_CS);
+
+ return val & WDOG_CS_EN;
+}
+
+static int imx7ulp_wdt_ping(struct watchdog_device *wdog)
+{
+ /* refresh the wdt counter to keepalive */
+ struct imx7ulp_wdt *wdt = watchdog_get_drvdata(wdog);
+ local_irq_disable();
+ writel(REFRESH, wdt->base + WDOG_CNT);
+ local_irq_enable();
+ return 0;
+}
+
+static int imx7ulp_wdt_start(struct watchdog_device *wdog)
+{
+ struct imx7ulp_wdt *wdt = watchdog_get_drvdata(wdog);
+ imx7ulp_wdt_enable(wdt->base, true);
+
+ return 0;
+}
+
+static int imx7ulp_wdt_stop(struct watchdog_device *wdog)
+{
+ struct imx7ulp_wdt *wdt = watchdog_get_drvdata(wdog);
+ imx7ulp_wdt_enable(wdt->base, false);
+
+ return 0;
+}
+
+static int imx7ulp_wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout)
+{
+ struct imx7ulp_wdt *wdt = watchdog_get_drvdata(wdog);
+ u32 val = wdt->rate * timeout;
+
+ local_irq_disable();
+
+ writel(UNLOCK, wdt->base + WDOG_CNT);
+ writel(val, wdt->base + WDOG_TOVAL);
+
+ local_irq_enable();
+
+ wdog->timeout = timeout;
+
+ imx7ulp_wdt_ping(wdog);
+
+ return 0;
+}
+
+static const struct watchdog_ops imx7ulp_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = imx7ulp_wdt_start,
+ .stop = imx7ulp_wdt_stop,
+ .ping = imx7ulp_wdt_ping,
+ .set_timeout = imx7ulp_wdt_set_timeout,
+};
+
+static const struct watchdog_info imx7ulp_wdt_info = {
+ .identity = "i.MX7ULP watchdog timer",
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
+ | WDIOF_MAGICCLOSE,
+};
+
+static int imx7ulp_wdt_restart_handler(struct notifier_block *this,
+ unsigned long action, void *data)
+{
+ struct imx7ulp_wdt *wdt = container_of(this, struct imx7ulp_wdt, restart_handler);
+
+ local_irq_disable();
+
+ imx7ulp_wdt_enable(wdt->base, true);
+ imx7ulp_wdt_set_timeout(&wdt->wdd, 1);
+
+ local_irq_enable();
+
+ /* wait for wdog to fire */
+ while(true)
+ ;
+
+ return NOTIFY_DONE;
+}
+
+static inline void imx7ulp_wdt_init(void __iomem *base, unsigned int timeout)
+{
+ u32 val;
+
+ local_irq_disable();
+
+ /* unlock the wdog for reconfiguration */
+ writel_relaxed(UNLOCK_SEQ0, base + WDOG_CNT);
+ writel_relaxed(UNLOCK_SEQ1, base + WDOG_CNT);
+
+ /*set an initial timeout value in TOVAL */
+ writel(timeout, base + WDOG_TOVAL);
+ /* enable 32bit command sequence and reconfigure */
+ val = (1 << 13) | (1 << 8) | (1 << 5);
+ writel(val, base + WDOG_CS);
+
+ local_irq_enable();
+}
+
+static int imx7ulp_wdt_probe(struct platform_device *pdev)
+{
+ struct imx7ulp_wdt *wdt;
+ struct resource *res;
+ int err;
+ u32 timeout;
+
+ wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+ if (!wdt)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, wdt);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ wdt->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(wdt->base))
+ return PTR_ERR(wdt->base);
+
+ /* use the 1KHz LPO as the counter clock */
+ wdt->rate = 1000;
+
+ /* init the wdd */
+ wdt->wdd.info = &imx7ulp_wdt_info;
+ wdt->wdd.ops = &imx7ulp_wdt_ops;
+ wdt->wdd.min_timeout = 1;
+ wdt->wdd.max_timeout = 60;
+ wdt->wdd.parent = &pdev->dev;
+ watchdog_set_drvdata(&wdt->wdd, wdt);
+ /*
+ * set the timeout_parm to 0 to get the timeout
+ * from 'timeout-sec' property in dtb.
+ */
+ err = watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init the wdog timeout\n");
+ return err;
+ }
+
+ timeout = wdt->wdd.timeout * wdt->rate;
+ /* reconfigure the watchdog timer.*/
+ imx7ulp_wdt_init(wdt->base, timeout);
+
+ err = watchdog_register_device(&wdt->wdd);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to register watchdog device\n");
+ return err;
+ }
+
+ wdt->restart_handler.notifier_call = imx7ulp_wdt_restart_handler;
+ wdt->restart_handler.priority = 128;
+ err = register_restart_handler(&wdt->restart_handler);
+ if (err) {
+ dev_err(&pdev->dev, "cannot register restart handler\n");
+ watchdog_unregister_device(&wdt->wdd);
+ return err;
+ }
+
+ return 0;
+}
+
+static int imx7ulp_wdt_remove(struct platform_device *pdev)
+{
+ struct imx7ulp_wdt *wdt = platform_get_drvdata(pdev);
+
+ imx7ulp_wdt_stop(&wdt->wdd);
+
+ watchdog_unregister_device(&wdt->wdd);
+
+ return 0;
+}
+
+static void imx7ulp_wdt_shutdown(struct platform_device *pdev)
+{
+ struct imx7ulp_wdt *wdt = platform_get_drvdata(pdev);
+
+ if (watchdog_active(&wdt->wdd))
+ imx7ulp_wdt_stop(&wdt->wdd);
+}
+
+#ifdef CONFIG_PM_SLEEP
+/* Disable watchdog before suspend */
+static int imx7ulp_wdt_suspend(struct device *dev)
+{
+ struct imx7ulp_wdt *wdt = dev_get_drvdata(dev);
+
+ imx7ulp_wdt_enable(wdt->base, false);
+
+ return 0;
+}
+
+static int imx7ulp_wdt_resume(struct device *dev)
+{
+ struct imx7ulp_wdt *wdt = dev_get_drvdata(dev);
+ u32 timeout = wdt->wdd.timeout * wdt->rate;
+
+ if (imx7ulp_wdt_is_enabled(wdt->base))
+ imx7ulp_wdt_init(wdt->base, timeout);
+
+ if (watchdog_active(&wdt->wdd))
+ imx7ulp_wdt_enable(wdt->base, true);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(imx7ulp_wdt_pm_ops, imx7ulp_wdt_suspend,
+ imx7ulp_wdt_resume);
+
+static const struct of_device_id imx7ulp_wdt_dt_ids[] = {
+ { .compatible = "fsl,imx7ulp-wdt", },
+ { /*sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx7ulp_wdt_dt_ids);
+
+static struct platform_driver imx7ulp_wdt_driver = {
+ .probe = imx7ulp_wdt_probe,
+ .remove = imx7ulp_wdt_remove,
+ .shutdown = imx7ulp_wdt_shutdown,
+ .driver = {
+ .name = "imx7ulp-wdt",
+ .pm = &imx7ulp_wdt_pm_ops,
+ .of_match_table = imx7ulp_wdt_dt_ids,
+ },
+};
+
+module_platform_driver(imx7ulp_wdt_driver);
+
+MODULE_AUTHOR("Bai Ping <ping.bai@nxp.com>");
+MODULE_DESCRIPTION("Freescale i.MX7ULP watchdog driver");
+MODULE_LICENSE("GPL v2");
diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..ee4c05c918c7 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -61,6 +61,7 @@ fw-shipped-$(CONFIG_DRM_RADEON) += radeon/R100_cp.bin radeon/R200_cp.bin \
radeon/RV770_pfp.bin radeon/RV770_me.bin \
radeon/RV730_pfp.bin radeon/RV730_me.bin \
radeon/RV710_pfp.bin radeon/RV710_me.bin
+fw-shipped-$(CONFIG_IMX_SDMA) += imx/sdma/sdma-imx6q.bin imx/sdma/sdma-imx7d.bin
fw-shipped-$(CONFIG_DVB_AV7110) += av7110/bootcode.bin
fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin
fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \
diff --git a/firmware/imx/sdma/sdma-imx6q.bin.ihex b/firmware/imx/sdma/sdma-imx6q.bin.ihex
new file mode 100755
index 000000000000..ba5da62ce733
--- /dev/null
+++ b/firmware/imx/sdma/sdma-imx6q.bin.ihex
@@ -0,0 +1,139 @@
+:1000000053444D4103000000030000001C000000A9
+:1000100029000000C0000000D40700008202000098
+:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
+:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
+:10004000FFFFFFFFFFFFFFFF421A0000FFFFFFFF60
+:10005000EB020000B4180000FFFFFFFF9E1A000033
+:10006000FFFFFFFFC0030000FFFFFFFFFFFFFFFFD9
+:10007000FFFFFFFFAB020000FFFFFFFF7B0300005D
+:10008000FFFFFFFFFFFFFFFF4C0400006E040000B6
+:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
+:1000A000FFFFFFFF001800005B180000EE190000C2
+:1000B0004D1B0000E81A0000841B0000001800001F
+:1000C000E3C1DB57F352016AFB52D36AFB521C1A9D
+:1000D000C36AE8621102FF3A3008D0023F7C8F0009
+:1000E0003F00D500017D8D00A005EB5D7804037D08
+:1000F00079041C7D207C7904157CEE566006057D14
+:100100000965337E0A62317E29980A622E7E09656E
+:100110002C7E12051205AD02C86A277F0320004815
+:10012000ED7C419802780962C86A4098150002780F
+:100130000A62C86A40981500150002780B62C86A06
+:10014000147CDF6D127F7F07097DFB52041AC36A9E
+:10015000D36AC862042AC86AFB52D36A0000EB550E
+:10016000004D077DFAC1DB5706980700CC680C6884
+:1001700013C20AC20198D9C1E3C1DB57E35FE35759
+:10018000F352216A8F00D500017D8D00A005EB5D43
+:10019000FB567804037D79042A7D317C7904207C28
+:1001A000700B1103EB53000F6003057D0965377E6B
+:1001B0000A62357E7F980A62327E0965307E1205BA
+:1001C0001205AD026007027D065A8798265A277FDE
+:1001D000011F03200048E87C700B11031353A898FB
+:1001E000150004780962065A0962265AA798150074
+:1001F000150004780A62065A0A62265AA798150062
+:100200001500150004780B62065A0B62265A077C0B
+:100210000000EB55004D067DFAC1E35762980700D8
+:100220000C6813C20AC25F98700B110313536C075A
+:10023000017CD9C1FB5E8A066B07017CD9C1F35EE4
+:10024000DB59D3588F0110010F398B003CC12B7D36
+:10025000C05AC85B4EC1277C88038906E35CFF0D4A
+:100260001105FF1DBC053E07004D187D70081100EB
+:100270007E07097D7D07027D2852DF98F852DB5406
+:10028000BC02CC02097C7C07027D2852E898F85217
+:10029000D354BC02CC02097D0004D6988B00C05216
+:1002A000C85359C1D67D0002C698FF08BF007F071A
+:1002B000157D8804D500017D8D00A005EB5D8F02C2
+:1002C00012021202FF3ADA05027C3E071399A402D9
+:1002D000DD02027D3E0713995E071399EB55004D31
+:1002E000027C9805EB5DF352FB546A07387D6C077E
+:1002F000017D62996B077D7C6907047D6807027D3B
+:10030000010E2A999358D600017D8E009355A005C1
+:10031000935DA0066D07067D6E070B7D0278025582
+:10032000045D3F99150004780255045D2255045D73
+:100330003F99150004780255045D0255245D1D7C2B
+:10034000004E087C6907037D0255177E4999045DBC
+:10035000147F890693500048017D2299D599150094
+:1003600006780255045D4F070255245D2F07017C76
+:10037000D59917006F07017C012093559D00070058
+:10038000DCD9EE986907047D6807027D010E70993B
+:100390009358D600017D8E009355A005935DA0066D
+:1003A0006D07077D6E070D7DD36C02780255C86D11
+:1003B00088991500D36C04780255C86D2255C86D14
+:1003C000889915000578D76C0255C86D0255C86D1F
+:1003D0000F7C004E087C6907037D0255097E9299C7
+:1003E000C86D067F890693500048017D6899D599AC
+:1003F000CF996907047D6807027D010EA79993587C
+:10040000D600017D8E009355A005935DA0066D0773
+:10041000077D6E070D7DC36A0278C865045DBF99CC
+:1004200015000578C76AC865045DC865045DBF9995
+:100430001500C36A0478C865045DC865245D0F7C37
+:10044000004E087C6907037DC865097EC999045D73
+:10045000067F890693500048017D9F99D599935551
+:100460009D000700FF6CDCD9EE980000E354EB55CB
+:10047000004D017CEE98D698E354EB55FF0A11022B
+:10048000FF1A7F07027CA005E9999D008C05BA053B
+:10049000A0051002BA04AD0454040600D9C1E3C19A
+:1004A000DB57F352056A8F00D500017D8D00A00552
+:1004B000FB567804037D7904297D1F7C79042E7C0A
+:1004C000E35D700D1105ED55000F6007027D0652CA
+:1004D0000A9A2652337E6005027D10021202096AD2
+:1004E0002D7F1202096A2A7F1202096A277F011FE3
+:1004F00003200048EA7CE355359A150015001500E5
+:10050000047806520B6A26520B6A349A15001500BD
+:10051000047806520A6A26520A6A349A1500047848
+:100520000652096A2652096A097C286A077F000078
+:10053000DB57004D057DFAC1DB57F39977C25404B0
+:100540000AC2F099E3C1DB57F352056AFB568E02EB
+:10055000941AC36AC8626902267D941EC36ED36E64
+:10056000C862010A1102C86A9426981EC36EC86246
+:100570009826C36E60020F7D981EC36EC8626C021F
+:10058000037D9826C36E819A100A1102D36EC86A41
+:100590009826C36E919AC8626D9A096A187F0125E0
+:1005A000004D1F7D559AE36E8F00D805017D8D00AB
+:1005B000C862096A0C7F01250120FA7CDB57004DD7
+:1005C000107D286A047F0000FAC1DB57469A0700B5
+:1005D00004620C6A8E9A286AFA7F04627AC258040E
+:1005E0005404FF081100FF18BC00CD00017C819A63
+:1005F000286AED7F04627AC20AC2439AD9C1E3C174
+:10060000DB57F352056AFB568E02941A02526902B6
+:100610001D7D941E06524802065A9426981E0652C4
+:100620004C02065A9826981E065260020A7C9826AA
+:1006300006526E02237D096A1D7F0125004D247D2F
+:10064000B39A286A177F04627AC2E49A8F00D805A9
+:10065000017D8D00A00506526E02107D096A0A7F99
+:100660000120F97C286A067F0000004D0D7DFAC14B
+:10067000DB57A39A070004620C6AE19A286AFA7FA2
+:1006800004627AC258045404286AF47F0AC2A09A09
+:100690002CDBDB57F352056AC7698F00D500017D5B
+:1006A0008D00A0057804037D79041C7D157C7904F8
+:1006B0001E7CEE56C862287E6006027D1002120281
+:1006C000096A227F1202096A1F7F1202096A1C7FCF
+:1006D00003200048EF7C1B9B150015000278C862C0
+:1006E0000B6A1A9B15000278C8620A6A1A9B027884
+:1006F000C862096A097C286A077F004D077DD352CA
+:10070000010802580004EC9A77C25404D35201083D
+:100710000258010444DBE99A700B11031353DB5FA9
+:100720000A07D3588B00FB5E3CC1157DC05AC85BDD
+:100730004EC1117C8803F05DFF0D1105FF1DBC0546
+:10074000004D047D439B0807DB5F0A078B00C35203
+:10075000CB5359C1EC7D0002349B016E0B612F7E9F
+:100760000B622D7E0B632B7E0C0D170417041704F0
+:100770009D04081DCC05017C0C0DD16A000F4207B9
+:10078000C86FDD6F1C7F8E009D0001680B67177EB0
+:10079000D56B04080278C86F1207117C0B670F7EB7
+:1007A00004080278C86F12070A7CDD6F087FD169E0
+:1007B000010FC86FDD6F037F01010004599B070023
+:1007C000FF680C680002599BC9DBDB57F352056ACE
+:1007D000FB52C76A8F00D500017D8D00A00578040B
+:1007E000037D79041C7D157C79041E7CEE56C8625D
+:1007F000287E6006027D10021202096A227F120220
+:10080000096A1F7F1202096A1C7F03200048EF7CDF
+:10081000B89B150015000278C8620B6AB79B1500DB
+:100820000278C8620A6AB79B0278C862096A097CC2
+:10083000286A077F004D077DD35201080258000443
+:10084000889B77C25404D352010802580104E1DBAB
+:10085000859B700B11031353DB5F0A07D3588B0082
+:10086000FB5E3CC1157DC05AC85B4EC1117C88033C
+:10087000F05DFF0D1105FF1DBC05004D047DE09BE3
+:100880000807DB5F0A078B00C352CB5359C1EC7DCD
+:040890000002D19BF6
+:00000001FF
diff --git a/firmware/imx/sdma/sdma-imx7d.bin.ihex b/firmware/imx/sdma/sdma-imx7d.bin.ihex
new file mode 100644
index 000000000000..4d88fe28849c
--- /dev/null
+++ b/firmware/imx/sdma/sdma-imx7d.bin.ihex
@@ -0,0 +1,145 @@
+:1000000053444D4104000000020000001C000000A9
+:100010002A000000C40000003A080000840200002A
+:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
+:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
+:10004000FFFFFFFFFFFFFFFF081A0000FFFFFFFF9A
+:10005000ED020000B4180000FFFFFFFF641A00006B
+:10006000FFFFFFFFC2030000FFFFFFFFFFFFFFFFD7
+:10007000FFFFFFFFAD020000FFFFFFFF7D03000059
+:10008000FFFFFFFFFFFFFFFF4E04000070040000B2
+:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
+:1000A000FFFFFFFF001800005B180000B4190000FC
+:1000B000131B0000AE1A00004A1B000000180000CD
+:1000C000FFFFFFFFE5C1DB57F352016AFB52D36A22
+:1000D000FB521C1AC36AE8621102FF3A3008D002D0
+:1000E0003F7C8F003F00D500017D8D00A005EB5DBA
+:1000F0007804037D79041C7D207C7904157CEE5600
+:100100006006057D0965337E0A62317E29980A62A0
+:100110002E7E09652C7E12051205AD02C86A277F66
+:1001200003200048ED7C419802780962C86A409833
+:10013000150002780A62C86A409815001500027816
+:100140000B62C86A147CDF6D127F7F07097DFB524A
+:10015000041AC36AD36AC862042AC86AFB52D36A03
+:100160000000EB55004D077DFCC1DB5706980700EA
+:10017000CC680C6815C20CC20198D9C1E5C1DB5727
+:10018000E35FE357F352216A8F00D500017D8D00B4
+:10019000A005EB5DFB567804037D79042A7D317C54
+:1001A0007904207C700B1103EB53000F6003057D75
+:1001B0000965377E0A62357E7F980A62327E09655C
+:1001C000307E12051205AD026007027C065A879840
+:1001D000265A277F011F03200048E87C700B11037B
+:1001E0001353A898150004780962065A0962265A22
+:1001F000A7981500150004780A62065A0A62265A62
+:10020000A79815001500150004780B62065A0B62BA
+:10021000265A077C0000EB55004D067DFCC1E357D4
+:10022000629807000C6815C20CC25F98700B11032E
+:1002300013536C07017CD9C1FB5E8A066B07017CF6
+:10024000D9C1F35EDB59D3588F0110010F398B00F0
+:100250003CC12B7DC05AC85B4EC1277C88038906F0
+:10026000E35CFF0D1105FF1DBC053E07004D187D29
+:10027000700811007E07097D7D07027D2852DF98F6
+:10028000F852DB54BC02CC02097C7C07027D285268
+:10029000E898F852D354BC02CC02097D0004D698E9
+:1002A0008B00C052C85359C1D67D0002C698FF08C2
+:1002B000BF007F07157D8804D500017D8D00A00556
+:1002C000EB5D8F0212021202FF3ADA05027C3E0752
+:1002D0001399A402DD02027D3E0713995E0713996C
+:1002E000EB55004D027C9805EB5DF352FB546A0719
+:1002F000267D6C07017D50996B07577C6907047D4B
+:100300006807027D010E2A999358D600017D8E0060
+:100310009355A005935DA00602780255045D1D7CEF
+:10032000004E087C6907037D0255177E3799045DEE
+:10033000147F890693500048017D22999B991500EE
+:1003400006780255045D4F070255245D2F07017C96
+:100350009B9917006F07017C012093559D000700B2
+:10036000A2D9EE98D36C6907047D6807027D010E5F
+:100370005F999358D600017D8E009355A005935D3B
+:10038000A00602780255C86D0F7C004E087C6907F4
+:10039000037D0255097E6C99C86D067F89069350CE
+:1003A0000048017D57999B999599C36A6907047D17
+:1003B0006807027D010E82999358D600017D8E0058
+:1003C0009355A005935DA0060278C865045D0F7C77
+:1003D000004E087C6907037DC865097E8F99045D1E
+:1003E000067F890693500048017D7A999B99935521
+:1003F0009D000700FF6CA2D9EE980000E354EB5576
+:10040000004D017CEE98D698E354EB55FF0A11029B
+:10041000FF1A7F07027CA005AF999D008C05BA05E5
+:10042000A0051002BA04AD0454040600D9C1E5C108
+:10043000DB57F352056A8F00D500017D8D00A005C2
+:10044000FB567804037D7904297D1F7C79042E7C7A
+:10045000E35D700D1105ED55000F6007027D06523A
+:10046000D0992652337E6005027D10021202096A7D
+:100470002D7F1202096A2A7F1202096A277F011F53
+:1004800003200048EA7CE355FB9915001500150090
+:10049000047806520B6A26520B6AFA991500150069
+:1004A000047806520A6A26520A6AFA9915000478F4
+:1004B0000652096A2652096A097C286A077F0000E9
+:1004C000DB57004D057DFCC1DB57B99979C2540457
+:1004D0000CC2B699E5C1DB57F352056AFB568E0292
+:1004E000941AC36AC8626902267D941EC36ED36ED5
+:1004F000C862010A1102C86A9426981EC36EC862B7
+:100500009826C36E60020F7D981EC36EC8626C028F
+:10051000037D9826C36E479A100A1102D36EC86AEB
+:100520009826C36E579AC862339A096A187F0125C4
+:10053000004D1F7D1B9AE36E8F00D805017D8D0055
+:10054000C862096A0C7F01250120FA7CDB57004D47
+:10055000107D286A047F0000FCC1DB570C9A07005D
+:1005600004620C6A549A286AFA7F04627CC25804B6
+:100570005404FF081100FF18BC00CD00017C479A0D
+:10058000286AED7F04627CC20CC2099AD9C1E5C118
+:10059000DB57F352056AFB568E02941A0252690227
+:1005A0001D7D941E06524802065A9426981E065235
+:1005B0004C02065A9826981E065260020A7C98261B
+:1005C00006526E02237D096A1D7F0125004D247DA0
+:1005D000799A286A177F04627CC2AA9A8F00D8058C
+:1005E000017D8D00A00506526E02107D096A0A7F0A
+:1005F0000120F97C286A067F0000004D0D7DFCC1BA
+:10060000DB57699A070004620C6AA79A286AFA7F86
+:1006100004627CC258045404286AF47F0CC2669AAF
+:10062000F2DADB57F352056AC7698F00D500017D06
+:100630008D00A0057804037D79041C7D157C790468
+:100640001E7CEE56C862287E6006027D10021202F1
+:10065000096A227F1202096A1F7F1202096A1C7F3F
+:1006600003200048EF7CE19A150015000278C8626B
+:100670000B6AE09A15000278C8620A6AE09A02786A
+:10068000C862096A097C286A077F004D077DD3523A
+:10069000010802580004B29A79C25404D3520108E6
+:1006A000025801040ADBAF9A700B11031353DB5F8E
+:1006B0000A07D3588B00FB5E3CC1157DC05AC85B4E
+:1006C0004EC1117C8803F05DFF0D1105FF1DBC05B7
+:1006D000004D047D099B0807DB5F0A078B00C352AE
+:1006E000CB5359C1EC7D0002FA9A016E0B612F7E4B
+:1006F0000B622D7E0B632B7E0C0D17041704170461
+:100700009D04081DCC05017C0C0DD16A000F420729
+:10071000C86FDD6F1C7F8E009D0001680B67177E20
+:10072000D56B04080278C86F1207117C0B670F7E27
+:1007300004080278C86F12070A7CDD6F087FD16950
+:10074000010FC86FDD6F037F010100041F9B0700CD
+:10075000FF680C6800021F9B8FDBDB57F352056AB2
+:10076000FB52C76A8F00D500017D8D00A00578047B
+:10077000037D79041C7D157C79041E7CEE56C862CD
+:10078000287E6006027D10021202096A227F120290
+:10079000096A1F7F1202096A1C7F03200048EF7C50
+:1007A0007E9B150015000278C8620B6A7D9B1500C0
+:1007B0000278C8620A6A7D9B0278C862096A097C6D
+:1007C000286A077F004D077DD352010802580004B4
+:1007D0004E9B79C25404D352010802580104A7DB8E
+:1007E0004B9B700B11031353DB5F0A07D3588B002D
+:1007F000FB5E3CC1157DC05AC85B4EC1117C8803AD
+:10080000F05DFF0D1105FF1DBC05004D047DA69B8D
+:100810000807DB5F0A078B00C352CB5359C1EC7D3D
+:100820000002979BFCDBDB57F352016AFB52D36A51
+:100830008F00D500017D8D00A005EB5D7804037D60
+:1008400079041C7D207C7904157CEE566006057DBC
+:1008500009652A7E0A62287ECF9B0A62257E096589
+:10086000237E12051205AD02C86A1E7F03200048D0
+:10087000ED7CE79B02780962C86AE69B1500027866
+:100880000A62C86AE69B1500150002780B62C86A06
+:100890000B7CDF6D097F0000EB55004D097DD352C5
+:1008A000010802580004B69B0700CC680C6815C20A
+:1008B000D35201080258010414DCB19B700B1103E0
+:1008C0001353DB5F0A07D3588B00FB5E3CC1157DD9
+:1008D000C05AC85B4EC1117C8803F05DFF0D110545
+:1008E000FF1DBC05004D047D139C0807DB5F0A0754
+:0E08F0008B00C352CB5359C1EC7D0002049C17
+:00000001FF
diff --git a/include/dt-bindings/clock/imx6qdl-clock.h b/include/dt-bindings/clock/imx6qdl-clock.h
index da59fd9cdb5e..2a25fdb2d9b8 100644
--- a/include/dt-bindings/clock/imx6qdl-clock.h
+++ b/include/dt-bindings/clock/imx6qdl-clock.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * 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
@@ -271,6 +271,13 @@
#define IMX6QDL_CLK_PRE_AXI 258
#define IMX6QDL_CLK_MLB_SEL 259
#define IMX6QDL_CLK_MLB_PODF 260
-#define IMX6QDL_CLK_END 261
+#define IMX6QDL_CLK_AXI_ALT_SEL 261
+#define IMX6QDL_CLK_LDB_DI0_DIV_7 262
+#define IMX6QDL_CLK_LDB_DI1_DIV_7 263
+#define IMX6QDL_CLK_LDB_DI0_DIV_SEL 264
+#define IMX6QDL_CLK_LDB_DI1_DIV_SEL 265
+#define IMX6QDL_CLK_DCIC1 266
+#define IMX6QDL_CLK_DCIC2 267
+#define IMX6QDL_CLK_END 268
#endif /* __DT_BINDINGS_CLOCK_IMX6QDL_H */
diff --git a/include/dt-bindings/clock/imx6sl-clock.h b/include/dt-bindings/clock/imx6sl-clock.h
index e14573e293c5..6bc731e00a89 100644
--- a/include/dt-bindings/clock/imx6sl-clock.h
+++ b/include/dt-bindings/clock/imx6sl-clock.h
@@ -175,6 +175,7 @@
#define IMX6SL_CLK_SSI2_IPG 162
#define IMX6SL_CLK_SSI3_IPG 163
#define IMX6SL_CLK_SPDIF_GCLK 164
-#define IMX6SL_CLK_END 165
+#define IMX6SL_CLK_UART_OSC_4M 165
+#define IMX6SL_CLK_END 166
#endif /* __DT_BINDINGS_CLOCK_IMX6SL_H */
diff --git a/include/dt-bindings/clock/imx6sll-clock.h b/include/dt-bindings/clock/imx6sll-clock.h
new file mode 100644
index 000000000000..b68a89ee82cd
--- /dev/null
+++ b/include/dt-bindings/clock/imx6sll-clock.h
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX6SLL_H
+#define __DT_BINDINGS_CLOCK_IMX6SLL_H
+
+#define IMX6SLL_CLK_DUMMY 0
+#define IMX6SLL_CLK_CKIL 1
+#define IMX6SLL_CLK_OSC 2
+#define IMX6SLL_PLL1_BYPASS_SRC 3
+#define IMX6SLL_PLL2_BYPASS_SRC 4
+#define IMX6SLL_PLL3_BYPASS_SRC 5
+#define IMX6SLL_PLL4_BYPASS_SRC 6
+#define IMX6SLL_PLL5_BYPASS_SRC 7
+#define IMX6SLL_PLL6_BYPASS_SRC 8
+#define IMX6SLL_PLL7_BYPASS_SRC 9
+#define IMX6SLL_CLK_PLL1 10
+#define IMX6SLL_CLK_PLL2 11
+#define IMX6SLL_CLK_PLL3 12
+#define IMX6SLL_CLK_PLL4 13
+#define IMX6SLL_CLK_PLL5 14
+#define IMX6SLL_CLK_PLL6 15
+#define IMX6SLL_CLK_PLL7 16
+#define IMX6SLL_PLL1_BYPASS 17
+#define IMX6SLL_PLL2_BYPASS 18
+#define IMX6SLL_PLL3_BYPASS 19
+#define IMX6SLL_PLL4_BYPASS 20
+#define IMX6SLL_PLL5_BYPASS 21
+#define IMX6SLL_PLL6_BYPASS 22
+#define IMX6SLL_PLL7_BYPASS 23
+#define IMX6SLL_CLK_PLL1_SYS 24
+#define IMX6SLL_CLK_PLL2_BUS 25
+#define IMX6SLL_CLK_PLL3_USB_OTG 26
+#define IMX6SLL_CLK_PLL4_AUDIO 27
+#define IMX6SLL_CLK_PLL5_VIDEO 28
+#define IMX6SLL_CLK_PLL6_ENET 29
+#define IMX6SLL_CLK_PLL7_USB_HOST 30
+#define IMX6SLL_CLK_USBPHY1 31
+#define IMX6SLL_CLK_USBPHY2 32
+#define IMX6SLL_CLK_USBPHY1_GATE 33
+#define IMX6SLL_CLK_USBPHY2_GATE 34
+#define IMX6SLL_CLK_PLL2_PFD0 35
+#define IMX6SLL_CLK_PLL2_PFD1 36
+#define IMX6SLL_CLK_PLL2_PFD2 37
+#define IMX6SLL_CLK_PLL2_PFD3 38
+#define IMX6SLL_CLK_PLL3_PFD0 39
+#define IMX6SLL_CLK_PLL3_PFD1 40
+#define IMX6SLL_CLK_PLL3_PFD2 41
+#define IMX6SLL_CLK_PLL3_PFD3 42
+#define IMX6SLL_CLK_PLL4_POST_DIV 43
+#define IMX6SLL_CLK_PLL4_AUDIO_DIV 44
+#define IMX6SLL_CLK_PLL5_POST_DIV 45
+#define IMX6SLL_CLK_PLL5_VIDEO_DIV 46
+#define IMX6SLL_CLK_PLL2_198M 47
+#define IMX6SLL_CLK_PLL3_120M 48
+#define IMX6SLL_CLK_PLL3_80M 49
+#define IMX6SLL_CLK_PLL3_60M 50
+#define IMX6SLL_CLK_STEP 51
+#define IMX6SLL_CLK_PLL1_SW 52
+#define IMX6SLL_CLK_AXI_ALT_SEL 53
+#define IMX6SLL_CLK_AXI_SEL 54
+#define IMX6SLL_CLK_PERIPH_PRE 55
+#define IMX6SLL_CLK_PERIPH2_PRE 56
+#define IMX6SLL_CLK_PERIPH_CLK2_SEL 57
+#define IMX6SLL_CLK_PERIPH2_CLK2_SEL 58
+#define IMX6SLL_CLK_PERCLK_SEL 59
+#define IMX6SLL_CLK_USDHC1_SEL 60
+#define IMX6SLL_CLK_USDHC2_SEL 61
+#define IMX6SLL_CLK_USDHC3_SEL 62
+#define IMX6SLL_CLK_SSI1_SEL 63
+#define IMX6SLL_CLK_SSI2_SEL 64
+#define IMX6SLL_CLK_SSI3_SEL 65
+#define IMX6SLL_CLK_PXP_SEL 66
+#define IMX6SLL_CLK_LCDIF_PRE_SEL 67
+#define IMX6SLL_CLK_LCDIF_SEL 68
+#define IMX6SLL_CLK_EPDC_PRE_SEL 69
+#define IMX6SLL_CLK_SPDIF_SEL 70
+#define IMX6SLL_CLK_ECSPI_SEL 71
+#define IMX6SLL_CLK_UART_SEL 72
+#define IMX6SLL_CLK_ARM 73
+#define IMX6SLL_CLK_PERIPH 74
+#define IMX6SLL_CLK_PERIPH2 75
+#define IMX6SLL_CLK_PERIPH2_CLK2 76
+#define IMX6SLL_CLK_PERIPH_CLK2 77
+#define IMX6SLL_CLK_MMDC_PODF 78
+#define IMX6SLL_CLK_AXI_PODF 79
+#define IMX6SLL_CLK_AHB 80
+#define IMX6SLL_CLK_IPG 81
+#define IMX6SLL_CLK_PERCLK 82
+#define IMX6SLL_CLK_USDHC1_PODF 83
+#define IMX6SLL_CLK_USDHC2_PODF 84
+#define IMX6SLL_CLK_USDHC3_PODF 85
+#define IMX6SLL_CLK_SSI1_PRED 86
+#define IMX6SLL_CLK_SSI2_PRED 87
+#define IMX6SLL_CLK_SSI3_PRED 88
+#define IMX6SLL_CLK_SSI1_PODF 89
+#define IMX6SLL_CLK_SSI2_PODF 90
+#define IMX6SLL_CLK_SSI3_PODF 91
+#define IMX6SLL_CLK_PXP_PODF 92
+#define IMX6SLL_CLK_LCDIF_PRED 93
+#define IMX6SLL_CLK_LCDIF_PODF 94
+#define IMX6SLL_CLK_EPDC_SEL 95
+#define IMX6SLL_CLK_EPDC_PODF 96
+#define IMX6SLL_CLK_SPDIF_PRED 97
+#define IMX6SLL_CLK_SPDIF_PODF 98
+#define IMX6SLL_CLK_ECSPI_PODF 99
+#define IMX6SLL_CLK_UART_PODF 100
+
+/* CCGR 0 */
+#define IMX6SLL_CLK_AIPSTZ1 101
+#define IMX6SLL_CLK_AIPSTZ2 102
+#define IMX6SLL_CLK_DCP 103
+#define IMX6SLL_CLK_UART2_IPG 104
+#define IMX6SLL_CLK_UART2_SERIAL 105
+
+/* CCGR 1 */
+#define IMX6SLL_CLK_ECSPI1 106
+#define IMX6SLL_CLK_ECSPI2 107
+#define IMX6SLL_CLK_ECSPI3 108
+#define IMX6SLL_CLK_ECSPI4 109
+#define IMX6SLL_CLK_UART3_IPG 110
+#define IMX6SLL_CLK_UART3_SERIAL 111
+#define IMX6SLL_CLK_UART4_IPG 112
+#define IMX6SLL_CLK_UART4_SERIAL 113
+#define IMX6SLL_CLK_EPIT1 114
+#define IMX6SLL_CLK_EPIT2 115
+#define IMX6SLL_CLK_GPT_BUS 116
+#define IMX6SLL_CLK_GPT_SERIAL 117
+
+/* CCGR2 */
+#define IMX6SLL_CLK_CSI 118
+#define IMX6SLL_CLK_I2C1 119
+#define IMX6SLL_CLK_I2C2 120
+#define IMX6SLL_CLK_I2C3 121
+#define IMX6SLL_CLK_OCOTP 122
+#define IMX6SLL_CLK_LCDIF_APB 123
+#define IMX6SLL_CLK_PXP 124
+
+/* CCGR3 */
+#define IMX6SLL_CLK_UART5_IPG 125
+#define IMX6SLL_CLK_UART5_SERIAL 126
+#define IMX6SLL_CLK_EPDC_AXI 127
+#define IMX6SLL_CLK_EPDC_PIX 128
+#define IMX6SLL_CLK_LCDIF_PIX 129
+#define IMX6SLL_CLK_WDOG1 130
+#define IMX6SLL_CLK_MMDC_P0_FAST 131
+#define IMX6SLL_CLK_MMDC_P0_IPG 132
+#define IMX6SLL_CLK_OCRAM 133
+
+/* CCGR4 */
+#define IMX6SLL_CLK_PWM1 134
+#define IMX6SLL_CLK_PWM2 135
+#define IMX6SLL_CLK_PWM3 136
+#define IMX6SLL_CLK_PWM4 137
+
+/* CCGR 5 */
+#define IMX6SLL_CLK_ROM 138
+#define IMX6SLL_CLK_SDMA 139
+#define IMX6SLL_CLK_KPP 140
+#define IMX6SLL_CLK_WDOG2 141
+#define IMX6SLL_CLK_SPBA 142
+#define IMX6SLL_CLK_SPDIF 143
+#define IMX6SLL_CLK_SPDIF_GCLK 144
+#define IMX6SLL_CLK_SSI1 145
+#define IMX6SLL_CLK_SSI1_IPG 146
+#define IMX6SLL_CLK_SSI2 147
+#define IMX6SLL_CLK_SSI2_IPG 148
+#define IMX6SLL_CLK_SSI3 149
+#define IMX6SLL_CLK_SSI3_IPG 150
+#define IMX6SLL_CLK_UART1_IPG 151
+#define IMX6SLL_CLK_UART1_SERIAL 152
+
+/* CCGR 6 */
+#define IMX6SLL_CLK_USBOH3 153
+#define IMX6SLL_CLK_USDHC1 154
+#define IMX6SLL_CLK_USDHC2 155
+#define IMX6SLL_CLK_USDHC3 156
+
+#define IMX6SLL_CLK_IPP_DI0 157
+#define IMX6SLL_CLK_IPP_DI1 158
+#define IMX6SLL_CLK_LDB_DI0_SEL 159
+#define IMX6SLL_CLK_LDB_DI0_DIV_3_5 160
+#define IMX6SLL_CLK_LDB_DI0_DIV_7 161
+#define IMX6SLL_CLK_LDB_DI0_DIV_SEL 162
+#define IMX6SLL_CLK_LDB_DI0 163
+#define IMX6SLL_CLK_LDB_DI1_SEL 164
+#define IMX6SLL_CLK_LDB_DI1_DIV_3_5 165
+#define IMX6SLL_CLK_LDB_DI1_DIV_7 166
+#define IMX6SLL_CLK_LDB_DI1_DIV_SEL 167
+#define IMX6SLL_CLK_LDB_DI1 168
+#define IMX6SLL_CLK_EXTERN_AUDIO_SEL 169
+#define IMX6SLL_CLK_EXTERN_AUDIO_PRED 170
+#define IMX6SLL_CLK_EXTERN_AUDIO_PODF 171
+#define IMX6SLL_CLK_EXTERN_AUDIO 172
+#define IMX6SLL_CLK_GPT_3M 173
+
+#define IMX6SLL_CLK_END 174
+
+#endif /* __DT_BINDINGS_CLOCK_IMX6SLL_H */
diff --git a/include/dt-bindings/clock/imx6sx-clock.h b/include/dt-bindings/clock/imx6sx-clock.h
index 36f0324902a5..a248f928a30a 100644
--- a/include/dt-bindings/clock/imx6sx-clock.h
+++ b/include/dt-bindings/clock/imx6sx-clock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * 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
@@ -275,6 +275,10 @@
#define IMX6SX_PLL6_BYPASS 262
#define IMX6SX_PLL7_BYPASS 263
#define IMX6SX_CLK_SPDIF_GCLK 264
-#define IMX6SX_CLK_CLK_END 265
+#define IMX6SX_CLK_LVDS2_SEL 265
+#define IMX6SX_CLK_LVDS2_OUT 266
+#define IMX6SX_CLK_LVDS2_IN 267
+#define IMX6SX_CLK_ANACLK2 268
+#define IMX6SX_CLK_CLK_END 269
#endif /* __DT_BINDINGS_CLOCK_IMX6SX_H */
diff --git a/include/dt-bindings/clock/imx6ul-clock.h b/include/dt-bindings/clock/imx6ul-clock.h
index fd8aee8f64ae..45954981b659 100644
--- a/include/dt-bindings/clock/imx6ul-clock.h
+++ b/include/dt-bindings/clock/imx6ul-clock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * 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
@@ -235,7 +235,19 @@
#define IMX6UL_CLK_CSI_PODF 222
#define IMX6UL_CLK_PLL3_120M 223
#define IMX6UL_CLK_KPP 224
-
-#define IMX6UL_CLK_END 225
+/* For i.MX6ULL */
+#define IMX6UL_CLK_ESAI_SEL 225
+#define IMX6UL_CLK_ESAI_PRED 226
+#define IMX6UL_CLK_ESAI_PODF 227
+#define IMX6UL_CLK_ESAI_EXTAL 228
+#define IMX6UL_CLK_ESAI_MEM 229
+#define IMX6UL_CLK_ESAI_IPG 230
+#define IMX6UL_CLK_DCP_CLK 231
+#define IMX6UL_CLK_EPDC_PRE_SEL 232
+#define IMX6UL_CLK_EPDC_SEL 233
+#define IMX6UL_CLK_EPDC_PODF 234
+#define IMX6UL_CLK_EPDC_ACLK 235
+#define IMX6UL_CLK_EPDC_PIX 236
+#define IMX6UL_CLK_END 237
#endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
diff --git a/include/dt-bindings/clock/imx7d-clock.h b/include/dt-bindings/clock/imx7d-clock.h
index 1183347c383f..8691a8549ec0 100644
--- a/include/dt-bindings/clock/imx7d-clock.h
+++ b/include/dt-bindings/clock/imx7d-clock.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014-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
@@ -449,5 +450,12 @@
#define IMX7D_ADC_ROOT_CLK 436
#define IMX7D_CLK_ARM 437
#define IMX7D_CKIL 438
-#define IMX7D_CLK_END 439
+#define IMX7D_OCOTP_CLK 439
+#define IMX7D_CAAM_CLK 440
+#define IMX7D_PXP_IPG_CLK 441
+#define IMX7D_PXP_AXI_CLK 442
+#define IMX7D_ENET1_IPG_ROOT_CLK 443
+#define IMX7D_ENET2_IPG_ROOT_CLK 444
+#define IMX7D_CLK_END 445
+
#endif /* __DT_BINDINGS_CLOCK_IMX7D_H */
diff --git a/include/dt-bindings/clock/imx7ulp-clock.h b/include/dt-bindings/clock/imx7ulp-clock.h
new file mode 100644
index 000000000000..672a89f838a7
--- /dev/null
+++ b/include/dt-bindings/clock/imx7ulp-clock.h
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX7ULP_H
+#define __DT_BINDINGS_CLOCK_IMX7ULP_H
+
+#define IMX7ULP_CLK_DUMMY 0
+#define IMX7ULP_CLK_CKIL 1
+#define IMX7ULP_CLK_OSC 2
+#define IMX7ULP_CLK_FIRC 3
+
+/* SCG1 */
+#define IMX7ULP_CLK_SPLL_PRE_SEL 4
+#define IMX7ULP_CLK_SPLL_PRE_DIV 5
+#define IMX7ULP_CLK_SPLL 6
+#define IMX7ULP_CLK_SPLL_POST_DIV1 7
+#define IMX7ULP_CLK_SPLL_POST_DIV2 8
+#define IMX7ULP_CLK_SPLL_PFD0 9
+#define IMX7ULP_CLK_SPLL_PFD1 10
+#define IMX7ULP_CLK_SPLL_PFD2 11
+#define IMX7ULP_CLK_SPLL_PFD3 12
+#define IMX7ULP_CLK_SPLL_PFD_SEL 13
+#define IMX7ULP_CLK_SPLL_SEL 14
+#define IMX7ULP_CLK_APLL_PRE_SEL 15
+#define IMX7ULP_CLK_APLL_PRE_DIV 16
+#define IMX7ULP_CLK_APLL 17
+#define IMX7ULP_CLK_APLL_POST_DIV1 18
+#define IMX7ULP_CLK_APLL_POST_DIV2 19
+#define IMX7ULP_CLK_APLL_PFD0 20
+#define IMX7ULP_CLK_APLL_PFD1 21
+#define IMX7ULP_CLK_APLL_PFD2 22
+#define IMX7ULP_CLK_APLL_PFD3 23
+#define IMX7ULP_CLK_APLL_PFD_SEL 24
+#define IMX7ULP_CLK_APLL_SEL 25
+#define IMX7ULP_CLK_UPLL 26
+#define IMX7ULP_CLK_SYS_SEL 27
+#define IMX7ULP_CLK_CORE_DIV 28
+#define IMX7ULP_CLK_BUS_DIV 29
+#define IMX7ULP_CLK_PLAT_DIV 30
+#define IMX7ULP_CLK_DDR_SEL 31
+#define IMX7ULP_CLK_DDR_DIV 32
+#define IMX7ULP_CLK_NIC_SEL 33
+#define IMX7ULP_CLK_NIC0_DIV 34
+#define IMX7ULP_CLK_GPU_DIV 35
+#define IMX7ULP_CLK_NIC1_DIV 36
+#define IMX7ULP_CLK_NIC1_BUS_DIV 37
+#define IMX7ULP_CLK_NIC1_EXT_DIV 38
+
+/* PCG2 */
+#define IMX7ULP_CLK_DMA1 39
+#define IMX7ULP_CLK_RGPIO2P1 40
+#define IMX7ULP_CLK_FLEXBUS 41
+#define IMX7ULP_CLK_SEMA42_1 42
+#define IMX7ULP_CLK_DMA_MUX1 43
+#define IMX7ULP_CLK_SNVS 44
+#define IMX7ULP_CLK_CAAM 45
+#define IMX7ULP_CLK_LPTPM4 46
+#define IMX7ULP_CLK_LPTPM5 47
+#define IMX7ULP_CLK_LPIT1 48
+#define IMX7ULP_CLK_LPSPI2 49
+#define IMX7ULP_CLK_LPSPI3 50
+#define IMX7ULP_CLK_LPI2C4 51
+#define IMX7ULP_CLK_LPI2C5 52
+#define IMX7ULP_CLK_LPUART4 53
+#define IMX7ULP_CLK_LPUART5 54
+#define IMX7ULP_CLK_FLEXIO1 55
+#define IMX7ULP_CLK_USB0 56
+#define IMX7ULP_CLK_USB1 57
+#define IMX7ULP_CLK_USB_PHY 58
+#define IMX7ULP_CLK_USB_PL301 59
+#define IMX7ULP_CLK_USDHC0 60
+#define IMX7ULP_CLK_USDHC1 61
+#define IMX7ULP_CLK_WDG1 62
+#define IMX7ULP_CLK_WDG2 63
+
+/* PCG3 */
+#define IMX7ULP_CLK_LPTPM6 64
+#define IMX7ULP_CLK_LPTPM7 65
+#define IMX7ULP_CLK_LPI2C6 66
+#define IMX7ULP_CLK_LPI2C7 67
+#define IMX7ULP_CLK_LPUART6 68
+#define IMX7ULP_CLK_LPUART7 69
+#define IMX7ULP_CLK_VIU 70
+#define IMX7ULP_CLK_DSI 71
+#define IMX7ULP_CLK_LCDIF 72
+#define IMX7ULP_CLK_MMDC 73
+#define IMX7ULP_CLK_PCTLC 74
+#define IMX7ULP_CLK_PCTLD 75
+#define IMX7ULP_CLK_PCTLE 76
+#define IMX7ULP_CLK_PCTLF 77
+#define IMX7ULP_CLK_GPU3D 78
+#define IMX7ULP_CLK_GPU2D 79
+
+#define IMX7ULP_CLK_MIPI_PLL 80
+#define IMX7ULP_CLK_SIRC 81
+
+#define IMX7ULP_CLK_SCG1_CLKOUT 82
+#define IMX7ULP_CLK_HSRUN_SYS_SEL 83
+#define IMX7ULP_CLK_HSRUN_CORE 84
+#define IMX7ULP_CLK_ARM 85
+
+#define IMX7ULP_CLK_END 86
+
+/*cm4 clocks*/
+#define IMX7ULP_CM4_CLK_DUMMY 0
+#define IMX7ULP_CM4_CLK_CKIL 1
+#define IMX7ULP_CM4_CLK_OSC 2
+#define IMX7ULP_CM4_CLK_FIRC 3
+#define IMX7ULP_CM4_CLK_SIRC 4
+
+/* SCG0 */
+#define IMX7ULP_CM4_CLK_SPLL_VCO_PRE_SEL 5
+#define IMX7ULP_CM4_CLK_SPLL_VCO_PRE_DIV 6
+#define IMX7ULP_CM4_CLK_SPLL 7
+#define IMX7ULP_CM4_CLK_SPLL_VCO 8
+#define IMX7ULP_CM4_CLK_SPLL_VCO_POST_DIV1 9
+#define IMX7ULP_CM4_CLK_SPLL_VCO_POST_DIV2 10
+#define IMX7ULP_CM4_CLK_SPLL_PFD0 11
+#define IMX7ULP_CM4_CLK_SPLL_PFD1 12
+#define IMX7ULP_CM4_CLK_SPLL_PFD2 13
+#define IMX7ULP_CM4_CLK_SPLL_PFD3 14
+#define IMX7ULP_CM4_CLK_SPLL_PFD_SEL 15
+#define IMX7ULP_CM4_CLK_SPLL_PFD 16
+#define IMX7ULP_CM4_CLK_SPLL_SEL 17
+#define IMX7ULP_CM4_CLK_APLL_VCO_PRE_SEL 18
+#define IMX7ULP_CM4_CLK_APLL_VCO_PRE_DIV 19
+#define IMX7ULP_CM4_CLK_APLL 20
+#define IMX7ULP_CM4_CLK_APLL_VCO 21
+#define IMX7ULP_CM4_CLK_APLL_VCO_POST_DIV1 22
+#define IMX7ULP_CM4_CLK_APLL_VCO_POST_DIV2 23
+#define IMX7ULP_CM4_CLK_APLL_PFD0 24
+#define IMX7ULP_CM4_CLK_APLL_PFD1 25
+#define IMX7ULP_CM4_CLK_APLL_PFD2 26
+#define IMX7ULP_CM4_CLK_APLL_PFD3 27
+#define IMX7ULP_CM4_CLK_APLL_PFD_SEL 28
+#define IMX7ULP_CM4_CLK_APLL_PFD 29
+#define IMX7ULP_CM4_CLK_APLL_SEL 30
+#define IMX7ULP_CM4_CLK_APLL_PFD0_PRE_DIV 31
+#define IMX7ULP_CM4_CLK_SYS_SEL 32
+#define IMX7ULP_CM4_CLK_CORE_DIV 33
+#define IMX7ULP_CM4_CLK_BUS_DIV 34
+#define IMX7ULP_CM4_CLK_PLAT_DIV 35
+#define IMX7ULP_CM4_CLK_SLOW_DIV 36
+
+#define IMX7ULP_CM4_CLK_SAI0_SEL 37
+#define IMX7ULP_CM4_CLK_SAI0_DIV 38
+#define IMX7ULP_CM4_CLK_SAI0_ROOT 39
+#define IMX7ULP_CM4_CLK_SAI0_IPG 40
+#define IMX7ULP_CM4_CLK_SAI1_SEL 41
+#define IMX7ULP_CM4_CLK_SAI1_DIV 42
+#define IMX7ULP_CM4_CLK_SAI1_ROOT 43
+#define IMX7ULP_CM4_CLK_SAI1_IPG 44
+
+#define IMX7ULP_CLK_SCG0_CLKOUT 45
+
+#define IMX7ULP_CM4_CLK_END 46
+
+#endif /* __DT_BINDINGS_CLOCK_IMX7ULP_H */
diff --git a/include/dt-bindings/input/input.h b/include/dt-bindings/input/input.h
index a21413324a3f..14f91301f96f 100644
--- a/include/dt-bindings/input/input.h
+++ b/include/dt-bindings/input/input.h
@@ -14,4 +14,7 @@
#define MATRIX_KEY(row, col, code) \
((((row) & 0xFF) << 24) | (((col) & 0xFF) << 16) | ((code) & 0xFFFF))
+#define FT5416 0x54160002
+#define FT5426 0x54260002
+
#endif /* _DT_BINDINGS_INPUT_INPUT_H */
diff --git a/include/linux/busfreq-imx.h b/include/linux/busfreq-imx.h
new file mode 100644
index 000000000000..6c98244bfd67
--- /dev/null
+++ b/include/linux/busfreq-imx.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MXC_BUSFREQ_H__
+#define __ASM_ARCH_MXC_BUSFREQ_H__
+
+#include <linux/notifier.h>
+#include <linux/regulator/consumer.h>
+
+/*
+ * This enumerates busfreq low power mode entry and exit.
+ */
+enum busfreq_event {
+ LOW_BUSFREQ_ENTER,
+ LOW_BUSFREQ_EXIT,
+};
+
+/*
+ * This enumerates the system bus and ddr frequencies in various modes.
+ * BUS_FREQ_HIGH - DDR @ 528MHz, AHB @ 132MHz.
+ * BUS_FREQ_MED - DDR @ 400MHz, AHB @ 132MHz
+ * BUS_FREQ_AUDIO - DDR @ 50MHz/100MHz, AHB @ 24MHz.
+ * BUS_FREQ_LOW - DDR @ 24MHz, AHB @ 24MHz.
+ * BUS_FREQ_ULTRA_LOW - DDR @ 1MHz, AHB - 3MHz.
+ *
+ * Drivers need to request/release the bus/ddr frequencies based on
+ * their performance requirements. Drivers cannot request/release
+ * BUS_FREQ_ULTRA_LOW mode as this mode is automatically entered from
+ * either BUS_FREQ_AUDIO or BUS_FREQ_LOW
+ * modes.
+ */
+enum bus_freq_mode {
+ BUS_FREQ_HIGH,
+ BUS_FREQ_MED,
+ BUS_FREQ_AUDIO,
+ BUS_FREQ_LOW,
+ BUS_FREQ_ULTRA_LOW,
+};
+
+#if defined(CONFIG_CPU_FREQ) && !defined(CONFIG_ARM64)
+extern struct regulator *arm_reg;
+extern struct regulator *soc_reg;
+void request_bus_freq(enum bus_freq_mode mode);
+void release_bus_freq(enum bus_freq_mode mode);
+int register_busfreq_notifier(struct notifier_block *nb);
+int unregister_busfreq_notifier(struct notifier_block *nb);
+int get_bus_freq_mode(void);
+#else
+static inline void request_bus_freq(enum bus_freq_mode mode)
+{
+}
+static inline void release_bus_freq(enum bus_freq_mode mode)
+{
+}
+static inline int register_busfreq_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+static inline int unregister_busfreq_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+static inline int get_bus_freq_mode(void)
+{
+ return BUS_FREQ_HIGH;
+}
+#endif
+#endif
diff --git a/include/linux/can/platform/flexcan.h b/include/linux/can/platform/flexcan.h
new file mode 100644
index 000000000000..fdfe76f16ea7
--- /dev/null
+++ b/include/linux/can/platform/flexcan.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#ifndef __CAN_PLATFORM_FLEXCAN_H
+#define __CAN_PLATFORM_FLEXCAN_H
+
+/**
+ * struct flexcan_platform_data - flex CAN controller platform data
+ * @transceiver_enable: - called to power on/off the transceiver
+ *
+ */
+struct flexcan_platform_data {
+ void (*transceiver_switch)(int enable);
+};
+
+#endif /* __CAN_PLATFORM_FLEXCAN_H */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 2f475ad89a0d..b86c3fbb6668 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -253,4 +253,11 @@ void cpuhp_report_idle_dead(void);
static inline void cpuhp_report_idle_dead(void) { }
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+#define IDLE_START 1
+#define IDLE_END 2
+
+void idle_notifier_register(struct notifier_block *n);
+void idle_notifier_unregister(struct notifier_block *n);
+void idle_notifier_call_chain(unsigned long val);
+
#endif /* _LINUX_CPU_H_ */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 32dc0cbd51ca..7643354f0b86 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -539,6 +539,18 @@ struct gov_attr_set {
int usage_count;
};
+#define gov_attr_ro(_name) \
+static struct governor_attr _name = \
+__ATTR(_name, 0444, show_##_name, NULL)
+
+#define gov_attr_wo(_name) \
+static struct governor_attr _name = \
+__ATTR(_name, 0200, NULL, store_##_name)
+
+#define gov_attr_rw(_name) \
+static struct governor_attr _name = \
+__ATTR(_name, 0644, show_##_name, store_##_name)
+
/* sysfs ops for cpufreq governors */
extern const struct sysfs_ops governor_sysfs_ops;
diff --git a/include/linux/device_cooling.h b/include/linux/device_cooling.h
new file mode 100644
index 000000000000..18d9e3b90ed9
--- /dev/null
+++ b/include/linux/device_cooling.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2013-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.
+ *
+ */
+
+#ifndef __DEVICE_THERMAL_H__
+#define __DEVICE_THERMAL_H__
+
+#include <linux/thermal.h>
+
+#ifdef CONFIG_DEVICE_THERMAL
+int register_devfreq_cooling_notifier(struct notifier_block *nb);
+int unregister_devfreq_cooling_notifier(struct notifier_block *nb);
+struct thermal_cooling_device *devfreq_cooling_register(void);
+void devfreq_cooling_unregister(struct thermal_cooling_device *cdev);
+#else
+static inline
+int register_devfreq_cooling_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline
+int unregister_devfreq_cooling_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline
+struct thermal_cooling_device *devfreq_cooling_register(void)
+{
+ return NULL;
+}
+
+static inline
+void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
+{
+ return;
+}
+#endif
+#endif /* __DEVICE_THERMAL_H__ */
diff --git a/include/linux/imx_gpc.h b/include/linux/imx_gpc.h
new file mode 100644
index 000000000000..2cffa4be22aa
--- /dev/null
+++ b/include/linux/imx_gpc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+/*
+ * @file linux/imx_gpc.h
+ *
+ * @brief Global header file for imx GPC
+ *
+ * @ingroup GPC
+ */
+#ifndef __LINUX_IMX_GPC_H__
+#define __LINUX_IMX_GPC_H__
+
+int imx_gpc_mf_request_on(unsigned int irq, unsigned int on);
+#endif /* __LINUX_IMX_GPC_H__ */
diff --git a/include/linux/imx_mu.h b/include/linux/imx_mu.h
new file mode 100644
index 000000000000..a26d2c6f9b17
--- /dev/null
+++ b/include/linux/imx_mu.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#define MU_ATR0_OFFSET1 0x0
+#define MU_ARR0_OFFSET1 0x10
+#define MU_ASR_OFFSET1 0x20
+#define MU_ACR_OFFSET1 0x24
+
+/* Registers offsets of the MU Version 1.0 */
+#define MU_V10_VER_OFFSET1 0x0
+#define MU_V10_ATR0_OFFSET1 0x20
+#define MU_V10_ARR0_OFFSET1 0x40
+#define MU_V10_ASR_OFFSET1 0x60
+#define MU_V10_ACR_OFFSET1 0x64
+#define MU_VER_ID_V10 0x0100 /* Version 1.0 */
+
+#define MU_TR_COUNT1 4
+#define MU_RR_COUNT1 4
+
+#define MU_CR_GIEn_MASK1 (0xF << 28)
+#define MU_CR_RIEn_MASK1 (0xF << 24)
+#define MU_CR_TIEn_MASK1 (0xF << 20)
+#define MU_CR_GIRn_MASK1 (0xF << 16)
+#define MU_CR_NMI_MASK1 (1 << 3)
+#define MU_CR_Fn_MASK1 0x7
+
+#define MU_SR_TE0_MASK1 (1 << 23)
+#define MU_SR_RF0_MASK1 (1 << 27)
+#define MU_CR_RIE0_MASK1 (1 << 27)
+#define MU_CR_GIE0_MASK1 (1 << 31)
+
+#define MU_TR_COUNT 4
+#define MU_RR_COUNT 4
+
+
+void MU_Init(void __iomem *base);
+void MU_SendMessage(void __iomem *base, uint32_t regIndex, uint32_t msg);
+void MU_ReceiveMsg(void __iomem *base, uint32_t regIndex, uint32_t *msg);
+void MU_EnableGeneralInt(void __iomem *base, uint32_t index);
+void MU_EnableRxFullInt(void __iomem *base, uint32_t index);
+uint32_t MU_ReadStatus(void __iomem *base);
+int32_t MU_SetFn(void __iomem *base, uint32_t Fn);
+
diff --git a/include/linux/imx_rpmsg.h b/include/linux/imx_rpmsg.h
new file mode 100644
index 000000000000..0cf531ceb57d
--- /dev/null
+++ b/include/linux/imx_rpmsg.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright (C) 2017 NXP.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+/*
+ * @file linux/imx_rpmsg.h
+ *
+ * @brief Global header file for imx RPMSG
+ *
+ * @ingroup RPMSG
+ */
+#ifndef __LINUX_IMX_RPMSG_H__
+#define __LINUX_IMX_RPMSG_H__
+
+/* Category define */
+#define IMX_RMPSG_LIFECYCLE 1
+#define IMX_RPMSG_PMIC 2
+#define IMX_RPMSG_AUDIO 3
+#define IMX_RPMSG_KEY 4
+#define IMX_RPMSG_GPIO 5
+/* rpmsg version */
+#define IMX_RMPSG_MAJOR 1
+#define IMX_RMPSG_MINOR 0
+
+struct imx_rpmsg_head {
+ u8 cate;
+ u8 major;
+ u8 minor;
+ u8 type;
+ u8 cmd;
+ u8 reserved[5];
+} __attribute__ ((packed));
+
+int imx_mu_rpmsg_register_nb(const char *name, struct notifier_block *nb);
+int imx_mu_rpmsg_unregister_nb(const char *name, struct notifier_block *nb);
+#endif /* __LINUX_IMX_RPMSG_H__ */
diff --git a/include/linux/imx_sema4.h b/include/linux/imx_sema4.h
new file mode 100644
index 000000000000..19850ae7742b
--- /dev/null
+++ b/include/linux/imx_sema4.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef __LINUX_IMX_SEMA4_H__
+#define __LINUX_IMX_SEMA4_H__
+
+#define SEMA4_NUM_DEVICES 1
+#define SEMA4_NUM_GATES 16
+
+#define SEMA4_UNLOCK 0x00
+#define SEMA4_A9_LOCK 0x01
+#define SEMA4_GATE_MASK 0x03
+
+#define CORE_MUTEX_VALID (('c'<<24)|('m'<<24)|('t'<<24)|'x')
+
+/*
+ * The enumerates
+ */
+enum {
+ /* sema4 registers offset */
+ SEMA4_CP0INE = 0x40,
+ SEMA4_CP1INE = 0x48,
+ SEMA4_CP0NTF = 0x80,
+ SEMA4_CP1NTF = 0x88,
+};
+
+static const unsigned int idx_sema4[SEMA4_NUM_GATES] = {
+ 1 << 7, 1 << 6, 1 << 5, 1 << 4,
+ 1 << 3, 1 << 2, 1 << 1, 1 << 0,
+ 1 << 15, 1 << 14, 1 << 13, 1 << 12,
+ 1 << 11, 1 << 10, 1 << 9, 1 << 8,
+};
+
+struct imx_sema4_mutex {
+ u32 valid;
+ u32 gate_num;
+ unsigned char gate_val;
+ wait_queue_head_t wait_q;
+};
+
+struct imx_sema4_mutex_device {
+ struct device *dev;
+ u16 cpntf_val;
+ u16 cpine_val;
+ void __iomem *ioaddr; /* Mapped address */
+ spinlock_t lock; /* Mutex */
+ int irq;
+
+ u16 alloced;
+ struct imx_sema4_mutex *mutex_ptr[SEMA4_NUM_GATES];
+};
+
+struct imx_sema4_mutex *
+ imx_sema4_mutex_create(u32 dev_num, u32 mutex_num);
+#ifdef CONFIG_IMX_SEMA4
+int imx_sema4_mutex_destroy(struct imx_sema4_mutex *mutex_ptr);
+int imx_sema4_mutex_trylock(struct imx_sema4_mutex *mutex_ptr);
+int imx_sema4_mutex_lock(struct imx_sema4_mutex *mutex_ptr);
+int imx_sema4_mutex_unlock(struct imx_sema4_mutex *mutex_ptr);
+#else
+static inline int imx_sema4_mutex_destroy(struct imx_sema4_mutex *mutex_ptr)
+{
+ return 0;
+}
+static inline int imx_sema4_mutex_trylock(struct imx_sema4_mutex *mutex_ptr)
+{
+ return 0;
+}
+static inline int imx_sema4_mutex_lock(struct imx_sema4_mutex *mutex_ptr)
+{
+ return 0;
+}
+static inline int imx_sema4_mutex_unlock(struct imx_sema4_mutex *mutex_ptr)
+{
+ return 0;
+}
+#endif
+#endif /* __LINUX_IMX_SEMA4_H__ */
diff --git a/include/linux/ipu-v3-pre.h b/include/linux/ipu-v3-pre.h
new file mode 100644
index 000000000000..f5a26e5eadbf
--- /dev/null
+++ b/include/linux/ipu-v3-pre.h
@@ -0,0 +1,155 @@
+/*
+ * 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
+ */
+#ifndef __LINUX_IPU_V3_PRE_H_
+#define __LINUX_IPU_V3_PRE_H_
+
+#define IPU_PRE_MAX_WIDTH 1920
+#define IPU_PRE_MAX_BPP 4
+#define IPU_PRE_SMALL_LINE 9 /* to workaround errata ERR009624*/
+
+struct ipu_rect {
+ int left;
+ int top;
+ int width;
+ int height;
+};
+
+struct ipu_pre_context {
+ bool repeat;
+ bool vflip;
+ bool handshake_en;
+ bool hsk_abort_en;
+ unsigned int hsk_line_num;
+ bool sdw_update;
+ unsigned int block_size;
+ unsigned int interlaced;
+ unsigned int prefetch_mode;
+
+ unsigned long cur_buf;
+ unsigned long next_buf;
+
+ unsigned int tile_fmt;
+
+ unsigned int read_burst;
+ unsigned int prefetch_input_bpp;
+ unsigned int prefetch_input_pixel_fmt;
+ unsigned int prefetch_shift_offset;
+ unsigned int prefetch_shift_width;
+ bool shift_bypass;
+ bool field_inverse;
+ bool tpr_coor_offset_en;
+ /* the output of prefetch is
+ * also the input of store
+ */
+ struct ipu_rect prefetch_output_size;
+ unsigned int prefetch_input_active_width;
+ unsigned int prefetch_input_width;
+ unsigned int prefetch_input_height;
+ unsigned int store_pitch;
+ int interlace_offset;
+
+ bool store_en;
+ unsigned int write_burst;
+ unsigned int store_output_bpp;
+
+ unsigned int sec_buf_off;
+ unsigned int trd_buf_off;
+
+ /* return for IPU fb caller */
+ unsigned long store_addr;
+};
+
+/*
+ * In order to workaround the PRE SoC bug recorded by errata ERR009624,
+ * the software cannot write the PRE_CTRL register when the PRE writes
+ * the PRE_CTRL register automatically to set the ENABLE bit(bit0) to 1
+ * in the PRE repeat mode.
+ * The software mechanism to set the PRE_CTRL register is different for
+ * PRE Y resolution higher than 9 lines and lower or equal to 9 lines.
+ * Use this helper to check the Y resolution.
+ */
+static inline bool ipu_pre_yres_is_small(unsigned int yres)
+{
+ return yres <= IPU_PRE_SMALL_LINE;
+}
+
+#ifdef CONFIG_MXC_IPU_V3_PRE
+int ipu_pre_alloc(int ipu_id, ipu_channel_t ipu_ch);
+void ipu_pre_free(unsigned int *id);
+unsigned long ipu_pre_alloc_double_buffer(unsigned int id, unsigned int size);
+void ipu_pre_free_double_buffer(unsigned int id);
+int ipu_pre_config(int id, struct ipu_pre_context *config);
+int ipu_pre_set_ctrl(unsigned int id, struct ipu_pre_context *config);
+int ipu_pre_enable(int id);
+void ipu_pre_disable(int id);
+int ipu_pre_set_fb_buffer(int id, bool resolve,
+ unsigned long fb_paddr,
+ unsigned int y_res,
+ unsigned int x_crop,
+ unsigned int y_crop,
+ unsigned int sec_buf_off,
+ unsigned int trd_buf_off);
+int ipu_pre_sdw_update(int id);
+#else
+int ipu_pre_alloc(int ipu_id, ipu_channel_t channel)
+{
+ return -ENODEV;
+}
+
+void ipu_pre_free(unsigned int *id)
+{
+}
+
+unsigned long ipu_pre_alloc_double_buffer(unsigned int id, unsigned int size)
+{
+ return -ENODEV;
+}
+
+void ipu_pre_free_double_buffer(unsigned int id)
+{
+}
+
+int ipu_pre_config(int id, struct ipu_pre_context *config)
+{
+ return -ENODEV;
+}
+
+int ipu_pre_set_ctrl(unsigned int id, struct ipu_pre_context *config)
+{
+ return -ENODEV;
+}
+
+int ipu_pre_enable(int id)
+{
+ return -ENODEV;
+}
+
+void ipu_pre_disable(int id)
+{
+ return;
+}
+
+int ipu_pre_set_fb_buffer(int id, bool resolve,
+ unsigned long fb_paddr,
+ unsigned int y_res,
+ unsigned int x_crop,
+ unsigned int y_crop,
+ unsigned int sec_buf_off,
+ unsigned int trd_buf_off)
+{
+ return -ENODEV;
+}
+int ipu_pre_sdw_update(int id)
+{
+ return -ENODEV;
+}
+#endif
+#endif /* __LINUX_IPU_V3_PRE_H_ */
diff --git a/include/linux/ipu-v3-prg.h b/include/linux/ipu-v3-prg.h
new file mode 100644
index 000000000000..2ab803a6699f
--- /dev/null
+++ b/include/linux/ipu-v3-prg.h
@@ -0,0 +1,61 @@
+/*
+ * 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
+ */
+#ifndef __LINUX_IPU_V3_PRG_H_
+#define __LINUX_IPU_V3_PRG_H_
+
+#include <linux/ipu-v3.h>
+
+#define PRG_SO_INTERLACE 1
+#define PRG_SO_PROGRESSIVE 0
+#define PRG_BLOCK_MODE 1
+#define PRG_SCAN_MODE 0
+
+struct ipu_prg_config {
+ unsigned int id;
+ unsigned int pre_num;
+ ipu_channel_t ipu_ch;
+ unsigned int stride;
+ unsigned int height;
+ unsigned int ipu_height;
+ unsigned int crop_line;
+ unsigned int so;
+ unsigned int ilo;
+ unsigned int block_mode;
+ bool vflip;
+ u32 baddr;
+ u32 offset;
+};
+
+#ifdef CONFIG_MXC_IPU_V3_PRG
+int ipu_prg_config(struct ipu_prg_config *config);
+int ipu_prg_disable(unsigned int ipu_id, unsigned int pre_num);
+int ipu_prg_wait_buf_ready(unsigned int ipu_id, unsigned int pre_num,
+ unsigned int hsk_line_num,
+ int pre_store_out_height);
+#else
+int ipu_prg_config(struct ipu_prg_config *config)
+{
+ return -ENODEV;
+}
+
+int ipu_prg_disable(unsigned int ipu_id, unsigned int pre_num)
+{
+ return -ENODEV;
+}
+
+int ipu_prg_wait_buf_ready(unsigned int ipu_id, unsigned int pre_num,
+ unsigned int hsk_line_num,
+ int pre_store_out_height)
+{
+ return -ENODEV;
+}
+#endif
+#endif /* __LINUX_IPU_V3_PRG_H_ */
diff --git a/include/linux/ipu-v3.h b/include/linux/ipu-v3.h
new file mode 100644
index 000000000000..ae09614a2257
--- /dev/null
+++ b/include/linux/ipu-v3.h
@@ -0,0 +1,770 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright (C) 2011-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 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.
+ */
+
+#ifndef __LINUX_IPU_V3_H_
+#define __LINUX_IPU_V3_H_
+
+#include <linux/ipu.h>
+
+/* IPU Driver channels definitions. */
+/* Note these are different from IDMA channels */
+#define IPU_MAX_CH 32
+#define _MAKE_CHAN(num, v_in, g_in, a_in, out) \
+ ((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out)
+#define _MAKE_ALT_CHAN(ch) (ch | (IPU_MAX_CH << 24))
+#define IPU_CHAN_ID(ch) (ch >> 24)
+#define IPU_CHAN_ALT(ch) (ch & 0x02000000)
+#define IPU_CHAN_ALPHA_IN_DMA(ch) ((uint32_t) (ch >> 6) & 0x3F)
+#define IPU_CHAN_GRAPH_IN_DMA(ch) ((uint32_t) (ch >> 12) & 0x3F)
+#define IPU_CHAN_VIDEO_IN_DMA(ch) ((uint32_t) (ch >> 18) & 0x3F)
+#define IPU_CHAN_OUT_DMA(ch) ((uint32_t) (ch & 0x3F))
+#define NO_DMA 0x3F
+#define ALT 1
+/*!
+ * Enumeration of IPU logical channels. An IPU logical channel is defined as a
+ * combination of an input (memory to IPU), output (IPU to memory), and/or
+ * secondary input IDMA channels and in some cases an Image Converter task.
+ * Some channels consist of only an input or output.
+ */
+typedef enum {
+ CHAN_NONE = -1,
+ MEM_ROT_ENC_MEM = _MAKE_CHAN(1, 45, NO_DMA, NO_DMA, 48),
+ MEM_ROT_VF_MEM = _MAKE_CHAN(2, 46, NO_DMA, NO_DMA, 49),
+ MEM_ROT_PP_MEM = _MAKE_CHAN(3, 47, NO_DMA, NO_DMA, 50),
+
+ MEM_PRP_ENC_MEM = _MAKE_CHAN(4, 12, 14, 17, 20),
+ MEM_PRP_VF_MEM = _MAKE_CHAN(5, 12, 14, 17, 21),
+ MEM_PP_MEM = _MAKE_CHAN(6, 11, 15, 18, 22),
+
+ MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA),
+ MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA),
+ MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA),
+ MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA),
+
+ MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA),
+ MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA),
+ MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0),
+ MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0),
+
+ DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
+ DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
+
+ CSI_MEM0 = _MAKE_CHAN(15, NO_DMA, NO_DMA, NO_DMA, 0),
+ CSI_MEM1 = _MAKE_CHAN(16, NO_DMA, NO_DMA, NO_DMA, 1),
+ CSI_MEM2 = _MAKE_CHAN(17, NO_DMA, NO_DMA, NO_DMA, 2),
+ CSI_MEM3 = _MAKE_CHAN(18, NO_DMA, NO_DMA, NO_DMA, 3),
+
+ CSI_MEM = CSI_MEM0,
+
+ CSI_PRP_ENC_MEM = _MAKE_CHAN(19, NO_DMA, NO_DMA, NO_DMA, 20),
+ CSI_PRP_VF_MEM = _MAKE_CHAN(20, NO_DMA, NO_DMA, NO_DMA, 21),
+
+ /* for vdi mem->vdi->ic->mem , add graphics plane and alpha*/
+ MEM_VDI_PRP_VF_MEM_P = _MAKE_CHAN(21, 8, 14, 17, 21),
+ MEM_VDI_PRP_VF_MEM = _MAKE_CHAN(22, 9, 14, 17, 21),
+ MEM_VDI_PRP_VF_MEM_N = _MAKE_CHAN(23, 10, 14, 17, 21),
+
+ /* for vdi mem->vdi->mem */
+ MEM_VDI_MEM_P = _MAKE_CHAN(24, 8, NO_DMA, NO_DMA, 5),
+ MEM_VDI_MEM = _MAKE_CHAN(25, 9, NO_DMA, NO_DMA, 5),
+ MEM_VDI_MEM_N = _MAKE_CHAN(26, 10, NO_DMA, NO_DMA, 5),
+
+ /* fake channel for vdoa to link with IPU */
+ MEM_VDOA_MEM = _MAKE_CHAN(27, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
+
+ MEM_PP_ADC = CHAN_NONE,
+ ADC_SYS2 = CHAN_NONE,
+
+} ipu_channel_t;
+
+/*!
+ * Enumeration of types of buffers for a logical channel.
+ */
+typedef enum {
+ IPU_OUTPUT_BUFFER = 0, /*!< Buffer for output from IPU */
+ IPU_ALPHA_IN_BUFFER = 1, /*!< Buffer for input to IPU */
+ IPU_GRAPH_IN_BUFFER = 2, /*!< Buffer for input to IPU */
+ IPU_VIDEO_IN_BUFFER = 3, /*!< Buffer for input to IPU */
+ IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER,
+ IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER,
+} ipu_buffer_t;
+
+#define IPU_PANEL_SERIAL 1
+#define IPU_PANEL_PARALLEL 2
+
+/*!
+ * Enumeration of ADC channel operation mode.
+ */
+typedef enum {
+ Disable,
+ WriteTemplateNonSeq,
+ ReadTemplateNonSeq,
+ WriteTemplateUnCon,
+ ReadTemplateUnCon,
+ WriteDataWithRS,
+ WriteDataWoRS,
+ WriteCmd
+} mcu_mode_t;
+
+/*!
+ * Enumeration of ADC channel addressing mode.
+ */
+typedef enum {
+ FullWoBE,
+ FullWithBE,
+ XY
+} display_addressing_t;
+
+/*!
+ * Union of initialization parameters for a logical channel.
+ */
+typedef union {
+ struct {
+ uint32_t csi;
+ uint32_t mipi_id;
+ uint32_t mipi_vc;
+ bool mipi_en;
+ bool interlaced;
+ } csi_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t outh_resize_ratio;
+ uint32_t outv_resize_ratio;
+ uint32_t csi;
+ uint32_t mipi_id;
+ uint32_t mipi_vc;
+ bool mipi_en;
+ } csi_prp_enc_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t outh_resize_ratio;
+ uint32_t outv_resize_ratio;
+ } mem_prp_enc_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ } mem_rot_enc_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t outh_resize_ratio;
+ uint32_t outv_resize_ratio;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ uint32_t in_g_pixel_fmt;
+ uint8_t alpha;
+ uint32_t key_color;
+ bool alpha_chan_en;
+ ipu_motion_sel motion_sel;
+ enum v4l2_field field_fmt;
+ uint32_t csi;
+ uint32_t mipi_id;
+ uint32_t mipi_vc;
+ bool mipi_en;
+ } csi_prp_vf_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ display_port_t disp;
+ uint32_t out_left;
+ uint32_t out_top;
+ } csi_prp_vf_adc;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t outh_resize_ratio;
+ uint32_t outv_resize_ratio;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ uint32_t in_g_pixel_fmt;
+ uint8_t alpha;
+ uint32_t key_color;
+ bool alpha_chan_en;
+ ipu_motion_sel motion_sel;
+ enum v4l2_field field_fmt;
+ } mem_prp_vf_mem;
+ struct {
+ uint32_t temp;
+ } mem_prp_vf_adc;
+ struct {
+ uint32_t temp;
+ } mem_rot_vf_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t outh_resize_ratio;
+ uint32_t outv_resize_ratio;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ uint32_t in_g_pixel_fmt;
+ uint8_t alpha;
+ uint32_t key_color;
+ bool alpha_chan_en;
+ } mem_pp_mem;
+ struct {
+ uint32_t temp;
+ } mem_rot_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ display_port_t disp;
+ uint32_t out_left;
+ uint32_t out_top;
+ } mem_pp_adc;
+ struct {
+ uint32_t di;
+ bool interlaced;
+ uint32_t in_pixel_fmt;
+ uint32_t out_pixel_fmt;
+ } mem_dc_sync;
+ struct {
+ uint32_t temp;
+ } mem_sdc_fg;
+ struct {
+ uint32_t di;
+ bool interlaced;
+ uint32_t in_pixel_fmt;
+ uint32_t out_pixel_fmt;
+ bool alpha_chan_en;
+ } mem_dp_bg_sync;
+ struct {
+ uint32_t temp;
+ } mem_sdc_bg;
+ struct {
+ uint32_t di;
+ bool interlaced;
+ uint32_t in_pixel_fmt;
+ uint32_t out_pixel_fmt;
+ bool alpha_chan_en;
+ } mem_dp_fg_sync;
+ struct {
+ uint32_t di;
+ } direct_async;
+ struct {
+ display_port_t disp;
+ mcu_mode_t ch_mode;
+ uint32_t out_left;
+ uint32_t out_top;
+ } adc_sys1;
+ struct {
+ display_port_t disp;
+ mcu_mode_t ch_mode;
+ uint32_t out_left;
+ uint32_t out_top;
+ } adc_sys2;
+} ipu_channel_params_t;
+
+/*
+ * IPU_IRQF_ONESHOT - Interrupt is not reenabled after the irq handler finished.
+ */
+#define IPU_IRQF_NONE 0x00000000
+#define IPU_IRQF_ONESHOT 0x00000001
+
+/*!
+ * Enumeration of IPU interrupt sources.
+ */
+enum ipu_irq_line {
+ IPU_IRQ_CSI0_OUT_EOF = 0,
+ IPU_IRQ_CSI1_OUT_EOF = 1,
+ IPU_IRQ_CSI2_OUT_EOF = 2,
+ IPU_IRQ_CSI3_OUT_EOF = 3,
+ IPU_IRQ_VDIC_OUT_EOF = 5,
+ IPU_IRQ_VDI_P_IN_EOF = 8,
+ IPU_IRQ_VDI_C_IN_EOF = 9,
+ IPU_IRQ_VDI_N_IN_EOF = 10,
+ IPU_IRQ_PP_IN_EOF = 11,
+ IPU_IRQ_PRP_IN_EOF = 12,
+ IPU_IRQ_PRP_GRAPH_IN_EOF = 14,
+ IPU_IRQ_PP_GRAPH_IN_EOF = 15,
+ IPU_IRQ_PRP_ALPHA_IN_EOF = 17,
+ IPU_IRQ_PP_ALPHA_IN_EOF = 18,
+ IPU_IRQ_PRP_ENC_OUT_EOF = 20,
+ IPU_IRQ_PRP_VF_OUT_EOF = 21,
+ IPU_IRQ_PP_OUT_EOF = 22,
+ IPU_IRQ_BG_SYNC_EOF = 23,
+ IPU_IRQ_BG_ASYNC_EOF = 24,
+ IPU_IRQ_FG_SYNC_EOF = 27,
+ IPU_IRQ_DC_SYNC_EOF = 28,
+ IPU_IRQ_FG_ASYNC_EOF = 29,
+ IPU_IRQ_FG_ALPHA_SYNC_EOF = 31,
+
+ IPU_IRQ_FG_ALPHA_ASYNC_EOF = 33,
+ IPU_IRQ_DC_READ_EOF = 40,
+ IPU_IRQ_DC_ASYNC_EOF = 41,
+ IPU_IRQ_DC_CMD1_EOF = 42,
+ IPU_IRQ_DC_CMD2_EOF = 43,
+ IPU_IRQ_DC_MASK_EOF = 44,
+ IPU_IRQ_PRP_ENC_ROT_IN_EOF = 45,
+ IPU_IRQ_PRP_VF_ROT_IN_EOF = 46,
+ IPU_IRQ_PP_ROT_IN_EOF = 47,
+ IPU_IRQ_PRP_ENC_ROT_OUT_EOF = 48,
+ IPU_IRQ_PRP_VF_ROT_OUT_EOF = 49,
+ IPU_IRQ_PP_ROT_OUT_EOF = 50,
+ IPU_IRQ_BG_ALPHA_SYNC_EOF = 51,
+ IPU_IRQ_BG_ALPHA_ASYNC_EOF = 52,
+
+ IPU_IRQ_BG_SYNC_NFACK = 64 + 23,
+ IPU_IRQ_FG_SYNC_NFACK = 64 + 27,
+ IPU_IRQ_DC_SYNC_NFACK = 64 + 28,
+
+ IPU_IRQ_DP_SF_START = 448 + 2,
+ IPU_IRQ_DP_SF_END = 448 + 3,
+ IPU_IRQ_BG_SF_END = IPU_IRQ_DP_SF_END,
+ IPU_IRQ_DC_FC_0 = 448 + 8,
+ IPU_IRQ_DC_FC_1 = 448 + 9,
+ IPU_IRQ_DC_FC_2 = 448 + 10,
+ IPU_IRQ_DC_FC_3 = 448 + 11,
+ IPU_IRQ_DC_FC_4 = 448 + 12,
+ IPU_IRQ_DC_FC_6 = 448 + 13,
+ IPU_IRQ_VSYNC_PRE_0 = 448 + 14,
+ IPU_IRQ_VSYNC_PRE_1 = 448 + 15,
+
+ IPU_IRQ_COUNT
+};
+
+/*!
+ * Bitfield of Display Interface signal polarities.
+ */
+typedef struct {
+ unsigned datamask_en:1;
+ unsigned int_clk:1;
+ unsigned interlaced:1;
+ unsigned odd_field_first:1;
+ unsigned clksel_en:1;
+ unsigned clkidle_en:1;
+ unsigned data_pol:1; /* true = inverted */
+ unsigned clk_pol:1; /* true = rising edge */
+ unsigned enable_pol:1;
+ unsigned Hsync_pol:1; /* true = active high */
+ unsigned Vsync_pol:1;
+} ipu_di_signal_cfg_t;
+
+/*!
+ * Bitfield of CSI signal polarities and modes.
+ */
+
+typedef struct {
+ unsigned data_width:4;
+ unsigned clk_mode:3;
+ unsigned ext_vsync:1;
+ unsigned Vsync_pol:1;
+ unsigned Hsync_pol:1;
+ unsigned pixclk_pol:1;
+ unsigned data_pol:1;
+ unsigned sens_clksrc:1;
+ unsigned pack_tight:1;
+ unsigned force_eof:1;
+ unsigned data_en_pol:1;
+ unsigned data_fmt;
+ unsigned csi;
+ unsigned mclk;
+} ipu_csi_signal_cfg_t;
+
+/*!
+ * Enumeration of CSI data bus widths.
+ */
+enum {
+ IPU_CSI_DATA_WIDTH_4 = 0,
+ IPU_CSI_DATA_WIDTH_8 = 1,
+ IPU_CSI_DATA_WIDTH_10 = 3,
+ IPU_CSI_DATA_WIDTH_16 = 9,
+};
+
+/*!
+ * Enumeration of CSI clock modes.
+ */
+enum {
+ IPU_CSI_CLK_MODE_GATED_CLK,
+ IPU_CSI_CLK_MODE_NONGATED_CLK,
+ IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
+ IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
+ IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
+ IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
+ IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
+ IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
+};
+
+enum {
+ IPU_CSI_MIPI_DI0,
+ IPU_CSI_MIPI_DI1,
+ IPU_CSI_MIPI_DI2,
+ IPU_CSI_MIPI_DI3,
+};
+
+typedef enum {
+ RGB,
+ YCbCr,
+ YUV
+} ipu_color_space_t;
+
+/*!
+ * Enumeration of ADC vertical sync mode.
+ */
+typedef enum {
+ VsyncNone,
+ VsyncInternal,
+ VsyncCSI,
+ VsyncExternal
+} vsync_t;
+
+typedef enum {
+ DAT,
+ CMD
+} cmddata_t;
+
+/*!
+ * Enumeration of ADC display update mode.
+ */
+typedef enum {
+ IPU_ADC_REFRESH_NONE,
+ IPU_ADC_AUTO_REFRESH,
+ IPU_ADC_AUTO_REFRESH_SNOOP,
+ IPU_ADC_SNOOPING,
+} ipu_adc_update_mode_t;
+
+/*!
+ * Enumeration of ADC display interface types (serial or parallel).
+ */
+enum {
+ IPU_ADC_IFC_MODE_SYS80_TYPE1,
+ IPU_ADC_IFC_MODE_SYS80_TYPE2,
+ IPU_ADC_IFC_MODE_SYS68K_TYPE1,
+ IPU_ADC_IFC_MODE_SYS68K_TYPE2,
+ IPU_ADC_IFC_MODE_3WIRE_SERIAL,
+ IPU_ADC_IFC_MODE_4WIRE_SERIAL,
+ IPU_ADC_IFC_MODE_5WIRE_SERIAL_CLK,
+ IPU_ADC_IFC_MODE_5WIRE_SERIAL_CS,
+};
+
+enum {
+ IPU_ADC_IFC_WIDTH_8,
+ IPU_ADC_IFC_WIDTH_16,
+};
+
+/*!
+ * Enumeration of ADC display interface burst mode.
+ */
+enum {
+ IPU_ADC_BURST_WCS,
+ IPU_ADC_BURST_WBLCK,
+ IPU_ADC_BURST_NONE,
+ IPU_ADC_BURST_SERIAL,
+};
+
+/*!
+ * Enumeration of ADC display interface RW signal timing modes.
+ */
+enum {
+ IPU_ADC_SER_NO_RW,
+ IPU_ADC_SER_RW_BEFORE_RS,
+ IPU_ADC_SER_RW_AFTER_RS,
+};
+
+/*!
+ * Bitfield of ADC signal polarities and modes.
+ */
+typedef struct {
+ unsigned data_pol:1;
+ unsigned clk_pol:1;
+ unsigned cs_pol:1;
+ unsigned rs_pol:1;
+ unsigned addr_pol:1;
+ unsigned read_pol:1;
+ unsigned write_pol:1;
+ unsigned Vsync_pol:1;
+ unsigned burst_pol:1;
+ unsigned burst_mode:2;
+ unsigned ifc_mode:3;
+ unsigned ifc_width:5;
+ unsigned ser_preamble_len:4;
+ unsigned ser_preamble:8;
+ unsigned ser_rw_mode:2;
+} ipu_adc_sig_cfg_t;
+
+/*!
+ * Enumeration of ADC template commands.
+ */
+enum {
+ RD_DATA,
+ RD_ACK,
+ RD_WAIT,
+ WR_XADDR,
+ WR_YADDR,
+ WR_ADDR,
+ WR_CMND,
+ WR_DATA,
+};
+
+/*!
+ * Enumeration of ADC template command flow control.
+ */
+enum {
+ SINGLE_STEP,
+ PAUSE,
+ STOP,
+};
+
+
+/*Define template constants*/
+#define ATM_ADDR_RANGE 0x20 /*offset address of DISP */
+#define TEMPLATE_BUF_SIZE 0x20 /*size of template */
+
+/*!
+ * Define to create ADC template command entry.
+ */
+#define ipu_adc_template_gen(oc, rs, fc, dat) (((rs) << 29) | ((fc) << 27) | \
+ ((oc) << 24) | (dat))
+
+typedef struct {
+ u32 reg;
+ u32 value;
+} ipu_lpmc_reg_t;
+
+#define IPU_LPMC_REG_READ 0x80000000L
+
+#define CSI_MCLK_VF 1
+#define CSI_MCLK_ENC 2
+#define CSI_MCLK_RAW 4
+#define CSI_MCLK_I2C 8
+
+struct ipu_soc;
+/* Common IPU API */
+struct ipu_soc *ipu_get_soc(int id);
+int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
+void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel);
+void ipu_disable_hsp_clk(struct ipu_soc *ipu);
+
+static inline bool ipu_can_rotate_in_place(ipu_rotate_mode_t rot)
+{
+#ifdef CONFIG_MXC_IPU_V3D
+ return (rot < IPU_ROTATE_HORIZ_FLIP);
+#else
+ return (rot < IPU_ROTATE_90_RIGHT);
+#endif
+}
+
+int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ ipu_rotate_mode_t rot_mode,
+ dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
+ dma_addr_t phyaddr_2,
+ uint32_t u_offset, uint32_t v_offset);
+
+int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum, dma_addr_t phyaddr);
+
+int32_t ipu_update_channel_offset(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ uint32_t u, uint32_t v,
+ uint32_t vertical_offset, uint32_t horizontal_offset);
+
+int32_t ipu_get_channel_offset(uint32_t pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ uint32_t u, uint32_t v,
+ uint32_t vertical_offset, uint32_t horizontal_offset,
+ uint32_t *u_offset, uint32_t *v_offset);
+
+int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
+ ipu_buffer_t type, uint32_t bufNum);
+int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum);
+
+int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
+int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
+
+int32_t ipu_is_channel_busy(struct ipu_soc *ipu, ipu_channel_t channel);
+int32_t ipu_check_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum);
+void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum);
+uint32_t ipu_get_cur_buffer_idx(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type);
+int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel);
+int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop);
+int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch);
+uint32_t ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel);
+
+int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi);
+int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi);
+
+int ipu_lowpwr_display_enable(void);
+int ipu_lowpwr_display_disable(void);
+
+int ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq);
+void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq);
+void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq);
+int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
+ irqreturn_t(*handler) (int, void *),
+ uint32_t irq_flags, const char *devname, void *dev_id);
+void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id);
+bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq);
+void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
+int32_t ipu_set_channel_bandmode(struct ipu_soc *ipu, ipu_channel_t channel,
+ ipu_buffer_t type, uint32_t band_height);
+
+/* two stripe calculations */
+struct stripe_param{
+ unsigned int input_width; /* width of the input stripe */
+ unsigned int output_width; /* width of the output stripe */
+ unsigned int input_column; /* the first column on the input stripe */
+ unsigned int output_column; /* the first column on the output stripe */
+ unsigned int idr;
+ /* inverse downisizing ratio parameter; expressed as a power of 2 */
+ unsigned int irr;
+ /* inverse resizing ratio parameter; expressed as a multiple of 2^-13 */
+};
+int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
+ unsigned int output_frame_width,
+ const unsigned int maximal_stripe_width,
+ const unsigned long long cirr,
+ const unsigned int equal_stripes,
+ u32 input_pixelformat,
+ u32 output_pixelformat,
+ struct stripe_param *left,
+ struct stripe_param *right);
+
+/* SDC API */
+int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp,
+ uint32_t pixel_clk,
+ uint16_t width, uint16_t height,
+ uint32_t pixel_fmt,
+ uint16_t h_start_width, uint16_t h_sync_width,
+ uint16_t h_end_width, uint16_t v_start_width,
+ uint16_t v_sync_width, uint16_t v_end_width,
+ uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig);
+
+void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp);
+
+int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t x_pos,
+ int16_t y_pos);
+int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t *x_pos,
+ int16_t *y_pos);
+int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
+ uint8_t alpha);
+int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
+ uint32_t colorKey);
+int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
+ int constk[], int slopek[]);
+
+int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
+ uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig);
+void ipu_reset_disp_panel(struct ipu_soc *ipu);
+
+/* CMOS Sensor Interface API */
+int32_t ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
+ uint32_t pixel_fmt, ipu_csi_signal_cfg_t sig);
+
+int32_t ipu_csi_get_sensor_protocol(struct ipu_soc *ipu, uint32_t csi);
+
+int32_t ipu_csi_enable_mclk(struct ipu_soc *ipu, int src, bool flag, bool wait);
+
+static inline int32_t ipu_csi_enable_mclk_if(struct ipu_soc *ipu, int src, uint32_t csi,
+ bool flag, bool wait)
+{
+ return ipu_csi_enable_mclk(ipu, csi, flag, wait);
+}
+
+int ipu_csi_read_mclk_flag(void);
+
+void ipu_csi_flash_strobe(bool flag);
+
+void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi);
+
+void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi);
+
+void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi);
+
+uint32_t bytes_per_pixel(uint32_t fmt);
+
+bool ipu_ch_param_bad_alpha_pos(uint32_t fmt);
+int ipu_ch_param_get_axi_id(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type);
+ipu_color_space_t format_to_colorspace(uint32_t fmt);
+bool ipu_pixel_format_is_gpu_tile(uint32_t fmt);
+bool ipu_pixel_format_is_split_gpu_tile(uint32_t fmt);
+bool ipu_pixel_format_is_pre_yuv(uint32_t fmt);
+bool ipu_pixel_format_is_multiplanar_yuv(uint32_t fmt);
+
+struct ipuv3_fb_platform_data {
+ char disp_dev[32];
+ u32 interface_pix_fmt;
+ char *mode_str;
+ int default_bpp;
+ bool int_clk;
+
+ /* reserved mem */
+ resource_size_t res_base[2];
+ resource_size_t res_size[2];
+
+ /*
+ * Late init to avoid display channel being
+ * re-initialized as we've probably setup the
+ * channel in bootloader.
+ */
+ bool late_init;
+
+ /* Enable prefetch engine or not? */
+ bool prefetch;
+
+ /* Enable the PRE resolve engine or not? */
+ bool resolve;
+};
+
+#endif /* __LINUX_IPU_V3_H_ */
diff --git a/include/linux/ipu.h b/include/linux/ipu.h
new file mode 100644
index 000000000000..1090ac65f24b
--- /dev/null
+++ b/include/linux/ipu.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2005-2015 Freescale Semiconductor, Inc.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+/*!
+ * @defgroup IPU MXC Image Processing Unit (IPU) Driver
+ */
+/*!
+ * @file linux/ipu.h
+ *
+ * @brief This file contains the IPU driver API declarations.
+ *
+ * @ingroup IPU
+ */
+
+#ifndef __LINUX_IPU_H__
+#define __LINUX_IPU_H__
+
+#include <linux/interrupt.h>
+#include <uapi/linux/ipu.h>
+
+unsigned int fmt_to_bpp(unsigned int pixelformat);
+cs_t colorspaceofpixel(int fmt);
+int need_csc(int ifmt, int ofmt);
+
+int ipu_queue_task(struct ipu_task *task);
+int ipu_check_task(struct ipu_task *task);
+
+#endif
diff --git a/include/linux/isl29023.h b/include/linux/isl29023.h
new file mode 100644
index 000000000000..5c84566b7b21
--- /dev/null
+++ b/include/linux/isl29023.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+#ifndef __ISL29023_H__
+#define __ISL29023_H__
+
+#include <linux/types.h>
+
+#define ISL29023_PD_MODE 0x0
+#define ISL29023_ALS_ONCE_MODE 0x1
+#define ISL29023_IR_ONCE_MODE 0x2
+#define ISL29023_ALS_CONT_MODE 0x5
+#define ISL29023_IR_CONT_MODE 0x6
+
+#define ISL29023_INT_PERSISTS_1 0x0
+#define ISL29023_INT_PERSISTS_4 0x1
+#define ISL29023_INT_PERSISTS_8 0x2
+#define ISL29023_INT_PERSISTS_16 0x3
+
+#define ISL29023_RES_16 0x0
+#define ISL29023_RES_12 0x1
+#define ISL29023_RES_8 0x2
+#define ISL29023_RES_4 0x3
+
+#define ISL29023_RANGE_1K 0x0
+#define ISL29023_RANGE_4K 0x1
+#define ISL29023_RANGE_16K 0x2
+#define ISL29023_RANGE_64K 0x3
+
+#endif
diff --git a/include/linux/mfd/max17135.h b/include/linux/mfd/max17135.h
new file mode 100644
index 000000000000..e3b8777c8630
--- /dev/null
+++ b/include/linux/mfd/max17135.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2010-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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __LINUX_REGULATOR_MAX17135_H_
+#define __LINUX_REGULATOR_MAX17135_H_
+
+/*
+ * PMIC Register Addresses
+ */
+enum {
+ REG_MAX17135_EXT_TEMP = 0x0,
+ REG_MAX17135_CONFIG,
+ REG_MAX17135_INT_TEMP = 0x4,
+ REG_MAX17135_STATUS,
+ REG_MAX17135_PRODUCT_REV,
+ REG_MAX17135_PRODUCT_ID,
+ REG_MAX17135_DVR,
+ REG_MAX17135_ENABLE,
+ REG_MAX17135_FAULT, /*0x0A*/
+ REG_MAX17135_HVINP,
+ REG_MAX17135_PRGM_CTRL,
+ REG_MAX17135_TIMING1 = 0x10, /* Timing regs base address is 0x10 */
+ REG_MAX17135_TIMING2,
+ REG_MAX17135_TIMING3,
+ REG_MAX17135_TIMING4,
+ REG_MAX17135_TIMING5,
+ REG_MAX17135_TIMING6,
+ REG_MAX17135_TIMING7,
+ REG_MAX17135_TIMING8,
+};
+#define MAX17135_REG_NUM 21
+#define MAX17135_MAX_REGISTER 0xFF
+
+/*
+ * Bitfield macros that use rely on bitfield width/shift information.
+ */
+#define BITFMASK(field) (((1U << (field ## _WID)) - 1) << (field ## _LSH))
+#define BITFVAL(field, val) ((val) << (field ## _LSH))
+#define BITFEXT(var, bit) ((var & BITFMASK(bit)) >> (bit ## _LSH))
+
+/*
+ * Shift and width values for each register bitfield
+ */
+#define EXT_TEMP_LSH 7
+#define EXT_TEMP_WID 9
+
+#define THERMAL_SHUTDOWN_LSH 0
+#define THERMAL_SHUTDOWN_WID 1
+
+#define INT_TEMP_LSH 7
+#define INT_TEMP_WID 9
+
+#define STAT_BUSY_LSH 0
+#define STAT_BUSY_WID 1
+#define STAT_OPEN_LSH 1
+#define STAT_OPEN_WID 1
+#define STAT_SHRT_LSH 2
+#define STAT_SHRT_WID 1
+
+#define PROD_REV_LSH 0
+#define PROD_REV_WID 8
+
+#define PROD_ID_LSH 0
+#define PROD_ID_WID 8
+
+#define DVR_LSH 0
+#define DVR_WID 8
+
+#define ENABLE_LSH 0
+#define ENABLE_WID 1
+#define VCOM_ENABLE_LSH 1
+#define VCOM_ENABLE_WID 1
+
+#define FAULT_FBPG_LSH 0
+#define FAULT_FBPG_WID 1
+#define FAULT_HVINP_LSH 1
+#define FAULT_HVINP_WID 1
+#define FAULT_HVINN_LSH 2
+#define FAULT_HVINN_WID 1
+#define FAULT_FBNG_LSH 3
+#define FAULT_FBNG_WID 1
+#define FAULT_HVINPSC_LSH 4
+#define FAULT_HVINPSC_WID 1
+#define FAULT_HVINNSC_LSH 5
+#define FAULT_HVINNSC_WID 1
+#define FAULT_OT_LSH 6
+#define FAULT_OT_WID 1
+#define FAULT_POK_LSH 7
+#define FAULT_POK_WID 1
+
+#define HVINP_LSH 0
+#define HVINP_WID 4
+
+#define CTRL_DVR_LSH 0
+#define CTRL_DVR_WID 1
+#define CTRL_TIMING_LSH 1
+#define CTRL_TIMING_WID 1
+
+#define TIMING1_LSH 0
+#define TIMING1_WID 8
+#define TIMING2_LSH 0
+#define TIMING2_WID 8
+#define TIMING3_LSH 0
+#define TIMING3_WID 8
+#define TIMING4_LSH 0
+#define TIMING4_WID 8
+#define TIMING5_LSH 0
+#define TIMING5_WID 8
+#define TIMING6_LSH 0
+#define TIMING6_WID 8
+#define TIMING7_LSH 0
+#define TIMING7_WID 8
+#define TIMING8_LSH 0
+#define TIMING8_WID 8
+
+struct max17135 {
+ /* chip revision */
+ int rev;
+
+ struct device *dev;
+ struct max17135_platform_data *pdata;
+
+ /* Platform connection */
+ struct i2c_client *i2c_client;
+
+ /* Timings */
+ unsigned int gvee_pwrup;
+ unsigned int vneg_pwrup;
+ unsigned int vpos_pwrup;
+ unsigned int gvdd_pwrup;
+ unsigned int gvdd_pwrdn;
+ unsigned int vpos_pwrdn;
+ unsigned int vneg_pwrdn;
+ unsigned int gvee_pwrdn;
+
+ /* GPIOs */
+ int gpio_pmic_pwrgood;
+ int gpio_pmic_vcom_ctrl;
+ int gpio_pmic_wakeup;
+ int gpio_pmic_v3p3;
+ int gpio_pmic_intr;
+
+ /* MAX17135 part variables */
+ int pass_num;
+ int vcom_uV;
+
+ /* One-time VCOM setup marker */
+ bool vcom_setup;
+
+ /* powerup/powerdown wait time */
+ int max_wait;
+};
+
+enum {
+ /* In alphabetical order */
+ MAX17135_DISPLAY, /* virtual master enable */
+ MAX17135_GVDD,
+ MAX17135_GVEE,
+ MAX17135_HVINN,
+ MAX17135_HVINP,
+ MAX17135_VCOM,
+ MAX17135_VNEG,
+ MAX17135_VPOS,
+ MAX17135_V3P3,
+ MAX17135_NUM_REGULATORS,
+};
+
+/*
+ * Declarations
+ */
+struct regulator_init_data;
+struct max17135_regulator_data;
+
+struct max17135_platform_data {
+ unsigned int gvee_pwrup;
+ unsigned int vneg_pwrup;
+ unsigned int vpos_pwrup;
+ unsigned int gvdd_pwrup;
+ unsigned int gvdd_pwrdn;
+ unsigned int vpos_pwrdn;
+ unsigned int vneg_pwrdn;
+ unsigned int gvee_pwrdn;
+ int gpio_pmic_pwrgood;
+ int gpio_pmic_vcom_ctrl;
+ int gpio_pmic_wakeup;
+ int gpio_pmic_v3p3;
+ int gpio_pmic_intr;
+ int pass_num;
+ int vcom_uV;
+
+ /* PMIC */
+ struct max17135_regulator_data *regulators;
+ int num_regulators;
+};
+
+struct max17135_regulator_data {
+ int id;
+ struct regulator_init_data *initdata;
+ struct device_node *reg_node;
+};
+
+int max17135_reg_read(int reg_num, unsigned int *reg_val);
+int max17135_reg_write(int reg_num, const unsigned int reg_val);
+
+#endif
diff --git a/include/linux/mfd/mxc-hdmi-core.h b/include/linux/mfd/mxc-hdmi-core.h
new file mode 100644
index 000000000000..b2696b951f43
--- /dev/null
+++ b/include/linux/mfd/mxc-hdmi-core.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011-2015 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
+ */
+#ifndef __LINUX_MXC_HDMI_CORE_H_
+#define __LINUX_MXC_HDMI_CORE_H_
+
+#include <video/mxc_edid.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define IRQ_DISABLE_SUCCEED 0
+#define IRQ_DISABLE_FAIL 1
+
+bool hdmi_check_overflow(void);
+
+u8 hdmi_readb(unsigned int reg);
+void hdmi_writeb(u8 value, unsigned int reg);
+void hdmi_mask_writeb(u8 data, unsigned int addr, u8 shift, u8 mask);
+unsigned int hdmi_read4(unsigned int reg);
+void hdmi_write4(unsigned int value, unsigned int reg);
+
+void hdmi_irq_init(void);
+void hdmi_irq_enable(int irq);
+unsigned int hdmi_irq_disable(int irq);
+
+void hdmi_set_sample_rate(unsigned int rate);
+void hdmi_set_dma_mode(unsigned int dma_running);
+void hdmi_init_clk_regenerator(void);
+void hdmi_clk_regenerator_update_pixel_clock(u32 pixclock);
+
+void hdmi_set_edid_cfg(struct mxc_edid_cfg *cfg);
+void hdmi_get_edid_cfg(struct mxc_edid_cfg *cfg);
+
+extern int mxc_hdmi_ipu_id;
+extern int mxc_hdmi_disp_id;
+
+void hdmi_set_registered(int registered);
+int hdmi_get_registered(void);
+int mxc_hdmi_abort_stream(void);
+int mxc_hdmi_register_audio(struct snd_pcm_substream *substream);
+void mxc_hdmi_unregister_audio(struct snd_pcm_substream *substream);
+unsigned int hdmi_set_cable_state(unsigned int state);
+unsigned int hdmi_set_blank_state(unsigned int state);
+int check_hdmi_state(void);
+
+#endif
diff --git a/include/linux/mfd/pf1550.h b/include/linux/mfd/pf1550.h
new file mode 100644
index 000000000000..7d0a13e1144a
--- /dev/null
+++ b/include/linux/mfd/pf1550.h
@@ -0,0 +1,250 @@
+/*
+ * pf1550.h - mfd head file for PF1550
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Robin Gong <yibin.gong@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_MFD_PF1550_H
+#define __LINUX_MFD_PF1550_H
+
+#include <linux/i2c.h>
+
+enum chips { PF1550 = 1, };
+
+enum pf1550_pmic_reg {
+ /* PMIC regulator part */
+ PF1550_PMIC_REG_DEVICE_ID = 0x00,
+ PF1550_PMIC_REG_OTP_FLAVOR = 0x01,
+ PF1550_PMIC_REG_SILICON_REV = 0x02,
+
+ PF1550_PMIC_REG_INT_CATEGORY = 0x06,
+ PF1550_PMIC_REG_SW_INT_STAT0 = 0x08,
+ PF1550_PMIC_REG_SW_INT_MASK0 = 0x09,
+ PF1550_PMIC_REG_SW_INT_SENSE0 = 0x0A,
+ PF1550_PMIC_REG_SW_INT_STAT1 = 0x0B,
+ PF1550_PMIC_REG_SW_INT_MASK1 = 0x0C,
+ PF1550_PMIC_REG_SW_INT_SENSE1 = 0x0D,
+ PF1550_PMIC_REG_SW_INT_STAT2 = 0x0E,
+ PF1550_PMIC_REG_SW_INT_MASK2 = 0x0F,
+ PF1550_PMIC_REG_SW_INT_SENSE2 = 0x10,
+ PF1550_PMIC_REG_LDO_INT_STAT0 = 0x18,
+ PF1550_PMIC_REG_LDO_INT_MASK0 = 0x19,
+ PF1550_PMIC_REG_LDO_INT_SENSE0 = 0x1A,
+ PF1550_PMIC_REG_TEMP_INT_STAT0 = 0x20,
+ PF1550_PMIC_REG_TEMP_INT_MASK0 = 0x21,
+ PF1550_PMIC_REG_TEMP_INT_SENSE0 = 0x22,
+ PF1550_PMIC_REG_ONKEY_INT_STAT0 = 0x24,
+ PF1550_PMIC_REG_ONKEY_INT_MASK0 = 0x25,
+ PF1550_PMIC_REG_ONKEY_INT_SENSE0 = 0x26,
+ PF1550_PMIC_REG_MISC_INT_STAT0 = 0x28,
+ PF1550_PMIC_REG_MISC_INT_MASK0 = 0x29,
+ PF1550_PMIC_REG_MISC_INT_SENSE0 = 0x2A,
+
+ PF1550_PMIC_REG_COINCELL_CONTROL = 0x30,
+
+ PF1550_PMIC_REG_SW1_VOLT = 0x32,
+ PF1550_PMIC_REG_SW1_STBY_VOLT = 0x33,
+ PF1550_PMIC_REG_SW1_SLP_VOLT = 0x34,
+ PF1550_PMIC_REG_SW1_CTRL = 0x35,
+ PF1550_PMIC_REG_SW1_CTRL1 = 0x36,
+ PF1550_PMIC_REG_SW2_VOLT = 0x38,
+ PF1550_PMIC_REG_SW2_STBY_VOLT = 0x39,
+ PF1550_PMIC_REG_SW2_SLP_VOLT = 0x3A,
+ PF1550_PMIC_REG_SW2_CTRL = 0x3B,
+ PF1550_PMIC_REG_SW2_CTRL1 = 0x3C,
+ PF1550_PMIC_REG_SW3_VOLT = 0x3E,
+ PF1550_PMIC_REG_SW3_STBY_VOLT = 0x3F,
+ PF1550_PMIC_REG_SW3_SLP_VOLT = 0x40,
+ PF1550_PMIC_REG_SW3_CTRL = 0x41,
+ PF1550_PMIC_REG_SW3_CTRL1 = 0x42,
+ PF1550_PMIC_REG_VSNVS_CTRL = 0x48,
+ PF1550_PMIC_REG_VREFDDR_CTRL = 0x4A,
+ PF1550_PMIC_REG_LDO1_VOLT = 0x4C,
+ PF1550_PMIC_REG_LDO1_CTRL = 0x4D,
+ PF1550_PMIC_REG_LDO2_VOLT = 0x4F,
+ PF1550_PMIC_REG_LDO2_CTRL = 0x50,
+ PF1550_PMIC_REG_LDO3_VOLT = 0x52,
+ PF1550_PMIC_REG_LDO3_CTRL = 0x53,
+ PF1550_PMIC_REG_PWRCTRL0 = 0x58,
+ PF1550_PMIC_REG_PWRCTRL1 = 0x59,
+ PF1550_PMIC_REG_PWRCTRL2 = 0x5A,
+ PF1550_PMIC_REG_PWRCTRL3 = 0x5B,
+ PF1550_PMIC_REG_SW1_PWRDN_SEQ = 0x5F,
+ PF1550_PMIC_REG_SW2_PWRDN_SEQ = 0x60,
+ PF1550_PMIC_REG_SW3_PWRDN_SEQ = 0x61,
+ PF1550_PMIC_REG_LDO1_PWRDN_SEQ = 0x62,
+ PF1550_PMIC_REG_LDO2_PWRDN_SEQ = 0x63,
+ PF1550_PMIC_REG_LDO3_PWRDN_SEQ = 0x64,
+ PF1550_PMIC_REG_VREFDDR_PWRDN_SEQ = 0x65,
+
+ PF1550_PMIC_REG_STATE_INFO = 0x67,
+ PF1550_PMIC_REG_I2C_ADDR = 0x68,
+ PF1550_PMIC_REG_IO_DRV0 = 0x69,
+ PF1550_PMIC_REG_IO_DRV1 = 0x6A,
+ PF1550_PMIC_REG_RC_16MHZ = 0x6B,
+ PF1550_PMIC_REG_KEY = 0x6F,
+
+ /* charger part */
+ PF1550_CHARG_REG_CHG_INT = 0x80,
+ PF1550_CHARG_REG_CHG_INT_MASK = 0x82,
+ PF1550_CHARG_REG_CHG_INT_OK = 0x84,
+ PF1550_CHARG_REG_VBUS_SNS = 0x86,
+ PF1550_CHARG_REG_CHG_SNS = 0x87,
+ PF1550_CHARG_REG_BATT_SNS = 0x88,
+ PF1550_CHARG_REG_CHG_OPER = 0x89,
+ PF1550_CHARG_REG_CHG_TMR = 0x8A,
+ PF1550_CHARG_REG_CHG_EOC_CNFG = 0x8D,
+ PF1550_CHARG_REG_CHG_CURR_CNFG = 0x8E,
+ PF1550_CHARG_REG_BATT_REG = 0x8F,
+ PF1550_CHARG_REG_BATFET_CNFG = 0x91,
+ PF1550_CHARG_REG_THM_REG_CNFG = 0x92,
+ PF1550_CHARG_REG_VBUS_INLIM_CNFG = 0x94,
+ PF1550_CHARG_REG_VBUS_LIN_DPM = 0x95,
+ PF1550_CHARG_REG_USB_PHY_LDO_CNFG = 0x96,
+ PF1550_CHARG_REG_DBNC_DELAY_TIME = 0x98,
+ PF1550_CHARG_REG_CHG_INT_CNFG = 0x99,
+ PF1550_CHARG_REG_THM_ADJ_SETTING = 0x9A,
+ PF1550_CHARG_REG_VBUS2SYS_CNFG = 0x9B,
+ PF1550_CHARG_REG_LED_PWM = 0x9C,
+ PF1550_CHARG_REG_FAULT_BATFET_CNFG = 0x9D,
+ PF1550_CHARG_REG_LED_CNFG = 0x9E,
+ PF1550_CHARG_REG_CHGR_KEY2 = 0x9F,
+
+ PF1550_TEST_REG_FMRADDR = 0xC4,
+ PF1550_TEST_REG_FMRDATA = 0xC5,
+ PF1550_TEST_REG_KEY3 = 0xDF,
+
+ PF1550_PMIC_REG_END = 0xff,
+};
+
+#define PF1550_CHG_PRECHARGE 0
+#define PF1550_CHG_CONSTANT_CURRENT 1
+#define PF1550_CHG_CONSTANT_VOL 2
+#define PF1550_CHG_EOC 3
+#define PF1550_CHG_DONE 4
+#define PF1550_CHG_TIMER_FAULT 6
+#define PF1550_CHG_SUSPEND 7
+#define PF1550_CHG_OFF_INV 8
+#define PF1550_CHG_BAT_OVER 9
+#define PF1550_CHG_OFF_TEMP 10
+#define PF1550_CHG_LINEAR_ONLY 12
+#define PF1550_CHG_SNS_MASK 0xf
+
+#define PF1550_BAT_NO_VBUS 0
+#define PF1550_BAT_LOW_THAN_PRECHARG 1
+#define PF1550_BAT_CHARG_FAIL 2
+#define PF1550_BAT_HIGH_THAN_PRECHARG 4
+#define PF1550_BAT_OVER_VOL 5
+#define PF1550_BAT_NO_DETECT 6
+#define PF1550_BAT_SNS_MASK 0x7
+
+#define PF1550_VBUS_UVLO BIT(2)
+#define PF1550_VBUS_IN2SYS BIT(3)
+#define PF1550_VBUS_OVLO BIT(4)
+#define PF1550_VBUS_VALID BIT(5)
+
+#define PF1550_CHARG_REG_BATT_REG_CHGCV_MASK 0x3f
+#define PF1550_CHARG_REG_BATT_REG_VMINSYS_SHIFT 6
+#define PF1550_CHARG_REG_BATT_REG_VMINSYS_MASK (0x3 << 6)
+#define PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_SHIFT 2
+#define PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_MASK (0x3 << 2)
+
+#define PMIC_IRQ_SW1_LS BIT(0)
+#define PMIC_IRQ_SW2_LS BIT(1)
+#define PMIC_IRQ_SW3_LS BIT(2)
+#define PMIC_IRQ_SW1_HS BIT(0)
+#define PMIC_IRQ_SW2_HS BIT(1)
+#define PMIC_IRQ_SW3_HS BIT(2)
+#define PMIC_IRQ_LDO1_FAULT BIT(0)
+#define PMIC_IRQ_LDO2_FAULT BIT(1)
+#define PMIC_IRQ_LDO3_FAULT BIT(2)
+#define PMIC_IRQ_TEMP_110 BIT(0)
+#define PMIC_IRQ_TEMP_125 BIT(1)
+
+#define ONKEY_IRQ_PUSHI BIT(0)
+#define ONKEY_IRQ_1SI BIT(1)
+#define ONKEY_IRQ_2SI BIT(2)
+#define ONKEY_IRQ_3SI BIT(3)
+#define ONKEY_IRQ_4SI BIT(4)
+#define ONKEY_IRQ_8SI BIT(5)
+
+#define CHARG_IRQ_BAT2SOCI BIT(1)
+#define CHARG_IRQ_BATI BIT(2)
+#define CHARG_IRQ_CHGI BIT(3)
+#define CHARG_IRQ_VBUSI BIT(5)
+#define CHARG_IRQ_DPMI BIT(6)
+#define CHARG_IRQ_THMI BIT(7)
+
+enum pf1550_pmic_irq {
+ PF1550_PMIC_IRQ_SW1_LS,
+ PF1550_PMIC_IRQ_SW2_LS,
+ PF1550_PMIC_IRQ_SW3_LS,
+ PF1550_PMIC_IRQ_SW1_HS,
+ PF1550_PMIC_IRQ_SW2_HS,
+ PF1550_PMIC_IRQ_SW3_HS,
+ PF1550_PMIC_IRQ_LDO1_FAULT,
+ PF1550_PMIC_IRQ_LDO2_FAULT,
+ PF1550_PMIC_IRQ_LDO3_FAULT,
+ PF1550_PMIC_IRQ_TEMP_110,
+ PF1550_PMIC_IRQ_TEMP_125,
+};
+
+enum pf1550_onkey_irq {
+ PF1550_ONKEY_IRQ_PUSHI,
+ PF1550_ONKEY_IRQ_1SI,
+ PF1550_ONKEY_IRQ_2SI,
+ PF1550_ONKEY_IRQ_3SI,
+ PF1550_ONKEY_IRQ_4SI,
+ PF1550_ONKEY_IRQ_8SI,
+};
+
+enum pf1550_charg_irq {
+ PF1550_CHARG_IRQ_BAT2SOCI,
+ PF1550_CHARG_IRQ_BATI,
+ PF1550_CHARG_IRQ_CHGI,
+ PF1550_CHARG_IRQ_VBUSI,
+ PF1550_CHARG_IRQ_THMI,
+};
+
+enum pf1550_regulators {
+ PF1550_SW1,
+ PF1550_SW2,
+ PF1550_SW3,
+ PF1550_VREFDDR,
+ PF1550_LDO1,
+ PF1550_LDO2,
+ PF1550_LDO3,
+};
+
+struct pf1550_irq_info {
+ unsigned int irq;
+ const char *name;
+ unsigned int virq;
+};
+
+struct pf1550_dev {
+ struct device *dev;
+ struct i2c_client *i2c;
+ int type;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *irq_data_regulator;
+ struct regmap_irq_chip_data *irq_data_onkey;
+ struct regmap_irq_chip_data *irq_data_charger;
+ int irq;
+};
+
+int pf1550_read_otp(struct pf1550_dev *pf1550, unsigned int index,
+ unsigned int *val);
+
+#endif /* __LINUX_MFD_PF1550_H */
diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h
index 674b45d5a757..78a2b2c936f3 100644
--- a/include/linux/mfd/si476x-core.h
+++ b/include/linux/mfd/si476x-core.h
@@ -493,6 +493,8 @@ enum si476x_common_receiver_properties {
SI476X_PROP_DIGITAL_IO_OUTPUT_SAMPLE_RATE = 0x0202,
SI476X_PROP_DIGITAL_IO_OUTPUT_FORMAT = 0x0203,
+ SI476X_PROP_AUDIO_MUTE = 0x0301,
+
SI476X_PROP_SEEK_BAND_BOTTOM = 0x1100,
SI476X_PROP_SEEK_BAND_TOP = 0x1101,
SI476X_PROP_SEEK_FREQUENCY_SPACING = 0x1102,
diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
index c8e0164c5423..29f225235782 100644
--- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
@@ -101,6 +101,7 @@
#define IMX6Q_GPR1_PCIE_ENTER_L1 BIT(26)
#define IMX6Q_GPR1_MIPI_COLOR_SW BIT(25)
#define IMX6Q_GPR1_DPI_OFF BIT(24)
+#define IMX6Q_GPR1_PCIE_SW_PERST BIT(23)
#define IMX6Q_GPR1_EXC_MON_MASK BIT(22)
#define IMX6Q_GPR1_EXC_MON_OKAY 0x0
#define IMX6Q_GPR1_EXC_MON_SLVE BIT(22)
@@ -243,6 +244,23 @@
#define IMX6Q_GPR4_IPU_RD_CACHE_CTL BIT(0)
#define IMX6Q_GPR5_L2_CLK_STOP BIT(8)
+#define IMX6Q_GPR5_ENET_TX_CLK_SEL BIT(9)
+#define IMX6Q_GPR5_PRE_PRG_SEL0_MASK (0x3 << 12)
+#define IMX6Q_GPR5_PRE_PRG_SEL0_SHIFT 12
+#define IMX6Q_GPR5_PRE_PRG_SEL0_MSB 13
+#define IMX6Q_GPR5_PRE_PRG_SEL0_LSB 12
+#define IMX6Q_GPR5_PRE_PRG_SEL0_PRE1_PRG0_CHAN1 (0x0 << 12)
+#define IMX6Q_GPR5_PRE_PRG_SEL0_PRE1_PRG0_CHAN2 (0x1 << 12)
+#define IMX6Q_GPR5_PRE_PRG_SEL0_PRE1_PRG1_CHAN1 (0x2 << 12)
+#define IMX6Q_GPR5_PRE_PRG_SEL0_PRE1_PRG1_CHAN2 (0x3 << 12)
+#define IMX6Q_GPR5_PRE_PRG_SEL1_MASK (0x3 << 14)
+#define IMX6Q_GPR5_PRE_PRG_SEL1_SHIFT 14
+#define IMX6Q_GPR5_PRE_PRG_SEL1_MSB 15
+#define IMX6Q_GPR5_PRE_PRG_SEL1_LSB 14
+#define IMX6Q_GPR5_PRE_PRG_SEL1_PRE2_PRG0_CHAN1 (0x0 << 14)
+#define IMX6Q_GPR5_PRE_PRG_SEL1_PRE2_PRG0_CHAN2 (0x1 << 14)
+#define IMX6Q_GPR5_PRE_PRG_SEL1_PRE2_PRG1_CHAN1 (0x2 << 14)
+#define IMX6Q_GPR5_PRE_PRG_SEL1_PRE2_PRG1_CHAN2 (0x3 << 14)
#define IMX6Q_GPR6_IPU1_ID00_WR_QOS_MASK (0xf << 0)
#define IMX6Q_GPR6_IPU1_ID01_WR_QOS_MASK (0xf << 4)
@@ -286,23 +304,25 @@
#define IMX6Q_GPR10_OCRAM_TZ_ADDR_MASK (0x3f << 5)
#define IMX6Q_GPR10_OCRAM_TZ_EN_MASK BIT(4)
#define IMX6Q_GPR10_DCIC2_MUX_CTL_MASK (0x3 << 2)
-#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI0 (0x0 << 2)
-#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI1 (0x1 << 2)
-#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU2_DI0 (0x2 << 2)
-#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU2_DI1 (0x3 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI1 (0x0 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_LVDS0 (0x1 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_LVDS1 (0x2 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_MIPI (0x3 << 2)
#define IMX6Q_GPR10_DCIC1_MUX_CTL_MASK (0x3 << 0)
#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI0 (0x0 << 0)
-#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI1 (0x1 << 0)
-#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU2_DI0 (0x2 << 0)
-#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU2_DI1 (0x3 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_LVDS0 (0x1 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_LVDS1 (0x2 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_HDMI (0x3 << 0)
#define IMX6Q_GPR12_ARMP_IPG_CLK_EN BIT(27)
#define IMX6Q_GPR12_ARMP_AHB_CLK_EN BIT(26)
#define IMX6Q_GPR12_ARMP_ATB_CLK_EN BIT(25)
#define IMX6Q_GPR12_ARMP_APB_CLK_EN BIT(24)
+#define IMX6Q_GPR12_PCIE_PM_TURN_OFF BIT(16)
#define IMX6Q_GPR12_DEVICE_TYPE (0xf << 12)
#define IMX6Q_GPR12_PCIE_CTL_2 BIT(10)
#define IMX6Q_GPR12_LOS_LEVEL (0x1f << 4)
+#define IMX6Q_GPR12_LOS_LEVEL_9 (0x9 << 4)
#define IMX6Q_GPR13_SDMA_STOP_REQ BIT(30)
#define IMX6Q_GPR13_CAN2_STOP_REQ BIT(29)
@@ -411,6 +431,15 @@
#define IMX6SX_GPR4_FEC_ENET1_STOP_REQ (0x1 << 3)
#define IMX6SX_GPR4_FEC_ENET2_STOP_REQ (0x1 << 4)
+#define IMX6SX_GPR2_MQS_OVERSAMPLE_MASK (0x1 << 26)
+#define IMX6SX_GPR2_MQS_OVERSAMPLE_SHIFT (26)
+#define IMX6SX_GPR2_MQS_EN_MASK (0x1 << 25)
+#define IMX6SX_GPR2_MQS_EN_SHIFT (25)
+#define IMX6SX_GPR2_MQS_SW_RST_MASK (0x1 << 24)
+#define IMX6SX_GPR2_MQS_SW_RST_SHIFT (24)
+#define IMX6SX_GPR2_MQS_CLK_DIV_MASK (0xFF << 16)
+#define IMX6SX_GPR2_MQS_CLK_DIV_SHIFT (16)
+
#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_MASK (0x1 << 3)
#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF1 (0x0 << 3)
#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF2 (0x1 << 3)
@@ -423,6 +452,7 @@
#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_MASK (0x1 << 26)
#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_ENABLE (0x1 << 26)
#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_DISABLE (0x0 << 26)
+#define IMX6SX_GPR5_PCIE_PERST BIT(18)
#define IMX6SX_GPR5_PCIE_BTNRST_RESET BIT(19)
#define IMX6SX_GPR5_CSI1_MUX_CTRL_MASK (0x3 << 4)
#define IMX6SX_GPR5_CSI1_MUX_CTRL_EXT_PIN (0x0 << 4)
@@ -437,10 +467,21 @@
#define IMX6SX_GPR5_DISP_MUX_DCIC1_LVDS (0x1 << 1)
#define IMX6SX_GPR5_DISP_MUX_DCIC1_MASK (0x1 << 1)
+#define IMX6SX_GPR12_PCIE_PM_TURN_OFF BIT(16)
#define IMX6SX_GPR12_PCIE_TEST_POWERDOWN BIT(30)
#define IMX6SX_GPR12_PCIE_RX_EQ_MASK (0x7 << 0)
#define IMX6SX_GPR12_PCIE_RX_EQ_2 (0x2 << 0)
+/* For imx6dl iomux gpr register field definitions */
+#define IMX6DL_GPR3_LVDS1_MUX_CTL_MASK (0x3 << 8)
+#define IMX6DL_GPR3_LVDS1_MUX_CTL_IPU1_DI0 (0x0 << 8)
+#define IMX6DL_GPR3_LVDS1_MUX_CTL_IPU1_DI1 (0x1 << 8)
+#define IMX6DL_GPR3_LVDS1_MUX_CTL_LCDIF (0x2 << 8)
+#define IMX6DL_GPR3_LVDS0_MUX_CTL_MASK (0x3 << 6)
+#define IMX6DL_GPR3_LVDS0_MUX_CTL_IPU1_DI0 (0x0 << 6)
+#define IMX6DL_GPR3_LVDS0_MUX_CTL_IPU1_DI1 (0x1 << 6)
+#define IMX6DL_GPR3_LVDS0_MUX_CTL_LCDIF (0x2 << 6)
+
/* For imx6ul iomux gpr register field define */
#define IMX6UL_GPR1_ENET1_CLK_DIR (0x1 << 17)
#define IMX6UL_GPR1_ENET2_CLK_DIR (0x1 << 18)
diff --git a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h
index 4585d6105d68..e0cbf3cd8f82 100644
--- a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h
@@ -34,6 +34,8 @@
#define IOMUXC_GPR22 0x58
/* For imx7d iomux gpr register field define */
+#define IMX7D_GPR0_ENET_MDIO_OPEN_DRAIN_MASK (0x3 << 7)
+
#define IMX7D_GPR1_IRQ_MASK (0x1 << 12)
#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK (0x1 << 13)
#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK (0x1 << 14)
diff --git a/include/linux/mipi_csi2.h b/include/linux/mipi_csi2.h
new file mode 100644
index 000000000000..7dc76fd293f8
--- /dev/null
+++ b/include/linux/mipi_csi2.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011-2013 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.
+ */
+
+#ifndef __INCLUDE_MIPI_CSI2_H
+#define __INCLUDE_MIPI_CSI2_H
+
+/* MIPI CSI2 registers */
+#define MIPI_CSI2_REG(offset) (offset)
+
+#define MIPI_CSI2_VERSION MIPI_CSI2_REG(0x000)
+#define MIPI_CSI2_N_LANES MIPI_CSI2_REG(0x004)
+#define MIPI_CSI2_PHY_SHUTDOWNZ MIPI_CSI2_REG(0x008)
+#define MIPI_CSI2_DPHY_RSTZ MIPI_CSI2_REG(0x00c)
+#define MIPI_CSI2_CSI2_RESETN MIPI_CSI2_REG(0x010)
+#define MIPI_CSI2_PHY_STATE MIPI_CSI2_REG(0x014)
+#define MIPI_CSI2_DATA_IDS_1 MIPI_CSI2_REG(0x018)
+#define MIPI_CSI2_DATA_IDS_2 MIPI_CSI2_REG(0x01c)
+#define MIPI_CSI2_ERR1 MIPI_CSI2_REG(0x020)
+#define MIPI_CSI2_ERR2 MIPI_CSI2_REG(0x024)
+#define MIPI_CSI2_MASK1 MIPI_CSI2_REG(0x028)
+#define MIPI_CSI2_MASK2 MIPI_CSI2_REG(0x02c)
+#define MIPI_CSI2_PHY_TST_CTRL0 MIPI_CSI2_REG(0x030)
+#define MIPI_CSI2_PHY_TST_CTRL1 MIPI_CSI2_REG(0x034)
+#define MIPI_CSI2_SFT_RESET MIPI_CSI2_REG(0xf00)
+
+/* mipi data type */
+#define MIPI_DT_YUV420 0x18 /* YYY.../UYVY.... */
+#define MIPI_DT_YUV420_LEGACY 0x1a /* UYY.../VYY... */
+#define MIPI_DT_YUV422 0x1e /* UYVY... */
+#define MIPI_DT_RGB444 0x20
+#define MIPI_DT_RGB555 0x21
+#define MIPI_DT_RGB565 0x22
+#define MIPI_DT_RGB666 0x23
+#define MIPI_DT_RGB888 0x24
+#define MIPI_DT_RAW6 0x28
+#define MIPI_DT_RAW7 0x29
+#define MIPI_DT_RAW8 0x2a
+#define MIPI_DT_RAW10 0x2b
+#define MIPI_DT_RAW12 0x2c
+#define MIPI_DT_RAW14 0x2d
+
+
+struct mipi_csi2_info;
+/* mipi csi2 API */
+struct mipi_csi2_info *mipi_csi2_get_info(void);
+
+bool mipi_csi2_enable(struct mipi_csi2_info *info);
+
+bool mipi_csi2_disable(struct mipi_csi2_info *info);
+
+bool mipi_csi2_get_status(struct mipi_csi2_info *info);
+
+int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info,
+ unsigned int datatype);
+
+unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_dphy_status(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_get_error1(struct mipi_csi2_info *info);
+
+unsigned int mipi_csi2_get_error2(struct mipi_csi2_info *info);
+
+int mipi_csi2_pixelclk_enable(struct mipi_csi2_info *info);
+
+void mipi_csi2_pixelclk_disable(struct mipi_csi2_info *info);
+
+int mipi_csi2_reset(struct mipi_csi2_info *info);
+
+#endif
diff --git a/include/linux/mipi_dsi.h b/include/linux/mipi_dsi.h
new file mode 100644
index 000000000000..dbc249a38f68
--- /dev/null
+++ b/include/linux/mipi_dsi.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011-2015 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
+ */
+#ifndef __INCLUDE_MIPI_DSI_H
+#define __INCLUDE_MIPI_DSI_H
+
+#define MIPI_DSI_VERSION (0x000)
+#define MIPI_DSI_PWR_UP (0x004)
+#define MIPI_DSI_CLKMGR_CFG (0x008)
+#define MIPI_DSI_DPI_CFG (0x00c)
+#define MIPI_DSI_DBI_CFG (0x010)
+#define MIPI_DSI_DBIS_CMDSIZE (0x014)
+#define MIPI_DSI_PCKHDL_CFG (0x018)
+#define MIPI_DSI_VID_MODE_CFG (0x01c)
+#define MIPI_DSI_VID_PKT_CFG (0x020)
+#define MIPI_DSI_CMD_MODE_CFG (0x024)
+#define MIPI_DSI_TMR_LINE_CFG (0x028)
+#define MIPI_DSI_VTIMING_CFG (0x02c)
+#define MIPI_DSI_PHY_TMR_CFG (0x030)
+#define MIPI_DSI_GEN_HDR (0x034)
+#define MIPI_DSI_GEN_PLD_DATA (0x038)
+#define MIPI_DSI_CMD_PKT_STATUS (0x03c)
+#define MIPI_DSI_TO_CNT_CFG (0x040)
+#define MIPI_DSI_ERROR_ST0 (0x044)
+#define MIPI_DSI_ERROR_ST1 (0x048)
+#define MIPI_DSI_ERROR_MSK0 (0x04c)
+#define MIPI_DSI_ERROR_MSK1 (0x050)
+#define MIPI_DSI_PHY_RSTZ (0x054)
+#define MIPI_DSI_PHY_IF_CFG (0x058)
+#define MIPI_DSI_PHY_IF_CTRL (0x05c)
+#define MIPI_DSI_PHY_STATUS (0x060)
+#define MIPI_DSI_PHY_TST_CTRL0 (0x064)
+#define MIPI_DSI_PHY_TST_CTRL1 (0x068)
+
+#define DSI_PWRUP_RESET (0x0 << 0)
+#define DSI_PWRUP_POWERUP (0x1 << 0)
+
+#define DSI_DPI_CFG_VID_SHIFT (0)
+#define DSI_DPI_CFG_VID_MASK (0x3)
+#define DSI_DPI_CFG_COLORCODE_SHIFT (2)
+#define DSI_DPI_CFG_COLORCODE_MASK (0x7)
+#define DSI_DPI_CFG_DATAEN_ACT_LOW (0x1 << 5)
+#define DSI_DPI_CFG_DATAEN_ACT_HIGH (0x0 << 5)
+#define DSI_DPI_CFG_VSYNC_ACT_LOW (0x1 << 6)
+#define DSI_DPI_CFG_VSYNC_ACT_HIGH (0x0 << 6)
+#define DSI_DPI_CFG_HSYNC_ACT_LOW (0x1 << 7)
+#define DSI_DPI_CFG_HSYNC_ACT_HIGH (0x0 << 7)
+#define DSI_DPI_CFG_SHUTD_ACT_LOW (0x1 << 8)
+#define DSI_DPI_CFG_SHUTD_ACT_HIGH (0x0 << 8)
+#define DSI_DPI_CFG_COLORMODE_ACT_LOW (0x1 << 9)
+#define DSI_DPI_CFG_COLORMODE_ACT_HIGH (0x0 << 9)
+#define DSI_DPI_CFG_EN18LOOSELY (0x1 << 10)
+
+#define DSI_PCKHDL_CFG_EN_EOTP_TX (0x1 << 0)
+#define DSI_PCKHDL_CFG_EN_EOTP_RX (0x1 << 1)
+#define DSI_PCKHDL_CFG_EN_BTA (0x1 << 2)
+#define DSI_PCKHDL_CFG_EN_ECC_RX (0x1 << 3)
+#define DSI_PCKHDL_CFG_EN_CRC_RX (0x1 << 4)
+#define DSI_PCKHDL_CFG_GEN_VID_RX_MASK (0x3)
+#define DSI_PCKHDL_CFG_GEN_VID_RX_SHIFT (5)
+
+#define DSI_VID_MODE_CFG_EN (0x1 << 0)
+#define DSI_VID_MODE_CFG_EN_BURSTMODE (0x3 << 1)
+#define DSI_VID_MODE_CFG_TYPE_MASK (0x3)
+#define DSI_VID_MODE_CFG_TYPE_SHIFT (1)
+#define DSI_VID_MODE_CFG_EN_LP_VSA (0x1 << 3)
+#define DSI_VID_MODE_CFG_EN_LP_VBP (0x1 << 4)
+#define DSI_VID_MODE_CFG_EN_LP_VFP (0x1 << 5)
+#define DSI_VID_MODE_CFG_EN_LP_VACT (0x1 << 6)
+#define DSI_VID_MODE_CFG_EN_LP_HBP (0x1 << 7)
+#define DSI_VID_MODE_CFG_EN_LP_HFP (0x1 << 8)
+#define DSI_VID_MODE_CFG_EN_MULTI_PKT (0x1 << 9)
+#define DSI_VID_MODE_CFG_EN_NULL_PKT (0x1 << 10)
+#define DSI_VID_MODE_CFG_EN_FRAME_ACK (0x1 << 11)
+#define DSI_VID_MODE_CFG_EN_LP_MODE (DSI_VID_MODE_CFG_EN_LP_VSA | \
+ DSI_VID_MODE_CFG_EN_LP_VBP | \
+ DSI_VID_MODE_CFG_EN_LP_VFP | \
+ DSI_VID_MODE_CFG_EN_LP_HFP | \
+ DSI_VID_MODE_CFG_EN_LP_HBP | \
+ DSI_VID_MODE_CFG_EN_LP_VACT)
+
+
+
+#define DSI_VID_PKT_CFG_VID_PKT_SZ_MASK (0x7ff)
+#define DSI_VID_PKT_CFG_VID_PKT_SZ_SHIFT (0)
+#define DSI_VID_PKT_CFG_NUM_CHUNKS_MASK (0x3ff)
+#define DSI_VID_PKT_CFG_NUM_CHUNKS_SHIFT (11)
+#define DSI_VID_PKT_CFG_NULL_PKT_SZ_MASK (0x3ff)
+#define DSI_VID_PKT_CFG_NULL_PKT_SZ_SHIFT (21)
+
+#define MIPI_DSI_CMD_MODE_CFG_EN_LOWPOWER (0x1FFF)
+#define MIPI_DSI_CMD_MODE_CFG_EN_CMD_MODE (0x1 << 0)
+
+#define DSI_TME_LINE_CFG_HSA_TIME_MASK (0x1ff)
+#define DSI_TME_LINE_CFG_HSA_TIME_SHIFT (0)
+#define DSI_TME_LINE_CFG_HBP_TIME_MASK (0x1ff)
+#define DSI_TME_LINE_CFG_HBP_TIME_SHIFT (9)
+#define DSI_TME_LINE_CFG_HLINE_TIME_MASK (0x3fff)
+#define DSI_TME_LINE_CFG_HLINE_TIME_SHIFT (18)
+
+#define DSI_VTIMING_CFG_VSA_LINES_MASK (0xf)
+#define DSI_VTIMING_CFG_VSA_LINES_SHIFT (0)
+#define DSI_VTIMING_CFG_VBP_LINES_MASK (0x3f)
+#define DSI_VTIMING_CFG_VBP_LINES_SHIFT (4)
+#define DSI_VTIMING_CFG_VFP_LINES_MASK (0x3f)
+#define DSI_VTIMING_CFG_VFP_LINES_SHIFT (10)
+#define DSI_VTIMING_CFG_V_ACT_LINES_MASK (0x7ff)
+#define DSI_VTIMING_CFG_V_ACT_LINES_SHIFT (16)
+
+#define DSI_PHY_TMR_CFG_BTA_TIME_MASK (0xfff)
+#define DSI_PHY_TMR_CFG_BTA_TIME_SHIFT (0)
+#define DSI_PHY_TMR_CFG_LP2HS_TIME_MASK (0xff)
+#define DSI_PHY_TMR_CFG_LP2HS_TIME_SHIFT (12)
+#define DSI_PHY_TMR_CFG_HS2LP_TIME_MASK (0xff)
+#define DSI_PHY_TMR_CFG_HS2LP_TIME_SHIFT (20)
+
+#define DSI_PHY_IF_CFG_N_LANES_MASK (0x3)
+#define DSI_PHY_IF_CFG_N_LANES_SHIFT (0)
+#define DSI_PHY_IF_CFG_WAIT_TIME_MASK (0xff)
+#define DSI_PHY_IF_CFG_WAIT_TIME_SHIFT (2)
+
+#define DSI_PHY_RSTZ_EN_CLK (0x1 << 2)
+#define DSI_PHY_RSTZ_DISABLE_RST (0x1 << 1)
+#define DSI_PHY_RSTZ_DISABLE_SHUTDOWN (0x1 << 0)
+#define DSI_PHY_RSTZ_RST (0x0)
+
+#define DSI_PHY_STATUS_LOCK (0x1 << 0)
+#define DSI_PHY_STATUS_STOPSTATE_CLK_LANE (0x1 << 2)
+
+#define DSI_GEN_HDR_TYPE_MASK (0xff)
+#define DSI_GEN_HDR_TYPE_SHIFT (0)
+#define DSI_GEN_HDR_DATA_MASK (0xffff)
+#define DSI_GEN_HDR_DATA_SHIFT (8)
+
+#define DSI_CMD_PKT_STATUS_GEN_CMD_EMPTY (0x1 << 0)
+#define DSI_CMD_PKT_STATUS_GEN_CMD_FULL (0x1 << 1)
+#define DSI_CMD_PKT_STATUS_GEN_PLD_W_EMPTY (0x1 << 2)
+#define DSI_CMD_PKT_STATUS_GEN_PLD_W_FULL (0x1 << 3)
+#define DSI_CMD_PKT_STATUS_GEN_PLD_R_EMPTY (0x1 << 4)
+#define DSI_CMD_PKT_STATUS_GEN_RD_CMD_BUSY (0x1 << 6)
+
+#define DSI_ERROR_MSK0_ALL_MASK (0x1fffff)
+#define DSI_ERROR_MSK1_ALL_MASK (0x3ffff)
+
+#define DSI_PHY_IF_CTRL_RESET (0x0)
+#define DSI_PHY_IF_CTRL_TX_REQ_CLK_HS (0x1 << 0)
+#define DSI_PHY_IF_CTRL_TX_REQ_CLK_ULPS (0x1 << 1)
+#define DSI_PHY_IF_CTRL_TX_EXIT_CLK_ULPS (0x1 << 2)
+#define DSI_PHY_IF_CTRL_TX_REQ_DATA_ULPS (0x1 << 3)
+#define DSI_PHY_IF_CTRL_TX_EXIT_DATA_ULPS (0x1 << 4)
+#define DSI_PHY_IF_CTRL_TX_TRIG_MASK (0xF)
+#define DSI_PHY_IF_CTRL_TX_TRIG_SHIFT (5)
+
+#define DSI_PHY_CLK_INIT_COMMAND (0x44)
+#define DSI_GEN_PLD_DATA_BUF_SIZE (0x4)
+#endif
diff --git a/include/linux/mipi_dsi_northwest.h b/include/linux/mipi_dsi_northwest.h
new file mode 100644
index 000000000000..21c964ad94df
--- /dev/null
+++ b/include/linux/mipi_dsi_northwest.h
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+#ifndef __INCLUDE_MIPI_DSI_NORTHWEST_H
+#define __INCLUDE_MIPI_DSI_NORTHWEST_H
+
+/* ---------------------------- register offsets --------------------------- */
+
+/* sim */
+#define SIM_SOPT1 0x0
+#define MIPI_ISO_DISABLE 0x8
+
+#define SIM_SOPT1CFG 0x4
+#define DSI_RST_DPI_N 0x80000000
+#define DSI_RST_ESC_N 0x40000000
+#define DSI_RST_BYTE_N 0x20000000
+#define DSI_SD 0x200
+#define DSI_CM 0x100
+#define DSI_PLL_EN 0x80
+
+/* dphy */
+#define DPHY_PD_DPHY 0x300
+#define DPHY_M_PRG_HS_PREPARE 0x304
+#define DPHY_MC_PRG_HS_PREPARE 0x308
+#define DPHY_M_PRG_HS_ZERO 0x30c
+#define DPHY_MC_PRG_HS_ZERO 0x310
+#define DPHY_M_PRG_HS_TRAIL 0x314
+#define DPHY_MC_PRG_HS_TRAIL 0x318
+#define DPHY_PD_PLL 0x31c
+#define DPHY_TST 0x320
+#define DPHY_CN 0x324
+#define DPHY_CM 0x328
+#define DPHY_CO 0x32c
+#define DPHY_LOCK 0x330
+#define DPHY_LOCK_BYP 0x334
+#define DPHY_RTERM_SEL 0x338
+#define DPHY_AUTO_PD_EN 0x33c
+#define DPHY_RXLPRP 0x340
+#define DPHY_RXCDRP 0x344
+
+/* host */
+#define HOST_CFG_NUM_LANES 0x0
+#define HOST_CFG_NONCONTINUOUS_CLK 0x4
+#define HOST_CFG_T_PRE 0x8
+#define HOST_CFG_T_POST 0xc
+#define HOST_CFG_TX_GAP 0x10
+#define HOST_CFG_AUTOINSERT_EOTP 0x14
+#define HOST_CFG_EXTRA_CMDS_AFTER_EOTP 0x18
+#define HOST_CFG_HTX_TO_COUNT 0x1c
+#define HOST_CFG_LRX_H_TO_COUNT 0x20
+#define HOST_CFG_BTA_H_TO_COUNT 0x24
+#define HOST_CFG_TWAKEUP 0x28
+#define HOST_CFG_STATUS_OUT 0x2c
+#define HOST_RX_ERROR_STATUS 0x30
+
+/* dpi */
+#define DPI_PIXEL_PAYLOAD_SIZE 0x200
+#define DPI_PIXEL_FIFO_SEND_LEVEL 0x204
+#define DPI_INTERFACE_COLOR_CODING 0x208
+#define DPI_PIXEL_FORMAT 0x20c
+#define DPI_VSYNC_POLARITY 0x210
+#define DPI_HSYNC_POLARITY 0x214
+#define DPI_VIDEO_MODE 0x218
+#define DPI_HFP 0x21c
+#define DPI_HBP 0x220
+#define DPI_HSA 0x224
+#define DPI_ENABLE_MULT_PKTS 0x228
+#define DPI_VBP 0x22c
+#define DPI_VFP 0x230
+#define DPI_BLLP_MODE 0x234
+#define DPI_USE_NULL_PKT_BLLP 0x238
+#define DPI_VACTIVE 0x23c
+#define DPI_VC 0x240
+
+/* apb pkt */
+#define HOST_TX_PAYLOAD 0x280
+
+#define HOST_PKT_CONTROL 0x284
+#define HOST_PKT_CONTROL_WC(x) (((x) & 0xffff) << 0)
+#define HOST_PKT_CONTROL_VC(x) (((x) & 0x3) << 16)
+#define HOST_PKT_CONTROL_DT(x) (((x) & 0x3f) << 18)
+#define HOST_PKT_CONTROL_HS_SEL(x) (((x) & 0x1) << 24)
+#define HOST_PKT_CONTROL_BTA_TX(x) (((x) & 0x1) << 25)
+#define HOST_PKT_CONTROL_BTA_NO_TX(x) (((x) & 0x1) << 26)
+
+#define HOST_SEND_PACKET 0x288
+#define HOST_PKT_STATUS 0x28c
+#define HOST_PKT_FIFO_WR_LEVEL 0x290
+#define HOST_PKT_FIFO_RD_LEVEL 0x294
+#define HOST_PKT_RX_PAYLOAD 0x298
+
+#define HOST_PKT_RX_PKT_HEADER 0x29c
+#define HOST_PKT_RX_PKT_HEADER_WC(x) (((x) & 0xffff) << 0)
+#define HOST_PKT_RX_PKT_HEADER_DT(x) (((x) & 0x3f) << 16)
+#define HOST_PKT_RX_PKT_HEADER_VC(x) (((x) & 0x3) << 22)
+
+#define HOST_IRQ_STATUS 0x2a0
+#define HOST_IRQ_STATUS_SM_NOT_IDLE (1 << 0)
+#define HOST_IRQ_STATUS_TX_PKT_DONE (1 << 1)
+#define HOST_IRQ_STATUS_DPHY_DIRECTION (1 << 2)
+#define HOST_IRQ_STATUS_TX_FIFO_OVFLW (1 << 3)
+#define HOST_IRQ_STATUS_TX_FIFO_UDFLW (1 << 4)
+#define HOST_IRQ_STATUS_RX_FIFO_OVFLW (1 << 5)
+#define HOST_IRQ_STATUS_RX_FIFO_UDFLW (1 << 6)
+#define HOST_IRQ_STATUS_RX_PKT_HDR_RCVD (1 << 7)
+#define HOST_IRQ_STATUS_RX_PKT_PAYLOAD_DATA_RCVD (1 << 8)
+#define HOST_IRQ_STATUS_HOST_BTA_TIMEOUT (1 << 29)
+#define HOST_IRQ_STATUS_LP_RX_TIMEOUT (1 << 30)
+#define HOST_IRQ_STATUS_HS_TX_TIMEOUT (1 << 31)
+
+#define HOST_IRQ_STATUS2 0x2a4
+#define HOST_IRQ_STATUS2_SINGLE_BIT_ECC_ERR (1 << 0)
+#define HOST_IRQ_STATUS2_MULTI_BIT_ECC_ERR (1 << 1)
+#define HOST_IRQ_STATUS2_CRC_ERR (1 << 2)
+
+#define HOST_IRQ_MASK 0x2a8
+#define HOST_IRQ_MASK_SM_NOT_IDLE_MASK (1 << 0)
+#define HOST_IRQ_MASK_TX_PKT_DONE_MASK (1 << 1)
+#define HOST_IRQ_MASK_DPHY_DIRECTION_MASK (1 << 2)
+#define HOST_IRQ_MASK_TX_FIFO_OVFLW_MASK (1 << 3)
+#define HOST_IRQ_MASK_TX_FIFO_UDFLW_MASK (1 << 4)
+#define HOST_IRQ_MASK_RX_FIFO_OVFLW_MASK (1 << 5)
+#define HOST_IRQ_MASK_RX_FIFO_UDFLW_MASK (1 << 6)
+#define HOST_IRQ_MASK_RX_PKT_HDR_RCVD_MASK (1 << 7)
+#define HOST_IRQ_MASK_RX_PKT_PAYLOAD_DATA_RCVD_MASK (1 << 8)
+#define HOST_IRQ_MASK_HOST_BTA_TIMEOUT_MASK (1 << 29)
+#define HOST_IRQ_MASK_LP_RX_TIMEOUT_MASK (1 << 30)
+#define HOST_IRQ_MASK_HS_TX_TIMEOUT_MASK (1 << 31)
+
+#define HOST_IRQ_MASK2 0x2ac
+#define HOST_IRQ_MASK2_SINGLE_BIT_ECC_ERR_MASK (1 << 0)
+#define HOST_IRQ_MASK2_MULTI_BIT_ECC_ERR_MASK (1 << 1)
+#define HOST_IRQ_MASK2_CRC_ERR_MASK (1 << 2)
+
+/* ------------------------------------- end -------------------------------- */
+
+#endif
diff --git a/include/linux/mipi_dsi_samsung.h b/include/linux/mipi_dsi_samsung.h
new file mode 100644
index 000000000000..e58da9541cfb
--- /dev/null
+++ b/include/linux/mipi_dsi_samsung.h
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+#ifndef __INCLUDE_MIPI_DSI_SAMSUNG_H
+#define __INCLUDE_MIPI_DSI_SAMSUNG_H
+
+#define MIPI_DSI_VERSION (0x000)
+#define MIPI_DSI_STATUS (0x004)
+#define MIPI_DSI_RGB_STATUS (0x008)
+#define MIPI_DSI_SWRST (0x00c)
+#define MIPI_DSI_CLKCTRL (0x010)
+#define MIPI_DSI_TIMEOUT (0x014)
+#define MIPI_DSI_CONFIG (0x018)
+#define MIPI_DSI_ESCMODE (0x01c)
+#define MIPI_DSI_MDRESOL (0x020)
+#define MIPI_DSI_MVPORCH (0x024)
+#define MIPI_DSI_MHPORCH (0x028)
+#define MIPI_DSI_MSYNC (0x02c)
+#define MIPI_DSI_SDRESOL (0x030)
+#define MIPI_DSI_INTSRC (0x034)
+#define MIPI_DSI_INTMSK (0x038)
+#define MIPI_DSI_PKTHDR (0x03c)
+#define MIPI_DSI_PAYLOAD (0x040)
+#define MIPI_DSI_RXFIFO (0x044)
+#define MIPI_DSI_FIFOTHLD (0x048)
+#define MIPI_DSI_FIFOCTRL (0x04c)
+#define MIPI_DSI_MEMACCHR (0x050)
+#define MIPI_DSI_MULTI_PKT (0x078)
+#define MIPI_DSI_PLLCTRL_1G (0x090)
+#define MIPI_DSI_PLLCTRL (0x094)
+#define MIPI_DSI_PLLCTRL1 (0x098)
+#define MIPI_DSI_PLLCTRL2 (0x09c)
+#define MIPI_DSI_PLLTMR (0x0a0)
+#define MIPI_DSI_PHYCTRL_B1 (0x0a4)
+#define MIPI_DSI_PHYCTRL_B2 (0x0a8)
+#define MIPI_DSI_PHYCTRL_M1 (0x0a8)
+#define MIPI_DSI_PHYCTRL_M2 (0x0ac)
+#define MIPI_DSI_PHYTIMING (0x0b4)
+#define MIPI_DSI_PHYTIMING1 (0x0b8)
+#define MIPI_DSI_PHYTIMING2 (0x0bc)
+
+#define MIPI_DSI_SWRST_SWRST (0x1 << 0)
+#define MIPI_DSI_SWRST_FUNCRST (0x1 << 16)
+#define MIPI_DSI_MAIN_HRESOL(x) (((x) & 0x7ff) << 0)
+#define MIPI_DSI_MAIN_VRESOL(x) (((x) & 0x7ff) << 16)
+#define MIPI_DSI_MAIN_STANDBY(x) (((x) & 0x1) << 31)
+#define MIPI_DSI_MAIN_VBP(x) (((x) & 0x7ff) << 0)
+#define MIPI_DSI_STABLE_VFP(x) (((x) & 0x7ff) << 16)
+#define MIPI_DSI_CMDALLOW(x) (((x) & 0xf) << 28)
+#define MIPI_DSI_MAIN_HBP(x) (((x) & 0xffff) << 0)
+#define MIPI_DSI_MAIN_HFP(x) (((x) & 0xffff) << 16)
+#define MIPI_DSI_MAIN_VSA(x) (((x) & 0x3ff) << 22)
+#define MIPI_DSI_MAIN_HSA(x) (((x) & 0xffff) << 0)
+
+#define MIPI_DSI_LANE_EN(x) (((x) & 0x1f) << 0)
+#define MIPI_DSI_NUM_OF_DATALANE(x) (((x) & 0x3) << 5)
+#define MIPI_DSI_SUB_PIX_FORMAT(x) (((x) & 0x7) << 8)
+#define MIPI_DSI_MAIN_PIX_FORMAT(x) (((x) & 0x7) << 12)
+#define MIPI_DSI_SUB_VC(x) (((x) & 0x3) << 16)
+#define MIPI_DSI_MAIN_VC(x) (((x) & 0x3) << 18)
+#define MIPI_DSI_HSA_DISABLE_MODE(x) (((x) & 0x1) << 20)
+#define MIPI_DSI_HBP_DISABLE_MODE(x) (((x) & 0x1) << 21)
+#define MIPI_DSI_HFP_DISABLE_MODE(x) (((x) & 0x1) << 22)
+#define MIPI_DSI_HSE_DISABLE_MODE(x) (((x) & 0x1) << 23)
+#define MIPI_DSI_AUTO_MODE(x) (((x) & 0x1) << 24)
+#define MIPI_DSI_VIDEO_MODE(x) (((x) & 0x1) << 25)
+#define MIPI_DSI_BURST_MODE(x) (((x) & 0x1) << 26)
+#define MIPI_DSI_SYNC_IN_FORM(x) (((x) & 0x1) << 27)
+#define MIPI_DSI_EOT_R03(x) (((x) & 0x1) << 28)
+#define MIPI_DSI_MFLUSH_VS(x) (((x) & 0x1) << 29)
+
+#define MIPI_DSI_DP_DN_SWAP_DATA (0x1 << 24)
+#define MIPI_DSI_PLL_EN(x) (((x) & 0x1) << 23)
+#define MIPI_DSI_PMS(x) (((x) & 0x7ffff) << 1)
+
+#define MIPI_DSI_TX_REQUEST_HSCLK(x) (((x) & 0x1) << 31)
+#define MIPI_DSI_DPHY_SEL(x) (((x) & 0x1) << 29)
+#define MIPI_DSI_ESC_CLK_EN(x) (((x) & 0x1) << 28)
+#define MIPI_DSI_PLL_BYPASS(x) (((x) & 0x1) << 27)
+#define MIPI_DSI_BYTE_CLK_SRC(x) (((x) & 0x3) << 25)
+#define MIPI_DSI_BYTE_CLK_EN(x) (((x) & 0x1) << 24)
+#define MIPI_DSI_LANE_ESC_CLK_EN(x) (((x) & 0x1f) << 19)
+
+#define MIPI_DSI_FORCE_STOP_STATE(x) (((x) & 0x1) << 20)
+
+#define MIPI_DSI_M_TLPXCTL(x) (((x) & 0xff) << 8)
+#define MIPI_DSI_M_THSEXITCTL(x) (((x) & 0xff) << 0)
+
+#define MIPI_DSI_M_TCLKPRPRCTL(x) (((x) & 0xff) << 24)
+#define MIPI_DSI_M_TCLKZEROCTL(x) (((x) & 0xff) << 16)
+#define MIPI_DSI_M_TCLKPOSTCTL(x) (((x) & 0xff) << 8)
+#define MIPI_DSI_M_TCLKTRAILCTL(x) (((x) & 0xff) << 0)
+
+#define MIPI_DSI_M_THSPRPRCTL(x) (((x) & 0xff) << 16)
+#define MIPI_DSI_M_THSZEROCTL(x) (((x) & 0xff) << 8)
+#define MIPI_DSI_M_THSTRAILCTL(x) (((x) & 0xff) << 0)
+
+#define MIPI_DSI_PLL_STABLE(x) (((x) & 0x1) << 31)
+#define MIPI_DSI_TX_READY_HS_CLK(x) (((x) & 0x1) << 10)
+#define MIPI_DSI_ULPS_CLK(x) (((x) & 0x1) << 9)
+#define MIPI_DSI_STOP_STATE_CLK(x) (((x) & 0x1) << 8)
+#define MIPI_DSI_ULPS_DAT(x) (((x) & 0xf) << 4)
+#define MIPI_DSI_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
+
+#define INTSRC_SFR_PL_FIFO_EMPTY (0x1 << 29)
+#define INTSRC_SFR_PH_FIFO_EMPTY (0x1 << 28)
+#define INTSRC_RX_DATA_DONE (0x1 << 18)
+#define INTMSK_SFR_PL_FIFO_EMPTY (0x1 << 29)
+#define INTMSK_SFR_PH_FIFO_EMPTY (0x1 << 28)
+#define INTMSK_RX_DATA_DONE (0x1 << 18)
+
+#define MIPI_DSI_STOP_STATE_CNT(x) (((x) & 0x7ff) << 21)
+#define MIPI_DSI_CMD_LPDT (0x1 << 7)
+#define MIPI_DSI_TX_LPDT (0x1 << 6)
+
+#endif
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 2b953eb8ceae..aa3edb7c5192 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -205,6 +205,9 @@ extern int mmc_flush_cache(struct mmc_card *);
extern int mmc_detect_card_removed(struct mmc_host *host);
+int mmc_first_nonreserved_index(void);
+int mmc_get_reserved_index(struct mmc_host *host);
+
/**
* mmc_claim_host - exclusively claim a host
* @host: mmc host to claim
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 0b2439441cc8..71676e56c8eb 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -312,6 +312,8 @@ struct mmc_host {
#define MMC_CAP2_HS400_ES (1 << 20) /* Host supports enhanced strobe */
#define MMC_CAP2_NO_SD (1 << 21) /* Do not send SD commands during initialization */
#define MMC_CAP2_NO_MMC (1 << 22) /* Do not send (e)MMC commands during initialization */
+#define MMC_CAP2_CD_POST (1 << 23) /* post card rescan, let client driver to start */
+#define MMC_CAP2_DDR52_3_3V (1 << 24) /* Only supprot eMMC DDR52 at 3.3v */
mmc_pm_flag_t pm_caps; /* supported pm features */
diff --git a/include/linux/mmc/pm.h b/include/linux/mmc/pm.h
index 4a139204c20c..6e2d6a135c7e 100644
--- a/include/linux/mmc/pm.h
+++ b/include/linux/mmc/pm.h
@@ -26,5 +26,6 @@ typedef unsigned int mmc_pm_flag_t;
#define MMC_PM_KEEP_POWER (1 << 0) /* preserve card power during suspend */
#define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */
+#define MMC_PM_IGNORE_PM_NOTIFY (1 << 2) /* ignore mmc pm notify */
#endif /* LINUX_MMC_PM_H */
diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h
index 17446d3c3602..bbb9c0010cce 100644
--- a/include/linux/mmc/sdio.h
+++ b/include/linux/mmc/sdio.h
@@ -12,6 +12,8 @@
#ifndef LINUX_MMC_SDIO_H
#define LINUX_MMC_SDIO_H
+#include <linux/mmc/host.h>
+
/* SDIO commands type argument response */
#define SD_IO_SEND_OP_COND 5 /* bcr [23:0] OCR R4 */
#define SD_IO_RW_DIRECT 52 /* ac [31:0] See below R5 */
@@ -190,4 +192,6 @@
#define SDIO_FBR_BLKSIZE 0x10 /* block size (2 bytes) */
+void mmc_sdio_force_remove(struct mmc_host *host);
+
#endif /* LINUX_MMC_SDIO_H */
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index b5b43f94f311..2ae1f8d5fa42 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -446,7 +446,7 @@ static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned
if (map->cached)
memcpy(to, (char *)map->cached + from, len);
else
- memcpy_fromio(to, map->virt + from, len);
+ memcpy(to, map->virt + from, len);
}
static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index c425c7b4c2a0..e73a46013eef 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-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 as published by
@@ -31,10 +31,11 @@
/*
* Note on opcode nomenclature: some opcodes have a format like
- * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
+ * SPINOR_OP_FUNCTION{4,}_x_y_z{_D}. The numbers x, y, and z stand for the number
* of I/O lines used for the opcode, address, and data (respectively). The
* FUNCTION has an optional suffix of '4', to represent an opcode which
- * requires a 4-byte (32-bit) address.
+ * requires a 4-byte (32-bit) address. The suffix of 'D' stands for the
+ * DDR mode.
*/
/* Flash opcodes. */
@@ -45,6 +46,8 @@
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
+#define SPINOR_OP_READ_1_1_4_D 0x6d /* Read data bytes (DDR Quad SPI) */
+#define SPINOR_OP_READ_1_4_4_D 0xed /* Read data bytes (DDR Quad SPI) */
#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
@@ -60,6 +63,7 @@
#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
+#define SPINOR_OP_READ4_1_4_4_D 0xee /* Read data bytes (DDR Quad SPI) */
#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
@@ -78,6 +82,8 @@
/* Used for Micron flashes only. */
#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */
#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */
+#define SPINOR_OP_RD_VCR 0x85 /* Read VCR register */
+#define SPINOR_OP_WR_VCR 0x81 /* Write VCR register */
/* Status Register bits. */
#define SR_WIP BIT(0) /* Write in progress */
@@ -105,6 +111,7 @@ enum read_mode {
SPI_NOR_FAST,
SPI_NOR_DUAL,
SPI_NOR_QUAD,
+ SPI_NOR_DDR_QUAD,
};
#define SPI_NOR_MAX_CMD_SIZE 8
diff --git a/include/linux/mxc_dcic.h b/include/linux/mxc_dcic.h
new file mode 100644
index 000000000000..8e330bd466da
--- /dev/null
+++ b/include/linux/mxc_dcic.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2014-2015 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 linux/mxc_dcic.h
+ *
+ * @brief Global header file for the MXC DCIC driver
+ *
+ * @ingroup MXC DCIC
+ */
+
+#ifndef __LINUX_DCIC_H__
+#define __LINUX_DCIC_H__
+
+#include <uapi/linux/mxc_dcic.h>
+
+#define DCICC_IC_ENABLE 0x1
+#define DCICC_IC_DISABLE 0x0
+#define DCICC_IC_MASK 0x1
+#define DCICC_DE_ACTIVE_HIGH 0
+#define DCICC_DE_ACTIVE_LOW (0x1 << 4)
+#define DCICC_DE_ACTIVE_MASK (0x1 << 4)
+#define DCICC_HSYNC_POL_ACTIVE_HIGH 0
+#define DCICC_HSYNC_POL_ACTIVE_LOW (0x1 << 5)
+#define DCICC_HSYNC_POL_ACTIVE_MASK (0x1 << 5)
+#define DCICC_VSYNC_POL_ACTIVE_HIGH 0
+#define DCICC_VSYNC_POL_ACTIVE_LOW (0x1 << 6)
+#define DCICC_VSYNC_POL_ACTIVE_MASK (0x1 << 6)
+#define DCICC_CLK_POL_NO_INVERTED 0
+#define DCICC_CLK_POL_INVERTED (0x1 << 7)
+#define DCICC_CLK_POL_INVERTED_MASK (0x1 << 7)
+
+#define DCICIC_ERROR_INT_DISABLE 1
+#define DCICIC_ERROR_INT_ENABLE 0
+#define DCICIC_ERROR_INT_MASK_MASK 1
+#define DCICIC_FUN_INT_DISABLE (0x1 << 1)
+#define DCICIC_FUN_INT_ENABLE 0
+#define DCICIC_FUN_INT_MASK (0x1 << 1)
+#define DCICIC_FREEZE_MASK_CHANGED 0
+#define DCICIC_FREEZE_MASK_FORZEN (0x1 << 3)
+#define DCICIC_FREEZE_MASK_MASK (0x1 << 3)
+#define DCICIC_EXT_SIG_EX_DISABLE 0
+#define DCICIC_EXT_SIG_EN_ENABLE (0x1 << 16)
+#define DCICIC_EXT_SIG_EN_MASK (0x1 << 16)
+
+#define DCICS_ROI_MATCH_STAT_MASK 0xFFFF
+#define DCICS_EI_STAT_PENDING (0x1 << 16)
+#define DCICS_EI_STAT_NO_PENDING 0
+#define DCICS_FI_STAT_PENDING (0x1 << 17)
+#define DCICS_FI_STAT_NO_PENDING 0
+
+#define DCICRC_ROI_START_OFFSET_X_MASK 0x1FFF
+#define DCICRC_ROI_START_OFFSET_X_SHIFT 0
+#define DCICRC_ROI_START_OFFSET_Y_MASK (0xFFF << 16)
+#define DCICRC_ROI_START_OFFSET_Y_SHIFT 16
+#define DCICRC_ROI_CHANGED 0
+#define DCICRC_ROI_FROZEN (0x1 << 30)
+#define DCICRC_ROI_ENABLE (0x1 << 31)
+#define DCICRC_ROI_DISABLE 0
+
+#define DCICRS_ROI_END_OFFSET_X_MASK 0x1FFF
+#define DCICRS_ROI_END_OFFSET_X_SHIFT 0
+#define DCICRS_ROI_END_OFFSET_Y_MASK (0xFFF << 16)
+#define DCICRS_ROI_END_OFFSET_Y_SHIFT 16
+
+struct roi_regs {
+ u32 dcicrc;
+ u32 dcicrs;
+ u32 dcicrrs;
+ u32 dcicrcs;
+};
+
+struct dcic_regs {
+ u32 dcicc;
+ u32 dcicic;
+ u32 dcics;
+ u32 dcic_reserved;
+ struct roi_regs ROI[16];
+};
+
+struct dcic_mux {
+ char dcic[16];
+ u32 val;
+};
+
+struct bus_mux {
+ char name[16];
+ int reg;
+ int shift;
+ int mask;
+ int dcic_mux_num;
+ const struct dcic_mux *dcics;
+};
+
+struct dcic_info {
+ int bus_mux_num;
+ const struct bus_mux *buses;
+};
+
+struct dcic_data {
+ struct regmap *regmap;
+ struct device *dev;
+ struct dcic_regs *regs;
+ const struct bus_mux *buses;
+ u32 bus_n;
+ u32 mux_n;
+ struct clk *disp_axi_clk;
+ struct clk *dcic_clk;
+ struct mutex lock;
+ struct completion roi_crc_comp;
+ struct class *class;
+ int major;
+ struct cdev cdev; /* Char device structure */
+ dev_t devt;
+ unsigned int result;
+};
+#endif
diff --git a/include/linux/mxc_mlb.h b/include/linux/mxc_mlb.h
new file mode 100644
index 000000000000..d7c792a2bee4
--- /dev/null
+++ b/include/linux/mxc_mlb.h
@@ -0,0 +1,55 @@
+/*
+ * mxc_mlb.h
+ *
+ * Copyright 2008-2013 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
+ */
+
+#ifndef _MXC_MLB_H
+#define _MXC_MLB_H
+
+/* define IOCTL command */
+#define MLB_DBG_RUNTIME _IO('S', 0x09)
+#define MLB_SET_FPS _IOW('S', 0x10, unsigned int)
+#define MLB_GET_VER _IOR('S', 0x11, unsigned long)
+#define MLB_SET_DEVADDR _IOR('S', 0x12, unsigned char)
+
+/*!
+ * set channel address for each logical channel
+ * the MSB 16bits is for tx channel, the left LSB is for rx channel
+ */
+#define MLB_CHAN_SETADDR _IOW('S', 0x13, unsigned int)
+#define MLB_CHAN_STARTUP _IO('S', 0x14)
+#define MLB_CHAN_SHUTDOWN _IO('S', 0x15)
+#define MLB_CHAN_GETEVENT _IOR('S', 0x16, unsigned long)
+
+#define MLB_SET_ISOC_BLKSIZE_188 _IO('S', 0x17)
+#define MLB_SET_ISOC_BLKSIZE_196 _IO('S', 0x18)
+#define MLB_SET_SYNC_QUAD _IOW('S', 0x19, unsigned int)
+#define MLB_IRQ_ENABLE _IO('S', 0x20)
+#define MLB_IRQ_DISABLE _IO('S', 0x21)
+
+/*!
+ * MLB event define
+ */
+enum {
+ MLB_EVT_TX_PROTO_ERR_CUR = 1 << 0,
+ MLB_EVT_TX_BRK_DETECT_CUR = 1 << 1,
+ MLB_EVT_TX_PROTO_ERR_PREV = 1 << 8,
+ MLB_EVT_TX_BRK_DETECT_PREV = 1 << 9,
+ MLB_EVT_RX_PROTO_ERR_CUR = 1 << 16,
+ MLB_EVT_RX_BRK_DETECT_CUR = 1 << 17,
+ MLB_EVT_RX_PROTO_ERR_PREV = 1 << 24,
+ MLB_EVT_RX_BRK_DETECT_PREV = 1 << 25,
+};
+
+
+#endif /* _MXC_MLB_H */
diff --git a/include/linux/mxc_sim_interface.h b/include/linux/mxc_sim_interface.h
new file mode 100644
index 000000000000..5eae53a59075
--- /dev/null
+++ b/include/linux/mxc_sim_interface.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+#ifndef MXC_SIM_INTERFACE_H
+#define MXC_SIM_INTERFACE_H
+
+#define SIM_ATR_LENGTH_MAX 32
+
+/* Raw ATR SIM_IOCTL_GET_ATR */
+typedef struct {
+ unsigned int size;/* length of ATR received */
+ unsigned char *atr_buffer;/* raw ATR string received */
+ int errval;/* The error vale reported to user space after completing ATR*/
+} sim_atr_t;
+
+/* ISO7816-3 protocols */
+#define SIM_PROTOCOL_T0 1
+#define SIM_PROTOCOL_T1 2
+
+/* Transfer types for SIM_IOCTL_XFER */
+#define SIM_XFER_TYPE_TPDU 1
+#define SIM_XFER_TYPE_PTS 2
+
+typedef struct {
+ unsigned int wwt;
+ unsigned int cwt;
+ unsigned int bwt;
+ unsigned int bgt;
+ unsigned int cgt;
+} sim_timing_t;
+
+/* Transfer data for SIM_IOCTL_XFER */
+typedef struct {
+ unsigned char *xmt_buffer; /* transmit buffer pointer */
+ int xmt_length;/* transmit buffer length */
+ int timeout;/* transfer timeout in milliseconds */
+ int errval;/* The error vale reported to user space after completing transmitting*/
+} sim_xmt_t;
+
+typedef struct {
+ unsigned char *rcv_buffer; /* receive buffer pointer */
+ int rcv_length; /* receive buffer length */
+ int timeout;/* transfer timeout in milliseconds */
+ int errval;/* The error vale reported to user space after receiving*/
+} sim_rcv_t;
+
+typedef struct {
+ unsigned char di;
+ unsigned char fi;
+} sim_baud_t;
+
+/* Interface power states */
+#define SIM_POWER_OFF (0)
+#define SIM_POWER_ON (1)
+
+/* Return values for SIM_IOCTL_GET_PRESENSE */
+#define SIM_PRESENT_REMOVED (0)
+#define SIM_PRESENT_DETECTED (1)
+#define SIM_PRESENT_OPERATIONAL (2)
+
+/* The error value */
+#define SIM_OK (0)
+#define SIM_ERROR_CWT (1 << 0)
+#define SIM_ERROR_BWT (1 << 1)
+#define SIM_ERROR_PARITY (1 << 2)
+#define SIM_ERROR_INVALID_TS (1 << 3)
+#define SIM_ERROR_FRAME (1 << 4)
+#define SIM_ERROR_ATR_TIMEROUT (1 << 5)
+#define SIM_ERROR_NACK_THRESHOLD (1 << 6)
+#define SIM_ERROR_BGT (1 << 7)
+#define SIM_ERROR_ATR_DELAY (1 << 8)
+
+/* Return values for SIM_IOCTL_GET_ERROR */
+#define SIM_E_ACCESS (1)
+#define SIM_E_TPDUSHORT (2)
+#define SIM_E_PTSEMPTY (3)
+#define SIM_E_INVALIDXFERTYPE (4)
+#define SIM_E_INVALIDXMTLENGTH (5)
+#define SIM_E_INVALIDRCVLENGTH (6)
+#define SIM_E_NACK (7)
+#define SIM_E_TIMEOUT (8)
+#define SIM_E_NOCARD (9)
+#define SIM_E_PARAM_FI_INVALID (10)
+#define SIM_E_PARAM_DI_INVALID (11)
+#define SIM_E_PARAM_FBYD_WITHFRACTION (12)
+#define SIM_E_PARAM_FBYD_NOTDIVBY8OR12 (13)
+#define SIM_E_PARAM_DIVISOR_RANGE (14)
+#define SIM_E_MALLOC (15)
+#define SIM_E_IRQ (16)
+#define SIM_E_POWERED_ON (17)
+#define SIM_E_POWERED_OFF (18)
+
+/* ioctl encodings */
+#define SIM_IOCTL_BASE (0xc0)
+#define SIM_IOCTL_GET_PRESENSE _IOR(SIM_IOCTL_BASE, 1, int)
+#define SIM_IOCTL_GET_ATR _IOR(SIM_IOCTL_BASE, 2, sim_atr_t)
+#define SIM_IOCTL_XMT _IOR(SIM_IOCTL_BASE, 3, sim_xmt_t)
+#define SIM_IOCTL_RCV _IOR(SIM_IOCTL_BASE, 4, sim_rcv_t)
+#define SIM_IOCTL_ACTIVATE _IO(SIM_IOCTL_BASE, 5)
+#define SIM_IOCTL_DEACTIVATE _IO(SIM_IOCTL_BASE, 6)
+#define SIM_IOCTL_WARM_RESET _IO(SIM_IOCTL_BASE, 7)
+#define SIM_IOCTL_COLD_RESET _IO(SIM_IOCTL_BASE, 8)
+#define SIM_IOCTL_CARD_LOCK _IO(SIM_IOCTL_BASE, 9)
+#define SIM_IOCTL_CARD_EJECT _IO(SIM_IOCTL_BASE, 10)
+#define SIM_IOCTL_SET_PROTOCOL _IOR(SIM_IOCTL_BASE, 11, unsigned int)
+#define SIM_IOCTL_SET_TIMING _IOR(SIM_IOCTL_BASE, 12, sim_timing_t)
+#define SIM_IOCTL_SET_BAUD _IOR(SIM_IOCTL_BASE, 13, sim_baud_t)
+#define SIM_IOCTL_WAIT _IOR(SIM_IOCTL_BASE, 14, unsigned int)
+
+#endif
diff --git a/include/linux/mxc_v4l2.h b/include/linux/mxc_v4l2.h
new file mode 100644
index 000000000000..6d778e83ef53
--- /dev/null
+++ b/include/linux/mxc_v4l2.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2004-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+/*!
+ * @file linux/mxc_v4l2.h
+ *
+ * @brief MXC V4L2 private header file
+ *
+ * @ingroup MXC V4L2
+ */
+
+#ifndef __LINUX_MXC_V4L2_H__
+#define __LINUX_MXC_V4L2_H__
+
+#include <uapi/linux/mxc_v4l2.h>
+
+#endif
diff --git a/include/linux/mxc_vpu.h b/include/linux/mxc_vpu.h
new file mode 100644
index 000000000000..df024698dee7
--- /dev/null
+++ b/include/linux/mxc_vpu.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2004-2013, 2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+/*!
+ * @defgroup VPU Video Processor Unit Driver
+ */
+
+/*!
+ * @file linux/mxc_vpu.h
+ *
+ * @brief VPU system initialization and file operation definition
+ *
+ * @ingroup VPU
+ */
+
+#ifndef __LINUX_MXC_VPU_H__
+#define __LINUX_MXC_VPU_H__
+
+#include <linux/fs.h>
+
+struct mxc_vpu_platform_data {
+ bool iram_enable;
+ int iram_size;
+ void (*reset) (void);
+ void (*pg) (int);
+};
+
+struct vpu_mem_desc {
+ u32 size;
+ dma_addr_t phy_addr;
+ u32 cpu_addr; /* cpu address to free the dma mem */
+ u32 virt_uaddr; /* virtual user space address */
+};
+
+#define VPU_IOC_MAGIC 'V'
+
+#define VPU_IOC_PHYMEM_ALLOC _IO(VPU_IOC_MAGIC, 0)
+#define VPU_IOC_PHYMEM_FREE _IO(VPU_IOC_MAGIC, 1)
+#define VPU_IOC_WAIT4INT _IO(VPU_IOC_MAGIC, 2)
+#define VPU_IOC_PHYMEM_DUMP _IO(VPU_IOC_MAGIC, 3)
+#define VPU_IOC_REG_DUMP _IO(VPU_IOC_MAGIC, 4)
+#define VPU_IOC_IRAM_SETTING _IO(VPU_IOC_MAGIC, 6)
+#define VPU_IOC_CLKGATE_SETTING _IO(VPU_IOC_MAGIC, 7)
+#define VPU_IOC_GET_WORK_ADDR _IO(VPU_IOC_MAGIC, 8)
+#define VPU_IOC_REQ_VSHARE_MEM _IO(VPU_IOC_MAGIC, 9)
+#define VPU_IOC_SYS_SW_RESET _IO(VPU_IOC_MAGIC, 11)
+#define VPU_IOC_GET_SHARE_MEM _IO(VPU_IOC_MAGIC, 12)
+#define VPU_IOC_QUERY_BITWORK_MEM _IO(VPU_IOC_MAGIC, 13)
+#define VPU_IOC_SET_BITWORK_MEM _IO(VPU_IOC_MAGIC, 14)
+#define VPU_IOC_PHYMEM_CHECK _IO(VPU_IOC_MAGIC, 15)
+#define VPU_IOC_LOCK_DEV _IO(VPU_IOC_MAGIC, 16)
+
+#define BIT_CODE_RUN 0x000
+#define BIT_CODE_DOWN 0x004
+#define BIT_INT_CLEAR 0x00C
+#define BIT_INT_STATUS 0x010
+#define BIT_CUR_PC 0x018
+#define BIT_INT_REASON 0x174
+
+#define MJPEG_PIC_STATUS_REG 0x3004
+#define MBC_SET_SUBBLK_EN 0x4A0
+
+#define BIT_WORK_CTRL_BUF_BASE 0x100
+#define BIT_WORK_CTRL_BUF_REG(i) (BIT_WORK_CTRL_BUF_BASE + i * 4)
+#define BIT_CODE_BUF_ADDR BIT_WORK_CTRL_BUF_REG(0)
+#define BIT_WORK_BUF_ADDR BIT_WORK_CTRL_BUF_REG(1)
+#define BIT_PARA_BUF_ADDR BIT_WORK_CTRL_BUF_REG(2)
+#define BIT_BIT_STREAM_CTRL BIT_WORK_CTRL_BUF_REG(3)
+#define BIT_FRAME_MEM_CTRL BIT_WORK_CTRL_BUF_REG(4)
+#define BIT_BIT_STREAM_PARAM BIT_WORK_CTRL_BUF_REG(5)
+
+#ifndef CONFIG_SOC_IMX6Q
+#define BIT_RESET_CTRL 0x11C
+#else
+#define BIT_RESET_CTRL 0x128
+#endif
+
+/* i could be 0, 1, 2, 3 */
+#define BIT_RD_PTR_BASE 0x120
+#define BIT_RD_PTR_REG(i) (BIT_RD_PTR_BASE + i * 8)
+#define BIT_WR_PTR_REG(i) (BIT_RD_PTR_BASE + i * 8 + 4)
+
+/* i could be 0, 1, 2, 3 */
+#define BIT_FRM_DIS_FLG_BASE (cpu_is_mx51() ? 0x150 : 0x140)
+#define BIT_FRM_DIS_FLG_REG(i) (BIT_FRM_DIS_FLG_BASE + i * 4)
+
+#define BIT_BUSY_FLAG 0x160
+#define BIT_RUN_COMMAND 0x164
+#define BIT_INT_ENABLE 0x170
+
+#define BITVAL_PIC_RUN 8
+
+#define VPU_SLEEP_REG_VALUE 10
+#define VPU_WAKE_REG_VALUE 11
+
+int vl2cc_init(u32 vl2cc_hw_base);
+void vl2cc_enable(void);
+void vl2cc_flush(void);
+void vl2cc_disable(void);
+void vl2cc_cleanup(void);
+
+int vl2cc_init(u32 vl2cc_hw_base);
+void vl2cc_enable(void);
+void vl2cc_flush(void);
+void vl2cc_disable(void);
+void vl2cc_cleanup(void);
+
+#endif
diff --git a/include/linux/mxcfb.h b/include/linux/mxcfb.h
new file mode 100644
index 000000000000..67db5ee3fd11
--- /dev/null
+++ b/include/linux/mxcfb.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+/*
+ * @file linux/mxcfb.h
+ *
+ * @brief Global header file for the MXC Frame buffer
+ *
+ * @ingroup Framebuffer
+ */
+#ifndef __LINUX_MXCFB_H__
+#define __LINUX_MXCFB_H__
+
+#include <uapi/linux/mxcfb.h>
+
+extern struct fb_videomode mxcfb_modedb[];
+extern int mxcfb_modedb_sz;
+
+enum {
+ MXC_DISP_SPEC_DEV = 0,
+ MXC_DISP_DDC_DEV = 1,
+};
+
+enum {
+ MXCFB_REFRESH_OFF,
+ MXCFB_REFRESH_AUTO,
+ MXCFB_REFRESH_PARTIAL,
+};
+
+int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode,
+ struct mxcfb_rect *update_region);
+int mxc_elcdif_frame_addr_setup(dma_addr_t phys);
+void mxcfb_elcdif_register_mode(const struct fb_videomode *modedb,
+ int num_modes, int dev_mode);
+
+#endif
diff --git a/include/linux/mxcfb_epdc.h b/include/linux/mxcfb_epdc.h
new file mode 100644
index 000000000000..35a8b83b22d3
--- /dev/null
+++ b/include/linux/mxcfb_epdc.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010-2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _MXCFB_EPDC_KERNEL
+#define _MXCFB_EPDC_KERNEL
+
+struct imx_epdc_fb_mode {
+ struct fb_videomode *vmode;
+ int vscan_holdoff;
+ int sdoed_width;
+ int sdoed_delay;
+ int sdoez_width;
+ int sdoez_delay;
+ int gdclk_hp_offs;
+ int gdsp_offs;
+ int gdoe_offs;
+ int gdclk_offs;
+ int num_ce;
+};
+
+struct imx_epdc_fb_platform_data {
+ struct imx_epdc_fb_mode *epdc_mode;
+ int num_modes;
+ int (*get_pins) (void);
+ void (*put_pins) (void);
+ void (*enable_pins) (void);
+ void (*disable_pins) (void);
+};
+
+#endif
diff --git a/include/linux/of.h b/include/linux/of.h
index 299aeb192727..fc12b433c54f 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -365,6 +365,7 @@ extern int of_phandle_iterator_args(struct of_phandle_iterator *it,
extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
extern int of_alias_get_id(struct device_node *np, const char *stem);
extern int of_alias_get_highest_id(const char *stem);
+extern int of_alias_max_index(const char *stem);
extern int of_machine_is_compatible(const char *compat);
@@ -783,6 +784,11 @@ static inline int of_alias_get_highest_id(const char *stem)
return -ENOSYS;
}
+static inline int of_alias_max_index(const char *stem)
+{
+ return -ENODEV;
+}
+
static inline int of_machine_is_compatible(const char *compat)
{
return 0;
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
index f8e1992d6423..4cd75fcf6c78 100644
--- a/include/linux/of_reserved_mem.h
+++ b/include/linux/of_reserved_mem.h
@@ -34,13 +34,13 @@ int of_reserved_mem_device_init_by_idx(struct device *dev,
struct device_node *np, int idx);
void of_reserved_mem_device_release(struct device *dev);
-int early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
+int early_init_dt_alloc_reserved_memory_arch(unsigned long node,
+ phys_addr_t size,
phys_addr_t align,
phys_addr_t start,
phys_addr_t end,
bool nomap,
phys_addr_t *res_base);
-
void fdt_init_reserved_mem(void);
void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
phys_addr_t base, phys_addr_t size);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 867110c9d707..cc374eb47c26 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -833,6 +833,7 @@ void phy_print_status(struct phy_device *phydev);
void phy_device_free(struct phy_device *phydev);
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed);
+int phy_scan_fixups(struct phy_device *phydev);
int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *));
int phy_register_fixup_for_id(const char *bus_id,
diff --git a/include/linux/platform_data/dma-imx-sdma.h b/include/linux/platform_data/dma-imx-sdma.h
index 2d08816720f6..5bb0a119f39a 100644
--- a/include/linux/platform_data/dma-imx-sdma.h
+++ b/include/linux/platform_data/dma-imx-sdma.h
@@ -50,7 +50,10 @@ struct sdma_script_start_addrs {
/* End of v2 array */
s32 zcanfd_2_mcu_addr;
s32 zqspi_2_mcu_addr;
+ s32 mcu_2_ecspi_addr;
/* End of v3 array */
+ s32 mcu_2_zqspi_addr;
+ /* End of v4 array */
};
/**
diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h
index 7d964e787299..bee13cf86387 100644
--- a/include/linux/platform_data/dma-imx.h
+++ b/include/linux/platform_data/dma-imx.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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
@@ -42,6 +42,7 @@ enum sdma_peripheral_type {
IMX_DMATYPE_SSI_DUAL, /* SSI Dual FIFO */
IMX_DMATYPE_ASRC_SP, /* Shared ASRC */
IMX_DMATYPE_SAI, /* SAI */
+ IMX_DMATYPE_HDMI, /* HDMI Audio */
};
enum imx_dma_prio {
@@ -55,6 +56,8 @@ struct imx_dma_data {
int dma_request2; /* secondary DMA request line */
enum sdma_peripheral_type peripheral_type;
int priority;
+ bool src_dualfifo;
+ bool dst_dualfifo;
};
static inline int imx_dma_is_ipu(struct dma_chan *chan)
@@ -62,6 +65,11 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
return !strcmp(dev_name(chan->device->dev), "ipu-core");
}
+static inline int imx_dma_is_pxp(struct dma_chan *chan)
+{
+ return strstr(dev_name(chan->device->dev), "pxp") != NULL;
+}
+
static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
{
return !strcmp(chan->device->dev->driver->name, "imx-sdma") ||
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index a09fe5c009c8..cf987dc35081 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -207,6 +207,8 @@ extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
int genpd_dev_pm_attach(struct device *dev);
+struct generic_pm_domain *genpd_get_from_provider(
+ struct of_phandle_args *genpdspec);
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
static inline int of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
@@ -244,6 +246,13 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
{
return ERR_PTR(-ENOTSUPP);
}
+
+static inline
+struct generic_pm_domain *genpd_get_from_provider(
+ struct of_phandle_args *genpdspec)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
#ifdef CONFIG_PM
diff --git a/include/linux/pmic_status.h b/include/linux/pmic_status.h
new file mode 100644
index 000000000000..a127c7117e13
--- /dev/null
+++ b/include/linux/pmic_status.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2004-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+#ifndef __ASM_ARCH_MXC_PMIC_STATUS_H__
+#define __ASM_ARCH_MXC_PMIC_STATUS_H__
+#include <asm-generic/errno-base.h>
+#ifdef __KERNEL__
+#include <asm/uaccess.h> /* copy_{from,to}_user() */
+#endif
+/*!
+ * @file arch-mxc/pmic_status.h
+ * @brief PMIC APIs return code definition.
+ *
+ * @ingroup PMIC_CORE
+ */
+
+/*!
+ * @enum PMIC_STATUS
+ * @brief Define return values for all PMIC APIs.
+ *
+ * These return values are used by all of the PMIC APIs.
+ *
+ * @ingroup PMIC
+ */
+typedef enum {
+ PMIC_SUCCESS = 0, /*!< The requested operation was successfully
+ completed. */
+ PMIC_ERROR = -1, /*!< The requested operation could not be completed
+ due to an error. */
+ PMIC_PARAMETER_ERROR = -2, /*!< The requested operation failed because
+ one or more of the parameters was
+ invalid. */
+ PMIC_NOT_SUPPORTED = -3, /*!< The requested operation could not be
+ completed because the PMIC hardware
+ does not support it. */
+ PMIC_SYSTEM_ERROR_EINTR = -EINTR,
+
+ PMIC_MALLOC_ERROR = -5, /*!< Error in malloc function */
+ PMIC_UNSUBSCRIBE_ERROR = -6, /*!< Error in un-subscribe event */
+ PMIC_EVENT_NOT_SUBSCRIBED = -7, /*!< Event occur and not subscribed */
+ PMIC_EVENT_CALL_BACK = -8, /*!< Error - bad call back */
+ PMIC_CLIENT_NBOVERFLOW = -9, /*!< The requested operation could not be
+ completed because there are too many
+ PMIC client requests */
+} PMIC_STATUS;
+
+/*
+ * Bitfield macros that use rely on bitfield width/shift information.
+ */
+#define BITFMASK(field) (((1U << (field ## _WID)) - 1) << (field ## _LSH))
+#define BITFVAL(field, val) ((val) << (field ## _LSH))
+#define BITFEXT(var, bit) ((var & BITFMASK(bit)) >> (bit ## _LSH))
+
+/*
+ * Macros implementing error handling
+ */
+#define CHECK_ERROR(a) \
+do { \
+ int ret = (a); \
+ if (ret != PMIC_SUCCESS) \
+ return ret; \
+} while (0)
+
+#define CHECK_ERROR_KFREE(func, freeptrs) \
+do { \
+ int ret = (func); \
+ if (ret != PMIC_SUCCESS) { \
+ freeptrs; \
+ return ret; \
+ } \
+} while (0);
+
+#endif /* __ASM_ARCH_MXC_PMIC_STATUS_H__ */
diff --git a/include/linux/power/sabresd_battery.h b/include/linux/power/sabresd_battery.h
new file mode 100644
index 000000000000..10bfa4588864
--- /dev/null
+++ b/include/linux/power/sabresd_battery.h
@@ -0,0 +1,65 @@
+/*
+ * sabresd_battery.h - Maxim 8903 USB/Adapter Charger Driver
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc.
+ * Based on max8903_charger.h
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __MAX8903_SABRESD_H__
+#define __MAX8903_SABRESD_H__
+
+struct max8903_pdata {
+ /*
+ * GPIOs
+ * cen, chg, flt, and usus are optional.
+ * dok, dcm, and uok are not optional depending on the status of
+ * dc_valid and usb_valid.
+ */
+ int cen; /* Charger Enable input */
+ int dok; /* DC(Adapter) Power OK output */
+ int uok; /* USB Power OK output */
+ int chg; /* Charger status output */
+ int flt; /* Fault output */
+ int dcm; /* Current-Limit Mode input (1: DC, 2: USB) */
+ int usus; /* USB Suspend Input (1: suspended) */
+ int feature_flag;/* battery capacity feature(0:enable, 1:disable) */
+
+ /*
+ * DCM wired to Logic High Set this true when DCM pin connect to
+ * Logic high.
+ */
+ bool dcm_always_high;
+
+ /*
+ * DC(Adapter/TA) is wired
+ * When dc_valid is true,
+ * dok and dcm should be valid.
+ *
+ * At least one of dc_valid or usb_valid should be true.
+ */
+ bool dc_valid;
+ /*
+ * USB is wired
+ * When usb_valid is true,
+ * uok should be valid.
+ */
+ bool usb_valid;
+};
+
+#endif /* __SABRESD_BATTERY_H__ */
diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h
index efdd9227a49c..3619c9a260b6 100644
--- a/include/linux/pwm_backlight.h
+++ b/include/linux/pwm_backlight.h
@@ -20,6 +20,7 @@ struct platform_pwm_backlight_data {
void (*notify_after)(struct device *dev, int brightness);
void (*exit)(struct device *dev);
int (*check_fb)(struct device *dev, struct fb_info *info);
+ char fb_id[16];
};
#endif
diff --git a/include/linux/pxp_device.h b/include/linux/pxp_device.h
new file mode 100644
index 000000000000..df185c49d017
--- /dev/null
+++ b/include/linux/pxp_device.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _PXP_DEVICE
+#define _PXP_DEVICE
+
+#include <linux/idr.h>
+#include <linux/hash.h>
+#include <uapi/linux/pxp_device.h>
+
+struct pxp_irq_info {
+ wait_queue_head_t waitq;
+ atomic_t irq_pending;
+ int hist_status;
+};
+
+struct pxp_buffer_hash {
+ struct hlist_head *hash_table;
+ u32 order;
+ spinlock_t hash_lock;
+};
+
+struct pxp_buf_obj {
+ uint32_t handle;
+
+ uint32_t size;
+ uint32_t mem_type;
+
+ unsigned long offset;
+ void *virtual;
+
+ struct hlist_node item;
+};
+
+struct pxp_chan_obj {
+ uint32_t handle;
+ struct dma_chan *chan;
+};
+
+/* File private data */
+struct pxp_file {
+ struct file *filp;
+
+ /* record allocated dma buffer */
+ struct idr buffer_idr;
+ spinlock_t buffer_lock;
+
+ /* record allocated dma channel */
+ struct idr channel_idr;
+ spinlock_t channel_lock;
+};
+
+#endif
diff --git a/include/linux/pxp_dma.h b/include/linux/pxp_dma.h
new file mode 100644
index 000000000000..a48871caebfc
--- /dev/null
+++ b/include/linux/pxp_dma.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010-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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _PXP_DMA
+#define _PXP_DMA
+
+#include <uapi/linux/pxp_dma.h>
+
+struct pxp_tx_desc {
+ struct dma_async_tx_descriptor txd;
+ struct list_head tx_list;
+ struct list_head list;
+ int len;
+ union {
+ struct pxp_layer_param s0_param;
+ struct pxp_layer_param out_param;
+ struct pxp_layer_param ol_param;
+ struct pxp_layer_param processing_param;
+ } layer_param;
+ struct pxp_proc_data proc_data;
+
+ u32 hist_status; /* Histogram output status */
+
+ struct pxp_tx_desc *next;
+};
+
+struct pxp_channel {
+ struct dma_chan dma_chan;
+ dma_cookie_t completed; /* last completed cookie */
+ enum pxp_channel_status status;
+ void *client; /* Only one client per channel */
+ unsigned int n_tx_desc;
+ struct pxp_tx_desc *desc; /* allocated tx-descriptors */
+ struct list_head active_list; /* active tx-descriptors */
+ struct list_head free_list; /* free tx-descriptors */
+ struct list_head queue; /* queued tx-descriptors */
+ struct list_head list; /* track queued channel number */
+ spinlock_t lock; /* protects sg[0,1], queue */
+ struct mutex chan_mutex; /* protects status, cookie, free_list */
+ int active_buffer;
+ unsigned int eof_irq;
+ char eof_name[16]; /* EOF IRQ name for request_irq() */
+};
+
+#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
+#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
+
+void pxp_txd_ack(struct dma_async_tx_descriptor *txd,
+ struct pxp_channel *pxp_chan);
+
+#ifdef CONFIG_MXC_PXP_CLIENT_DEVICE
+int register_pxp_device(void);
+void unregister_pxp_device(void);
+#else
+static int register_pxp_device(void) { return 0; }
+static void unregister_pxp_device(void) {}
+#endif
+void pxp_fill(
+ u32 bpp,
+ u32 value,
+ u32 width,
+ u32 height,
+ u32 output_buffer,
+ u32 output_pitch);
+
+void m4_process(void);
+#endif
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 692108222271..ce63a80679d1 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -119,6 +119,9 @@ struct regmap;
#define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200
#define REGULATOR_EVENT_PRE_DISABLE 0x400
#define REGULATOR_EVENT_ABORT_DISABLE 0x800
+#define REGULATOR_EVENT_PRE_DO_ENABLE 0x1000
+#define REGULATOR_EVENT_PRE_DO_DISABLE 0x2000
+#define REGULATOR_EVENT_AFT_DO_ENABLE 0x4000
/**
* struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event
diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h
index 48918be649d4..ba4ac009d832 100644
--- a/include/linux/regulator/fixed.h
+++ b/include/linux/regulator/fixed.h
@@ -51,6 +51,7 @@ struct fixed_voltage_config {
int microvolts;
int gpio;
unsigned startup_delay;
+ unsigned off_on_delay;
unsigned gpio_is_open_drain:1;
unsigned enable_high:1;
unsigned enabled_at_boot:1;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index eba1f10e8cfd..7a1d2d96449f 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -361,6 +361,7 @@ struct usb_bus {
* Does the host controller use PIO
* for control transfers?
*/
+ struct otg_fsm *otg_fsm; /* usb otg finite state machine */
u8 otg_port; /* 0, or number of OTG/HNP port */
unsigned is_b_host:1; /* true during some HNP roleswitches */
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index f9be467d6695..c25e448f5ce3 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -12,7 +12,7 @@ struct ci_hdrc;
/**
* struct ci_hdrc_cable - structure for external connector cable state tracking
- * @state: current state of the line
+ * @connected: true if cable is connected, false otherwise
* @changed: set to true when extcon event happen
* @enabled: set to true if we've enabled the vbus or id interrupt
* @edev: device which generate events
@@ -21,7 +21,7 @@ struct ci_hdrc;
* @conn: used for notification registration
*/
struct ci_hdrc_cable {
- bool state;
+ bool connected;
bool changed;
bool enabled;
struct extcon_dev *edev;
@@ -57,10 +57,21 @@ struct ci_hdrc_platform_data {
#define CI_HDRC_OVERRIDE_AHB_BURST BIT(9)
#define CI_HDRC_OVERRIDE_TX_BURST BIT(10)
#define CI_HDRC_OVERRIDE_RX_BURST BIT(11)
+#define CI_HDRC_IMX_EHCI_QUIRK BIT(12)
+#define CI_HDRC_IMX_IS_HSIC BIT(13)
+/* need request pmqos during low power */
+#define CI_HDRC_PMQOS BIT(14)
enum usb_dr_mode dr_mode;
#define CI_HDRC_CONTROLLER_RESET_EVENT 0
#define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
- void (*notify_event) (struct ci_hdrc *ci, unsigned event);
+#define CI_HDRC_CONTROLLER_VBUS_EVENT 2
+#define CI_HDRC_NOTIFY_RET_DEFER_EVENT 3
+#define CI_HDRC_CONTROLLER_CHARGER_POST_EVENT 4
+#define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 5
+#define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 6
+#define CI_HDRC_IMX_TERM_SELECT_OVERRIDE_FS 7
+#define CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF 8
+ int (*notify_event)(struct ci_hdrc *ci, unsigned event);
struct regulator *reg_vbus;
struct usb_otg_caps ci_otg_caps;
bool tpl_support;
@@ -86,4 +97,6 @@ struct platform_device *ci_hdrc_add_device(struct device *dev,
/* Remove ci hdrc device */
void ci_hdrc_remove_device(struct platform_device *pdev);
+/* Get current available role */
+enum usb_dr_mode ci_hdrc_query_available_role(struct platform_device *pdev);
#endif
diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h
index 7a0350535cb1..229d3649d858 100644
--- a/include/linux/usb/otg-fsm.h
+++ b/include/linux/usb/otg-fsm.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007,2008 Freescale Semiconductor, Inc.
+/* Copyright (C) 2007-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 as published by the
@@ -68,6 +68,10 @@ enum otg_fsm_timer {
A_WAIT_ENUM,
B_DATA_PLS,
B_SSEND_SRP,
+ A_DP_END,
+ A_TST_MAINT,
+ B_SRP_REQD,
+ B_TST_SUSP,
NUM_OTG_FSM_TIMERS,
};
@@ -185,6 +189,13 @@ struct otg_fsm {
int b_srp_done;
int b_hnp_enable;
int a_clr_err;
+ int hnp_polling;
+
+ /* OTG test device */
+ int tst_maint;
+ int otg_vbus_off;
+ int otg_srp_reqd;
+ int otg_hnp_reqd;
/* Informative variables. All unused as of now */
int a_bus_drop_inf;
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index 31a8068c42a5..cfc463c30b1f 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -60,6 +60,13 @@ enum usb_otg_state {
OTG_STATE_A_VBUS_ERR,
};
+/* The usb role of phy to be working with */
+enum usb_current_mode {
+ USB_MODE_NONE,
+ USB_MODE_HOST,
+ USB_MODE_DEVICE,
+};
+
struct usb_phy;
struct usb_otg;
@@ -122,6 +129,14 @@ struct usb_phy {
enum usb_device_speed speed);
int (*notify_disconnect)(struct usb_phy *x,
enum usb_device_speed speed);
+ int (*notify_suspend)(struct usb_phy *x,
+ enum usb_device_speed speed);
+ int (*notify_resume)(struct usb_phy *x,
+ enum usb_device_speed speed);
+
+ int (*set_mode)(struct usb_phy *x,
+ enum usb_current_mode mode);
+
};
/**
@@ -196,6 +211,15 @@ usb_phy_vbus_off(struct usb_phy *x)
return x->set_vbus(x, false);
}
+static inline int
+usb_phy_set_mode(struct usb_phy *x, enum usb_current_mode mode)
+{
+ if (!x || !x->set_mode)
+ return 0;
+
+ return x->set_mode(x, mode);
+}
+
/* for usb host and peripheral controller drivers */
#if IS_ENABLED(CONFIG_USB_PHY)
extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
@@ -310,6 +334,24 @@ usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
return 0;
}
+static inline int usb_phy_notify_suspend
+ (struct usb_phy *x, enum usb_device_speed speed)
+{
+ if (x && x->notify_suspend)
+ return x->notify_suspend(x, speed);
+ else
+ return 0;
+}
+
+static inline int usb_phy_notify_resume
+ (struct usb_phy *x, enum usb_device_speed speed)
+{
+ if (x && x->notify_resume)
+ return x->notify_resume(x, speed);
+ else
+ return 0;
+}
+
/* notifiers */
static inline int
usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h
new file mode 100644
index 000000000000..f4a698a22880
--- /dev/null
+++ b/include/linux/wakelock.h
@@ -0,0 +1,67 @@
+/* include/linux/wakelock.h
+ *
+ * Copyright (C) 2007-2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_WAKELOCK_H
+#define _LINUX_WAKELOCK_H
+
+#include <linux/ktime.h>
+#include <linux/device.h>
+
+/* A wake_lock prevents the system from entering suspend or other low power
+ * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock
+ * prevents a full system suspend.
+ */
+
+enum {
+ WAKE_LOCK_SUSPEND, /* Prevent suspend */
+ WAKE_LOCK_TYPE_COUNT
+};
+
+struct wake_lock {
+ struct wakeup_source ws;
+};
+
+static inline void wake_lock_init(struct wake_lock *lock, int type,
+ const char *name)
+{
+ wakeup_source_init(&lock->ws, name);
+}
+
+static inline void wake_lock_destroy(struct wake_lock *lock)
+{
+ wakeup_source_trash(&lock->ws);
+}
+
+static inline void wake_lock(struct wake_lock *lock)
+{
+ __pm_stay_awake(&lock->ws);
+}
+
+static inline void wake_lock_timeout(struct wake_lock *lock, long timeout)
+{
+ __pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout));
+}
+
+static inline void wake_unlock(struct wake_lock *lock)
+{
+ __pm_relax(&lock->ws);
+}
+
+static inline int wake_lock_active(struct wake_lock *lock)
+{
+ return lock->ws.active;
+}
+
+#endif
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
new file mode 100644
index 000000000000..b4c8416c3d1f
--- /dev/null
+++ b/include/media/v4l2-chip-ident.h
@@ -0,0 +1,355 @@
+/*
+ v4l2 chip identifiers header
+
+ This header provides a list of chip identifiers that can be returned
+ through the VIDIOC_DBG_G_CHIP_IDENT ioctl.
+
+ Copyright (C) 2011-2014 Freescale Semiconductor, Inc.
+ Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef V4L2_CHIP_IDENT_H_
+#define V4L2_CHIP_IDENT_H_
+
+/* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */
+
+/* KEEP THIS LIST ORDERED BY ID!
+ Otherwise it will be hard to see which ranges are already in use when
+ adding support to a new chip family. */
+enum {
+ /* general idents: reserved range 0-49 */
+ V4L2_IDENT_NONE = 0, /* No chip matched */
+ V4L2_IDENT_AMBIGUOUS = 1, /* Match too general, multiple chips matched */
+ V4L2_IDENT_UNKNOWN = 2, /* Chip found, but cannot identify */
+
+ /* module tvaudio: reserved range 50-99 */
+ V4L2_IDENT_TVAUDIO = 50, /* A tvaudio chip, unknown which it is exactly */
+
+ /* Sony IMX074 */
+ V4L2_IDENT_IMX074 = 74,
+
+ /* module saa7110: just ident 100 */
+ V4L2_IDENT_SAA7110 = 100,
+
+ /* module saa7115: reserved range 101-149 */
+ V4L2_IDENT_SAA7111 = 101,
+ V4L2_IDENT_SAA7111A = 102,
+ V4L2_IDENT_SAA7113 = 103,
+ V4L2_IDENT_SAA7114 = 104,
+ V4L2_IDENT_SAA7115 = 105,
+ V4L2_IDENT_SAA7118 = 108,
+
+ V4L2_IDENT_GM7113C = 140,
+
+ /* module saa7127: reserved range 150-199 */
+ V4L2_IDENT_SAA7127 = 157,
+ V4L2_IDENT_SAA7129 = 159,
+
+ /* module cx25840: reserved range 200-249 */
+ V4L2_IDENT_CX25836 = 236,
+ V4L2_IDENT_CX25837 = 237,
+ V4L2_IDENT_CX25840 = 240,
+ V4L2_IDENT_CX25841 = 241,
+ V4L2_IDENT_CX25842 = 242,
+ V4L2_IDENT_CX25843 = 243,
+
+ /* OmniVision sensors: reserved range 250-299 */
+ V4L2_IDENT_OV7670 = 250,
+ V4L2_IDENT_OV7720 = 251,
+ V4L2_IDENT_OV7725 = 252,
+ V4L2_IDENT_OV7660 = 253,
+ V4L2_IDENT_OV9650 = 254,
+ V4L2_IDENT_OV9655 = 255,
+ V4L2_IDENT_SOI968 = 256,
+ V4L2_IDENT_OV9640 = 257,
+ V4L2_IDENT_OV6650 = 258,
+ V4L2_IDENT_OV2640 = 259,
+ V4L2_IDENT_OV9740 = 260,
+ V4L2_IDENT_OV5642 = 261,
+
+ /* module saa7146: reserved range 300-309 */
+ V4L2_IDENT_SAA7146 = 300,
+
+ /* Conexant MPEG encoder/decoders: reserved range 400-420 */
+ V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */
+ V4L2_IDENT_CX23415 = 415,
+ V4L2_IDENT_CX23416 = 416,
+ V4L2_IDENT_CX23417 = 417,
+ V4L2_IDENT_CX23418 = 418,
+
+ /* module bt819: reserved range 810-819 */
+ V4L2_IDENT_BT815A = 815,
+ V4L2_IDENT_BT817A = 817,
+ V4L2_IDENT_BT819A = 819,
+
+ /* module au0828 */
+ V4L2_IDENT_AU0828 = 828,
+
+ /* module bttv: ident 848 + 849 */
+ V4L2_IDENT_BT848 = 848,
+ V4L2_IDENT_BT849 = 849,
+
+ /* module bt856: just ident 856 */
+ V4L2_IDENT_BT856 = 856,
+
+ /* module bt866: just ident 866 */
+ V4L2_IDENT_BT866 = 866,
+
+ /* module bttv: ident 878 + 879 */
+ V4L2_IDENT_BT878 = 878,
+ V4L2_IDENT_BT879 = 879,
+
+ /* module ks0127: reserved range 1120-1129 */
+ V4L2_IDENT_KS0122S = 1122,
+ V4L2_IDENT_KS0127 = 1127,
+ V4L2_IDENT_KS0127B = 1128,
+
+ /* module indycam: just ident 2000 */
+ V4L2_IDENT_INDYCAM = 2000,
+
+ /* module vp27smpx: just ident 2700 */
+ V4L2_IDENT_VP27SMPX = 2700,
+
+ /* module vpx3220: reserved range: 3210-3229 */
+ V4L2_IDENT_VPX3214C = 3214,
+ V4L2_IDENT_VPX3216B = 3216,
+ V4L2_IDENT_VPX3220A = 3220,
+
+ /* VX855 just ident 3409 */
+ /* Other via devs could use 3314, 3324, 3327, 3336, 3364, 3353 */
+ V4L2_IDENT_VIA_VX855 = 3409,
+
+ /* module tvp5150 */
+ V4L2_IDENT_TVP5150 = 5150,
+
+ /* module saa5246a: just ident 5246 */
+ V4L2_IDENT_SAA5246A = 5246,
+
+ /* module saa5249: just ident 5249 */
+ V4L2_IDENT_SAA5249 = 5249,
+
+ /* module cs5345: just ident 5345 */
+ V4L2_IDENT_CS5345 = 5345,
+
+ /* module tea6415c: just ident 6415 */
+ V4L2_IDENT_TEA6415C = 6415,
+
+ /* module tea6420: just ident 6420 */
+ V4L2_IDENT_TEA6420 = 6420,
+
+ /* module saa6588: just ident 6588 */
+ V4L2_IDENT_SAA6588 = 6588,
+
+ /* module vs6624: just ident 6624 */
+ V4L2_IDENT_VS6624 = 6624,
+
+ /* module saa6752hs: reserved range 6750-6759 */
+ V4L2_IDENT_SAA6752HS = 6752,
+ V4L2_IDENT_SAA6752HS_AC3 = 6753,
+
+ /* modules tef6862: just ident 6862 */
+ V4L2_IDENT_TEF6862 = 6862,
+
+ /* module tvp7002: just ident 7002 */
+ V4L2_IDENT_TVP7002 = 7002,
+
+ /* module adv7170: just ident 7170 */
+ V4L2_IDENT_ADV7170 = 7170,
+
+ /* module adv7175: just ident 7175 */
+ V4L2_IDENT_ADV7175 = 7175,
+
+ /* module adv7180: just ident 7180 */
+ V4L2_IDENT_ADV7180 = 7180,
+
+ /* module adv7183: just ident 7183 */
+ V4L2_IDENT_ADV7183 = 7183,
+
+ /* module saa7185: just ident 7185 */
+ V4L2_IDENT_SAA7185 = 7185,
+
+ /* module saa7191: just ident 7191 */
+ V4L2_IDENT_SAA7191 = 7191,
+
+ /* module ths7303: just ident 7303 */
+ V4L2_IDENT_THS7303 = 7303,
+
+ /* module adv7343: just ident 7343 */
+ V4L2_IDENT_ADV7343 = 7343,
+
+ /* module ths7353: just ident 7353 */
+ V4L2_IDENT_THS7353 = 7353,
+
+ /* module adv7393: just ident 7393 */
+ V4L2_IDENT_ADV7393 = 7393,
+
+ /* module adv7604: just ident 7604 */
+ V4L2_IDENT_ADV7604 = 7604,
+
+ /* module saa7706h: just ident 7706 */
+ V4L2_IDENT_SAA7706H = 7706,
+
+ /* module mt9v011, just ident 8243 */
+ V4L2_IDENT_MT9V011 = 8243,
+
+ /* module wm8739: just ident 8739 */
+ V4L2_IDENT_WM8739 = 8739,
+
+ /* module wm8775: just ident 8775 */
+ V4L2_IDENT_WM8775 = 8775,
+
+ /* Marvell controllers starting at 8801 */
+ V4L2_IDENT_CAFE = 8801,
+ V4L2_IDENT_ARMADA610 = 8802,
+
+ /* AKM AK8813/AK8814 */
+ V4L2_IDENT_AK8813 = 8813,
+ V4L2_IDENT_AK8814 = 8814,
+
+ /* module cx23885 and cx25840 */
+ V4L2_IDENT_CX23885 = 8850,
+ V4L2_IDENT_CX23885_AV = 8851, /* Integrated A/V decoder */
+ V4L2_IDENT_CX23887 = 8870,
+ V4L2_IDENT_CX23887_AV = 8871, /* Integrated A/V decoder */
+ V4L2_IDENT_CX23888 = 8880,
+ V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */
+ V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */
+
+ /* module ad9389b: just ident 9389 */
+ V4L2_IDENT_AD9389B = 9389,
+
+ /* module tda9840: just ident 9840 */
+ V4L2_IDENT_TDA9840 = 9840,
+
+ /* module tw9910: just ident 9910 */
+ V4L2_IDENT_TW9910 = 9910,
+
+ /* module sn9c20x: just ident 10000 */
+ V4L2_IDENT_SN9C20X = 10000,
+
+ /* module cx231xx and cx25840 */
+ V4L2_IDENT_CX2310X_AV = 23099, /* Integrated A/V decoder; not in '100 */
+ V4L2_IDENT_CX23100 = 23100,
+ V4L2_IDENT_CX23101 = 23101,
+ V4L2_IDENT_CX23102 = 23102,
+
+ /* module msp3400: reserved range 34000-34999 for msp34xx */
+ V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only
+ use internally (tveeprom.c). */
+
+ V4L2_IDENT_MSP3400B = 34002,
+ V4L2_IDENT_MSP3400C = 34003,
+ V4L2_IDENT_MSP3400D = 34004,
+ V4L2_IDENT_MSP3400G = 34007,
+ V4L2_IDENT_MSP3401G = 34017,
+ V4L2_IDENT_MSP3402G = 34027,
+ V4L2_IDENT_MSP3405D = 34054,
+ V4L2_IDENT_MSP3405G = 34057,
+ V4L2_IDENT_MSP3407D = 34074,
+ V4L2_IDENT_MSP3407G = 34077,
+
+ V4L2_IDENT_MSP3410B = 34102,
+ V4L2_IDENT_MSP3410C = 34103,
+ V4L2_IDENT_MSP3410D = 34104,
+ V4L2_IDENT_MSP3410G = 34107,
+ V4L2_IDENT_MSP3411G = 34117,
+ V4L2_IDENT_MSP3412G = 34127,
+ V4L2_IDENT_MSP3415D = 34154,
+ V4L2_IDENT_MSP3415G = 34157,
+ V4L2_IDENT_MSP3417D = 34174,
+ V4L2_IDENT_MSP3417G = 34177,
+
+ V4L2_IDENT_MSP3420G = 34207,
+ V4L2_IDENT_MSP3421G = 34217,
+ V4L2_IDENT_MSP3422G = 34227,
+ V4L2_IDENT_MSP3425G = 34257,
+ V4L2_IDENT_MSP3427G = 34277,
+
+ V4L2_IDENT_MSP3430G = 34307,
+ V4L2_IDENT_MSP3431G = 34317,
+ V4L2_IDENT_MSP3435G = 34357,
+ V4L2_IDENT_MSP3437G = 34377,
+
+ V4L2_IDENT_MSP3440G = 34407,
+ V4L2_IDENT_MSP3441G = 34417,
+ V4L2_IDENT_MSP3442G = 34427,
+ V4L2_IDENT_MSP3445G = 34457,
+ V4L2_IDENT_MSP3447G = 34477,
+
+ V4L2_IDENT_MSP3450G = 34507,
+ V4L2_IDENT_MSP3451G = 34517,
+ V4L2_IDENT_MSP3452G = 34527,
+ V4L2_IDENT_MSP3455G = 34557,
+ V4L2_IDENT_MSP3457G = 34577,
+
+ V4L2_IDENT_MSP3460G = 34607,
+ V4L2_IDENT_MSP3461G = 34617,
+ V4L2_IDENT_MSP3465G = 34657,
+ V4L2_IDENT_MSP3467G = 34677,
+
+ /* module msp3400: reserved range 44000-44999 for msp44xx */
+ V4L2_IDENT_MSP4400G = 44007,
+ V4L2_IDENT_MSP4408G = 44087,
+ V4L2_IDENT_MSP4410G = 44107,
+ V4L2_IDENT_MSP4418G = 44187,
+ V4L2_IDENT_MSP4420G = 44207,
+ V4L2_IDENT_MSP4428G = 44287,
+ V4L2_IDENT_MSP4440G = 44407,
+ V4L2_IDENT_MSP4448G = 44487,
+ V4L2_IDENT_MSP4450G = 44507,
+ V4L2_IDENT_MSP4458G = 44587,
+
+ /* Micron CMOS sensor chips: 45000-45099 */
+ V4L2_IDENT_MT9M001C12ST = 45000,
+ V4L2_IDENT_MT9M001C12STM = 45005,
+ V4L2_IDENT_MT9M111 = 45007,
+ V4L2_IDENT_MT9M112 = 45008,
+ V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */
+ V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */
+ V4L2_IDENT_MT9T031 = 45020,
+ V4L2_IDENT_MT9T111 = 45021,
+ V4L2_IDENT_MT9T112 = 45022,
+ V4L2_IDENT_MT9V111 = 45031,
+ V4L2_IDENT_MT9V112 = 45032,
+
+ /* HV7131R CMOS sensor: just ident 46000 */
+ V4L2_IDENT_HV7131R = 46000,
+
+ /* Sharp RJ54N1CB0C, 0xCB0C = 51980 */
+ V4L2_IDENT_RJ54N1CB0C = 51980,
+
+ /* module m52790: just ident 52790 */
+ V4L2_IDENT_M52790 = 52790,
+
+ /* module cs53132a: just ident 53132 */
+ V4L2_IDENT_CS53l32A = 53132,
+
+ /* modules upd61151 MPEG2 encoder: just ident 54000 */
+ V4L2_IDENT_UPD61161 = 54000,
+ /* modules upd61152 MPEG2 encoder with AC3: just ident 54001 */
+ V4L2_IDENT_UPD61162 = 54001,
+
+ /* module upd64031a: just ident 64031 */
+ V4L2_IDENT_UPD64031A = 64031,
+
+ /* module upd64083: just ident 64083 */
+ V4L2_IDENT_UPD64083 = 64083,
+
+ /* Don't just add new IDs at the end: KEEP THIS LIST ORDERED BY ID! */
+};
+
+#endif
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index e657614521e3..252bd3dae53f 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -152,6 +152,7 @@ struct v4l2_file_operations {
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
+ long (*ioctl) (struct file *, unsigned int, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
#ifdef CONFIG_COMPAT
long (*compat_ioctl32) (struct file *, unsigned int, unsigned long);
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index 8ffa94009d1a..bb97f64e91c8 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -69,6 +69,8 @@ struct v4l2_device {
unsigned int notification, void *arg);
struct v4l2_ctrl_handler *ctrl_handler;
struct v4l2_prio_state prio;
+ /* BKL replacement mutex. Temporary solution only. */
+ struct mutex ioctl_lock;
struct kref ref;
void (*release)(struct v4l2_device *v4l2_dev);
};
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 574ff2ae94be..9ee69a5c568f 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -536,6 +536,8 @@ struct v4l2_ioctl_ops {
int (*vidioc_g_chip_info)(struct file *file, void *fh,
struct v4l2_dbg_chip_info *chip);
#endif
+ int (*vidioc_g_chip_ident) (struct file *file, void *fh,
+ struct v4l2_dbg_chip_ident *chip);
int (*vidioc_enum_framesizes)(struct file *file, void *fh,
struct v4l2_frmsizeenum *fsize);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index cf778c5dca18..79f6761e4e37 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -97,6 +97,7 @@ struct v4l2_decode_vbi_line {
/*
* Core ops: it is highly recommended to implement at least these ops:
*
+ * g_chip_ident
* log_status
* g_register
* s_register
@@ -186,6 +187,7 @@ struct v4l2_subdev_io_pin_config {
* @unsubscribe_event: remove event subscription from the control framework.
*/
struct v4l2_subdev_core_ops {
+ int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);
int (*log_status)(struct v4l2_subdev *sd);
int (*s_io_pin_config)(struct v4l2_subdev *sd, size_t n,
struct v4l2_subdev_io_pin_config *pincfg);
diff --git a/include/soc/imx/gpc.h b/include/soc/imx/gpc.h
new file mode 100644
index 000000000000..6a976e6aa3fe
--- /dev/null
+++ b/include/soc/imx/gpc.h
@@ -0,0 +1,7 @@
+#ifndef __SOC_IMX_GPC_H
+#define __SOC_IMX_GPC_H
+
+void imx_gpc_hold_m4_in_sleep(void);
+void imx_gpc_release_m4_in_sleep(void);
+
+#endif /* __SOC_IMX_GPC_H */
diff --git a/include/soc/imx/src.h b/include/soc/imx/src.h
new file mode 100644
index 000000000000..c55c34cd2366
--- /dev/null
+++ b/include/soc/imx/src.h
@@ -0,0 +1,6 @@
+#ifndef __SOC_IMX_SRC_H
+#define __SOC_IMX_SRC_H
+
+bool imx_src_is_m4_enabled(void);
+
+#endif /* __SOC_IMX_SRC_H */
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index 67be2445941a..57eadbe0b4ef 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -74,6 +74,8 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
* @chan_name: Custom channel name to use when requesting DMA channel.
* @fifo_size: FIFO size of the DAI controller in bytes
* @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
+ * @check_xrun: check if hardware xrun happen in the cpu dai.
+ * @device_reset: if xrun happened, then do cpu dai reset.
*/
struct snd_dmaengine_dai_dma_data {
dma_addr_t addr;
@@ -84,6 +86,16 @@ struct snd_dmaengine_dai_dma_data {
const char *chan_name;
unsigned int fifo_size;
unsigned int flags;
+ bool (*check_xrun)(struct snd_pcm_substream *substream);
+ void (*device_reset)(struct snd_pcm_substream *substream, bool stop);
+};
+
+struct dmaengine_pcm_runtime_data {
+ struct dma_chan *dma_chan;
+ dma_cookie_t cookie;
+
+ unsigned int pos;
+ dma_async_tx_callback callback;
};
void snd_dmaengine_pcm_set_config_from_dai_data(
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 4f1c784e44f6..7551854f2d16 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1052,6 +1052,7 @@ struct snd_soc_dai_link {
/* DPCM used FE & BE merged format */
unsigned int dpcm_merged_format:1;
+ unsigned int dpcm_merged_chan:1;
/* pmdown_time is ignored at stop */
unsigned int ignore_pmdown_time:1;
diff --git a/include/trace/events/cpufreq_interactive.h b/include/trace/events/cpufreq_interactive.h
new file mode 100644
index 000000000000..faecc0bfdeff
--- /dev/null
+++ b/include/trace/events/cpufreq_interactive.h
@@ -0,0 +1,112 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cpufreq_interactive
+
+#if !defined(_TRACE_CPUFREQ_INTERACTIVE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_CPUFREQ_INTERACTIVE_H
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(set,
+ TP_PROTO(u32 cpu_id, unsigned long targfreq,
+ unsigned long actualfreq),
+ TP_ARGS(cpu_id, targfreq, actualfreq),
+
+ TP_STRUCT__entry(
+ __field(u32, cpu_id)
+ __field(unsigned long, targfreq)
+ __field(unsigned long, actualfreq)
+ ),
+
+ TP_fast_assign(
+ __entry->cpu_id = (u32)cpu_id;
+ __entry->targfreq = targfreq;
+ __entry->actualfreq = actualfreq;
+ ),
+
+ TP_printk("cpu=%u targ=%lu actual=%lu",
+ __entry->cpu_id, __entry->targfreq,
+ __entry->actualfreq)
+);
+
+DEFINE_EVENT(set, cpufreq_interactive_setspeed,
+ TP_PROTO(u32 cpu_id, unsigned long targfreq,
+ unsigned long actualfreq),
+ TP_ARGS(cpu_id, targfreq, actualfreq)
+);
+
+DECLARE_EVENT_CLASS(loadeval,
+ TP_PROTO(unsigned long cpu_id, unsigned long load,
+ unsigned long curtarg, unsigned long curactual,
+ unsigned long newtarg),
+ TP_ARGS(cpu_id, load, curtarg, curactual, newtarg),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, cpu_id)
+ __field(unsigned long, load)
+ __field(unsigned long, curtarg)
+ __field(unsigned long, curactual)
+ __field(unsigned long, newtarg)
+ ),
+
+ TP_fast_assign(
+ __entry->cpu_id = cpu_id;
+ __entry->load = load;
+ __entry->curtarg = curtarg;
+ __entry->curactual = curactual;
+ __entry->newtarg = newtarg;
+ ),
+
+ TP_printk("cpu=%lu load=%lu cur=%lu actual=%lu targ=%lu",
+ __entry->cpu_id, __entry->load, __entry->curtarg,
+ __entry->curactual, __entry->newtarg)
+);
+
+DEFINE_EVENT(loadeval, cpufreq_interactive_target,
+ TP_PROTO(unsigned long cpu_id, unsigned long load,
+ unsigned long curtarg, unsigned long curactual,
+ unsigned long newtarg),
+ TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
+);
+
+DEFINE_EVENT(loadeval, cpufreq_interactive_already,
+ TP_PROTO(unsigned long cpu_id, unsigned long load,
+ unsigned long curtarg, unsigned long curactual,
+ unsigned long newtarg),
+ TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
+);
+
+DEFINE_EVENT(loadeval, cpufreq_interactive_notyet,
+ TP_PROTO(unsigned long cpu_id, unsigned long load,
+ unsigned long curtarg, unsigned long curactual,
+ unsigned long newtarg),
+ TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
+);
+
+TRACE_EVENT(cpufreq_interactive_boost,
+ TP_PROTO(const char *s),
+ TP_ARGS(s),
+ TP_STRUCT__entry(
+ __string(s, s)
+ ),
+ TP_fast_assign(
+ __assign_str(s, s);
+ ),
+ TP_printk("%s", __get_str(s))
+);
+
+TRACE_EVENT(cpufreq_interactive_unboost,
+ TP_PROTO(const char *s),
+ TP_ARGS(s),
+ TP_STRUCT__entry(
+ __string(s, s)
+ ),
+ TP_fast_assign(
+ __assign_str(s, s);
+ ),
+ TP_printk("%s", __get_str(s))
+);
+
+#endif /* _TRACE_CPUFREQ_INTERACTIVE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index cd2be1c8e9fb..12274d7237d4 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -245,6 +245,8 @@ header-y += kvm_para.h
endif
header-y += hw_breakpoint.h
+header-y += ipu.h
+header-y += isl29023.h
header-y += l2tp.h
header-y += libc-compat.h
header-y += lirc.h
@@ -278,7 +280,13 @@ header-y += mroute6.h
header-y += mroute.h
header-y += msdos_fs.h
header-y += msg.h
+header-y += mxcfb.h
+header-y += mxc_dcic.h
+header-y += mxc_mlb.h
+header-y += mxc_sim_interface.h
+header-y += mxc_v4l2.h
header-y += mtio.h
+header-y += mxc_asrc.h
header-y += nbd.h
header-y += ncp_fs.h
header-y += ncp.h
@@ -349,6 +357,8 @@ header-y += prctl.h
header-y += psci.h
header-y += ptp_clock.h
header-y += ptrace.h
+header-y += pxp_dma.h
+header-y += pxp_device.h
header-y += qnx4_fs.h
header-y += qnxtypes.h
header-y += quota.h
diff --git a/include/uapi/linux/ipu.h b/include/uapi/linux/ipu.h
new file mode 100644
index 000000000000..c92f292bcc9d
--- /dev/null
+++ b/include/uapi/linux/ipu.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2013-2015 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
+ */
+
+/*!
+ * @defgroup IPU MXC Image Processing Unit (IPU) Driver
+ */
+/*!
+ * @file uapi/linux/ipu.h
+ *
+ * @brief This file contains the IPU driver API declarations.
+ *
+ * @ingroup IPU
+ */
+
+#ifndef __ASM_ARCH_IPU_H__
+#define __ASM_ARCH_IPU_H__
+
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#ifndef __KERNEL__
+#ifndef __cplusplus
+typedef unsigned char bool;
+#endif
+#define irqreturn_t int
+#define dma_addr_t int
+#define uint32_t unsigned int
+#define uint16_t unsigned short
+#define uint8_t unsigned char
+#define u32 unsigned int
+#define u8 unsigned char
+#define __u32 u32
+#endif
+
+/*!
+ * Enumeration of IPU rotation modes
+ */
+typedef enum {
+ /* Note the enum values correspond to BAM value */
+ IPU_ROTATE_NONE = 0,
+ IPU_ROTATE_VERT_FLIP = 1,
+ IPU_ROTATE_HORIZ_FLIP = 2,
+ IPU_ROTATE_180 = 3,
+ IPU_ROTATE_90_RIGHT = 4,
+ IPU_ROTATE_90_RIGHT_VFLIP = 5,
+ IPU_ROTATE_90_RIGHT_HFLIP = 6,
+ IPU_ROTATE_90_LEFT = 7,
+} ipu_rotate_mode_t;
+
+/*!
+ * Enumeration of VDI MOTION select
+ */
+typedef enum {
+ MED_MOTION = 0,
+ LOW_MOTION = 1,
+ HIGH_MOTION = 2,
+} ipu_motion_sel;
+
+/*!
+ * Enumeration of DI ports for ADC.
+ */
+typedef enum {
+ DISP0,
+ DISP1,
+ DISP2,
+ DISP3
+} display_port_t;
+
+/* IPU Pixel format definitions */
+/* Four-character-code (FOURCC) */
+#define fourcc(a, b, c, d)\
+ (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
+
+/*!
+ * @name IPU Pixel Formats
+ *
+ * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
+ * the same used by V4L2 API.
+ */
+
+/*! @{ */
+/*! @name GPU Tile Formats */
+/*! @{ */
+#define IPU_PIX_FMT_GPU32_SB_ST fourcc('5', 'P', '4', 'S') /*!< 32bit split buf 4x4 standard */
+#define IPU_PIX_FMT_GPU32_SB_SRT fourcc('5', 'P', '4', 'R') /*!< 32bit split buf 4x4 super */
+#define IPU_PIX_FMT_GPU32_ST fourcc('5', 'I', '4', 'S') /*!< 32bit single buf 4x4 standard */
+#define IPU_PIX_FMT_GPU32_SRT fourcc('5', 'I', '4', 'R') /*!< 32bit single buf 4x4 super */
+#define IPU_PIX_FMT_GPU16_SB_ST fourcc('4', 'P', '8', 'S') /*!< 16bit split buf 8x4 standard */
+#define IPU_PIX_FMT_GPU16_SB_SRT fourcc('4', 'P', '8', 'R') /*!< 16bit split buf 8x4 super */
+#define IPU_PIX_FMT_GPU16_ST fourcc('4', 'I', '8', 'S') /*!< 16bit single buf 8x4 standard */
+#define IPU_PIX_FMT_GPU16_SRT fourcc('4', 'I', '8', 'R') /*!< 16bit single buf 8x4 super */
+
+/*! @{ */
+/*! @name Generic or Raw Data Formats */
+/*! @{ */
+#define IPU_PIX_FMT_GENERIC fourcc('I', 'P', 'U', '0') /*!< IPU Generic Data */
+#define IPU_PIX_FMT_GENERIC_32 fourcc('I', 'P', 'U', '1') /*!< IPU Generic Data */
+#define IPU_PIX_FMT_GENERIC_16 fourcc('I', 'P', 'U', '2') /*!< IPU Generic Data */
+#define IPU_PIX_FMT_LVDS666 fourcc('L', 'V', 'D', '6') /*!< IPU Generic Data */
+#define IPU_PIX_FMT_LVDS888 fourcc('L', 'V', 'D', '8') /*!< IPU Generic Data */
+/*! @} */
+/*! @name RGB Formats */
+/*! @{ */
+#define IPU_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*!< 8 RGB-3-3-2 */
+#define IPU_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*!< 16 RGB-5-5-5 */
+#define IPU_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*!< 1 6 RGB-5-6-5 */
+#define IPU_PIX_FMT_BGRA4444 fourcc('4', '4', '4', '4') /*!< 16 RGBA-4-4-4-4 */
+#define IPU_PIX_FMT_BGRA5551 fourcc('5', '5', '5', '1') /*!< 16 RGBA-5-5-5-1 */
+#define IPU_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*!< 18 RGB-6-6-6 */
+#define IPU_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*!< 18 BGR-6-6-6 */
+#define IPU_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*!< 24 BGR-8-8-8 */
+#define IPU_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*!< 24 RGB-8-8-8 */
+#define IPU_PIX_FMT_GBR24 fourcc('G', 'B', 'R', '3') /*!< 24 GBR-8-8-8 */
+#define IPU_PIX_FMT_BGR32 fourcc('B', 'G', 'R', '4') /*!< 32 BGR-8-8-8-8 */
+#define IPU_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*!< 32 BGR-8-8-8-8 */
+#define IPU_PIX_FMT_RGB32 fourcc('R', 'G', 'B', '4') /*!< 32 RGB-8-8-8-8 */
+#define IPU_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*!< 32 RGB-8-8-8-8 */
+#define IPU_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*!< 32 ABGR-8-8-8-8 */
+/*! @} */
+/*! @name YUV Interleaved Formats */
+/*! @{ */
+#define IPU_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*!< 16 YUV 4:2:2 */
+#define IPU_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*!< 16 YUV 4:2:2 */
+#define IPU_PIX_FMT_YVYU fourcc('Y', 'V', 'Y', 'U') /*!< 16 YVYU 4:2:2 */
+#define IPU_PIX_FMT_VYUY fourcc('V', 'Y', 'U', 'Y') /*!< 16 VYYU 4:2:2 */
+#define IPU_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*!< 12 YUV 4:1:1 */
+#define IPU_PIX_FMT_YUV444 fourcc('Y', '4', '4', '4') /*!< 24 YUV 4:4:4 */
+#define IPU_PIX_FMT_VYU444 fourcc('V', '4', '4', '4') /*!< 24 VYU 4:4:4 */
+#define IPU_PIX_FMT_AYUV fourcc('A', 'Y', 'U', 'V') /*!< 32 AYUV 4:4:4:4 */
+/* two planes -- one Y, one Cb + Cr interleaved */
+#define IPU_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
+#define PRE_PIX_FMT_NV21 fourcc('N', 'V', '2', '1') /* 12 Y/CbCr 4:2:0 */
+#define IPU_PIX_FMT_NV16 fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */
+#define PRE_PIX_FMT_NV61 fourcc('N', 'V', '6', '1') /* 16 Y/CbCr 4:2:2 */
+/* two planes -- 12 tiled Y/CbCr 4:2:0 */
+#define IPU_PIX_FMT_TILED_NV12 fourcc('T', 'N', 'V', 'P')
+#define IPU_PIX_FMT_TILED_NV12F fourcc('T', 'N', 'V', 'F')
+
+/*! @} */
+/*! @name YUV Planar Formats */
+/*! @{ */
+#define IPU_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*!< 8 Greyscale */
+#define IPU_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*!< 9 YVU 4:1:0 */
+#define IPU_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*!< 9 YUV 4:1:0 */
+#define IPU_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*!< 12 YVU 4:2:0 */
+#define IPU_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*!< 12 YUV 4:2:0 */
+#define IPU_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*!< 12 YUV 4:2:0 */
+#define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*!< 16 YVU 4:2:2 */
+#define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*!< 16 YUV 4:2:2 */
+/* non-interleaved 4:4:4 */
+#define IPU_PIX_FMT_YUV444P fourcc('4', '4', '4', 'P') /*!< 24 YUV 4:4:4 */
+/*! @} */
+#define IPU_PIX_FMT_TILED_NV12_MBALIGN (16)
+#define TILED_NV12_FRAME_SIZE(w, h) \
+ (ALIGN((w) * (h), SZ_4K) + ALIGN((w) * (h) / 2, SZ_4K))
+/* IPU device */
+typedef enum {
+ RGB_CS,
+ YUV_CS,
+ NULL_CS
+} cs_t;
+
+struct ipu_pos {
+ u32 x;
+ u32 y;
+};
+
+struct ipu_crop {
+ struct ipu_pos pos;
+ u32 w;
+ u32 h;
+};
+
+struct ipu_deinterlace {
+ bool enable;
+ u8 motion; /*see ipu_motion_sel*/
+#define IPU_DEINTERLACE_FIELD_TOP 0
+#define IPU_DEINTERLACE_FIELD_BOTTOM 1
+#define IPU_DEINTERLACE_FIELD_MASK \
+ (IPU_DEINTERLACE_FIELD_TOP | IPU_DEINTERLACE_FIELD_BOTTOM)
+ /* deinterlace frame rate double flags */
+#define IPU_DEINTERLACE_RATE_EN 0x80
+#define IPU_DEINTERLACE_RATE_FRAME1 0x40
+#define IPU_DEINTERLACE_RATE_MASK \
+ (IPU_DEINTERLACE_RATE_EN | IPU_DEINTERLACE_RATE_FRAME1)
+#define IPU_DEINTERLACE_MAX_FRAME 2
+ u8 field_fmt;
+};
+
+struct ipu_input {
+ u32 width;
+ u32 height;
+ u32 format;
+ struct ipu_crop crop;
+ dma_addr_t paddr;
+
+ struct ipu_deinterlace deinterlace;
+ dma_addr_t paddr_n; /*valid when deinterlace enable*/
+};
+
+struct ipu_alpha {
+#define IPU_ALPHA_MODE_GLOBAL 0
+#define IPU_ALPHA_MODE_LOCAL 1
+ u8 mode;
+ u8 gvalue; /* 0~255 */
+ dma_addr_t loc_alp_paddr;
+};
+
+struct ipu_colorkey {
+ bool enable;
+ u32 value; /* RGB 24bit */
+};
+
+struct ipu_overlay {
+ u32 width;
+ u32 height;
+ u32 format;
+ struct ipu_crop crop;
+ struct ipu_alpha alpha;
+ struct ipu_colorkey colorkey;
+ dma_addr_t paddr;
+};
+
+struct ipu_output {
+ u32 width;
+ u32 height;
+ u32 format;
+ u8 rotate;
+ struct ipu_crop crop;
+ dma_addr_t paddr;
+};
+
+struct ipu_task {
+ struct ipu_input input;
+ struct ipu_output output;
+
+ bool overlay_en;
+ struct ipu_overlay overlay;
+
+#define IPU_TASK_PRIORITY_NORMAL 0
+#define IPU_TASK_PRIORITY_HIGH 1
+ u8 priority;
+
+#define IPU_TASK_ID_ANY 0
+#define IPU_TASK_ID_VF 1
+#define IPU_TASK_ID_PP 2
+#define IPU_TASK_ID_MAX 3
+ u8 task_id;
+
+ int timeout;
+};
+
+enum {
+ IPU_CHECK_OK = 0,
+ IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN = 0x1,
+ IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN = 0x2,
+ IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN = 0x4,
+ IPU_CHECK_ERR_MIN,
+ IPU_CHECK_ERR_INPUT_CROP,
+ IPU_CHECK_ERR_OUTPUT_CROP,
+ IPU_CHECK_ERR_OVERLAY_CROP,
+ IPU_CHECK_ERR_INPUT_OVER_LIMIT,
+ IPU_CHECK_ERR_OV_OUT_NO_FIT,
+ IPU_CHECK_ERR_OVERLAY_WITH_VDI,
+ IPU_CHECK_ERR_PROC_NO_NEED,
+ IPU_CHECK_ERR_SPLIT_INPUTW_OVER,
+ IPU_CHECK_ERR_SPLIT_INPUTH_OVER,
+ IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER,
+ IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER,
+ IPU_CHECK_ERR_SPLIT_WITH_ROT,
+ IPU_CHECK_ERR_NOT_SUPPORT,
+ IPU_CHECK_ERR_NOT16ALIGN,
+ IPU_CHECK_ERR_W_DOWNSIZE_OVER,
+ IPU_CHECK_ERR_H_DOWNSIZE_OVER,
+};
+
+/* IOCTL commands */
+#define IPU_CHECK_TASK _IOWR('I', 0x1, struct ipu_task)
+#define IPU_QUEUE_TASK _IOW('I', 0x2, struct ipu_task)
+#define IPU_ALLOC _IOWR('I', 0x3, int)
+#define IPU_FREE _IOW('I', 0x4, int)
+
+#endif
diff --git a/include/uapi/linux/isl29023.h b/include/uapi/linux/isl29023.h
new file mode 100644
index 000000000000..9fddf4282573
--- /dev/null
+++ b/include/uapi/linux/isl29023.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+#ifndef __UAPI_LINUX_ISL29023_H__
+#define __UAPI_LINUX_ISL29023_H__
+
+#include <linux/types.h>
+
+#define ISL29023_PD_MODE 0x0
+#define ISL29023_ALS_ONCE_MODE 0x1
+#define ISL29023_IR_ONCE_MODE 0x2
+#define ISL29023_ALS_CONT_MODE 0x5
+#define ISL29023_IR_CONT_MODE 0x6
+
+#define ISL29023_INT_PERSISTS_1 0x0
+#define ISL29023_INT_PERSISTS_4 0x1
+#define ISL29023_INT_PERSISTS_8 0x2
+#define ISL29023_INT_PERSISTS_16 0x3
+
+#define ISL29023_RES_16 0x0
+#define ISL29023_RES_12 0x1
+#define ISL29023_RES_8 0x2
+#define ISL29023_RES_4 0x3
+
+#define ISL29023_RANGE_1K 0x0
+#define ISL29023_RANGE_4K 0x1
+#define ISL29023_RANGE_16K 0x2
+#define ISL29023_RANGE_64K 0x3
+
+#endif
diff --git a/include/uapi/linux/mxc_asrc.h b/include/uapi/linux/mxc_asrc.h
new file mode 100644
index 000000000000..7a2b7dfcdc5b
--- /dev/null
+++ b/include/uapi/linux/mxc_asrc.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2008-2014 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 mxc_asrc.h
+ *
+ * @brief i.MX Asynchronous Sample Rate Converter
+ *
+ * @ingroup Audio
+ */
+
+#ifndef __MXC_ASRC_UAPI_H__
+#define __MXC_ASRC_UAPI_H__
+
+#define ASRC_IOC_MAGIC 'C'
+
+#define ASRC_REQ_PAIR _IOWR(ASRC_IOC_MAGIC, 0, struct asrc_req)
+#define ASRC_CONFIG_PAIR _IOWR(ASRC_IOC_MAGIC, 1, struct asrc_config)
+#define ASRC_RELEASE_PAIR _IOW(ASRC_IOC_MAGIC, 2, enum asrc_pair_index)
+#define ASRC_CONVERT _IOW(ASRC_IOC_MAGIC, 3, struct asrc_convert_buffer)
+#define ASRC_START_CONV _IOW(ASRC_IOC_MAGIC, 4, enum asrc_pair_index)
+#define ASRC_STOP_CONV _IOW(ASRC_IOC_MAGIC, 5, enum asrc_pair_index)
+#define ASRC_STATUS _IOW(ASRC_IOC_MAGIC, 6, struct asrc_status_flags)
+#define ASRC_FLUSH _IOW(ASRC_IOC_MAGIC, 7, enum asrc_pair_index)
+
+enum asrc_pair_index {
+ ASRC_INVALID_PAIR = -1,
+ ASRC_PAIR_A = 0,
+ ASRC_PAIR_B = 1,
+ ASRC_PAIR_C = 2,
+};
+
+#define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1)
+
+enum asrc_inclk {
+ INCLK_NONE = 0x03,
+ INCLK_ESAI_RX = 0x00,
+ INCLK_SSI1_RX = 0x01,
+ INCLK_SSI2_RX = 0x02,
+ INCLK_SSI3_RX = 0x07,
+ INCLK_SPDIF_RX = 0x04,
+ INCLK_MLB_CLK = 0x05,
+ INCLK_PAD = 0x06,
+ INCLK_ESAI_TX = 0x08,
+ INCLK_SSI1_TX = 0x09,
+ INCLK_SSI2_TX = 0x0a,
+ INCLK_SSI3_TX = 0x0b,
+ INCLK_SPDIF_TX = 0x0c,
+ INCLK_ASRCK1_CLK = 0x0f,
+};
+
+enum asrc_outclk {
+ OUTCLK_NONE = 0x03,
+ OUTCLK_ESAI_TX = 0x00,
+ OUTCLK_SSI1_TX = 0x01,
+ OUTCLK_SSI2_TX = 0x02,
+ OUTCLK_SSI3_TX = 0x07,
+ OUTCLK_SPDIF_TX = 0x04,
+ OUTCLK_MLB_CLK = 0x05,
+ OUTCLK_PAD = 0x06,
+ OUTCLK_ESAI_RX = 0x08,
+ OUTCLK_SSI1_RX = 0x09,
+ OUTCLK_SSI2_RX = 0x0a,
+ OUTCLK_SSI3_RX = 0x0b,
+ OUTCLK_SPDIF_RX = 0x0c,
+ OUTCLK_ASRCK1_CLK = 0x0f,
+};
+
+enum asrc_word_width {
+ ASRC_WIDTH_24_BIT = 0,
+ ASRC_WIDTH_16_BIT = 1,
+ ASRC_WIDTH_8_BIT = 2,
+};
+
+struct asrc_config {
+ enum asrc_pair_index pair;
+ unsigned int channel_num;
+ unsigned int buffer_num;
+ unsigned int dma_buffer_size;
+ unsigned int input_sample_rate;
+ unsigned int output_sample_rate;
+ enum asrc_word_width input_word_width;
+ enum asrc_word_width output_word_width;
+ enum asrc_inclk inclk;
+ enum asrc_outclk outclk;
+};
+
+struct asrc_req {
+ unsigned int chn_num;
+ enum asrc_pair_index index;
+};
+
+struct asrc_querybuf {
+ unsigned int buffer_index;
+ unsigned int input_length;
+ unsigned int output_length;
+ unsigned long input_offset;
+ unsigned long output_offset;
+};
+
+struct asrc_convert_buffer {
+ void *input_buffer_vaddr;
+ void *output_buffer_vaddr;
+ unsigned int input_buffer_length;
+ unsigned int output_buffer_length;
+};
+
+struct asrc_status_flags {
+ enum asrc_pair_index index;
+ unsigned int overload_error;
+};
+
+enum asrc_error_status {
+ ASRC_TASK_Q_OVERLOAD = 0x01,
+ ASRC_OUTPUT_TASK_OVERLOAD = 0x02,
+ ASRC_INPUT_TASK_OVERLOAD = 0x04,
+ ASRC_OUTPUT_BUFFER_OVERFLOW = 0x08,
+ ASRC_INPUT_BUFFER_UNDERRUN = 0x10,
+};
+#endif/* __MXC_ASRC_UAPI_H__ */
diff --git a/include/uapi/linux/mxc_dcic.h b/include/uapi/linux/mxc_dcic.h
new file mode 100644
index 000000000000..83e3e2c68c02
--- /dev/null
+++ b/include/uapi/linux/mxc_dcic.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*!
+ * @file uapi/linux/mxc_dcic.h
+ *
+ * @brief MXC DCIC private header file
+ *
+ * @ingroup MXC DCIC
+ */
+#ifndef __ASM_ARCH_MXC_DCIC_H__
+#define __ASM_ARCH_MXC_DCIC_H__
+
+#define DCIC_IOC_ALLOC_ROI_NUM _IO('D', 10)
+#define DCIC_IOC_FREE_ROI_NUM _IO('D', 11)
+#define DCIC_IOC_CONFIG_DCIC _IO('D', 12)
+#define DCIC_IOC_CONFIG_ROI _IO('D', 13)
+#define DCIC_IOC_GET_RESULT _IO('D', 14)
+
+struct roi_params {
+ unsigned int roi_n;
+ unsigned int ref_sig;
+ unsigned int start_y;
+ unsigned int start_x;
+ unsigned int end_y;
+ unsigned int end_x;
+ char freeze;
+};
+
+#endif
diff --git a/include/uapi/linux/mxc_mlb.h b/include/uapi/linux/mxc_mlb.h
new file mode 100644
index 000000000000..20ba5240ea51
--- /dev/null
+++ b/include/uapi/linux/mxc_mlb.h
@@ -0,0 +1,55 @@
+/*
+ * mxc_mlb.h
+ *
+ * Copyright 2008-2013 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
+ */
+
+#ifndef _MXC_MLB_UAPI_H
+#define _MXC_MLB_UAPI_H
+
+/* define IOCTL command */
+#define MLB_DBG_RUNTIME _IO('S', 0x09)
+#define MLB_SET_FPS _IOW('S', 0x10, unsigned int)
+#define MLB_GET_VER _IOR('S', 0x11, unsigned long)
+#define MLB_SET_DEVADDR _IOR('S', 0x12, unsigned char)
+
+/*!
+ * set channel address for each logical channel
+ * the MSB 16bits is for tx channel, the left LSB is for rx channel
+ */
+#define MLB_CHAN_SETADDR _IOW('S', 0x13, unsigned int)
+#define MLB_CHAN_STARTUP _IO('S', 0x14)
+#define MLB_CHAN_SHUTDOWN _IO('S', 0x15)
+#define MLB_CHAN_GETEVENT _IOR('S', 0x16, unsigned long)
+
+#define MLB_SET_ISOC_BLKSIZE_188 _IO('S', 0x17)
+#define MLB_SET_ISOC_BLKSIZE_196 _IO('S', 0x18)
+#define MLB_SET_SYNC_QUAD _IOW('S', 0x19, unsigned int)
+#define MLB_IRQ_ENABLE _IO('S', 0x20)
+#define MLB_IRQ_DISABLE _IO('S', 0x21)
+
+/*!
+ * MLB event define
+ */
+enum {
+ MLB_EVT_TX_PROTO_ERR_CUR = 1 << 0,
+ MLB_EVT_TX_BRK_DETECT_CUR = 1 << 1,
+ MLB_EVT_TX_PROTO_ERR_PREV = 1 << 8,
+ MLB_EVT_TX_BRK_DETECT_PREV = 1 << 9,
+ MLB_EVT_RX_PROTO_ERR_CUR = 1 << 16,
+ MLB_EVT_RX_BRK_DETECT_CUR = 1 << 17,
+ MLB_EVT_RX_PROTO_ERR_PREV = 1 << 24,
+ MLB_EVT_RX_BRK_DETECT_PREV = 1 << 25,
+};
+
+
+#endif /* _MXC_MLB_H */
diff --git a/include/uapi/linux/mxc_sim_interface.h b/include/uapi/linux/mxc_sim_interface.h
new file mode 100644
index 000000000000..9ac3c029ab40
--- /dev/null
+++ b/include/uapi/linux/mxc_sim_interface.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+#ifndef UAPI_MXC_SIM_INTERFACE_H
+#define UAPI_MXC_SIM_INTERFACE_H
+
+#define SIM_ATR_LENGTH_MAX 32
+
+/* Raw ATR SIM_IOCTL_GET_ATR */
+typedef struct {
+ unsigned int size;/* length of ATR received */
+ unsigned char *atr_buffer;/* raw ATR string received */
+ int errval;/* The error vale reported to user space after completing ATR*/
+} sim_atr_t;
+
+/* ISO7816-3 protocols */
+#define SIM_PROTOCOL_T0 1
+#define SIM_PROTOCOL_T1 2
+
+/* Transfer types for SIM_IOCTL_XFER */
+#define SIM_XFER_TYPE_TPDU 1
+#define SIM_XFER_TYPE_PTS 2
+
+typedef struct {
+ unsigned int wwt;
+ unsigned int cwt;
+ unsigned int bwt;
+ unsigned int bgt;
+ unsigned int cgt;
+} sim_timing_t;
+
+/* Transfer data for SIM_IOCTL_XFER */
+typedef struct {
+ unsigned char *xmt_buffer; /* transmit buffer pointer */
+ int xmt_length;/* transmit buffer length */
+ int timeout;/* transfer timeout in milliseconds */
+ int errval;/* The error vale reported to user space after completing transmitting*/
+} sim_xmt_t;
+
+typedef struct {
+ unsigned char *rcv_buffer; /* receive buffer pointer */
+ int rcv_length; /* receive buffer length */
+ int timeout;/* transfer timeout in milliseconds */
+ int errval;/* The error vale reported to user space after receiving*/
+} sim_rcv_t;
+
+typedef struct {
+ unsigned char di;
+ unsigned char fi;
+} sim_baud_t;
+
+/* Interface power states */
+#define SIM_POWER_OFF (0)
+#define SIM_POWER_ON (1)
+
+/* Return values for SIM_IOCTL_GET_PRESENSE */
+#define SIM_PRESENT_REMOVED (0)
+#define SIM_PRESENT_DETECTED (1)
+#define SIM_PRESENT_OPERATIONAL (2)
+
+/* The error value */
+#define SIM_OK (0)
+#define SIM_ERROR_CWT (1 << 0)
+#define SIM_ERROR_BWT (1 << 1)
+#define SIM_ERROR_PARITY (1 << 2)
+#define SIM_ERROR_INVALID_TS (1 << 3)
+#define SIM_ERROR_FRAME (1 << 4)
+#define SIM_ERROR_ATR_TIMEROUT (1 << 5)
+#define SIM_ERROR_NACK_THRESHOLD (1 << 6)
+#define SIM_ERROR_BGT (1 << 7)
+#define SIM_ERROR_ATR_DELAY (1 << 8)
+
+/* Return values for SIM_IOCTL_GET_ERROR */
+#define SIM_E_ACCESS (1)
+#define SIM_E_TPDUSHORT (2)
+#define SIM_E_PTSEMPTY (3)
+#define SIM_E_INVALIDXFERTYPE (4)
+#define SIM_E_INVALIDXMTLENGTH (5)
+#define SIM_E_INVALIDRCVLENGTH (6)
+#define SIM_E_NACK (7)
+#define SIM_E_TIMEOUT (8)
+#define SIM_E_NOCARD (9)
+#define SIM_E_PARAM_FI_INVALID (10)
+#define SIM_E_PARAM_DI_INVALID (11)
+#define SIM_E_PARAM_FBYD_WITHFRACTION (12)
+#define SIM_E_PARAM_FBYD_NOTDIVBY8OR12 (13)
+#define SIM_E_PARAM_DIVISOR_RANGE (14)
+#define SIM_E_MALLOC (15)
+#define SIM_E_IRQ (16)
+#define SIM_E_POWERED_ON (17)
+#define SIM_E_POWERED_OFF (18)
+
+/* ioctl encodings */
+#define SIM_IOCTL_BASE (0xc0)
+#define SIM_IOCTL_GET_PRESENSE _IOR(SIM_IOCTL_BASE, 1, int)
+#define SIM_IOCTL_GET_ATR _IOR(SIM_IOCTL_BASE, 2, sim_atr_t)
+#define SIM_IOCTL_XMT _IOR(SIM_IOCTL_BASE, 3, sim_xmt_t)
+#define SIM_IOCTL_RCV _IOR(SIM_IOCTL_BASE, 4, sim_rcv_t)
+#define SIM_IOCTL_ACTIVATE _IO(SIM_IOCTL_BASE, 5)
+#define SIM_IOCTL_DEACTIVATE _IO(SIM_IOCTL_BASE, 6)
+#define SIM_IOCTL_WARM_RESET _IO(SIM_IOCTL_BASE, 7)
+#define SIM_IOCTL_COLD_RESET _IO(SIM_IOCTL_BASE, 8)
+#define SIM_IOCTL_CARD_LOCK _IO(SIM_IOCTL_BASE, 9)
+#define SIM_IOCTL_CARD_EJECT _IO(SIM_IOCTL_BASE, 10)
+#define SIM_IOCTL_SET_PROTOCOL _IOR(SIM_IOCTL_BASE, 11, unsigned int)
+#define SIM_IOCTL_SET_TIMING _IOR(SIM_IOCTL_BASE, 12, sim_timing_t)
+#define SIM_IOCTL_SET_BAUD _IOR(SIM_IOCTL_BASE, 13, sim_baud_t)
+#define SIM_IOCTL_WAIT _IOR(SIM_IOCTL_BASE, 14, unsigned int)
+
+#endif
diff --git a/include/uapi/linux/mxc_v4l2.h b/include/uapi/linux/mxc_v4l2.h
new file mode 100644
index 000000000000..f261b925a7ed
--- /dev/null
+++ b/include/uapi/linux/mxc_v4l2.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013-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.
+ */
+
+/*!
+ * @file uapi/linux/mxc_v4l2.h
+ *
+ * @brief MXC V4L2 private header file
+ *
+ * @ingroup MXC V4L2
+ */
+
+#ifndef __ASM_ARCH_MXC_V4L2_H__
+#define __ASM_ARCH_MXC_V4L2_H__
+
+/*
+ * For IPUv1 and IPUv3, V4L2_CID_MXC_ROT means encoder ioctl ID.
+ * And V4L2_CID_MXC_VF_ROT is viewfinder ioctl ID only for IPUv1 and IPUv3.
+ */
+#define V4L2_CID_MXC_ROT (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_MXC_FLASH (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_MXC_VF_ROT (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_MXC_MOTION (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_MXC_SWITCH_CAM (V4L2_CID_PRIVATE_BASE + 6)
+
+#define V4L2_MXC_ROTATE_NONE 0
+#define V4L2_MXC_ROTATE_VERT_FLIP 1
+#define V4L2_MXC_ROTATE_HORIZ_FLIP 2
+#define V4L2_MXC_ROTATE_180 3
+#define V4L2_MXC_ROTATE_90_RIGHT 4
+#define V4L2_MXC_ROTATE_90_RIGHT_VFLIP 5
+#define V4L2_MXC_ROTATE_90_RIGHT_HFLIP 6
+#define V4L2_MXC_ROTATE_90_LEFT 7
+
+struct v4l2_mxc_offset {
+ uint32_t u_offset;
+ uint32_t v_offset;
+};
+
+struct v4l2_mxc_dest_crop {
+ __u32 type; /* enum v4l2_buf_type */
+ struct v4l2_mxc_offset offset;
+};
+
+/*
+ * Private IOCTLs
+ *
+ * VIDIOC_S_INOUT_CROP: Set input stream crop size
+ * VIDIOC_G_INOUT_CROP: Get input stream crop size
+ */
+#define VIDIOC_S_INPUT_CROP \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct v4l2_crop)
+#define VIDIOC_G_INPUT_CROP \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct v4l2_crop)
+#define VIDIOC_S_DEST_CROP \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct v4l2_mxc_dest_crop)
+#endif
diff --git a/include/uapi/linux/mxcfb.h b/include/uapi/linux/mxcfb.h
new file mode 100644
index 000000000000..3a984090769a
--- /dev/null
+++ b/include/uapi/linux/mxcfb.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2013-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.
+ */
+
+/*
+ * @file uapi/linux/mxcfb.h
+ *
+ * @brief Global header file for the MXC frame buffer
+ *
+ * @ingroup Framebuffer
+ */
+#ifndef __ASM_ARCH_MXCFB_H__
+#define __ASM_ARCH_MXCFB_H__
+
+#include <linux/fb.h>
+
+#define FB_SYNC_OE_LOW_ACT 0x80000000
+#define FB_SYNC_CLK_LAT_FALL 0x40000000
+#define FB_SYNC_DATA_INVERT 0x20000000
+#define FB_SYNC_CLK_IDLE_EN 0x10000000
+#define FB_SYNC_SHARP_MODE 0x08000000
+#define FB_SYNC_SWAP_RGB 0x04000000
+#define FB_ACCEL_TRIPLE_FLAG 0x00000000
+#define FB_ACCEL_DOUBLE_FLAG 0x00000001
+
+struct mxcfb_gbl_alpha {
+ int enable;
+ int alpha;
+};
+
+struct mxcfb_loc_alpha {
+ int enable;
+ int alpha_in_pixel;
+ unsigned long alpha_phy_addr0;
+ unsigned long alpha_phy_addr1;
+};
+
+struct mxcfb_color_key {
+ int enable;
+ __u32 color_key;
+};
+
+struct mxcfb_pos {
+ __u16 x;
+ __u16 y;
+};
+
+struct mxcfb_gamma {
+ int enable;
+ int constk[16];
+ int slopek[16];
+};
+
+struct mxcfb_gpu_split_fmt {
+ struct fb_var_screeninfo var;
+ unsigned long offset;
+};
+
+struct mxcfb_rect {
+ __u32 top;
+ __u32 left;
+ __u32 width;
+ __u32 height;
+};
+
+#define GRAYSCALE_8BIT 0x1
+#define GRAYSCALE_8BIT_INVERTED 0x2
+#define GRAYSCALE_4BIT 0x3
+#define GRAYSCALE_4BIT_INVERTED 0x4
+
+#define AUTO_UPDATE_MODE_REGION_MODE 0
+#define AUTO_UPDATE_MODE_AUTOMATIC_MODE 1
+
+#define UPDATE_SCHEME_SNAPSHOT 0
+#define UPDATE_SCHEME_QUEUE 1
+#define UPDATE_SCHEME_QUEUE_AND_MERGE 2
+
+#define UPDATE_MODE_PARTIAL 0x0
+#define UPDATE_MODE_FULL 0x1
+
+#define WAVEFORM_MODE_GLR16 4
+#define WAVEFORM_MODE_GLD16 5
+#define WAVEFORM_MODE_AUTO 257
+
+#define TEMP_USE_AMBIENT 0x1000
+
+#define EPDC_FLAG_ENABLE_INVERSION 0x01
+#define EPDC_FLAG_FORCE_MONOCHROME 0x02
+#define EPDC_FLAG_USE_CMAP 0x04
+#define EPDC_FLAG_USE_ALT_BUFFER 0x100
+#define EPDC_FLAG_TEST_COLLISION 0x200
+#define EPDC_FLAG_GROUP_UPDATE 0x400
+#define EPDC_FLAG_USE_DITHERING_Y1 0x2000
+#define EPDC_FLAG_USE_DITHERING_Y4 0x4000
+#define EPDC_FLAG_USE_REGAL 0x8000
+
+enum mxcfb_dithering_mode {
+ EPDC_FLAG_USE_DITHERING_PASSTHROUGH = 0x0,
+ EPDC_FLAG_USE_DITHERING_FLOYD_STEINBERG,
+ EPDC_FLAG_USE_DITHERING_ATKINSON,
+ EPDC_FLAG_USE_DITHERING_ORDERED,
+ EPDC_FLAG_USE_DITHERING_QUANT_ONLY,
+ EPDC_FLAG_USE_DITHERING_MAX,
+};
+
+#define FB_POWERDOWN_DISABLE -1
+
+struct mxcfb_alt_buffer_data {
+ __u32 phys_addr;
+ __u32 width; /* width of entire buffer */
+ __u32 height; /* height of entire buffer */
+ struct mxcfb_rect alt_update_region; /* region within buffer to update */
+};
+
+struct mxcfb_update_data {
+ struct mxcfb_rect update_region;
+ __u32 waveform_mode;
+ __u32 update_mode;
+ __u32 update_marker;
+ int temp;
+ unsigned int flags;
+ int dither_mode;
+ int quant_bit;
+ struct mxcfb_alt_buffer_data alt_buffer_data;
+};
+
+struct mxcfb_update_marker_data {
+ __u32 update_marker;
+ __u32 collision_test;
+};
+
+/*
+ * Structure used to define waveform modes for driver
+ * Needed for driver to perform auto-waveform selection
+ */
+struct mxcfb_waveform_modes {
+ int mode_init;
+ int mode_du;
+ int mode_gc4;
+ int mode_gc8;
+ int mode_gc16;
+ int mode_gc32;
+};
+
+/*
+ * Structure used to define a 5*3 matrix of parameters for
+ * setting IPU DP CSC module related to this framebuffer.
+ */
+struct mxcfb_csc_matrix {
+ int param[5][3];
+};
+
+#define MXCFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t)
+#define MXCFB_SET_GBL_ALPHA _IOW('F', 0x21, struct mxcfb_gbl_alpha)
+#define MXCFB_SET_CLR_KEY _IOW('F', 0x22, struct mxcfb_color_key)
+#define MXCFB_SET_OVERLAY_POS _IOWR('F', 0x24, struct mxcfb_pos)
+#define MXCFB_GET_FB_IPU_CHAN _IOR('F', 0x25, u_int32_t)
+#define MXCFB_SET_LOC_ALPHA _IOWR('F', 0x26, struct mxcfb_loc_alpha)
+#define MXCFB_SET_LOC_ALP_BUF _IOW('F', 0x27, unsigned long)
+#define MXCFB_SET_GAMMA _IOW('F', 0x28, struct mxcfb_gamma)
+#define MXCFB_GET_FB_IPU_DI _IOR('F', 0x29, u_int32_t)
+#define MXCFB_GET_DIFMT _IOR('F', 0x2A, u_int32_t)
+#define MXCFB_GET_FB_BLANK _IOR('F', 0x2B, u_int32_t)
+#define MXCFB_SET_DIFMT _IOW('F', 0x2C, u_int32_t)
+#define MXCFB_CSC_UPDATE _IOW('F', 0x2D, struct mxcfb_csc_matrix)
+#define MXCFB_SET_GPU_SPLIT_FMT _IOW('F', 0x2F, struct mxcfb_gpu_split_fmt)
+#define MXCFB_SET_PREFETCH _IOW('F', 0x30, int)
+#define MXCFB_GET_PREFETCH _IOR('F', 0x31, int)
+
+/* IOCTLs for E-ink panel updates */
+#define MXCFB_SET_WAVEFORM_MODES _IOW('F', 0x2B, struct mxcfb_waveform_modes)
+#define MXCFB_SET_TEMPERATURE _IOW('F', 0x2C, int32_t)
+#define MXCFB_SET_AUTO_UPDATE_MODE _IOW('F', 0x2D, __u32)
+#define MXCFB_SEND_UPDATE _IOW('F', 0x2E, struct mxcfb_update_data)
+#define MXCFB_WAIT_FOR_UPDATE_COMPLETE _IOWR('F', 0x2F, struct mxcfb_update_marker_data)
+#define MXCFB_SET_PWRDOWN_DELAY _IOW('F', 0x30, int32_t)
+#define MXCFB_GET_PWRDOWN_DELAY _IOR('F', 0x31, int32_t)
+#define MXCFB_SET_UPDATE_SCHEME _IOW('F', 0x32, __u32)
+#define MXCFB_GET_WORK_BUFFER _IOWR('F', 0x34, unsigned long)
+#define MXCFB_DISABLE_EPDC_ACCESS _IO('F', 0x35)
+#define MXCFB_ENABLE_EPDC_ACCESS _IO('F', 0x36)
+#endif
diff --git a/include/uapi/linux/pxp_device.h b/include/uapi/linux/pxp_device.h
new file mode 100644
index 000000000000..fce89ce066bb
--- /dev/null
+++ b/include/uapi/linux/pxp_device.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _UAPI_PXP_DEVICE
+#define _UAPI_PXP_DEVICE
+
+#include <linux/pxp_dma.h>
+
+struct pxp_chan_handle {
+ unsigned int handle;
+ int hist_status;
+};
+
+struct pxp_mem_desc {
+ unsigned int handle;
+ unsigned int size;
+ dma_addr_t phys_addr;
+ unsigned int virt_uaddr; /* virtual user space address */
+ unsigned int mtype;
+};
+
+struct pxp_mem_flush {
+ unsigned int handle;
+ unsigned int type;
+};
+
+#define PXP_IOC_MAGIC 'P'
+
+#define PXP_IOC_GET_CHAN _IOR(PXP_IOC_MAGIC, 0, struct pxp_mem_desc)
+#define PXP_IOC_PUT_CHAN _IOW(PXP_IOC_MAGIC, 1, struct pxp_mem_desc)
+#define PXP_IOC_CONFIG_CHAN _IOW(PXP_IOC_MAGIC, 2, struct pxp_mem_desc)
+#define PXP_IOC_START_CHAN _IOW(PXP_IOC_MAGIC, 3, struct pxp_mem_desc)
+#define PXP_IOC_GET_PHYMEM _IOWR(PXP_IOC_MAGIC, 4, struct pxp_mem_desc)
+#define PXP_IOC_PUT_PHYMEM _IOW(PXP_IOC_MAGIC, 5, struct pxp_mem_desc)
+#define PXP_IOC_WAIT4CMPLT _IOWR(PXP_IOC_MAGIC, 6, struct pxp_mem_desc)
+#define PXP_IOC_FLUSH_PHYMEM _IOR(PXP_IOC_MAGIC, 7, struct pxp_mem_flush)
+
+/* Memory types supported*/
+#define MEMORY_TYPE_UNCACHED 0x0
+#define MEMORY_TYPE_WC 0x1
+#define MEMORY_TYPE_CACHED 0x2
+
+/* Cache flush operations */
+#define CACHE_CLEAN 0x1
+#define CACHE_INVALIDATE 0x2
+#define CACHE_FLUSH 0x4
+
+#endif
diff --git a/include/uapi/linux/pxp_dma.h b/include/uapi/linux/pxp_dma.h
new file mode 100644
index 000000000000..76983abb4344
--- /dev/null
+++ b/include/uapi/linux/pxp_dma.h
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _UAPI_PXP_DMA
+#define _UAPI_PXP_DMA
+
+#include <linux/posix_types.h>
+#include <linux/types.h>
+
+#ifndef __KERNEL__
+typedef unsigned long dma_addr_t;
+typedef unsigned char bool;
+#endif
+
+/* PXP Pixel format definitions */
+/* Four-character-code (FOURCC) */
+#define fourcc(a, b, c, d)\
+ (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
+
+/*!
+ * @name PXP Pixel Formats
+ *
+ * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
+ * the same used by V4L2 API.
+ */
+
+/*! @} */
+/*! @name RGB Formats */
+/*! @{ */
+#define PXP_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*!< 8 RGB-3-3-2 */
+#define PXP_PIX_FMT_RGB444 fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */
+#define PXP_PIX_FMT_ARGB444 fourcc('A', 'R', '1', '2') /* 16 aaaarrrr ggggbbbb */
+#define PXP_PIX_FMT_RGBA444 fourcc('R', 'A', '1', '2') /* 16 rrrrgggg bbbbaaaa */
+#define PXP_PIX_FMT_XRGB444 fourcc('X', 'R', '1', '2') /* 16 xxxxrrrr ggggbbbb */
+#define PXP_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*!< 16 RGB-5-5-5 */
+#define PXP_PIX_FMT_ARGB555 fourcc('A', 'R', '1', '5') /*!< 16 ARGB-1-5-5-5 */
+#define PXP_PIX_FMT_RGBA555 fourcc('R', 'A', '1', '5') /*!< 16 RGBA-5-5-5-1 */
+#define PXP_PIX_FMT_XRGB555 fourcc('X', 'R', '1', '5') /*!< 16 XRGB-1-5-5-5 */
+#define PXP_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*!< 16 RGB-5-6-5 */
+#define PXP_PIX_FMT_BGR565 fourcc('B', 'G', 'R', 'P') /*!< 16 BGR-5-6-5 */
+#define PXP_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*!< 18 RGB-6-6-6 */
+#define PXP_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*!< 18 BGR-6-6-6 */
+#define PXP_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*!< 24 BGR-8-8-8 */
+#define PXP_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*!< 24 RGB-8-8-8 */
+#define PXP_PIX_FMT_XBGR32 fourcc('X', 'B', 'G', 'R') /*!< 32 XBGR-8-8-8-8 */
+#define PXP_PIX_FMT_BGRX32 fourcc('B', 'G', 'R', 'X') /*!< 32 BGRX-8-8-8-8 */
+#define PXP_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*!< 32 BGRA-8-8-8-8 */
+#define PXP_PIX_FMT_XRGB32 fourcc('X', 'R', 'G', 'B') /*!< 32 XRGB-8-8-8-8 */
+#define PXP_PIX_FMT_RGBX32 fourcc('R', 'G', 'B', 'X') /*!< 32 RGBX-8-8-8-8 */
+#define PXP_PIX_FMT_ARGB32 fourcc('A', 'R', 'G', 'B') /*!< 32 ARGB-8-8-8-8 */
+#define PXP_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*!< 32 RGBA-8-8-8-8 */
+#define PXP_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*!< 32 ABGR-8-8-8-8 */
+#define PXP_PIX_FMT_RGB32 PXP_PIX_FMT_XRGB32
+/*! @} */
+/*! @name YUV Interleaved Formats */
+/*! @{ */
+#define PXP_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*!< 16 YUV 4:2:2 */
+#define PXP_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*!< 16 YUV 4:2:2 */
+#define PXP_PIX_FMT_VYUY fourcc('V', 'Y', 'U', 'Y') /*!< 16 YVU 4:2:2 */
+#define PXP_PIX_FMT_YVYU fourcc('Y', 'V', 'Y', 'U') /*!< 16 YVU 4:2:2 */
+#define PXP_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*!< 12 YUV 4:1:1 */
+#define PXP_PIX_FMT_VUY444 fourcc('V', 'U', 'Y', 'A') /*!< 32 VUYA 8:8:8 */
+#define PXP_PIX_FMT_YUV444 fourcc('A', 'Y', 'U', 'V') /*!< 32 AYUV 8:8:8 */
+#define PXP_PIX_FMT_YVU444 fourcc('A', 'Y', 'V', 'U') /*!< 32 AYUV 8:8:8 */
+/* two planes -- one Y, one Cb + Cr interleaved */
+#define PXP_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
+#define PXP_PIX_FMT_NV21 fourcc('N', 'V', '2', '1') /* 12 Y/CbCr 4:2:0 */
+#define PXP_PIX_FMT_NV16 fourcc('N', 'V', '1', '6') /* 12 Y/CbCr 4:2:2 */
+#define PXP_PIX_FMT_NV61 fourcc('N', 'V', '6', '1') /* 12 Y/CbCr 4:2:2 */
+/*! @} */
+/*! @name YUV Planar Formats */
+/*! @{ */
+#define PXP_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*!< 8 Greyscale */
+#define PXP_PIX_FMT_GY04 fourcc('G', 'Y', '0', '4') /*!< 4 Greyscale */
+#define PXP_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*!< 9 YVU 4:1:0 */
+#define PXP_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*!< 9 YUV 4:1:0 */
+#define PXP_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*!< 12 YVU 4:2:0 */
+#define PXP_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*!< 12 YUV 4:2:0 */
+#define PXP_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*!< 12 YUV 4:2:0 */
+#define PXP_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*!< 16 YVU 4:2:2 */
+#define PXP_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*!< 16 YUV 4:2:2 */
+/*! @} */
+
+#define PXP_LUT_NONE 0x0
+#define PXP_LUT_INVERT 0x1
+#define PXP_LUT_BLACK_WHITE 0x2
+#define PXP_LUT_USE_CMAP 0x4
+
+/* dithering modes enum */
+#define PXP_DITHER_PASS_THROUGH 0
+#define PXP_DITHER_FLOYD 1
+#define PXP_DITHER_ATKINSON 2
+#define PXP_DITHER_ORDERED 3
+#define PXP_DITHER_QUANT_ONLY 4
+
+#define NR_PXP_VIRT_CHANNEL 16
+
+#define PXP_IOC_MAGIC 'P'
+
+#define PXP_IOC_GET_CHAN _IOR(PXP_IOC_MAGIC, 0, struct pxp_mem_desc)
+#define PXP_IOC_PUT_CHAN _IOW(PXP_IOC_MAGIC, 1, struct pxp_mem_desc)
+#define PXP_IOC_CONFIG_CHAN _IOW(PXP_IOC_MAGIC, 2, struct pxp_mem_desc)
+#define PXP_IOC_START_CHAN _IOW(PXP_IOC_MAGIC, 3, struct pxp_mem_desc)
+#define PXP_IOC_GET_PHYMEM _IOWR(PXP_IOC_MAGIC, 4, struct pxp_mem_desc)
+#define PXP_IOC_PUT_PHYMEM _IOW(PXP_IOC_MAGIC, 5, struct pxp_mem_desc)
+#define PXP_IOC_WAIT4CMPLT _IOWR(PXP_IOC_MAGIC, 6, struct pxp_mem_desc)
+
+#define PXP_IOC_FILL_DATA _IOWR(PXP_IOC_MAGIC, 7, struct pxp_mem_desc)
+
+#define ALPHA_MODE_ROP 0x1
+#define ALPHA_MODE_LEGACY 0x2
+#define ALPHA_MODE_PORTER_DUFF 0x3
+
+#define PXP_DEVICE_LEGACY
+
+/* Order significant! */
+enum pxp_channel_status {
+ PXP_CHANNEL_FREE,
+ PXP_CHANNEL_INITIALIZED,
+ PXP_CHANNEL_READY,
+};
+
+enum pxp_working_mode {
+ PXP_MODE_LEGACY = 0x1,
+ PXP_MODE_STANDARD = 0x2,
+ PXP_MODE_ADVANCED = 0x4,
+};
+
+enum pxp_buffer_flag {
+ PXP_BUF_FLAG_WFE_A_FETCH0 = 0x0001,
+ PXP_BUF_FLAG_WFE_A_FETCH1 = 0x0002,
+ PXP_BUF_FLAG_WFE_A_STORE0 = 0x0004,
+ PXP_BUF_FLAG_WFE_A_STORE1 = 0x0008,
+ PXP_BUF_FLAG_WFE_B_FETCH0 = 0x0010,
+ PXP_BUF_FLAG_WFE_B_FETCH1 = 0x0020,
+ PXP_BUF_FLAG_WFE_B_STORE0 = 0x0040,
+ PXP_BUF_FLAG_WFE_B_STORE1 = 0x0080,
+ PXP_BUF_FLAG_DITHER_FETCH0 = 0x0100,
+ PXP_BUF_FLAG_DITHER_FETCH1 = 0x0200,
+ PXP_BUF_FLAG_DITHER_STORE0 = 0x0400,
+ PXP_BUF_FLAG_DITHER_STORE1 = 0x0800,
+};
+
+enum pxp_engine_ctrl {
+ PXP_ENABLE_ROTATE0 = 0x001,
+ PXP_ENABLE_ROTATE1 = 0x002,
+ PXP_ENABLE_LUT = 0x004,
+ PXP_ENABLE_CSC2 = 0x008,
+ PXP_ENABLE_ALPHA_B = 0x010,
+ PXP_ENABLE_INPUT_FETCH_SOTRE = 0x020,
+ PXP_ENABLE_WFE_B = 0x040,
+ PXP_ENABLE_WFE_A = 0x080,
+ PXP_ENABLE_DITHER = 0x100,
+ PXP_ENABLE_PS_AS_OUT = 0x200,
+ PXP_ENABLE_COLLISION_DETECT = 0x400,
+ PXP_ENABLE_HANDSHAKE = 0x1000,
+ PXP_ENABLE_DITHER_BYPASS = 0x2000,
+};
+
+enum pxp_op_type {
+ PXP_OP_2D = 0x001,
+ PXP_OP_DITHER = 0x002,
+ PXP_OP_WFE_A = 0x004,
+ PXP_OP_WFE_B = 0x008,
+};
+
+struct rect {
+ int top; /* Upper left coordinate of rectangle */
+ int left;
+ int width;
+ int height;
+};
+
+#define ALPHA_MODE_STRAIGHT 0x0
+#define ALPHA_MODE_INVERSED 0x1
+
+#define GLOBAL_ALPHA_MODE_ON 0x0
+#define GLOBAL_ALPHA_MODE_OFF 0x1
+#define GLOBAL_ALPHA_MODE_SCALE 0x2
+
+#define FACTOR_MODE_ONE 0x0
+#define FACTOR_MODE_ZERO 0x1
+#define FACTOR_MODE_STRAIGHT 0x2
+#define FACTOR_MODE_INVERSED 0x3
+
+#define COLOR_MODE_STRAIGHT 0x0
+#define COLOR_MODE_MULTIPLY 0x1
+
+struct pxp_alpha {
+ unsigned int alpha_mode;
+ unsigned int global_alpha_mode;
+ unsigned int global_alpha_value;
+ unsigned int factor_mode;
+ unsigned int color_mode;
+};
+
+struct pxp_layer_param {
+ unsigned short left;
+ unsigned short top;
+ unsigned short width;
+ unsigned short height;
+ unsigned short stride; /* aka pitch */
+ unsigned int pixel_fmt;
+
+ unsigned int flag;
+ /* layers combining parameters
+ * (these are ignored for S0 and output
+ * layers, and only apply for OL layer)
+ */
+ bool combine_enable;
+ unsigned int color_key_enable;
+ unsigned int color_key;
+ bool global_alpha_enable;
+ /* global alpha is either override or multiply */
+ bool global_override;
+ unsigned char global_alpha;
+ bool alpha_invert;
+ bool local_alpha_enable;
+ int comp_mask;
+
+ struct pxp_alpha alpha;
+ struct rect crop;
+
+ dma_addr_t paddr;
+};
+
+struct pxp_collision_info {
+ unsigned int pixel_cnt;
+ unsigned int rect_min_x;
+ unsigned int rect_min_y;
+ unsigned int rect_max_x;
+ unsigned int rect_max_y;
+ unsigned int victim_luts[2];
+};
+
+struct pxp_proc_data {
+ /* S0 Transformation Info */
+ int scaling;
+ int hflip;
+ int vflip;
+ int rotate;
+ int rot_pos;
+ int yuv;
+ unsigned int alpha_mode;
+
+ /* Source rectangle (srect) defines the sub-rectangle
+ * within S0 to undergo processing.
+ */
+ struct rect srect;
+ /* Dest rect (drect) defines how to position the processed
+ * source rectangle (after resizing) within the output frame,
+ * whose dimensions are defined in pxp->pxp_conf_state.out_param
+ */
+ struct rect drect;
+
+ /* Current S0 configuration */
+ unsigned int bgcolor;
+ unsigned char fill_en;
+
+ /* Output overlay support */
+ int overlay_state;
+
+ /* LUT transformation on Y data */
+ int lut_transform;
+ unsigned char *lut_map; /* 256 entries */
+ bool lut_map_updated; /* Map recently changed */
+ bool combine_enable;
+
+ enum pxp_op_type op_type;
+
+ /* LUT cleanup */
+ __u64 lut_sels;
+
+ /* the mode pxp's working against */
+ enum pxp_working_mode working_mode;
+ enum pxp_engine_ctrl engine_enable;
+
+ /* wfe */
+/*
+ * partial:
+ * 0 - full update
+ * 1 - partial update
+ * alpha_en:
+ * 0 - upd is {Y4[3:0],4'b0000} format
+ * 1 - upd is {Y4[3:0],3'b000,alpha} format
+ * reagl_en:
+ * 0 - use normal waveform algorithm
+ * 1 - enable reagl/-d waveform algorithm
+ * detection_only:
+ * 0 - write working buffer
+ * 1 - do no write working buffer, detection only
+ * lut:
+ * valid value 0-63
+ * set to the lut used for next update
+ */
+ bool partial_update;
+ bool alpha_en;
+ bool lut_update;
+ bool reagl_en; /* enable reagl/-d */
+ bool reagl_d_en; /* enable reagl or reagl-d */
+ bool detection_only;
+ bool pxp_legacy;
+ int lut;
+ bool lut_cleanup;
+ unsigned int lut_status_1;
+ unsigned int lut_status_2;
+
+ /* Dithering specific data */
+ int dither_mode;
+ unsigned int quant_bit;
+};
+
+struct pxp_config_data {
+ struct pxp_layer_param s0_param;
+ struct pxp_layer_param ol_param[1];
+ struct pxp_layer_param out_param;
+ struct pxp_layer_param wfe_a_fetch_param[2];
+ struct pxp_layer_param wfe_a_store_param[2];
+ struct pxp_layer_param wfe_b_fetch_param[2];
+ struct pxp_layer_param wfe_b_store_param[2];
+ struct pxp_layer_param dither_fetch_param[2];
+ struct pxp_layer_param dither_store_param[2];
+ struct pxp_proc_data proc_data;
+ int layer_nr;
+
+ /* Users don't touch */
+ int handle;
+};
+
+#endif
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
index 33c603dd7cd3..772f7e88a165 100644
--- a/include/uapi/linux/usb/ch9.h
+++ b/include/uapi/linux/usb/ch9.h
@@ -142,6 +142,8 @@
#define TEST_SE0_NAK 3
#define TEST_PACKET 4
#define TEST_FORCE_EN 5
+#define TEST_OTG_SRP_REQD 6
+#define TEST_OTG_HNP_REQD 7
/*
* New Feature Selectors as added by USB 3.0
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 7f34d3c67648..b7f50f942d72 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -2156,13 +2156,11 @@ struct v4l2_event_subscription {
/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
#define V4L2_CHIP_MATCH_BRIDGE 0 /* Match against chip ID on the bridge (0 for the bridge) */
-#define V4L2_CHIP_MATCH_SUBDEV 4 /* Match against subdev index */
-
-/* The following four defines are no longer in use */
#define V4L2_CHIP_MATCH_HOST V4L2_CHIP_MATCH_BRIDGE
#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver name */
#define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */
#define V4L2_CHIP_MATCH_AC97 3 /* Match against ancillary AC97 chip */
+#define V4L2_CHIP_MATCH_SUBDEV 4 /* Match against subdev index */
struct v4l2_dbg_match {
__u32 type; /* Match type */
@@ -2179,6 +2177,13 @@ struct v4l2_dbg_register {
__u64 val;
} __attribute__ ((packed));
+/* VIDIOC_DBG_G_CHIP_IDENT */
+struct v4l2_dbg_chip_ident {
+ struct v4l2_dbg_match match;
+ __u32 ident; /* chip identifier as specified in <media/v4l2-chip-ident.h> */
+ __u32 revision; /* chip revision, chip specific */
+} __attribute__ ((packed));
+
#define V4L2_CHIP_FL_READABLE (1 << 0)
#define V4L2_CHIP_FL_WRITABLE (1 << 1)
@@ -2283,6 +2288,12 @@ struct v4l2_create_buffers {
#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register)
#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register)
+/* Experimental, meant for debugging, testing and internal use.
+ Never use this ioctl in applications!
+ Note: this ioctl is deprecated in favor of VIDIOC_DBG_G_CHIP_INFO and
+ will go away in the future. */
+#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident)
+
#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek)
#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings)
diff --git a/include/video/mxc_edid.h b/include/video/mxc_edid.h
new file mode 100644
index 000000000000..ff7ddd92a3bc
--- /dev/null
+++ b/include/video/mxc_edid.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2009-2015 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
+ */
+
+/*!
+ * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
+ */
+
+/*!
+ * @file mxc_edid.h
+ *
+ * @brief MXC EDID tools
+ *
+ * @ingroup Framebuffer
+ */
+
+#ifndef MXC_EDID_H
+#define MXC_EDID_H
+
+#include <linux/fb.h>
+
+#define FB_VMODE_ASPECT_4_3 0x10
+#define FB_VMODE_ASPECT_16_9 0x20
+#define FB_VMODE_ASPECT_MASK (FB_VMODE_ASPECT_4_3 | FB_VMODE_ASPECT_16_9)
+
+enum cea_audio_coding_types {
+ AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0,
+ AUDIO_CODING_TYPE_LPCM = 1,
+ AUDIO_CODING_TYPE_AC3 = 2,
+ AUDIO_CODING_TYPE_MPEG1 = 3,
+ AUDIO_CODING_TYPE_MP3 = 4,
+ AUDIO_CODING_TYPE_MPEG2 = 5,
+ AUDIO_CODING_TYPE_AACLC = 6,
+ AUDIO_CODING_TYPE_DTS = 7,
+ AUDIO_CODING_TYPE_ATRAC = 8,
+ AUDIO_CODING_TYPE_SACD = 9,
+ AUDIO_CODING_TYPE_EAC3 = 10,
+ AUDIO_CODING_TYPE_DTS_HD = 11,
+ AUDIO_CODING_TYPE_MLP = 12,
+ AUDIO_CODING_TYPE_DST = 13,
+ AUDIO_CODING_TYPE_WMAPRO = 14,
+ AUDIO_CODING_TYPE_RESERVED = 15,
+};
+
+struct mxc_hdmi_3d_format {
+ unsigned char vic_order_2d;
+ unsigned char struct_3d;
+ unsigned char detail_3d;
+ unsigned char reserved;
+};
+
+struct mxc_edid_cfg {
+ bool cea_underscan;
+ bool cea_basicaudio;
+ bool cea_ycbcr444;
+ bool cea_ycbcr422;
+ bool hdmi_cap;
+
+ /*VSD*/
+ bool vsd_support_ai;
+ bool vsd_dc_48bit;
+ bool vsd_dc_36bit;
+ bool vsd_dc_30bit;
+ bool vsd_dc_y444;
+ bool vsd_dvi_dual;
+
+ bool vsd_cnc0;
+ bool vsd_cnc1;
+ bool vsd_cnc2;
+ bool vsd_cnc3;
+
+ u8 vsd_video_latency;
+ u8 vsd_audio_latency;
+ u8 vsd_I_video_latency;
+ u8 vsd_I_audio_latency;
+
+ u8 physical_address[4];
+ u8 hdmi_vic[64];
+ struct mxc_hdmi_3d_format hdmi_3d_format[64];
+ u16 hdmi_3d_mask_all;
+ u16 hdmi_3d_struct_all;
+ u32 vsd_max_tmdsclk_rate;
+
+ u8 max_channels;
+ u8 sample_sizes;
+ u8 sample_rates;
+ u8 speaker_alloc;
+};
+
+extern const struct fb_videomode mxc_cea_mode[64];
+
+int mxc_edid_var_to_vic(struct fb_var_screeninfo *var);
+int mxc_edid_mode_to_vic(const struct fb_videomode *mode);
+int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
+ unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi);
+int mxc_edid_parse_ext_blk(unsigned char *edid, struct mxc_edid_cfg *cfg,
+ struct fb_monspecs *specs);
+#endif
diff --git a/include/video/mxc_hdmi.h b/include/video/mxc_hdmi.h
new file mode 100644
index 000000000000..79eb3024f65c
--- /dev/null
+++ b/include/video/mxc_hdmi.h
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (C) 2011-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
+ */
+
+#ifndef __MXC_HDMI_H__
+#define __MXC_HDMI_H__
+
+/*
+ * Hdmi controller registers
+ */
+
+/* Identification Registers */
+#define HDMI_DESIGN_ID 0x0000
+#define HDMI_REVISION_ID 0x0001
+#define HDMI_PRODUCT_ID0 0x0002
+#define HDMI_PRODUCT_ID1 0x0003
+#define HDMI_CONFIG0_ID 0x0004
+#define HDMI_CONFIG1_ID 0x0005
+#define HDMI_CONFIG2_ID 0x0006
+#define HDMI_CONFIG3_ID 0x0007
+
+/* Interrupt Registers */
+#define HDMI_IH_FC_STAT0 0x0100
+#define HDMI_IH_FC_STAT1 0x0101
+#define HDMI_IH_FC_STAT2 0x0102
+#define HDMI_IH_AS_STAT0 0x0103
+#define HDMI_IH_PHY_STAT0 0x0104
+#define HDMI_IH_I2CM_STAT0 0x0105
+#define HDMI_IH_CEC_STAT0 0x0106
+#define HDMI_IH_VP_STAT0 0x0107
+#define HDMI_IH_I2CMPHY_STAT0 0x0108
+#define HDMI_IH_AHBDMAAUD_STAT0 0x0109
+
+#define HDMI_IH_MUTE_FC_STAT0 0x0180
+#define HDMI_IH_MUTE_FC_STAT1 0x0181
+#define HDMI_IH_MUTE_FC_STAT2 0x0182
+#define HDMI_IH_MUTE_AS_STAT0 0x0183
+#define HDMI_IH_MUTE_PHY_STAT0 0x0184
+#define HDMI_IH_MUTE_I2CM_STAT0 0x0185
+#define HDMI_IH_MUTE_CEC_STAT0 0x0186
+#define HDMI_IH_MUTE_VP_STAT0 0x0187
+#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188
+#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189
+#define HDMI_IH_MUTE 0x01FF
+
+/* Video Sample Registers */
+#define HDMI_TX_INVID0 0x0200
+#define HDMI_TX_INSTUFFING 0x0201
+#define HDMI_TX_GYDATA0 0x0202
+#define HDMI_TX_GYDATA1 0x0203
+#define HDMI_TX_RCRDATA0 0x0204
+#define HDMI_TX_RCRDATA1 0x0205
+#define HDMI_TX_BCBDATA0 0x0206
+#define HDMI_TX_BCBDATA1 0x0207
+
+/* Video Packetizer Registers */
+#define HDMI_VP_STATUS 0x0800
+#define HDMI_VP_PR_CD 0x0801
+#define HDMI_VP_STUFF 0x0802
+#define HDMI_VP_REMAP 0x0803
+#define HDMI_VP_CONF 0x0804
+#define HDMI_VP_STAT 0x0805
+#define HDMI_VP_INT 0x0806
+#define HDMI_VP_MASK 0x0807
+#define HDMI_VP_POL 0x0808
+
+/* Frame Composer Registers */
+#define HDMI_FC_INVIDCONF 0x1000
+#define HDMI_FC_INHACTV0 0x1001
+#define HDMI_FC_INHACTV1 0x1002
+#define HDMI_FC_INHBLANK0 0x1003
+#define HDMI_FC_INHBLANK1 0x1004
+#define HDMI_FC_INVACTV0 0x1005
+#define HDMI_FC_INVACTV1 0x1006
+#define HDMI_FC_INVBLANK 0x1007
+#define HDMI_FC_HSYNCINDELAY0 0x1008
+#define HDMI_FC_HSYNCINDELAY1 0x1009
+#define HDMI_FC_HSYNCINWIDTH0 0x100A
+#define HDMI_FC_HSYNCINWIDTH1 0x100B
+#define HDMI_FC_VSYNCINDELAY 0x100C
+#define HDMI_FC_VSYNCINWIDTH 0x100D
+#define HDMI_FC_INFREQ0 0x100E
+#define HDMI_FC_INFREQ1 0x100F
+#define HDMI_FC_INFREQ2 0x1010
+#define HDMI_FC_CTRLDUR 0x1011
+#define HDMI_FC_EXCTRLDUR 0x1012
+#define HDMI_FC_EXCTRLSPAC 0x1013
+#define HDMI_FC_CH0PREAM 0x1014
+#define HDMI_FC_CH1PREAM 0x1015
+#define HDMI_FC_CH2PREAM 0x1016
+#define HDMI_FC_AVICONF3 0x1017
+#define HDMI_FC_GCP 0x1018
+#define HDMI_FC_AVICONF0 0x1019
+#define HDMI_FC_AVICONF1 0x101A
+#define HDMI_FC_AVICONF2 0x101B
+#define HDMI_FC_AVIVID 0x101C
+#define HDMI_FC_AVIETB0 0x101D
+#define HDMI_FC_AVIETB1 0x101E
+#define HDMI_FC_AVISBB0 0x101F
+#define HDMI_FC_AVISBB1 0x1020
+#define HDMI_FC_AVIELB0 0x1021
+#define HDMI_FC_AVIELB1 0x1022
+#define HDMI_FC_AVISRB0 0x1023
+#define HDMI_FC_AVISRB1 0x1024
+#define HDMI_FC_AUDICONF0 0x1025
+#define HDMI_FC_AUDICONF1 0x1026
+#define HDMI_FC_AUDICONF2 0x1027
+#define HDMI_FC_AUDICONF3 0x1028
+#define HDMI_FC_VSDIEEEID0 0x1029
+#define HDMI_FC_VSDSIZE 0x102A
+#define HDMI_FC_VSDIEEEID1 0x1030
+#define HDMI_FC_VSDIEEEID2 0x1031
+#define HDMI_FC_VSDPAYLOAD0 0x1032
+#define HDMI_FC_VSDPAYLOAD1 0x1033
+#define HDMI_FC_VSDPAYLOAD2 0x1034
+#define HDMI_FC_VSDPAYLOAD3 0x1035
+#define HDMI_FC_VSDPAYLOAD4 0x1036
+#define HDMI_FC_VSDPAYLOAD5 0x1037
+#define HDMI_FC_VSDPAYLOAD6 0x1038
+#define HDMI_FC_VSDPAYLOAD7 0x1039
+#define HDMI_FC_VSDPAYLOAD8 0x103A
+#define HDMI_FC_VSDPAYLOAD9 0x103B
+#define HDMI_FC_VSDPAYLOAD10 0x103C
+#define HDMI_FC_VSDPAYLOAD11 0x103D
+#define HDMI_FC_VSDPAYLOAD12 0x103E
+#define HDMI_FC_VSDPAYLOAD13 0x103F
+#define HDMI_FC_VSDPAYLOAD14 0x1040
+#define HDMI_FC_VSDPAYLOAD15 0x1041
+#define HDMI_FC_VSDPAYLOAD16 0x1042
+#define HDMI_FC_VSDPAYLOAD17 0x1043
+#define HDMI_FC_VSDPAYLOAD18 0x1044
+#define HDMI_FC_VSDPAYLOAD19 0x1045
+#define HDMI_FC_VSDPAYLOAD20 0x1046
+#define HDMI_FC_VSDPAYLOAD21 0x1047
+#define HDMI_FC_VSDPAYLOAD22 0x1048
+#define HDMI_FC_VSDPAYLOAD23 0x1049
+#define HDMI_FC_SPDVENDORNAME0 0x104A
+#define HDMI_FC_SPDVENDORNAME1 0x104B
+#define HDMI_FC_SPDVENDORNAME2 0x104C
+#define HDMI_FC_SPDVENDORNAME3 0x104D
+#define HDMI_FC_SPDVENDORNAME4 0x104E
+#define HDMI_FC_SPDVENDORNAME5 0x104F
+#define HDMI_FC_SPDVENDORNAME6 0x1050
+#define HDMI_FC_SPDVENDORNAME7 0x1051
+#define HDMI_FC_SDPPRODUCTNAME0 0x1052
+#define HDMI_FC_SDPPRODUCTNAME1 0x1053
+#define HDMI_FC_SDPPRODUCTNAME2 0x1054
+#define HDMI_FC_SDPPRODUCTNAME3 0x1055
+#define HDMI_FC_SDPPRODUCTNAME4 0x1056
+#define HDMI_FC_SDPPRODUCTNAME5 0x1057
+#define HDMI_FC_SDPPRODUCTNAME6 0x1058
+#define HDMI_FC_SDPPRODUCTNAME7 0x1059
+#define HDMI_FC_SDPPRODUCTNAME8 0x105A
+#define HDMI_FC_SDPPRODUCTNAME9 0x105B
+#define HDMI_FC_SDPPRODUCTNAME10 0x105C
+#define HDMI_FC_SDPPRODUCTNAME11 0x105D
+#define HDMI_FC_SDPPRODUCTNAME12 0x105E
+#define HDMI_FC_SDPPRODUCTNAME13 0x105F
+#define HDMI_FC_SDPPRODUCTNAME14 0x1060
+#define HDMI_FC_SPDPRODUCTNAME15 0x1061
+#define HDMI_FC_SPDDEVICEINF 0x1062
+#define HDMI_FC_AUDSCONF 0x1063
+#define HDMI_FC_AUDSSTAT 0x1064
+#define HDMI_FC_DATACH0FILL 0x1070
+#define HDMI_FC_DATACH1FILL 0x1071
+#define HDMI_FC_DATACH2FILL 0x1072
+#define HDMI_FC_CTRLQHIGH 0x1073
+#define HDMI_FC_CTRLQLOW 0x1074
+#define HDMI_FC_ACP0 0x1075
+#define HDMI_FC_ACP28 0x1076
+#define HDMI_FC_ACP27 0x1077
+#define HDMI_FC_ACP26 0x1078
+#define HDMI_FC_ACP25 0x1079
+#define HDMI_FC_ACP24 0x107A
+#define HDMI_FC_ACP23 0x107B
+#define HDMI_FC_ACP22 0x107C
+#define HDMI_FC_ACP21 0x107D
+#define HDMI_FC_ACP20 0x107E
+#define HDMI_FC_ACP19 0x107F
+#define HDMI_FC_ACP18 0x1080
+#define HDMI_FC_ACP17 0x1081
+#define HDMI_FC_ACP16 0x1082
+#define HDMI_FC_ACP15 0x1083
+#define HDMI_FC_ACP14 0x1084
+#define HDMI_FC_ACP13 0x1085
+#define HDMI_FC_ACP12 0x1086
+#define HDMI_FC_ACP11 0x1087
+#define HDMI_FC_ACP10 0x1088
+#define HDMI_FC_ACP9 0x1089
+#define HDMI_FC_ACP8 0x108A
+#define HDMI_FC_ACP7 0x108B
+#define HDMI_FC_ACP6 0x108C
+#define HDMI_FC_ACP5 0x108D
+#define HDMI_FC_ACP4 0x108E
+#define HDMI_FC_ACP3 0x108F
+#define HDMI_FC_ACP2 0x1090
+#define HDMI_FC_ACP1 0x1091
+#define HDMI_FC_ISCR1_0 0x1092
+#define HDMI_FC_ISCR1_16 0x1093
+#define HDMI_FC_ISCR1_15 0x1094
+#define HDMI_FC_ISCR1_14 0x1095
+#define HDMI_FC_ISCR1_13 0x1096
+#define HDMI_FC_ISCR1_12 0x1097
+#define HDMI_FC_ISCR1_11 0x1098
+#define HDMI_FC_ISCR1_10 0x1099
+#define HDMI_FC_ISCR1_9 0x109A
+#define HDMI_FC_ISCR1_8 0x109B
+#define HDMI_FC_ISCR1_7 0x109C
+#define HDMI_FC_ISCR1_6 0x109D
+#define HDMI_FC_ISCR1_5 0x109E
+#define HDMI_FC_ISCR1_4 0x109F
+#define HDMI_FC_ISCR1_3 0x10A0
+#define HDMI_FC_ISCR1_2 0x10A1
+#define HDMI_FC_ISCR1_1 0x10A2
+#define HDMI_FC_ISCR2_15 0x10A3
+#define HDMI_FC_ISCR2_14 0x10A4
+#define HDMI_FC_ISCR2_13 0x10A5
+#define HDMI_FC_ISCR2_12 0x10A6
+#define HDMI_FC_ISCR2_11 0x10A7
+#define HDMI_FC_ISCR2_10 0x10A8
+#define HDMI_FC_ISCR2_9 0x10A9
+#define HDMI_FC_ISCR2_8 0x10AA
+#define HDMI_FC_ISCR2_7 0x10AB
+#define HDMI_FC_ISCR2_6 0x10AC
+#define HDMI_FC_ISCR2_5 0x10AD
+#define HDMI_FC_ISCR2_4 0x10AE
+#define HDMI_FC_ISCR2_3 0x10AF
+#define HDMI_FC_ISCR2_2 0x10B0
+#define HDMI_FC_ISCR2_1 0x10B1
+#define HDMI_FC_ISCR2_0 0x10B2
+#define HDMI_FC_DATAUTO0 0x10B3
+#define HDMI_FC_DATAUTO1 0x10B4
+#define HDMI_FC_DATAUTO2 0x10B5
+#define HDMI_FC_DATMAN 0x10B6
+#define HDMI_FC_DATAUTO3 0x10B7
+#define HDMI_FC_RDRB0 0x10B8
+#define HDMI_FC_RDRB1 0x10B9
+#define HDMI_FC_RDRB2 0x10BA
+#define HDMI_FC_RDRB3 0x10BB
+#define HDMI_FC_RDRB4 0x10BC
+#define HDMI_FC_RDRB5 0x10BD
+#define HDMI_FC_RDRB6 0x10BE
+#define HDMI_FC_RDRB7 0x10BF
+#define HDMI_FC_STAT0 0x10D0
+#define HDMI_FC_INT0 0x10D1
+#define HDMI_FC_MASK0 0x10D2
+#define HDMI_FC_POL0 0x10D3
+#define HDMI_FC_STAT1 0x10D4
+#define HDMI_FC_INT1 0x10D5
+#define HDMI_FC_MASK1 0x10D6
+#define HDMI_FC_POL1 0x10D7
+#define HDMI_FC_STAT2 0x10D8
+#define HDMI_FC_INT2 0x10D9
+#define HDMI_FC_MASK2 0x10DA
+#define HDMI_FC_POL2 0x10DB
+#define HDMI_FC_PRCONF 0x10E0
+
+#define HDMI_FC_GMD_STAT 0x1100
+#define HDMI_FC_GMD_EN 0x1101
+#define HDMI_FC_GMD_UP 0x1102
+#define HDMI_FC_GMD_CONF 0x1103
+#define HDMI_FC_GMD_HB 0x1104
+#define HDMI_FC_GMD_PB0 0x1105
+#define HDMI_FC_GMD_PB1 0x1106
+#define HDMI_FC_GMD_PB2 0x1107
+#define HDMI_FC_GMD_PB3 0x1108
+#define HDMI_FC_GMD_PB4 0x1109
+#define HDMI_FC_GMD_PB5 0x110A
+#define HDMI_FC_GMD_PB6 0x110B
+#define HDMI_FC_GMD_PB7 0x110C
+#define HDMI_FC_GMD_PB8 0x110D
+#define HDMI_FC_GMD_PB9 0x110E
+#define HDMI_FC_GMD_PB10 0x110F
+#define HDMI_FC_GMD_PB11 0x1110
+#define HDMI_FC_GMD_PB12 0x1111
+#define HDMI_FC_GMD_PB13 0x1112
+#define HDMI_FC_GMD_PB14 0x1113
+#define HDMI_FC_GMD_PB15 0x1114
+#define HDMI_FC_GMD_PB16 0x1115
+#define HDMI_FC_GMD_PB17 0x1116
+#define HDMI_FC_GMD_PB18 0x1117
+#define HDMI_FC_GMD_PB19 0x1118
+#define HDMI_FC_GMD_PB20 0x1119
+#define HDMI_FC_GMD_PB21 0x111A
+#define HDMI_FC_GMD_PB22 0x111B
+#define HDMI_FC_GMD_PB23 0x111C
+#define HDMI_FC_GMD_PB24 0x111D
+#define HDMI_FC_GMD_PB25 0x111E
+#define HDMI_FC_GMD_PB26 0x111F
+#define HDMI_FC_GMD_PB27 0x1120
+
+#define HDMI_FC_DBGFORCE 0x1200
+#define HDMI_FC_DBGAUD0CH0 0x1201
+#define HDMI_FC_DBGAUD1CH0 0x1202
+#define HDMI_FC_DBGAUD2CH0 0x1203
+#define HDMI_FC_DBGAUD0CH1 0x1204
+#define HDMI_FC_DBGAUD1CH1 0x1205
+#define HDMI_FC_DBGAUD2CH1 0x1206
+#define HDMI_FC_DBGAUD0CH2 0x1207
+#define HDMI_FC_DBGAUD1CH2 0x1208
+#define HDMI_FC_DBGAUD2CH2 0x1209
+#define HDMI_FC_DBGAUD0CH3 0x120A
+#define HDMI_FC_DBGAUD1CH3 0x120B
+#define HDMI_FC_DBGAUD2CH3 0x120C
+#define HDMI_FC_DBGAUD0CH4 0x120D
+#define HDMI_FC_DBGAUD1CH4 0x120E
+#define HDMI_FC_DBGAUD2CH4 0x120F
+#define HDMI_FC_DBGAUD0CH5 0x1210
+#define HDMI_FC_DBGAUD1CH5 0x1211
+#define HDMI_FC_DBGAUD2CH5 0x1212
+#define HDMI_FC_DBGAUD0CH6 0x1213
+#define HDMI_FC_DBGAUD1CH6 0x1214
+#define HDMI_FC_DBGAUD2CH6 0x1215
+#define HDMI_FC_DBGAUD0CH7 0x1216
+#define HDMI_FC_DBGAUD1CH7 0x1217
+#define HDMI_FC_DBGAUD2CH7 0x1218
+#define HDMI_FC_DBGTMDS0 0x1219
+#define HDMI_FC_DBGTMDS1 0x121A
+#define HDMI_FC_DBGTMDS2 0x121B
+
+/* HDMI Source PHY Registers */
+#define HDMI_PHY_CONF0 0x3000
+#define HDMI_PHY_TST0 0x3001
+#define HDMI_PHY_TST1 0x3002
+#define HDMI_PHY_TST2 0x3003
+#define HDMI_PHY_STAT0 0x3004
+#define HDMI_PHY_INT0 0x3005
+#define HDMI_PHY_MASK0 0x3006
+#define HDMI_PHY_POL0 0x3007
+
+/* HDMI Master PHY Registers */
+#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020
+#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021
+#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022
+#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023
+#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024
+#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025
+#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026
+#define HDMI_PHY_I2CM_INT_ADDR 0x3027
+#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028
+#define HDMI_PHY_I2CM_DIV_ADDR 0x3029
+#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032
+
+/* Audio Sampler Registers */
+#define HDMI_AUD_CONF0 0x3100
+#define HDMI_AUD_CONF1 0x3101
+#define HDMI_AUD_INT 0x3102
+#define HDMI_AUD_CONF2 0x3103
+#define HDMI_AUD_N1 0x3200
+#define HDMI_AUD_N2 0x3201
+#define HDMI_AUD_N3 0x3202
+#define HDMI_AUD_CTS1 0x3203
+#define HDMI_AUD_CTS2 0x3204
+#define HDMI_AUD_CTS3 0x3205
+#define HDMI_AUD_INPUTCLKFS 0x3206
+#define HDMI_AUD_SPDIFINT 0x3302
+#define HDMI_AUD_CONF0_HBR 0x3400
+#define HDMI_AUD_HBR_STATUS 0x3401
+#define HDMI_AUD_HBR_INT 0x3402
+#define HDMI_AUD_HBR_POL 0x3403
+#define HDMI_AUD_HBR_MASK 0x3404
+
+/* Generic Parallel Audio Interface Registers */
+/* Not used as GPAUD interface is not enabled in hw */
+#define HDMI_GP_CONF0 0x3500
+#define HDMI_GP_CONF1 0x3501
+#define HDMI_GP_CONF2 0x3502
+#define HDMI_GP_STAT 0x3503
+#define HDMI_GP_INT 0x3504
+#define HDMI_GP_MASK 0x3505
+#define HDMI_GP_POL 0x3506
+
+/* Audio DMA Registers */
+#define HDMI_AHB_DMA_CONF0 0x3600
+#define HDMI_AHB_DMA_START 0x3601
+#define HDMI_AHB_DMA_STOP 0x3602
+#define HDMI_AHB_DMA_THRSLD 0x3603
+#define HDMI_AHB_DMA_STRADDR0 0x3604
+#define HDMI_AHB_DMA_STRADDR1 0x3605
+#define HDMI_AHB_DMA_STRADDR2 0x3606
+#define HDMI_AHB_DMA_STRADDR3 0x3607
+#define HDMI_AHB_DMA_STPADDR0 0x3608
+#define HDMI_AHB_DMA_STPADDR1 0x3609
+#define HDMI_AHB_DMA_STPADDR2 0x360a
+#define HDMI_AHB_DMA_STPADDR3 0x360b
+#define HDMI_AHB_DMA_BSTADDR0 0x360c
+#define HDMI_AHB_DMA_BSTADDR1 0x360d
+#define HDMI_AHB_DMA_BSTADDR2 0x360e
+#define HDMI_AHB_DMA_BSTADDR3 0x360f
+#define HDMI_AHB_DMA_MBLENGTH0 0x3610
+#define HDMI_AHB_DMA_MBLENGTH1 0x3611
+#define HDMI_AHB_DMA_STAT 0x3612
+#define HDMI_AHB_DMA_INT 0x3613
+#define HDMI_AHB_DMA_MASK 0x3614
+#define HDMI_AHB_DMA_POL 0x3615
+#define HDMI_AHB_DMA_CONF1 0x3616
+#define HDMI_AHB_DMA_BUFFSTAT 0x3617
+#define HDMI_AHB_DMA_BUFFINT 0x3618
+#define HDMI_AHB_DMA_BUFFMASK 0x3619
+#define HDMI_AHB_DMA_BUFFPOL 0x361a
+
+/* Main Controller Registers */
+#define HDMI_MC_SFRDIV 0x4000
+#define HDMI_MC_CLKDIS 0x4001
+#define HDMI_MC_SWRSTZ 0x4002
+#define HDMI_MC_OPCTRL 0x4003
+#define HDMI_MC_FLOWCTRL 0x4004
+#define HDMI_MC_PHYRSTZ 0x4005
+#define HDMI_MC_LOCKONCLOCK 0x4006
+#define HDMI_MC_HEACPHY_RST 0x4007
+
+/* Color Space Converter Registers */
+#define HDMI_CSC_CFG 0x4100
+#define HDMI_CSC_SCALE 0x4101
+#define HDMI_CSC_COEF_A1_MSB 0x4102
+#define HDMI_CSC_COEF_A1_LSB 0x4103
+#define HDMI_CSC_COEF_A2_MSB 0x4104
+#define HDMI_CSC_COEF_A2_LSB 0x4105
+#define HDMI_CSC_COEF_A3_MSB 0x4106
+#define HDMI_CSC_COEF_A3_LSB 0x4107
+#define HDMI_CSC_COEF_A4_MSB 0x4108
+#define HDMI_CSC_COEF_A4_LSB 0x4109
+#define HDMI_CSC_COEF_B1_MSB 0x410A
+#define HDMI_CSC_COEF_B1_LSB 0x410B
+#define HDMI_CSC_COEF_B2_MSB 0x410C
+#define HDMI_CSC_COEF_B2_LSB 0x410D
+#define HDMI_CSC_COEF_B3_MSB 0x410E
+#define HDMI_CSC_COEF_B3_LSB 0x410F
+#define HDMI_CSC_COEF_B4_MSB 0x4110
+#define HDMI_CSC_COEF_B4_LSB 0x4111
+#define HDMI_CSC_COEF_C1_MSB 0x4112
+#define HDMI_CSC_COEF_C1_LSB 0x4113
+#define HDMI_CSC_COEF_C2_MSB 0x4114
+#define HDMI_CSC_COEF_C2_LSB 0x4115
+#define HDMI_CSC_COEF_C3_MSB 0x4116
+#define HDMI_CSC_COEF_C3_LSB 0x4117
+#define HDMI_CSC_COEF_C4_MSB 0x4118
+#define HDMI_CSC_COEF_C4_LSB 0x4119
+
+/* HDCP Interrupt Registers */
+#define HDMI_A_APIINTCLR 0x5006
+#define HDMI_A_APIINTSTAT 0x5007
+#define HDMI_A_APIINTMSK 0x5008
+
+/* CEC Engine Registers */
+#define HDMI_CEC_CTRL 0x7D00
+#define HDMI_CEC_STAT 0x7D01
+#define HDMI_CEC_MASK 0x7D02
+#define HDMI_CEC_POLARITY 0x7D03
+#define HDMI_CEC_INT 0x7D04
+#define HDMI_CEC_ADDR_L 0x7D05
+#define HDMI_CEC_ADDR_H 0x7D06
+#define HDMI_CEC_TX_CNT 0x7D07
+#define HDMI_CEC_RX_CNT 0x7D08
+#define HDMI_CEC_TX_DATA0 0x7D10
+#define HDMI_CEC_TX_DATA1 0x7D11
+#define HDMI_CEC_TX_DATA2 0x7D12
+#define HDMI_CEC_TX_DATA3 0x7D13
+#define HDMI_CEC_TX_DATA4 0x7D14
+#define HDMI_CEC_TX_DATA5 0x7D15
+#define HDMI_CEC_TX_DATA6 0x7D16
+#define HDMI_CEC_TX_DATA7 0x7D17
+#define HDMI_CEC_TX_DATA8 0x7D18
+#define HDMI_CEC_TX_DATA9 0x7D19
+#define HDMI_CEC_TX_DATA10 0x7D1a
+#define HDMI_CEC_TX_DATA11 0x7D1b
+#define HDMI_CEC_TX_DATA12 0x7D1c
+#define HDMI_CEC_TX_DATA13 0x7D1d
+#define HDMI_CEC_TX_DATA14 0x7D1e
+#define HDMI_CEC_TX_DATA15 0x7D1f
+#define HDMI_CEC_RX_DATA0 0x7D20
+#define HDMI_CEC_RX_DATA1 0x7D21
+#define HDMI_CEC_RX_DATA2 0x7D22
+#define HDMI_CEC_RX_DATA3 0x7D23
+#define HDMI_CEC_RX_DATA4 0x7D24
+#define HDMI_CEC_RX_DATA5 0x7D25
+#define HDMI_CEC_RX_DATA6 0x7D26
+#define HDMI_CEC_RX_DATA7 0x7D27
+#define HDMI_CEC_RX_DATA8 0x7D28
+#define HDMI_CEC_RX_DATA9 0x7D29
+#define HDMI_CEC_RX_DATA10 0x7D2a
+#define HDMI_CEC_RX_DATA11 0x7D2b
+#define HDMI_CEC_RX_DATA12 0x7D2c
+#define HDMI_CEC_RX_DATA13 0x7D2d
+#define HDMI_CEC_RX_DATA14 0x7D2e
+#define HDMI_CEC_RX_DATA15 0x7D2f
+#define HDMI_CEC_LOCK 0x7D30
+#define HDMI_CEC_WKUPCTRL 0x7D31
+
+/* I2C Master Registers (E-DDC) */
+#define HDMI_I2CM_SLAVE 0x7E00
+#define HDMI_I2CM_ADDRESS 0x7E01
+#define HDMI_I2CM_DATAO 0x7E02
+#define HDMI_I2CM_DATAI 0x7E03
+#define HDMI_I2CM_OPERATION 0x7E04
+#define HDMI_I2CM_INT 0x7E05
+#define HDMI_I2CM_CTLINT 0x7E06
+#define HDMI_I2CM_DIV 0x7E07
+#define HDMI_I2CM_SEGADDR 0x7E08
+#define HDMI_I2CM_SOFTRSTZ 0x7E09
+#define HDMI_I2CM_SEGPTR 0x7E0A
+#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B
+#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C
+#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D
+#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E
+#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F
+#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10
+#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11
+#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
+
+/* Random Number Generator Registers (RNG) */
+#define HDMI_RNG_BASE 0x8000
+
+
+/*
+ * Register field definitions
+ */
+enum {
+/* IH_FC_INT2 field values */
+ HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
+ HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_FC_STAT2 field values */
+ HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03,
+ HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_PHY_STAT0 field values */
+ HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20,
+ HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10,
+ HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8,
+ HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4,
+ HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
+ HDMI_IH_PHY_STAT0_HPD = 0x1,
+
+/* IH_CEC_STAT0 field values */
+ HDMI_IH_CEC_STAT0_WAKEUP = 0x40,
+ HDMI_IH_CEC_STAT0_ERROR_FOLL = 0x20,
+ HDMI_IH_CEC_STAT0_ERROR_INIT = 0x10,
+ HDMI_IH_CEC_STAT0_ARB_LOST = 0x8,
+ HDMI_IH_CEC_STAT0_NACK = 0x4,
+ HDMI_IH_CEC_STAT0_EOM = 0x2,
+ HDMI_IH_CEC_STAT0_DONE = 0x1,
+
+
+/* IH_MUTE_I2CMPHY_STAT0 field values */
+ HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
+ HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
+
+/* IH_PHY_STAT0 field values */
+ HDMI_IH_MUTE_PHY_STAT0_RX_SENSE3 = 0x20,
+ HDMI_IH_MUTE_PHY_STAT0_RX_SENSE2 = 0x10,
+ HDMI_IH_MUTE_PHY_STAT0_RX_SENSE1 = 0x8,
+ HDMI_IH_MUTE_PHY_STAT0_RX_SENSE0 = 0x4,
+ HDMI_IH_MUTE_PHY_STAT0_TX_PHY_LOCK = 0x2,
+ HDMI_IH_MUTE_PHY_STAT0_HPD = 0x1,
+
+/* IH_AHBDMAAUD_STAT0 field values */
+ HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
+ HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
+ HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08,
+ HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04,
+ HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
+ HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
+
+/* IH_MUTE_FC_STAT2 field values */
+ HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03,
+ HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_MUTE_AHBDMAAUD_STAT0 field values */
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
+
+/* IH_MUTE field values */
+ HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2,
+ HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1,
+
+/* TX_INVID0 field values */
+ HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80,
+ HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80,
+ HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00,
+ HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F,
+ HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0,
+
+/* TX_INSTUFFING field values */
+ HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4,
+ HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4,
+ HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0,
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2,
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2,
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0,
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1,
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1,
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0,
+
+/* VP_PR_CD field values */
+ HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0,
+ HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4,
+ HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F,
+ HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0,
+
+/* VP_STUFF field values */
+ HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20,
+ HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5,
+ HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10,
+ HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4,
+ HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8,
+ HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3,
+ HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4,
+ HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4,
+ HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0,
+ HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2,
+ HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2,
+ HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0,
+ HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1,
+ HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1,
+ HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0,
+
+/* VP_CONF field values */
+ HDMI_VP_CONF_BYPASS_EN_MASK = 0x40,
+ HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40,
+ HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00,
+ HDMI_VP_CONF_PP_EN_ENMASK = 0x20,
+ HDMI_VP_CONF_PP_EN_ENABLE = 0x20,
+ HDMI_VP_CONF_PP_EN_DISABLE = 0x00,
+ HDMI_VP_CONF_PR_EN_MASK = 0x10,
+ HDMI_VP_CONF_PR_EN_ENABLE = 0x10,
+ HDMI_VP_CONF_PR_EN_DISABLE = 0x00,
+ HDMI_VP_CONF_YCC422_EN_MASK = 0x8,
+ HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8,
+ HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0,
+ HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4,
+ HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4,
+ HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0,
+ HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3,
+ HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3,
+ HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1,
+ HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0,
+
+/* VP_REMAP field values */
+ HDMI_VP_REMAP_MASK = 0x3,
+ HDMI_VP_REMAP_YCC422_24bit = 0x2,
+ HDMI_VP_REMAP_YCC422_20bit = 0x1,
+ HDMI_VP_REMAP_YCC422_16bit = 0x0,
+
+/* FC_INVIDCONF field values */
+ HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80,
+ HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80,
+ HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00,
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40,
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40,
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20,
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20,
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
+ HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10,
+ HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10,
+ HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00,
+ HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8,
+ HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8,
+ HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0,
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2,
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2,
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0,
+ HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1,
+ HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1,
+ HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0,
+
+/* FC_AUDICONF0 field values */
+ HDMI_FC_AUDICONF0_CC_OFFSET = 4,
+ HDMI_FC_AUDICONF0_CC_MASK = 0x70,
+ HDMI_FC_AUDICONF0_CT_OFFSET = 0,
+ HDMI_FC_AUDICONF0_CT_MASK = 0xF,
+
+/* FC_AUDICONF1 field values */
+ HDMI_FC_AUDICONF1_SS_OFFSET = 3,
+ HDMI_FC_AUDICONF1_SS_MASK = 0x18,
+ HDMI_FC_AUDICONF1_SF_OFFSET = 0,
+ HDMI_FC_AUDICONF1_SF_MASK = 0x7,
+
+/* FC_AUDICONF3 field values */
+ HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5,
+ HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60,
+ HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4,
+ HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10,
+ HDMI_FC_AUDICONF3_LSV_OFFSET = 0,
+ HDMI_FC_AUDICONF3_LSV_MASK = 0xF,
+
+/* FC_AUDSCHNLS0 field values */
+ HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30,
+ HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01,
+
+/* FC_AUDSCHNLS3-6 field values */
+ HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0,
+ HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0,
+
+ HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0,
+ HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0,
+
+/* HDMI_FC_AUDSCHNLS7 field values */
+ HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
+
+/* HDMI_FC_AUDSCHNLS8 field values */
+ HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
+ HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0,
+
+/* FC_AUDSCONF field values */
+ HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0,
+ HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4,
+ HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1,
+ HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0,
+ HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1,
+ HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0,
+
+/* FC_STAT2 field values */
+ HDMI_FC_STAT2_OVERFLOW_MASK = 0x03,
+ HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_INT2 field values */
+ HDMI_FC_INT2_OVERFLOW_MASK = 0x03,
+ HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_MASK2 field values */
+ HDMI_FC_MASK2_OVERFLOW_MASK = 0x03,
+ HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_PRCONF field values */
+ HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0,
+ HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4,
+ HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F,
+ HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0,
+
+/* FC_AVICONF0-FC_AVICONF3 field values */
+ HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03,
+ HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00,
+ HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01,
+ HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02,
+ HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40,
+ HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40,
+ HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00,
+ HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C,
+ HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00,
+ HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04,
+ HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08,
+ HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C,
+ HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30,
+ HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10,
+ HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20,
+ HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00,
+
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F,
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08,
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09,
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A,
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B,
+ HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30,
+ HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00,
+ HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10,
+ HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20,
+ HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0,
+ HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00,
+ HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40,
+ HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80,
+ HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0,
+
+ HDMI_FC_AVICONF2_SCALING_MASK = 0x03,
+ HDMI_FC_AVICONF2_SCALING_NONE = 0x00,
+ HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01,
+ HDMI_FC_AVICONF2_SCALING_VERT = 0x02,
+ HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03,
+ HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C,
+ HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00,
+ HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04,
+ HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40,
+ HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80,
+ HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00,
+ HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80,
+
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03,
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00,
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01,
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02,
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03,
+ HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C,
+ HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
+ HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
+
+/* FC_DBGFORCE field values */
+ HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
+ HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
+
+/* PHY_CONF0 field values */
+ HDMI_PHY_CONF0_PDZ_MASK = 0x80,
+ HDMI_PHY_CONF0_PDZ_OFFSET = 7,
+ HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
+ HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
+ HDMI_PHY_CONF0_SPARECTRL = 0x20,
+ HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
+ HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
+ HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
+ HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3,
+ HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4,
+ HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2,
+ HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2,
+ HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1,
+ HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1,
+ HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0,
+
+/* PHY_TST0 field values */
+ HDMI_PHY_TST0_TSTCLR_MASK = 0x20,
+ HDMI_PHY_TST0_TSTCLR_OFFSET = 5,
+ HDMI_PHY_TST0_TSTEN_MASK = 0x10,
+ HDMI_PHY_TST0_TSTEN_OFFSET = 4,
+ HDMI_PHY_TST0_TSTCLK_MASK = 0x1,
+ HDMI_PHY_TST0_TSTCLK_OFFSET = 0,
+
+/* PHY_STAT0 field values */
+ HDMI_PHY_RX_SENSE3 = 0x80,
+ HDMI_PHY_RX_SENSE2 = 0x40,
+ HDMI_PHY_RX_SENSE1 = 0x20,
+ HDMI_PHY_RX_SENSE0 = 0x10,
+ HDMI_PHY_HPD = 0x02,
+ HDMI_PHY_TX_PHY_LOCK = 0x01,
+
+/* PHY_I2CM_SLAVE_ADDR field values */
+ HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
+ HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
+
+/* PHY_I2CM_OPERATION_ADDR field values */
+ HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10,
+ HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1,
+
+/* HDMI_PHY_I2CM_INT_ADDR */
+ HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08,
+ HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04,
+
+/* HDMI_PHY_I2CM_CTLINT_ADDR */
+ HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80,
+ HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40,
+ HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
+ HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
+
+/* AUD_CTS3 field values */
+ HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
+ HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
+ HDMI_AUD_CTS3_N_SHIFT_1 = 0,
+ HDMI_AUD_CTS3_N_SHIFT_16 = 0x20,
+ HDMI_AUD_CTS3_N_SHIFT_32 = 0x40,
+ HDMI_AUD_CTS3_N_SHIFT_64 = 0x60,
+ HDMI_AUD_CTS3_N_SHIFT_128 = 0x80,
+ HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0,
+ /* note that the CTS3 MANUAL bit has been removed
+ from our part. Can't set it, will read as 0. */
+ HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
+ HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
+
+/* AHB_DMA_CONF0 field values */
+ HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
+ HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
+ HDMI_AHB_DMA_CONF0_HBR = 0x10,
+ HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3,
+ HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08,
+ HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1,
+ HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06,
+ HDMI_AHB_DMA_CONF0_INCR4 = 0x0,
+ HDMI_AHB_DMA_CONF0_INCR8 = 0x2,
+ HDMI_AHB_DMA_CONF0_INCR16 = 0x4,
+ HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1,
+
+/* HDMI_AHB_DMA_START field values */
+ HDMI_AHB_DMA_START_START_OFFSET = 0,
+ HDMI_AHB_DMA_START_START_MASK = 0x01,
+
+/* HDMI_AHB_DMA_STOP field values */
+ HDMI_AHB_DMA_STOP_STOP_OFFSET = 0,
+ HDMI_AHB_DMA_STOP_STOP_MASK = 0x01,
+
+/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */
+ HDMI_AHB_DMA_DONE = 0x80,
+ HDMI_AHB_DMA_RETRY_SPLIT = 0x40,
+ HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20,
+ HDMI_AHB_DMA_ERROR = 0x10,
+ HDMI_AHB_DMA_FIFO_THREMPTY = 0x04,
+ HDMI_AHB_DMA_FIFO_FULL = 0x02,
+ HDMI_AHB_DMA_FIFO_EMPTY = 0x01,
+
+/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT, AHB_DMA_BUFFMASK, AHB_DMA_BUFFPOL field values */
+ HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02,
+ HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01,
+
+/* MC_CLKDIS field values */
+ HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40,
+ HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20,
+ HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10,
+ HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
+ HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4,
+ HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2,
+ HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1,
+
+/* MC_SWRSTZ field values */
+ HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02,
+
+/* MC_FLOWCTRL field values */
+ HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1,
+ HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1,
+ HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
+
+/* MC_PHYRSTZ field values */
+ HDMI_MC_PHYRSTZ_ASSERT = 0x0,
+ HDMI_MC_PHYRSTZ_DEASSERT = 0x1,
+
+/* MC_HEACPHY_RST field values */
+ HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
+ HDMI_MC_HEACPHY_RST_DEASSERT = 0x0,
+
+/* CSC_CFG field values */
+ HDMI_CSC_CFG_INTMODE_MASK = 0x30,
+ HDMI_CSC_CFG_INTMODE_OFFSET = 4,
+ HDMI_CSC_CFG_INTMODE_DISABLE = 0x00,
+ HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10,
+ HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20,
+ HDMI_CSC_CFG_DECMODE_MASK = 0x3,
+ HDMI_CSC_CFG_DECMODE_OFFSET = 0,
+ HDMI_CSC_CFG_DECMODE_DISABLE = 0x0,
+ HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1,
+ HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2,
+ HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3,
+
+/* CSC_SCALE field values */
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0,
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00,
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50,
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60,
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70,
+ HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03,
+
+/* I2CM_OPERATION field values */
+ HDMI_I2CM_OPERATION_WRITE = 0x10,
+ HDMI_I2CM_OPERATION_READ_EXT = 0x2,
+ HDMI_I2CM_OPERATION_READ = 0x1,
+
+/* HDMI_I2CM_INT */
+ HDMI_I2CM_INT_DONE_POL = 0x08,
+ HDMI_I2CM_INT_DONE_MASK = 0x04,
+
+/* HDMI_I2CM_CTLINT */
+ HDMI_I2CM_CTLINT_NAC_POL = 0x80,
+ HDMI_I2CM_CTLINT_NAC_MASK = 0x40,
+ HDMI_I2CM_CTLINT_ARBITRATION_POL = 0x08,
+ HDMI_I2CM_CTLINT_ARBITRATION_MASK = 0x04,
+
+};
+
+enum imx_hdmi_type {
+ IMX6DL_HDMI,
+ IMX6Q_HDMI,
+};
+
+/* IOCTL commands */
+#define HDMI_IOC_MAGIC 'H'
+
+#define HDMI_IOC_GET_RESOURCE _IO(HDMI_IOC_MAGIC, 0)
+#define HDMI_IOC_GET_CPU_TYPE _IO(HDMI_IOC_MAGIC, 1)
+
+
+#endif /* __MXC_HDMI_H__ */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 802eb3361a0a..a7707247cfb6 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1935,3 +1935,23 @@ void __init boot_cpu_state_init(void)
{
per_cpu_ptr(&cpuhp_state, smp_processor_id())->state = CPUHP_ONLINE;
}
+
+static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+
+void idle_notifier_register(struct notifier_block *n)
+{
+ atomic_notifier_chain_register(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+ atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_unregister);
+
+void idle_notifier_call_chain(unsigned long val)
+{
+ atomic_notifier_call_chain(&idle_notifier, val, NULL);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_call_chain);
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index cb771c76682e..4704f654e7c3 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -321,15 +321,15 @@ static inline struct sugov_tunables *to_sugov_tunables(struct gov_attr_set *attr
return container_of(attr_set, struct sugov_tunables, attr_set);
}
-static ssize_t rate_limit_us_show(struct gov_attr_set *attr_set, char *buf)
+static ssize_t show_rate_limit_us(struct gov_attr_set *attr_set, char *buf)
{
struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
return sprintf(buf, "%u\n", tunables->rate_limit_us);
}
-static ssize_t rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf,
- size_t count)
+static ssize_t store_rate_limit_us(struct gov_attr_set *attr_set,
+ const char *buf, size_t count)
{
struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
struct sugov_policy *sg_policy;
@@ -346,7 +346,7 @@ static ssize_t rate_limit_us_store(struct gov_attr_set *attr_set, const char *bu
return count;
}
-static struct governor_attr rate_limit_us = __ATTR_RW(rate_limit_us);
+gov_attr_rw(rate_limit_us);
static struct attribute *sugov_attributes[] = {
&rate_limit_us.attr,
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index dae1a45be504..08333d1d73b2 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -717,8 +717,6 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
*/
delta = next_tick - basemono;
if (delta <= (u64)TICK_NSEC) {
- tick.tv64 = 0;
-
/*
* Tell the timer code that the base is not idle, i.e. undo
* the effect of get_next_timer_interrupt():
@@ -728,23 +726,8 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
* We've not stopped the tick yet, and there's a timer in the
* next period, so no point in stopping it either, bail.
*/
- if (!ts->tick_stopped)
- goto out;
-
- /*
- * If, OTOH, we did stop it, but there's a pending (expired)
- * timer reprogram the timer hardware to fire now.
- *
- * We will not restart the tick proper, just prod the timer
- * hardware into firing an interrupt to process the pending
- * timers. Just like tick_irq_exit() will not restart the tick
- * for 'normal' interrupts.
- *
- * Only once we exit the idle loop will we re-enable the tick,
- * see tick_nohz_idle_exit().
- */
- if (delta == 0) {
- tick_nohz_restart(ts, now);
+ if (!ts->tick_stopped) {
+ tick.tv64 = 0;
goto out;
}
}
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 8eb58c709b14..99abc917427f 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -5,6 +5,7 @@
* Based on:
* imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
* mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * imx-pcm-dma.c, Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
* ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
* Copyright (C) 2006 Applied Data Systems
*
@@ -28,13 +29,6 @@
#include <sound/dmaengine_pcm.h>
-struct dmaengine_pcm_runtime_data {
- struct dma_chan *dma_chan;
- dma_cookie_t cookie;
-
- unsigned int pos;
-};
-
static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
const struct snd_pcm_substream *substream)
{
@@ -171,7 +165,10 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
if (!desc)
return -ENOMEM;
- desc->callback = dmaengine_pcm_dma_complete;
+ if (prtd->callback)
+ desc->callback = prtd->callback;
+ else
+ desc->callback = dmaengine_pcm_dma_complete;
desc->callback_param = substream;
prtd->cookie = dmaengine_submit(desc);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c67667bb970f..d5405660ea4a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -523,6 +523,9 @@ config SND_SOC_ES8328_SPI
tristate
select SND_SOC_ES8328
+config SND_SOC_FSL_MQS
+ tristate
+
config SND_SOC_GTM601
tristate 'GTM601 UMTS modem audio codec'
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 958cd4912fbc..1861d9fd3370 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -64,6 +64,7 @@ snd-soc-dmic-objs := dmic.o
snd-soc-es8328-objs := es8328.o
snd-soc-es8328-i2c-objs := es8328-i2c.o
snd-soc-es8328-spi-objs := es8328-spi.o
+snd-soc-fsl-mqs-objs := fsl_mqs.o
snd-soc-gtm601-objs := gtm601.o
snd-soc-hdac-hdmi-objs := hdac_hdmi.o
snd-soc-ics43432-objs := ics43432.o
@@ -289,6 +290,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
+obj-$(CONFIG_SND_SOC_FSL_MQS) += snd-soc-fsl-mqs.o
obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o
obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c
index b4d87379d2bc..7d2c921d912c 100644
--- a/sound/soc/codecs/cs42xx8.c
+++ b/sound/soc/codecs/cs42xx8.c
@@ -1,7 +1,7 @@
/*
* Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver
*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
*
* Author: Nicolin Chen <Guangyu.Chen@freescale.com>
*
@@ -32,8 +32,7 @@ static const char *const cs42xx8_supply_names[CS42XX8_NUM_SUPPLIES] = {
#define CS42XX8_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S20_3LE | \
- SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE)
+ SNDRV_PCM_FMTBIT_S24_LE)
/* codec private data */
struct cs42xx8_priv {
@@ -45,6 +44,7 @@ struct cs42xx8_priv {
bool slave_mode;
unsigned long sysclk;
u32 tx_channels;
+ int rate[2];
};
/* -127.5dB to 0dB with step of 0.5dB */
@@ -128,7 +128,6 @@ static const struct snd_soc_dapm_widget cs42xx8_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("AIN2L"),
SND_SOC_DAPM_INPUT("AIN2R"),
- SND_SOC_DAPM_SUPPLY("PWR", CS42XX8_PWRCTL, 0, 1, NULL, 0),
};
static const struct snd_soc_dapm_widget cs42xx8_adc3_dapm_widgets[] = {
@@ -142,53 +141,43 @@ static const struct snd_soc_dapm_route cs42xx8_dapm_routes[] = {
/* Playback */
{ "AOUT1L", NULL, "DAC1" },
{ "AOUT1R", NULL, "DAC1" },
- { "DAC1", NULL, "PWR" },
{ "AOUT2L", NULL, "DAC2" },
{ "AOUT2R", NULL, "DAC2" },
- { "DAC2", NULL, "PWR" },
{ "AOUT3L", NULL, "DAC3" },
{ "AOUT3R", NULL, "DAC3" },
- { "DAC3", NULL, "PWR" },
{ "AOUT4L", NULL, "DAC4" },
{ "AOUT4R", NULL, "DAC4" },
- { "DAC4", NULL, "PWR" },
/* Capture */
{ "ADC1", NULL, "AIN1L" },
{ "ADC1", NULL, "AIN1R" },
- { "ADC1", NULL, "PWR" },
{ "ADC2", NULL, "AIN2L" },
{ "ADC2", NULL, "AIN2R" },
- { "ADC2", NULL, "PWR" },
};
static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = {
/* Capture */
{ "ADC3", NULL, "AIN3L" },
{ "ADC3", NULL, "AIN3R" },
- { "ADC3", NULL, "PWR" },
};
struct cs42xx8_ratios {
- unsigned int ratio;
- unsigned char speed;
- unsigned char mclk;
+ unsigned int mfreq;
+ unsigned int min_mclk;
+ unsigned int max_mclk;
+ unsigned int ratio[3];
};
static const struct cs42xx8_ratios cs42xx8_ratios[] = {
- { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) },
- { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) },
- { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) },
- { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) },
- { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) },
- { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) },
- { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) },
- { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) },
- { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) }
+ { 0, 1029000, 12800000, {256, 128, 64} },
+ { 2, 1536000, 19200000, {384, 192, 96} },
+ { 4, 2048000, 25600000, {512, 256, 128} },
+ { 6, 3072000, 38400000, {768, 384, 192} },
+ { 8, 4096000, 51200000, {1024, 512, 256} },
};
static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai,
@@ -255,15 +244,70 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- u32 ratio = cs42xx8->sysclk / params_rate(params);
+ u32 rate = params_rate(params);
+ u32 ratio_tx, ratio_rx;
+ u32 rate_tx, rate_rx;
+ u32 fm_tx, fm_rx;
u32 i, fm, val, mask;
if (tx)
cs42xx8->tx_channels = params_channels(params);
- for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
- if (cs42xx8_ratios[i].ratio == ratio)
- break;
+ rate_tx = tx ? rate : cs42xx8->rate[0];
+ rate_rx = tx ? cs42xx8->rate[1] : rate;
+
+ ratio_tx = rate_tx > 0 ? cs42xx8->sysclk / rate_tx : 0;
+ ratio_rx = rate_rx > 0 ? cs42xx8->sysclk / rate_rx : 0;
+
+ if (cs42xx8->slave_mode) {
+ fm_rx = CS42XX8_FM_AUTO;
+ fm_tx = CS42XX8_FM_AUTO;
+ } else {
+ if (rate_tx < 50000)
+ fm_tx = CS42XX8_FM_SINGLE;
+ else if (rate_tx > 50000 && rate_tx < 100000)
+ fm_tx = CS42XX8_FM_DOUBLE;
+ else if (rate_tx > 100000 && rate_tx < 200000)
+ fm_tx = CS42XX8_FM_QUAD;
+ else {
+ dev_err(codec->dev, "unsupported sample rate or rate combine\n");
+ return -EINVAL;
+ }
+
+ if (rate_rx < 50000)
+ fm_rx = CS42XX8_FM_SINGLE;
+ else if (rate_rx > 50000 && rate_rx < 100000)
+ fm_rx = CS42XX8_FM_DOUBLE;
+ else if (rate_rx > 100000 && rate_rx < 200000)
+ fm_rx = CS42XX8_FM_QUAD;
+ else {
+ dev_err(codec->dev, "unsupported sample rate or rate combine\n");
+ return -EINVAL;
+ }
+ }
+
+ fm = tx ? fm_tx : fm_rx;
+
+ if (fm == CS42XX8_FM_AUTO) {
+ for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
+ if ((ratio_tx > 0 ? (cs42xx8_ratios[i].ratio[0] == ratio_tx ||
+ cs42xx8_ratios[i].ratio[1] == ratio_tx ||
+ cs42xx8_ratios[i].ratio[2] == ratio_tx) : true) &&
+ (ratio_rx > 0 ? (cs42xx8_ratios[i].ratio[0] == ratio_rx ||
+ cs42xx8_ratios[i].ratio[1] == ratio_rx ||
+ cs42xx8_ratios[i].ratio[2] == ratio_rx) : true) &&
+ cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk &&
+ cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk)
+ break;
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
+ if ((ratio_tx > 0 ? (cs42xx8_ratios[i].ratio[fm_tx] == ratio_tx) : true) &&
+ (ratio_rx > 0 ? (cs42xx8_ratios[i].ratio[fm_rx] == ratio_rx) : true) &&
+ cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk &&
+ cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk)
+ break;
+ }
}
if (i == ARRAY_SIZE(cs42xx8_ratios)) {
@@ -271,10 +315,10 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- mask = CS42XX8_FUNCMOD_MFREQ_MASK;
- val = cs42xx8_ratios[i].mclk;
+ cs42xx8->rate[substream->stream] = rate;
- fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed;
+ mask = CS42XX8_FUNCMOD_MFREQ_MASK;
+ val = cs42xx8_ratios[i].mfreq;
regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask,
@@ -283,6 +327,22 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int cs42xx8_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+
+ cs42xx8->rate[substream->stream] = 0;
+
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
+ CS42XX8_FUNCMOD_xC_FM_MASK(tx),
+ CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO));
+ return 0;
+}
+
static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
@@ -300,6 +360,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = {
.set_fmt = cs42xx8_set_dai_fmt,
.set_sysclk = cs42xx8_set_dai_sysclk,
.hw_params = cs42xx8_hw_params,
+ .hw_free = cs42xx8_hw_free,
.digital_mute = cs42xx8_digital_mute,
};
@@ -321,7 +382,6 @@ static struct snd_soc_dai_driver cs42xx8_dai = {
};
static const struct reg_default cs42xx8_reg[] = {
- { 0x01, 0x01 }, /* Chip I.D. and Revision Register */
{ 0x02, 0x00 }, /* Power Control */
{ 0x03, 0xF0 }, /* Functional Mode */
{ 0x04, 0x46 }, /* Interface Formats */
@@ -403,7 +463,8 @@ static int cs42xx8_codec_probe(struct snd_soc_codec *codec)
/* Mute all DAC channels */
regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, CS42XX8_DACMUTE_ALL);
-
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_PWRCTL,
+ CS42XX8_PWRCTL_PDN_MASK, 0);
return 0;
}
@@ -565,9 +626,14 @@ static int cs42xx8_runtime_resume(struct device *dev)
goto err_clk;
}
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_PWRCTL,
+ CS42XX8_PWRCTL_PDN_MASK, 1);
/* Make sure hardware reset done */
msleep(5);
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_PWRCTL,
+ CS42XX8_PWRCTL_PDN_MASK, 0);
+
regcache_cache_only(cs42xx8->regmap, false);
ret = regcache_sync(cs42xx8->regmap);
diff --git a/sound/soc/codecs/fsl_mqs.c b/sound/soc/codecs/fsl_mqs.c
new file mode 100644
index 000000000000..a8725fba6e99
--- /dev/null
+++ b/sound/soc/codecs/fsl_mqs.c
@@ -0,0 +1,228 @@
+/*
+ * ALSA SoC IMX MQS driver
+ *
+ * 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 <linux/clk.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+
+
+/* codec private data */
+struct fsl_mqs {
+ struct platform_device *pdev;
+ struct regmap *gpr;
+ struct clk *mclk;
+
+ unsigned long mclk_rate;
+
+ int sysclk_rate;
+ int bclk;
+ int lrclk;
+ char name[32];
+};
+
+#define FSL_MQS_RATES SNDRV_PCM_RATE_8000_192000
+#define FSL_MQS_FORMATS SNDRV_PCM_FMTBIT_S16_LE
+
+static int fsl_mqs_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct fsl_mqs *mqs_priv = snd_soc_codec_get_drvdata(codec);
+ int div, res;
+
+ mqs_priv->mclk_rate = clk_get_rate(mqs_priv->mclk);
+
+ mqs_priv->bclk = snd_soc_params_to_bclk(params);
+ mqs_priv->lrclk = params_rate(params);
+
+ /*
+ * mclk_rate / (oversample(32,64) * FS * 2 * divider ) = repeat_rate;
+ * if repeat_rate is 8, mqs can achieve better quality.
+ * oversample rate is fix to 32 currently.
+ */
+ div = mqs_priv->mclk_rate / (32 * 2 * mqs_priv->lrclk * 8);
+ res = mqs_priv->mclk_rate % (32 * 2 * mqs_priv->lrclk * 8);
+
+ if (res == 0 && div > 0 && div <= 256) {
+ regmap_update_bits(mqs_priv->gpr, IOMUXC_GPR2,
+ IMX6SX_GPR2_MQS_CLK_DIV_MASK, (div-1) << IMX6SX_GPR2_MQS_CLK_DIV_SHIFT);
+ regmap_update_bits(mqs_priv->gpr, IOMUXC_GPR2,
+ IMX6SX_GPR2_MQS_OVERSAMPLE_MASK, 0 << IMX6SX_GPR2_MQS_OVERSAMPLE_SHIFT);
+ } else
+ dev_err(&mqs_priv->pdev->dev, "can't get proper divider\n");
+
+ return 0;
+}
+
+static int fsl_mqs_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_LEFT_J:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fsl_mqs_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct fsl_mqs *mqs_priv = snd_soc_codec_get_drvdata(codec);
+
+ mqs_priv->sysclk_rate = freq;
+
+ return 0;
+}
+
+static int fsl_mqs_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct fsl_mqs *mqs_priv = snd_soc_codec_get_drvdata(codec);
+
+ regmap_update_bits(mqs_priv->gpr, IOMUXC_GPR2, IMX6SX_GPR2_MQS_EN_MASK,
+ 1 << IMX6SX_GPR2_MQS_EN_SHIFT);
+ return 0;
+}
+
+static void fsl_mqs_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct fsl_mqs *mqs_priv = snd_soc_codec_get_drvdata(codec);
+
+ regmap_update_bits(mqs_priv->gpr, IOMUXC_GPR2,
+ IMX6SX_GPR2_MQS_EN_MASK, 0);
+
+}
+
+
+static struct snd_soc_codec_driver soc_codec_fsl_mqs;
+
+static const struct snd_soc_dai_ops fsl_mqs_dai_ops = {
+ .startup = fsl_mqs_startup,
+ .shutdown = fsl_mqs_shutdown,
+ .hw_params = fsl_mqs_hw_params,
+ .set_fmt = fsl_mqs_set_dai_fmt,
+ .set_sysclk = fsl_mqs_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver fsl_mqs_dai = {
+ .name = "fsl-mqs-dai",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = FSL_MQS_RATES,
+ .formats = FSL_MQS_FORMATS,
+ },
+ .ops = &fsl_mqs_dai_ops,
+};
+
+static int fsl_mqs_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *gpr_np;
+ struct fsl_mqs *mqs_priv;
+ int ret = 0;
+
+ mqs_priv = devm_kzalloc(&pdev->dev, sizeof(*mqs_priv), GFP_KERNEL);
+ if (!mqs_priv)
+ return -ENOMEM;
+
+ mqs_priv->pdev = pdev;
+ strncpy(mqs_priv->name, np->name, sizeof(mqs_priv->name) - 1);
+
+ gpr_np = of_parse_phandle(np, "gpr", 0);
+ if (IS_ERR(gpr_np)) {
+ dev_err(&pdev->dev, "failed to get gpr node by phandle\n");
+ ret = PTR_ERR(gpr_np);
+ goto out;
+ }
+
+ mqs_priv->gpr = syscon_node_to_regmap(gpr_np);
+ if (IS_ERR(mqs_priv->gpr)) {
+ dev_err(&pdev->dev, "failed to get gpr regmap\n");
+ ret = PTR_ERR(mqs_priv->gpr);
+ goto out;
+ }
+
+ mqs_priv->mclk = devm_clk_get(&pdev->dev, "mclk");
+ if (IS_ERR(mqs_priv->mclk)) {
+ dev_err(&pdev->dev, "failed to get the clock: %ld\n",
+ PTR_ERR(mqs_priv->mclk));
+ goto out;
+ }
+
+ dev_set_drvdata(&pdev->dev, mqs_priv);
+
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_fsl_mqs,
+ &fsl_mqs_dai, 1);
+
+out:
+ if (!IS_ERR(gpr_np))
+ of_node_put(gpr_np);
+
+ return ret;
+}
+
+static int fsl_mqs_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static const struct of_device_id fsl_mqs_dt_ids[] = {
+ { .compatible = "fsl,imx6sx-mqs", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids);
+
+
+static struct platform_driver fsl_mqs_driver = {
+ .probe = fsl_mqs_probe,
+ .remove = fsl_mqs_remove,
+ .driver = {
+ .name = "fsl-mqs",
+ .of_match_table = fsl_mqs_dt_ids,
+ },
+};
+
+module_platform_driver(fsl_mqs_driver);
+
+MODULE_AUTHOR("shengjiu wang <shengjiu.wang@freescale.com>");
+MODULE_DESCRIPTION("MQS dummy codec driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform: fsl-mqs");
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 1589325855bc..5a2702edeb77 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -99,6 +99,13 @@ enum sgtl5000_micbias_resistor {
SGTL5000_MICBIAS_8K = 8,
};
+enum {
+ I2S_LRCLK_STRENGTH_DISABLE,
+ I2S_LRCLK_STRENGTH_LOW,
+ I2S_LRCLK_STRENGTH_MEDIUM,
+ I2S_LRCLK_STRENGTH_HIGH,
+};
+
/* sgtl5000 private structure in codec */
struct sgtl5000_priv {
int sysclk; /* sysclk rate */
@@ -111,6 +118,7 @@ struct sgtl5000_priv {
int revision;
u8 micbias_resistor;
u8 micbias_voltage;
+ u8 lrclk_strength;
};
/*
@@ -1089,6 +1097,7 @@ static int sgtl5000_enable_regulators(struct i2c_client *client)
static int sgtl5000_probe(struct snd_soc_codec *codec)
{
int ret;
+ u16 reg;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
/* power up sgtl5000 */
@@ -1118,7 +1127,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
SGTL5000_DAC_MUTE_RIGHT |
SGTL5000_DAC_MUTE_LEFT);
- snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f);
+ reg = ((sgtl5000->lrclk_strength) << SGTL5000_PAD_I2S_LRCLK_SHIFT | 0x5f);
+ snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, reg);
snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL,
SGTL5000_HP_ZCD_EN |
@@ -1347,6 +1357,13 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
}
}
+ sgtl5000->lrclk_strength = I2S_LRCLK_STRENGTH_LOW;
+ if (!of_property_read_u32(np, "lrclk-strength", &value)) {
+ if (value > I2S_LRCLK_STRENGTH_HIGH)
+ value = I2S_LRCLK_STRENGTH_LOW;
+ sgtl5000->lrclk_strength = value;
+ }
+
/* Ensure sgtl5000 will start with sane register values */
sgtl5000_fill_defaults(client);
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 5344f4aa8fde..db5676adc385 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -208,9 +208,28 @@ out:
return err;
}
+static int si476x_codec_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai) {
+ struct si476x_core *core = i2c_mfd_cell_to_core(dai->dev);
+
+ if (!si476x_core_is_powered_up(core))
+ si476x_core_set_power_state(core, SI476X_POWER_UP_FULL);
+ return 0;
+}
+
+static void si476x_codec_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai) {
+ struct si476x_core *core = i2c_mfd_cell_to_core(dai->dev);
+
+ if (si476x_core_is_powered_up(core))
+ si476x_core_set_power_state(core, SI476X_POWER_DOWN);
+}
+
static const struct snd_soc_dai_ops si476x_dai_ops = {
.hw_params = si476x_codec_hw_params,
.set_fmt = si476x_codec_set_dai_fmt,
+ .startup = si476x_codec_startup,
+ .shutdown = si476x_codec_shutdown,
};
static struct snd_soc_dai_driver si476x_dai = {
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 3bf081a7e450..956c5d0f923a 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -604,12 +604,135 @@ static const int bclk_divs[] = {
120, 160, 220, 240, 320, 320, 320
};
+/**
+ * wm8960_configure_sysclk - checks if there is a sysclk frequency available
+ * The sysclk must be chosen such that:
+ * - sysclk = MCLK / sysclk_divs
+ * - lrclk = sysclk / dac_divs
+ * - 10 * bclk = sysclk / bclk_divs
+ *
+ * @wm8960_priv: wm8960 codec private data
+ * @mclk: MCLK used to derive sysclk
+ * @sysclk_idx: sysclk_divs index for found sysclk
+ * @dac_idx: dac_divs index for found lrclk
+ * @bclk_idx: bclk_divs index for found bclk
+ *
+ * Returns:
+ * -1, in case no sysclk frequency available found
+ * >=0, in case we could derive bclk and lrclk from sysclk using
+ * (@sysclk_idx, @dac_idx, @bclk_idx) dividers
+ */
+static
+int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
+ int *sysclk_idx, int *dac_idx, int *bclk_idx)
+{
+ int sysclk, bclk, lrclk;
+ int i, j, k;
+ int diff;
+
+ /* marker for no match */
+ *bclk_idx = -1;
+
+ bclk = wm8960->bclk;
+ lrclk = wm8960->lrclk;
+
+ /* check if the sysclk frequency is available. */
+ for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
+ if (sysclk_divs[i] == -1)
+ continue;
+ sysclk = mclk / sysclk_divs[i];
+ for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
+ if (sysclk != dac_divs[j] * lrclk)
+ continue;
+ for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) {
+ diff = sysclk - bclk * bclk_divs[k] / 10;
+ if (diff == 0) {
+ *sysclk_idx = i;
+ *dac_idx = j;
+ *bclk_idx = k;
+ break;
+ }
+ }
+ if (k != ARRAY_SIZE(bclk_divs))
+ break;
+ }
+ if (j != ARRAY_SIZE(dac_divs))
+ break;
+ }
+ return *bclk_idx;
+}
+
+/**
+ * wm8960_configure_pll - checks if there is a PLL out frequency available
+ * The PLL out frequency must be chosen such that:
+ * - sysclk = lrclk * dac_divs
+ * - freq_out = sysclk * sysclk_divs
+ * - 10 * sysclk = bclk * bclk_divs
+ *
+ * @codec: codec structure
+ * @freq_in: input frequency used to derive freq out via PLL
+ * @sysclk_idx: sysclk_divs index for found sysclk
+ * @dac_idx: dac_divs index for found lrclk
+ * @bclk_idx: bclk_divs index for found bclk
+ *
+ * Returns:
+ * -1, in case no PLL frequency out available was found
+ * >=0, in case we could derive bclk, lrclk, sysclk from PLL out using
+ * (@sysclk_idx, @dac_idx, @bclk_idx) dividers
+ */
+static
+int wm8960_configure_pll(struct snd_soc_codec *codec, int freq_in,
+ int *sysclk_idx, int *dac_idx, int *bclk_idx)
+{
+ struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+ int sysclk, bclk, lrclk, freq_out;
+ int diff, best_freq_out = 0;
+ int i, j, k;
+
+ bclk = wm8960->bclk;
+ lrclk = wm8960->lrclk;
+
+ *bclk_idx = *dac_idx = *sysclk_idx = -1;
+
+ for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
+ if (sysclk_divs[i] == -1)
+ continue;
+ for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
+ sysclk = lrclk * dac_divs[j];
+ freq_out = sysclk * sysclk_divs[i];
+
+ for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) {
+ if (!is_pll_freq_available(freq_in, freq_out))
+ continue;
+
+ diff = sysclk - bclk * bclk_divs[k] / 10;
+ if (diff == 0) {
+ *sysclk_idx = i;
+ *dac_idx = j;
+ *bclk_idx = k;
+ best_freq_out = freq_out;
+ break;
+ }
+ }
+ if (k != ARRAY_SIZE(bclk_divs))
+ break;
+ }
+ if (j != ARRAY_SIZE(dac_divs))
+ break;
+ }
+
+ if (*bclk_idx != -1)
+ wm8960_set_pll(codec, freq_in, best_freq_out);
+
+ return *bclk_idx;
+}
static int wm8960_configure_clocking(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
- int sysclk, bclk, lrclk, freq_out, freq_in;
+ int freq_out, freq_in;
u16 iface1 = snd_soc_read(codec, WM8960_IFACE1);
int i, j, k;
+ int ret;
if (!(iface1 & (1<<6))) {
dev_dbg(codec->dev,
@@ -623,8 +746,6 @@ static int wm8960_configure_clocking(struct snd_soc_codec *codec)
}
freq_in = wm8960->freq_in;
- bclk = wm8960->bclk;
- lrclk = wm8960->lrclk;
/*
* If it's sysclk auto mode, check if the MCLK can provide sysclk or
* not. If MCLK can provide sysclk, using MCLK to provide sysclk
@@ -643,58 +764,18 @@ static int wm8960_configure_clocking(struct snd_soc_codec *codec)
}
if (wm8960->clk_id != WM8960_SYSCLK_PLL) {
- /* check if the sysclk frequency is available. */
- for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
- if (sysclk_divs[i] == -1)
- continue;
- sysclk = freq_out / sysclk_divs[i];
- for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
- if (sysclk != dac_divs[j] * lrclk)
- continue;
- for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k)
- if (sysclk == bclk * bclk_divs[k] / 10)
- break;
- if (k != ARRAY_SIZE(bclk_divs))
- break;
- }
- if (j != ARRAY_SIZE(dac_divs))
- break;
- }
-
- if (i != ARRAY_SIZE(sysclk_divs)) {
+ ret = wm8960_configure_sysclk(wm8960, freq_out, &i, &j, &k);
+ if (ret >= 0) {
goto configure_clock;
} else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) {
dev_err(codec->dev, "failed to configure clock\n");
return -EINVAL;
}
}
- /* get a available pll out frequency and set pll */
- for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
- if (sysclk_divs[i] == -1)
- continue;
- for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
- sysclk = lrclk * dac_divs[j];
- freq_out = sysclk * sysclk_divs[i];
-
- for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) {
- if (sysclk == bclk * bclk_divs[k] / 10 &&
- is_pll_freq_available(freq_in, freq_out)) {
- wm8960_set_pll(codec,
- freq_in, freq_out);
- break;
- } else {
- continue;
- }
- }
- if (k != ARRAY_SIZE(bclk_divs))
- break;
- }
- if (j != ARRAY_SIZE(dac_divs))
- break;
- }
- if (i == ARRAY_SIZE(sysclk_divs)) {
- dev_err(codec->dev, "failed to configure clock\n");
+ ret = wm8960_configure_pll(codec, freq_in, &i, &j, &k);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to configure clock via PLL\n");
return -EINVAL;
}
@@ -765,8 +846,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
wm8960->is_stream_in_use[tx] = true;
- if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON &&
- !wm8960->is_stream_in_use[!tx])
+ if (!wm8960->is_stream_in_use[!tx])
return wm8960_configure_clocking(codec);
return 0;
@@ -1025,11 +1105,6 @@ static bool is_pll_freq_available(unsigned int source, unsigned int target)
target *= 4;
Ndiv = target / source;
- if (Ndiv < 6) {
- source >>= 1;
- Ndiv = target / source;
- }
-
if ((Ndiv < 6) || (Ndiv > 12))
return false;
@@ -1140,6 +1215,9 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
if (pll_id == WM8960_SYSCLK_AUTO)
return 0;
+ if (is_pll_freq_available(freq_in, freq_out))
+ return -EINVAL;
+
return wm8960_set_pll(codec, freq_in, freq_out);
}
@@ -1299,6 +1377,7 @@ static int wm8960_i2c_probe(struct i2c_client *i2c,
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8960_priv *wm8960;
int ret;
+ int repeat_reset = 10;
wm8960 = devm_kzalloc(&i2c->dev, sizeof(struct wm8960_priv),
GFP_KERNEL);
@@ -1320,7 +1399,11 @@ static int wm8960_i2c_probe(struct i2c_client *i2c,
else if (i2c->dev.of_node)
wm8960_set_pdata_from_of(i2c, &wm8960->pdata);
- ret = wm8960_reset(wm8960->regmap);
+ do {
+ ret = wm8960_reset(wm8960->regmap);
+ repeat_reset--;
+ } while (repeat_reset > 0 && ret != 0);
+
if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
return ret;
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index fd2731d171dd..47bb93e71136 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2,6 +2,7 @@
* wm8962.c -- WM8962 ALSA SoC Audio driver
*
* Copyright 2010-2 Wolfson Microelectronics plc
+ * Copyright 2017 NXP
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*
@@ -1781,8 +1782,11 @@ SND_SOC_BYTES("HD Bass Coefficients", WM8962_HDBASS_AI_1, 30),
SOC_DOUBLE("ALC Switch", WM8962_ALC1, WM8962_ALCL_ENA_SHIFT,
WM8962_ALCR_ENA_SHIFT, 1, 0),
-SND_SOC_BYTES_MASK("ALC Coefficients", WM8962_ALC1, 4,
+SND_SOC_BYTES_MASK("ALC1", WM8962_ALC1, 1,
WM8962_ALCL_ENA_MASK | WM8962_ALCR_ENA_MASK),
+SND_SOC_BYTES("ALC2", WM8962_ALC2, 1),
+SND_SOC_BYTES("ALC3", WM8962_ALC3, 1),
+SND_SOC_BYTES("Noise Gate", WM8962_NOISE_GATE, 1),
};
static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
@@ -2558,11 +2562,17 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_codec *codec = dai->codec;
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ snd_pcm_format_t sample_format = params_format(params);
int i;
int aif0 = 0;
int adctl3 = 0;
- wm8962->bclk = snd_soc_params_to_bclk(params);
+ if (sample_format == SNDRV_PCM_FORMAT_S20_3LE)
+ wm8962->bclk = params_rate(params) *
+ params_channels(params) *
+ params_physical_width(params);
+ else
+ wm8962->bclk = snd_soc_params_to_bclk(params);
if (params_channels(params) == 1)
wm8962->bclk *= 2;
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 3896523b71e9..e79cc4cbbcc5 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -3150,9 +3150,67 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
};
#ifdef CONFIG_PM
+static void wm8994_store_context(struct wm8994 *wm8994)
+{
+ struct device *dev = wm8994->dev;
+ int ret;
+
+ /* Disable LDO pulldowns while the device is suspended if we
+ * don't know that something will be driving them. */
+ if (!wm8994->ldo_ena_always_driven)
+ wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+ WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
+ WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
+
+ /* Explicitly put the device into reset in case regulators
+ * don't get disabled in order to ensure consistent restart.
+ */
+ wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
+ wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
+
+ regcache_mark_dirty(wm8994->regmap);
+
+ /* Restore GPIO registers to prevent problems with mismatched
+ * pin configurations.
+ */
+ ret = regcache_sync_region(wm8994->regmap, WM8994_GPIO_1,
+ WM8994_GPIO_11);
+ if (ret != 0)
+ dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
+
+ /* In case one of the GPIOs is used as a wake input. */
+ ret = regcache_sync_region(wm8994->regmap,
+ WM8994_INTERRUPT_STATUS_1_MASK,
+ WM8994_INTERRUPT_STATUS_1_MASK);
+ if (ret != 0)
+ dev_err(dev, "Failed to restore interrupt mask: %d\n", ret);
+
+ regcache_cache_only(wm8994->regmap, true);
+}
+
+static int wm8994_load_context(struct wm8994 *wm8994)
+{
+ struct device *dev = wm8994->dev;
+ int ret;
+
+ regcache_cache_only(wm8994->regmap, false);
+ ret = regcache_sync(wm8994->regmap);
+ if (ret != 0) {
+ dev_err(dev, "Failed to restore register map: %d\n", ret);
+ return ret;
+ }
+
+ /* Disable LDO pulldowns while the device is active */
+ wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+ WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD, 0);
+
+ return 0;
+}
+
static int wm8994_codec_suspend(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int i, ret;
for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
@@ -3164,6 +3222,8 @@ static int wm8994_codec_suspend(struct snd_soc_codec *codec)
i + 1, ret);
}
+ wm8994_store_context(control);
+
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -3172,8 +3232,15 @@ static int wm8994_codec_suspend(struct snd_soc_codec *codec)
static int wm8994_codec_resume(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int i, ret;
+ ret = wm8994_load_context(control);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to load context: %d\n", ret);
+ return ret;
+ }
+
for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
if (!wm8994->fll_suspend[i].out)
continue;
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 19bdcac71775..4b2ad1be47e9 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -56,13 +56,30 @@ config SND_SOC_FSL_ESAI
This option is only useful for out-of-tree drivers since
in-tree drivers select it automatically.
+config SND_SOC_FSL_RPMSG_I2S
+ tristate "I2S base on the RPMSG support"
+ depends on RPMSG
+ help
+ Say Y if you want to add rpmsg i2s support for the Freescale CPUs.
+ which is depends on the rpmsg.
+ This option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
config SND_SOC_FSL_UTILS
tristate
+config SND_SOC_FSL_HDMI
+ tristate
+
config SND_SOC_IMX_PCM_DMA
tristate
select SND_SOC_GENERIC_DMAENGINE_PCM
+config SND_SOC_IMX_PCM_RPMSG
+ tristate
+ depends on RPMSG
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+
config SND_SOC_IMX_AUDMUX
tristate "Digital Audio Mux module support"
help
@@ -182,6 +199,11 @@ config SND_SOC_IMX_PCM_FIQ
tristate
select FIQ
+config SND_SOC_IMX_HDMI_DMA
+ bool
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ select SND_SOC_IMX_PCM_DMA
+
comment "SoC Audio support for Freescale i.MX boards:"
config SND_MXC_SOC_WM1133_EV1
@@ -230,6 +252,57 @@ config SND_SOC_EUKREA_TLV320
Enable I2S based access to the TLV320AIC23B codec attached
to the SSI interface
+config SND_SOC_IMX_WM8960
+ tristate "SoC Audio support for i.MX boards with wm8960"
+ depends on OF && I2C
+ select SND_SOC_WM8960
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_FSL_SAI
+ select SND_SOC_FSL_UTILS
+ select SND_KCTL_JACK
+ help
+ SoC Audio support for i.MX boards with WM8960
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a wm8960 codec.
+
+config SND_SOC_IMX_SII902X
+ tristate "SoC Audio support for i.MX boards with sii902x"
+ depends on OF && I2C
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_FSL_SAI
+ select SND_SOC_FSL_UTILS
+ help
+ SoC Audio support for i.MX boards with SII902X
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a sii902x.
+
+config SND_SOC_IMX_WM8958
+ tristate "SoC Audio support for i.MX boards with wm8958"
+ depends on OF && I2C
+ select MFD_WM8994
+ select SND_SOC_WM8994
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_FSL_SAI
+ select SND_SOC_FSL_UTILS
+ select SND_KCTL_JACK
+ help
+ SoC Audio support for i.MX boards with WM8958
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a wm8958 codec.
+
+config SND_SOC_IMX_CS42888
+ tristate "SoC Audio support for i.MX boards with cs42888"
+ depends on OF && I2C
+ select SND_SOC_CS42XX8_I2C
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_FSL_ESAI
+ select SND_SOC_FSL_ASRC
+ select SND_SOC_FSL_UTILS
+ help
+ SoC Audio support for i.MX boards with cs42888
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a cs42888 codec.
+
config SND_SOC_IMX_WM8962
tristate "SoC Audio support for i.MX boards with wm8962"
depends on OF && I2C && INPUT
@@ -237,10 +310,29 @@ config SND_SOC_IMX_WM8962
select SND_SOC_IMX_PCM_DMA
select SND_SOC_IMX_AUDMUX
select SND_SOC_FSL_SSI
+ select SND_KCTL_JACK
help
Say Y if you want to add support for SoC audio on an i.MX board with
a wm8962 codec.
+config SND_SOC_IMX_WM8962_ANDROID
+ tristate "SoC Audio support for i.MX boards with wm8962 in android"
+ depends on SND_SOC_IMX_WM8962=y
+ help
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a wm8962 codec in android.
+
+config SND_SOC_IMX_RPMSG
+ tristate "SoC Audio support for i.MX boards with rpmsg"
+ depends on OF && I2C && INPUT
+ select SND_SOC_IMX_PCM_RPMSG
+ select SND_SOC_FSL_RPMSG_I2S
+ help
+ SoC Audio support for i.MX boards with rpmsg.
+ There should be rpmsg devices defined in other core
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a rpmsg devices.
+
config SND_SOC_IMX_ES8328
tristate "SoC Audio support for i.MX boards with the ES8328 codec"
depends on OF && (I2C || SPI)
@@ -253,6 +345,17 @@ config SND_SOC_IMX_ES8328
Say Y if you want to add support for the ES8328 audio codec connected
via SSI/I2S over either SPI or I2C.
+config SND_SOC_IMX_XTOR
+ tristate "SoC Audio support for i.MX boards with xtor codec"
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_FSL_ESAI
+ select SND_SOC_FSL_SAI
+ select SND_SOC_FSL_UTILS
+ help
+ SoC Audio support for i.MX boards with xtor codec
+ Say Y if you want to add support for SoC audio on
+ an i.MX board with a xtor codec.
+
config SND_SOC_IMX_SGTL5000
tristate "SoC Audio support for i.MX boards with sgtl5000"
depends on OF && I2C
@@ -264,6 +367,14 @@ config SND_SOC_IMX_SGTL5000
Say Y if you want to add support for SoC audio on an i.MX board with
a sgtl5000 codec.
+config SND_SOC_IMX_MQS
+ tristate "SoC Audio support for i.MX boards with MQS"
+ depends on OF
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_FSL_SAI
+ select SND_SOC_FSL_MQS
+ select SND_SOC_FSL_UTILS
+
config SND_SOC_IMX_SPDIF
tristate "SoC Audio support for i.MX boards with S/PDIF"
select SND_SOC_IMX_PCM_DMA
@@ -297,6 +408,29 @@ config SND_SOC_FSL_ASOC_CARD
CS4271, CS4272 and SGTL5000.
Say Y if you want to add support for Freescale Generic ASoC Sound Card.
+config SND_SOC_IMX_SI476X
+ tristate "SoC Audio support for i.MX boards with si476x"
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_FSL_SSI
+ select SND_SOC_FSL_UTILS
+ select SND_SOC_SI476X
+ help
+ SoC Audio support for i.MX boards with SI476x
+ Say Y if you want to add support for Soc audio for the AMFM Tuner chip
+ SI476x module.
+
+config SND_SOC_IMX_HDMI
+ tristate "SoC Audio support for i.MX boards with HDMI port"
+ depends on MFD_MXC_HDMI
+ select SND_SOC_IMX_HDMI_DMA
+ select SND_SOC_FSL_HDMI
+ select SND_SOC_HDMI_CODEC
+ help
+ SoC Audio support for i.MX boards with HDMI audio
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ IMX HDMI.
+
endif # SND_IMX_SOC
endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index d28dc25c9375..7830d522de47 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -20,14 +20,18 @@ snd-soc-fsl-spdif-objs := fsl_spdif.o
snd-soc-fsl-esai-objs := fsl_esai.o
snd-soc-fsl-utils-objs := fsl_utils.o
snd-soc-fsl-dma-objs := fsl_dma.o
+snd-soc-fsl-rpmsg-i2s-objs := fsl_rpmsg_i2s.o
obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o
+snd-soc-fsl-hdmi-objs := fsl_hdmi.o
obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o
obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
obj-$(CONFIG_SND_SOC_FSL_ESAI) += snd-soc-fsl-esai.o
obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
+obj-$(CONFIG_SND_SOC_FSL_HDMI) += snd-soc-fsl-hdmi.o
obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
+obj-$(CONFIG_SND_SOC_FSL_RPMSG_I2S) += snd-soc-fsl-rpmsg-i2s.o
# MPC5200 Platform Support
obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
@@ -45,7 +49,9 @@ obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
-obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o imx-pcm-dma-v2.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o
+obj-$(CONFIG_SND_SOC_IMX_HDMI_DMA) += imx-hdmi-dma.o hdmi_pcm.o
# i.MX Machine Support
snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
@@ -53,17 +59,37 @@ snd-soc-phycore-ac97-objs := phycore-ac97.o
snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
snd-soc-wm1133-ev1-objs := wm1133-ev1.o
snd-soc-imx-es8328-objs := imx-es8328.o
+snd-soc-imx-cs42888-objs := imx-cs42888.o
snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
+snd-soc-imx-wm8958-objs := imx-wm8958.o
+snd-soc-imx-wm8960-objs := imx-wm8960.o
snd-soc-imx-wm8962-objs := imx-wm8962.o
+snd-soc-imx-xtor-objs := imx-xtor.o
+snd-soc-imx-sii902x-objs := imx-sii902x.o
snd-soc-imx-spdif-objs := imx-spdif.o
snd-soc-imx-mc13783-objs := imx-mc13783.o
+snd-soc-imx-mqs-objs := imx-mqs.o
+snd-soc-imx-si476x-objs := imx-si476x.o
+snd-soc-imx-hdmi-objs := imx-hdmi.o
+snd-soc-imx-rpmsg-objs := imx-rpmsg.o
obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
+obj-$(CONFIG_SND_SOC_IMX_CS42888) += snd-soc-imx-cs42888.o
obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
+obj-${CONFIG_SND_SOC_IMX_WM8958} += snd-soc-imx-wm8958.o
+obj-$(CONFIG_SND_SOC_IMX_WM8960) += snd-soc-imx-wm8960.o
obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
+obj-$(CONFIG_SND_SOC_IMX_XTOR) += snd-soc-imx-xtor.o
+obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
+obj-$(CONFIG_SND_SOC_IMX_SII902X) += snd-soc-imx-sii902x.o
obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
+obj-$(CONFIG_SND_SOC_IMX_MQS) += snd-soc-imx-mqs.o
+obj-$(CONFIG_SND_SOC_IMX_SI476X) += snd-soc-imx-si476x.o
+obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
+
+AFLAGS_hdmi_pcm.o := -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 1d82f68305c3..f0652c41536f 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1,7 +1,8 @@
/*
* Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
*
* Author: Nicolin Chen <nicoleotsuka@gmail.com>
*
@@ -21,41 +22,28 @@
#include <sound/pcm_params.h>
#include "fsl_asrc.h"
+#include "imx-pcm.h"
#define IDEAL_RATIO_DECIMAL_DEPTH 26
#define pair_err(fmt, ...) \
dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
+#define pair_warn(fmt, ...) \
+ dev_warn(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
+
#define pair_dbg(fmt, ...) \
dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
-/* Sample rates are aligned with that defined in pcm.h file */
-static const u8 process_option[][12][2] = {
- /* 8kHz 11.025kHz 16kHz 22.05kHz 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */
- {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */
- {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */
- {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */
- {{1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */
- {{1, 2}, {1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */
- {{1, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */
- {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */
- {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */
- {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */
- {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */
- {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */
- {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */
- {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */
-};
-
/* Corresponding to process_option */
-static int supported_input_rate[] = {
- 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
- 96000, 176400, 192000,
+static unsigned int supported_asrc_rate[] = {
+ 5512, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
+ 64000, 88200, 96000, 128000, 176400, 192000,
};
-static int supported_asrc_rate[] = {
- 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
+static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = {
+ .count = ARRAY_SIZE(supported_asrc_rate),
+ .list = supported_asrc_rate,
};
/**
@@ -113,7 +101,8 @@ static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
if (index == ASRC_INVALID_PAIR) {
dev_err(dev, "all pairs are busy now\n");
ret = -EBUSY;
- } else if (asrc_priv->channel_avail < channels) {
+ } else if (asrc_priv->channel_avail < channels ||
+ (asrc_priv->channel_bits < 4 && channels % 2 != 0)) {
dev_err(dev, "can't afford required channels: %d\n", channels);
ret = -EINVAL;
} else {
@@ -128,6 +117,47 @@ static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
return ret;
}
+static int proc_autosel(int Fsin, int Fsout, int *pre_proc, int *post_proc)
+{
+ bool det_out_op2_cond;
+ bool det_out_op0_cond;
+ det_out_op2_cond = (((Fsin * 15 > Fsout * 16) & (Fsout < 56000)) |
+ ((Fsin > 56000) & (Fsout < 56000)));
+ det_out_op0_cond = (Fsin * 23 < Fsout * 8);
+
+ /*
+ * Not supported case: Tsout>16.125*Tsin, and Tsout>8.125*Tsin.
+ */
+ if (Fsin * 8 > 129 * Fsout)
+ *pre_proc = 5;
+ else if (Fsin * 8 > 65 * Fsout)
+ *pre_proc = 4;
+ else if (Fsin * 8 > 33 * Fsout)
+ *pre_proc = 2;
+ else if (Fsin * 8 > 15 * Fsout) {
+ if (Fsin > 152000)
+ *pre_proc = 2;
+ else
+ *pre_proc = 1;
+ } else if (Fsin < 76000)
+ *pre_proc = 0;
+ else if (Fsin > 152000)
+ *pre_proc = 2;
+ else
+ *pre_proc = 1;
+
+ if (det_out_op2_cond)
+ *post_proc = 2;
+ else if (det_out_op0_cond)
+ *post_proc = 0;
+ else
+ *post_proc = 1;
+
+ if (*pre_proc == 4 || *pre_proc == 5)
+ return -EINVAL;
+ return 0;
+}
+
/**
* Release ASRC pair
*
@@ -235,7 +265,7 @@ static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair,
* of struct asrc_config which includes in/output sample rate, width, channel
* and clock settings.
*/
-static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
+static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool p2p_in, bool p2p_out)
{
struct asrc_config *config = pair->config;
struct fsl_asrc *asrc_priv = pair->asrc_priv;
@@ -243,8 +273,10 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
u32 inrate, outrate, indiv, outdiv;
u32 clk_index[2], div[2];
int in, out, channels;
+ int pre_proc, post_proc;
struct clk *clk;
bool ideal;
+ int ret;
if (!config) {
pair_err("invalid pair config\n");
@@ -268,11 +300,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
ideal = config->inclk == INCLK_NONE;
/* Validate input and output sample rates */
- for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++)
- if (inrate == supported_input_rate[in])
+ for (in = 0; in < ARRAY_SIZE(supported_asrc_rate); in++)
+ if (inrate == supported_asrc_rate[in])
break;
- if (in == ARRAY_SIZE(supported_input_rate)) {
+ if (in == ARRAY_SIZE(supported_asrc_rate)) {
pair_err("unsupported input sample rate: %dHz\n", inrate);
return -EINVAL;
}
@@ -309,11 +341,17 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
clk = asrc_priv->asrck_clk[clk_index[OUT]];
- /* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */
- if (ideal)
- div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE;
- else
+ /*
+ * When P2P mode, output rate should align with the out samplerate.
+ * if set too high output rate, there will be lots of Overload.
+ * When M2M mode, output rate should also need to align with the out
+ * samplerate, but M2M must use less time to achieve good performance.
+ */
+ if (p2p_out)
div[OUT] = clk_get_rate(clk) / outrate;
+ else
+ div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE;
+
if (div[OUT] == 0) {
pair_err("failed to support output sample rate %dHz by asrck_%x\n",
@@ -321,6 +359,17 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
return -EINVAL;
}
+ if (div[IN] > 1024 && div[OUT] > 1024) {
+ pair_warn("both divider (%d, %d) are larger than threshold\n",
+ div[IN], div[OUT]);
+ }
+
+ if (div[IN] > 1024)
+ div[IN] = 1024;
+
+ if (div[OUT] > 1024)
+ div[OUT] = 1024;
+
/* Set the channel number */
channels = config->channel_num;
@@ -381,11 +430,17 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
ASRCTR_IDR(index) | ASRCTR_USR(index));
+ ret = proc_autosel(inrate, outrate, &pre_proc, &post_proc);
+ if (ret) {
+ pair_err("No supported pre-processing options\n");
+ return ret;
+ }
+
/* Apply configurations for pre- and post-processing */
regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index),
- ASRCFG_PREMOD(index, process_option[in][out][0]) |
- ASRCFG_POSTMOD(index, process_option[in][out][1]));
+ ASRCFG_PREMOD(index, pre_proc) |
+ ASRCFG_POSTMOD(index, post_proc));
return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
}
@@ -468,6 +523,7 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+ asrc_priv->pair_streams |= BIT(substream->stream);
pair->config = &config;
if (width == 16)
@@ -490,17 +546,24 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
config.output_word_width = word_width;
config.input_sample_rate = rate;
config.output_sample_rate = asrc_priv->asrc_rate;
+
+ ret = fsl_asrc_config_pair(pair, false, true);
+ if (ret) {
+ dev_err(dai->dev, "fail to config asrc pair\n");
+ return ret;
+ }
+
} else {
config.input_word_width = word_width;
config.output_word_width = width;
config.input_sample_rate = asrc_priv->asrc_rate;
config.output_sample_rate = rate;
- }
- ret = fsl_asrc_config_pair(pair);
- if (ret) {
- dev_err(dai->dev, "fail to config asrc pair\n");
- return ret;
+ ret = fsl_asrc_config_pair(pair, true, false);
+ if (ret) {
+ dev_err(dai->dev, "fail to config asrc pair\n");
+ return ret;
+ }
}
return 0;
@@ -509,11 +572,15 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
static int fsl_asrc_dai_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
+ struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
- if (pair)
- fsl_asrc_release_pair(pair);
+ if (asrc_priv->pair_streams & BIT(substream->stream)) {
+ if (pair)
+ fsl_asrc_release_pair(pair);
+ asrc_priv->pair_streams &= ~BIT(substream->stream);
+ }
return 0;
}
@@ -529,6 +596,8 @@ static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
fsl_asrc_start_pair(pair);
+ /* Output enough data to content the DMA burstsize of BE */
+ mdelay(1);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -542,7 +611,28 @@ static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
return 0;
}
+static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(cpu_dai);
+
+ asrc_priv->substream[substream->stream] = substream;
+
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &fsl_asrc_rate_constraints);
+}
+
+static void fsl_asrc_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(cpu_dai);
+
+ asrc_priv->substream[substream->stream] = NULL;
+}
+
static struct snd_soc_dai_ops fsl_asrc_dai_ops = {
+ .startup = fsl_asrc_dai_startup,
+ .shutdown = fsl_asrc_dai_shutdown,
.hw_params = fsl_asrc_dai_hw_params,
.hw_free = fsl_asrc_dai_hw_free,
.trigger = fsl_asrc_dai_trigger,
@@ -561,7 +651,7 @@ static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
#define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000
#define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S20_3LE)
+ SNDRV_PCM_FMTBIT_S24_3LE)
static struct snd_soc_dai_driver fsl_asrc_dai = {
.probe = fsl_asrc_dai_probe,
@@ -569,14 +659,18 @@ static struct snd_soc_dai_driver fsl_asrc_dai = {
.stream_name = "ASRC-Playback",
.channels_min = 1,
.channels_max = 10,
- .rates = FSL_ASRC_RATES,
+ .rate_min = 5512,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_KNOT,
.formats = FSL_ASRC_FORMATS,
},
.capture = {
.stream_name = "ASRC-Capture",
.channels_min = 1,
.channels_max = 10,
- .rates = FSL_ASRC_RATES,
+ .rate_min = 5512,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_KNOT,
.formats = FSL_ASRC_FORMATS,
},
.ops = &fsl_asrc_dai_ops,
@@ -729,6 +823,64 @@ static const struct regmap_config fsl_asrc_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+#include "fsl_asrc_m2m.c"
+
+static bool fsl_asrc_check_xrun(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
+ struct snd_pcm_substream *be_substream;
+ struct snd_soc_dpcm *dpcm;
+ int ret = 0;
+
+ /* find the be for this fe stream */
+ list_for_each_entry(dpcm, &rtd->dpcm[substream->stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+
+ if (dpcm->fe != rtd)
+ continue;
+
+ be_substream = snd_soc_dpcm_get_substream(be, substream->stream);
+ dma_params_be = snd_soc_dai_get_dma_data(dai, be_substream);
+ if (dma_params_be->check_xrun && dma_params_be->check_xrun(be_substream))
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static void fsl_asrc_reset(struct snd_pcm_substream *substream, bool stop)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(cpu_dai);
+ struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
+ struct snd_soc_dpcm *dpcm;
+ struct snd_pcm_substream *be_substream;
+ unsigned long flags = 0;
+
+ if (stop)
+ imx_stop_lock_pcm_streams(asrc_priv->substream, 2, &flags);
+
+ /* find the be for this fe stream */
+ list_for_each_entry(dpcm, &rtd->dpcm[substream->stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_soc_dai *dai = be->cpu_dai;
+
+ if (dpcm->fe != rtd)
+ continue;
+
+ be_substream = snd_soc_dpcm_get_substream(be, substream->stream);
+ dma_params_be = snd_soc_dai_get_dma_data(dai, be_substream);
+ dma_params_be->device_reset(be_substream, 0);
+ break;
+ }
+
+ if (stop)
+ imx_start_unlock_pcm_streams(asrc_priv->substream, 2, &flags);
+}
+
/**
* Initialize ASRC registers with a default configurations
*/
@@ -911,6 +1063,11 @@ static int fsl_asrc_probe(struct platform_device *pdev)
return ret;
}
+ asrc_priv->dma_params_tx.check_xrun = fsl_asrc_check_xrun;
+ asrc_priv->dma_params_rx.check_xrun = fsl_asrc_check_xrun;
+ asrc_priv->dma_params_tx.device_reset = fsl_asrc_reset;
+ asrc_priv->dma_params_rx.device_reset = fsl_asrc_reset;
+
if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) {
dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n");
asrc_priv->asrc_width = 24;
@@ -933,6 +1090,12 @@ static int fsl_asrc_probe(struct platform_device *pdev)
return ret;
}
+ ret = fsl_asrc_m2m_init(asrc_priv);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to init m2m device %d\n", ret);
+ return ret;
+ }
+
return 0;
}
@@ -994,6 +1157,8 @@ static int fsl_asrc_suspend(struct device *dev)
{
struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+ fsl_asrc_m2m_suspend(asrc_priv);
+
regmap_read(asrc_priv->regmap, REG_ASRCFG,
&asrc_priv->regcache_cfg);
@@ -1043,6 +1208,7 @@ MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
static struct platform_driver fsl_asrc_driver = {
.probe = fsl_asrc_probe,
+ .remove = fsl_asrc_m2m_remove,
.driver = {
.name = "fsl-asrc",
.of_match_table = fsl_asrc_ids,
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
index 0f163abe4ba3..df332fc9afcb 100644
--- a/sound/soc/fsl/fsl_asrc.h
+++ b/sound/soc/fsl/fsl_asrc.h
@@ -1,7 +1,7 @@
/*
* fsl_asrc.h - Freescale ASRC ALSA SoC header file
*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
*
* Author: Nicolin Chen <nicoleotsuka@gmail.com>
*
@@ -13,6 +13,8 @@
#ifndef _FSL_ASRC_H
#define _FSL_ASRC_H
+#include <uapi/linux/mxc_asrc.h>
+
#define IN 0
#define OUT 1
@@ -23,7 +25,8 @@
#define ASRC_FIFO_THRESHOLD_MAX 63
#define ASRC_DMA_BUFFER_SIZE (1024 * 48 * 4)
#define ASRC_MAX_BUFFER_SIZE (1024 * 48)
-#define ASRC_OUTPUT_LAST_SAMPLE 8
+#define ASRC_OUTPUT_LAST_SAMPLE_MAX 32
+#define ASRC_OUTPUT_LAST_SAMPLE 16
#define IDEAL_RATIO_RATE 1000000
@@ -286,103 +289,8 @@
#define ASRMCR1i_OW16_MASK (1 << ASRMCR1i_OW16_SHIFT)
#define ASRMCR1i_OW16(v) ((v) << ASRMCR1i_OW16_SHIFT)
-
-enum asrc_pair_index {
- ASRC_INVALID_PAIR = -1,
- ASRC_PAIR_A = 0,
- ASRC_PAIR_B = 1,
- ASRC_PAIR_C = 2,
-};
-
-#define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1)
-
-enum asrc_inclk {
- INCLK_NONE = 0x03,
- INCLK_ESAI_RX = 0x00,
- INCLK_SSI1_RX = 0x01,
- INCLK_SSI2_RX = 0x02,
- INCLK_SSI3_RX = 0x07,
- INCLK_SPDIF_RX = 0x04,
- INCLK_MLB_CLK = 0x05,
- INCLK_PAD = 0x06,
- INCLK_ESAI_TX = 0x08,
- INCLK_SSI1_TX = 0x09,
- INCLK_SSI2_TX = 0x0a,
- INCLK_SSI3_TX = 0x0b,
- INCLK_SPDIF_TX = 0x0c,
- INCLK_ASRCK1_CLK = 0x0f,
-};
-
-enum asrc_outclk {
- OUTCLK_NONE = 0x03,
- OUTCLK_ESAI_TX = 0x00,
- OUTCLK_SSI1_TX = 0x01,
- OUTCLK_SSI2_TX = 0x02,
- OUTCLK_SSI3_TX = 0x07,
- OUTCLK_SPDIF_TX = 0x04,
- OUTCLK_MLB_CLK = 0x05,
- OUTCLK_PAD = 0x06,
- OUTCLK_ESAI_RX = 0x08,
- OUTCLK_SSI1_RX = 0x09,
- OUTCLK_SSI2_RX = 0x0a,
- OUTCLK_SSI3_RX = 0x0b,
- OUTCLK_SPDIF_RX = 0x0c,
- OUTCLK_ASRCK1_CLK = 0x0f,
-};
-
#define ASRC_CLK_MAX_NUM 16
-enum asrc_word_width {
- ASRC_WIDTH_24_BIT = 0,
- ASRC_WIDTH_16_BIT = 1,
- ASRC_WIDTH_8_BIT = 2,
-};
-
-struct asrc_config {
- enum asrc_pair_index pair;
- unsigned int channel_num;
- unsigned int buffer_num;
- unsigned int dma_buffer_size;
- unsigned int input_sample_rate;
- unsigned int output_sample_rate;
- enum asrc_word_width input_word_width;
- enum asrc_word_width output_word_width;
- enum asrc_inclk inclk;
- enum asrc_outclk outclk;
-};
-
-struct asrc_req {
- unsigned int chn_num;
- enum asrc_pair_index index;
-};
-
-struct asrc_querybuf {
- unsigned int buffer_index;
- unsigned int input_length;
- unsigned int output_length;
- unsigned long input_offset;
- unsigned long output_offset;
-};
-
-struct asrc_convert_buffer {
- void *input_buffer_vaddr;
- void *output_buffer_vaddr;
- unsigned int input_buffer_length;
- unsigned int output_buffer_length;
-};
-
-struct asrc_status_flags {
- enum asrc_pair_index index;
- unsigned int overload_error;
-};
-
-enum asrc_error_status {
- ASRC_TASK_Q_OVERLOAD = 0x01,
- ASRC_OUTPUT_TASK_OVERLOAD = 0x02,
- ASRC_INPUT_TASK_OVERLOAD = 0x04,
- ASRC_OUTPUT_BUFFER_OVERFLOW = 0x08,
- ASRC_INPUT_BUFFER_UNDERRUN = 0x10,
-};
struct dma_block {
dma_addr_t dma_paddr;
@@ -436,6 +344,7 @@ struct fsl_asrc_pair {
* @pair: pair pointers
* @channel_bits: width of ASRCNCR register for each pair
* @channel_avail: non-occupied channel numbers
+ * @pair_streams:indicat which substream is running
* @asrc_rate: default sample rate for ASoC Back-Ends
* @asrc_width: default sample width for ASoC Back-Ends
* @regcache_cfg: store register value of REG_ASRCFG
@@ -452,9 +361,11 @@ struct fsl_asrc {
struct clk *asrck_clk[ASRC_CLK_MAX_NUM];
spinlock_t lock;
+ struct snd_pcm_substream *substream[2];
struct fsl_asrc_pair *pair[ASRC_PAIR_MAX_NUM];
unsigned int channel_bits;
unsigned int channel_avail;
+ unsigned int pair_streams;
int asrc_rate;
int asrc_width;
@@ -464,4 +375,5 @@ struct fsl_asrc {
extern struct snd_soc_platform_driver fsl_asrc_platform;
struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir);
+
#endif /* _FSL_ASRC_H */
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index dc30d780f874..02f3de1106ba 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -1,7 +1,7 @@
/*
* Freescale ASRC ALSA SoC Platform (DMA) driver
*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
*
* Author: Nicolin Chen <nicoleotsuka@gmail.com>
*
@@ -29,7 +29,7 @@ static struct snd_pcm_hardware snd_imx_hardware = {
SNDRV_PCM_INFO_RESUME,
.buffer_bytes_max = FSL_ASRC_DMABUF_SIZE,
.period_bytes_min = 128,
- .period_bytes_max = 65535, /* Limited by SDMA engine */
+ .period_bytes_max = 65532, /* Limited by SDMA engine */
.periods_min = 2,
.periods_max = 255,
.fifo_size = 0,
@@ -50,12 +50,19 @@ static void fsl_asrc_dma_complete(void *arg)
struct snd_pcm_substream *substream = arg;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_dmaengine_dai_dma_data *dma_data;
pair->pos += snd_pcm_lib_period_bytes(substream);
if (pair->pos >= snd_pcm_lib_buffer_bytes(substream))
pair->pos = 0;
snd_pcm_period_elapsed(substream);
+
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ if (dma_data->check_xrun && dma_data->check_xrun(substream))
+ dma_data->device_reset(substream, 1);
+
}
static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream)
@@ -150,6 +157,7 @@ static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
struct device *dev_be;
u8 dir = tx ? OUT : IN;
dma_cap_mask_t mask;
+ enum sdma_peripheral_type be_peripheral_type;
int ret;
/* Fetch the Back-End dma_data from DPCM */
@@ -205,6 +213,7 @@ static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
tmp_data = tmp_chan->private;
pair->dma_data.dma_request = tmp_data->dma_request;
+ be_peripheral_type = tmp_data->peripheral_type;
dma_release_channel(tmp_chan);
/* Get DMA request of Front-End */
@@ -215,6 +224,11 @@ static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
pair->dma_data.priority = tmp_data->priority;
dma_release_channel(tmp_chan);
+ if (tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
+ pair->dma_data.dst_dualfifo = true;
+ if (!tx && be_peripheral_type == IMX_DMATYPE_SSI_DUAL)
+ pair->dma_data.src_dualfifo = true;
+
pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data);
if (!pair->dma_chan[dir]) {
dev_err(dev, "failed to request DMA channel for Back-End\n");
@@ -226,6 +240,8 @@ static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
else
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ memset(&config_be, 0, sizeof(config_be));
+
config_be.direction = DMA_DEV_TO_DEV;
config_be.src_addr_width = buswidth;
config_be.src_maxburst = dma_params_be->maxburst;
@@ -277,6 +293,7 @@ static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream)
struct device *dev = rtd->platform->dev;
struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
struct fsl_asrc_pair *pair;
+ int ret;
pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL);
if (!pair) {
@@ -288,8 +305,12 @@ static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream)
runtime->private_data = pair;
- snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
+ ret = snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0) {
+ dev_err(dev, "failed to set pcm hw params periods\n");
+ return ret;
+ }
snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
return 0;
diff --git a/sound/soc/fsl/fsl_asrc_m2m.c b/sound/soc/fsl/fsl_asrc_m2m.c
new file mode 100644
index 000000000000..7363dc003aa6
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc_m2m.c
@@ -0,0 +1,956 @@
+/*
+ * Freescale ASRC Memory to Memory (M2M) driver
+ *
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#define FSL_ASRC_INPUTFIFO_WML 0x4
+#define FSL_ASRC_OUTPUTFIFO_WML 0x2
+
+#define DIR_STR(dir) dir == IN ? "in" : "out"
+
+struct fsl_asrc_m2m {
+ struct fsl_asrc_pair *pair;
+ struct completion complete[2];
+ struct dma_block dma_block[2];
+ unsigned int pair_hold;
+ unsigned int asrc_active;
+ unsigned int sg_nodes[2];
+ struct scatterlist sg[2][4];
+
+ enum asrc_word_width word_width[2];
+ unsigned int rate[2];
+ unsigned int last_period_size;
+ u32 watermark[2];
+ spinlock_t lock;
+};
+
+static struct miscdevice asrc_miscdev = {
+ .name = "mxc_asrc",
+ .minor = MISC_DYNAMIC_MINOR,
+};
+
+static void fsl_asrc_get_status(struct fsl_asrc_pair *pair,
+ struct asrc_status_flags *flags)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&asrc_priv->lock, lock_flags);
+
+ flags->overload_error = pair->error;
+
+ spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
+}
+
+#define ASRC_xPUT_DMA_CALLBACK(dir) \
+ ((dir == IN) ? fsl_asrc_input_dma_callback : fsl_asrc_output_dma_callback)
+
+static void fsl_asrc_input_dma_callback(void *data)
+{
+ struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data;
+ struct fsl_asrc_m2m *m2m = pair->private;
+
+ complete(&m2m->complete[IN]);
+}
+
+static void fsl_asrc_output_dma_callback(void *data)
+{
+ struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data;
+ struct fsl_asrc_m2m *m2m = pair->private;
+
+ complete(&m2m->complete[OUT]);
+}
+
+static unsigned int fsl_asrc_get_output_FIFO_size(struct fsl_asrc_pair *pair)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ u32 val;
+
+ regmap_read(asrc_priv->regmap, REG_ASRFST(index), &val);
+
+ val &= ASRFSTi_OUTPUT_FIFO_MASK;
+
+ return val >> ASRFSTi_OUTPUT_FIFO_SHIFT;
+}
+
+static void fsl_asrc_read_last_FIFO(struct fsl_asrc_pair *pair)
+{
+ struct fsl_asrc_m2m *m2m = pair->private;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ struct dma_block *output = &m2m->dma_block[OUT];
+ u32 i, reg, size, t_size = 0;
+ u32 *reg24 = NULL;
+ u16 *reg16 = NULL;
+
+ if (m2m->word_width[OUT] == ASRC_WIDTH_24_BIT)
+ reg24 = output->dma_vaddr + output->length;
+ else
+ reg16 = output->dma_vaddr + output->length;
+
+retry:
+ size = fsl_asrc_get_output_FIFO_size(pair);
+
+ for (i = 0; i < size * pair->channels; i++) {
+ regmap_read(asrc_priv->regmap, REG_ASRDO(index), &reg);
+ if (reg24) {
+ *(reg24) = reg;
+ reg24++;
+ } else {
+ *(reg16) = (u16)reg;
+ reg16++;
+ }
+ }
+ t_size += size;
+
+ if (size)
+ goto retry;
+
+ if (t_size > m2m->last_period_size)
+ t_size = m2m->last_period_size;
+
+ if (reg24)
+ output->length += t_size * pair->channels * 4;
+ else
+ output->length += t_size * pair->channels * 2;
+}
+
+static int fsl_allocate_dma_buf(struct fsl_asrc_pair *pair)
+{
+ struct fsl_asrc_m2m *m2m = pair->private;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct dma_block *input = &m2m->dma_block[IN];
+ struct dma_block *output = &m2m->dma_block[OUT];
+ enum asrc_pair_index index = pair->index;
+
+ input->dma_vaddr = kzalloc(input->length, GFP_KERNEL);
+ if (!input->dma_vaddr) {
+ pair_err("failed to allocate input DMA buffer\n");
+ return -ENOMEM;
+ }
+ input->dma_paddr = virt_to_dma(NULL, input->dma_vaddr);
+
+ output->dma_vaddr = kzalloc(output->length, GFP_KERNEL);
+ if (!output->dma_vaddr) {
+ pair_err("failed to allocate output DMA buffer\n");
+ goto exit;
+ }
+ output->dma_paddr = virt_to_dma(NULL, output->dma_vaddr);
+
+ return 0;
+
+exit:
+ kfree(input->dma_vaddr);
+
+ return -ENOMEM;
+}
+
+static int fsl_asrc_dmaconfig(struct fsl_asrc_pair *pair, struct dma_chan *chan,
+ u32 dma_addr, void *buf_addr, u32 buf_len,
+ bool dir, enum asrc_word_width word_width)
+{
+ struct dma_async_tx_descriptor *desc = pair->desc[dir];
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct fsl_asrc_m2m *m2m = pair->private;
+ unsigned int sg_nent = m2m->sg_nodes[dir];
+ enum asrc_pair_index index = pair->index;
+ struct scatterlist *sg = m2m->sg[dir];
+ struct dma_slave_config slave_config;
+ enum dma_slave_buswidth buswidth;
+ int ret, i;
+
+ switch (word_width) {
+ case ASRC_WIDTH_16_BIT:
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ break;
+ case ASRC_WIDTH_24_BIT:
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ break;
+ default:
+ pair_err("invalid word width\n");
+ return -EINVAL;
+ }
+
+ if (dir == IN) {
+ slave_config.direction = DMA_MEM_TO_DEV;
+ slave_config.dst_addr = dma_addr;
+ slave_config.dst_addr_width = buswidth;
+ slave_config.dst_maxburst =
+ m2m->watermark[IN] * pair->channels;
+ } else {
+ slave_config.direction = DMA_DEV_TO_MEM;
+ slave_config.src_addr = dma_addr;
+ slave_config.src_addr_width = buswidth;
+ slave_config.src_maxburst =
+ m2m->watermark[OUT] * pair->channels;
+ }
+
+ ret = dmaengine_slave_config(chan, &slave_config);
+ if (ret) {
+ pair_err("failed to config dmaengine for %sput task: %d\n",
+ DIR_STR(dir), ret);
+ return -EINVAL;
+ }
+
+ sg_init_table(sg, sg_nent);
+ switch (sg_nent) {
+ case 1:
+ sg_init_one(sg, buf_addr, buf_len);
+ break;
+ case 2:
+ case 3:
+ case 4:
+ for (i = 0; i < (sg_nent - 1); i++)
+ sg_set_buf(&sg[i], buf_addr + i * ASRC_MAX_BUFFER_SIZE,
+ ASRC_MAX_BUFFER_SIZE);
+
+ sg_set_buf(&sg[i], buf_addr + i * ASRC_MAX_BUFFER_SIZE,
+ buf_len - ASRC_MAX_BUFFER_SIZE * i);
+ break;
+ default:
+ pair_err("invalid input DMA nodes number: %d\n", sg_nent);
+ return -EINVAL;
+ }
+
+ ret = dma_map_sg(NULL, sg, sg_nent, slave_config.direction);
+ if (ret != sg_nent) {
+ pair_err("failed to map DMA sg for %sput task\n", DIR_STR(dir));
+ return -EINVAL;
+ }
+
+ desc = dmaengine_prep_slave_sg(chan, sg, sg_nent,
+ slave_config.direction, DMA_PREP_INTERRUPT);
+ if (!desc) {
+ pair_err("failed to prepare dmaengine for %sput task\n",
+ DIR_STR(dir));
+ return -EINVAL;
+ }
+
+ pair->desc[dir] = desc;
+ pair->desc[dir]->callback = ASRC_xPUT_DMA_CALLBACK(dir);
+
+ desc->callback = ASRC_xPUT_DMA_CALLBACK(dir);
+ desc->callback_param = pair;
+
+ return 0;
+}
+
+static int fsl_asrc_prepare_io_buffer(struct fsl_asrc_pair *pair,
+ struct asrc_convert_buffer *pbuf, bool dir)
+{
+ struct fsl_asrc_m2m *m2m = pair->private;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ unsigned int *dma_len = &m2m->dma_block[dir].length;
+ enum asrc_word_width width = m2m->word_width[dir];
+ void *dma_vaddr = m2m->dma_block[dir].dma_vaddr;
+ struct dma_chan *dma_chan = pair->dma_chan[dir];
+ unsigned int buf_len, wm = m2m->watermark[dir];
+ unsigned int *sg_nodes = &m2m->sg_nodes[dir];
+ unsigned int last_period_size = m2m->last_period_size;
+ enum asrc_pair_index index = pair->index;
+ u32 word_size, fifo_addr;
+ void __user *buf_vaddr;
+
+ /* Clean the DMA buffer */
+ memset(dma_vaddr, 0, ASRC_DMA_BUFFER_SIZE);
+
+ if (dir == IN) {
+ buf_vaddr = (void __user *)pbuf->input_buffer_vaddr;
+ buf_len = pbuf->input_buffer_length;
+ } else {
+ buf_vaddr = (void __user *)pbuf->output_buffer_vaddr;
+ buf_len = pbuf->output_buffer_length;
+ }
+
+ if (width == ASRC_WIDTH_24_BIT)
+ word_size = 4;
+ else
+ word_size = 2;
+
+ if (buf_len < word_size * pair->channels * wm ||
+ buf_len > ASRC_DMA_BUFFER_SIZE ||
+ (dir == OUT && buf_len < word_size * pair->channels * last_period_size)) {
+ pair_err("%sput buffer size is error: [%d]\n",
+ DIR_STR(dir), buf_len);
+ return -EINVAL;
+ }
+
+ /* Copy origin data into input buffer */
+ if (dir == IN && copy_from_user(dma_vaddr, buf_vaddr, buf_len))
+ return -EFAULT;
+
+ *dma_len = buf_len;
+ if (dir == OUT)
+ *dma_len -= last_period_size * word_size * pair->channels;
+
+ *sg_nodes = *dma_len / ASRC_MAX_BUFFER_SIZE + 1;
+
+ fifo_addr = asrc_priv->paddr + REG_ASRDx(dir, index);
+
+ return fsl_asrc_dmaconfig(pair, dma_chan, fifo_addr, dma_vaddr,
+ *dma_len, dir, width);
+}
+
+static int fsl_asrc_prepare_buffer(struct fsl_asrc_pair *pair,
+ struct asrc_convert_buffer *pbuf)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ int ret;
+
+ ret = fsl_asrc_prepare_io_buffer(pair, pbuf, IN);
+ if (ret) {
+ pair_err("failed to prepare input buffer: %d\n", ret);
+ return ret;
+ }
+
+ ret = fsl_asrc_prepare_io_buffer(pair, pbuf, OUT);
+ if (ret) {
+ pair_err("failed to prepare output buffer: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int fsl_asrc_process_buffer_pre(struct completion *complete,
+ enum asrc_pair_index index, bool dir)
+{
+ if (!wait_for_completion_interruptible_timeout(complete, 10 * HZ)) {
+ pr_err("%sput DMA task timeout\n", DIR_STR(dir));
+ return -ETIME;
+ } else if (signal_pending(current)) {
+ pr_err("%sput task forcibly aborted\n", DIR_STR(dir));
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+#define mxc_asrc_dma_umap(m2m) \
+ do { \
+ dma_unmap_sg(NULL, m2m->sg[IN], m2m->sg_nodes[IN], \
+ DMA_MEM_TO_DEV); \
+ dma_unmap_sg(NULL, m2m->sg[OUT], m2m->sg_nodes[OUT], \
+ DMA_DEV_TO_MEM); \
+ } while (0)
+
+int fsl_asrc_process_buffer(struct fsl_asrc_pair *pair,
+ struct asrc_convert_buffer *pbuf)
+{
+ struct fsl_asrc_m2m *m2m = pair->private;
+ enum asrc_pair_index index = pair->index;
+ unsigned long lock_flags;
+ int ret;
+
+ /* Check input task first */
+ ret = fsl_asrc_process_buffer_pre(&m2m->complete[IN], index, IN);
+ if (ret) {
+ mxc_asrc_dma_umap(m2m);
+ return ret;
+ }
+
+ /* ...then output task*/
+ ret = fsl_asrc_process_buffer_pre(&m2m->complete[OUT], index, OUT);
+ if (ret) {
+ mxc_asrc_dma_umap(m2m);
+ return ret;
+ }
+
+ mxc_asrc_dma_umap(m2m);
+
+ /* Fetch the remaining data */
+ spin_lock_irqsave(&m2m->lock, lock_flags);
+ if (!m2m->pair_hold) {
+ spin_unlock_irqrestore(&m2m->lock, lock_flags);
+ return -EFAULT;
+ }
+ spin_unlock_irqrestore(&m2m->lock, lock_flags);
+
+ fsl_asrc_read_last_FIFO(pair);
+
+ /* Update final lengths after getting last FIFO */
+ pbuf->input_buffer_length = m2m->dma_block[IN].length;
+ pbuf->output_buffer_length = m2m->dma_block[OUT].length;
+
+ if (copy_to_user((void __user *)pbuf->output_buffer_vaddr,
+ m2m->dma_block[OUT].dma_vaddr,
+ m2m->dma_block[OUT].length))
+ return -EFAULT;
+
+ return 0;
+}
+
+#ifdef ASRC_POLLING_WITHOUT_DMA
+/* THIS FUNCTION ONLY EXISTS FOR DEBUGGING AND ONLY SUPPORTS TWO CHANNELS */
+static void fsl_asrc_polling_debug(struct fsl_asrc_pair *pair)
+{
+ struct fsl_asrc_m2m *m2m = pair->private;
+ enum asrc_pair_index index = pair->index;
+ u32 *in24 = m2m->dma_block[IN].dma_vaddr;
+ u32 dma_len = m2m->dma_block[IN].length / (pair->channels * 4);
+ u32 *reg24 = m2m->dma_block[OUT].dma_vaddr;
+ u32 size, i, j, t_size, reg;
+
+ t_size = 0;
+
+ for (i = 0; i < dma_len; ) {
+ for (j = 0; j < 2; j++) {
+ regmap_write(asrc_priv->regmap, REG_ASRDx(index), *in24);
+ in24++;
+ regmap_write(asrc_priv->regmap, REG_ASRDx(index), *in24);
+ in24++;
+ i++;
+ }
+ udelay(50);
+ udelay(50 * m2m->rate[OUT] / m2m->rate[IN]);
+
+ size = fsl_asrc_get_output_FIFO_size(index);
+ for (j = 0; j < size; j++) {
+ regmap_read(asrc_priv->regmap, REG_ASRDO(index), &reg);
+ *(reg24) = reg;
+ reg24++;
+ regmap_read(asrc_priv->regmap, REG_ASRDO(index), &reg);
+ *(reg24) = reg;
+ reg24++;
+ }
+ t_size += size;
+ }
+
+ mdelay(1);
+ size = fsl_asrc_get_output_FIFO_size(index);
+ for (j = 0; j < size; j++) {
+ regmap_read(asrc_priv->regmap, REG_ASRDO(index), &reg);
+ *(reg24) = reg;
+ reg24++;
+ regmap_read(asrc_priv->regmap, REG_ASRDO(index), &reg);
+ *(reg24) = reg;
+ reg24++;
+ }
+ t_size += size;
+
+ m2m->dma_block[OUT].length = t_size * pair->channels * 4;
+
+ complete(&m2m->complete[OUT]);
+ complete(&m2m->complete[IN]);
+}
+#else
+static void fsl_asrc_submit_dma(struct fsl_asrc_pair *pair)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct fsl_asrc_m2m *m2m = pair->private;
+ enum asrc_pair_index index = pair->index;
+ u32 size = fsl_asrc_get_output_FIFO_size(pair);
+ int i;
+
+ /* Read all data in OUTPUT FIFO */
+ while (size) {
+ u32 val;
+ for (i = 0; i < size * pair->channels; i++)
+ regmap_read(asrc_priv->regmap, REG_ASRDO(index), &val);
+ /* Fetch the data every 100us */
+ udelay(100);
+
+ size = fsl_asrc_get_output_FIFO_size(pair);
+ }
+
+ /* Submit DMA request */
+ dmaengine_submit(pair->desc[IN]);
+ dma_async_issue_pending(pair->desc[IN]->chan);
+
+ dmaengine_submit(pair->desc[OUT]);
+ dma_async_issue_pending(pair->desc[OUT]->chan);
+
+ /*
+ * Clear DMA request during the stall state of ASRC:
+ * During STALL state, the remaining in input fifo would never be
+ * smaller than the input threshold while the output fifo would not
+ * be bigger than output one. Thus the DMA request would be cleared.
+ */
+ fsl_asrc_set_watermarks(pair, ASRC_FIFO_THRESHOLD_MIN,
+ ASRC_FIFO_THRESHOLD_MAX);
+
+ /* Update the real input threshold to raise DMA request */
+ fsl_asrc_set_watermarks(pair, m2m->watermark[IN], m2m->watermark[OUT]);
+}
+#endif /* ASRC_POLLING_WITHOUT_DMA */
+
+static long fsl_asrc_ioctl_req_pair(struct fsl_asrc_pair *pair,
+ void __user *user)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct fsl_asrc_m2m *m2m = pair->private;
+ struct device *dev = &asrc_priv->pdev->dev;
+ struct asrc_req req;
+ unsigned long lock_flags;
+ long ret;
+
+ ret = copy_from_user(&req, user, sizeof(req));
+ if (ret) {
+ dev_err(dev, "failed to get req from user space: %ld\n", ret);
+ return ret;
+ }
+
+ ret = fsl_asrc_request_pair(req.chn_num, pair);
+ if (ret) {
+ dev_err(dev, "failed to request pair: %ld\n", ret);
+ return ret;
+ }
+
+ spin_lock_irqsave(&m2m->lock, lock_flags);
+ m2m->pair_hold = 1;
+ spin_unlock_irqrestore(&m2m->lock, lock_flags);
+ pair->channels = req.chn_num;
+
+ req.index = pair->index;
+
+ ret = copy_to_user(user, &req, sizeof(req));
+ if (ret) {
+ dev_err(dev, "failed to send req to user space: %ld\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static long fsl_asrc_ioctl_config_pair(struct fsl_asrc_pair *pair,
+ void __user *user)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct fsl_asrc_m2m *m2m = pair->private;
+ struct device *dev = &asrc_priv->pdev->dev;
+ struct asrc_config config;
+ enum asrc_pair_index index;
+ long ret;
+
+ ret = copy_from_user(&config, user, sizeof(config));
+ if (ret) {
+ dev_err(dev, "failed to get config from user space: %ld\n", ret);
+ return ret;
+ }
+
+ index = config.pair;
+
+ pair->config = &config;
+ ret = fsl_asrc_config_pair(pair, false, false);
+ if (ret) {
+ pair_err("failed to config pair: %ld\n", ret);
+ return ret;
+ }
+
+ m2m->watermark[IN] = FSL_ASRC_INPUTFIFO_WML;
+ m2m->watermark[OUT] = FSL_ASRC_OUTPUTFIFO_WML;
+
+ fsl_asrc_set_watermarks(pair, m2m->watermark[IN], m2m->watermark[OUT]);
+
+ m2m->dma_block[IN].length = ASRC_DMA_BUFFER_SIZE;
+ m2m->dma_block[OUT].length = ASRC_DMA_BUFFER_SIZE;
+
+ m2m->word_width[IN] = config.input_word_width;
+ m2m->word_width[OUT] = config.output_word_width;
+
+ m2m->rate[IN] = config.input_sample_rate;
+ m2m->rate[OUT] = config.output_sample_rate;
+
+ if (m2m->rate[OUT] >= m2m->rate[IN] * 8)
+ m2m->last_period_size = (m2m->rate[OUT] / m2m->rate[IN]) * 5;
+ else if (m2m->rate[OUT] > m2m->rate[IN])
+ m2m->last_period_size = ASRC_OUTPUT_LAST_SAMPLE_MAX;
+ else
+ m2m->last_period_size = ASRC_OUTPUT_LAST_SAMPLE;
+
+ ret = fsl_allocate_dma_buf(pair);
+ if (ret) {
+ pair_err("failed to allocate DMA buffer: %ld\n", ret);
+ return ret;
+ }
+
+ /* Request DMA channel for both input and output */
+ pair->dma_chan[IN] = fsl_asrc_get_dma_channel(pair, IN);
+ if (pair->dma_chan[IN] == NULL) {
+ pair_err("failed to request input task DMA channel\n");
+ return -EBUSY;
+ }
+
+ pair->dma_chan[OUT] = fsl_asrc_get_dma_channel(pair, OUT);
+ if (pair->dma_chan[OUT] == NULL) {
+ pair_err("failed to request output task DMA channel\n");
+ return -EBUSY;
+ }
+
+ ret = copy_to_user(user, &config, sizeof(config));
+ if (ret) {
+ pair_err("failed to send config to user space: %ld\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static long fsl_asrc_ioctl_release_pair(struct fsl_asrc_pair *pair,
+ void __user *user)
+{
+ struct fsl_asrc_m2m *m2m = pair->private;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index;
+ unsigned long lock_flags;
+ long ret;
+
+ ret = copy_from_user(&index, user, sizeof(index));
+ if (ret) {
+ pair_err("failed to get index from user space: %ld\n", ret);
+ return ret;
+ }
+
+ /* index might be not valid due to some application failure. */
+ if (index < 0)
+ return -EINVAL;
+
+ m2m->asrc_active = 0;
+
+ spin_lock_irqsave(&m2m->lock, lock_flags);
+ m2m->pair_hold = 0;
+ spin_unlock_irqrestore(&m2m->lock, lock_flags);
+
+ if (pair->dma_chan[IN])
+ dma_release_channel(pair->dma_chan[IN]);
+ if (pair->dma_chan[OUT])
+ dma_release_channel(pair->dma_chan[OUT]);
+ kfree(m2m->dma_block[IN].dma_vaddr);
+ kfree(m2m->dma_block[OUT].dma_vaddr);
+ fsl_asrc_release_pair(pair);
+
+ return 0;
+}
+
+static long fsl_asrc_ioctl_convert(struct fsl_asrc_pair *pair,
+ void __user *user)
+{
+ struct fsl_asrc_m2m *m2m = pair->private;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ struct asrc_convert_buffer buf;
+ long ret;
+
+ ret = copy_from_user(&buf, user, sizeof(buf));
+ if (ret) {
+ pair_err("failed to get buf from user space: %ld\n", ret);
+ return ret;
+ }
+
+ ret = fsl_asrc_prepare_buffer(pair, &buf);
+ if (ret) {
+ pair_err("failed to prepare buffer: %ld\n", ret);
+ return ret;
+ }
+
+ init_completion(&m2m->complete[IN]);
+ init_completion(&m2m->complete[OUT]);
+
+#ifdef ASRC_POLLING_WITHOUT_DMA
+ fsl_asrc_polling_debug(pair);
+#else
+ fsl_asrc_submit_dma(pair);
+#endif
+
+ ret = fsl_asrc_process_buffer(pair, &buf);
+ if (ret) {
+ pair_err("failed to process buffer: %ld\n", ret);
+ return ret;
+ }
+
+ ret = copy_to_user(user, &buf, sizeof(buf));
+ if (ret) {
+ pair_err("failed to send buf to user space: %ld\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static long fsl_asrc_ioctl_start_conv(struct fsl_asrc_pair *pair,
+ void __user *user)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct fsl_asrc_m2m *m2m = pair->private;
+ enum asrc_pair_index index;
+ long ret;
+
+ ret = copy_from_user(&index, user, sizeof(index));
+ if (ret) {
+ pair_err("failed to get index from user space: %ld\n", ret);
+ return ret;
+ }
+
+ m2m->asrc_active = 1;
+ fsl_asrc_start_pair(pair);
+
+ return 0;
+}
+
+static long fsl_asrc_ioctl_stop_conv(struct fsl_asrc_pair *pair,
+ void __user *user)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct fsl_asrc_m2m *m2m = pair->private;
+ enum asrc_pair_index index;
+ long ret;
+
+ ret = copy_from_user(&index, user, sizeof(index));
+ if (ret) {
+ pair_err("failed to get index from user space: %ld\n", ret);
+ return ret;
+ }
+
+ dmaengine_terminate_all(pair->dma_chan[IN]);
+ dmaengine_terminate_all(pair->dma_chan[OUT]);
+
+ fsl_asrc_stop_pair(pair);
+ m2m->asrc_active = 0;
+
+ return 0;
+}
+
+static long fsl_asrc_ioctl_status(struct fsl_asrc_pair *pair, void __user *user)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+ struct asrc_status_flags flags;
+ long ret;
+
+ ret = copy_from_user(&flags, user, sizeof(flags));
+ if (ret) {
+ pair_err("failed to get flags from user space: %ld\n", ret);
+ return ret;
+ }
+
+ fsl_asrc_get_status(pair, &flags);
+
+ ret = copy_to_user(user, &flags, sizeof(flags));
+ if (ret) {
+ pair_err("failed to send flags to user space: %ld\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static long fsl_asrc_ioctl_flush(struct fsl_asrc_pair *pair, void __user *user)
+{
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ enum asrc_pair_index index = pair->index;
+
+ /* Release DMA and request again */
+ dma_release_channel(pair->dma_chan[IN]);
+ dma_release_channel(pair->dma_chan[OUT]);
+
+ pair->dma_chan[IN] = fsl_asrc_get_dma_channel(pair, IN);
+ if (pair->dma_chan[IN] == NULL) {
+ pair_err("failed to request input task DMA channel\n");
+ return -EBUSY;
+ }
+
+ pair->dma_chan[OUT] = fsl_asrc_get_dma_channel(pair, OUT);
+ if (pair->dma_chan[OUT] == NULL) {
+ pair_err("failed to request output task DMA channel\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static long fsl_asrc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct fsl_asrc_pair *pair = file->private_data;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ void __user *user = (void __user *)arg;
+ long ret = 0;
+
+ switch (cmd) {
+ case ASRC_REQ_PAIR:
+ ret = fsl_asrc_ioctl_req_pair(pair, user);
+ break;
+ case ASRC_CONFIG_PAIR:
+ ret = fsl_asrc_ioctl_config_pair(pair, user);
+ break;
+ case ASRC_RELEASE_PAIR:
+ ret = fsl_asrc_ioctl_release_pair(pair, user);
+ break;
+ case ASRC_CONVERT:
+ ret = fsl_asrc_ioctl_convert(pair, user);
+ break;
+ case ASRC_START_CONV:
+ ret = fsl_asrc_ioctl_start_conv(pair, user);
+ break;
+ case ASRC_STOP_CONV:
+ ret = fsl_asrc_ioctl_stop_conv(pair, user);
+ break;
+ case ASRC_STATUS:
+ ret = fsl_asrc_ioctl_status(pair, user);
+ break;
+ case ASRC_FLUSH:
+ ret = fsl_asrc_ioctl_flush(pair, user);
+ break;
+ default:
+ dev_err(&asrc_priv->pdev->dev, "invalid ioctl cmd!\n");
+ break;
+ }
+
+ return ret;
+}
+
+static int fsl_asrc_open(struct inode *inode, struct file *file)
+{
+ struct fsl_asrc *asrc_priv = dev_get_drvdata(asrc_miscdev.this_device);
+ struct device *dev = &asrc_priv->pdev->dev;
+ struct fsl_asrc_pair *pair;
+ struct fsl_asrc_m2m *m2m;
+ int ret;
+
+ ret = signal_pending(current);
+ if (ret) {
+ dev_err(dev, "current process has a signal pending\n");
+ return ret;
+ }
+
+ pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL);
+ if (!pair) {
+ dev_err(dev, "failed to allocate pair\n");
+ return -ENOMEM;
+ }
+
+ m2m = kzalloc(sizeof(struct fsl_asrc_m2m), GFP_KERNEL);
+ if (!m2m) {
+ dev_err(dev, "failed to allocate m2m resource\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ pair->private = m2m;
+ pair->asrc_priv = asrc_priv;
+
+ spin_lock_init(&m2m->lock);
+
+ file->private_data = pair;
+
+ pm_runtime_get_sync(dev);
+
+ return 0;
+out:
+ kfree(pair);
+
+ return ret;
+}
+
+static int fsl_asrc_close(struct inode *inode, struct file *file)
+{
+ struct fsl_asrc_pair *pair = file->private_data;
+ struct fsl_asrc_m2m *m2m = pair->private;
+ struct fsl_asrc *asrc_priv = pair->asrc_priv;
+ struct device *dev = &asrc_priv->pdev->dev;
+ unsigned long lock_flags;
+
+ if (m2m->asrc_active) {
+ m2m->asrc_active = 0;
+
+ dmaengine_terminate_all(pair->dma_chan[IN]);
+ dmaengine_terminate_all(pair->dma_chan[OUT]);
+
+ fsl_asrc_stop_pair(pair);
+ fsl_asrc_input_dma_callback((void *)pair);
+ fsl_asrc_output_dma_callback((void *)pair);
+ }
+
+ spin_lock_irqsave(&m2m->lock, lock_flags);
+ if (m2m->pair_hold) {
+ m2m->pair_hold = 0;
+ spin_unlock_irqrestore(&m2m->lock, lock_flags);
+
+ if (pair->dma_chan[IN])
+ dma_release_channel(pair->dma_chan[IN]);
+ if (pair->dma_chan[OUT])
+ dma_release_channel(pair->dma_chan[OUT]);
+
+ kfree(m2m->dma_block[IN].dma_vaddr);
+ kfree(m2m->dma_block[OUT].dma_vaddr);
+
+ fsl_asrc_release_pair(pair);
+ } else
+ spin_unlock_irqrestore(&m2m->lock, lock_flags);
+
+ spin_lock_irqsave(&asrc_priv->lock, lock_flags);
+ kfree(m2m);
+ kfree(pair);
+ spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
+ file->private_data = NULL;
+
+ pm_runtime_put_sync(dev);
+
+ return 0;
+}
+
+static const struct file_operations asrc_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = fsl_asrc_ioctl,
+ .open = fsl_asrc_open,
+ .release = fsl_asrc_close,
+};
+
+static int fsl_asrc_m2m_init(struct fsl_asrc *asrc_priv)
+{
+ struct device *dev = &asrc_priv->pdev->dev;
+ int ret;
+
+ asrc_miscdev.fops = &asrc_fops,
+ ret = misc_register(&asrc_miscdev);
+ if (ret) {
+ dev_err(dev, "failed to register char device %d\n", ret);
+ return ret;
+ }
+ dev_set_drvdata(asrc_miscdev.this_device, asrc_priv);
+
+ return 0;
+}
+
+static int fsl_asrc_m2m_remove(struct platform_device *pdev)
+{
+ misc_deregister(&asrc_miscdev);
+ return 0;
+}
+
+static void fsl_asrc_m2m_suspend(struct fsl_asrc *asrc_priv)
+{
+ struct fsl_asrc_pair *pair;
+ struct fsl_asrc_m2m *m2m;
+ unsigned long lock_flags;
+ int i;
+
+ for (i = 0; i < ASRC_PAIR_MAX_NUM; i++) {
+ spin_lock_irqsave(&asrc_priv->lock, lock_flags);
+ pair = asrc_priv->pair[i];
+ if (!pair || !pair->private) {
+ spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
+ continue;
+ }
+ m2m = pair->private;
+
+ if (!completion_done(&m2m->complete[IN])) {
+ if (pair->dma_chan[IN])
+ dmaengine_terminate_all(pair->dma_chan[IN]);
+ fsl_asrc_input_dma_callback((void *)pair);
+ }
+ if (!completion_done(&m2m->complete[OUT])) {
+ if (pair->dma_chan[OUT])
+ dmaengine_terminate_all(pair->dma_chan[OUT]);
+ fsl_asrc_output_dma_callback((void *)pair);
+ }
+
+ spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
+ }
+}
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 38bfd46f4ad8..93b5f59a27cc 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -1,7 +1,8 @@
/*
* Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver
*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
@@ -50,6 +51,7 @@
struct fsl_esai {
struct snd_dmaengine_dai_dma_data dma_params_rx;
struct snd_dmaengine_dai_dma_data dma_params_tx;
+ struct snd_pcm_substream *substream[2];
struct platform_device *pdev;
struct regmap *regmap;
struct clk *coreclk;
@@ -59,6 +61,8 @@ struct fsl_esai {
u32 fifo_depth;
u32 slot_width;
u32 slots;
+ u32 tx_mask;
+ u32 rx_mask;
u32 hck_rate[2];
u32 sck_rate[2];
bool hck_dir[2];
@@ -220,6 +224,21 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned long clk_rate;
int ret;
+ if (esai_priv->synchronous && !tx) {
+ switch (clk_id) {
+ case ESAI_HCKR_FSYS:
+ fsl_esai_set_dai_sysclk(dai, ESAI_HCKT_FSYS,
+ freq, dir);
+ break;
+ case ESAI_HCKR_EXTAL:
+ fsl_esai_set_dai_sysclk(dai, ESAI_HCKT_EXTAL,
+ freq, dir);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
/* Bypass divider settings if the requirement doesn't change */
if (freq == esai_priv->hck_rate[tx] && dir == esai_priv->hck_dir[tx])
return 0;
@@ -241,6 +260,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
break;
case ESAI_HCKT_EXTAL:
ecr |= ESAI_ECR_ETI;
+ break;
case ESAI_HCKR_EXTAL:
ecr |= ESAI_ECR_ERI;
break;
@@ -352,21 +372,13 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
- regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
- ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
- regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
- ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
-
regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
- regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
- ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
- regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
- ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
-
esai_priv->slot_width = slot_width;
esai_priv->slots = slots;
+ esai_priv->tx_mask = tx_mask;
+ esai_priv->rx_mask = rx_mask;
return 0;
}
@@ -389,7 +401,8 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
break;
case SND_SOC_DAIFMT_RIGHT_J:
/* Data on rising edge of bclk, frame high, right aligned */
- xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCR_xWA;
+ xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
+ xcr |= ESAI_xCR_xWA;
break;
case SND_SOC_DAIFMT_DSP_A:
/* Data on rising edge of bclk, frame high, 1clk before data */
@@ -446,12 +459,12 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return -EINVAL;
}
- mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR;
+ mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR | ESAI_xCR_xWA;
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);
mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
- ESAI_xCCR_xFSD | ESAI_xCCR_xCKD | ESAI_xCR_xWA;
+ ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);
@@ -500,6 +513,8 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
}
+ esai_priv->substream[substream->stream] = substream;
+
return 0;
err_fsysclk:
@@ -533,10 +548,21 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
bclk = params_rate(params) * slot_width * esai_priv->slots;
- ret = fsl_esai_set_bclk(dai, tx, bclk);
+ ret = fsl_esai_set_bclk(dai, esai_priv->synchronous ? true : tx, bclk);
if (ret)
return ret;
+ if (esai_priv->synchronous && !tx) {
+ /* Use Normal mode to support monaural audio */
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
+ ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
+ ESAI_xCR_xMOD_NETWORK : 0);
+
+ mask = ESAI_xCR_xSWS_MASK | ESAI_xCR_PADC;
+ val = ESAI_xCR_xSWS(slot_width, width) | ESAI_xCR_PADC;
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, val);
+ }
+
/* Use Normal mode to support monaural audio */
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
@@ -570,6 +596,8 @@ static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
{
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+ esai_priv->substream[substream->stream] = NULL;
+
if (!IS_ERR(esai_priv->fsysclk))
clk_disable_unprepare(esai_priv->fsysclk);
if (!IS_ERR(esai_priv->extalclk))
@@ -586,6 +614,7 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
u8 i, channels = substream->runtime->channels;
u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
+ u32 mask;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -601,12 +630,23 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
+ mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
+
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
+ ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
+ ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
+
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
+ ESAI_xSMA_xS_MASK, 0);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
+ ESAI_xSMB_xS_MASK, 0);
/* Disable and reset FIFO */
regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
@@ -784,6 +824,83 @@ static const struct regmap_config fsl_esai_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static bool fsl_esai_check_xrun(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai);
+ u32 saisr;
+
+ regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr);
+
+ return saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE) ;
+}
+
+/*
+ *Here is ESAI underrun reset step:
+ *1. Read "TUE" and got TUE=1
+ *2. stop DMA.
+ *3. stop ESAI TX section.
+ *4. Set the transmitter section individual reset "TPR=1"
+ *5. Reset the ESAI Transmit FIFO (set ESAI_TFCR[1]=1).
+ *6. Config the control registers ESAI_TCCR and ESAI_TCR.config the Transmit FIFO register.
+ *7. clear "TPR"
+ *8. read "TUE"
+ *9. Prefill ESAI TX FIFO.
+ *10.Start DMA.
+ *11 Enable the ESAI
+ */
+static void fsl_esai_reset(struct snd_pcm_substream *substream, bool stop)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned long flags = 0;
+ u32 saisr;
+
+ if (stop)
+ imx_stop_lock_pcm_streams(esai_priv->substream, 2, &flags);
+
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
+ ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
+ ESAI_ECR_ESAIEN | ESAI_ECR_ERST);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
+ ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
+ ESAI_ECR_ESAIEN);
+
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, ESAI_xCR_xPR_MASK, ESAI_xCR_xPR);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, ESAI_xCR_xPR_MASK, ESAI_xCR_xPR);
+
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, ESAI_PRRC_PDC_MASK, 0);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, ESAI_PCRC_PC_MASK, 0);
+
+ /*
+ * Add fifo reset here, because the regcache_sync will write one more data to ETDR.
+ * Which will cause channel shift.
+ */
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
+
+ regcache_mark_dirty(esai_priv->regmap);
+ regcache_sync(esai_priv->regmap);
+
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR_MASK, 0);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR_MASK, 0);
+
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, ESAI_xCR_xPR_MASK, 0);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, ESAI_xCR_xPR_MASK, 0);
+
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
+ ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
+ ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
+
+ regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr);
+
+ if (stop)
+ imx_start_unlock_pcm_streams(esai_priv->substream, 2, &flags);
+}
+
static int fsl_esai_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -792,6 +909,8 @@ static int fsl_esai_probe(struct platform_device *pdev)
const uint32_t *iprop;
void __iomem *regs;
int irq, ret;
+ u32 buffer_size;
+ unsigned long irqflag = 0;
esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL);
if (!esai_priv)
@@ -842,7 +961,11 @@ static int fsl_esai_probe(struct platform_device *pdev)
return irq;
}
- ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0,
+ /* ESAI shared interrupt */
+ if (of_property_read_bool(np, "shared-interrupt"))
+ irqflag = IRQF_SHARED;
+
+ ret = devm_request_irq(&pdev->dev, irq, esai_isr, irqflag,
esai_priv->name, esai_priv);
if (ret) {
dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
@@ -867,6 +990,16 @@ static int fsl_esai_probe(struct platform_device *pdev)
esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR;
esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR;
+ /* From imx6ull, the channel swap issue in underrun/overrun is
+ * fixed in hardware. So remove the workaround.
+ */
+ if (!of_device_is_compatible(pdev->dev.of_node, "fsl,imx6ull-esai")) {
+ esai_priv->dma_params_tx.check_xrun = fsl_esai_check_xrun;
+ esai_priv->dma_params_rx.check_xrun = fsl_esai_check_xrun;
+ esai_priv->dma_params_tx.device_reset = fsl_esai_reset;
+ esai_priv->dma_params_rx.device_reset = fsl_esai_reset;
+ }
+
esai_priv->synchronous =
of_property_read_bool(np, "fsl,esai-synchronous");
@@ -896,6 +1029,12 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}
+ /* Clear the TSMA, TSMB, RSMA, RSMB */
+ regmap_write(esai_priv->regmap, REG_ESAI_TSMA, 0);
+ regmap_write(esai_priv->regmap, REG_ESAI_TSMB, 0);
+ regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0);
+ regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0);
+
ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
&fsl_esai_dai, 1);
if (ret) {
@@ -903,7 +1042,10 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}
- ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE);
+ if (of_property_read_u32(np, "fsl,dma-buffer-size", &buffer_size))
+ buffer_size = IMX_ESAI_DMABUF_SIZE;
+
+ ret = imx_pcm_dma_init(pdev, buffer_size);
if (ret)
dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
@@ -911,6 +1053,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
}
static const struct of_device_id fsl_esai_dt_ids[] = {
+ { .compatible = "fsl,imx6ull-esai", },
{ .compatible = "fsl,imx35-esai", },
{ .compatible = "fsl,vf610-esai", },
{}
diff --git a/sound/soc/fsl/fsl_hdmi.c b/sound/soc/fsl/fsl_hdmi.c
new file mode 100644
index 000000000000..0a0fafc360c9
--- /dev/null
+++ b/sound/soc/fsl/fsl_hdmi.c
@@ -0,0 +1,750 @@
+/*
+ * ALSA SoC HDMI Audio Layer for Freescale i.MX
+ *
+ * Copyright (C) 2011-2014 Freescale Semiconductor, Inc.
+ *
+ * Some code from patch_hdmi.c
+ * Copyright (c) 2008-2010 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 ATI Technologies Inc.
+ * Copyright (c) 2008 NVIDIA Corp. All rights reserved.
+ * Copyright (c) 2008 Wei Ni <wni@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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/init.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/asoundef.h>
+#include <sound/hdmi-codec.h>
+
+#include <video/mxc_hdmi.h>
+
+#include "imx-hdmi.h"
+
+
+static struct mxc_edid_cfg edid_cfg;
+
+static u32 playback_rates[HDMI_MAX_RATES];
+static u32 playback_sample_size[HDMI_MAX_SAMPLE_SIZE];
+static u32 playback_channels[HDMI_MAX_CHANNEL_CONSTRAINTS];
+
+static struct snd_pcm_hw_constraint_list playback_constraint_rates;
+static struct snd_pcm_hw_constraint_list playback_constraint_bits;
+static struct snd_pcm_hw_constraint_list playback_constraint_channels;
+
+#ifdef DEBUG
+static void dumpregs(struct snd_soc_dai *dai)
+{
+ u32 n, cts;
+
+ cts = (hdmi_readb(HDMI_AUD_CTS3) << 16) |
+ (hdmi_readb(HDMI_AUD_CTS2) << 8) |
+ hdmi_readb(HDMI_AUD_CTS1);
+
+ n = (hdmi_readb(HDMI_AUD_N3) << 16) |
+ (hdmi_readb(HDMI_AUD_N2) << 8) |
+ hdmi_readb(HDMI_AUD_N1);
+
+ dev_dbg(dai->dev, "HDMI_PHY_CONF0 0x%02x\n",
+ hdmi_readb(HDMI_PHY_CONF0));
+ dev_dbg(dai->dev, "HDMI_MC_CLKDIS 0x%02x\n",
+ hdmi_readb(HDMI_MC_CLKDIS));
+ dev_dbg(dai->dev, "HDMI_AUD_N[1-3] 0x%06x (%d)\n",
+ n, n);
+ dev_dbg(dai->dev, "HDMI_AUD_CTS[1-3] 0x%06x (%d)\n",
+ cts, cts);
+ dev_dbg(dai->dev, "HDMI_FC_AUDSCONF 0x%02x\n",
+ hdmi_readb(HDMI_FC_AUDSCONF));
+}
+#else
+static void dumpregs(struct snd_soc_dai *dai) {}
+#endif
+
+enum cea_speaker_placement {
+ FL = (1 << 0), /* Front Left */
+ FC = (1 << 1), /* Front Center */
+ FR = (1 << 2), /* Front Right */
+ FLC = (1 << 3), /* Front Left Center */
+ FRC = (1 << 4), /* Front Right Center */
+ RL = (1 << 5), /* Rear Left */
+ RC = (1 << 6), /* Rear Center */
+ RR = (1 << 7), /* Rear Right */
+ RLC = (1 << 8), /* Rear Left Center */
+ RRC = (1 << 9), /* Rear Right Center */
+ LFE = (1 << 10), /* Low Frequency Effect */
+ FLW = (1 << 11), /* Front Left Wide */
+ FRW = (1 << 12), /* Front Right Wide */
+ FLH = (1 << 13), /* Front Left High */
+ FCH = (1 << 14), /* Front Center High */
+ FRH = (1 << 15), /* Front Right High */
+ TC = (1 << 16), /* Top Center */
+};
+
+/*
+ * EDID SA bits in the CEA Speaker Allocation data block
+ */
+static int edid_speaker_allocation_bits[] = {
+ [0] = FL | FR,
+ [1] = LFE,
+ [2] = FC,
+ [3] = RL | RR,
+ [4] = RC,
+ [5] = FLC | FRC,
+ [6] = RLC | RRC,
+ [7] = FLW | FRW,
+ [8] = FLH | FRH,
+ [9] = TC,
+ [10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+ int ca_index;
+ int speakers[8];
+
+ /* Derived values, just for convenience */
+ int channels;
+ int spk_mask;
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+ /* channel: 7 6 5 4 3 2 1 0 */
+ { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL },},
+ /* 2.1 */
+ { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL },},
+ /* Dolby Surround */
+ { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL },},
+ { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL },},
+ { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL },},
+ { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL },},
+ { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL },},
+ { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL },},
+ { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL },},
+ { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL },},
+ { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL },},
+ /* surround51 */
+ { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL },},
+ { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL },},
+ { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL },},
+ /* 6.1 */
+ { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL },},
+ { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL },},
+ { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL },},
+ /* surround71 */
+ { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL },},
+ { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL },},
+ { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL },},
+ { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL },},
+ { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL },},
+ { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL },},
+ { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL },},
+ { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL },},
+ { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL },},
+ { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL },},
+ { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL },},
+ { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL },},
+ { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL },},
+ { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL },},
+ { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL },},
+ { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL },},
+ { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL },},
+ { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL },},
+ { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL },},
+ { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL },},
+ { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL },},
+ { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL },},
+ { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL },},
+ { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL },},
+};
+
+/* Compute derived values in channel_allocations[] */
+static void init_channel_allocations(void)
+{
+ struct cea_channel_speaker_allocation *p;
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+ p = channel_allocations + i;
+ p->channels = 0;
+ p->spk_mask = 0;
+ for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+ if (p->speakers[j]) {
+ p->channels++;
+ p->spk_mask |= p->speakers[j];
+ }
+ }
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * speaker_alloc => (edid_speaker_allocation_bits[]) => spk_mask
+ * spk_mask => (channel_allocations[]) => CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_channel_allocation(int channels)
+{
+ int spk_mask = 0, ca = 0, i, tmpchn, tmpspk;
+
+ /* CA defaults to 0 for basic stereo audio */
+ if (channels <= 2)
+ return 0;
+
+ /*
+ * Expand EDID's speaker allocation mask
+ *
+ * EDID tells the speaker mask in a compact(paired) form,
+ * expand EDID's notions to match the ones used by Audio InfoFrame.
+ */
+ for (i = 0; i < ARRAY_SIZE(edid_speaker_allocation_bits); i++) {
+ if (edid_cfg.speaker_alloc & (1 << i))
+ spk_mask |= edid_speaker_allocation_bits[i];
+ }
+
+ /* Search for the first working match in the CA table */
+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+ tmpchn = channel_allocations[i].channels;
+ tmpspk = channel_allocations[i].spk_mask;
+
+ if (channels == tmpchn && (spk_mask & tmpspk) == tmpspk) {
+ ca = channel_allocations[i].ca_index;
+ break;
+ }
+ }
+
+ return ca;
+}
+
+static void hdmi_set_audio_infoframe(unsigned int channels)
+{
+ u8 audiconf0, audiconf2;
+
+ /*
+ * From CEA-861-D spec:
+ * HDMI requires the CT, SS and SF fields to be set to 0 ("Refer
+ * to Stream Header") as these items are carried in the audio stream.
+ *
+ * So we only set the CC and CA fields.
+ */
+ audiconf0 = ((channels - 1) << HDMI_FC_AUDICONF0_CC_OFFSET) &
+ HDMI_FC_AUDICONF0_CC_MASK;
+
+ audiconf2 = hdmi_channel_allocation(channels);
+
+ hdmi_writeb(audiconf0, HDMI_FC_AUDICONF0);
+ hdmi_writeb(0, HDMI_FC_AUDICONF1);
+ hdmi_writeb(audiconf2, HDMI_FC_AUDICONF2);
+ hdmi_writeb(0, HDMI_FC_AUDICONF3);
+}
+
+static int cea_audio_rates[HDMI_MAX_RATES] = {
+ 32000, 44100, 48000, 88200, 96000, 176400, 192000,
+};
+
+static void fsl_hdmi_get_playback_rates(void)
+{
+ int i, count = 0;
+ u8 rates;
+
+ /* Always assume basic audio support */
+ rates = edid_cfg.sample_rates | 0x7;
+
+ for (i = 0 ; i < HDMI_MAX_RATES ; i++)
+ if ((rates & (1 << i)) != 0)
+ playback_rates[count++] = cea_audio_rates[i];
+
+ playback_constraint_rates.list = playback_rates;
+ playback_constraint_rates.count = count;
+
+ for (i = 0 ; i < playback_constraint_rates.count ; i++)
+ pr_debug("%s: constraint = %d Hz\n", __func__, playback_rates[i]);
+}
+
+static void fsl_hdmi_get_playback_sample_size(void)
+{
+ int i = 0;
+
+ /* Always assume basic audio support */
+ playback_sample_size[i++] = 16;
+
+ if (edid_cfg.sample_sizes & 0x4)
+ playback_sample_size[i++] = 24;
+
+ playback_constraint_bits.list = playback_sample_size;
+ playback_constraint_bits.count = i;
+
+ for (i = 0 ; i < playback_constraint_bits.count ; i++)
+ pr_debug("%s: constraint = %d bits\n", __func__, playback_sample_size[i]);
+}
+
+static void fsl_hdmi_get_playback_channels(void)
+{
+ int channels = 2, i = 0;
+
+ /* Always assume basic audio support */
+ playback_channels[i++] = channels;
+ channels += 2;
+
+ while ((i < HDMI_MAX_CHANNEL_CONSTRAINTS) &&
+ (channels <= edid_cfg.max_channels)) {
+ playback_channels[i++] = channels;
+ channels += 2;
+ }
+
+ playback_constraint_channels.list = playback_channels;
+ playback_constraint_channels.count = i;
+
+ for (i = 0 ; i < playback_constraint_channels.count ; i++)
+ pr_debug("%s: constraint = %d channels\n", __func__, playback_channels[i]);
+}
+
+static int fsl_hdmi_update_constraints(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ hdmi_get_edid_cfg(&edid_cfg);
+
+ fsl_hdmi_get_playback_rates();
+ ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &playback_constraint_rates);
+ if (ret)
+ return ret;
+
+ fsl_hdmi_get_playback_sample_size();
+ ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ &playback_constraint_bits);
+ if (ret)
+ return ret;
+
+ fsl_hdmi_get_playback_channels();
+ ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &playback_constraint_channels);
+ if (ret)
+ return ret;
+
+ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int fsl_hdmi_soc_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct imx_hdmi *hdmi_data = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ clk_prepare_enable(hdmi_data->mipi_core_clk);
+ clk_prepare_enable(hdmi_data->isfr_clk);
+ clk_prepare_enable(hdmi_data->iahb_clk);
+
+ dev_dbg(dai->dev, "%s hdmi clks: mipi_core: %d isfr:%d iahb:%d\n", __func__,
+ (int)clk_get_rate(hdmi_data->mipi_core_clk),
+ (int)clk_get_rate(hdmi_data->isfr_clk),
+ (int)clk_get_rate(hdmi_data->iahb_clk));
+
+ ret = fsl_hdmi_update_constraints(substream);
+ if (ret < 0)
+ return ret;
+
+ /* Indicates the subpacket represents a flatline sample */
+ hdmi_audio_writeb(FC_AUDSCONF, AUD_PACKET_SAMPFIT, 0x0);
+
+ return 0;
+}
+
+static void fsl_hdmi_soc_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct imx_hdmi *hdmi_data = snd_soc_dai_get_drvdata(dai);
+
+ clk_disable_unprepare(hdmi_data->iahb_clk);
+ clk_disable_unprepare(hdmi_data->isfr_clk);
+ clk_disable_unprepare(hdmi_data->mipi_core_clk);
+}
+
+static int fsl_hdmi_soc_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ hdmi_set_audio_infoframe(runtime->channels);
+ hdmi_audio_writeb(FC_AUDSCONF, AUD_PACKET_LAYOUT,
+ (runtime->channels > 2) ? 0x1 : 0x0);
+ hdmi_set_sample_rate(runtime->rate);
+ dumpregs(dai);
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops fsl_hdmi_soc_dai_ops = {
+ .startup = fsl_hdmi_soc_startup,
+ .shutdown = fsl_hdmi_soc_shutdown,
+ .prepare = fsl_hdmi_soc_prepare,
+};
+
+/* IEC60958 status functions */
+static int fsl_hdmi_iec_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+
+static int fsl_hdmi_iec_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uvalue)
+{
+ int i;
+
+ for (i = 0 ; i < 4 ; i++)
+ uvalue->value.iec958.status[i] = iec_header.status[i];
+
+ return 0;
+}
+
+static int fsl_hdmi_iec_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uvalue)
+{
+ int i;
+
+ /* Do not allow professional mode */
+ if (uvalue->value.iec958.status[0] & IEC958_AES0_PROFESSIONAL)
+ return -EPERM;
+
+ for (i = 0 ; i < 4 ; i++) {
+ iec_header.status[i] = uvalue->value.iec958.status[i];
+ pr_debug("%s status[%d]=0x%02x\n", __func__, i, iec_header.status[i]);
+ }
+
+ return 0;
+}
+
+static int fsl_hdmi_channels_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ hdmi_get_edid_cfg(&edid_cfg);
+ fsl_hdmi_get_playback_channels();
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = playback_constraint_channels.count;
+
+ return 0;
+}
+
+
+static int fsl_hdmi_channels_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uvalue)
+{
+ int i;
+ hdmi_get_edid_cfg(&edid_cfg);
+ fsl_hdmi_get_playback_channels();
+
+ for (i = 0 ; i < playback_constraint_channels.count ; i++)
+ uvalue->value.integer.value[i] = playback_channels[i];
+
+ return 0;
+}
+
+static int fsl_hdmi_rates_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ hdmi_get_edid_cfg(&edid_cfg);
+ fsl_hdmi_get_playback_rates();
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = playback_constraint_rates.count;
+
+ return 0;
+}
+
+static int fsl_hdmi_rates_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uvalue)
+{
+ int i;
+ hdmi_get_edid_cfg(&edid_cfg);
+ fsl_hdmi_get_playback_rates();
+
+ for (i = 0 ; i < playback_constraint_rates.count ; i++)
+ uvalue->value.integer.value[i] = playback_rates[i];
+
+ return 0;
+}
+
+static int fsl_hdmi_formats_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ hdmi_get_edid_cfg(&edid_cfg);
+ fsl_hdmi_get_playback_sample_size();
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = playback_constraint_bits.count;
+
+ return 0;
+}
+
+static int fsl_hdmi_formats_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uvalue)
+{
+ int i;
+ hdmi_get_edid_cfg(&edid_cfg);
+ fsl_hdmi_get_playback_sample_size();
+
+ for (i = 0 ; i < playback_constraint_bits.count ; i++)
+ uvalue->value.integer.value[i] = playback_sample_size[i];
+
+ return 0;
+}
+
+static struct snd_kcontrol_new fsl_hdmi_ctrls[] = {
+ /* Status cchanel controller */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_WRITE |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = fsl_hdmi_iec_info,
+ .get = fsl_hdmi_iec_get,
+ .put = fsl_hdmi_iec_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HDMI Support Channels",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = fsl_hdmi_channels_info,
+ .get = fsl_hdmi_channels_get,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HDMI Support Rates",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = fsl_hdmi_rates_info,
+ .get = fsl_hdmi_rates_get,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HDMI Support Formats",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = fsl_hdmi_formats_info,
+ .get = fsl_hdmi_formats_get,
+ },
+};
+
+static int fsl_hdmi_soc_dai_probe(struct snd_soc_dai *dai)
+{
+ int ret;
+
+ init_channel_allocations();
+
+ ret = snd_soc_add_dai_controls(dai, fsl_hdmi_ctrls,
+ ARRAY_SIZE(fsl_hdmi_ctrls));
+ if (ret)
+ dev_warn(dai->dev, "failed to add dai controls\n");
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver fsl_hdmi_dai = {
+ .probe = &fsl_hdmi_soc_dai_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = MXC_HDMI_RATES_PLAYBACK,
+ .formats = MXC_HDMI_FORMATS_PLAYBACK,
+ },
+ .ops = &fsl_hdmi_soc_dai_ops,
+};
+
+static const struct snd_soc_component_driver fsl_hdmi_component = {
+ .name = "fsl-hdmi",
+};
+
+/* HDMI audio codec callbacks */
+static int fsl_hdmi_audio_hw_params(struct device *dev, void *data,
+ struct hdmi_codec_daifmt *fmt,
+ struct hdmi_codec_params *hparms)
+{
+ dev_dbg(dev, "[%s]: %u Hz, %d bit, %d channels\n", __func__,
+ hparms->sample_rate, hparms->sample_width, hparms->cea.channels);
+
+ return 0;
+}
+
+static void fsl_hdmi_audio_shutdown(struct device *dev, void *data)
+{
+ dev_dbg(dev, "[%s]\n", __func__);
+}
+
+static const struct hdmi_codec_ops fsl_hdmi_audio_codec_ops = {
+ .hw_params = fsl_hdmi_audio_hw_params,
+ .audio_shutdown = fsl_hdmi_audio_shutdown,
+};
+
+static struct hdmi_codec_pdata codec_data = {
+ .ops = &fsl_hdmi_audio_codec_ops,
+ .i2s = 1,
+ .max_i2s_channels = 8,
+};
+
+static int fsl_hdmi_dai_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct imx_hdmi *hdmi_data;
+ int ret = 0;
+
+ if (!np)
+ return -ENODEV;
+
+ if (!hdmi_get_registered()) {
+ dev_err(&pdev->dev, "failed to probe. Load HDMI-video first.\n");
+ return -ENOMEM;
+ }
+
+ hdmi_data = devm_kzalloc(&pdev->dev, sizeof(*hdmi_data), GFP_KERNEL);
+ if (!hdmi_data) {
+ dev_err(&pdev->dev, "failed to alloc hdmi_data\n");
+ return -ENOMEM;
+ }
+
+ hdmi_data->pdev = pdev;
+
+ memcpy(&hdmi_data->cpu_dai_drv, &fsl_hdmi_dai, sizeof(fsl_hdmi_dai));
+ hdmi_data->cpu_dai_drv.name = np->name;
+
+ hdmi_data->mipi_core_clk = devm_clk_get(&pdev->dev, "mipi_core");
+ if (IS_ERR(hdmi_data->mipi_core_clk)) {
+ ret = PTR_ERR(hdmi_data->mipi_core_clk);
+ dev_err(&pdev->dev, "failed to get mipi core clk: %d\n", ret);
+ return -EINVAL;
+ }
+
+ hdmi_data->isfr_clk = devm_clk_get(&pdev->dev, "hdmi_isfr");
+ if (IS_ERR(hdmi_data->isfr_clk)) {
+ ret = PTR_ERR(hdmi_data->isfr_clk);
+ dev_err(&pdev->dev, "failed to get HDMI isfr clk: %d\n", ret);
+ return -EINVAL;
+ }
+
+ hdmi_data->iahb_clk = devm_clk_get(&pdev->dev, "hdmi_iahb");
+ if (IS_ERR(hdmi_data->iahb_clk)) {
+ ret = PTR_ERR(hdmi_data->iahb_clk);
+ dev_err(&pdev->dev, "failed to get HDMI ahb clk: %d\n", ret);
+ return -EINVAL;
+ }
+
+ dev_set_drvdata(&pdev->dev, hdmi_data);
+ ret = snd_soc_register_component(&pdev->dev, &fsl_hdmi_component,
+ &hdmi_data->cpu_dai_drv, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "register DAI failed\n");
+ return ret;
+ }
+
+ hdmi_data->codec_dev = platform_device_register_data(&pdev->dev,
+ HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_NONE,
+ &codec_data, sizeof(codec_data));
+ if (IS_ERR(hdmi_data->codec_dev)) {
+ dev_err(&pdev->dev, "failed to register HDMI audio codec\n");
+ ret = PTR_ERR(hdmi_data->codec_dev);
+ goto fail;
+ }
+
+ hdmi_data->dma_dev = platform_device_alloc("imx-hdmi-audio", -1);
+ if (IS_ERR(hdmi_data->dma_dev)) {
+ ret = PTR_ERR(hdmi_data->dma_dev);
+ goto fail_dma;
+ }
+
+ platform_set_drvdata(hdmi_data->dma_dev, hdmi_data);
+
+ ret = platform_device_add(hdmi_data->dma_dev);
+ if (ret) {
+ platform_device_put(hdmi_data->dma_dev);
+ goto fail_dma;
+ }
+
+ return 0;
+
+fail_dma:
+ platform_device_unregister(hdmi_data->codec_dev);
+fail:
+ snd_soc_unregister_component(&pdev->dev);
+
+ return ret;
+}
+
+static int fsl_hdmi_dai_remove(struct platform_device *pdev)
+{
+ struct imx_hdmi *hdmi_data = platform_get_drvdata(pdev);
+
+ platform_device_unregister(hdmi_data->dma_dev);
+ platform_device_unregister(hdmi_data->codec_dev);
+ snd_soc_unregister_component(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id fsl_hdmi_dai_dt_ids[] = {
+ { .compatible = "fsl,imx6dl-hdmi-audio", },
+ { .compatible = "fsl,imx6q-hdmi-audio", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_hdmi_dai_dt_ids);
+
+static struct platform_driver fsl_hdmi_driver = {
+ .probe = fsl_hdmi_dai_probe,
+ .remove = fsl_hdmi_dai_remove,
+ .driver = {
+ .name = "fsl-hdmi-dai",
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_hdmi_dai_dt_ids,
+ },
+};
+module_platform_driver(fsl_hdmi_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IMX HDMI TX DAI");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:fsl-hdmi-dai");
diff --git a/sound/soc/fsl/fsl_rpmsg_i2s.c b/sound/soc/fsl/fsl_rpmsg_i2s.c
new file mode 100644
index 000000000000..3cfa3e9e50e2
--- /dev/null
+++ b/sound/soc/fsl/fsl_rpmsg_i2s.c
@@ -0,0 +1,259 @@
+/*
+ * Freescale ALSA SoC rpmsg i2s driver.
+ *
+ * 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 as published by the
+ * Free Software Foundation, either version 2 of the License, or(at your
+ * option) any later version.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/pm_runtime.h>
+#include <linux/rpmsg.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_rpmsg_i2s.h"
+#include "imx-pcm.h"
+
+#define FSL_RPMSG_I2S_RATES (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\
+ SNDRV_PCM_RATE_48000)
+#define FSL_RPMSG_I2S_FORMATS SNDRV_PCM_FMTBIT_S16_LE
+
+static int i2s_send_message(struct i2s_rpmsg_s *msg,
+ struct i2s_info *info)
+{
+ int err;
+
+ mutex_lock(&info->tx_lock);
+ if (!info->rpdev) {
+ dev_dbg(info->dev, "rpmsg channel not ready, m4 image ready?\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(&info->rpdev->dev, "send cmd %d\n", msg->header.cmd);
+
+ reinit_completion(&info->cmd_complete);
+ err = rpmsg_send(info->rpdev->ept, (void *)msg,
+ sizeof(struct i2s_rpmsg_s));
+ if (err) {
+ dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err);
+ return err;
+ }
+
+ /* wait response from rpmsg */
+ err = wait_for_completion_timeout(&info->cmd_complete,
+ msecs_to_jiffies(RPMSG_TIMEOUT));
+ if (!err) {
+ dev_err(&info->rpdev->dev, "rpmsg_send cmd %d timeout!\n",
+ msg->header.cmd);
+ return -ETIMEDOUT;
+ }
+
+ dev_dbg(&info->rpdev->dev, "cmd:%d, resp %d\n", msg->header.cmd,
+ info->recv_msg.param.resp);
+ mutex_unlock(&info->tx_lock);
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver fsl_rpmsg_i2s_dai = {
+ .playback = {
+ .stream_name = "CPU-Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = FSL_RPMSG_I2S_RATES,
+ .formats = FSL_RPMSG_I2S_FORMATS,
+ },
+ .capture = {
+ .stream_name = "CPU-Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = FSL_RPMSG_I2S_RATES,
+ .formats = FSL_RPMSG_I2S_FORMATS,
+ },
+ .symmetric_rates = 1,
+ .symmetric_channels = 1,
+ .symmetric_samplebits = 1,
+};
+
+static const struct snd_soc_component_driver fsl_component = {
+ .name = "fsl-rpmsg-i2s",
+};
+
+static const struct of_device_id fsl_rpmsg_i2s_ids[] = {
+ { .compatible = "fsl,imx7ulp-rpmsg-i2s"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_rpmsg_i2s_ids);
+
+static void rpmsg_i2s_work(struct work_struct *work)
+{
+ struct work_of_rpmsg *work_of_rpmsg;
+ struct i2s_info *i2s_info;
+
+ work_of_rpmsg = container_of(work, struct work_of_rpmsg, work);
+ i2s_info = work_of_rpmsg->i2s_info;
+
+ i2s_send_message(&work_of_rpmsg->msg, i2s_info);
+}
+
+static int fsl_rpmsg_i2s_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct fsl_rpmsg_i2s *rpmsg_i2s;
+ struct i2s_info *i2s_info;
+ int audioindex = 0;
+ int ret;
+ int i;
+
+ rpmsg_i2s = devm_kzalloc(&pdev->dev, sizeof(struct fsl_rpmsg_i2s),
+ GFP_KERNEL);
+ if (!rpmsg_i2s)
+ return -ENOMEM;
+
+ rpmsg_i2s->pdev = pdev;
+ i2s_info = &rpmsg_i2s->i2s_info;
+
+ ret = of_property_read_u32(np, "fsl,audioindex", &audioindex);
+ if (ret)
+ audioindex = 0;
+
+ /* Setup work queue */
+ i2s_info->rpmsg_wq = create_singlethread_workqueue("rpmsg_i2s");
+ if (i2s_info->rpmsg_wq == NULL) {
+ dev_err(&pdev->dev, "workqueue create failed\n");
+ return -ENOMEM;
+ }
+
+ i2s_info->send_message = i2s_send_message;
+
+ for (i = 0; i < WORK_MAX_NUM; i++) {
+ INIT_WORK(&i2s_info->work_list[i].work, rpmsg_i2s_work);
+ i2s_info->work_list[i].i2s_info = i2s_info;
+ }
+
+ for (i = 0; i < 2; i++) {
+ i2s_info->send_msg[i].header.cate = IMX_RPMSG_AUDIO;
+ i2s_info->send_msg[i].header.major = IMX_RMPSG_MAJOR;
+ i2s_info->send_msg[i].header.minor = IMX_RMPSG_MINOR;
+ i2s_info->send_msg[i].header.type = I2S_TYPE_A;
+ i2s_info->send_msg[i].param.audioindex = audioindex;
+ }
+
+ mutex_init(&i2s_info->tx_lock);
+
+ platform_set_drvdata(pdev, rpmsg_i2s);
+ pm_runtime_enable(&pdev->dev);
+
+ ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
+ &fsl_rpmsg_i2s_dai, 1);
+ if (ret)
+ return ret;
+
+ return imx_rpmsg_platform_register(&pdev->dev);
+}
+
+static int fsl_rpmsg_i2s_remove(struct platform_device *pdev)
+{
+ struct fsl_rpmsg_i2s *rpmsg_i2s = platform_get_drvdata(pdev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+
+ if (i2s_info->rpmsg_wq)
+ destroy_workqueue(i2s_info->rpmsg_wq);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int fsl_rpmsg_i2s_runtime_resume(struct device *dev)
+{
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(dev);
+
+ pm_qos_add_request(&rpmsg_i2s->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0);
+ return 0;
+}
+
+static int fsl_rpmsg_i2s_runtime_suspend(struct device *dev)
+{
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(dev);
+
+ pm_qos_remove_request(&rpmsg_i2s->pm_qos_req);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int fsl_rpmsg_i2s_suspend(struct device *dev)
+{
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg_tx;
+ struct i2s_rpmsg_s *rpmsg_rx;
+
+ flush_workqueue(i2s_info->rpmsg_wq);
+ rpmsg_tx = &i2s_info->send_msg[SNDRV_PCM_STREAM_PLAYBACK];
+ rpmsg_rx = &i2s_info->send_msg[SNDRV_PCM_STREAM_CAPTURE];
+
+ rpmsg_tx->header.cmd = I2S_TX_SUSPEND;
+ i2s_send_message(rpmsg_tx, i2s_info);
+
+ rpmsg_rx->header.cmd = I2S_RX_SUSPEND;
+ i2s_send_message(rpmsg_rx, i2s_info);
+
+ return 0;
+}
+
+static int fsl_rpmsg_i2s_resume(struct device *dev)
+{
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg_tx;
+ struct i2s_rpmsg_s *rpmsg_rx;
+
+ rpmsg_tx = &i2s_info->send_msg[SNDRV_PCM_STREAM_PLAYBACK];
+ rpmsg_rx = &i2s_info->send_msg[SNDRV_PCM_STREAM_CAPTURE];
+
+ rpmsg_tx->header.cmd = I2S_TX_RESUME;
+ i2s_send_message(rpmsg_tx, i2s_info);
+
+ rpmsg_rx->header.cmd = I2S_RX_RESUME;
+ i2s_send_message(rpmsg_rx, i2s_info);
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops fsl_rpmsg_i2s_pm_ops = {
+ SET_RUNTIME_PM_OPS(fsl_rpmsg_i2s_runtime_suspend,
+ fsl_rpmsg_i2s_runtime_resume,
+ NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(fsl_rpmsg_i2s_suspend, fsl_rpmsg_i2s_resume)
+};
+
+static struct platform_driver fsl_rpmsg_i2s_driver = {
+ .probe = fsl_rpmsg_i2s_probe,
+ .remove = fsl_rpmsg_i2s_remove,
+ .driver = {
+ .name = "fsl-rpmsg-i2s",
+ .pm = &fsl_rpmsg_i2s_pm_ops,
+ .of_match_table = fsl_rpmsg_i2s_ids,
+ },
+};
+
+module_platform_driver(fsl_rpmsg_i2s_driver);
+
+MODULE_DESCRIPTION("Freescale Soc rpmsg_i2s Interface");
+MODULE_AUTHOR("Shengjiu Wang <shengjiu.wang@freescale.com>");
+MODULE_ALIAS("platform:fsl-rpmsg_i2s");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_rpmsg_i2s.h b/sound/soc/fsl/fsl_rpmsg_i2s.h
new file mode 100644
index 000000000000..be951e91df29
--- /dev/null
+++ b/sound/soc/fsl/fsl_rpmsg_i2s.h
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ *
+ ******************************************************************************
+ * communication stack of audio with rpmsg
+ ******************************************************************************
+ * Packet structure:
+ * A SRTM message consists of a 10 bytes header followed by 0~N bytes of data
+ *
+ * +---------------+-------------------------------+
+ * | | Content |
+ * +---------------+-------------------------------+
+ * | Byte Offset | 7 6 5 4 3 2 1 0 |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 0 | Category |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 1 ~ 2 | Version |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 3 | Type |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 4 | Command |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 5 | Reserved0 |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 6 | Reserved1 |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 7 | Reserved2 |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 8 | Reserved3 |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 9 | Reserved4 |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | 10 | DATA 0 |
+ * +---------------+---+---+---+---+---+---+---+---+
+ * : : : : : : : : : : : : :
+ * +---------------+---+---+---+---+---+---+---+---+
+ * | N + 10 - 1 | DATA N-1 |
+ * +---------------+---+---+---+---+---+---+---+---+
+ *
+ * +----------+------------+------------------------------------------------+
+ * | Field | Byte | |
+ * +----------+------------+------------------------------------------------+
+ * | Category | 0 | The destination category. |
+ * +----------+------------+------------------------------------------------+
+ * | Version | 1 ~ 2 | The category version of the sender of the |
+ * | | | packet. |
+ * | | | The first byte represent the major version of |
+ * | | | the packet.The second byte represent the minor |
+ * | | | version of the packet. |
+ * +----------+------------+------------------------------------------------+
+ * | Type | 3 | The message type of current message packet. |
+ * +----------+------------+------------------------------------------------+
+ * | Command | 4 | The command byte sent to remote processor/SoC. |
+ * +----------+------------+------------------------------------------------+
+ * | Reserved | 5 ~ 9 | Reserved field for future extension. |
+ * +----------+------------+------------------------------------------------+
+ * | Data | N | The data payload of the message packet. |
+ * +----------+------------+------------------------------------------------+
+ *
+ * Audio control:
+ * SRTM Audio Control Category Request Command Table:
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | Category | Version | Type | Command | Data | Function |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x00 | Data[0]: Audio Device Index | Open an Audio TX Instance. |
+ * | | | | | Data[1]: format | |
+ * | | | | | Data[2]: channels | |
+ * | | | | | Data[3-6]: samplerate | |
+ * | | | | | Data[7-10]: buffer_addr | |
+ * | | | | | Data[11-14]: buffer_size | |
+ * | | | | | Data[15-18]: period_size | |
+ * | | | | | Data[19-22]: buffer_tail | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x01 | Data[0]: Audio Device Index | Start an Audio TX Instance. |
+ * | | | | | Same as above command | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x02 | Data[0]: Audio Device Index | Pause an Audio TX Instance. |
+ * | | | | | Same as above command | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x03 | Data[0]: Audio Device Index | Resume an Audio TX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x04 | Data[0]: Audio Device Index | Terminate an Audio TX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x05 | Data[0]: Audio Device Index | Close an Audio TX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x06 | Data[0]: Audio Device Index | Set Parameters for an Audio TX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x07 | Data[0]: Audio Device Index | Set Audio TX Buffer. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x08 | Data[0]: Audio Device Index | Open an Audio RX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x09 | Data[0]: Audio Device Index | Start an Audio RX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x0A | Data[0]: Audio Device Index | Pause an Audio RX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x0B | Data[0]: Audio Device Index | Resume an Audio RX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x0C | Data[0]: Audio Device Index | Terminate an Audio RX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x0D | Data[0]: Audio Device Index | Close an Audio RX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x0E | Data[0]: Audio Device Index | Set Parameters for an Audio RX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x00 | 0x0F | Data[0]: Audio Device Index | Set Audio RX Buffer. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * Note 1: See <List of Sample Format> for available value of
+ * Sample Format;
+ * Note 2: See <List of Audio Channels> for available value of Channels;
+ * Note 3: Sample Rate of Set Parameters for an Audio TX Instance
+ * Command and Set Parameters for an Audio RX Instance Command is
+ * in little-endian format.
+ *
+ * SRTM Audio Control Category Response Command Table:
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | Category | Version | Type | Command | Data | Function |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x00 | Data[0]: Audio Device Index | Reply for Open an Audio TX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x01 | Data[0]: Audio Device Index | Reply for Start an Audio TX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x02 | Data[0]: Audio Device Index | Reply for Pause an Audio TX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x03 | Data[0]: Audio Device Index | Reply for Resume an Audio TX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x04 | Data[0]: Audio Device Index | Reply for Terminate an Audio TX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x05 | Data[0]: Audio Device Index | Reply for Close an Audio TX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x06 | Data[0]: Audio Device Index | Reply for Set Parameters for an Audio |
+ * | | | | | Data[1]: Return code | TX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x07 | Data[0]: Audio Device Index | Reply for Set Audio TX Buffer. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x08 | Data[0]: Audio Device Index | Reply for Open an Audio RX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x09 | Data[0]: Audio Device Index | Reply for Start an Audio RX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x0A | Data[0]: Audio Device Index | Reply for Pause an Audio RX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x0B | Data[0]: Audio Device Index | Reply for Resume an Audio RX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x0C | Data[0]: Audio Device Index | Reply for Terminate an Audio RX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x0D | Data[0]: Audio Device Index | Reply for Close an Audio RX Instance. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x0E | Data[0]: Audio Device Index | Reply for Set Parameters for an Audio |
+ * | | | | | Data[1]: Return code | RX Instance. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x01 | 0x0F | Data[0]: Audio Device Index | Reply for Set Audio RX Buffer. |
+ * | | | | | Data[1]: Return code | |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ *
+ * SRTM Audio Control Category Notification Command Table:
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | Category | Version | Type | Command | Data | Function |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x02 | 0x00 | Data[0]: Audio Device Index | Notify one TX period is finished. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ * | 0x03 | 0x0100 | 0x02 | 0x01 | Data[0]: Audio Device Index | Notify one RX period is finished. |
+ * +------------+---------+------+---------+-------------------------------+------------------------------------------------+
+ *
+ * List of Sample Format:
+ * +--------------------+----------------------------------------------+
+ * | Sample Format | Description |
+ * +--------------------+----------------------------------------------+
+ * | 0x0 | S16_LE |
+ * +--------------------+----------------------------------------------+
+ * | 0x1 | S24_LE |
+ * +--------------------+----------------------------------------------+
+ *
+ * List of Audio Channels
+ * +--------------------+----------------------------------------------+
+ * | Audio Channel | Description |
+ * +--------------------+----------------------------------------------+
+ * | 0x0 | Left Channel |
+ * +--------------------+----------------------------------------------+
+ * | 0x1 | Right Channel |
+ * +--------------------+----------------------------------------------+
+ * | 0x2 | Left & Right Channel |
+ * +--------------------+----------------------------------------------+
+ *
+ */
+
+#ifndef __FSL_RPMSG_I2S_H
+#define __FSL_RPMSG_I2S_H
+
+#include <linux/pm_qos.h>
+#include <linux/imx_rpmsg.h>
+#include <linux/interrupt.h>
+#include <sound/dmaengine_pcm.h>
+
+#define RPMSG_TIMEOUT 1000
+
+#define I2S_TX_OPEN 0x0
+#define I2S_TX_START 0x1
+#define I2S_TX_PAUSE 0x2
+#define I2S_TX_RESTART 0x3
+#define I2S_TX_TERMINATE 0x4
+#define I2S_TX_CLOSE 0x5
+#define I2S_TX_HW_PARAM 0x6
+#define I2S_TX_BUFFER 0x7
+#define I2S_TX_SUSPEND 0x8
+#define I2S_TX_RESUME 0x9
+
+#define I2S_RX_OPEN 0xA
+#define I2S_RX_START 0xB
+#define I2S_RX_PAUSE 0xC
+#define I2S_RX_RESTART 0xD
+#define I2S_RX_TERMINATE 0xE
+#define I2S_RX_CLOSE 0xF
+#define I2S_RX_HW_PARAM 0x10
+#define I2S_RX_BUFFER 0x11
+#define I2S_RX_SUSPEND 0x12
+#define I2S_RX_RESUME 0x13
+#define WORK_MAX_NUM 0x14
+
+#define I2S_TX_PERIOD_DONE 0x0
+#define I2S_RX_PERIOD_DONE 0x1
+
+#define I2S_TYPE_A 0x0
+#define I2S_TYPE_B 0x1
+#define I2S_TYPE_C 0x2
+
+#define I2S_RESP_NONE 0x0
+#define I2S_RESP_NOT_ALLOWED 0x1
+#define I2S_RESP_SUCCESS 0x2
+#define I2S_RESP_FAILED 0x3
+
+#define RPMSG_S16_LE 0x0
+#define RPMSG_S24_LE 0x1
+
+#define RPMSG_CH_LEFT 0x0
+#define RPMSG_CH_RIGHT 0x1
+#define RPMSG_CH_STEREO 0x2
+
+struct i2s_param_s {
+ unsigned char audioindex;
+ unsigned char format;
+ unsigned char channels;
+ unsigned int rate;
+ unsigned int buffer_addr;
+ unsigned int buffer_size;
+ unsigned int period_size;
+ unsigned int buffer_tail;
+} __packed;
+
+struct i2s_param_r {
+ unsigned char audioindex;
+ unsigned char resp;
+} __packed;
+
+/* struct of send message */
+struct i2s_rpmsg_s {
+ struct imx_rpmsg_head header;
+ struct i2s_param_s param;
+};
+
+/* struct of received message */
+struct i2s_rpmsg_r {
+ struct imx_rpmsg_head header;
+ struct i2s_param_r param;
+};
+
+struct work_of_rpmsg {
+ struct i2s_info *i2s_info;
+ /* sent msg for each work */
+ struct i2s_rpmsg_s msg;
+ struct work_struct work;
+};
+
+typedef void (*dma_callback)(void *arg);
+struct i2s_info {
+ struct rpmsg_device *rpdev;
+ struct device *dev;
+ struct completion cmd_complete;
+ /* received msg */
+ struct i2s_rpmsg_r recv_msg;
+ /* backup sent msg */
+ struct i2s_rpmsg_s send_msg[2];
+
+ struct workqueue_struct *rpmsg_wq;
+ struct work_of_rpmsg work_list[WORK_MAX_NUM];
+ int work_index;
+ int num_period[2];
+ void *callback_param[2];
+ int (*send_message)(struct i2s_rpmsg_s *msg, struct i2s_info *info);
+ dma_callback callback[2];
+ spinlock_t lock[2];
+ struct mutex tx_lock;
+};
+
+struct fsl_rpmsg_i2s {
+ struct platform_device *pdev;
+ struct i2s_info i2s_info;
+ struct pm_qos_request pm_qos_req;
+};
+
+#endif /* __FSL_RPMSG_I2S_H */
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 9fadf7e31c5f..6c308a490132 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -1,7 +1,7 @@
/*
* Freescale ALSA SoC Digital Audio Interface (SAI) driver.
*
- * Copyright 2012-2015 Freescale Semiconductor, Inc.
+ * Copyright 2012-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 as published by the
@@ -10,14 +10,18 @@
*
*/
+#include <linux/busfreq-imx.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/of_address.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/pm_qos.h>
#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
@@ -30,6 +34,39 @@
#define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
FSL_SAI_CSR_FEIE)
+static struct fsl_sai_soc_data fsl_sai_vf610 = {
+ .imx = false,
+ /*dataline is mask, not index*/
+ .dataline = 0x1,
+ .fifos = 1,
+ .fifo_depth = 32,
+ .flags = 0,
+};
+
+static struct fsl_sai_soc_data fsl_sai_imx6sx = {
+ .imx = true,
+ .dataline = 0x1,
+ .fifos = 1,
+ .fifo_depth = 32,
+ .flags = 0,
+};
+
+static struct fsl_sai_soc_data fsl_sai_imx6ul = {
+ .imx = true,
+ .dataline = 0x1,
+ .fifos = 1,
+ .fifo_depth = 32,
+ .flags = 0,
+};
+
+static struct fsl_sai_soc_data fsl_sai_imx7ulp = {
+ .imx = true,
+ .dataline = 0x3,
+ .fifos = 2,
+ .fifo_depth = 16,
+ .flags = SAI_FLAG_PMQOS,
+};
+
static const unsigned int fsl_sai_rates[] = {
8000, 11025, 12000, 16000, 22050,
24000, 32000, 44100, 48000, 64000,
@@ -68,10 +105,10 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
dev_dbg(dev, "isr: Start of Tx word detected\n");
if (flags & FSL_SAI_CSR_SEF)
- dev_warn(dev, "isr: Tx Frame sync error detected\n");
+ dev_dbg(dev, "isr: Tx Frame sync error detected\n");
if (flags & FSL_SAI_CSR_FEF) {
- dev_warn(dev, "isr: Transmit underrun detected\n");
+ dev_dbg(dev, "isr: Transmit underrun detected\n");
/* FIFO reset for safety */
xcsr |= FSL_SAI_CSR_FR;
}
@@ -102,10 +139,10 @@ irq_rx:
dev_dbg(dev, "isr: Start of Rx word detected\n");
if (flags & FSL_SAI_CSR_SEF)
- dev_warn(dev, "isr: Rx Frame sync error detected\n");
+ dev_dbg(dev, "isr: Rx Frame sync error detected\n");
if (flags & FSL_SAI_CSR_FEF) {
- dev_warn(dev, "isr: Receive overflow detected\n");
+ dev_dbg(dev, "isr: Receive overflow detected\n");
/* FIFO reset for safety */
xcsr |= FSL_SAI_CSR_FR;
}
@@ -269,6 +306,8 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
return -EINVAL;
}
+ sai->slave_mode[tx] = false;
+
/* DAI clock master masks */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
@@ -276,14 +315,14 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
break;
case SND_SOC_DAIFMT_CBM_CFM:
- sai->is_slave_mode = true;
+ sai->slave_mode[tx] = true;
break;
case SND_SOC_DAIFMT_CBS_CFM:
val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
break;
case SND_SOC_DAIFMT_CBM_CFS:
val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
- sai->is_slave_mode = true;
+ sai->slave_mode[tx] = true;
break;
default:
return -EINVAL;
@@ -300,14 +339,23 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
+ struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
int ret;
+ if (sai->i2s_xtor)
+ fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
if (ret) {
dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
return ret;
}
+ if (sai->i2s_xtor)
+ fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+
ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
if (ret)
dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret);
@@ -324,7 +372,7 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
int ret = 0;
/* Don't apply to slave mode */
- if (sai->is_slave_mode)
+ if (sai->slave_mode[tx])
return 0;
for (id = 0; id < FSL_SAI_MCLK_MAX; id++) {
@@ -419,7 +467,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
if (sai->slot_width)
slot_width = sai->slot_width;
- if (!sai->is_slave_mode) {
+ if (!sai->slave_mode[tx]) {
ret = fsl_sai_set_bclk(cpu_dai, tx,
slots * slot_width * params_rate(params));
if (ret)
@@ -455,7 +503,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
* error.
*/
- if (!sai->is_slave_mode) {
+ if (!sai->slave_mode[tx]) {
if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
regmap_update_bits(sai->regmap, FSL_SAI_TCR4,
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
@@ -463,8 +511,6 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(sai->regmap, FSL_SAI_TCR5,
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
FSL_SAI_CR5_FBT_MASK, val_cr5);
- regmap_write(sai->regmap, FSL_SAI_TMR,
- ~0UL - ((1 << channels) - 1));
} else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
regmap_update_bits(sai->regmap, FSL_SAI_RCR4,
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
@@ -472,8 +518,29 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(sai->regmap, FSL_SAI_RCR5,
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
FSL_SAI_CR5_FBT_MASK, val_cr5);
- regmap_write(sai->regmap, FSL_SAI_RMR,
- ~0UL - ((1 << channels) - 1));
+ }
+ }
+
+ if (sai->soc->dataline != 0x1) {
+ switch (sai->dataline[tx]) {
+ case 0x0:
+ break;
+ case 0x1:
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+ FSL_SAI_CR4_FCOMB_SOFT | FSL_SAI_CR4_FCOMB_SHIFT, 0);
+ break;
+ case 0x2:
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+ FSL_SAI_CR4_FCOMB_SOFT | FSL_SAI_CR4_FCOMB_SHIFT,
+ FSL_SAI_CR4_FCOMB_SOFT | FSL_SAI_CR4_FCOMB_SHIFT);
+ break;
+ case 0x3:
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+ FSL_SAI_CR4_FCOMB_SOFT | FSL_SAI_CR4_FCOMB_SHIFT,
+ FSL_SAI_CR4_FCOMB_SOFT);
+ break;
+ default:
+ break;
}
}
@@ -494,7 +561,7 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- if (!sai->is_slave_mode &&
+ if (!sai->slave_mode[tx] &&
sai->mclk_streams & BIT(substream->stream)) {
clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
sai->mclk_streams &= ~BIT(substream->stream);
@@ -509,7 +576,9 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ u8 channels = substream->runtime->channels;
u32 xcsr, count = 100;
+ int i;
/*
* Asynchronous mode: Clear SYNC for both Tx and Rx.
@@ -529,13 +598,24 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ for (i = 0; tx && i < channels; i++)
+ regmap_write(sai->regmap, FSL_SAI_TDR0, 0x0);
+ if (tx)
+ udelay(10);
+
regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
-
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ FSL_SAI_CSR_SE, FSL_SAI_CSR_SE);
+ if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR((!tx)),
FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
+ } else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR((!tx)),
+ FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
+ }
regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
@@ -575,7 +655,7 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
* This is a hardware bug, and will be fix in the
* next sai version.
*/
- if (!sai->is_slave_mode) {
+ if (!sai->slave_mode[tx]) {
/* Software Reset for both Tx and Rx */
regmap_write(sai->regmap,
FSL_SAI_TCSR, FSL_SAI_CSR_SR);
@@ -602,14 +682,21 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
struct device *dev = &sai->pdev->dev;
int ret;
+ if (sai->is_stream_opened[tx])
+ return -EBUSY;
+ else
+ sai->is_stream_opened[tx] = true;
+
+ pm_runtime_get_sync(cpu_dai->dev);
+
ret = clk_prepare_enable(sai->bus_clk);
if (ret) {
dev_err(dev, "failed to enable bus clock: %d\n", ret);
return ret;
}
- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE,
- FSL_SAI_CR3_TRCE);
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE0|FSL_SAI_CR3_TRCE1,
+ FSL_SAI_CR3_TRCE(sai->dataline[tx]));
ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints);
@@ -623,9 +710,12 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0);
-
- clk_disable_unprepare(sai->bus_clk);
+ if (sai->is_stream_opened[tx]) {
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE0 | FSL_SAI_CR3_TRCE1, 0);
+ clk_disable_unprepare(sai->bus_clk);
+ sai->is_stream_opened[tx] = false;
+ pm_runtime_put_sync(cpu_dai->dev);
+ }
}
static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
@@ -651,7 +741,7 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
- FSL_SAI_MAXBURST_TX * 2);
+ sai->soc->fifo_depth - FSL_SAI_MAXBURST_TX);
regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
FSL_SAI_MAXBURST_RX - 1);
@@ -668,7 +758,7 @@ static struct snd_soc_dai_driver fsl_sai_dai = {
.playback = {
.stream_name = "CPU-Playback",
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_KNOT,
@@ -677,7 +767,7 @@ static struct snd_soc_dai_driver fsl_sai_dai = {
.capture = {
.stream_name = "CPU-Capture",
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_KNOT,
@@ -696,7 +786,8 @@ static struct reg_default fsl_sai_reg_defaults[] = {
{FSL_SAI_TCR3, 0},
{FSL_SAI_TCR4, 0},
{FSL_SAI_TCR5, 0},
- {FSL_SAI_TDR, 0},
+ {FSL_SAI_TDR0, 0},
+ {FSL_SAI_TDR1, 0},
{FSL_SAI_TMR, 0},
{FSL_SAI_RCR1, 0},
{FSL_SAI_RCR2, 0},
@@ -715,7 +806,8 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
case FSL_SAI_TCR3:
case FSL_SAI_TCR4:
case FSL_SAI_TCR5:
- case FSL_SAI_TFR:
+ case FSL_SAI_TFR0:
+ case FSL_SAI_TFR1:
case FSL_SAI_TMR:
case FSL_SAI_RCSR:
case FSL_SAI_RCR1:
@@ -723,8 +815,10 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
case FSL_SAI_RCR3:
case FSL_SAI_RCR4:
case FSL_SAI_RCR5:
- case FSL_SAI_RDR:
- case FSL_SAI_RFR:
+ case FSL_SAI_RDR0:
+ case FSL_SAI_RDR1:
+ case FSL_SAI_RFR0:
+ case FSL_SAI_RFR1:
case FSL_SAI_RMR:
return true;
default:
@@ -737,9 +831,12 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
switch (reg) {
case FSL_SAI_TCSR:
case FSL_SAI_RCSR:
- case FSL_SAI_TFR:
- case FSL_SAI_RFR:
- case FSL_SAI_RDR:
+ case FSL_SAI_TFR0:
+ case FSL_SAI_TFR1:
+ case FSL_SAI_RFR0:
+ case FSL_SAI_RFR1:
+ case FSL_SAI_RDR0:
+ case FSL_SAI_RDR1:
return true;
default:
return false;
@@ -755,7 +852,8 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
case FSL_SAI_TCR3:
case FSL_SAI_TCR4:
case FSL_SAI_TCR5:
- case FSL_SAI_TDR:
+ case FSL_SAI_TDR0:
+ case FSL_SAI_TDR1:
case FSL_SAI_TMR:
case FSL_SAI_RCSR:
case FSL_SAI_RCR1:
@@ -784,9 +882,19 @@ static const struct regmap_config fsl_sai_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static const struct of_device_id fsl_sai_ids[] = {
+ { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610 },
+ { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx },
+ { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6ul },
+ { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_sai_ids);
+
static int fsl_sai_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id;
struct fsl_sai *sai;
struct regmap *gpr;
struct resource *res;
@@ -794,6 +902,8 @@ static int fsl_sai_probe(struct platform_device *pdev)
char tmp[8];
int irq, ret, i;
int index;
+ u32 buffer_size;
+ unsigned long irqflag = 0;
sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
if (!sai)
@@ -801,11 +911,12 @@ static int fsl_sai_probe(struct platform_device *pdev)
sai->pdev = pdev;
- if (of_device_is_compatible(np, "fsl,imx6sx-sai") ||
- of_device_is_compatible(np, "fsl,imx6ul-sai"))
- sai->sai_on_imx = true;
+ of_id = of_match_device(fsl_sai_ids, &pdev->dev);
+ if (!of_id || !of_id->data)
+ return -EINVAL;
sai->is_lsb_first = of_property_read_bool(np, "lsb-first");
+ sai->soc = of_id->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
@@ -832,24 +943,45 @@ static int fsl_sai_probe(struct platform_device *pdev)
sai->bus_clk = NULL;
}
- sai->mclk_clk[0] = sai->bus_clk;
- for (i = 1; i < FSL_SAI_MCLK_MAX; i++) {
+ for (i = 0; i < FSL_SAI_MCLK_MAX; i++) {
sprintf(tmp, "mclk%d", i);
sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp);
if (IS_ERR(sai->mclk_clk[i])) {
dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n",
- i + 1, PTR_ERR(sai->mclk_clk[i]));
+ i, PTR_ERR(sai->mclk_clk[i]));
sai->mclk_clk[i] = NULL;
}
}
+ /*dataline mask for rx and tx*/
+ ret = of_property_read_u32_index(np, "fsl,dataline", 0, &sai->dataline[0]);
+ if (ret)
+ sai->dataline[0] = 1;
+
+ ret = of_property_read_u32_index(np, "fsl,dataline", 1, &sai->dataline[1]);
+ if (ret)
+ sai->dataline[1] = 1;
+
+ if ((sai->dataline[0] & (~sai->soc->dataline)) || sai->dataline[1] & (~sai->soc->dataline)) {
+ dev_err(&pdev->dev, "dataline setting error, Mask is 0x%x\n", sai->soc->dataline);
+ return -EINVAL;
+ }
+
+ /* I2S XTOR mode */
+ sai->i2s_xtor = (of_find_property(np, "fsl,i2s-xtor", NULL) != NULL);
+
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
return irq;
}
- ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai);
+ /* SAI shared interrupt */
+ if (of_property_read_bool(np, "shared-interrupt"))
+ irqflag = IRQF_SHARED;
+
+ ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, irqflag,
+ np->name, sai);
if (ret) {
dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
return ret;
@@ -898,31 +1030,56 @@ static int fsl_sai_probe(struct platform_device *pdev)
MCLK_DIR(index));
}
- sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
- sai->dma_params_tx.addr = res->start + FSL_SAI_TDR;
+ sai->dma_params_rx.filter_data = "rx";
+ sai->dma_params_tx.filter_data = "tx";
+ sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
+ sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
platform_set_drvdata(pdev, sai);
+ pm_runtime_enable(&pdev->dev);
+
ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
&fsl_sai_dai, 1);
if (ret)
return ret;
- if (sai->sai_on_imx)
- return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
+ if (of_property_read_u32(np, "fsl,dma-buffer-size", &buffer_size))
+ buffer_size = IMX_SAI_DMABUF_SIZE;
+
+ if (sai->soc->imx)
+ return imx_pcm_platform_register(&pdev->dev);
else
return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
}
-static const struct of_device_id fsl_sai_ids[] = {
- { .compatible = "fsl,vf610-sai", },
- { .compatible = "fsl,imx6sx-sai", },
- { .compatible = "fsl,imx6ul-sai", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, fsl_sai_ids);
+#ifdef CONFIG_PM
+static int fsl_sai_runtime_resume(struct device *dev)
+{
+ struct fsl_sai *sai = dev_get_drvdata(dev);
+
+ request_bus_freq(BUS_FREQ_AUDIO);
+
+ if (sai->soc->flags & SAI_FLAG_PMQOS)
+ pm_qos_add_request(&sai->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, 0);
+ return 0;
+}
+
+static int fsl_sai_runtime_suspend(struct device *dev)
+{
+ struct fsl_sai *sai = dev_get_drvdata(dev);
+
+ release_bus_freq(BUS_FREQ_AUDIO);
+
+ if (sai->soc->flags & SAI_FLAG_PMQOS)
+ pm_qos_remove_request(&sai->pm_qos_req);
+
+ return 0;
+}
+#endif
#ifdef CONFIG_PM_SLEEP
static int fsl_sai_suspend(struct device *dev)
@@ -950,6 +1107,9 @@ static int fsl_sai_resume(struct device *dev)
#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops fsl_sai_pm_ops = {
+ SET_RUNTIME_PM_OPS(fsl_sai_runtime_suspend,
+ fsl_sai_runtime_resume,
+ NULL)
SET_SYSTEM_SLEEP_PM_OPS(fsl_sai_suspend, fsl_sai_resume)
};
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index d9ed7be8cb34..e1c0f332e94e 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ * Copyright 2012-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
@@ -9,10 +9,10 @@
#ifndef __FSL_SAI_H
#define __FSL_SAI_H
+#include <linux/pm_qos.h>
#include <sound/dmaengine_pcm.h>
#define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
@@ -23,8 +23,10 @@
#define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */
#define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */
#define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */
-#define FSL_SAI_TDR 0x20 /* SAI Transmit Data */
-#define FSL_SAI_TFR 0x40 /* SAI Transmit FIFO */
+#define FSL_SAI_TDR0 0x20 /* SAI Transmit Data */
+#define FSL_SAI_TDR1 0x24 /* SAI Transmit Data */
+#define FSL_SAI_TFR0 0x40 /* SAI Transmit FIFO */
+#define FSL_SAI_TFR1 0x44 /* SAI Transmit FIFO */
#define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */
#define FSL_SAI_RCSR 0x80 /* SAI Receive Control */
#define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */
@@ -32,8 +34,10 @@
#define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */
#define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */
#define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */
-#define FSL_SAI_RDR 0xa0 /* SAI Receive Data */
-#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */
+#define FSL_SAI_RDR0 0xa0 /* SAI Receive Data */
+#define FSL_SAI_RDR1 0xa4 /* SAI Receive Data */
+#define FSL_SAI_RFR0 0xc0 /* SAI Receive FIFO */
+#define FSL_SAI_RFR1 0xc4 /* SAI Receive FIFO */
#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */
#define FSL_SAI_xCSR(tx) (tx ? FSL_SAI_TCSR : FSL_SAI_RCSR)
@@ -48,6 +52,7 @@
/* SAI Transmit/Receive Control Register */
#define FSL_SAI_CSR_TERE BIT(31)
+#define FSL_SAI_CSR_SE BIT(30)
#define FSL_SAI_CSR_FR BIT(25)
#define FSL_SAI_CSR_SR BIT(24)
#define FSL_SAI_CSR_xF_SHIFT 16
@@ -84,11 +89,19 @@
#define FSL_SAI_CR2_DIV_MASK 0xff
/* SAI Transmit and Receive Configuration 3 Register */
-#define FSL_SAI_CR3_TRCE BIT(16)
+#define FSL_SAI_CR3_TRCE0 BIT(16)
+#define FSL_SAI_CR3_TRCE1 BIT(17)
+#define FSL_SAI_CR3_TRCE(x) (x << 16)
#define FSL_SAI_CR3_WDFL(x) (x)
#define FSL_SAI_CR3_WDFL_MASK 0x1f
/* SAI Transmit and Receive Configuration 4 Register */
+
+#define FSL_SAI_CR4_FCONT BIT(28)
+#define FSL_SAI_CR4_FCOMB_SHIFT BIT(26)
+#define FSL_SAI_CR4_FCOMB_SOFT BIT(27)
+#define FSL_SAI_CR4_FPACK_8 (0x2 << 24)
+#define FSL_SAI_CR4_FPACK_16 (0x3 << 24)
#define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16)
#define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16)
#define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8)
@@ -129,17 +142,29 @@
#define FSL_SAI_MAXBURST_TX 6
#define FSL_SAI_MAXBURST_RX 6
+#define SAI_FLAG_PMQOS BIT(0)
+
+struct fsl_sai_soc_data {
+ unsigned int fifo_depth;
+ unsigned int fifos;
+ unsigned int dataline;
+ unsigned int flags;
+ bool imx;
+};
+
struct fsl_sai {
struct platform_device *pdev;
struct regmap *regmap;
struct clk *bus_clk;
struct clk *mclk_clk[FSL_SAI_MCLK_MAX];
- bool is_slave_mode;
+ bool slave_mode[2];
bool is_lsb_first;
bool is_dsp_mode;
- bool sai_on_imx;
+ bool i2s_xtor;
bool synchronous[2];
+ bool is_stream_opened[2];
+ unsigned int dataline[2];
unsigned int mclk_id[2];
unsigned int mclk_streams;
@@ -148,6 +173,8 @@ struct fsl_sai {
struct snd_dmaengine_dai_dma_data dma_params_rx;
struct snd_dmaengine_dai_dma_data dma_params_tx;
+ const struct fsl_sai_soc_data *soc;
+ struct pm_qos_request pm_qos_req;
};
#define TX 1
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 1ff467c9598a..b210deef3b6d 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -1,7 +1,7 @@
/*
* Freescale S/PDIF ALSA SoC Digital Audio Interface (DAI) driver
*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
*
* Based on stmp3xxx_spdif_dai.c
* Vladimir Barinov <vbarinov@embeddedalley.com>
@@ -20,6 +20,8 @@
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
+#include <linux/pm_runtime.h>
+#include <linux/busfreq-imx.h>
#include <sound/asoundef.h>
#include <sound/dmaengine_pcm.h>
@@ -381,7 +383,6 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
unsigned long csfs = 0;
u32 stc, mask, rate;
u8 clk, txclk_df, sysclk_df;
- int ret;
switch (sample_rate) {
case 32000:
@@ -423,19 +424,6 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
sysclk_df = spdif_priv->sysclk_df[rate];
- /* Don't mess up the clocks from other modules */
- if (clk != STC_TXCLK_SPDIF_ROOT)
- goto clk_set_bypass;
-
- /* The S/PDIF block needs a clock of 64 * fs * txclk_df */
- ret = clk_set_rate(spdif_priv->txclk[rate],
- 64 * sample_rate * txclk_df);
- if (ret) {
- dev_err(&pdev->dev, "failed to set tx clock rate\n");
- return ret;
- }
-
-clk_set_bypass:
dev_dbg(&pdev->dev, "expected clock rate = %d\n",
(64 * sample_rate * txclk_df * sysclk_df));
dev_dbg(&pdev->dev, "actual clock rate = %ld\n",
@@ -468,6 +456,8 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream,
int i;
int ret;
+ pm_runtime_get_sync(cpu_dai->dev);
+
/* Reset module and interrupts only for first initialization */
if (!cpu_dai->active) {
ret = clk_prepare_enable(spdif_priv->coreclk);
@@ -565,6 +555,8 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream,
clk_disable_unprepare(spdif_priv->spbaclk);
clk_disable_unprepare(spdif_priv->coreclk);
}
+
+ pm_runtime_put_sync(cpu_dai->dev);
}
static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
@@ -772,7 +764,7 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol,
}
/* Valid bit information */
-static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol,
+static int fsl_spdif_rx_vbit_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -784,7 +776,7 @@ static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol,
}
/* Get valid good bit from interrupt status register */
-static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol,
+static int fsl_spdif_rx_vbit_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
@@ -799,6 +791,46 @@ static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol,
return 0;
}
+static int fsl_spdif_tx_vbit_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+
+ return 0;
+}
+
+static int fsl_spdif_tx_vbit_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
+ struct regmap *regmap = spdif_priv->regmap;
+ u32 val;
+
+ regmap_read(regmap, REG_SPDIF_SCR, &val);
+ val = (val & SCR_VAL_MASK) >> SCR_VAL_OFFSET;
+ val = 1 - val;
+ ucontrol->value.integer.value[0] = val;
+
+ return 0;
+}
+
+static int fsl_spdif_tx_vbit_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
+ struct regmap *regmap = spdif_priv->regmap;
+ u32 val = (1 - ucontrol->value.integer.value[0]) << SCR_VAL_OFFSET;
+
+ regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_VAL_MASK, val);
+
+ return 0;
+}
+
/* DPLL lock information */
static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -956,11 +988,21 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
/* Valid bit error controller */
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "IEC958 V-Bit Errors",
+ .name = "IEC958 Rx V-Bit Errors",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = fsl_spdif_rx_vbit_info,
+ .get = fsl_spdif_rx_vbit_get,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Tx V-Bit",
.access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_WRITE |
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .info = fsl_spdif_vbit_info,
- .get = fsl_spdif_vbit_get,
+ .info = fsl_spdif_tx_vbit_info,
+ .get = fsl_spdif_tx_vbit_get,
+ .put = fsl_spdif_tx_vbit_put,
},
/* DPLL lock info get controller */
{
@@ -1112,7 +1154,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
{
const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
bool is_sysclk = clk_is_match(clk, spdif_priv->sysclk);
- u64 rate_ideal, rate_actual, sub;
+ u64 rate_actual, sub;
u32 sysclk_dfmin, sysclk_dfmax;
u32 txclk_df, sysclk_df, arate;
@@ -1122,11 +1164,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
for (sysclk_df = sysclk_dfmin; sysclk_df <= sysclk_dfmax; sysclk_df++) {
for (txclk_df = 1; txclk_df <= 128; txclk_df++) {
- rate_ideal = rate[index] * txclk_df * 64;
- if (round)
- rate_actual = clk_round_rate(clk, rate_ideal);
- else
- rate_actual = clk_get_rate(clk);
+ rate_actual = clk_get_rate(clk);
arate = rate_actual / 64;
arate /= txclk_df * sysclk_df;
@@ -1222,6 +1260,7 @@ static int fsl_spdif_probe(struct platform_device *pdev)
struct resource *res;
void __iomem *regs;
int irq, ret, i;
+ u32 buffer_size;
if (!np)
return -ENODEV;
@@ -1313,6 +1352,12 @@ static int fsl_spdif_probe(struct platform_device *pdev)
spdif_priv->dma_params_tx.addr = res->start + REG_SPDIF_STL;
spdif_priv->dma_params_rx.addr = res->start + REG_SPDIF_SRL;
+ /*Clear the val bit for Tx*/
+ regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SCR,
+ SCR_VAL_MASK, 1 << SCR_VAL_OFFSET);
+
+ pm_runtime_enable(&pdev->dev);
+
/* Register with ASoC */
dev_set_drvdata(&pdev->dev, spdif_priv);
@@ -1323,7 +1368,10 @@ static int fsl_spdif_probe(struct platform_device *pdev)
return ret;
}
- ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE);
+ if (of_property_read_u32(np, "fsl,dma-buffer-size", &buffer_size))
+ buffer_size = IMX_SPDIF_DMABUF_SIZE;
+
+ ret = imx_pcm_dma_init(pdev, buffer_size);
if (ret)
dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
@@ -1338,7 +1386,6 @@ static int fsl_spdif_suspend(struct device *dev)
regmap_read(spdif_priv->regmap, REG_SPDIF_SRPC,
&spdif_priv->regcache_srpc);
- regcache_cache_only(spdif_priv->regmap, true);
regcache_mark_dirty(spdif_priv->regmap);
return 0;
@@ -1348,8 +1395,6 @@ static int fsl_spdif_resume(struct device *dev)
{
struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev);
- regcache_cache_only(spdif_priv->regmap, false);
-
regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SRPC,
SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK,
spdif_priv->regcache_srpc);
@@ -1358,8 +1403,24 @@ static int fsl_spdif_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
+#ifdef CONFIG_PM
+static int fsl_spdif_runtime_resume(struct device *dev)
+{
+ request_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+
+static int fsl_spdif_runtime_suspend(struct device *dev)
+{
+ release_bus_freq(BUS_FREQ_HIGH);
+ return 0;
+}
+#endif
+
static const struct dev_pm_ops fsl_spdif_pm = {
SET_SYSTEM_SLEEP_PM_OPS(fsl_spdif_suspend, fsl_spdif_resume)
+ SET_RUNTIME_PM_OPS(fsl_spdif_runtime_suspend, fsl_spdif_runtime_resume,
+ NULL)
};
static const struct of_device_id fsl_spdif_dt_ids[] = {
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 1c03490e1182..3ba8bd195308 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -3,7 +3,8 @@
*
* Author: Timur Tabi <timur@freescale.com>
*
- * Copyright 2007-2010 Freescale Semiconductor, Inc.
+ * Copyright 2007-2015, Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
@@ -43,6 +44,8 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <linux/busfreq-imx.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -676,6 +679,8 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
if (ret)
return ret;
+ pm_runtime_get_sync(dai->dev);
+
/* When using dual fifo mode, it is safer to ensure an even period
* size. If appearing to an odd number while DMA always starts its
* task from fifo0, fifo1 would be neglected at the end of each
@@ -699,6 +704,8 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
struct fsl_ssi_private *ssi_private =
snd_soc_dai_get_drvdata(rtd->cpu_dai);
+ pm_runtime_put_sync(dai->dev);
+
clk_disable_unprepare(ssi_private->clk);
}
@@ -724,12 +731,24 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
u64 sub, savesub = 100000;
unsigned int freq;
bool baudclk_is_used;
+ snd_pcm_format_t sample_format = params_format(hw_params);
/* Prefer the explicitly set bitclock frequency */
if (ssi_private->bitclk_freq)
freq = ssi_private->bitclk_freq;
- else
- freq = params_channels(hw_params) * 32 * params_rate(hw_params);
+ else {
+ if (params_channels(hw_params) == 1) {
+ freq = 2 * params_width(hw_params) *
+ params_rate(hw_params);
+
+ if (sample_format == SNDRV_PCM_FORMAT_S20_3LE)
+ freq = 2 * params_physical_width(hw_params) *
+ params_rate(hw_params);
+ } else {
+ freq = params_channels(hw_params) * 32 *
+ params_rate(hw_params);
+ }
+ }
/* Don't apply it to any non-baudclk circumstance */
if (IS_ERR(ssi_private->baudclk))
@@ -848,16 +867,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
int ret;
u32 scr_val;
int enabled;
-
- regmap_read(regs, CCSR_SSI_SCR, &scr_val);
- enabled = scr_val & CCSR_SSI_SCR_SSIEN;
-
- /*
- * If we're in synchronous mode, and the SSI is already enabled,
- * then STCCR is already set properly.
- */
- if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
- return 0;
+ u8 i2smode = ssi_private->i2s_mode;
if (fsl_ssi_is_i2s_master(ssi_private)) {
ret = fsl_ssi_set_bclk(substream, cpu_dai, hw_params);
@@ -874,8 +884,17 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
}
}
+ regmap_read(regs, CCSR_SSI_SCR, &scr_val);
+ enabled = scr_val & CCSR_SSI_SCR_SSIEN;
+
+ /*
+ * If we're in synchronous mode, and the SSI is already enabled,
+ * then STCCR is already set properly.
+ */
+ if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
+ return 0;
+
if (!fsl_ssi_is_ac97(ssi_private)) {
- u8 i2smode;
/*
* Switch to normal net mode in order to have a frame sync
* signal every 32 bits instead of 16 bits
@@ -883,14 +902,14 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
if (fsl_ssi_is_i2s_cbm_cfs(ssi_private) && sample_size == 16)
i2smode = CCSR_SSI_SCR_I2S_MODE_NORMAL |
CCSR_SSI_SCR_NET;
- else
- i2smode = ssi_private->i2s_mode;
-
- regmap_update_bits(regs, CCSR_SSI_SCR,
- CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
- channels == 1 ? 0 : i2smode);
+ if (channels == 1)
+ i2smode = 0;
}
+ regmap_update_bits(regs, CCSR_SSI_SCR,
+ CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
+ i2smode);
+
/*
* FIXME: The documentation says that SxCCR[WL] should not be
* modified while the SSI is enabled. The only time this can
@@ -947,7 +966,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
fsl_ssi_setup_reg_vals(ssi_private);
regmap_read(regs, CCSR_SSI_SCR, &scr);
- scr &= ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
+ scr &= ~CCSR_SSI_SCR_SYN;
scr |= CCSR_SSI_SCR_SYNC_TX_FS;
mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
@@ -1003,7 +1022,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
default:
return -EINVAL;
}
- scr |= ssi_private->i2s_mode;
/* DAI clock inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -1196,7 +1214,7 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
.startup = fsl_ssi_startup,
- .shutdown = fsl_ssi_shutdown,
+ .shutdown = fsl_ssi_shutdown,
.hw_params = fsl_ssi_hw_params,
.hw_free = fsl_ssi_hw_free,
.set_fmt = fsl_ssi_set_dai_fmt,
@@ -1341,6 +1359,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
struct device_node *np = pdev->dev.of_node;
u32 dmas[4];
int ret;
+ u32 buffer_size;
if (ssi_private->has_ipg_clk_name)
ssi_private->clk = devm_clk_get(&pdev->dev, "ipg");
@@ -1383,6 +1402,9 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
ssi_private->dma_params_rx.maxburst &= ~0x1;
}
+ if (of_property_read_u32(np, "fsl,dma-buffer-size", &buffer_size))
+ buffer_size = IMX_SSI_DMABUF_SIZE;
+
if (!ssi_private->use_dma) {
/*
@@ -1403,7 +1425,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
if (ret)
goto error_pcm;
} else {
- ret = imx_pcm_dma_init(pdev, IMX_SSI_DMABUF_SIZE);
+ ret = imx_pcm_dma_init(pdev, buffer_size);
if (ret)
goto error_pcm;
}
@@ -1569,6 +1591,8 @@ static int fsl_ssi_probe(struct platform_device *pdev)
break;
}
+ pm_runtime_enable(&pdev->dev);
+
dev_set_drvdata(&pdev->dev, ssi_private);
if (ssi_private->soc->imx) {
@@ -1731,8 +1755,24 @@ static int fsl_ssi_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
+#ifdef CONFIG_PM
+static int fsl_ssi_runtime_resume(struct device *dev)
+{
+ request_bus_freq(BUS_FREQ_AUDIO);
+ return 0;
+}
+
+static int fsl_ssi_runtime_suspend(struct device *dev)
+{
+ release_bus_freq(BUS_FREQ_AUDIO);
+ return 0;
+}
+#endif
+
static const struct dev_pm_ops fsl_ssi_pm = {
SET_SYSTEM_SLEEP_PM_OPS(fsl_ssi_suspend, fsl_ssi_resume)
+ SET_RUNTIME_PM_OPS(fsl_ssi_runtime_suspend, fsl_ssi_runtime_resume,
+ NULL)
};
static struct platform_driver fsl_ssi_driver = {
diff --git a/sound/soc/fsl/hdmi_pcm.S b/sound/soc/fsl/hdmi_pcm.S
new file mode 100644
index 000000000000..d8d95fd8f42f
--- /dev/null
+++ b/sound/soc/fsl/hdmi_pcm.S
@@ -0,0 +1,246 @@
+/**
+ * Copyright (C) 2010-2014 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.
+ */
+
+.section .text
+
+.global hdmi_dma_copy_16_neon_lut
+.global hdmi_dma_copy_16_neon_fast
+.global hdmi_dma_copy_24_neon_lut
+.global hdmi_dma_copy_24_neon_fast
+
+
+/**
+ * hdmi_dma_copy_16_neon_lut
+ * Convert pcm sample to iec sample. Pcm sample is 16 bits.
+ * Frame index's between 0 and 47 inclusively. Channel count can be 1, 2, 4, 8.
+ * Frame count should be multipliable by 4, and Sample count by 8.
+ *
+ * C Prototype
+ * void hdmi_dma_copy_16_neon_lut(unsigned short *src, unsigned int *dst,
+ * int samples, unsigned char *lookup_table);
+ * Return value
+ * None
+ * Parameters
+ * src Source PCM16 samples
+ * dst Dest buffer to store pcm with header
+ * samples Contains sample count (=frame_count * channel_count)
+ * lookup_table Preconstructed header table. Channels interleaved.
+ */
+
+hdmi_dma_copy_16_neon_lut:
+ mov r12, #1 /* construct vector(1) */
+ vdup.8 d6, r12
+
+hdmi_dma_copy_16_neon_lut_start:
+
+ /* get 8 samples to q0 */
+ vld1.16 {d0, d1}, [r0]! /* TODO: aligned */
+
+ /* pld [r1, #(64*4)] */
+
+ /* xor every bit */
+ vcnt.8 q1, q0 /* count of 1s */
+ vpadd.i8 d2, d2, d3 /* only care about the LST in every element */
+ vand d2, d2, d6 /* clear other bits while keep the least bit */
+ vshl.u8 d2, d2, #3 /* bit p: d2 = d2 << 3 */
+
+ /* get packet header */
+ vld1.8 {d5}, [r3]!
+ veor d4, d5, d2 /* xor bit c */
+
+ /* store: (d4 << 16 | q0) << 8 */
+ vmovl.u8 q2, d4 /* expand from char to short */
+ vzip.16 q0, q2
+ vshl.u32 q0, q0, #8
+ vshl.u32 q1, q2, #8
+ vst1.32 {d0, d1, d2, d3}, [r1]!
+
+ /* decrease sample count */
+ subs r2, r2, #8
+ bne hdmi_dma_copy_16_neon_lut_start
+
+ mov pc, lr
+
+/**
+ * hdmi_dma_copy_16_neon_fast
+ * Convert pcm sample to iec sample. Pcm sample is 16 bits.
+ * Frame index's between 48 and 191 inclusively.
+ * Channel count can be 1, 2, 4 or 8.
+ * Frame count should be multipliable by 4, and Sample count by 8.
+ *
+ * C Prototype
+ * void hdmi_dma_copy_16_neon_fast(unsigned short *src,
+ * unsigned int *dst, int samples);
+ * Return value
+ * None
+ * Parameters
+ * src Source PCM16 samples
+ * dst Dest buffer to store pcm with header
+ * samples Contains sample count (=frame_count * channel_count)
+ */
+
+hdmi_dma_copy_16_neon_fast:
+ mov r12, #1 /* construct vector(1) */
+ vdup.8 d6, r12
+
+hdmi_dma_copy_16_neon_fast_start:
+ /* get 8 samples to q0 */
+ vld1.16 {d0, d1}, [r0]! /* TODO: aligned */
+
+ /* pld [r1, #(64*4)] */
+
+ /* xor every bit */
+ vcnt.8 q1, q0 /* count of 1s */
+ vpadd.i8 d2, d2, d3
+ vand d2, d2, d6 /* clear other bits while keep the LST */
+ /* finally we construct packet header */
+ vshl.u8 d4, d2, #3 /* bit p: d2 = d2 << 3 */
+
+ /* get packet header: always 0 */
+
+ /* store: (d4 << 16 | q0) << 8 */
+ vmovl.u8 q2, d4 /* expand from char to short */
+ vzip.16 q0, q2
+ vshl.u32 q0, q0, #8
+ vshl.u32 q1, q2, #8
+ vst1.32 {d0, d1, d2, d3}, [r1]!
+
+ /* decrease sample count */
+ subs r2, r2, #8
+ bne hdmi_dma_copy_16_neon_fast_start
+
+ mov pc, lr
+
+
+
+/**
+ * hdmi_dma_copy_24_neon_lut
+ * Convert pcm sample to iec sample. Pcm sample is 24 bits.
+ * Frame index's between 0 and 47 inclusively. Channel count can be 1, 2, 4, 8.
+ * Frame count should be multipliable by 4, and Sample count by 8.
+ *
+ * C Prototype
+ * void hdmi_dma_copy_24_neon_lut(unsigned int *src, unsigned int *dst,
+ * int samples, unsigned char *lookup_table);
+ * Return value
+ * None
+ * Parameters
+ * src Source PCM24 samples
+ * dst Dest buffer to store pcm with header
+ * samples Contains sample count (=frame_count * channel_count)
+ * lookup_table Preconstructed header table. Channels interleaved.
+ */
+
+hdmi_dma_copy_24_neon_lut:
+ vpush {d8}
+
+ mov r12, #1 /* construct vector(1) */
+ vdup.8 d8, r12
+
+hdmi_dma_copy_24_neon_lut_start:
+
+ /* get 8 samples to q0 and q1 */
+ vld1.32 {d0, d1, d2, d3}, [r0]! /* TODO: aligned */
+
+ /* pld [r1, #(64*4)] */
+
+ /* xor every bit */
+ vcnt.8 q2, q0 /* count of 1s */
+ vpadd.i8 d4, d4, d5 /* only care about the LSB in every element */
+ vcnt.8 q3, q1
+ vpadd.i8 d6, d6, d7
+ vpadd.i8 d4, d4, d6 /* d4: contains xor result and other dirty bits */
+ vand d4, d4, d8 /* clear other bits while keep the least bit */
+ vshl.u8 d4, d4, #3 /* bit p: d4 = d4 << 3 */
+
+ /* get packet header */
+ vld1.8 {d5}, [r3]!/* d5: original header */
+ veor d5, d5, d4 /* fix bit p */
+
+ /* store: (d5 << 24 | q0) */
+ vmovl.u8 q3, d5 /* expand from char to short */
+ vmovl.u16 q2, d6 /* expand from short to int */
+ vmovl.u16 q3, d7
+ vshl.u32 q2, q2, #24
+ vshl.u32 q3, q3, #24
+ vorr q0, q0, q2
+ vorr q1, q1, q3
+ vst1.32 {d0, d1, d2, d3}, [r1]!
+
+ /* decrease sample count */
+ subs r2, r2, #8
+ bne hdmi_dma_copy_24_neon_lut_start
+
+ vpop {d8}
+ mov pc, lr
+
+/**
+ * hdmi_dma_copy_24_neon_fast
+ * Convert pcm sample to iec sample. Pcm sample is 24 bits.
+ * Frame index's between 48 and 191 inclusively.
+ * Channel count can be 1, 2, 4 or 8.
+ * Frame count should be multipliable by 4, and Sample count by 8.
+ *
+ * C Prototype
+ * void hdmi_dma_copy_24_neon_fast(unsigned int *src,
+ * unsigned int *dst, int samples);
+ * Return value
+ * None
+ * Parameters
+ * src Source PCM24 samples
+ * dst Dest buffer to store pcm with header
+ * samples Contains sample count (=frame_count * channel_count)
+ */
+
+hdmi_dma_copy_24_neon_fast:
+ vpush {d8}
+
+ mov r12, #1 /* construct vector(1) */
+ vdup.8 d8, r12
+
+hdmi_dma_copy_24_neon_fast_start:
+ /* get 8 samples to q0 and q1 */
+ vld1.32 {d0, d1, d2, d3}, [r0]! /* TODO: aligned */
+
+ /* pld [r1, #(64*4)] */
+
+ /* xor every bit */
+ vcnt.8 q2, q0 /* count of 1s */
+ vpadd.i8 d4, d4, d5 /* only care about the LSB in every element */
+ vcnt.8 q3, q1
+ vpadd.i8 d6, d6, d7
+ vpadd.i8 d4, d4, d6 /* d4: contains xor result and other dirty bits */
+ vand d4, d4, d8 /* clear other bits while keep the least bit */
+ vshl.u8 d4, d4, #3 /* bit p: d4 = d4 << 3 */
+
+ /* store: (d4 << 24 | q0) */
+ vmovl.u8 q3, d4 /* expand from char to short */
+ vmovl.u16 q2, d6 /* expand from short to int */
+ vmovl.u16 q3, d7
+ vshl.u32 q2, q2, #24
+ vshl.u32 q3, q3, #24
+ vorr q0, q0, q2
+ vorr q1, q1, q3
+ vst1.32 {d0, d1, d2, d3}, [r1]!
+
+ /* decrease sample count */
+ subs r2, r2, #8
+ bne hdmi_dma_copy_24_neon_fast_start
+
+ vpop {d8}
+ mov pc, lr
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index fc57da341d61..17766f8b09a8 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2015 Freescale Semiconductor, Inc.
* Copyright 2012 Linaro Ltd.
* Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
*
@@ -33,6 +33,8 @@
static struct clk *audmux_clk;
static void __iomem *audmux_base;
+static u32 *regcache;
+static u32 reg_max;
#define IMX_AUDMUX_V2_PTCR(x) ((x) * 8)
#define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4)
@@ -333,8 +335,23 @@ static int imx_audmux_probe(struct platform_device *pdev)
if (of_id)
pdev->id_entry = of_id->data;
audmux_type = pdev->id_entry->driver_data;
- if (audmux_type == IMX31_AUDMUX)
+
+ switch (audmux_type) {
+ case IMX31_AUDMUX:
audmux_debugfs_init();
+ reg_max = 14;
+ break;
+ case IMX21_AUDMUX:
+ reg_max = 6;
+ break;
+ default:
+ dev_err(&pdev->dev, "unsupported version!\n");
+ return -EINVAL;
+ }
+
+ regcache = devm_kzalloc(&pdev->dev, sizeof(u32) * reg_max, GFP_KERNEL);
+ if (!regcache)
+ return -ENOMEM;
if (of_id)
imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node);
@@ -350,12 +367,47 @@ static int imx_audmux_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int imx_audmux_suspend(struct device *dev)
+{
+ int i;
+
+ clk_prepare_enable(audmux_clk);
+
+ for (i = 0; i < reg_max; i++)
+ regcache[i] = readl(audmux_base + i * 4);
+
+ clk_disable_unprepare(audmux_clk);
+
+ return 0;
+}
+
+static int imx_audmux_resume(struct device *dev)
+{
+ int i;
+
+ clk_prepare_enable(audmux_clk);
+
+ for (i = 0; i < reg_max; i++)
+ writel(regcache[i], audmux_base + i * 4);
+
+ clk_disable_unprepare(audmux_clk);
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops imx_audmux_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(imx_audmux_suspend, imx_audmux_resume)
+};
+
static struct platform_driver imx_audmux_driver = {
.probe = imx_audmux_probe,
.remove = imx_audmux_remove,
.id_table = imx_audmux_ids,
.driver = {
.name = DRIVER_NAME,
+ .pm = &imx_audmux_pm,
.of_match_table = imx_audmux_dt_ids,
}
};
diff --git a/sound/soc/fsl/imx-cs42888.c b/sound/soc/fsl/imx-cs42888.c
new file mode 100644
index 000000000000..1e4a80579741
--- /dev/null
+++ b/sound/soc/fsl/imx-cs42888.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2010-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
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_esai.h"
+
+#define CODEC_CLK_EXTER_OSC 1
+#define CODEC_CLK_ESAI_HCKT 2
+#define SUPPORT_RATE_NUM 10
+
+struct imx_priv {
+ unsigned int mclk_freq;
+ struct platform_device *pdev;
+ struct platform_device *asrc_pdev;
+ u32 asrc_rate;
+ u32 asrc_format;
+ bool is_codec_master;
+};
+
+static struct imx_priv card_priv;
+
+static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct imx_priv *priv = &card_priv;
+ struct device *dev = &priv->pdev->dev;
+ u32 channels = params_channels(params);
+ u32 max_tdm_rate;
+
+ bool enable_tdm = channels > 1 && channels % 2;
+ u32 dai_format = SND_SOC_DAIFMT_NB_NF |
+ (enable_tdm ? SND_SOC_DAIFMT_DSP_A : SND_SOC_DAIFMT_LEFT_J);
+
+ int ret = 0;
+
+ if (priv->is_codec_master) {
+ /* TDM is not supported by codec in master mode */
+ if (enable_tdm) {
+ dev_err(dev, "%d channels are not supported in codec master mode\n",
+ channels);
+ return -EINVAL;
+ }
+ dai_format |= SND_SOC_DAIFMT_CBM_CFM;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = snd_soc_dai_set_sysclk(cpu_dai, ESAI_HCKT_EXTAL,
+ priv->mclk_freq, SND_SOC_CLOCK_IN);
+ else
+ ret = snd_soc_dai_set_sysclk(cpu_dai, ESAI_HCKR_EXTAL,
+ priv->mclk_freq, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+ priv->mclk_freq, SND_SOC_CLOCK_OUT);
+ if (ret) {
+ dev_err(dev, "failed to set codec sysclk: %d\n", ret);
+ return ret;
+ }
+
+ } else {
+ dai_format |= SND_SOC_DAIFMT_CBS_CFS;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = snd_soc_dai_set_sysclk(cpu_dai, ESAI_HCKT_EXTAL,
+ priv->mclk_freq, SND_SOC_CLOCK_OUT);
+ else
+ ret = snd_soc_dai_set_sysclk(cpu_dai, ESAI_HCKR_EXTAL,
+ priv->mclk_freq, SND_SOC_CLOCK_OUT);
+ if (ret) {
+ dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+ priv->mclk_freq, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(dev, "failed to set codec sysclk: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
+ return ret;
+ }
+ /* set i.MX active slot mask */
+ if (enable_tdm) {
+ /* 2 required by ESAI BCLK divisors, 8 slots, 32 width */
+ max_tdm_rate = priv->mclk_freq / (2*8*32);
+ if (params_rate(params) > max_tdm_rate) {
+ dev_err(dev,
+ "maximum supported sampling rate for %d channels is %dKHz\n",
+ channels, max_tdm_rate / 1000);
+ return -EINVAL;
+ }
+
+ /*
+ * Per datasheet, the codec expects 8 slots and 32 bits
+ * for every slot in TDM mode.
+ */
+ snd_soc_dai_set_tdm_slot(cpu_dai,
+ BIT(channels) - 1, BIT(channels) - 1,
+ 8, 32);
+ } else
+ snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32);
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
+ if (ret) {
+ dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int imx_cs42888_surround_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ static struct snd_pcm_hw_constraint_list constraint_rates;
+ struct imx_priv *priv = &card_priv;
+ struct device *dev = &priv->pdev->dev;
+ static u32 support_rates[SUPPORT_RATE_NUM];
+ int ret;
+
+ if (priv->mclk_freq == 24576000) {
+ support_rates[0] = 48000;
+ support_rates[1] = 96000;
+ support_rates[2] = 192000;
+ constraint_rates.list = support_rates;
+ constraint_rates.count = 3;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &constraint_rates);
+ if (ret)
+ return ret;
+ } else
+ dev_warn(dev, "mclk may be not supported %d\n", priv->mclk_freq);
+
+ return 0;
+}
+
+static struct snd_soc_ops imx_cs42888_surround_ops = {
+ .startup = imx_cs42888_surround_startup,
+ .hw_params = imx_cs42888_surround_hw_params,
+};
+
+/**
+ * imx_cs42888_surround_startup() is to set constrain for hw parameter, but
+ * backend use same runtime as frontend, for p2p backend need to use different
+ * parameter, so backend can't use the startup.
+ */
+static struct snd_soc_ops imx_cs42888_surround_ops_be = {
+ .hw_params = imx_cs42888_surround_hw_params,
+};
+
+
+static const struct snd_soc_dapm_widget imx_cs42888_dapm_widgets[] = {
+ SND_SOC_DAPM_LINE("Line Out Jack", NULL),
+ SND_SOC_DAPM_LINE("Line In Jack", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Line out jack */
+ {"Line Out Jack", NULL, "AOUT1L"},
+ {"Line Out Jack", NULL, "AOUT1R"},
+ {"Line Out Jack", NULL, "AOUT2L"},
+ {"Line Out Jack", NULL, "AOUT2R"},
+ {"Line Out Jack", NULL, "AOUT3L"},
+ {"Line Out Jack", NULL, "AOUT3R"},
+ {"Line Out Jack", NULL, "AOUT4L"},
+ {"Line Out Jack", NULL, "AOUT4R"},
+ {"AIN1L", NULL, "Line In Jack"},
+ {"AIN1R", NULL, "Line In Jack"},
+ {"AIN2L", NULL, "Line In Jack"},
+ {"AIN2R", NULL, "Line In Jack"},
+ {"CPU-Playback", NULL, "ASRC-Playback"},
+ {"Playback", NULL, "CPU-Playback"},/* dai route for be and fe */
+ {"ASRC-Capture", NULL, "CPU-Capture"},
+ {"CPU-Capture", NULL, "Capture"},
+};
+
+static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params) {
+
+ struct imx_priv *priv = &card_priv;
+ struct snd_interval *rate;
+ struct snd_mask *mask;
+
+ if (!priv->asrc_pdev)
+ return -EINVAL;
+
+ rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ rate->max = rate->min = priv->asrc_rate;
+
+ mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ snd_mask_none(mask);
+ snd_mask_set(mask, priv->asrc_format);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link imx_cs42888_dai[] = {
+ {
+ .name = "HiFi",
+ .stream_name = "HiFi",
+ .codec_dai_name = "cs42888",
+ .ops = &imx_cs42888_surround_ops,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = "HiFi-ASRC-FE",
+ .stream_name = "HiFi-ASRC-FE",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .dynamic = 1,
+ .ignore_pmdown_time = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .dpcm_merged_chan = 1,
+ },
+ {
+ .name = "HiFi-ASRC-BE",
+ .stream_name = "HiFi-ASRC-BE",
+ .codec_dai_name = "cs42888",
+ .platform_name = "snd-soc-dummy",
+ .no_pcm = 1,
+ .ignore_pmdown_time = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ops = &imx_cs42888_surround_ops_be,
+ .be_hw_params_fixup = be_hw_params_fixup,
+ },
+};
+
+static struct snd_soc_card snd_soc_card_imx_cs42888 = {
+ .name = "cs42888-audio",
+ .dai_link = imx_cs42888_dai,
+ .dapm_widgets = imx_cs42888_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(imx_cs42888_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+ .owner = THIS_MODULE,
+};
+
+/*
+ * This function will register the snd_soc_pcm_link drivers.
+ */
+static int imx_cs42888_probe(struct platform_device *pdev)
+{
+ struct device_node *esai_np, *codec_np;
+ struct device_node *asrc_np = NULL;
+ struct platform_device *esai_pdev;
+ struct platform_device *asrc_pdev = NULL;
+ struct i2c_client *codec_dev;
+ struct imx_priv *priv = &card_priv;
+ struct clk *codec_clk = NULL;
+ int ret;
+ u32 width;
+
+ priv->pdev = pdev;
+ priv->asrc_pdev = NULL;
+
+ esai_np = of_parse_phandle(pdev->dev.of_node, "esai-controller", 0);
+ codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
+ if (!esai_np || !codec_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0);
+ if (asrc_np) {
+ asrc_pdev = of_find_device_by_node(asrc_np);
+ priv->asrc_pdev = asrc_pdev;
+ }
+
+ esai_pdev = of_find_device_by_node(esai_np);
+ if (!esai_pdev) {
+ dev_err(&pdev->dev, "failed to find ESAI platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ codec_dev = of_find_i2c_device_by_node(codec_np);
+ if (!codec_dev || !codec_dev->dev.driver) {
+ dev_err(&pdev->dev, "failed to find codec platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ /*if there is no asrc controller, we only enable one device*/
+ if (!asrc_pdev) {
+ imx_cs42888_dai[0].codec_of_node = codec_np;
+ imx_cs42888_dai[0].cpu_dai_name = dev_name(&esai_pdev->dev);
+ imx_cs42888_dai[0].platform_of_node = esai_np;
+ snd_soc_card_imx_cs42888.num_links = 1;
+ } else {
+ imx_cs42888_dai[0].codec_of_node = codec_np;
+ imx_cs42888_dai[0].cpu_dai_name = dev_name(&esai_pdev->dev);
+ imx_cs42888_dai[0].platform_of_node = esai_np;
+ imx_cs42888_dai[1].cpu_of_node = asrc_np;
+ imx_cs42888_dai[1].platform_of_node = asrc_np;
+ imx_cs42888_dai[2].codec_of_node = codec_np;
+ imx_cs42888_dai[2].cpu_dai_name = dev_name(&esai_pdev->dev);
+ snd_soc_card_imx_cs42888.num_links = 3;
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
+ &priv->asrc_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (width == 24)
+ priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+ else
+ priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+ }
+
+ codec_clk = devm_clk_get(&codec_dev->dev, NULL);
+ if (IS_ERR(codec_clk)) {
+ ret = PTR_ERR(codec_clk);
+ dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret);
+ goto fail;
+ }
+ priv->mclk_freq = clk_get_rate(codec_clk);
+
+ priv->is_codec_master = false;
+ if (of_property_read_bool(pdev->dev.of_node, "codec-master"))
+ priv->is_codec_master = true;
+
+ snd_soc_card_imx_cs42888.dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, &snd_soc_card_imx_cs42888);
+
+ ret = snd_soc_register_card(&snd_soc_card_imx_cs42888);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+fail:
+ if (asrc_np)
+ of_node_put(asrc_np);
+ if (esai_np)
+ of_node_put(esai_np);
+ if (codec_np)
+ of_node_put(codec_np);
+ return ret;
+}
+
+static int imx_cs42888_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_card(&snd_soc_card_imx_cs42888);
+ return 0;
+}
+
+static const struct of_device_id imx_cs42888_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-cs42888", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx_cs42888_driver = {
+ .probe = imx_cs42888_probe,
+ .remove = imx_cs42888_remove,
+ .driver = {
+ .name = "imx-cs42888",
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = imx_cs42888_dt_ids,
+ },
+};
+module_platform_driver(imx_cs42888_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("ALSA SoC cs42888 Machine Layer Driver");
+MODULE_ALIAS("platform:imx-cs42888");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-hdmi-dma.c b/sound/soc/fsl/imx-hdmi-dma.c
new file mode 100644
index 000000000000..411906f9ab70
--- /dev/null
+++ b/sound/soc/fsl/imx-hdmi-dma.c
@@ -0,0 +1,1171 @@
+/*
+ * imx-hdmi-dma.c -- HDMI DMA driver for ALSA Soc Audio Layer
+ *
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc.
+ *
+ * based on imx-pcm-dma-mx2.c
+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is based on code copyrighted by Freescale,
+ * Liam Girdwood, Javier Martin and probably others.
+ *
+ * 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 <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+#include <linux/platform_data/dma-imx.h>
+
+#include <video/mxc_hdmi.h>
+
+#include "imx-hdmi.h"
+
+#define HDMI_DMA_BURST_UNSPECIFIED_LEGNTH 0
+#define HDMI_DMA_BURST_INCR4 1
+#define HDMI_DMA_BURST_INCR8 2
+#define HDMI_DMA_BURST_INCR16 3
+
+#define HDMI_BASE_ADDR 0x00120000
+
+struct hdmi_sdma_script {
+ int control_reg_addr;
+ int status_reg_addr;
+ int dma_start_addr;
+ u32 buffer[20];
+};
+
+struct hdmi_dma_priv {
+ struct snd_pcm_substream *substream;
+ struct platform_device *pdev;
+
+ struct snd_dma_buffer hw_buffer;
+ unsigned long buffer_bytes;
+ unsigned long appl_bytes;
+
+ int periods;
+ int period_time;
+ int period_bytes;
+ int dma_period_bytes;
+ int buffer_ratio;
+
+ unsigned long offset;
+
+ snd_pcm_format_t format;
+ int sample_align;
+ int sample_bits;
+ int channels;
+ int rate;
+
+ int frame_idx;
+
+ bool tx_active;
+ spinlock_t irq_lock;
+
+ /* SDMA part */
+ dma_addr_t phy_hdmi_sdma_t;
+ struct hdmi_sdma_script *hdmi_sdma_t;
+ struct dma_chan *dma_channel;
+ struct dma_async_tx_descriptor *desc;
+ struct imx_hdmi_sdma_params sdma_params;
+};
+
+/* bit 0:0:0:b:p(0):c:(u)0:(v)0 */
+/* max 8 channels supported; channels are interleaved */
+static u8 g_packet_head_table[48 * 8];
+
+void hdmi_dma_copy_16_neon_lut(unsigned short *src, unsigned int *dst,
+ int samples, unsigned char *lookup_table);
+void hdmi_dma_copy_16_neon_fast(unsigned short *src, unsigned int *dst,
+ int samples);
+void hdmi_dma_copy_24_neon_lut(unsigned int *src, unsigned int *dst,
+ int samples, unsigned char *lookup_table);
+void hdmi_dma_copy_24_neon_fast(unsigned int *src, unsigned int *dst,
+ int samples);
+static void hdmi_dma_irq_enable(struct hdmi_dma_priv *priv);
+static void hdmi_dma_irq_disable(struct hdmi_dma_priv *priv);
+
+union hdmi_audio_header_t iec_header;
+EXPORT_SYMBOL(iec_header);
+
+/*
+ * Note that the period size for DMA != period size for ALSA because the
+ * driver adds iec frame info to the audio samples (in hdmi_dma_copy).
+ *
+ * Each 4 byte subframe = 1 byte of iec data + 3 byte audio sample.
+ *
+ * A 16 bit audio sample becomes 32 bits including the frame info. Ratio=2
+ * A 24 bit audio sample becomes 32 bits including the frame info. Ratio=3:4
+ * If the 24 bit raw audio is in 32 bit words, the
+ *
+ * Original Packed into subframe Ratio of size Format
+ * sample how many size of DMA buffer
+ * (bits) bits to ALSA buffer
+ * -------- ----------- -------- -------------- ------------------------
+ * 16 16 32 2 SNDRV_PCM_FORMAT_S16_LE
+ * 24 24 32 1.33 SNDRV_PCM_FORMAT_S24_3LE*
+ * 24 32 32 1 SNDRV_PCM_FORMAT_S24_LE
+ *
+ * *so SNDRV_PCM_FORMAT_S24_3LE is not supported.
+ */
+
+/*
+ * The minimum dma period is one IEC audio frame (192 * 4 * channels).
+ * The maximum dma period for the HDMI DMA is 8K.
+ *
+ * channels minimum maximum
+ * dma period dma period
+ * -------- ------------------ ----------
+ * 2 192 * 4 * 2 = 1536 * 4 = 6144
+ * 4 192 * 4 * 4 = 3072 * 2 = 6144
+ * 6 192 * 4 * 6 = 4608 * 1 = 4608
+ * 8 192 * 4 * 8 = 6144 * 1 = 6144
+ *
+ * Bottom line:
+ * 1. Must keep the ratio of DMA buffer to ALSA buffer consistent.
+ * 2. frame_idx is saved in the private data, so even if a frame cannot be
+ * transmitted in a period, it can be continued in the next period. This
+ * is necessary for 6 ch.
+ */
+#define HDMI_DMA_PERIOD_BYTES (12288)
+#define HDMI_DMA_BUF_SIZE (128 * 1024)
+#define HDMI_PCM_BUF_SIZE (128 * 1024)
+
+#define hdmi_audio_debug(dev, reg) \
+ dev_dbg(dev, #reg ": 0x%02x\n", hdmi_readb(reg))
+
+#ifdef DEBUG
+static void dumpregs(struct device *dev)
+{
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_CONF0);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_START);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_STOP);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_THRSLD);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_STRADDR0);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_STPADDR0);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_BSTADDR0);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_MBLENGTH0);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_MBLENGTH1);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_STAT);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_INT);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_MASK);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_POL);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_CONF1);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_BUFFSTAT);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_BUFFINT);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_BUFFMASK);
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_BUFFPOL);
+ hdmi_audio_debug(dev, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+ hdmi_audio_debug(dev, HDMI_IH_AHBDMAAUD_STAT0);
+ hdmi_audio_debug(dev, HDMI_IH_MUTE);
+}
+
+static void dumppriv(struct device *dev, struct hdmi_dma_priv *priv)
+{
+ dev_dbg(dev, "channels = %d\n", priv->channels);
+ dev_dbg(dev, "periods = %d\n", priv->periods);
+ dev_dbg(dev, "period_bytes = %d\n", priv->period_bytes);
+ dev_dbg(dev, "dma period_bytes = %d\n", priv->dma_period_bytes);
+ dev_dbg(dev, "buffer_ratio = %d\n", priv->buffer_ratio);
+ dev_dbg(dev, "hw dma buffer = 0x%08x\n", (int)priv->hw_buffer.addr);
+ dev_dbg(dev, "dma buf size = %d\n", (int)priv->buffer_bytes);
+ dev_dbg(dev, "sample_rate = %d\n", (int)priv->rate);
+}
+#else
+static void dumpregs(struct device *dev) {}
+static void dumppriv(struct device *dev, struct hdmi_dma_priv *priv) {}
+#endif
+
+/*
+ * Conditions for DMA to work:
+ * ((final_addr - initial_addr)>>2)+1) < 2k. So max period is 8k.
+ * (inital_addr & 0x3) == 0
+ * (final_addr & 0x3) == 0x3
+ *
+ * The DMA Period should be an integer multiple of the IEC 60958 audio
+ * frame size, which is 768 bytes (192 * 4).
+ */
+static void hdmi_dma_set_addr(int start_addr, int dma_period_bytes)
+{
+ int final_addr = start_addr + dma_period_bytes - 1;
+
+ hdmi_write4(start_addr, HDMI_AHB_DMA_STRADDR0);
+ hdmi_write4(final_addr, HDMI_AHB_DMA_STPADDR0);
+}
+
+static void hdmi_dma_irq_set(bool set)
+{
+ u8 val = hdmi_readb(HDMI_AHB_DMA_MASK);
+
+ if (set)
+ val |= HDMI_AHB_DMA_DONE;
+ else
+ val &= (u8)~HDMI_AHB_DMA_DONE;
+
+ hdmi_writeb(val, HDMI_AHB_DMA_MASK);
+}
+
+static void hdmi_mask(int mask)
+{
+ u8 regval = hdmi_readb(HDMI_AHB_DMA_MASK);
+
+ if (mask)
+ regval |= HDMI_AHB_DMA_ERROR | HDMI_AHB_DMA_FIFO_EMPTY;
+ else
+ regval &= (u8)~(HDMI_AHB_DMA_ERROR | HDMI_AHB_DMA_FIFO_EMPTY);
+
+ hdmi_writeb(regval, HDMI_AHB_DMA_MASK);
+}
+
+int odd_ones(unsigned a)
+{
+ a ^= a >> 8;
+ a ^= a >> 4;
+ a ^= a >> 2;
+ a ^= a >> 1;
+
+ return a & 1;
+}
+
+/* Add frame information for one pcm subframe */
+static u32 hdmi_dma_add_frame_info(struct hdmi_dma_priv *priv,
+ u32 pcm_data, int subframe_idx)
+{
+ union hdmi_audio_dma_data_t subframe;
+
+ subframe.U = 0;
+ iec_header.B.channel = subframe_idx;
+
+ /* fill b (start-of-block) */
+ subframe.B.b = (priv->frame_idx == 0) ? 1 : 0;
+
+ /* fill c (channel status) */
+ if (priv->frame_idx < 42)
+ subframe.B.c = (iec_header.U >> priv->frame_idx) & 0x1;
+ else
+ subframe.B.c = 0;
+
+ subframe.B.p = odd_ones(pcm_data);
+ subframe.B.p ^= subframe.B.c;
+ subframe.B.p ^= subframe.B.u;
+ subframe.B.p ^= subframe.B.v;
+
+ /* fill data */
+ if (priv->sample_bits == 16)
+ subframe.B.data = pcm_data << 8;
+ else
+ subframe.B.data = pcm_data;
+
+ return subframe.U;
+}
+
+static void init_table(int channels)
+{
+ unsigned char *p = g_packet_head_table;
+ int i, ch = 0;
+
+ for (i = 0; i < 48; i++) {
+ int b = 0;
+ if (i == 0)
+ b = 1;
+
+ for (ch = 0; ch < channels; ch++) {
+ int c = 0;
+ if (i < 42) {
+ iec_header.B.channel = ch+1;
+ c = (iec_header.U >> i) & 0x1;
+ }
+ /* preset bit p as c */
+ *p++ = (b << 4) | (c << 2) | (c << 3);
+ }
+ }
+}
+
+/*
+ * FIXME: Disable NEON Optimization in hdmi, or it will cause crash of
+ * pulseaudio in the userspace. There is no issue for the Optimization
+ * implemenation, if only use "VPUSH, VPOP" in the function, the pulseaudio
+ * will crash also. So for my assumption, we can't use the NEON in the
+ * interrupt.(tasklet is implemented by softirq.)
+ * Disable SMP, preempt, change the dma buffer to nocached, add protection of
+ * Dn register and fpscr, all these operation have no effect to the result.
+ */
+#define HDMI_DMA_NO_NEON
+
+#ifdef HDMI_DMA_NO_NEON
+/* Optimization for IEC head */
+static void hdmi_dma_copy_16_c_lut(u16 *src, u32 *dst, int samples,
+ u8 *lookup_table)
+{
+ u32 sample, head, p;
+ int i;
+
+ for (i = 0; i < samples; i++) {
+ /* get source sample */
+ sample = *src++;
+
+ /* xor every bit */
+ p = sample ^ (sample >> 8);
+ p ^= (p >> 4);
+ p ^= (p >> 2);
+ p ^= (p >> 1);
+ p &= 1; /* only want last bit */
+ p <<= 3; /* bit p */
+
+ /* get packet header */
+ head = *lookup_table++;
+
+ /* fix head */
+ head ^= p;
+
+ /* store */
+ *dst++ = (head << 24) | (sample << 8);
+ }
+}
+
+static void hdmi_dma_copy_16_c_fast(u16 *src, u32 *dst, int samples)
+{
+ u32 sample, p;
+ int i;
+
+ for (i = 0; i < samples; i++) {
+ /* get source sample */
+ sample = *src++;
+
+ /* xor every bit */
+ p = sample ^ (sample >> 8);
+ p ^= (p >> 4);
+ p ^= (p >> 2);
+ p ^= (p >> 1);
+ p &= 1; /* only want last bit */
+ p <<= 3; /* bit p */
+
+ /* store */
+ *dst++ = (p << 24) | (sample << 8);
+ }
+}
+
+static void hdmi_dma_copy_16(u16 *src, u32 *dst, int framecnt, int channelcnt)
+{
+ /* split input frames into 192-frame each */
+ int count_in_192 = (framecnt + 191) / 192;
+ int i;
+
+ for (i = 0; i < count_in_192; i++) {
+ int count, samples;
+
+ /* handles frame index [0, 48) */
+ count = (framecnt < 48) ? framecnt : 48;
+ samples = count * channelcnt;
+ hdmi_dma_copy_16_c_lut(src, dst, samples, g_packet_head_table);
+ framecnt -= count;
+ if (framecnt == 0)
+ break;
+
+ src += samples;
+ dst += samples;
+
+ /* handles frame index [48, 192) */
+ count = (framecnt < 192 - 48) ? framecnt : 192 - 48;
+ samples = count * channelcnt;
+ hdmi_dma_copy_16_c_fast(src, dst, samples);
+ framecnt -= count;
+ src += samples;
+ dst += samples;
+ }
+}
+#else
+/* NEON optimization for IEC head*/
+
+/**
+ * Convert pcm samples to iec samples suitable for HDMI transfer.
+ * PCM sample is 16 bits length.
+ * Frame index always starts from 0.
+ * Channel count can be 1, 2, 4, 6, or 8
+ * Sample count (frame_count * channel_count) is multipliable by 8.
+ */
+static void hdmi_dma_copy_16(u16 *src, u32 *dst, int framecount, int channelcount)
+{
+ /* split input frames into 192-frame each */
+ int i, count_in_192 = (framecount + 191) / 192;
+
+ for (i = 0; i < count_in_192; i++) {
+ int count, samples;
+
+ /* handles frame index [0, 48) */
+ count = (framecount < 48) ? framecount : 48;
+ samples = count * channelcount;
+ hdmi_dma_copy_16_neon_lut(src, dst, samples, g_packet_head_table);
+ framecount -= count;
+ if (framecount == 0)
+ break;
+
+ src += samples;
+ dst += samples;
+
+ /* handles frame index [48, 192) */
+ count = (framecount < 192 - 48) ? framecount : (192 - 48);
+ samples = count * channelcount;
+ hdmi_dma_copy_16_neon_fast(src, dst, samples);
+ framecount -= count;
+ src += samples;
+ dst += samples;
+ }
+}
+#endif
+
+static void hdmi_dma_mmap_copy(struct snd_pcm_substream *substream,
+ int offset, int count)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdmi_dma_priv *priv = runtime->private_data;
+ struct device *dev = rtd->platform->dev;
+ u32 framecount, *dst;
+ u16 *src16;
+
+ framecount = count / (priv->sample_align * priv->channels);
+
+ /* hw_buffer is the destination for pcm data plus frame info. */
+ dst = (u32 *)(priv->hw_buffer.area + (offset * priv->buffer_ratio));
+
+ switch (priv->format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /* dma_buffer is the mmapped buffer we are copying pcm from. */
+ src16 = (u16 *)(runtime->dma_area + offset);
+ hdmi_dma_copy_16(src16, dst, framecount, priv->channels);
+ break;
+ default:
+ dev_err(dev, "unsupported sample format %s\n",
+ snd_pcm_format_name(priv->format));
+ return;
+ }
+}
+
+static void hdmi_dma_data_copy(struct snd_pcm_substream *substream,
+ struct hdmi_dma_priv *priv, char type)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned long offset, count, appl_bytes, space_to_end;
+
+ if (runtime->access != SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
+ return;
+
+ appl_bytes = (runtime->status->hw_ptr % (priv->buffer_bytes/(runtime->frame_bits/8))) * (runtime->frame_bits/8);
+ if (type == 'p')
+ appl_bytes += 2 * priv->period_bytes;
+ offset = appl_bytes % priv->buffer_bytes;
+
+ switch (type) {
+ case 'p':
+ count = priv->period_bytes;
+ space_to_end = priv->period_bytes;
+ break;
+ case 'b':
+ count = priv->buffer_bytes;
+ space_to_end = priv->buffer_bytes - offset;
+
+ break;
+ default:
+ return;
+ }
+
+ if (count <= space_to_end) {
+ hdmi_dma_mmap_copy(substream, offset, count);
+ } else {
+ hdmi_dma_mmap_copy(substream, offset, space_to_end);
+ hdmi_dma_mmap_copy(substream, 0, count - space_to_end);
+ }
+}
+
+static void hdmi_sdma_callback(void *data)
+{
+ struct hdmi_dma_priv *priv = (struct hdmi_dma_priv *)data;
+ struct snd_pcm_substream *substream = priv->substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+
+ if (runtime && runtime->dma_area && priv->tx_active) {
+ priv->offset += priv->period_bytes;
+ priv->offset %= priv->period_bytes * priv->periods;
+
+ /* Copy data by period_bytes */
+ hdmi_dma_data_copy(substream, priv, 'p');
+
+ snd_pcm_period_elapsed(substream);
+ }
+
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+
+ return;
+}
+
+static int hdmi_dma_set_thrsld_incrtype(struct device *dev, int channels)
+{
+ u8 mask = HDMI_AHB_DMA_CONF0_BURST_MODE | HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK;
+ u8 val = hdmi_readb(HDMI_AHB_DMA_CONF0) & ~mask;
+ int incr_type, threshold;
+
+ switch (hdmi_readb(HDMI_REVISION_ID)) {
+ case 0x0a:
+ incr_type = HDMI_DMA_BURST_INCR4;
+ if (channels == 2)
+ threshold = 126;
+ else
+ threshold = 124;
+ break;
+ case 0x1a:
+ incr_type = HDMI_DMA_BURST_INCR8;
+ threshold = 128;
+ break;
+ default:
+ dev_err(dev, "unknown hdmi controller!\n");
+ return -ENODEV;
+ }
+
+ hdmi_writeb(threshold, HDMI_AHB_DMA_THRSLD);
+
+ switch (incr_type) {
+ case HDMI_DMA_BURST_UNSPECIFIED_LEGNTH:
+ break;
+ case HDMI_DMA_BURST_INCR4:
+ val |= HDMI_AHB_DMA_CONF0_BURST_MODE;
+ break;
+ case HDMI_DMA_BURST_INCR8:
+ val |= HDMI_AHB_DMA_CONF0_BURST_MODE |
+ HDMI_AHB_DMA_CONF0_INCR8;
+ break;
+ case HDMI_DMA_BURST_INCR16:
+ val |= HDMI_AHB_DMA_CONF0_BURST_MODE |
+ HDMI_AHB_DMA_CONF0_INCR16;
+ break;
+ default:
+ dev_err(dev, "invalid increment type: %d!", incr_type);
+ return -EINVAL;
+ }
+
+ hdmi_writeb(val, HDMI_AHB_DMA_CONF0);
+
+ hdmi_audio_debug(dev, HDMI_AHB_DMA_THRSLD);
+
+ return 0;
+}
+
+static int hdmi_dma_configure_dma(struct device *dev, int channels)
+{
+ u8 i, val = 0;
+ int ret;
+
+ if (channels <= 0 || channels > 8 || channels % 2 != 0) {
+ dev_err(dev, "unsupported channel number: %d\n", channels);
+ return -EINVAL;
+ }
+
+ hdmi_audio_writeb(AHB_DMA_CONF0, EN_HLOCK, 0x1);
+
+ ret = hdmi_dma_set_thrsld_incrtype(dev, channels);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < channels; i += 2)
+ val |= 0x3 << i;
+
+ hdmi_writeb(val, HDMI_AHB_DMA_CONF1);
+
+ return 0;
+}
+
+static void hdmi_dma_init_iec_header(void)
+{
+ iec_header.U = 0;
+
+ iec_header.B.consumer = 0; /* Consumer use */
+ iec_header.B.linear_pcm = 0; /* linear pcm audio */
+ iec_header.B.copyright = 1; /* no copyright */
+ iec_header.B.pre_emphasis = 0; /* 2 channels without pre-emphasis */
+ iec_header.B.mode = 0; /* Mode 0 */
+
+ iec_header.B.category_code = 0;
+
+ iec_header.B.source = 2; /* stereo */
+ iec_header.B.channel = 0;
+
+ iec_header.B.sample_freq = 0x02; /* 48 KHz */
+ iec_header.B.clock_acc = 0; /* Level II */
+
+ iec_header.B.word_length = 0x02; /* 16 bits */
+ iec_header.B.org_sample_freq = 0x0D; /* 48 KHz */
+
+ iec_header.B.cgms_a = 0; /* Copying is permitted without restriction */
+}
+
+static int hdmi_dma_update_iec_header(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdmi_dma_priv *priv = runtime->private_data;
+ struct device *dev = rtd->platform->dev;
+
+ iec_header.B.source = priv->channels;
+
+ switch (priv->rate) {
+ case 32000:
+ iec_header.B.sample_freq = 0x03;
+ iec_header.B.org_sample_freq = 0x0C;
+ break;
+ case 44100:
+ iec_header.B.sample_freq = 0x00;
+ iec_header.B.org_sample_freq = 0x0F;
+ break;
+ case 48000:
+ iec_header.B.sample_freq = 0x02;
+ iec_header.B.org_sample_freq = 0x0D;
+ break;
+ case 88200:
+ iec_header.B.sample_freq = 0x08;
+ iec_header.B.org_sample_freq = 0x07;
+ break;
+ case 96000:
+ iec_header.B.sample_freq = 0x0A;
+ iec_header.B.org_sample_freq = 0x05;
+ break;
+ case 176400:
+ iec_header.B.sample_freq = 0x0C;
+ iec_header.B.org_sample_freq = 0x03;
+ break;
+ case 192000:
+ iec_header.B.sample_freq = 0x0E;
+ iec_header.B.org_sample_freq = 0x01;
+ break;
+ default:
+ dev_err(dev, "unsupported sample rate\n");
+ return -EFAULT;
+ }
+
+ switch (priv->format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ iec_header.B.word_length = 0x02;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iec_header.B.word_length = 0x0b;
+ break;
+ default:
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*
+ * The HDMI block transmits the audio data without adding any of the audio
+ * frame bits. So we have to copy the raw dma data from the ALSA buffer
+ * to the DMA buffer, adding the frame information.
+ */
+static int hdmi_dma_copy(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos, void __user *buf,
+ snd_pcm_uframes_t frames)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdmi_dma_priv *priv = runtime->private_data;
+ unsigned int count = frames_to_bytes(runtime, frames);
+ unsigned int pos_bytes = frames_to_bytes(runtime, pos);
+ u32 *hw_buf;
+ int subframe_idx;
+ u32 pcm_data;
+
+ /* Adding frame info to pcm data from userspace and copy to hw_buffer */
+ hw_buf = (u32 *)(priv->hw_buffer.area + (pos_bytes * priv->buffer_ratio));
+
+ while (count > 0) {
+ for (subframe_idx = 1 ; subframe_idx <= priv->channels ; subframe_idx++) {
+ if (copy_from_user(&pcm_data, buf, priv->sample_align))
+ return -EFAULT;
+
+ buf += priv->sample_align;
+ count -= priv->sample_align;
+
+ /* Save the header info to the audio dma buffer */
+ *hw_buf++ = hdmi_dma_add_frame_info(priv, pcm_data, subframe_idx);
+ }
+
+ priv->frame_idx++;
+ if (priv->frame_idx == 192)
+ priv->frame_idx = 0;
+ }
+
+ return 0;
+}
+
+static int hdmi_sdma_initbuf(struct device *dev, struct hdmi_dma_priv *priv)
+{
+ struct hdmi_sdma_script *hdmi_sdma_t = priv->hdmi_sdma_t;
+ u32 *head, *tail, i;
+
+ if (!hdmi_sdma_t) {
+ dev_err(dev, "hdmi private addr invalid!!!\n");
+ return -EINVAL;
+ }
+
+ hdmi_sdma_t->control_reg_addr = HDMI_BASE_ADDR + HDMI_AHB_DMA_START;
+ hdmi_sdma_t->status_reg_addr = HDMI_BASE_ADDR + HDMI_IH_AHBDMAAUD_STAT0;
+ hdmi_sdma_t->dma_start_addr = HDMI_BASE_ADDR + HDMI_AHB_DMA_STRADDR0;
+
+ head = &hdmi_sdma_t->buffer[0];
+ tail = &hdmi_sdma_t->buffer[1];
+
+ for (i = 0; i < priv->sdma_params.buffer_num; i++) {
+ *head = priv->hw_buffer.addr + i * priv->period_bytes * priv->buffer_ratio;
+ *tail = *head + priv->dma_period_bytes - 1;
+ head += 2;
+ tail += 2;
+ }
+
+ return 0;
+}
+
+static int hdmi_sdma_config(struct snd_pcm_substream *substream,
+ struct hdmi_dma_priv *priv)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dai_dev = &priv->pdev->dev;
+ struct device *dev = rtd->platform->dev;
+ struct dma_slave_config slave_config;
+ int ret;
+
+ priv->dma_channel = dma_request_slave_channel(dai_dev, "tx");
+ if (priv->dma_channel == NULL) {
+ dev_err(dev, "failed to alloc dma channel\n");
+ return -EBUSY;
+ }
+
+ slave_config.direction = DMA_TRANS_NONE;
+ slave_config.src_addr = (dma_addr_t)priv->sdma_params.buffer_num;
+ slave_config.dst_addr = (dma_addr_t)priv->sdma_params.phyaddr;
+
+ ret = dmaengine_slave_config(priv->dma_channel, &slave_config);
+ if (ret) {
+ dev_err(dev, "failed to config slave dma\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hdmi_dma_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdmi_dma_priv *priv = runtime->private_data;
+
+ if (priv->dma_channel) {
+ dma_release_channel(priv->dma_channel);
+ priv->dma_channel = NULL;
+ }
+
+ return 0;
+}
+
+static int hdmi_dma_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdmi_dma_priv *priv = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dev = rtd->platform->dev;
+ int ret;
+
+ priv->buffer_bytes = params_buffer_bytes(params);
+ priv->periods = params_periods(params);
+ priv->period_bytes = params_period_bytes(params);
+ priv->channels = params_channels(params);
+ priv->format = params_format(params);
+ priv->rate = params_rate(params);
+
+ priv->offset = 0;
+ priv->period_time = HZ / (priv->rate / params_period_size(params));
+
+ switch (priv->format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ priv->buffer_ratio = 2;
+ priv->sample_align = 2;
+ priv->sample_bits = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ /* 24 bit audio in 32 bit word */
+ priv->buffer_ratio = 1;
+ priv->sample_align = 4;
+ priv->sample_bits = 24;
+ break;
+ default:
+ dev_err(dev, "unsupported sample format: %d\n", priv->format);
+ return -EINVAL;
+ }
+
+ priv->dma_period_bytes = priv->period_bytes * priv->buffer_ratio;
+ priv->sdma_params.buffer_num = priv->periods;
+ priv->sdma_params.phyaddr = priv->phy_hdmi_sdma_t;
+
+ ret = hdmi_sdma_initbuf(dev, priv);
+ if (ret)
+ return ret;
+
+ ret = hdmi_sdma_config(substream, priv);
+ if (ret)
+ return ret;
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+ ret = hdmi_dma_configure_dma(dev, priv->channels);
+ if (ret)
+ return ret;
+
+ hdmi_dma_set_addr(priv->hw_buffer.addr, priv->dma_period_bytes);
+
+ dumppriv(dev, priv);
+
+ hdmi_dma_update_iec_header(substream);
+
+ /* Init par for mmap optimizate */
+ init_table(priv->channels);
+
+ priv->appl_bytes = 0;
+
+ return 0;
+}
+
+static void hdmi_dma_trigger_init(struct snd_pcm_substream *substream,
+ struct hdmi_dma_priv *priv)
+{
+ unsigned long status;
+
+ priv->offset = 0;
+ priv->frame_idx = 0;
+
+ /* Copy data by buffer_bytes */
+ hdmi_dma_data_copy(substream, priv, 'b');
+
+ hdmi_audio_writeb(AHB_DMA_CONF0, SW_FIFO_RST, 0x1);
+
+ /* Delay after reset */
+ udelay(1);
+
+ status = hdmi_readb(HDMI_IH_AHBDMAAUD_STAT0);
+ hdmi_writeb(status, HDMI_IH_AHBDMAAUD_STAT0);
+}
+
+static int hdmi_dma_prepare_and_submit(struct snd_pcm_substream *substream,
+ struct hdmi_dma_priv *priv)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dev = rtd->platform->dev;
+
+ priv->desc = dmaengine_prep_dma_cyclic(priv->dma_channel, 0, 0, 0,
+ DMA_TRANS_NONE, 0);
+ if (!priv->desc) {
+ dev_err(dev, "failed to prepare slave dma\n");
+ return -EINVAL;
+ }
+
+ priv->desc->callback = hdmi_sdma_callback;
+ priv->desc->callback_param = (void *)priv;
+ dmaengine_submit(priv->desc);
+
+ return 0;
+}
+
+static int hdmi_dma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct hdmi_dma_priv *priv = runtime->private_data;
+ struct device *dev = rtd->platform->dev;
+ int ret;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!check_hdmi_state())
+ return 0;
+ hdmi_dma_trigger_init(substream, priv);
+
+ dumpregs(dev);
+
+ priv->tx_active = true;
+ hdmi_audio_writeb(AHB_DMA_START, START, 0x1);
+ hdmi_dma_irq_set(false);
+ hdmi_set_dma_mode(1);
+ ret = hdmi_dma_prepare_and_submit(substream, priv);
+ if (ret)
+ return ret;
+ dma_async_issue_pending(priv->desc->chan);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dmaengine_terminate_all(priv->dma_channel);
+ hdmi_set_dma_mode(0);
+ hdmi_dma_irq_set(true);
+ hdmi_audio_writeb(AHB_DMA_STOP, STOP, 0x1);
+ priv->tx_active = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static snd_pcm_uframes_t hdmi_dma_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdmi_dma_priv *priv = runtime->private_data;
+
+ return bytes_to_frames(runtime, priv->offset);
+}
+
+static struct snd_pcm_hardware snd_imx_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = MXC_HDMI_FORMATS_PLAYBACK,
+ .rate_min = 32000,
+ .channels_min = 2,
+ .channels_max = 8,
+ .buffer_bytes_max = HDMI_PCM_BUF_SIZE,
+ .period_bytes_min = HDMI_DMA_PERIOD_BYTES / 2,
+ .period_bytes_max = HDMI_DMA_PERIOD_BYTES / 2,
+ .periods_min = 8,
+ .periods_max = 8,
+ .fifo_size = 0,
+};
+
+static void hdmi_dma_irq_enable(struct hdmi_dma_priv *priv)
+{
+ unsigned long flags;
+
+ hdmi_writeb(0xff, HDMI_AHB_DMA_POL);
+ hdmi_writeb(0xff, HDMI_AHB_DMA_BUFFPOL);
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+
+ hdmi_writeb(0xff, HDMI_IH_AHBDMAAUD_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+ hdmi_dma_irq_set(false);
+ hdmi_mask(0);
+
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static void hdmi_dma_irq_disable(struct hdmi_dma_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+
+ hdmi_dma_irq_set(true);
+ hdmi_writeb(0x0, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+ hdmi_writeb(0xff, HDMI_IH_AHBDMAAUD_STAT0);
+ hdmi_mask(1);
+
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static int hdmi_dma_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct device *dev = rtd->platform->dev;
+ struct hdmi_dma_priv *priv = dev_get_drvdata(dev);
+ int ret;
+
+ runtime->private_data = priv;
+
+ ret = mxc_hdmi_register_audio(substream);
+ if (ret < 0) {
+ dev_err(dev, "HDMI Video is not ready!\n");
+ return ret;
+ }
+
+ hdmi_audio_writeb(AHB_DMA_CONF0, SW_FIFO_RST, 0x1);
+
+ ret = snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ return ret;
+
+ snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+
+ hdmi_dma_irq_enable(priv);
+
+ return 0;
+}
+
+static int hdmi_dma_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdmi_dma_priv *priv = runtime->private_data;
+
+ hdmi_dma_irq_disable(priv);
+ mxc_hdmi_unregister_audio(substream);
+
+ return 0;
+}
+
+static struct snd_pcm_ops imx_hdmi_dma_pcm_ops = {
+ .open = hdmi_dma_open,
+ .close = hdmi_dma_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = hdmi_dma_hw_params,
+ .hw_free = hdmi_dma_hw_free,
+ .trigger = hdmi_dma_trigger,
+ .pointer = hdmi_dma_pointer,
+ .copy = hdmi_dma_copy,
+};
+
+static int imx_hdmi_dma_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct hdmi_dma_priv *priv = dev_get_drvdata(rtd->platform->dev);
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm *pcm = rtd->pcm;
+ u64 dma_mask = DMA_BIT_MASK(32);
+ int ret = 0;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &dma_mask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+
+ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
+ HDMI_PCM_BUF_SIZE, &substream->dma_buffer);
+ if (ret) {
+ dev_err(card->dev, "failed to alloc playback dma buffer\n");
+ return ret;
+ }
+
+ priv->substream = substream;
+
+ /* Alloc the hw_buffer */
+ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
+ HDMI_DMA_BUF_SIZE, &priv->hw_buffer);
+ if (ret) {
+ dev_err(card->dev, "failed to alloc hw dma buffer\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static void imx_hdmi_dma_pcm_free(struct snd_pcm *pcm)
+{
+ int stream = SNDRV_PCM_STREAM_PLAYBACK;
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_soc_pcm_runtime *rtd = pcm->private_data;
+ struct hdmi_dma_priv *priv = dev_get_drvdata(rtd->platform->dev);
+
+ if (substream) {
+ snd_dma_free_pages(&substream->dma_buffer);
+ substream->dma_buffer.area = NULL;
+ substream->dma_buffer.addr = 0;
+ }
+
+ /* Free the hw_buffer */
+ snd_dma_free_pages(&priv->hw_buffer);
+ priv->hw_buffer.area = NULL;
+ priv->hw_buffer.addr = 0;
+}
+
+static struct snd_soc_platform_driver imx_hdmi_platform = {
+ .ops = &imx_hdmi_dma_pcm_ops,
+ .pcm_new = imx_hdmi_dma_pcm_new,
+ .pcm_free = imx_hdmi_dma_pcm_free,
+};
+
+static int imx_soc_platform_probe(struct platform_device *pdev)
+{
+ struct imx_hdmi *hdmi_drvdata = platform_get_drvdata(pdev);
+ struct hdmi_dma_priv *priv;
+ int ret = 0;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "Failed to alloc hdmi_dma\n");
+ return -ENOMEM;
+ }
+
+ priv->hdmi_sdma_t = dma_alloc_coherent(NULL,
+ sizeof(struct hdmi_sdma_script),
+ &priv->phy_hdmi_sdma_t, GFP_KERNEL);
+ if (!priv->hdmi_sdma_t) {
+ dev_err(&pdev->dev, "Failed to alloc hdmi_sdma_t\n");
+ return -ENOMEM;
+ }
+
+ priv->tx_active = false;
+ spin_lock_init(&priv->irq_lock);
+
+ priv->pdev = hdmi_drvdata->pdev;
+
+ hdmi_dma_init_iec_header();
+
+ dev_set_drvdata(&pdev->dev, priv);
+
+ switch (hdmi_readb(HDMI_REVISION_ID)) {
+ case 0x0a:
+ snd_imx_hardware.period_bytes_max = HDMI_DMA_PERIOD_BYTES / 4;
+ snd_imx_hardware.period_bytes_min = HDMI_DMA_PERIOD_BYTES / 4;
+ break;
+ default:
+ break;
+ }
+
+ ret = snd_soc_register_platform(&pdev->dev, &imx_hdmi_platform);
+ if (ret)
+ goto err_plat;
+
+ return 0;
+
+err_plat:
+ dma_free_coherent(NULL, sizeof(struct hdmi_sdma_script),
+ priv->hdmi_sdma_t, priv->phy_hdmi_sdma_t);
+
+ return ret;
+}
+
+static int imx_soc_platform_remove(struct platform_device *pdev)
+{
+ struct hdmi_dma_priv *priv = dev_get_drvdata(&pdev->dev);
+
+ dma_free_coherent(NULL, sizeof(struct hdmi_sdma_script),
+ priv->hdmi_sdma_t, priv->phy_hdmi_sdma_t);
+
+ snd_soc_unregister_platform(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver imx_hdmi_dma_driver = {
+ .driver = {
+ .name = "imx-hdmi-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = imx_soc_platform_probe,
+ .remove = imx_soc_platform_remove,
+};
+
+module_platform_driver(imx_hdmi_dma_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX HDMI audio DMA");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c
new file mode 100644
index 000000000000..e99a1ed81956
--- /dev/null
+++ b/sound/soc/fsl/imx-hdmi.c
@@ -0,0 +1,114 @@
+/*
+ * ASoC HDMI Transmitter driver for IMX development boards
+ *
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc.
+ *
+ * based on stmp3780_devb_hdmi.c
+ *
+ * Vladimir Barinov <vbarinov@embeddedalley.com>
+ *
+ * Copyright 2008 SigmaTel, Inc
+ * Copyright 2008 Embedded Alley Solutions, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+#include <sound/soc.h>
+
+#include "imx-hdmi.h"
+
+/* imx digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link imx_hdmi_dai_link = {
+ .name = "i.MX HDMI Audio Tx",
+ .stream_name = "i.MX HDMI Audio Tx",
+ .codec_dai_name = "hdmi-hifi.0",
+ .codec_name = "hdmi-audio-codec",
+ .platform_name = "imx-hdmi-audio",
+};
+
+static struct snd_soc_card snd_soc_card_imx_hdmi = {
+ .name = "imx-hdmi-soc",
+ .dai_link = &imx_hdmi_dai_link,
+ .num_links = 1,
+ .owner = THIS_MODULE,
+};
+
+static int imx_hdmi_audio_probe(struct platform_device *pdev)
+{
+ struct device_node *hdmi_np, *np = pdev->dev.of_node;
+ struct snd_soc_card *card = &snd_soc_card_imx_hdmi;
+ struct platform_device *hdmi_pdev;
+ int ret = 0;
+
+ if (!hdmi_get_registered()) {
+ dev_err(&pdev->dev, "initialize HDMI-audio failed. load HDMI-video first!\n");
+ return -ENODEV;
+ }
+
+ hdmi_np = of_parse_phandle(np, "hdmi-controller", 0);
+ if (!hdmi_np) {
+ dev_err(&pdev->dev, "failed to find hdmi-audio cpudai\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ hdmi_pdev = of_find_device_by_node(hdmi_np);
+ if (!hdmi_pdev) {
+ dev_err(&pdev->dev, "failed to find SSI platform device\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ card->dev = &pdev->dev;
+ card->dai_link->cpu_dai_name = dev_name(&hdmi_pdev->dev);
+
+ platform_set_drvdata(pdev, card);
+
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "failed to register card: %d\n", ret);
+
+end:
+ if (hdmi_np)
+ of_node_put(hdmi_np);
+
+ return ret;
+}
+
+static int imx_hdmi_audio_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static const struct of_device_id imx_hdmi_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-hdmi", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
+
+static struct platform_driver imx_hdmi_audio_driver = {
+ .probe = imx_hdmi_audio_probe,
+ .remove = imx_hdmi_audio_remove,
+ .driver = {
+ .of_match_table = imx_hdmi_dt_ids,
+ .name = "imx-audio-hdmi",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+};
+
+module_platform_driver(imx_hdmi_audio_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IMX HDMI TX ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx-audio-hdmi");
diff --git a/sound/soc/fsl/imx-hdmi.h b/sound/soc/fsl/imx-hdmi.h
new file mode 100644
index 000000000000..d06ce9c34d32
--- /dev/null
+++ b/sound/soc/fsl/imx-hdmi.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011-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 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.
+ */
+
+#ifndef __IMX_HDMI_H
+#define __IMX_HDMI_H
+
+struct imx_hdmi_sdma_params {
+ dma_addr_t phyaddr;
+ u32 buffer_num;
+ int dma;
+};
+
+struct imx_hdmi {
+ struct snd_soc_dai_driver cpu_dai_drv;
+ struct platform_device *codec_dev;
+ struct platform_device *dma_dev;
+ struct platform_device *pdev;
+ struct clk *isfr_clk;
+ struct clk *iahb_clk;
+ struct clk *mipi_core_clk;
+};
+
+#define HDMI_MAX_RATES 7
+#define HDMI_MAX_SAMPLE_SIZE 3
+#define HDMI_MAX_CHANNEL_CONSTRAINTS 4
+
+#define MXC_HDMI_RATES_PLAYBACK \
+ (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
+ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+#define MXC_HDMI_FORMATS_PLAYBACK \
+ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+union hdmi_audio_header_t {
+ uint64_t U;
+ struct {
+ unsigned consumer:1;
+ unsigned linear_pcm:1;
+ unsigned copyright:1;
+ unsigned pre_emphasis:3;
+ unsigned mode:2;
+
+ unsigned category_code:8;
+
+ unsigned source:4;
+ unsigned channel:4;
+
+ unsigned sample_freq:4;
+ unsigned clock_acc:2;
+ unsigned reserved0:2;
+
+ unsigned word_length:4;
+ unsigned org_sample_freq:4;
+
+ unsigned cgms_a:2;
+ unsigned reserved1:6;
+
+ unsigned reserved2:8;
+
+ unsigned reserved3:8;
+ } B;
+ unsigned char status[8];
+};
+
+union hdmi_audio_dma_data_t {
+ uint32_t U;
+ struct {
+ unsigned data:24;
+ unsigned v:1;
+ unsigned u:1;
+ unsigned c:1;
+ unsigned p:1;
+ unsigned b:1;
+ unsigned reserved:3;
+ } B;
+};
+
+extern union hdmi_audio_header_t iec_header;
+
+#define hdmi_audio_writeb(reg, bit, val) \
+ do { \
+ hdmi_mask_writeb(val, HDMI_ ## reg, \
+ HDMI_ ## reg ## _ ## bit ## _OFFSET, \
+ HDMI_ ## reg ## _ ## bit ## _MASK); \
+ pr_debug("Set reg: HDMI_" #reg " (0x%x) "\
+ "bit: HDMI_" #reg "_" #bit " (%d) to val: %x\n", \
+ HDMI_ ## reg, HDMI_ ## reg ## _ ## bit ## _OFFSET, val); \
+ } while (0)
+
+#endif /* __IMX_HDMI_H */
diff --git a/sound/soc/fsl/imx-mqs.c b/sound/soc/fsl/imx-mqs.c
new file mode 100644
index 000000000000..a39363590711
--- /dev/null
+++ b/sound/soc/fsl/imx-mqs.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2012, 2014-2016 Freescale Semiconductor, Inc.
+ * Copyright 2012 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 <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#define SUPPORT_RATE_NUM 10
+
+struct imx_priv {
+ unsigned int mclk_freq;
+ struct platform_device *pdev;
+ struct platform_device *asrc_pdev;
+ u32 asrc_rate;
+ u32 asrc_format;
+};
+
+static struct imx_priv card_priv;
+
+static int imx_mqs_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ static struct snd_pcm_hw_constraint_list constraint_rates;
+ struct imx_priv *priv = &card_priv;
+ struct device *dev = &priv->pdev->dev;
+ static u32 support_rates[SUPPORT_RATE_NUM];
+ int ret;
+
+ if (priv->mclk_freq == 24576000) {
+ support_rates[0] = 48000;
+ constraint_rates.list = support_rates;
+ constraint_rates.count = 1;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &constraint_rates);
+ if (ret)
+ return ret;
+ } else
+ dev_warn(dev, "mclk may be not supported %d\n", priv->mclk_freq);
+
+ return 0;
+}
+
+static int imx_mqs_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_card *card = rtd->card;
+ int ret;
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 2, params_width(params));
+ if (ret) {
+ dev_err(card->dev, "failed to set cpu dai tdm slot: %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static struct snd_soc_ops imx_mqs_ops = {
+ .startup = imx_mqs_startup,
+ .hw_params = imx_mqs_hw_params,
+};
+
+static struct snd_soc_ops imx_mqs_ops_be = {
+ .hw_params = imx_mqs_hw_params,
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"CPU-Playback", NULL, "ASRC-Playback"},
+ {"Playback", NULL, "CPU-Playback"},/* dai route for be and fe */
+};
+
+static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params) {
+
+ struct imx_priv *priv = &card_priv;
+ struct snd_interval *rate;
+ struct snd_mask *mask;
+
+ if (!priv->asrc_pdev)
+ return -EINVAL;
+
+ rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ rate->max = rate->min = priv->asrc_rate;
+
+ mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ snd_mask_none(mask);
+ snd_mask_set(mask, priv->asrc_format);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link imx_mqs_dai[] = {
+ {
+ .name = "HiFi",
+ .stream_name = "HiFi",
+ .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .ops = &imx_mqs_ops,
+ },
+ {
+ .name = "HiFi-ASRC-FE",
+ .stream_name = "HiFi-ASRC-FE",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .dynamic = 1,
+ .ignore_pmdown_time = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 0,
+ .dpcm_merged_chan = 1,
+ },
+ {
+ .name = "HiFi-ASRC-BE",
+ .stream_name = "HiFi-ASRC-BE",
+ .codec_dai_name = "fsl-mqs-dai",
+ .platform_name = "snd-soc-dummy",
+ .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .no_pcm = 1,
+ .ignore_pmdown_time = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 0,
+ .ops = &imx_mqs_ops_be,
+ .be_hw_params_fixup = be_hw_params_fixup,
+ },
+};
+
+static struct snd_soc_card snd_soc_card_imx_mqs = {
+ .name = "mqs-audio",
+ .dai_link = imx_mqs_dai,
+ .owner = THIS_MODULE,
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static int imx_mqs_probe(struct platform_device *pdev)
+{
+ struct device_node *cpu_np, *codec_np;
+ struct imx_priv *priv = &card_priv;
+ struct clk *codec_clk = NULL;
+ struct platform_device *codec_dev;
+ struct platform_device *asrc_pdev = NULL;
+ struct platform_device *cpu_pdev;
+ struct device_node *asrc_np;
+ int ret;
+ u32 width;
+
+ priv->pdev = pdev;
+
+ cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
+ if (!cpu_np) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ cpu_pdev = of_find_device_by_node(cpu_np);
+ if (!cpu_pdev) {
+ dev_err(&pdev->dev, "failed to find cpu dai device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0);
+ if (asrc_np) {
+ asrc_pdev = of_find_device_by_node(asrc_np);
+ priv->asrc_pdev = asrc_pdev;
+ }
+
+ codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
+ if (!codec_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ codec_dev = of_find_device_by_node(codec_np);
+ if (!codec_dev) {
+ dev_err(&codec_dev->dev, "failed to find codec device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ codec_clk = devm_clk_get(&codec_dev->dev, NULL);
+ if (IS_ERR(codec_clk)) {
+ ret = PTR_ERR(codec_clk);
+ dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret);
+ goto fail;
+ }
+ priv->mclk_freq = clk_get_rate(codec_clk);
+
+ imx_mqs_dai[0].codec_dai_name = "fsl-mqs-dai";
+
+ if (!asrc_pdev) {
+ imx_mqs_dai[0].codec_of_node = codec_np;
+ imx_mqs_dai[0].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ imx_mqs_dai[0].platform_of_node = cpu_np;
+ snd_soc_card_imx_mqs.num_links = 1;
+ } else {
+ imx_mqs_dai[0].codec_of_node = codec_np;
+ imx_mqs_dai[0].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ imx_mqs_dai[0].platform_of_node = cpu_np;
+ imx_mqs_dai[1].cpu_of_node = asrc_np;
+ imx_mqs_dai[1].platform_of_node = asrc_np;
+ imx_mqs_dai[2].codec_of_node = codec_np;
+ imx_mqs_dai[2].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ snd_soc_card_imx_mqs.num_links = 3;
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
+ &priv->asrc_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (width == 24)
+ priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+ else
+ priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+ }
+
+ snd_soc_card_imx_mqs.dev = &pdev->dev;
+
+ ret = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_imx_mqs);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto fail;
+ }
+
+fail:
+ if (cpu_np)
+ of_node_put(cpu_np);
+
+ return ret;
+}
+
+static const struct of_device_id imx_mqs_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-mqs", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_mqs_dt_ids);
+
+static struct platform_driver imx_mqs_driver = {
+ .driver = {
+ .name = "imx-mqs",
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = imx_mqs_dt_ids,
+ },
+ .probe = imx_mqs_probe,
+};
+module_platform_driver(imx_mqs_driver);
+
+MODULE_AUTHOR("Nicolin Chen <Guangyu.Chen@freescale.com>");
+MODULE_DESCRIPTION("Freescale i.MX MQS ASoC machine driver");
+MODULE_ALIAS("platform:imx-mqs");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/imx-pcm-dma-v2.c b/sound/soc/fsl/imx-pcm-dma-v2.c
new file mode 100644
index 000000000000..f44c760b18d5
--- /dev/null
+++ b/sound/soc/fsl/imx-pcm-dma-v2.c
@@ -0,0 +1,230 @@
+/*
+ * imx-pcm-dma-v2.c -- ALSA Soc Audio Layer
+ *
+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is based on code copyrighted by Freescale,
+ * Liam Girdwood, Javier Martin and probably others.
+ *
+ * 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 <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/soc.h>
+
+#include "imx-pcm.h"
+
+static const struct snd_pcm_hardware imx_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
+ .period_bytes_min = 128,
+ .period_bytes_max = 65532, /* Limited by SDMA engine */
+ .periods_min = 2,
+ .periods_max = 255,
+ .fifo_size = 0,
+};
+
+static bool imx_dma_filter_fn(struct dma_chan *chan, void *param)
+{
+ if (!imx_dma_is_general_purpose(chan))
+ return false;
+
+ chan->private = param;
+
+ return true;
+}
+
+/* this may get called several times by oss emulation */
+static int imx_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct imx_pcm_dma_data *dma_data;
+ struct dma_slave_config config;
+ struct dma_chan *chan;
+ int err = 0;
+
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+ /* return if this is a bufferless transfer e.g.
+ * codec <--> BT codec or GSM modem -- lg FIXME
+ */
+ if (!dma_data)
+ return 0;
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = params_buffer_bytes(params);
+
+ chan = snd_dmaengine_pcm_get_chan(substream);
+ if (!chan)
+ return -EINVAL;
+
+ /* fills in addr_width and direction */
+ err = snd_hwparams_to_dma_slave_config(substream, params, &config);
+ if (err)
+ return err;
+
+ snd_dmaengine_pcm_set_config_from_dai_data(substream,
+ snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
+ &config);
+
+ return dmaengine_slave_config(chan, &config);
+}
+
+static int imx_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ snd_pcm_set_runtime_buffer(substream, NULL);
+ return 0;
+}
+
+static snd_pcm_uframes_t imx_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ return snd_dmaengine_pcm_pointer(substream);
+}
+
+static int imx_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_dmaengine_dai_dma_data *dma_data;
+ int ret;
+
+ snd_soc_set_runtime_hwparams(substream, &imx_pcm_hardware);
+
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+ /* DT boot: filter_data is the DMA name */
+ if (rtd->cpu_dai->dev->of_node) {
+ struct dma_chan *chan;
+
+ chan = dma_request_slave_channel(rtd->cpu_dai->dev,
+ dma_data->filter_data);
+ ret = snd_dmaengine_pcm_open(substream, chan);
+ } else {
+ ret = snd_dmaengine_pcm_open_request_chan(substream,
+ imx_dma_filter_fn,
+ dma_data->filter_data);
+ }
+ return ret;
+}
+
+static int imx_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops imx_pcm_ops = {
+ .open = imx_pcm_open,
+ .close = snd_dmaengine_pcm_close_release_chan,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = imx_pcm_hw_params,
+ .hw_free = imx_pcm_hw_free,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = imx_pcm_pointer,
+ .mmap = imx_pcm_mmap,
+};
+
+static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+ int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = imx_pcm_hardware.buffer_bytes_max;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ if (!buf->area)
+ return -ENOMEM;
+
+ buf->bytes = size;
+ return 0;
+}
+
+static void imx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = SNDRV_PCM_STREAM_PLAYBACK; stream < SNDRV_PCM_STREAM_LAST; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+
+ dma_free_writecombine(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
+ int ret;
+
+ ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ret = imx_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ret = imx_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+
+out:
+ /* free preallocated buffers in case of error */
+ if (ret)
+ imx_pcm_free_dma_buffers(pcm);
+
+ return ret;
+}
+
+static struct snd_soc_platform_driver imx_soc_platform = {
+ .ops = &imx_pcm_ops,
+ .pcm_new = imx_pcm_new,
+ .pcm_free = imx_pcm_free_dma_buffers,
+};
+
+int imx_pcm_platform_register(struct device *dev)
+{
+ return devm_snd_soc_register_platform(dev, &imx_soc_platform);
+}
+EXPORT_SYMBOL_GPL(imx_pcm_platform_register);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index f3d3d1ffa84e..89be19a8e55f 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -42,15 +42,55 @@ static const struct snd_pcm_hardware imx_pcm_hardware = {
SNDRV_PCM_INFO_RESUME,
.buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
.period_bytes_min = 128,
- .period_bytes_max = 65535, /* Limited by SDMA engine */
+ .period_bytes_max = 65532, /* Limited by SDMA engine */
.periods_min = 2,
.periods_max = 255,
.fifo_size = 0,
};
+static void imx_pcm_dma_complete(void *arg)
+{
+ struct snd_pcm_substream *substream = arg;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dmaengine_pcm_runtime_data *prtd = substream->runtime->private_data;
+ struct snd_dmaengine_dai_dma_data *dma_data;
+
+ prtd->pos += snd_pcm_lib_period_bytes(substream);
+ if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
+ prtd->pos = 0;
+
+ snd_pcm_period_elapsed(substream);
+
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ if (dma_data->check_xrun && dma_data->check_xrun(substream))
+ dma_data->device_reset(substream, 1);
+}
+
+static int imx_pcm_dma_prepare_slave_config(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_dmaengine_dai_dma_data *dma_data;
+ struct dmaengine_pcm_runtime_data *prtd = substream->runtime->private_data;
+ int ret;
+
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ prtd->callback = imx_pcm_dma_complete;
+
+ ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
+ if (ret)
+ return ret;
+
+ snd_dmaengine_pcm_set_config_from_dai_data(substream, dma_data,
+ slave_config);
+
+ return 0;
+
+}
+
static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
.pcm_hardware = &imx_pcm_hardware,
- .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+ .prepare_slave_config = imx_pcm_dma_prepare_slave_config,
.compat_filter_fn = filter,
.prealloc_buffer_size = IMX_DEFAULT_DMABUF_SIZE,
};
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
new file mode 100644
index 000000000000..45b71fdbb38d
--- /dev/null
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -0,0 +1,535 @@
+/*
+ * imx-rpmsg-platform.c -- ALSA Soc Audio Layer
+ *
+ * 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 as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/imx_rpmsg.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/soc.h>
+
+#include "imx-pcm.h"
+#include "fsl_rpmsg_i2s.h"
+
+struct i2s_info *i2s_info_g;
+
+static const struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .buffer_bytes_max = IMX_SAI_DMABUF_SIZE,
+ .period_bytes_min = 512,
+ .period_bytes_max = 65532, /* Limited by SDMA engine */
+ .periods_min = 2,
+ .periods_max = 255,
+ .fifo_size = 0,
+};
+
+static int imx_rpmsg_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg_tx = &i2s_info->send_msg[SNDRV_PCM_STREAM_PLAYBACK];
+ struct i2s_rpmsg_s *rpmsg_rx = &i2s_info->send_msg[SNDRV_PCM_STREAM_CAPTURE];
+
+ rpmsg_tx->param.rate = params_rate(params);
+ rpmsg_rx->param.rate = params_rate(params);
+ if (SNDRV_PCM_FORMAT_S16_LE == params_format(params)) {
+ rpmsg_tx->param.format = RPMSG_S16_LE;
+ rpmsg_rx->param.format = RPMSG_S16_LE;
+ } else {
+ rpmsg_tx->param.format = RPMSG_S24_LE;
+ rpmsg_rx->param.format = RPMSG_S24_LE;
+ }
+
+ if (params_channels(params) == 1) {
+ rpmsg_tx->param.channels = RPMSG_CH_LEFT;
+ rpmsg_rx->param.channels = RPMSG_CH_LEFT;
+ } else {
+ rpmsg_tx->param.channels = RPMSG_CH_STEREO;
+ rpmsg_rx->param.channels = RPMSG_CH_STEREO;
+ }
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = params_buffer_bytes(params);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ rpmsg_tx->header.cmd = I2S_TX_HW_PARAM;
+ i2s_info->send_message(rpmsg_tx, i2s_info);
+ } else {
+ rpmsg_rx->header.cmd = I2S_RX_HW_PARAM;
+ i2s_info->send_message(rpmsg_rx, i2s_info);
+ }
+
+ return 0;
+}
+
+static int imx_rpmsg_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ snd_pcm_set_runtime_buffer(substream, NULL);
+ return 0;
+}
+
+static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(
+ struct snd_pcm_substream *substream)
+{
+ struct dma_tx_state state;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
+ unsigned int buf_size;
+ unsigned int pos = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2s_info->lock[substream->stream], flags);
+ state.residue = (i2s_info->num_period[substream->stream] -
+ rpmsg->param.buffer_tail)
+ * rpmsg->param.period_size;
+ spin_unlock_irqrestore(&i2s_info->lock[substream->stream], flags);
+
+ buf_size = snd_pcm_lib_buffer_bytes(substream);
+ if (state.residue > 0 && state.residue <= buf_size)
+ pos = buf_size - state.residue;
+
+ return bytes_to_frames(substream->runtime, pos);
+}
+
+static int imx_rpmsg_pcm_open(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
+ struct dmaengine_pcm_runtime_data *prtd;
+
+ snd_soc_set_runtime_hwparams(substream, &imx_rpmsg_pcm_hardware);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rpmsg->header.cmd = I2S_TX_OPEN;
+ else
+ rpmsg->header.cmd = I2S_RX_OPEN;
+ i2s_info->send_message(rpmsg, i2s_info);
+
+ prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+ if (!prtd)
+ return -ENOMEM;
+
+ substream->runtime->private_data = prtd;
+
+ ret = snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
+static int imx_rpmsg_pcm_close(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
+ struct dmaengine_pcm_runtime_data *prtd =
+ substream->runtime->private_data;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rpmsg->header.cmd = I2S_TX_CLOSE;
+ else
+ rpmsg->header.cmd = I2S_RX_CLOSE;
+
+ flush_workqueue(i2s_info->rpmsg_wq);
+ i2s_info->send_message(rpmsg, i2s_info);
+
+ kfree(prtd);
+
+ return ret;
+}
+
+static int imx_rpmsg_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+}
+
+static void imx_rpmsg_pcm_dma_complete(void *arg)
+{
+ struct snd_pcm_substream *substream = arg;
+ struct dmaengine_pcm_runtime_data *prtd
+ = substream->runtime->private_data;
+
+ prtd->pos += snd_pcm_lib_period_bytes(substream);
+ if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
+ prtd->pos = 0;
+
+ snd_pcm_period_elapsed(substream);
+}
+
+static int imx_rpmsg_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
+ u8 index = i2s_info->work_index;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rpmsg->header.cmd = I2S_TX_BUFFER;
+ else
+ rpmsg->header.cmd = I2S_RX_BUFFER;
+
+ rpmsg->param.buffer_addr = substream->runtime->dma_addr;
+ rpmsg->param.buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ rpmsg->param.period_size = snd_pcm_lib_period_bytes(substream);
+ rpmsg->param.buffer_tail = 0;
+
+ i2s_info->num_period[substream->stream] =
+ rpmsg->param.buffer_size/rpmsg->param.period_size;
+
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
+ sizeof(struct i2s_rpmsg_s));
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
+
+ i2s_info->callback[substream->stream] = imx_rpmsg_pcm_dma_complete;
+ i2s_info->callback_param[substream->stream] = substream;
+ return 0;
+}
+
+static void imx_rpmsg_async_issue_pending(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
+ u8 index = i2s_info->work_index;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rpmsg->header.cmd = I2S_TX_START;
+ else
+ rpmsg->header.cmd = I2S_RX_START;
+
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
+ sizeof(struct i2s_rpmsg_s));
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
+}
+
+static int imx_rpmsg_resume(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
+ u8 index = i2s_info->work_index;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rpmsg->header.cmd = I2S_TX_RESTART;
+ else
+ rpmsg->header.cmd = I2S_RX_RESTART;
+
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
+ sizeof(struct i2s_rpmsg_s));
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
+
+ return 0;
+}
+
+static int imx_rpmsg_pause(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
+ u8 index = i2s_info->work_index;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rpmsg->header.cmd = I2S_TX_PAUSE;
+ else
+ rpmsg->header.cmd = I2S_RX_PAUSE;
+
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
+ sizeof(struct i2s_rpmsg_s));
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
+
+ return 0;
+}
+
+static int imx_rpmsg_terminate_all(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
+ struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
+ struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
+ u8 index = i2s_info->work_index;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rpmsg->header.cmd = I2S_TX_TERMINATE;
+ else
+ rpmsg->header.cmd = I2S_RX_TERMINATE;
+
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
+ sizeof(struct i2s_rpmsg_s));
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
+
+ return 0;
+}
+
+int imx_rpmsg_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ ret = imx_rpmsg_pcm_prepare_and_submit(substream);
+ if (ret)
+ return ret;
+ imx_rpmsg_async_issue_pending(substream);
+ break;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ imx_rpmsg_resume(substream);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (runtime->info & SNDRV_PCM_INFO_PAUSE)
+ imx_rpmsg_pause(substream);
+ else
+ imx_rpmsg_terminate_all(substream);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ imx_rpmsg_pause(substream);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ imx_rpmsg_terminate_all(substream);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct snd_pcm_ops imx_rpmsg_pcm_ops = {
+ .open = imx_rpmsg_pcm_open,
+ .close = imx_rpmsg_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = imx_rpmsg_pcm_hw_params,
+ .hw_free = imx_rpmsg_pcm_hw_free,
+ .trigger = imx_rpmsg_pcm_trigger,
+ .pointer = imx_rpmsg_pcm_pointer,
+ .mmap = imx_rpmsg_pcm_mmap,
+};
+
+static int imx_rpmsg_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+ int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = imx_rpmsg_pcm_hardware.buffer_bytes_max;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ if (!buf->area)
+ return -ENOMEM;
+
+ buf->bytes = size;
+ return 0;
+}
+
+static void imx_rpmsg_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = SNDRV_PCM_STREAM_PLAYBACK;
+ stream < SNDRV_PCM_STREAM_LAST; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+
+ dma_free_writecombine(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+static int imx_rpmsg_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
+ int ret;
+
+ ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+
+out:
+ /* free preallocated buffers in case of error */
+ if (ret)
+ imx_rpmsg_pcm_free_dma_buffers(pcm);
+
+ return ret;
+}
+
+static struct snd_soc_platform_driver imx_rpmsg_soc_platform = {
+ .ops = &imx_rpmsg_pcm_ops,
+ .pcm_new = imx_rpmsg_pcm_new,
+ .pcm_free = imx_rpmsg_pcm_free_dma_buffers,
+};
+
+int imx_rpmsg_platform_register(struct device *dev)
+{
+
+ struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(dev);
+
+ i2s_info_g = &rpmsg_i2s->i2s_info;
+
+ return devm_snd_soc_register_platform(dev, &imx_rpmsg_soc_platform);
+}
+EXPORT_SYMBOL_GPL(imx_rpmsg_platform_register);
+
+static int i2s_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
+ void *priv, u32 src)
+{
+ struct i2s_rpmsg_r *msg = (struct i2s_rpmsg_r *)data;
+ struct i2s_rpmsg_s *rpmsg;
+ unsigned long flags;
+
+ dev_dbg(&rpdev->dev, "get from%d: cmd:%d.\n", src, msg->header.cmd);
+
+ memcpy(&i2s_info_g->recv_msg, msg, sizeof(struct i2s_rpmsg_r));
+
+ if (msg->header.type == I2S_TYPE_C) {
+ if (msg->header.cmd == I2S_TX_PERIOD_DONE) {
+ spin_lock_irqsave(&i2s_info_g->lock[0], flags);
+ rpmsg = &i2s_info_g->send_msg[0];
+ rpmsg->param.buffer_tail++;
+ rpmsg->param.buffer_tail %= i2s_info_g->num_period[0];
+ spin_unlock_irqrestore(&i2s_info_g->lock[0], flags);
+ i2s_info_g->callback[0](i2s_info_g->callback_param[0]);
+ } else if (msg->header.cmd == I2S_RX_PERIOD_DONE) {
+ spin_lock_irqsave(&i2s_info_g->lock[1], flags);
+ rpmsg = &i2s_info_g->send_msg[1];
+ rpmsg->param.buffer_tail++;
+ rpmsg->param.buffer_tail %= i2s_info_g->num_period[1];
+ spin_unlock_irqrestore(&i2s_info_g->lock[1], flags);
+ i2s_info_g->callback[1](i2s_info_g->callback_param[1]);
+ }
+ }
+
+ if (msg->header.type == I2S_TYPE_B)
+ complete(&i2s_info_g->cmd_complete);
+
+ return 0;
+}
+
+static int i2s_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+ i2s_info_g->rpdev = rpdev;
+
+ init_completion(&i2s_info_g->cmd_complete);
+
+ dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+ rpdev->src, rpdev->dst);
+ return 0;
+}
+
+static void i2s_rpmsg_remove(struct rpmsg_device *rpdev)
+{
+ dev_info(&rpdev->dev, "i2s rpmsg driver is removed\n");
+}
+
+static struct rpmsg_device_id i2s_rpmsg_id_table[] = {
+ { .name = "rpmsg-audio-channel" },
+ { },
+};
+
+static struct rpmsg_driver i2s_rpmsg_driver = {
+ .drv.name = "i2s_rpmsg",
+ .drv.owner = THIS_MODULE,
+ .id_table = i2s_rpmsg_id_table,
+ .probe = i2s_rpmsg_probe,
+ .callback = i2s_rpmsg_cb,
+ .remove = i2s_rpmsg_remove,
+};
+
+static int __init i2s_rpmsg_init(void)
+{
+ return register_rpmsg_driver(&i2s_rpmsg_driver);
+}
+
+static void __exit i2s_rpmsg_exit(void)
+{
+ unregister_rpmsg_driver(&i2s_rpmsg_driver);
+}
+module_init(i2s_rpmsg_init);
+module_exit(i2s_rpmsg_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
index 133c4470acad..c9c03d2b4aa5 100644
--- a/sound/soc/fsl/imx-pcm.h
+++ b/sound/soc/fsl/imx-pcm.h
@@ -43,13 +43,27 @@ struct imx_pcm_fiq_params {
struct snd_dmaengine_dai_dma_data *dma_params_tx;
};
+#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_RPMSG)
+int imx_rpmsg_platform_register(struct device *dev);
+#else
+static inline int imx_rpmsg_platform_register(struct device *dev)
+{
+ return -ENODEV;
+}
+#endif
+
#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)
int imx_pcm_dma_init(struct platform_device *pdev, size_t size);
+int imx_pcm_platform_register(struct device *dev);
#else
static inline int imx_pcm_dma_init(struct platform_device *pdev, size_t size)
{
return -ENODEV;
}
+static inline int imx_pcm_platform_register(struct device *dev)
+{
+ return -ENODEV;
+}
#endif
#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ)
@@ -68,4 +82,39 @@ static inline void imx_pcm_fiq_exit(struct platform_device *pdev)
}
#endif
+static inline void imx_pcm_stream_trigger(struct snd_pcm_substream *s, int tr)
+{
+ if (s->runtime->status->state == SNDRV_PCM_STATE_RUNNING && s->ops)
+ s->ops->trigger(s, tr);
+}
+
+static inline void imx_stop_lock_pcm_streams(struct snd_pcm_substream **s,
+ int count, unsigned long *flags)
+{
+ int i;
+
+ local_irq_save(*flags);
+ for (i = 0; i < count; i++) {
+ if (!s[i])
+ continue;
+ snd_pcm_stream_lock(s[i]);
+ imx_pcm_stream_trigger(s[i], SNDRV_PCM_TRIGGER_STOP);
+ }
+}
+
+static inline void imx_start_unlock_pcm_streams(struct snd_pcm_substream **s,
+ int count, unsigned long *flags)
+{
+ int i;
+
+ for (i = count - 1; i >= 0; i--) {
+ if (!s[i])
+ continue;
+ imx_pcm_stream_trigger(s[i], SNDRV_PCM_TRIGGER_START);
+ snd_pcm_stream_unlock(s[i]);
+ }
+ local_irq_restore(*flags);
+}
+
+
#endif /* _IMX_PCM_H */
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
new file mode 100644
index 000000000000..72b2e01212d9
--- /dev/null
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 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/module.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/control.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <linux/pinctrl/consumer.h>
+#include "fsl_rpmsg_i2s.h"
+
+struct imx_rpmsg_data {
+ struct snd_soc_dai_link dai[1];
+ struct snd_soc_card card;
+};
+
+static int imx_rpmsg_probe(struct platform_device *pdev)
+{
+ struct device_node *cpu_np;
+ struct platform_device *cpu_pdev;
+ struct imx_rpmsg_data *data;
+ int ret;
+
+ cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ cpu_pdev = of_find_device_by_node(cpu_np);
+ if (!cpu_pdev) {
+ dev_err(&pdev->dev, "failed to find rpmsg platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ data->dai[0].name = "rpmsg hifi";
+ data->dai[0].stream_name = "rpmsg hifi";
+ data->dai[0].codec_dai_name = "snd-soc-dummy-dai";
+ data->dai[0].codec_name = "snd-soc-dummy";
+ data->dai[0].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ data->dai[0].platform_of_node = cpu_np;
+ data->dai[0].playback_only = false;
+ data->dai[0].capture_only = false;
+ data->dai[0].dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+ data->card.num_links = 1;
+ data->card.dai_link = data->dai;
+
+ data->card.dev = &pdev->dev;
+ data->card.owner = THIS_MODULE;
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto fail;
+
+ platform_set_drvdata(pdev, &data->card);
+ snd_soc_card_set_drvdata(&data->card, data);
+ ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto fail;
+ }
+
+fail:
+ if (cpu_np)
+ of_node_put(cpu_np);
+ return ret;
+}
+
+static const struct of_device_id imx_rpmsg_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-rpmsg", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_rpmsg_dt_ids);
+
+static struct platform_driver imx_rpmsg_driver = {
+ .driver = {
+ .name = "imx-audio-rpmsg",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = imx_rpmsg_dt_ids,
+ },
+ .probe = imx_rpmsg_probe,
+};
+module_platform_driver(imx_rpmsg_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale i.MX rpmsg audio ASoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-rpmsg");
diff --git a/sound/soc/fsl/imx-si476x.c b/sound/soc/fsl/imx-si476x.c
new file mode 100644
index 000000000000..767667f135a0
--- /dev/null
+++ b/sound/soc/fsl/imx-si476x.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2008-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
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <sound/soc.h>
+
+#include "imx-audmux.h"
+
+static int imx_audmux_config(int slave, int master)
+{
+ unsigned int ptcr, pdcr;
+ slave = slave - 1;
+ master = master - 1;
+
+ ptcr = IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TFSEL(slave) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR |
+ IMX_AUDMUX_V2_PTCR_TCSEL(slave);
+ pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(slave);
+ imx_audmux_v2_configure_port(master, ptcr, pdcr);
+
+ /*
+ * According to RM, RCLKDIR and SYN should not be changed at same time.
+ * So separate to two step for configuring this port.
+ */
+ ptcr |= IMX_AUDMUX_V2_PTCR_RFSDIR |
+ IMX_AUDMUX_V2_PTCR_RFSEL(slave) |
+ IMX_AUDMUX_V2_PTCR_RCLKDIR |
+ IMX_AUDMUX_V2_PTCR_RCSEL(slave);
+ imx_audmux_v2_configure_port(master, ptcr, pdcr);
+
+ ptcr = IMX_AUDMUX_V2_PTCR_SYN;
+ pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(master);
+ imx_audmux_v2_configure_port(slave, ptcr, pdcr);
+
+ return 0;
+}
+
+static int imx_si476x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ u32 channels = params_channels(params);
+ u32 rate = params_rate(params);
+ u32 bclk = rate * channels * 32;
+ int ret = 0;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret) {
+ dev_err(cpu_dai->dev, "failed to set dai fmt\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai,
+ channels == 1 ? 1 : 0x3,
+ channels == 1 ? 1 : 0x3,
+ 2, 32);
+ if (ret) {
+ dev_err(cpu_dai->dev, "failed to set dai tdm slot\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, bclk, SND_SOC_CLOCK_OUT);
+ if (ret)
+ dev_err(cpu_dai->dev, "failed to set sysclk\n");
+
+ return ret;
+}
+
+static struct snd_soc_ops imx_si476x_ops = {
+ .hw_params = imx_si476x_hw_params,
+};
+
+static struct snd_soc_dai_link imx_dai = {
+ .name = "imx-si476x",
+ .stream_name = "imx-si476x",
+ .codec_dai_name = "si476x-codec",
+ .ops = &imx_si476x_ops,
+};
+
+static struct snd_soc_card snd_soc_card_imx_3stack = {
+ .name = "imx-audio-si476x",
+ .dai_link = &imx_dai,
+ .num_links = 1,
+ .owner = THIS_MODULE,
+};
+
+static int imx_si476x_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &snd_soc_card_imx_3stack;
+ struct device_node *ssi_np, *np = pdev->dev.of_node;
+ struct platform_device *ssi_pdev;
+ struct i2c_client *fm_dev;
+ struct device_node *fm_np = NULL;
+ int int_port, ext_port, ret;
+
+ ret = of_property_read_u32(np, "mux-int-port", &int_port);
+ if (ret) {
+ dev_err(&pdev->dev, "mux-int-port missing or invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
+ if (ret) {
+ dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");
+ return ret;
+ }
+
+ imx_audmux_config(int_port, ext_port);
+
+ ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
+ if (!ssi_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ return -EINVAL;
+ }
+
+ ssi_pdev = of_find_device_by_node(ssi_np);
+ if (!ssi_pdev) {
+ dev_err(&pdev->dev, "failed to find SSI platform device\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ fm_np = of_parse_phandle(pdev->dev.of_node, "fm-controller", 0);
+ if (!fm_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ fm_dev = of_find_i2c_device_by_node(fm_np->parent);
+ if (!fm_dev || !fm_dev->dev.driver) {
+ dev_err(&pdev->dev, "failed to find FM platform device\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ card->dev = &pdev->dev;
+ card->dai_link->cpu_dai_name = dev_name(&ssi_pdev->dev);
+ card->dai_link->platform_of_node = ssi_np;
+ card->dai_link->codec_of_node = fm_np;
+
+ platform_set_drvdata(pdev, card);
+
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to register card: %d\n", ret);
+
+end:
+ if (ssi_np)
+ of_node_put(ssi_np);
+ if (fm_np)
+ of_node_put(fm_np);
+
+ return ret;
+}
+
+static int imx_si476x_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &snd_soc_card_imx_3stack;
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static const struct of_device_id imx_si476x_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-si476x", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_si476x_dt_ids);
+
+static struct platform_driver imx_si476x_driver = {
+ .driver = {
+ .name = "imx-tuner-si476x",
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = imx_si476x_dt_ids,
+ },
+ .probe = imx_si476x_probe,
+ .remove = imx_si476x_remove,
+};
+
+module_platform_driver(imx_si476x_driver);
+
+/* Module information */
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("ALSA SoC i.MX si476x");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx-tuner-si476x");
diff --git a/sound/soc/fsl/imx-sii902x.c b/sound/soc/fsl/imx-sii902x.c
new file mode 100644
index 000000000000..b9059920415f
--- /dev/null
+++ b/sound/soc/fsl/imx-sii902x.c
@@ -0,0 +1,276 @@
+/*
+ * 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/module.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/control.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <linux/pinctrl/consumer.h>
+#include "fsl_sai.h"
+
+#define SUPPORT_RATE_NUM 10
+
+struct imx_sii902x_data {
+ struct snd_soc_dai_link dai;
+ struct snd_soc_card card;
+ struct i2c_client *sii902x;
+ bool is_stream_opened[2];
+};
+
+static int imx_sii902x_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ static struct snd_pcm_hw_constraint_list constraint_rates;
+ static u32 support_rates[SUPPORT_RATE_NUM];
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_sii902x_data *data = snd_soc_card_get_drvdata(card);
+ struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ int ret;
+
+ data->is_stream_opened[tx] = true;
+ if (data->is_stream_opened[tx] != sai->is_stream_opened[tx] ||
+ data->is_stream_opened[!tx] != sai->is_stream_opened[!tx]) {
+ data->is_stream_opened[tx] = false;
+ return -EBUSY;
+ }
+
+ support_rates[0] = 32000;
+ support_rates[1] = 48000;
+ support_rates[2] = 96000;
+ support_rates[3] = 192000;
+ constraint_rates.list = support_rates;
+ constraint_rates.count = 4;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &constraint_rates);
+ if (ret)
+ return ret;
+
+ ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
+ 1, 2);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int imx_sii902x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct device *dev = card->dev;
+ struct imx_sii902x_data *data = snd_soc_card_get_drvdata(card);
+ int ret;
+ unsigned char reg;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_LEFT_J |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
+ if (ret) {
+ dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 2, 24);
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
+ return ret;
+ }
+
+ /* sii90sx hdmi audio setup */
+ i2c_smbus_write_byte_data(data->sii902x, 0x26, 0x90);
+ i2c_smbus_write_byte_data(data->sii902x, 0x20, 0x2d);
+ i2c_smbus_write_byte_data(data->sii902x, 0x1f, 0x88);
+ i2c_smbus_write_byte_data(data->sii902x, 0x1f, 0x91);
+ i2c_smbus_write_byte_data(data->sii902x, 0x1f, 0xa2);
+ i2c_smbus_write_byte_data(data->sii902x, 0x1f, 0xb3);
+ i2c_smbus_write_byte_data(data->sii902x, 0x27, 0);
+ switch (params_rate(params)) {
+ case 44100:
+ reg = 0;
+ break;
+ case 48000:
+ reg = 0x2;
+ break;
+ case 32000:
+ reg = 0x3;
+ break;
+ case 88200:
+ reg = 0x8;
+ break;
+ case 96000:
+ reg = 0xa;
+ break;
+ case 176400:
+ reg = 0xc;
+ break;
+ case 192000:
+ reg = 0xe;
+ break;
+ default:
+ reg = 0x1;
+ break;
+ }
+ i2c_smbus_write_byte_data(data->sii902x, 0x24, reg);
+ i2c_smbus_write_byte_data(data->sii902x, 0x25, 0x0b);
+ i2c_smbus_write_byte_data(data->sii902x, 0x26, 0x80);
+
+ return 0;
+}
+
+static int imx_sii902x_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_sii902x_data *data = snd_soc_card_get_drvdata(card);
+
+ i2c_smbus_write_byte_data(data->sii902x, 0x26, 0x10);
+
+ return 0;
+}
+
+static void imx_sii902x_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_sii902x_data *data = snd_soc_card_get_drvdata(card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+
+ data->is_stream_opened[tx] = false;
+}
+
+static struct snd_soc_ops imx_sii902x_ops = {
+ .startup = imx_sii902x_startup,
+ .shutdown = imx_sii902x_shutdown,
+ .hw_params = imx_sii902x_hw_params,
+ .hw_free = imx_sii902x_hw_free,
+};
+
+static int imx_sii902x_probe(struct platform_device *pdev)
+{
+ struct device_node *cpu_np, *sii902x_np = NULL;
+ struct platform_device *cpu_pdev;
+ struct imx_sii902x_data *data;
+ int ret;
+
+ cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ sii902x_np = of_parse_phandle(pdev->dev.of_node, "hdmi-controler", 0);
+ if (!sii902x_np) {
+ dev_err(&pdev->dev, "sii902x phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ cpu_pdev = of_find_device_by_node(cpu_np);
+ if (!cpu_pdev) {
+ dev_err(&pdev->dev, "failed to find SAI platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ data->sii902x = of_find_i2c_device_by_node(sii902x_np);
+ if (!data->sii902x) {
+ dev_err(&pdev->dev, "failed to find sii902x i2c client\n");
+ ret = -EPROBE_DEFER;
+ goto fail;
+ }
+
+ data->dai.name = "sii902x hdmi";
+ data->dai.stream_name = "sii902x hdmi";
+ data->dai.codec_dai_name = "snd-soc-dummy-dai";
+ data->dai.codec_name = "snd-soc-dummy";
+ data->dai.cpu_dai_name = dev_name(&cpu_pdev->dev);
+ data->dai.platform_of_node = cpu_np;
+ data->dai.ops = &imx_sii902x_ops;
+ data->dai.playback_only = true;
+ data->dai.capture_only = false;
+ data->dai.dai_fmt = SND_SOC_DAIFMT_LEFT_J |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
+ data->card.dev = &pdev->dev;
+ data->card.owner = THIS_MODULE;
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto fail;
+ data->card.num_links = 1;
+ data->card.dai_link = &data->dai;
+
+ platform_set_drvdata(pdev, &data->card);
+ snd_soc_card_set_drvdata(&data->card, data);
+ ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto fail;
+ }
+
+fail:
+ if (cpu_np)
+ of_node_put(cpu_np);
+ if (sii902x_np)
+ of_node_put(sii902x_np);
+ return ret;
+}
+
+static const struct of_device_id imx_sii902x_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-sii902x", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_sii902x_dt_ids);
+
+static struct platform_driver imx_sii902x_driver = {
+ .driver = {
+ .name = "imx-sii902x",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = imx_sii902x_dt_ids,
+ },
+ .probe = imx_sii902x_probe,
+};
+module_platform_driver(imx_sii902x_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale i.MX SII902X hdmi audio ASoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-sii902x");
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c
index fb896b2c9ba3..79942430eb94 100644
--- a/sound/soc/fsl/imx-spdif.c
+++ b/sound/soc/fsl/imx-spdif.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-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
diff --git a/sound/soc/fsl/imx-wm8958.c b/sound/soc/fsl/imx-wm8958.c
new file mode 100644
index 000000000000..09b8187f94af
--- /dev/null
+++ b/sound/soc/fsl/imx-wm8958.c
@@ -0,0 +1,587 @@
+/*
+ * 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/module.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/control.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/mfd/wm8994/registers.h>
+#include <linux/mfd/syscon.h>
+#include "../fsl/fsl_sai.h"
+#include "../codecs/wm8994.h"
+
+#define DAI_NAME_SIZE 32
+
+struct imx_wm8958_data {
+ struct snd_soc_dai_link dai;
+ struct snd_soc_card card;
+ char codec_dai_name[DAI_NAME_SIZE];
+ char platform_name[DAI_NAME_SIZE];
+ struct clk *mclk;
+ unsigned int clk_frequency;
+ bool is_codec_master;
+ int sr_stream[2];
+ struct regmap *gpr;
+};
+
+struct imx_priv {
+ int hp_gpio;
+ int hp_active_low;
+ struct snd_soc_codec *codec;
+ struct platform_device *pdev;
+ struct snd_kcontrol *headphone_kctl;
+ struct snd_card *snd_card;
+};
+
+static struct imx_priv card_priv;
+
+static struct snd_soc_jack imx_hp_jack;
+
+static struct snd_soc_jack_pin imx_hp_jack_pins[] = {
+ {
+ .pin = "Headphone Jack",
+ .mask = SND_JACK_HEADPHONE,
+ },
+};
+
+static struct snd_soc_jack_gpio imx_hp_jack_gpio = {
+ .name = "headphone detect",
+ .report = SND_JACK_HEADPHONE,
+ .debounce_time = 250,
+ .invert = 1,
+};
+
+static int hpjack_status_check(void *data)
+{
+ struct imx_priv *priv = &card_priv;
+ struct platform_device *pdev = priv->pdev;
+ char *envp[3], *buf;
+ int hp_status, ret;
+
+ if (!gpio_is_valid(priv->hp_gpio))
+ return 0;
+
+ hp_status = gpio_get_value(priv->hp_gpio);
+ buf = kmalloc(32, GFP_ATOMIC);
+ if (!buf) {
+ dev_err(&pdev->dev, "%s kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (hp_status != priv->hp_active_low) {
+ snprintf(buf, 32, "STATE=%d", 2);
+ snd_soc_dapm_disable_pin(snd_soc_codec_get_dapm(priv->codec), "Ext Spk");
+ ret = imx_hp_jack_gpio.report;
+ snd_kctl_jack_report(priv->snd_card, priv->headphone_kctl, 1);
+ } else {
+ snprintf(buf, 32, "STATE=%d", 0);
+ snd_soc_dapm_enable_pin(snd_soc_codec_get_dapm(priv->codec), "Ext Spk");
+ ret = 0;
+ snd_kctl_jack_report(priv->snd_card, priv->headphone_kctl, 0);
+ }
+
+ envp[0] = "NAME=headphone";
+ envp[1] = buf;
+ envp[2] = NULL;
+ kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
+ kfree(buf);
+
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget imx_wm8958_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static const struct snd_soc_dapm_route imx_wm8958_dapm_route[] = {
+ {"Headphone Jack", NULL, "HPOUT1L"},
+ {"Headphone Jack", NULL, "HPOUT1R"},
+ {"Ext Spk", NULL, "SPKOUTLP"},
+ {"Ext Spk", NULL, "SPKOUTLN"},
+ {"Ext Spk", NULL, "SPKOUTRP"},
+ {"Ext Spk", NULL, "SPKOUTRN"},
+ {"IN1LN", NULL, "MICBIAS2"},
+};
+
+static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct snd_soc_card *card = rtd->card;
+ struct device *dev = card->dev;
+ struct imx_wm8958_data *data = snd_soc_card_get_drvdata(card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ unsigned int sample_rate = params_rate(params);
+ unsigned int pll_out;
+ int ret;
+
+ if (tx && params_width(params) == 24) {
+ if (sample_rate == 88200 || sample_rate == 96000 ||
+ sample_rate == 48000 || sample_rate == 44100) {
+ dev_err(dev, "Can't support sample rate %dHZ\n", sample_rate);
+ return -EINVAL;
+ }
+ } else if (!tx && params_width(params) == 24) {
+ if (sample_rate == 44100 || sample_rate == 48000) {
+ dev_err(dev, "Can't support sample rate %dHZ\n", sample_rate);
+ return -EINVAL;
+ }
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, data->dai.dai_fmt);
+ if (ret) {
+ dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, data->dai.dai_fmt);
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ data->clk_frequency = clk_get_rate(data->mclk);
+
+ if (!data->is_codec_master) {
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
+ if (ret) {
+ dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_FLL_SRC_MCLK1,
+ data->clk_frequency, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(dev, "failed to set codec sysclk: %d\n", ret);
+ return ret;
+ }
+ } else {
+ data->sr_stream[tx] = sample_rate;
+
+ if (params_width(params) == 24)
+ pll_out = data->sr_stream[tx] * 384;
+ else
+ pll_out = data->sr_stream[tx] * 256;
+
+ ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+ WM8994_FLL_SRC_MCLK1,
+ data->clk_frequency,
+ pll_out);
+ if (ret) {
+ dev_err(dev, "failed to set codec pll: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
+ pll_out, SND_SOC_CLOCK_OUT);
+ if (ret) {
+ dev_err(dev, "failed to set codec sysclk: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /*
+ * Set GPIO1 pin function to reserve, so that DAC1 and ADC1 using shared
+ * LRCLK from DACLRCK1.
+ */
+ snd_soc_update_bits(codec, WM8994_GPIO_1, 0x1f, 0x2);
+
+ /*
+ * Clear ADC_OSR128 bit to support slower SYSCLK, and support ADC sample
+ * rate 8K, 11.025K and 12K.
+ */
+ snd_soc_update_bits(codec, WM8994_OVERSAMPLING, 1<<1, 0);
+ return 0;
+}
+
+static int imx_hifi_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_wm8958_data *data = snd_soc_card_get_drvdata(card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+
+ if (data->is_codec_master &&
+ data->sr_stream[!tx] == 0 && data->sr_stream[tx]) {
+ /*
+ * We should connect AIF1CLK source to FLL after enable FLL, and
+ * disconnet AIF1CLK source to FLL before disable FLL, otherwise
+ * FLL worked abnormal.
+ */
+ snd_soc_dai_set_sysclk(codec_dai, WM8994_FLL_SRC_MCLK1,
+ data->clk_frequency, SND_SOC_CLOCK_OUT);
+
+ /* Disable FLL1 after all stream finished. */
+ snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, 0, 0);
+ }
+
+ data->sr_stream[tx] = 0;
+
+ return 0;
+}
+
+static u32 imx_wm8958_adc_rates[] = {
+ 8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 44100, 48000
+};
+
+static u32 imx_wm8958_dac_rates[] = {
+ 8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 44100, 48000, 88200, 96000
+};
+
+static struct snd_pcm_hw_constraint_list imx_wm8958_adc_rate_constraints = {
+ .count = ARRAY_SIZE(imx_wm8958_adc_rates),
+ .list = imx_wm8958_adc_rates,
+};
+
+static struct snd_pcm_hw_constraint_list imx_wm8958_dac_rate_constraints = {
+ .count = ARRAY_SIZE(imx_wm8958_dac_rates),
+ .list = imx_wm8958_dac_rates,
+};
+
+static int imx_hifi_startup(struct snd_pcm_substream *substream)
+{
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ int ret = 0;
+
+ if (!tx)
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &imx_wm8958_adc_rate_constraints);
+ else
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &imx_wm8958_dac_rate_constraints);
+ return ret;
+}
+
+static struct snd_soc_ops imx_hifi_ops = {
+ .hw_params = imx_hifi_hw_params,
+ .hw_free = imx_hifi_hw_free,
+ .startup = imx_hifi_startup,
+};
+
+static int imx_wm8958_gpio_init(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd = list_first_entry(
+ &card->rtd_list, struct snd_soc_pcm_runtime, list);
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct imx_priv *priv = &card_priv;
+ int ret;
+ priv->codec = codec;
+
+ if (gpio_is_valid(priv->hp_gpio)) {
+ imx_hp_jack_gpio.gpio = priv->hp_gpio;
+ imx_hp_jack_gpio.jack_status_check = hpjack_status_check;
+
+ ret = snd_soc_card_jack_new(card, "Headphone Jack",
+ SND_JACK_HEADPHONE, &imx_hp_jack,
+ imx_hp_jack_pins, ARRAY_SIZE(imx_hp_jack_pins));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_jack_add_gpios(&imx_hp_jack, 1,
+ &imx_hp_jack_gpio);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static ssize_t show_headphone(struct device_driver *dev, char *buf)
+{
+ struct imx_priv *priv = &card_priv;
+ int hp_status;
+
+ if (!gpio_is_valid(priv->hp_gpio)) {
+ strcpy(buf, "no detect gpio connected\n");
+ return strlen(buf);
+ }
+
+ /* Check if headphone is plugged in */
+ hp_status = gpio_get_value(priv->hp_gpio);
+
+ if (hp_status != priv->hp_active_low)
+ strcpy(buf, "headphone\n");
+ else
+ strcpy(buf, "speaker\n");
+
+ return strlen(buf);
+}
+
+static DRIVER_ATTR(headphone, S_IRUGO | S_IWUSR, show_headphone, NULL);
+
+static int imx_wm8958_set_bias_level(struct snd_soc_card *card,
+ struct snd_soc_dapm_context *dapm,
+ enum snd_soc_bias_level level)
+{
+ struct snd_soc_pcm_runtime *rtd = list_first_entry(
+ &card->rtd_list, struct snd_soc_pcm_runtime, list);
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct imx_wm8958_data *data = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ if (dapm->dev != codec_dai->dev)
+ return 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ if (card->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ if (!IS_ERR(data->mclk)) {
+ ret = clk_prepare_enable(data->mclk);
+ if (ret) {
+ dev_err(card->dev,
+ "Failed to enable MCLK: %d\n",
+ ret);
+ return ret;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int imx_wm8958_set_bias_level_post(struct snd_soc_card *card,
+ struct snd_soc_dapm_context *dapm,
+ enum snd_soc_bias_level level)
+{
+ struct snd_soc_pcm_runtime *rtd = list_first_entry(
+ &card->rtd_list, struct snd_soc_pcm_runtime, list);
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct imx_wm8958_data *data = snd_soc_card_get_drvdata(card);
+
+ if (dapm->dev != codec_dai->dev)
+ return 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_OFF:
+ if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+ if (!IS_ERR(data->mclk))
+ clk_disable_unprepare(data->mclk);
+ break;
+ default:
+ break;
+ }
+
+ card->dapm.bias_level = level;
+
+ return 0;
+}
+
+static int of_parse_gpr(struct platform_device *pdev,
+ struct imx_wm8958_data *data)
+{
+ int ret;
+ struct of_phandle_args args;
+
+ if (of_device_is_compatible(pdev->dev.of_node,
+ "fsl,imx7d-12x12-lpddr3-arm2-wm8958"))
+ return 0;
+
+ ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
+ "gpr", 3, 0, &args);
+ if (ret) {
+ dev_warn(&pdev->dev, "failed to get gpr property\n");
+ return ret;
+ }
+
+ data->gpr = syscon_node_to_regmap(args.np);
+ if (IS_ERR(data->gpr)) {
+ ret = PTR_ERR(data->gpr);
+ dev_err(&pdev->dev, "failed to get gpr regmap\n");
+ return ret;
+ }
+
+ regmap_update_bits(data->gpr, args.args[0], args.args[1],
+ args.args[2]);
+
+ return 0;
+}
+
+static int imx_wm8958_probe(struct platform_device *pdev)
+{
+ struct device_node *cpu_np, *codec_np = NULL;
+ struct device_node *np = pdev->dev.of_node;
+ struct platform_device *cpu_pdev;
+ struct imx_priv *priv = &card_priv;
+ struct i2c_client *codec_dev;
+ struct imx_wm8958_data *data;
+ int ret;
+
+ priv->pdev = pdev;
+
+ cpu_np = of_parse_phandle(np, "cpu-dai", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ codec_np = of_parse_phandle(np, "audio-codec", 0);
+ if (!codec_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ cpu_pdev = of_find_device_by_node(cpu_np);
+ if (!cpu_pdev) {
+ dev_err(&pdev->dev, "failed to find SAI platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ codec_dev = of_find_i2c_device_by_node(codec_np);
+ if (!codec_dev || !codec_dev->dev.driver) {
+ dev_err(&pdev->dev, "failed to find codec platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = of_parse_gpr(pdev, data);
+ if (ret)
+ goto fail;
+
+ if (of_property_read_bool(np, "codec-master")) {
+ data->dai.dai_fmt = SND_SOC_DAIFMT_CBM_CFM;
+ data->is_codec_master = true;
+ } else
+ data->dai.dai_fmt = SND_SOC_DAIFMT_CBS_CFS;
+
+ data->mclk = devm_clk_get(&codec_dev->dev, "mclk1");
+ if (IS_ERR(data->mclk)) {
+ ret = PTR_ERR(data->mclk);
+ dev_err(&pdev->dev, "failed to get codec clk: %d\n", ret);
+ goto fail;
+ }
+
+ priv->hp_gpio = of_get_named_gpio_flags(np, "hp-det-gpios", 0,
+ (enum of_gpio_flags *)&priv->hp_active_low);
+
+ data->dai.name = "HiFi";
+ data->dai.stream_name = "HiFi";
+ data->dai.codec_dai_name = "wm8994-aif1";
+ data->dai.codec_name = "wm8994-codec";
+ data->dai.cpu_dai_name = dev_name(&cpu_pdev->dev);
+ data->dai.platform_of_node = cpu_np;
+ data->dai.ops = &imx_hifi_ops;
+ data->dai.dai_fmt |= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF;
+ data->card.set_bias_level = imx_wm8958_set_bias_level;
+ data->card.set_bias_level_post = imx_wm8958_set_bias_level_post;
+ data->card.owner = THIS_MODULE;
+
+ data->card.dev = &pdev->dev;
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto fail;
+
+ data->card.num_links = 1;
+ data->card.dai_link = &data->dai;
+ data->card.dapm_widgets = imx_wm8958_dapm_widgets;
+ data->card.num_dapm_widgets = ARRAY_SIZE(imx_wm8958_dapm_widgets);
+ data->card.dapm_routes = imx_wm8958_dapm_route;
+ data->card.num_dapm_routes = ARRAY_SIZE(imx_wm8958_dapm_route);
+ platform_set_drvdata(pdev, &data->card);
+ snd_soc_card_set_drvdata(&data->card, data);
+
+ ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto fail;
+ }
+
+ priv->snd_card = data->card.snd_card;
+
+ priv->headphone_kctl = snd_kctl_jack_new("Headphone", NULL);
+ ret = snd_ctl_add(data->card.snd_card, priv->headphone_kctl);
+ if (ret)
+ goto fail;
+
+ ret = imx_wm8958_gpio_init(&data->card);
+
+ if (gpio_is_valid(priv->hp_gpio)) {
+ ret = driver_create_file(pdev->dev.driver,
+ &driver_attr_headphone);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "create hp attr failed (%d)\n", ret);
+ goto fail;
+ }
+ }
+
+fail:
+ if (cpu_np)
+ of_node_put(cpu_np);
+ if (codec_np)
+ of_node_put(codec_np);
+
+ return ret;
+}
+
+static int imx_wm8958_remove(struct platform_device *pdev)
+{
+ driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
+ return 0;
+}
+
+static const struct of_device_id imx_wm8958_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-wm8958", },
+ { .compatible = "fsl,imx7d-12x12-lpddr3-arm2-wm8958", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_wm8958_dt_ids);
+
+static struct platform_driver imx_wm8958_driver = {
+ .driver = {
+ .name = "imx-wm8958",
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = imx_wm8958_dt_ids,
+ },
+ .probe = imx_wm8958_probe,
+ .remove = imx_wm8958_remove,
+};
+module_platform_driver(imx_wm8958_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale i.MX WM8958 ASoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-wm8958");
diff --git a/sound/soc/fsl/imx-wm8960.c b/sound/soc/fsl/imx-wm8960.c
new file mode 100644
index 000000000000..8dbf997d3d8c
--- /dev/null
+++ b/sound/soc/fsl/imx-wm8960.c
@@ -0,0 +1,675 @@
+/*
+ * 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/module.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/control.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/mfd/syscon.h>
+#include "../codecs/wm8960.h"
+#include "fsl_sai.h"
+
+struct imx_wm8960_data {
+ struct snd_soc_card card;
+ struct clk *codec_clk;
+ unsigned int clk_frequency;
+ bool is_codec_master;
+ bool is_stream_in_use[2];
+ bool is_stream_opened[2];
+ struct regmap *gpr;
+ unsigned int hp_det[2];
+ u32 asrc_rate;
+ u32 asrc_format;
+};
+
+struct imx_priv {
+ enum of_gpio_flags hp_active_low;
+ enum of_gpio_flags mic_active_low;
+ bool is_headset_jack;
+ struct snd_kcontrol *headphone_kctl;
+ struct platform_device *pdev;
+ struct platform_device *asrc_pdev;
+ struct snd_card *snd_card;
+};
+
+static struct imx_priv card_priv;
+
+static struct snd_soc_jack imx_hp_jack;
+static struct snd_soc_jack_pin imx_hp_jack_pin = {
+ .pin = "Headphone Jack",
+ .mask = SND_JACK_HEADPHONE,
+};
+static struct snd_soc_jack_gpio imx_hp_jack_gpio = {
+ .name = "headphone detect",
+ .report = SND_JACK_HEADPHONE,
+ .debounce_time = 250,
+ .invert = 0,
+};
+
+static struct snd_soc_jack imx_mic_jack;
+static struct snd_soc_jack_pin imx_mic_jack_pins = {
+ .pin = "Mic Jack",
+ .mask = SND_JACK_MICROPHONE,
+};
+static struct snd_soc_jack_gpio imx_mic_jack_gpio = {
+ .name = "mic detect",
+ .report = SND_JACK_MICROPHONE,
+ .debounce_time = 250,
+ .invert = 0,
+};
+
+static int hp_jack_status_check(void *data)
+{
+ struct imx_priv *priv = &card_priv;
+ struct snd_soc_jack *jack = data;
+ struct snd_soc_dapm_context *dapm = &jack->card->dapm;
+ int hp_status, ret;
+
+ hp_status = gpio_get_value(imx_hp_jack_gpio.gpio);
+
+ if (hp_status != priv->hp_active_low) {
+ snd_soc_dapm_disable_pin(dapm, "Ext Spk");
+ if (priv->is_headset_jack) {
+ snd_soc_dapm_enable_pin(dapm, "Mic Jack");
+ snd_soc_dapm_disable_pin(dapm, "Main MIC");
+ }
+ ret = imx_hp_jack_gpio.report;
+ snd_kctl_jack_report(priv->snd_card, priv->headphone_kctl, 1);
+ } else {
+ snd_soc_dapm_enable_pin(dapm, "Ext Spk");
+ if (priv->is_headset_jack) {
+ snd_soc_dapm_disable_pin(dapm, "Mic Jack");
+ snd_soc_dapm_enable_pin(dapm, "Main MIC");
+ }
+ ret = 0;
+ snd_kctl_jack_report(priv->snd_card, priv->headphone_kctl, 0);
+ }
+
+ return ret;
+}
+
+static int mic_jack_status_check(void *data)
+{
+ struct imx_priv *priv = &card_priv;
+ struct snd_soc_jack *jack = data;
+ struct snd_soc_dapm_context *dapm = &jack->card->dapm;
+ int mic_status, ret;
+
+ mic_status = gpio_get_value(imx_mic_jack_gpio.gpio);
+
+ if (mic_status != priv->mic_active_low) {
+ snd_soc_dapm_disable_pin(dapm, "Main MIC");
+ ret = imx_mic_jack_gpio.report;
+ } else {
+ snd_soc_dapm_enable_pin(dapm, "Main MIC");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget imx_wm8960_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_MIC("Main MIC", NULL),
+};
+
+static int imx_wm8960_jack_init(struct snd_soc_card *card,
+ struct snd_soc_jack *jack, struct snd_soc_jack_pin *pin,
+ struct snd_soc_jack_gpio *gpio)
+{
+ int ret;
+
+ ret = snd_soc_card_jack_new(card, pin->pin, pin->mask, jack, pin, 1);
+ if (ret) {
+ return ret;
+ }
+
+ ret = snd_soc_jack_add_gpios(jack, 1, gpio);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static ssize_t show_headphone(struct device_driver *dev, char *buf)
+{
+ struct imx_priv *priv = &card_priv;
+ int hp_status;
+
+ /* Check if headphone is plugged in */
+ hp_status = gpio_get_value(imx_hp_jack_gpio.gpio);
+
+ if (hp_status != priv->hp_active_low)
+ strcpy(buf, "Headphone\n");
+ else
+ strcpy(buf, "Speaker\n");
+
+ return strlen(buf);
+}
+
+static ssize_t show_micphone(struct device_driver *dev, char *buf)
+{
+ struct imx_priv *priv = &card_priv;
+ int mic_status;
+
+ /* Check if headphone is plugged in */
+ mic_status = gpio_get_value(imx_mic_jack_gpio.gpio);
+
+ if (mic_status != priv->mic_active_low)
+ strcpy(buf, "Mic Jack\n");
+ else
+ strcpy(buf, "Main MIC\n");
+
+ return strlen(buf);
+}
+static DRIVER_ATTR(headphone, S_IRUGO | S_IWUSR, show_headphone, NULL);
+static DRIVER_ATTR(micphone, S_IRUGO | S_IWUSR, show_micphone, NULL);
+
+static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_wm8960_data *data = snd_soc_card_get_drvdata(card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ struct device *dev = card->dev;
+ unsigned int sample_rate = params_rate(params);
+ unsigned int pll_out;
+ unsigned int fmt;
+ int ret = 0;
+
+ data->is_stream_in_use[tx] = true;
+
+ if (data->is_stream_in_use[!tx])
+ return 0;
+
+ if (data->is_codec_master)
+ fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+ else
+ fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
+ return ret;
+ }
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+ if (ret) {
+ dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ if (!data->is_codec_master) {
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 2,
+ params_physical_width(params));
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
+ if (ret) {
+ dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+ return ret;
+ }
+ return 0;
+ } else {
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+ return ret;
+ }
+ }
+
+ data->clk_frequency = clk_get_rate(data->codec_clk);
+
+ /* Set codec pll */
+ if (params_width(params) == 24)
+ pll_out = sample_rate * 768;
+ else
+ pll_out = sample_rate * 512;
+
+ ret = snd_soc_dai_set_pll(codec_dai, WM8960_SYSCLK_AUTO, 0, data->clk_frequency, pll_out);
+ if (ret)
+ return ret;
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8960_SYSCLK_AUTO, pll_out, 0);
+
+ return ret;
+}
+
+static int imx_hifi_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_wm8960_data *data = snd_soc_card_get_drvdata(card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ struct device *dev = card->dev;
+ int ret;
+
+ data->is_stream_in_use[tx] = false;
+
+ if (data->is_codec_master && !data->is_stream_in_use[!tx]) {
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF);
+ if (ret)
+ dev_warn(dev, "failed to set codec dai fmt: %d\n", ret);
+ }
+
+ return 0;
+}
+
+static u32 imx_wm8960_rates[] = { 8000, 16000, 32000, 48000 };
+static struct snd_pcm_hw_constraint_list imx_wm8960_rate_constraints = {
+ .count = ARRAY_SIZE(imx_wm8960_rates),
+ .list = imx_wm8960_rates,
+};
+
+static int imx_hifi_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_wm8960_data *data = snd_soc_card_get_drvdata(card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
+ int ret = 0;
+
+ data->is_stream_opened[tx] = true;
+ if (data->is_stream_opened[tx] != sai->is_stream_opened[tx] ||
+ data->is_stream_opened[!tx] != sai->is_stream_opened[!tx]) {
+ data->is_stream_opened[tx] = false;
+ return -EBUSY;
+ }
+
+ if (!data->is_codec_master) {
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &imx_wm8960_rate_constraints);
+ if (ret)
+ return ret;
+ }
+
+ ret = clk_prepare_enable(data->codec_clk);
+ if (ret) {
+ dev_err(card->dev, "Failed to enable MCLK: %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void imx_hifi_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_wm8960_data *data = snd_soc_card_get_drvdata(card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+
+ clk_disable_unprepare(data->codec_clk);
+
+ data->is_stream_opened[tx] = false;
+}
+
+static struct snd_soc_ops imx_hifi_ops = {
+ .hw_params = imx_hifi_hw_params,
+ .hw_free = imx_hifi_hw_free,
+ .startup = imx_hifi_startup,
+ .shutdown = imx_hifi_shutdown,
+};
+
+static int imx_wm8960_late_probe(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd = list_first_entry(
+ &card->rtd_list, struct snd_soc_pcm_runtime, list);
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct imx_wm8960_data *data = snd_soc_card_get_drvdata(card);
+
+ /*
+ * codec ADCLRC pin configured as GPIO, DACLRC pin is used as a frame
+ * clock for ADCs and DACs
+ */
+ snd_soc_update_bits(codec, WM8960_IFACE2, 1<<6, 1<<6);
+
+ /* GPIO1 used as headphone detect output */
+ snd_soc_update_bits(codec, WM8960_ADDCTL4, 7<<4, 3<<4);
+
+ /* Enable headphone jack detect */
+ snd_soc_update_bits(codec, WM8960_ADDCTL2, 1<<6, 1<<6);
+ snd_soc_update_bits(codec, WM8960_ADDCTL2, 1<<5, data->hp_det[1]<<5);
+ snd_soc_update_bits(codec, WM8960_ADDCTL4, 3<<2, data->hp_det[0]<<2);
+ snd_soc_update_bits(codec, WM8960_ADDCTL1, 3, 3);
+
+ return 0;
+}
+
+static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct imx_wm8960_data *data = snd_soc_card_get_drvdata(card);
+ struct imx_priv *priv = &card_priv;
+ struct snd_interval *rate;
+ struct snd_mask *mask;
+
+ if (!priv->asrc_pdev)
+ return -EINVAL;
+
+ rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ rate->max = rate->min = data->asrc_rate;
+
+ mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ snd_mask_none(mask);
+ snd_mask_set(mask, data->asrc_format);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link imx_wm8960_dai[] = {
+ {
+ .name = "HiFi",
+ .stream_name = "HiFi",
+ .codec_dai_name = "wm8960-hifi",
+ .ops = &imx_hifi_ops,
+ },
+ {
+ .name = "HiFi-ASRC-FE",
+ .stream_name = "HiFi-ASRC-FE",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .dynamic = 1,
+ .ignore_pmdown_time = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .dpcm_merged_chan = 1,
+ },
+ {
+ .name = "HiFi-ASRC-BE",
+ .stream_name = "HiFi-ASRC-BE",
+ .codec_dai_name = "wm8960-hifi",
+ .platform_name = "snd-soc-dummy",
+ .no_pcm = 1,
+ .ignore_pmdown_time = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ops = &imx_hifi_ops,
+ .be_hw_params_fixup = be_hw_params_fixup,
+ },
+};
+
+static int of_parse_gpr(struct platform_device *pdev,
+ struct imx_wm8960_data *data)
+{
+ int ret;
+ struct of_phandle_args args;
+
+ if (of_device_is_compatible(pdev->dev.of_node,
+ "fsl,imx7d-evk-wm8960"))
+ return 0;
+
+ ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
+ "gpr", 3, 0, &args);
+ if (ret) {
+ dev_warn(&pdev->dev, "failed to get gpr property\n");
+ return ret;
+ }
+
+ data->gpr = syscon_node_to_regmap(args.np);
+ if (IS_ERR(data->gpr)) {
+ ret = PTR_ERR(data->gpr);
+ dev_err(&pdev->dev, "failed to get gpr regmap\n");
+ return ret;
+ }
+
+ regmap_update_bits(data->gpr, args.args[0], args.args[1],
+ args.args[2]);
+
+ return 0;
+}
+
+static int imx_wm8960_probe(struct platform_device *pdev)
+{
+ struct device_node *cpu_np, *codec_np = NULL;
+ struct platform_device *cpu_pdev;
+ struct imx_priv *priv = &card_priv;
+ struct i2c_client *codec_dev;
+ struct imx_wm8960_data *data;
+ struct platform_device *asrc_pdev = NULL;
+ struct device_node *asrc_np;
+ u32 width;
+ int ret;
+
+ priv->pdev = pdev;
+
+ cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
+ if (!codec_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ cpu_pdev = of_find_device_by_node(cpu_np);
+ if (!cpu_pdev) {
+ dev_err(&pdev->dev, "failed to find SAI platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ codec_dev = of_find_i2c_device_by_node(codec_np);
+ if (!codec_dev || !codec_dev->dev.driver) {
+ dev_err(&pdev->dev, "failed to find codec platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (of_property_read_bool(pdev->dev.of_node, "codec-master"))
+ data->is_codec_master = true;
+
+ data->codec_clk = devm_clk_get(&codec_dev->dev, "mclk");
+ if (IS_ERR(data->codec_clk)) {
+ ret = PTR_ERR(data->codec_clk);
+ dev_err(&pdev->dev, "failed to get codec clk: %d\n", ret);
+ goto fail;
+ }
+
+ ret = of_parse_gpr(pdev, data);
+ if (ret)
+ goto fail;
+
+ of_property_read_u32_array(pdev->dev.of_node, "hp-det", data->hp_det, 2);
+
+ asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0);
+ if (asrc_np) {
+ asrc_pdev = of_find_device_by_node(asrc_np);
+ priv->asrc_pdev = asrc_pdev;
+ }
+
+ data->card.dai_link = imx_wm8960_dai;
+
+ imx_wm8960_dai[0].codec_of_node = codec_np;
+ imx_wm8960_dai[0].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ imx_wm8960_dai[0].platform_of_node = cpu_np;
+
+ if (!asrc_pdev) {
+ data->card.num_links = 1;
+ } else {
+ imx_wm8960_dai[1].cpu_of_node = asrc_np;
+ imx_wm8960_dai[1].platform_of_node = asrc_np;
+ imx_wm8960_dai[2].codec_of_node = codec_np;
+ imx_wm8960_dai[2].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ data->card.num_links = 3;
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
+ &data->asrc_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (width == 24)
+ data->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+ else
+ data->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+ }
+
+ data->card.dev = &pdev->dev;
+ data->card.owner = THIS_MODULE;
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto fail;
+ data->card.dapm_widgets = imx_wm8960_dapm_widgets;
+ data->card.num_dapm_widgets = ARRAY_SIZE(imx_wm8960_dapm_widgets);
+
+ ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
+ if (ret)
+ goto fail;
+
+ data->card.late_probe = imx_wm8960_late_probe;
+
+ platform_set_drvdata(pdev, &data->card);
+ snd_soc_card_set_drvdata(&data->card, data);
+ ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto fail;
+ }
+
+ priv->snd_card = data->card.snd_card;
+
+ imx_hp_jack_gpio.gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+ "hp-det-gpios", 0, &priv->hp_active_low);
+
+ imx_mic_jack_gpio.gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+ "mic-det-gpios", 0, &priv->mic_active_low);
+
+ if (gpio_is_valid(imx_hp_jack_gpio.gpio) &&
+ gpio_is_valid(imx_mic_jack_gpio.gpio) &&
+ imx_hp_jack_gpio.gpio == imx_mic_jack_gpio.gpio)
+ priv->is_headset_jack = true;
+
+ if (gpio_is_valid(imx_hp_jack_gpio.gpio)) {
+ priv->headphone_kctl = snd_kctl_jack_new("Headphone", NULL);
+ ret = snd_ctl_add(priv->snd_card, priv->headphone_kctl);
+ if (ret)
+ dev_warn(&pdev->dev, "failed to create headphone jack kctl\n");
+
+ if (priv->is_headset_jack) {
+ imx_hp_jack_pin.mask |= SND_JACK_MICROPHONE;
+ imx_hp_jack_gpio.report |= SND_JACK_MICROPHONE;
+ }
+ imx_hp_jack_gpio.jack_status_check = hp_jack_status_check;
+ imx_hp_jack_gpio.data = &imx_hp_jack;
+ ret = imx_wm8960_jack_init(&data->card, &imx_hp_jack,
+ &imx_hp_jack_pin, &imx_hp_jack_gpio);
+ if (ret) {
+ dev_warn(&pdev->dev, "hp jack init failed (%d)\n", ret);
+ goto out;
+ }
+
+ ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
+ if (ret)
+ dev_warn(&pdev->dev, "create hp attr failed (%d)\n", ret);
+ }
+
+ if (gpio_is_valid(imx_mic_jack_gpio.gpio)) {
+ if (!priv->is_headset_jack) {
+ imx_mic_jack_gpio.jack_status_check = mic_jack_status_check;
+ imx_mic_jack_gpio.data = &imx_mic_jack;
+ ret = imx_wm8960_jack_init(&data->card, &imx_mic_jack,
+ &imx_mic_jack_pins, &imx_mic_jack_gpio);
+ if (ret) {
+ dev_warn(&pdev->dev, "mic jack init failed (%d)\n", ret);
+ goto out;
+ }
+ }
+ ret = driver_create_file(pdev->dev.driver, &driver_attr_micphone);
+ if (ret)
+ dev_warn(&pdev->dev, "create mic attr failed (%d)\n", ret);
+ }
+
+out:
+ ret = 0;
+fail:
+ if (cpu_np)
+ of_node_put(cpu_np);
+ if (codec_np)
+ of_node_put(codec_np);
+
+ return ret;
+}
+
+static int imx_wm8960_remove(struct platform_device *pdev)
+{
+ driver_remove_file(pdev->dev.driver, &driver_attr_micphone);
+ driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
+
+ return 0;
+}
+
+static const struct of_device_id imx_wm8960_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-wm8960", },
+ { .compatible = "fsl,imx7d-evk-wm8960" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_wm8960_dt_ids);
+
+static struct platform_driver imx_wm8960_driver = {
+ .driver = {
+ .name = "imx-wm8960",
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = imx_wm8960_dt_ids,
+ },
+ .probe = imx_wm8960_probe,
+ .remove = imx_wm8960_remove,
+};
+module_platform_driver(imx_wm8960_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale i.MX WM8960 ASoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-wm8960");
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index 201a70d1027a..a8ef512c4f37 100644
--- a/sound/soc/fsl/imx-wm8962.c
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -1,9 +1,10 @@
/*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
*
* Based on imx-sgtl5000.c
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2012 Linaro Ltd.
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ * 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
@@ -16,9 +17,13 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/i2c.h>
+#include <linux/of_gpio.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
#include <linux/clk.h>
#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/control.h>
#include <sound/pcm_params.h>
#include <sound/soc-dapm.h>
#include <linux/pinctrl/consumer.h>
@@ -29,19 +34,151 @@
#define DAI_NAME_SIZE 32
struct imx_wm8962_data {
- struct snd_soc_dai_link dai;
+ struct snd_soc_dai_link dai[3];
struct snd_soc_card card;
char codec_dai_name[DAI_NAME_SIZE];
char platform_name[DAI_NAME_SIZE];
- struct clk *codec_clk;
unsigned int clk_frequency;
+ bool is_codec_master;
};
struct imx_priv {
+ int hp_gpio;
+ int hp_active_low;
+ int mic_gpio;
+ int mic_active_low;
+ bool amic_mono;
+ bool dmic_mono;
+ struct snd_soc_codec *codec;
struct platform_device *pdev;
+ struct snd_pcm_substream *first_stream;
+ struct snd_pcm_substream *second_stream;
+ struct snd_kcontrol *headphone_kctl;
+ struct snd_card *snd_card;
+ struct platform_device *asrc_pdev;
+ u32 asrc_rate;
+ u32 asrc_format;
};
static struct imx_priv card_priv;
+#ifdef CONFIG_SND_SOC_IMX_WM8962_ANDROID
+static int sample_rate = 44100;
+static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE;
+#endif
+
+static struct snd_soc_jack imx_hp_jack;
+static struct snd_soc_jack_pin imx_hp_jack_pins[] = {
+ {
+ .pin = "Headphone Jack",
+ .mask = SND_JACK_HEADPHONE,
+ },
+};
+static struct snd_soc_jack_gpio imx_hp_jack_gpio = {
+ .name = "headphone detect",
+ .report = SND_JACK_HEADPHONE,
+ .debounce_time = 250,
+ .invert = 0,
+};
+
+static struct snd_soc_jack imx_mic_jack;
+static struct snd_soc_jack_pin imx_mic_jack_pins[] = {
+ {
+ .pin = "AMIC",
+ .mask = SND_JACK_MICROPHONE,
+ },
+};
+static struct snd_soc_jack_gpio imx_mic_jack_gpio = {
+ .name = "microphone detect",
+ .report = SND_JACK_MICROPHONE,
+ .debounce_time = 250,
+ .invert = 0,
+};
+
+static int hpjack_status_check(void *data)
+{
+ struct imx_priv *priv = &card_priv;
+ struct platform_device *pdev = priv->pdev;
+ char *envp[3], *buf;
+ int hp_status, ret;
+
+ if (!gpio_is_valid(priv->hp_gpio))
+ return 0;
+
+ hp_status = gpio_get_value(priv->hp_gpio) ? 1 : 0;
+
+ buf = kmalloc(32, GFP_ATOMIC);
+ if (!buf) {
+ dev_err(&pdev->dev, "%s kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (hp_status != priv->hp_active_low) {
+ snprintf(buf, 32, "STATE=%d", 2);
+ snd_soc_dapm_disable_pin(snd_soc_codec_get_dapm(priv->codec), "Ext Spk");
+ ret = imx_hp_jack_gpio.report;
+ snd_kctl_jack_report(priv->snd_card, priv->headphone_kctl, 1);
+ } else {
+ snprintf(buf, 32, "STATE=%d", 0);
+ snd_soc_dapm_enable_pin(snd_soc_codec_get_dapm(priv->codec), "Ext Spk");
+ ret = 0;
+ snd_kctl_jack_report(priv->snd_card, priv->headphone_kctl, 0);
+ }
+
+ envp[0] = "NAME=headphone";
+ envp[1] = buf;
+ envp[2] = NULL;
+ kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
+ kfree(buf);
+
+ return ret;
+}
+
+static int micjack_status_check(void *data)
+{
+ struct imx_priv *priv = &card_priv;
+ struct platform_device *pdev = priv->pdev;
+ char *envp[3], *buf;
+ int mic_status, ret;
+
+ if (!gpio_is_valid(priv->mic_gpio))
+ return 0;
+
+ mic_status = gpio_get_value(priv->mic_gpio) ? 1 : 0;
+
+ if ((mic_status != priv->mic_active_low && priv->amic_mono)
+ || (mic_status == priv->mic_active_low && priv->dmic_mono))
+ snd_soc_update_bits(priv->codec, WM8962_THREED1,
+ WM8962_ADC_MONOMIX_MASK, WM8962_ADC_MONOMIX);
+ else
+ snd_soc_update_bits(priv->codec, WM8962_THREED1,
+ WM8962_ADC_MONOMIX_MASK, 0);
+
+ buf = kmalloc(32, GFP_ATOMIC);
+ if (!buf) {
+ dev_err(&pdev->dev, "%s kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (mic_status != priv->mic_active_low) {
+ snprintf(buf, 32, "STATE=%d", 2);
+ snd_soc_dapm_disable_pin(snd_soc_codec_get_dapm(priv->codec), "DMIC");
+ ret = imx_mic_jack_gpio.report;
+ } else {
+ snprintf(buf, 32, "STATE=%d", 0);
+ snd_soc_dapm_enable_pin(snd_soc_codec_get_dapm(priv->codec), "DMIC");
+ ret = 0;
+ }
+
+ envp[0] = "NAME=microphone";
+ envp[1] = buf;
+ envp[2] = NULL;
+ kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
+ kfree(buf);
+
+ return ret;
+}
+
+
static const struct snd_soc_dapm_widget imx_wm8962_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_SPK("Ext Spk", NULL),
@@ -49,19 +186,64 @@ static const struct snd_soc_dapm_widget imx_wm8962_dapm_widgets[] = {
SND_SOC_DAPM_MIC("DMIC", NULL),
};
-static int sample_rate = 44100;
-static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE;
+static u32 imx_wm8962_rates[] = {32000, 48000, 96000};
+static struct snd_pcm_hw_constraint_list imx_wm8962_rate_constraints = {
+ .count = ARRAY_SIZE(imx_wm8962_rates),
+ .list = imx_wm8962_rates,
+};
+
+static int imx_hifi_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
+ int ret;
+ if (!data->is_codec_master) {
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &imx_wm8962_rate_constraints);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_SND_SOC_IMX_WM8962_ANDROID
static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct imx_priv *priv = &card_priv;
+ struct device *dev = &priv->pdev->dev;
+ u32 dai_format;
+ int ret = 0;
+
sample_rate = params_rate(params);
sample_format = params_format(params);
+ if (data->is_codec_master)
+ dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+ else
+ dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
+ if (ret) {
+ dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
+ return ret;
+ }
+
return 0;
}
static struct snd_soc_ops imx_hifi_ops = {
+ .startup = imx_hifi_startup,
.hw_params = imx_hifi_hw_params,
};
@@ -69,23 +251,21 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_pcm_runtime *rtd;
- struct snd_soc_dai *codec_dai;
+ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
struct imx_priv *priv = &card_priv;
struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
struct device *dev = &priv->pdev->dev;
unsigned int pll_out;
int ret;
- rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
- codec_dai = rtd->codec_dai;
if (dapm->dev != codec_dai->dev)
return 0;
switch (level) {
case SND_SOC_BIAS_PREPARE:
if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
- if (sample_format == SNDRV_PCM_FORMAT_S24_LE)
+ if (sample_format == SNDRV_PCM_FORMAT_S24_LE
+ || sample_format == SNDRV_PCM_FORMAT_S20_3LE)
pll_out = sample_rate * 384;
else
pll_out = sample_rate * 256;
@@ -136,6 +316,210 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
return 0;
}
+#else
+
+static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct imx_priv *priv = &card_priv;
+ struct device *dev = &priv->pdev->dev;
+ struct snd_soc_card *card = platform_get_drvdata(priv->pdev);
+ struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
+ unsigned int sample_rate = params_rate(params);
+ snd_pcm_format_t sample_format = params_format(params);
+ u32 dai_format, pll_out;
+ int ret = 0;
+
+ if (!priv->first_stream) {
+ priv->first_stream = substream;
+ } else {
+ priv->second_stream = substream;
+
+ /* We suppose the two substream are using same params */
+ return 0;
+ }
+
+ if (data->is_codec_master)
+ dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+ else
+ dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
+ if (ret) {
+ dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ if (sample_format == SNDRV_PCM_FORMAT_S24_LE
+ || sample_format == SNDRV_PCM_FORMAT_S20_3LE)
+ pll_out = sample_rate * 384;
+ else
+ pll_out = sample_rate * 256;
+
+ ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, WM8962_FLL_MCLK,
+ data->clk_frequency, pll_out);
+ if (ret) {
+ dev_err(dev, "failed to start FLL: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_FLL,
+ pll_out, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(dev, "failed to set SYSCLK: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int imx_hifi_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct imx_priv *priv = &card_priv;
+ struct device *dev = &priv->pdev->dev;
+ int ret;
+
+ /* We don't need to handle anything if there's no substream running */
+ if (!priv->first_stream)
+ return 0;
+
+ if (priv->first_stream == substream)
+ priv->first_stream = priv->second_stream;
+ priv->second_stream = NULL;
+
+ if (!priv->first_stream) {
+ /*
+ * Continuously setting FLL would cause playback distortion.
+ * We can fix it just by mute codec after playback.
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
+
+ /*
+ * WM8962 doesn't allow us to continuously setting FLL,
+ * So we set MCLK as sysclk once, which'd remove the limitation.
+ */
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
+ 0, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(dev, "failed to switch away from FLL: %d\n", ret);
+ return ret;
+ }
+
+ /* Disable FLL and let codec do pm_runtime_put() */
+ ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
+ WM8962_FLL_MCLK, 0, 0);
+ if (ret < 0) {
+ dev_err(dev, "failed to stop FLL: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops imx_hifi_ops = {
+ .startup = imx_hifi_startup,
+ .hw_params = imx_hifi_hw_params,
+ .hw_free = imx_hifi_hw_free,
+};
+#endif /* CONFIG_SND_SOC_IMX_WM8962_ANDROID */
+
+static int imx_wm8962_gpio_init(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd = list_first_entry(
+ &card->rtd_list, struct snd_soc_pcm_runtime, list);
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct imx_priv *priv = &card_priv;
+
+ priv->codec = codec;
+
+ if (gpio_is_valid(priv->hp_gpio)) {
+ imx_hp_jack_gpio.gpio = priv->hp_gpio;
+ imx_hp_jack_gpio.jack_status_check = hpjack_status_check;
+
+ snd_soc_card_jack_new(card, "Headphone Jack",
+ SND_JACK_HEADPHONE, &imx_hp_jack,
+ imx_hp_jack_pins, ARRAY_SIZE(imx_hp_jack_pins));
+
+ snd_soc_jack_add_gpios(&imx_hp_jack, 1, &imx_hp_jack_gpio);
+ }
+
+ if (gpio_is_valid(priv->mic_gpio)) {
+ imx_mic_jack_gpio.gpio = priv->mic_gpio;
+ imx_mic_jack_gpio.jack_status_check = micjack_status_check;
+
+ snd_soc_card_jack_new(card, "AMIC",
+ SND_JACK_MICROPHONE, &imx_mic_jack,
+ imx_mic_jack_pins, ARRAY_SIZE(imx_mic_jack_pins));
+
+ snd_soc_jack_add_gpios(&imx_mic_jack, 1, &imx_mic_jack_gpio);
+ } else if (priv->amic_mono || priv->dmic_mono) {
+ /*
+ * Permanent set monomix bit if only one microphone
+ * is present on the board while it needs monomix.
+ */
+ snd_soc_update_bits(priv->codec, WM8962_THREED1,
+ WM8962_ADC_MONOMIX_MASK, WM8962_ADC_MONOMIX);
+ }
+
+ return 0;
+}
+
+static ssize_t show_headphone(struct device_driver *dev, char *buf)
+{
+ struct imx_priv *priv = &card_priv;
+ int hp_status;
+
+ if (!gpio_is_valid(priv->hp_gpio)) {
+ strcpy(buf, "no detect gpio connected\n");
+ return strlen(buf);
+ }
+
+ /* Check if headphone is plugged in */
+ hp_status = gpio_get_value(priv->hp_gpio) ? 1 : 0;
+
+ if (hp_status != priv->hp_active_low)
+ strcpy(buf, "headphone\n");
+ else
+ strcpy(buf, "speaker\n");
+
+ return strlen(buf);
+}
+
+static DRIVER_ATTR(headphone, S_IRUGO | S_IWUSR, show_headphone, NULL);
+
+static ssize_t show_mic(struct device_driver *dev, char *buf)
+{
+ struct imx_priv *priv = &card_priv;
+ int mic_status;
+
+ if (!gpio_is_valid(priv->mic_gpio)) {
+ strcpy(buf, "no detect gpio connected\n");
+ return strlen(buf);
+ }
+
+ /* Check if analog microphone is plugged in */
+ mic_status = gpio_get_value(priv->mic_gpio) ? 1 : 0;
+
+ if (mic_status != priv->mic_active_low)
+ strcpy(buf, "amic\n");
+ else
+ strcpy(buf, "dmic\n");
+
+ return strlen(buf);
+}
+
+static DRIVER_ATTR(microphone, S_IRUGO | S_IWUSR, show_mic, NULL);
+
static int imx_wm8962_late_probe(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd;
@@ -155,28 +539,71 @@ static int imx_wm8962_late_probe(struct snd_soc_card *card)
return ret;
}
+static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params) {
+ struct imx_priv *priv = &card_priv;
+ struct snd_interval *rate;
+ struct snd_mask *mask;
+
+ if (!priv->asrc_pdev)
+ return -EINVAL;
+
+ rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ rate->max = rate->min = priv->asrc_rate;
+
+ mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ snd_mask_none(mask);
+ snd_mask_set(mask, priv->asrc_format);
+
+ return 0;
+}
+
static int imx_wm8962_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct device_node *ssi_np, *codec_np;
- struct platform_device *ssi_pdev;
+ struct device_node *cpu_np, *codec_np = NULL;
+ struct platform_device *cpu_pdev;
struct imx_priv *priv = &card_priv;
struct i2c_client *codec_dev;
struct imx_wm8962_data *data;
- int int_port, ext_port;
+ struct clk *codec_clk = NULL;
+ int int_port, ext_port, tmp_port;
int ret;
+ struct platform_device *asrc_pdev = NULL;
+ struct device_node *asrc_np;
+ u32 width;
priv->pdev = pdev;
+ priv->asrc_pdev = NULL;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (of_property_read_bool(pdev->dev.of_node, "codec-master"))
+ data->is_codec_master = true;
+
+ cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (!strstr(cpu_np->name, "ssi"))
+ goto audmux_bypass;
ret = of_property_read_u32(np, "mux-int-port", &int_port);
if (ret) {
dev_err(&pdev->dev, "mux-int-port missing or invalid\n");
- return ret;
+ goto fail;
}
ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
if (ret) {
dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");
- return ret;
+ goto fail;
}
/*
@@ -185,35 +612,41 @@ static int imx_wm8962_probe(struct platform_device *pdev)
*/
int_port--;
ext_port--;
- ret = imx_audmux_v2_configure_port(int_port,
+ if (data->is_codec_master) {
+ tmp_port = int_port;
+ int_port = ext_port;
+ ext_port = tmp_port;
+ }
+
+ ret = imx_audmux_v2_configure_port(ext_port,
IMX_AUDMUX_V2_PTCR_SYN |
- IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
- IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
+ IMX_AUDMUX_V2_PTCR_TFSEL(int_port) |
+ IMX_AUDMUX_V2_PTCR_TCSEL(int_port) |
IMX_AUDMUX_V2_PTCR_TFSDIR |
IMX_AUDMUX_V2_PTCR_TCLKDIR,
- IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));
+ IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
if (ret) {
dev_err(&pdev->dev, "audmux internal port setup failed\n");
- return ret;
+ goto fail;
}
- ret = imx_audmux_v2_configure_port(ext_port,
+ ret = imx_audmux_v2_configure_port(int_port,
IMX_AUDMUX_V2_PTCR_SYN,
- IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
+ IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));
if (ret) {
dev_err(&pdev->dev, "audmux external port setup failed\n");
- return ret;
+ goto fail;
}
- ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
+audmux_bypass:
codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
- if (!ssi_np || !codec_np) {
+ if (!codec_np) {
dev_err(&pdev->dev, "phandle missing or invalid\n");
ret = -EINVAL;
goto fail;
}
- ssi_pdev = of_find_device_by_node(ssi_np);
- if (!ssi_pdev) {
+ cpu_pdev = of_find_device_by_node(cpu_np);
+ if (!cpu_pdev) {
dev_err(&pdev->dev, "failed to find SSI platform device\n");
ret = -EINVAL;
goto fail;
@@ -225,70 +658,153 @@ static int imx_wm8962_probe(struct platform_device *pdev)
goto fail;
}
- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- ret = -ENOMEM;
- goto fail;
+ asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0);
+ if (asrc_np) {
+ asrc_pdev = of_find_device_by_node(asrc_np);
+ priv->asrc_pdev = asrc_pdev;
}
- data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
- if (IS_ERR(data->codec_clk)) {
- ret = PTR_ERR(data->codec_clk);
+ priv->first_stream = NULL;
+ priv->second_stream = NULL;
+
+ codec_clk = devm_clk_get(&codec_dev->dev, NULL);
+ if (IS_ERR(codec_clk)) {
+ ret = PTR_ERR(codec_clk);
dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret);
goto fail;
}
- data->clk_frequency = clk_get_rate(data->codec_clk);
- ret = clk_prepare_enable(data->codec_clk);
- if (ret) {
- dev_err(&codec_dev->dev, "failed to enable codec clk: %d\n", ret);
- goto fail;
- }
+ data->clk_frequency = clk_get_rate(codec_clk);
+
+ priv->amic_mono = of_property_read_bool(codec_np, "amic-mono");
+ priv->dmic_mono = of_property_read_bool(codec_np, "dmic-mono");
+
+ priv->hp_gpio = of_get_named_gpio_flags(np, "hp-det-gpios", 0,
+ (enum of_gpio_flags *)&priv->hp_active_low);
+ priv->mic_gpio = of_get_named_gpio_flags(np, "mic-det-gpios", 0,
+ (enum of_gpio_flags *)&priv->mic_active_low);
+
+ data->dai[0].name = "HiFi";
+ data->dai[0].stream_name = "HiFi";
+ data->dai[0].codec_dai_name = "wm8962";
+ data->dai[0].codec_of_node = codec_np;
+ data->dai[0].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ data->dai[0].platform_of_node = cpu_np;
+ data->dai[0].ops = &imx_hifi_ops;
+ data->dai[0].dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF;
+ if (data->is_codec_master)
+ data->dai[0].dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
+ else
+ data->dai[0].dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
+
+ data->card.num_links = 1;
+
+ if (asrc_pdev) {
+ data->dai[0].ignore_pmdown_time = 1;
+ data->dai[1].name = "HiFi-ASRC-FE";
+ data->dai[1].stream_name = "HiFi-ASRC-FE";
+ data->dai[1].codec_name = "snd-soc-dummy";
+ data->dai[1].codec_dai_name = "snd-soc-dummy-dai";
+ data->dai[1].cpu_of_node = asrc_np;
+ data->dai[1].platform_of_node = asrc_np;
+ data->dai[1].dynamic = 1;
+ data->dai[1].ignore_pmdown_time = 1;
+ data->dai[1].dpcm_playback = 1;
+ data->dai[1].dpcm_capture = 1;
+ data->dai[1].dpcm_merged_chan = 1;
+
+ data->dai[2].name = "HiFi-ASRC-BE";
+ data->dai[2].stream_name = "HiFi-ASRC-BE";
+ data->dai[2].codec_dai_name = "wm8962";
+ data->dai[2].codec_of_node = codec_np;
+ data->dai[2].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ data->dai[2].platform_name = "snd-soc-dummy";
+ data->dai[2].ops = &imx_hifi_ops;
+ data->dai[2].be_hw_params_fixup = be_hw_params_fixup;
+ data->dai[2].no_pcm = 1;
+ data->dai[2].ignore_pmdown_time = 1;
+ data->dai[2].dpcm_playback = 1;
+ data->dai[2].dpcm_capture = 1;
+ data->card.num_links = 3;
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
+ &priv->asrc_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
- data->dai.name = "HiFi";
- data->dai.stream_name = "HiFi";
- data->dai.codec_dai_name = "wm8962";
- data->dai.codec_of_node = codec_np;
- data->dai.cpu_dai_name = dev_name(&ssi_pdev->dev);
- data->dai.platform_of_node = ssi_np;
- data->dai.ops = &imx_hifi_ops;
- data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM;
+ if (width == 24)
+ priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+ else
+ priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+ }
data->card.dev = &pdev->dev;
ret = snd_soc_of_parse_card_name(&data->card, "model");
if (ret)
- goto clk_fail;
+ goto fail;
ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
if (ret)
- goto clk_fail;
- data->card.num_links = 1;
+ goto fail;
data->card.owner = THIS_MODULE;
- data->card.dai_link = &data->dai;
+ data->card.dai_link = data->dai;
data->card.dapm_widgets = imx_wm8962_dapm_widgets;
data->card.num_dapm_widgets = ARRAY_SIZE(imx_wm8962_dapm_widgets);
data->card.late_probe = imx_wm8962_late_probe;
- data->card.set_bias_level = imx_wm8962_set_bias_level;
+#ifdef CONFIG_SND_SOC_IMX_WM8962_ANDROID
+ data->card.set_bias_level = imx_wm8962_set_bias_level;
+#endif
platform_set_drvdata(pdev, &data->card);
snd_soc_card_set_drvdata(&data->card, data);
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
- goto clk_fail;
+ goto fail;
}
- of_node_put(ssi_np);
- of_node_put(codec_np);
+ priv->snd_card = data->card.snd_card;
+ priv->headphone_kctl = snd_kctl_jack_new("Headphone", NULL);
+ ret = snd_ctl_add(data->card.snd_card, priv->headphone_kctl);
+ if (ret)
+ goto fail;
- return 0;
+ imx_wm8962_gpio_init(&data->card);
+
+ if (gpio_is_valid(priv->hp_gpio)) {
+ ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
+ if (ret) {
+ dev_err(&pdev->dev, "create hp attr failed (%d)\n", ret);
+ goto fail_hp;
+ }
+ }
-clk_fail:
- clk_disable_unprepare(data->codec_clk);
+ if (gpio_is_valid(priv->mic_gpio)) {
+ ret = driver_create_file(pdev->dev.driver, &driver_attr_microphone);
+ if (ret) {
+ dev_err(&pdev->dev, "create mic attr failed (%d)\n", ret);
+ goto fail_mic;
+ }
+ }
+
+ goto fail;
+
+fail_mic:
+ driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
+fail_hp:
fail:
- of_node_put(ssi_np);
+ of_node_put(cpu_np);
of_node_put(codec_np);
return ret;
@@ -296,11 +812,8 @@ fail:
static int imx_wm8962_remove(struct platform_device *pdev)
{
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
-
- if (!IS_ERR(data->codec_clk))
- clk_disable_unprepare(data->codec_clk);
+ driver_remove_file(pdev->dev.driver, &driver_attr_microphone);
+ driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
return 0;
}
diff --git a/sound/soc/fsl/imx-xtor.c b/sound/soc/fsl/imx-xtor.c
new file mode 100644
index 000000000000..0d6f92d0285d
--- /dev/null
+++ b/sound/soc/fsl/imx-xtor.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2015-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/module.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/control.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <linux/pinctrl/consumer.h>
+#include "fsl_sai.h"
+#include "fsl_esai.h"
+
+#define RX 0
+#define TX 1
+
+/**
+ * CPU private data
+ *
+ * @sysclk_id[2]: SYSCLK ids for set_sysclk()
+ * @slots: number of slots supported by DAI
+ *
+ * Note: [0] for rx and [1] for tx
+ */
+struct cpu_priv {
+ u32 sysclk_id[2];
+ u32 slots;
+};
+
+struct imx_xtor_data {
+ struct snd_soc_dai_link dai[3];
+ struct snd_soc_card card;
+ struct cpu_priv cpu_priv;
+ bool is_stream_opened[2];
+ struct platform_device *asrc_pdev;
+ u32 asrc_rate;
+ u32 asrc_format;
+};
+
+static int imx_xtor_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ static struct snd_pcm_hw_constraint_list constraint_rates;
+ int ret;
+ static u32 support_rates[] = { 8000, 32000, 48000, 96000, 192000, };
+
+ constraint_rates.list = support_rates;
+ constraint_rates.count = ARRAY_SIZE(support_rates);
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &constraint_rates);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int imx_xtor_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct imx_xtor_data *data = snd_soc_card_get_drvdata(rtd->card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ struct cpu_priv *cpu_priv = &data->cpu_priv;
+ struct device *dev = rtd->card->dev;
+ unsigned int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF;
+ int ret, dir;
+ u32 freq;
+
+ /* For playback the XTOR is slave, and for record is master */
+ fmt |= tx ? SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+ dir = tx ? SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(rtd->cpu_dai, fmt);
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
+ return ret;
+ }
+
+ /* Specific configurations of DAIs starts from here */
+ freq = params_rate(params) * params_width(params) * cpu_priv->slots;
+ ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, cpu_priv->sysclk_id[tx],
+ freq, dir);
+ if (ret) {
+ dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, cpu_priv->slots,
+ params_width(params));
+ if (ret) {
+ dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int imx_xtor_hw_free(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static void imx_xtor_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct imx_xtor_data *data = snd_soc_card_get_drvdata(card);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+
+ data->is_stream_opened[tx] = false;
+}
+
+static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct imx_xtor_data *data = snd_soc_card_get_drvdata(card);
+ struct snd_interval *rate;
+ struct snd_mask *mask;
+
+ if (!data->asrc_pdev)
+ return -EINVAL;
+
+ rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ rate->max = rate->min = data->asrc_rate;
+
+ mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ snd_mask_none(mask);
+ snd_mask_set(mask, data->asrc_format);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Line out jack */
+ {"CPU-Playback", NULL, "ASRC-Playback"},
+ {"Playback", NULL, "CPU-Playback"},/* dai route for be and fe */
+ {"ASRC-Capture", NULL, "CPU-Capture"},
+ {"CPU-Capture", NULL, "Capture"},
+};
+
+
+static struct snd_soc_ops imx_xtor_ops = {
+ .startup = imx_xtor_startup,
+ .shutdown = imx_xtor_shutdown,
+ .hw_params = imx_xtor_hw_params,
+ .hw_free = imx_xtor_hw_free,
+};
+
+static struct snd_soc_ops imx_xtor_be_ops = {
+ .hw_params = imx_xtor_hw_params,
+ .hw_free = imx_xtor_hw_free,
+};
+
+static int imx_xtor_probe(struct platform_device *pdev)
+{
+ struct device_node *cpu_np, *xtor_np = NULL;
+ struct device_node *asrc_np = NULL;
+ struct platform_device *asrc_pdev = NULL;
+ struct platform_device *cpu_pdev;
+ struct imx_xtor_data *data;
+ int ret;
+ u32 width;
+
+ cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0);
+ if (asrc_np) {
+ asrc_pdev = of_find_device_by_node(asrc_np);
+ data->asrc_pdev = asrc_pdev;
+ }
+
+ cpu_pdev = of_find_device_by_node(cpu_np);
+ if (!cpu_pdev) {
+ dev_err(&pdev->dev, "failed to find SAI platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (strstr(cpu_np->name, "esai")) {
+ data->cpu_priv.sysclk_id[TX] = ESAI_HCKT_EXTAL;
+ data->cpu_priv.sysclk_id[RX] = ESAI_HCKR_EXTAL;
+ } else if (strstr(cpu_np->name, "sai")) {
+ data->cpu_priv.sysclk_id[TX] = FSL_SAI_CLK_MAST1;
+ data->cpu_priv.sysclk_id[RX] = FSL_SAI_CLK_MAST1;
+ }
+ data->cpu_priv.slots = 2;
+
+ data->dai[0].name = "xtor hifi";
+ data->dai[0].stream_name = "xtor hifi";
+ data->dai[0].codec_dai_name = "snd-soc-dummy-dai";
+ data->dai[0].codec_name = "snd-soc-dummy";
+ data->dai[0].cpu_dai_name = dev_name(&cpu_pdev->dev);
+ data->dai[0].platform_of_node = cpu_np;
+ data->dai[0].ops = &imx_xtor_ops;
+ data->dai[0].playback_only = false;
+ data->dai[0].capture_only = false;
+ data->card.num_links = 1;
+ data->card.dai_link = data->dai;
+
+ /*if there is no asrc controller, we only enable one device*/
+ if (asrc_pdev) {
+ data->dai[1].name = "HiFi-ASRC-FE";
+ data->dai[1].stream_name = "HiFi-ASRC-FE";
+ data->dai[1].codec_dai_name = "snd-soc-dummy-dai";
+ data->dai[1].codec_name = "snd-soc-dummy";
+ data->dai[1].cpu_of_node = asrc_np;
+ data->dai[1].platform_of_node = asrc_np;
+ data->dai[1].dynamic = 1;
+ data->dai[1].dpcm_playback = 1;
+ data->dai[1].dpcm_capture = 1;
+
+ data->dai[2].name = "HiFi-ASRC-BE";
+ data->dai[2].stream_name = "HiFi-ASRC-BE";
+ data->dai[2].codec_dai_name = "snd-soc-dummy-dai";
+ data->dai[2].codec_name = "snd-soc-dummy";
+ data->dai[2].cpu_of_node = cpu_np;
+ data->dai[2].platform_name = "snd-soc-dummy";
+ data->dai[2].no_pcm = 1;
+ data->dai[2].dpcm_playback = 1;
+ data->dai[2].dpcm_capture = 1;
+ data->dai[2].ops = &imx_xtor_be_ops,
+ data->dai[2].be_hw_params_fixup = be_hw_params_fixup,
+ data->card.num_links = 3;
+ data->card.dai_link = &data->dai[0];
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
+ &data->asrc_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get output rate\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (width == 24)
+ data->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+ else
+ data->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+ }
+
+ data->card.dapm_routes = audio_map,
+ data->card.num_dapm_routes = ARRAY_SIZE(audio_map),
+ data->card.dev = &pdev->dev;
+ data->card.owner = THIS_MODULE;
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto fail;
+
+ platform_set_drvdata(pdev, &data->card);
+ snd_soc_card_set_drvdata(&data->card, data);
+ ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto fail;
+ }
+
+fail:
+ if (cpu_np)
+ of_node_put(cpu_np);
+ if (xtor_np)
+ of_node_put(xtor_np);
+ return ret;
+}
+
+static const struct of_device_id imx_xtor_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-xtor", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_xtor_dt_ids);
+
+static struct platform_driver imx_xtor_driver = {
+ .driver = {
+ .name = "imx-xtor",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = imx_xtor_dt_ids,
+ },
+ .probe = imx_xtor_probe,
+};
+module_platform_driver(imx_xtor_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale i.MX Dummy audio ASoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-xtor");
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 80088c98ce27..7f0e36dc50aa 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1264,7 +1264,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
}
}
- dev_err(card->dev, "ASoC: can't get %s BE for %s\n",
+ dev_dbg(card->dev, "ASoC: can't get %s BE for %s\n",
stream ? "capture" : "playback", widget->name);
return NULL;
}
@@ -1415,7 +1415,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
/* is there a valid BE rtd for this widget */
be = dpcm_get_be(card, list->widgets[i], stream);
if (!be) {
- dev_err(fe->dev, "ASoC: no BE found for %s\n",
+ dev_dbg(fe->dev, "ASoC: no BE found for %s\n",
list->widgets[i]->name);
continue;
}
@@ -1634,6 +1634,43 @@ static u64 dpcm_runtime_base_format(struct snd_pcm_substream *substream)
return formats;
}
+static void dpcm_runtime_base_chan(struct snd_pcm_substream *substream,
+ unsigned int *channels_min,
+ unsigned int *channels_max)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ struct snd_soc_dpcm *dpcm;
+ int stream = substream->stream;
+ *channels_min = 0;
+ *channels_max = UINT_MAX;
+
+ if (!fe->dai_link->dpcm_merged_chan)
+ return;
+
+ /*
+ * It returns merged BE codec channel;
+ * if FE want to use it (= dpcm_merged_chan)
+ */
+
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_soc_dai_driver *codec_dai_drv;
+ struct snd_soc_pcm_stream *codec_stream;
+ int i;
+
+ for (i = 0; i < be->num_codecs; i++) {
+ codec_dai_drv = be->codec_dais[i]->driver;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ codec_stream = &codec_dai_drv->playback;
+ else
+ codec_stream = &codec_dai_drv->capture;
+
+ *channels_min = max(*channels_min, codec_stream->channels_min);
+ *channels_max = min(*channels_max, codec_stream->channels_max);
+ }
+ }
+}
+
static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1641,11 +1678,17 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
u64 format = dpcm_runtime_base_format(substream);
+ unsigned int channels_min = 0, channels_max = UINT_MAX;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback, format);
else
dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture, format);
+
+ dpcm_runtime_base_chan(substream, &channels_min, &channels_max);
+
+ runtime->hw.channels_min = max(channels_min, runtime->hw.channels_min);
+ runtime->hw.channels_max = min(channels_max, runtime->hw.channels_max);
}
static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);